summaryrefslogtreecommitdiffhomepage
path: root/packages/openai-stream
diff options
context:
space:
mode:
authorAdam Malczewski <[email protected]>2026-06-27 18:36:36 +0900
committerAdam Malczewski <[email protected]>2026-06-27 18:36:36 +0900
commitfe338f88a52df1360347408fb3a8f9ea83172f62 (patch)
tree00a0994cf7e19f22540fe74582fb670fab684075 /packages/openai-stream
parente76790fef11de3cc33f60689f9301030ed740cd6 (diff)
downloaddispatch-fe338f88a52df1360347408fb3a8f9ea83172f62.tar.gz
dispatch-fe338f88a52df1360347408fb3a8f9ea83172f62.zip
fix(vision): detect umans kimi + qwen models as vision-capable (not just kimi)
Diffstat (limited to 'packages/openai-stream')
-rw-r--r--packages/openai-stream/src/listModels.test.ts33
-rw-r--r--packages/openai-stream/src/listModels.ts14
2 files changed, 26 insertions, 21 deletions
diff --git a/packages/openai-stream/src/listModels.test.ts b/packages/openai-stream/src/listModels.test.ts
index 3acf46e..2e3b1a3 100644
--- a/packages/openai-stream/src/listModels.test.ts
+++ b/packages/openai-stream/src/listModels.test.ts
@@ -53,28 +53,33 @@ describe("listModels — pure mapping (parseModelList)", () => {
});
describe("listModels — vision capability detection", () => {
- it("isVisionModelId returns true for kimi-family model ids", () => {
- expect(isVisionModelId("kimi-k2.7")).toBe(true);
- expect(isVisionModelId("Kimi-K2.7")).toBe(true); // case-insensitive
- expect(isVisionModelId("moonshot/kimi-k2-thinking")).toBe(true);
+ it("isVisionModelId returns true for umans kimi and qwen model ids", () => {
+ expect(isVisionModelId("umans-kimi-k2.7")).toBe(true);
+ expect(isVisionModelId("Umans-Kimi-K2.7")).toBe(true); // case-insensitive
+ expect(isVisionModelId("umans-qwen3.6-35b-a3b")).toBe(true);
});
- it("isVisionModelId returns false for non-kimi model ids", () => {
- expect(isVisionModelId("glm-5.2")).toBe(false);
- expect(isVisionModelId("deepseek-v4-flash")).toBe(false);
+ it("isVisionModelId returns false for non-vision model ids", () => {
+ expect(isVisionModelId("umans-glm-5.2")).toBe(false);
expect(isVisionModelId("umans-coder")).toBe(false);
+ expect(isVisionModelId("umans-flash")).toBe(false);
+ expect(isVisionModelId("kimi-k2.7-code")).toBe(false); // opencode kimi, not umans
+ expect(isVisionModelId("qwen3.7-max")).toBe(false); // opencode qwen, not umans
+ expect(isVisionModelId("deepseek-v4-flash")).toBe(false);
});
- it("parseModelList sets vision: true on kimi-family models", () => {
+ it("parseModelList sets vision: true on umans kimi and qwen models only", () => {
const result = parseModelList([
- { id: "kimi-k2.7", context_length: 200000 },
- { id: "glm-5.2", context_length: 128000 },
- { id: "deepseek-v4-flash" },
+ { id: "umans-kimi-k2.7", context_length: 262144 },
+ { id: "umans-qwen3.6-35b-a3b", context_length: 262144 },
+ { id: "umans-glm-5.2", context_length: 405504 },
+ { id: "umans-coder" },
]);
expect(result).toEqual([
- { id: "kimi-k2.7", contextWindow: 200000, vision: true },
- { id: "glm-5.2", contextWindow: 128000 },
- { id: "deepseek-v4-flash" },
+ { id: "umans-kimi-k2.7", contextWindow: 262144, vision: true },
+ { id: "umans-qwen3.6-35b-a3b", contextWindow: 262144, vision: true },
+ { id: "umans-glm-5.2", contextWindow: 405504 },
+ { id: "umans-coder" },
]);
});
});
diff --git a/packages/openai-stream/src/listModels.ts b/packages/openai-stream/src/listModels.ts
index 273fee3..df116b0 100644
--- a/packages/openai-stream/src/listModels.ts
+++ b/packages/openai-stream/src/listModels.ts
@@ -27,19 +27,19 @@ interface OpenAIModelListResponse {
* Whether a model id is vision-capable (can natively accept image input).
*
* The OpenAI-compatible `/models` endpoint does not reliably report image
- * capabilities, so this is a hardcoded heuristic by model id: a model whose id
- * contains "kimi" (e.g. `kimi-k2.7`, `moonshot/kimi-k2.7`) is vision-capable;
- * all others are treated as non-vision. This is the single source of truth —
- * the orchestrator's vision handoff and the `read_image` tool both consult the
- * `ModelInfo.vision` flag this sets, so adding a model here enables vision
- * everywhere. Pure: id → boolean, no I/O.
+ * capabilities, so this is a hardcoded heuristic by model id: the Umans Kimi
+ * (`umans-kimi-k2.7`) and Umans Qwen (`umans-qwen3.6-35b-a3b`) models are
+ * vision-capable; all others are treated as non-vision. This is the single
+ * source of truth — the orchestrator's vision handoff and the `consult_vision`
+ * tool both consult the `ModelInfo.vision` flag this sets, so adding a model
+ * here enables vision everywhere. Pure: id → boolean, no I/O.
*
* (When an endpoint gains reliable vision reporting, this can be replaced with
* a real capability check without changing callers.)
*/
export function isVisionModelId(id: string): boolean {
const lower = id.toLowerCase();
- return lower.includes("kimi");
+ return lower.includes("umans-kimi") || lower.includes("umans-qwen");
}
/**