dsh-model-extension 0.2.0 → 0.3.2-alpha.4
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/LICENSE +21 -21
- package/README.md +77 -68
- package/assets/model-extension-mockup.html +105 -105
- package/cordis.patch.yml +3 -3
- package/lib/client.js +381 -278
- package/lib/client.js.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/package.json +9 -10
package/lib/client.js
CHANGED
|
@@ -3,7 +3,7 @@ window.__ModuleLoader__.load({
|
|
|
3
3
|
factory: (require) => {
|
|
4
4
|
var module = { exports: {} };
|
|
5
5
|
var exports = module.exports;
|
|
6
|
-
var __extCss = ".Qji2zG_section{max-width:720px;color:var(--dsw-alias-label-primary);flex-direction:column;gap:12px;display:flex}.Qji2zG_title{color:var(--dsw-alias-label-primary);margin:0;font-size:16px;font-weight:500;line-height:24px}.Qji2zG_intro{color:var(--dsw-alias-label-tertiary);margin:0;font-size:14px;line-height:22px}.Qji2zG_notice{color:var(--dsw-alias-state-warn-label);margin:0;font-size:12px;line-height:18px}.Qji2zG_savedNotice{color:var(--dsw-alias-state-success-primary);margin:0;font-size:12px;line-height:18px}.Qji2zG_rows{flex-direction:column;gap:8px;margin:12px 0 0;padding:0;list-style:none;display:flex}.Qji2zG_rowCard{border:1px solid var(--dsw-alias-border-l2);border-radius:12px;flex-direction:column;gap:12px;padding:12px 14px;display:flex}.Qji2zG_rowHead{align-items:center;gap:10px;display:flex}.Qji2zG_rowIdentity{align-items:center;gap:6px;min-width:0;display:inline-flex}.Qji2zG_rowName{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:500;line-height:22px}.Qji2zG_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}.Qji2zG_credentialDot{box-sizing:border-box;border-radius:50%;flex:none;width:8px;height:8px;display:inline-block}.Qji2zG_credentialDotConfigured{background:var(--dsw-alias-state-success-primary)}.Qji2zG_credentialDotMissing{background:var(--dsw-alias-state-error-primary)}.Qji2zG_rowActions{align-items:center;gap:4px;margin-left:auto;display:inline-flex}.Qji2zG_primaryButton,.Qji2zG_secondaryButton,.Qji2zG_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}.Qji2zG_primaryButton{background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-foreground)}.Qji2zG_primaryButton:hover:not(:disabled){background:var(--dsw-alias-button-primary-hover)}.Qji2zG_secondaryButton,.Qji2zG_addButton{border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary);background:0 0}.Qji2zG_secondaryButton:hover:not(:disabled),.Qji2zG_addButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.Qji2zG_secondaryButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-solid)}.Qji2zG_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}.Qji2zG_dangerButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger)}.Qji2zG_rowActions .Qji2zG_secondaryButton,.Qji2zG_rowActions .Qji2zG_dangerButton{border-radius:14px;height:28px;padding:0 10px;font-size:12px;line-height:18px}.Qji2zG_primaryButton:disabled,.Qji2zG_secondaryButton:disabled,.Qji2zG_dangerButton:disabled,.Qji2zG_addButton:disabled,.Qji2zG_linkButton:disabled,.Qji2zG_addModelButton:disabled{opacity:.4;cursor:default}.Qji2zG_primaryButton:focus-visible,.Qji2zG_secondaryButton:focus-visible,.Qji2zG_dangerButton:focus-visible,.Qji2zG_addButton:focus-visible,.Qji2zG_linkButton:focus-visible,.Qji2zG_addModelButton:focus-visible,.Qji2zG_iconButton:focus-visible,.Qji2zG_customizedSummary:focus-visible{box-shadow:0 0 0 2px var(--dsw-alias-border-l3);outline:none}.Qji2zG_editor{background:var(--dsw-alias-bg-module-platform);border-radius:12px;flex-direction:column;gap:14px;padding:14px 16px;display:flex}.Qji2zG_editorHeader{align-items:baseline;gap:8px;display:flex}.Qji2zG_editorTitle{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:500;line-height:22px}.Qji2zG_editorRoute{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}.Qji2zG_field{flex-direction:column;gap:6px;display:flex}.Qji2zG_fieldLabel{color:var(--dsw-alias-label-secondary);align-items:center;gap:10px;font-size:12px;font-weight:500;line-height:18px;display:inline-flex}.Qji2zG_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}.Qji2zG_linkButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-secondary)}.Qji2zG_advancedHint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}.Qji2zG_editorActions{justify-content:flex-end;gap:8px;display:flex}.Qji2zG_addBlock{flex-direction:column;gap:12px;display:flex}.Qji2zG_addActions{flex-wrap:wrap;gap:10px;display:flex}.Qji2zG_addButton{border:1px dashed var(--dsw-alias-border-l3);border-radius:12px;flex:1 1 0;gap:6px;min-width:180px;height:44px}.Qji2zG_addCard,.Qji2zG_setupCard{background:var(--dsw-alias-bg-module-platform);border-radius:12px;flex-direction:column;gap:14px;padding:14px 16px;list-style:none;display:flex}.Qji2zG_addCard .Qji2zG_editor,.Qji2zG_setupCard .Qji2zG_editor{background:0 0;padding:0}.Qji2zG_customized{border-top:1px solid var(--dsw-alias-border-l2);padding-top:10px}.Qji2zG_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}.Qji2zG_customizedSummary::-webkit-details-marker{display:none}.Qji2zG_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)}.Qji2zG_customized[open]>.Qji2zG_customizedSummary:before{transform:rotate(45deg)translate(-1px,-1px)}.Qji2zG_customizedSummary:hover{color:var(--dsw-alias-label-primary)}.Qji2zG_customizedBody{flex-direction:column;gap:12px;padding-top:12px;display:flex}.Qji2zG_modelCatalog{border-top:1px solid var(--dsw-alias-border-l2);flex-direction:column;gap:10px;padding-top:12px;display:flex}.Qji2zG_modelCatalogHeading{flex-direction:column;gap:2px;display:flex}.Qji2zG_modelCatalogTitle{color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:500;line-height:18px}.Qji2zG_modelCatalogMeta,.Qji2zG_modelEmpty{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}.Qji2zG_modelList{flex-direction:column;gap:8px;display:flex}.Qji2zG_modelListHead{justify-content:space-between;align-items:flex-start;gap:12px;display:flex}.Qji2zG_modelEntry{border:1px solid var(--dsw-alias-border-l2);border-radius:8px;padding:6px}.Qji2zG_modelRow{grid-template-columns:minmax(0,1.4fr) minmax(0,1fr) auto auto;align-items:center;gap:6px;display:grid}.Qji2zG_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}.Qji2zG_iconButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.Qji2zG_iconButton:disabled{cursor:default;opacity:.4}.Qji2zG_iconButtonDanger:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger);color:var(--dsw-alias-state-error-primary)}.Qji2zG_modelAdvanced{grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:8px;padding:8px 4px 2px;display:grid}.Qji2zG_modelField{flex-direction:column;gap:4px;display:flex}.Qji2zG_modelFieldLabel{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}.Qji2zG_modelEmpty{border:1px dashed var(--dsw-alias-border-l3);text-align:center;border-radius:8px;padding:12px}.Qji2zG_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}.Qji2zG_addModelButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.Qji2zG_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.Qji2zG_input{cursor:pointer;max-width:240px}.Qji2zG_input:focus{border-color:var(--dsw-alias-brand-primary);outline:none}.Qji2zG_input::placeholder{color:var(--dsw-alias-label-dimmed)}.Qji2zG_input:disabled{opacity:.6;cursor:default}.Qji2zG_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}.Qji2zG_error{color:var(--dsw-alias-state-error-primary);margin:0;font-size:12px;line-height:18px}.Qji2zG_deleteDialog{width:min(480px,100%)}.Qji2zG_deleteConfirm:not(:disabled){border-color:var(--dsw-alias-state-error-primary);color:var(--dsw-alias-state-error-primary)}.Qji2zG_deleteConfirm:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger)}.Qji2zG_hiddenLabel{clip:rect(0 0 0 0);white-space:nowrap;width:1px;height:1px;position:absolute;overflow:hidden}@media (prefers-reduced-motion:reduce){.Qji2zG_customizedSummary:before{transition:none}}.Qji2zG_fetchDialog{--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);max-width:520px}.Qji2zG_candidateActions{justify-content:flex-end;margin-bottom:6px;display:flex}.Qji2zG_candidateList{flex-direction:column;gap:2px;max-height:320px;margin:0;padding:0;list-style:none;display:flex;overflow-y:auto}.Qji2zG_candidate{border-radius:6px}.Qji2zG_candidateLabel{cursor:pointer;align-items:center;gap:8px;padding:6px 8px;display:flex}.Qji2zG_candidateId{font-family:var(--ds-font-family-code);overflow-wrap:anywhere;flex:auto;font-size:13px}.TST7FW_section{max-width:720px;color:var(--dsw-alias-label-primary);flex-direction:column;gap:12px;display:flex}.TST7FW_title{color:var(--dsw-alias-label-primary);margin:0;font-size:16px;font-weight:500;line-height:24px}.TST7FW_intro{color:var(--dsw-alias-label-tertiary);margin:0;font-size:14px;line-height:22px}.TST7FW_notice{color:var(--dsw-alias-state-warn-label);margin:0;font-size:12px;line-height:18px}.TST7FW_savedNotice{color:var(--dsw-alias-state-success-primary);margin:0;font-size:12px;line-height:18px}.TST7FW_rows{flex-direction:column;gap:8px;margin:12px 0 0;padding:0;list-style:none;display:flex}.TST7FW_rowCard{border:1px solid var(--dsw-alias-border-l2);border-radius:12px;flex-direction:column;gap:12px;padding:12px 14px;display:flex}.TST7FW_rowHead{align-items:center;gap:10px;display:flex}.TST7FW_rowIdentity{align-items:center;gap:6px;min-width:0;display:inline-flex}.TST7FW_rowName{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:500;line-height:22px}.TST7FW_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}.TST7FW_credentialDot{box-sizing:border-box;border-radius:50%;flex:none;width:8px;height:8px;display:inline-block}.TST7FW_credentialDotConfigured{background:var(--dsw-alias-state-success-primary)}.TST7FW_credentialDotMissing{background:var(--dsw-alias-state-error-primary)}.TST7FW_rowActions{align-items:center;gap:4px;margin-left:auto;display:inline-flex}.TST7FW_primaryButton,.TST7FW_secondaryButton,.TST7FW_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}.TST7FW_primaryButton{background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-foreground)}.TST7FW_primaryButton:hover:not(:disabled){background:var(--dsw-alias-button-primary-hover)}.TST7FW_secondaryButton,.TST7FW_addButton{border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary);background:0 0}.TST7FW_secondaryButton:hover:not(:disabled),.TST7FW_addButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.TST7FW_secondaryButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-solid)}.TST7FW_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}.TST7FW_dangerButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger)}.TST7FW_rowActions .TST7FW_secondaryButton,.TST7FW_rowActions .TST7FW_dangerButton{border-radius:14px;height:28px;padding:0 10px;font-size:12px;line-height:18px}.TST7FW_primaryButton:disabled,.TST7FW_secondaryButton:disabled,.TST7FW_dangerButton:disabled,.TST7FW_addButton:disabled,.TST7FW_linkButton:disabled,.TST7FW_addModelButton:disabled{opacity:.4;cursor:default}.TST7FW_primaryButton:focus-visible,.TST7FW_secondaryButton:focus-visible,.TST7FW_dangerButton:focus-visible,.TST7FW_addButton:focus-visible,.TST7FW_linkButton:focus-visible,.TST7FW_addModelButton:focus-visible,.TST7FW_iconButton:focus-visible,.TST7FW_customizedSummary:focus-visible{box-shadow:0 0 0 2px var(--dsw-alias-border-l3);outline:none}.TST7FW_editor{background:var(--dsw-alias-bg-module-platform);border-radius:12px;flex-direction:column;gap:14px;padding:14px 16px;display:flex}.TST7FW_editorHeader{align-items:baseline;gap:8px;display:flex}.TST7FW_editorTitle{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:500;line-height:22px}.TST7FW_editorRoute{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}.TST7FW_field{flex-direction:column;gap:6px;display:flex}.TST7FW_fieldLabel{color:var(--dsw-alias-label-secondary);align-items:center;gap:10px;font-size:12px;font-weight:500;line-height:18px;display:inline-flex}.TST7FW_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}.TST7FW_linkButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-secondary)}.TST7FW_advancedHint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}.TST7FW_editorActions{justify-content:flex-end;gap:8px;display:flex}.TST7FW_addBlock{flex-direction:column;gap:12px;display:flex}.TST7FW_addActions{flex-wrap:wrap;gap:10px;display:flex}.TST7FW_addButton{border:1px dashed var(--dsw-alias-border-l3);border-radius:12px;flex:1 1 0;gap:6px;min-width:180px;height:44px}.TST7FW_addCard,.TST7FW_setupCard{background:var(--dsw-alias-bg-module-platform);border-radius:12px;flex-direction:column;gap:14px;padding:14px 16px;list-style:none;display:flex}.TST7FW_addCard .TST7FW_editor,.TST7FW_setupCard .TST7FW_editor{background:0 0;padding:0}.TST7FW_customized{border-top:1px solid var(--dsw-alias-border-l2);padding-top:10px}.TST7FW_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}.TST7FW_customizedSummary::-webkit-details-marker{display:none}.TST7FW_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)}.TST7FW_customized[open]>.TST7FW_customizedSummary:before{transform:rotate(45deg)translate(-1px,-1px)}.TST7FW_customizedSummary:hover{color:var(--dsw-alias-label-primary)}.TST7FW_customizedBody{flex-direction:column;gap:12px;padding-top:12px;display:flex}.TST7FW_modelCatalog{border-top:1px solid var(--dsw-alias-border-l2);flex-direction:column;gap:10px;padding-top:12px;display:flex}.TST7FW_modelCatalogHeading{flex-direction:column;gap:2px;display:flex}.TST7FW_modelCatalogTitle{color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:500;line-height:18px}.TST7FW_modelCatalogMeta,.TST7FW_modelEmpty{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}.TST7FW_modelList{flex-direction:column;gap:8px;display:flex}.TST7FW_modelListHead{justify-content:space-between;align-items:flex-start;gap:12px;display:flex}.TST7FW_modelEntry{border:1px solid var(--dsw-alias-border-l2);border-radius:8px;padding:6px}.TST7FW_modelRow{grid-template-columns:minmax(0,1.4fr) minmax(0,1fr) auto auto;align-items:center;gap:6px;display:grid}.TST7FW_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}.TST7FW_iconButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.TST7FW_iconButton:disabled{cursor:default;opacity:.4}.TST7FW_iconButtonDanger:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger);color:var(--dsw-alias-state-error-primary)}.TST7FW_modelAdvanced{grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:8px;padding:8px 4px 2px;display:grid}.TST7FW_modelExtensionFields{box-sizing:border-box;width:100%;display:block}.TST7FW_modelField{flex-direction:column;gap:4px;display:flex}.TST7FW_modelFieldLabel{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}.TST7FW_modelEmpty{border:1px dashed var(--dsw-alias-border-l3);text-align:center;border-radius:8px;padding:12px}.TST7FW_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}.TST7FW_addModelButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.TST7FW_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.TST7FW_input{cursor:pointer;max-width:240px}.TST7FW_input:focus{border-color:var(--dsw-alias-brand-primary);outline:none}.TST7FW_input::placeholder{color:var(--dsw-alias-label-dimmed)}.TST7FW_input:disabled{opacity:.6;cursor:default}.TST7FW_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}.TST7FW_error{color:var(--dsw-alias-state-error-primary);margin:0;font-size:12px;line-height:18px}.TST7FW_deleteDialog{width:min(480px,100%)}.TST7FW_deleteConfirm:not(:disabled){border-color:var(--dsw-alias-state-error-primary);color:var(--dsw-alias-state-error-primary)}.TST7FW_deleteConfirm:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger)}.TST7FW_hiddenLabel{clip:rect(0 0 0 0);white-space:nowrap;width:1px;height:1px;position:absolute;overflow:hidden}@media (prefers-reduced-motion:reduce){.TST7FW_customizedSummary:before{transition:none}}.TST7FW_fetchDialog{--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);max-width:520px}.TST7FW_candidateActions{justify-content:flex-end;margin-bottom:6px;display:flex}.TST7FW_candidateList{flex-direction:column;gap:2px;max-height:320px;margin:0;padding:0;list-style:none;display:flex;overflow-y:auto}.TST7FW_candidate{border-radius:6px}.TST7FW_candidateLabel{cursor:pointer;align-items:center;gap:8px;padding:6px 8px;display:flex}.TST7FW_candidateId{font-family:var(--ds-font-family-code);overflow-wrap:anywhere;flex:auto;font-size:13px}\n";
|
|
6
|
+
var __extCss = ".Qji2zG_section{max-width:720px;color:var(--dsw-alias-label-primary);flex-direction:column;gap:12px;display:flex}.Qji2zG_title{color:var(--dsw-alias-label-primary);margin:0;font-size:16px;font-weight:500;line-height:24px}.Qji2zG_intro{color:var(--dsw-alias-label-tertiary);margin:0;font-size:14px;line-height:22px}.Qji2zG_notice{color:var(--dsw-alias-state-warn-label);margin:0;font-size:12px;line-height:18px}.Qji2zG_savedNotice{color:var(--dsw-alias-state-success-primary);margin:0;font-size:12px;line-height:18px}.Qji2zG_rows{flex-direction:column;gap:8px;margin:12px 0 0;padding:0;list-style:none;display:flex}.Qji2zG_rowCard{border:.5px solid var(--dsw-alias-border-l4);border-radius:16px;flex-direction:column;gap:12px;padding:12px 14px;display:flex}.Qji2zG_rowHead{align-items:center;gap:10px;display:flex}.Qji2zG_rowIdentity{align-items:center;gap:6px;min-width:0;display:inline-flex}.Qji2zG_rowName{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:500;line-height:22px}.Qji2zG_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}.Qji2zG_credentialDot{box-sizing:border-box;corner-shape:round;border-radius:50%;flex:none;width:8px;height:8px;display:inline-block}.Qji2zG_credentialDotConfigured{background:var(--dsw-alias-state-success-primary)}.Qji2zG_credentialDotMissing{background:var(--dsw-alias-state-error-primary)}.Qji2zG_rowActions{align-items:center;gap:4px;margin-left:auto;display:inline-flex}.Qji2zG_primaryButton,.Qji2zG_secondaryButton,.Qji2zG_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}.Qji2zG_primaryButton{background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-foreground)}.Qji2zG_primaryButton:hover:not(:disabled){background:var(--dsw-alias-button-primary-hover)}.Qji2zG_secondaryButton,.Qji2zG_addButton{border:.5px solid var(--dsw-alias-border-l3);color:var(--dsw-alias-label-primary);background:0 0}.Qji2zG_secondaryButton:hover:not(:disabled),.Qji2zG_addButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.Qji2zG_secondaryButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-solid)}.Qji2zG_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}.Qji2zG_dangerButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger)}.Qji2zG_rowActions .Qji2zG_secondaryButton,.Qji2zG_rowActions .Qji2zG_dangerButton{border-radius:14px;height:28px;padding:0 10px;font-size:12px;line-height:18px}.Qji2zG_primaryButton:disabled,.Qji2zG_secondaryButton:disabled,.Qji2zG_dangerButton:disabled,.Qji2zG_addButton:disabled,.Qji2zG_linkButton:disabled,.Qji2zG_addModelButton:disabled{opacity:.4;cursor:default}.Qji2zG_primaryButton:focus-visible,.Qji2zG_secondaryButton:focus-visible,.Qji2zG_dangerButton:focus-visible,.Qji2zG_addButton:focus-visible,.Qji2zG_linkButton:focus-visible,.Qji2zG_addModelButton:focus-visible,.Qji2zG_iconButton:focus-visible,.Qji2zG_customizedSummary:focus-visible{box-shadow:0 0 0 2px var(--dsw-alias-border-l3);outline:none}.Qji2zG_editor{background:var(--dsw-alias-bg-module-platform);border-radius:12px;flex-direction:column;gap:14px;padding:14px 16px;display:flex}.Qji2zG_editorHeader{align-items:baseline;gap:8px;display:flex}.Qji2zG_editorTitle{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:500;line-height:22px}.Qji2zG_editorRoute{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}.Qji2zG_field{flex-direction:column;gap:6px;display:flex}.Qji2zG_fieldLabel{color:var(--dsw-alias-label-secondary);align-items:center;gap:10px;font-size:12px;font-weight:500;line-height:18px;display:inline-flex}.Qji2zG_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}.Qji2zG_linkButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-secondary)}.Qji2zG_advancedHint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}.Qji2zG_editorActions{justify-content:flex-end;gap:8px;display:flex}.Qji2zG_addBlock{flex-direction:column;gap:12px;display:flex}.Qji2zG_addActions{flex-wrap:wrap;gap:10px;display:flex}.Qji2zG_addButton{border:1px dashed var(--dsw-alias-border-l3);border-radius:16px;flex:1 1 0;gap:6px;min-width:180px;height:44px}.Qji2zG_addCard,.Qji2zG_setupCard{background:var(--dsw-alias-bg-module-platform);border-radius:12px;flex-direction:column;gap:14px;padding:14px 16px;list-style:none;display:flex}.Qji2zG_addCard .Qji2zG_editor,.Qji2zG_setupCard .Qji2zG_editor{background:0 0;padding:0}.Qji2zG_customized{border-top:.5px solid var(--dsw-alias-border-l2);padding-top:10px}.Qji2zG_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}.Qji2zG_customizedSummary::-webkit-details-marker{display:none}.Qji2zG_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)}.Qji2zG_customized[open]>.Qji2zG_customizedSummary:before{transform:rotate(45deg)translate(-1px,-1px)}.Qji2zG_customizedSummary:hover{color:var(--dsw-alias-label-primary)}.Qji2zG_customizedBody{flex-direction:column;gap:12px;padding-top:12px;display:flex}.Qji2zG_modelCatalog{border-top:.5px solid var(--dsw-alias-border-l2);flex-direction:column;gap:10px;padding-top:12px;display:flex}.Qji2zG_modelCatalogHeading{flex-direction:column;gap:2px;display:flex}.Qji2zG_modelCatalogTitle{color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:500;line-height:18px}.Qji2zG_modelCatalogMeta,.Qji2zG_modelEmpty{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}.Qji2zG_modelList{flex-direction:column;gap:8px;display:flex}.Qji2zG_modelListHead{justify-content:space-between;align-items:flex-start;gap:12px;display:flex}.Qji2zG_modelEntry{border:.5px solid var(--dsw-alias-border-l4);border-radius:10px;padding:6px}.Qji2zG_modelRow{grid-template-columns:minmax(0,1.4fr) minmax(0,1fr) auto auto;align-items:center;gap:6px;display:grid}.Qji2zG_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}.Qji2zG_iconButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.Qji2zG_iconButton:disabled{cursor:default;opacity:.4}.Qji2zG_iconButtonDanger:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger);color:var(--dsw-alias-state-error-primary)}.Qji2zG_modelAdvanced{grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:8px;padding:8px 4px 2px;display:grid}.Qji2zG_modelField{flex-direction:column;gap:4px;display:flex}.Qji2zG_modelFieldLabel{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}.Qji2zG_modelEmpty{border:1px dashed var(--dsw-alias-border-l3);text-align:center;border-radius:8px;padding:12px}.Qji2zG_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}.Qji2zG_addModelButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.Qji2zG_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.Qji2zG_input{cursor:pointer;max-width:240px}.Qji2zG_input:focus{border-color:var(--dsw-alias-brand-primary);outline:none}.Qji2zG_input::placeholder{color:var(--dsw-alias-label-dimmed)}.Qji2zG_input:disabled{opacity:.6;cursor:default}.Qji2zG_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}.Qji2zG_error{color:var(--dsw-alias-state-error-primary);margin:0;font-size:12px;line-height:18px}.Qji2zG_deleteDialog{width:min(480px,100%)}.Qji2zG_deleteConfirm:not(:disabled){border-color:var(--dsw-alias-state-error-primary);color:var(--dsw-alias-state-error-primary)}.Qji2zG_deleteConfirm:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger)}.Qji2zG_hiddenLabel{clip:rect(0 0 0 0);white-space:nowrap;width:1px;height:1px;position:absolute;overflow:hidden}@media (prefers-reduced-motion:reduce){.Qji2zG_customizedSummary:before,.Qji2zG_switchThumb{transition:none}}.Qji2zG_fetchDialog{--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);max-width:520px}.Qji2zG_candidateToolbar{align-items:center;gap:8px;margin-bottom:6px;display:flex}.Qji2zG_candidateSearch{flex:240px;min-width:0}.Qji2zG_candidateList{flex-direction:column;gap:2px;max-height:320px;margin:0;padding:0;list-style:none;display:flex;overflow-y:auto}.Qji2zG_candidate{border-radius:6px}.Qji2zG_candidateLabel{cursor:pointer;align-items:center;gap:8px;padding:6px 8px;display:flex}.Qji2zG_candidateId{font-family:var(--ds-font-family-code);overflow-wrap:anywhere;flex:auto;font-size:13px}.Qji2zG_candidateEmpty{color:var(--dsw-alias-label-secondary);text-align:center;margin:24px 0;font-size:13px;line-height:20px}.TST7FW_section{max-width:720px;color:var(--dsw-alias-label-primary);flex-direction:column;gap:12px;display:flex}.TST7FW_title{color:var(--dsw-alias-label-primary);margin:0;font-size:16px;font-weight:500;line-height:24px}.TST7FW_intro{color:var(--dsw-alias-label-tertiary);margin:0;font-size:14px;line-height:22px}.TST7FW_notice{color:var(--dsw-alias-state-warn-label);margin:0;font-size:12px;line-height:18px}.TST7FW_savedNotice{color:var(--dsw-alias-state-success-primary);margin:0;font-size:12px;line-height:18px}.TST7FW_rows{flex-direction:column;gap:8px;margin:12px 0 0;padding:0;list-style:none;display:flex}.TST7FW_rowCard{border:.5px solid var(--dsw-alias-border-l4);border-radius:16px;flex-direction:column;gap:12px;padding:12px 14px;display:flex}.TST7FW_rowHead{align-items:center;gap:10px;display:flex}.TST7FW_rowIdentity{align-items:center;gap:6px;min-width:0;display:inline-flex}.TST7FW_rowName{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:500;line-height:22px}.TST7FW_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}.TST7FW_credentialDot{box-sizing:border-box;corner-shape:round;border-radius:50%;flex:none;width:8px;height:8px;display:inline-block}.TST7FW_credentialDotConfigured{background:var(--dsw-alias-state-success-primary)}.TST7FW_credentialDotMissing{background:var(--dsw-alias-state-error-primary)}.TST7FW_rowActions{align-items:center;gap:4px;margin-left:auto;display:inline-flex}.TST7FW_primaryButton,.TST7FW_secondaryButton,.TST7FW_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}.TST7FW_primaryButton{background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-foreground)}.TST7FW_primaryButton:hover:not(:disabled){background:var(--dsw-alias-button-primary-hover)}.TST7FW_secondaryButton,.TST7FW_addButton{border:.5px solid var(--dsw-alias-border-l3);color:var(--dsw-alias-label-primary);background:0 0}.TST7FW_secondaryButton:hover:not(:disabled),.TST7FW_addButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.TST7FW_secondaryButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-solid)}.TST7FW_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}.TST7FW_dangerButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger)}.TST7FW_rowActions .TST7FW_secondaryButton,.TST7FW_rowActions .TST7FW_dangerButton{border-radius:14px;height:28px;padding:0 10px;font-size:12px;line-height:18px}.TST7FW_primaryButton:disabled,.TST7FW_secondaryButton:disabled,.TST7FW_dangerButton:disabled,.TST7FW_addButton:disabled,.TST7FW_linkButton:disabled,.TST7FW_addModelButton:disabled{opacity:.4;cursor:default}.TST7FW_primaryButton:focus-visible,.TST7FW_secondaryButton:focus-visible,.TST7FW_dangerButton:focus-visible,.TST7FW_addButton:focus-visible,.TST7FW_linkButton:focus-visible,.TST7FW_addModelButton:focus-visible,.TST7FW_iconButton:focus-visible,.TST7FW_customizedSummary:focus-visible{box-shadow:0 0 0 2px var(--dsw-alias-border-l3);outline:none}.TST7FW_editor{background:var(--dsw-alias-bg-module-platform);border-radius:12px;flex-direction:column;gap:14px;padding:14px 16px;display:flex}.TST7FW_editorHeader{align-items:baseline;gap:8px;display:flex}.TST7FW_editorTitle{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:500;line-height:22px}.TST7FW_editorRoute{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}.TST7FW_field{flex-direction:column;gap:6px;display:flex}.TST7FW_fieldLabel{color:var(--dsw-alias-label-secondary);align-items:center;gap:10px;font-size:12px;font-weight:500;line-height:18px;display:inline-flex}.TST7FW_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}.TST7FW_linkButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-secondary)}.TST7FW_advancedHint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}.TST7FW_editorActions{justify-content:flex-end;gap:8px;display:flex}.TST7FW_addBlock{flex-direction:column;gap:12px;display:flex}.TST7FW_addActions{flex-wrap:wrap;gap:10px;display:flex}.TST7FW_addButton{border:1px dashed var(--dsw-alias-border-l3);border-radius:16px;flex:1 1 0;gap:6px;min-width:180px;height:44px}.TST7FW_addCard,.TST7FW_setupCard{background:var(--dsw-alias-bg-module-platform);border-radius:12px;flex-direction:column;gap:14px;padding:14px 16px;list-style:none;display:flex}.TST7FW_addCard .TST7FW_editor,.TST7FW_setupCard .TST7FW_editor{background:0 0;padding:0}.TST7FW_customized{border-top:.5px solid var(--dsw-alias-border-l2);padding-top:10px}.TST7FW_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}.TST7FW_customizedSummary::-webkit-details-marker{display:none}.TST7FW_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)}.TST7FW_customized[open]>.TST7FW_customizedSummary:before{transform:rotate(45deg)translate(-1px,-1px)}.TST7FW_customizedSummary:hover{color:var(--dsw-alias-label-primary)}.TST7FW_customizedBody{flex-direction:column;gap:12px;padding-top:12px;display:flex}.TST7FW_modelCatalog{border-top:.5px solid var(--dsw-alias-border-l2);flex-direction:column;gap:10px;padding-top:12px;display:flex}.TST7FW_modelCatalogHeading{flex-direction:column;gap:2px;display:flex}.TST7FW_modelCatalogTitle{color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:500;line-height:18px}.TST7FW_modelCatalogMeta,.TST7FW_modelEmpty{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}.TST7FW_modelList{flex-direction:column;gap:8px;display:flex}.TST7FW_modelListHead{justify-content:space-between;align-items:flex-start;gap:12px;display:flex}.TST7FW_modelEntry{border:.5px solid var(--dsw-alias-border-l4);border-radius:10px;padding:6px}.TST7FW_modelRow{grid-template-columns:minmax(0,1.4fr) minmax(0,1fr) auto auto;align-items:center;gap:6px;display:grid}.TST7FW_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}.TST7FW_iconButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.TST7FW_iconButton:disabled{cursor:default;opacity:.4}.TST7FW_iconButtonDanger:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger);color:var(--dsw-alias-state-error-primary)}.TST7FW_modelAdvanced{grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:8px;padding:8px 4px 2px;display:grid}.TST7FW_modelExtensionFields{box-sizing:border-box;width:100%;display:block}.TST7FW_modelField{flex-direction:column;gap:4px;display:flex}.TST7FW_modelFieldLabel{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}.TST7FW_modelEmpty{border:1px dashed var(--dsw-alias-border-l3);text-align:center;border-radius:8px;padding:12px}.TST7FW_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}.TST7FW_addModelButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.TST7FW_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.TST7FW_input{cursor:pointer;max-width:240px}.TST7FW_input:focus{border-color:var(--dsw-alias-brand-primary);outline:none}.TST7FW_input::placeholder{color:var(--dsw-alias-label-dimmed)}.TST7FW_input:disabled{opacity:.6;cursor:default}.TST7FW_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}.TST7FW_error{color:var(--dsw-alias-state-error-primary);margin:0;font-size:12px;line-height:18px}.TST7FW_deleteDialog{width:min(480px,100%)}.TST7FW_deleteConfirm:not(:disabled){border-color:var(--dsw-alias-state-error-primary);color:var(--dsw-alias-state-error-primary)}.TST7FW_deleteConfirm:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger)}.TST7FW_hiddenLabel{clip:rect(0 0 0 0);white-space:nowrap;width:1px;height:1px;position:absolute;overflow:hidden}@media (prefers-reduced-motion:reduce){.TST7FW_customizedSummary:before,.TST7FW_switchThumb{transition:none}}.TST7FW_fetchDialog{--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);max-width:520px}.TST7FW_candidateToolbar{align-items:center;gap:8px;margin-bottom:6px;display:flex}.TST7FW_candidateSearch{flex:240px;min-width:0}.TST7FW_candidateList{flex-direction:column;gap:2px;max-height:320px;margin:0;padding:0;list-style:none;display:flex;overflow-y:auto}.TST7FW_candidate{border-radius:6px}.TST7FW_candidateLabel{cursor:pointer;align-items:center;gap:8px;padding:6px 8px;display:flex}.TST7FW_candidateId{font-family:var(--ds-font-family-code);overflow-wrap:anywhere;flex:auto;font-size:13px}.TST7FW_candidateEmpty{color:var(--dsw-alias-label-secondary);text-align:center;margin:24px 0;font-size:13px;line-height:20px}\n";
|
|
7
7
|
if (typeof document !== 'undefined' && document.querySelector('style[data-plugin-css="dsh-model-extension"]') === null) {
|
|
8
8
|
var __tag = document.createElement('style');
|
|
9
9
|
__tag.dataset.plugin = "dsh-model-extension";
|
|
@@ -15,7 +15,7 @@ if (typeof document !== 'undefined' && document.querySelector('style[data-plugin
|
|
|
15
15
|
let react = require("react");
|
|
16
16
|
let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
17
17
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
18
|
-
let
|
|
18
|
+
let _deepseek_ai_dsh_client_store = require("@deepseek-ai/dsh-client-store");
|
|
19
19
|
//#region
|
|
20
20
|
/**
|
|
21
21
|
* Browser-side judgement of a typed API key.
|
|
@@ -71,10 +71,12 @@ if (typeof document !== 'undefined' && document.querySelector('style[data-plugin
|
|
|
71
71
|
"addModelButton": "Qji2zG_addModelButton",
|
|
72
72
|
"advancedHint": "Qji2zG_advancedHint",
|
|
73
73
|
"candidate": "Qji2zG_candidate",
|
|
74
|
-
"
|
|
74
|
+
"candidateEmpty": "Qji2zG_candidateEmpty",
|
|
75
75
|
"candidateId": "Qji2zG_candidateId",
|
|
76
76
|
"candidateLabel": "Qji2zG_candidateLabel",
|
|
77
77
|
"candidateList": "Qji2zG_candidateList",
|
|
78
|
+
"candidateSearch": "Qji2zG_candidateSearch",
|
|
79
|
+
"candidateToolbar": "Qji2zG_candidateToolbar",
|
|
78
80
|
"credentialDot": "Qji2zG_credentialDot",
|
|
79
81
|
"credentialDotConfigured": "Qji2zG_credentialDotConfigured",
|
|
80
82
|
"credentialDotMissing": "Qji2zG_credentialDotMissing",
|
|
@@ -125,6 +127,7 @@ if (typeof document !== 'undefined' && document.querySelector('style[data-plugin
|
|
|
125
127
|
"section": "Qji2zG_section",
|
|
126
128
|
"selectInput": "Qji2zG_selectInput",
|
|
127
129
|
"setupCard": "Qji2zG_setupCard",
|
|
130
|
+
"switchThumb": "Qji2zG_switchThumb",
|
|
128
131
|
"title": "Qji2zG_title"
|
|
129
132
|
};
|
|
130
133
|
//#endregion
|
|
@@ -143,13 +146,13 @@ if (typeof document !== 'undefined' && document.querySelector('style[data-plugin
|
|
|
143
146
|
className: ModelsSection_module_default["secondaryButton"],
|
|
144
147
|
disabled: props.busy,
|
|
145
148
|
onClick: props.onCancel,
|
|
146
|
-
children: t(props.
|
|
149
|
+
children: t(props.cancelLabelKey ?? "cancel")
|
|
147
150
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
148
151
|
type: "button",
|
|
149
152
|
className: ModelsSection_module_default["primaryButton"],
|
|
150
153
|
disabled: props.submitDisabled,
|
|
151
154
|
onClick: props.onSubmit,
|
|
152
|
-
children: props.busy ? t(props.
|
|
155
|
+
children: props.busy ? t(props.submitBusyLabelKey) : t(props.submitLabelKey)
|
|
153
156
|
})]
|
|
154
157
|
});
|
|
155
158
|
}
|
|
@@ -441,168 +444,6 @@ if (typeof document !== 'undefined' && document.querySelector('style[data-plugin
|
|
|
441
444
|
});
|
|
442
445
|
}
|
|
443
446
|
//#endregion
|
|
444
|
-
//#region
|
|
445
|
-
/**
|
|
446
|
-
* Any route key walks a dict schema to the same profile node, so the lookup
|
|
447
|
-
* names one that cannot collide with a configured route.
|
|
448
|
-
*/
|
|
449
|
-
const PROBE_ROUTE = "\0probe";
|
|
450
|
-
/**
|
|
451
|
-
* Human text for a rejected wire call. A transport failure rejects with an
|
|
452
|
-
* Error; a host or a runtime can reject with anything, and the page still has
|
|
453
|
-
* to say something.
|
|
454
|
-
* @param error - the rejection value.
|
|
455
|
-
* @returns the message to show.
|
|
456
|
-
*/
|
|
457
|
-
function messageOf(error) {
|
|
458
|
-
return error instanceof Error ? error.message : String(error);
|
|
459
|
-
}
|
|
460
|
-
/**
|
|
461
|
-
* Derive the conventional credential reference for a provider route: the v1
|
|
462
|
-
* page never asks for an environment-variable name, so a typed key stores
|
|
463
|
-
* under this derived reference and the profile records it as `apiKeyEnv`.
|
|
464
|
-
* @param provider - provider route id (e.g. `anthropic`, `minimax-cn`).
|
|
465
|
-
* @returns the derived reference name (e.g. `MINIMAX_CN_API_KEY`).
|
|
466
|
-
*/
|
|
467
|
-
function deriveKeyRef(provider) {
|
|
468
|
-
return `${provider.toUpperCase().replace(/[^A-Z0-9]+/g, "_")}_API_KEY`;
|
|
469
|
-
}
|
|
470
|
-
/**
|
|
471
|
-
* The wire protocols a hand-declared route may name, read out of the owning
|
|
472
|
-
* namespace's own schema. This stays a schema read rather than a wire field so
|
|
473
|
-
* the choices the page offers cannot drift from the ones the adapter accepts:
|
|
474
|
-
* both come from the same `Config`.
|
|
475
|
-
* @param namespace - the namespace view whose schema declares the profile shape.
|
|
476
|
-
* @param schema - settings schema operations.
|
|
477
|
-
* @returns the protocol identifiers, or an empty list when the schema has none.
|
|
478
|
-
*/
|
|
479
|
-
function protocolChoices(namespace, schema) {
|
|
480
|
-
if (namespace === void 0) return [];
|
|
481
|
-
const list = schema.nodeAtPath(schema.rehydrate(namespace.schema), [
|
|
482
|
-
"providers",
|
|
483
|
-
PROBE_ROUTE,
|
|
484
|
-
"api"
|
|
485
|
-
]);
|
|
486
|
-
if (list?.type !== "union" || list.list === void 0) return [];
|
|
487
|
-
return list.list.map((entry) => entry.value).filter((value) => typeof value === "string");
|
|
488
|
-
}
|
|
489
|
-
/** The credential reference a resolved profile names (its `apiKeyEnv` field). */
|
|
490
|
-
function apiKeyEnvOf(namespace, path, schema) {
|
|
491
|
-
if (namespace === void 0) return void 0;
|
|
492
|
-
const profile = schema.getPath(namespace.value, path);
|
|
493
|
-
if (typeof profile !== "object" || profile === null) return void 0;
|
|
494
|
-
const ref = profile.apiKeyEnv;
|
|
495
|
-
return typeof ref === "string" && ref.length > 0 ? ref : void 0;
|
|
496
|
-
}
|
|
497
|
-
/** The models settings page controller (one per settings surface). */
|
|
498
|
-
var ModelsSettingsStore = class {
|
|
499
|
-
api;
|
|
500
|
-
schema;
|
|
501
|
-
describeFace;
|
|
502
|
-
/** The snapshot the section renders from (uSES-safe store). */
|
|
503
|
-
store = (0, _deepseek_ai_dsh_client_runtime_client.createSnapshotStore)({
|
|
504
|
-
status: "idle",
|
|
505
|
-
error: null,
|
|
506
|
-
credentialError: null,
|
|
507
|
-
writable: false,
|
|
508
|
-
rows: [],
|
|
509
|
-
namespaces: /* @__PURE__ */ new Map()
|
|
510
|
-
});
|
|
511
|
-
/** Latest load wins; an older response never overwrites a newer one. */
|
|
512
|
-
generation = 0;
|
|
513
|
-
/**
|
|
514
|
-
* @param api - the wire face (credentials/llm domains, and settings writes).
|
|
515
|
-
* @param describeFace - the shared mirror's describe face (namespace views and writability).
|
|
516
|
-
*/
|
|
517
|
-
constructor(api, schema, describeFace) {
|
|
518
|
-
this.api = api;
|
|
519
|
-
this.schema = schema;
|
|
520
|
-
this.describeFace = describeFace;
|
|
521
|
-
}
|
|
522
|
-
/**
|
|
523
|
-
* Refresh the whole page snapshot: the provider directory and the mirror's
|
|
524
|
-
* settings answer in parallel, then one batched credential describe over
|
|
525
|
-
* every referenced ref. Provider failure or absence of an initial settings
|
|
526
|
-
* answer keeps the last good rows and surfaces an error; a failed settings
|
|
527
|
-
* refresh reuses the mirror's held view.
|
|
528
|
-
* @returns nothing; the snapshot carries the outcome.
|
|
529
|
-
*/
|
|
530
|
-
async load() {
|
|
531
|
-
const generation = ++this.generation;
|
|
532
|
-
this.store.update((s) => {
|
|
533
|
-
s.status = "loading";
|
|
534
|
-
s.error = null;
|
|
535
|
-
});
|
|
536
|
-
let providers;
|
|
537
|
-
let writable;
|
|
538
|
-
let views;
|
|
539
|
-
try {
|
|
540
|
-
const [providersResponse] = await Promise.all([this.api.llm.providers({}), this.describeFace.ensure()]);
|
|
541
|
-
if (!providersResponse.result.ok) throw new Error(providersResponse.result.error.message);
|
|
542
|
-
const mirrored = this.describeFace.getSnapshot();
|
|
543
|
-
if (mirrored.view === void 0) throw new Error(mirrored.error ?? "settings are unavailable in this browser");
|
|
544
|
-
providers = providersResponse.result.value.providers;
|
|
545
|
-
writable = mirrored.view.writable;
|
|
546
|
-
views = mirrored.view.namespaces;
|
|
547
|
-
} catch (error) {
|
|
548
|
-
if (generation !== this.generation) return;
|
|
549
|
-
this.store.update((s) => {
|
|
550
|
-
s.status = "error";
|
|
551
|
-
s.error = error instanceof Error ? error.message : String(error);
|
|
552
|
-
});
|
|
553
|
-
return;
|
|
554
|
-
}
|
|
555
|
-
const namespaces = new Map(views.map((view) => [view.ns, view]));
|
|
556
|
-
const rows = providers.map((entry) => {
|
|
557
|
-
const namespace = namespaces.get(entry.settingsNs);
|
|
558
|
-
return {
|
|
559
|
-
entry,
|
|
560
|
-
configured: namespace !== void 0 && (entry.settingsPath.length === 0 || this.schema.getPath(namespace.value, entry.settingsPath) !== void 0),
|
|
561
|
-
removable: namespace !== void 0 && entry.settingsPath.length > 0 && this.schema.hasPath(namespace.user, entry.settingsPath) && !this.schema.hasPath(namespace.base, entry.settingsPath),
|
|
562
|
-
apiKeyEnv: apiKeyEnvOf(namespace, entry.settingsPath, this.schema),
|
|
563
|
-
credential: void 0
|
|
564
|
-
};
|
|
565
|
-
});
|
|
566
|
-
const refs = [...new Set(rows.flatMap((row) => row.apiKeyEnv === void 0 ? [] : [row.apiKeyEnv]))];
|
|
567
|
-
let credentials = {};
|
|
568
|
-
let credentialError = null;
|
|
569
|
-
if (refs.length > 0) try {
|
|
570
|
-
const response = await this.api.credentials.describe({ refs });
|
|
571
|
-
if (response.result.ok) credentials = response.result.value.credentials;
|
|
572
|
-
else credentialError = response.result.error.message;
|
|
573
|
-
} catch (error) {
|
|
574
|
-
credentialError = messageOf(error);
|
|
575
|
-
}
|
|
576
|
-
if (generation !== this.generation) return;
|
|
577
|
-
this.store.update((s) => {
|
|
578
|
-
s.status = "ready";
|
|
579
|
-
s.error = null;
|
|
580
|
-
s.credentialError = credentialError;
|
|
581
|
-
s.writable = writable;
|
|
582
|
-
s.rows = rows.map((row) => ({
|
|
583
|
-
...row,
|
|
584
|
-
...row.apiKeyEnv !== void 0 && credentials[row.apiKeyEnv] !== void 0 ? { credential: credentials[row.apiKeyEnv] } : {}
|
|
585
|
-
}));
|
|
586
|
-
s.namespaces = namespaces;
|
|
587
|
-
});
|
|
588
|
-
}
|
|
589
|
-
};
|
|
590
|
-
/**
|
|
591
|
-
* Whether a joined row can serve model requests as it stands: the route is
|
|
592
|
-
* registered with the adapter registry, and whatever credential its resolved
|
|
593
|
-
* profile names is stored. A profile naming no reference authenticates through
|
|
594
|
-
* the provider's own path (the Bedrock chain, Vertex ADC, a gateway that needs
|
|
595
|
-
* nothing), as does a live route with no settings address at all, so neither
|
|
596
|
-
* owes this page a key.
|
|
597
|
-
* @param row - one joined provider row.
|
|
598
|
-
* @returns whether the user already has this provider to talk to.
|
|
599
|
-
*/
|
|
600
|
-
function providerUsable(row) {
|
|
601
|
-
if (!row.entry.active) return false;
|
|
602
|
-
if (row.apiKeyEnv === void 0) return true;
|
|
603
|
-
return row.credential?.configured === true;
|
|
604
|
-
}
|
|
605
|
-
//#endregion
|
|
606
447
|
//#region src/client/ModelsSection.ext.module.css
|
|
607
448
|
var ModelsSection_ext_module_default = {
|
|
608
449
|
"addActions": "TST7FW_addActions",
|
|
@@ -612,10 +453,12 @@ if (typeof document !== 'undefined' && document.querySelector('style[data-plugin
|
|
|
612
453
|
"addModelButton": "TST7FW_addModelButton",
|
|
613
454
|
"advancedHint": "TST7FW_advancedHint",
|
|
614
455
|
"candidate": "TST7FW_candidate",
|
|
615
|
-
"
|
|
456
|
+
"candidateEmpty": "TST7FW_candidateEmpty",
|
|
616
457
|
"candidateId": "TST7FW_candidateId",
|
|
617
458
|
"candidateLabel": "TST7FW_candidateLabel",
|
|
618
459
|
"candidateList": "TST7FW_candidateList",
|
|
460
|
+
"candidateSearch": "TST7FW_candidateSearch",
|
|
461
|
+
"candidateToolbar": "TST7FW_candidateToolbar",
|
|
619
462
|
"credentialDot": "TST7FW_credentialDot",
|
|
620
463
|
"credentialDotConfigured": "TST7FW_credentialDotConfigured",
|
|
621
464
|
"credentialDotMissing": "TST7FW_credentialDotMissing",
|
|
@@ -667,12 +510,13 @@ if (typeof document !== 'undefined' && document.querySelector('style[data-plugin
|
|
|
667
510
|
"section": "TST7FW_section",
|
|
668
511
|
"selectInput": "TST7FW_selectInput",
|
|
669
512
|
"setupCard": "TST7FW_setupCard",
|
|
513
|
+
"switchThumb": "TST7FW_switchThumb",
|
|
670
514
|
"title": "TST7FW_title"
|
|
671
515
|
};
|
|
672
516
|
//#endregion
|
|
673
517
|
//#region src/client/extension-meta.ts
|
|
674
|
-
const ADAPTER_VERSION = "0.1.
|
|
675
|
-
/** Thinking levels offered by llm-pi-ai (THINKING_LEVEL_GATE @
|
|
518
|
+
const ADAPTER_VERSION = "0.1.2-alpha.4";
|
|
519
|
+
/** Thinking levels offered by llm-pi-ai (THINKING_LEVEL_GATE @ 0.1.2-alpha.4). Only `off` may carry an empty wire value. */
|
|
676
520
|
const THINKING_LEVELS = [
|
|
677
521
|
"off",
|
|
678
522
|
"minimal",
|
|
@@ -682,14 +526,15 @@ if (typeof document !== 'undefined' && document.querySelector('style[data-plugin
|
|
|
682
526
|
"xhigh",
|
|
683
527
|
"max"
|
|
684
528
|
];
|
|
685
|
-
/** Input modalities accepted by llm-pi-ai (MODALITY_GATE @
|
|
529
|
+
/** Input modalities accepted by llm-pi-ai (MODALITY_GATE @ 0.1.2-alpha.4). */
|
|
686
530
|
const MODALITIES = ["text", "image"];
|
|
687
|
-
/** Reasoning wire formats understood by llm-pi-ai (SUPPORTED_THINKING_FORMATS @
|
|
531
|
+
/** Reasoning wire formats understood by llm-pi-ai (SUPPORTED_THINKING_FORMATS @ 0.1.2-alpha.4). */
|
|
688
532
|
const THINKING_FORMATS = [
|
|
689
533
|
"openai",
|
|
690
534
|
"deepseek",
|
|
691
535
|
"openrouter",
|
|
692
536
|
"together",
|
|
537
|
+
"baseten",
|
|
693
538
|
"zai",
|
|
694
539
|
"qwen",
|
|
695
540
|
"chat-template",
|
|
@@ -782,6 +627,8 @@ if (typeof document !== 'undefined' && document.querySelector('style[data-plugin
|
|
|
782
627
|
customApiUnset: "Not selected",
|
|
783
628
|
customNeedsBaseUrl: "A custom provider needs a base URL.",
|
|
784
629
|
customNeedsModels: "A custom provider needs at least one model.",
|
|
630
|
+
customBaseUrlPlaceholder: "https://gateway.example/v1",
|
|
631
|
+
settingsPathUnresolvable: "unresolvable settings path",
|
|
785
632
|
create: "Create provider",
|
|
786
633
|
creating: "Creating…",
|
|
787
634
|
onboardingTitle: "Add an API key to get started",
|
|
@@ -892,6 +739,8 @@ if (typeof document !== 'undefined' && document.querySelector('style[data-plugin
|
|
|
892
739
|
customApiUnset: "未选择",
|
|
893
740
|
customNeedsBaseUrl: "自定义提供方需要 API 地址。",
|
|
894
741
|
customNeedsModels: "自定义提供方至少需要一个模型。",
|
|
742
|
+
customBaseUrlPlaceholder: "https://gateway.example/v1",
|
|
743
|
+
settingsPathUnresolvable: "无法解析设置路径",
|
|
895
744
|
create: "创建提供方",
|
|
896
745
|
creating: "创建中…",
|
|
897
746
|
onboardingTitle: "先添加一个 API 密钥即可开始",
|
|
@@ -1303,7 +1152,7 @@ if (typeof document !== 'undefined' && document.querySelector('style[data-plugin
|
|
|
1303
1152
|
* The model list of one pi-ai provider profile (EXT fork for dsh-model-extension).
|
|
1304
1153
|
*
|
|
1305
1154
|
* Forked from deepseek-harness packages/client/ui-settings-models
|
|
1306
|
-
* src/client/ModelListEditor.tsx @ 0.1.
|
|
1155
|
+
* src/client/ModelListEditor.tsx @ 0.1.2-alpha.4.
|
|
1307
1156
|
* Only difference vs upstream: each row's expanded capacities area additionally
|
|
1308
1157
|
* renders <ModelExtensionFields>, which edits the same draft object in place —
|
|
1309
1158
|
* the extension fields ride the card's existing save path untouched.
|
|
@@ -1407,11 +1256,12 @@ if (typeof document !== 'undefined' && document.querySelector('style[data-plugin
|
|
|
1407
1256
|
* @returns the model-list editor.
|
|
1408
1257
|
*/
|
|
1409
1258
|
function ModelListEditor(props) {
|
|
1410
|
-
const { models, onChange, probe,
|
|
1259
|
+
const { models, onChange, probe, operations, t, disabled } = props;
|
|
1411
1260
|
const [busy, setBusy] = (0, react.useState)(false);
|
|
1412
1261
|
const [failure, setFailure] = (0, react.useState)(void 0);
|
|
1413
1262
|
const [candidates, setCandidates] = (0, react.useState)(void 0);
|
|
1414
1263
|
const [picked, setPicked] = (0, react.useState)(/* @__PURE__ */ new Set());
|
|
1264
|
+
const [candidateQuery, setCandidateQuery] = (0, react.useState)("");
|
|
1415
1265
|
const [expanded, setExpanded] = (0, react.useState)(/* @__PURE__ */ new Set());
|
|
1416
1266
|
const [editing, setEditing] = (0, react.useState)(/* @__PURE__ */ new Map());
|
|
1417
1267
|
/** Buffer key for one capacity field; the row half moves when rows do. */
|
|
@@ -1453,27 +1303,25 @@ if (typeof document !== 'undefined' && document.querySelector('style[data-plugin
|
|
|
1453
1303
|
setBusy(true);
|
|
1454
1304
|
setFailure(void 0);
|
|
1455
1305
|
try {
|
|
1456
|
-
const
|
|
1457
|
-
settingsNs: probe.settingsNs,
|
|
1306
|
+
const answer = await operations.discoverModels(probe.settingsNs, {
|
|
1458
1307
|
...probe.provider === void 0 ? {} : { provider: probe.provider },
|
|
1459
1308
|
...probe.baseURL === void 0 || probe.baseURL.length === 0 ? {} : { baseURL: probe.baseURL },
|
|
1460
1309
|
...probe.api === void 0 ? {} : { api: probe.api },
|
|
1461
1310
|
...probe.apiKey === void 0 ? {} : { apiKey: probe.apiKey }
|
|
1462
1311
|
});
|
|
1463
|
-
if (
|
|
1464
|
-
setFailure(
|
|
1312
|
+
if (answer.kind === "refused") {
|
|
1313
|
+
setFailure(answer.message);
|
|
1465
1314
|
return;
|
|
1466
1315
|
}
|
|
1467
|
-
const found =
|
|
1316
|
+
const found = answer.models;
|
|
1468
1317
|
if (found.length === 0) {
|
|
1469
1318
|
setFailure(t("fetchEmpty"));
|
|
1470
1319
|
return;
|
|
1471
1320
|
}
|
|
1472
1321
|
const known = new Set(models.map((model) => textOf(model, "id")));
|
|
1322
|
+
setCandidateQuery("");
|
|
1473
1323
|
setCandidates(found);
|
|
1474
1324
|
setPicked(new Set(found.filter((model) => !known.has(model.id)).map((model) => model.id)));
|
|
1475
|
-
} catch (error) {
|
|
1476
|
-
setFailure(messageOf(error));
|
|
1477
1325
|
} finally {
|
|
1478
1326
|
setBusy(false);
|
|
1479
1327
|
}
|
|
@@ -1481,6 +1329,7 @@ if (typeof document !== 'undefined' && document.querySelector('style[data-plugin
|
|
|
1481
1329
|
const closePicker = () => {
|
|
1482
1330
|
setCandidates(void 0);
|
|
1483
1331
|
setPicked(/* @__PURE__ */ new Set());
|
|
1332
|
+
setCandidateQuery("");
|
|
1484
1333
|
};
|
|
1485
1334
|
const adoptPicked = () => {
|
|
1486
1335
|
/* v8 ignore next -- the dialog only renders with candidates loaded */
|
|
@@ -1501,10 +1350,15 @@ if (typeof document !== 'undefined' && document.querySelector('style[data-plugin
|
|
|
1501
1350
|
});
|
|
1502
1351
|
};
|
|
1503
1352
|
const activeCandidates = candidates ?? [];
|
|
1504
|
-
const
|
|
1505
|
-
const
|
|
1353
|
+
const normalizedCandidateQuery = candidateQuery.trim().toLowerCase();
|
|
1354
|
+
const visibleCandidates = normalizedCandidateQuery.length === 0 ? activeCandidates : activeCandidates.filter((candidate) => candidate.id.toLowerCase().includes(normalizedCandidateQuery) || candidate.name?.toLowerCase().includes(normalizedCandidateQuery) === true);
|
|
1355
|
+
const allVisibleCandidatesPicked = visibleCandidates.length > 0 && visibleCandidates.every((candidate) => picked.has(candidate.id));
|
|
1356
|
+
const toggleVisibleCandidates = () => {
|
|
1506
1357
|
setPicked((current) => {
|
|
1507
|
-
|
|
1358
|
+
const next = new Set(current);
|
|
1359
|
+
if (visibleCandidates.every((candidate) => current.has(candidate.id))) for (const candidate of visibleCandidates) next.delete(candidate.id);
|
|
1360
|
+
else for (const candidate of visibleCandidates) next.add(candidate.id);
|
|
1361
|
+
return next;
|
|
1508
1362
|
});
|
|
1509
1363
|
};
|
|
1510
1364
|
const askable = probe.provider !== void 0 || probe.baseURL !== void 0 && probe.baseURL.length > 0;
|
|
@@ -1682,17 +1536,31 @@ if (typeof document !== 'undefined' && document.querySelector('style[data-plugin
|
|
|
1682
1536
|
onClick: adoptPicked,
|
|
1683
1537
|
children: t("fetchAdopt")
|
|
1684
1538
|
})] }),
|
|
1685
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.
|
|
1686
|
-
className: ModelsSection_ext_module_default["
|
|
1687
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
1539
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1540
|
+
className: ModelsSection_ext_module_default["candidateToolbar"],
|
|
1541
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
1542
|
+
className: `${ModelsSection_ext_module_default["input"]} ${ModelsSection_ext_module_default["candidateSearch"]}`,
|
|
1543
|
+
type: "search",
|
|
1544
|
+
value: candidateQuery,
|
|
1545
|
+
placeholder: t("fetchSearch"),
|
|
1546
|
+
"aria-label": t("fetchSearch"),
|
|
1547
|
+
onChange: (event) => {
|
|
1548
|
+
setCandidateQuery(event.target.value);
|
|
1549
|
+
}
|
|
1550
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
1688
1551
|
variant: "ghost",
|
|
1689
1552
|
size: "sm",
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1553
|
+
disabled: visibleCandidates.length === 0,
|
|
1554
|
+
onClick: toggleVisibleCandidates,
|
|
1555
|
+
children: t(allVisibleCandidatesPicked ? "fetchDeselectAll" : "fetchSelectAll")
|
|
1556
|
+
})]
|
|
1557
|
+
}), visibleCandidates.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1558
|
+
className: ModelsSection_ext_module_default["candidateEmpty"],
|
|
1559
|
+
role: "status",
|
|
1560
|
+
children: t("fetchNoMatches")
|
|
1561
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
1694
1562
|
className: ModelsSection_ext_module_default["candidateList"],
|
|
1695
|
-
children:
|
|
1563
|
+
children: visibleCandidates.map((candidate) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", {
|
|
1696
1564
|
className: ModelsSection_ext_module_default["candidate"],
|
|
1697
1565
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
1698
1566
|
className: ModelsSection_ext_module_default["candidateLabel"],
|
|
@@ -1716,6 +1584,202 @@ if (typeof document !== 'undefined' && document.querySelector('style[data-plugin
|
|
|
1716
1584
|
//#endregion
|
|
1717
1585
|
//#region
|
|
1718
1586
|
/**
|
|
1587
|
+
* Any route key walks a dict schema to the same profile node, so the lookup
|
|
1588
|
+
* names one that cannot collide with a configured route.
|
|
1589
|
+
*/
|
|
1590
|
+
const PROBE_ROUTE = "\0probe";
|
|
1591
|
+
/**
|
|
1592
|
+
* Join declared configurable providers with the currently registered routes.
|
|
1593
|
+
* @param registered - live provider routes in registration order.
|
|
1594
|
+
* @param directory - declared configurable providers in declaration order.
|
|
1595
|
+
* @returns declared rows followed by live routes with no declaration.
|
|
1596
|
+
*/
|
|
1597
|
+
function joinProviderDirectory(registered, directory) {
|
|
1598
|
+
const active = new Set(registered.map((provider) => provider.id));
|
|
1599
|
+
const declared = new Set(directory.map((entry) => entry.provider));
|
|
1600
|
+
const rows = directory.map((entry) => ({
|
|
1601
|
+
provider: entry.provider,
|
|
1602
|
+
displayName: entry.displayName,
|
|
1603
|
+
settingsNs: entry.settingsNs,
|
|
1604
|
+
settingsPath: [...entry.settingsPath],
|
|
1605
|
+
active: active.has(entry.provider),
|
|
1606
|
+
...entry.declared === void 0 ? {} : { declared: entry.declared }
|
|
1607
|
+
}));
|
|
1608
|
+
for (const provider of registered) {
|
|
1609
|
+
if (declared.has(provider.id)) continue;
|
|
1610
|
+
rows.push({
|
|
1611
|
+
provider: provider.id,
|
|
1612
|
+
displayName: provider.name,
|
|
1613
|
+
settingsNs: "",
|
|
1614
|
+
settingsPath: [],
|
|
1615
|
+
active: true
|
|
1616
|
+
});
|
|
1617
|
+
}
|
|
1618
|
+
return rows;
|
|
1619
|
+
}
|
|
1620
|
+
/**
|
|
1621
|
+
* Derive the conventional credential reference for a provider route: the v1
|
|
1622
|
+
* page never asks for an environment-variable name, so a typed key stores
|
|
1623
|
+
* under this derived reference and the profile records it as `apiKeyEnv`.
|
|
1624
|
+
* @param provider - provider route id (e.g. `anthropic`, `minimax-cn`).
|
|
1625
|
+
* @returns the derived reference name (e.g. `MINIMAX_CN_API_KEY`).
|
|
1626
|
+
*/
|
|
1627
|
+
function deriveKeyRef(provider) {
|
|
1628
|
+
return `${provider.toUpperCase().replace(/[^A-Z0-9]+/g, "_")}_API_KEY`;
|
|
1629
|
+
}
|
|
1630
|
+
/**
|
|
1631
|
+
* The wire protocols a hand-declared route may name, read out of the owning
|
|
1632
|
+
* namespace's own schema. This stays a schema read rather than a wire field so
|
|
1633
|
+
* the choices the page offers cannot drift from the ones the adapter accepts:
|
|
1634
|
+
* both come from the same `Config`.
|
|
1635
|
+
* @param namespace - the namespace view whose schema declares the profile shape.
|
|
1636
|
+
* @param schema - settings schema operations.
|
|
1637
|
+
* @returns the protocol identifiers, or an empty list when the schema has none.
|
|
1638
|
+
*/
|
|
1639
|
+
function protocolChoices(namespace, schema) {
|
|
1640
|
+
if (namespace === void 0) return [];
|
|
1641
|
+
const list = schema.nodeAtPath(schema.rehydrate(namespace.schema), [
|
|
1642
|
+
"providers",
|
|
1643
|
+
PROBE_ROUTE,
|
|
1644
|
+
"api"
|
|
1645
|
+
]);
|
|
1646
|
+
if (list?.type !== "union" || list.list === void 0) return [];
|
|
1647
|
+
return list.list.map((entry) => entry.value).filter((value) => typeof value === "string");
|
|
1648
|
+
}
|
|
1649
|
+
/** The credential reference a resolved profile names (its `apiKeyEnv` field). */
|
|
1650
|
+
function apiKeyEnvOf(namespace, path, schema) {
|
|
1651
|
+
if (namespace === void 0) return void 0;
|
|
1652
|
+
const profile = schema.getPath(namespace.value, path);
|
|
1653
|
+
if (typeof profile !== "object" || profile === null) return void 0;
|
|
1654
|
+
const ref = profile.apiKeyEnv;
|
|
1655
|
+
return typeof ref === "string" && ref.length > 0 ? ref : void 0;
|
|
1656
|
+
}
|
|
1657
|
+
/** The models settings page controller (one per settings surface). */
|
|
1658
|
+
var ModelsSettingsStore = class {
|
|
1659
|
+
ctx;
|
|
1660
|
+
schema;
|
|
1661
|
+
describeFace;
|
|
1662
|
+
/** The snapshot the section renders from (uSES-safe store). */
|
|
1663
|
+
store = (0, _deepseek_ai_dsh_client_store.createSnapshotStore)({
|
|
1664
|
+
status: "idle",
|
|
1665
|
+
error: null,
|
|
1666
|
+
credentialError: null,
|
|
1667
|
+
writable: false,
|
|
1668
|
+
rows: [],
|
|
1669
|
+
namespaces: /* @__PURE__ */ new Map()
|
|
1670
|
+
});
|
|
1671
|
+
/** Latest load wins; an older response never overwrites a newer one. */
|
|
1672
|
+
generation = 0;
|
|
1673
|
+
/**
|
|
1674
|
+
* @param ctx - the page plugin's context, whose `remote.llm` and
|
|
1675
|
+
* `remote.credentials` namespaces carry the directory and credential reads.
|
|
1676
|
+
* @param schema - settings-owned schema and immutable path operations.
|
|
1677
|
+
* @param describeFace - the shared mirror's describe face (namespace views and writability).
|
|
1678
|
+
*/
|
|
1679
|
+
constructor(ctx, schema, describeFace) {
|
|
1680
|
+
this.ctx = ctx;
|
|
1681
|
+
this.schema = schema;
|
|
1682
|
+
this.describeFace = describeFace;
|
|
1683
|
+
}
|
|
1684
|
+
/**
|
|
1685
|
+
* Refresh the whole page snapshot: the provider directory and the mirror's
|
|
1686
|
+
* settings answer in parallel, then one batched credential describe over
|
|
1687
|
+
* every referenced ref. Provider failure or absence of an initial settings
|
|
1688
|
+
* answer keeps the last good rows and surfaces an error; a failed settings
|
|
1689
|
+
* refresh reuses the mirror's held view.
|
|
1690
|
+
* @returns nothing; the snapshot carries the outcome.
|
|
1691
|
+
*/
|
|
1692
|
+
async load() {
|
|
1693
|
+
const generation = ++this.generation;
|
|
1694
|
+
this.store.update((s) => {
|
|
1695
|
+
s.status = "loading";
|
|
1696
|
+
s.error = null;
|
|
1697
|
+
});
|
|
1698
|
+
const [registered, declared] = await Promise.all([
|
|
1699
|
+
this.ctx.remote.llm.listProviders(),
|
|
1700
|
+
this.ctx.remote.llm.listConfigurableProviders(),
|
|
1701
|
+
this.describeFace.ensure()
|
|
1702
|
+
]);
|
|
1703
|
+
if (!registered.ok) {
|
|
1704
|
+
this.failLoad(generation, registered.error.message);
|
|
1705
|
+
return;
|
|
1706
|
+
}
|
|
1707
|
+
if (!declared.ok) {
|
|
1708
|
+
this.failLoad(generation, declared.error.message);
|
|
1709
|
+
return;
|
|
1710
|
+
}
|
|
1711
|
+
const mirrored = this.describeFace.getSnapshot();
|
|
1712
|
+
if (mirrored.view === void 0) {
|
|
1713
|
+
this.failLoad(generation, mirrored.error ?? "settings are unavailable in this browser");
|
|
1714
|
+
return;
|
|
1715
|
+
}
|
|
1716
|
+
const providers = joinProviderDirectory(registered.value, declared.value);
|
|
1717
|
+
const writable = mirrored.view.writable;
|
|
1718
|
+
const views = mirrored.view.namespaces;
|
|
1719
|
+
const namespaces = new Map(views.map((view) => [view.ns, view]));
|
|
1720
|
+
const rows = providers.map((entry) => {
|
|
1721
|
+
const namespace = namespaces.get(entry.settingsNs);
|
|
1722
|
+
return {
|
|
1723
|
+
entry,
|
|
1724
|
+
configured: namespace !== void 0 && (entry.settingsPath.length === 0 || this.schema.getPath(namespace.value, entry.settingsPath) !== void 0),
|
|
1725
|
+
removable: namespace !== void 0 && entry.settingsPath.length > 0 && this.schema.hasPath(namespace.user, entry.settingsPath) && !this.schema.hasPath(namespace.base, entry.settingsPath),
|
|
1726
|
+
apiKeyEnv: apiKeyEnvOf(namespace, entry.settingsPath, this.schema),
|
|
1727
|
+
credential: void 0
|
|
1728
|
+
};
|
|
1729
|
+
});
|
|
1730
|
+
const refs = [...new Set(rows.map((row) => row.apiKeyEnv ?? deriveKeyRef(row.entry.provider)))];
|
|
1731
|
+
let credentials = {};
|
|
1732
|
+
let credentialError = null;
|
|
1733
|
+
if (refs.length > 0) {
|
|
1734
|
+
const response = await this.ctx.remote.credentials.describe(refs);
|
|
1735
|
+
if (response.ok) credentials = response.value;
|
|
1736
|
+
else credentialError = response.error.message;
|
|
1737
|
+
}
|
|
1738
|
+
if (generation !== this.generation) return;
|
|
1739
|
+
this.store.update((s) => {
|
|
1740
|
+
s.status = "ready";
|
|
1741
|
+
s.error = null;
|
|
1742
|
+
s.credentialError = credentialError;
|
|
1743
|
+
s.writable = writable;
|
|
1744
|
+
s.rows = rows.map((row) => {
|
|
1745
|
+
const named = row.apiKeyEnv === void 0 ? void 0 : credentials[row.apiKeyEnv];
|
|
1746
|
+
const derived = row.apiKeyEnv !== void 0 ? void 0 : credentials[deriveKeyRef(row.entry.provider)];
|
|
1747
|
+
return {
|
|
1748
|
+
...row,
|
|
1749
|
+
...named === void 0 ? {} : { credential: named },
|
|
1750
|
+
...derived === void 0 ? {} : { derivedCredential: derived }
|
|
1751
|
+
};
|
|
1752
|
+
});
|
|
1753
|
+
s.namespaces = namespaces;
|
|
1754
|
+
});
|
|
1755
|
+
}
|
|
1756
|
+
/** Publish one load's failure text, unless a newer load already took over. */
|
|
1757
|
+
failLoad(generation, message) {
|
|
1758
|
+
if (generation !== this.generation) return;
|
|
1759
|
+
this.store.update((s) => {
|
|
1760
|
+
s.status = "error";
|
|
1761
|
+
s.error = message;
|
|
1762
|
+
});
|
|
1763
|
+
}
|
|
1764
|
+
};
|
|
1765
|
+
/**
|
|
1766
|
+
* Whether a joined row can serve model requests as it stands: the route is
|
|
1767
|
+
* registered with the adapter registry, and whatever credential its resolved
|
|
1768
|
+
* profile names is stored. A profile naming no reference authenticates through
|
|
1769
|
+
* the provider's own path (the Bedrock chain, Vertex ADC, a gateway that needs
|
|
1770
|
+
* nothing), as does a live route with no settings address at all, so neither
|
|
1771
|
+
* owes this page a key.
|
|
1772
|
+
* @param row - one joined provider row.
|
|
1773
|
+
* @returns whether the user already has this provider to talk to.
|
|
1774
|
+
*/
|
|
1775
|
+
function providerUsable(row) {
|
|
1776
|
+
if (!row.entry.active) return false;
|
|
1777
|
+
if (row.apiKeyEnv === void 0) return true;
|
|
1778
|
+
return row.credential?.configured === true;
|
|
1779
|
+
}
|
|
1780
|
+
//#endregion
|
|
1781
|
+
//#region
|
|
1782
|
+
/**
|
|
1719
1783
|
* The card that declares a provider pi-ai does not ship — an OpenAI-compatible
|
|
1720
1784
|
* gateway, a self-hosted server, or a provider newer than the installed
|
|
1721
1785
|
* catalog.
|
|
@@ -1724,7 +1788,7 @@ if (typeof document !== 'undefined' && document.querySelector('style[data-plugin
|
|
|
1724
1788
|
* the provider editor with extra fields: the route id is being *chosen* here,
|
|
1725
1789
|
* and the settings address does not exist until it is. One `settings.mutate`
|
|
1726
1790
|
* sets the whole profile at `providers.<route>`; the key travels separately
|
|
1727
|
-
* through `credentials
|
|
1791
|
+
* through `credentials/set` under the reference the profile records, exactly as
|
|
1728
1792
|
* an existing provider's key does.
|
|
1729
1793
|
*
|
|
1730
1794
|
* The three fields a hand-declared route cannot default — endpoint, protocol,
|
|
@@ -1754,7 +1818,7 @@ if (typeof document !== 'undefined' && document.querySelector('style[data-plugin
|
|
|
1754
1818
|
* @returns the creation card.
|
|
1755
1819
|
*/
|
|
1756
1820
|
function CustomProviderCard(props) {
|
|
1757
|
-
const { taken, protocols,
|
|
1821
|
+
const { taken, protocols, operations, t } = props;
|
|
1758
1822
|
const [openedAt] = (0, react.useState)(() => props.revision);
|
|
1759
1823
|
const [route, setRoute] = (0, react.useState)("");
|
|
1760
1824
|
const [displayName, setDisplayName] = (0, react.useState)("");
|
|
@@ -1792,24 +1856,17 @@ if (typeof document !== 'undefined' && document.querySelector('style[data-plugin
|
|
|
1792
1856
|
baseURL,
|
|
1793
1857
|
models: models.map((model) => ({ ...model }))
|
|
1794
1858
|
};
|
|
1795
|
-
const
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
}],
|
|
1802
|
-
expectedRevision: openedAt
|
|
1803
|
-
});
|
|
1804
|
-
if (!response.result.ok) return response.result.error.message;
|
|
1859
|
+
const written = await operations.writeSettings(NS, [{
|
|
1860
|
+
op: "set",
|
|
1861
|
+
path: ["providers", route],
|
|
1862
|
+
value: profile
|
|
1863
|
+
}], openedAt);
|
|
1864
|
+
if (written.kind !== "written") return written.kind === "conflict" ? t("conflict") : written.message;
|
|
1805
1865
|
setCommitted(true);
|
|
1806
1866
|
}
|
|
1807
1867
|
if (storesKey) {
|
|
1808
|
-
const stored = await
|
|
1809
|
-
|
|
1810
|
-
value: keyValue
|
|
1811
|
-
});
|
|
1812
|
-
if (!stored.result.ok) return stored.result.error.message;
|
|
1868
|
+
const stored = await operations.storeCredential(keyRef, keyValue);
|
|
1869
|
+
if (stored !== void 0) return stored;
|
|
1813
1870
|
}
|
|
1814
1871
|
};
|
|
1815
1872
|
const create = async () => {
|
|
@@ -1822,8 +1879,6 @@ if (typeof document !== 'undefined' && document.querySelector('style[data-plugin
|
|
|
1822
1879
|
return;
|
|
1823
1880
|
}
|
|
1824
1881
|
props.onClose(true);
|
|
1825
|
-
} catch (error) {
|
|
1826
|
-
setFailure(messageOf(error));
|
|
1827
1882
|
} finally {
|
|
1828
1883
|
setBusy(false);
|
|
1829
1884
|
}
|
|
@@ -1888,7 +1943,7 @@ if (typeof document !== 'undefined' && document.querySelector('style[data-plugin
|
|
|
1888
1943
|
className: ModelsSection_module_default["input"],
|
|
1889
1944
|
type: "text",
|
|
1890
1945
|
value: baseURL,
|
|
1891
|
-
placeholder: "
|
|
1946
|
+
placeholder: t("customBaseUrlPlaceholder"),
|
|
1892
1947
|
"aria-label": t("baseUrl"),
|
|
1893
1948
|
disabled: profileDisabled,
|
|
1894
1949
|
onChange: (event) => {
|
|
@@ -1950,7 +2005,7 @@ if (typeof document !== 'undefined' && document.querySelector('style[data-plugin
|
|
|
1950
2005
|
...keyValue.length === 0 ? {} : { apiKey: keyValue }
|
|
1951
2006
|
},
|
|
1952
2007
|
probeBlocked: keyFailure === "keyBlank" ? "keyBlankNew" : keyFailure,
|
|
1953
|
-
|
|
2008
|
+
operations,
|
|
1954
2009
|
t,
|
|
1955
2010
|
disabled: profileDisabled
|
|
1956
2011
|
}),
|
|
@@ -1966,8 +2021,8 @@ if (typeof document !== 'undefined' && document.querySelector('style[data-plugin
|
|
|
1966
2021
|
t,
|
|
1967
2022
|
busy,
|
|
1968
2023
|
submitDisabled: disabled || !ready,
|
|
1969
|
-
|
|
1970
|
-
|
|
2024
|
+
submitLabelKey: "create",
|
|
2025
|
+
submitBusyLabelKey: "creating",
|
|
1971
2026
|
onCancel: () => {
|
|
1972
2027
|
props.onClose(committed);
|
|
1973
2028
|
},
|
|
@@ -1983,7 +2038,7 @@ if (typeof document !== 'undefined' && document.querySelector('style[data-plugin
|
|
|
1983
2038
|
/**
|
|
1984
2039
|
* One provider's editor card, hand-written per adapter family: the primary
|
|
1985
2040
|
* field is a single write-only **API key** input (the page never asks for an
|
|
1986
|
-
* environment-variable name — a typed key stores through `credentials
|
|
2041
|
+
* environment-variable name — a typed key stores through `credentials/set`
|
|
1987
2042
|
* under the profile's reference, deriving `<ROUTE>_API_KEY` when the profile
|
|
1988
2043
|
* has none. The pi-ai profile records that derivation as `apiKeyEnv` only when
|
|
1989
2044
|
* a key is entered; a blank key materializes a reference-free profile for
|
|
@@ -2055,7 +2110,7 @@ if (typeof document !== 'undefined' && document.querySelector('style[data-plugin
|
|
|
2055
2110
|
* @returns the editor card.
|
|
2056
2111
|
*/
|
|
2057
2112
|
function ProviderEditor(props) {
|
|
2058
|
-
const { namespace, schema, settingsPath,
|
|
2113
|
+
const { namespace, schema, settingsPath, operations, t } = props;
|
|
2059
2114
|
const [draft, setDraft] = (0, react.useState)(() => draftAt(schema, namespace, settingsPath));
|
|
2060
2115
|
const [keyDraft, setKeyDraft] = (0, react.useState)("");
|
|
2061
2116
|
const [keyState, setKeyState] = (0, react.useState)(void 0);
|
|
@@ -2081,14 +2136,14 @@ if (typeof document !== 'undefined' && document.querySelector('style[data-plugin
|
|
|
2081
2136
|
(0, react.useEffect)(() => {
|
|
2082
2137
|
let stale = false;
|
|
2083
2138
|
setKeyState(void 0);
|
|
2084
|
-
|
|
2085
|
-
if (stale
|
|
2086
|
-
setKeyState(
|
|
2087
|
-
}
|
|
2139
|
+
operations.describeCredential(keyRef).then((described) => {
|
|
2140
|
+
if (stale) return;
|
|
2141
|
+
setKeyState(described);
|
|
2142
|
+
});
|
|
2088
2143
|
return () => {
|
|
2089
2144
|
stale = true;
|
|
2090
2145
|
};
|
|
2091
|
-
}, [
|
|
2146
|
+
}, [operations, keyRef]);
|
|
2092
2147
|
const stringAt = (source, key) => {
|
|
2093
2148
|
const value = schema.getPath(source, [key]);
|
|
2094
2149
|
return typeof value === "string" && value.trim().length > 0 ? value : void 0;
|
|
@@ -2136,22 +2191,15 @@ if (typeof document !== 'undefined' && document.querySelector('style[data-plugin
|
|
|
2136
2191
|
value: {}
|
|
2137
2192
|
}] : pathOps(settingsPath, committedOriginal, next);
|
|
2138
2193
|
if (ops.length > 0) {
|
|
2139
|
-
const
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
});
|
|
2144
|
-
if (!response.result.ok) return response.result.error.code === "settings-conflict" ? t("conflict") : response.result.error.message;
|
|
2145
|
-
setCommittedOriginal(schema.getPath(response.result.value.user, settingsPath));
|
|
2146
|
-
setExpectedRevision(response.result.value.revision);
|
|
2194
|
+
const written = await operations.writeSettings(ns, ops, expectedRevision);
|
|
2195
|
+
if (written.kind !== "written") return written.kind === "conflict" ? t("conflict") : written.message;
|
|
2196
|
+
setCommittedOriginal(schema.getPath(written.view.user, settingsPath));
|
|
2197
|
+
setExpectedRevision(written.view.revision);
|
|
2147
2198
|
setDraft(next);
|
|
2148
2199
|
}
|
|
2149
2200
|
if (keyValue.length > 0) {
|
|
2150
|
-
const stored = await
|
|
2151
|
-
|
|
2152
|
-
value: keyValue
|
|
2153
|
-
});
|
|
2154
|
-
if (!stored.result.ok) return stored.result.error.message;
|
|
2201
|
+
const stored = await operations.storeCredential(keyRef, keyValue);
|
|
2202
|
+
if (stored !== void 0) return stored;
|
|
2155
2203
|
}
|
|
2156
2204
|
setKeyDraft("");
|
|
2157
2205
|
};
|
|
@@ -2165,15 +2213,17 @@ if (typeof document !== 'undefined' && document.querySelector('style[data-plugin
|
|
|
2165
2213
|
return;
|
|
2166
2214
|
}
|
|
2167
2215
|
props.onClose(true);
|
|
2168
|
-
} catch (error) {
|
|
2169
|
-
setFailure(messageOf(error));
|
|
2170
2216
|
} finally {
|
|
2171
2217
|
setBusy(false);
|
|
2172
2218
|
}
|
|
2173
2219
|
};
|
|
2174
|
-
if (node === void 0) return /* @__PURE__ */ (0, react_jsx_runtime.
|
|
2220
|
+
if (node === void 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
|
|
2175
2221
|
className: ModelsSection_module_default["error"],
|
|
2176
|
-
children:
|
|
2222
|
+
children: [
|
|
2223
|
+
props.provider,
|
|
2224
|
+
": ",
|
|
2225
|
+
props.t("settingsPathUnresolvable")
|
|
2226
|
+
]
|
|
2177
2227
|
});
|
|
2178
2228
|
const keyLocked = keyState?.writable === false;
|
|
2179
2229
|
/**
|
|
@@ -2311,7 +2361,7 @@ if (typeof document !== 'undefined' && document.querySelector('style[data-plugin
|
|
|
2311
2361
|
...catalogProps,
|
|
2312
2362
|
probe,
|
|
2313
2363
|
probeBlocked: keyFailure,
|
|
2314
|
-
|
|
2364
|
+
operations
|
|
2315
2365
|
})
|
|
2316
2366
|
]
|
|
2317
2367
|
})]
|
|
@@ -2346,9 +2396,9 @@ if (typeof document !== 'undefined' && document.querySelector('style[data-plugin
|
|
|
2346
2396
|
t,
|
|
2347
2397
|
busy,
|
|
2348
2398
|
submitDisabled: disabled || layout === "unknown" || props.credentialOnly !== true && modelFailure !== void 0 || shownKeyFailure !== void 0 || props.credentialRequired === true && keyValue.length === 0,
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
...props.
|
|
2399
|
+
submitLabelKey: props.submitLabelKey ?? "apply",
|
|
2400
|
+
submitBusyLabelKey: props.submitBusyLabelKey ?? "applying",
|
|
2401
|
+
...props.cancelLabelKey === void 0 ? {} : { cancelLabelKey: props.cancelLabelKey },
|
|
2352
2402
|
onCancel: () => {
|
|
2353
2403
|
props.onClose(false);
|
|
2354
2404
|
},
|
|
@@ -2365,10 +2415,19 @@ if (typeof document !== 'undefined' && document.querySelector('style[data-plugin
|
|
|
2365
2415
|
* Models settings section (EXT fork for dsh-model-extension).
|
|
2366
2416
|
*
|
|
2367
2417
|
* Forked from deepseek-harness packages/client/ui-settings-models
|
|
2368
|
-
* src/client/ModelsSection.tsx @ 0.1.
|
|
2369
|
-
*
|
|
2370
|
-
*
|
|
2371
|
-
*
|
|
2418
|
+
* src/client/ModelsSection.tsx @ 0.1.2-alpha.4.
|
|
2419
|
+
* Differences vs upstream (keep this list exhaustive when merging drift):
|
|
2420
|
+
* 1. The h2 title row carries an adapter-version badge.
|
|
2421
|
+
* 2. No child-slot machinery: this is a standalone section (id
|
|
2422
|
+
* 'models-extension'), and the 'settings.models.provider-card' /
|
|
2423
|
+
* 'settings.models.footer' children are already declared globally by the
|
|
2424
|
+
* official Models section — redeclaring them throws, so every renderSlot
|
|
2425
|
+
* call (and the addRow/keyConfiguredOf helpers serving only the seat) is
|
|
2426
|
+
* removed. Third-party provider-card/footer extensions therefore render on
|
|
2427
|
+
* the official Models page only; that is an accepted trade-off of the fork.
|
|
2428
|
+
* 3. Styles come from the plugin's own ModelsSection.ext.module.css.
|
|
2429
|
+
* Everything else is upstream verbatim — keep this file minimal when merging
|
|
2430
|
+
* drift after a host upgrade.
|
|
2372
2431
|
*
|
|
2373
2432
|
* Models settings section: the provider rows joined from the configurable
|
|
2374
2433
|
* directory, settings namespaces, and credential states, with one editor
|
|
@@ -2398,28 +2457,21 @@ if (typeof document !== 'undefined' && document.querySelector('style[data-plugin
|
|
|
2398
2457
|
* and the whole operation safely retryable; both unsets are idempotent.
|
|
2399
2458
|
* The settings removal names the profile rather than rebuilding its whole
|
|
2400
2459
|
* namespace from a partial view.
|
|
2401
|
-
* @param
|
|
2460
|
+
* @param operations - the page's Host operations.
|
|
2402
2461
|
* @param controller - the page store to refresh.
|
|
2403
2462
|
* @param target - the provider's settings address and optional managed credential.
|
|
2404
2463
|
* @returns the failure message, or undefined once the write and reload landed.
|
|
2405
2464
|
*/
|
|
2406
|
-
async function removeProviderProfile(
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
if (!credential.result.ok) return credential.result.error.message;
|
|
2411
|
-
}
|
|
2412
|
-
const response = await api.settings.mutate({
|
|
2413
|
-
ns: target.settingsNs,
|
|
2414
|
-
ops: [{
|
|
2415
|
-
op: "unset",
|
|
2416
|
-
path: [...target.settingsPath]
|
|
2417
|
-
}]
|
|
2418
|
-
});
|
|
2419
|
-
if (!response.result.ok) return response.result.error.message;
|
|
2420
|
-
} catch (error) {
|
|
2421
|
-
return messageOf(error);
|
|
2465
|
+
async function removeProviderProfile(operations, controller, target) {
|
|
2466
|
+
if (target.credentialRef !== void 0) {
|
|
2467
|
+
const credential = await operations.removeCredential(target.credentialRef);
|
|
2468
|
+
if (credential !== void 0) return credential;
|
|
2422
2469
|
}
|
|
2470
|
+
const written = await operations.writeSettings(target.settingsNs, [{
|
|
2471
|
+
op: "unset",
|
|
2472
|
+
path: [...target.settingsPath]
|
|
2473
|
+
}], void 0);
|
|
2474
|
+
if (written.kind !== "written") return written.message;
|
|
2423
2475
|
await controller.load();
|
|
2424
2476
|
}
|
|
2425
2477
|
/**
|
|
@@ -2462,18 +2514,18 @@ if (typeof document !== 'undefined' && document.querySelector('style[data-plugin
|
|
|
2462
2514
|
* @returns the section, or null while the shell has not injected yet.
|
|
2463
2515
|
*/
|
|
2464
2516
|
function ModelsSection(props) {
|
|
2465
|
-
const { controller, useSnapshot,
|
|
2466
|
-
if (controller === void 0 || useSnapshot === void 0 ||
|
|
2517
|
+
const { controller, useSnapshot, operations, schema, t } = props;
|
|
2518
|
+
if (controller === void 0 || useSnapshot === void 0 || operations === void 0 || schema === void 0 || t === void 0) return null;
|
|
2467
2519
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Loaded, { injected: {
|
|
2468
2520
|
controller,
|
|
2469
2521
|
useSnapshot,
|
|
2470
|
-
|
|
2522
|
+
operations,
|
|
2471
2523
|
schema,
|
|
2472
2524
|
t
|
|
2473
2525
|
} });
|
|
2474
2526
|
}
|
|
2475
2527
|
function Loaded({ injected }) {
|
|
2476
|
-
const { controller,
|
|
2528
|
+
const { controller, operations, schema, t } = injected;
|
|
2477
2529
|
const state = injected.useSnapshot((snapshot) => snapshot);
|
|
2478
2530
|
const [editing, setEditing] = (0, react.useState)(void 0);
|
|
2479
2531
|
const [adding, setAdding] = (0, react.useState)(false);
|
|
@@ -2515,7 +2567,7 @@ if (typeof document !== 'undefined' && document.querySelector('style[data-plugin
|
|
|
2515
2567
|
if (deleteTarget === void 0 || deleting) return;
|
|
2516
2568
|
setDeleting(true);
|
|
2517
2569
|
setDeleteFailure(void 0);
|
|
2518
|
-
removeProviderProfile(
|
|
2570
|
+
removeProviderProfile(operations, controller, deleteTarget).then((failure) => {
|
|
2519
2571
|
if (failure !== void 0) {
|
|
2520
2572
|
setDeleteFailure(failure);
|
|
2521
2573
|
return;
|
|
@@ -2592,7 +2644,7 @@ if (typeof document !== 'undefined' && document.querySelector('style[data-plugin
|
|
|
2592
2644
|
target,
|
|
2593
2645
|
namespace,
|
|
2594
2646
|
schema,
|
|
2595
|
-
|
|
2647
|
+
operations,
|
|
2596
2648
|
t,
|
|
2597
2649
|
readOnly: !state.writable,
|
|
2598
2650
|
onClose: (changed) => {
|
|
@@ -2660,7 +2712,7 @@ if (typeof document !== 'undefined' && document.querySelector('style[data-plugin
|
|
|
2660
2712
|
target,
|
|
2661
2713
|
namespace,
|
|
2662
2714
|
schema,
|
|
2663
|
-
|
|
2715
|
+
operations,
|
|
2664
2716
|
t,
|
|
2665
2717
|
readOnly: !state.writable,
|
|
2666
2718
|
onClose: (changed) => {
|
|
@@ -2701,7 +2753,7 @@ if (typeof document !== 'undefined' && document.querySelector('style[data-plugin
|
|
|
2701
2753
|
namespace: addNamespace,
|
|
2702
2754
|
schema,
|
|
2703
2755
|
settingsPath: addTarget.settingsPath,
|
|
2704
|
-
|
|
2756
|
+
operations,
|
|
2705
2757
|
t,
|
|
2706
2758
|
readOnly: !state.writable,
|
|
2707
2759
|
onClose: (changed) => {
|
|
@@ -2715,7 +2767,7 @@ if (typeof document !== 'undefined' && document.querySelector('style[data-plugin
|
|
|
2715
2767
|
protocols,
|
|
2716
2768
|
/* v8 ignore next -- the card only opens from a button disabled without this namespace */
|
|
2717
2769
|
revision: state.namespaces.get("llm-pi-ai")?.revision ?? 0,
|
|
2718
|
-
|
|
2770
|
+
operations,
|
|
2719
2771
|
t,
|
|
2720
2772
|
readOnly: !state.writable,
|
|
2721
2773
|
onClose: (changed) => {
|
|
@@ -2784,6 +2836,55 @@ if (typeof document !== 'undefined' && document.querySelector('style[data-plugin
|
|
|
2784
2836
|
//#endregion
|
|
2785
2837
|
//#region
|
|
2786
2838
|
/**
|
|
2839
|
+
* Bind the page's Host operations to the plugin's own Remote namespaces.
|
|
2840
|
+
* @param ctx - the page plugin's context, which declares `remote.credentials`,
|
|
2841
|
+
* `remote.llm`, and `remote.settings` in its own `inject`.
|
|
2842
|
+
* @returns the callbacks the section and its cards are injected with.
|
|
2843
|
+
*/
|
|
2844
|
+
function createModelsOperations(ctx) {
|
|
2845
|
+
return {
|
|
2846
|
+
describeCredential: async (ref) => {
|
|
2847
|
+
const response = await ctx.remote.credentials.describe([ref]);
|
|
2848
|
+
return response.ok ? response.value[ref] : void 0;
|
|
2849
|
+
},
|
|
2850
|
+
storeCredential: async (ref, value) => {
|
|
2851
|
+
const response = await ctx.remote.credentials.set(ref, value);
|
|
2852
|
+
return response.ok ? void 0 : response.error.message;
|
|
2853
|
+
},
|
|
2854
|
+
removeCredential: async (ref) => {
|
|
2855
|
+
const response = await ctx.remote.credentials.unset(ref);
|
|
2856
|
+
return response.ok ? void 0 : response.error.message;
|
|
2857
|
+
},
|
|
2858
|
+
writeSettings: async (ns, ops, expectedRevision) => {
|
|
2859
|
+
const response = await ctx.remote.settings.mutate(ns, ops, expectedRevision);
|
|
2860
|
+
if (response.ok) return {
|
|
2861
|
+
kind: "written",
|
|
2862
|
+
view: response.value
|
|
2863
|
+
};
|
|
2864
|
+
const { code, message } = response.error;
|
|
2865
|
+
return code === "settings/conflict" ? {
|
|
2866
|
+
kind: "conflict",
|
|
2867
|
+
message
|
|
2868
|
+
} : {
|
|
2869
|
+
kind: "refused",
|
|
2870
|
+
message
|
|
2871
|
+
};
|
|
2872
|
+
},
|
|
2873
|
+
discoverModels: async (settingsNs, request) => {
|
|
2874
|
+
const response = await ctx.remote.llm.discoverModels(settingsNs, request);
|
|
2875
|
+
return response.ok ? {
|
|
2876
|
+
kind: "found",
|
|
2877
|
+
models: response.value
|
|
2878
|
+
} : {
|
|
2879
|
+
kind: "refused",
|
|
2880
|
+
message: response.error.message
|
|
2881
|
+
};
|
|
2882
|
+
}
|
|
2883
|
+
};
|
|
2884
|
+
}
|
|
2885
|
+
//#endregion
|
|
2886
|
+
//#region
|
|
2887
|
+
/**
|
|
2787
2888
|
* Hide the Cordis service identity behind bound schema callbacks.
|
|
2788
2889
|
* @param service - settings-owned schema service available in the apply context.
|
|
2789
2890
|
* @returns callbacks that cannot expose the service context to React components.
|
|
@@ -2803,12 +2904,14 @@ if (typeof document !== 'undefined' && document.querySelector('style[data-plugin
|
|
|
2803
2904
|
//#region src/client/index-extension.ts
|
|
2804
2905
|
/** Cordis service name (distinct from the npm package name). */
|
|
2805
2906
|
const name = "model-extension-client";
|
|
2806
|
-
/** Required services — mirrors the upstream Models section registration. */
|
|
2907
|
+
/** Required services — mirrors the upstream Models section registration @ 0.1.2-alpha.4. */
|
|
2807
2908
|
const inject = [
|
|
2808
2909
|
"slots",
|
|
2809
2910
|
"locale",
|
|
2810
|
-
"connection",
|
|
2811
2911
|
"remote",
|
|
2912
|
+
"remote.credentials",
|
|
2913
|
+
"remote.llm",
|
|
2914
|
+
"remote.settings",
|
|
2812
2915
|
"settingsScope",
|
|
2813
2916
|
"settingsSchema"
|
|
2814
2917
|
];
|
|
@@ -2827,14 +2930,14 @@ if (typeof document !== 'undefined' && document.querySelector('style[data-plugin
|
|
|
2827
2930
|
zh: { ...zh },
|
|
2828
2931
|
en: { ...en }
|
|
2829
2932
|
}), "dsh-model-extension: copy dictionaries");
|
|
2830
|
-
const connection = ctx.get("connection");
|
|
2831
2933
|
const schema = createSettingsSchemaOperations(ctx.settingsSchema);
|
|
2832
|
-
const
|
|
2934
|
+
const operations = createModelsOperations(ctx);
|
|
2935
|
+
const controller = new ModelsSettingsStore(ctx, schema, ctx.settingsScope.describe());
|
|
2833
2936
|
const t = ctx.locale.bind(NS);
|
|
2834
2937
|
const injected = () => ({
|
|
2835
2938
|
controller,
|
|
2836
2939
|
hooks: { snapshot: controller.store },
|
|
2837
|
-
|
|
2940
|
+
operations,
|
|
2838
2941
|
schema,
|
|
2839
2942
|
t
|
|
2840
2943
|
});
|