diff --git a/packages/kilo-vscode/package.json b/packages/kilo-vscode/package.json index d98fd247dc0..490f61b04e6 100644 --- a/packages/kilo-vscode/package.json +++ b/packages/kilo-vscode/package.json @@ -110,6 +110,21 @@ "when": "true" } ] + }, + "configuration": { + "title": "Kilo Code", + "properties": { + "kilo-code.new.model.providerID": { + "type": "string", + "default": "", + "description": "Selected model provider ID" + }, + "kilo-code.new.model.modelID": { + "type": "string", + "default": "", + "description": "Selected model ID" + } + } } }, "scripts": { diff --git a/packages/kilo-vscode/src/KiloProvider.ts b/packages/kilo-vscode/src/KiloProvider.ts index 125d34de252..f1d7d821baf 100644 --- a/packages/kilo-vscode/src/KiloProvider.ts +++ b/packages/kilo-vscode/src/KiloProvider.ts @@ -142,7 +142,7 @@ export class KiloProvider implements vscode.WebviewViewProvider { await this.syncWebviewState("webviewReady") break case "sendMessage": - await this.handleSendMessage(message.text, message.sessionID) + await this.handleSendMessage(message.text, message.sessionID, message.providerID, message.modelID) break case "abort": await this.handleAbort(message.sessionID) @@ -177,6 +177,9 @@ export class KiloProvider implements vscode.WebviewViewProvider { vscode.env.openExternal(vscode.Uri.parse(message.url)) } break + case "saveModel": + await this.handleSaveModel(message.providerID, message.modelID) + break } }) } @@ -248,6 +251,10 @@ export class KiloProvider implements vscode.WebviewViewProvider { this.postMessage({ type: "connectionState", state: this.connectionState }) await this.syncWebviewState("initializeConnection") + + // Fetch providers and send to webview + await this.fetchAndSendProviders() + console.log("[Kilo New] KiloProvider: ✅ initializeConnection completed successfully") } catch (error) { console.error("[Kilo New] KiloProvider: ❌ Failed to initialize connection:", error) @@ -379,10 +386,58 @@ export class KiloProvider implements vscode.WebviewViewProvider { } } + /** + * Fetch providers from the backend and send to webview. + */ + private async fetchAndSendProviders(): Promise { + if (!this.httpClient) { + return + } + + try { + const workspaceDir = this.getWorkspaceDirectory() + const response = await this.httpClient.listProviders(workspaceDir) + const config = vscode.workspace.getConfiguration("kilo-code.new.model") + const providerID = config.get("providerID", "") + const modelID = config.get("modelID", "") + + console.log("[Kilo New] KiloProvider: 📦 Providers loaded, sending to webview", { + providerCount: Object.keys(response.all).length, + connectedCount: response.connected.length, + savedProvider: providerID, + savedModel: modelID, + }) + + this.postMessage({ + type: "providersLoaded", + providers: response.all, + connected: response.connected, + defaults: response.default, + savedSelection: providerID || modelID ? { providerID, modelID } : undefined, + }) + } catch (error) { + console.error("[Kilo New] KiloProvider: Failed to fetch providers:", error) + } + } + + /** + * Handle saving model selection to VS Code settings. + */ + private async handleSaveModel(providerID: string, modelID: string): Promise { + const config = vscode.workspace.getConfiguration("kilo-code.new.model") + try { + await config.update("providerID", providerID, vscode.ConfigurationTarget.Global) + await config.update("modelID", modelID, vscode.ConfigurationTarget.Global) + console.log("[Kilo New] KiloProvider: 💾 Model selection saved:", { providerID, modelID }) + } catch (error) { + console.error("[Kilo New] KiloProvider: Failed to save model selection:", error) + } + } + /** * Handle sending a message from the webview. */ - private async handleSendMessage(text: string, sessionID?: string): Promise { + private async handleSendMessage(text: string, sessionID?: string, providerID?: string, modelID?: string): Promise { if (!this.httpClient) { this.postMessage({ type: "error", @@ -410,8 +465,11 @@ export class KiloProvider implements vscode.WebviewViewProvider { throw new Error("No session available") } - // Send message with text part - await this.httpClient.sendMessage(targetSessionID, [{ type: "text", text }], workspaceDir) + // Send message with text part and optional model selection + await this.httpClient.sendMessage(targetSessionID, [{ type: "text", text }], workspaceDir, { + providerID, + modelID, + }) } catch (error) { console.error("[Kilo New] KiloProvider: Failed to send message:", error) this.postMessage({ diff --git a/packages/kilo-vscode/src/services/cli-backend/http-client.ts b/packages/kilo-vscode/src/services/cli-backend/http-client.ts index 324e2744e53..c651cd9e89b 100644 --- a/packages/kilo-vscode/src/services/cli-backend/http-client.ts +++ b/packages/kilo-vscode/src/services/cli-backend/http-client.ts @@ -113,11 +113,19 @@ export class HttpClient { sessionId: string, parts: Array<{ type: "text"; text: string } | { type: "file"; mime: string; url: string }>, directory: string, + options?: { providerID?: string; modelID?: string }, ): Promise<{ info: MessageInfo; parts: MessagePart[] }> { + const body: Record = { parts } + if (options?.providerID) { + body.providerID = options.providerID + } + if (options?.modelID) { + body.modelID = options.modelID + } return this.request<{ info: MessageInfo; parts: MessagePart[] }>( "POST", `/session/${sessionId}/message`, - { parts }, + body, { directory }, ) }