Merge remote-tracking branch 'origin/main' into new_unified

This commit is contained in:
Matt Rubens
2025-01-16 21:53:36 -05:00
40 changed files with 2911 additions and 254 deletions

View File

@@ -25,8 +25,12 @@ export interface ExtensionMessage {
| "enhancedPrompt"
| "commitSearchResults"
| "listApiConfig"
| "vsCodeLmModels"
| "vsCodeLmApiAvailable"
| "requestVsCodeLmModels"
| "updatePrompt"
| "systemPrompt"
| "autoApprovalEnabled"
text?: string
action?:
| "chatButtonClicked"
@@ -40,6 +44,7 @@ export interface ExtensionMessage {
images?: string[]
ollamaModels?: string[]
lmStudioModels?: string[]
vsCodeLmModels?: { vendor?: string; family?: string; version?: string; id?: string }[]
filePaths?: string[]
partialMessage?: ClineMessage
glamaModels?: Record<string, ModelInfo>
@@ -89,7 +94,8 @@ export interface ExtensionState {
mode: Mode
modeApiConfigs?: Record<Mode, string>
enhancementApiConfigId?: string
experimentalDiffStrategy?: boolean
experimentalDiffStrategy?: boolean
autoApprovalEnabled?: boolean
}
export interface ClineMessage {

View File

@@ -61,17 +61,19 @@ export interface WebviewMessage {
| "terminalOutputLineLimit"
| "mcpEnabled"
| "searchCommits"
| "refreshGlamaModels"
| "alwaysApproveResubmit"
| "requestDelaySeconds"
| "setApiConfigPassword"
| "requestVsCodeLmModels"
| "mode"
| "updatePrompt"
| "updateEnhancedPrompt"
| "getSystemPrompt"
| "systemPrompt"
| "enhancementApiConfigId"
| "experimentalDiffStrategy"
| "experimentalDiffStrategy"
| "autoApprovalEnabled"
text?: string
disabled?: boolean
askResponse?: ClineAskResponse

View File

@@ -0,0 +1,56 @@
import { checkExistKey } from '../checkExistApiConfig';
import { ApiConfiguration } from '../api';
describe('checkExistKey', () => {
it('should return false for undefined config', () => {
expect(checkExistKey(undefined)).toBe(false);
});
it('should return false for empty config', () => {
const config: ApiConfiguration = {};
expect(checkExistKey(config)).toBe(false);
});
it('should return true when one key is defined', () => {
const config: ApiConfiguration = {
apiKey: 'test-key'
};
expect(checkExistKey(config)).toBe(true);
});
it('should return true when multiple keys are defined', () => {
const config: ApiConfiguration = {
apiKey: 'test-key',
glamaApiKey: 'glama-key',
openRouterApiKey: 'openrouter-key'
};
expect(checkExistKey(config)).toBe(true);
});
it('should return true when only non-key fields are undefined', () => {
const config: ApiConfiguration = {
apiKey: 'test-key',
apiProvider: undefined,
anthropicBaseUrl: undefined
};
expect(checkExistKey(config)).toBe(true);
});
it('should return false when all key fields are undefined', () => {
const config: ApiConfiguration = {
apiKey: undefined,
glamaApiKey: undefined,
openRouterApiKey: undefined,
awsRegion: undefined,
vertexProjectId: undefined,
openAiApiKey: undefined,
ollamaModelId: undefined,
lmStudioModelId: undefined,
geminiApiKey: undefined,
openAiNativeApiKey: undefined,
deepSeekApiKey: undefined,
vsCodeLmModelSelector: undefined
};
expect(checkExistKey(config)).toBe(false);
});
});

View File

@@ -0,0 +1,44 @@
import { stringifyVsCodeLmModelSelector, SELECTOR_SEPARATOR } from '../vsCodeSelectorUtils';
import { LanguageModelChatSelector } from 'vscode';
describe('vsCodeSelectorUtils', () => {
describe('stringifyVsCodeLmModelSelector', () => {
it('should join all defined selector properties with separator', () => {
const selector: LanguageModelChatSelector = {
vendor: 'test-vendor',
family: 'test-family',
version: 'v1',
id: 'test-id'
};
const result = stringifyVsCodeLmModelSelector(selector);
expect(result).toBe('test-vendor/test-family/v1/test-id');
});
it('should skip undefined properties', () => {
const selector: LanguageModelChatSelector = {
vendor: 'test-vendor',
family: 'test-family'
};
const result = stringifyVsCodeLmModelSelector(selector);
expect(result).toBe('test-vendor/test-family');
});
it('should handle empty selector', () => {
const selector: LanguageModelChatSelector = {};
const result = stringifyVsCodeLmModelSelector(selector);
expect(result).toBe('');
});
it('should handle selector with only one property', () => {
const selector: LanguageModelChatSelector = {
vendor: 'test-vendor'
};
const result = stringifyVsCodeLmModelSelector(selector);
expect(result).toBe('test-vendor');
});
});
});

View File

@@ -1,3 +1,5 @@
import * as vscode from 'vscode';
export type ApiProvider =
| "anthropic"
| "glama"
@@ -10,11 +12,13 @@ export type ApiProvider =
| "gemini"
| "openai-native"
| "deepseek"
| "vscode-lm"
export interface ApiHandlerOptions {
apiModelId?: string
apiKey?: string // anthropic
anthropicBaseUrl?: string
vsCodeLmModelSelector?: vscode.LanguageModelChatSelector
glamaModelId?: string
glamaModelInfo?: ModelInfo
glamaApiKey?: string
@@ -58,7 +62,7 @@ export type ApiConfiguration = ApiHandlerOptions & {
export interface ModelInfo {
maxTokens?: number
contextWindow?: number
contextWindow: number
supportsImages?: boolean
supportsComputerUse?: boolean
supportsPromptCache: boolean // this value is hardcoded for now

View File

@@ -13,7 +13,8 @@ export function checkExistKey(config: ApiConfiguration | undefined) {
config.lmStudioModelId,
config.geminiApiKey,
config.openAiNativeApiKey,
config.deepSeekApiKey
config.deepSeekApiKey,
config.vsCodeLmModelSelector,
].some((key) => key !== undefined)
: false;
}

View File

@@ -0,0 +1,14 @@
import { LanguageModelChatSelector } from 'vscode';
export const SELECTOR_SEPARATOR = '/';
export function stringifyVsCodeLmModelSelector(selector: LanguageModelChatSelector): string {
return [
selector.vendor,
selector.family,
selector.version,
selector.id
]
.filter(Boolean)
.join(SELECTOR_SEPARATOR);
}