codexmate 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -3
- package/cli.js +375 -4
- package/package.json +1 -1
- package/web-ui/app.js +16 -2
- package/web-ui/index.html +1 -0
- package/web-ui/modules/app.computed.dashboard.mjs +14 -0
- package/web-ui/modules/app.methods.index.mjs +2 -0
- package/web-ui/modules/app.methods.install.mjs +14 -0
- package/web-ui/modules/app.methods.kilocode-config.mjs +164 -0
- package/web-ui/modules/app.methods.navigation.mjs +12 -0
- package/web-ui/modules/app.methods.startup-claude.mjs +2 -1
- package/web-ui/modules/app.methods.tool-config-permissions.mjs +3 -2
- package/web-ui/modules/app.methods.web-ui-preferences.mjs +2 -1
- package/web-ui/modules/config-mode.computed.mjs +11 -1
- package/web-ui/modules/i18n/locales/en.mjs +31 -2
- package/web-ui/modules/i18n/locales/ja.mjs +34 -6
- package/web-ui/modules/i18n/locales/vi.mjs +35 -7
- package/web-ui/modules/i18n/locales/zh-tw.mjs +36 -7
- package/web-ui/modules/i18n/locales/zh.mjs +36 -7
- package/web-ui/partials/index/layout-header.html +32 -21
- package/web-ui/partials/index/panel-config-kilocode.html +101 -0
- package/web-ui/partials/index/panel-config-opencode.html +1 -0
- package/web-ui/partials/index/panel-docs.html +17 -1
- package/web-ui/res/web-ui-render.precompiled.js +328 -33
- package/web-ui/styles/controls-forms.css +10 -0
- package/web-ui/styles/docs-panel.css +51 -0
- package/web-ui/styles/layout-shell.css +11 -0
|
@@ -142,8 +142,9 @@ const zh = Object.freeze({
|
|
|
142
142
|
'side.docs': '文档',
|
|
143
143
|
'side.config': '配置',
|
|
144
144
|
'side.sessions': '会话',
|
|
145
|
-
'side.
|
|
146
|
-
'side.prompts
|
|
145
|
+
'side.workspace': '工作区',
|
|
146
|
+
'side.prompts': '提示词',
|
|
147
|
+
'side.prompts.meta': '提示词文件与预设',
|
|
147
148
|
'side.plugins': '插件',
|
|
148
149
|
'side.system': '系统',
|
|
149
150
|
'side.orchestration': '任务',
|
|
@@ -168,13 +169,13 @@ const zh = Object.freeze({
|
|
|
168
169
|
'side.update.currentOnly': '当前 v{current}',
|
|
169
170
|
'side.update.retry': '重试版本检查',
|
|
170
171
|
'side.config.codex': 'Codex',
|
|
171
|
-
'side.config.codex.meta': '
|
|
172
|
+
'side.config.codex.meta': '提供商 · 模型',
|
|
172
173
|
'side.config.claude': 'Claude Code',
|
|
173
|
-
'side.config.claude.meta': '
|
|
174
|
+
'side.config.claude.meta': '设置',
|
|
174
175
|
'side.config.openclaw': 'OpenClaw',
|
|
175
|
-
'side.config.openclaw.meta': '
|
|
176
|
+
'side.config.openclaw.meta': '配置',
|
|
176
177
|
'side.config.opencode': 'OpenCode',
|
|
177
|
-
'side.config.opencode.meta': '
|
|
178
|
+
'side.config.opencode.meta': '提供商',
|
|
178
179
|
'side.sessions.browser': '会话浏览',
|
|
179
180
|
'side.sessions.browser.meta': '浏览 / 导出 / 清理',
|
|
180
181
|
'side.prompts.agents': 'AGENTS.md',
|
|
@@ -618,9 +619,12 @@ const zh = Object.freeze({
|
|
|
618
619
|
|
|
619
620
|
// Docs panel
|
|
620
621
|
'docs.title': 'CLI 安装文档',
|
|
621
|
-
'docs.subtitle': '查看 Claude Code / Gemini CLI / CodeBuddy Code / Codex CLI 命令。',
|
|
622
|
+
'docs.subtitle': '查看 Claude Code / Gemini CLI / CodeBuddy Code / Codex CLI / KiloCode CLI 命令。',
|
|
622
623
|
'docs.section.commands': '安装命令',
|
|
623
624
|
'docs.section.commandsNote': '命令可直接复制。',
|
|
625
|
+
'docs.installed.title': '当前已安装命令',
|
|
626
|
+
'docs.installed.count': '已安装 {count} 个',
|
|
627
|
+
'docs.installed.empty': '未检测到已安装命令',
|
|
624
628
|
'docs.section.faq': '常见问题',
|
|
625
629
|
'docs.section.faqNote': '常见问题见下。',
|
|
626
630
|
'docs.command.aria': '{name} 命令',
|
|
@@ -1530,6 +1534,31 @@ const zh = Object.freeze({
|
|
|
1530
1534
|
'openclaw.action.applyAria': '应用 OpenClaw 配置:{name}',
|
|
1531
1535
|
'openclaw.action.editAria': '编辑 OpenClaw 配置:{name}',
|
|
1532
1536
|
'openclaw.action.deleteAria': '删除 OpenClaw 配置:{name}'
|
|
1537
|
+
,
|
|
1538
|
+
|
|
1539
|
+
'tab.config.kilocode': 'KiloCode',
|
|
1540
|
+
'side.config.kilocode': 'KiloCode',
|
|
1541
|
+
'side.config.kilocode.meta': '提供商',
|
|
1542
|
+
'toolConfig.kilocode.title': 'KiloCode 配置写入与启动',
|
|
1543
|
+
'toolConfig.kilocode.desc': '默认只读;开启后可写入 KiloCode 配置并从 Web 启动。',
|
|
1544
|
+
'toolConfig.kilocode.lockedTitle': '只读模式',
|
|
1545
|
+
'toolConfig.kilocode.lockedDesc': '开启写入权限后可保存配置或启动 KiloCode。',
|
|
1546
|
+
'toolConfig.kilocode.confirmMessage': '打开后,KiloCode tab 内的操作会写入 ~/.config/kilo/kilo.jsonc 或已存在的 kilo.json,并可启动本机 KiloCode。',
|
|
1547
|
+
'kilocode.providerModel.title': 'KiloCode provider / model',
|
|
1548
|
+
'kilocode.connection.title': 'KiloCode 连接',
|
|
1549
|
+
'kilocode.targetFile': 'KiloCode 生效配置:{path} · {status}',
|
|
1550
|
+
'kilocode.saveConfig': '保存配置',
|
|
1551
|
+
'kilocode.start': '启动 KiloCode',
|
|
1552
|
+
'kilocode.starting': '启动中',
|
|
1553
|
+
'kilocode.saveAndStart': '保存并启动',
|
|
1554
|
+
'kilocode.summary.title': '当前 KiloCode provider',
|
|
1555
|
+
'kilocode.configPreview.title': 'KiloCode 配置预览',
|
|
1556
|
+
'kilocode.configPreview.hint': 'API Key 已脱敏;保存会写入真实 key。',
|
|
1557
|
+
'kilocode.saveFailed': '保存 KiloCode 配置失败',
|
|
1558
|
+
'kilocode.fillRequired': '请填写 KiloCode URL 和 API Key',
|
|
1559
|
+
'kilocode.writeRequired': '请先打开 KiloCode 写入开关',
|
|
1560
|
+
'kilocode.saved': 'KiloCode 配置已保存',
|
|
1561
|
+
'kilocode.autoSaved': 'KiloCode 配置已同步',
|
|
1533
1562
|
});
|
|
1534
1563
|
|
|
1535
1564
|
export { zh };
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
:data-config-mode="configMode"
|
|
40
40
|
:tabindex="mainTab === 'config' ? 0 : -1"
|
|
41
41
|
:aria-selected="mainTab === 'config'"
|
|
42
|
-
:aria-controls="configMode === 'claude' ? 'panel-config-claude' : (configMode === 'openclaw' ? 'panel-config-openclaw' : (configMode === 'opencode' ? 'panel-config-opencode' : 'panel-config-provider'))"
|
|
42
|
+
:aria-controls="configMode === 'claude' ? 'panel-config-claude' : (configMode === 'openclaw' ? 'panel-config-openclaw' : (configMode === 'opencode' ? 'panel-config-opencode' : (configMode === 'kilocode' ? 'panel-config-kilocode' : 'panel-config-provider')))"
|
|
43
43
|
:class="{ active: isMainTabNavActive('config') }"
|
|
44
44
|
@pointerdown="onMainTabPointerDown('config', $event)"
|
|
45
45
|
@click="onMainTabClick('config', $event)">{{ t('tab.config') }}</button>
|
|
@@ -196,14 +196,13 @@
|
|
|
196
196
|
data-main-tab="config"
|
|
197
197
|
data-config-mode="codex"
|
|
198
198
|
:aria-current="mainTab === 'config' && configMode === 'codex' ? 'page' : null"
|
|
199
|
-
:class="['side-item', { active: isConfigModeNavActive('codex') }]"
|
|
199
|
+
:class="['side-item', 'side-item-compact', { active: isConfigModeNavActive('codex') }]"
|
|
200
200
|
@pointerdown="onConfigTabPointerDown('codex', $event)"
|
|
201
201
|
@click="onConfigTabClick('codex', $event)">
|
|
202
202
|
<span class="side-item-icon" aria-hidden="true">C</span>
|
|
203
203
|
<div class="side-item-title">{{ t('side.config.codex') }}</div>
|
|
204
204
|
<div class="side-item-meta">
|
|
205
205
|
<span>{{ t('side.config.codex.meta') }}</span>
|
|
206
|
-
<span v-if="currentProvider">{{ t('common.current', { value: currentProvider }) }}</span>
|
|
207
206
|
</div>
|
|
208
207
|
</button>
|
|
209
208
|
<button
|
|
@@ -211,14 +210,13 @@
|
|
|
211
210
|
data-main-tab="config"
|
|
212
211
|
data-config-mode="claude"
|
|
213
212
|
:aria-current="mainTab === 'config' && configMode === 'claude' ? 'page' : null"
|
|
214
|
-
:class="['side-item', { active: isConfigModeNavActive('claude') }]"
|
|
213
|
+
:class="['side-item', 'side-item-compact', { active: isConfigModeNavActive('claude') }]"
|
|
215
214
|
@pointerdown="onConfigTabPointerDown('claude', $event)"
|
|
216
215
|
@click="onConfigTabClick('claude', $event)">
|
|
217
216
|
<span class="side-item-icon" aria-hidden="true">A</span>
|
|
218
217
|
<div class="side-item-title">{{ t('side.config.claude') }}</div>
|
|
219
218
|
<div class="side-item-meta">
|
|
220
219
|
<span>{{ t('side.config.claude.meta') }}</span>
|
|
221
|
-
<span v-if="currentClaudeConfig">{{ t('common.current', { value: currentClaudeConfig }) }}</span>
|
|
222
220
|
</div>
|
|
223
221
|
</button>
|
|
224
222
|
<button
|
|
@@ -226,14 +224,13 @@
|
|
|
226
224
|
data-main-tab="config"
|
|
227
225
|
data-config-mode="openclaw"
|
|
228
226
|
:aria-current="mainTab === 'config' && configMode === 'openclaw' ? 'page' : null"
|
|
229
|
-
:class="['side-item', { active: isConfigModeNavActive('openclaw') }]"
|
|
227
|
+
:class="['side-item', 'side-item-compact', { active: isConfigModeNavActive('openclaw') }]"
|
|
230
228
|
@pointerdown="onConfigTabPointerDown('openclaw', $event)"
|
|
231
229
|
@click="onConfigTabClick('openclaw', $event)">
|
|
232
230
|
<span class="side-item-icon" aria-hidden="true">O</span>
|
|
233
231
|
<div class="side-item-title">{{ t('side.config.openclaw') }}</div>
|
|
234
232
|
<div class="side-item-meta">
|
|
235
233
|
<span>{{ t('side.config.openclaw.meta') }}</span>
|
|
236
|
-
<span v-if="currentOpenclawConfig">{{ t('common.current', { value: currentOpenclawConfig }) }}</span>
|
|
237
234
|
</div>
|
|
238
235
|
</button>
|
|
239
236
|
<button
|
|
@@ -241,35 +238,35 @@
|
|
|
241
238
|
data-main-tab="config"
|
|
242
239
|
data-config-mode="opencode"
|
|
243
240
|
:aria-current="mainTab === 'config' && configMode === 'opencode' ? 'page' : null"
|
|
244
|
-
:class="['side-item', { active: isConfigModeNavActive('opencode') }]"
|
|
241
|
+
:class="['side-item', 'side-item-compact', { active: isConfigModeNavActive('opencode') }]"
|
|
245
242
|
@pointerdown="onConfigTabPointerDown('opencode', $event)"
|
|
246
243
|
@click="onConfigTabClick('opencode', $event)">
|
|
247
244
|
<span class="side-item-icon" aria-hidden="true">N</span>
|
|
248
245
|
<div class="side-item-title">{{ t('side.config.opencode') }}</div>
|
|
249
246
|
<div class="side-item-meta">
|
|
250
247
|
<span>{{ t('side.config.opencode.meta') }}</span>
|
|
251
|
-
<span v-if="opencodeModel">{{ t('common.current', { value: opencodeModel }) }}</span>
|
|
252
248
|
</div>
|
|
253
249
|
</button>
|
|
250
|
+
|
|
254
251
|
<button
|
|
255
|
-
id="side-tab-
|
|
256
|
-
data-main-tab="
|
|
257
|
-
|
|
258
|
-
:
|
|
259
|
-
|
|
260
|
-
@
|
|
261
|
-
|
|
262
|
-
<
|
|
252
|
+
id="side-tab-config-kilocode"
|
|
253
|
+
data-main-tab="config"
|
|
254
|
+
data-config-mode="kilocode"
|
|
255
|
+
:aria-current="mainTab === 'config' && configMode === 'kilocode' ? 'page' : null"
|
|
256
|
+
:class="['side-item', 'side-item-compact', { active: isConfigModeNavActive('kilocode') }]"
|
|
257
|
+
@pointerdown="onConfigTabPointerDown('kilocode', $event)"
|
|
258
|
+
@click="onConfigTabClick('kilocode', $event)">
|
|
259
|
+
<span class="side-item-icon" aria-hidden="true">K</span>
|
|
260
|
+
<div class="side-item-title">{{ t('side.config.kilocode') }}</div>
|
|
263
261
|
<div class="side-item-meta">
|
|
264
|
-
<span>{{ t('side.
|
|
262
|
+
<span>{{ t('side.config.kilocode.meta') }}</span>
|
|
265
263
|
</div>
|
|
266
264
|
</button>
|
|
267
|
-
|
|
268
265
|
</div>
|
|
269
266
|
|
|
270
267
|
|
|
271
|
-
<div class="side-section" role="navigation" :aria-label="t('side.
|
|
272
|
-
<div class="side-section-title">{{ t('side.
|
|
268
|
+
<div class="side-section" role="navigation" :aria-label="t('side.workspace')">
|
|
269
|
+
<div class="side-section-title">{{ t('side.workspace') }}</div>
|
|
273
270
|
<button
|
|
274
271
|
id="side-tab-sessions"
|
|
275
272
|
data-main-tab="sessions"
|
|
@@ -284,6 +281,20 @@
|
|
|
284
281
|
<span>{{ t('sessions.sourceLabel', { value: (sessionFilterSource === 'all' ? t('sessions.source.all') : (sessionFilterSource === 'claude' ? 'Claude Code' : (sessionFilterSource === 'gemini' ? 'Gemini CLI' : (sessionFilterSource === 'codebuddy' ? 'CodeBuddy Code' : 'Codex')))) }) }}</span>
|
|
285
282
|
</div>
|
|
286
283
|
</button>
|
|
284
|
+
<button
|
|
285
|
+
id="side-tab-prompts"
|
|
286
|
+
data-main-tab="prompts"
|
|
287
|
+
:aria-current="mainTab === 'prompts' ? 'page' : null"
|
|
288
|
+
:class="['side-item', { active: isMainTabNavActive('prompts') }]"
|
|
289
|
+
@pointerdown="onMainTabPointerDown('prompts', $event)"
|
|
290
|
+
@click="onMainTabClick('prompts', $event)">
|
|
291
|
+
<span class="side-item-icon" aria-hidden="true">P</span>
|
|
292
|
+
<div class="side-item-title">{{ t('side.prompts') }}</div>
|
|
293
|
+
<div class="side-item-meta">
|
|
294
|
+
<span>{{ t('side.prompts.meta') }}</span>
|
|
295
|
+
</div>
|
|
296
|
+
</button>
|
|
297
|
+
|
|
287
298
|
<button
|
|
288
299
|
id="side-tab-usage"
|
|
289
300
|
data-main-tab="usage"
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
<!-- KiloCode 配置 -->
|
|
2
|
+
<div
|
|
3
|
+
v-show="mainTab === 'config' && configMode === 'kilocode'"
|
|
4
|
+
class="mode-content mode-cards"
|
|
5
|
+
id="panel-config-kilocode"
|
|
6
|
+
role="tabpanel"
|
|
7
|
+
:aria-labelledby="forceCompactLayout ? 'tab-config' : 'side-tab-config-kilocode'">
|
|
8
|
+
<div v-if="forceCompactLayout && !sessionStandalone" class="segmented-control">
|
|
9
|
+
<button type="button" :class="['segment', { active: configMode === 'codex' }]" @click="switchConfigMode('codex')">{{ t('tab.config.codex') }}</button>
|
|
10
|
+
<button type="button" :class="['segment', { active: configMode === 'claude' }]" @click="switchConfigMode('claude')">{{ t('tab.config.claude') }}</button>
|
|
11
|
+
<button type="button" :class="['segment', { active: configMode === 'openclaw' }]" @click="switchConfigMode('openclaw')">{{ t('tab.config.openclaw') }}</button>
|
|
12
|
+
<button type="button" :class="['segment', { active: configMode === 'opencode' }]" @click="switchConfigMode('opencode')">{{ t('tab.config.opencode') }}</button>
|
|
13
|
+
<button type="button" :class="['segment', { active: configMode === 'kilocode' }]" @click="switchConfigMode('kilocode')">{{ t('tab.config.kilocode') }}</button>
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
<section class="tool-config-write-card" :aria-label="t('toolConfig.kilocode.title')">
|
|
17
|
+
<div class="tool-config-write-copy">
|
|
18
|
+
<div class="tool-config-write-title">{{ t('toolConfig.kilocode.title') }}</div>
|
|
19
|
+
<p class="tool-config-write-desc">{{ t('toolConfig.kilocode.desc') }}</p>
|
|
20
|
+
</div>
|
|
21
|
+
<label class="settings-toggle-row tool-config-write-toggle">
|
|
22
|
+
<input
|
|
23
|
+
type="checkbox"
|
|
24
|
+
autocomplete="off"
|
|
25
|
+
:checked="isToolConfigWriteAllowed('kilocode')"
|
|
26
|
+
:disabled="toolConfigPermissionSaving.kilocode"
|
|
27
|
+
@change="setToolConfigPermission('kilocode', $event.target.checked)">
|
|
28
|
+
<span class="toggle-track"><span class="toggle-thumb"></span></span>
|
|
29
|
+
<span>{{ toolConfigPermissionStatusLabel('kilocode') }}</span>
|
|
30
|
+
</label>
|
|
31
|
+
</section>
|
|
32
|
+
|
|
33
|
+
<div class="tool-config-write-scope" :class="{ locked: !isToolConfigWriteAllowed('kilocode') }">
|
|
34
|
+
<div class="tool-config-write-body">
|
|
35
|
+
<section class="selector-section">
|
|
36
|
+
<div class="selector-header">
|
|
37
|
+
<span class="selector-title">{{ t('kilocode.providerModel.title') }}</span>
|
|
38
|
+
</div>
|
|
39
|
+
<div class="config-template-hint">{{ t('kilocode.targetFile', { path: kilocodeConfigPath || '~/.config/kilo/kilo.jsonc', status: kilocodeConfigExists ? t('common.exists') : t('common.notExistsWillCreateOnSave') }) }}</div>
|
|
40
|
+
<div class="codex-config-grid">
|
|
41
|
+
<div class="form-group codex-config-field">
|
|
42
|
+
<label class="form-label" for="kilocode-provider">{{ t('field.provider') }}</label>
|
|
43
|
+
<input id="kilocode-provider" class="form-input" v-model="kilocodeProvider" autocomplete="off" spellcheck="false" placeholder="codexmate" @blur="autoSaveKilocodeConfig">
|
|
44
|
+
</div>
|
|
45
|
+
<div class="form-group codex-config-field">
|
|
46
|
+
<label class="form-label" for="kilocode-base-url">{{ t('field.url') }}</label>
|
|
47
|
+
<input id="kilocode-base-url" class="form-input" v-model="kilocodeBaseUrl" autocomplete="off" spellcheck="false" placeholder="https://api.example.com/v1" @blur="autoSaveKilocodeConfig">
|
|
48
|
+
</div>
|
|
49
|
+
<div class="form-group codex-config-field">
|
|
50
|
+
<label class="form-label" for="kilocode-model">{{ t('field.model') }}</label>
|
|
51
|
+
<input id="kilocode-model" class="form-input" v-model="kilocodeModel" autocomplete="off" spellcheck="false" placeholder="gpt-5.3" @blur="autoSaveKilocodeConfig">
|
|
52
|
+
</div>
|
|
53
|
+
<div class="form-group codex-config-field">
|
|
54
|
+
<label class="form-label" for="kilocode-api-key">{{ t('opencode.field.apiKeyKeep') }}</label>
|
|
55
|
+
<div class="input-with-toggle">
|
|
56
|
+
<input id="kilocode-api-key" class="form-input" v-model="kilocodeApiKey" :type="kilocodeShowKey ? 'text' : 'password'" autocomplete="off" spellcheck="false" placeholder="sk-..." @blur="autoSaveKilocodeConfig">
|
|
57
|
+
<button type="button" class="input-toggle-btn" @mousedown.prevent @click="kilocodeShowKey = !kilocodeShowKey" :title="kilocodeShowKey ? t('common.hide') : t('common.show')" :aria-label="kilocodeShowKey ? t('common.hide') : t('common.show')">
|
|
58
|
+
<svg v-if="!kilocodeShowKey" viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5" width="16" height="16"><path d="M10 4C5 4 1.73 8.11 1 10c.73 1.89 4 6 9 6s8.27-4.11 9-6c-.73-1.89-4-6-9-6z"/><circle cx="10" cy="10" r="3"/></svg>
|
|
59
|
+
<svg v-else viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5" width="16" height="16"><path d="M2 2l16 16M8.2 4.2A9.9 9.9 0 0 1 10 4c5 0 8.27 4.11 9 6-.44.94-1.5 2.7-3.2 4.2M14.5 14.5A5.9 5.9 0 0 1 10 16c-5 0-8.27-4.11-9-6 .76-1.66 2.2-3.6 4.3-5"/></svg>
|
|
60
|
+
</button>
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
</div>
|
|
64
|
+
<div v-if="kilocodeError" class="config-template-hint error-text">{{ kilocodeError }}</div>
|
|
65
|
+
</section>
|
|
66
|
+
|
|
67
|
+
<section class="selector-section" v-if="kilocodeProviders.length">
|
|
68
|
+
<div class="selector-header"><span class="selector-title">{{ t('kilocode.summary.title') }}</span></div>
|
|
69
|
+
<div class="card-list">
|
|
70
|
+
<div v-for="provider in kilocodeProviders" :key="provider.name" :class="['card', { active: normalizeKilocodeProviderNameForUi(provider.name) === normalizeKilocodeProviderNameForUi(kilocodeProvider) }]" @dblclick="selectKilocodeProvider(provider)" @keydown.enter.self.prevent="selectKilocodeProvider(provider)" tabindex="0" role="button" :aria-current="normalizeKilocodeProviderNameForUi(provider.name) === normalizeKilocodeProviderNameForUi(kilocodeProvider) ? 'true' : null">
|
|
71
|
+
<div class="card-leading">
|
|
72
|
+
<div class="card-icon">{{ provider.name.charAt(0).toUpperCase() }}</div>
|
|
73
|
+
<div class="card-content">
|
|
74
|
+
<div class="card-title">{{ provider.name }}</div>
|
|
75
|
+
<div class="card-subtitle">{{ provider.baseURL || provider.api || t('config.url.unset') }}</div>
|
|
76
|
+
<div class="card-subtitle">{{ (provider.models || []).join(', ') || t('opencode.summary.noModel') }}</div>
|
|
77
|
+
</div>
|
|
78
|
+
</div>
|
|
79
|
+
<div class="card-trailing">
|
|
80
|
+
<span :class="['pill', provider.hasKey ? 'configured' : 'empty']">{{ provider.hasKey ? t('common.configured') : t('common.notConfigured') }}</span>
|
|
81
|
+
</div>
|
|
82
|
+
</div>
|
|
83
|
+
</div>
|
|
84
|
+
</section>
|
|
85
|
+
|
|
86
|
+
<section class="selector-section">
|
|
87
|
+
<div class="selector-header"><span class="selector-title">{{ t('kilocode.configPreview.title') }}</span></div>
|
|
88
|
+
<textarea class="template-textarea" :value="kilocodeContent" spellcheck="false" readonly aria-readonly="true"></textarea>
|
|
89
|
+
<div class="config-template-hint">{{ t('kilocode.configPreview.hint') }}</div>
|
|
90
|
+
</section>
|
|
91
|
+
|
|
92
|
+
<div v-if="!isToolConfigWriteAllowed('kilocode')" class="tool-config-write-overlay">
|
|
93
|
+
<div class="tool-config-write-overlay-card">
|
|
94
|
+
<div class="tool-config-write-overlay-title">{{ t('toolConfig.kilocode.lockedTitle') }}</div>
|
|
95
|
+
<p>{{ t('toolConfig.kilocode.lockedDesc') }}</p>
|
|
96
|
+
<button type="button" class="btn-tool" @click="setToolConfigPermission('kilocode', true)" :disabled="toolConfigPermissionSaving.kilocode">{{ t('toolConfig.enableWrite') }}</button>
|
|
97
|
+
</div>
|
|
98
|
+
</div>
|
|
99
|
+
</div>
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
<button type="button" :class="['segment', { active: configMode === 'claude' }]" @click="switchConfigMode('claude')">{{ t('tab.config.claude') }}</button>
|
|
11
11
|
<button type="button" :class="['segment', { active: configMode === 'openclaw' }]" @click="switchConfigMode('openclaw')">{{ t('tab.config.openclaw') }}</button>
|
|
12
12
|
<button type="button" :class="['segment', { active: configMode === 'opencode' }]" @click="switchConfigMode('opencode')">{{ t('tab.config.opencode') }}</button>
|
|
13
|
+
<button type="button" :class="['segment', { active: configMode === 'kilocode' }]" @click="switchConfigMode('kilocode')">{{ t('tab.config.kilocode') }}</button>
|
|
13
14
|
</div>
|
|
14
15
|
|
|
15
16
|
<section class="tool-config-write-card" :aria-label="t('opencode.writeAria')">
|
|
@@ -54,6 +54,22 @@
|
|
|
54
54
|
<strong class="docs-summary-value">{{ installRegistryPreview || 'npmmirror' }}</strong>
|
|
55
55
|
</div>
|
|
56
56
|
</div>
|
|
57
|
+
|
|
58
|
+
<div class="docs-installed-card">
|
|
59
|
+
<div class="docs-installed-head">
|
|
60
|
+
<span class="docs-installed-title">{{ t('docs.installed.title') }}</span>
|
|
61
|
+
<span class="docs-installed-count">{{ currentInstalledCommandCards.length ? t('docs.installed.count', { count: currentInstalledCommandCards.length }) : t('docs.installed.empty') }}</span>
|
|
62
|
+
</div>
|
|
63
|
+
<div v-if="currentInstalledCommandCards.length" class="docs-installed-list">
|
|
64
|
+
<div v-for="target in currentInstalledCommandCards" :key="'docs-installed-' + target.id" class="docs-installed-item">
|
|
65
|
+
<div class="docs-installed-main">
|
|
66
|
+
<span class="docs-installed-name">{{ target.name }}</span>
|
|
67
|
+
<span class="docs-installed-version">{{ target.version || '—' }}</span>
|
|
68
|
+
</div>
|
|
69
|
+
<code class="docs-installed-command">{{ target.commandPath || target.bin }}</code>
|
|
70
|
+
</div>
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
57
73
|
</div>
|
|
58
74
|
|
|
59
75
|
<div class="selector-section">
|
|
@@ -111,4 +127,4 @@
|
|
|
111
127
|
</div>
|
|
112
128
|
</div>
|
|
113
129
|
</div>
|
|
114
|
-
</div>
|
|
130
|
+
</div>
|