Skip to content

Commit 4353547

Browse files
committed
feat(opencode): add OpenCode Go platform to admin frontend
- GroupsView: opencode option in platform select + filter - CreateAccountModal/EditAccountModal: opencode platform button, base_url/api_key placeholders (opencode.ai/zen/go/v1), credentials builder fallback - PlatformIcon: opencode terminal icon - useModelWhitelist: opencode preset with 11 chat-completions models (grok-4.5, glm-5.1/5.2, kimi-k3/k2.7-code/k2.6, deepseek-v4-pro/flash, mimo-v2.5/pro, hy3) - i18n en/zh: admin.groups.platforms.opencode - types: opencode added to GroupPlatform/AccountPlatform
1 parent d889993 commit 4353547

8 files changed

Lines changed: 67 additions & 7 deletions

File tree

‎frontend/src/components/account/CreateAccountModal.vue‎

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,19 @@
160160
<PlatformIcon platform="grok" size="sm" />
161161
Grok
162162
</button>
163+
<button
164+
type="button"
165+
@click="form.platform = 'opencode'; accountCategory = 'apikey'"
166+
:class="[
167+
'flex flex-1 items-center justify-center gap-2 rounded-md px-4 py-2.5 text-sm font-medium transition-all',
168+
form.platform === 'opencode'
169+
? 'bg-white text-zinc-900 shadow-sm dark:bg-dark-600 dark:text-zinc-100'
170+
: 'text-gray-600 hover:text-gray-900 dark:text-gray-400 dark:hover:text-gray-200'
171+
]"
172+
>
173+
<PlatformIcon platform="opencode" size="sm" />
174+
OpenCode Go
175+
</button>
163176
</div>
164177
</div>
165178

@@ -1127,7 +1140,9 @@
11271140
? 'https://generativelanguage.googleapis.com'
11281141
: form.platform === 'grok'
11291142
? 'https://api.x.ai/v1'
1130-
: 'https://api.anthropic.com'
1143+
: form.platform === 'opencode'
1144+
? 'https://opencode.ai/zen/go/v1'
1145+
: 'https://api.anthropic.com'
11311146
"
11321147
/>
11331148
<p v-if="baseUrlHint" class="input-hint">{{ baseUrlHint }}</p>
@@ -1151,7 +1166,9 @@
11511166
? 'AIza...'
11521167
: form.platform === 'grok'
11531168
? 'xai-...'
1154-
: 'sk-ant-...'
1169+
: form.platform === 'opencode'
1170+
? 'sk-opencode-...'
1171+
: 'sk-ant-...'
11551172
"
11561173
/>
11571174
<p v-if="apiKeyHint" class="input-hint">{{ apiKeyHint }}</p>
@@ -5113,7 +5130,9 @@ const handleSubmit = async () => {
51135130
? 'https://generativelanguage.googleapis.com'
51145131
: form.platform === 'grok'
51155132
? 'https://api.x.ai/v1'
5116-
: 'https://api.anthropic.com'
5133+
: form.platform === 'opencode'
5134+
? 'https://opencode.ai/zen/go/v1'
5135+
: 'https://api.anthropic.com'
51175136
51185137
// Build credentials with optional model mapping
51195138
const credentials: Record<string, unknown> = {
@@ -5294,6 +5313,17 @@ const createAccountAndFinish = async (
52945313
delete credentials.model_mapping
52955314
}
52965315
}
5316+
if (platform === 'opencode') {
5317+
if (!credentials.base_url) {
5318+
credentials.base_url = apiKeyBaseUrl.value.trim() || 'https://opencode.ai/zen/go/v1'
5319+
}
5320+
const modelMapping = buildModelMappingObject(modelRestrictionMode.value, allowedModels.value, modelMappings.value)
5321+
if (modelMapping) {
5322+
credentials.model_mapping = modelMapping
5323+
} else {
5324+
delete credentials.model_mapping
5325+
}
5326+
}
52975327
await doCreateAccount({
52985328
name: form.name,
52995329
notes: form.notes,

‎frontend/src/components/account/EditAccountModal.vue‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@
4343
? 'https://cloudcode-pa.googleapis.com'
4444
: account.platform === 'grok'
4545
? 'https://api.x.ai/v1'
46-
: 'https://api.anthropic.com'
46+
: account.platform === 'opencode'
47+
? 'https://opencode.ai/zen/go/v1'
48+
: 'https://api.anthropic.com'
4749
"
4850
/>
4951
<p v-if="baseUrlHint" class="input-hint">{{ baseUrlHint }}</p>
@@ -72,7 +74,9 @@
7274
? 'sk-...'
7375
: account.platform === 'grok'
7476
? 'xai-...'
75-
: 'sk-ant-...'
77+
: account.platform === 'opencode'
78+
? 'sk-opencode-...'
79+
: 'sk-ant-...'
7680
"
7781
/>
7882
<p class="input-hint">{{ t('admin.accounts.leaveEmptyToKeep') }}</p>

‎frontend/src/components/common/PlatformIcon.vue‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@
3232
<circle cx="18" cy="18" r="3" />
3333
<path stroke-linecap="round" stroke-linejoin="round" d="M8.7 10.7 15.3 7.3M8.7 13.3l6.6 3.4" />
3434
</svg>
35+
<!-- OpenCode Go icon (terminal prompt) -->
36+
<svg v-else-if="platform === 'opencode'" :class="sizeClass" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
37+
<polyline points="4 17 10 11 4 5" />
38+
<line x1="12" y1="19" x2="20" y2="19" />
39+
</svg>
3540
<!-- Fallback: generic platform icon -->
3641
<svg v-else :class="sizeClass" fill="currentColor" viewBox="0 0 24 24">
3742
<path

‎frontend/src/composables/useModelWhitelist.ts‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,21 @@ const xaiModels = [
160160
'grok-imagine-video-1.5'
161161
]
162162

163+
// OpenCode Go (opencode 平台,OpenAI 兼容 chat/completions 端点模型)
164+
const opencodeModels = [
165+
'grok-4.5',
166+
'glm-5.2',
167+
'glm-5.1',
168+
'kimi-k3',
169+
'kimi-k2.7-code',
170+
'kimi-k2.6',
171+
'deepseek-v4-pro',
172+
'deepseek-v4-flash',
173+
'mimo-v2.5',
174+
'mimo-v2.5-pro',
175+
'hy3'
176+
]
177+
163178
// Cohere
164179
const cohereModels = [
165180
'command-a-03-2025',
@@ -240,6 +255,7 @@ const allModelsList: string[] = [
240255
...mistralModels,
241256
...metaModels,
242257
...xaiModels,
258+
...opencodeModels,
243259
...cohereModels,
244260
...yiModels,
245261
...moonshotModels,
@@ -423,6 +439,7 @@ export function getModelsByPlatform(platform: string): string[] {
423439
case 'meta': return metaModels
424440
case 'xai':
425441
case 'grok': return xaiModels
442+
case 'opencode': return opencodeModels
426443
case 'cohere': return cohereModels
427444
case 'yi': return yiModels
428445
case 'moonshot': return moonshotModels

‎frontend/src/i18n/locales/en/admin/overview.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -949,6 +949,7 @@ export default {
949949
gemini: 'Gemini',
950950
antigravity: 'Antigravity',
951951
grok: 'Grok',
952+
opencode: 'OpenCode Go',
952953
composite: 'Composite',
953954
},
954955
deleteConfirm:

‎frontend/src/i18n/locales/zh/admin/overview.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -882,6 +882,7 @@ export default {
882882
gemini: 'Gemini',
883883
antigravity: 'Antigravity',
884884
grok: 'Grok',
885+
opencode: 'OpenCode Go',
885886
composite: 'Composite',
886887
},
887888
saving: '保存中...',

‎frontend/src/types/index.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,7 @@ export interface PaginationConfig {
525525

526526
// ==================== API Key & Group Types ====================
527527

528-
export type GroupPlatform = 'anthropic' | 'openai' | 'gemini' | 'antigravity' | 'grok' | 'composite'
528+
export type GroupPlatform = 'anthropic' | 'openai' | 'gemini' | 'antigravity' | 'grok' | 'opencode' | 'composite'
529529

530530
export type VideoModelPrices = Record<string, Record<string, number>>
531531

@@ -876,7 +876,7 @@ export interface UpdateGroupRequest {
876876

877877
// ==================== Account & Proxy Types ====================
878878

879-
export type AccountPlatform = 'anthropic' | 'openai' | 'gemini' | 'antigravity' | 'grok'
879+
export type AccountPlatform = 'anthropic' | 'openai' | 'gemini' | 'antigravity' | 'grok' | 'opencode'
880880
export type AccountType = 'oauth' | 'setup-token' | 'apikey' | 'upstream' | 'bedrock' | 'service_account'
881881
export type OAuthAddMethod = 'oauth' | 'setup-token'
882882
export type ProxyProtocol = 'http' | 'https' | 'socks5' | 'socks5h'

‎frontend/src/views/admin/GroupsView.vue‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4614,6 +4614,7 @@ const platformOptions = computed(() => [
46144614
{ value: "gemini", label: "Gemini" },
46154615
{ value: "antigravity", label: "Antigravity" },
46164616
{ value: "grok", label: "Grok" },
4617+
{ value: "opencode", label: "OpenCode Go" },
46174618
{ value: "composite", label: "Composite" },
46184619
]);
46194620
@@ -4624,6 +4625,7 @@ const platformFilterOptions = computed(() => [
46244625
{ value: "gemini", label: "Gemini" },
46254626
{ value: "antigravity", label: "Antigravity" },
46264627
{ value: "grok", label: "Grok" },
4628+
{ value: "opencode", label: "OpenCode Go" },
46274629
{ value: "composite", label: "Composite" },
46284630
]);
46294631

0 commit comments

Comments
 (0)