@deepseek-ai/dsh-client-ui-settings-models 0.1.6-alpha.1 → 0.1.7-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.i18n.yaml +2 -2
- package/README.md +15 -8
- package/README.zh.md +26 -19
- package/lib/client.js +1485 -402
- package/lib/index.js +24 -4
- package/lib/types/client/CustomProviderCard.d.ts +13 -5
- package/lib/types/client/DeepSeekModelsEditor.d.ts +1 -1
- package/lib/types/client/DeepSeekOnboardingDialog.d.ts +4 -2
- package/lib/types/client/ModelInputTypes.d.ts +29 -0
- package/lib/types/client/ModelListEditor.d.ts +11 -0
- package/lib/types/client/ModelRow.d.ts +37 -0
- package/lib/types/client/ModelsSection.d.ts +13 -5
- package/lib/types/client/ProviderEditor.d.ts +8 -2
- package/lib/types/client/locales.d.ts +15 -6
- package/lib/types/client/protocol-label.d.ts +16 -0
- package/lib/types/client/slot-contract.d.ts +9 -0
- package/lib/types/client/welcome-store.d.ts +2 -2
- package/lib/types/index.d.ts +10 -3
- package/lib/types/onboarding-config.d.ts +12 -0
- package/lib/types/onboarding-copy.d.ts +1 -1
- package/package.json +17 -13
package/lib/client.js
CHANGED
|
@@ -55,7 +55,7 @@ window.__ModuleLoader__.load({
|
|
|
55
55
|
}
|
|
56
56
|
//#endregion
|
|
57
57
|
//#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-settings-models/src/client/ModelsSection.module.css.mjs
|
|
58
|
-
const css$3 = ".zGbnIq_section{max-width:720px;color:var(--dsw-alias-label-primary);flex-direction:column;gap:12px;display:flex}.zGbnIq_title{color:var(--dsw-alias-label-primary);margin:0;font-size:16px;font-weight:500;line-height:24px}.zGbnIq_intro{color:var(--dsw-alias-label-tertiary);margin:0;font-size:14px;line-height:22px}.zGbnIq_notice{color:var(--dsw-alias-state-warn-label);margin:0;font-size:12px;line-height:18px}.zGbnIq_savedNotice{color:var(--dsw-alias-state-success-primary);margin:0;font-size:12px;line-height:18px}.zGbnIq_rows{flex-direction:column;gap:8px;margin:12px 0 0;padding:0;list-style:none;display:flex}.zGbnIq_rowCard{border:.5px solid var(--dsw-alias-border-l4);border-radius:16px;flex-direction:column;gap:12px;padding:12px 14px;display:flex}.zGbnIq_rowHead{align-items:center;gap:10px;display:flex}.zGbnIq_rowIdentity{align-items:center;gap:6px;min-width:0;display:inline-flex}.zGbnIq_rowName{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:500;line-height:22px}.zGbnIq_rowTag{border:.5px solid var(--dsw-alias-border-l3);color:var(--dsw-alias-label-secondary);border-radius:4px;flex:none;padding:1px 6px;font-size:11px;line-height:16px}.zGbnIq_credentialDot{box-sizing:border-box;corner-shape:round;border-radius:50%;flex:none;width:8px;height:8px;display:inline-block}.zGbnIq_credentialDotConfigured{background:var(--dsw-alias-state-success-primary)}.zGbnIq_credentialDotMissing{background:var(--dsw-alias-state-error-primary)}.zGbnIq_rowActions{align-items:center;gap:4px;margin-left:auto;display:inline-flex}.zGbnIq_primaryButton,.zGbnIq_secondaryButton,.zGbnIq_addButton{box-sizing:border-box;height:36px;font:inherit;cursor:pointer;border:none;border-radius:18px;justify-content:center;align-items:center;gap:4px;padding:0 14px;font-size:14px;line-height:22px;display:inline-flex}.zGbnIq_primaryButton{background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-foreground)}.zGbnIq_primaryButton:hover:not(:disabled){background:var(--dsw-alias-button-primary-hover)}.zGbnIq_secondaryButton,.zGbnIq_addButton{border:.5px solid var(--dsw-alias-border-l3);color:var(--dsw-alias-label-primary);background:0 0}.zGbnIq_secondaryButton:hover:not(:disabled),.zGbnIq_addButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.zGbnIq_secondaryButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-solid)}.zGbnIq_dangerButton{box-sizing:border-box;height:36px;color:var(--dsw-alias-state-error-primary);font:inherit;cursor:pointer;background:0 0;border:none;border-radius:18px;justify-content:center;align-items:center;padding:0 14px;font-size:14px;line-height:22px;display:inline-flex}.zGbnIq_dangerButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger)}.zGbnIq_rowActions .zGbnIq_secondaryButton,.zGbnIq_rowActions .zGbnIq_dangerButton{border-radius:14px;height:28px;padding:0 10px;font-size:12px;line-height:18px}.zGbnIq_primaryButton:disabled,.zGbnIq_secondaryButton:disabled,.zGbnIq_dangerButton:disabled,.zGbnIq_addButton:disabled,.zGbnIq_linkButton:disabled,.zGbnIq_addModelButton:disabled{opacity:.4;cursor:default}.zGbnIq_primaryButton:focus-visible,.zGbnIq_secondaryButton:focus-visible,.zGbnIq_dangerButton:focus-visible,.zGbnIq_addButton:focus-visible,.zGbnIq_linkButton:focus-visible,.zGbnIq_addModelButton:focus-visible,.zGbnIq_iconButton:focus-visible,.zGbnIq_customizedSummary:focus-visible{box-shadow:0 0 0 2px var(--dsw-alias-border-l3);outline:none}.zGbnIq_editor{background:var(--dsw-alias-bg-module-platform);border-radius:12px;flex-direction:column;gap:14px;padding:14px 16px;display:flex}.zGbnIq_editorHeader{align-items:baseline;gap:8px;display:flex}.zGbnIq_editorTitle{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:500;line-height:22px}.zGbnIq_editorRoute{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}.zGbnIq_field{flex-direction:column;gap:6px;display:flex}.zGbnIq_fieldLabel{color:var(--dsw-alias-label-secondary);align-items:center;gap:10px;font-size:12px;font-weight:500;line-height:18px;display:inline-flex}.zGbnIq_linkButton{box-sizing:border-box;height:28px;color:var(--dsw-alias-label-tertiary);font:inherit;cursor:pointer;background:0 0;border:none;border-radius:14px;align-items:center;padding:0 10px;font-size:12px;line-height:18px;display:inline-flex}.zGbnIq_linkButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-secondary)}.zGbnIq_advancedHint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}.zGbnIq_editorActions{justify-content:flex-end;gap:8px;display:flex}.zGbnIq_addBlock{flex-direction:column;gap:12px;display:flex}.zGbnIq_addActions{flex-wrap:wrap;gap:10px;display:flex}.zGbnIq_addButton{border:1px dashed var(--dsw-alias-border-l3);border-radius:16px;flex:1 1 0;gap:6px;min-width:180px;height:44px}.zGbnIq_addCard,.zGbnIq_setupCard{background:var(--dsw-alias-bg-module-platform);border-radius:12px;flex-direction:column;gap:14px;padding:14px 16px;list-style:none;display:flex}.zGbnIq_addCard .zGbnIq_editor,.zGbnIq_setupCard .zGbnIq_editor{background:0 0;padding:0}.zGbnIq_customized{border-top:.5px solid var(--dsw-alias-border-l2);padding-top:10px}.zGbnIq_customizedSummary{cursor:pointer;width:fit-content;color:var(--dsw-alias-label-secondary);border-radius:6px;align-items:center;gap:6px;margin-left:-4px;padding:2px 4px;font-size:12px;font-weight:500;line-height:18px;list-style:none;display:flex}.zGbnIq_customizedSummary::-webkit-details-marker{display:none}.zGbnIq_customizedSummary:before{content:\"\";border-bottom:1.5px solid;border-right:1.5px solid;width:5px;height:5px;transition:transform .12s;transform:rotate(-45deg)translate(-1px,-1px)}.zGbnIq_customized[open]>.zGbnIq_customizedSummary:before{transform:rotate(45deg)translate(-1px,-1px)}.zGbnIq_customizedSummary:hover{color:var(--dsw-alias-label-primary)}.zGbnIq_customizedBody{flex-direction:column;gap:12px;padding-top:12px;display:flex}.zGbnIq_modelCatalog{border-top:.5px solid var(--dsw-alias-border-l2);flex-direction:column;gap:10px;padding-top:12px;display:flex}.zGbnIq_modelCatalogHeading{flex-direction:column;gap:2px;display:flex}.zGbnIq_modelCatalogTitle{color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:500;line-height:18px}.zGbnIq_modelCatalogMeta,.zGbnIq_modelEmpty{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}.zGbnIq_modelList{flex-direction:column;gap:8px;display:flex}.zGbnIq_modelListHead{justify-content:space-between;align-items:flex-start;gap:12px;display:flex}.zGbnIq_modelEntry{border:.5px solid var(--dsw-alias-border-l4);border-radius:10px;padding:6px}.zGbnIq_modelRow{grid-template-columns:minmax(0,1.4fr) minmax(0,1fr) auto auto;align-items:center;gap:6px;display:grid}.zGbnIq_iconButton{box-sizing:border-box;width:28px;height:28px;color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:none;border-radius:6px;justify-content:center;align-items:center;display:inline-flex}.zGbnIq_iconButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.zGbnIq_iconButton:disabled{cursor:default;opacity:.4}.zGbnIq_iconButtonDanger:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger);color:var(--dsw-alias-state-error-primary)}.zGbnIq_modelAdvanced{grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:8px;padding:8px 4px 2px;display:grid}.zGbnIq_modelField{flex-direction:column;gap:4px;display:flex}.zGbnIq_modelFieldLabel{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}.zGbnIq_modelEmpty{border:1px dashed var(--dsw-alias-border-l3);text-align:center;border-radius:8px;padding:12px}.zGbnIq_addModelButton{box-sizing:border-box;border:.5px solid var(--dsw-alias-border-l3);height:28px;color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;background:0 0;border-radius:14px;align-self:flex-start;align-items:center;gap:4px;padding:0 10px;font-size:12px;line-height:18px;display:inline-flex}.zGbnIq_addModelButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.zGbnIq_input{box-sizing:border-box;border:.5px solid var(--dsw-alias-border-l4);width:100%;height:32px;font:inherit;background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);border-radius:8px;padding:0 10px;font-size:14px;line-height:22px}select.zGbnIq_input{cursor:pointer;max-width:240px}.zGbnIq_input:focus{border-color:var(--dsw-alias-brand-primary);outline:none}.zGbnIq_input::placeholder{color:var(--dsw-alias-label-dimmed)}.zGbnIq_input:disabled{opacity:.6;cursor:default}.zGbnIq_selectInput{appearance:none;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12' fill='none'%3E%3Cpath d='M3 4.5L6 7.5L9 4.5' stroke='%2381858C' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\");background-position:right 12px center;background-repeat:no-repeat;background-size:12px 12px;padding-right:32px}.zGbnIq_error{color:var(--dsw-alias-state-error-primary);margin:0;font-size:12px;line-height:18px}.zGbnIq_deleteDialog{width:min(480px,100%)}.zGbnIq_deleteConfirm:not(:disabled){border-color:var(--dsw-alias-state-error-primary);color:var(--dsw-alias-state-error-primary)}.zGbnIq_deleteConfirm:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger)}.zGbnIq_hiddenLabel{clip:rect(0 0 0 0);white-space:nowrap;width:1px;height:1px;position:absolute;overflow:hidden}@media (prefers-reduced-motion:reduce){.zGbnIq_customizedSummary:before,.zGbnIq_switchThumb{transition:none}}.zGbnIq_fetchDialog{--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);max-width:520px}.zGbnIq_candidateToolbar{align-items:center;gap:8px;margin-bottom:6px;display:flex}.zGbnIq_candidateSearch{flex:240px;min-width:0}.zGbnIq_candidateList{flex-direction:column;gap:2px;max-height:320px;margin:0;padding:0;list-style:none;display:flex;overflow-y:auto}.zGbnIq_candidate{border-radius:6px}.zGbnIq_candidateLabel{cursor:pointer;align-items:center;gap:8px;padding:6px 8px;display:flex}.zGbnIq_candidateId{font-family:var(--ds-font-family-code);overflow-wrap:anywhere;flex:auto;font-size:13px}.zGbnIq_candidateEmpty{color:var(--dsw-alias-label-secondary);text-align:center;margin:24px 0;font-size:13px;line-height:20px}";
|
|
58
|
+
const css$3 = ".zGbnIq_section{max-width:720px;color:var(--dsw-alias-label-primary);flex-direction:column;gap:12px;display:flex}.zGbnIq_title{color:var(--dsw-alias-label-primary);margin:0;font-size:16px;font-weight:500;line-height:24px}.zGbnIq_intro{color:var(--dsw-alias-label-tertiary);margin:0;font-size:14px;line-height:22px}.zGbnIq_notice{color:var(--dsw-alias-state-warn-label);margin:0;font-size:12px;line-height:18px}.zGbnIq_savedNotice{color:var(--dsw-alias-state-success-primary);margin:0;font-size:12px;line-height:18px}.zGbnIq_rows{flex-direction:column;gap:8px;margin:12px 0 0;padding:0;list-style:none;display:flex}.zGbnIq_rowCard{border:.5px solid var(--dsw-alias-border-l4);border-radius:16px;flex-direction:column;gap:12px;padding:12px 14px;display:flex}.zGbnIq_rowHead{align-items:center;gap:10px;display:flex}.zGbnIq_rowIdentity{align-items:center;gap:6px;min-width:0;display:inline-flex}.zGbnIq_rowName{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:500;line-height:22px}.zGbnIq_rowTag{border:.5px solid var(--dsw-alias-border-l3);color:var(--dsw-alias-label-secondary);border-radius:4px;flex:none;padding:1px 6px;font-size:11px;line-height:16px}.zGbnIq_credentialDot{box-sizing:border-box;corner-shape:round;border-radius:50%;flex:none;width:8px;height:8px;display:inline-block}.zGbnIq_credentialDotConfigured{background:var(--dsw-alias-state-success-primary)}.zGbnIq_credentialDotMissing{background:var(--dsw-alias-state-error-primary)}.zGbnIq_rowActions{align-items:center;gap:4px;margin-left:auto;display:inline-flex}.zGbnIq_primaryButton,.zGbnIq_secondaryButton,.zGbnIq_addButton{box-sizing:border-box;height:36px;font:inherit;cursor:pointer;border:none;border-radius:18px;justify-content:center;align-items:center;gap:4px;padding:0 14px;font-size:14px;line-height:22px;display:inline-flex}.zGbnIq_primaryButton{background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-foreground)}.zGbnIq_primaryButton:hover:not(:disabled){background:var(--dsw-alias-button-primary-hover)}.zGbnIq_secondaryButton,.zGbnIq_addButton{border:.5px solid var(--dsw-alias-border-l3);color:var(--dsw-alias-label-primary);background:0 0}.zGbnIq_secondaryButton:hover:not(:disabled),.zGbnIq_addButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.zGbnIq_secondaryButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-solid)}.zGbnIq_dangerButton{box-sizing:border-box;height:36px;color:var(--dsw-alias-state-error-primary);font:inherit;cursor:pointer;background:0 0;border:none;border-radius:18px;justify-content:center;align-items:center;padding:0 14px;font-size:14px;line-height:22px;display:inline-flex}.zGbnIq_dangerButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger)}.zGbnIq_rowActions .zGbnIq_secondaryButton,.zGbnIq_rowActions .zGbnIq_dangerButton{border-radius:14px;height:28px;padding:0 10px;font-size:12px;line-height:18px}.zGbnIq_primaryButton:disabled,.zGbnIq_secondaryButton:disabled,.zGbnIq_dangerButton:disabled,.zGbnIq_addButton:disabled,.zGbnIq_linkButton:disabled,.zGbnIq_addModelButton:disabled{opacity:.4;cursor:default}.zGbnIq_primaryButton:focus-visible,.zGbnIq_secondaryButton:focus-visible,.zGbnIq_dangerButton:focus-visible,.zGbnIq_addButton:focus-visible,.zGbnIq_linkButton:focus-visible,.zGbnIq_addModelButton:focus-visible,.zGbnIq_iconButton:focus-visible,.zGbnIq_customizedSummary:focus-visible{box-shadow:0 0 0 2px var(--dsw-alias-border-l3);outline:none}.zGbnIq_editor{background:var(--dsw-alias-bg-module-platform);border-radius:12px;flex-direction:column;gap:14px;padding:14px 16px;display:flex}.zGbnIq_editorHeader{align-items:baseline;gap:8px;display:flex}.zGbnIq_editorTitle{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:500;line-height:22px}.zGbnIq_editorRoute{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}.zGbnIq_field{flex-direction:column;gap:6px;display:flex}.zGbnIq_fieldLabel{color:var(--dsw-alias-label-secondary);align-items:center;gap:10px;font-size:12px;font-weight:500;line-height:18px;display:inline-flex}.zGbnIq_linkButton{box-sizing:border-box;height:28px;color:var(--dsw-alias-label-tertiary);font:inherit;cursor:pointer;background:0 0;border:none;border-radius:14px;align-items:center;padding:0 10px;font-size:12px;line-height:18px;display:inline-flex}.zGbnIq_linkButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-secondary)}.zGbnIq_advancedHint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}.zGbnIq_editorActions{justify-content:flex-end;gap:8px;display:flex}.zGbnIq_addBlock{flex-direction:column;gap:12px;display:flex}.zGbnIq_addActions{display:flex}.zGbnIq_addButton{border:1px dashed var(--dsw-alias-border-l3);border-radius:16px;flex:1 1 0;gap:6px;min-width:180px;height:44px}.zGbnIq_addModes{flex-direction:column;align-items:flex-start;gap:8px;display:flex}.zGbnIq_addPanel{flex-direction:column;gap:14px;display:flex}.zGbnIq_addPanel[hidden]{display:none}.zGbnIq_addCard,.zGbnIq_setupCard{background:var(--dsw-alias-bg-module-platform);border-radius:12px;flex-direction:column;gap:14px;padding:14px 16px;list-style:none;display:flex}.zGbnIq_addCard .zGbnIq_editor,.zGbnIq_setupCard .zGbnIq_editor{background:0 0;padding:0}.zGbnIq_customized{border-top:.5px solid var(--dsw-alias-border-l2);padding-top:10px}.zGbnIq_customizedSummary{cursor:pointer;width:fit-content;color:var(--dsw-alias-label-secondary);border-radius:6px;align-items:center;gap:6px;margin-left:-4px;padding:2px 4px;font-size:12px;font-weight:500;line-height:18px;list-style:none;display:flex}.zGbnIq_customizedSummary::-webkit-details-marker{display:none}.zGbnIq_customizedSummary:before{content:\"\";border-bottom:1.5px solid;border-right:1.5px solid;width:5px;height:5px;transition:transform .12s;transform:rotate(-45deg)translate(-1px,-1px)}.zGbnIq_customized[open]>.zGbnIq_customizedSummary:before{transform:rotate(45deg)translate(-1px,-1px)}.zGbnIq_customizedSummary:hover{color:var(--dsw-alias-label-primary)}.zGbnIq_customizedBody{flex-direction:column;gap:12px;padding-top:12px;display:flex}.zGbnIq_modelCatalog{border-top:.5px solid var(--dsw-alias-border-l2);flex-direction:column;gap:10px;padding-top:12px;display:flex}.zGbnIq_modelCatalogHeading{flex-direction:column;gap:2px;display:flex}.zGbnIq_modelCatalogTitle{color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:500;line-height:18px}.zGbnIq_modelCatalogMeta,.zGbnIq_modelEmpty{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}.zGbnIq_modelList{flex-direction:column;gap:8px;display:flex}.zGbnIq_modelListHead{justify-content:space-between;align-items:flex-start;gap:12px;display:flex}.zGbnIq_modelEntry{border:.5px solid var(--dsw-alias-border-l4);border-radius:10px;padding:6px}.zGbnIq_modelRow{grid-template-columns:minmax(0,1.4fr) minmax(0,1fr) auto auto;align-items:center;gap:6px;display:grid}.zGbnIq_iconButton{box-sizing:border-box;width:28px;height:28px;color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:none;border-radius:6px;justify-content:center;align-items:center;display:inline-flex}.zGbnIq_iconButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.zGbnIq_iconButton:disabled{cursor:default;opacity:.4}.zGbnIq_iconButtonDanger:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger);color:var(--dsw-alias-state-error-primary)}.zGbnIq_modelAdvanced{grid-template-columns:repeat(2,minmax(0,1fr));gap:8px;padding:8px 4px 2px;display:grid}.zGbnIq_modelField{flex-direction:column;gap:4px;min-width:0;display:flex}.zGbnIq_modelInputTypes{border:none;grid-column:1/-1;min-width:0;margin:0;padding:0}.zGbnIq_modelInputTypes legend{margin-bottom:4px;padding:0}.zGbnIq_modelInputChoices{flex-wrap:wrap;align-items:center;gap:16px;min-height:32px;display:flex}.zGbnIq_modelFieldLabel{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}.zGbnIq_modelEmpty{border:1px dashed var(--dsw-alias-border-l3);text-align:center;border-radius:8px;padding:12px}.zGbnIq_addModelButton{box-sizing:border-box;border:.5px solid var(--dsw-alias-border-l3);height:28px;color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;background:0 0;border-radius:14px;align-self:flex-start;align-items:center;gap:4px;padding:0 10px;font-size:12px;line-height:18px;display:inline-flex}.zGbnIq_addModelButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.zGbnIq_input{box-sizing:border-box;border:.5px solid var(--dsw-alias-border-l4);width:100%;height:32px;font:inherit;background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);border-radius:8px;padding:0 10px;font-size:14px;line-height:22px}select.zGbnIq_input{cursor:pointer;max-width:240px}.zGbnIq_input:focus{border-color:var(--dsw-alias-brand-primary);outline:none}.zGbnIq_input::placeholder{color:var(--dsw-alias-label-dimmed)}.zGbnIq_input:disabled{opacity:.6;cursor:default}.zGbnIq_selectInput{appearance:none;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12' fill='none'%3E%3Cpath d='M3 4.5L6 7.5L9 4.5' stroke='%2381858C' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\");background-position:right 12px center;background-repeat:no-repeat;background-size:12px 12px;padding-right:32px}.zGbnIq_error{color:var(--dsw-alias-state-error-primary);margin:0;font-size:12px;line-height:18px}.zGbnIq_deleteDialog{width:min(480px,100%)}.zGbnIq_deleteConfirm:not(:disabled){border-color:var(--dsw-alias-state-error-primary);color:var(--dsw-alias-state-error-primary)}.zGbnIq_deleteConfirm:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger)}.zGbnIq_hiddenLabel{clip:rect(0 0 0 0);white-space:nowrap;width:1px;height:1px;position:absolute;overflow:hidden}@media (prefers-reduced-motion:reduce){.zGbnIq_customizedSummary:before,.zGbnIq_switchThumb{transition:none}}.zGbnIq_fetchDialog{--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);max-width:520px}.zGbnIq_candidateToolbar{align-items:center;gap:8px;margin-bottom:6px;display:flex}.zGbnIq_candidateSearch{flex:240px;min-width:0}.zGbnIq_candidateList{flex-direction:column;gap:2px;max-height:320px;margin:0;padding:0;list-style:none;display:flex;overflow-y:auto}.zGbnIq_candidate{border-radius:6px}.zGbnIq_candidateLabel{cursor:pointer;align-items:center;gap:8px;padding:6px 8px;display:flex}.zGbnIq_candidateId{font-family:var(--ds-font-family-code);overflow-wrap:anywhere;flex:auto;font-size:13px}.zGbnIq_candidateEmpty{color:var(--dsw-alias-label-secondary);text-align:center;margin:24px 0;font-size:13px;line-height:20px}";
|
|
59
59
|
const tagId$3 = "@deepseek-ai/dsh-client-ui-settings-models/ModelsSection.module.css";
|
|
60
60
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$3) + "]") === null) {
|
|
61
61
|
const tag = document.createElement("style");
|
|
@@ -70,6 +70,8 @@ window.__ModuleLoader__.load({
|
|
|
70
70
|
"addButton": "zGbnIq_addButton",
|
|
71
71
|
"addCard": "zGbnIq_addCard",
|
|
72
72
|
"addModelButton": "zGbnIq_addModelButton",
|
|
73
|
+
"addModes": "zGbnIq_addModes",
|
|
74
|
+
"addPanel": "zGbnIq_addPanel",
|
|
73
75
|
"advancedHint": "zGbnIq_advancedHint",
|
|
74
76
|
"candidate": "zGbnIq_candidate",
|
|
75
77
|
"candidateEmpty": "zGbnIq_candidateEmpty",
|
|
@@ -111,6 +113,8 @@ window.__ModuleLoader__.load({
|
|
|
111
113
|
"modelEntry": "zGbnIq_modelEntry",
|
|
112
114
|
"modelField": "zGbnIq_modelField",
|
|
113
115
|
"modelFieldLabel": "zGbnIq_modelFieldLabel",
|
|
116
|
+
"modelInputChoices": "zGbnIq_modelInputChoices",
|
|
117
|
+
"modelInputTypes": "zGbnIq_modelInputTypes",
|
|
114
118
|
"modelList": "zGbnIq_modelList",
|
|
115
119
|
"modelListHead": "zGbnIq_modelListHead",
|
|
116
120
|
"modelRow": "zGbnIq_modelRow",
|
|
@@ -158,6 +162,122 @@ window.__ModuleLoader__.load({
|
|
|
158
162
|
});
|
|
159
163
|
}
|
|
160
164
|
//#endregion
|
|
165
|
+
//#region lib/types/client/ModelInputTypes.js
|
|
166
|
+
/**
|
|
167
|
+
* Edit a nonempty set of input types, displaying inherited types before an override exists.
|
|
168
|
+
* @param props - model declaration and row replacement action.
|
|
169
|
+
* @returns the labeled text and image checkboxes.
|
|
170
|
+
*/
|
|
171
|
+
function ModelInputTypes({ model, field, position, disabled, fallback, t, onChange }) {
|
|
172
|
+
const modalities = model[field];
|
|
173
|
+
const selected = Array.isArray(modalities) && modalities.length > 0 ? modalities : fallback ?? ["text"];
|
|
174
|
+
return (0, react_jsx_runtime.jsxs)("fieldset", {
|
|
175
|
+
className: ModelsSection_module_css_default["modelInputTypes"],
|
|
176
|
+
"aria-label": `${t("modelInputTypes")} ${String(position)}`,
|
|
177
|
+
children: [(0, react_jsx_runtime.jsx)("legend", {
|
|
178
|
+
className: ModelsSection_module_css_default["modelFieldLabel"],
|
|
179
|
+
children: t("modelInputTypes")
|
|
180
|
+
}), (0, react_jsx_runtime.jsx)("div", {
|
|
181
|
+
className: ModelsSection_module_css_default["modelInputChoices"],
|
|
182
|
+
children: ["text", "image"].map((modality) => (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Checkbox, {
|
|
183
|
+
label: t(modality === "text" ? "modelInputText" : "modelInputImage"),
|
|
184
|
+
checked: selected.includes(modality),
|
|
185
|
+
disabled: disabled || selected.length === 1 && selected.includes(modality),
|
|
186
|
+
onChange: (checked) => {
|
|
187
|
+
const nextSelected = ["text", "image"].filter((value) => value === modality ? checked : selected.includes(value));
|
|
188
|
+
const next = {
|
|
189
|
+
...model,
|
|
190
|
+
[field]: nextSelected
|
|
191
|
+
};
|
|
192
|
+
if (field === "inputModalities" && !nextSelected.includes("image")) {
|
|
193
|
+
Reflect.deleteProperty(next, "imagePixelBudget");
|
|
194
|
+
Reflect.deleteProperty(next, "imageMaxBytes");
|
|
195
|
+
}
|
|
196
|
+
onChange(next);
|
|
197
|
+
}
|
|
198
|
+
}, modality))
|
|
199
|
+
})]
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
//#endregion
|
|
203
|
+
//#region lib/types/client/ModelRow.js
|
|
204
|
+
/**
|
|
205
|
+
* Render consistent model identity, capacity, and input-type controls.
|
|
206
|
+
* @param props - drafted fields and their owning editor's actions.
|
|
207
|
+
* @returns one expandable model entry.
|
|
208
|
+
*/
|
|
209
|
+
function ModelRow(props) {
|
|
210
|
+
const { model, position, t, disabled } = props;
|
|
211
|
+
return (0, react_jsx_runtime.jsxs)("div", {
|
|
212
|
+
className: ModelsSection_module_css_default["modelEntry"],
|
|
213
|
+
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
214
|
+
className: ModelsSection_module_css_default["modelRow"],
|
|
215
|
+
children: [
|
|
216
|
+
["id", "name"].map((field) => (0, react_jsx_runtime.jsx)("input", {
|
|
217
|
+
className: ModelsSection_module_css_default["input"],
|
|
218
|
+
type: "text",
|
|
219
|
+
value: typeof model[field] === "string" ? model[field] : "",
|
|
220
|
+
placeholder: t(field === "id" ? "modelId" : "modelName"),
|
|
221
|
+
"aria-label": `${t(field === "id" ? "modelId" : "modelName")} ${String(position)}`,
|
|
222
|
+
disabled,
|
|
223
|
+
onChange: (event) => {
|
|
224
|
+
const value = event.target.value;
|
|
225
|
+
props.onFieldChange(field, field === "name" && value === "" ? void 0 : value);
|
|
226
|
+
},
|
|
227
|
+
onBlur: field === "id" ? (event) => props.onIdBlur?.(event.target.value) : void 0
|
|
228
|
+
}, field)),
|
|
229
|
+
(0, react_jsx_runtime.jsx)("button", {
|
|
230
|
+
type: "button",
|
|
231
|
+
className: ModelsSection_module_css_default["iconButton"],
|
|
232
|
+
"aria-label": `${t("modelAdvanced")} ${String(position)}`,
|
|
233
|
+
"aria-expanded": props.expanded,
|
|
234
|
+
title: t("modelAdvanced"),
|
|
235
|
+
onClick: props.onToggle,
|
|
236
|
+
children: props.expanded ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutlineRegular, {}) : (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronRightOutlineRegular, {})
|
|
237
|
+
}),
|
|
238
|
+
(0, react_jsx_runtime.jsx)("button", {
|
|
239
|
+
type: "button",
|
|
240
|
+
className: `${ModelsSection_module_css_default["iconButton"]} ${ModelsSection_module_css_default["iconButtonDanger"]}`,
|
|
241
|
+
"aria-label": `${t("removeModel")} ${String(position)}`,
|
|
242
|
+
title: t("removeModel"),
|
|
243
|
+
disabled,
|
|
244
|
+
onClick: props.onRemove,
|
|
245
|
+
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutlineRegular, { size: 14 })
|
|
246
|
+
})
|
|
247
|
+
]
|
|
248
|
+
}), props.expanded ? (0, react_jsx_runtime.jsxs)("div", {
|
|
249
|
+
className: ModelsSection_module_css_default["modelAdvanced"],
|
|
250
|
+
children: [["contextWindow", "maxTokens"].map((field) => (0, react_jsx_runtime.jsxs)("label", {
|
|
251
|
+
className: ModelsSection_module_css_default["modelField"],
|
|
252
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
253
|
+
className: ModelsSection_module_css_default["modelFieldLabel"],
|
|
254
|
+
children: t(field)
|
|
255
|
+
}), (0, react_jsx_runtime.jsx)("input", {
|
|
256
|
+
className: ModelsSection_module_css_default["input"],
|
|
257
|
+
type: "text",
|
|
258
|
+
inputMode: "numeric",
|
|
259
|
+
value: props[field].value,
|
|
260
|
+
placeholder: props[field].placeholder,
|
|
261
|
+
"aria-label": `${t(field)} ${String(position)}`,
|
|
262
|
+
disabled,
|
|
263
|
+
onChange: (event) => {
|
|
264
|
+
props[field].onChange(event.target.value);
|
|
265
|
+
},
|
|
266
|
+
onBlur: props[field].onBlur
|
|
267
|
+
})]
|
|
268
|
+
}, field)), (0, react_jsx_runtime.jsx)(ModelInputTypes, {
|
|
269
|
+
model,
|
|
270
|
+
field: props.inputField,
|
|
271
|
+
position,
|
|
272
|
+
fallback: props.inputFallback,
|
|
273
|
+
disabled: disabled || props.inputLoading === true,
|
|
274
|
+
t,
|
|
275
|
+
onChange: props.onChange
|
|
276
|
+
})]
|
|
277
|
+
}) : null]
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
//#endregion
|
|
161
281
|
//#region lib/types/client/DeepSeekModelsEditor.js
|
|
162
282
|
/**
|
|
163
283
|
* Curated editor for the direct DeepSeek adapter's advisory model catalog.
|
|
@@ -252,7 +372,7 @@ window.__ModuleLoader__.load({
|
|
|
252
372
|
}
|
|
253
373
|
/**
|
|
254
374
|
* Render the direct DeepSeek adapter's model catalog: id and display name on
|
|
255
|
-
* each row, capacities behind the row's own disclosure.
|
|
375
|
+
* each row, capacities and input types behind the row's own disclosure.
|
|
256
376
|
* @param props - effective rows plus the array-level override actions.
|
|
257
377
|
* @returns the catalog editor.
|
|
258
378
|
*/
|
|
@@ -320,29 +440,16 @@ window.__ModuleLoader__.load({
|
|
|
320
440
|
return next;
|
|
321
441
|
});
|
|
322
442
|
};
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
value: capacityText(model, index, field),
|
|
334
|
-
placeholder: fallback === void 0 ? props.t(field === "contextWindow" ? "contextWindowPlaceholder" : "maxTokensPlaceholder") : formatCapacity(fallback),
|
|
335
|
-
"aria-label": `${props.t(field === "contextWindow" ? "contextWindow" : "maxTokens")} ${String(index + 1)}`,
|
|
336
|
-
disabled: props.disabled,
|
|
337
|
-
onChange: (event) => {
|
|
338
|
-
const text = event.target.value;
|
|
339
|
-
setEditing((current) => new Map(current).set(`${String(index)}:${field}`, text));
|
|
340
|
-
update(index, field, parseCapacity(text));
|
|
341
|
-
},
|
|
342
|
-
onBlur: () => {
|
|
343
|
-
settleCapacity(index, field);
|
|
344
|
-
}
|
|
345
|
-
})]
|
|
443
|
+
const capacityInput = (model, index, field, fallback) => ({
|
|
444
|
+
value: capacityText(model, index, field),
|
|
445
|
+
placeholder: fallback === void 0 ? props.t(field === "contextWindow" ? "contextWindowPlaceholder" : "maxTokensPlaceholder") : formatCapacity(fallback),
|
|
446
|
+
onChange: (text) => {
|
|
447
|
+
setEditing((current) => new Map(current).set(`${String(index)}:${field}`, text));
|
|
448
|
+
update(index, field, parseCapacity(text));
|
|
449
|
+
},
|
|
450
|
+
onBlur: () => {
|
|
451
|
+
settleCapacity(index, field);
|
|
452
|
+
}
|
|
346
453
|
});
|
|
347
454
|
return (0, react_jsx_runtime.jsxs)("section", {
|
|
348
455
|
className: ModelsSection_module_css_default["modelCatalog"],
|
|
@@ -372,64 +479,31 @@ window.__ModuleLoader__.load({
|
|
|
372
479
|
children: props.t("modelsEmpty")
|
|
373
480
|
}) : (0, react_jsx_runtime.jsx)("div", {
|
|
374
481
|
className: ModelsSection_module_css_default["modelList"],
|
|
375
|
-
children: props.models.map((model, index) => (0, react_jsx_runtime.
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
"aria-label": `${props.t("modelName")} ${String(index + 1)}`,
|
|
401
|
-
disabled: props.disabled,
|
|
402
|
-
onChange: (event) => {
|
|
403
|
-
update(index, "name", event.target.value === "" ? void 0 : event.target.value);
|
|
404
|
-
}
|
|
405
|
-
}),
|
|
406
|
-
(0, react_jsx_runtime.jsx)("button", {
|
|
407
|
-
type: "button",
|
|
408
|
-
className: ModelsSection_module_css_default["iconButton"],
|
|
409
|
-
"aria-label": `${props.t("modelAdvanced")} ${String(index + 1)}`,
|
|
410
|
-
"aria-expanded": expanded.has(index),
|
|
411
|
-
title: props.t("modelAdvanced"),
|
|
412
|
-
onClick: () => {
|
|
413
|
-
toggle(index);
|
|
414
|
-
},
|
|
415
|
-
children: expanded.has(index) ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, {}) : (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronRightOutline14, {})
|
|
416
|
-
}),
|
|
417
|
-
(0, react_jsx_runtime.jsx)("button", {
|
|
418
|
-
type: "button",
|
|
419
|
-
className: `${ModelsSection_module_css_default["iconButton"]} ${ModelsSection_module_css_default["iconButtonDanger"]}`,
|
|
420
|
-
"aria-label": `${props.t("removeModel")} ${String(index + 1)}`,
|
|
421
|
-
title: props.t("removeModel"),
|
|
422
|
-
disabled: props.disabled,
|
|
423
|
-
onClick: () => {
|
|
424
|
-
remove(index);
|
|
425
|
-
},
|
|
426
|
-
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutline16, { size: 14 })
|
|
427
|
-
})
|
|
428
|
-
]
|
|
429
|
-
}), expanded.has(index) ? (0, react_jsx_runtime.jsxs)("div", {
|
|
430
|
-
className: ModelsSection_module_css_default["modelAdvanced"],
|
|
431
|
-
children: [capacityField(model, index, "contextWindow", props.defaultContextWindow), capacityField(model, index, "maxTokens", props.defaultMaxTokens)]
|
|
432
|
-
}) : null]
|
|
482
|
+
children: props.models.map((model, index) => (0, react_jsx_runtime.jsx)(ModelRow, {
|
|
483
|
+
model,
|
|
484
|
+
position: index + 1,
|
|
485
|
+
inputField: "inputModalities",
|
|
486
|
+
expanded: expanded.has(index),
|
|
487
|
+
disabled: props.disabled,
|
|
488
|
+
t: props.t,
|
|
489
|
+
contextWindow: capacityInput(model, index, "contextWindow", props.defaultContextWindow),
|
|
490
|
+
maxTokens: capacityInput(model, index, "maxTokens", props.defaultMaxTokens),
|
|
491
|
+
onFieldChange: (field, value) => {
|
|
492
|
+
update(index, field, value);
|
|
493
|
+
},
|
|
494
|
+
onIdBlur: (value) => {
|
|
495
|
+
const trimmed = value.trim();
|
|
496
|
+
if (trimmed !== value) update(index, "id", trimmed);
|
|
497
|
+
},
|
|
498
|
+
onChange: (next) => {
|
|
499
|
+
props.onChange(props.models.map((row, at) => at === index ? next : row));
|
|
500
|
+
},
|
|
501
|
+
onToggle: () => {
|
|
502
|
+
toggle(index);
|
|
503
|
+
},
|
|
504
|
+
onRemove: () => {
|
|
505
|
+
remove(index);
|
|
506
|
+
}
|
|
433
507
|
}, index))
|
|
434
508
|
}),
|
|
435
509
|
(0, react_jsx_runtime.jsxs)("button", {
|
|
@@ -439,7 +513,7 @@ window.__ModuleLoader__.load({
|
|
|
439
513
|
onClick: () => {
|
|
440
514
|
props.onChange([...props.models.map((model) => ({ ...model })), { id: "" }]);
|
|
441
515
|
},
|
|
442
|
-
children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
516
|
+
children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutlineRegular, { size: 14 }), props.t("addModel")]
|
|
443
517
|
})
|
|
444
518
|
]
|
|
445
519
|
});
|
|
@@ -471,44 +545,6 @@ window.__ModuleLoader__.load({
|
|
|
471
545
|
const value = model[key];
|
|
472
546
|
return typeof value === "number" ? value : void 0;
|
|
473
547
|
}
|
|
474
|
-
/** Disclosure chevron; rotates to point down while its row is open. */
|
|
475
|
-
function IconChevron({ open }) {
|
|
476
|
-
return (0, react_jsx_runtime.jsx)("svg", {
|
|
477
|
-
width: "14",
|
|
478
|
-
height: "14",
|
|
479
|
-
viewBox: "0 0 16 16",
|
|
480
|
-
fill: "none",
|
|
481
|
-
"aria-hidden": true,
|
|
482
|
-
style: {
|
|
483
|
-
transform: open ? "rotate(90deg)" : void 0,
|
|
484
|
-
transition: "transform 120ms ease"
|
|
485
|
-
},
|
|
486
|
-
children: (0, react_jsx_runtime.jsx)("path", {
|
|
487
|
-
d: "M6 3.5L10.5 8L6 12.5",
|
|
488
|
-
stroke: "currentColor",
|
|
489
|
-
strokeWidth: "1.5",
|
|
490
|
-
strokeLinecap: "round",
|
|
491
|
-
strokeLinejoin: "round"
|
|
492
|
-
})
|
|
493
|
-
});
|
|
494
|
-
}
|
|
495
|
-
/** Removal glyph for one model row. */
|
|
496
|
-
function IconTrash() {
|
|
497
|
-
return (0, react_jsx_runtime.jsx)("svg", {
|
|
498
|
-
width: "14",
|
|
499
|
-
height: "14",
|
|
500
|
-
viewBox: "0 0 16 16",
|
|
501
|
-
fill: "none",
|
|
502
|
-
"aria-hidden": true,
|
|
503
|
-
children: (0, react_jsx_runtime.jsx)("path", {
|
|
504
|
-
d: "M2.5 4h11M6.5 4V2.5h3V4M4 4l.7 9a1 1 0 001 .9h4.6a1 1 0 001-.9L12 4M6.5 6.8v4.4M9.5 6.8v4.4",
|
|
505
|
-
stroke: "currentColor",
|
|
506
|
-
strokeWidth: "1.3",
|
|
507
|
-
strokeLinecap: "round",
|
|
508
|
-
strokeLinejoin: "round"
|
|
509
|
-
})
|
|
510
|
-
});
|
|
511
|
-
}
|
|
512
548
|
/**
|
|
513
549
|
* What an empty capacity field is worth, shown as its placeholder so a row left
|
|
514
550
|
* blank does not read as a model with no capacity at all.
|
|
@@ -534,13 +570,14 @@ window.__ModuleLoader__.load({
|
|
|
534
570
|
function capacitySpelling(value) {
|
|
535
571
|
return value === void 0 ? "" : formatCapacity(value);
|
|
536
572
|
}
|
|
537
|
-
/** Adopt a candidate,
|
|
573
|
+
/** Adopt a candidate, preserving disclosed capacities and input types. */
|
|
538
574
|
function adopt(candidate) {
|
|
539
575
|
return {
|
|
540
576
|
id: candidate.id,
|
|
541
577
|
...candidate.name === void 0 ? {} : { name: candidate.name },
|
|
542
578
|
...candidate.contextWindow === void 0 ? {} : { contextWindow: candidate.contextWindow },
|
|
543
|
-
...candidate.maxTokens === void 0 ? {} : { maxTokens: candidate.maxTokens }
|
|
579
|
+
...candidate.maxTokens === void 0 ? {} : { maxTokens: candidate.maxTokens },
|
|
580
|
+
...candidate.inputModalities === void 0 ? {} : { input: [...candidate.inputModalities] }
|
|
544
581
|
};
|
|
545
582
|
}
|
|
546
583
|
/**
|
|
@@ -549,9 +586,35 @@ window.__ModuleLoader__.load({
|
|
|
549
586
|
* @returns the model-list editor.
|
|
550
587
|
*/
|
|
551
588
|
function ModelListEditor(props) {
|
|
552
|
-
const { models, onChange, probe, operations, t, disabled } = props;
|
|
589
|
+
const { models, onChange, probe, operations, t, disabled, onBusyChange } = props;
|
|
590
|
+
const { catalogProvider } = props;
|
|
553
591
|
const [busy, setBusy] = (0, react.useState)(false);
|
|
592
|
+
(0, react.useEffect)(() => {
|
|
593
|
+
onBusyChange(busy);
|
|
594
|
+
}, [busy, onBusyChange]);
|
|
554
595
|
const [failure, setFailure] = (0, react.useState)(void 0);
|
|
596
|
+
const [inheritedCatalog, setInheritedCatalog] = (0, react.useState)(void 0);
|
|
597
|
+
(0, react.useEffect)(() => {
|
|
598
|
+
if (catalogProvider === void 0) return;
|
|
599
|
+
let current = true;
|
|
600
|
+
operations.discoverModels(probe.settingsNs, { provider: catalogProvider }).then((answer) => {
|
|
601
|
+
if (!current) return;
|
|
602
|
+
setInheritedCatalog({
|
|
603
|
+
provider: catalogProvider,
|
|
604
|
+
models: answer.kind === "found" ? answer.models : []
|
|
605
|
+
});
|
|
606
|
+
setFailure(answer.kind === "refused" ? answer.message : void 0);
|
|
607
|
+
});
|
|
608
|
+
return () => {
|
|
609
|
+
current = false;
|
|
610
|
+
};
|
|
611
|
+
}, [
|
|
612
|
+
catalogProvider,
|
|
613
|
+
operations,
|
|
614
|
+
probe.settingsNs
|
|
615
|
+
]);
|
|
616
|
+
const catalog = inheritedCatalog?.provider === catalogProvider ? inheritedCatalog?.models : void 0;
|
|
617
|
+
const inputDefaults = (0, react.useMemo)(() => new Map(catalog?.map((model) => [model.id, model.inputModalities])), [catalog]);
|
|
555
618
|
const [candidates, setCandidates] = (0, react.useState)(void 0);
|
|
556
619
|
const [picked, setPicked] = (0, react.useState)(/* @__PURE__ */ new Set());
|
|
557
620
|
const [candidateQuery, setCandidateQuery] = (0, react.useState)("");
|
|
@@ -607,6 +670,10 @@ window.__ModuleLoader__.load({
|
|
|
607
670
|
return;
|
|
608
671
|
}
|
|
609
672
|
const found = answer.models;
|
|
673
|
+
if (catalogProvider !== void 0) setInheritedCatalog({
|
|
674
|
+
provider: catalogProvider,
|
|
675
|
+
models: found
|
|
676
|
+
});
|
|
610
677
|
if (found.length === 0) {
|
|
611
678
|
setFailure(t("fetchEmpty"));
|
|
612
679
|
return;
|
|
@@ -695,110 +762,60 @@ window.__ModuleLoader__.load({
|
|
|
695
762
|
className: ModelsSection_module_css_default["modelEmpty"],
|
|
696
763
|
children: t("modelsEmpty")
|
|
697
764
|
}) : null,
|
|
698
|
-
|
|
699
|
-
className: ModelsSection_module_css_default["
|
|
700
|
-
children:
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
})
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
const next = /* @__PURE__ */ new Set();
|
|
746
|
-
for (const at of current) if (at < index) next.add(at);
|
|
747
|
-
else if (at > index) next.add(at - 1);
|
|
748
|
-
return next;
|
|
749
|
-
});
|
|
750
|
-
setEditing((current) => reindexOnRemove(current, index));
|
|
751
|
-
},
|
|
752
|
-
children: (0, react_jsx_runtime.jsx)(IconTrash, {})
|
|
753
|
-
})
|
|
754
|
-
]
|
|
755
|
-
}), expanded.has(index) ? (0, react_jsx_runtime.jsxs)("div", {
|
|
756
|
-
className: ModelsSection_module_css_default["modelAdvanced"],
|
|
757
|
-
children: [(0, react_jsx_runtime.jsxs)("label", {
|
|
758
|
-
className: ModelsSection_module_css_default["modelField"],
|
|
759
|
-
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
760
|
-
className: ModelsSection_module_css_default["modelFieldLabel"],
|
|
761
|
-
children: t("modelContextWindow")
|
|
762
|
-
}), (0, react_jsx_runtime.jsx)("input", {
|
|
763
|
-
className: ModelsSection_module_css_default["input"],
|
|
764
|
-
type: "text",
|
|
765
|
-
inputMode: "numeric",
|
|
766
|
-
value: capacityText(model, index, "contextWindow"),
|
|
767
|
-
placeholder: CAPACITY_HINT.contextWindow,
|
|
768
|
-
"aria-label": `${t("modelContextWindow")} ${index + 1}`,
|
|
769
|
-
disabled,
|
|
770
|
-
onChange: (event) => {
|
|
771
|
-
editCapacity(index, "contextWindow", event.target.value);
|
|
772
|
-
}
|
|
773
|
-
})]
|
|
774
|
-
}), (0, react_jsx_runtime.jsxs)("label", {
|
|
775
|
-
className: ModelsSection_module_css_default["modelField"],
|
|
776
|
-
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
777
|
-
className: ModelsSection_module_css_default["modelFieldLabel"],
|
|
778
|
-
children: t("modelMaxTokens")
|
|
779
|
-
}), (0, react_jsx_runtime.jsx)("input", {
|
|
780
|
-
className: ModelsSection_module_css_default["input"],
|
|
781
|
-
type: "text",
|
|
782
|
-
inputMode: "numeric",
|
|
783
|
-
value: capacityText(model, index, "maxTokens"),
|
|
784
|
-
placeholder: CAPACITY_HINT.maxTokens,
|
|
785
|
-
"aria-label": `${t("modelMaxTokens")} ${index + 1}`,
|
|
786
|
-
disabled,
|
|
787
|
-
onChange: (event) => {
|
|
788
|
-
editCapacity(index, "maxTokens", event.target.value);
|
|
789
|
-
}
|
|
790
|
-
})]
|
|
791
|
-
})]
|
|
792
|
-
}) : null]
|
|
793
|
-
}, index)),
|
|
794
|
-
(0, react_jsx_runtime.jsx)("button", {
|
|
765
|
+
(0, react_jsx_runtime.jsx)("div", {
|
|
766
|
+
className: ModelsSection_module_css_default["modelList"],
|
|
767
|
+
children: models.map((model, index) => (0, react_jsx_runtime.jsx)(ModelRow, {
|
|
768
|
+
model,
|
|
769
|
+
position: index + 1,
|
|
770
|
+
inputField: "input",
|
|
771
|
+
inputFallback: inputDefaults.get(textOf(model, "id")) ?? props.defaultInput,
|
|
772
|
+
inputLoading: catalogProvider !== void 0 && catalog === void 0,
|
|
773
|
+
expanded: expanded.has(index),
|
|
774
|
+
disabled,
|
|
775
|
+
t,
|
|
776
|
+
contextWindow: {
|
|
777
|
+
value: capacityText(model, index, "contextWindow"),
|
|
778
|
+
placeholder: CAPACITY_HINT.contextWindow,
|
|
779
|
+
onChange: (text) => {
|
|
780
|
+
editCapacity(index, "contextWindow", text);
|
|
781
|
+
}
|
|
782
|
+
},
|
|
783
|
+
maxTokens: {
|
|
784
|
+
value: capacityText(model, index, "maxTokens"),
|
|
785
|
+
placeholder: CAPACITY_HINT.maxTokens,
|
|
786
|
+
onChange: (text) => {
|
|
787
|
+
editCapacity(index, "maxTokens", text);
|
|
788
|
+
}
|
|
789
|
+
},
|
|
790
|
+
onFieldChange: (field, value) => {
|
|
791
|
+
patch(index, { [field]: value });
|
|
792
|
+
},
|
|
793
|
+
onChange: (next) => {
|
|
794
|
+
onChange(models.map((row, at) => at === index ? next : row));
|
|
795
|
+
},
|
|
796
|
+
onToggle: () => {
|
|
797
|
+
toggleExpanded(index);
|
|
798
|
+
},
|
|
799
|
+
onRemove: () => {
|
|
800
|
+
onChange(models.filter((_model, at) => at !== index));
|
|
801
|
+
setExpanded((current) => {
|
|
802
|
+
const next = /* @__PURE__ */ new Set();
|
|
803
|
+
for (const at of current) if (at < index) next.add(at);
|
|
804
|
+
else if (at > index) next.add(at - 1);
|
|
805
|
+
return next;
|
|
806
|
+
});
|
|
807
|
+
setEditing((current) => reindexOnRemove(current, index));
|
|
808
|
+
}
|
|
809
|
+
}, index))
|
|
810
|
+
}),
|
|
811
|
+
(0, react_jsx_runtime.jsxs)("button", {
|
|
795
812
|
type: "button",
|
|
796
813
|
className: ModelsSection_module_css_default["addModelButton"],
|
|
797
814
|
disabled,
|
|
798
815
|
onClick: () => {
|
|
799
816
|
onChange([...models, { id: "" }]);
|
|
800
817
|
},
|
|
801
|
-
children: t("addModel")
|
|
818
|
+
children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutlineRegular, { size: 14 }), t("addModel")]
|
|
802
819
|
}),
|
|
803
820
|
failure !== void 0 ? (0, react_jsx_runtime.jsx)("p", {
|
|
804
821
|
className: ModelsSection_module_css_default["error"],
|
|
@@ -1108,18 +1125,46 @@ window.__ModuleLoader__.load({
|
|
|
1108
1125
|
return { kind: "credential-missing" };
|
|
1109
1126
|
}
|
|
1110
1127
|
//#endregion
|
|
1128
|
+
//#region lib/types/client/protocol-label.js
|
|
1129
|
+
/**
|
|
1130
|
+
* Product names for the wire protocols a pi-ai route may speak. The pickers
|
|
1131
|
+
* show these instead of the schema identifiers (`openai-completions`), which
|
|
1132
|
+
* are what `settings.yaml` carries and what the option values stay.
|
|
1133
|
+
*/
|
|
1134
|
+
/** The protocols this page names, keyed by their schema identifier. */
|
|
1135
|
+
const PROTOCOL_LABEL_KEYS = {
|
|
1136
|
+
"openai-completions": "protocolOpenAiCompletions",
|
|
1137
|
+
"openai-responses": "protocolOpenAiResponses",
|
|
1138
|
+
"anthropic-messages": "protocolAnthropicMessages"
|
|
1139
|
+
};
|
|
1140
|
+
/**
|
|
1141
|
+
* The picker text for one protocol identifier.
|
|
1142
|
+
* @param t - section copy.
|
|
1143
|
+
* @param protocol - the schema identifier of the protocol.
|
|
1144
|
+
* @returns the product name this page knows the protocol by; a protocol the
|
|
1145
|
+
* adapter adds before this page names it shows its identifier, the spelling
|
|
1146
|
+
* `settings.yaml` needs anyway.
|
|
1147
|
+
*/
|
|
1148
|
+
function protocolLabel(t, protocol) {
|
|
1149
|
+
const key = PROTOCOL_LABEL_KEYS[protocol];
|
|
1150
|
+
return key === void 0 ? protocol : t(key);
|
|
1151
|
+
}
|
|
1152
|
+
//#endregion
|
|
1111
1153
|
//#region lib/types/client/CustomProviderCard.js
|
|
1112
1154
|
/**
|
|
1113
1155
|
* The card that declares a provider pi-ai does not ship — an OpenAI-compatible
|
|
1114
1156
|
* gateway, a self-hosted server, or a provider newer than the installed
|
|
1115
1157
|
* catalog.
|
|
1116
1158
|
*
|
|
1117
|
-
* This is a create, not an edit, which is why it is its own
|
|
1159
|
+
* This is a create, not an edit, which is why it is its own form rather than
|
|
1118
1160
|
* the provider editor with extra fields: the route id is being *chosen* here,
|
|
1119
|
-
* and the settings address does not exist until it is.
|
|
1120
|
-
*
|
|
1121
|
-
*
|
|
1122
|
-
*
|
|
1161
|
+
* and the settings address does not exist until it is. It renders as the
|
|
1162
|
+
* custom-API panel of the section's add card; the card's mode switch names it
|
|
1163
|
+
* when both modes are offered, and with the custom mode alone the card shows
|
|
1164
|
+
* this form directly. One `settings.mutate` sets the whole profile at
|
|
1165
|
+
* `providers.<route>`; the key travels separately through `credentials/set`
|
|
1166
|
+
* under the reference the profile records, exactly as an existing provider's
|
|
1167
|
+
* key does.
|
|
1123
1168
|
*
|
|
1124
1169
|
* The three fields a hand-declared route cannot default — endpoint, protocol,
|
|
1125
1170
|
* and at least one model — are required here rather than at load, so the
|
|
@@ -1156,7 +1201,7 @@ window.__ModuleLoader__.load({
|
|
|
1156
1201
|
* @returns the creation card.
|
|
1157
1202
|
*/
|
|
1158
1203
|
function CustomProviderCard(props) {
|
|
1159
|
-
const { taken, protocols, operations, t } = props;
|
|
1204
|
+
const { taken, protocols, operations, t, onBusyChange } = props;
|
|
1160
1205
|
const [openedAt] = (0, react.useState)(() => props.revision);
|
|
1161
1206
|
const [route, setRoute] = (0, react.useState)("");
|
|
1162
1207
|
const [displayName, setDisplayName] = (0, react.useState)("");
|
|
@@ -1165,6 +1210,14 @@ window.__ModuleLoader__.load({
|
|
|
1165
1210
|
const [keyDraft, setKeyDraft] = (0, react.useState)("");
|
|
1166
1211
|
const [models, setModels] = (0, react.useState)([]);
|
|
1167
1212
|
const [busy, setBusy] = (0, react.useState)(false);
|
|
1213
|
+
const [listBusy, setListBusy] = (0, react.useState)(false);
|
|
1214
|
+
(0, react.useEffect)(() => {
|
|
1215
|
+
onBusyChange?.(busy || listBusy);
|
|
1216
|
+
}, [
|
|
1217
|
+
busy,
|
|
1218
|
+
listBusy,
|
|
1219
|
+
onBusyChange
|
|
1220
|
+
]);
|
|
1168
1221
|
const [failure, setFailure] = (0, react.useState)(void 0);
|
|
1169
1222
|
/**
|
|
1170
1223
|
* The profile write landed. Only the key write can still be outstanding, so
|
|
@@ -1226,13 +1279,6 @@ window.__ModuleLoader__.load({
|
|
|
1226
1279
|
return (0, react_jsx_runtime.jsxs)("div", {
|
|
1227
1280
|
className: ModelsSection_module_css_default["editor"],
|
|
1228
1281
|
children: [
|
|
1229
|
-
(0, react_jsx_runtime.jsx)("div", {
|
|
1230
|
-
className: ModelsSection_module_css_default["editorHeader"],
|
|
1231
|
-
children: (0, react_jsx_runtime.jsx)("span", {
|
|
1232
|
-
className: ModelsSection_module_css_default["editorTitle"],
|
|
1233
|
-
children: t("customTitle")
|
|
1234
|
-
})
|
|
1235
|
-
}),
|
|
1236
1282
|
(0, react_jsx_runtime.jsxs)("div", {
|
|
1237
1283
|
className: ModelsSection_module_css_default["field"],
|
|
1238
1284
|
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
@@ -1283,7 +1329,7 @@ window.__ModuleLoader__.load({
|
|
|
1283
1329
|
className: ModelsSection_module_css_default["input"],
|
|
1284
1330
|
type: "text",
|
|
1285
1331
|
value: baseURL,
|
|
1286
|
-
placeholder: t("customBaseUrlPlaceholder"),
|
|
1332
|
+
placeholder: t(protocol === "anthropic-messages" ? "customAnthropicBaseUrlPlaceholder" : "customBaseUrlPlaceholder"),
|
|
1287
1333
|
"aria-label": t("baseUrl"),
|
|
1288
1334
|
"aria-invalid": baseUrlInvalid,
|
|
1289
1335
|
disabled: profileDisabled,
|
|
@@ -1311,7 +1357,7 @@ window.__ModuleLoader__.load({
|
|
|
1311
1357
|
},
|
|
1312
1358
|
children: protocols.map((choice) => (0, react_jsx_runtime.jsx)("option", {
|
|
1313
1359
|
value: choice,
|
|
1314
|
-
children: choice
|
|
1360
|
+
children: protocolLabel(t, choice)
|
|
1315
1361
|
}, choice))
|
|
1316
1362
|
})]
|
|
1317
1363
|
}),
|
|
@@ -1352,7 +1398,8 @@ window.__ModuleLoader__.load({
|
|
|
1352
1398
|
probeBlocked: baseUrlInvalid ? "customBaseUrlInvalid" : keyFailure === "keyBlank" ? "keyBlankNew" : keyFailure,
|
|
1353
1399
|
operations,
|
|
1354
1400
|
t,
|
|
1355
|
-
disabled: profileDisabled
|
|
1401
|
+
disabled: profileDisabled,
|
|
1402
|
+
onBusyChange: setListBusy
|
|
1356
1403
|
}),
|
|
1357
1404
|
failure !== void 0 ? (0, react_jsx_runtime.jsx)("p", {
|
|
1358
1405
|
className: ModelsSection_module_css_default["error"],
|
|
@@ -1396,9 +1443,9 @@ window.__ModuleLoader__.load({
|
|
|
1396
1443
|
* Reasoning effort is deliberately absent: it is a per-MODEL capability, and
|
|
1397
1444
|
* the models under one provider disagree about it, so a provider-scoped
|
|
1398
1445
|
* control can only be set to a value some of them reject. The composer's
|
|
1399
|
-
* model picker offers each model its own levels; `
|
|
1446
|
+
* model picker offers each model its own levels; `cordis.patch.yml` keeps the
|
|
1400
1447
|
* profile field for a deployment that knows its route. Everything else stays
|
|
1401
|
-
* owned by `
|
|
1448
|
+
* owned by `cordis.patch.yml`. Profile edits land as minimal `settings.mutate`
|
|
1402
1449
|
* path ops against the stored section — the card names only the fields it can
|
|
1403
1450
|
* see instead of rebuilding the whole subtree from a partial descriptor.
|
|
1404
1451
|
*/
|
|
@@ -1458,6 +1505,15 @@ window.__ModuleLoader__.load({
|
|
|
1458
1505
|
const [keyDraft, setKeyDraft] = (0, react.useState)("");
|
|
1459
1506
|
const [keyState, setKeyState] = (0, react.useState)(void 0);
|
|
1460
1507
|
const [busy, setBusy] = (0, react.useState)(false);
|
|
1508
|
+
const [listBusy, setListBusy] = (0, react.useState)(false);
|
|
1509
|
+
const { onBusyChange } = props;
|
|
1510
|
+
(0, react.useEffect)(() => {
|
|
1511
|
+
onBusyChange?.(busy || listBusy);
|
|
1512
|
+
}, [
|
|
1513
|
+
busy,
|
|
1514
|
+
listBusy,
|
|
1515
|
+
onBusyChange
|
|
1516
|
+
]);
|
|
1461
1517
|
const [failure, setFailure] = (0, react.useState)(void 0);
|
|
1462
1518
|
const [committedOriginal, setCommittedOriginal] = (0, react.useState)(() => schema.getPath(namespace.user, settingsPath));
|
|
1463
1519
|
const [expectedRevision, setExpectedRevision] = (0, react.useState)(() => namespace.revision);
|
|
@@ -1591,6 +1647,7 @@ window.__ModuleLoader__.load({
|
|
|
1591
1647
|
const models = modelDrafts(modelsOverridden ? customModels : inheritedModels());
|
|
1592
1648
|
const defaultContextWindow = schema.getPath(fallback, ["defaultContextWindow"]);
|
|
1593
1649
|
const defaultMaxTokens = schema.getPath(fallback, ["maxTokens"]);
|
|
1650
|
+
const defaultInput = schema.getPath(fallback, ["defaultInput"]);
|
|
1594
1651
|
const keyPlaceholder = keyLocked ? t("keyEnvLocked") : keyState?.configured === true && props.credentialRequired !== true ? t("keyStored") : family === "pi-ai" ? t("keyPlaceholderNative") : t("keyPlaceholder");
|
|
1595
1652
|
/** What both family editors take: the rows, whose layer owns them, and the two writes. */
|
|
1596
1653
|
const catalogProps = {
|
|
@@ -1668,7 +1725,7 @@ window.__ModuleLoader__.load({
|
|
|
1668
1725
|
className: ModelsSection_module_css_default["input"],
|
|
1669
1726
|
type: "text",
|
|
1670
1727
|
value: stringAt(draft, "baseURL") ?? "",
|
|
1671
|
-
placeholder: family === "deepseek" ? t(
|
|
1728
|
+
placeholder: family === "deepseek" ? t("deepSeekBaseUrl") : stringAt(fallback, "baseURL") ?? t("baseUrlDefault"),
|
|
1672
1729
|
"aria-describedby": family === "deepseek" ? `${props.provider}-endpoint-hint` : void 0,
|
|
1673
1730
|
"aria-label": t("baseUrl"),
|
|
1674
1731
|
disabled,
|
|
@@ -1701,7 +1758,7 @@ window.__ModuleLoader__.load({
|
|
|
1701
1758
|
children: t("customApiUnset")
|
|
1702
1759
|
}) : null, protocols.map((choice) => (0, react_jsx_runtime.jsx)("option", {
|
|
1703
1760
|
value: choice,
|
|
1704
|
-
children: choice
|
|
1761
|
+
children: protocolLabel(t, choice)
|
|
1705
1762
|
}, choice))]
|
|
1706
1763
|
})]
|
|
1707
1764
|
}) : null,
|
|
@@ -1711,9 +1768,12 @@ window.__ModuleLoader__.load({
|
|
|
1711
1768
|
defaultMaxTokens: typeof defaultMaxTokens === "number" ? defaultMaxTokens : void 0
|
|
1712
1769
|
}) : (0, react_jsx_runtime.jsx)(ModelListEditor, {
|
|
1713
1770
|
...catalogProps,
|
|
1771
|
+
catalogProvider: props.declared === true ? void 0 : props.provider,
|
|
1772
|
+
defaultInput: Array.isArray(defaultInput) ? defaultInput : void 0,
|
|
1714
1773
|
probe,
|
|
1715
1774
|
probeBlocked: keyFailure,
|
|
1716
|
-
operations
|
|
1775
|
+
operations,
|
|
1776
|
+
onBusyChange: setListBusy
|
|
1717
1777
|
})
|
|
1718
1778
|
]
|
|
1719
1779
|
})]
|
|
@@ -1770,11 +1830,19 @@ window.__ModuleLoader__.load({
|
|
|
1770
1830
|
* solid configured or missing dots. A whole-section provider without a
|
|
1771
1831
|
* configured key renders as its open setup card instead of a row, but only in
|
|
1772
1832
|
* the first-run posture — no provider on the page can serve requests yet — and
|
|
1773
|
-
* only until the user closes that card
|
|
1774
|
-
*
|
|
1775
|
-
*
|
|
1776
|
-
*
|
|
1777
|
-
*
|
|
1833
|
+
* only until the user closes that card. The add flow is one card behind one
|
|
1834
|
+
* button: a mode switch chooses between adopting a dormant directory provider
|
|
1835
|
+
* (the catalog select over the provider editor) and declaring a custom model
|
|
1836
|
+
* API (the create form). A panel mounts the first time its mode is shown and
|
|
1837
|
+
* stays mounted, hidden, while the card is open and its mode stays offered,
|
|
1838
|
+
* so switching modes discards neither draft and an unvisited mode costs
|
|
1839
|
+
* nothing; the switch holds still while either panel has a write or an
|
|
1840
|
+
* endpoint interrogation in flight, since a switch underneath one would
|
|
1841
|
+
* orphan the answer. Each card kind owns its own open state, so closing one
|
|
1842
|
+
* never discards a draft in another. Every
|
|
1843
|
+
* mutation writes through the wire, while a provider removal first requires
|
|
1844
|
+
* confirmation; the page re-renders from pushed invalidations or the
|
|
1845
|
+
* post-apply reload.
|
|
1778
1846
|
*/
|
|
1779
1847
|
/** Render an editor for either the setup posture or an expanded provider row. */
|
|
1780
1848
|
function renderProviderEditor({ target, ...props }) {
|
|
@@ -1876,30 +1944,48 @@ window.__ModuleLoader__.load({
|
|
|
1876
1944
|
const { controller, operations, schema, t } = injected;
|
|
1877
1945
|
const state = injected.useSnapshot((snapshot) => snapshot);
|
|
1878
1946
|
const [editing, setEditing] = (0, react.useState)(void 0);
|
|
1879
|
-
const [
|
|
1947
|
+
const [addOpen, setAddOpen] = (0, react.useState)(false);
|
|
1948
|
+
const [addMode, setAddMode] = (0, react.useState)("catalog");
|
|
1949
|
+
/** The modes shown since the add card opened; each keeps its panel mounted. */
|
|
1950
|
+
const [visited, setVisited] = (0, react.useState)(() => /* @__PURE__ */ new Set());
|
|
1951
|
+
/** Whether each add panel has a write or an interrogation in flight. */
|
|
1952
|
+
const [catalogBusy, setCatalogBusy] = (0, react.useState)(false);
|
|
1953
|
+
const [customBusy, setCustomBusy] = (0, react.useState)(false);
|
|
1954
|
+
/** Base of the add card's tab and panel ids. */
|
|
1955
|
+
const addId = (0, react.useId)();
|
|
1880
1956
|
const [deleteTarget, setDeleteTarget] = (0, react.useState)(void 0);
|
|
1881
1957
|
const [deleting, setDeleting] = (0, react.useState)(false);
|
|
1882
1958
|
const [deleteFailure, setDeleteFailure] = (0, react.useState)(void 0);
|
|
1883
1959
|
const [savedTarget, setSavedTarget] = (0, react.useState)(void 0);
|
|
1884
|
-
const [declaring, setDeclaring] = (0, react.useState)(false);
|
|
1885
1960
|
const [dismissedSetup, setDismissedSetup] = (0, react.useState)(() => /* @__PURE__ */ new Set());
|
|
1886
1961
|
const announceSaved = (target) => {
|
|
1887
1962
|
controller.load().then(() => {
|
|
1888
1963
|
setSavedTarget(target);
|
|
1889
1964
|
});
|
|
1890
1965
|
};
|
|
1891
|
-
|
|
1966
|
+
/**
|
|
1967
|
+
* Close the add card whole. The catalog target is forgotten with it, since
|
|
1968
|
+
* `editing` doubles as the row editor's target once the card is closed and a
|
|
1969
|
+
* refresh could otherwise open the row of a provider the draft never saved.
|
|
1970
|
+
* The busy flags reset here because a panel that closes itself on success
|
|
1971
|
+
* unmounts before it can report idle.
|
|
1972
|
+
*/
|
|
1973
|
+
const closeAdd = () => {
|
|
1892
1974
|
setEditing(void 0);
|
|
1893
|
-
|
|
1894
|
-
|
|
1975
|
+
setAddOpen(false);
|
|
1976
|
+
setCatalogBusy(false);
|
|
1977
|
+
setCustomBusy(false);
|
|
1978
|
+
};
|
|
1979
|
+
const closeEditor = (changed, target) => {
|
|
1980
|
+
closeAdd();
|
|
1895
1981
|
if (changed) announceSaved(target);
|
|
1896
1982
|
};
|
|
1897
1983
|
/**
|
|
1898
|
-
* Close a setup card, which owns none of the state above: the row-editor
|
|
1899
|
-
*
|
|
1900
|
-
*
|
|
1901
|
-
*
|
|
1902
|
-
*
|
|
1984
|
+
* Close a setup card, which owns none of the state above: the row-editor
|
|
1985
|
+
* and add cards each own one of those, so clearing them here would discard
|
|
1986
|
+
* a draft the user opened beside this card. Dismissal is this card's own —
|
|
1987
|
+
* the provider falls back to an ordinary row for the rest of the session,
|
|
1988
|
+
* and reopens through Edit.
|
|
1903
1989
|
*/
|
|
1904
1990
|
const closeSetup = (changed, target) => {
|
|
1905
1991
|
setDismissedSetup((previous) => new Set([...previous, target.provider]));
|
|
@@ -1952,11 +2038,37 @@ window.__ModuleLoader__.load({
|
|
|
1952
2038
|
const anyUsable = state.rows.some(providerUsable);
|
|
1953
2039
|
const configured = state.rows.filter((row) => row.configured);
|
|
1954
2040
|
const configurable = state.rows.filter((row) => state.namespaces.has(row.entry.settingsNs));
|
|
1955
|
-
const addable =
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
2041
|
+
const addable = state.rows.flatMap((row) => {
|
|
2042
|
+
const namespace = state.namespaces.get(row.entry.settingsNs);
|
|
2043
|
+
return namespace === void 0 || row.configured ? [] : [{
|
|
2044
|
+
row,
|
|
2045
|
+
namespace
|
|
2046
|
+
}];
|
|
2047
|
+
});
|
|
2048
|
+
const piAi = state.namespaces.get("llm-pi-ai");
|
|
2049
|
+
const protocols = protocolChoices(piAi, schema);
|
|
2050
|
+
const catalogOffered = configurable.length > 0;
|
|
2051
|
+
const catalogEnabled = addable.length > 0;
|
|
2052
|
+
const customOffered = piAi !== void 0;
|
|
2053
|
+
const customEnabled = protocols.length > 0;
|
|
2054
|
+
const bothOffered = catalogOffered && customOffered;
|
|
2055
|
+
const mode = bothOffered ? addMode : customOffered ? "custom" : "catalog";
|
|
2056
|
+
const mounted = (candidate) => mode === candidate || visited.has(candidate);
|
|
2057
|
+
const switchLocked = catalogBusy || customBusy;
|
|
2058
|
+
const draft = (() => {
|
|
2059
|
+
if (!addOpen || !catalogOffered) return void 0;
|
|
2060
|
+
const kept = editing === void 0 ? void 0 : state.namespaces.get(editing.settingsNs);
|
|
2061
|
+
if (editing !== void 0 && kept !== void 0) return {
|
|
2062
|
+
target: editing,
|
|
2063
|
+
namespace: kept
|
|
2064
|
+
};
|
|
2065
|
+
const first = addable[0];
|
|
2066
|
+
return first === void 0 ? void 0 : {
|
|
2067
|
+
target: targetOf(first.row),
|
|
2068
|
+
namespace: first.namespace
|
|
2069
|
+
};
|
|
2070
|
+
})();
|
|
2071
|
+
const addRow = draft === void 0 ? void 0 : state.rows.find((row) => row.entry.provider === draft.target.provider);
|
|
1960
2072
|
return (0, react_jsx_runtime.jsxs)("div", {
|
|
1961
2073
|
className: ModelsSection_module_css_default["section"],
|
|
1962
2074
|
children: [
|
|
@@ -2012,7 +2124,7 @@ window.__ModuleLoader__.load({
|
|
|
2012
2124
|
}, { entryKey: row.entry.settingsNs })
|
|
2013
2125
|
]
|
|
2014
2126
|
}, row.entry.provider);
|
|
2015
|
-
const open = !
|
|
2127
|
+
const open = !addOpen && editing?.provider === row.entry.provider;
|
|
2016
2128
|
const credentialConfigured = row.credential?.configured === true;
|
|
2017
2129
|
const credentialMissing = !credentialConfigured && row.apiKeyEnv !== void 0 && row.credential?.configured === false;
|
|
2018
2130
|
return (0, react_jsx_runtime.jsxs)("li", {
|
|
@@ -2051,8 +2163,7 @@ window.__ModuleLoader__.load({
|
|
|
2051
2163
|
"aria-label": providerCopy(t("editProvider"), target),
|
|
2052
2164
|
onClick: () => {
|
|
2053
2165
|
setSavedTarget(void 0);
|
|
2054
|
-
|
|
2055
|
-
setAdding(false);
|
|
2166
|
+
setAddOpen(false);
|
|
2056
2167
|
setEditing(open ? void 0 : target);
|
|
2057
2168
|
},
|
|
2058
2169
|
children: t("edit")
|
|
@@ -2093,94 +2204,136 @@ window.__ModuleLoader__.load({
|
|
|
2093
2204
|
}),
|
|
2094
2205
|
(0, react_jsx_runtime.jsx)("div", {
|
|
2095
2206
|
className: ModelsSection_module_css_default["addBlock"],
|
|
2096
|
-
children:
|
|
2207
|
+
children: addOpen ? (0, react_jsx_runtime.jsxs)("div", {
|
|
2097
2208
|
className: ModelsSection_module_css_default["addCard"],
|
|
2098
2209
|
children: [
|
|
2099
2210
|
(0, react_jsx_runtime.jsxs)("div", {
|
|
2100
|
-
className: ModelsSection_module_css_default["
|
|
2101
|
-
children: [(0, react_jsx_runtime.jsx)(
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2211
|
+
className: ModelsSection_module_css_default["addModes"],
|
|
2212
|
+
children: [bothOffered ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.SegmentedControl, {
|
|
2213
|
+
id: addId,
|
|
2214
|
+
label: t("addMode"),
|
|
2215
|
+
value: mode,
|
|
2216
|
+
disabled: switchLocked,
|
|
2217
|
+
options: [{
|
|
2218
|
+
value: "catalog",
|
|
2219
|
+
label: t("addCatalog"),
|
|
2220
|
+
disabled: !catalogEnabled,
|
|
2221
|
+
...catalogEnabled ? {} : { title: t("addCatalogExhausted") }
|
|
2222
|
+
}, {
|
|
2223
|
+
value: "custom",
|
|
2224
|
+
label: t("addCustom"),
|
|
2225
|
+
disabled: !customEnabled,
|
|
2226
|
+
...customEnabled ? {} : { title: t("addCustomUnavailable") }
|
|
2227
|
+
}],
|
|
2228
|
+
onChange: (next) => {
|
|
2229
|
+
setAddMode(next);
|
|
2230
|
+
setVisited((previous) => new Set([...previous, next]));
|
|
2231
|
+
}
|
|
2232
|
+
}) : (0, react_jsx_runtime.jsx)("div", {
|
|
2233
|
+
className: ModelsSection_module_css_default["editorHeader"],
|
|
2234
|
+
children: (0, react_jsx_runtime.jsx)("span", {
|
|
2235
|
+
className: ModelsSection_module_css_default["editorTitle"],
|
|
2236
|
+
children: t(mode === "catalog" ? "addCatalog" : "addCustom")
|
|
2237
|
+
})
|
|
2238
|
+
}), (0, react_jsx_runtime.jsx)("p", {
|
|
2239
|
+
className: ModelsSection_module_css_default["advancedHint"],
|
|
2240
|
+
children: t(mode === "catalog" ? "addCatalogHint" : "addCustomHint")
|
|
2118
2241
|
})]
|
|
2119
2242
|
}),
|
|
2120
|
-
(0, react_jsx_runtime.
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2243
|
+
mounted("catalog") && draft !== void 0 ? (0, react_jsx_runtime.jsxs)("div", {
|
|
2244
|
+
id: `${addId}-catalog-panel`,
|
|
2245
|
+
...bothOffered ? {
|
|
2246
|
+
role: "tabpanel",
|
|
2247
|
+
"aria-labelledby": `${addId}-catalog`
|
|
2248
|
+
} : {},
|
|
2249
|
+
hidden: mode !== "catalog",
|
|
2250
|
+
className: ModelsSection_module_css_default["addPanel"],
|
|
2251
|
+
children: [
|
|
2252
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
2253
|
+
className: ModelsSection_module_css_default["field"],
|
|
2254
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
2255
|
+
className: ModelsSection_module_css_default["fieldLabel"],
|
|
2256
|
+
children: t("provider")
|
|
2257
|
+
}), (0, react_jsx_runtime.jsx)("select", {
|
|
2258
|
+
className: `${ModelsSection_module_css_default["input"]} ${ModelsSection_module_css_default["selectInput"]}`,
|
|
2259
|
+
value: draft.target.provider,
|
|
2260
|
+
"aria-label": t("provider"),
|
|
2261
|
+
disabled: catalogBusy,
|
|
2262
|
+
onChange: (event) => {
|
|
2263
|
+
const picked = addable.find((candidate) => candidate.row.entry.provider === event.target.value);
|
|
2264
|
+
/* v8 ignore next -- the select only lists addable rows */
|
|
2265
|
+
if (picked === void 0) return;
|
|
2266
|
+
setEditing(targetOf(picked.row));
|
|
2267
|
+
},
|
|
2268
|
+
children: addable.map(({ row }) => (0, react_jsx_runtime.jsx)("option", {
|
|
2269
|
+
value: row.entry.provider,
|
|
2270
|
+
children: row.entry.displayName
|
|
2271
|
+
}, row.entry.provider))
|
|
2272
|
+
})]
|
|
2273
|
+
}),
|
|
2274
|
+
(0, react_jsx_runtime.jsx)(ProviderEditor, {
|
|
2275
|
+
provider: draft.target.provider,
|
|
2276
|
+
displayName: draft.target.displayName,
|
|
2277
|
+
hideTitle: true,
|
|
2278
|
+
namespace: draft.namespace,
|
|
2279
|
+
schema,
|
|
2280
|
+
settingsPath: draft.target.settingsPath,
|
|
2281
|
+
operations,
|
|
2282
|
+
t,
|
|
2283
|
+
readOnly: !state.writable,
|
|
2284
|
+
onClose: (changed) => {
|
|
2285
|
+
closeEditor(changed, draft.target);
|
|
2286
|
+
},
|
|
2287
|
+
onBusyChange: setCatalogBusy
|
|
2288
|
+
}, draft.target.provider),
|
|
2289
|
+
addRow === void 0 ? null : renderSlot("settings.models.provider-card", {
|
|
2290
|
+
provider: addRow.entry,
|
|
2291
|
+
configured: addRow.configured,
|
|
2292
|
+
keyConfigured: keyConfiguredOf(addRow)
|
|
2293
|
+
}, { entryKey: addRow.entry.settingsNs })
|
|
2294
|
+
]
|
|
2295
|
+
}) : null,
|
|
2296
|
+
mounted("custom") && piAi !== void 0 ? (0, react_jsx_runtime.jsx)("div", {
|
|
2297
|
+
id: `${addId}-custom-panel`,
|
|
2298
|
+
...bothOffered ? {
|
|
2299
|
+
role: "tabpanel",
|
|
2300
|
+
"aria-labelledby": `${addId}-custom`
|
|
2301
|
+
} : {},
|
|
2302
|
+
hidden: mode !== "custom",
|
|
2303
|
+
className: ModelsSection_module_css_default["addPanel"],
|
|
2304
|
+
children: (0, react_jsx_runtime.jsx)(CustomProviderCard, {
|
|
2305
|
+
taken: state.rows.map((row) => row.entry.provider),
|
|
2306
|
+
protocols,
|
|
2307
|
+
revision: piAi.revision,
|
|
2308
|
+
operations,
|
|
2309
|
+
t,
|
|
2310
|
+
readOnly: !state.writable,
|
|
2311
|
+
onClose: (changed) => {
|
|
2312
|
+
closeAdd();
|
|
2313
|
+
if (changed) controller.load();
|
|
2314
|
+
},
|
|
2315
|
+
onBusyChange: setCustomBusy
|
|
2316
|
+
})
|
|
2317
|
+
}) : null
|
|
2139
2318
|
]
|
|
2140
|
-
}) :
|
|
2141
|
-
className: ModelsSection_module_css_default["addCard"],
|
|
2142
|
-
children: (0, react_jsx_runtime.jsx)(CustomProviderCard, {
|
|
2143
|
-
taken: state.rows.map((row) => row.entry.provider),
|
|
2144
|
-
protocols,
|
|
2145
|
-
/* v8 ignore next -- the card only opens from a button disabled without this namespace */
|
|
2146
|
-
revision: state.namespaces.get("llm-pi-ai")?.revision ?? 0,
|
|
2147
|
-
operations,
|
|
2148
|
-
t,
|
|
2149
|
-
readOnly: !state.writable,
|
|
2150
|
-
onClose: (changed) => {
|
|
2151
|
-
setDeclaring(false);
|
|
2152
|
-
if (changed) controller.load();
|
|
2153
|
-
}
|
|
2154
|
-
})
|
|
2155
|
-
}) : (0, react_jsx_runtime.jsxs)("div", {
|
|
2319
|
+
}) : catalogOffered || customOffered ? (0, react_jsx_runtime.jsx)("div", {
|
|
2156
2320
|
className: ModelsSection_module_css_default["addActions"],
|
|
2157
|
-
children:
|
|
2321
|
+
children: (0, react_jsx_runtime.jsxs)("button", {
|
|
2158
2322
|
type: "button",
|
|
2159
2323
|
className: ModelsSection_module_css_default["addButton"],
|
|
2160
|
-
disabled:
|
|
2324
|
+
disabled: !state.writable || !catalogEnabled && !customEnabled,
|
|
2161
2325
|
onClick: () => {
|
|
2162
2326
|
const first = addable[0];
|
|
2163
|
-
|
|
2164
|
-
if (first === void 0) return;
|
|
2327
|
+
const initial = catalogEnabled ? "catalog" : "custom";
|
|
2165
2328
|
setSavedTarget(void 0);
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2329
|
+
setEditing(first === void 0 ? void 0 : targetOf(first.row));
|
|
2330
|
+
setAddMode(initial);
|
|
2331
|
+
setVisited(new Set([initial]));
|
|
2332
|
+
setAddOpen(true);
|
|
2169
2333
|
},
|
|
2170
|
-
children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
2171
|
-
})
|
|
2172
|
-
|
|
2173
|
-
className: ModelsSection_module_css_default["addButton"],
|
|
2174
|
-
disabled: protocols.length === 0 || !state.writable,
|
|
2175
|
-
onClick: () => {
|
|
2176
|
-
setSavedTarget(void 0);
|
|
2177
|
-
setAdding(false);
|
|
2178
|
-
setEditing(void 0);
|
|
2179
|
-
setDeclaring(true);
|
|
2180
|
-
},
|
|
2181
|
-
children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutline16, { size: 14 }), t("customAdd")]
|
|
2182
|
-
})]
|
|
2183
|
-
})
|
|
2334
|
+
children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutlineRegular, { size: 14 }), t("add")]
|
|
2335
|
+
})
|
|
2336
|
+
}) : null
|
|
2184
2337
|
}),
|
|
2185
2338
|
renderSlot("settings.models.footer", {}),
|
|
2186
2339
|
(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
@@ -2213,7 +2366,7 @@ window.__ModuleLoader__.load({
|
|
|
2213
2366
|
}
|
|
2214
2367
|
//#endregion
|
|
2215
2368
|
//#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-settings-models/src/client/OnboardingModal.module.css.mjs
|
|
2216
|
-
const css$2 = ".jLrgrW_dialog{width:min(600px,100%);padding:0}.jLrgrW_content{box-sizing:border-box;flex-direction:column;
|
|
2369
|
+
const css$2 = ".jLrgrW_dialog{width:min(600px,100%);max-height:100%;padding:0}.jLrgrW_content{box-sizing:border-box;flex-direction:column;min-height:0;padding:28px;display:flex;overflow-y:auto}.jLrgrW_title{color:var(--dsw-alias-label-primary);outline:none;margin:0;font-size:20px;font-weight:500;line-height:28px}.jLrgrW_body{margin-top:20px}@media (width<=560px){.jLrgrW_content{padding:24px}}";
|
|
2217
2370
|
const tagId$2 = "@deepseek-ai/dsh-client-ui-settings-models/OnboardingModal.module.css";
|
|
2218
2371
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$2) + "]") === null) {
|
|
2219
2372
|
const tag = document.createElement("style");
|
|
@@ -2308,20 +2461,34 @@ window.__ModuleLoader__.load({
|
|
|
2308
2461
|
* @returns the onboarding modal or null when onboarding needs no intervention.
|
|
2309
2462
|
*/
|
|
2310
2463
|
function DeepSeekOnboardingDialog(props) {
|
|
2311
|
-
const { complete, controller, useModels, operations, schema, t } = props;
|
|
2464
|
+
const { complete, controller, useModels, operations, schema, t, renderSlot, automatic, explicit = false } = props;
|
|
2465
|
+
const [apiKey, setApiKey] = (0, react.useState)(explicit);
|
|
2312
2466
|
const state = useModels((snapshot) => snapshot);
|
|
2313
2467
|
const readiness = onboardingReadiness(state);
|
|
2314
2468
|
(0, react.useEffect)(() => {
|
|
2315
|
-
if (state.status === "idle") controller.load();
|
|
2316
|
-
}, [
|
|
2469
|
+
if ((automatic || explicit) && state.status === "idle") controller.load();
|
|
2470
|
+
}, [
|
|
2471
|
+
controller,
|
|
2472
|
+
state.status,
|
|
2473
|
+
automatic,
|
|
2474
|
+
explicit
|
|
2475
|
+
]);
|
|
2317
2476
|
(0, react.useEffect)(() => {
|
|
2318
|
-
if (readiness.kind === "adapter-absent" || readiness.kind === "provider-ready" || readiness.kind === "unavailable") complete();
|
|
2319
|
-
}, [
|
|
2477
|
+
if (!automatic && !explicit || readiness.kind === "adapter-absent" || !explicit && readiness.kind === "provider-ready" || readiness.kind === "unavailable") complete();
|
|
2478
|
+
}, [
|
|
2479
|
+
complete,
|
|
2480
|
+
readiness.kind,
|
|
2481
|
+
explicit,
|
|
2482
|
+
automatic
|
|
2483
|
+
]);
|
|
2484
|
+
if (!automatic && !explicit) return null;
|
|
2320
2485
|
switch (readiness.kind) {
|
|
2321
2486
|
case "loading":
|
|
2322
2487
|
case "adapter-absent":
|
|
2323
|
-
case "provider-ready":
|
|
2324
2488
|
case "unavailable": return null;
|
|
2489
|
+
case "provider-ready":
|
|
2490
|
+
if (!explicit) return null;
|
|
2491
|
+
break;
|
|
2325
2492
|
case "credential-missing": break;
|
|
2326
2493
|
/* v8 ignore next -- every current readiness variant is handled above */
|
|
2327
2494
|
default: return assertNever$1(readiness);
|
|
@@ -2337,7 +2504,7 @@ window.__ModuleLoader__.load({
|
|
|
2337
2504
|
}
|
|
2338
2505
|
controller.load();
|
|
2339
2506
|
};
|
|
2340
|
-
|
|
2507
|
+
const editor = (0, react_jsx_runtime.jsxs)(OnboardingModal, {
|
|
2341
2508
|
title: t("onboardingTitle"),
|
|
2342
2509
|
children: [(0, react_jsx_runtime.jsx)("p", {
|
|
2343
2510
|
className: DeepSeekOnboardingDialog_module_css_default.description,
|
|
@@ -2364,6 +2531,12 @@ window.__ModuleLoader__.load({
|
|
|
2364
2531
|
})
|
|
2365
2532
|
})]
|
|
2366
2533
|
});
|
|
2534
|
+
return apiKey ? editor : renderSlot("settings.models.sign-in", {
|
|
2535
|
+
complete,
|
|
2536
|
+
useApiKey: () => {
|
|
2537
|
+
setApiKey(true);
|
|
2538
|
+
}
|
|
2539
|
+
}, { fallback: editor });
|
|
2367
2540
|
}
|
|
2368
2541
|
//#endregion
|
|
2369
2542
|
//#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-settings-models/src/client/WelcomeNotice.module.css.mjs
|
|
@@ -2441,7 +2614,7 @@ window.__ModuleLoader__.load({
|
|
|
2441
2614
|
//#endregion
|
|
2442
2615
|
//#region lib/types/onboarding-copy.js
|
|
2443
2616
|
/** Durable settings namespace for product-wide GUI onboarding facts. */
|
|
2444
|
-
const WELCOME_NOTICE_SETTINGS_NAMESPACE = "ui-
|
|
2617
|
+
const WELCOME_NOTICE_SETTINGS_NAMESPACE = "ui-settings-general";
|
|
2445
2618
|
/** Field storing the last welcome notice version the user acknowledged. */
|
|
2446
2619
|
const WELCOME_NOTICE_ACK_FIELD = "welcomeNoticeVersion";
|
|
2447
2620
|
/**
|
|
@@ -2457,16 +2630,6 @@ window.__ModuleLoader__.load({
|
|
|
2457
2630
|
* remote browser's memory-mode scope never answers and the acknowledgement
|
|
2458
2631
|
* stays process-local here.
|
|
2459
2632
|
*/
|
|
2460
|
-
/**
|
|
2461
|
-
* Accept any object section verbatim; a malformed durable value reads as an
|
|
2462
|
-
* empty section, so the notice treats it as unacknowledged instead of leaving
|
|
2463
|
-
* the scope stuck on its previous value.
|
|
2464
|
-
* @param section - the wire section value.
|
|
2465
|
-
* @returns the section object, or an empty one for non-object values.
|
|
2466
|
-
*/
|
|
2467
|
-
function decodeWelcomeSection(section) {
|
|
2468
|
-
return typeof section === "object" && section !== null && !Array.isArray(section) ? section : {};
|
|
2469
|
-
}
|
|
2470
2633
|
/* v8 ignore next 3 -- closed-union default only defends future source widening */
|
|
2471
2634
|
function assertNever(_value) {
|
|
2472
2635
|
throw new Error("unexpected welcome settings status");
|
|
@@ -2665,7 +2828,14 @@ window.__ModuleLoader__.load({
|
|
|
2665
2828
|
deleteDescriptionWithCredential: "Deleting {provider} removes its configuration and stored API key.",
|
|
2666
2829
|
deleteConfirm: "Delete {provider}",
|
|
2667
2830
|
deleting: "Deleting {provider}…",
|
|
2668
|
-
add: "Add provider",
|
|
2831
|
+
add: "Add model provider",
|
|
2832
|
+
addMode: "How to add",
|
|
2833
|
+
addCatalog: "Third-party model provider",
|
|
2834
|
+
addCustom: "Custom model API",
|
|
2835
|
+
addCatalogHint: "Pick OpenAI, Anthropic, Kimi, or another provider from the built-in catalog and enter its API key.",
|
|
2836
|
+
addCustomHint: "Connect a relay, a self-hosted server, or any other OpenAI- or Anthropic-compatible endpoint by its base URL, protocol, and models.",
|
|
2837
|
+
addCatalogExhausted: "Every catalog provider is already configured.",
|
|
2838
|
+
addCustomUnavailable: "No API protocol is available to declare.",
|
|
2669
2839
|
provider: "Provider",
|
|
2670
2840
|
close: "Close",
|
|
2671
2841
|
cancel: "Cancel",
|
|
@@ -2686,9 +2856,8 @@ window.__ModuleLoader__.load({
|
|
|
2686
2856
|
customized: "Customized settings",
|
|
2687
2857
|
baseUrl: "Base URL",
|
|
2688
2858
|
baseUrlDefault: "Provider default",
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
deepSeekEndpointHint: "Use an endpoint compatible with the configured connection.",
|
|
2859
|
+
deepSeekBaseUrl: "https://api.deepseek.com/anthropic",
|
|
2860
|
+
deepSeekEndpointHint: "Use an API endpoint compatible with Anthropic Messages.",
|
|
2692
2861
|
models: "Models",
|
|
2693
2862
|
modelsInherited: "Using the adapter defaults",
|
|
2694
2863
|
modelsCustomized: "Customized model catalog",
|
|
@@ -2701,7 +2870,10 @@ window.__ModuleLoader__.load({
|
|
|
2701
2870
|
contextWindowPlaceholder: "Uses the provider default",
|
|
2702
2871
|
maxTokens: "Max output tokens",
|
|
2703
2872
|
maxTokensPlaceholder: "Uses the provider default",
|
|
2704
|
-
modelAdvanced: "
|
|
2873
|
+
modelAdvanced: "Model options",
|
|
2874
|
+
modelInputTypes: "Input types",
|
|
2875
|
+
modelInputText: "Text",
|
|
2876
|
+
modelInputImage: "Image",
|
|
2705
2877
|
addModel: "Add model",
|
|
2706
2878
|
removeModel: "Delete model",
|
|
2707
2879
|
modelsEmpty: "No models will be shown in the selector. Unlisted IDs can still be sent directly.",
|
|
@@ -2713,11 +2885,9 @@ window.__ModuleLoader__.load({
|
|
|
2713
2885
|
modelNameInvalid: "Display name cannot be empty.",
|
|
2714
2886
|
modelContextInvalid: "Context window must be a positive count, like 131072, 256K, or 1M.",
|
|
2715
2887
|
modelMaxTokensInvalid: "Max output tokens must be a positive count, like 8192, 64K, or 1M.",
|
|
2716
|
-
advancedHint: "Other fields live in
|
|
2888
|
+
advancedHint: "Other fields live in cordis.patch.yml; edit that section directly.",
|
|
2717
2889
|
modelCapacityInvalid: "A capacity must be a number, optionally suffixed K or M.",
|
|
2718
2890
|
modelDuplicate: "Each model ID may appear once.",
|
|
2719
|
-
modelContextWindow: "Context window",
|
|
2720
|
-
modelMaxTokens: "Max output tokens",
|
|
2721
2891
|
fetchModels: "Fetch available models",
|
|
2722
2892
|
fetching: "Asking the provider…",
|
|
2723
2893
|
fetchNeedsBaseUrl: "Enter the base URL first, then fetch.",
|
|
@@ -2729,8 +2899,6 @@ window.__ModuleLoader__.load({
|
|
|
2729
2899
|
fetchSelectAll: "Select all",
|
|
2730
2900
|
fetchDeselectAll: "Deselect all",
|
|
2731
2901
|
fetchAdopt: "Add selected",
|
|
2732
|
-
customAdd: "Add a custom provider",
|
|
2733
|
-
customTitle: "Custom provider",
|
|
2734
2902
|
customTag: "Custom",
|
|
2735
2903
|
customRoute: "Provider ID",
|
|
2736
2904
|
customRouteHint: "Lowercase identifier, starting with a letter, that uniquely names this provider in requests and as its credential name.",
|
|
@@ -2739,10 +2907,14 @@ window.__ModuleLoader__.load({
|
|
|
2739
2907
|
customDisplayName: "Display name",
|
|
2740
2908
|
customApi: "API protocol",
|
|
2741
2909
|
customApiUnset: "Not selected",
|
|
2910
|
+
protocolOpenAiCompletions: "OpenAI Chat Completions",
|
|
2911
|
+
protocolOpenAiResponses: "OpenAI Responses",
|
|
2912
|
+
protocolAnthropicMessages: "Anthropic Messages",
|
|
2742
2913
|
customNeedsBaseUrl: "A custom provider needs a base URL.",
|
|
2743
2914
|
customBaseUrlInvalid: "Enter a valid HTTP or HTTPS URL.",
|
|
2744
2915
|
customNeedsModels: "A custom provider needs at least one model.",
|
|
2745
2916
|
customBaseUrlPlaceholder: "https://gateway.example/v1",
|
|
2917
|
+
customAnthropicBaseUrlPlaceholder: "https://gateway.example",
|
|
2746
2918
|
settingsPathUnresolvable: "unresolvable settings path",
|
|
2747
2919
|
create: "Create provider",
|
|
2748
2920
|
creating: "Creating…",
|
|
@@ -2761,7 +2933,7 @@ window.__ModuleLoader__.load({
|
|
|
2761
2933
|
const zh = {
|
|
2762
2934
|
nav: "模型",
|
|
2763
2935
|
title: "模型",
|
|
2764
|
-
intro: "
|
|
2936
|
+
intro: "填入各提供商的 API 密钥即可使用其模型。",
|
|
2765
2937
|
edit: "编辑",
|
|
2766
2938
|
editProvider: "编辑 {provider}",
|
|
2767
2939
|
remove: "删除",
|
|
@@ -2771,8 +2943,15 @@ window.__ModuleLoader__.load({
|
|
|
2771
2943
|
deleteDescriptionWithCredential: "删除 {provider} 会移除其配置和存储的 API 密钥。",
|
|
2772
2944
|
deleteConfirm: "删除 {provider}",
|
|
2773
2945
|
deleting: "正在删除 {provider}…",
|
|
2774
|
-
add: "
|
|
2775
|
-
|
|
2946
|
+
add: "添加模型提供商",
|
|
2947
|
+
addMode: "添加方式",
|
|
2948
|
+
addCatalog: "第三方模型提供商",
|
|
2949
|
+
addCustom: "自定义模型 API",
|
|
2950
|
+
addCatalogHint: "从内置目录中选择 OpenAI、Anthropic、Kimi 等提供商,填入其 API 密钥即可使用。",
|
|
2951
|
+
addCustomHint: "连接中转站、自部署服务或其他兼容 OpenAI / Anthropic 协议的接口,需填写 API 地址、协议和模型。",
|
|
2952
|
+
addCatalogExhausted: "目录中的提供商都已添加。",
|
|
2953
|
+
addCustomUnavailable: "没有可用的 API 协议。",
|
|
2954
|
+
provider: "提供商",
|
|
2776
2955
|
close: "关闭",
|
|
2777
2956
|
cancel: "取消",
|
|
2778
2957
|
apply: "保存",
|
|
@@ -2781,7 +2960,7 @@ window.__ModuleLoader__.load({
|
|
|
2781
2960
|
credentialConfigured: "API 密钥已配置",
|
|
2782
2961
|
credentialMissing: "API 密钥缺失",
|
|
2783
2962
|
readOnly: "当前部署的设置文档为只读。",
|
|
2784
|
-
loadFailed: "
|
|
2963
|
+
loadFailed: "加载提供商目录失败",
|
|
2785
2964
|
conflict: "这张卡片打开期间,这些设置已被其他地方改动。请关闭后重新打开,在当前值上编辑。",
|
|
2786
2965
|
retry: "重试",
|
|
2787
2966
|
keyInput: "API 密钥",
|
|
@@ -2791,10 +2970,9 @@ window.__ModuleLoader__.load({
|
|
|
2791
2970
|
keyEnvLocked: "由启动环境提供(只读)",
|
|
2792
2971
|
customized: "自定义设置",
|
|
2793
2972
|
baseUrl: "API 地址",
|
|
2794
|
-
baseUrlDefault: "
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
deepSeekEndpointHint: "请填写与当前连接配置兼容的 API 地址。",
|
|
2973
|
+
baseUrlDefault: "提供商默认",
|
|
2974
|
+
deepSeekBaseUrl: "https://api.deepseek.com/anthropic",
|
|
2975
|
+
deepSeekEndpointHint: "请填写兼容 Anthropic Messages 协议的 API 地址。",
|
|
2798
2976
|
models: "模型目录",
|
|
2799
2977
|
modelsInherited: "正在使用适配器默认模型",
|
|
2800
2978
|
modelsCustomized: "已自定义模型目录",
|
|
@@ -2804,53 +2982,56 @@ window.__ModuleLoader__.load({
|
|
|
2804
2982
|
modelName: "显示名称",
|
|
2805
2983
|
modelNamePlaceholder: "留空时使用模型 ID",
|
|
2806
2984
|
contextWindow: "上下文窗口",
|
|
2807
|
-
contextWindowPlaceholder: "
|
|
2985
|
+
contextWindowPlaceholder: "使用提供商默认值",
|
|
2808
2986
|
maxTokens: "最大输出 token 数",
|
|
2809
|
-
maxTokensPlaceholder: "
|
|
2810
|
-
modelAdvanced: "
|
|
2987
|
+
maxTokensPlaceholder: "使用提供商默认值",
|
|
2988
|
+
modelAdvanced: "模型选项",
|
|
2989
|
+
modelInputTypes: "输入类型",
|
|
2990
|
+
modelInputText: "文本",
|
|
2991
|
+
modelInputImage: "图片",
|
|
2811
2992
|
addModel: "添加模型",
|
|
2812
2993
|
removeModel: "删除模型",
|
|
2813
2994
|
modelsEmpty: "模型选择器中将不显示任何模型;目录外 ID 仍可直接发送。",
|
|
2814
2995
|
keyBlank: "请输入 API 密钥;留空则保持已存储的密钥。",
|
|
2815
|
-
keyBlankNew: "请输入 API
|
|
2996
|
+
keyBlankNew: "请输入 API 密钥;若该提供商以其他方式鉴权,可以留空。",
|
|
2816
2997
|
keyIllegalCharacters: "该 API 密钥格式错误,请检查。",
|
|
2817
2998
|
modelIdRequired: "模型 ID 不能为空。",
|
|
2818
2999
|
modelIdDuplicate: "模型 ID 不能重复。",
|
|
2819
3000
|
modelNameInvalid: "显示名称不能为空。",
|
|
2820
3001
|
modelContextInvalid: "上下文窗口必须是正数,例如 131072、256K 或 1M。",
|
|
2821
3002
|
modelMaxTokensInvalid: "最大输出 token 数必须是正数,例如 8192、64K 或 1M。",
|
|
2822
|
-
advancedHint: "其余字段在
|
|
3003
|
+
advancedHint: "其余字段在 cordis.patch.yml 中,请直接编辑对应段。",
|
|
2823
3004
|
modelCapacityInvalid: "容量需为数字,可加 K 或 M 后缀。",
|
|
2824
3005
|
modelDuplicate: "每个模型 ID 只能出现一次。",
|
|
2825
|
-
modelContextWindow: "上下文窗口",
|
|
2826
|
-
modelMaxTokens: "最大输出 token",
|
|
2827
3006
|
fetchModels: "获取可用模型",
|
|
2828
|
-
fetching: "
|
|
3007
|
+
fetching: "正在询问提供商…",
|
|
2829
3008
|
fetchNeedsBaseUrl: "请先填写 API 地址,再获取。",
|
|
2830
|
-
fetchEmpty: "
|
|
3009
|
+
fetchEmpty: "该提供商没有列出任何模型,请手动添加。",
|
|
2831
3010
|
fetchTitle: "选择要添加的模型",
|
|
2832
|
-
fetchDescription: "
|
|
3011
|
+
fetchDescription: "以下是模型提供商的可用模型,勾选要添加的模型。",
|
|
2833
3012
|
fetchSearch: "搜索模型",
|
|
2834
3013
|
fetchNoMatches: "没有匹配的模型。",
|
|
2835
3014
|
fetchSelectAll: "全选",
|
|
2836
3015
|
fetchDeselectAll: "取消全选",
|
|
2837
3016
|
fetchAdopt: "添加所选",
|
|
2838
|
-
customAdd: "添加自定义提供方",
|
|
2839
|
-
customTitle: "自定义提供方",
|
|
2840
3017
|
customTag: "自定义",
|
|
2841
3018
|
customRoute: "Provider ID",
|
|
2842
|
-
customRouteHint: "
|
|
3019
|
+
customRouteHint: "以小写字母开头的标识,在请求中唯一标识该提供商,并用于派生凭据名。",
|
|
2843
3020
|
customRouteInvalid: "需以小写字母开头,之后可用小写字母、数字和短横线。",
|
|
2844
|
-
customRouteTaken: "
|
|
3021
|
+
customRouteTaken: "已有提供商使用了这个 ID。",
|
|
2845
3022
|
customDisplayName: "显示名称",
|
|
2846
3023
|
customApi: "API 协议",
|
|
2847
3024
|
customApiUnset: "未选择",
|
|
2848
|
-
|
|
3025
|
+
protocolOpenAiCompletions: "OpenAI Chat Completions",
|
|
3026
|
+
protocolOpenAiResponses: "OpenAI Responses",
|
|
3027
|
+
protocolAnthropicMessages: "Anthropic Messages",
|
|
3028
|
+
customNeedsBaseUrl: "自定义模型 API 需要填写 API 地址。",
|
|
2849
3029
|
customBaseUrlInvalid: "请输入有效的 HTTP 或 HTTPS 地址。",
|
|
2850
|
-
customNeedsModels: "
|
|
3030
|
+
customNeedsModels: "自定义模型 API 至少需要一个模型。",
|
|
2851
3031
|
customBaseUrlPlaceholder: "https://gateway.example/v1",
|
|
3032
|
+
customAnthropicBaseUrlPlaceholder: "https://gateway.example",
|
|
2852
3033
|
settingsPathUnresolvable: "无法解析设置路径",
|
|
2853
|
-
create: "
|
|
3034
|
+
create: "创建提供商",
|
|
2854
3035
|
creating: "创建中…",
|
|
2855
3036
|
welcomeTitle: "内测声明",
|
|
2856
3037
|
welcomeBody: "DeepSeek Harness 目前的 0.1 版本仍处在面向 Harness 开发者进行测试的阶段,还有许多地方需要持续改进和打磨,希望听取广大开发者的反馈建议。预计 DeepSeek Harness 的核心插件以及基础 API 都会在接下来的一段时间内快速迭代、持续演化。\n\n我们期待与全球开发者一起,在开源、开放、可复用、可组合的基础设施之上,共同探索智能上限。欢迎全球 Harness 开发者加入 DSH 插件生态。",
|
|
@@ -2864,6 +3045,904 @@ window.__ModuleLoader__.load({
|
|
|
2864
3045
|
keyRequired: "请输入 API 密钥后继续。"
|
|
2865
3046
|
};
|
|
2866
3047
|
//#endregion
|
|
3048
|
+
//#region ../../../vendor/cosmokit/src/misc.ts
|
|
3049
|
+
/** Return true when a value is `null` or `undefined`. */
|
|
3050
|
+
function isNullable(value) {
|
|
3051
|
+
return value === null || value === void 0;
|
|
3052
|
+
}
|
|
3053
|
+
/** Return true for non-array object values. */
|
|
3054
|
+
function isPlainObject(data) {
|
|
3055
|
+
return data && typeof data === "object" && !Array.isArray(data);
|
|
3056
|
+
}
|
|
3057
|
+
/** Filter object entries and return a new object. */
|
|
3058
|
+
function filterKeys(object, filter) {
|
|
3059
|
+
return Object.fromEntries(Object.entries(object).filter(([key, value]) => filter(key, value)));
|
|
3060
|
+
}
|
|
3061
|
+
/** Map object values while preserving the original key set. */
|
|
3062
|
+
function mapValues(object, transform) {
|
|
3063
|
+
return Object.fromEntries(Object.entries(object).map(([key, value]) => [key, transform(value, key)]));
|
|
3064
|
+
}
|
|
3065
|
+
/** Pick selected keys from an object, optionally including `undefined` values. */
|
|
3066
|
+
function pick(source, keys, forced) {
|
|
3067
|
+
if (!keys) return { ...source };
|
|
3068
|
+
const result = {};
|
|
3069
|
+
for (const key of keys) if (forced || source[key] !== void 0) result[key] = source[key];
|
|
3070
|
+
return result;
|
|
3071
|
+
}
|
|
3072
|
+
//#endregion
|
|
3073
|
+
//#region ../../../vendor/cosmokit/src/volatile.ts
|
|
3074
|
+
/** Shared config references used by schema validators and plugin runtimes. */
|
|
3075
|
+
const write = Symbol.for("cosmokit.volatile.write");
|
|
3076
|
+
function snapshot(value, ancestors = /* @__PURE__ */ new Set()) {
|
|
3077
|
+
if (typeof value === "function") throw new TypeError("volatile config cannot contain functions");
|
|
3078
|
+
if (value === null || typeof value !== "object") return value;
|
|
3079
|
+
if (ancestors.has(value)) throw new TypeError("volatile config cannot contain cycles");
|
|
3080
|
+
ancestors.add(value);
|
|
3081
|
+
try {
|
|
3082
|
+
if (Array.isArray(value)) return Object.freeze(value.map((item) => snapshot(item, ancestors)));
|
|
3083
|
+
if (Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) throw new TypeError("volatile config objects must be plain objects or arrays");
|
|
3084
|
+
return Object.freeze(Object.fromEntries(Object.entries(value).map(([key, item]) => [key, snapshot(item, ancestors)])));
|
|
3085
|
+
} finally {
|
|
3086
|
+
ancestors.delete(value);
|
|
3087
|
+
}
|
|
3088
|
+
}
|
|
3089
|
+
/**
|
|
3090
|
+
* Create a detached reference containing an immutable copy of the supplied data.
|
|
3091
|
+
* @param value - validated config data; class instances and functions are unsupported.
|
|
3092
|
+
* @returns a reference whose value is updated only by its owning runtime.
|
|
3093
|
+
*/
|
|
3094
|
+
function createVolatile(value) {
|
|
3095
|
+
let current = snapshot(value);
|
|
3096
|
+
return Object.freeze({
|
|
3097
|
+
get: () => current,
|
|
3098
|
+
[write]: (value) => {
|
|
3099
|
+
current = value;
|
|
3100
|
+
}
|
|
3101
|
+
});
|
|
3102
|
+
}
|
|
3103
|
+
/**
|
|
3104
|
+
* Identify references across ESM/CJS copies of the shared library.
|
|
3105
|
+
* @param value - a parsed config value.
|
|
3106
|
+
* @returns whether the value implements the shared reference protocol.
|
|
3107
|
+
*/
|
|
3108
|
+
function isVolatile(value) {
|
|
3109
|
+
return typeof value === "object" && value !== null && write in value;
|
|
3110
|
+
}
|
|
3111
|
+
//#endregion
|
|
3112
|
+
//#region ../../../vendor/cosmokit/src/types.ts
|
|
3113
|
+
/** Test values using `instanceof` with a `toStringTag` fallback. */
|
|
3114
|
+
function is(type, value) {
|
|
3115
|
+
if (arguments.length === 1) return (value) => is(type, value);
|
|
3116
|
+
return type in globalThis && value instanceof globalThis[type] || Object.prototype.toString.call(value).slice(8, -1) === type;
|
|
3117
|
+
}
|
|
3118
|
+
function isArrayBufferLike(value) {
|
|
3119
|
+
return is("ArrayBuffer", value) || is("SharedArrayBuffer", value);
|
|
3120
|
+
}
|
|
3121
|
+
function isArrayBufferSource(value) {
|
|
3122
|
+
return isArrayBufferLike(value) || ArrayBuffer.isView(value);
|
|
3123
|
+
}
|
|
3124
|
+
let Binary;
|
|
3125
|
+
(function(_Binary) {
|
|
3126
|
+
_Binary.is = isArrayBufferLike;
|
|
3127
|
+
_Binary.isSource = isArrayBufferSource;
|
|
3128
|
+
function fromSource(source) {
|
|
3129
|
+
if (ArrayBuffer.isView(source)) return source.buffer.slice(source.byteOffset, source.byteOffset + source.byteLength);
|
|
3130
|
+
else return source;
|
|
3131
|
+
}
|
|
3132
|
+
_Binary.fromSource = fromSource;
|
|
3133
|
+
function toBase64(source) {
|
|
3134
|
+
source = fromSource(source);
|
|
3135
|
+
if (typeof Buffer !== "undefined") return Buffer.from(source).toString("base64");
|
|
3136
|
+
let binary = "";
|
|
3137
|
+
const bytes = new Uint8Array(source);
|
|
3138
|
+
for (let i = 0; i < bytes.byteLength; i++) binary += String.fromCharCode(bytes[i]);
|
|
3139
|
+
return btoa(binary);
|
|
3140
|
+
}
|
|
3141
|
+
_Binary.toBase64 = toBase64;
|
|
3142
|
+
function fromBase64(source) {
|
|
3143
|
+
if (typeof Buffer !== "undefined") return fromSource(Buffer.from(source, "base64"));
|
|
3144
|
+
return Uint8Array.from(atob(source), (c) => c.charCodeAt(0));
|
|
3145
|
+
}
|
|
3146
|
+
_Binary.fromBase64 = fromBase64;
|
|
3147
|
+
function toHex(source) {
|
|
3148
|
+
source = fromSource(source);
|
|
3149
|
+
if (typeof Buffer !== "undefined") return Buffer.from(source).toString("hex");
|
|
3150
|
+
return Array.from(new Uint8Array(source), (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
3151
|
+
}
|
|
3152
|
+
_Binary.toHex = toHex;
|
|
3153
|
+
function fromHex(source) {
|
|
3154
|
+
if (typeof Buffer !== "undefined") return fromSource(Buffer.from(source, "hex"));
|
|
3155
|
+
const hex = source.length % 2 === 0 ? source : source.slice(0, source.length - 1);
|
|
3156
|
+
const buffer = [];
|
|
3157
|
+
for (let i = 0; i < hex.length; i += 2) buffer.push(parseInt(`${hex[i]}${hex[i + 1]}`, 16));
|
|
3158
|
+
return Uint8Array.from(buffer).buffer;
|
|
3159
|
+
}
|
|
3160
|
+
_Binary.fromHex = fromHex;
|
|
3161
|
+
})(Binary || (Binary = {}));
|
|
3162
|
+
Binary.fromBase64;
|
|
3163
|
+
Binary.toBase64;
|
|
3164
|
+
Binary.fromHex;
|
|
3165
|
+
Binary.toHex;
|
|
3166
|
+
/** Deep-clone common JavaScript values while preserving prototypes and cycles. */
|
|
3167
|
+
function clone(source, refs = /* @__PURE__ */ new Map()) {
|
|
3168
|
+
if (!source || typeof source !== "object") return source;
|
|
3169
|
+
if (is("Date", source)) return new Date(source.valueOf());
|
|
3170
|
+
if (is("RegExp", source)) return new RegExp(source.source, source.flags);
|
|
3171
|
+
if (isArrayBufferLike(source)) return source.slice(0);
|
|
3172
|
+
if (ArrayBuffer.isView(source)) return source.buffer.slice(source.byteOffset, source.byteOffset + source.byteLength);
|
|
3173
|
+
const cached = refs.get(source);
|
|
3174
|
+
if (cached) return cached;
|
|
3175
|
+
if (Array.isArray(source)) {
|
|
3176
|
+
const result = [];
|
|
3177
|
+
refs.set(source, result);
|
|
3178
|
+
source.forEach((value, index) => {
|
|
3179
|
+
result[index] = Reflect.apply(clone, null, [value, refs]);
|
|
3180
|
+
});
|
|
3181
|
+
return result;
|
|
3182
|
+
}
|
|
3183
|
+
const result = Object.create(Object.getPrototypeOf(source));
|
|
3184
|
+
refs.set(source, result);
|
|
3185
|
+
for (const key of Reflect.ownKeys(source)) {
|
|
3186
|
+
const descriptor = { ...Reflect.getOwnPropertyDescriptor(source, key) };
|
|
3187
|
+
if ("value" in descriptor) descriptor.value = Reflect.apply(clone, null, [descriptor.value, refs]);
|
|
3188
|
+
Reflect.defineProperty(result, key, descriptor);
|
|
3189
|
+
}
|
|
3190
|
+
return result;
|
|
3191
|
+
}
|
|
3192
|
+
/**
|
|
3193
|
+
* Compare values recursively, treating two volatile references as equal regardless of value.
|
|
3194
|
+
* Strict comparison distinguishes null/undefined, treats opaque objects by identity,
|
|
3195
|
+
* compares URLs by normalized href, treats array holes as undefined, and considers distinct cyclic structures unequal.
|
|
3196
|
+
* @param a - first value.
|
|
3197
|
+
* @param b - second value.
|
|
3198
|
+
* @param strict - whether to require strict data equality outside volatile references.
|
|
3199
|
+
* @returns whether the values compare equal.
|
|
3200
|
+
*/
|
|
3201
|
+
function deepEqual(a, b, strict) {
|
|
3202
|
+
const ancestors = /* @__PURE__ */ new Set();
|
|
3203
|
+
function compare(a, b) {
|
|
3204
|
+
if (a === b) return true;
|
|
3205
|
+
if (isVolatile(a) || isVolatile(b)) return isVolatile(a) && isVolatile(b);
|
|
3206
|
+
if (!strict && isNullable(a) && isNullable(b)) return true;
|
|
3207
|
+
if (typeof a !== typeof b || typeof a !== "object" || !a || !b) return false;
|
|
3208
|
+
if (ancestors.has(a)) return false;
|
|
3209
|
+
function check(test, then) {
|
|
3210
|
+
return test(a) ? test(b) ? then(a, b) : false : test(b) ? false : void 0;
|
|
3211
|
+
}
|
|
3212
|
+
ancestors.add(a);
|
|
3213
|
+
try {
|
|
3214
|
+
return check(Array.isArray, (a, b) => {
|
|
3215
|
+
if (a.length !== b.length) return false;
|
|
3216
|
+
for (let index = 0; index < a.length; index++) if (!compare(a[index], b[index])) return false;
|
|
3217
|
+
return true;
|
|
3218
|
+
}) ?? 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) => {
|
|
3219
|
+
if (a.byteLength !== b.byteLength) return false;
|
|
3220
|
+
const viewA = new Uint8Array(a);
|
|
3221
|
+
const viewB = new Uint8Array(b);
|
|
3222
|
+
for (let i = 0; i < viewA.length; i++) if (viewA[i] !== viewB[i]) return false;
|
|
3223
|
+
return true;
|
|
3224
|
+
}) ?? ((!strict || [a, b].every((value) => Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null)) && Object.keys({
|
|
3225
|
+
...a,
|
|
3226
|
+
...b
|
|
3227
|
+
}).every((key) => compare(a[key], b[key])));
|
|
3228
|
+
} finally {
|
|
3229
|
+
ancestors.delete(a);
|
|
3230
|
+
}
|
|
3231
|
+
}
|
|
3232
|
+
return compare(a, b);
|
|
3233
|
+
}
|
|
3234
|
+
//#endregion
|
|
3235
|
+
//#region ../../../vendor/cosmokit/src/time.ts
|
|
3236
|
+
let Time;
|
|
3237
|
+
(function(_Time) {
|
|
3238
|
+
_Time.millisecond = 1;
|
|
3239
|
+
const second = _Time.second = 1e3;
|
|
3240
|
+
const minute = _Time.minute = second * 60;
|
|
3241
|
+
const hour = _Time.hour = minute * 60;
|
|
3242
|
+
const day = _Time.day = hour * 24;
|
|
3243
|
+
const week = _Time.week = day * 7;
|
|
3244
|
+
let timezoneOffset = (/* @__PURE__ */ new Date()).getTimezoneOffset();
|
|
3245
|
+
function setTimezoneOffset(offset) {
|
|
3246
|
+
timezoneOffset = offset;
|
|
3247
|
+
}
|
|
3248
|
+
_Time.setTimezoneOffset = setTimezoneOffset;
|
|
3249
|
+
function getTimezoneOffset() {
|
|
3250
|
+
return timezoneOffset;
|
|
3251
|
+
}
|
|
3252
|
+
_Time.getTimezoneOffset = getTimezoneOffset;
|
|
3253
|
+
function getDateNumber(date = /* @__PURE__ */ new Date(), offset) {
|
|
3254
|
+
if (typeof date === "number") date = new Date(date);
|
|
3255
|
+
if (offset === void 0) offset = timezoneOffset;
|
|
3256
|
+
return Math.floor((date.valueOf() / minute - offset) / 1440);
|
|
3257
|
+
}
|
|
3258
|
+
_Time.getDateNumber = getDateNumber;
|
|
3259
|
+
function fromDateNumber(value, offset) {
|
|
3260
|
+
const date = new Date(value * day);
|
|
3261
|
+
if (offset === void 0) offset = timezoneOffset;
|
|
3262
|
+
return new Date(+date + offset * minute);
|
|
3263
|
+
}
|
|
3264
|
+
_Time.fromDateNumber = fromDateNumber;
|
|
3265
|
+
const numeric = /\d+(?:\.\d+)?/.source;
|
|
3266
|
+
const timeRegExp = new RegExp(`^${[
|
|
3267
|
+
"w(?:eek(?:s)?)?",
|
|
3268
|
+
"d(?:ay(?:s)?)?",
|
|
3269
|
+
"h(?:our(?:s)?)?",
|
|
3270
|
+
"m(?:in(?:ute)?(?:s)?)?",
|
|
3271
|
+
"s(?:ec(?:ond)?(?:s)?)?"
|
|
3272
|
+
].map((unit) => `(${numeric}${unit})?`).join("")}$`);
|
|
3273
|
+
function parseTime(source) {
|
|
3274
|
+
const capture = timeRegExp.exec(source);
|
|
3275
|
+
if (!capture) return 0;
|
|
3276
|
+
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);
|
|
3277
|
+
}
|
|
3278
|
+
_Time.parseTime = parseTime;
|
|
3279
|
+
function parseDate(date) {
|
|
3280
|
+
const parsed = parseTime(date);
|
|
3281
|
+
if (parsed) date = Date.now() + parsed;
|
|
3282
|
+
else if (/^\d{1,2}(:\d{1,2}){1,2}$/.test(date)) date = `${(/* @__PURE__ */ new Date()).toLocaleDateString()}-${date}`;
|
|
3283
|
+
else if (/^\d{1,2}-\d{1,2}-\d{1,2}(:\d{1,2}){1,2}$/.test(date)) date = `${(/* @__PURE__ */ new Date()).getFullYear()}-${date}`;
|
|
3284
|
+
return date ? new Date(date) : /* @__PURE__ */ new Date();
|
|
3285
|
+
}
|
|
3286
|
+
_Time.parseDate = parseDate;
|
|
3287
|
+
function format(ms) {
|
|
3288
|
+
const abs = Math.abs(ms);
|
|
3289
|
+
if (abs >= day - hour / 2) return Math.round(ms / day) + "d";
|
|
3290
|
+
else if (abs >= hour - minute / 2) return Math.round(ms / hour) + "h";
|
|
3291
|
+
else if (abs >= minute - second / 2) return Math.round(ms / minute) + "m";
|
|
3292
|
+
else if (abs >= second) return Math.round(ms / second) + "s";
|
|
3293
|
+
return ms + "ms";
|
|
3294
|
+
}
|
|
3295
|
+
_Time.format = format;
|
|
3296
|
+
function toDigits(source, length = 2) {
|
|
3297
|
+
return source.toString().padStart(length, "0");
|
|
3298
|
+
}
|
|
3299
|
+
_Time.toDigits = toDigits;
|
|
3300
|
+
function template(template, time = /* @__PURE__ */ new Date()) {
|
|
3301
|
+
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));
|
|
3302
|
+
}
|
|
3303
|
+
_Time.template = template;
|
|
3304
|
+
})(Time || (Time = {}));
|
|
3305
|
+
//#endregion
|
|
3306
|
+
//#region ../../../vendor/schemastery/src/index.ts
|
|
3307
|
+
const kSchema = Symbol.for("schemastery");
|
|
3308
|
+
const kValidationError = Symbol.for("ValidationError");
|
|
3309
|
+
globalThis.__schemastery_index__ ??= 0;
|
|
3310
|
+
globalThis.__schemastery_refs__ = void 0;
|
|
3311
|
+
var ValidationError = class extends TypeError {
|
|
3312
|
+
options;
|
|
3313
|
+
name = "ValidationError";
|
|
3314
|
+
constructor(message, options) {
|
|
3315
|
+
let prefix = "$";
|
|
3316
|
+
for (const segment of options.path || []) if (typeof segment === "string") prefix += "." + segment;
|
|
3317
|
+
else if (typeof segment === "number") prefix += "[" + segment + "]";
|
|
3318
|
+
else if (typeof segment === "symbol") prefix += `[Symbol(${segment.toString()})]`;
|
|
3319
|
+
if (prefix.startsWith(".")) prefix = prefix.slice(1);
|
|
3320
|
+
super((prefix === "$" ? "" : `${prefix} `) + message);
|
|
3321
|
+
this.options = options;
|
|
3322
|
+
}
|
|
3323
|
+
static is(error) {
|
|
3324
|
+
return !!error?.[kValidationError];
|
|
3325
|
+
}
|
|
3326
|
+
};
|
|
3327
|
+
Object.defineProperty(ValidationError.prototype, kValidationError, { value: true });
|
|
3328
|
+
const Schema = function(options) {
|
|
3329
|
+
const schema = function(data, options = {}) {
|
|
3330
|
+
return Schema.resolve(data, schema, options)[0];
|
|
3331
|
+
};
|
|
3332
|
+
if (options.refs) {
|
|
3333
|
+
const refs = mapValues(options.refs, (options) => new Schema(options));
|
|
3334
|
+
const getRef = (uid) => refs[uid];
|
|
3335
|
+
for (const key in refs) {
|
|
3336
|
+
const options = refs[key];
|
|
3337
|
+
options.sKey = getRef(options.sKey);
|
|
3338
|
+
options.inner = getRef(options.inner);
|
|
3339
|
+
options.list = options.list && options.list.map(getRef);
|
|
3340
|
+
options.dict = options.dict && mapValues(options.dict, getRef);
|
|
3341
|
+
}
|
|
3342
|
+
return refs[options.uid];
|
|
3343
|
+
}
|
|
3344
|
+
Object.assign(schema, options);
|
|
3345
|
+
if (typeof schema.callback === "string") try {
|
|
3346
|
+
schema.callback = new Function("return " + schema.callback)();
|
|
3347
|
+
} catch {}
|
|
3348
|
+
Object.defineProperty(schema, "uid", { value: globalThis.__schemastery_index__++ });
|
|
3349
|
+
Object.setPrototypeOf(schema, Schema.prototype);
|
|
3350
|
+
schema.meta ||= {};
|
|
3351
|
+
schema.toString = schema.toString.bind(schema);
|
|
3352
|
+
return schema;
|
|
3353
|
+
};
|
|
3354
|
+
Schema.prototype = Object.create(Function.prototype);
|
|
3355
|
+
Schema.prototype[kSchema] = true;
|
|
3356
|
+
Object.defineProperty(Schema.prototype, "~standard", { get() {
|
|
3357
|
+
return {
|
|
3358
|
+
version: 1,
|
|
3359
|
+
vendor: "schemastery",
|
|
3360
|
+
validate: (value) => {
|
|
3361
|
+
try {
|
|
3362
|
+
return { value: Schema.resolve(value, this, {})[0] };
|
|
3363
|
+
} catch (error) {
|
|
3364
|
+
if (ValidationError.is(error)) return { issues: [{
|
|
3365
|
+
message: error.message,
|
|
3366
|
+
path: error.options.path
|
|
3367
|
+
}] };
|
|
3368
|
+
throw error;
|
|
3369
|
+
}
|
|
3370
|
+
}
|
|
3371
|
+
};
|
|
3372
|
+
} });
|
|
3373
|
+
Schema.ValidationError = ValidationError;
|
|
3374
|
+
Schema.prototype.toJSON = function toJSON() {
|
|
3375
|
+
if (globalThis.__schemastery_refs__) {
|
|
3376
|
+
globalThis.__schemastery_refs__[this.uid] ??= JSON.parse(JSON.stringify({ ...this }));
|
|
3377
|
+
return this.uid;
|
|
3378
|
+
}
|
|
3379
|
+
globalThis.__schemastery_refs__ = { [this.uid]: { ...this } };
|
|
3380
|
+
globalThis.__schemastery_refs__[this.uid] = JSON.parse(JSON.stringify({ ...this }));
|
|
3381
|
+
const result = {
|
|
3382
|
+
uid: this.uid,
|
|
3383
|
+
refs: globalThis.__schemastery_refs__
|
|
3384
|
+
};
|
|
3385
|
+
globalThis.__schemastery_refs__ = void 0;
|
|
3386
|
+
return result;
|
|
3387
|
+
};
|
|
3388
|
+
Schema.prototype.set = function set(key, value) {
|
|
3389
|
+
this.dict[key] = value;
|
|
3390
|
+
return this;
|
|
3391
|
+
};
|
|
3392
|
+
Schema.prototype.push = function push(value) {
|
|
3393
|
+
this.list.push(value);
|
|
3394
|
+
return this;
|
|
3395
|
+
};
|
|
3396
|
+
function mergeDesc(original, messages) {
|
|
3397
|
+
const result = typeof original === "string" ? { "": original } : { ...original };
|
|
3398
|
+
for (const locale in messages) {
|
|
3399
|
+
const value = messages[locale];
|
|
3400
|
+
if (value?.$description || value?.$desc) result[locale] = value.$description || value.$desc;
|
|
3401
|
+
else if (typeof value === "string") result[locale] = value;
|
|
3402
|
+
}
|
|
3403
|
+
return result;
|
|
3404
|
+
}
|
|
3405
|
+
function getInner(value) {
|
|
3406
|
+
return value?.$value ?? value?.$inner;
|
|
3407
|
+
}
|
|
3408
|
+
function extractKeys(data) {
|
|
3409
|
+
return filterKeys(data ?? {}, (key) => !key.startsWith("$"));
|
|
3410
|
+
}
|
|
3411
|
+
Schema.prototype.i18n = function i18n(messages) {
|
|
3412
|
+
const schema = Schema(this);
|
|
3413
|
+
const desc = mergeDesc(schema.meta.description, messages);
|
|
3414
|
+
if (Object.keys(desc).length) schema.meta.description = desc;
|
|
3415
|
+
if (schema.dict) schema.dict = mapValues(schema.dict, (inner, key) => {
|
|
3416
|
+
return inner.i18n(mapValues(messages, (data) => getInner(data)?.[key] ?? data?.[key]));
|
|
3417
|
+
});
|
|
3418
|
+
if (schema.list) schema.list = schema.list.map((inner, index) => {
|
|
3419
|
+
return inner.i18n(mapValues(messages, (data = {}) => {
|
|
3420
|
+
if (Array.isArray(getInner(data))) return getInner(data)[index];
|
|
3421
|
+
if (Array.isArray(data)) return data[index];
|
|
3422
|
+
return extractKeys(data);
|
|
3423
|
+
}));
|
|
3424
|
+
});
|
|
3425
|
+
if (schema.inner) schema.inner = schema.inner.i18n(mapValues(messages, (data) => {
|
|
3426
|
+
if (getInner(data)) return getInner(data);
|
|
3427
|
+
return extractKeys(data);
|
|
3428
|
+
}));
|
|
3429
|
+
if (schema.sKey) schema.sKey = schema.sKey.i18n(mapValues(messages, (data) => data?.$key));
|
|
3430
|
+
return schema;
|
|
3431
|
+
};
|
|
3432
|
+
Schema.prototype.extra = function extra(key, value) {
|
|
3433
|
+
const schema = Schema(this);
|
|
3434
|
+
schema.meta = {
|
|
3435
|
+
...schema.meta,
|
|
3436
|
+
[key]: value
|
|
3437
|
+
};
|
|
3438
|
+
return schema;
|
|
3439
|
+
};
|
|
3440
|
+
for (const key of [
|
|
3441
|
+
"required",
|
|
3442
|
+
"disabled",
|
|
3443
|
+
"collapse",
|
|
3444
|
+
"hidden",
|
|
3445
|
+
"loose"
|
|
3446
|
+
]) Object.assign(Schema.prototype, { [key](value = true) {
|
|
3447
|
+
const schema = Schema(this);
|
|
3448
|
+
schema.meta = {
|
|
3449
|
+
...schema.meta,
|
|
3450
|
+
[key]: value
|
|
3451
|
+
};
|
|
3452
|
+
return schema;
|
|
3453
|
+
} });
|
|
3454
|
+
Schema.prototype.deprecated = function deprecated() {
|
|
3455
|
+
const schema = Schema(this);
|
|
3456
|
+
schema.meta.badges ||= [];
|
|
3457
|
+
schema.meta.badges.push({
|
|
3458
|
+
text: "deprecated",
|
|
3459
|
+
type: "danger"
|
|
3460
|
+
});
|
|
3461
|
+
return schema;
|
|
3462
|
+
};
|
|
3463
|
+
Schema.prototype.experimental = function experimental() {
|
|
3464
|
+
const schema = Schema(this);
|
|
3465
|
+
schema.meta.badges ||= [];
|
|
3466
|
+
schema.meta.badges.push({
|
|
3467
|
+
text: "experimental",
|
|
3468
|
+
type: "warning"
|
|
3469
|
+
});
|
|
3470
|
+
return schema;
|
|
3471
|
+
};
|
|
3472
|
+
Schema.prototype.pattern = function pattern(regexp) {
|
|
3473
|
+
const schema = Schema(this);
|
|
3474
|
+
const pattern = pick(regexp, ["source", "flags"]);
|
|
3475
|
+
schema.meta = {
|
|
3476
|
+
...schema.meta,
|
|
3477
|
+
pattern
|
|
3478
|
+
};
|
|
3479
|
+
return schema;
|
|
3480
|
+
};
|
|
3481
|
+
Schema.prototype.simplify = function simplify(value) {
|
|
3482
|
+
if (isVolatile(value)) value = value.get();
|
|
3483
|
+
if (deepEqual(value, this.meta.default, this.type === "dict")) return null;
|
|
3484
|
+
if (isNullable(value)) return value;
|
|
3485
|
+
if (this.type === "object" || this.type === "dict") {
|
|
3486
|
+
const result = {};
|
|
3487
|
+
for (const key in value) {
|
|
3488
|
+
const item = (this.type === "object" ? this.dict[key] : this.inner)?.simplify(value[key]);
|
|
3489
|
+
if (this.type === "dict" || !isNullable(item)) result[key] = item;
|
|
3490
|
+
}
|
|
3491
|
+
if (deepEqual(result, this.meta.default, this.type === "dict")) return null;
|
|
3492
|
+
return result;
|
|
3493
|
+
} else if (this.type === "array" || this.type === "tuple") {
|
|
3494
|
+
const result = [];
|
|
3495
|
+
value.forEach((value, index) => {
|
|
3496
|
+
const schema = this.type === "array" ? this.inner : this.list[index];
|
|
3497
|
+
const item = schema ? schema.simplify(value) : value;
|
|
3498
|
+
result.push(item);
|
|
3499
|
+
});
|
|
3500
|
+
return result;
|
|
3501
|
+
} else if (this.type === "intersect") {
|
|
3502
|
+
const result = {};
|
|
3503
|
+
for (const item of this.list) Object.assign(result, item.simplify(value));
|
|
3504
|
+
return result;
|
|
3505
|
+
} else if (this.type === "union") for (const schema of this.list) try {
|
|
3506
|
+
Schema.resolve(value, schema, {});
|
|
3507
|
+
return schema.simplify(value);
|
|
3508
|
+
} catch {}
|
|
3509
|
+
return value;
|
|
3510
|
+
};
|
|
3511
|
+
Schema.prototype.toString = function toString(inline) {
|
|
3512
|
+
return formatters[this.type]?.(this, inline) ?? `Schema<${this.type}>`;
|
|
3513
|
+
};
|
|
3514
|
+
Schema.prototype.role = function role(role, extra) {
|
|
3515
|
+
const schema = Schema(this);
|
|
3516
|
+
schema.meta = {
|
|
3517
|
+
...schema.meta,
|
|
3518
|
+
role,
|
|
3519
|
+
extra
|
|
3520
|
+
};
|
|
3521
|
+
return schema;
|
|
3522
|
+
};
|
|
3523
|
+
for (const key of [
|
|
3524
|
+
"default",
|
|
3525
|
+
"link",
|
|
3526
|
+
"comment",
|
|
3527
|
+
"description",
|
|
3528
|
+
"max",
|
|
3529
|
+
"min",
|
|
3530
|
+
"step"
|
|
3531
|
+
]) Object.assign(Schema.prototype, { [key](value) {
|
|
3532
|
+
const schema = Schema(this);
|
|
3533
|
+
schema.meta = {
|
|
3534
|
+
...schema.meta,
|
|
3535
|
+
[key]: value
|
|
3536
|
+
};
|
|
3537
|
+
return schema;
|
|
3538
|
+
} });
|
|
3539
|
+
Schema.prototype.volatile = function volatile() {
|
|
3540
|
+
if (this.meta.volatile) throw new TypeError("volatile schema is already wrapped");
|
|
3541
|
+
return this.extra("volatile", true);
|
|
3542
|
+
};
|
|
3543
|
+
const resolvers = {};
|
|
3544
|
+
const checkedVolatile = Symbol("checked-volatile-schema");
|
|
3545
|
+
function validateVolatileSchema(schema, path = [], blocked = false, seen = /* @__PURE__ */ new Map()) {
|
|
3546
|
+
const states = seen.get(schema) ?? /* @__PURE__ */ new Set();
|
|
3547
|
+
if (states.has(blocked)) return;
|
|
3548
|
+
states.add(blocked);
|
|
3549
|
+
seen.set(schema, states);
|
|
3550
|
+
if (schema.meta?.volatile && blocked) throw new ValidationError("volatile fields require a fixed object path without an enclosing volatile field", { path });
|
|
3551
|
+
const nested = blocked || !!schema.meta?.volatile;
|
|
3552
|
+
if (schema.dict) for (const [key, child] of Object.entries(schema.dict)) validateVolatileSchema(child, [...path, key], nested, seen);
|
|
3553
|
+
if (schema.sKey) validateVolatileSchema(schema.sKey, [...path, "<key>"], true, seen);
|
|
3554
|
+
if (schema.inner && (schema.type !== "lazy" || schema.inner[kSchema])) validateVolatileSchema(schema.inner, [...path, "*"], true, seen);
|
|
3555
|
+
if (schema.list) for (let index = 0; index < schema.list.length; index++) validateVolatileSchema(schema.list[index], [...path, String(index)], true, seen);
|
|
3556
|
+
}
|
|
3557
|
+
Schema.extend = function extend(type, resolve) {
|
|
3558
|
+
resolvers[type] = resolve;
|
|
3559
|
+
};
|
|
3560
|
+
Schema.resolve = function resolve(data, schema, options = {}, strict = false) {
|
|
3561
|
+
if (!schema) return [data];
|
|
3562
|
+
if (!options[checkedVolatile]) {
|
|
3563
|
+
validateVolatileSchema(schema, options.path);
|
|
3564
|
+
options = {
|
|
3565
|
+
...options,
|
|
3566
|
+
[checkedVolatile]: true
|
|
3567
|
+
};
|
|
3568
|
+
}
|
|
3569
|
+
if (schema.meta?.volatile) {
|
|
3570
|
+
const inner = Schema(schema);
|
|
3571
|
+
inner.meta = {
|
|
3572
|
+
...schema.meta,
|
|
3573
|
+
volatile: false
|
|
3574
|
+
};
|
|
3575
|
+
const [value, adapted] = Schema.resolve(data, inner, options, strict);
|
|
3576
|
+
try {
|
|
3577
|
+
return [createVolatile(value), adapted];
|
|
3578
|
+
} catch (error) {
|
|
3579
|
+
throw new ValidationError(error instanceof Error ? error.message : String(error), options);
|
|
3580
|
+
}
|
|
3581
|
+
}
|
|
3582
|
+
if (options.ignore?.(data, schema)) return [data];
|
|
3583
|
+
if (isNullable(data) && schema.type !== "lazy") {
|
|
3584
|
+
if (schema.meta.required) throw new ValidationError(`missing required value`, options);
|
|
3585
|
+
let current = schema;
|
|
3586
|
+
let fallback = schema.meta.default;
|
|
3587
|
+
while (current?.type === "intersect" && isNullable(fallback)) {
|
|
3588
|
+
current = current.list[0];
|
|
3589
|
+
fallback = current?.meta.default;
|
|
3590
|
+
}
|
|
3591
|
+
if (isNullable(fallback)) return [data];
|
|
3592
|
+
data = clone(fallback);
|
|
3593
|
+
}
|
|
3594
|
+
const callback = resolvers[schema.type];
|
|
3595
|
+
if (!callback) throw new ValidationError(`unsupported type "${schema.type}"`, options);
|
|
3596
|
+
try {
|
|
3597
|
+
return callback(data, schema, options, strict);
|
|
3598
|
+
} catch (error) {
|
|
3599
|
+
if (!schema.meta.loose) throw error;
|
|
3600
|
+
return [schema.meta.default];
|
|
3601
|
+
}
|
|
3602
|
+
};
|
|
3603
|
+
Schema.from = function from(source) {
|
|
3604
|
+
if (isNullable(source)) return Schema.any();
|
|
3605
|
+
else if ([
|
|
3606
|
+
"string",
|
|
3607
|
+
"number",
|
|
3608
|
+
"boolean"
|
|
3609
|
+
].includes(typeof source)) return Schema.const(source).required();
|
|
3610
|
+
else if (source[kSchema]) return source;
|
|
3611
|
+
else if (typeof source === "function") switch (source) {
|
|
3612
|
+
case String: return Schema.string().required();
|
|
3613
|
+
case Number: return Schema.number().required();
|
|
3614
|
+
case Boolean: return Schema.boolean().required();
|
|
3615
|
+
case Function: return Schema.function().required();
|
|
3616
|
+
default: return Schema.is(source).required();
|
|
3617
|
+
}
|
|
3618
|
+
else throw new TypeError(`cannot infer schema from ${source}`);
|
|
3619
|
+
};
|
|
3620
|
+
Schema.lazy = function lazy(builder) {
|
|
3621
|
+
const toJSON = () => {
|
|
3622
|
+
if (!schema.inner[kSchema]) {
|
|
3623
|
+
schema.inner = schema.builder();
|
|
3624
|
+
schema.inner.meta = {
|
|
3625
|
+
...schema.meta,
|
|
3626
|
+
...schema.inner.meta
|
|
3627
|
+
};
|
|
3628
|
+
}
|
|
3629
|
+
return schema.inner.toJSON();
|
|
3630
|
+
};
|
|
3631
|
+
const schema = new Schema({
|
|
3632
|
+
type: "lazy",
|
|
3633
|
+
builder,
|
|
3634
|
+
inner: { toJSON }
|
|
3635
|
+
});
|
|
3636
|
+
return schema;
|
|
3637
|
+
};
|
|
3638
|
+
Schema.natural = function natural() {
|
|
3639
|
+
return Schema.number().step(1).min(0);
|
|
3640
|
+
};
|
|
3641
|
+
Schema.percent = function percent() {
|
|
3642
|
+
return Schema.number().step(.01).min(0).max(1).role("slider");
|
|
3643
|
+
};
|
|
3644
|
+
Schema.date = function date() {
|
|
3645
|
+
return Schema.union([Schema.is(Date), Schema.transform(Schema.string().role("datetime"), (value, options) => {
|
|
3646
|
+
const date = new Date(value);
|
|
3647
|
+
if (isNaN(+date)) throw new ValidationError(`invalid date "${value}"`, options);
|
|
3648
|
+
return date;
|
|
3649
|
+
}, true)]);
|
|
3650
|
+
};
|
|
3651
|
+
Schema.regExp = function regExp(flag = "") {
|
|
3652
|
+
return Schema.union([Schema.is(RegExp), Schema.transform(Schema.string().role("regexp", { flag }), (value, options) => {
|
|
3653
|
+
try {
|
|
3654
|
+
return new RegExp(value, flag);
|
|
3655
|
+
} catch (e) {
|
|
3656
|
+
throw new ValidationError(e.message, options);
|
|
3657
|
+
}
|
|
3658
|
+
}, true)]);
|
|
3659
|
+
};
|
|
3660
|
+
Schema.arrayBuffer = function arrayBuffer(encoding) {
|
|
3661
|
+
return Schema.union([
|
|
3662
|
+
Schema.is(ArrayBuffer),
|
|
3663
|
+
Schema.is(SharedArrayBuffer),
|
|
3664
|
+
Schema.transform(Schema.any(), (value, options) => {
|
|
3665
|
+
if (Binary.isSource(value)) return Binary.fromSource(value);
|
|
3666
|
+
throw new ValidationError(`expected ArrayBufferSource but got ${value}`, options);
|
|
3667
|
+
}, true),
|
|
3668
|
+
...encoding ? [Schema.transform(Schema.string(), (value, options) => {
|
|
3669
|
+
try {
|
|
3670
|
+
return encoding === "base64" ? Binary.fromBase64(value) : Binary.fromHex(value);
|
|
3671
|
+
} catch (e) {
|
|
3672
|
+
throw new ValidationError(e.message, options);
|
|
3673
|
+
}
|
|
3674
|
+
}, true)] : []
|
|
3675
|
+
]);
|
|
3676
|
+
};
|
|
3677
|
+
Schema.extend("lazy", (data, schema, options, strict) => {
|
|
3678
|
+
if (!schema.inner[kSchema]) {
|
|
3679
|
+
schema.inner = schema.builder();
|
|
3680
|
+
schema.inner.meta = {
|
|
3681
|
+
...schema.meta,
|
|
3682
|
+
...schema.inner.meta
|
|
3683
|
+
};
|
|
3684
|
+
validateVolatileSchema(schema.inner, options.path, true);
|
|
3685
|
+
}
|
|
3686
|
+
return Schema.resolve(data, schema.inner, options, strict);
|
|
3687
|
+
});
|
|
3688
|
+
Schema.extend("any", (data) => {
|
|
3689
|
+
return [data];
|
|
3690
|
+
});
|
|
3691
|
+
Schema.extend("never", (data, _, options) => {
|
|
3692
|
+
throw new ValidationError(`expected nullable but got ${data}`, options);
|
|
3693
|
+
});
|
|
3694
|
+
Schema.extend("const", (data, { value }, options) => {
|
|
3695
|
+
if (deepEqual(data, value)) return [value];
|
|
3696
|
+
throw new ValidationError(`expected ${value} but got ${data}`, options);
|
|
3697
|
+
});
|
|
3698
|
+
function checkWithinRange(data, meta, description, options, skipMin = false) {
|
|
3699
|
+
const { max = Infinity, min = -Infinity } = meta;
|
|
3700
|
+
if (data > max) throw new ValidationError(`expected ${description} <= ${max} but got ${data}`, options);
|
|
3701
|
+
if (data < min && !skipMin) throw new ValidationError(`expected ${description} >= ${min} but got ${data}`, options);
|
|
3702
|
+
}
|
|
3703
|
+
Schema.extend("string", (data, { meta }, options) => {
|
|
3704
|
+
if (typeof data !== "string") throw new ValidationError(`expected string but got ${data}`, options);
|
|
3705
|
+
if (meta.pattern) {
|
|
3706
|
+
const regexp = new RegExp(meta.pattern.source, meta.pattern.flags);
|
|
3707
|
+
if (!regexp.test(data)) throw new ValidationError(`expect string to match regexp ${regexp}`, options);
|
|
3708
|
+
}
|
|
3709
|
+
checkWithinRange(data.length, meta, "string length", options);
|
|
3710
|
+
return [data];
|
|
3711
|
+
});
|
|
3712
|
+
function decimalShift(data, digits) {
|
|
3713
|
+
const str = data.toString();
|
|
3714
|
+
if (str.includes("e")) return data * Math.pow(10, digits);
|
|
3715
|
+
const index = str.indexOf(".");
|
|
3716
|
+
if (index === -1) return data * Math.pow(10, digits);
|
|
3717
|
+
const frac = str.slice(index + 1);
|
|
3718
|
+
const integer = str.slice(0, index);
|
|
3719
|
+
if (frac.length <= digits) return +(integer + frac.padEnd(digits, "0"));
|
|
3720
|
+
return +(integer + frac.slice(0, digits) + "." + frac.slice(digits));
|
|
3721
|
+
}
|
|
3722
|
+
function isMultipleOf(data, min, step) {
|
|
3723
|
+
step = Math.abs(step);
|
|
3724
|
+
if (!/^\d+\.\d+$/.test(step.toString())) return (data - min) % step === 0;
|
|
3725
|
+
const index = step.toString().indexOf(".");
|
|
3726
|
+
const digits = step.toString().slice(index + 1).length;
|
|
3727
|
+
return Math.abs(decimalShift(data, digits) - decimalShift(min, digits)) % decimalShift(step, digits) === 0;
|
|
3728
|
+
}
|
|
3729
|
+
Schema.extend("number", (data, { meta }, options) => {
|
|
3730
|
+
if (typeof data !== "number") throw new ValidationError(`expected number but got ${data}`, options);
|
|
3731
|
+
checkWithinRange(data, meta, "number", options);
|
|
3732
|
+
const { step } = meta;
|
|
3733
|
+
if (step && !isMultipleOf(data, meta.min ?? 0, step)) throw new ValidationError(`expected number multiple of ${step} but got ${data}`, options);
|
|
3734
|
+
return [data];
|
|
3735
|
+
});
|
|
3736
|
+
Schema.extend("boolean", (data, _, options) => {
|
|
3737
|
+
if (typeof data === "boolean") return [data];
|
|
3738
|
+
throw new ValidationError(`expected boolean but got ${data}`, options);
|
|
3739
|
+
});
|
|
3740
|
+
Schema.extend("bitset", (data, { bits, meta }, options) => {
|
|
3741
|
+
let value = 0, keys = [];
|
|
3742
|
+
if (typeof data === "number") {
|
|
3743
|
+
value = data;
|
|
3744
|
+
for (const key in bits) if (data & bits[key]) keys.push(key);
|
|
3745
|
+
} else if (Array.isArray(data)) {
|
|
3746
|
+
keys = data;
|
|
3747
|
+
for (const key of keys) {
|
|
3748
|
+
if (typeof key !== "string") throw new ValidationError(`expected string but got ${key}`, options);
|
|
3749
|
+
if (key in bits) value |= bits[key];
|
|
3750
|
+
}
|
|
3751
|
+
} else throw new ValidationError(`expected number or array but got ${data}`, options);
|
|
3752
|
+
if (value === meta.default) return [value];
|
|
3753
|
+
return [value, keys];
|
|
3754
|
+
});
|
|
3755
|
+
Schema.extend("function", (data, _, options) => {
|
|
3756
|
+
if (typeof data === "function") return [data];
|
|
3757
|
+
throw new ValidationError(`expected function but got ${data}`, options);
|
|
3758
|
+
});
|
|
3759
|
+
Schema.extend("is", (data, { constructor }, options) => {
|
|
3760
|
+
if (typeof constructor === "function") {
|
|
3761
|
+
if (data instanceof constructor) return [data];
|
|
3762
|
+
throw new ValidationError(`expected ${constructor.name} but got ${data}`, options);
|
|
3763
|
+
} else {
|
|
3764
|
+
if (isNullable(data)) throw new ValidationError(`expected ${constructor} but got ${data}`, options);
|
|
3765
|
+
let prototype = Object.getPrototypeOf(data);
|
|
3766
|
+
while (prototype) {
|
|
3767
|
+
if (prototype.constructor?.name === constructor) return [data];
|
|
3768
|
+
prototype = Object.getPrototypeOf(prototype);
|
|
3769
|
+
}
|
|
3770
|
+
throw new ValidationError(`expected ${constructor} but got ${data}`, options);
|
|
3771
|
+
}
|
|
3772
|
+
});
|
|
3773
|
+
function property(data, key, schema, options) {
|
|
3774
|
+
try {
|
|
3775
|
+
const [value, adapted] = Schema.resolve(data[key], schema, {
|
|
3776
|
+
...options,
|
|
3777
|
+
path: [...options.path || [], key]
|
|
3778
|
+
});
|
|
3779
|
+
if (adapted !== void 0) data[key] = adapted;
|
|
3780
|
+
return value;
|
|
3781
|
+
} catch (e) {
|
|
3782
|
+
if (!options?.autofix) throw e;
|
|
3783
|
+
delete data[key];
|
|
3784
|
+
return schema.meta.volatile ? createVolatile(schema.meta.default) : schema.meta.default;
|
|
3785
|
+
}
|
|
3786
|
+
}
|
|
3787
|
+
Schema.extend("array", (data, { inner, meta }, options) => {
|
|
3788
|
+
if (!Array.isArray(data)) throw new ValidationError(`expected array but got ${data}`, options);
|
|
3789
|
+
checkWithinRange(data.length, meta, "array length", options, !isNullable(inner.meta.default));
|
|
3790
|
+
return [data.map((_, index) => property(data, index, inner, options))];
|
|
3791
|
+
});
|
|
3792
|
+
Schema.extend("dict", (data, { inner, sKey }, options, strict) => {
|
|
3793
|
+
if (!isPlainObject(data)) throw new ValidationError(`expected object but got ${data}`, options);
|
|
3794
|
+
const result = {};
|
|
3795
|
+
for (const key in data) {
|
|
3796
|
+
let rKey;
|
|
3797
|
+
try {
|
|
3798
|
+
rKey = Schema.resolve(key, sKey, options)[0];
|
|
3799
|
+
} catch (error) {
|
|
3800
|
+
if (strict) continue;
|
|
3801
|
+
throw error;
|
|
3802
|
+
}
|
|
3803
|
+
result[rKey] = property(data, key, inner, options);
|
|
3804
|
+
data[rKey] = data[key];
|
|
3805
|
+
if (key !== rKey) delete data[key];
|
|
3806
|
+
}
|
|
3807
|
+
return [result];
|
|
3808
|
+
});
|
|
3809
|
+
Schema.extend("tuple", (data, { list }, options, strict) => {
|
|
3810
|
+
if (!Array.isArray(data)) throw new ValidationError(`expected array but got ${data}`, options);
|
|
3811
|
+
const result = list.map((inner, index) => property(data, index, inner, options));
|
|
3812
|
+
if (strict) return [result];
|
|
3813
|
+
result.push(...data.slice(list.length));
|
|
3814
|
+
return [result];
|
|
3815
|
+
});
|
|
3816
|
+
function merge(result, data) {
|
|
3817
|
+
for (const key in data) {
|
|
3818
|
+
if (key in result) continue;
|
|
3819
|
+
result[key] = data[key];
|
|
3820
|
+
}
|
|
3821
|
+
}
|
|
3822
|
+
Schema.extend("object", (data, { dict }, options, strict) => {
|
|
3823
|
+
if (!isPlainObject(data)) throw new ValidationError(`expected object but got ${data}`, options);
|
|
3824
|
+
const result = {};
|
|
3825
|
+
for (const key in dict) {
|
|
3826
|
+
const value = property(data, key, dict[key], options);
|
|
3827
|
+
if (!isNullable(value) || key in data) result[key] = value;
|
|
3828
|
+
}
|
|
3829
|
+
if (!strict) merge(result, data);
|
|
3830
|
+
return [result];
|
|
3831
|
+
});
|
|
3832
|
+
Schema.extend("union", (data, { list, toString }, options, strict) => {
|
|
3833
|
+
const messages = [];
|
|
3834
|
+
for (const inner of list) try {
|
|
3835
|
+
return Schema.resolve(data, inner, options, strict);
|
|
3836
|
+
} catch (error) {
|
|
3837
|
+
messages.push(error);
|
|
3838
|
+
}
|
|
3839
|
+
throw new ValidationError(`expected ${toString()} but got ${JSON.stringify(data)}`, options);
|
|
3840
|
+
});
|
|
3841
|
+
Schema.extend("intersect", (data, { list, toString }, options, strict) => {
|
|
3842
|
+
if (!list.length) return [data];
|
|
3843
|
+
let result;
|
|
3844
|
+
for (const inner of list) {
|
|
3845
|
+
const value = Schema.resolve(data, inner, options, true)[0];
|
|
3846
|
+
if (isNullable(value)) continue;
|
|
3847
|
+
if (isNullable(result)) result = value;
|
|
3848
|
+
else if (typeof result !== typeof value) throw new ValidationError(`expected ${toString()} but got ${JSON.stringify(data)}`, options);
|
|
3849
|
+
else if (typeof value === "object") merge(result ??= {}, value);
|
|
3850
|
+
else if (result !== value) throw new ValidationError(`expected ${toString()} but got ${JSON.stringify(data)}`, options);
|
|
3851
|
+
}
|
|
3852
|
+
if (!strict && isPlainObject(data)) merge(result, data);
|
|
3853
|
+
return [result];
|
|
3854
|
+
});
|
|
3855
|
+
Schema.extend("transform", (data, { inner, callback, preserve }, options) => {
|
|
3856
|
+
const [result, adapted = data] = Schema.resolve(data, inner, options, true);
|
|
3857
|
+
if (preserve) return [callback(result)];
|
|
3858
|
+
else return [callback(result), callback(adapted)];
|
|
3859
|
+
});
|
|
3860
|
+
const formatters = {};
|
|
3861
|
+
function defineMethod(name, keys, format) {
|
|
3862
|
+
formatters[name] = format;
|
|
3863
|
+
Object.assign(Schema, { [name](...args) {
|
|
3864
|
+
const schema = new Schema({ type: name });
|
|
3865
|
+
keys.forEach((key, index) => {
|
|
3866
|
+
switch (key) {
|
|
3867
|
+
case "sKey":
|
|
3868
|
+
schema.sKey = args[index] ?? Schema.string();
|
|
3869
|
+
break;
|
|
3870
|
+
case "inner":
|
|
3871
|
+
schema.inner = Schema.from(args[index]);
|
|
3872
|
+
break;
|
|
3873
|
+
case "list":
|
|
3874
|
+
schema.list = args[index].map(Schema.from);
|
|
3875
|
+
break;
|
|
3876
|
+
case "dict":
|
|
3877
|
+
schema.dict = mapValues(args[index], Schema.from);
|
|
3878
|
+
break;
|
|
3879
|
+
case "bits":
|
|
3880
|
+
schema.bits = {};
|
|
3881
|
+
for (const key in args[index]) {
|
|
3882
|
+
if (typeof args[index][key] !== "number") continue;
|
|
3883
|
+
schema.bits[key] = args[index][key];
|
|
3884
|
+
}
|
|
3885
|
+
break;
|
|
3886
|
+
case "callback": {
|
|
3887
|
+
const callback = schema.callback = args[index];
|
|
3888
|
+
callback["toJSON"] ||= () => callback.toString();
|
|
3889
|
+
break;
|
|
3890
|
+
}
|
|
3891
|
+
case "constructor": {
|
|
3892
|
+
const constructor = schema.constructor = args[index];
|
|
3893
|
+
if (typeof constructor === "function") constructor["toJSON"] ||= () => constructor["name"];
|
|
3894
|
+
break;
|
|
3895
|
+
}
|
|
3896
|
+
default: schema[key] = args[index];
|
|
3897
|
+
}
|
|
3898
|
+
});
|
|
3899
|
+
if (name === "object" || name === "dict") schema.meta.default = {};
|
|
3900
|
+
else if (name === "array" || name === "tuple") schema.meta.default = [];
|
|
3901
|
+
else if (name === "bitset") schema.meta.default = 0;
|
|
3902
|
+
return schema;
|
|
3903
|
+
} });
|
|
3904
|
+
}
|
|
3905
|
+
defineMethod("is", ["constructor"], ({ constructor }) => {
|
|
3906
|
+
if (typeof constructor === "function") return constructor.name;
|
|
3907
|
+
else return constructor;
|
|
3908
|
+
});
|
|
3909
|
+
defineMethod("any", [], () => "any");
|
|
3910
|
+
defineMethod("never", [], () => "never");
|
|
3911
|
+
defineMethod("const", ["value"], ({ value }) => typeof value === "string" ? JSON.stringify(value) : value);
|
|
3912
|
+
defineMethod("string", [], () => "string");
|
|
3913
|
+
defineMethod("number", [], () => "number");
|
|
3914
|
+
defineMethod("boolean", [], () => "boolean");
|
|
3915
|
+
defineMethod("bitset", ["bits"], () => "bitset");
|
|
3916
|
+
defineMethod("function", [], () => "function");
|
|
3917
|
+
defineMethod("array", ["inner"], ({ inner }) => `${inner.toString(true)}[]`);
|
|
3918
|
+
defineMethod("dict", ["inner", "sKey"], ({ inner, sKey }) => `{ [key: ${sKey.toString()}]: ${inner.toString()} }`);
|
|
3919
|
+
defineMethod("tuple", ["list"], ({ list }) => `[${list.map((inner) => inner.toString()).join(", ")}]`);
|
|
3920
|
+
defineMethod("object", ["dict"], ({ dict }) => {
|
|
3921
|
+
if (Object.keys(dict).length === 0) return "{}";
|
|
3922
|
+
return `{ ${Object.entries(dict).map(([key, inner]) => {
|
|
3923
|
+
return `${key}${inner.meta.required ? "" : "?"}: ${inner.toString()}`;
|
|
3924
|
+
}).join(", ")} }`;
|
|
3925
|
+
});
|
|
3926
|
+
defineMethod("union", ["list"], ({ list }, inline) => {
|
|
3927
|
+
const result = list.map(({ toString: format }) => format()).join(" | ");
|
|
3928
|
+
return inline ? `(${result})` : result;
|
|
3929
|
+
});
|
|
3930
|
+
defineMethod("intersect", ["list"], ({ list }) => {
|
|
3931
|
+
return `${list.map((inner) => inner.toString(true)).join(" & ")}`;
|
|
3932
|
+
});
|
|
3933
|
+
defineMethod("transform", [
|
|
3934
|
+
"inner",
|
|
3935
|
+
"callback",
|
|
3936
|
+
"preserve"
|
|
3937
|
+
], ({ inner }, isInner) => inner.toString(isInner));
|
|
3938
|
+
//#endregion
|
|
3939
|
+
//#region lib/types/onboarding-config.js
|
|
3940
|
+
/** Public page-bootstrap options shared by the Host and Client halves. */
|
|
3941
|
+
/** Validate Host configuration and its public page-bootstrap payload. */
|
|
3942
|
+
const Config = Schema.object({ credentialOnboarding: Schema.boolean().default(true) });
|
|
3943
|
+
/** Page-global key carrying only the public onboarding options. */
|
|
3944
|
+
const ONBOARDING_CONFIG_GLOBAL = "__DSH_MODELS_ONBOARDING__";
|
|
3945
|
+
//#endregion
|
|
2867
3946
|
//#region lib/types/client/index.js
|
|
2868
3947
|
/** Dictionary namespace owned by this plugin. */
|
|
2869
3948
|
const NS = "settings.models";
|
|
@@ -2888,7 +3967,7 @@ window.__ModuleLoader__.load({
|
|
|
2888
3967
|
"remote.credentials",
|
|
2889
3968
|
"remote.llm",
|
|
2890
3969
|
"remote.settings",
|
|
2891
|
-
"
|
|
3970
|
+
"configForms",
|
|
2892
3971
|
"settingsSchema"
|
|
2893
3972
|
];
|
|
2894
3973
|
/**
|
|
@@ -2898,13 +3977,15 @@ window.__ModuleLoader__.load({
|
|
|
2898
3977
|
* @param ctx - client root context.
|
|
2899
3978
|
*/
|
|
2900
3979
|
function apply(ctx) {
|
|
3980
|
+
const payload = globalThis[ONBOARDING_CONFIG_GLOBAL];
|
|
3981
|
+
const credentialOnboarding = Config(payload === void 0 ? {} : payload).credentialOnboarding && !("dshDesktop" in globalThis);
|
|
2901
3982
|
ctx.effect(() => ctx.locale.register(NS, {
|
|
2902
3983
|
zh,
|
|
2903
3984
|
en
|
|
2904
3985
|
}), "ui-settings-models: copy dictionaries");
|
|
2905
3986
|
const schema = createSettingsSchemaOperations(ctx.settingsSchema);
|
|
2906
3987
|
const operations = createModelsOperations(ctx);
|
|
2907
|
-
const controller = new ModelsSettingsStore(ctx, schema, ctx.
|
|
3988
|
+
const controller = new ModelsSettingsStore(ctx, schema, ctx.configForms.describe());
|
|
2908
3989
|
const t = ctx.locale.bind(NS);
|
|
2909
3990
|
const injected = () => ({
|
|
2910
3991
|
controller,
|
|
@@ -2914,16 +3995,14 @@ window.__ModuleLoader__.load({
|
|
|
2914
3995
|
t
|
|
2915
3996
|
});
|
|
2916
3997
|
const deepSeekOnboardingInjected = () => ({
|
|
3998
|
+
automatic: credentialOnboarding,
|
|
2917
3999
|
controller,
|
|
2918
4000
|
hooks: { models: controller.store },
|
|
2919
4001
|
operations,
|
|
2920
4002
|
schema,
|
|
2921
4003
|
t
|
|
2922
4004
|
});
|
|
2923
|
-
const welcomeController = new WelcomeNoticeStore(ctx.
|
|
2924
|
-
namespace: WELCOME_NOTICE_SETTINGS_NAMESPACE,
|
|
2925
|
-
decode: decodeWelcomeSection
|
|
2926
|
-
}));
|
|
4005
|
+
const welcomeController = new WelcomeNoticeStore(ctx.configForms.get(WELCOME_NOTICE_SETTINGS_NAMESPACE));
|
|
2927
4006
|
const welcomeInjected = () => ({
|
|
2928
4007
|
controller: welcomeController,
|
|
2929
4008
|
hooks: { welcome: welcomeController.store },
|
|
@@ -2972,6 +4051,10 @@ window.__ModuleLoader__.load({
|
|
|
2972
4051
|
ctx.slots.inject("settings.onboarding", () => ctx.slots.register({
|
|
2973
4052
|
name: "settings.onboarding",
|
|
2974
4053
|
id: "deepseek-official",
|
|
4054
|
+
children: { "settings.models.sign-in": {
|
|
4055
|
+
kind: "single",
|
|
4056
|
+
scope: "root"
|
|
4057
|
+
} },
|
|
2975
4058
|
order: 0,
|
|
2976
4059
|
inject: deepSeekOnboardingInjected
|
|
2977
4060
|
}, DeepSeekOnboardingDialog));
|