codexmate 0.1.19 → 0.1.21
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 +1 -1
- package/README.vi.md +1 -1
- package/README.zh.md +1 -1
- package/cli/agents-files.js +46 -1
- package/cli.js +12 -2
- package/package.json +1 -1
- package/web-ui/modules/app.methods.agents.mjs +21 -3
- package/web-ui/modules/app.methods.navigation.mjs +2 -2
- package/web-ui/modules/app.methods.pi-config.mjs +10 -1
- package/web-ui/modules/app.methods.web-ui-preferences.mjs +1 -0
- package/web-ui/modules/i18n/locales/en.mjs +5 -1
- package/web-ui/modules/i18n/locales/ja.mjs +5 -1
- package/web-ui/modules/i18n/locales/vi.mjs +5 -1
- package/web-ui/modules/i18n/locales/zh-tw.mjs +5 -1
- package/web-ui/modules/i18n/locales/zh.mjs +5 -1
- package/web-ui/partials/index/panel-config-pi.html +23 -15
- package/web-ui/partials/index/panel-prompts.html +1 -0
- package/web-ui/res/web-ui-render.precompiled.js +53 -39
- package/web-ui/session-helpers.mjs +23 -12
- package/web-ui/styles/controls-forms.css +7 -0
package/README.md
CHANGED
|
@@ -63,7 +63,7 @@ Unlike simple wrappers, Codex Mate acts as a **Local Agent Bridge**:
|
|
|
63
63
|
- **Pi Provider Config**: Manage Pi providers from the Web UI with lossless round-trip writes to `~/.pi/agent/models.json`, auto-fetched remote model lists, and one-click default provider/model switching via `~/.pi/agent/settings.json`.
|
|
64
64
|
- **Provider Health Cleanup**: Probe local Codex and Claude provider routes, surface failed configs in one modal, and bulk-clean selected broken providers without touching healthy or protected entries.
|
|
65
65
|
- **Skills Marketplace**: A local-first market to share and import skills between different agent apps.
|
|
66
|
-
- **Prompt File Editor**: Unified editor for global and project-level `CLAUDE.md` and `AGENTS.md` with auto-detection of project paths, plus a shared preset pool for reusable prompts.
|
|
66
|
+
- **Prompt File Editor**: Unified editor for global and project-level `CLAUDE.md` and `AGENTS.md` (including OpenCode's `~/.config/opencode/AGENTS.md`) with auto-detection of project paths, plus a shared preset pool for reusable prompts.
|
|
67
67
|
- **Task Orchestrator**: Plan and execute complex tasks with dependency tracking.
|
|
68
68
|
|
|
69
69
|
---
|
package/README.vi.md
CHANGED
|
@@ -69,7 +69,7 @@ Khác với các wrapper đơn giản, Codex Mate hoạt động như một **Ag
|
|
|
69
69
|
| **Bridge OpenAI** | ✅ | Chuyển đổi Codex Responses API sang định dạng OpenAI chuẩn |
|
|
70
70
|
| **Kiểm tra sức khỏe Provider** | ✅ | Kiểm tra route provider Codex/Claude, đánh dấu cấu hình lỗi và xóa hàng loạt các provider hỏng đã chọn một cách an toàn |
|
|
71
71
|
| **Mẫu Prompt** | ✅ | Plugin prompt tái sử dụng được với hỗ trợ biến |
|
|
72
|
-
| **Trình sửa tệp prompt** | ✅ | Chỉnh sửa CLAUDE.md / AGENTS.md và dùng kho preset chung. Áp dụng preset chỉ cập nhật editor; cần lưu thủ công để ghi vào tệp. |
|
|
72
|
+
| **Trình sửa tệp prompt** | ✅ | Chỉnh sửa CLAUDE.md / AGENTS.md (bao gồm `~/.config/opencode/AGENTS.md` của OpenCode) và dùng kho preset chung. Áp dụng preset chỉ cập nhật editor; cần lưu thủ công để ghi vào tệp. |
|
|
73
73
|
| **Tích hợp MCP** | ✅ | Expose tool và resource cục bộ qua MCP stdio |
|
|
74
74
|
| **Tự động cập nhật** | ✅ | Cập nhật nhanh qua `codexmate update` |
|
|
75
75
|
|
package/README.zh.md
CHANGED
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
- **Pi Provider 配置**:在 Web UI 中管理 Pi 供应商,写入 `~/.pi/agent/models.json` 时无损保留未知字段,支持自动拉取远端模型列表,并可一键切换 `~/.pi/agent/settings.json` 中的默认供应商/模型。
|
|
62
62
|
- **Provider 健康清理**:探测本地 Codex 与 Claude provider 路由,在同一个弹窗里集中展示失败配置,并批量清理已选坏配置,不影响正常或受保护项。
|
|
63
63
|
- **Skills 市场**:本地优先的市场,支持在不同的智能体应用之间共享和导入 Skills。
|
|
64
|
-
- **提示词文件编辑器**:统一编辑全局和项目级 `CLAUDE.md` 与 `AGENTS.md
|
|
64
|
+
- **提示词文件编辑器**:统一编辑全局和项目级 `CLAUDE.md` 与 `AGENTS.md`(含 OpenCode 的 `~/.config/opencode/AGENTS.md`),支持项目路径自动检测,并提供通用预设池复用 prompt。
|
|
65
65
|
- **任务编排器**:支持带有依赖跟踪的复杂任务规划与执行。
|
|
66
66
|
|
|
67
67
|
---
|
package/cli/agents-files.js
CHANGED
|
@@ -15,6 +15,7 @@ function createAgentsFileController(deps = {}) {
|
|
|
15
15
|
CLAUDE_MD_FILE_NAME,
|
|
16
16
|
readOpenclawAgentsFile,
|
|
17
17
|
readOpenclawWorkspaceFile,
|
|
18
|
+
OPENCODE_CONFIG_DIR,
|
|
18
19
|
backupPromptBeforeWrite
|
|
19
20
|
} = deps;
|
|
20
21
|
|
|
@@ -33,6 +34,7 @@ function createAgentsFileController(deps = {}) {
|
|
|
33
34
|
if (typeof CLAUDE_MD_FILE_NAME !== 'string' || !CLAUDE_MD_FILE_NAME) throw new Error('createAgentsFileController 缺少 CLAUDE_MD_FILE_NAME');
|
|
34
35
|
if (typeof readOpenclawAgentsFile !== 'function') throw new Error('createAgentsFileController 缺少 readOpenclawAgentsFile');
|
|
35
36
|
if (typeof readOpenclawWorkspaceFile !== 'function') throw new Error('createAgentsFileController 缺少 readOpenclawWorkspaceFile');
|
|
37
|
+
if (typeof OPENCODE_CONFIG_DIR !== 'string' || !OPENCODE_CONFIG_DIR) throw new Error('createAgentsFileController 缺少 OPENCODE_CONFIG_DIR');
|
|
36
38
|
if (typeof backupPromptBeforeWrite !== 'function' && typeof backupPromptBeforeWrite !== 'undefined') throw new Error('createAgentsFileController 备份回调无效');
|
|
37
39
|
|
|
38
40
|
function resolveAgentsFilePath(params = {}) {
|
|
@@ -236,7 +238,9 @@ function createAgentsFileController(deps = {}) {
|
|
|
236
238
|
}
|
|
237
239
|
let agentsHistoryBucket = '';
|
|
238
240
|
if (typeof backupPromptBeforeWrite === 'function') {
|
|
239
|
-
const
|
|
241
|
+
const explicitBucket = typeof params.historyBucket === 'string' ? params.historyBucket.trim() : '';
|
|
242
|
+
const bucket = explicitBucket
|
|
243
|
+
|| ('codex_' + sanitizeHistoryId(String(params.baseDir || '').trim() || 'global'));
|
|
240
244
|
backupPromptBeforeWrite(bucket, filePath);
|
|
241
245
|
agentsHistoryBucket = bucket;
|
|
242
246
|
}
|
|
@@ -254,6 +258,43 @@ function createAgentsFileController(deps = {}) {
|
|
|
254
258
|
}
|
|
255
259
|
}
|
|
256
260
|
|
|
261
|
+
|
|
262
|
+
function readOpencodeAgentsFile(params = {}) {
|
|
263
|
+
const baseDir = OPENCODE_CONFIG_DIR;
|
|
264
|
+
const filePath = path.join(baseDir, AGENTS_FILE_NAME);
|
|
265
|
+
const lineEndingFallback = os.EOL === '\r\n' ? '\r\n' : '\n';
|
|
266
|
+
|
|
267
|
+
if (!fs.existsSync(baseDir)) {
|
|
268
|
+
return {
|
|
269
|
+
exists: false,
|
|
270
|
+
path: filePath,
|
|
271
|
+
content: '',
|
|
272
|
+
lineEnding: lineEndingFallback,
|
|
273
|
+
configDir: baseDir,
|
|
274
|
+
baseDirMissing: true
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const readResult = readAgentsFile({ baseDir, metaOnly: !!params.metaOnly });
|
|
279
|
+
return {
|
|
280
|
+
...readResult,
|
|
281
|
+
configDir: baseDir
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function applyOpencodeAgentsFile(params = {}) {
|
|
286
|
+
const baseDir = OPENCODE_CONFIG_DIR;
|
|
287
|
+
ensureDir(baseDir);
|
|
288
|
+
const result = applyAgentsFile({
|
|
289
|
+
...params,
|
|
290
|
+
baseDir,
|
|
291
|
+
historyBucket: 'opencode_global'
|
|
292
|
+
});
|
|
293
|
+
return {
|
|
294
|
+
...result,
|
|
295
|
+
configDir: baseDir
|
|
296
|
+
};
|
|
297
|
+
}
|
|
257
298
|
function normalizeDiffText(input) {
|
|
258
299
|
const safe = typeof input === 'string' ? input : '';
|
|
259
300
|
return normalizeLineEnding(stripUtf8Bom(safe), '\n');
|
|
@@ -273,6 +314,8 @@ function createAgentsFileController(deps = {}) {
|
|
|
273
314
|
readResult = readOpenclawAgentsFile({ metaOnly });
|
|
274
315
|
} else if (context === 'openclaw-workspace') {
|
|
275
316
|
readResult = readOpenclawWorkspaceFile({ ...params, metaOnly });
|
|
317
|
+
} else if (context === 'opencode') {
|
|
318
|
+
readResult = readOpencodeAgentsFile({ metaOnly });
|
|
276
319
|
} else if (context === 'codex') {
|
|
277
320
|
readResult = readAgentsFile({ ...params, metaOnly });
|
|
278
321
|
} else {
|
|
@@ -310,6 +353,8 @@ function createAgentsFileController(deps = {}) {
|
|
|
310
353
|
applyClaudeMdFile,
|
|
311
354
|
readAgentsFile,
|
|
312
355
|
applyAgentsFile,
|
|
356
|
+
readOpencodeAgentsFile,
|
|
357
|
+
applyOpencodeAgentsFile,
|
|
313
358
|
normalizeDiffText,
|
|
314
359
|
buildAgentsDiff
|
|
315
360
|
};
|
package/cli.js
CHANGED
|
@@ -1190,7 +1190,8 @@ function getApiToolConfigWriteTarget(action) {
|
|
|
1190
1190
|
]);
|
|
1191
1191
|
const opencodeWriteActions = new Set([
|
|
1192
1192
|
'apply-opencode-config',
|
|
1193
|
-
'update-opencode-selection'
|
|
1193
|
+
'update-opencode-selection',
|
|
1194
|
+
'apply-opencode-agents-file'
|
|
1194
1195
|
]);
|
|
1195
1196
|
const kilocodeWriteActions = new Set([
|
|
1196
1197
|
'apply-kilocode-config',
|
|
@@ -2372,6 +2373,8 @@ const {
|
|
|
2372
2373
|
applyClaudeMdFile,
|
|
2373
2374
|
readAgentsFile,
|
|
2374
2375
|
applyAgentsFile,
|
|
2376
|
+
readOpencodeAgentsFile,
|
|
2377
|
+
applyOpencodeAgentsFile,
|
|
2375
2378
|
normalizeDiffText,
|
|
2376
2379
|
buildAgentsDiff
|
|
2377
2380
|
} = createAgentsFileController({
|
|
@@ -2394,7 +2397,8 @@ const {
|
|
|
2394
2397
|
},
|
|
2395
2398
|
readOpenclawWorkspaceFile() {
|
|
2396
2399
|
return readOpenclawWorkspaceFile(...arguments);
|
|
2397
|
-
}
|
|
2400
|
+
},
|
|
2401
|
+
OPENCODE_CONFIG_DIR
|
|
2398
2402
|
});
|
|
2399
2403
|
|
|
2400
2404
|
const {
|
|
@@ -13694,6 +13698,12 @@ function createWebServer({ htmlPath, assetsDir, webDir, host, port, openBrowser
|
|
|
13694
13698
|
case 'get-openclaw-agents-file':
|
|
13695
13699
|
result = readOpenclawAgentsFile();
|
|
13696
13700
|
break;
|
|
13701
|
+
case 'get-opencode-agents-file':
|
|
13702
|
+
result = readOpencodeAgentsFile(params || {});
|
|
13703
|
+
break;
|
|
13704
|
+
case 'apply-opencode-agents-file':
|
|
13705
|
+
result = applyOpencodeAgentsFile(params || {});
|
|
13706
|
+
break;
|
|
13697
13707
|
case 'apply-openclaw-agents-file':
|
|
13698
13708
|
result = applyOpenclawAgentsFile(params || {});
|
|
13699
13709
|
break;
|
package/package.json
CHANGED
|
@@ -33,6 +33,9 @@ function resolveAgentsHistoryBucket(instance) {
|
|
|
33
33
|
const projectPath = (instance.projectClaudeMdPath || '').trim();
|
|
34
34
|
return 'claude-project_' + sanitizePromptHistoryId(projectPath || 'global');
|
|
35
35
|
}
|
|
36
|
+
if (subTab === 'opencode') {
|
|
37
|
+
return 'opencode_global';
|
|
38
|
+
}
|
|
36
39
|
return 'codex_global';
|
|
37
40
|
}
|
|
38
41
|
|
|
@@ -216,6 +219,13 @@ export function createAgentsMethods(options = {}) {
|
|
|
216
219
|
this.agentsModalHint = tr('modal.agents.hint.openclawWorkspaceFile', `Workspace / ${fileName}`, { fileName });
|
|
217
220
|
return;
|
|
218
221
|
}
|
|
222
|
+
if (context === 'opencode') {
|
|
223
|
+
this.agentsContext = 'opencode';
|
|
224
|
+
this.agentsWorkspaceFileName = '';
|
|
225
|
+
this.agentsModalTitle = tr('modal.agents.title.opencode', 'OpenCode AGENTS.md 编辑器');
|
|
226
|
+
this.agentsModalHint = tr('modal.agents.hint.opencode', '保存后会写入 ~/.config/opencode/AGENTS.md。');
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
219
229
|
this.agentsContext = context === 'openclaw' ? 'openclaw' : 'codex';
|
|
220
230
|
if (this.agentsContext === 'openclaw') {
|
|
221
231
|
this.agentsModalTitle = tr('modal.agents.title.openclaw', 'OpenClaw AGENTS.md 编辑器');
|
|
@@ -700,6 +710,8 @@ export function createAgentsMethods(options = {}) {
|
|
|
700
710
|
}
|
|
701
711
|
} else if (this.agentsContext === 'openclaw') {
|
|
702
712
|
action = 'apply-openclaw-agents-file';
|
|
713
|
+
} else if (this.agentsContext === 'opencode') {
|
|
714
|
+
action = 'apply-opencode-agents-file';
|
|
703
715
|
} else if (this.agentsContext === 'openclaw-workspace') {
|
|
704
716
|
action = 'apply-openclaw-workspace-file';
|
|
705
717
|
params.fileName = this.agentsWorkspaceFileName;
|
|
@@ -716,7 +728,11 @@ export function createAgentsMethods(options = {}) {
|
|
|
716
728
|
? this.t('toast.agents.saved.workspace', { name: this.agentsWorkspaceFileName || '' }).replace(/:\s*$/, '')
|
|
717
729
|
: (this.agentsContext === 'claude-project'
|
|
718
730
|
? this.t('toast.agents.saved.claudeProject')
|
|
719
|
-
: (this.agentsContext === 'openclaw'
|
|
731
|
+
: (this.agentsContext === 'openclaw'
|
|
732
|
+
? this.t('toast.agents.saved.openclaw')
|
|
733
|
+
: (this.agentsContext === 'opencode'
|
|
734
|
+
? this.t('toast.agents.saved.opencode')
|
|
735
|
+
: this.t('toast.agents.saved.agents'))));
|
|
720
736
|
this.showMessage(successLabel, 'success');
|
|
721
737
|
if (this.mainTab === 'prompts') {
|
|
722
738
|
this.loadPromptsContent();
|
|
@@ -987,7 +1003,7 @@ export function createAgentsMethods(options = {}) {
|
|
|
987
1003
|
},
|
|
988
1004
|
|
|
989
1005
|
switchPromptsSubTab(subTab) {
|
|
990
|
-
const normalized = subTab === 'claude-project' || subTab === 'system' ? subTab : 'codex';
|
|
1006
|
+
const normalized = subTab === 'claude-project' || subTab === 'system' || subTab === 'opencode' ? subTab : 'codex';
|
|
991
1007
|
if (normalized === 'claude-project' && !this.projectPathOptions.length && !this.projectPathOptionsLoading) {
|
|
992
1008
|
this.loadProjectPathOptions();
|
|
993
1009
|
}
|
|
@@ -1035,6 +1051,8 @@ export function createAgentsMethods(options = {}) {
|
|
|
1035
1051
|
if (projectPath) {
|
|
1036
1052
|
rpcParams.baseDir = projectPath;
|
|
1037
1053
|
}
|
|
1054
|
+
} else if (subTab === 'opencode') {
|
|
1055
|
+
action = 'get-opencode-agents-file';
|
|
1038
1056
|
} else {
|
|
1039
1057
|
action = 'get-agents-file';
|
|
1040
1058
|
}
|
|
@@ -1051,7 +1069,7 @@ export function createAgentsMethods(options = {}) {
|
|
|
1051
1069
|
this.agentsPath = res.path || '';
|
|
1052
1070
|
this.agentsExists = !!res.exists;
|
|
1053
1071
|
this.agentsLineEnding = res.lineEnding === '\r\n' ? '\r\n' : '\n';
|
|
1054
|
-
this.agentsContext = subTab === 'claude-project' ? 'claude-project' : 'codex';
|
|
1072
|
+
this.agentsContext = subTab === 'claude-project' ? 'claude-project' : (subTab === 'opencode' ? 'opencode' : 'codex');
|
|
1055
1073
|
} catch (e) {
|
|
1056
1074
|
if (!isLatestRequestToken(this, '_agentsOpenRequestToken', requestToken)) {
|
|
1057
1075
|
return;
|
|
@@ -732,8 +732,8 @@
|
|
|
732
732
|
this.invalidateSessionTimelineMeasurementCache();
|
|
733
733
|
},
|
|
734
734
|
|
|
735
|
-
async loadMoreSessionMessages() {
|
|
736
|
-
return loadMoreSessionMessagesHelper.call(this);
|
|
735
|
+
async loadMoreSessionMessages(stepSize) {
|
|
736
|
+
return loadMoreSessionMessagesHelper.call(this, stepSize);
|
|
737
737
|
},
|
|
738
738
|
|
|
739
739
|
suspendSessionTabRender() {
|
|
@@ -55,6 +55,7 @@ export function createPiConfigMethods({ api: apiClient }) {
|
|
|
55
55
|
: '';
|
|
56
56
|
const updates = { defaultProvider: providerId };
|
|
57
57
|
if (firstModel) updates.defaultModel = firstModel;
|
|
58
|
+
else updates.defaultModel = '';
|
|
58
59
|
try {
|
|
59
60
|
const result = await apiClient('write-pi-settings', updates);
|
|
60
61
|
if (result && result.error) throw new Error(result.error);
|
|
@@ -126,6 +127,11 @@ export function createPiConfigMethods({ api: apiClient }) {
|
|
|
126
127
|
this.messageType = 'error';
|
|
127
128
|
return;
|
|
128
129
|
}
|
|
130
|
+
if (!Array.isArray(merged.models) || merged.models.length === 0) {
|
|
131
|
+
this.message = '请至少导入或输入一个模型';
|
|
132
|
+
this.messageType = 'error';
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
129
135
|
const providerId = isNew ? this.derivePiProviderId(baseUrl) : editor.id;
|
|
130
136
|
if (isNew) {
|
|
131
137
|
merged.id = providerId;
|
|
@@ -207,6 +213,7 @@ export function createPiConfigMethods({ api: apiClient }) {
|
|
|
207
213
|
startPiProviderDraft(tpl) {
|
|
208
214
|
const template = isPiPlainObject(tpl) ? tpl : {};
|
|
209
215
|
this.resetPiEditorTransientState();
|
|
216
|
+
this.showAddPiProviderModal = false;
|
|
210
217
|
this.editingPiProvider = {
|
|
211
218
|
id: '',
|
|
212
219
|
isNew: true,
|
|
@@ -350,6 +357,8 @@ export function createPiConfigMethods({ api: apiClient }) {
|
|
|
350
357
|
const wasNew = !!editor.isNew;
|
|
351
358
|
this.resetPiProviderEditing();
|
|
352
359
|
if (wasNew) this.piSelectedProviderTemplate = '';
|
|
360
|
+
this.showAddPiProviderModal = false;
|
|
361
|
+
this.piProviderPickerQuery = '';
|
|
353
362
|
},
|
|
354
363
|
removePiProviderModel(index) {
|
|
355
364
|
if (!this.editingPiProvider) return;
|
|
@@ -544,7 +553,7 @@ export function createPiConfigMethods({ api: apiClient }) {
|
|
|
544
553
|
if (merged.baseUrl === undefined) merged.baseUrl = values.baseUrl || '';
|
|
545
554
|
if (merged.api === undefined) merged.api = values.api || '';
|
|
546
555
|
if (merged.apiKey === undefined) merged.apiKey = values.apiKey || '';
|
|
547
|
-
|
|
556
|
+
merged.models = mapModels(merged.models !== undefined ? merged.models : values.models);
|
|
548
557
|
if (isPiPlainObject(orig.headers)) merged.headers = orig.headers;
|
|
549
558
|
if (typeof orig.title === 'string') merged.title = orig.title;
|
|
550
559
|
else if (typeof orig.name === 'string') merged.name = orig.name;
|
|
@@ -63,6 +63,7 @@ function normalizePromptsSubTab(value) {
|
|
|
63
63
|
const normalized = typeof value === 'string' ? value.trim().toLowerCase() : '';
|
|
64
64
|
if (normalized === 'claude-project') return normalized;
|
|
65
65
|
if (normalized === 'system') return normalized;
|
|
66
|
+
if (normalized === 'opencode') return normalized;
|
|
66
67
|
return 'codex';
|
|
67
68
|
}
|
|
68
69
|
|
|
@@ -229,6 +229,7 @@ const en = Object.freeze({
|
|
|
229
229
|
'subtitle.settings': 'Manage downloads, directories, and trash.',
|
|
230
230
|
'subtitle.prompts': 'Edit AGENTS.md and CLAUDE.md.',
|
|
231
231
|
'prompts.subTab.codex': 'AGENTS.md (Codex)',
|
|
232
|
+
'prompts.subTab.opencode': 'AGENTS.md (OpenCode)',
|
|
232
233
|
'prompts.subTab.project': 'CLAUDE.md',
|
|
233
234
|
'prompts.subTab.system': 'System Prompt (Pi)',
|
|
234
235
|
'prompts.subTab.presets': 'Preset pool',
|
|
@@ -439,6 +440,7 @@ const en = Object.freeze({
|
|
|
439
440
|
'toast.agents.saved.agents': 'AGENTS.md saved',
|
|
440
441
|
'toast.agents.saved.claudeProject': 'Project CLAUDE.md saved',
|
|
441
442
|
'toast.agents.saved.openclaw': 'OpenClaw AGENTS.md saved',
|
|
443
|
+
'toast.agents.saved.opencode': 'OpenCode AGENTS.md saved',
|
|
442
444
|
'toast.agents.saved.workspace': 'Workspace file saved: {name}',
|
|
443
445
|
'toast.delete.ok': 'Deleted',
|
|
444
446
|
'toast.delete.fail': 'Delete failed',
|
|
@@ -961,6 +963,7 @@ const en = Object.freeze({
|
|
|
961
963
|
'config.agents.open': 'Open AGENTS.md',
|
|
962
964
|
'modal.agents.title.default': 'AGENTS.md editor',
|
|
963
965
|
'modal.agents.title.openclaw': 'OpenClaw AGENTS.md editor',
|
|
966
|
+
'modal.agents.title.opencode': 'OpenCode AGENTS.md editor',
|
|
964
967
|
'modal.agents.hint.default': 'Saved content will be written to AGENTS.md (next to config.toml).',
|
|
965
968
|
'modal.agents.title.claudeProject': 'Project CLAUDE.md: {path}',
|
|
966
969
|
'modal.agents.hint.claudeProject': 'Saved content will be written to CLAUDE.md in: {path}',
|
|
@@ -969,6 +972,7 @@ const en = Object.freeze({
|
|
|
969
972
|
'modal.agents.contentLabel.claudeProject': 'CLAUDE.md content',
|
|
970
973
|
'modal.agents.placeholder.claudeProject': 'Edit CLAUDE.md here',
|
|
971
974
|
'modal.agents.hint.openclaw': 'Saved content will be written to OpenClaw workspace AGENTS.md.',
|
|
975
|
+
'modal.agents.hint.opencode': 'Saved content will be written to ~/.config/opencode/AGENTS.md.',
|
|
972
976
|
'modal.agents.title.openclawWorkspaceFile': 'OpenClaw workspace file: {fileName}',
|
|
973
977
|
'modal.agents.hint.openclawWorkspaceFile': 'Saved content will be written to OpenClaw workspace {fileName}.',
|
|
974
978
|
'config.url.unset': 'URL not set',
|
|
@@ -1362,9 +1366,9 @@ const en = Object.freeze({
|
|
|
1362
1366
|
'pi.providers.json.previewTitle': 'Preview',
|
|
1363
1367
|
'pi.providers.json.editTitle': 'Edit JSON',
|
|
1364
1368
|
'pi.files.title': 'File JSON',
|
|
1365
|
-
'pi.files.desc': 'View and edit Pi settings.json and models.json in full; JSON validity is checked before saving and invalid content is never written.',
|
|
1366
1369
|
'pi.files.settingsTitle': 'settings.json (active settings)',
|
|
1367
1370
|
'pi.files.modelsTitle': 'models.json (providers and models)',
|
|
1371
|
+
'pi.files.modelsHint': 'Merged automatically from the provider management above; prefer editing providers there instead.',
|
|
1368
1372
|
'pi.history.apply': 'Apply this record',
|
|
1369
1373
|
'pi.history.applied': 'History record applied',
|
|
1370
1374
|
'pi.history.applyFailed': 'Failed to apply history record',
|
|
@@ -230,6 +230,7 @@ const ja = Object.freeze({
|
|
|
230
230
|
'subtitle.settings': 'ダウンロード・ディレクトリ・ゴミ箱の管理。',
|
|
231
231
|
'subtitle.prompts': 'AGENTS.md と CLAUDE.md を編集。',
|
|
232
232
|
'prompts.subTab.codex': 'AGENTS.md (Codex)',
|
|
233
|
+
'prompts.subTab.opencode': 'AGENTS.md (OpenCode)',
|
|
233
234
|
'prompts.subTab.project': 'CLAUDE.md',
|
|
234
235
|
'prompts.subTab.system': 'System Prompt (Pi)',
|
|
235
236
|
'prompts.subTab.presets': 'プリセット',
|
|
@@ -441,6 +442,7 @@ const ja = Object.freeze({
|
|
|
441
442
|
'toast.agents.saved.agents': 'AGENTS.md 保存しました',
|
|
442
443
|
'toast.agents.saved.claudeProject': 'プロジェクト CLAUDE.md 保存しました',
|
|
443
444
|
'toast.agents.saved.openclaw': 'OpenClaw AGENTS.md 保存しました',
|
|
445
|
+
'toast.agents.saved.opencode': 'OpenCode AGENTS.md 保存しました',
|
|
444
446
|
'toast.agents.saved.workspace': 'ワークスペースファイル保存済み: {name}',
|
|
445
447
|
'toast.delete.ok': '削除しました',
|
|
446
448
|
'toast.delete.fail': '削除に失敗しました',
|
|
@@ -964,6 +966,7 @@ const ja = Object.freeze({
|
|
|
964
966
|
'config.agents.open': 'AGENTS.md を開く',
|
|
965
967
|
'modal.agents.title.default': 'AGENTS.md エディタ',
|
|
966
968
|
'modal.agents.title.openclaw': 'OpenClaw AGENTS.md エディタ',
|
|
969
|
+
'modal.agents.title.opencode': 'OpenCode AGENTS.md エディタ',
|
|
967
970
|
'modal.agents.hint.default': '保存すると対象の AGENTS.md(config.toml と同階層)に書き込まれます。',
|
|
968
971
|
'modal.agents.title.claudeProject': 'プロジェクト CLAUDE.md: {path}',
|
|
969
972
|
'modal.agents.hint.claudeProject': '保存するとプロジェクトの CLAUDE.md に書き込まれます: {path}',
|
|
@@ -972,6 +975,7 @@ const ja = Object.freeze({
|
|
|
972
975
|
'modal.agents.contentLabel.claudeProject': 'CLAUDE.md 内容',
|
|
973
976
|
'modal.agents.placeholder.claudeProject': 'CLAUDE.md を編集',
|
|
974
977
|
'modal.agents.hint.openclaw': '保存すると OpenClaw Workspace の AGENTS.md に書き込まれます。',
|
|
978
|
+
'modal.agents.hint.opencode': '保存すると ~/.config/opencode/AGENTS.md に書き込まれます。',
|
|
975
979
|
'modal.agents.title.openclawWorkspaceFile': 'OpenClaw ワークスペースファイル: {fileName}',
|
|
976
980
|
'modal.agents.hint.openclawWorkspaceFile': '保存すると OpenClaw Workspace の {fileName} に書き込まれます。',
|
|
977
981
|
'config.url.unset': 'URL 未設定',
|
|
@@ -1363,9 +1367,9 @@ const ja = Object.freeze({
|
|
|
1363
1367
|
'pi.providers.json.previewTitle': 'プレビュー',
|
|
1364
1368
|
'pi.providers.json.editTitle': 'JSON を編集',
|
|
1365
1369
|
'pi.files.title': 'ファイル JSON',
|
|
1366
|
-
'pi.files.desc': 'Pi の settings.json と models.json を全文表示して直接編集します。保存前に JSON の正当性を検証し、不正な内容は書き込みません。',
|
|
1367
1370
|
'pi.files.settingsTitle': 'settings.json(有効な設定)',
|
|
1368
1371
|
'pi.files.modelsTitle': 'models.json(プロバイダーとモデル)',
|
|
1372
|
+
'pi.files.modelsHint': '上のプロバイダー管理から自動的にマージされます。プロバイダーの変更は上の管理画面を優先してください。',
|
|
1369
1373
|
'pi.history.apply': 'この履歴を適用',
|
|
1370
1374
|
'pi.history.applied': '履歴を適用しました',
|
|
1371
1375
|
'pi.history.applyFailed': '履歴の適用に失敗しました',
|
|
@@ -247,6 +247,7 @@ const vi = Object.freeze({
|
|
|
247
247
|
'subtitle.settings': 'Quản lý tải xuống, thư mục và dữ liệu.',
|
|
248
248
|
'subtitle.prompts': 'Chỉnh sửa AGENTS.md và CLAUDE.md.',
|
|
249
249
|
'prompts.subTab.codex': 'AGENTS.md (Codex)',
|
|
250
|
+
'prompts.subTab.opencode': 'AGENTS.md (OpenCode)',
|
|
250
251
|
'prompts.subTab.project': 'CLAUDE.md',
|
|
251
252
|
'prompts.subTab.system': 'System Prompt (Pi)',
|
|
252
253
|
'prompts.subTab.presets': 'Kho preset',
|
|
@@ -401,6 +402,7 @@ const vi = Object.freeze({
|
|
|
401
402
|
'toast.agents.saved.agents': 'AGENTS.md đã lưu',
|
|
402
403
|
'toast.agents.saved.claudeProject': 'CLAUDE.md dự án đã lưu',
|
|
403
404
|
'toast.agents.saved.openclaw': 'OpenClaw AGENTS.md đã lưu',
|
|
405
|
+
'toast.agents.saved.opencode': 'OpenCode AGENTS.md đã lưu',
|
|
404
406
|
'toast.agents.saved.workspace': 'Tệp workspace đã lưu: {name}',
|
|
405
407
|
'toast.delete.ok': 'Đã xóa',
|
|
406
408
|
'toast.delete.fail': 'Xóa thất bại',
|
|
@@ -1073,8 +1075,10 @@ const vi = Object.freeze({
|
|
|
1073
1075
|
'config.agents.open': 'Mở AGENTS.md',
|
|
1074
1076
|
'modal.agents.title.default': 'Trình soạn thảo AGENTS.md',
|
|
1075
1077
|
'modal.agents.title.openclaw': 'Trình soạn thảo AGENTS.md OpenClaw',
|
|
1078
|
+
'modal.agents.title.opencode': 'Trình soạn thảo AGENTS.md OpenCode',
|
|
1076
1079
|
'modal.agents.hint.default': 'Nội dung đã lưu sẽ được ghi vào AGENTS.md (cạnh config.toml).',
|
|
1077
1080
|
'modal.agents.hint.openclaw': 'Nội dung đã lưu sẽ được ghi vào AGENTS.md không gian làm việc OpenClaw.',
|
|
1081
|
+
'modal.agents.hint.opencode': 'Nội dung đã lưu sẽ được ghi vào ~/.config/opencode/AGENTS.md.',
|
|
1078
1082
|
'modal.agents.title.openclawWorkspaceFile': 'File không gian làm việc OpenClaw: {fileName}',
|
|
1079
1083
|
'modal.agents.hint.openclawWorkspaceFile': 'Nội dung đã lưu sẽ được ghi vào OpenClaw {fileName}.',
|
|
1080
1084
|
'config.url.unset': 'URL chưa đặt',
|
|
@@ -1331,9 +1335,9 @@ const vi = Object.freeze({
|
|
|
1331
1335
|
'pi.providers.json.previewTitle': 'Xem trước',
|
|
1332
1336
|
'pi.providers.json.editTitle': 'Chỉnh sửa JSON',
|
|
1333
1337
|
'pi.files.title': 'JSON tập tin',
|
|
1334
|
-
'pi.files.desc': 'Hiển thị đầy đủ và chỉnh sửa trực tiếp settings.json và models.json của Pi; kiểm tra tính hợp lệ của JSON trước khi lưu, nội dung không hợp lệ sẽ không được ghi.',
|
|
1335
1338
|
'pi.files.settingsTitle': 'settings.json (cài đặt đang dùng)',
|
|
1336
1339
|
'pi.files.modelsTitle': 'models.json (nhà cung cấp và mô hình)',
|
|
1340
|
+
'pi.files.modelsHint': 'Được hợp nhất tự động từ phần quản lý nhà cung cấp phía trên; hãy ưu tiên chỉnh sửa ở đó.',
|
|
1337
1341
|
'pi.history.apply': 'Áp dụng bản ghi này',
|
|
1338
1342
|
'pi.history.applied': 'Đã áp dụng lịch sử',
|
|
1339
1343
|
'pi.history.applyFailed': 'Áp dụng lịch sử thất bại',
|
|
@@ -229,6 +229,7 @@ const zhTw = Object.freeze({
|
|
|
229
229
|
'subtitle.settings': '管理下載、目錄與回收站。',
|
|
230
230
|
'subtitle.prompts': '編輯 AGENTS.md 與 CLAUDE.md。',
|
|
231
231
|
'prompts.subTab.codex': 'AGENTS.md (Codex)',
|
|
232
|
+
'prompts.subTab.opencode': 'AGENTS.md (OpenCode)',
|
|
232
233
|
'prompts.subTab.project': 'CLAUDE.md',
|
|
233
234
|
'prompts.subTab.system': 'System Prompt (Pi)',
|
|
234
235
|
'prompts.subTab.presets': '預設池',
|
|
@@ -439,6 +440,7 @@ const zhTw = Object.freeze({
|
|
|
439
440
|
'toast.agents.saved.agents': 'AGENTS.md 已保存',
|
|
440
441
|
'toast.agents.saved.claudeProject': '專案 CLAUDE.md 已保存',
|
|
441
442
|
'toast.agents.saved.openclaw': 'OpenClaw AGENTS.md 已保存',
|
|
443
|
+
'toast.agents.saved.opencode': 'OpenCode AGENTS.md 已保存',
|
|
442
444
|
'toast.agents.saved.workspace': '工作區文件已保存: {name}',
|
|
443
445
|
'toast.delete.ok': '已刪除',
|
|
444
446
|
'toast.delete.fail': '刪除失敗',
|
|
@@ -960,6 +962,7 @@ const zhTw = Object.freeze({
|
|
|
960
962
|
'config.agents.open': '打開 AGENTS.md',
|
|
961
963
|
'modal.agents.title.default': 'AGENTS.md 編輯器',
|
|
962
964
|
'modal.agents.title.openclaw': 'OpenClaw AGENTS.md 編輯器',
|
|
965
|
+
'modal.agents.title.opencode': 'OpenCode AGENTS.md 編輯器',
|
|
963
966
|
'modal.agents.hint.default': '保存後會寫入目標 AGENTS.md(與 config.toml 同級)。',
|
|
964
967
|
'modal.agents.title.claudeProject': '專案 CLAUDE.md: {path}',
|
|
965
968
|
'modal.agents.hint.claudeProject': '保存後會寫入專案目錄下的 CLAUDE.md: {path}',
|
|
@@ -968,6 +971,7 @@ const zhTw = Object.freeze({
|
|
|
968
971
|
'modal.agents.contentLabel.claudeProject': 'CLAUDE.md 內容',
|
|
969
972
|
'modal.agents.placeholder.claudeProject': '在這裡編輯 CLAUDE.md',
|
|
970
973
|
'modal.agents.hint.openclaw': '保存後會寫入 OpenClaw Workspace 下的 AGENTS.md。',
|
|
974
|
+
'modal.agents.hint.opencode': '儲存後會寫入 ~/.config/opencode/AGENTS.md。',
|
|
971
975
|
'modal.agents.title.openclawWorkspaceFile': 'OpenClaw 工作區文件: {fileName}',
|
|
972
976
|
'modal.agents.hint.openclawWorkspaceFile': '保存後會寫入 OpenClaw Workspace 下的 {fileName}。',
|
|
973
977
|
'config.url.unset': '未設 URL',
|
|
@@ -1360,9 +1364,9 @@ const zhTw = Object.freeze({
|
|
|
1360
1364
|
'pi.providers.json.previewTitle': '預覽',
|
|
1361
1365
|
'pi.providers.json.editTitle': '編輯 JSON',
|
|
1362
1366
|
'pi.files.title': '檔案 JSON',
|
|
1363
|
-
'pi.files.desc': '完整展示並直接編輯 Pi 的 settings.json 與 models.json;儲存前校驗 JSON 合法性,非法內容不會寫入。',
|
|
1364
1367
|
'pi.files.settingsTitle': 'settings.json(生效設定)',
|
|
1365
1368
|
'pi.files.modelsTitle': 'models.json(供應商與模型)',
|
|
1369
|
+
'pi.files.modelsHint': '由上方供應商管理自動合併生成;調整供應商請優先使用上方的供應商管理。',
|
|
1366
1370
|
'pi.history.apply': '套用此紀錄',
|
|
1367
1371
|
'pi.history.applied': '已套用歷史紀錄',
|
|
1368
1372
|
'pi.history.applyFailed': '套用歷史紀錄失敗',
|
|
@@ -229,6 +229,7 @@ const zh = Object.freeze({
|
|
|
229
229
|
'subtitle.settings': '管理下载、目录与回收站。',
|
|
230
230
|
'subtitle.prompts': '编辑 AGENTS.md 与 CLAUDE.md。',
|
|
231
231
|
'prompts.subTab.codex': 'AGENTS.md (Codex)',
|
|
232
|
+
'prompts.subTab.opencode': 'AGENTS.md (OpenCode)',
|
|
232
233
|
'prompts.subTab.project': 'CLAUDE.md',
|
|
233
234
|
'prompts.subTab.system': 'System Prompt (Pi)',
|
|
234
235
|
'prompts.subTab.presets': '预设池',
|
|
@@ -439,6 +440,7 @@ const zh = Object.freeze({
|
|
|
439
440
|
'toast.agents.saved.agents': 'AGENTS.md 已保存',
|
|
440
441
|
'toast.agents.saved.claudeProject': '项目 CLAUDE.md 已保存',
|
|
441
442
|
'toast.agents.saved.openclaw': 'OpenClaw AGENTS.md 已保存',
|
|
443
|
+
'toast.agents.saved.opencode': 'OpenCode AGENTS.md 已保存',
|
|
442
444
|
'toast.agents.saved.workspace': '工作区文件已保存: {name}',
|
|
443
445
|
'toast.delete.ok': '已删除',
|
|
444
446
|
'toast.delete.fail': '删除失败',
|
|
@@ -960,6 +962,7 @@ const zh = Object.freeze({
|
|
|
960
962
|
'config.agents.open': '打开 AGENTS.md',
|
|
961
963
|
'modal.agents.title.default': 'AGENTS.md 编辑器',
|
|
962
964
|
'modal.agents.title.openclaw': 'OpenClaw AGENTS.md 编辑器',
|
|
965
|
+
'modal.agents.title.opencode': 'OpenCode AGENTS.md 编辑器',
|
|
963
966
|
'modal.agents.hint.default': '保存后会写入目标 AGENTS.md(与 config.toml 同级)。',
|
|
964
967
|
'modal.agents.title.claudeProject': '项目 CLAUDE.md: {path}',
|
|
965
968
|
'modal.agents.hint.claudeProject': '保存后会写入项目目录下的 CLAUDE.md: {path}',
|
|
@@ -968,6 +971,7 @@ const zh = Object.freeze({
|
|
|
968
971
|
'modal.agents.contentLabel.claudeProject': 'CLAUDE.md 内容',
|
|
969
972
|
'modal.agents.placeholder.claudeProject': '在这里编辑 CLAUDE.md',
|
|
970
973
|
'modal.agents.hint.openclaw': 'Workspace / AGENTS.md',
|
|
974
|
+
'modal.agents.hint.opencode': '保存后会写入 ~/.config/opencode/AGENTS.md。',
|
|
971
975
|
'modal.agents.title.openclawWorkspaceFile': 'OpenClaw 工作区文件: {fileName}',
|
|
972
976
|
'modal.agents.hint.openclawWorkspaceFile': 'Workspace / {fileName}',
|
|
973
977
|
'config.url.unset': '未设 URL',
|
|
@@ -1360,9 +1364,9 @@ const zh = Object.freeze({
|
|
|
1360
1364
|
'pi.providers.json.previewTitle': '预览',
|
|
1361
1365
|
'pi.providers.json.editTitle': '编辑 JSON',
|
|
1362
1366
|
'pi.files.title': '文件 JSON',
|
|
1363
|
-
'pi.files.desc': '完整展示并直接编辑 Pi 的 settings.json 与 models.json;保存前校验 JSON 合法性,非法内容不会写入。',
|
|
1364
1367
|
'pi.files.settingsTitle': 'settings.json(生效设置)',
|
|
1365
1368
|
'pi.files.modelsTitle': 'models.json(供应商与模型)',
|
|
1369
|
+
'pi.files.modelsHint': '由上方供应商管理自动合并生成;调整供应商请优先使用上方的供应商管理。',
|
|
1366
1370
|
'pi.history.apply': '应用此记录',
|
|
1367
1371
|
'pi.history.applied': '已应用历史记录',
|
|
1368
1372
|
'pi.history.applyFailed': '应用历史记录失败',
|
|
@@ -49,19 +49,24 @@
|
|
|
49
49
|
</div>
|
|
50
50
|
<div class="card-trailing">
|
|
51
51
|
<span v-if="piActiveProvider === providerId" class="pill configured">{{ t('pi.providers.active') }}</span>
|
|
52
|
-
<button v-else type="button" class="btn-tool" @click.stop="switchPiActiveProvider(providerId)" :disabled="!isToolConfigWriteAllowed('pi') || piSaving">{{ t('pi.providers.setActive') }}</button>
|
|
52
|
+
<button v-else type="button" class="btn-tool btn-tool-compact" @click.stop="switchPiActiveProvider(providerId)" :disabled="!isToolConfigWriteAllowed('pi') || piSaving">{{ t('pi.providers.setActive') }}</button>
|
|
53
53
|
</div>
|
|
54
54
|
</div>
|
|
55
55
|
</div>
|
|
56
|
-
<div v-if="!piProviderIds.length" class="
|
|
56
|
+
<div v-if="!piProviderIds.length" class="empty-state">
|
|
57
|
+
<div class="empty-state-title">{{ t('pi.providers.empty') }}</div>
|
|
58
|
+
</div>
|
|
57
59
|
</section>
|
|
58
60
|
|
|
59
|
-
<section class="selector-section">
|
|
61
|
+
<section class="selector-section pi-file-section">
|
|
60
62
|
<div class="selector-header">
|
|
61
|
-
<span class="selector-title">{{ t('pi.files.
|
|
63
|
+
<span class="selector-title">{{ t('pi.files.settingsTitle') }}</span>
|
|
64
|
+
<div class="selector-actions">
|
|
65
|
+
<button type="button" class="btn-tool btn-tool-compact" @click="openPiConfigHistory('settings')" :disabled="piHistoryLoading">{{ t('common.history') }}</button>
|
|
66
|
+
<button type="button" class="btn-tool btn-tool-compact" @click="savePiSettingsJson" :disabled="!isToolConfigWriteAllowed('pi') || piSaving || piFileJsonSaving || !!piSettingsJsonError">{{ t('common.save') }}</button>
|
|
67
|
+
</div>
|
|
62
68
|
</div>
|
|
63
|
-
<div class="config-template-hint">{{ t('pi.
|
|
64
|
-
<label class="form-label">{{ t('pi.files.settingsTitle') }}</label>
|
|
69
|
+
<div class="config-template-hint">{{ t('pi.providers.targetFile', { path: '~/.pi/agent/settings.json' }) }}</div>
|
|
65
70
|
<textarea
|
|
66
71
|
class="template-textarea config-json-editor"
|
|
67
72
|
v-model="piSettingsJsonDraft"
|
|
@@ -71,10 +76,6 @@
|
|
|
71
76
|
@input="piSettingsJsonInput"
|
|
72
77
|
placeholder="{}"></textarea>
|
|
73
78
|
<p v-if="piSettingsJsonError" class="config-template-hint error-text">{{ piSettingsJsonError }}</p>
|
|
74
|
-
<div class="settings-tab-actions">
|
|
75
|
-
<button type="button" class="btn-tool" @click="savePiSettingsJson" :disabled="!isToolConfigWriteAllowed('pi') || piSaving || piFileJsonSaving || !!piSettingsJsonError">{{ t('common.save') }}</button>
|
|
76
|
-
<button type="button" class="btn-mini" @click="openPiConfigHistory('settings')" :disabled="piHistoryLoading">{{ t('common.history') }}</button>
|
|
77
|
-
</div>
|
|
78
79
|
<details v-if="piHistoryTarget === 'settings'" class="prompt-history-panel" open>
|
|
79
80
|
<summary class="prompt-history-summary">
|
|
80
81
|
<span>{{ t('common.history') }}</span>
|
|
@@ -96,7 +97,18 @@
|
|
|
96
97
|
</div>
|
|
97
98
|
</div>
|
|
98
99
|
</details>
|
|
99
|
-
|
|
100
|
+
</section>
|
|
101
|
+
|
|
102
|
+
<section class="selector-section pi-file-section">
|
|
103
|
+
<div class="selector-header">
|
|
104
|
+
<span class="selector-title">{{ t('pi.files.modelsTitle') }}</span>
|
|
105
|
+
<div class="selector-actions">
|
|
106
|
+
<button type="button" class="btn-tool btn-tool-compact" @click="openPiConfigHistory('models')" :disabled="piHistoryLoading">{{ t('common.history') }}</button>
|
|
107
|
+
<button type="button" class="btn-tool btn-tool-compact" @click="savePiModelsJson" :disabled="!isToolConfigWriteAllowed('pi') || piSaving || piFileJsonSaving || !!piModelsJsonError">{{ t('common.save') }}</button>
|
|
108
|
+
</div>
|
|
109
|
+
</div>
|
|
110
|
+
<div class="config-template-hint">{{ t('pi.files.modelsHint') }}</div>
|
|
111
|
+
<div class="config-template-hint">{{ t('pi.providers.targetFile', { path: '~/.pi/agent/models.json' }) }}</div>
|
|
100
112
|
<textarea
|
|
101
113
|
class="template-textarea config-json-editor"
|
|
102
114
|
v-model="piModelsJsonDraft"
|
|
@@ -106,10 +118,6 @@
|
|
|
106
118
|
@input="piModelsJsonInput"
|
|
107
119
|
placeholder="{}"></textarea>
|
|
108
120
|
<p v-if="piModelsJsonError" class="config-template-hint error-text">{{ piModelsJsonError }}</p>
|
|
109
|
-
<div class="settings-tab-actions">
|
|
110
|
-
<button type="button" class="btn-tool" @click="savePiModelsJson" :disabled="!isToolConfigWriteAllowed('pi') || piSaving || piFileJsonSaving || !!piModelsJsonError">{{ t('common.save') }}</button>
|
|
111
|
-
<button type="button" class="btn-mini" @click="openPiConfigHistory('models')" :disabled="piHistoryLoading">{{ t('common.history') }}</button>
|
|
112
|
-
</div>
|
|
113
121
|
<details v-if="piHistoryTarget === 'models'" class="prompt-history-panel" open>
|
|
114
122
|
<summary class="prompt-history-summary">
|
|
115
123
|
<span>{{ t('common.history') }}</span>
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
aria-labelledby="tab-prompts">
|
|
8
8
|
<div class="prompts-md-tabs" role="tablist" :aria-label="t('tab.prompts')">
|
|
9
9
|
<button type="button" :class="['prompts-md-tab', { active: promptsSubTab === 'codex' }]" role="tab" :aria-selected="promptsSubTab === 'codex'" @click="switchPromptsSubTab('codex')">{{ t('prompts.subTab.codex') }}</button>
|
|
10
|
+
<button type="button" :class="['prompts-md-tab', { active: promptsSubTab === 'opencode' }]" role="tab" :aria-selected="promptsSubTab === 'opencode'" @click="switchPromptsSubTab('opencode')">{{ t('prompts.subTab.opencode') }}</button>
|
|
10
11
|
<button type="button" :class="['prompts-md-tab', { active: promptsSubTab === 'claude-project' }]" role="tab" :aria-selected="promptsSubTab === 'claude-project'" @click="switchPromptsSubTab('claude-project')">{{ t('prompts.subTab.project') }}</button>
|
|
11
12
|
<button type="button" :class="['prompts-md-tab', { active: promptsSubTab === 'system' }]" role="tab" :aria-selected="promptsSubTab === 'system'" @click="switchPromptsSubTab('system')">{{ t('prompts.subTab.system') }}</button>
|
|
12
13
|
</div>
|
|
@@ -3268,7 +3268,7 @@ return function render(_ctx, _cache) {
|
|
|
3268
3268
|
: (_openBlock(), _createElementBlock("button", {
|
|
3269
3269
|
key: 1,
|
|
3270
3270
|
type: "button",
|
|
3271
|
-
class: "btn-tool",
|
|
3271
|
+
class: "btn-tool btn-tool-compact",
|
|
3272
3272
|
onClick: _withModifiers($event => (_ctx.switchPiActiveProvider(providerId)), ["stop"]),
|
|
3273
3273
|
disabled: !_ctx.isToolConfigWriteAllowed('pi') || _ctx.piSaving
|
|
3274
3274
|
}, _toDisplayString(_ctx.t('pi.providers.setActive')), 9 /* TEXT, PROPS */, ["onClick", "disabled"]))
|
|
@@ -3280,16 +3280,31 @@ return function render(_ctx, _cache) {
|
|
|
3280
3280
|
(!_ctx.piProviderIds.length)
|
|
3281
3281
|
? (_openBlock(), _createElementBlock("div", {
|
|
3282
3282
|
key: 1,
|
|
3283
|
-
class: "
|
|
3284
|
-
},
|
|
3283
|
+
class: "empty-state"
|
|
3284
|
+
}, [
|
|
3285
|
+
_createElementVNode("div", { class: "empty-state-title" }, _toDisplayString(_ctx.t('pi.providers.empty')), 1 /* TEXT */)
|
|
3286
|
+
]))
|
|
3285
3287
|
: _createCommentVNode("v-if", true)
|
|
3286
3288
|
]),
|
|
3287
|
-
_createElementVNode("section", { class: "selector-section" }, [
|
|
3289
|
+
_createElementVNode("section", { class: "selector-section pi-file-section" }, [
|
|
3288
3290
|
_createElementVNode("div", { class: "selector-header" }, [
|
|
3289
|
-
_createElementVNode("span", { class: "selector-title" }, _toDisplayString(_ctx.t('pi.files.
|
|
3291
|
+
_createElementVNode("span", { class: "selector-title" }, _toDisplayString(_ctx.t('pi.files.settingsTitle')), 1 /* TEXT */),
|
|
3292
|
+
_createElementVNode("div", { class: "selector-actions" }, [
|
|
3293
|
+
_createElementVNode("button", {
|
|
3294
|
+
type: "button",
|
|
3295
|
+
class: "btn-tool btn-tool-compact",
|
|
3296
|
+
onClick: $event => (_ctx.openPiConfigHistory('settings')),
|
|
3297
|
+
disabled: _ctx.piHistoryLoading
|
|
3298
|
+
}, _toDisplayString(_ctx.t('common.history')), 9 /* TEXT, PROPS */, ["onClick", "disabled"]),
|
|
3299
|
+
_createElementVNode("button", {
|
|
3300
|
+
type: "button",
|
|
3301
|
+
class: "btn-tool btn-tool-compact",
|
|
3302
|
+
onClick: _ctx.savePiSettingsJson,
|
|
3303
|
+
disabled: !_ctx.isToolConfigWriteAllowed('pi') || _ctx.piSaving || _ctx.piFileJsonSaving || !!_ctx.piSettingsJsonError
|
|
3304
|
+
}, _toDisplayString(_ctx.t('common.save')), 9 /* TEXT, PROPS */, ["onClick", "disabled"])
|
|
3305
|
+
])
|
|
3290
3306
|
]),
|
|
3291
|
-
_createElementVNode("div", { class: "config-template-hint" }, _toDisplayString(_ctx.t('pi.
|
|
3292
|
-
_createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('pi.files.settingsTitle')), 1 /* TEXT */),
|
|
3307
|
+
_createElementVNode("div", { class: "config-template-hint" }, _toDisplayString(_ctx.t('pi.providers.targetFile', { path: '~/.pi/agent/settings.json' })), 1 /* TEXT */),
|
|
3293
3308
|
_withDirectives(_createElementVNode("textarea", {
|
|
3294
3309
|
class: "template-textarea config-json-editor",
|
|
3295
3310
|
"onUpdate:modelValue": $event => ((_ctx.piSettingsJsonDraft) = $event),
|
|
@@ -3307,20 +3322,6 @@ return function render(_ctx, _cache) {
|
|
|
3307
3322
|
class: "config-template-hint error-text"
|
|
3308
3323
|
}, _toDisplayString(_ctx.piSettingsJsonError), 1 /* TEXT */))
|
|
3309
3324
|
: _createCommentVNode("v-if", true),
|
|
3310
|
-
_createElementVNode("div", { class: "settings-tab-actions" }, [
|
|
3311
|
-
_createElementVNode("button", {
|
|
3312
|
-
type: "button",
|
|
3313
|
-
class: "btn-tool",
|
|
3314
|
-
onClick: _ctx.savePiSettingsJson,
|
|
3315
|
-
disabled: !_ctx.isToolConfigWriteAllowed('pi') || _ctx.piSaving || _ctx.piFileJsonSaving || !!_ctx.piSettingsJsonError
|
|
3316
|
-
}, _toDisplayString(_ctx.t('common.save')), 9 /* TEXT, PROPS */, ["onClick", "disabled"]),
|
|
3317
|
-
_createElementVNode("button", {
|
|
3318
|
-
type: "button",
|
|
3319
|
-
class: "btn-mini",
|
|
3320
|
-
onClick: $event => (_ctx.openPiConfigHistory('settings')),
|
|
3321
|
-
disabled: _ctx.piHistoryLoading
|
|
3322
|
-
}, _toDisplayString(_ctx.t('common.history')), 9 /* TEXT, PROPS */, ["onClick", "disabled"])
|
|
3323
|
-
]),
|
|
3324
3325
|
(_ctx.piHistoryTarget === 'settings')
|
|
3325
3326
|
? (_openBlock(), _createElementBlock("details", {
|
|
3326
3327
|
key: 1,
|
|
@@ -3386,8 +3387,28 @@ return function render(_ctx, _cache) {
|
|
|
3386
3387
|
: _createCommentVNode("v-if", true)
|
|
3387
3388
|
])
|
|
3388
3389
|
]))
|
|
3389
|
-
: _createCommentVNode("v-if", true)
|
|
3390
|
-
|
|
3390
|
+
: _createCommentVNode("v-if", true)
|
|
3391
|
+
]),
|
|
3392
|
+
_createElementVNode("section", { class: "selector-section pi-file-section" }, [
|
|
3393
|
+
_createElementVNode("div", { class: "selector-header" }, [
|
|
3394
|
+
_createElementVNode("span", { class: "selector-title" }, _toDisplayString(_ctx.t('pi.files.modelsTitle')), 1 /* TEXT */),
|
|
3395
|
+
_createElementVNode("div", { class: "selector-actions" }, [
|
|
3396
|
+
_createElementVNode("button", {
|
|
3397
|
+
type: "button",
|
|
3398
|
+
class: "btn-tool btn-tool-compact",
|
|
3399
|
+
onClick: $event => (_ctx.openPiConfigHistory('models')),
|
|
3400
|
+
disabled: _ctx.piHistoryLoading
|
|
3401
|
+
}, _toDisplayString(_ctx.t('common.history')), 9 /* TEXT, PROPS */, ["onClick", "disabled"]),
|
|
3402
|
+
_createElementVNode("button", {
|
|
3403
|
+
type: "button",
|
|
3404
|
+
class: "btn-tool btn-tool-compact",
|
|
3405
|
+
onClick: _ctx.savePiModelsJson,
|
|
3406
|
+
disabled: !_ctx.isToolConfigWriteAllowed('pi') || _ctx.piSaving || _ctx.piFileJsonSaving || !!_ctx.piModelsJsonError
|
|
3407
|
+
}, _toDisplayString(_ctx.t('common.save')), 9 /* TEXT, PROPS */, ["onClick", "disabled"])
|
|
3408
|
+
])
|
|
3409
|
+
]),
|
|
3410
|
+
_createElementVNode("div", { class: "config-template-hint" }, _toDisplayString(_ctx.t('pi.files.modelsHint')), 1 /* TEXT */),
|
|
3411
|
+
_createElementVNode("div", { class: "config-template-hint" }, _toDisplayString(_ctx.t('pi.providers.targetFile', { path: '~/.pi/agent/models.json' })), 1 /* TEXT */),
|
|
3391
3412
|
_withDirectives(_createElementVNode("textarea", {
|
|
3392
3413
|
class: "template-textarea config-json-editor",
|
|
3393
3414
|
"onUpdate:modelValue": $event => ((_ctx.piModelsJsonDraft) = $event),
|
|
@@ -3401,27 +3422,13 @@ return function render(_ctx, _cache) {
|
|
|
3401
3422
|
]),
|
|
3402
3423
|
(_ctx.piModelsJsonError)
|
|
3403
3424
|
? (_openBlock(), _createElementBlock("p", {
|
|
3404
|
-
key:
|
|
3425
|
+
key: 0,
|
|
3405
3426
|
class: "config-template-hint error-text"
|
|
3406
3427
|
}, _toDisplayString(_ctx.piModelsJsonError), 1 /* TEXT */))
|
|
3407
3428
|
: _createCommentVNode("v-if", true),
|
|
3408
|
-
_createElementVNode("div", { class: "settings-tab-actions" }, [
|
|
3409
|
-
_createElementVNode("button", {
|
|
3410
|
-
type: "button",
|
|
3411
|
-
class: "btn-tool",
|
|
3412
|
-
onClick: _ctx.savePiModelsJson,
|
|
3413
|
-
disabled: !_ctx.isToolConfigWriteAllowed('pi') || _ctx.piSaving || _ctx.piFileJsonSaving || !!_ctx.piModelsJsonError
|
|
3414
|
-
}, _toDisplayString(_ctx.t('common.save')), 9 /* TEXT, PROPS */, ["onClick", "disabled"]),
|
|
3415
|
-
_createElementVNode("button", {
|
|
3416
|
-
type: "button",
|
|
3417
|
-
class: "btn-mini",
|
|
3418
|
-
onClick: $event => (_ctx.openPiConfigHistory('models')),
|
|
3419
|
-
disabled: _ctx.piHistoryLoading
|
|
3420
|
-
}, _toDisplayString(_ctx.t('common.history')), 9 /* TEXT, PROPS */, ["onClick", "disabled"])
|
|
3421
|
-
]),
|
|
3422
3429
|
(_ctx.piHistoryTarget === 'models')
|
|
3423
3430
|
? (_openBlock(), _createElementBlock("details", {
|
|
3424
|
-
key:
|
|
3431
|
+
key: 1,
|
|
3425
3432
|
class: "prompt-history-panel",
|
|
3426
3433
|
open: ""
|
|
3427
3434
|
}, [
|
|
@@ -6875,6 +6882,13 @@ return function render(_ctx, _cache) {
|
|
|
6875
6882
|
"aria-selected": _ctx.promptsSubTab === 'codex',
|
|
6876
6883
|
onClick: $event => (_ctx.switchPromptsSubTab('codex'))
|
|
6877
6884
|
}, _toDisplayString(_ctx.t('prompts.subTab.codex')), 11 /* TEXT, CLASS, PROPS */, ["aria-selected", "onClick"]),
|
|
6885
|
+
_createElementVNode("button", {
|
|
6886
|
+
type: "button",
|
|
6887
|
+
class: _normalizeClass(['prompts-md-tab', { active: _ctx.promptsSubTab === 'opencode' }]),
|
|
6888
|
+
role: "tab",
|
|
6889
|
+
"aria-selected": _ctx.promptsSubTab === 'opencode',
|
|
6890
|
+
onClick: $event => (_ctx.switchPromptsSubTab('opencode'))
|
|
6891
|
+
}, _toDisplayString(_ctx.t('prompts.subTab.opencode')), 11 /* TEXT, CLASS, PROPS */, ["aria-selected", "onClick"]),
|
|
6878
6892
|
_createElementVNode("button", {
|
|
6879
6893
|
type: "button",
|
|
6880
6894
|
class: _normalizeClass(['prompts-md-tab', { active: _ctx.promptsSubTab === 'claude-project' }]),
|
|
@@ -530,7 +530,7 @@ export async function loadActiveSessionDetail(api, options = {}) {
|
|
|
530
530
|
}
|
|
531
531
|
}
|
|
532
532
|
|
|
533
|
-
export async function loadMoreSessionMessages() {
|
|
533
|
+
export async function loadMoreSessionMessages(stepSize) {
|
|
534
534
|
if (this.mainTab !== 'sessions' || !this.sessionPreviewRenderEnabled) {
|
|
535
535
|
return;
|
|
536
536
|
}
|
|
@@ -541,6 +541,19 @@ export async function loadMoreSessionMessages() {
|
|
|
541
541
|
this.sessionPreviewVisibleCount = 0;
|
|
542
542
|
return;
|
|
543
543
|
}
|
|
544
|
+
const step = Number.isFinite(stepSize)
|
|
545
|
+
? Math.max(1, Math.floor(stepSize))
|
|
546
|
+
: (Number.isFinite(this.sessionPreviewLoadStep)
|
|
547
|
+
? Math.max(1, Math.floor(this.sessionPreviewLoadStep))
|
|
548
|
+
: 40);
|
|
549
|
+
const current = Number.isFinite(this.sessionPreviewVisibleCount)
|
|
550
|
+
? Math.max(0, Math.floor(this.sessionPreviewVisibleCount))
|
|
551
|
+
: 0;
|
|
552
|
+
const targetVisible = current + step;
|
|
553
|
+
if (targetVisible <= total) {
|
|
554
|
+
this.sessionPreviewVisibleCount = Math.min(total, targetVisible);
|
|
555
|
+
return;
|
|
556
|
+
}
|
|
544
557
|
|
|
545
558
|
this.sessionPreviewVisibleCount = total;
|
|
546
559
|
if (this.sessionDetailLoading) {
|
|
@@ -560,19 +573,24 @@ export async function loadMoreSessionMessages() {
|
|
|
560
573
|
const currentLimit = Number.isFinite(currentLimitRaw)
|
|
561
574
|
? Math.max(1, Math.floor(currentLimitRaw))
|
|
562
575
|
: Math.max(1, total);
|
|
576
|
+
const fetchStep = Number.isFinite(this.sessionDetailFetchStep)
|
|
577
|
+
? Math.max(1, Math.floor(this.sessionDetailFetchStep))
|
|
578
|
+
: 80;
|
|
563
579
|
const limitCapRaw = Number(this.sessionDetailMessageLimitCap);
|
|
564
580
|
const limitCap = Number.isFinite(limitCapRaw)
|
|
565
581
|
? Math.max(1, Math.floor(limitCapRaw))
|
|
566
582
|
: 1000;
|
|
567
583
|
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
584
|
+
let nextLimit = Math.max(currentLimit + fetchStep, targetVisible);
|
|
585
|
+
if (totalKnown > total) {
|
|
586
|
+
nextLimit = Math.min(nextLimit, totalKnown);
|
|
587
|
+
}
|
|
588
|
+
nextLimit = Math.min(nextLimit, limitCap);
|
|
571
589
|
if (nextLimit <= currentLimit) {
|
|
572
590
|
return;
|
|
573
591
|
}
|
|
574
592
|
|
|
575
|
-
this.sessionPreviewPendingVisibleCount =
|
|
593
|
+
this.sessionPreviewPendingVisibleCount = targetVisible;
|
|
576
594
|
this.sessionDetailMessageLimit = nextLimit;
|
|
577
595
|
this.sessionPreviewLoadingMore = true;
|
|
578
596
|
try {
|
|
@@ -580,11 +598,4 @@ export async function loadMoreSessionMessages() {
|
|
|
580
598
|
} finally {
|
|
581
599
|
this.sessionPreviewLoadingMore = false;
|
|
582
600
|
}
|
|
583
|
-
|
|
584
|
-
const loadedTotal = Array.isArray(this.activeSessionMessages)
|
|
585
|
-
? this.activeSessionMessages.length
|
|
586
|
-
: 0;
|
|
587
|
-
if (loadedTotal > this.sessionPreviewVisibleCount) {
|
|
588
|
-
this.sessionPreviewVisibleCount = loadedTotal;
|
|
589
|
-
}
|
|
590
601
|
}
|
|
@@ -104,6 +104,13 @@
|
|
|
104
104
|
flex: 0 0 auto;
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
+
.selector-header .selector-actions > .btn-tool + .btn-tool,
|
|
108
|
+
.selector-header .selector-actions > .btn-tool-compact + .btn-tool,
|
|
109
|
+
.selector-header .selector-actions > .btn-tool + .btn-tool-compact,
|
|
110
|
+
.selector-header .selector-actions > .btn-tool-compact + .btn-tool-compact {
|
|
111
|
+
margin-top: 0;
|
|
112
|
+
}
|
|
113
|
+
|
|
107
114
|
.selector-actions.opencode-provider-actions {
|
|
108
115
|
display: inline-flex;
|
|
109
116
|
align-items: stretch;
|