Skip to content

Commit

Permalink
feat: refactor mention plugin system
Browse files Browse the repository at this point in the history
  • Loading branch information
2214962083 committed Dec 17, 2024
1 parent 60024ea commit 36615e8
Show file tree
Hide file tree
Showing 93 changed files with 2,953 additions and 1,614 deletions.
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -134,5 +134,6 @@
"xsss",
"Zhipu",
"zustand"
]
],
"testing.automaticallyOpenTestResults": "neverOpen"
}
23 changes: 21 additions & 2 deletions src/extension/ai/model-providers/helpers/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ import { aiModelDB } from '@extension/webview-api/lowdb/ai-model-db'
import { aiProviderDB } from '@extension/webview-api/lowdb/ai-provider-db'
import { globalSettingsDB } from '@extension/webview-api/lowdb/settings-db'
import type { MessageContent } from '@langchain/core/messages'
import type { ChatContext } from '@shared/entities'
import type { AIModel } from '@shared/entities/ai-model-entity'
import {
AIProvider,
AIProviderType,
chatContextTypeModelSettingKeyMap,
FeatureModelSettingKey,
FeatureModelSettingValue
} from '@shared/entities/ai-provider-entity'
Expand All @@ -23,6 +25,7 @@ export class ModelProviderFactory {
const provider = (await aiProviderDB.getAll()).find(
p => p.id === providerId
)

if (!provider) {
throw new Error(`Provider not found: ${providerId}`)
}
Expand Down Expand Up @@ -90,6 +93,12 @@ export class ModelProviderFactory {
return await this.create(setting)
}

static async getModelProviderForChatContext(chatContext: ChatContext) {
const chatContextType = chatContext.type
const modelSettingKey = chatContextTypeModelSettingKeyMap[chatContextType]
return await this.getModelProvider(modelSettingKey)
}

static async getModelSettingForFeature(
key: FeatureModelSettingKey,
useDefault = true
Expand All @@ -99,9 +108,19 @@ export class ModelProviderFactory {
FeatureModelSettingValue
> | null = await globalSettingsDB.getSetting('models')

const isExtendsDefault =
!settings?.[key]?.providerId && !settings?.[key]?.modelName

const defaultSetting = settings?.[FeatureModelSettingKey.Default]

if (isExtendsDefault && useDefault && !defaultSetting) {
throw new Error(
'You forgot to set provider or model in your settings, please check your settings.'
)
}

const setting =
settings?.[key] ||
(useDefault ? settings?.[FeatureModelSettingKey.Default] : undefined)
isExtendsDefault && useDefault ? defaultSetting : settings?.[key]

return setting
}
Expand Down
46 changes: 46 additions & 0 deletions src/extension/registers/controller-register.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import type { CommandManager } from '@extension/commands/command-manager'
import {
controllers,
type Controllers
} from '@extension/webview-api/controllers'
import type { Controller } from '@extension/webview-api/types'
import * as vscode from 'vscode'

import { BaseRegister } from './base-register'
import type { RegisterManager } from './register-manager'

export class ControllerRegister extends BaseRegister {
public controllers: Map<string, Controller> = new Map()

constructor(
protected context: vscode.ExtensionContext,
protected registerManager: RegisterManager,
protected commandManager: CommandManager
) {
super(context, registerManager, commandManager)
}

async register(): Promise<void> {
for (const ControllerClass of controllers) {
const controller = new ControllerClass(
this.registerManager,
this.commandManager
)
this.controllers.set(controller.name, controller)
}
}

api<T extends InstanceType<Controllers[number]>['name']>(
apiName: T
): Extract<InstanceType<Controllers[number]>, { name: T }> {
// Type assertion needed since Map.get doesn't preserve the exact type
return this.controllers.get(apiName) as Extract<
InstanceType<Controllers[number]>,
{ name: T }
>
}

dispose(): void {
this.controllers.clear()
}
}
2 changes: 2 additions & 0 deletions src/extension/registers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { AideKeyUsageStatusBarRegister } from './aide-key-usage-statusbar-regist
import { AutoOpenCorrespondingFilesRegister } from './auto-open-corresponding-files-register'
import { BaseRegister } from './base-register'
import { CodebaseWatcherRegister } from './codebase-watcher-register'
import { ControllerRegister } from './controller-register'
import { InlineDiffRegister } from './inline-diff-register'
import { ModelRegister } from './model-register'
import { RegisterManager } from './register-manager'
Expand All @@ -22,6 +23,7 @@ export const setupRegisters = async (registerManager: RegisterManager) => {
InlineDiffRegister,
TerminalWatcherRegister,
ServerPluginRegister,
ControllerRegister,
WebviewRegister,
ModelRegister,
CodebaseWatcherRegister
Expand Down
2 changes: 1 addition & 1 deletion src/extension/webview-api/chat-context-processor/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { AutoTaskStrategy } from './strategies/auto-task-strategy'
import type {
BaseStrategy,
BaseStrategyOptions
} from './strategies/base-strategy'
} from './strategies/base/base-strategy'
import { ChatStrategy } from './strategies/chat-strategy'
import { ComposerStrategy } from './strategies/composer-strategy'
import { UIDesignerStrategy } from './strategies/ui-designer-strategy'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import type { BaseGraphState } from '@extension/webview-api/chat-context-processor/strategies/base/base-state'
import type { BaseStrategyOptions } from '@extension/webview-api/chat-context-processor/strategies/base/base-strategy'
import { DynamicStructuredTool } from '@langchain/core/tools'
import type { Agent } from '@shared/entities'
import { z } from 'zod'

export interface AgentContext<
State extends BaseGraphState = BaseGraphState,
CreateToolOptions extends Record<string, any> = Record<string, any>,
StrategyOptions extends BaseStrategyOptions = BaseStrategyOptions
> {
state: State
createToolOptions: CreateToolOptions
strategyOptions: StrategyOptions
}

export abstract class BaseAgent<
State extends BaseGraphState = BaseGraphState,
CreateToolOptions extends Record<string, any> = Record<string, any>,
StrategyOptions extends BaseStrategyOptions = BaseStrategyOptions,
TInput extends z.ZodType = z.ZodType,
TOutput extends z.ZodType = z.ZodType
> {
abstract inputSchema: TInput

abstract outputSchema: TOutput

abstract name: string

abstract logTitle: string

abstract description: string

constructor(
public context: AgentContext<State, CreateToolOptions, StrategyOptions>
) {}

// Abstract method that needs to be implemented by concrete agents
abstract execute(input: z.infer<TInput>): Promise<z.infer<TOutput>>

// Create the Langchain tool
public async createTool(): Promise<DynamicStructuredTool | null> {
return new DynamicStructuredTool({
name: this.name,
description: this.description,
schema: this.inputSchema as any,
func: async (input: z.infer<TInput>) => {
const result = await this.execute(input)
return this.outputSchema.parse(result)
}
})
}
}

export type GetAgentInput<T extends BaseAgent> = z.infer<T['inputSchema']>

export type GetAgentOutput<T extends BaseAgent> = z.infer<T['outputSchema']>

export type GetAgent<T extends BaseAgent> = Agent<
GetAgentInput<T>,
GetAgentOutput<T>
>
Loading

0 comments on commit 36615e8

Please sign in to comment.