codexmate 0.1.23 → 0.1.24
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 +3 -0
- package/web-ui/logic.prompts-change-axis.mjs +3 -88
- package/web-ui/logic.prompts-path-reference.mjs +118 -0
- package/web-ui/modules/app.methods.agents.mjs +1 -0
- package/web-ui/modules/app.methods.index.mjs +1 -1
- package/web-ui/modules/app.methods.prompts-editor.mjs +136 -83
- package/web-ui/modules/i18n/locales/en.mjs +11 -1
- package/web-ui/modules/i18n/locales/ja.mjs +11 -1
- package/web-ui/modules/i18n/locales/vi.mjs +11 -1
- package/web-ui/modules/i18n/locales/zh-tw.mjs +11 -1
- package/web-ui/modules/i18n/locales/zh.mjs +11 -1
- package/web-ui/partials/index/panel-prompts.html +22 -14
- package/web-ui/res/web-ui-render.precompiled.js +38 -58
- package/web-ui/styles/prompts-editor.css +17 -25
package/package.json
CHANGED
package/web-ui/app.js
CHANGED
|
@@ -108,6 +108,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
108
108
|
sysChangeAxis: { mode: 'edit', ticks: [], truncated: false, totalLines: 0, added: 0, removed: 0 },
|
|
109
109
|
promptsMobileView: 'edit',
|
|
110
110
|
promptsPreviewLibsMissing: false,
|
|
111
|
+
promptsPathReferencePaths: {},
|
|
112
|
+
promptsPathReferenceLoading: false,
|
|
113
|
+
promptsPathReferenceCacheKey: '',
|
|
111
114
|
agentsHighlightHtml: '',
|
|
112
115
|
sysPromptHighlightHtml: '',
|
|
113
116
|
agentsPreviewHtml: '',
|
|
@@ -1,15 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Prompts-panel change axis: aggregates the
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* The diff engine itself is reused from logic.agents-diff.mjs (LCS for
|
|
7
|
-
* small inputs, window-sync for large ones) so hunk line numbers stay
|
|
8
|
-
* consistent with the red/green preview flow.
|
|
2
|
+
* Prompts-panel change axis: aggregates the rendered diff rows into
|
|
3
|
+
* clickable tick positions for the red/green diff preview view.
|
|
4
|
+
* Pure functions only.
|
|
9
5
|
*/
|
|
10
6
|
|
|
11
|
-
import { buildLineDiff } from './logic.agents-diff.mjs';
|
|
12
|
-
|
|
13
7
|
const AXIS_MAX_TICKS = 200;
|
|
14
8
|
const AXIS_MIN_TICK_HEIGHT_PERCENT = 1.2;
|
|
15
9
|
|
|
@@ -55,64 +49,6 @@ function capAxisTicks(runs, positioning) {
|
|
|
55
49
|
};
|
|
56
50
|
}
|
|
57
51
|
|
|
58
|
-
/**
|
|
59
|
-
* Build change-axis ticks for the editor view.
|
|
60
|
-
*
|
|
61
|
-
* @param {string} baseText saved original content
|
|
62
|
-
* @param {string} currentText current editor content
|
|
63
|
-
* @returns {{ ticks: Array<object>, totalLines: number, truncated: boolean,
|
|
64
|
-
* stats: { added: number, removed: number, unchanged: number } }}
|
|
65
|
-
*/
|
|
66
|
-
export function buildPromptsChangeAxis(baseText, currentText) {
|
|
67
|
-
const diff = buildLineDiff(baseText, currentText);
|
|
68
|
-
const totalLines = Math.max(1, diff.newLineCount);
|
|
69
|
-
const runs = [];
|
|
70
|
-
let run = null;
|
|
71
|
-
let newCursor = 0;
|
|
72
|
-
const flushRun = () => {
|
|
73
|
-
if (run) {
|
|
74
|
-
runs.push(run);
|
|
75
|
-
run = null;
|
|
76
|
-
}
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
for (const line of diff.lines) {
|
|
80
|
-
if (!line || !isChangedDiffType(line.type)) {
|
|
81
|
-
flushRun();
|
|
82
|
-
if (line && line.type === 'context' && typeof line.newNumber === 'number') {
|
|
83
|
-
newCursor = line.newNumber;
|
|
84
|
-
}
|
|
85
|
-
continue;
|
|
86
|
-
}
|
|
87
|
-
if (!run) {
|
|
88
|
-
run = {
|
|
89
|
-
anchor: line.type === 'add' && typeof line.newNumber === 'number'
|
|
90
|
-
? line.newNumber - 1
|
|
91
|
-
: newCursor,
|
|
92
|
-
startLine: line.type === 'add' && typeof line.newNumber === 'number'
|
|
93
|
-
? line.newNumber
|
|
94
|
-
: newCursor + 1,
|
|
95
|
-
added: 0,
|
|
96
|
-
removed: 0
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
if (line.type === 'add') {
|
|
100
|
-
run.added += 1;
|
|
101
|
-
} else {
|
|
102
|
-
run.removed += 1;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
flushRun();
|
|
106
|
-
|
|
107
|
-
const { ticks, truncated } = capAxisTicks(runs, { total: totalLines });
|
|
108
|
-
return {
|
|
109
|
-
ticks,
|
|
110
|
-
totalLines,
|
|
111
|
-
truncated,
|
|
112
|
-
stats: diff.stats
|
|
113
|
-
};
|
|
114
|
-
}
|
|
115
|
-
|
|
116
52
|
/**
|
|
117
53
|
* Build change-axis ticks for the diff preview view. Tick positions map to
|
|
118
54
|
* rendered row indexes so clicks scroll the diff list to the exact row.
|
|
@@ -164,24 +100,3 @@ export function buildPromptsDiffAxis(diffLines) {
|
|
|
164
100
|
};
|
|
165
101
|
}
|
|
166
102
|
|
|
167
|
-
/**
|
|
168
|
-
* Proportional scroll position for jumping to a line inside the editor
|
|
169
|
-
* textarea. The textarea scrolls internally (min-height contract in
|
|
170
|
-
* prompts-editor.css), so scrollTop maps linearly onto the line space.
|
|
171
|
-
*
|
|
172
|
-
* @param {number} scrollHeight textarea scrollHeight
|
|
173
|
-
* @param {number} clientHeight textarea clientHeight
|
|
174
|
-
* @param {number} lineIndex 1-based target line in the current content
|
|
175
|
-
* @param {number} totalLines total line count of the current content
|
|
176
|
-
* @returns {number} clamped scrollTop value
|
|
177
|
-
*/
|
|
178
|
-
export function computePromptsAxisScrollTop(scrollHeight, clientHeight, lineIndex, totalLines) {
|
|
179
|
-
const maxScroll = Math.max(0, (Number(scrollHeight) || 0) - (Number(clientHeight) || 0));
|
|
180
|
-
if (maxScroll <= 0) {
|
|
181
|
-
return 0;
|
|
182
|
-
}
|
|
183
|
-
const safeTotal = Math.max(1, Number(totalLines) || 1);
|
|
184
|
-
const safeLine = Math.max(1, Number(lineIndex) || 1);
|
|
185
|
-
const ratio = Math.min(1, Math.max(0, (safeLine - 1) / Math.max(1, safeTotal - 1)));
|
|
186
|
-
return Math.min(maxScroll, Math.round(maxScroll * ratio));
|
|
187
|
-
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prompts-panel "path reference" logic: build the dropdown entries that
|
|
3
|
+
* point to the OTHER instruction-file tabs' real absolute paths, and
|
|
4
|
+
* splice the rendered reference sentence into editor content at the caret.
|
|
5
|
+
*
|
|
6
|
+
* The inserted sentence is instruction-file CONTENT (not UI text), so it
|
|
7
|
+
* is intentionally a fixed English template, independent of the UI locale.
|
|
8
|
+
*
|
|
9
|
+
* Pure functions only: no Vue, no DOM, no api access.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
export const PROMPT_PATH_REFERENCE_TEMPLATE = 'Always follow the rules defined in `{path}`.';
|
|
13
|
+
|
|
14
|
+
const PROMPT_PATH_REFERENCE_ENTRY_ORDER = ['codex', 'opencode', 'claudeGlobal', 'claudeProject', 'system'];
|
|
15
|
+
|
|
16
|
+
// promptsSubTab value -> entry id excluded from that tab's own dropdown.
|
|
17
|
+
const CURRENT_TAB_EXCLUDED_ENTRY = {
|
|
18
|
+
'codex': 'codex',
|
|
19
|
+
'opencode': 'opencode',
|
|
20
|
+
'claude-project': 'claudeProject',
|
|
21
|
+
'system': 'system'
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export function buildPromptPathReferenceSentence(path) {
|
|
25
|
+
const target = typeof path === 'string' ? path.trim() : '';
|
|
26
|
+
if (!target) {
|
|
27
|
+
return '';
|
|
28
|
+
}
|
|
29
|
+
return PROMPT_PATH_REFERENCE_TEMPLATE.replace('{path}', target);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Splice `text` into `content` at the given selection, replacing the
|
|
34
|
+
* selected range (same contract as typing over a selection). Out-of-range
|
|
35
|
+
* indices are clamped; invalid indices fall back to "insert at end".
|
|
36
|
+
*/
|
|
37
|
+
export function insertPromptPathReferenceText(content, selectionStart, selectionEnd, text) {
|
|
38
|
+
const source = typeof content === 'string' ? content : '';
|
|
39
|
+
const inserted = typeof text === 'string' ? text : '';
|
|
40
|
+
const fallback = source.length;
|
|
41
|
+
const rawStart = Number.isFinite(selectionStart) ? Number(selectionStart) : fallback;
|
|
42
|
+
const rawEnd = Number.isFinite(selectionEnd) ? Number(selectionEnd) : fallback;
|
|
43
|
+
const start = Math.min(Math.max(rawStart, 0), source.length);
|
|
44
|
+
const end = Math.min(Math.max(rawEnd, start), source.length);
|
|
45
|
+
return {
|
|
46
|
+
content: source.slice(0, start) + inserted + source.slice(end),
|
|
47
|
+
caret: start + inserted.length
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Build the dropdown option list for the prompts editors.
|
|
53
|
+
*
|
|
54
|
+
* config:
|
|
55
|
+
* - currentTab: promptsSubTab value ('codex' | 'opencode' | 'claude-project' | 'system')
|
|
56
|
+
* - paths: map entry id -> { path, exists, error } (server-resolved absolute paths)
|
|
57
|
+
* - t: i18n translator, signature t(key, params)
|
|
58
|
+
* - systemFile: file name shown for the Pi system-prompt entry (SYSTEM.md / APPEND_SYSTEM.md)
|
|
59
|
+
*
|
|
60
|
+
* Each option: { id, label, path, exists, disabled, disabledReason }.
|
|
61
|
+
* Missing/error entries stay in the list but render disabled, so a failed
|
|
62
|
+
* fetch is visible instead of silently hiding a tab.
|
|
63
|
+
*/
|
|
64
|
+
export function buildPromptPathReferenceOptions(config) {
|
|
65
|
+
const cfg = config || {};
|
|
66
|
+
const currentTab = CURRENT_TAB_EXCLUDED_ENTRY[cfg.currentTab] ? cfg.currentTab : 'codex';
|
|
67
|
+
const excludedEntry = CURRENT_TAB_EXCLUDED_ENTRY[currentTab];
|
|
68
|
+
const paths = cfg.paths || {};
|
|
69
|
+
const t = typeof cfg.t === 'function' ? cfg.t : ((key) => key);
|
|
70
|
+
const systemFile = typeof cfg.systemFile === 'string' && cfg.systemFile.trim()
|
|
71
|
+
? cfg.systemFile.trim()
|
|
72
|
+
: 'SYSTEM.md';
|
|
73
|
+
|
|
74
|
+
const labelKeys = {
|
|
75
|
+
codex: 'prompts.pathReference.codex',
|
|
76
|
+
opencode: 'prompts.pathReference.opencode',
|
|
77
|
+
claudeGlobal: 'prompts.pathReference.claudeGlobal',
|
|
78
|
+
claudeProject: 'prompts.pathReference.claudeProject',
|
|
79
|
+
system: 'prompts.pathReference.system'
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const options = [];
|
|
83
|
+
for (const id of PROMPT_PATH_REFERENCE_ENTRY_ORDER) {
|
|
84
|
+
if (id === excludedEntry) {
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
const entry = paths[id] || null;
|
|
88
|
+
let label = id === 'system'
|
|
89
|
+
? t(labelKeys[id], { file: systemFile })
|
|
90
|
+
: t(labelKeys[id]);
|
|
91
|
+
let disabled = false;
|
|
92
|
+
let disabledReason = '';
|
|
93
|
+
if (id === 'claudeProject' && !(entry && entry.path)) {
|
|
94
|
+
disabled = true;
|
|
95
|
+
disabledReason = t('prompts.pathReference.projectMissing');
|
|
96
|
+
}
|
|
97
|
+
if (!entry) {
|
|
98
|
+
disabled = true;
|
|
99
|
+
if (!disabledReason) {
|
|
100
|
+
disabledReason = t('prompts.pathReference.notLoaded');
|
|
101
|
+
}
|
|
102
|
+
} else if (entry.error) {
|
|
103
|
+
disabled = true;
|
|
104
|
+
disabledReason = entry.error;
|
|
105
|
+
} else if (entry.path && entry.exists === false) {
|
|
106
|
+
label += ' · ' + t('common.notExistsWillCreateOnSave');
|
|
107
|
+
}
|
|
108
|
+
options.push({
|
|
109
|
+
id,
|
|
110
|
+
label,
|
|
111
|
+
path: entry && entry.path ? entry.path : '',
|
|
112
|
+
exists: entry ? !!entry.exists : false,
|
|
113
|
+
disabled,
|
|
114
|
+
disabledReason
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
return options;
|
|
118
|
+
}
|
|
@@ -1020,6 +1020,7 @@ export function createAgentsMethods(options = {}) {
|
|
|
1020
1020
|
},
|
|
1021
1021
|
|
|
1022
1022
|
loadPromptsTabContent() {
|
|
1023
|
+
if (typeof this.loadPromptsPathReferences === "function") this.loadPromptsPathReferences();
|
|
1023
1024
|
if (this.promptsSubTab === 'system') {
|
|
1024
1025
|
if (typeof this.loadSystemPrompt === 'function') this.loadSystemPrompt();
|
|
1025
1026
|
} else {
|
|
@@ -7,7 +7,9 @@
|
|
|
7
7
|
* State contract (declared in app.js data()):
|
|
8
8
|
* promptsPreviewEnabled, promptsPreviewCollapsed, promptsMobileView,
|
|
9
9
|
* promptsPreviewLibsMissing, agentsHighlightHtml, sysPromptHighlightHtml,
|
|
10
|
-
* agentsPreviewHtml, sysPromptPreviewHtml, agentsChangeAxis, sysChangeAxis
|
|
10
|
+
* agentsPreviewHtml, sysPromptPreviewHtml, agentsChangeAxis, sysChangeAxis,
|
|
11
|
+
* promptsPathReferencePaths, promptsPathReferenceLoading,
|
|
12
|
+
* promptsPathReferenceCacheKey (path-reference dropdown)
|
|
11
13
|
* Template contract:
|
|
12
14
|
* refs promptsAgentsTextarea / promptsSysTextarea on the two textareas,
|
|
13
15
|
* refs promptsAgentsHighlight / promptsSysHighlight on the backdrop <pre>,
|
|
@@ -19,9 +21,12 @@ import {
|
|
|
19
21
|
highlightMarkdownText
|
|
20
22
|
} from '../logic.markdown-editor.mjs';
|
|
21
23
|
import {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
buildPromptPathReferenceOptions as buildPromptPathReferenceOptionList,
|
|
25
|
+
buildPromptPathReferenceSentence,
|
|
26
|
+
insertPromptPathReferenceText
|
|
27
|
+
} from '../logic.prompts-path-reference.mjs';
|
|
28
|
+
import {
|
|
29
|
+
buildPromptsDiffAxis
|
|
25
30
|
} from '../logic.prompts-change-axis.mjs';
|
|
26
31
|
|
|
27
32
|
const PROMPTS_HIGHLIGHT_DEBOUNCE_MS = 150;
|
|
@@ -83,7 +88,9 @@ function resolvePromptsPreviewLibs() {
|
|
|
83
88
|
return { marked: window.marked || null, purify: window.DOMPurify || null };
|
|
84
89
|
}
|
|
85
90
|
|
|
86
|
-
export function createPromptsEditorMethods() {
|
|
91
|
+
export function createPromptsEditorMethods(options = {}) {
|
|
92
|
+
const { api } = options;
|
|
93
|
+
|
|
87
94
|
return {
|
|
88
95
|
promptsEditorMeta(key) {
|
|
89
96
|
return PROMPTS_EDITOR_META[key] || null;
|
|
@@ -188,25 +195,12 @@ export function createPromptsEditorMethods() {
|
|
|
188
195
|
added: Number(stats && stats.added) || 0,
|
|
189
196
|
removed: Number(stats && stats.removed) || 0
|
|
190
197
|
};
|
|
191
|
-
this.consumePromptsAxisPendingJump(key);
|
|
192
|
-
return;
|
|
193
|
-
}
|
|
194
|
-
this.clearPromptsAxisPendingJump(key);
|
|
195
|
-
const current = this[meta.contentField];
|
|
196
|
-
const original = this[meta.originalField];
|
|
197
|
-
if (typeof current !== 'string' || current === original) {
|
|
198
|
-
this[meta.axisField] = emptyPromptsChangeAxis();
|
|
199
198
|
return;
|
|
200
199
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
truncated: axis.truncated,
|
|
206
|
-
totalLines: axis.totalLines,
|
|
207
|
-
added: Number(axis.stats && axis.stats.added) || 0,
|
|
208
|
-
removed: Number(axis.stats && axis.stats.removed) || 0
|
|
209
|
-
};
|
|
200
|
+
// Edit mode renders no axis (the axis is a diff-preview-only
|
|
201
|
+
// affordance): keep it empty so the full line-diff cost is only
|
|
202
|
+
// paid while the red/green preview is open.
|
|
203
|
+
this[meta.axisField] = emptyPromptsChangeAxis();
|
|
210
204
|
},
|
|
211
205
|
|
|
212
206
|
schedulePromptsChangeAxis(key) {
|
|
@@ -241,85 +235,144 @@ export function createPromptsEditorMethods() {
|
|
|
241
235
|
}
|
|
242
236
|
return;
|
|
243
237
|
}
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
const canOpenDiff = typeof this[meta.prepareDiffMethod] === 'function'
|
|
250
|
-
&& !this[meta.loadingField]
|
|
251
|
-
&& !this[meta.savingField]
|
|
252
|
-
&& !this[meta.diffLoadingField];
|
|
253
|
-
if (canOpenDiff) {
|
|
254
|
-
this._promptsAxisPendingJump = { key, startLine: tick.startLine };
|
|
255
|
-
this[meta.prepareDiffMethod]();
|
|
256
|
-
return;
|
|
238
|
+
},
|
|
239
|
+
|
|
240
|
+
setPromptsMobileView(view) {
|
|
241
|
+
if (view === 'edit' || view === 'preview') {
|
|
242
|
+
this.promptsMobileView = view;
|
|
257
243
|
}
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
if (
|
|
263
|
-
|
|
244
|
+
},
|
|
245
|
+
|
|
246
|
+
togglePromptsPreviewCollapsed() {
|
|
247
|
+
this.promptsPreviewCollapsed = !this.promptsPreviewCollapsed;
|
|
248
|
+
if (typeof this.persistWebUiPreferences === 'function') {
|
|
249
|
+
this.persistWebUiPreferences({ promptsPreviewCollapsed: this.promptsPreviewCollapsed });
|
|
264
250
|
}
|
|
265
|
-
textarea.scrollTop = computePromptsAxisScrollTop(
|
|
266
|
-
textarea.scrollHeight,
|
|
267
|
-
textarea.clientHeight,
|
|
268
|
-
tick.startLine,
|
|
269
|
-
axis.totalLines
|
|
270
|
-
);
|
|
271
|
-
this.syncPromptsOverlayScroll(key);
|
|
272
251
|
},
|
|
273
252
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
this.
|
|
253
|
+
buildPromptsPathReferenceCacheKey() {
|
|
254
|
+
return [
|
|
255
|
+
(this.projectClaudeMdPath || '').trim(),
|
|
256
|
+
this.sysPromptScope || 'global',
|
|
257
|
+
this.sysPromptMode || 'system'
|
|
258
|
+
].join('|');
|
|
259
|
+
},
|
|
260
|
+
|
|
261
|
+
// Lazy loader for the path-reference dropdown. Fetches the OTHER tabs'
|
|
262
|
+
// real absolute paths via the existing metaOnly RPC contracts
|
|
263
|
+
// (get-agents-file / get-opencode-agents-file / get-claude-md-file
|
|
264
|
+
// return path + exists without content; get-system-prompt returns
|
|
265
|
+
// path + a small SYSTEM.md/APPEND_SYSTEM.md read). Cache key covers the
|
|
266
|
+
// only inputs that change a resolved path: project baseDir, sysPrompt
|
|
267
|
+
// scope and mode. Idempotent per key; concurrent callers share the
|
|
268
|
+
// in-flight promise.
|
|
269
|
+
loadPromptsPathReferences() {
|
|
270
|
+
const cacheKey = this.buildPromptsPathReferenceCacheKey();
|
|
271
|
+
if (this.promptsPathReferenceCacheKey === cacheKey && !this.promptsPathReferenceLoading) {
|
|
272
|
+
return Promise.resolve();
|
|
277
273
|
}
|
|
274
|
+
if (this.promptsPathReferenceLoading && this._promptsPathReferencePromise) {
|
|
275
|
+
return this._promptsPathReferencePromise;
|
|
276
|
+
}
|
|
277
|
+
if (typeof api !== 'function') {
|
|
278
|
+
return Promise.resolve();
|
|
279
|
+
}
|
|
280
|
+
const projectPath = (this.projectClaudeMdPath || '').trim();
|
|
281
|
+
const scope = this.sysPromptScope || 'global';
|
|
282
|
+
const mode = this.sysPromptMode || 'system';
|
|
283
|
+
const fetchEntry = async (action, params) => {
|
|
284
|
+
try {
|
|
285
|
+
const res = await api(action, params);
|
|
286
|
+
if (res && res.error) {
|
|
287
|
+
return { path: '', exists: false, error: String(res.error) };
|
|
288
|
+
}
|
|
289
|
+
return { path: (res && res.path) || '', exists: !!(res && res.exists) };
|
|
290
|
+
} catch (e) {
|
|
291
|
+
return {
|
|
292
|
+
path: '',
|
|
293
|
+
exists: false,
|
|
294
|
+
error: typeof this.t === 'function' ? this.t('prompts.pathReference.loadFailed') : 'load failed'
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
};
|
|
298
|
+
this.promptsPathReferenceLoading = true;
|
|
299
|
+
const promise = Promise.all([
|
|
300
|
+
fetchEntry('get-agents-file', { metaOnly: true }),
|
|
301
|
+
fetchEntry('get-opencode-agents-file', { metaOnly: true }),
|
|
302
|
+
fetchEntry('get-claude-md-file', { metaOnly: true }),
|
|
303
|
+
projectPath
|
|
304
|
+
? fetchEntry('get-claude-md-file', { baseDir: projectPath, metaOnly: true })
|
|
305
|
+
: Promise.resolve(null),
|
|
306
|
+
fetchEntry('get-system-prompt', { scope, mode })
|
|
307
|
+
]).then((results) => {
|
|
308
|
+
this.promptsPathReferencePaths = {
|
|
309
|
+
codex: results[0],
|
|
310
|
+
opencode: results[1],
|
|
311
|
+
claudeGlobal: results[2],
|
|
312
|
+
claudeProject: results[3] || { path: '', exists: false, error: '' },
|
|
313
|
+
system: results[4]
|
|
314
|
+
};
|
|
315
|
+
this.promptsPathReferenceCacheKey = cacheKey;
|
|
316
|
+
}).finally(() => {
|
|
317
|
+
this.promptsPathReferenceLoading = false;
|
|
318
|
+
this._promptsPathReferencePromise = null;
|
|
319
|
+
});
|
|
320
|
+
this._promptsPathReferencePromise = promise;
|
|
321
|
+
return promise;
|
|
278
322
|
},
|
|
279
323
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
324
|
+
promptsPathReferenceOptionList() {
|
|
325
|
+
return buildPromptPathReferenceOptionList({
|
|
326
|
+
currentTab: this.promptsSubTab,
|
|
327
|
+
paths: this.promptsPathReferencePaths || {},
|
|
328
|
+
t: (key, params) => (typeof this.t === 'function' ? this.t(key, params) : key),
|
|
329
|
+
systemFile: (this.sysPromptMode || 'system') === 'append' ? 'APPEND_SYSTEM.md' : 'SYSTEM.md'
|
|
330
|
+
});
|
|
331
|
+
},
|
|
332
|
+
|
|
333
|
+
insertPromptPathReference(entryId, key, event) {
|
|
334
|
+
const select = event && event.target;
|
|
335
|
+
if (select && typeof select.value === 'string') {
|
|
336
|
+
select.value = '';
|
|
284
337
|
}
|
|
285
338
|
const meta = this.promptsEditorMeta(key);
|
|
286
|
-
|
|
287
|
-
|
|
339
|
+
const entry = (this.promptsPathReferencePaths || {})[entryId];
|
|
340
|
+
if (!meta || !entry || !entry.path || entry.error) {
|
|
288
341
|
return;
|
|
289
342
|
}
|
|
290
|
-
|
|
291
|
-
if (!axis || axis.mode !== 'diff' || !axis.ticks.length) {
|
|
343
|
+
if (this[meta.loadingField] || this[meta.savingField] || this[meta.diffVisibleField]) {
|
|
292
344
|
return;
|
|
293
345
|
}
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
const
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
346
|
+
const sentence = buildPromptPathReferenceSentence(entry.path);
|
|
347
|
+
if (!sentence) {
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
const textarea = typeof this.$refs === 'object' && this.$refs
|
|
351
|
+
? this.$refs[meta.textareaRef]
|
|
352
|
+
: null;
|
|
353
|
+
const content = typeof this[meta.contentField] === 'string' ? this[meta.contentField] : '';
|
|
354
|
+
let start = content.length;
|
|
355
|
+
let end = content.length;
|
|
356
|
+
if (textarea && typeof textarea.selectionStart === 'number') {
|
|
357
|
+
start = textarea.selectionStart;
|
|
358
|
+
end = textarea.selectionEnd;
|
|
359
|
+
}
|
|
360
|
+
const result = insertPromptPathReferenceText(content, start, end, sentence);
|
|
361
|
+
this[meta.contentField] = result.content;
|
|
362
|
+
this.schedulePromptsEditorRefresh(key);
|
|
363
|
+
const restoreCaret = () => {
|
|
364
|
+
if (textarea && typeof textarea.setSelectionRange === 'function') {
|
|
365
|
+
textarea.setSelectionRange(result.caret, result.caret);
|
|
366
|
+
textarea.focus();
|
|
304
367
|
}
|
|
305
368
|
};
|
|
306
369
|
if (typeof this.$nextTick === 'function') {
|
|
307
|
-
this.$nextTick(
|
|
370
|
+
this.$nextTick(restoreCaret);
|
|
308
371
|
} else {
|
|
309
|
-
|
|
372
|
+
restoreCaret();
|
|
310
373
|
}
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
setPromptsMobileView(view) {
|
|
314
|
-
if (view === 'edit' || view === 'preview') {
|
|
315
|
-
this.promptsMobileView = view;
|
|
316
|
-
}
|
|
317
|
-
},
|
|
318
|
-
|
|
319
|
-
togglePromptsPreviewCollapsed() {
|
|
320
|
-
this.promptsPreviewCollapsed = !this.promptsPreviewCollapsed;
|
|
321
|
-
if (typeof this.persistWebUiPreferences === 'function') {
|
|
322
|
-
this.persistWebUiPreferences({ promptsPreviewCollapsed: this.promptsPreviewCollapsed });
|
|
374
|
+
if (typeof this.showMessage === 'function') {
|
|
375
|
+
this.showMessage(this.t('prompts.pathReference.toast.inserted'), 'success');
|
|
323
376
|
}
|
|
324
377
|
}
|
|
325
378
|
};
|
|
@@ -232,6 +232,17 @@ const en = Object.freeze({
|
|
|
232
232
|
'prompts.subTab.opencode': 'AGENTS.md (OpenCode)',
|
|
233
233
|
'prompts.subTab.project': 'CLAUDE.md',
|
|
234
234
|
'prompts.subTab.system': 'System Prompt (Pi)',
|
|
235
|
+
'prompts.pathReference.title': 'Insert rule reference',
|
|
236
|
+
'prompts.pathReference.placeholder': 'Insert rule reference…',
|
|
237
|
+
'prompts.pathReference.codex': 'AGENTS.md (Codex)',
|
|
238
|
+
'prompts.pathReference.opencode': 'AGENTS.md (OpenCode)',
|
|
239
|
+
'prompts.pathReference.claudeGlobal': 'CLAUDE.md (Global)',
|
|
240
|
+
'prompts.pathReference.claudeProject': 'CLAUDE.md (Project)',
|
|
241
|
+
'prompts.pathReference.system': '{file} (Pi System Prompt)',
|
|
242
|
+
'prompts.pathReference.projectMissing': 'No project path selected',
|
|
243
|
+
'prompts.pathReference.notLoaded': 'Loading path…',
|
|
244
|
+
'prompts.pathReference.loadFailed': 'Failed to load path',
|
|
245
|
+
'prompts.pathReference.toast.inserted': 'Rule reference inserted',
|
|
235
246
|
'prompts.subTab.presets': 'Preset pool',
|
|
236
247
|
'prompts.editor.toolbar': 'Markdown toolbar',
|
|
237
248
|
'prompts.editor.collapsePreview': 'Collapse preview',
|
|
@@ -243,7 +254,6 @@ const en = Object.freeze({
|
|
|
243
254
|
'prompts.editor.previewEmpty': 'Nothing to preview yet',
|
|
244
255
|
'prompts.editor.changeAxis': 'Change navigation axis',
|
|
245
256
|
'prompts.editor.changeAxisTick': 'Line {line} (+{added} / -{removed})',
|
|
246
|
-
'prompts.editor.changeAxisTruncated': 'Too many changed regions; collapsed to summary',
|
|
247
257
|
'prompts.presets.title': 'Presets',
|
|
248
258
|
'prompts.presets.hint': 'Manage presets.',
|
|
249
259
|
'prompts.presets.namePlaceholder': 'Preset name',
|
|
@@ -233,6 +233,17 @@ const ja = Object.freeze({
|
|
|
233
233
|
'prompts.subTab.opencode': 'AGENTS.md (OpenCode)',
|
|
234
234
|
'prompts.subTab.project': 'CLAUDE.md',
|
|
235
235
|
'prompts.subTab.system': 'System Prompt (Pi)',
|
|
236
|
+
'prompts.pathReference.title': 'ルール参照を挿入',
|
|
237
|
+
'prompts.pathReference.placeholder': 'ルール参照を挿入…',
|
|
238
|
+
'prompts.pathReference.codex': 'AGENTS.md (Codex)',
|
|
239
|
+
'prompts.pathReference.opencode': 'AGENTS.md (OpenCode)',
|
|
240
|
+
'prompts.pathReference.claudeGlobal': 'CLAUDE.md(グローバル)',
|
|
241
|
+
'prompts.pathReference.claudeProject': 'CLAUDE.md(現在のプロジェクト)',
|
|
242
|
+
'prompts.pathReference.system': '{file}(Pi System Prompt)',
|
|
243
|
+
'prompts.pathReference.projectMissing': 'プロジェクトパス未選択',
|
|
244
|
+
'prompts.pathReference.notLoaded': 'パス読み込み中…',
|
|
245
|
+
'prompts.pathReference.loadFailed': 'パスの読み込みに失敗しました',
|
|
246
|
+
'prompts.pathReference.toast.inserted': 'ルール参照を挿入しました',
|
|
236
247
|
'prompts.subTab.presets': 'プリセット',
|
|
237
248
|
'prompts.editor.toolbar': 'Markdown ツールバー',
|
|
238
249
|
'prompts.editor.collapsePreview': 'プレビューを折りたたむ',
|
|
@@ -244,7 +255,6 @@ const ja = Object.freeze({
|
|
|
244
255
|
'prompts.editor.previewEmpty': 'プレビューする内容がありません',
|
|
245
256
|
'prompts.editor.changeAxis': '変更ナビゲーション軸',
|
|
246
257
|
'prompts.editor.changeAxisTick': '{line} 行目(+{added} / -{removed})',
|
|
247
|
-
'prompts.editor.changeAxisTruncated': '変更領域が多すぎるため、統計に折りたたまれました',
|
|
248
258
|
'prompts.presets.title': 'プリセット',
|
|
249
259
|
'prompts.presets.hint': 'プリセットを管理します。',
|
|
250
260
|
'prompts.presets.namePlaceholder': 'プリセット名',
|
|
@@ -250,6 +250,17 @@ const vi = Object.freeze({
|
|
|
250
250
|
'prompts.subTab.opencode': 'AGENTS.md (OpenCode)',
|
|
251
251
|
'prompts.subTab.project': 'CLAUDE.md',
|
|
252
252
|
'prompts.subTab.system': 'System Prompt (Pi)',
|
|
253
|
+
'prompts.pathReference.title': 'Chèn tham chiếu quy tắc',
|
|
254
|
+
'prompts.pathReference.placeholder': 'Chèn tham chiếu quy tắc…',
|
|
255
|
+
'prompts.pathReference.codex': 'AGENTS.md (Codex)',
|
|
256
|
+
'prompts.pathReference.opencode': 'AGENTS.md (OpenCode)',
|
|
257
|
+
'prompts.pathReference.claudeGlobal': 'CLAUDE.md (Toàn cục)',
|
|
258
|
+
'prompts.pathReference.claudeProject': 'CLAUDE.md (Dự án hiện tại)',
|
|
259
|
+
'prompts.pathReference.system': '{file} (System Prompt Pi)',
|
|
260
|
+
'prompts.pathReference.projectMissing': 'Chưa chọn đường dẫn dự án',
|
|
261
|
+
'prompts.pathReference.notLoaded': 'Đang tải đường dẫn…',
|
|
262
|
+
'prompts.pathReference.loadFailed': 'Tải đường dẫn thất bại',
|
|
263
|
+
'prompts.pathReference.toast.inserted': 'Đã chèn tham chiếu quy tắc',
|
|
253
264
|
'prompts.subTab.presets': 'Kho preset',
|
|
254
265
|
'prompts.editor.toolbar': 'Thanh công cụ Markdown',
|
|
255
266
|
'prompts.editor.collapsePreview': 'Thu gọn bản xem trước',
|
|
@@ -261,7 +272,6 @@ const vi = Object.freeze({
|
|
|
261
272
|
'prompts.editor.previewEmpty': 'Chưa có nội dung để xem trước',
|
|
262
273
|
'prompts.editor.changeAxis': 'Trục điều hướng thay đổi',
|
|
263
274
|
'prompts.editor.changeAxisTick': 'Dòng {line} (+{added} / -{removed})',
|
|
264
|
-
'prompts.editor.changeAxisTruncated': 'Quá nhiều vùng thay đổi; đã thu gọn thành thống kê',
|
|
265
275
|
'prompts.presets.title': 'Preset',
|
|
266
276
|
'prompts.presets.hint': 'Quản lý preset.',
|
|
267
277
|
'prompts.presets.namePlaceholder': 'Tên preset',
|
|
@@ -232,6 +232,17 @@ const zhTw = Object.freeze({
|
|
|
232
232
|
'prompts.subTab.opencode': 'AGENTS.md (OpenCode)',
|
|
233
233
|
'prompts.subTab.project': 'CLAUDE.md',
|
|
234
234
|
'prompts.subTab.system': 'System Prompt (Pi)',
|
|
235
|
+
'prompts.pathReference.title': '插入規則引用',
|
|
236
|
+
'prompts.pathReference.placeholder': '插入規則引用…',
|
|
237
|
+
'prompts.pathReference.codex': 'AGENTS.md (Codex)',
|
|
238
|
+
'prompts.pathReference.opencode': 'AGENTS.md (OpenCode)',
|
|
239
|
+
'prompts.pathReference.claudeGlobal': 'CLAUDE.md(全域)',
|
|
240
|
+
'prompts.pathReference.claudeProject': 'CLAUDE.md(目前專案)',
|
|
241
|
+
'prompts.pathReference.system': '{file}(Pi System Prompt)',
|
|
242
|
+
'prompts.pathReference.projectMissing': '未選擇專案路徑',
|
|
243
|
+
'prompts.pathReference.notLoaded': '路徑載入中…',
|
|
244
|
+
'prompts.pathReference.loadFailed': '路徑載入失敗',
|
|
245
|
+
'prompts.pathReference.toast.inserted': '已插入規則引用',
|
|
235
246
|
'prompts.subTab.presets': '預設池',
|
|
236
247
|
'prompts.editor.toolbar': 'Markdown 工具列',
|
|
237
248
|
'prompts.editor.collapsePreview': '收起預覽',
|
|
@@ -243,7 +254,6 @@ const zhTw = Object.freeze({
|
|
|
243
254
|
'prompts.editor.previewEmpty': '尚無內容可預覽',
|
|
244
255
|
'prompts.editor.changeAxis': '改動導覽軸',
|
|
245
256
|
'prompts.editor.changeAxisTick': '第 {line} 行(+{added} / -{removed})',
|
|
246
|
-
'prompts.editor.changeAxisTruncated': '改動區域過多,已摺疊為統計',
|
|
247
257
|
'prompts.presets.title': '預設池',
|
|
248
258
|
'prompts.presets.hint': '管理預設。',
|
|
249
259
|
'prompts.presets.namePlaceholder': '預設名稱',
|
|
@@ -232,6 +232,17 @@ const zh = Object.freeze({
|
|
|
232
232
|
'prompts.subTab.opencode': 'AGENTS.md (OpenCode)',
|
|
233
233
|
'prompts.subTab.project': 'CLAUDE.md',
|
|
234
234
|
'prompts.subTab.system': 'System Prompt (Pi)',
|
|
235
|
+
'prompts.pathReference.title': '插入规则引用',
|
|
236
|
+
'prompts.pathReference.placeholder': '插入规则引用…',
|
|
237
|
+
'prompts.pathReference.codex': 'AGENTS.md (Codex)',
|
|
238
|
+
'prompts.pathReference.opencode': 'AGENTS.md (OpenCode)',
|
|
239
|
+
'prompts.pathReference.claudeGlobal': 'CLAUDE.md(全局)',
|
|
240
|
+
'prompts.pathReference.claudeProject': 'CLAUDE.md(当前项目)',
|
|
241
|
+
'prompts.pathReference.system': '{file}(Pi System Prompt)',
|
|
242
|
+
'prompts.pathReference.projectMissing': '未选择项目路径',
|
|
243
|
+
'prompts.pathReference.notLoaded': '路径加载中…',
|
|
244
|
+
'prompts.pathReference.loadFailed': '路径加载失败',
|
|
245
|
+
'prompts.pathReference.toast.inserted': '已插入规则引用',
|
|
235
246
|
'prompts.subTab.presets': '预设池',
|
|
236
247
|
'prompts.editor.toolbar': 'Markdown 工具栏',
|
|
237
248
|
'prompts.editor.collapsePreview': '收起预览',
|
|
@@ -243,7 +254,6 @@ const zh = Object.freeze({
|
|
|
243
254
|
'prompts.editor.previewEmpty': '暂无内容可预览',
|
|
244
255
|
'prompts.editor.changeAxis': '改动导航轴',
|
|
245
256
|
'prompts.editor.changeAxisTick': '第 {line} 行(+{added} / -{removed})',
|
|
246
|
-
'prompts.editor.changeAxisTruncated': '改动区域过多,已折叠为统计',
|
|
247
257
|
'prompts.presets.title': '预设池',
|
|
248
258
|
'prompts.presets.hint': '管理预设。',
|
|
249
259
|
'prompts.presets.namePlaceholder': '预设名称',
|
|
@@ -44,6 +44,17 @@
|
|
|
44
44
|
</span>
|
|
45
45
|
</div>
|
|
46
46
|
<div class="prompts-editor-actions">
|
|
47
|
+
<div class="prompts-editor-group prompts-editor-group--pathref">
|
|
48
|
+
<select
|
|
49
|
+
class="form-input prompts-path-reference-select"
|
|
50
|
+
:disabled="agentsLoading || agentsSaving || agentsDiffVisible || promptsPathReferenceLoading"
|
|
51
|
+
:title="t('prompts.pathReference.title')"
|
|
52
|
+
@focus="loadPromptsPathReferences()"
|
|
53
|
+
@change="insertPromptPathReference($event.target.value, 'agents', $event)">
|
|
54
|
+
<option value="">{{ t('prompts.pathReference.placeholder') }}</option>
|
|
55
|
+
<option v-for="opt in promptsPathReferenceOptionList()" :key="opt.id" :value="opt.id" :disabled="opt.disabled">{{ opt.label }}</option>
|
|
56
|
+
</select>
|
|
57
|
+
</div>
|
|
47
58
|
<div class="prompts-editor-group prompts-editor-group--secondary">
|
|
48
59
|
<button
|
|
49
60
|
class="btn-mini"
|
|
@@ -233,13 +244,6 @@
|
|
|
233
244
|
@input="onAgentsContentInput"
|
|
234
245
|
@scroll="syncPromptsOverlayScroll('agents')"
|
|
235
246
|
:placeholder="t(promptsSubTab === 'claude-project' ? 'modal.agents.placeholder.claudeProject' : 'modal.agents.placeholder')"></textarea>
|
|
236
|
-
<div v-if="!agentsDiffVisible && agentsChangeAxis.ticks.length" class="prompts-change-axis" role="navigation" :aria-label="t('prompts.editor.changeAxis')">
|
|
237
|
-
<button v-for="(tick, index) in agentsChangeAxis.ticks" :key="'agents-change-axis-' + index" type="button" class="prompts-change-tick" :class="'prompts-change-tick--' + tick.kind" :style="{ top: tick.top + '%', height: tick.height + '%' }" :title="t('prompts.editor.changeAxisTick', { line: tick.startLine, added: tick.added, removed: tick.removed })" @click="jumpToPromptsChangeTick('agents', tick)"></button>
|
|
238
|
-
</div>
|
|
239
|
-
<div v-else-if="!agentsDiffVisible && agentsChangeAxis.truncated" class="prompts-change-axis prompts-change-axis--summary" :title="t('prompts.editor.changeAxisTruncated')">
|
|
240
|
-
<span class="prompts-change-summary add">+{{ agentsChangeAxis.added }}</span>
|
|
241
|
-
<span class="prompts-change-summary del">-{{ agentsChangeAxis.removed }}</span>
|
|
242
|
-
</div>
|
|
243
247
|
</div>
|
|
244
248
|
<div v-if="promptsPreviewEnabled" class="prompts-preview-pane">
|
|
245
249
|
<div v-if="promptsPreviewLibsMissing" class="state-message error">{{ t('prompts.editor.previewUnavailable') }}</div>
|
|
@@ -282,6 +286,17 @@
|
|
|
282
286
|
</span>
|
|
283
287
|
</div>
|
|
284
288
|
<div class="prompts-editor-actions">
|
|
289
|
+
<div class="prompts-editor-group prompts-editor-group--pathref">
|
|
290
|
+
<select
|
|
291
|
+
class="form-input prompts-path-reference-select"
|
|
292
|
+
:disabled="sysPromptLoading || sysPromptSaving || sysPromptDiffVisible || promptsPathReferenceLoading"
|
|
293
|
+
:title="t('prompts.pathReference.title')"
|
|
294
|
+
@focus="loadPromptsPathReferences()"
|
|
295
|
+
@change="insertPromptPathReference($event.target.value, 'sys', $event)">
|
|
296
|
+
<option value="">{{ t('prompts.pathReference.placeholder') }}</option>
|
|
297
|
+
<option v-for="opt in promptsPathReferenceOptionList()" :key="opt.id" :value="opt.id" :disabled="opt.disabled">{{ opt.label }}</option>
|
|
298
|
+
</select>
|
|
299
|
+
</div>
|
|
285
300
|
<div class="prompts-editor-group prompts-editor-group--secondary">
|
|
286
301
|
<button class="btn-mini" @click="exportSysPromptContent" :disabled="sysPromptLoading || sysPromptSaving || !sysPromptContent" :title="t('modal.agents.export')">
|
|
287
302
|
<svg class="btn-icon-sm" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 3v12M8 11l4 4 4-4M4 17v2h16v-2"/></svg>
|
|
@@ -386,13 +401,6 @@
|
|
|
386
401
|
:readonly="sysPromptLoading || sysPromptSaving || sysPromptDiffVisible"
|
|
387
402
|
@scroll="syncPromptsOverlayScroll('sys')"
|
|
388
403
|
:placeholder="t('sysPrompt.placeholder')"></textarea>
|
|
389
|
-
<div v-if="!sysPromptDiffVisible && sysChangeAxis.ticks.length" class="prompts-change-axis" role="navigation" :aria-label="t('prompts.editor.changeAxis')">
|
|
390
|
-
<button v-for="(tick, index) in sysChangeAxis.ticks" :key="'sys-change-axis-' + index" type="button" class="prompts-change-tick" :class="'prompts-change-tick--' + tick.kind" :style="{ top: tick.top + '%', height: tick.height + '%' }" :title="t('prompts.editor.changeAxisTick', { line: tick.startLine, added: tick.added, removed: tick.removed })" @click="jumpToPromptsChangeTick('sys', tick)"></button>
|
|
391
|
-
</div>
|
|
392
|
-
<div v-else-if="!sysPromptDiffVisible && sysChangeAxis.truncated" class="prompts-change-axis prompts-change-axis--summary" :title="t('prompts.editor.changeAxisTruncated')">
|
|
393
|
-
<span class="prompts-change-summary add">+{{ sysChangeAxis.added }}</span>
|
|
394
|
-
<span class="prompts-change-summary del">-{{ sysChangeAxis.removed }}</span>
|
|
395
|
-
</div>
|
|
396
404
|
</div>
|
|
397
405
|
<div v-if="promptsPreviewEnabled" class="prompts-preview-pane">
|
|
398
406
|
<div v-if="promptsPreviewLibsMissing" class="state-message error">{{ t('prompts.editor.previewUnavailable') }}</div>
|
|
@@ -6953,6 +6953,24 @@ return function render(_ctx, _cache) {
|
|
|
6953
6953
|
: _createCommentVNode("v-if", true)
|
|
6954
6954
|
]),
|
|
6955
6955
|
_createElementVNode("div", { class: "prompts-editor-actions" }, [
|
|
6956
|
+
_createElementVNode("div", { class: "prompts-editor-group prompts-editor-group--pathref" }, [
|
|
6957
|
+
_createElementVNode("select", {
|
|
6958
|
+
class: "form-input prompts-path-reference-select",
|
|
6959
|
+
disabled: _ctx.agentsLoading || _ctx.agentsSaving || _ctx.agentsDiffVisible || _ctx.promptsPathReferenceLoading,
|
|
6960
|
+
title: _ctx.t('prompts.pathReference.title'),
|
|
6961
|
+
onFocus: $event => (_ctx.loadPromptsPathReferences()),
|
|
6962
|
+
onChange: $event => (_ctx.insertPromptPathReference($event.target.value, 'agents', $event))
|
|
6963
|
+
}, [
|
|
6964
|
+
_createElementVNode("option", { value: "" }, _toDisplayString(_ctx.t('prompts.pathReference.placeholder')), 1 /* TEXT */),
|
|
6965
|
+
(_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.promptsPathReferenceOptionList(), (opt) => {
|
|
6966
|
+
return (_openBlock(), _createElementBlock("option", {
|
|
6967
|
+
key: opt.id,
|
|
6968
|
+
value: opt.id,
|
|
6969
|
+
disabled: opt.disabled
|
|
6970
|
+
}, _toDisplayString(opt.label), 9 /* TEXT, PROPS */, ["value", "disabled"]))
|
|
6971
|
+
}), 128 /* KEYED_FRAGMENT */))
|
|
6972
|
+
], 40 /* PROPS, NEED_HYDRATION */, ["disabled", "title", "onFocus", "onChange"])
|
|
6973
|
+
]),
|
|
6956
6974
|
_createElementVNode("div", { class: "prompts-editor-group prompts-editor-group--secondary" }, [
|
|
6957
6975
|
_createElementVNode("button", {
|
|
6958
6976
|
class: "btn-mini",
|
|
@@ -7424,35 +7442,7 @@ return function render(_ctx, _cache) {
|
|
|
7424
7442
|
placeholder: _ctx.t(_ctx.promptsSubTab === 'claude-project' ? 'modal.agents.placeholder.claudeProject' : 'modal.agents.placeholder')
|
|
7425
7443
|
}, null, 40 /* PROPS, NEED_HYDRATION */, ["onUpdate:modelValue", "readonly", "onInput", "onScroll", "placeholder"]), [
|
|
7426
7444
|
[_vModelText, _ctx.agentsContent]
|
|
7427
|
-
])
|
|
7428
|
-
(!_ctx.agentsDiffVisible && _ctx.agentsChangeAxis.ticks.length)
|
|
7429
|
-
? (_openBlock(), _createElementBlock("div", {
|
|
7430
|
-
key: 0,
|
|
7431
|
-
class: "prompts-change-axis",
|
|
7432
|
-
role: "navigation",
|
|
7433
|
-
"aria-label": _ctx.t('prompts.editor.changeAxis')
|
|
7434
|
-
}, [
|
|
7435
|
-
(_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.agentsChangeAxis.ticks, (tick, index) => {
|
|
7436
|
-
return (_openBlock(), _createElementBlock("button", {
|
|
7437
|
-
key: 'agents-change-axis-' + index,
|
|
7438
|
-
type: "button",
|
|
7439
|
-
class: _normalizeClass(["prompts-change-tick", 'prompts-change-tick--' + tick.kind]),
|
|
7440
|
-
style: _normalizeStyle({ top: tick.top + '%', height: tick.height + '%' }),
|
|
7441
|
-
title: _ctx.t('prompts.editor.changeAxisTick', { line: tick.startLine, added: tick.added, removed: tick.removed }),
|
|
7442
|
-
onClick: $event => (_ctx.jumpToPromptsChangeTick('agents', tick))
|
|
7443
|
-
}, null, 14 /* CLASS, STYLE, PROPS */, ["title", "onClick"]))
|
|
7444
|
-
}), 128 /* KEYED_FRAGMENT */))
|
|
7445
|
-
], 8 /* PROPS */, ["aria-label"]))
|
|
7446
|
-
: (!_ctx.agentsDiffVisible && _ctx.agentsChangeAxis.truncated)
|
|
7447
|
-
? (_openBlock(), _createElementBlock("div", {
|
|
7448
|
-
key: 1,
|
|
7449
|
-
class: "prompts-change-axis prompts-change-axis--summary",
|
|
7450
|
-
title: _ctx.t('prompts.editor.changeAxisTruncated')
|
|
7451
|
-
}, [
|
|
7452
|
-
_createElementVNode("span", { class: "prompts-change-summary add" }, "+" + _toDisplayString(_ctx.agentsChangeAxis.added), 1 /* TEXT */),
|
|
7453
|
-
_createElementVNode("span", { class: "prompts-change-summary del" }, "-" + _toDisplayString(_ctx.agentsChangeAxis.removed), 1 /* TEXT */)
|
|
7454
|
-
], 8 /* PROPS */, ["title"]))
|
|
7455
|
-
: _createCommentVNode("v-if", true)
|
|
7445
|
+
])
|
|
7456
7446
|
]),
|
|
7457
7447
|
(_ctx.promptsPreviewEnabled)
|
|
7458
7448
|
? (_openBlock(), _createElementBlock("div", {
|
|
@@ -7524,6 +7514,24 @@ return function render(_ctx, _cache) {
|
|
|
7524
7514
|
: _createCommentVNode("v-if", true)
|
|
7525
7515
|
]),
|
|
7526
7516
|
_createElementVNode("div", { class: "prompts-editor-actions" }, [
|
|
7517
|
+
_createElementVNode("div", { class: "prompts-editor-group prompts-editor-group--pathref" }, [
|
|
7518
|
+
_createElementVNode("select", {
|
|
7519
|
+
class: "form-input prompts-path-reference-select",
|
|
7520
|
+
disabled: _ctx.sysPromptLoading || _ctx.sysPromptSaving || _ctx.sysPromptDiffVisible || _ctx.promptsPathReferenceLoading,
|
|
7521
|
+
title: _ctx.t('prompts.pathReference.title'),
|
|
7522
|
+
onFocus: $event => (_ctx.loadPromptsPathReferences()),
|
|
7523
|
+
onChange: $event => (_ctx.insertPromptPathReference($event.target.value, 'sys', $event))
|
|
7524
|
+
}, [
|
|
7525
|
+
_createElementVNode("option", { value: "" }, _toDisplayString(_ctx.t('prompts.pathReference.placeholder')), 1 /* TEXT */),
|
|
7526
|
+
(_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.promptsPathReferenceOptionList(), (opt) => {
|
|
7527
|
+
return (_openBlock(), _createElementBlock("option", {
|
|
7528
|
+
key: opt.id,
|
|
7529
|
+
value: opt.id,
|
|
7530
|
+
disabled: opt.disabled
|
|
7531
|
+
}, _toDisplayString(opt.label), 9 /* TEXT, PROPS */, ["value", "disabled"]))
|
|
7532
|
+
}), 128 /* KEYED_FRAGMENT */))
|
|
7533
|
+
], 40 /* PROPS, NEED_HYDRATION */, ["disabled", "title", "onFocus", "onChange"])
|
|
7534
|
+
]),
|
|
7527
7535
|
_createElementVNode("div", { class: "prompts-editor-group prompts-editor-group--secondary" }, [
|
|
7528
7536
|
_createElementVNode("button", {
|
|
7529
7537
|
class: "btn-mini",
|
|
@@ -7900,35 +7908,7 @@ return function render(_ctx, _cache) {
|
|
|
7900
7908
|
placeholder: _ctx.t('sysPrompt.placeholder')
|
|
7901
7909
|
}, null, 40 /* PROPS, NEED_HYDRATION */, ["onUpdate:modelValue", "readonly", "onScroll", "placeholder"]), [
|
|
7902
7910
|
[_vModelText, _ctx.sysPromptContent]
|
|
7903
|
-
])
|
|
7904
|
-
(!_ctx.sysPromptDiffVisible && _ctx.sysChangeAxis.ticks.length)
|
|
7905
|
-
? (_openBlock(), _createElementBlock("div", {
|
|
7906
|
-
key: 0,
|
|
7907
|
-
class: "prompts-change-axis",
|
|
7908
|
-
role: "navigation",
|
|
7909
|
-
"aria-label": _ctx.t('prompts.editor.changeAxis')
|
|
7910
|
-
}, [
|
|
7911
|
-
(_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.sysChangeAxis.ticks, (tick, index) => {
|
|
7912
|
-
return (_openBlock(), _createElementBlock("button", {
|
|
7913
|
-
key: 'sys-change-axis-' + index,
|
|
7914
|
-
type: "button",
|
|
7915
|
-
class: _normalizeClass(["prompts-change-tick", 'prompts-change-tick--' + tick.kind]),
|
|
7916
|
-
style: _normalizeStyle({ top: tick.top + '%', height: tick.height + '%' }),
|
|
7917
|
-
title: _ctx.t('prompts.editor.changeAxisTick', { line: tick.startLine, added: tick.added, removed: tick.removed }),
|
|
7918
|
-
onClick: $event => (_ctx.jumpToPromptsChangeTick('sys', tick))
|
|
7919
|
-
}, null, 14 /* CLASS, STYLE, PROPS */, ["title", "onClick"]))
|
|
7920
|
-
}), 128 /* KEYED_FRAGMENT */))
|
|
7921
|
-
], 8 /* PROPS */, ["aria-label"]))
|
|
7922
|
-
: (!_ctx.sysPromptDiffVisible && _ctx.sysChangeAxis.truncated)
|
|
7923
|
-
? (_openBlock(), _createElementBlock("div", {
|
|
7924
|
-
key: 1,
|
|
7925
|
-
class: "prompts-change-axis prompts-change-axis--summary",
|
|
7926
|
-
title: _ctx.t('prompts.editor.changeAxisTruncated')
|
|
7927
|
-
}, [
|
|
7928
|
-
_createElementVNode("span", { class: "prompts-change-summary add" }, "+" + _toDisplayString(_ctx.sysChangeAxis.added), 1 /* TEXT */),
|
|
7929
|
-
_createElementVNode("span", { class: "prompts-change-summary del" }, "-" + _toDisplayString(_ctx.sysChangeAxis.removed), 1 /* TEXT */)
|
|
7930
|
-
], 8 /* PROPS */, ["title"]))
|
|
7931
|
-
: _createCommentVNode("v-if", true)
|
|
7911
|
+
])
|
|
7932
7912
|
]),
|
|
7933
7913
|
(_ctx.promptsPreviewEnabled)
|
|
7934
7914
|
? (_openBlock(), _createElementBlock("div", {
|
|
@@ -364,31 +364,6 @@
|
|
|
364
364
|
position: relative;
|
|
365
365
|
}
|
|
366
366
|
|
|
367
|
-
.prompts-change-axis--summary {
|
|
368
|
-
display: flex;
|
|
369
|
-
flex-direction: column;
|
|
370
|
-
align-items: flex-end;
|
|
371
|
-
gap: 2px;
|
|
372
|
-
width: auto;
|
|
373
|
-
font-size: 10px;
|
|
374
|
-
font-weight: var(--font-weight-secondary);
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
.prompts-change-summary {
|
|
378
|
-
padding: 0 6px;
|
|
379
|
-
border-radius: 999px;
|
|
380
|
-
white-space: nowrap;
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
.prompts-change-summary.add {
|
|
384
|
-
color: #2b6a3b;
|
|
385
|
-
background: rgba(57, 181, 97, 0.12);
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
.prompts-change-summary.del {
|
|
389
|
-
color: #8a2f36;
|
|
390
|
-
background: rgba(220, 95, 108, 0.12);
|
|
391
|
-
}
|
|
392
367
|
/* Mobile: force single column and edit/preview tab switching */
|
|
393
368
|
@media (max-width: 767.98px) {
|
|
394
369
|
.prompts-mobile-view-switch {
|
|
@@ -420,3 +395,20 @@
|
|
|
420
395
|
min-height: 12px;
|
|
421
396
|
}
|
|
422
397
|
}
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
.prompts-editor-group--pathref .prompts-path-reference-select {
|
|
401
|
+
width: auto;
|
|
402
|
+
max-width: 190px;
|
|
403
|
+
min-width: 120px;
|
|
404
|
+
padding: 5px 8px;
|
|
405
|
+
font-size: var(--font-size-caption);
|
|
406
|
+
color: var(--color-text-secondary);
|
|
407
|
+
cursor: pointer;
|
|
408
|
+
flex-shrink: 1;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
.prompts-editor-group--pathref .prompts-path-reference-select:disabled {
|
|
412
|
+
opacity: 0.6;
|
|
413
|
+
cursor: not-allowed;
|
|
414
|
+
}
|