dsh-modellix 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +56 -0
- package/README.md +101 -169
- package/README.zh-CN.md +99 -167
- package/docs/assets/chat-media-generation-en.webp +0 -0
- package/docs/assets/chat-media-generation-zh.webp +0 -0
- package/docs/assets/design-results-drawer-en.webp +0 -0
- package/docs/assets/design-results-drawer-zh.webp +0 -0
- package/docs/assets/llm-model-selector-en.webp +0 -0
- package/docs/assets/llm-model-selector-zh.webp +0 -0
- package/docs/assets/media-players-en.webp +0 -0
- package/docs/assets/media-players-zh.webp +0 -0
- package/docs/assets/settings-ready-en.webp +0 -0
- package/docs/assets/settings-ready-zh.webp +0 -0
- package/docs/assets/web-tools-auto-en.webp +0 -0
- package/docs/assets/web-tools-auto-zh.webp +0 -0
- package/docs/en-US/LOCAL_USAGE.md +17 -15
- package/docs/en-US/RELEASE_CHECKLIST.md +270 -0
- package/docs/en-US/USER_GUIDE.md +183 -401
- package/docs/zh-CN/LOCAL_USAGE.md +17 -15
- package/docs/zh-CN/RELEASE_CHECKLIST.md +270 -0
- package/docs/zh-CN/USER_GUIDE.md +182 -400
- package/lib/client.d.ts +16 -2
- package/lib/client.js +1308 -466
- package/lib/client.js.map +1 -1
- package/lib/index.d.ts +159 -109
- package/lib/index.js +995 -192
- package/lib/index.js.map +1 -1
- package/package.json +7 -2
- package/docs/assets/credential-recovery.webp +0 -0
- package/docs/assets/design-desktop.webp +0 -0
- package/docs/assets/design-mobile-en.webp +0 -0
- package/docs/assets/design-proposal.webp +0 -0
- package/docs/assets/design-results-media.webp +0 -0
- package/docs/assets/llm-model-selector.webp +0 -0
- package/docs/assets/onboarding-defaults.webp +0 -0
- package/docs/assets/settings-ready.webp +0 -0
- package/docs/assets/web-tools.webp +0 -0
package/lib/client.js
CHANGED
|
@@ -342,6 +342,8 @@ function parseModel(value) {
|
|
|
342
342
|
"audio",
|
|
343
343
|
"unknown"
|
|
344
344
|
], "model.kind"),
|
|
345
|
+
...model.taskType === void 0 ? {} : { taskType: readable(model.taskType, "model.taskType", 64) },
|
|
346
|
+
...model.description === void 0 ? {} : { description: readable(model.description, "model.description", MAX_SHORT_TEXT) },
|
|
345
347
|
featured: boolean(model.featured, "model.featured"),
|
|
346
348
|
available: boolean(model.available, "model.available"),
|
|
347
349
|
unavailableReason: model.unavailableReason === null ? null : oneOf(model.unavailableReason, DESIGN_MODEL_UNAVAILABLE_CODES, "model.unavailableReason")
|
|
@@ -440,7 +442,7 @@ function parseJob(value) {
|
|
|
440
442
|
createdAt: isoTimestamp(job.createdAt, "job.createdAt"),
|
|
441
443
|
updatedAt: isoTimestamp(job.updatedAt, "job.updatedAt"),
|
|
442
444
|
resources: array(job.resources, "job.resources", MAX_RESOURCES).map(parseResource),
|
|
443
|
-
diagnostic: job.diagnostic === null ? null : parseDiagnostic(job.diagnostic)
|
|
445
|
+
diagnostic: job.diagnostic === null ? null : parseDiagnostic$1(job.diagnostic)
|
|
444
446
|
};
|
|
445
447
|
}
|
|
446
448
|
function parseResource(value) {
|
|
@@ -457,7 +459,7 @@ function parseResource(value) {
|
|
|
457
459
|
expiresAt: resource.expiresAt === null ? null : isoTimestamp(resource.expiresAt, "resource.expiresAt")
|
|
458
460
|
};
|
|
459
461
|
}
|
|
460
|
-
function parseDiagnostic(value) {
|
|
462
|
+
function parseDiagnostic$1(value) {
|
|
461
463
|
const diagnostic = object(value, "diagnostic");
|
|
462
464
|
if (Object.hasOwn(diagnostic, "message")) throw new ModellixClientContractError("diagnostic must use a stable code instead of Host prose");
|
|
463
465
|
return {
|
|
@@ -911,7 +913,7 @@ const MODAL_DIALOG_SELECTOR = "[role=\"dialog\"][aria-modal=\"true\"]";
|
|
|
911
913
|
* therefore uses only the ARIA modal contract and a marker owned by this
|
|
912
914
|
* plugin; it does not depend on host classes or DOM structure.
|
|
913
915
|
*/
|
|
914
|
-
function useExternalDialogGate(requestedOpen) {
|
|
916
|
+
function useExternalDialogGate(requestedOpen, externalDialogOwner) {
|
|
915
917
|
const [decision, setDecision] = (0, react.useState)({
|
|
916
918
|
requestedOpen: false,
|
|
917
919
|
allowed: false
|
|
@@ -931,7 +933,7 @@ function useExternalDialogGate(requestedOpen) {
|
|
|
931
933
|
const reconcile = () => {
|
|
932
934
|
reconciliationQueued = false;
|
|
933
935
|
if (disposed) return;
|
|
934
|
-
const allowed = !hasVisibleExternalDialog(ownerDocument);
|
|
936
|
+
const allowed = !hasVisibleExternalDialog(ownerDocument, resolveExternalDialogOwner(externalDialogOwner));
|
|
935
937
|
setDecision((current) => current.requestedOpen && current.allowed === allowed ? current : {
|
|
936
938
|
requestedOpen: true,
|
|
937
939
|
allowed
|
|
@@ -962,12 +964,12 @@ function useExternalDialogGate(requestedOpen) {
|
|
|
962
964
|
disposed = true;
|
|
963
965
|
observer?.disconnect();
|
|
964
966
|
};
|
|
965
|
-
}, [requestedOpen]);
|
|
967
|
+
}, [externalDialogOwner, requestedOpen]);
|
|
966
968
|
return requestedOpen && decision.requestedOpen && decision.allowed;
|
|
967
969
|
}
|
|
968
970
|
/** Adds the focus behavior intentionally absent from the public Modal primitive. */
|
|
969
971
|
function useDialogA11y(options) {
|
|
970
|
-
const { open, container, initialFocusSelector, mandatory, onEscape } = options;
|
|
972
|
+
const { open, container, externalDialogOwner, initialFocusSelector, mandatory, onEscape } = options;
|
|
971
973
|
const onEscapeRef = (0, react.useRef)(onEscape);
|
|
972
974
|
const restoreTargetRef = (0, react.useRef)(null);
|
|
973
975
|
onEscapeRef.current = onEscape;
|
|
@@ -1019,13 +1021,14 @@ function useDialogA11y(options) {
|
|
|
1019
1021
|
document.removeEventListener("keydown", onKeyDown, true);
|
|
1020
1022
|
unlockInert();
|
|
1021
1023
|
unlockScroll();
|
|
1022
|
-
if (!hasVisibleExternalDialog(document)) {
|
|
1024
|
+
if (!hasVisibleExternalDialog(document, resolveExternalDialogOwner(externalDialogOwner))) {
|
|
1023
1025
|
restoreFocus(restoreTargetRef.current, dialogRoot, appRoot);
|
|
1024
1026
|
restoreTargetRef.current = null;
|
|
1025
1027
|
}
|
|
1026
1028
|
};
|
|
1027
1029
|
}, [
|
|
1028
1030
|
container,
|
|
1031
|
+
externalDialogOwner,
|
|
1029
1032
|
initialFocusSelector,
|
|
1030
1033
|
mandatory,
|
|
1031
1034
|
open
|
|
@@ -1111,8 +1114,11 @@ function restoreFocus(previous, dialog, appRoot) {
|
|
|
1111
1114
|
if (fallback !== void 0 && focus(fallback)) return;
|
|
1112
1115
|
}
|
|
1113
1116
|
}
|
|
1114
|
-
function hasVisibleExternalDialog(ownerDocument) {
|
|
1115
|
-
return [...ownerDocument.querySelectorAll(MODAL_DIALOG_SELECTOR)].some((candidate) => candidate.querySelector(MODELLIX_DIALOG_SENTINEL) === null && isVisibleDialog(candidate));
|
|
1117
|
+
function hasVisibleExternalDialog(ownerDocument, allowedOwner = null) {
|
|
1118
|
+
return [...ownerDocument.querySelectorAll(MODAL_DIALOG_SELECTOR)].some((candidate) => candidate !== allowedOwner && candidate.querySelector(MODELLIX_DIALOG_SENTINEL) === null && isVisibleDialog(candidate));
|
|
1119
|
+
}
|
|
1120
|
+
function resolveExternalDialogOwner(owner) {
|
|
1121
|
+
return owner?.current?.closest(MODAL_DIALOG_SELECTOR) ?? null;
|
|
1116
1122
|
}
|
|
1117
1123
|
function isVisibleDialog(candidate) {
|
|
1118
1124
|
if (candidate.tagName === "DIALOG" && !candidate.hasAttribute("open")) return false;
|
|
@@ -1276,7 +1282,7 @@ function CredentialStatus({ configured, source, verification, t }) {
|
|
|
1276
1282
|
});
|
|
1277
1283
|
}
|
|
1278
1284
|
function CredentialModal(props) {
|
|
1279
|
-
const { open, mandatory, title, description, services, onServicesChange, busy, errorCode, onSave, onSaved, onCancel, laterLabel = "cancel", t } = props;
|
|
1285
|
+
const { open, mandatory, title, description, services, onServicesChange, busy, errorCode, onSave, onSaved, onCancel, laterLabel = "cancel", t, externalDialogOwner } = props;
|
|
1280
1286
|
const [draft, setDraft] = (0, react.useState)("");
|
|
1281
1287
|
const [visible, setVisible] = (0, react.useState)(false);
|
|
1282
1288
|
const [displayedErrorCode, setDisplayedErrorCode] = (0, react.useState)(errorCode);
|
|
@@ -1286,7 +1292,7 @@ function CredentialModal(props) {
|
|
|
1286
1292
|
const helpId = `${keyId}-help`;
|
|
1287
1293
|
const errorId = `${keyId}-error`;
|
|
1288
1294
|
const errorPresentation = displayedErrorCode === null ? null : presentClientError(displayedErrorCode);
|
|
1289
|
-
const surfaceOpen = useExternalDialogGate(open);
|
|
1295
|
+
const surfaceOpen = useExternalDialogGate(open, externalDialogOwner);
|
|
1290
1296
|
const clear = (0, react.useCallback)(() => {
|
|
1291
1297
|
draftRef.current = "";
|
|
1292
1298
|
setDraft("");
|
|
@@ -1301,6 +1307,7 @@ function CredentialModal(props) {
|
|
|
1301
1307
|
useDialogA11y({
|
|
1302
1308
|
open: surfaceOpen,
|
|
1303
1309
|
container: contentRef,
|
|
1310
|
+
externalDialogOwner,
|
|
1304
1311
|
initialFocusSelector: "[data-mdlx-initial-focus]",
|
|
1305
1312
|
mandatory,
|
|
1306
1313
|
onEscape: close
|
|
@@ -1686,6 +1693,11 @@ var CredentialDialogCoordinator = class {
|
|
|
1686
1693
|
if (this.#snapshot.activeOwner !== null) return;
|
|
1687
1694
|
this.#publish({ activeOwner: owner });
|
|
1688
1695
|
}
|
|
1696
|
+
/** Lets an explicit Credential editor adopt a queued shell recovery prompt. */
|
|
1697
|
+
openCredential(owner) {
|
|
1698
|
+
if (this.#snapshot.activeOwner !== null && this.#snapshot.activeOwner !== "shell:credential-recovery") return;
|
|
1699
|
+
this.#publish({ activeOwner: owner });
|
|
1700
|
+
}
|
|
1689
1701
|
presentRecovery(token) {
|
|
1690
1702
|
if (token === this.#snapshot.dismissedRecoveryToken) return;
|
|
1691
1703
|
if (token === this.#snapshot.recoveryToken) {
|
|
@@ -1916,8 +1928,28 @@ function DesignResultPreview({ resource, t }) {
|
|
|
1916
1928
|
});
|
|
1917
1929
|
}
|
|
1918
1930
|
//#endregion
|
|
1931
|
+
//#region src/client/result-tabs.ts
|
|
1932
|
+
/** Implements the WAI-ARIA Tabs arrow/Home/End keyboard pattern. */
|
|
1933
|
+
function handleResultTabKeyDown(event) {
|
|
1934
|
+
if (![
|
|
1935
|
+
"ArrowLeft",
|
|
1936
|
+
"ArrowRight",
|
|
1937
|
+
"Home",
|
|
1938
|
+
"End"
|
|
1939
|
+
].includes(event.key)) return;
|
|
1940
|
+
const tabs = [...event.currentTarget.querySelectorAll("[role=\"tab\"]:not([disabled])")];
|
|
1941
|
+
if (tabs.length === 0) return;
|
|
1942
|
+
const active = tabs.findIndex((tab) => tab === event.target);
|
|
1943
|
+
if (active < 0) return;
|
|
1944
|
+
const next = event.key === "Home" ? tabs[0] : event.key === "End" ? tabs.at(-1) : tabs[(active + (event.key === "ArrowRight" ? 1 : -1) + tabs.length) % tabs.length];
|
|
1945
|
+
if (next === void 0) return;
|
|
1946
|
+
event.preventDefault();
|
|
1947
|
+
next.focus();
|
|
1948
|
+
next.click();
|
|
1949
|
+
}
|
|
1950
|
+
//#endregion
|
|
1919
1951
|
//#region src/client/DesignView.tsx
|
|
1920
|
-
function ModellixDesignView({ controller, settingsController, t }) {
|
|
1952
|
+
function ModellixDesignView({ advancedEditorOpen = true, controller, settingsController, onAddUrl, t }) {
|
|
1921
1953
|
const state = useResourceState(controller.store);
|
|
1922
1954
|
const settingsState = useResourceState(settingsController.store);
|
|
1923
1955
|
const snapshot = state.data;
|
|
@@ -1989,6 +2021,9 @@ function ModellixDesignView({ controller, settingsController, t }) {
|
|
|
1989
2021
|
(0, react.useEffect)(() => {
|
|
1990
2022
|
if (state.pending !== null) setOutcomeAnnouncement("");
|
|
1991
2023
|
}, [state.pending]);
|
|
2024
|
+
(0, react.useEffect)(() => {
|
|
2025
|
+
setOutcomeAnnouncement("");
|
|
2026
|
+
}, [t]);
|
|
1992
2027
|
(0, react.useEffect)(() => {
|
|
1993
2028
|
if (snapshot === null) return;
|
|
1994
2029
|
const transition = designOutcomeTransition(previousOutcome.current, snapshot);
|
|
@@ -2056,307 +2091,294 @@ function ModellixDesignView({ controller, settingsController, t }) {
|
|
|
2056
2091
|
className: "mdlx-design",
|
|
2057
2092
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2058
2093
|
className: "mdlx-design-shell",
|
|
2059
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
})
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
onChange: (event) => setModelQuery(event.currentTarget.value)
|
|
2117
|
-
}),
|
|
2118
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
2119
|
-
className: "mdlx-select",
|
|
2120
|
-
value: modelKind,
|
|
2121
|
-
"aria-label": t("modelCategoryLabel"),
|
|
2122
|
-
disabled: interactionBusy || !snapshot.enabled,
|
|
2123
|
-
onChange: (event) => {
|
|
2124
|
-
setModelKind(event.currentTarget.value);
|
|
2125
|
-
},
|
|
2126
|
-
children: [
|
|
2127
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
2128
|
-
value: "all",
|
|
2129
|
-
children: t("modelCategoryAll")
|
|
2130
|
-
}),
|
|
2131
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
2132
|
-
value: "image",
|
|
2133
|
-
children: t("modelCategoryImage")
|
|
2134
|
-
}),
|
|
2135
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
2136
|
-
value: "video",
|
|
2137
|
-
children: t("modelCategoryVideo")
|
|
2138
|
-
}),
|
|
2139
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
2140
|
-
value: "audio",
|
|
2141
|
-
children: t("modelCategoryAudio")
|
|
2142
|
-
})
|
|
2143
|
-
]
|
|
2144
|
-
}),
|
|
2145
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
2094
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2095
|
+
id: "mdlx-design-editor",
|
|
2096
|
+
className: "mdlx-design-editor",
|
|
2097
|
+
hidden: !advancedEditorOpen,
|
|
2098
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
2099
|
+
className: "mdlx-design-pane",
|
|
2100
|
+
"aria-label": t("advancedEditor"),
|
|
2101
|
+
children: [
|
|
2102
|
+
!snapshot.enabled && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2103
|
+
className: "mdlx-info",
|
|
2104
|
+
children: t("designDisabled")
|
|
2105
|
+
}),
|
|
2106
|
+
!snapshot.credentialReady && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2107
|
+
className: "mdlx-info",
|
|
2108
|
+
children: [
|
|
2109
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: t("keyRequired") }),
|
|
2110
|
+
settings?.credential.writable === true && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
2111
|
+
type: "button",
|
|
2112
|
+
variant: "primary",
|
|
2113
|
+
onClick: () => credentialDialogs.openCredential(credentialDialogOwner),
|
|
2114
|
+
children: t("configureToContinue")
|
|
2115
|
+
}),
|
|
2116
|
+
settings?.credential.source === "env" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2117
|
+
className: "mdlx-muted",
|
|
2118
|
+
children: t("envReadonly")
|
|
2119
|
+
})
|
|
2120
|
+
]
|
|
2121
|
+
}),
|
|
2122
|
+
snapshot.notice !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2123
|
+
className: "mdlx-info",
|
|
2124
|
+
role: "status",
|
|
2125
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("strong", { children: [t("notice"), ": "] }), t(designNoticeMessageKey(snapshot.notice))]
|
|
2126
|
+
}),
|
|
2127
|
+
draft !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
2128
|
+
className: "mdlx-card",
|
|
2129
|
+
"aria-labelledby": "mdlx-assistant-title",
|
|
2130
|
+
children: [
|
|
2131
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2132
|
+
className: "mdlx-heading",
|
|
2133
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
|
|
2134
|
+
id: "mdlx-assistant-title",
|
|
2135
|
+
children: t("assistantTitle")
|
|
2136
|
+
})
|
|
2137
|
+
}),
|
|
2138
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
|
|
2139
|
+
id: "mdlx-assistant-instruction",
|
|
2140
|
+
className: "mdlx-textarea mdlx-textarea-small",
|
|
2141
|
+
value: instruction,
|
|
2142
|
+
maxLength: 8e3,
|
|
2143
|
+
placeholder: t("assistantPlaceholder"),
|
|
2144
|
+
"aria-labelledby": "mdlx-assistant-title",
|
|
2145
|
+
disabled: interactionBusy,
|
|
2146
|
+
onChange: (event) => setInstruction(event.currentTarget.value)
|
|
2147
|
+
}),
|
|
2148
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2149
|
+
className: "mdlx-actions",
|
|
2150
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
2146
2151
|
type: "button",
|
|
2147
2152
|
variant: "outline",
|
|
2148
|
-
disabled: interactionBusy ||
|
|
2149
|
-
"aria-busy": state.pending === "
|
|
2153
|
+
disabled: interactionBusy || instruction.trim().length === 0,
|
|
2154
|
+
"aria-busy": state.pending === "propose",
|
|
2150
2155
|
onClick: () => {
|
|
2151
|
-
|
|
2156
|
+
const request = instruction.trim();
|
|
2157
|
+
if (request === "") return;
|
|
2158
|
+
controller.propose(request, parameters).then((accepted) => {
|
|
2159
|
+
if (accepted) setInstruction("");
|
|
2160
|
+
});
|
|
2152
2161
|
},
|
|
2153
|
-
children: state.pending === "
|
|
2162
|
+
children: state.pending === "propose" ? t("proposing") : t("propose")
|
|
2154
2163
|
})
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
value: snapshot.selectedModelId ?? "",
|
|
2161
|
-
"aria-describedby": selectedModel?.available === false ? "mdlx-design-model-status" : void 0,
|
|
2162
|
-
disabled: interactionBusy || !snapshot.enabled || snapshot.models.length === 0,
|
|
2163
|
-
onChange: (event) => {
|
|
2164
|
-
const modelId = event.currentTarget.value;
|
|
2165
|
-
if (modelId !== "") controller.selectModel(modelId);
|
|
2166
|
-
},
|
|
2167
|
-
children: [
|
|
2168
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
2169
|
-
value: "",
|
|
2170
|
-
disabled: true,
|
|
2171
|
-
children: t("chooseModel")
|
|
2172
|
-
}),
|
|
2173
|
-
snapshot.selectedModelId !== null && !visibleModels.some((model) => model.id === snapshot.selectedModelId) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
2174
|
-
value: snapshot.selectedModelId,
|
|
2175
|
-
disabled: selectedModel?.available === false,
|
|
2176
|
-
children: snapshot.models.find((model) => model.id === snapshot.selectedModelId)?.label ?? snapshot.selectedModelId
|
|
2177
|
-
}),
|
|
2178
|
-
visibleModels.map((model) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("option", {
|
|
2179
|
-
value: model.id,
|
|
2180
|
-
disabled: !model.available,
|
|
2181
|
-
children: [model.label, model.featured ? " ★" : ""]
|
|
2182
|
-
}, model.id))
|
|
2183
|
-
]
|
|
2184
|
-
}),
|
|
2185
|
-
selectedModel?.available === false && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2186
|
-
id: "mdlx-design-model-status",
|
|
2187
|
-
className: "mdlx-error",
|
|
2188
|
-
role: "status",
|
|
2189
|
-
children: selectedModel.unavailableReason === null ? t("modelUnavailable") : t(designModelUnavailableMessageKey(selectedModel.unavailableReason))
|
|
2190
|
-
}),
|
|
2191
|
-
snapshot.models.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2192
|
-
className: "mdlx-help",
|
|
2193
|
-
children: t("noModels")
|
|
2194
|
-
}) : visibleModels.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2195
|
-
className: "mdlx-help",
|
|
2196
|
-
children: t("noMatchingModels")
|
|
2197
|
-
})
|
|
2198
|
-
]
|
|
2199
|
-
}),
|
|
2200
|
-
draft !== null && promptPath !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2201
|
-
className: "mdlx-field",
|
|
2202
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
2203
|
-
className: "mdlx-label",
|
|
2204
|
-
htmlFor: "mdlx-design-prompt",
|
|
2164
|
+
})
|
|
2165
|
+
]
|
|
2166
|
+
}),
|
|
2167
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2168
|
+
className: "mdlx-field",
|
|
2205
2169
|
children: [
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2170
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
|
|
2171
|
+
className: "mdlx-label",
|
|
2172
|
+
htmlFor: "mdlx-design-model",
|
|
2173
|
+
children: t("modelLabel")
|
|
2174
|
+
}),
|
|
2175
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2176
|
+
className: "mdlx-model-tools",
|
|
2177
|
+
children: [
|
|
2178
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Input, {
|
|
2179
|
+
className: "mdlx-input",
|
|
2180
|
+
value: modelQuery,
|
|
2181
|
+
maxLength: 512,
|
|
2182
|
+
placeholder: t("modelSearchPlaceholder"),
|
|
2183
|
+
"aria-label": t("modelSearchLabel"),
|
|
2184
|
+
disabled: interactionBusy || !snapshot.enabled,
|
|
2185
|
+
onChange: (event) => setModelQuery(event.currentTarget.value)
|
|
2186
|
+
}),
|
|
2187
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
2188
|
+
className: "mdlx-select",
|
|
2189
|
+
value: modelKind,
|
|
2190
|
+
"aria-label": t("modelCategoryLabel"),
|
|
2191
|
+
disabled: interactionBusy || !snapshot.enabled,
|
|
2192
|
+
onChange: (event) => {
|
|
2193
|
+
setModelKind(event.currentTarget.value);
|
|
2194
|
+
},
|
|
2195
|
+
children: [
|
|
2196
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
2197
|
+
value: "all",
|
|
2198
|
+
children: t("modelCategoryAll")
|
|
2199
|
+
}),
|
|
2200
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
2201
|
+
value: "image",
|
|
2202
|
+
children: t("modelCategoryImage")
|
|
2203
|
+
}),
|
|
2204
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
2205
|
+
value: "video",
|
|
2206
|
+
children: t("modelCategoryVideo")
|
|
2207
|
+
}),
|
|
2208
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
2209
|
+
value: "audio",
|
|
2210
|
+
children: t("modelCategoryAudio")
|
|
2211
|
+
})
|
|
2212
|
+
]
|
|
2213
|
+
}),
|
|
2214
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
2215
|
+
type: "button",
|
|
2216
|
+
variant: "outline",
|
|
2217
|
+
disabled: interactionBusy || !snapshot.enabled || !snapshot.credentialReady,
|
|
2218
|
+
"aria-busy": state.pending === "refresh-design",
|
|
2219
|
+
onClick: () => {
|
|
2220
|
+
controller.refreshCatalog();
|
|
2221
|
+
},
|
|
2222
|
+
children: state.pending === "refresh-design" ? t("modelRefreshing") : t("modelRefresh")
|
|
2223
|
+
})
|
|
2224
|
+
]
|
|
2225
|
+
}),
|
|
2226
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
2227
|
+
id: "mdlx-design-model",
|
|
2228
|
+
className: "mdlx-select",
|
|
2229
|
+
value: snapshot.selectedModelId ?? "",
|
|
2230
|
+
"aria-describedby": selectedModel?.available === false ? "mdlx-design-model-status" : void 0,
|
|
2231
|
+
disabled: interactionBusy || !snapshot.enabled || snapshot.models.length === 0,
|
|
2232
|
+
onChange: (event) => {
|
|
2233
|
+
const modelId = event.currentTarget.value;
|
|
2234
|
+
if (modelId !== "") controller.selectModel(modelId);
|
|
2235
|
+
},
|
|
2236
|
+
children: [
|
|
2237
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
2238
|
+
value: "",
|
|
2239
|
+
disabled: true,
|
|
2240
|
+
children: t("chooseModel")
|
|
2241
|
+
}),
|
|
2242
|
+
snapshot.selectedModelId !== null && !visibleModels.some((model) => model.id === snapshot.selectedModelId) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
2243
|
+
value: snapshot.selectedModelId,
|
|
2244
|
+
disabled: selectedModel?.available === false,
|
|
2245
|
+
children: snapshot.models.find((model) => model.id === snapshot.selectedModelId)?.label ?? snapshot.selectedModelId
|
|
2246
|
+
}),
|
|
2247
|
+
visibleModels.map((model) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("option", {
|
|
2248
|
+
value: model.id,
|
|
2249
|
+
disabled: !model.available,
|
|
2250
|
+
children: [model.label, model.featured ? " ★" : ""]
|
|
2251
|
+
}, model.id))
|
|
2252
|
+
]
|
|
2253
|
+
}),
|
|
2254
|
+
selectedModel?.available === false && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2255
|
+
id: "mdlx-design-model-status",
|
|
2256
|
+
className: "mdlx-error",
|
|
2257
|
+
role: "status",
|
|
2258
|
+
children: selectedModel.unavailableReason === null ? t("modelUnavailable") : t(designModelUnavailableMessageKey(selectedModel.unavailableReason))
|
|
2259
|
+
}),
|
|
2260
|
+
snapshot.models.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2261
|
+
className: "mdlx-help",
|
|
2262
|
+
children: t("noModels")
|
|
2263
|
+
}) : visibleModels.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2264
|
+
className: "mdlx-help",
|
|
2265
|
+
children: t("noMatchingModels")
|
|
2211
2266
|
})
|
|
2212
2267
|
]
|
|
2213
|
-
}),
|
|
2214
|
-
|
|
2215
|
-
className: "mdlx-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
className: "mdlx-parameter-list",
|
|
2234
|
-
children: [requiredFields.map((field) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DesignParameterField, {
|
|
2235
|
-
field,
|
|
2236
|
-
value: parameters[field.path],
|
|
2237
|
-
invalid: invalidFields.has(field.path),
|
|
2268
|
+
}),
|
|
2269
|
+
draft !== null && promptPath !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2270
|
+
className: "mdlx-field",
|
|
2271
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
2272
|
+
className: "mdlx-label",
|
|
2273
|
+
htmlFor: "mdlx-design-prompt",
|
|
2274
|
+
children: [
|
|
2275
|
+
t("promptLabel"),
|
|
2276
|
+
" ",
|
|
2277
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2278
|
+
className: "mdlx-required",
|
|
2279
|
+
children: t("required")
|
|
2280
|
+
})
|
|
2281
|
+
]
|
|
2282
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
|
|
2283
|
+
id: "mdlx-design-prompt",
|
|
2284
|
+
className: "mdlx-textarea",
|
|
2285
|
+
value: promptValue,
|
|
2286
|
+
maxLength: fieldAtPath(draft.fields, promptPath)?.maxLength ?? void 0,
|
|
2287
|
+
placeholder: t("promptPlaceholder"),
|
|
2238
2288
|
disabled: interactionBusy,
|
|
2239
|
-
onChange: (
|
|
2240
|
-
onValidityChange: (valid) => setFieldValidity(field.path, valid),
|
|
2241
|
-
t
|
|
2242
|
-
}, field.path)), optionalFields.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
|
|
2243
|
-
className: "mdlx-advanced",
|
|
2244
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("summary", { children: t("advancedParameters", { count: optionalFields.length }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2245
|
-
className: "mdlx-parameter-list",
|
|
2246
|
-
children: optionalFields.map((field) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DesignParameterField, {
|
|
2247
|
-
field,
|
|
2248
|
-
value: parameters[field.path],
|
|
2249
|
-
invalid: invalidFields.has(field.path),
|
|
2250
|
-
disabled: interactionBusy,
|
|
2251
|
-
onChange: (value) => updateParameter(field.path, value),
|
|
2252
|
-
onValidityChange: (valid) => setFieldValidity(field.path, valid),
|
|
2253
|
-
t
|
|
2254
|
-
}, field.path))
|
|
2255
|
-
})]
|
|
2289
|
+
onChange: (event) => updateParameter(promptPath, event.currentTarget.value)
|
|
2256
2290
|
})]
|
|
2257
|
-
})
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
children: [
|
|
2263
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2291
|
+
}),
|
|
2292
|
+
draft !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
2293
|
+
className: "mdlx-design-scroll",
|
|
2294
|
+
"aria-labelledby": "mdlx-parameters-title",
|
|
2295
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2264
2296
|
className: "mdlx-heading",
|
|
2265
|
-
children:
|
|
2266
|
-
id: "mdlx-
|
|
2267
|
-
children: t("
|
|
2268
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2269
|
-
id: "mdlx-assistant-paid-notice",
|
|
2270
|
-
className: "mdlx-help",
|
|
2271
|
-
children: t("assistantPaidNotice")
|
|
2272
|
-
})]
|
|
2273
|
-
}),
|
|
2274
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
|
|
2275
|
-
id: "mdlx-assistant-instruction",
|
|
2276
|
-
className: "mdlx-textarea mdlx-textarea-small",
|
|
2277
|
-
value: instruction,
|
|
2278
|
-
maxLength: 8e3,
|
|
2279
|
-
placeholder: t("assistantPlaceholder"),
|
|
2280
|
-
"aria-labelledby": "mdlx-assistant-title",
|
|
2281
|
-
"aria-describedby": "mdlx-assistant-paid-notice",
|
|
2282
|
-
disabled: interactionBusy,
|
|
2283
|
-
onChange: (event) => setInstruction(event.currentTarget.value)
|
|
2284
|
-
}),
|
|
2285
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2286
|
-
className: "mdlx-actions",
|
|
2287
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
2288
|
-
type: "button",
|
|
2289
|
-
variant: "outline",
|
|
2290
|
-
disabled: interactionBusy || instruction.trim().length === 0,
|
|
2291
|
-
"aria-busy": state.pending === "propose",
|
|
2292
|
-
onClick: () => {
|
|
2293
|
-
const request = instruction.trim();
|
|
2294
|
-
if (request === "") return;
|
|
2295
|
-
controller.propose(request, parameters).then((accepted) => {
|
|
2296
|
-
if (accepted) setInstruction("");
|
|
2297
|
-
});
|
|
2298
|
-
},
|
|
2299
|
-
children: state.pending === "propose" ? t("proposing") : t("propose")
|
|
2297
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
|
|
2298
|
+
id: "mdlx-parameters-title",
|
|
2299
|
+
children: t("parametersTitle")
|
|
2300
2300
|
})
|
|
2301
|
-
})
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2301
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2302
|
+
className: "mdlx-parameter-list",
|
|
2303
|
+
children: [requiredFields.map((field) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DesignParameterField, {
|
|
2304
|
+
field,
|
|
2305
|
+
value: parameters[field.path],
|
|
2306
|
+
invalid: invalidFields.has(field.path),
|
|
2307
|
+
disabled: interactionBusy,
|
|
2308
|
+
onChange: (value) => updateParameter(field.path, value),
|
|
2309
|
+
onValidityChange: (valid) => setFieldValidity(field.path, valid),
|
|
2310
|
+
t
|
|
2311
|
+
}, field.path)), optionalFields.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
|
|
2312
|
+
className: "mdlx-advanced",
|
|
2313
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("summary", { children: t("advancedParameters", { count: optionalFields.length }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2314
|
+
className: "mdlx-parameter-list",
|
|
2315
|
+
children: optionalFields.map((field) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DesignParameterField, {
|
|
2316
|
+
field,
|
|
2317
|
+
value: parameters[field.path],
|
|
2318
|
+
invalid: invalidFields.has(field.path),
|
|
2319
|
+
disabled: interactionBusy,
|
|
2320
|
+
onChange: (value) => updateParameter(field.path, value),
|
|
2321
|
+
onValidityChange: (valid) => setFieldValidity(field.path, valid),
|
|
2322
|
+
t
|
|
2323
|
+
}, field.path))
|
|
2324
|
+
})]
|
|
2325
|
+
})]
|
|
2326
|
+
})]
|
|
2327
|
+
}),
|
|
2328
|
+
snapshot.proposal !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ProposalCard, {
|
|
2329
|
+
snapshot,
|
|
2330
|
+
parameters,
|
|
2331
|
+
controller,
|
|
2332
|
+
t
|
|
2333
|
+
}),
|
|
2334
|
+
draft !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2335
|
+
className: "mdlx-generate-block",
|
|
2336
|
+
children: [
|
|
2337
|
+
missingRequired && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2338
|
+
className: "mdlx-error",
|
|
2339
|
+
children: t("requiredMissing")
|
|
2340
|
+
}),
|
|
2341
|
+
invalidFields.size > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2342
|
+
className: "mdlx-error",
|
|
2343
|
+
children: t("parametersInvalid")
|
|
2344
|
+
}),
|
|
2345
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2346
|
+
className: "mdlx-actions",
|
|
2347
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
2348
|
+
type: "button",
|
|
2349
|
+
variant: snapshot.credentialReady && snapshot.proposal === null ? "primary" : "outline",
|
|
2350
|
+
disabled: !canGenerate,
|
|
2351
|
+
"aria-busy": submitting,
|
|
2352
|
+
onClick: () => {
|
|
2353
|
+
controller.submit(parameters);
|
|
2354
|
+
},
|
|
2355
|
+
children: submitting ? t("generating") : t("generate")
|
|
2356
|
+
})
|
|
2336
2357
|
})
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2358
|
+
]
|
|
2359
|
+
}),
|
|
2360
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ErrorNotice, {
|
|
2361
|
+
code: state.errorCode,
|
|
2362
|
+
t
|
|
2363
|
+
}),
|
|
2364
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(BusyStatus, {
|
|
2365
|
+
busy: interactionBusy,
|
|
2366
|
+
text: operationText(state.pending, t)
|
|
2367
|
+
}),
|
|
2368
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2369
|
+
className: "mdlx-live",
|
|
2370
|
+
role: "status",
|
|
2371
|
+
"aria-live": "polite",
|
|
2372
|
+
children: outcomeAnnouncement
|
|
2373
|
+
})
|
|
2374
|
+
]
|
|
2375
|
+
})
|
|
2355
2376
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DesignResults, {
|
|
2356
2377
|
snapshot,
|
|
2357
2378
|
dateLocale: t("dateLocale"),
|
|
2358
2379
|
dialogCoordinator: credentialDialogs,
|
|
2359
2380
|
dialog: credentialDialog,
|
|
2381
|
+
...onAddUrl === void 0 ? {} : { onAddUrl },
|
|
2360
2382
|
t
|
|
2361
2383
|
})]
|
|
2362
2384
|
}), settings !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CredentialModal, {
|
|
@@ -2599,125 +2621,167 @@ function ProposalCard({ snapshot, parameters, controller, t }) {
|
|
|
2599
2621
|
]
|
|
2600
2622
|
});
|
|
2601
2623
|
}
|
|
2602
|
-
function DesignResults({ snapshot, dateLocale, dialogCoordinator, dialog, t }) {
|
|
2603
|
-
const
|
|
2604
|
-
|
|
2605
|
-
const succeeded = [];
|
|
2606
|
-
const diagnostics = [];
|
|
2607
|
-
for (const job of snapshot.jobs) if (job.status === "running") running.push(job);
|
|
2608
|
-
else if (job.status === "succeeded") succeeded.push(job);
|
|
2609
|
-
else diagnostics.push(job);
|
|
2610
|
-
return {
|
|
2611
|
-
running,
|
|
2612
|
-
succeeded,
|
|
2613
|
-
diagnostics
|
|
2614
|
-
};
|
|
2615
|
-
}, [snapshot.jobs]);
|
|
2624
|
+
function DesignResults({ snapshot, dateLocale, dialogCoordinator, dialog, onAddUrl, t }) {
|
|
2625
|
+
const [open, setOpen] = (0, react.useState)(true);
|
|
2626
|
+
const jobs = (0, react.useMemo)(() => [...snapshot.jobs].sort((left, right) => Date.parse(right.createdAt) - Date.parse(left.createdAt)), [snapshot.jobs]);
|
|
2616
2627
|
const empty = snapshot.jobs.length === 0;
|
|
2617
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("
|
|
2618
|
-
className: "mdlx-design-pane",
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2628
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
|
|
2629
|
+
className: "mdlx-design-pane mdlx-results-disclosure",
|
|
2630
|
+
open,
|
|
2631
|
+
onToggle: (event) => setOpen(event.currentTarget.open),
|
|
2632
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("summary", {
|
|
2633
|
+
className: "mdlx-results-summary",
|
|
2634
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2623
2635
|
id: "mdlx-results-title",
|
|
2624
2636
|
children: t("resultsTitle")
|
|
2625
|
-
})
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
})
|
|
2630
|
-
className: "mdlx-
|
|
2631
|
-
children:
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
t
|
|
2639
|
-
}),
|
|
2640
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ResultSection, {
|
|
2641
|
-
title: t("succeededTitle"),
|
|
2642
|
-
jobs: groups.succeeded,
|
|
2643
|
-
dateLocale,
|
|
2644
|
-
dialogCoordinator,
|
|
2645
|
-
dialog,
|
|
2646
|
-
t
|
|
2647
|
-
}),
|
|
2648
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ResultSection, {
|
|
2649
|
-
title: t("diagnosticsTitle"),
|
|
2650
|
-
jobs: groups.diagnostics,
|
|
2637
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2638
|
+
className: "mdlx-muted",
|
|
2639
|
+
children: t("resultsCount", { count: jobs.length })
|
|
2640
|
+
})]
|
|
2641
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2642
|
+
className: "mdlx-results-body",
|
|
2643
|
+
children: empty ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2644
|
+
className: "mdlx-empty",
|
|
2645
|
+
children: t("noResults")
|
|
2646
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
2647
|
+
className: "mdlx-result-list",
|
|
2648
|
+
children: jobs.map((job) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ResultCard, {
|
|
2649
|
+
job,
|
|
2651
2650
|
dateLocale,
|
|
2652
2651
|
dialogCoordinator,
|
|
2653
2652
|
dialog,
|
|
2653
|
+
...onAddUrl === void 0 ? {} : { onAddUrl },
|
|
2654
2654
|
t
|
|
2655
|
-
})
|
|
2656
|
-
|
|
2657
|
-
})]
|
|
2658
|
-
});
|
|
2659
|
-
}
|
|
2660
|
-
function ResultSection({ title, jobs, dateLocale, dialogCoordinator, dialog, t }) {
|
|
2661
|
-
if (jobs.length === 0) return null;
|
|
2662
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
2663
|
-
className: "mdlx-result-section",
|
|
2664
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: title }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
2665
|
-
className: "mdlx-result-list",
|
|
2666
|
-
children: jobs.map((job) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ResultCard, {
|
|
2667
|
-
job,
|
|
2668
|
-
dateLocale,
|
|
2669
|
-
dialogCoordinator,
|
|
2670
|
-
dialog,
|
|
2671
|
-
t
|
|
2672
|
-
}, job.jobId))
|
|
2655
|
+
}, job.jobId))
|
|
2656
|
+
})
|
|
2673
2657
|
})]
|
|
2674
2658
|
});
|
|
2675
2659
|
}
|
|
2676
|
-
function ResultCard({ job, dateLocale, dialogCoordinator, dialog, t }) {
|
|
2660
|
+
function ResultCard({ job, dateLocale, dialogCoordinator, dialog, onAddUrl, t }) {
|
|
2661
|
+
const [open, setOpen] = (0, react.useState)(true);
|
|
2662
|
+
const [tab, setTab] = (0, react.useState)("preview");
|
|
2663
|
+
const [activeIndex, setActiveIndex] = (0, react.useState)(0);
|
|
2664
|
+
const tabId = (0, react.useId)();
|
|
2677
2665
|
const status = jobStatus(job.status, t);
|
|
2678
2666
|
const created = formatTime(job.createdAt, dateLocale);
|
|
2679
|
-
|
|
2667
|
+
const dot = job.status === "succeeded" ? "done" : job.status === "running" ? "ongoing" : job.status === "failed" ? "error" : "warning";
|
|
2668
|
+
const resources = job.status === "expired" ? [] : job.resources;
|
|
2669
|
+
const succeeded = job.status === "succeeded";
|
|
2670
|
+
const resourceIndex = resources.length === 0 ? 0 : activeIndex % resources.length;
|
|
2671
|
+
const currentResource = resources[resourceIndex];
|
|
2672
|
+
const activeTabId = `${tabId}-${tab}-tab`;
|
|
2673
|
+
const activePanelId = `${tabId}-${tab}-panel`;
|
|
2674
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", {
|
|
2680
2675
|
className: "mdlx-result-card",
|
|
2681
|
-
children:
|
|
2682
|
-
|
|
2683
|
-
|
|
2676
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
|
|
2677
|
+
className: "mdlx-result-disclosure",
|
|
2678
|
+
open,
|
|
2679
|
+
onToggle: (event) => setOpen(event.currentTarget.open),
|
|
2680
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("summary", {
|
|
2681
|
+
className: "mdlx-result-card-summary",
|
|
2684
2682
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2685
|
-
className: "mdlx-
|
|
2686
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.
|
|
2683
|
+
className: "mdlx-result-head",
|
|
2684
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2685
|
+
className: "mdlx-status-copy",
|
|
2686
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.StateDot, { state: dot }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: status })]
|
|
2687
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2688
|
+
className: "mdlx-muted",
|
|
2689
|
+
children: t("jobCreated", { time: created })
|
|
2690
|
+
})]
|
|
2687
2691
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2688
2692
|
className: "mdlx-muted",
|
|
2689
|
-
children: t("
|
|
2693
|
+
children: t("jobModel", { model: job.modelId })
|
|
2690
2694
|
})]
|
|
2691
|
-
}),
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2695
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2696
|
+
className: "mdlx-result-card-body",
|
|
2697
|
+
children: [succeeded && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2698
|
+
className: "mdlx-result-tabs",
|
|
2699
|
+
role: "tablist",
|
|
2700
|
+
"aria-label": t("resultViewLabel"),
|
|
2701
|
+
onKeyDown: handleResultTabKeyDown,
|
|
2702
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2703
|
+
id: `${tabId}-preview-tab`,
|
|
2704
|
+
type: "button",
|
|
2705
|
+
role: "tab",
|
|
2706
|
+
"aria-controls": `${tabId}-preview-panel`,
|
|
2707
|
+
"aria-selected": tab === "preview",
|
|
2708
|
+
tabIndex: tab === "preview" ? 0 : -1,
|
|
2709
|
+
className: "mdlx-result-tab",
|
|
2710
|
+
onClick: () => setTab("preview"),
|
|
2711
|
+
children: t("previewTab")
|
|
2712
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2713
|
+
id: `${tabId}-json-tab`,
|
|
2714
|
+
type: "button",
|
|
2715
|
+
role: "tab",
|
|
2716
|
+
"aria-controls": `${tabId}-json-panel`,
|
|
2717
|
+
"aria-selected": tab === "json",
|
|
2718
|
+
tabIndex: tab === "json" ? 0 : -1,
|
|
2719
|
+
className: "mdlx-result-tab",
|
|
2720
|
+
onClick: () => setTab("json"),
|
|
2721
|
+
children: t("jsonTab")
|
|
2722
|
+
})]
|
|
2723
|
+
}), tab === "preview" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2724
|
+
id: activePanelId,
|
|
2725
|
+
role: "tabpanel",
|
|
2726
|
+
"aria-labelledby": activeTabId,
|
|
2727
|
+
className: "mdlx-result-panel",
|
|
2728
|
+
children: currentResource === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2729
|
+
className: "mdlx-empty mdlx-empty-compact",
|
|
2730
|
+
children: t("noPreview")
|
|
2731
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ResultResource, {
|
|
2732
|
+
resource: currentResource,
|
|
2733
|
+
dateLocale,
|
|
2734
|
+
dialogCoordinator,
|
|
2735
|
+
dialog,
|
|
2736
|
+
...onAddUrl === void 0 ? {} : { onAddUrl },
|
|
2737
|
+
t
|
|
2738
|
+
}), resources.length > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2739
|
+
className: "mdlx-resource-nav",
|
|
2740
|
+
"aria-label": t("resourceNavigation"),
|
|
2741
|
+
children: [
|
|
2742
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
2743
|
+
type: "button",
|
|
2744
|
+
variant: "outline",
|
|
2745
|
+
onClick: () => setActiveIndex((resourceIndex - 1 + resources.length) % resources.length),
|
|
2746
|
+
children: t("previousResource")
|
|
2747
|
+
}),
|
|
2748
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2749
|
+
className: "mdlx-muted",
|
|
2750
|
+
children: t("resourcePosition", {
|
|
2751
|
+
current: resourceIndex + 1,
|
|
2752
|
+
total: resources.length
|
|
2753
|
+
})
|
|
2754
|
+
}),
|
|
2755
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
2756
|
+
type: "button",
|
|
2757
|
+
variant: "outline",
|
|
2758
|
+
onClick: () => setActiveIndex((resourceIndex + 1) % resources.length),
|
|
2759
|
+
children: t("nextResource")
|
|
2760
|
+
})
|
|
2761
|
+
]
|
|
2762
|
+
})] })
|
|
2763
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
|
|
2764
|
+
id: activePanelId,
|
|
2765
|
+
role: "tabpanel",
|
|
2766
|
+
"aria-labelledby": activeTabId,
|
|
2767
|
+
className: "mdlx-result-json",
|
|
2768
|
+
children: JSON.stringify(job, null, 2)
|
|
2769
|
+
})] }), job.diagnostic !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2770
|
+
className: "mdlx-error",
|
|
2771
|
+
children: [
|
|
2772
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", {
|
|
2773
|
+
className: "mdlx-code",
|
|
2774
|
+
children: job.diagnostic.code
|
|
2775
|
+
}),
|
|
2776
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: t(designDiagnosticMessageKey(job.diagnostic.code)) }),
|
|
2777
|
+
job.diagnostic.retryable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: t("diagnosticRetryable") })
|
|
2778
|
+
]
|
|
2779
|
+
})]
|
|
2780
|
+
})]
|
|
2781
|
+
})
|
|
2718
2782
|
});
|
|
2719
2783
|
}
|
|
2720
|
-
function ResultResource({ resource, dateLocale, dialogCoordinator, dialog, t }) {
|
|
2784
|
+
function ResultResource({ resource, dateLocale, dialogCoordinator, dialog, onAddUrl, t }) {
|
|
2721
2785
|
const imageDialogOwner = `design-image:${(0, react.useId)()}`;
|
|
2722
2786
|
const imageSurfaceOpen = useExternalDialogGate(dialog.activeOwner === imageDialogOwner);
|
|
2723
2787
|
const imageDialogRef = (0, react.useRef)(null);
|
|
@@ -2733,29 +2797,34 @@ function ResultResource({ resource, dateLocale, dialogCoordinator, dialog, t })
|
|
|
2733
2797
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("article", {
|
|
2734
2798
|
className: "mdlx-resource",
|
|
2735
2799
|
children: [
|
|
2736
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
2800
|
+
resource.kind === "image" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2801
|
+
type: "button",
|
|
2802
|
+
className: "mdlx-image-preview-button",
|
|
2803
|
+
"aria-label": t("openImage"),
|
|
2804
|
+
onClick: () => dialogCoordinator.open(imageDialogOwner),
|
|
2805
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DesignResultPreview, {
|
|
2806
|
+
resource,
|
|
2807
|
+
t
|
|
2808
|
+
})
|
|
2809
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DesignResultPreview, {
|
|
2737
2810
|
resource,
|
|
2738
2811
|
t
|
|
2739
2812
|
}),
|
|
2740
2813
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2741
2814
|
className: "mdlx-actions mdlx-actions-start",
|
|
2742
|
-
children: [
|
|
2815
|
+
children: [onAddUrl !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
2743
2816
|
type: "button",
|
|
2744
|
-
|
|
2745
|
-
onClick: () =>
|
|
2746
|
-
children: t("
|
|
2747
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.
|
|
2817
|
+
variant: "outline",
|
|
2818
|
+
onClick: () => onAddUrl(resource.url),
|
|
2819
|
+
children: t("addUrlToChat")
|
|
2820
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
|
|
2748
2821
|
className: "mdlx-safe-link",
|
|
2749
2822
|
href: resource.downloadUrl,
|
|
2750
2823
|
target: "_blank",
|
|
2751
2824
|
rel: "noopener noreferrer",
|
|
2752
2825
|
referrerPolicy: "no-referrer",
|
|
2753
2826
|
download: true,
|
|
2754
|
-
children:
|
|
2755
|
-
t("download"),
|
|
2756
|
-
" ",
|
|
2757
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconRightUpOutline14, { size: 14 })
|
|
2758
|
-
]
|
|
2827
|
+
children: t("download")
|
|
2759
2828
|
})]
|
|
2760
2829
|
}),
|
|
2761
2830
|
resource.expiresAt !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
@@ -2797,18 +2866,14 @@ function ResultResource({ resource, dateLocale, dialogCoordinator, dialog, t })
|
|
|
2797
2866
|
"data-mdlx-initial-focus": "",
|
|
2798
2867
|
onClick: closeImage,
|
|
2799
2868
|
children: t("close")
|
|
2800
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.
|
|
2869
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
|
|
2801
2870
|
className: "mdlx-safe-link",
|
|
2802
2871
|
href: resource.downloadUrl,
|
|
2803
2872
|
target: "_blank",
|
|
2804
2873
|
rel: "noopener noreferrer",
|
|
2805
2874
|
referrerPolicy: "no-referrer",
|
|
2806
2875
|
download: true,
|
|
2807
|
-
children:
|
|
2808
|
-
t("download"),
|
|
2809
|
-
" ",
|
|
2810
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconRightUpOutline14, { size: 14 })
|
|
2811
|
-
]
|
|
2876
|
+
children: t("download")
|
|
2812
2877
|
})]
|
|
2813
2878
|
})
|
|
2814
2879
|
]
|
|
@@ -2849,12 +2914,727 @@ function formatTime(value, locale) {
|
|
|
2849
2914
|
}).format(new Date(value));
|
|
2850
2915
|
}
|
|
2851
2916
|
//#endregion
|
|
2917
|
+
//#region src/client/DesignDrawer.tsx
|
|
2918
|
+
const MODELLIX_DESIGN_SPLIT_MEDIA_QUERY = "(min-width: 1280px)";
|
|
2919
|
+
const MODELLIX_DRAWER_EXIT_MS = 180;
|
|
2920
|
+
const MODELLIX_ADVANCED_EDITOR_ENTRY_HIDDEN = true;
|
|
2921
|
+
function isSplitViewport() {
|
|
2922
|
+
return typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia("(min-width: 1280px)").matches;
|
|
2923
|
+
}
|
|
2924
|
+
var DesignDrawerController = class {
|
|
2925
|
+
#rpc;
|
|
2926
|
+
#layout;
|
|
2927
|
+
#isSplitViewport;
|
|
2928
|
+
#listeners = /* @__PURE__ */ new Set();
|
|
2929
|
+
#controllers = /* @__PURE__ */ new Map();
|
|
2930
|
+
#watchedJobs = /* @__PURE__ */ new Map();
|
|
2931
|
+
#mediaCardClaims = /* @__PURE__ */ new Map();
|
|
2932
|
+
#mediaCardListeners = /* @__PURE__ */ new Set();
|
|
2933
|
+
#sessionReferences = /* @__PURE__ */ new Map();
|
|
2934
|
+
#sessionReleaseTimers = /* @__PURE__ */ new Map();
|
|
2935
|
+
#mediaCardVersion = 0;
|
|
2936
|
+
#mediaCardOrder = 0;
|
|
2937
|
+
#snapshot = {
|
|
2938
|
+
open: false,
|
|
2939
|
+
sessionId: null,
|
|
2940
|
+
controller: null,
|
|
2941
|
+
draft: "",
|
|
2942
|
+
inputActions: null
|
|
2943
|
+
};
|
|
2944
|
+
#trigger = null;
|
|
2945
|
+
#splitActive = false;
|
|
2946
|
+
constructor(rpc, layout, splitViewport = isSplitViewport) {
|
|
2947
|
+
this.#rpc = rpc;
|
|
2948
|
+
this.#layout = layout;
|
|
2949
|
+
this.#isSplitViewport = splitViewport;
|
|
2950
|
+
}
|
|
2951
|
+
subscribe = (listener) => {
|
|
2952
|
+
this.#listeners.add(listener);
|
|
2953
|
+
return () => this.#listeners.delete(listener);
|
|
2954
|
+
};
|
|
2955
|
+
getSnapshot = () => this.#snapshot;
|
|
2956
|
+
subscribeMediaCards = (listener) => {
|
|
2957
|
+
this.#mediaCardListeners.add(listener);
|
|
2958
|
+
return () => this.#mediaCardListeners.delete(listener);
|
|
2959
|
+
};
|
|
2960
|
+
getMediaCardVersion = () => this.#mediaCardVersion;
|
|
2961
|
+
claimMediaCard(sessionId, jobId, callId, operation) {
|
|
2962
|
+
const key = `${sessionId}\n${jobId}`;
|
|
2963
|
+
const claims = this.#mediaCardClaims.get(key) ?? /* @__PURE__ */ new Map();
|
|
2964
|
+
if (claims.has(callId)) return () => void 0;
|
|
2965
|
+
claims.set(callId, {
|
|
2966
|
+
operation,
|
|
2967
|
+
order: this.#mediaCardOrder++
|
|
2968
|
+
});
|
|
2969
|
+
this.#mediaCardClaims.set(key, claims);
|
|
2970
|
+
this.#publishMediaCards();
|
|
2971
|
+
return () => {
|
|
2972
|
+
const current = this.#mediaCardClaims.get(key);
|
|
2973
|
+
if (current?.delete(callId) !== true) return;
|
|
2974
|
+
if (current.size === 0) this.#mediaCardClaims.delete(key);
|
|
2975
|
+
this.#publishMediaCards();
|
|
2976
|
+
};
|
|
2977
|
+
}
|
|
2978
|
+
isMediaCardPrimary(sessionId, jobId, callId, operation) {
|
|
2979
|
+
const claims = this.#mediaCardClaims.get(`${sessionId}\n${jobId}`);
|
|
2980
|
+
if (claims === void 0 || claims.size === 0) return true;
|
|
2981
|
+
let primaryCallId = callId;
|
|
2982
|
+
let primary = {
|
|
2983
|
+
operation,
|
|
2984
|
+
order: Number.MAX_SAFE_INTEGER
|
|
2985
|
+
};
|
|
2986
|
+
for (const [candidateCallId, candidate] of claims) if (compareMediaCardClaims(candidate, primary) < 0) {
|
|
2987
|
+
primaryCallId = candidateCallId;
|
|
2988
|
+
primary = candidate;
|
|
2989
|
+
}
|
|
2990
|
+
return primaryCallId === callId;
|
|
2991
|
+
}
|
|
2992
|
+
controllerForSession(sessionId) {
|
|
2993
|
+
const existing = this.#controllers.get(sessionId);
|
|
2994
|
+
if (existing !== void 0) return existing;
|
|
2995
|
+
const controller = new DesignController(this.#rpc, sessionId);
|
|
2996
|
+
this.#controllers.set(sessionId, controller);
|
|
2997
|
+
return controller;
|
|
2998
|
+
}
|
|
2999
|
+
retainSession(sessionId) {
|
|
3000
|
+
const pendingRelease = this.#sessionReleaseTimers.get(sessionId);
|
|
3001
|
+
if (pendingRelease !== void 0) {
|
|
3002
|
+
window.clearTimeout(pendingRelease);
|
|
3003
|
+
this.#sessionReleaseTimers.delete(sessionId);
|
|
3004
|
+
}
|
|
3005
|
+
this.#sessionReferences.set(sessionId, (this.#sessionReferences.get(sessionId) ?? 0) + 1);
|
|
3006
|
+
let retained = true;
|
|
3007
|
+
return () => {
|
|
3008
|
+
if (!retained) return;
|
|
3009
|
+
retained = false;
|
|
3010
|
+
const remaining = Math.max(0, (this.#sessionReferences.get(sessionId) ?? 1) - 1);
|
|
3011
|
+
if (remaining > 0) {
|
|
3012
|
+
this.#sessionReferences.set(sessionId, remaining);
|
|
3013
|
+
return;
|
|
3014
|
+
}
|
|
3015
|
+
this.#sessionReferences.delete(sessionId);
|
|
3016
|
+
const timer = window.setTimeout(() => {
|
|
3017
|
+
this.#sessionReleaseTimers.delete(sessionId);
|
|
3018
|
+
if ((this.#sessionReferences.get(sessionId) ?? 0) === 0) this.releaseSession(sessionId);
|
|
3019
|
+
}, 0);
|
|
3020
|
+
this.#sessionReleaseTimers.set(sessionId, timer);
|
|
3021
|
+
};
|
|
3022
|
+
}
|
|
3023
|
+
watchJob(sessionId, jobId, initialStatus) {
|
|
3024
|
+
if (initialStatus !== "running") return () => void 0;
|
|
3025
|
+
const key = `${sessionId}\n${jobId}`;
|
|
3026
|
+
const existing = this.#watchedJobs.get(key);
|
|
3027
|
+
if (existing !== void 0) {
|
|
3028
|
+
existing.references += 1;
|
|
3029
|
+
return () => this.#releaseJobWatch(key, existing);
|
|
3030
|
+
}
|
|
3031
|
+
const controller = this.controllerForSession(sessionId);
|
|
3032
|
+
const watched = {
|
|
3033
|
+
references: 1,
|
|
3034
|
+
timer: null,
|
|
3035
|
+
stopped: false,
|
|
3036
|
+
unsubscribeStore: () => void 0
|
|
3037
|
+
};
|
|
3038
|
+
const liveStatus = () => controller.store.getSnapshot().data?.jobs.find((job) => job.jobId === jobId)?.status;
|
|
3039
|
+
const stopWhenTerminal = () => {
|
|
3040
|
+
const status = liveStatus();
|
|
3041
|
+
if (status === void 0 || status === "running") return;
|
|
3042
|
+
watched.stopped = true;
|
|
3043
|
+
if (watched.timer !== null) window.clearTimeout(watched.timer);
|
|
3044
|
+
watched.timer = null;
|
|
3045
|
+
};
|
|
3046
|
+
const poll = async () => {
|
|
3047
|
+
watched.timer = null;
|
|
3048
|
+
if (watched.stopped) return;
|
|
3049
|
+
await controller.load();
|
|
3050
|
+
stopWhenTerminal();
|
|
3051
|
+
if (!watched.stopped && watched.references > 0) watched.timer = window.setTimeout(() => {
|
|
3052
|
+
poll();
|
|
3053
|
+
}, 5e3);
|
|
3054
|
+
};
|
|
3055
|
+
watched.unsubscribeStore = controller.store.subscribe(stopWhenTerminal);
|
|
3056
|
+
this.#watchedJobs.set(key, watched);
|
|
3057
|
+
watched.timer = window.setTimeout(() => {
|
|
3058
|
+
poll();
|
|
3059
|
+
}, 0);
|
|
3060
|
+
return () => this.#releaseJobWatch(key, watched);
|
|
3061
|
+
}
|
|
3062
|
+
open(sessionId, inputActions, draft, trigger) {
|
|
3063
|
+
const controller = this.controllerForSession(sessionId);
|
|
3064
|
+
this.#trigger = trigger;
|
|
3065
|
+
this.#syncSplit(this.#isSplitViewport());
|
|
3066
|
+
this.#publish({
|
|
3067
|
+
open: true,
|
|
3068
|
+
sessionId,
|
|
3069
|
+
controller,
|
|
3070
|
+
draft,
|
|
3071
|
+
inputActions
|
|
3072
|
+
});
|
|
3073
|
+
}
|
|
3074
|
+
close(restoreFocus = true) {
|
|
3075
|
+
if (!this.#snapshot.open) return;
|
|
3076
|
+
this.#syncSplit(false);
|
|
3077
|
+
this.#publish({
|
|
3078
|
+
...this.#snapshot,
|
|
3079
|
+
open: false
|
|
3080
|
+
});
|
|
3081
|
+
if (restoreFocus) queueMicrotask(() => this.#trigger?.focus());
|
|
3082
|
+
}
|
|
3083
|
+
setSplitMode(enabled) {
|
|
3084
|
+
if (!this.#snapshot.open) return;
|
|
3085
|
+
this.#syncSplit(enabled);
|
|
3086
|
+
}
|
|
3087
|
+
updateSession(sessionId, inputActions, draft) {
|
|
3088
|
+
if (this.#snapshot.sessionId !== sessionId) return;
|
|
3089
|
+
this.#publish({
|
|
3090
|
+
...this.#snapshot,
|
|
3091
|
+
inputActions,
|
|
3092
|
+
draft
|
|
3093
|
+
});
|
|
3094
|
+
}
|
|
3095
|
+
releaseSession(sessionId) {
|
|
3096
|
+
if (this.#snapshot.sessionId !== sessionId) return;
|
|
3097
|
+
this.#syncSplit(false);
|
|
3098
|
+
this.#trigger = null;
|
|
3099
|
+
this.#publish({
|
|
3100
|
+
open: false,
|
|
3101
|
+
sessionId: null,
|
|
3102
|
+
controller: null,
|
|
3103
|
+
draft: "",
|
|
3104
|
+
inputActions: null
|
|
3105
|
+
});
|
|
3106
|
+
}
|
|
3107
|
+
#releaseJobWatch(key, watched) {
|
|
3108
|
+
if (this.#watchedJobs.get(key) !== watched) return;
|
|
3109
|
+
watched.references -= 1;
|
|
3110
|
+
if (watched.references > 0) return;
|
|
3111
|
+
watched.stopped = true;
|
|
3112
|
+
if (watched.timer !== null) window.clearTimeout(watched.timer);
|
|
3113
|
+
watched.unsubscribeStore();
|
|
3114
|
+
this.#watchedJobs.delete(key);
|
|
3115
|
+
}
|
|
3116
|
+
appendUrl(url) {
|
|
3117
|
+
const actions = this.#snapshot.inputActions;
|
|
3118
|
+
if (actions === null) return;
|
|
3119
|
+
const current = this.#snapshot.draft;
|
|
3120
|
+
const next = `${current}${current === "" || /\s$/u.test(current) ? "" : "\n"}${url}`;
|
|
3121
|
+
actions.setDraft(next);
|
|
3122
|
+
this.#publish({
|
|
3123
|
+
...this.#snapshot,
|
|
3124
|
+
draft: next
|
|
3125
|
+
});
|
|
3126
|
+
}
|
|
3127
|
+
#publish(snapshot) {
|
|
3128
|
+
this.#snapshot = snapshot;
|
|
3129
|
+
for (const listener of this.#listeners) listener();
|
|
3130
|
+
}
|
|
3131
|
+
#publishMediaCards() {
|
|
3132
|
+
this.#mediaCardVersion += 1;
|
|
3133
|
+
for (const listener of this.#mediaCardListeners) listener();
|
|
3134
|
+
}
|
|
3135
|
+
#syncSplit(enabled) {
|
|
3136
|
+
if (enabled === this.#splitActive) return;
|
|
3137
|
+
if (enabled) {
|
|
3138
|
+
this.#layout.closeDetails();
|
|
3139
|
+
this.#layout.openDetails();
|
|
3140
|
+
} else this.#layout.closeDetails();
|
|
3141
|
+
this.#splitActive = enabled;
|
|
3142
|
+
}
|
|
3143
|
+
};
|
|
3144
|
+
function compareMediaCardClaims(left, right) {
|
|
3145
|
+
return (left.operation === "generate" ? 0 : 1) - (right.operation === "generate" ? 0 : 1) || left.order - right.order;
|
|
3146
|
+
}
|
|
3147
|
+
function ModellixDesignLauncher({ drawer, inputActions, sessionId, t, useInput }) {
|
|
3148
|
+
const draft = useInput((state) => state.draft);
|
|
3149
|
+
const snapshot = (0, react.useSyncExternalStore)(drawer.subscribe, drawer.getSnapshot, drawer.getSnapshot);
|
|
3150
|
+
const active = snapshot.open && snapshot.sessionId === String(sessionId);
|
|
3151
|
+
(0, react.useEffect)(() => {
|
|
3152
|
+
drawer.updateSession(String(sessionId), inputActions, draft);
|
|
3153
|
+
}, [
|
|
3154
|
+
draft,
|
|
3155
|
+
drawer,
|
|
3156
|
+
inputActions,
|
|
3157
|
+
sessionId
|
|
3158
|
+
]);
|
|
3159
|
+
(0, react.useEffect)(() => drawer.retainSession(String(sessionId)), [drawer, sessionId]);
|
|
3160
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
3161
|
+
type: "button",
|
|
3162
|
+
variant: "outline",
|
|
3163
|
+
className: "mdlx-design-launcher",
|
|
3164
|
+
"aria-label": t("designTitle"),
|
|
3165
|
+
"aria-expanded": active,
|
|
3166
|
+
"aria-controls": "mdlx-design-drawer",
|
|
3167
|
+
onClick: (event) => {
|
|
3168
|
+
if (active) drawer.close();
|
|
3169
|
+
else drawer.open(String(sessionId), inputActions, draft, event.currentTarget);
|
|
3170
|
+
},
|
|
3171
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3172
|
+
className: "mdlx-launcher-label",
|
|
3173
|
+
children: t("designTitle")
|
|
3174
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3175
|
+
className: "mdlx-launcher-compact",
|
|
3176
|
+
"aria-hidden": "true",
|
|
3177
|
+
children: "M"
|
|
3178
|
+
})]
|
|
3179
|
+
});
|
|
3180
|
+
}
|
|
3181
|
+
function ModellixDesignDrawer({ drawer, settingsController, t }) {
|
|
3182
|
+
const snapshot = (0, react.useSyncExternalStore)(drawer.subscribe, drawer.getSnapshot, drawer.getSnapshot);
|
|
3183
|
+
const [retainedSnapshot, setRetainedSnapshot] = (0, react.useState)(snapshot.open && snapshot.controller !== null ? snapshot : null);
|
|
3184
|
+
const [advancedEditorOpen, setAdvancedEditorOpen] = (0, react.useState)(false);
|
|
3185
|
+
(0, react.useEffect)(() => {
|
|
3186
|
+
if (snapshot.open && snapshot.controller !== null) setRetainedSnapshot(snapshot);
|
|
3187
|
+
}, [
|
|
3188
|
+
snapshot.controller,
|
|
3189
|
+
snapshot.open,
|
|
3190
|
+
snapshot.sessionId
|
|
3191
|
+
]);
|
|
3192
|
+
(0, react.useEffect)(() => {
|
|
3193
|
+
if (snapshot.open || retainedSnapshot === null) return;
|
|
3194
|
+
const timer = window.setTimeout(() => setRetainedSnapshot(null), MODELLIX_DRAWER_EXIT_MS);
|
|
3195
|
+
return () => window.clearTimeout(timer);
|
|
3196
|
+
}, [retainedSnapshot, snapshot.open]);
|
|
3197
|
+
(0, react.useEffect)(() => {
|
|
3198
|
+
setAdvancedEditorOpen(false);
|
|
3199
|
+
}, [snapshot.sessionId]);
|
|
3200
|
+
(0, react.useEffect)(() => {
|
|
3201
|
+
if (!snapshot.open || typeof window.matchMedia !== "function") return;
|
|
3202
|
+
const media = window.matchMedia(MODELLIX_DESIGN_SPLIT_MEDIA_QUERY);
|
|
3203
|
+
const sync = () => drawer.setSplitMode(media.matches);
|
|
3204
|
+
sync();
|
|
3205
|
+
media.addEventListener("change", sync);
|
|
3206
|
+
return () => media.removeEventListener("change", sync);
|
|
3207
|
+
}, [drawer, snapshot.open]);
|
|
3208
|
+
const presentedSnapshot = snapshot.open && snapshot.controller !== null ? snapshot : retainedSnapshot;
|
|
3209
|
+
if (presentedSnapshot === null || presentedSnapshot.controller === null) return null;
|
|
3210
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3211
|
+
className: "mdlx-design-drawer-viewport",
|
|
3212
|
+
"data-closing": !snapshot.open || void 0,
|
|
3213
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("aside", {
|
|
3214
|
+
id: "mdlx-design-drawer",
|
|
3215
|
+
className: "mdlx-design-drawer",
|
|
3216
|
+
"aria-labelledby": "mdlx-design-drawer-title",
|
|
3217
|
+
onKeyDown: (event) => {
|
|
3218
|
+
if (event.key === "Escape") {
|
|
3219
|
+
event.preventDefault();
|
|
3220
|
+
drawer.close();
|
|
3221
|
+
}
|
|
3222
|
+
},
|
|
3223
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", {
|
|
3224
|
+
className: "mdlx-drawer-header",
|
|
3225
|
+
"data-editor-open": advancedEditorOpen || void 0,
|
|
3226
|
+
children: [
|
|
3227
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
3228
|
+
type: "button",
|
|
3229
|
+
variant: "ghost",
|
|
3230
|
+
size: "sm",
|
|
3231
|
+
className: "mdlx-drawer-close",
|
|
3232
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCloseOutline16, { size: 16 }),
|
|
3233
|
+
"aria-label": `${t("close")} ${t("designTitle")}`,
|
|
3234
|
+
onClick: () => drawer.close()
|
|
3235
|
+
}),
|
|
3236
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3237
|
+
className: "mdlx-heading",
|
|
3238
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
|
|
3239
|
+
id: "mdlx-design-drawer-title",
|
|
3240
|
+
children: t("designTitle")
|
|
3241
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
3242
|
+
className: "mdlx-muted",
|
|
3243
|
+
children: t("designDescription")
|
|
3244
|
+
})]
|
|
3245
|
+
}),
|
|
3246
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3247
|
+
className: "mdlx-drawer-header-reveal",
|
|
3248
|
+
hidden: MODELLIX_ADVANCED_EDITOR_ENTRY_HIDDEN,
|
|
3249
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
3250
|
+
type: "button",
|
|
3251
|
+
variant: "outline",
|
|
3252
|
+
className: "mdlx-drawer-editor-toggle",
|
|
3253
|
+
"aria-controls": "mdlx-design-editor",
|
|
3254
|
+
"aria-expanded": advancedEditorOpen,
|
|
3255
|
+
onClick: (event) => {
|
|
3256
|
+
const next = !advancedEditorOpen;
|
|
3257
|
+
setAdvancedEditorOpen(next);
|
|
3258
|
+
if (!next && event.detail > 0) event.currentTarget.blur();
|
|
3259
|
+
},
|
|
3260
|
+
children: t("advancedEditor")
|
|
3261
|
+
}) })
|
|
3262
|
+
})
|
|
3263
|
+
]
|
|
3264
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3265
|
+
className: "mdlx-drawer-body",
|
|
3266
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModellixDesignView, {
|
|
3267
|
+
advancedEditorOpen,
|
|
3268
|
+
controller: presentedSnapshot.controller,
|
|
3269
|
+
settingsController,
|
|
3270
|
+
onAddUrl: (url) => drawer.appendUrl(url),
|
|
3271
|
+
t
|
|
3272
|
+
})
|
|
3273
|
+
})]
|
|
3274
|
+
})
|
|
3275
|
+
});
|
|
3276
|
+
}
|
|
3277
|
+
//#endregion
|
|
3278
|
+
//#region src/client/MediaToolView.tsx
|
|
3279
|
+
function ModellixMediaToolView({ block, drawer, inputActions, sessionId, t, useInput }) {
|
|
3280
|
+
const draft = useInput((state) => state.draft);
|
|
3281
|
+
const [tab, setTab] = (0, react.useState)("preview");
|
|
3282
|
+
const [activeIndex, setActiveIndex] = (0, react.useState)(0);
|
|
3283
|
+
const [imageOpen, setImageOpen] = (0, react.useState)(false);
|
|
3284
|
+
const tabId = (0, react.useId)();
|
|
3285
|
+
const imageDialogRef = (0, react.useRef)(null);
|
|
3286
|
+
const isResultBlock = "kind" in block && block.kind === "tool-result";
|
|
3287
|
+
const parsedResult = isResultBlock ? parseMediaToolResult(block.meta) : null;
|
|
3288
|
+
const liveState = useResourceState(drawer.controllerForSession(String(sessionId)).store);
|
|
3289
|
+
const trackedJobId = mediaToolJobId(parsedResult);
|
|
3290
|
+
const operation = parsedResult?.operation;
|
|
3291
|
+
const callId = "callId" in block && typeof block.callId === "string" ? block.callId : `${String(sessionId)}:${trackedJobId ?? "pending"}`;
|
|
3292
|
+
(0, react.useSyncExternalStore)(drawer.subscribeMediaCards, drawer.getMediaCardVersion, drawer.getMediaCardVersion);
|
|
3293
|
+
const parsedStatus = mediaToolStatus(parsedResult);
|
|
3294
|
+
const result = resolveLiveMediaToolResult(parsedResult, trackedJobId === void 0 ? void 0 : liveState.data?.jobs.find((job) => job.jobId === trackedJobId), t);
|
|
3295
|
+
(0, react.useEffect)(() => trackedJobId === void 0 ? void 0 : drawer.watchJob(String(sessionId), trackedJobId, parsedStatus), [
|
|
3296
|
+
drawer,
|
|
3297
|
+
parsedStatus,
|
|
3298
|
+
sessionId,
|
|
3299
|
+
trackedJobId
|
|
3300
|
+
]);
|
|
3301
|
+
(0, react.useEffect)(() => trackedJobId === void 0 || operation === void 0 ? void 0 : drawer.claimMediaCard(String(sessionId), trackedJobId, callId, operation), [
|
|
3302
|
+
callId,
|
|
3303
|
+
drawer,
|
|
3304
|
+
operation,
|
|
3305
|
+
sessionId,
|
|
3306
|
+
trackedJobId
|
|
3307
|
+
]);
|
|
3308
|
+
const resources = result?.operation === "get_result" ? result.job?.resources ?? [] : result?.resources ?? [];
|
|
3309
|
+
const resourceIndex = resources.length === 0 ? 0 : activeIndex % resources.length;
|
|
3310
|
+
const current = resources[resourceIndex];
|
|
3311
|
+
const imageSurfaceOpen = useExternalDialogGate(imageOpen && current?.kind === "image");
|
|
3312
|
+
const closeImage = (0, react.useCallback)(() => setImageOpen(false), []);
|
|
3313
|
+
useDialogA11y({
|
|
3314
|
+
open: imageSurfaceOpen,
|
|
3315
|
+
container: imageDialogRef,
|
|
3316
|
+
initialFocusSelector: "[data-mdlx-initial-focus]",
|
|
3317
|
+
mandatory: false,
|
|
3318
|
+
onEscape: closeImage
|
|
3319
|
+
});
|
|
3320
|
+
(0, react.useEffect)(() => setImageOpen(false), [current?.url]);
|
|
3321
|
+
if (trackedJobId !== void 0 && operation !== void 0 && !drawer.isMediaCardPrimary(String(sessionId), trackedJobId, callId, operation)) return null;
|
|
3322
|
+
if (!isResultBlock) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3323
|
+
className: "mdlx-tool-result mdlx-muted",
|
|
3324
|
+
role: "status",
|
|
3325
|
+
children: t("generating")
|
|
3326
|
+
});
|
|
3327
|
+
if (result === null) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3328
|
+
className: "mdlx-tool-result mdlx-muted",
|
|
3329
|
+
role: "status",
|
|
3330
|
+
children: t("noPreview")
|
|
3331
|
+
});
|
|
3332
|
+
const status = result.operation === "get_result" ? result.job?.status : result.status;
|
|
3333
|
+
const modelId = result.operation === "get_result" ? result.job?.modelId : result.modelId;
|
|
3334
|
+
const diagnostic = result.operation === "get_result" ? result.job?.diagnostic : result.diagnostic;
|
|
3335
|
+
const succeeded = status === "succeeded";
|
|
3336
|
+
const activeTabId = `${tabId}-${tab}-tab`;
|
|
3337
|
+
const activePanelId = `${tabId}-${tab}-panel`;
|
|
3338
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("article", {
|
|
3339
|
+
className: "mdlx-tool-result",
|
|
3340
|
+
children: [
|
|
3341
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3342
|
+
className: "mdlx-result-head",
|
|
3343
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: result.found === false ? t("resultNotFound") : mediaStatusLabel(status, t) }), modelId !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3344
|
+
className: "mdlx-muted",
|
|
3345
|
+
children: modelId
|
|
3346
|
+
})]
|
|
3347
|
+
}),
|
|
3348
|
+
succeeded && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3349
|
+
className: "mdlx-result-tabs",
|
|
3350
|
+
role: "tablist",
|
|
3351
|
+
"aria-label": t("resultViewLabel"),
|
|
3352
|
+
onKeyDown: handleResultTabKeyDown,
|
|
3353
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3354
|
+
id: `${tabId}-preview-tab`,
|
|
3355
|
+
type: "button",
|
|
3356
|
+
role: "tab",
|
|
3357
|
+
"aria-controls": `${tabId}-preview-panel`,
|
|
3358
|
+
"aria-selected": tab === "preview",
|
|
3359
|
+
tabIndex: tab === "preview" ? 0 : -1,
|
|
3360
|
+
className: "mdlx-result-tab",
|
|
3361
|
+
onClick: () => setTab("preview"),
|
|
3362
|
+
children: t("previewTab")
|
|
3363
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3364
|
+
id: `${tabId}-json-tab`,
|
|
3365
|
+
type: "button",
|
|
3366
|
+
role: "tab",
|
|
3367
|
+
"aria-controls": `${tabId}-json-panel`,
|
|
3368
|
+
"aria-selected": tab === "json",
|
|
3369
|
+
tabIndex: tab === "json" ? 0 : -1,
|
|
3370
|
+
className: "mdlx-result-tab",
|
|
3371
|
+
onClick: () => setTab("json"),
|
|
3372
|
+
children: t("jsonTab")
|
|
3373
|
+
})]
|
|
3374
|
+
}), tab === "json" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
|
|
3375
|
+
id: activePanelId,
|
|
3376
|
+
role: "tabpanel",
|
|
3377
|
+
"aria-labelledby": activeTabId,
|
|
3378
|
+
className: "mdlx-result-json",
|
|
3379
|
+
children: JSON.stringify(result, null, 2)
|
|
3380
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3381
|
+
id: activePanelId,
|
|
3382
|
+
role: "tabpanel",
|
|
3383
|
+
"aria-labelledby": activeTabId,
|
|
3384
|
+
className: "mdlx-result-panel",
|
|
3385
|
+
children: current === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3386
|
+
className: "mdlx-empty mdlx-empty-compact",
|
|
3387
|
+
children: t("noPreview")
|
|
3388
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
3389
|
+
current.kind === "image" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3390
|
+
type: "button",
|
|
3391
|
+
className: "mdlx-image-preview-button",
|
|
3392
|
+
"aria-label": t("openImage"),
|
|
3393
|
+
onClick: () => setImageOpen(true),
|
|
3394
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DesignResultPreview, {
|
|
3395
|
+
resource: toWireResource(current, resourceIndex),
|
|
3396
|
+
t
|
|
3397
|
+
})
|
|
3398
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DesignResultPreview, {
|
|
3399
|
+
resource: toWireResource(current, resourceIndex),
|
|
3400
|
+
t
|
|
3401
|
+
}),
|
|
3402
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3403
|
+
className: "mdlx-actions mdlx-actions-start",
|
|
3404
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
3405
|
+
type: "button",
|
|
3406
|
+
variant: "outline",
|
|
3407
|
+
onClick: () => {
|
|
3408
|
+
const separator = draft === "" || /\s$/u.test(draft) ? "" : "\n";
|
|
3409
|
+
inputActions.setDraft(`${draft}${separator}${current.url}`);
|
|
3410
|
+
},
|
|
3411
|
+
children: t("addUrlToChat")
|
|
3412
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
|
|
3413
|
+
className: "mdlx-safe-link",
|
|
3414
|
+
href: current.url,
|
|
3415
|
+
target: "_blank",
|
|
3416
|
+
rel: "noopener noreferrer",
|
|
3417
|
+
referrerPolicy: "no-referrer",
|
|
3418
|
+
download: true,
|
|
3419
|
+
children: t("download")
|
|
3420
|
+
})]
|
|
3421
|
+
}),
|
|
3422
|
+
resources.length > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3423
|
+
className: "mdlx-resource-nav",
|
|
3424
|
+
"aria-label": t("resourceNavigation"),
|
|
3425
|
+
children: [
|
|
3426
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
3427
|
+
type: "button",
|
|
3428
|
+
variant: "outline",
|
|
3429
|
+
onClick: () => setActiveIndex((resourceIndex - 1 + resources.length) % resources.length),
|
|
3430
|
+
children: t("previousResource")
|
|
3431
|
+
}),
|
|
3432
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3433
|
+
className: "mdlx-muted",
|
|
3434
|
+
children: t("resourcePosition", {
|
|
3435
|
+
current: resourceIndex + 1,
|
|
3436
|
+
total: resources.length
|
|
3437
|
+
})
|
|
3438
|
+
}),
|
|
3439
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
3440
|
+
type: "button",
|
|
3441
|
+
variant: "outline",
|
|
3442
|
+
onClick: () => setActiveIndex((resourceIndex + 1) % resources.length),
|
|
3443
|
+
children: t("nextResource")
|
|
3444
|
+
})
|
|
3445
|
+
]
|
|
3446
|
+
})
|
|
3447
|
+
] })
|
|
3448
|
+
})] }),
|
|
3449
|
+
diagnostic !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3450
|
+
className: "mdlx-error",
|
|
3451
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", {
|
|
3452
|
+
className: "mdlx-code",
|
|
3453
|
+
children: diagnostic.code
|
|
3454
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: diagnostic.message })]
|
|
3455
|
+
})
|
|
3456
|
+
]
|
|
3457
|
+
}), succeeded && current?.kind === "image" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
3458
|
+
open: imageSurfaceOpen,
|
|
3459
|
+
title: t("imageViewerTitle"),
|
|
3460
|
+
closeLabel: t("close"),
|
|
3461
|
+
onClose: closeImage,
|
|
3462
|
+
headless: true,
|
|
3463
|
+
className: "mdlx-modal mdlx-image-modal",
|
|
3464
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3465
|
+
ref: imageDialogRef,
|
|
3466
|
+
className: "mdlx-modal-content",
|
|
3467
|
+
"data-mdlx-dialog-surface": "",
|
|
3468
|
+
tabIndex: -1,
|
|
3469
|
+
children: [
|
|
3470
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3471
|
+
className: "mdlx-heading",
|
|
3472
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
|
|
3473
|
+
className: "mdlx-modal-title",
|
|
3474
|
+
children: t("imageViewerTitle")
|
|
3475
|
+
})
|
|
3476
|
+
}),
|
|
3477
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
|
|
3478
|
+
className: "mdlx-image-full",
|
|
3479
|
+
src: current.url,
|
|
3480
|
+
alt: t("generatedPreview"),
|
|
3481
|
+
referrerPolicy: "no-referrer"
|
|
3482
|
+
}),
|
|
3483
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3484
|
+
className: "mdlx-actions",
|
|
3485
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
3486
|
+
type: "button",
|
|
3487
|
+
variant: "outline",
|
|
3488
|
+
"data-mdlx-initial-focus": "",
|
|
3489
|
+
onClick: closeImage,
|
|
3490
|
+
children: t("close")
|
|
3491
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
|
|
3492
|
+
className: "mdlx-safe-link",
|
|
3493
|
+
href: current.url,
|
|
3494
|
+
target: "_blank",
|
|
3495
|
+
rel: "noopener noreferrer",
|
|
3496
|
+
referrerPolicy: "no-referrer",
|
|
3497
|
+
download: true,
|
|
3498
|
+
children: t("download")
|
|
3499
|
+
})]
|
|
3500
|
+
})
|
|
3501
|
+
]
|
|
3502
|
+
})
|
|
3503
|
+
})] });
|
|
3504
|
+
}
|
|
3505
|
+
function mediaToolJobId(result) {
|
|
3506
|
+
return result?.operation === "get_result" ? result.job?.jobId : result?.jobId;
|
|
3507
|
+
}
|
|
3508
|
+
function mediaToolStatus(result) {
|
|
3509
|
+
return result?.operation === "get_result" ? result.job?.status : result?.status;
|
|
3510
|
+
}
|
|
3511
|
+
function resolveLiveMediaToolResult(result, liveJob, t) {
|
|
3512
|
+
if (result === null || liveJob === void 0) return result;
|
|
3513
|
+
const resources = liveJob.resources.map((resource) => ({
|
|
3514
|
+
kind: resource.kind,
|
|
3515
|
+
url: resource.url,
|
|
3516
|
+
...resource.expiresAt === null ? {} : { expiresAt: resource.expiresAt }
|
|
3517
|
+
}));
|
|
3518
|
+
const diagnostic = liveJob.diagnostic === null ? void 0 : {
|
|
3519
|
+
code: liveJob.diagnostic.code,
|
|
3520
|
+
message: t(designDiagnosticMessageKey(liveJob.diagnostic.code))
|
|
3521
|
+
};
|
|
3522
|
+
if (result.operation === "generate") {
|
|
3523
|
+
const { diagnostic: _staleDiagnostic, ...withoutDiagnostic } = result;
|
|
3524
|
+
return {
|
|
3525
|
+
...withoutDiagnostic,
|
|
3526
|
+
status: liveJob.status,
|
|
3527
|
+
modelId: liveJob.modelId,
|
|
3528
|
+
resources,
|
|
3529
|
+
...diagnostic === void 0 ? {} : { diagnostic }
|
|
3530
|
+
};
|
|
3531
|
+
}
|
|
3532
|
+
return {
|
|
3533
|
+
...result,
|
|
3534
|
+
found: true,
|
|
3535
|
+
job: {
|
|
3536
|
+
jobId: liveJob.jobId,
|
|
3537
|
+
modelId: liveJob.modelId,
|
|
3538
|
+
status: liveJob.status,
|
|
3539
|
+
resources,
|
|
3540
|
+
...diagnostic === void 0 ? {} : { diagnostic }
|
|
3541
|
+
}
|
|
3542
|
+
};
|
|
3543
|
+
}
|
|
3544
|
+
function parseMediaToolResult(value) {
|
|
3545
|
+
const root = record(value);
|
|
3546
|
+
if (root === null || root.service !== "media" || root.operation !== "generate" && root.operation !== "get_result") return null;
|
|
3547
|
+
if (root.operation === "generate") {
|
|
3548
|
+
const status = safeText(root.status, 64);
|
|
3549
|
+
const modelId = safeText(root.modelId, 256);
|
|
3550
|
+
const jobId = safeText(root.jobId, 256);
|
|
3551
|
+
const diagnostic = parseDiagnostic(root.diagnostic);
|
|
3552
|
+
return {
|
|
3553
|
+
operation: "generate",
|
|
3554
|
+
...status === void 0 ? {} : { status },
|
|
3555
|
+
...modelId === void 0 ? {} : { modelId },
|
|
3556
|
+
...jobId === void 0 ? {} : { jobId },
|
|
3557
|
+
resources: parseResources(root.resources),
|
|
3558
|
+
...diagnostic === void 0 ? {} : { diagnostic }
|
|
3559
|
+
};
|
|
3560
|
+
}
|
|
3561
|
+
const job = record(root.job);
|
|
3562
|
+
const diagnostic = job === null ? void 0 : parseDiagnostic(job.diagnostic);
|
|
3563
|
+
return {
|
|
3564
|
+
operation: "get_result",
|
|
3565
|
+
found: root.found === true,
|
|
3566
|
+
...job === null ? {} : { job: {
|
|
3567
|
+
jobId: safeText(job.jobId, 256) ?? "",
|
|
3568
|
+
modelId: safeText(job.modelId, 256) ?? "",
|
|
3569
|
+
status: safeText(job.status, 64) ?? "",
|
|
3570
|
+
resources: parseResources(job.resources),
|
|
3571
|
+
...diagnostic === void 0 ? {} : { diagnostic }
|
|
3572
|
+
} }
|
|
3573
|
+
};
|
|
3574
|
+
}
|
|
3575
|
+
function parseResources(value) {
|
|
3576
|
+
if (!Array.isArray(value)) return [];
|
|
3577
|
+
const resources = [];
|
|
3578
|
+
for (const candidate of value.slice(0, 32)) {
|
|
3579
|
+
const resource = record(candidate);
|
|
3580
|
+
if (resource === null || resource.kind !== "image" && resource.kind !== "video" && resource.kind !== "audio" || typeof resource.url !== "string") continue;
|
|
3581
|
+
let url;
|
|
3582
|
+
try {
|
|
3583
|
+
url = safeResourceHref(resource.url);
|
|
3584
|
+
} catch {
|
|
3585
|
+
continue;
|
|
3586
|
+
}
|
|
3587
|
+
const expiresAt = safeText(resource.expiresAt, 128);
|
|
3588
|
+
resources.push({
|
|
3589
|
+
kind: resource.kind,
|
|
3590
|
+
url,
|
|
3591
|
+
...expiresAt === void 0 ? {} : { expiresAt }
|
|
3592
|
+
});
|
|
3593
|
+
}
|
|
3594
|
+
return resources;
|
|
3595
|
+
}
|
|
3596
|
+
function parseDiagnostic(value) {
|
|
3597
|
+
const diagnostic = record(value);
|
|
3598
|
+
if (diagnostic === null) return void 0;
|
|
3599
|
+
const code = safeText(diagnostic.code, 128);
|
|
3600
|
+
const message = safeText(diagnostic.message, 1024);
|
|
3601
|
+
return code === void 0 || message === void 0 ? void 0 : {
|
|
3602
|
+
code,
|
|
3603
|
+
message
|
|
3604
|
+
};
|
|
3605
|
+
}
|
|
3606
|
+
function safeText(value, maximum) {
|
|
3607
|
+
return typeof value === "string" && value.length > 0 && value.length <= maximum ? value : void 0;
|
|
3608
|
+
}
|
|
3609
|
+
function record(value) {
|
|
3610
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
|
|
3611
|
+
}
|
|
3612
|
+
function mediaStatusLabel(status, t) {
|
|
3613
|
+
switch (status) {
|
|
3614
|
+
case "running": return t("running");
|
|
3615
|
+
case "succeeded": return t("succeeded");
|
|
3616
|
+
case "failed": return t("failed");
|
|
3617
|
+
case "canceled": return t("canceled");
|
|
3618
|
+
case "expired": return t("expired");
|
|
3619
|
+
case "submit-unknown": return t("unknown");
|
|
3620
|
+
default: return t("unknown");
|
|
3621
|
+
}
|
|
3622
|
+
}
|
|
3623
|
+
function toWireResource(resource, index) {
|
|
3624
|
+
return {
|
|
3625
|
+
id: `tool-resource-${String(index)}`,
|
|
3626
|
+
kind: resource.kind,
|
|
3627
|
+
url: resource.url,
|
|
3628
|
+
downloadUrl: resource.url,
|
|
3629
|
+
expiresAt: resource.expiresAt ?? null
|
|
3630
|
+
};
|
|
3631
|
+
}
|
|
3632
|
+
//#endregion
|
|
2852
3633
|
//#region src/client/locales.ts
|
|
2853
3634
|
const MODELLIX_LOCALE_NAMESPACE = "modellix";
|
|
2854
3635
|
const zh = {
|
|
2855
3636
|
dateLocale: "zh-CN",
|
|
2856
3637
|
nav: "Modellix",
|
|
2857
|
-
designTab: "Design",
|
|
2858
3638
|
onboardingTitle: "连接 Modellix",
|
|
2859
3639
|
onboardingDescription: "输入一个 Modellix API Key,即可启用 Design、LLM 模型和 Web Tools。",
|
|
2860
3640
|
keyLabel: "Modellix API Key",
|
|
@@ -2871,7 +3651,7 @@ const zh = {
|
|
|
2871
3651
|
serviceLlm: "LLM 模型",
|
|
2872
3652
|
serviceLlmDescription: "在 Harness 中快速切换 Modellix 支持的模型。",
|
|
2873
3653
|
serviceWeb: "Web Tools",
|
|
2874
|
-
serviceWebDescription: "
|
|
3654
|
+
serviceWebDescription: "提供可自动调用的 Modellix 网页搜索与读取工具。",
|
|
2875
3655
|
settingsTitle: "Modellix",
|
|
2876
3656
|
settingsDescription: "一个 API Key,统一使用 Design、LLM 与 Web Tools。",
|
|
2877
3657
|
credentialTitle: "API Key",
|
|
@@ -2914,13 +3694,13 @@ const zh = {
|
|
|
2914
3694
|
errorGeneric: "暂时无法完成操作,请重试。",
|
|
2915
3695
|
errorConflict: "配置已在其他位置更新,请刷新后重试。",
|
|
2916
3696
|
errorKeyInvalid: "这个 API Key 无效,请检查后重新输入。",
|
|
2917
|
-
errorBilling: "
|
|
3697
|
+
errorBilling: "当前请求无法完成,请在 Modellix 控制台查看账户状态。",
|
|
2918
3698
|
errorRateLimited: "请求过于频繁,请稍后手动重试。",
|
|
2919
3699
|
errorOffline: "当前无法连接 Modellix,请检查网络后重试。",
|
|
2920
3700
|
errorTimeout: "Modellix 响应超时,请稍后手动重试。",
|
|
2921
3701
|
errorServer: "Modellix 服务暂时不可用,请稍后手动重试。",
|
|
2922
3702
|
errorPolicy: "当前账户或环境策略不允许此操作。",
|
|
2923
|
-
errorSubmitUnknown: "
|
|
3703
|
+
errorSubmitUnknown: "提交结果未知。请先查看结果列表,不要重复提交。",
|
|
2924
3704
|
errorAssetExpired: "结果资源已过期,无法继续访问。",
|
|
2925
3705
|
errorDesignSchema: "模型参数定义已变化或无法解析,请刷新模型后重试。",
|
|
2926
3706
|
designTitle: "Modellix Design",
|
|
@@ -2940,11 +3720,11 @@ const zh = {
|
|
|
2940
3720
|
promptPlaceholder: "描述画面、视频动作或要合成的声音…",
|
|
2941
3721
|
parametersTitle: "参数",
|
|
2942
3722
|
advancedParameters: "高级参数({count})",
|
|
3723
|
+
advancedEditor: "高级参数编辑器",
|
|
2943
3724
|
required: "必填",
|
|
2944
3725
|
optional: "可选",
|
|
2945
3726
|
requiredMissing: "请填写所有必填参数后再生成。",
|
|
2946
3727
|
assistantTitle: "用对话调整参数",
|
|
2947
|
-
assistantPaidNotice: "发送后会使用同一个 Modellix Key 调用固定 LLM 生成参数提议,可能产生费用;不会自动生成媒体。",
|
|
2948
3728
|
assistantPlaceholder: "例如:改成 16:9,生成 8 秒视频,风格更电影化",
|
|
2949
3729
|
propose: "生成参数提议",
|
|
2950
3730
|
proposing: "正在分析…",
|
|
@@ -2956,7 +3736,6 @@ const zh = {
|
|
|
2956
3736
|
conflicts: "需要先解决冲突",
|
|
2957
3737
|
generate: "确认并生成",
|
|
2958
3738
|
generating: "正在提交…",
|
|
2959
|
-
paidNotice: "生成是计费操作;每次点击只提交一次,不会自动重试。",
|
|
2960
3739
|
designDisabled: "Design 已关闭,可在 Modellix 设置中重新开启。",
|
|
2961
3740
|
keyRequired: "请先在 Modellix 设置中配置 API Key。",
|
|
2962
3741
|
noModels: "当前没有可用模型,请稍后刷新。",
|
|
@@ -2970,9 +3749,17 @@ const zh = {
|
|
|
2970
3749
|
designNoticeCatalogUnavailable: "Modellix Design 模型目录暂时不可用,请稍后刷新。",
|
|
2971
3750
|
designNoticeCredentialReloaded: "API Key 已更改,Design 模型和参数已重新加载。",
|
|
2972
3751
|
resultsTitle: "结果",
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
3752
|
+
resultsCount: "{count} 条",
|
|
3753
|
+
resultViewLabel: "结果视图",
|
|
3754
|
+
previewTab: "预览",
|
|
3755
|
+
jsonTab: "JSON",
|
|
3756
|
+
noPreview: "当前还没有可预览的媒体结果。",
|
|
3757
|
+
resultNotFound: "未找到对应的生成任务。",
|
|
3758
|
+
resourceNavigation: "媒体结果导航",
|
|
3759
|
+
previousResource: "上一项",
|
|
3760
|
+
nextResource: "下一项",
|
|
3761
|
+
resourcePosition: "第 {current} / {total} 项",
|
|
3762
|
+
addUrlToChat: "添加 URL 到对话框",
|
|
2976
3763
|
noResults: "还没有生成记录。确认参数并生成后,结果会显示在这里。",
|
|
2977
3764
|
running: "生成中",
|
|
2978
3765
|
succeeded: "已完成",
|
|
@@ -2980,10 +3767,10 @@ const zh = {
|
|
|
2980
3767
|
canceled: "已取消",
|
|
2981
3768
|
unknown: "提交结果未知",
|
|
2982
3769
|
expired: "结果已过期",
|
|
2983
|
-
openImage: "
|
|
3770
|
+
openImage: "放大图片",
|
|
2984
3771
|
imageViewerTitle: "生成图片",
|
|
2985
3772
|
close: "关闭",
|
|
2986
|
-
download: "
|
|
3773
|
+
download: "下载",
|
|
2987
3774
|
expiresAt: "有效期至 {time}",
|
|
2988
3775
|
invalidJson: "请输入有效的 JSON。",
|
|
2989
3776
|
invalidParameter: "此参数不符合当前模型的约束。",
|
|
@@ -2994,9 +3781,9 @@ const zh = {
|
|
|
2994
3781
|
generatedAudioPreview: "生成音频结果预览",
|
|
2995
3782
|
jobModel: "模型:{model}",
|
|
2996
3783
|
jobCreated: "创建于 {time}",
|
|
2997
|
-
diagnosticRetryable: "
|
|
3784
|
+
diagnosticRetryable: "插件会继续尝试安全的只读状态查询,但绝不会自动重复生成提交。",
|
|
2998
3785
|
diagnosticCredentialChanged: "此任务属于更早的 API Key,无法继续刷新。",
|
|
2999
|
-
diagnosticSubmitUnknown: "
|
|
3786
|
+
diagnosticSubmitUnknown: "生成提交结果未知,请先检查结果列表,不要重复提交。",
|
|
3000
3787
|
diagnosticGenerationFailed: "生成任务未完成。",
|
|
3001
3788
|
diagnosticResultUnavailable: "生成已完成,但没有可用的结果资源。",
|
|
3002
3789
|
diagnosticCredentialRejected: "刷新任务时 Modellix 拒绝了当前 API Key。",
|
|
@@ -3015,7 +3802,6 @@ const zh = {
|
|
|
3015
3802
|
const en = {
|
|
3016
3803
|
dateLocale: "en-US",
|
|
3017
3804
|
nav: "Modellix",
|
|
3018
|
-
designTab: "Design",
|
|
3019
3805
|
onboardingTitle: "Connect Modellix",
|
|
3020
3806
|
onboardingDescription: "Enter one Modellix API Key to enable Design, LLM models, and Web Tools.",
|
|
3021
3807
|
keyLabel: "Modellix API Key",
|
|
@@ -3032,7 +3818,7 @@ const en = {
|
|
|
3032
3818
|
serviceLlm: "LLM models",
|
|
3033
3819
|
serviceLlmDescription: "Quickly switch between Modellix models in Harness.",
|
|
3034
3820
|
serviceWeb: "Web Tools",
|
|
3035
|
-
serviceWebDescription: "Provide Modellix
|
|
3821
|
+
serviceWebDescription: "Provide automatic Modellix Web Search and Web Fetch tools.",
|
|
3036
3822
|
settingsTitle: "Modellix",
|
|
3037
3823
|
settingsDescription: "One API Key for Design, LLM, and Web Tools.",
|
|
3038
3824
|
credentialTitle: "API Key",
|
|
@@ -3075,13 +3861,13 @@ const en = {
|
|
|
3075
3861
|
errorGeneric: "The operation could not be completed. Try again.",
|
|
3076
3862
|
errorConflict: "Settings changed elsewhere. Refresh and try again.",
|
|
3077
3863
|
errorKeyInvalid: "This API Key is invalid. Check it and enter it again.",
|
|
3078
|
-
errorBilling: "
|
|
3864
|
+
errorBilling: "This request cannot be completed. Check the account status in the Modellix console.",
|
|
3079
3865
|
errorRateLimited: "Too many requests. Wait before retrying manually.",
|
|
3080
3866
|
errorOffline: "Modellix cannot be reached. Check the network and try again.",
|
|
3081
3867
|
errorTimeout: "Modellix timed out. Retry manually later.",
|
|
3082
3868
|
errorServer: "Modellix is temporarily unavailable. Retry manually later.",
|
|
3083
3869
|
errorPolicy: "The current account or environment policy does not allow this operation.",
|
|
3084
|
-
errorSubmitUnknown: "The submission outcome is unknown. Check Results before submitting
|
|
3870
|
+
errorSubmitUnknown: "The submission outcome is unknown. Check Results before submitting again.",
|
|
3085
3871
|
errorAssetExpired: "This result resource has expired and is no longer available.",
|
|
3086
3872
|
errorDesignSchema: "The model parameter definition changed or could not be parsed. Refresh the model and try again.",
|
|
3087
3873
|
designTitle: "Modellix Design",
|
|
@@ -3101,11 +3887,11 @@ const en = {
|
|
|
3101
3887
|
promptPlaceholder: "Describe the image, video motion, or sound…",
|
|
3102
3888
|
parametersTitle: "Parameters",
|
|
3103
3889
|
advancedParameters: "Advanced parameters ({count})",
|
|
3890
|
+
advancedEditor: "Advanced parameter editor",
|
|
3104
3891
|
required: "Required",
|
|
3105
3892
|
optional: "Optional",
|
|
3106
3893
|
requiredMissing: "Complete every required parameter before generating.",
|
|
3107
3894
|
assistantTitle: "Adjust parameters by chat",
|
|
3108
|
-
assistantPaidNotice: "Sending calls a fixed LLM with the same Modellix Key to propose parameter changes and may incur a charge. It never starts media generation.",
|
|
3109
3895
|
assistantPlaceholder: "For example: make it 16:9, eight seconds, and more cinematic",
|
|
3110
3896
|
propose: "Propose parameter changes",
|
|
3111
3897
|
proposing: "Analyzing…",
|
|
@@ -3117,7 +3903,6 @@ const en = {
|
|
|
3117
3903
|
conflicts: "Resolve conflicts before applying",
|
|
3118
3904
|
generate: "Confirm and generate",
|
|
3119
3905
|
generating: "Submitting…",
|
|
3120
|
-
paidNotice: "Generation is billed. Each click submits once and is never retried automatically.",
|
|
3121
3906
|
designDisabled: "Design is disabled. Enable it in Modellix settings.",
|
|
3122
3907
|
keyRequired: "Configure a Modellix API Key in settings first.",
|
|
3123
3908
|
noModels: "No model is currently available. Refresh and try again.",
|
|
@@ -3131,9 +3916,17 @@ const en = {
|
|
|
3131
3916
|
designNoticeCatalogUnavailable: "The Modellix Design model catalog is temporarily unavailable. Refresh it later.",
|
|
3132
3917
|
designNoticeCredentialReloaded: "The API Key changed, so the Design model and parameters were reloaded.",
|
|
3133
3918
|
resultsTitle: "Results",
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3919
|
+
resultsCount: "{count} item(s)",
|
|
3920
|
+
resultViewLabel: "Result view",
|
|
3921
|
+
previewTab: "Preview",
|
|
3922
|
+
jsonTab: "JSON",
|
|
3923
|
+
noPreview: "No media preview is available yet.",
|
|
3924
|
+
resultNotFound: "The requested generation task was not found.",
|
|
3925
|
+
resourceNavigation: "Media result navigation",
|
|
3926
|
+
previousResource: "Previous",
|
|
3927
|
+
nextResource: "Next",
|
|
3928
|
+
resourcePosition: "{current} of {total}",
|
|
3929
|
+
addUrlToChat: "Add URL to chat",
|
|
3137
3930
|
noResults: "No generations yet. Confirm parameters and generate to see results here.",
|
|
3138
3931
|
running: "Running",
|
|
3139
3932
|
succeeded: "Succeeded",
|
|
@@ -3141,10 +3934,10 @@ const en = {
|
|
|
3141
3934
|
canceled: "Canceled",
|
|
3142
3935
|
unknown: "Submission outcome unknown",
|
|
3143
3936
|
expired: "Result expired",
|
|
3144
|
-
openImage: "
|
|
3937
|
+
openImage: "Enlarge image",
|
|
3145
3938
|
imageViewerTitle: "Generated image",
|
|
3146
3939
|
close: "Close",
|
|
3147
|
-
download: "Download
|
|
3940
|
+
download: "Download",
|
|
3148
3941
|
expiresAt: "Available until {time}",
|
|
3149
3942
|
invalidJson: "Enter valid JSON.",
|
|
3150
3943
|
invalidParameter: "This value does not satisfy the current model constraints.",
|
|
@@ -3155,9 +3948,9 @@ const en = {
|
|
|
3155
3948
|
generatedAudioPreview: "Generated audio result preview",
|
|
3156
3949
|
jobModel: "Model: {model}",
|
|
3157
3950
|
jobCreated: "Created {time}",
|
|
3158
|
-
diagnosticRetryable: "The plugin will continue safe read-only status checks, but it never repeats a
|
|
3951
|
+
diagnosticRetryable: "The plugin will continue safe read-only status checks, but it never repeats a generation submission automatically.",
|
|
3159
3952
|
diagnosticCredentialChanged: "This task belongs to an earlier API Key and cannot be refreshed.",
|
|
3160
|
-
diagnosticSubmitUnknown: "The generation submission outcome is unknown. Check Results before submitting
|
|
3953
|
+
diagnosticSubmitUnknown: "The generation submission outcome is unknown. Check Results before submitting again.",
|
|
3161
3954
|
diagnosticGenerationFailed: "The generation did not complete.",
|
|
3162
3955
|
diagnosticResultUnavailable: "The generation completed without a usable result resource.",
|
|
3163
3956
|
diagnosticCredentialRejected: "Modellix rejected the current API Key while refreshing this task.",
|
|
@@ -3177,6 +3970,7 @@ const en = {
|
|
|
3177
3970
|
//#region src/client/SettingsSection.tsx
|
|
3178
3971
|
function ModellixSettingsSection({ controller, t }) {
|
|
3179
3972
|
const state = useResourceState(controller.store);
|
|
3973
|
+
const settingsSectionRef = (0, react.useRef)(null);
|
|
3180
3974
|
const snapshot = state.data;
|
|
3181
3975
|
const [services, setServices] = (0, react.useState)(null);
|
|
3182
3976
|
const [announcement, setAnnouncement] = (0, react.useState)("");
|
|
@@ -3204,6 +3998,9 @@ function ModellixSettingsSection({ controller, t }) {
|
|
|
3204
3998
|
(0, react.useEffect)(() => {
|
|
3205
3999
|
if (snapshot !== null) setServices(snapshot.services);
|
|
3206
4000
|
}, [snapshot?.settingsRevision]);
|
|
4001
|
+
(0, react.useEffect)(() => {
|
|
4002
|
+
setAnnouncement("");
|
|
4003
|
+
}, [t]);
|
|
3207
4004
|
const busy = state.pending !== null;
|
|
3208
4005
|
const saveServices = (0, react.useCallback)(() => {
|
|
3209
4006
|
if (snapshot === null || services === null || busy) return;
|
|
@@ -3219,6 +4016,7 @@ function ModellixSettingsSection({ controller, t }) {
|
|
|
3219
4016
|
t
|
|
3220
4017
|
]);
|
|
3221
4018
|
if (snapshot === null || services === null) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4019
|
+
ref: settingsSectionRef,
|
|
3222
4020
|
className: "mdlx-settings",
|
|
3223
4021
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3224
4022
|
className: "mdlx-live",
|
|
@@ -3239,6 +4037,7 @@ function ModellixSettingsSection({ controller, t }) {
|
|
|
3239
4037
|
const canWriteCredential = credential.writable && credential.source !== "env";
|
|
3240
4038
|
const llmRefreshDisabled = busy || !snapshot.services.llm || !credential.configured;
|
|
3241
4039
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4040
|
+
ref: settingsSectionRef,
|
|
3242
4041
|
className: "mdlx-settings",
|
|
3243
4042
|
children: [
|
|
3244
4043
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", {
|
|
@@ -3277,7 +4076,7 @@ function ModellixSettingsSection({ controller, t }) {
|
|
|
3277
4076
|
type: "button",
|
|
3278
4077
|
variant: !credential.configured || credential.verification === "invalid" ? "primary" : "outline",
|
|
3279
4078
|
disabled: busy,
|
|
3280
|
-
onClick: () => credentialDialogs.
|
|
4079
|
+
onClick: () => credentialDialogs.openCredential(credentialDialogOwner),
|
|
3281
4080
|
children: credential.configured ? t("replaceKey") : t("configureKey")
|
|
3282
4081
|
}), credential.configured && canWriteCredential && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
3283
4082
|
type: "button",
|
|
@@ -3356,7 +4155,8 @@ function ModellixSettingsSection({ controller, t }) {
|
|
|
3356
4155
|
},
|
|
3357
4156
|
onCancel: () => credentialDialogs.dismissCredential(credentialDialogOwner),
|
|
3358
4157
|
laterLabel: credentialRecovery ? "later" : "cancel",
|
|
3359
|
-
t
|
|
4158
|
+
t,
|
|
4159
|
+
externalDialogOwner: settingsSectionRef
|
|
3360
4160
|
}),
|
|
3361
4161
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(RemoveCredentialDialog, {
|
|
3362
4162
|
open: removeOpen,
|
|
@@ -3371,7 +4171,8 @@ function ModellixSettingsSection({ controller, t }) {
|
|
|
3371
4171
|
setAnnouncement(t("saved"));
|
|
3372
4172
|
});
|
|
3373
4173
|
},
|
|
3374
|
-
t
|
|
4174
|
+
t,
|
|
4175
|
+
externalDialogOwner: settingsSectionRef
|
|
3375
4176
|
})
|
|
3376
4177
|
]
|
|
3377
4178
|
});
|
|
@@ -3426,12 +4227,13 @@ function LlmCatalogCard({ snapshot, dateLocale, busy, disabled, onRefresh, t })
|
|
|
3426
4227
|
]
|
|
3427
4228
|
});
|
|
3428
4229
|
}
|
|
3429
|
-
function RemoveCredentialDialog({ open, busy, errorCode, onClose, onConfirm, t }) {
|
|
4230
|
+
function RemoveCredentialDialog({ open, busy, errorCode, onClose, onConfirm, t, externalDialogOwner }) {
|
|
3430
4231
|
const contentRef = (0, react.useRef)(null);
|
|
3431
|
-
const surfaceOpen = useExternalDialogGate(open);
|
|
4232
|
+
const surfaceOpen = useExternalDialogGate(open, externalDialogOwner);
|
|
3432
4233
|
useDialogA11y({
|
|
3433
4234
|
open: surfaceOpen,
|
|
3434
4235
|
container: contentRef,
|
|
4236
|
+
externalDialogOwner,
|
|
3435
4237
|
initialFocusSelector: "[data-mdlx-initial-focus]",
|
|
3436
4238
|
mandatory: false,
|
|
3437
4239
|
onEscape: onClose
|
|
@@ -3505,7 +4307,7 @@ function llmHealthText(health, t) {
|
|
|
3505
4307
|
//#endregion
|
|
3506
4308
|
//#region src/client/styles.ts
|
|
3507
4309
|
const MODELLIX_CLIENT_CSS = String.raw`
|
|
3508
|
-
.mdlx-settings,.mdlx-design,.mdlx-modal-content{font-family:var(--dsw-font-family,inherit);color:var(--dsw-alias-label-primary);box-sizing:border-box}.mdlx-settings *,.mdlx-design *,.mdlx-modal-content *{box-sizing:border-box}
|
|
4310
|
+
.mdlx-settings,.mdlx-design,.mdlx-design-drawer,.mdlx-tool-result,.mdlx-modal-content{font-family:var(--dsw-font-family,inherit);color:var(--dsw-alias-label-primary);box-sizing:border-box}.mdlx-settings *,.mdlx-design *,.mdlx-design-drawer *,.mdlx-tool-result *,.mdlx-modal-content *{box-sizing:border-box}
|
|
3509
4311
|
.mdlx-settings{width:min(100%,760px);min-width:0;display:grid;gap:12px;padding:4px}
|
|
3510
4312
|
.mdlx-heading{display:grid;gap:4px;min-width:0;margin:0 0 8px}.mdlx-heading h2,.mdlx-heading h3,.mdlx-heading p{margin:0;overflow-wrap:anywhere}
|
|
3511
4313
|
.mdlx-heading h2{font-size:20px;line-height:28px;font-weight:500}.mdlx-heading h3{font-size:15px;line-height:22px;font-weight:600}
|
|
@@ -3514,7 +4316,7 @@ const MODELLIX_CLIENT_CSS = String.raw`
|
|
|
3514
4316
|
.mdlx-card-head,.mdlx-status-row,.mdlx-actions,.mdlx-result-head{display:flex;align-items:center;gap:12px;min-width:0;justify-content:space-between;flex-wrap:wrap}
|
|
3515
4317
|
.mdlx-card-head>.mdlx-heading{margin-bottom:0}
|
|
3516
4318
|
.mdlx-status-copy{display:flex;align-items:center;gap:8px;min-width:0}.mdlx-status-copy span{overflow-wrap:anywhere}
|
|
3517
|
-
.mdlx-actions{justify-content:flex-end}.mdlx-actions>*{min-width:0;max-width:100%}.mdlx-actions-start{justify-content:flex-start}.mdlx-grow{flex:1 1 auto}.mdlx-settings button,.mdlx-design button,.mdlx-modal-content button{height:auto;min-height:36px}
|
|
4319
|
+
.mdlx-actions{justify-content:flex-end}.mdlx-actions>*{min-width:0;max-width:100%}.mdlx-actions-start{justify-content:flex-start}.mdlx-grow{flex:1 1 auto}.mdlx-settings button,.mdlx-design button,.mdlx-design-drawer button,.mdlx-tool-result button,.mdlx-modal-content button{height:auto;min-height:36px}
|
|
3518
4320
|
.mdlx-service-list{display:grid;gap:8px}.mdlx-switch-row{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:16px;align-items:center;padding:12px;border-radius:12px;border:1px solid var(--dsw-alias-border-l2)}
|
|
3519
4321
|
.mdlx-switch-copy{display:grid;gap:2px;min-width:0}.mdlx-switch-copy strong{font-size:14px;font-weight:500;overflow-wrap:anywhere}.mdlx-switch-copy span{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:18px;overflow-wrap:anywhere}
|
|
3520
4322
|
.mdlx-switch-target{display:inline-flex;width:24px;height:24px;align-items:center;justify-content:center;justify-self:center}.mdlx-switch{width:24px;height:24px;accent-color:var(--dsw-alias-brand-primary);cursor:pointer}.mdlx-switch:disabled{cursor:not-allowed}
|
|
@@ -3531,25 +4333,28 @@ const MODELLIX_CLIENT_CSS = String.raw`
|
|
|
3531
4333
|
.mdlx-link-button{appearance:none;border:0;padding:0;background:transparent;font:inherit;cursor:pointer}
|
|
3532
4334
|
.mdlx-modal{box-sizing:border-box;width:min(600px,calc(100vw - 48px));max-height:calc(100dvh - 48px);padding:0!important;gap:0!important;border-radius:24px!important;box-shadow:var(--dsw-shadow-lv3)!important;overflow:auto;overscroll-behavior:contain}.mdlx-modal-confirm{width:min(380px,calc(100vw - 48px))}.mdlx-modal-content{width:100%;min-width:0;padding:28px;display:grid;gap:20px;outline:none}.mdlx-modal-content>.mdlx-heading{margin-bottom:0}.mdlx-modal-title{font-size:20px;line-height:28px;font-weight:500;margin:0;overflow-wrap:anywhere}.mdlx-modal-description{font-size:14px;line-height:22px;color:var(--dsw-alias-label-secondary);margin:0;overflow-wrap:anywhere}
|
|
3533
4335
|
.mdlx-design{container-type:inline-size;height:100%;min-height:0;box-sizing:border-box;padding:16px;padding-bottom:max(16px,env(safe-area-inset-bottom));scroll-padding-block-end:max(24px,env(safe-area-inset-bottom));overflow:auto;background:var(--dsw-alias-bg-base)}
|
|
3534
|
-
.mdlx-design-shell{width:100%;min-height:100%;display:grid;grid-template-columns:minmax(
|
|
4336
|
+
.mdlx-design-shell{width:100%;min-height:100%;display:grid;grid-template-columns:minmax(0,1fr);align-content:start;gap:12px}.mdlx-design-pane{min-width:0;border:1px solid var(--dsw-alias-border-l2);border-radius:12px;background:var(--dsw-alias-bg-layer-1);padding:16px;display:flex;flex-direction:column;gap:16px;overflow-wrap:anywhere}
|
|
4337
|
+
.mdlx-design-launcher{height:32px!important;min-height:32px!important;padding:6px 12px!important;border-radius:18px!important;font-size:13px!important;font-weight:400!important;line-height:20px!important}.mdlx-design-launcher .mdlx-launcher-compact{display:none}.mdlx-design-drawer-viewport{position:fixed;inset:0 0 0 auto;width:360px;max-width:100vw;overflow:hidden;pointer-events:none}.mdlx-design-drawer{position:absolute;inset:0 0 0 auto;width:360px;min-width:360px;display:grid;grid-template-rows:auto minmax(0,1fr);border-inline-start:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-base);box-shadow:var(--dsw-shadow-lv2);pointer-events:auto;transform:translateX(0);opacity:1;transition:transform 180ms ease-out,opacity 180ms ease-out}@starting-style{.mdlx-design-drawer{transform:translateX(100%);opacity:.72}}.mdlx-design-drawer-viewport[data-closing="true"] .mdlx-design-drawer{transform:translateX(100%);opacity:.72;pointer-events:none}.mdlx-drawer-header{position:relative;display:grid;gap:0;padding:16px 60px 16px 16px;border-bottom:1px solid var(--dsw-alias-border-l2)}.mdlx-drawer-header>.mdlx-heading{margin:0}.mdlx-drawer-close{position:absolute!important;inset-block-start:12px;inset-inline-end:12px;width:36px!important;min-width:36px!important;height:36px!important;min-height:36px!important;padding:0!important;border-radius:50%!important;justify-content:center}.mdlx-drawer-header-reveal{display:grid;grid-template-rows:0fr;opacity:0;margin-top:0;transition:grid-template-rows 160ms ease,opacity 120ms ease,margin-top 160ms ease}.mdlx-drawer-header-reveal[hidden]{display:none!important}.mdlx-drawer-header-reveal>div{min-height:0;overflow:hidden}.mdlx-drawer-header:hover .mdlx-drawer-header-reveal,.mdlx-drawer-header:focus-within .mdlx-drawer-header-reveal,.mdlx-drawer-header[data-editor-open="true"] .mdlx-drawer-header-reveal{grid-template-rows:1fr;opacity:1;margin-top:12px}.mdlx-drawer-editor-toggle{justify-self:start}.mdlx-drawer-body{min-height:0;overflow:hidden}.mdlx-drawer-body>.mdlx-design{padding:12px}.mdlx-design-editor{display:grid;gap:12px}.mdlx-design-editor[hidden]{display:none}.mdlx-results-summary{cursor:pointer;min-height:40px;display:flex;align-items:center;justify-content:space-between;gap:12px;font-size:15px;font-weight:600;overflow-wrap:anywhere}.mdlx-results-disclosure{display:block}.mdlx-results-summary{margin:-4px 0;padding:4px 0}.mdlx-results-body{padding-top:12px}
|
|
3535
4338
|
.mdlx-design-scroll{display:grid;gap:16px;min-height:0}.mdlx-parameter-list{display:grid;gap:12px}.mdlx-parameter{display:grid;gap:6px;border-top:1px solid var(--dsw-alias-border-l2);padding-top:12px}
|
|
3536
4339
|
.mdlx-advanced{display:grid;gap:12px;border-top:1px solid var(--dsw-alias-border-l2);padding-top:12px}.mdlx-advanced>summary{cursor:pointer;font-size:14px;font-weight:500;min-height:24px;overflow-wrap:anywhere}
|
|
3537
4340
|
.mdlx-proposal{display:grid;gap:12px;border:1px solid var(--dsw-alias-border-l2);border-radius:12px;padding:12px;background:var(--dsw-alias-bg-layer-2)}
|
|
3538
4341
|
.mdlx-generate-block{display:grid;gap:8px;min-width:0}.mdlx-generate-block>p{margin:0}
|
|
3539
4342
|
.mdlx-change-list{display:grid;gap:8px;margin:0;padding:0;list-style:none}.mdlx-change{display:grid;grid-template-columns:minmax(100px,.4fr) minmax(0,1fr);gap:8px;min-width:0;font-size:13px}.mdlx-change>*{min-width:0;overflow-wrap:anywhere}.mdlx-code{font-family:var(--ds-font-family-code,monospace);font-size:12px;overflow-wrap:anywhere}
|
|
3540
4343
|
.mdlx-result-section{display:grid;gap:10px}.mdlx-result-section h3{margin:0;font-size:14px;font-weight:600}.mdlx-result-list{display:grid;gap:12px;margin:0;padding:0;list-style:none}
|
|
3541
|
-
.mdlx-result-card{display:
|
|
3542
|
-
.mdlx-resource-list{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:12px}.mdlx-resource{display:grid;gap:8px;min-width:0}.mdlx-media{display:block;width:100%;max-height:
|
|
3543
|
-
.mdlx-media-audio{min-height:48px}.mdlx-empty{display:grid;place-items:center;min-height:160px;text-align:center;color:var(--dsw-alias-label-secondary);font-size:13px;line-height:20px;padding:24px}
|
|
4344
|
+
.mdlx-result-card{display:block;border:1px solid var(--dsw-alias-border-l2);border-radius:12px;background:var(--dsw-alias-bg-layer-2);overflow:hidden}.mdlx-result-disclosure{display:block}.mdlx-result-card-summary{position:relative;display:grid;gap:8px;min-height:72px;padding:12px 44px 12px 12px;cursor:pointer;list-style:none}.mdlx-result-card-summary::-webkit-details-marker{display:none}.mdlx-result-card-summary::after{content:"";position:absolute;inset-block-start:18px;inset-inline-end:18px;width:8px;height:8px;border-inline-end:2px solid currentColor;border-block-end:2px solid currentColor;transform:rotate(-45deg);transition:transform 160ms ease}.mdlx-result-disclosure[open]>.mdlx-result-card-summary::after{transform:rotate(45deg)}.mdlx-result-card-body{display:grid;gap:12px;padding:0 12px 12px}
|
|
4345
|
+
.mdlx-result-tabs{display:flex;align-items:center;gap:4px;border-bottom:1px solid var(--dsw-alias-border-l2)}.mdlx-result-tab{appearance:none;border:0;border-bottom:2px solid transparent;background:transparent;color:var(--dsw-alias-label-secondary);font:inherit;padding:8px 12px;cursor:pointer}.mdlx-result-tab[aria-selected="true"]{border-bottom-color:var(--dsw-alias-brand-primary);color:var(--dsw-alias-label-primary);font-weight:600}.mdlx-result-panel{display:grid;gap:12px;min-width:0}.mdlx-result-json{max-height:320px;margin:0;padding:12px;border-radius:12px;background:var(--dsw-alias-markdown-code-block,var(--dsw-alias-bg-layer-3));font-family:var(--ds-font-family-code,monospace);font-size:12px;line-height:18px;white-space:pre-wrap;overflow:auto;overflow-wrap:anywhere}.mdlx-resource-list{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:12px}.mdlx-resource{display:grid;gap:8px;min-width:0}.mdlx-resource-nav{display:flex;align-items:center;justify-content:space-between;gap:8px;flex-wrap:wrap}.mdlx-media{display:block;width:100%;max-height:420px;object-fit:contain;border-radius:12px;background:var(--dsw-alias-bg-layer-3)}.mdlx-image-preview-button{appearance:none;width:100%;padding:0;border:0;border-radius:12px;background:transparent;cursor:zoom-in}.mdlx-image-preview-button>.mdlx-media{pointer-events:none}
|
|
4346
|
+
.mdlx-media-audio{min-height:48px}.mdlx-empty{display:grid;place-items:center;min-height:160px;text-align:center;color:var(--dsw-alias-label-secondary);font-size:13px;line-height:20px;padding:24px}.mdlx-empty-compact{min-height:96px}.mdlx-tool-result{display:grid;gap:12px;margin:4px 0 4px 4px;padding:12px;border:1px solid var(--dsw-alias-border-l2);border-radius:12px;background:var(--dsw-alias-bg-layer-1);overflow:hidden}
|
|
3544
4347
|
.mdlx-image-modal{width:min(1000px,calc(100vw - 48px))}.mdlx-image-full{display:block;width:100%;max-height:calc(100dvh - 220px);object-fit:contain;border-radius:12px;background:var(--dsw-alias-bg-layer-3)}
|
|
3545
4348
|
.mdlx-hidden{position:absolute!important;width:1px!important;height:1px!important;padding:0!important;margin:-1px!important;overflow:hidden!important;clip:rect(0,0,0,0)!important;white-space:nowrap!important;border:0!important}
|
|
3546
|
-
.mdlx-input{height:auto;min-height:40px}.mdlx-input:focus-within,.mdlx-textarea:focus-visible,.mdlx-select:focus-visible,.mdlx-native-input:focus-visible,.mdlx-switch:focus-visible,.mdlx-safe-link:focus-visible,.mdlx-modal-content:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}
|
|
4349
|
+
.mdlx-input{height:auto;min-height:40px}.mdlx-input:focus-within,.mdlx-textarea:focus-visible,.mdlx-select:focus-visible,.mdlx-native-input:focus-visible,.mdlx-switch:focus-visible,.mdlx-safe-link:focus-visible,.mdlx-modal-content:focus-visible,.mdlx-result-tab:focus-visible,.mdlx-image-preview-button:focus-visible,.mdlx-drawer-editor-toggle:focus-visible,.mdlx-results-summary:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}.mdlx-result-card-summary:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}
|
|
4350
|
+
@media (min-width:1280px){.mdlx-design-drawer{box-shadow:none}}
|
|
3547
4351
|
@media (max-width:768px){.mdlx-design{padding:12px;padding-bottom:max(12px,env(safe-area-inset-bottom))}.mdlx-design-shell{grid-template-columns:minmax(0,1fr)}.mdlx-design-pane{padding:12px}.mdlx-resource-list{grid-template-columns:minmax(0,1fr)}}
|
|
3548
4352
|
@container (max-width:992px){.mdlx-design-shell{grid-template-columns:minmax(0,1fr)}.mdlx-design-pane{padding:12px}.mdlx-resource-list{grid-template-columns:minmax(0,1fr)}}
|
|
3549
|
-
@media (max-width:560px){.mdlx-modal{width:calc(100vw - 48px)}.mdlx-modal-content{padding:24px}.mdlx-input-row,.mdlx-model-tools{grid-template-columns:minmax(0,1fr)}.mdlx-input-row>button,.mdlx-model-tools button,.mdlx-actions button{width:100%;min-width:0;justify-self:stretch}.mdlx-actions{display:grid;grid-template-columns:minmax(0,1fr)}.mdlx-switch-row{grid-template-columns:minmax(0,1fr) 48px}.mdlx-change{grid-template-columns:minmax(0,1fr)}}
|
|
3550
|
-
@media (
|
|
3551
|
-
@media (
|
|
3552
|
-
@media (
|
|
4353
|
+
@media (max-width:560px){.mdlx-design-launcher{width:40px;min-width:40px;padding-inline:0!important}.mdlx-design-launcher .mdlx-launcher-label{display:none}.mdlx-design-launcher .mdlx-launcher-compact{display:inline}.mdlx-modal{width:calc(100vw - 48px)}.mdlx-modal-content{padding:24px}.mdlx-input-row,.mdlx-model-tools{grid-template-columns:minmax(0,1fr)}.mdlx-input-row>button,.mdlx-model-tools button,.mdlx-actions button{width:100%;min-width:0;justify-self:stretch}.mdlx-actions{display:grid;grid-template-columns:minmax(0,1fr)}.mdlx-switch-row{grid-template-columns:minmax(0,1fr) 48px}.mdlx-change{grid-template-columns:minmax(0,1fr)}.mdlx-design-drawer-viewport,.mdlx-design-drawer{width:100vw;min-width:0}.mdlx-drawer-header{padding:12px 56px 12px 12px}.mdlx-drawer-close{inset-block-start:8px;inset-inline-end:8px}.mdlx-resource-nav{display:grid;grid-template-columns:1fr}.mdlx-resource-nav>*{width:100%;text-align:center}}
|
|
4354
|
+
@media (max-width:360px){.mdlx-design-launcher{position:fixed!important;inset-block-start:92px;inset-inline-end:12px;z-index:10;width:48px;min-width:48px;height:48px;min-height:48px!important;padding:0!important;border-radius:50%!important}}
|
|
4355
|
+
@media (pointer:coarse){.mdlx-design-launcher{height:48px!important;min-height:48px!important}.mdlx-drawer-header-reveal{grid-template-rows:1fr;opacity:1;margin-top:12px}.mdlx-switch-row,.mdlx-switch-target,.mdlx-safe-link{min-width:48px;min-height:48px}.mdlx-settings button,.mdlx-design button,.mdlx-design-drawer button,.mdlx-tool-result button,.mdlx-modal-content button{min-height:48px}.mdlx-input,.mdlx-select,.mdlx-native-input,.mdlx-advanced>summary{min-height:48px}}
|
|
4356
|
+
@media (prefers-reduced-motion:reduce){.mdlx-design-drawer-viewport,.mdlx-design-drawer,.mdlx-settings *,.mdlx-design *,.mdlx-design-drawer *,.mdlx-tool-result *,.mdlx-modal-content *{animation:none!important;transition:none!important;scroll-behavior:auto!important}}
|
|
4357
|
+
@media (forced-colors:active){.mdlx-modal,.mdlx-design-drawer{border:1px solid CanvasText;box-shadow:none!important}.mdlx-card,.mdlx-switch-row,.mdlx-design-pane,.mdlx-result-card,.mdlx-tool-result,.mdlx-proposal,.mdlx-error,.mdlx-info{forced-color-adjust:auto;border:1px solid CanvasText}.mdlx-input,.mdlx-textarea,.mdlx-select,.mdlx-native-input{border-color:CanvasText}.mdlx-safe-link{color:LinkText}.mdlx-input:focus-within,.mdlx-textarea:focus-visible,.mdlx-select:focus-visible,.mdlx-native-input:focus-visible,.mdlx-switch:focus-visible,.mdlx-safe-link:focus-visible,.mdlx-modal-content:focus-visible,.mdlx-result-tab:focus-visible,.mdlx-image-preview-button:focus-visible,.mdlx-drawer-editor-toggle:focus-visible,.mdlx-results-summary:focus-visible,.mdlx-result-card-summary:focus-visible{outline-color:Highlight}}
|
|
3553
4358
|
`;
|
|
3554
4359
|
function installModellixClientStyles(target = typeof document === "undefined" ? void 0 : document) {
|
|
3555
4360
|
if (target === void 0) return () => void 0;
|
|
@@ -3567,6 +4372,11 @@ const MODELLIX_CLIENT_SLOTS = Object.freeze([
|
|
|
3567
4372
|
id: "modellix.credential-recovery",
|
|
3568
4373
|
order: 10
|
|
3569
4374
|
},
|
|
4375
|
+
{
|
|
4376
|
+
name: "shell.overlay",
|
|
4377
|
+
id: "modellix.design-drawer",
|
|
4378
|
+
order: 20
|
|
4379
|
+
},
|
|
3570
4380
|
{
|
|
3571
4381
|
name: "settings.onboarding",
|
|
3572
4382
|
id: "modellix.onboarding",
|
|
@@ -3578,9 +4388,19 @@ const MODELLIX_CLIENT_SLOTS = Object.freeze([
|
|
|
3578
4388
|
order: 30
|
|
3579
4389
|
},
|
|
3580
4390
|
{
|
|
3581
|
-
name: "conversation.
|
|
3582
|
-
id: "modellix.design",
|
|
4391
|
+
name: "conversation.session.header.utilities",
|
|
4392
|
+
id: "modellix.design-launcher",
|
|
3583
4393
|
order: 20
|
|
4394
|
+
},
|
|
4395
|
+
{
|
|
4396
|
+
name: "tool.call.toolview",
|
|
4397
|
+
key: "modellix_media_generate",
|
|
4398
|
+
priority: 20
|
|
4399
|
+
},
|
|
4400
|
+
{
|
|
4401
|
+
name: "tool.call.toolview",
|
|
4402
|
+
key: "modellix_media_get_result",
|
|
4403
|
+
priority: 20
|
|
3584
4404
|
}
|
|
3585
4405
|
]);
|
|
3586
4406
|
//#endregion
|
|
@@ -3588,7 +4408,8 @@ const MODELLIX_CLIENT_SLOTS = Object.freeze([
|
|
|
3588
4408
|
const inject = [
|
|
3589
4409
|
"slots",
|
|
3590
4410
|
"locale",
|
|
3591
|
-
"connection"
|
|
4411
|
+
"connection",
|
|
4412
|
+
"layout"
|
|
3592
4413
|
];
|
|
3593
4414
|
function apply(ctx) {
|
|
3594
4415
|
ctx.effect(() => ctx.locale.register(MODELLIX_LOCALE_NAMESPACE, {
|
|
@@ -3599,6 +4420,7 @@ function apply(ctx) {
|
|
|
3599
4420
|
const t = ctx.locale.bind(MODELLIX_LOCALE_NAMESPACE);
|
|
3600
4421
|
const rpc = new ModellixRpcClient(ctx.connection.rpc);
|
|
3601
4422
|
const settingsController = new SettingsController(rpc);
|
|
4423
|
+
const designDrawer = new DesignDrawerController(rpc, ctx.layout);
|
|
3602
4424
|
ctx.slots.inject("shell.overlay", () => ctx.slots.register({
|
|
3603
4425
|
name: "shell.overlay",
|
|
3604
4426
|
id: "modellix.credential-recovery",
|
|
@@ -3606,6 +4428,16 @@ function apply(ctx) {
|
|
|
3606
4428
|
locale: MODELLIX_LOCALE_NAMESPACE,
|
|
3607
4429
|
inject: () => ({ controller: settingsController })
|
|
3608
4430
|
}, CredentialRecoveryOverlay));
|
|
4431
|
+
ctx.slots.inject("shell.overlay", () => ctx.slots.register({
|
|
4432
|
+
name: "shell.overlay",
|
|
4433
|
+
id: "modellix.design-drawer",
|
|
4434
|
+
order: 20,
|
|
4435
|
+
locale: MODELLIX_LOCALE_NAMESPACE,
|
|
4436
|
+
inject: () => ({
|
|
4437
|
+
drawer: designDrawer,
|
|
4438
|
+
settingsController
|
|
4439
|
+
})
|
|
4440
|
+
}, ModellixDesignDrawer));
|
|
3609
4441
|
ctx.slots.inject("settings.onboarding", () => ctx.slots.register({
|
|
3610
4442
|
name: "settings.onboarding",
|
|
3611
4443
|
id: "modellix.onboarding",
|
|
@@ -3621,17 +4453,27 @@ function apply(ctx) {
|
|
|
3621
4453
|
locale: MODELLIX_LOCALE_NAMESPACE,
|
|
3622
4454
|
inject: () => ({ controller: settingsController })
|
|
3623
4455
|
}, ModellixSettingsSection));
|
|
3624
|
-
ctx.slots.inject("conversation.
|
|
3625
|
-
name: "conversation.
|
|
3626
|
-
id: "modellix.design",
|
|
4456
|
+
ctx.slots.inject("conversation.session.header.utilities", () => ctx.slots.register({
|
|
4457
|
+
name: "conversation.session.header.utilities",
|
|
4458
|
+
id: "modellix.design-launcher",
|
|
3627
4459
|
order: 20,
|
|
3628
|
-
label: () => t("designTab"),
|
|
3629
4460
|
locale: MODELLIX_LOCALE_NAMESPACE,
|
|
3630
|
-
inject: (
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
4461
|
+
inject: () => ({ drawer: designDrawer })
|
|
4462
|
+
}, ModellixDesignLauncher));
|
|
4463
|
+
ctx.slots.inject("tool.call.toolview", () => ctx.slots.register({
|
|
4464
|
+
name: "tool.call.toolview",
|
|
4465
|
+
key: "modellix_media_generate",
|
|
4466
|
+
priority: 20,
|
|
4467
|
+
locale: MODELLIX_LOCALE_NAMESPACE,
|
|
4468
|
+
inject: () => ({ drawer: designDrawer })
|
|
4469
|
+
}, ModellixMediaToolView));
|
|
4470
|
+
ctx.slots.inject("tool.call.toolview", () => ctx.slots.register({
|
|
4471
|
+
name: "tool.call.toolview",
|
|
4472
|
+
key: "modellix_media_get_result",
|
|
4473
|
+
priority: 20,
|
|
4474
|
+
locale: MODELLIX_LOCALE_NAMESPACE,
|
|
4475
|
+
inject: () => ({ drawer: designDrawer })
|
|
4476
|
+
}, ModellixMediaToolView));
|
|
3635
4477
|
}
|
|
3636
4478
|
//#endregion
|
|
3637
4479
|
exports.MODELLIX_CLIENT_SLOTS = MODELLIX_CLIENT_SLOTS;
|