From 9e88d6ce963720883f1ee355dbbfe7646d5b31df Mon Sep 17 00:00:00 2001 From: JinmingYang <2214962083@qq.com> Date: Tue, 13 Aug 2024 23:51:04 +0800 Subject: [PATCH] feat: add expert-code-enhancer feature --- .vscode/launch.json | 4 +- package.json | 107 +++++++++- package.nls.en.json | 15 +- package.nls.json | 15 +- package.nls.zh-cn.json | 15 +- pnpm-lock.yaml | 64 +++--- src/extension/cleanup.ts | 4 +- .../build-generate-prompt.ts | 187 ++++++++++++++++++ .../commands/expert-code-enhancer/index.ts | 107 ++++++++++ src/extension/commands/index.ts | 7 + src/extension/config.ts | 4 + src/extension/file-utils/create-tmp-file.ts | 8 + src/extension/i18n.ts | 6 +- 13 files changed, 501 insertions(+), 42 deletions(-) create mode 100644 src/extension/commands/expert-code-enhancer/build-generate-prompt.ts create mode 100644 src/extension/commands/expert-code-enhancer/index.ts diff --git a/.vscode/launch.json b/.vscode/launch.json index 7b36a75..14db135 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -11,8 +11,8 @@ "request": "launch", "runtimeExecutable": "${execPath}", "args": [ - "--extensionDevelopmentPath=${workspaceFolder}", - "--disable-extensions" + "--extensionDevelopmentPath=${workspaceFolder}" + // "--disable-extensions" ], "outFiles": ["${workspaceFolder}/dist/**/*.js"], "preLaunchTask": "npm: watch", diff --git a/package.json b/package.json index 22cf4fe..298c6dd 100644 --- a/package.json +++ b/package.json @@ -103,6 +103,11 @@ "title": "%command.codeViewerHelper%", "icon": "$(open-editors-view-icon)" }, + { + "command": "aide.expertCodeEnhancer", + "title": "%command.expertCodeEnhancer%", + "icon": "$(extensions-configure-recommended)" + }, { "command": "aide.renameVariable", "title": "%command.renameVariable%" @@ -170,6 +175,10 @@ { "command": "aide.codeConvert", "group": "0_aide@121" + }, + { + "command": "aide.expertCodeEnhancer", + "group": "0_aide@122" } ], "editor/title": [ @@ -180,6 +189,10 @@ { "command": "aide.codeConvert", "group": "navigation@2" + }, + { + "command": "aide.expertCodeEnhancer", + "group": "navigation@3" } ] }, @@ -218,6 +231,96 @@ "scope": "resource", "markdownDescription": "%config.codeViewerHelperPrompt.description%" }, + "aide.expertCodeEnhancerPromptList": { + "type": "array", + "default": [ + { + "match": "**/*", + "title": "%config.expertCodeEnhancerPromptList.solid%", + "prompt": "Please refactor the following code to better adhere to SOLID principles. Focus on Single Responsibility, Open-Closed, Liskov Substitution, Interface Segregation, and Dependency Inversion where applicable. Explain your changes briefly in comments.", + "sort": 150, + "autoContext": false + }, + { + "match": "**/*", + "title": "%config.expertCodeEnhancerPromptList.dry%", + "prompt": "Refactor the following code to eliminate redundancy and improve maintainability by applying the DRY (Don't Repeat Yourself) principle. Identify repeated code patterns and abstract them into reusable functions or classes as appropriate.", + "sort": 160, + "autoContext": false + }, + { + "match": "**/*", + "title": "%config.expertCodeEnhancerPromptList.designPatterns%", + "prompt": "Analyze the following code and suggest refactoring using appropriate design patterns. Consider creational, structural, and behavioral patterns that could improve the code's flexibility, maintainability, and scalability.", + "sort": 170, + "autoContext": false + }, + { + "match": [ + "**/*.vue", + "**/*.tsx", + "**/*.jsx" + ], + "title": "%config.expertCodeEnhancerPromptList.splitComponents%", + "prompt": "Analyze the following code and split it into smaller, more manageable components. Focus on identifying reusable parts, separating concerns, and improving overall component structure. Provide the refactored code with new component files clearly separated.", + "sort": 140, + "autoContext": true + }, + { + "match": "**/*", + "title": "%config.expertCodeEnhancerPromptList.cleanliness%", + "prompt": "Refactor the following code to improve its cleanliness and readability. Focus on consistent naming conventions, appropriate comments, logical code organization, and reducing complexity. Ensure the code follows best practices for the given language.", + "sort": 180, + "autoContext": false + }, + { + "match": "**/*", + "title": "%config.expertCodeEnhancerPromptList.performance%", + "prompt": "Review the following code and optimize it for better performance. Focus on algorithmic efficiency, reducing unnecessary computations, and improving data structure usage. If applicable, consider asynchronous operations and memory management.", + "sort": 190, + "autoContext": true + }, + { + "match": [ + "**/*.sql", + "**/*Repository.{java,kt,scala,cs,py,js,ts}", + "**/*Dao.{java,kt,scala,cs,py,js,ts}", + "**/*Mapper.{java,kt,scala,cs,py,js,ts}", + "**/*Query.{java,kt,scala,cs,py,js,ts}", + "**/*.orm.{py,rb}", + "**/*.entity.{ts,js}", + "**/*Service.{java,kt,scala,cs,py,js,ts}" + ], + "title": "%config.expertCodeEnhancerPromptList.databaseQueries%", + "prompt": "Analyze and optimize the database queries in the following code. Focus on improving query performance, reducing unnecessary joins, optimizing indexing suggestions, and ensuring efficient data retrieval patterns.", + "sort": 130, + "autoContext": true + }, + { + "match": "**/*", + "title": "%config.expertCodeEnhancerPromptList.security%", + "prompt": "Review the following code and enhance its security measures. Focus on identifying and mitigating common vulnerabilities such as SQL injection, XSS, CSRF, and insecure data handling. Provide safer alternatives and explain the security improvements.", + "sort": 200, + "autoContext": true + }, + { + "match": [ + "**/*.{java,kt,scala,cs,go,cpp,c,rs,py}", + "**/*Async*.{java,kt,scala,cs,go,cpp,c,rs,py}", + "**/*Parallel*.{java,kt,scala,cs,go,cpp,c,rs,py}", + "**/*Concurrent*.{java,kt,scala,cs,go,cpp,c,rs,py}", + "**/*Thread*.{java,kt,scala,cs,go,cpp,c,rs,py}", + "**/*Worker*.{java,kt,scala,cs,go,cpp,c,rs,py}" + ], + "title": "%config.expertCodeEnhancerPromptList.concurrency%", + "prompt": "Refactor the following code to improve its concurrency and multithreading capabilities. Focus on efficient resource sharing, preventing race conditions, and enhancing overall parallel processing performance.", + "sort": 180, + "autoContext": true + } + ], + "scope": "resource", + "markdownDescription": "%config.expertCodeEnhancerPromptList.description%" + }, "aide.convertLanguagePairs": { "type": "object", "default": {}, @@ -347,8 +450,8 @@ "ignore": "^5.3.2", "inquirer": "^9.3.4", "knip": "^5.27.2", - "langchain": "^0.2.15", - "lint-staged": "^15.2.8", + "langchain": "^0.2.16", + "lint-staged": "^15.2.9", "minimatch": "^9.0.5", "node-fetch": "^3.3.2", "p-limit": "^6.1.0", diff --git a/package.nls.en.json b/package.nls.en.json index b5863c9..1a4cee0 100644 --- a/package.nls.en.json +++ b/package.nls.en.json @@ -3,6 +3,7 @@ "command.askAI": "✨ Aide: Ask AI", "command.codeConvert": "✨ Aide: Code Convert", "command.codeViewerHelper": "✨ Aide: Code Viewer Helper", + "command.expertCodeEnhancer": "✨ Aide: Expert Code Enhancer", "command.renameVariable": "✨ Aide: Rename Variable", "command.smartPaste": "✨ Aide: Smart Paste", "command.batchProcessor": "✨ Aide: AI Batch Processor", @@ -16,7 +17,17 @@ "config.openaiBaseUrl.description": "OpenAI Base URL, [click to view online documentation](https://aide.nicepkg.cn/guide/configuration/openai-base-url)", "config.apiConcurrency.description": "API request concurrency, [click to view online documentation](https://aide.nicepkg.cn/guide/configuration/api-concurrency)", "config.useSystemProxy.description": "Use global proxy (`HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`), you need to restart `VSCode` to take effect after changing this setting, [click to view online documentation](https://aide.nicepkg.cn/guide/configuration/use-system-proxy)", - "config.codeViewerHelperPrompt.description": "Code viewer helper prompt template, [click to view online documentation](https://aide.nicepkg.cn/guide/configuration/code-viewer-helper-prompt)", + "config.codeViewerHelperPrompt.description": "Code viewer helper AI prompt template, [click to view online documentation](https://aide.nicepkg.cn/guide/configuration/code-viewer-helper-prompt)", + "config.expertCodeEnhancerPromptList.description": "Expert code enhancer AI prompt template list, [click to view online documentation](https://aide.nicepkg.cn/guide/configuration/expert-code-enhancer-prompt-list)", + "config.expertCodeEnhancerPromptList.solid": "Optimize using SOLID principles", + "config.expertCodeEnhancerPromptList.dry": "Apply DRY principle", + "config.expertCodeEnhancerPromptList.designPatterns": "Apply appropriate design patterns", + "config.expertCodeEnhancerPromptList.splitComponents": "Split into smaller components", + "config.expertCodeEnhancerPromptList.cleanliness": "Improve code cleanliness", + "config.expertCodeEnhancerPromptList.performance": "Optimize for performance", + "config.expertCodeEnhancerPromptList.databaseQueries": "Optimize database queries", + "config.expertCodeEnhancerPromptList.security": "Enhance security measures", + "config.expertCodeEnhancerPromptList.concurrency": "Optimize concurrency and multithreading", "config.convertLanguagePairs.description": "Default convert language pairs, [click to view online documentation](https://aide.nicepkg.cn/guide/configuration/convert-language-pairs)", "config.autoRememberConvertLanguagePairs.description": "Automatically remember convert language pairs, [click to view online documentation](https://aide.nicepkg.cn/guide/configuration/auto-remember-convert-language-pairs)", "config.readClipboardImage.description": "Allow reading clipboard images as AI context in certain scenarios, [click to view online documentation](https://aide.nicepkg.cn/guide/configuration/read-clipboard-image)", @@ -74,5 +85,7 @@ "input.selectAiSuggestionsVariableName.prompt": "Select AI suggestions variable name", "input.batchProcessor.prompt": "Let AI batch process your selected {0} files, what do you want AI to do?", "input.batchProcessor.placeholder": "eg: help me migrate from python2 to python3", + "input.expertCodeEnhancer.selectPrompt.title": "Select code optimize method", + "input.expertCodeEnhancer.customPrompt.placeholder": "Custom optimize prompt", "file.content": "File: {0}\n```{1}\n{2}\n```\n\n" } diff --git a/package.nls.json b/package.nls.json index b5863c9..1a4cee0 100644 --- a/package.nls.json +++ b/package.nls.json @@ -3,6 +3,7 @@ "command.askAI": "✨ Aide: Ask AI", "command.codeConvert": "✨ Aide: Code Convert", "command.codeViewerHelper": "✨ Aide: Code Viewer Helper", + "command.expertCodeEnhancer": "✨ Aide: Expert Code Enhancer", "command.renameVariable": "✨ Aide: Rename Variable", "command.smartPaste": "✨ Aide: Smart Paste", "command.batchProcessor": "✨ Aide: AI Batch Processor", @@ -16,7 +17,17 @@ "config.openaiBaseUrl.description": "OpenAI Base URL, [click to view online documentation](https://aide.nicepkg.cn/guide/configuration/openai-base-url)", "config.apiConcurrency.description": "API request concurrency, [click to view online documentation](https://aide.nicepkg.cn/guide/configuration/api-concurrency)", "config.useSystemProxy.description": "Use global proxy (`HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`), you need to restart `VSCode` to take effect after changing this setting, [click to view online documentation](https://aide.nicepkg.cn/guide/configuration/use-system-proxy)", - "config.codeViewerHelperPrompt.description": "Code viewer helper prompt template, [click to view online documentation](https://aide.nicepkg.cn/guide/configuration/code-viewer-helper-prompt)", + "config.codeViewerHelperPrompt.description": "Code viewer helper AI prompt template, [click to view online documentation](https://aide.nicepkg.cn/guide/configuration/code-viewer-helper-prompt)", + "config.expertCodeEnhancerPromptList.description": "Expert code enhancer AI prompt template list, [click to view online documentation](https://aide.nicepkg.cn/guide/configuration/expert-code-enhancer-prompt-list)", + "config.expertCodeEnhancerPromptList.solid": "Optimize using SOLID principles", + "config.expertCodeEnhancerPromptList.dry": "Apply DRY principle", + "config.expertCodeEnhancerPromptList.designPatterns": "Apply appropriate design patterns", + "config.expertCodeEnhancerPromptList.splitComponents": "Split into smaller components", + "config.expertCodeEnhancerPromptList.cleanliness": "Improve code cleanliness", + "config.expertCodeEnhancerPromptList.performance": "Optimize for performance", + "config.expertCodeEnhancerPromptList.databaseQueries": "Optimize database queries", + "config.expertCodeEnhancerPromptList.security": "Enhance security measures", + "config.expertCodeEnhancerPromptList.concurrency": "Optimize concurrency and multithreading", "config.convertLanguagePairs.description": "Default convert language pairs, [click to view online documentation](https://aide.nicepkg.cn/guide/configuration/convert-language-pairs)", "config.autoRememberConvertLanguagePairs.description": "Automatically remember convert language pairs, [click to view online documentation](https://aide.nicepkg.cn/guide/configuration/auto-remember-convert-language-pairs)", "config.readClipboardImage.description": "Allow reading clipboard images as AI context in certain scenarios, [click to view online documentation](https://aide.nicepkg.cn/guide/configuration/read-clipboard-image)", @@ -74,5 +85,7 @@ "input.selectAiSuggestionsVariableName.prompt": "Select AI suggestions variable name", "input.batchProcessor.prompt": "Let AI batch process your selected {0} files, what do you want AI to do?", "input.batchProcessor.placeholder": "eg: help me migrate from python2 to python3", + "input.expertCodeEnhancer.selectPrompt.title": "Select code optimize method", + "input.expertCodeEnhancer.customPrompt.placeholder": "Custom optimize prompt", "file.content": "File: {0}\n```{1}\n{2}\n```\n\n" } diff --git a/package.nls.zh-cn.json b/package.nls.zh-cn.json index 4fed887..705c932 100644 --- a/package.nls.zh-cn.json +++ b/package.nls.zh-cn.json @@ -3,6 +3,7 @@ "command.askAI": "✨ Aide: 问 AI", "command.codeConvert": "✨ Aide: 代码转换", "command.codeViewerHelper": "✨ Aide: 代码查看器助手", + "command.expertCodeEnhancer": "✨ Aide: 让大师帮你改代码", "command.renameVariable": "✨ Aide: 重命名变量", "command.smartPaste": "✨ Aide: 智能粘贴", "command.batchProcessor": "✨ Aide: AI 批量处理文件", @@ -16,7 +17,17 @@ "config.openaiBaseUrl.description": "OpenAI Base URL, [点击查看在线文档](https://aide.nicepkg.cn/zh/guide/configuration/openai-base-url)", "config.apiConcurrency.description": "API 请求并发数, [点击查看在线文档](https://aide.nicepkg.cn/zh/guide/configuration/api-concurrency)", "config.useSystemProxy.description": "是否使用全局代理 (`HTTP_PROXY`、`HTTPS_PROXY`、`ALL_PROXY`) , 更改此设置后需要重启 `VSCode` 才生效, [点击查看在线文档](https://aide.nicepkg.cn/zh/guide/configuration/use-system-proxy)", - "config.codeViewerHelperPrompt.description": "代码查看器助手 prompt 模板, [点击查看在线文档](https://aide.nicepkg.cn/zh/guide/configuration/code-viewer-helper-prompt)", + "config.codeViewerHelperPrompt.description": "代码查看器助手 AI 提示词模板, [点击查看在线文档](https://aide.nicepkg.cn/zh/guide/configuration/code-viewer-helper-prompt)", + "config.expertCodeEnhancerPromptList.description": "大师代码优化 AI 提示词模板列表, [点击查看在线文档](https://aide.nicepkg.cn/zh/guide/configuration/expert-code-enhancer-prompt-list)", + "config.expertCodeEnhancerPromptList.solid": "使用 SOLID 原则优化", + "config.expertCodeEnhancerPromptList.dry": "应用 DRY 原则", + "config.expertCodeEnhancerPromptList.designPatterns": "应用适当的设计模式", + "config.expertCodeEnhancerPromptList.splitComponents": "拆分为更小的组件", + "config.expertCodeEnhancerPromptList.cleanliness": "提高代码整洁度", + "config.expertCodeEnhancerPromptList.performance": "优化性能", + "config.expertCodeEnhancerPromptList.databaseQueries": "优化数据库查询", + "config.expertCodeEnhancerPromptList.security": "加强安全措施", + "config.expertCodeEnhancerPromptList.concurrency": "优化并发和多线程", "config.convertLanguagePairs.description": "默认转换语言对照表, [点击查看在线文档](https://aide.nicepkg.cn/zh/guide/configuration/convert-language-pairs)", "config.autoRememberConvertLanguagePairs.description": "是否自动记住转换语言对照表, [点击查看在线文档](https://aide.nicepkg.cn/zh/guide/configuration/auto-remember-convert-language-pairs)", "config.readClipboardImage.description": "是否允许某些场景读取剪贴板图片作为 AI 上下文, [点击查看在线文档](https://aide.nicepkg.cn/zh/guide/configuration/read-clipboard-image)", @@ -74,5 +85,7 @@ "input.selectAiSuggestionsVariableName.prompt": "选择 AI 建议的变量名", "input.batchProcessor.prompt": "让 AI 批量处理你选中的 {0} 个文件,你想 AI 做什么?", "input.batchProcessor.placeholder": "比如:帮我从 python2 迁移到 python3", + "input.expertCodeEnhancer.selectPrompt.title": "选择代码优化方式", + "input.expertCodeEnhancer.customPrompt.placeholder": "自定义优化提示词", "file.content": "File: {0}\n```{1}\n{2}\n```\n\n" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0667582..22a77a3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -28,13 +28,13 @@ importers: version: 4.3.1(@vue/compiler-sfc@3.4.36)(prettier@3.3.3) '@langchain/anthropic': specifier: ^0.2.14 - version: 0.2.14(langchain@0.2.15)(openai@4.55.4(zod@3.23.8)) + version: 0.2.14(langchain@0.2.16)(openai@4.55.4(zod@3.23.8)) '@langchain/core': specifier: 0.2.23 - version: 0.2.23(langchain@0.2.15(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1))(openai@4.55.4(zod@3.23.8)) + version: 0.2.23(langchain@0.2.16(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1))(openai@4.55.4(zod@3.23.8)) '@langchain/openai': specifier: ^0.2.6 - version: 0.2.6(langchain@0.2.15(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1)) + version: 0.2.6(langchain@0.2.16(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1)) '@tomjs/vite-plugin-vscode': specifier: ^2.5.5 version: 2.5.5(@swc/core@1.7.10)(postcss@8.4.40)(typescript@5.4.5)(vite@5.4.0(@types/node@22.2.0)(less@4.2.0)) @@ -147,11 +147,11 @@ importers: specifier: ^5.27.2 version: 5.27.2(@types/node@22.2.0)(typescript@5.4.5) langchain: - specifier: ^0.2.15 - version: 0.2.15(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1) + specifier: ^0.2.16 + version: 0.2.16(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1) lint-staged: - specifier: ^15.2.8 - version: 15.2.8 + specifier: ^15.2.9 + version: 15.2.9 minimatch: specifier: ^9.0.5 version: 9.0.5 @@ -3695,8 +3695,8 @@ packages: kolorist@1.8.0: resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} - langchain@0.2.15: - resolution: {integrity: sha512-SW4YdRnNPNDRhu6vsxHhxwx+OhDcQsOuiQ/K5gzsUMXUkgbS+y8kG3Kjgs08MXgKAkT4IKW0f2/o1B+2n0Lubw==} + langchain@0.2.16: + resolution: {integrity: sha512-NaCl1jdxladaLd63VxGtVcbuypzTq14XSmQI6vBajAISJgz02Q1+wiAIPIC2wMfsKjBRoCSgNCJw3/7nxqUuoQ==} engines: {node: '>=18'} peerDependencies: '@aws-sdk/client-s3': '*' @@ -3939,8 +3939,8 @@ packages: linkify-it@5.0.0: resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==} - lint-staged@15.2.8: - resolution: {integrity: sha512-PUWFf2zQzsd9EFU+kM1d7UP+AZDbKFKuj+9JNVTBkhUFhbg4MAt6WfyMMwBfM4lYqd4D2Jwac5iuTu9rVj4zCQ==} + lint-staged@15.2.9: + resolution: {integrity: sha512-BZAt8Lk3sEnxw7tfxM7jeZlPRuT4M68O0/CwZhhaw6eeWu0Lz5eERE3m386InivXB64fp/mDID452h48tvKlRQ==} engines: {node: '>=18.12.0'} hasBin: true @@ -6724,10 +6724,10 @@ snapshots: '@jridgewell/resolve-uri': 3.1.1 '@jridgewell/sourcemap-codec': 1.4.15 - '@langchain/anthropic@0.2.14(langchain@0.2.15)(openai@4.55.4(zod@3.23.8))': + '@langchain/anthropic@0.2.14(langchain@0.2.16)(openai@4.55.4(zod@3.23.8))': dependencies: '@anthropic-ai/sdk': 0.22.0 - '@langchain/core': 0.2.23(langchain@0.2.15(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1))(openai@4.55.4(zod@3.23.8)) + '@langchain/core': 0.2.23(langchain@0.2.16(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1))(openai@4.55.4(zod@3.23.8)) fast-xml-parser: 4.4.1 zod: 3.23.8 zod-to-json-schema: 3.22.5(zod@3.23.8) @@ -6736,13 +6736,13 @@ snapshots: - langchain - openai - '@langchain/core@0.2.23(langchain@0.2.15(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1))(openai@4.55.4(zod@3.23.8))': + '@langchain/core@0.2.23(langchain@0.2.16(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1))(openai@4.55.4(zod@3.23.8))': dependencies: ansi-styles: 5.2.0 camelcase: 6.3.0 decamelize: 1.2.0 js-tiktoken: 1.0.12 - langsmith: 0.1.39(@langchain/core@0.2.23(langchain@0.2.15(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1))(openai@4.55.4(zod@3.23.8)))(langchain@0.2.15(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1))(openai@4.55.4(zod@3.23.8)) + langsmith: 0.1.39(@langchain/core@0.2.23(langchain@0.2.16(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1))(openai@4.55.4(zod@3.23.8)))(langchain@0.2.16(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1))(openai@4.55.4(zod@3.23.8)) mustache: 4.2.0 p-queue: 6.6.2 p-retry: 4.6.2 @@ -6753,9 +6753,9 @@ snapshots: - langchain - openai - '@langchain/openai@0.2.6(langchain@0.2.15(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1))': + '@langchain/openai@0.2.6(langchain@0.2.16(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1))': dependencies: - '@langchain/core': 0.2.23(langchain@0.2.15(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1))(openai@4.55.4(zod@3.23.8)) + '@langchain/core': 0.2.23(langchain@0.2.16(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1))(openai@4.55.4(zod@3.23.8)) js-tiktoken: 1.0.12 openai: 4.55.4(zod@3.23.8) zod: 3.23.8 @@ -6764,9 +6764,9 @@ snapshots: - encoding - langchain - '@langchain/textsplitters@0.0.3(langchain@0.2.15(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1))(openai@4.55.4(zod@3.23.8))': + '@langchain/textsplitters@0.0.3(langchain@0.2.16(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1))(openai@4.55.4(zod@3.23.8))': dependencies: - '@langchain/core': 0.2.23(langchain@0.2.15(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1))(openai@4.55.4(zod@3.23.8)) + '@langchain/core': 0.2.23(langchain@0.2.16(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1))(openai@4.55.4(zod@3.23.8)) js-tiktoken: 1.0.12 transitivePeerDependencies: - langchain @@ -9605,16 +9605,16 @@ snapshots: kolorist@1.8.0: {} - langchain@0.2.15(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1): + langchain@0.2.16(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1): dependencies: - '@langchain/core': 0.2.23(langchain@0.2.15(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1))(openai@4.55.4(zod@3.23.8)) - '@langchain/openai': 0.2.6(langchain@0.2.15(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1)) - '@langchain/textsplitters': 0.0.3(langchain@0.2.15(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1))(openai@4.55.4(zod@3.23.8)) + '@langchain/core': 0.2.23(langchain@0.2.16(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1))(openai@4.55.4(zod@3.23.8)) + '@langchain/openai': 0.2.6(langchain@0.2.16(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1)) + '@langchain/textsplitters': 0.0.3(langchain@0.2.16(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1))(openai@4.55.4(zod@3.23.8)) binary-extensions: 2.2.0 js-tiktoken: 1.0.12 js-yaml: 4.1.0 jsonpointer: 5.0.1 - langsmith: 0.1.41(@langchain/core@0.2.23(langchain@0.2.15(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1))(openai@4.55.4(zod@3.23.8)))(langchain@0.2.15(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1))(openai@4.55.4(zod@3.23.8)) + langsmith: 0.1.41(@langchain/core@0.2.23(langchain@0.2.16(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1))(openai@4.55.4(zod@3.23.8)))(langchain@0.2.16(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1))(openai@4.55.4(zod@3.23.8)) openapi-types: 12.1.3 p-retry: 4.6.2 uuid: 10.0.0 @@ -9622,7 +9622,7 @@ snapshots: zod: 3.23.8 zod-to-json-schema: 3.22.5(zod@3.23.8) optionalDependencies: - '@langchain/anthropic': 0.2.14(langchain@0.2.15)(openai@4.55.4(zod@3.23.8)) + '@langchain/anthropic': 0.2.14(langchain@0.2.16)(openai@4.55.4(zod@3.23.8)) fast-xml-parser: 4.4.1 ignore: 5.3.2 playwright: 1.45.1 @@ -9630,7 +9630,7 @@ snapshots: - encoding - openai - langsmith@0.1.39(@langchain/core@0.2.23(langchain@0.2.15(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1))(openai@4.55.4(zod@3.23.8)))(langchain@0.2.15(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1))(openai@4.55.4(zod@3.23.8)): + langsmith@0.1.39(@langchain/core@0.2.23(langchain@0.2.16(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1))(openai@4.55.4(zod@3.23.8)))(langchain@0.2.16(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1))(openai@4.55.4(zod@3.23.8)): dependencies: '@types/uuid': 9.0.8 commander: 10.0.1 @@ -9638,11 +9638,11 @@ snapshots: p-retry: 4.6.2 uuid: 9.0.1 optionalDependencies: - '@langchain/core': 0.2.23(langchain@0.2.15(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1))(openai@4.55.4(zod@3.23.8)) - langchain: 0.2.15(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1) + '@langchain/core': 0.2.23(langchain@0.2.16(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1))(openai@4.55.4(zod@3.23.8)) + langchain: 0.2.16(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1) openai: 4.55.4(zod@3.23.8) - langsmith@0.1.41(@langchain/core@0.2.23(langchain@0.2.15(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1))(openai@4.55.4(zod@3.23.8)))(langchain@0.2.15(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1))(openai@4.55.4(zod@3.23.8)): + langsmith@0.1.41(@langchain/core@0.2.23(langchain@0.2.16(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1))(openai@4.55.4(zod@3.23.8)))(langchain@0.2.16(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1))(openai@4.55.4(zod@3.23.8)): dependencies: '@types/uuid': 9.0.8 commander: 10.0.1 @@ -9651,8 +9651,8 @@ snapshots: semver: 7.6.3 uuid: 9.0.1 optionalDependencies: - '@langchain/core': 0.2.23(langchain@0.2.15(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1))(openai@4.55.4(zod@3.23.8)) - langchain: 0.2.15(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1) + '@langchain/core': 0.2.23(langchain@0.2.16(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1))(openai@4.55.4(zod@3.23.8)) + langchain: 0.2.16(@langchain/anthropic@0.2.14)(fast-xml-parser@4.4.1)(ignore@5.3.2)(openai@4.55.4(zod@3.23.8))(playwright@1.45.1) openai: 4.55.4(zod@3.23.8) language-subtag-registry@0.3.23: {} @@ -9694,7 +9694,7 @@ snapshots: dependencies: uc.micro: 2.1.0 - lint-staged@15.2.8: + lint-staged@15.2.9: dependencies: chalk: 5.3.0 commander: 12.1.0 diff --git a/src/extension/cleanup.ts b/src/extension/cleanup.ts index 820f8fe..ee49c89 100644 --- a/src/extension/cleanup.ts +++ b/src/extension/cleanup.ts @@ -2,6 +2,7 @@ import * as vscode from 'vscode' import { cleanupCodeConvertRunnables } from './commands/code-convert' import { cleanupCodeViewerHelperRunnables } from './commands/code-viewer-helper' +import { cleanupExpertCodeEnhancerRunnables } from './commands/expert-code-enhancer' import { cleanupSmartPasteRunnables } from './commands/smart-paste' export const cleanup = async (context: vscode.ExtensionContext) => { @@ -9,7 +10,8 @@ export const cleanup = async (context: vscode.ExtensionContext) => { vscode.workspace.onDidCloseTextDocument(() => { cleanupCodeConvertRunnables() cleanupCodeViewerHelperRunnables() - cleanupSmartPasteRunnables + cleanupExpertCodeEnhancerRunnables() + cleanupSmartPasteRunnables() }) ) } diff --git a/src/extension/commands/expert-code-enhancer/build-generate-prompt.ts b/src/extension/commands/expert-code-enhancer/build-generate-prompt.ts new file mode 100644 index 0000000..45a0d61 --- /dev/null +++ b/src/extension/commands/expert-code-enhancer/build-generate-prompt.ts @@ -0,0 +1,187 @@ +import { getReferenceFilePaths } from '@extension/ai/get-reference-file-paths' +import { getConfigKey } from '@extension/config' +import { AbortError } from '@extension/constants' +import { getFileOrFoldersPromptInfo } from '@extension/file-utils/get-fs-prompt-info' +import { t, translateVscodeJsonText } from '@extension/i18n' +import { cacheFn } from '@extension/storage' +import { showQuickPickWithCustomInput } from '@extension/utils' +import type { BaseLanguageModelInput } from '@langchain/core/language_models/base' +import { Minimatch, type MinimatchOptions } from 'minimatch' +import * as vscode from 'vscode' + +interface ExpertCodeEnhancerPromptItem { + match?: string | string[] + title?: string + prompt: string + sort?: number + autoContext?: boolean // need function_call, default is false +} + +const isMatched = ( + item: ExpertCodeEnhancerPromptItem, + filePath: string +): boolean => { + const minimatchOptions: MinimatchOptions = { + dot: true, + matchBase: true + } + const unixFilePath = filePath.replace(/\\/g, '/') + + if (typeof item.match === 'string') { + return new Minimatch(item.match, minimatchOptions).match(unixFilePath) + } + + if (Array.isArray(item.match)) { + return item.match.some(pattern => + new Minimatch(pattern, minimatchOptions).match(unixFilePath) + ) + } + + return false +} + +// cache for 5 minutes +const cacheGetReferenceFilePaths = cacheFn(getReferenceFilePaths, 60 * 5) + +export const buildGeneratePrompt = async ({ + workspaceFolder, + currentFilePath, + code, + codeIsFromSelection, + abortController +}: { + workspaceFolder: vscode.WorkspaceFolder + currentFilePath: string + code: string + codeIsFromSelection: boolean + abortController?: AbortController +}): Promise => { + const expertCodeEnhancerPromptList = ((await getConfigKey( + 'expertCodeEnhancerPromptList' + )) || []) as ExpertCodeEnhancerPromptItem[] + + const currentFileRelativePath = + vscode.workspace.asRelativePath(currentFilePath) + const currentFileFullContent = codeIsFromSelection + + const matchedPrompts = expertCodeEnhancerPromptList + .map(item => { + const title = item.title + ? translateVscodeJsonText(item.title) + : item.prompt.split('\n')[0]! + const match = item.match ?? '**/*' + + return { + ...item, + title, + match + } + }) + .filter(item => isMatched(item, currentFileRelativePath)) + .sort((a, b) => { + const hasA = a.sort ?? false + const hasB = b.sort ?? false + if (hasA && hasB) return a.sort! - b.sort! + if (!hasA && !hasB) return 0 + return hasA ? -1 : 1 + }) + + const selected = await showQuickPickWithCustomInput({ + items: matchedPrompts.map(item => item.title) as string[], + placeholder: t('input.expertCodeEnhancer.selectPrompt.title') + }) + + const selectedPrompt = selected + ? matchedPrompts.find(item => item.title === selected) || + ({ + prompt: selected, + title: 'Custom Prompt', + match: '**/*', + sort: 0 + } as ExpertCodeEnhancerPromptItem) + : undefined + + if (!selectedPrompt) throw AbortError + + const customPrompt = selectedPrompt.prompt + + const baseInstructions = [ + '1. Focus solely on generating optimized code. Do not include any explanations, comments, or markdown formatting in your output.', + '2. Always provide a complete and fully functional code solution. Do not omit or abbreviate any part of the code.', + "3. Strictly adhere to the user's prompt and requirements specified below.", + '4. Maintain the original functionality of the code while improving its efficiency, readability, or structure as requested.', + '5. If the prompt asks for specific optimizations or changes, prioritize those requirements.', + "6. Ensure that the optimized code is compatible with the original codebase and doesn't introduce new dependencies unless explicitly requested." + ] + + const selectionInstructions = codeIsFromSelection + ? [ + '7. The provided code is a selection from a larger file. Ensure your optimizations fit seamlessly into the larger context.' + ] + : [] + + const contextInstructions = selectedPrompt.autoContext + ? [ + '7. Use the provided context from related files to inform your optimization decisions. This may include understanding shared functions, data structures, or coding patterns used in the project.', + '8. If the context reveals project-specific conventions or patterns, apply them consistently in your optimized code.', + '9. Be cautious not to introduce conflicts with the existing codebase or break dependencies based on the provided context.' + ] + : [] + + const allInstructions = [ + ...baseInstructions, + ...selectionInstructions, + ...contextInstructions + ] + + let prompt = ` + You are an AI assistant specialized in code optimization and refactoring${selectedPrompt.autoContext ? ', with access to additional context from related files' : ''}. Your task is to analyze and improve the provided code based on the following instructions: + + ${allInstructions.join('\n')} + + Here's the user's prompt: + ${customPrompt} + + Here's the code you need to optimize: + ${code} + + ${ + codeIsFromSelection + ? ` + Full file content: + ${currentFileFullContent} + + File path: ${currentFileRelativePath} + + The code to be optimized is a selection from the above file. + ` + : '' + } + ` + + if (selectedPrompt.autoContext) { + const { referenceFileRelativePaths, dependenceFileRelativePath } = + await cacheGetReferenceFilePaths({ currentFilePath, abortController }) + + const referencePaths = [ + ...new Set([dependenceFileRelativePath, ...referenceFileRelativePaths]) + ] + const { promptFullContent: referenceFileContent } = + await getFileOrFoldersPromptInfo( + referencePaths, + workspaceFolder.uri.fsPath + ) + + prompt += ` + Context from related files: + ${referenceFileContent} + ` + } + + prompt += ` + Please provide the optimized code based on these instructions${selectedPrompt.autoContext ? ", the user's prompt, and the given context" : " and the user's prompt"}. + Please do not reply with any text other than the code, and do not use markdown syntax. + ` + + return prompt +} diff --git a/src/extension/commands/expert-code-enhancer/index.ts b/src/extension/commands/expert-code-enhancer/index.ts new file mode 100644 index 0000000..ee3b013 --- /dev/null +++ b/src/extension/commands/expert-code-enhancer/index.ts @@ -0,0 +1,107 @@ +import { + createModelProvider, + getCurrentSessionIdHistoriesMap +} from '@extension/ai/helpers' +import { createTmpFileInfo } from '@extension/file-utils/create-tmp-file' +import { showContinueMessage } from '@extension/file-utils/show-continue-message' +import { tmpFileWriter } from '@extension/file-utils/tmp-file-writer' +import { t } from '@extension/i18n' +import { getCurrentWorkspaceFolderEditor } from '@extension/utils' +import type { RunnableConfig } from '@langchain/core/runnables' +import * as vscode from 'vscode' + +import { buildGeneratePrompt } from './build-generate-prompt' + +export const cleanupExpertCodeEnhancerRunnables = async () => { + const openDocumentPaths = new Set( + vscode.workspace.textDocuments.map(doc => doc.uri.fsPath) + ) + const sessionIdHistoriesMap = await getCurrentSessionIdHistoriesMap() + + Object.keys(sessionIdHistoriesMap).forEach(sessionId => { + const path = sessionId.match(/^expertCodeEnhancer:(.*)$/)?.[1] + + if (path && !openDocumentPaths.has(path)) { + delete sessionIdHistoriesMap[sessionId] + } + }) +} + +export const handleExpertCodeEnhancer = async () => { + const { workspaceFolder } = await getCurrentWorkspaceFolderEditor() + const { + originalFileExt, + originalFileContent, + originalFileLanguageId, + originalFileUri, + originalFileContentIsFromSelection, + tmpFileUri, + isTmpFileHasContent + } = await createTmpFileInfo() + + // ai + const modelProvider = await createModelProvider() + const aiRunnableAbortController = new AbortController() + const aiRunnable = await modelProvider.createRunnable({ + signal: aiRunnableAbortController.signal + }) + const sessionId = `expertCodeEnhancer:${tmpFileUri.fsPath}}` + const aiRunnableConfig: RunnableConfig = { + configurable: { + sessionId + } + } + const sessionIdHistoriesMap = await getCurrentSessionIdHistoriesMap() + const isSessionHistoryExists = !!sessionIdHistoriesMap[sessionId] + const isContinue = isTmpFileHasContent && isSessionHistoryExists + + const prompt = await buildGeneratePrompt({ + workspaceFolder, + currentFilePath: originalFileUri.fsPath, + code: originalFileContent, + codeIsFromSelection: originalFileContentIsFromSelection, + abortController: aiRunnableAbortController + }) + + const tmpFileWriterReturns = await tmpFileWriter({ + ext: originalFileExt, + languageId: originalFileLanguageId, + onCancel() { + aiRunnableAbortController.abort() + }, + buildAiStream: async () => { + if (!isContinue) { + // cleanup previous session + delete sessionIdHistoriesMap[sessionId] + + const aiStream = aiRunnable.stream( + { + input: prompt + }, + aiRunnableConfig + ) + return aiStream + } + + // continue + return aiRunnable.stream( + { + input: ` + continue, please do not reply with any text other than the code, and do not use markdown syntax. + go continue. + ` + }, + aiRunnableConfig + ) + } + }) + + await showContinueMessage({ + tmpFileUri: tmpFileWriterReturns?.tmpFileUri, + originalFileContentLineCount: originalFileContent.split('\n').length, + continueMessage: t('info.continueMessage') + t('info.iconContinueMessage'), + onContinue: async () => { + await handleExpertCodeEnhancer() + } + }) +} diff --git a/src/extension/commands/index.ts b/src/extension/commands/index.ts index cfb6c61..325b3b8 100644 --- a/src/extension/commands/index.ts +++ b/src/extension/commands/index.ts @@ -6,6 +6,7 @@ import { handleBatchProcessor } from './batch-processor' import { handleCodeConvert } from './code-convert' import { handleCodeViewerHelper } from './code-viewer-helper' import { handleCopyAsPrompt } from './copy-as-prompt' +import { handleExpertCodeEnhancer } from './expert-code-enhancer' import { handleCopyFileText } from './private/copy-file-text' import { handleQuickCloseFileWithoutSave } from './private/quick-close-file-without-save' import { handleReplaceFile } from './private/replace-file' @@ -34,6 +35,11 @@ export const registerCommands = async (context: vscode.ExtensionContext) => { commandErrorCatcher(handleCodeViewerHelper) ) + const expertCodeEnhancerDisposable = vscode.commands.registerCommand( + 'aide.expertCodeEnhancer', + commandErrorCatcher(handleExpertCodeEnhancer) + ) + const renameVariableDisposable = vscode.commands.registerCommand( 'aide.renameVariable', commandErrorCatcher(handleRenameVariable) @@ -84,6 +90,7 @@ export const registerCommands = async (context: vscode.ExtensionContext) => { askAIDisposable, codeConvertDisposable, codeViewerHelperDisposable, + expertCodeEnhancerDisposable, renameVariableDisposable, smartPasteDisposable, batchProcessorDisposable, diff --git a/src/extension/config.ts b/src/extension/config.ts index 9c4323b..8a34a6f 100644 --- a/src/extension/config.ts +++ b/src/extension/config.ts @@ -76,6 +76,10 @@ const configKey = { type: 'object', optional: true }, + expertCodeEnhancerPromptList: { + ...pkgConfig['aide.expertCodeEnhancerPromptList'], + type: 'array' + }, codeViewerHelperPrompt: { ...pkgConfig['aide.codeViewerHelperPrompt'], type: 'string' diff --git a/src/extension/file-utils/create-tmp-file.ts b/src/extension/file-utils/create-tmp-file.ts index bd3a7d0..22c4c3e 100644 --- a/src/extension/file-utils/create-tmp-file.ts +++ b/src/extension/file-utils/create-tmp-file.ts @@ -115,6 +115,11 @@ export interface TmpFileInfo { */ originalFileContent: string + /** + * Indicates whether the original file content is from selection. + */ + originalFileContentIsFromSelection: boolean + /** * The language ID of the original file. */ @@ -167,6 +172,7 @@ export const createTmpFileInfo = async (): Promise => { let originalFileContent = '' let isSelection = false let originalFileDocument: vscode.TextDocument + let originalFileContentIsFromSelection = false if (activeIsOriginalFile) { const { selection } = activeEditor @@ -175,6 +181,7 @@ export const createTmpFileInfo = async (): Promise => { ? activeEditor.document.getText(selection) : activeEditor.document.getText() originalFileDocument = activeEditor.document + originalFileContentIsFromSelection = isSelection } else { originalFileDocument = await vscode.workspace.openTextDocument(originalFileUri) @@ -197,6 +204,7 @@ export const createTmpFileInfo = async (): Promise => { originalFileUri, originalFileDocument, originalFileContent, + originalFileContentIsFromSelection, originalFileLanguageId, originalFileExt, activeIsOriginalFile, diff --git a/src/extension/i18n.ts b/src/extension/i18n.ts index 33227b8..1b05260 100644 --- a/src/extension/i18n.ts +++ b/src/extension/i18n.ts @@ -32,5 +32,7 @@ export const t: LocalizeFunction = (key: string, ...args: any[]) => { * @example * translateVscodeJsonText("%config.key%") === t('config.key') */ -export const translateVscodeJsonText = (text: string): string => - text.replace(/%([^%]+)%/g, (_, key) => t(key)) +export const translateVscodeJsonText = (text: string): string => { + if (!text.match(/%[^%]+%/)) return text + return text.replace(/%([^%]+)%/g, (_, key) => t(key)) +}