-
Notifications
You must be signed in to change notification settings - Fork 452
feat: refactor AI code completion with monacopilot and FIM support #1745
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Conversation
…nt and FIM support
WalkthroughThis pull request transitions away from an older AI completion approach by removing related code and documentation, then introduces a new monacopilot-based code completion system. It updates model configurations to mark code-completion-capable models and adjusts the robot plugin UI accordingly. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ 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. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
🤖 Fix all issues with AI agents
In `@packages/plugins/script/package.json`:
- Around line 30-31: The package.json currently depends on "monacopilot":
"^1.2.12", which is not published to npm; change the dependency to the latest
published version "monacopilot": "^1.2.7" (or pin to 1.2.7) so installs succeed;
locate the dependency entry for "monacopilot" in
packages/plugins/script/package.json and update the version string accordingly,
then run install/lockfile update.
In `@packages/plugins/script/src/ai-completion/adapters/deepseekAdapter.js`:
- Around line 37-57: The JSDoc for callDeepSeekAPI wrongly promises
Promise<string> while the implementation uses optional chaining
(response?.choices?.[0]?.message?.content) and can return undefined; either
update the JSDoc to Promise<string|undefined> to match the actual return or
change callDeepSeekAPI to validate the response and either throw an error or
return a defined fallback (e.g., empty string) before returning, making sure to
reference the callDeepSeekAPI function and the
response?.choices?.[0]?.message?.content access when you locate and fix the
code.
In `@packages/plugins/script/src/ai-completion/builders/promptBuilder.js`:
- Around line 15-35: In isInComment, remove the outer trimmed.includes('//')
guard that causes false positives for URLs and instead directly compute the
current line (using lastIndexOf('\n') and substring as already present) and
check currentLine.trim().startsWith('//') to determine line comments; keep the
existing block-comment detection (lastBlockStart/lastBlockEnd) unchanged so only
true line-starting '//' are treated as comments.
In `@packages/plugins/script/src/ai-completion/utils/completionUtils.js`:
- Around line 67-86: The truncation logic can produce an empty result when
cutoffIndex becomes 0 (e.g., first line starts with a CUTOFF_KEYWORD); update
the block in completionUtils.js that computes cutoffIndex (references: lines,
maxLines, truncation.CUTOFF_KEYWORDS, truncation.BLOCK_ENDINGS, cutoffIndex,
cleaned) to ensure at least one non-empty line is kept: if cutoffIndex is 0,
advance it to 1 (or scan forward to the next non-empty/safe line) before slicing
so lines.slice(0, cutoffIndex) never returns an empty array and cleaned always
contains content.
In `@packages/plugins/script/src/Main.vue`:
- Around line 148-155: The global registration uses
monaco.editor.addEditorAction which registers the action for all editors and
lacks cleanup; replace that call with the instance method editor.addAction to
scope the action to this editor (the local editor variable used around line 130)
and ensure it is tied to this editor's lifecycle alongside
completion.deregister(); update the registration to use editor.addAction and
rely on the editor instance unmount/cleanup (or explicitly dispose the returned
action if needed) so triggering only calls completion.trigger() for this editor.
🧹 Nitpick comments (13)
packages/plugins/script/src/ai-completion/triggers/completionTrigger.js (2)
11-17: Edge case: Parenthesis counting may misfire in complex code.The parenthesis counting approach doesn't account for parentheses inside string literals or comments. For example,
console.log("(");would be incorrectly detected as having unclosed parentheses.This is an acceptable tradeoff for most real-world code, but consider documenting this limitation or using a more robust approach if edge cases become problematic.
32-36: Redundant condition inisAfterBlockEnd.After
trimmedEnd = beforeCursor.trimEnd(), the expressionbeforeCursor.substring(trimmedEnd.length)yields only trailing whitespace. CheckingafterBrace.trim().length === 0will always be true.The check can be simplified:
♻️ Suggested simplification
function isAfterBlockEnd(beforeCursor) { const trimmedEnd = beforeCursor.trimEnd() // 检查是否以右花括号结尾 if (trimmedEnd.endsWith('}')) { - // 检查后面是否只有空格(没有其他字符) - const afterBrace = beforeCursor.substring(trimmedEnd.length) - return afterBrace.trim().length === 0 + return true } return false }packages/plugins/script/src/ai-completion/builders/lowcodeContextBuilder.js (2)
32-37: Arrow function regex may miss destructured parameters.The regex
(?:\(([^)]*)\)|(\w+))\s*=>won't correctly capture nested parentheses in destructured parameters like({a, b}) =>or([x, y]) =>, as[^)]*stops at the first).For the current use case (extracting approximate signatures for context), this is likely acceptable, but consider documenting the limitation.
213-252: Consider deduplication when merging contexts.
mergeLowcodeContextsconcatenates arrays without deduplication. If the same data source or utility appears in multiple contexts, it will be duplicated in the merged result, potentially inflating the AI prompt context.If this becomes an issue, consider deduplicating by
nameorid:♻️ Optional deduplication approach
+const dedupeByKey = (arr, key) => { + const seen = new Set() + return arr.filter((item) => { + const k = item[key] + if (seen.has(k)) return false + seen.add(k) + return true + }) +} + export function mergeLowcodeContexts(...contexts) { // ...existing merge logic... + + // Deduplicate arrays + merged.dataSource = dedupeByKey(merged.dataSource, 'name') + merged.utils = dedupeByKey(merged.utils, 'name') + merged.globalState = dedupeByKey(merged.globalState, 'id') + return merged }packages/plugins/script/src/Main.vue (1)
129-130: Variable shadowing may cause confusion.
monacoandeditorshadow outer variables:monacoshadows the component ref (line 68), andeditorshadows the function parameter (line 111). This can lead to maintenance confusion.♻️ Suggested rename for clarity
try { - const monaco = monacoRef.value.getMonaco() - const editor = monacoRef.value.getEditor() + const monacoInstance = monacoRef.value.getMonaco() + const editorInstance = monacoRef.value.getEditor() - completion = registerCompletion(monaco, editor, { + completion = registerCompletion(monacoInstance, editorInstance, { language: 'javascript', // ... }) - monaco.editor.addEditorAction({ + monacoInstance.editor.addEditorAction({packages/plugins/script/src/ai-completion/adapters/qwenAdapter.js (1)
46-61: Consider adding request timeout and handling malformed API responses.Two potential reliability concerns:
- The
fetchcall has no timeout, which could cause indefinite hangs if the API is unresponsive.- Line 61 returns
response?.choices?.[0]?.textwhich may silently returnundefinedon malformed responses without signaling an error to callers.♻️ Suggested improvement
+const TIMEOUT_MS = 30000 + export async function callQwenAPI(messages, config, apiKey, baseUrl) { const completionsUrl = `${baseUrl}${QWEN_CONFIG.COMPLETION_PATH}` + const controller = new AbortController() + const timeoutId = setTimeout(() => controller.abort(), TIMEOUT_MS) // ... request body construction ... - const fetchResponse = await fetch(completionsUrl, { + const fetchResponse = await fetch(completionsUrl, { method: HTTP_CONFIG.METHOD, headers: { 'Content-Type': HTTP_CONFIG.CONTENT_TYPE, Authorization: `Bearer ${apiKey}` }, - body: JSON.stringify(requestBody) + body: JSON.stringify(requestBody), + signal: controller.signal }) + clearTimeout(timeoutId) // ... error handling ... const response = await fetchResponse.json() - return response?.choices?.[0]?.text + const completionText = response?.choices?.[0]?.text + if (completionText === undefined) { + throw new Error(`${ERROR_MESSAGES.QWEN_API_ERROR} Malformed response: missing completion text`) + } + return completionText }packages/plugins/robot/src/constants/model-config.ts (1)
126-135: Minor: Inconsistent capitalization in label.The label
'Deepseek Coder编程模型'uses lowercase 's' while other DeepSeek references use'DeepSeek'(e.g., line 66, 108, 113).✏️ Suggested fix
{ - label: 'Deepseek Coder编程模型', + label: 'DeepSeek Coder编程模型', name: 'deepseek-coder',packages/plugins/script/src/ai-completion/adapters/index.js (2)
78-79: URL replacement may silently fail if baseUrl doesn't contain/v1.The
replace(DEEPSEEK_CONFIG.PATH_REPLACE, DEEPSEEK_CONFIG.COMPLETION_PATH)will return the original URL unchanged if/v1is not present. Consider adding validation or a warning log if the replacement doesn't occur, to help with debugging configuration issues.💡 Optional: Add validation for URL replacement
// 构建 DeepSeek FIM 端点:将 /v1 替换为 /beta - const completionBaseUrl = baseUrl.replace(DEEPSEEK_CONFIG.PATH_REPLACE, DEEPSEEK_CONFIG.COMPLETION_PATH) + const completionBaseUrl = baseUrl.replace(DEEPSEEK_CONFIG.PATH_REPLACE, DEEPSEEK_CONFIG.COMPLETION_PATH) + if (completionBaseUrl === baseUrl && !baseUrl.includes(DEEPSEEK_CONFIG.COMPLETION_PATH)) { + // eslint-disable-next-line no-console + console.warn('⚠️ DeepSeek baseUrl does not contain expected path for replacement:', baseUrl) + }
84-94: Empty string completion returns success instead of error.If
completionTextis a non-empty string that becomes empty aftertrim()andcleanCompletion(), the function returns{ completion: '', error: null }. Consider checking for empty string after cleaning:💡 Optional: Handle empty completion after cleaning
if (completionText) { completionText = completionText.trim() - completionText = cleanCompletion(completionText, modelType, cursorContext) + if (!completionText) { + return { + completion: null, + error: ERROR_MESSAGES.NO_COMPLETION + } + } + return { completion: completionText, error: null } }packages/plugins/robot/src/components/header-extension/robot-setting/RobotSetting.vue (1)
291-294: Type loosening:serviceparameter changed toany.The parameter type was changed to
anyto accommodate broader input types. While this works, consider using a more specific type or union type if the actual input types are known, to maintain better type safety.💡 Optional: Use more specific type
-const editService = (service: any) => { +const editService = (service: ModelService | Partial<ModelService>) => { state.editingService = JSON.parse(JSON.stringify(service)) as ModelService state.showServiceDialog = true }packages/plugins/script/src/ai-completion/builders/fimPromptBuilder.js (1)
86-100: Logic overlap:{is classified as statement, not object-property.The condition order means a prefix ending with
{will match line 92 (/[{;]\s*$/) and be classified asstatement, even though line 97 (/{\s*$/) also intends to detect object literals. If you want{to indicate object context, consider reordering the conditions or refining the patterns.Additionally, in the regex at line 87, the
[character should be escaped as\[for clarity, though it works at the end of a character class.💡 Optional: Reorder conditions or refine patterns
// 检测是否在表达式中 - if (/[=+\-*/%<>!&|,([]$/.test(prefixTrimmed)) { + if (/[=+\-*/%<>!&|,(\[]$/.test(prefixTrimmed)) { context.needsExpression = true context.type = 'expression' } - // 检测是否在语句开始 - else if (/[{;]\s*$/.test(prefixTrimmed) || prefixTrimmed.length === 0) { - context.needsStatement = true - context.type = 'statement' - } // 检测是否在对象字面量中 else if (/{\s*$/.test(prefixTrimmed) || /,\s*$/.test(prefixTrimmed)) { context.inObject = true context.type = 'object-property' } + // 检测是否在语句开始 + else if (/;\s*$/.test(prefixTrimmed) || prefixTrimmed.length === 0) { + context.needsStatement = true + context.type = 'statement' + }packages/plugins/script/src/ai-completion/prompts/templates.js (1)
130-172: Large JSON payloads could inflate prompt size.The
JSON.stringify(currentSchema, null, 2)at line 161 could produce very large strings for complex component schemas, potentially exceeding token limits or diluting the prompt quality. Consider implementing size limits or summarization for very large schemas.💡 Optional: Add size limit for schema serialization
// 添加当前组件 schema if (currentSchema) { - instruction += `\n\nCURRENT COMPONENT SCHEMA:\n${JSON.stringify(currentSchema, null, 2)}` + const schemaJson = JSON.stringify(currentSchema, null, 2) + const MAX_SCHEMA_LENGTH = 2000 + if (schemaJson.length > MAX_SCHEMA_LENGTH) { + instruction += `\n\nCURRENT COMPONENT SCHEMA (truncated):\n${schemaJson.substring(0, MAX_SCHEMA_LENGTH)}...` + } else { + instruction += `\n\nCURRENT COMPONENT SCHEMA:\n${schemaJson}` + }packages/plugins/script/src/ai-completion/constants.js (1)
170-171: Complex regex for meta info pattern.The
META_INFO_PATTERNregex is quite long and could be difficult to maintain. Consider adding inline comments or breaking it into named sub-patterns for clarity.💡 Optional: Document regex pattern
// Alternative: document the pattern components META_INFO_PATTERN: // Matches optional file/language/context header comments at start of content // Format: // File: ...\n // Language: ...\n // Current ...\n etc. /^(\/\/ File:.*\n)?(\/\/ Language:.*\n)?(\/\/ Current .*\n)*(\/\/ IMPORTANT:.*\n)*(\/\/ Technologies:.*\n)?(\/\/ NOTE:.*\n)*\n*/
📜 Review details
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (22)
packages/common/js/completion-files/context.mdpackages/common/js/completion.jspackages/plugins/robot/src/components/header-extension/robot-setting/RobotSetting.vuepackages/plugins/robot/src/composables/core/useConfig.tspackages/plugins/robot/src/constants/model-config.tspackages/plugins/robot/src/types/setting.types.tspackages/plugins/script/meta.jspackages/plugins/script/package.jsonpackages/plugins/script/src/Main.vuepackages/plugins/script/src/ai-completion/adapters/deepseekAdapter.jspackages/plugins/script/src/ai-completion/adapters/index.jspackages/plugins/script/src/ai-completion/adapters/qwenAdapter.jspackages/plugins/script/src/ai-completion/builders/fimPromptBuilder.jspackages/plugins/script/src/ai-completion/builders/index.jspackages/plugins/script/src/ai-completion/builders/lowcodeContextBuilder.jspackages/plugins/script/src/ai-completion/builders/promptBuilder.jspackages/plugins/script/src/ai-completion/constants.jspackages/plugins/script/src/ai-completion/index.jspackages/plugins/script/src/ai-completion/prompts/templates.jspackages/plugins/script/src/ai-completion/triggers/completionTrigger.jspackages/plugins/script/src/ai-completion/utils/completionUtils.jspackages/plugins/script/src/ai-completion/utils/modelUtils.js
💤 Files with no reviewable changes (1)
- packages/common/js/completion-files/context.md
🧰 Additional context used
🧠 Learnings (8)
📓 Common learnings
Learnt from: rhlin
Repo: opentiny/tiny-engine PR: 1011
File: packages/canvas/render/src/RenderMain.ts:82-88
Timestamp: 2025-01-14T08:50:50.226Z
Learning: For PR `#1011`, the focus is on resolving conflicts and migrating code, with architectural improvements deferred for future PRs.
📚 Learning: 2024-10-10T02:47:46.239Z
Learnt from: yy-wow
Repo: opentiny/tiny-engine PR: 850
File: packages/toolbars/preview/src/Main.vue:16-16
Timestamp: 2024-10-10T02:47:46.239Z
Learning: In `packages/toolbars/preview/src/Main.vue`, within the `preview` function, the `getMergeMeta` method is used at lines 64 and 65 to retrieve `engine.config` configurations.
Applied to files:
packages/common/js/completion.jspackages/plugins/script/src/Main.vue
📚 Learning: 2025-01-14T06:49:00.797Z
Learnt from: gene9831
Repo: opentiny/tiny-engine PR: 1011
File: packages/configurator/src/router-select-configurator/RouterSelectConfigurator.vue:63-73
Timestamp: 2025-01-14T06:49:00.797Z
Learning: In the tiny-engine project, the SvgIcon component is globally registered and available throughout Vue components without requiring explicit imports.
Applied to files:
packages/common/js/completion.js
📚 Learning: 2024-09-30T07:51:10.036Z
Learnt from: chilingling
Repo: opentiny/tiny-engine PR: 837
File: packages/vue-generator/src/plugins/genDependenciesPlugin.js:66-66
Timestamp: 2024-09-30T07:51:10.036Z
Learning: In the `tiny-engine` project, `opentiny/tiny-engine-dsl-vue` refers to the current package itself, and importing types from it may cause circular dependencies.
Applied to files:
packages/plugins/script/package.json
📚 Learning: 2025-07-03T09:22:59.512Z
Learnt from: hexqi
Repo: opentiny/tiny-engine PR: 1501
File: mockServer/src/tool/Common.js:79-82
Timestamp: 2025-07-03T09:22:59.512Z
Learning: In the tiny-engine project, the mockServer code uses ES6 import syntax but is compiled to CommonJS output. This means CommonJS globals like `__dirname` are available at runtime, while ES6 module-specific features like `import.meta` would cause runtime errors.
Applied to files:
packages/plugins/script/package.json
📚 Learning: 2025-01-14T04:25:46.281Z
Learnt from: rhlin
Repo: opentiny/tiny-engine PR: 1011
File: packages/canvas/render/src/material-function/material-getter.ts:66-80
Timestamp: 2025-01-14T04:25:46.281Z
Learning: In the tiny-engine project, styles from block components are processed through Vite's CSS compilation pipeline, and additional style sanitization libraries should be avoided to maintain consistency with this approach.
Applied to files:
packages/plugins/script/package.json
📚 Learning: 2025-01-15T02:19:06.755Z
Learnt from: yy-wow
Repo: opentiny/tiny-engine PR: 940
File: packages/canvas/DesignCanvas/src/DesignCanvas.vue:0-0
Timestamp: 2025-01-15T02:19:06.755Z
Learning: In Vue components using message subscriptions from opentiny/tiny-engine-meta-register, always clean up subscriptions in the onUnmounted hook using useMessage().unsubscribe() to prevent memory leaks.
Applied to files:
packages/plugins/script/src/Main.vue
📚 Learning: 2025-01-14T06:55:59.692Z
Learnt from: gene9831
Repo: opentiny/tiny-engine PR: 1011
File: packages/configurator/src/router-select-configurator/RouterSelectConfigurator.vue:95-98
Timestamp: 2025-01-14T06:55:59.692Z
Learning: The tiny-select component from opentiny/vue library ensures selected options are valid internally, requiring no additional validation in the change handler.
Applied to files:
packages/plugins/robot/src/components/header-extension/robot-setting/RobotSetting.vue
🧬 Code graph analysis (3)
packages/plugins/script/src/ai-completion/utils/completionUtils.js (2)
packages/register/src/hooks.ts (1)
useCanvas(80-80)packages/plugins/script/src/ai-completion/constants.js (4)
MODEL_COMMON_CONFIG(90-118)MODEL_COMMON_CONFIG(90-118)FIM_CONFIG(152-172)FIM_CONFIG(152-172)
packages/plugins/script/src/ai-completion/utils/modelUtils.js (1)
packages/plugins/script/src/ai-completion/constants.js (8)
MODEL_CONFIG(37-50)MODEL_CONFIG(37-50)MODEL_COMMON_CONFIG(90-118)MODEL_COMMON_CONFIG(90-118)STOP_SEQUENCES(123-147)STOP_SEQUENCES(123-147)FIM_CONFIG(152-172)FIM_CONFIG(152-172)
packages/plugins/script/src/ai-completion/adapters/deepseekAdapter.js (2)
packages/plugins/script/src/ai-completion/prompts/templates.js (4)
instruction(128-128)SYSTEM_BASE_PROMPT(4-18)SYSTEM_BASE_PROMPT(4-18)createUserPrompt(183-190)packages/plugins/script/src/ai-completion/constants.js (4)
API_ENDPOINTS(55-57)API_ENDPOINTS(55-57)HTTP_CONFIG(62-66)HTTP_CONFIG(62-66)
🔇 Additional comments (40)
packages/common/js/completion.js (2)
12-12: LGTM! Clean simplification of imports.The removal of AI-related imports (
vue ref,meta API,context.md) aligns with the refactoring strategy to move AI completion logic to a dedicated module.
174-204: LGTM! Simplified completion initialization.The
initCompletionfunction now focuses solely on static completions (Lowcode API hints, snippets, user variables), cleanly delegating AI completion to the new monacopilot-based architecture in the script plugin.packages/plugins/script/src/ai-completion/triggers/completionTrigger.js (1)
50-73: LGTM! Well-structured trigger logic.The
shouldTriggerCompletionfunction provides sensible defaults: avoiding completion after completed statements or blocks while allowing it in most other contexts. The guard for minimum text length prevents spurious triggers.packages/plugins/script/src/ai-completion/builders/lowcodeContextBuilder.js (1)
259-270: LGTM! Clean builder composition.The
buildLowcodeContextfunction provides a well-structured API with sensible defaults. The separation of formatting concerns into individual functions promotes maintainability.packages/plugins/script/src/Main.vue (2)
163-173: LGTM! Proper cleanup of AI completion and resources.The cleanup logic correctly deregisters the AI completion, disposes of completion providers, and terminates the ESLint worker. The use of optional chaining ensures safe disposal even if resources weren't initialized.
Based on learnings, this follows the best practice of always cleaning up subscriptions in the unmount hook.
111-161: Solid integration of monacopilot with appropriate error handling.The AI completion setup is well-structured:
- Preserves existing Lowcode API hints and ESLint integration
- Feature-flags AI completion via
aiCompletionEnabled- Uses try-catch to prevent registration failures from breaking the editor
- Configures reasonable defaults (
maxContextLines: 50,enableCaching: true)packages/plugins/script/meta.js (1)
9-10: LGTM! Clear configuration options for AI completion.The renamed
aiCompletionEnabledflag and documentedaiCompletionTriggeroption provide a clean configuration interface. The commented trigger modes—onIdle(default, low resource usage),onTyping(real-time completions), andonDemand(manual trigger)—show all available monacopilot options clearly.packages/plugins/robot/src/types/setting.types.ts (1)
33-33: LGTM!The new
codeCompletioncapability flag follows the existing pattern and is properly typed as optional boolean, consistent with the other capability fields.packages/plugins/script/src/ai-completion/builders/index.js (1)
1-3: LGTM!Clean barrel file providing a unified export surface for the builder modules.
packages/plugins/script/src/ai-completion/index.js (1)
1-6: LGTM!Clean entry point providing unified exports for the AI completion module. The selected exports appropriately expose the main public API surface.
packages/plugins/script/src/ai-completion/adapters/deepseekAdapter.js (1)
11-28: LGTM!The message construction is clean and properly composes system and user prompts using the shared templates. The
cursorContext: nullcorrectly indicates this adapter uses chat-based completion rather than FIM.packages/plugins/robot/src/composables/core/useConfig.ts (3)
321-324: Verify: IncludingcodeCompletionmodels in "compact" list.The
getCompactModelsfunction now returns models withcompactORcodeCompletioncapability. Ensure this is the intended behavior—code completion models (likeqwen3-coder-plus) may not necessarily be "compact/lightweight" models. If the intent is to have a combined list for quick model selection, the function name and comment accurately reflect this, but it's worth confirming the semantic alignment.
326-334: LGTM!The new filter functions are clean, follow existing patterns, and properly use optional chaining for capability access.
469-470: LGTM!The new helper functions are properly exposed in the composable's public API.
packages/plugins/script/src/ai-completion/adapters/qwenAdapter.js (1)
9-21: LGTM!Clean delegation to the FIM builder with appropriate structure for the messages payload.
packages/plugins/script/src/ai-completion/utils/completionUtils.js (1)
8-21: LGTM!Clean extraction of low-code metadata with appropriate defaults for missing values.
packages/plugins/script/src/ai-completion/builders/promptBuilder.js (2)
42-80: LGTM!Clean backwards iteration to find the nearest code context definitions with early exit optimization.
158-204: LGTM!Well-structured prompt orchestration with clear conditional logic for different completion contexts (comments, low-code, general code).
packages/plugins/robot/src/constants/model-config.ts (1)
55-64: LGTM!The
codeCompletion: truecapability is appropriately added to FIM-capable coding models, aligning with the PR's goal to mark models suitable for code completion.Also applies to: 84-103
packages/plugins/script/src/ai-completion/utils/modelUtils.js (3)
8-22: LGTM!Clean model type detection using keyword matching with proper null handling.
29-47: LGTM!Token calculation follows a clear priority order based on cursor context, with sensible defaults.
55-78: LGTM!Stop sequence composition correctly builds upon the base sequences with model-specific (FIM markers for Qwen) and context-specific additions. The spread operator ensures the base array isn't mutated.
packages/plugins/script/src/ai-completion/adapters/index.js (4)
14-16: FIMPromptBuilder initialized with QWEN_CONFIG but used for all model types.The
fimBuilderis instantiated withQWEN_CONFIGat line 15, but it's also used in the Qwen flow at line 57 (buildQwenMessages(fileContent, fimBuilder)). For DeepSeek,fimBuilderis not used directly (line 69 usesbuildDeepSeekMessages), so this appears intentional. However, if DeepSeek ever needs FIM building with different config, this would need adjustment.
20-27: LGTM!The configuration retrieval with proper null-safety and early return on missing config is well implemented.
29-35: LGTM!Good use of optional chaining and default values for extracting completion metadata.
100-107: LGTM!Error handling is robust with proper logging and fallback error message.
packages/plugins/robot/src/components/header-extension/robot-setting/RobotSetting.vue (3)
45-45: LGTM!The updated tooltip clearly explains the quick model's purpose and recommends models with the "代码" tag for code completion.
59-71: LGTM!The custom option template with capability tags provides excellent visual feedback for users selecting quick models. The tag colors are consistent and meaningful.
213-232: LGTM!The computed properties correctly filter models based on capabilities and sort by service name for better organization. The Chinese locale sorting is appropriate for the target audience.
packages/plugins/script/src/ai-completion/builders/fimPromptBuilder.js (4)
7-10: LGTM!Simple constructor that stores the configuration for later use.
17-53: LGTM!The
buildOptimizedFIMPromptmethod follows a clear workflow: clean → locate cursor → split → analyze → optimize → build. The fallback for missing cursor marker is appropriate.
117-127: LGTM!The prefix optimization correctly preserves the most recent context by keeping the last N lines closest to the cursor.
134-171: LGTM!The smart suffix truncation at natural code boundaries (function/class definitions, closing braces) is a good approach for providing relevant context without excessive noise. The heuristics are reasonable for JavaScript/TypeScript code.
packages/plugins/script/src/ai-completion/prompts/templates.js (3)
4-18: LGTM!The system prompt provides clear, comprehensive rules for the AI assistant. The emphasis on scope constraints and avoiding code from other functions is well-designed for focused completions.
25-39: LGTM!The instruction template effectively guides the model to follow language best practices while respecting scope boundaries.
183-189: LGTM!The user prompt template clearly structures the instruction and file content, with explicit guidance to return only the completion text.
packages/plugins/script/src/ai-completion/constants.js (4)
4-32: LGTM!The model-specific configurations for Qwen and DeepSeek are well-organized with appropriate temperature, top_p, and FIM settings. Having separate configs allows for model-specific tuning.
37-50: LGTM!The model configuration with type identifiers and keywords provides a clean abstraction for model detection and routing.
123-147: LGTM!The stop sequences are comprehensive for JavaScript/TypeScript code completion, covering function boundaries, imports, comments, and code blocks. This should help produce focused completions.
184-193: LGTM!The code patterns provide good coverage for common JavaScript/TypeScript declarations. These patterns serve well for context detection purposes.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
English | 简体中文
PR:优化 JS 面板编辑器 AI 代码补全架构
本 PR 对 AI 代码补全功能进行了全面重构,移除了旧的补全系统,
采用 monacopilot 作为新的补全引擎,并优化了模型配置和选择体验。
PR Checklist
Please check if your PR fulfills the following requirements:
PR Type
What kind of change does this PR introduce?
Background and solution
🌐 体验入口 --> TinyEngine
🎯 主要变更
1. 移除旧的 AI 补全实现
删除的代码:
packages/common/js/completion.js中的旧 AI 补全相关函数(~150 行)generateBaseReference()- 生成 AI prompt 的上下文fetchAiInlineCompletion()- 调用 AI APIinitInlineCompletion()- 注册旧的 inline completion providerpackages/common/js/completion-files/context.md- 旧的 AI prompt 模板packages/common/js/completion-files/目录保留的功能:
2. 新的 AI 补全架构(基于 monacopilot)
核心实现:
packages/plugins/script/src/ai-completion/- 新的 AI 补全模块adapters/- 适配器层,支持 Qwen 和 DeepSeek 模型builders/- Prompt 构建器,支持 FIM(Fill-In-the-Middle)triggers/- 智能触发器,优化补全时机utils/- 工具函数(模型检测、Token 计算等)constants.js- 配置常量技术特性:
registerCompletionAPItrigger: 'onIdle')补全触发条件:
输入代码自动触发
命令面板手动触发
3. 配置化支持
meta.js 配置:
Main.vue 实现:
aiCompletionEnabled和aiCompletionTrigger4. 模型配置优化
新增
codeCompletion能力标识:更新的模型配置:
codeCompletion: truecodeCompletion: true标记为代码补全优化的模型:
qwen3-coder-plusqwen-coder-turbo-latestqwen2.5-coder-32b-instructdeepseek-coder4.1 模型列表调整(支持 FIM)
调整原因:
新的 AI 代码补全基于 FIM(Fill-In-the-Middle)技术,需要模型原生支持 FIM 能力才能提供高质量的代码补全。因此需要:
阿里云百炼模型变更:
删除的模型(3个 - 不支持 FIM):
Qwen Coder编程模型(Flash)(qwen3-coder-flash) - 旧版本,不支持 FIMQwen3(14b)(qwen3-14b) - 小参数通用模型,不支持 FIMQwen3(8b)(qwen3-8b) - 小参数通用模型,不支持 FIM新增的模型(2个 - 支持 FIM):
Qwen2.5 Coder编程模型-最快响应(qwen-coder-turbo-latest)qwen3-coder-flashQwen2.5 Coder编程模型(32B)(qwen2.5-coder-32b-instruct)qwen3-14b和qwen3-8b保留并增强的模型:
Qwen Coder编程模型(PLUS)(qwen3-coder-plus) - 添加codeCompletion: trueDeepSeek 模型变更:
新增的模型(1个 - 支持 FIM):
Deepseek Coder编程模型(deepseek-coder)toolCalling: true,compact: true,codeCompletion: true保留的模型:
DeepSeek(deepseek-chat) - 对话模型,用于默认助手代码补全模型(支持 FIM):
5. UI/UX 优化
RobotSetting.vue 改进:
模型选择分离
视觉标签
智能排序
优化提示文案
6. 类型安全改进
类型推导:
优势:
7. 依赖变更
新增依赖:
monacopilot@^1.2.12- AI 代码补全引擎库导入路径调整:
@opentiny/tiny-engine-common→@opentiny/tiny-engine-common/component安装方式:
注意事项:
pnpm install安装新依赖📁 ai-completion 目录结构
🔄 基本调用流程
1. 初始化阶段(Main.vue)
2. 补全触发流程
3. 详细调用链
📊 影响范围
新增文件
packages/plugins/script/src/ai-completion/目录及所有子文件index.js- 统一导出constants.js- 配置常量adapters/index.js- 主适配器adapters/qwenAdapter.js- Qwen 适配器adapters/deepseekAdapter.js- DeepSeek 适配器builders/index.js- 构建器导出builders/promptBuilder.js- Prompt 构建器builders/fimPromptBuilder.js- FIM 构建器builders/lowcodeContextBuilder.js- 低代码上下文构建器prompts/templates.js- Prompt 模板triggers/completionTrigger.js- 触发器utils/modelUtils.js- 模型工具utils/completionUtils.js- 补全工具修改文件
packages/common/js/completion.js- 移除旧 AI 补全代码packages/plugins/script/src/Main.vue- 集成新的 AI 补全packages/plugins/script/meta.js- 添加配置选项packages/plugins/robot/src/constants/model-config.ts- 优化模型配置packages/plugins/robot/src/types/setting.types.ts- 添加 codeCompletion 类型packages/plugins/robot/src/composables/core/useConfig.ts- 添加模型筛选函数packages/plugins/robot/src/components/header-extension/robot-setting/RobotSetting.vue- UI 优化删除文件
packages/common/js/completion-files/context.mdpackages/common/js/completion-files/目录🎨 用户体验改进
代码补全
模型选择
📝 配置示例
启用 AI 补全(默认)
禁用 AI 补全
自定义触发模式
或
📚 相关文档
扩展阅读
Does this PR introduce a breaking change?
Other information
Summary by CodeRabbit
Release Notes
New Features
Chores
✏️ Tip: You can customize this high-level summary in your review settings.