From e0db29813d8ee7a6bb2da50f714a3fa27fcddce9 Mon Sep 17 00:00:00 2001 From: JinmingYang <2214962083@qq.com> Date: Wed, 8 Jan 2025 22:43:36 +0800 Subject: [PATCH] feat: add auto start action for markdown --- package.json | 2 +- pnpm-lock.yaml | 10 +- src/extension/actions/agent-actions.ts | 126 +++++++--------- src/extension/actions/apply-actions.ts | 66 ++++++-- src/extension/chat/index.ts | 6 +- .../strategies/{base => _base}/base-agent.ts | 4 +- .../strategies/{base => _base}/base-node.ts | 4 +- .../strategies/{base => _base}/base-state.ts | 0 .../{base => _base}/base-strategy.ts | 0 .../chat/strategies/{base => _base}/index.ts | 0 .../index.ts | 2 +- .../strategies/chat-strategy/chat-workflow.ts | 2 +- .../chat/strategies/chat-strategy/index.ts | 4 +- .../chat-messages-constructor.ts | 2 +- .../chat-strategy/nodes/agent-node.ts | 4 +- .../chat-strategy/nodes/generate-node.ts | 4 +- .../chat/strategies/chat-strategy/state.ts | 4 +- .../inline-diff-provider.ts | 26 +++- .../inline-diff-register/task-entity.ts | 26 +--- .../inline-diff-register/task-manager.ts | 11 ++ .../registers/inline-diff-register/types.ts | 15 ++ .../entities/ai-provider-entity/index.ts | 6 +- src/shared/entities/chat-context-entity.ts | 2 +- src/shared/plugins/_shared/strategies.ts | 2 +- .../server/create-agent-provider-manager.ts | 36 ++--- .../_for-migrate/codebase-search-agent.ts | 4 +- .../agents/_for-migrate/delete-files-agent.ts | 4 +- .../_for-migrate/doc-retriever-agent.ts | 4 +- .../agents/_for-migrate/edit-file-agent.ts | 4 +- .../agents/_for-migrate/file-search-agent.ts | 4 +- .../agents/_for-migrate/fs-visit-agent.ts | 4 +- .../agents/_for-migrate/grep-search-agent.ts | 4 +- .../agents/_for-migrate/list-dir-agent.ts | 4 +- .../_for-migrate/parallel-apply-agent.ts | 4 +- .../agents/_for-migrate/read-files-agent.ts | 4 +- .../agents/_for-migrate/reapply-agent.ts | 4 +- .../_for-migrate/run-terminal-cmd-agent.ts | 4 +- .../agents/_for-migrate/web-search-agent.ts | 4 +- .../agents/_for-migrate/web-visit-agent.ts | 4 +- .../codebase-search-agent-think-item.tsx | 2 +- .../server/codebase-search-agent.ts | 4 +- .../server/doc-retriever-agent.ts | 4 +- .../edit-file-agent-server-utils-provider.ts | 63 +++++--- .../server/edit-file-agent.ts | 4 +- .../agents/edit-file-agent-plugin/types.ts | 6 +- .../client/read-files-agent-think-item.tsx | 2 +- .../server/read-files-agent.ts | 4 +- .../client/web-search-agent-think-item.tsx | 2 +- .../server/web-search-agent.ts | 4 +- .../client/web-visit-agent-think-item.tsx | 2 +- .../server/web-visit-agent.ts | 4 +- .../plugins/mentions/_base/base-to-state.ts | 2 +- src/webview/components/chat/chat-ui.tsx | 2 +- .../markdown/code/block/file-block/index.tsx | 16 +- .../code/block/helpers/action-controller.tsx | 87 +++++++---- .../markdown/code/block/helpers/utils.ts | 1 + .../messages/markdown/code/block/index.tsx | 6 +- .../chat/messages/markdown/index.tsx | 103 +++++++------ .../markdown}/markdown-action-context.tsx | 45 +++++- .../messages/markdown/markdown-context.tsx | 26 ++++ .../chat/messages/markdown/utils.ts | 32 ++++ .../chat/messages/roles/chat-ai-message.tsx | 2 +- .../session-action-context.tsx | 141 +++++++----------- .../use-search-categories.tsx | 2 +- src/webview/hooks/chat/use-apply-code.ts | 6 +- 65 files changed, 564 insertions(+), 428 deletions(-) rename src/extension/chat/strategies/{base => _base}/base-agent.ts (97%) rename src/extension/chat/strategies/{base => _base}/base-node.ts (98%) rename src/extension/chat/strategies/{base => _base}/base-state.ts (100%) rename src/extension/chat/strategies/{base => _base}/base-strategy.ts (100%) rename src/extension/chat/strategies/{base => _base}/index.ts (100%) rename src/extension/chat/strategies/{auto-task-strategy => agent-strategy}/index.ts (67%) rename src/webview/{contexts/conversation-action-context => components/chat/messages/markdown}/markdown-action-context.tsx (65%) create mode 100644 src/webview/components/chat/messages/markdown/markdown-context.tsx diff --git a/package.json b/package.json index 8988a995..850cd91e 100644 --- a/package.json +++ b/package.json @@ -522,7 +522,7 @@ "@types/react-dom": "^19.0.2", "@types/shell-quote": "^1.7.5", "@types/turndown": "^5.0.5", - "@types/vscode": "1.93.0", + "@types/vscode": "1.96.0", "@types/vscode-webview": "^1.57.5", "@typescript-eslint/eslint-plugin": "^7.17.0", "@typescript-eslint/parser": "^7.17.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 173a773d..4bbae0de 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -160,8 +160,8 @@ importers: specifier: ^5.0.5 version: 5.0.5 '@types/vscode': - specifier: 1.93.0 - version: 1.93.0 + specifier: 1.96.0 + version: 1.96.0 '@types/vscode-webview': specifier: ^1.57.5 version: 1.57.5 @@ -3865,8 +3865,8 @@ packages: '@types/vscode-webview@1.57.5': resolution: {integrity: sha512-iBAUYNYkz+uk1kdsq05fEcoh8gJmwT3lqqFPN7MGyjQ3HVloViMdo7ZJ8DFIP8WOK74PjOEilosqAyxV2iUFUw==} - '@types/vscode@1.93.0': - resolution: {integrity: sha512-kUK6jAHSR5zY8ps42xuW89NLcBpw1kOabah7yv38J8MyiYuOHxLQBi0e7zeXbQgVefDy/mZZetqEFC+Fl5eIEQ==} + '@types/vscode@1.96.0': + resolution: {integrity: sha512-qvZbSZo+K4ZYmmDuaodMbAa67Pl6VDQzLKFka6rq+3WUTY4Kro7Bwoi0CuZLO/wema0ygcmpwow7zZfPJTs5jg==} '@types/web-bluetooth@0.0.20': resolution: {integrity: sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==} @@ -12606,7 +12606,7 @@ snapshots: '@types/vscode-webview@1.57.5': {} - '@types/vscode@1.93.0': {} + '@types/vscode@1.96.0': {} '@types/web-bluetooth@0.0.20': {} diff --git a/src/extension/actions/agent-actions.ts b/src/extension/actions/agent-actions.ts index 379e4cf7..24ab5aca 100644 --- a/src/extension/actions/agent-actions.ts +++ b/src/extension/actions/agent-actions.ts @@ -11,6 +11,23 @@ import type { AgentServerUtilsProvider } from '@shared/plugins/agents/_base/serv import { produce } from 'immer' import type { DraftFunction } from 'use-immer' +export type SingleSessionActionParams< + ActionType extends ConversationAction = ConversationAction +> = { + chatContext: ChatContext + conversation: Conversation + action: ActionType + autoRefresh?: boolean +} + +export type MultipleSessionActionParams< + ActionType extends ConversationAction = ConversationAction +> = { + chatContext: ChatContext + actionItems: { conversation: Conversation; action: ActionType }[] + autoRefresh?: boolean +} + export class AgentActionsCollection extends ServerActionCollection { readonly categoryName = 'agent' @@ -48,17 +65,13 @@ export class AgentActionsCollection extends ServerActionCollection { } private async handleAction( - context: ActionContext<{ - chatContext: ChatContext - conversation: Conversation - action: ConversationAction - autoRefresh?: boolean - }>, + context: ActionContext, handlerType: | 'onAcceptAction' | 'onRejectAction' | 'onStartAction' | 'onRestartAction' + | 'onRefreshAction' ) { const { action, autoRefresh = true } = context.actionParams const provider = this.getAgentServerUtilsProvider(action.agent?.name) @@ -71,15 +84,8 @@ export class AgentActionsCollection extends ServerActionCollection { } private async handleMultipleActions( - context: ActionContext<{ - chatContext: ChatContext - actionItems: { - conversation: Conversation - action: ConversationAction - }[] - autoRefresh?: boolean - }>, - handlerType: 'acceptAction' | 'rejectAction' + context: ActionContext, + handlerType: 'acceptAction' | 'rejectAction' | 'refreshAction' ) { const { chatContext, @@ -112,73 +118,41 @@ export class AgentActionsCollection extends ServerActionCollection { ) } - async acceptAction( - context: ActionContext<{ - chatContext: ChatContext - conversation: Conversation - action: ConversationAction - autoRefresh?: boolean - }> - ) { + async acceptAction(context: ActionContext) { await this.handleAction(context, 'onAcceptAction') } - async rejectAction( - context: ActionContext<{ - chatContext: ChatContext - conversation: Conversation - action: ConversationAction - autoRefresh?: boolean - }> - ) { + async rejectAction(context: ActionContext) { await this.handleAction(context, 'onRejectAction') } + async refreshAction(context: ActionContext) { + await this.handleAction(context, 'onRefreshAction') + } + async acceptMultipleActions( - context: ActionContext<{ - chatContext: ChatContext - actionItems: { - conversation: Conversation - action: ConversationAction - }[] - autoRefresh?: boolean - }> + context: ActionContext ) { await this.handleMultipleActions(context, 'acceptAction') } async rejectMultipleActions( - context: ActionContext<{ - chatContext: ChatContext - actionItems: { - conversation: Conversation - action: ConversationAction - }[] - autoRefresh?: boolean - }> + context: ActionContext ) { await this.handleMultipleActions(context, 'rejectAction') } - async startAction( - context: ActionContext<{ - chatContext: ChatContext - conversation: Conversation - action: ConversationAction - autoRefresh?: boolean - }> + async refreshMultipleActions( + context: ActionContext ) { + await this.handleMultipleActions(context, 'refreshAction') + } + + async startAction(context: ActionContext) { await this.handleAction(context, 'onStartAction') } - async restartAction( - context: ActionContext<{ - chatContext: ChatContext - conversation: Conversation - action: ConversationAction - autoRefresh?: boolean - }> - ) { + async restartAction(context: ActionContext) { await this.handleAction(context, 'onRestartAction') } @@ -188,13 +162,15 @@ export class AgentActionsCollection extends ServerActionCollection { conversation: Conversation action: ConversationAction updater: ConversationAction | DraftFunction + autoRefresh?: boolean }> ) { const { chatContext: oldChatContext, conversation, action, - updater + updater, + autoRefresh = false } = context.actionParams const chatContext = await runAction( @@ -213,25 +189,19 @@ export class AgentActionsCollection extends ServerActionCollection { if (conversationIndex === -1) throw new Error('Conversation not found') - const actionIndex = chatContext.conversations[ + let actionIndex = chatContext.conversations[ conversationIndex ]!.actions.findIndex(a => a.id === action.id) - if (actionIndex === -1) throw new Error('Action not found') - - const currentChatContext = await runAction( - this.registerManager - ).server.chatSession.getChatContext({ - actionParams: { - sessionId: chatContext.id + const newChatContext = produce(chatContext, draft => { + if (actionIndex === -1) { + draft!.conversations[conversationIndex]!.actions.push(action) + actionIndex = + draft!.conversations[conversationIndex]!.actions.length - 1 } - }) - const newChatContext = produce(currentChatContext, draft => { - const action = - draft!.conversations[conversationIndex]!.actions[actionIndex]! if (typeof updater === 'function') { - updater(action) + updater(draft!.conversations[conversationIndex]!.actions[actionIndex]!) } else { draft!.conversations[conversationIndex]!.actions[actionIndex] = updater } @@ -243,5 +213,9 @@ export class AgentActionsCollection extends ServerActionCollection { chatContext: newChatContext! } }) + + if (autoRefresh) { + await this.refreshChatSession() + } } } diff --git a/src/extension/actions/apply-actions.ts b/src/extension/actions/apply-actions.ts index 1357a8a3..7c792a8f 100644 --- a/src/extension/actions/apply-actions.ts +++ b/src/extension/actions/apply-actions.ts @@ -2,7 +2,7 @@ import { ModelProviderFactory } from '@extension/ai/model-providers/helpers/fact import { VsCodeFS } from '@extension/file-utils/vscode-fs' import { InlineDiffRegister } from '@extension/registers/inline-diff-register' import { TaskEntity } from '@extension/registers/inline-diff-register/task-entity' -import type { InlineDiffTask } from '@extension/registers/inline-diff-register/types' +import type { InlineDiffTaskJson } from '@extension/registers/inline-diff-register/types' import { HumanMessage, SystemMessage } from '@langchain/core/messages' import { ServerActionCollection } from '@shared/actions/server-action-collection' import type { ActionContext } from '@shared/actions/types' @@ -23,8 +23,9 @@ export class ApplyActionsCollection extends ServerActionCollection { code: string selectionRange?: vscode.Range cleanLast?: boolean + onTaskChange?: (task: InlineDiffTaskJson) => void }> - ): AsyncGenerator { + ): AsyncGenerator { const { abortController, actionParams } = context const { path, code, selectionRange, cleanLast } = actionParams if (!path || !code || !this.inlineDiffProvider) @@ -76,22 +77,57 @@ Don't reply with anything except the code. ) const finalSelectionRange = selectionRange || fullRange - yield await this.inlineDiffProvider.createTask( + this.inlineDiffProvider.taskChangeEmitter.event(task => { + if (task.id === taskId) { + context.actionParams.onTaskChange?.(task) + } + }) + + yield TaskEntity.toJson( + await this.inlineDiffProvider.createTask( + taskId, + uri, + finalSelectionRange, + '', + abortController + ) + ) + + const streamTask = await this.inlineDiffProvider.startStreamTask( taskId, - uri, - finalSelectionRange, - '', - abortController + buildAiStream ) - yield* await this.inlineDiffProvider.startStreamTask(taskId, buildAiStream) + for await (const task of streamTask) { + yield TaskEntity.toJson(task) + } + } + + async refreshApplyCodeTask( + context: ActionContext<{ + task: InlineDiffTaskJson + }> + ): Promise { + const { actionParams } = context + const task = TaskEntity.fromJson({ + ...actionParams.task, + abortController: context.abortController + }) + + if (!this.inlineDiffProvider) + throw new Error('refreshApplyCodeTask: inlineDiffProvider not found') + + const finalTask = this.inlineDiffProvider.taskManager.getTask(task.id) + if (!finalTask) return null + + return TaskEntity.toJson(finalTask) } async acceptApplyCodeTask( context: ActionContext<{ - task: InlineDiffTask + task: InlineDiffTaskJson }> - ): Promise { + ): Promise { const { actionParams } = context const task = TaskEntity.fromJson({ ...actionParams.task, @@ -101,14 +137,14 @@ Don't reply with anything except the code. if (!this.inlineDiffProvider) throw new Error('acceptApplyCodeTask: inlineDiffProvider not found') - return this.inlineDiffProvider.acceptAll(task) + return TaskEntity.toJson(await this.inlineDiffProvider.acceptAll(task)) } async rejectApplyCodeTask( context: ActionContext<{ - task: InlineDiffTask + task: InlineDiffTaskJson }> - ): Promise { + ): Promise { const { actionParams } = context const task = TaskEntity.fromJson({ ...actionParams.task, @@ -118,7 +154,7 @@ Don't reply with anything except the code. if (!this.inlineDiffProvider) throw new Error('rejectApplyCodeTask: inlineDiffProvider not found') - return this.inlineDiffProvider.rejectAll(task) + return TaskEntity.toJson(await this.inlineDiffProvider.rejectAll(task)) } async abortAndCleanApplyCodeTaskByPath( @@ -135,7 +171,7 @@ Don't reply with anything except the code. async abortAndCleanApplyCodeTask( context: ActionContext<{ - task: InlineDiffTask + task: InlineDiffTaskJson }> ): Promise { const { actionParams } = context diff --git a/src/extension/chat/index.ts b/src/extension/chat/index.ts index b8b4a96e..30cfa84d 100644 --- a/src/extension/chat/index.ts +++ b/src/extension/chat/index.ts @@ -6,11 +6,11 @@ import { type Conversation } from '@shared/entities' -import { AutoTaskStrategy } from './strategies/auto-task-strategy' import type { BaseStrategy, BaseStrategyOptions -} from './strategies/base/base-strategy' +} from './strategies/_base/base-strategy' +import { AgentStrategy } from './strategies/agent-strategy' import { ChatStrategy } from './strategies/chat-strategy' import { ComposerStrategy } from './strategies/composer-strategy' import { UIDesignerStrategy } from './strategies/ui-designer-strategy' @@ -38,7 +38,7 @@ export class ChatContextProcessor { [ChatContextType.Chat, new ChatStrategy(baseStrategyOptions)], [ChatContextType.Composer, new ComposerStrategy(baseStrategyOptions)], [ChatContextType.UIDesigner, new UIDesignerStrategy(baseStrategyOptions)], - [ChatContextType.AutoTask, new AutoTaskStrategy(baseStrategyOptions)] + [ChatContextType.Agent, new AgentStrategy(baseStrategyOptions)] ]) } diff --git a/src/extension/chat/strategies/base/base-agent.ts b/src/extension/chat/strategies/_base/base-agent.ts similarity index 97% rename from src/extension/chat/strategies/base/base-agent.ts rename to src/extension/chat/strategies/_base/base-agent.ts index 96a3d489..0dd5125e 100644 --- a/src/extension/chat/strategies/base/base-agent.ts +++ b/src/extension/chat/strategies/_base/base-agent.ts @@ -1,5 +1,5 @@ -import type { BaseGraphState } from '@extension/chat/strategies/base/base-state' -import type { BaseStrategyOptions } from '@extension/chat/strategies/base/base-strategy' +import type { BaseGraphState } from '@extension/chat/strategies/_base/base-state' +import type { BaseStrategyOptions } from '@extension/chat/strategies/_base/base-strategy' import { DynamicStructuredTool } from '@langchain/core/tools' import type { Agent } from '@shared/entities' import { z } from 'zod' diff --git a/src/extension/chat/strategies/base/base-node.ts b/src/extension/chat/strategies/_base/base-node.ts similarity index 98% rename from src/extension/chat/strategies/base/base-node.ts rename to src/extension/chat/strategies/_base/base-node.ts index f93357da..f2028d23 100644 --- a/src/extension/chat/strategies/base/base-node.ts +++ b/src/extension/chat/strategies/_base/base-node.ts @@ -2,8 +2,8 @@ import type { BaseGraphNode, BaseGraphState -} from '@extension/chat/strategies/base/base-state' -import type { BaseStrategyOptions } from '@extension/chat/strategies/base/base-strategy' +} from '@extension/chat/strategies/_base/base-state' +import type { BaseStrategyOptions } from '@extension/chat/strategies/_base/base-strategy' import { findCurrentToolsCallParams } from '@extension/chat/utils/find-current-tools-call-params' import { logger } from '@extension/logger' import type { ToolMessage } from '@langchain/core/messages' diff --git a/src/extension/chat/strategies/base/base-state.ts b/src/extension/chat/strategies/_base/base-state.ts similarity index 100% rename from src/extension/chat/strategies/base/base-state.ts rename to src/extension/chat/strategies/_base/base-state.ts diff --git a/src/extension/chat/strategies/base/base-strategy.ts b/src/extension/chat/strategies/_base/base-strategy.ts similarity index 100% rename from src/extension/chat/strategies/base/base-strategy.ts rename to src/extension/chat/strategies/_base/base-strategy.ts diff --git a/src/extension/chat/strategies/base/index.ts b/src/extension/chat/strategies/_base/index.ts similarity index 100% rename from src/extension/chat/strategies/base/index.ts rename to src/extension/chat/strategies/_base/index.ts diff --git a/src/extension/chat/strategies/auto-task-strategy/index.ts b/src/extension/chat/strategies/agent-strategy/index.ts similarity index 67% rename from src/extension/chat/strategies/auto-task-strategy/index.ts rename to src/extension/chat/strategies/agent-strategy/index.ts index 7ef63daa..d0438fea 100644 --- a/src/extension/chat/strategies/auto-task-strategy/index.ts +++ b/src/extension/chat/strategies/agent-strategy/index.ts @@ -1,4 +1,4 @@ /* eslint-disable @typescript-eslint/no-useless-constructor */ import { ChatStrategy } from '../chat-strategy' -export class AutoTaskStrategy extends ChatStrategy {} +export class AgentStrategy extends ChatStrategy {} diff --git a/src/extension/chat/strategies/chat-strategy/chat-workflow.ts b/src/extension/chat/strategies/chat-strategy/chat-workflow.ts index f3f2ddc8..407fa7d2 100644 --- a/src/extension/chat/strategies/chat-strategy/chat-workflow.ts +++ b/src/extension/chat/strategies/chat-strategy/chat-workflow.ts @@ -1,8 +1,8 @@ import { ServerPluginRegister } from '@extension/registers/server-plugin-register' import { END, START, StateGraph } from '@langchain/langgraph' +import type { BaseStrategyOptions } from '../_base/base-strategy' import { combineNode } from '../../utils/combine-node' -import type { BaseStrategyOptions } from '../base/base-strategy' import { AgentNode } from './nodes/agent-node' import { GenerateNode } from './nodes/generate-node' import { ChatGraphNodeName, chatGraphState, type ChatGraphState } from './state' diff --git a/src/extension/chat/strategies/chat-strategy/index.ts b/src/extension/chat/strategies/chat-strategy/index.ts index 7e0f7fe4..f1b95f79 100644 --- a/src/extension/chat/strategies/chat-strategy/index.ts +++ b/src/extension/chat/strategies/chat-strategy/index.ts @@ -2,8 +2,8 @@ import { type ChatContext, type Conversation } from '@shared/entities' import { UnPromise } from '@shared/types/common' import { produce } from 'immer' -import { baseGraphStateEventName } from '../base/base-state' -import { BaseStrategy } from '../base/base-strategy' +import { baseGraphStateEventName } from '../_base/base-state' +import { BaseStrategy } from '../_base/base-strategy' import { createChatWorkflow } from './chat-workflow' import { type ChatGraphState } from './state' diff --git a/src/extension/chat/strategies/chat-strategy/messages-constructors/chat-messages-constructor.ts b/src/extension/chat/strategies/chat-strategy/messages-constructors/chat-messages-constructor.ts index b3b293ec..c4a94641 100644 --- a/src/extension/chat/strategies/chat-strategy/messages-constructors/chat-messages-constructor.ts +++ b/src/extension/chat/strategies/chat-strategy/messages-constructors/chat-messages-constructor.ts @@ -6,7 +6,7 @@ import { HumanMessage, SystemMessage } from '@langchain/core/messages' import type { ChatContext, LangchainMessage } from '@shared/entities' import { settledPromiseResults } from '@shared/utils/common' -import type { BaseStrategyOptions } from '../../base/base-strategy' +import type { BaseStrategyOptions } from '../../_base/base-strategy' import { ConversationMessageConstructor } from './conversation-message-constructor' interface ChatMessagesConstructorOptions extends BaseStrategyOptions { diff --git a/src/extension/chat/strategies/chat-strategy/nodes/agent-node.ts b/src/extension/chat/strategies/chat-strategy/nodes/agent-node.ts index 96cbc166..bad66c8f 100644 --- a/src/extension/chat/strategies/chat-strategy/nodes/agent-node.ts +++ b/src/extension/chat/strategies/chat-strategy/nodes/agent-node.ts @@ -7,8 +7,8 @@ import { mergeConversationContents } from '@shared/utils/chat-context-helper/com import { parseAsConversationContents } from '@shared/utils/chat-context-helper/common/parse-as-conversation-contents' import { produce } from 'immer' -import { BaseNode } from '../../base/base-node' -import { dispatchBaseGraphState } from '../../base/base-state' +import { BaseNode } from '../../_base/base-node' +import { dispatchBaseGraphState } from '../../_base/base-state' import { ChatMessagesConstructor } from '../messages-constructors/chat-messages-constructor' import { type ChatGraphState } from '../state' diff --git a/src/extension/chat/strategies/chat-strategy/nodes/generate-node.ts b/src/extension/chat/strategies/chat-strategy/nodes/generate-node.ts index e4f82fa0..c8f1273e 100644 --- a/src/extension/chat/strategies/chat-strategy/nodes/generate-node.ts +++ b/src/extension/chat/strategies/chat-strategy/nodes/generate-node.ts @@ -4,8 +4,8 @@ import { mergeConversationContents } from '@shared/utils/chat-context-helper/com import { parseAsConversationContents } from '@shared/utils/chat-context-helper/common/parse-as-conversation-contents' import { produce } from 'immer' -import { BaseNode } from '../../base/base-node' -import { dispatchBaseGraphState } from '../../base/base-state' +import { BaseNode } from '../../_base/base-node' +import { dispatchBaseGraphState } from '../../_base/base-state' import { ChatMessagesConstructor } from '../messages-constructors/chat-messages-constructor' import { type ChatGraphState } from '../state' diff --git a/src/extension/chat/strategies/chat-strategy/state.ts b/src/extension/chat/strategies/chat-strategy/state.ts index 9d87ffec..114aae3f 100644 --- a/src/extension/chat/strategies/chat-strategy/state.ts +++ b/src/extension/chat/strategies/chat-strategy/state.ts @@ -4,8 +4,8 @@ import { baseGraphStateConfig, type BaseGraphNode, type CreateBaseGraphNode -} from '../base/base-state' -import type { BaseStrategyOptions } from '../base/base-strategy' +} from '../_base/base-state' +import type { BaseStrategyOptions } from '../_base/base-strategy' export enum ChatGraphNodeName { Agent = 'agent', diff --git a/src/extension/registers/inline-diff-register/inline-diff-provider.ts b/src/extension/registers/inline-diff-register/inline-diff-provider.ts index 03690e01..790bb849 100644 --- a/src/extension/registers/inline-diff-register/inline-diff-provider.ts +++ b/src/extension/registers/inline-diff-register/inline-diff-provider.ts @@ -5,15 +5,17 @@ import * as vscode from 'vscode' import { DecorationManager } from './decoration-manager' import { DiffProcessor } from './diff-processor' +import { TaskEntity } from './task-entity' import { TaskManager } from './task-manager' import { InlineDiffTaskState, type DiffBlock, - type InlineDiffTask + type InlineDiffTask, + type InlineDiffTaskJson } from './types' export class InlineDiffProvider implements vscode.CodeLensProvider { - private taskManager: TaskManager + taskManager: TaskManager private diffProcessor: DiffProcessor @@ -21,6 +23,9 @@ export class InlineDiffProvider implements vscode.CodeLensProvider { private codeLensEventEmitter: vscode.EventEmitter + taskChangeEmitter: vscode.EventEmitter = + new vscode.EventEmitter() + constructor() { this.diffProcessor = new DiffProcessor() this.decorationManager = new DecorationManager(this.diffProcessor) @@ -189,30 +194,38 @@ export class InlineDiffProvider implements vscode.CodeLensProvider { async acceptDiffs( task: InlineDiffTask, blocks: DiffBlock[], - actionId = uuidv4() + actionId = uuidv4(), + emitChange = true ) { const finalTask = this.taskManager.getTask(task.id) || task await this.taskManager.acceptDiffs(finalTask, blocks, actionId) + + if (emitChange) this.taskChangeEmitter.fire(TaskEntity.toJson(task)) } async rejectDiffs( task: InlineDiffTask, blocks: DiffBlock[], - actionId = uuidv4() + actionId = uuidv4(), + emitChange = true ) { const finalTask = this.taskManager.getTask(task.id) || task await this.taskManager.rejectDiffs(finalTask, blocks, actionId) + + if (emitChange) this.taskChangeEmitter.fire(TaskEntity.toJson(task)) } async acceptAll(task: InlineDiffTask, actionId = uuidv4()) { - await this.acceptDiffs(task, task.diffBlocks, actionId) + await this.acceptDiffs(task, task.diffBlocks, actionId, false) this.taskManager.updateTaskState(task, InlineDiffTaskState.Accepted) + this.taskChangeEmitter.fire(TaskEntity.toJson(task)) return task } async rejectAll(task: InlineDiffTask, actionId = uuidv4()) { - await this.rejectDiffs(task, task.diffBlocks, actionId) + await this.rejectDiffs(task, task.diffBlocks, actionId, false) this.taskManager.updateTaskState(task, InlineDiffTaskState.Rejected) + this.taskChangeEmitter.fire(TaskEntity.toJson(task)) return task } @@ -225,5 +238,6 @@ export class InlineDiffProvider implements vscode.CodeLensProvider { this.taskManager.dispose() this.decorationManager.dispose() this.diffProcessor.dispose() + this.taskChangeEmitter.dispose() } } diff --git a/src/extension/registers/inline-diff-register/task-entity.ts b/src/extension/registers/inline-diff-register/task-entity.ts index 67ae3934..0fe7170f 100644 --- a/src/extension/registers/inline-diff-register/task-entity.ts +++ b/src/extension/registers/inline-diff-register/task-entity.ts @@ -1,8 +1,6 @@ import { convertRangeJsonToVSCodeRange, - convertUriJsonToVSCodeUri, - type VSCodeRangeJson, - type VSCodeUriJson + convertUriJsonToVSCodeUri } from '@extension/utils' import { BaseEntity } from '@shared/entities' import { v4 as uuidv4 } from 'uuid' @@ -11,24 +9,10 @@ import * as vscode from 'vscode' import { HistoryManager } from './history-manager' import { InlineDiffTaskState, - type DiffAction, - type InlineDiffTask + type InlineDiffTask, + type InlineDiffTaskJson } from './types' -export interface TaskEntityJsonData - extends Omit< - InlineDiffTask, - 'selectionRange' | 'originalFileUri' | 'history' | 'error' - > { - selectionRange: VSCodeRangeJson - originalFileUri: VSCodeUriJson - error?: string - history: { - actions: DiffAction[] - position: number - } -} - export class TaskEntity extends BaseEntity { protected getDefaults(override?: Partial) { return { @@ -48,12 +32,12 @@ export class TaskEntity extends BaseEntity { } } - static toJson(task: InlineDiffTask): TaskEntityJsonData { + static toJson(task: InlineDiffTask): InlineDiffTaskJson { return JSON.parse(JSON.stringify(task)) } static fromJson( - taskJsonData: TaskEntityJsonData | InlineDiffTask + taskJsonData: InlineDiffTaskJson | InlineDiffTask ): InlineDiffTask { const task: InlineDiffTask = new TaskEntity({ ...taskJsonData, diff --git a/src/extension/registers/inline-diff-register/task-manager.ts b/src/extension/registers/inline-diff-register/task-manager.ts index 0521c0b3..eb660e60 100644 --- a/src/extension/registers/inline-diff-register/task-manager.ts +++ b/src/extension/registers/inline-diff-register/task-manager.ts @@ -126,6 +126,8 @@ export class TaskManager { try { this.updateTaskState(task, InlineDiffTaskState.Generating) + this.forceRefreshCodeLens() + yield task if (!task.abortController) { task.abortController = new AbortController() @@ -200,6 +202,7 @@ export class TaskManager { task.state = InlineDiffTaskState.Error task.error = error instanceof Error ? error : new Error(String(error)) logger.error('Error in task', error) + this.forceRefreshCodeLens() } async resetAndCleanHistory(taskId: string) { @@ -231,7 +234,15 @@ export class TaskManager { blocksWithRange ) + this.forceRefreshCodeLens() + } + + async forceRefreshCodeLens() { this.codeLensChangeEmitter.fire() + + setTimeout(() => { + this.codeLensChangeEmitter.fire() + }, 100) } async applyToDocumentAndRefresh( diff --git a/src/extension/registers/inline-diff-register/types.ts b/src/extension/registers/inline-diff-register/types.ts index e8200e60..1b76bb57 100644 --- a/src/extension/registers/inline-diff-register/types.ts +++ b/src/extension/registers/inline-diff-register/types.ts @@ -1,3 +1,4 @@ +import type { VSCodeRangeJson, VSCodeUriJson } from '@extension/utils' import type { Range, Uri } from 'vscode' import type { HistoryManager } from './history-manager' @@ -53,3 +54,17 @@ export interface InlineDiffTask { originalWaitForReviewDiffBlockIdCount: number history: HistoryManager } + +export interface InlineDiffTaskJson + extends Omit< + InlineDiffTask, + 'selectionRange' | 'originalFileUri' | 'history' | 'error' + > { + selectionRange: VSCodeRangeJson + originalFileUri: VSCodeUriJson + error?: string + history: { + actions: DiffAction[] + position: number + } +} diff --git a/src/shared/entities/ai-provider-entity/index.ts b/src/shared/entities/ai-provider-entity/index.ts index be029e9c..bebbed2f 100644 --- a/src/shared/entities/ai-provider-entity/index.ts +++ b/src/shared/entities/ai-provider-entity/index.ts @@ -68,7 +68,7 @@ export enum FeatureModelSettingKey { Default = 'default', Chat = 'chat', Composer = 'composer', - AutoTask = 'autoTask', + Agent = 'agent', UIDesigner = 'uiDesigner', Completion = 'completion', ApplyFile = 'applyFile', @@ -92,7 +92,7 @@ export const chatContextTypeModelSettingKeyMap: Record< [ChatContextType.Chat]: FeatureModelSettingKey.Chat, [ChatContextType.Composer]: FeatureModelSettingKey.Composer, [ChatContextType.UIDesigner]: FeatureModelSettingKey.UIDesigner, - [ChatContextType.AutoTask]: FeatureModelSettingKey.AutoTask + [ChatContextType.Agent]: FeatureModelSettingKey.Agent } export const modelSettingKeyTitleMap: Record = { @@ -100,7 +100,7 @@ export const modelSettingKeyTitleMap: Record = { [FeatureModelSettingKey.Chat]: 'Chat Model', [FeatureModelSettingKey.Composer]: 'Composer Model', [FeatureModelSettingKey.UIDesigner]: 'UI Designer Model', - [FeatureModelSettingKey.AutoTask]: 'Auto Task Model', + [FeatureModelSettingKey.Agent]: 'Agent Model', [FeatureModelSettingKey.Completion]: 'Completion Model', [FeatureModelSettingKey.ApplyFile]: 'Apply File Model', [FeatureModelSettingKey.BatchProcessor]: 'Batch Processor Model', diff --git a/src/shared/entities/chat-context-entity.ts b/src/shared/entities/chat-context-entity.ts index 98aedc31..c9975e22 100644 --- a/src/shared/entities/chat-context-entity.ts +++ b/src/shared/entities/chat-context-entity.ts @@ -68,5 +68,5 @@ export enum ChatContextType { Chat = 'chat', Composer = 'composer', UIDesigner = 'UIDesigner', - AutoTask = 'auto-task' + Agent = 'auto-task' } diff --git a/src/shared/plugins/_shared/strategies.ts b/src/shared/plugins/_shared/strategies.ts index 2adac033..4eefc0eb 100644 --- a/src/shared/plugins/_shared/strategies.ts +++ b/src/shared/plugins/_shared/strategies.ts @@ -1,2 +1,2 @@ -export * from '@extension/chat/strategies/base' +export * from '@extension/chat/strategies/_base' export * from '@extension/chat/strategies/chat-strategy/state' diff --git a/src/shared/plugins/agents/_base/server/create-agent-provider-manager.ts b/src/shared/plugins/agents/_base/server/create-agent-provider-manager.ts index b5ee4491..4a019aa9 100644 --- a/src/shared/plugins/agents/_base/server/create-agent-provider-manager.ts +++ b/src/shared/plugins/agents/_base/server/create-agent-provider-manager.ts @@ -1,10 +1,7 @@ -import type { BaseAgent } from '@extension/chat/strategies/base' +import type { SingleSessionActionParams } from '@extension/actions/agent-actions' +import type { BaseAgent } from '@extension/chat/strategies/_base' import type { ActionContext } from '@shared/actions/types' -import type { - ChatContext, - Conversation, - ConversationAction -} from '@shared/entities' +import type { ConversationAction } from '@shared/entities' import { ProviderManager } from '@shared/plugins/_shared/provider-manager' import type { AgentPluginId } from '../types' @@ -15,32 +12,19 @@ export interface AgentServerUtilsProvider< > { getAgentClass: () => new (...args: any[]) => AgentType onStartAction?: ( - context: ActionContext<{ - chatContext: ChatContext - conversation: Conversation - action: ActionType - }> + context: ActionContext> ) => Promise onRestartAction?: ( - context: ActionContext<{ - chatContext: ChatContext - conversation: Conversation - action: ActionType - }> + context: ActionContext> + ) => Promise + onRefreshAction?: ( + context: ActionContext> ) => Promise onAcceptAction?: ( - context: ActionContext<{ - chatContext: ChatContext - conversation: Conversation - action: ActionType - }> + context: ActionContext> ) => Promise onRejectAction?: ( - context: ActionContext<{ - chatContext: ChatContext - conversation: Conversation - action: ActionType - }> + context: ActionContext> ) => Promise } diff --git a/src/shared/plugins/agents/_for-migrate/codebase-search-agent.ts b/src/shared/plugins/agents/_for-migrate/codebase-search-agent.ts index 010c1bdf..1ea56080 100644 --- a/src/shared/plugins/agents/_for-migrate/codebase-search-agent.ts +++ b/src/shared/plugins/agents/_for-migrate/codebase-search-agent.ts @@ -1,5 +1,5 @@ -import { BaseAgent } from '@extension/chat/strategies/base/base-agent' -import type { BaseGraphState } from '@extension/chat/strategies/base/base-state' +import { BaseAgent } from '@extension/chat/strategies/_base/base-agent' +import type { BaseGraphState } from '@extension/chat/strategies/_base/base-state' import { CodebaseWatcherRegister } from '@extension/registers/codebase-watcher-register' import { mergeCodeSnippets } from '@shared/plugins/_shared/merge-code-snippets' import type { CodeSnippet } from '@shared/plugins/agents/codebase-search-agent-plugin/types' diff --git a/src/shared/plugins/agents/_for-migrate/delete-files-agent.ts b/src/shared/plugins/agents/_for-migrate/delete-files-agent.ts index 35456b27..8bed83a1 100644 --- a/src/shared/plugins/agents/_for-migrate/delete-files-agent.ts +++ b/src/shared/plugins/agents/_for-migrate/delete-files-agent.ts @@ -1,5 +1,5 @@ -import { BaseAgent } from '@extension/chat/strategies/base/base-agent' -import type { BaseGraphState } from '@extension/chat/strategies/base/base-state' +import { BaseAgent } from '@extension/chat/strategies/_base/base-agent' +import type { BaseGraphState } from '@extension/chat/strategies/_base/base-state' import { runAction } from '@extension/state' import { settledPromiseResults } from '@shared/utils/common' import { z } from 'zod' diff --git a/src/shared/plugins/agents/_for-migrate/doc-retriever-agent.ts b/src/shared/plugins/agents/_for-migrate/doc-retriever-agent.ts index 162c3193..7687c75b 100644 --- a/src/shared/plugins/agents/_for-migrate/doc-retriever-agent.ts +++ b/src/shared/plugins/agents/_for-migrate/doc-retriever-agent.ts @@ -1,5 +1,5 @@ -import { BaseAgent } from '@extension/chat/strategies/base/base-agent' -import type { BaseGraphState } from '@extension/chat/strategies/base/base-state' +import { BaseAgent } from '@extension/chat/strategies/_base/base-agent' +import type { BaseGraphState } from '@extension/chat/strategies/_base/base-state' import { DocCrawler } from '@extension/chat/utils/doc-crawler' import { DocIndexer } from '@extension/chat/vectordb/doc-indexer' import { aidePaths } from '@extension/file-utils/paths' diff --git a/src/shared/plugins/agents/_for-migrate/edit-file-agent.ts b/src/shared/plugins/agents/_for-migrate/edit-file-agent.ts index 54742cea..7338666e 100644 --- a/src/shared/plugins/agents/_for-migrate/edit-file-agent.ts +++ b/src/shared/plugins/agents/_for-migrate/edit-file-agent.ts @@ -1,5 +1,5 @@ -import { BaseAgent } from '@extension/chat/strategies/base/base-agent' -import type { BaseGraphState } from '@extension/chat/strategies/base/base-state' +import { BaseAgent } from '@extension/chat/strategies/_base/base-agent' +import type { BaseGraphState } from '@extension/chat/strategies/_base/base-state' import { runAction } from '@extension/state' import { z } from 'zod' diff --git a/src/shared/plugins/agents/_for-migrate/file-search-agent.ts b/src/shared/plugins/agents/_for-migrate/file-search-agent.ts index 39799a3d..ec4c4868 100644 --- a/src/shared/plugins/agents/_for-migrate/file-search-agent.ts +++ b/src/shared/plugins/agents/_for-migrate/file-search-agent.ts @@ -1,5 +1,5 @@ -import { BaseAgent } from '@extension/chat/strategies/base/base-agent' -import type { BaseGraphState } from '@extension/chat/strategies/base/base-state' +import { BaseAgent } from '@extension/chat/strategies/_base/base-agent' +import type { BaseGraphState } from '@extension/chat/strategies/_base/base-state' import { createShouldIgnore } from '@extension/file-utils/ignore-patterns' import { traverseFileOrFolders, diff --git a/src/shared/plugins/agents/_for-migrate/fs-visit-agent.ts b/src/shared/plugins/agents/_for-migrate/fs-visit-agent.ts index 9e0666fd..f2b20d7f 100644 --- a/src/shared/plugins/agents/_for-migrate/fs-visit-agent.ts +++ b/src/shared/plugins/agents/_for-migrate/fs-visit-agent.ts @@ -1,5 +1,5 @@ -import { BaseAgent } from '@extension/chat/strategies/base/base-agent' -import type { BaseGraphState } from '@extension/chat/strategies/base/base-state' +import { BaseAgent } from '@extension/chat/strategies/_base/base-agent' +import type { BaseGraphState } from '@extension/chat/strategies/_base/base-state' import { getValidFiles } from '@extension/file-utils/get-valid-files' import type { FileInfo } from '@extension/file-utils/traverse-fs' import { z } from 'zod' diff --git a/src/shared/plugins/agents/_for-migrate/grep-search-agent.ts b/src/shared/plugins/agents/_for-migrate/grep-search-agent.ts index 7f3c4f48..f5d40cff 100644 --- a/src/shared/plugins/agents/_for-migrate/grep-search-agent.ts +++ b/src/shared/plugins/agents/_for-migrate/grep-search-agent.ts @@ -1,5 +1,5 @@ -import { BaseAgent } from '@extension/chat/strategies/base/base-agent' -import type { BaseGraphState } from '@extension/chat/strategies/base/base-state' +import { BaseAgent } from '@extension/chat/strategies/_base/base-agent' +import type { BaseGraphState } from '@extension/chat/strategies/_base/base-state' import { createShouldIgnore } from '@extension/file-utils/ignore-patterns' import { VsCodeFS } from '@extension/file-utils/vscode-fs' import { getWorkspaceFolder } from '@extension/utils' diff --git a/src/shared/plugins/agents/_for-migrate/list-dir-agent.ts b/src/shared/plugins/agents/_for-migrate/list-dir-agent.ts index 6ba1f14a..0abc3b4a 100644 --- a/src/shared/plugins/agents/_for-migrate/list-dir-agent.ts +++ b/src/shared/plugins/agents/_for-migrate/list-dir-agent.ts @@ -1,5 +1,5 @@ -import { BaseAgent } from '@extension/chat/strategies/base/base-agent' -import type { BaseGraphState } from '@extension/chat/strategies/base/base-state' +import { BaseAgent } from '@extension/chat/strategies/_base/base-agent' +import type { BaseGraphState } from '@extension/chat/strategies/_base/base-state' import { traverseFileOrFolders } from '@extension/file-utils/traverse-fs' import { getWorkspaceFolder } from '@extension/utils' import { z } from 'zod' diff --git a/src/shared/plugins/agents/_for-migrate/parallel-apply-agent.ts b/src/shared/plugins/agents/_for-migrate/parallel-apply-agent.ts index bd25420b..5a085bee 100644 --- a/src/shared/plugins/agents/_for-migrate/parallel-apply-agent.ts +++ b/src/shared/plugins/agents/_for-migrate/parallel-apply-agent.ts @@ -1,5 +1,5 @@ -import { BaseAgent } from '@extension/chat/strategies/base/base-agent' -import type { BaseGraphState } from '@extension/chat/strategies/base/base-state' +import { BaseAgent } from '@extension/chat/strategies/_base/base-agent' +import type { BaseGraphState } from '@extension/chat/strategies/_base/base-state' import { runAction } from '@extension/state' import { z } from 'zod' diff --git a/src/shared/plugins/agents/_for-migrate/read-files-agent.ts b/src/shared/plugins/agents/_for-migrate/read-files-agent.ts index 78ad6e26..82dd941d 100644 --- a/src/shared/plugins/agents/_for-migrate/read-files-agent.ts +++ b/src/shared/plugins/agents/_for-migrate/read-files-agent.ts @@ -1,5 +1,5 @@ -import { BaseAgent } from '@extension/chat/strategies/base/base-agent' -import type { BaseGraphState } from '@extension/chat/strategies/base/base-state' +import { BaseAgent } from '@extension/chat/strategies/_base/base-agent' +import type { BaseGraphState } from '@extension/chat/strategies/_base/base-state' import { VsCodeFS } from '@extension/file-utils/vscode-fs' import { logger } from '@extension/logger' import { runAction } from '@extension/state' diff --git a/src/shared/plugins/agents/_for-migrate/reapply-agent.ts b/src/shared/plugins/agents/_for-migrate/reapply-agent.ts index 39835e2a..48786e47 100644 --- a/src/shared/plugins/agents/_for-migrate/reapply-agent.ts +++ b/src/shared/plugins/agents/_for-migrate/reapply-agent.ts @@ -1,5 +1,5 @@ -import { BaseAgent } from '@extension/chat/strategies/base/base-agent' -import type { BaseGraphState } from '@extension/chat/strategies/base/base-state' +import { BaseAgent } from '@extension/chat/strategies/_base/base-agent' +import type { BaseGraphState } from '@extension/chat/strategies/_base/base-state' import { runAction } from '@extension/state' import { z } from 'zod' diff --git a/src/shared/plugins/agents/_for-migrate/run-terminal-cmd-agent.ts b/src/shared/plugins/agents/_for-migrate/run-terminal-cmd-agent.ts index 0ced7ec9..bcfa4a4f 100644 --- a/src/shared/plugins/agents/_for-migrate/run-terminal-cmd-agent.ts +++ b/src/shared/plugins/agents/_for-migrate/run-terminal-cmd-agent.ts @@ -1,5 +1,5 @@ -import { BaseAgent } from '@extension/chat/strategies/base/base-agent' -import type { BaseGraphState } from '@extension/chat/strategies/base/base-state' +import { BaseAgent } from '@extension/chat/strategies/_base/base-agent' +import type { BaseGraphState } from '@extension/chat/strategies/_base/base-state' import { runAction } from '@extension/state' import { z } from 'zod' diff --git a/src/shared/plugins/agents/_for-migrate/web-search-agent.ts b/src/shared/plugins/agents/_for-migrate/web-search-agent.ts index a0b02984..1e0b735b 100644 --- a/src/shared/plugins/agents/_for-migrate/web-search-agent.ts +++ b/src/shared/plugins/agents/_for-migrate/web-search-agent.ts @@ -1,6 +1,6 @@ import { ModelProviderFactory } from '@extension/ai/model-providers/helpers/factory' -import { BaseAgent } from '@extension/chat/strategies/base/base-agent' -import type { BaseGraphState } from '@extension/chat/strategies/base/base-state' +import { BaseAgent } from '@extension/chat/strategies/_base/base-agent' +import type { BaseGraphState } from '@extension/chat/strategies/_base/base-state' import { ChatMessagesConstructor } from '@extension/chat/strategies/chat-strategy/messages-constructors/chat-messages-constructor' import { searxngSearch } from '@extension/chat/utils/searxng-search' import { logger } from '@extension/logger' diff --git a/src/shared/plugins/agents/_for-migrate/web-visit-agent.ts b/src/shared/plugins/agents/_for-migrate/web-visit-agent.ts index f6d29ee3..22ed397b 100644 --- a/src/shared/plugins/agents/_for-migrate/web-visit-agent.ts +++ b/src/shared/plugins/agents/_for-migrate/web-visit-agent.ts @@ -1,5 +1,5 @@ -import { BaseAgent } from '@extension/chat/strategies/base/base-agent' -import type { BaseGraphState } from '@extension/chat/strategies/base/base-state' +import { BaseAgent } from '@extension/chat/strategies/_base/base-agent' +import type { BaseGraphState } from '@extension/chat/strategies/_base/base-state' import { DocCrawler } from '@extension/chat/utils/doc-crawler' import { settledPromiseResults } from '@shared/utils/common' import { z } from 'zod' diff --git a/src/shared/plugins/agents/codebase-search-agent-plugin/client/codebase-search-agent-think-item.tsx b/src/shared/plugins/agents/codebase-search-agent-plugin/client/codebase-search-agent-think-item.tsx index f43feaea..f4629b46 100644 --- a/src/shared/plugins/agents/codebase-search-agent-plugin/client/codebase-search-agent-think-item.tsx +++ b/src/shared/plugins/agents/codebase-search-agent-plugin/client/codebase-search-agent-think-item.tsx @@ -1,5 +1,5 @@ import type { FC } from 'react' -import type { GetAgent } from '@extension/chat/strategies/base' +import type { GetAgent } from '@extension/chat/strategies/_base' import type { FileInfo } from '@extension/file-utils/traverse-fs' import type { CustomRenderThinkItemProps } from '@shared/plugins/agents/_base/client/agent-client-plugin-types' import type { CodebaseSearchAgent } from '@shared/plugins/agents/codebase-search-agent-plugin/server/codebase-search-agent' diff --git a/src/shared/plugins/agents/codebase-search-agent-plugin/server/codebase-search-agent.ts b/src/shared/plugins/agents/codebase-search-agent-plugin/server/codebase-search-agent.ts index 322ae6cc..199f3a74 100644 --- a/src/shared/plugins/agents/codebase-search-agent-plugin/server/codebase-search-agent.ts +++ b/src/shared/plugins/agents/codebase-search-agent-plugin/server/codebase-search-agent.ts @@ -1,5 +1,5 @@ -import { BaseAgent } from '@extension/chat/strategies/base' -import type { BaseGraphState } from '@extension/chat/strategies/base/base-state' +import { BaseAgent } from '@extension/chat/strategies/_base' +import type { BaseGraphState } from '@extension/chat/strategies/_base/base-state' import { CodebaseWatcherRegister } from '@extension/registers/codebase-watcher-register' import { mergeCodeSnippets } from '@shared/plugins/_shared/merge-code-snippets' import { AgentPluginId } from '@shared/plugins/agents/_base/types' diff --git a/src/shared/plugins/agents/doc-retriever-agent-plugin/server/doc-retriever-agent.ts b/src/shared/plugins/agents/doc-retriever-agent-plugin/server/doc-retriever-agent.ts index 61fa5d3c..43ccb0ed 100644 --- a/src/shared/plugins/agents/doc-retriever-agent-plugin/server/doc-retriever-agent.ts +++ b/src/shared/plugins/agents/doc-retriever-agent-plugin/server/doc-retriever-agent.ts @@ -1,5 +1,5 @@ -import { BaseAgent } from '@extension/chat/strategies/base/base-agent' -import type { BaseGraphState } from '@extension/chat/strategies/base/base-state' +import { BaseAgent } from '@extension/chat/strategies/_base/base-agent' +import type { BaseGraphState } from '@extension/chat/strategies/_base/base-state' import { DocCrawler } from '@extension/chat/utils/doc-crawler' import { DocIndexer } from '@extension/chat/vectordb/doc-indexer' import { aidePaths } from '@extension/file-utils/paths' diff --git a/src/shared/plugins/agents/edit-file-agent-plugin/server/edit-file-agent-server-utils-provider.ts b/src/shared/plugins/agents/edit-file-agent-plugin/server/edit-file-agent-server-utils-provider.ts index 8a3a1289..8423e3e4 100644 --- a/src/shared/plugins/agents/edit-file-agent-plugin/server/edit-file-agent-server-utils-provider.ts +++ b/src/shared/plugins/agents/edit-file-agent-plugin/server/edit-file-agent-server-utils-provider.ts @@ -1,7 +1,7 @@ +import type { SingleSessionActionParams } from '@extension/actions/agent-actions' import { InlineDiffTaskState } from '@extension/registers/inline-diff-register/types' import { runAction } from '@extension/state' import type { ActionContext } from '@shared/actions/types' -import type { ChatContext, Conversation } from '@shared/entities' import type { AgentServerUtilsProvider } from '@shared/plugins/agents/_base/server/create-agent-provider-manager' import { getErrorMsg } from '@shared/utils/common' import { cloneDeep } from 'es-toolkit' @@ -19,11 +19,7 @@ export class EditFileAgentServerUtilsProvider } async onStartAction( - context: ActionContext<{ - chatContext: ChatContext - conversation: Conversation - action: EditFileAction - }> + context: ActionContext> ) { const { agent } = context.actionParams.action const streamTask = @@ -32,11 +28,17 @@ export class EditFileAgentServerUtilsProvider actionParams: { path: agent?.input.targetFilePath || '', code: agent?.input.codeEdit || '', - cleanLast: true + cleanLast: true, + onTaskChange: () => { + runAction().server.agent.refreshAction({ + ...context, + abortController: new AbortController() + }) + } } }) - let lastTaskState: InlineDiffTaskState | undefined + let lastTaskState = InlineDiffTaskState.Idle for await (const task of streamTask) { if (lastTaskState !== task.state) { await runAction().server.agent.updateCurrentAction({ @@ -46,7 +48,8 @@ export class EditFileAgentServerUtilsProvider updater: _draft => { const draft = _draft as WritableDraft draft.state.inlineDiffTask = cloneDeep(task) - } + }, + autoRefresh: true } }) } @@ -59,11 +62,7 @@ export class EditFileAgentServerUtilsProvider } async onRestartAction( - context: ActionContext<{ - chatContext: ChatContext - conversation: Conversation - action: EditFileAction - }> + context: ActionContext> ) { const { inlineDiffTask } = context.actionParams.action.state if (!inlineDiffTask) throw new Error('Inline diff task not found') @@ -79,11 +78,7 @@ export class EditFileAgentServerUtilsProvider } async onAcceptAction( - context: ActionContext<{ - chatContext: ChatContext - conversation: Conversation - action: EditFileAction - }> + context: ActionContext> ) { const { inlineDiffTask } = context.actionParams.action.state if (!inlineDiffTask) throw new Error('Inline diff task not found') @@ -107,11 +102,7 @@ export class EditFileAgentServerUtilsProvider } async onRejectAction( - context: ActionContext<{ - chatContext: ChatContext - conversation: Conversation - action: EditFileAction - }> + context: ActionContext> ) { const { inlineDiffTask } = context.actionParams.action.state if (!inlineDiffTask) throw new Error('Inline diff task not found') @@ -133,4 +124,28 @@ export class EditFileAgentServerUtilsProvider } }) } + + async onRefreshAction( + context: ActionContext> + ) { + const { inlineDiffTask } = context.actionParams.action.state + if (!inlineDiffTask) throw new Error('Inline diff task not found') + const finalTask = await runAction().server.apply.refreshApplyCodeTask({ + ...context, + actionParams: { + task: inlineDiffTask + } + }) + + await runAction().server.agent.updateCurrentAction({ + ...context, + actionParams: { + ...context.actionParams, + updater: _draft => { + const draft = _draft as Writeable + draft.state.inlineDiffTask = finalTask + } + } + }) + } } diff --git a/src/shared/plugins/agents/edit-file-agent-plugin/server/edit-file-agent.ts b/src/shared/plugins/agents/edit-file-agent-plugin/server/edit-file-agent.ts index cfe09530..38dcef8e 100644 --- a/src/shared/plugins/agents/edit-file-agent-plugin/server/edit-file-agent.ts +++ b/src/shared/plugins/agents/edit-file-agent-plugin/server/edit-file-agent.ts @@ -1,5 +1,5 @@ -import { BaseAgent } from '@extension/chat/strategies/base/base-agent' -import type { BaseGraphState } from '@extension/chat/strategies/base/base-state' +import { BaseAgent } from '@extension/chat/strategies/_base/base-agent' +import type { BaseGraphState } from '@extension/chat/strategies/_base/base-state' import { VsCodeFS } from '@extension/file-utils/vscode-fs' import { z } from 'zod' diff --git a/src/shared/plugins/agents/edit-file-agent-plugin/types.ts b/src/shared/plugins/agents/edit-file-agent-plugin/types.ts index 22caea7d..1ecfaa22 100644 --- a/src/shared/plugins/agents/edit-file-agent-plugin/types.ts +++ b/src/shared/plugins/agents/edit-file-agent-plugin/types.ts @@ -1,11 +1,11 @@ -import type { GetAgent } from '@extension/chat/strategies/base' -import type { InlineDiffTask } from '@extension/registers/inline-diff-register/types' +import type { GetAgent } from '@extension/chat/strategies/_base' +import type { InlineDiffTaskJson } from '@extension/registers/inline-diff-register/types' import type { ConversationAction } from '@shared/entities' import type { EditFileAgent } from './server/edit-file-agent' export interface EditFileAgentState { - inlineDiffTask: InlineDiffTask | null + inlineDiffTask: InlineDiffTaskJson | null } export type EditFileAction = ConversationAction< diff --git a/src/shared/plugins/agents/read-files-agent-plugin/client/read-files-agent-think-item.tsx b/src/shared/plugins/agents/read-files-agent-plugin/client/read-files-agent-think-item.tsx index acc1c5ac..1079611c 100644 --- a/src/shared/plugins/agents/read-files-agent-plugin/client/read-files-agent-think-item.tsx +++ b/src/shared/plugins/agents/read-files-agent-plugin/client/read-files-agent-think-item.tsx @@ -1,4 +1,4 @@ -import type { GetAgent } from '@extension/chat/strategies/base' +import type { GetAgent } from '@extension/chat/strategies/_base' import type { CustomRenderThinkItemProps } from '@shared/plugins/agents/_base/client/agent-client-plugin-types' import type { SFC } from '@shared/types/common' import { ChatThinkItem } from '@webview/components/chat/messages/roles/chat-thinks' diff --git a/src/shared/plugins/agents/read-files-agent-plugin/server/read-files-agent.ts b/src/shared/plugins/agents/read-files-agent-plugin/server/read-files-agent.ts index 8ac205e2..46206faa 100644 --- a/src/shared/plugins/agents/read-files-agent-plugin/server/read-files-agent.ts +++ b/src/shared/plugins/agents/read-files-agent-plugin/server/read-files-agent.ts @@ -1,5 +1,5 @@ -import { BaseAgent } from '@extension/chat/strategies/base/base-agent' -import type { BaseGraphState } from '@extension/chat/strategies/base/base-state' +import { BaseAgent } from '@extension/chat/strategies/_base/base-agent' +import type { BaseGraphState } from '@extension/chat/strategies/_base/base-state' import { getFileHash } from '@extension/file-utils/get-file-hash' import { VsCodeFS } from '@extension/file-utils/vscode-fs' import { settledPromiseResults } from '@shared/utils/common' diff --git a/src/shared/plugins/agents/web-search-agent-plugin/client/web-search-agent-think-item.tsx b/src/shared/plugins/agents/web-search-agent-plugin/client/web-search-agent-think-item.tsx index fabdab27..169bee34 100644 --- a/src/shared/plugins/agents/web-search-agent-plugin/client/web-search-agent-think-item.tsx +++ b/src/shared/plugins/agents/web-search-agent-plugin/client/web-search-agent-think-item.tsx @@ -1,4 +1,4 @@ -import type { GetAgent } from '@extension/chat/strategies/base' +import type { GetAgent } from '@extension/chat/strategies/_base' import type { CustomRenderThinkItemProps } from '@shared/plugins/agents/_base/client/agent-client-plugin-types' import type { SFC } from '@shared/types/common' import { ChatThinkItem } from '@webview/components/chat/messages/roles/chat-thinks' diff --git a/src/shared/plugins/agents/web-search-agent-plugin/server/web-search-agent.ts b/src/shared/plugins/agents/web-search-agent-plugin/server/web-search-agent.ts index 8682ceeb..7287a825 100644 --- a/src/shared/plugins/agents/web-search-agent-plugin/server/web-search-agent.ts +++ b/src/shared/plugins/agents/web-search-agent-plugin/server/web-search-agent.ts @@ -1,6 +1,6 @@ import { ModelProviderFactory } from '@extension/ai/model-providers/helpers/factory' -import { BaseAgent } from '@extension/chat/strategies/base/base-agent' -import type { BaseGraphState } from '@extension/chat/strategies/base/base-state' +import { BaseAgent } from '@extension/chat/strategies/_base/base-agent' +import type { BaseGraphState } from '@extension/chat/strategies/_base/base-state' import { ChatMessagesConstructor } from '@extension/chat/strategies/chat-strategy/messages-constructors/chat-messages-constructor' import { searxngSearch } from '@extension/chat/utils/searxng-search' import { logger } from '@extension/logger' diff --git a/src/shared/plugins/agents/web-visit-agent-plugin/client/web-visit-agent-think-item.tsx b/src/shared/plugins/agents/web-visit-agent-plugin/client/web-visit-agent-think-item.tsx index 599a27ef..535c592a 100644 --- a/src/shared/plugins/agents/web-visit-agent-plugin/client/web-visit-agent-think-item.tsx +++ b/src/shared/plugins/agents/web-visit-agent-plugin/client/web-visit-agent-think-item.tsx @@ -1,4 +1,4 @@ -import type { GetAgent } from '@extension/chat/strategies/base' +import type { GetAgent } from '@extension/chat/strategies/_base' import type { CustomRenderThinkItemProps } from '@shared/plugins/agents/_base/client/agent-client-plugin-types' import type { SFC } from '@shared/types/common' import { ChatThinkItem } from '@webview/components/chat/messages/roles/chat-thinks' diff --git a/src/shared/plugins/agents/web-visit-agent-plugin/server/web-visit-agent.ts b/src/shared/plugins/agents/web-visit-agent-plugin/server/web-visit-agent.ts index a1c25682..e478ad14 100644 --- a/src/shared/plugins/agents/web-visit-agent-plugin/server/web-visit-agent.ts +++ b/src/shared/plugins/agents/web-visit-agent-plugin/server/web-visit-agent.ts @@ -1,5 +1,5 @@ -import { BaseAgent } from '@extension/chat/strategies/base/base-agent' -import type { BaseGraphState } from '@extension/chat/strategies/base/base-state' +import { BaseAgent } from '@extension/chat/strategies/_base/base-agent' +import type { BaseGraphState } from '@extension/chat/strategies/_base/base-state' import { DocCrawler } from '@extension/chat/utils/doc-crawler' import { settledPromiseResults } from '@shared/utils/common' import { z } from 'zod' diff --git a/src/shared/plugins/mentions/_base/base-to-state.ts b/src/shared/plugins/mentions/_base/base-to-state.ts index 54b32ae3..98982ca5 100644 --- a/src/shared/plugins/mentions/_base/base-to-state.ts +++ b/src/shared/plugins/mentions/_base/base-to-state.ts @@ -1,7 +1,7 @@ import type { BaseAgent, GetAgentOutput -} from '@extension/chat/strategies/base/base-agent' +} from '@extension/chat/strategies/_base/base-agent' import type { Agent, Conversation, Mention } from '@shared/entities' export abstract class BaseToState { diff --git a/src/webview/components/chat/chat-ui.tsx b/src/webview/components/chat/chat-ui.tsx index 7f0a60d0..f31856a5 100644 --- a/src/webview/components/chat/chat-ui.tsx +++ b/src/webview/components/chat/chat-ui.tsx @@ -28,7 +28,7 @@ import { ChatSidebar } from './sidebar/chat-sidebar' const CHAT_TYPES = [ { value: ChatContextType.Chat, label: 'Chat' }, { value: ChatContextType.Composer, label: 'Composer' }, - { value: ChatContextType.AutoTask, label: 'Auto Task' }, + { value: ChatContextType.Agent, label: 'Agent' }, { value: ChatContextType.UIDesigner, label: 'UI Designer' } ] as const diff --git a/src/webview/components/chat/messages/markdown/code/block/file-block/index.tsx b/src/webview/components/chat/messages/markdown/code/block/file-block/index.tsx index baecc272..c64e1f18 100644 --- a/src/webview/components/chat/messages/markdown/code/block/file-block/index.tsx +++ b/src/webview/components/chat/messages/markdown/code/block/file-block/index.tsx @@ -1,4 +1,3 @@ -/* eslint-disable unused-imports/no-unused-vars */ import { type FC } from 'react' import type { FileInfo } from '@extension/file-utils/traverse-fs' import { InlineDiffTaskState } from '@extension/registers/inline-diff-register/types' @@ -20,7 +19,7 @@ import { useChildrenInfo } from '../helpers/use-children-info' export interface FileBlockProps extends Omit { isLoading?: boolean - originalContent: string + isBlockClosed: boolean enableActionController?: boolean children: React.ReactNode } @@ -28,13 +27,17 @@ export interface FileBlockProps extends Omit { export const FileBlock: FC = ({ defaultExpanded, isLoading = false, - originalContent, enableActionController = false, + isBlockClosed, children, ...rest }) => { - const { content, shikiLang, markdownLang, fileInfo, fileContent } = - useChildrenInfo(children) + const { + content: codeBlockContent, + shikiLang, + fileInfo, + fileContent + } = useChildrenInfo(children) const copyToClipboard = () => { navigator.clipboard.writeText(fileContent) @@ -92,8 +95,9 @@ export const FileBlock: FC = ({ <> {enableActionController && ( )} = ({ - originalContent, - fileRelativePath + codeBlockContent, + fileRelativePath, + isBlockClosed }) => { - const [debouncedOriginalContent, setDebouncedOriginalContent] = useState('') - - useDebounce( - () => { - setDebouncedOriginalContent(originalContent) - }, - 1000, - [originalContent] - ) - const { addAction } = useMarkdownActionContext() + const { getContext } = useChatContext() + const { startActionMutation } = useSessionActionContext() + + const allowAutoStartAction = + true || + [ChatContextType.Composer, ChatContextType.Agent].includes( + getContext().type + ) useEffect(() => { // add file edit action - if (!debouncedOriginalContent || !fileRelativePath) return + if (!isBlockClosed || !fileRelativePath) return addAction({ - currentContent: debouncedOriginalContent, + currentContent: codeBlockContent, action: { state: { inlineDiffTask: null @@ -42,7 +46,7 @@ export const ActionController: React.FC = ({ name: AgentPluginId.EditFile, input: { blocking: false, - codeEdit: debouncedOriginalContent, + codeEdit: codeBlockContent, instructions: 'Edit the file by composer', targetFilePath: fileRelativePath }, @@ -51,18 +55,49 @@ export const ActionController: React.FC = ({ } } }, - onRemoveSameAction: oldAction => { - const oldInlineDiffTask = oldAction.state.inlineDiffTask - if (oldInlineDiffTask) { - api.actions().server.apply.abortAndCleanApplyCodeTask({ - actionParams: { - task: oldInlineDiffTask + onSuccess: async ({ conversation, action, oldAction }) => { + try { + if (!allowAutoStartAction) return + + logger.dev.log('auto start action', { + conversation, + action, + oldAction + }) + + // stop old action + if (oldAction) { + const oldInlineDiffTask = oldAction.state?.inlineDiffTask + if (oldInlineDiffTask) { + await api.actions().server.apply.abortAndCleanApplyCodeTask({ + actionParams: { + task: oldInlineDiffTask + } + }) } + } + + // start new action + await startActionMutation.mutateAsync({ + conversation, + action, + chatContext: getContext() }) + } catch (error) { + logAndToastError( + 'Failed to start action when closing code block', + error + ) } } }) - }, [debouncedOriginalContent, fileRelativePath]) + }, [ + codeBlockContent, + fileRelativePath, + isBlockClosed, + allowAutoStartAction, + getContext + ]) return null } diff --git a/src/webview/components/chat/messages/markdown/code/block/helpers/utils.ts b/src/webview/components/chat/messages/markdown/code/block/helpers/utils.ts index bd581bae..02518639 100644 --- a/src/webview/components/chat/messages/markdown/code/block/helpers/utils.ts +++ b/src/webview/components/chat/messages/markdown/code/block/helpers/utils.ts @@ -67,6 +67,7 @@ const _getContentInfoFromChildren = ( } export const FALLBACK_LANG = 'typescript' + export const getContentInfoFromChildren = ( children: React.ReactNode ): { diff --git a/src/webview/components/chat/messages/markdown/code/block/index.tsx b/src/webview/components/chat/messages/markdown/code/block/index.tsx index e69abdcd..f73004e0 100644 --- a/src/webview/components/chat/messages/markdown/code/block/index.tsx +++ b/src/webview/components/chat/messages/markdown/code/block/index.tsx @@ -1,6 +1,8 @@ import { type FC, type ReactNode } from 'react' import { cn } from '@webview/utils/common' +import { useMarkdownContext } from '../../markdown-context' +import { isCodeBlockClosed } from '../../utils' import { FileBlock } from './file-block' import type { BaseCodeBlockProps } from './helpers/types' import { getContentInfoFromChildren } from './helpers/utils' @@ -21,6 +23,8 @@ export const CodeBlock: FC = ({ ...rest }) => { const { content, markdownLang } = getContentInfoFromChildren(children) + const { markdownContent } = useMarkdownContext() + const isBlockClosed = isCodeBlockClosed(content, markdownContent || '') if (!content) return null @@ -38,8 +42,8 @@ export const CodeBlock: FC = ({ return ( {children} diff --git a/src/webview/components/chat/messages/markdown/index.tsx b/src/webview/components/chat/messages/markdown/index.tsx index 652f2c7b..89a55926 100644 --- a/src/webview/components/chat/messages/markdown/index.tsx +++ b/src/webview/components/chat/messages/markdown/index.tsx @@ -32,6 +32,7 @@ import { import { CodeBlock } from './code/block' import { InlineCode } from './code/inline' +import { MarkdownContextProvider } from './markdown-context' export type MarkdownVariant = 'normal' | 'chat' @@ -93,51 +94,63 @@ export const Markdown: FC = ({ } as CSSProperties return ( -
- - ) => , - img: (props: ComponentProps<'img'>) => ( - - ), - pre: (props: ComponentProps<'pre'>) => ( - - ), - code: (props: ComponentProps<'code'>) => , - video: (props: ComponentProps<'video'>) => ( -