dsh-image-gen 0.9.3 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +454 -454
- package/README.md +454 -454
- package/lib/client.js +927 -356
- package/lib/index.js +276 -61
- 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/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/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/package.json +139 -139
- package/skills/install-dsh-image-gen/SKILL.md +22 -22
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,
|
|
@@ -123036,6 +123150,7 @@ img.ProseMirror-separator {
|
|
|
123036
123150
|
attachment: payload.attachment,
|
|
123037
123151
|
prompt: payload.prompt,
|
|
123038
123152
|
provider: payload.provider,
|
|
123153
|
+
...payload.channel === void 0 ? {} : { channel: payload.channel },
|
|
123039
123154
|
model: payload.model,
|
|
123040
123155
|
createdAt: payload.createdAt,
|
|
123041
123156
|
aspectRatio: request.ratio,
|
|
@@ -124303,6 +124418,7 @@ img.ProseMirror-separator {
|
|
|
124303
124418
|
attachment,
|
|
124304
124419
|
prompt: stringValue(meta.prompt, "Generated Image"),
|
|
124305
124420
|
provider: stringValue(meta.provider, "google"),
|
|
124421
|
+
...typeof meta.channel === "string" ? { channel: meta.channel } : {},
|
|
124306
124422
|
model: stringValue(meta.model, ""),
|
|
124307
124423
|
output: stringValue(meta.output, ""),
|
|
124308
124424
|
...typeof meta.savedTo === "string" ? { savedTo: meta.savedTo } : {},
|
|
@@ -124969,7 +125085,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
124969
125085
|
function isRevision(value) {
|
|
124970
125086
|
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
124971
125087
|
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));
|
|
125088
|
+
return isAttachment(candidate.attachment) && typeof candidate.provider === "string" && STUDIO_PROVIDERS.includes(candidate.provider) && (candidate.channel === void 0 || typeof candidate.channel === "string") && typeof candidate.prompt === "string" && typeof candidate.model === "string" && typeof candidate.output === "string" && typeof candidate.createdAt === "number" && Number.isFinite(candidate.createdAt) && typeof candidate.ratio === "string" && typeof candidate.quality === "string" && (candidate.resolution === void 0 || typeof candidate.resolution === "string") && (candidate.generationQuality === void 0 || typeof candidate.generationQuality === "string") && (candidate.watermark === void 0 || STUDIO_WATERMARK_VALUES.some((value) => value === candidate.watermark));
|
|
124973
125089
|
}
|
|
124974
125090
|
function isAttachment(value) {
|
|
124975
125091
|
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
@@ -125096,16 +125212,51 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125096
125212
|
function pillVisible(value) {
|
|
125097
125213
|
return value?.showProviderPill === true;
|
|
125098
125214
|
}
|
|
125215
|
+
const PILL_MODEL_FIELDS = {
|
|
125216
|
+
google: "googleModel",
|
|
125217
|
+
openai: "openaiModel",
|
|
125218
|
+
"openai-compat": "openaiCompatModel",
|
|
125219
|
+
seedream: "seedreamModel",
|
|
125220
|
+
dashscope: "dashscopeModel",
|
|
125221
|
+
xai: "xaiModel",
|
|
125222
|
+
zhipu: "zhipuModel"
|
|
125223
|
+
};
|
|
125224
|
+
const PILL_MODEL_OPTIONS_FIELDS = { "openai-compat": "openaiCompatModels" };
|
|
125099
125225
|
/** Model (or ComfyUI workflow) a provider row will use with the persisted settings. */
|
|
125100
|
-
function pillModelOf(provider, value) {
|
|
125226
|
+
function pillModelOf(provider, value, channelId) {
|
|
125101
125227
|
if (provider === "comfyui") {
|
|
125102
125228
|
const workflow = activeComfyUIWorkflow(value ?? {});
|
|
125103
125229
|
return workflow === void 0 ? "" : workflow.name;
|
|
125104
125230
|
}
|
|
125105
125231
|
if (SUBSCRIPTION_PROVIDERS.includes(provider)) return DEFAULT_MODELS[provider];
|
|
125106
|
-
|
|
125232
|
+
if (provider === "openai-compat") {
|
|
125233
|
+
const channel = resolveOpenAICompatChannel(value ?? {}, channelId);
|
|
125234
|
+
return channel.model.trim().length > 0 ? channel.model.trim() : DEFAULT_MODELS[provider];
|
|
125235
|
+
}
|
|
125236
|
+
const field = PILL_MODEL_FIELDS[provider];
|
|
125237
|
+
const stored = field === void 0 ? void 0 : value?.[field];
|
|
125107
125238
|
return typeof stored === "string" && stored.length > 0 ? stored : DEFAULT_MODELS[provider];
|
|
125108
125239
|
}
|
|
125240
|
+
/** Optional model choices exposed by a provider; single-model providers return an empty list. */
|
|
125241
|
+
function pillModelOptionsOf(provider, value, channelId) {
|
|
125242
|
+
if (provider === "openai-compat") {
|
|
125243
|
+
const channel = resolveOpenAICompatChannel(value ?? {}, channelId);
|
|
125244
|
+
return resolveOpenAICompatModels({
|
|
125245
|
+
openaiCompatModel: pillModelOf(provider, value, channel.id),
|
|
125246
|
+
openaiCompatModels: channel.models ?? []
|
|
125247
|
+
});
|
|
125248
|
+
}
|
|
125249
|
+
const field = PILL_MODEL_OPTIONS_FIELDS[provider];
|
|
125250
|
+
if (field === void 0) return [];
|
|
125251
|
+
const configured = value?.[field];
|
|
125252
|
+
const models = Array.isArray(configured) ? [...new Set(configured.filter((model) => typeof model === "string").map((model) => model.trim()).filter(Boolean))] : [];
|
|
125253
|
+
const defaultModel = pillModelOf(provider, value);
|
|
125254
|
+
if (defaultModel.length > 0 && !models.includes(defaultModel)) models.unshift(defaultModel);
|
|
125255
|
+
return models;
|
|
125256
|
+
}
|
|
125257
|
+
function pillTargetKey(provider, channelId) {
|
|
125258
|
+
return provider === "openai-compat" ? `openai-compat:${channelId ?? "default"}` : provider;
|
|
125259
|
+
}
|
|
125109
125260
|
/** One fixed-position provider menu anchored to the pill button. */
|
|
125110
125261
|
function ImageProviderPill(props) {
|
|
125111
125262
|
const [snapshot, setSnapshot] = (0, react.useState)(() => props.scope.getSnapshot());
|
|
@@ -125113,15 +125264,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125113
125264
|
const [open, setOpen] = (0, react.useState)(false);
|
|
125114
125265
|
const [pending, setPending] = (0, react.useState)(void 0);
|
|
125115
125266
|
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
|
-
});
|
|
125267
|
+
const [dots, setDots] = (0, react.useState)({});
|
|
125125
125268
|
const [keyTick, setKeyTick] = (0, react.useState)(0);
|
|
125126
125269
|
const [subDots, setSubDots] = (0, react.useState)(() => ({
|
|
125127
125270
|
"chatgpt-sub": "unknown",
|
|
@@ -125141,35 +125284,33 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125141
125284
|
}), [props.credentialEvents]);
|
|
125142
125285
|
(0, react.useEffect)(() => {
|
|
125143
125286
|
let active = true;
|
|
125144
|
-
const
|
|
125145
|
-
|
|
125146
|
-
|
|
125147
|
-
|
|
125148
|
-
|
|
125149
|
-
|
|
125287
|
+
const targets = [...CLOUD_IMAGE_PROVIDERS.filter((provider) => provider !== "openai-compat").map((provider) => ({
|
|
125288
|
+
key: provider,
|
|
125289
|
+
ref: cloudCredentialRef(provider)
|
|
125290
|
+
})), ...resolveOpenAICompatChannels(snapshot.value ?? {}).map((channel) => ({
|
|
125291
|
+
key: pillTargetKey("openai-compat", channel.id),
|
|
125292
|
+
ref: channel.keyRef
|
|
125293
|
+
}))];
|
|
125294
|
+
props.credentials.describe(targets.map((target) => target.ref)).then((response) => {
|
|
125150
125295
|
if (!active) return;
|
|
125151
125296
|
const next = {};
|
|
125152
|
-
for (const
|
|
125153
|
-
const info = response.ok ? response.value?.[
|
|
125154
|
-
next[
|
|
125297
|
+
for (const target of targets) {
|
|
125298
|
+
const info = response.ok ? response.value?.[target.ref] : void 0;
|
|
125299
|
+
next[target.key] = response.ok ? info?.configured ? "configured" : "missing" : "unknown";
|
|
125155
125300
|
}
|
|
125156
125301
|
setDots(next);
|
|
125157
125302
|
}).catch(() => {
|
|
125158
125303
|
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
|
-
});
|
|
125304
|
+
setDots({});
|
|
125168
125305
|
});
|
|
125169
125306
|
return () => {
|
|
125170
125307
|
active = false;
|
|
125171
125308
|
};
|
|
125172
|
-
}, [
|
|
125309
|
+
}, [
|
|
125310
|
+
props.credentials,
|
|
125311
|
+
keyTick,
|
|
125312
|
+
snapshot.value
|
|
125313
|
+
]);
|
|
125173
125314
|
(0, react.useEffect)(() => {
|
|
125174
125315
|
if (!open) return;
|
|
125175
125316
|
let active = true;
|
|
@@ -125197,6 +125338,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125197
125338
|
}, [open, keyTick]);
|
|
125198
125339
|
const t = (keyName) => (lang === "en" ? PILL_DICT.en : PILL_DICT.zh)[keyName];
|
|
125199
125340
|
const current = snapshot.value?.provider ?? "google";
|
|
125341
|
+
const currentChannel = current === "openai-compat" ? resolveOpenAICompatChannel(snapshot.value ?? {}) : void 0;
|
|
125200
125342
|
const writable = snapshot.writable;
|
|
125201
125343
|
(0, react.useEffect)(() => {
|
|
125202
125344
|
if (!open) {
|
|
@@ -125244,15 +125386,27 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125244
125386
|
};
|
|
125245
125387
|
}, [open]);
|
|
125246
125388
|
if (!pillVisible(snapshot.value)) return null;
|
|
125247
|
-
|
|
125248
|
-
|
|
125249
|
-
|
|
125389
|
+
const select = (provider, model, channelId) => {
|
|
125390
|
+
const currentModel = pillModelOf(provider, snapshot.value, channelId);
|
|
125391
|
+
const sameChannel = provider !== "openai-compat" || currentChannel?.id === (channelId ?? "default");
|
|
125392
|
+
if (pending !== void 0 || provider === current && sameChannel && (model === void 0 || model === currentModel)) {
|
|
125250
125393
|
setOpen(false);
|
|
125251
125394
|
return;
|
|
125252
125395
|
}
|
|
125396
|
+
const modelField = model === void 0 ? void 0 : PILL_MODEL_FIELDS[provider];
|
|
125253
125397
|
setError("");
|
|
125254
125398
|
setPending(provider);
|
|
125255
|
-
|
|
125399
|
+
(async () => {
|
|
125400
|
+
if (model !== void 0 && provider === "openai-compat" && channelId !== void 0 && channelId !== "default") {
|
|
125401
|
+
const channels = (snapshot.value?.openaiCompatChannels ?? []).map((channel) => channel.id === channelId ? {
|
|
125402
|
+
...channel,
|
|
125403
|
+
model
|
|
125404
|
+
} : channel);
|
|
125405
|
+
await writeSetting(props.scope, "openaiCompatChannels", channels, t("writeRejected"));
|
|
125406
|
+
} else if (model !== void 0 && modelField !== void 0) await writeSetting(props.scope, modelField, model, t("writeRejected"));
|
|
125407
|
+
if (provider === "openai-compat" && channelId !== void 0 && currentChannel?.id !== channelId) await writeSetting(props.scope, "openaiCompatActiveChannel", channelId, t("writeRejected"));
|
|
125408
|
+
if (provider !== current) await writeSetting(props.scope, "provider", provider, t("writeRejected"));
|
|
125409
|
+
})().then(() => {
|
|
125256
125410
|
setOpen(false);
|
|
125257
125411
|
}).catch((cause) => {
|
|
125258
125412
|
setError(cause instanceof Error ? cause.message : String(cause));
|
|
@@ -125263,13 +125417,13 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125263
125417
|
/** Plan A dots: ComfyUI is always fixed blue (theme-independent); each
|
|
125264
125418
|
* subscription reflects its login state (green in, gray out); cloud rows
|
|
125265
125419
|
* reflect their API-key state as before. */
|
|
125266
|
-
const dotClassOf = (provider) => {
|
|
125420
|
+
const dotClassOf = (provider, channelId) => {
|
|
125267
125421
|
if (provider === "comfyui") return "dsh-ig-pill-dot-neutral";
|
|
125268
125422
|
if (isSubscriptionProvider(provider)) return subDots[provider] === "logged-in" ? "dsh-ig-pill-dot-ok" : "dsh-ig-pill-dot-missing";
|
|
125269
|
-
const dot = dots[provider];
|
|
125423
|
+
const dot = dots[pillTargetKey(provider, channelId)];
|
|
125270
125424
|
return dot === "configured" ? "dsh-ig-pill-dot-ok" : dot === "missing" ? "dsh-ig-pill-dot-missing" : "dsh-ig-pill-dot-neutral";
|
|
125271
125425
|
};
|
|
125272
|
-
const subtitleOf = (provider) => {
|
|
125426
|
+
const subtitleOf = (provider, includeModel = true, channelId) => {
|
|
125273
125427
|
if (provider === "comfyui") {
|
|
125274
125428
|
const workflow = pillModelOf(provider, snapshot.value);
|
|
125275
125429
|
return workflow.length > 0 ? `${t("noKeyNeeded")} · ${workflow}` : `${t("noKeyNeeded")} · ${t("noWorkflow")}`;
|
|
@@ -125279,12 +125433,17 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125279
125433
|
const stateText = state === "logged-in" ? t("subSignedIn") : state === "logged-out" ? t("subSignedOut") : t("subStatusUnknown");
|
|
125280
125434
|
return `${t("subNoKey")} · ${stateText} · ${pillModelOf(provider, snapshot.value)}`;
|
|
125281
125435
|
}
|
|
125282
|
-
const dot = dots[provider];
|
|
125283
|
-
const model = pillModelOf(provider, snapshot.value);
|
|
125284
|
-
|
|
125285
|
-
if (dot === "
|
|
125286
|
-
return
|
|
125436
|
+
const dot = dots[pillTargetKey(provider, channelId)];
|
|
125437
|
+
const model = pillModelOf(provider, snapshot.value, channelId);
|
|
125438
|
+
const modelSuffix = includeModel ? ` · ${model}` : "";
|
|
125439
|
+
if (dot === "configured") return `${t("keyConfigured")}${modelSuffix}`;
|
|
125440
|
+
if (dot === "missing") return `${t("keyMissing")}${modelSuffix}`;
|
|
125441
|
+
return includeModel ? model : "";
|
|
125287
125442
|
};
|
|
125443
|
+
const menuEntries = IMAGE_PROVIDERS.flatMap((provider) => provider === "openai-compat" ? resolveOpenAICompatChannels(snapshot.value ?? {}).map((channel) => ({
|
|
125444
|
+
provider,
|
|
125445
|
+
channel
|
|
125446
|
+
})) : [{ provider }]);
|
|
125288
125447
|
return (0, react_jsx_runtime.jsxs)("div", {
|
|
125289
125448
|
className: "dsh-ig-pill-root",
|
|
125290
125449
|
children: [(0, react_jsx_runtime.jsxs)("button", {
|
|
@@ -125328,7 +125487,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125328
125487
|
}),
|
|
125329
125488
|
(0, react_jsx_runtime.jsx)("span", {
|
|
125330
125489
|
className: "dsh-ig-pill-provider",
|
|
125331
|
-
children: PILL_PROVIDER_LABELS[lang][current]
|
|
125490
|
+
children: currentChannel?.label ?? PILL_PROVIDER_LABELS[lang][current]
|
|
125332
125491
|
}),
|
|
125333
125492
|
(0, react_jsx_runtime.jsx)("span", {
|
|
125334
125493
|
className: `dsh-ig-pill-caret${open ? " dsh-ig-pill-caret-open" : ""}`,
|
|
@@ -125356,47 +125515,83 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125356
125515
|
className: "dsh-ig-pill-menu-title",
|
|
125357
125516
|
children: t("menuTitle")
|
|
125358
125517
|
}),
|
|
125359
|
-
|
|
125360
|
-
|
|
125361
|
-
|
|
125362
|
-
"
|
|
125363
|
-
|
|
125364
|
-
|
|
125365
|
-
|
|
125366
|
-
|
|
125367
|
-
|
|
125368
|
-
|
|
125369
|
-
|
|
125370
|
-
|
|
125371
|
-
|
|
125372
|
-
}
|
|
125373
|
-
|
|
125374
|
-
|
|
125518
|
+
menuEntries.map(({ provider, channel }) => {
|
|
125519
|
+
const channelId = channel?.id;
|
|
125520
|
+
const modelOptions = pillModelOptionsOf(provider, snapshot.value, channelId);
|
|
125521
|
+
const active = provider === current && (provider !== "openai-compat" || currentChannel?.id === channelId);
|
|
125522
|
+
const currentModel = active ? pillModelOf(provider, snapshot.value, channelId) : "";
|
|
125523
|
+
return (0, react_jsx_runtime.jsxs)(react.Fragment, { children: [(0, react_jsx_runtime.jsxs)("button", {
|
|
125524
|
+
type: "button",
|
|
125525
|
+
role: modelOptions.length > 0 ? "menuitem" : "menuitemradio",
|
|
125526
|
+
"aria-checked": modelOptions.length > 0 ? void 0 : active,
|
|
125527
|
+
className: `dsh-ig-pill-option${active ? " dsh-ig-pill-option-active" : ""}`,
|
|
125528
|
+
disabled: pending !== void 0,
|
|
125529
|
+
onClick: () => {
|
|
125530
|
+
select(provider, void 0, channelId);
|
|
125531
|
+
},
|
|
125532
|
+
children: [
|
|
125533
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
125534
|
+
className: `dsh-ig-pill-dot ${dotClassOf(provider, channelId)}`,
|
|
125535
|
+
"aria-hidden": "true"
|
|
125536
|
+
}),
|
|
125537
|
+
(0, react_jsx_runtime.jsxs)("span", {
|
|
125538
|
+
className: "dsh-ig-pill-option-text",
|
|
125539
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
125540
|
+
className: "dsh-ig-pill-option-name",
|
|
125541
|
+
children: channel?.label ?? PILL_PROVIDER_LABELS[lang][provider]
|
|
125542
|
+
}), (0, react_jsx_runtime.jsx)("span", {
|
|
125543
|
+
className: "dsh-ig-pill-option-sub",
|
|
125544
|
+
children: subtitleOf(provider, modelOptions.length === 0, channelId)
|
|
125545
|
+
})]
|
|
125546
|
+
}),
|
|
125547
|
+
active && modelOptions.length === 0 ? (0, react_jsx_runtime.jsx)("span", {
|
|
125548
|
+
className: "dsh-ig-pill-check",
|
|
125549
|
+
"aria-hidden": "true",
|
|
125550
|
+
children: (0, react_jsx_runtime.jsx)("svg", {
|
|
125551
|
+
width: "13",
|
|
125552
|
+
height: "13",
|
|
125553
|
+
viewBox: "0 0 16 16",
|
|
125554
|
+
fill: "none",
|
|
125555
|
+
stroke: "currentColor",
|
|
125556
|
+
strokeWidth: "2.2",
|
|
125557
|
+
strokeLinecap: "round",
|
|
125558
|
+
strokeLinejoin: "round",
|
|
125559
|
+
children: (0, react_jsx_runtime.jsx)("path", { d: "M2.5 8.5l3.5 3.5 7-8" })
|
|
125560
|
+
})
|
|
125561
|
+
}) : null
|
|
125562
|
+
]
|
|
125563
|
+
}), modelOptions.map((model) => {
|
|
125564
|
+
const selected = active && model === currentModel;
|
|
125565
|
+
return (0, react_jsx_runtime.jsxs)("button", {
|
|
125566
|
+
type: "button",
|
|
125567
|
+
role: "menuitemradio",
|
|
125568
|
+
"aria-checked": selected,
|
|
125569
|
+
className: `dsh-ig-pill-option dsh-ig-pill-model-option${selected ? " dsh-ig-pill-option-active" : ""}`,
|
|
125570
|
+
disabled: pending !== void 0,
|
|
125571
|
+
onClick: () => {
|
|
125572
|
+
select(provider, model, channelId);
|
|
125573
|
+
},
|
|
125375
125574
|
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)),
|
|
125575
|
+
className: "dsh-ig-pill-model-name",
|
|
125576
|
+
children: model
|
|
125577
|
+
}), selected ? (0, react_jsx_runtime.jsx)("span", {
|
|
125578
|
+
className: "dsh-ig-pill-check",
|
|
125579
|
+
"aria-hidden": "true",
|
|
125580
|
+
children: (0, react_jsx_runtime.jsx)("svg", {
|
|
125581
|
+
width: "13",
|
|
125582
|
+
height: "13",
|
|
125583
|
+
viewBox: "0 0 16 16",
|
|
125584
|
+
fill: "none",
|
|
125585
|
+
stroke: "currentColor",
|
|
125586
|
+
strokeWidth: "2.2",
|
|
125587
|
+
strokeLinecap: "round",
|
|
125588
|
+
strokeLinejoin: "round",
|
|
125589
|
+
children: (0, react_jsx_runtime.jsx)("path", { d: "M2.5 8.5l3.5 3.5 7-8" })
|
|
125590
|
+
})
|
|
125591
|
+
}) : null]
|
|
125592
|
+
}, model);
|
|
125593
|
+
})] }, channelId === void 0 ? provider : pillTargetKey("openai-compat", channelId));
|
|
125594
|
+
}),
|
|
125400
125595
|
error.length > 0 ? (0, react_jsx_runtime.jsxs)("div", {
|
|
125401
125596
|
className: "dsh-ig-pill-error",
|
|
125402
125597
|
role: "alert",
|
|
@@ -125440,12 +125635,14 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125440
125635
|
.dsh-ig-pill-option-text{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
|
|
125441
125636
|
.dsh-ig-pill-option-name{font-size:12.5px;font-weight:500;color:var(--dsw-alias-label-primary,#111827);line-height:1.2}
|
|
125442
125637
|
.dsh-ig-pill-option-sub{font-size:11px;color:var(--dsw-alias-label-tertiary,#6b7280);line-height:1.2;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
125638
|
+
.dsh-ig-pill-model-option{padding-left:24px}
|
|
125639
|
+
.dsh-ig-pill-model-name{flex:1;min-width:0;font-size:12px;color:var(--dsw-alias-label-secondary,#4b5563);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
125443
125640
|
.dsh-ig-pill-check{flex:none;color:var(--dsw-alias-brand-primary,#4c78ff)}
|
|
125444
125641
|
.dsh-ig-pill-error{margin-top:4px;padding:6px 8px;border-radius:8px;background:rgba(239,68,68,.08);color:#ef4444;font-size:11.5px;line-height:1.4;word-break:break-all}
|
|
125445
125642
|
`;
|
|
125446
125643
|
//#endregion
|
|
125447
125644
|
//#region lib/types/client/index.js
|
|
125448
|
-
console.info(`[dsh-image-gen] canvas bundle 2026-10-
|
|
125645
|
+
console.info(`[dsh-image-gen] canvas bundle 2026-10-28T11:56:09.512Z`);
|
|
125449
125646
|
/** Right-sidebar tab-type registration id (DSH 0.1.5 `sidebarRightTabs`). */
|
|
125450
125647
|
const SIDEBAR_STUDIO_TAB_ID = "dsh-image-gen/studio";
|
|
125451
125648
|
/** The tab kind: a page type opened by kind, recognizing no resource address. */
|
|
@@ -125464,6 +125661,11 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125464
125661
|
providerGoogle: "Google Gemini",
|
|
125465
125662
|
providerOpenAI: "OpenAI",
|
|
125466
125663
|
providerOpenAICompat: "OpenAI 兼容(中转站)",
|
|
125664
|
+
addCompatChannel: "新增 OpenAI 兼容渠道",
|
|
125665
|
+
channelName: "渠道名称",
|
|
125666
|
+
channelNameRequired: "请填写渠道名称。",
|
|
125667
|
+
removeChannel: "删除渠道",
|
|
125668
|
+
removeChannelConfirm: "确定删除“{label}”吗?该渠道的配置将被移除。",
|
|
125467
125669
|
providerSeedream: "字节 Seedream",
|
|
125468
125670
|
providerDashScope: "阿里 DashScope (通义万相 / Qwen)",
|
|
125469
125671
|
providerXAI: "xAI Grok Imagine",
|
|
@@ -125570,6 +125772,10 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125570
125772
|
endpointHintZhipu: "智谱开放平台 open.bigmodel.cn 的 /api/paas/v4 地址。",
|
|
125571
125773
|
endpointHintComfyUI: "正在运行且 DSH Host 可以访问的 ComfyUI 地址,默认使用本机 8188 端口。",
|
|
125572
125774
|
model: "模型",
|
|
125775
|
+
defaultModel: "默认模型",
|
|
125776
|
+
availableModels: "工作台可选模型",
|
|
125777
|
+
availableModelsHint: "勾选后可在工作台切换。手动输入的默认模型会自动加入列表,且不可移除。",
|
|
125778
|
+
defaultModelTag: "默认",
|
|
125573
125779
|
workflow: "API Workflow 工作流",
|
|
125574
125780
|
workflowImport: "导入 JSON 文件",
|
|
125575
125781
|
workflowMissing: "尚未导入工作流",
|
|
@@ -125584,6 +125790,8 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125584
125790
|
workflowDuplicateName: "工作流名称不能重复。",
|
|
125585
125791
|
timeout: "生成超时(秒)",
|
|
125586
125792
|
timeoutHint: "包括提交、等待和下载图片;默认 300 秒。",
|
|
125793
|
+
cloudTimeout: "云端生成超时(秒)",
|
|
125794
|
+
cloudTimeoutHint: "工作台所有 API Key 通道共用,5–3600 秒,默认 150 秒。不影响订阅通道和 ComfyUI;修改后对新请求生效。",
|
|
125587
125795
|
workspaceSection: "工作区",
|
|
125588
125796
|
saveToWorkspace: "保存到工作区",
|
|
125589
125797
|
saveToWorkspaceHint: "每次生成后,把图片文件保存到当前会话工作区。",
|
|
@@ -125637,7 +125845,12 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125637
125845
|
settingsIncompatible: "The loaded settings library cannot save these settings. Update @deepseek-ai/schemastery in the plugin environment to 3.18.4 or a compatible 3.x version, then restart DSH.",
|
|
125638
125846
|
providerGoogle: "Google Gemini",
|
|
125639
125847
|
providerOpenAI: "OpenAI",
|
|
125640
|
-
providerOpenAICompat: "OpenAI
|
|
125848
|
+
providerOpenAICompat: "OpenAI Compatible (relay)",
|
|
125849
|
+
addCompatChannel: "Add OpenAI-compatible channel",
|
|
125850
|
+
channelName: "Channel name",
|
|
125851
|
+
channelNameRequired: "Enter a channel name.",
|
|
125852
|
+
removeChannel: "Remove channel",
|
|
125853
|
+
removeChannelConfirm: "Remove \"{label}\"? Its channel configuration will be deleted.",
|
|
125641
125854
|
providerSeedream: "ByteDance Seedream",
|
|
125642
125855
|
providerDashScope: "Aliyun DashScope (Wanx / Qwen)",
|
|
125643
125856
|
providerXAI: "xAI Grok Imagine",
|
|
@@ -125744,6 +125957,10 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125744
125957
|
endpointHintZhipu: "Zhipu open.bigmodel.cn /api/paas/v4 base URL.",
|
|
125745
125958
|
endpointHintComfyUI: "A running ComfyUI server reachable by the DSH Host; the default points to port 8188 on this computer.",
|
|
125746
125959
|
model: "Model",
|
|
125960
|
+
defaultModel: "Default model",
|
|
125961
|
+
availableModels: "Models available in Studio",
|
|
125962
|
+
availableModelsHint: "Selected models can be switched in Studio. A manually entered default is added automatically and cannot be removed.",
|
|
125963
|
+
defaultModelTag: "Default",
|
|
125747
125964
|
workflow: "API Workflows",
|
|
125748
125965
|
workflowImport: "Import JSON file",
|
|
125749
125966
|
workflowMissing: "No workflow imported",
|
|
@@ -125758,6 +125975,8 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125758
125975
|
workflowDuplicateName: "Workflow names must be unique.",
|
|
125759
125976
|
timeout: "Generation timeout (seconds)",
|
|
125760
125977
|
timeoutHint: "Covers submission, waiting, and image download; defaults to 300 seconds.",
|
|
125978
|
+
cloudTimeout: "Cloud generation timeout (seconds)",
|
|
125979
|
+
cloudTimeoutHint: "Shared by all API-key channels in the workbench, 5–3600 seconds; defaults to 150 seconds. Does not affect subscription channels or ComfyUI; applies to new requests.",
|
|
125761
125980
|
workspaceSection: "Workspace",
|
|
125762
125981
|
saveToWorkspace: "Save to workspace",
|
|
125763
125982
|
saveToWorkspaceHint: "Write each generated image as a file into the session workspace.",
|
|
@@ -125834,6 +126053,10 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125834
126053
|
.dsh-ig-actions{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:16px;padding-top:12px;border-top:1px solid var(--dsw-alias-border-l2,#eee)}
|
|
125835
126054
|
.dsh-ig-check-row{display:flex;align-items:center;gap:8px;cursor:pointer}
|
|
125836
126055
|
.dsh-ig-check-row input[type=checkbox]{width:15px;height:15px;accent-color:var(--dsw-alias-brand-primary,#4c78ff);margin:0}
|
|
126056
|
+
.dsh-ig-model-picker{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:8px 12px;max-height:180px;overflow-y:auto;padding:2px 0}
|
|
126057
|
+
.dsh-ig-model-picker .dsh-ig-check-row{min-width:0}
|
|
126058
|
+
.dsh-ig-model-option{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:12px}
|
|
126059
|
+
.dsh-ig-model-default{flex:none;color:var(--dsw-alias-label-tertiary,#7b818b);font-size:11px}
|
|
125837
126060
|
.dsh-ig-savedto{font-size:12px;line-height:1.5;color:var(--dsw-alias-label-tertiary,#7b818b);word-break:break-all}
|
|
125838
126061
|
.dsh-ig-save{appearance:none;border:0;border-radius:var(--dsw-radius-md,6px);padding:5px 14px;background:var(--dsw-alias-label-primary,#111827);color:var(--dsw-alias-bg-layer-3,#fff);font:inherit;font-size:13px;font-weight:400;cursor:pointer;transition:opacity .15s}
|
|
125839
126062
|
.dsh-ig-save:disabled{opacity:.4;cursor:default}
|
|
@@ -125842,7 +126065,9 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
125842
126065
|
.dsh-ig-providers{display:flex;flex-direction:column;margin-top:6px}
|
|
125843
126066
|
.dsh-ig-provider-row{border:0;background:none;padding:14px 0}
|
|
125844
126067
|
.dsh-ig-provider-row + .dsh-ig-provider-row{border-top:0.5px solid var(--dsw-alias-border-l2,#e8ebf0)}
|
|
125845
|
-
.dsh-ig-provider-head{
|
|
126068
|
+
.dsh-ig-provider-head-row{display:flex;align-items:center;gap:10px}
|
|
126069
|
+
.dsh-ig-provider-head{flex:1;min-width:0;width:100%;appearance:none;border:0;background:none;font:inherit;color:inherit;text-align:left;cursor:pointer;display:flex;align-items:center;gap:10px;padding:0}
|
|
126070
|
+
.dsh-ig-channel-add{flex:none;width:30px;padding:4px 0;font-size:16px;line-height:20px}
|
|
125846
126071
|
.dsh-ig-provider-head:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4c78ff);outline-offset:2px;border-radius:var(--dsw-radius-sm,4px)}
|
|
125847
126072
|
.dsh-ig-provider-head:hover .dsh-ig-provider-name{color:var(--dsw-alias-label-secondary,inherit)}
|
|
125848
126073
|
.dsh-ig-provider-name{flex:1;min-width:0;font-size:13.5px;font-weight:550;color:var(--dsw-alias-label-primary,inherit)}
|
|
@@ -126344,7 +126569,9 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126344
126569
|
function emptyProviderRow() {
|
|
126345
126570
|
return {
|
|
126346
126571
|
expanded: false,
|
|
126572
|
+
label: "",
|
|
126347
126573
|
model: "",
|
|
126574
|
+
models: [],
|
|
126348
126575
|
editModel: "",
|
|
126349
126576
|
baseURL: "",
|
|
126350
126577
|
googleNative: false,
|
|
@@ -126430,6 +126657,28 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126430
126657
|
function parseEditFormat(value) {
|
|
126431
126658
|
return value === "jsonImageUrlArray" || value === "formReferenceImages" || value === "siliconflowJson" ? value : "multipart";
|
|
126432
126659
|
}
|
|
126660
|
+
function compatChannelRowKey(channelId) {
|
|
126661
|
+
return `openai-compat:${channelId}`;
|
|
126662
|
+
}
|
|
126663
|
+
function compatRowFields(channel) {
|
|
126664
|
+
return {
|
|
126665
|
+
label: channel.label,
|
|
126666
|
+
model: channel.model,
|
|
126667
|
+
models: resolveOpenAICompatModels({
|
|
126668
|
+
openaiCompatModel: channel.model,
|
|
126669
|
+
openaiCompatModels: channel.models ?? []
|
|
126670
|
+
}),
|
|
126671
|
+
editModel: channel.editModel ?? "",
|
|
126672
|
+
baseURL: channel.baseURL,
|
|
126673
|
+
editFormat: parseEditFormat(channel.editFormat),
|
|
126674
|
+
editExtraText: editExtraTextOf(channel.editExtra),
|
|
126675
|
+
sizeTableText: editExtraTextOf(channel.sizes),
|
|
126676
|
+
generationQuality: channel.quality ?? "",
|
|
126677
|
+
qualityOptionsText: (channel.qualityOptions !== void 0 && channel.qualityOptions.length > 0 ? channel.qualityOptions : DEFAULT_COMPAT_QUALITIES).join(", "),
|
|
126678
|
+
generateExtraText: editExtraTextOf(channel.extraBody),
|
|
126679
|
+
editSizeMode: channel.editSizeMode === "selected" ? "selected" : "auto"
|
|
126680
|
+
};
|
|
126681
|
+
}
|
|
126433
126682
|
/** Build one row per provider from persisted settings, including ComfyUI extras. */
|
|
126434
126683
|
function rowsFromSettings(value) {
|
|
126435
126684
|
const rows = {};
|
|
@@ -126444,22 +126693,17 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126444
126693
|
activeWorkflow: activeComfyUIWorkflow(value ?? {})?.name ?? "",
|
|
126445
126694
|
timeoutSeconds: Math.max(1, Math.round((value?.comfyuiTimeoutMs ?? 3e5) / 1e3))
|
|
126446
126695
|
} : {},
|
|
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
|
-
} : {},
|
|
126696
|
+
...provider === "openai-compat" ? compatRowFields(resolveOpenAICompatChannels(value ?? {})[0]) : {},
|
|
126457
126697
|
...provider === "seedream" ? {
|
|
126458
126698
|
outputFormat: value?.seedreamOutputFormat === "png" ? "png" : "jpeg",
|
|
126459
126699
|
watermark: value?.seedreamWatermark !== false,
|
|
126460
126700
|
background: value?.seedreamBackground === "transparent" ? "transparent" : "opaque"
|
|
126461
126701
|
} : {}
|
|
126462
126702
|
};
|
|
126703
|
+
for (const channel of resolveOpenAICompatChannels(value ?? {}).slice(1)) rows[compatChannelRowKey(channel.id)] = {
|
|
126704
|
+
...emptyProviderRow(),
|
|
126705
|
+
...compatRowFields(channel)
|
|
126706
|
+
};
|
|
126463
126707
|
return rows;
|
|
126464
126708
|
}
|
|
126465
126709
|
/** Edit each provider independently, pick an explicit default, and verify keys inline. */
|
|
@@ -126473,6 +126717,8 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126473
126717
|
const [defaultProvider, setDefaultProvider] = (0, react.useState)(() => props.scope.getSnapshot().value?.provider ?? "google");
|
|
126474
126718
|
const [providerMessage, setProviderMessage] = (0, react.useState)("");
|
|
126475
126719
|
const [providerMessageIsError, setProviderMessageIsError] = (0, react.useState)(false);
|
|
126720
|
+
const [cloudTimeoutSeconds, setCloudTimeoutSeconds] = (0, react.useState)(() => (props.scope.getSnapshot().value?.cloudTimeoutMs ?? 15e4) / 1e3);
|
|
126721
|
+
const [cloudTimeoutMessage, setCloudTimeoutMessage] = (0, react.useState)("");
|
|
126476
126722
|
const [saveToWorkspace, setSaveToWorkspace] = (0, react.useState)(() => props.scope.getSnapshot().value?.saveToWorkspace ?? true);
|
|
126477
126723
|
const [workspaceFolder, setWorkspaceFolder] = (0, react.useState)(() => props.scope.getSnapshot().value?.workspaceFolder ?? "dsh-image-gen");
|
|
126478
126724
|
const [showPill, setShowPill] = (0, react.useState)(() => props.scope.getSnapshot().value?.showProviderPill === true);
|
|
@@ -126481,6 +126727,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126481
126727
|
const [workspaceMessage, setWorkspaceMessage] = (0, react.useState)("");
|
|
126482
126728
|
const [workspaceMessageIsError, setWorkspaceMessageIsError] = (0, react.useState)(false);
|
|
126483
126729
|
const [rows, setRows] = (0, react.useState)(() => rowsFromSettings(props.scope.getSnapshot().value));
|
|
126730
|
+
const [compatChannels, setCompatChannels] = (0, react.useState)(() => resolveOpenAICompatChannels(props.scope.getSnapshot().value ?? {}).slice(1));
|
|
126484
126731
|
const [keyTick, setKeyTick] = (0, react.useState)(0);
|
|
126485
126732
|
const [subStatus, setSubStatus] = (0, react.useState)(() => ({
|
|
126486
126733
|
"chatgpt-sub": { state: "unknown" },
|
|
@@ -126690,15 +126937,16 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126690
126937
|
(0, react.useEffect)(() => {
|
|
126691
126938
|
const value = snapshot.value;
|
|
126692
126939
|
setDefaultProvider(value?.provider ?? "google");
|
|
126940
|
+
setCloudTimeoutSeconds((value?.cloudTimeoutMs ?? 15e4) / 1e3);
|
|
126693
126941
|
setSaveToWorkspace(value?.saveToWorkspace ?? true);
|
|
126694
126942
|
setWorkspaceFolder(value?.workspaceFolder ?? "dsh-image-gen");
|
|
126695
126943
|
setShowPill(value?.showProviderPill === true);
|
|
126696
126944
|
setRows((current) => {
|
|
126697
|
-
const next = {};
|
|
126945
|
+
const next = { ...current };
|
|
126698
126946
|
for (const provider of IMAGE_PROVIDERS) next[provider] = {
|
|
126699
126947
|
...current[provider],
|
|
126700
126948
|
model: modelOf(provider, value),
|
|
126701
|
-
...provider === "openai-compat" ?
|
|
126949
|
+
...provider === "openai-compat" ? compatRowFields(resolveOpenAICompatChannels(value ?? {})[0]) : {},
|
|
126702
126950
|
baseURL: baseURLOf(provider, value),
|
|
126703
126951
|
...provider === "comfyui" ? {
|
|
126704
126952
|
workflows: resolveComfyUIWorkflows(value ?? {}),
|
|
@@ -126711,6 +126959,13 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126711
126959
|
background: value?.seedreamBackground === "transparent" ? "transparent" : "opaque"
|
|
126712
126960
|
} : {}
|
|
126713
126961
|
};
|
|
126962
|
+
for (const channel of resolveOpenAICompatChannels(value ?? {}).slice(1)) {
|
|
126963
|
+
const key = compatChannelRowKey(channel.id);
|
|
126964
|
+
next[key] = {
|
|
126965
|
+
...current[key] ?? emptyProviderRow(),
|
|
126966
|
+
...compatRowFields(channel)
|
|
126967
|
+
};
|
|
126968
|
+
}
|
|
126714
126969
|
return next;
|
|
126715
126970
|
});
|
|
126716
126971
|
}, [snapshot]);
|
|
@@ -126718,11 +126973,21 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126718
126973
|
const credentialsAvailable = props.credentialsAvailable;
|
|
126719
126974
|
(0, react.useEffect)(() => {
|
|
126720
126975
|
let active = true;
|
|
126976
|
+
const targets = [...CLOUD_IMAGE_PROVIDERS.flatMap((provider) => {
|
|
126977
|
+
const keyRef = cloudCredentialRef(provider);
|
|
126978
|
+
return keyRef === void 0 ? [] : [{
|
|
126979
|
+
key: provider,
|
|
126980
|
+
keyRef
|
|
126981
|
+
}];
|
|
126982
|
+
}), ...compatChannels.map((channel) => ({
|
|
126983
|
+
key: compatChannelRowKey(channel.id),
|
|
126984
|
+
keyRef: channel.keyRef
|
|
126985
|
+
}))];
|
|
126721
126986
|
if (!credentialsAvailable()) {
|
|
126722
126987
|
setRows((current) => {
|
|
126723
126988
|
const next = { ...current };
|
|
126724
|
-
for (const
|
|
126725
|
-
...current[
|
|
126989
|
+
for (const target of targets) next[target.key] = {
|
|
126990
|
+
...current[target.key] ?? emptyProviderRow(),
|
|
126726
126991
|
keyStatus: "unavailable",
|
|
126727
126992
|
keyInfo: void 0
|
|
126728
126993
|
};
|
|
@@ -126732,23 +126997,21 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126732
126997
|
active = false;
|
|
126733
126998
|
};
|
|
126734
126999
|
}
|
|
126735
|
-
for (const
|
|
126736
|
-
const keyRef = cloudCredentialRef(provider);
|
|
126737
|
-
if (keyRef === void 0) continue;
|
|
127000
|
+
for (const target of targets) {
|
|
126738
127001
|
setRows((current) => ({
|
|
126739
127002
|
...current,
|
|
126740
|
-
[
|
|
126741
|
-
...current[
|
|
127003
|
+
[target.key]: {
|
|
127004
|
+
...current[target.key],
|
|
126742
127005
|
keyStatus: "checking"
|
|
126743
127006
|
}
|
|
126744
127007
|
}));
|
|
126745
|
-
credentials.describe([keyRef]).then((response) => {
|
|
127008
|
+
credentials.describe([target.keyRef]).then((response) => {
|
|
126746
127009
|
if (!active) return;
|
|
126747
|
-
const info = response.ok ? response.value?.[keyRef] : void 0;
|
|
127010
|
+
const info = response.ok ? response.value?.[target.keyRef] : void 0;
|
|
126748
127011
|
setRows((current) => ({
|
|
126749
127012
|
...current,
|
|
126750
|
-
[
|
|
126751
|
-
...current[
|
|
127013
|
+
[target.key]: {
|
|
127014
|
+
...current[target.key],
|
|
126752
127015
|
keyStatus: response.ok ? info?.configured ? "configured" : "missing" : "unknown",
|
|
126753
127016
|
keyInfo: info
|
|
126754
127017
|
}
|
|
@@ -126757,8 +127020,8 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126757
127020
|
if (!active) return;
|
|
126758
127021
|
setRows((current) => ({
|
|
126759
127022
|
...current,
|
|
126760
|
-
[
|
|
126761
|
-
...current[
|
|
127023
|
+
[target.key]: {
|
|
127024
|
+
...current[target.key],
|
|
126762
127025
|
keyStatus: "unknown"
|
|
126763
127026
|
}
|
|
126764
127027
|
}));
|
|
@@ -126770,13 +127033,14 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126770
127033
|
}, [
|
|
126771
127034
|
credentials,
|
|
126772
127035
|
credentialsAvailable,
|
|
126773
|
-
keyTick
|
|
127036
|
+
keyTick,
|
|
127037
|
+
compatChannels
|
|
126774
127038
|
]);
|
|
126775
|
-
const updateRow = (
|
|
127039
|
+
const updateRow = (target, patch) => {
|
|
126776
127040
|
setRows((current) => ({
|
|
126777
127041
|
...current,
|
|
126778
|
-
[
|
|
126779
|
-
...current[
|
|
127042
|
+
[target]: {
|
|
127043
|
+
...current[target],
|
|
126780
127044
|
...patch
|
|
126781
127045
|
}
|
|
126782
127046
|
}));
|
|
@@ -126792,15 +127056,49 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126792
127056
|
setProviderMessageIsError(true);
|
|
126793
127057
|
});
|
|
126794
127058
|
};
|
|
126795
|
-
const saveProviderRow = async (provider) => {
|
|
126796
|
-
const
|
|
126797
|
-
|
|
127059
|
+
const saveProviderRow = async (provider, channel) => {
|
|
127060
|
+
const target = channel === void 0 ? provider : compatChannelRowKey(channel.id);
|
|
127061
|
+
const row = rows[target];
|
|
127062
|
+
updateRow(target, {
|
|
126798
127063
|
saving: true,
|
|
126799
127064
|
message: "",
|
|
126800
127065
|
messageIsError: false
|
|
126801
127066
|
});
|
|
126802
127067
|
try {
|
|
126803
|
-
if (
|
|
127068
|
+
if (channel !== void 0) {
|
|
127069
|
+
const label = row.label.trim();
|
|
127070
|
+
if (label.length === 0) throw new Error(t("channelNameRequired"));
|
|
127071
|
+
const updated = {
|
|
127072
|
+
...channel,
|
|
127073
|
+
label,
|
|
127074
|
+
baseURL: row.baseURL.trim(),
|
|
127075
|
+
model: row.model.trim(),
|
|
127076
|
+
models: resolveOpenAICompatModels({
|
|
127077
|
+
openaiCompatModel: row.model,
|
|
127078
|
+
openaiCompatModels: row.models
|
|
127079
|
+
}),
|
|
127080
|
+
editModel: row.editModel.trim(),
|
|
127081
|
+
quality: row.generationQuality.trim(),
|
|
127082
|
+
qualityOptions: [...new Set(row.qualityOptionsText.split(",").map((value) => value.trim()).filter(Boolean))],
|
|
127083
|
+
extraBody: parseExtraFields(row.generateExtraText, t("editExtraInvalid")),
|
|
127084
|
+
editSizeMode: row.editSizeMode,
|
|
127085
|
+
editFormat: row.editFormat,
|
|
127086
|
+
editExtra: parseExtraFields(row.editExtraText, t("editExtraInvalid")),
|
|
127087
|
+
sizes: parseSizeTable(row.sizeTableText, t("sizeTableInvalid"))
|
|
127088
|
+
};
|
|
127089
|
+
const nextChannels = compatChannels.some((entry) => entry.id === channel.id) ? compatChannels.map((entry) => entry.id === channel.id ? updated : entry) : [...compatChannels, updated];
|
|
127090
|
+
await saveSetting("openaiCompatChannels", nextChannels);
|
|
127091
|
+
setCompatChannels(nextChannels);
|
|
127092
|
+
if (row.keyInput.trim().length > 0) {
|
|
127093
|
+
if (!credentialsAvailable()) throw new Error(t("credentialsUnavailable"));
|
|
127094
|
+
const response = await props.credentials.set(channel.keyRef, row.keyInput.trim());
|
|
127095
|
+
if (!response.ok) throw new Error(response.error?.message ?? t("saveKeyFailed"));
|
|
127096
|
+
updateRow(target, {
|
|
127097
|
+
keyInput: "",
|
|
127098
|
+
keyStatus: "configured"
|
|
127099
|
+
});
|
|
127100
|
+
}
|
|
127101
|
+
} else if (provider === "comfyui") {
|
|
126804
127102
|
const entries = row.workflows.map((entry) => ({
|
|
126805
127103
|
name: entry.name.trim(),
|
|
126806
127104
|
json: entry.json,
|
|
@@ -126829,6 +127127,11 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126829
127127
|
if (provider === "google") await saveSetting("googleNative", row.googleNative);
|
|
126830
127128
|
if (provider === "openai") await saveSetting("openaiSizes", sizeTable);
|
|
126831
127129
|
if (provider === "openai-compat") {
|
|
127130
|
+
await saveSetting("openaiCompatLabel", row.label.trim());
|
|
127131
|
+
await saveSetting("openaiCompatModels", resolveOpenAICompatModels({
|
|
127132
|
+
openaiCompatModel: row.model,
|
|
127133
|
+
openaiCompatModels: row.models
|
|
127134
|
+
}));
|
|
126832
127135
|
await saveSetting("openaiCompatEditModel", row.editModel.trim());
|
|
126833
127136
|
await saveSetting("openaiCompatEditFormat", row.editFormat);
|
|
126834
127137
|
await saveSetting("openaiCompatEditExtra", editExtra);
|
|
@@ -126849,13 +127152,13 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126849
127152
|
if (!credentialsAvailable()) throw new Error(t("credentialsUnavailable"));
|
|
126850
127153
|
const response = await props.credentials.set(keyRef, row.keyInput.trim());
|
|
126851
127154
|
if (!response.ok) throw new Error(response.error?.message ?? t("saveKeyFailed"));
|
|
126852
|
-
updateRow(
|
|
127155
|
+
updateRow(target, {
|
|
126853
127156
|
keyInput: "",
|
|
126854
127157
|
keyStatus: "configured"
|
|
126855
127158
|
});
|
|
126856
127159
|
}
|
|
126857
127160
|
}
|
|
126858
|
-
updateRow(
|
|
127161
|
+
updateRow(target, {
|
|
126859
127162
|
message: t("saved"),
|
|
126860
127163
|
messageIsError: false,
|
|
126861
127164
|
testResult: void 0,
|
|
@@ -126863,38 +127166,99 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126863
127166
|
modelFetchIsError: false
|
|
126864
127167
|
});
|
|
126865
127168
|
} catch (cause) {
|
|
126866
|
-
updateRow(
|
|
127169
|
+
updateRow(target, {
|
|
126867
127170
|
message: cause instanceof Error ? cause.message : String(cause),
|
|
126868
127171
|
messageIsError: true
|
|
126869
127172
|
});
|
|
126870
127173
|
} finally {
|
|
126871
|
-
updateRow(
|
|
127174
|
+
updateRow(target, { saving: false });
|
|
127175
|
+
}
|
|
127176
|
+
};
|
|
127177
|
+
const addCompatChannel = () => {
|
|
127178
|
+
const id = `channel-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 7)}`;
|
|
127179
|
+
const channel = {
|
|
127180
|
+
id,
|
|
127181
|
+
label: `OpenAI 兼容 ${compatChannels.length + 2}`,
|
|
127182
|
+
keyRef: openAICompatKeyRef(id),
|
|
127183
|
+
baseURL: "",
|
|
127184
|
+
model: "",
|
|
127185
|
+
models: [],
|
|
127186
|
+
qualityOptions: [...DEFAULT_COMPAT_QUALITIES]
|
|
127187
|
+
};
|
|
127188
|
+
setCompatChannels((current) => [...current, channel]);
|
|
127189
|
+
setRows((current) => ({
|
|
127190
|
+
...current,
|
|
127191
|
+
[compatChannelRowKey(id)]: {
|
|
127192
|
+
...emptyProviderRow(),
|
|
127193
|
+
...compatRowFields(channel),
|
|
127194
|
+
expanded: true
|
|
127195
|
+
}
|
|
127196
|
+
}));
|
|
127197
|
+
};
|
|
127198
|
+
const removeCompatChannel = async (channel) => {
|
|
127199
|
+
if (!window.confirm(t("removeChannelConfirm", { label: channel.label }))) return;
|
|
127200
|
+
const target = compatChannelRowKey(channel.id);
|
|
127201
|
+
if (!(snapshot.value?.openaiCompatChannels?.some((entry) => entry.id === channel.id) === true)) {
|
|
127202
|
+
setCompatChannels((current) => current.filter((entry) => entry.id !== channel.id));
|
|
127203
|
+
setRows((current) => {
|
|
127204
|
+
const next = { ...current };
|
|
127205
|
+
delete next[target];
|
|
127206
|
+
return next;
|
|
127207
|
+
});
|
|
127208
|
+
return;
|
|
127209
|
+
}
|
|
127210
|
+
let removed = false;
|
|
127211
|
+
updateRow(target, {
|
|
127212
|
+
saving: true,
|
|
127213
|
+
message: "",
|
|
127214
|
+
messageIsError: false
|
|
127215
|
+
});
|
|
127216
|
+
try {
|
|
127217
|
+
const nextChannels = compatChannels.filter((entry) => entry.id !== channel.id);
|
|
127218
|
+
await saveSetting("openaiCompatChannels", nextChannels);
|
|
127219
|
+
if (snapshot.value?.openaiCompatActiveChannel === channel.id) await saveSetting("openaiCompatActiveChannel", "default");
|
|
127220
|
+
removed = true;
|
|
127221
|
+
setCompatChannels(nextChannels);
|
|
127222
|
+
setRows((current) => {
|
|
127223
|
+
const next = { ...current };
|
|
127224
|
+
delete next[target];
|
|
127225
|
+
return next;
|
|
127226
|
+
});
|
|
127227
|
+
} catch (cause) {
|
|
127228
|
+
updateRow(target, {
|
|
127229
|
+
message: cause instanceof Error ? cause.message : String(cause),
|
|
127230
|
+
messageIsError: true
|
|
127231
|
+
});
|
|
127232
|
+
} finally {
|
|
127233
|
+
if (!removed) updateRow(target, { saving: false });
|
|
126872
127234
|
}
|
|
126873
127235
|
};
|
|
126874
127236
|
/** These actions use host settings, so drafts must be saved before making a request. */
|
|
126875
|
-
const providerActionBlockMessage = (provider) => {
|
|
126876
|
-
const
|
|
127237
|
+
const providerActionBlockMessage = (provider, channel) => {
|
|
127238
|
+
const target = channel === void 0 ? provider : compatChannelRowKey(channel.id);
|
|
127239
|
+
const row = rows[target];
|
|
126877
127240
|
if (row.keyInput.trim().length > 0) return t("saveKeyFirst");
|
|
126878
127241
|
if (isSubscriptionProvider(provider)) return void 0;
|
|
126879
127242
|
const address = row.baseURL.trim();
|
|
126880
127243
|
if (address.length === 0) return t("endpointRequired");
|
|
126881
|
-
if (address !== baseURLOf(provider, props.scope.getSnapshot().value).trim()) return t("saveEndpointFirst");
|
|
127244
|
+
if (address !== (channel === void 0 ? baseURLOf(provider, props.scope.getSnapshot().value) : channel.baseURL).trim()) return t("saveEndpointFirst");
|
|
126882
127245
|
if (provider === "google" && row.googleNative !== (props.scope.getSnapshot().value?.googleNative === true)) return t("saveGoogleProtocolFirst");
|
|
126883
127246
|
};
|
|
126884
127247
|
/** Localize the host's missing-address error while preserving upstream details. */
|
|
126885
127248
|
const providerErrorMessage = (message) => message === "Base URL is not configured" ? t("savedEndpointMissing") : message ?? t("testFailed");
|
|
126886
127249
|
/** Probe through the host route so the browser side never touches credential values. */
|
|
126887
|
-
const testConnection = async (provider) => {
|
|
126888
|
-
const
|
|
127250
|
+
const testConnection = async (provider, channel) => {
|
|
127251
|
+
const target = channel === void 0 ? provider : compatChannelRowKey(channel.id);
|
|
127252
|
+
const blocked = providerActionBlockMessage(provider, channel);
|
|
126889
127253
|
if (blocked !== void 0) {
|
|
126890
|
-
updateRow(
|
|
127254
|
+
updateRow(target, {
|
|
126891
127255
|
message: blocked,
|
|
126892
127256
|
messageIsError: false,
|
|
126893
127257
|
testResult: void 0
|
|
126894
127258
|
});
|
|
126895
127259
|
return;
|
|
126896
127260
|
}
|
|
126897
|
-
updateRow(
|
|
127261
|
+
updateRow(target, {
|
|
126898
127262
|
testing: true,
|
|
126899
127263
|
testResult: void 0,
|
|
126900
127264
|
message: "",
|
|
@@ -126904,31 +127268,35 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126904
127268
|
const response = await fetch(TEST_CONNECTION_ROUTE, {
|
|
126905
127269
|
method: "POST",
|
|
126906
127270
|
headers: { "content-type": "application/json" },
|
|
126907
|
-
body: JSON.stringify({
|
|
127271
|
+
body: JSON.stringify({
|
|
127272
|
+
provider,
|
|
127273
|
+
...channel === void 0 ? {} : { channel: channel.id }
|
|
127274
|
+
})
|
|
126908
127275
|
});
|
|
126909
127276
|
if (!response.ok) throw new Error(`HTTP ${String(response.status)}`);
|
|
126910
|
-
updateRow(
|
|
127277
|
+
updateRow(target, { testResult: await response.json() });
|
|
126911
127278
|
} catch (cause) {
|
|
126912
|
-
updateRow(
|
|
127279
|
+
updateRow(target, { testResult: {
|
|
126913
127280
|
ok: false,
|
|
126914
127281
|
reason: "error",
|
|
126915
127282
|
message: cause instanceof Error ? cause.message : String(cause)
|
|
126916
127283
|
} });
|
|
126917
127284
|
} finally {
|
|
126918
|
-
updateRow(
|
|
127285
|
+
updateRow(target, { testing: false });
|
|
126919
127286
|
}
|
|
126920
127287
|
};
|
|
126921
127288
|
/** Pull the provider's image-capable model ids through the host route (Google and the OpenAI family). */
|
|
126922
|
-
const fetchProviderModels = async (provider) => {
|
|
126923
|
-
const
|
|
127289
|
+
const fetchProviderModels = async (provider, channel) => {
|
|
127290
|
+
const target = channel === void 0 ? provider : compatChannelRowKey(channel.id);
|
|
127291
|
+
const blocked = providerActionBlockMessage(provider, channel);
|
|
126924
127292
|
if (blocked !== void 0) {
|
|
126925
|
-
updateRow(
|
|
127293
|
+
updateRow(target, {
|
|
126926
127294
|
modelFetchMessage: blocked,
|
|
126927
127295
|
modelFetchIsError: false
|
|
126928
127296
|
});
|
|
126929
127297
|
return;
|
|
126930
127298
|
}
|
|
126931
|
-
updateRow(
|
|
127299
|
+
updateRow(target, {
|
|
126932
127300
|
fetchingModels: true,
|
|
126933
127301
|
modelFetchMessage: "",
|
|
126934
127302
|
modelFetchIsError: false
|
|
@@ -126939,50 +127307,52 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126939
127307
|
headers: { "content-type": "application/json" },
|
|
126940
127308
|
body: JSON.stringify({
|
|
126941
127309
|
provider,
|
|
126942
|
-
action: "models"
|
|
127310
|
+
action: "models",
|
|
127311
|
+
...channel === void 0 ? {} : { channel: channel.id }
|
|
126943
127312
|
})
|
|
126944
127313
|
});
|
|
126945
127314
|
if (!response.ok) throw new Error(`HTTP ${String(response.status)}`);
|
|
126946
127315
|
const payload = await response.json();
|
|
126947
127316
|
if (payload.ok && Array.isArray(payload.models)) {
|
|
126948
127317
|
const models = payload.models.filter((id) => typeof id === "string");
|
|
126949
|
-
updateRow(
|
|
127318
|
+
updateRow(target, {
|
|
126950
127319
|
modelOptions: models,
|
|
126951
127320
|
modelFetchMessage: models.length > 0 ? t("modelsFound", { n: String(models.length) }) : t("modelsNone"),
|
|
126952
127321
|
modelFetchIsError: models.length === 0
|
|
126953
127322
|
});
|
|
126954
|
-
} else if (payload.reason === "missing-key") updateRow(
|
|
127323
|
+
} else if (payload.reason === "missing-key") updateRow(target, {
|
|
126955
127324
|
modelFetchMessage: t("badgeMissing"),
|
|
126956
127325
|
modelFetchIsError: true
|
|
126957
127326
|
});
|
|
126958
|
-
else if (payload.reason === "unauthorized") updateRow(
|
|
127327
|
+
else if (payload.reason === "unauthorized") updateRow(target, {
|
|
126959
127328
|
modelFetchMessage: t("testUnauthorized"),
|
|
126960
127329
|
modelFetchIsError: true
|
|
126961
127330
|
});
|
|
126962
|
-
else updateRow(
|
|
127331
|
+
else updateRow(target, {
|
|
126963
127332
|
modelFetchMessage: providerErrorMessage(payload.message),
|
|
126964
127333
|
modelFetchIsError: true
|
|
126965
127334
|
});
|
|
126966
127335
|
} catch (cause) {
|
|
126967
|
-
updateRow(
|
|
127336
|
+
updateRow(target, {
|
|
126968
127337
|
modelFetchMessage: cause instanceof Error ? cause.message : String(cause),
|
|
126969
127338
|
modelFetchIsError: true
|
|
126970
127339
|
});
|
|
126971
127340
|
} finally {
|
|
126972
|
-
updateRow(
|
|
127341
|
+
updateRow(target, { fetchingModels: false });
|
|
126973
127342
|
}
|
|
126974
127343
|
};
|
|
126975
|
-
const clearProviderKey = async (provider) => {
|
|
126976
|
-
const
|
|
127344
|
+
const clearProviderKey = async (provider, channel) => {
|
|
127345
|
+
const target = channel === void 0 ? provider : compatChannelRowKey(channel.id);
|
|
127346
|
+
const keyRef = channel === void 0 ? cloudCredentialRef(provider) : channel.keyRef;
|
|
126977
127347
|
if (keyRef === void 0) return;
|
|
126978
127348
|
if (typeof props.credentials.unset !== "function") {
|
|
126979
|
-
updateRow(
|
|
127349
|
+
updateRow(target, {
|
|
126980
127350
|
message: t("clearKeyUnsupported"),
|
|
126981
127351
|
messageIsError: true
|
|
126982
127352
|
});
|
|
126983
127353
|
return;
|
|
126984
127354
|
}
|
|
126985
|
-
updateRow(
|
|
127355
|
+
updateRow(target, {
|
|
126986
127356
|
saving: true,
|
|
126987
127357
|
message: "",
|
|
126988
127358
|
messageIsError: false
|
|
@@ -126990,7 +127360,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126990
127360
|
try {
|
|
126991
127361
|
const response = await props.credentials.unset(keyRef);
|
|
126992
127362
|
if (!response.ok) throw new Error(response.error?.message ?? t("clearKeyFailed"));
|
|
126993
|
-
updateRow(
|
|
127363
|
+
updateRow(target, {
|
|
126994
127364
|
keyStatus: "missing",
|
|
126995
127365
|
keyInput: "",
|
|
126996
127366
|
testResult: void 0,
|
|
@@ -126998,12 +127368,12 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
126998
127368
|
messageIsError: false
|
|
126999
127369
|
});
|
|
127000
127370
|
} catch (cause) {
|
|
127001
|
-
updateRow(
|
|
127371
|
+
updateRow(target, {
|
|
127002
127372
|
message: cause instanceof Error ? cause.message : String(cause),
|
|
127003
127373
|
messageIsError: true
|
|
127004
127374
|
});
|
|
127005
127375
|
} finally {
|
|
127006
|
-
updateRow(
|
|
127376
|
+
updateRow(target, { saving: false });
|
|
127007
127377
|
}
|
|
127008
127378
|
};
|
|
127009
127379
|
const testResultText = (result) => {
|
|
@@ -127013,7 +127383,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127013
127383
|
if (result.reason === "unauthorized") return t("testUnauthorized");
|
|
127014
127384
|
return `${t("testFailed")}${result.message !== void 0 && result.message.length > 0 ? `: ${providerErrorMessage(result.message)}` : ""}`;
|
|
127015
127385
|
};
|
|
127016
|
-
const badgeOf = (provider) => {
|
|
127386
|
+
const badgeOf = (provider, channel) => {
|
|
127017
127387
|
if (provider === "comfyui") return {
|
|
127018
127388
|
text: t("comfyuiNoKey"),
|
|
127019
127389
|
className: "dsh-ig-badge dsh-ig-badge-neutral"
|
|
@@ -127033,7 +127403,8 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127033
127403
|
className: "dsh-ig-badge dsh-ig-badge-neutral"
|
|
127034
127404
|
};
|
|
127035
127405
|
}
|
|
127036
|
-
const
|
|
127406
|
+
const target = channel === void 0 ? provider : compatChannelRowKey(channel.id);
|
|
127407
|
+
const status = rows[target].keyStatus;
|
|
127037
127408
|
if (status === "checking") return {
|
|
127038
127409
|
text: t("badgeChecking"),
|
|
127039
127410
|
className: "dsh-ig-badge dsh-ig-badge-neutral dsh-ig-badge-checking"
|
|
@@ -127141,6 +127512,19 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127141
127512
|
};
|
|
127142
127513
|
});
|
|
127143
127514
|
};
|
|
127515
|
+
const commitCloudTimeout = () => {
|
|
127516
|
+
if (!Number.isInteger(cloudTimeoutSeconds) || cloudTimeoutSeconds < 5 || cloudTimeoutSeconds > 3600) {
|
|
127517
|
+
setCloudTimeoutSeconds((snapshot.value?.cloudTimeoutMs ?? 15e4) / 1e3);
|
|
127518
|
+
return;
|
|
127519
|
+
}
|
|
127520
|
+
const next = cloudTimeoutSeconds * 1e3;
|
|
127521
|
+
if (next === (snapshot.value?.cloudTimeoutMs ?? 15e4)) return;
|
|
127522
|
+
setCloudTimeoutMessage("");
|
|
127523
|
+
saveSetting("cloudTimeoutMs", next).catch((cause) => {
|
|
127524
|
+
setCloudTimeoutSeconds((snapshot.value?.cloudTimeoutMs ?? 15e4) / 1e3);
|
|
127525
|
+
setCloudTimeoutMessage(cause instanceof Error ? cause.message : String(cause));
|
|
127526
|
+
});
|
|
127527
|
+
};
|
|
127144
127528
|
/** Workspace checkbox persists immediately, like every other toggle on this card. */
|
|
127145
127529
|
const toggleSaveToWorkspace = (next) => {
|
|
127146
127530
|
setSaveToWorkspace(next);
|
|
@@ -127177,31 +127561,57 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127177
127561
|
setUiMessageIsError(true);
|
|
127178
127562
|
});
|
|
127179
127563
|
};
|
|
127180
|
-
const renderCloudBody = (provider) => {
|
|
127181
|
-
const
|
|
127564
|
+
const renderCloudBody = (provider, channel) => {
|
|
127565
|
+
const target = channel === void 0 ? provider : compatChannelRowKey(channel.id);
|
|
127566
|
+
const row = rows[target];
|
|
127567
|
+
const update = (patch) => {
|
|
127568
|
+
updateRow(target, patch);
|
|
127569
|
+
};
|
|
127570
|
+
const modelListId = `dsh-ig-${target.replace(/[^A-Za-z0-9_-]/g, "-")}-model-options`;
|
|
127182
127571
|
const officialEditFormat = provider === "openai-compat" ? compatEditFormat({
|
|
127183
127572
|
openaiCompatBaseURL: row.baseURL,
|
|
127184
127573
|
openaiCompatModel: row.editModel.trim() || row.model
|
|
127185
127574
|
}) : "multipart";
|
|
127186
127575
|
const automaticEditFormat = officialEditFormat !== "multipart";
|
|
127187
127576
|
const editFormat = automaticEditFormat ? officialEditFormat : row.editFormat;
|
|
127188
|
-
const keyRef = cloudCredentialRef(provider) ?? "";
|
|
127577
|
+
const keyRef = channel === void 0 ? cloudCredentialRef(provider) ?? "" : channel.keyRef;
|
|
127189
127578
|
const keyReadOnly = row.keyInfo?.writable === false;
|
|
127190
127579
|
const keyUnavailable = !credentialsAvailable();
|
|
127580
|
+
const providerLabel = provider === "openai-compat" && row.label.trim().length > 0 ? row.label.trim() : providerLabels[provider];
|
|
127581
|
+
const compatModelChoices = provider === "openai-compat" ? resolveOpenAICompatModels({
|
|
127582
|
+
openaiCompatModel: row.model,
|
|
127583
|
+
openaiCompatModels: [...row.models, ...row.modelOptions]
|
|
127584
|
+
}) : [];
|
|
127191
127585
|
return (0, react_jsx_runtime.jsx)("div", {
|
|
127192
127586
|
className: "dsh-ig-provider-body",
|
|
127193
127587
|
children: (0, react_jsx_runtime.jsxs)("form", {
|
|
127194
127588
|
onSubmit: (event) => {
|
|
127195
127589
|
event.preventDefault();
|
|
127196
|
-
saveProviderRow(provider);
|
|
127590
|
+
saveProviderRow(provider, channel);
|
|
127197
127591
|
},
|
|
127198
127592
|
children: [
|
|
127593
|
+
provider === "openai-compat" ? (0, react_jsx_runtime.jsxs)("label", {
|
|
127594
|
+
className: "dsh-ig-field",
|
|
127595
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
127596
|
+
className: "dsh-ig-label",
|
|
127597
|
+
children: t("channelName")
|
|
127598
|
+
}), (0, react_jsx_runtime.jsx)("input", {
|
|
127599
|
+
className: "dsh-ig-input",
|
|
127600
|
+
value: row.label,
|
|
127601
|
+
onChange: (event) => {
|
|
127602
|
+
update({ label: event.target.value });
|
|
127603
|
+
},
|
|
127604
|
+
placeholder: providerLabels[provider],
|
|
127605
|
+
required: channel !== void 0,
|
|
127606
|
+
disabled: !settingsWritable
|
|
127607
|
+
})]
|
|
127608
|
+
}) : null,
|
|
127199
127609
|
(0, react_jsx_runtime.jsxs)("label", {
|
|
127200
127610
|
className: "dsh-ig-field",
|
|
127201
127611
|
children: [
|
|
127202
127612
|
(0, react_jsx_runtime.jsx)("span", {
|
|
127203
127613
|
className: "dsh-ig-label",
|
|
127204
|
-
children: t("apiKeyLabel", { provider:
|
|
127614
|
+
children: t("apiKeyLabel", { provider: providerLabel })
|
|
127205
127615
|
}),
|
|
127206
127616
|
(0, react_jsx_runtime.jsx)("input", {
|
|
127207
127617
|
className: "dsh-ig-input",
|
|
@@ -127209,7 +127619,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127209
127619
|
autoComplete: "off",
|
|
127210
127620
|
value: row.keyInput,
|
|
127211
127621
|
onChange: (event) => {
|
|
127212
|
-
|
|
127622
|
+
update({ keyInput: event.target.value });
|
|
127213
127623
|
},
|
|
127214
127624
|
placeholder: row.keyStatus === "configured" ? t("apiKeyPlaceholder") : "",
|
|
127215
127625
|
disabled: !settingsWritable || keyReadOnly || keyUnavailable
|
|
@@ -127234,7 +127644,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127234
127644
|
type: "url",
|
|
127235
127645
|
value: row.baseURL,
|
|
127236
127646
|
onChange: (event) => {
|
|
127237
|
-
|
|
127647
|
+
update({ baseURL: event.target.value });
|
|
127238
127648
|
},
|
|
127239
127649
|
required: true,
|
|
127240
127650
|
disabled: !settingsWritable
|
|
@@ -127243,7 +127653,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127243
127653
|
className: "dsh-ig-btn-reset",
|
|
127244
127654
|
title: t("resetTitle"),
|
|
127245
127655
|
onClick: () => {
|
|
127246
|
-
|
|
127656
|
+
update({ baseURL: DEFAULT_BASE_URLS[provider] });
|
|
127247
127657
|
},
|
|
127248
127658
|
disabled: !settingsWritable,
|
|
127249
127659
|
children: t("reset")
|
|
@@ -127264,7 +127674,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127264
127674
|
className: "dsh-ig-input",
|
|
127265
127675
|
value: row.googleNative ? "native" : "interactions",
|
|
127266
127676
|
onChange: (event) => {
|
|
127267
|
-
|
|
127677
|
+
update({ googleNative: event.target.value === "native" });
|
|
127268
127678
|
},
|
|
127269
127679
|
disabled: !settingsWritable,
|
|
127270
127680
|
children: [(0, react_jsx_runtime.jsx)("option", {
|
|
@@ -127281,7 +127691,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127281
127691
|
children: [
|
|
127282
127692
|
(0, react_jsx_runtime.jsx)("span", {
|
|
127283
127693
|
className: "dsh-ig-label",
|
|
127284
|
-
children: t("model")
|
|
127694
|
+
children: t(provider === "openai-compat" ? "defaultModel" : "model")
|
|
127285
127695
|
}),
|
|
127286
127696
|
modelPullSupported(provider) ? (0, react_jsx_runtime.jsxs)("div", {
|
|
127287
127697
|
className: "dsh-ig-input-group",
|
|
@@ -127290,14 +127700,20 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127290
127700
|
className: "dsh-ig-input",
|
|
127291
127701
|
value: row.model,
|
|
127292
127702
|
onChange: (event) => {
|
|
127293
|
-
|
|
127703
|
+
update({ model: event.target.value });
|
|
127294
127704
|
},
|
|
127295
|
-
|
|
127705
|
+
onBlur: () => {
|
|
127706
|
+
if (provider === "openai-compat") update({ models: resolveOpenAICompatModels({
|
|
127707
|
+
openaiCompatModel: row.model,
|
|
127708
|
+
openaiCompatModels: row.models
|
|
127709
|
+
}) });
|
|
127710
|
+
},
|
|
127711
|
+
list: modelListId,
|
|
127296
127712
|
required: provider !== "openai-compat",
|
|
127297
127713
|
disabled: !settingsWritable
|
|
127298
127714
|
}),
|
|
127299
127715
|
(0, react_jsx_runtime.jsx)("datalist", {
|
|
127300
|
-
id:
|
|
127716
|
+
id: modelListId,
|
|
127301
127717
|
children: row.modelOptions.map((id) => (0, react_jsx_runtime.jsx)("option", { value: id }, id))
|
|
127302
127718
|
}),
|
|
127303
127719
|
(0, react_jsx_runtime.jsx)("button", {
|
|
@@ -127305,7 +127721,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127305
127721
|
className: "dsh-ig-btn-secondary",
|
|
127306
127722
|
disabled: row.fetchingModels || row.saving || !settingsWritable,
|
|
127307
127723
|
onClick: () => {
|
|
127308
|
-
fetchProviderModels(provider);
|
|
127724
|
+
fetchProviderModels(provider, channel);
|
|
127309
127725
|
},
|
|
127310
127726
|
children: row.fetchingModels ? t("fetchingModels") : t("fetchModels")
|
|
127311
127727
|
})
|
|
@@ -127314,7 +127730,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127314
127730
|
className: "dsh-ig-input",
|
|
127315
127731
|
value: row.model,
|
|
127316
127732
|
onChange: (event) => {
|
|
127317
|
-
|
|
127733
|
+
update({ model: event.target.value });
|
|
127318
127734
|
},
|
|
127319
127735
|
required: true,
|
|
127320
127736
|
disabled: !settingsWritable
|
|
@@ -127329,6 +127745,52 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127329
127745
|
}) : null
|
|
127330
127746
|
]
|
|
127331
127747
|
}),
|
|
127748
|
+
provider === "openai-compat" && compatModelChoices.length > 0 ? (0, react_jsx_runtime.jsxs)("div", {
|
|
127749
|
+
className: "dsh-ig-field",
|
|
127750
|
+
children: [
|
|
127751
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
127752
|
+
className: "dsh-ig-label",
|
|
127753
|
+
children: t("availableModels")
|
|
127754
|
+
}),
|
|
127755
|
+
(0, react_jsx_runtime.jsx)("div", {
|
|
127756
|
+
className: "dsh-ig-model-picker",
|
|
127757
|
+
children: compatModelChoices.map((id) => {
|
|
127758
|
+
const isDefault = row.model.trim() === id;
|
|
127759
|
+
const checked = isDefault || row.models.includes(id);
|
|
127760
|
+
return (0, react_jsx_runtime.jsxs)("label", {
|
|
127761
|
+
className: "dsh-ig-check-row",
|
|
127762
|
+
title: id,
|
|
127763
|
+
children: [
|
|
127764
|
+
(0, react_jsx_runtime.jsx)("input", {
|
|
127765
|
+
type: "checkbox",
|
|
127766
|
+
checked,
|
|
127767
|
+
disabled: !settingsWritable || isDefault,
|
|
127768
|
+
onChange: (event) => {
|
|
127769
|
+
const models = event.target.checked ? [...row.models, id] : row.models.filter((model) => model !== id);
|
|
127770
|
+
update({ models: resolveOpenAICompatModels({
|
|
127771
|
+
openaiCompatModel: row.model,
|
|
127772
|
+
openaiCompatModels: models
|
|
127773
|
+
}) });
|
|
127774
|
+
}
|
|
127775
|
+
}),
|
|
127776
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
127777
|
+
className: "dsh-ig-model-option",
|
|
127778
|
+
children: id
|
|
127779
|
+
}),
|
|
127780
|
+
isDefault ? (0, react_jsx_runtime.jsx)("span", {
|
|
127781
|
+
className: "dsh-ig-model-default",
|
|
127782
|
+
children: t("defaultModelTag")
|
|
127783
|
+
}) : null
|
|
127784
|
+
]
|
|
127785
|
+
}, id);
|
|
127786
|
+
})
|
|
127787
|
+
}),
|
|
127788
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
127789
|
+
className: "dsh-ig-hint",
|
|
127790
|
+
children: t("availableModelsHint")
|
|
127791
|
+
})
|
|
127792
|
+
]
|
|
127793
|
+
}) : null,
|
|
127332
127794
|
provider === "openai-compat" ? (0, react_jsx_runtime.jsxs)("label", {
|
|
127333
127795
|
className: "dsh-ig-field",
|
|
127334
127796
|
children: [
|
|
@@ -127340,9 +127802,9 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127340
127802
|
className: "dsh-ig-input",
|
|
127341
127803
|
value: row.editModel,
|
|
127342
127804
|
onChange: (event) => {
|
|
127343
|
-
|
|
127805
|
+
update({ editModel: event.target.value });
|
|
127344
127806
|
},
|
|
127345
|
-
list:
|
|
127807
|
+
list: modelListId,
|
|
127346
127808
|
disabled: !settingsWritable
|
|
127347
127809
|
}),
|
|
127348
127810
|
(0, react_jsx_runtime.jsx)("span", {
|
|
@@ -127362,7 +127824,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127362
127824
|
className: "dsh-ig-input",
|
|
127363
127825
|
value: automaticEditFormat ? "__official__" : row.editFormat,
|
|
127364
127826
|
onChange: (event) => {
|
|
127365
|
-
|
|
127827
|
+
update({ editFormat: parseEditFormat(event.target.value) });
|
|
127366
127828
|
},
|
|
127367
127829
|
disabled: !settingsWritable || automaticEditFormat,
|
|
127368
127830
|
children: [
|
|
@@ -127406,7 +127868,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127406
127868
|
className: "dsh-ig-input",
|
|
127407
127869
|
value: row.outputFormat,
|
|
127408
127870
|
onChange: (event) => {
|
|
127409
|
-
|
|
127871
|
+
update({ outputFormat: event.target.value === "png" ? "png" : "jpeg" });
|
|
127410
127872
|
},
|
|
127411
127873
|
disabled: !settingsWritable,
|
|
127412
127874
|
children: [(0, react_jsx_runtime.jsx)("option", {
|
|
@@ -127434,7 +127896,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127434
127896
|
className: "dsh-ig-input",
|
|
127435
127897
|
value: row.watermark ? "on" : "off",
|
|
127436
127898
|
onChange: (event) => {
|
|
127437
|
-
|
|
127899
|
+
update({ watermark: event.target.value === "on" });
|
|
127438
127900
|
},
|
|
127439
127901
|
disabled: !settingsWritable,
|
|
127440
127902
|
children: [(0, react_jsx_runtime.jsx)("option", {
|
|
@@ -127462,7 +127924,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127462
127924
|
className: "dsh-ig-input",
|
|
127463
127925
|
value: row.background,
|
|
127464
127926
|
onChange: (event) => {
|
|
127465
|
-
|
|
127927
|
+
update({ background: event.target.value === "transparent" ? "transparent" : "opaque" });
|
|
127466
127928
|
},
|
|
127467
127929
|
disabled: !settingsWritable,
|
|
127468
127930
|
children: [(0, react_jsx_runtime.jsx)("option", {
|
|
@@ -127491,7 +127953,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127491
127953
|
className: "dsh-ig-input dsh-ig-textarea",
|
|
127492
127954
|
value: row.sizeTableText,
|
|
127493
127955
|
onChange: (event) => {
|
|
127494
|
-
|
|
127956
|
+
update({ sizeTableText: event.target.value });
|
|
127495
127957
|
},
|
|
127496
127958
|
rows: 3,
|
|
127497
127959
|
disabled: !settingsWritable
|
|
@@ -127514,7 +127976,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127514
127976
|
className: "dsh-ig-input",
|
|
127515
127977
|
value: row.generationQuality,
|
|
127516
127978
|
onChange: (event) => {
|
|
127517
|
-
|
|
127979
|
+
update({ generationQuality: event.target.value });
|
|
127518
127980
|
},
|
|
127519
127981
|
placeholder: "high",
|
|
127520
127982
|
disabled: !settingsWritable
|
|
@@ -127534,7 +127996,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127534
127996
|
className: "dsh-ig-input",
|
|
127535
127997
|
value: row.qualityOptionsText,
|
|
127536
127998
|
onChange: (event) => {
|
|
127537
|
-
|
|
127999
|
+
update({ qualityOptionsText: event.target.value });
|
|
127538
128000
|
},
|
|
127539
128001
|
disabled: !settingsWritable
|
|
127540
128002
|
})]
|
|
@@ -127550,7 +128012,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127550
128012
|
className: "dsh-ig-input dsh-ig-textarea",
|
|
127551
128013
|
value: row.generateExtraText,
|
|
127552
128014
|
onChange: (event) => {
|
|
127553
|
-
|
|
128015
|
+
update({ generateExtraText: event.target.value });
|
|
127554
128016
|
},
|
|
127555
128017
|
placeholder: "{\"watermark\":false}",
|
|
127556
128018
|
rows: 2,
|
|
@@ -127572,7 +128034,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127572
128034
|
className: "dsh-ig-input",
|
|
127573
128035
|
value: row.editSizeMode,
|
|
127574
128036
|
onChange: (event) => {
|
|
127575
|
-
|
|
128037
|
+
update({ editSizeMode: event.target.value === "selected" ? "selected" : "auto" });
|
|
127576
128038
|
},
|
|
127577
128039
|
disabled: !settingsWritable,
|
|
127578
128040
|
children: [(0, react_jsx_runtime.jsx)("option", {
|
|
@@ -127594,7 +128056,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127594
128056
|
className: "dsh-ig-input dsh-ig-textarea",
|
|
127595
128057
|
value: row.editExtraText,
|
|
127596
128058
|
onChange: (event) => {
|
|
127597
|
-
|
|
128059
|
+
update({ editExtraText: event.target.value });
|
|
127598
128060
|
},
|
|
127599
128061
|
placeholder: t("editExtraPlaceholder"),
|
|
127600
128062
|
rows: 2,
|
|
@@ -127620,7 +128082,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127620
128082
|
className: "dsh-ig-btn-secondary",
|
|
127621
128083
|
disabled: row.testing || row.saving,
|
|
127622
128084
|
onClick: () => {
|
|
127623
|
-
testConnection(provider);
|
|
128085
|
+
testConnection(provider, channel);
|
|
127624
128086
|
},
|
|
127625
128087
|
children: row.testing ? t("testing") : t("testConnection")
|
|
127626
128088
|
}),
|
|
@@ -127629,7 +128091,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127629
128091
|
className: "dsh-ig-btn-secondary dsh-ig-btn-danger",
|
|
127630
128092
|
disabled: row.saving,
|
|
127631
128093
|
onClick: () => {
|
|
127632
|
-
clearProviderKey(provider);
|
|
128094
|
+
clearProviderKey(provider, channel);
|
|
127633
128095
|
},
|
|
127634
128096
|
children: t("clearKey")
|
|
127635
128097
|
}) : null,
|
|
@@ -127947,47 +128409,115 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
127947
128409
|
const renderProviderRow = (provider) => {
|
|
127948
128410
|
const row = rows[provider];
|
|
127949
128411
|
const badge = badgeOf(provider);
|
|
128412
|
+
const label = provider === "openai-compat" && row.label.trim().length > 0 ? row.label.trim() : providerLabels[provider];
|
|
127950
128413
|
return (0, react_jsx_runtime.jsxs)("div", {
|
|
127951
128414
|
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
|
-
|
|
128415
|
+
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
128416
|
+
className: "dsh-ig-provider-head-row",
|
|
128417
|
+
children: [provider === "openai-compat" ? (0, react_jsx_runtime.jsx)("button", {
|
|
128418
|
+
type: "button",
|
|
128419
|
+
className: "dsh-ig-btn-secondary dsh-ig-channel-add",
|
|
128420
|
+
title: t("addCompatChannel"),
|
|
128421
|
+
"aria-label": t("addCompatChannel"),
|
|
128422
|
+
onClick: addCompatChannel,
|
|
128423
|
+
disabled: !settingsWritable,
|
|
128424
|
+
children: "+"
|
|
128425
|
+
}) : null, (0, react_jsx_runtime.jsxs)("button", {
|
|
128426
|
+
type: "button",
|
|
128427
|
+
className: "dsh-ig-provider-head",
|
|
128428
|
+
"aria-expanded": row.expanded,
|
|
128429
|
+
onClick: () => {
|
|
128430
|
+
updateRow(provider, { expanded: !row.expanded });
|
|
128431
|
+
},
|
|
128432
|
+
children: [
|
|
128433
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
128434
|
+
className: "dsh-ig-provider-name",
|
|
128435
|
+
children: label
|
|
128436
|
+
}),
|
|
128437
|
+
(0, react_jsx_runtime.jsxs)("span", {
|
|
128438
|
+
className: badge.className,
|
|
128439
|
+
title: badge.text,
|
|
128440
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
128441
|
+
className: "dsh-ig-badge-dot",
|
|
128442
|
+
"aria-hidden": "true"
|
|
128443
|
+
}), badge.text]
|
|
128444
|
+
}),
|
|
128445
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
128446
|
+
className: `dsh-ig-provider-chevron ${row.expanded ? "dsh-ig-provider-chevron-open" : ""}`,
|
|
128447
|
+
"aria-hidden": "true",
|
|
128448
|
+
children: (0, react_jsx_runtime.jsx)("svg", {
|
|
128449
|
+
width: "12",
|
|
128450
|
+
height: "12",
|
|
128451
|
+
viewBox: "0 0 16 16",
|
|
128452
|
+
fill: "none",
|
|
128453
|
+
stroke: "currentColor",
|
|
128454
|
+
strokeWidth: "2",
|
|
128455
|
+
strokeLinecap: "round",
|
|
128456
|
+
strokeLinejoin: "round",
|
|
128457
|
+
children: (0, react_jsx_runtime.jsx)("path", { d: "M4 6l4 4 4-4" })
|
|
128458
|
+
})
|
|
127985
128459
|
})
|
|
127986
|
-
|
|
127987
|
-
]
|
|
128460
|
+
]
|
|
128461
|
+
})]
|
|
127988
128462
|
}), row.expanded ? provider === "comfyui" ? renderComfyUIBody() : isSubscriptionProvider(provider) ? renderSubscriptionBody(provider) : renderCloudBody(provider) : null]
|
|
127989
128463
|
}, provider);
|
|
127990
128464
|
};
|
|
128465
|
+
const renderCompatChannelRow = (channel) => {
|
|
128466
|
+
const target = compatChannelRowKey(channel.id);
|
|
128467
|
+
const row = rows[target];
|
|
128468
|
+
const badge = badgeOf("openai-compat", channel);
|
|
128469
|
+
return (0, react_jsx_runtime.jsxs)("div", {
|
|
128470
|
+
className: "dsh-ig-provider-row dsh-ig-compat-channel-row",
|
|
128471
|
+
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
128472
|
+
className: "dsh-ig-provider-head-row",
|
|
128473
|
+
children: [(0, react_jsx_runtime.jsxs)("button", {
|
|
128474
|
+
type: "button",
|
|
128475
|
+
className: "dsh-ig-provider-head",
|
|
128476
|
+
"aria-expanded": row.expanded,
|
|
128477
|
+
onClick: () => {
|
|
128478
|
+
updateRow(target, { expanded: !row.expanded });
|
|
128479
|
+
},
|
|
128480
|
+
children: [
|
|
128481
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
128482
|
+
className: "dsh-ig-provider-name",
|
|
128483
|
+
children: channel.label
|
|
128484
|
+
}),
|
|
128485
|
+
(0, react_jsx_runtime.jsxs)("span", {
|
|
128486
|
+
className: badge.className,
|
|
128487
|
+
title: badge.text,
|
|
128488
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
128489
|
+
className: "dsh-ig-badge-dot",
|
|
128490
|
+
"aria-hidden": "true"
|
|
128491
|
+
}), badge.text]
|
|
128492
|
+
}),
|
|
128493
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
128494
|
+
className: `dsh-ig-provider-chevron ${row.expanded ? "dsh-ig-provider-chevron-open" : ""}`,
|
|
128495
|
+
"aria-hidden": "true",
|
|
128496
|
+
children: (0, react_jsx_runtime.jsx)("svg", {
|
|
128497
|
+
width: "12",
|
|
128498
|
+
height: "12",
|
|
128499
|
+
viewBox: "0 0 16 16",
|
|
128500
|
+
fill: "none",
|
|
128501
|
+
stroke: "currentColor",
|
|
128502
|
+
strokeWidth: "2",
|
|
128503
|
+
strokeLinecap: "round",
|
|
128504
|
+
strokeLinejoin: "round",
|
|
128505
|
+
children: (0, react_jsx_runtime.jsx)("path", { d: "M4 6l4 4 4-4" })
|
|
128506
|
+
})
|
|
128507
|
+
})
|
|
128508
|
+
]
|
|
128509
|
+
}), (0, react_jsx_runtime.jsx)("button", {
|
|
128510
|
+
type: "button",
|
|
128511
|
+
className: "dsh-ig-btn-secondary dsh-ig-btn-danger",
|
|
128512
|
+
disabled: row.saving || !settingsWritable,
|
|
128513
|
+
onClick: () => {
|
|
128514
|
+
removeCompatChannel(channel);
|
|
128515
|
+
},
|
|
128516
|
+
children: t("removeChannel")
|
|
128517
|
+
})]
|
|
128518
|
+
}), row.expanded ? renderCloudBody("openai-compat", channel) : null]
|
|
128519
|
+
}, target);
|
|
128520
|
+
};
|
|
127991
128521
|
return (0, react_jsx_runtime.jsxs)("li", {
|
|
127992
128522
|
className: "dsh-ig-card",
|
|
127993
128523
|
children: [(0, react_jsx_runtime.jsx)("div", {
|
|
@@ -128045,9 +128575,46 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
128045
128575
|
}) : null
|
|
128046
128576
|
]
|
|
128047
128577
|
}),
|
|
128578
|
+
(0, react_jsx_runtime.jsxs)("label", {
|
|
128579
|
+
className: "dsh-ig-field",
|
|
128580
|
+
children: [
|
|
128581
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
128582
|
+
className: "dsh-ig-label",
|
|
128583
|
+
children: t("cloudTimeout")
|
|
128584
|
+
}),
|
|
128585
|
+
(0, react_jsx_runtime.jsx)("input", {
|
|
128586
|
+
className: "dsh-ig-input",
|
|
128587
|
+
type: "number",
|
|
128588
|
+
min: "5",
|
|
128589
|
+
max: "3600",
|
|
128590
|
+
step: "1",
|
|
128591
|
+
value: cloudTimeoutSeconds,
|
|
128592
|
+
onChange: (event) => {
|
|
128593
|
+
setCloudTimeoutSeconds(Number(event.target.value));
|
|
128594
|
+
},
|
|
128595
|
+
onBlur: () => {
|
|
128596
|
+
commitCloudTimeout();
|
|
128597
|
+
},
|
|
128598
|
+
onKeyDown: (event) => {
|
|
128599
|
+
if (event.key === "Enter") commitCloudTimeout();
|
|
128600
|
+
},
|
|
128601
|
+
required: true,
|
|
128602
|
+
disabled: !settingsWritable
|
|
128603
|
+
}),
|
|
128604
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
128605
|
+
className: "dsh-ig-hint",
|
|
128606
|
+
children: t("cloudTimeoutHint")
|
|
128607
|
+
}),
|
|
128608
|
+
cloudTimeoutMessage.length > 0 ? (0, react_jsx_runtime.jsx)("span", {
|
|
128609
|
+
className: "dsh-ig-status dsh-ig-status-error",
|
|
128610
|
+
role: "status",
|
|
128611
|
+
children: cloudTimeoutMessage
|
|
128612
|
+
}) : null
|
|
128613
|
+
]
|
|
128614
|
+
}),
|
|
128048
128615
|
(0, react_jsx_runtime.jsx)("div", {
|
|
128049
128616
|
className: "dsh-ig-providers",
|
|
128050
|
-
children: IMAGE_PROVIDERS.
|
|
128617
|
+
children: IMAGE_PROVIDERS.flatMap((provider) => [renderProviderRow(provider), ...provider === "openai-compat" ? compatChannels.map((channel) => renderCompatChannelRow(channel)) : []])
|
|
128051
128618
|
}),
|
|
128052
128619
|
(0, react_jsx_runtime.jsxs)("div", {
|
|
128053
128620
|
className: "dsh-ig-section",
|
|
@@ -128212,6 +128779,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
128212
128779
|
const activeResult = selectedRevision !== void 0 ? {
|
|
128213
128780
|
prompt: selectedRevision.prompt,
|
|
128214
128781
|
provider: selectedRevision.provider,
|
|
128782
|
+
...selectedRevision.channel === void 0 ? {} : { channel: selectedRevision.channel },
|
|
128215
128783
|
model: selectedRevision.model,
|
|
128216
128784
|
output: selectedRevision.output,
|
|
128217
128785
|
createdAt: selectedRevision.createdAt,
|
|
@@ -128242,6 +128810,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
128242
128810
|
attachment: result.attachment,
|
|
128243
128811
|
prompt: result.prompt,
|
|
128244
128812
|
provider: result.provider,
|
|
128813
|
+
...result.channel === void 0 ? {} : { channel: result.channel },
|
|
128245
128814
|
model: result.model,
|
|
128246
128815
|
output: result.output,
|
|
128247
128816
|
...result.savedTo ? { savedTo: result.savedTo } : {},
|
|
@@ -128380,6 +128949,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
128380
128949
|
attachment: payload.attachment,
|
|
128381
128950
|
prompt: payload.prompt,
|
|
128382
128951
|
provider: payload.provider,
|
|
128952
|
+
...payload.channel === void 0 ? {} : { channel: payload.channel },
|
|
128383
128953
|
model: payload.model,
|
|
128384
128954
|
output: payload.output,
|
|
128385
128955
|
createdAt: payload.createdAt,
|
|
@@ -128394,6 +128964,7 @@ body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a
|
|
|
128394
128964
|
attachment: revision.attachment,
|
|
128395
128965
|
prompt: revision.prompt,
|
|
128396
128966
|
provider: revision.provider,
|
|
128967
|
+
...revision.channel === void 0 ? {} : { channel: revision.channel },
|
|
128397
128968
|
model: revision.model,
|
|
128398
128969
|
createdAt: revision.createdAt,
|
|
128399
128970
|
aspectRatio: revision.ratio,
|