diff --git a/.changeset/chat-fim-fallback.md b/.changeset/chat-fim-fallback.md new file mode 100644 index 0000000000..73ff08611c --- /dev/null +++ b/.changeset/chat-fim-fallback.md @@ -0,0 +1,6 @@ +--- +"kilo-code": patch +"@kilocode/kilo-gateway": patch +--- + +Use the matching FIM model for chat autocomplete when Next Edit is selected. diff --git a/packages/kilo-gateway/src/autocomplete.ts b/packages/kilo-gateway/src/autocomplete.ts index 01aef3e52f..51d24b7c2f 100644 --- a/packages/kilo-gateway/src/autocomplete.ts +++ b/packages/kilo-gateway/src/autocomplete.ts @@ -1,7 +1,7 @@ export type AutocompleteProviderID = "kilo" | "mistral" | "inception" export type DirectAutocompleteProviderID = Exclude -export interface AutocompleteModelDef { +interface AutocompleteModelBase { /** Stable combined value for internal comparisons. */ readonly id: string /** Model value stored in settings and sent to the autocomplete API. */ @@ -18,14 +18,23 @@ export interface AutocompleteModelDef { readonly directProvider?: DirectAutocompleteProviderID /** Request temperature. */ readonly temperature: number - /** - * Which gateway endpoint this model targets. Defaults to "fim" if omitted - * (back-compat with existing entries). Models with `kind: "edit"` route - * through `/kilo/edit` and use Mercury's Next Edit pipeline. - */ - readonly kind?: "fim" | "edit" } +export type AutocompleteModelDef = AutocompleteModelBase & + ( + | { + /** Route through `/kilo/edit` using the Next Edit pipeline. */ + readonly kind: "edit" + /** Stable combined ID of the FIM model used where Next Edit is unsupported. */ + readonly fimModelID: string + } + | { + /** Route through the FIM endpoint. */ + readonly kind?: "fim" + readonly fimModelID?: never + } + ) + const models: AutocompleteModelDef[] = [ { id: "kilo/mistralai/codestral-2508", @@ -57,6 +66,7 @@ const models: AutocompleteModelDef[] = [ requestModel: "inception/mercury-edit-2", temperature: 0, kind: "edit", + fimModelID: "kilo/inception/mercury-edit-2", }, { id: "mistral/codestral-2508", @@ -91,6 +101,7 @@ const models: AutocompleteModelDef[] = [ directProvider: "inception", temperature: 0, kind: "edit", + fimModelID: "inception/mercury-edit-2", }, ] diff --git a/packages/kilo-gateway/test/autocomplete.test.ts b/packages/kilo-gateway/test/autocomplete.test.ts index 71518c8f7f..4910979a85 100644 --- a/packages/kilo-gateway/test/autocomplete.test.ts +++ b/packages/kilo-gateway/test/autocomplete.test.ts @@ -18,3 +18,15 @@ describe("DEFAULT_AUTOCOMPLETE_MODEL", () => { expect(DEFAULT_AUTOCOMPLETE_MODEL.kind).toBe("edit") }) }) + +describe("Next Edit FIM models", () => { + test("reference a FIM model from the same provider", () => { + for (const model of AUTOCOMPLETE_MODELS) { + if (model.kind !== "edit") continue + const sibling = AUTOCOMPLETE_MODELS.find((candidate) => candidate.id === model.fimModelID) + expect(sibling).toBeDefined() + expect(sibling?.kind).not.toBe("edit") + expect(sibling?.providerID).toBe(model.providerID) + } + }) +}) diff --git a/packages/kilo-vscode/src/services/autocomplete/chat-autocomplete/ChatTextAreaAutocomplete.ts b/packages/kilo-vscode/src/services/autocomplete/chat-autocomplete/ChatTextAreaAutocomplete.ts index 9d2c0d0082..369906ea4a 100644 --- a/packages/kilo-vscode/src/services/autocomplete/chat-autocomplete/ChatTextAreaAutocomplete.ts +++ b/packages/kilo-vscode/src/services/autocomplete/chat-autocomplete/ChatTextAreaAutocomplete.ts @@ -7,7 +7,7 @@ import { VisibleCodeTracker } from "../context/VisibleCodeTracker" import { FileIgnoreController } from "../shims/FileIgnoreController" import type { KiloConnectionService } from "../../cli-backend" import { generateFim, hasValidCredentials } from "../fim" -import { getAutocompleteModel } from "../../../shared/autocomplete-models" +import { getAutocompleteModel, getAutocompleteModelById } from "../../../shared/autocomplete-models" import { finalizeChatSuggestion, buildChatPrefix } from "./chat-autocomplete-utils" interface ChatCompletionRequestMessage { @@ -20,6 +20,12 @@ interface ChatCompletionResponseSender { postMessage(message: { type: "chatCompletionResult"; text: string; requestId: string }): void } +export function getChatAutocompleteModel(provider?: string, model?: string) { + const info = getAutocompleteModel(provider, model) + if (info.kind !== "edit") return info + return getAutocompleteModelById(info.fimModelID) +} + /** * Chat textarea autocomplete with cached per-request objects. * @@ -77,7 +83,7 @@ export class ChatTextAreaAutocomplete { async getCompletion(userText: string, visibleCodeContext?: VisibleCodeContext): Promise<{ suggestion: string }> { const cfg = vscode.workspace.getConfiguration("kilo-code.new.autocomplete") - const entry = getAutocompleteModel(cfg.get("provider"), cfg.get("model")) + const entry = getChatAutocompleteModel(cfg.get("provider"), cfg.get("model")) const startTime = Date.now() // Build context for telemetry diff --git a/packages/kilo-vscode/tests/unit/chat-autocomplete-utils.test.ts b/packages/kilo-vscode/tests/unit/chat-autocomplete-utils.test.ts index 415362ab7e..216c574d1d 100644 --- a/packages/kilo-vscode/tests/unit/chat-autocomplete-utils.test.ts +++ b/packages/kilo-vscode/tests/unit/chat-autocomplete-utils.test.ts @@ -3,6 +3,7 @@ import { finalizeChatSuggestion, buildChatPrefix, } from "../../src/services/autocomplete/chat-autocomplete/chat-autocomplete-utils" +import { getChatAutocompleteModel } from "../../src/services/autocomplete/chat-autocomplete/ChatTextAreaAutocomplete" describe("finalizeChatSuggestion", () => { it("returns empty string for empty input", () => { @@ -98,3 +99,14 @@ describe("buildChatPrefix", () => { expect(result).toContain("hi") }) }) + +describe("getChatAutocompleteModel", () => { + it("uses the matching FIM model for Next Edit settings", () => { + expect(getChatAutocompleteModel("kilo", "inception/mercury-next-edit").id).toBe("kilo/inception/mercury-edit-2") + expect(getChatAutocompleteModel("inception", "mercury-next-edit").id).toBe("inception/mercury-edit-2") + }) + + it("keeps FIM settings unchanged", () => { + expect(getChatAutocompleteModel("kilo", "mistralai/codestral-2508").id).toBe("kilo/mistralai/codestral-2508") + }) +})