Skip to content

Commit d732e24

Browse files
authored
feat: add dimcode acp agent (#1336)
* fix(think): persist reasoning duration * feat(acp): add dimcode-acp builtin agent * fix(session): sync model settings on switch * fix: test case
1 parent 14b3b66 commit d732e24

File tree

23 files changed

+696
-31
lines changed

23 files changed

+696
-31
lines changed

src/main/presenter/configPresenter/acpConfHelper.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,12 @@ import { McpConfHelper } from './mcpConfHelper'
1313
const ACP_STORE_VERSION = '2'
1414
const DEFAULT_PROFILE_NAME = 'Default'
1515

16-
const BUILTIN_ORDER: AcpBuiltinAgentId[] = ['kimi-cli', 'claude-code-acp', 'codex-acp']
16+
const BUILTIN_ORDER: AcpBuiltinAgentId[] = [
17+
'kimi-cli',
18+
'claude-code-acp',
19+
'codex-acp',
20+
'dimcode-acp'
21+
]
1722

1823
interface BuiltinTemplate {
1924
name: string
@@ -47,6 +52,15 @@ const BUILTIN_TEMPLATES: Record<AcpBuiltinAgentId, BuiltinTemplate> = {
4752
args: ['-y', '@zed-industries/codex-acp'],
4853
env: {}
4954
})
55+
},
56+
'dimcode-acp': {
57+
name: 'DimCode',
58+
defaultProfile: () => ({
59+
name: DEFAULT_PROFILE_NAME,
60+
command: 'dim',
61+
args: ['acp'],
62+
env: {}
63+
})
5064
}
5165
}
5266

src/main/presenter/configPresenter/acpInitHelper.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ const BUILTIN_INIT_COMMANDS: Record<AcpBuiltinAgentId, InitCommandConfig> = {
6767
'codex-acp': {
6868
commands: ['npm i -g @zed-industries/codex-acp', 'npm install -g @openai/codex', 'codex'],
6969
description: 'Initialize Codex CLI ACP'
70+
},
71+
'dimcode-acp': {
72+
commands: ['npm i -g dimcode', 'dim'],
73+
description: 'Initialize DimCode ACP'
7074
}
7175
}
7276

src/main/presenter/deepchatAgentPresenter/accumulator.ts

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,16 @@ function getCurrentBlock(
2020
return block
2121
}
2222

23+
function updateReasoningMetadata(state: StreamState, start: number, end: number): void {
24+
const relativeStart = Math.max(0, start - state.startTime)
25+
const relativeEnd = Math.max(0, end - state.startTime)
26+
27+
if (state.metadata.reasoningStartTime === undefined) {
28+
state.metadata.reasoningStartTime = relativeStart
29+
}
30+
state.metadata.reasoningEndTime = relativeEnd
31+
}
32+
2333
/**
2434
* Apply a single stream event to the accumulator state.
2535
* Pure block mutations only — no I/O, no finalization, no emit.
@@ -34,9 +44,25 @@ export function accumulate(state: StreamState, event: LLMCoreStreamEvent): void
3444
break
3545
}
3646
case 'reasoning': {
37-
if (state.firstTokenTime === null) state.firstTokenTime = Date.now()
47+
const currentTime = Date.now()
48+
if (state.firstTokenTime === null) state.firstTokenTime = currentTime
3849
const block = getCurrentBlock(state.blocks, 'reasoning_content')
3950
block.content += event.reasoning_content
51+
if (
52+
typeof block.reasoning_time !== 'object' ||
53+
block.reasoning_time === null ||
54+
typeof block.reasoning_time.start !== 'number' ||
55+
typeof block.reasoning_time.end !== 'number'
56+
) {
57+
block.reasoning_time = {
58+
start: currentTime,
59+
end: currentTime
60+
}
61+
} else {
62+
block.reasoning_time.end = currentTime
63+
}
64+
const reasoningTime = block.reasoning_time as { start: number; end: number }
65+
updateReasoningMetadata(state, reasoningTime.start, reasoningTime.end)
4066
state.dirty = true
4167
break
4268
}

src/main/presenter/deepchatAgentPresenter/index.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -618,12 +618,9 @@ export class DeepChatAgentPresenter implements IAgentImplementation {
618618
}
619619

620620
const currentGeneration = await this.getEffectiveSessionGenerationSettings(sessionId)
621-
const sanitized = await this.sanitizeGenerationSettings(
622-
nextProviderId,
623-
nextModelId,
624-
{},
625-
currentGeneration
626-
)
621+
const sanitized = await this.sanitizeGenerationSettings(nextProviderId, nextModelId, {
622+
systemPrompt: currentGeneration.systemPrompt
623+
})
627624

628625
if (state) {
629626
state.providerId = nextProviderId
Lines changed: 3 additions & 0 deletions
Loading

src/renderer/src/components/chat/ChatStatusBar.vue

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
class="h-6 px-2 gap-1 text-xs text-muted-foreground hover:text-foreground backdrop-blur-lg"
1111
>
1212
<ModelIcon
13-
:model-id="displayProviderId"
13+
:model-id="displayIconId"
1414
custom-class="w-3.5 h-3.5"
1515
:is-dark="themeStore.isDark"
1616
/>
@@ -25,7 +25,7 @@
2525
@click="selectModel(group.providerId, group.model.id)"
2626
>
2727
<ModelIcon
28-
:model-id="group.providerId"
28+
:model-id="resolveModelIconId(group.providerId, group.model.id)"
2929
custom-class="w-3.5 h-3.5"
3030
:is-dark="themeStore.isDark"
3131
/>
@@ -42,7 +42,7 @@
4242
:disabled="true"
4343
>
4444
<ModelIcon
45-
:model-id="displayProviderId"
45+
:model-id="displayIconId"
4646
custom-class="w-3.5 h-3.5"
4747
:is-dark="themeStore.isDark"
4848
/>
@@ -635,18 +635,27 @@ watch(
635635
{ immediate: true }
636636
)
637637
638-
const displayProviderId = computed(() => {
638+
const resolveModelIconId = (providerId?: string | null, modelId?: string | null): string => {
639+
if (providerId === 'acp' && modelId) {
640+
return modelId
641+
}
642+
return providerId || 'anthropic'
643+
}
644+
645+
const displayIconId = computed(() => {
639646
if (hasActiveSession.value) {
640-
return (
641-
activeSessionSelection.value?.providerId ||
642-
draftModelSelection.value?.providerId ||
643-
'anthropic'
647+
return resolveModelIconId(
648+
activeSessionSelection.value?.providerId || draftModelSelection.value?.providerId,
649+
activeSessionSelection.value?.modelId || draftModelSelection.value?.modelId
644650
)
645651
}
646652
if (isAcpAgent.value) {
647-
return agentStore.selectedAgentId ?? 'acp'
653+
return resolveModelIconId('acp', agentStore.selectedAgentId)
648654
}
649-
return draftModelSelection.value?.providerId || 'anthropic'
655+
return resolveModelIconId(
656+
draftModelSelection.value?.providerId,
657+
draftModelSelection.value?.modelId
658+
)
650659
})
651660
652661
const displayModelName = computed(() => {

src/renderer/src/components/icons/ModelIcon.vue

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import deepseekColorIcon from '@/assets/llm-icons/deepseek-color.svg?url'
3232
import openaiColorIcon from '@/assets/llm-icons/openai.svg?url'
3333
import ollamaColorIcon from '@/assets/llm-icons/ollama.svg?url'
3434
import doubaoColorIcon from '@/assets/llm-icons/doubao-color.svg?url'
35+
import dimcodeColorIcon from '@/assets/llm-icons/dimcode.svg?url'
3536
import minimaxColorIcon from '@/assets/llm-icons/minimax-color.svg?url'
3637
import fireworksColorIcon from '@/assets/llm-icons/fireworks-color.svg?url'
3738
import zerooneColorIcon from '@/assets/llm-icons/zeroone.svg?url'
@@ -75,6 +76,7 @@ const icons = {
7576
'kimi-cli': moonshotColorIcon,
7677
'claude-code-acp': claudeColorIcon,
7778
'codex-acp': openaiColorIcon,
79+
'dimcode-acp': dimcodeColorIcon,
7880
o3fan: o3fanColorIcon,
7981
cherryin: cherryinColorIcon,
8082
modelscope: modelscopeColorIcon,
@@ -197,6 +199,7 @@ const iconKey = computed(() => {
197199
// Monochrome icon URLs that need inversion in dark mode
198200
const monoIconUrls = new Set([
199201
openaiColorIcon,
202+
dimcodeColorIcon,
200203
ollamaColorIcon,
201204
zerooneColorIcon,
202205
xaiColorIcon,

src/renderer/src/i18n/zh-CN/routes.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@
1414
"settings-prompt": "Prompt管理",
1515
"settings-mcp-market": "MCP市场",
1616
"settings-acp": "ACP Agent",
17-
"settings-skills": "skills设置",
17+
"settings-skills": "Skills设置",
1818
"settings-notifications-hooks": "通知与Hooks"
1919
}

src/renderer/src/i18n/zh-CN/settings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1108,7 +1108,7 @@
11081108
"resetToDefaultFailed": "重置失败,请重试"
11091109
},
11101110
"skills": {
1111-
"title": "skills管理",
1111+
"title": "Skills设置",
11121112
"description": "管理和配置 AI 助手的 skill 模块",
11131113
"openFolder": "打开文件夹",
11141114
"addSkill": "添加 skill",

src/renderer/src/i18n/zh-HK/routes.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@
1414
"settings-mcp-market": "MCP市場",
1515
"playground": "Playground 實驗室",
1616
"settings-acp": "ACP Agent",
17-
"settings-skills": "skills設置",
17+
"settings-skills": "Skills設置",
1818
"settings-notifications-hooks": "通知與 Hooks"
1919
}

0 commit comments

Comments
 (0)