@mofeng2223/dsh-claude-provider 0.4.5 → 0.4.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -11
- package/README.zh-CN.md +23 -11
- package/cordis.patch.yml +1 -1
- package/lib/client.js +1533 -434
- package/package.json +7 -5
- package/scripts/migrate-legacy-types.mjs +42 -0
- package/src/index.js +3 -8
package/lib/client.js
CHANGED
|
@@ -56,7 +56,7 @@ window.__ModuleLoader__.load({
|
|
|
56
56
|
}
|
|
57
57
|
//#endregion
|
|
58
58
|
//#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-settings-models/src/client/ModelsSection.module.css.mjs
|
|
59
|
-
const css$3 = ".zGbnIq_section{max-width:720px;color:var(--dsw-alias-label-primary);flex-direction:column;gap:12px;display:flex}.zGbnIq_title{color:var(--dsw-alias-label-primary);margin:0;font-size:16px;font-weight:500;line-height:24px}.zGbnIq_intro{color:var(--dsw-alias-label-tertiary);margin:0;font-size:14px;line-height:22px}.zGbnIq_notice{color:var(--dsw-alias-state-warn-label);margin:0;font-size:12px;line-height:18px}.zGbnIq_savedNotice{color:var(--dsw-alias-state-success-primary);margin:0;font-size:12px;line-height:18px}.zGbnIq_rows{flex-direction:column;gap:8px;margin:12px 0 0;padding:0;list-style:none;display:flex}.zGbnIq_rowCard{border:.5px solid var(--dsw-alias-border-l4);border-radius:16px;flex-direction:column;gap:12px;padding:12px 14px;display:flex}.zGbnIq_rowHead{align-items:center;gap:10px;display:flex}.zGbnIq_rowIdentity{align-items:center;gap:6px;min-width:0;display:inline-flex}.zGbnIq_rowName{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:500;line-height:22px}.zGbnIq_rowTag{border:.5px solid var(--dsw-alias-border-l3);color:var(--dsw-alias-label-secondary);border-radius:4px;flex:none;padding:1px 6px;font-size:11px;line-height:16px}.zGbnIq_credentialDot{box-sizing:border-box;corner-shape:round;border-radius:50%;flex:none;width:8px;height:8px;display:inline-block}.zGbnIq_credentialDotConfigured{background:var(--dsw-alias-state-success-primary)}.zGbnIq_credentialDotMissing{background:var(--dsw-alias-state-error-primary)}.zGbnIq_rowActions{align-items:center;gap:4px;margin-left:auto;display:inline-flex}.zGbnIq_primaryButton,.zGbnIq_secondaryButton,.zGbnIq_addButton{box-sizing:border-box;height:36px;font:inherit;cursor:pointer;border:none;border-radius:18px;justify-content:center;align-items:center;gap:4px;padding:0 14px;font-size:14px;line-height:22px;display:inline-flex}.zGbnIq_primaryButton{background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-foreground)}.zGbnIq_primaryButton:hover:not(:disabled){background:var(--dsw-alias-button-primary-hover)}.zGbnIq_secondaryButton,.zGbnIq_addButton{border:.5px solid var(--dsw-alias-border-l3);color:var(--dsw-alias-label-primary);background:0 0}.zGbnIq_secondaryButton:hover:not(:disabled),.zGbnIq_addButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.zGbnIq_secondaryButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-solid)}.zGbnIq_dangerButton{box-sizing:border-box;height:36px;color:var(--dsw-alias-state-error-primary);font:inherit;cursor:pointer;background:0 0;border:none;border-radius:18px;justify-content:center;align-items:center;padding:0 14px;font-size:14px;line-height:22px;display:inline-flex}.zGbnIq_dangerButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger)}.zGbnIq_rowActions .zGbnIq_secondaryButton,.zGbnIq_rowActions .zGbnIq_dangerButton{border-radius:14px;height:28px;padding:0 10px;font-size:12px;line-height:18px}.zGbnIq_primaryButton:disabled,.zGbnIq_secondaryButton:disabled,.zGbnIq_dangerButton:disabled,.zGbnIq_addButton:disabled,.zGbnIq_linkButton:disabled,.zGbnIq_addModelButton:disabled{opacity:.4;cursor:default}.zGbnIq_primaryButton:focus-visible,.zGbnIq_secondaryButton:focus-visible,.zGbnIq_dangerButton:focus-visible,.zGbnIq_addButton:focus-visible,.zGbnIq_linkButton:focus-visible,.zGbnIq_addModelButton:focus-visible,.zGbnIq_iconButton:focus-visible,.zGbnIq_customizedSummary:focus-visible{box-shadow:0 0 0 2px var(--dsw-alias-border-l3);outline:none}.zGbnIq_editor{background:var(--dsw-alias-bg-module-platform);border-radius:12px;flex-direction:column;gap:14px;padding:14px 16px;display:flex}.zGbnIq_editorHeader{align-items:baseline;gap:8px;display:flex}.zGbnIq_editorTitle{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:500;line-height:22px}.zGbnIq_editorRoute{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}.zGbnIq_field{flex-direction:column;gap:6px;display:flex}.zGbnIq_fieldLabel{color:var(--dsw-alias-label-secondary);align-items:center;gap:10px;font-size:12px;font-weight:500;line-height:18px;display:inline-flex}.zGbnIq_linkButton{box-sizing:border-box;height:28px;color:var(--dsw-alias-label-tertiary);font:inherit;cursor:pointer;background:0 0;border:none;border-radius:14px;align-items:center;padding:0 10px;font-size:12px;line-height:18px;display:inline-flex}.zGbnIq_linkButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-secondary)}.zGbnIq_advancedHint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}.zGbnIq_editorActions{justify-content:flex-end;gap:8px;display:flex}.zGbnIq_addBlock{flex-direction:column;gap:12px;display:flex}.zGbnIq_addActions{flex-wrap:wrap;gap:10px;display:flex}.zGbnIq_addButton{border:1px dashed var(--dsw-alias-border-l3);border-radius:16px;flex:1 1 0;gap:6px;min-width:180px;height:44px}.zGbnIq_addCard,.zGbnIq_setupCard{background:var(--dsw-alias-bg-module-platform);border-radius:12px;flex-direction:column;gap:14px;padding:14px 16px;list-style:none;display:flex}.zGbnIq_addCard .zGbnIq_editor,.zGbnIq_setupCard .zGbnIq_editor{background:0 0;padding:0}.zGbnIq_customized{border-top:.5px solid var(--dsw-alias-border-l2);padding-top:10px}.zGbnIq_customizedSummary{cursor:pointer;width:fit-content;color:var(--dsw-alias-label-secondary);border-radius:6px;align-items:center;gap:6px;margin-left:-4px;padding:2px 4px;font-size:12px;font-weight:500;line-height:18px;list-style:none;display:flex}.zGbnIq_customizedSummary::-webkit-details-marker{display:none}.zGbnIq_customizedSummary:before{content:\"\";border-bottom:1.5px solid;border-right:1.5px solid;width:5px;height:5px;transition:transform .12s;transform:rotate(-45deg)translate(-1px,-1px)}.zGbnIq_customized[open]>.zGbnIq_customizedSummary:before{transform:rotate(45deg)translate(-1px,-1px)}.zGbnIq_customizedSummary:hover{color:var(--dsw-alias-label-primary)}.zGbnIq_customizedBody{flex-direction:column;gap:12px;padding-top:12px;display:flex}.zGbnIq_modelCatalog{border-top:.5px solid var(--dsw-alias-border-l2);flex-direction:column;gap:10px;padding-top:12px;display:flex}.zGbnIq_modelCatalogHeading{flex-direction:column;gap:2px;display:flex}.zGbnIq_modelCatalogTitle{color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:500;line-height:18px}.zGbnIq_modelCatalogMeta,.zGbnIq_modelEmpty{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}.zGbnIq_modelList{flex-direction:column;gap:8px;display:flex}.zGbnIq_modelListHead{justify-content:space-between;align-items:flex-start;gap:12px;display:flex}.zGbnIq_modelEntry{border:.5px solid var(--dsw-alias-border-l4);border-radius:10px;padding:6px}.zGbnIq_modelRow{grid-template-columns:minmax(0,1.4fr) minmax(0,1fr) auto auto;align-items:center;gap:6px;display:grid}.zGbnIq_iconButton{box-sizing:border-box;width:28px;height:28px;color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:none;border-radius:6px;justify-content:center;align-items:center;display:inline-flex}.zGbnIq_iconButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.zGbnIq_iconButton:disabled{cursor:default;opacity:.4}.zGbnIq_iconButtonDanger:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger);color:var(--dsw-alias-state-error-primary)}.zGbnIq_modelAdvanced{grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:8px;padding:8px 4px 2px;display:grid}.zGbnIq_modelField{flex-direction:column;gap:4px;display:flex}.zGbnIq_modelFieldLabel{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}.zGbnIq_modelEmpty{border:1px dashed var(--dsw-alias-border-l3);text-align:center;border-radius:8px;padding:12px}.zGbnIq_addModelButton{box-sizing:border-box;border:.5px solid var(--dsw-alias-border-l3);height:28px;color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;background:0 0;border-radius:14px;align-self:flex-start;align-items:center;gap:4px;padding:0 10px;font-size:12px;line-height:18px;display:inline-flex}.zGbnIq_addModelButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.zGbnIq_input{box-sizing:border-box;border:.5px solid var(--dsw-alias-border-l4);width:100%;height:32px;font:inherit;background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);border-radius:8px;padding:0 10px;font-size:14px;line-height:22px}select.zGbnIq_input{cursor:pointer;max-width:240px}.zGbnIq_input:focus{border-color:var(--dsw-alias-brand-primary);outline:none}.zGbnIq_input::placeholder{color:var(--dsw-alias-label-dimmed)}.zGbnIq_input:disabled{opacity:.6;cursor:default}.zGbnIq_selectInput{appearance:none;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12' fill='none'%3E%3Cpath d='M3 4.5L6 7.5L9 4.5' stroke='%2381858C' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\");background-position:right 12px center;background-repeat:no-repeat;background-size:12px 12px;padding-right:32px}.zGbnIq_error{color:var(--dsw-alias-state-error-primary);margin:0;font-size:12px;line-height:18px}.zGbnIq_deleteDialog{width:min(480px,100%)}.zGbnIq_deleteConfirm:not(:disabled){border-color:var(--dsw-alias-state-error-primary);color:var(--dsw-alias-state-error-primary)}.zGbnIq_deleteConfirm:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger)}.zGbnIq_hiddenLabel{clip:rect(0 0 0 0);white-space:nowrap;width:1px;height:1px;position:absolute;overflow:hidden}@media (prefers-reduced-motion:reduce){.zGbnIq_customizedSummary:before,.zGbnIq_switchThumb{transition:none}}.zGbnIq_fetchDialog{--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);max-width:520px}.zGbnIq_candidateToolbar{align-items:center;gap:8px;margin-bottom:6px;display:flex}.zGbnIq_candidateSearch{flex:240px;min-width:0}.zGbnIq_candidateList{flex-direction:column;gap:2px;max-height:320px;margin:0;padding:0;list-style:none;display:flex;overflow-y:auto}.zGbnIq_candidate{border-radius:6px}.zGbnIq_candidateLabel{cursor:pointer;align-items:center;gap:8px;padding:6px 8px;display:flex}.zGbnIq_candidateId{font-family:var(--ds-font-family-code);overflow-wrap:anywhere;flex:auto;font-size:13px}.zGbnIq_candidateEmpty{color:var(--dsw-alias-label-secondary);text-align:center;margin:24px 0;font-size:13px;line-height:20px}";
|
|
59
|
+
const css$3 = ".zGbnIq_section{max-width:720px;color:var(--dsw-alias-label-primary);flex-direction:column;gap:12px;display:flex}.zGbnIq_title{color:var(--dsw-alias-label-primary);margin:0;font-size:16px;font-weight:500;line-height:24px}.zGbnIq_intro{color:var(--dsw-alias-label-tertiary);margin:0;font-size:14px;line-height:22px}.zGbnIq_notice{color:var(--dsw-alias-state-warn-label);margin:0;font-size:12px;line-height:18px}.zGbnIq_savedNotice{color:var(--dsw-alias-state-success-primary);margin:0;font-size:12px;line-height:18px}.zGbnIq_rows{flex-direction:column;gap:8px;margin:12px 0 0;padding:0;list-style:none;display:flex}.zGbnIq_rowCard{border:.5px solid var(--dsw-alias-border-l4);border-radius:16px;flex-direction:column;gap:12px;padding:12px 14px;display:flex}.zGbnIq_rowHead{align-items:center;gap:10px;display:flex}.zGbnIq_rowIdentity{align-items:center;gap:6px;min-width:0;display:inline-flex}.zGbnIq_rowName{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:500;line-height:22px}.zGbnIq_rowTag{border:.5px solid var(--dsw-alias-border-l3);color:var(--dsw-alias-label-secondary);border-radius:4px;flex:none;padding:1px 6px;font-size:11px;line-height:16px}.zGbnIq_credentialDot{box-sizing:border-box;corner-shape:round;border-radius:50%;flex:none;width:8px;height:8px;display:inline-block}.zGbnIq_credentialDotConfigured{background:var(--dsw-alias-state-success-primary)}.zGbnIq_credentialDotMissing{background:var(--dsw-alias-state-error-primary)}.zGbnIq_rowActions{align-items:center;gap:4px;margin-left:auto;display:inline-flex}.zGbnIq_primaryButton,.zGbnIq_secondaryButton,.zGbnIq_addButton{box-sizing:border-box;height:36px;font:inherit;cursor:pointer;border:none;border-radius:18px;justify-content:center;align-items:center;gap:4px;padding:0 14px;font-size:14px;line-height:22px;display:inline-flex}.zGbnIq_primaryButton{background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-foreground)}.zGbnIq_primaryButton:hover:not(:disabled){background:var(--dsw-alias-button-primary-hover)}.zGbnIq_secondaryButton,.zGbnIq_addButton{border:.5px solid var(--dsw-alias-border-l3);color:var(--dsw-alias-label-primary);background:0 0}.zGbnIq_secondaryButton:hover:not(:disabled),.zGbnIq_addButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.zGbnIq_secondaryButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-solid)}.zGbnIq_dangerButton{box-sizing:border-box;height:36px;color:var(--dsw-alias-state-error-primary);font:inherit;cursor:pointer;background:0 0;border:none;border-radius:18px;justify-content:center;align-items:center;padding:0 14px;font-size:14px;line-height:22px;display:inline-flex}.zGbnIq_dangerButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger)}.zGbnIq_rowActions .zGbnIq_secondaryButton,.zGbnIq_rowActions .zGbnIq_dangerButton{border-radius:14px;height:28px;padding:0 10px;font-size:12px;line-height:18px}.zGbnIq_primaryButton:disabled,.zGbnIq_secondaryButton:disabled,.zGbnIq_dangerButton:disabled,.zGbnIq_addButton:disabled,.zGbnIq_linkButton:disabled,.zGbnIq_addModelButton:disabled{opacity:.4;cursor:default}.zGbnIq_primaryButton:focus-visible,.zGbnIq_secondaryButton:focus-visible,.zGbnIq_dangerButton:focus-visible,.zGbnIq_addButton:focus-visible,.zGbnIq_linkButton:focus-visible,.zGbnIq_addModelButton:focus-visible,.zGbnIq_iconButton:focus-visible,.zGbnIq_customizedSummary:focus-visible{box-shadow:0 0 0 2px var(--dsw-alias-border-l3);outline:none}.zGbnIq_editor{background:var(--dsw-alias-bg-module-platform);border-radius:12px;flex-direction:column;gap:14px;padding:14px 16px;display:flex}.zGbnIq_editorHeader{align-items:baseline;gap:8px;display:flex}.zGbnIq_editorTitle{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:500;line-height:22px}.zGbnIq_editorRoute{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}.zGbnIq_field{flex-direction:column;gap:6px;display:flex}.zGbnIq_fieldLabel{color:var(--dsw-alias-label-secondary);align-items:center;gap:10px;font-size:12px;font-weight:500;line-height:18px;display:inline-flex}.zGbnIq_linkButton{box-sizing:border-box;height:28px;color:var(--dsw-alias-label-tertiary);font:inherit;cursor:pointer;background:0 0;border:none;border-radius:14px;align-items:center;padding:0 10px;font-size:12px;line-height:18px;display:inline-flex}.zGbnIq_linkButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-secondary)}.zGbnIq_advancedHint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}.zGbnIq_editorActions{justify-content:flex-end;gap:8px;display:flex}.zGbnIq_addBlock{flex-direction:column;gap:12px;display:flex}.zGbnIq_addActions{display:flex}.zGbnIq_addButton{border:1px dashed var(--dsw-alias-border-l3);border-radius:16px;flex:1 1 0;gap:6px;min-width:180px;height:44px}.zGbnIq_addModes{flex-direction:column;align-items:flex-start;gap:8px;display:flex}.zGbnIq_addPanel{flex-direction:column;gap:14px;display:flex}.zGbnIq_addPanel[hidden]{display:none}.zGbnIq_addCard,.zGbnIq_setupCard{background:var(--dsw-alias-bg-module-platform);border-radius:12px;flex-direction:column;gap:14px;padding:14px 16px;list-style:none;display:flex}.zGbnIq_addCard .zGbnIq_editor,.zGbnIq_setupCard .zGbnIq_editor{background:0 0;padding:0}.zGbnIq_customized{border-top:.5px solid var(--dsw-alias-border-l2);padding-top:10px}.zGbnIq_customizedSummary{cursor:pointer;width:fit-content;color:var(--dsw-alias-label-secondary);border-radius:6px;align-items:center;gap:6px;margin-left:-4px;padding:2px 4px;font-size:12px;font-weight:500;line-height:18px;list-style:none;display:flex}.zGbnIq_customizedSummary::-webkit-details-marker{display:none}.zGbnIq_customizedSummary:before{content:\"\";border-bottom:1.5px solid;border-right:1.5px solid;width:5px;height:5px;transition:transform .12s;transform:rotate(-45deg)translate(-1px,-1px)}.zGbnIq_customized[open]>.zGbnIq_customizedSummary:before{transform:rotate(45deg)translate(-1px,-1px)}.zGbnIq_customizedSummary:hover{color:var(--dsw-alias-label-primary)}.zGbnIq_customizedBody{flex-direction:column;gap:12px;padding-top:12px;display:flex}.zGbnIq_modelCatalog{border-top:.5px solid var(--dsw-alias-border-l2);flex-direction:column;gap:10px;padding-top:12px;display:flex}.zGbnIq_modelCatalogHeading{flex-direction:column;gap:2px;display:flex}.zGbnIq_modelCatalogTitle{color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:500;line-height:18px}.zGbnIq_modelCatalogMeta,.zGbnIq_modelEmpty{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}.zGbnIq_modelList{flex-direction:column;gap:8px;display:flex}.zGbnIq_modelListHead{justify-content:space-between;align-items:flex-start;gap:12px;display:flex}.zGbnIq_modelEntry{border:.5px solid var(--dsw-alias-border-l4);border-radius:10px;padding:6px}.zGbnIq_modelRow{grid-template-columns:minmax(0,1.4fr) minmax(0,1fr) auto auto;align-items:center;gap:6px;display:grid}.zGbnIq_iconButton{box-sizing:border-box;width:28px;height:28px;color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:none;border-radius:6px;justify-content:center;align-items:center;display:inline-flex}.zGbnIq_iconButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.zGbnIq_iconButton:disabled{cursor:default;opacity:.4}.zGbnIq_iconButtonDanger:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger);color:var(--dsw-alias-state-error-primary)}.zGbnIq_modelAdvanced{grid-template-columns:repeat(2,minmax(0,1fr));gap:8px;padding:8px 4px 2px;display:grid}.zGbnIq_modelField{flex-direction:column;gap:4px;min-width:0;display:flex}.zGbnIq_modelInputTypes{border:none;grid-column:1/-1;min-width:0;margin:0;padding:0}.zGbnIq_modelInputTypes legend{margin-bottom:4px;padding:0}.zGbnIq_modelInputChoices{flex-wrap:wrap;align-items:center;gap:16px;min-height:32px;display:flex}.zGbnIq_modelFieldLabel{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}.zGbnIq_modelEmpty{border:1px dashed var(--dsw-alias-border-l3);text-align:center;border-radius:8px;padding:12px}.zGbnIq_addModelButton{box-sizing:border-box;border:.5px solid var(--dsw-alias-border-l3);height:28px;color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;background:0 0;border-radius:14px;align-self:flex-start;align-items:center;gap:4px;padding:0 10px;font-size:12px;line-height:18px;display:inline-flex}.zGbnIq_addModelButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.zGbnIq_input{box-sizing:border-box;border:.5px solid var(--dsw-alias-border-l4);width:100%;height:32px;font:inherit;background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);border-radius:8px;padding:0 10px;font-size:14px;line-height:22px}select.zGbnIq_input{cursor:pointer;max-width:240px}.zGbnIq_input:focus{border-color:var(--dsw-alias-brand-primary);outline:none}.zGbnIq_input::placeholder{color:var(--dsw-alias-label-dimmed)}.zGbnIq_input:disabled{opacity:.6;cursor:default}.zGbnIq_selectInput{appearance:none;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12' fill='none'%3E%3Cpath d='M3 4.5L6 7.5L9 4.5' stroke='%2381858C' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\");background-position:right 12px center;background-repeat:no-repeat;background-size:12px 12px;padding-right:32px}.zGbnIq_error{color:var(--dsw-alias-state-error-primary);margin:0;font-size:12px;line-height:18px}.zGbnIq_deleteDialog{width:min(480px,100%)}.zGbnIq_deleteConfirm:not(:disabled){border-color:var(--dsw-alias-state-error-primary);color:var(--dsw-alias-state-error-primary)}.zGbnIq_deleteConfirm:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger)}.zGbnIq_hiddenLabel{clip:rect(0 0 0 0);white-space:nowrap;width:1px;height:1px;position:absolute;overflow:hidden}@media (prefers-reduced-motion:reduce){.zGbnIq_customizedSummary:before,.zGbnIq_switchThumb{transition:none}}.zGbnIq_fetchDialog{--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);max-width:520px}.zGbnIq_candidateToolbar{align-items:center;gap:8px;margin-bottom:6px;display:flex}.zGbnIq_candidateSearch{flex:240px;min-width:0}.zGbnIq_candidateList{flex-direction:column;gap:2px;max-height:320px;margin:0;padding:0;list-style:none;display:flex;overflow-y:auto}.zGbnIq_candidate{border-radius:6px}.zGbnIq_candidateLabel{cursor:pointer;align-items:center;gap:8px;padding:6px 8px;display:flex}.zGbnIq_candidateName{text-overflow:ellipsis;white-space:nowrap;flex:auto;min-width:0;font-size:13px;overflow:hidden}.zGbnIq_candidateEmpty{color:var(--dsw-alias-label-secondary);text-align:center;margin:24px 0;font-size:13px;line-height:20px}";
|
|
60
60
|
const tagId$3 = "@mofeng2223/dsh-claude-provider/ModelsSection.module.css";
|
|
61
61
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$3) + "]") === null) {
|
|
62
62
|
const tag = document.createElement("style");
|
|
@@ -71,12 +71,14 @@ window.__ModuleLoader__.load({
|
|
|
71
71
|
"addButton": "zGbnIq_addButton",
|
|
72
72
|
"addCard": "zGbnIq_addCard",
|
|
73
73
|
"addModelButton": "zGbnIq_addModelButton",
|
|
74
|
+
"addModes": "zGbnIq_addModes",
|
|
75
|
+
"addPanel": "zGbnIq_addPanel",
|
|
74
76
|
"advancedHint": "zGbnIq_advancedHint",
|
|
75
77
|
"candidate": "zGbnIq_candidate",
|
|
76
78
|
"candidateEmpty": "zGbnIq_candidateEmpty",
|
|
77
|
-
"candidateId": "zGbnIq_candidateId",
|
|
78
79
|
"candidateLabel": "zGbnIq_candidateLabel",
|
|
79
80
|
"candidateList": "zGbnIq_candidateList",
|
|
81
|
+
"candidateName": "zGbnIq_candidateName",
|
|
80
82
|
"candidateSearch": "zGbnIq_candidateSearch",
|
|
81
83
|
"candidateToolbar": "zGbnIq_candidateToolbar",
|
|
82
84
|
"credentialDot": "zGbnIq_credentialDot",
|
|
@@ -112,6 +114,8 @@ window.__ModuleLoader__.load({
|
|
|
112
114
|
"modelEntry": "zGbnIq_modelEntry",
|
|
113
115
|
"modelField": "zGbnIq_modelField",
|
|
114
116
|
"modelFieldLabel": "zGbnIq_modelFieldLabel",
|
|
117
|
+
"modelInputChoices": "zGbnIq_modelInputChoices",
|
|
118
|
+
"modelInputTypes": "zGbnIq_modelInputTypes",
|
|
115
119
|
"modelList": "zGbnIq_modelList",
|
|
116
120
|
"modelListHead": "zGbnIq_modelListHead",
|
|
117
121
|
"modelRow": "zGbnIq_modelRow",
|
|
@@ -159,6 +163,132 @@ window.__ModuleLoader__.load({
|
|
|
159
163
|
});
|
|
160
164
|
}
|
|
161
165
|
//#endregion
|
|
166
|
+
//#region lib/types/client/ModelInputTypes.js
|
|
167
|
+
/**
|
|
168
|
+
* Edit a nonempty set of input types, displaying inherited types before an override exists.
|
|
169
|
+
* @param props - model declaration and row replacement action.
|
|
170
|
+
* @returns the labeled text and image checkboxes.
|
|
171
|
+
*/
|
|
172
|
+
function ModelInputTypes({ model, field, position, disabled, fallback, t, onChange }) {
|
|
173
|
+
const modalities = model[field];
|
|
174
|
+
const selected = Array.isArray(modalities) && modalities.length > 0 ? modalities : fallback ?? ["text"];
|
|
175
|
+
return (0, react_jsx_runtime.jsxs)("fieldset", {
|
|
176
|
+
className: ModelsSection_module_css_default["modelInputTypes"],
|
|
177
|
+
"aria-label": `${t("modelInputTypes")} ${String(position)}`,
|
|
178
|
+
children: [(0, react_jsx_runtime.jsx)("legend", {
|
|
179
|
+
className: ModelsSection_module_css_default["modelFieldLabel"],
|
|
180
|
+
children: t("modelInputTypes")
|
|
181
|
+
}), (0, react_jsx_runtime.jsx)("div", {
|
|
182
|
+
className: ModelsSection_module_css_default["modelInputChoices"],
|
|
183
|
+
children: ["text", "image"].map((modality) => (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Checkbox, {
|
|
184
|
+
label: t(modality === "text" ? "modelInputText" : "modelInputImage"),
|
|
185
|
+
checked: selected.includes(modality),
|
|
186
|
+
disabled: disabled || selected.length === 1 && selected.includes(modality),
|
|
187
|
+
onChange: (checked) => {
|
|
188
|
+
const nextSelected = ["text", "image"].filter((value) => value === modality ? checked : selected.includes(value));
|
|
189
|
+
const next = {
|
|
190
|
+
...model,
|
|
191
|
+
[field]: nextSelected
|
|
192
|
+
};
|
|
193
|
+
if (field === "inputModalities" && !nextSelected.includes("image")) {
|
|
194
|
+
Reflect.deleteProperty(next, "imagePixelBudget");
|
|
195
|
+
Reflect.deleteProperty(next, "imageMaxBytes");
|
|
196
|
+
}
|
|
197
|
+
onChange(next);
|
|
198
|
+
}
|
|
199
|
+
}, modality))
|
|
200
|
+
})]
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
//#endregion
|
|
204
|
+
//#region lib/types/client/ModelRow.js
|
|
205
|
+
/**
|
|
206
|
+
* Render consistent model identity, capacity, and input-type controls.
|
|
207
|
+
* @param props - drafted fields and their owning editor's actions.
|
|
208
|
+
* @returns one expandable model entry.
|
|
209
|
+
*/
|
|
210
|
+
function ModelRow(props) {
|
|
211
|
+
const { model, position, t, disabled } = props;
|
|
212
|
+
return (0, react_jsx_runtime.jsxs)("div", {
|
|
213
|
+
className: ModelsSection_module_css_default["modelEntry"],
|
|
214
|
+
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
215
|
+
className: ModelsSection_module_css_default["modelRow"],
|
|
216
|
+
children: [
|
|
217
|
+
["id", "name"].map((field) => (0, react_jsx_runtime.jsx)("input", {
|
|
218
|
+
className: ModelsSection_module_css_default["input"],
|
|
219
|
+
type: "text",
|
|
220
|
+
value: typeof model[field] === "string" ? model[field] : "",
|
|
221
|
+
placeholder: t(field === "id" ? "modelId" : "modelName"),
|
|
222
|
+
"aria-label": `${t(field === "id" ? "modelId" : "modelName")} ${String(position)}`,
|
|
223
|
+
disabled,
|
|
224
|
+
onChange: (event) => {
|
|
225
|
+
const value = event.target.value;
|
|
226
|
+
props.onFieldChange(field, field === "name" && value === "" ? void 0 : value);
|
|
227
|
+
},
|
|
228
|
+
onBlur: field === "id" ? (event) => props.onIdBlur?.(event.target.value) : void 0
|
|
229
|
+
}, field)),
|
|
230
|
+
(0, react_jsx_runtime.jsx)("button", {
|
|
231
|
+
type: "button",
|
|
232
|
+
className: ModelsSection_module_css_default["iconButton"],
|
|
233
|
+
"aria-label": `${t("modelAdvanced")} ${String(position)}`,
|
|
234
|
+
"aria-expanded": props.expanded,
|
|
235
|
+
title: t("modelAdvanced"),
|
|
236
|
+
onClick: props.onToggle,
|
|
237
|
+
children: props.expanded ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutlineRegular, {}) : (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronRightOutlineRegular, {})
|
|
238
|
+
}),
|
|
239
|
+
(0, react_jsx_runtime.jsx)("button", {
|
|
240
|
+
type: "button",
|
|
241
|
+
className: `${ModelsSection_module_css_default["iconButton"]} ${ModelsSection_module_css_default["iconButtonDanger"]}`,
|
|
242
|
+
"aria-label": `${t("removeModel")} ${String(position)}`,
|
|
243
|
+
title: t("removeModel"),
|
|
244
|
+
disabled,
|
|
245
|
+
onClick: props.onRemove,
|
|
246
|
+
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutlineRegular, { size: 14 })
|
|
247
|
+
})
|
|
248
|
+
]
|
|
249
|
+
}), props.expanded ? (0, react_jsx_runtime.jsxs)("div", {
|
|
250
|
+
className: ModelsSection_module_css_default["modelAdvanced"],
|
|
251
|
+
children: [["contextWindow", "maxTokens"].map((field) => (0, react_jsx_runtime.jsxs)("label", {
|
|
252
|
+
className: ModelsSection_module_css_default["modelField"],
|
|
253
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
254
|
+
className: ModelsSection_module_css_default["modelFieldLabel"],
|
|
255
|
+
children: t(field)
|
|
256
|
+
}), (0, react_jsx_runtime.jsx)("input", {
|
|
257
|
+
className: ModelsSection_module_css_default["input"],
|
|
258
|
+
type: "text",
|
|
259
|
+
inputMode: "numeric",
|
|
260
|
+
value: props[field].value,
|
|
261
|
+
placeholder: props[field].placeholder,
|
|
262
|
+
"aria-label": `${t(field)} ${String(position)}`,
|
|
263
|
+
disabled,
|
|
264
|
+
onChange: (event) => {
|
|
265
|
+
props[field].onChange(event.target.value);
|
|
266
|
+
},
|
|
267
|
+
onBlur: props[field].onBlur
|
|
268
|
+
})]
|
|
269
|
+
}, field)), (0, react_jsx_runtime.jsx)(ModelInputTypes, {
|
|
270
|
+
model,
|
|
271
|
+
field: props.inputField,
|
|
272
|
+
position,
|
|
273
|
+
fallback: props.inputFallback,
|
|
274
|
+
disabled: disabled || props.inputLoading === true,
|
|
275
|
+
t,
|
|
276
|
+
onChange: props.onChange
|
|
277
|
+
}), props.thinkingPresets ? (0, react_jsx_runtime.jsxs)("label", {
|
|
278
|
+
className: ModelsSection_module_css_default["modelField"],
|
|
279
|
+
children: [t("thinkingPreset"), (0, react_jsx_runtime.jsxs)("select", {
|
|
280
|
+
className: ModelsSection_module_css_default["input"] + " " + ModelsSection_module_css_default["selectInput"],
|
|
281
|
+
value: thinkingPresetOf(model),
|
|
282
|
+
"aria-label": t("thinkingPreset") + " " + position,
|
|
283
|
+
disabled,
|
|
284
|
+
onChange: (event) => props.onChange({ ...model, reasoningEfforts: reasoningEffortsForPreset(event.target.value) }),
|
|
285
|
+
children: ["toggle", "four", "five"].map((preset) => (0, react_jsx_runtime.jsx)("option", { value: preset, children: t({ toggle: "thinkingPresetToggle", four: "thinkingPresetFour", five: "thinkingPresetFive" }[preset]) }, preset))
|
|
286
|
+
})]
|
|
287
|
+
}) : null]
|
|
288
|
+
}) : null]
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
//#endregion
|
|
162
292
|
//#region lib/types/client/DeepSeekModelsEditor.js
|
|
163
293
|
/**
|
|
164
294
|
* Curated editor for the direct DeepSeek adapter's advisory model catalog.
|
|
@@ -253,7 +383,7 @@ window.__ModuleLoader__.load({
|
|
|
253
383
|
}
|
|
254
384
|
/**
|
|
255
385
|
* Render the direct DeepSeek adapter's model catalog: id and display name on
|
|
256
|
-
* each row, capacities behind the row's own disclosure.
|
|
386
|
+
* each row, capacities and input types behind the row's own disclosure.
|
|
257
387
|
* @param props - effective rows plus the array-level override actions.
|
|
258
388
|
* @returns the catalog editor.
|
|
259
389
|
*/
|
|
@@ -321,29 +451,16 @@ window.__ModuleLoader__.load({
|
|
|
321
451
|
return next;
|
|
322
452
|
});
|
|
323
453
|
};
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
value: capacityText(model, index, field),
|
|
335
|
-
placeholder: fallback === void 0 ? props.t(field === "contextWindow" ? "contextWindowPlaceholder" : "maxTokensPlaceholder") : formatCapacity(fallback),
|
|
336
|
-
"aria-label": `${props.t(field === "contextWindow" ? "contextWindow" : "maxTokens")} ${String(index + 1)}`,
|
|
337
|
-
disabled: props.disabled,
|
|
338
|
-
onChange: (event) => {
|
|
339
|
-
const text = event.target.value;
|
|
340
|
-
setEditing((current) => new Map(current).set(`${String(index)}:${field}`, text));
|
|
341
|
-
update(index, field, parseCapacity(text));
|
|
342
|
-
},
|
|
343
|
-
onBlur: () => {
|
|
344
|
-
settleCapacity(index, field);
|
|
345
|
-
}
|
|
346
|
-
})]
|
|
454
|
+
const capacityInput = (model, index, field, fallback) => ({
|
|
455
|
+
value: capacityText(model, index, field),
|
|
456
|
+
placeholder: fallback === void 0 ? props.t(field === "contextWindow" ? "contextWindowPlaceholder" : "maxTokensPlaceholder") : formatCapacity(fallback),
|
|
457
|
+
onChange: (text) => {
|
|
458
|
+
setEditing((current) => new Map(current).set(`${String(index)}:${field}`, text));
|
|
459
|
+
update(index, field, parseCapacity(text));
|
|
460
|
+
},
|
|
461
|
+
onBlur: () => {
|
|
462
|
+
settleCapacity(index, field);
|
|
463
|
+
}
|
|
347
464
|
});
|
|
348
465
|
return (0, react_jsx_runtime.jsxs)("section", {
|
|
349
466
|
className: ModelsSection_module_css_default["modelCatalog"],
|
|
@@ -373,64 +490,31 @@ window.__ModuleLoader__.load({
|
|
|
373
490
|
children: props.t("modelsEmpty")
|
|
374
491
|
}) : (0, react_jsx_runtime.jsx)("div", {
|
|
375
492
|
className: ModelsSection_module_css_default["modelList"],
|
|
376
|
-
children: props.models.map((model, index) => (0, react_jsx_runtime.
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
"aria-label": `${props.t("modelName")} ${String(index + 1)}`,
|
|
402
|
-
disabled: props.disabled,
|
|
403
|
-
onChange: (event) => {
|
|
404
|
-
update(index, "name", event.target.value === "" ? void 0 : event.target.value);
|
|
405
|
-
}
|
|
406
|
-
}),
|
|
407
|
-
(0, react_jsx_runtime.jsx)("button", {
|
|
408
|
-
type: "button",
|
|
409
|
-
className: ModelsSection_module_css_default["iconButton"],
|
|
410
|
-
"aria-label": `${props.t("modelAdvanced")} ${String(index + 1)}`,
|
|
411
|
-
"aria-expanded": expanded.has(index),
|
|
412
|
-
title: props.t("modelAdvanced"),
|
|
413
|
-
onClick: () => {
|
|
414
|
-
toggle(index);
|
|
415
|
-
},
|
|
416
|
-
children: expanded.has(index) ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, {}) : (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronRightOutline14, {})
|
|
417
|
-
}),
|
|
418
|
-
(0, react_jsx_runtime.jsx)("button", {
|
|
419
|
-
type: "button",
|
|
420
|
-
className: `${ModelsSection_module_css_default["iconButton"]} ${ModelsSection_module_css_default["iconButtonDanger"]}`,
|
|
421
|
-
"aria-label": `${props.t("removeModel")} ${String(index + 1)}`,
|
|
422
|
-
title: props.t("removeModel"),
|
|
423
|
-
disabled: props.disabled,
|
|
424
|
-
onClick: () => {
|
|
425
|
-
remove(index);
|
|
426
|
-
},
|
|
427
|
-
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutline16, { size: 14 })
|
|
428
|
-
})
|
|
429
|
-
]
|
|
430
|
-
}), expanded.has(index) ? (0, react_jsx_runtime.jsxs)("div", {
|
|
431
|
-
className: ModelsSection_module_css_default["modelAdvanced"],
|
|
432
|
-
children: [capacityField(model, index, "contextWindow", props.defaultContextWindow), capacityField(model, index, "maxTokens", props.defaultMaxTokens)]
|
|
433
|
-
}) : null]
|
|
493
|
+
children: props.models.map((model, index) => (0, react_jsx_runtime.jsx)(ModelRow, {
|
|
494
|
+
model,
|
|
495
|
+
position: index + 1,
|
|
496
|
+
inputField: "inputModalities",
|
|
497
|
+
expanded: expanded.has(index),
|
|
498
|
+
disabled: props.disabled,
|
|
499
|
+
t: props.t,
|
|
500
|
+
contextWindow: capacityInput(model, index, "contextWindow", props.defaultContextWindow),
|
|
501
|
+
maxTokens: capacityInput(model, index, "maxTokens", props.defaultMaxTokens),
|
|
502
|
+
onFieldChange: (field, value) => {
|
|
503
|
+
update(index, field, value);
|
|
504
|
+
},
|
|
505
|
+
onIdBlur: (value) => {
|
|
506
|
+
const trimmed = value.trim();
|
|
507
|
+
if (trimmed !== value) update(index, "id", trimmed);
|
|
508
|
+
},
|
|
509
|
+
onChange: (next) => {
|
|
510
|
+
props.onChange(props.models.map((row, at) => at === index ? next : row));
|
|
511
|
+
},
|
|
512
|
+
onToggle: () => {
|
|
513
|
+
toggle(index);
|
|
514
|
+
},
|
|
515
|
+
onRemove: () => {
|
|
516
|
+
remove(index);
|
|
517
|
+
}
|
|
434
518
|
}, index))
|
|
435
519
|
}),
|
|
436
520
|
(0, react_jsx_runtime.jsxs)("button", {
|
|
@@ -440,7 +524,7 @@ window.__ModuleLoader__.load({
|
|
|
440
524
|
onClick: () => {
|
|
441
525
|
props.onChange([...props.models.map((model) => ({ ...model })), { id: "" }]);
|
|
442
526
|
},
|
|
443
|
-
children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
527
|
+
children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutlineRegular, { size: 14 }), props.t("addModel")]
|
|
444
528
|
})
|
|
445
529
|
]
|
|
446
530
|
});
|
|
@@ -472,44 +556,6 @@ window.__ModuleLoader__.load({
|
|
|
472
556
|
const value = model[key];
|
|
473
557
|
return typeof value === "number" ? value : void 0;
|
|
474
558
|
}
|
|
475
|
-
/** Disclosure chevron; rotates to point down while its row is open. */
|
|
476
|
-
function IconChevron({ open }) {
|
|
477
|
-
return (0, react_jsx_runtime.jsx)("svg", {
|
|
478
|
-
width: "14",
|
|
479
|
-
height: "14",
|
|
480
|
-
viewBox: "0 0 16 16",
|
|
481
|
-
fill: "none",
|
|
482
|
-
"aria-hidden": true,
|
|
483
|
-
style: {
|
|
484
|
-
transform: open ? "rotate(90deg)" : void 0,
|
|
485
|
-
transition: "transform 120ms ease"
|
|
486
|
-
},
|
|
487
|
-
children: (0, react_jsx_runtime.jsx)("path", {
|
|
488
|
-
d: "M6 3.5L10.5 8L6 12.5",
|
|
489
|
-
stroke: "currentColor",
|
|
490
|
-
strokeWidth: "1.5",
|
|
491
|
-
strokeLinecap: "round",
|
|
492
|
-
strokeLinejoin: "round"
|
|
493
|
-
})
|
|
494
|
-
});
|
|
495
|
-
}
|
|
496
|
-
/** Removal glyph for one model row. */
|
|
497
|
-
function IconTrash() {
|
|
498
|
-
return (0, react_jsx_runtime.jsx)("svg", {
|
|
499
|
-
width: "14",
|
|
500
|
-
height: "14",
|
|
501
|
-
viewBox: "0 0 16 16",
|
|
502
|
-
fill: "none",
|
|
503
|
-
"aria-hidden": true,
|
|
504
|
-
children: (0, react_jsx_runtime.jsx)("path", {
|
|
505
|
-
d: "M2.5 4h11M6.5 4V2.5h3V4M4 4l.7 9a1 1 0 001 .9h4.6a1 1 0 001-.9L12 4M6.5 6.8v4.4M9.5 6.8v4.4",
|
|
506
|
-
stroke: "currentColor",
|
|
507
|
-
strokeWidth: "1.3",
|
|
508
|
-
strokeLinecap: "round",
|
|
509
|
-
strokeLinejoin: "round"
|
|
510
|
-
})
|
|
511
|
-
});
|
|
512
|
-
}
|
|
513
559
|
/**
|
|
514
560
|
* What an empty capacity field is worth, shown as its placeholder so a row left
|
|
515
561
|
* blank does not read as a model with no capacity at all.
|
|
@@ -535,13 +581,14 @@ window.__ModuleLoader__.load({
|
|
|
535
581
|
function capacitySpelling(value) {
|
|
536
582
|
return value === void 0 ? "" : formatCapacity(value);
|
|
537
583
|
}
|
|
538
|
-
/** Adopt a candidate,
|
|
584
|
+
/** Adopt a candidate, preserving disclosed capacities and input types. */
|
|
539
585
|
function adopt(candidate) {
|
|
540
586
|
return {
|
|
541
587
|
id: candidate.id,
|
|
542
588
|
...candidate.name === void 0 ? {} : { name: candidate.name },
|
|
543
589
|
...candidate.contextWindow === void 0 ? {} : { contextWindow: candidate.contextWindow },
|
|
544
|
-
...candidate.maxTokens === void 0 ? {} : { maxTokens: candidate.maxTokens }
|
|
590
|
+
...candidate.maxTokens === void 0 ? {} : { maxTokens: candidate.maxTokens },
|
|
591
|
+
...candidate.inputModalities === void 0 ? {} : { input: [...candidate.inputModalities] }
|
|
545
592
|
};
|
|
546
593
|
}
|
|
547
594
|
/**
|
|
@@ -550,9 +597,35 @@ window.__ModuleLoader__.load({
|
|
|
550
597
|
* @returns the model-list editor.
|
|
551
598
|
*/
|
|
552
599
|
function ModelListEditor(props) {
|
|
553
|
-
const { models, onChange, probe, operations, t, disabled } = props;
|
|
600
|
+
const { models, onChange, probe, operations, t, disabled, onBusyChange } = props;
|
|
601
|
+
const { catalogProvider } = props;
|
|
554
602
|
const [busy, setBusy] = (0, react.useState)(false);
|
|
603
|
+
(0, react.useEffect)(() => {
|
|
604
|
+
onBusyChange(busy);
|
|
605
|
+
}, [busy, onBusyChange]);
|
|
555
606
|
const [failure, setFailure] = (0, react.useState)(void 0);
|
|
607
|
+
const [inheritedCatalog, setInheritedCatalog] = (0, react.useState)(void 0);
|
|
608
|
+
(0, react.useEffect)(() => {
|
|
609
|
+
if (catalogProvider === void 0) return;
|
|
610
|
+
let current = true;
|
|
611
|
+
operations.discoverModels(probe.settingsNs, { provider: catalogProvider }).then((answer) => {
|
|
612
|
+
if (!current) return;
|
|
613
|
+
setInheritedCatalog({
|
|
614
|
+
provider: catalogProvider,
|
|
615
|
+
models: answer.kind === "found" ? answer.models : []
|
|
616
|
+
});
|
|
617
|
+
setFailure(answer.kind === "refused" ? answer.message : void 0);
|
|
618
|
+
});
|
|
619
|
+
return () => {
|
|
620
|
+
current = false;
|
|
621
|
+
};
|
|
622
|
+
}, [
|
|
623
|
+
catalogProvider,
|
|
624
|
+
operations,
|
|
625
|
+
probe.settingsNs
|
|
626
|
+
]);
|
|
627
|
+
const catalog = inheritedCatalog?.provider === catalogProvider ? inheritedCatalog?.models : void 0;
|
|
628
|
+
const inputDefaults = (0, react.useMemo)(() => new Map(catalog?.map((model) => [model.id, model.inputModalities])), [catalog]);
|
|
556
629
|
const [candidates, setCandidates] = (0, react.useState)(void 0);
|
|
557
630
|
const [picked, setPicked] = (0, react.useState)(/* @__PURE__ */ new Set());
|
|
558
631
|
const [candidateQuery, setCandidateQuery] = (0, react.useState)("");
|
|
@@ -608,6 +681,10 @@ window.__ModuleLoader__.load({
|
|
|
608
681
|
return;
|
|
609
682
|
}
|
|
610
683
|
const found = answer.models;
|
|
684
|
+
if (catalogProvider !== void 0) setInheritedCatalog({
|
|
685
|
+
provider: catalogProvider,
|
|
686
|
+
models: found
|
|
687
|
+
});
|
|
611
688
|
if (found.length === 0) {
|
|
612
689
|
setFailure(t("fetchEmpty"));
|
|
613
690
|
return;
|
|
@@ -696,125 +773,61 @@ window.__ModuleLoader__.load({
|
|
|
696
773
|
className: ModelsSection_module_css_default["modelEmpty"],
|
|
697
774
|
children: t("modelsEmpty")
|
|
698
775
|
}) : null,
|
|
699
|
-
|
|
700
|
-
className: ModelsSection_module_css_default["
|
|
701
|
-
children:
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
(
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
for (const at of current) if (at < index) next.add(at);
|
|
748
|
-
else if (at > index) next.add(at - 1);
|
|
749
|
-
return next;
|
|
750
|
-
});
|
|
751
|
-
setEditing((current) => reindexOnRemove(current, index));
|
|
752
|
-
},
|
|
753
|
-
children: (0, react_jsx_runtime.jsx)(IconTrash, {})
|
|
754
|
-
})
|
|
755
|
-
]
|
|
756
|
-
}), expanded.has(index) ? (0, react_jsx_runtime.jsxs)("div", {
|
|
757
|
-
className: ModelsSection_module_css_default["modelAdvanced"],
|
|
758
|
-
children: [(0, react_jsx_runtime.jsxs)("label", {
|
|
759
|
-
className: ModelsSection_module_css_default["modelField"],
|
|
760
|
-
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
761
|
-
className: ModelsSection_module_css_default["modelFieldLabel"],
|
|
762
|
-
children: t("modelContextWindow")
|
|
763
|
-
}), (0, react_jsx_runtime.jsx)("input", {
|
|
764
|
-
className: ModelsSection_module_css_default["input"],
|
|
765
|
-
type: "text",
|
|
766
|
-
inputMode: "numeric",
|
|
767
|
-
value: capacityText(model, index, "contextWindow"),
|
|
768
|
-
placeholder: CAPACITY_HINT.contextWindow,
|
|
769
|
-
"aria-label": `${t("modelContextWindow")} ${index + 1}`,
|
|
770
|
-
disabled,
|
|
771
|
-
onChange: (event) => {
|
|
772
|
-
editCapacity(index, "contextWindow", event.target.value);
|
|
773
|
-
}
|
|
774
|
-
})]
|
|
775
|
-
}), (0, react_jsx_runtime.jsxs)("label", {
|
|
776
|
-
className: ModelsSection_module_css_default["modelField"],
|
|
777
|
-
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
778
|
-
className: ModelsSection_module_css_default["modelFieldLabel"],
|
|
779
|
-
children: t("modelMaxTokens")
|
|
780
|
-
}), (0, react_jsx_runtime.jsx)("input", {
|
|
781
|
-
className: ModelsSection_module_css_default["input"],
|
|
782
|
-
type: "text",
|
|
783
|
-
inputMode: "numeric",
|
|
784
|
-
value: capacityText(model, index, "maxTokens"),
|
|
785
|
-
placeholder: CAPACITY_HINT.maxTokens,
|
|
786
|
-
"aria-label": `${t("modelMaxTokens")} ${index + 1}`,
|
|
787
|
-
disabled,
|
|
788
|
-
onChange: (event) => {
|
|
789
|
-
editCapacity(index, "maxTokens", event.target.value);
|
|
790
|
-
}
|
|
791
|
-
})]
|
|
792
|
-
}), props.thinkingPresets ? (0, react_jsx_runtime.jsxs)("label", {
|
|
793
|
-
className: ModelsSection_module_css_default["modelField"],
|
|
794
|
-
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
795
|
-
className: ModelsSection_module_css_default["modelFieldLabel"],
|
|
796
|
-
children: t("thinkingPreset")
|
|
797
|
-
}), (0, react_jsx_runtime.jsxs)("select", {
|
|
798
|
-
className: `${ModelsSection_module_css_default["input"]} ${ModelsSection_module_css_default["selectInput"]}`,
|
|
799
|
-
value: thinkingPresetOf(model),
|
|
800
|
-
"aria-label": `${t("thinkingPreset")} ${index + 1}`,
|
|
801
|
-
disabled,
|
|
802
|
-
onChange: (event) => {
|
|
803
|
-
patch(index, { reasoningEfforts: reasoningEffortsForPreset(event.target.value) });
|
|
804
|
-
},
|
|
805
|
-
children: [(0, react_jsx_runtime.jsx)("option", { value: "toggle", children: t("thinkingPresetToggle") }), (0, react_jsx_runtime.jsx)("option", { value: "four", children: t("thinkingPresetFour") }), (0, react_jsx_runtime.jsx)("option", { value: "five", children: t("thinkingPresetFive") })]
|
|
806
|
-
})]
|
|
807
|
-
}) : null]
|
|
808
|
-
}) : null]
|
|
809
|
-
}, index)),
|
|
810
|
-
(0, react_jsx_runtime.jsx)("button", {
|
|
776
|
+
(0, react_jsx_runtime.jsx)("div", {
|
|
777
|
+
className: ModelsSection_module_css_default["modelList"],
|
|
778
|
+
children: models.map((model, index) => (0, react_jsx_runtime.jsx)(ModelRow, {
|
|
779
|
+
model,
|
|
780
|
+
position: index + 1,
|
|
781
|
+
inputField: "input",
|
|
782
|
+
thinkingPresets: props.thinkingPresets,
|
|
783
|
+
inputFallback: props.thinkingPresets && CLAUDE_KNOWN_MODELS[model.id] ? ["text", "image"] : inputDefaults.get(textOf(model, "id")) ?? props.defaultInput,
|
|
784
|
+
inputLoading: catalogProvider !== void 0 && catalog === void 0,
|
|
785
|
+
expanded: expanded.has(index),
|
|
786
|
+
disabled,
|
|
787
|
+
t,
|
|
788
|
+
contextWindow: {
|
|
789
|
+
value: capacityText(model, index, "contextWindow"),
|
|
790
|
+
placeholder: CAPACITY_HINT.contextWindow,
|
|
791
|
+
onChange: (text) => {
|
|
792
|
+
editCapacity(index, "contextWindow", text);
|
|
793
|
+
}
|
|
794
|
+
},
|
|
795
|
+
maxTokens: {
|
|
796
|
+
value: capacityText(model, index, "maxTokens"),
|
|
797
|
+
placeholder: CAPACITY_HINT.maxTokens,
|
|
798
|
+
onChange: (text) => {
|
|
799
|
+
editCapacity(index, "maxTokens", text);
|
|
800
|
+
}
|
|
801
|
+
},
|
|
802
|
+
onFieldChange: (field, value) => {
|
|
803
|
+
patch(index, { [field]: value });
|
|
804
|
+
},
|
|
805
|
+
onChange: (next) => {
|
|
806
|
+
onChange(models.map((row, at) => at === index ? next : row));
|
|
807
|
+
},
|
|
808
|
+
onToggle: () => {
|
|
809
|
+
toggleExpanded(index);
|
|
810
|
+
},
|
|
811
|
+
onRemove: () => {
|
|
812
|
+
onChange(models.filter((_model, at) => at !== index));
|
|
813
|
+
setExpanded((current) => {
|
|
814
|
+
const next = /* @__PURE__ */ new Set();
|
|
815
|
+
for (const at of current) if (at < index) next.add(at);
|
|
816
|
+
else if (at > index) next.add(at - 1);
|
|
817
|
+
return next;
|
|
818
|
+
});
|
|
819
|
+
setEditing((current) => reindexOnRemove(current, index));
|
|
820
|
+
}
|
|
821
|
+
}, index))
|
|
822
|
+
}),
|
|
823
|
+
(0, react_jsx_runtime.jsxs)("button", {
|
|
811
824
|
type: "button",
|
|
812
825
|
className: ModelsSection_module_css_default["addModelButton"],
|
|
813
826
|
disabled,
|
|
814
827
|
onClick: () => {
|
|
815
828
|
onChange([...models, props.thinkingPresets ? withDefaultClaudeReasoning({ id: "" }) : { id: "" }]);
|
|
816
829
|
},
|
|
817
|
-
children: t("addModel")
|
|
830
|
+
children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutlineRegular, { size: 14 }), t("addModel")]
|
|
818
831
|
}),
|
|
819
832
|
failure !== void 0 ? (0, react_jsx_runtime.jsx)("p", {
|
|
820
833
|
className: ModelsSection_module_css_default["error"],
|
|
@@ -871,8 +884,9 @@ window.__ModuleLoader__.load({
|
|
|
871
884
|
toggle(candidate.id);
|
|
872
885
|
}
|
|
873
886
|
}), (0, react_jsx_runtime.jsx)("span", {
|
|
874
|
-
className: ModelsSection_module_css_default["
|
|
875
|
-
|
|
887
|
+
className: ModelsSection_module_css_default["candidateName"],
|
|
888
|
+
title: candidate.name ?? candidate.id,
|
|
889
|
+
children: candidate.name ?? candidate.id
|
|
876
890
|
})]
|
|
877
891
|
})
|
|
878
892
|
}, candidate.id))
|
|
@@ -1124,18 +1138,46 @@ window.__ModuleLoader__.load({
|
|
|
1124
1138
|
return { kind: "credential-missing" };
|
|
1125
1139
|
}
|
|
1126
1140
|
//#endregion
|
|
1141
|
+
//#region lib/types/client/protocol-label.js
|
|
1142
|
+
/**
|
|
1143
|
+
* Product names for the wire protocols a pi-ai route may speak. The pickers
|
|
1144
|
+
* show these instead of the schema identifiers (`openai-completions`), which
|
|
1145
|
+
* are what `settings.yaml` carries and what the option values stay.
|
|
1146
|
+
*/
|
|
1147
|
+
/** The protocols this page names, keyed by their schema identifier. */
|
|
1148
|
+
const PROTOCOL_LABEL_KEYS = {
|
|
1149
|
+
"openai-completions": "protocolOpenAiCompletions",
|
|
1150
|
+
"openai-responses": "protocolOpenAiResponses",
|
|
1151
|
+
"anthropic-messages": "protocolAnthropicMessages"
|
|
1152
|
+
};
|
|
1153
|
+
/**
|
|
1154
|
+
* The picker text for one protocol identifier.
|
|
1155
|
+
* @param t - section copy.
|
|
1156
|
+
* @param protocol - the schema identifier of the protocol.
|
|
1157
|
+
* @returns the product name this page knows the protocol by; a protocol the
|
|
1158
|
+
* adapter adds before this page names it shows its identifier, the spelling
|
|
1159
|
+
* `settings.yaml` needs anyway.
|
|
1160
|
+
*/
|
|
1161
|
+
function protocolLabel(t, protocol) {
|
|
1162
|
+
const key = PROTOCOL_LABEL_KEYS[protocol];
|
|
1163
|
+
return key === void 0 ? protocol : t(key);
|
|
1164
|
+
}
|
|
1165
|
+
//#endregion
|
|
1127
1166
|
//#region lib/types/client/CustomProviderCard.js
|
|
1128
1167
|
/**
|
|
1129
1168
|
* The card that declares a provider pi-ai does not ship — an OpenAI-compatible
|
|
1130
1169
|
* gateway, a self-hosted server, or a provider newer than the installed
|
|
1131
1170
|
* catalog.
|
|
1132
1171
|
*
|
|
1133
|
-
* This is a create, not an edit, which is why it is its own
|
|
1172
|
+
* This is a create, not an edit, which is why it is its own form rather than
|
|
1134
1173
|
* the provider editor with extra fields: the route id is being *chosen* here,
|
|
1135
|
-
* and the settings address does not exist until it is.
|
|
1136
|
-
*
|
|
1137
|
-
*
|
|
1138
|
-
*
|
|
1174
|
+
* and the settings address does not exist until it is. It renders as the
|
|
1175
|
+
* custom-API panel of the section's add card; the card's mode switch names it
|
|
1176
|
+
* when both modes are offered, and with the custom mode alone the card shows
|
|
1177
|
+
* this form directly. One `settings.mutate` sets the whole profile at
|
|
1178
|
+
* `providers.<route>`; the key travels separately through `credentials/set`
|
|
1179
|
+
* under the reference the profile records, exactly as an existing provider's
|
|
1180
|
+
* key does.
|
|
1139
1181
|
*
|
|
1140
1182
|
* The three fields a hand-declared route cannot default — endpoint, protocol,
|
|
1141
1183
|
* and at least one model — are required here rather than at load, so the
|
|
@@ -1172,7 +1214,7 @@ window.__ModuleLoader__.load({
|
|
|
1172
1214
|
* @returns the creation card.
|
|
1173
1215
|
*/
|
|
1174
1216
|
function CustomProviderCard(props) {
|
|
1175
|
-
const { taken, protocols, operations, t } = props;
|
|
1217
|
+
const { taken, protocols, operations, t, onBusyChange } = props;
|
|
1176
1218
|
const [openedAt] = (0, react.useState)(() => props.revision);
|
|
1177
1219
|
const [route, setRoute] = (0, react.useState)("");
|
|
1178
1220
|
const [displayName, setDisplayName] = (0, react.useState)("");
|
|
@@ -1183,6 +1225,14 @@ window.__ModuleLoader__.load({
|
|
|
1183
1225
|
const [keyDraft, setKeyDraft] = (0, react.useState)("");
|
|
1184
1226
|
const [models, setModels] = (0, react.useState)([]);
|
|
1185
1227
|
const [busy, setBusy] = (0, react.useState)(false);
|
|
1228
|
+
const [listBusy, setListBusy] = (0, react.useState)(false);
|
|
1229
|
+
(0, react.useEffect)(() => {
|
|
1230
|
+
onBusyChange?.(busy || listBusy);
|
|
1231
|
+
}, [
|
|
1232
|
+
busy,
|
|
1233
|
+
listBusy,
|
|
1234
|
+
onBusyChange
|
|
1235
|
+
]);
|
|
1186
1236
|
const [failure, setFailure] = (0, react.useState)(void 0);
|
|
1187
1237
|
/**
|
|
1188
1238
|
* The profile write landed. Only the key write can still be outstanding, so
|
|
@@ -1253,13 +1303,6 @@ window.__ModuleLoader__.load({
|
|
|
1253
1303
|
return (0, react_jsx_runtime.jsxs)("div", {
|
|
1254
1304
|
className: ModelsSection_module_css_default["editor"],
|
|
1255
1305
|
children: [
|
|
1256
|
-
(0, react_jsx_runtime.jsx)("div", {
|
|
1257
|
-
className: ModelsSection_module_css_default["editorHeader"],
|
|
1258
|
-
children: (0, react_jsx_runtime.jsx)("span", {
|
|
1259
|
-
className: ModelsSection_module_css_default["editorTitle"],
|
|
1260
|
-
children: t(isAdaptiveClaude ? "claudeCustomTitle" : "customTitle")
|
|
1261
|
-
})
|
|
1262
|
-
}),
|
|
1263
1306
|
isAdaptiveClaude ? (0, react_jsx_runtime.jsxs)("p", {
|
|
1264
1307
|
className: ModelsSection_module_css_default["savedNotice"],
|
|
1265
1308
|
role: "status",
|
|
@@ -1315,7 +1358,7 @@ window.__ModuleLoader__.load({
|
|
|
1315
1358
|
className: ModelsSection_module_css_default["input"],
|
|
1316
1359
|
type: "text",
|
|
1317
1360
|
value: baseURL,
|
|
1318
|
-
placeholder: t("customBaseUrlPlaceholder"),
|
|
1361
|
+
placeholder: t(protocol === "anthropic-messages" ? "customAnthropicBaseUrlPlaceholder" : "customBaseUrlPlaceholder"),
|
|
1319
1362
|
"aria-label": t("baseUrl"),
|
|
1320
1363
|
"aria-invalid": baseUrlInvalid,
|
|
1321
1364
|
disabled: profileDisabled,
|
|
@@ -1343,7 +1386,7 @@ window.__ModuleLoader__.load({
|
|
|
1343
1386
|
},
|
|
1344
1387
|
children: protocols.map((choice) => (0, react_jsx_runtime.jsx)("option", {
|
|
1345
1388
|
value: choice,
|
|
1346
|
-
children: choice
|
|
1389
|
+
children: protocolLabel(t, choice)
|
|
1347
1390
|
}, choice))
|
|
1348
1391
|
})]
|
|
1349
1392
|
}),
|
|
@@ -1385,7 +1428,8 @@ window.__ModuleLoader__.load({
|
|
|
1385
1428
|
thinkingPresets: isAdaptiveClaude,
|
|
1386
1429
|
operations,
|
|
1387
1430
|
t,
|
|
1388
|
-
disabled: profileDisabled
|
|
1431
|
+
disabled: profileDisabled,
|
|
1432
|
+
onBusyChange: setListBusy
|
|
1389
1433
|
}),
|
|
1390
1434
|
failure !== void 0 ? (0, react_jsx_runtime.jsx)("p", {
|
|
1391
1435
|
className: ModelsSection_module_css_default["error"],
|
|
@@ -1429,9 +1473,9 @@ window.__ModuleLoader__.load({
|
|
|
1429
1473
|
* Reasoning effort is deliberately absent: it is a per-MODEL capability, and
|
|
1430
1474
|
* the models under one provider disagree about it, so a provider-scoped
|
|
1431
1475
|
* control can only be set to a value some of them reject. The composer's
|
|
1432
|
-
* model picker offers each model its own levels; `
|
|
1476
|
+
* model picker offers each model its own levels; `cordis.patch.yml` keeps the
|
|
1433
1477
|
* profile field for a deployment that knows its route. Everything else stays
|
|
1434
|
-
* owned by `
|
|
1478
|
+
* owned by `cordis.patch.yml`. Profile edits land as minimal `settings.mutate`
|
|
1435
1479
|
* path ops against the stored section — the card names only the fields it can
|
|
1436
1480
|
* see instead of rebuilding the whole subtree from a partial descriptor.
|
|
1437
1481
|
*/
|
|
@@ -1491,6 +1535,15 @@ window.__ModuleLoader__.load({
|
|
|
1491
1535
|
const [keyDraft, setKeyDraft] = (0, react.useState)("");
|
|
1492
1536
|
const [keyState, setKeyState] = (0, react.useState)(void 0);
|
|
1493
1537
|
const [busy, setBusy] = (0, react.useState)(false);
|
|
1538
|
+
const [listBusy, setListBusy] = (0, react.useState)(false);
|
|
1539
|
+
const { onBusyChange } = props;
|
|
1540
|
+
(0, react.useEffect)(() => {
|
|
1541
|
+
onBusyChange?.(busy || listBusy);
|
|
1542
|
+
}, [
|
|
1543
|
+
busy,
|
|
1544
|
+
listBusy,
|
|
1545
|
+
onBusyChange
|
|
1546
|
+
]);
|
|
1494
1547
|
const [failure, setFailure] = (0, react.useState)(void 0);
|
|
1495
1548
|
const [committedOriginal, setCommittedOriginal] = (0, react.useState)(() => schema.getPath(namespace.user, settingsPath));
|
|
1496
1549
|
const [expectedRevision, setExpectedRevision] = (0, react.useState)(() => namespace.revision);
|
|
@@ -1625,6 +1678,7 @@ window.__ModuleLoader__.load({
|
|
|
1625
1678
|
const models = modelDrafts(modelsOverridden ? customModels : inheritedModels());
|
|
1626
1679
|
const defaultContextWindow = schema.getPath(fallback, ["defaultContextWindow"]);
|
|
1627
1680
|
const defaultMaxTokens = schema.getPath(fallback, ["maxTokens"]);
|
|
1681
|
+
const defaultInput = schema.getPath(fallback, ["defaultInput"]);
|
|
1628
1682
|
const keyPlaceholder = keyLocked ? t("keyEnvLocked") : keyState?.configured === true && props.credentialRequired !== true ? t("keyStored") : family === "pi-ai" ? t("keyPlaceholderNative") : t("keyPlaceholder");
|
|
1629
1683
|
/** What both family editors take: the rows, whose layer owns them, and the two writes. */
|
|
1630
1684
|
const catalogProps = {
|
|
@@ -1702,7 +1756,7 @@ window.__ModuleLoader__.load({
|
|
|
1702
1756
|
className: ModelsSection_module_css_default["input"],
|
|
1703
1757
|
type: "text",
|
|
1704
1758
|
value: stringAt(draft, "baseURL") ?? "",
|
|
1705
|
-
placeholder: family === "deepseek" ? t(
|
|
1759
|
+
placeholder: family === "deepseek" ? t("deepSeekBaseUrl") : stringAt(fallback, "baseURL") ?? t("baseUrlDefault"),
|
|
1706
1760
|
"aria-describedby": family === "deepseek" ? `${props.provider}-endpoint-hint` : void 0,
|
|
1707
1761
|
"aria-label": t("baseUrl"),
|
|
1708
1762
|
disabled,
|
|
@@ -1735,7 +1789,7 @@ window.__ModuleLoader__.load({
|
|
|
1735
1789
|
children: t("customApiUnset")
|
|
1736
1790
|
}) : null, protocols.map((choice) => (0, react_jsx_runtime.jsx)("option", {
|
|
1737
1791
|
value: choice,
|
|
1738
|
-
children: choice
|
|
1792
|
+
children: protocolLabel(t, choice)
|
|
1739
1793
|
}, choice))]
|
|
1740
1794
|
})]
|
|
1741
1795
|
}) : null,
|
|
@@ -1745,10 +1799,13 @@ window.__ModuleLoader__.load({
|
|
|
1745
1799
|
defaultMaxTokens: typeof defaultMaxTokens === "number" ? defaultMaxTokens : void 0
|
|
1746
1800
|
}) : (0, react_jsx_runtime.jsx)(ModelListEditor, {
|
|
1747
1801
|
...catalogProps,
|
|
1802
|
+
catalogProvider: props.declared === true ? void 0 : props.provider,
|
|
1803
|
+
defaultInput: Array.isArray(defaultInput) ? defaultInput : void 0,
|
|
1748
1804
|
probe,
|
|
1749
1805
|
probeBlocked: keyFailure,
|
|
1750
1806
|
thinkingPresets: props.thinkingPresets === true,
|
|
1751
|
-
operations
|
|
1807
|
+
operations,
|
|
1808
|
+
onBusyChange: setListBusy
|
|
1752
1809
|
})
|
|
1753
1810
|
]
|
|
1754
1811
|
})]
|
|
@@ -1805,11 +1862,19 @@ window.__ModuleLoader__.load({
|
|
|
1805
1862
|
* solid configured or missing dots. A whole-section provider without a
|
|
1806
1863
|
* configured key renders as its open setup card instead of a row, but only in
|
|
1807
1864
|
* the first-run posture — no provider on the page can serve requests yet — and
|
|
1808
|
-
* only until the user closes that card
|
|
1809
|
-
*
|
|
1810
|
-
*
|
|
1811
|
-
*
|
|
1812
|
-
*
|
|
1865
|
+
* only until the user closes that card. The add flow is one card behind one
|
|
1866
|
+
* button: a mode switch chooses between adopting a dormant directory provider
|
|
1867
|
+
* (the catalog select over the provider editor) and declaring a custom model
|
|
1868
|
+
* API (the create form). A panel mounts the first time its mode is shown and
|
|
1869
|
+
* stays mounted, hidden, while the card is open and its mode stays offered,
|
|
1870
|
+
* so switching modes discards neither draft and an unvisited mode costs
|
|
1871
|
+
* nothing; the switch holds still while either panel has a write or an
|
|
1872
|
+
* endpoint interrogation in flight, since a switch underneath one would
|
|
1873
|
+
* orphan the answer. Each card kind owns its own open state, so closing one
|
|
1874
|
+
* never discards a draft in another. Every
|
|
1875
|
+
* mutation writes through the wire, while a provider removal first requires
|
|
1876
|
+
* confirmation; the page re-renders from pushed invalidations or the
|
|
1877
|
+
* post-apply reload.
|
|
1813
1878
|
*/
|
|
1814
1879
|
/** Render an editor for either the setup posture or an expanded provider row. */
|
|
1815
1880
|
function renderProviderEditor({ target, ...props }) {
|
|
@@ -1908,10 +1973,14 @@ window.__ModuleLoader__.load({
|
|
|
1908
1973
|
if (preset === "four") return { ...CLAUDE_FOUR_EFFORTS };
|
|
1909
1974
|
return { ...CLAUDE_FIVE_EFFORTS };
|
|
1910
1975
|
}
|
|
1976
|
+
function withKnownClaudeInput(model) {
|
|
1977
|
+
if (!CLAUDE_KNOWN_MODELS[model?.id] || (Array.isArray(model.input) && model.input.length > 0)) return { ...model };
|
|
1978
|
+
return { ...model, input: ["text", "image"] };
|
|
1979
|
+
}
|
|
1911
1980
|
function withFetchedClaudeMetadata(model) {
|
|
1912
1981
|
const known = CLAUDE_KNOWN_MODELS[model?.id];
|
|
1913
1982
|
if (known === undefined) return withDefaultClaudeReasoning(model);
|
|
1914
|
-
return { ...model, contextWindow: known.contextWindow, maxTokens: known.maxTokens, reasoningEfforts: reasoningEffortsForPreset(known.preset) };
|
|
1983
|
+
return { ...withKnownClaudeInput(model), contextWindow: known.contextWindow, maxTokens: known.maxTokens, reasoningEfforts: reasoningEffortsForPreset(known.preset) };
|
|
1915
1984
|
}
|
|
1916
1985
|
function thinkingPresetOf(model) {
|
|
1917
1986
|
const efforts = model?.reasoningEfforts;
|
|
@@ -1928,7 +1997,7 @@ window.__ModuleLoader__.load({
|
|
|
1928
1997
|
: { ...model, reasoningEfforts: reasoningEffortsForPreset("five") };
|
|
1929
1998
|
}
|
|
1930
1999
|
function withNativeClaudeModel(model) {
|
|
1931
|
-
const next = withDefaultClaudeReasoning(model);
|
|
2000
|
+
const next = withKnownClaudeInput(withDefaultClaudeReasoning(model));
|
|
1932
2001
|
const efforts = next.reasoningEfforts;
|
|
1933
2002
|
const adaptive = efforts !== null && typeof efforts === "object" && !Array.isArray(efforts)
|
|
1934
2003
|
&& ["low", "medium", "high", "max"].every((level) => typeof efforts[level] === "string" && efforts[level].length > 0);
|
|
@@ -2035,30 +2104,50 @@ window.__ModuleLoader__.load({
|
|
|
2035
2104
|
const { controller, operations, schema, t } = injected;
|
|
2036
2105
|
const state = injected.useSnapshot((snapshot) => snapshot);
|
|
2037
2106
|
const [editing, setEditing] = (0, react.useState)(void 0);
|
|
2038
|
-
const [
|
|
2107
|
+
const [addOpen, setAddOpen] = (0, react.useState)(false);
|
|
2108
|
+
const [addMode, setAddMode] = (0, react.useState)("catalog");
|
|
2109
|
+
/** The modes shown since the add card opened; each keeps its panel mounted. */
|
|
2110
|
+
const [visited, setVisited] = (0, react.useState)(() => /* @__PURE__ */ new Set());
|
|
2111
|
+
/** Whether each add panel has a write or an interrogation in flight. */
|
|
2112
|
+
const [catalogBusy, setCatalogBusy] = (0, react.useState)(false);
|
|
2113
|
+
const [customBusy, setCustomBusy] = (0, react.useState)(false);
|
|
2114
|
+
const [claudeBusy, setClaudeBusy] = (0, react.useState)(false);
|
|
2115
|
+
/** Base of the add card's tab and panel ids. */
|
|
2116
|
+
const addId = (0, react.useId)();
|
|
2039
2117
|
const [deleteTarget, setDeleteTarget] = (0, react.useState)(void 0);
|
|
2040
2118
|
const [deleting, setDeleting] = (0, react.useState)(false);
|
|
2041
2119
|
const [deleteFailure, setDeleteFailure] = (0, react.useState)(void 0);
|
|
2042
2120
|
const [savedTarget, setSavedTarget] = (0, react.useState)(void 0);
|
|
2043
|
-
const [declaringType, setDeclaringType] = (0, react.useState)(void 0);
|
|
2044
2121
|
const [dismissedSetup, setDismissedSetup] = (0, react.useState)(() => /* @__PURE__ */ new Set());
|
|
2045
2122
|
const announceSaved = (target) => {
|
|
2046
2123
|
controller.load().then(() => {
|
|
2047
2124
|
setSavedTarget(target);
|
|
2048
2125
|
});
|
|
2049
2126
|
};
|
|
2050
|
-
|
|
2127
|
+
/**
|
|
2128
|
+
* Close the add card whole. The catalog target is forgotten with it, since
|
|
2129
|
+
* `editing` doubles as the row editor's target once the card is closed and a
|
|
2130
|
+
* refresh could otherwise open the row of a provider the draft never saved.
|
|
2131
|
+
* The busy flags reset here because a panel that closes itself on success
|
|
2132
|
+
* unmounts before it can report idle.
|
|
2133
|
+
*/
|
|
2134
|
+
const closeAdd = () => {
|
|
2051
2135
|
setEditing(void 0);
|
|
2052
|
-
|
|
2053
|
-
|
|
2136
|
+
setAddOpen(false);
|
|
2137
|
+
setCatalogBusy(false);
|
|
2138
|
+
setCustomBusy(false);
|
|
2139
|
+
setClaudeBusy(false);
|
|
2140
|
+
};
|
|
2141
|
+
const closeEditor = (changed, target) => {
|
|
2142
|
+
closeAdd();
|
|
2054
2143
|
if (changed) announceSaved(target);
|
|
2055
2144
|
};
|
|
2056
2145
|
/**
|
|
2057
|
-
* Close a setup card, which owns none of the state above: the row-editor
|
|
2058
|
-
*
|
|
2059
|
-
*
|
|
2060
|
-
*
|
|
2061
|
-
*
|
|
2146
|
+
* Close a setup card, which owns none of the state above: the row-editor
|
|
2147
|
+
* and add cards each own one of those, so clearing them here would discard
|
|
2148
|
+
* a draft the user opened beside this card. Dismissal is this card's own —
|
|
2149
|
+
* the provider falls back to an ordinary row for the rest of the session,
|
|
2150
|
+
* and reopens through Edit.
|
|
2062
2151
|
*/
|
|
2063
2152
|
const closeSetup = (changed, target) => {
|
|
2064
2153
|
setDismissedSetup((previous) => new Set([...previous, target.provider]));
|
|
@@ -2111,11 +2200,38 @@ window.__ModuleLoader__.load({
|
|
|
2111
2200
|
const anyUsable = state.rows.some(providerUsable);
|
|
2112
2201
|
const configured = state.rows.filter((row) => row.configured);
|
|
2113
2202
|
const configurable = state.rows.filter((row) => state.namespaces.has(row.entry.settingsNs));
|
|
2114
|
-
const addable =
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2203
|
+
const addable = state.rows.flatMap((row) => {
|
|
2204
|
+
const namespace = state.namespaces.get(row.entry.settingsNs);
|
|
2205
|
+
return namespace === void 0 || row.configured ? [] : [{
|
|
2206
|
+
row,
|
|
2207
|
+
namespace
|
|
2208
|
+
}];
|
|
2209
|
+
});
|
|
2210
|
+
const piAi = state.namespaces.get("llm-pi-ai");
|
|
2211
|
+
const protocols = protocolChoices(piAi, schema);
|
|
2212
|
+
const catalogOffered = configurable.length > 0;
|
|
2213
|
+
const catalogEnabled = addable.length > 0;
|
|
2214
|
+
const customOffered = piAi !== void 0;
|
|
2215
|
+
const customEnabled = protocols.length > 0;
|
|
2216
|
+
const claudeEnabled = customEnabled && state.namespaces.has(CLAUDE_PROVIDER_SETTINGS_NS);
|
|
2217
|
+
const bothOffered = customOffered;
|
|
2218
|
+
const mode = bothOffered ? addMode : customOffered ? "custom" : "catalog";
|
|
2219
|
+
const mounted = (candidate) => mode === candidate || visited.has(candidate);
|
|
2220
|
+
const switchLocked = catalogBusy || customBusy || claudeBusy;
|
|
2221
|
+
const draft = (() => {
|
|
2222
|
+
if (!addOpen || !catalogOffered) return void 0;
|
|
2223
|
+
const kept = editing === void 0 ? void 0 : state.namespaces.get(editing.settingsNs);
|
|
2224
|
+
if (editing !== void 0 && kept !== void 0) return {
|
|
2225
|
+
target: editing,
|
|
2226
|
+
namespace: kept
|
|
2227
|
+
};
|
|
2228
|
+
const first = addable[0];
|
|
2229
|
+
return first === void 0 ? void 0 : {
|
|
2230
|
+
target: targetOf(first.row),
|
|
2231
|
+
namespace: first.namespace
|
|
2232
|
+
};
|
|
2233
|
+
})();
|
|
2234
|
+
const addRow = draft === void 0 ? void 0 : state.rows.find((row) => row.entry.provider === draft.target.provider);
|
|
2119
2235
|
return (0, react_jsx_runtime.jsxs)("div", {
|
|
2120
2236
|
className: ModelsSection_module_css_default["section"],
|
|
2121
2237
|
children: [
|
|
@@ -2172,7 +2288,7 @@ window.__ModuleLoader__.load({
|
|
|
2172
2288
|
}, { entryKey: row.entry.settingsNs })
|
|
2173
2289
|
]
|
|
2174
2290
|
}, row.entry.provider);
|
|
2175
|
-
const open = !
|
|
2291
|
+
const open = !addOpen && editing?.provider === row.entry.provider;
|
|
2176
2292
|
const adaptiveClaude = isClaudeProvider(row, state);
|
|
2177
2293
|
const credentialConfigured = row.credential?.configured === true;
|
|
2178
2294
|
const credentialMissing = !credentialConfigured && row.apiKeyEnv !== void 0 && row.credential?.configured === false;
|
|
@@ -2216,8 +2332,7 @@ window.__ModuleLoader__.load({
|
|
|
2216
2332
|
"aria-label": providerCopy(t("editProvider"), target),
|
|
2217
2333
|
onClick: () => {
|
|
2218
2334
|
setSavedTarget(void 0);
|
|
2219
|
-
|
|
2220
|
-
setAdding(false);
|
|
2335
|
+
setAddOpen(false);
|
|
2221
2336
|
setEditing(open ? void 0 : target);
|
|
2222
2337
|
},
|
|
2223
2338
|
children: t("edit")
|
|
@@ -2259,106 +2374,160 @@ window.__ModuleLoader__.load({
|
|
|
2259
2374
|
}),
|
|
2260
2375
|
(0, react_jsx_runtime.jsx)("div", {
|
|
2261
2376
|
className: ModelsSection_module_css_default["addBlock"],
|
|
2262
|
-
children:
|
|
2377
|
+
children: addOpen ? (0, react_jsx_runtime.jsxs)("div", {
|
|
2263
2378
|
className: ModelsSection_module_css_default["addCard"],
|
|
2264
2379
|
children: [
|
|
2265
2380
|
(0, react_jsx_runtime.jsxs)("div", {
|
|
2266
|
-
className: ModelsSection_module_css_default["
|
|
2267
|
-
children: [(0, react_jsx_runtime.jsx)(
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2381
|
+
className: ModelsSection_module_css_default["addModes"],
|
|
2382
|
+
children: [bothOffered ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.SegmentedControl, {
|
|
2383
|
+
id: addId,
|
|
2384
|
+
label: t("addMode"),
|
|
2385
|
+
value: mode,
|
|
2386
|
+
disabled: switchLocked,
|
|
2387
|
+
options: [{
|
|
2388
|
+
value: "catalog",
|
|
2389
|
+
label: t("addCatalog"),
|
|
2390
|
+
disabled: !catalogEnabled,
|
|
2391
|
+
...catalogEnabled ? {} : { title: t("addCatalogExhausted") }
|
|
2392
|
+
}, {
|
|
2393
|
+
value: "custom",
|
|
2394
|
+
label: t("addCustom"),
|
|
2395
|
+
disabled: !customEnabled,
|
|
2396
|
+
...customEnabled ? {} : { title: t("addCustomUnavailable") }
|
|
2397
|
+
}, { value: "claude", label: t("claudeCustomTitle"), disabled: !claudeEnabled }],
|
|
2398
|
+
onChange: (next) => {
|
|
2399
|
+
setAddMode(next);
|
|
2400
|
+
setVisited((previous) => new Set([...previous, next]));
|
|
2401
|
+
}
|
|
2402
|
+
}) : (0, react_jsx_runtime.jsx)("div", {
|
|
2403
|
+
className: ModelsSection_module_css_default["editorHeader"],
|
|
2404
|
+
children: (0, react_jsx_runtime.jsx)("span", {
|
|
2405
|
+
className: ModelsSection_module_css_default["editorTitle"],
|
|
2406
|
+
children: t(mode === "catalog" ? "addCatalog" : "addCustom")
|
|
2407
|
+
})
|
|
2408
|
+
}), (0, react_jsx_runtime.jsx)("p", {
|
|
2409
|
+
hidden: mode === "claude",
|
|
2410
|
+
className: ModelsSection_module_css_default["advancedHint"],
|
|
2411
|
+
children: t(mode === "catalog" ? "addCatalogHint" : "addCustomHint")
|
|
2284
2412
|
})]
|
|
2285
2413
|
}),
|
|
2286
|
-
(0, react_jsx_runtime.
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2414
|
+
mounted("catalog") && draft !== void 0 ? (0, react_jsx_runtime.jsxs)("div", {
|
|
2415
|
+
id: `${addId}-catalog-panel`,
|
|
2416
|
+
...bothOffered ? {
|
|
2417
|
+
role: "tabpanel",
|
|
2418
|
+
"aria-labelledby": `${addId}-catalog`
|
|
2419
|
+
} : {},
|
|
2420
|
+
hidden: mode !== "catalog",
|
|
2421
|
+
className: ModelsSection_module_css_default["addPanel"],
|
|
2422
|
+
children: [
|
|
2423
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
2424
|
+
className: ModelsSection_module_css_default["field"],
|
|
2425
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
2426
|
+
className: ModelsSection_module_css_default["fieldLabel"],
|
|
2427
|
+
children: t("provider")
|
|
2428
|
+
}), (0, react_jsx_runtime.jsx)("select", {
|
|
2429
|
+
className: `${ModelsSection_module_css_default["input"]} ${ModelsSection_module_css_default["selectInput"]}`,
|
|
2430
|
+
value: draft.target.provider,
|
|
2431
|
+
"aria-label": t("provider"),
|
|
2432
|
+
disabled: catalogBusy,
|
|
2433
|
+
onChange: (event) => {
|
|
2434
|
+
const picked = addable.find((candidate) => candidate.row.entry.provider === event.target.value);
|
|
2435
|
+
/* v8 ignore next -- the select only lists addable rows */
|
|
2436
|
+
if (picked === void 0) return;
|
|
2437
|
+
setEditing(targetOf(picked.row));
|
|
2438
|
+
},
|
|
2439
|
+
children: addable.map(({ row }) => (0, react_jsx_runtime.jsx)("option", {
|
|
2440
|
+
value: row.entry.provider,
|
|
2441
|
+
children: row.entry.displayName
|
|
2442
|
+
}, row.entry.provider))
|
|
2443
|
+
})]
|
|
2444
|
+
}),
|
|
2445
|
+
(0, react_jsx_runtime.jsx)(ProviderEditor, {
|
|
2446
|
+
provider: draft.target.provider,
|
|
2447
|
+
displayName: draft.target.displayName,
|
|
2448
|
+
hideTitle: true,
|
|
2449
|
+
namespace: draft.namespace,
|
|
2450
|
+
schema,
|
|
2451
|
+
settingsPath: draft.target.settingsPath,
|
|
2452
|
+
operations,
|
|
2453
|
+
t,
|
|
2454
|
+
readOnly: !state.writable,
|
|
2455
|
+
onClose: (changed) => {
|
|
2456
|
+
closeEditor(changed, draft.target);
|
|
2457
|
+
},
|
|
2458
|
+
onBusyChange: setCatalogBusy
|
|
2459
|
+
}, draft.target.provider),
|
|
2460
|
+
addRow === void 0 ? null : renderSlot("settings.models.provider-card", {
|
|
2461
|
+
provider: addRow.entry,
|
|
2462
|
+
configured: addRow.configured,
|
|
2463
|
+
keyConfigured: keyConfiguredOf(addRow)
|
|
2464
|
+
}, { entryKey: addRow.entry.settingsNs })
|
|
2465
|
+
]
|
|
2466
|
+
}) : null,
|
|
2467
|
+
mounted("custom") && piAi !== void 0 ? (0, react_jsx_runtime.jsx)("div", {
|
|
2468
|
+
id: `${addId}-custom-panel`,
|
|
2469
|
+
...bothOffered ? {
|
|
2470
|
+
role: "tabpanel",
|
|
2471
|
+
"aria-labelledby": `${addId}-custom`
|
|
2472
|
+
} : {},
|
|
2473
|
+
hidden: mode !== "custom",
|
|
2474
|
+
className: ModelsSection_module_css_default["addPanel"],
|
|
2475
|
+
children: (0, react_jsx_runtime.jsx)(CustomProviderCard, {
|
|
2476
|
+
taken: state.rows.map((row) => row.entry.provider),
|
|
2477
|
+
protocols,
|
|
2478
|
+
revision: piAi.revision,
|
|
2479
|
+
operations,
|
|
2480
|
+
t,
|
|
2481
|
+
readOnly: !state.writable,
|
|
2482
|
+
onClose: (changed) => {
|
|
2483
|
+
closeAdd();
|
|
2484
|
+
if (changed) controller.load();
|
|
2485
|
+
},
|
|
2486
|
+
onBusyChange: setCustomBusy
|
|
2487
|
+
})
|
|
2488
|
+
}) : null,
|
|
2489
|
+
mounted("claude") && piAi !== void 0 ? (0, react_jsx_runtime.jsx)("div", {
|
|
2490
|
+
id: `${addId}-claude-panel`,
|
|
2491
|
+
...bothOffered ? {
|
|
2492
|
+
role: "tabpanel",
|
|
2493
|
+
"aria-labelledby": `${addId}-claude`
|
|
2494
|
+
} : {},
|
|
2495
|
+
hidden: mode !== "claude",
|
|
2496
|
+
className: ModelsSection_module_css_default["addPanel"],
|
|
2497
|
+
children: (0, react_jsx_runtime.jsx)(CustomProviderCard, {
|
|
2498
|
+
providerType: CLAUDE_PROVIDER_TYPE,
|
|
2499
|
+
taken: state.rows.map((row) => row.entry.provider),
|
|
2500
|
+
protocols,
|
|
2501
|
+
revision: piAi.revision,
|
|
2502
|
+
operations,
|
|
2503
|
+
t,
|
|
2504
|
+
readOnly: !state.writable,
|
|
2505
|
+
onClose: (changed) => {
|
|
2506
|
+
closeAdd();
|
|
2507
|
+
if (changed) controller.load();
|
|
2508
|
+
},
|
|
2509
|
+
onBusyChange: setClaudeBusy
|
|
2510
|
+
})
|
|
2511
|
+
}) : null
|
|
2305
2512
|
]
|
|
2306
|
-
}) :
|
|
2307
|
-
className: ModelsSection_module_css_default["addCard"],
|
|
2308
|
-
children: (0, react_jsx_runtime.jsx)(CustomProviderCard, {
|
|
2309
|
-
taken: state.rows.map((row) => row.entry.provider),
|
|
2310
|
-
protocols,
|
|
2311
|
-
providerType: declaringType,
|
|
2312
|
-
/* v8 ignore next -- the card only opens from a button disabled without this namespace */
|
|
2313
|
-
revision: state.namespaces.get("llm-pi-ai")?.revision ?? 0,
|
|
2314
|
-
operations,
|
|
2315
|
-
t,
|
|
2316
|
-
readOnly: !state.writable,
|
|
2317
|
-
onClose: (changed) => {
|
|
2318
|
-
setDeclaringType(void 0);
|
|
2319
|
-
if (changed) controller.load();
|
|
2320
|
-
}
|
|
2321
|
-
})
|
|
2322
|
-
}) : (0, react_jsx_runtime.jsxs)("div", {
|
|
2513
|
+
}) : catalogOffered || customOffered ? (0, react_jsx_runtime.jsx)("div", {
|
|
2323
2514
|
className: ModelsSection_module_css_default["addActions"],
|
|
2324
|
-
children:
|
|
2515
|
+
children: (0, react_jsx_runtime.jsxs)("button", {
|
|
2325
2516
|
type: "button",
|
|
2326
2517
|
className: ModelsSection_module_css_default["addButton"],
|
|
2327
|
-
disabled:
|
|
2518
|
+
disabled: !state.writable || !catalogEnabled && !customEnabled,
|
|
2328
2519
|
onClick: () => {
|
|
2329
2520
|
const first = addable[0];
|
|
2330
|
-
|
|
2331
|
-
if (first === void 0) return;
|
|
2521
|
+
const initial = catalogEnabled ? "catalog" : "custom";
|
|
2332
2522
|
setSavedTarget(void 0);
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2523
|
+
setEditing(first === void 0 ? void 0 : targetOf(first.row));
|
|
2524
|
+
setAddMode(initial);
|
|
2525
|
+
setVisited(new Set([initial]));
|
|
2526
|
+
setAddOpen(true);
|
|
2336
2527
|
},
|
|
2337
|
-
children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
2338
|
-
})
|
|
2339
|
-
|
|
2340
|
-
className: ModelsSection_module_css_default["addButton"],
|
|
2341
|
-
disabled: protocols.length === 0 || !state.writable,
|
|
2342
|
-
onClick: () => {
|
|
2343
|
-
setSavedTarget(void 0);
|
|
2344
|
-
setAdding(false);
|
|
2345
|
-
setEditing(void 0);
|
|
2346
|
-
setDeclaringType("generic");
|
|
2347
|
-
},
|
|
2348
|
-
children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutline16, { size: 14 }), t("customAdd")]
|
|
2349
|
-
}), (0, react_jsx_runtime.jsxs)("button", {
|
|
2350
|
-
type: "button",
|
|
2351
|
-
className: ModelsSection_module_css_default["addButton"],
|
|
2352
|
-
disabled: !state.namespaces.has("llm-pi-ai") || !state.namespaces.has(CLAUDE_PROVIDER_SETTINGS_NS) || !state.writable,
|
|
2353
|
-
onClick: () => {
|
|
2354
|
-
setSavedTarget(void 0);
|
|
2355
|
-
setAdding(false);
|
|
2356
|
-
setEditing(void 0);
|
|
2357
|
-
setDeclaringType(CLAUDE_PROVIDER_TYPE);
|
|
2358
|
-
},
|
|
2359
|
-
children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutline16, { size: 14 }), t("claudeCustomAdd")]
|
|
2360
|
-
})]
|
|
2361
|
-
})
|
|
2528
|
+
children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutlineRegular, { size: 14 }), t("add")]
|
|
2529
|
+
})
|
|
2530
|
+
}) : null
|
|
2362
2531
|
}),
|
|
2363
2532
|
renderSlot("settings.models.footer", {}),
|
|
2364
2533
|
(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
@@ -2391,7 +2560,7 @@ window.__ModuleLoader__.load({
|
|
|
2391
2560
|
}
|
|
2392
2561
|
//#endregion
|
|
2393
2562
|
//#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-settings-models/src/client/OnboardingModal.module.css.mjs
|
|
2394
|
-
const css$2 = ".jLrgrW_dialog{width:min(600px,100%);padding:0}.jLrgrW_content{box-sizing:border-box;flex-direction:column;
|
|
2563
|
+
const css$2 = ".jLrgrW_dialog{width:min(600px,100%);max-height:100%;padding:0}.jLrgrW_content{box-sizing:border-box;flex-direction:column;min-height:0;padding:28px;display:flex;overflow-y:auto}.jLrgrW_title{color:var(--dsw-alias-label-primary);outline:none;margin:0;font-size:20px;font-weight:500;line-height:28px}.jLrgrW_body{margin-top:20px}@media (width<=560px){.jLrgrW_content{padding:24px}}";
|
|
2395
2564
|
const tagId$2 = "@mofeng2223/dsh-claude-provider/OnboardingModal.module.css";
|
|
2396
2565
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$2) + "]") === null) {
|
|
2397
2566
|
const tag = document.createElement("style");
|
|
@@ -2486,20 +2655,34 @@ window.__ModuleLoader__.load({
|
|
|
2486
2655
|
* @returns the onboarding modal or null when onboarding needs no intervention.
|
|
2487
2656
|
*/
|
|
2488
2657
|
function DeepSeekOnboardingDialog(props) {
|
|
2489
|
-
const { complete, controller, useModels, operations, schema, t } = props;
|
|
2658
|
+
const { complete, controller, useModels, operations, schema, t, renderSlot, automatic, explicit = false } = props;
|
|
2659
|
+
const [apiKey, setApiKey] = (0, react.useState)(explicit);
|
|
2490
2660
|
const state = useModels((snapshot) => snapshot);
|
|
2491
2661
|
const readiness = onboardingReadiness(state);
|
|
2492
2662
|
(0, react.useEffect)(() => {
|
|
2493
|
-
if (state.status === "idle") controller.load();
|
|
2494
|
-
}, [
|
|
2663
|
+
if ((automatic || explicit) && state.status === "idle") controller.load();
|
|
2664
|
+
}, [
|
|
2665
|
+
controller,
|
|
2666
|
+
state.status,
|
|
2667
|
+
automatic,
|
|
2668
|
+
explicit
|
|
2669
|
+
]);
|
|
2495
2670
|
(0, react.useEffect)(() => {
|
|
2496
|
-
if (readiness.kind === "adapter-absent" || readiness.kind === "provider-ready" || readiness.kind === "unavailable") complete();
|
|
2497
|
-
}, [
|
|
2671
|
+
if (!automatic && !explicit || readiness.kind === "adapter-absent" || !explicit && readiness.kind === "provider-ready" || readiness.kind === "unavailable") complete();
|
|
2672
|
+
}, [
|
|
2673
|
+
complete,
|
|
2674
|
+
readiness.kind,
|
|
2675
|
+
explicit,
|
|
2676
|
+
automatic
|
|
2677
|
+
]);
|
|
2678
|
+
if (!automatic && !explicit) return null;
|
|
2498
2679
|
switch (readiness.kind) {
|
|
2499
2680
|
case "loading":
|
|
2500
2681
|
case "adapter-absent":
|
|
2501
|
-
case "provider-ready":
|
|
2502
2682
|
case "unavailable": return null;
|
|
2683
|
+
case "provider-ready":
|
|
2684
|
+
if (!explicit) return null;
|
|
2685
|
+
break;
|
|
2503
2686
|
case "credential-missing": break;
|
|
2504
2687
|
/* v8 ignore next -- every current readiness variant is handled above */
|
|
2505
2688
|
default: return assertNever$1(readiness);
|
|
@@ -2515,7 +2698,7 @@ window.__ModuleLoader__.load({
|
|
|
2515
2698
|
}
|
|
2516
2699
|
controller.load();
|
|
2517
2700
|
};
|
|
2518
|
-
|
|
2701
|
+
const editor = (0, react_jsx_runtime.jsxs)(OnboardingModal, {
|
|
2519
2702
|
title: t("onboardingTitle"),
|
|
2520
2703
|
children: [(0, react_jsx_runtime.jsx)("p", {
|
|
2521
2704
|
className: DeepSeekOnboardingDialog_module_css_default.description,
|
|
@@ -2542,6 +2725,12 @@ window.__ModuleLoader__.load({
|
|
|
2542
2725
|
})
|
|
2543
2726
|
})]
|
|
2544
2727
|
});
|
|
2728
|
+
return apiKey ? editor : renderSlot("settings.models.sign-in", {
|
|
2729
|
+
complete,
|
|
2730
|
+
useApiKey: () => {
|
|
2731
|
+
setApiKey(true);
|
|
2732
|
+
}
|
|
2733
|
+
}, { fallback: editor });
|
|
2545
2734
|
}
|
|
2546
2735
|
//#endregion
|
|
2547
2736
|
//#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-settings-models/src/client/WelcomeNotice.module.css.mjs
|
|
@@ -2619,7 +2808,7 @@ window.__ModuleLoader__.load({
|
|
|
2619
2808
|
//#endregion
|
|
2620
2809
|
//#region lib/types/onboarding-copy.js
|
|
2621
2810
|
/** Durable settings namespace for product-wide GUI onboarding facts. */
|
|
2622
|
-
const WELCOME_NOTICE_SETTINGS_NAMESPACE = "ui-
|
|
2811
|
+
const WELCOME_NOTICE_SETTINGS_NAMESPACE = "ui-settings-general";
|
|
2623
2812
|
/** Field storing the last welcome notice version the user acknowledged. */
|
|
2624
2813
|
const WELCOME_NOTICE_ACK_FIELD = "welcomeNoticeVersion";
|
|
2625
2814
|
/**
|
|
@@ -2635,16 +2824,6 @@ window.__ModuleLoader__.load({
|
|
|
2635
2824
|
* remote browser's memory-mode scope never answers and the acknowledgement
|
|
2636
2825
|
* stays process-local here.
|
|
2637
2826
|
*/
|
|
2638
|
-
/**
|
|
2639
|
-
* Accept any object section verbatim; a malformed durable value reads as an
|
|
2640
|
-
* empty section, so the notice treats it as unacknowledged instead of leaving
|
|
2641
|
-
* the scope stuck on its previous value.
|
|
2642
|
-
* @param section - the wire section value.
|
|
2643
|
-
* @returns the section object, or an empty one for non-object values.
|
|
2644
|
-
*/
|
|
2645
|
-
function decodeWelcomeSection(section) {
|
|
2646
|
-
return typeof section === "object" && section !== null && !Array.isArray(section) ? section : {};
|
|
2647
|
-
}
|
|
2648
2827
|
/* v8 ignore next 3 -- closed-union default only defends future source widening */
|
|
2649
2828
|
function assertNever(_value) {
|
|
2650
2829
|
throw new Error("unexpected welcome settings status");
|
|
@@ -2843,7 +3022,14 @@ window.__ModuleLoader__.load({
|
|
|
2843
3022
|
deleteDescriptionWithCredential: "Deleting {provider} removes its configuration and stored API key.",
|
|
2844
3023
|
deleteConfirm: "Delete {provider}",
|
|
2845
3024
|
deleting: "Deleting {provider}…",
|
|
2846
|
-
add: "Add provider",
|
|
3025
|
+
add: "Add model provider",
|
|
3026
|
+
addMode: "How to add",
|
|
3027
|
+
addCatalog: "Third-party providers",
|
|
3028
|
+
addCustom: "Custom API",
|
|
3029
|
+
addCatalogHint: "Pick OpenAI, Anthropic, Kimi, or another provider from the built-in catalog and enter its API key.",
|
|
3030
|
+
addCustomHint: "Connect a relay, a self-hosted server, or any other OpenAI- or Anthropic-compatible endpoint by its base URL, protocol, and models.",
|
|
3031
|
+
addCatalogExhausted: "Every catalog provider is already configured.",
|
|
3032
|
+
addCustomUnavailable: "No API protocol is available to declare.",
|
|
2847
3033
|
provider: "Provider",
|
|
2848
3034
|
close: "Close",
|
|
2849
3035
|
cancel: "Cancel",
|
|
@@ -2864,9 +3050,8 @@ window.__ModuleLoader__.load({
|
|
|
2864
3050
|
customized: "Customized settings",
|
|
2865
3051
|
baseUrl: "Base URL",
|
|
2866
3052
|
baseUrlDefault: "Provider default",
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
deepSeekEndpointHint: "Use an endpoint compatible with the configured connection.",
|
|
3053
|
+
deepSeekBaseUrl: "https://api.deepseek.com/anthropic",
|
|
3054
|
+
deepSeekEndpointHint: "Use an API endpoint compatible with Anthropic Messages.",
|
|
2870
3055
|
models: "Models",
|
|
2871
3056
|
modelsInherited: "Using the adapter defaults",
|
|
2872
3057
|
modelsCustomized: "Customized model catalog",
|
|
@@ -2879,7 +3064,10 @@ window.__ModuleLoader__.load({
|
|
|
2879
3064
|
contextWindowPlaceholder: "Uses the provider default",
|
|
2880
3065
|
maxTokens: "Max output tokens",
|
|
2881
3066
|
maxTokensPlaceholder: "Uses the provider default",
|
|
2882
|
-
modelAdvanced: "
|
|
3067
|
+
modelAdvanced: "Model options",
|
|
3068
|
+
modelInputTypes: "Input types",
|
|
3069
|
+
modelInputText: "Text",
|
|
3070
|
+
modelInputImage: "Image",
|
|
2883
3071
|
addModel: "Add model",
|
|
2884
3072
|
removeModel: "Delete model",
|
|
2885
3073
|
modelsEmpty: "No models will be shown in the selector. Unlisted IDs can still be sent directly.",
|
|
@@ -2891,11 +3079,9 @@ window.__ModuleLoader__.load({
|
|
|
2891
3079
|
modelNameInvalid: "Display name cannot be empty.",
|
|
2892
3080
|
modelContextInvalid: "Context window must be a positive count, like 131072, 256K, or 1M.",
|
|
2893
3081
|
modelMaxTokensInvalid: "Max output tokens must be a positive count, like 8192, 64K, or 1M.",
|
|
2894
|
-
advancedHint: "Other fields live in
|
|
3082
|
+
advancedHint: "Other fields live in cordis.patch.yml; edit that section directly.",
|
|
2895
3083
|
modelCapacityInvalid: "A capacity must be a number, optionally suffixed K or M.",
|
|
2896
3084
|
modelDuplicate: "Each model ID may appear once.",
|
|
2897
|
-
modelContextWindow: "Context window",
|
|
2898
|
-
modelMaxTokens: "Max output tokens",
|
|
2899
3085
|
fetchModels: "Fetch available models",
|
|
2900
3086
|
fetching: "Asking the provider…",
|
|
2901
3087
|
fetchNeedsBaseUrl: "Enter the base URL first, then fetch.",
|
|
@@ -2907,8 +3093,6 @@ window.__ModuleLoader__.load({
|
|
|
2907
3093
|
fetchSelectAll: "Select all",
|
|
2908
3094
|
fetchDeselectAll: "Deselect all",
|
|
2909
3095
|
fetchAdopt: "Add selected",
|
|
2910
|
-
customAdd: "Add a custom provider",
|
|
2911
|
-
customTitle: "Custom provider",
|
|
2912
3096
|
customTag: "Custom",
|
|
2913
3097
|
claudeCustomAdd: "Add Claude provider",
|
|
2914
3098
|
claudeCustomTitle: "Claude provider",
|
|
@@ -2930,10 +3114,14 @@ window.__ModuleLoader__.load({
|
|
|
2930
3114
|
customDisplayName: "Display name",
|
|
2931
3115
|
customApi: "API protocol",
|
|
2932
3116
|
customApiUnset: "Not selected",
|
|
3117
|
+
protocolOpenAiCompletions: "OpenAI Chat Completions",
|
|
3118
|
+
protocolOpenAiResponses: "OpenAI Responses",
|
|
3119
|
+
protocolAnthropicMessages: "Anthropic Messages",
|
|
2933
3120
|
customNeedsBaseUrl: "A custom provider needs a base URL.",
|
|
2934
3121
|
customBaseUrlInvalid: "Enter a valid HTTP or HTTPS URL.",
|
|
2935
3122
|
customNeedsModels: "A custom provider needs at least one model.",
|
|
2936
3123
|
customBaseUrlPlaceholder: "https://gateway.example/v1",
|
|
3124
|
+
customAnthropicBaseUrlPlaceholder: "https://gateway.example",
|
|
2937
3125
|
settingsPathUnresolvable: "unresolvable settings path",
|
|
2938
3126
|
create: "Create provider",
|
|
2939
3127
|
creating: "Creating…",
|
|
@@ -2952,7 +3140,7 @@ window.__ModuleLoader__.load({
|
|
|
2952
3140
|
const zh = {
|
|
2953
3141
|
nav: "模型",
|
|
2954
3142
|
title: "模型",
|
|
2955
|
-
intro: "
|
|
3143
|
+
intro: "填入各提供商的 API 密钥即可使用其模型。",
|
|
2956
3144
|
edit: "编辑",
|
|
2957
3145
|
editProvider: "编辑 {provider}",
|
|
2958
3146
|
remove: "删除",
|
|
@@ -2962,8 +3150,15 @@ window.__ModuleLoader__.load({
|
|
|
2962
3150
|
deleteDescriptionWithCredential: "删除 {provider} 会移除其配置和存储的 API 密钥。",
|
|
2963
3151
|
deleteConfirm: "删除 {provider}",
|
|
2964
3152
|
deleting: "正在删除 {provider}…",
|
|
2965
|
-
add: "
|
|
2966
|
-
|
|
3153
|
+
add: "添加模型提供商",
|
|
3154
|
+
addMode: "添加方式",
|
|
3155
|
+
addCatalog: "第三方模型提供商",
|
|
3156
|
+
addCustom: "自定义模型 API",
|
|
3157
|
+
addCatalogHint: "从内置目录中选择 OpenAI、Anthropic、Kimi 等提供商,填入其 API 密钥即可使用。",
|
|
3158
|
+
addCustomHint: "连接中转站、自部署服务或其他兼容 OpenAI / Anthropic 协议的接口,需填写 API 地址、协议和模型。",
|
|
3159
|
+
addCatalogExhausted: "目录中的提供商都已添加。",
|
|
3160
|
+
addCustomUnavailable: "没有可用的 API 协议。",
|
|
3161
|
+
provider: "提供商",
|
|
2967
3162
|
close: "关闭",
|
|
2968
3163
|
cancel: "取消",
|
|
2969
3164
|
apply: "保存",
|
|
@@ -2972,7 +3167,7 @@ window.__ModuleLoader__.load({
|
|
|
2972
3167
|
credentialConfigured: "API 密钥已配置",
|
|
2973
3168
|
credentialMissing: "API 密钥缺失",
|
|
2974
3169
|
readOnly: "当前部署的设置文档为只读。",
|
|
2975
|
-
loadFailed: "
|
|
3170
|
+
loadFailed: "加载提供商目录失败",
|
|
2976
3171
|
conflict: "这张卡片打开期间,这些设置已被其他地方改动。请关闭后重新打开,在当前值上编辑。",
|
|
2977
3172
|
retry: "重试",
|
|
2978
3173
|
keyInput: "API 密钥",
|
|
@@ -2982,10 +3177,9 @@ window.__ModuleLoader__.load({
|
|
|
2982
3177
|
keyEnvLocked: "由启动环境提供(只读)",
|
|
2983
3178
|
customized: "自定义设置",
|
|
2984
3179
|
baseUrl: "API 地址",
|
|
2985
|
-
baseUrlDefault: "
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
deepSeekEndpointHint: "请填写与当前连接配置兼容的 API 地址。",
|
|
3180
|
+
baseUrlDefault: "提供商默认",
|
|
3181
|
+
deepSeekBaseUrl: "https://api.deepseek.com/anthropic",
|
|
3182
|
+
deepSeekEndpointHint: "请填写兼容 Anthropic Messages 协议的 API 地址。",
|
|
2989
3183
|
models: "模型目录",
|
|
2990
3184
|
modelsInherited: "正在使用适配器默认模型",
|
|
2991
3185
|
modelsCustomized: "已自定义模型目录",
|
|
@@ -2995,39 +3189,38 @@ window.__ModuleLoader__.load({
|
|
|
2995
3189
|
modelName: "显示名称",
|
|
2996
3190
|
modelNamePlaceholder: "留空时使用模型 ID",
|
|
2997
3191
|
contextWindow: "上下文窗口",
|
|
2998
|
-
contextWindowPlaceholder: "
|
|
3192
|
+
contextWindowPlaceholder: "使用提供商默认值",
|
|
2999
3193
|
maxTokens: "最大输出 token 数",
|
|
3000
|
-
maxTokensPlaceholder: "
|
|
3001
|
-
modelAdvanced: "
|
|
3194
|
+
maxTokensPlaceholder: "使用提供商默认值",
|
|
3195
|
+
modelAdvanced: "模型选项",
|
|
3196
|
+
modelInputTypes: "输入类型",
|
|
3197
|
+
modelInputText: "文本",
|
|
3198
|
+
modelInputImage: "图片",
|
|
3002
3199
|
addModel: "添加模型",
|
|
3003
3200
|
removeModel: "删除模型",
|
|
3004
3201
|
modelsEmpty: "模型选择器中将不显示任何模型;目录外 ID 仍可直接发送。",
|
|
3005
3202
|
keyBlank: "请输入 API 密钥;留空则保持已存储的密钥。",
|
|
3006
|
-
keyBlankNew: "请输入 API
|
|
3203
|
+
keyBlankNew: "请输入 API 密钥;若该提供商以其他方式鉴权,可以留空。",
|
|
3007
3204
|
keyIllegalCharacters: "该 API 密钥格式错误,请检查。",
|
|
3008
3205
|
modelIdRequired: "模型 ID 不能为空。",
|
|
3009
3206
|
modelIdDuplicate: "模型 ID 不能重复。",
|
|
3010
3207
|
modelNameInvalid: "显示名称不能为空。",
|
|
3011
3208
|
modelContextInvalid: "上下文窗口必须是正数,例如 131072、256K 或 1M。",
|
|
3012
3209
|
modelMaxTokensInvalid: "最大输出 token 数必须是正数,例如 8192、64K 或 1M。",
|
|
3013
|
-
advancedHint: "其余字段在
|
|
3210
|
+
advancedHint: "其余字段在 cordis.patch.yml 中,请直接编辑对应段。",
|
|
3014
3211
|
modelCapacityInvalid: "容量需为数字,可加 K 或 M 后缀。",
|
|
3015
3212
|
modelDuplicate: "每个模型 ID 只能出现一次。",
|
|
3016
|
-
modelContextWindow: "上下文窗口",
|
|
3017
|
-
modelMaxTokens: "最大输出 token",
|
|
3018
3213
|
fetchModels: "获取可用模型",
|
|
3019
|
-
fetching: "
|
|
3214
|
+
fetching: "正在询问提供商…",
|
|
3020
3215
|
fetchNeedsBaseUrl: "请先填写 API 地址,再获取。",
|
|
3021
|
-
fetchEmpty: "
|
|
3216
|
+
fetchEmpty: "该提供商没有列出任何模型,请手动添加。",
|
|
3022
3217
|
fetchTitle: "选择要添加的模型",
|
|
3023
|
-
fetchDescription: "
|
|
3218
|
+
fetchDescription: "以下是模型提供商的可用模型,勾选要添加的模型。",
|
|
3024
3219
|
fetchSearch: "搜索模型",
|
|
3025
3220
|
fetchNoMatches: "没有匹配的模型。",
|
|
3026
3221
|
fetchSelectAll: "全选",
|
|
3027
3222
|
fetchDeselectAll: "取消全选",
|
|
3028
3223
|
fetchAdopt: "添加所选",
|
|
3029
|
-
customAdd: "添加自定义提供方",
|
|
3030
|
-
customTitle: "自定义提供方",
|
|
3031
3224
|
customTag: "自定义",
|
|
3032
3225
|
claudeCustomAdd: "添加 Claude 提供方",
|
|
3033
3226
|
claudeCustomTitle: "Claude 提供方",
|
|
@@ -3043,18 +3236,22 @@ window.__ModuleLoader__.load({
|
|
|
3043
3236
|
thinkingPresetFour: "四档",
|
|
3044
3237
|
thinkingPresetFive: "五档(默认)",
|
|
3045
3238
|
customRoute: "Provider ID",
|
|
3046
|
-
customRouteHint: "
|
|
3239
|
+
customRouteHint: "以小写字母开头的标识,在请求中唯一标识该提供商,并用于派生凭据名。",
|
|
3047
3240
|
customRouteInvalid: "需以小写字母开头,之后可用小写字母、数字和短横线。",
|
|
3048
|
-
customRouteTaken: "
|
|
3241
|
+
customRouteTaken: "已有提供商使用了这个 ID。",
|
|
3049
3242
|
customDisplayName: "显示名称",
|
|
3050
3243
|
customApi: "API 协议",
|
|
3051
3244
|
customApiUnset: "未选择",
|
|
3052
|
-
|
|
3245
|
+
protocolOpenAiCompletions: "OpenAI Chat Completions",
|
|
3246
|
+
protocolOpenAiResponses: "OpenAI Responses",
|
|
3247
|
+
protocolAnthropicMessages: "Anthropic Messages",
|
|
3248
|
+
customNeedsBaseUrl: "自定义模型 API 需要填写 API 地址。",
|
|
3053
3249
|
customBaseUrlInvalid: "请输入有效的 HTTP 或 HTTPS 地址。",
|
|
3054
|
-
customNeedsModels: "
|
|
3250
|
+
customNeedsModels: "自定义模型 API 至少需要一个模型。",
|
|
3055
3251
|
customBaseUrlPlaceholder: "https://gateway.example/v1",
|
|
3252
|
+
customAnthropicBaseUrlPlaceholder: "https://gateway.example",
|
|
3056
3253
|
settingsPathUnresolvable: "无法解析设置路径",
|
|
3057
|
-
create: "
|
|
3254
|
+
create: "创建提供商",
|
|
3058
3255
|
creating: "创建中…",
|
|
3059
3256
|
welcomeTitle: "内测声明",
|
|
3060
3257
|
welcomeBody: "DeepSeek Harness 目前的 0.1 版本仍处在面向 Harness 开发者进行测试的阶段,还有许多地方需要持续改进和打磨,希望听取广大开发者的反馈建议。预计 DeepSeek Harness 的核心插件以及基础 API 都会在接下来的一段时间内快速迭代、持续演化。\n\n我们期待与全球开发者一起,在开源、开放、可复用、可组合的基础设施之上,共同探索智能上限。欢迎全球 Harness 开发者加入 DSH 插件生态。",
|
|
@@ -3068,6 +3265,904 @@ window.__ModuleLoader__.load({
|
|
|
3068
3265
|
keyRequired: "请输入 API 密钥后继续。"
|
|
3069
3266
|
};
|
|
3070
3267
|
//#endregion
|
|
3268
|
+
//#region ../../../vendor/cosmokit/src/misc.ts
|
|
3269
|
+
/** Return true when a value is `null` or `undefined`. */
|
|
3270
|
+
function isNullable(value) {
|
|
3271
|
+
return value === null || value === void 0;
|
|
3272
|
+
}
|
|
3273
|
+
/** Return true for non-array object values. */
|
|
3274
|
+
function isPlainObject(data) {
|
|
3275
|
+
return data && typeof data === "object" && !Array.isArray(data);
|
|
3276
|
+
}
|
|
3277
|
+
/** Filter object entries and return a new object. */
|
|
3278
|
+
function filterKeys(object, filter) {
|
|
3279
|
+
return Object.fromEntries(Object.entries(object).filter(([key, value]) => filter(key, value)));
|
|
3280
|
+
}
|
|
3281
|
+
/** Map object values while preserving the original key set. */
|
|
3282
|
+
function mapValues(object, transform) {
|
|
3283
|
+
return Object.fromEntries(Object.entries(object).map(([key, value]) => [key, transform(value, key)]));
|
|
3284
|
+
}
|
|
3285
|
+
/** Pick selected keys from an object, optionally including `undefined` values. */
|
|
3286
|
+
function pick(source, keys, forced) {
|
|
3287
|
+
if (!keys) return { ...source };
|
|
3288
|
+
const result = {};
|
|
3289
|
+
for (const key of keys) if (forced || source[key] !== void 0) result[key] = source[key];
|
|
3290
|
+
return result;
|
|
3291
|
+
}
|
|
3292
|
+
//#endregion
|
|
3293
|
+
//#region ../../../vendor/cosmokit/src/volatile.ts
|
|
3294
|
+
/** Shared config references used by schema validators and plugin runtimes. */
|
|
3295
|
+
const write = Symbol.for("cosmokit.volatile.write");
|
|
3296
|
+
function snapshot(value, ancestors = /* @__PURE__ */ new Set()) {
|
|
3297
|
+
if (typeof value === "function") throw new TypeError("volatile config cannot contain functions");
|
|
3298
|
+
if (value === null || typeof value !== "object") return value;
|
|
3299
|
+
if (ancestors.has(value)) throw new TypeError("volatile config cannot contain cycles");
|
|
3300
|
+
ancestors.add(value);
|
|
3301
|
+
try {
|
|
3302
|
+
if (Array.isArray(value)) return Object.freeze(value.map((item) => snapshot(item, ancestors)));
|
|
3303
|
+
if (Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) throw new TypeError("volatile config objects must be plain objects or arrays");
|
|
3304
|
+
return Object.freeze(Object.fromEntries(Object.entries(value).map(([key, item]) => [key, snapshot(item, ancestors)])));
|
|
3305
|
+
} finally {
|
|
3306
|
+
ancestors.delete(value);
|
|
3307
|
+
}
|
|
3308
|
+
}
|
|
3309
|
+
/**
|
|
3310
|
+
* Create a detached reference containing an immutable copy of the supplied data.
|
|
3311
|
+
* @param value - validated config data; class instances and functions are unsupported.
|
|
3312
|
+
* @returns a reference whose value is updated only by its owning runtime.
|
|
3313
|
+
*/
|
|
3314
|
+
function createVolatile(value) {
|
|
3315
|
+
let current = snapshot(value);
|
|
3316
|
+
return Object.freeze({
|
|
3317
|
+
get: () => current,
|
|
3318
|
+
[write]: (value) => {
|
|
3319
|
+
current = value;
|
|
3320
|
+
}
|
|
3321
|
+
});
|
|
3322
|
+
}
|
|
3323
|
+
/**
|
|
3324
|
+
* Identify references across ESM/CJS copies of the shared library.
|
|
3325
|
+
* @param value - a parsed config value.
|
|
3326
|
+
* @returns whether the value implements the shared reference protocol.
|
|
3327
|
+
*/
|
|
3328
|
+
function isVolatile(value) {
|
|
3329
|
+
return typeof value === "object" && value !== null && write in value;
|
|
3330
|
+
}
|
|
3331
|
+
//#endregion
|
|
3332
|
+
//#region ../../../vendor/cosmokit/src/types.ts
|
|
3333
|
+
/** Test values using `instanceof` with a `toStringTag` fallback. */
|
|
3334
|
+
function is(type, value) {
|
|
3335
|
+
if (arguments.length === 1) return (value) => is(type, value);
|
|
3336
|
+
return type in globalThis && value instanceof globalThis[type] || Object.prototype.toString.call(value).slice(8, -1) === type;
|
|
3337
|
+
}
|
|
3338
|
+
function isArrayBufferLike(value) {
|
|
3339
|
+
return is("ArrayBuffer", value) || is("SharedArrayBuffer", value);
|
|
3340
|
+
}
|
|
3341
|
+
function isArrayBufferSource(value) {
|
|
3342
|
+
return isArrayBufferLike(value) || ArrayBuffer.isView(value);
|
|
3343
|
+
}
|
|
3344
|
+
let Binary;
|
|
3345
|
+
(function(_Binary) {
|
|
3346
|
+
_Binary.is = isArrayBufferLike;
|
|
3347
|
+
_Binary.isSource = isArrayBufferSource;
|
|
3348
|
+
function fromSource(source) {
|
|
3349
|
+
if (ArrayBuffer.isView(source)) return source.buffer.slice(source.byteOffset, source.byteOffset + source.byteLength);
|
|
3350
|
+
else return source;
|
|
3351
|
+
}
|
|
3352
|
+
_Binary.fromSource = fromSource;
|
|
3353
|
+
function toBase64(source) {
|
|
3354
|
+
source = fromSource(source);
|
|
3355
|
+
if (typeof Buffer !== "undefined") return Buffer.from(source).toString("base64");
|
|
3356
|
+
let binary = "";
|
|
3357
|
+
const bytes = new Uint8Array(source);
|
|
3358
|
+
for (let i = 0; i < bytes.byteLength; i++) binary += String.fromCharCode(bytes[i]);
|
|
3359
|
+
return btoa(binary);
|
|
3360
|
+
}
|
|
3361
|
+
_Binary.toBase64 = toBase64;
|
|
3362
|
+
function fromBase64(source) {
|
|
3363
|
+
if (typeof Buffer !== "undefined") return fromSource(Buffer.from(source, "base64"));
|
|
3364
|
+
return Uint8Array.from(atob(source), (c) => c.charCodeAt(0));
|
|
3365
|
+
}
|
|
3366
|
+
_Binary.fromBase64 = fromBase64;
|
|
3367
|
+
function toHex(source) {
|
|
3368
|
+
source = fromSource(source);
|
|
3369
|
+
if (typeof Buffer !== "undefined") return Buffer.from(source).toString("hex");
|
|
3370
|
+
return Array.from(new Uint8Array(source), (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
3371
|
+
}
|
|
3372
|
+
_Binary.toHex = toHex;
|
|
3373
|
+
function fromHex(source) {
|
|
3374
|
+
if (typeof Buffer !== "undefined") return fromSource(Buffer.from(source, "hex"));
|
|
3375
|
+
const hex = source.length % 2 === 0 ? source : source.slice(0, source.length - 1);
|
|
3376
|
+
const buffer = [];
|
|
3377
|
+
for (let i = 0; i < hex.length; i += 2) buffer.push(parseInt(`${hex[i]}${hex[i + 1]}`, 16));
|
|
3378
|
+
return Uint8Array.from(buffer).buffer;
|
|
3379
|
+
}
|
|
3380
|
+
_Binary.fromHex = fromHex;
|
|
3381
|
+
})(Binary || (Binary = {}));
|
|
3382
|
+
Binary.fromBase64;
|
|
3383
|
+
Binary.toBase64;
|
|
3384
|
+
Binary.fromHex;
|
|
3385
|
+
Binary.toHex;
|
|
3386
|
+
/** Deep-clone common JavaScript values while preserving prototypes and cycles. */
|
|
3387
|
+
function clone(source, refs = /* @__PURE__ */ new Map()) {
|
|
3388
|
+
if (!source || typeof source !== "object") return source;
|
|
3389
|
+
if (is("Date", source)) return new Date(source.valueOf());
|
|
3390
|
+
if (is("RegExp", source)) return new RegExp(source.source, source.flags);
|
|
3391
|
+
if (isArrayBufferLike(source)) return source.slice(0);
|
|
3392
|
+
if (ArrayBuffer.isView(source)) return source.buffer.slice(source.byteOffset, source.byteOffset + source.byteLength);
|
|
3393
|
+
const cached = refs.get(source);
|
|
3394
|
+
if (cached) return cached;
|
|
3395
|
+
if (Array.isArray(source)) {
|
|
3396
|
+
const result = [];
|
|
3397
|
+
refs.set(source, result);
|
|
3398
|
+
source.forEach((value, index) => {
|
|
3399
|
+
result[index] = Reflect.apply(clone, null, [value, refs]);
|
|
3400
|
+
});
|
|
3401
|
+
return result;
|
|
3402
|
+
}
|
|
3403
|
+
const result = Object.create(Object.getPrototypeOf(source));
|
|
3404
|
+
refs.set(source, result);
|
|
3405
|
+
for (const key of Reflect.ownKeys(source)) {
|
|
3406
|
+
const descriptor = { ...Reflect.getOwnPropertyDescriptor(source, key) };
|
|
3407
|
+
if ("value" in descriptor) descriptor.value = Reflect.apply(clone, null, [descriptor.value, refs]);
|
|
3408
|
+
Reflect.defineProperty(result, key, descriptor);
|
|
3409
|
+
}
|
|
3410
|
+
return result;
|
|
3411
|
+
}
|
|
3412
|
+
/**
|
|
3413
|
+
* Compare values recursively, treating two volatile references as equal regardless of value.
|
|
3414
|
+
* Strict comparison distinguishes null/undefined, treats opaque objects by identity,
|
|
3415
|
+
* compares URLs by normalized href, treats array holes as undefined, and considers distinct cyclic structures unequal.
|
|
3416
|
+
* @param a - first value.
|
|
3417
|
+
* @param b - second value.
|
|
3418
|
+
* @param strict - whether to require strict data equality outside volatile references.
|
|
3419
|
+
* @returns whether the values compare equal.
|
|
3420
|
+
*/
|
|
3421
|
+
function deepEqual(a, b, strict) {
|
|
3422
|
+
const ancestors = /* @__PURE__ */ new Set();
|
|
3423
|
+
function compare(a, b) {
|
|
3424
|
+
if (a === b) return true;
|
|
3425
|
+
if (isVolatile(a) || isVolatile(b)) return isVolatile(a) && isVolatile(b);
|
|
3426
|
+
if (!strict && isNullable(a) && isNullable(b)) return true;
|
|
3427
|
+
if (typeof a !== typeof b || typeof a !== "object" || !a || !b) return false;
|
|
3428
|
+
if (ancestors.has(a)) return false;
|
|
3429
|
+
function check(test, then) {
|
|
3430
|
+
return test(a) ? test(b) ? then(a, b) : false : test(b) ? false : void 0;
|
|
3431
|
+
}
|
|
3432
|
+
ancestors.add(a);
|
|
3433
|
+
try {
|
|
3434
|
+
return check(Array.isArray, (a, b) => {
|
|
3435
|
+
if (a.length !== b.length) return false;
|
|
3436
|
+
for (let index = 0; index < a.length; index++) if (!compare(a[index], b[index])) return false;
|
|
3437
|
+
return true;
|
|
3438
|
+
}) ?? check(is("Date"), (a, b) => a.valueOf() === b.valueOf()) ?? check(is("URL"), (a, b) => a.href === b.href) ?? check(is("RegExp"), (a, b) => a.source === b.source && a.flags === b.flags) ?? check(isArrayBufferLike, (a, b) => {
|
|
3439
|
+
if (a.byteLength !== b.byteLength) return false;
|
|
3440
|
+
const viewA = new Uint8Array(a);
|
|
3441
|
+
const viewB = new Uint8Array(b);
|
|
3442
|
+
for (let i = 0; i < viewA.length; i++) if (viewA[i] !== viewB[i]) return false;
|
|
3443
|
+
return true;
|
|
3444
|
+
}) ?? ((!strict || [a, b].every((value) => Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null)) && Object.keys({
|
|
3445
|
+
...a,
|
|
3446
|
+
...b
|
|
3447
|
+
}).every((key) => compare(a[key], b[key])));
|
|
3448
|
+
} finally {
|
|
3449
|
+
ancestors.delete(a);
|
|
3450
|
+
}
|
|
3451
|
+
}
|
|
3452
|
+
return compare(a, b);
|
|
3453
|
+
}
|
|
3454
|
+
//#endregion
|
|
3455
|
+
//#region ../../../vendor/cosmokit/src/time.ts
|
|
3456
|
+
let Time;
|
|
3457
|
+
(function(_Time) {
|
|
3458
|
+
_Time.millisecond = 1;
|
|
3459
|
+
const second = _Time.second = 1e3;
|
|
3460
|
+
const minute = _Time.minute = second * 60;
|
|
3461
|
+
const hour = _Time.hour = minute * 60;
|
|
3462
|
+
const day = _Time.day = hour * 24;
|
|
3463
|
+
const week = _Time.week = day * 7;
|
|
3464
|
+
let timezoneOffset = (/* @__PURE__ */ new Date()).getTimezoneOffset();
|
|
3465
|
+
function setTimezoneOffset(offset) {
|
|
3466
|
+
timezoneOffset = offset;
|
|
3467
|
+
}
|
|
3468
|
+
_Time.setTimezoneOffset = setTimezoneOffset;
|
|
3469
|
+
function getTimezoneOffset() {
|
|
3470
|
+
return timezoneOffset;
|
|
3471
|
+
}
|
|
3472
|
+
_Time.getTimezoneOffset = getTimezoneOffset;
|
|
3473
|
+
function getDateNumber(date = /* @__PURE__ */ new Date(), offset) {
|
|
3474
|
+
if (typeof date === "number") date = new Date(date);
|
|
3475
|
+
if (offset === void 0) offset = timezoneOffset;
|
|
3476
|
+
return Math.floor((date.valueOf() / minute - offset) / 1440);
|
|
3477
|
+
}
|
|
3478
|
+
_Time.getDateNumber = getDateNumber;
|
|
3479
|
+
function fromDateNumber(value, offset) {
|
|
3480
|
+
const date = new Date(value * day);
|
|
3481
|
+
if (offset === void 0) offset = timezoneOffset;
|
|
3482
|
+
return new Date(+date + offset * minute);
|
|
3483
|
+
}
|
|
3484
|
+
_Time.fromDateNumber = fromDateNumber;
|
|
3485
|
+
const numeric = /\d+(?:\.\d+)?/.source;
|
|
3486
|
+
const timeRegExp = new RegExp(`^${[
|
|
3487
|
+
"w(?:eek(?:s)?)?",
|
|
3488
|
+
"d(?:ay(?:s)?)?",
|
|
3489
|
+
"h(?:our(?:s)?)?",
|
|
3490
|
+
"m(?:in(?:ute)?(?:s)?)?",
|
|
3491
|
+
"s(?:ec(?:ond)?(?:s)?)?"
|
|
3492
|
+
].map((unit) => `(${numeric}${unit})?`).join("")}$`);
|
|
3493
|
+
function parseTime(source) {
|
|
3494
|
+
const capture = timeRegExp.exec(source);
|
|
3495
|
+
if (!capture) return 0;
|
|
3496
|
+
return (parseFloat(capture[1]) * week || 0) + (parseFloat(capture[2]) * day || 0) + (parseFloat(capture[3]) * hour || 0) + (parseFloat(capture[4]) * minute || 0) + (parseFloat(capture[5]) * second || 0);
|
|
3497
|
+
}
|
|
3498
|
+
_Time.parseTime = parseTime;
|
|
3499
|
+
function parseDate(date) {
|
|
3500
|
+
const parsed = parseTime(date);
|
|
3501
|
+
if (parsed) date = Date.now() + parsed;
|
|
3502
|
+
else if (/^\d{1,2}(:\d{1,2}){1,2}$/.test(date)) date = `${(/* @__PURE__ */ new Date()).toLocaleDateString()}-${date}`;
|
|
3503
|
+
else if (/^\d{1,2}-\d{1,2}-\d{1,2}(:\d{1,2}){1,2}$/.test(date)) date = `${(/* @__PURE__ */ new Date()).getFullYear()}-${date}`;
|
|
3504
|
+
return date ? new Date(date) : /* @__PURE__ */ new Date();
|
|
3505
|
+
}
|
|
3506
|
+
_Time.parseDate = parseDate;
|
|
3507
|
+
function format(ms) {
|
|
3508
|
+
const abs = Math.abs(ms);
|
|
3509
|
+
if (abs >= day - hour / 2) return Math.round(ms / day) + "d";
|
|
3510
|
+
else if (abs >= hour - minute / 2) return Math.round(ms / hour) + "h";
|
|
3511
|
+
else if (abs >= minute - second / 2) return Math.round(ms / minute) + "m";
|
|
3512
|
+
else if (abs >= second) return Math.round(ms / second) + "s";
|
|
3513
|
+
return ms + "ms";
|
|
3514
|
+
}
|
|
3515
|
+
_Time.format = format;
|
|
3516
|
+
function toDigits(source, length = 2) {
|
|
3517
|
+
return source.toString().padStart(length, "0");
|
|
3518
|
+
}
|
|
3519
|
+
_Time.toDigits = toDigits;
|
|
3520
|
+
function template(template, time = /* @__PURE__ */ new Date()) {
|
|
3521
|
+
return template.replace("yyyy", time.getFullYear().toString()).replace("yy", time.getFullYear().toString().slice(2)).replace("MM", toDigits(time.getMonth() + 1)).replace("dd", toDigits(time.getDate())).replace("hh", toDigits(time.getHours())).replace("mm", toDigits(time.getMinutes())).replace("ss", toDigits(time.getSeconds())).replace("SSS", toDigits(time.getMilliseconds(), 3));
|
|
3522
|
+
}
|
|
3523
|
+
_Time.template = template;
|
|
3524
|
+
})(Time || (Time = {}));
|
|
3525
|
+
//#endregion
|
|
3526
|
+
//#region ../../../vendor/schemastery/src/index.ts
|
|
3527
|
+
const kSchema = Symbol.for("schemastery");
|
|
3528
|
+
const kValidationError = Symbol.for("ValidationError");
|
|
3529
|
+
globalThis.__schemastery_index__ ??= 0;
|
|
3530
|
+
globalThis.__schemastery_refs__ = void 0;
|
|
3531
|
+
var ValidationError = class extends TypeError {
|
|
3532
|
+
options;
|
|
3533
|
+
name = "ValidationError";
|
|
3534
|
+
constructor(message, options) {
|
|
3535
|
+
let prefix = "$";
|
|
3536
|
+
for (const segment of options.path || []) if (typeof segment === "string") prefix += "." + segment;
|
|
3537
|
+
else if (typeof segment === "number") prefix += "[" + segment + "]";
|
|
3538
|
+
else if (typeof segment === "symbol") prefix += `[Symbol(${segment.toString()})]`;
|
|
3539
|
+
if (prefix.startsWith(".")) prefix = prefix.slice(1);
|
|
3540
|
+
super((prefix === "$" ? "" : `${prefix} `) + message);
|
|
3541
|
+
this.options = options;
|
|
3542
|
+
}
|
|
3543
|
+
static is(error) {
|
|
3544
|
+
return !!error?.[kValidationError];
|
|
3545
|
+
}
|
|
3546
|
+
};
|
|
3547
|
+
Object.defineProperty(ValidationError.prototype, kValidationError, { value: true });
|
|
3548
|
+
const Schema = function(options) {
|
|
3549
|
+
const schema = function(data, options = {}) {
|
|
3550
|
+
return Schema.resolve(data, schema, options)[0];
|
|
3551
|
+
};
|
|
3552
|
+
if (options.refs) {
|
|
3553
|
+
const refs = mapValues(options.refs, (options) => new Schema(options));
|
|
3554
|
+
const getRef = (uid) => refs[uid];
|
|
3555
|
+
for (const key in refs) {
|
|
3556
|
+
const options = refs[key];
|
|
3557
|
+
options.sKey = getRef(options.sKey);
|
|
3558
|
+
options.inner = getRef(options.inner);
|
|
3559
|
+
options.list = options.list && options.list.map(getRef);
|
|
3560
|
+
options.dict = options.dict && mapValues(options.dict, getRef);
|
|
3561
|
+
}
|
|
3562
|
+
return refs[options.uid];
|
|
3563
|
+
}
|
|
3564
|
+
Object.assign(schema, options);
|
|
3565
|
+
if (typeof schema.callback === "string") try {
|
|
3566
|
+
schema.callback = new Function("return " + schema.callback)();
|
|
3567
|
+
} catch {}
|
|
3568
|
+
Object.defineProperty(schema, "uid", { value: globalThis.__schemastery_index__++ });
|
|
3569
|
+
Object.setPrototypeOf(schema, Schema.prototype);
|
|
3570
|
+
schema.meta ||= {};
|
|
3571
|
+
schema.toString = schema.toString.bind(schema);
|
|
3572
|
+
return schema;
|
|
3573
|
+
};
|
|
3574
|
+
Schema.prototype = Object.create(Function.prototype);
|
|
3575
|
+
Schema.prototype[kSchema] = true;
|
|
3576
|
+
Object.defineProperty(Schema.prototype, "~standard", { get() {
|
|
3577
|
+
return {
|
|
3578
|
+
version: 1,
|
|
3579
|
+
vendor: "schemastery",
|
|
3580
|
+
validate: (value) => {
|
|
3581
|
+
try {
|
|
3582
|
+
return { value: Schema.resolve(value, this, {})[0] };
|
|
3583
|
+
} catch (error) {
|
|
3584
|
+
if (ValidationError.is(error)) return { issues: [{
|
|
3585
|
+
message: error.message,
|
|
3586
|
+
path: error.options.path
|
|
3587
|
+
}] };
|
|
3588
|
+
throw error;
|
|
3589
|
+
}
|
|
3590
|
+
}
|
|
3591
|
+
};
|
|
3592
|
+
} });
|
|
3593
|
+
Schema.ValidationError = ValidationError;
|
|
3594
|
+
Schema.prototype.toJSON = function toJSON() {
|
|
3595
|
+
if (globalThis.__schemastery_refs__) {
|
|
3596
|
+
globalThis.__schemastery_refs__[this.uid] ??= JSON.parse(JSON.stringify({ ...this }));
|
|
3597
|
+
return this.uid;
|
|
3598
|
+
}
|
|
3599
|
+
globalThis.__schemastery_refs__ = { [this.uid]: { ...this } };
|
|
3600
|
+
globalThis.__schemastery_refs__[this.uid] = JSON.parse(JSON.stringify({ ...this }));
|
|
3601
|
+
const result = {
|
|
3602
|
+
uid: this.uid,
|
|
3603
|
+
refs: globalThis.__schemastery_refs__
|
|
3604
|
+
};
|
|
3605
|
+
globalThis.__schemastery_refs__ = void 0;
|
|
3606
|
+
return result;
|
|
3607
|
+
};
|
|
3608
|
+
Schema.prototype.set = function set(key, value) {
|
|
3609
|
+
this.dict[key] = value;
|
|
3610
|
+
return this;
|
|
3611
|
+
};
|
|
3612
|
+
Schema.prototype.push = function push(value) {
|
|
3613
|
+
this.list.push(value);
|
|
3614
|
+
return this;
|
|
3615
|
+
};
|
|
3616
|
+
function mergeDesc(original, messages) {
|
|
3617
|
+
const result = typeof original === "string" ? { "": original } : { ...original };
|
|
3618
|
+
for (const locale in messages) {
|
|
3619
|
+
const value = messages[locale];
|
|
3620
|
+
if (value?.$description || value?.$desc) result[locale] = value.$description || value.$desc;
|
|
3621
|
+
else if (typeof value === "string") result[locale] = value;
|
|
3622
|
+
}
|
|
3623
|
+
return result;
|
|
3624
|
+
}
|
|
3625
|
+
function getInner(value) {
|
|
3626
|
+
return value?.$value ?? value?.$inner;
|
|
3627
|
+
}
|
|
3628
|
+
function extractKeys(data) {
|
|
3629
|
+
return filterKeys(data ?? {}, (key) => !key.startsWith("$"));
|
|
3630
|
+
}
|
|
3631
|
+
Schema.prototype.i18n = function i18n(messages) {
|
|
3632
|
+
const schema = Schema(this);
|
|
3633
|
+
const desc = mergeDesc(schema.meta.description, messages);
|
|
3634
|
+
if (Object.keys(desc).length) schema.meta.description = desc;
|
|
3635
|
+
if (schema.dict) schema.dict = mapValues(schema.dict, (inner, key) => {
|
|
3636
|
+
return inner.i18n(mapValues(messages, (data) => getInner(data)?.[key] ?? data?.[key]));
|
|
3637
|
+
});
|
|
3638
|
+
if (schema.list) schema.list = schema.list.map((inner, index) => {
|
|
3639
|
+
return inner.i18n(mapValues(messages, (data = {}) => {
|
|
3640
|
+
if (Array.isArray(getInner(data))) return getInner(data)[index];
|
|
3641
|
+
if (Array.isArray(data)) return data[index];
|
|
3642
|
+
return extractKeys(data);
|
|
3643
|
+
}));
|
|
3644
|
+
});
|
|
3645
|
+
if (schema.inner) schema.inner = schema.inner.i18n(mapValues(messages, (data) => {
|
|
3646
|
+
if (getInner(data)) return getInner(data);
|
|
3647
|
+
return extractKeys(data);
|
|
3648
|
+
}));
|
|
3649
|
+
if (schema.sKey) schema.sKey = schema.sKey.i18n(mapValues(messages, (data) => data?.$key));
|
|
3650
|
+
return schema;
|
|
3651
|
+
};
|
|
3652
|
+
Schema.prototype.extra = function extra(key, value) {
|
|
3653
|
+
const schema = Schema(this);
|
|
3654
|
+
schema.meta = {
|
|
3655
|
+
...schema.meta,
|
|
3656
|
+
[key]: value
|
|
3657
|
+
};
|
|
3658
|
+
return schema;
|
|
3659
|
+
};
|
|
3660
|
+
for (const key of [
|
|
3661
|
+
"required",
|
|
3662
|
+
"disabled",
|
|
3663
|
+
"collapse",
|
|
3664
|
+
"hidden",
|
|
3665
|
+
"loose"
|
|
3666
|
+
]) Object.assign(Schema.prototype, { [key](value = true) {
|
|
3667
|
+
const schema = Schema(this);
|
|
3668
|
+
schema.meta = {
|
|
3669
|
+
...schema.meta,
|
|
3670
|
+
[key]: value
|
|
3671
|
+
};
|
|
3672
|
+
return schema;
|
|
3673
|
+
} });
|
|
3674
|
+
Schema.prototype.deprecated = function deprecated() {
|
|
3675
|
+
const schema = Schema(this);
|
|
3676
|
+
schema.meta.badges ||= [];
|
|
3677
|
+
schema.meta.badges.push({
|
|
3678
|
+
text: "deprecated",
|
|
3679
|
+
type: "danger"
|
|
3680
|
+
});
|
|
3681
|
+
return schema;
|
|
3682
|
+
};
|
|
3683
|
+
Schema.prototype.experimental = function experimental() {
|
|
3684
|
+
const schema = Schema(this);
|
|
3685
|
+
schema.meta.badges ||= [];
|
|
3686
|
+
schema.meta.badges.push({
|
|
3687
|
+
text: "experimental",
|
|
3688
|
+
type: "warning"
|
|
3689
|
+
});
|
|
3690
|
+
return schema;
|
|
3691
|
+
};
|
|
3692
|
+
Schema.prototype.pattern = function pattern(regexp) {
|
|
3693
|
+
const schema = Schema(this);
|
|
3694
|
+
const pattern = pick(regexp, ["source", "flags"]);
|
|
3695
|
+
schema.meta = {
|
|
3696
|
+
...schema.meta,
|
|
3697
|
+
pattern
|
|
3698
|
+
};
|
|
3699
|
+
return schema;
|
|
3700
|
+
};
|
|
3701
|
+
Schema.prototype.simplify = function simplify(value) {
|
|
3702
|
+
if (isVolatile(value)) value = value.get();
|
|
3703
|
+
if (deepEqual(value, this.meta.default, this.type === "dict")) return null;
|
|
3704
|
+
if (isNullable(value)) return value;
|
|
3705
|
+
if (this.type === "object" || this.type === "dict") {
|
|
3706
|
+
const result = {};
|
|
3707
|
+
for (const key in value) {
|
|
3708
|
+
const item = (this.type === "object" ? this.dict[key] : this.inner)?.simplify(value[key]);
|
|
3709
|
+
if (this.type === "dict" || !isNullable(item)) result[key] = item;
|
|
3710
|
+
}
|
|
3711
|
+
if (deepEqual(result, this.meta.default, this.type === "dict")) return null;
|
|
3712
|
+
return result;
|
|
3713
|
+
} else if (this.type === "array" || this.type === "tuple") {
|
|
3714
|
+
const result = [];
|
|
3715
|
+
value.forEach((value, index) => {
|
|
3716
|
+
const schema = this.type === "array" ? this.inner : this.list[index];
|
|
3717
|
+
const item = schema ? schema.simplify(value) : value;
|
|
3718
|
+
result.push(item);
|
|
3719
|
+
});
|
|
3720
|
+
return result;
|
|
3721
|
+
} else if (this.type === "intersect") {
|
|
3722
|
+
const result = {};
|
|
3723
|
+
for (const item of this.list) Object.assign(result, item.simplify(value));
|
|
3724
|
+
return result;
|
|
3725
|
+
} else if (this.type === "union") for (const schema of this.list) try {
|
|
3726
|
+
Schema.resolve(value, schema, {});
|
|
3727
|
+
return schema.simplify(value);
|
|
3728
|
+
} catch {}
|
|
3729
|
+
return value;
|
|
3730
|
+
};
|
|
3731
|
+
Schema.prototype.toString = function toString(inline) {
|
|
3732
|
+
return formatters[this.type]?.(this, inline) ?? `Schema<${this.type}>`;
|
|
3733
|
+
};
|
|
3734
|
+
Schema.prototype.role = function role(role, extra) {
|
|
3735
|
+
const schema = Schema(this);
|
|
3736
|
+
schema.meta = {
|
|
3737
|
+
...schema.meta,
|
|
3738
|
+
role,
|
|
3739
|
+
extra
|
|
3740
|
+
};
|
|
3741
|
+
return schema;
|
|
3742
|
+
};
|
|
3743
|
+
for (const key of [
|
|
3744
|
+
"default",
|
|
3745
|
+
"link",
|
|
3746
|
+
"comment",
|
|
3747
|
+
"description",
|
|
3748
|
+
"max",
|
|
3749
|
+
"min",
|
|
3750
|
+
"step"
|
|
3751
|
+
]) Object.assign(Schema.prototype, { [key](value) {
|
|
3752
|
+
const schema = Schema(this);
|
|
3753
|
+
schema.meta = {
|
|
3754
|
+
...schema.meta,
|
|
3755
|
+
[key]: value
|
|
3756
|
+
};
|
|
3757
|
+
return schema;
|
|
3758
|
+
} });
|
|
3759
|
+
Schema.prototype.volatile = function volatile() {
|
|
3760
|
+
if (this.meta.volatile) throw new TypeError("volatile schema is already wrapped");
|
|
3761
|
+
return this.extra("volatile", true);
|
|
3762
|
+
};
|
|
3763
|
+
const resolvers = {};
|
|
3764
|
+
const checkedVolatile = Symbol("checked-volatile-schema");
|
|
3765
|
+
function validateVolatileSchema(schema, path = [], blocked = false, seen = /* @__PURE__ */ new Map()) {
|
|
3766
|
+
const states = seen.get(schema) ?? /* @__PURE__ */ new Set();
|
|
3767
|
+
if (states.has(blocked)) return;
|
|
3768
|
+
states.add(blocked);
|
|
3769
|
+
seen.set(schema, states);
|
|
3770
|
+
if (schema.meta?.volatile && blocked) throw new ValidationError("volatile fields require a fixed object path without an enclosing volatile field", { path });
|
|
3771
|
+
const nested = blocked || !!schema.meta?.volatile;
|
|
3772
|
+
if (schema.dict) for (const [key, child] of Object.entries(schema.dict)) validateVolatileSchema(child, [...path, key], nested, seen);
|
|
3773
|
+
if (schema.sKey) validateVolatileSchema(schema.sKey, [...path, "<key>"], true, seen);
|
|
3774
|
+
if (schema.inner && (schema.type !== "lazy" || schema.inner[kSchema])) validateVolatileSchema(schema.inner, [...path, "*"], true, seen);
|
|
3775
|
+
if (schema.list) for (let index = 0; index < schema.list.length; index++) validateVolatileSchema(schema.list[index], [...path, String(index)], true, seen);
|
|
3776
|
+
}
|
|
3777
|
+
Schema.extend = function extend(type, resolve) {
|
|
3778
|
+
resolvers[type] = resolve;
|
|
3779
|
+
};
|
|
3780
|
+
Schema.resolve = function resolve(data, schema, options = {}, strict = false) {
|
|
3781
|
+
if (!schema) return [data];
|
|
3782
|
+
if (!options[checkedVolatile]) {
|
|
3783
|
+
validateVolatileSchema(schema, options.path);
|
|
3784
|
+
options = {
|
|
3785
|
+
...options,
|
|
3786
|
+
[checkedVolatile]: true
|
|
3787
|
+
};
|
|
3788
|
+
}
|
|
3789
|
+
if (schema.meta?.volatile) {
|
|
3790
|
+
const inner = Schema(schema);
|
|
3791
|
+
inner.meta = {
|
|
3792
|
+
...schema.meta,
|
|
3793
|
+
volatile: false
|
|
3794
|
+
};
|
|
3795
|
+
const [value, adapted] = Schema.resolve(data, inner, options, strict);
|
|
3796
|
+
try {
|
|
3797
|
+
return [createVolatile(value), adapted];
|
|
3798
|
+
} catch (error) {
|
|
3799
|
+
throw new ValidationError(error instanceof Error ? error.message : String(error), options);
|
|
3800
|
+
}
|
|
3801
|
+
}
|
|
3802
|
+
if (options.ignore?.(data, schema)) return [data];
|
|
3803
|
+
if (isNullable(data) && schema.type !== "lazy") {
|
|
3804
|
+
if (schema.meta.required) throw new ValidationError(`missing required value`, options);
|
|
3805
|
+
let current = schema;
|
|
3806
|
+
let fallback = schema.meta.default;
|
|
3807
|
+
while (current?.type === "intersect" && isNullable(fallback)) {
|
|
3808
|
+
current = current.list[0];
|
|
3809
|
+
fallback = current?.meta.default;
|
|
3810
|
+
}
|
|
3811
|
+
if (isNullable(fallback)) return [data];
|
|
3812
|
+
data = clone(fallback);
|
|
3813
|
+
}
|
|
3814
|
+
const callback = resolvers[schema.type];
|
|
3815
|
+
if (!callback) throw new ValidationError(`unsupported type "${schema.type}"`, options);
|
|
3816
|
+
try {
|
|
3817
|
+
return callback(data, schema, options, strict);
|
|
3818
|
+
} catch (error) {
|
|
3819
|
+
if (!schema.meta.loose) throw error;
|
|
3820
|
+
return [schema.meta.default];
|
|
3821
|
+
}
|
|
3822
|
+
};
|
|
3823
|
+
Schema.from = function from(source) {
|
|
3824
|
+
if (isNullable(source)) return Schema.any();
|
|
3825
|
+
else if ([
|
|
3826
|
+
"string",
|
|
3827
|
+
"number",
|
|
3828
|
+
"boolean"
|
|
3829
|
+
].includes(typeof source)) return Schema.const(source).required();
|
|
3830
|
+
else if (source[kSchema]) return source;
|
|
3831
|
+
else if (typeof source === "function") switch (source) {
|
|
3832
|
+
case String: return Schema.string().required();
|
|
3833
|
+
case Number: return Schema.number().required();
|
|
3834
|
+
case Boolean: return Schema.boolean().required();
|
|
3835
|
+
case Function: return Schema.function().required();
|
|
3836
|
+
default: return Schema.is(source).required();
|
|
3837
|
+
}
|
|
3838
|
+
else throw new TypeError(`cannot infer schema from ${source}`);
|
|
3839
|
+
};
|
|
3840
|
+
Schema.lazy = function lazy(builder) {
|
|
3841
|
+
const toJSON = () => {
|
|
3842
|
+
if (!schema.inner[kSchema]) {
|
|
3843
|
+
schema.inner = schema.builder();
|
|
3844
|
+
schema.inner.meta = {
|
|
3845
|
+
...schema.meta,
|
|
3846
|
+
...schema.inner.meta
|
|
3847
|
+
};
|
|
3848
|
+
}
|
|
3849
|
+
return schema.inner.toJSON();
|
|
3850
|
+
};
|
|
3851
|
+
const schema = new Schema({
|
|
3852
|
+
type: "lazy",
|
|
3853
|
+
builder,
|
|
3854
|
+
inner: { toJSON }
|
|
3855
|
+
});
|
|
3856
|
+
return schema;
|
|
3857
|
+
};
|
|
3858
|
+
Schema.natural = function natural() {
|
|
3859
|
+
return Schema.number().step(1).min(0);
|
|
3860
|
+
};
|
|
3861
|
+
Schema.percent = function percent() {
|
|
3862
|
+
return Schema.number().step(.01).min(0).max(1).role("slider");
|
|
3863
|
+
};
|
|
3864
|
+
Schema.date = function date() {
|
|
3865
|
+
return Schema.union([Schema.is(Date), Schema.transform(Schema.string().role("datetime"), (value, options) => {
|
|
3866
|
+
const date = new Date(value);
|
|
3867
|
+
if (isNaN(+date)) throw new ValidationError(`invalid date "${value}"`, options);
|
|
3868
|
+
return date;
|
|
3869
|
+
}, true)]);
|
|
3870
|
+
};
|
|
3871
|
+
Schema.regExp = function regExp(flag = "") {
|
|
3872
|
+
return Schema.union([Schema.is(RegExp), Schema.transform(Schema.string().role("regexp", { flag }), (value, options) => {
|
|
3873
|
+
try {
|
|
3874
|
+
return new RegExp(value, flag);
|
|
3875
|
+
} catch (e) {
|
|
3876
|
+
throw new ValidationError(e.message, options);
|
|
3877
|
+
}
|
|
3878
|
+
}, true)]);
|
|
3879
|
+
};
|
|
3880
|
+
Schema.arrayBuffer = function arrayBuffer(encoding) {
|
|
3881
|
+
return Schema.union([
|
|
3882
|
+
Schema.is(ArrayBuffer),
|
|
3883
|
+
Schema.is(SharedArrayBuffer),
|
|
3884
|
+
Schema.transform(Schema.any(), (value, options) => {
|
|
3885
|
+
if (Binary.isSource(value)) return Binary.fromSource(value);
|
|
3886
|
+
throw new ValidationError(`expected ArrayBufferSource but got ${value}`, options);
|
|
3887
|
+
}, true),
|
|
3888
|
+
...encoding ? [Schema.transform(Schema.string(), (value, options) => {
|
|
3889
|
+
try {
|
|
3890
|
+
return encoding === "base64" ? Binary.fromBase64(value) : Binary.fromHex(value);
|
|
3891
|
+
} catch (e) {
|
|
3892
|
+
throw new ValidationError(e.message, options);
|
|
3893
|
+
}
|
|
3894
|
+
}, true)] : []
|
|
3895
|
+
]);
|
|
3896
|
+
};
|
|
3897
|
+
Schema.extend("lazy", (data, schema, options, strict) => {
|
|
3898
|
+
if (!schema.inner[kSchema]) {
|
|
3899
|
+
schema.inner = schema.builder();
|
|
3900
|
+
schema.inner.meta = {
|
|
3901
|
+
...schema.meta,
|
|
3902
|
+
...schema.inner.meta
|
|
3903
|
+
};
|
|
3904
|
+
validateVolatileSchema(schema.inner, options.path, true);
|
|
3905
|
+
}
|
|
3906
|
+
return Schema.resolve(data, schema.inner, options, strict);
|
|
3907
|
+
});
|
|
3908
|
+
Schema.extend("any", (data) => {
|
|
3909
|
+
return [data];
|
|
3910
|
+
});
|
|
3911
|
+
Schema.extend("never", (data, _, options) => {
|
|
3912
|
+
throw new ValidationError(`expected nullable but got ${data}`, options);
|
|
3913
|
+
});
|
|
3914
|
+
Schema.extend("const", (data, { value }, options) => {
|
|
3915
|
+
if (deepEqual(data, value)) return [value];
|
|
3916
|
+
throw new ValidationError(`expected ${value} but got ${data}`, options);
|
|
3917
|
+
});
|
|
3918
|
+
function checkWithinRange(data, meta, description, options, skipMin = false) {
|
|
3919
|
+
const { max = Infinity, min = -Infinity } = meta;
|
|
3920
|
+
if (data > max) throw new ValidationError(`expected ${description} <= ${max} but got ${data}`, options);
|
|
3921
|
+
if (data < min && !skipMin) throw new ValidationError(`expected ${description} >= ${min} but got ${data}`, options);
|
|
3922
|
+
}
|
|
3923
|
+
Schema.extend("string", (data, { meta }, options) => {
|
|
3924
|
+
if (typeof data !== "string") throw new ValidationError(`expected string but got ${data}`, options);
|
|
3925
|
+
if (meta.pattern) {
|
|
3926
|
+
const regexp = new RegExp(meta.pattern.source, meta.pattern.flags);
|
|
3927
|
+
if (!regexp.test(data)) throw new ValidationError(`expect string to match regexp ${regexp}`, options);
|
|
3928
|
+
}
|
|
3929
|
+
checkWithinRange(data.length, meta, "string length", options);
|
|
3930
|
+
return [data];
|
|
3931
|
+
});
|
|
3932
|
+
function decimalShift(data, digits) {
|
|
3933
|
+
const str = data.toString();
|
|
3934
|
+
if (str.includes("e")) return data * Math.pow(10, digits);
|
|
3935
|
+
const index = str.indexOf(".");
|
|
3936
|
+
if (index === -1) return data * Math.pow(10, digits);
|
|
3937
|
+
const frac = str.slice(index + 1);
|
|
3938
|
+
const integer = str.slice(0, index);
|
|
3939
|
+
if (frac.length <= digits) return +(integer + frac.padEnd(digits, "0"));
|
|
3940
|
+
return +(integer + frac.slice(0, digits) + "." + frac.slice(digits));
|
|
3941
|
+
}
|
|
3942
|
+
function isMultipleOf(data, min, step) {
|
|
3943
|
+
step = Math.abs(step);
|
|
3944
|
+
if (!/^\d+\.\d+$/.test(step.toString())) return (data - min) % step === 0;
|
|
3945
|
+
const index = step.toString().indexOf(".");
|
|
3946
|
+
const digits = step.toString().slice(index + 1).length;
|
|
3947
|
+
return Math.abs(decimalShift(data, digits) - decimalShift(min, digits)) % decimalShift(step, digits) === 0;
|
|
3948
|
+
}
|
|
3949
|
+
Schema.extend("number", (data, { meta }, options) => {
|
|
3950
|
+
if (typeof data !== "number") throw new ValidationError(`expected number but got ${data}`, options);
|
|
3951
|
+
checkWithinRange(data, meta, "number", options);
|
|
3952
|
+
const { step } = meta;
|
|
3953
|
+
if (step && !isMultipleOf(data, meta.min ?? 0, step)) throw new ValidationError(`expected number multiple of ${step} but got ${data}`, options);
|
|
3954
|
+
return [data];
|
|
3955
|
+
});
|
|
3956
|
+
Schema.extend("boolean", (data, _, options) => {
|
|
3957
|
+
if (typeof data === "boolean") return [data];
|
|
3958
|
+
throw new ValidationError(`expected boolean but got ${data}`, options);
|
|
3959
|
+
});
|
|
3960
|
+
Schema.extend("bitset", (data, { bits, meta }, options) => {
|
|
3961
|
+
let value = 0, keys = [];
|
|
3962
|
+
if (typeof data === "number") {
|
|
3963
|
+
value = data;
|
|
3964
|
+
for (const key in bits) if (data & bits[key]) keys.push(key);
|
|
3965
|
+
} else if (Array.isArray(data)) {
|
|
3966
|
+
keys = data;
|
|
3967
|
+
for (const key of keys) {
|
|
3968
|
+
if (typeof key !== "string") throw new ValidationError(`expected string but got ${key}`, options);
|
|
3969
|
+
if (key in bits) value |= bits[key];
|
|
3970
|
+
}
|
|
3971
|
+
} else throw new ValidationError(`expected number or array but got ${data}`, options);
|
|
3972
|
+
if (value === meta.default) return [value];
|
|
3973
|
+
return [value, keys];
|
|
3974
|
+
});
|
|
3975
|
+
Schema.extend("function", (data, _, options) => {
|
|
3976
|
+
if (typeof data === "function") return [data];
|
|
3977
|
+
throw new ValidationError(`expected function but got ${data}`, options);
|
|
3978
|
+
});
|
|
3979
|
+
Schema.extend("is", (data, { constructor }, options) => {
|
|
3980
|
+
if (typeof constructor === "function") {
|
|
3981
|
+
if (data instanceof constructor) return [data];
|
|
3982
|
+
throw new ValidationError(`expected ${constructor.name} but got ${data}`, options);
|
|
3983
|
+
} else {
|
|
3984
|
+
if (isNullable(data)) throw new ValidationError(`expected ${constructor} but got ${data}`, options);
|
|
3985
|
+
let prototype = Object.getPrototypeOf(data);
|
|
3986
|
+
while (prototype) {
|
|
3987
|
+
if (prototype.constructor?.name === constructor) return [data];
|
|
3988
|
+
prototype = Object.getPrototypeOf(prototype);
|
|
3989
|
+
}
|
|
3990
|
+
throw new ValidationError(`expected ${constructor} but got ${data}`, options);
|
|
3991
|
+
}
|
|
3992
|
+
});
|
|
3993
|
+
function property(data, key, schema, options) {
|
|
3994
|
+
try {
|
|
3995
|
+
const [value, adapted] = Schema.resolve(data[key], schema, {
|
|
3996
|
+
...options,
|
|
3997
|
+
path: [...options.path || [], key]
|
|
3998
|
+
});
|
|
3999
|
+
if (adapted !== void 0) data[key] = adapted;
|
|
4000
|
+
return value;
|
|
4001
|
+
} catch (e) {
|
|
4002
|
+
if (!options?.autofix) throw e;
|
|
4003
|
+
delete data[key];
|
|
4004
|
+
return schema.meta.volatile ? createVolatile(schema.meta.default) : schema.meta.default;
|
|
4005
|
+
}
|
|
4006
|
+
}
|
|
4007
|
+
Schema.extend("array", (data, { inner, meta }, options) => {
|
|
4008
|
+
if (!Array.isArray(data)) throw new ValidationError(`expected array but got ${data}`, options);
|
|
4009
|
+
checkWithinRange(data.length, meta, "array length", options, !isNullable(inner.meta.default));
|
|
4010
|
+
return [data.map((_, index) => property(data, index, inner, options))];
|
|
4011
|
+
});
|
|
4012
|
+
Schema.extend("dict", (data, { inner, sKey }, options, strict) => {
|
|
4013
|
+
if (!isPlainObject(data)) throw new ValidationError(`expected object but got ${data}`, options);
|
|
4014
|
+
const result = {};
|
|
4015
|
+
for (const key in data) {
|
|
4016
|
+
let rKey;
|
|
4017
|
+
try {
|
|
4018
|
+
rKey = Schema.resolve(key, sKey, options)[0];
|
|
4019
|
+
} catch (error) {
|
|
4020
|
+
if (strict) continue;
|
|
4021
|
+
throw error;
|
|
4022
|
+
}
|
|
4023
|
+
result[rKey] = property(data, key, inner, options);
|
|
4024
|
+
data[rKey] = data[key];
|
|
4025
|
+
if (key !== rKey) delete data[key];
|
|
4026
|
+
}
|
|
4027
|
+
return [result];
|
|
4028
|
+
});
|
|
4029
|
+
Schema.extend("tuple", (data, { list }, options, strict) => {
|
|
4030
|
+
if (!Array.isArray(data)) throw new ValidationError(`expected array but got ${data}`, options);
|
|
4031
|
+
const result = list.map((inner, index) => property(data, index, inner, options));
|
|
4032
|
+
if (strict) return [result];
|
|
4033
|
+
result.push(...data.slice(list.length));
|
|
4034
|
+
return [result];
|
|
4035
|
+
});
|
|
4036
|
+
function merge(result, data) {
|
|
4037
|
+
for (const key in data) {
|
|
4038
|
+
if (key in result) continue;
|
|
4039
|
+
result[key] = data[key];
|
|
4040
|
+
}
|
|
4041
|
+
}
|
|
4042
|
+
Schema.extend("object", (data, { dict }, options, strict) => {
|
|
4043
|
+
if (!isPlainObject(data)) throw new ValidationError(`expected object but got ${data}`, options);
|
|
4044
|
+
const result = {};
|
|
4045
|
+
for (const key in dict) {
|
|
4046
|
+
const value = property(data, key, dict[key], options);
|
|
4047
|
+
if (!isNullable(value) || key in data) result[key] = value;
|
|
4048
|
+
}
|
|
4049
|
+
if (!strict) merge(result, data);
|
|
4050
|
+
return [result];
|
|
4051
|
+
});
|
|
4052
|
+
Schema.extend("union", (data, { list, toString }, options, strict) => {
|
|
4053
|
+
const messages = [];
|
|
4054
|
+
for (const inner of list) try {
|
|
4055
|
+
return Schema.resolve(data, inner, options, strict);
|
|
4056
|
+
} catch (error) {
|
|
4057
|
+
messages.push(error);
|
|
4058
|
+
}
|
|
4059
|
+
throw new ValidationError(`expected ${toString()} but got ${JSON.stringify(data)}`, options);
|
|
4060
|
+
});
|
|
4061
|
+
Schema.extend("intersect", (data, { list, toString }, options, strict) => {
|
|
4062
|
+
if (!list.length) return [data];
|
|
4063
|
+
let result;
|
|
4064
|
+
for (const inner of list) {
|
|
4065
|
+
const value = Schema.resolve(data, inner, options, true)[0];
|
|
4066
|
+
if (isNullable(value)) continue;
|
|
4067
|
+
if (isNullable(result)) result = value;
|
|
4068
|
+
else if (typeof result !== typeof value) throw new ValidationError(`expected ${toString()} but got ${JSON.stringify(data)}`, options);
|
|
4069
|
+
else if (typeof value === "object") merge(result ??= {}, value);
|
|
4070
|
+
else if (result !== value) throw new ValidationError(`expected ${toString()} but got ${JSON.stringify(data)}`, options);
|
|
4071
|
+
}
|
|
4072
|
+
if (!strict && isPlainObject(data)) merge(result, data);
|
|
4073
|
+
return [result];
|
|
4074
|
+
});
|
|
4075
|
+
Schema.extend("transform", (data, { inner, callback, preserve }, options) => {
|
|
4076
|
+
const [result, adapted = data] = Schema.resolve(data, inner, options, true);
|
|
4077
|
+
if (preserve) return [callback(result)];
|
|
4078
|
+
else return [callback(result), callback(adapted)];
|
|
4079
|
+
});
|
|
4080
|
+
const formatters = {};
|
|
4081
|
+
function defineMethod(name, keys, format) {
|
|
4082
|
+
formatters[name] = format;
|
|
4083
|
+
Object.assign(Schema, { [name](...args) {
|
|
4084
|
+
const schema = new Schema({ type: name });
|
|
4085
|
+
keys.forEach((key, index) => {
|
|
4086
|
+
switch (key) {
|
|
4087
|
+
case "sKey":
|
|
4088
|
+
schema.sKey = args[index] ?? Schema.string();
|
|
4089
|
+
break;
|
|
4090
|
+
case "inner":
|
|
4091
|
+
schema.inner = Schema.from(args[index]);
|
|
4092
|
+
break;
|
|
4093
|
+
case "list":
|
|
4094
|
+
schema.list = args[index].map(Schema.from);
|
|
4095
|
+
break;
|
|
4096
|
+
case "dict":
|
|
4097
|
+
schema.dict = mapValues(args[index], Schema.from);
|
|
4098
|
+
break;
|
|
4099
|
+
case "bits":
|
|
4100
|
+
schema.bits = {};
|
|
4101
|
+
for (const key in args[index]) {
|
|
4102
|
+
if (typeof args[index][key] !== "number") continue;
|
|
4103
|
+
schema.bits[key] = args[index][key];
|
|
4104
|
+
}
|
|
4105
|
+
break;
|
|
4106
|
+
case "callback": {
|
|
4107
|
+
const callback = schema.callback = args[index];
|
|
4108
|
+
callback["toJSON"] ||= () => callback.toString();
|
|
4109
|
+
break;
|
|
4110
|
+
}
|
|
4111
|
+
case "constructor": {
|
|
4112
|
+
const constructor = schema.constructor = args[index];
|
|
4113
|
+
if (typeof constructor === "function") constructor["toJSON"] ||= () => constructor["name"];
|
|
4114
|
+
break;
|
|
4115
|
+
}
|
|
4116
|
+
default: schema[key] = args[index];
|
|
4117
|
+
}
|
|
4118
|
+
});
|
|
4119
|
+
if (name === "object" || name === "dict") schema.meta.default = {};
|
|
4120
|
+
else if (name === "array" || name === "tuple") schema.meta.default = [];
|
|
4121
|
+
else if (name === "bitset") schema.meta.default = 0;
|
|
4122
|
+
return schema;
|
|
4123
|
+
} });
|
|
4124
|
+
}
|
|
4125
|
+
defineMethod("is", ["constructor"], ({ constructor }) => {
|
|
4126
|
+
if (typeof constructor === "function") return constructor.name;
|
|
4127
|
+
else return constructor;
|
|
4128
|
+
});
|
|
4129
|
+
defineMethod("any", [], () => "any");
|
|
4130
|
+
defineMethod("never", [], () => "never");
|
|
4131
|
+
defineMethod("const", ["value"], ({ value }) => typeof value === "string" ? JSON.stringify(value) : value);
|
|
4132
|
+
defineMethod("string", [], () => "string");
|
|
4133
|
+
defineMethod("number", [], () => "number");
|
|
4134
|
+
defineMethod("boolean", [], () => "boolean");
|
|
4135
|
+
defineMethod("bitset", ["bits"], () => "bitset");
|
|
4136
|
+
defineMethod("function", [], () => "function");
|
|
4137
|
+
defineMethod("array", ["inner"], ({ inner }) => `${inner.toString(true)}[]`);
|
|
4138
|
+
defineMethod("dict", ["inner", "sKey"], ({ inner, sKey }) => `{ [key: ${sKey.toString()}]: ${inner.toString()} }`);
|
|
4139
|
+
defineMethod("tuple", ["list"], ({ list }) => `[${list.map((inner) => inner.toString()).join(", ")}]`);
|
|
4140
|
+
defineMethod("object", ["dict"], ({ dict }) => {
|
|
4141
|
+
if (Object.keys(dict).length === 0) return "{}";
|
|
4142
|
+
return `{ ${Object.entries(dict).map(([key, inner]) => {
|
|
4143
|
+
return `${key}${inner.meta.required ? "" : "?"}: ${inner.toString()}`;
|
|
4144
|
+
}).join(", ")} }`;
|
|
4145
|
+
});
|
|
4146
|
+
defineMethod("union", ["list"], ({ list }, inline) => {
|
|
4147
|
+
const result = list.map(({ toString: format }) => format()).join(" | ");
|
|
4148
|
+
return inline ? `(${result})` : result;
|
|
4149
|
+
});
|
|
4150
|
+
defineMethod("intersect", ["list"], ({ list }) => {
|
|
4151
|
+
return `${list.map((inner) => inner.toString(true)).join(" & ")}`;
|
|
4152
|
+
});
|
|
4153
|
+
defineMethod("transform", [
|
|
4154
|
+
"inner",
|
|
4155
|
+
"callback",
|
|
4156
|
+
"preserve"
|
|
4157
|
+
], ({ inner }, isInner) => inner.toString(isInner));
|
|
4158
|
+
//#endregion
|
|
4159
|
+
//#region lib/types/onboarding-config.js
|
|
4160
|
+
/** Public page-bootstrap options shared by the Host and Client halves. */
|
|
4161
|
+
/** Validate Host configuration and its public page-bootstrap payload. */
|
|
4162
|
+
const Config = Schema.object({ credentialOnboarding: Schema.boolean().default(true) });
|
|
4163
|
+
/** Page-global key carrying only the public onboarding options. */
|
|
4164
|
+
const ONBOARDING_CONFIG_GLOBAL = "__DSH_MODELS_ONBOARDING__";
|
|
4165
|
+
//#endregion
|
|
3071
4166
|
//#region lib/types/client/index.js
|
|
3072
4167
|
/** Dictionary namespace owned by this plugin. */
|
|
3073
4168
|
const NS = "settings.models";
|
|
@@ -3092,7 +4187,7 @@ window.__ModuleLoader__.load({
|
|
|
3092
4187
|
"remote.credentials",
|
|
3093
4188
|
"remote.llm",
|
|
3094
4189
|
"remote.settings",
|
|
3095
|
-
"
|
|
4190
|
+
"configForms",
|
|
3096
4191
|
"settingsSchema"
|
|
3097
4192
|
];
|
|
3098
4193
|
/**
|
|
@@ -3102,13 +4197,15 @@ window.__ModuleLoader__.load({
|
|
|
3102
4197
|
* @param ctx - client root context.
|
|
3103
4198
|
*/
|
|
3104
4199
|
function apply(ctx) {
|
|
4200
|
+
const payload = globalThis[ONBOARDING_CONFIG_GLOBAL];
|
|
4201
|
+
const credentialOnboarding = Config(payload === void 0 ? {} : payload).credentialOnboarding && !("dshDesktop" in globalThis);
|
|
3105
4202
|
ctx.effect(() => ctx.locale.register(NS, {
|
|
3106
4203
|
zh,
|
|
3107
4204
|
en
|
|
3108
4205
|
}), "ui-settings-models: copy dictionaries");
|
|
3109
4206
|
const schema = createSettingsSchemaOperations(ctx.settingsSchema);
|
|
3110
4207
|
const operations = createModelsOperations(ctx);
|
|
3111
|
-
const controller = new ModelsSettingsStore(ctx, schema, ctx.
|
|
4208
|
+
const controller = new ModelsSettingsStore(ctx, schema, ctx.configForms.describe());
|
|
3112
4209
|
const t = ctx.locale.bind(NS);
|
|
3113
4210
|
const injected = () => ({
|
|
3114
4211
|
controller,
|
|
@@ -3118,16 +4215,14 @@ window.__ModuleLoader__.load({
|
|
|
3118
4215
|
t
|
|
3119
4216
|
});
|
|
3120
4217
|
const deepSeekOnboardingInjected = () => ({
|
|
4218
|
+
automatic: credentialOnboarding,
|
|
3121
4219
|
controller,
|
|
3122
4220
|
hooks: { models: controller.store },
|
|
3123
4221
|
operations,
|
|
3124
4222
|
schema,
|
|
3125
4223
|
t
|
|
3126
4224
|
});
|
|
3127
|
-
const welcomeController = new WelcomeNoticeStore(ctx.
|
|
3128
|
-
namespace: WELCOME_NOTICE_SETTINGS_NAMESPACE,
|
|
3129
|
-
decode: decodeWelcomeSection
|
|
3130
|
-
}));
|
|
4225
|
+
const welcomeController = new WelcomeNoticeStore(ctx.configForms.get(WELCOME_NOTICE_SETTINGS_NAMESPACE));
|
|
3131
4226
|
const welcomeInjected = () => ({
|
|
3132
4227
|
controller: welcomeController,
|
|
3133
4228
|
hooks: { welcome: welcomeController.store },
|
|
@@ -3177,6 +4272,10 @@ window.__ModuleLoader__.load({
|
|
|
3177
4272
|
ctx.slots.inject("settings.onboarding", () => ctx.slots.register({
|
|
3178
4273
|
name: "settings.onboarding",
|
|
3179
4274
|
id: "deepseek-official",
|
|
4275
|
+
children: { "settings.models.sign-in": {
|
|
4276
|
+
kind: "single",
|
|
4277
|
+
scope: "root"
|
|
4278
|
+
} },
|
|
3180
4279
|
order: 0,
|
|
3181
4280
|
inject: deepSeekOnboardingInjected
|
|
3182
4281
|
}, DeepSeekOnboardingDialog));
|