dsh-image-gen 0.9.2 → 0.10.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/README.en.md +454 -452
- package/README.md +454 -452
- package/lib/client.js +984 -366
- package/lib/index.js +506 -194
- package/lib/types/client/conversation-image-revisions.d.ts +1 -0
- package/lib/types/client/conversation-regenerate.d.ts +1 -0
- package/lib/types/client/gallery-store.d.ts +1 -0
- package/lib/types/client/image-result-node.d.ts +1 -0
- package/lib/types/client/index.d.ts +8 -2
- package/lib/types/client/multi-model-compare.d.ts +3 -3
- package/lib/types/client/provider-pill.d.ts +9 -3
- package/lib/types/config.d.ts +15 -4
- package/lib/types/credentials.d.ts +2 -2
- package/lib/types/generation-timeout.d.ts +5 -0
- package/lib/types/image-tool-context.d.ts +3 -0
- package/lib/types/openai-compatible.d.ts +1 -1
- package/lib/types/shared.d.ts +57 -0
- package/lib/types/studio-route.d.ts +1 -0
- package/lib/types/studio.d.ts +1 -1
- package/lib/types/test-route.d.ts +3 -3
- package/package.json +139 -139
- package/skills/install-dsh-image-gen/SKILL.md +22 -22
package/lib/client.js
CHANGED
|
@@ -75,7 +75,7 @@ window.__ModuleLoader__.load({
|
|
|
75
75
|
//#region lib/types/watermark.js
|
|
76
76
|
/** Model names alone do not establish the protocol of an unknown relay. */
|
|
77
77
|
function officialContract(config, mode) {
|
|
78
|
-
const model = (mode === "generate" ? config.openaiCompatExtraBody : config.openaiCompatEditExtra)?.model ?? config.openaiCompatModel;
|
|
78
|
+
const model = (mode === "generate" ? config.openaiCompatExtraBody : config.openaiCompatEditExtra)?.model ?? (mode === "edit" ? config.openaiCompatEditModel?.trim() || config.openaiCompatModel : config.openaiCompatModel);
|
|
79
79
|
if (typeof model !== "string") return void 0;
|
|
80
80
|
try {
|
|
81
81
|
const url = new URL(config.openaiCompatBaseURL ?? "");
|
|
@@ -87,6 +87,10 @@ window.__ModuleLoader__.load({
|
|
|
87
87
|
}
|
|
88
88
|
/** Known official edit contracts take precedence over relay-specific format settings. */
|
|
89
89
|
function compatEditFormat(config) {
|
|
90
|
+
try {
|
|
91
|
+
const url = new URL(config.openaiCompatBaseURL ?? "");
|
|
92
|
+
if (url.protocol === "https:" && !url.port && !url.search && !url.hash && (url.hostname === "api.siliconflow.cn" || url.hostname === "api.siliconflow.com") && url.pathname.replace(/\/+$/, "") === "/v1") return "siliconflowJson";
|
|
93
|
+
} catch {}
|
|
90
94
|
const contract = officialContract(config, "edit");
|
|
91
95
|
if (contract === "sensenova") return "jsonImageUrlArray";
|
|
92
96
|
if (contract === "qwen") return "qwenJson";
|
|
@@ -156,17 +160,101 @@ window.__ModuleLoader__.load({
|
|
|
156
160
|
"xai",
|
|
157
161
|
"zhipu"
|
|
158
162
|
];
|
|
163
|
+
/** Normalize the relay model list while keeping the legacy default model selectable. */
|
|
164
|
+
function resolveOpenAICompatModels(config) {
|
|
165
|
+
const defaultModel = config.openaiCompatModel?.trim() ?? "";
|
|
166
|
+
const models = [...new Set((config.openaiCompatModels ?? []).map((model) => model.trim()).filter(Boolean))];
|
|
167
|
+
if (defaultModel.length > 0 && !models.includes(defaultModel)) models.unshift(defaultModel);
|
|
168
|
+
return models;
|
|
169
|
+
}
|
|
170
|
+
const DEFAULT_OPENAI_COMPAT_CHANNEL_ID = "default";
|
|
171
|
+
function openAICompatKeyRef(channelId) {
|
|
172
|
+
return channelId === "default" ? OPENAI_COMPAT_API_KEY_ENV : `${OPENAI_COMPAT_API_KEY_ENV}_${channelId.replace(/[^A-Za-z0-9]/g, "_").toUpperCase()}`;
|
|
173
|
+
}
|
|
174
|
+
/** The legacy flat fields remain the first channel; additional entries are fully independent. */
|
|
175
|
+
function resolveOpenAICompatChannels(source) {
|
|
176
|
+
const legacy = {
|
|
177
|
+
id: DEFAULT_OPENAI_COMPAT_CHANNEL_ID,
|
|
178
|
+
label: source.openaiCompatLabel?.trim() || "OpenAI 兼容",
|
|
179
|
+
keyRef: OPENAI_COMPAT_API_KEY_ENV,
|
|
180
|
+
baseURL: source.openaiCompatBaseURL ?? "",
|
|
181
|
+
model: source.openaiCompatModel ?? "",
|
|
182
|
+
models: [...source.openaiCompatModels ?? []],
|
|
183
|
+
editModel: source.openaiCompatEditModel ?? "",
|
|
184
|
+
quality: source.openaiCompatQuality ?? "",
|
|
185
|
+
qualityOptions: [...source.openaiCompatQualityOptions ?? []],
|
|
186
|
+
extraBody: source.openaiCompatExtraBody ?? {},
|
|
187
|
+
editSizeMode: source.openaiCompatEditSizeMode ?? "auto",
|
|
188
|
+
editFormat: source.openaiCompatEditFormat ?? "multipart",
|
|
189
|
+
editExtra: source.openaiCompatEditExtra ?? {},
|
|
190
|
+
sizes: source.openaiCompatSizes ?? {}
|
|
191
|
+
};
|
|
192
|
+
const channels = [legacy];
|
|
193
|
+
const seen = /* @__PURE__ */ new Set([legacy.id]);
|
|
194
|
+
for (const [index, entry] of (source.openaiCompatChannels ?? []).entries()) {
|
|
195
|
+
const id = typeof entry?.id === "string" ? entry.id.trim() : "";
|
|
196
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/.test(id) || seen.has(id)) continue;
|
|
197
|
+
seen.add(id);
|
|
198
|
+
const storedKeyRef = typeof entry.keyRef === "string" ? entry.keyRef.trim() : "";
|
|
199
|
+
channels.push({
|
|
200
|
+
id,
|
|
201
|
+
label: typeof entry.label === "string" && entry.label.trim().length > 0 ? entry.label.trim() : `OpenAI 兼容 ${index + 2}`,
|
|
202
|
+
keyRef: /^DSH_IMAGE_GEN_OPENAI_COMPAT_KEY_[A-Z0-9_]+$/.test(storedKeyRef) ? storedKeyRef : openAICompatKeyRef(id),
|
|
203
|
+
baseURL: typeof entry.baseURL === "string" ? entry.baseURL : "",
|
|
204
|
+
model: typeof entry.model === "string" ? entry.model : "",
|
|
205
|
+
models: Array.isArray(entry.models) ? entry.models.filter((model) => typeof model === "string") : [],
|
|
206
|
+
editModel: typeof entry.editModel === "string" ? entry.editModel : "",
|
|
207
|
+
quality: typeof entry.quality === "string" ? entry.quality : "",
|
|
208
|
+
qualityOptions: Array.isArray(entry.qualityOptions) ? entry.qualityOptions.filter((quality) => typeof quality === "string") : [],
|
|
209
|
+
extraBody: entry.extraBody ?? {},
|
|
210
|
+
editSizeMode: entry.editSizeMode === "selected" ? "selected" : "auto",
|
|
211
|
+
editFormat: entry.editFormat ?? "multipart",
|
|
212
|
+
editExtra: entry.editExtra ?? {},
|
|
213
|
+
sizes: entry.sizes ?? {}
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
return channels;
|
|
217
|
+
}
|
|
218
|
+
function resolveOpenAICompatChannel(source, channelId) {
|
|
219
|
+
const channels = resolveOpenAICompatChannels(source);
|
|
220
|
+
const explicit = channelId?.trim() ?? "";
|
|
221
|
+
if (explicit.length > 0) {
|
|
222
|
+
const selected = channels.find((channel) => channel.id === explicit);
|
|
223
|
+
if (selected === void 0) throw new Error(`Unknown OpenAI-compatible channel "${explicit}". Available channels: ${channels.map((channel) => channel.id).join(", ")}.`);
|
|
224
|
+
return selected;
|
|
225
|
+
}
|
|
226
|
+
const active = source.openaiCompatActiveChannel?.trim() ?? "";
|
|
227
|
+
return channels.find((channel) => channel.id === active) ?? channels[0];
|
|
228
|
+
}
|
|
159
229
|
/**
|
|
160
230
|
* Providers the browser workbench can drive: the BYOK cloud set plus the
|
|
161
231
|
* logged-in subscription channels. ComfyUI stays out; it has its own workflow
|
|
162
232
|
* pipeline and no shared request shape.
|
|
163
233
|
*/
|
|
164
234
|
const STUDIO_PROVIDERS = [...CLOUD_IMAGE_PROVIDERS, ...SUBSCRIPTION_PROVIDERS];
|
|
235
|
+
function studioTargetKey(provider, channel) {
|
|
236
|
+
return channel === void 0 ? provider : `${provider}:${channel}`;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Credential references resolved through the DSH Credentials service (BYOK).
|
|
240
|
+
* These are POSIX-style reference names, not environment variables: the host
|
|
241
|
+
* layers the process environment and its managed store behind them, so a name
|
|
242
|
+
* like OPENAI_API_KEY is shared with any other plugin resolving the same ref.
|
|
243
|
+
*/
|
|
244
|
+
const GOOGLE_API_KEY_ENV = "GEMINI_API_KEY";
|
|
245
|
+
/** OpenAI Platform credential reference. */
|
|
246
|
+
const OPENAI_API_KEY_ENV = "OPENAI_API_KEY";
|
|
247
|
+
/**
|
|
248
|
+
* OpenAI-compatible relay credential reference. Deliberately distinct from
|
|
249
|
+
* OPENAI_API_KEY so an official key and a relay key can coexist without
|
|
250
|
+
* overwriting each other.
|
|
251
|
+
*/
|
|
252
|
+
const OPENAI_COMPAT_API_KEY_ENV = "DSH_IMAGE_GEN_OPENAI_COMPAT_KEY";
|
|
165
253
|
/** The credential reference each cloud provider's API key is stored under. */
|
|
166
254
|
const CLOUD_CREDENTIAL_REFS = {
|
|
167
|
-
google:
|
|
168
|
-
openai:
|
|
169
|
-
"openai-compat":
|
|
255
|
+
google: GOOGLE_API_KEY_ENV,
|
|
256
|
+
openai: OPENAI_API_KEY_ENV,
|
|
257
|
+
"openai-compat": OPENAI_COMPAT_API_KEY_ENV,
|
|
170
258
|
seedream: "ARK_API_KEY",
|
|
171
259
|
dashscope: "DASHSCOPE_API_KEY",
|
|
172
260
|
xai: "XAI_API_KEY",
|
|
@@ -181,6 +269,20 @@ window.__ModuleLoader__.load({
|
|
|
181
269
|
"off",
|
|
182
270
|
"on"
|
|
183
271
|
];
|
|
272
|
+
/** A model picker/request must use the same operation-specific default. */
|
|
273
|
+
function studioModelForMode(profile, mode) {
|
|
274
|
+
return mode === "edit" ? profile.editModel ?? profile.model : profile.model;
|
|
275
|
+
}
|
|
276
|
+
function studioModelOptionsForMode(profile, mode) {
|
|
277
|
+
if (mode === "edit" && profile.editModel !== void 0) return [{
|
|
278
|
+
value: profile.editModel,
|
|
279
|
+
label: profile.editModel
|
|
280
|
+
}];
|
|
281
|
+
return profile.modelOptions ?? [{
|
|
282
|
+
value: profile.model,
|
|
283
|
+
label: profile.model
|
|
284
|
+
}];
|
|
285
|
+
}
|
|
184
286
|
function studioWatermarkCapability(profile, mode) {
|
|
185
287
|
return profile?.watermarkCapabilities?.[mode] ?? (mode === "generate" && profile?.watermarkOptions?.length ? { status: "supported" } : {
|
|
186
288
|
status: "unknown",
|
|
@@ -2096,9 +2198,9 @@ window.__ModuleLoader__.load({
|
|
|
2096
2198
|
//#endregion
|
|
2097
2199
|
//#region lib/types/client/multi-model-compare.js
|
|
2098
2200
|
/** Map one shared output intent to settings accepted by every target model. */
|
|
2099
|
-
function buildComparisonTargets(profiles,
|
|
2100
|
-
const selected = new Set(
|
|
2101
|
-
return profiles.filter((profile) => profile.configured && selected.has(profile.provider)).map((profile) => {
|
|
2201
|
+
function buildComparisonTargets(profiles, selectedTargets, ratio, quality, output) {
|
|
2202
|
+
const selected = new Set(selectedTargets);
|
|
2203
|
+
return profiles.filter((profile) => profile.configured && selected.has(studioTargetKey(profile.provider, profile.channel))).map((profile) => {
|
|
2102
2204
|
const targetRatio = profile.ratioOptions.some((option) => option.value === ratio) ? ratio : profile.defaultRatio;
|
|
2103
2205
|
const generationOptions = generationQualityOptions(profile);
|
|
2104
2206
|
const qualityIntent = output === void 0 ? quality : profile.provider === "openai" || profile.provider === "chatgpt-sub" || profile.provider === "zhipu" ? output.generationQuality : output.resolution;
|
|
@@ -2137,10 +2239,11 @@ window.__ModuleLoader__.load({
|
|
|
2137
2239
|
return [...options.values()];
|
|
2138
2240
|
}
|
|
2139
2241
|
/** Start with two models, not every configured API, to avoid surprise spend. */
|
|
2140
|
-
function initialComparisonProviders(profiles, activeProvider) {
|
|
2242
|
+
function initialComparisonProviders(profiles, activeProvider, activeChannel) {
|
|
2141
2243
|
const configured = profiles.filter((profile) => profile.configured);
|
|
2142
|
-
const active = configured.find((profile) => profile.provider === activeProvider);
|
|
2143
|
-
|
|
2244
|
+
const active = configured.find((profile) => studioTargetKey(profile.provider, profile.channel) === studioTargetKey(activeProvider, activeChannel)) ?? configured.find((profile) => profile.provider === activeProvider);
|
|
2245
|
+
const activeKey = active === void 0 ? void 0 : studioTargetKey(active.provider, active.channel);
|
|
2246
|
+
return (active === void 0 ? configured : [active, ...configured.filter((profile) => studioTargetKey(profile.provider, profile.channel) !== activeKey)]).slice(0, 2).map((profile) => studioTargetKey(profile.provider, profile.channel));
|
|
2144
2247
|
}
|
|
2145
2248
|
const RATIO_SORT_ORDER = [
|
|
2146
2249
|
"auto",
|
|
@@ -49149,7 +49252,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
49149
49252
|
should not mutate them or their content. Rather, you create new
|
|
49150
49253
|
instances whenever needed. The API tries to make this easy.
|
|
49151
49254
|
*/
|
|
49152
|
-
var Fragment$
|
|
49255
|
+
var Fragment$48 = class Fragment$48 {
|
|
49153
49256
|
/**
|
|
49154
49257
|
@internal
|
|
49155
49258
|
*/
|
|
@@ -49210,7 +49313,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
49210
49313
|
i = 1;
|
|
49211
49314
|
}
|
|
49212
49315
|
for (; i < other.content.length; i++) content.push(other.content[i]);
|
|
49213
|
-
return new Fragment$
|
|
49316
|
+
return new Fragment$48(content, this.size + other.size);
|
|
49214
49317
|
}
|
|
49215
49318
|
/**
|
|
49216
49319
|
Cut out the sub-fragment between the two given positions.
|
|
@@ -49230,15 +49333,15 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
49230
49333
|
}
|
|
49231
49334
|
pos = end;
|
|
49232
49335
|
}
|
|
49233
|
-
return new Fragment$
|
|
49336
|
+
return new Fragment$48(result, size);
|
|
49234
49337
|
}
|
|
49235
49338
|
/**
|
|
49236
49339
|
@internal
|
|
49237
49340
|
*/
|
|
49238
49341
|
cutByIndex(from, to) {
|
|
49239
|
-
if (from == to) return Fragment$
|
|
49342
|
+
if (from == to) return Fragment$48.empty;
|
|
49240
49343
|
if (from == 0 && to == this.content.length) return this;
|
|
49241
|
-
return new Fragment$
|
|
49344
|
+
return new Fragment$48(this.content.slice(from, to));
|
|
49242
49345
|
}
|
|
49243
49346
|
/**
|
|
49244
49347
|
Create a new fragment in which the node at the given index is
|
|
@@ -49250,21 +49353,21 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
49250
49353
|
let copy = this.content.slice();
|
|
49251
49354
|
let size = this.size + node.nodeSize - current.nodeSize;
|
|
49252
49355
|
copy[index] = node;
|
|
49253
|
-
return new Fragment$
|
|
49356
|
+
return new Fragment$48(copy, size);
|
|
49254
49357
|
}
|
|
49255
49358
|
/**
|
|
49256
49359
|
Create a new fragment by prepending the given node to this
|
|
49257
49360
|
fragment.
|
|
49258
49361
|
*/
|
|
49259
49362
|
addToStart(node) {
|
|
49260
|
-
return new Fragment$
|
|
49363
|
+
return new Fragment$48([node].concat(this.content), this.size + node.nodeSize);
|
|
49261
49364
|
}
|
|
49262
49365
|
/**
|
|
49263
49366
|
Create a new fragment by appending the given node to this
|
|
49264
49367
|
fragment.
|
|
49265
49368
|
*/
|
|
49266
49369
|
addToEnd(node) {
|
|
49267
|
-
return new Fragment$
|
|
49370
|
+
return new Fragment$48(this.content.concat(node), this.size + node.nodeSize);
|
|
49268
49371
|
}
|
|
49269
49372
|
/**
|
|
49270
49373
|
Compare this fragment to another one.
|
|
@@ -49374,16 +49477,16 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
49374
49477
|
Deserialize a fragment from its JSON representation.
|
|
49375
49478
|
*/
|
|
49376
49479
|
static fromJSON(schema, value) {
|
|
49377
|
-
if (!value) return Fragment$
|
|
49480
|
+
if (!value) return Fragment$48.empty;
|
|
49378
49481
|
if (!Array.isArray(value)) throw new RangeError("Invalid input for Fragment.fromJSON");
|
|
49379
|
-
return Fragment$
|
|
49482
|
+
return Fragment$48.fromArray(value.map(schema.nodeFromJSON));
|
|
49380
49483
|
}
|
|
49381
49484
|
/**
|
|
49382
49485
|
Build a fragment from an array of nodes. Ensures that adjacent
|
|
49383
49486
|
text nodes with the same marks are joined together.
|
|
49384
49487
|
*/
|
|
49385
49488
|
static fromArray(array) {
|
|
49386
|
-
if (!array.length) return Fragment$
|
|
49489
|
+
if (!array.length) return Fragment$48.empty;
|
|
49387
49490
|
let joined, size = 0;
|
|
49388
49491
|
for (let i = 0; i < array.length; i++) {
|
|
49389
49492
|
let node = array[i];
|
|
@@ -49393,7 +49496,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
49393
49496
|
joined[joined.length - 1] = node.withText(joined[joined.length - 1].text + node.text);
|
|
49394
49497
|
} else if (joined) joined.push(node);
|
|
49395
49498
|
}
|
|
49396
|
-
return new Fragment$
|
|
49499
|
+
return new Fragment$48(joined || array, size);
|
|
49397
49500
|
}
|
|
49398
49501
|
/**
|
|
49399
49502
|
Create a fragment from something that can be interpreted as a
|
|
@@ -49402,10 +49505,10 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
49402
49505
|
fragment containing those nodes.
|
|
49403
49506
|
*/
|
|
49404
49507
|
static from(nodes) {
|
|
49405
|
-
if (!nodes) return Fragment$
|
|
49406
|
-
if (nodes instanceof Fragment$
|
|
49508
|
+
if (!nodes) return Fragment$48.empty;
|
|
49509
|
+
if (nodes instanceof Fragment$48) return nodes;
|
|
49407
49510
|
if (Array.isArray(nodes)) return this.fromArray(nodes);
|
|
49408
|
-
if (nodes.attrs) return new Fragment$
|
|
49511
|
+
if (nodes.attrs) return new Fragment$48([nodes], nodes.nodeSize);
|
|
49409
49512
|
throw new RangeError("Can not convert " + nodes + " to a Fragment" + (nodes.nodesBetween ? " (looks like multiple versions of prosemirror-model were loaded)" : ""));
|
|
49410
49513
|
}
|
|
49411
49514
|
};
|
|
@@ -49414,7 +49517,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
49414
49517
|
contain anything (rather than allocating a new empty fragment for
|
|
49415
49518
|
each leaf node).
|
|
49416
49519
|
*/
|
|
49417
|
-
Fragment$
|
|
49520
|
+
Fragment$48.empty = new Fragment$48([], 0);
|
|
49418
49521
|
const found = {
|
|
49419
49522
|
index: 0,
|
|
49420
49523
|
offset: 0
|
|
@@ -49627,7 +49730,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
49627
49730
|
if (!json) return Slice.empty;
|
|
49628
49731
|
let openStart = json.openStart || 0, openEnd = json.openEnd || 0;
|
|
49629
49732
|
if (typeof openStart != "number" || typeof openEnd != "number") throw new RangeError("Invalid input for Slice.fromJSON");
|
|
49630
|
-
return new Slice(Fragment$
|
|
49733
|
+
return new Slice(Fragment$48.fromJSON(schema, json.content), openStart, openEnd);
|
|
49631
49734
|
}
|
|
49632
49735
|
/**
|
|
49633
49736
|
Create a slice from a fragment by taking the maximum possible
|
|
@@ -49643,7 +49746,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
49643
49746
|
/**
|
|
49644
49747
|
The empty slice.
|
|
49645
49748
|
*/
|
|
49646
|
-
Slice.empty = new Slice(Fragment$
|
|
49749
|
+
Slice.empty = new Slice(Fragment$48.empty, 0, 0);
|
|
49647
49750
|
function removeRange(content, from, to) {
|
|
49648
49751
|
let { index, offset } = content.findIndex(from), child = content.maybeChild(index);
|
|
49649
49752
|
let { index: indexTo, offset: offsetTo } = content.findIndex(to);
|
|
@@ -49727,19 +49830,19 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
49727
49830
|
if (openEnd) addNode(close(openEnd, replaceTwoWay($end, $to, depth + 1)), content);
|
|
49728
49831
|
}
|
|
49729
49832
|
addRange($to, null, depth, content);
|
|
49730
|
-
return new Fragment$
|
|
49833
|
+
return new Fragment$48(content);
|
|
49731
49834
|
}
|
|
49732
49835
|
function replaceTwoWay($from, $to, depth) {
|
|
49733
49836
|
let content = [];
|
|
49734
49837
|
addRange(null, $from, depth, content);
|
|
49735
49838
|
if ($from.depth > depth) addNode(close(joinable$1($from, $to, depth + 1), replaceTwoWay($from, $to, depth + 1)), content);
|
|
49736
49839
|
addRange($to, null, depth, content);
|
|
49737
|
-
return new Fragment$
|
|
49840
|
+
return new Fragment$48(content);
|
|
49738
49841
|
}
|
|
49739
49842
|
function prepareSliceForReplace(slice, $along) {
|
|
49740
49843
|
let extra = $along.depth - slice.openStart;
|
|
49741
49844
|
let node = $along.node(extra).copy(slice.content);
|
|
49742
|
-
for (let i = extra - 1; i >= 0; i--) node = $along.node(i).copy(Fragment$
|
|
49845
|
+
for (let i = extra - 1; i >= 0; i--) node = $along.node(i).copy(Fragment$48.from(node));
|
|
49743
49846
|
return {
|
|
49744
49847
|
start: node.resolveNoCache(slice.openStart + extra),
|
|
49745
49848
|
end: node.resolveNoCache(node.content.size - slice.openEnd - extra)
|
|
@@ -50079,7 +50182,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
50079
50182
|
this.type = type;
|
|
50080
50183
|
this.attrs = attrs;
|
|
50081
50184
|
this.marks = marks;
|
|
50082
|
-
this.content = content || Fragment$
|
|
50185
|
+
this.content = content || Fragment$48.empty;
|
|
50083
50186
|
}
|
|
50084
50187
|
/**
|
|
50085
50188
|
The array of this node's child nodes.
|
|
@@ -50388,7 +50491,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
50388
50491
|
can optionally pass `start` and `end` indices into the
|
|
50389
50492
|
replacement fragment.
|
|
50390
50493
|
*/
|
|
50391
|
-
canReplace(from, to, replacement = Fragment$
|
|
50494
|
+
canReplace(from, to, replacement = Fragment$48.empty, start = 0, end = replacement.childCount) {
|
|
50392
50495
|
let one = this.contentMatchAt(from).matchFragment(replacement, start, end);
|
|
50393
50496
|
let two = one && one.matchFragment(this.content, to);
|
|
50394
50497
|
if (!two || !two.validEnd) return false;
|
|
@@ -50458,7 +50561,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
50458
50561
|
if (typeof json.text != "string") throw new RangeError("Invalid text node in JSON");
|
|
50459
50562
|
return schema.text(json.text, marks);
|
|
50460
50563
|
}
|
|
50461
|
-
let content = Fragment$
|
|
50564
|
+
let content = Fragment$48.fromJSON(schema, json.content);
|
|
50462
50565
|
let node = schema.nodeType(json.type).create(json.attrs, content, marks);
|
|
50463
50566
|
node.type.checkAttrs(node.attrs);
|
|
50464
50567
|
return node;
|
|
@@ -50597,7 +50700,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
50597
50700
|
let seen = [this];
|
|
50598
50701
|
function search(match, types) {
|
|
50599
50702
|
let finished = match.matchFragment(after, startIndex);
|
|
50600
|
-
if (finished && (!toEnd || finished.validEnd)) return Fragment$
|
|
50703
|
+
if (finished && (!toEnd || finished.validEnd)) return Fragment$48.from(types.map((tp) => tp.createAndFill()));
|
|
50601
50704
|
for (let i = 0; i < match.next.length; i++) {
|
|
50602
50705
|
let { type, next } = match.next[i];
|
|
50603
50706
|
if (!(type.isText || type.hasRequiredAttrs()) && seen.indexOf(next) == -1) {
|
|
@@ -51037,7 +51140,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
51037
51140
|
*/
|
|
51038
51141
|
create(attrs = null, content, marks) {
|
|
51039
51142
|
if (this.isText) throw new Error("NodeType.create can't construct text nodes");
|
|
51040
|
-
return new Node$2(this, this.computeAttrs(attrs), Fragment$
|
|
51143
|
+
return new Node$2(this, this.computeAttrs(attrs), Fragment$48.from(content), Mark$1.setFrom(marks));
|
|
51041
51144
|
}
|
|
51042
51145
|
/**
|
|
51043
51146
|
Like [`create`](https://prosemirror.net/docs/ref/#model.NodeType.create), but check the given content
|
|
@@ -51045,7 +51148,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
51045
51148
|
if it doesn't match.
|
|
51046
51149
|
*/
|
|
51047
51150
|
createChecked(attrs = null, content, marks) {
|
|
51048
|
-
content = Fragment$
|
|
51151
|
+
content = Fragment$48.from(content);
|
|
51049
51152
|
this.checkContent(content);
|
|
51050
51153
|
return new Node$2(this, this.computeAttrs(attrs), content, Mark$1.setFrom(marks));
|
|
51051
51154
|
}
|
|
@@ -51059,14 +51162,14 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
51059
51162
|
*/
|
|
51060
51163
|
createAndFill(attrs = null, content, marks) {
|
|
51061
51164
|
attrs = this.computeAttrs(attrs);
|
|
51062
|
-
content = Fragment$
|
|
51165
|
+
content = Fragment$48.from(content);
|
|
51063
51166
|
if (content.size) {
|
|
51064
51167
|
let before = this.contentMatch.fillBefore(content);
|
|
51065
51168
|
if (!before) return null;
|
|
51066
51169
|
content = before.append(content);
|
|
51067
51170
|
}
|
|
51068
51171
|
let matched = this.contentMatch.matchFragment(content);
|
|
51069
|
-
let after = matched && matched.fillBefore(Fragment$
|
|
51172
|
+
let after = matched && matched.fillBefore(Fragment$48.empty, true);
|
|
51070
51173
|
if (!after) return null;
|
|
51071
51174
|
return new Node$2(this, attrs, content.append(after), Mark$1.setFrom(marks));
|
|
51072
51175
|
}
|
|
@@ -51518,7 +51621,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
51518
51621
|
findWrapping(node) {
|
|
51519
51622
|
if (!this.match) {
|
|
51520
51623
|
if (!this.type) return [];
|
|
51521
|
-
let fill = this.type.contentMatch.fillBefore(Fragment$
|
|
51624
|
+
let fill = this.type.contentMatch.fillBefore(Fragment$48.from(node));
|
|
51522
51625
|
if (fill) this.match = this.type.contentMatch.matchFragment(fill);
|
|
51523
51626
|
else {
|
|
51524
51627
|
let start = this.type.contentMatch, wrap;
|
|
@@ -51539,8 +51642,8 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
51539
51642
|
else this.content[this.content.length - 1] = text.withText(text.text.slice(0, text.text.length - m[0].length));
|
|
51540
51643
|
}
|
|
51541
51644
|
}
|
|
51542
|
-
let content = Fragment$
|
|
51543
|
-
if (!openEnd && this.match) content = content.append(this.match.fillBefore(Fragment$
|
|
51645
|
+
let content = Fragment$48.from(this.content);
|
|
51646
|
+
if (!openEnd && this.match) content = content.append(this.match.fillBefore(Fragment$48.empty, true));
|
|
51544
51647
|
return this.type ? this.type.create(this.attrs, content, this.marks) : content;
|
|
51545
51648
|
}
|
|
51546
51649
|
inlineContext(node) {
|
|
@@ -52467,7 +52570,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
52467
52570
|
if (child.isInline) child = f(child, parent, i);
|
|
52468
52571
|
mapped.push(child);
|
|
52469
52572
|
}
|
|
52470
|
-
return Fragment$
|
|
52573
|
+
return Fragment$48.fromArray(mapped);
|
|
52471
52574
|
}
|
|
52472
52575
|
/**
|
|
52473
52576
|
Add a mark to all inline content between two positions.
|
|
@@ -52585,7 +52688,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
52585
52688
|
let node = doc.nodeAt(this.pos);
|
|
52586
52689
|
if (!node) return StepResult.fail("No node at mark step's position");
|
|
52587
52690
|
let updated = node.type.create(node.attrs, null, this.mark.addToSet(node.marks));
|
|
52588
|
-
return StepResult.fromReplace(doc, this.pos, this.pos + 1, new Slice(Fragment$
|
|
52691
|
+
return StepResult.fromReplace(doc, this.pos, this.pos + 1, new Slice(Fragment$48.from(updated), 0, node.isLeaf ? 0 : 1));
|
|
52589
52692
|
}
|
|
52590
52693
|
invert(doc) {
|
|
52591
52694
|
let node = doc.nodeAt(this.pos);
|
|
@@ -52634,7 +52737,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
52634
52737
|
let node = doc.nodeAt(this.pos);
|
|
52635
52738
|
if (!node) return StepResult.fail("No node at mark step's position");
|
|
52636
52739
|
let updated = node.type.create(node.attrs, null, this.mark.removeFromSet(node.marks));
|
|
52637
|
-
return StepResult.fromReplace(doc, this.pos, this.pos + 1, new Slice(Fragment$
|
|
52740
|
+
return StepResult.fromReplace(doc, this.pos, this.pos + 1, new Slice(Fragment$48.from(updated), 0, node.isLeaf ? 0 : 1));
|
|
52638
52741
|
}
|
|
52639
52742
|
invert(doc) {
|
|
52640
52743
|
let node = doc.nodeAt(this.pos);
|
|
@@ -52898,7 +53001,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
52898
53001
|
if (clearNewlines && child.isText && parentType.whitespace != "pre") {
|
|
52899
53002
|
let m, newline = /\r?\n|\r/g, slice;
|
|
52900
53003
|
while (m = newline.exec(child.text)) {
|
|
52901
|
-
if (!slice) slice = new Slice(Fragment$
|
|
53004
|
+
if (!slice) slice = new Slice(Fragment$48.from(parentType.schema.text(" ", parentType.allowedMarks(child.marks))), 0, 0);
|
|
52902
53005
|
replSteps.push(new ReplaceStep(cur + m.index, cur + m.index + m[0].length, slice));
|
|
52903
53006
|
}
|
|
52904
53007
|
}
|
|
@@ -52906,7 +53009,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
52906
53009
|
cur = end;
|
|
52907
53010
|
}
|
|
52908
53011
|
if (!match.validEnd) {
|
|
52909
|
-
let fill = match.fillBefore(Fragment$
|
|
53012
|
+
let fill = match.fillBefore(Fragment$48.empty, true);
|
|
52910
53013
|
tr.replace(cur, cur, new Slice(fill, 0, 0));
|
|
52911
53014
|
}
|
|
52912
53015
|
for (let i = replSteps.length - 1; i >= 0; i--) tr.step(replSteps[i]);
|
|
@@ -52935,16 +53038,16 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
52935
53038
|
let { $from, $to, depth } = range;
|
|
52936
53039
|
let gapStart = $from.before(depth + 1), gapEnd = $to.after(depth + 1);
|
|
52937
53040
|
let start = gapStart, end = gapEnd;
|
|
52938
|
-
let before = Fragment$
|
|
53041
|
+
let before = Fragment$48.empty, openStart = 0;
|
|
52939
53042
|
for (let d = depth, splitting = false; d > target; d--) if (splitting || $from.index(d) > 0) {
|
|
52940
53043
|
splitting = true;
|
|
52941
|
-
before = Fragment$
|
|
53044
|
+
before = Fragment$48.from($from.node(d).copy(before));
|
|
52942
53045
|
openStart++;
|
|
52943
53046
|
} else start--;
|
|
52944
|
-
let after = Fragment$
|
|
53047
|
+
let after = Fragment$48.empty, openEnd = 0;
|
|
52945
53048
|
for (let d = depth, splitting = false; d > target; d--) if (splitting || $to.after(d + 1) < $to.end(d)) {
|
|
52946
53049
|
splitting = true;
|
|
52947
|
-
after = Fragment$
|
|
53050
|
+
after = Fragment$48.from($to.node(d).copy(after));
|
|
52948
53051
|
openEnd++;
|
|
52949
53052
|
} else end++;
|
|
52950
53053
|
tr.step(new ReplaceAroundStep(start, end, gapStart, gapEnd, new Slice(before.append(after), openStart, openEnd), before.size - openStart, true));
|
|
@@ -52990,13 +53093,13 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
52990
53093
|
return inside;
|
|
52991
53094
|
}
|
|
52992
53095
|
function wrap(tr, range, wrappers) {
|
|
52993
|
-
let content = Fragment$
|
|
53096
|
+
let content = Fragment$48.empty;
|
|
52994
53097
|
for (let i = wrappers.length - 1; i >= 0; i--) {
|
|
52995
53098
|
if (content.size) {
|
|
52996
53099
|
let match = wrappers[i].type.contentMatch.matchFragment(content);
|
|
52997
53100
|
if (!match || !match.validEnd) throw new RangeError("Wrapper type given to Transform.wrap does not form valid content of its parent wrapper");
|
|
52998
53101
|
}
|
|
52999
|
-
content = Fragment$
|
|
53102
|
+
content = Fragment$48.from(wrappers[i].type.create(wrappers[i].attrs, content));
|
|
53000
53103
|
}
|
|
53001
53104
|
let start = range.start, end = range.end;
|
|
53002
53105
|
tr.step(new ReplaceAroundStep(start, end, start, end, new Slice(content, 0, 0), wrappers.length, true));
|
|
@@ -53017,7 +53120,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
53017
53120
|
clearIncompatible(tr, tr.mapping.slice(mapFrom).map(pos, 1), type, void 0, convertNewlines === null);
|
|
53018
53121
|
let mapping = tr.mapping.slice(mapFrom);
|
|
53019
53122
|
let startM = mapping.map(pos, 1), endM = mapping.map(pos + node.nodeSize, 1);
|
|
53020
|
-
tr.step(new ReplaceAroundStep(startM, endM, startM + 1, endM - 1, new Slice(Fragment$
|
|
53123
|
+
tr.step(new ReplaceAroundStep(startM, endM, startM + 1, endM - 1, new Slice(Fragment$48.from(type.create(attrsHere, null, node.marks)), 0, 0), 1, true));
|
|
53021
53124
|
if (convertNewlines === true) replaceNewlines(tr, node, pos, mapFrom);
|
|
53022
53125
|
return false;
|
|
53023
53126
|
}
|
|
@@ -53057,7 +53160,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
53057
53160
|
let newNode = type.create(attrs, null, marks || node.marks);
|
|
53058
53161
|
if (node.isLeaf) return tr.replaceWith(pos, pos + node.nodeSize, newNode);
|
|
53059
53162
|
if (!type.validContent(node.content)) throw new RangeError("Invalid content for node type " + type.name);
|
|
53060
|
-
tr.step(new ReplaceAroundStep(pos, pos + node.nodeSize, pos + 1, pos + node.nodeSize - 1, new Slice(Fragment$
|
|
53163
|
+
tr.step(new ReplaceAroundStep(pos, pos + node.nodeSize, pos + 1, pos + node.nodeSize - 1, new Slice(Fragment$48.from(newNode), 0, 0), 1, true));
|
|
53061
53164
|
}
|
|
53062
53165
|
/**
|
|
53063
53166
|
Check whether splitting at the given position is allowed.
|
|
@@ -53080,11 +53183,11 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
53080
53183
|
return $pos.node(base).canReplaceWith(index, index, baseType ? baseType.type : $pos.node(base + 1).type);
|
|
53081
53184
|
}
|
|
53082
53185
|
function split(tr, pos, depth = 1, typesAfter) {
|
|
53083
|
-
let $pos = tr.doc.resolve(pos), before = Fragment$
|
|
53186
|
+
let $pos = tr.doc.resolve(pos), before = Fragment$48.empty, after = Fragment$48.empty;
|
|
53084
53187
|
for (let d = $pos.depth, e = $pos.depth - depth, i = depth - 1; d > e; d--, i--) {
|
|
53085
|
-
before = Fragment$
|
|
53188
|
+
before = Fragment$48.from($pos.node(d).copy(before));
|
|
53086
53189
|
let typeAfter = typesAfter && typesAfter[i];
|
|
53087
|
-
after = Fragment$
|
|
53190
|
+
after = Fragment$48.from(typeAfter ? typeAfter.type.create(typeAfter.attrs, after) : $pos.node(d).copy(after));
|
|
53088
53191
|
}
|
|
53089
53192
|
tr.step(new ReplaceStep(pos, pos, new Slice(before.append(after), depth, depth), true));
|
|
53090
53193
|
}
|
|
@@ -53227,7 +53330,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
53227
53330
|
this.$to = $to;
|
|
53228
53331
|
this.unplaced = unplaced;
|
|
53229
53332
|
this.frontier = [];
|
|
53230
|
-
this.placed = Fragment$
|
|
53333
|
+
this.placed = Fragment$48.empty;
|
|
53231
53334
|
for (let i = 0; i <= $from.depth; i++) {
|
|
53232
53335
|
let node = $from.node(i);
|
|
53233
53336
|
this.frontier.push({
|
|
@@ -53235,7 +53338,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
53235
53338
|
match: node.contentMatchAt($from.indexAfter(i))
|
|
53236
53339
|
});
|
|
53237
53340
|
}
|
|
53238
|
-
for (let i = $from.depth; i > 0; i--) this.placed = Fragment$
|
|
53341
|
+
for (let i = $from.depth; i > 0; i--) this.placed = Fragment$48.from($from.node(i).copy(this.placed));
|
|
53239
53342
|
}
|
|
53240
53343
|
get depth() {
|
|
53241
53344
|
return this.frontier.length - 1;
|
|
@@ -53280,7 +53383,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
53280
53383
|
let first = fragment.firstChild;
|
|
53281
53384
|
for (let frontierDepth = this.depth; frontierDepth >= 0; frontierDepth--) {
|
|
53282
53385
|
let { type, match } = this.frontier[frontierDepth], wrap, inject = null;
|
|
53283
|
-
if (pass == 1 && (first ? match.matchType(first.type) || (inject = match.fillBefore(Fragment$
|
|
53386
|
+
if (pass == 1 && (first ? match.matchType(first.type) || (inject = match.fillBefore(Fragment$48.from(first), false)) : parent && type.compatibleContent(parent.type))) return {
|
|
53284
53387
|
sliceDepth,
|
|
53285
53388
|
frontierDepth,
|
|
53286
53389
|
parent,
|
|
@@ -53334,7 +53437,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
53334
53437
|
}
|
|
53335
53438
|
let toEnd = taken == fragment.childCount;
|
|
53336
53439
|
if (!toEnd) openEndCount = -1;
|
|
53337
|
-
this.placed = addToFragment(this.placed, frontierDepth, Fragment$
|
|
53440
|
+
this.placed = addToFragment(this.placed, frontierDepth, Fragment$48.from(add));
|
|
53338
53441
|
this.frontier[frontierDepth].match = match;
|
|
53339
53442
|
if (toEnd && openEndCount < 0 && parent && parent.type == this.frontier[this.depth].type && this.frontier.length > 1) this.closeFrontierNode();
|
|
53340
53443
|
for (let i = 0, cur = fragment; i < openEndCount; i++) {
|
|
@@ -53388,14 +53491,14 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
53388
53491
|
openFrontierNode(type, attrs = null, content) {
|
|
53389
53492
|
let top = this.frontier[this.depth];
|
|
53390
53493
|
top.match = top.match.matchType(type);
|
|
53391
|
-
this.placed = addToFragment(this.placed, this.depth, Fragment$
|
|
53494
|
+
this.placed = addToFragment(this.placed, this.depth, Fragment$48.from(type.create(attrs, content)));
|
|
53392
53495
|
this.frontier.push({
|
|
53393
53496
|
type,
|
|
53394
53497
|
match: type.contentMatch
|
|
53395
53498
|
});
|
|
53396
53499
|
}
|
|
53397
53500
|
closeFrontierNode() {
|
|
53398
|
-
let add = this.frontier.pop().match.fillBefore(Fragment$
|
|
53501
|
+
let add = this.frontier.pop().match.fillBefore(Fragment$48.empty, true);
|
|
53399
53502
|
if (add.childCount) this.placed = addToFragment(this.placed, this.frontier.length, add);
|
|
53400
53503
|
}
|
|
53401
53504
|
};
|
|
@@ -53417,7 +53520,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
53417
53520
|
if (openStart > 1) frag = frag.replaceChild(0, closeNodeStart(frag.firstChild, openStart - 1, frag.childCount == 1 ? openEnd - 1 : 0));
|
|
53418
53521
|
if (openStart > 0) {
|
|
53419
53522
|
frag = node.type.contentMatch.fillBefore(frag).append(frag);
|
|
53420
|
-
if (openEnd <= 0) frag = frag.append(node.type.contentMatch.matchFragment(frag).fillBefore(Fragment$
|
|
53523
|
+
if (openEnd <= 0) frag = frag.append(node.type.contentMatch.matchFragment(frag).fillBefore(Fragment$48.empty, true));
|
|
53421
53524
|
}
|
|
53422
53525
|
return node.copy(frag);
|
|
53423
53526
|
}
|
|
@@ -53500,7 +53603,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
53500
53603
|
if (depth > newOpen) {
|
|
53501
53604
|
let match = parent.contentMatchAt(0);
|
|
53502
53605
|
let start = match.fillBefore(fragment).append(fragment);
|
|
53503
|
-
fragment = start.append(match.matchFragment(start).fillBefore(Fragment$
|
|
53606
|
+
fragment = start.append(match.matchFragment(start).fillBefore(Fragment$48.empty, true));
|
|
53504
53607
|
}
|
|
53505
53608
|
return fragment;
|
|
53506
53609
|
}
|
|
@@ -53509,7 +53612,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
53509
53612
|
let point = insertPoint(tr.doc, from, node.type);
|
|
53510
53613
|
if (point != null) from = to = point;
|
|
53511
53614
|
}
|
|
53512
|
-
tr.replaceRange(from, to, new Slice(Fragment$
|
|
53615
|
+
tr.replaceRange(from, to, new Slice(Fragment$48.from(node), 0, 0));
|
|
53513
53616
|
}
|
|
53514
53617
|
function deleteRange$1(tr, from, to) {
|
|
53515
53618
|
let $from = tr.doc.resolve(from), $to = tr.doc.resolve(to);
|
|
@@ -53562,7 +53665,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
53562
53665
|
for (let name in node.attrs) attrs[name] = node.attrs[name];
|
|
53563
53666
|
attrs[this.attr] = this.value;
|
|
53564
53667
|
let updated = node.type.create(attrs, null, node.marks);
|
|
53565
|
-
return StepResult.fromReplace(doc, this.pos, this.pos + 1, new Slice(Fragment$
|
|
53668
|
+
return StepResult.fromReplace(doc, this.pos, this.pos + 1, new Slice(Fragment$48.from(updated), 0, node.isLeaf ? 0 : 1));
|
|
53566
53669
|
}
|
|
53567
53670
|
getMap() {
|
|
53568
53671
|
return StepMap.empty;
|
|
@@ -53745,7 +53848,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
53745
53848
|
fragment, node, or array of nodes.
|
|
53746
53849
|
*/
|
|
53747
53850
|
replaceWith(from, to, content) {
|
|
53748
|
-
return this.replace(from, to, new Slice(Fragment$
|
|
53851
|
+
return this.replace(from, to, new Slice(Fragment$48.from(content), 0, 0));
|
|
53749
53852
|
}
|
|
53750
53853
|
/**
|
|
53751
53854
|
Delete the content between the given positions.
|
|
@@ -54250,7 +54353,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
54250
54353
|
return new NodeSelection($pos);
|
|
54251
54354
|
}
|
|
54252
54355
|
content() {
|
|
54253
|
-
return new Slice(Fragment$
|
|
54356
|
+
return new Slice(Fragment$48.from(this.node), 0, 0);
|
|
54254
54357
|
}
|
|
54255
54358
|
eq(other) {
|
|
54256
54359
|
return other instanceof NodeSelection && other.anchor == this.anchor;
|
|
@@ -55293,9 +55396,9 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
55293
55396
|
let canDelAfter = !isolated && $cut.parent.canReplace($cut.index(), $cut.index() + 1);
|
|
55294
55397
|
if (canDelAfter && (conn = (match = before.contentMatchAt(before.childCount)).findWrapping(after.type)) && match.matchType(conn[0] || after.type).validEnd) {
|
|
55295
55398
|
if (dispatch) {
|
|
55296
|
-
let end = $cut.pos + after.nodeSize, wrap = Fragment$
|
|
55297
|
-
for (let i = conn.length - 1; i >= 0; i--) wrap = Fragment$
|
|
55298
|
-
wrap = Fragment$
|
|
55399
|
+
let end = $cut.pos + after.nodeSize, wrap = Fragment$48.empty;
|
|
55400
|
+
for (let i = conn.length - 1; i >= 0; i--) wrap = Fragment$48.from(conn[i].create(null, wrap));
|
|
55401
|
+
wrap = Fragment$48.from(before.copy(wrap));
|
|
55299
55402
|
let tr = state.tr.step(new ReplaceAroundStep($cut.pos - 1, end, $cut.pos, end, new Slice(wrap, 1, 0), conn.length, true));
|
|
55300
55403
|
let $joinAt = tr.doc.resolve(end + 2 * conn.length);
|
|
55301
55404
|
if ($joinAt.nodeAfter && $joinAt.nodeAfter.type == before.type && canJoin(tr.doc, $joinAt.pos)) tr.join($joinAt.pos);
|
|
@@ -55320,8 +55423,8 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
55320
55423
|
for (; !afterText.isTextblock; afterText = afterText.firstChild) afterDepth++;
|
|
55321
55424
|
if (at.canReplace(at.childCount, at.childCount, afterText.content)) {
|
|
55322
55425
|
if (dispatch) {
|
|
55323
|
-
let end = Fragment$
|
|
55324
|
-
for (let i = wrap.length - 1; i >= 0; i--) end = Fragment$
|
|
55426
|
+
let end = Fragment$48.empty;
|
|
55427
|
+
for (let i = wrap.length - 1; i >= 0; i--) end = Fragment$48.from(wrap[i].copy(end));
|
|
55325
55428
|
dispatch(state.tr.step(new ReplaceAroundStep($cut.pos - wrap.length, $cut.pos + after.nodeSize, $cut.pos + afterDepth, $cut.pos + after.nodeSize - afterDepth, new Slice(end, wrap.length, 0), 0, true)).scrollIntoView());
|
|
55326
55429
|
}
|
|
55327
55430
|
return true;
|
|
@@ -55487,8 +55590,8 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
55487
55590
|
return true;
|
|
55488
55591
|
}
|
|
55489
55592
|
function doWrapInList(tr, range, wrappers, joinBefore, listType) {
|
|
55490
|
-
let content = Fragment$
|
|
55491
|
-
for (let i = wrappers.length - 1; i >= 0; i--) content = Fragment$
|
|
55593
|
+
let content = Fragment$48.empty;
|
|
55594
|
+
for (let i = wrappers.length - 1; i >= 0; i--) content = Fragment$48.from(wrappers[i].type.create(wrappers[i].attrs, content));
|
|
55492
55595
|
tr.step(new ReplaceAroundStep(range.start - (joinBefore ? 2 : 0), range.end, range.start, range.end, new Slice(content, 0, 0), wrappers.length, true));
|
|
55493
55596
|
let found = 0;
|
|
55494
55597
|
for (let i = 0; i < wrappers.length; i++) if (wrappers[i].type == listType) found = i + 1;
|
|
@@ -55520,7 +55623,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
55520
55623
|
function liftToOuterList(state, dispatch, itemType, range) {
|
|
55521
55624
|
let tr = state.tr, end = range.end, endOfList = range.$to.end(range.depth);
|
|
55522
55625
|
if (end < endOfList) {
|
|
55523
|
-
tr.step(new ReplaceAroundStep(end - 1, endOfList, end, endOfList, new Slice(Fragment$
|
|
55626
|
+
tr.step(new ReplaceAroundStep(end - 1, endOfList, end, endOfList, new Slice(Fragment$48.from(itemType.create(null, range.parent.copy())), 1, 0), 1, true));
|
|
55524
55627
|
range = new NodeRange(tr.doc.resolve(range.$from.pos), tr.doc.resolve(endOfList), range.depth);
|
|
55525
55628
|
}
|
|
55526
55629
|
const target = liftTarget(range);
|
|
@@ -55541,9 +55644,9 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
55541
55644
|
if (tr.mapping.map(range.end) != range.start + $start.nodeAfter.nodeSize) return false;
|
|
55542
55645
|
let atStart = range.startIndex == 0, atEnd = range.endIndex == list.childCount;
|
|
55543
55646
|
let parent = $start.node(-1), indexBefore = $start.index(-1);
|
|
55544
|
-
if (!parent.canReplace(indexBefore + (atStart ? 0 : 1), indexBefore + 1, item.content.append(atEnd ? Fragment$
|
|
55647
|
+
if (!parent.canReplace(indexBefore + (atStart ? 0 : 1), indexBefore + 1, item.content.append(atEnd ? Fragment$48.empty : Fragment$48.from(list)))) return false;
|
|
55545
55648
|
let start = $start.pos, end = start + item.nodeSize;
|
|
55546
|
-
tr.step(new ReplaceAroundStep(start - (atStart ? 1 : 0), end + (atEnd ? 1 : 0), start + 1, end - 1, new Slice((atStart ? Fragment$
|
|
55649
|
+
tr.step(new ReplaceAroundStep(start - (atStart ? 1 : 0), end + (atEnd ? 1 : 0), start + 1, end - 1, new Slice((atStart ? Fragment$48.empty : Fragment$48.from(list.copy(Fragment$48.empty))).append(atEnd ? Fragment$48.empty : Fragment$48.from(list.copy(Fragment$48.empty))), atStart ? 0 : 1, atEnd ? 0 : 1), atStart ? 0 : 1));
|
|
55547
55650
|
dispatch(tr.scrollIntoView());
|
|
55548
55651
|
return true;
|
|
55549
55652
|
}
|
|
@@ -55562,8 +55665,8 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
55562
55665
|
if (nodeBefore.type != itemType) return false;
|
|
55563
55666
|
if (dispatch) {
|
|
55564
55667
|
let nestedBefore = nodeBefore.lastChild && nodeBefore.lastChild.type == parent.type;
|
|
55565
|
-
let inner = Fragment$
|
|
55566
|
-
let slice = new Slice(Fragment$
|
|
55668
|
+
let inner = Fragment$48.from(nestedBefore ? itemType.create() : null);
|
|
55669
|
+
let slice = new Slice(Fragment$48.from(itemType.create(null, Fragment$48.from(parent.type.create(null, inner)))), nestedBefore ? 3 : 1, 0);
|
|
55567
55670
|
let before = range.start, after = range.end;
|
|
55568
55671
|
dispatch(state.tr.step(new ReplaceAroundStep(before - (nestedBefore ? 3 : 1), after, before, after, slice, 1, true)).scrollIntoView());
|
|
55569
55672
|
}
|
|
@@ -56657,7 +56760,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
56657
56760
|
if (!rule.contentElement) {
|
|
56658
56761
|
let found = addedNodes && addedNodes.find((n) => n.nodeType == 1 && addedNodes.indexOf(n.parentNode) < 0 && this.dom.contains(n));
|
|
56659
56762
|
if (found) rule.contentElement = found;
|
|
56660
|
-
else rule.getContent = () => Fragment$
|
|
56763
|
+
else rule.getContent = () => Fragment$48.empty;
|
|
56661
56764
|
}
|
|
56662
56765
|
}
|
|
56663
56766
|
return rule;
|
|
@@ -57767,7 +57870,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
57767
57870
|
text = f(text, inCode || plainText, view);
|
|
57768
57871
|
});
|
|
57769
57872
|
if (inCode) {
|
|
57770
|
-
slice = new Slice(Fragment$
|
|
57873
|
+
slice = new Slice(Fragment$48.from(view.state.schema.text(text.replace(/\r\n?/g, "\n"))), 0, 0);
|
|
57771
57874
|
view.someProp("transformPasted", (f) => {
|
|
57772
57875
|
slice = f(slice, view, true);
|
|
57773
57876
|
});
|
|
@@ -57841,32 +57944,32 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
57841
57944
|
lastWrap = wrap;
|
|
57842
57945
|
}
|
|
57843
57946
|
});
|
|
57844
|
-
if (result) return Fragment$
|
|
57947
|
+
if (result) return Fragment$48.from(result);
|
|
57845
57948
|
}
|
|
57846
57949
|
return fragment;
|
|
57847
57950
|
}
|
|
57848
57951
|
function withWrappers(node, wrap, from = 0) {
|
|
57849
|
-
for (let i = wrap.length - 1; i >= from; i--) node = wrap[i].create(null, Fragment$
|
|
57952
|
+
for (let i = wrap.length - 1; i >= from; i--) node = wrap[i].create(null, Fragment$48.from(node));
|
|
57850
57953
|
return node;
|
|
57851
57954
|
}
|
|
57852
57955
|
function addToSibling(wrap, lastWrap, node, sibling, depth) {
|
|
57853
57956
|
if (depth < wrap.length && depth < lastWrap.length && wrap[depth] == lastWrap[depth]) {
|
|
57854
57957
|
let inner = addToSibling(wrap, lastWrap, node, sibling.lastChild, depth + 1);
|
|
57855
57958
|
if (inner) return sibling.copy(sibling.content.replaceChild(sibling.childCount - 1, inner));
|
|
57856
|
-
if (sibling.contentMatchAt(sibling.childCount).matchType(depth == wrap.length - 1 ? node.type : wrap[depth + 1])) return sibling.copy(sibling.content.append(Fragment$
|
|
57959
|
+
if (sibling.contentMatchAt(sibling.childCount).matchType(depth == wrap.length - 1 ? node.type : wrap[depth + 1])) return sibling.copy(sibling.content.append(Fragment$48.from(withWrappers(node, wrap, depth + 1))));
|
|
57857
57960
|
}
|
|
57858
57961
|
}
|
|
57859
57962
|
function closeRight(node, depth) {
|
|
57860
57963
|
if (depth == 0) return node;
|
|
57861
57964
|
let fragment = node.content.replaceChild(node.childCount - 1, closeRight(node.lastChild, depth - 1));
|
|
57862
|
-
let fill = node.contentMatchAt(node.childCount).fillBefore(Fragment$
|
|
57965
|
+
let fill = node.contentMatchAt(node.childCount).fillBefore(Fragment$48.empty, true);
|
|
57863
57966
|
return node.copy(fragment.append(fill));
|
|
57864
57967
|
}
|
|
57865
57968
|
function closeRange(fragment, side, from, to, depth, openEnd) {
|
|
57866
57969
|
let node = side < 0 ? fragment.firstChild : fragment.lastChild, inner = node.content;
|
|
57867
57970
|
if (fragment.childCount > 1) openEnd = 0;
|
|
57868
57971
|
if (depth < to - 1) inner = closeRange(inner, side, from, to, depth + 1, openEnd);
|
|
57869
|
-
if (depth >= from) inner = side < 0 ? node.contentMatchAt(0).fillBefore(inner, openEnd <= depth).append(inner) : inner.append(node.contentMatchAt(node.childCount).fillBefore(Fragment$
|
|
57972
|
+
if (depth >= from) inner = side < 0 ? node.contentMatchAt(0).fillBefore(inner, openEnd <= depth).append(inner) : inner.append(node.contentMatchAt(node.childCount).fillBefore(Fragment$48.empty, true));
|
|
57870
57973
|
return fragment.replaceChild(side < 0 ? 0 : fragment.childCount - 1, node.copy(inner));
|
|
57871
57974
|
}
|
|
57872
57975
|
function closeSlice(slice, openStart, openEnd) {
|
|
@@ -57952,7 +58055,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
57952
58055
|
} catch (e) {
|
|
57953
58056
|
break;
|
|
57954
58057
|
}
|
|
57955
|
-
content = Fragment$
|
|
58058
|
+
content = Fragment$48.from(type.create(array[i + 1], content));
|
|
57956
58059
|
openStart++;
|
|
57957
58060
|
openEnd++;
|
|
57958
58061
|
}
|
|
@@ -59678,7 +59781,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
59678
59781
|
} else return null;
|
|
59679
59782
|
let updated = [];
|
|
59680
59783
|
for (let i = 0; i < prev.childCount; i++) updated.push(update(prev.child(i)));
|
|
59681
|
-
if (Fragment$
|
|
59784
|
+
if (Fragment$48.from(updated).eq(cur)) return {
|
|
59682
59785
|
mark,
|
|
59683
59786
|
type
|
|
59684
59787
|
};
|
|
@@ -60948,7 +61051,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
60948
61051
|
};
|
|
60949
61052
|
const isTextContent = typeof content === "string";
|
|
60950
61053
|
if (isJSONContent) try {
|
|
60951
|
-
if (Array.isArray(content) && content.length > 0) return Fragment$
|
|
61054
|
+
if (Array.isArray(content) && content.length > 0) return Fragment$48.fromArray(content.map((item) => schema.nodeFromJSON(item)));
|
|
60952
61055
|
const node = schema.nodeFromJSON(content);
|
|
60953
61056
|
if (options.errorOnInvalidContent) node.check();
|
|
60954
61057
|
return node;
|
|
@@ -61085,7 +61188,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
61085
61188
|
else newContent = value;
|
|
61086
61189
|
tr.insertText(newContent, from, to);
|
|
61087
61190
|
} else {
|
|
61088
|
-
newContent = Fragment$
|
|
61191
|
+
newContent = Fragment$48.from(nodes);
|
|
61089
61192
|
const $from = tr.doc.resolve(from);
|
|
61090
61193
|
const $fromNode = $from.node();
|
|
61091
61194
|
const fromSelectionAtStart = $from.parentOffset === 0;
|
|
@@ -62501,16 +62604,16 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
62501
62604
|
if ($from.depth === 2 || $from.node(-3).type !== type || $from.index(-2) !== $from.node(-2).childCount - 1) return false;
|
|
62502
62605
|
if (dispatch) {
|
|
62503
62606
|
var _type$contentMatch$de;
|
|
62504
|
-
let wrap = Fragment$
|
|
62607
|
+
let wrap = Fragment$48.empty;
|
|
62505
62608
|
const depthBefore = $from.index(-1) ? 1 : $from.index(-2) ? 2 : 3;
|
|
62506
|
-
for (let d = $from.depth - depthBefore; d >= $from.depth - 3; d -= 1) wrap = Fragment$
|
|
62609
|
+
for (let d = $from.depth - depthBefore; d >= $from.depth - 3; d -= 1) wrap = Fragment$48.from($from.node(d).copy(wrap));
|
|
62507
62610
|
const depthAfter = $from.indexAfter(-1) < $from.node(-2).childCount ? 1 : $from.indexAfter(-2) < $from.node(-3).childCount ? 2 : 3;
|
|
62508
62611
|
const newNextTypeAttributes = {
|
|
62509
62612
|
...getSplittedAttributes(extensionAttributes, $from.node().type.name, $from.node().attrs),
|
|
62510
62613
|
...overrideAttrs
|
|
62511
62614
|
};
|
|
62512
62615
|
const nextType = ((_type$contentMatch$de = type.contentMatch.defaultType) === null || _type$contentMatch$de === void 0 ? void 0 : _type$contentMatch$de.createAndFill(newNextTypeAttributes)) || void 0;
|
|
62513
|
-
wrap = wrap.append(Fragment$
|
|
62616
|
+
wrap = wrap.append(Fragment$48.from(type.createAndFill(null, nextType) || void 0));
|
|
62514
62617
|
const start = $from.before($from.depth - (depthBefore - 1));
|
|
62515
62618
|
tr.replace(start, $from.after(-depthAfter), new Slice(wrap, 4 - depthBefore, 0));
|
|
62516
62619
|
let sel = -1;
|
|
@@ -63904,7 +64007,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
63904
64007
|
if (!!simulatedInputMeta) setTimeout(() => {
|
|
63905
64008
|
let { text } = simulatedInputMeta;
|
|
63906
64009
|
if (typeof text === "string") text = text;
|
|
63907
|
-
else text = getHTMLFromFragment(Fragment$
|
|
64010
|
+
else text = getHTMLFromFragment(Fragment$48.from(text), state.schema);
|
|
63908
64011
|
const { from } = simulatedInputMeta;
|
|
63909
64012
|
const to = from + text.length;
|
|
63910
64013
|
run$1({
|
|
@@ -64209,7 +64312,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
64209
64312
|
if (isSimulatedPaste) {
|
|
64210
64313
|
let { text } = simulatedPasteMeta;
|
|
64211
64314
|
if (typeof text === "string") text = text;
|
|
64212
|
-
else text = getHTMLFromFragment(Fragment$
|
|
64315
|
+
else text = getHTMLFromFragment(Fragment$48.from(text), state.schema);
|
|
64213
64316
|
const { from } = simulatedPasteMeta;
|
|
64214
64317
|
const to = from + text.length;
|
|
64215
64318
|
const pasteEvt = createClipboardPasteEvent(text);
|
|
@@ -64941,7 +65044,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
64941
65044
|
} catch {
|
|
64942
65045
|
return;
|
|
64943
65046
|
}
|
|
64944
|
-
if (content instanceof Fragment$
|
|
65047
|
+
if (content instanceof Fragment$48) return;
|
|
64945
65048
|
console.warn("[tiptap warn]: prosemirror-model is loaded more than once. Wrapping and splitting nodes will fail. Deduplicate it in your lock file, or alias it to a single copy in your bundler.");
|
|
64946
65049
|
}
|
|
64947
65050
|
var NodePos = class NodePos {
|
|
@@ -71713,7 +71816,7 @@ img.ProseMirror-separator {
|
|
|
71713
71816
|
const tr = state.tr;
|
|
71714
71817
|
tr.delete(nestedListPos, nestedListPos + nestedList.nodeSize);
|
|
71715
71818
|
const mappedInsertPos = tr.mapping.map(insertPos);
|
|
71716
|
-
tr.insert(mappedInsertPos, Fragment$
|
|
71819
|
+
tr.insert(mappedInsertPos, Fragment$48.from(items));
|
|
71717
71820
|
tr.setSelection(selection.map(tr.doc, tr.mapping));
|
|
71718
71821
|
if (dispatch) dispatch(tr);
|
|
71719
71822
|
return true;
|
|
@@ -72126,13 +72229,13 @@ img.ProseMirror-separator {
|
|
|
72126
72229
|
const lastItem = previous.lastChild;
|
|
72127
72230
|
if (!lastItem || lastItem.type.name !== name) return false;
|
|
72128
72231
|
const block = $from.parent;
|
|
72129
|
-
if (!lastItem.canReplace(lastItem.childCount, lastItem.childCount, Fragment$
|
|
72232
|
+
if (!lastItem.canReplace(lastItem.childCount, lastItem.childCount, Fragment$48.from(block))) return false;
|
|
72130
72233
|
const blockStart = $from.before();
|
|
72131
72234
|
const blockEnd = $from.after();
|
|
72132
72235
|
const insideLastItemEnd = blockStart - 2;
|
|
72133
72236
|
return editor.commands.command(({ tr, dispatch }) => {
|
|
72134
72237
|
if (dispatch) {
|
|
72135
|
-
tr.delete(blockStart, blockEnd).insert(insideLastItemEnd, Fragment$
|
|
72238
|
+
tr.delete(blockStart, blockEnd).insert(insideLastItemEnd, Fragment$48.from(block));
|
|
72136
72239
|
tr.setSelection(TextSelection.create(tr.doc, insideLastItemEnd + 1));
|
|
72137
72240
|
tr.scrollIntoView();
|
|
72138
72241
|
}
|
|
@@ -73509,8 +73612,8 @@ img.ProseMirror-separator {
|
|
|
73509
73612
|
let { $from } = view.state.selection;
|
|
73510
73613
|
let insert = $from.parent.contentMatchAt($from.index()).findWrapping(view.state.schema.nodes.text);
|
|
73511
73614
|
if (!insert) return false;
|
|
73512
|
-
let frag = Fragment$
|
|
73513
|
-
for (let i = insert.length - 1; i >= 0; i--) frag = Fragment$
|
|
73615
|
+
let frag = Fragment$48.empty;
|
|
73616
|
+
for (let i = insert.length - 1; i >= 0; i--) frag = Fragment$48.from(insert[i].createAndFill(null, frag));
|
|
73514
73617
|
let tr = view.state.tr.replace($from.pos, $from.pos, new Slice(frag, 0, 0));
|
|
73515
73618
|
tr.setSelection(TextSelection.near(tr.doc.resolve($from.pos + 1)));
|
|
73516
73619
|
view.dispatch(tr);
|
|
@@ -117520,6 +117623,7 @@ img.ProseMirror-separator {
|
|
|
117520
117623
|
const [selected, setSelected] = (0, react.useState)(null);
|
|
117521
117624
|
const [mode, setMode] = (0, react.useState)("generate");
|
|
117522
117625
|
const [provider, setProvider] = (0, react.useState)("google");
|
|
117626
|
+
const [channel, setChannel] = (0, react.useState)(void 0);
|
|
117523
117627
|
const [model, setModel] = (0, react.useState)("");
|
|
117524
117628
|
const [ratio, setRatio] = (0, react.useState)("1:1");
|
|
117525
117629
|
const [quality, setQuality] = (0, react.useState)("1K");
|
|
@@ -117533,7 +117637,7 @@ img.ProseMirror-separator {
|
|
|
117533
117637
|
const [selectedBatchIds, setSelectedBatchIds] = (0, react.useState)([]);
|
|
117534
117638
|
const [batchKind, setBatchKind] = (0, react.useState)(null);
|
|
117535
117639
|
const [comparisonEnabled, setComparisonEnabled] = (0, react.useState)(false);
|
|
117536
|
-
const [
|
|
117640
|
+
const [comparisonProviderKeys, setComparisonProviderKeys] = (0, react.useState)([]);
|
|
117537
117641
|
const [isGenerating, setIsGenerating] = (0, react.useState)(false);
|
|
117538
117642
|
const [error, setError] = (0, react.useState)(null);
|
|
117539
117643
|
const [notice, setNotice] = (0, react.useState)(null);
|
|
@@ -117608,7 +117712,7 @@ img.ProseMirror-separator {
|
|
|
117608
117712
|
observer.disconnect();
|
|
117609
117713
|
};
|
|
117610
117714
|
}, []);
|
|
117611
|
-
const maxReferences = comparisonEnabled ?
|
|
117715
|
+
const maxReferences = comparisonEnabled ? comparisonProviderKeys.includes("dashscope") ? 3 : 5 : provider === "dashscope" ? 3 : 5;
|
|
117612
117716
|
const referencesRef = (0, react.useRef)(references);
|
|
117613
117717
|
referencesRef.current = references;
|
|
117614
117718
|
const t = (key, values) => {
|
|
@@ -117628,10 +117732,12 @@ img.ProseMirror-separator {
|
|
|
117628
117732
|
(0, react.useEffect)(() => locale?.subscribe?.(() => setLang(locale.getSnapshot().active?.startsWith("en") ? "en" : "zh")), [locale]);
|
|
117629
117733
|
const formStateRef = (0, react.useRef)({
|
|
117630
117734
|
provider,
|
|
117735
|
+
channel,
|
|
117631
117736
|
model
|
|
117632
117737
|
});
|
|
117633
117738
|
formStateRef.current = {
|
|
117634
117739
|
provider,
|
|
117740
|
+
channel,
|
|
117635
117741
|
model
|
|
117636
117742
|
};
|
|
117637
117743
|
const loadConfig = (0, react.useCallback)(async (options) => {
|
|
@@ -117650,16 +117756,19 @@ img.ProseMirror-separator {
|
|
|
117650
117756
|
if (!response.ok || !("providers" in payload)) throw new Error("error" in payload && payload.error ? payload.error : "Studio unavailable");
|
|
117651
117757
|
setConfig(payload);
|
|
117652
117758
|
if (silent) {
|
|
117653
|
-
const { provider: currentProvider, model: currentModel } = formStateRef.current;
|
|
117654
|
-
const activeProfile = payload.providers.find((item) => item.provider === currentProvider);
|
|
117655
|
-
if (activeProfile
|
|
117656
|
-
|
|
117759
|
+
const { provider: currentProvider, channel: currentChannel, model: currentModel } = formStateRef.current;
|
|
117760
|
+
const activeProfile = payload.providers.find((item) => item.provider === currentProvider && item.channel === currentChannel);
|
|
117761
|
+
if (activeProfile === void 0) {
|
|
117762
|
+
const fallback = payload.providers.find((item) => item.provider === payload.activeProvider && item.channel === payload.activeChannel) ?? payload.providers[0];
|
|
117763
|
+
if (fallback !== void 0) applyProvider(fallback);
|
|
117764
|
+
} else if (!studioModelOptionsForMode(activeProfile, "generate").some((option) => option.value === currentModel)) setModel(activeProfile.model);
|
|
117765
|
+
setComparisonProviderKeys((current) => current.filter((selectedKey) => payload.providers.some((item) => studioTargetKey(item.provider, item.channel) === selectedKey && item.configured)));
|
|
117657
117766
|
return;
|
|
117658
117767
|
}
|
|
117659
|
-
const initial = payload.providers.find((item) => item.provider === payload.activeProvider) ?? payload.providers[0];
|
|
117768
|
+
const initial = payload.providers.find((item) => item.provider === payload.activeProvider && item.channel === payload.activeChannel) ?? payload.providers.find((item) => item.provider === payload.activeProvider) ?? payload.providers[0];
|
|
117660
117769
|
if (initial !== void 0) {
|
|
117661
117770
|
applyProvider(initial);
|
|
117662
|
-
|
|
117771
|
+
setComparisonProviderKeys(initialComparisonProviders(payload.providers, initial.provider, initial.channel));
|
|
117663
117772
|
}
|
|
117664
117773
|
} catch (fetchError) {
|
|
117665
117774
|
if (!silent && !controller.signal.aborted) setConfigError(messageOf(fetchError));
|
|
@@ -117761,13 +117870,18 @@ img.ProseMirror-separator {
|
|
|
117761
117870
|
window.removeEventListener("mouseup", handleMouseUp);
|
|
117762
117871
|
};
|
|
117763
117872
|
}, []);
|
|
117764
|
-
const activeProfile = (0, react.useMemo)(() => config?.providers.find((item) => item.provider === provider), [
|
|
117873
|
+
const activeProfile = (0, react.useMemo)(() => config?.providers.find((item) => item.provider === provider && item.channel === channel), [
|
|
117874
|
+
config,
|
|
117875
|
+
provider,
|
|
117876
|
+
channel
|
|
117877
|
+
]);
|
|
117878
|
+
const requestModel = mode === "edit" && activeProfile?.editModel ? studioModelForMode(activeProfile, mode) : model;
|
|
117765
117879
|
const configuredCount = config?.providers.filter((item) => item.configured).length ?? 0;
|
|
117766
117880
|
const apiConfiguredCount = config?.providers.filter((item) => item.configured && !isSubscriptionProvider(item.provider)).length ?? 0;
|
|
117767
117881
|
const subscriptionSignedInCount = config?.providers.filter((item) => item.configured && isSubscriptionProvider(item.provider)).length ?? 0;
|
|
117768
117882
|
const displayItems = (0, react.useMemo)(() => items.slice(0, visibleLimit), [items, visibleLimit]);
|
|
117769
117883
|
const comparisonProfiles = (0, react.useMemo)(() => (config?.providers ?? []).filter((item) => item.configured && (mode === "generate" || item.supportsEditing)), [config, mode]);
|
|
117770
|
-
const selectedComparisonProfiles = (0, react.useMemo)(() => comparisonProfiles.filter((profile) =>
|
|
117884
|
+
const selectedComparisonProfiles = (0, react.useMemo)(() => comparisonProfiles.filter((profile) => comparisonProviderKeys.includes(studioTargetKey(profile.provider, profile.channel))), [comparisonProfiles, comparisonProviderKeys]);
|
|
117771
117885
|
const comparisonResolutionOpts = (0, react.useMemo)(() => comparisonOutputOptions(selectedComparisonProfiles, ratio, "resolution"), [selectedComparisonProfiles, ratio]);
|
|
117772
117886
|
const comparisonGenerationQualityOpts = (0, react.useMemo)(() => localizeQualityOptions(comparisonOutputOptions(selectedComparisonProfiles, ratio, "generationQuality"), lang), [
|
|
117773
117887
|
selectedComparisonProfiles,
|
|
@@ -117776,12 +117890,12 @@ img.ProseMirror-separator {
|
|
|
117776
117890
|
]);
|
|
117777
117891
|
const comparisonResolution = comparisonResolutionOpts.some((option) => option.value === resolution) ? resolution : comparisonResolutionOpts[0]?.value ?? "standard";
|
|
117778
117892
|
const comparisonGenerationQuality = comparisonGenerationQualityOpts.some((option) => option.value === generationQuality) ? generationQuality : comparisonGenerationQualityOpts[0]?.value ?? "__default__";
|
|
117779
|
-
const comparisonTargets = (0, react.useMemo)(() => buildComparisonTargets(comparisonProfiles,
|
|
117893
|
+
const comparisonTargets = (0, react.useMemo)(() => buildComparisonTargets(comparisonProfiles, comparisonProviderKeys, ratio, quality, {
|
|
117780
117894
|
resolution: comparisonResolution,
|
|
117781
117895
|
generationQuality: comparisonGenerationQuality
|
|
117782
117896
|
}), [
|
|
117783
117897
|
comparisonProfiles,
|
|
117784
|
-
|
|
117898
|
+
comparisonProviderKeys,
|
|
117785
117899
|
ratio,
|
|
117786
117900
|
quality,
|
|
117787
117901
|
comparisonResolution,
|
|
@@ -117798,6 +117912,7 @@ img.ProseMirror-separator {
|
|
|
117798
117912
|
const comparisonRatioOpts = (0, react.useMemo)(() => localizeRatioOptions(comparisonOptionUnion(comparisonProfiles, "ratioOptions"), lang), [comparisonProfiles, lang]);
|
|
117799
117913
|
const applyProvider = (profile) => {
|
|
117800
117914
|
setProvider(profile.provider);
|
|
117915
|
+
setChannel(profile.channel);
|
|
117801
117916
|
setModel(profile.model);
|
|
117802
117917
|
setRatio(profile.defaultRatio);
|
|
117803
117918
|
setQuality(profile.defaultQuality);
|
|
@@ -117806,8 +117921,8 @@ img.ProseMirror-separator {
|
|
|
117806
117921
|
setWatermark("default");
|
|
117807
117922
|
setError(null);
|
|
117808
117923
|
};
|
|
117809
|
-
const changeProvider = (value) => {
|
|
117810
|
-
const profile = config?.providers.find((item) => item.provider === value);
|
|
117924
|
+
const changeProvider = (value, channelId) => {
|
|
117925
|
+
const profile = config?.providers.find((item) => item.provider === value && (channelId === void 0 || item.channel === channelId));
|
|
117811
117926
|
if (profile !== void 0) {
|
|
117812
117927
|
applyProvider(profile);
|
|
117813
117928
|
const providerMax = value === "dashscope" ? 3 : 5;
|
|
@@ -117821,6 +117936,10 @@ img.ProseMirror-separator {
|
|
|
117821
117936
|
}
|
|
117822
117937
|
}
|
|
117823
117938
|
};
|
|
117939
|
+
const changeProfile = (value) => {
|
|
117940
|
+
const profile = config?.providers.find((item) => studioTargetKey(item.provider, item.channel) === value);
|
|
117941
|
+
if (profile !== void 0) changeProvider(profile.provider, profile.channel);
|
|
117942
|
+
};
|
|
117824
117943
|
const resetFit = () => {
|
|
117825
117944
|
setFit(true);
|
|
117826
117945
|
setZoom(100);
|
|
@@ -117847,9 +117966,10 @@ img.ProseMirror-separator {
|
|
|
117847
117966
|
setMode("generate");
|
|
117848
117967
|
setComparisonEnabled(false);
|
|
117849
117968
|
setPrompt(item.prompt);
|
|
117850
|
-
const profile = config?.providers.find((entry) => entry.provider === item.provider);
|
|
117969
|
+
const profile = config?.providers.find((entry) => entry.provider === item.provider && (item.channel === void 0 || entry.channel === item.channel));
|
|
117851
117970
|
if (!profile) return;
|
|
117852
117971
|
applyProvider(profile);
|
|
117972
|
+
if (studioModelOptionsForMode(profile, "generate").some((option) => option.value === item.model)) setModel(item.model);
|
|
117853
117973
|
const nextRatio = profile.ratioOptions.some((option) => option.value === item.aspectRatio) ? item.aspectRatio : profile.defaultRatio;
|
|
117854
117974
|
setRatio(nextRatio);
|
|
117855
117975
|
if (profile.qualityOptions.some((option) => option.value === item.imageSize)) {
|
|
@@ -117998,7 +118118,7 @@ img.ProseMirror-separator {
|
|
|
117998
118118
|
const targetMax = targetItem.provider === "dashscope" ? 3 : 5;
|
|
117999
118119
|
if (referencesRef.current.some((r) => r.attachment?.attachmentId === targetAttId)) {
|
|
118000
118120
|
setMode("edit");
|
|
118001
|
-
changeProvider(targetItem.provider);
|
|
118121
|
+
changeProvider(targetItem.provider, targetItem.channel);
|
|
118002
118122
|
return;
|
|
118003
118123
|
}
|
|
118004
118124
|
if (referencesRef.current.length >= targetMax) {
|
|
@@ -118009,7 +118129,7 @@ img.ProseMirror-separator {
|
|
|
118009
118129
|
const blob = image.blob ?? await fetchAttachmentBlob(targetItem.attachment);
|
|
118010
118130
|
if (referencesRef.current.some((r) => r.attachment?.attachmentId === targetAttId)) {
|
|
118011
118131
|
setMode("edit");
|
|
118012
|
-
changeProvider(targetItem.provider);
|
|
118132
|
+
changeProvider(targetItem.provider, targetItem.channel);
|
|
118013
118133
|
return;
|
|
118014
118134
|
}
|
|
118015
118135
|
if (referencesRef.current.length >= targetMax) {
|
|
@@ -118027,7 +118147,7 @@ img.ProseMirror-separator {
|
|
|
118027
118147
|
referencesRef.current = nextList;
|
|
118028
118148
|
setError(null);
|
|
118029
118149
|
setMode("edit");
|
|
118030
|
-
changeProvider(targetItem.provider);
|
|
118150
|
+
changeProvider(targetItem.provider, targetItem.channel);
|
|
118031
118151
|
} catch {
|
|
118032
118152
|
setError(t("imageLoadFailed"));
|
|
118033
118153
|
}
|
|
@@ -118050,8 +118170,8 @@ img.ProseMirror-separator {
|
|
|
118050
118170
|
return;
|
|
118051
118171
|
}
|
|
118052
118172
|
if (config === null) return;
|
|
118053
|
-
const initial = initialComparisonProviders(comparisonProfiles, provider).filter((item) => mode !== "edit" || referencesRef.current.length <= 3 || item !== "dashscope");
|
|
118054
|
-
|
|
118173
|
+
const initial = initialComparisonProviders(comparisonProfiles, provider, channel).filter((item) => mode !== "edit" || referencesRef.current.length <= 3 || item !== "dashscope");
|
|
118174
|
+
setComparisonProviderKeys(initial);
|
|
118055
118175
|
if (![
|
|
118056
118176
|
"1:1",
|
|
118057
118177
|
"3:2",
|
|
@@ -118066,12 +118186,12 @@ img.ProseMirror-separator {
|
|
|
118066
118186
|
"4K"
|
|
118067
118187
|
].includes(quality)) setQuality("1K");
|
|
118068
118188
|
};
|
|
118069
|
-
const toggleComparisonProvider = (
|
|
118070
|
-
if (mode === "edit" &&
|
|
118189
|
+
const toggleComparisonProvider = (targetKey) => {
|
|
118190
|
+
if (mode === "edit" && targetKey === "dashscope" && referencesRef.current.length > 3 && !comparisonProviderKeys.includes(targetKey)) {
|
|
118071
118191
|
setError(t("maxReferencesExceeded", { max: "3" }));
|
|
118072
118192
|
return;
|
|
118073
118193
|
}
|
|
118074
|
-
|
|
118194
|
+
setComparisonProviderKeys((current) => current.includes(targetKey) ? current.filter((item) => item !== targetKey) : [...current, targetKey]);
|
|
118075
118195
|
setError(null);
|
|
118076
118196
|
};
|
|
118077
118197
|
const submit = async () => {
|
|
@@ -118105,7 +118225,8 @@ img.ProseMirror-separator {
|
|
|
118105
118225
|
body: JSON.stringify({
|
|
118106
118226
|
mode,
|
|
118107
118227
|
provider: target.profile.provider,
|
|
118108
|
-
|
|
118228
|
+
...target.profile.channel === void 0 ? {} : { channel: target.profile.channel },
|
|
118229
|
+
model: studioModelForMode(target.profile, mode),
|
|
118109
118230
|
prompt: prompt.trim(),
|
|
118110
118231
|
ratio: target.ratio,
|
|
118111
118232
|
quality: target.quality,
|
|
@@ -118135,6 +118256,7 @@ img.ProseMirror-separator {
|
|
|
118135
118256
|
attachment: value.payload.attachment,
|
|
118136
118257
|
prompt: value.payload.prompt,
|
|
118137
118258
|
provider: value.payload.provider,
|
|
118259
|
+
...value.payload.channel === void 0 ? {} : { channel: value.payload.channel },
|
|
118138
118260
|
model: value.payload.model,
|
|
118139
118261
|
createdAt: value.payload.createdAt + idx,
|
|
118140
118262
|
aspectRatio: value.target.ratio,
|
|
@@ -118174,10 +118296,11 @@ img.ProseMirror-separator {
|
|
|
118174
118296
|
body: JSON.stringify({
|
|
118175
118297
|
mode,
|
|
118176
118298
|
provider,
|
|
118177
|
-
model,
|
|
118299
|
+
model: requestModel,
|
|
118178
118300
|
prompt: prompt.trim(),
|
|
118179
118301
|
ratio,
|
|
118180
118302
|
quality: selectedQuality,
|
|
118303
|
+
...activeProfile.channel === void 0 ? {} : { channel: activeProfile.channel },
|
|
118181
118304
|
...selectedResolution === void 0 ? {} : { resolution: selectedResolution },
|
|
118182
118305
|
...provider === "openai-compat" ? { generationQuality: selectedGenerationQuality } : {},
|
|
118183
118306
|
...watermarkCapability.status === "supported" ? { watermark } : {},
|
|
@@ -118198,6 +118321,7 @@ img.ProseMirror-separator {
|
|
|
118198
118321
|
attachment: gen.attachment,
|
|
118199
118322
|
prompt: payload.prompt,
|
|
118200
118323
|
provider: payload.provider,
|
|
118324
|
+
...payload.channel === void 0 ? {} : { channel: payload.channel },
|
|
118201
118325
|
model: payload.model,
|
|
118202
118326
|
createdAt: payload.createdAt + idx,
|
|
118203
118327
|
aspectRatio: ratio,
|
|
@@ -118759,7 +118883,7 @@ img.ProseMirror-separator {
|
|
|
118759
118883
|
className: p.configured ? "is-configured" : "is-missing",
|
|
118760
118884
|
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
118761
118885
|
className: "dsh-ig-status-item-name",
|
|
118762
|
-
children: [(0, react_jsx_runtime.jsx)("strong", { children: p.label }), (0, react_jsx_runtime.jsx)("small", { children: p
|
|
118886
|
+
children: [(0, react_jsx_runtime.jsx)("strong", { children: p.label }), (0, react_jsx_runtime.jsx)("small", { children: studioModelForMode(p, mode) })]
|
|
118763
118887
|
}), (0, react_jsx_runtime.jsx)("span", {
|
|
118764
118888
|
className: "dsh-ig-status-item-tag",
|
|
118765
118889
|
children: isSubscriptionProvider(p.provider) ? p.configured ? t("subSignedIn") : t("subSignedOut") : p.configured ? t("configured") : t("unconfigured")
|
|
@@ -118883,7 +119007,7 @@ img.ProseMirror-separator {
|
|
|
118883
119007
|
children: (0, react_jsx_runtime.jsx)(Sparkles, { size: 28 })
|
|
118884
119008
|
}),
|
|
118885
119009
|
(0, react_jsx_runtime.jsx)("strong", { children: comparisonEnabled ? t("comparing", { count: String(comparisonTargets.length) }) : count > 1 ? t("generatingCount", { count: String(count) }) : t("generating") }),
|
|
118886
|
-
(0, react_jsx_runtime.jsx)("span", { children: comparisonEnabled ? comparisonTargets.map((target) => target.profile.label).join(" · ") : `${activeProfile?.label ?? ""} · ${
|
|
119010
|
+
(0, react_jsx_runtime.jsx)("span", { children: comparisonEnabled ? comparisonTargets.map((target) => target.profile.label).join(" · ") : `${activeProfile?.label ?? ""} · ${requestModel}` })
|
|
118887
119011
|
]
|
|
118888
119012
|
}) : currentBatch && currentBatch.length > 1 ? (0, react_jsx_runtime.jsx)("div", {
|
|
118889
119013
|
className: "dsh-ig-canvas-cluster",
|
|
@@ -119183,12 +119307,13 @@ img.ProseMirror-separator {
|
|
|
119183
119307
|
(0, react_jsx_runtime.jsx)("div", {
|
|
119184
119308
|
className: "dsh-ig-model-checks",
|
|
119185
119309
|
children: comparisonProfiles.map((item) => {
|
|
119186
|
-
const
|
|
119310
|
+
const targetKey = studioTargetKey(item.provider, item.channel);
|
|
119311
|
+
const target = comparisonTargets.find((candidate) => studioTargetKey(candidate.profile.provider, candidate.profile.channel) === targetKey);
|
|
119187
119312
|
return (0, react_jsx_runtime.jsxs)("button", {
|
|
119188
119313
|
type: "button",
|
|
119189
119314
|
className: target ? "is-selected" : "",
|
|
119190
119315
|
"aria-pressed": Boolean(target),
|
|
119191
|
-
onClick: () => toggleComparisonProvider(
|
|
119316
|
+
onClick: () => toggleComparisonProvider(targetKey),
|
|
119192
119317
|
children: [
|
|
119193
119318
|
(0, react_jsx_runtime.jsx)("span", {
|
|
119194
119319
|
className: "dsh-ig-model-checkmark",
|
|
@@ -119197,8 +119322,8 @@ img.ProseMirror-separator {
|
|
|
119197
119322
|
(0, react_jsx_runtime.jsxs)("span", {
|
|
119198
119323
|
className: "dsh-ig-model-copy",
|
|
119199
119324
|
children: [(0, react_jsx_runtime.jsx)("strong", { children: item.label }), (0, react_jsx_runtime.jsx)("small", {
|
|
119200
|
-
title: item
|
|
119201
|
-
children: item
|
|
119325
|
+
title: studioModelForMode(item, mode),
|
|
119326
|
+
children: studioModelForMode(item, mode)
|
|
119202
119327
|
})]
|
|
119203
119328
|
}),
|
|
119204
119329
|
target && (0, react_jsx_runtime.jsxs)("span", {
|
|
@@ -119211,7 +119336,7 @@ img.ProseMirror-separator {
|
|
|
119211
119336
|
].filter(Boolean).join(" · "), target.adjusted ? (0, react_jsx_runtime.jsx)("em", { children: t("compareAdjusted") }) : null]
|
|
119212
119337
|
})
|
|
119213
119338
|
]
|
|
119214
|
-
},
|
|
119339
|
+
}, targetKey);
|
|
119215
119340
|
})
|
|
119216
119341
|
}),
|
|
119217
119342
|
(0, react_jsx_runtime.jsx)("p", { children: t("compareParameterHint") })
|
|
@@ -119259,20 +119384,17 @@ img.ProseMirror-separator {
|
|
|
119259
119384
|
className: "dsh-ig-field-grid",
|
|
119260
119385
|
children: [(0, react_jsx_runtime.jsx)(FieldSelect, {
|
|
119261
119386
|
label: t("provider"),
|
|
119262
|
-
value: provider,
|
|
119263
|
-
onChange:
|
|
119387
|
+
value: studioTargetKey(provider, channel),
|
|
119388
|
+
onChange: changeProfile,
|
|
119264
119389
|
options: config.providers.map((item) => ({
|
|
119265
|
-
value: item.provider,
|
|
119390
|
+
value: studioTargetKey(item.provider, item.channel),
|
|
119266
119391
|
label: `${item.label}${item.configured ? "" : ` · ${t("unconfigured")}`}`
|
|
119267
119392
|
}))
|
|
119268
119393
|
}), (0, react_jsx_runtime.jsx)(FieldSelect, {
|
|
119269
119394
|
label: t("model"),
|
|
119270
|
-
value:
|
|
119395
|
+
value: requestModel,
|
|
119271
119396
|
onChange: setModel,
|
|
119272
|
-
options: activeProfile === void 0 ? [] :
|
|
119273
|
-
value: activeProfile.model,
|
|
119274
|
-
label: activeProfile.model
|
|
119275
|
-
}]
|
|
119397
|
+
options: activeProfile === void 0 ? [] : studioModelOptionsForMode(activeProfile, mode)
|
|
119276
119398
|
})]
|
|
119277
119399
|
}),
|
|
119278
119400
|
(0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -122277,6 +122399,7 @@ img.ProseMirror-separator {
|
|
|
122277
122399
|
return {
|
|
122278
122400
|
mode: "generate",
|
|
122279
122401
|
provider,
|
|
122402
|
+
...provider === "openai-compat" && image.channel !== void 0 ? { channel: image.channel } : {},
|
|
122280
122403
|
model: image.model,
|
|
122281
122404
|
prompt: prompt.trim(),
|
|
122282
122405
|
ratio: settings.ratio,
|
|
@@ -123027,6 +123150,7 @@ img.ProseMirror-separator {
|
|
|
123027
123150
|
attachment: payload.attachment,
|
|
123028
123151
|
prompt: payload.prompt,
|
|
123029
123152
|
provider: payload.provider,
|
|
123153
|
+
...payload.channel === void 0 ? {} : { channel: payload.channel },
|
|
123030
123154
|
model: payload.model,
|
|
123031
123155
|
createdAt: payload.createdAt,
|
|
123032
123156
|
aspectRatio: request.ratio,
|
|
@@ -124294,6 +124418,7 @@ img.ProseMirror-separator {
|
|
|
124294
124418
|
attachment,
|
|
124295
124419
|
prompt: stringValue(meta.prompt, "Generated Image"),
|
|
124296
124420
|
provider: stringValue(meta.provider, "google"),
|
|
124421
|
+
...typeof meta.channel === "string" ? { channel: meta.channel } : {},
|
|
124297
124422
|
model: stringValue(meta.model, ""),
|
|
124298
124423
|
output: stringValue(meta.output, ""),
|
|
124299
124424
|
...typeof meta.savedTo === "string" ? { savedTo: meta.savedTo } : {},
|
|
@@ -124960,7 +125085,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
124960
125085
|
function isRevision(value) {
|
|
124961
125086
|
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
124962
125087
|
const candidate = value;
|
|
124963
|
-
return isAttachment(candidate.attachment) && typeof candidate.provider === "string" && STUDIO_PROVIDERS.includes(candidate.provider) && typeof candidate.prompt === "string" && typeof candidate.model === "string" && typeof candidate.output === "string" && typeof candidate.createdAt === "number" && Number.isFinite(candidate.createdAt) && typeof candidate.ratio === "string" && typeof candidate.quality === "string" && (candidate.resolution === void 0 || typeof candidate.resolution === "string") && (candidate.generationQuality === void 0 || typeof candidate.generationQuality === "string") && (candidate.watermark === void 0 || STUDIO_WATERMARK_VALUES.some((value) => value === candidate.watermark));
|
|
125088
|
+
return isAttachment(candidate.attachment) && typeof candidate.provider === "string" && STUDIO_PROVIDERS.includes(candidate.provider) && (candidate.channel === void 0 || typeof candidate.channel === "string") && typeof candidate.prompt === "string" && typeof candidate.model === "string" && typeof candidate.output === "string" && typeof candidate.createdAt === "number" && Number.isFinite(candidate.createdAt) && typeof candidate.ratio === "string" && typeof candidate.quality === "string" && (candidate.resolution === void 0 || typeof candidate.resolution === "string") && (candidate.generationQuality === void 0 || typeof candidate.generationQuality === "string") && (candidate.watermark === void 0 || STUDIO_WATERMARK_VALUES.some((value) => value === candidate.watermark));
|
|
124964
125089
|
}
|
|
124965
125090
|
function isAttachment(value) {
|
|
124966
125091
|
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
@@ -125087,16 +125212,51 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125087
125212
|
function pillVisible(value) {
|
|
125088
125213
|
return value?.showProviderPill === true;
|
|
125089
125214
|
}
|
|
125215
|
+
const PILL_MODEL_FIELDS = {
|
|
125216
|
+
google: "googleModel",
|
|
125217
|
+
openai: "openaiModel",
|
|
125218
|
+
"openai-compat": "openaiCompatModel",
|
|
125219
|
+
seedream: "seedreamModel",
|
|
125220
|
+
dashscope: "dashscopeModel",
|
|
125221
|
+
xai: "xaiModel",
|
|
125222
|
+
zhipu: "zhipuModel"
|
|
125223
|
+
};
|
|
125224
|
+
const PILL_MODEL_OPTIONS_FIELDS = { "openai-compat": "openaiCompatModels" };
|
|
125090
125225
|
/** Model (or ComfyUI workflow) a provider row will use with the persisted settings. */
|
|
125091
|
-
function pillModelOf(provider, value) {
|
|
125226
|
+
function pillModelOf(provider, value, channelId) {
|
|
125092
125227
|
if (provider === "comfyui") {
|
|
125093
125228
|
const workflow = activeComfyUIWorkflow(value ?? {});
|
|
125094
125229
|
return workflow === void 0 ? "" : workflow.name;
|
|
125095
125230
|
}
|
|
125096
125231
|
if (SUBSCRIPTION_PROVIDERS.includes(provider)) return DEFAULT_MODELS[provider];
|
|
125097
|
-
|
|
125232
|
+
if (provider === "openai-compat") {
|
|
125233
|
+
const channel = resolveOpenAICompatChannel(value ?? {}, channelId);
|
|
125234
|
+
return channel.model.trim().length > 0 ? channel.model.trim() : DEFAULT_MODELS[provider];
|
|
125235
|
+
}
|
|
125236
|
+
const field = PILL_MODEL_FIELDS[provider];
|
|
125237
|
+
const stored = field === void 0 ? void 0 : value?.[field];
|
|
125098
125238
|
return typeof stored === "string" && stored.length > 0 ? stored : DEFAULT_MODELS[provider];
|
|
125099
125239
|
}
|
|
125240
|
+
/** Optional model choices exposed by a provider; single-model providers return an empty list. */
|
|
125241
|
+
function pillModelOptionsOf(provider, value, channelId) {
|
|
125242
|
+
if (provider === "openai-compat") {
|
|
125243
|
+
const channel = resolveOpenAICompatChannel(value ?? {}, channelId);
|
|
125244
|
+
return resolveOpenAICompatModels({
|
|
125245
|
+
openaiCompatModel: pillModelOf(provider, value, channel.id),
|
|
125246
|
+
openaiCompatModels: channel.models ?? []
|
|
125247
|
+
});
|
|
125248
|
+
}
|
|
125249
|
+
const field = PILL_MODEL_OPTIONS_FIELDS[provider];
|
|
125250
|
+
if (field === void 0) return [];
|
|
125251
|
+
const configured = value?.[field];
|
|
125252
|
+
const models = Array.isArray(configured) ? [...new Set(configured.filter((model) => typeof model === "string").map((model) => model.trim()).filter(Boolean))] : [];
|
|
125253
|
+
const defaultModel = pillModelOf(provider, value);
|
|
125254
|
+
if (defaultModel.length > 0 && !models.includes(defaultModel)) models.unshift(defaultModel);
|
|
125255
|
+
return models;
|
|
125256
|
+
}
|
|
125257
|
+
function pillTargetKey(provider, channelId) {
|
|
125258
|
+
return provider === "openai-compat" ? `openai-compat:${channelId ?? "default"}` : provider;
|
|
125259
|
+
}
|
|
125100
125260
|
/** One fixed-position provider menu anchored to the pill button. */
|
|
125101
125261
|
function ImageProviderPill(props) {
|
|
125102
125262
|
const [snapshot, setSnapshot] = (0, react.useState)(() => props.scope.getSnapshot());
|
|
@@ -125104,15 +125264,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125104
125264
|
const [open, setOpen] = (0, react.useState)(false);
|
|
125105
125265
|
const [pending, setPending] = (0, react.useState)(void 0);
|
|
125106
125266
|
const [error, setError] = (0, react.useState)("");
|
|
125107
|
-
const [dots, setDots] = (0, react.useState)({
|
|
125108
|
-
google: "unknown",
|
|
125109
|
-
openai: "unknown",
|
|
125110
|
-
"openai-compat": "unknown",
|
|
125111
|
-
seedream: "unknown",
|
|
125112
|
-
dashscope: "unknown",
|
|
125113
|
-
xai: "unknown",
|
|
125114
|
-
zhipu: "unknown"
|
|
125115
|
-
});
|
|
125267
|
+
const [dots, setDots] = (0, react.useState)({});
|
|
125116
125268
|
const [keyTick, setKeyTick] = (0, react.useState)(0);
|
|
125117
125269
|
const [subDots, setSubDots] = (0, react.useState)(() => ({
|
|
125118
125270
|
"chatgpt-sub": "unknown",
|
|
@@ -125132,35 +125284,33 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125132
125284
|
}), [props.credentialEvents]);
|
|
125133
125285
|
(0, react.useEffect)(() => {
|
|
125134
125286
|
let active = true;
|
|
125135
|
-
const
|
|
125136
|
-
|
|
125137
|
-
|
|
125138
|
-
|
|
125139
|
-
|
|
125140
|
-
|
|
125287
|
+
const targets = [...CLOUD_IMAGE_PROVIDERS.filter((provider) => provider !== "openai-compat").map((provider) => ({
|
|
125288
|
+
key: provider,
|
|
125289
|
+
ref: cloudCredentialRef(provider)
|
|
125290
|
+
})), ...resolveOpenAICompatChannels(snapshot.value ?? {}).map((channel) => ({
|
|
125291
|
+
key: pillTargetKey("openai-compat", channel.id),
|
|
125292
|
+
ref: channel.keyRef
|
|
125293
|
+
}))];
|
|
125294
|
+
props.credentials.describe(targets.map((target) => target.ref)).then((response) => {
|
|
125141
125295
|
if (!active) return;
|
|
125142
125296
|
const next = {};
|
|
125143
|
-
for (const
|
|
125144
|
-
const info = response.ok ? response.value?.[
|
|
125145
|
-
next[
|
|
125297
|
+
for (const target of targets) {
|
|
125298
|
+
const info = response.ok ? response.value?.[target.ref] : void 0;
|
|
125299
|
+
next[target.key] = response.ok ? info?.configured ? "configured" : "missing" : "unknown";
|
|
125146
125300
|
}
|
|
125147
125301
|
setDots(next);
|
|
125148
125302
|
}).catch(() => {
|
|
125149
125303
|
if (!active) return;
|
|
125150
|
-
setDots({
|
|
125151
|
-
google: "unknown",
|
|
125152
|
-
openai: "unknown",
|
|
125153
|
-
"openai-compat": "unknown",
|
|
125154
|
-
seedream: "unknown",
|
|
125155
|
-
dashscope: "unknown",
|
|
125156
|
-
xai: "unknown",
|
|
125157
|
-
zhipu: "unknown"
|
|
125158
|
-
});
|
|
125304
|
+
setDots({});
|
|
125159
125305
|
});
|
|
125160
125306
|
return () => {
|
|
125161
125307
|
active = false;
|
|
125162
125308
|
};
|
|
125163
|
-
}, [
|
|
125309
|
+
}, [
|
|
125310
|
+
props.credentials,
|
|
125311
|
+
keyTick,
|
|
125312
|
+
snapshot.value
|
|
125313
|
+
]);
|
|
125164
125314
|
(0, react.useEffect)(() => {
|
|
125165
125315
|
if (!open) return;
|
|
125166
125316
|
let active = true;
|
|
@@ -125188,6 +125338,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125188
125338
|
}, [open, keyTick]);
|
|
125189
125339
|
const t = (keyName) => (lang === "en" ? PILL_DICT.en : PILL_DICT.zh)[keyName];
|
|
125190
125340
|
const current = snapshot.value?.provider ?? "google";
|
|
125341
|
+
const currentChannel = current === "openai-compat" ? resolveOpenAICompatChannel(snapshot.value ?? {}) : void 0;
|
|
125191
125342
|
const writable = snapshot.writable;
|
|
125192
125343
|
(0, react.useEffect)(() => {
|
|
125193
125344
|
if (!open) {
|
|
@@ -125235,15 +125386,27 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125235
125386
|
};
|
|
125236
125387
|
}, [open]);
|
|
125237
125388
|
if (!pillVisible(snapshot.value)) return null;
|
|
125238
|
-
|
|
125239
|
-
|
|
125240
|
-
|
|
125389
|
+
const select = (provider, model, channelId) => {
|
|
125390
|
+
const currentModel = pillModelOf(provider, snapshot.value, channelId);
|
|
125391
|
+
const sameChannel = provider !== "openai-compat" || currentChannel?.id === (channelId ?? "default");
|
|
125392
|
+
if (pending !== void 0 || provider === current && sameChannel && (model === void 0 || model === currentModel)) {
|
|
125241
125393
|
setOpen(false);
|
|
125242
125394
|
return;
|
|
125243
125395
|
}
|
|
125396
|
+
const modelField = model === void 0 ? void 0 : PILL_MODEL_FIELDS[provider];
|
|
125244
125397
|
setError("");
|
|
125245
125398
|
setPending(provider);
|
|
125246
|
-
|
|
125399
|
+
(async () => {
|
|
125400
|
+
if (model !== void 0 && provider === "openai-compat" && channelId !== void 0 && channelId !== "default") {
|
|
125401
|
+
const channels = (snapshot.value?.openaiCompatChannels ?? []).map((channel) => channel.id === channelId ? {
|
|
125402
|
+
...channel,
|
|
125403
|
+
model
|
|
125404
|
+
} : channel);
|
|
125405
|
+
await writeSetting(props.scope, "openaiCompatChannels", channels, t("writeRejected"));
|
|
125406
|
+
} else if (model !== void 0 && modelField !== void 0) await writeSetting(props.scope, modelField, model, t("writeRejected"));
|
|
125407
|
+
if (provider === "openai-compat" && channelId !== void 0 && currentChannel?.id !== channelId) await writeSetting(props.scope, "openaiCompatActiveChannel", channelId, t("writeRejected"));
|
|
125408
|
+
if (provider !== current) await writeSetting(props.scope, "provider", provider, t("writeRejected"));
|
|
125409
|
+
})().then(() => {
|
|
125247
125410
|
setOpen(false);
|
|
125248
125411
|
}).catch((cause) => {
|
|
125249
125412
|
setError(cause instanceof Error ? cause.message : String(cause));
|
|
@@ -125254,13 +125417,13 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125254
125417
|
/** Plan A dots: ComfyUI is always fixed blue (theme-independent); each
|
|
125255
125418
|
* subscription reflects its login state (green in, gray out); cloud rows
|
|
125256
125419
|
* reflect their API-key state as before. */
|
|
125257
|
-
const dotClassOf = (provider) => {
|
|
125420
|
+
const dotClassOf = (provider, channelId) => {
|
|
125258
125421
|
if (provider === "comfyui") return "dsh-ig-pill-dot-neutral";
|
|
125259
125422
|
if (isSubscriptionProvider(provider)) return subDots[provider] === "logged-in" ? "dsh-ig-pill-dot-ok" : "dsh-ig-pill-dot-missing";
|
|
125260
|
-
const dot = dots[provider];
|
|
125423
|
+
const dot = dots[pillTargetKey(provider, channelId)];
|
|
125261
125424
|
return dot === "configured" ? "dsh-ig-pill-dot-ok" : dot === "missing" ? "dsh-ig-pill-dot-missing" : "dsh-ig-pill-dot-neutral";
|
|
125262
125425
|
};
|
|
125263
|
-
const subtitleOf = (provider) => {
|
|
125426
|
+
const subtitleOf = (provider, includeModel = true, channelId) => {
|
|
125264
125427
|
if (provider === "comfyui") {
|
|
125265
125428
|
const workflow = pillModelOf(provider, snapshot.value);
|
|
125266
125429
|
return workflow.length > 0 ? `${t("noKeyNeeded")} · ${workflow}` : `${t("noKeyNeeded")} · ${t("noWorkflow")}`;
|
|
@@ -125270,12 +125433,17 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125270
125433
|
const stateText = state === "logged-in" ? t("subSignedIn") : state === "logged-out" ? t("subSignedOut") : t("subStatusUnknown");
|
|
125271
125434
|
return `${t("subNoKey")} · ${stateText} · ${pillModelOf(provider, snapshot.value)}`;
|
|
125272
125435
|
}
|
|
125273
|
-
const dot = dots[provider];
|
|
125274
|
-
const model = pillModelOf(provider, snapshot.value);
|
|
125275
|
-
|
|
125276
|
-
if (dot === "
|
|
125277
|
-
return
|
|
125436
|
+
const dot = dots[pillTargetKey(provider, channelId)];
|
|
125437
|
+
const model = pillModelOf(provider, snapshot.value, channelId);
|
|
125438
|
+
const modelSuffix = includeModel ? ` · ${model}` : "";
|
|
125439
|
+
if (dot === "configured") return `${t("keyConfigured")}${modelSuffix}`;
|
|
125440
|
+
if (dot === "missing") return `${t("keyMissing")}${modelSuffix}`;
|
|
125441
|
+
return includeModel ? model : "";
|
|
125278
125442
|
};
|
|
125443
|
+
const menuEntries = IMAGE_PROVIDERS.flatMap((provider) => provider === "openai-compat" ? resolveOpenAICompatChannels(snapshot.value ?? {}).map((channel) => ({
|
|
125444
|
+
provider,
|
|
125445
|
+
channel
|
|
125446
|
+
})) : [{ provider }]);
|
|
125279
125447
|
return (0, react_jsx_runtime.jsxs)("div", {
|
|
125280
125448
|
className: "dsh-ig-pill-root",
|
|
125281
125449
|
children: [(0, react_jsx_runtime.jsxs)("button", {
|
|
@@ -125319,7 +125487,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125319
125487
|
}),
|
|
125320
125488
|
(0, react_jsx_runtime.jsx)("span", {
|
|
125321
125489
|
className: "dsh-ig-pill-provider",
|
|
125322
|
-
children: PILL_PROVIDER_LABELS[lang][current]
|
|
125490
|
+
children: currentChannel?.label ?? PILL_PROVIDER_LABELS[lang][current]
|
|
125323
125491
|
}),
|
|
125324
125492
|
(0, react_jsx_runtime.jsx)("span", {
|
|
125325
125493
|
className: `dsh-ig-pill-caret${open ? " dsh-ig-pill-caret-open" : ""}`,
|
|
@@ -125347,47 +125515,83 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125347
125515
|
className: "dsh-ig-pill-menu-title",
|
|
125348
125516
|
children: t("menuTitle")
|
|
125349
125517
|
}),
|
|
125350
|
-
|
|
125351
|
-
|
|
125352
|
-
|
|
125353
|
-
"
|
|
125354
|
-
|
|
125355
|
-
|
|
125356
|
-
|
|
125357
|
-
|
|
125358
|
-
|
|
125359
|
-
|
|
125360
|
-
|
|
125361
|
-
|
|
125362
|
-
|
|
125363
|
-
}
|
|
125364
|
-
|
|
125365
|
-
|
|
125518
|
+
menuEntries.map(({ provider, channel }) => {
|
|
125519
|
+
const channelId = channel?.id;
|
|
125520
|
+
const modelOptions = pillModelOptionsOf(provider, snapshot.value, channelId);
|
|
125521
|
+
const active = provider === current && (provider !== "openai-compat" || currentChannel?.id === channelId);
|
|
125522
|
+
const currentModel = active ? pillModelOf(provider, snapshot.value, channelId) : "";
|
|
125523
|
+
return (0, react_jsx_runtime.jsxs)(react.Fragment, { children: [(0, react_jsx_runtime.jsxs)("button", {
|
|
125524
|
+
type: "button",
|
|
125525
|
+
role: modelOptions.length > 0 ? "menuitem" : "menuitemradio",
|
|
125526
|
+
"aria-checked": modelOptions.length > 0 ? void 0 : active,
|
|
125527
|
+
className: `dsh-ig-pill-option${active ? " dsh-ig-pill-option-active" : ""}`,
|
|
125528
|
+
disabled: pending !== void 0,
|
|
125529
|
+
onClick: () => {
|
|
125530
|
+
select(provider, void 0, channelId);
|
|
125531
|
+
},
|
|
125532
|
+
children: [
|
|
125533
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
125534
|
+
className: `dsh-ig-pill-dot ${dotClassOf(provider, channelId)}`,
|
|
125535
|
+
"aria-hidden": "true"
|
|
125536
|
+
}),
|
|
125537
|
+
(0, react_jsx_runtime.jsxs)("span", {
|
|
125538
|
+
className: "dsh-ig-pill-option-text",
|
|
125539
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
125540
|
+
className: "dsh-ig-pill-option-name",
|
|
125541
|
+
children: channel?.label ?? PILL_PROVIDER_LABELS[lang][provider]
|
|
125542
|
+
}), (0, react_jsx_runtime.jsx)("span", {
|
|
125543
|
+
className: "dsh-ig-pill-option-sub",
|
|
125544
|
+
children: subtitleOf(provider, modelOptions.length === 0, channelId)
|
|
125545
|
+
})]
|
|
125546
|
+
}),
|
|
125547
|
+
active && modelOptions.length === 0 ? (0, react_jsx_runtime.jsx)("span", {
|
|
125548
|
+
className: "dsh-ig-pill-check",
|
|
125549
|
+
"aria-hidden": "true",
|
|
125550
|
+
children: (0, react_jsx_runtime.jsx)("svg", {
|
|
125551
|
+
width: "13",
|
|
125552
|
+
height: "13",
|
|
125553
|
+
viewBox: "0 0 16 16",
|
|
125554
|
+
fill: "none",
|
|
125555
|
+
stroke: "currentColor",
|
|
125556
|
+
strokeWidth: "2.2",
|
|
125557
|
+
strokeLinecap: "round",
|
|
125558
|
+
strokeLinejoin: "round",
|
|
125559
|
+
children: (0, react_jsx_runtime.jsx)("path", { d: "M2.5 8.5l3.5 3.5 7-8" })
|
|
125560
|
+
})
|
|
125561
|
+
}) : null
|
|
125562
|
+
]
|
|
125563
|
+
}), modelOptions.map((model) => {
|
|
125564
|
+
const selected = active && model === currentModel;
|
|
125565
|
+
return (0, react_jsx_runtime.jsxs)("button", {
|
|
125566
|
+
type: "button",
|
|
125567
|
+
role: "menuitemradio",
|
|
125568
|
+
"aria-checked": selected,
|
|
125569
|
+
className: `dsh-ig-pill-option dsh-ig-pill-model-option${selected ? " dsh-ig-pill-option-active" : ""}`,
|
|
125570
|
+
disabled: pending !== void 0,
|
|
125571
|
+
onClick: () => {
|
|
125572
|
+
select(provider, model, channelId);
|
|
125573
|
+
},
|
|
125366
125574
|
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
125367
|
-
className: "dsh-ig-pill-
|
|
125368
|
-
children:
|
|
125369
|
-
}), (0, react_jsx_runtime.jsx)("span", {
|
|
125370
|
-
className: "dsh-ig-pill-
|
|
125371
|
-
|
|
125372
|
-
|
|
125373
|
-
|
|
125374
|
-
|
|
125375
|
-
|
|
125376
|
-
|
|
125377
|
-
|
|
125378
|
-
|
|
125379
|
-
|
|
125380
|
-
|
|
125381
|
-
|
|
125382
|
-
|
|
125383
|
-
|
|
125384
|
-
|
|
125385
|
-
|
|
125386
|
-
|
|
125387
|
-
})
|
|
125388
|
-
}) : null
|
|
125389
|
-
]
|
|
125390
|
-
}, provider)),
|
|
125575
|
+
className: "dsh-ig-pill-model-name",
|
|
125576
|
+
children: model
|
|
125577
|
+
}), selected ? (0, react_jsx_runtime.jsx)("span", {
|
|
125578
|
+
className: "dsh-ig-pill-check",
|
|
125579
|
+
"aria-hidden": "true",
|
|
125580
|
+
children: (0, react_jsx_runtime.jsx)("svg", {
|
|
125581
|
+
width: "13",
|
|
125582
|
+
height: "13",
|
|
125583
|
+
viewBox: "0 0 16 16",
|
|
125584
|
+
fill: "none",
|
|
125585
|
+
stroke: "currentColor",
|
|
125586
|
+
strokeWidth: "2.2",
|
|
125587
|
+
strokeLinecap: "round",
|
|
125588
|
+
strokeLinejoin: "round",
|
|
125589
|
+
children: (0, react_jsx_runtime.jsx)("path", { d: "M2.5 8.5l3.5 3.5 7-8" })
|
|
125590
|
+
})
|
|
125591
|
+
}) : null]
|
|
125592
|
+
}, model);
|
|
125593
|
+
})] }, channelId === void 0 ? provider : pillTargetKey("openai-compat", channelId));
|
|
125594
|
+
}),
|
|
125391
125595
|
error.length > 0 ? (0, react_jsx_runtime.jsxs)("div", {
|
|
125392
125596
|
className: "dsh-ig-pill-error",
|
|
125393
125597
|
role: "alert",
|
|
@@ -125431,12 +125635,14 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125431
125635
|
.dsh-ig-pill-option-text{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
|
|
125432
125636
|
.dsh-ig-pill-option-name{font-size:12.5px;font-weight:500;color:var(--dsw-alias-label-primary,#111827);line-height:1.2}
|
|
125433
125637
|
.dsh-ig-pill-option-sub{font-size:11px;color:var(--dsw-alias-label-tertiary,#6b7280);line-height:1.2;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
125638
|
+
.dsh-ig-pill-model-option{padding-left:24px}
|
|
125639
|
+
.dsh-ig-pill-model-name{flex:1;min-width:0;font-size:12px;color:var(--dsw-alias-label-secondary,#4b5563);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
125434
125640
|
.dsh-ig-pill-check{flex:none;color:var(--dsw-alias-brand-primary,#4c78ff)}
|
|
125435
125641
|
.dsh-ig-pill-error{margin-top:4px;padding:6px 8px;border-radius:8px;background:rgba(239,68,68,.08);color:#ef4444;font-size:11.5px;line-height:1.4;word-break:break-all}
|
|
125436
125642
|
`;
|
|
125437
125643
|
//#endregion
|
|
125438
125644
|
//#region lib/types/client/index.js
|
|
125439
|
-
console.info(`[dsh-image-gen] canvas bundle 2026-10-
|
|
125645
|
+
console.info(`[dsh-image-gen] canvas bundle 2026-10-28T11:56:09.512Z`);
|
|
125440
125646
|
/** Right-sidebar tab-type registration id (DSH 0.1.5 `sidebarRightTabs`). */
|
|
125441
125647
|
const SIDEBAR_STUDIO_TAB_ID = "dsh-image-gen/studio";
|
|
125442
125648
|
/** The tab kind: a page type opened by kind, recognizing no resource address. */
|
|
@@ -125455,6 +125661,11 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125455
125661
|
providerGoogle: "Google Gemini",
|
|
125456
125662
|
providerOpenAI: "OpenAI",
|
|
125457
125663
|
providerOpenAICompat: "OpenAI 兼容(中转站)",
|
|
125664
|
+
addCompatChannel: "新增 OpenAI 兼容渠道",
|
|
125665
|
+
channelName: "渠道名称",
|
|
125666
|
+
channelNameRequired: "请填写渠道名称。",
|
|
125667
|
+
removeChannel: "删除渠道",
|
|
125668
|
+
removeChannelConfirm: "确定删除“{label}”吗?该渠道的配置将被移除。",
|
|
125458
125669
|
providerSeedream: "字节 Seedream",
|
|
125459
125670
|
providerDashScope: "阿里 DashScope (通义万相 / Qwen)",
|
|
125460
125671
|
providerXAI: "xAI Grok Imagine",
|
|
@@ -125519,11 +125730,15 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125519
125730
|
endpointHintOpenAI: "官方 api.openai.com 的 /v1 地址;中转站请使用下方「OpenAI 兼容」行。",
|
|
125520
125731
|
endpointHintOpenAICompat: "中转站/自建服务的 OpenAI 兼容 /v1 地址(必填),例如 https://your-relay.example.com/v1。",
|
|
125521
125732
|
editFormat: "图生图请求形态",
|
|
125733
|
+
editModel: "图生图模型(可选)",
|
|
125734
|
+
editModelHint: "留空沿用上方模型。硅基流动可分别填写 Qwen/Qwen-Image(文生图)和 Qwen/Qwen-Image-Edit(图生图)。",
|
|
125735
|
+
editFormatSiliconFlow: "硅基流动 JSON(image 字符串)",
|
|
125736
|
+
editFormatSiliconFlowHint: "编辑尺寸由参考图决定,不发送尺寸和质量字段。Qwen-Image-Edit 支持一张图,Edit-2509 最多三张;参考图字段由插件填入。",
|
|
125522
125737
|
editFormatMultipart: "标准 multipart(OpenAI 官方)",
|
|
125523
125738
|
editFormatAutomatic: "自动:官方接口 JSON 格式",
|
|
125524
125739
|
editFormatJsonImageUrlArray: "JSON images 数组(商汤等中转)",
|
|
125525
125740
|
editFormatFormReferenceImages: "multipart + reference_images JSON 数组(base64)",
|
|
125526
|
-
editFormatHint: "
|
|
125741
|
+
editFormatHint: "商汤、通义、硅基流动已确认的官方接口自动使用对应 JSON 格式;其他中转按接口文档选择。文生图不受影响。",
|
|
125527
125742
|
editExtra: "附加 JSON 字段",
|
|
125528
125743
|
editExtraPlaceholder: "{\"watermark\": false, \"prompt_extend\": true}",
|
|
125529
125744
|
editExtraHint: "仅 JSON 形态生效;会合并到请求体末尾,可覆盖默认字段。留空表示不附加。",
|
|
@@ -125557,6 +125772,10 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125557
125772
|
endpointHintZhipu: "智谱开放平台 open.bigmodel.cn 的 /api/paas/v4 地址。",
|
|
125558
125773
|
endpointHintComfyUI: "正在运行且 DSH Host 可以访问的 ComfyUI 地址,默认使用本机 8188 端口。",
|
|
125559
125774
|
model: "模型",
|
|
125775
|
+
defaultModel: "默认模型",
|
|
125776
|
+
availableModels: "工作台可选模型",
|
|
125777
|
+
availableModelsHint: "勾选后可在工作台切换。手动输入的默认模型会自动加入列表,且不可移除。",
|
|
125778
|
+
defaultModelTag: "默认",
|
|
125560
125779
|
workflow: "API Workflow 工作流",
|
|
125561
125780
|
workflowImport: "导入 JSON 文件",
|
|
125562
125781
|
workflowMissing: "尚未导入工作流",
|
|
@@ -125571,6 +125790,8 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125571
125790
|
workflowDuplicateName: "工作流名称不能重复。",
|
|
125572
125791
|
timeout: "生成超时(秒)",
|
|
125573
125792
|
timeoutHint: "包括提交、等待和下载图片;默认 300 秒。",
|
|
125793
|
+
cloudTimeout: "云端生成超时(秒)",
|
|
125794
|
+
cloudTimeoutHint: "工作台所有 API Key 通道共用,5–3600 秒,默认 150 秒。不影响订阅通道和 ComfyUI;修改后对新请求生效。",
|
|
125574
125795
|
workspaceSection: "工作区",
|
|
125575
125796
|
saveToWorkspace: "保存到工作区",
|
|
125576
125797
|
saveToWorkspaceHint: "每次生成后,把图片文件保存到当前会话工作区。",
|
|
@@ -125624,7 +125845,12 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125624
125845
|
settingsIncompatible: "The loaded settings library cannot save these settings. Update @deepseek-ai/schemastery in the plugin environment to 3.18.4 or a compatible 3.x version, then restart DSH.",
|
|
125625
125846
|
providerGoogle: "Google Gemini",
|
|
125626
125847
|
providerOpenAI: "OpenAI",
|
|
125627
|
-
providerOpenAICompat: "OpenAI
|
|
125848
|
+
providerOpenAICompat: "OpenAI Compatible (relay)",
|
|
125849
|
+
addCompatChannel: "Add OpenAI-compatible channel",
|
|
125850
|
+
channelName: "Channel name",
|
|
125851
|
+
channelNameRequired: "Enter a channel name.",
|
|
125852
|
+
removeChannel: "Remove channel",
|
|
125853
|
+
removeChannelConfirm: "Remove \"{label}\"? Its channel configuration will be deleted.",
|
|
125628
125854
|
providerSeedream: "ByteDance Seedream",
|
|
125629
125855
|
providerDashScope: "Aliyun DashScope (Wanx / Qwen)",
|
|
125630
125856
|
providerXAI: "xAI Grok Imagine",
|
|
@@ -125689,11 +125915,15 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125689
125915
|
endpointHintOpenAI: "Official api.openai.com /v1 base URL; for relays use the \"OpenAI-compatible\" row below.",
|
|
125690
125916
|
endpointHintOpenAICompat: "OpenAI-compatible /v1 base URL of your relay or self-hosted service (required), e.g. https://your-relay.example.com/v1.",
|
|
125691
125917
|
editFormat: "Edit request format",
|
|
125918
|
+
editModel: "Editing model (optional)",
|
|
125919
|
+
editModelHint: "Leave empty to reuse the model above. SiliconFlow can use Qwen/Qwen-Image for generation and Qwen/Qwen-Image-Edit for editing.",
|
|
125920
|
+
editFormatSiliconFlow: "SiliconFlow JSON (image string)",
|
|
125921
|
+
editFormatSiliconFlowHint: "Edit dimensions follow the reference; size and quality fields are omitted. Qwen-Image-Edit supports one reference, Edit-2509 up to three. The plugin fills the image fields.",
|
|
125692
125922
|
editFormatMultipart: "Standard multipart (official OpenAI)",
|
|
125693
125923
|
editFormatAutomatic: "Automatic: official JSON contract",
|
|
125694
125924
|
editFormatJsonImageUrlArray: "JSON images array (SenseNova etc.)",
|
|
125695
125925
|
editFormatFormReferenceImages: "Multipart with a reference_images JSON array (base64)",
|
|
125696
|
-
editFormatHint: "Recognized official SenseNova and
|
|
125926
|
+
editFormatHint: "Recognized official SenseNova, Qwen and SiliconFlow endpoints automatically use their JSON edit contracts. Choose other relay formats according to their documentation. Text-to-image is unaffected.",
|
|
125697
125927
|
editExtra: "Extra JSON fields",
|
|
125698
125928
|
editExtraPlaceholder: "{\"watermark\": false, \"prompt_extend\": true}",
|
|
125699
125929
|
editExtraHint: "Only used with the JSON format; merged into the request body last and may override defaults. Leave empty for none.",
|
|
@@ -125727,6 +125957,10 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125727
125957
|
endpointHintZhipu: "Zhipu open.bigmodel.cn /api/paas/v4 base URL.",
|
|
125728
125958
|
endpointHintComfyUI: "A running ComfyUI server reachable by the DSH Host; the default points to port 8188 on this computer.",
|
|
125729
125959
|
model: "Model",
|
|
125960
|
+
defaultModel: "Default model",
|
|
125961
|
+
availableModels: "Models available in Studio",
|
|
125962
|
+
availableModelsHint: "Selected models can be switched in Studio. A manually entered default is added automatically and cannot be removed.",
|
|
125963
|
+
defaultModelTag: "Default",
|
|
125730
125964
|
workflow: "API Workflows",
|
|
125731
125965
|
workflowImport: "Import JSON file",
|
|
125732
125966
|
workflowMissing: "No workflow imported",
|
|
@@ -125741,6 +125975,8 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125741
125975
|
workflowDuplicateName: "Workflow names must be unique.",
|
|
125742
125976
|
timeout: "Generation timeout (seconds)",
|
|
125743
125977
|
timeoutHint: "Covers submission, waiting, and image download; defaults to 300 seconds.",
|
|
125978
|
+
cloudTimeout: "Cloud generation timeout (seconds)",
|
|
125979
|
+
cloudTimeoutHint: "Shared by all API-key channels in the workbench, 5–3600 seconds; defaults to 150 seconds. Does not affect subscription channels or ComfyUI; applies to new requests.",
|
|
125744
125980
|
workspaceSection: "Workspace",
|
|
125745
125981
|
saveToWorkspace: "Save to workspace",
|
|
125746
125982
|
saveToWorkspaceHint: "Write each generated image as a file into the session workspace.",
|
|
@@ -125817,6 +126053,10 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125817
126053
|
.dsh-ig-actions{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:16px;padding-top:12px;border-top:1px solid var(--dsw-alias-border-l2,#eee)}
|
|
125818
126054
|
.dsh-ig-check-row{display:flex;align-items:center;gap:8px;cursor:pointer}
|
|
125819
126055
|
.dsh-ig-check-row input[type=checkbox]{width:15px;height:15px;accent-color:var(--dsw-alias-brand-primary,#4c78ff);margin:0}
|
|
126056
|
+
.dsh-ig-model-picker{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:8px 12px;max-height:180px;overflow-y:auto;padding:2px 0}
|
|
126057
|
+
.dsh-ig-model-picker .dsh-ig-check-row{min-width:0}
|
|
126058
|
+
.dsh-ig-model-option{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:12px}
|
|
126059
|
+
.dsh-ig-model-default{flex:none;color:var(--dsw-alias-label-tertiary,#7b818b);font-size:11px}
|
|
125820
126060
|
.dsh-ig-savedto{font-size:12px;line-height:1.5;color:var(--dsw-alias-label-tertiary,#7b818b);word-break:break-all}
|
|
125821
126061
|
.dsh-ig-save{appearance:none;border:0;border-radius:var(--dsw-radius-md,6px);padding:5px 14px;background:var(--dsw-alias-label-primary,#111827);color:var(--dsw-alias-bg-layer-3,#fff);font:inherit;font-size:13px;font-weight:400;cursor:pointer;transition:opacity .15s}
|
|
125822
126062
|
.dsh-ig-save:disabled{opacity:.4;cursor:default}
|
|
@@ -125825,7 +126065,9 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125825
126065
|
.dsh-ig-providers{display:flex;flex-direction:column;margin-top:6px}
|
|
125826
126066
|
.dsh-ig-provider-row{border:0;background:none;padding:14px 0}
|
|
125827
126067
|
.dsh-ig-provider-row + .dsh-ig-provider-row{border-top:0.5px solid var(--dsw-alias-border-l2,#e8ebf0)}
|
|
125828
|
-
.dsh-ig-provider-head{
|
|
126068
|
+
.dsh-ig-provider-head-row{display:flex;align-items:center;gap:10px}
|
|
126069
|
+
.dsh-ig-provider-head{flex:1;min-width:0;width:100%;appearance:none;border:0;background:none;font:inherit;color:inherit;text-align:left;cursor:pointer;display:flex;align-items:center;gap:10px;padding:0}
|
|
126070
|
+
.dsh-ig-channel-add{flex:none;width:30px;padding:4px 0;font-size:16px;line-height:20px}
|
|
125829
126071
|
.dsh-ig-provider-head:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4c78ff);outline-offset:2px;border-radius:var(--dsw-radius-sm,4px)}
|
|
125830
126072
|
.dsh-ig-provider-head:hover .dsh-ig-provider-name{color:var(--dsw-alias-label-secondary,inherit)}
|
|
125831
126073
|
.dsh-ig-provider-name{flex:1;min-width:0;font-size:13.5px;font-weight:550;color:var(--dsw-alias-label-primary,inherit)}
|
|
@@ -126327,7 +126569,10 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126327
126569
|
function emptyProviderRow() {
|
|
126328
126570
|
return {
|
|
126329
126571
|
expanded: false,
|
|
126572
|
+
label: "",
|
|
126330
126573
|
model: "",
|
|
126574
|
+
models: [],
|
|
126575
|
+
editModel: "",
|
|
126331
126576
|
baseURL: "",
|
|
126332
126577
|
googleNative: false,
|
|
126333
126578
|
keyInput: "",
|
|
@@ -126410,7 +126655,29 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126410
126655
|
}
|
|
126411
126656
|
/** Persisted or selected edit-format value → row state; unknown values fall back to standard multipart. */
|
|
126412
126657
|
function parseEditFormat(value) {
|
|
126413
|
-
return value === "jsonImageUrlArray" || value === "formReferenceImages" ? value : "multipart";
|
|
126658
|
+
return value === "jsonImageUrlArray" || value === "formReferenceImages" || value === "siliconflowJson" ? value : "multipart";
|
|
126659
|
+
}
|
|
126660
|
+
function compatChannelRowKey(channelId) {
|
|
126661
|
+
return `openai-compat:${channelId}`;
|
|
126662
|
+
}
|
|
126663
|
+
function compatRowFields(channel) {
|
|
126664
|
+
return {
|
|
126665
|
+
label: channel.label,
|
|
126666
|
+
model: channel.model,
|
|
126667
|
+
models: resolveOpenAICompatModels({
|
|
126668
|
+
openaiCompatModel: channel.model,
|
|
126669
|
+
openaiCompatModels: channel.models ?? []
|
|
126670
|
+
}),
|
|
126671
|
+
editModel: channel.editModel ?? "",
|
|
126672
|
+
baseURL: channel.baseURL,
|
|
126673
|
+
editFormat: parseEditFormat(channel.editFormat),
|
|
126674
|
+
editExtraText: editExtraTextOf(channel.editExtra),
|
|
126675
|
+
sizeTableText: editExtraTextOf(channel.sizes),
|
|
126676
|
+
generationQuality: channel.quality ?? "",
|
|
126677
|
+
qualityOptionsText: (channel.qualityOptions !== void 0 && channel.qualityOptions.length > 0 ? channel.qualityOptions : DEFAULT_COMPAT_QUALITIES).join(", "),
|
|
126678
|
+
generateExtraText: editExtraTextOf(channel.extraBody),
|
|
126679
|
+
editSizeMode: channel.editSizeMode === "selected" ? "selected" : "auto"
|
|
126680
|
+
};
|
|
126414
126681
|
}
|
|
126415
126682
|
/** Build one row per provider from persisted settings, including ComfyUI extras. */
|
|
126416
126683
|
function rowsFromSettings(value) {
|
|
@@ -126426,21 +126693,17 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126426
126693
|
activeWorkflow: activeComfyUIWorkflow(value ?? {})?.name ?? "",
|
|
126427
126694
|
timeoutSeconds: Math.max(1, Math.round((value?.comfyuiTimeoutMs ?? 3e5) / 1e3))
|
|
126428
126695
|
} : {},
|
|
126429
|
-
...provider === "openai-compat" ? {
|
|
126430
|
-
editFormat: parseEditFormat(value?.openaiCompatEditFormat),
|
|
126431
|
-
editExtraText: editExtraTextOf(value?.openaiCompatEditExtra),
|
|
126432
|
-
sizeTableText: editExtraTextOf(value?.openaiCompatSizes),
|
|
126433
|
-
generationQuality: value?.openaiCompatQuality ?? "",
|
|
126434
|
-
qualityOptionsText: (value?.openaiCompatQualityOptions ?? DEFAULT_COMPAT_QUALITIES).join(", "),
|
|
126435
|
-
generateExtraText: editExtraTextOf(value?.openaiCompatExtraBody),
|
|
126436
|
-
editSizeMode: value?.openaiCompatEditSizeMode === "selected" ? "selected" : "auto"
|
|
126437
|
-
} : {},
|
|
126696
|
+
...provider === "openai-compat" ? compatRowFields(resolveOpenAICompatChannels(value ?? {})[0]) : {},
|
|
126438
126697
|
...provider === "seedream" ? {
|
|
126439
126698
|
outputFormat: value?.seedreamOutputFormat === "png" ? "png" : "jpeg",
|
|
126440
126699
|
watermark: value?.seedreamWatermark !== false,
|
|
126441
126700
|
background: value?.seedreamBackground === "transparent" ? "transparent" : "opaque"
|
|
126442
126701
|
} : {}
|
|
126443
126702
|
};
|
|
126703
|
+
for (const channel of resolveOpenAICompatChannels(value ?? {}).slice(1)) rows[compatChannelRowKey(channel.id)] = {
|
|
126704
|
+
...emptyProviderRow(),
|
|
126705
|
+
...compatRowFields(channel)
|
|
126706
|
+
};
|
|
126444
126707
|
return rows;
|
|
126445
126708
|
}
|
|
126446
126709
|
/** Edit each provider independently, pick an explicit default, and verify keys inline. */
|
|
@@ -126454,6 +126717,8 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126454
126717
|
const [defaultProvider, setDefaultProvider] = (0, react.useState)(() => props.scope.getSnapshot().value?.provider ?? "google");
|
|
126455
126718
|
const [providerMessage, setProviderMessage] = (0, react.useState)("");
|
|
126456
126719
|
const [providerMessageIsError, setProviderMessageIsError] = (0, react.useState)(false);
|
|
126720
|
+
const [cloudTimeoutSeconds, setCloudTimeoutSeconds] = (0, react.useState)(() => (props.scope.getSnapshot().value?.cloudTimeoutMs ?? 15e4) / 1e3);
|
|
126721
|
+
const [cloudTimeoutMessage, setCloudTimeoutMessage] = (0, react.useState)("");
|
|
126457
126722
|
const [saveToWorkspace, setSaveToWorkspace] = (0, react.useState)(() => props.scope.getSnapshot().value?.saveToWorkspace ?? true);
|
|
126458
126723
|
const [workspaceFolder, setWorkspaceFolder] = (0, react.useState)(() => props.scope.getSnapshot().value?.workspaceFolder ?? "dsh-image-gen");
|
|
126459
126724
|
const [showPill, setShowPill] = (0, react.useState)(() => props.scope.getSnapshot().value?.showProviderPill === true);
|
|
@@ -126462,6 +126727,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126462
126727
|
const [workspaceMessage, setWorkspaceMessage] = (0, react.useState)("");
|
|
126463
126728
|
const [workspaceMessageIsError, setWorkspaceMessageIsError] = (0, react.useState)(false);
|
|
126464
126729
|
const [rows, setRows] = (0, react.useState)(() => rowsFromSettings(props.scope.getSnapshot().value));
|
|
126730
|
+
const [compatChannels, setCompatChannels] = (0, react.useState)(() => resolveOpenAICompatChannels(props.scope.getSnapshot().value ?? {}).slice(1));
|
|
126465
126731
|
const [keyTick, setKeyTick] = (0, react.useState)(0);
|
|
126466
126732
|
const [subStatus, setSubStatus] = (0, react.useState)(() => ({
|
|
126467
126733
|
"chatgpt-sub": { state: "unknown" },
|
|
@@ -126671,14 +126937,16 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126671
126937
|
(0, react.useEffect)(() => {
|
|
126672
126938
|
const value = snapshot.value;
|
|
126673
126939
|
setDefaultProvider(value?.provider ?? "google");
|
|
126940
|
+
setCloudTimeoutSeconds((value?.cloudTimeoutMs ?? 15e4) / 1e3);
|
|
126674
126941
|
setSaveToWorkspace(value?.saveToWorkspace ?? true);
|
|
126675
126942
|
setWorkspaceFolder(value?.workspaceFolder ?? "dsh-image-gen");
|
|
126676
126943
|
setShowPill(value?.showProviderPill === true);
|
|
126677
126944
|
setRows((current) => {
|
|
126678
|
-
const next = {};
|
|
126945
|
+
const next = { ...current };
|
|
126679
126946
|
for (const provider of IMAGE_PROVIDERS) next[provider] = {
|
|
126680
126947
|
...current[provider],
|
|
126681
126948
|
model: modelOf(provider, value),
|
|
126949
|
+
...provider === "openai-compat" ? compatRowFields(resolveOpenAICompatChannels(value ?? {})[0]) : {},
|
|
126682
126950
|
baseURL: baseURLOf(provider, value),
|
|
126683
126951
|
...provider === "comfyui" ? {
|
|
126684
126952
|
workflows: resolveComfyUIWorkflows(value ?? {}),
|
|
@@ -126691,6 +126959,13 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126691
126959
|
background: value?.seedreamBackground === "transparent" ? "transparent" : "opaque"
|
|
126692
126960
|
} : {}
|
|
126693
126961
|
};
|
|
126962
|
+
for (const channel of resolveOpenAICompatChannels(value ?? {}).slice(1)) {
|
|
126963
|
+
const key = compatChannelRowKey(channel.id);
|
|
126964
|
+
next[key] = {
|
|
126965
|
+
...current[key] ?? emptyProviderRow(),
|
|
126966
|
+
...compatRowFields(channel)
|
|
126967
|
+
};
|
|
126968
|
+
}
|
|
126694
126969
|
return next;
|
|
126695
126970
|
});
|
|
126696
126971
|
}, [snapshot]);
|
|
@@ -126698,11 +126973,21 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126698
126973
|
const credentialsAvailable = props.credentialsAvailable;
|
|
126699
126974
|
(0, react.useEffect)(() => {
|
|
126700
126975
|
let active = true;
|
|
126976
|
+
const targets = [...CLOUD_IMAGE_PROVIDERS.flatMap((provider) => {
|
|
126977
|
+
const keyRef = cloudCredentialRef(provider);
|
|
126978
|
+
return keyRef === void 0 ? [] : [{
|
|
126979
|
+
key: provider,
|
|
126980
|
+
keyRef
|
|
126981
|
+
}];
|
|
126982
|
+
}), ...compatChannels.map((channel) => ({
|
|
126983
|
+
key: compatChannelRowKey(channel.id),
|
|
126984
|
+
keyRef: channel.keyRef
|
|
126985
|
+
}))];
|
|
126701
126986
|
if (!credentialsAvailable()) {
|
|
126702
126987
|
setRows((current) => {
|
|
126703
126988
|
const next = { ...current };
|
|
126704
|
-
for (const
|
|
126705
|
-
...current[
|
|
126989
|
+
for (const target of targets) next[target.key] = {
|
|
126990
|
+
...current[target.key] ?? emptyProviderRow(),
|
|
126706
126991
|
keyStatus: "unavailable",
|
|
126707
126992
|
keyInfo: void 0
|
|
126708
126993
|
};
|
|
@@ -126712,23 +126997,21 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126712
126997
|
active = false;
|
|
126713
126998
|
};
|
|
126714
126999
|
}
|
|
126715
|
-
for (const
|
|
126716
|
-
const keyRef = cloudCredentialRef(provider);
|
|
126717
|
-
if (keyRef === void 0) continue;
|
|
127000
|
+
for (const target of targets) {
|
|
126718
127001
|
setRows((current) => ({
|
|
126719
127002
|
...current,
|
|
126720
|
-
[
|
|
126721
|
-
...current[
|
|
127003
|
+
[target.key]: {
|
|
127004
|
+
...current[target.key],
|
|
126722
127005
|
keyStatus: "checking"
|
|
126723
127006
|
}
|
|
126724
127007
|
}));
|
|
126725
|
-
credentials.describe([keyRef]).then((response) => {
|
|
127008
|
+
credentials.describe([target.keyRef]).then((response) => {
|
|
126726
127009
|
if (!active) return;
|
|
126727
|
-
const info = response.ok ? response.value?.[keyRef] : void 0;
|
|
127010
|
+
const info = response.ok ? response.value?.[target.keyRef] : void 0;
|
|
126728
127011
|
setRows((current) => ({
|
|
126729
127012
|
...current,
|
|
126730
|
-
[
|
|
126731
|
-
...current[
|
|
127013
|
+
[target.key]: {
|
|
127014
|
+
...current[target.key],
|
|
126732
127015
|
keyStatus: response.ok ? info?.configured ? "configured" : "missing" : "unknown",
|
|
126733
127016
|
keyInfo: info
|
|
126734
127017
|
}
|
|
@@ -126737,8 +127020,8 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126737
127020
|
if (!active) return;
|
|
126738
127021
|
setRows((current) => ({
|
|
126739
127022
|
...current,
|
|
126740
|
-
[
|
|
126741
|
-
...current[
|
|
127023
|
+
[target.key]: {
|
|
127024
|
+
...current[target.key],
|
|
126742
127025
|
keyStatus: "unknown"
|
|
126743
127026
|
}
|
|
126744
127027
|
}));
|
|
@@ -126750,13 +127033,14 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126750
127033
|
}, [
|
|
126751
127034
|
credentials,
|
|
126752
127035
|
credentialsAvailable,
|
|
126753
|
-
keyTick
|
|
127036
|
+
keyTick,
|
|
127037
|
+
compatChannels
|
|
126754
127038
|
]);
|
|
126755
|
-
const updateRow = (
|
|
127039
|
+
const updateRow = (target, patch) => {
|
|
126756
127040
|
setRows((current) => ({
|
|
126757
127041
|
...current,
|
|
126758
|
-
[
|
|
126759
|
-
...current[
|
|
127042
|
+
[target]: {
|
|
127043
|
+
...current[target],
|
|
126760
127044
|
...patch
|
|
126761
127045
|
}
|
|
126762
127046
|
}));
|
|
@@ -126772,15 +127056,49 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126772
127056
|
setProviderMessageIsError(true);
|
|
126773
127057
|
});
|
|
126774
127058
|
};
|
|
126775
|
-
const saveProviderRow = async (provider) => {
|
|
126776
|
-
const
|
|
126777
|
-
|
|
127059
|
+
const saveProviderRow = async (provider, channel) => {
|
|
127060
|
+
const target = channel === void 0 ? provider : compatChannelRowKey(channel.id);
|
|
127061
|
+
const row = rows[target];
|
|
127062
|
+
updateRow(target, {
|
|
126778
127063
|
saving: true,
|
|
126779
127064
|
message: "",
|
|
126780
127065
|
messageIsError: false
|
|
126781
127066
|
});
|
|
126782
127067
|
try {
|
|
126783
|
-
if (
|
|
127068
|
+
if (channel !== void 0) {
|
|
127069
|
+
const label = row.label.trim();
|
|
127070
|
+
if (label.length === 0) throw new Error(t("channelNameRequired"));
|
|
127071
|
+
const updated = {
|
|
127072
|
+
...channel,
|
|
127073
|
+
label,
|
|
127074
|
+
baseURL: row.baseURL.trim(),
|
|
127075
|
+
model: row.model.trim(),
|
|
127076
|
+
models: resolveOpenAICompatModels({
|
|
127077
|
+
openaiCompatModel: row.model,
|
|
127078
|
+
openaiCompatModels: row.models
|
|
127079
|
+
}),
|
|
127080
|
+
editModel: row.editModel.trim(),
|
|
127081
|
+
quality: row.generationQuality.trim(),
|
|
127082
|
+
qualityOptions: [...new Set(row.qualityOptionsText.split(",").map((value) => value.trim()).filter(Boolean))],
|
|
127083
|
+
extraBody: parseExtraFields(row.generateExtraText, t("editExtraInvalid")),
|
|
127084
|
+
editSizeMode: row.editSizeMode,
|
|
127085
|
+
editFormat: row.editFormat,
|
|
127086
|
+
editExtra: parseExtraFields(row.editExtraText, t("editExtraInvalid")),
|
|
127087
|
+
sizes: parseSizeTable(row.sizeTableText, t("sizeTableInvalid"))
|
|
127088
|
+
};
|
|
127089
|
+
const nextChannels = compatChannels.some((entry) => entry.id === channel.id) ? compatChannels.map((entry) => entry.id === channel.id ? updated : entry) : [...compatChannels, updated];
|
|
127090
|
+
await saveSetting("openaiCompatChannels", nextChannels);
|
|
127091
|
+
setCompatChannels(nextChannels);
|
|
127092
|
+
if (row.keyInput.trim().length > 0) {
|
|
127093
|
+
if (!credentialsAvailable()) throw new Error(t("credentialsUnavailable"));
|
|
127094
|
+
const response = await props.credentials.set(channel.keyRef, row.keyInput.trim());
|
|
127095
|
+
if (!response.ok) throw new Error(response.error?.message ?? t("saveKeyFailed"));
|
|
127096
|
+
updateRow(target, {
|
|
127097
|
+
keyInput: "",
|
|
127098
|
+
keyStatus: "configured"
|
|
127099
|
+
});
|
|
127100
|
+
}
|
|
127101
|
+
} else if (provider === "comfyui") {
|
|
126784
127102
|
const entries = row.workflows.map((entry) => ({
|
|
126785
127103
|
name: entry.name.trim(),
|
|
126786
127104
|
json: entry.json,
|
|
@@ -126809,6 +127127,12 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126809
127127
|
if (provider === "google") await saveSetting("googleNative", row.googleNative);
|
|
126810
127128
|
if (provider === "openai") await saveSetting("openaiSizes", sizeTable);
|
|
126811
127129
|
if (provider === "openai-compat") {
|
|
127130
|
+
await saveSetting("openaiCompatLabel", row.label.trim());
|
|
127131
|
+
await saveSetting("openaiCompatModels", resolveOpenAICompatModels({
|
|
127132
|
+
openaiCompatModel: row.model,
|
|
127133
|
+
openaiCompatModels: row.models
|
|
127134
|
+
}));
|
|
127135
|
+
await saveSetting("openaiCompatEditModel", row.editModel.trim());
|
|
126812
127136
|
await saveSetting("openaiCompatEditFormat", row.editFormat);
|
|
126813
127137
|
await saveSetting("openaiCompatEditExtra", editExtra);
|
|
126814
127138
|
await saveSetting("openaiCompatSizes", sizeTable);
|
|
@@ -126828,13 +127152,13 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126828
127152
|
if (!credentialsAvailable()) throw new Error(t("credentialsUnavailable"));
|
|
126829
127153
|
const response = await props.credentials.set(keyRef, row.keyInput.trim());
|
|
126830
127154
|
if (!response.ok) throw new Error(response.error?.message ?? t("saveKeyFailed"));
|
|
126831
|
-
updateRow(
|
|
127155
|
+
updateRow(target, {
|
|
126832
127156
|
keyInput: "",
|
|
126833
127157
|
keyStatus: "configured"
|
|
126834
127158
|
});
|
|
126835
127159
|
}
|
|
126836
127160
|
}
|
|
126837
|
-
updateRow(
|
|
127161
|
+
updateRow(target, {
|
|
126838
127162
|
message: t("saved"),
|
|
126839
127163
|
messageIsError: false,
|
|
126840
127164
|
testResult: void 0,
|
|
@@ -126842,38 +127166,99 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126842
127166
|
modelFetchIsError: false
|
|
126843
127167
|
});
|
|
126844
127168
|
} catch (cause) {
|
|
126845
|
-
updateRow(
|
|
127169
|
+
updateRow(target, {
|
|
127170
|
+
message: cause instanceof Error ? cause.message : String(cause),
|
|
127171
|
+
messageIsError: true
|
|
127172
|
+
});
|
|
127173
|
+
} finally {
|
|
127174
|
+
updateRow(target, { saving: false });
|
|
127175
|
+
}
|
|
127176
|
+
};
|
|
127177
|
+
const addCompatChannel = () => {
|
|
127178
|
+
const id = `channel-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 7)}`;
|
|
127179
|
+
const channel = {
|
|
127180
|
+
id,
|
|
127181
|
+
label: `OpenAI 兼容 ${compatChannels.length + 2}`,
|
|
127182
|
+
keyRef: openAICompatKeyRef(id),
|
|
127183
|
+
baseURL: "",
|
|
127184
|
+
model: "",
|
|
127185
|
+
models: [],
|
|
127186
|
+
qualityOptions: [...DEFAULT_COMPAT_QUALITIES]
|
|
127187
|
+
};
|
|
127188
|
+
setCompatChannels((current) => [...current, channel]);
|
|
127189
|
+
setRows((current) => ({
|
|
127190
|
+
...current,
|
|
127191
|
+
[compatChannelRowKey(id)]: {
|
|
127192
|
+
...emptyProviderRow(),
|
|
127193
|
+
...compatRowFields(channel),
|
|
127194
|
+
expanded: true
|
|
127195
|
+
}
|
|
127196
|
+
}));
|
|
127197
|
+
};
|
|
127198
|
+
const removeCompatChannel = async (channel) => {
|
|
127199
|
+
if (!window.confirm(t("removeChannelConfirm", { label: channel.label }))) return;
|
|
127200
|
+
const target = compatChannelRowKey(channel.id);
|
|
127201
|
+
if (!(snapshot.value?.openaiCompatChannels?.some((entry) => entry.id === channel.id) === true)) {
|
|
127202
|
+
setCompatChannels((current) => current.filter((entry) => entry.id !== channel.id));
|
|
127203
|
+
setRows((current) => {
|
|
127204
|
+
const next = { ...current };
|
|
127205
|
+
delete next[target];
|
|
127206
|
+
return next;
|
|
127207
|
+
});
|
|
127208
|
+
return;
|
|
127209
|
+
}
|
|
127210
|
+
let removed = false;
|
|
127211
|
+
updateRow(target, {
|
|
127212
|
+
saving: true,
|
|
127213
|
+
message: "",
|
|
127214
|
+
messageIsError: false
|
|
127215
|
+
});
|
|
127216
|
+
try {
|
|
127217
|
+
const nextChannels = compatChannels.filter((entry) => entry.id !== channel.id);
|
|
127218
|
+
await saveSetting("openaiCompatChannels", nextChannels);
|
|
127219
|
+
if (snapshot.value?.openaiCompatActiveChannel === channel.id) await saveSetting("openaiCompatActiveChannel", "default");
|
|
127220
|
+
removed = true;
|
|
127221
|
+
setCompatChannels(nextChannels);
|
|
127222
|
+
setRows((current) => {
|
|
127223
|
+
const next = { ...current };
|
|
127224
|
+
delete next[target];
|
|
127225
|
+
return next;
|
|
127226
|
+
});
|
|
127227
|
+
} catch (cause) {
|
|
127228
|
+
updateRow(target, {
|
|
126846
127229
|
message: cause instanceof Error ? cause.message : String(cause),
|
|
126847
127230
|
messageIsError: true
|
|
126848
127231
|
});
|
|
126849
127232
|
} finally {
|
|
126850
|
-
updateRow(
|
|
127233
|
+
if (!removed) updateRow(target, { saving: false });
|
|
126851
127234
|
}
|
|
126852
127235
|
};
|
|
126853
127236
|
/** These actions use host settings, so drafts must be saved before making a request. */
|
|
126854
|
-
const providerActionBlockMessage = (provider) => {
|
|
126855
|
-
const
|
|
127237
|
+
const providerActionBlockMessage = (provider, channel) => {
|
|
127238
|
+
const target = channel === void 0 ? provider : compatChannelRowKey(channel.id);
|
|
127239
|
+
const row = rows[target];
|
|
126856
127240
|
if (row.keyInput.trim().length > 0) return t("saveKeyFirst");
|
|
126857
127241
|
if (isSubscriptionProvider(provider)) return void 0;
|
|
126858
127242
|
const address = row.baseURL.trim();
|
|
126859
127243
|
if (address.length === 0) return t("endpointRequired");
|
|
126860
|
-
if (address !== baseURLOf(provider, props.scope.getSnapshot().value).trim()) return t("saveEndpointFirst");
|
|
127244
|
+
if (address !== (channel === void 0 ? baseURLOf(provider, props.scope.getSnapshot().value) : channel.baseURL).trim()) return t("saveEndpointFirst");
|
|
126861
127245
|
if (provider === "google" && row.googleNative !== (props.scope.getSnapshot().value?.googleNative === true)) return t("saveGoogleProtocolFirst");
|
|
126862
127246
|
};
|
|
126863
127247
|
/** Localize the host's missing-address error while preserving upstream details. */
|
|
126864
127248
|
const providerErrorMessage = (message) => message === "Base URL is not configured" ? t("savedEndpointMissing") : message ?? t("testFailed");
|
|
126865
127249
|
/** Probe through the host route so the browser side never touches credential values. */
|
|
126866
|
-
const testConnection = async (provider) => {
|
|
126867
|
-
const
|
|
127250
|
+
const testConnection = async (provider, channel) => {
|
|
127251
|
+
const target = channel === void 0 ? provider : compatChannelRowKey(channel.id);
|
|
127252
|
+
const blocked = providerActionBlockMessage(provider, channel);
|
|
126868
127253
|
if (blocked !== void 0) {
|
|
126869
|
-
updateRow(
|
|
127254
|
+
updateRow(target, {
|
|
126870
127255
|
message: blocked,
|
|
126871
127256
|
messageIsError: false,
|
|
126872
127257
|
testResult: void 0
|
|
126873
127258
|
});
|
|
126874
127259
|
return;
|
|
126875
127260
|
}
|
|
126876
|
-
updateRow(
|
|
127261
|
+
updateRow(target, {
|
|
126877
127262
|
testing: true,
|
|
126878
127263
|
testResult: void 0,
|
|
126879
127264
|
message: "",
|
|
@@ -126883,31 +127268,35 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126883
127268
|
const response = await fetch(TEST_CONNECTION_ROUTE, {
|
|
126884
127269
|
method: "POST",
|
|
126885
127270
|
headers: { "content-type": "application/json" },
|
|
126886
|
-
body: JSON.stringify({
|
|
127271
|
+
body: JSON.stringify({
|
|
127272
|
+
provider,
|
|
127273
|
+
...channel === void 0 ? {} : { channel: channel.id }
|
|
127274
|
+
})
|
|
126887
127275
|
});
|
|
126888
127276
|
if (!response.ok) throw new Error(`HTTP ${String(response.status)}`);
|
|
126889
|
-
updateRow(
|
|
127277
|
+
updateRow(target, { testResult: await response.json() });
|
|
126890
127278
|
} catch (cause) {
|
|
126891
|
-
updateRow(
|
|
127279
|
+
updateRow(target, { testResult: {
|
|
126892
127280
|
ok: false,
|
|
126893
127281
|
reason: "error",
|
|
126894
127282
|
message: cause instanceof Error ? cause.message : String(cause)
|
|
126895
127283
|
} });
|
|
126896
127284
|
} finally {
|
|
126897
|
-
updateRow(
|
|
127285
|
+
updateRow(target, { testing: false });
|
|
126898
127286
|
}
|
|
126899
127287
|
};
|
|
126900
127288
|
/** Pull the provider's image-capable model ids through the host route (Google and the OpenAI family). */
|
|
126901
|
-
const fetchProviderModels = async (provider) => {
|
|
126902
|
-
const
|
|
127289
|
+
const fetchProviderModels = async (provider, channel) => {
|
|
127290
|
+
const target = channel === void 0 ? provider : compatChannelRowKey(channel.id);
|
|
127291
|
+
const blocked = providerActionBlockMessage(provider, channel);
|
|
126903
127292
|
if (blocked !== void 0) {
|
|
126904
|
-
updateRow(
|
|
127293
|
+
updateRow(target, {
|
|
126905
127294
|
modelFetchMessage: blocked,
|
|
126906
127295
|
modelFetchIsError: false
|
|
126907
127296
|
});
|
|
126908
127297
|
return;
|
|
126909
127298
|
}
|
|
126910
|
-
updateRow(
|
|
127299
|
+
updateRow(target, {
|
|
126911
127300
|
fetchingModels: true,
|
|
126912
127301
|
modelFetchMessage: "",
|
|
126913
127302
|
modelFetchIsError: false
|
|
@@ -126918,50 +127307,52 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126918
127307
|
headers: { "content-type": "application/json" },
|
|
126919
127308
|
body: JSON.stringify({
|
|
126920
127309
|
provider,
|
|
126921
|
-
action: "models"
|
|
127310
|
+
action: "models",
|
|
127311
|
+
...channel === void 0 ? {} : { channel: channel.id }
|
|
126922
127312
|
})
|
|
126923
127313
|
});
|
|
126924
127314
|
if (!response.ok) throw new Error(`HTTP ${String(response.status)}`);
|
|
126925
127315
|
const payload = await response.json();
|
|
126926
127316
|
if (payload.ok && Array.isArray(payload.models)) {
|
|
126927
127317
|
const models = payload.models.filter((id) => typeof id === "string");
|
|
126928
|
-
updateRow(
|
|
127318
|
+
updateRow(target, {
|
|
126929
127319
|
modelOptions: models,
|
|
126930
127320
|
modelFetchMessage: models.length > 0 ? t("modelsFound", { n: String(models.length) }) : t("modelsNone"),
|
|
126931
127321
|
modelFetchIsError: models.length === 0
|
|
126932
127322
|
});
|
|
126933
|
-
} else if (payload.reason === "missing-key") updateRow(
|
|
127323
|
+
} else if (payload.reason === "missing-key") updateRow(target, {
|
|
126934
127324
|
modelFetchMessage: t("badgeMissing"),
|
|
126935
127325
|
modelFetchIsError: true
|
|
126936
127326
|
});
|
|
126937
|
-
else if (payload.reason === "unauthorized") updateRow(
|
|
127327
|
+
else if (payload.reason === "unauthorized") updateRow(target, {
|
|
126938
127328
|
modelFetchMessage: t("testUnauthorized"),
|
|
126939
127329
|
modelFetchIsError: true
|
|
126940
127330
|
});
|
|
126941
|
-
else updateRow(
|
|
127331
|
+
else updateRow(target, {
|
|
126942
127332
|
modelFetchMessage: providerErrorMessage(payload.message),
|
|
126943
127333
|
modelFetchIsError: true
|
|
126944
127334
|
});
|
|
126945
127335
|
} catch (cause) {
|
|
126946
|
-
updateRow(
|
|
127336
|
+
updateRow(target, {
|
|
126947
127337
|
modelFetchMessage: cause instanceof Error ? cause.message : String(cause),
|
|
126948
127338
|
modelFetchIsError: true
|
|
126949
127339
|
});
|
|
126950
127340
|
} finally {
|
|
126951
|
-
updateRow(
|
|
127341
|
+
updateRow(target, { fetchingModels: false });
|
|
126952
127342
|
}
|
|
126953
127343
|
};
|
|
126954
|
-
const clearProviderKey = async (provider) => {
|
|
126955
|
-
const
|
|
127344
|
+
const clearProviderKey = async (provider, channel) => {
|
|
127345
|
+
const target = channel === void 0 ? provider : compatChannelRowKey(channel.id);
|
|
127346
|
+
const keyRef = channel === void 0 ? cloudCredentialRef(provider) : channel.keyRef;
|
|
126956
127347
|
if (keyRef === void 0) return;
|
|
126957
127348
|
if (typeof props.credentials.unset !== "function") {
|
|
126958
|
-
updateRow(
|
|
127349
|
+
updateRow(target, {
|
|
126959
127350
|
message: t("clearKeyUnsupported"),
|
|
126960
127351
|
messageIsError: true
|
|
126961
127352
|
});
|
|
126962
127353
|
return;
|
|
126963
127354
|
}
|
|
126964
|
-
updateRow(
|
|
127355
|
+
updateRow(target, {
|
|
126965
127356
|
saving: true,
|
|
126966
127357
|
message: "",
|
|
126967
127358
|
messageIsError: false
|
|
@@ -126969,7 +127360,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126969
127360
|
try {
|
|
126970
127361
|
const response = await props.credentials.unset(keyRef);
|
|
126971
127362
|
if (!response.ok) throw new Error(response.error?.message ?? t("clearKeyFailed"));
|
|
126972
|
-
updateRow(
|
|
127363
|
+
updateRow(target, {
|
|
126973
127364
|
keyStatus: "missing",
|
|
126974
127365
|
keyInput: "",
|
|
126975
127366
|
testResult: void 0,
|
|
@@ -126977,12 +127368,12 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126977
127368
|
messageIsError: false
|
|
126978
127369
|
});
|
|
126979
127370
|
} catch (cause) {
|
|
126980
|
-
updateRow(
|
|
127371
|
+
updateRow(target, {
|
|
126981
127372
|
message: cause instanceof Error ? cause.message : String(cause),
|
|
126982
127373
|
messageIsError: true
|
|
126983
127374
|
});
|
|
126984
127375
|
} finally {
|
|
126985
|
-
updateRow(
|
|
127376
|
+
updateRow(target, { saving: false });
|
|
126986
127377
|
}
|
|
126987
127378
|
};
|
|
126988
127379
|
const testResultText = (result) => {
|
|
@@ -126992,7 +127383,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126992
127383
|
if (result.reason === "unauthorized") return t("testUnauthorized");
|
|
126993
127384
|
return `${t("testFailed")}${result.message !== void 0 && result.message.length > 0 ? `: ${providerErrorMessage(result.message)}` : ""}`;
|
|
126994
127385
|
};
|
|
126995
|
-
const badgeOf = (provider) => {
|
|
127386
|
+
const badgeOf = (provider, channel) => {
|
|
126996
127387
|
if (provider === "comfyui") return {
|
|
126997
127388
|
text: t("comfyuiNoKey"),
|
|
126998
127389
|
className: "dsh-ig-badge dsh-ig-badge-neutral"
|
|
@@ -127012,7 +127403,8 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127012
127403
|
className: "dsh-ig-badge dsh-ig-badge-neutral"
|
|
127013
127404
|
};
|
|
127014
127405
|
}
|
|
127015
|
-
const
|
|
127406
|
+
const target = channel === void 0 ? provider : compatChannelRowKey(channel.id);
|
|
127407
|
+
const status = rows[target].keyStatus;
|
|
127016
127408
|
if (status === "checking") return {
|
|
127017
127409
|
text: t("badgeChecking"),
|
|
127018
127410
|
className: "dsh-ig-badge dsh-ig-badge-neutral dsh-ig-badge-checking"
|
|
@@ -127120,6 +127512,19 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127120
127512
|
};
|
|
127121
127513
|
});
|
|
127122
127514
|
};
|
|
127515
|
+
const commitCloudTimeout = () => {
|
|
127516
|
+
if (!Number.isInteger(cloudTimeoutSeconds) || cloudTimeoutSeconds < 5 || cloudTimeoutSeconds > 3600) {
|
|
127517
|
+
setCloudTimeoutSeconds((snapshot.value?.cloudTimeoutMs ?? 15e4) / 1e3);
|
|
127518
|
+
return;
|
|
127519
|
+
}
|
|
127520
|
+
const next = cloudTimeoutSeconds * 1e3;
|
|
127521
|
+
if (next === (snapshot.value?.cloudTimeoutMs ?? 15e4)) return;
|
|
127522
|
+
setCloudTimeoutMessage("");
|
|
127523
|
+
saveSetting("cloudTimeoutMs", next).catch((cause) => {
|
|
127524
|
+
setCloudTimeoutSeconds((snapshot.value?.cloudTimeoutMs ?? 15e4) / 1e3);
|
|
127525
|
+
setCloudTimeoutMessage(cause instanceof Error ? cause.message : String(cause));
|
|
127526
|
+
});
|
|
127527
|
+
};
|
|
127123
127528
|
/** Workspace checkbox persists immediately, like every other toggle on this card. */
|
|
127124
127529
|
const toggleSaveToWorkspace = (next) => {
|
|
127125
127530
|
setSaveToWorkspace(next);
|
|
@@ -127156,31 +127561,57 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127156
127561
|
setUiMessageIsError(true);
|
|
127157
127562
|
});
|
|
127158
127563
|
};
|
|
127159
|
-
const renderCloudBody = (provider) => {
|
|
127160
|
-
const
|
|
127564
|
+
const renderCloudBody = (provider, channel) => {
|
|
127565
|
+
const target = channel === void 0 ? provider : compatChannelRowKey(channel.id);
|
|
127566
|
+
const row = rows[target];
|
|
127567
|
+
const update = (patch) => {
|
|
127568
|
+
updateRow(target, patch);
|
|
127569
|
+
};
|
|
127570
|
+
const modelListId = `dsh-ig-${target.replace(/[^A-Za-z0-9_-]/g, "-")}-model-options`;
|
|
127161
127571
|
const officialEditFormat = provider === "openai-compat" ? compatEditFormat({
|
|
127162
127572
|
openaiCompatBaseURL: row.baseURL,
|
|
127163
|
-
openaiCompatModel: row.model
|
|
127573
|
+
openaiCompatModel: row.editModel.trim() || row.model
|
|
127164
127574
|
}) : "multipart";
|
|
127165
127575
|
const automaticEditFormat = officialEditFormat !== "multipart";
|
|
127166
127576
|
const editFormat = automaticEditFormat ? officialEditFormat : row.editFormat;
|
|
127167
|
-
const keyRef = cloudCredentialRef(provider) ?? "";
|
|
127577
|
+
const keyRef = channel === void 0 ? cloudCredentialRef(provider) ?? "" : channel.keyRef;
|
|
127168
127578
|
const keyReadOnly = row.keyInfo?.writable === false;
|
|
127169
127579
|
const keyUnavailable = !credentialsAvailable();
|
|
127580
|
+
const providerLabel = provider === "openai-compat" && row.label.trim().length > 0 ? row.label.trim() : providerLabels[provider];
|
|
127581
|
+
const compatModelChoices = provider === "openai-compat" ? resolveOpenAICompatModels({
|
|
127582
|
+
openaiCompatModel: row.model,
|
|
127583
|
+
openaiCompatModels: [...row.models, ...row.modelOptions]
|
|
127584
|
+
}) : [];
|
|
127170
127585
|
return (0, react_jsx_runtime.jsx)("div", {
|
|
127171
127586
|
className: "dsh-ig-provider-body",
|
|
127172
127587
|
children: (0, react_jsx_runtime.jsxs)("form", {
|
|
127173
127588
|
onSubmit: (event) => {
|
|
127174
127589
|
event.preventDefault();
|
|
127175
|
-
saveProviderRow(provider);
|
|
127590
|
+
saveProviderRow(provider, channel);
|
|
127176
127591
|
},
|
|
127177
127592
|
children: [
|
|
127593
|
+
provider === "openai-compat" ? (0, react_jsx_runtime.jsxs)("label", {
|
|
127594
|
+
className: "dsh-ig-field",
|
|
127595
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
127596
|
+
className: "dsh-ig-label",
|
|
127597
|
+
children: t("channelName")
|
|
127598
|
+
}), (0, react_jsx_runtime.jsx)("input", {
|
|
127599
|
+
className: "dsh-ig-input",
|
|
127600
|
+
value: row.label,
|
|
127601
|
+
onChange: (event) => {
|
|
127602
|
+
update({ label: event.target.value });
|
|
127603
|
+
},
|
|
127604
|
+
placeholder: providerLabels[provider],
|
|
127605
|
+
required: channel !== void 0,
|
|
127606
|
+
disabled: !settingsWritable
|
|
127607
|
+
})]
|
|
127608
|
+
}) : null,
|
|
127178
127609
|
(0, react_jsx_runtime.jsxs)("label", {
|
|
127179
127610
|
className: "dsh-ig-field",
|
|
127180
127611
|
children: [
|
|
127181
127612
|
(0, react_jsx_runtime.jsx)("span", {
|
|
127182
127613
|
className: "dsh-ig-label",
|
|
127183
|
-
children: t("apiKeyLabel", { provider:
|
|
127614
|
+
children: t("apiKeyLabel", { provider: providerLabel })
|
|
127184
127615
|
}),
|
|
127185
127616
|
(0, react_jsx_runtime.jsx)("input", {
|
|
127186
127617
|
className: "dsh-ig-input",
|
|
@@ -127188,7 +127619,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127188
127619
|
autoComplete: "off",
|
|
127189
127620
|
value: row.keyInput,
|
|
127190
127621
|
onChange: (event) => {
|
|
127191
|
-
|
|
127622
|
+
update({ keyInput: event.target.value });
|
|
127192
127623
|
},
|
|
127193
127624
|
placeholder: row.keyStatus === "configured" ? t("apiKeyPlaceholder") : "",
|
|
127194
127625
|
disabled: !settingsWritable || keyReadOnly || keyUnavailable
|
|
@@ -127213,7 +127644,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127213
127644
|
type: "url",
|
|
127214
127645
|
value: row.baseURL,
|
|
127215
127646
|
onChange: (event) => {
|
|
127216
|
-
|
|
127647
|
+
update({ baseURL: event.target.value });
|
|
127217
127648
|
},
|
|
127218
127649
|
required: true,
|
|
127219
127650
|
disabled: !settingsWritable
|
|
@@ -127222,7 +127653,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127222
127653
|
className: "dsh-ig-btn-reset",
|
|
127223
127654
|
title: t("resetTitle"),
|
|
127224
127655
|
onClick: () => {
|
|
127225
|
-
|
|
127656
|
+
update({ baseURL: DEFAULT_BASE_URLS[provider] });
|
|
127226
127657
|
},
|
|
127227
127658
|
disabled: !settingsWritable,
|
|
127228
127659
|
children: t("reset")
|
|
@@ -127243,7 +127674,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127243
127674
|
className: "dsh-ig-input",
|
|
127244
127675
|
value: row.googleNative ? "native" : "interactions",
|
|
127245
127676
|
onChange: (event) => {
|
|
127246
|
-
|
|
127677
|
+
update({ googleNative: event.target.value === "native" });
|
|
127247
127678
|
},
|
|
127248
127679
|
disabled: !settingsWritable,
|
|
127249
127680
|
children: [(0, react_jsx_runtime.jsx)("option", {
|
|
@@ -127260,7 +127691,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127260
127691
|
children: [
|
|
127261
127692
|
(0, react_jsx_runtime.jsx)("span", {
|
|
127262
127693
|
className: "dsh-ig-label",
|
|
127263
|
-
children: t("model")
|
|
127694
|
+
children: t(provider === "openai-compat" ? "defaultModel" : "model")
|
|
127264
127695
|
}),
|
|
127265
127696
|
modelPullSupported(provider) ? (0, react_jsx_runtime.jsxs)("div", {
|
|
127266
127697
|
className: "dsh-ig-input-group",
|
|
@@ -127269,14 +127700,20 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127269
127700
|
className: "dsh-ig-input",
|
|
127270
127701
|
value: row.model,
|
|
127271
127702
|
onChange: (event) => {
|
|
127272
|
-
|
|
127703
|
+
update({ model: event.target.value });
|
|
127273
127704
|
},
|
|
127274
|
-
|
|
127705
|
+
onBlur: () => {
|
|
127706
|
+
if (provider === "openai-compat") update({ models: resolveOpenAICompatModels({
|
|
127707
|
+
openaiCompatModel: row.model,
|
|
127708
|
+
openaiCompatModels: row.models
|
|
127709
|
+
}) });
|
|
127710
|
+
},
|
|
127711
|
+
list: modelListId,
|
|
127275
127712
|
required: provider !== "openai-compat",
|
|
127276
127713
|
disabled: !settingsWritable
|
|
127277
127714
|
}),
|
|
127278
127715
|
(0, react_jsx_runtime.jsx)("datalist", {
|
|
127279
|
-
id:
|
|
127716
|
+
id: modelListId,
|
|
127280
127717
|
children: row.modelOptions.map((id) => (0, react_jsx_runtime.jsx)("option", { value: id }, id))
|
|
127281
127718
|
}),
|
|
127282
127719
|
(0, react_jsx_runtime.jsx)("button", {
|
|
@@ -127284,7 +127721,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127284
127721
|
className: "dsh-ig-btn-secondary",
|
|
127285
127722
|
disabled: row.fetchingModels || row.saving || !settingsWritable,
|
|
127286
127723
|
onClick: () => {
|
|
127287
|
-
fetchProviderModels(provider);
|
|
127724
|
+
fetchProviderModels(provider, channel);
|
|
127288
127725
|
},
|
|
127289
127726
|
children: row.fetchingModels ? t("fetchingModels") : t("fetchModels")
|
|
127290
127727
|
})
|
|
@@ -127293,7 +127730,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127293
127730
|
className: "dsh-ig-input",
|
|
127294
127731
|
value: row.model,
|
|
127295
127732
|
onChange: (event) => {
|
|
127296
|
-
|
|
127733
|
+
update({ model: event.target.value });
|
|
127297
127734
|
},
|
|
127298
127735
|
required: true,
|
|
127299
127736
|
disabled: !settingsWritable
|
|
@@ -127308,6 +127745,74 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127308
127745
|
}) : null
|
|
127309
127746
|
]
|
|
127310
127747
|
}),
|
|
127748
|
+
provider === "openai-compat" && compatModelChoices.length > 0 ? (0, react_jsx_runtime.jsxs)("div", {
|
|
127749
|
+
className: "dsh-ig-field",
|
|
127750
|
+
children: [
|
|
127751
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
127752
|
+
className: "dsh-ig-label",
|
|
127753
|
+
children: t("availableModels")
|
|
127754
|
+
}),
|
|
127755
|
+
(0, react_jsx_runtime.jsx)("div", {
|
|
127756
|
+
className: "dsh-ig-model-picker",
|
|
127757
|
+
children: compatModelChoices.map((id) => {
|
|
127758
|
+
const isDefault = row.model.trim() === id;
|
|
127759
|
+
const checked = isDefault || row.models.includes(id);
|
|
127760
|
+
return (0, react_jsx_runtime.jsxs)("label", {
|
|
127761
|
+
className: "dsh-ig-check-row",
|
|
127762
|
+
title: id,
|
|
127763
|
+
children: [
|
|
127764
|
+
(0, react_jsx_runtime.jsx)("input", {
|
|
127765
|
+
type: "checkbox",
|
|
127766
|
+
checked,
|
|
127767
|
+
disabled: !settingsWritable || isDefault,
|
|
127768
|
+
onChange: (event) => {
|
|
127769
|
+
const models = event.target.checked ? [...row.models, id] : row.models.filter((model) => model !== id);
|
|
127770
|
+
update({ models: resolveOpenAICompatModels({
|
|
127771
|
+
openaiCompatModel: row.model,
|
|
127772
|
+
openaiCompatModels: models
|
|
127773
|
+
}) });
|
|
127774
|
+
}
|
|
127775
|
+
}),
|
|
127776
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
127777
|
+
className: "dsh-ig-model-option",
|
|
127778
|
+
children: id
|
|
127779
|
+
}),
|
|
127780
|
+
isDefault ? (0, react_jsx_runtime.jsx)("span", {
|
|
127781
|
+
className: "dsh-ig-model-default",
|
|
127782
|
+
children: t("defaultModelTag")
|
|
127783
|
+
}) : null
|
|
127784
|
+
]
|
|
127785
|
+
}, id);
|
|
127786
|
+
})
|
|
127787
|
+
}),
|
|
127788
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
127789
|
+
className: "dsh-ig-hint",
|
|
127790
|
+
children: t("availableModelsHint")
|
|
127791
|
+
})
|
|
127792
|
+
]
|
|
127793
|
+
}) : null,
|
|
127794
|
+
provider === "openai-compat" ? (0, react_jsx_runtime.jsxs)("label", {
|
|
127795
|
+
className: "dsh-ig-field",
|
|
127796
|
+
children: [
|
|
127797
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
127798
|
+
className: "dsh-ig-label",
|
|
127799
|
+
children: t("editModel")
|
|
127800
|
+
}),
|
|
127801
|
+
(0, react_jsx_runtime.jsx)("input", {
|
|
127802
|
+
className: "dsh-ig-input",
|
|
127803
|
+
value: row.editModel,
|
|
127804
|
+
onChange: (event) => {
|
|
127805
|
+
update({ editModel: event.target.value });
|
|
127806
|
+
},
|
|
127807
|
+
list: modelListId,
|
|
127808
|
+
disabled: !settingsWritable
|
|
127809
|
+
}),
|
|
127810
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
127811
|
+
className: "dsh-ig-hint",
|
|
127812
|
+
children: t("editModelHint")
|
|
127813
|
+
})
|
|
127814
|
+
]
|
|
127815
|
+
}) : null,
|
|
127311
127816
|
provider === "openai-compat" ? (0, react_jsx_runtime.jsxs)("label", {
|
|
127312
127817
|
className: "dsh-ig-field",
|
|
127313
127818
|
children: [
|
|
@@ -127319,7 +127824,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127319
127824
|
className: "dsh-ig-input",
|
|
127320
127825
|
value: automaticEditFormat ? "__official__" : row.editFormat,
|
|
127321
127826
|
onChange: (event) => {
|
|
127322
|
-
|
|
127827
|
+
update({ editFormat: parseEditFormat(event.target.value) });
|
|
127323
127828
|
},
|
|
127324
127829
|
disabled: !settingsWritable || automaticEditFormat,
|
|
127325
127830
|
children: [
|
|
@@ -127338,12 +127843,16 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127338
127843
|
(0, react_jsx_runtime.jsx)("option", {
|
|
127339
127844
|
value: "formReferenceImages",
|
|
127340
127845
|
children: t("editFormatFormReferenceImages")
|
|
127846
|
+
}),
|
|
127847
|
+
(0, react_jsx_runtime.jsx)("option", {
|
|
127848
|
+
value: "siliconflowJson",
|
|
127849
|
+
children: t("editFormatSiliconFlow")
|
|
127341
127850
|
})
|
|
127342
127851
|
]
|
|
127343
127852
|
}),
|
|
127344
127853
|
(0, react_jsx_runtime.jsx)("span", {
|
|
127345
127854
|
className: "dsh-ig-hint",
|
|
127346
|
-
children: t("editFormatHint")
|
|
127855
|
+
children: t(editFormat === "siliconflowJson" ? "editFormatSiliconFlowHint" : "editFormatHint")
|
|
127347
127856
|
})
|
|
127348
127857
|
]
|
|
127349
127858
|
}) : null,
|
|
@@ -127359,7 +127868,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127359
127868
|
className: "dsh-ig-input",
|
|
127360
127869
|
value: row.outputFormat,
|
|
127361
127870
|
onChange: (event) => {
|
|
127362
|
-
|
|
127871
|
+
update({ outputFormat: event.target.value === "png" ? "png" : "jpeg" });
|
|
127363
127872
|
},
|
|
127364
127873
|
disabled: !settingsWritable,
|
|
127365
127874
|
children: [(0, react_jsx_runtime.jsx)("option", {
|
|
@@ -127387,7 +127896,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127387
127896
|
className: "dsh-ig-input",
|
|
127388
127897
|
value: row.watermark ? "on" : "off",
|
|
127389
127898
|
onChange: (event) => {
|
|
127390
|
-
|
|
127899
|
+
update({ watermark: event.target.value === "on" });
|
|
127391
127900
|
},
|
|
127392
127901
|
disabled: !settingsWritable,
|
|
127393
127902
|
children: [(0, react_jsx_runtime.jsx)("option", {
|
|
@@ -127415,7 +127924,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127415
127924
|
className: "dsh-ig-input",
|
|
127416
127925
|
value: row.background,
|
|
127417
127926
|
onChange: (event) => {
|
|
127418
|
-
|
|
127927
|
+
update({ background: event.target.value === "transparent" ? "transparent" : "opaque" });
|
|
127419
127928
|
},
|
|
127420
127929
|
disabled: !settingsWritable,
|
|
127421
127930
|
children: [(0, react_jsx_runtime.jsx)("option", {
|
|
@@ -127444,7 +127953,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127444
127953
|
className: "dsh-ig-input dsh-ig-textarea",
|
|
127445
127954
|
value: row.sizeTableText,
|
|
127446
127955
|
onChange: (event) => {
|
|
127447
|
-
|
|
127956
|
+
update({ sizeTableText: event.target.value });
|
|
127448
127957
|
},
|
|
127449
127958
|
rows: 3,
|
|
127450
127959
|
disabled: !settingsWritable
|
|
@@ -127467,7 +127976,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127467
127976
|
className: "dsh-ig-input",
|
|
127468
127977
|
value: row.generationQuality,
|
|
127469
127978
|
onChange: (event) => {
|
|
127470
|
-
|
|
127979
|
+
update({ generationQuality: event.target.value });
|
|
127471
127980
|
},
|
|
127472
127981
|
placeholder: "high",
|
|
127473
127982
|
disabled: !settingsWritable
|
|
@@ -127487,7 +127996,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127487
127996
|
className: "dsh-ig-input",
|
|
127488
127997
|
value: row.qualityOptionsText,
|
|
127489
127998
|
onChange: (event) => {
|
|
127490
|
-
|
|
127999
|
+
update({ qualityOptionsText: event.target.value });
|
|
127491
128000
|
},
|
|
127492
128001
|
disabled: !settingsWritable
|
|
127493
128002
|
})]
|
|
@@ -127503,7 +128012,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127503
128012
|
className: "dsh-ig-input dsh-ig-textarea",
|
|
127504
128013
|
value: row.generateExtraText,
|
|
127505
128014
|
onChange: (event) => {
|
|
127506
|
-
|
|
128015
|
+
update({ generateExtraText: event.target.value });
|
|
127507
128016
|
},
|
|
127508
128017
|
placeholder: "{\"watermark\":false}",
|
|
127509
128018
|
rows: 2,
|
|
@@ -127516,7 +128025,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127516
128025
|
]
|
|
127517
128026
|
})
|
|
127518
128027
|
] }) : null,
|
|
127519
|
-
provider === "openai-compat" && (editFormat === "jsonImageUrlArray" || editFormat === "qwenJson") ? (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [editFormat === "jsonImageUrlArray" ? (0, react_jsx_runtime.jsxs)("label", {
|
|
128028
|
+
provider === "openai-compat" && (editFormat === "jsonImageUrlArray" || editFormat === "qwenJson" || editFormat === "siliconflowJson") ? (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [editFormat === "jsonImageUrlArray" ? (0, react_jsx_runtime.jsxs)("label", {
|
|
127520
128029
|
className: "dsh-ig-field",
|
|
127521
128030
|
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
127522
128031
|
className: "dsh-ig-label",
|
|
@@ -127525,7 +128034,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127525
128034
|
className: "dsh-ig-input",
|
|
127526
128035
|
value: row.editSizeMode,
|
|
127527
128036
|
onChange: (event) => {
|
|
127528
|
-
|
|
128037
|
+
update({ editSizeMode: event.target.value === "selected" ? "selected" : "auto" });
|
|
127529
128038
|
},
|
|
127530
128039
|
disabled: !settingsWritable,
|
|
127531
128040
|
children: [(0, react_jsx_runtime.jsx)("option", {
|
|
@@ -127547,7 +128056,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127547
128056
|
className: "dsh-ig-input dsh-ig-textarea",
|
|
127548
128057
|
value: row.editExtraText,
|
|
127549
128058
|
onChange: (event) => {
|
|
127550
|
-
|
|
128059
|
+
update({ editExtraText: event.target.value });
|
|
127551
128060
|
},
|
|
127552
128061
|
placeholder: t("editExtraPlaceholder"),
|
|
127553
128062
|
rows: 2,
|
|
@@ -127573,7 +128082,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127573
128082
|
className: "dsh-ig-btn-secondary",
|
|
127574
128083
|
disabled: row.testing || row.saving,
|
|
127575
128084
|
onClick: () => {
|
|
127576
|
-
testConnection(provider);
|
|
128085
|
+
testConnection(provider, channel);
|
|
127577
128086
|
},
|
|
127578
128087
|
children: row.testing ? t("testing") : t("testConnection")
|
|
127579
128088
|
}),
|
|
@@ -127582,7 +128091,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127582
128091
|
className: "dsh-ig-btn-secondary dsh-ig-btn-danger",
|
|
127583
128092
|
disabled: row.saving,
|
|
127584
128093
|
onClick: () => {
|
|
127585
|
-
clearProviderKey(provider);
|
|
128094
|
+
clearProviderKey(provider, channel);
|
|
127586
128095
|
},
|
|
127587
128096
|
children: t("clearKey")
|
|
127588
128097
|
}) : null,
|
|
@@ -127900,47 +128409,115 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127900
128409
|
const renderProviderRow = (provider) => {
|
|
127901
128410
|
const row = rows[provider];
|
|
127902
128411
|
const badge = badgeOf(provider);
|
|
128412
|
+
const label = provider === "openai-compat" && row.label.trim().length > 0 ? row.label.trim() : providerLabels[provider];
|
|
127903
128413
|
return (0, react_jsx_runtime.jsxs)("div", {
|
|
127904
128414
|
className: "dsh-ig-provider-row",
|
|
127905
|
-
children: [(0, react_jsx_runtime.jsxs)("
|
|
127906
|
-
|
|
127907
|
-
|
|
127908
|
-
|
|
127909
|
-
|
|
127910
|
-
|
|
127911
|
-
|
|
127912
|
-
|
|
127913
|
-
|
|
127914
|
-
|
|
127915
|
-
|
|
127916
|
-
|
|
127917
|
-
|
|
127918
|
-
|
|
127919
|
-
|
|
127920
|
-
|
|
127921
|
-
|
|
127922
|
-
|
|
127923
|
-
|
|
127924
|
-
|
|
127925
|
-
|
|
127926
|
-
|
|
127927
|
-
|
|
127928
|
-
|
|
127929
|
-
|
|
127930
|
-
|
|
127931
|
-
|
|
127932
|
-
|
|
127933
|
-
|
|
127934
|
-
|
|
127935
|
-
|
|
127936
|
-
|
|
127937
|
-
|
|
128415
|
+
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
128416
|
+
className: "dsh-ig-provider-head-row",
|
|
128417
|
+
children: [provider === "openai-compat" ? (0, react_jsx_runtime.jsx)("button", {
|
|
128418
|
+
type: "button",
|
|
128419
|
+
className: "dsh-ig-btn-secondary dsh-ig-channel-add",
|
|
128420
|
+
title: t("addCompatChannel"),
|
|
128421
|
+
"aria-label": t("addCompatChannel"),
|
|
128422
|
+
onClick: addCompatChannel,
|
|
128423
|
+
disabled: !settingsWritable,
|
|
128424
|
+
children: "+"
|
|
128425
|
+
}) : null, (0, react_jsx_runtime.jsxs)("button", {
|
|
128426
|
+
type: "button",
|
|
128427
|
+
className: "dsh-ig-provider-head",
|
|
128428
|
+
"aria-expanded": row.expanded,
|
|
128429
|
+
onClick: () => {
|
|
128430
|
+
updateRow(provider, { expanded: !row.expanded });
|
|
128431
|
+
},
|
|
128432
|
+
children: [
|
|
128433
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
128434
|
+
className: "dsh-ig-provider-name",
|
|
128435
|
+
children: label
|
|
128436
|
+
}),
|
|
128437
|
+
(0, react_jsx_runtime.jsxs)("span", {
|
|
128438
|
+
className: badge.className,
|
|
128439
|
+
title: badge.text,
|
|
128440
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
128441
|
+
className: "dsh-ig-badge-dot",
|
|
128442
|
+
"aria-hidden": "true"
|
|
128443
|
+
}), badge.text]
|
|
128444
|
+
}),
|
|
128445
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
128446
|
+
className: `dsh-ig-provider-chevron ${row.expanded ? "dsh-ig-provider-chevron-open" : ""}`,
|
|
128447
|
+
"aria-hidden": "true",
|
|
128448
|
+
children: (0, react_jsx_runtime.jsx)("svg", {
|
|
128449
|
+
width: "12",
|
|
128450
|
+
height: "12",
|
|
128451
|
+
viewBox: "0 0 16 16",
|
|
128452
|
+
fill: "none",
|
|
128453
|
+
stroke: "currentColor",
|
|
128454
|
+
strokeWidth: "2",
|
|
128455
|
+
strokeLinecap: "round",
|
|
128456
|
+
strokeLinejoin: "round",
|
|
128457
|
+
children: (0, react_jsx_runtime.jsx)("path", { d: "M4 6l4 4 4-4" })
|
|
128458
|
+
})
|
|
127938
128459
|
})
|
|
127939
|
-
|
|
127940
|
-
]
|
|
128460
|
+
]
|
|
128461
|
+
})]
|
|
127941
128462
|
}), row.expanded ? provider === "comfyui" ? renderComfyUIBody() : isSubscriptionProvider(provider) ? renderSubscriptionBody(provider) : renderCloudBody(provider) : null]
|
|
127942
128463
|
}, provider);
|
|
127943
128464
|
};
|
|
128465
|
+
const renderCompatChannelRow = (channel) => {
|
|
128466
|
+
const target = compatChannelRowKey(channel.id);
|
|
128467
|
+
const row = rows[target];
|
|
128468
|
+
const badge = badgeOf("openai-compat", channel);
|
|
128469
|
+
return (0, react_jsx_runtime.jsxs)("div", {
|
|
128470
|
+
className: "dsh-ig-provider-row dsh-ig-compat-channel-row",
|
|
128471
|
+
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
128472
|
+
className: "dsh-ig-provider-head-row",
|
|
128473
|
+
children: [(0, react_jsx_runtime.jsxs)("button", {
|
|
128474
|
+
type: "button",
|
|
128475
|
+
className: "dsh-ig-provider-head",
|
|
128476
|
+
"aria-expanded": row.expanded,
|
|
128477
|
+
onClick: () => {
|
|
128478
|
+
updateRow(target, { expanded: !row.expanded });
|
|
128479
|
+
},
|
|
128480
|
+
children: [
|
|
128481
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
128482
|
+
className: "dsh-ig-provider-name",
|
|
128483
|
+
children: channel.label
|
|
128484
|
+
}),
|
|
128485
|
+
(0, react_jsx_runtime.jsxs)("span", {
|
|
128486
|
+
className: badge.className,
|
|
128487
|
+
title: badge.text,
|
|
128488
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
128489
|
+
className: "dsh-ig-badge-dot",
|
|
128490
|
+
"aria-hidden": "true"
|
|
128491
|
+
}), badge.text]
|
|
128492
|
+
}),
|
|
128493
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
128494
|
+
className: `dsh-ig-provider-chevron ${row.expanded ? "dsh-ig-provider-chevron-open" : ""}`,
|
|
128495
|
+
"aria-hidden": "true",
|
|
128496
|
+
children: (0, react_jsx_runtime.jsx)("svg", {
|
|
128497
|
+
width: "12",
|
|
128498
|
+
height: "12",
|
|
128499
|
+
viewBox: "0 0 16 16",
|
|
128500
|
+
fill: "none",
|
|
128501
|
+
stroke: "currentColor",
|
|
128502
|
+
strokeWidth: "2",
|
|
128503
|
+
strokeLinecap: "round",
|
|
128504
|
+
strokeLinejoin: "round",
|
|
128505
|
+
children: (0, react_jsx_runtime.jsx)("path", { d: "M4 6l4 4 4-4" })
|
|
128506
|
+
})
|
|
128507
|
+
})
|
|
128508
|
+
]
|
|
128509
|
+
}), (0, react_jsx_runtime.jsx)("button", {
|
|
128510
|
+
type: "button",
|
|
128511
|
+
className: "dsh-ig-btn-secondary dsh-ig-btn-danger",
|
|
128512
|
+
disabled: row.saving || !settingsWritable,
|
|
128513
|
+
onClick: () => {
|
|
128514
|
+
removeCompatChannel(channel);
|
|
128515
|
+
},
|
|
128516
|
+
children: t("removeChannel")
|
|
128517
|
+
})]
|
|
128518
|
+
}), row.expanded ? renderCloudBody("openai-compat", channel) : null]
|
|
128519
|
+
}, target);
|
|
128520
|
+
};
|
|
127944
128521
|
return (0, react_jsx_runtime.jsxs)("li", {
|
|
127945
128522
|
className: "dsh-ig-card",
|
|
127946
128523
|
children: [(0, react_jsx_runtime.jsx)("div", {
|
|
@@ -127998,9 +128575,46 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127998
128575
|
}) : null
|
|
127999
128576
|
]
|
|
128000
128577
|
}),
|
|
128578
|
+
(0, react_jsx_runtime.jsxs)("label", {
|
|
128579
|
+
className: "dsh-ig-field",
|
|
128580
|
+
children: [
|
|
128581
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
128582
|
+
className: "dsh-ig-label",
|
|
128583
|
+
children: t("cloudTimeout")
|
|
128584
|
+
}),
|
|
128585
|
+
(0, react_jsx_runtime.jsx)("input", {
|
|
128586
|
+
className: "dsh-ig-input",
|
|
128587
|
+
type: "number",
|
|
128588
|
+
min: "5",
|
|
128589
|
+
max: "3600",
|
|
128590
|
+
step: "1",
|
|
128591
|
+
value: cloudTimeoutSeconds,
|
|
128592
|
+
onChange: (event) => {
|
|
128593
|
+
setCloudTimeoutSeconds(Number(event.target.value));
|
|
128594
|
+
},
|
|
128595
|
+
onBlur: () => {
|
|
128596
|
+
commitCloudTimeout();
|
|
128597
|
+
},
|
|
128598
|
+
onKeyDown: (event) => {
|
|
128599
|
+
if (event.key === "Enter") commitCloudTimeout();
|
|
128600
|
+
},
|
|
128601
|
+
required: true,
|
|
128602
|
+
disabled: !settingsWritable
|
|
128603
|
+
}),
|
|
128604
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
128605
|
+
className: "dsh-ig-hint",
|
|
128606
|
+
children: t("cloudTimeoutHint")
|
|
128607
|
+
}),
|
|
128608
|
+
cloudTimeoutMessage.length > 0 ? (0, react_jsx_runtime.jsx)("span", {
|
|
128609
|
+
className: "dsh-ig-status dsh-ig-status-error",
|
|
128610
|
+
role: "status",
|
|
128611
|
+
children: cloudTimeoutMessage
|
|
128612
|
+
}) : null
|
|
128613
|
+
]
|
|
128614
|
+
}),
|
|
128001
128615
|
(0, react_jsx_runtime.jsx)("div", {
|
|
128002
128616
|
className: "dsh-ig-providers",
|
|
128003
|
-
children: IMAGE_PROVIDERS.
|
|
128617
|
+
children: IMAGE_PROVIDERS.flatMap((provider) => [renderProviderRow(provider), ...provider === "openai-compat" ? compatChannels.map((channel) => renderCompatChannelRow(channel)) : []])
|
|
128004
128618
|
}),
|
|
128005
128619
|
(0, react_jsx_runtime.jsxs)("div", {
|
|
128006
128620
|
className: "dsh-ig-section",
|
|
@@ -128165,6 +128779,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
128165
128779
|
const activeResult = selectedRevision !== void 0 ? {
|
|
128166
128780
|
prompt: selectedRevision.prompt,
|
|
128167
128781
|
provider: selectedRevision.provider,
|
|
128782
|
+
...selectedRevision.channel === void 0 ? {} : { channel: selectedRevision.channel },
|
|
128168
128783
|
model: selectedRevision.model,
|
|
128169
128784
|
output: selectedRevision.output,
|
|
128170
128785
|
createdAt: selectedRevision.createdAt,
|
|
@@ -128195,6 +128810,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
128195
128810
|
attachment: result.attachment,
|
|
128196
128811
|
prompt: result.prompt,
|
|
128197
128812
|
provider: result.provider,
|
|
128813
|
+
...result.channel === void 0 ? {} : { channel: result.channel },
|
|
128198
128814
|
model: result.model,
|
|
128199
128815
|
output: result.output,
|
|
128200
128816
|
...result.savedTo ? { savedTo: result.savedTo } : {},
|
|
@@ -128333,6 +128949,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
128333
128949
|
attachment: payload.attachment,
|
|
128334
128950
|
prompt: payload.prompt,
|
|
128335
128951
|
provider: payload.provider,
|
|
128952
|
+
...payload.channel === void 0 ? {} : { channel: payload.channel },
|
|
128336
128953
|
model: payload.model,
|
|
128337
128954
|
output: payload.output,
|
|
128338
128955
|
createdAt: payload.createdAt,
|
|
@@ -128347,6 +128964,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
128347
128964
|
attachment: revision.attachment,
|
|
128348
128965
|
prompt: revision.prompt,
|
|
128349
128966
|
provider: revision.provider,
|
|
128967
|
+
...revision.channel === void 0 ? {} : { channel: revision.channel },
|
|
128350
128968
|
model: revision.model,
|
|
128351
128969
|
createdAt: revision.createdAt,
|
|
128352
128970
|
aspectRatio: revision.ratio,
|