mirror of
https://github.com/Kilo-Org/kilocode.git
synced 2026-08-28 11:05:31 +08:00
Merge branch 'main' into basalt-dirt
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"kilo-code": patch
|
||||
"@kilocode/kilo-gateway": patch
|
||||
---
|
||||
|
||||
Use the matching FIM model for chat autocomplete when Next Edit is selected.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"kilo-code": patch
|
||||
---
|
||||
|
||||
Preserve unchanged codebase indexes when extension or VS Code updates interrupt an incremental scan.
|
||||
@@ -1,7 +1,7 @@
|
||||
export type AutocompleteProviderID = "kilo" | "mistral" | "inception"
|
||||
export type DirectAutocompleteProviderID = Exclude<AutocompleteProviderID, "kilo">
|
||||
|
||||
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",
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
@@ -277,6 +277,8 @@ export class CodeIndexOrchestrator {
|
||||
|
||||
private async _runScan(mode: IndexingTelemetryMode, trigger: IndexingTelemetryTrigger): Promise<void> {
|
||||
if (this._cancelRequested) {
|
||||
if (mode === "incremental") await this.vectorStore.markIndexingComplete()
|
||||
this.stateManager.setSystemState("Standby", "Indexing cancelled.")
|
||||
log.info("scan skipped: cancellation was requested", { workspacePath: this.workspacePath, mode })
|
||||
return
|
||||
}
|
||||
@@ -319,6 +321,10 @@ export class CodeIndexOrchestrator {
|
||||
})
|
||||
|
||||
if (this._cancelRequested || this.scanner.isCancelled) {
|
||||
if (mode === "incremental" && result.stats.processed === 0 && batchErrors.length === 0) {
|
||||
await this.vectorStore.markIndexingComplete()
|
||||
log.info("preserved unchanged index after cancelled scan", { workspacePath: this.workspacePath })
|
||||
}
|
||||
this._isProcessing = false
|
||||
if (this.stateManager.state !== "Error") {
|
||||
this.stateManager.setSystemState("Standby", "Indexing cancelled.")
|
||||
|
||||
@@ -18,7 +18,9 @@ import { Emitter } from "../../../src/indexing/runtime"
|
||||
class Store {
|
||||
public clearCount = 0
|
||||
public closeCount = 0
|
||||
public completeCount = 0
|
||||
public deleteCount = 0
|
||||
public incompleteCount = 0
|
||||
|
||||
constructor(
|
||||
private readonly existing: boolean,
|
||||
@@ -57,8 +59,12 @@ class Store {
|
||||
async hasIndexedData(): Promise<boolean> {
|
||||
return this.existing
|
||||
}
|
||||
async markIndexingComplete(): Promise<void> {}
|
||||
async markIndexingIncomplete(): Promise<void> {}
|
||||
async markIndexingComplete(): Promise<void> {
|
||||
this.completeCount += 1
|
||||
}
|
||||
async markIndexingIncomplete(): Promise<void> {
|
||||
this.incompleteCount += 1
|
||||
}
|
||||
}
|
||||
|
||||
class Scanner {
|
||||
@@ -270,6 +276,31 @@ describe("CodeIndexOrchestrator telemetry", () => {
|
||||
|
||||
expect(scanner.finished).toBe(true)
|
||||
expect(store.closeCount).toBe(1)
|
||||
expect(store.incompleteCount).toBe(1)
|
||||
expect(store.completeCount).toBe(0)
|
||||
})
|
||||
|
||||
test("preserves an unchanged index when an incremental scan is interrupted", async () => {
|
||||
const scanner = new BlockingScanner()
|
||||
const store = new Store(true)
|
||||
const orchestrator = new CodeIndexOrchestrator(
|
||||
createConfig(),
|
||||
new CodeIndexStateManager(),
|
||||
"/tmp/ws",
|
||||
{ async clearCacheFile() {}, async flush() {} } as unknown as CacheManager,
|
||||
store as unknown as IVectorStore,
|
||||
scanner as unknown as DirectoryScanner,
|
||||
new Watcher() as unknown as IFileWatcher,
|
||||
)
|
||||
|
||||
const active = orchestrator.startIndexing("background")
|
||||
await scanner.started.promise
|
||||
await orchestrator.shutdown()
|
||||
await active
|
||||
|
||||
expect(store.incompleteCount).toBe(1)
|
||||
expect(store.completeCount).toBe(1)
|
||||
expect(store.clearCount).toBe(0)
|
||||
})
|
||||
|
||||
test("clears stale vectors and hashes before rebuilding an incomplete store", async () => {
|
||||
|
||||
+8
-2
@@ -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<string>("provider"), cfg.get<string>("model"))
|
||||
const entry = getChatAutocompleteModel(cfg.get<string>("provider"), cfg.get<string>("model"))
|
||||
const startTime = Date.now()
|
||||
|
||||
// Build context for telemetry
|
||||
|
||||
@@ -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")
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user