codexmate 0.1.13 → 0.1.15
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/package.json +1 -1
- package/web-ui/app.js +8 -18
- package/web-ui/modules/app.methods.agents.mjs +31 -4
- package/web-ui/modules/app.methods.pi-config.mjs +70 -44
- package/web-ui/modules/config-mode.computed.mjs +2 -2
- package/web-ui/modules/i18n/locales/en.mjs +4 -0
- package/web-ui/modules/i18n/locales/ja.mjs +4 -0
- package/web-ui/modules/i18n/locales/vi.mjs +4 -0
- package/web-ui/modules/i18n/locales/zh-tw.mjs +4 -0
- package/web-ui/modules/i18n/locales/zh.mjs +4 -0
- package/web-ui/partials/index/layout-header.html +2 -2
- package/web-ui/partials/index/panel-config-pi.html +20 -1
- package/web-ui/res/web-ui-render.precompiled.js +26 -0
- package/web-ui/styles/controls-forms.css +22 -0
package/package.json
CHANGED
package/web-ui/app.js
CHANGED
|
@@ -587,7 +587,11 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
587
587
|
return true;
|
|
588
588
|
}
|
|
589
589
|
})();
|
|
590
|
-
|
|
590
|
+
this.loadWebUiPreferences({ applyNavigation: applyPreferenceNavigation }).then(() => {
|
|
591
|
+
if (this.mainTab === 'prompts' && typeof this.loadPromptsTabContent === 'function') {
|
|
592
|
+
this.loadPromptsTabContent();
|
|
593
|
+
}
|
|
594
|
+
});
|
|
591
595
|
}
|
|
592
596
|
if (typeof this.t === 'function') {
|
|
593
597
|
this.confirmDialogConfirmText = this.t('confirm.ok');
|
|
@@ -786,14 +790,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
786
790
|
return;
|
|
787
791
|
}
|
|
788
792
|
if (newTab === 'prompts') {
|
|
789
|
-
if (
|
|
790
|
-
this.loadProjectPathOptions();
|
|
791
|
-
}
|
|
792
|
-
if (this.promptsSubTab === 'system') {
|
|
793
|
-
if (typeof this.loadSystemPrompt === 'function') this.loadSystemPrompt();
|
|
794
|
-
} else if (typeof this.loadPromptsContent === 'function') {
|
|
795
|
-
this.loadPromptsContent();
|
|
796
|
-
}
|
|
793
|
+
if (typeof this.loadPromptsTabContent === 'function') this.loadPromptsTabContent();
|
|
797
794
|
}
|
|
798
795
|
},
|
|
799
796
|
promptsSubTab(newVal) {
|
|
@@ -805,11 +802,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
805
802
|
return;
|
|
806
803
|
}
|
|
807
804
|
if (this.mainTab === 'prompts') {
|
|
808
|
-
if (this.
|
|
809
|
-
if (typeof this.loadSystemPrompt === 'function') this.loadSystemPrompt();
|
|
810
|
-
} else if (typeof this.loadPromptsContent === 'function') {
|
|
811
|
-
this.loadPromptsContent();
|
|
812
|
-
}
|
|
805
|
+
if (typeof this.loadPromptsTabContent === 'function') this.loadPromptsTabContent();
|
|
813
806
|
}
|
|
814
807
|
},
|
|
815
808
|
projectClaudeMdPath(newPath) {
|
|
@@ -826,10 +819,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
826
819
|
if (typeof this.persistWebUiPreferences === 'function') {
|
|
827
820
|
this.persistWebUiPreferences({ sysPromptMode: newVal });
|
|
828
821
|
}
|
|
829
|
-
}
|
|
830
|
-
},
|
|
831
|
-
|
|
832
|
-
watch: {
|
|
822
|
+
},
|
|
833
823
|
configMode(newMode) {
|
|
834
824
|
if (newMode === 'pi' && typeof this.loadPiSources === 'function') {
|
|
835
825
|
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 {
|
|
@@ -980,17 +992,28 @@ export function createAgentsMethods(options = {}) {
|
|
|
980
992
|
this.loadProjectPathOptions();
|
|
981
993
|
}
|
|
982
994
|
if (this.promptsSubTab === normalized) {
|
|
983
|
-
if (
|
|
984
|
-
else this.loadPromptsContent();
|
|
995
|
+
if (typeof this.loadPromptsTabContent === 'function') this.loadPromptsTabContent();
|
|
985
996
|
return;
|
|
986
997
|
}
|
|
998
|
+
this.__skipNextPromptsSubTabLoad = true;
|
|
987
999
|
this.promptsSubTab = normalized;
|
|
988
|
-
if (
|
|
1000
|
+
if (typeof this.loadPromptsTabContent === 'function') this.loadPromptsTabContent();
|
|
989
1001
|
this.$nextTick(() => {
|
|
990
1002
|
document.querySelector('.main-panel')?.scrollTo({ top: 0, left: 0, behavior: 'auto' });
|
|
991
1003
|
});
|
|
992
1004
|
},
|
|
993
1005
|
|
|
1006
|
+
loadPromptsTabContent() {
|
|
1007
|
+
if (this.promptsSubTab === 'system') {
|
|
1008
|
+
if (typeof this.loadSystemPrompt === 'function') this.loadSystemPrompt();
|
|
1009
|
+
} else {
|
|
1010
|
+
if (this.promptsSubTab === 'claude-project' && !this.projectPathOptions.length && !this.projectPathOptionsLoading && typeof this.loadProjectPathOptions === 'function') {
|
|
1011
|
+
this.loadProjectPathOptions();
|
|
1012
|
+
}
|
|
1013
|
+
if (typeof this.loadPromptsContent === 'function') this.loadPromptsContent();
|
|
1014
|
+
}
|
|
1015
|
+
},
|
|
1016
|
+
|
|
994
1017
|
async loadPromptsContent() {
|
|
995
1018
|
const requestToken = issueLatestRequestToken(this, '_agentsOpenRequestToken');
|
|
996
1019
|
this.agentsLoading = true;
|
|
@@ -1004,7 +1027,11 @@ export function createAgentsMethods(options = {}) {
|
|
|
1004
1027
|
if (!this.projectPathOptions.length && !this.projectPathOptionsLoading && typeof this.loadProjectPathOptions === 'function') {
|
|
1005
1028
|
this.loadProjectPathOptions();
|
|
1006
1029
|
}
|
|
1007
|
-
|
|
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
|
+
}
|
|
1008
1035
|
if (projectPath) {
|
|
1009
1036
|
rpcParams.baseDir = projectPath;
|
|
1010
1037
|
}
|
|
@@ -81,24 +81,13 @@ export function createPiConfigMethods({ api: apiClient }) {
|
|
|
81
81
|
this.piSaving = true;
|
|
82
82
|
try {
|
|
83
83
|
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;
|
|
84
|
+
const { merged, ok, error } = this.piBuildMergedEditorRecord();
|
|
85
|
+
if (!ok || !merged) {
|
|
86
|
+
this.piEditorJsonError = error || '配置 JSON 不合法';
|
|
87
|
+
this.message = this.piEditorJsonError;
|
|
88
|
+
this.messageType = 'error';
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
102
91
|
|
|
103
92
|
await this.persistPiProvider(providerId, merged);
|
|
104
93
|
this.piProviders = { ...this.piProviders, [providerId]: merged };
|
|
@@ -122,6 +111,8 @@ export function createPiConfigMethods({ api: apiClient }) {
|
|
|
122
111
|
const providerId = this.derivePiProviderId(baseUrl);
|
|
123
112
|
const modelId = (this.addingPiProviderModel || '').trim();
|
|
124
113
|
const values = {
|
|
114
|
+
id: providerId,
|
|
115
|
+
name: providerId,
|
|
125
116
|
baseUrl,
|
|
126
117
|
api: this.addingPiProviderApi || 'openai-completions',
|
|
127
118
|
apiKey: (this.addingPiProviderApiKey || '').trim(),
|
|
@@ -151,18 +142,12 @@ export function createPiConfigMethods({ api: apiClient }) {
|
|
|
151
142
|
}
|
|
152
143
|
},
|
|
153
144
|
derivePiProviderId(baseUrl) {
|
|
154
|
-
let
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
const candidate = (base || 'pi-provider').replace(/[^a-zA-Z0-9-]/g, '-')
|
|
161
|
-
.replace(/-+/g, '-').replace(/^-|-$/g, '') || 'pi-provider';
|
|
162
|
-
if (!this.piProviders[candidate]) return candidate;
|
|
163
|
-
let suffix = 2;
|
|
164
|
-
while (this.piProviders[`${candidate}-${suffix}`]) suffix += 1;
|
|
165
|
-
return `${candidate}-${suffix}`;
|
|
145
|
+
let candidate = String(Date.now());
|
|
146
|
+
while (this.piProviders[candidate]) candidate = String(Number(candidate) + 1);
|
|
147
|
+
return candidate;
|
|
148
|
+
},
|
|
149
|
+
piProviderUrlTitle() {
|
|
150
|
+
return '';
|
|
166
151
|
},
|
|
167
152
|
startAddPiProvider() {
|
|
168
153
|
if (!this.isToolConfigWriteAllowed('pi') || this.piSaving) return;
|
|
@@ -236,6 +221,7 @@ export function createPiConfigMethods({ api: apiClient }) {
|
|
|
236
221
|
this.piRemoteModels = [];
|
|
237
222
|
this.piRemoteModelError = '';
|
|
238
223
|
this.piModelSearch = '';
|
|
224
|
+
this.piEditorJsonError = '';
|
|
239
225
|
const provider = this.piProviders[providerId] || {};
|
|
240
226
|
const knownKeys = ['id', 'name', 'title', 'baseUrl', 'api', 'apiKey', 'models', 'headers', 'configJson'];
|
|
241
227
|
const extras = {};
|
|
@@ -273,6 +259,7 @@ export function createPiConfigMethods({ api: apiClient }) {
|
|
|
273
259
|
this.piRemoteModels = [];
|
|
274
260
|
this.piRemoteModelError = '';
|
|
275
261
|
this.piModelSearch = '';
|
|
262
|
+
this.piEditorJsonError = '';
|
|
276
263
|
},
|
|
277
264
|
removePiProviderModel(index) {
|
|
278
265
|
if (!this.editingPiProvider) return;
|
|
@@ -346,20 +333,7 @@ export function createPiConfigMethods({ api: apiClient }) {
|
|
|
346
333
|
this.messageType = 'success';
|
|
347
334
|
},
|
|
348
335
|
piProviderName(providerId) {
|
|
349
|
-
|
|
350
|
-
if (provider.title || provider.name) return provider.title || provider.name;
|
|
351
|
-
const urlTitle = this.piProviderUrlTitle(provider);
|
|
352
|
-
return urlTitle || providerId;
|
|
353
|
-
},
|
|
354
|
-
piProviderUrlTitle(provider) {
|
|
355
|
-
const baseUrl = provider && provider.baseUrl ? String(provider.baseUrl) : '';
|
|
356
|
-
if (!baseUrl) return '';
|
|
357
|
-
try {
|
|
358
|
-
const hostname = new URL(baseUrl).hostname;
|
|
359
|
-
return hostname.replace(/^www\./, '');
|
|
360
|
-
} catch (e) {
|
|
361
|
-
return '';
|
|
362
|
-
}
|
|
336
|
+
return String(providerId || '');
|
|
363
337
|
},
|
|
364
338
|
piProviderSummary(providerId) {
|
|
365
339
|
const provider = this.piProviders[providerId] || {};
|
|
@@ -367,5 +341,57 @@ export function createPiConfigMethods({ api: apiClient }) {
|
|
|
367
341
|
const api = provider.api || '';
|
|
368
342
|
return [baseUrl, api].filter(Boolean).join(' • ') || 'Piper provider';
|
|
369
343
|
}
|
|
344
|
+
,
|
|
345
|
+
piParseEditorJsonDraft() {
|
|
346
|
+
const provider = this.editingPiProvider;
|
|
347
|
+
const draft = provider && provider.form ? String(provider.form.configJsonDraft || '').trim() : '';
|
|
348
|
+
if (!draft) return { ok: true, extras: {} };
|
|
349
|
+
try {
|
|
350
|
+
const parsed = JSON.parse(draft);
|
|
351
|
+
if (parsed === null || Array.isArray(parsed) || typeof parsed !== 'object') {
|
|
352
|
+
return { ok: false, extras: {}, error: '配置 JSON 必须是对象' };
|
|
353
|
+
}
|
|
354
|
+
return { ok: true, extras: parsed };
|
|
355
|
+
} catch (e) {
|
|
356
|
+
return { ok: false, extras: {}, error: e && e.message ? '配置 JSON 解析失败:' + e.message : '配置 JSON 解析失败' };
|
|
357
|
+
}
|
|
358
|
+
},
|
|
359
|
+
piBuildMergedEditorRecord() {
|
|
360
|
+
const provider = this.editingPiProvider;
|
|
361
|
+
if (!provider || !provider.form) return { merged: null, ok: false, error: '未在编辑供应商', extras: {} };
|
|
362
|
+
const draft = this.piParseEditorJsonDraft();
|
|
363
|
+
if (!draft.ok) return { merged: null, ok: false, error: draft.error, extras: {} };
|
|
364
|
+
const values = provider.form || {};
|
|
365
|
+
const extras = draft.extras || {};
|
|
366
|
+
const orig = this.piProviders[provider.id] || {};
|
|
367
|
+
const mapModels = (xs) => (Array.isArray(xs) ? xs : []).map((model) => ({
|
|
368
|
+
...model,
|
|
369
|
+
id: (model && model.id) || '',
|
|
370
|
+
name: (model && (model.name || model.id)) || ''
|
|
371
|
+
}));
|
|
372
|
+
const merged = { ...extras };
|
|
373
|
+
if (merged.baseUrl === undefined) merged.baseUrl = values.baseUrl || '';
|
|
374
|
+
if (merged.api === undefined) merged.api = values.api || '';
|
|
375
|
+
if (merged.apiKey === undefined) merged.apiKey = values.apiKey || '';
|
|
376
|
+
if (merged.models === undefined) merged.models = mapModels(values.models);
|
|
377
|
+
if (isPiPlainObject(orig.headers)) merged.headers = orig.headers;
|
|
378
|
+
if (typeof orig.title === 'string') merged.title = orig.title;
|
|
379
|
+
else if (typeof orig.name === 'string') merged.name = orig.name;
|
|
380
|
+
if (isPiPlainObject(orig.configJson)) merged.configJson = orig.configJson;
|
|
381
|
+
return { merged, ok: true, error: '', extras };
|
|
382
|
+
},
|
|
383
|
+
piProviderPreviewJson() {
|
|
384
|
+
const { merged, ok } = this.piBuildMergedEditorRecord();
|
|
385
|
+
if (!ok || !merged) return '{}';
|
|
386
|
+
try {
|
|
387
|
+
return JSON.stringify(merged, null, 2);
|
|
388
|
+
} catch (_) {
|
|
389
|
+
return '{}';
|
|
390
|
+
}
|
|
391
|
+
},
|
|
392
|
+
piEditorJsonDraftInput() {
|
|
393
|
+
const draft = this.piParseEditorJsonDraft();
|
|
394
|
+
this.piEditorJsonError = draft.ok ? '' : draft.error;
|
|
395
|
+
}
|
|
370
396
|
};
|
|
371
397
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
export const PROVIDER_CONFIG_MODE_META = Object.freeze({
|
|
2
2
|
codex: Object.freeze({
|
|
3
3
|
label: 'Codex',
|
|
4
4
|
modelPlaceholder: '例如: gpt-5.3-codex',
|
|
@@ -148,4 +148,4 @@ export function createConfigModeComputed() {
|
|
|
148
148
|
return '未选择';
|
|
149
149
|
}
|
|
150
150
|
};
|
|
151
|
-
}
|
|
151
|
+
}
|
|
@@ -1346,6 +1346,10 @@ const en = Object.freeze({
|
|
|
1346
1346
|
'pi.providers.fields.apiKey': 'API Key',
|
|
1347
1347
|
'pi.providers.fields.models': 'Models',
|
|
1348
1348
|
'pi.providers.fields.configJson': 'Config JSON',
|
|
1349
|
+
'pi.providers.json.title': 'Config JSON',
|
|
1350
|
+
'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.',
|
|
1351
|
+
'pi.providers.json.previewTitle': 'Preview',
|
|
1352
|
+
'pi.providers.json.editTitle': 'Edit JSON',
|
|
1349
1353
|
'pi.providers.models.remove': 'Remove',
|
|
1350
1354
|
'pi.providers.models.search': 'Search available models…',
|
|
1351
1355
|
'pi.providers.models.remoteCount': '{count} models available, click to add',
|
|
@@ -1347,6 +1347,10 @@ const ja = Object.freeze({
|
|
|
1347
1347
|
'pi.providers.fields.apiKey': 'API Key',
|
|
1348
1348
|
'pi.providers.fields.models': 'モデル',
|
|
1349
1349
|
'pi.providers.fields.configJson': '設定 JSON',
|
|
1350
|
+
'pi.providers.json.title': '設定 JSON',
|
|
1351
|
+
'pi.providers.json.desc': 'フォーム変更と拡張フィールドを統合した最終レコードをリアルタイムにプレビュー。保存時に models.json へ統合します。',
|
|
1352
|
+
'pi.providers.json.previewTitle': 'プレビュー',
|
|
1353
|
+
'pi.providers.json.editTitle': 'JSON を編集',
|
|
1350
1354
|
'pi.providers.models.remove': '削除',
|
|
1351
1355
|
'pi.providers.models.search': '利用可能なモデルを検索…',
|
|
1352
1356
|
'pi.providers.models.remoteCount': '{count} 個のモデルを取得しました。クリックで追加',
|
|
@@ -1315,6 +1315,10 @@ const vi = Object.freeze({
|
|
|
1315
1315
|
'pi.providers.fields.apiKey': 'API Key',
|
|
1316
1316
|
'pi.providers.fields.models': 'Mô hình',
|
|
1317
1317
|
'pi.providers.fields.configJson': 'Cấu hình JSON',
|
|
1318
|
+
'pi.providers.json.title': 'Cấu hình JSON',
|
|
1319
|
+
'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.',
|
|
1320
|
+
'pi.providers.json.previewTitle': 'Xem trước',
|
|
1321
|
+
'pi.providers.json.editTitle': 'Chỉnh sửa JSON',
|
|
1318
1322
|
'pi.providers.models.remove': 'Xóa',
|
|
1319
1323
|
'pi.providers.models.search': 'Tìm kiếm mô hình khả dụng…',
|
|
1320
1324
|
'pi.providers.models.remoteCount': 'Đã lấy {count} mô hình, bấm để thêm',
|
|
@@ -1344,6 +1344,10 @@ const zhTw = Object.freeze({
|
|
|
1344
1344
|
'pi.providers.fields.apiKey': 'API Key',
|
|
1345
1345
|
'pi.providers.fields.models': '模型',
|
|
1346
1346
|
'pi.providers.fields.configJson': '組態 JSON',
|
|
1347
|
+
'pi.providers.json.title': '設定 JSON',
|
|
1348
|
+
'pi.providers.json.desc': '即時預覽表單異動合併後的最終紀錄;儲存時併入 models.json。',
|
|
1349
|
+
'pi.providers.json.previewTitle': '預覽',
|
|
1350
|
+
'pi.providers.json.editTitle': '編輯 JSON',
|
|
1347
1351
|
'pi.providers.models.remove': '刪除',
|
|
1348
1352
|
'pi.providers.models.search': '搜尋可用模型…',
|
|
1349
1353
|
'pi.providers.models.remoteCount': '已取得 {count} 個可用模型,點擊新增',
|
|
@@ -1344,6 +1344,10 @@ const zh = Object.freeze({
|
|
|
1344
1344
|
'pi.providers.fields.apiKey': 'API Key',
|
|
1345
1345
|
'pi.providers.fields.models': '模型',
|
|
1346
1346
|
'pi.providers.fields.configJson': '配置 JSON',
|
|
1347
|
+
'pi.providers.json.title': '配置 JSON',
|
|
1348
|
+
'pi.providers.json.desc': '实时预览表单改动合并后的最终记录;保存时并入 models.json。',
|
|
1349
|
+
'pi.providers.json.previewTitle': '预览',
|
|
1350
|
+
'pi.providers.json.editTitle': '编辑 JSON',
|
|
1347
1351
|
'pi.providers.models.remove': '删除',
|
|
1348
1352
|
'pi.providers.models.search': '搜索可用模型…',
|
|
1349
1353
|
'pi.providers.models.remoteCount': '已拉取 {count} 个可用模型,点击添加',
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
<div id="app" class="container" v-cloak>
|
|
2
2
|
<div v-if="!sessionStandalone" class="mobile-brand-bar">
|
|
3
3
|
<div class="mobile-brand-title">Codex Mate<span v-if="appVersion" class="brand-version"> v{{ appVersion }}</span></div>
|
|
4
4
|
<button
|
|
@@ -569,4 +569,4 @@
|
|
|
569
569
|
</div>
|
|
570
570
|
|
|
571
571
|
<!-- 内容包裹器 - 稳定布局 -->
|
|
572
|
-
<div class="content-wrapper">
|
|
572
|
+
<div class="content-wrapper">
|
|
@@ -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">
|
|
@@ -168,4 +187,4 @@
|
|
|
168
187
|
</div>
|
|
169
188
|
</div>
|
|
170
189
|
</div>
|
|
171
|
-
</div>
|
|
190
|
+
</div>
|
|
@@ -3458,6 +3458,32 @@ return function render(_ctx, _cache) {
|
|
|
3458
3458
|
onClick: _ctx.confirmDeletePiProvider,
|
|
3459
3459
|
disabled: !_ctx.isToolConfigWriteAllowed('pi') || _ctx.piSaving
|
|
3460
3460
|
}, _toDisplayString(_ctx.t('pi.providers.delete')), 9 /* TEXT, PROPS */, ["onClick", "disabled"])
|
|
3461
|
+
]),
|
|
3462
|
+
_createElementVNode("section", { class: "selector-section" }, [
|
|
3463
|
+
_createElementVNode("div", { class: "selector-header" }, [
|
|
3464
|
+
_createElementVNode("span", { class: "selector-title" }, _toDisplayString(_ctx.t('pi.providers.json.title')), 1 /* TEXT */)
|
|
3465
|
+
]),
|
|
3466
|
+
_createElementVNode("p", { class: "config-template-hint" }, _toDisplayString(_ctx.t('pi.providers.json.desc')), 1 /* TEXT */),
|
|
3467
|
+
_createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('pi.providers.json.previewTitle')), 1 /* TEXT */),
|
|
3468
|
+
_createElementVNode("pre", { class: "config-json-preview" }, _toDisplayString(_ctx.piProviderPreviewJson()), 1 /* TEXT */),
|
|
3469
|
+
_createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('pi.providers.json.editTitle')), 1 /* TEXT */),
|
|
3470
|
+
_withDirectives(_createElementVNode("textarea", {
|
|
3471
|
+
class: "template-textarea config-json-editor",
|
|
3472
|
+
"onUpdate:modelValue": $event => ((_ctx.editingPiProvider.form.configJsonDraft) = $event),
|
|
3473
|
+
spellcheck: "false",
|
|
3474
|
+
autocomplete: "off",
|
|
3475
|
+
disabled: !_ctx.isToolConfigWriteAllowed('pi'),
|
|
3476
|
+
onInput: _ctx.piEditorJsonDraftInput,
|
|
3477
|
+
placeholder: "{}"
|
|
3478
|
+
}, null, 40 /* PROPS, NEED_HYDRATION */, ["onUpdate:modelValue", "disabled", "onInput"]), [
|
|
3479
|
+
[_vModelText, _ctx.editingPiProvider.form.configJsonDraft]
|
|
3480
|
+
]),
|
|
3481
|
+
(_ctx.piEditorJsonError)
|
|
3482
|
+
? (_openBlock(), _createElementBlock("p", {
|
|
3483
|
+
key: 0,
|
|
3484
|
+
class: "config-template-hint error-text"
|
|
3485
|
+
}, _toDisplayString(_ctx.piEditorJsonError), 1 /* TEXT */))
|
|
3486
|
+
: _createCommentVNode("v-if", true)
|
|
3461
3487
|
])
|
|
3462
3488
|
]))
|
|
3463
3489
|
: _createCommentVNode("v-if", true),
|
|
@@ -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
|
============================================ */
|