@mofeng2223/dsh-claude-provider 0.3.1 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -16
- package/README.zh-CN.md +1 -16
- package/lib/client.js +591 -458
- package/package.json +7 -8
- package/src/index.js +37 -23
package/lib/client.js
CHANGED
|
@@ -8,7 +8,7 @@ window.__ModuleLoader__.load({
|
|
|
8
8
|
let react = require("react");
|
|
9
9
|
let react_dom = require("react-dom");
|
|
10
10
|
let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
11
|
-
let
|
|
11
|
+
let _deepseek_ai_dsh_client_store = require("@deepseek-ai/dsh-client-store");
|
|
12
12
|
//#region lib/types/client/apiKey.js
|
|
13
13
|
/**
|
|
14
14
|
* Browser-side judgement of a typed API key.
|
|
@@ -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:1px solid var(--dsw-alias-border-l2);border-radius:12px;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:1px 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;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:1px solid var(--dsw-alias-border-l2);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:12px;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:1px 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:1px 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:1px solid var(--dsw-alias-border-l2);border-radius:8px;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:1px solid var(--dsw-alias-border-l2);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:1px solid var(--dsw-alias-border-l2);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{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_candidateActions{justify-content:flex-end;margin-bottom:6px;display:flex}.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}";
|
|
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}";
|
|
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");
|
|
@@ -73,10 +73,12 @@ window.__ModuleLoader__.load({
|
|
|
73
73
|
"addModelButton": "zGbnIq_addModelButton",
|
|
74
74
|
"advancedHint": "zGbnIq_advancedHint",
|
|
75
75
|
"candidate": "zGbnIq_candidate",
|
|
76
|
-
"
|
|
76
|
+
"candidateEmpty": "zGbnIq_candidateEmpty",
|
|
77
77
|
"candidateId": "zGbnIq_candidateId",
|
|
78
78
|
"candidateLabel": "zGbnIq_candidateLabel",
|
|
79
79
|
"candidateList": "zGbnIq_candidateList",
|
|
80
|
+
"candidateSearch": "zGbnIq_candidateSearch",
|
|
81
|
+
"candidateToolbar": "zGbnIq_candidateToolbar",
|
|
80
82
|
"credentialDot": "zGbnIq_credentialDot",
|
|
81
83
|
"credentialDotConfigured": "zGbnIq_credentialDotConfigured",
|
|
82
84
|
"credentialDotMissing": "zGbnIq_credentialDotMissing",
|
|
@@ -127,6 +129,7 @@ window.__ModuleLoader__.load({
|
|
|
127
129
|
"section": "zGbnIq_section",
|
|
128
130
|
"selectInput": "zGbnIq_selectInput",
|
|
129
131
|
"setupCard": "zGbnIq_setupCard",
|
|
132
|
+
"switchThumb": "zGbnIq_switchThumb",
|
|
130
133
|
"title": "zGbnIq_title"
|
|
131
134
|
};
|
|
132
135
|
//#endregion
|
|
@@ -145,13 +148,13 @@ window.__ModuleLoader__.load({
|
|
|
145
148
|
className: ModelsSection_module_css_default["secondaryButton"],
|
|
146
149
|
disabled: props.busy,
|
|
147
150
|
onClick: props.onCancel,
|
|
148
|
-
children: t(props.
|
|
151
|
+
children: t(props.cancelLabelKey ?? "cancel")
|
|
149
152
|
}), (0, react_jsx_runtime.jsx)("button", {
|
|
150
153
|
type: "button",
|
|
151
154
|
className: ModelsSection_module_css_default["primaryButton"],
|
|
152
155
|
disabled: props.submitDisabled,
|
|
153
156
|
onClick: props.onSubmit,
|
|
154
|
-
children: props.busy ? t(props.
|
|
157
|
+
children: props.busy ? t(props.submitBusyLabelKey) : t(props.submitLabelKey)
|
|
155
158
|
})]
|
|
156
159
|
});
|
|
157
160
|
}
|
|
@@ -443,212 +446,6 @@ window.__ModuleLoader__.load({
|
|
|
443
446
|
});
|
|
444
447
|
}
|
|
445
448
|
//#endregion
|
|
446
|
-
//#region lib/types/client/store.js
|
|
447
|
-
/**
|
|
448
|
-
* Models settings page store: one snapshot joining the configurable-provider
|
|
449
|
-
* directory (`llm.providers`), the settings namespaces (shared settings mirror),
|
|
450
|
-
* and the referenced credentials (`credentials.describe`). The host stays the
|
|
451
|
-
* single fact source — every mutation writes through the wire and the page
|
|
452
|
-
* re-renders from the next describe, pushed or refetched.
|
|
453
|
-
*/
|
|
454
|
-
/**
|
|
455
|
-
* Any route key walks a dict schema to the same profile node, so the lookup
|
|
456
|
-
* names one that cannot collide with a configured route.
|
|
457
|
-
*/
|
|
458
|
-
const PROBE_ROUTE = "\0probe";
|
|
459
|
-
/**
|
|
460
|
-
* Human text for a rejected wire call. A transport failure rejects with an
|
|
461
|
-
* Error; a host or a runtime can reject with anything, and the page still has
|
|
462
|
-
* to say something.
|
|
463
|
-
* @param error - the rejection value.
|
|
464
|
-
* @returns the message to show.
|
|
465
|
-
*/
|
|
466
|
-
function messageOf(error) {
|
|
467
|
-
return error instanceof Error ? error.message : String(error);
|
|
468
|
-
}
|
|
469
|
-
/**
|
|
470
|
-
* Derive the conventional credential reference for a provider route: the v1
|
|
471
|
-
* page never asks for an environment-variable name, so a typed key stores
|
|
472
|
-
* under this derived reference and the profile records it as `apiKeyEnv`.
|
|
473
|
-
* @param provider - provider route id (e.g. `anthropic`, `minimax-cn`).
|
|
474
|
-
* @returns the derived reference name (e.g. `MINIMAX_CN_API_KEY`).
|
|
475
|
-
*/
|
|
476
|
-
function deriveKeyRef(provider) {
|
|
477
|
-
return `${provider.toUpperCase().replace(/[^A-Z0-9]+/g, "_")}_API_KEY`;
|
|
478
|
-
}
|
|
479
|
-
/**
|
|
480
|
-
* The wire protocols a hand-declared route may name, read out of the owning
|
|
481
|
-
* namespace's own schema. This stays a schema read rather than a wire field so
|
|
482
|
-
* the choices the page offers cannot drift from the ones the adapter accepts:
|
|
483
|
-
* both come from the same `Config`.
|
|
484
|
-
* @param namespace - the namespace view whose schema declares the profile shape.
|
|
485
|
-
* @param schema - settings schema operations.
|
|
486
|
-
* @returns the protocol identifiers, or an empty list when the schema has none.
|
|
487
|
-
*/
|
|
488
|
-
function protocolChoices(namespace, schema) {
|
|
489
|
-
if (namespace === void 0) return [];
|
|
490
|
-
const list = schema.nodeAtPath(schema.rehydrate(namespace.schema), [
|
|
491
|
-
"providers",
|
|
492
|
-
PROBE_ROUTE,
|
|
493
|
-
"api"
|
|
494
|
-
]);
|
|
495
|
-
if (list?.type !== "union" || list.list === void 0) return [];
|
|
496
|
-
return list.list.map((entry) => entry.value).filter((value) => typeof value === "string");
|
|
497
|
-
}
|
|
498
|
-
/** The credential reference a resolved profile names (its `apiKeyEnv` field). */
|
|
499
|
-
function apiKeyEnvOf(namespace, path, schema) {
|
|
500
|
-
if (namespace === void 0) return void 0;
|
|
501
|
-
const profile = schema.getPath(namespace.value, path);
|
|
502
|
-
if (typeof profile !== "object" || profile === null) return void 0;
|
|
503
|
-
const ref = profile.apiKeyEnv;
|
|
504
|
-
return typeof ref === "string" && ref.length > 0 ? ref : void 0;
|
|
505
|
-
}
|
|
506
|
-
/** The models settings page controller (one per settings surface). */
|
|
507
|
-
var ModelsSettingsStore = class {
|
|
508
|
-
api;
|
|
509
|
-
schema;
|
|
510
|
-
describeFace;
|
|
511
|
-
/** The snapshot the section renders from (uSES-safe store). */
|
|
512
|
-
store = (0, _deepseek_ai_dsh_client_runtime_client.createSnapshotStore)({
|
|
513
|
-
status: "idle",
|
|
514
|
-
error: null,
|
|
515
|
-
credentialError: null,
|
|
516
|
-
writable: false,
|
|
517
|
-
rows: [],
|
|
518
|
-
namespaces: /* @__PURE__ */ new Map()
|
|
519
|
-
});
|
|
520
|
-
/** Latest load wins; an older response never overwrites a newer one. */
|
|
521
|
-
generation = 0;
|
|
522
|
-
/**
|
|
523
|
-
* @param api - the wire face (credentials/llm domains, and settings writes).
|
|
524
|
-
* @param describeFace - the shared mirror's describe face (namespace views and writability).
|
|
525
|
-
*/
|
|
526
|
-
constructor(api, schema, describeFace) {
|
|
527
|
-
this.api = api;
|
|
528
|
-
this.schema = schema;
|
|
529
|
-
this.describeFace = describeFace;
|
|
530
|
-
}
|
|
531
|
-
/**
|
|
532
|
-
* Refresh the whole page snapshot: the provider directory and the mirror's
|
|
533
|
-
* settings answer in parallel, then one batched credential describe over
|
|
534
|
-
* every referenced ref. Provider failure or absence of an initial settings
|
|
535
|
-
* answer keeps the last good rows and surfaces an error; a failed settings
|
|
536
|
-
* refresh reuses the mirror's held view.
|
|
537
|
-
* @returns nothing; the snapshot carries the outcome.
|
|
538
|
-
*/
|
|
539
|
-
async load() {
|
|
540
|
-
const generation = ++this.generation;
|
|
541
|
-
this.store.update((s) => {
|
|
542
|
-
s.status = "loading";
|
|
543
|
-
s.error = null;
|
|
544
|
-
});
|
|
545
|
-
let providers;
|
|
546
|
-
let writable;
|
|
547
|
-
let views;
|
|
548
|
-
try {
|
|
549
|
-
const [providersResponse] = await Promise.all([this.api.llm.providers({}), this.describeFace.ensure()]);
|
|
550
|
-
if (!providersResponse.result.ok) throw new Error(providersResponse.result.error.message);
|
|
551
|
-
const mirrored = this.describeFace.getSnapshot();
|
|
552
|
-
if (mirrored.view === void 0) throw new Error(mirrored.error ?? "settings are unavailable in this browser");
|
|
553
|
-
providers = providersResponse.result.value.providers.filter((entry) => entry.provider !== CLAUDE_PROVIDER_DIRECTORY_SENTINEL);
|
|
554
|
-
writable = mirrored.view.writable;
|
|
555
|
-
views = mirrored.view.namespaces;
|
|
556
|
-
} catch (error) {
|
|
557
|
-
if (generation !== this.generation) return;
|
|
558
|
-
this.store.update((s) => {
|
|
559
|
-
s.status = "error";
|
|
560
|
-
s.error = error instanceof Error ? error.message : String(error);
|
|
561
|
-
});
|
|
562
|
-
return;
|
|
563
|
-
}
|
|
564
|
-
const namespaces = new Map(views.map((view) => [view.ns, view]));
|
|
565
|
-
const rows = providers.map((entry) => {
|
|
566
|
-
const namespace = namespaces.get(entry.settingsNs);
|
|
567
|
-
return {
|
|
568
|
-
entry,
|
|
569
|
-
configured: namespace !== void 0 && (entry.settingsPath.length === 0 || this.schema.getPath(namespace.value, entry.settingsPath) !== void 0),
|
|
570
|
-
removable: namespace !== void 0 && entry.settingsPath.length > 0 && this.schema.hasPath(namespace.user, entry.settingsPath) && !this.schema.hasPath(namespace.base, entry.settingsPath),
|
|
571
|
-
apiKeyEnv: apiKeyEnvOf(namespace, entry.settingsPath, this.schema),
|
|
572
|
-
credential: void 0
|
|
573
|
-
};
|
|
574
|
-
});
|
|
575
|
-
const refs = [...new Set(rows.flatMap((row) => row.apiKeyEnv === void 0 ? [] : [row.apiKeyEnv]))];
|
|
576
|
-
let credentials = {};
|
|
577
|
-
let credentialError = null;
|
|
578
|
-
if (refs.length > 0) try {
|
|
579
|
-
const response = await this.api.credentials.describe({ refs });
|
|
580
|
-
if (response.result.ok) credentials = response.result.value.credentials;
|
|
581
|
-
else credentialError = response.result.error.message;
|
|
582
|
-
} catch (error) {
|
|
583
|
-
credentialError = messageOf(error);
|
|
584
|
-
}
|
|
585
|
-
if (generation !== this.generation) return;
|
|
586
|
-
this.store.update((s) => {
|
|
587
|
-
s.status = "ready";
|
|
588
|
-
s.error = null;
|
|
589
|
-
s.credentialError = credentialError;
|
|
590
|
-
s.writable = writable;
|
|
591
|
-
s.rows = rows.map((row) => ({
|
|
592
|
-
...row,
|
|
593
|
-
...row.apiKeyEnv !== void 0 && credentials[row.apiKeyEnv] !== void 0 ? { credential: credentials[row.apiKeyEnv] } : {}
|
|
594
|
-
}));
|
|
595
|
-
s.namespaces = namespaces;
|
|
596
|
-
});
|
|
597
|
-
}
|
|
598
|
-
};
|
|
599
|
-
/**
|
|
600
|
-
* Whether a joined row can serve model requests as it stands: the route is
|
|
601
|
-
* registered with the adapter registry, and whatever credential its resolved
|
|
602
|
-
* profile names is stored. A profile naming no reference authenticates through
|
|
603
|
-
* the provider's own path (the Bedrock chain, Vertex ADC, a gateway that needs
|
|
604
|
-
* nothing), as does a live route with no settings address at all, so neither
|
|
605
|
-
* owes this page a key.
|
|
606
|
-
* @param row - one joined provider row.
|
|
607
|
-
* @returns whether the user already has this provider to talk to.
|
|
608
|
-
*/
|
|
609
|
-
function providerUsable(row) {
|
|
610
|
-
if (!row.entry.active) return false;
|
|
611
|
-
if (row.apiKeyEnv === void 0) return true;
|
|
612
|
-
return row.credential?.configured === true;
|
|
613
|
-
}
|
|
614
|
-
/**
|
|
615
|
-
* Project first-run readiness from the provider/settings/credential join used
|
|
616
|
-
* by the Models page. The step exists to leave the user with a model to talk
|
|
617
|
-
* to, so ANY usable provider ends it; only when none exists does the official
|
|
618
|
-
* DeepSeek route — the one route the prompt can offer a key field for — decide
|
|
619
|
-
* whether prompting can help. A missing official configurable-provider
|
|
620
|
-
* declaration means the adapter is not repairable by navigating to Models.
|
|
621
|
-
* @param state - current shared Models join snapshot.
|
|
622
|
-
* @returns the onboarding state without reading a parallel fact source.
|
|
623
|
-
*/
|
|
624
|
-
function onboardingReadiness(state) {
|
|
625
|
-
if ((state.status === "idle" || state.status === "loading") && state.rows.length === 0) return { kind: "loading" };
|
|
626
|
-
if (state.status === "error") return {
|
|
627
|
-
kind: "unavailable",
|
|
628
|
-
reason: "load-failed"
|
|
629
|
-
};
|
|
630
|
-
if (state.rows.some(providerUsable)) return { kind: "provider-ready" };
|
|
631
|
-
const row = state.rows.find((candidate) => candidate.entry.provider === "deepseek-official" && candidate.entry.settingsNs === "llm-deepseek" && candidate.entry.settingsPath.length === 0);
|
|
632
|
-
if (row === void 0) return { kind: "adapter-absent" };
|
|
633
|
-
if (!row.entry.active) return {
|
|
634
|
-
kind: "unavailable",
|
|
635
|
-
reason: "provider-inactive"
|
|
636
|
-
};
|
|
637
|
-
if (state.credentialError !== null || row.credential === void 0) return {
|
|
638
|
-
kind: "unavailable",
|
|
639
|
-
reason: "credentials-unavailable"
|
|
640
|
-
};
|
|
641
|
-
if (!state.writable) return {
|
|
642
|
-
kind: "unavailable",
|
|
643
|
-
reason: "settings-read-only"
|
|
644
|
-
};
|
|
645
|
-
if (!row.credential.writable) return {
|
|
646
|
-
kind: "unavailable",
|
|
647
|
-
reason: "credential-read-only"
|
|
648
|
-
};
|
|
649
|
-
return { kind: "credential-missing" };
|
|
650
|
-
}
|
|
651
|
-
//#endregion
|
|
652
449
|
//#region lib/types/client/ModelListEditor.js
|
|
653
450
|
/**
|
|
654
451
|
* The model list of one pi-ai provider profile, plus the action that asks the
|
|
@@ -753,11 +550,12 @@ window.__ModuleLoader__.load({
|
|
|
753
550
|
* @returns the model-list editor.
|
|
754
551
|
*/
|
|
755
552
|
function ModelListEditor(props) {
|
|
756
|
-
const { models, onChange, probe,
|
|
553
|
+
const { models, onChange, probe, operations, t, disabled } = props;
|
|
757
554
|
const [busy, setBusy] = (0, react.useState)(false);
|
|
758
555
|
const [failure, setFailure] = (0, react.useState)(void 0);
|
|
759
556
|
const [candidates, setCandidates] = (0, react.useState)(void 0);
|
|
760
557
|
const [picked, setPicked] = (0, react.useState)(/* @__PURE__ */ new Set());
|
|
558
|
+
const [candidateQuery, setCandidateQuery] = (0, react.useState)("");
|
|
761
559
|
const [expanded, setExpanded] = (0, react.useState)(/* @__PURE__ */ new Set());
|
|
762
560
|
const [editing, setEditing] = (0, react.useState)(/* @__PURE__ */ new Map());
|
|
763
561
|
/** Buffer key for one capacity field; the row half moves when rows do. */
|
|
@@ -799,27 +597,25 @@ window.__ModuleLoader__.load({
|
|
|
799
597
|
setBusy(true);
|
|
800
598
|
setFailure(void 0);
|
|
801
599
|
try {
|
|
802
|
-
const
|
|
803
|
-
settingsNs: probe.settingsNs,
|
|
600
|
+
const answer = await operations.discoverModels(probe.settingsNs, {
|
|
804
601
|
...probe.provider === void 0 ? {} : { provider: probe.provider },
|
|
805
602
|
...probe.baseURL === void 0 || probe.baseURL.length === 0 ? {} : { baseURL: probe.baseURL },
|
|
806
603
|
...probe.api === void 0 ? {} : { api: props.thinkingPresets ? CLAUDE_DISCOVERY_API : probe.api },
|
|
807
604
|
...probe.apiKey === void 0 ? {} : { apiKey: probe.apiKey }
|
|
808
605
|
});
|
|
809
|
-
if (
|
|
810
|
-
setFailure(
|
|
606
|
+
if (answer.kind === "refused") {
|
|
607
|
+
setFailure(answer.message);
|
|
811
608
|
return;
|
|
812
609
|
}
|
|
813
|
-
const found =
|
|
610
|
+
const found = answer.models;
|
|
814
611
|
if (found.length === 0) {
|
|
815
612
|
setFailure(t("fetchEmpty"));
|
|
816
613
|
return;
|
|
817
614
|
}
|
|
818
615
|
const known = new Set(models.map((model) => textOf(model, "id")));
|
|
616
|
+
setCandidateQuery("");
|
|
819
617
|
setCandidates(found);
|
|
820
618
|
setPicked(new Set(found.filter((model) => !known.has(model.id)).map((model) => model.id)));
|
|
821
|
-
} catch (error) {
|
|
822
|
-
setFailure(messageOf(error));
|
|
823
619
|
} finally {
|
|
824
620
|
setBusy(false);
|
|
825
621
|
}
|
|
@@ -827,6 +623,7 @@ window.__ModuleLoader__.load({
|
|
|
827
623
|
const closePicker = () => {
|
|
828
624
|
setCandidates(void 0);
|
|
829
625
|
setPicked(/* @__PURE__ */ new Set());
|
|
626
|
+
setCandidateQuery("");
|
|
830
627
|
};
|
|
831
628
|
const adoptPicked = () => {
|
|
832
629
|
/* v8 ignore next -- the dialog only renders with candidates loaded */
|
|
@@ -847,10 +644,15 @@ window.__ModuleLoader__.load({
|
|
|
847
644
|
});
|
|
848
645
|
};
|
|
849
646
|
const activeCandidates = candidates ?? [];
|
|
850
|
-
const
|
|
851
|
-
const
|
|
647
|
+
const normalizedCandidateQuery = candidateQuery.trim().toLowerCase();
|
|
648
|
+
const visibleCandidates = normalizedCandidateQuery.length === 0 ? activeCandidates : activeCandidates.filter((candidate) => candidate.id.toLowerCase().includes(normalizedCandidateQuery) || candidate.name?.toLowerCase().includes(normalizedCandidateQuery) === true);
|
|
649
|
+
const allVisibleCandidatesPicked = visibleCandidates.length > 0 && visibleCandidates.every((candidate) => picked.has(candidate.id));
|
|
650
|
+
const toggleVisibleCandidates = () => {
|
|
852
651
|
setPicked((current) => {
|
|
853
|
-
|
|
652
|
+
const next = new Set(current);
|
|
653
|
+
if (visibleCandidates.every((candidate) => current.has(candidate.id))) for (const candidate of visibleCandidates) next.delete(candidate.id);
|
|
654
|
+
else for (const candidate of visibleCandidates) next.add(candidate.id);
|
|
655
|
+
return next;
|
|
854
656
|
});
|
|
855
657
|
};
|
|
856
658
|
const askable = probe.provider !== void 0 || probe.baseURL !== void 0 && probe.baseURL.length > 0;
|
|
@@ -1034,17 +836,31 @@ window.__ModuleLoader__.load({
|
|
|
1034
836
|
onClick: adoptPicked,
|
|
1035
837
|
children: t("fetchAdopt")
|
|
1036
838
|
})] }),
|
|
1037
|
-
children: [(0, react_jsx_runtime.
|
|
1038
|
-
className: ModelsSection_module_css_default["
|
|
1039
|
-
children: (0, react_jsx_runtime.jsx)(
|
|
839
|
+
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
840
|
+
className: ModelsSection_module_css_default["candidateToolbar"],
|
|
841
|
+
children: [(0, react_jsx_runtime.jsx)("input", {
|
|
842
|
+
className: `${ModelsSection_module_css_default["input"]} ${ModelsSection_module_css_default["candidateSearch"]}`,
|
|
843
|
+
type: "search",
|
|
844
|
+
value: candidateQuery,
|
|
845
|
+
placeholder: t("fetchSearch"),
|
|
846
|
+
"aria-label": t("fetchSearch"),
|
|
847
|
+
onChange: (event) => {
|
|
848
|
+
setCandidateQuery(event.target.value);
|
|
849
|
+
}
|
|
850
|
+
}), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
1040
851
|
variant: "ghost",
|
|
1041
852
|
size: "sm",
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
853
|
+
disabled: visibleCandidates.length === 0,
|
|
854
|
+
onClick: toggleVisibleCandidates,
|
|
855
|
+
children: t(allVisibleCandidatesPicked ? "fetchDeselectAll" : "fetchSelectAll")
|
|
856
|
+
})]
|
|
857
|
+
}), visibleCandidates.length === 0 ? (0, react_jsx_runtime.jsx)("p", {
|
|
858
|
+
className: ModelsSection_module_css_default["candidateEmpty"],
|
|
859
|
+
role: "status",
|
|
860
|
+
children: t("fetchNoMatches")
|
|
861
|
+
}) : (0, react_jsx_runtime.jsx)("ul", {
|
|
1046
862
|
className: ModelsSection_module_css_default["candidateList"],
|
|
1047
|
-
children:
|
|
863
|
+
children: visibleCandidates.map((candidate) => (0, react_jsx_runtime.jsx)("li", {
|
|
1048
864
|
className: ModelsSection_module_css_default["candidate"],
|
|
1049
865
|
children: (0, react_jsx_runtime.jsxs)("label", {
|
|
1050
866
|
className: ModelsSection_module_css_default["candidateLabel"],
|
|
@@ -1066,6 +882,247 @@ window.__ModuleLoader__.load({
|
|
|
1066
882
|
});
|
|
1067
883
|
}
|
|
1068
884
|
//#endregion
|
|
885
|
+
//#region lib/types/client/store.js
|
|
886
|
+
/**
|
|
887
|
+
* Models settings page store: one snapshot joining the configurable-provider
|
|
888
|
+
* directory (`llm/listProviders` joined with `llm/listConfigurableProviders`),
|
|
889
|
+
* the settings namespaces (shared settings mirror),
|
|
890
|
+
* and the referenced credentials (`credentials/describe`). The host stays the
|
|
891
|
+
* single fact source — every mutation writes through the wire and the page
|
|
892
|
+
* re-renders from the next describe, pushed or refetched.
|
|
893
|
+
*/
|
|
894
|
+
/**
|
|
895
|
+
* Any route key walks a dict schema to the same profile node, so the lookup
|
|
896
|
+
* names one that cannot collide with a configured route.
|
|
897
|
+
*/
|
|
898
|
+
const PROBE_ROUTE = "\0probe";
|
|
899
|
+
/**
|
|
900
|
+
* Join declared configurable providers with the currently registered routes.
|
|
901
|
+
* @param registered - live provider routes in registration order.
|
|
902
|
+
* @param directory - declared configurable providers in declaration order.
|
|
903
|
+
* @returns declared rows followed by live routes with no declaration.
|
|
904
|
+
*/
|
|
905
|
+
function joinProviderDirectory(registered, directory) {
|
|
906
|
+
const active = new Set(registered.map((provider) => provider.id));
|
|
907
|
+
const declared = new Set(directory.map((entry) => entry.provider));
|
|
908
|
+
const rows = directory.map((entry) => ({
|
|
909
|
+
provider: entry.provider,
|
|
910
|
+
displayName: entry.displayName,
|
|
911
|
+
settingsNs: entry.settingsNs,
|
|
912
|
+
settingsPath: [...entry.settingsPath],
|
|
913
|
+
active: active.has(entry.provider),
|
|
914
|
+
...entry.declared === void 0 ? {} : { declared: entry.declared }
|
|
915
|
+
}));
|
|
916
|
+
for (const provider of registered) {
|
|
917
|
+
if (declared.has(provider.id)) continue;
|
|
918
|
+
rows.push({
|
|
919
|
+
provider: provider.id,
|
|
920
|
+
displayName: provider.name,
|
|
921
|
+
settingsNs: "",
|
|
922
|
+
settingsPath: [],
|
|
923
|
+
active: true
|
|
924
|
+
});
|
|
925
|
+
}
|
|
926
|
+
return rows;
|
|
927
|
+
}
|
|
928
|
+
/**
|
|
929
|
+
* Derive the conventional credential reference for a provider route: the v1
|
|
930
|
+
* page never asks for an environment-variable name, so a typed key stores
|
|
931
|
+
* under this derived reference and the profile records it as `apiKeyEnv`.
|
|
932
|
+
* @param provider - provider route id (e.g. `anthropic`, `minimax-cn`).
|
|
933
|
+
* @returns the derived reference name (e.g. `MINIMAX_CN_API_KEY`).
|
|
934
|
+
*/
|
|
935
|
+
function deriveKeyRef(provider) {
|
|
936
|
+
return `${provider.toUpperCase().replace(/[^A-Z0-9]+/g, "_")}_API_KEY`;
|
|
937
|
+
}
|
|
938
|
+
/**
|
|
939
|
+
* The wire protocols a hand-declared route may name, read out of the owning
|
|
940
|
+
* namespace's own schema. This stays a schema read rather than a wire field so
|
|
941
|
+
* the choices the page offers cannot drift from the ones the adapter accepts:
|
|
942
|
+
* both come from the same `Config`.
|
|
943
|
+
* @param namespace - the namespace view whose schema declares the profile shape.
|
|
944
|
+
* @param schema - settings schema operations.
|
|
945
|
+
* @returns the protocol identifiers, or an empty list when the schema has none.
|
|
946
|
+
*/
|
|
947
|
+
function protocolChoices(namespace, schema) {
|
|
948
|
+
if (namespace === void 0) return [];
|
|
949
|
+
const list = schema.nodeAtPath(schema.rehydrate(namespace.schema), [
|
|
950
|
+
"providers",
|
|
951
|
+
PROBE_ROUTE,
|
|
952
|
+
"api"
|
|
953
|
+
]);
|
|
954
|
+
if (list?.type !== "union" || list.list === void 0) return [];
|
|
955
|
+
return list.list.map((entry) => entry.value).filter((value) => typeof value === "string");
|
|
956
|
+
}
|
|
957
|
+
/** The credential reference a resolved profile names (its `apiKeyEnv` field). */
|
|
958
|
+
function apiKeyEnvOf(namespace, path, schema) {
|
|
959
|
+
if (namespace === void 0) return void 0;
|
|
960
|
+
const profile = schema.getPath(namespace.value, path);
|
|
961
|
+
if (typeof profile !== "object" || profile === null) return void 0;
|
|
962
|
+
const ref = profile.apiKeyEnv;
|
|
963
|
+
return typeof ref === "string" && ref.length > 0 ? ref : void 0;
|
|
964
|
+
}
|
|
965
|
+
/** The models settings page controller (one per settings surface). */
|
|
966
|
+
var ModelsSettingsStore = class {
|
|
967
|
+
ctx;
|
|
968
|
+
schema;
|
|
969
|
+
describeFace;
|
|
970
|
+
/** The snapshot the section renders from (uSES-safe store). */
|
|
971
|
+
store = (0, _deepseek_ai_dsh_client_store.createSnapshotStore)({
|
|
972
|
+
status: "idle",
|
|
973
|
+
error: null,
|
|
974
|
+
credentialError: null,
|
|
975
|
+
writable: false,
|
|
976
|
+
rows: [],
|
|
977
|
+
namespaces: /* @__PURE__ */ new Map()
|
|
978
|
+
});
|
|
979
|
+
/** Latest load wins; an older response never overwrites a newer one. */
|
|
980
|
+
generation = 0;
|
|
981
|
+
/**
|
|
982
|
+
* @param ctx - the page plugin's context, whose `remote.llm` and
|
|
983
|
+
* `remote.credentials` namespaces carry the directory and credential reads.
|
|
984
|
+
* @param schema - settings-owned schema and immutable path operations.
|
|
985
|
+
* @param describeFace - the shared mirror's describe face (namespace views and writability).
|
|
986
|
+
*/
|
|
987
|
+
constructor(ctx, schema, describeFace) {
|
|
988
|
+
this.ctx = ctx;
|
|
989
|
+
this.schema = schema;
|
|
990
|
+
this.describeFace = describeFace;
|
|
991
|
+
}
|
|
992
|
+
/**
|
|
993
|
+
* Refresh the whole page snapshot: the provider directory and the mirror's
|
|
994
|
+
* settings answer in parallel, then one batched credential describe over
|
|
995
|
+
* every referenced ref. Provider failure or absence of an initial settings
|
|
996
|
+
* answer keeps the last good rows and surfaces an error; a failed settings
|
|
997
|
+
* refresh reuses the mirror's held view.
|
|
998
|
+
* @returns nothing; the snapshot carries the outcome.
|
|
999
|
+
*/
|
|
1000
|
+
async load() {
|
|
1001
|
+
const generation = ++this.generation;
|
|
1002
|
+
this.store.update((s) => {
|
|
1003
|
+
s.status = "loading";
|
|
1004
|
+
s.error = null;
|
|
1005
|
+
});
|
|
1006
|
+
const [registered, declared] = await Promise.all([
|
|
1007
|
+
this.ctx.remote.llm.listProviders(),
|
|
1008
|
+
this.ctx.remote.llm.listConfigurableProviders(),
|
|
1009
|
+
this.describeFace.ensure()
|
|
1010
|
+
]);
|
|
1011
|
+
if (!registered.ok) {
|
|
1012
|
+
this.failLoad(generation, registered.error.message);
|
|
1013
|
+
return;
|
|
1014
|
+
}
|
|
1015
|
+
if (!declared.ok) {
|
|
1016
|
+
this.failLoad(generation, declared.error.message);
|
|
1017
|
+
return;
|
|
1018
|
+
}
|
|
1019
|
+
const mirrored = this.describeFace.getSnapshot();
|
|
1020
|
+
if (mirrored.view === void 0) {
|
|
1021
|
+
this.failLoad(generation, mirrored.error ?? "settings are unavailable in this browser");
|
|
1022
|
+
return;
|
|
1023
|
+
}
|
|
1024
|
+
const providers = joinProviderDirectory(registered.value, declared.value);
|
|
1025
|
+
const writable = mirrored.view.writable;
|
|
1026
|
+
const views = mirrored.view.namespaces;
|
|
1027
|
+
const namespaces = new Map(views.map((view) => [view.ns, view]));
|
|
1028
|
+
const rows = providers.map((entry) => {
|
|
1029
|
+
const namespace = namespaces.get(entry.settingsNs);
|
|
1030
|
+
return {
|
|
1031
|
+
entry,
|
|
1032
|
+
configured: namespace !== void 0 && (entry.settingsPath.length === 0 || this.schema.getPath(namespace.value, entry.settingsPath) !== void 0),
|
|
1033
|
+
removable: namespace !== void 0 && entry.settingsPath.length > 0 && this.schema.hasPath(namespace.user, entry.settingsPath) && !this.schema.hasPath(namespace.base, entry.settingsPath),
|
|
1034
|
+
apiKeyEnv: apiKeyEnvOf(namespace, entry.settingsPath, this.schema),
|
|
1035
|
+
credential: void 0
|
|
1036
|
+
};
|
|
1037
|
+
});
|
|
1038
|
+
const refs = [...new Set(rows.map((row) => row.apiKeyEnv ?? deriveKeyRef(row.entry.provider)))];
|
|
1039
|
+
let credentials = {};
|
|
1040
|
+
let credentialError = null;
|
|
1041
|
+
if (refs.length > 0) {
|
|
1042
|
+
const response = await this.ctx.remote.credentials.describe(refs);
|
|
1043
|
+
if (response.ok) credentials = response.value;
|
|
1044
|
+
else credentialError = response.error.message;
|
|
1045
|
+
}
|
|
1046
|
+
if (generation !== this.generation) return;
|
|
1047
|
+
this.store.update((s) => {
|
|
1048
|
+
s.status = "ready";
|
|
1049
|
+
s.error = null;
|
|
1050
|
+
s.credentialError = credentialError;
|
|
1051
|
+
s.writable = writable;
|
|
1052
|
+
s.rows = rows.map((row) => {
|
|
1053
|
+
const named = row.apiKeyEnv === void 0 ? void 0 : credentials[row.apiKeyEnv];
|
|
1054
|
+
const derived = row.apiKeyEnv !== void 0 ? void 0 : credentials[deriveKeyRef(row.entry.provider)];
|
|
1055
|
+
return {
|
|
1056
|
+
...row,
|
|
1057
|
+
...named === void 0 ? {} : { credential: named },
|
|
1058
|
+
...derived === void 0 ? {} : { derivedCredential: derived }
|
|
1059
|
+
};
|
|
1060
|
+
});
|
|
1061
|
+
s.namespaces = namespaces;
|
|
1062
|
+
});
|
|
1063
|
+
}
|
|
1064
|
+
/** Publish one load's failure text, unless a newer load already took over. */
|
|
1065
|
+
failLoad(generation, message) {
|
|
1066
|
+
if (generation !== this.generation) return;
|
|
1067
|
+
this.store.update((s) => {
|
|
1068
|
+
s.status = "error";
|
|
1069
|
+
s.error = message;
|
|
1070
|
+
});
|
|
1071
|
+
}
|
|
1072
|
+
};
|
|
1073
|
+
/**
|
|
1074
|
+
* Whether a joined row can serve model requests as it stands: the route is
|
|
1075
|
+
* registered with the adapter registry, and whatever credential its resolved
|
|
1076
|
+
* profile names is stored. A profile naming no reference authenticates through
|
|
1077
|
+
* the provider's own path (the Bedrock chain, Vertex ADC, a gateway that needs
|
|
1078
|
+
* nothing), as does a live route with no settings address at all, so neither
|
|
1079
|
+
* owes this page a key.
|
|
1080
|
+
* @param row - one joined provider row.
|
|
1081
|
+
* @returns whether the user already has this provider to talk to.
|
|
1082
|
+
*/
|
|
1083
|
+
function providerUsable(row) {
|
|
1084
|
+
if (!row.entry.active) return false;
|
|
1085
|
+
if (row.apiKeyEnv === void 0) return true;
|
|
1086
|
+
return row.credential?.configured === true;
|
|
1087
|
+
}
|
|
1088
|
+
/**
|
|
1089
|
+
* Project first-run readiness from the provider/settings/credential join used
|
|
1090
|
+
* by the Models page. The step exists to leave the user with a model to talk
|
|
1091
|
+
* to, so ANY usable provider ends it; only when none exists does the official
|
|
1092
|
+
* DeepSeek route — the one route the prompt can offer a key field for — decide
|
|
1093
|
+
* whether prompting can help. A missing official configurable-provider
|
|
1094
|
+
* declaration means the adapter is not repairable by navigating to Models.
|
|
1095
|
+
* @param state - current shared Models join snapshot.
|
|
1096
|
+
* @returns the onboarding state without reading a parallel fact source.
|
|
1097
|
+
*/
|
|
1098
|
+
function onboardingReadiness(state) {
|
|
1099
|
+
if ((state.status === "idle" || state.status === "loading") && state.rows.length === 0) return { kind: "loading" };
|
|
1100
|
+
if (state.status === "error") return {
|
|
1101
|
+
kind: "unavailable",
|
|
1102
|
+
reason: "load-failed"
|
|
1103
|
+
};
|
|
1104
|
+
if (state.rows.some(providerUsable)) return { kind: "provider-ready" };
|
|
1105
|
+
const row = state.rows.find((candidate) => candidate.entry.provider === "deepseek-official" && candidate.entry.settingsNs === "llm-deepseek" && candidate.entry.settingsPath.length === 0);
|
|
1106
|
+
if (row === void 0) return { kind: "adapter-absent" };
|
|
1107
|
+
if (!row.entry.active) return {
|
|
1108
|
+
kind: "unavailable",
|
|
1109
|
+
reason: "provider-inactive"
|
|
1110
|
+
};
|
|
1111
|
+
if (state.credentialError !== null || row.credential === void 0) return {
|
|
1112
|
+
kind: "unavailable",
|
|
1113
|
+
reason: "credentials-unavailable"
|
|
1114
|
+
};
|
|
1115
|
+
if (!state.writable) return {
|
|
1116
|
+
kind: "unavailable",
|
|
1117
|
+
reason: "settings-read-only"
|
|
1118
|
+
};
|
|
1119
|
+
if (!row.credential.writable) return {
|
|
1120
|
+
kind: "unavailable",
|
|
1121
|
+
reason: "credential-read-only"
|
|
1122
|
+
};
|
|
1123
|
+
return { kind: "credential-missing" };
|
|
1124
|
+
}
|
|
1125
|
+
//#endregion
|
|
1069
1126
|
//#region lib/types/client/CustomProviderCard.js
|
|
1070
1127
|
/**
|
|
1071
1128
|
* The card that declares a provider pi-ai does not ship — an OpenAI-compatible
|
|
@@ -1076,7 +1133,7 @@ window.__ModuleLoader__.load({
|
|
|
1076
1133
|
* the provider editor with extra fields: the route id is being *chosen* here,
|
|
1077
1134
|
* and the settings address does not exist until it is. One `settings.mutate`
|
|
1078
1135
|
* sets the whole profile at `providers.<route>`; the key travels separately
|
|
1079
|
-
* through `credentials
|
|
1136
|
+
* through `credentials/set` under the reference the profile records, exactly as
|
|
1080
1137
|
* an existing provider's key does.
|
|
1081
1138
|
*
|
|
1082
1139
|
* The three fields a hand-declared route cannot default — endpoint, protocol,
|
|
@@ -1106,7 +1163,7 @@ window.__ModuleLoader__.load({
|
|
|
1106
1163
|
* @returns the creation card.
|
|
1107
1164
|
*/
|
|
1108
1165
|
function CustomProviderCard(props) {
|
|
1109
|
-
const { taken, protocols,
|
|
1166
|
+
const { taken, protocols, operations, t } = props;
|
|
1110
1167
|
const [openedAt] = (0, react.useState)(() => props.revision);
|
|
1111
1168
|
const [route, setRoute] = (0, react.useState)("");
|
|
1112
1169
|
const [displayName, setDisplayName] = (0, react.useState)("");
|
|
@@ -1147,31 +1204,25 @@ window.__ModuleLoader__.load({
|
|
|
1147
1204
|
models: models.map((model) => isAdaptiveClaude ? withNativeClaudeModel(model) : { ...model }),
|
|
1148
1205
|
...isAdaptiveClaude ? { reasoning: "high" } : {}
|
|
1149
1206
|
};
|
|
1150
|
-
const
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
}],
|
|
1157
|
-
expectedRevision: openedAt
|
|
1158
|
-
});
|
|
1159
|
-
if (!response.result.ok) return response.result.error.message;
|
|
1207
|
+
const written = await operations.writeSettings(NS$1, [{
|
|
1208
|
+
op: "set",
|
|
1209
|
+
path: ["providers", route],
|
|
1210
|
+
value: profile
|
|
1211
|
+
}], openedAt);
|
|
1212
|
+
if (written.kind !== "written") return written.kind === "conflict" ? t("conflict") : written.message;
|
|
1160
1213
|
setCommitted(true);
|
|
1161
1214
|
}
|
|
1162
1215
|
if (isAdaptiveClaude) {
|
|
1163
|
-
const typed = await
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1216
|
+
const typed = await operations.writeSettings(CLAUDE_PROVIDER_SETTINGS_NS, [{
|
|
1217
|
+
op: "set",
|
|
1218
|
+
path: ["providerTypes", route],
|
|
1219
|
+
value: CLAUDE_PROVIDER_TYPE
|
|
1220
|
+
}], void 0);
|
|
1221
|
+
if (typed.kind !== "written") return typed.kind === "conflict" ? t("conflict") : typed.message;
|
|
1168
1222
|
}
|
|
1169
1223
|
if (storesKey) {
|
|
1170
|
-
const stored = await
|
|
1171
|
-
|
|
1172
|
-
value: keyValue
|
|
1173
|
-
});
|
|
1174
|
-
if (!stored.result.ok) return stored.result.error.message;
|
|
1224
|
+
const stored = await operations.storeCredential(keyRef, keyValue);
|
|
1225
|
+
if (stored !== void 0) return stored;
|
|
1175
1226
|
}
|
|
1176
1227
|
};
|
|
1177
1228
|
const create = async () => {
|
|
@@ -1184,8 +1235,6 @@ window.__ModuleLoader__.load({
|
|
|
1184
1235
|
return;
|
|
1185
1236
|
}
|
|
1186
1237
|
props.onClose(true);
|
|
1187
|
-
} catch (error) {
|
|
1188
|
-
setFailure(messageOf(error));
|
|
1189
1238
|
} finally {
|
|
1190
1239
|
setBusy(false);
|
|
1191
1240
|
}
|
|
@@ -1255,7 +1304,7 @@ window.__ModuleLoader__.load({
|
|
|
1255
1304
|
className: ModelsSection_module_css_default["input"],
|
|
1256
1305
|
type: "text",
|
|
1257
1306
|
value: baseURL,
|
|
1258
|
-
placeholder: "
|
|
1307
|
+
placeholder: t("customBaseUrlPlaceholder"),
|
|
1259
1308
|
"aria-label": t("baseUrl"),
|
|
1260
1309
|
disabled: profileDisabled,
|
|
1261
1310
|
onChange: (event) => {
|
|
@@ -1318,7 +1367,7 @@ window.__ModuleLoader__.load({
|
|
|
1318
1367
|
},
|
|
1319
1368
|
probeBlocked: keyFailure === "keyBlank" ? "keyBlankNew" : keyFailure,
|
|
1320
1369
|
thinkingPresets: isAdaptiveClaude,
|
|
1321
|
-
|
|
1370
|
+
operations,
|
|
1322
1371
|
t,
|
|
1323
1372
|
disabled: profileDisabled
|
|
1324
1373
|
}),
|
|
@@ -1334,8 +1383,8 @@ window.__ModuleLoader__.load({
|
|
|
1334
1383
|
t,
|
|
1335
1384
|
busy,
|
|
1336
1385
|
submitDisabled: disabled || !ready,
|
|
1337
|
-
|
|
1338
|
-
|
|
1386
|
+
submitLabelKey: "create",
|
|
1387
|
+
submitBusyLabelKey: "creating",
|
|
1339
1388
|
onCancel: () => {
|
|
1340
1389
|
props.onClose(committed);
|
|
1341
1390
|
},
|
|
@@ -1351,7 +1400,7 @@ window.__ModuleLoader__.load({
|
|
|
1351
1400
|
/**
|
|
1352
1401
|
* One provider's editor card, hand-written per adapter family: the primary
|
|
1353
1402
|
* field is a single write-only **API key** input (the page never asks for an
|
|
1354
|
-
* environment-variable name — a typed key stores through `credentials
|
|
1403
|
+
* environment-variable name — a typed key stores through `credentials/set`
|
|
1355
1404
|
* under the profile's reference, deriving `<ROUTE>_API_KEY` when the profile
|
|
1356
1405
|
* has none. The pi-ai profile records that derivation as `apiKeyEnv` only when
|
|
1357
1406
|
* a key is entered; a blank key materializes a reference-free profile for
|
|
@@ -1423,7 +1472,7 @@ window.__ModuleLoader__.load({
|
|
|
1423
1472
|
* @returns the editor card.
|
|
1424
1473
|
*/
|
|
1425
1474
|
function ProviderEditor(props) {
|
|
1426
|
-
const { namespace, schema, settingsPath,
|
|
1475
|
+
const { namespace, schema, settingsPath, operations, t } = props;
|
|
1427
1476
|
const [draft, setDraft] = (0, react.useState)(() => draftAt(schema, namespace, settingsPath));
|
|
1428
1477
|
const [keyDraft, setKeyDraft] = (0, react.useState)("");
|
|
1429
1478
|
const [keyState, setKeyState] = (0, react.useState)(void 0);
|
|
@@ -1449,14 +1498,14 @@ window.__ModuleLoader__.load({
|
|
|
1449
1498
|
(0, react.useEffect)(() => {
|
|
1450
1499
|
let stale = false;
|
|
1451
1500
|
setKeyState(void 0);
|
|
1452
|
-
|
|
1453
|
-
if (stale
|
|
1454
|
-
setKeyState(
|
|
1455
|
-
}
|
|
1501
|
+
operations.describeCredential(keyRef).then((described) => {
|
|
1502
|
+
if (stale) return;
|
|
1503
|
+
setKeyState(described);
|
|
1504
|
+
});
|
|
1456
1505
|
return () => {
|
|
1457
1506
|
stale = true;
|
|
1458
1507
|
};
|
|
1459
|
-
}, [
|
|
1508
|
+
}, [operations, keyRef]);
|
|
1460
1509
|
const stringAt = (source, key) => {
|
|
1461
1510
|
const value = schema.getPath(source, [key]);
|
|
1462
1511
|
return typeof value === "string" && value.trim().length > 0 ? value : void 0;
|
|
@@ -1505,22 +1554,15 @@ window.__ModuleLoader__.load({
|
|
|
1505
1554
|
value: {}
|
|
1506
1555
|
}] : pathOps(settingsPath, committedOriginal, next);
|
|
1507
1556
|
if (ops.length > 0) {
|
|
1508
|
-
const
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
});
|
|
1513
|
-
if (!response.result.ok) return response.result.error.code === "settings-conflict" ? t("conflict") : response.result.error.message;
|
|
1514
|
-
setCommittedOriginal(schema.getPath(response.result.value.user, settingsPath));
|
|
1515
|
-
setExpectedRevision(response.result.value.revision);
|
|
1557
|
+
const written = await operations.writeSettings(ns, ops, expectedRevision);
|
|
1558
|
+
if (written.kind !== "written") return written.kind === "conflict" ? t("conflict") : written.message;
|
|
1559
|
+
setCommittedOriginal(schema.getPath(written.view.user, settingsPath));
|
|
1560
|
+
setExpectedRevision(written.view.revision);
|
|
1516
1561
|
setDraft(next);
|
|
1517
1562
|
}
|
|
1518
1563
|
if (keyValue.length > 0) {
|
|
1519
|
-
const stored = await
|
|
1520
|
-
|
|
1521
|
-
value: keyValue
|
|
1522
|
-
});
|
|
1523
|
-
if (!stored.result.ok) return stored.result.error.message;
|
|
1564
|
+
const stored = await operations.storeCredential(keyRef, keyValue);
|
|
1565
|
+
if (stored !== void 0) return stored;
|
|
1524
1566
|
}
|
|
1525
1567
|
setKeyDraft("");
|
|
1526
1568
|
};
|
|
@@ -1534,15 +1576,17 @@ window.__ModuleLoader__.load({
|
|
|
1534
1576
|
return;
|
|
1535
1577
|
}
|
|
1536
1578
|
props.onClose(true);
|
|
1537
|
-
} catch (error) {
|
|
1538
|
-
setFailure(messageOf(error));
|
|
1539
1579
|
} finally {
|
|
1540
1580
|
setBusy(false);
|
|
1541
1581
|
}
|
|
1542
1582
|
};
|
|
1543
|
-
if (node === void 0) return (0, react_jsx_runtime.
|
|
1583
|
+
if (node === void 0) return (0, react_jsx_runtime.jsxs)("p", {
|
|
1544
1584
|
className: ModelsSection_module_css_default["error"],
|
|
1545
|
-
children:
|
|
1585
|
+
children: [
|
|
1586
|
+
props.provider,
|
|
1587
|
+
": ",
|
|
1588
|
+
props.t("settingsPathUnresolvable")
|
|
1589
|
+
]
|
|
1546
1590
|
});
|
|
1547
1591
|
const keyLocked = keyState?.writable === false;
|
|
1548
1592
|
/**
|
|
@@ -1681,7 +1725,7 @@ window.__ModuleLoader__.load({
|
|
|
1681
1725
|
probe,
|
|
1682
1726
|
probeBlocked: keyFailure,
|
|
1683
1727
|
thinkingPresets: props.thinkingPresets === true,
|
|
1684
|
-
|
|
1728
|
+
operations
|
|
1685
1729
|
})
|
|
1686
1730
|
]
|
|
1687
1731
|
})]
|
|
@@ -1716,9 +1760,9 @@ window.__ModuleLoader__.load({
|
|
|
1716
1760
|
t,
|
|
1717
1761
|
busy,
|
|
1718
1762
|
submitDisabled: disabled || layout === "unknown" || props.credentialOnly !== true && modelFailure !== void 0 || shownKeyFailure !== void 0 || props.credentialRequired === true && keyValue.length === 0,
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
...props.
|
|
1763
|
+
submitLabelKey: props.submitLabelKey ?? "apply",
|
|
1764
|
+
submitBusyLabelKey: props.submitBusyLabelKey ?? "applying",
|
|
1765
|
+
...props.cancelLabelKey === void 0 ? {} : { cancelLabelKey: props.cancelLabelKey },
|
|
1722
1766
|
onCancel: () => {
|
|
1723
1767
|
props.onClose(false);
|
|
1724
1768
|
},
|
|
@@ -1760,33 +1804,26 @@ window.__ModuleLoader__.load({
|
|
|
1760
1804
|
* and the whole operation safely retryable; both unsets are idempotent.
|
|
1761
1805
|
* The settings removal names the profile rather than rebuilding its whole
|
|
1762
1806
|
* namespace from a partial view.
|
|
1763
|
-
* @param
|
|
1807
|
+
* @param operations - the page's Host operations.
|
|
1764
1808
|
* @param controller - the page store to refresh.
|
|
1765
1809
|
* @param target - the provider's settings address and optional managed credential.
|
|
1766
1810
|
* @returns the failure message, or undefined once the write and reload landed.
|
|
1767
1811
|
*/
|
|
1768
|
-
async function removeProviderProfile(
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
if (!credential.result.ok) return credential.result.error.message;
|
|
1773
|
-
}
|
|
1774
|
-
const response = await api.settings.mutate({
|
|
1775
|
-
ns: target.settingsNs,
|
|
1776
|
-
ops: [{
|
|
1777
|
-
op: "unset",
|
|
1778
|
-
path: [...target.settingsPath]
|
|
1779
|
-
}]
|
|
1780
|
-
});
|
|
1781
|
-
if (!response.result.ok) return response.result.error.message;
|
|
1782
|
-
const typeResponse = await api.settings.mutate({
|
|
1783
|
-
ns: CLAUDE_PROVIDER_SETTINGS_NS,
|
|
1784
|
-
ops: [{ op: "unset", path: ["providerTypes", target.provider] }]
|
|
1785
|
-
});
|
|
1786
|
-
if (!typeResponse.result.ok) return typeResponse.result.error.message;
|
|
1787
|
-
} catch (error) {
|
|
1788
|
-
return messageOf(error);
|
|
1812
|
+
async function removeProviderProfile(operations, controller, target) {
|
|
1813
|
+
if (target.credentialRef !== void 0) {
|
|
1814
|
+
const credential = await operations.removeCredential(target.credentialRef);
|
|
1815
|
+
if (credential !== void 0) return credential;
|
|
1789
1816
|
}
|
|
1817
|
+
const written = await operations.writeSettings(target.settingsNs, [{
|
|
1818
|
+
op: "unset",
|
|
1819
|
+
path: [...target.settingsPath]
|
|
1820
|
+
}], void 0);
|
|
1821
|
+
if (written.kind !== "written") return written.message;
|
|
1822
|
+
const typedRemoval = await operations.writeSettings(CLAUDE_PROVIDER_SETTINGS_NS, [{
|
|
1823
|
+
op: "unset",
|
|
1824
|
+
path: ["providerTypes", target.provider]
|
|
1825
|
+
}], void 0);
|
|
1826
|
+
if (typedRemoval.kind !== "written") return typedRemoval.message;
|
|
1790
1827
|
await controller.load();
|
|
1791
1828
|
}
|
|
1792
1829
|
/**
|
|
@@ -1803,6 +1840,16 @@ window.__ModuleLoader__.load({
|
|
|
1803
1840
|
if (row.entry.settingsPath.length > 0) return false;
|
|
1804
1841
|
return row.credential?.configured !== true;
|
|
1805
1842
|
}
|
|
1843
|
+
/**
|
|
1844
|
+
* The provider-card seat's credential fact: the reference this page would use
|
|
1845
|
+
* for the row — the profile's `apiKeyEnv`, or the page's derived
|
|
1846
|
+
* `<ROUTE>_API_KEY` while the profile names none — confirmed configured. The
|
|
1847
|
+
* derived half is what keeps the seat consistent with the editor on the
|
|
1848
|
+
* add-provider draft, whose dormant row names no reference yet.
|
|
1849
|
+
*/
|
|
1850
|
+
function keyConfiguredOf(row) {
|
|
1851
|
+
return row.apiKeyEnv !== void 0 ? row.credential?.configured === true : row.derivedCredential?.configured === true;
|
|
1852
|
+
}
|
|
1806
1853
|
function targetOf(row) {
|
|
1807
1854
|
const managedRef = deriveKeyRef(row.entry.provider);
|
|
1808
1855
|
const credentialRef = row.apiKeyEnv === managedRef && row.credential?.configured === true && row.credential.writable ? managedRef : void 0;
|
|
@@ -1818,7 +1865,6 @@ window.__ModuleLoader__.load({
|
|
|
1818
1865
|
const CLAUDE_DISCOVERY_API = "mofeng-anthropic-models";
|
|
1819
1866
|
const CLAUDE_PROVIDER_SETTINGS_NS = "dsh-claude-provider";
|
|
1820
1867
|
const CLAUDE_PROVIDER_TYPE = "claude-adaptive";
|
|
1821
|
-
const CLAUDE_PROVIDER_DIRECTORY_SENTINEL = "dsh-claude-provider-type";
|
|
1822
1868
|
const CLAUDE_FIVE_EFFORTS = Object.freeze({ low: "low", medium: "medium", high: "high", xhigh: "xhigh", max: "max" });
|
|
1823
1869
|
const CLAUDE_FOUR_EFFORTS = Object.freeze({ low: "low", medium: "medium", high: "high", max: "max" });
|
|
1824
1870
|
const CLAUDE_TOGGLE_EFFORTS = Object.freeze({ off: null, high: "high" });
|
|
@@ -1948,18 +1994,21 @@ window.__ModuleLoader__.load({
|
|
|
1948
1994
|
* @returns the section, or null while the shell has not injected yet.
|
|
1949
1995
|
*/
|
|
1950
1996
|
function ModelsSection(props) {
|
|
1951
|
-
const { controller, useSnapshot,
|
|
1952
|
-
if (controller === void 0 || useSnapshot === void 0 ||
|
|
1953
|
-
return (0, react_jsx_runtime.jsx)(Loaded, {
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1997
|
+
const { controller, useSnapshot, operations, schema, t, renderSlot } = props;
|
|
1998
|
+
if (controller === void 0 || useSnapshot === void 0 || operations === void 0 || schema === void 0 || t === void 0) return null;
|
|
1999
|
+
return (0, react_jsx_runtime.jsx)(Loaded, {
|
|
2000
|
+
injected: {
|
|
2001
|
+
controller,
|
|
2002
|
+
useSnapshot,
|
|
2003
|
+
operations,
|
|
2004
|
+
schema,
|
|
2005
|
+
t
|
|
2006
|
+
},
|
|
2007
|
+
renderSlot
|
|
2008
|
+
});
|
|
1960
2009
|
}
|
|
1961
|
-
function Loaded({ injected }) {
|
|
1962
|
-
const { controller,
|
|
2010
|
+
function Loaded({ injected, renderSlot }) {
|
|
2011
|
+
const { controller, operations, schema, t } = injected;
|
|
1963
2012
|
const state = injected.useSnapshot((snapshot) => snapshot);
|
|
1964
2013
|
const [editing, setEditing] = (0, react.useState)(void 0);
|
|
1965
2014
|
const [adding, setAdding] = (0, react.useState)(false);
|
|
@@ -2001,7 +2050,7 @@ window.__ModuleLoader__.load({
|
|
|
2001
2050
|
if (deleteTarget === void 0 || deleting) return;
|
|
2002
2051
|
setDeleting(true);
|
|
2003
2052
|
setDeleteFailure(void 0);
|
|
2004
|
-
removeProviderProfile(
|
|
2053
|
+
removeProviderProfile(operations, controller, deleteTarget).then((failure) => {
|
|
2005
2054
|
if (failure !== void 0) {
|
|
2006
2055
|
setDeleteFailure(failure);
|
|
2007
2056
|
return;
|
|
@@ -2040,6 +2089,7 @@ window.__ModuleLoader__.load({
|
|
|
2040
2089
|
const addable = state.rows.filter((row) => !row.configured && row.entry.settingsNs !== "");
|
|
2041
2090
|
const addTarget = adding ? editing : void 0;
|
|
2042
2091
|
const addNamespace = addTarget === void 0 ? void 0 : state.namespaces.get(addTarget.settingsNs);
|
|
2092
|
+
const addRow = addTarget === void 0 ? void 0 : state.rows.find((row) => row.entry.provider === addTarget.provider);
|
|
2043
2093
|
const protocols = protocolChoices(state.namespaces.get("llm-pi-ai"), schema);
|
|
2044
2094
|
return (0, react_jsx_runtime.jsxs)("div", {
|
|
2045
2095
|
className: ModelsSection_module_css_default["section"],
|
|
@@ -2069,20 +2119,24 @@ window.__ModuleLoader__.load({
|
|
|
2069
2119
|
const namespace = state.namespaces.get(target.settingsNs);
|
|
2070
2120
|
/* v8 ignore next -- the join marks a row configured only when its namespace resolved */
|
|
2071
2121
|
if (namespace === void 0) return null;
|
|
2072
|
-
if (needsSetup(row, anyUsable) && !dismissedSetup.has(row.entry.provider)) return (0, react_jsx_runtime.
|
|
2122
|
+
if (needsSetup(row, anyUsable) && !dismissedSetup.has(row.entry.provider)) return (0, react_jsx_runtime.jsxs)("li", {
|
|
2073
2123
|
className: ModelsSection_module_css_default["setupCard"],
|
|
2074
|
-
children: renderProviderEditor({
|
|
2124
|
+
children: [renderProviderEditor({
|
|
2075
2125
|
target,
|
|
2076
2126
|
namespace,
|
|
2077
2127
|
schema,
|
|
2078
2128
|
thinkingPresets: isClaudeProvider(row, state),
|
|
2079
|
-
|
|
2129
|
+
operations,
|
|
2080
2130
|
t,
|
|
2081
2131
|
readOnly: !state.writable,
|
|
2082
2132
|
onClose: (changed) => {
|
|
2083
2133
|
closeSetup(changed, target);
|
|
2084
2134
|
}
|
|
2085
|
-
})
|
|
2135
|
+
}), renderSlot("settings.models.provider-card", {
|
|
2136
|
+
provider: row.entry,
|
|
2137
|
+
configured: row.configured,
|
|
2138
|
+
keyConfigured: keyConfiguredOf(row)
|
|
2139
|
+
}, { entryKey: row.entry.settingsNs })]
|
|
2086
2140
|
}, row.entry.provider);
|
|
2087
2141
|
const open = !adding && editing?.provider === row.entry.provider;
|
|
2088
2142
|
const adaptiveClaude = isClaudeProvider(row, state);
|
|
@@ -2090,73 +2144,81 @@ window.__ModuleLoader__.load({
|
|
|
2090
2144
|
const credentialMissing = !credentialConfigured && row.apiKeyEnv !== void 0 && row.credential?.configured === false;
|
|
2091
2145
|
return (0, react_jsx_runtime.jsxs)("li", {
|
|
2092
2146
|
className: ModelsSection_module_css_default["rowCard"],
|
|
2093
|
-
children: [
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2147
|
+
children: [
|
|
2148
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
2149
|
+
className: ModelsSection_module_css_default["rowHead"],
|
|
2150
|
+
children: [(0, react_jsx_runtime.jsxs)("span", {
|
|
2151
|
+
className: ModelsSection_module_css_default["rowIdentity"],
|
|
2152
|
+
children: [
|
|
2153
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
2154
|
+
className: ModelsSection_module_css_default["rowName"],
|
|
2155
|
+
children: row.entry.displayName
|
|
2156
|
+
}),
|
|
2157
|
+
row.entry.declared === true ? (0, react_jsx_runtime.jsx)("span", {
|
|
2158
|
+
className: ModelsSection_module_css_default["rowTag"],
|
|
2159
|
+
children: t("customTag")
|
|
2160
|
+
}) : null,
|
|
2161
|
+
adaptiveClaude ? (0, react_jsx_runtime.jsx)("span", {
|
|
2162
|
+
className: ModelsSection_module_css_default["rowTag"],
|
|
2163
|
+
children: t("claudeTypeTag")
|
|
2164
|
+
}) : null,
|
|
2165
|
+
credentialConfigured ? (0, react_jsx_runtime.jsx)("span", {
|
|
2166
|
+
className: `${ModelsSection_module_css_default["credentialDot"]} ${ModelsSection_module_css_default["credentialDotConfigured"]}`,
|
|
2167
|
+
role: "img",
|
|
2168
|
+
"aria-label": t("credentialConfigured"),
|
|
2169
|
+
title: t("credentialConfigured")
|
|
2170
|
+
}) : credentialMissing ? (0, react_jsx_runtime.jsx)("span", {
|
|
2171
|
+
className: `${ModelsSection_module_css_default["credentialDot"]} ${ModelsSection_module_css_default["credentialDotMissing"]}`,
|
|
2172
|
+
role: "img",
|
|
2173
|
+
"aria-label": t("credentialMissing"),
|
|
2174
|
+
title: t("credentialMissing")
|
|
2175
|
+
}) : null
|
|
2176
|
+
]
|
|
2177
|
+
}), (0, react_jsx_runtime.jsxs)("span", {
|
|
2178
|
+
className: ModelsSection_module_css_default["rowActions"],
|
|
2179
|
+
children: [(0, react_jsx_runtime.jsx)("button", {
|
|
2180
|
+
type: "button",
|
|
2181
|
+
className: ModelsSection_module_css_default["secondaryButton"],
|
|
2182
|
+
"aria-label": providerCopy(t("editProvider"), target),
|
|
2183
|
+
onClick: () => {
|
|
2184
|
+
setSavedTarget(void 0);
|
|
2185
|
+
setDeclaringType(void 0);
|
|
2186
|
+
setAdding(false);
|
|
2187
|
+
setEditing(open ? void 0 : target);
|
|
2188
|
+
},
|
|
2189
|
+
children: t("edit")
|
|
2190
|
+
}), row.removable ? (0, react_jsx_runtime.jsx)("button", {
|
|
2191
|
+
type: "button",
|
|
2192
|
+
className: ModelsSection_module_css_default["dangerButton"],
|
|
2193
|
+
"aria-label": providerCopy(t("removeProvider"), target),
|
|
2194
|
+
disabled: !state.writable,
|
|
2195
|
+
onClick: () => {
|
|
2196
|
+
setSavedTarget(void 0);
|
|
2197
|
+
setDeleteFailure(void 0);
|
|
2198
|
+
setDeleteTarget(target);
|
|
2199
|
+
},
|
|
2200
|
+
children: t("remove")
|
|
2201
|
+
}) : null]
|
|
2202
|
+
})]
|
|
2203
|
+
}),
|
|
2204
|
+
renderSlot("settings.models.provider-card", {
|
|
2205
|
+
provider: row.entry,
|
|
2206
|
+
configured: row.configured,
|
|
2207
|
+
keyConfigured: keyConfiguredOf(row)
|
|
2208
|
+
}, { entryKey: row.entry.settingsNs }),
|
|
2209
|
+
open ? renderProviderEditor({
|
|
2210
|
+
target,
|
|
2211
|
+
namespace,
|
|
2212
|
+
schema,
|
|
2213
|
+
thinkingPresets: isClaudeProvider(row, state),
|
|
2214
|
+
operations,
|
|
2215
|
+
t,
|
|
2216
|
+
readOnly: !state.writable,
|
|
2217
|
+
onClose: (changed) => {
|
|
2218
|
+
closeEditor(changed, target);
|
|
2219
|
+
}
|
|
2220
|
+
}) : null
|
|
2221
|
+
]
|
|
2160
2222
|
}, row.entry.provider);
|
|
2161
2223
|
})
|
|
2162
2224
|
}),
|
|
@@ -2164,40 +2226,48 @@ window.__ModuleLoader__.load({
|
|
|
2164
2226
|
className: ModelsSection_module_css_default["addBlock"],
|
|
2165
2227
|
children: addTarget !== void 0 && addNamespace !== void 0 ? (0, react_jsx_runtime.jsxs)("div", {
|
|
2166
2228
|
className: ModelsSection_module_css_default["addCard"],
|
|
2167
|
-
children: [
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2229
|
+
children: [
|
|
2230
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
2231
|
+
className: ModelsSection_module_css_default["field"],
|
|
2232
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
2233
|
+
className: ModelsSection_module_css_default["fieldLabel"],
|
|
2234
|
+
children: t("provider")
|
|
2235
|
+
}), (0, react_jsx_runtime.jsx)("select", {
|
|
2236
|
+
className: `${ModelsSection_module_css_default["input"]} ${ModelsSection_module_css_default["selectInput"]}`,
|
|
2237
|
+
value: addTarget.provider,
|
|
2238
|
+
"aria-label": t("provider"),
|
|
2239
|
+
onChange: (event) => {
|
|
2240
|
+
const row = addable.find((candidate) => candidate.entry.provider === event.target.value);
|
|
2241
|
+
/* v8 ignore next -- the select only lists addable rows */
|
|
2242
|
+
if (row === void 0) return;
|
|
2243
|
+
setEditing(targetOf(row));
|
|
2244
|
+
},
|
|
2245
|
+
children: addable.map((row) => (0, react_jsx_runtime.jsx)("option", {
|
|
2246
|
+
value: row.entry.provider,
|
|
2247
|
+
children: row.entry.displayName
|
|
2248
|
+
}, row.entry.provider))
|
|
2249
|
+
})]
|
|
2250
|
+
}),
|
|
2251
|
+
(0, react_jsx_runtime.jsx)(ProviderEditor, {
|
|
2252
|
+
provider: addTarget.provider,
|
|
2253
|
+
displayName: addTarget.displayName,
|
|
2254
|
+
hideTitle: true,
|
|
2255
|
+
namespace: addNamespace,
|
|
2256
|
+
schema,
|
|
2257
|
+
settingsPath: addTarget.settingsPath,
|
|
2258
|
+
operations,
|
|
2259
|
+
t,
|
|
2260
|
+
readOnly: !state.writable,
|
|
2261
|
+
onClose: (changed) => {
|
|
2262
|
+
closeEditor(changed, addTarget);
|
|
2263
|
+
}
|
|
2264
|
+
}, addTarget.provider),
|
|
2265
|
+
addRow === void 0 ? null : renderSlot("settings.models.provider-card", {
|
|
2266
|
+
provider: addRow.entry,
|
|
2267
|
+
configured: addRow.configured,
|
|
2268
|
+
keyConfigured: keyConfiguredOf(addRow)
|
|
2269
|
+
}, { entryKey: addRow.entry.settingsNs })
|
|
2270
|
+
]
|
|
2201
2271
|
}) : declaringType !== void 0 ? (0, react_jsx_runtime.jsx)("div", {
|
|
2202
2272
|
className: ModelsSection_module_css_default["addCard"],
|
|
2203
2273
|
children: (0, react_jsx_runtime.jsx)(CustomProviderCard, {
|
|
@@ -2206,7 +2276,7 @@ window.__ModuleLoader__.load({
|
|
|
2206
2276
|
providerType: declaringType,
|
|
2207
2277
|
/* v8 ignore next -- the card only opens from a button disabled without this namespace */
|
|
2208
2278
|
revision: state.namespaces.get("llm-pi-ai")?.revision ?? 0,
|
|
2209
|
-
|
|
2279
|
+
operations,
|
|
2210
2280
|
t,
|
|
2211
2281
|
readOnly: !state.writable,
|
|
2212
2282
|
onClose: (changed) => {
|
|
@@ -2255,6 +2325,7 @@ window.__ModuleLoader__.load({
|
|
|
2255
2325
|
})]
|
|
2256
2326
|
})
|
|
2257
2327
|
}),
|
|
2328
|
+
renderSlot("settings.models.footer", {}),
|
|
2258
2329
|
(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
2259
2330
|
open: deleteTarget !== void 0,
|
|
2260
2331
|
onClose: closeDelete,
|
|
@@ -2380,7 +2451,7 @@ window.__ModuleLoader__.load({
|
|
|
2380
2451
|
* @returns the onboarding modal or null when onboarding needs no intervention.
|
|
2381
2452
|
*/
|
|
2382
2453
|
function DeepSeekOnboardingDialog(props) {
|
|
2383
|
-
const { complete, controller, useModels,
|
|
2454
|
+
const { complete, controller, useModels, operations, schema, t } = props;
|
|
2384
2455
|
const state = useModels((snapshot) => snapshot);
|
|
2385
2456
|
const readiness = onboardingReadiness(state);
|
|
2386
2457
|
(0, react.useEffect)(() => {
|
|
@@ -2422,16 +2493,16 @@ window.__ModuleLoader__.load({
|
|
|
2422
2493
|
namespace,
|
|
2423
2494
|
schema,
|
|
2424
2495
|
settingsPath: row.entry.settingsPath,
|
|
2425
|
-
|
|
2496
|
+
operations,
|
|
2426
2497
|
t,
|
|
2427
2498
|
readOnly: false,
|
|
2428
2499
|
hideTitle: true,
|
|
2429
2500
|
credentialOnly: true,
|
|
2430
2501
|
credentialRequired: true,
|
|
2431
2502
|
autoFocusCredential: true,
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2503
|
+
cancelLabelKey: "onboardingLater",
|
|
2504
|
+
submitLabelKey: "onboardingSave",
|
|
2505
|
+
submitBusyLabelKey: "onboardingSaving",
|
|
2435
2506
|
onClose: finishCredential
|
|
2436
2507
|
})
|
|
2437
2508
|
})]
|
|
@@ -2521,19 +2592,6 @@ window.__ModuleLoader__.load({
|
|
|
2521
2592
|
* again. The acknowledgement is compared for exact equality.
|
|
2522
2593
|
*/
|
|
2523
2594
|
const WELCOME_NOTICE_VERSION = "2026-08-13.1";
|
|
2524
|
-
/** The complete editable internal-testing notice in both supported GUI locales. */
|
|
2525
|
-
const WELCOME_NOTICE_COPY = {
|
|
2526
|
-
zh: {
|
|
2527
|
-
title: "内测声明",
|
|
2528
|
-
body: "DeepSeek Harness 目前的 0.1 版本仍处在面向 Harness 开发者进行测试的阶段,还有许多地方需要持续改进和打磨,希望听取广大开发者的反馈建议。预计 DeepSeek Harness 的核心插件以及基础 API 都会在接下来的一段时间内快速迭代、持续演化。\n\n我们期待与全球开发者一起,在开源、开放、可复用、可组合的基础设施之上,共同探索智能上限。欢迎全球 Harness 开发者加入 DSH 插件生态。",
|
|
2529
|
-
continueLabel: "继续"
|
|
2530
|
-
},
|
|
2531
|
-
en: {
|
|
2532
|
-
title: "Internal Testing Notice",
|
|
2533
|
-
body: "DeepSeek Harness 0.1 remains in testing for Harness developers. Many areas need further improvement, and we welcome feedback from the developer community. DeepSeek Harness's core plugins and foundational APIs will continue to evolve rapidly over the coming months.\n\nWe look forward to exploring the limits of intelligence with developers around the world, building on open-source, open, reusable, and composable infrastructure. We welcome Harness developers everywhere to join the DSH plugin ecosystem.",
|
|
2534
|
-
continueLabel: "Continue"
|
|
2535
|
-
}
|
|
2536
|
-
};
|
|
2537
2595
|
//#endregion
|
|
2538
2596
|
//#region lib/types/client/welcome-store.js
|
|
2539
2597
|
/**
|
|
@@ -2560,7 +2618,7 @@ window.__ModuleLoader__.load({
|
|
|
2560
2618
|
var WelcomeNoticeStore = class {
|
|
2561
2619
|
scope;
|
|
2562
2620
|
/** uSES-safe state source shared by the registered welcome step. */
|
|
2563
|
-
store = (0,
|
|
2621
|
+
store = (0, _deepseek_ai_dsh_client_store.createSnapshotStore)({
|
|
2564
2622
|
status: "idle",
|
|
2565
2623
|
acknowledged: false,
|
|
2566
2624
|
error: null
|
|
@@ -2661,6 +2719,61 @@ window.__ModuleLoader__.load({
|
|
|
2661
2719
|
}
|
|
2662
2720
|
};
|
|
2663
2721
|
//#endregion
|
|
2722
|
+
//#region lib/types/client/operations.js
|
|
2723
|
+
/**
|
|
2724
|
+
* The Host reads and writes the Models cards perform, as callbacks built in the
|
|
2725
|
+
* plugin body. Cards receive these instead of a context: the outcomes name what
|
|
2726
|
+
* a card renders — a stored view, a stale revision, a refusal message — so the
|
|
2727
|
+
* failure codes and Remote namespaces stay in the apply world.
|
|
2728
|
+
*/
|
|
2729
|
+
/**
|
|
2730
|
+
* Bind the page's Host operations to the plugin's own Remote namespaces.
|
|
2731
|
+
* @param ctx - the page plugin's context, which declares `remote.credentials`,
|
|
2732
|
+
* `remote.llm`, and `remote.settings` in its own `inject`.
|
|
2733
|
+
* @returns the callbacks the section and its cards are injected with.
|
|
2734
|
+
*/
|
|
2735
|
+
function createModelsOperations(ctx) {
|
|
2736
|
+
return {
|
|
2737
|
+
describeCredential: async (ref) => {
|
|
2738
|
+
const response = await ctx.remote.credentials.describe([ref]);
|
|
2739
|
+
return response.ok ? response.value[ref] : void 0;
|
|
2740
|
+
},
|
|
2741
|
+
storeCredential: async (ref, value) => {
|
|
2742
|
+
const response = await ctx.remote.credentials.set(ref, value);
|
|
2743
|
+
return response.ok ? void 0 : response.error.message;
|
|
2744
|
+
},
|
|
2745
|
+
removeCredential: async (ref) => {
|
|
2746
|
+
const response = await ctx.remote.credentials.unset(ref);
|
|
2747
|
+
return response.ok ? void 0 : response.error.message;
|
|
2748
|
+
},
|
|
2749
|
+
writeSettings: async (ns, ops, expectedRevision) => {
|
|
2750
|
+
const response = await ctx.remote.settings.mutate(ns, ops, expectedRevision);
|
|
2751
|
+
if (response.ok) return {
|
|
2752
|
+
kind: "written",
|
|
2753
|
+
view: response.value
|
|
2754
|
+
};
|
|
2755
|
+
const { code, message } = response.error;
|
|
2756
|
+
return code === "settings/conflict" ? {
|
|
2757
|
+
kind: "conflict",
|
|
2758
|
+
message
|
|
2759
|
+
} : {
|
|
2760
|
+
kind: "refused",
|
|
2761
|
+
message
|
|
2762
|
+
};
|
|
2763
|
+
},
|
|
2764
|
+
discoverModels: async (settingsNs, request) => {
|
|
2765
|
+
const response = await ctx.remote.llm.discoverModels(settingsNs, request);
|
|
2766
|
+
return response.ok ? {
|
|
2767
|
+
kind: "found",
|
|
2768
|
+
models: response.value
|
|
2769
|
+
} : {
|
|
2770
|
+
kind: "refused",
|
|
2771
|
+
message: response.error.message
|
|
2772
|
+
};
|
|
2773
|
+
}
|
|
2774
|
+
};
|
|
2775
|
+
}
|
|
2776
|
+
//#endregion
|
|
2664
2777
|
//#region lib/types/client/schema-operations.js
|
|
2665
2778
|
/**
|
|
2666
2779
|
* Hide the Cordis service identity behind bound schema callbacks.
|
|
@@ -2751,6 +2864,8 @@ window.__ModuleLoader__.load({
|
|
|
2751
2864
|
fetchEmpty: "The provider listed no models. Add them by hand.",
|
|
2752
2865
|
fetchTitle: "Choose models to add",
|
|
2753
2866
|
fetchDescription: "These are the models this provider has available. Choose the ones to add.",
|
|
2867
|
+
fetchSearch: "Search models",
|
|
2868
|
+
fetchNoMatches: "No matching models.",
|
|
2754
2869
|
fetchSelectAll: "Select all",
|
|
2755
2870
|
fetchDeselectAll: "Deselect all",
|
|
2756
2871
|
fetchAdopt: "Add selected",
|
|
@@ -2779,11 +2894,13 @@ window.__ModuleLoader__.load({
|
|
|
2779
2894
|
customApiUnset: "Not selected",
|
|
2780
2895
|
customNeedsBaseUrl: "A custom provider needs a base URL.",
|
|
2781
2896
|
customNeedsModels: "A custom provider needs at least one model.",
|
|
2897
|
+
customBaseUrlPlaceholder: "https://gateway.example/v1",
|
|
2898
|
+
settingsPathUnresolvable: "unresolvable settings path",
|
|
2782
2899
|
create: "Create provider",
|
|
2783
2900
|
creating: "Creating…",
|
|
2784
|
-
welcomeTitle:
|
|
2785
|
-
welcomeBody:
|
|
2786
|
-
welcomeContinue:
|
|
2901
|
+
welcomeTitle: "Internal Testing Notice",
|
|
2902
|
+
welcomeBody: "DeepSeek Harness 0.1 remains in testing for Harness developers. Many areas need further improvement, and we welcome feedback from the developer community. DeepSeek Harness's core plugins and foundational APIs will continue to evolve rapidly over the coming months.\n\nWe look forward to exploring the limits of intelligence with developers around the world, building on open-source, open, reusable, and composable infrastructure. We welcome Harness developers everywhere to join the DSH plugin ecosystem.",
|
|
2903
|
+
welcomeContinue: "Continue",
|
|
2787
2904
|
welcomeError: "The acknowledgement could not be saved. Please try again.",
|
|
2788
2905
|
onboardingTitle: "Add an API key to get started",
|
|
2789
2906
|
onboardingDescription: "Configure the official DeepSeek provider to start building.",
|
|
@@ -2862,6 +2979,8 @@ window.__ModuleLoader__.load({
|
|
|
2862
2979
|
fetchEmpty: "该提供方没有列出任何模型,请手动添加。",
|
|
2863
2980
|
fetchTitle: "选择要添加的模型",
|
|
2864
2981
|
fetchDescription: "以下是模型提供方的可用模型,勾选要添加的模型。",
|
|
2982
|
+
fetchSearch: "搜索模型",
|
|
2983
|
+
fetchNoMatches: "没有匹配的模型。",
|
|
2865
2984
|
fetchSelectAll: "全选",
|
|
2866
2985
|
fetchDeselectAll: "取消全选",
|
|
2867
2986
|
fetchAdopt: "添加所选",
|
|
@@ -2890,11 +3009,13 @@ window.__ModuleLoader__.load({
|
|
|
2890
3009
|
customApiUnset: "未选择",
|
|
2891
3010
|
customNeedsBaseUrl: "自定义提供方需要填写 API 地址。",
|
|
2892
3011
|
customNeedsModels: "自定义提供方至少需要一个模型。",
|
|
3012
|
+
customBaseUrlPlaceholder: "https://gateway.example/v1",
|
|
3013
|
+
settingsPathUnresolvable: "无法解析设置路径",
|
|
2893
3014
|
create: "创建提供方",
|
|
2894
3015
|
creating: "创建中…",
|
|
2895
|
-
welcomeTitle:
|
|
2896
|
-
welcomeBody:
|
|
2897
|
-
welcomeContinue:
|
|
3016
|
+
welcomeTitle: "内测声明",
|
|
3017
|
+
welcomeBody: "DeepSeek Harness 目前的 0.1 版本仍处在面向 Harness 开发者进行测试的阶段,还有许多地方需要持续改进和打磨,希望听取广大开发者的反馈建议。预计 DeepSeek Harness 的核心插件以及基础 API 都会在接下来的一段时间内快速迭代、持续演化。\n\n我们期待与全球开发者一起,在开源、开放、可复用、可组合的基础设施之上,共同探索智能上限。欢迎全球 Harness 开发者加入 DSH 插件生态。",
|
|
3018
|
+
welcomeContinue: "继续",
|
|
2898
3019
|
welcomeError: "暂时无法保存确认状态,请重试。",
|
|
2899
3020
|
onboardingTitle: "添加一个 API Key 开始使用",
|
|
2900
3021
|
onboardingDescription: "配置 DeepSeek 官方模型,即可开始使用。",
|
|
@@ -2924,8 +3045,10 @@ window.__ModuleLoader__.load({
|
|
|
2924
3045
|
const inject = [
|
|
2925
3046
|
"slots",
|
|
2926
3047
|
"locale",
|
|
2927
|
-
"connection",
|
|
2928
3048
|
"remote",
|
|
3049
|
+
"remote.credentials",
|
|
3050
|
+
"remote.llm",
|
|
3051
|
+
"remote.settings",
|
|
2929
3052
|
"settingsScope",
|
|
2930
3053
|
"settingsSchema"
|
|
2931
3054
|
];
|
|
@@ -2940,21 +3063,21 @@ window.__ModuleLoader__.load({
|
|
|
2940
3063
|
zh,
|
|
2941
3064
|
en
|
|
2942
3065
|
}), "ui-settings-models: copy dictionaries");
|
|
2943
|
-
const connection = ctx.get("connection");
|
|
2944
3066
|
const schema = createSettingsSchemaOperations(ctx.settingsSchema);
|
|
2945
|
-
const
|
|
3067
|
+
const operations = createModelsOperations(ctx);
|
|
3068
|
+
const controller = new ModelsSettingsStore(ctx, schema, ctx.settingsScope.describe());
|
|
2946
3069
|
const t = ctx.locale.bind(NS);
|
|
2947
3070
|
const injected = () => ({
|
|
2948
3071
|
controller,
|
|
2949
3072
|
hooks: { snapshot: controller.store },
|
|
2950
|
-
|
|
3073
|
+
operations,
|
|
2951
3074
|
schema,
|
|
2952
3075
|
t
|
|
2953
3076
|
});
|
|
2954
3077
|
const deepSeekOnboardingInjected = () => ({
|
|
2955
3078
|
controller,
|
|
2956
3079
|
hooks: { models: controller.store },
|
|
2957
|
-
|
|
3080
|
+
operations,
|
|
2958
3081
|
schema,
|
|
2959
3082
|
t
|
|
2960
3083
|
});
|
|
@@ -2990,7 +3113,17 @@ window.__ModuleLoader__.load({
|
|
|
2990
3113
|
id: "models",
|
|
2991
3114
|
order: 10,
|
|
2992
3115
|
label: () => t("nav"),
|
|
2993
|
-
inject: injected
|
|
3116
|
+
inject: injected,
|
|
3117
|
+
children: {
|
|
3118
|
+
"settings.models.provider-card": {
|
|
3119
|
+
kind: "keyed",
|
|
3120
|
+
scope: "root"
|
|
3121
|
+
},
|
|
3122
|
+
"settings.models.footer": {
|
|
3123
|
+
kind: "list",
|
|
3124
|
+
scope: "root"
|
|
3125
|
+
}
|
|
3126
|
+
}
|
|
2994
3127
|
}, ModelsSection));
|
|
2995
3128
|
ctx.slots.inject("settings.onboarding", () => ctx.slots.register({
|
|
2996
3129
|
name: "settings.onboarding",
|