codexmate 0.1.14 → 0.1.16
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/cli.js +16 -5
- package/package.json +1 -1
- package/web-ui/app.js +6 -4
- package/web-ui/modules/app.methods.agents.mjs +17 -1
- package/web-ui/modules/app.methods.pi-config.mjs +145 -19
- package/web-ui/modules/i18n/locales/en.mjs +12 -0
- package/web-ui/modules/i18n/locales/ja.mjs +12 -0
- package/web-ui/modules/i18n/locales/vi.mjs +12 -0
- package/web-ui/modules/i18n/locales/zh-tw.mjs +12 -0
- package/web-ui/modules/i18n/locales/zh.mjs +12 -0
- package/web-ui/partials/index/layout-header.html +20 -0
- package/web-ui/partials/index/panel-config-pi.html +51 -0
- package/web-ui/res/web-ui-render.precompiled.js +113 -7
- package/web-ui/styles/controls-forms.css +22 -0
package/cli.js
CHANGED
|
@@ -1222,28 +1222,34 @@ function readPiModels(params = {}) {
|
|
|
1222
1222
|
const dir = getPiAgentDir();
|
|
1223
1223
|
const filePath = path.join(dir, 'models.json');
|
|
1224
1224
|
if (!fs.existsSync(filePath)) {
|
|
1225
|
-
return { providers: {} };
|
|
1225
|
+
return { providers: {}, file: {} };
|
|
1226
1226
|
}
|
|
1227
1227
|
const raw = fs.readFileSync(filePath, 'utf-8');
|
|
1228
1228
|
const data = JSON.parse(raw);
|
|
1229
1229
|
const providers = (data && typeof data === 'object' && data.providers && typeof data.providers === 'object')
|
|
1230
1230
|
? data.providers
|
|
1231
1231
|
: {};
|
|
1232
|
-
|
|
1232
|
+
const file = data && typeof data === 'object' && !Array.isArray(data) ? data : { providers };
|
|
1233
|
+
return { providers, file };
|
|
1233
1234
|
} catch (e) {
|
|
1234
1235
|
return { error: e && e.message ? e.message : '读取 Pi models.json 失败' };
|
|
1235
1236
|
}
|
|
1236
1237
|
}
|
|
1237
1238
|
|
|
1238
1239
|
function writePiModels(params = {}) {
|
|
1240
|
+
const file = params && typeof params.file === 'object' && params.file !== null && !Array.isArray(params.file) ? params.file : null;
|
|
1239
1241
|
const providers = params && typeof params.providers === 'object' ? params.providers : null;
|
|
1240
|
-
if (providers === null) {
|
|
1241
|
-
return { error: '
|
|
1242
|
+
if (!file && providers === null) {
|
|
1243
|
+
return { error: '缺少可写入的内容' };
|
|
1242
1244
|
}
|
|
1243
1245
|
try {
|
|
1244
1246
|
const dir = getPiAgentDir();
|
|
1245
1247
|
fs.mkdirSync(dir, { recursive: true });
|
|
1246
1248
|
const filePath = path.join(dir, 'models.json');
|
|
1249
|
+
if (file) {
|
|
1250
|
+
fs.writeFileSync(filePath, JSON.stringify(file, null, 2), 'utf-8');
|
|
1251
|
+
return { success: true };
|
|
1252
|
+
}
|
|
1247
1253
|
let existing = {};
|
|
1248
1254
|
if (fs.existsSync(filePath)) {
|
|
1249
1255
|
try {
|
|
@@ -1294,16 +1300,21 @@ function readPiSettings(params = {}) {
|
|
|
1294
1300
|
}
|
|
1295
1301
|
|
|
1296
1302
|
function writePiSettings(params = {}) {
|
|
1303
|
+
const fullSettings = params && typeof params.settings === 'object' && params.settings !== null && !Array.isArray(params.settings) ? params.settings : null;
|
|
1297
1304
|
const updates = {};
|
|
1298
1305
|
if (typeof (params && params.defaultProvider) === 'string') updates.defaultProvider = params.defaultProvider;
|
|
1299
1306
|
if (typeof (params && params.defaultModel) === 'string') updates.defaultModel = params.defaultModel;
|
|
1300
|
-
if (Object.keys(updates).length === 0) {
|
|
1307
|
+
if (!fullSettings && Object.keys(updates).length === 0) {
|
|
1301
1308
|
return { error: '缺少可写入的设置项' };
|
|
1302
1309
|
}
|
|
1303
1310
|
try {
|
|
1304
1311
|
const dir = getPiAgentDir();
|
|
1305
1312
|
fs.mkdirSync(dir, { recursive: true });
|
|
1306
1313
|
const filePath = path.join(dir, 'settings.json');
|
|
1314
|
+
if (fullSettings) {
|
|
1315
|
+
fs.writeFileSync(filePath, JSON.stringify(fullSettings, null, 2), 'utf-8');
|
|
1316
|
+
return { success: true, settings: fullSettings };
|
|
1317
|
+
}
|
|
1307
1318
|
let existing = {};
|
|
1308
1319
|
if (fs.existsSync(filePath)) {
|
|
1309
1320
|
try {
|
package/package.json
CHANGED
package/web-ui/app.js
CHANGED
|
@@ -148,6 +148,11 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
148
148
|
piActiveProvider: '',
|
|
149
149
|
piActiveModel: '',
|
|
150
150
|
piShowKey: false,
|
|
151
|
+
piSettingsJsonDraft: '',
|
|
152
|
+
piSettingsJsonError: '',
|
|
153
|
+
piModelsJsonDraft: '',
|
|
154
|
+
piModelsJsonError: '',
|
|
155
|
+
piFileJsonSaving: false,
|
|
151
156
|
// Plugins
|
|
152
157
|
pluginsActiveId: 'prompt-templates',
|
|
153
158
|
pluginsLoading: false,
|
|
@@ -819,10 +824,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
819
824
|
if (typeof this.persistWebUiPreferences === 'function') {
|
|
820
825
|
this.persistWebUiPreferences({ sysPromptMode: newVal });
|
|
821
826
|
}
|
|
822
|
-
}
|
|
823
|
-
},
|
|
824
|
-
|
|
825
|
-
watch: {
|
|
827
|
+
},
|
|
826
828
|
configMode(newMode) {
|
|
827
829
|
if (newMode === 'pi' && typeof this.loadPiSources === 'function') {
|
|
828
830
|
this.loadPiSources();
|
|
@@ -471,6 +471,18 @@ export function createAgentsMethods(options = {}) {
|
|
|
471
471
|
.filter(Boolean)
|
|
472
472
|
.filter(function (v, i, a) { return a.indexOf(v) === i; });
|
|
473
473
|
}
|
|
474
|
+
if (this.promptsSubTab === 'claude-project'
|
|
475
|
+
&& this.mainTab === 'prompts'
|
|
476
|
+
&& Array.isArray(this.projectPathOptions)
|
|
477
|
+
&& this.projectPathOptions.length) {
|
|
478
|
+
const currentPath = (this.projectClaudeMdPath || '').trim();
|
|
479
|
+
if (currentPath && this.projectPathOptions.indexOf(currentPath) !== -1) {
|
|
480
|
+
this.projectClaudeMdPath = currentPath;
|
|
481
|
+
} else {
|
|
482
|
+
this.projectClaudeMdPath = this.projectPathOptions[0];
|
|
483
|
+
}
|
|
484
|
+
if (typeof this.loadPromptsContent === 'function') this.loadPromptsContent();
|
|
485
|
+
}
|
|
474
486
|
} catch (_) {
|
|
475
487
|
// silent
|
|
476
488
|
} finally {
|
|
@@ -1015,7 +1027,11 @@ export function createAgentsMethods(options = {}) {
|
|
|
1015
1027
|
if (!this.projectPathOptions.length && !this.projectPathOptionsLoading && typeof this.loadProjectPathOptions === 'function') {
|
|
1016
1028
|
this.loadProjectPathOptions();
|
|
1017
1029
|
}
|
|
1018
|
-
|
|
1030
|
+
let projectPath = (this.projectClaudeMdPath || '').trim();
|
|
1031
|
+
if (!projectPath && Array.isArray(this.projectPathOptions) && this.projectPathOptions.length) {
|
|
1032
|
+
this.projectClaudeMdPath = this.projectPathOptions[0];
|
|
1033
|
+
projectPath = this.projectClaudeMdPath.trim();
|
|
1034
|
+
}
|
|
1019
1035
|
if (projectPath) {
|
|
1020
1036
|
rpcParams.baseDir = projectPath;
|
|
1021
1037
|
}
|
|
@@ -66,7 +66,8 @@ export function createPiConfigMethods({ api: apiClient }) {
|
|
|
66
66
|
try {
|
|
67
67
|
const [providers] = await Promise.all([
|
|
68
68
|
this.loadPiProviders(),
|
|
69
|
-
this.loadPiSettings()
|
|
69
|
+
this.loadPiSettings(),
|
|
70
|
+
this.loadPiFileJsons()
|
|
70
71
|
]);
|
|
71
72
|
this.piProviders = providers || {};
|
|
72
73
|
this.piProviderIds = Object.keys(this.piProviders || {}).sort();
|
|
@@ -81,24 +82,13 @@ export function createPiConfigMethods({ api: apiClient }) {
|
|
|
81
82
|
this.piSaving = true;
|
|
82
83
|
try {
|
|
83
84
|
const providerId = this.editingPiProvider.id;
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
api: values.api,
|
|
92
|
-
apiKey: values.apiKey || '',
|
|
93
|
-
models: (Array.isArray(values.models) ? values.models : []).map((model) => ({
|
|
94
|
-
...model,
|
|
95
|
-
id: model.id || '',
|
|
96
|
-
name: model.id || ''
|
|
97
|
-
}))
|
|
98
|
-
};
|
|
99
|
-
if (isPiPlainObject(provider.headers)) merged.headers = provider.headers;
|
|
100
|
-
if (typeof provider.title === 'string') merged.title = provider.title;
|
|
101
|
-
else if (typeof provider.name === 'string') merged.name = provider.name;
|
|
85
|
+
const { merged, ok, error } = this.piBuildMergedEditorRecord();
|
|
86
|
+
if (!ok || !merged) {
|
|
87
|
+
this.piEditorJsonError = error || '配置 JSON 不合法';
|
|
88
|
+
this.message = this.piEditorJsonError;
|
|
89
|
+
this.messageType = 'error';
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
102
92
|
|
|
103
93
|
await this.persistPiProvider(providerId, merged);
|
|
104
94
|
this.piProviders = { ...this.piProviders, [providerId]: merged };
|
|
@@ -232,6 +222,7 @@ export function createPiConfigMethods({ api: apiClient }) {
|
|
|
232
222
|
this.piRemoteModels = [];
|
|
233
223
|
this.piRemoteModelError = '';
|
|
234
224
|
this.piModelSearch = '';
|
|
225
|
+
this.piEditorJsonError = '';
|
|
235
226
|
const provider = this.piProviders[providerId] || {};
|
|
236
227
|
const knownKeys = ['id', 'name', 'title', 'baseUrl', 'api', 'apiKey', 'models', 'headers', 'configJson'];
|
|
237
228
|
const extras = {};
|
|
@@ -269,6 +260,7 @@ export function createPiConfigMethods({ api: apiClient }) {
|
|
|
269
260
|
this.piRemoteModels = [];
|
|
270
261
|
this.piRemoteModelError = '';
|
|
271
262
|
this.piModelSearch = '';
|
|
263
|
+
this.piEditorJsonError = '';
|
|
272
264
|
},
|
|
273
265
|
removePiProviderModel(index) {
|
|
274
266
|
if (!this.editingPiProvider) return;
|
|
@@ -350,5 +342,139 @@ export function createPiConfigMethods({ api: apiClient }) {
|
|
|
350
342
|
const api = provider.api || '';
|
|
351
343
|
return [baseUrl, api].filter(Boolean).join(' • ') || 'Piper provider';
|
|
352
344
|
}
|
|
345
|
+
,
|
|
346
|
+
piParseFileJsonDraft(draft, label) {
|
|
347
|
+
const name = label || 'JSON';
|
|
348
|
+
const text = String(draft || '').trim();
|
|
349
|
+
if (!text) return { ok: false, value: null, error: name + ' 内容不能为空' };
|
|
350
|
+
try {
|
|
351
|
+
const parsed = JSON.parse(text);
|
|
352
|
+
if (parsed === null || Array.isArray(parsed) || typeof parsed !== 'object') {
|
|
353
|
+
return { ok: false, value: null, error: name + ' 必须是 JSON 对象' };
|
|
354
|
+
}
|
|
355
|
+
return { ok: true, value: parsed, error: '' };
|
|
356
|
+
} catch (e) {
|
|
357
|
+
return { ok: false, value: null, error: name + ' 解析失败:' + (e && e.message ? e.message : '') };
|
|
358
|
+
}
|
|
359
|
+
},
|
|
360
|
+
async loadPiFileJsons() {
|
|
361
|
+
const [modelsResult, settingsResult] = await Promise.all([
|
|
362
|
+
apiClient('read-pi-models'),
|
|
363
|
+
apiClient('read-pi-settings')
|
|
364
|
+
]);
|
|
365
|
+
const modelsFile = isPiPlainObject(modelsResult && modelsResult.file) ? modelsResult.file : {};
|
|
366
|
+
const settings = isPiPlainObject(settingsResult && settingsResult.settings) ? settingsResult.settings : {};
|
|
367
|
+
this.piModelsJsonDraft = JSON.stringify(modelsFile, null, 2);
|
|
368
|
+
this.piSettingsJsonDraft = JSON.stringify(settings, null, 2);
|
|
369
|
+
this.piModelsJsonError = '';
|
|
370
|
+
this.piSettingsJsonError = '';
|
|
371
|
+
},
|
|
372
|
+
piSettingsJsonInput() {
|
|
373
|
+
const parsed = this.piParseFileJsonDraft(this.piSettingsJsonDraft, 'settings.json');
|
|
374
|
+
this.piSettingsJsonError = parsed.ok ? '' : parsed.error;
|
|
375
|
+
},
|
|
376
|
+
piModelsJsonInput() {
|
|
377
|
+
const parsed = this.piParseFileJsonDraft(this.piModelsJsonDraft, 'models.json');
|
|
378
|
+
this.piModelsJsonError = parsed.ok ? '' : parsed.error;
|
|
379
|
+
},
|
|
380
|
+
async savePiSettingsJson() {
|
|
381
|
+
if (!this.isToolConfigWriteAllowed('pi') || this.piSaving || this.piFileJsonSaving) return;
|
|
382
|
+
const parsed = this.piParseFileJsonDraft(this.piSettingsJsonDraft, 'settings.json');
|
|
383
|
+
if (!parsed.ok) {
|
|
384
|
+
this.piSettingsJsonError = parsed.error;
|
|
385
|
+
this.message = parsed.error;
|
|
386
|
+
this.messageType = 'error';
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
this.piFileJsonSaving = true;
|
|
390
|
+
try {
|
|
391
|
+
const result = await apiClient('write-pi-settings', { settings: parsed.value });
|
|
392
|
+
if (result && result.error) throw new Error(result.error);
|
|
393
|
+
this.piSettingsJsonError = '';
|
|
394
|
+
this.piSettingsJsonDraft = JSON.stringify(parsed.value, null, 2);
|
|
395
|
+
await this.loadPiSettings();
|
|
396
|
+
this.message = 'settings.json 已保存';
|
|
397
|
+
this.messageType = 'success';
|
|
398
|
+
} catch (e) {
|
|
399
|
+
this.message = e && e.message ? e.message : '保存 settings.json 失败';
|
|
400
|
+
this.messageType = 'error';
|
|
401
|
+
} finally {
|
|
402
|
+
this.piFileJsonSaving = false;
|
|
403
|
+
}
|
|
404
|
+
},
|
|
405
|
+
async savePiModelsJson() {
|
|
406
|
+
if (!this.isToolConfigWriteAllowed('pi') || this.piSaving || this.piFileJsonSaving) return;
|
|
407
|
+
const parsed = this.piParseFileJsonDraft(this.piModelsJsonDraft, 'models.json');
|
|
408
|
+
if (!parsed.ok) {
|
|
409
|
+
this.piModelsJsonError = parsed.error;
|
|
410
|
+
this.message = parsed.error;
|
|
411
|
+
this.messageType = 'error';
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
414
|
+
this.piFileJsonSaving = true;
|
|
415
|
+
try {
|
|
416
|
+
const result = await apiClient('write-pi-models', { file: parsed.value });
|
|
417
|
+
if (result && result.error) throw new Error(result.error);
|
|
418
|
+
await this.loadPiSources();
|
|
419
|
+
this.message = 'models.json 已保存';
|
|
420
|
+
this.messageType = 'success';
|
|
421
|
+
} catch (e) {
|
|
422
|
+
this.message = e && e.message ? e.message : '保存 models.json 失败';
|
|
423
|
+
this.messageType = 'error';
|
|
424
|
+
} finally {
|
|
425
|
+
this.piFileJsonSaving = false;
|
|
426
|
+
}
|
|
427
|
+
},
|
|
428
|
+
piParseEditorJsonDraft() {
|
|
429
|
+
const provider = this.editingPiProvider;
|
|
430
|
+
const draft = provider && provider.form ? String(provider.form.configJsonDraft || '').trim() : '';
|
|
431
|
+
if (!draft) return { ok: true, extras: {} };
|
|
432
|
+
try {
|
|
433
|
+
const parsed = JSON.parse(draft);
|
|
434
|
+
if (parsed === null || Array.isArray(parsed) || typeof parsed !== 'object') {
|
|
435
|
+
return { ok: false, extras: {}, error: '配置 JSON 必须是对象' };
|
|
436
|
+
}
|
|
437
|
+
return { ok: true, extras: parsed };
|
|
438
|
+
} catch (e) {
|
|
439
|
+
return { ok: false, extras: {}, error: e && e.message ? '配置 JSON 解析失败:' + e.message : '配置 JSON 解析失败' };
|
|
440
|
+
}
|
|
441
|
+
},
|
|
442
|
+
piBuildMergedEditorRecord() {
|
|
443
|
+
const provider = this.editingPiProvider;
|
|
444
|
+
if (!provider || !provider.form) return { merged: null, ok: false, error: '未在编辑供应商', extras: {} };
|
|
445
|
+
const draft = this.piParseEditorJsonDraft();
|
|
446
|
+
if (!draft.ok) return { merged: null, ok: false, error: draft.error, extras: {} };
|
|
447
|
+
const values = provider.form || {};
|
|
448
|
+
const extras = draft.extras || {};
|
|
449
|
+
const orig = this.piProviders[provider.id] || {};
|
|
450
|
+
const mapModels = (xs) => (Array.isArray(xs) ? xs : []).map((model) => ({
|
|
451
|
+
...model,
|
|
452
|
+
id: (model && model.id) || '',
|
|
453
|
+
name: (model && (model.name || model.id)) || ''
|
|
454
|
+
}));
|
|
455
|
+
const merged = { ...extras };
|
|
456
|
+
if (merged.baseUrl === undefined) merged.baseUrl = values.baseUrl || '';
|
|
457
|
+
if (merged.api === undefined) merged.api = values.api || '';
|
|
458
|
+
if (merged.apiKey === undefined) merged.apiKey = values.apiKey || '';
|
|
459
|
+
if (merged.models === undefined) merged.models = mapModels(values.models);
|
|
460
|
+
if (isPiPlainObject(orig.headers)) merged.headers = orig.headers;
|
|
461
|
+
if (typeof orig.title === 'string') merged.title = orig.title;
|
|
462
|
+
else if (typeof orig.name === 'string') merged.name = orig.name;
|
|
463
|
+
if (isPiPlainObject(orig.configJson)) merged.configJson = orig.configJson;
|
|
464
|
+
return { merged, ok: true, error: '', extras };
|
|
465
|
+
},
|
|
466
|
+
piProviderPreviewJson() {
|
|
467
|
+
const { merged, ok } = this.piBuildMergedEditorRecord();
|
|
468
|
+
if (!ok || !merged) return '{}';
|
|
469
|
+
try {
|
|
470
|
+
return JSON.stringify(merged, null, 2);
|
|
471
|
+
} catch (_) {
|
|
472
|
+
return '{}';
|
|
473
|
+
}
|
|
474
|
+
},
|
|
475
|
+
piEditorJsonDraftInput() {
|
|
476
|
+
const draft = this.piParseEditorJsonDraft();
|
|
477
|
+
this.piEditorJsonError = draft.ok ? '' : draft.error;
|
|
478
|
+
}
|
|
353
479
|
};
|
|
354
480
|
}
|
|
@@ -1030,6 +1030,10 @@ const en = Object.freeze({
|
|
|
1030
1030
|
'status.opencodeConfig': 'OpenCode config',
|
|
1031
1031
|
'status.workspaceFile': 'Workspace file',
|
|
1032
1032
|
'status.configMode': 'Config mode',
|
|
1033
|
+
'status.kilocodeProvider': 'Kilocode provider',
|
|
1034
|
+
'status.kilocodeModel': 'Kilocode model',
|
|
1035
|
+
'status.piProvider': 'Pi provider',
|
|
1036
|
+
'status.piModel': 'Pi model',
|
|
1033
1037
|
'status.currentProvider': 'Current provider',
|
|
1034
1038
|
'status.currentModel': 'Current model',
|
|
1035
1039
|
'status.quickSwitchProvider': 'Quick switch provider',
|
|
@@ -1346,6 +1350,14 @@ const en = Object.freeze({
|
|
|
1346
1350
|
'pi.providers.fields.apiKey': 'API Key',
|
|
1347
1351
|
'pi.providers.fields.models': 'Models',
|
|
1348
1352
|
'pi.providers.fields.configJson': 'Config JSON',
|
|
1353
|
+
'pi.providers.json.title': 'Config JSON',
|
|
1354
|
+
'pi.providers.json.desc': 'Live preview of the final provider record merged from form changes and extras; edits are merged into models.json on save.',
|
|
1355
|
+
'pi.providers.json.previewTitle': 'Preview',
|
|
1356
|
+
'pi.providers.json.editTitle': 'Edit JSON',
|
|
1357
|
+
'pi.files.title': 'File JSON',
|
|
1358
|
+
'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.',
|
|
1359
|
+
'pi.files.settingsTitle': 'settings.json (active settings)',
|
|
1360
|
+
'pi.files.modelsTitle': 'models.json (providers and models)',
|
|
1349
1361
|
'pi.providers.models.remove': 'Remove',
|
|
1350
1362
|
'pi.providers.models.search': 'Search available models…',
|
|
1351
1363
|
'pi.providers.models.remoteCount': '{count} models available, click to add',
|
|
@@ -1033,6 +1033,10 @@ const ja = Object.freeze({
|
|
|
1033
1033
|
'status.opencodeConfig': 'OpenCode 設定',
|
|
1034
1034
|
'status.workspaceFile': 'ワークスペースファイル',
|
|
1035
1035
|
'status.configMode': '設定モード',
|
|
1036
|
+
'status.kilocodeProvider': 'Kilocode プロバイダー',
|
|
1037
|
+
'status.kilocodeModel': 'Kilocode モデル',
|
|
1038
|
+
'status.piProvider': 'Pi プロバイダー',
|
|
1039
|
+
'status.piModel': 'Pi モデル',
|
|
1036
1040
|
'status.currentProvider': '現在の Provider',
|
|
1037
1041
|
'status.currentModel': '現在のモデル',
|
|
1038
1042
|
'status.quickSwitchProvider': 'プロバイダーをクイック切替',
|
|
@@ -1347,6 +1351,14 @@ const ja = Object.freeze({
|
|
|
1347
1351
|
'pi.providers.fields.apiKey': 'API Key',
|
|
1348
1352
|
'pi.providers.fields.models': 'モデル',
|
|
1349
1353
|
'pi.providers.fields.configJson': '設定 JSON',
|
|
1354
|
+
'pi.providers.json.title': '設定 JSON',
|
|
1355
|
+
'pi.providers.json.desc': 'フォーム変更と拡張フィールドを統合した最終レコードをリアルタイムにプレビュー。保存時に models.json へ統合します。',
|
|
1356
|
+
'pi.providers.json.previewTitle': 'プレビュー',
|
|
1357
|
+
'pi.providers.json.editTitle': 'JSON を編集',
|
|
1358
|
+
'pi.files.title': 'ファイル JSON',
|
|
1359
|
+
'pi.files.desc': 'Pi の settings.json と models.json を全文表示して直接編集します。保存前に JSON の正当性を検証し、不正な内容は書き込みません。',
|
|
1360
|
+
'pi.files.settingsTitle': 'settings.json(有効な設定)',
|
|
1361
|
+
'pi.files.modelsTitle': 'models.json(プロバイダーとモデル)',
|
|
1350
1362
|
'pi.providers.models.remove': '削除',
|
|
1351
1363
|
'pi.providers.models.search': '利用可能なモデルを検索…',
|
|
1352
1364
|
'pi.providers.models.remoteCount': '{count} 個のモデルを取得しました。クリックで追加',
|
|
@@ -1128,6 +1128,10 @@ const vi = Object.freeze({
|
|
|
1128
1128
|
'status.openclawConfig': 'Cấu hình OpenClaw',
|
|
1129
1129
|
'status.workspaceFile': 'File không gian làm việc',
|
|
1130
1130
|
'status.configMode': 'Chế độ cấu hình',
|
|
1131
|
+
'status.kilocodeProvider': 'Nhà cung cấp Kilocode',
|
|
1132
|
+
'status.kilocodeModel': 'Mô hình Kilocode',
|
|
1133
|
+
'status.piProvider': 'Nhà cung cấp Pi',
|
|
1134
|
+
'status.piModel': 'Mô hình Pi',
|
|
1131
1135
|
'status.currentProvider': 'Nhà cung cấp hiện tại',
|
|
1132
1136
|
'status.currentModel': 'Model hiện tại',
|
|
1133
1137
|
'status.quickSwitchProvider': 'Chuyển nhanh nhà cung cấp',
|
|
@@ -1315,6 +1319,14 @@ const vi = Object.freeze({
|
|
|
1315
1319
|
'pi.providers.fields.apiKey': 'API Key',
|
|
1316
1320
|
'pi.providers.fields.models': 'Mô hình',
|
|
1317
1321
|
'pi.providers.fields.configJson': 'Cấu hình JSON',
|
|
1322
|
+
'pi.providers.json.title': 'Cấu hình JSON',
|
|
1323
|
+
'pi.providers.json.desc': 'Xem trước bản ghi cuối từ thay đổi biểu mẫu; các chỉnh sửa được gộp vào models.json khi lưu.',
|
|
1324
|
+
'pi.providers.json.previewTitle': 'Xem trước',
|
|
1325
|
+
'pi.providers.json.editTitle': 'Chỉnh sửa JSON',
|
|
1326
|
+
'pi.files.title': 'JSON tập tin',
|
|
1327
|
+
'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.',
|
|
1328
|
+
'pi.files.settingsTitle': 'settings.json (cài đặt đang dùng)',
|
|
1329
|
+
'pi.files.modelsTitle': 'models.json (nhà cung cấp và mô hình)',
|
|
1318
1330
|
'pi.providers.models.remove': 'Xóa',
|
|
1319
1331
|
'pi.providers.models.search': 'Tìm kiếm mô hình khả dụng…',
|
|
1320
1332
|
'pi.providers.models.remoteCount': 'Đã lấy {count} mô hình, bấm để thêm',
|
|
@@ -1029,6 +1029,10 @@ const zhTw = Object.freeze({
|
|
|
1029
1029
|
'status.opencodeConfig': 'OpenCode 設定',
|
|
1030
1030
|
'status.workspaceFile': '工作區文件',
|
|
1031
1031
|
'status.configMode': '設定模式',
|
|
1032
|
+
'status.kilocodeProvider': 'Kilocode 供應商',
|
|
1033
|
+
'status.kilocodeModel': 'Kilocode 模型',
|
|
1034
|
+
'status.piProvider': 'Pi 供應商',
|
|
1035
|
+
'status.piModel': 'Pi 模型',
|
|
1032
1036
|
'status.currentProvider': '目前 Provider',
|
|
1033
1037
|
'status.currentModel': '目前模型',
|
|
1034
1038
|
'status.quickSwitchProvider': '快速切換提供商',
|
|
@@ -1344,6 +1348,14 @@ const zhTw = Object.freeze({
|
|
|
1344
1348
|
'pi.providers.fields.apiKey': 'API Key',
|
|
1345
1349
|
'pi.providers.fields.models': '模型',
|
|
1346
1350
|
'pi.providers.fields.configJson': '組態 JSON',
|
|
1351
|
+
'pi.providers.json.title': '設定 JSON',
|
|
1352
|
+
'pi.providers.json.desc': '即時預覽表單異動合併後的最終紀錄;儲存時併入 models.json。',
|
|
1353
|
+
'pi.providers.json.previewTitle': '預覽',
|
|
1354
|
+
'pi.providers.json.editTitle': '編輯 JSON',
|
|
1355
|
+
'pi.files.title': '檔案 JSON',
|
|
1356
|
+
'pi.files.desc': '完整展示並直接編輯 Pi 的 settings.json 與 models.json;儲存前校驗 JSON 合法性,非法內容不會寫入。',
|
|
1357
|
+
'pi.files.settingsTitle': 'settings.json(生效設定)',
|
|
1358
|
+
'pi.files.modelsTitle': 'models.json(供應商與模型)',
|
|
1347
1359
|
'pi.providers.models.remove': '刪除',
|
|
1348
1360
|
'pi.providers.models.search': '搜尋可用模型…',
|
|
1349
1361
|
'pi.providers.models.remoteCount': '已取得 {count} 個可用模型,點擊新增',
|
|
@@ -1029,6 +1029,10 @@ const zh = Object.freeze({
|
|
|
1029
1029
|
'status.opencodeConfig': 'OpenCode 配置',
|
|
1030
1030
|
'status.workspaceFile': '工作区文件',
|
|
1031
1031
|
'status.configMode': '配置模式',
|
|
1032
|
+
'status.kilocodeProvider': 'Kilocode 提供商',
|
|
1033
|
+
'status.kilocodeModel': 'Kilocode 模型',
|
|
1034
|
+
'status.piProvider': 'Pi 提供商',
|
|
1035
|
+
'status.piModel': 'Pi 模型',
|
|
1032
1036
|
'status.currentProvider': '当前 Provider',
|
|
1033
1037
|
'status.currentModel': '当前模型',
|
|
1034
1038
|
'status.quickSwitchProvider': '快速切换提供商',
|
|
@@ -1344,6 +1348,14 @@ const zh = Object.freeze({
|
|
|
1344
1348
|
'pi.providers.fields.apiKey': 'API Key',
|
|
1345
1349
|
'pi.providers.fields.models': '模型',
|
|
1346
1350
|
'pi.providers.fields.configJson': '配置 JSON',
|
|
1351
|
+
'pi.providers.json.title': '配置 JSON',
|
|
1352
|
+
'pi.providers.json.desc': '实时预览表单改动合并后的最终记录;保存时并入 models.json。',
|
|
1353
|
+
'pi.providers.json.previewTitle': '预览',
|
|
1354
|
+
'pi.providers.json.editTitle': '编辑 JSON',
|
|
1355
|
+
'pi.files.title': '文件 JSON',
|
|
1356
|
+
'pi.files.desc': '完整展示并直接编辑 Pi 的 settings.json 与 models.json;保存前校验 JSON 合法性,非法内容不会写入。',
|
|
1357
|
+
'pi.files.settingsTitle': 'settings.json(生效设置)',
|
|
1358
|
+
'pi.files.modelsTitle': 'models.json(供应商与模型)',
|
|
1347
1359
|
'pi.providers.models.remove': '删除',
|
|
1348
1360
|
'pi.providers.models.search': '搜索可用模型…',
|
|
1349
1361
|
'pi.providers.models.remoteCount': '已拉取 {count} 个可用模型,点击添加',
|
|
@@ -471,6 +471,26 @@
|
|
|
471
471
|
<span class="value">{{ opencodeConfigPath || t('common.notSelected') }}</span>
|
|
472
472
|
</div>
|
|
473
473
|
</template>
|
|
474
|
+
<template v-else-if="configMode === 'kilocode'">
|
|
475
|
+
<div class="status-chip">
|
|
476
|
+
<span class="label">{{ t('status.kilocodeProvider') }}</span>
|
|
477
|
+
<span class="value">{{ kilocodeProvider || t('common.notSelected') }}</span>
|
|
478
|
+
</div>
|
|
479
|
+
<div class="status-chip">
|
|
480
|
+
<span class="label">{{ t('status.kilocodeModel') }}</span>
|
|
481
|
+
<span class="value">{{ kilocodeModel || t('common.notSelected') }}</span>
|
|
482
|
+
</div>
|
|
483
|
+
</template>
|
|
484
|
+
<template v-else-if="configMode === 'pi'">
|
|
485
|
+
<div class="status-chip">
|
|
486
|
+
<span class="label">{{ t('status.piProvider') }}</span>
|
|
487
|
+
<span class="value">{{ piActiveProvider || t('common.notSelected') }}</span>
|
|
488
|
+
</div>
|
|
489
|
+
<div class="status-chip">
|
|
490
|
+
<span class="label">{{ t('status.piModel') }}</span>
|
|
491
|
+
<span class="value">{{ piActiveModel || t('common.notSelected') }}</span>
|
|
492
|
+
</div>
|
|
493
|
+
</template>
|
|
474
494
|
<template v-else>
|
|
475
495
|
<div class="status-chip">
|
|
476
496
|
<span class="label">{{ t('status.configMode') }}</span>
|
|
@@ -117,6 +117,25 @@
|
|
|
117
117
|
<div class="settings-tab-actions">
|
|
118
118
|
<button type="button" class="btn-tool" @click="confirmDeletePiProvider" :disabled="!isToolConfigWriteAllowed('pi') || piSaving">{{ t('pi.providers.delete') }}</button>
|
|
119
119
|
</div>
|
|
120
|
+
|
|
121
|
+
<section class="selector-section">
|
|
122
|
+
<div class="selector-header">
|
|
123
|
+
<span class="selector-title">{{ t('pi.providers.json.title') }}</span>
|
|
124
|
+
</div>
|
|
125
|
+
<p class="config-template-hint">{{ t('pi.providers.json.desc') }}</p>
|
|
126
|
+
<label class="form-label">{{ t('pi.providers.json.previewTitle') }}</label>
|
|
127
|
+
<pre class="config-json-preview">{{ piProviderPreviewJson() }}</pre>
|
|
128
|
+
<label class="form-label">{{ t('pi.providers.json.editTitle') }}</label>
|
|
129
|
+
<textarea
|
|
130
|
+
class="template-textarea config-json-editor"
|
|
131
|
+
v-model="editingPiProvider.form.configJsonDraft"
|
|
132
|
+
spellcheck="false"
|
|
133
|
+
autocomplete="off"
|
|
134
|
+
:disabled="!isToolConfigWriteAllowed('pi')"
|
|
135
|
+
@input="piEditorJsonDraftInput"
|
|
136
|
+
placeholder="{}"></textarea>
|
|
137
|
+
<p v-if="piEditorJsonError" class="config-template-hint error-text">{{ piEditorJsonError }}</p>
|
|
138
|
+
</section>
|
|
120
139
|
</section>
|
|
121
140
|
|
|
122
141
|
<section class="selector-section" v-if="showAddPiProviderModal">
|
|
@@ -159,6 +178,38 @@
|
|
|
159
178
|
</div>
|
|
160
179
|
</div>
|
|
161
180
|
</section>
|
|
181
|
+
<section class="selector-section">
|
|
182
|
+
<div class="selector-header">
|
|
183
|
+
<span class="selector-title">{{ t('pi.files.title') }}</span>
|
|
184
|
+
</div>
|
|
185
|
+
<div class="config-template-hint">{{ t('pi.files.desc') }}</div>
|
|
186
|
+
<label class="form-label">{{ t('pi.files.settingsTitle') }}</label>
|
|
187
|
+
<textarea
|
|
188
|
+
class="template-textarea config-json-editor"
|
|
189
|
+
v-model="piSettingsJsonDraft"
|
|
190
|
+
spellcheck="false"
|
|
191
|
+
autocomplete="off"
|
|
192
|
+
:disabled="!isToolConfigWriteAllowed('pi')"
|
|
193
|
+
@input="piSettingsJsonInput"
|
|
194
|
+
placeholder="{}"></textarea>
|
|
195
|
+
<p v-if="piSettingsJsonError" class="config-template-hint error-text">{{ piSettingsJsonError }}</p>
|
|
196
|
+
<div class="settings-tab-actions">
|
|
197
|
+
<button type="button" class="btn-tool" @click="savePiSettingsJson" :disabled="!isToolConfigWriteAllowed('pi') || piSaving || piFileJsonSaving || !!piSettingsJsonError">{{ t('common.save') }}</button>
|
|
198
|
+
</div>
|
|
199
|
+
<label class="form-label">{{ t('pi.files.modelsTitle') }}</label>
|
|
200
|
+
<textarea
|
|
201
|
+
class="template-textarea config-json-editor"
|
|
202
|
+
v-model="piModelsJsonDraft"
|
|
203
|
+
spellcheck="false"
|
|
204
|
+
autocomplete="off"
|
|
205
|
+
:disabled="!isToolConfigWriteAllowed('pi')"
|
|
206
|
+
@input="piModelsJsonInput"
|
|
207
|
+
placeholder="{}"></textarea>
|
|
208
|
+
<p v-if="piModelsJsonError" class="config-template-hint error-text">{{ piModelsJsonError }}</p>
|
|
209
|
+
<div class="settings-tab-actions">
|
|
210
|
+
<button type="button" class="btn-tool" @click="savePiModelsJson" :disabled="!isToolConfigWriteAllowed('pi') || piSaving || piFileJsonSaving || !!piModelsJsonError">{{ t('common.save') }}</button>
|
|
211
|
+
</div>
|
|
212
|
+
</section>
|
|
162
213
|
<div v-if="!isToolConfigWriteAllowed('pi')" class="tool-config-write-overlay">
|
|
163
214
|
<div class="tool-config-write-overlay-card">
|
|
164
215
|
<div class="tool-config-write-overlay-title">{{ t('toolConfig.pi.lockedTitle') }}</div>
|
|
@@ -661,13 +661,35 @@ return function render(_ctx, _cache) {
|
|
|
661
661
|
_createElementVNode("span", { class: "value" }, _toDisplayString(_ctx.opencodeConfigPath || _ctx.t('common.notSelected')), 1 /* TEXT */)
|
|
662
662
|
])
|
|
663
663
|
], 64 /* STABLE_FRAGMENT */))
|
|
664
|
-
: (
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
664
|
+
: (_ctx.configMode === 'kilocode')
|
|
665
|
+
? (_openBlock(), _createElementBlock(_Fragment, { key: 4 }, [
|
|
666
|
+
_createElementVNode("div", { class: "status-chip" }, [
|
|
667
|
+
_createElementVNode("span", { class: "label" }, _toDisplayString(_ctx.t('status.kilocodeProvider')), 1 /* TEXT */),
|
|
668
|
+
_createElementVNode("span", { class: "value" }, _toDisplayString(_ctx.kilocodeProvider || _ctx.t('common.notSelected')), 1 /* TEXT */)
|
|
669
|
+
]),
|
|
670
|
+
_createElementVNode("div", { class: "status-chip" }, [
|
|
671
|
+
_createElementVNode("span", { class: "label" }, _toDisplayString(_ctx.t('status.kilocodeModel')), 1 /* TEXT */),
|
|
672
|
+
_createElementVNode("span", { class: "value" }, _toDisplayString(_ctx.kilocodeModel || _ctx.t('common.notSelected')), 1 /* TEXT */)
|
|
673
|
+
])
|
|
674
|
+
], 64 /* STABLE_FRAGMENT */))
|
|
675
|
+
: (_ctx.configMode === 'pi')
|
|
676
|
+
? (_openBlock(), _createElementBlock(_Fragment, { key: 5 }, [
|
|
677
|
+
_createElementVNode("div", { class: "status-chip" }, [
|
|
678
|
+
_createElementVNode("span", { class: "label" }, _toDisplayString(_ctx.t('status.piProvider')), 1 /* TEXT */),
|
|
679
|
+
_createElementVNode("span", { class: "value" }, _toDisplayString(_ctx.piActiveProvider || _ctx.t('common.notSelected')), 1 /* TEXT */)
|
|
680
|
+
]),
|
|
681
|
+
_createElementVNode("div", { class: "status-chip" }, [
|
|
682
|
+
_createElementVNode("span", { class: "label" }, _toDisplayString(_ctx.t('status.piModel')), 1 /* TEXT */),
|
|
683
|
+
_createElementVNode("span", { class: "value" }, _toDisplayString(_ctx.piActiveModel || _ctx.t('common.notSelected')), 1 /* TEXT */)
|
|
684
|
+
])
|
|
685
|
+
], 64 /* STABLE_FRAGMENT */))
|
|
686
|
+
: (_openBlock(), _createElementBlock("div", {
|
|
687
|
+
key: 6,
|
|
688
|
+
class: "status-chip"
|
|
689
|
+
}, [
|
|
690
|
+
_createElementVNode("span", { class: "label" }, _toDisplayString(_ctx.t('status.configMode')), 1 /* TEXT */),
|
|
691
|
+
_createElementVNode("span", { class: "value" }, _toDisplayString(_ctx.t('common.notSelected')), 1 /* TEXT */)
|
|
692
|
+
]))
|
|
671
693
|
]))
|
|
672
694
|
: (!_ctx.sessionStandalone && _ctx.mainTab === 'sessions')
|
|
673
695
|
? (_openBlock(), _createElementBlock("div", {
|
|
@@ -3458,6 +3480,32 @@ return function render(_ctx, _cache) {
|
|
|
3458
3480
|
onClick: _ctx.confirmDeletePiProvider,
|
|
3459
3481
|
disabled: !_ctx.isToolConfigWriteAllowed('pi') || _ctx.piSaving
|
|
3460
3482
|
}, _toDisplayString(_ctx.t('pi.providers.delete')), 9 /* TEXT, PROPS */, ["onClick", "disabled"])
|
|
3483
|
+
]),
|
|
3484
|
+
_createElementVNode("section", { class: "selector-section" }, [
|
|
3485
|
+
_createElementVNode("div", { class: "selector-header" }, [
|
|
3486
|
+
_createElementVNode("span", { class: "selector-title" }, _toDisplayString(_ctx.t('pi.providers.json.title')), 1 /* TEXT */)
|
|
3487
|
+
]),
|
|
3488
|
+
_createElementVNode("p", { class: "config-template-hint" }, _toDisplayString(_ctx.t('pi.providers.json.desc')), 1 /* TEXT */),
|
|
3489
|
+
_createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('pi.providers.json.previewTitle')), 1 /* TEXT */),
|
|
3490
|
+
_createElementVNode("pre", { class: "config-json-preview" }, _toDisplayString(_ctx.piProviderPreviewJson()), 1 /* TEXT */),
|
|
3491
|
+
_createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('pi.providers.json.editTitle')), 1 /* TEXT */),
|
|
3492
|
+
_withDirectives(_createElementVNode("textarea", {
|
|
3493
|
+
class: "template-textarea config-json-editor",
|
|
3494
|
+
"onUpdate:modelValue": $event => ((_ctx.editingPiProvider.form.configJsonDraft) = $event),
|
|
3495
|
+
spellcheck: "false",
|
|
3496
|
+
autocomplete: "off",
|
|
3497
|
+
disabled: !_ctx.isToolConfigWriteAllowed('pi'),
|
|
3498
|
+
onInput: _ctx.piEditorJsonDraftInput,
|
|
3499
|
+
placeholder: "{}"
|
|
3500
|
+
}, null, 40 /* PROPS, NEED_HYDRATION */, ["onUpdate:modelValue", "disabled", "onInput"]), [
|
|
3501
|
+
[_vModelText, _ctx.editingPiProvider.form.configJsonDraft]
|
|
3502
|
+
]),
|
|
3503
|
+
(_ctx.piEditorJsonError)
|
|
3504
|
+
? (_openBlock(), _createElementBlock("p", {
|
|
3505
|
+
key: 0,
|
|
3506
|
+
class: "config-template-hint error-text"
|
|
3507
|
+
}, _toDisplayString(_ctx.piEditorJsonError), 1 /* TEXT */))
|
|
3508
|
+
: _createCommentVNode("v-if", true)
|
|
3461
3509
|
])
|
|
3462
3510
|
]))
|
|
3463
3511
|
: _createCommentVNode("v-if", true),
|
|
@@ -3572,6 +3620,64 @@ return function render(_ctx, _cache) {
|
|
|
3572
3620
|
])
|
|
3573
3621
|
]))
|
|
3574
3622
|
: _createCommentVNode("v-if", true),
|
|
3623
|
+
_createElementVNode("section", { class: "selector-section" }, [
|
|
3624
|
+
_createElementVNode("div", { class: "selector-header" }, [
|
|
3625
|
+
_createElementVNode("span", { class: "selector-title" }, _toDisplayString(_ctx.t('pi.files.title')), 1 /* TEXT */)
|
|
3626
|
+
]),
|
|
3627
|
+
_createElementVNode("div", { class: "config-template-hint" }, _toDisplayString(_ctx.t('pi.files.desc')), 1 /* TEXT */),
|
|
3628
|
+
_createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('pi.files.settingsTitle')), 1 /* TEXT */),
|
|
3629
|
+
_withDirectives(_createElementVNode("textarea", {
|
|
3630
|
+
class: "template-textarea config-json-editor",
|
|
3631
|
+
"onUpdate:modelValue": $event => ((_ctx.piSettingsJsonDraft) = $event),
|
|
3632
|
+
spellcheck: "false",
|
|
3633
|
+
autocomplete: "off",
|
|
3634
|
+
disabled: !_ctx.isToolConfigWriteAllowed('pi'),
|
|
3635
|
+
onInput: _ctx.piSettingsJsonInput,
|
|
3636
|
+
placeholder: "{}"
|
|
3637
|
+
}, null, 40 /* PROPS, NEED_HYDRATION */, ["onUpdate:modelValue", "disabled", "onInput"]), [
|
|
3638
|
+
[_vModelText, _ctx.piSettingsJsonDraft]
|
|
3639
|
+
]),
|
|
3640
|
+
(_ctx.piSettingsJsonError)
|
|
3641
|
+
? (_openBlock(), _createElementBlock("p", {
|
|
3642
|
+
key: 0,
|
|
3643
|
+
class: "config-template-hint error-text"
|
|
3644
|
+
}, _toDisplayString(_ctx.piSettingsJsonError), 1 /* TEXT */))
|
|
3645
|
+
: _createCommentVNode("v-if", true),
|
|
3646
|
+
_createElementVNode("div", { class: "settings-tab-actions" }, [
|
|
3647
|
+
_createElementVNode("button", {
|
|
3648
|
+
type: "button",
|
|
3649
|
+
class: "btn-tool",
|
|
3650
|
+
onClick: _ctx.savePiSettingsJson,
|
|
3651
|
+
disabled: !_ctx.isToolConfigWriteAllowed('pi') || _ctx.piSaving || _ctx.piFileJsonSaving || !!_ctx.piSettingsJsonError
|
|
3652
|
+
}, _toDisplayString(_ctx.t('common.save')), 9 /* TEXT, PROPS */, ["onClick", "disabled"])
|
|
3653
|
+
]),
|
|
3654
|
+
_createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('pi.files.modelsTitle')), 1 /* TEXT */),
|
|
3655
|
+
_withDirectives(_createElementVNode("textarea", {
|
|
3656
|
+
class: "template-textarea config-json-editor",
|
|
3657
|
+
"onUpdate:modelValue": $event => ((_ctx.piModelsJsonDraft) = $event),
|
|
3658
|
+
spellcheck: "false",
|
|
3659
|
+
autocomplete: "off",
|
|
3660
|
+
disabled: !_ctx.isToolConfigWriteAllowed('pi'),
|
|
3661
|
+
onInput: _ctx.piModelsJsonInput,
|
|
3662
|
+
placeholder: "{}"
|
|
3663
|
+
}, null, 40 /* PROPS, NEED_HYDRATION */, ["onUpdate:modelValue", "disabled", "onInput"]), [
|
|
3664
|
+
[_vModelText, _ctx.piModelsJsonDraft]
|
|
3665
|
+
]),
|
|
3666
|
+
(_ctx.piModelsJsonError)
|
|
3667
|
+
? (_openBlock(), _createElementBlock("p", {
|
|
3668
|
+
key: 1,
|
|
3669
|
+
class: "config-template-hint error-text"
|
|
3670
|
+
}, _toDisplayString(_ctx.piModelsJsonError), 1 /* TEXT */))
|
|
3671
|
+
: _createCommentVNode("v-if", true),
|
|
3672
|
+
_createElementVNode("div", { class: "settings-tab-actions" }, [
|
|
3673
|
+
_createElementVNode("button", {
|
|
3674
|
+
type: "button",
|
|
3675
|
+
class: "btn-tool",
|
|
3676
|
+
onClick: _ctx.savePiModelsJson,
|
|
3677
|
+
disabled: !_ctx.isToolConfigWriteAllowed('pi') || _ctx.piSaving || _ctx.piFileJsonSaving || !!_ctx.piModelsJsonError
|
|
3678
|
+
}, _toDisplayString(_ctx.t('common.save')), 9 /* TEXT, PROPS */, ["onClick", "disabled"])
|
|
3679
|
+
])
|
|
3680
|
+
]),
|
|
3575
3681
|
(!_ctx.isToolConfigWriteAllowed('pi'))
|
|
3576
3682
|
? (_openBlock(), _createElementBlock("div", {
|
|
3577
3683
|
key: 2,
|
|
@@ -352,6 +352,28 @@
|
|
|
352
352
|
margin-top: 2px;
|
|
353
353
|
}
|
|
354
354
|
|
|
355
|
+
.config-json-preview {
|
|
356
|
+
width: 100%;
|
|
357
|
+
max-height: 240px;
|
|
358
|
+
overflow: auto;
|
|
359
|
+
margin: 0 0 10px;
|
|
360
|
+
padding: 12px;
|
|
361
|
+
border: 1px solid var(--color-border);
|
|
362
|
+
border-radius: var(--radius-md);
|
|
363
|
+
background: rgba(0, 0, 0, 0.04);
|
|
364
|
+
color: var(--color-text-secondary);
|
|
365
|
+
font-family: var(--font-mono);
|
|
366
|
+
font-size: 12px;
|
|
367
|
+
line-height: 1.55;
|
|
368
|
+
white-space: pre;
|
|
369
|
+
box-shadow: var(--shadow-subtle);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
.config-json-editor {
|
|
373
|
+
min-height: 180px;
|
|
374
|
+
margin-bottom: 8px;
|
|
375
|
+
}
|
|
376
|
+
|
|
355
377
|
/* ============================================
|
|
356
378
|
按钮
|
|
357
379
|
============================================ */
|