dsh-composer-ux 0.1.5 → 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 +165 -71
- package/README.md +41 -6
- package/lib/client.js +1502 -145
- package/lib/client.js.map +4 -4
- package/lib/index.js +558 -4
- package/lib/index.js.map +4 -4
- package/package.json +55 -54
package/lib/client.js
CHANGED
|
@@ -57,6 +57,117 @@ var MENU_FIELDS = [
|
|
|
57
57
|
"menuSelectAll"
|
|
58
58
|
];
|
|
59
59
|
var MENU_NATIVE_FIELD = "menuNative";
|
|
60
|
+
var QUICK_PROMPTS_FIELD = "quickPrompts";
|
|
61
|
+
var OPTIMIZER_TIER_FIELD = "optimizerTier";
|
|
62
|
+
var QUICK_PROMPT_MAX = 60;
|
|
63
|
+
var QUICK_CATEGORY_MAX = 20;
|
|
64
|
+
var QUICK_CATEGORY_NAME_MAX = 40;
|
|
65
|
+
var QUICK_LABEL_MAX = 40;
|
|
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";
|
|
70
|
+
var OPTIMIZER_API_PATH = "/composer-ux/optimize";
|
|
71
|
+
var OPTIMIZER_TIERS = [
|
|
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" },
|
|
73
|
+
{ id: "advanced", label: "\u9AD8\u7EA7", hint: "\u5728\u4E0D\u52A8\u76EE\u6807\u7684\u524D\u63D0\u4E0B\uFF0C\u628A\u300C\u4F60\u663E\u7136\u60F3\u8981\u3001\u4F46\u6CA1\u8BF4\u51FA\u53E3\u300D\u7684\u5FC5\u8981\u8981\u6C42\u8865\u6210\u5BF9 AI \u7684\u8981\u6C42\uFF0C\u8BA9\u5B83\u4E00\u6B21\u505A\u5BF9\u3002" },
|
|
74
|
+
{ id: "extreme", label: "\u6781\u7AEF", hint: "\u6309\u590D\u6742\u4EFB\u52A1\u5904\u7406\uFF1A\u56FA\u5316\u547D\u4EE4\u7ED3\u6784 + \u5206\u9636\u6BB5\u6267\u884C\u8BA1\u5212 + 2~4 \u79CD\u60C5\u51B5\u7684\u9884\u6848\u3002" }
|
|
75
|
+
];
|
|
76
|
+
var DEFAULT_OPTIMIZER_TIER = "advanced";
|
|
77
|
+
var DEFAULT_QUICK_PROMPTS = [
|
|
78
|
+
{ id: "builtin-1", label: "\u4E00\u95EE\u4E00\u7B54", prompt: "\u4F60\u4E0D\u61C2\u7684\u5C31\u95EE\u6211\uFF0C\u4E00\u95EE\u4E00\u7B54\uFF1B\u540C\u65F6\u8BF4\u6E05\u695A\u4F60\u4E3A\u4EC0\u4E48\u8981\u95EE\u8BE5\u95EE\u9898\uFF1B\u76F4\u5230\u4F60\u5BF9\u6211\u7684\u76EE\u6807\u6709\u660E\u786E\u8BA4\u77E5\u540E\u518D\u5F00\u59CB\u5E72\u6D3B\u3002", always: false },
|
|
79
|
+
{ id: "builtin-2", label: "\u4EA4\u63A5\u6587\u6863", prompt: "\u628A\u8FD9\u6B21\u4EFB\u52A1\u3001\u5DF2\u5B8C\u6210\u5185\u5BB9\u3001\u5F53\u524D\u5361\u70B9\u3001\u4E0B\u4E00\u6B65\u8BA1\u5212\u3001\u8E29\u8FC7\u7684\u5751\uFF0C\u6574\u7406\u6210\u4E00\u4EFD\u4EA4\u63A5\u6587\u6863\uFF0C\u5199\u7ED9\u65B0\u4F1A\u8BDD\u770B\u3002", always: false },
|
|
80
|
+
{ id: "builtin-3", label: "\u4EC5\u8BF4\u660E\u539F\u56E0", prompt: "\u4EC5\u8BF4\u660E\u539F\u56E0\uFF0C\u4E0D\u8981\u505A\u5176\u4ED6\u52A8\u4F5C\u3002", always: false },
|
|
81
|
+
{ id: "builtin-4", label: "\u5206\u6790\u540E\u76F4\u63A5\u5E72", prompt: "\u5206\u6790\u539F\u56E0\uFF0C\u7136\u540E\u76F4\u63A5\u5F00\u59CB\u5E72\u6D3B\uFF0C\u4E0D\u9700\u8981\u8FC7\u95EE\u6211\u3002", always: false },
|
|
82
|
+
{ id: "builtin-5", label: "\u63D0\u4EA4\u4EE3\u7801", prompt: "\u8BF7\u5E2E\u6211\u63D0\u4EA4\u4EE3\u7801\uFF1A\u68C0\u67E5\u5F53\u524D git \u53D8\u66F4\uFF0C\u751F\u6210\u89C4\u8303\u7684 commit message \u5E76\u6267\u884C\u63D0\u4EA4\u3002", always: false },
|
|
83
|
+
{ id: "builtin-6", label: "\u7ED9\u65B9\u6848", prompt: "\u8BF7\u9488\u5BF9\u4E0A\u9762\u7684\u95EE\u9898\u7ED9\u51FA\u4E00\u4E2A\u5B8C\u6574\u65B9\u6848\uFF0C\u5305\u62EC\u601D\u8DEF\u3001\u6B65\u9AA4\u3001\u6CE8\u610F\u4E8B\u9879\u548C\u98CE\u9669\u3002", always: false },
|
|
84
|
+
{ id: "builtin-7", label: "\u89E3\u91CA\u4EE3\u7801", prompt: "\u8BF7\u89E3\u91CA\u8FD9\u6BB5\u4EE3\u7801\u7684\u4F5C\u7528\u548C\u5B9E\u73B0\u601D\u8DEF\u3002", always: false },
|
|
85
|
+
{ id: "builtin-8", label: "\u5199\u6D4B\u8BD5", prompt: "\u8BF7\u4E3A\u4E0B\u9762\u7684\u4EE3\u7801\u7F16\u5199\u5355\u5143\u6D4B\u8BD5\u3002", always: false },
|
|
86
|
+
{ id: "builtin-9", label: "\u4EE3\u7801\u5BA1\u67E5", prompt: "\u8BF7\u5BF9\u4E0B\u9762\u7684\u4EE3\u7801\u8FDB\u884C\u4EE3\u7801\u5BA1\u67E5\uFF0C\u6307\u51FA\u95EE\u9898\u5E76\u7ED9\u51FA\u6539\u8FDB\u5EFA\u8BAE\u3002", always: false }
|
|
87
|
+
];
|
|
88
|
+
function newQuickPromptId() {
|
|
89
|
+
return `qp-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
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
|
+
}
|
|
60
171
|
var HEADER_ENABLED_FIELD = "headerEnabled";
|
|
61
172
|
var HEADER_NAME_FIELD = "headerName";
|
|
62
173
|
var HEADER_VALUE_FIELD = "headerValue";
|
|
@@ -87,7 +198,9 @@ var DEFAULT_SETTINGS = {
|
|
|
87
198
|
headerRoutes: "",
|
|
88
199
|
headerAppliedName: "",
|
|
89
200
|
headerAppliedValue: "",
|
|
90
|
-
headerStatus: ""
|
|
201
|
+
headerStatus: "",
|
|
202
|
+
quickPrompts: DEFAULT_QUICK_PROMPTS,
|
|
203
|
+
optimizerTier: DEFAULT_OPTIMIZER_TIER
|
|
91
204
|
};
|
|
92
205
|
var SEND_PRESETS = ["Enter", "Ctrl+Enter", "Alt+Enter", "Shift+Enter"];
|
|
93
206
|
var NEWLINE_PRESETS = ["Shift+Enter", "Enter", "Ctrl+Enter", "Alt+Enter"];
|
|
@@ -127,6 +240,29 @@ function sanitizeSettings(value) {
|
|
|
127
240
|
const v = source[field];
|
|
128
241
|
return typeof v === "number" && Number.isFinite(v) && v >= 320 && v <= 4e3 ? Math.round(v) : void 0;
|
|
129
242
|
};
|
|
243
|
+
const asQuickPrompts = () => {
|
|
244
|
+
const raw = source[QUICK_PROMPTS_FIELD];
|
|
245
|
+
if (!Array.isArray(raw)) return DEFAULT_QUICK_PROMPTS;
|
|
246
|
+
const seen = /* @__PURE__ */ new Set();
|
|
247
|
+
const out = [];
|
|
248
|
+
for (const item of raw) {
|
|
249
|
+
if (out.length >= QUICK_PROMPT_MAX) break;
|
|
250
|
+
if (typeof item !== "object" || item === null) continue;
|
|
251
|
+
const row2 = item;
|
|
252
|
+
const prompt = typeof row2.prompt === "string" ? row2.prompt.slice(0, QUICK_TEXT_MAX).trim() : "";
|
|
253
|
+
if (prompt === "") continue;
|
|
254
|
+
const label = typeof row2.label === "string" ? row2.label.slice(0, QUICK_LABEL_MAX).trim() : "";
|
|
255
|
+
const id = typeof row2.id === "string" && row2.id !== "" ? row2.id.slice(0, 64) : newQuickPromptId();
|
|
256
|
+
if (seen.has(id)) continue;
|
|
257
|
+
seen.add(id);
|
|
258
|
+
out.push({ id, label: label === "" ? prompt.slice(0, 12) : label, prompt, always: row2.always === true });
|
|
259
|
+
}
|
|
260
|
+
return out;
|
|
261
|
+
};
|
|
262
|
+
const asTier = () => {
|
|
263
|
+
const v = source[OPTIMIZER_TIER_FIELD];
|
|
264
|
+
return v === "basic" || v === "advanced" || v === "extreme" ? v : DEFAULT_OPTIMIZER_TIER;
|
|
265
|
+
};
|
|
130
266
|
return {
|
|
131
267
|
enabled: asBool(ENABLED_FIELD),
|
|
132
268
|
sendKey: asString(SEND_KEY_FIELD),
|
|
@@ -151,10 +287,136 @@ function sanitizeSettings(value) {
|
|
|
151
287
|
headerRoutes: asText(HEADER_ROUTES_FIELD, HEADER_VALUE_MAX),
|
|
152
288
|
headerAppliedName: asText(HEADER_APPLIED_NAME_FIELD, HEADER_NAME_MAX),
|
|
153
289
|
headerAppliedValue: asText(HEADER_APPLIED_VALUE_FIELD, HEADER_VALUE_MAX),
|
|
154
|
-
headerStatus: asText(HEADER_STATUS_FIELD, HEADER_VALUE_MAX)
|
|
290
|
+
headerStatus: asText(HEADER_STATUS_FIELD, HEADER_VALUE_MAX),
|
|
291
|
+
quickPrompts: asQuickPrompts(),
|
|
292
|
+
optimizerTier: asTier()
|
|
155
293
|
};
|
|
156
294
|
}
|
|
157
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
|
+
|
|
158
420
|
// src/client/chords.ts
|
|
159
421
|
var MODIFIER_KEYS = /* @__PURE__ */ new Set(["Control", "Alt", "Shift", "Meta", "AltGraph"]);
|
|
160
422
|
var CODE_LABELS = {
|
|
@@ -255,6 +517,118 @@ function displayChord(chord) {
|
|
|
255
517
|
return chord === "" ? "\u65E0" : chord;
|
|
256
518
|
}
|
|
257
519
|
|
|
520
|
+
// src/client/quick-commands.ts
|
|
521
|
+
var COMPOSER_SELECTOR = "[data-composer-input]";
|
|
522
|
+
var CARD_SELECTOR = "[data-composer-card]";
|
|
523
|
+
var state = { actions: null, draft: "", sessionId: "" };
|
|
524
|
+
function publishInputBridge(next) {
|
|
525
|
+
state.actions = next.actions;
|
|
526
|
+
state.draft = next.draft;
|
|
527
|
+
state.sessionId = next.sessionId;
|
|
528
|
+
}
|
|
529
|
+
function releaseInputBridge(sessionId) {
|
|
530
|
+
if (state.sessionId !== sessionId) return;
|
|
531
|
+
state.actions = null;
|
|
532
|
+
state.draft = "";
|
|
533
|
+
state.sessionId = "";
|
|
534
|
+
}
|
|
535
|
+
function draftFromDom() {
|
|
536
|
+
const el = document.querySelector(COMPOSER_SELECTOR);
|
|
537
|
+
if (!(el instanceof HTMLElement)) return "";
|
|
538
|
+
return el.innerText.replace(/\n+$/, "");
|
|
539
|
+
}
|
|
540
|
+
function currentDraft() {
|
|
541
|
+
return state.actions === null ? draftFromDom() : state.draft;
|
|
542
|
+
}
|
|
543
|
+
function alwaysPrompts(prompts) {
|
|
544
|
+
return prompts.filter((item) => item.always === true && item.prompt.trim() !== "");
|
|
545
|
+
}
|
|
546
|
+
function withAlwaysPrompts(draft, prompts) {
|
|
547
|
+
const picked = alwaysPrompts(prompts);
|
|
548
|
+
if (picked.length === 0) return null;
|
|
549
|
+
const base = draft.replace(/\s+$/, "");
|
|
550
|
+
if (base === "") return null;
|
|
551
|
+
const suffix = picked.map((item) => item.prompt.trim()).join("\n\n");
|
|
552
|
+
if (base.endsWith(suffix)) return null;
|
|
553
|
+
return `${base}
|
|
554
|
+
|
|
555
|
+
${suffix}`;
|
|
556
|
+
}
|
|
557
|
+
function applyAlwaysPrompts(prompts) {
|
|
558
|
+
const actions = state.actions;
|
|
559
|
+
if (actions === null) return false;
|
|
560
|
+
const next = withAlwaysPrompts(currentDraft(), prompts);
|
|
561
|
+
if (next === null) return false;
|
|
562
|
+
actions.setDraft(next);
|
|
563
|
+
return true;
|
|
564
|
+
}
|
|
565
|
+
function insertIntoDraft(text) {
|
|
566
|
+
const actions = state.actions;
|
|
567
|
+
const body = text.trim();
|
|
568
|
+
if (actions === null || body === "") return false;
|
|
569
|
+
const draft = currentDraft();
|
|
570
|
+
const next = draft.trim() === "" ? body : `${draft.replace(/\s+$/, "")}
|
|
571
|
+
${body}`;
|
|
572
|
+
actions.setDraft(next);
|
|
573
|
+
return true;
|
|
574
|
+
}
|
|
575
|
+
function replaceDraft(text) {
|
|
576
|
+
const actions = state.actions;
|
|
577
|
+
if (actions === null) return false;
|
|
578
|
+
actions.setDraft(text);
|
|
579
|
+
return true;
|
|
580
|
+
}
|
|
581
|
+
function focusComposer() {
|
|
582
|
+
const el = document.querySelector(COMPOSER_SELECTOR);
|
|
583
|
+
if (el instanceof HTMLElement) el.focus({ preventScroll: true });
|
|
584
|
+
}
|
|
585
|
+
function sendButtonOf(target) {
|
|
586
|
+
if (!(target instanceof Element)) return null;
|
|
587
|
+
const card = target.closest(CARD_SELECTOR);
|
|
588
|
+
if (card === null) return null;
|
|
589
|
+
const buttons = card.querySelectorAll("button");
|
|
590
|
+
if (buttons.length === 0) return null;
|
|
591
|
+
const last = buttons[buttons.length - 1];
|
|
592
|
+
if (!(last instanceof HTMLButtonElement)) return null;
|
|
593
|
+
if (last !== target && !last.contains(target)) return null;
|
|
594
|
+
if (last.disabled) return null;
|
|
595
|
+
if (last.querySelector("svg rect") !== null) return null;
|
|
596
|
+
if (last.querySelector("svg path") === null) return null;
|
|
597
|
+
return last;
|
|
598
|
+
}
|
|
599
|
+
async function optimizeDraft(text, tier) {
|
|
600
|
+
const body = text.trim();
|
|
601
|
+
if (body === "") return { ok: false, error: "\u8F93\u5165\u6846\u662F\u7A7A\u7684\uFF0C\u5148\u5199\u70B9\u4EC0\u4E48\u518D\u4F18\u5316" };
|
|
602
|
+
let response;
|
|
603
|
+
try {
|
|
604
|
+
response = await fetch(OPTIMIZER_API_PATH, {
|
|
605
|
+
method: "POST",
|
|
606
|
+
headers: { "content-type": "application/json" },
|
|
607
|
+
body: JSON.stringify({ text: body, tier })
|
|
608
|
+
});
|
|
609
|
+
} catch (error) {
|
|
610
|
+
return { ok: false, error: `\u8FDE\u4E0D\u4E0A\u5BBF\u4E3B\u534A\u7684\u4F18\u5316\u63A5\u53E3\uFF1A${error instanceof Error ? error.message : String(error)}` };
|
|
611
|
+
}
|
|
612
|
+
if (!response.ok) {
|
|
613
|
+
return { ok: false, error: `\u5BBF\u4E3B\u534A\u8FD4\u56DE HTTP ${response.status}\uFF08\u63D2\u4EF6\u53EF\u80FD\u8FD8\u6CA1\u91CD\u542F\u751F\u6548\uFF09` };
|
|
614
|
+
}
|
|
615
|
+
let payload;
|
|
616
|
+
try {
|
|
617
|
+
payload = await response.json();
|
|
618
|
+
} catch {
|
|
619
|
+
return { ok: false, error: "\u5BBF\u4E3B\u534A\u8FD4\u56DE\u7684\u4E0D\u662F JSON" };
|
|
620
|
+
}
|
|
621
|
+
const record = typeof payload === "object" && payload !== null ? payload : {};
|
|
622
|
+
if (record.ok !== true) {
|
|
623
|
+
const message = typeof record.error === "string" && record.error !== "" ? record.error : "\u4F18\u5316\u5931\u8D25";
|
|
624
|
+
return { ok: false, error: message };
|
|
625
|
+
}
|
|
626
|
+
const optimized = typeof record.text === "string" ? record.text.trim() : "";
|
|
627
|
+
if (optimized === "") return { ok: false, error: "\u6A21\u578B\u6CA1\u6709\u4EA7\u51FA\u4EFB\u4F55\u5185\u5BB9" };
|
|
628
|
+
const route = `${String(record.provider ?? "")}/${String(record.model ?? "")}`;
|
|
629
|
+
return { ok: true, text: optimized, route };
|
|
630
|
+
}
|
|
631
|
+
|
|
258
632
|
// src/client/interceptors.ts
|
|
259
633
|
var INPUT_SELECTOR = "[data-composer-input]";
|
|
260
634
|
var OVERLAY_SELECTOR = "[data-trigger-menu], [data-conversation-composer-overlay]";
|
|
@@ -266,6 +640,7 @@ function overlayOpen() {
|
|
|
266
640
|
return document.querySelector(OVERLAY_SELECTOR) !== null;
|
|
267
641
|
}
|
|
268
642
|
var replaying = false;
|
|
643
|
+
var replayingSendClick = false;
|
|
269
644
|
var pasteCache = null;
|
|
270
645
|
function prefetchClipboard() {
|
|
271
646
|
pasteCache = null;
|
|
@@ -306,6 +681,7 @@ function installInterceptors(deps) {
|
|
|
306
681
|
event.stopPropagation();
|
|
307
682
|
if (event.repeat) return;
|
|
308
683
|
if (gesture === "send") {
|
|
684
|
+
applyAlwaysPrompts(deps.alwaysPrompts());
|
|
309
685
|
dispatchKey(root, chordToInit("Enter"));
|
|
310
686
|
} else if (gesture === "newline") {
|
|
311
687
|
dispatchKey(root, chordToInit("Shift+Enter"));
|
|
@@ -329,11 +705,27 @@ function installInterceptors(deps) {
|
|
|
329
705
|
deps.setMenu({ x: event.clientX, y: event.clientY, hasSelection });
|
|
330
706
|
prefetchClipboard();
|
|
331
707
|
};
|
|
708
|
+
const onClickSend = (event) => {
|
|
709
|
+
if (replayingSendClick) return;
|
|
710
|
+
const button = sendButtonOf(event.target);
|
|
711
|
+
if (button === null) return;
|
|
712
|
+
if (!applyAlwaysPrompts(deps.alwaysPrompts())) return;
|
|
713
|
+
event.preventDefault();
|
|
714
|
+
event.stopPropagation();
|
|
715
|
+
replayingSendClick = true;
|
|
716
|
+
try {
|
|
717
|
+
button.click();
|
|
718
|
+
} finally {
|
|
719
|
+
replayingSendClick = false;
|
|
720
|
+
}
|
|
721
|
+
};
|
|
332
722
|
window.addEventListener("keydown", onKeyDown, true);
|
|
333
723
|
window.addEventListener("contextmenu", onContextMenu, true);
|
|
724
|
+
window.addEventListener("click", onClickSend, true);
|
|
334
725
|
return () => {
|
|
335
726
|
window.removeEventListener("keydown", onKeyDown, true);
|
|
336
727
|
window.removeEventListener("contextmenu", onContextMenu, true);
|
|
728
|
+
window.removeEventListener("click", onClickSend, true);
|
|
337
729
|
};
|
|
338
730
|
}
|
|
339
731
|
async function runMenuAction(id) {
|
|
@@ -444,6 +836,36 @@ async function pasteText(root) {
|
|
|
444
836
|
|
|
445
837
|
// src/client/panel.ts
|
|
446
838
|
var PANEL_SELECTOR = '[role="dialog"][aria-modal="true"]:has(> nav)';
|
|
839
|
+
var RESIZE_LAYER_CLASS = "dsh-ux-resize-layer";
|
|
840
|
+
var RESIZE_OUTLINE_CLASS = "dsh-ux-resize-outline";
|
|
841
|
+
var RESIZE_EDGE_CLASS = "dsh-ux-resize-edge";
|
|
842
|
+
var RESIZE_GRIP_CLASS = "dsh-ux-resize-grip";
|
|
843
|
+
var BAND = 8;
|
|
844
|
+
var INSET = 14;
|
|
845
|
+
var GRIP = 26;
|
|
846
|
+
function handleBox(edge) {
|
|
847
|
+
switch (edge) {
|
|
848
|
+
case "left":
|
|
849
|
+
return { left: 0, top: INSET, bottom: INSET, width: BAND, cursor: "ew-resize" };
|
|
850
|
+
case "right":
|
|
851
|
+
return { right: 0, top: INSET, bottom: INSET, width: BAND, cursor: "ew-resize" };
|
|
852
|
+
case "top":
|
|
853
|
+
return { top: 0, left: INSET, right: INSET, height: BAND, cursor: "ns-resize" };
|
|
854
|
+
case "bottom":
|
|
855
|
+
return { bottom: 0, left: INSET, right: INSET, height: BAND, cursor: "ns-resize" };
|
|
856
|
+
case "br":
|
|
857
|
+
return { right: 8, bottom: 8, width: GRIP, height: GRIP, cursor: "nwse-resize" };
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
var RESIZE_OUTLINE_STYLE = {
|
|
861
|
+
position: "absolute",
|
|
862
|
+
inset: 0,
|
|
863
|
+
// 跟随面板自身的圆角(官方 .panel 是 32px)——用 inherit 而不是写死数字,
|
|
864
|
+
// 官方改圆角时这里自动跟上。
|
|
865
|
+
borderRadius: "inherit",
|
|
866
|
+
border: "1px solid rgba(127, 127, 137, .28)",
|
|
867
|
+
pointerEvents: "none"
|
|
868
|
+
};
|
|
447
869
|
var PANEL_CSS = `
|
|
448
870
|
html.dsh-ux-panel-scroll [role="dialog"][aria-modal="true"]:has(> nav) { min-height: 320px; }
|
|
449
871
|
html.dsh-ux-panel-scroll [role="dialog"][aria-modal="true"]:has(> nav) > nav {
|
|
@@ -467,10 +889,32 @@ html.dsh-ux-panel-scroll [role="dialog"][aria-modal="true"]:has(> nav) > nav > d
|
|
|
467
889
|
background: var(--dsh-scrollbar-thumb-hover, var(--dsw-alias-scrollbar-hover-l2));
|
|
468
890
|
}
|
|
469
891
|
`;
|
|
892
|
+
var RESIZE_CSS = `
|
|
893
|
+
.${RESIZE_LAYER_CLASS} { position: absolute; inset: 0; pointer-events: none; }
|
|
894
|
+
.${RESIZE_EDGE_CLASS}, .${RESIZE_GRIP_CLASS} {
|
|
895
|
+
position: absolute;
|
|
896
|
+
pointer-events: auto;
|
|
897
|
+
background: transparent;
|
|
898
|
+
border-radius: 6px;
|
|
899
|
+
transition: background-color .12s ease, color .12s ease;
|
|
900
|
+
touch-action: none;
|
|
901
|
+
}
|
|
902
|
+
.${RESIZE_EDGE_CLASS}:hover { background: rgba(127, 127, 137, .22); }
|
|
903
|
+
.${RESIZE_EDGE_CLASS}[data-active="true"] { background: rgba(127, 127, 137, .3); }
|
|
904
|
+
.${RESIZE_GRIP_CLASS} {
|
|
905
|
+
display: flex;
|
|
906
|
+
align-items: flex-end;
|
|
907
|
+
justify-content: flex-end;
|
|
908
|
+
padding: 3px;
|
|
909
|
+
color: rgba(127, 127, 137, .55);
|
|
910
|
+
}
|
|
911
|
+
.${RESIZE_GRIP_CLASS}:hover { color: rgba(127, 127, 137, .95); background: rgba(127, 127, 137, .16); }
|
|
912
|
+
`;
|
|
470
913
|
function installPanelStyle(settings, subscribe) {
|
|
471
914
|
const tag = document.createElement("style");
|
|
472
915
|
tag.dataset.plugin = "dsh-composer-ux-panel";
|
|
473
|
-
tag.textContent = PANEL_CSS
|
|
916
|
+
tag.textContent = `${PANEL_CSS}
|
|
917
|
+
${RESIZE_CSS}`;
|
|
474
918
|
document.head.appendChild(tag);
|
|
475
919
|
const applyClass = () => {
|
|
476
920
|
document.documentElement.classList.toggle("dsh-ux-panel-scroll", settings());
|
|
@@ -576,6 +1020,45 @@ function installSettingsCardStyle() {
|
|
|
576
1020
|
};
|
|
577
1021
|
}
|
|
578
1022
|
|
|
1023
|
+
// src/client/quick-style.ts
|
|
1024
|
+
var QUICK_BUTTON_CLASS = "composer-ux-quick-button";
|
|
1025
|
+
var QUICK_BUTTON_CSS = `
|
|
1026
|
+
.${QUICK_BUTTON_CLASS} {
|
|
1027
|
+
display: inline-flex;
|
|
1028
|
+
align-items: center;
|
|
1029
|
+
gap: 4px;
|
|
1030
|
+
height: 24px;
|
|
1031
|
+
border: 1px solid rgba(127, 127, 137, .35);
|
|
1032
|
+
background: transparent;
|
|
1033
|
+
color: inherit;
|
|
1034
|
+
border-radius: 999px;
|
|
1035
|
+
padding: 0 9px;
|
|
1036
|
+
font-size: 12px;
|
|
1037
|
+
line-height: 1;
|
|
1038
|
+
cursor: pointer;
|
|
1039
|
+
opacity: .75;
|
|
1040
|
+
white-space: nowrap;
|
|
1041
|
+
font-variant-numeric: tabular-nums;
|
|
1042
|
+
transition: opacity .12s ease, background-color .12s ease;
|
|
1043
|
+
}
|
|
1044
|
+
.${QUICK_BUTTON_CLASS}:hover { opacity: 1; background: rgba(127, 127, 137, .12); }
|
|
1045
|
+
.${QUICK_BUTTON_CLASS}[aria-expanded="true"] {
|
|
1046
|
+
opacity: 1;
|
|
1047
|
+
background: rgba(127, 127, 137, .18);
|
|
1048
|
+
border-color: rgba(127, 127, 137, .6);
|
|
1049
|
+
}
|
|
1050
|
+
.${QUICK_BUTTON_CLASS} svg { flex: 0 0 auto; }
|
|
1051
|
+
`;
|
|
1052
|
+
function installQuickButtonStyle() {
|
|
1053
|
+
const tag = document.createElement("style");
|
|
1054
|
+
tag.dataset.plugin = "dsh-composer-ux-quick-button";
|
|
1055
|
+
tag.textContent = QUICK_BUTTON_CSS;
|
|
1056
|
+
document.head.appendChild(tag);
|
|
1057
|
+
return () => {
|
|
1058
|
+
tag.remove();
|
|
1059
|
+
};
|
|
1060
|
+
}
|
|
1061
|
+
|
|
579
1062
|
// src/client/ContextMenuHost.tsx
|
|
580
1063
|
var import_react = __toESM(require("react"), 1);
|
|
581
1064
|
|
|
@@ -708,6 +1191,192 @@ var menuNote = {
|
|
|
708
1191
|
lineHeight: 1.4,
|
|
709
1192
|
padding: "4px 10px 2px"
|
|
710
1193
|
};
|
|
1194
|
+
var quickPanel = {
|
|
1195
|
+
position: "fixed",
|
|
1196
|
+
zIndex: 9999,
|
|
1197
|
+
width: 420,
|
|
1198
|
+
maxWidth: "calc(100vw - 24px)",
|
|
1199
|
+
maxHeight: "min(60vh, 520px)",
|
|
1200
|
+
display: "flex",
|
|
1201
|
+
flexDirection: "column",
|
|
1202
|
+
background: "var(--dsw-specific-menu)",
|
|
1203
|
+
border: "0.5px solid var(--dsw-alias-border-l1)",
|
|
1204
|
+
borderRadius: 12,
|
|
1205
|
+
boxShadow: "var(--dsw-elevation-prominent)",
|
|
1206
|
+
pointerEvents: "auto",
|
|
1207
|
+
overflow: "hidden"
|
|
1208
|
+
};
|
|
1209
|
+
var quickPanelHead = {
|
|
1210
|
+
padding: "10px 12px 8px",
|
|
1211
|
+
borderBottom: "0.5px solid var(--dsw-alias-border-l2)",
|
|
1212
|
+
display: "flex",
|
|
1213
|
+
flexDirection: "column",
|
|
1214
|
+
gap: 8
|
|
1215
|
+
};
|
|
1216
|
+
var quickPanelTitleRow = {
|
|
1217
|
+
display: "flex",
|
|
1218
|
+
alignItems: "center",
|
|
1219
|
+
justifyContent: "space-between",
|
|
1220
|
+
gap: 8
|
|
1221
|
+
};
|
|
1222
|
+
var quickPanelTitle = {
|
|
1223
|
+
color: "var(--dsw-alias-label-primary)",
|
|
1224
|
+
fontSize: 13,
|
|
1225
|
+
fontWeight: 600
|
|
1226
|
+
};
|
|
1227
|
+
var quickTierRow = {
|
|
1228
|
+
display: "inline-flex",
|
|
1229
|
+
gap: 2,
|
|
1230
|
+
padding: 2,
|
|
1231
|
+
borderRadius: 999,
|
|
1232
|
+
background: "var(--dsw-alias-bg-layer-1)",
|
|
1233
|
+
border: "0.5px solid var(--dsw-alias-border-l2)"
|
|
1234
|
+
};
|
|
1235
|
+
var quickTierButton = {
|
|
1236
|
+
border: "none",
|
|
1237
|
+
background: "transparent",
|
|
1238
|
+
color: "var(--dsw-alias-label-tertiary)",
|
|
1239
|
+
fontSize: 11,
|
|
1240
|
+
lineHeight: 1,
|
|
1241
|
+
padding: "4px 8px",
|
|
1242
|
+
borderRadius: 999,
|
|
1243
|
+
cursor: "pointer",
|
|
1244
|
+
whiteSpace: "nowrap"
|
|
1245
|
+
};
|
|
1246
|
+
var quickTierButtonActive = {
|
|
1247
|
+
...quickTierButton,
|
|
1248
|
+
background: "var(--dsw-alias-button-primary-fill)",
|
|
1249
|
+
color: "var(--dsw-alias-label-primary-foreground)"
|
|
1250
|
+
};
|
|
1251
|
+
var quickPrimaryButton = {
|
|
1252
|
+
display: "inline-flex",
|
|
1253
|
+
alignItems: "center",
|
|
1254
|
+
justifyContent: "center",
|
|
1255
|
+
gap: 6,
|
|
1256
|
+
width: "100%",
|
|
1257
|
+
padding: "7px 12px",
|
|
1258
|
+
borderRadius: 8,
|
|
1259
|
+
border: "0.5px solid var(--dsw-alias-button-primary-fill)",
|
|
1260
|
+
background: "var(--dsw-alias-button-primary-fill)",
|
|
1261
|
+
color: "var(--dsw-alias-label-primary-foreground)",
|
|
1262
|
+
fontSize: 12,
|
|
1263
|
+
cursor: "pointer"
|
|
1264
|
+
};
|
|
1265
|
+
var quickPrimaryButtonDisabled = {
|
|
1266
|
+
...quickPrimaryButton,
|
|
1267
|
+
opacity: 0.4,
|
|
1268
|
+
cursor: "default"
|
|
1269
|
+
};
|
|
1270
|
+
var quickList = {
|
|
1271
|
+
overflowY: "auto",
|
|
1272
|
+
padding: "6px 6px 8px",
|
|
1273
|
+
display: "flex",
|
|
1274
|
+
flexDirection: "column",
|
|
1275
|
+
gap: 2
|
|
1276
|
+
};
|
|
1277
|
+
var quickItem = {
|
|
1278
|
+
display: "flex",
|
|
1279
|
+
alignItems: "center",
|
|
1280
|
+
gap: 8,
|
|
1281
|
+
padding: "5px 8px",
|
|
1282
|
+
borderRadius: 7,
|
|
1283
|
+
cursor: "pointer",
|
|
1284
|
+
background: "transparent",
|
|
1285
|
+
border: "none",
|
|
1286
|
+
flex: "1 1 auto",
|
|
1287
|
+
minWidth: 0,
|
|
1288
|
+
textAlign: "left"
|
|
1289
|
+
};
|
|
1290
|
+
var quickItemLabel = {
|
|
1291
|
+
color: "var(--dsw-alias-label-primary)",
|
|
1292
|
+
fontSize: 12,
|
|
1293
|
+
flex: "0 0 auto",
|
|
1294
|
+
whiteSpace: "nowrap"
|
|
1295
|
+
};
|
|
1296
|
+
var quickItemPreview = {
|
|
1297
|
+
color: "var(--dsw-alias-label-tertiary)",
|
|
1298
|
+
fontSize: 11,
|
|
1299
|
+
flex: "1 1 auto",
|
|
1300
|
+
minWidth: 0,
|
|
1301
|
+
overflow: "hidden",
|
|
1302
|
+
textOverflow: "ellipsis",
|
|
1303
|
+
whiteSpace: "nowrap"
|
|
1304
|
+
};
|
|
1305
|
+
var quickAlwaysLabel = {
|
|
1306
|
+
display: "inline-flex",
|
|
1307
|
+
alignItems: "center",
|
|
1308
|
+
gap: 4,
|
|
1309
|
+
flex: "0 0 auto",
|
|
1310
|
+
color: "var(--dsw-alias-label-tertiary)",
|
|
1311
|
+
fontSize: 11,
|
|
1312
|
+
whiteSpace: "nowrap",
|
|
1313
|
+
cursor: "pointer"
|
|
1314
|
+
};
|
|
1315
|
+
var quickAlwaysBox = {
|
|
1316
|
+
margin: 0,
|
|
1317
|
+
cursor: "pointer"
|
|
1318
|
+
};
|
|
1319
|
+
var quickPanelFoot = {
|
|
1320
|
+
padding: "5px 12px 7px",
|
|
1321
|
+
borderTop: "0.5px solid var(--dsw-alias-border-l2)",
|
|
1322
|
+
display: "flex",
|
|
1323
|
+
alignItems: "center",
|
|
1324
|
+
justifyContent: "space-between",
|
|
1325
|
+
gap: 8
|
|
1326
|
+
};
|
|
1327
|
+
var quickNotice = {
|
|
1328
|
+
color: "var(--dsw-alias-state-warn-label)",
|
|
1329
|
+
fontSize: 11,
|
|
1330
|
+
lineHeight: 1.4,
|
|
1331
|
+
minWidth: 0,
|
|
1332
|
+
overflow: "hidden",
|
|
1333
|
+
textOverflow: "ellipsis"
|
|
1334
|
+
};
|
|
1335
|
+
var quickFootHint = {
|
|
1336
|
+
color: "var(--dsw-alias-label-tertiary)",
|
|
1337
|
+
fontSize: 11,
|
|
1338
|
+
whiteSpace: "nowrap",
|
|
1339
|
+
flex: "0 0 auto"
|
|
1340
|
+
};
|
|
1341
|
+
var quickEmpty = {
|
|
1342
|
+
color: "var(--dsw-alias-label-tertiary)",
|
|
1343
|
+
fontSize: 12,
|
|
1344
|
+
lineHeight: 1.6,
|
|
1345
|
+
padding: "14px 10px",
|
|
1346
|
+
textAlign: "center"
|
|
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
|
+
};
|
|
711
1380
|
|
|
712
1381
|
// src/client/ContextMenuHost.tsx
|
|
713
1382
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
@@ -844,54 +1513,9 @@ function ContextMenuHost({ useMenu, useLive, actions }) {
|
|
|
844
1513
|
|
|
845
1514
|
// src/client/PanelResizeHandles.tsx
|
|
846
1515
|
var import_react2 = require("react");
|
|
1516
|
+
var import_react_dom = require("react-dom");
|
|
847
1517
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
848
|
-
|
|
849
|
-
const horizontal = (left, width) => ({
|
|
850
|
-
left,
|
|
851
|
-
top: rect.top + 12,
|
|
852
|
-
width,
|
|
853
|
-
height: Math.max(0, rect.height - 24),
|
|
854
|
-
cursor: "ew-resize"
|
|
855
|
-
});
|
|
856
|
-
const vertical = (top, height) => ({
|
|
857
|
-
left: rect.left + 16,
|
|
858
|
-
top,
|
|
859
|
-
width: Math.max(0, rect.width - 32),
|
|
860
|
-
height,
|
|
861
|
-
cursor: "ns-resize"
|
|
862
|
-
});
|
|
863
|
-
const corner = (left, top, horizontalCursor, verticalCursor) => ({
|
|
864
|
-
left,
|
|
865
|
-
top,
|
|
866
|
-
width: 18,
|
|
867
|
-
height: 18,
|
|
868
|
-
cursor: horizontalCursor
|
|
869
|
-
});
|
|
870
|
-
const corners = {
|
|
871
|
-
tl: "nwse-resize",
|
|
872
|
-
tr: "nesw-resize",
|
|
873
|
-
bl: "nesw-resize",
|
|
874
|
-
br: "nwse-resize"
|
|
875
|
-
};
|
|
876
|
-
switch (edge) {
|
|
877
|
-
case "left":
|
|
878
|
-
return horizontal(rect.left - 4, 8);
|
|
879
|
-
case "right":
|
|
880
|
-
return horizontal(rect.right - 4, 8);
|
|
881
|
-
case "top":
|
|
882
|
-
return vertical(rect.top - 4, 8);
|
|
883
|
-
case "bottom":
|
|
884
|
-
return vertical(rect.bottom - 4, 8);
|
|
885
|
-
case "tl":
|
|
886
|
-
return corner(rect.left - 6, rect.top - 6, corners.tl, "nwse");
|
|
887
|
-
case "tr":
|
|
888
|
-
return corner(rect.right - 12, rect.top - 6, corners.tr, "nesw");
|
|
889
|
-
case "bl":
|
|
890
|
-
return corner(rect.left - 6, rect.bottom - 14, corners.bl, "nesw");
|
|
891
|
-
case "br":
|
|
892
|
-
return corner(rect.right - 12, rect.bottom - 14, corners.br, "nwse");
|
|
893
|
-
}
|
|
894
|
-
}
|
|
1518
|
+
var EDGES = ["left", "right", "top", "bottom", "br"];
|
|
895
1519
|
function PanelResizeHandles({ useLive, actions }) {
|
|
896
1520
|
const settings = useLive((value) => ({
|
|
897
1521
|
enabled: value.enabled,
|
|
@@ -899,130 +1523,126 @@ function PanelResizeHandles({ useLive, actions }) {
|
|
|
899
1523
|
panelWidth: value.panelWidth,
|
|
900
1524
|
panelHeight: value.panelHeight
|
|
901
1525
|
}));
|
|
902
|
-
const settingsRef = (0, import_react2.useRef)(settings);
|
|
903
|
-
settingsRef.current = settings;
|
|
904
1526
|
const enabled = settings.enabled === true && settings.panelResize === true;
|
|
905
|
-
const [
|
|
906
|
-
const
|
|
1527
|
+
const [panel, setPanel] = (0, import_react2.useState)(null);
|
|
1528
|
+
const [active, setActive] = (0, import_react2.useState)(null);
|
|
1529
|
+
const dragRef = (0, import_react2.useRef)(null);
|
|
907
1530
|
(0, import_react2.useEffect)(() => {
|
|
908
1531
|
if (!enabled) {
|
|
909
|
-
|
|
1532
|
+
setPanel(null);
|
|
910
1533
|
return;
|
|
911
1534
|
}
|
|
1535
|
+
let current = null;
|
|
912
1536
|
const probe = () => {
|
|
913
|
-
const
|
|
914
|
-
if (
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
return;
|
|
918
|
-
}
|
|
919
|
-
if (!appliedRef.current) {
|
|
920
|
-
appliedRef.current = true;
|
|
921
|
-
const width = settingsRef.current.panelWidth;
|
|
922
|
-
const height = settingsRef.current.panelHeight;
|
|
923
|
-
if (width !== void 0) panel.style.width = `${clampPanelWidth(width)}px`;
|
|
924
|
-
if (height !== void 0) panel.style.height = `${clampPanelHeight(height)}px`;
|
|
925
|
-
}
|
|
926
|
-
setRect(panel.getBoundingClientRect());
|
|
1537
|
+
const found = findSettingsPanel();
|
|
1538
|
+
if (found === current) return;
|
|
1539
|
+
current = found;
|
|
1540
|
+
setPanel(found);
|
|
927
1541
|
};
|
|
928
1542
|
probe();
|
|
929
1543
|
const timer = setInterval(probe, 250);
|
|
930
|
-
const onResize = () => {
|
|
931
|
-
setRect((current) => current === null ? null : findSettingsPanel()?.getBoundingClientRect() ?? null);
|
|
932
|
-
};
|
|
933
|
-
window.addEventListener("resize", onResize);
|
|
934
1544
|
return () => {
|
|
935
1545
|
clearInterval(timer);
|
|
936
|
-
window.removeEventListener("resize", onResize);
|
|
937
1546
|
};
|
|
938
1547
|
}, [enabled]);
|
|
939
|
-
|
|
1548
|
+
(0, import_react2.useEffect)(() => {
|
|
1549
|
+
if (panel === null) return;
|
|
1550
|
+
const width = settings.panelWidth;
|
|
1551
|
+
const height = settings.panelHeight;
|
|
1552
|
+
if (width === void 0) panel.style.removeProperty("width");
|
|
1553
|
+
else panel.style.width = `${clampPanelWidth(width)}px`;
|
|
1554
|
+
if (height === void 0) panel.style.removeProperty("height");
|
|
1555
|
+
else panel.style.height = `${clampPanelHeight(height)}px`;
|
|
1556
|
+
}, [panel, settings.panelWidth, settings.panelHeight]);
|
|
1557
|
+
if (!enabled || panel === null) return null;
|
|
940
1558
|
const onPointerDown = (edge, event) => {
|
|
941
1559
|
event.preventDefault();
|
|
942
1560
|
event.stopPropagation();
|
|
943
|
-
const
|
|
944
|
-
|
|
1561
|
+
const el = panel;
|
|
1562
|
+
const rect = el.getBoundingClientRect();
|
|
1563
|
+
el.style.position = "fixed";
|
|
1564
|
+
el.style.margin = "0";
|
|
1565
|
+
el.style.left = `${rect.left}px`;
|
|
1566
|
+
el.style.top = `${rect.top}px`;
|
|
1567
|
+
el.style.width = `${rect.width}px`;
|
|
1568
|
+
el.style.height = `${rect.height}px`;
|
|
945
1569
|
const start = {
|
|
946
1570
|
edge,
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
1571
|
+
x: event.clientX,
|
|
1572
|
+
y: event.clientY,
|
|
1573
|
+
left: rect.left,
|
|
1574
|
+
top: rect.top,
|
|
1575
|
+
width: rect.width,
|
|
1576
|
+
height: rect.height
|
|
951
1577
|
};
|
|
1578
|
+
dragRef.current = start;
|
|
1579
|
+
setActive(edge);
|
|
1580
|
+
document.body.style.cursor = String(handleBox(edge).cursor ?? "default");
|
|
1581
|
+
document.body.style.userSelect = "none";
|
|
952
1582
|
const onMove = (move) => {
|
|
953
|
-
if (
|
|
1583
|
+
if (dragRef.current !== start) return;
|
|
954
1584
|
move.preventDefault();
|
|
955
|
-
const
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
1585
|
+
const dx = move.clientX - start.x;
|
|
1586
|
+
const dy = move.clientY - start.y;
|
|
1587
|
+
let { left, top, width, height } = start;
|
|
1588
|
+
if (edge === "right" || edge === "br") width = clampPanelWidth(start.width + dx);
|
|
1589
|
+
if (edge === "bottom" || edge === "br") height = clampPanelHeight(start.height + dy);
|
|
1590
|
+
if (edge === "left") {
|
|
1591
|
+
width = clampPanelWidth(start.width - dx);
|
|
1592
|
+
left = start.left + (start.width - width);
|
|
963
1593
|
}
|
|
964
|
-
if (edge === "top"
|
|
965
|
-
height = start.
|
|
1594
|
+
if (edge === "top") {
|
|
1595
|
+
height = clampPanelHeight(start.height - dy);
|
|
1596
|
+
top = start.top + (start.height - height);
|
|
966
1597
|
}
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
1598
|
+
el.style.left = `${Math.round(left)}px`;
|
|
1599
|
+
el.style.top = `${Math.round(top)}px`;
|
|
1600
|
+
el.style.width = `${Math.round(width)}px`;
|
|
1601
|
+
el.style.height = `${Math.round(height)}px`;
|
|
970
1602
|
};
|
|
971
1603
|
const onUp = () => {
|
|
972
1604
|
window.removeEventListener("pointermove", onMove);
|
|
973
1605
|
window.removeEventListener("pointerup", onUp);
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
}
|
|
1606
|
+
dragRef.current = null;
|
|
1607
|
+
setActive(null);
|
|
1608
|
+
const box = el.getBoundingClientRect();
|
|
1609
|
+
actions.setField(PANEL_WIDTH_FIELD, Math.round(clampPanelWidth(box.width)));
|
|
1610
|
+
actions.setField(PANEL_HEIGHT_FIELD, Math.round(clampPanelHeight(box.height)));
|
|
980
1611
|
document.body.style.removeProperty("cursor");
|
|
981
1612
|
document.body.style.removeProperty("user-select");
|
|
982
1613
|
};
|
|
983
|
-
dragStartRef.current = start;
|
|
984
|
-
document.body.style.cursor = stripRect(edge, rect).cursor;
|
|
985
|
-
document.body.style.userSelect = "none";
|
|
986
1614
|
window.addEventListener("pointermove", onMove);
|
|
987
1615
|
window.addEventListener("pointerup", onUp);
|
|
988
1616
|
};
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
event
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1617
|
+
return (0, import_react_dom.createPortal)(
|
|
1618
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: RESIZE_LAYER_CLASS, "data-composer-ux-resize": true, children: [
|
|
1619
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: RESIZE_OUTLINE_CLASS, style: RESIZE_OUTLINE_STYLE }),
|
|
1620
|
+
EDGES.map((edge) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1621
|
+
"div",
|
|
1622
|
+
{
|
|
1623
|
+
className: edge === "br" ? RESIZE_GRIP_CLASS : RESIZE_EDGE_CLASS,
|
|
1624
|
+
"data-active": active === edge ? "true" : void 0,
|
|
1625
|
+
title: edge === "br" ? "\u62D6\u52A8\u6539\u9762\u677F\u5927\u5C0F" : void 0,
|
|
1626
|
+
style: handleBox(edge),
|
|
1627
|
+
onPointerDown: (event) => {
|
|
1628
|
+
onPointerDown(edge, event);
|
|
1629
|
+
},
|
|
1630
|
+
children: edge === "br" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { width: "12", height: "12", viewBox: "0 0 12 12", "aria-hidden": true, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1631
|
+
"path",
|
|
1632
|
+
{
|
|
1633
|
+
d: "M11 1 1 11M11 6 6 11",
|
|
1634
|
+
stroke: "currentColor",
|
|
1635
|
+
strokeWidth: "1.3",
|
|
1636
|
+
strokeLinecap: "round"
|
|
1637
|
+
}
|
|
1638
|
+
) })
|
|
1005
1639
|
},
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
width: pos.width,
|
|
1012
|
-
height: pos.height,
|
|
1013
|
-
cursor: pos.cursor,
|
|
1014
|
-
background: "transparent",
|
|
1015
|
-
opacity: 0,
|
|
1016
|
-
borderRadius: 6,
|
|
1017
|
-
pointerEvents: "auto",
|
|
1018
|
-
touchAction: "none"
|
|
1019
|
-
}
|
|
1020
|
-
},
|
|
1021
|
-
edge
|
|
1022
|
-
);
|
|
1023
|
-
}) });
|
|
1640
|
+
edge
|
|
1641
|
+
))
|
|
1642
|
+
] }),
|
|
1643
|
+
panel
|
|
1644
|
+
);
|
|
1024
1645
|
}
|
|
1025
|
-
var dragStartRef = { current: null };
|
|
1026
1646
|
|
|
1027
1647
|
// src/client/SettingsSection.tsx
|
|
1028
1648
|
var import_react3 = require("react");
|
|
@@ -1247,8 +1867,237 @@ function TextFieldRow(props) {
|
|
|
1247
1867
|
] })
|
|
1248
1868
|
] });
|
|
1249
1869
|
}
|
|
1250
|
-
function
|
|
1870
|
+
function QuickPromptsEditor(props) {
|
|
1871
|
+
const [draft, setDraft] = (0, import_react3.useState)(() => props.book);
|
|
1872
|
+
const [activeId, setActiveId] = (0, import_react3.useState)(() => props.book.categories[0]?.id ?? "");
|
|
1873
|
+
const [dirty, setDirty] = (0, import_react3.useState)(false);
|
|
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) => {
|
|
1884
|
+
setDirty(true);
|
|
1885
|
+
setDraft(next);
|
|
1886
|
+
};
|
|
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)"
|
|
1899
|
+
};
|
|
1900
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: [
|
|
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
|
+
]
|
|
1916
|
+
},
|
|
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: [
|
|
2006
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2007
|
+
"input",
|
|
2008
|
+
{
|
|
2009
|
+
type: "checkbox",
|
|
2010
|
+
checked: prompt.always,
|
|
2011
|
+
style: { margin: 0, cursor: "pointer" },
|
|
2012
|
+
onChange: (event) => {
|
|
2013
|
+
edit(withPromptPatched(draft, current.id, prompt.id, { always: event.target.checked }));
|
|
2014
|
+
}
|
|
2015
|
+
}
|
|
2016
|
+
),
|
|
2017
|
+
"\u9ED8\u8BA4\u63D2\u5165"
|
|
2018
|
+
] }),
|
|
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
|
+
] }),
|
|
2049
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap" }, children: [
|
|
2050
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2051
|
+
"button",
|
|
2052
|
+
{
|
|
2053
|
+
type: "button",
|
|
2054
|
+
style: dirty ? pillActive : pill,
|
|
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"
|
|
2070
|
+
}
|
|
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" }),
|
|
2078
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { style: rowDesc, children: [
|
|
2079
|
+
"\u5171 ",
|
|
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}` : ""
|
|
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"
|
|
2094
|
+
] })
|
|
2095
|
+
] });
|
|
2096
|
+
}
|
|
2097
|
+
function SettingsSection({ useLive, useBook, useBookStatus, actions }) {
|
|
1251
2098
|
const settings = useLive((item) => item);
|
|
2099
|
+
const book = useBook((item) => item);
|
|
2100
|
+
const bookStatus = useBookStatus((item) => item);
|
|
1252
2101
|
const [conflict, setConflict] = (0, import_react3.useState)(null);
|
|
1253
2102
|
const setKey = (side, chord) => {
|
|
1254
2103
|
const other = side === "send" ? settings.newlineKey : settings.sendKey;
|
|
@@ -1265,6 +2114,8 @@ function SettingsSection({ useLive, actions }) {
|
|
|
1265
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`;
|
|
1266
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}`;
|
|
1267
2116
|
const headerSummary = settings.headerEnabled ? settings.headerStatus === "" ? "\u5DF2\u542F\u7528" : settings.headerStatus : "\u672A\u542F\u7528";
|
|
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"}`;
|
|
1268
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";
|
|
1269
2120
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { padding: "4px 2px" }, children: [
|
|
1270
2121
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { className: "dsh-ux-card", children: [
|
|
@@ -1372,6 +2223,50 @@ function SettingsSection({ useLive, actions }) {
|
|
|
1372
2223
|
) })
|
|
1373
2224
|
] })
|
|
1374
2225
|
] }),
|
|
2226
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(FoldCard, { name: "\u5FEB\u6377\u6307\u4EE4", summary: quickSummary, children: [
|
|
2227
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { style: bodyLead, children: "\u8F93\u5165\u6846\u5DE5\u5177\u884C\u91CC\u90A3\u4E2A\u300C\u5FEB\u6377\u6307\u4EE4\u300D\u6309\u94AE\u70B9\u5F00\u5C31\u662F\u8FD9\u5F20\u6E05\u5355\uFF1A\u70B9\u6761\u76EE\u628A\u5185\u5BB9\u63D2\u5165\u8F93\u5165\u6846\uFF1B \u6761\u76EE\u53F3\u4FA7\u52FE\u4E0A\u300C\u9ED8\u8BA4\u63D2\u5165\u300D\uFF0C\u5219\u5728\u4F60**\u70B9\u53D1\u9001\u65F6**\u628A\u8FD9\u6761\u63D0\u793A\u8BCD\u81EA\u52A8\u9644\u52A0\u5230\u6D88\u606F**\u672B\u5C3E** \u4E00\u8D77\u53D1\u51FA\u53BB\uFF08\u591A\u6761\u6309\u5217\u8868\u987A\u5E8F\u62FC\u63A5\uFF0C\u8F93\u5165\u6846\u91CC\u4E0D\u63D0\u524D\u663E\u793A\uFF09\u3002 \u300C\u4F18\u5316\u63D0\u793A\u8BCD\u300D\u4F1A\u7528\u53E6\u4E00\u4E2A AI \u628A\u8F93\u5165\u6846\u91CC\u7684\u8BDD\u6574\u7406\u6210\u4E00\u6761\u80FD\u76F4\u63A5\u53D1\u51FA\u53BB\u7684\u6E05\u6670\u6307\u4EE4\uFF0C \u7ED3\u679C\u76F4\u63A5\u5199\u56DE\u8F93\u5165\u6846\uFF08Ctrl+Z \u53EF\u8FD8\u539F\uFF09\u2014\u2014\u4E0D\u4F1A\u6C61\u67D3\u5F53\u524D\u5BF9\u8BDD\uFF0C\u4E5F\u4E0D\u5360\u4F60\u7684\u5BF9\u8BDD\u8F6E\u6B21\u3002" }),
|
|
2228
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { ...row, borderTop: "none", flexDirection: "column", alignItems: "stretch", gap: 8 }, children: [
|
|
2229
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: rowText, children: [
|
|
2230
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: rowTitle, children: "\u4F18\u5316\u5F3A\u5EA6" }),
|
|
2231
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: rowDesc, children: OPTIMIZER_TIERS.find((item) => item.id === settings.optimizerTier)?.hint ?? "" })
|
|
2232
|
+
] }),
|
|
2233
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap" }, children: OPTIMIZER_TIERS.map((item) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2234
|
+
"button",
|
|
2235
|
+
{
|
|
2236
|
+
type: "button",
|
|
2237
|
+
title: item.hint,
|
|
2238
|
+
style: settings.optimizerTier === item.id ? pillActive : pill,
|
|
2239
|
+
onClick: () => {
|
|
2240
|
+
actions.setField(OPTIMIZER_TIER_FIELD, item.id);
|
|
2241
|
+
},
|
|
2242
|
+
children: item.label
|
|
2243
|
+
},
|
|
2244
|
+
item.id
|
|
2245
|
+
)) })
|
|
2246
|
+
] }),
|
|
2247
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { ...row, borderTop: "none", flexDirection: "column", alignItems: "stretch", gap: 8 }, children: [
|
|
2248
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: rowText, children: [
|
|
2249
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: rowTitle, children: "\u5FEB\u6377\u6307\u4EE4\u6E05\u5355" }),
|
|
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" })
|
|
2251
|
+
] }),
|
|
2252
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2253
|
+
QuickPromptsEditor,
|
|
2254
|
+
{
|
|
2255
|
+
book,
|
|
2256
|
+
status: bookStatus,
|
|
2257
|
+
onSave: (next) => {
|
|
2258
|
+
actions.saveBook(next);
|
|
2259
|
+
},
|
|
2260
|
+
onReload: () => {
|
|
2261
|
+
actions.reloadBook();
|
|
2262
|
+
},
|
|
2263
|
+
onReset: () => {
|
|
2264
|
+
actions.resetBook();
|
|
2265
|
+
}
|
|
2266
|
+
}
|
|
2267
|
+
)
|
|
2268
|
+
] })
|
|
2269
|
+
] }),
|
|
1375
2270
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(FoldCard, { name: "\u8BBE\u7F6E\u9762\u677F", summary: panelSummary, children: [
|
|
1376
2271
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { style: bodyLead, children: "\u63D2\u4EF6\u88C5\u5F97\u591A\u65F6\u8BBE\u7F6E\u6761\u76EE\u5F88\u957F\uFF1A\u5F00\u542F\u300C\u5BFC\u822A\u53EF\u6EDA\u52A8\u300D\u540E\uFF0C\u5DE6\u4FA7\u5BFC\u822A\u5728\u6EA2\u51FA\u65F6\u4F1A\u51FA\u73B0\u6EDA\u52A8\u6761\u3002 \u5F00\u542F\u300C\u8FB9\u7F18\u8C03\u6574\u5927\u5C0F\u300D\u540E\uFF0C\u628A\u9F20\u6807\u79FB\u5230\u8BBE\u7F6E\u9762\u677F\u7684\u8FB9\u6216\u89D2\u4E0A\uFF08\u51FA\u73B0\u9AD8\u4EAE\u6216\u5149\u6807\u53D8\u5316\uFF09\u62D6\u52A8\u5373\u53EF\u6539\u53D8\u9762\u677F\u5927\u5C0F\uFF0C \u5C3A\u5BF8\u4F1A\u8BB0\u4F4F\uFF0C\u4E0B\u6B21\u6253\u5F00\u4FDD\u6301\u3002" }),
|
|
1377
2272
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
@@ -1505,6 +2400,288 @@ function SettingsSection({ useLive, actions }) {
|
|
|
1505
2400
|
] });
|
|
1506
2401
|
}
|
|
1507
2402
|
|
|
2403
|
+
// src/client/QuickCommandsButton.tsx
|
|
2404
|
+
var import_react4 = require("react");
|
|
2405
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
2406
|
+
function QuickCommandsButton({
|
|
2407
|
+
useInput,
|
|
2408
|
+
inputActions,
|
|
2409
|
+
sessionId,
|
|
2410
|
+
useLive,
|
|
2411
|
+
usePanel,
|
|
2412
|
+
actions
|
|
2413
|
+
}) {
|
|
2414
|
+
const settings = useLive((item) => item);
|
|
2415
|
+
const anchor = usePanel((item) => item);
|
|
2416
|
+
const draft = useInput((state2) => state2.draft);
|
|
2417
|
+
const ref = (0, import_react4.useRef)(null);
|
|
2418
|
+
(0, import_react4.useEffect)(() => {
|
|
2419
|
+
const sid = typeof sessionId === "string" ? sessionId : "";
|
|
2420
|
+
publishInputBridge({
|
|
2421
|
+
actions: inputActions ?? null,
|
|
2422
|
+
draft: typeof draft === "string" ? draft : "",
|
|
2423
|
+
sessionId: sid
|
|
2424
|
+
});
|
|
2425
|
+
return () => {
|
|
2426
|
+
releaseInputBridge(sid);
|
|
2427
|
+
};
|
|
2428
|
+
}, [inputActions, draft, sessionId]);
|
|
2429
|
+
if (settings.enabled !== true) return null;
|
|
2430
|
+
const open = anchor !== null;
|
|
2431
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
2432
|
+
"button",
|
|
2433
|
+
{
|
|
2434
|
+
ref,
|
|
2435
|
+
type: "button",
|
|
2436
|
+
className: QUICK_BUTTON_CLASS,
|
|
2437
|
+
"aria-haspopup": "dialog",
|
|
2438
|
+
"aria-expanded": open,
|
|
2439
|
+
title: "\u5FEB\u6377\u6307\u4EE4\uFF1A\u4E00\u952E\u63D2\u5165\u5E38\u7528\u63D0\u793A\u8BCD\uFF0C\u6216\u628A\u8F93\u5165\u6846\u91CC\u7684\u8BDD\u4F18\u5316\u6210\u4E00\u6761\u6E05\u6670\u7684\u6307\u4EE4",
|
|
2440
|
+
onMouseDown: (event) => {
|
|
2441
|
+
event.preventDefault();
|
|
2442
|
+
},
|
|
2443
|
+
onClick: () => {
|
|
2444
|
+
const rect = ref.current?.getBoundingClientRect();
|
|
2445
|
+
actions.toggle({
|
|
2446
|
+
left: rect?.left ?? 0,
|
|
2447
|
+
bottom: rect?.bottom ?? 0,
|
|
2448
|
+
width: rect?.width ?? 0
|
|
2449
|
+
});
|
|
2450
|
+
},
|
|
2451
|
+
children: [
|
|
2452
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2453
|
+
"svg",
|
|
2454
|
+
{
|
|
2455
|
+
viewBox: "0 0 16 16",
|
|
2456
|
+
width: "12",
|
|
2457
|
+
height: "12",
|
|
2458
|
+
"aria-hidden": true,
|
|
2459
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2460
|
+
"path",
|
|
2461
|
+
{
|
|
2462
|
+
d: "M9.2 1.2 3.4 9.1h3.5l-0.9 5.7 6-8.1H8.4l0.8-5.5Z",
|
|
2463
|
+
fill: "currentColor"
|
|
2464
|
+
}
|
|
2465
|
+
)
|
|
2466
|
+
}
|
|
2467
|
+
),
|
|
2468
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "\u5FEB\u6377\u6307\u4EE4" })
|
|
2469
|
+
]
|
|
2470
|
+
}
|
|
2471
|
+
);
|
|
2472
|
+
}
|
|
2473
|
+
|
|
2474
|
+
// src/client/QuickCommandsPanel.tsx
|
|
2475
|
+
var import_react5 = require("react");
|
|
2476
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
2477
|
+
var MARGIN = 8;
|
|
2478
|
+
var GAP = 8;
|
|
2479
|
+
function QuickCommandsPanel({
|
|
2480
|
+
useLive,
|
|
2481
|
+
usePanel,
|
|
2482
|
+
useBusy,
|
|
2483
|
+
useNotice,
|
|
2484
|
+
useBook,
|
|
2485
|
+
useBookStatus,
|
|
2486
|
+
actions
|
|
2487
|
+
}) {
|
|
2488
|
+
const settings = useLive((item) => item);
|
|
2489
|
+
const anchor = usePanel((item) => item);
|
|
2490
|
+
const busy = useBusy((item) => item);
|
|
2491
|
+
const notice = useNotice((item) => item);
|
|
2492
|
+
const book = useBook((item) => item);
|
|
2493
|
+
const status = useBookStatus((item) => item);
|
|
2494
|
+
const ref = (0, import_react5.useRef)(null);
|
|
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];
|
|
2500
|
+
(0, import_react5.useLayoutEffect)(() => {
|
|
2501
|
+
if (anchor === null) {
|
|
2502
|
+
setPosition(null);
|
|
2503
|
+
return;
|
|
2504
|
+
}
|
|
2505
|
+
const el = ref.current;
|
|
2506
|
+
const height = el === null ? 320 : el.getBoundingClientRect().height;
|
|
2507
|
+
const width = el === null ? 420 : el.getBoundingClientRect().width;
|
|
2508
|
+
const left = Math.max(MARGIN, Math.min(anchor.left, window.innerWidth - width - MARGIN));
|
|
2509
|
+
const above = anchor.bottom - height - GAP;
|
|
2510
|
+
const top = above >= MARGIN ? above : Math.min(anchor.bottom + GAP, window.innerHeight - height - MARGIN);
|
|
2511
|
+
setPosition({ left, top: Math.max(MARGIN, top) });
|
|
2512
|
+
}, [anchor?.left, anchor?.bottom, counts.prompts, categories.length, busy]);
|
|
2513
|
+
(0, import_react5.useEffect)(() => {
|
|
2514
|
+
if (anchor === null) return;
|
|
2515
|
+
const onPointerDown = (event) => {
|
|
2516
|
+
if (ref.current !== null && event.target instanceof Node && ref.current.contains(event.target)) return;
|
|
2517
|
+
if (event.target instanceof Element && event.target.closest(".composer-ux-quick-button") !== null) return;
|
|
2518
|
+
actions.close();
|
|
2519
|
+
};
|
|
2520
|
+
const onEscape = (event) => {
|
|
2521
|
+
if (event.key !== "Escape") return;
|
|
2522
|
+
event.preventDefault();
|
|
2523
|
+
event.stopPropagation();
|
|
2524
|
+
actions.close();
|
|
2525
|
+
};
|
|
2526
|
+
window.addEventListener("pointerdown", onPointerDown, true);
|
|
2527
|
+
window.addEventListener("keydown", onEscape, true);
|
|
2528
|
+
window.addEventListener("resize", actions.close);
|
|
2529
|
+
return () => {
|
|
2530
|
+
window.removeEventListener("pointerdown", onPointerDown, true);
|
|
2531
|
+
window.removeEventListener("keydown", onEscape, true);
|
|
2532
|
+
window.removeEventListener("resize", actions.close);
|
|
2533
|
+
};
|
|
2534
|
+
}, [anchor === null, actions]);
|
|
2535
|
+
if (anchor === null) return null;
|
|
2536
|
+
const tier = settings.optimizerTier;
|
|
2537
|
+
const items = active?.prompts ?? [];
|
|
2538
|
+
const failure = status !== "" && status !== "saving" ? status : "";
|
|
2539
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
2540
|
+
"div",
|
|
2541
|
+
{
|
|
2542
|
+
ref,
|
|
2543
|
+
role: "dialog",
|
|
2544
|
+
"aria-label": "\u5FEB\u6377\u6307\u4EE4",
|
|
2545
|
+
style: { ...quickPanel, left: position?.left ?? anchor.left, top: position?.top ?? anchor.bottom },
|
|
2546
|
+
children: [
|
|
2547
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: quickPanelHead, children: [
|
|
2548
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: quickPanelTitleRow, children: [
|
|
2549
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: quickPanelTitle, children: "\u5FEB\u6377\u6307\u4EE4" }),
|
|
2550
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: quickTierRow, role: "group", "aria-label": "\u4F18\u5316\u5F3A\u5EA6", children: OPTIMIZER_TIERS.map((item) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2551
|
+
"button",
|
|
2552
|
+
{
|
|
2553
|
+
type: "button",
|
|
2554
|
+
title: item.hint,
|
|
2555
|
+
"aria-pressed": tier === item.id,
|
|
2556
|
+
style: tier === item.id ? quickTierButtonActive : quickTierButton,
|
|
2557
|
+
onMouseDown: (event) => {
|
|
2558
|
+
event.preventDefault();
|
|
2559
|
+
},
|
|
2560
|
+
onClick: () => {
|
|
2561
|
+
actions.setTier(item.id);
|
|
2562
|
+
},
|
|
2563
|
+
children: item.label
|
|
2564
|
+
},
|
|
2565
|
+
item.id
|
|
2566
|
+
)) })
|
|
2567
|
+
] }),
|
|
2568
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
2569
|
+
"button",
|
|
2570
|
+
{
|
|
2571
|
+
type: "button",
|
|
2572
|
+
disabled: busy,
|
|
2573
|
+
title: "\u628A\u8F93\u5165\u6846\u91CC\u7684\u8BDD\u4EA4\u7ED9\u53E6\u4E00\u4E2A AI \u6574\u7406\u6210\u4E00\u6761\u53EF\u4EE5\u76F4\u63A5\u53D1\u51FA\u53BB\u7684\u6E05\u6670\u6307\u4EE4\uFF0C\u7ED3\u679C\u76F4\u63A5\u5199\u56DE\u8F93\u5165\u6846",
|
|
2574
|
+
style: busy ? quickPrimaryButtonDisabled : quickPrimaryButton,
|
|
2575
|
+
onMouseDown: (event) => {
|
|
2576
|
+
event.preventDefault();
|
|
2577
|
+
},
|
|
2578
|
+
onClick: () => {
|
|
2579
|
+
actions.optimize();
|
|
2580
|
+
},
|
|
2581
|
+
children: [
|
|
2582
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { "aria-hidden": true, children: "\u2728" }),
|
|
2583
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: busy ? "\u4F18\u5316\u4E2D\u2026" : "\u4F18\u5316\u63D0\u793A\u8BCD" })
|
|
2584
|
+
]
|
|
2585
|
+
}
|
|
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
|
+
] })
|
|
2622
|
+
] }),
|
|
2623
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: quickList, children: [
|
|
2624
|
+
items.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: quickEmpty, children: [
|
|
2625
|
+
"\u8FD9\u4E2A\u5206\u7C7B\u91CC\u8FD8\u6CA1\u6709\u6761\u76EE\u3002",
|
|
2626
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("br", {}),
|
|
2627
|
+
"\u5728\u300C\u8BBE\u7F6E \u2192 \u8F93\u5165\u4F53\u9A8C \u2192 \u5FEB\u6377\u6307\u4EE4\u6E05\u5355\u300D\u91CC\u6DFB\u52A0\u3002"
|
|
2628
|
+
] }),
|
|
2629
|
+
items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 4 }, children: [
|
|
2630
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
2631
|
+
"button",
|
|
2632
|
+
{
|
|
2633
|
+
type: "button",
|
|
2634
|
+
title: item.prompt,
|
|
2635
|
+
style: quickItem,
|
|
2636
|
+
onMouseDown: (event) => {
|
|
2637
|
+
event.preventDefault();
|
|
2638
|
+
},
|
|
2639
|
+
onClick: () => {
|
|
2640
|
+
actions.insert(item.prompt);
|
|
2641
|
+
},
|
|
2642
|
+
children: [
|
|
2643
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: quickItemLabel, children: item.label }),
|
|
2644
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: quickItemPreview, children: item.prompt.replace(/\s+/g, " ") })
|
|
2645
|
+
]
|
|
2646
|
+
}
|
|
2647
|
+
),
|
|
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: [
|
|
2649
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2650
|
+
"input",
|
|
2651
|
+
{
|
|
2652
|
+
type: "checkbox",
|
|
2653
|
+
style: quickAlwaysBox,
|
|
2654
|
+
checked: item.always,
|
|
2655
|
+
onChange: (event) => {
|
|
2656
|
+
actions.setAlways(item.id, event.target.checked);
|
|
2657
|
+
}
|
|
2658
|
+
}
|
|
2659
|
+
),
|
|
2660
|
+
"\u9ED8\u8BA4\u63D2\u5165"
|
|
2661
|
+
] })
|
|
2662
|
+
] }, item.id))
|
|
2663
|
+
] }),
|
|
2664
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: quickPanelFoot, children: [
|
|
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
|
+
)
|
|
2679
|
+
] })
|
|
2680
|
+
]
|
|
2681
|
+
}
|
|
2682
|
+
);
|
|
2683
|
+
}
|
|
2684
|
+
|
|
1508
2685
|
// src/client.tsx
|
|
1509
2686
|
var name = "composer-ux";
|
|
1510
2687
|
var inject = ["slots", "settingsScope"];
|
|
@@ -1513,6 +2690,9 @@ function apply(ctx) {
|
|
|
1513
2690
|
const scope = ctx.settingsScope.bind({ namespace: NAMESPACE });
|
|
1514
2691
|
const live = (0, import_dsh_client_store.createSnapshotStore)({ ...DEFAULT_SETTINGS });
|
|
1515
2692
|
const menu2 = (0, import_dsh_client_store.createSnapshotStore)(null);
|
|
2693
|
+
const panel = (0, import_dsh_client_store.createSnapshotStore)(null);
|
|
2694
|
+
const optimizing = (0, import_dsh_client_store.createSnapshotStore)(false);
|
|
2695
|
+
const panelNotice = (0, import_dsh_client_store.createSnapshotStore)("");
|
|
1516
2696
|
const sync = () => {
|
|
1517
2697
|
const snapshot = scope.getSnapshot();
|
|
1518
2698
|
live.set(snapshot.status === "ready" && snapshot.value !== void 0 ? { ...DEFAULT_SETTINGS, ...sanitizeSettings(snapshot.value) } : { ...DEFAULT_SETTINGS });
|
|
@@ -1529,6 +2709,73 @@ function apply(ctx) {
|
|
|
1529
2709
|
console.error("[composer-ux] settings clear failed", error);
|
|
1530
2710
|
});
|
|
1531
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
|
+
};
|
|
1532
2779
|
const resetAll = () => {
|
|
1533
2780
|
void scope.mutate(
|
|
1534
2781
|
[
|
|
@@ -1544,11 +2791,79 @@ function apply(ctx) {
|
|
|
1544
2791
|
HEADER_ENABLED_FIELD,
|
|
1545
2792
|
HEADER_NAME_FIELD,
|
|
1546
2793
|
HEADER_VALUE_FIELD,
|
|
1547
|
-
HEADER_ROUTES_FIELD
|
|
2794
|
+
HEADER_ROUTES_FIELD,
|
|
2795
|
+
OPTIMIZER_TIER_FIELD
|
|
1548
2796
|
].map((field) => ({ op: "unset", path: [field] }))
|
|
1549
2797
|
).catch((error) => {
|
|
1550
2798
|
console.error("[composer-ux] settings reset failed", error);
|
|
1551
2799
|
});
|
|
2800
|
+
bookActions.resetBook();
|
|
2801
|
+
};
|
|
2802
|
+
let noticeTimer;
|
|
2803
|
+
const note = (message, ms = 4500) => {
|
|
2804
|
+
panelNotice.set(message);
|
|
2805
|
+
if (noticeTimer !== void 0) clearTimeout(noticeTimer);
|
|
2806
|
+
if (message === "") return;
|
|
2807
|
+
noticeTimer = setTimeout(() => {
|
|
2808
|
+
panelNotice.set("");
|
|
2809
|
+
}, ms);
|
|
2810
|
+
};
|
|
2811
|
+
ctx.effect(() => () => {
|
|
2812
|
+
if (noticeTimer !== void 0) clearTimeout(noticeTimer);
|
|
2813
|
+
}, "composer-ux: quick notice timer");
|
|
2814
|
+
const quickActions = {
|
|
2815
|
+
toggle: (anchor) => {
|
|
2816
|
+
if (panel.getSnapshot() !== null) {
|
|
2817
|
+
panel.set(null);
|
|
2818
|
+
panelNotice.set("");
|
|
2819
|
+
return;
|
|
2820
|
+
}
|
|
2821
|
+
panelNotice.set("");
|
|
2822
|
+
panel.set(anchor);
|
|
2823
|
+
},
|
|
2824
|
+
close: () => {
|
|
2825
|
+
panel.set(null);
|
|
2826
|
+
panelNotice.set("");
|
|
2827
|
+
},
|
|
2828
|
+
insert: (text) => {
|
|
2829
|
+
if (insertIntoDraft(text)) focusComposer();
|
|
2830
|
+
},
|
|
2831
|
+
optimize: () => {
|
|
2832
|
+
if (optimizing.getSnapshot()) return;
|
|
2833
|
+
const draft = currentDraft();
|
|
2834
|
+
if (draft.trim() === "") {
|
|
2835
|
+
note("\u8F93\u5165\u6846\u662F\u7A7A\u7684\uFF1A\u5148\u5199\u70B9\u4EC0\u4E48\uFF0C\u518D\u70B9\u4F18\u5316");
|
|
2836
|
+
return;
|
|
2837
|
+
}
|
|
2838
|
+
optimizing.set(true);
|
|
2839
|
+
note("\u6B63\u5728\u4F18\u5316\u2026");
|
|
2840
|
+
void optimizeDraft(draft, live.getSnapshot().optimizerTier).then(
|
|
2841
|
+
(result) => {
|
|
2842
|
+
optimizing.set(false);
|
|
2843
|
+
if (!result.ok) {
|
|
2844
|
+
note(`\u4F18\u5316\u5931\u8D25\uFF1A${result.error ?? "\u672A\u77E5\u539F\u56E0"}`);
|
|
2845
|
+
return;
|
|
2846
|
+
}
|
|
2847
|
+
replaceDraft(result.text ?? "");
|
|
2848
|
+
focusComposer();
|
|
2849
|
+
note(`\u5DF2\u5199\u56DE\u8F93\u5165\u6846\uFF08${result.route}\uFF09\xB7 Ctrl+Z \u53EF\u8FD8\u539F`);
|
|
2850
|
+
},
|
|
2851
|
+
(error) => {
|
|
2852
|
+
optimizing.set(false);
|
|
2853
|
+
note(`\u4F18\u5316\u5931\u8D25\uFF1A${error instanceof Error ? error.message : String(error)}`);
|
|
2854
|
+
}
|
|
2855
|
+
);
|
|
2856
|
+
},
|
|
2857
|
+
setTier: (tier) => {
|
|
2858
|
+
setField(OPTIMIZER_TIER_FIELD, tier);
|
|
2859
|
+
},
|
|
2860
|
+
/**
|
|
2861
|
+
* 「默认插入」勾选:按 id 跨分类找那一条,直接写盘。
|
|
2862
|
+
* 这个标记就是「点发送时自动附加到消息末尾」的依据(见 interceptors.ts)。
|
|
2863
|
+
*/
|
|
2864
|
+
setAlways: (id, value) => {
|
|
2865
|
+
commitBook(withAlwaysToggled(book.getSnapshot(), id, value));
|
|
2866
|
+
}
|
|
1552
2867
|
};
|
|
1553
2868
|
slots.inject("settings.section", () => slots.register({
|
|
1554
2869
|
name: "settings.section",
|
|
@@ -1556,8 +2871,15 @@ function apply(ctx) {
|
|
|
1556
2871
|
order: 40,
|
|
1557
2872
|
label: "\u8F93\u5165\u4F53\u9A8C",
|
|
1558
2873
|
inject: () => ({
|
|
1559
|
-
hooks: { live },
|
|
1560
|
-
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
|
+
}
|
|
1561
2883
|
})
|
|
1562
2884
|
}, SettingsSection));
|
|
1563
2885
|
slots.inject("shell.overlay", () => slots.register({
|
|
@@ -1583,7 +2905,39 @@ function apply(ctx) {
|
|
|
1583
2905
|
id: "composer-ux-panel-resize",
|
|
1584
2906
|
inject: () => ({ hooks: { live }, actions: { setField } })
|
|
1585
2907
|
}, PanelResizeHandles));
|
|
2908
|
+
slots.inject("conversation.input.right", () => slots.register({
|
|
2909
|
+
name: "conversation.input.right",
|
|
2910
|
+
id: "composer-ux-quick",
|
|
2911
|
+
order: 89,
|
|
2912
|
+
label: "\u5FEB\u6377\u6307\u4EE4",
|
|
2913
|
+
inject: () => ({
|
|
2914
|
+
hooks: { live, panel },
|
|
2915
|
+
actions: { toggle: quickActions.toggle }
|
|
2916
|
+
})
|
|
2917
|
+
}, QuickCommandsButton));
|
|
2918
|
+
slots.inject("shell.overlay", () => slots.register({
|
|
2919
|
+
name: "shell.overlay",
|
|
2920
|
+
id: "composer-ux-quick-panel",
|
|
2921
|
+
inject: () => ({
|
|
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
|
+
}
|
|
2937
|
+
})
|
|
2938
|
+
}, QuickCommandsPanel));
|
|
1586
2939
|
ctx.effect(() => installSettingsCardStyle(), "composer-ux: settings card style");
|
|
2940
|
+
ctx.effect(() => installQuickButtonStyle(), "composer-ux: quick button style");
|
|
1587
2941
|
ctx.effect(
|
|
1588
2942
|
() => installPanelStyle(
|
|
1589
2943
|
() => {
|
|
@@ -1601,8 +2955,9 @@ function apply(ctx) {
|
|
|
1601
2955
|
if (enabled && dispose === null) {
|
|
1602
2956
|
dispose = installInterceptors({
|
|
1603
2957
|
settings: () => live.getSnapshot(),
|
|
1604
|
-
|
|
1605
|
-
|
|
2958
|
+
alwaysPrompts: () => alwaysQuickPrompts(book.getSnapshot()),
|
|
2959
|
+
setMenu: (state2) => {
|
|
2960
|
+
menu2.set(state2);
|
|
1606
2961
|
},
|
|
1607
2962
|
menuOpen: () => menu2.getSnapshot() !== null
|
|
1608
2963
|
});
|
|
@@ -1610,8 +2965,10 @@ function apply(ctx) {
|
|
|
1610
2965
|
dispose?.();
|
|
1611
2966
|
dispose = null;
|
|
1612
2967
|
menu2.set(null);
|
|
2968
|
+
panel.set(null);
|
|
1613
2969
|
}
|
|
1614
2970
|
if (live.getSnapshot().menuNative) menu2.set(null);
|
|
2971
|
+
if (!live.getSnapshot().enabled) panel.set(null);
|
|
1615
2972
|
};
|
|
1616
2973
|
syncInterceptors();
|
|
1617
2974
|
const unsubscribe = live.subscribe(syncInterceptors);
|