@mofeng2223/dsh-claude-provider 0.4.6 → 0.4.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -11
- package/README.zh-CN.md +23 -11
- package/cordis.patch.yml +1 -1
- package/lib/client.js +1277 -195
- package/package.json +7 -5
- package/scripts/migrate-legacy-types.mjs +42 -0
- package/src/index.js +3 -8
package/lib/client.js
CHANGED
|
@@ -56,7 +56,7 @@ window.__ModuleLoader__.load({
|
|
|
56
56
|
}
|
|
57
57
|
//#endregion
|
|
58
58
|
//#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-settings-models/src/client/ModelsSection.module.css.mjs
|
|
59
|
-
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(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
|
+
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_candidateName{text-overflow:ellipsis;white-space:nowrap;flex:auto;min-width:0;font-size:13px;overflow:hidden}.zGbnIq_candidateEmpty{color:var(--dsw-alias-label-secondary);text-align:center;margin:24px 0;font-size:13px;line-height:20px}";
|
|
60
60
|
const tagId$3 = "@mofeng2223/dsh-claude-provider/ModelsSection.module.css";
|
|
61
61
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$3) + "]") === null) {
|
|
62
62
|
const tag = document.createElement("style");
|
|
@@ -71,12 +71,14 @@ window.__ModuleLoader__.load({
|
|
|
71
71
|
"addButton": "zGbnIq_addButton",
|
|
72
72
|
"addCard": "zGbnIq_addCard",
|
|
73
73
|
"addModelButton": "zGbnIq_addModelButton",
|
|
74
|
+
"addModes": "zGbnIq_addModes",
|
|
75
|
+
"addPanel": "zGbnIq_addPanel",
|
|
74
76
|
"advancedHint": "zGbnIq_advancedHint",
|
|
75
77
|
"candidate": "zGbnIq_candidate",
|
|
76
78
|
"candidateEmpty": "zGbnIq_candidateEmpty",
|
|
77
|
-
"candidateId": "zGbnIq_candidateId",
|
|
78
79
|
"candidateLabel": "zGbnIq_candidateLabel",
|
|
79
80
|
"candidateList": "zGbnIq_candidateList",
|
|
81
|
+
"candidateName": "zGbnIq_candidateName",
|
|
80
82
|
"candidateSearch": "zGbnIq_candidateSearch",
|
|
81
83
|
"candidateToolbar": "zGbnIq_candidateToolbar",
|
|
82
84
|
"credentialDot": "zGbnIq_credentialDot",
|
|
@@ -232,7 +234,7 @@ window.__ModuleLoader__.load({
|
|
|
232
234
|
"aria-expanded": props.expanded,
|
|
233
235
|
title: t("modelAdvanced"),
|
|
234
236
|
onClick: props.onToggle,
|
|
235
|
-
children: props.expanded ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
237
|
+
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, {})
|
|
236
238
|
}),
|
|
237
239
|
(0, react_jsx_runtime.jsx)("button", {
|
|
238
240
|
type: "button",
|
|
@@ -241,7 +243,7 @@ window.__ModuleLoader__.load({
|
|
|
241
243
|
title: t("removeModel"),
|
|
242
244
|
disabled,
|
|
243
245
|
onClick: props.onRemove,
|
|
244
|
-
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
246
|
+
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutlineRegular, { size: 14 })
|
|
245
247
|
})
|
|
246
248
|
]
|
|
247
249
|
}), props.expanded ? (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -275,7 +277,7 @@ window.__ModuleLoader__.load({
|
|
|
275
277
|
}), props.thinkingPresets ? (0, react_jsx_runtime.jsxs)("label", {
|
|
276
278
|
className: ModelsSection_module_css_default["modelField"],
|
|
277
279
|
children: [t("thinkingPreset"), (0, react_jsx_runtime.jsxs)("select", {
|
|
278
|
-
className: ModelsSection_module_css_default["input"],
|
|
280
|
+
className: ModelsSection_module_css_default["input"] + " " + ModelsSection_module_css_default["selectInput"],
|
|
279
281
|
value: thinkingPresetOf(model),
|
|
280
282
|
"aria-label": t("thinkingPreset") + " " + position,
|
|
281
283
|
disabled,
|
|
@@ -522,7 +524,7 @@ window.__ModuleLoader__.load({
|
|
|
522
524
|
onClick: () => {
|
|
523
525
|
props.onChange([...props.models.map((model) => ({ ...model })), { id: "" }]);
|
|
524
526
|
},
|
|
525
|
-
children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
527
|
+
children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutlineRegular, { size: 14 }), props.t("addModel")]
|
|
526
528
|
})
|
|
527
529
|
]
|
|
528
530
|
});
|
|
@@ -595,9 +597,12 @@ window.__ModuleLoader__.load({
|
|
|
595
597
|
* @returns the model-list editor.
|
|
596
598
|
*/
|
|
597
599
|
function ModelListEditor(props) {
|
|
598
|
-
const { models, onChange, probe, operations, t, disabled } = props;
|
|
600
|
+
const { models, onChange, probe, operations, t, disabled, onBusyChange } = props;
|
|
599
601
|
const { catalogProvider } = props;
|
|
600
602
|
const [busy, setBusy] = (0, react.useState)(false);
|
|
603
|
+
(0, react.useEffect)(() => {
|
|
604
|
+
onBusyChange(busy);
|
|
605
|
+
}, [busy, onBusyChange]);
|
|
601
606
|
const [failure, setFailure] = (0, react.useState)(void 0);
|
|
602
607
|
const [inheritedCatalog, setInheritedCatalog] = (0, react.useState)(void 0);
|
|
603
608
|
(0, react.useEffect)(() => {
|
|
@@ -822,7 +827,7 @@ window.__ModuleLoader__.load({
|
|
|
822
827
|
onClick: () => {
|
|
823
828
|
onChange([...models, props.thinkingPresets ? withDefaultClaudeReasoning({ id: "" }) : { id: "" }]);
|
|
824
829
|
},
|
|
825
|
-
children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
830
|
+
children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutlineRegular, { size: 14 }), t("addModel")]
|
|
826
831
|
}),
|
|
827
832
|
failure !== void 0 ? (0, react_jsx_runtime.jsx)("p", {
|
|
828
833
|
className: ModelsSection_module_css_default["error"],
|
|
@@ -879,8 +884,9 @@ window.__ModuleLoader__.load({
|
|
|
879
884
|
toggle(candidate.id);
|
|
880
885
|
}
|
|
881
886
|
}), (0, react_jsx_runtime.jsx)("span", {
|
|
882
|
-
className: ModelsSection_module_css_default["
|
|
883
|
-
|
|
887
|
+
className: ModelsSection_module_css_default["candidateName"],
|
|
888
|
+
title: candidate.name ?? candidate.id,
|
|
889
|
+
children: candidate.name ?? candidate.id
|
|
884
890
|
})]
|
|
885
891
|
})
|
|
886
892
|
}, candidate.id))
|
|
@@ -1132,18 +1138,46 @@ window.__ModuleLoader__.load({
|
|
|
1132
1138
|
return { kind: "credential-missing" };
|
|
1133
1139
|
}
|
|
1134
1140
|
//#endregion
|
|
1141
|
+
//#region lib/types/client/protocol-label.js
|
|
1142
|
+
/**
|
|
1143
|
+
* Product names for the wire protocols a pi-ai route may speak. The pickers
|
|
1144
|
+
* show these instead of the schema identifiers (`openai-completions`), which
|
|
1145
|
+
* are what `settings.yaml` carries and what the option values stay.
|
|
1146
|
+
*/
|
|
1147
|
+
/** The protocols this page names, keyed by their schema identifier. */
|
|
1148
|
+
const PROTOCOL_LABEL_KEYS = {
|
|
1149
|
+
"openai-completions": "protocolOpenAiCompletions",
|
|
1150
|
+
"openai-responses": "protocolOpenAiResponses",
|
|
1151
|
+
"anthropic-messages": "protocolAnthropicMessages"
|
|
1152
|
+
};
|
|
1153
|
+
/**
|
|
1154
|
+
* The picker text for one protocol identifier.
|
|
1155
|
+
* @param t - section copy.
|
|
1156
|
+
* @param protocol - the schema identifier of the protocol.
|
|
1157
|
+
* @returns the product name this page knows the protocol by; a protocol the
|
|
1158
|
+
* adapter adds before this page names it shows its identifier, the spelling
|
|
1159
|
+
* `settings.yaml` needs anyway.
|
|
1160
|
+
*/
|
|
1161
|
+
function protocolLabel(t, protocol) {
|
|
1162
|
+
const key = PROTOCOL_LABEL_KEYS[protocol];
|
|
1163
|
+
return key === void 0 ? protocol : t(key);
|
|
1164
|
+
}
|
|
1165
|
+
//#endregion
|
|
1135
1166
|
//#region lib/types/client/CustomProviderCard.js
|
|
1136
1167
|
/**
|
|
1137
1168
|
* The card that declares a provider pi-ai does not ship — an OpenAI-compatible
|
|
1138
1169
|
* gateway, a self-hosted server, or a provider newer than the installed
|
|
1139
1170
|
* catalog.
|
|
1140
1171
|
*
|
|
1141
|
-
* This is a create, not an edit, which is why it is its own
|
|
1172
|
+
* This is a create, not an edit, which is why it is its own form rather than
|
|
1142
1173
|
* the provider editor with extra fields: the route id is being *chosen* here,
|
|
1143
|
-
* and the settings address does not exist until it is.
|
|
1144
|
-
*
|
|
1145
|
-
*
|
|
1146
|
-
*
|
|
1174
|
+
* and the settings address does not exist until it is. It renders as the
|
|
1175
|
+
* custom-API panel of the section's add card; the card's mode switch names it
|
|
1176
|
+
* when both modes are offered, and with the custom mode alone the card shows
|
|
1177
|
+
* this form directly. One `settings.mutate` sets the whole profile at
|
|
1178
|
+
* `providers.<route>`; the key travels separately through `credentials/set`
|
|
1179
|
+
* under the reference the profile records, exactly as an existing provider's
|
|
1180
|
+
* key does.
|
|
1147
1181
|
*
|
|
1148
1182
|
* The three fields a hand-declared route cannot default — endpoint, protocol,
|
|
1149
1183
|
* and at least one model — are required here rather than at load, so the
|
|
@@ -1180,7 +1214,7 @@ window.__ModuleLoader__.load({
|
|
|
1180
1214
|
* @returns the creation card.
|
|
1181
1215
|
*/
|
|
1182
1216
|
function CustomProviderCard(props) {
|
|
1183
|
-
const { taken, protocols, operations, t } = props;
|
|
1217
|
+
const { taken, protocols, operations, t, onBusyChange } = props;
|
|
1184
1218
|
const [openedAt] = (0, react.useState)(() => props.revision);
|
|
1185
1219
|
const [route, setRoute] = (0, react.useState)("");
|
|
1186
1220
|
const [displayName, setDisplayName] = (0, react.useState)("");
|
|
@@ -1191,6 +1225,14 @@ window.__ModuleLoader__.load({
|
|
|
1191
1225
|
const [keyDraft, setKeyDraft] = (0, react.useState)("");
|
|
1192
1226
|
const [models, setModels] = (0, react.useState)([]);
|
|
1193
1227
|
const [busy, setBusy] = (0, react.useState)(false);
|
|
1228
|
+
const [listBusy, setListBusy] = (0, react.useState)(false);
|
|
1229
|
+
(0, react.useEffect)(() => {
|
|
1230
|
+
onBusyChange?.(busy || listBusy);
|
|
1231
|
+
}, [
|
|
1232
|
+
busy,
|
|
1233
|
+
listBusy,
|
|
1234
|
+
onBusyChange
|
|
1235
|
+
]);
|
|
1194
1236
|
const [failure, setFailure] = (0, react.useState)(void 0);
|
|
1195
1237
|
/**
|
|
1196
1238
|
* The profile write landed. Only the key write can still be outstanding, so
|
|
@@ -1261,13 +1303,6 @@ window.__ModuleLoader__.load({
|
|
|
1261
1303
|
return (0, react_jsx_runtime.jsxs)("div", {
|
|
1262
1304
|
className: ModelsSection_module_css_default["editor"],
|
|
1263
1305
|
children: [
|
|
1264
|
-
(0, react_jsx_runtime.jsx)("div", {
|
|
1265
|
-
className: ModelsSection_module_css_default["editorHeader"],
|
|
1266
|
-
children: (0, react_jsx_runtime.jsx)("span", {
|
|
1267
|
-
className: ModelsSection_module_css_default["editorTitle"],
|
|
1268
|
-
children: t(isAdaptiveClaude ? "claudeCustomTitle" : "customTitle")
|
|
1269
|
-
})
|
|
1270
|
-
}),
|
|
1271
1306
|
isAdaptiveClaude ? (0, react_jsx_runtime.jsxs)("p", {
|
|
1272
1307
|
className: ModelsSection_module_css_default["savedNotice"],
|
|
1273
1308
|
role: "status",
|
|
@@ -1323,7 +1358,7 @@ window.__ModuleLoader__.load({
|
|
|
1323
1358
|
className: ModelsSection_module_css_default["input"],
|
|
1324
1359
|
type: "text",
|
|
1325
1360
|
value: baseURL,
|
|
1326
|
-
placeholder: t("customBaseUrlPlaceholder"),
|
|
1361
|
+
placeholder: t(protocol === "anthropic-messages" ? "customAnthropicBaseUrlPlaceholder" : "customBaseUrlPlaceholder"),
|
|
1327
1362
|
"aria-label": t("baseUrl"),
|
|
1328
1363
|
"aria-invalid": baseUrlInvalid,
|
|
1329
1364
|
disabled: profileDisabled,
|
|
@@ -1351,7 +1386,7 @@ window.__ModuleLoader__.load({
|
|
|
1351
1386
|
},
|
|
1352
1387
|
children: protocols.map((choice) => (0, react_jsx_runtime.jsx)("option", {
|
|
1353
1388
|
value: choice,
|
|
1354
|
-
children: choice
|
|
1389
|
+
children: protocolLabel(t, choice)
|
|
1355
1390
|
}, choice))
|
|
1356
1391
|
})]
|
|
1357
1392
|
}),
|
|
@@ -1393,7 +1428,8 @@ window.__ModuleLoader__.load({
|
|
|
1393
1428
|
thinkingPresets: isAdaptiveClaude,
|
|
1394
1429
|
operations,
|
|
1395
1430
|
t,
|
|
1396
|
-
disabled: profileDisabled
|
|
1431
|
+
disabled: profileDisabled,
|
|
1432
|
+
onBusyChange: setListBusy
|
|
1397
1433
|
}),
|
|
1398
1434
|
failure !== void 0 ? (0, react_jsx_runtime.jsx)("p", {
|
|
1399
1435
|
className: ModelsSection_module_css_default["error"],
|
|
@@ -1437,9 +1473,9 @@ window.__ModuleLoader__.load({
|
|
|
1437
1473
|
* Reasoning effort is deliberately absent: it is a per-MODEL capability, and
|
|
1438
1474
|
* the models under one provider disagree about it, so a provider-scoped
|
|
1439
1475
|
* control can only be set to a value some of them reject. The composer's
|
|
1440
|
-
* model picker offers each model its own levels; `
|
|
1476
|
+
* model picker offers each model its own levels; `cordis.patch.yml` keeps the
|
|
1441
1477
|
* profile field for a deployment that knows its route. Everything else stays
|
|
1442
|
-
* owned by `
|
|
1478
|
+
* owned by `cordis.patch.yml`. Profile edits land as minimal `settings.mutate`
|
|
1443
1479
|
* path ops against the stored section — the card names only the fields it can
|
|
1444
1480
|
* see instead of rebuilding the whole subtree from a partial descriptor.
|
|
1445
1481
|
*/
|
|
@@ -1499,6 +1535,15 @@ window.__ModuleLoader__.load({
|
|
|
1499
1535
|
const [keyDraft, setKeyDraft] = (0, react.useState)("");
|
|
1500
1536
|
const [keyState, setKeyState] = (0, react.useState)(void 0);
|
|
1501
1537
|
const [busy, setBusy] = (0, react.useState)(false);
|
|
1538
|
+
const [listBusy, setListBusy] = (0, react.useState)(false);
|
|
1539
|
+
const { onBusyChange } = props;
|
|
1540
|
+
(0, react.useEffect)(() => {
|
|
1541
|
+
onBusyChange?.(busy || listBusy);
|
|
1542
|
+
}, [
|
|
1543
|
+
busy,
|
|
1544
|
+
listBusy,
|
|
1545
|
+
onBusyChange
|
|
1546
|
+
]);
|
|
1502
1547
|
const [failure, setFailure] = (0, react.useState)(void 0);
|
|
1503
1548
|
const [committedOriginal, setCommittedOriginal] = (0, react.useState)(() => schema.getPath(namespace.user, settingsPath));
|
|
1504
1549
|
const [expectedRevision, setExpectedRevision] = (0, react.useState)(() => namespace.revision);
|
|
@@ -1711,7 +1756,7 @@ window.__ModuleLoader__.load({
|
|
|
1711
1756
|
className: ModelsSection_module_css_default["input"],
|
|
1712
1757
|
type: "text",
|
|
1713
1758
|
value: stringAt(draft, "baseURL") ?? "",
|
|
1714
|
-
placeholder: family === "deepseek" ? t(
|
|
1759
|
+
placeholder: family === "deepseek" ? t("deepSeekBaseUrl") : stringAt(fallback, "baseURL") ?? t("baseUrlDefault"),
|
|
1715
1760
|
"aria-describedby": family === "deepseek" ? `${props.provider}-endpoint-hint` : void 0,
|
|
1716
1761
|
"aria-label": t("baseUrl"),
|
|
1717
1762
|
disabled,
|
|
@@ -1744,7 +1789,7 @@ window.__ModuleLoader__.load({
|
|
|
1744
1789
|
children: t("customApiUnset")
|
|
1745
1790
|
}) : null, protocols.map((choice) => (0, react_jsx_runtime.jsx)("option", {
|
|
1746
1791
|
value: choice,
|
|
1747
|
-
children: choice
|
|
1792
|
+
children: protocolLabel(t, choice)
|
|
1748
1793
|
}, choice))]
|
|
1749
1794
|
})]
|
|
1750
1795
|
}) : null,
|
|
@@ -1759,7 +1804,8 @@ window.__ModuleLoader__.load({
|
|
|
1759
1804
|
probe,
|
|
1760
1805
|
probeBlocked: keyFailure,
|
|
1761
1806
|
thinkingPresets: props.thinkingPresets === true,
|
|
1762
|
-
operations
|
|
1807
|
+
operations,
|
|
1808
|
+
onBusyChange: setListBusy
|
|
1763
1809
|
})
|
|
1764
1810
|
]
|
|
1765
1811
|
})]
|
|
@@ -1816,11 +1862,19 @@ window.__ModuleLoader__.load({
|
|
|
1816
1862
|
* solid configured or missing dots. A whole-section provider without a
|
|
1817
1863
|
* configured key renders as its open setup card instead of a row, but only in
|
|
1818
1864
|
* the first-run posture — no provider on the page can serve requests yet — and
|
|
1819
|
-
* only until the user closes that card
|
|
1820
|
-
*
|
|
1821
|
-
*
|
|
1822
|
-
*
|
|
1823
|
-
*
|
|
1865
|
+
* only until the user closes that card. The add flow is one card behind one
|
|
1866
|
+
* button: a mode switch chooses between adopting a dormant directory provider
|
|
1867
|
+
* (the catalog select over the provider editor) and declaring a custom model
|
|
1868
|
+
* API (the create form). A panel mounts the first time its mode is shown and
|
|
1869
|
+
* stays mounted, hidden, while the card is open and its mode stays offered,
|
|
1870
|
+
* so switching modes discards neither draft and an unvisited mode costs
|
|
1871
|
+
* nothing; the switch holds still while either panel has a write or an
|
|
1872
|
+
* endpoint interrogation in flight, since a switch underneath one would
|
|
1873
|
+
* orphan the answer. Each card kind owns its own open state, so closing one
|
|
1874
|
+
* never discards a draft in another. Every
|
|
1875
|
+
* mutation writes through the wire, while a provider removal first requires
|
|
1876
|
+
* confirmation; the page re-renders from pushed invalidations or the
|
|
1877
|
+
* post-apply reload.
|
|
1824
1878
|
*/
|
|
1825
1879
|
/** Render an editor for either the setup posture or an expanded provider row. */
|
|
1826
1880
|
function renderProviderEditor({ target, ...props }) {
|
|
@@ -2050,30 +2104,50 @@ window.__ModuleLoader__.load({
|
|
|
2050
2104
|
const { controller, operations, schema, t } = injected;
|
|
2051
2105
|
const state = injected.useSnapshot((snapshot) => snapshot);
|
|
2052
2106
|
const [editing, setEditing] = (0, react.useState)(void 0);
|
|
2053
|
-
const [
|
|
2107
|
+
const [addOpen, setAddOpen] = (0, react.useState)(false);
|
|
2108
|
+
const [addMode, setAddMode] = (0, react.useState)("catalog");
|
|
2109
|
+
/** The modes shown since the add card opened; each keeps its panel mounted. */
|
|
2110
|
+
const [visited, setVisited] = (0, react.useState)(() => /* @__PURE__ */ new Set());
|
|
2111
|
+
/** Whether each add panel has a write or an interrogation in flight. */
|
|
2112
|
+
const [catalogBusy, setCatalogBusy] = (0, react.useState)(false);
|
|
2113
|
+
const [customBusy, setCustomBusy] = (0, react.useState)(false);
|
|
2114
|
+
const [claudeBusy, setClaudeBusy] = (0, react.useState)(false);
|
|
2115
|
+
/** Base of the add card's tab and panel ids. */
|
|
2116
|
+
const addId = (0, react.useId)();
|
|
2054
2117
|
const [deleteTarget, setDeleteTarget] = (0, react.useState)(void 0);
|
|
2055
2118
|
const [deleting, setDeleting] = (0, react.useState)(false);
|
|
2056
2119
|
const [deleteFailure, setDeleteFailure] = (0, react.useState)(void 0);
|
|
2057
2120
|
const [savedTarget, setSavedTarget] = (0, react.useState)(void 0);
|
|
2058
|
-
const [declaringType, setDeclaringType] = (0, react.useState)(void 0);
|
|
2059
2121
|
const [dismissedSetup, setDismissedSetup] = (0, react.useState)(() => /* @__PURE__ */ new Set());
|
|
2060
2122
|
const announceSaved = (target) => {
|
|
2061
2123
|
controller.load().then(() => {
|
|
2062
2124
|
setSavedTarget(target);
|
|
2063
2125
|
});
|
|
2064
2126
|
};
|
|
2065
|
-
|
|
2127
|
+
/**
|
|
2128
|
+
* Close the add card whole. The catalog target is forgotten with it, since
|
|
2129
|
+
* `editing` doubles as the row editor's target once the card is closed and a
|
|
2130
|
+
* refresh could otherwise open the row of a provider the draft never saved.
|
|
2131
|
+
* The busy flags reset here because a panel that closes itself on success
|
|
2132
|
+
* unmounts before it can report idle.
|
|
2133
|
+
*/
|
|
2134
|
+
const closeAdd = () => {
|
|
2066
2135
|
setEditing(void 0);
|
|
2067
|
-
|
|
2068
|
-
|
|
2136
|
+
setAddOpen(false);
|
|
2137
|
+
setCatalogBusy(false);
|
|
2138
|
+
setCustomBusy(false);
|
|
2139
|
+
setClaudeBusy(false);
|
|
2140
|
+
};
|
|
2141
|
+
const closeEditor = (changed, target) => {
|
|
2142
|
+
closeAdd();
|
|
2069
2143
|
if (changed) announceSaved(target);
|
|
2070
2144
|
};
|
|
2071
2145
|
/**
|
|
2072
|
-
* Close a setup card, which owns none of the state above: the row-editor
|
|
2073
|
-
*
|
|
2074
|
-
*
|
|
2075
|
-
*
|
|
2076
|
-
*
|
|
2146
|
+
* Close a setup card, which owns none of the state above: the row-editor
|
|
2147
|
+
* and add cards each own one of those, so clearing them here would discard
|
|
2148
|
+
* a draft the user opened beside this card. Dismissal is this card's own —
|
|
2149
|
+
* the provider falls back to an ordinary row for the rest of the session,
|
|
2150
|
+
* and reopens through Edit.
|
|
2077
2151
|
*/
|
|
2078
2152
|
const closeSetup = (changed, target) => {
|
|
2079
2153
|
setDismissedSetup((previous) => new Set([...previous, target.provider]));
|
|
@@ -2126,11 +2200,38 @@ window.__ModuleLoader__.load({
|
|
|
2126
2200
|
const anyUsable = state.rows.some(providerUsable);
|
|
2127
2201
|
const configured = state.rows.filter((row) => row.configured);
|
|
2128
2202
|
const configurable = state.rows.filter((row) => state.namespaces.has(row.entry.settingsNs));
|
|
2129
|
-
const addable =
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2203
|
+
const addable = state.rows.flatMap((row) => {
|
|
2204
|
+
const namespace = state.namespaces.get(row.entry.settingsNs);
|
|
2205
|
+
return namespace === void 0 || row.configured ? [] : [{
|
|
2206
|
+
row,
|
|
2207
|
+
namespace
|
|
2208
|
+
}];
|
|
2209
|
+
});
|
|
2210
|
+
const piAi = state.namespaces.get("llm-pi-ai");
|
|
2211
|
+
const protocols = protocolChoices(piAi, schema);
|
|
2212
|
+
const catalogOffered = configurable.length > 0;
|
|
2213
|
+
const catalogEnabled = addable.length > 0;
|
|
2214
|
+
const customOffered = piAi !== void 0;
|
|
2215
|
+
const customEnabled = protocols.length > 0;
|
|
2216
|
+
const claudeEnabled = customEnabled && state.namespaces.has(CLAUDE_PROVIDER_SETTINGS_NS);
|
|
2217
|
+
const bothOffered = customOffered;
|
|
2218
|
+
const mode = bothOffered ? addMode : customOffered ? "custom" : "catalog";
|
|
2219
|
+
const mounted = (candidate) => mode === candidate || visited.has(candidate);
|
|
2220
|
+
const switchLocked = catalogBusy || customBusy || claudeBusy;
|
|
2221
|
+
const draft = (() => {
|
|
2222
|
+
if (!addOpen || !catalogOffered) return void 0;
|
|
2223
|
+
const kept = editing === void 0 ? void 0 : state.namespaces.get(editing.settingsNs);
|
|
2224
|
+
if (editing !== void 0 && kept !== void 0) return {
|
|
2225
|
+
target: editing,
|
|
2226
|
+
namespace: kept
|
|
2227
|
+
};
|
|
2228
|
+
const first = addable[0];
|
|
2229
|
+
return first === void 0 ? void 0 : {
|
|
2230
|
+
target: targetOf(first.row),
|
|
2231
|
+
namespace: first.namespace
|
|
2232
|
+
};
|
|
2233
|
+
})();
|
|
2234
|
+
const addRow = draft === void 0 ? void 0 : state.rows.find((row) => row.entry.provider === draft.target.provider);
|
|
2134
2235
|
return (0, react_jsx_runtime.jsxs)("div", {
|
|
2135
2236
|
className: ModelsSection_module_css_default["section"],
|
|
2136
2237
|
children: [
|
|
@@ -2187,7 +2288,7 @@ window.__ModuleLoader__.load({
|
|
|
2187
2288
|
}, { entryKey: row.entry.settingsNs })
|
|
2188
2289
|
]
|
|
2189
2290
|
}, row.entry.provider);
|
|
2190
|
-
const open = !
|
|
2291
|
+
const open = !addOpen && editing?.provider === row.entry.provider;
|
|
2191
2292
|
const adaptiveClaude = isClaudeProvider(row, state);
|
|
2192
2293
|
const credentialConfigured = row.credential?.configured === true;
|
|
2193
2294
|
const credentialMissing = !credentialConfigured && row.apiKeyEnv !== void 0 && row.credential?.configured === false;
|
|
@@ -2231,8 +2332,7 @@ window.__ModuleLoader__.load({
|
|
|
2231
2332
|
"aria-label": providerCopy(t("editProvider"), target),
|
|
2232
2333
|
onClick: () => {
|
|
2233
2334
|
setSavedTarget(void 0);
|
|
2234
|
-
|
|
2235
|
-
setAdding(false);
|
|
2335
|
+
setAddOpen(false);
|
|
2236
2336
|
setEditing(open ? void 0 : target);
|
|
2237
2337
|
},
|
|
2238
2338
|
children: t("edit")
|
|
@@ -2274,106 +2374,160 @@ window.__ModuleLoader__.load({
|
|
|
2274
2374
|
}),
|
|
2275
2375
|
(0, react_jsx_runtime.jsx)("div", {
|
|
2276
2376
|
className: ModelsSection_module_css_default["addBlock"],
|
|
2277
|
-
children:
|
|
2377
|
+
children: addOpen ? (0, react_jsx_runtime.jsxs)("div", {
|
|
2278
2378
|
className: ModelsSection_module_css_default["addCard"],
|
|
2279
2379
|
children: [
|
|
2280
2380
|
(0, react_jsx_runtime.jsxs)("div", {
|
|
2281
|
-
className: ModelsSection_module_css_default["
|
|
2282
|
-
children: [(0, react_jsx_runtime.jsx)(
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2381
|
+
className: ModelsSection_module_css_default["addModes"],
|
|
2382
|
+
children: [bothOffered ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.SegmentedControl, {
|
|
2383
|
+
id: addId,
|
|
2384
|
+
label: t("addMode"),
|
|
2385
|
+
value: mode,
|
|
2386
|
+
disabled: switchLocked,
|
|
2387
|
+
options: [{
|
|
2388
|
+
value: "catalog",
|
|
2389
|
+
label: t("addCatalog"),
|
|
2390
|
+
disabled: !catalogEnabled,
|
|
2391
|
+
...catalogEnabled ? {} : { title: t("addCatalogExhausted") }
|
|
2392
|
+
}, {
|
|
2393
|
+
value: "custom",
|
|
2394
|
+
label: t("addCustom"),
|
|
2395
|
+
disabled: !customEnabled,
|
|
2396
|
+
...customEnabled ? {} : { title: t("addCustomUnavailable") }
|
|
2397
|
+
}, { value: "claude", label: t("claudeCustomTitle"), disabled: !claudeEnabled }],
|
|
2398
|
+
onChange: (next) => {
|
|
2399
|
+
setAddMode(next);
|
|
2400
|
+
setVisited((previous) => new Set([...previous, next]));
|
|
2401
|
+
}
|
|
2402
|
+
}) : (0, react_jsx_runtime.jsx)("div", {
|
|
2403
|
+
className: ModelsSection_module_css_default["editorHeader"],
|
|
2404
|
+
children: (0, react_jsx_runtime.jsx)("span", {
|
|
2405
|
+
className: ModelsSection_module_css_default["editorTitle"],
|
|
2406
|
+
children: t(mode === "catalog" ? "addCatalog" : "addCustom")
|
|
2407
|
+
})
|
|
2408
|
+
}), (0, react_jsx_runtime.jsx)("p", {
|
|
2409
|
+
hidden: mode === "claude",
|
|
2410
|
+
className: ModelsSection_module_css_default["advancedHint"],
|
|
2411
|
+
children: t(mode === "catalog" ? "addCatalogHint" : "addCustomHint")
|
|
2299
2412
|
})]
|
|
2300
2413
|
}),
|
|
2301
|
-
(0, react_jsx_runtime.
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2414
|
+
mounted("catalog") && draft !== void 0 ? (0, react_jsx_runtime.jsxs)("div", {
|
|
2415
|
+
id: `${addId}-catalog-panel`,
|
|
2416
|
+
...bothOffered ? {
|
|
2417
|
+
role: "tabpanel",
|
|
2418
|
+
"aria-labelledby": `${addId}-catalog`
|
|
2419
|
+
} : {},
|
|
2420
|
+
hidden: mode !== "catalog",
|
|
2421
|
+
className: ModelsSection_module_css_default["addPanel"],
|
|
2422
|
+
children: [
|
|
2423
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
2424
|
+
className: ModelsSection_module_css_default["field"],
|
|
2425
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
2426
|
+
className: ModelsSection_module_css_default["fieldLabel"],
|
|
2427
|
+
children: t("provider")
|
|
2428
|
+
}), (0, react_jsx_runtime.jsx)("select", {
|
|
2429
|
+
className: `${ModelsSection_module_css_default["input"]} ${ModelsSection_module_css_default["selectInput"]}`,
|
|
2430
|
+
value: draft.target.provider,
|
|
2431
|
+
"aria-label": t("provider"),
|
|
2432
|
+
disabled: catalogBusy,
|
|
2433
|
+
onChange: (event) => {
|
|
2434
|
+
const picked = addable.find((candidate) => candidate.row.entry.provider === event.target.value);
|
|
2435
|
+
/* v8 ignore next -- the select only lists addable rows */
|
|
2436
|
+
if (picked === void 0) return;
|
|
2437
|
+
setEditing(targetOf(picked.row));
|
|
2438
|
+
},
|
|
2439
|
+
children: addable.map(({ row }) => (0, react_jsx_runtime.jsx)("option", {
|
|
2440
|
+
value: row.entry.provider,
|
|
2441
|
+
children: row.entry.displayName
|
|
2442
|
+
}, row.entry.provider))
|
|
2443
|
+
})]
|
|
2444
|
+
}),
|
|
2445
|
+
(0, react_jsx_runtime.jsx)(ProviderEditor, {
|
|
2446
|
+
provider: draft.target.provider,
|
|
2447
|
+
displayName: draft.target.displayName,
|
|
2448
|
+
hideTitle: true,
|
|
2449
|
+
namespace: draft.namespace,
|
|
2450
|
+
schema,
|
|
2451
|
+
settingsPath: draft.target.settingsPath,
|
|
2452
|
+
operations,
|
|
2453
|
+
t,
|
|
2454
|
+
readOnly: !state.writable,
|
|
2455
|
+
onClose: (changed) => {
|
|
2456
|
+
closeEditor(changed, draft.target);
|
|
2457
|
+
},
|
|
2458
|
+
onBusyChange: setCatalogBusy
|
|
2459
|
+
}, draft.target.provider),
|
|
2460
|
+
addRow === void 0 ? null : renderSlot("settings.models.provider-card", {
|
|
2461
|
+
provider: addRow.entry,
|
|
2462
|
+
configured: addRow.configured,
|
|
2463
|
+
keyConfigured: keyConfiguredOf(addRow)
|
|
2464
|
+
}, { entryKey: addRow.entry.settingsNs })
|
|
2465
|
+
]
|
|
2466
|
+
}) : null,
|
|
2467
|
+
mounted("custom") && piAi !== void 0 ? (0, react_jsx_runtime.jsx)("div", {
|
|
2468
|
+
id: `${addId}-custom-panel`,
|
|
2469
|
+
...bothOffered ? {
|
|
2470
|
+
role: "tabpanel",
|
|
2471
|
+
"aria-labelledby": `${addId}-custom`
|
|
2472
|
+
} : {},
|
|
2473
|
+
hidden: mode !== "custom",
|
|
2474
|
+
className: ModelsSection_module_css_default["addPanel"],
|
|
2475
|
+
children: (0, react_jsx_runtime.jsx)(CustomProviderCard, {
|
|
2476
|
+
taken: state.rows.map((row) => row.entry.provider),
|
|
2477
|
+
protocols,
|
|
2478
|
+
revision: piAi.revision,
|
|
2479
|
+
operations,
|
|
2480
|
+
t,
|
|
2481
|
+
readOnly: !state.writable,
|
|
2482
|
+
onClose: (changed) => {
|
|
2483
|
+
closeAdd();
|
|
2484
|
+
if (changed) controller.load();
|
|
2485
|
+
},
|
|
2486
|
+
onBusyChange: setCustomBusy
|
|
2487
|
+
})
|
|
2488
|
+
}) : null,
|
|
2489
|
+
mounted("claude") && piAi !== void 0 ? (0, react_jsx_runtime.jsx)("div", {
|
|
2490
|
+
id: `${addId}-claude-panel`,
|
|
2491
|
+
...bothOffered ? {
|
|
2492
|
+
role: "tabpanel",
|
|
2493
|
+
"aria-labelledby": `${addId}-claude`
|
|
2494
|
+
} : {},
|
|
2495
|
+
hidden: mode !== "claude",
|
|
2496
|
+
className: ModelsSection_module_css_default["addPanel"],
|
|
2497
|
+
children: (0, react_jsx_runtime.jsx)(CustomProviderCard, {
|
|
2498
|
+
providerType: CLAUDE_PROVIDER_TYPE,
|
|
2499
|
+
taken: state.rows.map((row) => row.entry.provider),
|
|
2500
|
+
protocols,
|
|
2501
|
+
revision: piAi.revision,
|
|
2502
|
+
operations,
|
|
2503
|
+
t,
|
|
2504
|
+
readOnly: !state.writable,
|
|
2505
|
+
onClose: (changed) => {
|
|
2506
|
+
closeAdd();
|
|
2507
|
+
if (changed) controller.load();
|
|
2508
|
+
},
|
|
2509
|
+
onBusyChange: setClaudeBusy
|
|
2510
|
+
})
|
|
2511
|
+
}) : null
|
|
2320
2512
|
]
|
|
2321
|
-
}) :
|
|
2322
|
-
className: ModelsSection_module_css_default["addCard"],
|
|
2323
|
-
children: (0, react_jsx_runtime.jsx)(CustomProviderCard, {
|
|
2324
|
-
taken: state.rows.map((row) => row.entry.provider),
|
|
2325
|
-
protocols,
|
|
2326
|
-
providerType: declaringType,
|
|
2327
|
-
/* v8 ignore next -- the card only opens from a button disabled without this namespace */
|
|
2328
|
-
revision: state.namespaces.get("llm-pi-ai")?.revision ?? 0,
|
|
2329
|
-
operations,
|
|
2330
|
-
t,
|
|
2331
|
-
readOnly: !state.writable,
|
|
2332
|
-
onClose: (changed) => {
|
|
2333
|
-
setDeclaringType(void 0);
|
|
2334
|
-
if (changed) controller.load();
|
|
2335
|
-
}
|
|
2336
|
-
})
|
|
2337
|
-
}) : (0, react_jsx_runtime.jsxs)("div", {
|
|
2513
|
+
}) : catalogOffered || customOffered ? (0, react_jsx_runtime.jsx)("div", {
|
|
2338
2514
|
className: ModelsSection_module_css_default["addActions"],
|
|
2339
|
-
children:
|
|
2515
|
+
children: (0, react_jsx_runtime.jsxs)("button", {
|
|
2340
2516
|
type: "button",
|
|
2341
2517
|
className: ModelsSection_module_css_default["addButton"],
|
|
2342
|
-
disabled:
|
|
2518
|
+
disabled: !state.writable || !catalogEnabled && !customEnabled,
|
|
2343
2519
|
onClick: () => {
|
|
2344
2520
|
const first = addable[0];
|
|
2345
|
-
|
|
2346
|
-
if (first === void 0) return;
|
|
2347
|
-
setSavedTarget(void 0);
|
|
2348
|
-
setDeclaringType(void 0);
|
|
2349
|
-
setAdding(true);
|
|
2350
|
-
setEditing(targetOf(first));
|
|
2351
|
-
},
|
|
2352
|
-
children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutline16, { size: 14 }), t("add")]
|
|
2353
|
-
}), state.namespaces.has("llm-pi-ai") && (0, react_jsx_runtime.jsxs)("button", {
|
|
2354
|
-
type: "button",
|
|
2355
|
-
className: ModelsSection_module_css_default["addButton"],
|
|
2356
|
-
disabled: protocols.length === 0 || !state.writable,
|
|
2357
|
-
onClick: () => {
|
|
2521
|
+
const initial = catalogEnabled ? "catalog" : "custom";
|
|
2358
2522
|
setSavedTarget(void 0);
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2523
|
+
setEditing(first === void 0 ? void 0 : targetOf(first.row));
|
|
2524
|
+
setAddMode(initial);
|
|
2525
|
+
setVisited(new Set([initial]));
|
|
2526
|
+
setAddOpen(true);
|
|
2362
2527
|
},
|
|
2363
|
-
children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
2364
|
-
})
|
|
2365
|
-
|
|
2366
|
-
className: ModelsSection_module_css_default["addButton"],
|
|
2367
|
-
disabled: !state.namespaces.has("llm-pi-ai") || !state.namespaces.has(CLAUDE_PROVIDER_SETTINGS_NS) || !state.writable,
|
|
2368
|
-
onClick: () => {
|
|
2369
|
-
setSavedTarget(void 0);
|
|
2370
|
-
setAdding(false);
|
|
2371
|
-
setEditing(void 0);
|
|
2372
|
-
setDeclaringType(CLAUDE_PROVIDER_TYPE);
|
|
2373
|
-
},
|
|
2374
|
-
children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutline16, { size: 14 }), t("claudeCustomAdd")]
|
|
2375
|
-
})]
|
|
2376
|
-
})
|
|
2528
|
+
children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutlineRegular, { size: 14 }), t("add")]
|
|
2529
|
+
})
|
|
2530
|
+
}) : null
|
|
2377
2531
|
}),
|
|
2378
2532
|
renderSlot("settings.models.footer", {}),
|
|
2379
2533
|
(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
@@ -2406,7 +2560,7 @@ window.__ModuleLoader__.load({
|
|
|
2406
2560
|
}
|
|
2407
2561
|
//#endregion
|
|
2408
2562
|
//#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-settings-models/src/client/OnboardingModal.module.css.mjs
|
|
2409
|
-
const css$2 = ".jLrgrW_dialog{width:min(600px,100%);padding:0}.jLrgrW_content{box-sizing:border-box;flex-direction:column;
|
|
2563
|
+
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}}";
|
|
2410
2564
|
const tagId$2 = "@mofeng2223/dsh-claude-provider/OnboardingModal.module.css";
|
|
2411
2565
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$2) + "]") === null) {
|
|
2412
2566
|
const tag = document.createElement("style");
|
|
@@ -2501,20 +2655,34 @@ window.__ModuleLoader__.load({
|
|
|
2501
2655
|
* @returns the onboarding modal or null when onboarding needs no intervention.
|
|
2502
2656
|
*/
|
|
2503
2657
|
function DeepSeekOnboardingDialog(props) {
|
|
2504
|
-
const { complete, controller, useModels, operations, schema, t } = props;
|
|
2658
|
+
const { complete, controller, useModels, operations, schema, t, renderSlot, automatic, explicit = false } = props;
|
|
2659
|
+
const [apiKey, setApiKey] = (0, react.useState)(explicit);
|
|
2505
2660
|
const state = useModels((snapshot) => snapshot);
|
|
2506
2661
|
const readiness = onboardingReadiness(state);
|
|
2507
2662
|
(0, react.useEffect)(() => {
|
|
2508
|
-
if (state.status === "idle") controller.load();
|
|
2509
|
-
}, [
|
|
2663
|
+
if ((automatic || explicit) && state.status === "idle") controller.load();
|
|
2664
|
+
}, [
|
|
2665
|
+
controller,
|
|
2666
|
+
state.status,
|
|
2667
|
+
automatic,
|
|
2668
|
+
explicit
|
|
2669
|
+
]);
|
|
2510
2670
|
(0, react.useEffect)(() => {
|
|
2511
|
-
if (readiness.kind === "adapter-absent" || readiness.kind === "provider-ready" || readiness.kind === "unavailable") complete();
|
|
2512
|
-
}, [
|
|
2671
|
+
if (!automatic && !explicit || readiness.kind === "adapter-absent" || !explicit && readiness.kind === "provider-ready" || readiness.kind === "unavailable") complete();
|
|
2672
|
+
}, [
|
|
2673
|
+
complete,
|
|
2674
|
+
readiness.kind,
|
|
2675
|
+
explicit,
|
|
2676
|
+
automatic
|
|
2677
|
+
]);
|
|
2678
|
+
if (!automatic && !explicit) return null;
|
|
2513
2679
|
switch (readiness.kind) {
|
|
2514
2680
|
case "loading":
|
|
2515
2681
|
case "adapter-absent":
|
|
2516
|
-
case "provider-ready":
|
|
2517
2682
|
case "unavailable": return null;
|
|
2683
|
+
case "provider-ready":
|
|
2684
|
+
if (!explicit) return null;
|
|
2685
|
+
break;
|
|
2518
2686
|
case "credential-missing": break;
|
|
2519
2687
|
/* v8 ignore next -- every current readiness variant is handled above */
|
|
2520
2688
|
default: return assertNever$1(readiness);
|
|
@@ -2530,7 +2698,7 @@ window.__ModuleLoader__.load({
|
|
|
2530
2698
|
}
|
|
2531
2699
|
controller.load();
|
|
2532
2700
|
};
|
|
2533
|
-
|
|
2701
|
+
const editor = (0, react_jsx_runtime.jsxs)(OnboardingModal, {
|
|
2534
2702
|
title: t("onboardingTitle"),
|
|
2535
2703
|
children: [(0, react_jsx_runtime.jsx)("p", {
|
|
2536
2704
|
className: DeepSeekOnboardingDialog_module_css_default.description,
|
|
@@ -2557,6 +2725,12 @@ window.__ModuleLoader__.load({
|
|
|
2557
2725
|
})
|
|
2558
2726
|
})]
|
|
2559
2727
|
});
|
|
2728
|
+
return apiKey ? editor : renderSlot("settings.models.sign-in", {
|
|
2729
|
+
complete,
|
|
2730
|
+
useApiKey: () => {
|
|
2731
|
+
setApiKey(true);
|
|
2732
|
+
}
|
|
2733
|
+
}, { fallback: editor });
|
|
2560
2734
|
}
|
|
2561
2735
|
//#endregion
|
|
2562
2736
|
//#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-settings-models/src/client/WelcomeNotice.module.css.mjs
|
|
@@ -2634,7 +2808,7 @@ window.__ModuleLoader__.load({
|
|
|
2634
2808
|
//#endregion
|
|
2635
2809
|
//#region lib/types/onboarding-copy.js
|
|
2636
2810
|
/** Durable settings namespace for product-wide GUI onboarding facts. */
|
|
2637
|
-
const WELCOME_NOTICE_SETTINGS_NAMESPACE = "ui-
|
|
2811
|
+
const WELCOME_NOTICE_SETTINGS_NAMESPACE = "ui-settings-general";
|
|
2638
2812
|
/** Field storing the last welcome notice version the user acknowledged. */
|
|
2639
2813
|
const WELCOME_NOTICE_ACK_FIELD = "welcomeNoticeVersion";
|
|
2640
2814
|
/**
|
|
@@ -2650,16 +2824,6 @@ window.__ModuleLoader__.load({
|
|
|
2650
2824
|
* remote browser's memory-mode scope never answers and the acknowledgement
|
|
2651
2825
|
* stays process-local here.
|
|
2652
2826
|
*/
|
|
2653
|
-
/**
|
|
2654
|
-
* Accept any object section verbatim; a malformed durable value reads as an
|
|
2655
|
-
* empty section, so the notice treats it as unacknowledged instead of leaving
|
|
2656
|
-
* the scope stuck on its previous value.
|
|
2657
|
-
* @param section - the wire section value.
|
|
2658
|
-
* @returns the section object, or an empty one for non-object values.
|
|
2659
|
-
*/
|
|
2660
|
-
function decodeWelcomeSection(section) {
|
|
2661
|
-
return typeof section === "object" && section !== null && !Array.isArray(section) ? section : {};
|
|
2662
|
-
}
|
|
2663
2827
|
/* v8 ignore next 3 -- closed-union default only defends future source widening */
|
|
2664
2828
|
function assertNever(_value) {
|
|
2665
2829
|
throw new Error("unexpected welcome settings status");
|
|
@@ -2858,7 +3022,14 @@ window.__ModuleLoader__.load({
|
|
|
2858
3022
|
deleteDescriptionWithCredential: "Deleting {provider} removes its configuration and stored API key.",
|
|
2859
3023
|
deleteConfirm: "Delete {provider}",
|
|
2860
3024
|
deleting: "Deleting {provider}…",
|
|
2861
|
-
add: "Add provider",
|
|
3025
|
+
add: "Add model provider",
|
|
3026
|
+
addMode: "How to add",
|
|
3027
|
+
addCatalog: "Third-party providers",
|
|
3028
|
+
addCustom: "Custom API",
|
|
3029
|
+
addCatalogHint: "Pick OpenAI, Anthropic, Kimi, or another provider from the built-in catalog and enter its API key.",
|
|
3030
|
+
addCustomHint: "Connect a relay, a self-hosted server, or any other OpenAI- or Anthropic-compatible endpoint by its base URL, protocol, and models.",
|
|
3031
|
+
addCatalogExhausted: "Every catalog provider is already configured.",
|
|
3032
|
+
addCustomUnavailable: "No API protocol is available to declare.",
|
|
2862
3033
|
provider: "Provider",
|
|
2863
3034
|
close: "Close",
|
|
2864
3035
|
cancel: "Cancel",
|
|
@@ -2879,9 +3050,8 @@ window.__ModuleLoader__.load({
|
|
|
2879
3050
|
customized: "Customized settings",
|
|
2880
3051
|
baseUrl: "Base URL",
|
|
2881
3052
|
baseUrlDefault: "Provider default",
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
deepSeekEndpointHint: "Use an endpoint compatible with the configured connection.",
|
|
3053
|
+
deepSeekBaseUrl: "https://api.deepseek.com/anthropic",
|
|
3054
|
+
deepSeekEndpointHint: "Use an API endpoint compatible with Anthropic Messages.",
|
|
2885
3055
|
models: "Models",
|
|
2886
3056
|
modelsInherited: "Using the adapter defaults",
|
|
2887
3057
|
modelsCustomized: "Customized model catalog",
|
|
@@ -2909,7 +3079,7 @@ window.__ModuleLoader__.load({
|
|
|
2909
3079
|
modelNameInvalid: "Display name cannot be empty.",
|
|
2910
3080
|
modelContextInvalid: "Context window must be a positive count, like 131072, 256K, or 1M.",
|
|
2911
3081
|
modelMaxTokensInvalid: "Max output tokens must be a positive count, like 8192, 64K, or 1M.",
|
|
2912
|
-
advancedHint: "Other fields live in
|
|
3082
|
+
advancedHint: "Other fields live in cordis.patch.yml; edit that section directly.",
|
|
2913
3083
|
modelCapacityInvalid: "A capacity must be a number, optionally suffixed K or M.",
|
|
2914
3084
|
modelDuplicate: "Each model ID may appear once.",
|
|
2915
3085
|
fetchModels: "Fetch available models",
|
|
@@ -2923,8 +3093,6 @@ window.__ModuleLoader__.load({
|
|
|
2923
3093
|
fetchSelectAll: "Select all",
|
|
2924
3094
|
fetchDeselectAll: "Deselect all",
|
|
2925
3095
|
fetchAdopt: "Add selected",
|
|
2926
|
-
customAdd: "Add a custom provider",
|
|
2927
|
-
customTitle: "Custom provider",
|
|
2928
3096
|
customTag: "Custom",
|
|
2929
3097
|
claudeCustomAdd: "Add Claude provider",
|
|
2930
3098
|
claudeCustomTitle: "Claude provider",
|
|
@@ -2946,10 +3114,14 @@ window.__ModuleLoader__.load({
|
|
|
2946
3114
|
customDisplayName: "Display name",
|
|
2947
3115
|
customApi: "API protocol",
|
|
2948
3116
|
customApiUnset: "Not selected",
|
|
3117
|
+
protocolOpenAiCompletions: "OpenAI Chat Completions",
|
|
3118
|
+
protocolOpenAiResponses: "OpenAI Responses",
|
|
3119
|
+
protocolAnthropicMessages: "Anthropic Messages",
|
|
2949
3120
|
customNeedsBaseUrl: "A custom provider needs a base URL.",
|
|
2950
3121
|
customBaseUrlInvalid: "Enter a valid HTTP or HTTPS URL.",
|
|
2951
3122
|
customNeedsModels: "A custom provider needs at least one model.",
|
|
2952
3123
|
customBaseUrlPlaceholder: "https://gateway.example/v1",
|
|
3124
|
+
customAnthropicBaseUrlPlaceholder: "https://gateway.example",
|
|
2953
3125
|
settingsPathUnresolvable: "unresolvable settings path",
|
|
2954
3126
|
create: "Create provider",
|
|
2955
3127
|
creating: "Creating…",
|
|
@@ -2968,7 +3140,7 @@ window.__ModuleLoader__.load({
|
|
|
2968
3140
|
const zh = {
|
|
2969
3141
|
nav: "模型",
|
|
2970
3142
|
title: "模型",
|
|
2971
|
-
intro: "
|
|
3143
|
+
intro: "填入各提供商的 API 密钥即可使用其模型。",
|
|
2972
3144
|
edit: "编辑",
|
|
2973
3145
|
editProvider: "编辑 {provider}",
|
|
2974
3146
|
remove: "删除",
|
|
@@ -2978,8 +3150,15 @@ window.__ModuleLoader__.load({
|
|
|
2978
3150
|
deleteDescriptionWithCredential: "删除 {provider} 会移除其配置和存储的 API 密钥。",
|
|
2979
3151
|
deleteConfirm: "删除 {provider}",
|
|
2980
3152
|
deleting: "正在删除 {provider}…",
|
|
2981
|
-
add: "
|
|
2982
|
-
|
|
3153
|
+
add: "添加模型提供商",
|
|
3154
|
+
addMode: "添加方式",
|
|
3155
|
+
addCatalog: "第三方模型提供商",
|
|
3156
|
+
addCustom: "自定义模型 API",
|
|
3157
|
+
addCatalogHint: "从内置目录中选择 OpenAI、Anthropic、Kimi 等提供商,填入其 API 密钥即可使用。",
|
|
3158
|
+
addCustomHint: "连接中转站、自部署服务或其他兼容 OpenAI / Anthropic 协议的接口,需填写 API 地址、协议和模型。",
|
|
3159
|
+
addCatalogExhausted: "目录中的提供商都已添加。",
|
|
3160
|
+
addCustomUnavailable: "没有可用的 API 协议。",
|
|
3161
|
+
provider: "提供商",
|
|
2983
3162
|
close: "关闭",
|
|
2984
3163
|
cancel: "取消",
|
|
2985
3164
|
apply: "保存",
|
|
@@ -2988,7 +3167,7 @@ window.__ModuleLoader__.load({
|
|
|
2988
3167
|
credentialConfigured: "API 密钥已配置",
|
|
2989
3168
|
credentialMissing: "API 密钥缺失",
|
|
2990
3169
|
readOnly: "当前部署的设置文档为只读。",
|
|
2991
|
-
loadFailed: "
|
|
3170
|
+
loadFailed: "加载提供商目录失败",
|
|
2992
3171
|
conflict: "这张卡片打开期间,这些设置已被其他地方改动。请关闭后重新打开,在当前值上编辑。",
|
|
2993
3172
|
retry: "重试",
|
|
2994
3173
|
keyInput: "API 密钥",
|
|
@@ -2998,10 +3177,9 @@ window.__ModuleLoader__.load({
|
|
|
2998
3177
|
keyEnvLocked: "由启动环境提供(只读)",
|
|
2999
3178
|
customized: "自定义设置",
|
|
3000
3179
|
baseUrl: "API 地址",
|
|
3001
|
-
baseUrlDefault: "
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
deepSeekEndpointHint: "请填写与当前连接配置兼容的 API 地址。",
|
|
3180
|
+
baseUrlDefault: "提供商默认",
|
|
3181
|
+
deepSeekBaseUrl: "https://api.deepseek.com/anthropic",
|
|
3182
|
+
deepSeekEndpointHint: "请填写兼容 Anthropic Messages 协议的 API 地址。",
|
|
3005
3183
|
models: "模型目录",
|
|
3006
3184
|
modelsInherited: "正在使用适配器默认模型",
|
|
3007
3185
|
modelsCustomized: "已自定义模型目录",
|
|
@@ -3011,9 +3189,9 @@ window.__ModuleLoader__.load({
|
|
|
3011
3189
|
modelName: "显示名称",
|
|
3012
3190
|
modelNamePlaceholder: "留空时使用模型 ID",
|
|
3013
3191
|
contextWindow: "上下文窗口",
|
|
3014
|
-
contextWindowPlaceholder: "
|
|
3192
|
+
contextWindowPlaceholder: "使用提供商默认值",
|
|
3015
3193
|
maxTokens: "最大输出 token 数",
|
|
3016
|
-
maxTokensPlaceholder: "
|
|
3194
|
+
maxTokensPlaceholder: "使用提供商默认值",
|
|
3017
3195
|
modelAdvanced: "模型选项",
|
|
3018
3196
|
modelInputTypes: "输入类型",
|
|
3019
3197
|
modelInputText: "文本",
|
|
@@ -3022,29 +3200,27 @@ window.__ModuleLoader__.load({
|
|
|
3022
3200
|
removeModel: "删除模型",
|
|
3023
3201
|
modelsEmpty: "模型选择器中将不显示任何模型;目录外 ID 仍可直接发送。",
|
|
3024
3202
|
keyBlank: "请输入 API 密钥;留空则保持已存储的密钥。",
|
|
3025
|
-
keyBlankNew: "请输入 API
|
|
3203
|
+
keyBlankNew: "请输入 API 密钥;若该提供商以其他方式鉴权,可以留空。",
|
|
3026
3204
|
keyIllegalCharacters: "该 API 密钥格式错误,请检查。",
|
|
3027
3205
|
modelIdRequired: "模型 ID 不能为空。",
|
|
3028
3206
|
modelIdDuplicate: "模型 ID 不能重复。",
|
|
3029
3207
|
modelNameInvalid: "显示名称不能为空。",
|
|
3030
3208
|
modelContextInvalid: "上下文窗口必须是正数,例如 131072、256K 或 1M。",
|
|
3031
3209
|
modelMaxTokensInvalid: "最大输出 token 数必须是正数,例如 8192、64K 或 1M。",
|
|
3032
|
-
advancedHint: "其余字段在
|
|
3210
|
+
advancedHint: "其余字段在 cordis.patch.yml 中,请直接编辑对应段。",
|
|
3033
3211
|
modelCapacityInvalid: "容量需为数字,可加 K 或 M 后缀。",
|
|
3034
3212
|
modelDuplicate: "每个模型 ID 只能出现一次。",
|
|
3035
3213
|
fetchModels: "获取可用模型",
|
|
3036
|
-
fetching: "
|
|
3214
|
+
fetching: "正在询问提供商…",
|
|
3037
3215
|
fetchNeedsBaseUrl: "请先填写 API 地址,再获取。",
|
|
3038
|
-
fetchEmpty: "
|
|
3216
|
+
fetchEmpty: "该提供商没有列出任何模型,请手动添加。",
|
|
3039
3217
|
fetchTitle: "选择要添加的模型",
|
|
3040
|
-
fetchDescription: "
|
|
3218
|
+
fetchDescription: "以下是模型提供商的可用模型,勾选要添加的模型。",
|
|
3041
3219
|
fetchSearch: "搜索模型",
|
|
3042
3220
|
fetchNoMatches: "没有匹配的模型。",
|
|
3043
3221
|
fetchSelectAll: "全选",
|
|
3044
3222
|
fetchDeselectAll: "取消全选",
|
|
3045
3223
|
fetchAdopt: "添加所选",
|
|
3046
|
-
customAdd: "添加自定义提供方",
|
|
3047
|
-
customTitle: "自定义提供方",
|
|
3048
3224
|
customTag: "自定义",
|
|
3049
3225
|
claudeCustomAdd: "添加 Claude 提供方",
|
|
3050
3226
|
claudeCustomTitle: "Claude 提供方",
|
|
@@ -3060,18 +3236,22 @@ window.__ModuleLoader__.load({
|
|
|
3060
3236
|
thinkingPresetFour: "四档",
|
|
3061
3237
|
thinkingPresetFive: "五档(默认)",
|
|
3062
3238
|
customRoute: "Provider ID",
|
|
3063
|
-
customRouteHint: "
|
|
3239
|
+
customRouteHint: "以小写字母开头的标识,在请求中唯一标识该提供商,并用于派生凭据名。",
|
|
3064
3240
|
customRouteInvalid: "需以小写字母开头,之后可用小写字母、数字和短横线。",
|
|
3065
|
-
customRouteTaken: "
|
|
3241
|
+
customRouteTaken: "已有提供商使用了这个 ID。",
|
|
3066
3242
|
customDisplayName: "显示名称",
|
|
3067
3243
|
customApi: "API 协议",
|
|
3068
3244
|
customApiUnset: "未选择",
|
|
3069
|
-
|
|
3245
|
+
protocolOpenAiCompletions: "OpenAI Chat Completions",
|
|
3246
|
+
protocolOpenAiResponses: "OpenAI Responses",
|
|
3247
|
+
protocolAnthropicMessages: "Anthropic Messages",
|
|
3248
|
+
customNeedsBaseUrl: "自定义模型 API 需要填写 API 地址。",
|
|
3070
3249
|
customBaseUrlInvalid: "请输入有效的 HTTP 或 HTTPS 地址。",
|
|
3071
|
-
customNeedsModels: "
|
|
3250
|
+
customNeedsModels: "自定义模型 API 至少需要一个模型。",
|
|
3072
3251
|
customBaseUrlPlaceholder: "https://gateway.example/v1",
|
|
3252
|
+
customAnthropicBaseUrlPlaceholder: "https://gateway.example",
|
|
3073
3253
|
settingsPathUnresolvable: "无法解析设置路径",
|
|
3074
|
-
create: "
|
|
3254
|
+
create: "创建提供商",
|
|
3075
3255
|
creating: "创建中…",
|
|
3076
3256
|
welcomeTitle: "内测声明",
|
|
3077
3257
|
welcomeBody: "DeepSeek Harness 目前的 0.1 版本仍处在面向 Harness 开发者进行测试的阶段,还有许多地方需要持续改进和打磨,希望听取广大开发者的反馈建议。预计 DeepSeek Harness 的核心插件以及基础 API 都会在接下来的一段时间内快速迭代、持续演化。\n\n我们期待与全球开发者一起,在开源、开放、可复用、可组合的基础设施之上,共同探索智能上限。欢迎全球 Harness 开发者加入 DSH 插件生态。",
|
|
@@ -3085,6 +3265,904 @@ window.__ModuleLoader__.load({
|
|
|
3085
3265
|
keyRequired: "请输入 API 密钥后继续。"
|
|
3086
3266
|
};
|
|
3087
3267
|
//#endregion
|
|
3268
|
+
//#region ../../../vendor/cosmokit/src/misc.ts
|
|
3269
|
+
/** Return true when a value is `null` or `undefined`. */
|
|
3270
|
+
function isNullable(value) {
|
|
3271
|
+
return value === null || value === void 0;
|
|
3272
|
+
}
|
|
3273
|
+
/** Return true for non-array object values. */
|
|
3274
|
+
function isPlainObject(data) {
|
|
3275
|
+
return data && typeof data === "object" && !Array.isArray(data);
|
|
3276
|
+
}
|
|
3277
|
+
/** Filter object entries and return a new object. */
|
|
3278
|
+
function filterKeys(object, filter) {
|
|
3279
|
+
return Object.fromEntries(Object.entries(object).filter(([key, value]) => filter(key, value)));
|
|
3280
|
+
}
|
|
3281
|
+
/** Map object values while preserving the original key set. */
|
|
3282
|
+
function mapValues(object, transform) {
|
|
3283
|
+
return Object.fromEntries(Object.entries(object).map(([key, value]) => [key, transform(value, key)]));
|
|
3284
|
+
}
|
|
3285
|
+
/** Pick selected keys from an object, optionally including `undefined` values. */
|
|
3286
|
+
function pick(source, keys, forced) {
|
|
3287
|
+
if (!keys) return { ...source };
|
|
3288
|
+
const result = {};
|
|
3289
|
+
for (const key of keys) if (forced || source[key] !== void 0) result[key] = source[key];
|
|
3290
|
+
return result;
|
|
3291
|
+
}
|
|
3292
|
+
//#endregion
|
|
3293
|
+
//#region ../../../vendor/cosmokit/src/volatile.ts
|
|
3294
|
+
/** Shared config references used by schema validators and plugin runtimes. */
|
|
3295
|
+
const write = Symbol.for("cosmokit.volatile.write");
|
|
3296
|
+
function snapshot(value, ancestors = /* @__PURE__ */ new Set()) {
|
|
3297
|
+
if (typeof value === "function") throw new TypeError("volatile config cannot contain functions");
|
|
3298
|
+
if (value === null || typeof value !== "object") return value;
|
|
3299
|
+
if (ancestors.has(value)) throw new TypeError("volatile config cannot contain cycles");
|
|
3300
|
+
ancestors.add(value);
|
|
3301
|
+
try {
|
|
3302
|
+
if (Array.isArray(value)) return Object.freeze(value.map((item) => snapshot(item, ancestors)));
|
|
3303
|
+
if (Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) throw new TypeError("volatile config objects must be plain objects or arrays");
|
|
3304
|
+
return Object.freeze(Object.fromEntries(Object.entries(value).map(([key, item]) => [key, snapshot(item, ancestors)])));
|
|
3305
|
+
} finally {
|
|
3306
|
+
ancestors.delete(value);
|
|
3307
|
+
}
|
|
3308
|
+
}
|
|
3309
|
+
/**
|
|
3310
|
+
* Create a detached reference containing an immutable copy of the supplied data.
|
|
3311
|
+
* @param value - validated config data; class instances and functions are unsupported.
|
|
3312
|
+
* @returns a reference whose value is updated only by its owning runtime.
|
|
3313
|
+
*/
|
|
3314
|
+
function createVolatile(value) {
|
|
3315
|
+
let current = snapshot(value);
|
|
3316
|
+
return Object.freeze({
|
|
3317
|
+
get: () => current,
|
|
3318
|
+
[write]: (value) => {
|
|
3319
|
+
current = value;
|
|
3320
|
+
}
|
|
3321
|
+
});
|
|
3322
|
+
}
|
|
3323
|
+
/**
|
|
3324
|
+
* Identify references across ESM/CJS copies of the shared library.
|
|
3325
|
+
* @param value - a parsed config value.
|
|
3326
|
+
* @returns whether the value implements the shared reference protocol.
|
|
3327
|
+
*/
|
|
3328
|
+
function isVolatile(value) {
|
|
3329
|
+
return typeof value === "object" && value !== null && write in value;
|
|
3330
|
+
}
|
|
3331
|
+
//#endregion
|
|
3332
|
+
//#region ../../../vendor/cosmokit/src/types.ts
|
|
3333
|
+
/** Test values using `instanceof` with a `toStringTag` fallback. */
|
|
3334
|
+
function is(type, value) {
|
|
3335
|
+
if (arguments.length === 1) return (value) => is(type, value);
|
|
3336
|
+
return type in globalThis && value instanceof globalThis[type] || Object.prototype.toString.call(value).slice(8, -1) === type;
|
|
3337
|
+
}
|
|
3338
|
+
function isArrayBufferLike(value) {
|
|
3339
|
+
return is("ArrayBuffer", value) || is("SharedArrayBuffer", value);
|
|
3340
|
+
}
|
|
3341
|
+
function isArrayBufferSource(value) {
|
|
3342
|
+
return isArrayBufferLike(value) || ArrayBuffer.isView(value);
|
|
3343
|
+
}
|
|
3344
|
+
let Binary;
|
|
3345
|
+
(function(_Binary) {
|
|
3346
|
+
_Binary.is = isArrayBufferLike;
|
|
3347
|
+
_Binary.isSource = isArrayBufferSource;
|
|
3348
|
+
function fromSource(source) {
|
|
3349
|
+
if (ArrayBuffer.isView(source)) return source.buffer.slice(source.byteOffset, source.byteOffset + source.byteLength);
|
|
3350
|
+
else return source;
|
|
3351
|
+
}
|
|
3352
|
+
_Binary.fromSource = fromSource;
|
|
3353
|
+
function toBase64(source) {
|
|
3354
|
+
source = fromSource(source);
|
|
3355
|
+
if (typeof Buffer !== "undefined") return Buffer.from(source).toString("base64");
|
|
3356
|
+
let binary = "";
|
|
3357
|
+
const bytes = new Uint8Array(source);
|
|
3358
|
+
for (let i = 0; i < bytes.byteLength; i++) binary += String.fromCharCode(bytes[i]);
|
|
3359
|
+
return btoa(binary);
|
|
3360
|
+
}
|
|
3361
|
+
_Binary.toBase64 = toBase64;
|
|
3362
|
+
function fromBase64(source) {
|
|
3363
|
+
if (typeof Buffer !== "undefined") return fromSource(Buffer.from(source, "base64"));
|
|
3364
|
+
return Uint8Array.from(atob(source), (c) => c.charCodeAt(0));
|
|
3365
|
+
}
|
|
3366
|
+
_Binary.fromBase64 = fromBase64;
|
|
3367
|
+
function toHex(source) {
|
|
3368
|
+
source = fromSource(source);
|
|
3369
|
+
if (typeof Buffer !== "undefined") return Buffer.from(source).toString("hex");
|
|
3370
|
+
return Array.from(new Uint8Array(source), (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
3371
|
+
}
|
|
3372
|
+
_Binary.toHex = toHex;
|
|
3373
|
+
function fromHex(source) {
|
|
3374
|
+
if (typeof Buffer !== "undefined") return fromSource(Buffer.from(source, "hex"));
|
|
3375
|
+
const hex = source.length % 2 === 0 ? source : source.slice(0, source.length - 1);
|
|
3376
|
+
const buffer = [];
|
|
3377
|
+
for (let i = 0; i < hex.length; i += 2) buffer.push(parseInt(`${hex[i]}${hex[i + 1]}`, 16));
|
|
3378
|
+
return Uint8Array.from(buffer).buffer;
|
|
3379
|
+
}
|
|
3380
|
+
_Binary.fromHex = fromHex;
|
|
3381
|
+
})(Binary || (Binary = {}));
|
|
3382
|
+
Binary.fromBase64;
|
|
3383
|
+
Binary.toBase64;
|
|
3384
|
+
Binary.fromHex;
|
|
3385
|
+
Binary.toHex;
|
|
3386
|
+
/** Deep-clone common JavaScript values while preserving prototypes and cycles. */
|
|
3387
|
+
function clone(source, refs = /* @__PURE__ */ new Map()) {
|
|
3388
|
+
if (!source || typeof source !== "object") return source;
|
|
3389
|
+
if (is("Date", source)) return new Date(source.valueOf());
|
|
3390
|
+
if (is("RegExp", source)) return new RegExp(source.source, source.flags);
|
|
3391
|
+
if (isArrayBufferLike(source)) return source.slice(0);
|
|
3392
|
+
if (ArrayBuffer.isView(source)) return source.buffer.slice(source.byteOffset, source.byteOffset + source.byteLength);
|
|
3393
|
+
const cached = refs.get(source);
|
|
3394
|
+
if (cached) return cached;
|
|
3395
|
+
if (Array.isArray(source)) {
|
|
3396
|
+
const result = [];
|
|
3397
|
+
refs.set(source, result);
|
|
3398
|
+
source.forEach((value, index) => {
|
|
3399
|
+
result[index] = Reflect.apply(clone, null, [value, refs]);
|
|
3400
|
+
});
|
|
3401
|
+
return result;
|
|
3402
|
+
}
|
|
3403
|
+
const result = Object.create(Object.getPrototypeOf(source));
|
|
3404
|
+
refs.set(source, result);
|
|
3405
|
+
for (const key of Reflect.ownKeys(source)) {
|
|
3406
|
+
const descriptor = { ...Reflect.getOwnPropertyDescriptor(source, key) };
|
|
3407
|
+
if ("value" in descriptor) descriptor.value = Reflect.apply(clone, null, [descriptor.value, refs]);
|
|
3408
|
+
Reflect.defineProperty(result, key, descriptor);
|
|
3409
|
+
}
|
|
3410
|
+
return result;
|
|
3411
|
+
}
|
|
3412
|
+
/**
|
|
3413
|
+
* Compare values recursively, treating two volatile references as equal regardless of value.
|
|
3414
|
+
* Strict comparison distinguishes null/undefined, treats opaque objects by identity,
|
|
3415
|
+
* compares URLs by normalized href, treats array holes as undefined, and considers distinct cyclic structures unequal.
|
|
3416
|
+
* @param a - first value.
|
|
3417
|
+
* @param b - second value.
|
|
3418
|
+
* @param strict - whether to require strict data equality outside volatile references.
|
|
3419
|
+
* @returns whether the values compare equal.
|
|
3420
|
+
*/
|
|
3421
|
+
function deepEqual(a, b, strict) {
|
|
3422
|
+
const ancestors = /* @__PURE__ */ new Set();
|
|
3423
|
+
function compare(a, b) {
|
|
3424
|
+
if (a === b) return true;
|
|
3425
|
+
if (isVolatile(a) || isVolatile(b)) return isVolatile(a) && isVolatile(b);
|
|
3426
|
+
if (!strict && isNullable(a) && isNullable(b)) return true;
|
|
3427
|
+
if (typeof a !== typeof b || typeof a !== "object" || !a || !b) return false;
|
|
3428
|
+
if (ancestors.has(a)) return false;
|
|
3429
|
+
function check(test, then) {
|
|
3430
|
+
return test(a) ? test(b) ? then(a, b) : false : test(b) ? false : void 0;
|
|
3431
|
+
}
|
|
3432
|
+
ancestors.add(a);
|
|
3433
|
+
try {
|
|
3434
|
+
return check(Array.isArray, (a, b) => {
|
|
3435
|
+
if (a.length !== b.length) return false;
|
|
3436
|
+
for (let index = 0; index < a.length; index++) if (!compare(a[index], b[index])) return false;
|
|
3437
|
+
return true;
|
|
3438
|
+
}) ?? 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) => {
|
|
3439
|
+
if (a.byteLength !== b.byteLength) return false;
|
|
3440
|
+
const viewA = new Uint8Array(a);
|
|
3441
|
+
const viewB = new Uint8Array(b);
|
|
3442
|
+
for (let i = 0; i < viewA.length; i++) if (viewA[i] !== viewB[i]) return false;
|
|
3443
|
+
return true;
|
|
3444
|
+
}) ?? ((!strict || [a, b].every((value) => Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null)) && Object.keys({
|
|
3445
|
+
...a,
|
|
3446
|
+
...b
|
|
3447
|
+
}).every((key) => compare(a[key], b[key])));
|
|
3448
|
+
} finally {
|
|
3449
|
+
ancestors.delete(a);
|
|
3450
|
+
}
|
|
3451
|
+
}
|
|
3452
|
+
return compare(a, b);
|
|
3453
|
+
}
|
|
3454
|
+
//#endregion
|
|
3455
|
+
//#region ../../../vendor/cosmokit/src/time.ts
|
|
3456
|
+
let Time;
|
|
3457
|
+
(function(_Time) {
|
|
3458
|
+
_Time.millisecond = 1;
|
|
3459
|
+
const second = _Time.second = 1e3;
|
|
3460
|
+
const minute = _Time.minute = second * 60;
|
|
3461
|
+
const hour = _Time.hour = minute * 60;
|
|
3462
|
+
const day = _Time.day = hour * 24;
|
|
3463
|
+
const week = _Time.week = day * 7;
|
|
3464
|
+
let timezoneOffset = (/* @__PURE__ */ new Date()).getTimezoneOffset();
|
|
3465
|
+
function setTimezoneOffset(offset) {
|
|
3466
|
+
timezoneOffset = offset;
|
|
3467
|
+
}
|
|
3468
|
+
_Time.setTimezoneOffset = setTimezoneOffset;
|
|
3469
|
+
function getTimezoneOffset() {
|
|
3470
|
+
return timezoneOffset;
|
|
3471
|
+
}
|
|
3472
|
+
_Time.getTimezoneOffset = getTimezoneOffset;
|
|
3473
|
+
function getDateNumber(date = /* @__PURE__ */ new Date(), offset) {
|
|
3474
|
+
if (typeof date === "number") date = new Date(date);
|
|
3475
|
+
if (offset === void 0) offset = timezoneOffset;
|
|
3476
|
+
return Math.floor((date.valueOf() / minute - offset) / 1440);
|
|
3477
|
+
}
|
|
3478
|
+
_Time.getDateNumber = getDateNumber;
|
|
3479
|
+
function fromDateNumber(value, offset) {
|
|
3480
|
+
const date = new Date(value * day);
|
|
3481
|
+
if (offset === void 0) offset = timezoneOffset;
|
|
3482
|
+
return new Date(+date + offset * minute);
|
|
3483
|
+
}
|
|
3484
|
+
_Time.fromDateNumber = fromDateNumber;
|
|
3485
|
+
const numeric = /\d+(?:\.\d+)?/.source;
|
|
3486
|
+
const timeRegExp = new RegExp(`^${[
|
|
3487
|
+
"w(?:eek(?:s)?)?",
|
|
3488
|
+
"d(?:ay(?:s)?)?",
|
|
3489
|
+
"h(?:our(?:s)?)?",
|
|
3490
|
+
"m(?:in(?:ute)?(?:s)?)?",
|
|
3491
|
+
"s(?:ec(?:ond)?(?:s)?)?"
|
|
3492
|
+
].map((unit) => `(${numeric}${unit})?`).join("")}$`);
|
|
3493
|
+
function parseTime(source) {
|
|
3494
|
+
const capture = timeRegExp.exec(source);
|
|
3495
|
+
if (!capture) return 0;
|
|
3496
|
+
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);
|
|
3497
|
+
}
|
|
3498
|
+
_Time.parseTime = parseTime;
|
|
3499
|
+
function parseDate(date) {
|
|
3500
|
+
const parsed = parseTime(date);
|
|
3501
|
+
if (parsed) date = Date.now() + parsed;
|
|
3502
|
+
else if (/^\d{1,2}(:\d{1,2}){1,2}$/.test(date)) date = `${(/* @__PURE__ */ new Date()).toLocaleDateString()}-${date}`;
|
|
3503
|
+
else if (/^\d{1,2}-\d{1,2}-\d{1,2}(:\d{1,2}){1,2}$/.test(date)) date = `${(/* @__PURE__ */ new Date()).getFullYear()}-${date}`;
|
|
3504
|
+
return date ? new Date(date) : /* @__PURE__ */ new Date();
|
|
3505
|
+
}
|
|
3506
|
+
_Time.parseDate = parseDate;
|
|
3507
|
+
function format(ms) {
|
|
3508
|
+
const abs = Math.abs(ms);
|
|
3509
|
+
if (abs >= day - hour / 2) return Math.round(ms / day) + "d";
|
|
3510
|
+
else if (abs >= hour - minute / 2) return Math.round(ms / hour) + "h";
|
|
3511
|
+
else if (abs >= minute - second / 2) return Math.round(ms / minute) + "m";
|
|
3512
|
+
else if (abs >= second) return Math.round(ms / second) + "s";
|
|
3513
|
+
return ms + "ms";
|
|
3514
|
+
}
|
|
3515
|
+
_Time.format = format;
|
|
3516
|
+
function toDigits(source, length = 2) {
|
|
3517
|
+
return source.toString().padStart(length, "0");
|
|
3518
|
+
}
|
|
3519
|
+
_Time.toDigits = toDigits;
|
|
3520
|
+
function template(template, time = /* @__PURE__ */ new Date()) {
|
|
3521
|
+
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));
|
|
3522
|
+
}
|
|
3523
|
+
_Time.template = template;
|
|
3524
|
+
})(Time || (Time = {}));
|
|
3525
|
+
//#endregion
|
|
3526
|
+
//#region ../../../vendor/schemastery/src/index.ts
|
|
3527
|
+
const kSchema = Symbol.for("schemastery");
|
|
3528
|
+
const kValidationError = Symbol.for("ValidationError");
|
|
3529
|
+
globalThis.__schemastery_index__ ??= 0;
|
|
3530
|
+
globalThis.__schemastery_refs__ = void 0;
|
|
3531
|
+
var ValidationError = class extends TypeError {
|
|
3532
|
+
options;
|
|
3533
|
+
name = "ValidationError";
|
|
3534
|
+
constructor(message, options) {
|
|
3535
|
+
let prefix = "$";
|
|
3536
|
+
for (const segment of options.path || []) if (typeof segment === "string") prefix += "." + segment;
|
|
3537
|
+
else if (typeof segment === "number") prefix += "[" + segment + "]";
|
|
3538
|
+
else if (typeof segment === "symbol") prefix += `[Symbol(${segment.toString()})]`;
|
|
3539
|
+
if (prefix.startsWith(".")) prefix = prefix.slice(1);
|
|
3540
|
+
super((prefix === "$" ? "" : `${prefix} `) + message);
|
|
3541
|
+
this.options = options;
|
|
3542
|
+
}
|
|
3543
|
+
static is(error) {
|
|
3544
|
+
return !!error?.[kValidationError];
|
|
3545
|
+
}
|
|
3546
|
+
};
|
|
3547
|
+
Object.defineProperty(ValidationError.prototype, kValidationError, { value: true });
|
|
3548
|
+
const Schema = function(options) {
|
|
3549
|
+
const schema = function(data, options = {}) {
|
|
3550
|
+
return Schema.resolve(data, schema, options)[0];
|
|
3551
|
+
};
|
|
3552
|
+
if (options.refs) {
|
|
3553
|
+
const refs = mapValues(options.refs, (options) => new Schema(options));
|
|
3554
|
+
const getRef = (uid) => refs[uid];
|
|
3555
|
+
for (const key in refs) {
|
|
3556
|
+
const options = refs[key];
|
|
3557
|
+
options.sKey = getRef(options.sKey);
|
|
3558
|
+
options.inner = getRef(options.inner);
|
|
3559
|
+
options.list = options.list && options.list.map(getRef);
|
|
3560
|
+
options.dict = options.dict && mapValues(options.dict, getRef);
|
|
3561
|
+
}
|
|
3562
|
+
return refs[options.uid];
|
|
3563
|
+
}
|
|
3564
|
+
Object.assign(schema, options);
|
|
3565
|
+
if (typeof schema.callback === "string") try {
|
|
3566
|
+
schema.callback = new Function("return " + schema.callback)();
|
|
3567
|
+
} catch {}
|
|
3568
|
+
Object.defineProperty(schema, "uid", { value: globalThis.__schemastery_index__++ });
|
|
3569
|
+
Object.setPrototypeOf(schema, Schema.prototype);
|
|
3570
|
+
schema.meta ||= {};
|
|
3571
|
+
schema.toString = schema.toString.bind(schema);
|
|
3572
|
+
return schema;
|
|
3573
|
+
};
|
|
3574
|
+
Schema.prototype = Object.create(Function.prototype);
|
|
3575
|
+
Schema.prototype[kSchema] = true;
|
|
3576
|
+
Object.defineProperty(Schema.prototype, "~standard", { get() {
|
|
3577
|
+
return {
|
|
3578
|
+
version: 1,
|
|
3579
|
+
vendor: "schemastery",
|
|
3580
|
+
validate: (value) => {
|
|
3581
|
+
try {
|
|
3582
|
+
return { value: Schema.resolve(value, this, {})[0] };
|
|
3583
|
+
} catch (error) {
|
|
3584
|
+
if (ValidationError.is(error)) return { issues: [{
|
|
3585
|
+
message: error.message,
|
|
3586
|
+
path: error.options.path
|
|
3587
|
+
}] };
|
|
3588
|
+
throw error;
|
|
3589
|
+
}
|
|
3590
|
+
}
|
|
3591
|
+
};
|
|
3592
|
+
} });
|
|
3593
|
+
Schema.ValidationError = ValidationError;
|
|
3594
|
+
Schema.prototype.toJSON = function toJSON() {
|
|
3595
|
+
if (globalThis.__schemastery_refs__) {
|
|
3596
|
+
globalThis.__schemastery_refs__[this.uid] ??= JSON.parse(JSON.stringify({ ...this }));
|
|
3597
|
+
return this.uid;
|
|
3598
|
+
}
|
|
3599
|
+
globalThis.__schemastery_refs__ = { [this.uid]: { ...this } };
|
|
3600
|
+
globalThis.__schemastery_refs__[this.uid] = JSON.parse(JSON.stringify({ ...this }));
|
|
3601
|
+
const result = {
|
|
3602
|
+
uid: this.uid,
|
|
3603
|
+
refs: globalThis.__schemastery_refs__
|
|
3604
|
+
};
|
|
3605
|
+
globalThis.__schemastery_refs__ = void 0;
|
|
3606
|
+
return result;
|
|
3607
|
+
};
|
|
3608
|
+
Schema.prototype.set = function set(key, value) {
|
|
3609
|
+
this.dict[key] = value;
|
|
3610
|
+
return this;
|
|
3611
|
+
};
|
|
3612
|
+
Schema.prototype.push = function push(value) {
|
|
3613
|
+
this.list.push(value);
|
|
3614
|
+
return this;
|
|
3615
|
+
};
|
|
3616
|
+
function mergeDesc(original, messages) {
|
|
3617
|
+
const result = typeof original === "string" ? { "": original } : { ...original };
|
|
3618
|
+
for (const locale in messages) {
|
|
3619
|
+
const value = messages[locale];
|
|
3620
|
+
if (value?.$description || value?.$desc) result[locale] = value.$description || value.$desc;
|
|
3621
|
+
else if (typeof value === "string") result[locale] = value;
|
|
3622
|
+
}
|
|
3623
|
+
return result;
|
|
3624
|
+
}
|
|
3625
|
+
function getInner(value) {
|
|
3626
|
+
return value?.$value ?? value?.$inner;
|
|
3627
|
+
}
|
|
3628
|
+
function extractKeys(data) {
|
|
3629
|
+
return filterKeys(data ?? {}, (key) => !key.startsWith("$"));
|
|
3630
|
+
}
|
|
3631
|
+
Schema.prototype.i18n = function i18n(messages) {
|
|
3632
|
+
const schema = Schema(this);
|
|
3633
|
+
const desc = mergeDesc(schema.meta.description, messages);
|
|
3634
|
+
if (Object.keys(desc).length) schema.meta.description = desc;
|
|
3635
|
+
if (schema.dict) schema.dict = mapValues(schema.dict, (inner, key) => {
|
|
3636
|
+
return inner.i18n(mapValues(messages, (data) => getInner(data)?.[key] ?? data?.[key]));
|
|
3637
|
+
});
|
|
3638
|
+
if (schema.list) schema.list = schema.list.map((inner, index) => {
|
|
3639
|
+
return inner.i18n(mapValues(messages, (data = {}) => {
|
|
3640
|
+
if (Array.isArray(getInner(data))) return getInner(data)[index];
|
|
3641
|
+
if (Array.isArray(data)) return data[index];
|
|
3642
|
+
return extractKeys(data);
|
|
3643
|
+
}));
|
|
3644
|
+
});
|
|
3645
|
+
if (schema.inner) schema.inner = schema.inner.i18n(mapValues(messages, (data) => {
|
|
3646
|
+
if (getInner(data)) return getInner(data);
|
|
3647
|
+
return extractKeys(data);
|
|
3648
|
+
}));
|
|
3649
|
+
if (schema.sKey) schema.sKey = schema.sKey.i18n(mapValues(messages, (data) => data?.$key));
|
|
3650
|
+
return schema;
|
|
3651
|
+
};
|
|
3652
|
+
Schema.prototype.extra = function extra(key, value) {
|
|
3653
|
+
const schema = Schema(this);
|
|
3654
|
+
schema.meta = {
|
|
3655
|
+
...schema.meta,
|
|
3656
|
+
[key]: value
|
|
3657
|
+
};
|
|
3658
|
+
return schema;
|
|
3659
|
+
};
|
|
3660
|
+
for (const key of [
|
|
3661
|
+
"required",
|
|
3662
|
+
"disabled",
|
|
3663
|
+
"collapse",
|
|
3664
|
+
"hidden",
|
|
3665
|
+
"loose"
|
|
3666
|
+
]) Object.assign(Schema.prototype, { [key](value = true) {
|
|
3667
|
+
const schema = Schema(this);
|
|
3668
|
+
schema.meta = {
|
|
3669
|
+
...schema.meta,
|
|
3670
|
+
[key]: value
|
|
3671
|
+
};
|
|
3672
|
+
return schema;
|
|
3673
|
+
} });
|
|
3674
|
+
Schema.prototype.deprecated = function deprecated() {
|
|
3675
|
+
const schema = Schema(this);
|
|
3676
|
+
schema.meta.badges ||= [];
|
|
3677
|
+
schema.meta.badges.push({
|
|
3678
|
+
text: "deprecated",
|
|
3679
|
+
type: "danger"
|
|
3680
|
+
});
|
|
3681
|
+
return schema;
|
|
3682
|
+
};
|
|
3683
|
+
Schema.prototype.experimental = function experimental() {
|
|
3684
|
+
const schema = Schema(this);
|
|
3685
|
+
schema.meta.badges ||= [];
|
|
3686
|
+
schema.meta.badges.push({
|
|
3687
|
+
text: "experimental",
|
|
3688
|
+
type: "warning"
|
|
3689
|
+
});
|
|
3690
|
+
return schema;
|
|
3691
|
+
};
|
|
3692
|
+
Schema.prototype.pattern = function pattern(regexp) {
|
|
3693
|
+
const schema = Schema(this);
|
|
3694
|
+
const pattern = pick(regexp, ["source", "flags"]);
|
|
3695
|
+
schema.meta = {
|
|
3696
|
+
...schema.meta,
|
|
3697
|
+
pattern
|
|
3698
|
+
};
|
|
3699
|
+
return schema;
|
|
3700
|
+
};
|
|
3701
|
+
Schema.prototype.simplify = function simplify(value) {
|
|
3702
|
+
if (isVolatile(value)) value = value.get();
|
|
3703
|
+
if (deepEqual(value, this.meta.default, this.type === "dict")) return null;
|
|
3704
|
+
if (isNullable(value)) return value;
|
|
3705
|
+
if (this.type === "object" || this.type === "dict") {
|
|
3706
|
+
const result = {};
|
|
3707
|
+
for (const key in value) {
|
|
3708
|
+
const item = (this.type === "object" ? this.dict[key] : this.inner)?.simplify(value[key]);
|
|
3709
|
+
if (this.type === "dict" || !isNullable(item)) result[key] = item;
|
|
3710
|
+
}
|
|
3711
|
+
if (deepEqual(result, this.meta.default, this.type === "dict")) return null;
|
|
3712
|
+
return result;
|
|
3713
|
+
} else if (this.type === "array" || this.type === "tuple") {
|
|
3714
|
+
const result = [];
|
|
3715
|
+
value.forEach((value, index) => {
|
|
3716
|
+
const schema = this.type === "array" ? this.inner : this.list[index];
|
|
3717
|
+
const item = schema ? schema.simplify(value) : value;
|
|
3718
|
+
result.push(item);
|
|
3719
|
+
});
|
|
3720
|
+
return result;
|
|
3721
|
+
} else if (this.type === "intersect") {
|
|
3722
|
+
const result = {};
|
|
3723
|
+
for (const item of this.list) Object.assign(result, item.simplify(value));
|
|
3724
|
+
return result;
|
|
3725
|
+
} else if (this.type === "union") for (const schema of this.list) try {
|
|
3726
|
+
Schema.resolve(value, schema, {});
|
|
3727
|
+
return schema.simplify(value);
|
|
3728
|
+
} catch {}
|
|
3729
|
+
return value;
|
|
3730
|
+
};
|
|
3731
|
+
Schema.prototype.toString = function toString(inline) {
|
|
3732
|
+
return formatters[this.type]?.(this, inline) ?? `Schema<${this.type}>`;
|
|
3733
|
+
};
|
|
3734
|
+
Schema.prototype.role = function role(role, extra) {
|
|
3735
|
+
const schema = Schema(this);
|
|
3736
|
+
schema.meta = {
|
|
3737
|
+
...schema.meta,
|
|
3738
|
+
role,
|
|
3739
|
+
extra
|
|
3740
|
+
};
|
|
3741
|
+
return schema;
|
|
3742
|
+
};
|
|
3743
|
+
for (const key of [
|
|
3744
|
+
"default",
|
|
3745
|
+
"link",
|
|
3746
|
+
"comment",
|
|
3747
|
+
"description",
|
|
3748
|
+
"max",
|
|
3749
|
+
"min",
|
|
3750
|
+
"step"
|
|
3751
|
+
]) Object.assign(Schema.prototype, { [key](value) {
|
|
3752
|
+
const schema = Schema(this);
|
|
3753
|
+
schema.meta = {
|
|
3754
|
+
...schema.meta,
|
|
3755
|
+
[key]: value
|
|
3756
|
+
};
|
|
3757
|
+
return schema;
|
|
3758
|
+
} });
|
|
3759
|
+
Schema.prototype.volatile = function volatile() {
|
|
3760
|
+
if (this.meta.volatile) throw new TypeError("volatile schema is already wrapped");
|
|
3761
|
+
return this.extra("volatile", true);
|
|
3762
|
+
};
|
|
3763
|
+
const resolvers = {};
|
|
3764
|
+
const checkedVolatile = Symbol("checked-volatile-schema");
|
|
3765
|
+
function validateVolatileSchema(schema, path = [], blocked = false, seen = /* @__PURE__ */ new Map()) {
|
|
3766
|
+
const states = seen.get(schema) ?? /* @__PURE__ */ new Set();
|
|
3767
|
+
if (states.has(blocked)) return;
|
|
3768
|
+
states.add(blocked);
|
|
3769
|
+
seen.set(schema, states);
|
|
3770
|
+
if (schema.meta?.volatile && blocked) throw new ValidationError("volatile fields require a fixed object path without an enclosing volatile field", { path });
|
|
3771
|
+
const nested = blocked || !!schema.meta?.volatile;
|
|
3772
|
+
if (schema.dict) for (const [key, child] of Object.entries(schema.dict)) validateVolatileSchema(child, [...path, key], nested, seen);
|
|
3773
|
+
if (schema.sKey) validateVolatileSchema(schema.sKey, [...path, "<key>"], true, seen);
|
|
3774
|
+
if (schema.inner && (schema.type !== "lazy" || schema.inner[kSchema])) validateVolatileSchema(schema.inner, [...path, "*"], true, seen);
|
|
3775
|
+
if (schema.list) for (let index = 0; index < schema.list.length; index++) validateVolatileSchema(schema.list[index], [...path, String(index)], true, seen);
|
|
3776
|
+
}
|
|
3777
|
+
Schema.extend = function extend(type, resolve) {
|
|
3778
|
+
resolvers[type] = resolve;
|
|
3779
|
+
};
|
|
3780
|
+
Schema.resolve = function resolve(data, schema, options = {}, strict = false) {
|
|
3781
|
+
if (!schema) return [data];
|
|
3782
|
+
if (!options[checkedVolatile]) {
|
|
3783
|
+
validateVolatileSchema(schema, options.path);
|
|
3784
|
+
options = {
|
|
3785
|
+
...options,
|
|
3786
|
+
[checkedVolatile]: true
|
|
3787
|
+
};
|
|
3788
|
+
}
|
|
3789
|
+
if (schema.meta?.volatile) {
|
|
3790
|
+
const inner = Schema(schema);
|
|
3791
|
+
inner.meta = {
|
|
3792
|
+
...schema.meta,
|
|
3793
|
+
volatile: false
|
|
3794
|
+
};
|
|
3795
|
+
const [value, adapted] = Schema.resolve(data, inner, options, strict);
|
|
3796
|
+
try {
|
|
3797
|
+
return [createVolatile(value), adapted];
|
|
3798
|
+
} catch (error) {
|
|
3799
|
+
throw new ValidationError(error instanceof Error ? error.message : String(error), options);
|
|
3800
|
+
}
|
|
3801
|
+
}
|
|
3802
|
+
if (options.ignore?.(data, schema)) return [data];
|
|
3803
|
+
if (isNullable(data) && schema.type !== "lazy") {
|
|
3804
|
+
if (schema.meta.required) throw new ValidationError(`missing required value`, options);
|
|
3805
|
+
let current = schema;
|
|
3806
|
+
let fallback = schema.meta.default;
|
|
3807
|
+
while (current?.type === "intersect" && isNullable(fallback)) {
|
|
3808
|
+
current = current.list[0];
|
|
3809
|
+
fallback = current?.meta.default;
|
|
3810
|
+
}
|
|
3811
|
+
if (isNullable(fallback)) return [data];
|
|
3812
|
+
data = clone(fallback);
|
|
3813
|
+
}
|
|
3814
|
+
const callback = resolvers[schema.type];
|
|
3815
|
+
if (!callback) throw new ValidationError(`unsupported type "${schema.type}"`, options);
|
|
3816
|
+
try {
|
|
3817
|
+
return callback(data, schema, options, strict);
|
|
3818
|
+
} catch (error) {
|
|
3819
|
+
if (!schema.meta.loose) throw error;
|
|
3820
|
+
return [schema.meta.default];
|
|
3821
|
+
}
|
|
3822
|
+
};
|
|
3823
|
+
Schema.from = function from(source) {
|
|
3824
|
+
if (isNullable(source)) return Schema.any();
|
|
3825
|
+
else if ([
|
|
3826
|
+
"string",
|
|
3827
|
+
"number",
|
|
3828
|
+
"boolean"
|
|
3829
|
+
].includes(typeof source)) return Schema.const(source).required();
|
|
3830
|
+
else if (source[kSchema]) return source;
|
|
3831
|
+
else if (typeof source === "function") switch (source) {
|
|
3832
|
+
case String: return Schema.string().required();
|
|
3833
|
+
case Number: return Schema.number().required();
|
|
3834
|
+
case Boolean: return Schema.boolean().required();
|
|
3835
|
+
case Function: return Schema.function().required();
|
|
3836
|
+
default: return Schema.is(source).required();
|
|
3837
|
+
}
|
|
3838
|
+
else throw new TypeError(`cannot infer schema from ${source}`);
|
|
3839
|
+
};
|
|
3840
|
+
Schema.lazy = function lazy(builder) {
|
|
3841
|
+
const toJSON = () => {
|
|
3842
|
+
if (!schema.inner[kSchema]) {
|
|
3843
|
+
schema.inner = schema.builder();
|
|
3844
|
+
schema.inner.meta = {
|
|
3845
|
+
...schema.meta,
|
|
3846
|
+
...schema.inner.meta
|
|
3847
|
+
};
|
|
3848
|
+
}
|
|
3849
|
+
return schema.inner.toJSON();
|
|
3850
|
+
};
|
|
3851
|
+
const schema = new Schema({
|
|
3852
|
+
type: "lazy",
|
|
3853
|
+
builder,
|
|
3854
|
+
inner: { toJSON }
|
|
3855
|
+
});
|
|
3856
|
+
return schema;
|
|
3857
|
+
};
|
|
3858
|
+
Schema.natural = function natural() {
|
|
3859
|
+
return Schema.number().step(1).min(0);
|
|
3860
|
+
};
|
|
3861
|
+
Schema.percent = function percent() {
|
|
3862
|
+
return Schema.number().step(.01).min(0).max(1).role("slider");
|
|
3863
|
+
};
|
|
3864
|
+
Schema.date = function date() {
|
|
3865
|
+
return Schema.union([Schema.is(Date), Schema.transform(Schema.string().role("datetime"), (value, options) => {
|
|
3866
|
+
const date = new Date(value);
|
|
3867
|
+
if (isNaN(+date)) throw new ValidationError(`invalid date "${value}"`, options);
|
|
3868
|
+
return date;
|
|
3869
|
+
}, true)]);
|
|
3870
|
+
};
|
|
3871
|
+
Schema.regExp = function regExp(flag = "") {
|
|
3872
|
+
return Schema.union([Schema.is(RegExp), Schema.transform(Schema.string().role("regexp", { flag }), (value, options) => {
|
|
3873
|
+
try {
|
|
3874
|
+
return new RegExp(value, flag);
|
|
3875
|
+
} catch (e) {
|
|
3876
|
+
throw new ValidationError(e.message, options);
|
|
3877
|
+
}
|
|
3878
|
+
}, true)]);
|
|
3879
|
+
};
|
|
3880
|
+
Schema.arrayBuffer = function arrayBuffer(encoding) {
|
|
3881
|
+
return Schema.union([
|
|
3882
|
+
Schema.is(ArrayBuffer),
|
|
3883
|
+
Schema.is(SharedArrayBuffer),
|
|
3884
|
+
Schema.transform(Schema.any(), (value, options) => {
|
|
3885
|
+
if (Binary.isSource(value)) return Binary.fromSource(value);
|
|
3886
|
+
throw new ValidationError(`expected ArrayBufferSource but got ${value}`, options);
|
|
3887
|
+
}, true),
|
|
3888
|
+
...encoding ? [Schema.transform(Schema.string(), (value, options) => {
|
|
3889
|
+
try {
|
|
3890
|
+
return encoding === "base64" ? Binary.fromBase64(value) : Binary.fromHex(value);
|
|
3891
|
+
} catch (e) {
|
|
3892
|
+
throw new ValidationError(e.message, options);
|
|
3893
|
+
}
|
|
3894
|
+
}, true)] : []
|
|
3895
|
+
]);
|
|
3896
|
+
};
|
|
3897
|
+
Schema.extend("lazy", (data, schema, options, strict) => {
|
|
3898
|
+
if (!schema.inner[kSchema]) {
|
|
3899
|
+
schema.inner = schema.builder();
|
|
3900
|
+
schema.inner.meta = {
|
|
3901
|
+
...schema.meta,
|
|
3902
|
+
...schema.inner.meta
|
|
3903
|
+
};
|
|
3904
|
+
validateVolatileSchema(schema.inner, options.path, true);
|
|
3905
|
+
}
|
|
3906
|
+
return Schema.resolve(data, schema.inner, options, strict);
|
|
3907
|
+
});
|
|
3908
|
+
Schema.extend("any", (data) => {
|
|
3909
|
+
return [data];
|
|
3910
|
+
});
|
|
3911
|
+
Schema.extend("never", (data, _, options) => {
|
|
3912
|
+
throw new ValidationError(`expected nullable but got ${data}`, options);
|
|
3913
|
+
});
|
|
3914
|
+
Schema.extend("const", (data, { value }, options) => {
|
|
3915
|
+
if (deepEqual(data, value)) return [value];
|
|
3916
|
+
throw new ValidationError(`expected ${value} but got ${data}`, options);
|
|
3917
|
+
});
|
|
3918
|
+
function checkWithinRange(data, meta, description, options, skipMin = false) {
|
|
3919
|
+
const { max = Infinity, min = -Infinity } = meta;
|
|
3920
|
+
if (data > max) throw new ValidationError(`expected ${description} <= ${max} but got ${data}`, options);
|
|
3921
|
+
if (data < min && !skipMin) throw new ValidationError(`expected ${description} >= ${min} but got ${data}`, options);
|
|
3922
|
+
}
|
|
3923
|
+
Schema.extend("string", (data, { meta }, options) => {
|
|
3924
|
+
if (typeof data !== "string") throw new ValidationError(`expected string but got ${data}`, options);
|
|
3925
|
+
if (meta.pattern) {
|
|
3926
|
+
const regexp = new RegExp(meta.pattern.source, meta.pattern.flags);
|
|
3927
|
+
if (!regexp.test(data)) throw new ValidationError(`expect string to match regexp ${regexp}`, options);
|
|
3928
|
+
}
|
|
3929
|
+
checkWithinRange(data.length, meta, "string length", options);
|
|
3930
|
+
return [data];
|
|
3931
|
+
});
|
|
3932
|
+
function decimalShift(data, digits) {
|
|
3933
|
+
const str = data.toString();
|
|
3934
|
+
if (str.includes("e")) return data * Math.pow(10, digits);
|
|
3935
|
+
const index = str.indexOf(".");
|
|
3936
|
+
if (index === -1) return data * Math.pow(10, digits);
|
|
3937
|
+
const frac = str.slice(index + 1);
|
|
3938
|
+
const integer = str.slice(0, index);
|
|
3939
|
+
if (frac.length <= digits) return +(integer + frac.padEnd(digits, "0"));
|
|
3940
|
+
return +(integer + frac.slice(0, digits) + "." + frac.slice(digits));
|
|
3941
|
+
}
|
|
3942
|
+
function isMultipleOf(data, min, step) {
|
|
3943
|
+
step = Math.abs(step);
|
|
3944
|
+
if (!/^\d+\.\d+$/.test(step.toString())) return (data - min) % step === 0;
|
|
3945
|
+
const index = step.toString().indexOf(".");
|
|
3946
|
+
const digits = step.toString().slice(index + 1).length;
|
|
3947
|
+
return Math.abs(decimalShift(data, digits) - decimalShift(min, digits)) % decimalShift(step, digits) === 0;
|
|
3948
|
+
}
|
|
3949
|
+
Schema.extend("number", (data, { meta }, options) => {
|
|
3950
|
+
if (typeof data !== "number") throw new ValidationError(`expected number but got ${data}`, options);
|
|
3951
|
+
checkWithinRange(data, meta, "number", options);
|
|
3952
|
+
const { step } = meta;
|
|
3953
|
+
if (step && !isMultipleOf(data, meta.min ?? 0, step)) throw new ValidationError(`expected number multiple of ${step} but got ${data}`, options);
|
|
3954
|
+
return [data];
|
|
3955
|
+
});
|
|
3956
|
+
Schema.extend("boolean", (data, _, options) => {
|
|
3957
|
+
if (typeof data === "boolean") return [data];
|
|
3958
|
+
throw new ValidationError(`expected boolean but got ${data}`, options);
|
|
3959
|
+
});
|
|
3960
|
+
Schema.extend("bitset", (data, { bits, meta }, options) => {
|
|
3961
|
+
let value = 0, keys = [];
|
|
3962
|
+
if (typeof data === "number") {
|
|
3963
|
+
value = data;
|
|
3964
|
+
for (const key in bits) if (data & bits[key]) keys.push(key);
|
|
3965
|
+
} else if (Array.isArray(data)) {
|
|
3966
|
+
keys = data;
|
|
3967
|
+
for (const key of keys) {
|
|
3968
|
+
if (typeof key !== "string") throw new ValidationError(`expected string but got ${key}`, options);
|
|
3969
|
+
if (key in bits) value |= bits[key];
|
|
3970
|
+
}
|
|
3971
|
+
} else throw new ValidationError(`expected number or array but got ${data}`, options);
|
|
3972
|
+
if (value === meta.default) return [value];
|
|
3973
|
+
return [value, keys];
|
|
3974
|
+
});
|
|
3975
|
+
Schema.extend("function", (data, _, options) => {
|
|
3976
|
+
if (typeof data === "function") return [data];
|
|
3977
|
+
throw new ValidationError(`expected function but got ${data}`, options);
|
|
3978
|
+
});
|
|
3979
|
+
Schema.extend("is", (data, { constructor }, options) => {
|
|
3980
|
+
if (typeof constructor === "function") {
|
|
3981
|
+
if (data instanceof constructor) return [data];
|
|
3982
|
+
throw new ValidationError(`expected ${constructor.name} but got ${data}`, options);
|
|
3983
|
+
} else {
|
|
3984
|
+
if (isNullable(data)) throw new ValidationError(`expected ${constructor} but got ${data}`, options);
|
|
3985
|
+
let prototype = Object.getPrototypeOf(data);
|
|
3986
|
+
while (prototype) {
|
|
3987
|
+
if (prototype.constructor?.name === constructor) return [data];
|
|
3988
|
+
prototype = Object.getPrototypeOf(prototype);
|
|
3989
|
+
}
|
|
3990
|
+
throw new ValidationError(`expected ${constructor} but got ${data}`, options);
|
|
3991
|
+
}
|
|
3992
|
+
});
|
|
3993
|
+
function property(data, key, schema, options) {
|
|
3994
|
+
try {
|
|
3995
|
+
const [value, adapted] = Schema.resolve(data[key], schema, {
|
|
3996
|
+
...options,
|
|
3997
|
+
path: [...options.path || [], key]
|
|
3998
|
+
});
|
|
3999
|
+
if (adapted !== void 0) data[key] = adapted;
|
|
4000
|
+
return value;
|
|
4001
|
+
} catch (e) {
|
|
4002
|
+
if (!options?.autofix) throw e;
|
|
4003
|
+
delete data[key];
|
|
4004
|
+
return schema.meta.volatile ? createVolatile(schema.meta.default) : schema.meta.default;
|
|
4005
|
+
}
|
|
4006
|
+
}
|
|
4007
|
+
Schema.extend("array", (data, { inner, meta }, options) => {
|
|
4008
|
+
if (!Array.isArray(data)) throw new ValidationError(`expected array but got ${data}`, options);
|
|
4009
|
+
checkWithinRange(data.length, meta, "array length", options, !isNullable(inner.meta.default));
|
|
4010
|
+
return [data.map((_, index) => property(data, index, inner, options))];
|
|
4011
|
+
});
|
|
4012
|
+
Schema.extend("dict", (data, { inner, sKey }, options, strict) => {
|
|
4013
|
+
if (!isPlainObject(data)) throw new ValidationError(`expected object but got ${data}`, options);
|
|
4014
|
+
const result = {};
|
|
4015
|
+
for (const key in data) {
|
|
4016
|
+
let rKey;
|
|
4017
|
+
try {
|
|
4018
|
+
rKey = Schema.resolve(key, sKey, options)[0];
|
|
4019
|
+
} catch (error) {
|
|
4020
|
+
if (strict) continue;
|
|
4021
|
+
throw error;
|
|
4022
|
+
}
|
|
4023
|
+
result[rKey] = property(data, key, inner, options);
|
|
4024
|
+
data[rKey] = data[key];
|
|
4025
|
+
if (key !== rKey) delete data[key];
|
|
4026
|
+
}
|
|
4027
|
+
return [result];
|
|
4028
|
+
});
|
|
4029
|
+
Schema.extend("tuple", (data, { list }, options, strict) => {
|
|
4030
|
+
if (!Array.isArray(data)) throw new ValidationError(`expected array but got ${data}`, options);
|
|
4031
|
+
const result = list.map((inner, index) => property(data, index, inner, options));
|
|
4032
|
+
if (strict) return [result];
|
|
4033
|
+
result.push(...data.slice(list.length));
|
|
4034
|
+
return [result];
|
|
4035
|
+
});
|
|
4036
|
+
function merge(result, data) {
|
|
4037
|
+
for (const key in data) {
|
|
4038
|
+
if (key in result) continue;
|
|
4039
|
+
result[key] = data[key];
|
|
4040
|
+
}
|
|
4041
|
+
}
|
|
4042
|
+
Schema.extend("object", (data, { dict }, options, strict) => {
|
|
4043
|
+
if (!isPlainObject(data)) throw new ValidationError(`expected object but got ${data}`, options);
|
|
4044
|
+
const result = {};
|
|
4045
|
+
for (const key in dict) {
|
|
4046
|
+
const value = property(data, key, dict[key], options);
|
|
4047
|
+
if (!isNullable(value) || key in data) result[key] = value;
|
|
4048
|
+
}
|
|
4049
|
+
if (!strict) merge(result, data);
|
|
4050
|
+
return [result];
|
|
4051
|
+
});
|
|
4052
|
+
Schema.extend("union", (data, { list, toString }, options, strict) => {
|
|
4053
|
+
const messages = [];
|
|
4054
|
+
for (const inner of list) try {
|
|
4055
|
+
return Schema.resolve(data, inner, options, strict);
|
|
4056
|
+
} catch (error) {
|
|
4057
|
+
messages.push(error);
|
|
4058
|
+
}
|
|
4059
|
+
throw new ValidationError(`expected ${toString()} but got ${JSON.stringify(data)}`, options);
|
|
4060
|
+
});
|
|
4061
|
+
Schema.extend("intersect", (data, { list, toString }, options, strict) => {
|
|
4062
|
+
if (!list.length) return [data];
|
|
4063
|
+
let result;
|
|
4064
|
+
for (const inner of list) {
|
|
4065
|
+
const value = Schema.resolve(data, inner, options, true)[0];
|
|
4066
|
+
if (isNullable(value)) continue;
|
|
4067
|
+
if (isNullable(result)) result = value;
|
|
4068
|
+
else if (typeof result !== typeof value) throw new ValidationError(`expected ${toString()} but got ${JSON.stringify(data)}`, options);
|
|
4069
|
+
else if (typeof value === "object") merge(result ??= {}, value);
|
|
4070
|
+
else if (result !== value) throw new ValidationError(`expected ${toString()} but got ${JSON.stringify(data)}`, options);
|
|
4071
|
+
}
|
|
4072
|
+
if (!strict && isPlainObject(data)) merge(result, data);
|
|
4073
|
+
return [result];
|
|
4074
|
+
});
|
|
4075
|
+
Schema.extend("transform", (data, { inner, callback, preserve }, options) => {
|
|
4076
|
+
const [result, adapted = data] = Schema.resolve(data, inner, options, true);
|
|
4077
|
+
if (preserve) return [callback(result)];
|
|
4078
|
+
else return [callback(result), callback(adapted)];
|
|
4079
|
+
});
|
|
4080
|
+
const formatters = {};
|
|
4081
|
+
function defineMethod(name, keys, format) {
|
|
4082
|
+
formatters[name] = format;
|
|
4083
|
+
Object.assign(Schema, { [name](...args) {
|
|
4084
|
+
const schema = new Schema({ type: name });
|
|
4085
|
+
keys.forEach((key, index) => {
|
|
4086
|
+
switch (key) {
|
|
4087
|
+
case "sKey":
|
|
4088
|
+
schema.sKey = args[index] ?? Schema.string();
|
|
4089
|
+
break;
|
|
4090
|
+
case "inner":
|
|
4091
|
+
schema.inner = Schema.from(args[index]);
|
|
4092
|
+
break;
|
|
4093
|
+
case "list":
|
|
4094
|
+
schema.list = args[index].map(Schema.from);
|
|
4095
|
+
break;
|
|
4096
|
+
case "dict":
|
|
4097
|
+
schema.dict = mapValues(args[index], Schema.from);
|
|
4098
|
+
break;
|
|
4099
|
+
case "bits":
|
|
4100
|
+
schema.bits = {};
|
|
4101
|
+
for (const key in args[index]) {
|
|
4102
|
+
if (typeof args[index][key] !== "number") continue;
|
|
4103
|
+
schema.bits[key] = args[index][key];
|
|
4104
|
+
}
|
|
4105
|
+
break;
|
|
4106
|
+
case "callback": {
|
|
4107
|
+
const callback = schema.callback = args[index];
|
|
4108
|
+
callback["toJSON"] ||= () => callback.toString();
|
|
4109
|
+
break;
|
|
4110
|
+
}
|
|
4111
|
+
case "constructor": {
|
|
4112
|
+
const constructor = schema.constructor = args[index];
|
|
4113
|
+
if (typeof constructor === "function") constructor["toJSON"] ||= () => constructor["name"];
|
|
4114
|
+
break;
|
|
4115
|
+
}
|
|
4116
|
+
default: schema[key] = args[index];
|
|
4117
|
+
}
|
|
4118
|
+
});
|
|
4119
|
+
if (name === "object" || name === "dict") schema.meta.default = {};
|
|
4120
|
+
else if (name === "array" || name === "tuple") schema.meta.default = [];
|
|
4121
|
+
else if (name === "bitset") schema.meta.default = 0;
|
|
4122
|
+
return schema;
|
|
4123
|
+
} });
|
|
4124
|
+
}
|
|
4125
|
+
defineMethod("is", ["constructor"], ({ constructor }) => {
|
|
4126
|
+
if (typeof constructor === "function") return constructor.name;
|
|
4127
|
+
else return constructor;
|
|
4128
|
+
});
|
|
4129
|
+
defineMethod("any", [], () => "any");
|
|
4130
|
+
defineMethod("never", [], () => "never");
|
|
4131
|
+
defineMethod("const", ["value"], ({ value }) => typeof value === "string" ? JSON.stringify(value) : value);
|
|
4132
|
+
defineMethod("string", [], () => "string");
|
|
4133
|
+
defineMethod("number", [], () => "number");
|
|
4134
|
+
defineMethod("boolean", [], () => "boolean");
|
|
4135
|
+
defineMethod("bitset", ["bits"], () => "bitset");
|
|
4136
|
+
defineMethod("function", [], () => "function");
|
|
4137
|
+
defineMethod("array", ["inner"], ({ inner }) => `${inner.toString(true)}[]`);
|
|
4138
|
+
defineMethod("dict", ["inner", "sKey"], ({ inner, sKey }) => `{ [key: ${sKey.toString()}]: ${inner.toString()} }`);
|
|
4139
|
+
defineMethod("tuple", ["list"], ({ list }) => `[${list.map((inner) => inner.toString()).join(", ")}]`);
|
|
4140
|
+
defineMethod("object", ["dict"], ({ dict }) => {
|
|
4141
|
+
if (Object.keys(dict).length === 0) return "{}";
|
|
4142
|
+
return `{ ${Object.entries(dict).map(([key, inner]) => {
|
|
4143
|
+
return `${key}${inner.meta.required ? "" : "?"}: ${inner.toString()}`;
|
|
4144
|
+
}).join(", ")} }`;
|
|
4145
|
+
});
|
|
4146
|
+
defineMethod("union", ["list"], ({ list }, inline) => {
|
|
4147
|
+
const result = list.map(({ toString: format }) => format()).join(" | ");
|
|
4148
|
+
return inline ? `(${result})` : result;
|
|
4149
|
+
});
|
|
4150
|
+
defineMethod("intersect", ["list"], ({ list }) => {
|
|
4151
|
+
return `${list.map((inner) => inner.toString(true)).join(" & ")}`;
|
|
4152
|
+
});
|
|
4153
|
+
defineMethod("transform", [
|
|
4154
|
+
"inner",
|
|
4155
|
+
"callback",
|
|
4156
|
+
"preserve"
|
|
4157
|
+
], ({ inner }, isInner) => inner.toString(isInner));
|
|
4158
|
+
//#endregion
|
|
4159
|
+
//#region lib/types/onboarding-config.js
|
|
4160
|
+
/** Public page-bootstrap options shared by the Host and Client halves. */
|
|
4161
|
+
/** Validate Host configuration and its public page-bootstrap payload. */
|
|
4162
|
+
const Config = Schema.object({ credentialOnboarding: Schema.boolean().default(true) });
|
|
4163
|
+
/** Page-global key carrying only the public onboarding options. */
|
|
4164
|
+
const ONBOARDING_CONFIG_GLOBAL = "__DSH_MODELS_ONBOARDING__";
|
|
4165
|
+
//#endregion
|
|
3088
4166
|
//#region lib/types/client/index.js
|
|
3089
4167
|
/** Dictionary namespace owned by this plugin. */
|
|
3090
4168
|
const NS = "settings.models";
|
|
@@ -3109,7 +4187,7 @@ window.__ModuleLoader__.load({
|
|
|
3109
4187
|
"remote.credentials",
|
|
3110
4188
|
"remote.llm",
|
|
3111
4189
|
"remote.settings",
|
|
3112
|
-
"
|
|
4190
|
+
"configForms",
|
|
3113
4191
|
"settingsSchema"
|
|
3114
4192
|
];
|
|
3115
4193
|
/**
|
|
@@ -3119,13 +4197,15 @@ window.__ModuleLoader__.load({
|
|
|
3119
4197
|
* @param ctx - client root context.
|
|
3120
4198
|
*/
|
|
3121
4199
|
function apply(ctx) {
|
|
4200
|
+
const payload = globalThis[ONBOARDING_CONFIG_GLOBAL];
|
|
4201
|
+
const credentialOnboarding = Config(payload === void 0 ? {} : payload).credentialOnboarding && !("dshDesktop" in globalThis);
|
|
3122
4202
|
ctx.effect(() => ctx.locale.register(NS, {
|
|
3123
4203
|
zh,
|
|
3124
4204
|
en
|
|
3125
4205
|
}), "ui-settings-models: copy dictionaries");
|
|
3126
4206
|
const schema = createSettingsSchemaOperations(ctx.settingsSchema);
|
|
3127
4207
|
const operations = createModelsOperations(ctx);
|
|
3128
|
-
const controller = new ModelsSettingsStore(ctx, schema, ctx.
|
|
4208
|
+
const controller = new ModelsSettingsStore(ctx, schema, ctx.configForms.describe());
|
|
3129
4209
|
const t = ctx.locale.bind(NS);
|
|
3130
4210
|
const injected = () => ({
|
|
3131
4211
|
controller,
|
|
@@ -3135,16 +4215,14 @@ window.__ModuleLoader__.load({
|
|
|
3135
4215
|
t
|
|
3136
4216
|
});
|
|
3137
4217
|
const deepSeekOnboardingInjected = () => ({
|
|
4218
|
+
automatic: credentialOnboarding,
|
|
3138
4219
|
controller,
|
|
3139
4220
|
hooks: { models: controller.store },
|
|
3140
4221
|
operations,
|
|
3141
4222
|
schema,
|
|
3142
4223
|
t
|
|
3143
4224
|
});
|
|
3144
|
-
const welcomeController = new WelcomeNoticeStore(ctx.
|
|
3145
|
-
namespace: WELCOME_NOTICE_SETTINGS_NAMESPACE,
|
|
3146
|
-
decode: decodeWelcomeSection
|
|
3147
|
-
}));
|
|
4225
|
+
const welcomeController = new WelcomeNoticeStore(ctx.configForms.get(WELCOME_NOTICE_SETTINGS_NAMESPACE));
|
|
3148
4226
|
const welcomeInjected = () => ({
|
|
3149
4227
|
controller: welcomeController,
|
|
3150
4228
|
hooks: { welcome: welcomeController.store },
|
|
@@ -3194,6 +4272,10 @@ window.__ModuleLoader__.load({
|
|
|
3194
4272
|
ctx.slots.inject("settings.onboarding", () => ctx.slots.register({
|
|
3195
4273
|
name: "settings.onboarding",
|
|
3196
4274
|
id: "deepseek-official",
|
|
4275
|
+
children: { "settings.models.sign-in": {
|
|
4276
|
+
kind: "single",
|
|
4277
|
+
scope: "root"
|
|
4278
|
+
} },
|
|
3197
4279
|
order: 0,
|
|
3198
4280
|
inject: deepSeekOnboardingInjected
|
|
3199
4281
|
}, DeepSeekOnboardingDialog));
|