codexmate 0.1.14 → 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 +1 -4
- package/web-ui/modules/app.methods.agents.mjs +17 -1
- package/web-ui/modules/app.methods.pi-config.mjs +61 -18
- 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/panel-config-pi.html +19 -0
- 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
|
@@ -819,10 +819,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
819
819
|
if (typeof this.persistWebUiPreferences === 'function') {
|
|
820
820
|
this.persistWebUiPreferences({ sysPromptMode: newVal });
|
|
821
821
|
}
|
|
822
|
-
}
|
|
823
|
-
},
|
|
824
|
-
|
|
825
|
-
watch: {
|
|
822
|
+
},
|
|
826
823
|
configMode(newMode) {
|
|
827
824
|
if (newMode === 'pi' && typeof this.loadPiSources === 'function') {
|
|
828
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 {
|
|
@@ -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
|
}
|
|
@@ -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 };
|
|
@@ -232,6 +221,7 @@ export function createPiConfigMethods({ api: apiClient }) {
|
|
|
232
221
|
this.piRemoteModels = [];
|
|
233
222
|
this.piRemoteModelError = '';
|
|
234
223
|
this.piModelSearch = '';
|
|
224
|
+
this.piEditorJsonError = '';
|
|
235
225
|
const provider = this.piProviders[providerId] || {};
|
|
236
226
|
const knownKeys = ['id', 'name', 'title', 'baseUrl', 'api', 'apiKey', 'models', 'headers', 'configJson'];
|
|
237
227
|
const extras = {};
|
|
@@ -269,6 +259,7 @@ export function createPiConfigMethods({ api: apiClient }) {
|
|
|
269
259
|
this.piRemoteModels = [];
|
|
270
260
|
this.piRemoteModelError = '';
|
|
271
261
|
this.piModelSearch = '';
|
|
262
|
+
this.piEditorJsonError = '';
|
|
272
263
|
},
|
|
273
264
|
removePiProviderModel(index) {
|
|
274
265
|
if (!this.editingPiProvider) return;
|
|
@@ -350,5 +341,57 @@ export function createPiConfigMethods({ api: apiClient }) {
|
|
|
350
341
|
const api = provider.api || '';
|
|
351
342
|
return [baseUrl, api].filter(Boolean).join(' • ') || 'Piper provider';
|
|
352
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
|
+
}
|
|
353
396
|
};
|
|
354
397
|
}
|
|
@@ -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} 个可用模型,点击添加',
|
|
@@ -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">
|
|
@@ -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
|
============================================ */
|