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/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 _deepseek_ai_dsh_client_runtime_client = require("@deepseek-ai/dsh-client-runtime/client");
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
- "candidateActions": "Qji2zG_candidateActions",
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.cancelLabel ?? "cancel")
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.submitBusyLabel) : t(props.submitLabel)
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
- "candidateActions": "TST7FW_candidateActions",
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.1-rc.2";
675
- /** Thinking levels offered by llm-pi-ai (THINKING_LEVEL_GATE @ rc.2). Only `off` may carry an empty wire value. */
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 @ rc.2). */
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 @ rc.2). */
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.1-rc.2.
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, api, t, disabled } = props;
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 response = await api.llm.discoverModels({
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 (!response.result.ok) {
1464
- setFailure(response.result.error.message);
1312
+ if (answer.kind === "refused") {
1313
+ setFailure(answer.message);
1465
1314
  return;
1466
1315
  }
1467
- const found = response.result.value.models;
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 allCandidatesPicked = activeCandidates.length > 0 && activeCandidates.every((candidate) => picked.has(candidate.id));
1505
- const toggleAllCandidates = () => {
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
- return activeCandidates.every((candidate) => current.has(candidate.id)) ? /* @__PURE__ */ new Set() : new Set(activeCandidates.map((candidate) => candidate.id));
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.jsx)("div", {
1686
- className: ModelsSection_ext_module_default["candidateActions"],
1687
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
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
- onClick: toggleAllCandidates,
1691
- children: t(allCandidatesPicked ? "fetchDeselectAll" : "fetchSelectAll")
1692
- })
1693
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
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: (candidates ?? []).map((candidate) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", {
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.set` under the reference the profile records, exactly as
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, api, t } = props;
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 response = await api.settings.mutate({
1796
- ns: NS,
1797
- ops: [{
1798
- op: "set",
1799
- path: ["providers", route],
1800
- value: profile
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 api.credentials.set({
1809
- ref: keyRef,
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: "https://gateway.example/v1",
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
- api,
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
- submitLabel: "create",
1970
- submitBusyLabel: "creating",
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.set`
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, api, t } = props;
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
- api.credentials.describe({ refs: [keyRef] }).then((response) => {
2085
- if (stale || !response.result.ok) return;
2086
- setKeyState(response.result.value.credentials[keyRef]);
2087
- }, () => void 0);
2139
+ operations.describeCredential(keyRef).then((described) => {
2140
+ if (stale) return;
2141
+ setKeyState(described);
2142
+ });
2088
2143
  return () => {
2089
2144
  stale = true;
2090
2145
  };
2091
- }, [api.credentials, keyRef]);
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 response = await api.settings.mutate({
2140
- ns,
2141
- ops,
2142
- expectedRevision
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 api.credentials.set({
2151
- ref: keyRef,
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.jsx)("p", {
2220
+ if (node === void 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
2175
2221
  className: ModelsSection_module_default["error"],
2176
- children: `${props.provider}: unresolvable settings path`
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
- api
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
- submitLabel: props.submitLabel ?? "apply",
2350
- submitBusyLabel: props.submitBusyLabel ?? "applying",
2351
- ...props.cancelLabel === void 0 ? {} : { cancelLabel: props.cancelLabel },
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.1-rc.2.
2369
- * Only difference vs upstream: the h2 title row carries an adapter-version
2370
- * badge. Everything else is upstream verbatim — keep this file minimal when
2371
- * merging drift after a host upgrade.
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 api - settings and credential wire faces.
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(api, controller, target) {
2407
- try {
2408
- if (target.credentialRef !== void 0) {
2409
- const credential = await api.credentials.unset({ ref: target.credentialRef });
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, api, schema, t } = props;
2466
- if (controller === void 0 || useSnapshot === void 0 || api === void 0 || schema === void 0 || t === void 0) return null;
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
- api,
2522
+ operations,
2471
2523
  schema,
2472
2524
  t
2473
2525
  } });
2474
2526
  }
2475
2527
  function Loaded({ injected }) {
2476
- const { controller, api, schema, t } = injected;
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(api, controller, deleteTarget).then((failure) => {
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
- api,
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
- api,
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
- api,
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
- api,
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 controller = new ModelsSettingsStore(connection.api, schema, ctx.settingsScope.describe());
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
- api: connection.api,
2940
+ operations,
2838
2941
  schema,
2839
2942
  t
2840
2943
  });