Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

## Unreleased

- Enable image input for models the pinned catalog predates. `src/commandcode-catalog.ts` is generated from a Command Code CLI release, so a model published afterwards is absent from `MODEL_INPUT_MODALITIES` and stays text-only until the next catalog sync: the provider transport publishes `input: ["text"]` to the host and the generate transport refuses image blocks. A new `MODEL_INPUT_MODALITIES_OVERRIDES` hook next to the effort overrides carries the modalities. It re-enables vision for `deepseek/deepseek-v4.1-flash` and `xai/grok-4.6`, both served by the Provider API and both declared `inputModalities:["text","image"]` by `command-code@1.53.0`.

### Contributors

- @eibednejo — added the input-modality override hook and the vision entries for the affected models.

## 0.6.4 - 2026-09-03

- Refresh the generated Command Code capability catalog from `command-code@1.40.1` to `command-code@1.44.0`, adding current image-input, reasoning, effort, and output-limit metadata for newly published models.
Expand Down
25 changes: 24 additions & 1 deletion src/commandcode-catalog-overrides.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { CommandCodeReasoningEffort } from "./commandcode-catalog.ts"
import type { CommandCodeInputType, CommandCodeReasoningEffort } from "./commandcode-catalog.ts"

/**
* Manual reasoning-effort policy for models the official CLI marks as
Expand All @@ -23,3 +23,26 @@ export const MODEL_EFFORT_OVERRIDES: Readonly<
"meta/muse-spark-1.3": ["minimal", "low", "medium", "high", "xhigh"],
"meta/muse-spark-1.3-contributor": ["minimal", "low", "medium", "high", "xhigh"],
}

/**
* Manual input-modality overrides for models the generated catalog predates.
*
* Same rationale as the effort overrides above: the generated catalog is pinned
* to one CLI release, so a model published afterwards is absent from
* `MODEL_INPUT_MODALITIES` and falls back to `["text"]`. Both transports honor
* the absence: the provider transport publishes `input: ["text"]` to the host
* and the generate transport refuses image blocks outright.
*
* The Provider API model list carries no modality metadata, so the CLI registry
* is the only source available for this. Add a model only when the CLI registry
* declares `image` for it; remove it once the generated catalog ships the same
* modalities.
*/
export const MODEL_INPUT_MODALITIES_OVERRIDES: Readonly<
Record<string, readonly CommandCodeInputType[]>
> = {
// Served by the Provider API and declared with
// `inputModalities:["text","image"]` by command-code@1.53.0.
"deepseek/deepseek-v4.1-flash": ["text", "image"],
"xai/grok-4.6": ["text", "image"],
}
15 changes: 12 additions & 3 deletions src/models.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { mkdir, readFile, rename, rm, writeFile } from "node:fs/promises"
import { dirname } from "node:path"

import { MODEL_EFFORT_OVERRIDES } from "./commandcode-catalog-overrides.ts"
import {
MODEL_EFFORT_OVERRIDES,
MODEL_INPUT_MODALITIES_OVERRIDES,
} from "./commandcode-catalog-overrides.ts"
import {
MODEL_EFFORTS as CATALOG_MODEL_EFFORTS,
MODEL_INPUT_MODALITIES,
MODEL_INPUT_MODALITIES as CATALOG_MODEL_INPUT_MODALITIES,
MODEL_MAX_OUTPUT_TOKENS,
MODEL_REASONING,
type CommandCodeInputType,
Expand All @@ -17,7 +20,13 @@ export const MODEL_EFFORTS: Readonly<Record<string, readonly CommandCodeReasonin
...MODEL_EFFORT_OVERRIDES,
}

export { MODEL_INPUT_MODALITIES, MODEL_MAX_OUTPUT_TOKENS, MODEL_REASONING }
/** Upstream CLI input modalities with the manual overrides merged over them. */
export const MODEL_INPUT_MODALITIES: Readonly<Record<string, readonly CommandCodeInputType[]>> = {
...CATALOG_MODEL_INPUT_MODALITIES,
...MODEL_INPUT_MODALITIES_OVERRIDES,
}

export { MODEL_MAX_OUTPUT_TOKENS, MODEL_REASONING }
export type { CommandCodeInputType }

export const DEFAULT_PROVIDER_API_BASE = "https://api.commandcode.ai/provider/v1"
Expand Down
30 changes: 29 additions & 1 deletion tests/test-models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@ import { tmpdir } from "node:os"
import { join } from "node:path"
import { describe, it } from "node:test"

import { MODEL_EFFORT_OVERRIDES } from "../src/commandcode-catalog-overrides.ts"
import {
MODEL_EFFORT_OVERRIDES,
MODEL_INPUT_MODALITIES_OVERRIDES,
} from "../src/commandcode-catalog-overrides.ts"
import {
COMMAND_CODE_CLI_VERSION,
MODEL_EFFORTS as CATALOG_MODEL_EFFORTS,
MODEL_INPUT_MODALITIES as CATALOG_MODEL_INPUT_MODALITIES,
} from "../src/commandcode-catalog.ts"
import {
apiForModelId,
Expand Down Expand Up @@ -216,6 +220,30 @@ describe("commandCodeModelsFromApiResponse()", () => {
}
})

it("merges manual input-modality overrides over the generated catalog", () => {
assert.ok(Object.keys(MODEL_INPUT_MODALITIES_OVERRIDES).length > 0)
for (const [modelId, modalities] of Object.entries(MODEL_INPUT_MODALITIES_OVERRIDES)) {
assert.equal(
CATALOG_MODEL_INPUT_MODALITIES[modelId],
undefined,
`${modelId} now has upstream modalities; drop the manual override`,
)
assert.ok(
modalities.includes("image"),
`${modelId} override is pointless without image input`,
)
assert.deepEqual(inputModalitiesForModel(modelId), modalities)
assert.equal(modelSupportsImageInput(modelId), true)
}
for (const [modelId, modalities] of Object.entries(CATALOG_MODEL_INPUT_MODALITIES)) {
assert.deepEqual(
MODEL_INPUT_MODALITIES[modelId],
modalities,
`${modelId} upstream modalities changed`,
)
}
})

it("builds separate canonical pi and OMP metadata", () => {
for (const [modelId, efforts] of Object.entries(MODEL_EFFORTS)) {
const metadata = thinkingMetadataForModel(modelId)
Expand Down