dsh-composer-ux 0.2.0 → 0.3.0
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/CHANGELOG.md +32 -0
- package/README.md +16 -3
- package/lib/client.js +621 -151
- package/lib/client.js.map +4 -4
- package/lib/index.js +321 -6
- package/lib/index.js.map +4 -4
- package/package.json +3 -3
package/lib/client.js
CHANGED
|
@@ -60,8 +60,13 @@ var MENU_NATIVE_FIELD = "menuNative";
|
|
|
60
60
|
var QUICK_PROMPTS_FIELD = "quickPrompts";
|
|
61
61
|
var OPTIMIZER_TIER_FIELD = "optimizerTier";
|
|
62
62
|
var QUICK_PROMPT_MAX = 60;
|
|
63
|
+
var QUICK_CATEGORY_MAX = 20;
|
|
64
|
+
var QUICK_CATEGORY_NAME_MAX = 40;
|
|
63
65
|
var QUICK_LABEL_MAX = 40;
|
|
64
|
-
var QUICK_TEXT_MAX =
|
|
66
|
+
var QUICK_TEXT_MAX = 2e5;
|
|
67
|
+
var QUICK_PROMPTS_API_PATH = "/composer-ux/prompts";
|
|
68
|
+
var QUICK_BOOK_VERSION = 2;
|
|
69
|
+
var DEFAULT_CATEGORY_NAME = "\u9ED8\u8BA4";
|
|
65
70
|
var OPTIMIZER_API_PATH = "/composer-ux/optimize";
|
|
66
71
|
var OPTIMIZER_TIERS = [
|
|
67
72
|
{ id: "basic", label: "\u666E\u901A", hint: "\u53EA\u505A\u8BED\u8A00\u5C42\u4FEE\u590D\uFF1A\u75C5\u53E5\u3001\u9519\u522B\u5B57\u3001\u6307\u4EE3\u4E0E\u542B\u7CCA\u8BCD\uFF0C\u4E0D\u65B0\u589E\u4EFB\u4F55\u9700\u6C42\uFF0C\u7BC7\u5E45\u4E0E\u539F\u6587\u76F8\u5F53\u3002" },
|
|
@@ -83,6 +88,86 @@ var DEFAULT_QUICK_PROMPTS = [
|
|
|
83
88
|
function newQuickPromptId() {
|
|
84
89
|
return `qp-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
85
90
|
}
|
|
91
|
+
function newQuickCategoryId() {
|
|
92
|
+
return `qc-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
93
|
+
}
|
|
94
|
+
function defaultQuickBook() {
|
|
95
|
+
return {
|
|
96
|
+
version: QUICK_BOOK_VERSION,
|
|
97
|
+
categories: [{ id: "cat-default", name: DEFAULT_CATEGORY_NAME, prompts: DEFAULT_QUICK_PROMPTS }]
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
function asPromptRow(value) {
|
|
101
|
+
if (typeof value !== "object" || value === null) return void 0;
|
|
102
|
+
const row2 = value;
|
|
103
|
+
const either = (first, second) => {
|
|
104
|
+
const picked = typeof first === "string" && first !== "" ? first : second;
|
|
105
|
+
return typeof picked === "string" ? picked : "";
|
|
106
|
+
};
|
|
107
|
+
const prompt = either(row2.prompt, row2.text).slice(0, QUICK_TEXT_MAX).trim();
|
|
108
|
+
if (prompt === "") return void 0;
|
|
109
|
+
const label = either(row2.label, row2.title).slice(0, QUICK_LABEL_MAX).trim();
|
|
110
|
+
const id = typeof row2.id === "string" && row2.id !== "" ? row2.id.slice(0, 64) : newQuickPromptId();
|
|
111
|
+
const order = typeof row2.order === "number" && Number.isFinite(row2.order) ? Math.max(1, Math.round(row2.order)) : void 0;
|
|
112
|
+
return {
|
|
113
|
+
prompt: { id, label: label === "" ? prompt.slice(0, 12) : label, prompt, always: row2.always === true || row2.autoSend === true },
|
|
114
|
+
order
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
function toPromptList(values) {
|
|
118
|
+
const rows = [];
|
|
119
|
+
for (const value of values) {
|
|
120
|
+
const row2 = asPromptRow(value);
|
|
121
|
+
if (row2 !== void 0) rows.push({ ...row2, index: rows.length });
|
|
122
|
+
}
|
|
123
|
+
rows.sort((a, b) => {
|
|
124
|
+
const left = a.order ?? Number.MAX_SAFE_INTEGER;
|
|
125
|
+
const right = b.order ?? Number.MAX_SAFE_INTEGER;
|
|
126
|
+
return left === right ? a.index - b.index : left - right;
|
|
127
|
+
});
|
|
128
|
+
const seen = /* @__PURE__ */ new Set();
|
|
129
|
+
const out = [];
|
|
130
|
+
for (const row2 of rows) {
|
|
131
|
+
if (out.length >= QUICK_PROMPT_MAX) break;
|
|
132
|
+
if (seen.has(row2.prompt.id)) continue;
|
|
133
|
+
seen.add(row2.prompt.id);
|
|
134
|
+
out.push(row2.prompt);
|
|
135
|
+
}
|
|
136
|
+
return out;
|
|
137
|
+
}
|
|
138
|
+
function sanitizeBook(value) {
|
|
139
|
+
if (typeof value !== "object" || value === null) return void 0;
|
|
140
|
+
const source = value;
|
|
141
|
+
const flat = Array.isArray(value) ? value : Array.isArray(source.prompts) ? source.prompts : void 0;
|
|
142
|
+
if (flat !== void 0) {
|
|
143
|
+
const prompts = toPromptList(flat);
|
|
144
|
+
return {
|
|
145
|
+
version: QUICK_BOOK_VERSION,
|
|
146
|
+
categories: prompts.length === 0 ? [] : [{ id: "cat-default", name: DEFAULT_CATEGORY_NAME, prompts }]
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
if (!Array.isArray(source.categories)) return void 0;
|
|
150
|
+
const seen = /* @__PURE__ */ new Set();
|
|
151
|
+
const categories = [];
|
|
152
|
+
for (const raw of source.categories) {
|
|
153
|
+
if (categories.length >= QUICK_CATEGORY_MAX) break;
|
|
154
|
+
if (typeof raw !== "object" || raw === null) continue;
|
|
155
|
+
const row2 = raw;
|
|
156
|
+
const prompts = toPromptList(Array.isArray(row2.prompts) ? row2.prompts : []);
|
|
157
|
+
const wanted = typeof row2.id === "string" && row2.id !== "" ? row2.id.slice(0, 64) : newQuickCategoryId();
|
|
158
|
+
const id = seen.has(wanted) ? newQuickCategoryId() : wanted;
|
|
159
|
+
seen.add(id);
|
|
160
|
+
const name2 = (typeof row2.name === "string" ? row2.name : "").slice(0, QUICK_CATEGORY_NAME_MAX).trim();
|
|
161
|
+
categories.push({ id, name: name2 === "" ? DEFAULT_CATEGORY_NAME : name2, prompts });
|
|
162
|
+
}
|
|
163
|
+
return { version: QUICK_BOOK_VERSION, categories };
|
|
164
|
+
}
|
|
165
|
+
function flattenQuickPrompts(book) {
|
|
166
|
+
return book.categories.flatMap((category) => category.prompts);
|
|
167
|
+
}
|
|
168
|
+
function alwaysQuickPrompts(book) {
|
|
169
|
+
return flattenQuickPrompts(book).filter((prompt) => prompt.always);
|
|
170
|
+
}
|
|
86
171
|
var HEADER_ENABLED_FIELD = "headerEnabled";
|
|
87
172
|
var HEADER_NAME_FIELD = "headerName";
|
|
88
173
|
var HEADER_VALUE_FIELD = "headerValue";
|
|
@@ -208,6 +293,130 @@ function sanitizeSettings(value) {
|
|
|
208
293
|
};
|
|
209
294
|
}
|
|
210
295
|
|
|
296
|
+
// src/client/prompt-book.ts
|
|
297
|
+
async function requestBook(method, body) {
|
|
298
|
+
try {
|
|
299
|
+
const response = await fetch(QUICK_PROMPTS_API_PATH, {
|
|
300
|
+
method,
|
|
301
|
+
headers: body === void 0 ? void 0 : { "content-type": "application/json" },
|
|
302
|
+
body: body === void 0 ? void 0 : JSON.stringify(body)
|
|
303
|
+
});
|
|
304
|
+
const text = await response.text();
|
|
305
|
+
let parsed;
|
|
306
|
+
try {
|
|
307
|
+
parsed = JSON.parse(text);
|
|
308
|
+
} catch {
|
|
309
|
+
return { ok: false, error: `\u670D\u52A1\u7AEF\u8FD4\u56DE\u7684\u4E0D\u662F JSON\uFF08HTTP ${String(response.status)}\uFF09` };
|
|
310
|
+
}
|
|
311
|
+
const row2 = typeof parsed === "object" && parsed !== null ? parsed : {};
|
|
312
|
+
const book = sanitizeBook(row2.book);
|
|
313
|
+
const textOf = (value) => typeof value === "string" && value !== "" ? value : void 0;
|
|
314
|
+
return {
|
|
315
|
+
ok: row2.ok === true,
|
|
316
|
+
...book === void 0 ? {} : { book },
|
|
317
|
+
...textOf(row2.error) === void 0 ? {} : { error: textOf(row2.error) },
|
|
318
|
+
...textOf(row2.file) === void 0 ? {} : { file: textOf(row2.file) },
|
|
319
|
+
...textOf(row2.quarantined) === void 0 ? {} : { quarantined: textOf(row2.quarantined) }
|
|
320
|
+
};
|
|
321
|
+
} catch (error) {
|
|
322
|
+
return { ok: false, error: error instanceof Error ? error.message : String(error) };
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
function loadPromptBook() {
|
|
326
|
+
return requestBook("GET");
|
|
327
|
+
}
|
|
328
|
+
function savePromptBook(book) {
|
|
329
|
+
return requestBook("POST", { book });
|
|
330
|
+
}
|
|
331
|
+
function categoryOf(book, categoryId) {
|
|
332
|
+
return book.categories.find((category) => category.id === categoryId);
|
|
333
|
+
}
|
|
334
|
+
function findPrompt(book, promptId) {
|
|
335
|
+
for (const category of book.categories) {
|
|
336
|
+
const prompt = category.prompts.find((item) => item.id === promptId);
|
|
337
|
+
if (prompt !== void 0) return { category, prompt };
|
|
338
|
+
}
|
|
339
|
+
return void 0;
|
|
340
|
+
}
|
|
341
|
+
function bookCounts(book) {
|
|
342
|
+
const prompts = book.categories.flatMap((category) => category.prompts);
|
|
343
|
+
return {
|
|
344
|
+
categories: book.categories.length,
|
|
345
|
+
prompts: prompts.length,
|
|
346
|
+
always: prompts.filter((prompt) => prompt.always).length
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
function mapCategory(book, categoryId, edit) {
|
|
350
|
+
return {
|
|
351
|
+
version: book.version,
|
|
352
|
+
categories: book.categories.map((category) => category.id === categoryId ? edit(category) : category)
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
function withCategoryAdded(book, name2) {
|
|
356
|
+
if (book.categories.length >= QUICK_CATEGORY_MAX) return book;
|
|
357
|
+
const clean = name2.trim().slice(0, QUICK_CATEGORY_NAME_MAX);
|
|
358
|
+
return {
|
|
359
|
+
version: book.version,
|
|
360
|
+
categories: [...book.categories, { id: newQuickCategoryId(), name: clean === "" ? DEFAULT_CATEGORY_NAME : clean, prompts: [] }]
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
function withCategoryRenamed(book, categoryId, name2) {
|
|
364
|
+
const clean = name2.trim().slice(0, QUICK_CATEGORY_NAME_MAX);
|
|
365
|
+
return mapCategory(book, categoryId, (category) => ({ ...category, name: clean === "" ? DEFAULT_CATEGORY_NAME : clean }));
|
|
366
|
+
}
|
|
367
|
+
function withCategoryRemoved(book, categoryId) {
|
|
368
|
+
return { version: book.version, categories: book.categories.filter((category) => category.id !== categoryId) };
|
|
369
|
+
}
|
|
370
|
+
function withCategoryMoved(book, categoryId, delta) {
|
|
371
|
+
const index = book.categories.findIndex((category) => category.id === categoryId);
|
|
372
|
+
const next = index + delta;
|
|
373
|
+
if (index < 0 || next < 0 || next >= book.categories.length) return book;
|
|
374
|
+
const categories = [...book.categories];
|
|
375
|
+
const [moved] = categories.splice(index, 1);
|
|
376
|
+
categories.splice(next, 0, moved);
|
|
377
|
+
return { version: book.version, categories };
|
|
378
|
+
}
|
|
379
|
+
function withPromptAdded(book, categoryId) {
|
|
380
|
+
return mapCategory(book, categoryId, (category) => {
|
|
381
|
+
if (category.prompts.length >= QUICK_PROMPT_MAX) return category;
|
|
382
|
+
return { ...category, prompts: [...category.prompts, { id: newQuickPromptId(), label: "\u65B0\u6307\u4EE4", prompt: "", always: false }] };
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
function withPromptPatched(book, categoryId, promptId, patch) {
|
|
386
|
+
return mapCategory(book, categoryId, (category) => ({
|
|
387
|
+
...category,
|
|
388
|
+
prompts: category.prompts.map((prompt) => {
|
|
389
|
+
if (prompt.id !== promptId) return prompt;
|
|
390
|
+
const label = patch.label === void 0 ? prompt.label : patch.label.slice(0, QUICK_LABEL_MAX);
|
|
391
|
+
const text = patch.prompt === void 0 ? prompt.prompt : patch.prompt.slice(0, QUICK_TEXT_MAX);
|
|
392
|
+
const always = patch.always === void 0 ? prompt.always : patch.always;
|
|
393
|
+
return { id: prompt.id, label, prompt: text, always };
|
|
394
|
+
})
|
|
395
|
+
}));
|
|
396
|
+
}
|
|
397
|
+
function withPromptRemoved(book, categoryId, promptId) {
|
|
398
|
+
return mapCategory(book, categoryId, (category) => ({
|
|
399
|
+
...category,
|
|
400
|
+
prompts: category.prompts.filter((prompt) => prompt.id !== promptId)
|
|
401
|
+
}));
|
|
402
|
+
}
|
|
403
|
+
function withPromptMoved(book, categoryId, promptId, delta) {
|
|
404
|
+
const category = categoryOf(book, categoryId);
|
|
405
|
+
if (category === void 0) return book;
|
|
406
|
+
const index = category.prompts.findIndex((prompt) => prompt.id === promptId);
|
|
407
|
+
const next = index + delta;
|
|
408
|
+
if (index < 0 || next < 0 || next >= category.prompts.length) return book;
|
|
409
|
+
const prompts = [...category.prompts];
|
|
410
|
+
const [moved] = prompts.splice(index, 1);
|
|
411
|
+
prompts.splice(next, 0, moved);
|
|
412
|
+
return mapCategory(book, categoryId, (target) => ({ ...target, prompts }));
|
|
413
|
+
}
|
|
414
|
+
function withAlwaysToggled(book, promptId, value) {
|
|
415
|
+
const hit = findPrompt(book, promptId);
|
|
416
|
+
if (hit === void 0) return book;
|
|
417
|
+
return withPromptPatched(book, hit.category.id, promptId, { always: value });
|
|
418
|
+
}
|
|
419
|
+
|
|
211
420
|
// src/client/chords.ts
|
|
212
421
|
var MODIFIER_KEYS = /* @__PURE__ */ new Set(["Control", "Alt", "Shift", "Meta", "AltGraph"]);
|
|
213
422
|
var CODE_LABELS = {
|
|
@@ -472,7 +681,7 @@ function installInterceptors(deps) {
|
|
|
472
681
|
event.stopPropagation();
|
|
473
682
|
if (event.repeat) return;
|
|
474
683
|
if (gesture === "send") {
|
|
475
|
-
applyAlwaysPrompts(
|
|
684
|
+
applyAlwaysPrompts(deps.alwaysPrompts());
|
|
476
685
|
dispatchKey(root, chordToInit("Enter"));
|
|
477
686
|
} else if (gesture === "newline") {
|
|
478
687
|
dispatchKey(root, chordToInit("Shift+Enter"));
|
|
@@ -500,7 +709,7 @@ function installInterceptors(deps) {
|
|
|
500
709
|
if (replayingSendClick) return;
|
|
501
710
|
const button = sendButtonOf(event.target);
|
|
502
711
|
if (button === null) return;
|
|
503
|
-
if (!applyAlwaysPrompts(deps.
|
|
712
|
+
if (!applyAlwaysPrompts(deps.alwaysPrompts())) return;
|
|
504
713
|
event.preventDefault();
|
|
505
714
|
event.stopPropagation();
|
|
506
715
|
replayingSendClick = true;
|
|
@@ -1136,6 +1345,38 @@ var quickEmpty = {
|
|
|
1136
1345
|
padding: "14px 10px",
|
|
1137
1346
|
textAlign: "center"
|
|
1138
1347
|
};
|
|
1348
|
+
var quickCategoryRow = {
|
|
1349
|
+
display: "flex",
|
|
1350
|
+
alignItems: "center",
|
|
1351
|
+
gap: 4,
|
|
1352
|
+
flexWrap: "wrap"
|
|
1353
|
+
};
|
|
1354
|
+
var quickCategoryTab = {
|
|
1355
|
+
border: "0.5px solid var(--dsw-alias-border-l2)",
|
|
1356
|
+
background: "transparent",
|
|
1357
|
+
color: "var(--dsw-alias-label-tertiary)",
|
|
1358
|
+
fontSize: 11,
|
|
1359
|
+
lineHeight: 1,
|
|
1360
|
+
padding: "4px 8px",
|
|
1361
|
+
borderRadius: 999,
|
|
1362
|
+
cursor: "pointer",
|
|
1363
|
+
whiteSpace: "nowrap",
|
|
1364
|
+
maxWidth: 160,
|
|
1365
|
+
overflow: "hidden",
|
|
1366
|
+
textOverflow: "ellipsis"
|
|
1367
|
+
};
|
|
1368
|
+
var quickCategoryTabActive = {
|
|
1369
|
+
...quickCategoryTab,
|
|
1370
|
+
border: "0.5px solid var(--dsw-alias-brand-primary)",
|
|
1371
|
+
color: "var(--dsw-alias-label-primary)",
|
|
1372
|
+
fontWeight: 600
|
|
1373
|
+
};
|
|
1374
|
+
var quickCategoryAdd = {
|
|
1375
|
+
...quickCategoryTab,
|
|
1376
|
+
color: "var(--dsw-alias-label-tertiary)",
|
|
1377
|
+
padding: "4px 7px",
|
|
1378
|
+
cursor: "pointer"
|
|
1379
|
+
};
|
|
1139
1380
|
|
|
1140
1381
|
// src/client/ContextMenuHost.tsx
|
|
1141
1382
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
@@ -1627,146 +1868,236 @@ function TextFieldRow(props) {
|
|
|
1627
1868
|
] });
|
|
1628
1869
|
}
|
|
1629
1870
|
function QuickPromptsEditor(props) {
|
|
1630
|
-
const [
|
|
1871
|
+
const [draft, setDraft] = (0, import_react3.useState)(() => props.book);
|
|
1872
|
+
const [activeId, setActiveId] = (0, import_react3.useState)(() => props.book.categories[0]?.id ?? "");
|
|
1631
1873
|
const [dirty, setDirty] = (0, import_react3.useState)(false);
|
|
1632
|
-
const
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
setDirty(true);
|
|
1643
|
-
setRows((current) => current.concat([{
|
|
1644
|
-
id: newQuickPromptId(),
|
|
1645
|
-
label: "",
|
|
1646
|
-
prompt: "",
|
|
1647
|
-
always: false
|
|
1648
|
-
}]));
|
|
1649
|
-
};
|
|
1650
|
-
const move = (index, delta) => {
|
|
1651
|
-
const target = index + delta;
|
|
1652
|
-
if (target < 0 || target >= rows.length) return;
|
|
1874
|
+
const [newName, setNewName] = (0, import_react3.useState)("");
|
|
1875
|
+
const [note, setNote] = (0, import_react3.useState)("");
|
|
1876
|
+
(0, import_react3.useEffect)(() => {
|
|
1877
|
+
if (dirty) return;
|
|
1878
|
+
setDraft(props.book);
|
|
1879
|
+
if (!props.book.categories.some((category) => category.id === activeId)) {
|
|
1880
|
+
setActiveId(props.book.categories[0]?.id ?? "");
|
|
1881
|
+
}
|
|
1882
|
+
}, [props.book, dirty, activeId]);
|
|
1883
|
+
const edit = (next) => {
|
|
1653
1884
|
setDirty(true);
|
|
1654
|
-
|
|
1655
|
-
const next = [...current];
|
|
1656
|
-
const [row2] = next.splice(index, 1);
|
|
1657
|
-
next.splice(target, 0, row2);
|
|
1658
|
-
return next;
|
|
1659
|
-
});
|
|
1885
|
+
setDraft(next);
|
|
1660
1886
|
};
|
|
1661
|
-
const
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1887
|
+
const current = draft.categories.find((category) => category.id === activeId) ?? draft.categories[0];
|
|
1888
|
+
const counts = bookCounts(draft);
|
|
1889
|
+
const saving = props.status === "saving";
|
|
1890
|
+
const failed = props.status !== "" && props.status !== "saving";
|
|
1891
|
+
const rowBox = {
|
|
1892
|
+
display: "flex",
|
|
1893
|
+
flexDirection: "column",
|
|
1894
|
+
gap: 6,
|
|
1895
|
+
padding: 8,
|
|
1896
|
+
borderRadius: 8,
|
|
1897
|
+
border: "0.5px solid var(--dsw-alias-border-l2)",
|
|
1898
|
+
background: "var(--dsw-alias-bg-layer-1)"
|
|
1670
1899
|
};
|
|
1671
1900
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: [
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1901
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 4, flexWrap: "wrap" }, children: [
|
|
1902
|
+
draft.categories.map((category) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
1903
|
+
"button",
|
|
1904
|
+
{
|
|
1905
|
+
type: "button",
|
|
1906
|
+
style: category.id === current?.id ? pillActive : pill,
|
|
1907
|
+
onClick: () => {
|
|
1908
|
+
setActiveId(category.id);
|
|
1909
|
+
},
|
|
1910
|
+
children: [
|
|
1911
|
+
category.name,
|
|
1912
|
+
"\uFF08",
|
|
1913
|
+
category.prompts.length,
|
|
1914
|
+
"\uFF09"
|
|
1915
|
+
]
|
|
1683
1916
|
},
|
|
1684
|
-
|
|
1685
|
-
|
|
1917
|
+
category.id
|
|
1918
|
+
)),
|
|
1919
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1920
|
+
"input",
|
|
1921
|
+
{
|
|
1922
|
+
type: "text",
|
|
1923
|
+
value: newName,
|
|
1924
|
+
placeholder: "\u65B0\u5206\u7C7B\u540D",
|
|
1925
|
+
maxLength: QUICK_CATEGORY_NAME_MAX,
|
|
1926
|
+
spellCheck: false,
|
|
1927
|
+
onChange: (event) => {
|
|
1928
|
+
setNewName(event.target.value);
|
|
1929
|
+
},
|
|
1930
|
+
style: { ...textInput, flex: "0 0 110px" }
|
|
1931
|
+
}
|
|
1932
|
+
),
|
|
1933
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1934
|
+
"button",
|
|
1935
|
+
{
|
|
1936
|
+
type: "button",
|
|
1937
|
+
style: pill,
|
|
1938
|
+
disabled: draft.categories.length >= QUICK_CATEGORY_MAX,
|
|
1939
|
+
onClick: () => {
|
|
1940
|
+
edit(withCategoryAdded(draft, newName === "" ? DEFAULT_CATEGORY_NAME : newName));
|
|
1941
|
+
setNewName("");
|
|
1942
|
+
},
|
|
1943
|
+
children: "+ \u52A0\u5206\u7C7B"
|
|
1944
|
+
}
|
|
1945
|
+
)
|
|
1946
|
+
] }),
|
|
1947
|
+
current === void 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { style: rowDesc, children: "\u8FD8\u6CA1\u6709\u5206\u7C7B\u3002\u5148\u52A0\u4E00\u4E2A\u5206\u7C7B\uFF0C\u518D\u5F80\u91CC\u653E\u6761\u76EE\u3002" }),
|
|
1948
|
+
current !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
1949
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 6, flexWrap: "wrap" }, children: [
|
|
1950
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1951
|
+
"input",
|
|
1952
|
+
{
|
|
1953
|
+
type: "text",
|
|
1954
|
+
value: current.name,
|
|
1955
|
+
"aria-label": "\u5206\u7C7B\u540D",
|
|
1956
|
+
maxLength: QUICK_CATEGORY_NAME_MAX,
|
|
1957
|
+
spellCheck: false,
|
|
1958
|
+
onChange: (event) => {
|
|
1959
|
+
edit(withCategoryRenamed(draft, current.id, event.target.value));
|
|
1960
|
+
},
|
|
1961
|
+
style: { ...textInput, flex: "0 0 150px" }
|
|
1962
|
+
}
|
|
1963
|
+
),
|
|
1964
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", style: pill, title: "\u5206\u7C7B\u4E0A\u79FB", onClick: () => {
|
|
1965
|
+
edit(withCategoryMoved(draft, current.id, -1));
|
|
1966
|
+
}, children: "\u2191" }),
|
|
1967
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", style: pill, title: "\u5206\u7C7B\u4E0B\u79FB", onClick: () => {
|
|
1968
|
+
edit(withCategoryMoved(draft, current.id, 1));
|
|
1969
|
+
}, children: "\u2193" }),
|
|
1970
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1971
|
+
"button",
|
|
1972
|
+
{
|
|
1973
|
+
type: "button",
|
|
1974
|
+
style: pill,
|
|
1975
|
+
title: "\u5220\u9664\u8FD9\u4E2A\u5206\u7C7B\uFF08\u8FDE\u540C\u5B83\u91CC\u9762\u7684\u6761\u76EE\uFF09",
|
|
1976
|
+
onClick: () => {
|
|
1977
|
+
edit(withCategoryRemoved(draft, current.id));
|
|
1978
|
+
},
|
|
1979
|
+
children: "\u2715 \u5220\u9664\u5206\u7C7B"
|
|
1980
|
+
}
|
|
1981
|
+
),
|
|
1982
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { style: rowDesc, children: [
|
|
1983
|
+
current.prompts.length,
|
|
1984
|
+
" / ",
|
|
1985
|
+
QUICK_PROMPT_MAX,
|
|
1986
|
+
" \u6761"
|
|
1987
|
+
] })
|
|
1988
|
+
] }),
|
|
1989
|
+
current.prompts.map((prompt) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: rowBox, children: [
|
|
1990
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
|
|
1991
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1992
|
+
"input",
|
|
1993
|
+
{
|
|
1994
|
+
type: "text",
|
|
1995
|
+
value: prompt.label,
|
|
1996
|
+
placeholder: "\u540D\u79F0\uFF0C\u5982\uFF1A\u4EC5\u8BF4\u660E\u539F\u56E0",
|
|
1997
|
+
maxLength: QUICK_LABEL_MAX,
|
|
1998
|
+
spellCheck: false,
|
|
1999
|
+
onChange: (event) => {
|
|
2000
|
+
edit(withPromptPatched(draft, current.id, prompt.id, { label: event.target.value }));
|
|
2001
|
+
},
|
|
2002
|
+
style: { ...textInput, flex: "0 0 150px" }
|
|
2003
|
+
}
|
|
2004
|
+
),
|
|
2005
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { style: { display: "inline-flex", alignItems: "center", gap: 4, ...rowDesc, margin: 0, flex: "0 0 auto" }, children: [
|
|
1686
2006
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1687
2007
|
"input",
|
|
1688
2008
|
{
|
|
1689
|
-
type: "
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
maxLength: QUICK_LABEL_MAX,
|
|
1693
|
-
spellCheck: false,
|
|
2009
|
+
type: "checkbox",
|
|
2010
|
+
checked: prompt.always,
|
|
2011
|
+
style: { margin: 0, cursor: "pointer" },
|
|
1694
2012
|
onChange: (event) => {
|
|
1695
|
-
|
|
1696
|
-
}
|
|
1697
|
-
style: { ...textInput, flex: "0 0 150px" }
|
|
2013
|
+
edit(withPromptPatched(draft, current.id, prompt.id, { always: event.target.checked }));
|
|
2014
|
+
}
|
|
1698
2015
|
}
|
|
1699
2016
|
),
|
|
1700
|
-
|
|
1701
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1702
|
-
"input",
|
|
1703
|
-
{
|
|
1704
|
-
type: "checkbox",
|
|
1705
|
-
checked: row2.always,
|
|
1706
|
-
style: { margin: 0, cursor: "pointer" },
|
|
1707
|
-
onChange: (event) => {
|
|
1708
|
-
update(row2.id, { always: event.target.checked });
|
|
1709
|
-
}
|
|
1710
|
-
}
|
|
1711
|
-
),
|
|
1712
|
-
"\u9ED8\u8BA4\u63D2\u5165"
|
|
1713
|
-
] }),
|
|
1714
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { flex: 1 } }),
|
|
1715
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", style: pill, title: "\u4E0A\u79FB", onClick: () => {
|
|
1716
|
-
move(index, -1);
|
|
1717
|
-
}, children: "\u2191" }),
|
|
1718
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", style: pill, title: "\u4E0B\u79FB", onClick: () => {
|
|
1719
|
-
move(index, 1);
|
|
1720
|
-
}, children: "\u2193" }),
|
|
1721
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", style: pill, title: "\u5220\u9664\u8FD9\u6761", onClick: () => {
|
|
1722
|
-
remove(row2.id);
|
|
1723
|
-
}, children: "\u2715" })
|
|
2017
|
+
"\u9ED8\u8BA4\u63D2\u5165"
|
|
1724
2018
|
] }),
|
|
1725
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
2019
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { flex: 1 } }),
|
|
2020
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", style: pill, title: "\u4E0A\u79FB", onClick: () => {
|
|
2021
|
+
edit(withPromptMoved(draft, current.id, prompt.id, -1));
|
|
2022
|
+
}, children: "\u2191" }),
|
|
2023
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", style: pill, title: "\u4E0B\u79FB", onClick: () => {
|
|
2024
|
+
edit(withPromptMoved(draft, current.id, prompt.id, 1));
|
|
2025
|
+
}, children: "\u2193" }),
|
|
2026
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", style: pill, title: "\u5220\u9664\u8FD9\u6761", onClick: () => {
|
|
2027
|
+
edit(withPromptRemoved(draft, current.id, prompt.id));
|
|
2028
|
+
}, children: "\u2715" })
|
|
2029
|
+
] }),
|
|
2030
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2031
|
+
"textarea",
|
|
2032
|
+
{
|
|
2033
|
+
value: prompt.prompt,
|
|
2034
|
+
placeholder: "\u63D0\u793A\u8BCD\u6B63\u6587\uFF1A\u70B9\u51FB\u8BE5\u6761\u76EE\u65F6\u63D2\u5165\u8F93\u5165\u6846\uFF1B\u52FE\u4E86\u300C\u9ED8\u8BA4\u63D2\u5165\u300D\u5219\u5728\u53D1\u9001\u65F6\u81EA\u52A8\u9644\u52A0\u5230\u6D88\u606F\u672B\u5C3E",
|
|
2035
|
+
maxLength: QUICK_TEXT_MAX,
|
|
2036
|
+
spellCheck: false,
|
|
2037
|
+
rows: Math.min(4, Math.max(2, Math.ceil(prompt.prompt.length / 46))),
|
|
2038
|
+
onChange: (event) => {
|
|
2039
|
+
edit(withPromptPatched(draft, current.id, prompt.id, { prompt: event.target.value }));
|
|
2040
|
+
},
|
|
2041
|
+
style: { ...textInput, resize: "vertical", fontFamily: "inherit", lineHeight: 1.5 }
|
|
2042
|
+
}
|
|
2043
|
+
)
|
|
2044
|
+
] }, prompt.id)),
|
|
2045
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", style: pill, onClick: () => {
|
|
2046
|
+
edit(withPromptAdded(draft, current.id));
|
|
2047
|
+
}, children: "+ \u6DFB\u52A0\u4E00\u6761" }) })
|
|
2048
|
+
] }),
|
|
1744
2049
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap" }, children: [
|
|
1745
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", style: pill, onClick: add, children: "+ \u6DFB\u52A0\u4E00\u6761" }),
|
|
1746
2050
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1747
2051
|
"button",
|
|
1748
2052
|
{
|
|
1749
2053
|
type: "button",
|
|
1750
2054
|
style: dirty ? pillActive : pill,
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
2055
|
+
disabled: !dirty || saving,
|
|
2056
|
+
onClick: () => {
|
|
2057
|
+
const next = {
|
|
2058
|
+
version: draft.version,
|
|
2059
|
+
categories: draft.categories.map((category) => ({
|
|
2060
|
+
...category,
|
|
2061
|
+
prompts: category.prompts.filter((prompt) => prompt.prompt.trim() !== "")
|
|
2062
|
+
}))
|
|
2063
|
+
};
|
|
2064
|
+
const skipped = counts.prompts - bookCounts(next).prompts;
|
|
2065
|
+
setNote(skipped > 0 ? `\u5DF2\u8DF3\u8FC7 ${String(skipped)} \u6761\u6B63\u6587\u4E3A\u7A7A\u7684\u6761\u76EE` : "");
|
|
2066
|
+
props.onSave(next);
|
|
2067
|
+
setDirty(false);
|
|
2068
|
+
},
|
|
2069
|
+
children: saving ? "\u4FDD\u5B58\u4E2D\u2026" : dirty ? "\u4FDD\u5B58\u4FEE\u6539" : "\u5DF2\u4FDD\u5B58"
|
|
1754
2070
|
}
|
|
1755
2071
|
),
|
|
2072
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", style: pill, onClick: () => {
|
|
2073
|
+
props.onReload();
|
|
2074
|
+
}, children: "\u91CD\u65B0\u8BFB\u53D6" }),
|
|
2075
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", style: pill, onClick: () => {
|
|
2076
|
+
props.onReset();
|
|
2077
|
+
}, children: "\u6062\u590D\u5185\u7F6E 9 \u6761" }),
|
|
1756
2078
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { style: rowDesc, children: [
|
|
1757
2079
|
"\u5171 ",
|
|
1758
|
-
|
|
1759
|
-
"
|
|
1760
|
-
|
|
1761
|
-
" \u6761 \xB7 \
|
|
1762
|
-
|
|
1763
|
-
" \u6761"
|
|
2080
|
+
counts.categories,
|
|
2081
|
+
" \u4E2A\u5206\u7C7B \xB7 ",
|
|
2082
|
+
counts.prompts,
|
|
2083
|
+
" \u6761 \xB7 \u9ED8\u8BA4\u63D2\u5165 ",
|
|
2084
|
+
counts.always,
|
|
2085
|
+
" \u6761",
|
|
2086
|
+
note === "" ? "" : ` \xB7 ${note}`,
|
|
2087
|
+
failed ? ` \xB7 ${props.status}` : ""
|
|
1764
2088
|
] })
|
|
2089
|
+
] }),
|
|
2090
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("p", { style: rowDesc, children: [
|
|
2091
|
+
"\u6570\u636E\u5B58\u5728 ",
|
|
2092
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("code", { children: "~/.dsh/quick-prompts.json" }),
|
|
2093
|
+
"\uFF08\u4E0E\u4F1A\u8BDD\u3001\u9879\u76EE\u65E0\u5173\uFF0C\u53EF\u5355\u72EC\u5907\u4EFD\u6216\u624B\u5DE5\u7F16\u8F91\uFF0C \u6539\u5B8C\u70B9\u300C\u91CD\u65B0\u8BFB\u53D6\u300D\u5373\u53EF\u52A0\u8F7D\uFF09\u3002"
|
|
1765
2094
|
] })
|
|
1766
2095
|
] });
|
|
1767
2096
|
}
|
|
1768
|
-
function SettingsSection({ useLive, actions }) {
|
|
2097
|
+
function SettingsSection({ useLive, useBook, useBookStatus, actions }) {
|
|
1769
2098
|
const settings = useLive((item) => item);
|
|
2099
|
+
const book = useBook((item) => item);
|
|
2100
|
+
const bookStatus = useBookStatus((item) => item);
|
|
1770
2101
|
const [conflict, setConflict] = (0, import_react3.useState)(null);
|
|
1771
2102
|
const setKey = (side, chord) => {
|
|
1772
2103
|
const other = side === "send" ? settings.newlineKey : settings.sendKey;
|
|
@@ -1783,8 +2114,8 @@ function SettingsSection({ useLive, actions }) {
|
|
|
1783
2114
|
const menuSummary = settings.menuNative ? "\u5F53\u524D\uFF1A\u7CFB\u7EDF\u539F\u751F\u83DC\u5355\uFF08\u7C98\u8D34\u514D\u6388\u6743\uFF09" : `\u5F53\u524D\uFF1A\u81EA\u5B9A\u4E49\u83DC\u5355 \xB7 ${menuEnabled} / ${MENU_ITEMS.length} \u9879\u5F00\u542F`;
|
|
1784
2115
|
const panelSummary = `\u5BFC\u822A\u6EDA\u52A8 ${settings.panelScroll ? "\u5F00" : "\u5173"} \xB7 \u8FB9\u7F18\u7F29\u653E ${settings.panelResize ? "\u5F00" : "\u5173"} \xB7 ${settings.panelWidth}\xD7${settings.panelHeight}`;
|
|
1785
2116
|
const headerSummary = settings.headerEnabled ? settings.headerStatus === "" ? "\u5DF2\u542F\u7528" : settings.headerStatus : "\u672A\u542F\u7528";
|
|
1786
|
-
const
|
|
1787
|
-
const quickSummary = `${
|
|
2117
|
+
const quickCounts = bookCounts(book);
|
|
2118
|
+
const quickSummary = `${quickCounts.categories} \u4E2A\u5206\u7C7B \xB7 ${quickCounts.prompts} \u6761 \xB7 \u9ED8\u8BA4\u63D2\u5165 ${quickCounts.always} \u6761 \xB7 \u4F18\u5316\u6863\u4F4D ${OPTIMIZER_TIERS.find((item) => item.id === settings.optimizerTier)?.label ?? "\u9AD8\u7EA7"}`;
|
|
1788
2119
|
const headerStatusText = settings.headerEnabled ? settings.headerStatus === "" ? "\u7B49\u5F85\u9996\u6B21\u5199\u5165\u2026" : settings.headerStatus : "\u672A\u542F\u7528\uFF08\u6253\u5F00\u4E0A\u65B9\u5F00\u5173\u5373\u5199\u5165\uFF09";
|
|
1789
2120
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { padding: "4px 2px" }, children: [
|
|
1790
2121
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { className: "dsh-ux-card", children: [
|
|
@@ -1916,28 +2247,24 @@ function SettingsSection({ useLive, actions }) {
|
|
|
1916
2247
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { ...row, borderTop: "none", flexDirection: "column", alignItems: "stretch", gap: 8 }, children: [
|
|
1917
2248
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: rowText, children: [
|
|
1918
2249
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: rowTitle, children: "\u5FEB\u6377\u6307\u4EE4\u6E05\u5355" }),
|
|
1919
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: rowDesc, children: "\u5185\u7F6E 9 \u6761\u53EF\u4EE5\u76F4\u63A5\u7528\
|
|
2250
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: rowDesc, children: "\u5206\u7C7B\u5728\u8FD9\u91CC\u7BA1\u7406\uFF08\u9762\u677F\u91CC\u53EA\u505A\u5207\u6362\uFF09\uFF1B\u5185\u7F6E 9 \u6761\u53EF\u4EE5\u76F4\u63A5\u7528\uFF0C\u6539\u5B8C\u8BB0\u5F97\u70B9\u300C\u4FDD\u5B58\u4FEE\u6539\u300D\u3002" })
|
|
1920
2251
|
] }),
|
|
1921
2252
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1922
2253
|
QuickPromptsEditor,
|
|
1923
2254
|
{
|
|
1924
|
-
|
|
2255
|
+
book,
|
|
2256
|
+
status: bookStatus,
|
|
1925
2257
|
onSave: (next) => {
|
|
1926
|
-
actions.
|
|
1927
|
-
}
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { display: "flex", gap: 8 }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1931
|
-
"button",
|
|
1932
|
-
{
|
|
1933
|
-
type: "button",
|
|
1934
|
-
style: pill,
|
|
1935
|
-
onClick: () => {
|
|
1936
|
-
actions.clearField(QUICK_PROMPTS_FIELD);
|
|
2258
|
+
actions.saveBook(next);
|
|
2259
|
+
},
|
|
2260
|
+
onReload: () => {
|
|
2261
|
+
actions.reloadBook();
|
|
1937
2262
|
},
|
|
1938
|
-
|
|
2263
|
+
onReset: () => {
|
|
2264
|
+
actions.resetBook();
|
|
2265
|
+
}
|
|
1939
2266
|
}
|
|
1940
|
-
)
|
|
2267
|
+
)
|
|
1941
2268
|
] })
|
|
1942
2269
|
] }),
|
|
1943
2270
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(FoldCard, { name: "\u8BBE\u7F6E\u9762\u677F", summary: panelSummary, children: [
|
|
@@ -2154,14 +2481,22 @@ function QuickCommandsPanel({
|
|
|
2154
2481
|
usePanel,
|
|
2155
2482
|
useBusy,
|
|
2156
2483
|
useNotice,
|
|
2484
|
+
useBook,
|
|
2485
|
+
useBookStatus,
|
|
2157
2486
|
actions
|
|
2158
2487
|
}) {
|
|
2159
2488
|
const settings = useLive((item) => item);
|
|
2160
2489
|
const anchor = usePanel((item) => item);
|
|
2161
2490
|
const busy = useBusy((item) => item);
|
|
2162
2491
|
const notice = useNotice((item) => item);
|
|
2492
|
+
const book = useBook((item) => item);
|
|
2493
|
+
const status = useBookStatus((item) => item);
|
|
2163
2494
|
const ref = (0, import_react5.useRef)(null);
|
|
2164
2495
|
const [position, setPosition] = (0, import_react5.useState)(null);
|
|
2496
|
+
const [activeId, setActiveId] = (0, import_react5.useState)("");
|
|
2497
|
+
const counts = bookCounts(book);
|
|
2498
|
+
const categories = book.categories;
|
|
2499
|
+
const active = categories.find((category) => category.id === activeId) ?? categories[0];
|
|
2165
2500
|
(0, import_react5.useLayoutEffect)(() => {
|
|
2166
2501
|
if (anchor === null) {
|
|
2167
2502
|
setPosition(null);
|
|
@@ -2174,7 +2509,7 @@ function QuickCommandsPanel({
|
|
|
2174
2509
|
const above = anchor.bottom - height - GAP;
|
|
2175
2510
|
const top = above >= MARGIN ? above : Math.min(anchor.bottom + GAP, window.innerHeight - height - MARGIN);
|
|
2176
2511
|
setPosition({ left, top: Math.max(MARGIN, top) });
|
|
2177
|
-
}, [anchor?.left, anchor?.bottom,
|
|
2512
|
+
}, [anchor?.left, anchor?.bottom, counts.prompts, categories.length, busy]);
|
|
2178
2513
|
(0, import_react5.useEffect)(() => {
|
|
2179
2514
|
if (anchor === null) return;
|
|
2180
2515
|
const onPointerDown = (event) => {
|
|
@@ -2198,8 +2533,9 @@ function QuickCommandsPanel({
|
|
|
2198
2533
|
};
|
|
2199
2534
|
}, [anchor === null, actions]);
|
|
2200
2535
|
if (anchor === null) return null;
|
|
2201
|
-
const items = settings.quickPrompts;
|
|
2202
2536
|
const tier = settings.optimizerTier;
|
|
2537
|
+
const items = active?.prompts ?? [];
|
|
2538
|
+
const failure = status !== "" && status !== "saving" ? status : "";
|
|
2203
2539
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
2204
2540
|
"div",
|
|
2205
2541
|
{
|
|
@@ -2247,13 +2583,48 @@ function QuickCommandsPanel({
|
|
|
2247
2583
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: busy ? "\u4F18\u5316\u4E2D\u2026" : "\u4F18\u5316\u63D0\u793A\u8BCD" })
|
|
2248
2584
|
]
|
|
2249
2585
|
}
|
|
2250
|
-
)
|
|
2586
|
+
),
|
|
2587
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: quickCategoryRow, children: [
|
|
2588
|
+
categories.map((category) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2589
|
+
"button",
|
|
2590
|
+
{
|
|
2591
|
+
type: "button",
|
|
2592
|
+
title: `${category.name}\uFF08${String(category.prompts.length)} \u6761\uFF09`,
|
|
2593
|
+
"aria-pressed": category.id === active?.id,
|
|
2594
|
+
style: category.id === active?.id ? quickCategoryTabActive : quickCategoryTab,
|
|
2595
|
+
onMouseDown: (event) => {
|
|
2596
|
+
event.preventDefault();
|
|
2597
|
+
},
|
|
2598
|
+
onClick: () => {
|
|
2599
|
+
setActiveId(category.id);
|
|
2600
|
+
},
|
|
2601
|
+
children: category.name
|
|
2602
|
+
},
|
|
2603
|
+
category.id
|
|
2604
|
+
)),
|
|
2605
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2606
|
+
"button",
|
|
2607
|
+
{
|
|
2608
|
+
type: "button",
|
|
2609
|
+
style: quickCategoryAdd,
|
|
2610
|
+
disabled: categories.length >= QUICK_CATEGORY_MAX,
|
|
2611
|
+
title: "\u65B0\u589E\u4E00\u4E2A\u5206\u7C7B\uFF08\u540D\u5B57\u5230\u300C\u8BBE\u7F6E \u2192 \u8F93\u5165\u4F53\u9A8C\u300D\u91CC\u6539\uFF09",
|
|
2612
|
+
onMouseDown: (event) => {
|
|
2613
|
+
event.preventDefault();
|
|
2614
|
+
},
|
|
2615
|
+
onClick: () => {
|
|
2616
|
+
actions.addCategory(DEFAULT_CATEGORY_NAME);
|
|
2617
|
+
},
|
|
2618
|
+
children: "\uFF0B"
|
|
2619
|
+
}
|
|
2620
|
+
)
|
|
2621
|
+
] })
|
|
2251
2622
|
] }),
|
|
2252
2623
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: quickList, children: [
|
|
2253
2624
|
items.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: quickEmpty, children: [
|
|
2254
|
-
"\u8FD8\u6CA1\u6709\
|
|
2625
|
+
"\u8FD9\u4E2A\u5206\u7C7B\u91CC\u8FD8\u6CA1\u6709\u6761\u76EE\u3002",
|
|
2255
2626
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("br", {}),
|
|
2256
|
-
"\u5728\u300C\u8BBE\u7F6E \u2192 \u8F93\u5165\u4F53\u9A8C \u2192 \u5FEB\u6377\u6307\u4EE4\u300D\u91CC\u6DFB\u52A0\u3002"
|
|
2627
|
+
"\u5728\u300C\u8BBE\u7F6E \u2192 \u8F93\u5165\u4F53\u9A8C \u2192 \u5FEB\u6377\u6307\u4EE4\u6E05\u5355\u300D\u91CC\u6DFB\u52A0\u3002"
|
|
2257
2628
|
] }),
|
|
2258
2629
|
items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 4 }, children: [
|
|
2259
2630
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
@@ -2274,7 +2645,7 @@ function QuickCommandsPanel({
|
|
|
2274
2645
|
]
|
|
2275
2646
|
}
|
|
2276
2647
|
),
|
|
2277
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { style: quickAlwaysLabel, title: "\u52FE\u4E0A\u540E\uFF0C\u70B9\u53D1\u9001\u65F6\u8FD9\u6761\u63D0\u793A\u8BCD\u4F1A\u81EA\u52A8\u9644\u52A0\u5230\u4F60\u7684\u6D88\u606F\u672B\u5C3E", children: [
|
|
2648
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { style: quickAlwaysLabel, title: "\u52FE\u4E0A\u540E\uFF0C\u70B9\u53D1\u9001\u65F6\u8FD9\u6761\u63D0\u793A\u8BCD\u4F1A\u81EA\u52A8\u9644\u52A0\u5230\u4F60\u7684\u6D88\u606F\u672B\u5C3E\uFF08\u5BF9\u6240\u6709\u5206\u7C7B\u751F\u6548\uFF09", children: [
|
|
2278
2649
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2279
2650
|
"input",
|
|
2280
2651
|
{
|
|
@@ -2291,8 +2662,20 @@ function QuickCommandsPanel({
|
|
|
2291
2662
|
] }, item.id))
|
|
2292
2663
|
] }),
|
|
2293
2664
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: quickPanelFoot, children: [
|
|
2294
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: quickNotice, role: "status", children: notice }),
|
|
2295
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.
|
|
2665
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: quickNotice, role: "status", children: notice !== "" ? notice : failure }),
|
|
2666
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
2667
|
+
"span",
|
|
2668
|
+
{
|
|
2669
|
+
style: quickFootHint,
|
|
2670
|
+
title: "\u6570\u636E\u5728 ~/.dsh/quick-prompts.json",
|
|
2671
|
+
children: [
|
|
2672
|
+
counts.categories,
|
|
2673
|
+
" \u5206\u7C7B \xB7 ",
|
|
2674
|
+
counts.prompts,
|
|
2675
|
+
" \u6761"
|
|
2676
|
+
]
|
|
2677
|
+
}
|
|
2678
|
+
)
|
|
2296
2679
|
] })
|
|
2297
2680
|
]
|
|
2298
2681
|
}
|
|
@@ -2326,6 +2709,73 @@ function apply(ctx) {
|
|
|
2326
2709
|
console.error("[composer-ux] settings clear failed", error);
|
|
2327
2710
|
});
|
|
2328
2711
|
};
|
|
2712
|
+
const book = (0, import_dsh_client_store.createSnapshotStore)(defaultQuickBook());
|
|
2713
|
+
const bookStatus = (0, import_dsh_client_store.createSnapshotStore)("");
|
|
2714
|
+
const reloadBook = async () => {
|
|
2715
|
+
const reply = await loadPromptBook();
|
|
2716
|
+
if (reply.ok && reply.book !== void 0) {
|
|
2717
|
+
book.set(reply.book);
|
|
2718
|
+
bookStatus.set("");
|
|
2719
|
+
return;
|
|
2720
|
+
}
|
|
2721
|
+
bookStatus.set(reply.error ?? "\u8BFB\u53D6\u5FEB\u6377\u6307\u4EE4\u5931\u8D25");
|
|
2722
|
+
};
|
|
2723
|
+
const commitBook = (next) => {
|
|
2724
|
+
book.set(next);
|
|
2725
|
+
bookStatus.set("saving");
|
|
2726
|
+
void savePromptBook(next).then(
|
|
2727
|
+
(reply) => {
|
|
2728
|
+
if (reply.ok && reply.book !== void 0) {
|
|
2729
|
+
book.set(reply.book);
|
|
2730
|
+
bookStatus.set("");
|
|
2731
|
+
return;
|
|
2732
|
+
}
|
|
2733
|
+
bookStatus.set(reply.error ?? "\u4FDD\u5B58\u5931\u8D25");
|
|
2734
|
+
void reloadBook();
|
|
2735
|
+
},
|
|
2736
|
+
(error) => {
|
|
2737
|
+
bookStatus.set(error instanceof Error ? error.message : String(error));
|
|
2738
|
+
void reloadBook();
|
|
2739
|
+
}
|
|
2740
|
+
);
|
|
2741
|
+
};
|
|
2742
|
+
void reloadBook();
|
|
2743
|
+
const bookActions = {
|
|
2744
|
+
reload: () => {
|
|
2745
|
+
void reloadBook();
|
|
2746
|
+
},
|
|
2747
|
+
addCategory: (name2) => {
|
|
2748
|
+
commitBook(withCategoryAdded(book.getSnapshot(), name2));
|
|
2749
|
+
},
|
|
2750
|
+
renameCategory: (id, name2) => {
|
|
2751
|
+
commitBook(withCategoryRenamed(book.getSnapshot(), id, name2));
|
|
2752
|
+
},
|
|
2753
|
+
removeCategory: (id) => {
|
|
2754
|
+
commitBook(withCategoryRemoved(book.getSnapshot(), id));
|
|
2755
|
+
},
|
|
2756
|
+
moveCategory: (id, delta) => {
|
|
2757
|
+
commitBook(withCategoryMoved(book.getSnapshot(), id, delta));
|
|
2758
|
+
},
|
|
2759
|
+
addPrompt: (categoryId) => {
|
|
2760
|
+
commitBook(withPromptAdded(book.getSnapshot(), categoryId));
|
|
2761
|
+
},
|
|
2762
|
+
patchPrompt: (categoryId, id, patch) => {
|
|
2763
|
+
commitBook(withPromptPatched(book.getSnapshot(), categoryId, id, patch));
|
|
2764
|
+
},
|
|
2765
|
+
removePrompt: (categoryId, id) => {
|
|
2766
|
+
commitBook(withPromptRemoved(book.getSnapshot(), categoryId, id));
|
|
2767
|
+
},
|
|
2768
|
+
movePrompt: (categoryId, id, delta) => {
|
|
2769
|
+
commitBook(withPromptMoved(book.getSnapshot(), categoryId, id, delta));
|
|
2770
|
+
},
|
|
2771
|
+
resetBook: () => {
|
|
2772
|
+
commitBook(defaultQuickBook());
|
|
2773
|
+
},
|
|
2774
|
+
/** 设置页「保存」:把编辑器里的整本一次写回(而不是每敲一个字就写盘)。 */
|
|
2775
|
+
saveBook: (next) => {
|
|
2776
|
+
commitBook(next);
|
|
2777
|
+
}
|
|
2778
|
+
};
|
|
2329
2779
|
const resetAll = () => {
|
|
2330
2780
|
void scope.mutate(
|
|
2331
2781
|
[
|
|
@@ -2342,12 +2792,12 @@ function apply(ctx) {
|
|
|
2342
2792
|
HEADER_NAME_FIELD,
|
|
2343
2793
|
HEADER_VALUE_FIELD,
|
|
2344
2794
|
HEADER_ROUTES_FIELD,
|
|
2345
|
-
QUICK_PROMPTS_FIELD,
|
|
2346
2795
|
OPTIMIZER_TIER_FIELD
|
|
2347
2796
|
].map((field) => ({ op: "unset", path: [field] }))
|
|
2348
2797
|
).catch((error) => {
|
|
2349
2798
|
console.error("[composer-ux] settings reset failed", error);
|
|
2350
2799
|
});
|
|
2800
|
+
bookActions.resetBook();
|
|
2351
2801
|
};
|
|
2352
2802
|
let noticeTimer;
|
|
2353
2803
|
const note = (message, ms = 4500) => {
|
|
@@ -2361,9 +2811,6 @@ function apply(ctx) {
|
|
|
2361
2811
|
ctx.effect(() => () => {
|
|
2362
2812
|
if (noticeTimer !== void 0) clearTimeout(noticeTimer);
|
|
2363
2813
|
}, "composer-ux: quick notice timer");
|
|
2364
|
-
const writeQuickPrompts = (next) => {
|
|
2365
|
-
setField(QUICK_PROMPTS_FIELD, next);
|
|
2366
|
-
};
|
|
2367
2814
|
const quickActions = {
|
|
2368
2815
|
toggle: (anchor) => {
|
|
2369
2816
|
if (panel.getSnapshot() !== null) {
|
|
@@ -2410,10 +2857,12 @@ function apply(ctx) {
|
|
|
2410
2857
|
setTier: (tier) => {
|
|
2411
2858
|
setField(OPTIMIZER_TIER_FIELD, tier);
|
|
2412
2859
|
},
|
|
2860
|
+
/**
|
|
2861
|
+
* 「默认插入」勾选:按 id 跨分类找那一条,直接写盘。
|
|
2862
|
+
* 这个标记就是「点发送时自动附加到消息末尾」的依据(见 interceptors.ts)。
|
|
2863
|
+
*/
|
|
2413
2864
|
setAlways: (id, value) => {
|
|
2414
|
-
|
|
2415
|
-
(item) => item.id === id ? { ...item, always: value } : item
|
|
2416
|
-
));
|
|
2865
|
+
commitBook(withAlwaysToggled(book.getSnapshot(), id, value));
|
|
2417
2866
|
}
|
|
2418
2867
|
};
|
|
2419
2868
|
slots.inject("settings.section", () => slots.register({
|
|
@@ -2422,8 +2871,15 @@ function apply(ctx) {
|
|
|
2422
2871
|
order: 40,
|
|
2423
2872
|
label: "\u8F93\u5165\u4F53\u9A8C",
|
|
2424
2873
|
inject: () => ({
|
|
2425
|
-
hooks: { live },
|
|
2426
|
-
actions: {
|
|
2874
|
+
hooks: { live, book, bookStatus },
|
|
2875
|
+
actions: {
|
|
2876
|
+
setField,
|
|
2877
|
+
clearField,
|
|
2878
|
+
resetAll,
|
|
2879
|
+
saveBook: bookActions.saveBook,
|
|
2880
|
+
reloadBook: bookActions.reload,
|
|
2881
|
+
resetBook: bookActions.resetBook
|
|
2882
|
+
}
|
|
2427
2883
|
})
|
|
2428
2884
|
}, SettingsSection));
|
|
2429
2885
|
slots.inject("shell.overlay", () => slots.register({
|
|
@@ -2463,8 +2919,21 @@ function apply(ctx) {
|
|
|
2463
2919
|
name: "shell.overlay",
|
|
2464
2920
|
id: "composer-ux-quick-panel",
|
|
2465
2921
|
inject: () => ({
|
|
2466
|
-
hooks: { live, panel, busy: optimizing, notice: panelNotice },
|
|
2467
|
-
actions:
|
|
2922
|
+
hooks: { live, panel, busy: optimizing, notice: panelNotice, book, bookStatus },
|
|
2923
|
+
actions: {
|
|
2924
|
+
toggle: quickActions.toggle,
|
|
2925
|
+
close: quickActions.close,
|
|
2926
|
+
insert: quickActions.insert,
|
|
2927
|
+
optimize: quickActions.optimize,
|
|
2928
|
+
setTier: quickActions.setTier,
|
|
2929
|
+
setAlways: quickActions.setAlways,
|
|
2930
|
+
toggleAlways: quickActions.setAlways,
|
|
2931
|
+
addCategory: bookActions.addCategory,
|
|
2932
|
+
renameCategory: bookActions.renameCategory,
|
|
2933
|
+
removeCategory: bookActions.removeCategory,
|
|
2934
|
+
moveCategory: bookActions.moveCategory,
|
|
2935
|
+
reloadBook: bookActions.reload
|
|
2936
|
+
}
|
|
2468
2937
|
})
|
|
2469
2938
|
}, QuickCommandsPanel));
|
|
2470
2939
|
ctx.effect(() => installSettingsCardStyle(), "composer-ux: settings card style");
|
|
@@ -2486,6 +2955,7 @@ function apply(ctx) {
|
|
|
2486
2955
|
if (enabled && dispose === null) {
|
|
2487
2956
|
dispose = installInterceptors({
|
|
2488
2957
|
settings: () => live.getSnapshot(),
|
|
2958
|
+
alwaysPrompts: () => alwaysQuickPrompts(book.getSnapshot()),
|
|
2489
2959
|
setMenu: (state2) => {
|
|
2490
2960
|
menu2.set(state2);
|
|
2491
2961
|
},
|