@qilin-agent/client-ui-settings-models 3.1.6 → 3.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/client.js CHANGED
@@ -507,7 +507,7 @@ window.__ModuleLoader__.load({
507
507
  "aria-expanded": props.expanded,
508
508
  title: t("modelAdvanced"),
509
509
  onClick: props.onToggle,
510
- children: props.expanded ? (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconChevronDownOutline14, {}) : (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconChevronRightOutline14, {})
510
+ children: props.expanded ? (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconChevronDownOutlineRegular, {}) : (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconChevronRightOutlineRegular, {})
511
511
  }),
512
512
  (0, react_jsx_runtime.jsx)("button", {
513
513
  type: "button",
@@ -516,7 +516,7 @@ window.__ModuleLoader__.load({
516
516
  title: t("removeModel"),
517
517
  disabled,
518
518
  onClick: props.onRemove,
519
- children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconTrashOutline16, { size: 14 })
519
+ children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconTrashOutlineRegular, { size: 14 })
520
520
  })
521
521
  ]
522
522
  }), props.expanded ? (0, react_jsx_runtime.jsxs)("div", {
@@ -798,7 +798,7 @@ window.__ModuleLoader__.load({
798
798
  onClick: () => {
799
799
  props.onChange([...props.models.map((model) => ({ ...model })), { id: "" }]);
800
800
  },
801
- children: [(0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconPlusOutline16, { size: 14 }), props.t("addModel")]
801
+ children: [(0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconPlusOutlineRegular, { size: 14 }), props.t("addModel")]
802
802
  })
803
803
  ]
804
804
  });
@@ -871,9 +871,12 @@ window.__ModuleLoader__.load({
871
871
  * @returns the model-list editor.
872
872
  */
873
873
  function ModelListEditor(props) {
874
- const { models, onChange, probe, operations, t, disabled } = props;
874
+ const { models, onChange, probe, operations, t, disabled, onBusyChange } = props;
875
875
  const { catalogProvider } = props;
876
876
  const [busy, setBusy] = (0, react.useState)(false);
877
+ (0, react.useEffect)(() => {
878
+ onBusyChange(busy);
879
+ }, [busy, onBusyChange]);
877
880
  const [failure, setFailure] = (0, react.useState)(void 0);
878
881
  const [inheritedCatalog, setInheritedCatalog] = (0, react.useState)(void 0);
879
882
  (0, react.useEffect)(() => {
@@ -1098,7 +1101,7 @@ window.__ModuleLoader__.load({
1098
1101
  onClick: () => {
1099
1102
  onChange([...models, { id: "" }]);
1100
1103
  },
1101
- children: [(0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconPlusOutline16, { size: 14 }), t("addModel")]
1104
+ children: [(0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconPlusOutlineRegular, { size: 14 }), t("addModel")]
1102
1105
  }),
1103
1106
  failure !== void 0 ? (0, react_jsx_runtime.jsx)("p", {
1104
1107
  className: ModelsSection_module_css_default["error"],
@@ -1346,7 +1349,9 @@ window.__ModuleLoader__.load({
1346
1349
  }
1347
1350
  const mirrored = this.describeFace.getSnapshot();
1348
1351
  if (mirrored.view === void 0) {
1349
- this.failLoad(mirrored.error ?? "settings are unavailable in this browser");
1352
+ /* v8 ignore next -- SettingsDescribeFace.ensure settles with a view or the read's error */
1353
+ if (mirrored.error === null) throw new Error("settings describe settled with neither a view nor an error");
1354
+ this.failLoad(mirrored.error);
1350
1355
  return;
1351
1356
  }
1352
1357
  const providers = joinProviderDirectory(registered.value, declared.value);
@@ -1541,7 +1546,7 @@ window.__ModuleLoader__.load({
1541
1546
  * @returns the creation card.
1542
1547
  */
1543
1548
  function CustomProviderCard(props) {
1544
- const { taken, protocols, reasoningLevels, operations, t } = props;
1549
+ const { taken, protocols, reasoningLevels, operations, t, onBusyChange } = props;
1545
1550
  const [openedAt] = (0, react.useState)(() => props.revision);
1546
1551
  const [route, setRoute] = (0, react.useState)("");
1547
1552
  const [displayName, setDisplayName] = (0, react.useState)("");
@@ -1550,6 +1555,14 @@ window.__ModuleLoader__.load({
1550
1555
  const [keyDraft, setKeyDraft] = (0, react.useState)("");
1551
1556
  const [models, setModels] = (0, react.useState)([]);
1552
1557
  const [busy, setBusy] = (0, react.useState)(false);
1558
+ const [listBusy, setListBusy] = (0, react.useState)(false);
1559
+ (0, react.useEffect)(() => {
1560
+ onBusyChange?.(busy || listBusy);
1561
+ }, [
1562
+ busy,
1563
+ listBusy,
1564
+ onBusyChange
1565
+ ]);
1553
1566
  const [failure, setFailure] = (0, react.useState)(void 0);
1554
1567
  /**
1555
1568
  * The profile write landed. Only the key write can still be outstanding, so
@@ -1668,7 +1681,7 @@ window.__ModuleLoader__.load({
1668
1681
  className: ModelsSection_module_css_default["input"],
1669
1682
  type: "text",
1670
1683
  value: baseURL,
1671
- placeholder: t("customBaseUrlPlaceholder"),
1684
+ placeholder: t(protocol === "anthropic-messages" ? "customAnthropicBaseUrlPlaceholder" : "customBaseUrlPlaceholder"),
1672
1685
  "aria-label": t("baseUrl"),
1673
1686
  "aria-invalid": baseUrlInvalid,
1674
1687
  disabled: profileDisabled,
@@ -1736,7 +1749,8 @@ window.__ModuleLoader__.load({
1736
1749
  probeBlocked: baseUrlInvalid ? "customBaseUrlInvalid" : keyFailure === "keyBlank" ? "keyBlankNew" : keyFailure,
1737
1750
  operations,
1738
1751
  t,
1739
- disabled: profileDisabled
1752
+ disabled: profileDisabled,
1753
+ onBusyChange: setListBusy
1740
1754
  }),
1741
1755
  failure !== void 0 ? (0, react_jsx_runtime.jsx)("p", {
1742
1756
  className: ModelsSection_module_css_default["error"],
@@ -1841,8 +1855,16 @@ window.__ModuleLoader__.load({
1841
1855
  const { namespace, schema, settingsPath, operations, t } = props;
1842
1856
  const [draft, setDraft] = (0, react.useState)(() => draftAt(schema, namespace, settingsPath));
1843
1857
  const [keyDraft, setKeyDraft] = (0, react.useState)("");
1844
- const [keyState, setKeyState] = (0, react.useState)(void 0);
1845
1858
  const [busy, setBusy] = (0, react.useState)(false);
1859
+ const [listBusy, setListBusy] = (0, react.useState)(false);
1860
+ const { onBusyChange } = props;
1861
+ (0, react.useEffect)(() => {
1862
+ onBusyChange?.(busy || listBusy);
1863
+ }, [
1864
+ busy,
1865
+ listBusy,
1866
+ onBusyChange
1867
+ ]);
1846
1868
  const [failure, setFailure] = (0, react.useState)(void 0);
1847
1869
  const [committedOriginal, setCommittedOriginal] = (0, react.useState)(() => schema.getPath(namespace.user, settingsPath));
1848
1870
  const [expectedRevision, setExpectedRevision] = (0, react.useState)(() => namespace.revision);
@@ -1861,17 +1883,6 @@ window.__ModuleLoader__.load({
1861
1883
  namespace,
1862
1884
  schema
1863
1885
  ]);
1864
- (0, react.useEffect)(() => {
1865
- let stale = false;
1866
- setKeyState(void 0);
1867
- operations.describeCredential(keyRef).then((described) => {
1868
- if (stale) return;
1869
- setKeyState(described);
1870
- });
1871
- return () => {
1872
- stale = true;
1873
- };
1874
- }, [operations, keyRef]);
1875
1886
  const stringAt = (source, key) => {
1876
1887
  const value = schema.getPath(source, [key]);
1877
1888
  return typeof value === "string" && value.trim().length > 0 ? value : void 0;
@@ -1961,7 +1972,6 @@ window.__ModuleLoader__.load({
1961
1972
  props.t("settingsPathUnresolvable")
1962
1973
  ]
1963
1974
  });
1964
- const keyLocked = keyState?.writable === false;
1965
1975
  /**
1966
1976
  * The catalog beneath the user layer: what the composition entry pinned, or
1967
1977
  * else the schema default that `resolve` would supply. The effective value
@@ -1985,22 +1995,38 @@ window.__ModuleLoader__.load({
1985
1995
  const defaultContextWindow = schema.getPath(fallback, ["defaultContextWindow"]);
1986
1996
  const defaultMaxTokens = schema.getPath(fallback, ["maxTokens"]);
1987
1997
  const defaultInput = schema.getPath(fallback, ["defaultInput"]);
1988
- const namedRef = stringAt(fallback, "apiKeyEnv");
1989
- const nativeAuth = namedRef === void 0 ? props.nativeAuth : void 0;
1998
+ const baseURL = stringAt(fallback, "baseURL") ?? props.defaultBaseURL;
1990
1999
  const endpointEnv = props.baseURLEnv ?? [];
1991
- const baseURL = stringAt(fallback, "baseURL");
1992
2000
  const endpointHint = family === "deepseek" ? t("deepSeekEndpointHint") : baseURL === void 0 && endpointEnv.length > 0 ? t("baseUrlEnvironment").replace("{env}", () => endpointEnv.join(", ")) : void 0;
2001
+ const namedRef = stringAt(fallback, "apiKeyEnv");
2002
+ const nativeAuth = namedRef === void 0 ? props.nativeAuth : void 0;
1993
2003
  const authRefs = namedRef === void 0 ? (nativeAuth?.env ?? []).filter((ref) => !endpointEnv.includes(ref)) : [namedRef];
1994
2004
  const visibleRefs = authRefs.filter((ref) => !ref.toLowerCase().includes("oauth"));
1995
2005
  const keyHint = visibleRefs[0];
1996
- const checkedRefs = authRefs.map((ref) => [ref, props.credentialChecks?.[ref] ?? (ref === keyRef ? keyState : void 0)]);
2006
+ const checkedRefs = authRefs.map((ref) => [ref, props.credentialChecks?.[ref] ?? (ref === namedRef ? props.credential : void 0)]);
1997
2007
  const detected = checkedRefs.find(([, info]) => info?.configured === true);
1998
2008
  const detectedRef = detected?.[0];
1999
2009
  const detectedVisibleRef = detectedRef === void 0 || !visibleRefs.includes(detectedRef) ? void 0 : detectedRef;
2000
2010
  const missingRefs = checkedRefs.length > 0 && checkedRefs.every(([, info]) => info?.configured === false);
2001
2011
  const savedCredential = detected?.[1]?.source === "file";
2002
- const credentialHint = keyDraft.length > 0 || savedCredential || keyHint === void 0 || props.credentialRequired === true || keyLocked ? void 0 : t(detectedRef === void 0 ? missingRefs ? "keyFallbackMissing" : "keyFallbackUnchecked" : detectedVisibleRef === void 0 ? "keyFallbackDetectedHidden" : "keyFallbackDetected").replace("{hint}", () => detectedVisibleRef ?? keyHint);
2003
- const keyPlaceholder = keyLocked ? t("keyEnvLocked") : keyState?.configured === true && props.credentialRequired !== true ? t("keyStored") : savedCredential ? t("keyPlaceholderSaved") : family === "pi-ai" && keyHint !== void 0 && props.credentialRequired !== true ? t("keyPlaceholderNative") : t("keyPlaceholder");
2012
+ const credentialHint = keyDraft.length > 0 || savedCredential || keyHint === void 0 || props.credentialRequired === true ? void 0 : t(detectedRef === void 0 ? missingRefs ? "keyFallbackMissing" : "keyFallbackUnchecked" : detectedVisibleRef === void 0 ? "keyFallbackDetectedHidden" : "keyFallbackDetected").replace("{hint}", () => detectedVisibleRef ?? keyHint);
2013
+ const keyHelp = visibleRefs.length === 0 ? void 0 : t("keyHelp").replace("{env}", () => visibleRefs.join(" / "));
2014
+ const authHelp = keyHelp === void 0 ? null : (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.Tooltip, {
2015
+ label: keyHelp,
2016
+ side: "right",
2017
+ delayMs: 0,
2018
+ focusDelayMs: 0,
2019
+ portal: true,
2020
+ openOnClick: true,
2021
+ children: (0, react_jsx_runtime.jsx)("button", {
2022
+ type: "button",
2023
+ className: ModelsSection_module_css_default["helpButton"],
2024
+ "aria-label": t("authHelp"),
2025
+ children: "?"
2026
+ })
2027
+ });
2028
+ const keylessNativeAuth = nativeAuth?.env.length === 0 && nativeAuth.oauth;
2029
+ const keyPlaceholder = keyHint === void 0 || props.credentialRequired === true ? t("keyPlaceholder") : t(savedCredential ? "keyPlaceholderSaved" : "keyPlaceholderFallback").replace("{hint}", () => keyHint);
2004
2030
  /** What both family editors take: the rows, whose layer owns them, and the two writes. */
2005
2031
  const catalogProps = {
2006
2032
  models,
@@ -2014,12 +2040,12 @@ window.__ModuleLoader__.load({
2014
2040
  setDraft((current) => schema.deletePath(current, ["models"]));
2015
2041
  }
2016
2042
  };
2017
- return (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsxs)("div", {
2043
+ return (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [keylessNativeAuth ? null : (0, react_jsx_runtime.jsxs)("div", {
2018
2044
  className: ModelsSection_module_css_default["field"],
2019
2045
  children: [
2020
- (0, react_jsx_runtime.jsx)("span", {
2046
+ (0, react_jsx_runtime.jsxs)("span", {
2021
2047
  className: ModelsSection_module_css_default["fieldLabel"],
2022
- children: t("keyInput")
2048
+ children: [t("keyInput"), authHelp]
2023
2049
  }),
2024
2050
  (0, react_jsx_runtime.jsx)(ApiKeyInput, {
2025
2051
  t,
@@ -2030,7 +2056,7 @@ window.__ModuleLoader__.load({
2030
2056
  "aria-describedby": credentialHint === void 0 ? void 0 : `${props.provider}-credential-hint`,
2031
2057
  required: props.credentialRequired === true,
2032
2058
  autoFocus: props.autoFocusCredential === true,
2033
- disabled: disabled || keyLocked,
2059
+ disabled,
2034
2060
  onChange: (event) => {
2035
2061
  setKeyDraft(event.target.value);
2036
2062
  }
@@ -2081,7 +2107,7 @@ window.__ModuleLoader__.load({
2081
2107
  className: ModelsSection_module_css_default["input"],
2082
2108
  type: "text",
2083
2109
  value: stringAt(draft, "baseURL") ?? "",
2084
- placeholder: family === "deepseek" ? t("deepSeekBaseUrl") : baseURL === void 0 ? t(endpointEnv.length > 0 ? "baseUrlConfigured" : "baseUrlDefault") : baseURL,
2110
+ placeholder: family === "deepseek" ? t("deepSeekBaseUrl") : baseURL === void 0 ? t(endpointEnv.length > 0 ? "baseUrlConfigured" : "baseUrlDefault") : t("baseUrlPlaceholder").replace("{url}", () => baseURL),
2085
2111
  "aria-describedby": endpointHint === void 0 ? void 0 : `${props.provider}-endpoint-hint`,
2086
2112
  "aria-label": t("baseUrl"),
2087
2113
  disabled,
@@ -2129,7 +2155,8 @@ window.__ModuleLoader__.load({
2129
2155
  defaultInput: Array.isArray(defaultInput) ? defaultInput : void 0,
2130
2156
  probe,
2131
2157
  probeBlocked: keyFailure,
2132
- operations
2158
+ operations,
2159
+ onBusyChange: setListBusy
2133
2160
  })
2134
2161
  ]
2135
2162
  })]
@@ -2171,6 +2198,7 @@ window.__ModuleLoader__.load({
2171
2198
  props.onClose(false);
2172
2199
  },
2173
2200
  onSubmit: () => {
2201
+ props.onSubmitCredential?.();
2174
2202
  apply();
2175
2203
  }
2176
2204
  })
@@ -2199,8 +2227,10 @@ window.__ModuleLoader__.load({
2199
2227
  displayName: target.displayName,
2200
2228
  settingsPath: target.settingsPath,
2201
2229
  ...target.declared === true ? { declared: true } : {},
2230
+ ...target.defaultBaseURL === void 0 ? {} : { defaultBaseURL: target.defaultBaseURL },
2202
2231
  ...target.baseURLEnv === void 0 ? {} : { baseURLEnv: target.baseURLEnv },
2203
2232
  ...target.nativeAuth === void 0 ? {} : { nativeAuth: target.nativeAuth },
2233
+ ...row.credential === void 0 ? {} : { credential: row.credential },
2204
2234
  ...row.credentialChecks === void 0 ? {} : { credentialChecks: row.credentialChecks },
2205
2235
  ...props
2206
2236
  });
@@ -2262,6 +2292,7 @@ window.__ModuleLoader__.load({
2262
2292
  settingsPath: row.entry.settingsPath,
2263
2293
  ...credentialRef === void 0 ? {} : { credentialRef },
2264
2294
  ...row.entry.declared === true ? { declared: true } : {},
2295
+ ...row.entry.defaultBaseURL === void 0 ? {} : { defaultBaseURL: row.entry.defaultBaseURL },
2265
2296
  ...row.entry.baseURLEnv === void 0 ? {} : { baseURLEnv: row.entry.baseURLEnv },
2266
2297
  ...row.entry.nativeAuth === void 0 ? {} : { nativeAuth: row.entry.nativeAuth }
2267
2298
  };
@@ -2307,6 +2338,8 @@ window.__ModuleLoader__.load({
2307
2338
  const [deleteFailure, setDeleteFailure] = (0, react.useState)(void 0);
2308
2339
  const [savedTarget, setSavedTarget] = (0, react.useState)(void 0);
2309
2340
  const [declaring, setDeclaring] = (0, react.useState)(false);
2341
+ /** Whether the add card's editor has a write or an interrogation in flight. */
2342
+ const [addBusy, setAddBusy] = (0, react.useState)(false);
2310
2343
  const [dismissedSetup, setDismissedSetup] = (0, react.useState)(() => /* @__PURE__ */ new Set());
2311
2344
  const announceSaved = (target) => {
2312
2345
  controller.load().then(() => {
@@ -2317,6 +2350,7 @@ window.__ModuleLoader__.load({
2317
2350
  setEditing(void 0);
2318
2351
  setAdding(false);
2319
2352
  setDeclaring(false);
2353
+ setAddBusy(false);
2320
2354
  if (changed) announceSaved(target);
2321
2355
  };
2322
2356
  /**
@@ -2546,6 +2580,7 @@ window.__ModuleLoader__.load({
2546
2580
  className: `${ModelsSection_module_css_default["input"]} ${ModelsSection_module_css_default["selectInput"]}`,
2547
2581
  value: addTarget.provider,
2548
2582
  "aria-label": t("provider"),
2583
+ disabled: addBusy,
2549
2584
  onChange: (event) => {
2550
2585
  const row = addable.find((candidate) => candidate.entry.provider === event.target.value);
2551
2586
  /* v8 ignore next -- the select only lists addable rows */
@@ -2565,6 +2600,7 @@ window.__ModuleLoader__.load({
2565
2600
  namespace: addNamespace,
2566
2601
  schema,
2567
2602
  settingsPath: addTarget.settingsPath,
2603
+ ...addTarget.defaultBaseURL === void 0 ? {} : { defaultBaseURL: addTarget.defaultBaseURL },
2568
2604
  ...addTarget.baseURLEnv === void 0 ? {} : { baseURLEnv: addTarget.baseURLEnv },
2569
2605
  ...addTarget.nativeAuth === void 0 ? {} : { nativeAuth: addTarget.nativeAuth },
2570
2606
  ...addRow?.credentialChecks === void 0 ? {} : { credentialChecks: addRow.credentialChecks },
@@ -2573,7 +2609,8 @@ window.__ModuleLoader__.load({
2573
2609
  readOnly: !state.writable,
2574
2610
  onClose: (changed) => {
2575
2611
  closeEditor(changed, addTarget);
2576
- }
2612
+ },
2613
+ onBusyChange: setAddBusy
2577
2614
  }, addTarget.provider),
2578
2615
  addRow === void 0 ? null : renderSlot("settings.models.provider-card", {
2579
2616
  provider: addRow.entry,
@@ -2613,7 +2650,7 @@ window.__ModuleLoader__.load({
2613
2650
  setAdding(true);
2614
2651
  setEditing(targetOf(first));
2615
2652
  },
2616
- children: [(0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconPlusOutline16, { size: 14 }), t("add")]
2653
+ children: [(0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconPlusOutlineRegular, { size: 14 }), t("add")]
2617
2654
  }), state.namespaces.has("llm-pi-ai") && (0, react_jsx_runtime.jsxs)("button", {
2618
2655
  type: "button",
2619
2656
  className: ModelsSection_module_css_default["addButton"],
@@ -2626,7 +2663,7 @@ window.__ModuleLoader__.load({
2626
2663
  setEditing(void 0);
2627
2664
  setDeclaring(true);
2628
2665
  },
2629
- children: [(0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconPlusOutline16, { size: 14 }), t("customAdd")]
2666
+ children: [(0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconPlusOutlineRegular, { size: 14 }), t("customAdd")]
2630
2667
  })]
2631
2668
  })
2632
2669
  }),
@@ -2829,10 +2866,6 @@ window.__ModuleLoader__.load({
2829
2866
  */
2830
2867
  function createModelsOperations(ctx) {
2831
2868
  return {
2832
- describeCredential: async (ref) => {
2833
- const response = await ctx.remote.credentials.describe([ref]);
2834
- return response.ok ? response.value[ref] : void 0;
2835
- },
2836
2869
  storeCredential: async (ref, value) => {
2837
2870
  const response = await ctx.remote.credentials.set(ref, value);
2838
2871
  return response.ok ? void 0 : response.error.message;
@@ -2920,19 +2953,20 @@ window.__ModuleLoader__.load({
2920
2953
  keyReveal: "Show secret",
2921
2954
  keyHide: "Hide secret",
2922
2955
  keyPlaceholder: "Enter your API key",
2923
- keyPlaceholderNative: "Enter an API key, or leave blank to use environment authentication",
2924
- keyStored: "Configured — enter a new value to replace",
2925
- keyEnvLocked: "Provided by the launch environment (read-only)",
2956
+ keyPlaceholderFallback: "Leave blank to use env as auth ({hint})",
2926
2957
  keyPlaceholderSaved: "Leave blank to use saved credentials",
2927
2958
  keyFallbackMissing: "Env var not detected. Enter an API key, or configure {hint} in your env.",
2928
2959
  keyFallbackDetected: "Env var detected. ({hint})",
2929
2960
  keyFallbackDetectedHidden: "Env var detected.",
2930
2961
  keyFallbackUnchecked: "Environment credential status has not been confirmed.",
2962
+ keyHelp: "Saved credentials are used first. Environment fallbacks shown here, in order: {env}. Sources are launch environment, $cwd/.env, then $QILIN_HOME/.env.",
2963
+ authHelp: "Authentication details",
2931
2964
  customized: "Customized settings",
2932
2965
  baseUrl: "Base URL",
2933
- baseUrlDefault: "Provider default",
2966
+ baseUrlDefault: "No default endpoint",
2934
2967
  baseUrlEnvironment: "Provider endpoint configuration: {env}",
2935
2968
  baseUrlConfigured: "Provider-configured endpoint",
2969
+ baseUrlPlaceholder: "{url}",
2936
2970
  deepSeekBaseUrl: "https://api.deepseek.com/anthropic",
2937
2971
  deepSeekEndpointHint: "Use an endpoint compatible with the configured connection.",
2938
2972
  models: "Models",
@@ -3003,6 +3037,7 @@ window.__ModuleLoader__.load({
3003
3037
  customBaseUrlInvalid: "Enter a valid HTTP or HTTPS URL.",
3004
3038
  customNeedsModels: "A custom provider needs at least one model.",
3005
3039
  customBaseUrlPlaceholder: "https://gateway.example/v1",
3040
+ customAnthropicBaseUrlPlaceholder: "https://gateway.example",
3006
3041
  settingsPathUnresolvable: "unresolvable settings path",
3007
3042
  create: "Create provider",
3008
3043
  creating: "Creating…",
@@ -3044,19 +3079,20 @@ window.__ModuleLoader__.load({
3044
3079
  keyReveal: "显示密钥",
3045
3080
  keyHide: "隐藏密钥",
3046
3081
  keyPlaceholder: "输入 API 密钥",
3047
- keyPlaceholderNative: "输入 API 密钥,或留空使用环境认证",
3048
- keyStored: "已配置——输入新值可替换",
3049
- keyEnvLocked: "由启动环境提供(只读)",
3082
+ keyPlaceholderFallback: "留空使用环境认证({hint})",
3050
3083
  keyPlaceholderSaved: "留空使用已保存凭据",
3051
3084
  keyFallbackMissing: "未检测到环境变量。请填写 API 密钥,或设置环境变量 {hint}。",
3052
3085
  keyFallbackDetected: "已检测到环境变量({hint})",
3053
3086
  keyFallbackDetectedHidden: "已检测到环境变量",
3054
3087
  keyFallbackUnchecked: "环境凭据状态尚未确认",
3088
+ keyHelp: "优先使用已保存的凭据。此处显示的环境后备按以下顺序排列:{env}。来源依次为启动环境、$cwd/.env、$QILIN_HOME/.env。",
3089
+ authHelp: "认证说明",
3055
3090
  customized: "自定义设置",
3056
3091
  baseUrl: "API 地址",
3057
- baseUrlDefault: "提供方默认",
3092
+ baseUrlDefault: "没有默认地址",
3058
3093
  baseUrlEnvironment: "提供方地址配置:{env}",
3059
3094
  baseUrlConfigured: "由提供方配置地址",
3095
+ baseUrlPlaceholder: "{url}",
3060
3096
  deepSeekBaseUrl: "https://api.deepseek.com/anthropic",
3061
3097
  deepSeekEndpointHint: "请填写与当前连接配置兼容的 API 地址。",
3062
3098
  models: "模型目录",
@@ -3127,6 +3163,7 @@ window.__ModuleLoader__.load({
3127
3163
  customBaseUrlInvalid: "请输入有效的 HTTP 或 HTTPS 地址。",
3128
3164
  customNeedsModels: "自定义提供方至少需要一个模型。",
3129
3165
  customBaseUrlPlaceholder: "https://gateway.example/v1",
3166
+ customAnthropicBaseUrlPlaceholder: "https://gateway.example",
3130
3167
  settingsPathUnresolvable: "无法解析设置路径",
3131
3168
  create: "创建提供方",
3132
3169
  creating: "创建中…",
@@ -3138,6 +3175,904 @@ window.__ModuleLoader__.load({
3138
3175
  keyRequired: "请输入 API 密钥后继续。"
3139
3176
  };
3140
3177
  //#endregion
3178
+ //#region ../../../vendor/cosmokit/src/misc.ts
3179
+ /** Return true when a value is `null` or `undefined`. */
3180
+ function isNullable(value) {
3181
+ return value === null || value === void 0;
3182
+ }
3183
+ /** Return true for non-array object values. */
3184
+ function isPlainObject(data) {
3185
+ return data && typeof data === "object" && !Array.isArray(data);
3186
+ }
3187
+ /** Filter object entries and return a new object. */
3188
+ function filterKeys(object, filter) {
3189
+ return Object.fromEntries(Object.entries(object).filter(([key, value]) => filter(key, value)));
3190
+ }
3191
+ /** Map object values while preserving the original key set. */
3192
+ function mapValues(object, transform) {
3193
+ return Object.fromEntries(Object.entries(object).map(([key, value]) => [key, transform(value, key)]));
3194
+ }
3195
+ /** Pick selected keys from an object, optionally including `undefined` values. */
3196
+ function pick(source, keys, forced) {
3197
+ if (!keys) return { ...source };
3198
+ const result = {};
3199
+ for (const key of keys) if (forced || source[key] !== void 0) result[key] = source[key];
3200
+ return result;
3201
+ }
3202
+ //#endregion
3203
+ //#region ../../../vendor/cosmokit/src/volatile.ts
3204
+ /** Shared config references used by schema validators and plugin runtimes. */
3205
+ const write = Symbol.for("cosmokit.volatile.write");
3206
+ function snapshot(value, ancestors = /* @__PURE__ */ new Set()) {
3207
+ if (typeof value === "function") throw new TypeError("volatile config cannot contain functions");
3208
+ if (value === null || typeof value !== "object") return value;
3209
+ if (ancestors.has(value)) throw new TypeError("volatile config cannot contain cycles");
3210
+ ancestors.add(value);
3211
+ try {
3212
+ if (Array.isArray(value)) return Object.freeze(value.map((item) => snapshot(item, ancestors)));
3213
+ if (Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) throw new TypeError("volatile config objects must be plain objects or arrays");
3214
+ return Object.freeze(Object.fromEntries(Object.entries(value).map(([key, item]) => [key, snapshot(item, ancestors)])));
3215
+ } finally {
3216
+ ancestors.delete(value);
3217
+ }
3218
+ }
3219
+ /**
3220
+ * Create a detached reference containing an immutable copy of the supplied data.
3221
+ * @param value - validated config data; class instances and functions are unsupported.
3222
+ * @returns a reference whose value is updated only by its owning runtime.
3223
+ */
3224
+ function createVolatile(value) {
3225
+ let current = snapshot(value);
3226
+ return Object.freeze({
3227
+ get: () => current,
3228
+ [write]: (value) => {
3229
+ current = value;
3230
+ }
3231
+ });
3232
+ }
3233
+ /**
3234
+ * Identify references across ESM/CJS copies of the shared library.
3235
+ * @param value - a parsed config value.
3236
+ * @returns whether the value implements the shared reference protocol.
3237
+ */
3238
+ function isVolatile(value) {
3239
+ return typeof value === "object" && value !== null && write in value;
3240
+ }
3241
+ //#endregion
3242
+ //#region ../../../vendor/cosmokit/src/types.ts
3243
+ /** Test values using `instanceof` with a `toStringTag` fallback. */
3244
+ function is(type, value) {
3245
+ if (arguments.length === 1) return (value) => is(type, value);
3246
+ return type in globalThis && value instanceof globalThis[type] || Object.prototype.toString.call(value).slice(8, -1) === type;
3247
+ }
3248
+ function isArrayBufferLike(value) {
3249
+ return is("ArrayBuffer", value) || is("SharedArrayBuffer", value);
3250
+ }
3251
+ function isArrayBufferSource(value) {
3252
+ return isArrayBufferLike(value) || ArrayBuffer.isView(value);
3253
+ }
3254
+ let Binary;
3255
+ (function(_Binary) {
3256
+ _Binary.is = isArrayBufferLike;
3257
+ _Binary.isSource = isArrayBufferSource;
3258
+ function fromSource(source) {
3259
+ if (ArrayBuffer.isView(source)) return source.buffer.slice(source.byteOffset, source.byteOffset + source.byteLength);
3260
+ else return source;
3261
+ }
3262
+ _Binary.fromSource = fromSource;
3263
+ function toBase64(source) {
3264
+ source = fromSource(source);
3265
+ if (typeof Buffer !== "undefined") return Buffer.from(source).toString("base64");
3266
+ let binary = "";
3267
+ const bytes = new Uint8Array(source);
3268
+ for (let i = 0; i < bytes.byteLength; i++) binary += String.fromCharCode(bytes[i]);
3269
+ return btoa(binary);
3270
+ }
3271
+ _Binary.toBase64 = toBase64;
3272
+ function fromBase64(source) {
3273
+ if (typeof Buffer !== "undefined") return fromSource(Buffer.from(source, "base64"));
3274
+ return Uint8Array.from(atob(source), (c) => c.charCodeAt(0));
3275
+ }
3276
+ _Binary.fromBase64 = fromBase64;
3277
+ function toHex(source) {
3278
+ source = fromSource(source);
3279
+ if (typeof Buffer !== "undefined") return Buffer.from(source).toString("hex");
3280
+ return Array.from(new Uint8Array(source), (byte) => byte.toString(16).padStart(2, "0")).join("");
3281
+ }
3282
+ _Binary.toHex = toHex;
3283
+ function fromHex(source) {
3284
+ if (typeof Buffer !== "undefined") return fromSource(Buffer.from(source, "hex"));
3285
+ const hex = source.length % 2 === 0 ? source : source.slice(0, source.length - 1);
3286
+ const buffer = [];
3287
+ for (let i = 0; i < hex.length; i += 2) buffer.push(parseInt(`${hex[i]}${hex[i + 1]}`, 16));
3288
+ return Uint8Array.from(buffer).buffer;
3289
+ }
3290
+ _Binary.fromHex = fromHex;
3291
+ })(Binary || (Binary = {}));
3292
+ Binary.fromBase64;
3293
+ Binary.toBase64;
3294
+ Binary.fromHex;
3295
+ Binary.toHex;
3296
+ /** Deep-clone common JavaScript values while preserving prototypes and cycles. */
3297
+ function clone(source, refs = /* @__PURE__ */ new Map()) {
3298
+ if (!source || typeof source !== "object") return source;
3299
+ if (is("Date", source)) return new Date(source.valueOf());
3300
+ if (is("RegExp", source)) return new RegExp(source.source, source.flags);
3301
+ if (isArrayBufferLike(source)) return source.slice(0);
3302
+ if (ArrayBuffer.isView(source)) return source.buffer.slice(source.byteOffset, source.byteOffset + source.byteLength);
3303
+ const cached = refs.get(source);
3304
+ if (cached) return cached;
3305
+ if (Array.isArray(source)) {
3306
+ const result = [];
3307
+ refs.set(source, result);
3308
+ source.forEach((value, index) => {
3309
+ result[index] = Reflect.apply(clone, null, [value, refs]);
3310
+ });
3311
+ return result;
3312
+ }
3313
+ const result = Object.create(Object.getPrototypeOf(source));
3314
+ refs.set(source, result);
3315
+ for (const key of Reflect.ownKeys(source)) {
3316
+ const descriptor = { ...Reflect.getOwnPropertyDescriptor(source, key) };
3317
+ if ("value" in descriptor) descriptor.value = Reflect.apply(clone, null, [descriptor.value, refs]);
3318
+ Reflect.defineProperty(result, key, descriptor);
3319
+ }
3320
+ return result;
3321
+ }
3322
+ /**
3323
+ * Compare values recursively, treating two volatile references as equal regardless of value.
3324
+ * Strict comparison distinguishes null/undefined, treats opaque objects by identity,
3325
+ * compares URLs by normalized href, treats array holes as undefined, and considers distinct cyclic structures unequal.
3326
+ * @param a - first value.
3327
+ * @param b - second value.
3328
+ * @param strict - whether to require strict data equality outside volatile references.
3329
+ * @returns whether the values compare equal.
3330
+ */
3331
+ function deepEqual(a, b, strict) {
3332
+ const ancestors = /* @__PURE__ */ new Set();
3333
+ function compare(a, b) {
3334
+ if (a === b) return true;
3335
+ if (isVolatile(a) || isVolatile(b)) return isVolatile(a) && isVolatile(b);
3336
+ if (!strict && isNullable(a) && isNullable(b)) return true;
3337
+ if (typeof a !== typeof b || typeof a !== "object" || !a || !b) return false;
3338
+ if (ancestors.has(a)) return false;
3339
+ function check(test, then) {
3340
+ return test(a) ? test(b) ? then(a, b) : false : test(b) ? false : void 0;
3341
+ }
3342
+ ancestors.add(a);
3343
+ try {
3344
+ return check(Array.isArray, (a, b) => {
3345
+ if (a.length !== b.length) return false;
3346
+ for (let index = 0; index < a.length; index++) if (!compare(a[index], b[index])) return false;
3347
+ return true;
3348
+ }) ?? check(is("Date"), (a, b) => a.valueOf() === b.valueOf()) ?? check(is("URL"), (a, b) => a.href === b.href) ?? check(is("RegExp"), (a, b) => a.source === b.source && a.flags === b.flags) ?? check(isArrayBufferLike, (a, b) => {
3349
+ if (a.byteLength !== b.byteLength) return false;
3350
+ const viewA = new Uint8Array(a);
3351
+ const viewB = new Uint8Array(b);
3352
+ for (let i = 0; i < viewA.length; i++) if (viewA[i] !== viewB[i]) return false;
3353
+ return true;
3354
+ }) ?? ((!strict || [a, b].every((value) => Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null)) && Object.keys({
3355
+ ...a,
3356
+ ...b
3357
+ }).every((key) => compare(a[key], b[key])));
3358
+ } finally {
3359
+ ancestors.delete(a);
3360
+ }
3361
+ }
3362
+ return compare(a, b);
3363
+ }
3364
+ //#endregion
3365
+ //#region ../../../vendor/cosmokit/src/time.ts
3366
+ let Time;
3367
+ (function(_Time) {
3368
+ _Time.millisecond = 1;
3369
+ const second = _Time.second = 1e3;
3370
+ const minute = _Time.minute = second * 60;
3371
+ const hour = _Time.hour = minute * 60;
3372
+ const day = _Time.day = hour * 24;
3373
+ const week = _Time.week = day * 7;
3374
+ let timezoneOffset = (/* @__PURE__ */ new Date()).getTimezoneOffset();
3375
+ function setTimezoneOffset(offset) {
3376
+ timezoneOffset = offset;
3377
+ }
3378
+ _Time.setTimezoneOffset = setTimezoneOffset;
3379
+ function getTimezoneOffset() {
3380
+ return timezoneOffset;
3381
+ }
3382
+ _Time.getTimezoneOffset = getTimezoneOffset;
3383
+ function getDateNumber(date = /* @__PURE__ */ new Date(), offset) {
3384
+ if (typeof date === "number") date = new Date(date);
3385
+ if (offset === void 0) offset = timezoneOffset;
3386
+ return Math.floor((date.valueOf() / minute - offset) / 1440);
3387
+ }
3388
+ _Time.getDateNumber = getDateNumber;
3389
+ function fromDateNumber(value, offset) {
3390
+ const date = new Date(value * day);
3391
+ if (offset === void 0) offset = timezoneOffset;
3392
+ return new Date(+date + offset * minute);
3393
+ }
3394
+ _Time.fromDateNumber = fromDateNumber;
3395
+ const numeric = /\d+(?:\.\d+)?/.source;
3396
+ const timeRegExp = new RegExp(`^${[
3397
+ "w(?:eek(?:s)?)?",
3398
+ "d(?:ay(?:s)?)?",
3399
+ "h(?:our(?:s)?)?",
3400
+ "m(?:in(?:ute)?(?:s)?)?",
3401
+ "s(?:ec(?:ond)?(?:s)?)?"
3402
+ ].map((unit) => `(${numeric}${unit})?`).join("")}$`);
3403
+ function parseTime(source) {
3404
+ const capture = timeRegExp.exec(source);
3405
+ if (!capture) return 0;
3406
+ return (parseFloat(capture[1]) * week || 0) + (parseFloat(capture[2]) * day || 0) + (parseFloat(capture[3]) * hour || 0) + (parseFloat(capture[4]) * minute || 0) + (parseFloat(capture[5]) * second || 0);
3407
+ }
3408
+ _Time.parseTime = parseTime;
3409
+ function parseDate(date) {
3410
+ const parsed = parseTime(date);
3411
+ if (parsed) date = Date.now() + parsed;
3412
+ else if (/^\d{1,2}(:\d{1,2}){1,2}$/.test(date)) date = `${(/* @__PURE__ */ new Date()).toLocaleDateString()}-${date}`;
3413
+ else if (/^\d{1,2}-\d{1,2}-\d{1,2}(:\d{1,2}){1,2}$/.test(date)) date = `${(/* @__PURE__ */ new Date()).getFullYear()}-${date}`;
3414
+ return date ? new Date(date) : /* @__PURE__ */ new Date();
3415
+ }
3416
+ _Time.parseDate = parseDate;
3417
+ function format(ms) {
3418
+ const abs = Math.abs(ms);
3419
+ if (abs >= day - hour / 2) return Math.round(ms / day) + "d";
3420
+ else if (abs >= hour - minute / 2) return Math.round(ms / hour) + "h";
3421
+ else if (abs >= minute - second / 2) return Math.round(ms / minute) + "m";
3422
+ else if (abs >= second) return Math.round(ms / second) + "s";
3423
+ return ms + "ms";
3424
+ }
3425
+ _Time.format = format;
3426
+ function toDigits(source, length = 2) {
3427
+ return source.toString().padStart(length, "0");
3428
+ }
3429
+ _Time.toDigits = toDigits;
3430
+ function template(template, time = /* @__PURE__ */ new Date()) {
3431
+ return template.replace("yyyy", time.getFullYear().toString()).replace("yy", time.getFullYear().toString().slice(2)).replace("MM", toDigits(time.getMonth() + 1)).replace("dd", toDigits(time.getDate())).replace("hh", toDigits(time.getHours())).replace("mm", toDigits(time.getMinutes())).replace("ss", toDigits(time.getSeconds())).replace("SSS", toDigits(time.getMilliseconds(), 3));
3432
+ }
3433
+ _Time.template = template;
3434
+ })(Time || (Time = {}));
3435
+ //#endregion
3436
+ //#region ../../../vendor/schemastery/src/index.ts
3437
+ const kSchema = Symbol.for("schemastery");
3438
+ const kValidationError = Symbol.for("ValidationError");
3439
+ globalThis.__schemastery_index__ ??= 0;
3440
+ globalThis.__schemastery_refs__ = void 0;
3441
+ var ValidationError = class extends TypeError {
3442
+ options;
3443
+ name = "ValidationError";
3444
+ constructor(message, options) {
3445
+ let prefix = "$";
3446
+ for (const segment of options.path || []) if (typeof segment === "string") prefix += "." + segment;
3447
+ else if (typeof segment === "number") prefix += "[" + segment + "]";
3448
+ else if (typeof segment === "symbol") prefix += `[Symbol(${segment.toString()})]`;
3449
+ if (prefix.startsWith(".")) prefix = prefix.slice(1);
3450
+ super((prefix === "$" ? "" : `${prefix} `) + message);
3451
+ this.options = options;
3452
+ }
3453
+ static is(error) {
3454
+ return !!error?.[kValidationError];
3455
+ }
3456
+ };
3457
+ Object.defineProperty(ValidationError.prototype, kValidationError, { value: true });
3458
+ const Schema = function(options) {
3459
+ const schema = function(data, options = {}) {
3460
+ return Schema.resolve(data, schema, options)[0];
3461
+ };
3462
+ if (options.refs) {
3463
+ const refs = mapValues(options.refs, (options) => new Schema(options));
3464
+ const getRef = (uid) => refs[uid];
3465
+ for (const key in refs) {
3466
+ const options = refs[key];
3467
+ options.sKey = getRef(options.sKey);
3468
+ options.inner = getRef(options.inner);
3469
+ options.list = options.list && options.list.map(getRef);
3470
+ options.dict = options.dict && mapValues(options.dict, getRef);
3471
+ }
3472
+ return refs[options.uid];
3473
+ }
3474
+ Object.assign(schema, options);
3475
+ if (typeof schema.callback === "string") try {
3476
+ schema.callback = new Function("return " + schema.callback)();
3477
+ } catch {}
3478
+ Object.defineProperty(schema, "uid", { value: globalThis.__schemastery_index__++ });
3479
+ Object.setPrototypeOf(schema, Schema.prototype);
3480
+ schema.meta ||= {};
3481
+ schema.toString = schema.toString.bind(schema);
3482
+ return schema;
3483
+ };
3484
+ Schema.prototype = Object.create(Function.prototype);
3485
+ Schema.prototype[kSchema] = true;
3486
+ Object.defineProperty(Schema.prototype, "~standard", { get() {
3487
+ return {
3488
+ version: 1,
3489
+ vendor: "schemastery",
3490
+ validate: (value) => {
3491
+ try {
3492
+ return { value: Schema.resolve(value, this, {})[0] };
3493
+ } catch (error) {
3494
+ if (ValidationError.is(error)) return { issues: [{
3495
+ message: error.message,
3496
+ path: error.options.path
3497
+ }] };
3498
+ throw error;
3499
+ }
3500
+ }
3501
+ };
3502
+ } });
3503
+ Schema.ValidationError = ValidationError;
3504
+ Schema.prototype.toJSON = function toJSON() {
3505
+ if (globalThis.__schemastery_refs__) {
3506
+ globalThis.__schemastery_refs__[this.uid] ??= JSON.parse(JSON.stringify({ ...this }));
3507
+ return this.uid;
3508
+ }
3509
+ globalThis.__schemastery_refs__ = { [this.uid]: { ...this } };
3510
+ globalThis.__schemastery_refs__[this.uid] = JSON.parse(JSON.stringify({ ...this }));
3511
+ const result = {
3512
+ uid: this.uid,
3513
+ refs: globalThis.__schemastery_refs__
3514
+ };
3515
+ globalThis.__schemastery_refs__ = void 0;
3516
+ return result;
3517
+ };
3518
+ Schema.prototype.set = function set(key, value) {
3519
+ this.dict[key] = value;
3520
+ return this;
3521
+ };
3522
+ Schema.prototype.push = function push(value) {
3523
+ this.list.push(value);
3524
+ return this;
3525
+ };
3526
+ function mergeDesc(original, messages) {
3527
+ const result = typeof original === "string" ? { "": original } : { ...original };
3528
+ for (const locale in messages) {
3529
+ const value = messages[locale];
3530
+ if (value?.$description || value?.$desc) result[locale] = value.$description || value.$desc;
3531
+ else if (typeof value === "string") result[locale] = value;
3532
+ }
3533
+ return result;
3534
+ }
3535
+ function getInner(value) {
3536
+ return value?.$value ?? value?.$inner;
3537
+ }
3538
+ function extractKeys(data) {
3539
+ return filterKeys(data ?? {}, (key) => !key.startsWith("$"));
3540
+ }
3541
+ Schema.prototype.i18n = function i18n(messages) {
3542
+ const schema = Schema(this);
3543
+ const desc = mergeDesc(schema.meta.description, messages);
3544
+ if (Object.keys(desc).length) schema.meta.description = desc;
3545
+ if (schema.dict) schema.dict = mapValues(schema.dict, (inner, key) => {
3546
+ return inner.i18n(mapValues(messages, (data) => getInner(data)?.[key] ?? data?.[key]));
3547
+ });
3548
+ if (schema.list) schema.list = schema.list.map((inner, index) => {
3549
+ return inner.i18n(mapValues(messages, (data = {}) => {
3550
+ if (Array.isArray(getInner(data))) return getInner(data)[index];
3551
+ if (Array.isArray(data)) return data[index];
3552
+ return extractKeys(data);
3553
+ }));
3554
+ });
3555
+ if (schema.inner) schema.inner = schema.inner.i18n(mapValues(messages, (data) => {
3556
+ if (getInner(data)) return getInner(data);
3557
+ return extractKeys(data);
3558
+ }));
3559
+ if (schema.sKey) schema.sKey = schema.sKey.i18n(mapValues(messages, (data) => data?.$key));
3560
+ return schema;
3561
+ };
3562
+ Schema.prototype.extra = function extra(key, value) {
3563
+ const schema = Schema(this);
3564
+ schema.meta = {
3565
+ ...schema.meta,
3566
+ [key]: value
3567
+ };
3568
+ return schema;
3569
+ };
3570
+ for (const key of [
3571
+ "required",
3572
+ "disabled",
3573
+ "collapse",
3574
+ "hidden",
3575
+ "loose"
3576
+ ]) Object.assign(Schema.prototype, { [key](value = true) {
3577
+ const schema = Schema(this);
3578
+ schema.meta = {
3579
+ ...schema.meta,
3580
+ [key]: value
3581
+ };
3582
+ return schema;
3583
+ } });
3584
+ Schema.prototype.deprecated = function deprecated() {
3585
+ const schema = Schema(this);
3586
+ schema.meta.badges ||= [];
3587
+ schema.meta.badges.push({
3588
+ text: "deprecated",
3589
+ type: "danger"
3590
+ });
3591
+ return schema;
3592
+ };
3593
+ Schema.prototype.experimental = function experimental() {
3594
+ const schema = Schema(this);
3595
+ schema.meta.badges ||= [];
3596
+ schema.meta.badges.push({
3597
+ text: "experimental",
3598
+ type: "warning"
3599
+ });
3600
+ return schema;
3601
+ };
3602
+ Schema.prototype.pattern = function pattern(regexp) {
3603
+ const schema = Schema(this);
3604
+ const pattern = pick(regexp, ["source", "flags"]);
3605
+ schema.meta = {
3606
+ ...schema.meta,
3607
+ pattern
3608
+ };
3609
+ return schema;
3610
+ };
3611
+ Schema.prototype.simplify = function simplify(value) {
3612
+ if (isVolatile(value)) value = value.get();
3613
+ if (deepEqual(value, this.meta.default, this.type === "dict")) return null;
3614
+ if (isNullable(value)) return value;
3615
+ if (this.type === "object" || this.type === "dict") {
3616
+ const result = {};
3617
+ for (const key in value) {
3618
+ const item = (this.type === "object" ? this.dict[key] : this.inner)?.simplify(value[key]);
3619
+ if (this.type === "dict" || !isNullable(item)) result[key] = item;
3620
+ }
3621
+ if (deepEqual(result, this.meta.default, this.type === "dict")) return null;
3622
+ return result;
3623
+ } else if (this.type === "array" || this.type === "tuple") {
3624
+ const result = [];
3625
+ value.forEach((value, index) => {
3626
+ const schema = this.type === "array" ? this.inner : this.list[index];
3627
+ const item = schema ? schema.simplify(value) : value;
3628
+ result.push(item);
3629
+ });
3630
+ return result;
3631
+ } else if (this.type === "intersect") {
3632
+ const result = {};
3633
+ for (const item of this.list) Object.assign(result, item.simplify(value));
3634
+ return result;
3635
+ } else if (this.type === "union") for (const schema of this.list) try {
3636
+ Schema.resolve(value, schema, {});
3637
+ return schema.simplify(value);
3638
+ } catch {}
3639
+ return value;
3640
+ };
3641
+ Schema.prototype.toString = function toString(inline) {
3642
+ return formatters[this.type]?.(this, inline) ?? `Schema<${this.type}>`;
3643
+ };
3644
+ Schema.prototype.role = function role(role, extra) {
3645
+ const schema = Schema(this);
3646
+ schema.meta = {
3647
+ ...schema.meta,
3648
+ role,
3649
+ extra
3650
+ };
3651
+ return schema;
3652
+ };
3653
+ for (const key of [
3654
+ "default",
3655
+ "link",
3656
+ "comment",
3657
+ "description",
3658
+ "max",
3659
+ "min",
3660
+ "step"
3661
+ ]) Object.assign(Schema.prototype, { [key](value) {
3662
+ const schema = Schema(this);
3663
+ schema.meta = {
3664
+ ...schema.meta,
3665
+ [key]: value
3666
+ };
3667
+ return schema;
3668
+ } });
3669
+ Schema.prototype.volatile = function volatile() {
3670
+ if (this.meta.volatile) throw new TypeError("volatile schema is already wrapped");
3671
+ return this.extra("volatile", true);
3672
+ };
3673
+ const resolvers = {};
3674
+ const checkedVolatile = Symbol("checked-volatile-schema");
3675
+ function validateVolatileSchema(schema, path = [], blocked = false, seen = /* @__PURE__ */ new Map()) {
3676
+ const states = seen.get(schema) ?? /* @__PURE__ */ new Set();
3677
+ if (states.has(blocked)) return;
3678
+ states.add(blocked);
3679
+ seen.set(schema, states);
3680
+ if (schema.meta?.volatile && blocked) throw new ValidationError("volatile fields require a fixed object path without an enclosing volatile field", { path });
3681
+ const nested = blocked || !!schema.meta?.volatile;
3682
+ if (schema.dict) for (const [key, child] of Object.entries(schema.dict)) validateVolatileSchema(child, [...path, key], nested, seen);
3683
+ if (schema.sKey) validateVolatileSchema(schema.sKey, [...path, "<key>"], true, seen);
3684
+ if (schema.inner && (schema.type !== "lazy" || schema.inner[kSchema])) validateVolatileSchema(schema.inner, [...path, "*"], true, seen);
3685
+ if (schema.list) for (let index = 0; index < schema.list.length; index++) validateVolatileSchema(schema.list[index], [...path, String(index)], true, seen);
3686
+ }
3687
+ Schema.extend = function extend(type, resolve) {
3688
+ resolvers[type] = resolve;
3689
+ };
3690
+ Schema.resolve = function resolve(data, schema, options = {}, strict = false) {
3691
+ if (!schema) return [data];
3692
+ if (!options[checkedVolatile]) {
3693
+ validateVolatileSchema(schema, options.path);
3694
+ options = {
3695
+ ...options,
3696
+ [checkedVolatile]: true
3697
+ };
3698
+ }
3699
+ if (schema.meta?.volatile) {
3700
+ const inner = Schema(schema);
3701
+ inner.meta = {
3702
+ ...schema.meta,
3703
+ volatile: false
3704
+ };
3705
+ const [value, adapted] = Schema.resolve(data, inner, options, strict);
3706
+ try {
3707
+ return [createVolatile(value), adapted];
3708
+ } catch (error) {
3709
+ throw new ValidationError(error instanceof Error ? error.message : String(error), options);
3710
+ }
3711
+ }
3712
+ if (options.ignore?.(data, schema)) return [data];
3713
+ if (isNullable(data) && schema.type !== "lazy") {
3714
+ if (schema.meta.required) throw new ValidationError(`missing required value`, options);
3715
+ let current = schema;
3716
+ let fallback = schema.meta.default;
3717
+ while (current?.type === "intersect" && isNullable(fallback)) {
3718
+ current = current.list[0];
3719
+ fallback = current?.meta.default;
3720
+ }
3721
+ if (isNullable(fallback)) return [data];
3722
+ data = clone(fallback);
3723
+ }
3724
+ const callback = resolvers[schema.type];
3725
+ if (!callback) throw new ValidationError(`unsupported type "${schema.type}"`, options);
3726
+ try {
3727
+ return callback(data, schema, options, strict);
3728
+ } catch (error) {
3729
+ if (!schema.meta.loose) throw error;
3730
+ return [schema.meta.default];
3731
+ }
3732
+ };
3733
+ Schema.from = function from(source) {
3734
+ if (isNullable(source)) return Schema.any();
3735
+ else if ([
3736
+ "string",
3737
+ "number",
3738
+ "boolean"
3739
+ ].includes(typeof source)) return Schema.const(source).required();
3740
+ else if (source[kSchema]) return source;
3741
+ else if (typeof source === "function") switch (source) {
3742
+ case String: return Schema.string().required();
3743
+ case Number: return Schema.number().required();
3744
+ case Boolean: return Schema.boolean().required();
3745
+ case Function: return Schema.function().required();
3746
+ default: return Schema.is(source).required();
3747
+ }
3748
+ else throw new TypeError(`cannot infer schema from ${source}`);
3749
+ };
3750
+ Schema.lazy = function lazy(builder) {
3751
+ const toJSON = () => {
3752
+ if (!schema.inner[kSchema]) {
3753
+ schema.inner = schema.builder();
3754
+ schema.inner.meta = {
3755
+ ...schema.meta,
3756
+ ...schema.inner.meta
3757
+ };
3758
+ }
3759
+ return schema.inner.toJSON();
3760
+ };
3761
+ const schema = new Schema({
3762
+ type: "lazy",
3763
+ builder,
3764
+ inner: { toJSON }
3765
+ });
3766
+ return schema;
3767
+ };
3768
+ Schema.natural = function natural() {
3769
+ return Schema.number().step(1).min(0);
3770
+ };
3771
+ Schema.percent = function percent() {
3772
+ return Schema.number().step(.01).min(0).max(1).role("slider");
3773
+ };
3774
+ Schema.date = function date() {
3775
+ return Schema.union([Schema.is(Date), Schema.transform(Schema.string().role("datetime"), (value, options) => {
3776
+ const date = new Date(value);
3777
+ if (isNaN(+date)) throw new ValidationError(`invalid date "${value}"`, options);
3778
+ return date;
3779
+ }, true)]);
3780
+ };
3781
+ Schema.regExp = function regExp(flag = "") {
3782
+ return Schema.union([Schema.is(RegExp), Schema.transform(Schema.string().role("regexp", { flag }), (value, options) => {
3783
+ try {
3784
+ return new RegExp(value, flag);
3785
+ } catch (e) {
3786
+ throw new ValidationError(e.message, options);
3787
+ }
3788
+ }, true)]);
3789
+ };
3790
+ Schema.arrayBuffer = function arrayBuffer(encoding) {
3791
+ return Schema.union([
3792
+ Schema.is(ArrayBuffer),
3793
+ Schema.is(SharedArrayBuffer),
3794
+ Schema.transform(Schema.any(), (value, options) => {
3795
+ if (Binary.isSource(value)) return Binary.fromSource(value);
3796
+ throw new ValidationError(`expected ArrayBufferSource but got ${value}`, options);
3797
+ }, true),
3798
+ ...encoding ? [Schema.transform(Schema.string(), (value, options) => {
3799
+ try {
3800
+ return encoding === "base64" ? Binary.fromBase64(value) : Binary.fromHex(value);
3801
+ } catch (e) {
3802
+ throw new ValidationError(e.message, options);
3803
+ }
3804
+ }, true)] : []
3805
+ ]);
3806
+ };
3807
+ Schema.extend("lazy", (data, schema, options, strict) => {
3808
+ if (!schema.inner[kSchema]) {
3809
+ schema.inner = schema.builder();
3810
+ schema.inner.meta = {
3811
+ ...schema.meta,
3812
+ ...schema.inner.meta
3813
+ };
3814
+ validateVolatileSchema(schema.inner, options.path, true);
3815
+ }
3816
+ return Schema.resolve(data, schema.inner, options, strict);
3817
+ });
3818
+ Schema.extend("any", (data) => {
3819
+ return [data];
3820
+ });
3821
+ Schema.extend("never", (data, _, options) => {
3822
+ throw new ValidationError(`expected nullable but got ${data}`, options);
3823
+ });
3824
+ Schema.extend("const", (data, { value }, options) => {
3825
+ if (deepEqual(data, value)) return [value];
3826
+ throw new ValidationError(`expected ${value} but got ${data}`, options);
3827
+ });
3828
+ function checkWithinRange(data, meta, description, options, skipMin = false) {
3829
+ const { max = Infinity, min = -Infinity } = meta;
3830
+ if (data > max) throw new ValidationError(`expected ${description} <= ${max} but got ${data}`, options);
3831
+ if (data < min && !skipMin) throw new ValidationError(`expected ${description} >= ${min} but got ${data}`, options);
3832
+ }
3833
+ Schema.extend("string", (data, { meta }, options) => {
3834
+ if (typeof data !== "string") throw new ValidationError(`expected string but got ${data}`, options);
3835
+ if (meta.pattern) {
3836
+ const regexp = new RegExp(meta.pattern.source, meta.pattern.flags);
3837
+ if (!regexp.test(data)) throw new ValidationError(`expect string to match regexp ${regexp}`, options);
3838
+ }
3839
+ checkWithinRange(data.length, meta, "string length", options);
3840
+ return [data];
3841
+ });
3842
+ function decimalShift(data, digits) {
3843
+ const str = data.toString();
3844
+ if (str.includes("e")) return data * Math.pow(10, digits);
3845
+ const index = str.indexOf(".");
3846
+ if (index === -1) return data * Math.pow(10, digits);
3847
+ const frac = str.slice(index + 1);
3848
+ const integer = str.slice(0, index);
3849
+ if (frac.length <= digits) return +(integer + frac.padEnd(digits, "0"));
3850
+ return +(integer + frac.slice(0, digits) + "." + frac.slice(digits));
3851
+ }
3852
+ function isMultipleOf(data, min, step) {
3853
+ step = Math.abs(step);
3854
+ if (!/^\d+\.\d+$/.test(step.toString())) return (data - min) % step === 0;
3855
+ const index = step.toString().indexOf(".");
3856
+ const digits = step.toString().slice(index + 1).length;
3857
+ return Math.abs(decimalShift(data, digits) - decimalShift(min, digits)) % decimalShift(step, digits) === 0;
3858
+ }
3859
+ Schema.extend("number", (data, { meta }, options) => {
3860
+ if (typeof data !== "number") throw new ValidationError(`expected number but got ${data}`, options);
3861
+ checkWithinRange(data, meta, "number", options);
3862
+ const { step } = meta;
3863
+ if (step && !isMultipleOf(data, meta.min ?? 0, step)) throw new ValidationError(`expected number multiple of ${step} but got ${data}`, options);
3864
+ return [data];
3865
+ });
3866
+ Schema.extend("boolean", (data, _, options) => {
3867
+ if (typeof data === "boolean") return [data];
3868
+ throw new ValidationError(`expected boolean but got ${data}`, options);
3869
+ });
3870
+ Schema.extend("bitset", (data, { bits, meta }, options) => {
3871
+ let value = 0, keys = [];
3872
+ if (typeof data === "number") {
3873
+ value = data;
3874
+ for (const key in bits) if (data & bits[key]) keys.push(key);
3875
+ } else if (Array.isArray(data)) {
3876
+ keys = data;
3877
+ for (const key of keys) {
3878
+ if (typeof key !== "string") throw new ValidationError(`expected string but got ${key}`, options);
3879
+ if (key in bits) value |= bits[key];
3880
+ }
3881
+ } else throw new ValidationError(`expected number or array but got ${data}`, options);
3882
+ if (value === meta.default) return [value];
3883
+ return [value, keys];
3884
+ });
3885
+ Schema.extend("function", (data, _, options) => {
3886
+ if (typeof data === "function") return [data];
3887
+ throw new ValidationError(`expected function but got ${data}`, options);
3888
+ });
3889
+ Schema.extend("is", (data, { constructor }, options) => {
3890
+ if (typeof constructor === "function") {
3891
+ if (data instanceof constructor) return [data];
3892
+ throw new ValidationError(`expected ${constructor.name} but got ${data}`, options);
3893
+ } else {
3894
+ if (isNullable(data)) throw new ValidationError(`expected ${constructor} but got ${data}`, options);
3895
+ let prototype = Object.getPrototypeOf(data);
3896
+ while (prototype) {
3897
+ if (prototype.constructor?.name === constructor) return [data];
3898
+ prototype = Object.getPrototypeOf(prototype);
3899
+ }
3900
+ throw new ValidationError(`expected ${constructor} but got ${data}`, options);
3901
+ }
3902
+ });
3903
+ function property(data, key, schema, options) {
3904
+ try {
3905
+ const [value, adapted] = Schema.resolve(data[key], schema, {
3906
+ ...options,
3907
+ path: [...options.path || [], key]
3908
+ });
3909
+ if (adapted !== void 0) data[key] = adapted;
3910
+ return value;
3911
+ } catch (e) {
3912
+ if (!options?.autofix) throw e;
3913
+ delete data[key];
3914
+ return schema.meta.volatile ? createVolatile(schema.meta.default) : schema.meta.default;
3915
+ }
3916
+ }
3917
+ Schema.extend("array", (data, { inner, meta }, options) => {
3918
+ if (!Array.isArray(data)) throw new ValidationError(`expected array but got ${data}`, options);
3919
+ checkWithinRange(data.length, meta, "array length", options, !isNullable(inner.meta.default));
3920
+ return [data.map((_, index) => property(data, index, inner, options))];
3921
+ });
3922
+ Schema.extend("dict", (data, { inner, sKey }, options, strict) => {
3923
+ if (!isPlainObject(data)) throw new ValidationError(`expected object but got ${data}`, options);
3924
+ const result = {};
3925
+ for (const key in data) {
3926
+ let rKey;
3927
+ try {
3928
+ rKey = Schema.resolve(key, sKey, options)[0];
3929
+ } catch (error) {
3930
+ if (strict) continue;
3931
+ throw error;
3932
+ }
3933
+ result[rKey] = property(data, key, inner, options);
3934
+ data[rKey] = data[key];
3935
+ if (key !== rKey) delete data[key];
3936
+ }
3937
+ return [result];
3938
+ });
3939
+ Schema.extend("tuple", (data, { list }, options, strict) => {
3940
+ if (!Array.isArray(data)) throw new ValidationError(`expected array but got ${data}`, options);
3941
+ const result = list.map((inner, index) => property(data, index, inner, options));
3942
+ if (strict) return [result];
3943
+ result.push(...data.slice(list.length));
3944
+ return [result];
3945
+ });
3946
+ function merge(result, data) {
3947
+ for (const key in data) {
3948
+ if (key in result) continue;
3949
+ result[key] = data[key];
3950
+ }
3951
+ }
3952
+ Schema.extend("object", (data, { dict }, options, strict) => {
3953
+ if (!isPlainObject(data)) throw new ValidationError(`expected object but got ${data}`, options);
3954
+ const result = {};
3955
+ for (const key in dict) {
3956
+ const value = property(data, key, dict[key], options);
3957
+ if (!isNullable(value) || key in data) result[key] = value;
3958
+ }
3959
+ if (!strict) merge(result, data);
3960
+ return [result];
3961
+ });
3962
+ Schema.extend("union", (data, { list, toString }, options, strict) => {
3963
+ const messages = [];
3964
+ for (const inner of list) try {
3965
+ return Schema.resolve(data, inner, options, strict);
3966
+ } catch (error) {
3967
+ messages.push(error);
3968
+ }
3969
+ throw new ValidationError(`expected ${toString()} but got ${JSON.stringify(data)}`, options);
3970
+ });
3971
+ Schema.extend("intersect", (data, { list, toString }, options, strict) => {
3972
+ if (!list.length) return [data];
3973
+ let result;
3974
+ for (const inner of list) {
3975
+ const value = Schema.resolve(data, inner, options, true)[0];
3976
+ if (isNullable(value)) continue;
3977
+ if (isNullable(result)) result = value;
3978
+ else if (typeof result !== typeof value) throw new ValidationError(`expected ${toString()} but got ${JSON.stringify(data)}`, options);
3979
+ else if (typeof value === "object") merge(result ??= {}, value);
3980
+ else if (result !== value) throw new ValidationError(`expected ${toString()} but got ${JSON.stringify(data)}`, options);
3981
+ }
3982
+ if (!strict && isPlainObject(data)) merge(result, data);
3983
+ return [result];
3984
+ });
3985
+ Schema.extend("transform", (data, { inner, callback, preserve }, options) => {
3986
+ const [result, adapted = data] = Schema.resolve(data, inner, options, true);
3987
+ if (preserve) return [callback(result)];
3988
+ else return [callback(result), callback(adapted)];
3989
+ });
3990
+ const formatters = {};
3991
+ function defineMethod(name, keys, format) {
3992
+ formatters[name] = format;
3993
+ Object.assign(Schema, { [name](...args) {
3994
+ const schema = new Schema({ type: name });
3995
+ keys.forEach((key, index) => {
3996
+ switch (key) {
3997
+ case "sKey":
3998
+ schema.sKey = args[index] ?? Schema.string();
3999
+ break;
4000
+ case "inner":
4001
+ schema.inner = Schema.from(args[index]);
4002
+ break;
4003
+ case "list":
4004
+ schema.list = args[index].map(Schema.from);
4005
+ break;
4006
+ case "dict":
4007
+ schema.dict = mapValues(args[index], Schema.from);
4008
+ break;
4009
+ case "bits":
4010
+ schema.bits = {};
4011
+ for (const key in args[index]) {
4012
+ if (typeof args[index][key] !== "number") continue;
4013
+ schema.bits[key] = args[index][key];
4014
+ }
4015
+ break;
4016
+ case "callback": {
4017
+ const callback = schema.callback = args[index];
4018
+ callback["toJSON"] ||= () => callback.toString();
4019
+ break;
4020
+ }
4021
+ case "constructor": {
4022
+ const constructor = schema.constructor = args[index];
4023
+ if (typeof constructor === "function") constructor["toJSON"] ||= () => constructor["name"];
4024
+ break;
4025
+ }
4026
+ default: schema[key] = args[index];
4027
+ }
4028
+ });
4029
+ if (name === "object" || name === "dict") schema.meta.default = {};
4030
+ else if (name === "array" || name === "tuple") schema.meta.default = [];
4031
+ else if (name === "bitset") schema.meta.default = 0;
4032
+ return schema;
4033
+ } });
4034
+ }
4035
+ defineMethod("is", ["constructor"], ({ constructor }) => {
4036
+ if (typeof constructor === "function") return constructor.name;
4037
+ else return constructor;
4038
+ });
4039
+ defineMethod("any", [], () => "any");
4040
+ defineMethod("never", [], () => "never");
4041
+ defineMethod("const", ["value"], ({ value }) => typeof value === "string" ? JSON.stringify(value) : value);
4042
+ defineMethod("string", [], () => "string");
4043
+ defineMethod("number", [], () => "number");
4044
+ defineMethod("boolean", [], () => "boolean");
4045
+ defineMethod("bitset", ["bits"], () => "bitset");
4046
+ defineMethod("function", [], () => "function");
4047
+ defineMethod("array", ["inner"], ({ inner }) => `${inner.toString(true)}[]`);
4048
+ defineMethod("dict", ["inner", "sKey"], ({ inner, sKey }) => `{ [key: ${sKey.toString()}]: ${inner.toString()} }`);
4049
+ defineMethod("tuple", ["list"], ({ list }) => `[${list.map((inner) => inner.toString()).join(", ")}]`);
4050
+ defineMethod("object", ["dict"], ({ dict }) => {
4051
+ if (Object.keys(dict).length === 0) return "{}";
4052
+ return `{ ${Object.entries(dict).map(([key, inner]) => {
4053
+ return `${key}${inner.meta.required ? "" : "?"}: ${inner.toString()}`;
4054
+ }).join(", ")} }`;
4055
+ });
4056
+ defineMethod("union", ["list"], ({ list }, inline) => {
4057
+ const result = list.map(({ toString: format }) => format()).join(" | ");
4058
+ return inline ? `(${result})` : result;
4059
+ });
4060
+ defineMethod("intersect", ["list"], ({ list }) => {
4061
+ return `${list.map((inner) => inner.toString(true)).join(" & ")}`;
4062
+ });
4063
+ defineMethod("transform", [
4064
+ "inner",
4065
+ "callback",
4066
+ "preserve"
4067
+ ], ({ inner }, isInner) => inner.toString(isInner));
4068
+ //#endregion
4069
+ //#region lib/types/onboarding-config.js
4070
+ /** Public page-bootstrap options shared by the Host and Client halves. */
4071
+ /** Validate Host configuration and its public page-bootstrap payload. */
4072
+ const Config = Schema.object({ credentialOnboarding: Schema.boolean().default(true) });
4073
+ /** Page-global key carrying only the public onboarding options. */
4074
+ const ONBOARDING_CONFIG_GLOBAL = "__QILIN_MODELS_ONBOARDING__";
4075
+ //#endregion
3141
4076
  //#region lib/types/client/index.js
3142
4077
  /** Dictionary namespace owned by this plugin. */
3143
4078
  const NS = "settings.models";
@@ -3172,6 +4107,8 @@ window.__ModuleLoader__.load({
3172
4107
  * @param ctx - client root context.
3173
4108
  */
3174
4109
  function apply(ctx) {
4110
+ const payload = globalThis[ONBOARDING_CONFIG_GLOBAL];
4111
+ const configured = Config(payload === void 0 ? {} : payload);
3175
4112
  ctx.effect(() => ctx.locale.register(NS, {
3176
4113
  zh,
3177
4114
  en
@@ -3227,7 +4164,7 @@ window.__ModuleLoader__.load({
3227
4164
  }
3228
4165
  }
3229
4166
  }, ModelsSection));
3230
- ctx.slots.inject("settings.onboarding", () => ctx.slots.register({
4167
+ if (configured.credentialOnboarding) ctx.slots.inject("settings.onboarding", () => ctx.slots.register({
3231
4168
  name: "settings.onboarding",
3232
4169
  id: "deepseek-official",
3233
4170
  order: 0,