Skip to content

Commit fcfeca9

Browse files
committed
feat(robot): Enhance model selection with code completion capabilities
1 parent 9cbb592 commit fcfeca9

6 files changed

Lines changed: 93 additions & 49 deletions

File tree

packages/plugins/robot/src/components/header-extension/robot-setting/RobotSetting.vue

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
快速模型
4343
<tiny-tooltip
4444
effect="light"
45-
content="用于代码补全、话题命名等场景。建议选择轻量模型以实现更快的响应速度,例如flash类型或8b/14b模型"
45+
content="用于代码补全、话题命名等快速响应场景。推荐选择带「代码」标签的模型以获得更好的代码补全效果"
4646
placement="top"
4747
>
4848
<svg-icon class="help-link" name="plugin-icon-plugin-help"></svg-icon>
@@ -51,11 +51,25 @@
5151
<tiny-select
5252
clearable
5353
v-model="state.modelSelection.quickModel"
54-
:options="compactModelOptions"
5554
filterable
5655
placeholder="请选择"
5756
@change="handleCompactModelChange"
58-
></tiny-select>
57+
popper-class="model-select-popper"
58+
>
59+
<template v-for="item in compactModelOptions" :key="item.value">
60+
<tiny-option :label="item.label" :value="item.value">
61+
<span class="left">{{ item.label }}</span>
62+
<div>
63+
<tiny-tag v-if="item.capabilities?.codeCompletion" type="success" effect="light" size="small"
64+
>代码</tiny-tag
65+
>
66+
<tiny-tag v-if="item.capabilities?.compact" type="info" effect="light" size="small"
67+
>轻量</tiny-tag
68+
>
69+
</div>
70+
</tiny-option>
71+
</template>
72+
</tiny-select>
5973
</tiny-form-item>
6074

6175
<div v-if="selectedDefaultModelInfo" class="model-info">
@@ -172,8 +186,8 @@ const emit = defineEmits(['close'])
172186
const {
173187
robotSettingState,
174188
saveRobotSettingState,
175-
getAllAvailableModels,
176189
getCompactModels,
190+
getNonCodeCompletionModels,
177191
addCustomService,
178192
updateService,
179193
deleteService,
@@ -196,9 +210,9 @@ const state = reactive({
196210
editingService: undefined as ModelService | undefined
197211
})
198212
199-
// 获取所有可用模型选项
213+
// 获取所有可用模型选项(排除代码补全专用模型)
200214
const allModelOptions = computed(() => {
201-
return getAllAvailableModels().map((model) => ({
215+
return getNonCodeCompletionModels().map((model) => ({
202216
label: model.displayLabel,
203217
value: model.value,
204218
capabilities: model.capabilities
@@ -207,10 +221,14 @@ const allModelOptions = computed(() => {
207221
208222
// 获取快速模型选项
209223
const compactModelOptions = computed(() => {
210-
return getCompactModels().map((model) => ({
224+
const models = getCompactModels().map((model) => ({
211225
label: model.displayLabel,
212-
value: model.value
226+
value: model.value,
227+
capabilities: model.capabilities,
228+
serviceName: model.serviceName
213229
}))
230+
231+
return models.sort((a, b) => a.serviceName.localeCompare(b.serviceName, 'zh-CN'))
214232
})
215233
216234
// 获取当前选择的默认模型信息
@@ -270,8 +288,8 @@ const addService = () => {
270288
state.showServiceDialog = true
271289
}
272290
273-
const editService = (service: ModelService) => {
274-
state.editingService = JSON.parse(JSON.stringify(service))
291+
const editService = (service: any) => {
292+
state.editingService = JSON.parse(JSON.stringify(service)) as ModelService
275293
state.showServiceDialog = true
276294
}
277295

packages/plugins/robot/src/composables/core/useConfig.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -318,9 +318,19 @@ const getAllAvailableModels = () => {
318318
)
319319
}
320320

321-
// 获取快速模型列表
321+
// 获取快速模型列表(包含 compact 或 codeCompletion 的模型)
322322
const getCompactModels = () => {
323-
return getAllAvailableModels().filter((model) => model.capabilities?.compact)
323+
return getAllAvailableModels().filter((model) => model.capabilities?.compact || model.capabilities?.codeCompletion)
324+
}
325+
326+
// 获取代码补全优化模型列表
327+
const getCodeCompletionModels = () => {
328+
return getAllAvailableModels().filter((model) => model.capabilities?.codeCompletion)
329+
}
330+
331+
// 获取非代码补全模型列表(用于默认助手模型)
332+
const getNonCodeCompletionModels = () => {
333+
return getAllAvailableModels().filter((model) => !model.capabilities?.codeCompletion)
324334
}
325335

326336
const updateThinkingState = (value: boolean) => {
@@ -456,6 +466,8 @@ export default () => {
456466
getModelCapabilities,
457467
getAllAvailableModels,
458468
getCompactModels,
469+
getCodeCompletionModels, // 代码补全模型列表
470+
getNonCodeCompletionModels, // 非代码补全模型列表
459471
getSelectedModelInfo, // 对话模型信息
460472
getSelectedQuickModelInfo, // 快速模型信息
461473

packages/plugins/robot/src/constants/model-config.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ export const DEFAULT_LLM_MODELS = [
5757
name: 'qwen3-coder-plus',
5858
capabilities: {
5959
toolCalling: true,
60+
codeCompletion: true,
6061
reasoning: reasoningExtraBody,
6162
jsonOutput: bailianJsonOutputExtraBody
6263
}
@@ -86,6 +87,7 @@ export const DEFAULT_LLM_MODELS = [
8687
capabilities: {
8788
toolCalling: true,
8889
compact: true,
90+
codeCompletion: true,
8991
jsonOutput: bailianJsonOutputExtraBody
9092
}
9193
},
@@ -95,6 +97,7 @@ export const DEFAULT_LLM_MODELS = [
9597
capabilities: {
9698
toolCalling: true,
9799
compact: true,
100+
codeCompletion: true,
98101
jsonOutput: bailianJsonOutputExtraBody
99102
}
100103
}
@@ -122,11 +125,12 @@ export const DEFAULT_LLM_MODELS = [
122125
},
123126
{
124127
label: 'Deepseek Coder编程模型',
125-
name: 'deepseek-chat',
128+
name: 'deepseek-coder',
126129
capabilities: {
127130
toolCalling: true,
128131
compact: true,
129-
jsonOutput: bailianJsonOutputExtraBody
132+
codeCompletion: true,
133+
jsonOutput: jsonOutputExtraBody
130134
}
131135
}
132136
]

packages/plugins/robot/src/types/setting.types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export interface ModelConfig {
3030
vision?: boolean
3131
reasoning?: boolean | Capability
3232
compact?: boolean
33+
codeCompletion?: boolean
3334
jsonOutput?: boolean | Capability
3435
}
3536
}

packages/plugins/script/meta.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ export default {
66
width: 600,
77
widthResizable: true,
88
options: {
9-
enableAICompletion: false // 禁用旧的 AI 补全系统,使用新的 monacopilot
9+
aiCompletionEnabled: true
10+
// aiCompletionTrigger: 'onIdle' // 可选:触发模式 'onIdle'(默认) | 'onTyping' | 'onDemand'
1011
},
1112
confirm: 'close' // 当点击插件栏切换或关闭前是否需要确认, 会调用插件中confirm值指定的方法,e.g. 此处指向 close方法,会调用插件的close方法执行确认逻辑
1213
}

packages/plugins/script/src/Main.vue

Lines changed: 42 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ import { onBeforeUnmount, reactive, provide } from 'vue'
3636
import { Button } from '@opentiny/vue'
3737
import { registerCompletion, type CompletionRegistration, type RegisterCompletionOptions } from 'monacopilot'
3838
import { VueMonaco, PluginPanel } from '@opentiny/tiny-engine-common/component'
39-
import { useHelp, useLayout } from '@opentiny/tiny-engine-meta-register'
39+
import { useHelp, useLayout, getMergeMeta } from '@opentiny/tiny-engine-meta-register'
4040
import { initCompletion } from '@opentiny/tiny-engine-common/js/completion'
4141
import { initLinter } from '@opentiny/tiny-engine-common/js/linter'
4242
import useMethod, { saveMethod, highlightMethod, getMethodNameList, getMethods } from './js/method'
@@ -70,6 +70,7 @@ export default {
7070
const { PLUGIN_NAME } = useLayout()
7171
7272
type RequestHandler = NonNullable<RegisterCompletionOptions['requestHandler']>
73+
type TriggerMode = NonNullable<RegisterCompletionOptions['trigger']>
7374
let completion: CompletionRegistration | null = null
7475
7576
const panelState = reactive({
@@ -120,43 +121,50 @@ export default {
120121
// 保留原有的 ESLint
121122
state.linterWorker = initLinter(editor, monacoRef.value.getMonaco(), state) as any
122123
123-
// 🆕 新增: 注册 AI 补全
124-
try {
125-
const monaco = monacoRef.value.getMonaco()
126-
const editor = monacoRef.value.getEditor()
127-
128-
completion = registerCompletion(monaco, editor, {
129-
language: 'javascript',
130-
filename: 'page.js',
131-
maxContextLines: 50,
132-
enableCaching: true,
133-
allowFollowUpCompletions: false,
134-
trigger: 'onIdle',
135-
triggerIf: ({ text, position }) => {
136-
return shouldTriggerCompletion({
137-
text,
138-
position
139-
})
140-
},
141-
requestHandler: createCompletionHandler() as RequestHandler
142-
})
143-
144-
monaco.editor.addEditorAction({
145-
id: 'monacopilot.triggerCompletion',
146-
label: 'Complete Code',
147-
contextMenuGroupId: 'navigation',
148-
run: () => {
149-
completion!.trigger()
150-
}
151-
})
152-
} catch (error) {
153-
// eslint-disable-next-line no-console
154-
console.error('❌ AI 补全注册失败:', error)
124+
const { aiCompletionEnabled, aiCompletionTrigger = 'onIdle' } =
125+
getMergeMeta('engine.plugins.pagecontroller')?.options || {}
126+
127+
if (aiCompletionEnabled) {
128+
try {
129+
const monaco = monacoRef.value.getMonaco()
130+
const editor = monacoRef.value.getEditor()
131+
132+
completion = registerCompletion(monaco, editor, {
133+
language: 'javascript',
134+
filename: 'page.js',
135+
maxContextLines: 50,
136+
enableCaching: true,
137+
allowFollowUpCompletions: false,
138+
trigger: aiCompletionTrigger as TriggerMode,
139+
triggerIf: ({ text, position }) => {
140+
return shouldTriggerCompletion({
141+
text,
142+
position
143+
})
144+
},
145+
requestHandler: createCompletionHandler() as RequestHandler
146+
})
147+
148+
monaco.editor.addEditorAction({
149+
id: 'monacopilot.triggerCompletion',
150+
label: 'Complete Code',
151+
contextMenuGroupId: 'navigation',
152+
run: () => {
153+
completion!.trigger()
154+
}
155+
})
156+
} catch (error) {
157+
// eslint-disable-next-line no-console
158+
console.error('❌ AI 补全注册失败:', error)
159+
}
155160
}
156161
}
157162
158163
onBeforeUnmount(() => {
159-
completion?.deregister?.()
164+
// 清理 AI 补全
165+
if (completion) {
166+
completion.deregister()
167+
}
160168
;(state.completionProvider as any)?.forEach?.((provider: any) => {
161169
provider?.dispose?.()
162170
})

0 commit comments

Comments
 (0)