dsh-image-gen 0.9.3 → 0.10.1
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/lib/client.js +965 -405
- package/lib/index.js +306 -67
- 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 +6 -1
- package/lib/types/client/multi-model-compare.d.ts +3 -3
- package/lib/types/client/provider-pill.d.ts +9 -3
- package/lib/types/client/studio-view.d.ts +1 -0
- package/lib/types/client/tl/tl-trace-bridge.d.ts +55 -0
- package/lib/types/client/tl/trace-playback.d.ts +101 -0
- package/lib/types/config.d.ts +11 -2
- 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 +1 -1
- package/lib/types/shared.d.ts +53 -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/lib/types/trace-drawing.d.ts +102 -0
- package/lib/types/trace-route.d.ts +12 -0
- package/lib/types/trace-sketch.d.ts +26 -0
- package/lib/types/trace-store.d.ts +23 -0
- package/lib/types/vendor/drawai/raster.d.ts +43 -0
- package/lib/types/vendor/drawai/trace-image.d.ts +257 -0
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -160,17 +160,101 @@ window.__ModuleLoader__.load({
|
|
|
160
160
|
"xai",
|
|
161
161
|
"zhipu"
|
|
162
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
|
+
}
|
|
163
229
|
/**
|
|
164
230
|
* Providers the browser workbench can drive: the BYOK cloud set plus the
|
|
165
231
|
* logged-in subscription channels. ComfyUI stays out; it has its own workflow
|
|
166
232
|
* pipeline and no shared request shape.
|
|
167
233
|
*/
|
|
168
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";
|
|
169
253
|
/** The credential reference each cloud provider's API key is stored under. */
|
|
170
254
|
const CLOUD_CREDENTIAL_REFS = {
|
|
171
|
-
google:
|
|
172
|
-
openai:
|
|
173
|
-
"openai-compat":
|
|
255
|
+
google: GOOGLE_API_KEY_ENV,
|
|
256
|
+
openai: OPENAI_API_KEY_ENV,
|
|
257
|
+
"openai-compat": OPENAI_COMPAT_API_KEY_ENV,
|
|
174
258
|
seedream: "ARK_API_KEY",
|
|
175
259
|
dashscope: "DASHSCOPE_API_KEY",
|
|
176
260
|
xai: "XAI_API_KEY",
|
|
@@ -189,6 +273,16 @@ window.__ModuleLoader__.load({
|
|
|
189
273
|
function studioModelForMode(profile, mode) {
|
|
190
274
|
return mode === "edit" ? profile.editModel ?? profile.model : profile.model;
|
|
191
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
|
+
}
|
|
192
286
|
function studioWatermarkCapability(profile, mode) {
|
|
193
287
|
return profile?.watermarkCapabilities?.[mode] ?? (mode === "generate" && profile?.watermarkOptions?.length ? { status: "supported" } : {
|
|
194
288
|
status: "unknown",
|
|
@@ -2104,9 +2198,9 @@ window.__ModuleLoader__.load({
|
|
|
2104
2198
|
//#endregion
|
|
2105
2199
|
//#region lib/types/client/multi-model-compare.js
|
|
2106
2200
|
/** Map one shared output intent to settings accepted by every target model. */
|
|
2107
|
-
function buildComparisonTargets(profiles,
|
|
2108
|
-
const selected = new Set(
|
|
2109
|
-
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) => {
|
|
2110
2204
|
const targetRatio = profile.ratioOptions.some((option) => option.value === ratio) ? ratio : profile.defaultRatio;
|
|
2111
2205
|
const generationOptions = generationQualityOptions(profile);
|
|
2112
2206
|
const qualityIntent = output === void 0 ? quality : profile.provider === "openai" || profile.provider === "chatgpt-sub" || profile.provider === "zhipu" ? output.generationQuality : output.resolution;
|
|
@@ -2145,10 +2239,11 @@ window.__ModuleLoader__.load({
|
|
|
2145
2239
|
return [...options.values()];
|
|
2146
2240
|
}
|
|
2147
2241
|
/** Start with two models, not every configured API, to avoid surprise spend. */
|
|
2148
|
-
function initialComparisonProviders(profiles, activeProvider) {
|
|
2242
|
+
function initialComparisonProviders(profiles, activeProvider, activeChannel) {
|
|
2149
2243
|
const configured = profiles.filter((profile) => profile.configured);
|
|
2150
|
-
const active = configured.find((profile) => profile.provider === activeProvider);
|
|
2151
|
-
|
|
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));
|
|
2152
2247
|
}
|
|
2153
2248
|
const RATIO_SORT_ORDER = [
|
|
2154
2249
|
"auto",
|
|
@@ -49157,7 +49252,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
49157
49252
|
should not mutate them or their content. Rather, you create new
|
|
49158
49253
|
instances whenever needed. The API tries to make this easy.
|
|
49159
49254
|
*/
|
|
49160
|
-
var Fragment$
|
|
49255
|
+
var Fragment$48 = class Fragment$48 {
|
|
49161
49256
|
/**
|
|
49162
49257
|
@internal
|
|
49163
49258
|
*/
|
|
@@ -49218,7 +49313,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
49218
49313
|
i = 1;
|
|
49219
49314
|
}
|
|
49220
49315
|
for (; i < other.content.length; i++) content.push(other.content[i]);
|
|
49221
|
-
return new Fragment$
|
|
49316
|
+
return new Fragment$48(content, this.size + other.size);
|
|
49222
49317
|
}
|
|
49223
49318
|
/**
|
|
49224
49319
|
Cut out the sub-fragment between the two given positions.
|
|
@@ -49238,15 +49333,15 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
49238
49333
|
}
|
|
49239
49334
|
pos = end;
|
|
49240
49335
|
}
|
|
49241
|
-
return new Fragment$
|
|
49336
|
+
return new Fragment$48(result, size);
|
|
49242
49337
|
}
|
|
49243
49338
|
/**
|
|
49244
49339
|
@internal
|
|
49245
49340
|
*/
|
|
49246
49341
|
cutByIndex(from, to) {
|
|
49247
|
-
if (from == to) return Fragment$
|
|
49342
|
+
if (from == to) return Fragment$48.empty;
|
|
49248
49343
|
if (from == 0 && to == this.content.length) return this;
|
|
49249
|
-
return new Fragment$
|
|
49344
|
+
return new Fragment$48(this.content.slice(from, to));
|
|
49250
49345
|
}
|
|
49251
49346
|
/**
|
|
49252
49347
|
Create a new fragment in which the node at the given index is
|
|
@@ -49258,21 +49353,21 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
49258
49353
|
let copy = this.content.slice();
|
|
49259
49354
|
let size = this.size + node.nodeSize - current.nodeSize;
|
|
49260
49355
|
copy[index] = node;
|
|
49261
|
-
return new Fragment$
|
|
49356
|
+
return new Fragment$48(copy, size);
|
|
49262
49357
|
}
|
|
49263
49358
|
/**
|
|
49264
49359
|
Create a new fragment by prepending the given node to this
|
|
49265
49360
|
fragment.
|
|
49266
49361
|
*/
|
|
49267
49362
|
addToStart(node) {
|
|
49268
|
-
return new Fragment$
|
|
49363
|
+
return new Fragment$48([node].concat(this.content), this.size + node.nodeSize);
|
|
49269
49364
|
}
|
|
49270
49365
|
/**
|
|
49271
49366
|
Create a new fragment by appending the given node to this
|
|
49272
49367
|
fragment.
|
|
49273
49368
|
*/
|
|
49274
49369
|
addToEnd(node) {
|
|
49275
|
-
return new Fragment$
|
|
49370
|
+
return new Fragment$48(this.content.concat(node), this.size + node.nodeSize);
|
|
49276
49371
|
}
|
|
49277
49372
|
/**
|
|
49278
49373
|
Compare this fragment to another one.
|
|
@@ -49382,16 +49477,16 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
49382
49477
|
Deserialize a fragment from its JSON representation.
|
|
49383
49478
|
*/
|
|
49384
49479
|
static fromJSON(schema, value) {
|
|
49385
|
-
if (!value) return Fragment$
|
|
49480
|
+
if (!value) return Fragment$48.empty;
|
|
49386
49481
|
if (!Array.isArray(value)) throw new RangeError("Invalid input for Fragment.fromJSON");
|
|
49387
|
-
return Fragment$
|
|
49482
|
+
return Fragment$48.fromArray(value.map(schema.nodeFromJSON));
|
|
49388
49483
|
}
|
|
49389
49484
|
/**
|
|
49390
49485
|
Build a fragment from an array of nodes. Ensures that adjacent
|
|
49391
49486
|
text nodes with the same marks are joined together.
|
|
49392
49487
|
*/
|
|
49393
49488
|
static fromArray(array) {
|
|
49394
|
-
if (!array.length) return Fragment$
|
|
49489
|
+
if (!array.length) return Fragment$48.empty;
|
|
49395
49490
|
let joined, size = 0;
|
|
49396
49491
|
for (let i = 0; i < array.length; i++) {
|
|
49397
49492
|
let node = array[i];
|
|
@@ -49401,7 +49496,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
49401
49496
|
joined[joined.length - 1] = node.withText(joined[joined.length - 1].text + node.text);
|
|
49402
49497
|
} else if (joined) joined.push(node);
|
|
49403
49498
|
}
|
|
49404
|
-
return new Fragment$
|
|
49499
|
+
return new Fragment$48(joined || array, size);
|
|
49405
49500
|
}
|
|
49406
49501
|
/**
|
|
49407
49502
|
Create a fragment from something that can be interpreted as a
|
|
@@ -49410,10 +49505,10 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
49410
49505
|
fragment containing those nodes.
|
|
49411
49506
|
*/
|
|
49412
49507
|
static from(nodes) {
|
|
49413
|
-
if (!nodes) return Fragment$
|
|
49414
|
-
if (nodes instanceof Fragment$
|
|
49508
|
+
if (!nodes) return Fragment$48.empty;
|
|
49509
|
+
if (nodes instanceof Fragment$48) return nodes;
|
|
49415
49510
|
if (Array.isArray(nodes)) return this.fromArray(nodes);
|
|
49416
|
-
if (nodes.attrs) return new Fragment$
|
|
49511
|
+
if (nodes.attrs) return new Fragment$48([nodes], nodes.nodeSize);
|
|
49417
49512
|
throw new RangeError("Can not convert " + nodes + " to a Fragment" + (nodes.nodesBetween ? " (looks like multiple versions of prosemirror-model were loaded)" : ""));
|
|
49418
49513
|
}
|
|
49419
49514
|
};
|
|
@@ -49422,7 +49517,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
49422
49517
|
contain anything (rather than allocating a new empty fragment for
|
|
49423
49518
|
each leaf node).
|
|
49424
49519
|
*/
|
|
49425
|
-
Fragment$
|
|
49520
|
+
Fragment$48.empty = new Fragment$48([], 0);
|
|
49426
49521
|
const found = {
|
|
49427
49522
|
index: 0,
|
|
49428
49523
|
offset: 0
|
|
@@ -49635,7 +49730,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
49635
49730
|
if (!json) return Slice.empty;
|
|
49636
49731
|
let openStart = json.openStart || 0, openEnd = json.openEnd || 0;
|
|
49637
49732
|
if (typeof openStart != "number" || typeof openEnd != "number") throw new RangeError("Invalid input for Slice.fromJSON");
|
|
49638
|
-
return new Slice(Fragment$
|
|
49733
|
+
return new Slice(Fragment$48.fromJSON(schema, json.content), openStart, openEnd);
|
|
49639
49734
|
}
|
|
49640
49735
|
/**
|
|
49641
49736
|
Create a slice from a fragment by taking the maximum possible
|
|
@@ -49651,7 +49746,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
49651
49746
|
/**
|
|
49652
49747
|
The empty slice.
|
|
49653
49748
|
*/
|
|
49654
|
-
Slice.empty = new Slice(Fragment$
|
|
49749
|
+
Slice.empty = new Slice(Fragment$48.empty, 0, 0);
|
|
49655
49750
|
function removeRange(content, from, to) {
|
|
49656
49751
|
let { index, offset } = content.findIndex(from), child = content.maybeChild(index);
|
|
49657
49752
|
let { index: indexTo, offset: offsetTo } = content.findIndex(to);
|
|
@@ -49735,19 +49830,19 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
49735
49830
|
if (openEnd) addNode(close(openEnd, replaceTwoWay($end, $to, depth + 1)), content);
|
|
49736
49831
|
}
|
|
49737
49832
|
addRange($to, null, depth, content);
|
|
49738
|
-
return new Fragment$
|
|
49833
|
+
return new Fragment$48(content);
|
|
49739
49834
|
}
|
|
49740
49835
|
function replaceTwoWay($from, $to, depth) {
|
|
49741
49836
|
let content = [];
|
|
49742
49837
|
addRange(null, $from, depth, content);
|
|
49743
49838
|
if ($from.depth > depth) addNode(close(joinable$1($from, $to, depth + 1), replaceTwoWay($from, $to, depth + 1)), content);
|
|
49744
49839
|
addRange($to, null, depth, content);
|
|
49745
|
-
return new Fragment$
|
|
49840
|
+
return new Fragment$48(content);
|
|
49746
49841
|
}
|
|
49747
49842
|
function prepareSliceForReplace(slice, $along) {
|
|
49748
49843
|
let extra = $along.depth - slice.openStart;
|
|
49749
49844
|
let node = $along.node(extra).copy(slice.content);
|
|
49750
|
-
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));
|
|
49751
49846
|
return {
|
|
49752
49847
|
start: node.resolveNoCache(slice.openStart + extra),
|
|
49753
49848
|
end: node.resolveNoCache(node.content.size - slice.openEnd - extra)
|
|
@@ -50087,7 +50182,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
50087
50182
|
this.type = type;
|
|
50088
50183
|
this.attrs = attrs;
|
|
50089
50184
|
this.marks = marks;
|
|
50090
|
-
this.content = content || Fragment$
|
|
50185
|
+
this.content = content || Fragment$48.empty;
|
|
50091
50186
|
}
|
|
50092
50187
|
/**
|
|
50093
50188
|
The array of this node's child nodes.
|
|
@@ -50396,7 +50491,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
50396
50491
|
can optionally pass `start` and `end` indices into the
|
|
50397
50492
|
replacement fragment.
|
|
50398
50493
|
*/
|
|
50399
|
-
canReplace(from, to, replacement = Fragment$
|
|
50494
|
+
canReplace(from, to, replacement = Fragment$48.empty, start = 0, end = replacement.childCount) {
|
|
50400
50495
|
let one = this.contentMatchAt(from).matchFragment(replacement, start, end);
|
|
50401
50496
|
let two = one && one.matchFragment(this.content, to);
|
|
50402
50497
|
if (!two || !two.validEnd) return false;
|
|
@@ -50466,7 +50561,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
50466
50561
|
if (typeof json.text != "string") throw new RangeError("Invalid text node in JSON");
|
|
50467
50562
|
return schema.text(json.text, marks);
|
|
50468
50563
|
}
|
|
50469
|
-
let content = Fragment$
|
|
50564
|
+
let content = Fragment$48.fromJSON(schema, json.content);
|
|
50470
50565
|
let node = schema.nodeType(json.type).create(json.attrs, content, marks);
|
|
50471
50566
|
node.type.checkAttrs(node.attrs);
|
|
50472
50567
|
return node;
|
|
@@ -50605,7 +50700,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
50605
50700
|
let seen = [this];
|
|
50606
50701
|
function search(match, types) {
|
|
50607
50702
|
let finished = match.matchFragment(after, startIndex);
|
|
50608
|
-
if (finished && (!toEnd || finished.validEnd)) return Fragment$
|
|
50703
|
+
if (finished && (!toEnd || finished.validEnd)) return Fragment$48.from(types.map((tp) => tp.createAndFill()));
|
|
50609
50704
|
for (let i = 0; i < match.next.length; i++) {
|
|
50610
50705
|
let { type, next } = match.next[i];
|
|
50611
50706
|
if (!(type.isText || type.hasRequiredAttrs()) && seen.indexOf(next) == -1) {
|
|
@@ -51045,7 +51140,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
51045
51140
|
*/
|
|
51046
51141
|
create(attrs = null, content, marks) {
|
|
51047
51142
|
if (this.isText) throw new Error("NodeType.create can't construct text nodes");
|
|
51048
|
-
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));
|
|
51049
51144
|
}
|
|
51050
51145
|
/**
|
|
51051
51146
|
Like [`create`](https://prosemirror.net/docs/ref/#model.NodeType.create), but check the given content
|
|
@@ -51053,7 +51148,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
51053
51148
|
if it doesn't match.
|
|
51054
51149
|
*/
|
|
51055
51150
|
createChecked(attrs = null, content, marks) {
|
|
51056
|
-
content = Fragment$
|
|
51151
|
+
content = Fragment$48.from(content);
|
|
51057
51152
|
this.checkContent(content);
|
|
51058
51153
|
return new Node$2(this, this.computeAttrs(attrs), content, Mark$1.setFrom(marks));
|
|
51059
51154
|
}
|
|
@@ -51067,14 +51162,14 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
51067
51162
|
*/
|
|
51068
51163
|
createAndFill(attrs = null, content, marks) {
|
|
51069
51164
|
attrs = this.computeAttrs(attrs);
|
|
51070
|
-
content = Fragment$
|
|
51165
|
+
content = Fragment$48.from(content);
|
|
51071
51166
|
if (content.size) {
|
|
51072
51167
|
let before = this.contentMatch.fillBefore(content);
|
|
51073
51168
|
if (!before) return null;
|
|
51074
51169
|
content = before.append(content);
|
|
51075
51170
|
}
|
|
51076
51171
|
let matched = this.contentMatch.matchFragment(content);
|
|
51077
|
-
let after = matched && matched.fillBefore(Fragment$
|
|
51172
|
+
let after = matched && matched.fillBefore(Fragment$48.empty, true);
|
|
51078
51173
|
if (!after) return null;
|
|
51079
51174
|
return new Node$2(this, attrs, content.append(after), Mark$1.setFrom(marks));
|
|
51080
51175
|
}
|
|
@@ -51526,7 +51621,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
51526
51621
|
findWrapping(node) {
|
|
51527
51622
|
if (!this.match) {
|
|
51528
51623
|
if (!this.type) return [];
|
|
51529
|
-
let fill = this.type.contentMatch.fillBefore(Fragment$
|
|
51624
|
+
let fill = this.type.contentMatch.fillBefore(Fragment$48.from(node));
|
|
51530
51625
|
if (fill) this.match = this.type.contentMatch.matchFragment(fill);
|
|
51531
51626
|
else {
|
|
51532
51627
|
let start = this.type.contentMatch, wrap;
|
|
@@ -51547,8 +51642,8 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
51547
51642
|
else this.content[this.content.length - 1] = text.withText(text.text.slice(0, text.text.length - m[0].length));
|
|
51548
51643
|
}
|
|
51549
51644
|
}
|
|
51550
|
-
let content = Fragment$
|
|
51551
|
-
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));
|
|
51552
51647
|
return this.type ? this.type.create(this.attrs, content, this.marks) : content;
|
|
51553
51648
|
}
|
|
51554
51649
|
inlineContext(node) {
|
|
@@ -52475,7 +52570,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
52475
52570
|
if (child.isInline) child = f(child, parent, i);
|
|
52476
52571
|
mapped.push(child);
|
|
52477
52572
|
}
|
|
52478
|
-
return Fragment$
|
|
52573
|
+
return Fragment$48.fromArray(mapped);
|
|
52479
52574
|
}
|
|
52480
52575
|
/**
|
|
52481
52576
|
Add a mark to all inline content between two positions.
|
|
@@ -52593,7 +52688,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
52593
52688
|
let node = doc.nodeAt(this.pos);
|
|
52594
52689
|
if (!node) return StepResult.fail("No node at mark step's position");
|
|
52595
52690
|
let updated = node.type.create(node.attrs, null, this.mark.addToSet(node.marks));
|
|
52596
|
-
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));
|
|
52597
52692
|
}
|
|
52598
52693
|
invert(doc) {
|
|
52599
52694
|
let node = doc.nodeAt(this.pos);
|
|
@@ -52642,7 +52737,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
52642
52737
|
let node = doc.nodeAt(this.pos);
|
|
52643
52738
|
if (!node) return StepResult.fail("No node at mark step's position");
|
|
52644
52739
|
let updated = node.type.create(node.attrs, null, this.mark.removeFromSet(node.marks));
|
|
52645
|
-
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));
|
|
52646
52741
|
}
|
|
52647
52742
|
invert(doc) {
|
|
52648
52743
|
let node = doc.nodeAt(this.pos);
|
|
@@ -52906,7 +53001,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
52906
53001
|
if (clearNewlines && child.isText && parentType.whitespace != "pre") {
|
|
52907
53002
|
let m, newline = /\r?\n|\r/g, slice;
|
|
52908
53003
|
while (m = newline.exec(child.text)) {
|
|
52909
|
-
if (!slice) slice = new Slice(Fragment$
|
|
53004
|
+
if (!slice) slice = new Slice(Fragment$48.from(parentType.schema.text(" ", parentType.allowedMarks(child.marks))), 0, 0);
|
|
52910
53005
|
replSteps.push(new ReplaceStep(cur + m.index, cur + m.index + m[0].length, slice));
|
|
52911
53006
|
}
|
|
52912
53007
|
}
|
|
@@ -52914,7 +53009,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
52914
53009
|
cur = end;
|
|
52915
53010
|
}
|
|
52916
53011
|
if (!match.validEnd) {
|
|
52917
|
-
let fill = match.fillBefore(Fragment$
|
|
53012
|
+
let fill = match.fillBefore(Fragment$48.empty, true);
|
|
52918
53013
|
tr.replace(cur, cur, new Slice(fill, 0, 0));
|
|
52919
53014
|
}
|
|
52920
53015
|
for (let i = replSteps.length - 1; i >= 0; i--) tr.step(replSteps[i]);
|
|
@@ -52943,16 +53038,16 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
52943
53038
|
let { $from, $to, depth } = range;
|
|
52944
53039
|
let gapStart = $from.before(depth + 1), gapEnd = $to.after(depth + 1);
|
|
52945
53040
|
let start = gapStart, end = gapEnd;
|
|
52946
|
-
let before = Fragment$
|
|
53041
|
+
let before = Fragment$48.empty, openStart = 0;
|
|
52947
53042
|
for (let d = depth, splitting = false; d > target; d--) if (splitting || $from.index(d) > 0) {
|
|
52948
53043
|
splitting = true;
|
|
52949
|
-
before = Fragment$
|
|
53044
|
+
before = Fragment$48.from($from.node(d).copy(before));
|
|
52950
53045
|
openStart++;
|
|
52951
53046
|
} else start--;
|
|
52952
|
-
let after = Fragment$
|
|
53047
|
+
let after = Fragment$48.empty, openEnd = 0;
|
|
52953
53048
|
for (let d = depth, splitting = false; d > target; d--) if (splitting || $to.after(d + 1) < $to.end(d)) {
|
|
52954
53049
|
splitting = true;
|
|
52955
|
-
after = Fragment$
|
|
53050
|
+
after = Fragment$48.from($to.node(d).copy(after));
|
|
52956
53051
|
openEnd++;
|
|
52957
53052
|
} else end++;
|
|
52958
53053
|
tr.step(new ReplaceAroundStep(start, end, gapStart, gapEnd, new Slice(before.append(after), openStart, openEnd), before.size - openStart, true));
|
|
@@ -52998,13 +53093,13 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
52998
53093
|
return inside;
|
|
52999
53094
|
}
|
|
53000
53095
|
function wrap(tr, range, wrappers) {
|
|
53001
|
-
let content = Fragment$
|
|
53096
|
+
let content = Fragment$48.empty;
|
|
53002
53097
|
for (let i = wrappers.length - 1; i >= 0; i--) {
|
|
53003
53098
|
if (content.size) {
|
|
53004
53099
|
let match = wrappers[i].type.contentMatch.matchFragment(content);
|
|
53005
53100
|
if (!match || !match.validEnd) throw new RangeError("Wrapper type given to Transform.wrap does not form valid content of its parent wrapper");
|
|
53006
53101
|
}
|
|
53007
|
-
content = Fragment$
|
|
53102
|
+
content = Fragment$48.from(wrappers[i].type.create(wrappers[i].attrs, content));
|
|
53008
53103
|
}
|
|
53009
53104
|
let start = range.start, end = range.end;
|
|
53010
53105
|
tr.step(new ReplaceAroundStep(start, end, start, end, new Slice(content, 0, 0), wrappers.length, true));
|
|
@@ -53025,7 +53120,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
53025
53120
|
clearIncompatible(tr, tr.mapping.slice(mapFrom).map(pos, 1), type, void 0, convertNewlines === null);
|
|
53026
53121
|
let mapping = tr.mapping.slice(mapFrom);
|
|
53027
53122
|
let startM = mapping.map(pos, 1), endM = mapping.map(pos + node.nodeSize, 1);
|
|
53028
|
-
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));
|
|
53029
53124
|
if (convertNewlines === true) replaceNewlines(tr, node, pos, mapFrom);
|
|
53030
53125
|
return false;
|
|
53031
53126
|
}
|
|
@@ -53065,7 +53160,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
53065
53160
|
let newNode = type.create(attrs, null, marks || node.marks);
|
|
53066
53161
|
if (node.isLeaf) return tr.replaceWith(pos, pos + node.nodeSize, newNode);
|
|
53067
53162
|
if (!type.validContent(node.content)) throw new RangeError("Invalid content for node type " + type.name);
|
|
53068
|
-
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));
|
|
53069
53164
|
}
|
|
53070
53165
|
/**
|
|
53071
53166
|
Check whether splitting at the given position is allowed.
|
|
@@ -53088,11 +53183,11 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
53088
53183
|
return $pos.node(base).canReplaceWith(index, index, baseType ? baseType.type : $pos.node(base + 1).type);
|
|
53089
53184
|
}
|
|
53090
53185
|
function split(tr, pos, depth = 1, typesAfter) {
|
|
53091
|
-
let $pos = tr.doc.resolve(pos), before = Fragment$
|
|
53186
|
+
let $pos = tr.doc.resolve(pos), before = Fragment$48.empty, after = Fragment$48.empty;
|
|
53092
53187
|
for (let d = $pos.depth, e = $pos.depth - depth, i = depth - 1; d > e; d--, i--) {
|
|
53093
|
-
before = Fragment$
|
|
53188
|
+
before = Fragment$48.from($pos.node(d).copy(before));
|
|
53094
53189
|
let typeAfter = typesAfter && typesAfter[i];
|
|
53095
|
-
after = Fragment$
|
|
53190
|
+
after = Fragment$48.from(typeAfter ? typeAfter.type.create(typeAfter.attrs, after) : $pos.node(d).copy(after));
|
|
53096
53191
|
}
|
|
53097
53192
|
tr.step(new ReplaceStep(pos, pos, new Slice(before.append(after), depth, depth), true));
|
|
53098
53193
|
}
|
|
@@ -53235,7 +53330,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
53235
53330
|
this.$to = $to;
|
|
53236
53331
|
this.unplaced = unplaced;
|
|
53237
53332
|
this.frontier = [];
|
|
53238
|
-
this.placed = Fragment$
|
|
53333
|
+
this.placed = Fragment$48.empty;
|
|
53239
53334
|
for (let i = 0; i <= $from.depth; i++) {
|
|
53240
53335
|
let node = $from.node(i);
|
|
53241
53336
|
this.frontier.push({
|
|
@@ -53243,7 +53338,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
53243
53338
|
match: node.contentMatchAt($from.indexAfter(i))
|
|
53244
53339
|
});
|
|
53245
53340
|
}
|
|
53246
|
-
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));
|
|
53247
53342
|
}
|
|
53248
53343
|
get depth() {
|
|
53249
53344
|
return this.frontier.length - 1;
|
|
@@ -53288,7 +53383,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
53288
53383
|
let first = fragment.firstChild;
|
|
53289
53384
|
for (let frontierDepth = this.depth; frontierDepth >= 0; frontierDepth--) {
|
|
53290
53385
|
let { type, match } = this.frontier[frontierDepth], wrap, inject = null;
|
|
53291
|
-
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 {
|
|
53292
53387
|
sliceDepth,
|
|
53293
53388
|
frontierDepth,
|
|
53294
53389
|
parent,
|
|
@@ -53342,7 +53437,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
53342
53437
|
}
|
|
53343
53438
|
let toEnd = taken == fragment.childCount;
|
|
53344
53439
|
if (!toEnd) openEndCount = -1;
|
|
53345
|
-
this.placed = addToFragment(this.placed, frontierDepth, Fragment$
|
|
53440
|
+
this.placed = addToFragment(this.placed, frontierDepth, Fragment$48.from(add));
|
|
53346
53441
|
this.frontier[frontierDepth].match = match;
|
|
53347
53442
|
if (toEnd && openEndCount < 0 && parent && parent.type == this.frontier[this.depth].type && this.frontier.length > 1) this.closeFrontierNode();
|
|
53348
53443
|
for (let i = 0, cur = fragment; i < openEndCount; i++) {
|
|
@@ -53396,14 +53491,14 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
53396
53491
|
openFrontierNode(type, attrs = null, content) {
|
|
53397
53492
|
let top = this.frontier[this.depth];
|
|
53398
53493
|
top.match = top.match.matchType(type);
|
|
53399
|
-
this.placed = addToFragment(this.placed, this.depth, Fragment$
|
|
53494
|
+
this.placed = addToFragment(this.placed, this.depth, Fragment$48.from(type.create(attrs, content)));
|
|
53400
53495
|
this.frontier.push({
|
|
53401
53496
|
type,
|
|
53402
53497
|
match: type.contentMatch
|
|
53403
53498
|
});
|
|
53404
53499
|
}
|
|
53405
53500
|
closeFrontierNode() {
|
|
53406
|
-
let add = this.frontier.pop().match.fillBefore(Fragment$
|
|
53501
|
+
let add = this.frontier.pop().match.fillBefore(Fragment$48.empty, true);
|
|
53407
53502
|
if (add.childCount) this.placed = addToFragment(this.placed, this.frontier.length, add);
|
|
53408
53503
|
}
|
|
53409
53504
|
};
|
|
@@ -53425,7 +53520,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
53425
53520
|
if (openStart > 1) frag = frag.replaceChild(0, closeNodeStart(frag.firstChild, openStart - 1, frag.childCount == 1 ? openEnd - 1 : 0));
|
|
53426
53521
|
if (openStart > 0) {
|
|
53427
53522
|
frag = node.type.contentMatch.fillBefore(frag).append(frag);
|
|
53428
|
-
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));
|
|
53429
53524
|
}
|
|
53430
53525
|
return node.copy(frag);
|
|
53431
53526
|
}
|
|
@@ -53508,7 +53603,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
53508
53603
|
if (depth > newOpen) {
|
|
53509
53604
|
let match = parent.contentMatchAt(0);
|
|
53510
53605
|
let start = match.fillBefore(fragment).append(fragment);
|
|
53511
|
-
fragment = start.append(match.matchFragment(start).fillBefore(Fragment$
|
|
53606
|
+
fragment = start.append(match.matchFragment(start).fillBefore(Fragment$48.empty, true));
|
|
53512
53607
|
}
|
|
53513
53608
|
return fragment;
|
|
53514
53609
|
}
|
|
@@ -53517,7 +53612,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
53517
53612
|
let point = insertPoint(tr.doc, from, node.type);
|
|
53518
53613
|
if (point != null) from = to = point;
|
|
53519
53614
|
}
|
|
53520
|
-
tr.replaceRange(from, to, new Slice(Fragment$
|
|
53615
|
+
tr.replaceRange(from, to, new Slice(Fragment$48.from(node), 0, 0));
|
|
53521
53616
|
}
|
|
53522
53617
|
function deleteRange$1(tr, from, to) {
|
|
53523
53618
|
let $from = tr.doc.resolve(from), $to = tr.doc.resolve(to);
|
|
@@ -53570,7 +53665,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
53570
53665
|
for (let name in node.attrs) attrs[name] = node.attrs[name];
|
|
53571
53666
|
attrs[this.attr] = this.value;
|
|
53572
53667
|
let updated = node.type.create(attrs, null, node.marks);
|
|
53573
|
-
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));
|
|
53574
53669
|
}
|
|
53575
53670
|
getMap() {
|
|
53576
53671
|
return StepMap.empty;
|
|
@@ -53753,7 +53848,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
53753
53848
|
fragment, node, or array of nodes.
|
|
53754
53849
|
*/
|
|
53755
53850
|
replaceWith(from, to, content) {
|
|
53756
|
-
return this.replace(from, to, new Slice(Fragment$
|
|
53851
|
+
return this.replace(from, to, new Slice(Fragment$48.from(content), 0, 0));
|
|
53757
53852
|
}
|
|
53758
53853
|
/**
|
|
53759
53854
|
Delete the content between the given positions.
|
|
@@ -54258,7 +54353,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
54258
54353
|
return new NodeSelection($pos);
|
|
54259
54354
|
}
|
|
54260
54355
|
content() {
|
|
54261
|
-
return new Slice(Fragment$
|
|
54356
|
+
return new Slice(Fragment$48.from(this.node), 0, 0);
|
|
54262
54357
|
}
|
|
54263
54358
|
eq(other) {
|
|
54264
54359
|
return other instanceof NodeSelection && other.anchor == this.anchor;
|
|
@@ -55301,9 +55396,9 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
55301
55396
|
let canDelAfter = !isolated && $cut.parent.canReplace($cut.index(), $cut.index() + 1);
|
|
55302
55397
|
if (canDelAfter && (conn = (match = before.contentMatchAt(before.childCount)).findWrapping(after.type)) && match.matchType(conn[0] || after.type).validEnd) {
|
|
55303
55398
|
if (dispatch) {
|
|
55304
|
-
let end = $cut.pos + after.nodeSize, wrap = Fragment$
|
|
55305
|
-
for (let i = conn.length - 1; i >= 0; i--) wrap = Fragment$
|
|
55306
|
-
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));
|
|
55307
55402
|
let tr = state.tr.step(new ReplaceAroundStep($cut.pos - 1, end, $cut.pos, end, new Slice(wrap, 1, 0), conn.length, true));
|
|
55308
55403
|
let $joinAt = tr.doc.resolve(end + 2 * conn.length);
|
|
55309
55404
|
if ($joinAt.nodeAfter && $joinAt.nodeAfter.type == before.type && canJoin(tr.doc, $joinAt.pos)) tr.join($joinAt.pos);
|
|
@@ -55328,8 +55423,8 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
55328
55423
|
for (; !afterText.isTextblock; afterText = afterText.firstChild) afterDepth++;
|
|
55329
55424
|
if (at.canReplace(at.childCount, at.childCount, afterText.content)) {
|
|
55330
55425
|
if (dispatch) {
|
|
55331
|
-
let end = Fragment$
|
|
55332
|
-
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));
|
|
55333
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());
|
|
55334
55429
|
}
|
|
55335
55430
|
return true;
|
|
@@ -55495,8 +55590,8 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
55495
55590
|
return true;
|
|
55496
55591
|
}
|
|
55497
55592
|
function doWrapInList(tr, range, wrappers, joinBefore, listType) {
|
|
55498
|
-
let content = Fragment$
|
|
55499
|
-
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));
|
|
55500
55595
|
tr.step(new ReplaceAroundStep(range.start - (joinBefore ? 2 : 0), range.end, range.start, range.end, new Slice(content, 0, 0), wrappers.length, true));
|
|
55501
55596
|
let found = 0;
|
|
55502
55597
|
for (let i = 0; i < wrappers.length; i++) if (wrappers[i].type == listType) found = i + 1;
|
|
@@ -55528,7 +55623,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
55528
55623
|
function liftToOuterList(state, dispatch, itemType, range) {
|
|
55529
55624
|
let tr = state.tr, end = range.end, endOfList = range.$to.end(range.depth);
|
|
55530
55625
|
if (end < endOfList) {
|
|
55531
|
-
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));
|
|
55532
55627
|
range = new NodeRange(tr.doc.resolve(range.$from.pos), tr.doc.resolve(endOfList), range.depth);
|
|
55533
55628
|
}
|
|
55534
55629
|
const target = liftTarget(range);
|
|
@@ -55549,9 +55644,9 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
55549
55644
|
if (tr.mapping.map(range.end) != range.start + $start.nodeAfter.nodeSize) return false;
|
|
55550
55645
|
let atStart = range.startIndex == 0, atEnd = range.endIndex == list.childCount;
|
|
55551
55646
|
let parent = $start.node(-1), indexBefore = $start.index(-1);
|
|
55552
|
-
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;
|
|
55553
55648
|
let start = $start.pos, end = start + item.nodeSize;
|
|
55554
|
-
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));
|
|
55555
55650
|
dispatch(tr.scrollIntoView());
|
|
55556
55651
|
return true;
|
|
55557
55652
|
}
|
|
@@ -55570,8 +55665,8 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
55570
55665
|
if (nodeBefore.type != itemType) return false;
|
|
55571
55666
|
if (dispatch) {
|
|
55572
55667
|
let nestedBefore = nodeBefore.lastChild && nodeBefore.lastChild.type == parent.type;
|
|
55573
|
-
let inner = Fragment$
|
|
55574
|
-
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);
|
|
55575
55670
|
let before = range.start, after = range.end;
|
|
55576
55671
|
dispatch(state.tr.step(new ReplaceAroundStep(before - (nestedBefore ? 3 : 1), after, before, after, slice, 1, true)).scrollIntoView());
|
|
55577
55672
|
}
|
|
@@ -56665,7 +56760,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
56665
56760
|
if (!rule.contentElement) {
|
|
56666
56761
|
let found = addedNodes && addedNodes.find((n) => n.nodeType == 1 && addedNodes.indexOf(n.parentNode) < 0 && this.dom.contains(n));
|
|
56667
56762
|
if (found) rule.contentElement = found;
|
|
56668
|
-
else rule.getContent = () => Fragment$
|
|
56763
|
+
else rule.getContent = () => Fragment$48.empty;
|
|
56669
56764
|
}
|
|
56670
56765
|
}
|
|
56671
56766
|
return rule;
|
|
@@ -57775,7 +57870,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
57775
57870
|
text = f(text, inCode || plainText, view);
|
|
57776
57871
|
});
|
|
57777
57872
|
if (inCode) {
|
|
57778
|
-
slice = new Slice(Fragment$
|
|
57873
|
+
slice = new Slice(Fragment$48.from(view.state.schema.text(text.replace(/\r\n?/g, "\n"))), 0, 0);
|
|
57779
57874
|
view.someProp("transformPasted", (f) => {
|
|
57780
57875
|
slice = f(slice, view, true);
|
|
57781
57876
|
});
|
|
@@ -57849,32 +57944,32 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
57849
57944
|
lastWrap = wrap;
|
|
57850
57945
|
}
|
|
57851
57946
|
});
|
|
57852
|
-
if (result) return Fragment$
|
|
57947
|
+
if (result) return Fragment$48.from(result);
|
|
57853
57948
|
}
|
|
57854
57949
|
return fragment;
|
|
57855
57950
|
}
|
|
57856
57951
|
function withWrappers(node, wrap, from = 0) {
|
|
57857
|
-
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));
|
|
57858
57953
|
return node;
|
|
57859
57954
|
}
|
|
57860
57955
|
function addToSibling(wrap, lastWrap, node, sibling, depth) {
|
|
57861
57956
|
if (depth < wrap.length && depth < lastWrap.length && wrap[depth] == lastWrap[depth]) {
|
|
57862
57957
|
let inner = addToSibling(wrap, lastWrap, node, sibling.lastChild, depth + 1);
|
|
57863
57958
|
if (inner) return sibling.copy(sibling.content.replaceChild(sibling.childCount - 1, inner));
|
|
57864
|
-
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))));
|
|
57865
57960
|
}
|
|
57866
57961
|
}
|
|
57867
57962
|
function closeRight(node, depth) {
|
|
57868
57963
|
if (depth == 0) return node;
|
|
57869
57964
|
let fragment = node.content.replaceChild(node.childCount - 1, closeRight(node.lastChild, depth - 1));
|
|
57870
|
-
let fill = node.contentMatchAt(node.childCount).fillBefore(Fragment$
|
|
57965
|
+
let fill = node.contentMatchAt(node.childCount).fillBefore(Fragment$48.empty, true);
|
|
57871
57966
|
return node.copy(fragment.append(fill));
|
|
57872
57967
|
}
|
|
57873
57968
|
function closeRange(fragment, side, from, to, depth, openEnd) {
|
|
57874
57969
|
let node = side < 0 ? fragment.firstChild : fragment.lastChild, inner = node.content;
|
|
57875
57970
|
if (fragment.childCount > 1) openEnd = 0;
|
|
57876
57971
|
if (depth < to - 1) inner = closeRange(inner, side, from, to, depth + 1, openEnd);
|
|
57877
|
-
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));
|
|
57878
57973
|
return fragment.replaceChild(side < 0 ? 0 : fragment.childCount - 1, node.copy(inner));
|
|
57879
57974
|
}
|
|
57880
57975
|
function closeSlice(slice, openStart, openEnd) {
|
|
@@ -57960,7 +58055,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
57960
58055
|
} catch (e) {
|
|
57961
58056
|
break;
|
|
57962
58057
|
}
|
|
57963
|
-
content = Fragment$
|
|
58058
|
+
content = Fragment$48.from(type.create(array[i + 1], content));
|
|
57964
58059
|
openStart++;
|
|
57965
58060
|
openEnd++;
|
|
57966
58061
|
}
|
|
@@ -59686,7 +59781,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
59686
59781
|
} else return null;
|
|
59687
59782
|
let updated = [];
|
|
59688
59783
|
for (let i = 0; i < prev.childCount; i++) updated.push(update(prev.child(i)));
|
|
59689
|
-
if (Fragment$
|
|
59784
|
+
if (Fragment$48.from(updated).eq(cur)) return {
|
|
59690
59785
|
mark,
|
|
59691
59786
|
type
|
|
59692
59787
|
};
|
|
@@ -60956,7 +61051,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
60956
61051
|
};
|
|
60957
61052
|
const isTextContent = typeof content === "string";
|
|
60958
61053
|
if (isJSONContent) try {
|
|
60959
|
-
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)));
|
|
60960
61055
|
const node = schema.nodeFromJSON(content);
|
|
60961
61056
|
if (options.errorOnInvalidContent) node.check();
|
|
60962
61057
|
return node;
|
|
@@ -61093,7 +61188,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
61093
61188
|
else newContent = value;
|
|
61094
61189
|
tr.insertText(newContent, from, to);
|
|
61095
61190
|
} else {
|
|
61096
|
-
newContent = Fragment$
|
|
61191
|
+
newContent = Fragment$48.from(nodes);
|
|
61097
61192
|
const $from = tr.doc.resolve(from);
|
|
61098
61193
|
const $fromNode = $from.node();
|
|
61099
61194
|
const fromSelectionAtStart = $from.parentOffset === 0;
|
|
@@ -62509,16 +62604,16 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
62509
62604
|
if ($from.depth === 2 || $from.node(-3).type !== type || $from.index(-2) !== $from.node(-2).childCount - 1) return false;
|
|
62510
62605
|
if (dispatch) {
|
|
62511
62606
|
var _type$contentMatch$de;
|
|
62512
|
-
let wrap = Fragment$
|
|
62607
|
+
let wrap = Fragment$48.empty;
|
|
62513
62608
|
const depthBefore = $from.index(-1) ? 1 : $from.index(-2) ? 2 : 3;
|
|
62514
|
-
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));
|
|
62515
62610
|
const depthAfter = $from.indexAfter(-1) < $from.node(-2).childCount ? 1 : $from.indexAfter(-2) < $from.node(-3).childCount ? 2 : 3;
|
|
62516
62611
|
const newNextTypeAttributes = {
|
|
62517
62612
|
...getSplittedAttributes(extensionAttributes, $from.node().type.name, $from.node().attrs),
|
|
62518
62613
|
...overrideAttrs
|
|
62519
62614
|
};
|
|
62520
62615
|
const nextType = ((_type$contentMatch$de = type.contentMatch.defaultType) === null || _type$contentMatch$de === void 0 ? void 0 : _type$contentMatch$de.createAndFill(newNextTypeAttributes)) || void 0;
|
|
62521
|
-
wrap = wrap.append(Fragment$
|
|
62616
|
+
wrap = wrap.append(Fragment$48.from(type.createAndFill(null, nextType) || void 0));
|
|
62522
62617
|
const start = $from.before($from.depth - (depthBefore - 1));
|
|
62523
62618
|
tr.replace(start, $from.after(-depthAfter), new Slice(wrap, 4 - depthBefore, 0));
|
|
62524
62619
|
let sel = -1;
|
|
@@ -63912,7 +64007,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
63912
64007
|
if (!!simulatedInputMeta) setTimeout(() => {
|
|
63913
64008
|
let { text } = simulatedInputMeta;
|
|
63914
64009
|
if (typeof text === "string") text = text;
|
|
63915
|
-
else text = getHTMLFromFragment(Fragment$
|
|
64010
|
+
else text = getHTMLFromFragment(Fragment$48.from(text), state.schema);
|
|
63916
64011
|
const { from } = simulatedInputMeta;
|
|
63917
64012
|
const to = from + text.length;
|
|
63918
64013
|
run$1({
|
|
@@ -64217,7 +64312,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
64217
64312
|
if (isSimulatedPaste) {
|
|
64218
64313
|
let { text } = simulatedPasteMeta;
|
|
64219
64314
|
if (typeof text === "string") text = text;
|
|
64220
|
-
else text = getHTMLFromFragment(Fragment$
|
|
64315
|
+
else text = getHTMLFromFragment(Fragment$48.from(text), state.schema);
|
|
64221
64316
|
const { from } = simulatedPasteMeta;
|
|
64222
64317
|
const to = from + text.length;
|
|
64223
64318
|
const pasteEvt = createClipboardPasteEvent(text);
|
|
@@ -64949,7 +65044,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
64949
65044
|
} catch {
|
|
64950
65045
|
return;
|
|
64951
65046
|
}
|
|
64952
|
-
if (content instanceof Fragment$
|
|
65047
|
+
if (content instanceof Fragment$48) return;
|
|
64953
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.");
|
|
64954
65049
|
}
|
|
64955
65050
|
var NodePos = class NodePos {
|
|
@@ -71721,7 +71816,7 @@ img.ProseMirror-separator {
|
|
|
71721
71816
|
const tr = state.tr;
|
|
71722
71817
|
tr.delete(nestedListPos, nestedListPos + nestedList.nodeSize);
|
|
71723
71818
|
const mappedInsertPos = tr.mapping.map(insertPos);
|
|
71724
|
-
tr.insert(mappedInsertPos, Fragment$
|
|
71819
|
+
tr.insert(mappedInsertPos, Fragment$48.from(items));
|
|
71725
71820
|
tr.setSelection(selection.map(tr.doc, tr.mapping));
|
|
71726
71821
|
if (dispatch) dispatch(tr);
|
|
71727
71822
|
return true;
|
|
@@ -72134,13 +72229,13 @@ img.ProseMirror-separator {
|
|
|
72134
72229
|
const lastItem = previous.lastChild;
|
|
72135
72230
|
if (!lastItem || lastItem.type.name !== name) return false;
|
|
72136
72231
|
const block = $from.parent;
|
|
72137
|
-
if (!lastItem.canReplace(lastItem.childCount, lastItem.childCount, Fragment$
|
|
72232
|
+
if (!lastItem.canReplace(lastItem.childCount, lastItem.childCount, Fragment$48.from(block))) return false;
|
|
72138
72233
|
const blockStart = $from.before();
|
|
72139
72234
|
const blockEnd = $from.after();
|
|
72140
72235
|
const insideLastItemEnd = blockStart - 2;
|
|
72141
72236
|
return editor.commands.command(({ tr, dispatch }) => {
|
|
72142
72237
|
if (dispatch) {
|
|
72143
|
-
tr.delete(blockStart, blockEnd).insert(insideLastItemEnd, Fragment$
|
|
72238
|
+
tr.delete(blockStart, blockEnd).insert(insideLastItemEnd, Fragment$48.from(block));
|
|
72144
72239
|
tr.setSelection(TextSelection.create(tr.doc, insideLastItemEnd + 1));
|
|
72145
72240
|
tr.scrollIntoView();
|
|
72146
72241
|
}
|
|
@@ -73517,8 +73612,8 @@ img.ProseMirror-separator {
|
|
|
73517
73612
|
let { $from } = view.state.selection;
|
|
73518
73613
|
let insert = $from.parent.contentMatchAt($from.index()).findWrapping(view.state.schema.nodes.text);
|
|
73519
73614
|
if (!insert) return false;
|
|
73520
|
-
let frag = Fragment$
|
|
73521
|
-
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));
|
|
73522
73617
|
let tr = view.state.tr.replace($from.pos, $from.pos, new Slice(frag, 0, 0));
|
|
73523
73618
|
tr.setSelection(TextSelection.near(tr.doc.resolve($from.pos + 1)));
|
|
73524
73619
|
view.dispatch(tr);
|
|
@@ -117528,6 +117623,7 @@ img.ProseMirror-separator {
|
|
|
117528
117623
|
const [selected, setSelected] = (0, react.useState)(null);
|
|
117529
117624
|
const [mode, setMode] = (0, react.useState)("generate");
|
|
117530
117625
|
const [provider, setProvider] = (0, react.useState)("google");
|
|
117626
|
+
const [channel, setChannel] = (0, react.useState)(void 0);
|
|
117531
117627
|
const [model, setModel] = (0, react.useState)("");
|
|
117532
117628
|
const [ratio, setRatio] = (0, react.useState)("1:1");
|
|
117533
117629
|
const [quality, setQuality] = (0, react.useState)("1K");
|
|
@@ -117541,7 +117637,7 @@ img.ProseMirror-separator {
|
|
|
117541
117637
|
const [selectedBatchIds, setSelectedBatchIds] = (0, react.useState)([]);
|
|
117542
117638
|
const [batchKind, setBatchKind] = (0, react.useState)(null);
|
|
117543
117639
|
const [comparisonEnabled, setComparisonEnabled] = (0, react.useState)(false);
|
|
117544
|
-
const [
|
|
117640
|
+
const [comparisonProviderKeys, setComparisonProviderKeys] = (0, react.useState)([]);
|
|
117545
117641
|
const [isGenerating, setIsGenerating] = (0, react.useState)(false);
|
|
117546
117642
|
const [error, setError] = (0, react.useState)(null);
|
|
117547
117643
|
const [notice, setNotice] = (0, react.useState)(null);
|
|
@@ -117616,7 +117712,7 @@ img.ProseMirror-separator {
|
|
|
117616
117712
|
observer.disconnect();
|
|
117617
117713
|
};
|
|
117618
117714
|
}, []);
|
|
117619
|
-
const maxReferences = comparisonEnabled ?
|
|
117715
|
+
const maxReferences = comparisonEnabled ? comparisonProviderKeys.includes("dashscope") ? 3 : 5 : provider === "dashscope" ? 3 : 5;
|
|
117620
117716
|
const referencesRef = (0, react.useRef)(references);
|
|
117621
117717
|
referencesRef.current = references;
|
|
117622
117718
|
const t = (key, values) => {
|
|
@@ -117636,10 +117732,12 @@ img.ProseMirror-separator {
|
|
|
117636
117732
|
(0, react.useEffect)(() => locale?.subscribe?.(() => setLang(locale.getSnapshot().active?.startsWith("en") ? "en" : "zh")), [locale]);
|
|
117637
117733
|
const formStateRef = (0, react.useRef)({
|
|
117638
117734
|
provider,
|
|
117735
|
+
channel,
|
|
117639
117736
|
model
|
|
117640
117737
|
});
|
|
117641
117738
|
formStateRef.current = {
|
|
117642
117739
|
provider,
|
|
117740
|
+
channel,
|
|
117643
117741
|
model
|
|
117644
117742
|
};
|
|
117645
117743
|
const loadConfig = (0, react.useCallback)(async (options) => {
|
|
@@ -117658,16 +117756,19 @@ img.ProseMirror-separator {
|
|
|
117658
117756
|
if (!response.ok || !("providers" in payload)) throw new Error("error" in payload && payload.error ? payload.error : "Studio unavailable");
|
|
117659
117757
|
setConfig(payload);
|
|
117660
117758
|
if (silent) {
|
|
117661
|
-
const { provider: currentProvider, model: currentModel } = formStateRef.current;
|
|
117662
|
-
const activeProfile = payload.providers.find((item) => item.provider === currentProvider);
|
|
117663
|
-
if (activeProfile
|
|
117664
|
-
|
|
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)));
|
|
117665
117766
|
return;
|
|
117666
117767
|
}
|
|
117667
|
-
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];
|
|
117668
117769
|
if (initial !== void 0) {
|
|
117669
117770
|
applyProvider(initial);
|
|
117670
|
-
|
|
117771
|
+
setComparisonProviderKeys(initialComparisonProviders(payload.providers, initial.provider, initial.channel));
|
|
117671
117772
|
}
|
|
117672
117773
|
} catch (fetchError) {
|
|
117673
117774
|
if (!silent && !controller.signal.aborted) setConfigError(messageOf(fetchError));
|
|
@@ -117769,14 +117870,18 @@ img.ProseMirror-separator {
|
|
|
117769
117870
|
window.removeEventListener("mouseup", handleMouseUp);
|
|
117770
117871
|
};
|
|
117771
117872
|
}, []);
|
|
117772
|
-
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
|
+
]);
|
|
117773
117878
|
const requestModel = mode === "edit" && activeProfile?.editModel ? studioModelForMode(activeProfile, mode) : model;
|
|
117774
117879
|
const configuredCount = config?.providers.filter((item) => item.configured).length ?? 0;
|
|
117775
117880
|
const apiConfiguredCount = config?.providers.filter((item) => item.configured && !isSubscriptionProvider(item.provider)).length ?? 0;
|
|
117776
117881
|
const subscriptionSignedInCount = config?.providers.filter((item) => item.configured && isSubscriptionProvider(item.provider)).length ?? 0;
|
|
117777
117882
|
const displayItems = (0, react.useMemo)(() => items.slice(0, visibleLimit), [items, visibleLimit]);
|
|
117778
117883
|
const comparisonProfiles = (0, react.useMemo)(() => (config?.providers ?? []).filter((item) => item.configured && (mode === "generate" || item.supportsEditing)), [config, mode]);
|
|
117779
|
-
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]);
|
|
117780
117885
|
const comparisonResolutionOpts = (0, react.useMemo)(() => comparisonOutputOptions(selectedComparisonProfiles, ratio, "resolution"), [selectedComparisonProfiles, ratio]);
|
|
117781
117886
|
const comparisonGenerationQualityOpts = (0, react.useMemo)(() => localizeQualityOptions(comparisonOutputOptions(selectedComparisonProfiles, ratio, "generationQuality"), lang), [
|
|
117782
117887
|
selectedComparisonProfiles,
|
|
@@ -117785,12 +117890,12 @@ img.ProseMirror-separator {
|
|
|
117785
117890
|
]);
|
|
117786
117891
|
const comparisonResolution = comparisonResolutionOpts.some((option) => option.value === resolution) ? resolution : comparisonResolutionOpts[0]?.value ?? "standard";
|
|
117787
117892
|
const comparisonGenerationQuality = comparisonGenerationQualityOpts.some((option) => option.value === generationQuality) ? generationQuality : comparisonGenerationQualityOpts[0]?.value ?? "__default__";
|
|
117788
|
-
const comparisonTargets = (0, react.useMemo)(() => buildComparisonTargets(comparisonProfiles,
|
|
117893
|
+
const comparisonTargets = (0, react.useMemo)(() => buildComparisonTargets(comparisonProfiles, comparisonProviderKeys, ratio, quality, {
|
|
117789
117894
|
resolution: comparisonResolution,
|
|
117790
117895
|
generationQuality: comparisonGenerationQuality
|
|
117791
117896
|
}), [
|
|
117792
117897
|
comparisonProfiles,
|
|
117793
|
-
|
|
117898
|
+
comparisonProviderKeys,
|
|
117794
117899
|
ratio,
|
|
117795
117900
|
quality,
|
|
117796
117901
|
comparisonResolution,
|
|
@@ -117807,6 +117912,7 @@ img.ProseMirror-separator {
|
|
|
117807
117912
|
const comparisonRatioOpts = (0, react.useMemo)(() => localizeRatioOptions(comparisonOptionUnion(comparisonProfiles, "ratioOptions"), lang), [comparisonProfiles, lang]);
|
|
117808
117913
|
const applyProvider = (profile) => {
|
|
117809
117914
|
setProvider(profile.provider);
|
|
117915
|
+
setChannel(profile.channel);
|
|
117810
117916
|
setModel(profile.model);
|
|
117811
117917
|
setRatio(profile.defaultRatio);
|
|
117812
117918
|
setQuality(profile.defaultQuality);
|
|
@@ -117815,8 +117921,8 @@ img.ProseMirror-separator {
|
|
|
117815
117921
|
setWatermark("default");
|
|
117816
117922
|
setError(null);
|
|
117817
117923
|
};
|
|
117818
|
-
const changeProvider = (value) => {
|
|
117819
|
-
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));
|
|
117820
117926
|
if (profile !== void 0) {
|
|
117821
117927
|
applyProvider(profile);
|
|
117822
117928
|
const providerMax = value === "dashscope" ? 3 : 5;
|
|
@@ -117830,6 +117936,10 @@ img.ProseMirror-separator {
|
|
|
117830
117936
|
}
|
|
117831
117937
|
}
|
|
117832
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
|
+
};
|
|
117833
117943
|
const resetFit = () => {
|
|
117834
117944
|
setFit(true);
|
|
117835
117945
|
setZoom(100);
|
|
@@ -117856,9 +117966,10 @@ img.ProseMirror-separator {
|
|
|
117856
117966
|
setMode("generate");
|
|
117857
117967
|
setComparisonEnabled(false);
|
|
117858
117968
|
setPrompt(item.prompt);
|
|
117859
|
-
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));
|
|
117860
117970
|
if (!profile) return;
|
|
117861
117971
|
applyProvider(profile);
|
|
117972
|
+
if (studioModelOptionsForMode(profile, "generate").some((option) => option.value === item.model)) setModel(item.model);
|
|
117862
117973
|
const nextRatio = profile.ratioOptions.some((option) => option.value === item.aspectRatio) ? item.aspectRatio : profile.defaultRatio;
|
|
117863
117974
|
setRatio(nextRatio);
|
|
117864
117975
|
if (profile.qualityOptions.some((option) => option.value === item.imageSize)) {
|
|
@@ -118007,7 +118118,7 @@ img.ProseMirror-separator {
|
|
|
118007
118118
|
const targetMax = targetItem.provider === "dashscope" ? 3 : 5;
|
|
118008
118119
|
if (referencesRef.current.some((r) => r.attachment?.attachmentId === targetAttId)) {
|
|
118009
118120
|
setMode("edit");
|
|
118010
|
-
changeProvider(targetItem.provider);
|
|
118121
|
+
changeProvider(targetItem.provider, targetItem.channel);
|
|
118011
118122
|
return;
|
|
118012
118123
|
}
|
|
118013
118124
|
if (referencesRef.current.length >= targetMax) {
|
|
@@ -118018,7 +118129,7 @@ img.ProseMirror-separator {
|
|
|
118018
118129
|
const blob = image.blob ?? await fetchAttachmentBlob(targetItem.attachment);
|
|
118019
118130
|
if (referencesRef.current.some((r) => r.attachment?.attachmentId === targetAttId)) {
|
|
118020
118131
|
setMode("edit");
|
|
118021
|
-
changeProvider(targetItem.provider);
|
|
118132
|
+
changeProvider(targetItem.provider, targetItem.channel);
|
|
118022
118133
|
return;
|
|
118023
118134
|
}
|
|
118024
118135
|
if (referencesRef.current.length >= targetMax) {
|
|
@@ -118036,7 +118147,7 @@ img.ProseMirror-separator {
|
|
|
118036
118147
|
referencesRef.current = nextList;
|
|
118037
118148
|
setError(null);
|
|
118038
118149
|
setMode("edit");
|
|
118039
|
-
changeProvider(targetItem.provider);
|
|
118150
|
+
changeProvider(targetItem.provider, targetItem.channel);
|
|
118040
118151
|
} catch {
|
|
118041
118152
|
setError(t("imageLoadFailed"));
|
|
118042
118153
|
}
|
|
@@ -118059,8 +118170,8 @@ img.ProseMirror-separator {
|
|
|
118059
118170
|
return;
|
|
118060
118171
|
}
|
|
118061
118172
|
if (config === null) return;
|
|
118062
|
-
const initial = initialComparisonProviders(comparisonProfiles, provider).filter((item) => mode !== "edit" || referencesRef.current.length <= 3 || item !== "dashscope");
|
|
118063
|
-
|
|
118173
|
+
const initial = initialComparisonProviders(comparisonProfiles, provider, channel).filter((item) => mode !== "edit" || referencesRef.current.length <= 3 || item !== "dashscope");
|
|
118174
|
+
setComparisonProviderKeys(initial);
|
|
118064
118175
|
if (![
|
|
118065
118176
|
"1:1",
|
|
118066
118177
|
"3:2",
|
|
@@ -118075,12 +118186,12 @@ img.ProseMirror-separator {
|
|
|
118075
118186
|
"4K"
|
|
118076
118187
|
].includes(quality)) setQuality("1K");
|
|
118077
118188
|
};
|
|
118078
|
-
const toggleComparisonProvider = (
|
|
118079
|
-
if (mode === "edit" &&
|
|
118189
|
+
const toggleComparisonProvider = (targetKey) => {
|
|
118190
|
+
if (mode === "edit" && targetKey === "dashscope" && referencesRef.current.length > 3 && !comparisonProviderKeys.includes(targetKey)) {
|
|
118080
118191
|
setError(t("maxReferencesExceeded", { max: "3" }));
|
|
118081
118192
|
return;
|
|
118082
118193
|
}
|
|
118083
|
-
|
|
118194
|
+
setComparisonProviderKeys((current) => current.includes(targetKey) ? current.filter((item) => item !== targetKey) : [...current, targetKey]);
|
|
118084
118195
|
setError(null);
|
|
118085
118196
|
};
|
|
118086
118197
|
const submit = async () => {
|
|
@@ -118114,6 +118225,7 @@ img.ProseMirror-separator {
|
|
|
118114
118225
|
body: JSON.stringify({
|
|
118115
118226
|
mode,
|
|
118116
118227
|
provider: target.profile.provider,
|
|
118228
|
+
...target.profile.channel === void 0 ? {} : { channel: target.profile.channel },
|
|
118117
118229
|
model: studioModelForMode(target.profile, mode),
|
|
118118
118230
|
prompt: prompt.trim(),
|
|
118119
118231
|
ratio: target.ratio,
|
|
@@ -118144,6 +118256,7 @@ img.ProseMirror-separator {
|
|
|
118144
118256
|
attachment: value.payload.attachment,
|
|
118145
118257
|
prompt: value.payload.prompt,
|
|
118146
118258
|
provider: value.payload.provider,
|
|
118259
|
+
...value.payload.channel === void 0 ? {} : { channel: value.payload.channel },
|
|
118147
118260
|
model: value.payload.model,
|
|
118148
118261
|
createdAt: value.payload.createdAt + idx,
|
|
118149
118262
|
aspectRatio: value.target.ratio,
|
|
@@ -118187,6 +118300,7 @@ img.ProseMirror-separator {
|
|
|
118187
118300
|
prompt: prompt.trim(),
|
|
118188
118301
|
ratio,
|
|
118189
118302
|
quality: selectedQuality,
|
|
118303
|
+
...activeProfile.channel === void 0 ? {} : { channel: activeProfile.channel },
|
|
118190
118304
|
...selectedResolution === void 0 ? {} : { resolution: selectedResolution },
|
|
118191
118305
|
...provider === "openai-compat" ? { generationQuality: selectedGenerationQuality } : {},
|
|
118192
118306
|
...watermarkCapability.status === "supported" ? { watermark } : {},
|
|
@@ -118207,6 +118321,7 @@ img.ProseMirror-separator {
|
|
|
118207
118321
|
attachment: gen.attachment,
|
|
118208
118322
|
prompt: payload.prompt,
|
|
118209
118323
|
provider: payload.provider,
|
|
118324
|
+
...payload.channel === void 0 ? {} : { channel: payload.channel },
|
|
118210
118325
|
model: payload.model,
|
|
118211
118326
|
createdAt: payload.createdAt + idx,
|
|
118212
118327
|
aspectRatio: ratio,
|
|
@@ -119192,12 +119307,13 @@ img.ProseMirror-separator {
|
|
|
119192
119307
|
(0, react_jsx_runtime.jsx)("div", {
|
|
119193
119308
|
className: "dsh-ig-model-checks",
|
|
119194
119309
|
children: comparisonProfiles.map((item) => {
|
|
119195
|
-
const
|
|
119310
|
+
const targetKey = studioTargetKey(item.provider, item.channel);
|
|
119311
|
+
const target = comparisonTargets.find((candidate) => studioTargetKey(candidate.profile.provider, candidate.profile.channel) === targetKey);
|
|
119196
119312
|
return (0, react_jsx_runtime.jsxs)("button", {
|
|
119197
119313
|
type: "button",
|
|
119198
119314
|
className: target ? "is-selected" : "",
|
|
119199
119315
|
"aria-pressed": Boolean(target),
|
|
119200
|
-
onClick: () => toggleComparisonProvider(
|
|
119316
|
+
onClick: () => toggleComparisonProvider(targetKey),
|
|
119201
119317
|
children: [
|
|
119202
119318
|
(0, react_jsx_runtime.jsx)("span", {
|
|
119203
119319
|
className: "dsh-ig-model-checkmark",
|
|
@@ -119220,7 +119336,7 @@ img.ProseMirror-separator {
|
|
|
119220
119336
|
].filter(Boolean).join(" · "), target.adjusted ? (0, react_jsx_runtime.jsx)("em", { children: t("compareAdjusted") }) : null]
|
|
119221
119337
|
})
|
|
119222
119338
|
]
|
|
119223
|
-
},
|
|
119339
|
+
}, targetKey);
|
|
119224
119340
|
})
|
|
119225
119341
|
}),
|
|
119226
119342
|
(0, react_jsx_runtime.jsx)("p", { children: t("compareParameterHint") })
|
|
@@ -119268,20 +119384,17 @@ img.ProseMirror-separator {
|
|
|
119268
119384
|
className: "dsh-ig-field-grid",
|
|
119269
119385
|
children: [(0, react_jsx_runtime.jsx)(FieldSelect, {
|
|
119270
119386
|
label: t("provider"),
|
|
119271
|
-
value: provider,
|
|
119272
|
-
onChange:
|
|
119387
|
+
value: studioTargetKey(provider, channel),
|
|
119388
|
+
onChange: changeProfile,
|
|
119273
119389
|
options: config.providers.map((item) => ({
|
|
119274
|
-
value: item.provider,
|
|
119390
|
+
value: studioTargetKey(item.provider, item.channel),
|
|
119275
119391
|
label: `${item.label}${item.configured ? "" : ` · ${t("unconfigured")}`}`
|
|
119276
119392
|
}))
|
|
119277
119393
|
}), (0, react_jsx_runtime.jsx)(FieldSelect, {
|
|
119278
119394
|
label: t("model"),
|
|
119279
119395
|
value: requestModel,
|
|
119280
119396
|
onChange: setModel,
|
|
119281
|
-
options: activeProfile === void 0 ? [] :
|
|
119282
|
-
value: studioModelForMode(activeProfile, mode),
|
|
119283
|
-
label: studioModelForMode(activeProfile, mode)
|
|
119284
|
-
}]
|
|
119397
|
+
options: activeProfile === void 0 ? [] : studioModelOptionsForMode(activeProfile, mode)
|
|
119285
119398
|
})]
|
|
119286
119399
|
}),
|
|
119287
119400
|
(0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -122286,6 +122399,7 @@ img.ProseMirror-separator {
|
|
|
122286
122399
|
return {
|
|
122287
122400
|
mode: "generate",
|
|
122288
122401
|
provider,
|
|
122402
|
+
...provider === "openai-compat" && image.channel !== void 0 ? { channel: image.channel } : {},
|
|
122289
122403
|
model: image.model,
|
|
122290
122404
|
prompt: prompt.trim(),
|
|
122291
122405
|
ratio: settings.ratio,
|
|
@@ -122869,7 +122983,6 @@ img.ProseMirror-separator {
|
|
|
122869
122983
|
};
|
|
122870
122984
|
}, []);
|
|
122871
122985
|
const [previewLoading, setPreviewLoading] = (0, react.useState)(false);
|
|
122872
|
-
const blobCache = (0, react.useMemo)(() => /* @__PURE__ */ new Map(), []);
|
|
122873
122986
|
const abortControllerRef = (0, react.useRef)(null);
|
|
122874
122987
|
const filteredItems = (0, react.useMemo)(() => {
|
|
122875
122988
|
return items.filter((item) => {
|
|
@@ -122925,7 +123038,6 @@ img.ProseMirror-separator {
|
|
|
122925
123038
|
}
|
|
122926
123039
|
setPreviewItem(item);
|
|
122927
123040
|
if (blob) {
|
|
122928
|
-
blobCache.set(item.id, blob);
|
|
122929
123041
|
const url = URL.createObjectURL(blob);
|
|
122930
123042
|
previewUrlRef.current = url;
|
|
122931
123043
|
setPreviewBlob(blob);
|
|
@@ -122933,15 +123045,6 @@ img.ProseMirror-separator {
|
|
|
122933
123045
|
setPreviewLoading(false);
|
|
122934
123046
|
return;
|
|
122935
123047
|
}
|
|
122936
|
-
const cached = blobCache.get(item.id);
|
|
122937
|
-
if (cached) {
|
|
122938
|
-
const url = URL.createObjectURL(cached);
|
|
122939
|
-
previewUrlRef.current = url;
|
|
122940
|
-
setPreviewBlob(cached);
|
|
122941
|
-
setPreviewUrl(url);
|
|
122942
|
-
setPreviewLoading(false);
|
|
122943
|
-
return;
|
|
122944
|
-
}
|
|
122945
123048
|
setPreviewLoading(true);
|
|
122946
123049
|
setPreviewBlob(null);
|
|
122947
123050
|
setPreviewUrl(null);
|
|
@@ -122949,7 +123052,6 @@ img.ProseMirror-separator {
|
|
|
122949
123052
|
abortControllerRef.current = controller;
|
|
122950
123053
|
fetchAttachmentBlob(item.attachment).then((fetchedBlob) => {
|
|
122951
123054
|
if (controller.signal.aborted) return;
|
|
122952
|
-
blobCache.set(item.id, fetchedBlob);
|
|
122953
123055
|
const url = URL.createObjectURL(fetchedBlob);
|
|
122954
123056
|
previewUrlRef.current = url;
|
|
122955
123057
|
setPreviewBlob(fetchedBlob);
|
|
@@ -123036,6 +123138,7 @@ img.ProseMirror-separator {
|
|
|
123036
123138
|
attachment: payload.attachment,
|
|
123037
123139
|
prompt: payload.prompt,
|
|
123038
123140
|
provider: payload.provider,
|
|
123141
|
+
...payload.channel === void 0 ? {} : { channel: payload.channel },
|
|
123039
123142
|
model: payload.model,
|
|
123040
123143
|
createdAt: payload.createdAt,
|
|
123041
123144
|
aspectRatio: request.ratio,
|
|
@@ -123212,11 +123315,7 @@ img.ProseMirror-separator {
|
|
|
123212
123315
|
if (itemsToDownload.length === 1) {
|
|
123213
123316
|
const single = itemsToDownload[0];
|
|
123214
123317
|
if (!single) return;
|
|
123215
|
-
|
|
123216
|
-
if (!blob) {
|
|
123217
|
-
blob = await fetchAttachmentBlob(single.attachment);
|
|
123218
|
-
blobCache.set(single.id, blob);
|
|
123219
|
-
}
|
|
123318
|
+
const blob = await fetchAttachmentBlob(single.attachment);
|
|
123220
123319
|
const objectUrl = URL.createObjectURL(blob);
|
|
123221
123320
|
downloadBlobUrl(objectUrl, `dsh-${single.provider}-${single.id}.png`);
|
|
123222
123321
|
URL.revokeObjectURL(objectUrl);
|
|
@@ -123229,11 +123328,7 @@ img.ProseMirror-separator {
|
|
|
123229
123328
|
const it = itemsToDownload[i];
|
|
123230
123329
|
if (!it) continue;
|
|
123231
123330
|
setBatchDownloadProgress(`${i + 1}/${itemsToDownload.length}`);
|
|
123232
|
-
|
|
123233
|
-
if (!blob) {
|
|
123234
|
-
blob = await fetchAttachmentBlob(it.attachment);
|
|
123235
|
-
blobCache.set(it.id, blob);
|
|
123236
|
-
}
|
|
123331
|
+
const blob = await fetchAttachmentBlob(it.attachment);
|
|
123237
123332
|
const arrayBuffer = await blob.arrayBuffer();
|
|
123238
123333
|
const ext = blob.type === "image/jpeg" ? "jpg" : blob.type === "image/webp" ? "webp" : "png";
|
|
123239
123334
|
let baseName = `dsh-${it.provider}-${it.id.slice(0, 8)}.${ext}`;
|
|
@@ -123637,7 +123732,6 @@ img.ProseMirror-separator {
|
|
|
123637
123732
|
onToggleSelect: (e) => handleToggleSelect(item.id, idx, e),
|
|
123638
123733
|
onRequestDelete: () => requestSingleDelete(item),
|
|
123639
123734
|
onPreview: (blob) => openPreviewItem(item, blob),
|
|
123640
|
-
onBlobLoaded: (b) => blobCache.set(item.id, b),
|
|
123641
123735
|
onToast: showToast
|
|
123642
123736
|
}, item.id))
|
|
123643
123737
|
}) : activeTab === "inspiration" ? (0, react_jsx_runtime.jsx)(InspirationView, {
|
|
@@ -124012,39 +124106,37 @@ img.ProseMirror-separator {
|
|
|
124012
124106
|
]
|
|
124013
124107
|
});
|
|
124014
124108
|
};
|
|
124015
|
-
const GalleryCard = ({ lang, item, index: _index, isManageMode, isSelected, t, onClick, onToggleSelect, onRequestDelete, onPreview: _onPreview,
|
|
124109
|
+
const GalleryCard = ({ lang, item, index: _index, isManageMode, isSelected, t, onClick, onToggleSelect, onRequestDelete, onPreview: _onPreview, onToast }) => {
|
|
124110
|
+
const [setCardRef, inView] = useInView();
|
|
124016
124111
|
const [url, setUrl] = (0, react.useState)();
|
|
124017
124112
|
const [blob, setBlob] = (0, react.useState)();
|
|
124018
124113
|
const [loading, setLoading] = (0, react.useState)(true);
|
|
124019
124114
|
const [error, setError] = (0, react.useState)();
|
|
124020
124115
|
(0, react.useEffect)(() => {
|
|
124021
|
-
|
|
124116
|
+
if (!inView) return;
|
|
124117
|
+
let active = true;
|
|
124022
124118
|
let objectUrl;
|
|
124023
|
-
|
|
124024
|
-
|
|
124025
|
-
|
|
124026
|
-
|
|
124027
|
-
|
|
124028
|
-
|
|
124029
|
-
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
|
124030
|
-
const resBlob = await response.blob();
|
|
124031
|
-
if (controller.signal.aborted) return;
|
|
124119
|
+
setUrl(void 0);
|
|
124120
|
+
setBlob(void 0);
|
|
124121
|
+
setError(void 0);
|
|
124122
|
+
setLoading(true);
|
|
124123
|
+
fetchAttachmentBlob(item.attachment).then((resBlob) => {
|
|
124124
|
+
if (!active) return;
|
|
124032
124125
|
setBlob(resBlob);
|
|
124033
|
-
onBlobLoaded?.(resBlob);
|
|
124034
124126
|
objectUrl = URL.createObjectURL(resBlob);
|
|
124035
124127
|
setUrl(objectUrl);
|
|
124036
124128
|
setLoading(false);
|
|
124037
124129
|
}).catch((err) => {
|
|
124038
|
-
if (
|
|
124130
|
+
if (active) {
|
|
124039
124131
|
setError(err instanceof Error ? err.message : String(err));
|
|
124040
124132
|
setLoading(false);
|
|
124041
124133
|
}
|
|
124042
124134
|
});
|
|
124043
124135
|
return () => {
|
|
124044
|
-
|
|
124136
|
+
active = false;
|
|
124045
124137
|
if (objectUrl) URL.revokeObjectURL(objectUrl);
|
|
124046
124138
|
};
|
|
124047
|
-
}, [item.attachment]);
|
|
124139
|
+
}, [item.attachment.attachmentId, inView]);
|
|
124048
124140
|
const copyPrompt = async (e) => {
|
|
124049
124141
|
e.stopPropagation();
|
|
124050
124142
|
try {
|
|
@@ -124075,6 +124167,7 @@ img.ProseMirror-separator {
|
|
|
124075
124167
|
};
|
|
124076
124168
|
const badgeLabel = item.model || item.provider;
|
|
124077
124169
|
return (0, react_jsx_runtime.jsxs)("div", {
|
|
124170
|
+
ref: setCardRef,
|
|
124078
124171
|
className: `dsh-ig-gallery-card ${isSelected ? "is-selected" : ""} ${isManageMode ? "is-manage-mode" : ""}`,
|
|
124079
124172
|
onClick: (e) => onClick(e, blob),
|
|
124080
124173
|
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -124303,6 +124396,7 @@ img.ProseMirror-separator {
|
|
|
124303
124396
|
attachment,
|
|
124304
124397
|
prompt: stringValue(meta.prompt, "Generated Image"),
|
|
124305
124398
|
provider: stringValue(meta.provider, "google"),
|
|
124399
|
+
...typeof meta.channel === "string" ? { channel: meta.channel } : {},
|
|
124306
124400
|
model: stringValue(meta.model, ""),
|
|
124307
124401
|
output: stringValue(meta.output, ""),
|
|
124308
124402
|
...typeof meta.savedTo === "string" ? { savedTo: meta.savedTo } : {},
|
|
@@ -124969,7 +125063,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
124969
125063
|
function isRevision(value) {
|
|
124970
125064
|
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
124971
125065
|
const candidate = value;
|
|
124972
|
-
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));
|
|
125066
|
+
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));
|
|
124973
125067
|
}
|
|
124974
125068
|
function isAttachment(value) {
|
|
124975
125069
|
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
@@ -125096,16 +125190,51 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125096
125190
|
function pillVisible(value) {
|
|
125097
125191
|
return value?.showProviderPill === true;
|
|
125098
125192
|
}
|
|
125193
|
+
const PILL_MODEL_FIELDS = {
|
|
125194
|
+
google: "googleModel",
|
|
125195
|
+
openai: "openaiModel",
|
|
125196
|
+
"openai-compat": "openaiCompatModel",
|
|
125197
|
+
seedream: "seedreamModel",
|
|
125198
|
+
dashscope: "dashscopeModel",
|
|
125199
|
+
xai: "xaiModel",
|
|
125200
|
+
zhipu: "zhipuModel"
|
|
125201
|
+
};
|
|
125202
|
+
const PILL_MODEL_OPTIONS_FIELDS = { "openai-compat": "openaiCompatModels" };
|
|
125099
125203
|
/** Model (or ComfyUI workflow) a provider row will use with the persisted settings. */
|
|
125100
|
-
function pillModelOf(provider, value) {
|
|
125204
|
+
function pillModelOf(provider, value, channelId) {
|
|
125101
125205
|
if (provider === "comfyui") {
|
|
125102
125206
|
const workflow = activeComfyUIWorkflow(value ?? {});
|
|
125103
125207
|
return workflow === void 0 ? "" : workflow.name;
|
|
125104
125208
|
}
|
|
125105
125209
|
if (SUBSCRIPTION_PROVIDERS.includes(provider)) return DEFAULT_MODELS[provider];
|
|
125106
|
-
|
|
125210
|
+
if (provider === "openai-compat") {
|
|
125211
|
+
const channel = resolveOpenAICompatChannel(value ?? {}, channelId);
|
|
125212
|
+
return channel.model.trim().length > 0 ? channel.model.trim() : DEFAULT_MODELS[provider];
|
|
125213
|
+
}
|
|
125214
|
+
const field = PILL_MODEL_FIELDS[provider];
|
|
125215
|
+
const stored = field === void 0 ? void 0 : value?.[field];
|
|
125107
125216
|
return typeof stored === "string" && stored.length > 0 ? stored : DEFAULT_MODELS[provider];
|
|
125108
125217
|
}
|
|
125218
|
+
/** Optional model choices exposed by a provider; single-model providers return an empty list. */
|
|
125219
|
+
function pillModelOptionsOf(provider, value, channelId) {
|
|
125220
|
+
if (provider === "openai-compat") {
|
|
125221
|
+
const channel = resolveOpenAICompatChannel(value ?? {}, channelId);
|
|
125222
|
+
return resolveOpenAICompatModels({
|
|
125223
|
+
openaiCompatModel: pillModelOf(provider, value, channel.id),
|
|
125224
|
+
openaiCompatModels: channel.models ?? []
|
|
125225
|
+
});
|
|
125226
|
+
}
|
|
125227
|
+
const field = PILL_MODEL_OPTIONS_FIELDS[provider];
|
|
125228
|
+
if (field === void 0) return [];
|
|
125229
|
+
const configured = value?.[field];
|
|
125230
|
+
const models = Array.isArray(configured) ? [...new Set(configured.filter((model) => typeof model === "string").map((model) => model.trim()).filter(Boolean))] : [];
|
|
125231
|
+
const defaultModel = pillModelOf(provider, value);
|
|
125232
|
+
if (defaultModel.length > 0 && !models.includes(defaultModel)) models.unshift(defaultModel);
|
|
125233
|
+
return models;
|
|
125234
|
+
}
|
|
125235
|
+
function pillTargetKey(provider, channelId) {
|
|
125236
|
+
return provider === "openai-compat" ? `openai-compat:${channelId ?? "default"}` : provider;
|
|
125237
|
+
}
|
|
125109
125238
|
/** One fixed-position provider menu anchored to the pill button. */
|
|
125110
125239
|
function ImageProviderPill(props) {
|
|
125111
125240
|
const [snapshot, setSnapshot] = (0, react.useState)(() => props.scope.getSnapshot());
|
|
@@ -125113,15 +125242,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125113
125242
|
const [open, setOpen] = (0, react.useState)(false);
|
|
125114
125243
|
const [pending, setPending] = (0, react.useState)(void 0);
|
|
125115
125244
|
const [error, setError] = (0, react.useState)("");
|
|
125116
|
-
const [dots, setDots] = (0, react.useState)({
|
|
125117
|
-
google: "unknown",
|
|
125118
|
-
openai: "unknown",
|
|
125119
|
-
"openai-compat": "unknown",
|
|
125120
|
-
seedream: "unknown",
|
|
125121
|
-
dashscope: "unknown",
|
|
125122
|
-
xai: "unknown",
|
|
125123
|
-
zhipu: "unknown"
|
|
125124
|
-
});
|
|
125245
|
+
const [dots, setDots] = (0, react.useState)({});
|
|
125125
125246
|
const [keyTick, setKeyTick] = (0, react.useState)(0);
|
|
125126
125247
|
const [subDots, setSubDots] = (0, react.useState)(() => ({
|
|
125127
125248
|
"chatgpt-sub": "unknown",
|
|
@@ -125141,35 +125262,33 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125141
125262
|
}), [props.credentialEvents]);
|
|
125142
125263
|
(0, react.useEffect)(() => {
|
|
125143
125264
|
let active = true;
|
|
125144
|
-
const
|
|
125145
|
-
|
|
125146
|
-
|
|
125147
|
-
|
|
125148
|
-
|
|
125149
|
-
|
|
125265
|
+
const targets = [...CLOUD_IMAGE_PROVIDERS.filter((provider) => provider !== "openai-compat").map((provider) => ({
|
|
125266
|
+
key: provider,
|
|
125267
|
+
ref: cloudCredentialRef(provider)
|
|
125268
|
+
})), ...resolveOpenAICompatChannels(snapshot.value ?? {}).map((channel) => ({
|
|
125269
|
+
key: pillTargetKey("openai-compat", channel.id),
|
|
125270
|
+
ref: channel.keyRef
|
|
125271
|
+
}))];
|
|
125272
|
+
props.credentials.describe(targets.map((target) => target.ref)).then((response) => {
|
|
125150
125273
|
if (!active) return;
|
|
125151
125274
|
const next = {};
|
|
125152
|
-
for (const
|
|
125153
|
-
const info = response.ok ? response.value?.[
|
|
125154
|
-
next[
|
|
125275
|
+
for (const target of targets) {
|
|
125276
|
+
const info = response.ok ? response.value?.[target.ref] : void 0;
|
|
125277
|
+
next[target.key] = response.ok ? info?.configured ? "configured" : "missing" : "unknown";
|
|
125155
125278
|
}
|
|
125156
125279
|
setDots(next);
|
|
125157
125280
|
}).catch(() => {
|
|
125158
125281
|
if (!active) return;
|
|
125159
|
-
setDots({
|
|
125160
|
-
google: "unknown",
|
|
125161
|
-
openai: "unknown",
|
|
125162
|
-
"openai-compat": "unknown",
|
|
125163
|
-
seedream: "unknown",
|
|
125164
|
-
dashscope: "unknown",
|
|
125165
|
-
xai: "unknown",
|
|
125166
|
-
zhipu: "unknown"
|
|
125167
|
-
});
|
|
125282
|
+
setDots({});
|
|
125168
125283
|
});
|
|
125169
125284
|
return () => {
|
|
125170
125285
|
active = false;
|
|
125171
125286
|
};
|
|
125172
|
-
}, [
|
|
125287
|
+
}, [
|
|
125288
|
+
props.credentials,
|
|
125289
|
+
keyTick,
|
|
125290
|
+
snapshot.value
|
|
125291
|
+
]);
|
|
125173
125292
|
(0, react.useEffect)(() => {
|
|
125174
125293
|
if (!open) return;
|
|
125175
125294
|
let active = true;
|
|
@@ -125197,6 +125316,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125197
125316
|
}, [open, keyTick]);
|
|
125198
125317
|
const t = (keyName) => (lang === "en" ? PILL_DICT.en : PILL_DICT.zh)[keyName];
|
|
125199
125318
|
const current = snapshot.value?.provider ?? "google";
|
|
125319
|
+
const currentChannel = current === "openai-compat" ? resolveOpenAICompatChannel(snapshot.value ?? {}) : void 0;
|
|
125200
125320
|
const writable = snapshot.writable;
|
|
125201
125321
|
(0, react.useEffect)(() => {
|
|
125202
125322
|
if (!open) {
|
|
@@ -125244,15 +125364,27 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125244
125364
|
};
|
|
125245
125365
|
}, [open]);
|
|
125246
125366
|
if (!pillVisible(snapshot.value)) return null;
|
|
125247
|
-
|
|
125248
|
-
|
|
125249
|
-
|
|
125367
|
+
const select = (provider, model, channelId) => {
|
|
125368
|
+
const currentModel = pillModelOf(provider, snapshot.value, channelId);
|
|
125369
|
+
const sameChannel = provider !== "openai-compat" || currentChannel?.id === (channelId ?? "default");
|
|
125370
|
+
if (pending !== void 0 || provider === current && sameChannel && (model === void 0 || model === currentModel)) {
|
|
125250
125371
|
setOpen(false);
|
|
125251
125372
|
return;
|
|
125252
125373
|
}
|
|
125374
|
+
const modelField = model === void 0 ? void 0 : PILL_MODEL_FIELDS[provider];
|
|
125253
125375
|
setError("");
|
|
125254
125376
|
setPending(provider);
|
|
125255
|
-
|
|
125377
|
+
(async () => {
|
|
125378
|
+
if (model !== void 0 && provider === "openai-compat" && channelId !== void 0 && channelId !== "default") {
|
|
125379
|
+
const channels = (snapshot.value?.openaiCompatChannels ?? []).map((channel) => channel.id === channelId ? {
|
|
125380
|
+
...channel,
|
|
125381
|
+
model
|
|
125382
|
+
} : channel);
|
|
125383
|
+
await writeSetting(props.scope, "openaiCompatChannels", channels, t("writeRejected"));
|
|
125384
|
+
} else if (model !== void 0 && modelField !== void 0) await writeSetting(props.scope, modelField, model, t("writeRejected"));
|
|
125385
|
+
if (provider === "openai-compat" && channelId !== void 0 && currentChannel?.id !== channelId) await writeSetting(props.scope, "openaiCompatActiveChannel", channelId, t("writeRejected"));
|
|
125386
|
+
if (provider !== current) await writeSetting(props.scope, "provider", provider, t("writeRejected"));
|
|
125387
|
+
})().then(() => {
|
|
125256
125388
|
setOpen(false);
|
|
125257
125389
|
}).catch((cause) => {
|
|
125258
125390
|
setError(cause instanceof Error ? cause.message : String(cause));
|
|
@@ -125263,13 +125395,13 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125263
125395
|
/** Plan A dots: ComfyUI is always fixed blue (theme-independent); each
|
|
125264
125396
|
* subscription reflects its login state (green in, gray out); cloud rows
|
|
125265
125397
|
* reflect their API-key state as before. */
|
|
125266
|
-
const dotClassOf = (provider) => {
|
|
125398
|
+
const dotClassOf = (provider, channelId) => {
|
|
125267
125399
|
if (provider === "comfyui") return "dsh-ig-pill-dot-neutral";
|
|
125268
125400
|
if (isSubscriptionProvider(provider)) return subDots[provider] === "logged-in" ? "dsh-ig-pill-dot-ok" : "dsh-ig-pill-dot-missing";
|
|
125269
|
-
const dot = dots[provider];
|
|
125401
|
+
const dot = dots[pillTargetKey(provider, channelId)];
|
|
125270
125402
|
return dot === "configured" ? "dsh-ig-pill-dot-ok" : dot === "missing" ? "dsh-ig-pill-dot-missing" : "dsh-ig-pill-dot-neutral";
|
|
125271
125403
|
};
|
|
125272
|
-
const subtitleOf = (provider) => {
|
|
125404
|
+
const subtitleOf = (provider, includeModel = true, channelId) => {
|
|
125273
125405
|
if (provider === "comfyui") {
|
|
125274
125406
|
const workflow = pillModelOf(provider, snapshot.value);
|
|
125275
125407
|
return workflow.length > 0 ? `${t("noKeyNeeded")} · ${workflow}` : `${t("noKeyNeeded")} · ${t("noWorkflow")}`;
|
|
@@ -125279,12 +125411,17 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125279
125411
|
const stateText = state === "logged-in" ? t("subSignedIn") : state === "logged-out" ? t("subSignedOut") : t("subStatusUnknown");
|
|
125280
125412
|
return `${t("subNoKey")} · ${stateText} · ${pillModelOf(provider, snapshot.value)}`;
|
|
125281
125413
|
}
|
|
125282
|
-
const dot = dots[provider];
|
|
125283
|
-
const model = pillModelOf(provider, snapshot.value);
|
|
125284
|
-
|
|
125285
|
-
if (dot === "
|
|
125286
|
-
return
|
|
125414
|
+
const dot = dots[pillTargetKey(provider, channelId)];
|
|
125415
|
+
const model = pillModelOf(provider, snapshot.value, channelId);
|
|
125416
|
+
const modelSuffix = includeModel ? ` · ${model}` : "";
|
|
125417
|
+
if (dot === "configured") return `${t("keyConfigured")}${modelSuffix}`;
|
|
125418
|
+
if (dot === "missing") return `${t("keyMissing")}${modelSuffix}`;
|
|
125419
|
+
return includeModel ? model : "";
|
|
125287
125420
|
};
|
|
125421
|
+
const menuEntries = IMAGE_PROVIDERS.flatMap((provider) => provider === "openai-compat" ? resolveOpenAICompatChannels(snapshot.value ?? {}).map((channel) => ({
|
|
125422
|
+
provider,
|
|
125423
|
+
channel
|
|
125424
|
+
})) : [{ provider }]);
|
|
125288
125425
|
return (0, react_jsx_runtime.jsxs)("div", {
|
|
125289
125426
|
className: "dsh-ig-pill-root",
|
|
125290
125427
|
children: [(0, react_jsx_runtime.jsxs)("button", {
|
|
@@ -125328,7 +125465,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125328
125465
|
}),
|
|
125329
125466
|
(0, react_jsx_runtime.jsx)("span", {
|
|
125330
125467
|
className: "dsh-ig-pill-provider",
|
|
125331
|
-
children: PILL_PROVIDER_LABELS[lang][current]
|
|
125468
|
+
children: currentChannel?.label ?? PILL_PROVIDER_LABELS[lang][current]
|
|
125332
125469
|
}),
|
|
125333
125470
|
(0, react_jsx_runtime.jsx)("span", {
|
|
125334
125471
|
className: `dsh-ig-pill-caret${open ? " dsh-ig-pill-caret-open" : ""}`,
|
|
@@ -125356,47 +125493,83 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125356
125493
|
className: "dsh-ig-pill-menu-title",
|
|
125357
125494
|
children: t("menuTitle")
|
|
125358
125495
|
}),
|
|
125359
|
-
|
|
125360
|
-
|
|
125361
|
-
|
|
125362
|
-
"
|
|
125363
|
-
|
|
125364
|
-
|
|
125365
|
-
|
|
125366
|
-
|
|
125367
|
-
|
|
125368
|
-
|
|
125369
|
-
|
|
125370
|
-
|
|
125371
|
-
|
|
125372
|
-
}
|
|
125373
|
-
|
|
125374
|
-
|
|
125496
|
+
menuEntries.map(({ provider, channel }) => {
|
|
125497
|
+
const channelId = channel?.id;
|
|
125498
|
+
const modelOptions = pillModelOptionsOf(provider, snapshot.value, channelId);
|
|
125499
|
+
const active = provider === current && (provider !== "openai-compat" || currentChannel?.id === channelId);
|
|
125500
|
+
const currentModel = active ? pillModelOf(provider, snapshot.value, channelId) : "";
|
|
125501
|
+
return (0, react_jsx_runtime.jsxs)(react.Fragment, { children: [(0, react_jsx_runtime.jsxs)("button", {
|
|
125502
|
+
type: "button",
|
|
125503
|
+
role: modelOptions.length > 0 ? "menuitem" : "menuitemradio",
|
|
125504
|
+
"aria-checked": modelOptions.length > 0 ? void 0 : active,
|
|
125505
|
+
className: `dsh-ig-pill-option${active ? " dsh-ig-pill-option-active" : ""}`,
|
|
125506
|
+
disabled: pending !== void 0,
|
|
125507
|
+
onClick: () => {
|
|
125508
|
+
select(provider, void 0, channelId);
|
|
125509
|
+
},
|
|
125510
|
+
children: [
|
|
125511
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
125512
|
+
className: `dsh-ig-pill-dot ${dotClassOf(provider, channelId)}`,
|
|
125513
|
+
"aria-hidden": "true"
|
|
125514
|
+
}),
|
|
125515
|
+
(0, react_jsx_runtime.jsxs)("span", {
|
|
125516
|
+
className: "dsh-ig-pill-option-text",
|
|
125517
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
125518
|
+
className: "dsh-ig-pill-option-name",
|
|
125519
|
+
children: channel?.label ?? PILL_PROVIDER_LABELS[lang][provider]
|
|
125520
|
+
}), (0, react_jsx_runtime.jsx)("span", {
|
|
125521
|
+
className: "dsh-ig-pill-option-sub",
|
|
125522
|
+
children: subtitleOf(provider, modelOptions.length === 0, channelId)
|
|
125523
|
+
})]
|
|
125524
|
+
}),
|
|
125525
|
+
active && modelOptions.length === 0 ? (0, react_jsx_runtime.jsx)("span", {
|
|
125526
|
+
className: "dsh-ig-pill-check",
|
|
125527
|
+
"aria-hidden": "true",
|
|
125528
|
+
children: (0, react_jsx_runtime.jsx)("svg", {
|
|
125529
|
+
width: "13",
|
|
125530
|
+
height: "13",
|
|
125531
|
+
viewBox: "0 0 16 16",
|
|
125532
|
+
fill: "none",
|
|
125533
|
+
stroke: "currentColor",
|
|
125534
|
+
strokeWidth: "2.2",
|
|
125535
|
+
strokeLinecap: "round",
|
|
125536
|
+
strokeLinejoin: "round",
|
|
125537
|
+
children: (0, react_jsx_runtime.jsx)("path", { d: "M2.5 8.5l3.5 3.5 7-8" })
|
|
125538
|
+
})
|
|
125539
|
+
}) : null
|
|
125540
|
+
]
|
|
125541
|
+
}), modelOptions.map((model) => {
|
|
125542
|
+
const selected = active && model === currentModel;
|
|
125543
|
+
return (0, react_jsx_runtime.jsxs)("button", {
|
|
125544
|
+
type: "button",
|
|
125545
|
+
role: "menuitemradio",
|
|
125546
|
+
"aria-checked": selected,
|
|
125547
|
+
className: `dsh-ig-pill-option dsh-ig-pill-model-option${selected ? " dsh-ig-pill-option-active" : ""}`,
|
|
125548
|
+
disabled: pending !== void 0,
|
|
125549
|
+
onClick: () => {
|
|
125550
|
+
select(provider, model, channelId);
|
|
125551
|
+
},
|
|
125375
125552
|
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
125376
|
-
className: "dsh-ig-pill-
|
|
125377
|
-
children:
|
|
125378
|
-
}), (0, react_jsx_runtime.jsx)("span", {
|
|
125379
|
-
className: "dsh-ig-pill-
|
|
125380
|
-
|
|
125381
|
-
|
|
125382
|
-
|
|
125383
|
-
|
|
125384
|
-
|
|
125385
|
-
|
|
125386
|
-
|
|
125387
|
-
|
|
125388
|
-
|
|
125389
|
-
|
|
125390
|
-
|
|
125391
|
-
|
|
125392
|
-
|
|
125393
|
-
|
|
125394
|
-
|
|
125395
|
-
|
|
125396
|
-
})
|
|
125397
|
-
}) : null
|
|
125398
|
-
]
|
|
125399
|
-
}, provider)),
|
|
125553
|
+
className: "dsh-ig-pill-model-name",
|
|
125554
|
+
children: model
|
|
125555
|
+
}), selected ? (0, react_jsx_runtime.jsx)("span", {
|
|
125556
|
+
className: "dsh-ig-pill-check",
|
|
125557
|
+
"aria-hidden": "true",
|
|
125558
|
+
children: (0, react_jsx_runtime.jsx)("svg", {
|
|
125559
|
+
width: "13",
|
|
125560
|
+
height: "13",
|
|
125561
|
+
viewBox: "0 0 16 16",
|
|
125562
|
+
fill: "none",
|
|
125563
|
+
stroke: "currentColor",
|
|
125564
|
+
strokeWidth: "2.2",
|
|
125565
|
+
strokeLinecap: "round",
|
|
125566
|
+
strokeLinejoin: "round",
|
|
125567
|
+
children: (0, react_jsx_runtime.jsx)("path", { d: "M2.5 8.5l3.5 3.5 7-8" })
|
|
125568
|
+
})
|
|
125569
|
+
}) : null]
|
|
125570
|
+
}, model);
|
|
125571
|
+
})] }, channelId === void 0 ? provider : pillTargetKey("openai-compat", channelId));
|
|
125572
|
+
}),
|
|
125400
125573
|
error.length > 0 ? (0, react_jsx_runtime.jsxs)("div", {
|
|
125401
125574
|
className: "dsh-ig-pill-error",
|
|
125402
125575
|
role: "alert",
|
|
@@ -125440,12 +125613,14 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125440
125613
|
.dsh-ig-pill-option-text{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
|
|
125441
125614
|
.dsh-ig-pill-option-name{font-size:12.5px;font-weight:500;color:var(--dsw-alias-label-primary,#111827);line-height:1.2}
|
|
125442
125615
|
.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}
|
|
125616
|
+
.dsh-ig-pill-model-option{padding-left:24px}
|
|
125617
|
+
.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}
|
|
125443
125618
|
.dsh-ig-pill-check{flex:none;color:var(--dsw-alias-brand-primary,#4c78ff)}
|
|
125444
125619
|
.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}
|
|
125445
125620
|
`;
|
|
125446
125621
|
//#endregion
|
|
125447
125622
|
//#region lib/types/client/index.js
|
|
125448
|
-
console.info(`[dsh-image-gen] canvas bundle 2026-
|
|
125623
|
+
console.info(`[dsh-image-gen] canvas bundle 2026-11-01T16:40:54.993Z`);
|
|
125449
125624
|
/** Right-sidebar tab-type registration id (DSH 0.1.5 `sidebarRightTabs`). */
|
|
125450
125625
|
const SIDEBAR_STUDIO_TAB_ID = "dsh-image-gen/studio";
|
|
125451
125626
|
/** The tab kind: a page type opened by kind, recognizing no resource address. */
|
|
@@ -125464,6 +125639,11 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125464
125639
|
providerGoogle: "Google Gemini",
|
|
125465
125640
|
providerOpenAI: "OpenAI",
|
|
125466
125641
|
providerOpenAICompat: "OpenAI 兼容(中转站)",
|
|
125642
|
+
addCompatChannel: "新增 OpenAI 兼容渠道",
|
|
125643
|
+
channelName: "渠道名称",
|
|
125644
|
+
channelNameRequired: "请填写渠道名称。",
|
|
125645
|
+
removeChannel: "删除渠道",
|
|
125646
|
+
removeChannelConfirm: "确定删除“{label}”吗?该渠道的配置将被移除。",
|
|
125467
125647
|
providerSeedream: "字节 Seedream",
|
|
125468
125648
|
providerDashScope: "阿里 DashScope (通义万相 / Qwen)",
|
|
125469
125649
|
providerXAI: "xAI Grok Imagine",
|
|
@@ -125570,6 +125750,10 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125570
125750
|
endpointHintZhipu: "智谱开放平台 open.bigmodel.cn 的 /api/paas/v4 地址。",
|
|
125571
125751
|
endpointHintComfyUI: "正在运行且 DSH Host 可以访问的 ComfyUI 地址,默认使用本机 8188 端口。",
|
|
125572
125752
|
model: "模型",
|
|
125753
|
+
defaultModel: "默认模型",
|
|
125754
|
+
availableModels: "工作台可选模型",
|
|
125755
|
+
availableModelsHint: "勾选后可在工作台切换。手动输入的默认模型会自动加入列表,且不可移除。",
|
|
125756
|
+
defaultModelTag: "默认",
|
|
125573
125757
|
workflow: "API Workflow 工作流",
|
|
125574
125758
|
workflowImport: "导入 JSON 文件",
|
|
125575
125759
|
workflowMissing: "尚未导入工作流",
|
|
@@ -125584,6 +125768,8 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125584
125768
|
workflowDuplicateName: "工作流名称不能重复。",
|
|
125585
125769
|
timeout: "生成超时(秒)",
|
|
125586
125770
|
timeoutHint: "包括提交、等待和下载图片;默认 300 秒。",
|
|
125771
|
+
cloudTimeout: "云端生成超时(秒)",
|
|
125772
|
+
cloudTimeoutHint: "工作台所有 API Key 通道共用,5–3600 秒,默认 150 秒。不影响订阅通道和 ComfyUI;修改后对新请求生效。",
|
|
125587
125773
|
workspaceSection: "工作区",
|
|
125588
125774
|
saveToWorkspace: "保存到工作区",
|
|
125589
125775
|
saveToWorkspaceHint: "每次生成后,把图片文件保存到当前会话工作区。",
|
|
@@ -125637,7 +125823,12 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125637
125823
|
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.",
|
|
125638
125824
|
providerGoogle: "Google Gemini",
|
|
125639
125825
|
providerOpenAI: "OpenAI",
|
|
125640
|
-
providerOpenAICompat: "OpenAI
|
|
125826
|
+
providerOpenAICompat: "OpenAI Compatible (relay)",
|
|
125827
|
+
addCompatChannel: "Add OpenAI-compatible channel",
|
|
125828
|
+
channelName: "Channel name",
|
|
125829
|
+
channelNameRequired: "Enter a channel name.",
|
|
125830
|
+
removeChannel: "Remove channel",
|
|
125831
|
+
removeChannelConfirm: "Remove \"{label}\"? Its channel configuration will be deleted.",
|
|
125641
125832
|
providerSeedream: "ByteDance Seedream",
|
|
125642
125833
|
providerDashScope: "Aliyun DashScope (Wanx / Qwen)",
|
|
125643
125834
|
providerXAI: "xAI Grok Imagine",
|
|
@@ -125744,6 +125935,10 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125744
125935
|
endpointHintZhipu: "Zhipu open.bigmodel.cn /api/paas/v4 base URL.",
|
|
125745
125936
|
endpointHintComfyUI: "A running ComfyUI server reachable by the DSH Host; the default points to port 8188 on this computer.",
|
|
125746
125937
|
model: "Model",
|
|
125938
|
+
defaultModel: "Default model",
|
|
125939
|
+
availableModels: "Models available in Studio",
|
|
125940
|
+
availableModelsHint: "Selected models can be switched in Studio. A manually entered default is added automatically and cannot be removed.",
|
|
125941
|
+
defaultModelTag: "Default",
|
|
125747
125942
|
workflow: "API Workflows",
|
|
125748
125943
|
workflowImport: "Import JSON file",
|
|
125749
125944
|
workflowMissing: "No workflow imported",
|
|
@@ -125758,6 +125953,8 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125758
125953
|
workflowDuplicateName: "Workflow names must be unique.",
|
|
125759
125954
|
timeout: "Generation timeout (seconds)",
|
|
125760
125955
|
timeoutHint: "Covers submission, waiting, and image download; defaults to 300 seconds.",
|
|
125956
|
+
cloudTimeout: "Cloud generation timeout (seconds)",
|
|
125957
|
+
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.",
|
|
125761
125958
|
workspaceSection: "Workspace",
|
|
125762
125959
|
saveToWorkspace: "Save to workspace",
|
|
125763
125960
|
saveToWorkspaceHint: "Write each generated image as a file into the session workspace.",
|
|
@@ -125834,26 +126031,35 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125834
126031
|
.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)}
|
|
125835
126032
|
.dsh-ig-check-row{display:flex;align-items:center;gap:8px;cursor:pointer}
|
|
125836
126033
|
.dsh-ig-check-row input[type=checkbox]{width:15px;height:15px;accent-color:var(--dsw-alias-brand-primary,#4c78ff);margin:0}
|
|
126034
|
+
.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}
|
|
126035
|
+
.dsh-ig-model-picker .dsh-ig-check-row{min-width:0}
|
|
126036
|
+
.dsh-ig-model-option{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:12px}
|
|
126037
|
+
.dsh-ig-model-default{flex:none;color:var(--dsw-alias-label-tertiary,#7b818b);font-size:11px}
|
|
125837
126038
|
.dsh-ig-savedto{font-size:12px;line-height:1.5;color:var(--dsw-alias-label-tertiary,#7b818b);word-break:break-all}
|
|
125838
126039
|
.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}
|
|
125839
126040
|
.dsh-ig-save:disabled{opacity:.4;cursor:default}
|
|
125840
126041
|
|
|
125841
126042
|
/* Provider list: one expandable row per provider, each saving independently. */
|
|
125842
|
-
.dsh-ig-providers{display:flex;flex-direction:column;margin-top:
|
|
125843
|
-
.dsh-ig-provider-row{border:0;background:none;padding:14px
|
|
125844
|
-
.dsh-ig-provider-row + .dsh-ig-provider-row{border-top:
|
|
125845
|
-
.dsh-ig-provider-head{
|
|
126043
|
+
.dsh-ig-providers{display:flex;flex-direction:column;margin-top:12px;overflow:hidden;border:1px solid var(--dsw-alias-border-l2,#e8ebf0);border-radius:10px;background:var(--dsw-alias-bg-layer-3,transparent)}
|
|
126044
|
+
.dsh-ig-provider-row{border:0;background:none;padding:0 14px}
|
|
126045
|
+
.dsh-ig-provider-row + .dsh-ig-provider-row{border-top:1px solid var(--dsw-alias-border-l2,#e8ebf0)}
|
|
126046
|
+
.dsh-ig-provider-head-row{display:flex;align-items:center;gap:8px;min-height:48px}
|
|
126047
|
+
.dsh-ig-provider-head{flex:1;min-width:0;width:100%;min-height:48px;appearance:none;border:0;background:none;font:inherit;color:inherit;text-align:left;cursor:pointer;display:flex;align-items:center;gap:10px;padding:0}
|
|
126048
|
+
.dsh-ig-channel-add.dsh-ig-btn-secondary{display:inline-flex;align-items:center;justify-content:center;flex:none;box-sizing:border-box;width:26px;height:26px;padding:0;border:0;border-radius:7px;background:var(--dsw-alias-bg-layer-2,#f3f4f6);color:var(--dsw-alias-label-tertiary,#7b818b);line-height:1;transition:background .15s,color .15s}
|
|
126049
|
+
.dsh-ig-channel-add.dsh-ig-btn-secondary:hover:not(:disabled){border:0;background:var(--dsw-alias-bg-layer-1,#e5e7eb);color:var(--dsw-alias-label-primary,inherit)}
|
|
126050
|
+
.dsh-ig-channel-add svg{width:14px;height:14px}
|
|
125846
126051
|
.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)}
|
|
125847
|
-
.dsh-ig-provider-head:hover .dsh-ig-provider-name{color:var(--dsw-alias-label-
|
|
125848
|
-
.dsh-ig-provider-
|
|
125849
|
-
.dsh-ig-provider-
|
|
126052
|
+
.dsh-ig-provider-head:hover .dsh-ig-provider-name{color:var(--dsw-alias-label-primary,inherit)}
|
|
126053
|
+
.dsh-ig-provider-head:hover .dsh-ig-provider-chevron{color:var(--dsw-alias-label-primary,inherit)}
|
|
126054
|
+
.dsh-ig-provider-name{flex:1;min-width:0;font-size:13px;font-weight:550;line-height:20px;color:var(--dsw-alias-label-primary,inherit);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
126055
|
+
.dsh-ig-provider-chevron{display:inline-flex;align-items:center;justify-content:center;flex:none;width:20px;height:20px;color:var(--dsw-alias-label-tertiary,#7b818b);transition:transform .16s,color .15s}
|
|
125850
126056
|
.dsh-ig-provider-chevron-open{transform:rotate(180deg)}
|
|
125851
|
-
.dsh-ig-provider-body{border-top:0;padding:
|
|
125852
|
-
.dsh-ig-badge{flex:none;display:inline-flex;align-items:center;gap:5px;
|
|
125853
|
-
.dsh-ig-badge-dot{width:
|
|
125854
|
-
.dsh-ig-badge-ok{border-color:rgba(34,197,94,.
|
|
125855
|
-
.dsh-ig-badge-missing{border-color:rgba(239,68,68,.
|
|
125856
|
-
.dsh-ig-badge-neutral{color:var(--dsw-alias-label-tertiary,#7b818b)}
|
|
126057
|
+
.dsh-ig-provider-body{border-top:0;padding:0 0 14px}
|
|
126058
|
+
.dsh-ig-badge{flex:none;display:inline-flex;align-items:center;gap:5px;box-sizing:border-box;min-height:22px;padding:1px 8px;border:1px solid transparent;border-radius:6px;font-size:11px;font-weight:500;line-height:18px;color:var(--dsw-alias-label-secondary,inherit);white-space:nowrap;max-width:60%;overflow:hidden;text-overflow:ellipsis}
|
|
126059
|
+
.dsh-ig-badge-dot{width:5px;height:5px;border-radius:50%;background:currentColor;flex:none}
|
|
126060
|
+
.dsh-ig-badge-ok{border-color:rgba(34,197,94,.2);color:#15803d;background:rgba(34,197,94,.08)}
|
|
126061
|
+
.dsh-ig-badge-missing{border-color:rgba(239,68,68,.18);color:#b91c1c;background:rgba(239,68,68,.06)}
|
|
126062
|
+
.dsh-ig-badge-neutral{border-color:var(--dsw-alias-border-l2,#e8ebf0);color:var(--dsw-alias-label-tertiary,#7b818b);background:var(--dsw-alias-bg-layer-2,transparent)}
|
|
125857
126063
|
.dsh-ig-badge-checking .dsh-ig-badge-dot{animation:dsh-ig-pulse 1s ease-in-out infinite}
|
|
125858
126064
|
@keyframes dsh-ig-pulse{50%{opacity:.25}}
|
|
125859
126065
|
|
|
@@ -126344,7 +126550,9 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126344
126550
|
function emptyProviderRow() {
|
|
126345
126551
|
return {
|
|
126346
126552
|
expanded: false,
|
|
126553
|
+
label: "",
|
|
126347
126554
|
model: "",
|
|
126555
|
+
models: [],
|
|
126348
126556
|
editModel: "",
|
|
126349
126557
|
baseURL: "",
|
|
126350
126558
|
googleNative: false,
|
|
@@ -126430,6 +126638,28 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126430
126638
|
function parseEditFormat(value) {
|
|
126431
126639
|
return value === "jsonImageUrlArray" || value === "formReferenceImages" || value === "siliconflowJson" ? value : "multipart";
|
|
126432
126640
|
}
|
|
126641
|
+
function compatChannelRowKey(channelId) {
|
|
126642
|
+
return `openai-compat:${channelId}`;
|
|
126643
|
+
}
|
|
126644
|
+
function compatRowFields(channel) {
|
|
126645
|
+
return {
|
|
126646
|
+
label: channel.label,
|
|
126647
|
+
model: channel.model,
|
|
126648
|
+
models: resolveOpenAICompatModels({
|
|
126649
|
+
openaiCompatModel: channel.model,
|
|
126650
|
+
openaiCompatModels: channel.models ?? []
|
|
126651
|
+
}),
|
|
126652
|
+
editModel: channel.editModel ?? "",
|
|
126653
|
+
baseURL: channel.baseURL,
|
|
126654
|
+
editFormat: parseEditFormat(channel.editFormat),
|
|
126655
|
+
editExtraText: editExtraTextOf(channel.editExtra),
|
|
126656
|
+
sizeTableText: editExtraTextOf(channel.sizes),
|
|
126657
|
+
generationQuality: channel.quality ?? "",
|
|
126658
|
+
qualityOptionsText: (channel.qualityOptions !== void 0 && channel.qualityOptions.length > 0 ? channel.qualityOptions : DEFAULT_COMPAT_QUALITIES).join(", "),
|
|
126659
|
+
generateExtraText: editExtraTextOf(channel.extraBody),
|
|
126660
|
+
editSizeMode: channel.editSizeMode === "selected" ? "selected" : "auto"
|
|
126661
|
+
};
|
|
126662
|
+
}
|
|
126433
126663
|
/** Build one row per provider from persisted settings, including ComfyUI extras. */
|
|
126434
126664
|
function rowsFromSettings(value) {
|
|
126435
126665
|
const rows = {};
|
|
@@ -126444,22 +126674,17 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126444
126674
|
activeWorkflow: activeComfyUIWorkflow(value ?? {})?.name ?? "",
|
|
126445
126675
|
timeoutSeconds: Math.max(1, Math.round((value?.comfyuiTimeoutMs ?? 3e5) / 1e3))
|
|
126446
126676
|
} : {},
|
|
126447
|
-
...provider === "openai-compat" ? {
|
|
126448
|
-
editModel: value?.openaiCompatEditModel ?? "",
|
|
126449
|
-
editFormat: parseEditFormat(value?.openaiCompatEditFormat),
|
|
126450
|
-
editExtraText: editExtraTextOf(value?.openaiCompatEditExtra),
|
|
126451
|
-
sizeTableText: editExtraTextOf(value?.openaiCompatSizes),
|
|
126452
|
-
generationQuality: value?.openaiCompatQuality ?? "",
|
|
126453
|
-
qualityOptionsText: (value?.openaiCompatQualityOptions ?? DEFAULT_COMPAT_QUALITIES).join(", "),
|
|
126454
|
-
generateExtraText: editExtraTextOf(value?.openaiCompatExtraBody),
|
|
126455
|
-
editSizeMode: value?.openaiCompatEditSizeMode === "selected" ? "selected" : "auto"
|
|
126456
|
-
} : {},
|
|
126677
|
+
...provider === "openai-compat" ? compatRowFields(resolveOpenAICompatChannels(value ?? {})[0]) : {},
|
|
126457
126678
|
...provider === "seedream" ? {
|
|
126458
126679
|
outputFormat: value?.seedreamOutputFormat === "png" ? "png" : "jpeg",
|
|
126459
126680
|
watermark: value?.seedreamWatermark !== false,
|
|
126460
126681
|
background: value?.seedreamBackground === "transparent" ? "transparent" : "opaque"
|
|
126461
126682
|
} : {}
|
|
126462
126683
|
};
|
|
126684
|
+
for (const channel of resolveOpenAICompatChannels(value ?? {}).slice(1)) rows[compatChannelRowKey(channel.id)] = {
|
|
126685
|
+
...emptyProviderRow(),
|
|
126686
|
+
...compatRowFields(channel)
|
|
126687
|
+
};
|
|
126463
126688
|
return rows;
|
|
126464
126689
|
}
|
|
126465
126690
|
/** Edit each provider independently, pick an explicit default, and verify keys inline. */
|
|
@@ -126473,6 +126698,8 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126473
126698
|
const [defaultProvider, setDefaultProvider] = (0, react.useState)(() => props.scope.getSnapshot().value?.provider ?? "google");
|
|
126474
126699
|
const [providerMessage, setProviderMessage] = (0, react.useState)("");
|
|
126475
126700
|
const [providerMessageIsError, setProviderMessageIsError] = (0, react.useState)(false);
|
|
126701
|
+
const [cloudTimeoutSeconds, setCloudTimeoutSeconds] = (0, react.useState)(() => (props.scope.getSnapshot().value?.cloudTimeoutMs ?? 15e4) / 1e3);
|
|
126702
|
+
const [cloudTimeoutMessage, setCloudTimeoutMessage] = (0, react.useState)("");
|
|
126476
126703
|
const [saveToWorkspace, setSaveToWorkspace] = (0, react.useState)(() => props.scope.getSnapshot().value?.saveToWorkspace ?? true);
|
|
126477
126704
|
const [workspaceFolder, setWorkspaceFolder] = (0, react.useState)(() => props.scope.getSnapshot().value?.workspaceFolder ?? "dsh-image-gen");
|
|
126478
126705
|
const [showPill, setShowPill] = (0, react.useState)(() => props.scope.getSnapshot().value?.showProviderPill === true);
|
|
@@ -126481,6 +126708,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126481
126708
|
const [workspaceMessage, setWorkspaceMessage] = (0, react.useState)("");
|
|
126482
126709
|
const [workspaceMessageIsError, setWorkspaceMessageIsError] = (0, react.useState)(false);
|
|
126483
126710
|
const [rows, setRows] = (0, react.useState)(() => rowsFromSettings(props.scope.getSnapshot().value));
|
|
126711
|
+
const [compatChannels, setCompatChannels] = (0, react.useState)(() => resolveOpenAICompatChannels(props.scope.getSnapshot().value ?? {}).slice(1));
|
|
126484
126712
|
const [keyTick, setKeyTick] = (0, react.useState)(0);
|
|
126485
126713
|
const [subStatus, setSubStatus] = (0, react.useState)(() => ({
|
|
126486
126714
|
"chatgpt-sub": { state: "unknown" },
|
|
@@ -126690,15 +126918,16 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126690
126918
|
(0, react.useEffect)(() => {
|
|
126691
126919
|
const value = snapshot.value;
|
|
126692
126920
|
setDefaultProvider(value?.provider ?? "google");
|
|
126921
|
+
setCloudTimeoutSeconds((value?.cloudTimeoutMs ?? 15e4) / 1e3);
|
|
126693
126922
|
setSaveToWorkspace(value?.saveToWorkspace ?? true);
|
|
126694
126923
|
setWorkspaceFolder(value?.workspaceFolder ?? "dsh-image-gen");
|
|
126695
126924
|
setShowPill(value?.showProviderPill === true);
|
|
126696
126925
|
setRows((current) => {
|
|
126697
|
-
const next = {};
|
|
126926
|
+
const next = { ...current };
|
|
126698
126927
|
for (const provider of IMAGE_PROVIDERS) next[provider] = {
|
|
126699
126928
|
...current[provider],
|
|
126700
126929
|
model: modelOf(provider, value),
|
|
126701
|
-
...provider === "openai-compat" ?
|
|
126930
|
+
...provider === "openai-compat" ? compatRowFields(resolveOpenAICompatChannels(value ?? {})[0]) : {},
|
|
126702
126931
|
baseURL: baseURLOf(provider, value),
|
|
126703
126932
|
...provider === "comfyui" ? {
|
|
126704
126933
|
workflows: resolveComfyUIWorkflows(value ?? {}),
|
|
@@ -126711,6 +126940,13 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126711
126940
|
background: value?.seedreamBackground === "transparent" ? "transparent" : "opaque"
|
|
126712
126941
|
} : {}
|
|
126713
126942
|
};
|
|
126943
|
+
for (const channel of resolveOpenAICompatChannels(value ?? {}).slice(1)) {
|
|
126944
|
+
const key = compatChannelRowKey(channel.id);
|
|
126945
|
+
next[key] = {
|
|
126946
|
+
...current[key] ?? emptyProviderRow(),
|
|
126947
|
+
...compatRowFields(channel)
|
|
126948
|
+
};
|
|
126949
|
+
}
|
|
126714
126950
|
return next;
|
|
126715
126951
|
});
|
|
126716
126952
|
}, [snapshot]);
|
|
@@ -126718,11 +126954,21 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126718
126954
|
const credentialsAvailable = props.credentialsAvailable;
|
|
126719
126955
|
(0, react.useEffect)(() => {
|
|
126720
126956
|
let active = true;
|
|
126957
|
+
const targets = [...CLOUD_IMAGE_PROVIDERS.flatMap((provider) => {
|
|
126958
|
+
const keyRef = cloudCredentialRef(provider);
|
|
126959
|
+
return keyRef === void 0 ? [] : [{
|
|
126960
|
+
key: provider,
|
|
126961
|
+
keyRef
|
|
126962
|
+
}];
|
|
126963
|
+
}), ...compatChannels.map((channel) => ({
|
|
126964
|
+
key: compatChannelRowKey(channel.id),
|
|
126965
|
+
keyRef: channel.keyRef
|
|
126966
|
+
}))];
|
|
126721
126967
|
if (!credentialsAvailable()) {
|
|
126722
126968
|
setRows((current) => {
|
|
126723
126969
|
const next = { ...current };
|
|
126724
|
-
for (const
|
|
126725
|
-
...current[
|
|
126970
|
+
for (const target of targets) next[target.key] = {
|
|
126971
|
+
...current[target.key] ?? emptyProviderRow(),
|
|
126726
126972
|
keyStatus: "unavailable",
|
|
126727
126973
|
keyInfo: void 0
|
|
126728
126974
|
};
|
|
@@ -126732,23 +126978,21 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126732
126978
|
active = false;
|
|
126733
126979
|
};
|
|
126734
126980
|
}
|
|
126735
|
-
for (const
|
|
126736
|
-
const keyRef = cloudCredentialRef(provider);
|
|
126737
|
-
if (keyRef === void 0) continue;
|
|
126981
|
+
for (const target of targets) {
|
|
126738
126982
|
setRows((current) => ({
|
|
126739
126983
|
...current,
|
|
126740
|
-
[
|
|
126741
|
-
...current[
|
|
126984
|
+
[target.key]: {
|
|
126985
|
+
...current[target.key],
|
|
126742
126986
|
keyStatus: "checking"
|
|
126743
126987
|
}
|
|
126744
126988
|
}));
|
|
126745
|
-
credentials.describe([keyRef]).then((response) => {
|
|
126989
|
+
credentials.describe([target.keyRef]).then((response) => {
|
|
126746
126990
|
if (!active) return;
|
|
126747
|
-
const info = response.ok ? response.value?.[keyRef] : void 0;
|
|
126991
|
+
const info = response.ok ? response.value?.[target.keyRef] : void 0;
|
|
126748
126992
|
setRows((current) => ({
|
|
126749
126993
|
...current,
|
|
126750
|
-
[
|
|
126751
|
-
...current[
|
|
126994
|
+
[target.key]: {
|
|
126995
|
+
...current[target.key],
|
|
126752
126996
|
keyStatus: response.ok ? info?.configured ? "configured" : "missing" : "unknown",
|
|
126753
126997
|
keyInfo: info
|
|
126754
126998
|
}
|
|
@@ -126757,8 +127001,8 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126757
127001
|
if (!active) return;
|
|
126758
127002
|
setRows((current) => ({
|
|
126759
127003
|
...current,
|
|
126760
|
-
[
|
|
126761
|
-
...current[
|
|
127004
|
+
[target.key]: {
|
|
127005
|
+
...current[target.key],
|
|
126762
127006
|
keyStatus: "unknown"
|
|
126763
127007
|
}
|
|
126764
127008
|
}));
|
|
@@ -126770,13 +127014,14 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126770
127014
|
}, [
|
|
126771
127015
|
credentials,
|
|
126772
127016
|
credentialsAvailable,
|
|
126773
|
-
keyTick
|
|
127017
|
+
keyTick,
|
|
127018
|
+
compatChannels
|
|
126774
127019
|
]);
|
|
126775
|
-
const updateRow = (
|
|
127020
|
+
const updateRow = (target, patch) => {
|
|
126776
127021
|
setRows((current) => ({
|
|
126777
127022
|
...current,
|
|
126778
|
-
[
|
|
126779
|
-
...current[
|
|
127023
|
+
[target]: {
|
|
127024
|
+
...current[target],
|
|
126780
127025
|
...patch
|
|
126781
127026
|
}
|
|
126782
127027
|
}));
|
|
@@ -126792,15 +127037,49 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126792
127037
|
setProviderMessageIsError(true);
|
|
126793
127038
|
});
|
|
126794
127039
|
};
|
|
126795
|
-
const saveProviderRow = async (provider) => {
|
|
126796
|
-
const
|
|
126797
|
-
|
|
127040
|
+
const saveProviderRow = async (provider, channel) => {
|
|
127041
|
+
const target = channel === void 0 ? provider : compatChannelRowKey(channel.id);
|
|
127042
|
+
const row = rows[target];
|
|
127043
|
+
updateRow(target, {
|
|
126798
127044
|
saving: true,
|
|
126799
127045
|
message: "",
|
|
126800
127046
|
messageIsError: false
|
|
126801
127047
|
});
|
|
126802
127048
|
try {
|
|
126803
|
-
if (
|
|
127049
|
+
if (channel !== void 0) {
|
|
127050
|
+
const label = row.label.trim();
|
|
127051
|
+
if (label.length === 0) throw new Error(t("channelNameRequired"));
|
|
127052
|
+
const updated = {
|
|
127053
|
+
...channel,
|
|
127054
|
+
label,
|
|
127055
|
+
baseURL: row.baseURL.trim(),
|
|
127056
|
+
model: row.model.trim(),
|
|
127057
|
+
models: resolveOpenAICompatModels({
|
|
127058
|
+
openaiCompatModel: row.model,
|
|
127059
|
+
openaiCompatModels: row.models
|
|
127060
|
+
}),
|
|
127061
|
+
editModel: row.editModel.trim(),
|
|
127062
|
+
quality: row.generationQuality.trim(),
|
|
127063
|
+
qualityOptions: [...new Set(row.qualityOptionsText.split(",").map((value) => value.trim()).filter(Boolean))],
|
|
127064
|
+
extraBody: parseExtraFields(row.generateExtraText, t("editExtraInvalid")),
|
|
127065
|
+
editSizeMode: row.editSizeMode,
|
|
127066
|
+
editFormat: row.editFormat,
|
|
127067
|
+
editExtra: parseExtraFields(row.editExtraText, t("editExtraInvalid")),
|
|
127068
|
+
sizes: parseSizeTable(row.sizeTableText, t("sizeTableInvalid"))
|
|
127069
|
+
};
|
|
127070
|
+
const nextChannels = compatChannels.some((entry) => entry.id === channel.id) ? compatChannels.map((entry) => entry.id === channel.id ? updated : entry) : [...compatChannels, updated];
|
|
127071
|
+
await saveSetting("openaiCompatChannels", nextChannels);
|
|
127072
|
+
setCompatChannels(nextChannels);
|
|
127073
|
+
if (row.keyInput.trim().length > 0) {
|
|
127074
|
+
if (!credentialsAvailable()) throw new Error(t("credentialsUnavailable"));
|
|
127075
|
+
const response = await props.credentials.set(channel.keyRef, row.keyInput.trim());
|
|
127076
|
+
if (!response.ok) throw new Error(response.error?.message ?? t("saveKeyFailed"));
|
|
127077
|
+
updateRow(target, {
|
|
127078
|
+
keyInput: "",
|
|
127079
|
+
keyStatus: "configured"
|
|
127080
|
+
});
|
|
127081
|
+
}
|
|
127082
|
+
} else if (provider === "comfyui") {
|
|
126804
127083
|
const entries = row.workflows.map((entry) => ({
|
|
126805
127084
|
name: entry.name.trim(),
|
|
126806
127085
|
json: entry.json,
|
|
@@ -126829,6 +127108,11 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126829
127108
|
if (provider === "google") await saveSetting("googleNative", row.googleNative);
|
|
126830
127109
|
if (provider === "openai") await saveSetting("openaiSizes", sizeTable);
|
|
126831
127110
|
if (provider === "openai-compat") {
|
|
127111
|
+
await saveSetting("openaiCompatLabel", row.label.trim());
|
|
127112
|
+
await saveSetting("openaiCompatModels", resolveOpenAICompatModels({
|
|
127113
|
+
openaiCompatModel: row.model,
|
|
127114
|
+
openaiCompatModels: row.models
|
|
127115
|
+
}));
|
|
126832
127116
|
await saveSetting("openaiCompatEditModel", row.editModel.trim());
|
|
126833
127117
|
await saveSetting("openaiCompatEditFormat", row.editFormat);
|
|
126834
127118
|
await saveSetting("openaiCompatEditExtra", editExtra);
|
|
@@ -126849,13 +127133,13 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126849
127133
|
if (!credentialsAvailable()) throw new Error(t("credentialsUnavailable"));
|
|
126850
127134
|
const response = await props.credentials.set(keyRef, row.keyInput.trim());
|
|
126851
127135
|
if (!response.ok) throw new Error(response.error?.message ?? t("saveKeyFailed"));
|
|
126852
|
-
updateRow(
|
|
127136
|
+
updateRow(target, {
|
|
126853
127137
|
keyInput: "",
|
|
126854
127138
|
keyStatus: "configured"
|
|
126855
127139
|
});
|
|
126856
127140
|
}
|
|
126857
127141
|
}
|
|
126858
|
-
updateRow(
|
|
127142
|
+
updateRow(target, {
|
|
126859
127143
|
message: t("saved"),
|
|
126860
127144
|
messageIsError: false,
|
|
126861
127145
|
testResult: void 0,
|
|
@@ -126863,38 +127147,99 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126863
127147
|
modelFetchIsError: false
|
|
126864
127148
|
});
|
|
126865
127149
|
} catch (cause) {
|
|
126866
|
-
updateRow(
|
|
127150
|
+
updateRow(target, {
|
|
127151
|
+
message: cause instanceof Error ? cause.message : String(cause),
|
|
127152
|
+
messageIsError: true
|
|
127153
|
+
});
|
|
127154
|
+
} finally {
|
|
127155
|
+
updateRow(target, { saving: false });
|
|
127156
|
+
}
|
|
127157
|
+
};
|
|
127158
|
+
const addCompatChannel = () => {
|
|
127159
|
+
const id = `channel-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 7)}`;
|
|
127160
|
+
const channel = {
|
|
127161
|
+
id,
|
|
127162
|
+
label: `OpenAI 兼容 ${compatChannels.length + 2}`,
|
|
127163
|
+
keyRef: openAICompatKeyRef(id),
|
|
127164
|
+
baseURL: "",
|
|
127165
|
+
model: "",
|
|
127166
|
+
models: [],
|
|
127167
|
+
qualityOptions: [...DEFAULT_COMPAT_QUALITIES]
|
|
127168
|
+
};
|
|
127169
|
+
setCompatChannels((current) => [...current, channel]);
|
|
127170
|
+
setRows((current) => ({
|
|
127171
|
+
...current,
|
|
127172
|
+
[compatChannelRowKey(id)]: {
|
|
127173
|
+
...emptyProviderRow(),
|
|
127174
|
+
...compatRowFields(channel),
|
|
127175
|
+
expanded: true
|
|
127176
|
+
}
|
|
127177
|
+
}));
|
|
127178
|
+
};
|
|
127179
|
+
const removeCompatChannel = async (channel) => {
|
|
127180
|
+
if (!window.confirm(t("removeChannelConfirm", { label: channel.label }))) return;
|
|
127181
|
+
const target = compatChannelRowKey(channel.id);
|
|
127182
|
+
if (!(snapshot.value?.openaiCompatChannels?.some((entry) => entry.id === channel.id) === true)) {
|
|
127183
|
+
setCompatChannels((current) => current.filter((entry) => entry.id !== channel.id));
|
|
127184
|
+
setRows((current) => {
|
|
127185
|
+
const next = { ...current };
|
|
127186
|
+
delete next[target];
|
|
127187
|
+
return next;
|
|
127188
|
+
});
|
|
127189
|
+
return;
|
|
127190
|
+
}
|
|
127191
|
+
let removed = false;
|
|
127192
|
+
updateRow(target, {
|
|
127193
|
+
saving: true,
|
|
127194
|
+
message: "",
|
|
127195
|
+
messageIsError: false
|
|
127196
|
+
});
|
|
127197
|
+
try {
|
|
127198
|
+
const nextChannels = compatChannels.filter((entry) => entry.id !== channel.id);
|
|
127199
|
+
await saveSetting("openaiCompatChannels", nextChannels);
|
|
127200
|
+
if (snapshot.value?.openaiCompatActiveChannel === channel.id) await saveSetting("openaiCompatActiveChannel", "default");
|
|
127201
|
+
removed = true;
|
|
127202
|
+
setCompatChannels(nextChannels);
|
|
127203
|
+
setRows((current) => {
|
|
127204
|
+
const next = { ...current };
|
|
127205
|
+
delete next[target];
|
|
127206
|
+
return next;
|
|
127207
|
+
});
|
|
127208
|
+
} catch (cause) {
|
|
127209
|
+
updateRow(target, {
|
|
126867
127210
|
message: cause instanceof Error ? cause.message : String(cause),
|
|
126868
127211
|
messageIsError: true
|
|
126869
127212
|
});
|
|
126870
127213
|
} finally {
|
|
126871
|
-
updateRow(
|
|
127214
|
+
if (!removed) updateRow(target, { saving: false });
|
|
126872
127215
|
}
|
|
126873
127216
|
};
|
|
126874
127217
|
/** These actions use host settings, so drafts must be saved before making a request. */
|
|
126875
|
-
const providerActionBlockMessage = (provider) => {
|
|
126876
|
-
const
|
|
127218
|
+
const providerActionBlockMessage = (provider, channel) => {
|
|
127219
|
+
const target = channel === void 0 ? provider : compatChannelRowKey(channel.id);
|
|
127220
|
+
const row = rows[target];
|
|
126877
127221
|
if (row.keyInput.trim().length > 0) return t("saveKeyFirst");
|
|
126878
127222
|
if (isSubscriptionProvider(provider)) return void 0;
|
|
126879
127223
|
const address = row.baseURL.trim();
|
|
126880
127224
|
if (address.length === 0) return t("endpointRequired");
|
|
126881
|
-
if (address !== baseURLOf(provider, props.scope.getSnapshot().value).trim()) return t("saveEndpointFirst");
|
|
127225
|
+
if (address !== (channel === void 0 ? baseURLOf(provider, props.scope.getSnapshot().value) : channel.baseURL).trim()) return t("saveEndpointFirst");
|
|
126882
127226
|
if (provider === "google" && row.googleNative !== (props.scope.getSnapshot().value?.googleNative === true)) return t("saveGoogleProtocolFirst");
|
|
126883
127227
|
};
|
|
126884
127228
|
/** Localize the host's missing-address error while preserving upstream details. */
|
|
126885
127229
|
const providerErrorMessage = (message) => message === "Base URL is not configured" ? t("savedEndpointMissing") : message ?? t("testFailed");
|
|
126886
127230
|
/** Probe through the host route so the browser side never touches credential values. */
|
|
126887
|
-
const testConnection = async (provider) => {
|
|
126888
|
-
const
|
|
127231
|
+
const testConnection = async (provider, channel) => {
|
|
127232
|
+
const target = channel === void 0 ? provider : compatChannelRowKey(channel.id);
|
|
127233
|
+
const blocked = providerActionBlockMessage(provider, channel);
|
|
126889
127234
|
if (blocked !== void 0) {
|
|
126890
|
-
updateRow(
|
|
127235
|
+
updateRow(target, {
|
|
126891
127236
|
message: blocked,
|
|
126892
127237
|
messageIsError: false,
|
|
126893
127238
|
testResult: void 0
|
|
126894
127239
|
});
|
|
126895
127240
|
return;
|
|
126896
127241
|
}
|
|
126897
|
-
updateRow(
|
|
127242
|
+
updateRow(target, {
|
|
126898
127243
|
testing: true,
|
|
126899
127244
|
testResult: void 0,
|
|
126900
127245
|
message: "",
|
|
@@ -126904,31 +127249,35 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126904
127249
|
const response = await fetch(TEST_CONNECTION_ROUTE, {
|
|
126905
127250
|
method: "POST",
|
|
126906
127251
|
headers: { "content-type": "application/json" },
|
|
126907
|
-
body: JSON.stringify({
|
|
127252
|
+
body: JSON.stringify({
|
|
127253
|
+
provider,
|
|
127254
|
+
...channel === void 0 ? {} : { channel: channel.id }
|
|
127255
|
+
})
|
|
126908
127256
|
});
|
|
126909
127257
|
if (!response.ok) throw new Error(`HTTP ${String(response.status)}`);
|
|
126910
|
-
updateRow(
|
|
127258
|
+
updateRow(target, { testResult: await response.json() });
|
|
126911
127259
|
} catch (cause) {
|
|
126912
|
-
updateRow(
|
|
127260
|
+
updateRow(target, { testResult: {
|
|
126913
127261
|
ok: false,
|
|
126914
127262
|
reason: "error",
|
|
126915
127263
|
message: cause instanceof Error ? cause.message : String(cause)
|
|
126916
127264
|
} });
|
|
126917
127265
|
} finally {
|
|
126918
|
-
updateRow(
|
|
127266
|
+
updateRow(target, { testing: false });
|
|
126919
127267
|
}
|
|
126920
127268
|
};
|
|
126921
127269
|
/** Pull the provider's image-capable model ids through the host route (Google and the OpenAI family). */
|
|
126922
|
-
const fetchProviderModels = async (provider) => {
|
|
126923
|
-
const
|
|
127270
|
+
const fetchProviderModels = async (provider, channel) => {
|
|
127271
|
+
const target = channel === void 0 ? provider : compatChannelRowKey(channel.id);
|
|
127272
|
+
const blocked = providerActionBlockMessage(provider, channel);
|
|
126924
127273
|
if (blocked !== void 0) {
|
|
126925
|
-
updateRow(
|
|
127274
|
+
updateRow(target, {
|
|
126926
127275
|
modelFetchMessage: blocked,
|
|
126927
127276
|
modelFetchIsError: false
|
|
126928
127277
|
});
|
|
126929
127278
|
return;
|
|
126930
127279
|
}
|
|
126931
|
-
updateRow(
|
|
127280
|
+
updateRow(target, {
|
|
126932
127281
|
fetchingModels: true,
|
|
126933
127282
|
modelFetchMessage: "",
|
|
126934
127283
|
modelFetchIsError: false
|
|
@@ -126939,50 +127288,52 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126939
127288
|
headers: { "content-type": "application/json" },
|
|
126940
127289
|
body: JSON.stringify({
|
|
126941
127290
|
provider,
|
|
126942
|
-
action: "models"
|
|
127291
|
+
action: "models",
|
|
127292
|
+
...channel === void 0 ? {} : { channel: channel.id }
|
|
126943
127293
|
})
|
|
126944
127294
|
});
|
|
126945
127295
|
if (!response.ok) throw new Error(`HTTP ${String(response.status)}`);
|
|
126946
127296
|
const payload = await response.json();
|
|
126947
127297
|
if (payload.ok && Array.isArray(payload.models)) {
|
|
126948
127298
|
const models = payload.models.filter((id) => typeof id === "string");
|
|
126949
|
-
updateRow(
|
|
127299
|
+
updateRow(target, {
|
|
126950
127300
|
modelOptions: models,
|
|
126951
127301
|
modelFetchMessage: models.length > 0 ? t("modelsFound", { n: String(models.length) }) : t("modelsNone"),
|
|
126952
127302
|
modelFetchIsError: models.length === 0
|
|
126953
127303
|
});
|
|
126954
|
-
} else if (payload.reason === "missing-key") updateRow(
|
|
127304
|
+
} else if (payload.reason === "missing-key") updateRow(target, {
|
|
126955
127305
|
modelFetchMessage: t("badgeMissing"),
|
|
126956
127306
|
modelFetchIsError: true
|
|
126957
127307
|
});
|
|
126958
|
-
else if (payload.reason === "unauthorized") updateRow(
|
|
127308
|
+
else if (payload.reason === "unauthorized") updateRow(target, {
|
|
126959
127309
|
modelFetchMessage: t("testUnauthorized"),
|
|
126960
127310
|
modelFetchIsError: true
|
|
126961
127311
|
});
|
|
126962
|
-
else updateRow(
|
|
127312
|
+
else updateRow(target, {
|
|
126963
127313
|
modelFetchMessage: providerErrorMessage(payload.message),
|
|
126964
127314
|
modelFetchIsError: true
|
|
126965
127315
|
});
|
|
126966
127316
|
} catch (cause) {
|
|
126967
|
-
updateRow(
|
|
127317
|
+
updateRow(target, {
|
|
126968
127318
|
modelFetchMessage: cause instanceof Error ? cause.message : String(cause),
|
|
126969
127319
|
modelFetchIsError: true
|
|
126970
127320
|
});
|
|
126971
127321
|
} finally {
|
|
126972
|
-
updateRow(
|
|
127322
|
+
updateRow(target, { fetchingModels: false });
|
|
126973
127323
|
}
|
|
126974
127324
|
};
|
|
126975
|
-
const clearProviderKey = async (provider) => {
|
|
126976
|
-
const
|
|
127325
|
+
const clearProviderKey = async (provider, channel) => {
|
|
127326
|
+
const target = channel === void 0 ? provider : compatChannelRowKey(channel.id);
|
|
127327
|
+
const keyRef = channel === void 0 ? cloudCredentialRef(provider) : channel.keyRef;
|
|
126977
127328
|
if (keyRef === void 0) return;
|
|
126978
127329
|
if (typeof props.credentials.unset !== "function") {
|
|
126979
|
-
updateRow(
|
|
127330
|
+
updateRow(target, {
|
|
126980
127331
|
message: t("clearKeyUnsupported"),
|
|
126981
127332
|
messageIsError: true
|
|
126982
127333
|
});
|
|
126983
127334
|
return;
|
|
126984
127335
|
}
|
|
126985
|
-
updateRow(
|
|
127336
|
+
updateRow(target, {
|
|
126986
127337
|
saving: true,
|
|
126987
127338
|
message: "",
|
|
126988
127339
|
messageIsError: false
|
|
@@ -126990,7 +127341,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126990
127341
|
try {
|
|
126991
127342
|
const response = await props.credentials.unset(keyRef);
|
|
126992
127343
|
if (!response.ok) throw new Error(response.error?.message ?? t("clearKeyFailed"));
|
|
126993
|
-
updateRow(
|
|
127344
|
+
updateRow(target, {
|
|
126994
127345
|
keyStatus: "missing",
|
|
126995
127346
|
keyInput: "",
|
|
126996
127347
|
testResult: void 0,
|
|
@@ -126998,12 +127349,12 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126998
127349
|
messageIsError: false
|
|
126999
127350
|
});
|
|
127000
127351
|
} catch (cause) {
|
|
127001
|
-
updateRow(
|
|
127352
|
+
updateRow(target, {
|
|
127002
127353
|
message: cause instanceof Error ? cause.message : String(cause),
|
|
127003
127354
|
messageIsError: true
|
|
127004
127355
|
});
|
|
127005
127356
|
} finally {
|
|
127006
|
-
updateRow(
|
|
127357
|
+
updateRow(target, { saving: false });
|
|
127007
127358
|
}
|
|
127008
127359
|
};
|
|
127009
127360
|
const testResultText = (result) => {
|
|
@@ -127013,7 +127364,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127013
127364
|
if (result.reason === "unauthorized") return t("testUnauthorized");
|
|
127014
127365
|
return `${t("testFailed")}${result.message !== void 0 && result.message.length > 0 ? `: ${providerErrorMessage(result.message)}` : ""}`;
|
|
127015
127366
|
};
|
|
127016
|
-
const badgeOf = (provider) => {
|
|
127367
|
+
const badgeOf = (provider, channel) => {
|
|
127017
127368
|
if (provider === "comfyui") return {
|
|
127018
127369
|
text: t("comfyuiNoKey"),
|
|
127019
127370
|
className: "dsh-ig-badge dsh-ig-badge-neutral"
|
|
@@ -127033,7 +127384,8 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127033
127384
|
className: "dsh-ig-badge dsh-ig-badge-neutral"
|
|
127034
127385
|
};
|
|
127035
127386
|
}
|
|
127036
|
-
const
|
|
127387
|
+
const target = channel === void 0 ? provider : compatChannelRowKey(channel.id);
|
|
127388
|
+
const status = rows[target].keyStatus;
|
|
127037
127389
|
if (status === "checking") return {
|
|
127038
127390
|
text: t("badgeChecking"),
|
|
127039
127391
|
className: "dsh-ig-badge dsh-ig-badge-neutral dsh-ig-badge-checking"
|
|
@@ -127141,6 +127493,19 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127141
127493
|
};
|
|
127142
127494
|
});
|
|
127143
127495
|
};
|
|
127496
|
+
const commitCloudTimeout = () => {
|
|
127497
|
+
if (!Number.isInteger(cloudTimeoutSeconds) || cloudTimeoutSeconds < 5 || cloudTimeoutSeconds > 3600) {
|
|
127498
|
+
setCloudTimeoutSeconds((snapshot.value?.cloudTimeoutMs ?? 15e4) / 1e3);
|
|
127499
|
+
return;
|
|
127500
|
+
}
|
|
127501
|
+
const next = cloudTimeoutSeconds * 1e3;
|
|
127502
|
+
if (next === (snapshot.value?.cloudTimeoutMs ?? 15e4)) return;
|
|
127503
|
+
setCloudTimeoutMessage("");
|
|
127504
|
+
saveSetting("cloudTimeoutMs", next).catch((cause) => {
|
|
127505
|
+
setCloudTimeoutSeconds((snapshot.value?.cloudTimeoutMs ?? 15e4) / 1e3);
|
|
127506
|
+
setCloudTimeoutMessage(cause instanceof Error ? cause.message : String(cause));
|
|
127507
|
+
});
|
|
127508
|
+
};
|
|
127144
127509
|
/** Workspace checkbox persists immediately, like every other toggle on this card. */
|
|
127145
127510
|
const toggleSaveToWorkspace = (next) => {
|
|
127146
127511
|
setSaveToWorkspace(next);
|
|
@@ -127177,31 +127542,57 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127177
127542
|
setUiMessageIsError(true);
|
|
127178
127543
|
});
|
|
127179
127544
|
};
|
|
127180
|
-
const renderCloudBody = (provider) => {
|
|
127181
|
-
const
|
|
127545
|
+
const renderCloudBody = (provider, channel) => {
|
|
127546
|
+
const target = channel === void 0 ? provider : compatChannelRowKey(channel.id);
|
|
127547
|
+
const row = rows[target];
|
|
127548
|
+
const update = (patch) => {
|
|
127549
|
+
updateRow(target, patch);
|
|
127550
|
+
};
|
|
127551
|
+
const modelListId = `dsh-ig-${target.replace(/[^A-Za-z0-9_-]/g, "-")}-model-options`;
|
|
127182
127552
|
const officialEditFormat = provider === "openai-compat" ? compatEditFormat({
|
|
127183
127553
|
openaiCompatBaseURL: row.baseURL,
|
|
127184
127554
|
openaiCompatModel: row.editModel.trim() || row.model
|
|
127185
127555
|
}) : "multipart";
|
|
127186
127556
|
const automaticEditFormat = officialEditFormat !== "multipart";
|
|
127187
127557
|
const editFormat = automaticEditFormat ? officialEditFormat : row.editFormat;
|
|
127188
|
-
const keyRef = cloudCredentialRef(provider) ?? "";
|
|
127558
|
+
const keyRef = channel === void 0 ? cloudCredentialRef(provider) ?? "" : channel.keyRef;
|
|
127189
127559
|
const keyReadOnly = row.keyInfo?.writable === false;
|
|
127190
127560
|
const keyUnavailable = !credentialsAvailable();
|
|
127561
|
+
const providerLabel = provider === "openai-compat" && row.label.trim().length > 0 ? row.label.trim() : providerLabels[provider];
|
|
127562
|
+
const compatModelChoices = provider === "openai-compat" ? resolveOpenAICompatModels({
|
|
127563
|
+
openaiCompatModel: row.model,
|
|
127564
|
+
openaiCompatModels: [...row.models, ...row.modelOptions]
|
|
127565
|
+
}) : [];
|
|
127191
127566
|
return (0, react_jsx_runtime.jsx)("div", {
|
|
127192
127567
|
className: "dsh-ig-provider-body",
|
|
127193
127568
|
children: (0, react_jsx_runtime.jsxs)("form", {
|
|
127194
127569
|
onSubmit: (event) => {
|
|
127195
127570
|
event.preventDefault();
|
|
127196
|
-
saveProviderRow(provider);
|
|
127571
|
+
saveProviderRow(provider, channel);
|
|
127197
127572
|
},
|
|
127198
127573
|
children: [
|
|
127574
|
+
provider === "openai-compat" ? (0, react_jsx_runtime.jsxs)("label", {
|
|
127575
|
+
className: "dsh-ig-field",
|
|
127576
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
127577
|
+
className: "dsh-ig-label",
|
|
127578
|
+
children: t("channelName")
|
|
127579
|
+
}), (0, react_jsx_runtime.jsx)("input", {
|
|
127580
|
+
className: "dsh-ig-input",
|
|
127581
|
+
value: row.label,
|
|
127582
|
+
onChange: (event) => {
|
|
127583
|
+
update({ label: event.target.value });
|
|
127584
|
+
},
|
|
127585
|
+
placeholder: providerLabels[provider],
|
|
127586
|
+
required: channel !== void 0,
|
|
127587
|
+
disabled: !settingsWritable
|
|
127588
|
+
})]
|
|
127589
|
+
}) : null,
|
|
127199
127590
|
(0, react_jsx_runtime.jsxs)("label", {
|
|
127200
127591
|
className: "dsh-ig-field",
|
|
127201
127592
|
children: [
|
|
127202
127593
|
(0, react_jsx_runtime.jsx)("span", {
|
|
127203
127594
|
className: "dsh-ig-label",
|
|
127204
|
-
children: t("apiKeyLabel", { provider:
|
|
127595
|
+
children: t("apiKeyLabel", { provider: providerLabel })
|
|
127205
127596
|
}),
|
|
127206
127597
|
(0, react_jsx_runtime.jsx)("input", {
|
|
127207
127598
|
className: "dsh-ig-input",
|
|
@@ -127209,7 +127600,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127209
127600
|
autoComplete: "off",
|
|
127210
127601
|
value: row.keyInput,
|
|
127211
127602
|
onChange: (event) => {
|
|
127212
|
-
|
|
127603
|
+
update({ keyInput: event.target.value });
|
|
127213
127604
|
},
|
|
127214
127605
|
placeholder: row.keyStatus === "configured" ? t("apiKeyPlaceholder") : "",
|
|
127215
127606
|
disabled: !settingsWritable || keyReadOnly || keyUnavailable
|
|
@@ -127234,7 +127625,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127234
127625
|
type: "url",
|
|
127235
127626
|
value: row.baseURL,
|
|
127236
127627
|
onChange: (event) => {
|
|
127237
|
-
|
|
127628
|
+
update({ baseURL: event.target.value });
|
|
127238
127629
|
},
|
|
127239
127630
|
required: true,
|
|
127240
127631
|
disabled: !settingsWritable
|
|
@@ -127243,7 +127634,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127243
127634
|
className: "dsh-ig-btn-reset",
|
|
127244
127635
|
title: t("resetTitle"),
|
|
127245
127636
|
onClick: () => {
|
|
127246
|
-
|
|
127637
|
+
update({ baseURL: DEFAULT_BASE_URLS[provider] });
|
|
127247
127638
|
},
|
|
127248
127639
|
disabled: !settingsWritable,
|
|
127249
127640
|
children: t("reset")
|
|
@@ -127264,7 +127655,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127264
127655
|
className: "dsh-ig-input",
|
|
127265
127656
|
value: row.googleNative ? "native" : "interactions",
|
|
127266
127657
|
onChange: (event) => {
|
|
127267
|
-
|
|
127658
|
+
update({ googleNative: event.target.value === "native" });
|
|
127268
127659
|
},
|
|
127269
127660
|
disabled: !settingsWritable,
|
|
127270
127661
|
children: [(0, react_jsx_runtime.jsx)("option", {
|
|
@@ -127281,7 +127672,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127281
127672
|
children: [
|
|
127282
127673
|
(0, react_jsx_runtime.jsx)("span", {
|
|
127283
127674
|
className: "dsh-ig-label",
|
|
127284
|
-
children: t("model")
|
|
127675
|
+
children: t(provider === "openai-compat" ? "defaultModel" : "model")
|
|
127285
127676
|
}),
|
|
127286
127677
|
modelPullSupported(provider) ? (0, react_jsx_runtime.jsxs)("div", {
|
|
127287
127678
|
className: "dsh-ig-input-group",
|
|
@@ -127290,14 +127681,20 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127290
127681
|
className: "dsh-ig-input",
|
|
127291
127682
|
value: row.model,
|
|
127292
127683
|
onChange: (event) => {
|
|
127293
|
-
|
|
127684
|
+
update({ model: event.target.value });
|
|
127294
127685
|
},
|
|
127295
|
-
|
|
127686
|
+
onBlur: () => {
|
|
127687
|
+
if (provider === "openai-compat") update({ models: resolveOpenAICompatModels({
|
|
127688
|
+
openaiCompatModel: row.model,
|
|
127689
|
+
openaiCompatModels: row.models
|
|
127690
|
+
}) });
|
|
127691
|
+
},
|
|
127692
|
+
list: modelListId,
|
|
127296
127693
|
required: provider !== "openai-compat",
|
|
127297
127694
|
disabled: !settingsWritable
|
|
127298
127695
|
}),
|
|
127299
127696
|
(0, react_jsx_runtime.jsx)("datalist", {
|
|
127300
|
-
id:
|
|
127697
|
+
id: modelListId,
|
|
127301
127698
|
children: row.modelOptions.map((id) => (0, react_jsx_runtime.jsx)("option", { value: id }, id))
|
|
127302
127699
|
}),
|
|
127303
127700
|
(0, react_jsx_runtime.jsx)("button", {
|
|
@@ -127305,7 +127702,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127305
127702
|
className: "dsh-ig-btn-secondary",
|
|
127306
127703
|
disabled: row.fetchingModels || row.saving || !settingsWritable,
|
|
127307
127704
|
onClick: () => {
|
|
127308
|
-
fetchProviderModels(provider);
|
|
127705
|
+
fetchProviderModels(provider, channel);
|
|
127309
127706
|
},
|
|
127310
127707
|
children: row.fetchingModels ? t("fetchingModels") : t("fetchModels")
|
|
127311
127708
|
})
|
|
@@ -127314,7 +127711,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127314
127711
|
className: "dsh-ig-input",
|
|
127315
127712
|
value: row.model,
|
|
127316
127713
|
onChange: (event) => {
|
|
127317
|
-
|
|
127714
|
+
update({ model: event.target.value });
|
|
127318
127715
|
},
|
|
127319
127716
|
required: true,
|
|
127320
127717
|
disabled: !settingsWritable
|
|
@@ -127329,6 +127726,52 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127329
127726
|
}) : null
|
|
127330
127727
|
]
|
|
127331
127728
|
}),
|
|
127729
|
+
provider === "openai-compat" && compatModelChoices.length > 0 ? (0, react_jsx_runtime.jsxs)("div", {
|
|
127730
|
+
className: "dsh-ig-field",
|
|
127731
|
+
children: [
|
|
127732
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
127733
|
+
className: "dsh-ig-label",
|
|
127734
|
+
children: t("availableModels")
|
|
127735
|
+
}),
|
|
127736
|
+
(0, react_jsx_runtime.jsx)("div", {
|
|
127737
|
+
className: "dsh-ig-model-picker",
|
|
127738
|
+
children: compatModelChoices.map((id) => {
|
|
127739
|
+
const isDefault = row.model.trim() === id;
|
|
127740
|
+
const checked = isDefault || row.models.includes(id);
|
|
127741
|
+
return (0, react_jsx_runtime.jsxs)("label", {
|
|
127742
|
+
className: "dsh-ig-check-row",
|
|
127743
|
+
title: id,
|
|
127744
|
+
children: [
|
|
127745
|
+
(0, react_jsx_runtime.jsx)("input", {
|
|
127746
|
+
type: "checkbox",
|
|
127747
|
+
checked,
|
|
127748
|
+
disabled: !settingsWritable || isDefault,
|
|
127749
|
+
onChange: (event) => {
|
|
127750
|
+
const models = event.target.checked ? [...row.models, id] : row.models.filter((model) => model !== id);
|
|
127751
|
+
update({ models: resolveOpenAICompatModels({
|
|
127752
|
+
openaiCompatModel: row.model,
|
|
127753
|
+
openaiCompatModels: models
|
|
127754
|
+
}) });
|
|
127755
|
+
}
|
|
127756
|
+
}),
|
|
127757
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
127758
|
+
className: "dsh-ig-model-option",
|
|
127759
|
+
children: id
|
|
127760
|
+
}),
|
|
127761
|
+
isDefault ? (0, react_jsx_runtime.jsx)("span", {
|
|
127762
|
+
className: "dsh-ig-model-default",
|
|
127763
|
+
children: t("defaultModelTag")
|
|
127764
|
+
}) : null
|
|
127765
|
+
]
|
|
127766
|
+
}, id);
|
|
127767
|
+
})
|
|
127768
|
+
}),
|
|
127769
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
127770
|
+
className: "dsh-ig-hint",
|
|
127771
|
+
children: t("availableModelsHint")
|
|
127772
|
+
})
|
|
127773
|
+
]
|
|
127774
|
+
}) : null,
|
|
127332
127775
|
provider === "openai-compat" ? (0, react_jsx_runtime.jsxs)("label", {
|
|
127333
127776
|
className: "dsh-ig-field",
|
|
127334
127777
|
children: [
|
|
@@ -127340,9 +127783,9 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127340
127783
|
className: "dsh-ig-input",
|
|
127341
127784
|
value: row.editModel,
|
|
127342
127785
|
onChange: (event) => {
|
|
127343
|
-
|
|
127786
|
+
update({ editModel: event.target.value });
|
|
127344
127787
|
},
|
|
127345
|
-
list:
|
|
127788
|
+
list: modelListId,
|
|
127346
127789
|
disabled: !settingsWritable
|
|
127347
127790
|
}),
|
|
127348
127791
|
(0, react_jsx_runtime.jsx)("span", {
|
|
@@ -127362,7 +127805,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127362
127805
|
className: "dsh-ig-input",
|
|
127363
127806
|
value: automaticEditFormat ? "__official__" : row.editFormat,
|
|
127364
127807
|
onChange: (event) => {
|
|
127365
|
-
|
|
127808
|
+
update({ editFormat: parseEditFormat(event.target.value) });
|
|
127366
127809
|
},
|
|
127367
127810
|
disabled: !settingsWritable || automaticEditFormat,
|
|
127368
127811
|
children: [
|
|
@@ -127406,7 +127849,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127406
127849
|
className: "dsh-ig-input",
|
|
127407
127850
|
value: row.outputFormat,
|
|
127408
127851
|
onChange: (event) => {
|
|
127409
|
-
|
|
127852
|
+
update({ outputFormat: event.target.value === "png" ? "png" : "jpeg" });
|
|
127410
127853
|
},
|
|
127411
127854
|
disabled: !settingsWritable,
|
|
127412
127855
|
children: [(0, react_jsx_runtime.jsx)("option", {
|
|
@@ -127434,7 +127877,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127434
127877
|
className: "dsh-ig-input",
|
|
127435
127878
|
value: row.watermark ? "on" : "off",
|
|
127436
127879
|
onChange: (event) => {
|
|
127437
|
-
|
|
127880
|
+
update({ watermark: event.target.value === "on" });
|
|
127438
127881
|
},
|
|
127439
127882
|
disabled: !settingsWritable,
|
|
127440
127883
|
children: [(0, react_jsx_runtime.jsx)("option", {
|
|
@@ -127462,7 +127905,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127462
127905
|
className: "dsh-ig-input",
|
|
127463
127906
|
value: row.background,
|
|
127464
127907
|
onChange: (event) => {
|
|
127465
|
-
|
|
127908
|
+
update({ background: event.target.value === "transparent" ? "transparent" : "opaque" });
|
|
127466
127909
|
},
|
|
127467
127910
|
disabled: !settingsWritable,
|
|
127468
127911
|
children: [(0, react_jsx_runtime.jsx)("option", {
|
|
@@ -127491,7 +127934,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127491
127934
|
className: "dsh-ig-input dsh-ig-textarea",
|
|
127492
127935
|
value: row.sizeTableText,
|
|
127493
127936
|
onChange: (event) => {
|
|
127494
|
-
|
|
127937
|
+
update({ sizeTableText: event.target.value });
|
|
127495
127938
|
},
|
|
127496
127939
|
rows: 3,
|
|
127497
127940
|
disabled: !settingsWritable
|
|
@@ -127514,7 +127957,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127514
127957
|
className: "dsh-ig-input",
|
|
127515
127958
|
value: row.generationQuality,
|
|
127516
127959
|
onChange: (event) => {
|
|
127517
|
-
|
|
127960
|
+
update({ generationQuality: event.target.value });
|
|
127518
127961
|
},
|
|
127519
127962
|
placeholder: "high",
|
|
127520
127963
|
disabled: !settingsWritable
|
|
@@ -127534,7 +127977,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127534
127977
|
className: "dsh-ig-input",
|
|
127535
127978
|
value: row.qualityOptionsText,
|
|
127536
127979
|
onChange: (event) => {
|
|
127537
|
-
|
|
127980
|
+
update({ qualityOptionsText: event.target.value });
|
|
127538
127981
|
},
|
|
127539
127982
|
disabled: !settingsWritable
|
|
127540
127983
|
})]
|
|
@@ -127550,7 +127993,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127550
127993
|
className: "dsh-ig-input dsh-ig-textarea",
|
|
127551
127994
|
value: row.generateExtraText,
|
|
127552
127995
|
onChange: (event) => {
|
|
127553
|
-
|
|
127996
|
+
update({ generateExtraText: event.target.value });
|
|
127554
127997
|
},
|
|
127555
127998
|
placeholder: "{\"watermark\":false}",
|
|
127556
127999
|
rows: 2,
|
|
@@ -127572,7 +128015,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127572
128015
|
className: "dsh-ig-input",
|
|
127573
128016
|
value: row.editSizeMode,
|
|
127574
128017
|
onChange: (event) => {
|
|
127575
|
-
|
|
128018
|
+
update({ editSizeMode: event.target.value === "selected" ? "selected" : "auto" });
|
|
127576
128019
|
},
|
|
127577
128020
|
disabled: !settingsWritable,
|
|
127578
128021
|
children: [(0, react_jsx_runtime.jsx)("option", {
|
|
@@ -127594,7 +128037,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127594
128037
|
className: "dsh-ig-input dsh-ig-textarea",
|
|
127595
128038
|
value: row.editExtraText,
|
|
127596
128039
|
onChange: (event) => {
|
|
127597
|
-
|
|
128040
|
+
update({ editExtraText: event.target.value });
|
|
127598
128041
|
},
|
|
127599
128042
|
placeholder: t("editExtraPlaceholder"),
|
|
127600
128043
|
rows: 2,
|
|
@@ -127620,7 +128063,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127620
128063
|
className: "dsh-ig-btn-secondary",
|
|
127621
128064
|
disabled: row.testing || row.saving,
|
|
127622
128065
|
onClick: () => {
|
|
127623
|
-
testConnection(provider);
|
|
128066
|
+
testConnection(provider, channel);
|
|
127624
128067
|
},
|
|
127625
128068
|
children: row.testing ? t("testing") : t("testConnection")
|
|
127626
128069
|
}),
|
|
@@ -127629,7 +128072,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127629
128072
|
className: "dsh-ig-btn-secondary dsh-ig-btn-danger",
|
|
127630
128073
|
disabled: row.saving,
|
|
127631
128074
|
onClick: () => {
|
|
127632
|
-
clearProviderKey(provider);
|
|
128075
|
+
clearProviderKey(provider, channel);
|
|
127633
128076
|
},
|
|
127634
128077
|
children: t("clearKey")
|
|
127635
128078
|
}) : null,
|
|
@@ -127947,47 +128390,123 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127947
128390
|
const renderProviderRow = (provider) => {
|
|
127948
128391
|
const row = rows[provider];
|
|
127949
128392
|
const badge = badgeOf(provider);
|
|
128393
|
+
const label = provider === "openai-compat" && row.label.trim().length > 0 ? row.label.trim() : providerLabels[provider];
|
|
127950
128394
|
return (0, react_jsx_runtime.jsxs)("div", {
|
|
127951
128395
|
className: "dsh-ig-provider-row",
|
|
127952
|
-
children: [(0, react_jsx_runtime.jsxs)("
|
|
127953
|
-
|
|
127954
|
-
|
|
127955
|
-
|
|
127956
|
-
|
|
127957
|
-
|
|
127958
|
-
|
|
127959
|
-
|
|
127960
|
-
|
|
127961
|
-
|
|
127962
|
-
|
|
127963
|
-
|
|
127964
|
-
|
|
127965
|
-
|
|
127966
|
-
|
|
127967
|
-
|
|
127968
|
-
|
|
127969
|
-
|
|
127970
|
-
|
|
127971
|
-
|
|
127972
|
-
|
|
127973
|
-
|
|
127974
|
-
|
|
127975
|
-
|
|
127976
|
-
|
|
127977
|
-
|
|
127978
|
-
|
|
127979
|
-
|
|
127980
|
-
|
|
127981
|
-
|
|
127982
|
-
|
|
127983
|
-
|
|
127984
|
-
|
|
128396
|
+
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
128397
|
+
className: "dsh-ig-provider-head-row",
|
|
128398
|
+
children: [(0, react_jsx_runtime.jsxs)("button", {
|
|
128399
|
+
type: "button",
|
|
128400
|
+
className: "dsh-ig-provider-head",
|
|
128401
|
+
"aria-expanded": row.expanded,
|
|
128402
|
+
onClick: () => {
|
|
128403
|
+
updateRow(provider, { expanded: !row.expanded });
|
|
128404
|
+
},
|
|
128405
|
+
children: [
|
|
128406
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
128407
|
+
className: "dsh-ig-provider-name",
|
|
128408
|
+
children: label
|
|
128409
|
+
}),
|
|
128410
|
+
(0, react_jsx_runtime.jsxs)("span", {
|
|
128411
|
+
className: badge.className,
|
|
128412
|
+
title: badge.text,
|
|
128413
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
128414
|
+
className: "dsh-ig-badge-dot",
|
|
128415
|
+
"aria-hidden": "true"
|
|
128416
|
+
}), badge.text]
|
|
128417
|
+
}),
|
|
128418
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
128419
|
+
className: `dsh-ig-provider-chevron ${row.expanded ? "dsh-ig-provider-chevron-open" : ""}`,
|
|
128420
|
+
"aria-hidden": "true",
|
|
128421
|
+
children: (0, react_jsx_runtime.jsx)("svg", {
|
|
128422
|
+
width: "12",
|
|
128423
|
+
height: "12",
|
|
128424
|
+
viewBox: "0 0 16 16",
|
|
128425
|
+
fill: "none",
|
|
128426
|
+
stroke: "currentColor",
|
|
128427
|
+
strokeWidth: "2",
|
|
128428
|
+
strokeLinecap: "round",
|
|
128429
|
+
strokeLinejoin: "round",
|
|
128430
|
+
children: (0, react_jsx_runtime.jsx)("path", { d: "M4 6l4 4 4-4" })
|
|
128431
|
+
})
|
|
127985
128432
|
})
|
|
128433
|
+
]
|
|
128434
|
+
}), provider === "openai-compat" ? (0, react_jsx_runtime.jsx)("button", {
|
|
128435
|
+
type: "button",
|
|
128436
|
+
className: "dsh-ig-btn-secondary dsh-ig-channel-add",
|
|
128437
|
+
title: t("addCompatChannel"),
|
|
128438
|
+
"aria-label": t("addCompatChannel"),
|
|
128439
|
+
onClick: addCompatChannel,
|
|
128440
|
+
disabled: !settingsWritable,
|
|
128441
|
+
children: (0, react_jsx_runtime.jsx)("svg", {
|
|
128442
|
+
viewBox: "0 0 16 16",
|
|
128443
|
+
fill: "none",
|
|
128444
|
+
stroke: "currentColor",
|
|
128445
|
+
strokeWidth: "1.6",
|
|
128446
|
+
strokeLinecap: "round",
|
|
128447
|
+
"aria-hidden": "true",
|
|
128448
|
+
children: (0, react_jsx_runtime.jsx)("path", { d: "M8 3v10M3 8h10" })
|
|
127986
128449
|
})
|
|
127987
|
-
]
|
|
128450
|
+
}) : null]
|
|
127988
128451
|
}), row.expanded ? provider === "comfyui" ? renderComfyUIBody() : isSubscriptionProvider(provider) ? renderSubscriptionBody(provider) : renderCloudBody(provider) : null]
|
|
127989
128452
|
}, provider);
|
|
127990
128453
|
};
|
|
128454
|
+
const renderCompatChannelRow = (channel) => {
|
|
128455
|
+
const target = compatChannelRowKey(channel.id);
|
|
128456
|
+
const row = rows[target];
|
|
128457
|
+
const badge = badgeOf("openai-compat", channel);
|
|
128458
|
+
return (0, react_jsx_runtime.jsxs)("div", {
|
|
128459
|
+
className: "dsh-ig-provider-row dsh-ig-compat-channel-row",
|
|
128460
|
+
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
128461
|
+
className: "dsh-ig-provider-head-row",
|
|
128462
|
+
children: [(0, react_jsx_runtime.jsxs)("button", {
|
|
128463
|
+
type: "button",
|
|
128464
|
+
className: "dsh-ig-provider-head",
|
|
128465
|
+
"aria-expanded": row.expanded,
|
|
128466
|
+
onClick: () => {
|
|
128467
|
+
updateRow(target, { expanded: !row.expanded });
|
|
128468
|
+
},
|
|
128469
|
+
children: [
|
|
128470
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
128471
|
+
className: "dsh-ig-provider-name",
|
|
128472
|
+
children: channel.label
|
|
128473
|
+
}),
|
|
128474
|
+
(0, react_jsx_runtime.jsxs)("span", {
|
|
128475
|
+
className: badge.className,
|
|
128476
|
+
title: badge.text,
|
|
128477
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
128478
|
+
className: "dsh-ig-badge-dot",
|
|
128479
|
+
"aria-hidden": "true"
|
|
128480
|
+
}), badge.text]
|
|
128481
|
+
}),
|
|
128482
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
128483
|
+
className: `dsh-ig-provider-chevron ${row.expanded ? "dsh-ig-provider-chevron-open" : ""}`,
|
|
128484
|
+
"aria-hidden": "true",
|
|
128485
|
+
children: (0, react_jsx_runtime.jsx)("svg", {
|
|
128486
|
+
width: "12",
|
|
128487
|
+
height: "12",
|
|
128488
|
+
viewBox: "0 0 16 16",
|
|
128489
|
+
fill: "none",
|
|
128490
|
+
stroke: "currentColor",
|
|
128491
|
+
strokeWidth: "2",
|
|
128492
|
+
strokeLinecap: "round",
|
|
128493
|
+
strokeLinejoin: "round",
|
|
128494
|
+
children: (0, react_jsx_runtime.jsx)("path", { d: "M4 6l4 4 4-4" })
|
|
128495
|
+
})
|
|
128496
|
+
})
|
|
128497
|
+
]
|
|
128498
|
+
}), (0, react_jsx_runtime.jsx)("button", {
|
|
128499
|
+
type: "button",
|
|
128500
|
+
className: "dsh-ig-btn-secondary dsh-ig-btn-danger",
|
|
128501
|
+
disabled: row.saving || !settingsWritable,
|
|
128502
|
+
onClick: () => {
|
|
128503
|
+
removeCompatChannel(channel);
|
|
128504
|
+
},
|
|
128505
|
+
children: t("removeChannel")
|
|
128506
|
+
})]
|
|
128507
|
+
}), row.expanded ? renderCloudBody("openai-compat", channel) : null]
|
|
128508
|
+
}, target);
|
|
128509
|
+
};
|
|
127991
128510
|
return (0, react_jsx_runtime.jsxs)("li", {
|
|
127992
128511
|
className: "dsh-ig-card",
|
|
127993
128512
|
children: [(0, react_jsx_runtime.jsx)("div", {
|
|
@@ -128045,9 +128564,46 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
128045
128564
|
}) : null
|
|
128046
128565
|
]
|
|
128047
128566
|
}),
|
|
128567
|
+
(0, react_jsx_runtime.jsxs)("label", {
|
|
128568
|
+
className: "dsh-ig-field",
|
|
128569
|
+
children: [
|
|
128570
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
128571
|
+
className: "dsh-ig-label",
|
|
128572
|
+
children: t("cloudTimeout")
|
|
128573
|
+
}),
|
|
128574
|
+
(0, react_jsx_runtime.jsx)("input", {
|
|
128575
|
+
className: "dsh-ig-input",
|
|
128576
|
+
type: "number",
|
|
128577
|
+
min: "5",
|
|
128578
|
+
max: "3600",
|
|
128579
|
+
step: "1",
|
|
128580
|
+
value: cloudTimeoutSeconds,
|
|
128581
|
+
onChange: (event) => {
|
|
128582
|
+
setCloudTimeoutSeconds(Number(event.target.value));
|
|
128583
|
+
},
|
|
128584
|
+
onBlur: () => {
|
|
128585
|
+
commitCloudTimeout();
|
|
128586
|
+
},
|
|
128587
|
+
onKeyDown: (event) => {
|
|
128588
|
+
if (event.key === "Enter") commitCloudTimeout();
|
|
128589
|
+
},
|
|
128590
|
+
required: true,
|
|
128591
|
+
disabled: !settingsWritable
|
|
128592
|
+
}),
|
|
128593
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
128594
|
+
className: "dsh-ig-hint",
|
|
128595
|
+
children: t("cloudTimeoutHint")
|
|
128596
|
+
}),
|
|
128597
|
+
cloudTimeoutMessage.length > 0 ? (0, react_jsx_runtime.jsx)("span", {
|
|
128598
|
+
className: "dsh-ig-status dsh-ig-status-error",
|
|
128599
|
+
role: "status",
|
|
128600
|
+
children: cloudTimeoutMessage
|
|
128601
|
+
}) : null
|
|
128602
|
+
]
|
|
128603
|
+
}),
|
|
128048
128604
|
(0, react_jsx_runtime.jsx)("div", {
|
|
128049
128605
|
className: "dsh-ig-providers",
|
|
128050
|
-
children: IMAGE_PROVIDERS.
|
|
128606
|
+
children: IMAGE_PROVIDERS.flatMap((provider) => [renderProviderRow(provider), ...provider === "openai-compat" ? compatChannels.map((channel) => renderCompatChannelRow(channel)) : []])
|
|
128051
128607
|
}),
|
|
128052
128608
|
(0, react_jsx_runtime.jsxs)("div", {
|
|
128053
128609
|
className: "dsh-ig-section",
|
|
@@ -128212,6 +128768,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
128212
128768
|
const activeResult = selectedRevision !== void 0 ? {
|
|
128213
128769
|
prompt: selectedRevision.prompt,
|
|
128214
128770
|
provider: selectedRevision.provider,
|
|
128771
|
+
...selectedRevision.channel === void 0 ? {} : { channel: selectedRevision.channel },
|
|
128215
128772
|
model: selectedRevision.model,
|
|
128216
128773
|
output: selectedRevision.output,
|
|
128217
128774
|
createdAt: selectedRevision.createdAt,
|
|
@@ -128242,6 +128799,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
128242
128799
|
attachment: result.attachment,
|
|
128243
128800
|
prompt: result.prompt,
|
|
128244
128801
|
provider: result.provider,
|
|
128802
|
+
...result.channel === void 0 ? {} : { channel: result.channel },
|
|
128245
128803
|
model: result.model,
|
|
128246
128804
|
output: result.output,
|
|
128247
128805
|
...result.savedTo ? { savedTo: result.savedTo } : {},
|
|
@@ -128380,6 +128938,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
128380
128938
|
attachment: payload.attachment,
|
|
128381
128939
|
prompt: payload.prompt,
|
|
128382
128940
|
provider: payload.provider,
|
|
128941
|
+
...payload.channel === void 0 ? {} : { channel: payload.channel },
|
|
128383
128942
|
model: payload.model,
|
|
128384
128943
|
output: payload.output,
|
|
128385
128944
|
createdAt: payload.createdAt,
|
|
@@ -128394,6 +128953,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
128394
128953
|
attachment: revision.attachment,
|
|
128395
128954
|
prompt: revision.prompt,
|
|
128396
128955
|
provider: revision.provider,
|
|
128956
|
+
...revision.channel === void 0 ? {} : { channel: revision.channel },
|
|
128397
128957
|
model: revision.model,
|
|
128398
128958
|
createdAt: revision.createdAt,
|
|
128399
128959
|
aspectRatio: revision.ratio,
|