@mofeng2223/dsh-claude-provider 0.3.0 → 0.4.0
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 +3 -18
- package/README.zh-CN.md +3 -18
- package/lib/client.js +552 -446
- package/package.json +7 -9
- package/src/index.js +38 -25
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: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,.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_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}";
|
|
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");
|
|
@@ -127,6 +127,7 @@ window.__ModuleLoader__.load({
|
|
|
127
127
|
"section": "zGbnIq_section",
|
|
128
128
|
"selectInput": "zGbnIq_selectInput",
|
|
129
129
|
"setupCard": "zGbnIq_setupCard",
|
|
130
|
+
"switchThumb": "zGbnIq_switchThumb",
|
|
130
131
|
"title": "zGbnIq_title"
|
|
131
132
|
};
|
|
132
133
|
//#endregion
|
|
@@ -145,13 +146,13 @@ window.__ModuleLoader__.load({
|
|
|
145
146
|
className: ModelsSection_module_css_default["secondaryButton"],
|
|
146
147
|
disabled: props.busy,
|
|
147
148
|
onClick: props.onCancel,
|
|
148
|
-
children: t(props.
|
|
149
|
+
children: t(props.cancelLabelKey ?? "cancel")
|
|
149
150
|
}), (0, react_jsx_runtime.jsx)("button", {
|
|
150
151
|
type: "button",
|
|
151
152
|
className: ModelsSection_module_css_default["primaryButton"],
|
|
152
153
|
disabled: props.submitDisabled,
|
|
153
154
|
onClick: props.onSubmit,
|
|
154
|
-
children: props.busy ? t(props.
|
|
155
|
+
children: props.busy ? t(props.submitBusyLabelKey) : t(props.submitLabelKey)
|
|
155
156
|
})]
|
|
156
157
|
});
|
|
157
158
|
}
|
|
@@ -443,212 +444,6 @@ window.__ModuleLoader__.load({
|
|
|
443
444
|
});
|
|
444
445
|
}
|
|
445
446
|
//#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
447
|
//#region lib/types/client/ModelListEditor.js
|
|
653
448
|
/**
|
|
654
449
|
* The model list of one pi-ai provider profile, plus the action that asks the
|
|
@@ -753,7 +548,7 @@ window.__ModuleLoader__.load({
|
|
|
753
548
|
* @returns the model-list editor.
|
|
754
549
|
*/
|
|
755
550
|
function ModelListEditor(props) {
|
|
756
|
-
const { models, onChange, probe,
|
|
551
|
+
const { models, onChange, probe, operations, t, disabled } = props;
|
|
757
552
|
const [busy, setBusy] = (0, react.useState)(false);
|
|
758
553
|
const [failure, setFailure] = (0, react.useState)(void 0);
|
|
759
554
|
const [candidates, setCandidates] = (0, react.useState)(void 0);
|
|
@@ -799,18 +594,17 @@ window.__ModuleLoader__.load({
|
|
|
799
594
|
setBusy(true);
|
|
800
595
|
setFailure(void 0);
|
|
801
596
|
try {
|
|
802
|
-
const
|
|
803
|
-
settingsNs: probe.settingsNs,
|
|
597
|
+
const answer = await operations.discoverModels(probe.settingsNs, {
|
|
804
598
|
...probe.provider === void 0 ? {} : { provider: probe.provider },
|
|
805
599
|
...probe.baseURL === void 0 || probe.baseURL.length === 0 ? {} : { baseURL: probe.baseURL },
|
|
806
600
|
...probe.api === void 0 ? {} : { api: props.thinkingPresets ? CLAUDE_DISCOVERY_API : probe.api },
|
|
807
601
|
...probe.apiKey === void 0 ? {} : { apiKey: probe.apiKey }
|
|
808
602
|
});
|
|
809
|
-
if (
|
|
810
|
-
setFailure(
|
|
603
|
+
if (answer.kind === "refused") {
|
|
604
|
+
setFailure(answer.message);
|
|
811
605
|
return;
|
|
812
606
|
}
|
|
813
|
-
const found =
|
|
607
|
+
const found = answer.models;
|
|
814
608
|
if (found.length === 0) {
|
|
815
609
|
setFailure(t("fetchEmpty"));
|
|
816
610
|
return;
|
|
@@ -818,8 +612,6 @@ window.__ModuleLoader__.load({
|
|
|
818
612
|
const known = new Set(models.map((model) => textOf(model, "id")));
|
|
819
613
|
setCandidates(found);
|
|
820
614
|
setPicked(new Set(found.filter((model) => !known.has(model.id)).map((model) => model.id)));
|
|
821
|
-
} catch (error) {
|
|
822
|
-
setFailure(messageOf(error));
|
|
823
615
|
} finally {
|
|
824
616
|
setBusy(false);
|
|
825
617
|
}
|
|
@@ -1066,6 +858,247 @@ window.__ModuleLoader__.load({
|
|
|
1066
858
|
});
|
|
1067
859
|
}
|
|
1068
860
|
//#endregion
|
|
861
|
+
//#region lib/types/client/store.js
|
|
862
|
+
/**
|
|
863
|
+
* Models settings page store: one snapshot joining the configurable-provider
|
|
864
|
+
* directory (`llm/listProviders` joined with `llm/listConfigurableProviders`),
|
|
865
|
+
* the settings namespaces (shared settings mirror),
|
|
866
|
+
* and the referenced credentials (`credentials/describe`). The host stays the
|
|
867
|
+
* single fact source — every mutation writes through the wire and the page
|
|
868
|
+
* re-renders from the next describe, pushed or refetched.
|
|
869
|
+
*/
|
|
870
|
+
/**
|
|
871
|
+
* Any route key walks a dict schema to the same profile node, so the lookup
|
|
872
|
+
* names one that cannot collide with a configured route.
|
|
873
|
+
*/
|
|
874
|
+
const PROBE_ROUTE = "\0probe";
|
|
875
|
+
/**
|
|
876
|
+
* Join declared configurable providers with the currently registered routes.
|
|
877
|
+
* @param registered - live provider routes in registration order.
|
|
878
|
+
* @param directory - declared configurable providers in declaration order.
|
|
879
|
+
* @returns declared rows followed by live routes with no declaration.
|
|
880
|
+
*/
|
|
881
|
+
function joinProviderDirectory(registered, directory) {
|
|
882
|
+
const active = new Set(registered.map((provider) => provider.id));
|
|
883
|
+
const declared = new Set(directory.map((entry) => entry.provider));
|
|
884
|
+
const rows = directory.map((entry) => ({
|
|
885
|
+
provider: entry.provider,
|
|
886
|
+
displayName: entry.displayName,
|
|
887
|
+
settingsNs: entry.settingsNs,
|
|
888
|
+
settingsPath: [...entry.settingsPath],
|
|
889
|
+
active: active.has(entry.provider),
|
|
890
|
+
...entry.declared === void 0 ? {} : { declared: entry.declared }
|
|
891
|
+
}));
|
|
892
|
+
for (const provider of registered) {
|
|
893
|
+
if (declared.has(provider.id)) continue;
|
|
894
|
+
rows.push({
|
|
895
|
+
provider: provider.id,
|
|
896
|
+
displayName: provider.name,
|
|
897
|
+
settingsNs: "",
|
|
898
|
+
settingsPath: [],
|
|
899
|
+
active: true
|
|
900
|
+
});
|
|
901
|
+
}
|
|
902
|
+
return rows;
|
|
903
|
+
}
|
|
904
|
+
/**
|
|
905
|
+
* Derive the conventional credential reference for a provider route: the v1
|
|
906
|
+
* page never asks for an environment-variable name, so a typed key stores
|
|
907
|
+
* under this derived reference and the profile records it as `apiKeyEnv`.
|
|
908
|
+
* @param provider - provider route id (e.g. `anthropic`, `minimax-cn`).
|
|
909
|
+
* @returns the derived reference name (e.g. `MINIMAX_CN_API_KEY`).
|
|
910
|
+
*/
|
|
911
|
+
function deriveKeyRef(provider) {
|
|
912
|
+
return `${provider.toUpperCase().replace(/[^A-Z0-9]+/g, "_")}_API_KEY`;
|
|
913
|
+
}
|
|
914
|
+
/**
|
|
915
|
+
* The wire protocols a hand-declared route may name, read out of the owning
|
|
916
|
+
* namespace's own schema. This stays a schema read rather than a wire field so
|
|
917
|
+
* the choices the page offers cannot drift from the ones the adapter accepts:
|
|
918
|
+
* both come from the same `Config`.
|
|
919
|
+
* @param namespace - the namespace view whose schema declares the profile shape.
|
|
920
|
+
* @param schema - settings schema operations.
|
|
921
|
+
* @returns the protocol identifiers, or an empty list when the schema has none.
|
|
922
|
+
*/
|
|
923
|
+
function protocolChoices(namespace, schema) {
|
|
924
|
+
if (namespace === void 0) return [];
|
|
925
|
+
const list = schema.nodeAtPath(schema.rehydrate(namespace.schema), [
|
|
926
|
+
"providers",
|
|
927
|
+
PROBE_ROUTE,
|
|
928
|
+
"api"
|
|
929
|
+
]);
|
|
930
|
+
if (list?.type !== "union" || list.list === void 0) return [];
|
|
931
|
+
return list.list.map((entry) => entry.value).filter((value) => typeof value === "string");
|
|
932
|
+
}
|
|
933
|
+
/** The credential reference a resolved profile names (its `apiKeyEnv` field). */
|
|
934
|
+
function apiKeyEnvOf(namespace, path, schema) {
|
|
935
|
+
if (namespace === void 0) return void 0;
|
|
936
|
+
const profile = schema.getPath(namespace.value, path);
|
|
937
|
+
if (typeof profile !== "object" || profile === null) return void 0;
|
|
938
|
+
const ref = profile.apiKeyEnv;
|
|
939
|
+
return typeof ref === "string" && ref.length > 0 ? ref : void 0;
|
|
940
|
+
}
|
|
941
|
+
/** The models settings page controller (one per settings surface). */
|
|
942
|
+
var ModelsSettingsStore = class {
|
|
943
|
+
ctx;
|
|
944
|
+
schema;
|
|
945
|
+
describeFace;
|
|
946
|
+
/** The snapshot the section renders from (uSES-safe store). */
|
|
947
|
+
store = (0, _deepseek_ai_dsh_client_store.createSnapshotStore)({
|
|
948
|
+
status: "idle",
|
|
949
|
+
error: null,
|
|
950
|
+
credentialError: null,
|
|
951
|
+
writable: false,
|
|
952
|
+
rows: [],
|
|
953
|
+
namespaces: /* @__PURE__ */ new Map()
|
|
954
|
+
});
|
|
955
|
+
/** Latest load wins; an older response never overwrites a newer one. */
|
|
956
|
+
generation = 0;
|
|
957
|
+
/**
|
|
958
|
+
* @param ctx - the page plugin's context, whose `remote.llm` and
|
|
959
|
+
* `remote.credentials` namespaces carry the directory and credential reads.
|
|
960
|
+
* @param schema - settings-owned schema and immutable path operations.
|
|
961
|
+
* @param describeFace - the shared mirror's describe face (namespace views and writability).
|
|
962
|
+
*/
|
|
963
|
+
constructor(ctx, schema, describeFace) {
|
|
964
|
+
this.ctx = ctx;
|
|
965
|
+
this.schema = schema;
|
|
966
|
+
this.describeFace = describeFace;
|
|
967
|
+
}
|
|
968
|
+
/**
|
|
969
|
+
* Refresh the whole page snapshot: the provider directory and the mirror's
|
|
970
|
+
* settings answer in parallel, then one batched credential describe over
|
|
971
|
+
* every referenced ref. Provider failure or absence of an initial settings
|
|
972
|
+
* answer keeps the last good rows and surfaces an error; a failed settings
|
|
973
|
+
* refresh reuses the mirror's held view.
|
|
974
|
+
* @returns nothing; the snapshot carries the outcome.
|
|
975
|
+
*/
|
|
976
|
+
async load() {
|
|
977
|
+
const generation = ++this.generation;
|
|
978
|
+
this.store.update((s) => {
|
|
979
|
+
s.status = "loading";
|
|
980
|
+
s.error = null;
|
|
981
|
+
});
|
|
982
|
+
const [registered, declared] = await Promise.all([
|
|
983
|
+
this.ctx.remote.llm.listProviders(),
|
|
984
|
+
this.ctx.remote.llm.listConfigurableProviders(),
|
|
985
|
+
this.describeFace.ensure()
|
|
986
|
+
]);
|
|
987
|
+
if (!registered.ok) {
|
|
988
|
+
this.failLoad(generation, registered.error.message);
|
|
989
|
+
return;
|
|
990
|
+
}
|
|
991
|
+
if (!declared.ok) {
|
|
992
|
+
this.failLoad(generation, declared.error.message);
|
|
993
|
+
return;
|
|
994
|
+
}
|
|
995
|
+
const mirrored = this.describeFace.getSnapshot();
|
|
996
|
+
if (mirrored.view === void 0) {
|
|
997
|
+
this.failLoad(generation, mirrored.error ?? "settings are unavailable in this browser");
|
|
998
|
+
return;
|
|
999
|
+
}
|
|
1000
|
+
const providers = joinProviderDirectory(registered.value, declared.value);
|
|
1001
|
+
const writable = mirrored.view.writable;
|
|
1002
|
+
const views = mirrored.view.namespaces;
|
|
1003
|
+
const namespaces = new Map(views.map((view) => [view.ns, view]));
|
|
1004
|
+
const rows = providers.map((entry) => {
|
|
1005
|
+
const namespace = namespaces.get(entry.settingsNs);
|
|
1006
|
+
return {
|
|
1007
|
+
entry,
|
|
1008
|
+
configured: namespace !== void 0 && (entry.settingsPath.length === 0 || this.schema.getPath(namespace.value, entry.settingsPath) !== void 0),
|
|
1009
|
+
removable: namespace !== void 0 && entry.settingsPath.length > 0 && this.schema.hasPath(namespace.user, entry.settingsPath) && !this.schema.hasPath(namespace.base, entry.settingsPath),
|
|
1010
|
+
apiKeyEnv: apiKeyEnvOf(namespace, entry.settingsPath, this.schema),
|
|
1011
|
+
credential: void 0
|
|
1012
|
+
};
|
|
1013
|
+
});
|
|
1014
|
+
const refs = [...new Set(rows.map((row) => row.apiKeyEnv ?? deriveKeyRef(row.entry.provider)))];
|
|
1015
|
+
let credentials = {};
|
|
1016
|
+
let credentialError = null;
|
|
1017
|
+
if (refs.length > 0) {
|
|
1018
|
+
const response = await this.ctx.remote.credentials.describe(refs);
|
|
1019
|
+
if (response.ok) credentials = response.value;
|
|
1020
|
+
else credentialError = response.error.message;
|
|
1021
|
+
}
|
|
1022
|
+
if (generation !== this.generation) return;
|
|
1023
|
+
this.store.update((s) => {
|
|
1024
|
+
s.status = "ready";
|
|
1025
|
+
s.error = null;
|
|
1026
|
+
s.credentialError = credentialError;
|
|
1027
|
+
s.writable = writable;
|
|
1028
|
+
s.rows = rows.map((row) => {
|
|
1029
|
+
const named = row.apiKeyEnv === void 0 ? void 0 : credentials[row.apiKeyEnv];
|
|
1030
|
+
const derived = row.apiKeyEnv !== void 0 ? void 0 : credentials[deriveKeyRef(row.entry.provider)];
|
|
1031
|
+
return {
|
|
1032
|
+
...row,
|
|
1033
|
+
...named === void 0 ? {} : { credential: named },
|
|
1034
|
+
...derived === void 0 ? {} : { derivedCredential: derived }
|
|
1035
|
+
};
|
|
1036
|
+
});
|
|
1037
|
+
s.namespaces = namespaces;
|
|
1038
|
+
});
|
|
1039
|
+
}
|
|
1040
|
+
/** Publish one load's failure text, unless a newer load already took over. */
|
|
1041
|
+
failLoad(generation, message) {
|
|
1042
|
+
if (generation !== this.generation) return;
|
|
1043
|
+
this.store.update((s) => {
|
|
1044
|
+
s.status = "error";
|
|
1045
|
+
s.error = message;
|
|
1046
|
+
});
|
|
1047
|
+
}
|
|
1048
|
+
};
|
|
1049
|
+
/**
|
|
1050
|
+
* Whether a joined row can serve model requests as it stands: the route is
|
|
1051
|
+
* registered with the adapter registry, and whatever credential its resolved
|
|
1052
|
+
* profile names is stored. A profile naming no reference authenticates through
|
|
1053
|
+
* the provider's own path (the Bedrock chain, Vertex ADC, a gateway that needs
|
|
1054
|
+
* nothing), as does a live route with no settings address at all, so neither
|
|
1055
|
+
* owes this page a key.
|
|
1056
|
+
* @param row - one joined provider row.
|
|
1057
|
+
* @returns whether the user already has this provider to talk to.
|
|
1058
|
+
*/
|
|
1059
|
+
function providerUsable(row) {
|
|
1060
|
+
if (!row.entry.active) return false;
|
|
1061
|
+
if (row.apiKeyEnv === void 0) return true;
|
|
1062
|
+
return row.credential?.configured === true;
|
|
1063
|
+
}
|
|
1064
|
+
/**
|
|
1065
|
+
* Project first-run readiness from the provider/settings/credential join used
|
|
1066
|
+
* by the Models page. The step exists to leave the user with a model to talk
|
|
1067
|
+
* to, so ANY usable provider ends it; only when none exists does the official
|
|
1068
|
+
* DeepSeek route — the one route the prompt can offer a key field for — decide
|
|
1069
|
+
* whether prompting can help. A missing official configurable-provider
|
|
1070
|
+
* declaration means the adapter is not repairable by navigating to Models.
|
|
1071
|
+
* @param state - current shared Models join snapshot.
|
|
1072
|
+
* @returns the onboarding state without reading a parallel fact source.
|
|
1073
|
+
*/
|
|
1074
|
+
function onboardingReadiness(state) {
|
|
1075
|
+
if ((state.status === "idle" || state.status === "loading") && state.rows.length === 0) return { kind: "loading" };
|
|
1076
|
+
if (state.status === "error") return {
|
|
1077
|
+
kind: "unavailable",
|
|
1078
|
+
reason: "load-failed"
|
|
1079
|
+
};
|
|
1080
|
+
if (state.rows.some(providerUsable)) return { kind: "provider-ready" };
|
|
1081
|
+
const row = state.rows.find((candidate) => candidate.entry.provider === "deepseek-official" && candidate.entry.settingsNs === "llm-deepseek" && candidate.entry.settingsPath.length === 0);
|
|
1082
|
+
if (row === void 0) return { kind: "adapter-absent" };
|
|
1083
|
+
if (!row.entry.active) return {
|
|
1084
|
+
kind: "unavailable",
|
|
1085
|
+
reason: "provider-inactive"
|
|
1086
|
+
};
|
|
1087
|
+
if (state.credentialError !== null || row.credential === void 0) return {
|
|
1088
|
+
kind: "unavailable",
|
|
1089
|
+
reason: "credentials-unavailable"
|
|
1090
|
+
};
|
|
1091
|
+
if (!state.writable) return {
|
|
1092
|
+
kind: "unavailable",
|
|
1093
|
+
reason: "settings-read-only"
|
|
1094
|
+
};
|
|
1095
|
+
if (!row.credential.writable) return {
|
|
1096
|
+
kind: "unavailable",
|
|
1097
|
+
reason: "credential-read-only"
|
|
1098
|
+
};
|
|
1099
|
+
return { kind: "credential-missing" };
|
|
1100
|
+
}
|
|
1101
|
+
//#endregion
|
|
1069
1102
|
//#region lib/types/client/CustomProviderCard.js
|
|
1070
1103
|
/**
|
|
1071
1104
|
* The card that declares a provider pi-ai does not ship — an OpenAI-compatible
|
|
@@ -1076,7 +1109,7 @@ window.__ModuleLoader__.load({
|
|
|
1076
1109
|
* the provider editor with extra fields: the route id is being *chosen* here,
|
|
1077
1110
|
* and the settings address does not exist until it is. One `settings.mutate`
|
|
1078
1111
|
* sets the whole profile at `providers.<route>`; the key travels separately
|
|
1079
|
-
* through `credentials
|
|
1112
|
+
* through `credentials/set` under the reference the profile records, exactly as
|
|
1080
1113
|
* an existing provider's key does.
|
|
1081
1114
|
*
|
|
1082
1115
|
* The three fields a hand-declared route cannot default — endpoint, protocol,
|
|
@@ -1106,7 +1139,7 @@ window.__ModuleLoader__.load({
|
|
|
1106
1139
|
* @returns the creation card.
|
|
1107
1140
|
*/
|
|
1108
1141
|
function CustomProviderCard(props) {
|
|
1109
|
-
const { taken, protocols,
|
|
1142
|
+
const { taken, protocols, operations, t } = props;
|
|
1110
1143
|
const [openedAt] = (0, react.useState)(() => props.revision);
|
|
1111
1144
|
const [route, setRoute] = (0, react.useState)("");
|
|
1112
1145
|
const [displayName, setDisplayName] = (0, react.useState)("");
|
|
@@ -1147,31 +1180,25 @@ window.__ModuleLoader__.load({
|
|
|
1147
1180
|
models: models.map((model) => isAdaptiveClaude ? withNativeClaudeModel(model) : { ...model }),
|
|
1148
1181
|
...isAdaptiveClaude ? { reasoning: "high" } : {}
|
|
1149
1182
|
};
|
|
1150
|
-
const
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
}],
|
|
1157
|
-
expectedRevision: openedAt
|
|
1158
|
-
});
|
|
1159
|
-
if (!response.result.ok) return response.result.error.message;
|
|
1183
|
+
const written = await operations.writeSettings(NS$1, [{
|
|
1184
|
+
op: "set",
|
|
1185
|
+
path: ["providers", route],
|
|
1186
|
+
value: profile
|
|
1187
|
+
}], openedAt);
|
|
1188
|
+
if (written.kind !== "written") return written.kind === "conflict" ? t("conflict") : written.message;
|
|
1160
1189
|
setCommitted(true);
|
|
1161
1190
|
}
|
|
1162
1191
|
if (isAdaptiveClaude) {
|
|
1163
|
-
const typed = await
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1192
|
+
const typed = await operations.writeSettings(CLAUDE_PROVIDER_SETTINGS_NS, [{
|
|
1193
|
+
op: "set",
|
|
1194
|
+
path: ["providerTypes", route],
|
|
1195
|
+
value: CLAUDE_PROVIDER_TYPE
|
|
1196
|
+
}], void 0);
|
|
1197
|
+
if (typed.kind !== "written") return typed.kind === "conflict" ? t("conflict") : typed.message;
|
|
1168
1198
|
}
|
|
1169
1199
|
if (storesKey) {
|
|
1170
|
-
const stored = await
|
|
1171
|
-
|
|
1172
|
-
value: keyValue
|
|
1173
|
-
});
|
|
1174
|
-
if (!stored.result.ok) return stored.result.error.message;
|
|
1200
|
+
const stored = await operations.storeCredential(keyRef, keyValue);
|
|
1201
|
+
if (stored !== void 0) return stored;
|
|
1175
1202
|
}
|
|
1176
1203
|
};
|
|
1177
1204
|
const create = async () => {
|
|
@@ -1184,8 +1211,6 @@ window.__ModuleLoader__.load({
|
|
|
1184
1211
|
return;
|
|
1185
1212
|
}
|
|
1186
1213
|
props.onClose(true);
|
|
1187
|
-
} catch (error) {
|
|
1188
|
-
setFailure(messageOf(error));
|
|
1189
1214
|
} finally {
|
|
1190
1215
|
setBusy(false);
|
|
1191
1216
|
}
|
|
@@ -1255,7 +1280,7 @@ window.__ModuleLoader__.load({
|
|
|
1255
1280
|
className: ModelsSection_module_css_default["input"],
|
|
1256
1281
|
type: "text",
|
|
1257
1282
|
value: baseURL,
|
|
1258
|
-
placeholder: "
|
|
1283
|
+
placeholder: t("customBaseUrlPlaceholder"),
|
|
1259
1284
|
"aria-label": t("baseUrl"),
|
|
1260
1285
|
disabled: profileDisabled,
|
|
1261
1286
|
onChange: (event) => {
|
|
@@ -1318,7 +1343,7 @@ window.__ModuleLoader__.load({
|
|
|
1318
1343
|
},
|
|
1319
1344
|
probeBlocked: keyFailure === "keyBlank" ? "keyBlankNew" : keyFailure,
|
|
1320
1345
|
thinkingPresets: isAdaptiveClaude,
|
|
1321
|
-
|
|
1346
|
+
operations,
|
|
1322
1347
|
t,
|
|
1323
1348
|
disabled: profileDisabled
|
|
1324
1349
|
}),
|
|
@@ -1334,8 +1359,8 @@ window.__ModuleLoader__.load({
|
|
|
1334
1359
|
t,
|
|
1335
1360
|
busy,
|
|
1336
1361
|
submitDisabled: disabled || !ready,
|
|
1337
|
-
|
|
1338
|
-
|
|
1362
|
+
submitLabelKey: "create",
|
|
1363
|
+
submitBusyLabelKey: "creating",
|
|
1339
1364
|
onCancel: () => {
|
|
1340
1365
|
props.onClose(committed);
|
|
1341
1366
|
},
|
|
@@ -1351,7 +1376,7 @@ window.__ModuleLoader__.load({
|
|
|
1351
1376
|
/**
|
|
1352
1377
|
* One provider's editor card, hand-written per adapter family: the primary
|
|
1353
1378
|
* 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
|
|
1379
|
+
* environment-variable name — a typed key stores through `credentials/set`
|
|
1355
1380
|
* under the profile's reference, deriving `<ROUTE>_API_KEY` when the profile
|
|
1356
1381
|
* has none. The pi-ai profile records that derivation as `apiKeyEnv` only when
|
|
1357
1382
|
* a key is entered; a blank key materializes a reference-free profile for
|
|
@@ -1423,7 +1448,7 @@ window.__ModuleLoader__.load({
|
|
|
1423
1448
|
* @returns the editor card.
|
|
1424
1449
|
*/
|
|
1425
1450
|
function ProviderEditor(props) {
|
|
1426
|
-
const { namespace, schema, settingsPath,
|
|
1451
|
+
const { namespace, schema, settingsPath, operations, t } = props;
|
|
1427
1452
|
const [draft, setDraft] = (0, react.useState)(() => draftAt(schema, namespace, settingsPath));
|
|
1428
1453
|
const [keyDraft, setKeyDraft] = (0, react.useState)("");
|
|
1429
1454
|
const [keyState, setKeyState] = (0, react.useState)(void 0);
|
|
@@ -1449,14 +1474,14 @@ window.__ModuleLoader__.load({
|
|
|
1449
1474
|
(0, react.useEffect)(() => {
|
|
1450
1475
|
let stale = false;
|
|
1451
1476
|
setKeyState(void 0);
|
|
1452
|
-
|
|
1453
|
-
if (stale
|
|
1454
|
-
setKeyState(
|
|
1455
|
-
}
|
|
1477
|
+
operations.describeCredential(keyRef).then((described) => {
|
|
1478
|
+
if (stale) return;
|
|
1479
|
+
setKeyState(described);
|
|
1480
|
+
});
|
|
1456
1481
|
return () => {
|
|
1457
1482
|
stale = true;
|
|
1458
1483
|
};
|
|
1459
|
-
}, [
|
|
1484
|
+
}, [operations, keyRef]);
|
|
1460
1485
|
const stringAt = (source, key) => {
|
|
1461
1486
|
const value = schema.getPath(source, [key]);
|
|
1462
1487
|
return typeof value === "string" && value.trim().length > 0 ? value : void 0;
|
|
@@ -1505,22 +1530,15 @@ window.__ModuleLoader__.load({
|
|
|
1505
1530
|
value: {}
|
|
1506
1531
|
}] : pathOps(settingsPath, committedOriginal, next);
|
|
1507
1532
|
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);
|
|
1533
|
+
const written = await operations.writeSettings(ns, ops, expectedRevision);
|
|
1534
|
+
if (written.kind !== "written") return written.kind === "conflict" ? t("conflict") : written.message;
|
|
1535
|
+
setCommittedOriginal(schema.getPath(written.view.user, settingsPath));
|
|
1536
|
+
setExpectedRevision(written.view.revision);
|
|
1516
1537
|
setDraft(next);
|
|
1517
1538
|
}
|
|
1518
1539
|
if (keyValue.length > 0) {
|
|
1519
|
-
const stored = await
|
|
1520
|
-
|
|
1521
|
-
value: keyValue
|
|
1522
|
-
});
|
|
1523
|
-
if (!stored.result.ok) return stored.result.error.message;
|
|
1540
|
+
const stored = await operations.storeCredential(keyRef, keyValue);
|
|
1541
|
+
if (stored !== void 0) return stored;
|
|
1524
1542
|
}
|
|
1525
1543
|
setKeyDraft("");
|
|
1526
1544
|
};
|
|
@@ -1534,15 +1552,17 @@ window.__ModuleLoader__.load({
|
|
|
1534
1552
|
return;
|
|
1535
1553
|
}
|
|
1536
1554
|
props.onClose(true);
|
|
1537
|
-
} catch (error) {
|
|
1538
|
-
setFailure(messageOf(error));
|
|
1539
1555
|
} finally {
|
|
1540
1556
|
setBusy(false);
|
|
1541
1557
|
}
|
|
1542
1558
|
};
|
|
1543
|
-
if (node === void 0) return (0, react_jsx_runtime.
|
|
1559
|
+
if (node === void 0) return (0, react_jsx_runtime.jsxs)("p", {
|
|
1544
1560
|
className: ModelsSection_module_css_default["error"],
|
|
1545
|
-
children:
|
|
1561
|
+
children: [
|
|
1562
|
+
props.provider,
|
|
1563
|
+
": ",
|
|
1564
|
+
props.t("settingsPathUnresolvable")
|
|
1565
|
+
]
|
|
1546
1566
|
});
|
|
1547
1567
|
const keyLocked = keyState?.writable === false;
|
|
1548
1568
|
/**
|
|
@@ -1681,7 +1701,7 @@ window.__ModuleLoader__.load({
|
|
|
1681
1701
|
probe,
|
|
1682
1702
|
probeBlocked: keyFailure,
|
|
1683
1703
|
thinkingPresets: props.thinkingPresets === true,
|
|
1684
|
-
|
|
1704
|
+
operations
|
|
1685
1705
|
})
|
|
1686
1706
|
]
|
|
1687
1707
|
})]
|
|
@@ -1716,9 +1736,9 @@ window.__ModuleLoader__.load({
|
|
|
1716
1736
|
t,
|
|
1717
1737
|
busy,
|
|
1718
1738
|
submitDisabled: disabled || layout === "unknown" || props.credentialOnly !== true && modelFailure !== void 0 || shownKeyFailure !== void 0 || props.credentialRequired === true && keyValue.length === 0,
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
...props.
|
|
1739
|
+
submitLabelKey: props.submitLabelKey ?? "apply",
|
|
1740
|
+
submitBusyLabelKey: props.submitBusyLabelKey ?? "applying",
|
|
1741
|
+
...props.cancelLabelKey === void 0 ? {} : { cancelLabelKey: props.cancelLabelKey },
|
|
1722
1742
|
onCancel: () => {
|
|
1723
1743
|
props.onClose(false);
|
|
1724
1744
|
},
|
|
@@ -1760,33 +1780,26 @@ window.__ModuleLoader__.load({
|
|
|
1760
1780
|
* and the whole operation safely retryable; both unsets are idempotent.
|
|
1761
1781
|
* The settings removal names the profile rather than rebuilding its whole
|
|
1762
1782
|
* namespace from a partial view.
|
|
1763
|
-
* @param
|
|
1783
|
+
* @param operations - the page's Host operations.
|
|
1764
1784
|
* @param controller - the page store to refresh.
|
|
1765
1785
|
* @param target - the provider's settings address and optional managed credential.
|
|
1766
1786
|
* @returns the failure message, or undefined once the write and reload landed.
|
|
1767
1787
|
*/
|
|
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);
|
|
1788
|
+
async function removeProviderProfile(operations, controller, target) {
|
|
1789
|
+
if (target.credentialRef !== void 0) {
|
|
1790
|
+
const credential = await operations.removeCredential(target.credentialRef);
|
|
1791
|
+
if (credential !== void 0) return credential;
|
|
1789
1792
|
}
|
|
1793
|
+
const written = await operations.writeSettings(target.settingsNs, [{
|
|
1794
|
+
op: "unset",
|
|
1795
|
+
path: [...target.settingsPath]
|
|
1796
|
+
}], void 0);
|
|
1797
|
+
if (written.kind !== "written") return written.message;
|
|
1798
|
+
const typedRemoval = await operations.writeSettings(CLAUDE_PROVIDER_SETTINGS_NS, [{
|
|
1799
|
+
op: "unset",
|
|
1800
|
+
path: ["providerTypes", target.provider]
|
|
1801
|
+
}], void 0);
|
|
1802
|
+
if (typedRemoval.kind !== "written") return typedRemoval.message;
|
|
1790
1803
|
await controller.load();
|
|
1791
1804
|
}
|
|
1792
1805
|
/**
|
|
@@ -1803,6 +1816,16 @@ window.__ModuleLoader__.load({
|
|
|
1803
1816
|
if (row.entry.settingsPath.length > 0) return false;
|
|
1804
1817
|
return row.credential?.configured !== true;
|
|
1805
1818
|
}
|
|
1819
|
+
/**
|
|
1820
|
+
* The provider-card seat's credential fact: the reference this page would use
|
|
1821
|
+
* for the row — the profile's `apiKeyEnv`, or the page's derived
|
|
1822
|
+
* `<ROUTE>_API_KEY` while the profile names none — confirmed configured. The
|
|
1823
|
+
* derived half is what keeps the seat consistent with the editor on the
|
|
1824
|
+
* add-provider draft, whose dormant row names no reference yet.
|
|
1825
|
+
*/
|
|
1826
|
+
function keyConfiguredOf(row) {
|
|
1827
|
+
return row.apiKeyEnv !== void 0 ? row.credential?.configured === true : row.derivedCredential?.configured === true;
|
|
1828
|
+
}
|
|
1806
1829
|
function targetOf(row) {
|
|
1807
1830
|
const managedRef = deriveKeyRef(row.entry.provider);
|
|
1808
1831
|
const credentialRef = row.apiKeyEnv === managedRef && row.credential?.configured === true && row.credential.writable ? managedRef : void 0;
|
|
@@ -1818,7 +1841,6 @@ window.__ModuleLoader__.load({
|
|
|
1818
1841
|
const CLAUDE_DISCOVERY_API = "mofeng-anthropic-models";
|
|
1819
1842
|
const CLAUDE_PROVIDER_SETTINGS_NS = "dsh-claude-provider";
|
|
1820
1843
|
const CLAUDE_PROVIDER_TYPE = "claude-adaptive";
|
|
1821
|
-
const CLAUDE_PROVIDER_DIRECTORY_SENTINEL = "dsh-claude-provider-type";
|
|
1822
1844
|
const CLAUDE_FIVE_EFFORTS = Object.freeze({ low: "low", medium: "medium", high: "high", xhigh: "xhigh", max: "max" });
|
|
1823
1845
|
const CLAUDE_FOUR_EFFORTS = Object.freeze({ low: "low", medium: "medium", high: "high", max: "max" });
|
|
1824
1846
|
const CLAUDE_TOGGLE_EFFORTS = Object.freeze({ off: null, high: "high" });
|
|
@@ -1948,18 +1970,21 @@ window.__ModuleLoader__.load({
|
|
|
1948
1970
|
* @returns the section, or null while the shell has not injected yet.
|
|
1949
1971
|
*/
|
|
1950
1972
|
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
|
-
|
|
1973
|
+
const { controller, useSnapshot, operations, schema, t, renderSlot } = props;
|
|
1974
|
+
if (controller === void 0 || useSnapshot === void 0 || operations === void 0 || schema === void 0 || t === void 0) return null;
|
|
1975
|
+
return (0, react_jsx_runtime.jsx)(Loaded, {
|
|
1976
|
+
injected: {
|
|
1977
|
+
controller,
|
|
1978
|
+
useSnapshot,
|
|
1979
|
+
operations,
|
|
1980
|
+
schema,
|
|
1981
|
+
t
|
|
1982
|
+
},
|
|
1983
|
+
renderSlot
|
|
1984
|
+
});
|
|
1960
1985
|
}
|
|
1961
|
-
function Loaded({ injected }) {
|
|
1962
|
-
const { controller,
|
|
1986
|
+
function Loaded({ injected, renderSlot }) {
|
|
1987
|
+
const { controller, operations, schema, t } = injected;
|
|
1963
1988
|
const state = injected.useSnapshot((snapshot) => snapshot);
|
|
1964
1989
|
const [editing, setEditing] = (0, react.useState)(void 0);
|
|
1965
1990
|
const [adding, setAdding] = (0, react.useState)(false);
|
|
@@ -2001,7 +2026,7 @@ window.__ModuleLoader__.load({
|
|
|
2001
2026
|
if (deleteTarget === void 0 || deleting) return;
|
|
2002
2027
|
setDeleting(true);
|
|
2003
2028
|
setDeleteFailure(void 0);
|
|
2004
|
-
removeProviderProfile(
|
|
2029
|
+
removeProviderProfile(operations, controller, deleteTarget).then((failure) => {
|
|
2005
2030
|
if (failure !== void 0) {
|
|
2006
2031
|
setDeleteFailure(failure);
|
|
2007
2032
|
return;
|
|
@@ -2040,6 +2065,7 @@ window.__ModuleLoader__.load({
|
|
|
2040
2065
|
const addable = state.rows.filter((row) => !row.configured && row.entry.settingsNs !== "");
|
|
2041
2066
|
const addTarget = adding ? editing : void 0;
|
|
2042
2067
|
const addNamespace = addTarget === void 0 ? void 0 : state.namespaces.get(addTarget.settingsNs);
|
|
2068
|
+
const addRow = addTarget === void 0 ? void 0 : state.rows.find((row) => row.entry.provider === addTarget.provider);
|
|
2043
2069
|
const protocols = protocolChoices(state.namespaces.get("llm-pi-ai"), schema);
|
|
2044
2070
|
return (0, react_jsx_runtime.jsxs)("div", {
|
|
2045
2071
|
className: ModelsSection_module_css_default["section"],
|
|
@@ -2069,20 +2095,24 @@ window.__ModuleLoader__.load({
|
|
|
2069
2095
|
const namespace = state.namespaces.get(target.settingsNs);
|
|
2070
2096
|
/* v8 ignore next -- the join marks a row configured only when its namespace resolved */
|
|
2071
2097
|
if (namespace === void 0) return null;
|
|
2072
|
-
if (needsSetup(row, anyUsable) && !dismissedSetup.has(row.entry.provider)) return (0, react_jsx_runtime.
|
|
2098
|
+
if (needsSetup(row, anyUsable) && !dismissedSetup.has(row.entry.provider)) return (0, react_jsx_runtime.jsxs)("li", {
|
|
2073
2099
|
className: ModelsSection_module_css_default["setupCard"],
|
|
2074
|
-
children: renderProviderEditor({
|
|
2100
|
+
children: [renderProviderEditor({
|
|
2075
2101
|
target,
|
|
2076
2102
|
namespace,
|
|
2077
2103
|
schema,
|
|
2078
2104
|
thinkingPresets: isClaudeProvider(row, state),
|
|
2079
|
-
|
|
2105
|
+
operations,
|
|
2080
2106
|
t,
|
|
2081
2107
|
readOnly: !state.writable,
|
|
2082
2108
|
onClose: (changed) => {
|
|
2083
2109
|
closeSetup(changed, target);
|
|
2084
2110
|
}
|
|
2085
|
-
})
|
|
2111
|
+
}), renderSlot("settings.models.provider-card", {
|
|
2112
|
+
provider: row.entry,
|
|
2113
|
+
configured: row.configured,
|
|
2114
|
+
keyConfigured: keyConfiguredOf(row)
|
|
2115
|
+
}, { entryKey: row.entry.settingsNs })]
|
|
2086
2116
|
}, row.entry.provider);
|
|
2087
2117
|
const open = !adding && editing?.provider === row.entry.provider;
|
|
2088
2118
|
const adaptiveClaude = isClaudeProvider(row, state);
|
|
@@ -2090,73 +2120,81 @@ window.__ModuleLoader__.load({
|
|
|
2090
2120
|
const credentialMissing = !credentialConfigured && row.apiKeyEnv !== void 0 && row.credential?.configured === false;
|
|
2091
2121
|
return (0, react_jsx_runtime.jsxs)("li", {
|
|
2092
2122
|
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
|
-
|
|
2123
|
+
children: [
|
|
2124
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
2125
|
+
className: ModelsSection_module_css_default["rowHead"],
|
|
2126
|
+
children: [(0, react_jsx_runtime.jsxs)("span", {
|
|
2127
|
+
className: ModelsSection_module_css_default["rowIdentity"],
|
|
2128
|
+
children: [
|
|
2129
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
2130
|
+
className: ModelsSection_module_css_default["rowName"],
|
|
2131
|
+
children: row.entry.displayName
|
|
2132
|
+
}),
|
|
2133
|
+
row.entry.declared === true ? (0, react_jsx_runtime.jsx)("span", {
|
|
2134
|
+
className: ModelsSection_module_css_default["rowTag"],
|
|
2135
|
+
children: t("customTag")
|
|
2136
|
+
}) : null,
|
|
2137
|
+
adaptiveClaude ? (0, react_jsx_runtime.jsx)("span", {
|
|
2138
|
+
className: ModelsSection_module_css_default["rowTag"],
|
|
2139
|
+
children: t("claudeTypeTag")
|
|
2140
|
+
}) : null,
|
|
2141
|
+
credentialConfigured ? (0, react_jsx_runtime.jsx)("span", {
|
|
2142
|
+
className: `${ModelsSection_module_css_default["credentialDot"]} ${ModelsSection_module_css_default["credentialDotConfigured"]}`,
|
|
2143
|
+
role: "img",
|
|
2144
|
+
"aria-label": t("credentialConfigured"),
|
|
2145
|
+
title: t("credentialConfigured")
|
|
2146
|
+
}) : credentialMissing ? (0, react_jsx_runtime.jsx)("span", {
|
|
2147
|
+
className: `${ModelsSection_module_css_default["credentialDot"]} ${ModelsSection_module_css_default["credentialDotMissing"]}`,
|
|
2148
|
+
role: "img",
|
|
2149
|
+
"aria-label": t("credentialMissing"),
|
|
2150
|
+
title: t("credentialMissing")
|
|
2151
|
+
}) : null
|
|
2152
|
+
]
|
|
2153
|
+
}), (0, react_jsx_runtime.jsxs)("span", {
|
|
2154
|
+
className: ModelsSection_module_css_default["rowActions"],
|
|
2155
|
+
children: [(0, react_jsx_runtime.jsx)("button", {
|
|
2156
|
+
type: "button",
|
|
2157
|
+
className: ModelsSection_module_css_default["secondaryButton"],
|
|
2158
|
+
"aria-label": providerCopy(t("editProvider"), target),
|
|
2159
|
+
onClick: () => {
|
|
2160
|
+
setSavedTarget(void 0);
|
|
2161
|
+
setDeclaringType(void 0);
|
|
2162
|
+
setAdding(false);
|
|
2163
|
+
setEditing(open ? void 0 : target);
|
|
2164
|
+
},
|
|
2165
|
+
children: t("edit")
|
|
2166
|
+
}), row.removable ? (0, react_jsx_runtime.jsx)("button", {
|
|
2167
|
+
type: "button",
|
|
2168
|
+
className: ModelsSection_module_css_default["dangerButton"],
|
|
2169
|
+
"aria-label": providerCopy(t("removeProvider"), target),
|
|
2170
|
+
disabled: !state.writable,
|
|
2171
|
+
onClick: () => {
|
|
2172
|
+
setSavedTarget(void 0);
|
|
2173
|
+
setDeleteFailure(void 0);
|
|
2174
|
+
setDeleteTarget(target);
|
|
2175
|
+
},
|
|
2176
|
+
children: t("remove")
|
|
2177
|
+
}) : null]
|
|
2178
|
+
})]
|
|
2179
|
+
}),
|
|
2180
|
+
renderSlot("settings.models.provider-card", {
|
|
2181
|
+
provider: row.entry,
|
|
2182
|
+
configured: row.configured,
|
|
2183
|
+
keyConfigured: keyConfiguredOf(row)
|
|
2184
|
+
}, { entryKey: row.entry.settingsNs }),
|
|
2185
|
+
open ? renderProviderEditor({
|
|
2186
|
+
target,
|
|
2187
|
+
namespace,
|
|
2188
|
+
schema,
|
|
2189
|
+
thinkingPresets: isClaudeProvider(row, state),
|
|
2190
|
+
operations,
|
|
2191
|
+
t,
|
|
2192
|
+
readOnly: !state.writable,
|
|
2193
|
+
onClose: (changed) => {
|
|
2194
|
+
closeEditor(changed, target);
|
|
2195
|
+
}
|
|
2196
|
+
}) : null
|
|
2197
|
+
]
|
|
2160
2198
|
}, row.entry.provider);
|
|
2161
2199
|
})
|
|
2162
2200
|
}),
|
|
@@ -2164,40 +2202,48 @@ window.__ModuleLoader__.load({
|
|
|
2164
2202
|
className: ModelsSection_module_css_default["addBlock"],
|
|
2165
2203
|
children: addTarget !== void 0 && addNamespace !== void 0 ? (0, react_jsx_runtime.jsxs)("div", {
|
|
2166
2204
|
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
|
-
|
|
2205
|
+
children: [
|
|
2206
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
2207
|
+
className: ModelsSection_module_css_default["field"],
|
|
2208
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
2209
|
+
className: ModelsSection_module_css_default["fieldLabel"],
|
|
2210
|
+
children: t("provider")
|
|
2211
|
+
}), (0, react_jsx_runtime.jsx)("select", {
|
|
2212
|
+
className: `${ModelsSection_module_css_default["input"]} ${ModelsSection_module_css_default["selectInput"]}`,
|
|
2213
|
+
value: addTarget.provider,
|
|
2214
|
+
"aria-label": t("provider"),
|
|
2215
|
+
onChange: (event) => {
|
|
2216
|
+
const row = addable.find((candidate) => candidate.entry.provider === event.target.value);
|
|
2217
|
+
/* v8 ignore next -- the select only lists addable rows */
|
|
2218
|
+
if (row === void 0) return;
|
|
2219
|
+
setEditing(targetOf(row));
|
|
2220
|
+
},
|
|
2221
|
+
children: addable.map((row) => (0, react_jsx_runtime.jsx)("option", {
|
|
2222
|
+
value: row.entry.provider,
|
|
2223
|
+
children: row.entry.displayName
|
|
2224
|
+
}, row.entry.provider))
|
|
2225
|
+
})]
|
|
2226
|
+
}),
|
|
2227
|
+
(0, react_jsx_runtime.jsx)(ProviderEditor, {
|
|
2228
|
+
provider: addTarget.provider,
|
|
2229
|
+
displayName: addTarget.displayName,
|
|
2230
|
+
hideTitle: true,
|
|
2231
|
+
namespace: addNamespace,
|
|
2232
|
+
schema,
|
|
2233
|
+
settingsPath: addTarget.settingsPath,
|
|
2234
|
+
operations,
|
|
2235
|
+
t,
|
|
2236
|
+
readOnly: !state.writable,
|
|
2237
|
+
onClose: (changed) => {
|
|
2238
|
+
closeEditor(changed, addTarget);
|
|
2239
|
+
}
|
|
2240
|
+
}, addTarget.provider),
|
|
2241
|
+
addRow === void 0 ? null : renderSlot("settings.models.provider-card", {
|
|
2242
|
+
provider: addRow.entry,
|
|
2243
|
+
configured: addRow.configured,
|
|
2244
|
+
keyConfigured: keyConfiguredOf(addRow)
|
|
2245
|
+
}, { entryKey: addRow.entry.settingsNs })
|
|
2246
|
+
]
|
|
2201
2247
|
}) : declaringType !== void 0 ? (0, react_jsx_runtime.jsx)("div", {
|
|
2202
2248
|
className: ModelsSection_module_css_default["addCard"],
|
|
2203
2249
|
children: (0, react_jsx_runtime.jsx)(CustomProviderCard, {
|
|
@@ -2206,7 +2252,7 @@ window.__ModuleLoader__.load({
|
|
|
2206
2252
|
providerType: declaringType,
|
|
2207
2253
|
/* v8 ignore next -- the card only opens from a button disabled without this namespace */
|
|
2208
2254
|
revision: state.namespaces.get("llm-pi-ai")?.revision ?? 0,
|
|
2209
|
-
|
|
2255
|
+
operations,
|
|
2210
2256
|
t,
|
|
2211
2257
|
readOnly: !state.writable,
|
|
2212
2258
|
onClose: (changed) => {
|
|
@@ -2255,6 +2301,7 @@ window.__ModuleLoader__.load({
|
|
|
2255
2301
|
})]
|
|
2256
2302
|
})
|
|
2257
2303
|
}),
|
|
2304
|
+
renderSlot("settings.models.footer", {}),
|
|
2258
2305
|
(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
2259
2306
|
open: deleteTarget !== void 0,
|
|
2260
2307
|
onClose: closeDelete,
|
|
@@ -2380,7 +2427,7 @@ window.__ModuleLoader__.load({
|
|
|
2380
2427
|
* @returns the onboarding modal or null when onboarding needs no intervention.
|
|
2381
2428
|
*/
|
|
2382
2429
|
function DeepSeekOnboardingDialog(props) {
|
|
2383
|
-
const { complete, controller, useModels,
|
|
2430
|
+
const { complete, controller, useModels, operations, schema, t } = props;
|
|
2384
2431
|
const state = useModels((snapshot) => snapshot);
|
|
2385
2432
|
const readiness = onboardingReadiness(state);
|
|
2386
2433
|
(0, react.useEffect)(() => {
|
|
@@ -2422,16 +2469,16 @@ window.__ModuleLoader__.load({
|
|
|
2422
2469
|
namespace,
|
|
2423
2470
|
schema,
|
|
2424
2471
|
settingsPath: row.entry.settingsPath,
|
|
2425
|
-
|
|
2472
|
+
operations,
|
|
2426
2473
|
t,
|
|
2427
2474
|
readOnly: false,
|
|
2428
2475
|
hideTitle: true,
|
|
2429
2476
|
credentialOnly: true,
|
|
2430
2477
|
credentialRequired: true,
|
|
2431
2478
|
autoFocusCredential: true,
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2479
|
+
cancelLabelKey: "onboardingLater",
|
|
2480
|
+
submitLabelKey: "onboardingSave",
|
|
2481
|
+
submitBusyLabelKey: "onboardingSaving",
|
|
2435
2482
|
onClose: finishCredential
|
|
2436
2483
|
})
|
|
2437
2484
|
})]
|
|
@@ -2521,19 +2568,6 @@ window.__ModuleLoader__.load({
|
|
|
2521
2568
|
* again. The acknowledgement is compared for exact equality.
|
|
2522
2569
|
*/
|
|
2523
2570
|
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
2571
|
//#endregion
|
|
2538
2572
|
//#region lib/types/client/welcome-store.js
|
|
2539
2573
|
/**
|
|
@@ -2560,7 +2594,7 @@ window.__ModuleLoader__.load({
|
|
|
2560
2594
|
var WelcomeNoticeStore = class {
|
|
2561
2595
|
scope;
|
|
2562
2596
|
/** uSES-safe state source shared by the registered welcome step. */
|
|
2563
|
-
store = (0,
|
|
2597
|
+
store = (0, _deepseek_ai_dsh_client_store.createSnapshotStore)({
|
|
2564
2598
|
status: "idle",
|
|
2565
2599
|
acknowledged: false,
|
|
2566
2600
|
error: null
|
|
@@ -2661,6 +2695,61 @@ window.__ModuleLoader__.load({
|
|
|
2661
2695
|
}
|
|
2662
2696
|
};
|
|
2663
2697
|
//#endregion
|
|
2698
|
+
//#region lib/types/client/operations.js
|
|
2699
|
+
/**
|
|
2700
|
+
* The Host reads and writes the Models cards perform, as callbacks built in the
|
|
2701
|
+
* plugin body. Cards receive these instead of a context: the outcomes name what
|
|
2702
|
+
* a card renders — a stored view, a stale revision, a refusal message — so the
|
|
2703
|
+
* failure codes and Remote namespaces stay in the apply world.
|
|
2704
|
+
*/
|
|
2705
|
+
/**
|
|
2706
|
+
* Bind the page's Host operations to the plugin's own Remote namespaces.
|
|
2707
|
+
* @param ctx - the page plugin's context, which declares `remote.credentials`,
|
|
2708
|
+
* `remote.llm`, and `remote.settings` in its own `inject`.
|
|
2709
|
+
* @returns the callbacks the section and its cards are injected with.
|
|
2710
|
+
*/
|
|
2711
|
+
function createModelsOperations(ctx) {
|
|
2712
|
+
return {
|
|
2713
|
+
describeCredential: async (ref) => {
|
|
2714
|
+
const response = await ctx.remote.credentials.describe([ref]);
|
|
2715
|
+
return response.ok ? response.value[ref] : void 0;
|
|
2716
|
+
},
|
|
2717
|
+
storeCredential: async (ref, value) => {
|
|
2718
|
+
const response = await ctx.remote.credentials.set(ref, value);
|
|
2719
|
+
return response.ok ? void 0 : response.error.message;
|
|
2720
|
+
},
|
|
2721
|
+
removeCredential: async (ref) => {
|
|
2722
|
+
const response = await ctx.remote.credentials.unset(ref);
|
|
2723
|
+
return response.ok ? void 0 : response.error.message;
|
|
2724
|
+
},
|
|
2725
|
+
writeSettings: async (ns, ops, expectedRevision) => {
|
|
2726
|
+
const response = await ctx.remote.settings.mutate(ns, ops, expectedRevision);
|
|
2727
|
+
if (response.ok) return {
|
|
2728
|
+
kind: "written",
|
|
2729
|
+
view: response.value
|
|
2730
|
+
};
|
|
2731
|
+
const { code, message } = response.error;
|
|
2732
|
+
return code === "settings/conflict" ? {
|
|
2733
|
+
kind: "conflict",
|
|
2734
|
+
message
|
|
2735
|
+
} : {
|
|
2736
|
+
kind: "refused",
|
|
2737
|
+
message
|
|
2738
|
+
};
|
|
2739
|
+
},
|
|
2740
|
+
discoverModels: async (settingsNs, request) => {
|
|
2741
|
+
const response = await ctx.remote.llm.discoverModels(settingsNs, request);
|
|
2742
|
+
return response.ok ? {
|
|
2743
|
+
kind: "found",
|
|
2744
|
+
models: response.value
|
|
2745
|
+
} : {
|
|
2746
|
+
kind: "refused",
|
|
2747
|
+
message: response.error.message
|
|
2748
|
+
};
|
|
2749
|
+
}
|
|
2750
|
+
};
|
|
2751
|
+
}
|
|
2752
|
+
//#endregion
|
|
2664
2753
|
//#region lib/types/client/schema-operations.js
|
|
2665
2754
|
/**
|
|
2666
2755
|
* Hide the Cordis service identity behind bound schema callbacks.
|
|
@@ -2779,11 +2868,13 @@ window.__ModuleLoader__.load({
|
|
|
2779
2868
|
customApiUnset: "Not selected",
|
|
2780
2869
|
customNeedsBaseUrl: "A custom provider needs a base URL.",
|
|
2781
2870
|
customNeedsModels: "A custom provider needs at least one model.",
|
|
2871
|
+
customBaseUrlPlaceholder: "https://gateway.example/v1",
|
|
2872
|
+
settingsPathUnresolvable: "unresolvable settings path",
|
|
2782
2873
|
create: "Create provider",
|
|
2783
2874
|
creating: "Creating…",
|
|
2784
|
-
welcomeTitle:
|
|
2785
|
-
welcomeBody:
|
|
2786
|
-
welcomeContinue:
|
|
2875
|
+
welcomeTitle: "Internal Testing Notice",
|
|
2876
|
+
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.",
|
|
2877
|
+
welcomeContinue: "Continue",
|
|
2787
2878
|
welcomeError: "The acknowledgement could not be saved. Please try again.",
|
|
2788
2879
|
onboardingTitle: "Add an API key to get started",
|
|
2789
2880
|
onboardingDescription: "Configure the official DeepSeek provider to start building.",
|
|
@@ -2890,11 +2981,13 @@ window.__ModuleLoader__.load({
|
|
|
2890
2981
|
customApiUnset: "未选择",
|
|
2891
2982
|
customNeedsBaseUrl: "自定义提供方需要填写 API 地址。",
|
|
2892
2983
|
customNeedsModels: "自定义提供方至少需要一个模型。",
|
|
2984
|
+
customBaseUrlPlaceholder: "https://gateway.example/v1",
|
|
2985
|
+
settingsPathUnresolvable: "无法解析设置路径",
|
|
2893
2986
|
create: "创建提供方",
|
|
2894
2987
|
creating: "创建中…",
|
|
2895
|
-
welcomeTitle:
|
|
2896
|
-
welcomeBody:
|
|
2897
|
-
welcomeContinue:
|
|
2988
|
+
welcomeTitle: "内测声明",
|
|
2989
|
+
welcomeBody: "DeepSeek Harness 目前的 0.1 版本仍处在面向 Harness 开发者进行测试的阶段,还有许多地方需要持续改进和打磨,希望听取广大开发者的反馈建议。预计 DeepSeek Harness 的核心插件以及基础 API 都会在接下来的一段时间内快速迭代、持续演化。\n\n我们期待与全球开发者一起,在开源、开放、可复用、可组合的基础设施之上,共同探索智能上限。欢迎全球 Harness 开发者加入 DSH 插件生态。",
|
|
2990
|
+
welcomeContinue: "继续",
|
|
2898
2991
|
welcomeError: "暂时无法保存确认状态,请重试。",
|
|
2899
2992
|
onboardingTitle: "添加一个 API Key 开始使用",
|
|
2900
2993
|
onboardingDescription: "配置 DeepSeek 官方模型,即可开始使用。",
|
|
@@ -2924,8 +3017,10 @@ window.__ModuleLoader__.load({
|
|
|
2924
3017
|
const inject = [
|
|
2925
3018
|
"slots",
|
|
2926
3019
|
"locale",
|
|
2927
|
-
"connection",
|
|
2928
3020
|
"remote",
|
|
3021
|
+
"remote.credentials",
|
|
3022
|
+
"remote.llm",
|
|
3023
|
+
"remote.settings",
|
|
2929
3024
|
"settingsScope",
|
|
2930
3025
|
"settingsSchema"
|
|
2931
3026
|
];
|
|
@@ -2940,21 +3035,21 @@ window.__ModuleLoader__.load({
|
|
|
2940
3035
|
zh,
|
|
2941
3036
|
en
|
|
2942
3037
|
}), "ui-settings-models: copy dictionaries");
|
|
2943
|
-
const connection = ctx.get("connection");
|
|
2944
3038
|
const schema = createSettingsSchemaOperations(ctx.settingsSchema);
|
|
2945
|
-
const
|
|
3039
|
+
const operations = createModelsOperations(ctx);
|
|
3040
|
+
const controller = new ModelsSettingsStore(ctx, schema, ctx.settingsScope.describe());
|
|
2946
3041
|
const t = ctx.locale.bind(NS);
|
|
2947
3042
|
const injected = () => ({
|
|
2948
3043
|
controller,
|
|
2949
3044
|
hooks: { snapshot: controller.store },
|
|
2950
|
-
|
|
3045
|
+
operations,
|
|
2951
3046
|
schema,
|
|
2952
3047
|
t
|
|
2953
3048
|
});
|
|
2954
3049
|
const deepSeekOnboardingInjected = () => ({
|
|
2955
3050
|
controller,
|
|
2956
3051
|
hooks: { models: controller.store },
|
|
2957
|
-
|
|
3052
|
+
operations,
|
|
2958
3053
|
schema,
|
|
2959
3054
|
t
|
|
2960
3055
|
});
|
|
@@ -2975,6 +3070,7 @@ window.__ModuleLoader__.load({
|
|
|
2975
3070
|
ctx.remote.$on("settings/document-updated", () => {
|
|
2976
3071
|
refreshModels();
|
|
2977
3072
|
}),
|
|
3073
|
+
ctx.remote.$on("credentials/reference-updated", refreshModels),
|
|
2978
3074
|
ctx.remote.$on("credentials/updated", refreshModels),
|
|
2979
3075
|
ctx.remote.$on("llm/adapters-updated", refreshModels),
|
|
2980
3076
|
ctx.on("connection/reset", refreshModels)
|
|
@@ -2989,7 +3085,17 @@ window.__ModuleLoader__.load({
|
|
|
2989
3085
|
id: "models",
|
|
2990
3086
|
order: 10,
|
|
2991
3087
|
label: () => t("nav"),
|
|
2992
|
-
inject: injected
|
|
3088
|
+
inject: injected,
|
|
3089
|
+
children: {
|
|
3090
|
+
"settings.models.provider-card": {
|
|
3091
|
+
kind: "keyed",
|
|
3092
|
+
scope: "root"
|
|
3093
|
+
},
|
|
3094
|
+
"settings.models.footer": {
|
|
3095
|
+
kind: "list",
|
|
3096
|
+
scope: "root"
|
|
3097
|
+
}
|
|
3098
|
+
}
|
|
2993
3099
|
}, ModelsSection));
|
|
2994
3100
|
ctx.slots.inject("settings.onboarding", () => ctx.slots.register({
|
|
2995
3101
|
name: "settings.onboarding",
|