Skip to content

Commit a3ddaf6

Browse files
committed
feat: fix some bug for provider
1 parent aa1c592 commit a3ddaf6

File tree

7 files changed

+136
-26
lines changed

7 files changed

+136
-26
lines changed

src/extension/ai/model-providers/aide.ts

Lines changed: 101 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,108 @@
11
import { logger } from '@extension/logger'
2-
import { AIProviderType, type AideProvider } from '@shared/entities'
2+
import { ChatAnthropic } from '@langchain/anthropic'
3+
import {
4+
ChatOpenAI,
5+
type ChatOpenAICallOptions,
6+
type ClientOptions as OpenAIClientOptions
7+
} from '@langchain/openai'
8+
import {
9+
AIProviderType,
10+
type AideProvider,
11+
type OpenAIProvider
12+
} from '@shared/entities'
13+
import { t } from 'i18next'
14+
import OpenAI from 'openai'
315

416
import { aideKeyUsageInfo } from '../aide-key-request'
5-
import { type BaseModelUsageInfo } from './helpers/base'
6-
import { OpenAIModelProvider } from './openai'
17+
import { BaseModelProvider, type BaseModelUsageInfo } from './helpers/base'
18+
19+
export class AideModelProvider extends BaseModelProvider<
20+
ChatOpenAI<ChatOpenAICallOptions> | ChatAnthropic
21+
> {
22+
createOpenaiClient(options?: OpenAIClientOptions) {
23+
const { extraFields } = this.aiProvider as OpenAIProvider
24+
const openai = new OpenAI({
25+
baseURL: extraFields.apiBaseUrl,
26+
apiKey: extraFields.apiKey,
27+
fetch,
28+
...options
29+
})
30+
31+
return openai
32+
}
33+
34+
private async createLangChainAnthropicModel() {
35+
if (!this.aiModel?.name) {
36+
throw new Error(t('extension.modelProviders.errors.modelNameRequired'))
37+
}
38+
39+
const { extraFields } = this.aiProvider as AideProvider
40+
// remove baseURL /v1
41+
const anthropicApiUrl = extraFields.apiBaseUrl.replace(/\/v1$/, '')
42+
43+
const model = new ChatAnthropic({
44+
apiKey: extraFields.apiKey,
45+
anthropicApiUrl,
46+
clientOptions: {
47+
fetch,
48+
defaultHeaders: {
49+
Authorization: `Bearer ${extraFields.apiKey}`
50+
}
51+
},
52+
modelName: this.aiModel.name,
53+
temperature: 0.95,
54+
maxRetries: 6,
55+
verbose: this.isDev
56+
})
57+
58+
return model
59+
}
60+
61+
private async createLangChainOpenAIModel() {
62+
if (!this.aiModel?.name) {
63+
throw new Error(t('extension.modelProviders.errors.modelNameRequired'))
64+
}
65+
66+
const { extraFields } = this.aiProvider as AideProvider
67+
68+
const model = new ChatOpenAI({
69+
apiKey: extraFields.apiKey,
70+
configuration: {
71+
baseURL: extraFields.apiBaseUrl,
72+
fetch
73+
},
74+
modelName: this.aiModel.name,
75+
temperature: 0.95,
76+
maxRetries: 3,
77+
verbose: this.isDev
78+
})
79+
80+
// Clear incompatible parameters for third-party models
81+
model.frequencyPenalty = undefined as any
82+
model.n = undefined as any
83+
model.presencePenalty = undefined as any
84+
model.topP = undefined as any
85+
86+
return model
87+
}
88+
89+
createLangChainModel() {
90+
const isAnthropicModels = /claude|anthropic/.test(this.aiModel?.name || '')
91+
92+
if (isAnthropicModels) {
93+
return this.createLangChainAnthropicModel()
94+
}
95+
96+
return this.createLangChainOpenAIModel()
97+
}
98+
99+
async getSupportModelNames() {
100+
const openai = this.createOpenaiClient()
101+
const list = await openai.models.list()
102+
103+
return list.data.map(model => model.id)
104+
}
7105

8-
export class AideModelProvider extends OpenAIModelProvider {
9106
async getUsageInfo(): Promise<BaseModelUsageInfo | null> {
10107
try {
11108
// Ensure this is an Aide provider and has an API key

src/extension/ai/model-providers/anthropic.ts

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,13 @@ import { t } from 'i18next'
55

66
import { BaseModelProvider } from './helpers/base'
77

8-
interface AnthropicModel {
9-
id: string
10-
}
11-
128
export class AnthropicModelProvider extends BaseModelProvider<ChatAnthropic> {
139
createAnthropicClient(options?: ClientOptions) {
1410
const { extraFields } = this.aiProvider as AnthropicProvider
1511

1612
return new Anthropic({
17-
apiKey: extraFields.anthropicApiKey,
18-
baseURL: extraFields.anthropicApiUrl,
13+
apiKey: extraFields.apiKey,
14+
baseURL: extraFields.apiBaseUrl,
1915
fetch,
2016
...options
2117
})
@@ -29,8 +25,8 @@ export class AnthropicModelProvider extends BaseModelProvider<ChatAnthropic> {
2925
const { extraFields } = this.aiProvider as AnthropicProvider
3026

3127
const model = new ChatAnthropic({
32-
apiKey: extraFields.anthropicApiKey,
33-
anthropicApiUrl: extraFields.anthropicApiUrl,
28+
apiKey: extraFields.apiKey,
29+
anthropicApiUrl: extraFields.apiBaseUrl,
3430
clientOptions: {
3531
fetch
3632
},
@@ -45,8 +41,8 @@ export class AnthropicModelProvider extends BaseModelProvider<ChatAnthropic> {
4541

4642
async getSupportModelNames() {
4743
const anthropic = this.createAnthropicClient()
48-
const list = await anthropic.get<any, AnthropicModel[]>('/v1/models')
44+
const list = await anthropic.models.list()
4945

50-
return list.map(model => model.id)
46+
return list.data.map(model => model.id)
5147
}
5248
}

src/shared/entities/ai-provider-entity/anthropic.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ import {
1010
export interface AnthropicProvider extends AIProvider {
1111
type: AIProviderType.Anthropic
1212
extraFields: {
13-
anthropicApiUrl: string
14-
anthropicApiKey: string
13+
apiBaseUrl: string
14+
apiKey: string
1515
}
1616
}
1717

@@ -23,14 +23,14 @@ export class AnthropicProviderEntity extends AIProviderEntity<AnthropicProvider>
2323
name: t('shared.aiProvider.name.anthropic'),
2424
fields: [
2525
{
26-
key: 'anthropicApiUrl',
26+
key: 'apiBaseUrl',
2727
label: t('shared.aiProvider.fields.label.anthropicApiUrl'),
2828
required: true,
29-
disabled: true,
29+
disabled: false,
3030
defaultValue: 'https://api.anthropic.com'
3131
},
3232
{
33-
key: 'anthropicApiKey',
33+
key: 'apiKey',
3434
label: t('shared.aiProvider.fields.label.anthropicApiKey'),
3535
required: true,
3636
isSecret: true

src/shared/entities/ai-provider-entity/openai.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export class OpenAIProviderEntity extends AIProviderEntity<OpenAIProvider> {
2828
key: 'apiBaseUrl',
2929
label: t('shared.aiProvider.fields.label.openaiApiBaseUrl'),
3030
required: true,
31-
disabled: true,
31+
disabled: false,
3232
defaultValue: 'https://api.openai.com/v1'
3333
},
3434
{

src/webview/components/chat/selectors/file-selector/file-list-view.tsx

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ export const FileListView: React.FC<FileListViewProps> = ({
7070
className={cn(
7171
'cursor-pointer text-sm mx-2 px-1 py-1 flex items-center data-[selected=true]:bg-secondary data-[selected=true]:text-foreground'
7272
)}
73+
style={{
74+
height: '28px',
75+
containIntrinsicSize: '28px'
76+
}}
7377
>
7478
<div className="flex shrink-0 items-center mr-2">
7579
<input
@@ -90,9 +94,19 @@ export const FileListView: React.FC<FileListViewProps> = ({
9094
return (
9195
<div className="flex flex-col h-full pt-1">
9296
<Command loop ref={commandRef} shouldFilter={false}>
93-
<CommandList className="py-2">
97+
<CommandList
98+
className="py-2"
99+
style={{
100+
contentVisibility: 'auto'
101+
}}
102+
>
94103
{!filteredFiles.length ? (
95-
<CommandEmpty>
104+
<CommandEmpty
105+
style={{
106+
containIntrinsicSize: '28px',
107+
height: '28px'
108+
}}
109+
>
96110
{t('webview.fileSelector.noFilesFound')}
97111
</CommandEmpty>
98112
) : (

src/webview/components/chat/selectors/model-selector.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -250,11 +250,11 @@ export const ModelSelector: React.FC<ModelSelectorProps> = ({
250250
actionParams: { ...data, order } as Omit<AIProvider, 'id'>
251251
})
252252
setIsAddingProvider(false)
253-
invalidateQueries({
253+
await invalidateQueries({
254254
type: 'all-webview',
255255
queryKeys: [providersQueryKey]
256256
})
257-
invalidateQueries({
257+
await invalidateQueries({
258258
type: 'all-webview',
259259
queryKeys: [modelsQueryKey]
260260
})
@@ -373,7 +373,10 @@ export const ModelSelector: React.FC<ModelSelectorProps> = ({
373373
initialProvider={editingProvider}
374374
onSubmit={async data => {
375375
await api.actions().server.aiProvider.updateProvider({
376-
actionParams: data as AIProvider
376+
actionParams: {
377+
...data,
378+
id: editingProvider?.id
379+
} as AIProvider
377380
})
378381
setEditingProvider(undefined)
379382
invalidateQueries({

src/webview/components/settings/custom-renders/ai-provider-management/provider-form/edit-provider-form.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ export const EditProviderForm = ({
8383
/>
8484
</ScrollArea>
8585

86-
<Button className="w-full" disabled={isSubmitting}>
86+
<Button className="w-full" type="submit" disabled={isSubmitting}>
8787
{isSubmitting
8888
? t('webview.aiProvider.saving')
8989
: t('webview.aiProvider.saveChanges')}

0 commit comments

Comments
 (0)