feat: add stop functionality to chat input and update related components#4440
Conversation
Walkthrough该 PR 涉及多个模块的改动,更新了测试用例、服务组件、样式、国际化以及公共接口。改动内容包括重构聊天代理服务及其测试、新增和调整 MCP 服务器管理接口、优化内联补全与上下文提示逻辑、扩展 AI 模型配置支持(如 Anthropic、DeepSeek、OpenAICompatible)以及更新交互组件与工具调用接口。整体上,这些更新重新组织了上下文管理、消息报告、工具调用及相关视图逻辑,增强了扩展性和配置灵活性。 Changes
Sequence Diagram(s)sequenceDiagram
participant C as 客户端
participant ABS as AIBackService
participant AModel as AnthropicModel
participant OAM as OpenAICompatibleModel
C->>ABS: requestStream(model, request)
alt model 为 "anthropic"
ABS->>AModel: 调用 request(request, options)
AModel-->>ABS: 返回数据流
else model 不为 openai、deepseek、anthropic
ABS->>OAM: 调用 request(request, options, trimTexts)
OAM-->>ABS: 返回数据流
end
ABS-->>C: 返回数据流
Possibly related PRs
Suggested labels
Warning There were issues while running some tools. Please review the errors and either fix the tool’s configuration or disable the tool if it’s a critical failure. 🔧 ESLint
yarn install v1.22.22 ✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Caution
Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.
Actionable comments posted: 12
🔭 Outside diff range comments (1)
packages/components/src/popover/index.tsx (1)
30-50: 🛠️ Refactor suggestion接口定义与实现不一致
注意到
IPopoverProps接口中的delay属性定义(第36行)没有包含默认值,而在组件实现中添加了默认值。为了保持代码的一致性和自文档化,建议也更新接口定义。- delay?: number; + delay?: number = 200;
🧹 Nitpick comments (62)
packages/ai-native/src/browser/mcp/tools/handlers/ListDir.ts (2)
59-61: 新方法getWorkspaceDir()实现正确,但可以考虑重用它这个方法提供了一个获取工作区目录的简洁方式,实现正确。不过,在
handler方法的第 70 行中,您直接使用了this.appConfig.workspaceDir,可以考虑重用这个新方法以提高代码一致性。建议在
handler方法中使用新的getWorkspaceDir()方法:- const absolutePath = `${this.appConfig.workspaceDir}/${relativeWorkspacePath}`; + const absolutePath = `${this.getWorkspaceDir()}/${relativeWorkspacePath}`;
59-61: 缺少 JSDoc 文档注释作为公共 API,建议为
getWorkspaceDir()方法添加 JSDoc 文档注释,说明其用途和返回值。建议添加以下文档注释:
+/** + * 获取工作区目录路径 + * @returns {string} 工作区目录的绝对路径 + */ getWorkspaceDir(): string { return this.appConfig.workspaceDir; }packages/core-browser/src/contextkey/ai-native.ts (1)
7-7: 缺少上下文键的用途说明建议添加简短注释说明此上下文键的用途,与文件中其他键保持一致的文档风格。
建议添加简短注释:
+// 代码编辑是否可见 export const CodeEditsIsVisible = new RawContextKey('ai.native.codeEditsIsVisible', false);packages/core-browser/src/style/override.less (1)
94-96: 建议添加样式注释为了提高代码可维护性,建议添加简短注释说明此样式的用途。
建议添加简短注释:
+ /* 键盘 Tab 按键图标样式 */ .codicon-keyboard-tab { color: var(--vscode-icon-foreground); }packages/core-common/src/settings/ai-native.ts (1)
32-32: 缺少 JSDoc 文档注释与其他设置项相比,新添加的
ModelID缺少 JSDoc 文档注释来说明其用途。建议添加 JSDoc 文档注释,与文件中其他设置项保持一致:
+ /** + * 语言模型 ID + */ ModelID = 'ai.native.llm.model.id',packages/preferences/src/browser/preferenceItem.view.tsx (1)
148-151: 使用 useMemo 优化性能,减少不必要的计算将
isModified的计算逻辑包装在React.useMemo中是一个良好的性能优化。这样只有当value或defaultValue发生变化时,才会重新计算isModified,避免了在每次组件重新渲染时都进行不必要的计算。packages/utils/src/platform.ts (2)
88-88: 改进了代码格式在 catch 语句的闭合大括号前添加了空格,提高了代码可读性和一致性。
137-145: 添加了获取操作系统名称的实用函数新增的
getOperatingSystemName函数提供了一种简便的方式来获取当前操作系统的可读名称,而不是直接使用布尔标志。此函数返回 'Windows'、'Macintosh' 或 'Linux' 字符串,方便在需要显示操作系统名称的场景中使用。建议考虑将此函数与现有的
PlatformToString函数功能统一,或者添加文档注释说明两者的区别和适用场景。packages/comments/src/browser/comments-thread.ts (1)
254-257: 改进了小部件显示逻辑,避免潜在问题通过使用
setTimeout和移除widget.isShow检查,该修改确保了小部件能在下一个事件循环周期中可靠地显示出来,即使在某些边缘情况下也能正常工作。这个改动非常好,解决了可能存在的小部件显示同步问题。不过,建议考虑添加简短的代码注释,解释为什么需要使用
setTimeout,这将帮助其他开发者理解此更改的目的:if (editor.currentUri?.isEqual(this.uri)) { + // 使用 setTimeout 确保在下一个事件循环中执行,避免可能的渲染同步问题 setTimeout(() => { widget?.show(); }, 0); }packages/ai-native/src/browser/components/ChatToolRender.tsx (1)
70-70: 统一使用 Icon 组件替代直接使用样式类将直接使用样式类的 span 元素替换为标准的 Icon 组件,提高了代码一致性和可维护性。
这个改进很好,统一了图标的实现方式。考虑在整个代码库中寻找类似的模式并进行一致性更新,确保所有图标都使用 Icon 组件。
packages/ai-native/src/browser/widget/inline-diff/inline-diff-widget.module.less (2)
23-49: 新增内联差异管理器样式类新增的
.inlineDiffManager类提供了用于内联差异管理器的样式。样式定义合理,包括灵活的定位(使用absolute定位和translate变换居中)、边框圆角和溢出控制等。使用CSS变量确保了主题一致性。需要注意的是,z-index设置为999可能在某些情况下过高,建议考虑使用已定义的堆叠级别变量(如第18行使用的
--stacking-level-overlay-top)以保持一致性。- z-index: 999; + z-index: var(--stacking-level-overlay-top);
50-54: 禁用状态的样式类
.disabled类适当定义了禁用状态的样式。注意第51行被注释掉的样式,如果不再需要,建议删除以保持代码整洁。- // color: var(--kt-button-disableForeground) !important;packages/components/src/popover/index.tsx (1)
115-115: 验证delay值的转换逻辑第115行的逻辑
mouseEnterDelay={delay ? delay / 1000 : undefined}将毫秒转换为秒,这是正确的,因为底层的rc-tooltip组件期望延迟时间以秒为单位。然而,现在既然有了默认值,可以简化这个逻辑:
- mouseEnterDelay={delay ? delay / 1000 : undefined} + mouseEnterDelay={delay / 1000}packages/ai-native/__test__/browser/chat/chat-agent.service.test.ts (1)
71-71: 代码格式规范化调整在空函数体前添加空格,提高了代码的一致性和可读性。
packages/ai-native/src/common/model.ts (1)
25-51: 类型声明与注释不一致第51行注释提到"
as constassertion makes the object deeply readonly",但实际代码仅使用了as Record<string, ModelInfo>,没有应用as const断言。如果确实需要深度只读性,建议修改为:
-} as Record<string, ModelInfo>; // as const assertion makes the object deeply readonly +} as const as Record<string, ModelInfo>; // as const assertion makes the object deeply readonly如果不需要深度只读,建议删除误导的注释:
-} as Record<string, ModelInfo>; // as const assertion makes the object deeply readonly +} as Record<string, ModelInfo>;packages/ai-native/src/browser/mcp/mcp-server-proxy.service.ts (3)
56-58: 服务器信息获取方法
$getServers方法简单代理到sumiMCPServerProxyService.getServers(),功能明确。但缺少错误处理机制,可能在服务不可用时引发未捕获的异常。建议添加错误处理:
async $getServers() { - return this.sumiMCPServerProxyService.getServers(); + try { + return await this.sumiMCPServerProxyService.getServers(); + } catch (error) { + this.logger.error('获取服务器列表失败', error); + throw error; + } }
60-62: 启动服务器方法缺少错误处理
$startServer方法缺少错误处理机制,没有记录任何操作日志,也没有处理可能的异常情况。建议添加错误处理和日志记录:
async $startServer(serverName: string) { - await this.sumiMCPServerProxyService.startServer(serverName); + try { + this.logger.log(`开始启动服务器: ${serverName}`); + await this.sumiMCPServerProxyService.startServer(serverName); + this.logger.log(`服务器 ${serverName} 启动成功`); + } catch (error) { + this.logger.error(`启动服务器 ${serverName} 失败`, error); + throw error; + } }
64-66: 停止服务器方法缺少错误处理与启动服务器方法类似,
$stopServer方法也缺少错误处理和日志记录。建议添加错误处理和日志记录:
async $stopServer(serverName: string) { - await this.sumiMCPServerProxyService.stopServer(serverName); + try { + this.logger.log(`开始停止服务器: ${serverName}`); + await this.sumiMCPServerProxyService.stopServer(serverName); + this.logger.log(`服务器 ${serverName} 停止成功`); + } catch (error) { + this.logger.error(`停止服务器 ${serverName} 失败`, error); + throw error; + } }packages/ai-native/src/browser/chat/chat-proxy.service.ts (1)
125-126: 缺少 Anthropi c 的 baseURL 设置
如果未来需要自定义 Anthropic 模型的地址,建议与其他模型逻辑保持一致,或在此段代码中添加对应的 baseURL 获取。packages/ai-native/src/browser/chat/chat-manager.service.ts (1)
38-38: 新增 MAX_SESSION_COUNT 常量
预设最大会话数为 20,建议根据实际需求决定是否让用户可配,避免在应用规模扩大后出现限制过严的问题。packages/ai-native/src/browser/mcp/config/mcp-config.commands.ts (1)
13-29: 实现命令贡献类通过
@Domain装饰器将类标记为命令贡献,确保其被自动注册。实现了registerCommands方法来注册打开MCP配置的命令,并通过编辑器服务打开指定URI的配置文件。命令执行逻辑清晰,使用适当的参数确保配置打开时获得焦点且不是预览模式。
不过,建议添加一些错误处理,以防编辑器服务无法打开URI时提供用户反馈。
registerCommands(registry: CommandRegistry) { registry.registerCommand(OPEN_MCP_CONFIG_COMMAND, { execute: () => { const uri = new URI().withScheme(MCP_CONFIG_COMPONENTS_SCHEME_ID); - this.editorService.open(uri, { - preview: false, - focus: true, - }); + try { + this.editorService.open(uri, { + preview: false, + focus: true, + }); + } catch (error) { + console.error('无法打开MCP配置', error); + // 可以考虑添加用户通知 + } }, }); }packages/ai-native/src/browser/widget/inline-diff/inline-diff-manager.tsx (3)
1-7: 组件引入依赖合理,但请关注 Path 引入但未使用的问题组件引入了必要的 React hooks 和 OpenSumi 相关组件,但注意到第6行导入了
Path,但在代码中并未使用该类型。-import { AppConfig, IDisposable, URI, localize, path, useInjectable } from '@opensumi/ide-core-browser'; -import { IResource, WorkbenchEditorService } from '@opensumi/ide-editor'; -import { Path } from '@opensumi/ide-utils/lib/path'; +import { AppConfig, IDisposable, URI, localize, path, useInjectable } from '@opensumi/ide-core-browser'; +import { IResource, WorkbenchEditorService } from '@opensumi/ide-editor';
52-66: 注释应使用英文或国际化代码中包含中文注释 "不同编辑器是不同实例,所以不需要监听",建议使用英文注释或将这类说明添加到国际化文件中。
另外,Effect 钩子中正确地处理了资源的释放,这是良好的实践。
- // 不同编辑器是不同实例,所以不需要监听 + // Different editors are different instances, so no need to listen
104-158: UI布局合理,但存在注释掉的代码UI组件结构清晰,但存在大段被注释掉的代码(第106-113行)。如果这些代码不再需要,应当移除而非保留为注释。
return ( <div className={styles.inlineDiffManager} style={{ display: show ? 'flex' : 'none' }}> - {/* <div className={styles.left}> - <IconWithPopover - icon='codicon codicon-issues' - content={localize('aiNative.inlineDiff.reveal')} - id='inline-diff-manager-reveal' - onClick={handleReveal} - /> - </div> */} <div className={styles.mid}>packages/ai-native/src/browser/mcp/tools/handlers/EditFile.ts (1)
5-9: TODO 注释应该使用英文TODO注释使用了中文,建议使用英文以保持代码库的一致性和可读性。此外,该注释提供了有价值的信息,但格式不够规范。
-/** - * TODO: 代码块改动版本号,次数,流式工具调用? - * 基础文件编辑处理类 - * 用于处理代码改动的应用、保存等操作 - */ +/** + * TODO: Version number for code block changes, count, streaming tool calls? + * Base file edit handler class + * Used to handle code change application, saving and other operations + */packages/ai-native/src/common/prompts/context-prompt-provider.ts (2)
8-14: 接口方法签名更新合理从
MaybePromise<string>更改为string的返回类型使接口更清晰,简化了异步处理。但注意文档注释仍然不够完整,缺少userMessage参数的描述。/** * 提供上下文提示 * @param context 上下文 + * @param userMessage 用户消息 */ provideContextPrompt(context: SerializedContext, userMessage: string): string;
21-54: 上下文提示生成逻辑结构良好,但字符串模板可读性有待提高方法实现使用了大量的模板字符串嵌套,这降低了代码的可读性。考虑将一些模板逻辑抽取为单独的函数或常量,以提高可维护性。另外,当没有
currentModel时,返回的模板字符串中会有额外的空行,可能影响格式一致性。provideContextPrompt(context: SerializedContext, userMessage: string): string { const editor = this.workbenchEditorService.currentEditor; const currentModel = editor?.currentDocumentModel; + + const recentlyViewedFilesSection = ` <recently_viewed_files> +${context.recentlyViewFiles.map((file, idx) => ` ${idx + 1}: ${file}`).join('\n')} + </recently_viewed_files>`; + + const attachedFilesSection = ` <attached_files> + ${context.attachedFiles.map( + (file) => + ` + <file_contents> + \`\`\`${file.path} + ${file.content} + \`\`\` + </file_contents> + <linter_errors> + ${file.lineErrors.join('\n')} + </linter_errors> + `, + )} + </attached_files>`; + + const currentOpenedFileSection = currentModel ? `<current_opened_file> + \`\`\`${currentModel.languageId} ${currentModel.uri.toString()} +${currentModel.getText()} + \`\`\` + </current_opened_file>` : ''; + return ` <additional_data> Below are some potentially helpful/relevant pieces of information for figuring out to respond +${recentlyViewedFilesSection} +${attachedFilesSection} +${currentOpenedFileSection} - <recently_viewed_files> -${context.recentlyViewFiles.map((file, idx) => ` ${idx + 1}: ${file}`).join('\n')} - </recently_viewed_files> - <attached_files> - ${context.attachedFiles.map( - (file) => - ` - <file_contents> - \`\`\`${file.path} - ${file.content} - \`\`\` - </file_contents> - <linter_errors> - ${file.lineErrors.join('\n')} - </linter_errors> - `, - )} - </attached_files> -${currentModel ? `<current_opened_file> - \`\`\`${currentModel.languageId} ${currentModel.uri.toString()} -${currentModel.getText()} - \`\`\` - </current_opened_file>` : ''} </additional_data> <user_query> ${userMessage} </user_query>`; }packages/ai-native/src/common/mcp-server-manager.ts (2)
3-11: 接口设计合理,但返回类型缺少详细说明新增的
IMCPServer接口定义了服务器管理所需的方法,结构清晰。但部分方法的返回类型使用了ReturnType<Client['methodName']>的形式,虽然简洁,但可能降低代码可读性和自文档性。考虑使用更具体的类型定义,或添加更详细的文档注释来解释这些方法的返回值结构。
建议为接口增加更详细的文档注释,特别是对返回类型较复杂的方法:
+/** + * MCP服务器接口,定义与MCP服务器交互的方法 + */ export interface IMCPServer { + /** + * 检查服务器是否已启动 + * @returns 服务器启动状态 + */ isStarted(): boolean; + /** + * 启动服务器 + * @returns 启动操作的Promise + */ start(): Promise<void>; + /** + * 获取服务器名称 + * @returns 服务器名称 + */ getServerName(): string; + /** + * 调用工具 + * @param toolName 工具名称 + * @param toolCallId 工具调用ID + * @param arg_string 参数字符串 + * @returns 工具调用结果 + */ callTool(toolName: string, toolCallId: string, arg_string: string): ReturnType<Client['callTool']>;
23-25: 参数命名不一致
initBuiltinServer方法新增了enabled参数,这与MCPServerDescription接口中新增的enabled属性相对应,这是良好的设计。但是,builtinMCPServer参数类型仅标注为any,这降低了类型安全性。- initBuiltinServer(builtinMCPServer: any, enabled: boolean): void; + initBuiltinServer(builtinMCPServer: IMCPServer, enabled: boolean): void;packages/ai-native/src/common/types.ts (1)
52-67: 注意处理可能的状态一致性问题
CodeBlockData接口设计合理,包含了代码块所需的所有属性。但需注意确保status与其他字段的状态一致性,尤其是当状态为failed或cancelled时,相关结果字段可能为空。建议添加注释说明各个状态下哪些字段是必需的,哪些可能为空,以帮助使用者正确处理不同状态下的数据。
packages/ai-native/src/browser/mcp/config/components/mcp-server-form.tsx (2)
94-94: 表单提交处理重复在这里调用
e.preventDefault()是多余的,因为handleSubmit函数中已经包含了这个调用。- <form className={styles.form} onSubmit={(e) => e.preventDefault()}> + <form className={styles.form} onSubmit={handleSubmit}>
116-123: 缺少参数格式验证参数文本框缺少格式验证。用户可能输入格式不正确的参数,导致服务器启动失败。
建议添加输入验证或提示,确保用户按照正确的格式输入参数。
packages/ai-native/src/browser/mcp/config/components/mcp-config.view.tsx (4)
45-95: 服务器控制逻辑过于复杂
handleServerControl函数包含了太多逻辑,尤其是处理内置服务器的特殊情况部分较为复杂。建议将内置服务器和普通服务器的处理逻辑分离为独立的辅助函数,以提高代码可读性和可维护性:
+ const updateBuiltinServerPreferences = (servers: MCPServerDescription[], start: boolean) => { + const builtinServerExists = servers.some((server) => server.name === BUILTIN_MCP_SERVER_NAME); + if (!builtinServerExists && !start) { + return [ + ...servers, + { + name: BUILTIN_MCP_SERVER_NAME, + enabled: false, + command: '', + }, + ]; + } else { + return servers.map((server) => { + if (server.name === BUILTIN_MCP_SERVER_NAME) { + return { ...server, enabled: start }; + } + return server; + }); + } + }; + + const updateNormalServerPreferences = (servers: MCPServerDescription[], serverName: string, start: boolean) => { + return servers.map((server) => { + if (server.name === serverName) { + return { ...server, enabled: start }; + } + return server; + }); + };
57-79: 注释使用中文,不符合国际化要求代码中的注释使用了中文,这可能对非中文开发者造成理解障碍。
建议将中文注释翻译为英文,以保持代码的国际化标准。
- // 处理内置服务器的特殊情况 + // Handle special case for built-in server- // 如果是停止内置服务器且之前没有配置,添加一个新的配置项 - // 内置服务器不需要 command,因为它是直接集成在 IDE 中的 + // If stopping the built-in server and no configuration exists, add a new config item + // Built-in server doesn't need a command as it's directly integrated into the IDE- // 如果已经存在配置,更新 enabled 状态 + // If configuration already exists, update the enabled status- // 处理其他外部服务器 + // Handle other external servers
112-117: 删除服务器缺少确认机制删除服务器的操作没有确认步骤,可能导致用户误删数据。
建议添加删除确认对话框,防止意外操作。可以利用 Modal 组件或者提示组件实现确认功能。
163-165: 服务器删除按钮需增加安全确认与前面的建议相关,删除按钮直接触发删除操作,没有确认步骤。
修改删除按钮的点击处理函数,添加确认步骤:
- <button className={styles.iconButton} title='Delete' onClick={() => handleDeleteServer(server.name)}> + <button className={styles.iconButton} title='Delete' onClick={() => { + if (confirm(`Are you sure you want to delete server "${server.name}"?`)) { + handleDeleteServer(server.name); + } + }}>packages/ai-native/src/browser/mcp/tools/components/ExpandableFileList.tsx (3)
25-33: 组件封装建议:
当前FileSearchToolComponent仅简单传递 props 过去,可根据需求在此处增加逻辑或 useEffect 处理,如对参数进行校验等。
81-90: 目录与文件点击逻辑可扩充异常处理。
若文件打开或目录展开指令执行失败,目前缺少异常捕获,建议在执行editorService.open或commandService.executeCommand时做容错或提示处理。
108-133: 交互设计与可访问性建议:
- 当前使用 span 标签展示箭头旋转,可考虑为有交互的区域添加
aria-expanded等属性,增强可访问性。- 展开/收起指示符可使用更易于理解的图标组件。
packages/ai-native/src/browser/mcp/mcp-server.feature.registry.ts (1)
95-107: 上报工具调用逻辑可扩充。
reportToolCall中包含了对 tool 的二次查找并抛错,若同名 tool 已被移除建议引入完整日志记录辅助排查。packages/ai-native/src/browser/chat/chat.view.tsx (3)
165-165: 考虑使用可选链
可用containerRef?.current代替containerRef && containerRef.current,让逻辑更简洁。- if (containerRef && containerRef.current && autoScroll.current) { + if (containerRef?.current && autoScroll.current) {🧰 Tools
🪛 Biome (1.9.4)
[error] 165-165: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
517-517: 请求创建接口
aiChatService.createRequest(...)可进一步考虑异常处理,如 request 返回undefined或抛错时是否提示用户。
528-539: 补充超时设置
这里将工具调用超时时间设置较长,有助于避免复杂操作时提早中断;若需更精细化的操作可在不同命令中进一步区分。packages/ai-native/src/browser/mcp/tools/listDir.ts (1)
54-62: 产生 fileUris 用于前端渲染目录结构。
建议使用更安全的路径拼接方式(如 path 库或内置工具),以避免潜在的路径分隔符兼容问题。- const filePath = `${this.listDirHandler.getWorkspaceDir()}/${result.directoryRelativeWorkspacePath}/${file.name}`; + // 示例:使用内部方法或库进行拼接 + const base = this.listDirHandler.getWorkspaceDir(); + const folder = result.directoryRelativeWorkspacePath; + const filePath = joinPath(base, folder, file.name);packages/ai-native/src/browser/ai-core.contribution.ts (1)
361-385: 实时切换 LLMModelSelection 并动态更新 AI 模型选项。
此处使用 reduce + 展开运算构造对象,时间复杂度可能较高。若模型列表较大,可考虑使用普通赋值方式:- modelIds.reduce((obj, item) => ({ ...obj, [item]: item }), {}) + modelIds.reduce((obj, item) => { + obj[item] = item; + return obj; + }, {})🧰 Tools
🪛 Biome (1.9.4)
[error] 382-382: Avoid the use of spread (
...) syntax on accumulators.Spread syntax should be avoided on accumulators (like those in
.reduce) because it causes a time complexity ofO(n^2).
Consider methods such as .splice or .push instead.(lint/performance/noAccumulatingSpread)
packages/ai-native/src/node/mcp/sumi-mcp-server.ts (1)
133-181: 实现新的getServers方法以获取各 MCP Server 的状态与类型。
- 如果某个 server 在
getTools()调用时出现异常,可能会导致整体执行被中断或延后。建议为单个服务器调用添加异常捕获,避免影响其他服务器信息的获取。- 目前做了内置服务器置顶的处理策略,能快速向前端展示内置 server,但若有后续排序需求,可在此函数中预留扩展。
packages/ai-native/src/node/base-language-model.ts (5)
17-17: 新增静态属性ModelOptions的声明。
建议在注释中说明其用途或默认值,以便后续维护时更易理解。
48-53: 根据是否提供clientId决定是否加载工具。
若clientId为空时完全跳过工具调用,建议在日志或调试信息中注明,方便后续排查无工具可用的原因。
114-114: 在请求中通过modelId获取对应modelInfo。
若找不到对应配置可考虑提供回退方案或日志提示,避免用户传入无效modelId时无从排查。
130-133: 新增本地变量用于处理流式文本的缓存与分段。
实现思路清晰,建议附加简要注释说明各变量作用,便于长期维护。
136-165: 按行切分并处理trimTexts逻辑,动态缓冲与分段发送文本。
实现对流式文本的边界裁剪,整体思路可行。若处理非常大的文本,需留意缓冲区内存占用或分割效率。packages/ai-native/src/browser/mcp/tools/createNewFileWithText.ts (1)
86-86: 注意直接返回错误信息可能存在敏感信息风险。
error.message可能将底层敏感数据暴露给调用者,建议酌情考虑对错误提示做脱敏或包装处理,以防止潜在信息泄露。packages/ai-native/src/browser/chat/chat-agent.service.ts (2)
43-47: 新增存储与控制上下文状态的字段。
initialUserMessageMap、shouldUpdateContext、contextVersion有助于管理初始化消息与上下文更新。注意后续若并发场景较多,需要留意线程安全及多会话冲突。
165-175: 抽取上下文再进行消息拼接并上报统计。
provideContextMessage将上下文序列化后,构建完整消息并向aiReporter发送。此处整合上下文与原消息思路清晰,但要留意过大的上下文可能导致无用的开销。packages/i18n/src/common/en-US.lang.ts (1)
1587-1591: “允许/拒绝”与 key 命名微小差异。
ai.native.mcp.terminal.deny的 value 是'Reject'。与 key 中deny含义一致,但可考虑统一措辞:如使用'Deny'显示文案,让键值更直观一一对应;也可保留现状,仅属轻微文字差异。packages/ai-native/src/browser/mcp/base-apply.service.ts (4)
75-83: 建议关注会话切换时的并发问题
当会话切换触发cancelAllApply()时,如果此时仍有异步操作(如文件保存、渲染等)未完成,可能导致竞争条件或状态不一致。建议在切换会话前后增加更明确的状态同步或锁机制,防止多次并发修改同一资源。
149-168: 处理TODO:刷新后恢复应用的逻辑
在onEditorGroupOpen内部有注释 “TODO: 刷新后重新应用...需要改造成批量apply形式”。若用户在刷新/重开编辑器后希望自动恢复所有挂起的代码块,需要进一步完善这部分逻辑,确保在加载期就一次性批量恢复代码块。
331-430: 改进renderApplyResult的错误检测
本方法会匹配hunkInfo.match(/@@ -(\d+),(\d+) \+(\d+),(\d+) @@/)!,若正则匹配失败时,代码会抛出不可控异常。建议在调用match后先检查返回值是否有效来防止潜在崩溃:- const [, , , start, end] = hunkInfo.match(/@@ -(\d+),(\d+) \+(\d+),(\d+) @@/)!; + const matchResult = hunkInfo.match(/@@ -(\d+),(\d+) \+(\d+),(\d+) @@/); + if (!matchResult) { + // 进行容错处理,如直接 return 或记录日志 + ... + } + const [, , , start, end] = matchResult;
499-555: 为listenPartialEdit增加异常处理
listenPartialEdit方法里只要满足event.totalPartialEditCount === event.resolvedPartialEditCount就会根据event.acceptPartialEditCount来更新状态。目前缺乏针对异常情况的保护逻辑,例如编辑器引用丢失或 AIReporter 发送错误时的处理,建议在回调中加上错误捕获,减少未捕获异常导致的影响。packages/ai-native/src/browser/widget/inline-stream-diff/inline-stream-diff.handler.tsx (3)
307-309: 在renderDiffEdits中获取原始模型
通过this.getOriginalModel()获取到的originalModel决定后续的 EOL 检测和编辑范围。如果外部在某些时刻切换了实际操作的 model,需要确认此处引用是否仍旧有效,避免因 model 不一致导致渲染或 diff 失效。
416-429:recompute函数对参数的处理
recompute(computerMode, content)在传入content后会立即更新到virtualModel,再调用processDiffComputation。若外部调用高频变更此语句时,流式渲染时序可能出现覆盖。建议在高频场景下增加缓冲机制,或在调用前检测是否有未完成的差异计算。
531-610: 子类化实现增强反向对比支持
ReverseInlineStreamDiffHandler与InlineStreamDiffHandler分别覆盖了getOriginalModel和差异计算逻辑,充分利用了抽象基类的设计。对于TODO: reverse 模式暂不支持 range相关限制,建议尽快完善或在文档明确说明,避免用户误用。
🛑 Comments failed to post (12)
packages/core-browser/src/contextkey/ai-native.ts (1)
7-7: 💡 Verification agent
🧩 Analysis chain
上下文键名称重构,从 MultiLineEdits 改为 CodeEdits
将
MultiLineEditsIsVisible更改为CodeEditsIsVisible表明范围扩大,从多行编辑扩展到所有代码编辑。这个修改是合理的,但需要确保所有使用旧上下文键的地方都已更新。
🏁 Script executed:
#!/bin/bash # 检查是否仍有地方使用旧的 MultiLineEditsIsVisible 上下文键 echo "检查代码库中是否仍有使用 MultiLineEditsIsVisible 的地方:" rg -i "MultiLineEditsIsVisible" --type tsLength of output: 1433
请更新所有旧上下文键引用
在
packages/core-browser/src/contextkey/ai-native.ts中已将上下文键从MultiLineEditsIsVisible更改为CodeEditsIsVisible,以扩展其适用范围(从仅多行编辑到所有代码编辑)。但在packages/ai-native/src/browser/contrib/intelligent-completions/intelligent-completions.controller.ts中,仍存在若干对旧命名MultiLineEditsIsVisible的引用(如变量multiLineEditsIsVisibleObs等)。建议将这些旧引用同步更新为新的命名,以保证全库命名的一致性和逻辑正确性。packages/ai-native/src/browser/contrib/inline-completions/inline-completions.controller.ts (1)
173-173: 💡 Verification agent
🧩 Analysis chain
上下文键名称更新为更准确的描述
将
multiLineEditsIsVisible更改为codeEditsIsVisible使上下文键的名称更加准确,更好地反映了其实际用途。这种变更是统一命名约定的一部分,提高了代码的可理解性。
🏁 Script executed:
#!/bin/bash # 查找codebase中是否还有其他地方使用了旧的上下文键名称 echo "查找 multiLineEditsIsVisible 的引用..." rg "multiLineEditsIsVisible" # 检查新的上下文键在哪些文件中定义和使用 echo "查找 codeEditsIsVisible 的引用..." rg "codeEditsIsVisible"Length of output: 3156
请注意保持上下文键命名的一致性
文件
packages/ai-native/src/browser/contrib/inline-completions/inline-completions.controller.ts中第 173 行的修改已正确使用新的上下文键:const isVisible = this.aiNativeContextKey.codeEditsIsVisible.get();这符合更新命名约定、提升代码可理解性的要求。
然而,通过搜索发现文件
packages/ai-native/src/browser/contrib/intelligent-completions/intelligent-completions.controller.ts中仍存在对旧上下文键multiLineEditsIsVisible(如变量multiLineEditsIsVisibleObs)的引用。为保持整体的一致性,建议同步更新这些引用,除非有意为之并在代码中作了说明。packages/ai-native/src/browser/index.ts (1)
96-97: 💡 Verification agent
🧩 Analysis chain
注册 MCP 配置贡献组件
正确地注册了 MCP 配置相关的贡献组件。请确保这些组件在项目中有相关测试覆盖。
🏁 Script executed:
#!/bin/bash # 检查是否有相应的测试文件 echo "查找 MCP 配置相关的测试文件:" fd "mcp-config.*test" --type fileLength of output: 80
注意: 需要补充测试覆盖
组件注册部分(
MCPConfigContribution和MCPConfigCommandContribution)看起来已正确完成,但目前在代码库中未发现与这些组件相关的测试用例。请补充相应的测试代码以确保组件行为得到验证。
- 在项目测试目录中添加针对 MCP 配置组件的单元或集成测试。
packages/ai-native/src/browser/contrib/intelligent-completions/view/code-edits-previewer.ts (2)
64-64: 🛠️ Refactor suggestion
新增上下文键状态重置 - accept方法
添加了代码确保在accept方法执行后将
codeEditsIsVisible重置为false。这是一个良好的改进,可以防止上下文键状态不一致的问题。
69-69: 🛠️ Refactor suggestion
新增上下文键状态重置 - discard方法
与accept方法类似,现在在discard方法执行后也会将
codeEditsIsVisible重置为false。这有助于确保上下文键状态的正确性。packages/ai-native/src/node/openai-compatible/openai-compatible-language-model.ts (1)
27-29: 🛠️ Refactor suggestion
未实现的模型信息获取方法
getModelInfo方法目前只返回undefined,这似乎是未完成的实现。考虑到其他模型类(如AnthropicModel)都有相应的实现,这里应该也需要实现模型信息的获取。建议参考其他模型实现,返回相应的模型信息:
- protected getModelInfo() { - return undefined; + protected getModelInfo(modelId: string): ModelInfo | undefined { + // 从相应的模型集合中获取信息,如果有的话 + // 例如:return compatibleModels[modelId]; + return undefined; }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.protected getModelInfo(modelId: string): ModelInfo | undefined { // 从相应的模型集合中获取信息,如果有的话 // 例如:return compatibleModels[modelId]; return undefined; }packages/ai-native/src/browser/widget/inline-diff/inline-diff-manager.tsx (2)
78-88: 🛠️ Refactor suggestion
存在潜在的数组越界问题
handleSiblingFile函数中,计算下一个或上一个文件索引时缺少边界检查。虽然在UI中通过disabled属性限制了按钮点击,但代码逻辑中仍应增加边界检查以提高健壮性。另外,回调的依赖项需要添加
editorService和appConfig。const handleSiblingFile = useCallback( (direction: 'up' | 'down') => { const index = filePaths.indexOf(currentFilePath!); if (index === -1) { return; } + const nextIndex = index + (direction === 'up' ? -1 : 1); + if (nextIndex < 0 || nextIndex >= filePaths.length) { + return; + } - const uri = URI.file(path.join(appConfig.workspaceDir, filePaths[index + (direction === 'up' ? -1 : 1)])); + const uri = URI.file(path.join(appConfig.workspaceDir, filePaths[nextIndex])); editorService.open(uri); }, - [currentFilePath, filePaths], + [currentFilePath, filePaths, editorService, appConfig], );📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.const handleSiblingFile = useCallback( (direction: 'up' | 'down') => { const index = filePaths.indexOf(currentFilePath!); if (index === -1) { return; } const nextIndex = index + (direction === 'up' ? -1 : 1); if (nextIndex < 0 || nextIndex >= filePaths.length) { return; } const uri = URI.file(path.join(appConfig.workspaceDir, filePaths[nextIndex])); editorService.open(uri); }, [currentFilePath, filePaths, editorService, appConfig], );
39-50: 🛠️ Refactor suggestion
Effect 依赖项需要补充
useEffect钩子缺少依赖项,目前只有空数组[],但函数体内使用了props.resource和appConfig,这可能导致组件更新时无法正确反应这些依赖的变化。- }, []); + }, [props.resource, appConfig]);packages/ai-native/src/browser/mcp/tools/handlers/EditFile.ts (1)
15-18: 🛠️ Refactor suggestion
方法参数结构优化得当,但缺少错误处理
方法参数使用对象结构提高了代码可读性和扩展性,但缺少异常处理机制。如果
registerCodeBlock或apply方法失败,当前实现没有处理这些异常的逻辑。async handler(params: { targetFile: string; codeEdit: string; instructions?: string }, toolCallId: string) { const { targetFile, codeEdit } = params; - const block = await this.applyService.registerCodeBlock(targetFile, codeEdit, toolCallId); - const blockData = await this.applyService.apply(block); - return blockData; + try { + const block = await this.applyService.registerCodeBlock(targetFile, codeEdit, toolCallId); + const blockData = await this.applyService.apply(block); + return blockData; + } catch (error) { + console.error('Failed to handle file edit:', error); + throw error; + } }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.async handler(params: { targetFile: string; codeEdit: string; instructions?: string }, toolCallId: string) { const { targetFile, codeEdit } = params; try { const block = await this.applyService.registerCodeBlock(targetFile, codeEdit, toolCallId); const blockData = await this.applyService.apply(block); return blockData; } catch (error) { console.error('Failed to handle file edit:', error); throw error; } }packages/ai-native/src/browser/mcp/config/components/mcp-server-form.tsx (1)
22-30:
⚠️ Potential issue表单初始状态与接口定义不匹配
初始状态中包含了
type: 'stdio'字段,但该字段在MCPServerFormData接口中未定义。应该更新接口定义以包含该字段,或者从初始状态中移除该字段:
export interface MCPServerFormData { name: string; command: string; args: string[]; env?: Record<string, string>; + type?: string; }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.export interface MCPServerFormData { name: string; command: string; args: string[]; env?: Record<string, string>; type?: string; } export const MCPServerForm: React.FC<Props> = ({ visible, initialData, onSave, onCancel }) => { const [formData, setFormData] = React.useState<MCPServerFormData>(() => ({ name: '', command: '', args: [], env: {}, type: 'stdio', // TODO: 支持 SSE ...initialData, })); // ... rest of the component code };packages/i18n/src/common/zh-CN.lang.ts (1)
1264-1274:
⚠️ Potential issue本地化新增与重复key冲突
新增一系列 inlineDiff 相关键值,但aiNative.chat.session.max同一键在行 1264 与行 1274 重复定义,可能造成冲突且后者会覆盖前者。建议去重:- 'aiNative.chat.session.max': '最多只能创建 {0} 个聊天'📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.'aiNative.inlineDiff.acceptAll': '接受全部', 'aiNative.inlineDiff.rejectAll': '拒绝全部', 'aiNative.inlineDiff.reveal': '在聊天中展示', 'aiNative.inlineDiff.up': '上一处变更', 'aiNative.inlineDiff.down': '下一处变更', 'aiNative.inlineDiff.right': '下一处文件', 'aiNative.inlineDiff.left': '上一处文件', 'aiNative.inlineDiff.noMoreChangesUp': '顶部没有更多变更了', 'aiNative.inlineDiff.noMoreChangesDown': '底部没有更多变更了', 'preference.ai.native.inlineChat.title': 'Inline Chat',packages/ai-native/src/browser/mcp/base-apply.service.ts (1)
282-329: 🛠️ Refactor suggestion
检查
apply方法可能的并发风险
apply方法使用this.duringApply = true来表明正在应用中的状态,但本类方法可能会同时处理多个代码块应用。如果多个代码块并行触发apply,this.duringApply没有区分度,可能导致状态错乱。建议改成单次调用局部控制,或使用区分 codeBlockId 的并发管理机制。
Types
Background or solution
Changelog
Summary by CodeRabbit