@deepseek-ai/dsh-client-ui-settings-models 0.1.6-alpha.2 → 0.1.7-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/client.js CHANGED
@@ -55,7 +55,7 @@ window.__ModuleLoader__.load({
55
55
  }
56
56
  //#endregion
57
57
  //#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-settings-models/src/client/ModelsSection.module.css.mjs
58
- const css$3 = ".zGbnIq_section{max-width:720px;color:var(--dsw-alias-label-primary);flex-direction:column;gap:12px;display:flex}.zGbnIq_title{color:var(--dsw-alias-label-primary);margin:0;font-size:16px;font-weight:500;line-height:24px}.zGbnIq_intro{color:var(--dsw-alias-label-tertiary);margin:0;font-size:14px;line-height:22px}.zGbnIq_notice{color:var(--dsw-alias-state-warn-label);margin:0;font-size:12px;line-height:18px}.zGbnIq_savedNotice{color:var(--dsw-alias-state-success-primary);margin:0;font-size:12px;line-height:18px}.zGbnIq_rows{flex-direction:column;gap:8px;margin:12px 0 0;padding:0;list-style:none;display:flex}.zGbnIq_rowCard{border:.5px solid var(--dsw-alias-border-l4);border-radius:16px;flex-direction:column;gap:12px;padding:12px 14px;display:flex}.zGbnIq_rowHead{align-items:center;gap:10px;display:flex}.zGbnIq_rowIdentity{align-items:center;gap:6px;min-width:0;display:inline-flex}.zGbnIq_rowName{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:500;line-height:22px}.zGbnIq_rowTag{border:.5px solid var(--dsw-alias-border-l3);color:var(--dsw-alias-label-secondary);border-radius:4px;flex:none;padding:1px 6px;font-size:11px;line-height:16px}.zGbnIq_credentialDot{box-sizing:border-box;corner-shape:round;border-radius:50%;flex:none;width:8px;height:8px;display:inline-block}.zGbnIq_credentialDotConfigured{background:var(--dsw-alias-state-success-primary)}.zGbnIq_credentialDotMissing{background:var(--dsw-alias-state-error-primary)}.zGbnIq_rowActions{align-items:center;gap:4px;margin-left:auto;display:inline-flex}.zGbnIq_primaryButton,.zGbnIq_secondaryButton,.zGbnIq_addButton{box-sizing:border-box;height:36px;font:inherit;cursor:pointer;border:none;border-radius:18px;justify-content:center;align-items:center;gap:4px;padding:0 14px;font-size:14px;line-height:22px;display:inline-flex}.zGbnIq_primaryButton{background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-foreground)}.zGbnIq_primaryButton:hover:not(:disabled){background:var(--dsw-alias-button-primary-hover)}.zGbnIq_secondaryButton,.zGbnIq_addButton{border:.5px solid var(--dsw-alias-border-l3);color:var(--dsw-alias-label-primary);background:0 0}.zGbnIq_secondaryButton:hover:not(:disabled),.zGbnIq_addButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.zGbnIq_secondaryButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-solid)}.zGbnIq_dangerButton{box-sizing:border-box;height:36px;color:var(--dsw-alias-state-error-primary);font:inherit;cursor:pointer;background:0 0;border:none;border-radius:18px;justify-content:center;align-items:center;padding:0 14px;font-size:14px;line-height:22px;display:inline-flex}.zGbnIq_dangerButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger)}.zGbnIq_rowActions .zGbnIq_secondaryButton,.zGbnIq_rowActions .zGbnIq_dangerButton{border-radius:14px;height:28px;padding:0 10px;font-size:12px;line-height:18px}.zGbnIq_primaryButton:disabled,.zGbnIq_secondaryButton:disabled,.zGbnIq_dangerButton:disabled,.zGbnIq_addButton:disabled,.zGbnIq_linkButton:disabled,.zGbnIq_addModelButton:disabled{opacity:.4;cursor:default}.zGbnIq_primaryButton:focus-visible,.zGbnIq_secondaryButton:focus-visible,.zGbnIq_dangerButton:focus-visible,.zGbnIq_addButton:focus-visible,.zGbnIq_linkButton:focus-visible,.zGbnIq_addModelButton:focus-visible,.zGbnIq_iconButton:focus-visible,.zGbnIq_customizedSummary:focus-visible{box-shadow:0 0 0 2px var(--dsw-alias-border-l3);outline:none}.zGbnIq_editor{background:var(--dsw-alias-bg-module-platform);border-radius:12px;flex-direction:column;gap:14px;padding:14px 16px;display:flex}.zGbnIq_editorHeader{align-items:baseline;gap:8px;display:flex}.zGbnIq_editorTitle{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:500;line-height:22px}.zGbnIq_editorRoute{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}.zGbnIq_field{flex-direction:column;gap:6px;display:flex}.zGbnIq_fieldLabel{color:var(--dsw-alias-label-secondary);align-items:center;gap:10px;font-size:12px;font-weight:500;line-height:18px;display:inline-flex}.zGbnIq_linkButton{box-sizing:border-box;height:28px;color:var(--dsw-alias-label-tertiary);font:inherit;cursor:pointer;background:0 0;border:none;border-radius:14px;align-items:center;padding:0 10px;font-size:12px;line-height:18px;display:inline-flex}.zGbnIq_linkButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-secondary)}.zGbnIq_advancedHint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}.zGbnIq_editorActions{justify-content:flex-end;gap:8px;display:flex}.zGbnIq_addBlock{flex-direction:column;gap:12px;display:flex}.zGbnIq_addActions{flex-wrap:wrap;gap:10px;display:flex}.zGbnIq_addButton{border:1px dashed var(--dsw-alias-border-l3);border-radius:16px;flex:1 1 0;gap:6px;min-width:180px;height:44px}.zGbnIq_addCard,.zGbnIq_setupCard{background:var(--dsw-alias-bg-module-platform);border-radius:12px;flex-direction:column;gap:14px;padding:14px 16px;list-style:none;display:flex}.zGbnIq_addCard .zGbnIq_editor,.zGbnIq_setupCard .zGbnIq_editor{background:0 0;padding:0}.zGbnIq_customized{border-top:.5px solid var(--dsw-alias-border-l2);padding-top:10px}.zGbnIq_customizedSummary{cursor:pointer;width:fit-content;color:var(--dsw-alias-label-secondary);border-radius:6px;align-items:center;gap:6px;margin-left:-4px;padding:2px 4px;font-size:12px;font-weight:500;line-height:18px;list-style:none;display:flex}.zGbnIq_customizedSummary::-webkit-details-marker{display:none}.zGbnIq_customizedSummary:before{content:\"\";border-bottom:1.5px solid;border-right:1.5px solid;width:5px;height:5px;transition:transform .12s;transform:rotate(-45deg)translate(-1px,-1px)}.zGbnIq_customized[open]>.zGbnIq_customizedSummary:before{transform:rotate(45deg)translate(-1px,-1px)}.zGbnIq_customizedSummary:hover{color:var(--dsw-alias-label-primary)}.zGbnIq_customizedBody{flex-direction:column;gap:12px;padding-top:12px;display:flex}.zGbnIq_modelCatalog{border-top:.5px solid var(--dsw-alias-border-l2);flex-direction:column;gap:10px;padding-top:12px;display:flex}.zGbnIq_modelCatalogHeading{flex-direction:column;gap:2px;display:flex}.zGbnIq_modelCatalogTitle{color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:500;line-height:18px}.zGbnIq_modelCatalogMeta,.zGbnIq_modelEmpty{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}.zGbnIq_modelList{flex-direction:column;gap:8px;display:flex}.zGbnIq_modelListHead{justify-content:space-between;align-items:flex-start;gap:12px;display:flex}.zGbnIq_modelEntry{border:.5px solid var(--dsw-alias-border-l4);border-radius:10px;padding:6px}.zGbnIq_modelRow{grid-template-columns:minmax(0,1.4fr) minmax(0,1fr) auto auto;align-items:center;gap:6px;display:grid}.zGbnIq_iconButton{box-sizing:border-box;width:28px;height:28px;color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:none;border-radius:6px;justify-content:center;align-items:center;display:inline-flex}.zGbnIq_iconButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.zGbnIq_iconButton:disabled{cursor:default;opacity:.4}.zGbnIq_iconButtonDanger:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger);color:var(--dsw-alias-state-error-primary)}.zGbnIq_modelAdvanced{grid-template-columns:repeat(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}";
58
+ const css$3 = ".zGbnIq_section{max-width:720px;color:var(--dsw-alias-label-primary);flex-direction:column;gap:12px;display:flex}.zGbnIq_title{color:var(--dsw-alias-label-primary);margin:0;font-size:16px;font-weight:500;line-height:24px}.zGbnIq_intro{color:var(--dsw-alias-label-tertiary);margin:0;font-size:14px;line-height:22px}.zGbnIq_notice{color:var(--dsw-alias-state-warn-label);margin:0;font-size:12px;line-height:18px}.zGbnIq_savedNotice{color:var(--dsw-alias-state-success-primary);margin:0;font-size:12px;line-height:18px}.zGbnIq_rows{flex-direction:column;gap:8px;margin:12px 0 0;padding:0;list-style:none;display:flex}.zGbnIq_rowCard{border:.5px solid var(--dsw-alias-border-l4);border-radius:16px;flex-direction:column;gap:12px;padding:12px 14px;display:flex}.zGbnIq_rowHead{align-items:center;gap:10px;display:flex}.zGbnIq_rowIdentity{align-items:center;gap:6px;min-width:0;display:inline-flex}.zGbnIq_rowName{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:500;line-height:22px}.zGbnIq_rowTag{border:.5px solid var(--dsw-alias-border-l3);color:var(--dsw-alias-label-secondary);border-radius:4px;flex:none;padding:1px 6px;font-size:11px;line-height:16px}.zGbnIq_credentialDot{box-sizing:border-box;corner-shape:round;border-radius:50%;flex:none;width:8px;height:8px;display:inline-block}.zGbnIq_credentialDotConfigured{background:var(--dsw-alias-state-success-primary)}.zGbnIq_credentialDotMissing{background:var(--dsw-alias-state-error-primary)}.zGbnIq_rowActions{align-items:center;gap:4px;margin-left:auto;display:inline-flex}.zGbnIq_primaryButton,.zGbnIq_secondaryButton,.zGbnIq_addButton{box-sizing:border-box;height:36px;font:inherit;cursor:pointer;border:none;border-radius:18px;justify-content:center;align-items:center;gap:4px;padding:0 14px;font-size:14px;line-height:22px;display:inline-flex}.zGbnIq_primaryButton{background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-foreground)}.zGbnIq_primaryButton:hover:not(:disabled){background:var(--dsw-alias-button-primary-hover)}.zGbnIq_secondaryButton,.zGbnIq_addButton{border:.5px solid var(--dsw-alias-border-l3);color:var(--dsw-alias-label-primary);background:0 0}.zGbnIq_secondaryButton:hover:not(:disabled),.zGbnIq_addButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.zGbnIq_secondaryButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-solid)}.zGbnIq_dangerButton{box-sizing:border-box;height:36px;color:var(--dsw-alias-state-error-primary);font:inherit;cursor:pointer;background:0 0;border:none;border-radius:18px;justify-content:center;align-items:center;padding:0 14px;font-size:14px;line-height:22px;display:inline-flex}.zGbnIq_dangerButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger)}.zGbnIq_rowActions .zGbnIq_secondaryButton,.zGbnIq_rowActions .zGbnIq_dangerButton{border-radius:14px;height:28px;padding:0 10px;font-size:12px;line-height:18px}.zGbnIq_primaryButton:disabled,.zGbnIq_secondaryButton:disabled,.zGbnIq_dangerButton:disabled,.zGbnIq_addButton:disabled,.zGbnIq_linkButton:disabled,.zGbnIq_addModelButton:disabled{opacity:.4;cursor:default}.zGbnIq_primaryButton:focus-visible,.zGbnIq_secondaryButton:focus-visible,.zGbnIq_dangerButton:focus-visible,.zGbnIq_addButton:focus-visible,.zGbnIq_linkButton:focus-visible,.zGbnIq_addModelButton:focus-visible,.zGbnIq_iconButton:focus-visible,.zGbnIq_customizedSummary:focus-visible{box-shadow:0 0 0 2px var(--dsw-alias-border-l3);outline:none}.zGbnIq_editor{background:var(--dsw-alias-bg-module-platform);border-radius:12px;flex-direction:column;gap:14px;padding:14px 16px;display:flex}.zGbnIq_editorHeader{align-items:baseline;gap:8px;display:flex}.zGbnIq_editorTitle{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:500;line-height:22px}.zGbnIq_editorRoute{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}.zGbnIq_field{flex-direction:column;gap:6px;display:flex}.zGbnIq_fieldLabel{color:var(--dsw-alias-label-secondary);align-items:center;gap:10px;font-size:12px;font-weight:500;line-height:18px;display:inline-flex}.zGbnIq_linkButton{box-sizing:border-box;height:28px;color:var(--dsw-alias-label-tertiary);font:inherit;cursor:pointer;background:0 0;border:none;border-radius:14px;align-items:center;padding:0 10px;font-size:12px;line-height:18px;display:inline-flex}.zGbnIq_linkButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-secondary)}.zGbnIq_advancedHint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}.zGbnIq_editorActions{justify-content:flex-end;gap:8px;display:flex}.zGbnIq_addBlock{flex-direction:column;gap:12px;display:flex}.zGbnIq_addActions{display:flex}.zGbnIq_addButton{border:1px dashed var(--dsw-alias-border-l3);border-radius:16px;flex:1 1 0;gap:6px;min-width:180px;height:44px}.zGbnIq_addModes{flex-direction:column;align-items:flex-start;gap:8px;display:flex}.zGbnIq_addPanel{flex-direction:column;gap:14px;display:flex}.zGbnIq_addPanel[hidden]{display:none}.zGbnIq_addCard,.zGbnIq_setupCard{background:var(--dsw-alias-bg-module-platform);border-radius:12px;flex-direction:column;gap:14px;padding:14px 16px;list-style:none;display:flex}.zGbnIq_addCard .zGbnIq_editor,.zGbnIq_setupCard .zGbnIq_editor{background:0 0;padding:0}.zGbnIq_customized{border-top:.5px solid var(--dsw-alias-border-l2);padding-top:10px}.zGbnIq_customizedSummary{cursor:pointer;width:fit-content;color:var(--dsw-alias-label-secondary);border-radius:6px;align-items:center;gap:6px;margin-left:-4px;padding:2px 4px;font-size:12px;font-weight:500;line-height:18px;list-style:none;display:flex}.zGbnIq_customizedSummary::-webkit-details-marker{display:none}.zGbnIq_customizedSummary:before{content:\"\";border-bottom:1.5px solid;border-right:1.5px solid;width:5px;height:5px;transition:transform .12s;transform:rotate(-45deg)translate(-1px,-1px)}.zGbnIq_customized[open]>.zGbnIq_customizedSummary:before{transform:rotate(45deg)translate(-1px,-1px)}.zGbnIq_customizedSummary:hover{color:var(--dsw-alias-label-primary)}.zGbnIq_customizedBody{flex-direction:column;gap:12px;padding-top:12px;display:flex}.zGbnIq_modelCatalog{border-top:.5px solid var(--dsw-alias-border-l2);flex-direction:column;gap:10px;padding-top:12px;display:flex}.zGbnIq_modelCatalogHeading{flex-direction:column;gap:2px;display:flex}.zGbnIq_modelCatalogTitle{color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:500;line-height:18px}.zGbnIq_modelCatalogMeta,.zGbnIq_modelEmpty{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}.zGbnIq_modelList{flex-direction:column;gap:8px;display:flex}.zGbnIq_modelListHead{justify-content:space-between;align-items:flex-start;gap:12px;display:flex}.zGbnIq_modelEntry{border:.5px solid var(--dsw-alias-border-l4);border-radius:10px;padding:6px}.zGbnIq_modelRow{grid-template-columns:minmax(0,1.4fr) minmax(0,1fr) auto auto;align-items:center;gap:6px;display:grid}.zGbnIq_iconButton{box-sizing:border-box;width:28px;height:28px;color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:none;border-radius:6px;justify-content:center;align-items:center;display:inline-flex}.zGbnIq_iconButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.zGbnIq_iconButton:disabled{cursor:default;opacity:.4}.zGbnIq_iconButtonDanger:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger);color:var(--dsw-alias-state-error-primary)}.zGbnIq_modelAdvanced{grid-template-columns:repeat(2,minmax(0,1fr));gap:8px;padding:8px 4px 2px;display:grid}.zGbnIq_modelField{flex-direction:column;gap:4px;min-width:0;display:flex}.zGbnIq_modelInputTypes{border:none;grid-column:1/-1;min-width:0;margin:0;padding:0}.zGbnIq_modelInputTypes legend{margin-bottom:4px;padding:0}.zGbnIq_modelInputChoices{flex-wrap:wrap;align-items:center;gap:16px;min-height:32px;display:flex}.zGbnIq_modelFieldLabel{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}.zGbnIq_modelEmpty{border:1px dashed var(--dsw-alias-border-l3);text-align:center;border-radius:8px;padding:12px}.zGbnIq_addModelButton{box-sizing:border-box;border:.5px solid var(--dsw-alias-border-l3);height:28px;color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;background:0 0;border-radius:14px;align-self:flex-start;align-items:center;gap:4px;padding:0 10px;font-size:12px;line-height:18px;display:inline-flex}.zGbnIq_addModelButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.zGbnIq_input{box-sizing:border-box;border:.5px solid var(--dsw-alias-border-l4);width:100%;height:32px;font:inherit;background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);border-radius:8px;padding:0 10px;font-size:14px;line-height:22px}select.zGbnIq_input{cursor:pointer;max-width:240px}.zGbnIq_input:focus{border-color:var(--dsw-alias-brand-primary);outline:none}.zGbnIq_input::placeholder{color:var(--dsw-alias-label-dimmed)}.zGbnIq_input:disabled{opacity:.6;cursor:default}.zGbnIq_selectInput{appearance:none;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12' fill='none'%3E%3Cpath d='M3 4.5L6 7.5L9 4.5' stroke='%2381858C' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\");background-position:right 12px center;background-repeat:no-repeat;background-size:12px 12px;padding-right:32px}.zGbnIq_error{color:var(--dsw-alias-state-error-primary);margin:0;font-size:12px;line-height:18px}.zGbnIq_deleteDialog{width:min(480px,100%)}.zGbnIq_deleteConfirm:not(:disabled){border-color:var(--dsw-alias-state-error-primary);color:var(--dsw-alias-state-error-primary)}.zGbnIq_deleteConfirm:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger)}.zGbnIq_hiddenLabel{clip:rect(0 0 0 0);white-space:nowrap;width:1px;height:1px;position:absolute;overflow:hidden}@media (prefers-reduced-motion:reduce){.zGbnIq_customizedSummary:before,.zGbnIq_switchThumb{transition:none}}.zGbnIq_fetchDialog{--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);max-width:520px}.zGbnIq_candidateToolbar{align-items:center;gap:8px;margin-bottom:6px;display:flex}.zGbnIq_candidateSearch{flex:240px;min-width:0}.zGbnIq_candidateList{flex-direction:column;gap:2px;max-height:320px;margin:0;padding:0;list-style:none;display:flex;overflow-y:auto}.zGbnIq_candidate{border-radius:6px}.zGbnIq_candidateLabel{cursor:pointer;align-items:center;gap:8px;padding:6px 8px;display:flex}.zGbnIq_candidateId{font-family:var(--ds-font-family-code);overflow-wrap:anywhere;flex:auto;font-size:13px}.zGbnIq_candidateEmpty{color:var(--dsw-alias-label-secondary);text-align:center;margin:24px 0;font-size:13px;line-height:20px}";
59
59
  const tagId$3 = "@deepseek-ai/dsh-client-ui-settings-models/ModelsSection.module.css";
60
60
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$3) + "]") === null) {
61
61
  const tag = document.createElement("style");
@@ -70,6 +70,8 @@ window.__ModuleLoader__.load({
70
70
  "addButton": "zGbnIq_addButton",
71
71
  "addCard": "zGbnIq_addCard",
72
72
  "addModelButton": "zGbnIq_addModelButton",
73
+ "addModes": "zGbnIq_addModes",
74
+ "addPanel": "zGbnIq_addPanel",
73
75
  "advancedHint": "zGbnIq_advancedHint",
74
76
  "candidate": "zGbnIq_candidate",
75
77
  "candidateEmpty": "zGbnIq_candidateEmpty",
@@ -231,7 +233,7 @@ window.__ModuleLoader__.load({
231
233
  "aria-expanded": props.expanded,
232
234
  title: t("modelAdvanced"),
233
235
  onClick: props.onToggle,
234
- children: props.expanded ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, {}) : (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronRightOutline14, {})
236
+ children: props.expanded ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutlineRegular, {}) : (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronRightOutlineRegular, {})
235
237
  }),
236
238
  (0, react_jsx_runtime.jsx)("button", {
237
239
  type: "button",
@@ -240,7 +242,7 @@ window.__ModuleLoader__.load({
240
242
  title: t("removeModel"),
241
243
  disabled,
242
244
  onClick: props.onRemove,
243
- children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutline16, { size: 14 })
245
+ children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutlineRegular, { size: 14 })
244
246
  })
245
247
  ]
246
248
  }), props.expanded ? (0, react_jsx_runtime.jsxs)("div", {
@@ -511,7 +513,7 @@ window.__ModuleLoader__.load({
511
513
  onClick: () => {
512
514
  props.onChange([...props.models.map((model) => ({ ...model })), { id: "" }]);
513
515
  },
514
- children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutline16, { size: 14 }), props.t("addModel")]
516
+ children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutlineRegular, { size: 14 }), props.t("addModel")]
515
517
  })
516
518
  ]
517
519
  });
@@ -584,9 +586,12 @@ window.__ModuleLoader__.load({
584
586
  * @returns the model-list editor.
585
587
  */
586
588
  function ModelListEditor(props) {
587
- const { models, onChange, probe, operations, t, disabled } = props;
589
+ const { models, onChange, probe, operations, t, disabled, onBusyChange } = props;
588
590
  const { catalogProvider } = props;
589
591
  const [busy, setBusy] = (0, react.useState)(false);
592
+ (0, react.useEffect)(() => {
593
+ onBusyChange(busy);
594
+ }, [busy, onBusyChange]);
590
595
  const [failure, setFailure] = (0, react.useState)(void 0);
591
596
  const [inheritedCatalog, setInheritedCatalog] = (0, react.useState)(void 0);
592
597
  (0, react.useEffect)(() => {
@@ -810,7 +815,7 @@ window.__ModuleLoader__.load({
810
815
  onClick: () => {
811
816
  onChange([...models, { id: "" }]);
812
817
  },
813
- children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutline16, { size: 14 }), t("addModel")]
818
+ children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutlineRegular, { size: 14 }), t("addModel")]
814
819
  }),
815
820
  failure !== void 0 ? (0, react_jsx_runtime.jsx)("p", {
816
821
  className: ModelsSection_module_css_default["error"],
@@ -1120,18 +1125,46 @@ window.__ModuleLoader__.load({
1120
1125
  return { kind: "credential-missing" };
1121
1126
  }
1122
1127
  //#endregion
1128
+ //#region lib/types/client/protocol-label.js
1129
+ /**
1130
+ * Product names for the wire protocols a pi-ai route may speak. The pickers
1131
+ * show these instead of the schema identifiers (`openai-completions`), which
1132
+ * are what `settings.yaml` carries and what the option values stay.
1133
+ */
1134
+ /** The protocols this page names, keyed by their schema identifier. */
1135
+ const PROTOCOL_LABEL_KEYS = {
1136
+ "openai-completions": "protocolOpenAiCompletions",
1137
+ "openai-responses": "protocolOpenAiResponses",
1138
+ "anthropic-messages": "protocolAnthropicMessages"
1139
+ };
1140
+ /**
1141
+ * The picker text for one protocol identifier.
1142
+ * @param t - section copy.
1143
+ * @param protocol - the schema identifier of the protocol.
1144
+ * @returns the product name this page knows the protocol by; a protocol the
1145
+ * adapter adds before this page names it shows its identifier, the spelling
1146
+ * `settings.yaml` needs anyway.
1147
+ */
1148
+ function protocolLabel(t, protocol) {
1149
+ const key = PROTOCOL_LABEL_KEYS[protocol];
1150
+ return key === void 0 ? protocol : t(key);
1151
+ }
1152
+ //#endregion
1123
1153
  //#region lib/types/client/CustomProviderCard.js
1124
1154
  /**
1125
1155
  * The card that declares a provider pi-ai does not ship — an OpenAI-compatible
1126
1156
  * gateway, a self-hosted server, or a provider newer than the installed
1127
1157
  * catalog.
1128
1158
  *
1129
- * This is a create, not an edit, which is why it is its own card rather than
1159
+ * This is a create, not an edit, which is why it is its own form rather than
1130
1160
  * the provider editor with extra fields: the route id is being *chosen* here,
1131
- * and the settings address does not exist until it is. One `settings.mutate`
1132
- * sets the whole profile at `providers.<route>`; the key travels separately
1133
- * through `credentials/set` under the reference the profile records, exactly as
1134
- * an existing provider's key does.
1161
+ * and the settings address does not exist until it is. It renders as the
1162
+ * custom-API panel of the section's add card; the card's mode switch names it
1163
+ * when both modes are offered, and with the custom mode alone the card shows
1164
+ * this form directly. One `settings.mutate` sets the whole profile at
1165
+ * `providers.<route>`; the key travels separately through `credentials/set`
1166
+ * under the reference the profile records, exactly as an existing provider's
1167
+ * key does.
1135
1168
  *
1136
1169
  * The three fields a hand-declared route cannot default — endpoint, protocol,
1137
1170
  * and at least one model — are required here rather than at load, so the
@@ -1168,7 +1201,7 @@ window.__ModuleLoader__.load({
1168
1201
  * @returns the creation card.
1169
1202
  */
1170
1203
  function CustomProviderCard(props) {
1171
- const { taken, protocols, operations, t } = props;
1204
+ const { taken, protocols, operations, t, onBusyChange } = props;
1172
1205
  const [openedAt] = (0, react.useState)(() => props.revision);
1173
1206
  const [route, setRoute] = (0, react.useState)("");
1174
1207
  const [displayName, setDisplayName] = (0, react.useState)("");
@@ -1177,6 +1210,14 @@ window.__ModuleLoader__.load({
1177
1210
  const [keyDraft, setKeyDraft] = (0, react.useState)("");
1178
1211
  const [models, setModels] = (0, react.useState)([]);
1179
1212
  const [busy, setBusy] = (0, react.useState)(false);
1213
+ const [listBusy, setListBusy] = (0, react.useState)(false);
1214
+ (0, react.useEffect)(() => {
1215
+ onBusyChange?.(busy || listBusy);
1216
+ }, [
1217
+ busy,
1218
+ listBusy,
1219
+ onBusyChange
1220
+ ]);
1180
1221
  const [failure, setFailure] = (0, react.useState)(void 0);
1181
1222
  /**
1182
1223
  * The profile write landed. Only the key write can still be outstanding, so
@@ -1238,13 +1279,6 @@ window.__ModuleLoader__.load({
1238
1279
  return (0, react_jsx_runtime.jsxs)("div", {
1239
1280
  className: ModelsSection_module_css_default["editor"],
1240
1281
  children: [
1241
- (0, react_jsx_runtime.jsx)("div", {
1242
- className: ModelsSection_module_css_default["editorHeader"],
1243
- children: (0, react_jsx_runtime.jsx)("span", {
1244
- className: ModelsSection_module_css_default["editorTitle"],
1245
- children: t("customTitle")
1246
- })
1247
- }),
1248
1282
  (0, react_jsx_runtime.jsxs)("div", {
1249
1283
  className: ModelsSection_module_css_default["field"],
1250
1284
  children: [(0, react_jsx_runtime.jsx)("span", {
@@ -1295,7 +1329,7 @@ window.__ModuleLoader__.load({
1295
1329
  className: ModelsSection_module_css_default["input"],
1296
1330
  type: "text",
1297
1331
  value: baseURL,
1298
- placeholder: t("customBaseUrlPlaceholder"),
1332
+ placeholder: t(protocol === "anthropic-messages" ? "customAnthropicBaseUrlPlaceholder" : "customBaseUrlPlaceholder"),
1299
1333
  "aria-label": t("baseUrl"),
1300
1334
  "aria-invalid": baseUrlInvalid,
1301
1335
  disabled: profileDisabled,
@@ -1323,7 +1357,7 @@ window.__ModuleLoader__.load({
1323
1357
  },
1324
1358
  children: protocols.map((choice) => (0, react_jsx_runtime.jsx)("option", {
1325
1359
  value: choice,
1326
- children: choice
1360
+ children: protocolLabel(t, choice)
1327
1361
  }, choice))
1328
1362
  })]
1329
1363
  }),
@@ -1364,7 +1398,8 @@ window.__ModuleLoader__.load({
1364
1398
  probeBlocked: baseUrlInvalid ? "customBaseUrlInvalid" : keyFailure === "keyBlank" ? "keyBlankNew" : keyFailure,
1365
1399
  operations,
1366
1400
  t,
1367
- disabled: profileDisabled
1401
+ disabled: profileDisabled,
1402
+ onBusyChange: setListBusy
1368
1403
  }),
1369
1404
  failure !== void 0 ? (0, react_jsx_runtime.jsx)("p", {
1370
1405
  className: ModelsSection_module_css_default["error"],
@@ -1408,9 +1443,9 @@ window.__ModuleLoader__.load({
1408
1443
  * Reasoning effort is deliberately absent: it is a per-MODEL capability, and
1409
1444
  * the models under one provider disagree about it, so a provider-scoped
1410
1445
  * control can only be set to a value some of them reject. The composer's
1411
- * model picker offers each model its own levels; `settings.yaml` keeps the
1446
+ * model picker offers each model its own levels; `cordis.patch.yml` keeps the
1412
1447
  * profile field for a deployment that knows its route. Everything else stays
1413
- * owned by `settings.yaml`. Profile edits land as minimal `settings.mutate`
1448
+ * owned by `cordis.patch.yml`. Profile edits land as minimal `settings.mutate`
1414
1449
  * path ops against the stored section — the card names only the fields it can
1415
1450
  * see instead of rebuilding the whole subtree from a partial descriptor.
1416
1451
  */
@@ -1470,6 +1505,15 @@ window.__ModuleLoader__.load({
1470
1505
  const [keyDraft, setKeyDraft] = (0, react.useState)("");
1471
1506
  const [keyState, setKeyState] = (0, react.useState)(void 0);
1472
1507
  const [busy, setBusy] = (0, react.useState)(false);
1508
+ const [listBusy, setListBusy] = (0, react.useState)(false);
1509
+ const { onBusyChange } = props;
1510
+ (0, react.useEffect)(() => {
1511
+ onBusyChange?.(busy || listBusy);
1512
+ }, [
1513
+ busy,
1514
+ listBusy,
1515
+ onBusyChange
1516
+ ]);
1473
1517
  const [failure, setFailure] = (0, react.useState)(void 0);
1474
1518
  const [committedOriginal, setCommittedOriginal] = (0, react.useState)(() => schema.getPath(namespace.user, settingsPath));
1475
1519
  const [expectedRevision, setExpectedRevision] = (0, react.useState)(() => namespace.revision);
@@ -1681,7 +1725,7 @@ window.__ModuleLoader__.load({
1681
1725
  className: ModelsSection_module_css_default["input"],
1682
1726
  type: "text",
1683
1727
  value: stringAt(draft, "baseURL") ?? "",
1684
- placeholder: family === "deepseek" ? t(stringAt(fallback, "protocol") === "messages" ? "deepSeekMessagesBaseUrl" : "deepSeekChatBaseUrl") : stringAt(fallback, "baseURL") ?? t("baseUrlDefault"),
1728
+ placeholder: family === "deepseek" ? t("deepSeekBaseUrl") : stringAt(fallback, "baseURL") ?? t("baseUrlDefault"),
1685
1729
  "aria-describedby": family === "deepseek" ? `${props.provider}-endpoint-hint` : void 0,
1686
1730
  "aria-label": t("baseUrl"),
1687
1731
  disabled,
@@ -1714,7 +1758,7 @@ window.__ModuleLoader__.load({
1714
1758
  children: t("customApiUnset")
1715
1759
  }) : null, protocols.map((choice) => (0, react_jsx_runtime.jsx)("option", {
1716
1760
  value: choice,
1717
- children: choice
1761
+ children: protocolLabel(t, choice)
1718
1762
  }, choice))]
1719
1763
  })]
1720
1764
  }) : null,
@@ -1728,7 +1772,8 @@ window.__ModuleLoader__.load({
1728
1772
  defaultInput: Array.isArray(defaultInput) ? defaultInput : void 0,
1729
1773
  probe,
1730
1774
  probeBlocked: keyFailure,
1731
- operations
1775
+ operations,
1776
+ onBusyChange: setListBusy
1732
1777
  })
1733
1778
  ]
1734
1779
  })]
@@ -1785,11 +1830,19 @@ window.__ModuleLoader__.load({
1785
1830
  * solid configured or missing dots. A whole-section provider without a
1786
1831
  * configured key renders as its open setup card instead of a row, but only in
1787
1832
  * the first-run posture — no provider on the page can serve requests yet — and
1788
- * only until the user closes that card; the add flow is a card carrying the
1789
- * dormant-provider select. Each card kind owns its own open state, so closing
1790
- * one never discards a draft in another. Every mutation writes through the
1791
- * wire, while a provider removal first requires confirmation; the page
1792
- * re-renders from pushed invalidations or the post-apply reload.
1833
+ * only until the user closes that card. The add flow is one card behind one
1834
+ * button: a mode switch chooses between adopting a dormant directory provider
1835
+ * (the catalog select over the provider editor) and declaring a custom model
1836
+ * API (the create form). A panel mounts the first time its mode is shown and
1837
+ * stays mounted, hidden, while the card is open and its mode stays offered,
1838
+ * so switching modes discards neither draft and an unvisited mode costs
1839
+ * nothing; the switch holds still while either panel has a write or an
1840
+ * endpoint interrogation in flight, since a switch underneath one would
1841
+ * orphan the answer. Each card kind owns its own open state, so closing one
1842
+ * never discards a draft in another. Every
1843
+ * mutation writes through the wire, while a provider removal first requires
1844
+ * confirmation; the page re-renders from pushed invalidations or the
1845
+ * post-apply reload.
1793
1846
  */
1794
1847
  /** Render an editor for either the setup posture or an expanded provider row. */
1795
1848
  function renderProviderEditor({ target, ...props }) {
@@ -1891,30 +1944,48 @@ window.__ModuleLoader__.load({
1891
1944
  const { controller, operations, schema, t } = injected;
1892
1945
  const state = injected.useSnapshot((snapshot) => snapshot);
1893
1946
  const [editing, setEditing] = (0, react.useState)(void 0);
1894
- const [adding, setAdding] = (0, react.useState)(false);
1947
+ const [addOpen, setAddOpen] = (0, react.useState)(false);
1948
+ const [addMode, setAddMode] = (0, react.useState)("catalog");
1949
+ /** The modes shown since the add card opened; each keeps its panel mounted. */
1950
+ const [visited, setVisited] = (0, react.useState)(() => /* @__PURE__ */ new Set());
1951
+ /** Whether each add panel has a write or an interrogation in flight. */
1952
+ const [catalogBusy, setCatalogBusy] = (0, react.useState)(false);
1953
+ const [customBusy, setCustomBusy] = (0, react.useState)(false);
1954
+ /** Base of the add card's tab and panel ids. */
1955
+ const addId = (0, react.useId)();
1895
1956
  const [deleteTarget, setDeleteTarget] = (0, react.useState)(void 0);
1896
1957
  const [deleting, setDeleting] = (0, react.useState)(false);
1897
1958
  const [deleteFailure, setDeleteFailure] = (0, react.useState)(void 0);
1898
1959
  const [savedTarget, setSavedTarget] = (0, react.useState)(void 0);
1899
- const [declaring, setDeclaring] = (0, react.useState)(false);
1900
1960
  const [dismissedSetup, setDismissedSetup] = (0, react.useState)(() => /* @__PURE__ */ new Set());
1901
1961
  const announceSaved = (target) => {
1902
1962
  controller.load().then(() => {
1903
1963
  setSavedTarget(target);
1904
1964
  });
1905
1965
  };
1906
- const closeEditor = (changed, target) => {
1966
+ /**
1967
+ * Close the add card whole. The catalog target is forgotten with it, since
1968
+ * `editing` doubles as the row editor's target once the card is closed and a
1969
+ * refresh could otherwise open the row of a provider the draft never saved.
1970
+ * The busy flags reset here because a panel that closes itself on success
1971
+ * unmounts before it can report idle.
1972
+ */
1973
+ const closeAdd = () => {
1907
1974
  setEditing(void 0);
1908
- setAdding(false);
1909
- setDeclaring(false);
1975
+ setAddOpen(false);
1976
+ setCatalogBusy(false);
1977
+ setCustomBusy(false);
1978
+ };
1979
+ const closeEditor = (changed, target) => {
1980
+ closeAdd();
1910
1981
  if (changed) announceSaved(target);
1911
1982
  };
1912
1983
  /**
1913
- * Close a setup card, which owns none of the state above: the row-editor,
1914
- * add, and declare cards each own one of those, so clearing them here would
1915
- * discard a draft the user opened beside this card. Dismissal is this card's
1916
- * own — the provider falls back to an ordinary row for the rest of the
1917
- * session, and reopens through Edit.
1984
+ * Close a setup card, which owns none of the state above: the row-editor
1985
+ * and add cards each own one of those, so clearing them here would discard
1986
+ * a draft the user opened beside this card. Dismissal is this card's own —
1987
+ * the provider falls back to an ordinary row for the rest of the session,
1988
+ * and reopens through Edit.
1918
1989
  */
1919
1990
  const closeSetup = (changed, target) => {
1920
1991
  setDismissedSetup((previous) => new Set([...previous, target.provider]));
@@ -1967,11 +2038,37 @@ window.__ModuleLoader__.load({
1967
2038
  const anyUsable = state.rows.some(providerUsable);
1968
2039
  const configured = state.rows.filter((row) => row.configured);
1969
2040
  const configurable = state.rows.filter((row) => state.namespaces.has(row.entry.settingsNs));
1970
- const addable = configurable.filter((row) => !row.configured);
1971
- const addTarget = adding ? editing : void 0;
1972
- const addNamespace = addTarget === void 0 ? void 0 : state.namespaces.get(addTarget.settingsNs);
1973
- const addRow = addTarget === void 0 ? void 0 : state.rows.find((row) => row.entry.provider === addTarget.provider);
1974
- const protocols = protocolChoices(state.namespaces.get("llm-pi-ai"), schema);
2041
+ const addable = state.rows.flatMap((row) => {
2042
+ const namespace = state.namespaces.get(row.entry.settingsNs);
2043
+ return namespace === void 0 || row.configured ? [] : [{
2044
+ row,
2045
+ namespace
2046
+ }];
2047
+ });
2048
+ const piAi = state.namespaces.get("llm-pi-ai");
2049
+ const protocols = protocolChoices(piAi, schema);
2050
+ const catalogOffered = configurable.length > 0;
2051
+ const catalogEnabled = addable.length > 0;
2052
+ const customOffered = piAi !== void 0;
2053
+ const customEnabled = protocols.length > 0;
2054
+ const bothOffered = catalogOffered && customOffered;
2055
+ const mode = bothOffered ? addMode : customOffered ? "custom" : "catalog";
2056
+ const mounted = (candidate) => mode === candidate || visited.has(candidate);
2057
+ const switchLocked = catalogBusy || customBusy;
2058
+ const draft = (() => {
2059
+ if (!addOpen || !catalogOffered) return void 0;
2060
+ const kept = editing === void 0 ? void 0 : state.namespaces.get(editing.settingsNs);
2061
+ if (editing !== void 0 && kept !== void 0) return {
2062
+ target: editing,
2063
+ namespace: kept
2064
+ };
2065
+ const first = addable[0];
2066
+ return first === void 0 ? void 0 : {
2067
+ target: targetOf(first.row),
2068
+ namespace: first.namespace
2069
+ };
2070
+ })();
2071
+ const addRow = draft === void 0 ? void 0 : state.rows.find((row) => row.entry.provider === draft.target.provider);
1975
2072
  return (0, react_jsx_runtime.jsxs)("div", {
1976
2073
  className: ModelsSection_module_css_default["section"],
1977
2074
  children: [
@@ -2027,7 +2124,7 @@ window.__ModuleLoader__.load({
2027
2124
  }, { entryKey: row.entry.settingsNs })
2028
2125
  ]
2029
2126
  }, row.entry.provider);
2030
- const open = !adding && editing?.provider === row.entry.provider;
2127
+ const open = !addOpen && editing?.provider === row.entry.provider;
2031
2128
  const credentialConfigured = row.credential?.configured === true;
2032
2129
  const credentialMissing = !credentialConfigured && row.apiKeyEnv !== void 0 && row.credential?.configured === false;
2033
2130
  return (0, react_jsx_runtime.jsxs)("li", {
@@ -2066,8 +2163,7 @@ window.__ModuleLoader__.load({
2066
2163
  "aria-label": providerCopy(t("editProvider"), target),
2067
2164
  onClick: () => {
2068
2165
  setSavedTarget(void 0);
2069
- setDeclaring(false);
2070
- setAdding(false);
2166
+ setAddOpen(false);
2071
2167
  setEditing(open ? void 0 : target);
2072
2168
  },
2073
2169
  children: t("edit")
@@ -2108,94 +2204,136 @@ window.__ModuleLoader__.load({
2108
2204
  }),
2109
2205
  (0, react_jsx_runtime.jsx)("div", {
2110
2206
  className: ModelsSection_module_css_default["addBlock"],
2111
- children: addTarget !== void 0 && addNamespace !== void 0 ? (0, react_jsx_runtime.jsxs)("div", {
2207
+ children: addOpen ? (0, react_jsx_runtime.jsxs)("div", {
2112
2208
  className: ModelsSection_module_css_default["addCard"],
2113
2209
  children: [
2114
2210
  (0, react_jsx_runtime.jsxs)("div", {
2115
- className: ModelsSection_module_css_default["field"],
2116
- children: [(0, react_jsx_runtime.jsx)("span", {
2117
- className: ModelsSection_module_css_default["fieldLabel"],
2118
- children: t("provider")
2119
- }), (0, react_jsx_runtime.jsx)("select", {
2120
- className: `${ModelsSection_module_css_default["input"]} ${ModelsSection_module_css_default["selectInput"]}`,
2121
- value: addTarget.provider,
2122
- "aria-label": t("provider"),
2123
- onChange: (event) => {
2124
- const row = addable.find((candidate) => candidate.entry.provider === event.target.value);
2125
- /* v8 ignore next -- the select only lists addable rows */
2126
- if (row === void 0) return;
2127
- setEditing(targetOf(row));
2128
- },
2129
- children: addable.map((row) => (0, react_jsx_runtime.jsx)("option", {
2130
- value: row.entry.provider,
2131
- children: row.entry.displayName
2132
- }, row.entry.provider))
2211
+ className: ModelsSection_module_css_default["addModes"],
2212
+ children: [bothOffered ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.SegmentedControl, {
2213
+ id: addId,
2214
+ label: t("addMode"),
2215
+ value: mode,
2216
+ disabled: switchLocked,
2217
+ options: [{
2218
+ value: "catalog",
2219
+ label: t("addCatalog"),
2220
+ disabled: !catalogEnabled,
2221
+ ...catalogEnabled ? {} : { title: t("addCatalogExhausted") }
2222
+ }, {
2223
+ value: "custom",
2224
+ label: t("addCustom"),
2225
+ disabled: !customEnabled,
2226
+ ...customEnabled ? {} : { title: t("addCustomUnavailable") }
2227
+ }],
2228
+ onChange: (next) => {
2229
+ setAddMode(next);
2230
+ setVisited((previous) => new Set([...previous, next]));
2231
+ }
2232
+ }) : (0, react_jsx_runtime.jsx)("div", {
2233
+ className: ModelsSection_module_css_default["editorHeader"],
2234
+ children: (0, react_jsx_runtime.jsx)("span", {
2235
+ className: ModelsSection_module_css_default["editorTitle"],
2236
+ children: t(mode === "catalog" ? "addCatalog" : "addCustom")
2237
+ })
2238
+ }), (0, react_jsx_runtime.jsx)("p", {
2239
+ className: ModelsSection_module_css_default["advancedHint"],
2240
+ children: t(mode === "catalog" ? "addCatalogHint" : "addCustomHint")
2133
2241
  })]
2134
2242
  }),
2135
- (0, react_jsx_runtime.jsx)(ProviderEditor, {
2136
- provider: addTarget.provider,
2137
- displayName: addTarget.displayName,
2138
- hideTitle: true,
2139
- namespace: addNamespace,
2140
- schema,
2141
- settingsPath: addTarget.settingsPath,
2142
- operations,
2143
- t,
2144
- readOnly: !state.writable,
2145
- onClose: (changed) => {
2146
- closeEditor(changed, addTarget);
2147
- }
2148
- }, addTarget.provider),
2149
- addRow === void 0 ? null : renderSlot("settings.models.provider-card", {
2150
- provider: addRow.entry,
2151
- configured: addRow.configured,
2152
- keyConfigured: keyConfiguredOf(addRow)
2153
- }, { entryKey: addRow.entry.settingsNs })
2243
+ mounted("catalog") && draft !== void 0 ? (0, react_jsx_runtime.jsxs)("div", {
2244
+ id: `${addId}-catalog-panel`,
2245
+ ...bothOffered ? {
2246
+ role: "tabpanel",
2247
+ "aria-labelledby": `${addId}-catalog`
2248
+ } : {},
2249
+ hidden: mode !== "catalog",
2250
+ className: ModelsSection_module_css_default["addPanel"],
2251
+ children: [
2252
+ (0, react_jsx_runtime.jsxs)("div", {
2253
+ className: ModelsSection_module_css_default["field"],
2254
+ children: [(0, react_jsx_runtime.jsx)("span", {
2255
+ className: ModelsSection_module_css_default["fieldLabel"],
2256
+ children: t("provider")
2257
+ }), (0, react_jsx_runtime.jsx)("select", {
2258
+ className: `${ModelsSection_module_css_default["input"]} ${ModelsSection_module_css_default["selectInput"]}`,
2259
+ value: draft.target.provider,
2260
+ "aria-label": t("provider"),
2261
+ disabled: catalogBusy,
2262
+ onChange: (event) => {
2263
+ const picked = addable.find((candidate) => candidate.row.entry.provider === event.target.value);
2264
+ /* v8 ignore next -- the select only lists addable rows */
2265
+ if (picked === void 0) return;
2266
+ setEditing(targetOf(picked.row));
2267
+ },
2268
+ children: addable.map(({ row }) => (0, react_jsx_runtime.jsx)("option", {
2269
+ value: row.entry.provider,
2270
+ children: row.entry.displayName
2271
+ }, row.entry.provider))
2272
+ })]
2273
+ }),
2274
+ (0, react_jsx_runtime.jsx)(ProviderEditor, {
2275
+ provider: draft.target.provider,
2276
+ displayName: draft.target.displayName,
2277
+ hideTitle: true,
2278
+ namespace: draft.namespace,
2279
+ schema,
2280
+ settingsPath: draft.target.settingsPath,
2281
+ operations,
2282
+ t,
2283
+ readOnly: !state.writable,
2284
+ onClose: (changed) => {
2285
+ closeEditor(changed, draft.target);
2286
+ },
2287
+ onBusyChange: setCatalogBusy
2288
+ }, draft.target.provider),
2289
+ addRow === void 0 ? null : renderSlot("settings.models.provider-card", {
2290
+ provider: addRow.entry,
2291
+ configured: addRow.configured,
2292
+ keyConfigured: keyConfiguredOf(addRow)
2293
+ }, { entryKey: addRow.entry.settingsNs })
2294
+ ]
2295
+ }) : null,
2296
+ mounted("custom") && piAi !== void 0 ? (0, react_jsx_runtime.jsx)("div", {
2297
+ id: `${addId}-custom-panel`,
2298
+ ...bothOffered ? {
2299
+ role: "tabpanel",
2300
+ "aria-labelledby": `${addId}-custom`
2301
+ } : {},
2302
+ hidden: mode !== "custom",
2303
+ className: ModelsSection_module_css_default["addPanel"],
2304
+ children: (0, react_jsx_runtime.jsx)(CustomProviderCard, {
2305
+ taken: state.rows.map((row) => row.entry.provider),
2306
+ protocols,
2307
+ revision: piAi.revision,
2308
+ operations,
2309
+ t,
2310
+ readOnly: !state.writable,
2311
+ onClose: (changed) => {
2312
+ closeAdd();
2313
+ if (changed) controller.load();
2314
+ },
2315
+ onBusyChange: setCustomBusy
2316
+ })
2317
+ }) : null
2154
2318
  ]
2155
- }) : declaring ? (0, react_jsx_runtime.jsx)("div", {
2156
- className: ModelsSection_module_css_default["addCard"],
2157
- children: (0, react_jsx_runtime.jsx)(CustomProviderCard, {
2158
- taken: state.rows.map((row) => row.entry.provider),
2159
- protocols,
2160
- /* v8 ignore next -- the card only opens from a button disabled without this namespace */
2161
- revision: state.namespaces.get("llm-pi-ai")?.revision ?? 0,
2162
- operations,
2163
- t,
2164
- readOnly: !state.writable,
2165
- onClose: (changed) => {
2166
- setDeclaring(false);
2167
- if (changed) controller.load();
2168
- }
2169
- })
2170
- }) : (0, react_jsx_runtime.jsxs)("div", {
2319
+ }) : catalogOffered || customOffered ? (0, react_jsx_runtime.jsx)("div", {
2171
2320
  className: ModelsSection_module_css_default["addActions"],
2172
- children: [configurable.length > 0 && (0, react_jsx_runtime.jsxs)("button", {
2321
+ children: (0, react_jsx_runtime.jsxs)("button", {
2173
2322
  type: "button",
2174
2323
  className: ModelsSection_module_css_default["addButton"],
2175
- disabled: addable.length === 0 || !state.writable,
2324
+ disabled: !state.writable || !catalogEnabled && !customEnabled,
2176
2325
  onClick: () => {
2177
2326
  const first = addable[0];
2178
- /* v8 ignore next -- the button is disabled while nothing is addable */
2179
- if (first === void 0) return;
2327
+ const initial = catalogEnabled ? "catalog" : "custom";
2180
2328
  setSavedTarget(void 0);
2181
- setDeclaring(false);
2182
- setAdding(true);
2183
- setEditing(targetOf(first));
2329
+ setEditing(first === void 0 ? void 0 : targetOf(first.row));
2330
+ setAddMode(initial);
2331
+ setVisited(new Set([initial]));
2332
+ setAddOpen(true);
2184
2333
  },
2185
- children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutline16, { size: 14 }), t("add")]
2186
- }), state.namespaces.has("llm-pi-ai") && (0, react_jsx_runtime.jsxs)("button", {
2187
- type: "button",
2188
- className: ModelsSection_module_css_default["addButton"],
2189
- disabled: protocols.length === 0 || !state.writable,
2190
- onClick: () => {
2191
- setSavedTarget(void 0);
2192
- setAdding(false);
2193
- setEditing(void 0);
2194
- setDeclaring(true);
2195
- },
2196
- children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutline16, { size: 14 }), t("customAdd")]
2197
- })]
2198
- })
2334
+ children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutlineRegular, { size: 14 }), t("add")]
2335
+ })
2336
+ }) : null
2199
2337
  }),
2200
2338
  renderSlot("settings.models.footer", {}),
2201
2339
  (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
@@ -2228,7 +2366,7 @@ window.__ModuleLoader__.load({
2228
2366
  }
2229
2367
  //#endregion
2230
2368
  //#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-settings-models/src/client/OnboardingModal.module.css.mjs
2231
- const css$2 = ".jLrgrW_dialog{width:min(600px,100%);padding:0}.jLrgrW_content{box-sizing:border-box;flex-direction:column;max-height:calc(100vh - 48px);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}}";
2369
+ const css$2 = ".jLrgrW_dialog{width:min(600px,100%);max-height:100%;padding:0}.jLrgrW_content{box-sizing:border-box;flex-direction:column;min-height:0;padding:28px;display:flex;overflow-y:auto}.jLrgrW_title{color:var(--dsw-alias-label-primary);outline:none;margin:0;font-size:20px;font-weight:500;line-height:28px}.jLrgrW_body{margin-top:20px}@media (width<=560px){.jLrgrW_content{padding:24px}}";
2232
2370
  const tagId$2 = "@deepseek-ai/dsh-client-ui-settings-models/OnboardingModal.module.css";
2233
2371
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$2) + "]") === null) {
2234
2372
  const tag = document.createElement("style");
@@ -2323,20 +2461,34 @@ window.__ModuleLoader__.load({
2323
2461
  * @returns the onboarding modal or null when onboarding needs no intervention.
2324
2462
  */
2325
2463
  function DeepSeekOnboardingDialog(props) {
2326
- const { complete, controller, useModels, operations, schema, t } = props;
2464
+ const { complete, controller, useModels, operations, schema, t, renderSlot, automatic, explicit = false } = props;
2465
+ const [apiKey, setApiKey] = (0, react.useState)(explicit);
2327
2466
  const state = useModels((snapshot) => snapshot);
2328
2467
  const readiness = onboardingReadiness(state);
2329
2468
  (0, react.useEffect)(() => {
2330
- if (state.status === "idle") controller.load();
2331
- }, [controller, state.status]);
2469
+ if ((automatic || explicit) && state.status === "idle") controller.load();
2470
+ }, [
2471
+ controller,
2472
+ state.status,
2473
+ automatic,
2474
+ explicit
2475
+ ]);
2332
2476
  (0, react.useEffect)(() => {
2333
- if (readiness.kind === "adapter-absent" || readiness.kind === "provider-ready" || readiness.kind === "unavailable") complete();
2334
- }, [complete, readiness.kind]);
2477
+ if (!automatic && !explicit || readiness.kind === "adapter-absent" || !explicit && readiness.kind === "provider-ready" || readiness.kind === "unavailable") complete();
2478
+ }, [
2479
+ complete,
2480
+ readiness.kind,
2481
+ explicit,
2482
+ automatic
2483
+ ]);
2484
+ if (!automatic && !explicit) return null;
2335
2485
  switch (readiness.kind) {
2336
2486
  case "loading":
2337
2487
  case "adapter-absent":
2338
- case "provider-ready":
2339
2488
  case "unavailable": return null;
2489
+ case "provider-ready":
2490
+ if (!explicit) return null;
2491
+ break;
2340
2492
  case "credential-missing": break;
2341
2493
  /* v8 ignore next -- every current readiness variant is handled above */
2342
2494
  default: return assertNever$1(readiness);
@@ -2352,7 +2504,7 @@ window.__ModuleLoader__.load({
2352
2504
  }
2353
2505
  controller.load();
2354
2506
  };
2355
- return (0, react_jsx_runtime.jsxs)(OnboardingModal, {
2507
+ const editor = (0, react_jsx_runtime.jsxs)(OnboardingModal, {
2356
2508
  title: t("onboardingTitle"),
2357
2509
  children: [(0, react_jsx_runtime.jsx)("p", {
2358
2510
  className: DeepSeekOnboardingDialog_module_css_default.description,
@@ -2379,6 +2531,12 @@ window.__ModuleLoader__.load({
2379
2531
  })
2380
2532
  })]
2381
2533
  });
2534
+ return apiKey ? editor : renderSlot("settings.models.sign-in", {
2535
+ complete,
2536
+ useApiKey: () => {
2537
+ setApiKey(true);
2538
+ }
2539
+ }, { fallback: editor });
2382
2540
  }
2383
2541
  //#endregion
2384
2542
  //#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-settings-models/src/client/WelcomeNotice.module.css.mjs
@@ -2456,7 +2614,7 @@ window.__ModuleLoader__.load({
2456
2614
  //#endregion
2457
2615
  //#region lib/types/onboarding-copy.js
2458
2616
  /** Durable settings namespace for product-wide GUI onboarding facts. */
2459
- const WELCOME_NOTICE_SETTINGS_NAMESPACE = "ui-onboarding";
2617
+ const WELCOME_NOTICE_SETTINGS_NAMESPACE = "ui-settings-general";
2460
2618
  /** Field storing the last welcome notice version the user acknowledged. */
2461
2619
  const WELCOME_NOTICE_ACK_FIELD = "welcomeNoticeVersion";
2462
2620
  /**
@@ -2472,16 +2630,6 @@ window.__ModuleLoader__.load({
2472
2630
  * remote browser's memory-mode scope never answers and the acknowledgement
2473
2631
  * stays process-local here.
2474
2632
  */
2475
- /**
2476
- * Accept any object section verbatim; a malformed durable value reads as an
2477
- * empty section, so the notice treats it as unacknowledged instead of leaving
2478
- * the scope stuck on its previous value.
2479
- * @param section - the wire section value.
2480
- * @returns the section object, or an empty one for non-object values.
2481
- */
2482
- function decodeWelcomeSection(section) {
2483
- return typeof section === "object" && section !== null && !Array.isArray(section) ? section : {};
2484
- }
2485
2633
  /* v8 ignore next 3 -- closed-union default only defends future source widening */
2486
2634
  function assertNever(_value) {
2487
2635
  throw new Error("unexpected welcome settings status");
@@ -2680,7 +2828,14 @@ window.__ModuleLoader__.load({
2680
2828
  deleteDescriptionWithCredential: "Deleting {provider} removes its configuration and stored API key.",
2681
2829
  deleteConfirm: "Delete {provider}",
2682
2830
  deleting: "Deleting {provider}…",
2683
- add: "Add provider",
2831
+ add: "Add model provider",
2832
+ addMode: "How to add",
2833
+ addCatalog: "Third-party model provider",
2834
+ addCustom: "Custom model API",
2835
+ addCatalogHint: "Pick OpenAI, Anthropic, Kimi, or another provider from the built-in catalog and enter its API key.",
2836
+ addCustomHint: "Connect a relay, a self-hosted server, or any other OpenAI- or Anthropic-compatible endpoint by its base URL, protocol, and models.",
2837
+ addCatalogExhausted: "Every catalog provider is already configured.",
2838
+ addCustomUnavailable: "No API protocol is available to declare.",
2684
2839
  provider: "Provider",
2685
2840
  close: "Close",
2686
2841
  cancel: "Cancel",
@@ -2701,9 +2856,8 @@ window.__ModuleLoader__.load({
2701
2856
  customized: "Customized settings",
2702
2857
  baseUrl: "Base URL",
2703
2858
  baseUrlDefault: "Provider default",
2704
- deepSeekChatBaseUrl: "https://api.deepseek.com",
2705
- deepSeekMessagesBaseUrl: "https://api.deepseek.com/anthropic",
2706
- deepSeekEndpointHint: "Use an endpoint compatible with the configured connection.",
2859
+ deepSeekBaseUrl: "https://api.deepseek.com/anthropic",
2860
+ deepSeekEndpointHint: "Use an API endpoint compatible with Anthropic Messages.",
2707
2861
  models: "Models",
2708
2862
  modelsInherited: "Using the adapter defaults",
2709
2863
  modelsCustomized: "Customized model catalog",
@@ -2731,7 +2885,7 @@ window.__ModuleLoader__.load({
2731
2885
  modelNameInvalid: "Display name cannot be empty.",
2732
2886
  modelContextInvalid: "Context window must be a positive count, like 131072, 256K, or 1M.",
2733
2887
  modelMaxTokensInvalid: "Max output tokens must be a positive count, like 8192, 64K, or 1M.",
2734
- advancedHint: "Other fields live in settings.yaml; edit that section directly.",
2888
+ advancedHint: "Other fields live in cordis.patch.yml; edit that section directly.",
2735
2889
  modelCapacityInvalid: "A capacity must be a number, optionally suffixed K or M.",
2736
2890
  modelDuplicate: "Each model ID may appear once.",
2737
2891
  fetchModels: "Fetch available models",
@@ -2745,8 +2899,6 @@ window.__ModuleLoader__.load({
2745
2899
  fetchSelectAll: "Select all",
2746
2900
  fetchDeselectAll: "Deselect all",
2747
2901
  fetchAdopt: "Add selected",
2748
- customAdd: "Add a custom provider",
2749
- customTitle: "Custom provider",
2750
2902
  customTag: "Custom",
2751
2903
  customRoute: "Provider ID",
2752
2904
  customRouteHint: "Lowercase identifier, starting with a letter, that uniquely names this provider in requests and as its credential name.",
@@ -2755,10 +2907,14 @@ window.__ModuleLoader__.load({
2755
2907
  customDisplayName: "Display name",
2756
2908
  customApi: "API protocol",
2757
2909
  customApiUnset: "Not selected",
2910
+ protocolOpenAiCompletions: "OpenAI Chat Completions",
2911
+ protocolOpenAiResponses: "OpenAI Responses",
2912
+ protocolAnthropicMessages: "Anthropic Messages",
2758
2913
  customNeedsBaseUrl: "A custom provider needs a base URL.",
2759
2914
  customBaseUrlInvalid: "Enter a valid HTTP or HTTPS URL.",
2760
2915
  customNeedsModels: "A custom provider needs at least one model.",
2761
2916
  customBaseUrlPlaceholder: "https://gateway.example/v1",
2917
+ customAnthropicBaseUrlPlaceholder: "https://gateway.example",
2762
2918
  settingsPathUnresolvable: "unresolvable settings path",
2763
2919
  create: "Create provider",
2764
2920
  creating: "Creating…",
@@ -2777,7 +2933,7 @@ window.__ModuleLoader__.load({
2777
2933
  const zh = {
2778
2934
  nav: "模型",
2779
2935
  title: "模型",
2780
- intro: "填入各提供方的 API 密钥即可使用其模型。",
2936
+ intro: "填入各提供商的 API 密钥即可使用其模型。",
2781
2937
  edit: "编辑",
2782
2938
  editProvider: "编辑 {provider}",
2783
2939
  remove: "删除",
@@ -2787,8 +2943,15 @@ window.__ModuleLoader__.load({
2787
2943
  deleteDescriptionWithCredential: "删除 {provider} 会移除其配置和存储的 API 密钥。",
2788
2944
  deleteConfirm: "删除 {provider}",
2789
2945
  deleting: "正在删除 {provider}…",
2790
- add: "添加提供方",
2791
- provider: "提供方",
2946
+ add: "添加模型提供商",
2947
+ addMode: "添加方式",
2948
+ addCatalog: "第三方模型提供商",
2949
+ addCustom: "自定义模型 API",
2950
+ addCatalogHint: "从内置目录中选择 OpenAI、Anthropic、Kimi 等提供商,填入其 API 密钥即可使用。",
2951
+ addCustomHint: "连接中转站、自部署服务或其他兼容 OpenAI / Anthropic 协议的接口,需填写 API 地址、协议和模型。",
2952
+ addCatalogExhausted: "目录中的提供商都已添加。",
2953
+ addCustomUnavailable: "没有可用的 API 协议。",
2954
+ provider: "提供商",
2792
2955
  close: "关闭",
2793
2956
  cancel: "取消",
2794
2957
  apply: "保存",
@@ -2797,7 +2960,7 @@ window.__ModuleLoader__.load({
2797
2960
  credentialConfigured: "API 密钥已配置",
2798
2961
  credentialMissing: "API 密钥缺失",
2799
2962
  readOnly: "当前部署的设置文档为只读。",
2800
- loadFailed: "加载提供方目录失败",
2963
+ loadFailed: "加载提供商目录失败",
2801
2964
  conflict: "这张卡片打开期间,这些设置已被其他地方改动。请关闭后重新打开,在当前值上编辑。",
2802
2965
  retry: "重试",
2803
2966
  keyInput: "API 密钥",
@@ -2807,10 +2970,9 @@ window.__ModuleLoader__.load({
2807
2970
  keyEnvLocked: "由启动环境提供(只读)",
2808
2971
  customized: "自定义设置",
2809
2972
  baseUrl: "API 地址",
2810
- baseUrlDefault: "提供方默认",
2811
- deepSeekChatBaseUrl: "https://api.deepseek.com",
2812
- deepSeekMessagesBaseUrl: "https://api.deepseek.com/anthropic",
2813
- deepSeekEndpointHint: "请填写与当前连接配置兼容的 API 地址。",
2973
+ baseUrlDefault: "提供商默认",
2974
+ deepSeekBaseUrl: "https://api.deepseek.com/anthropic",
2975
+ deepSeekEndpointHint: "请填写兼容 Anthropic Messages 协议的 API 地址。",
2814
2976
  models: "模型目录",
2815
2977
  modelsInherited: "正在使用适配器默认模型",
2816
2978
  modelsCustomized: "已自定义模型目录",
@@ -2820,9 +2982,9 @@ window.__ModuleLoader__.load({
2820
2982
  modelName: "显示名称",
2821
2983
  modelNamePlaceholder: "留空时使用模型 ID",
2822
2984
  contextWindow: "上下文窗口",
2823
- contextWindowPlaceholder: "使用提供方默认值",
2985
+ contextWindowPlaceholder: "使用提供商默认值",
2824
2986
  maxTokens: "最大输出 token 数",
2825
- maxTokensPlaceholder: "使用提供方默认值",
2987
+ maxTokensPlaceholder: "使用提供商默认值",
2826
2988
  modelAdvanced: "模型选项",
2827
2989
  modelInputTypes: "输入类型",
2828
2990
  modelInputText: "文本",
@@ -2831,43 +2993,45 @@ window.__ModuleLoader__.load({
2831
2993
  removeModel: "删除模型",
2832
2994
  modelsEmpty: "模型选择器中将不显示任何模型;目录外 ID 仍可直接发送。",
2833
2995
  keyBlank: "请输入 API 密钥;留空则保持已存储的密钥。",
2834
- keyBlankNew: "请输入 API 密钥;若该提供方以其他方式鉴权,可以留空。",
2996
+ keyBlankNew: "请输入 API 密钥;若该提供商以其他方式鉴权,可以留空。",
2835
2997
  keyIllegalCharacters: "该 API 密钥格式错误,请检查。",
2836
2998
  modelIdRequired: "模型 ID 不能为空。",
2837
2999
  modelIdDuplicate: "模型 ID 不能重复。",
2838
3000
  modelNameInvalid: "显示名称不能为空。",
2839
3001
  modelContextInvalid: "上下文窗口必须是正数,例如 131072、256K 或 1M。",
2840
3002
  modelMaxTokensInvalid: "最大输出 token 数必须是正数,例如 8192、64K 或 1M。",
2841
- advancedHint: "其余字段在 settings.yaml 中,请直接编辑对应段。",
3003
+ advancedHint: "其余字段在 cordis.patch.yml 中,请直接编辑对应段。",
2842
3004
  modelCapacityInvalid: "容量需为数字,可加 K 或 M 后缀。",
2843
3005
  modelDuplicate: "每个模型 ID 只能出现一次。",
2844
3006
  fetchModels: "获取可用模型",
2845
- fetching: "正在询问提供方…",
3007
+ fetching: "正在询问提供商…",
2846
3008
  fetchNeedsBaseUrl: "请先填写 API 地址,再获取。",
2847
- fetchEmpty: "该提供方没有列出任何模型,请手动添加。",
3009
+ fetchEmpty: "该提供商没有列出任何模型,请手动添加。",
2848
3010
  fetchTitle: "选择要添加的模型",
2849
- fetchDescription: "以下是模型提供方的可用模型,勾选要添加的模型。",
3011
+ fetchDescription: "以下是模型提供商的可用模型,勾选要添加的模型。",
2850
3012
  fetchSearch: "搜索模型",
2851
3013
  fetchNoMatches: "没有匹配的模型。",
2852
3014
  fetchSelectAll: "全选",
2853
3015
  fetchDeselectAll: "取消全选",
2854
3016
  fetchAdopt: "添加所选",
2855
- customAdd: "添加自定义提供方",
2856
- customTitle: "自定义提供方",
2857
3017
  customTag: "自定义",
2858
3018
  customRoute: "Provider ID",
2859
- customRouteHint: "以小写字母开头的标识,在请求中唯一标识该提供方,并用于派生凭据名。",
3019
+ customRouteHint: "以小写字母开头的标识,在请求中唯一标识该提供商,并用于派生凭据名。",
2860
3020
  customRouteInvalid: "需以小写字母开头,之后可用小写字母、数字和短横线。",
2861
- customRouteTaken: "已有提供方使用了这个 ID。",
3021
+ customRouteTaken: "已有提供商使用了这个 ID。",
2862
3022
  customDisplayName: "显示名称",
2863
3023
  customApi: "API 协议",
2864
3024
  customApiUnset: "未选择",
2865
- customNeedsBaseUrl: "自定义提供方需要填写 API 地址。",
3025
+ protocolOpenAiCompletions: "OpenAI Chat Completions",
3026
+ protocolOpenAiResponses: "OpenAI Responses",
3027
+ protocolAnthropicMessages: "Anthropic Messages",
3028
+ customNeedsBaseUrl: "自定义模型 API 需要填写 API 地址。",
2866
3029
  customBaseUrlInvalid: "请输入有效的 HTTP 或 HTTPS 地址。",
2867
- customNeedsModels: "自定义提供方至少需要一个模型。",
3030
+ customNeedsModels: "自定义模型 API 至少需要一个模型。",
2868
3031
  customBaseUrlPlaceholder: "https://gateway.example/v1",
3032
+ customAnthropicBaseUrlPlaceholder: "https://gateway.example",
2869
3033
  settingsPathUnresolvable: "无法解析设置路径",
2870
- create: "创建提供方",
3034
+ create: "创建提供商",
2871
3035
  creating: "创建中…",
2872
3036
  welcomeTitle: "内测声明",
2873
3037
  welcomeBody: "DeepSeek Harness 目前的 0.1 版本仍处在面向 Harness 开发者进行测试的阶段,还有许多地方需要持续改进和打磨,希望听取广大开发者的反馈建议。预计 DeepSeek Harness 的核心插件以及基础 API 都会在接下来的一段时间内快速迭代、持续演化。\n\n我们期待与全球开发者一起,在开源、开放、可复用、可组合的基础设施之上,共同探索智能上限。欢迎全球 Harness 开发者加入 DSH 插件生态。",
@@ -2881,6 +3045,904 @@ window.__ModuleLoader__.load({
2881
3045
  keyRequired: "请输入 API 密钥后继续。"
2882
3046
  };
2883
3047
  //#endregion
3048
+ //#region ../../../vendor/cosmokit/src/misc.ts
3049
+ /** Return true when a value is `null` or `undefined`. */
3050
+ function isNullable(value) {
3051
+ return value === null || value === void 0;
3052
+ }
3053
+ /** Return true for non-array object values. */
3054
+ function isPlainObject(data) {
3055
+ return data && typeof data === "object" && !Array.isArray(data);
3056
+ }
3057
+ /** Filter object entries and return a new object. */
3058
+ function filterKeys(object, filter) {
3059
+ return Object.fromEntries(Object.entries(object).filter(([key, value]) => filter(key, value)));
3060
+ }
3061
+ /** Map object values while preserving the original key set. */
3062
+ function mapValues(object, transform) {
3063
+ return Object.fromEntries(Object.entries(object).map(([key, value]) => [key, transform(value, key)]));
3064
+ }
3065
+ /** Pick selected keys from an object, optionally including `undefined` values. */
3066
+ function pick(source, keys, forced) {
3067
+ if (!keys) return { ...source };
3068
+ const result = {};
3069
+ for (const key of keys) if (forced || source[key] !== void 0) result[key] = source[key];
3070
+ return result;
3071
+ }
3072
+ //#endregion
3073
+ //#region ../../../vendor/cosmokit/src/volatile.ts
3074
+ /** Shared config references used by schema validators and plugin runtimes. */
3075
+ const write = Symbol.for("cosmokit.volatile.write");
3076
+ function snapshot(value, ancestors = /* @__PURE__ */ new Set()) {
3077
+ if (typeof value === "function") throw new TypeError("volatile config cannot contain functions");
3078
+ if (value === null || typeof value !== "object") return value;
3079
+ if (ancestors.has(value)) throw new TypeError("volatile config cannot contain cycles");
3080
+ ancestors.add(value);
3081
+ try {
3082
+ if (Array.isArray(value)) return Object.freeze(value.map((item) => snapshot(item, ancestors)));
3083
+ if (Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) throw new TypeError("volatile config objects must be plain objects or arrays");
3084
+ return Object.freeze(Object.fromEntries(Object.entries(value).map(([key, item]) => [key, snapshot(item, ancestors)])));
3085
+ } finally {
3086
+ ancestors.delete(value);
3087
+ }
3088
+ }
3089
+ /**
3090
+ * Create a detached reference containing an immutable copy of the supplied data.
3091
+ * @param value - validated config data; class instances and functions are unsupported.
3092
+ * @returns a reference whose value is updated only by its owning runtime.
3093
+ */
3094
+ function createVolatile(value) {
3095
+ let current = snapshot(value);
3096
+ return Object.freeze({
3097
+ get: () => current,
3098
+ [write]: (value) => {
3099
+ current = value;
3100
+ }
3101
+ });
3102
+ }
3103
+ /**
3104
+ * Identify references across ESM/CJS copies of the shared library.
3105
+ * @param value - a parsed config value.
3106
+ * @returns whether the value implements the shared reference protocol.
3107
+ */
3108
+ function isVolatile(value) {
3109
+ return typeof value === "object" && value !== null && write in value;
3110
+ }
3111
+ //#endregion
3112
+ //#region ../../../vendor/cosmokit/src/types.ts
3113
+ /** Test values using `instanceof` with a `toStringTag` fallback. */
3114
+ function is(type, value) {
3115
+ if (arguments.length === 1) return (value) => is(type, value);
3116
+ return type in globalThis && value instanceof globalThis[type] || Object.prototype.toString.call(value).slice(8, -1) === type;
3117
+ }
3118
+ function isArrayBufferLike(value) {
3119
+ return is("ArrayBuffer", value) || is("SharedArrayBuffer", value);
3120
+ }
3121
+ function isArrayBufferSource(value) {
3122
+ return isArrayBufferLike(value) || ArrayBuffer.isView(value);
3123
+ }
3124
+ let Binary;
3125
+ (function(_Binary) {
3126
+ _Binary.is = isArrayBufferLike;
3127
+ _Binary.isSource = isArrayBufferSource;
3128
+ function fromSource(source) {
3129
+ if (ArrayBuffer.isView(source)) return source.buffer.slice(source.byteOffset, source.byteOffset + source.byteLength);
3130
+ else return source;
3131
+ }
3132
+ _Binary.fromSource = fromSource;
3133
+ function toBase64(source) {
3134
+ source = fromSource(source);
3135
+ if (typeof Buffer !== "undefined") return Buffer.from(source).toString("base64");
3136
+ let binary = "";
3137
+ const bytes = new Uint8Array(source);
3138
+ for (let i = 0; i < bytes.byteLength; i++) binary += String.fromCharCode(bytes[i]);
3139
+ return btoa(binary);
3140
+ }
3141
+ _Binary.toBase64 = toBase64;
3142
+ function fromBase64(source) {
3143
+ if (typeof Buffer !== "undefined") return fromSource(Buffer.from(source, "base64"));
3144
+ return Uint8Array.from(atob(source), (c) => c.charCodeAt(0));
3145
+ }
3146
+ _Binary.fromBase64 = fromBase64;
3147
+ function toHex(source) {
3148
+ source = fromSource(source);
3149
+ if (typeof Buffer !== "undefined") return Buffer.from(source).toString("hex");
3150
+ return Array.from(new Uint8Array(source), (byte) => byte.toString(16).padStart(2, "0")).join("");
3151
+ }
3152
+ _Binary.toHex = toHex;
3153
+ function fromHex(source) {
3154
+ if (typeof Buffer !== "undefined") return fromSource(Buffer.from(source, "hex"));
3155
+ const hex = source.length % 2 === 0 ? source : source.slice(0, source.length - 1);
3156
+ const buffer = [];
3157
+ for (let i = 0; i < hex.length; i += 2) buffer.push(parseInt(`${hex[i]}${hex[i + 1]}`, 16));
3158
+ return Uint8Array.from(buffer).buffer;
3159
+ }
3160
+ _Binary.fromHex = fromHex;
3161
+ })(Binary || (Binary = {}));
3162
+ Binary.fromBase64;
3163
+ Binary.toBase64;
3164
+ Binary.fromHex;
3165
+ Binary.toHex;
3166
+ /** Deep-clone common JavaScript values while preserving prototypes and cycles. */
3167
+ function clone(source, refs = /* @__PURE__ */ new Map()) {
3168
+ if (!source || typeof source !== "object") return source;
3169
+ if (is("Date", source)) return new Date(source.valueOf());
3170
+ if (is("RegExp", source)) return new RegExp(source.source, source.flags);
3171
+ if (isArrayBufferLike(source)) return source.slice(0);
3172
+ if (ArrayBuffer.isView(source)) return source.buffer.slice(source.byteOffset, source.byteOffset + source.byteLength);
3173
+ const cached = refs.get(source);
3174
+ if (cached) return cached;
3175
+ if (Array.isArray(source)) {
3176
+ const result = [];
3177
+ refs.set(source, result);
3178
+ source.forEach((value, index) => {
3179
+ result[index] = Reflect.apply(clone, null, [value, refs]);
3180
+ });
3181
+ return result;
3182
+ }
3183
+ const result = Object.create(Object.getPrototypeOf(source));
3184
+ refs.set(source, result);
3185
+ for (const key of Reflect.ownKeys(source)) {
3186
+ const descriptor = { ...Reflect.getOwnPropertyDescriptor(source, key) };
3187
+ if ("value" in descriptor) descriptor.value = Reflect.apply(clone, null, [descriptor.value, refs]);
3188
+ Reflect.defineProperty(result, key, descriptor);
3189
+ }
3190
+ return result;
3191
+ }
3192
+ /**
3193
+ * Compare values recursively, treating two volatile references as equal regardless of value.
3194
+ * Strict comparison distinguishes null/undefined, treats opaque objects by identity,
3195
+ * compares URLs by normalized href, treats array holes as undefined, and considers distinct cyclic structures unequal.
3196
+ * @param a - first value.
3197
+ * @param b - second value.
3198
+ * @param strict - whether to require strict data equality outside volatile references.
3199
+ * @returns whether the values compare equal.
3200
+ */
3201
+ function deepEqual(a, b, strict) {
3202
+ const ancestors = /* @__PURE__ */ new Set();
3203
+ function compare(a, b) {
3204
+ if (a === b) return true;
3205
+ if (isVolatile(a) || isVolatile(b)) return isVolatile(a) && isVolatile(b);
3206
+ if (!strict && isNullable(a) && isNullable(b)) return true;
3207
+ if (typeof a !== typeof b || typeof a !== "object" || !a || !b) return false;
3208
+ if (ancestors.has(a)) return false;
3209
+ function check(test, then) {
3210
+ return test(a) ? test(b) ? then(a, b) : false : test(b) ? false : void 0;
3211
+ }
3212
+ ancestors.add(a);
3213
+ try {
3214
+ return check(Array.isArray, (a, b) => {
3215
+ if (a.length !== b.length) return false;
3216
+ for (let index = 0; index < a.length; index++) if (!compare(a[index], b[index])) return false;
3217
+ return true;
3218
+ }) ?? check(is("Date"), (a, b) => a.valueOf() === b.valueOf()) ?? check(is("URL"), (a, b) => a.href === b.href) ?? check(is("RegExp"), (a, b) => a.source === b.source && a.flags === b.flags) ?? check(isArrayBufferLike, (a, b) => {
3219
+ if (a.byteLength !== b.byteLength) return false;
3220
+ const viewA = new Uint8Array(a);
3221
+ const viewB = new Uint8Array(b);
3222
+ for (let i = 0; i < viewA.length; i++) if (viewA[i] !== viewB[i]) return false;
3223
+ return true;
3224
+ }) ?? ((!strict || [a, b].every((value) => Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null)) && Object.keys({
3225
+ ...a,
3226
+ ...b
3227
+ }).every((key) => compare(a[key], b[key])));
3228
+ } finally {
3229
+ ancestors.delete(a);
3230
+ }
3231
+ }
3232
+ return compare(a, b);
3233
+ }
3234
+ //#endregion
3235
+ //#region ../../../vendor/cosmokit/src/time.ts
3236
+ let Time;
3237
+ (function(_Time) {
3238
+ _Time.millisecond = 1;
3239
+ const second = _Time.second = 1e3;
3240
+ const minute = _Time.minute = second * 60;
3241
+ const hour = _Time.hour = minute * 60;
3242
+ const day = _Time.day = hour * 24;
3243
+ const week = _Time.week = day * 7;
3244
+ let timezoneOffset = (/* @__PURE__ */ new Date()).getTimezoneOffset();
3245
+ function setTimezoneOffset(offset) {
3246
+ timezoneOffset = offset;
3247
+ }
3248
+ _Time.setTimezoneOffset = setTimezoneOffset;
3249
+ function getTimezoneOffset() {
3250
+ return timezoneOffset;
3251
+ }
3252
+ _Time.getTimezoneOffset = getTimezoneOffset;
3253
+ function getDateNumber(date = /* @__PURE__ */ new Date(), offset) {
3254
+ if (typeof date === "number") date = new Date(date);
3255
+ if (offset === void 0) offset = timezoneOffset;
3256
+ return Math.floor((date.valueOf() / minute - offset) / 1440);
3257
+ }
3258
+ _Time.getDateNumber = getDateNumber;
3259
+ function fromDateNumber(value, offset) {
3260
+ const date = new Date(value * day);
3261
+ if (offset === void 0) offset = timezoneOffset;
3262
+ return new Date(+date + offset * minute);
3263
+ }
3264
+ _Time.fromDateNumber = fromDateNumber;
3265
+ const numeric = /\d+(?:\.\d+)?/.source;
3266
+ const timeRegExp = new RegExp(`^${[
3267
+ "w(?:eek(?:s)?)?",
3268
+ "d(?:ay(?:s)?)?",
3269
+ "h(?:our(?:s)?)?",
3270
+ "m(?:in(?:ute)?(?:s)?)?",
3271
+ "s(?:ec(?:ond)?(?:s)?)?"
3272
+ ].map((unit) => `(${numeric}${unit})?`).join("")}$`);
3273
+ function parseTime(source) {
3274
+ const capture = timeRegExp.exec(source);
3275
+ if (!capture) return 0;
3276
+ return (parseFloat(capture[1]) * week || 0) + (parseFloat(capture[2]) * day || 0) + (parseFloat(capture[3]) * hour || 0) + (parseFloat(capture[4]) * minute || 0) + (parseFloat(capture[5]) * second || 0);
3277
+ }
3278
+ _Time.parseTime = parseTime;
3279
+ function parseDate(date) {
3280
+ const parsed = parseTime(date);
3281
+ if (parsed) date = Date.now() + parsed;
3282
+ else if (/^\d{1,2}(:\d{1,2}){1,2}$/.test(date)) date = `${(/* @__PURE__ */ new Date()).toLocaleDateString()}-${date}`;
3283
+ else if (/^\d{1,2}-\d{1,2}-\d{1,2}(:\d{1,2}){1,2}$/.test(date)) date = `${(/* @__PURE__ */ new Date()).getFullYear()}-${date}`;
3284
+ return date ? new Date(date) : /* @__PURE__ */ new Date();
3285
+ }
3286
+ _Time.parseDate = parseDate;
3287
+ function format(ms) {
3288
+ const abs = Math.abs(ms);
3289
+ if (abs >= day - hour / 2) return Math.round(ms / day) + "d";
3290
+ else if (abs >= hour - minute / 2) return Math.round(ms / hour) + "h";
3291
+ else if (abs >= minute - second / 2) return Math.round(ms / minute) + "m";
3292
+ else if (abs >= second) return Math.round(ms / second) + "s";
3293
+ return ms + "ms";
3294
+ }
3295
+ _Time.format = format;
3296
+ function toDigits(source, length = 2) {
3297
+ return source.toString().padStart(length, "0");
3298
+ }
3299
+ _Time.toDigits = toDigits;
3300
+ function template(template, time = /* @__PURE__ */ new Date()) {
3301
+ return template.replace("yyyy", time.getFullYear().toString()).replace("yy", time.getFullYear().toString().slice(2)).replace("MM", toDigits(time.getMonth() + 1)).replace("dd", toDigits(time.getDate())).replace("hh", toDigits(time.getHours())).replace("mm", toDigits(time.getMinutes())).replace("ss", toDigits(time.getSeconds())).replace("SSS", toDigits(time.getMilliseconds(), 3));
3302
+ }
3303
+ _Time.template = template;
3304
+ })(Time || (Time = {}));
3305
+ //#endregion
3306
+ //#region ../../../vendor/schemastery/src/index.ts
3307
+ const kSchema = Symbol.for("schemastery");
3308
+ const kValidationError = Symbol.for("ValidationError");
3309
+ globalThis.__schemastery_index__ ??= 0;
3310
+ globalThis.__schemastery_refs__ = void 0;
3311
+ var ValidationError = class extends TypeError {
3312
+ options;
3313
+ name = "ValidationError";
3314
+ constructor(message, options) {
3315
+ let prefix = "$";
3316
+ for (const segment of options.path || []) if (typeof segment === "string") prefix += "." + segment;
3317
+ else if (typeof segment === "number") prefix += "[" + segment + "]";
3318
+ else if (typeof segment === "symbol") prefix += `[Symbol(${segment.toString()})]`;
3319
+ if (prefix.startsWith(".")) prefix = prefix.slice(1);
3320
+ super((prefix === "$" ? "" : `${prefix} `) + message);
3321
+ this.options = options;
3322
+ }
3323
+ static is(error) {
3324
+ return !!error?.[kValidationError];
3325
+ }
3326
+ };
3327
+ Object.defineProperty(ValidationError.prototype, kValidationError, { value: true });
3328
+ const Schema = function(options) {
3329
+ const schema = function(data, options = {}) {
3330
+ return Schema.resolve(data, schema, options)[0];
3331
+ };
3332
+ if (options.refs) {
3333
+ const refs = mapValues(options.refs, (options) => new Schema(options));
3334
+ const getRef = (uid) => refs[uid];
3335
+ for (const key in refs) {
3336
+ const options = refs[key];
3337
+ options.sKey = getRef(options.sKey);
3338
+ options.inner = getRef(options.inner);
3339
+ options.list = options.list && options.list.map(getRef);
3340
+ options.dict = options.dict && mapValues(options.dict, getRef);
3341
+ }
3342
+ return refs[options.uid];
3343
+ }
3344
+ Object.assign(schema, options);
3345
+ if (typeof schema.callback === "string") try {
3346
+ schema.callback = new Function("return " + schema.callback)();
3347
+ } catch {}
3348
+ Object.defineProperty(schema, "uid", { value: globalThis.__schemastery_index__++ });
3349
+ Object.setPrototypeOf(schema, Schema.prototype);
3350
+ schema.meta ||= {};
3351
+ schema.toString = schema.toString.bind(schema);
3352
+ return schema;
3353
+ };
3354
+ Schema.prototype = Object.create(Function.prototype);
3355
+ Schema.prototype[kSchema] = true;
3356
+ Object.defineProperty(Schema.prototype, "~standard", { get() {
3357
+ return {
3358
+ version: 1,
3359
+ vendor: "schemastery",
3360
+ validate: (value) => {
3361
+ try {
3362
+ return { value: Schema.resolve(value, this, {})[0] };
3363
+ } catch (error) {
3364
+ if (ValidationError.is(error)) return { issues: [{
3365
+ message: error.message,
3366
+ path: error.options.path
3367
+ }] };
3368
+ throw error;
3369
+ }
3370
+ }
3371
+ };
3372
+ } });
3373
+ Schema.ValidationError = ValidationError;
3374
+ Schema.prototype.toJSON = function toJSON() {
3375
+ if (globalThis.__schemastery_refs__) {
3376
+ globalThis.__schemastery_refs__[this.uid] ??= JSON.parse(JSON.stringify({ ...this }));
3377
+ return this.uid;
3378
+ }
3379
+ globalThis.__schemastery_refs__ = { [this.uid]: { ...this } };
3380
+ globalThis.__schemastery_refs__[this.uid] = JSON.parse(JSON.stringify({ ...this }));
3381
+ const result = {
3382
+ uid: this.uid,
3383
+ refs: globalThis.__schemastery_refs__
3384
+ };
3385
+ globalThis.__schemastery_refs__ = void 0;
3386
+ return result;
3387
+ };
3388
+ Schema.prototype.set = function set(key, value) {
3389
+ this.dict[key] = value;
3390
+ return this;
3391
+ };
3392
+ Schema.prototype.push = function push(value) {
3393
+ this.list.push(value);
3394
+ return this;
3395
+ };
3396
+ function mergeDesc(original, messages) {
3397
+ const result = typeof original === "string" ? { "": original } : { ...original };
3398
+ for (const locale in messages) {
3399
+ const value = messages[locale];
3400
+ if (value?.$description || value?.$desc) result[locale] = value.$description || value.$desc;
3401
+ else if (typeof value === "string") result[locale] = value;
3402
+ }
3403
+ return result;
3404
+ }
3405
+ function getInner(value) {
3406
+ return value?.$value ?? value?.$inner;
3407
+ }
3408
+ function extractKeys(data) {
3409
+ return filterKeys(data ?? {}, (key) => !key.startsWith("$"));
3410
+ }
3411
+ Schema.prototype.i18n = function i18n(messages) {
3412
+ const schema = Schema(this);
3413
+ const desc = mergeDesc(schema.meta.description, messages);
3414
+ if (Object.keys(desc).length) schema.meta.description = desc;
3415
+ if (schema.dict) schema.dict = mapValues(schema.dict, (inner, key) => {
3416
+ return inner.i18n(mapValues(messages, (data) => getInner(data)?.[key] ?? data?.[key]));
3417
+ });
3418
+ if (schema.list) schema.list = schema.list.map((inner, index) => {
3419
+ return inner.i18n(mapValues(messages, (data = {}) => {
3420
+ if (Array.isArray(getInner(data))) return getInner(data)[index];
3421
+ if (Array.isArray(data)) return data[index];
3422
+ return extractKeys(data);
3423
+ }));
3424
+ });
3425
+ if (schema.inner) schema.inner = schema.inner.i18n(mapValues(messages, (data) => {
3426
+ if (getInner(data)) return getInner(data);
3427
+ return extractKeys(data);
3428
+ }));
3429
+ if (schema.sKey) schema.sKey = schema.sKey.i18n(mapValues(messages, (data) => data?.$key));
3430
+ return schema;
3431
+ };
3432
+ Schema.prototype.extra = function extra(key, value) {
3433
+ const schema = Schema(this);
3434
+ schema.meta = {
3435
+ ...schema.meta,
3436
+ [key]: value
3437
+ };
3438
+ return schema;
3439
+ };
3440
+ for (const key of [
3441
+ "required",
3442
+ "disabled",
3443
+ "collapse",
3444
+ "hidden",
3445
+ "loose"
3446
+ ]) Object.assign(Schema.prototype, { [key](value = true) {
3447
+ const schema = Schema(this);
3448
+ schema.meta = {
3449
+ ...schema.meta,
3450
+ [key]: value
3451
+ };
3452
+ return schema;
3453
+ } });
3454
+ Schema.prototype.deprecated = function deprecated() {
3455
+ const schema = Schema(this);
3456
+ schema.meta.badges ||= [];
3457
+ schema.meta.badges.push({
3458
+ text: "deprecated",
3459
+ type: "danger"
3460
+ });
3461
+ return schema;
3462
+ };
3463
+ Schema.prototype.experimental = function experimental() {
3464
+ const schema = Schema(this);
3465
+ schema.meta.badges ||= [];
3466
+ schema.meta.badges.push({
3467
+ text: "experimental",
3468
+ type: "warning"
3469
+ });
3470
+ return schema;
3471
+ };
3472
+ Schema.prototype.pattern = function pattern(regexp) {
3473
+ const schema = Schema(this);
3474
+ const pattern = pick(regexp, ["source", "flags"]);
3475
+ schema.meta = {
3476
+ ...schema.meta,
3477
+ pattern
3478
+ };
3479
+ return schema;
3480
+ };
3481
+ Schema.prototype.simplify = function simplify(value) {
3482
+ if (isVolatile(value)) value = value.get();
3483
+ if (deepEqual(value, this.meta.default, this.type === "dict")) return null;
3484
+ if (isNullable(value)) return value;
3485
+ if (this.type === "object" || this.type === "dict") {
3486
+ const result = {};
3487
+ for (const key in value) {
3488
+ const item = (this.type === "object" ? this.dict[key] : this.inner)?.simplify(value[key]);
3489
+ if (this.type === "dict" || !isNullable(item)) result[key] = item;
3490
+ }
3491
+ if (deepEqual(result, this.meta.default, this.type === "dict")) return null;
3492
+ return result;
3493
+ } else if (this.type === "array" || this.type === "tuple") {
3494
+ const result = [];
3495
+ value.forEach((value, index) => {
3496
+ const schema = this.type === "array" ? this.inner : this.list[index];
3497
+ const item = schema ? schema.simplify(value) : value;
3498
+ result.push(item);
3499
+ });
3500
+ return result;
3501
+ } else if (this.type === "intersect") {
3502
+ const result = {};
3503
+ for (const item of this.list) Object.assign(result, item.simplify(value));
3504
+ return result;
3505
+ } else if (this.type === "union") for (const schema of this.list) try {
3506
+ Schema.resolve(value, schema, {});
3507
+ return schema.simplify(value);
3508
+ } catch {}
3509
+ return value;
3510
+ };
3511
+ Schema.prototype.toString = function toString(inline) {
3512
+ return formatters[this.type]?.(this, inline) ?? `Schema<${this.type}>`;
3513
+ };
3514
+ Schema.prototype.role = function role(role, extra) {
3515
+ const schema = Schema(this);
3516
+ schema.meta = {
3517
+ ...schema.meta,
3518
+ role,
3519
+ extra
3520
+ };
3521
+ return schema;
3522
+ };
3523
+ for (const key of [
3524
+ "default",
3525
+ "link",
3526
+ "comment",
3527
+ "description",
3528
+ "max",
3529
+ "min",
3530
+ "step"
3531
+ ]) Object.assign(Schema.prototype, { [key](value) {
3532
+ const schema = Schema(this);
3533
+ schema.meta = {
3534
+ ...schema.meta,
3535
+ [key]: value
3536
+ };
3537
+ return schema;
3538
+ } });
3539
+ Schema.prototype.volatile = function volatile() {
3540
+ if (this.meta.volatile) throw new TypeError("volatile schema is already wrapped");
3541
+ return this.extra("volatile", true);
3542
+ };
3543
+ const resolvers = {};
3544
+ const checkedVolatile = Symbol("checked-volatile-schema");
3545
+ function validateVolatileSchema(schema, path = [], blocked = false, seen = /* @__PURE__ */ new Map()) {
3546
+ const states = seen.get(schema) ?? /* @__PURE__ */ new Set();
3547
+ if (states.has(blocked)) return;
3548
+ states.add(blocked);
3549
+ seen.set(schema, states);
3550
+ if (schema.meta?.volatile && blocked) throw new ValidationError("volatile fields require a fixed object path without an enclosing volatile field", { path });
3551
+ const nested = blocked || !!schema.meta?.volatile;
3552
+ if (schema.dict) for (const [key, child] of Object.entries(schema.dict)) validateVolatileSchema(child, [...path, key], nested, seen);
3553
+ if (schema.sKey) validateVolatileSchema(schema.sKey, [...path, "<key>"], true, seen);
3554
+ if (schema.inner && (schema.type !== "lazy" || schema.inner[kSchema])) validateVolatileSchema(schema.inner, [...path, "*"], true, seen);
3555
+ if (schema.list) for (let index = 0; index < schema.list.length; index++) validateVolatileSchema(schema.list[index], [...path, String(index)], true, seen);
3556
+ }
3557
+ Schema.extend = function extend(type, resolve) {
3558
+ resolvers[type] = resolve;
3559
+ };
3560
+ Schema.resolve = function resolve(data, schema, options = {}, strict = false) {
3561
+ if (!schema) return [data];
3562
+ if (!options[checkedVolatile]) {
3563
+ validateVolatileSchema(schema, options.path);
3564
+ options = {
3565
+ ...options,
3566
+ [checkedVolatile]: true
3567
+ };
3568
+ }
3569
+ if (schema.meta?.volatile) {
3570
+ const inner = Schema(schema);
3571
+ inner.meta = {
3572
+ ...schema.meta,
3573
+ volatile: false
3574
+ };
3575
+ const [value, adapted] = Schema.resolve(data, inner, options, strict);
3576
+ try {
3577
+ return [createVolatile(value), adapted];
3578
+ } catch (error) {
3579
+ throw new ValidationError(error instanceof Error ? error.message : String(error), options);
3580
+ }
3581
+ }
3582
+ if (options.ignore?.(data, schema)) return [data];
3583
+ if (isNullable(data) && schema.type !== "lazy") {
3584
+ if (schema.meta.required) throw new ValidationError(`missing required value`, options);
3585
+ let current = schema;
3586
+ let fallback = schema.meta.default;
3587
+ while (current?.type === "intersect" && isNullable(fallback)) {
3588
+ current = current.list[0];
3589
+ fallback = current?.meta.default;
3590
+ }
3591
+ if (isNullable(fallback)) return [data];
3592
+ data = clone(fallback);
3593
+ }
3594
+ const callback = resolvers[schema.type];
3595
+ if (!callback) throw new ValidationError(`unsupported type "${schema.type}"`, options);
3596
+ try {
3597
+ return callback(data, schema, options, strict);
3598
+ } catch (error) {
3599
+ if (!schema.meta.loose) throw error;
3600
+ return [schema.meta.default];
3601
+ }
3602
+ };
3603
+ Schema.from = function from(source) {
3604
+ if (isNullable(source)) return Schema.any();
3605
+ else if ([
3606
+ "string",
3607
+ "number",
3608
+ "boolean"
3609
+ ].includes(typeof source)) return Schema.const(source).required();
3610
+ else if (source[kSchema]) return source;
3611
+ else if (typeof source === "function") switch (source) {
3612
+ case String: return Schema.string().required();
3613
+ case Number: return Schema.number().required();
3614
+ case Boolean: return Schema.boolean().required();
3615
+ case Function: return Schema.function().required();
3616
+ default: return Schema.is(source).required();
3617
+ }
3618
+ else throw new TypeError(`cannot infer schema from ${source}`);
3619
+ };
3620
+ Schema.lazy = function lazy(builder) {
3621
+ const toJSON = () => {
3622
+ if (!schema.inner[kSchema]) {
3623
+ schema.inner = schema.builder();
3624
+ schema.inner.meta = {
3625
+ ...schema.meta,
3626
+ ...schema.inner.meta
3627
+ };
3628
+ }
3629
+ return schema.inner.toJSON();
3630
+ };
3631
+ const schema = new Schema({
3632
+ type: "lazy",
3633
+ builder,
3634
+ inner: { toJSON }
3635
+ });
3636
+ return schema;
3637
+ };
3638
+ Schema.natural = function natural() {
3639
+ return Schema.number().step(1).min(0);
3640
+ };
3641
+ Schema.percent = function percent() {
3642
+ return Schema.number().step(.01).min(0).max(1).role("slider");
3643
+ };
3644
+ Schema.date = function date() {
3645
+ return Schema.union([Schema.is(Date), Schema.transform(Schema.string().role("datetime"), (value, options) => {
3646
+ const date = new Date(value);
3647
+ if (isNaN(+date)) throw new ValidationError(`invalid date "${value}"`, options);
3648
+ return date;
3649
+ }, true)]);
3650
+ };
3651
+ Schema.regExp = function regExp(flag = "") {
3652
+ return Schema.union([Schema.is(RegExp), Schema.transform(Schema.string().role("regexp", { flag }), (value, options) => {
3653
+ try {
3654
+ return new RegExp(value, flag);
3655
+ } catch (e) {
3656
+ throw new ValidationError(e.message, options);
3657
+ }
3658
+ }, true)]);
3659
+ };
3660
+ Schema.arrayBuffer = function arrayBuffer(encoding) {
3661
+ return Schema.union([
3662
+ Schema.is(ArrayBuffer),
3663
+ Schema.is(SharedArrayBuffer),
3664
+ Schema.transform(Schema.any(), (value, options) => {
3665
+ if (Binary.isSource(value)) return Binary.fromSource(value);
3666
+ throw new ValidationError(`expected ArrayBufferSource but got ${value}`, options);
3667
+ }, true),
3668
+ ...encoding ? [Schema.transform(Schema.string(), (value, options) => {
3669
+ try {
3670
+ return encoding === "base64" ? Binary.fromBase64(value) : Binary.fromHex(value);
3671
+ } catch (e) {
3672
+ throw new ValidationError(e.message, options);
3673
+ }
3674
+ }, true)] : []
3675
+ ]);
3676
+ };
3677
+ Schema.extend("lazy", (data, schema, options, strict) => {
3678
+ if (!schema.inner[kSchema]) {
3679
+ schema.inner = schema.builder();
3680
+ schema.inner.meta = {
3681
+ ...schema.meta,
3682
+ ...schema.inner.meta
3683
+ };
3684
+ validateVolatileSchema(schema.inner, options.path, true);
3685
+ }
3686
+ return Schema.resolve(data, schema.inner, options, strict);
3687
+ });
3688
+ Schema.extend("any", (data) => {
3689
+ return [data];
3690
+ });
3691
+ Schema.extend("never", (data, _, options) => {
3692
+ throw new ValidationError(`expected nullable but got ${data}`, options);
3693
+ });
3694
+ Schema.extend("const", (data, { value }, options) => {
3695
+ if (deepEqual(data, value)) return [value];
3696
+ throw new ValidationError(`expected ${value} but got ${data}`, options);
3697
+ });
3698
+ function checkWithinRange(data, meta, description, options, skipMin = false) {
3699
+ const { max = Infinity, min = -Infinity } = meta;
3700
+ if (data > max) throw new ValidationError(`expected ${description} <= ${max} but got ${data}`, options);
3701
+ if (data < min && !skipMin) throw new ValidationError(`expected ${description} >= ${min} but got ${data}`, options);
3702
+ }
3703
+ Schema.extend("string", (data, { meta }, options) => {
3704
+ if (typeof data !== "string") throw new ValidationError(`expected string but got ${data}`, options);
3705
+ if (meta.pattern) {
3706
+ const regexp = new RegExp(meta.pattern.source, meta.pattern.flags);
3707
+ if (!regexp.test(data)) throw new ValidationError(`expect string to match regexp ${regexp}`, options);
3708
+ }
3709
+ checkWithinRange(data.length, meta, "string length", options);
3710
+ return [data];
3711
+ });
3712
+ function decimalShift(data, digits) {
3713
+ const str = data.toString();
3714
+ if (str.includes("e")) return data * Math.pow(10, digits);
3715
+ const index = str.indexOf(".");
3716
+ if (index === -1) return data * Math.pow(10, digits);
3717
+ const frac = str.slice(index + 1);
3718
+ const integer = str.slice(0, index);
3719
+ if (frac.length <= digits) return +(integer + frac.padEnd(digits, "0"));
3720
+ return +(integer + frac.slice(0, digits) + "." + frac.slice(digits));
3721
+ }
3722
+ function isMultipleOf(data, min, step) {
3723
+ step = Math.abs(step);
3724
+ if (!/^\d+\.\d+$/.test(step.toString())) return (data - min) % step === 0;
3725
+ const index = step.toString().indexOf(".");
3726
+ const digits = step.toString().slice(index + 1).length;
3727
+ return Math.abs(decimalShift(data, digits) - decimalShift(min, digits)) % decimalShift(step, digits) === 0;
3728
+ }
3729
+ Schema.extend("number", (data, { meta }, options) => {
3730
+ if (typeof data !== "number") throw new ValidationError(`expected number but got ${data}`, options);
3731
+ checkWithinRange(data, meta, "number", options);
3732
+ const { step } = meta;
3733
+ if (step && !isMultipleOf(data, meta.min ?? 0, step)) throw new ValidationError(`expected number multiple of ${step} but got ${data}`, options);
3734
+ return [data];
3735
+ });
3736
+ Schema.extend("boolean", (data, _, options) => {
3737
+ if (typeof data === "boolean") return [data];
3738
+ throw new ValidationError(`expected boolean but got ${data}`, options);
3739
+ });
3740
+ Schema.extend("bitset", (data, { bits, meta }, options) => {
3741
+ let value = 0, keys = [];
3742
+ if (typeof data === "number") {
3743
+ value = data;
3744
+ for (const key in bits) if (data & bits[key]) keys.push(key);
3745
+ } else if (Array.isArray(data)) {
3746
+ keys = data;
3747
+ for (const key of keys) {
3748
+ if (typeof key !== "string") throw new ValidationError(`expected string but got ${key}`, options);
3749
+ if (key in bits) value |= bits[key];
3750
+ }
3751
+ } else throw new ValidationError(`expected number or array but got ${data}`, options);
3752
+ if (value === meta.default) return [value];
3753
+ return [value, keys];
3754
+ });
3755
+ Schema.extend("function", (data, _, options) => {
3756
+ if (typeof data === "function") return [data];
3757
+ throw new ValidationError(`expected function but got ${data}`, options);
3758
+ });
3759
+ Schema.extend("is", (data, { constructor }, options) => {
3760
+ if (typeof constructor === "function") {
3761
+ if (data instanceof constructor) return [data];
3762
+ throw new ValidationError(`expected ${constructor.name} but got ${data}`, options);
3763
+ } else {
3764
+ if (isNullable(data)) throw new ValidationError(`expected ${constructor} but got ${data}`, options);
3765
+ let prototype = Object.getPrototypeOf(data);
3766
+ while (prototype) {
3767
+ if (prototype.constructor?.name === constructor) return [data];
3768
+ prototype = Object.getPrototypeOf(prototype);
3769
+ }
3770
+ throw new ValidationError(`expected ${constructor} but got ${data}`, options);
3771
+ }
3772
+ });
3773
+ function property(data, key, schema, options) {
3774
+ try {
3775
+ const [value, adapted] = Schema.resolve(data[key], schema, {
3776
+ ...options,
3777
+ path: [...options.path || [], key]
3778
+ });
3779
+ if (adapted !== void 0) data[key] = adapted;
3780
+ return value;
3781
+ } catch (e) {
3782
+ if (!options?.autofix) throw e;
3783
+ delete data[key];
3784
+ return schema.meta.volatile ? createVolatile(schema.meta.default) : schema.meta.default;
3785
+ }
3786
+ }
3787
+ Schema.extend("array", (data, { inner, meta }, options) => {
3788
+ if (!Array.isArray(data)) throw new ValidationError(`expected array but got ${data}`, options);
3789
+ checkWithinRange(data.length, meta, "array length", options, !isNullable(inner.meta.default));
3790
+ return [data.map((_, index) => property(data, index, inner, options))];
3791
+ });
3792
+ Schema.extend("dict", (data, { inner, sKey }, options, strict) => {
3793
+ if (!isPlainObject(data)) throw new ValidationError(`expected object but got ${data}`, options);
3794
+ const result = {};
3795
+ for (const key in data) {
3796
+ let rKey;
3797
+ try {
3798
+ rKey = Schema.resolve(key, sKey, options)[0];
3799
+ } catch (error) {
3800
+ if (strict) continue;
3801
+ throw error;
3802
+ }
3803
+ result[rKey] = property(data, key, inner, options);
3804
+ data[rKey] = data[key];
3805
+ if (key !== rKey) delete data[key];
3806
+ }
3807
+ return [result];
3808
+ });
3809
+ Schema.extend("tuple", (data, { list }, options, strict) => {
3810
+ if (!Array.isArray(data)) throw new ValidationError(`expected array but got ${data}`, options);
3811
+ const result = list.map((inner, index) => property(data, index, inner, options));
3812
+ if (strict) return [result];
3813
+ result.push(...data.slice(list.length));
3814
+ return [result];
3815
+ });
3816
+ function merge(result, data) {
3817
+ for (const key in data) {
3818
+ if (key in result) continue;
3819
+ result[key] = data[key];
3820
+ }
3821
+ }
3822
+ Schema.extend("object", (data, { dict }, options, strict) => {
3823
+ if (!isPlainObject(data)) throw new ValidationError(`expected object but got ${data}`, options);
3824
+ const result = {};
3825
+ for (const key in dict) {
3826
+ const value = property(data, key, dict[key], options);
3827
+ if (!isNullable(value) || key in data) result[key] = value;
3828
+ }
3829
+ if (!strict) merge(result, data);
3830
+ return [result];
3831
+ });
3832
+ Schema.extend("union", (data, { list, toString }, options, strict) => {
3833
+ const messages = [];
3834
+ for (const inner of list) try {
3835
+ return Schema.resolve(data, inner, options, strict);
3836
+ } catch (error) {
3837
+ messages.push(error);
3838
+ }
3839
+ throw new ValidationError(`expected ${toString()} but got ${JSON.stringify(data)}`, options);
3840
+ });
3841
+ Schema.extend("intersect", (data, { list, toString }, options, strict) => {
3842
+ if (!list.length) return [data];
3843
+ let result;
3844
+ for (const inner of list) {
3845
+ const value = Schema.resolve(data, inner, options, true)[0];
3846
+ if (isNullable(value)) continue;
3847
+ if (isNullable(result)) result = value;
3848
+ else if (typeof result !== typeof value) throw new ValidationError(`expected ${toString()} but got ${JSON.stringify(data)}`, options);
3849
+ else if (typeof value === "object") merge(result ??= {}, value);
3850
+ else if (result !== value) throw new ValidationError(`expected ${toString()} but got ${JSON.stringify(data)}`, options);
3851
+ }
3852
+ if (!strict && isPlainObject(data)) merge(result, data);
3853
+ return [result];
3854
+ });
3855
+ Schema.extend("transform", (data, { inner, callback, preserve }, options) => {
3856
+ const [result, adapted = data] = Schema.resolve(data, inner, options, true);
3857
+ if (preserve) return [callback(result)];
3858
+ else return [callback(result), callback(adapted)];
3859
+ });
3860
+ const formatters = {};
3861
+ function defineMethod(name, keys, format) {
3862
+ formatters[name] = format;
3863
+ Object.assign(Schema, { [name](...args) {
3864
+ const schema = new Schema({ type: name });
3865
+ keys.forEach((key, index) => {
3866
+ switch (key) {
3867
+ case "sKey":
3868
+ schema.sKey = args[index] ?? Schema.string();
3869
+ break;
3870
+ case "inner":
3871
+ schema.inner = Schema.from(args[index]);
3872
+ break;
3873
+ case "list":
3874
+ schema.list = args[index].map(Schema.from);
3875
+ break;
3876
+ case "dict":
3877
+ schema.dict = mapValues(args[index], Schema.from);
3878
+ break;
3879
+ case "bits":
3880
+ schema.bits = {};
3881
+ for (const key in args[index]) {
3882
+ if (typeof args[index][key] !== "number") continue;
3883
+ schema.bits[key] = args[index][key];
3884
+ }
3885
+ break;
3886
+ case "callback": {
3887
+ const callback = schema.callback = args[index];
3888
+ callback["toJSON"] ||= () => callback.toString();
3889
+ break;
3890
+ }
3891
+ case "constructor": {
3892
+ const constructor = schema.constructor = args[index];
3893
+ if (typeof constructor === "function") constructor["toJSON"] ||= () => constructor["name"];
3894
+ break;
3895
+ }
3896
+ default: schema[key] = args[index];
3897
+ }
3898
+ });
3899
+ if (name === "object" || name === "dict") schema.meta.default = {};
3900
+ else if (name === "array" || name === "tuple") schema.meta.default = [];
3901
+ else if (name === "bitset") schema.meta.default = 0;
3902
+ return schema;
3903
+ } });
3904
+ }
3905
+ defineMethod("is", ["constructor"], ({ constructor }) => {
3906
+ if (typeof constructor === "function") return constructor.name;
3907
+ else return constructor;
3908
+ });
3909
+ defineMethod("any", [], () => "any");
3910
+ defineMethod("never", [], () => "never");
3911
+ defineMethod("const", ["value"], ({ value }) => typeof value === "string" ? JSON.stringify(value) : value);
3912
+ defineMethod("string", [], () => "string");
3913
+ defineMethod("number", [], () => "number");
3914
+ defineMethod("boolean", [], () => "boolean");
3915
+ defineMethod("bitset", ["bits"], () => "bitset");
3916
+ defineMethod("function", [], () => "function");
3917
+ defineMethod("array", ["inner"], ({ inner }) => `${inner.toString(true)}[]`);
3918
+ defineMethod("dict", ["inner", "sKey"], ({ inner, sKey }) => `{ [key: ${sKey.toString()}]: ${inner.toString()} }`);
3919
+ defineMethod("tuple", ["list"], ({ list }) => `[${list.map((inner) => inner.toString()).join(", ")}]`);
3920
+ defineMethod("object", ["dict"], ({ dict }) => {
3921
+ if (Object.keys(dict).length === 0) return "{}";
3922
+ return `{ ${Object.entries(dict).map(([key, inner]) => {
3923
+ return `${key}${inner.meta.required ? "" : "?"}: ${inner.toString()}`;
3924
+ }).join(", ")} }`;
3925
+ });
3926
+ defineMethod("union", ["list"], ({ list }, inline) => {
3927
+ const result = list.map(({ toString: format }) => format()).join(" | ");
3928
+ return inline ? `(${result})` : result;
3929
+ });
3930
+ defineMethod("intersect", ["list"], ({ list }) => {
3931
+ return `${list.map((inner) => inner.toString(true)).join(" & ")}`;
3932
+ });
3933
+ defineMethod("transform", [
3934
+ "inner",
3935
+ "callback",
3936
+ "preserve"
3937
+ ], ({ inner }, isInner) => inner.toString(isInner));
3938
+ //#endregion
3939
+ //#region lib/types/onboarding-config.js
3940
+ /** Public page-bootstrap options shared by the Host and Client halves. */
3941
+ /** Validate Host configuration and its public page-bootstrap payload. */
3942
+ const Config = Schema.object({ credentialOnboarding: Schema.boolean().default(true) });
3943
+ /** Page-global key carrying only the public onboarding options. */
3944
+ const ONBOARDING_CONFIG_GLOBAL = "__DSH_MODELS_ONBOARDING__";
3945
+ //#endregion
2884
3946
  //#region lib/types/client/index.js
2885
3947
  /** Dictionary namespace owned by this plugin. */
2886
3948
  const NS = "settings.models";
@@ -2905,7 +3967,7 @@ window.__ModuleLoader__.load({
2905
3967
  "remote.credentials",
2906
3968
  "remote.llm",
2907
3969
  "remote.settings",
2908
- "settingsScope",
3970
+ "configForms",
2909
3971
  "settingsSchema"
2910
3972
  ];
2911
3973
  /**
@@ -2915,13 +3977,15 @@ window.__ModuleLoader__.load({
2915
3977
  * @param ctx - client root context.
2916
3978
  */
2917
3979
  function apply(ctx) {
3980
+ const payload = globalThis[ONBOARDING_CONFIG_GLOBAL];
3981
+ const credentialOnboarding = Config(payload === void 0 ? {} : payload).credentialOnboarding && !("dshDesktop" in globalThis);
2918
3982
  ctx.effect(() => ctx.locale.register(NS, {
2919
3983
  zh,
2920
3984
  en
2921
3985
  }), "ui-settings-models: copy dictionaries");
2922
3986
  const schema = createSettingsSchemaOperations(ctx.settingsSchema);
2923
3987
  const operations = createModelsOperations(ctx);
2924
- const controller = new ModelsSettingsStore(ctx, schema, ctx.settingsScope.describe());
3988
+ const controller = new ModelsSettingsStore(ctx, schema, ctx.configForms.describe());
2925
3989
  const t = ctx.locale.bind(NS);
2926
3990
  const injected = () => ({
2927
3991
  controller,
@@ -2931,16 +3995,14 @@ window.__ModuleLoader__.load({
2931
3995
  t
2932
3996
  });
2933
3997
  const deepSeekOnboardingInjected = () => ({
3998
+ automatic: credentialOnboarding,
2934
3999
  controller,
2935
4000
  hooks: { models: controller.store },
2936
4001
  operations,
2937
4002
  schema,
2938
4003
  t
2939
4004
  });
2940
- const welcomeController = new WelcomeNoticeStore(ctx.settingsScope.bind({
2941
- namespace: WELCOME_NOTICE_SETTINGS_NAMESPACE,
2942
- decode: decodeWelcomeSection
2943
- }));
4005
+ const welcomeController = new WelcomeNoticeStore(ctx.configForms.get(WELCOME_NOTICE_SETTINGS_NAMESPACE));
2944
4006
  const welcomeInjected = () => ({
2945
4007
  controller: welcomeController,
2946
4008
  hooks: { welcome: welcomeController.store },
@@ -2989,6 +4051,10 @@ window.__ModuleLoader__.load({
2989
4051
  ctx.slots.inject("settings.onboarding", () => ctx.slots.register({
2990
4052
  name: "settings.onboarding",
2991
4053
  id: "deepseek-official",
4054
+ children: { "settings.models.sign-in": {
4055
+ kind: "single",
4056
+ scope: "root"
4057
+ } },
2992
4058
  order: 0,
2993
4059
  inject: deepSeekOnboardingInjected
2994
4060
  }, DeepSeekOnboardingDialog));