@qilin-agent/client-ui-settings-models 3.1.6 → 3.1.8

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
@@ -55,7 +55,7 @@ window.__ModuleLoader__.load({
55
55
  }
56
56
  //#endregion
57
57
  //#region \0qilin-css:/home/runner/work/QiLin/QiLin/packages/client/ui-settings-models/src/client/ModelsSection.module.css.mjs
58
- const css$2 = ".PF5DZW_section{color:var(--qilin-alias-label-primary);flex-direction:column;gap:12px;display:flex}.PF5DZW_title{color:var(--qilin-alias-label-primary);margin:0;font-size:16px;font-weight:500;line-height:24px}.PF5DZW_intro{color:var(--qilin-alias-label-tertiary);margin:0;font-size:14px;line-height:22px}.PF5DZW_notice{color:var(--qilin-alias-state-warn-label);margin:0;font-size:12px;line-height:18px}.PF5DZW_savedNotice{color:var(--qilin-alias-state-success-primary);margin:0;font-size:12px;line-height:18px}.PF5DZW_rows{flex-direction:column;gap:8px;margin:12px 0 0;padding:0;list-style:none;display:flex}.PF5DZW_rowCard{border:.5px solid var(--qilin-alias-border-l4);border-radius:16px;flex-direction:column;gap:12px;padding:12px 14px;display:flex}.PF5DZW_rowHead{align-items:center;gap:10px;display:flex}.PF5DZW_rowIdentity{align-items:center;gap:6px;min-width:0;display:inline-flex}.PF5DZW_rowName{color:var(--qilin-alias-label-primary);font-size:14px;font-weight:500;line-height:22px}.PF5DZW_rowTag{border:.5px solid var(--qilin-alias-border-l3);color:var(--qilin-alias-label-secondary);border-radius:4px;flex:none;padding:1px 6px;font-size:11px;line-height:16px}.PF5DZW_credentialDot{box-sizing:border-box;corner-shape:round;border-radius:50%;flex:none;width:8px;height:8px;display:inline-block}.PF5DZW_credentialDotConfigured{background:var(--qilin-alias-state-success-primary)}.PF5DZW_credentialDotMissing{background:var(--qilin-alias-state-error-primary)}.PF5DZW_rowActions{align-items:center;gap:4px;margin-left:auto;display:inline-flex}.PF5DZW_primaryButton,.PF5DZW_secondaryButton,.PF5DZW_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}.PF5DZW_primaryButton{background:var(--qilin-alias-button-primary-fill);color:var(--qilin-alias-label-primary-foreground)}.PF5DZW_primaryButton:hover:not(:disabled){background:var(--qilin-alias-button-primary-hover)}.PF5DZW_secondaryButton,.PF5DZW_addButton{border:.5px solid var(--qilin-alias-border-l3);color:var(--qilin-alias-label-primary);background:0 0}.PF5DZW_secondaryButton:hover:not(:disabled),.PF5DZW_addButton:hover:not(:disabled){background:var(--qilin-alias-interactive-bg-hover)}.PF5DZW_secondaryButton:hover:not(:disabled){background:var(--qilin-alias-interactive-bg-hover-solid)}.PF5DZW_dangerButton{box-sizing:border-box;height:36px;color:var(--qilin-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}.PF5DZW_dangerButton:hover:not(:disabled){background:var(--qilin-alias-interactive-bg-hover-danger)}.PF5DZW_rowActions .PF5DZW_secondaryButton,.PF5DZW_rowActions .PF5DZW_dangerButton{border-radius:14px;height:28px;padding:0 10px;font-size:12px;line-height:18px}.PF5DZW_primaryButton:disabled,.PF5DZW_secondaryButton:disabled,.PF5DZW_dangerButton:disabled,.PF5DZW_addButton:disabled,.PF5DZW_linkButton:disabled,.PF5DZW_addModelButton:disabled{opacity:.4;cursor:default}.PF5DZW_primaryButton:focus-visible,.PF5DZW_secondaryButton:focus-visible,.PF5DZW_dangerButton:focus-visible,.PF5DZW_addButton:focus-visible,.PF5DZW_linkButton:focus-visible,.PF5DZW_addModelButton:focus-visible,.PF5DZW_iconButton:focus-visible,.PF5DZW_customizedSummary:focus-visible{box-shadow:0 0 0 2px var(--qilin-focus-ring-color,var(--qilin-alias-state-business-primary));outline:none}.PF5DZW_editor{background:var(--qilin-alias-bg-module-platform);border-radius:12px;flex-direction:column;gap:14px;padding:14px 16px;display:flex}.PF5DZW_editorHeader{align-items:baseline;gap:8px;display:flex}.PF5DZW_editorTitle{color:var(--qilin-alias-label-primary);font-size:14px;font-weight:500;line-height:22px}.PF5DZW_editorRoute{color:var(--qilin-alias-label-tertiary);font-size:12px;line-height:18px}.PF5DZW_field{flex-direction:column;gap:6px;display:flex}.PF5DZW_fieldLabel{color:var(--qilin-alias-label-secondary);align-items:center;gap:10px;font-size:12px;font-weight:500;line-height:18px;display:inline-flex}.PF5DZW_helpButton{border:.5px solid var(--qilin-alias-border-l3);corner-shape:round;width:16px;height:16px;color:var(--qilin-alias-label-tertiary);font:inherit;text-align:center;cursor:help;background:0 0;border-radius:50%;padding:0;font-size:11px;line-height:15px}.PF5DZW_helpButton:hover,.PF5DZW_helpButton:focus-visible{color:var(--qilin-alias-label-primary);border-color:var(--qilin-alias-label-tertiary)}.PF5DZW_linkButton{box-sizing:border-box;height:28px;color:var(--qilin-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}.PF5DZW_linkButton:hover:not(:disabled){background:var(--qilin-alias-interactive-bg-hover);color:var(--qilin-alias-label-secondary)}.PF5DZW_advancedHint{color:var(--qilin-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}.PF5DZW_editorActions{justify-content:flex-end;gap:8px;display:flex}.PF5DZW_addBlock{flex-direction:column;gap:12px;display:flex}.PF5DZW_addActions{flex-wrap:wrap;gap:10px;display:flex}.PF5DZW_addButton{border:1px dashed var(--qilin-alias-border-l3);border-radius:16px;flex:1 1 0;gap:6px;min-width:180px;height:44px}.PF5DZW_addCard,.PF5DZW_setupCard{background:var(--qilin-alias-bg-module-platform);border-radius:12px;flex-direction:column;gap:14px;padding:14px 16px;list-style:none;display:flex}.PF5DZW_addCard .PF5DZW_editor,.PF5DZW_setupCard .PF5DZW_editor{background:0 0;padding:0}.PF5DZW_customized{border-top:.5px solid var(--qilin-alias-border-l2);padding-top:10px}.PF5DZW_customizedSummary{cursor:pointer;width:fit-content;color:var(--qilin-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}.PF5DZW_customizedSummary::-webkit-details-marker{display:none}.PF5DZW_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)}.PF5DZW_customized[open]>.PF5DZW_customizedSummary:before{transform:rotate(45deg)translate(-1px,-1px)}.PF5DZW_customizedSummary:hover{color:var(--qilin-alias-label-primary)}.PF5DZW_customizedBody{flex-direction:column;gap:12px;padding-top:12px;display:flex}.PF5DZW_modelCatalog{border-top:.5px solid var(--qilin-alias-border-l2);flex-direction:column;gap:10px;padding-top:12px;display:flex}.PF5DZW_modelCatalogHeading{flex-direction:column;gap:2px;display:flex}.PF5DZW_modelCatalogTitle{color:var(--qilin-alias-label-secondary);font-size:12px;font-weight:500;line-height:18px}.PF5DZW_modelCatalogMeta,.PF5DZW_modelEmpty{color:var(--qilin-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}.PF5DZW_modelList{flex-direction:column;gap:8px;display:flex}.PF5DZW_modelListHead{justify-content:space-between;align-items:flex-start;gap:12px;display:flex}.PF5DZW_modelEntry{border:.5px solid var(--qilin-alias-border-l4);border-radius:10px;padding:6px}.PF5DZW_modelRow{grid-template-columns:minmax(0,1.4fr) minmax(0,1fr) auto auto;align-items:center;gap:6px;display:grid}.PF5DZW_iconButton{box-sizing:border-box;width:28px;height:28px;color:var(--qilin-alias-label-tertiary);cursor:pointer;background:0 0;border:none;border-radius:6px;justify-content:center;align-items:center;display:inline-flex}.PF5DZW_iconButton:hover:not(:disabled){background:var(--qilin-alias-interactive-bg-hover);color:var(--qilin-alias-label-primary)}.PF5DZW_iconButton:disabled{cursor:default;opacity:.4}.PF5DZW_iconButtonDanger:hover:not(:disabled){background:var(--qilin-alias-interactive-bg-hover-danger);color:var(--qilin-alias-state-error-primary)}.PF5DZW_modelAdvanced{grid-template-columns:repeat(2,minmax(0,1fr));gap:8px;padding:8px 4px 2px;display:grid}.PF5DZW_modelField{flex-direction:column;gap:4px;min-width:0;display:flex}.PF5DZW_modelInputTypes{border:none;grid-column:1/-1;min-width:0;margin:0;padding:0}.PF5DZW_modelInputTypes legend{margin-bottom:4px;padding:0}.PF5DZW_modelInputChoices{flex-wrap:wrap;align-items:center;gap:16px;min-height:32px;display:flex}.PF5DZW_modelFieldLabel{color:var(--qilin-alias-label-tertiary);font-size:12px;line-height:18px}.PF5DZW_modelReasoning{flex-direction:column;grid-column:1/-1;gap:6px;min-width:0;display:flex}.PF5DZW_modelReasoningLabel{align-items:center;gap:6px;display:inline-flex}.PF5DZW_modelReasoningHead{justify-content:space-between;align-items:center;gap:8px;display:flex}.PF5DZW_modelReasoningRow{grid-template-columns:minmax(0,1fr) minmax(0,1fr) auto;align-items:center;gap:6px;display:grid}.PF5DZW_modelReasoningRow .PF5DZW_selectInput{max-width:none}.PF5DZW_modelReasoningValueInput{font-family:var(--ds-font-family-code);font-size:13px}.PF5DZW_modelEmpty{border:1px dashed var(--qilin-alias-border-l3);text-align:center;border-radius:8px;padding:12px}.PF5DZW_addModelButton{box-sizing:border-box;border:.5px solid var(--qilin-alias-border-l3);height:28px;color:var(--qilin-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}.PF5DZW_addModelButton:hover:not(:disabled){background:var(--qilin-alias-interactive-bg-hover)}.PF5DZW_input{box-sizing:border-box;border:.5px solid var(--qilin-alias-border-l4);width:100%;height:32px;font:inherit;background:var(--qilin-alias-bg-layer-1);color:var(--qilin-alias-label-primary);border-radius:8px;padding:0 10px;font-size:14px;line-height:22px}select.PF5DZW_input{cursor:pointer;max-width:240px}.PF5DZW_input:focus{border-color:var(--qilin-alias-state-business-primary);outline:none}.PF5DZW_input::placeholder{color:var(--qilin-alias-label-dimmed)}.PF5DZW_input:disabled{opacity:.6;cursor:default}.PF5DZW_keyInput{position:relative}.PF5DZW_keyInputFilled{padding-right:40px}.PF5DZW_keyToggle{border-radius:var(--qilin-radius-md);width:32px;color:var(--qilin-alias-label-secondary);cursor:pointer;background:0 0;border:none;justify-content:center;align-items:center;padding:0;display:inline-flex;position:absolute;inset:1px 1px 1px auto}.PF5DZW_keyToggle:hover:not(:disabled){color:var(--qilin-alias-label-primary)}.PF5DZW_keyToggle:focus-visible{outline:var(--qilin-focus-ring-width) solid var(--qilin-focus-ring-color,var(--qilin-alias-state-business-primary));outline-offset:-2px}.PF5DZW_keyToggle:disabled{opacity:.6;cursor:default}.PF5DZW_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}.PF5DZW_error{color:var(--qilin-alias-state-error-primary);margin:0;font-size:12px;line-height:18px}.PF5DZW_deleteDialog{width:min(480px,100%)}.PF5DZW_deleteConfirm:not(:disabled){border-color:var(--qilin-alias-state-error-primary);color:var(--qilin-alias-state-error-primary)}.PF5DZW_deleteConfirm:hover:not(:disabled){background:var(--qilin-alias-interactive-bg-hover-danger)}.PF5DZW_hiddenLabel{clip:rect(0 0 0 0);white-space:nowrap;width:1px;height:1px;position:absolute;overflow:hidden}@media (prefers-reduced-motion:reduce){.PF5DZW_customizedSummary:before,.PF5DZW_switchThumb{transition:none}}.PF5DZW_fetchDialog{--qilin-scrollbar-thumb:var(--qilin-alias-scrollbar-bg-l2);--qilin-scrollbar-thumb-hover:var(--qilin-alias-scrollbar-hover-l2);max-width:520px}.PF5DZW_candidateToolbar{align-items:center;gap:8px;margin-bottom:6px;display:flex}.PF5DZW_candidateSearch{flex:240px;min-width:0}.PF5DZW_candidateList{flex-direction:column;gap:2px;max-height:320px;margin:0;padding:0;list-style:none;display:flex;overflow-y:auto}.PF5DZW_candidate{border-radius:6px}.PF5DZW_candidateLabel{cursor:pointer;align-items:center;gap:8px;padding:6px 8px;display:flex}.PF5DZW_candidateId{font-family:var(--ds-font-family-code);overflow-wrap:anywhere;flex:auto;font-size:13px}.PF5DZW_candidateEmpty{color:var(--qilin-alias-label-secondary);text-align:center;margin:24px 0;font-size:13px;line-height:20px}";
58
+ const css$2 = ".PF5DZW_section{color:var(--qilin-alias-label-primary);flex-direction:column;gap:12px;display:flex}.PF5DZW_title{color:var(--qilin-alias-label-primary);margin:0;font-size:16px;font-weight:500;line-height:24px}.PF5DZW_intro{color:var(--qilin-alias-label-tertiary);margin:0;font-size:14px;line-height:22px}.PF5DZW_notice{color:var(--qilin-alias-state-warn-label);margin:0;font-size:12px;line-height:18px}.PF5DZW_savedNotice{color:var(--qilin-alias-state-success-primary);margin:0;font-size:12px;line-height:18px}.PF5DZW_rows{flex-direction:column;gap:8px;margin:12px 0 0;padding:0;list-style:none;display:flex}.PF5DZW_rowCard{border:1px solid var(--qilin-alias-border-l4);border-radius:16px;flex-direction:column;gap:12px;padding:12px 14px;display:flex}.PF5DZW_rowHead{align-items:center;gap:10px;display:flex}.PF5DZW_rowIdentity{align-items:center;gap:6px;min-width:0;display:inline-flex}.PF5DZW_rowName{color:var(--qilin-alias-label-primary);font-size:14px;font-weight:500;line-height:22px}.PF5DZW_rowTag{border:1px solid var(--qilin-alias-border-l3);color:var(--qilin-alias-label-secondary);border-radius:4px;flex:none;padding:1px 6px;font-size:11px;line-height:16px}.PF5DZW_credentialDot{box-sizing:border-box;corner-shape:round;border-radius:50%;flex:none;width:8px;height:8px;display:inline-block}.PF5DZW_credentialDotConfigured{background:var(--qilin-alias-state-success-primary)}.PF5DZW_credentialDotMissing{background:var(--qilin-alias-state-error-primary)}.PF5DZW_rowActions{align-items:center;gap:4px;margin-left:auto;display:inline-flex}.PF5DZW_primaryButton,.PF5DZW_secondaryButton,.PF5DZW_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}.PF5DZW_primaryButton{background:var(--qilin-alias-button-primary-fill);color:var(--qilin-alias-label-primary-foreground)}.PF5DZW_primaryButton:hover:not(:disabled){background:var(--qilin-alias-button-primary-hover)}.PF5DZW_secondaryButton,.PF5DZW_addButton{border:1px solid var(--qilin-alias-border-l3);color:var(--qilin-alias-label-primary);background:0 0}.PF5DZW_secondaryButton:hover:not(:disabled),.PF5DZW_addButton:hover:not(:disabled){background:var(--qilin-alias-interactive-bg-hover)}.PF5DZW_secondaryButton:hover:not(:disabled){background:var(--qilin-alias-interactive-bg-hover-solid)}.PF5DZW_dangerButton{box-sizing:border-box;height:36px;color:var(--qilin-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}.PF5DZW_dangerButton:hover:not(:disabled){background:var(--qilin-alias-interactive-bg-hover-danger)}.PF5DZW_rowActions .PF5DZW_secondaryButton,.PF5DZW_rowActions .PF5DZW_dangerButton{border-radius:14px;height:28px;padding:0 10px;font-size:12px;line-height:18px}.PF5DZW_primaryButton:disabled,.PF5DZW_secondaryButton:disabled,.PF5DZW_dangerButton:disabled,.PF5DZW_addButton:disabled,.PF5DZW_linkButton:disabled,.PF5DZW_addModelButton:disabled{opacity:.4;cursor:default}.PF5DZW_primaryButton:focus-visible,.PF5DZW_secondaryButton:focus-visible,.PF5DZW_dangerButton:focus-visible,.PF5DZW_addButton:focus-visible,.PF5DZW_linkButton:focus-visible,.PF5DZW_addModelButton:focus-visible,.PF5DZW_iconButton:focus-visible,.PF5DZW_customizedSummary:focus-visible{box-shadow:0 0 0 2px var(--qilin-focus-ring-color,var(--qilin-alias-state-business-primary));outline:none}.PF5DZW_editor{background:var(--qilin-alias-bg-module-platform);border-radius:12px;flex-direction:column;gap:14px;padding:14px 16px;display:flex}.PF5DZW_editorHeader{align-items:baseline;gap:8px;display:flex}.PF5DZW_editorTitle{color:var(--qilin-alias-label-primary);font-size:14px;font-weight:500;line-height:22px}.PF5DZW_editorRoute{color:var(--qilin-alias-label-tertiary);font-size:12px;line-height:18px}.PF5DZW_field{flex-direction:column;gap:6px;display:flex}.PF5DZW_fieldLabel{color:var(--qilin-alias-label-secondary);align-items:center;gap:10px;font-size:12px;font-weight:500;line-height:18px;display:inline-flex}.PF5DZW_helpButton{border:1px solid var(--qilin-alias-border-l3);corner-shape:round;width:16px;height:16px;color:var(--qilin-alias-label-tertiary);font:inherit;text-align:center;cursor:help;background:0 0;border-radius:50%;padding:0;font-size:11px;line-height:15px}.PF5DZW_helpButton:hover,.PF5DZW_helpButton:focus-visible{color:var(--qilin-alias-label-primary);border-color:var(--qilin-alias-label-tertiary)}.PF5DZW_linkButton{box-sizing:border-box;height:28px;color:var(--qilin-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}.PF5DZW_linkButton:hover:not(:disabled){background:var(--qilin-alias-interactive-bg-hover);color:var(--qilin-alias-label-secondary)}.PF5DZW_advancedHint{color:var(--qilin-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}.PF5DZW_editorActions{justify-content:flex-end;gap:8px;display:flex}.PF5DZW_addBlock{flex-direction:column;gap:12px;display:flex}.PF5DZW_addActions{flex-wrap:wrap;gap:10px;display:flex}.PF5DZW_addButton{border:1px dashed var(--qilin-alias-border-l3);border-radius:16px;flex:1 1 0;gap:6px;min-width:180px;height:44px}.PF5DZW_addCard,.PF5DZW_setupCard{background:var(--qilin-alias-bg-module-platform);border-radius:12px;flex-direction:column;gap:14px;padding:14px 16px;list-style:none;display:flex}.PF5DZW_addCard .PF5DZW_editor,.PF5DZW_setupCard .PF5DZW_editor{background:0 0;padding:0}.PF5DZW_customized{border-top:1px solid var(--qilin-alias-border-l2);padding-top:10px}.PF5DZW_customizedSummary{cursor:pointer;width:fit-content;color:var(--qilin-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}.PF5DZW_customizedSummary::-webkit-details-marker{display:none}.PF5DZW_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)}.PF5DZW_customized[open]>.PF5DZW_customizedSummary:before{transform:rotate(45deg)translate(-1px,-1px)}.PF5DZW_customizedSummary:hover{color:var(--qilin-alias-label-primary)}.PF5DZW_customizedBody{flex-direction:column;gap:12px;padding-top:12px;display:flex}.PF5DZW_modelCatalog{border-top:1px solid var(--qilin-alias-border-l2);flex-direction:column;gap:10px;padding-top:12px;display:flex;position:relative}.PF5DZW_modelCatalogHeading{flex-direction:column;gap:2px;display:flex}.PF5DZW_modelCatalogTitle{color:var(--qilin-alias-label-secondary);font-size:12px;font-weight:500;line-height:18px}.PF5DZW_modelCatalogMeta,.PF5DZW_modelEmpty{color:var(--qilin-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}.PF5DZW_modelList{flex-direction:column;gap:8px;display:flex}.PF5DZW_modelListHead{justify-content:space-between;align-items:flex-start;gap:12px;display:flex}.PF5DZW_modelEntry{border:1px solid var(--qilin-alias-border-l4);border-radius:10px;padding:6px;position:relative;container:PF5DZW_model-row/inline-size}.PF5DZW_modelRow{grid-template-columns:auto minmax(0,1.4fr) minmax(0,1fr) auto auto;align-items:center;gap:6px;display:grid}@container PF5DZW_model-row (width<=440px){.PF5DZW_modelRow{grid-template-columns:auto minmax(0,1fr) auto auto}.PF5DZW_modelRow>input:first-of-type{grid-area:1/2}.PF5DZW_modelRow>input:nth-of-type(2){grid-area:2/2/auto/-1}}.PF5DZW_modelDragHandle:not(:disabled){cursor:grab}.PF5DZW_modelEntry[data-dragging]{opacity:.5}.PF5DZW_modelDragPreview{background:var(--qilin-alias-bg-module-platform)}.PF5DZW_modelEntry:before,.PF5DZW_modelEntry:after{content:\"\";z-index:1;height:4px;position:absolute;left:0;right:0}.PF5DZW_modelEntry:before{top:-4px}.PF5DZW_modelEntry:after{bottom:-4px}.PF5DZW_modelEntry[data-drop-target=before]:before,.PF5DZW_modelEntry[data-drop-target=after]:after{background:linear-gradient(55deg, transparent calc(50% - 1px), var(--qilin-alias-state-business-primary) calc(50% - 1px) calc(50% + 1px), transparent calc(50% + 1px)) 0 0 / 5px 7px no-repeat, linear-gradient(125deg, transparent calc(50% - 1px), var(--qilin-alias-state-business-primary) calc(50% - 1px) calc(50% + 1px), transparent calc(50% + 1px)) 0 5px / 5px 7px no-repeat, linear-gradient(var(--qilin-alias-state-business-primary) 0 0) 4px 5px / calc(100% - 4px) 2px no-repeat;height:12px}.PF5DZW_modelEntry[data-drop-target=before]:before{top:-10px}.PF5DZW_modelEntry[data-drop-target=after]:after{bottom:-10px}.PF5DZW_iconButton{box-sizing:border-box;width:28px;height:28px;color:var(--qilin-alias-label-tertiary);cursor:pointer;background:0 0;border:none;border-radius:6px;justify-content:center;align-items:center;display:inline-flex}.PF5DZW_iconButton:hover:not(:disabled){background:var(--qilin-alias-interactive-bg-hover);color:var(--qilin-alias-label-primary)}.PF5DZW_iconButton:disabled{cursor:default;opacity:.4}.PF5DZW_iconButtonDanger:hover:not(:disabled){background:var(--qilin-alias-interactive-bg-hover-danger);color:var(--qilin-alias-state-error-primary)}.PF5DZW_modelAdvanced{grid-template-columns:repeat(2,minmax(0,1fr));gap:8px;padding:8px 4px 2px;display:grid}.PF5DZW_modelField{flex-direction:column;gap:4px;min-width:0;display:flex}.PF5DZW_modelInputTypes{border:none;grid-column:1/-1;min-width:0;margin:0;padding:0}.PF5DZW_modelInputTypes legend{margin-bottom:4px;padding:0}.PF5DZW_modelInputChoices{flex-wrap:wrap;align-items:center;gap:16px;min-height:32px;display:flex}.PF5DZW_modelFieldLabel{color:var(--qilin-alias-label-tertiary);font-size:12px;line-height:18px}.PF5DZW_modelReasoning{flex-direction:column;grid-column:1/-1;gap:6px;min-width:0;display:flex}.PF5DZW_modelReasoningLabel{align-items:center;gap:6px;display:inline-flex}.PF5DZW_modelReasoningHead{justify-content:space-between;align-items:center;gap:8px;display:flex}.PF5DZW_modelReasoningRow{grid-template-columns:minmax(0,1fr) minmax(0,1fr) auto;align-items:center;gap:6px;display:grid}.PF5DZW_modelReasoningRow .PF5DZW_selectInput{max-width:none}.PF5DZW_modelReasoningValueInput{font-family:var(--ds-font-family-code);font-size:13px}.PF5DZW_modelEmpty{border:1px dashed var(--qilin-alias-border-l3);text-align:center;border-radius:8px;padding:12px}.PF5DZW_addModelButton{box-sizing:border-box;border:1px solid var(--qilin-alias-border-l3);height:28px;color:var(--qilin-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}.PF5DZW_addModelButton:hover:not(:disabled){background:var(--qilin-alias-interactive-bg-hover)}.PF5DZW_input{box-sizing:border-box;border:1px solid var(--qilin-alias-border-l4);width:100%;height:32px;font:inherit;background:var(--qilin-alias-bg-layer-1);color:var(--qilin-alias-label-primary);border-radius:8px;padding:0 10px;font-size:14px;line-height:22px}select.PF5DZW_input{cursor:pointer;max-width:240px}.PF5DZW_input:focus{border-color:var(--qilin-alias-state-business-primary);outline:none}.PF5DZW_input::placeholder{color:var(--qilin-alias-label-dimmed)}.PF5DZW_input:disabled{opacity:.6;cursor:default}.PF5DZW_keyInput{position:relative}.PF5DZW_keyInputFilled{padding-right:40px}.PF5DZW_keyToggle{border-radius:var(--qilin-radius-md);width:32px;color:var(--qilin-alias-label-secondary);cursor:pointer;background:0 0;border:none;justify-content:center;align-items:center;padding:0;display:inline-flex;position:absolute;inset:1px 1px 1px auto}.PF5DZW_keyToggle:hover:not(:disabled){color:var(--qilin-alias-label-primary)}.PF5DZW_keyToggle:focus-visible{outline:var(--qilin-focus-ring-width) solid var(--qilin-focus-ring-color,var(--qilin-alias-state-business-primary));outline-offset:-2px}.PF5DZW_keyToggle:disabled{opacity:.6;cursor:default}.PF5DZW_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}.PF5DZW_error{color:var(--qilin-alias-state-error-primary);margin:0;font-size:12px;line-height:18px}.PF5DZW_deleteDialog{width:min(480px,100%)}.PF5DZW_deleteConfirm:not(:disabled){border-color:var(--qilin-alias-state-error-primary);color:var(--qilin-alias-state-error-primary)}.PF5DZW_deleteConfirm:hover:not(:disabled){background:var(--qilin-alias-interactive-bg-hover-danger)}.PF5DZW_hiddenLabel{clip:rect(0 0 0 0);white-space:nowrap;width:1px;height:1px;position:absolute;overflow:hidden}@media (prefers-reduced-motion:reduce){.PF5DZW_customizedSummary:before,.PF5DZW_switchThumb{transition:none}}.PF5DZW_fetchDialog{--qilin-scrollbar-thumb:var(--qilin-alias-scrollbar-bg-l2);--qilin-scrollbar-thumb-hover:var(--qilin-alias-scrollbar-hover-l2);max-width:520px}.PF5DZW_candidateToolbar{align-items:center;gap:8px;margin-bottom:6px;display:flex}.PF5DZW_candidateSearch{flex:240px;min-width:0}.PF5DZW_candidateList{flex-direction:column;gap:2px;max-height:320px;margin:0;padding:0;list-style:none;display:flex;overflow-y:auto}.PF5DZW_candidate{border-radius:6px}.PF5DZW_candidateLabel{cursor:pointer;align-items:center;gap:8px;padding:6px 8px;display:flex}.PF5DZW_candidateId{font-family:var(--ds-font-family-code);overflow-wrap:anywhere;flex:auto;font-size:13px}.PF5DZW_candidateEmpty{color:var(--qilin-alias-label-secondary);text-align:center;margin:24px 0;font-size:13px;line-height:20px}";
59
59
  const tagId$2 = "@qilin-agent/client-ui-settings-models/ModelsSection.module.css";
60
60
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$2) + "]") === null) {
61
61
  const tag = document.createElement("style");
@@ -106,11 +106,14 @@ window.__ModuleLoader__.load({
106
106
  "keyInputFilled": "PF5DZW_keyInputFilled",
107
107
  "keyToggle": "PF5DZW_keyToggle",
108
108
  "linkButton": "PF5DZW_linkButton",
109
+ "model-row": "PF5DZW_model-row",
109
110
  "modelAdvanced": "PF5DZW_modelAdvanced",
110
111
  "modelCatalog": "PF5DZW_modelCatalog",
111
112
  "modelCatalogHeading": "PF5DZW_modelCatalogHeading",
112
113
  "modelCatalogMeta": "PF5DZW_modelCatalogMeta",
113
114
  "modelCatalogTitle": "PF5DZW_modelCatalogTitle",
115
+ "modelDragHandle": "PF5DZW_modelDragHandle",
116
+ "modelDragPreview": "PF5DZW_modelDragPreview",
114
117
  "modelEmpty": "PF5DZW_modelEmpty",
115
118
  "modelEntry": "PF5DZW_modelEntry",
116
119
  "modelField": "PF5DZW_modelField",
@@ -475,6 +478,10 @@ window.__ModuleLoader__.load({
475
478
  }
476
479
  //#endregion
477
480
  //#region lib/types/client/ModelRow.js
481
+ function rowHalf(event) {
482
+ const rect = event.currentTarget.getBoundingClientRect();
483
+ return event.clientY < rect.top + rect.height / 2 ? "before" : "after";
484
+ }
478
485
  /**
479
486
  * Render consistent model identity, capacity, and input-type controls.
480
487
  * @param props - drafted fields and their owning editor's actions.
@@ -482,11 +489,58 @@ window.__ModuleLoader__.load({
482
489
  */
483
490
  function ModelRow(props) {
484
491
  const { model, position, t, disabled } = props;
492
+ const preview = (0, _qilin_agent_client_ui_primitives.useRowDragPreview)(ModelsSection_module_css_default["modelDragPreview"]);
485
493
  return (0, react_jsx_runtime.jsxs)("div", {
486
494
  className: ModelsSection_module_css_default["modelEntry"],
495
+ "data-row-key": props.rowKey,
496
+ "data-dragging": props.order.dragging || void 0,
497
+ "data-drop-target": props.order.dragging ? void 0 : props.order.target,
498
+ onDragOver: (event) => {
499
+ if (!props.order.canDrop) return;
500
+ event.preventDefault();
501
+ event.dataTransfer.dropEffect = "move";
502
+ props.order.onOver(rowHalf(event));
503
+ },
504
+ onDragLeave: (event) => {
505
+ if (event.relatedTarget instanceof Node && event.currentTarget.contains(event.relatedTarget)) return;
506
+ props.order.onLeave();
507
+ },
508
+ onDrop: (event) => {
509
+ if (!props.order.canDrop) return;
510
+ event.preventDefault();
511
+ props.order.onDrop(rowHalf(event));
512
+ },
487
513
  children: [(0, react_jsx_runtime.jsxs)("div", {
488
514
  className: ModelsSection_module_css_default["modelRow"],
489
515
  children: [
516
+ (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.Tooltip, {
517
+ label: t("reorderModelHelp"),
518
+ children: (0, react_jsx_runtime.jsx)("button", {
519
+ type: "button",
520
+ className: `${ModelsSection_module_css_default["iconButton"]} ${ModelsSection_module_css_default["modelDragHandle"]}`,
521
+ "aria-label": `${t("reorderModel")} ${String(position)}`,
522
+ "aria-keyshortcuts": "ArrowUp ArrowDown",
523
+ "aria-description": t("reorderModelHelp"),
524
+ disabled,
525
+ draggable: !disabled,
526
+ onDragStart: (event) => {
527
+ event.dataTransfer.effectAllowed = "move";
528
+ event.dataTransfer.setData("application/x-qilin-model-order", String(position));
529
+ props.order.onStart();
530
+ preview.start(event, event.currentTarget.closest("[data-row-key]"));
531
+ },
532
+ onDragEnd: () => {
533
+ if (preview.clear()) props.order.onEnd();
534
+ },
535
+ onKeyDown: (event) => {
536
+ if (event.key !== "ArrowUp" && event.key !== "ArrowDown") return;
537
+ event.preventDefault();
538
+ event.stopPropagation();
539
+ props.order.onMove(event.key === "ArrowUp" ? -1 : 1);
540
+ },
541
+ children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconDragHandleOutlineRegular, { size: 14 })
542
+ })
543
+ }),
490
544
  ["id", "name"].map((field) => (0, react_jsx_runtime.jsx)("input", {
491
545
  className: ModelsSection_module_css_default["input"],
492
546
  type: "text",
@@ -507,7 +561,7 @@ window.__ModuleLoader__.load({
507
561
  "aria-expanded": props.expanded,
508
562
  title: t("modelAdvanced"),
509
563
  onClick: props.onToggle,
510
- children: props.expanded ? (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconChevronDownOutline14, {}) : (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconChevronRightOutline14, {})
564
+ children: props.expanded ? (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconChevronDownOutlineRegular, {}) : (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconChevronRightOutlineRegular, {})
511
565
  }),
512
566
  (0, react_jsx_runtime.jsx)("button", {
513
567
  type: "button",
@@ -516,7 +570,7 @@ window.__ModuleLoader__.load({
516
570
  title: t("removeModel"),
517
571
  disabled,
518
572
  onClick: props.onRemove,
519
- children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconTrashOutline16, { size: 14 })
573
+ children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconTrashOutlineRegular, { size: 14 })
520
574
  })
521
575
  ]
522
576
  }), props.expanded ? (0, react_jsx_runtime.jsxs)("div", {
@@ -563,17 +617,108 @@ window.__ModuleLoader__.load({
563
617
  });
564
618
  }
565
619
  //#endregion
566
- //#region lib/types/client/DeepSeekModelsEditor.js
620
+ //#region lib/types/client/useModelRows.js
621
+ /** Local model-row identities, disclosures, capacity text, and draft ordering. */
622
+ /** One editor-local identity; editing a model ID never replaces its controls. */
623
+ function createRow(key) {
624
+ return {
625
+ key,
626
+ expanded: false,
627
+ editing: /* @__PURE__ */ new Map()
628
+ };
629
+ }
567
630
  /**
568
- * Curated editor for the direct DeepSeek adapter's advisory model catalog.
569
- * The settings layer replaces `models` as one array, so the parent supplies
570
- * the effective inherited rows until the first edit materializes a user
571
- * override; reset removes that override instead of copying defaults into it.
631
+ * Keep row state with its model through draft moves and removals.
632
+ * @param models - current draft array, owned by the provider card.
633
+ * @param onChange - replaces only that card's draft array.
634
+ * @param disabled - prevents reordering while the card cannot be edited.
635
+ * @returns row state and local editing and ordering actions.
572
636
  */
573
- /** Row index encoded in an editing-buffer key. */
574
- function rowOf(key) {
575
- return Number(key.slice(0, key.indexOf(":")));
637
+ function useModelRows(models, onChange, disabled) {
638
+ const nextKey = (0, react.useRef)(0);
639
+ const [stored, setRows] = (0, react.useState)(() => models.map(() => createRow(nextKey.current++)));
640
+ const [dragged, setDragged] = (0, react.useState)();
641
+ const [target, setTarget] = (0, react.useState)();
642
+ const entries = models.map((model, index) => ({
643
+ model,
644
+ state: stored[index] ?? createRow(nextKey.current++)
645
+ }));
646
+ const rows = entries.map((entry) => entry.state);
647
+ if (stored.length !== models.length) setRows(rows);
648
+ const endDrag = () => {
649
+ setDragged(void 0);
650
+ setTarget(void 0);
651
+ };
652
+ const move = (from, to) => {
653
+ if (disabled || from === to || from < 0 || to < 0 || to >= models.length) return;
654
+ const order = [...entries];
655
+ const moved = order.splice(from, 1);
656
+ order.splice(to, 0, ...moved);
657
+ setRows(order.map((entry) => entry.state));
658
+ onChange(order.map((entry) => entry.model));
659
+ };
660
+ return {
661
+ rows: entries.map(({ model, state }, index) => ({
662
+ ...state,
663
+ model,
664
+ order: {
665
+ dragging: dragged === state.key,
666
+ target: target?.key === state.key ? target.half : void 0,
667
+ canDrop: !disabled && dragged !== void 0,
668
+ onStart: () => {
669
+ setDragged(state.key);
670
+ },
671
+ onEnd: endDrag,
672
+ onOver: (half) => {
673
+ setTarget((current) => current?.key === state.key && current.half === half ? current : {
674
+ key: state.key,
675
+ half
676
+ });
677
+ },
678
+ onLeave: () => {
679
+ setTarget((current) => current?.key === state.key ? void 0 : current);
680
+ },
681
+ onDrop: (half) => {
682
+ const from = rows.findIndex((row) => row.key === dragged);
683
+ const insertion = index + (half === "after" ? 1 : 0);
684
+ move(from, insertion > from ? insertion - 1 : insertion);
685
+ endDrag();
686
+ },
687
+ onMove: (offset) => {
688
+ move(index, index + offset);
689
+ }
690
+ }
691
+ })),
692
+ toggle: (index) => {
693
+ setRows(rows.map((row, at) => at === index ? {
694
+ ...row,
695
+ expanded: !row.expanded
696
+ } : row));
697
+ },
698
+ edit: (index, field, text) => {
699
+ setRows(rows.map((row, at) => {
700
+ if (at !== index) return row;
701
+ const editing = new Map(row.editing);
702
+ if (text === void 0) editing.delete(field);
703
+ else editing.set(field, text);
704
+ return {
705
+ ...row,
706
+ editing
707
+ };
708
+ }));
709
+ },
710
+ forget: (removed) => {
711
+ setRows(rows.filter((_row, index) => !removed.has(index)));
712
+ endDrag();
713
+ },
714
+ reset: () => {
715
+ setRows(models.map(() => createRow(nextKey.current++)));
716
+ endDrag();
717
+ }
718
+ };
576
719
  }
720
+ //#endregion
721
+ //#region lib/types/client/DeepSeekModelsEditor.js
577
722
  /** Accepted capacity spellings: a decimal count with an optional K/M suffix. */
578
723
  const CAPACITY_PATTERN = /^(\d+(?:\.\d+)?)([km])?$/i;
579
724
  /** Decimal suffix scales — `1M` is 1000K, matching how model capacities are quoted. */
@@ -662,8 +807,7 @@ window.__ModuleLoader__.load({
662
807
  * @returns the catalog editor.
663
808
  */
664
809
  function DeepSeekModelsEditor(props) {
665
- const [editing, setEditing] = (0, react.useState)(() => /* @__PURE__ */ new Map());
666
- const [expanded, setExpanded] = (0, react.useState)(() => /* @__PURE__ */ new Set());
810
+ const rowState = useModelRows(props.models, props.onChange, props.disabled);
667
811
  const update = (index, key, value) => {
668
812
  const next = props.models.map((model, at) => {
669
813
  const copy = { ...model };
@@ -675,61 +819,32 @@ window.__ModuleLoader__.load({
675
819
  props.onChange(next);
676
820
  };
677
821
  const remove = (index) => {
678
- setEditing((current) => {
679
- const next = /* @__PURE__ */ new Map();
680
- for (const [key, text] of current) {
681
- const at = rowOf(key);
682
- if (at === index) continue;
683
- next.set(at > index ? key.replace(/^\d+/, String(at - 1)) : key, text);
684
- }
685
- return next;
686
- });
687
- setExpanded((current) => {
688
- const next = /* @__PURE__ */ new Set();
689
- for (const at of current) {
690
- if (at === index) continue;
691
- next.add(at > index ? at - 1 : at);
692
- }
693
- return next;
694
- });
822
+ rowState.forget(new Set([index]));
695
823
  props.onChange(props.models.filter((_model, at) => at !== index).map((model) => ({ ...model })));
696
824
  };
697
825
  const reset = () => {
698
- setEditing(/* @__PURE__ */ new Map());
699
- setExpanded(/* @__PURE__ */ new Set());
826
+ rowState.reset();
700
827
  props.onReset();
701
828
  };
702
- const toggle = (index) => {
703
- setExpanded((current) => {
704
- const next = new Set(current);
705
- if (!next.delete(index)) next.add(index);
706
- return next;
707
- });
708
- };
709
829
  /** The field's text: its live keystrokes, else the stored count spelled short. */
710
830
  const capacityText = (model, index, field) => {
711
- const typed = editing.get(`${String(index)}:${field}`);
831
+ const typed = rowState.rows[index]?.editing.get(field);
712
832
  if (typed !== void 0) return typed;
713
833
  const value = model[field];
714
834
  return typeof value === "number" ? formatCapacity(value) : "";
715
835
  };
716
836
  const settleCapacity = (index, field) => {
717
- const key = `${String(index)}:${field}`;
718
- const typed = editing.get(key);
837
+ const typed = rowState.rows[index]?.editing.get(field);
719
838
  if (typed === void 0) return;
720
839
  const parsed = parseCapacity(typed);
721
840
  if (parsed !== void 0 && Number.isNaN(parsed)) return;
722
- setEditing((current) => {
723
- const next = new Map(current);
724
- next.delete(key);
725
- return next;
726
- });
841
+ rowState.edit(index, field, void 0);
727
842
  };
728
843
  const capacityInput = (model, index, field, fallback) => ({
729
844
  value: capacityText(model, index, field),
730
845
  placeholder: fallback === void 0 ? props.t(field === "contextWindow" ? "contextWindowPlaceholder" : "maxTokensPlaceholder") : formatCapacity(fallback),
731
846
  onChange: (text) => {
732
- setEditing((current) => new Map(current).set(`${String(index)}:${field}`, text));
847
+ rowState.edit(index, field, text);
733
848
  update(index, field, parseCapacity(text));
734
849
  },
735
850
  onBlur: () => {
@@ -759,16 +874,21 @@ window.__ModuleLoader__.load({
759
874
  children: props.t("resetModels")
760
875
  }) : null]
761
876
  }),
762
- props.models.length === 0 ? (0, react_jsx_runtime.jsx)("p", {
763
- className: ModelsSection_module_css_default["modelEmpty"],
764
- children: props.t("modelsEmpty")
765
- }) : (0, react_jsx_runtime.jsx)("div", {
877
+ (0, react_jsx_runtime.jsxs)(_qilin_agent_client_ui_primitives.AnimatedRows, {
766
878
  className: ModelsSection_module_css_default["modelList"],
767
- children: props.models.map((model, index) => (0, react_jsx_runtime.jsx)(ModelRow, {
879
+ rowKeys: rowState.rows.map((row) => String(row.key)),
880
+ ready: true,
881
+ resetKey: "",
882
+ children: [props.models.length === 0 ? (0, react_jsx_runtime.jsx)("p", {
883
+ className: ModelsSection_module_css_default["modelEmpty"],
884
+ children: props.t("modelsEmpty")
885
+ }) : null, rowState.rows.map(({ model, key, expanded, order }, index) => (0, react_jsx_runtime.jsx)(ModelRow, {
886
+ rowKey: key,
887
+ order,
768
888
  model,
769
889
  position: index + 1,
770
890
  inputField: "inputModalities",
771
- expanded: expanded.has(index),
891
+ expanded,
772
892
  disabled: props.disabled,
773
893
  t: props.t,
774
894
  contextWindow: capacityInput(model, index, "contextWindow", props.defaultContextWindow),
@@ -784,12 +904,12 @@ window.__ModuleLoader__.load({
784
904
  props.onChange(props.models.map((row, at) => at === index ? next : row));
785
905
  },
786
906
  onToggle: () => {
787
- toggle(index);
907
+ rowState.toggle(index);
788
908
  },
789
909
  onRemove: () => {
790
910
  remove(index);
791
911
  }
792
- }, index))
912
+ }, key))]
793
913
  }),
794
914
  (0, react_jsx_runtime.jsxs)("button", {
795
915
  type: "button",
@@ -798,7 +918,7 @@ window.__ModuleLoader__.load({
798
918
  onClick: () => {
799
919
  props.onChange([...props.models.map((model) => ({ ...model })), { id: "" }]);
800
920
  },
801
- children: [(0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconPlusOutline16, { size: 14 }), props.t("addModel")]
921
+ children: [(0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconPlusOutlineRegular, { size: 14 }), props.t("addModel")]
802
922
  })
803
923
  ]
804
924
  });
@@ -871,9 +991,12 @@ window.__ModuleLoader__.load({
871
991
  * @returns the model-list editor.
872
992
  */
873
993
  function ModelListEditor(props) {
874
- const { models, onChange, probe, operations, t, disabled } = props;
994
+ const { models, onChange, probe, operations, t, disabled, onBusyChange } = props;
875
995
  const { catalogProvider } = props;
876
996
  const [busy, setBusy] = (0, react.useState)(false);
997
+ (0, react.useEffect)(() => {
998
+ onBusyChange(busy);
999
+ }, [busy, onBusyChange]);
877
1000
  const [failure, setFailure] = (0, react.useState)(void 0);
878
1001
  const [inheritedCatalog, setInheritedCatalog] = (0, react.useState)(void 0);
879
1002
  (0, react.useEffect)(() => {
@@ -900,33 +1023,13 @@ window.__ModuleLoader__.load({
900
1023
  const [candidates, setCandidates] = (0, react.useState)(void 0);
901
1024
  const [picked, setPicked] = (0, react.useState)(/* @__PURE__ */ new Set());
902
1025
  const [candidateQuery, setCandidateQuery] = (0, react.useState)("");
903
- const [expanded, setExpanded] = (0, react.useState)(/* @__PURE__ */ new Set());
904
- const [editing, setEditing] = (0, react.useState)(/* @__PURE__ */ new Map());
905
- /** Buffer key for one capacity field; the row half moves when rows do. */
906
- const bufferKey = (index, field) => `${String(index)}:${field}`;
1026
+ const rowState = useModelRows(models, onChange, disabled);
907
1027
  const editCapacity = (index, field, text) => {
908
- setEditing((current) => new Map(current).set(bufferKey(index, field), text));
1028
+ rowState.edit(index, field, text);
909
1029
  patch(index, { [field]: parseCapacity(text) });
910
1030
  };
911
1031
  /** What a capacity field shows: the buffer while typing, else the stored count. */
912
- const capacityText = (model, index, field) => editing.get(bufferKey(index, field)) ?? capacitySpelling(numberOf(model, field));
913
- /** Drop one row's entries and shift the rows after it down, in one pass. */
914
- const reindexOnRemove = (current, index) => {
915
- const next = /* @__PURE__ */ new Map();
916
- for (const [key, value] of current) {
917
- const at = Number(key.slice(0, key.indexOf(":")));
918
- if (at === index) continue;
919
- next.set(at > index ? key.replace(/^\d+/, String(at - 1)) : key, value);
920
- }
921
- return next;
922
- };
923
- const toggleExpanded = (index) => {
924
- setExpanded((current) => {
925
- const next = new Set(current);
926
- if (!next.delete(index)) next.add(index);
927
- return next;
928
- });
929
- };
1032
+ const capacityText = (model, index, field) => rowState.rows[index]?.editing.get(field) ?? capacitySpelling(numberOf(model, field));
930
1033
  const patch = (index, next) => {
931
1034
  onChange(models.map((model, at) => {
932
1035
  if (at !== index) return model;
@@ -1025,7 +1128,10 @@ window.__ModuleLoader__.load({
1025
1128
  type: "button",
1026
1129
  className: ModelsSection_module_css_default["linkButton"],
1027
1130
  disabled,
1028
- onClick: props.onReset,
1131
+ onClick: () => {
1132
+ rowState.reset();
1133
+ props.onReset?.();
1134
+ },
1029
1135
  children: t("resetModels")
1030
1136
  }) : null,
1031
1137
  (0, react_jsx_runtime.jsx)("button", {
@@ -1044,16 +1150,21 @@ window.__ModuleLoader__.load({
1044
1150
  className: ModelsSection_module_css_default["modelEmpty"],
1045
1151
  children: t("modelsEmpty")
1046
1152
  }) : null,
1047
- (0, react_jsx_runtime.jsx)("div", {
1153
+ (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.AnimatedRows, {
1048
1154
  className: ModelsSection_module_css_default["modelList"],
1049
- children: models.map((model, index) => (0, react_jsx_runtime.jsx)(ModelRow, {
1155
+ rowKeys: rowState.rows.map((row) => String(row.key)),
1156
+ ready: true,
1157
+ resetKey: "",
1158
+ children: rowState.rows.map(({ model, key, expanded, order }, index) => (0, react_jsx_runtime.jsx)(ModelRow, {
1159
+ rowKey: key,
1160
+ order,
1050
1161
  model,
1051
1162
  position: index + 1,
1052
1163
  inputField: "input",
1053
1164
  inputFallback: inputDefaults.get(textOf(model, "id")) ?? props.defaultInput,
1054
1165
  inputLoading: catalogProvider !== void 0 && catalog === void 0,
1055
1166
  reasoningLevels: props.reasoningLevels,
1056
- expanded: expanded.has(index),
1167
+ expanded,
1057
1168
  disabled,
1058
1169
  t,
1059
1170
  contextWindow: {
@@ -1077,19 +1188,13 @@ window.__ModuleLoader__.load({
1077
1188
  onChange(models.map((row, at) => at === index ? next : row));
1078
1189
  },
1079
1190
  onToggle: () => {
1080
- toggleExpanded(index);
1191
+ rowState.toggle(index);
1081
1192
  },
1082
1193
  onRemove: () => {
1083
1194
  onChange(models.filter((_model, at) => at !== index));
1084
- setExpanded((current) => {
1085
- const next = /* @__PURE__ */ new Set();
1086
- for (const at of current) if (at < index) next.add(at);
1087
- else if (at > index) next.add(at - 1);
1088
- return next;
1089
- });
1090
- setEditing((current) => reindexOnRemove(current, index));
1195
+ rowState.forget(new Set([index]));
1091
1196
  }
1092
- }, index))
1197
+ }, key))
1093
1198
  }),
1094
1199
  (0, react_jsx_runtime.jsxs)("button", {
1095
1200
  type: "button",
@@ -1098,7 +1203,7 @@ window.__ModuleLoader__.load({
1098
1203
  onClick: () => {
1099
1204
  onChange([...models, { id: "" }]);
1100
1205
  },
1101
- children: [(0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconPlusOutline16, { size: 14 }), t("addModel")]
1206
+ children: [(0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconPlusOutlineRegular, { size: 14 }), t("addModel")]
1102
1207
  }),
1103
1208
  failure !== void 0 ? (0, react_jsx_runtime.jsx)("p", {
1104
1209
  className: ModelsSection_module_css_default["error"],
@@ -1346,7 +1451,9 @@ window.__ModuleLoader__.load({
1346
1451
  }
1347
1452
  const mirrored = this.describeFace.getSnapshot();
1348
1453
  if (mirrored.view === void 0) {
1349
- this.failLoad(mirrored.error ?? "settings are unavailable in this browser");
1454
+ /* v8 ignore next -- SettingsDescribeFace.ensure settles with a view or the read's error */
1455
+ if (mirrored.error === null) throw new Error("settings describe settled with neither a view nor an error");
1456
+ this.failLoad(mirrored.error);
1350
1457
  return;
1351
1458
  }
1352
1459
  const providers = joinProviderDirectory(registered.value, declared.value);
@@ -1541,7 +1648,7 @@ window.__ModuleLoader__.load({
1541
1648
  * @returns the creation card.
1542
1649
  */
1543
1650
  function CustomProviderCard(props) {
1544
- const { taken, protocols, reasoningLevels, operations, t } = props;
1651
+ const { taken, protocols, reasoningLevels, operations, t, onBusyChange } = props;
1545
1652
  const [openedAt] = (0, react.useState)(() => props.revision);
1546
1653
  const [route, setRoute] = (0, react.useState)("");
1547
1654
  const [displayName, setDisplayName] = (0, react.useState)("");
@@ -1550,6 +1657,14 @@ window.__ModuleLoader__.load({
1550
1657
  const [keyDraft, setKeyDraft] = (0, react.useState)("");
1551
1658
  const [models, setModels] = (0, react.useState)([]);
1552
1659
  const [busy, setBusy] = (0, react.useState)(false);
1660
+ const [listBusy, setListBusy] = (0, react.useState)(false);
1661
+ (0, react.useEffect)(() => {
1662
+ onBusyChange?.(busy || listBusy);
1663
+ }, [
1664
+ busy,
1665
+ listBusy,
1666
+ onBusyChange
1667
+ ]);
1553
1668
  const [failure, setFailure] = (0, react.useState)(void 0);
1554
1669
  /**
1555
1670
  * The profile write landed. Only the key write can still be outstanding, so
@@ -1668,7 +1783,7 @@ window.__ModuleLoader__.load({
1668
1783
  className: ModelsSection_module_css_default["input"],
1669
1784
  type: "text",
1670
1785
  value: baseURL,
1671
- placeholder: t("customBaseUrlPlaceholder"),
1786
+ placeholder: t(protocol === "anthropic-messages" ? "customAnthropicBaseUrlPlaceholder" : "customBaseUrlPlaceholder"),
1672
1787
  "aria-label": t("baseUrl"),
1673
1788
  "aria-invalid": baseUrlInvalid,
1674
1789
  disabled: profileDisabled,
@@ -1736,7 +1851,8 @@ window.__ModuleLoader__.load({
1736
1851
  probeBlocked: baseUrlInvalid ? "customBaseUrlInvalid" : keyFailure === "keyBlank" ? "keyBlankNew" : keyFailure,
1737
1852
  operations,
1738
1853
  t,
1739
- disabled: profileDisabled
1854
+ disabled: profileDisabled,
1855
+ onBusyChange: setListBusy
1740
1856
  }),
1741
1857
  failure !== void 0 ? (0, react_jsx_runtime.jsx)("p", {
1742
1858
  className: ModelsSection_module_css_default["error"],
@@ -1841,8 +1957,16 @@ window.__ModuleLoader__.load({
1841
1957
  const { namespace, schema, settingsPath, operations, t } = props;
1842
1958
  const [draft, setDraft] = (0, react.useState)(() => draftAt(schema, namespace, settingsPath));
1843
1959
  const [keyDraft, setKeyDraft] = (0, react.useState)("");
1844
- const [keyState, setKeyState] = (0, react.useState)(void 0);
1845
1960
  const [busy, setBusy] = (0, react.useState)(false);
1961
+ const [listBusy, setListBusy] = (0, react.useState)(false);
1962
+ const { onBusyChange } = props;
1963
+ (0, react.useEffect)(() => {
1964
+ onBusyChange?.(busy || listBusy);
1965
+ }, [
1966
+ busy,
1967
+ listBusy,
1968
+ onBusyChange
1969
+ ]);
1846
1970
  const [failure, setFailure] = (0, react.useState)(void 0);
1847
1971
  const [committedOriginal, setCommittedOriginal] = (0, react.useState)(() => schema.getPath(namespace.user, settingsPath));
1848
1972
  const [expectedRevision, setExpectedRevision] = (0, react.useState)(() => namespace.revision);
@@ -1861,17 +1985,6 @@ window.__ModuleLoader__.load({
1861
1985
  namespace,
1862
1986
  schema
1863
1987
  ]);
1864
- (0, react.useEffect)(() => {
1865
- let stale = false;
1866
- setKeyState(void 0);
1867
- operations.describeCredential(keyRef).then((described) => {
1868
- if (stale) return;
1869
- setKeyState(described);
1870
- });
1871
- return () => {
1872
- stale = true;
1873
- };
1874
- }, [operations, keyRef]);
1875
1988
  const stringAt = (source, key) => {
1876
1989
  const value = schema.getPath(source, [key]);
1877
1990
  return typeof value === "string" && value.trim().length > 0 ? value : void 0;
@@ -1961,7 +2074,6 @@ window.__ModuleLoader__.load({
1961
2074
  props.t("settingsPathUnresolvable")
1962
2075
  ]
1963
2076
  });
1964
- const keyLocked = keyState?.writable === false;
1965
2077
  /**
1966
2078
  * The catalog beneath the user layer: what the composition entry pinned, or
1967
2079
  * else the schema default that `resolve` would supply. The effective value
@@ -1985,22 +2097,38 @@ window.__ModuleLoader__.load({
1985
2097
  const defaultContextWindow = schema.getPath(fallback, ["defaultContextWindow"]);
1986
2098
  const defaultMaxTokens = schema.getPath(fallback, ["maxTokens"]);
1987
2099
  const defaultInput = schema.getPath(fallback, ["defaultInput"]);
1988
- const namedRef = stringAt(fallback, "apiKeyEnv");
1989
- const nativeAuth = namedRef === void 0 ? props.nativeAuth : void 0;
2100
+ const baseURL = stringAt(fallback, "baseURL") ?? props.defaultBaseURL;
1990
2101
  const endpointEnv = props.baseURLEnv ?? [];
1991
- const baseURL = stringAt(fallback, "baseURL");
1992
2102
  const endpointHint = family === "deepseek" ? t("deepSeekEndpointHint") : baseURL === void 0 && endpointEnv.length > 0 ? t("baseUrlEnvironment").replace("{env}", () => endpointEnv.join(", ")) : void 0;
2103
+ const namedRef = stringAt(fallback, "apiKeyEnv");
2104
+ const nativeAuth = namedRef === void 0 ? props.nativeAuth : void 0;
1993
2105
  const authRefs = namedRef === void 0 ? (nativeAuth?.env ?? []).filter((ref) => !endpointEnv.includes(ref)) : [namedRef];
1994
2106
  const visibleRefs = authRefs.filter((ref) => !ref.toLowerCase().includes("oauth"));
1995
2107
  const keyHint = visibleRefs[0];
1996
- const checkedRefs = authRefs.map((ref) => [ref, props.credentialChecks?.[ref] ?? (ref === keyRef ? keyState : void 0)]);
2108
+ const checkedRefs = authRefs.map((ref) => [ref, props.credentialChecks?.[ref] ?? (ref === namedRef ? props.credential : void 0)]);
1997
2109
  const detected = checkedRefs.find(([, info]) => info?.configured === true);
1998
2110
  const detectedRef = detected?.[0];
1999
2111
  const detectedVisibleRef = detectedRef === void 0 || !visibleRefs.includes(detectedRef) ? void 0 : detectedRef;
2000
2112
  const missingRefs = checkedRefs.length > 0 && checkedRefs.every(([, info]) => info?.configured === false);
2001
2113
  const savedCredential = detected?.[1]?.source === "file";
2002
- const credentialHint = keyDraft.length > 0 || savedCredential || keyHint === void 0 || props.credentialRequired === true || keyLocked ? void 0 : t(detectedRef === void 0 ? missingRefs ? "keyFallbackMissing" : "keyFallbackUnchecked" : detectedVisibleRef === void 0 ? "keyFallbackDetectedHidden" : "keyFallbackDetected").replace("{hint}", () => detectedVisibleRef ?? keyHint);
2003
- const keyPlaceholder = keyLocked ? t("keyEnvLocked") : keyState?.configured === true && props.credentialRequired !== true ? t("keyStored") : savedCredential ? t("keyPlaceholderSaved") : family === "pi-ai" && keyHint !== void 0 && props.credentialRequired !== true ? t("keyPlaceholderNative") : t("keyPlaceholder");
2114
+ const credentialHint = keyDraft.length > 0 || savedCredential || keyHint === void 0 || props.credentialRequired === true ? void 0 : t(detectedRef === void 0 ? missingRefs ? "keyFallbackMissing" : "keyFallbackUnchecked" : detectedVisibleRef === void 0 ? "keyFallbackDetectedHidden" : "keyFallbackDetected").replace("{hint}", () => detectedVisibleRef ?? keyHint);
2115
+ const keyHelp = visibleRefs.length === 0 ? void 0 : t("keyHelp").replace("{env}", () => visibleRefs.join(" / "));
2116
+ const authHelp = keyHelp === void 0 ? null : (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.Tooltip, {
2117
+ label: keyHelp,
2118
+ side: "right",
2119
+ delayMs: 0,
2120
+ focusDelayMs: 0,
2121
+ portal: true,
2122
+ openOnClick: true,
2123
+ children: (0, react_jsx_runtime.jsx)("button", {
2124
+ type: "button",
2125
+ className: ModelsSection_module_css_default["helpButton"],
2126
+ "aria-label": t("authHelp"),
2127
+ children: "?"
2128
+ })
2129
+ });
2130
+ const keylessNativeAuth = nativeAuth?.env.length === 0 && nativeAuth.oauth;
2131
+ const keyPlaceholder = keyHint === void 0 || props.credentialRequired === true ? t("keyPlaceholder") : t(savedCredential ? "keyPlaceholderSaved" : "keyPlaceholderFallback").replace("{hint}", () => keyHint);
2004
2132
  /** What both family editors take: the rows, whose layer owns them, and the two writes. */
2005
2133
  const catalogProps = {
2006
2134
  models,
@@ -2014,12 +2142,12 @@ window.__ModuleLoader__.load({
2014
2142
  setDraft((current) => schema.deletePath(current, ["models"]));
2015
2143
  }
2016
2144
  };
2017
- return (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsxs)("div", {
2145
+ return (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [keylessNativeAuth ? null : (0, react_jsx_runtime.jsxs)("div", {
2018
2146
  className: ModelsSection_module_css_default["field"],
2019
2147
  children: [
2020
- (0, react_jsx_runtime.jsx)("span", {
2148
+ (0, react_jsx_runtime.jsxs)("span", {
2021
2149
  className: ModelsSection_module_css_default["fieldLabel"],
2022
- children: t("keyInput")
2150
+ children: [t("keyInput"), authHelp]
2023
2151
  }),
2024
2152
  (0, react_jsx_runtime.jsx)(ApiKeyInput, {
2025
2153
  t,
@@ -2030,7 +2158,7 @@ window.__ModuleLoader__.load({
2030
2158
  "aria-describedby": credentialHint === void 0 ? void 0 : `${props.provider}-credential-hint`,
2031
2159
  required: props.credentialRequired === true,
2032
2160
  autoFocus: props.autoFocusCredential === true,
2033
- disabled: disabled || keyLocked,
2161
+ disabled,
2034
2162
  onChange: (event) => {
2035
2163
  setKeyDraft(event.target.value);
2036
2164
  }
@@ -2081,7 +2209,7 @@ window.__ModuleLoader__.load({
2081
2209
  className: ModelsSection_module_css_default["input"],
2082
2210
  type: "text",
2083
2211
  value: stringAt(draft, "baseURL") ?? "",
2084
- placeholder: family === "deepseek" ? t("deepSeekBaseUrl") : baseURL === void 0 ? t(endpointEnv.length > 0 ? "baseUrlConfigured" : "baseUrlDefault") : baseURL,
2212
+ placeholder: family === "deepseek" ? t("deepSeekBaseUrl") : baseURL === void 0 ? t(endpointEnv.length > 0 ? "baseUrlConfigured" : "baseUrlDefault") : t("baseUrlPlaceholder").replace("{url}", () => baseURL),
2085
2213
  "aria-describedby": endpointHint === void 0 ? void 0 : `${props.provider}-endpoint-hint`,
2086
2214
  "aria-label": t("baseUrl"),
2087
2215
  disabled,
@@ -2129,7 +2257,8 @@ window.__ModuleLoader__.load({
2129
2257
  defaultInput: Array.isArray(defaultInput) ? defaultInput : void 0,
2130
2258
  probe,
2131
2259
  probeBlocked: keyFailure,
2132
- operations
2260
+ operations,
2261
+ onBusyChange: setListBusy
2133
2262
  })
2134
2263
  ]
2135
2264
  })]
@@ -2171,6 +2300,7 @@ window.__ModuleLoader__.load({
2171
2300
  props.onClose(false);
2172
2301
  },
2173
2302
  onSubmit: () => {
2303
+ props.onSubmitCredential?.();
2174
2304
  apply();
2175
2305
  }
2176
2306
  })
@@ -2199,8 +2329,10 @@ window.__ModuleLoader__.load({
2199
2329
  displayName: target.displayName,
2200
2330
  settingsPath: target.settingsPath,
2201
2331
  ...target.declared === true ? { declared: true } : {},
2332
+ ...target.defaultBaseURL === void 0 ? {} : { defaultBaseURL: target.defaultBaseURL },
2202
2333
  ...target.baseURLEnv === void 0 ? {} : { baseURLEnv: target.baseURLEnv },
2203
2334
  ...target.nativeAuth === void 0 ? {} : { nativeAuth: target.nativeAuth },
2335
+ ...row.credential === void 0 ? {} : { credential: row.credential },
2204
2336
  ...row.credentialChecks === void 0 ? {} : { credentialChecks: row.credentialChecks },
2205
2337
  ...props
2206
2338
  });
@@ -2262,6 +2394,7 @@ window.__ModuleLoader__.load({
2262
2394
  settingsPath: row.entry.settingsPath,
2263
2395
  ...credentialRef === void 0 ? {} : { credentialRef },
2264
2396
  ...row.entry.declared === true ? { declared: true } : {},
2397
+ ...row.entry.defaultBaseURL === void 0 ? {} : { defaultBaseURL: row.entry.defaultBaseURL },
2265
2398
  ...row.entry.baseURLEnv === void 0 ? {} : { baseURLEnv: row.entry.baseURLEnv },
2266
2399
  ...row.entry.nativeAuth === void 0 ? {} : { nativeAuth: row.entry.nativeAuth }
2267
2400
  };
@@ -2307,6 +2440,8 @@ window.__ModuleLoader__.load({
2307
2440
  const [deleteFailure, setDeleteFailure] = (0, react.useState)(void 0);
2308
2441
  const [savedTarget, setSavedTarget] = (0, react.useState)(void 0);
2309
2442
  const [declaring, setDeclaring] = (0, react.useState)(false);
2443
+ /** Whether the add card's editor has a write or an interrogation in flight. */
2444
+ const [addBusy, setAddBusy] = (0, react.useState)(false);
2310
2445
  const [dismissedSetup, setDismissedSetup] = (0, react.useState)(() => /* @__PURE__ */ new Set());
2311
2446
  const announceSaved = (target) => {
2312
2447
  controller.load().then(() => {
@@ -2317,6 +2452,7 @@ window.__ModuleLoader__.load({
2317
2452
  setEditing(void 0);
2318
2453
  setAdding(false);
2319
2454
  setDeclaring(false);
2455
+ setAddBusy(false);
2320
2456
  if (changed) announceSaved(target);
2321
2457
  };
2322
2458
  /**
@@ -2546,6 +2682,7 @@ window.__ModuleLoader__.load({
2546
2682
  className: `${ModelsSection_module_css_default["input"]} ${ModelsSection_module_css_default["selectInput"]}`,
2547
2683
  value: addTarget.provider,
2548
2684
  "aria-label": t("provider"),
2685
+ disabled: addBusy,
2549
2686
  onChange: (event) => {
2550
2687
  const row = addable.find((candidate) => candidate.entry.provider === event.target.value);
2551
2688
  /* v8 ignore next -- the select only lists addable rows */
@@ -2565,6 +2702,7 @@ window.__ModuleLoader__.load({
2565
2702
  namespace: addNamespace,
2566
2703
  schema,
2567
2704
  settingsPath: addTarget.settingsPath,
2705
+ ...addTarget.defaultBaseURL === void 0 ? {} : { defaultBaseURL: addTarget.defaultBaseURL },
2568
2706
  ...addTarget.baseURLEnv === void 0 ? {} : { baseURLEnv: addTarget.baseURLEnv },
2569
2707
  ...addTarget.nativeAuth === void 0 ? {} : { nativeAuth: addTarget.nativeAuth },
2570
2708
  ...addRow?.credentialChecks === void 0 ? {} : { credentialChecks: addRow.credentialChecks },
@@ -2573,7 +2711,8 @@ window.__ModuleLoader__.load({
2573
2711
  readOnly: !state.writable,
2574
2712
  onClose: (changed) => {
2575
2713
  closeEditor(changed, addTarget);
2576
- }
2714
+ },
2715
+ onBusyChange: setAddBusy
2577
2716
  }, addTarget.provider),
2578
2717
  addRow === void 0 ? null : renderSlot("settings.models.provider-card", {
2579
2718
  provider: addRow.entry,
@@ -2613,7 +2752,7 @@ window.__ModuleLoader__.load({
2613
2752
  setAdding(true);
2614
2753
  setEditing(targetOf(first));
2615
2754
  },
2616
- children: [(0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconPlusOutline16, { size: 14 }), t("add")]
2755
+ children: [(0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconPlusOutlineRegular, { size: 14 }), t("add")]
2617
2756
  }), state.namespaces.has("llm-pi-ai") && (0, react_jsx_runtime.jsxs)("button", {
2618
2757
  type: "button",
2619
2758
  className: ModelsSection_module_css_default["addButton"],
@@ -2626,7 +2765,7 @@ window.__ModuleLoader__.load({
2626
2765
  setEditing(void 0);
2627
2766
  setDeclaring(true);
2628
2767
  },
2629
- children: [(0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconPlusOutline16, { size: 14 }), t("customAdd")]
2768
+ children: [(0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconPlusOutlineRegular, { size: 14 }), t("customAdd")]
2630
2769
  })]
2631
2770
  })
2632
2771
  }),
@@ -2829,10 +2968,6 @@ window.__ModuleLoader__.load({
2829
2968
  */
2830
2969
  function createModelsOperations(ctx) {
2831
2970
  return {
2832
- describeCredential: async (ref) => {
2833
- const response = await ctx.remote.credentials.describe([ref]);
2834
- return response.ok ? response.value[ref] : void 0;
2835
- },
2836
2971
  storeCredential: async (ref, value) => {
2837
2972
  const response = await ctx.remote.credentials.set(ref, value);
2838
2973
  return response.ok ? void 0 : response.error.message;
@@ -2920,19 +3055,20 @@ window.__ModuleLoader__.load({
2920
3055
  keyReveal: "Show secret",
2921
3056
  keyHide: "Hide secret",
2922
3057
  keyPlaceholder: "Enter your API key",
2923
- keyPlaceholderNative: "Enter an API key, or leave blank to use environment authentication",
2924
- keyStored: "Configured — enter a new value to replace",
2925
- keyEnvLocked: "Provided by the launch environment (read-only)",
3058
+ keyPlaceholderFallback: "Leave blank to use env as auth ({hint})",
2926
3059
  keyPlaceholderSaved: "Leave blank to use saved credentials",
2927
3060
  keyFallbackMissing: "Env var not detected. Enter an API key, or configure {hint} in your env.",
2928
3061
  keyFallbackDetected: "Env var detected. ({hint})",
2929
3062
  keyFallbackDetectedHidden: "Env var detected.",
2930
3063
  keyFallbackUnchecked: "Environment credential status has not been confirmed.",
3064
+ keyHelp: "Saved credentials are used first. Environment fallbacks shown here, in order: {env}. Sources are launch environment, $cwd/.env, then $QILIN_HOME/.env.",
3065
+ authHelp: "Authentication details",
2931
3066
  customized: "Customized settings",
2932
3067
  baseUrl: "Base URL",
2933
- baseUrlDefault: "Provider default",
3068
+ baseUrlDefault: "No default endpoint",
2934
3069
  baseUrlEnvironment: "Provider endpoint configuration: {env}",
2935
3070
  baseUrlConfigured: "Provider-configured endpoint",
3071
+ baseUrlPlaceholder: "{url}",
2936
3072
  deepSeekBaseUrl: "https://api.deepseek.com/anthropic",
2937
3073
  deepSeekEndpointHint: "Use an endpoint compatible with the configured connection.",
2938
3074
  models: "Models",
@@ -2963,6 +3099,8 @@ window.__ModuleLoader__.load({
2963
3099
  modelReasoningOffValuePlaceholder: "Turns reasoning off",
2964
3100
  addModel: "Add model",
2965
3101
  removeModel: "Delete model",
3102
+ reorderModel: "Reorder model",
3103
+ reorderModelHelp: "Drag the handle, or focus it and press the up or down arrow key.",
2966
3104
  modelsEmpty: "No models will be shown in the selector. Unlisted IDs can still be sent directly.",
2967
3105
  keyBlank: "Enter the API key, or leave the field empty to keep the stored one.",
2968
3106
  keyBlankNew: "Enter the API key, or leave the field empty if this provider authenticates another way.",
@@ -3003,6 +3141,7 @@ window.__ModuleLoader__.load({
3003
3141
  customBaseUrlInvalid: "Enter a valid HTTP or HTTPS URL.",
3004
3142
  customNeedsModels: "A custom provider needs at least one model.",
3005
3143
  customBaseUrlPlaceholder: "https://gateway.example/v1",
3144
+ customAnthropicBaseUrlPlaceholder: "https://gateway.example",
3006
3145
  settingsPathUnresolvable: "unresolvable settings path",
3007
3146
  create: "Create provider",
3008
3147
  creating: "Creating…",
@@ -3044,19 +3183,20 @@ window.__ModuleLoader__.load({
3044
3183
  keyReveal: "显示密钥",
3045
3184
  keyHide: "隐藏密钥",
3046
3185
  keyPlaceholder: "输入 API 密钥",
3047
- keyPlaceholderNative: "输入 API 密钥,或留空使用环境认证",
3048
- keyStored: "已配置——输入新值可替换",
3049
- keyEnvLocked: "由启动环境提供(只读)",
3186
+ keyPlaceholderFallback: "留空使用环境认证({hint})",
3050
3187
  keyPlaceholderSaved: "留空使用已保存凭据",
3051
3188
  keyFallbackMissing: "未检测到环境变量。请填写 API 密钥,或设置环境变量 {hint}。",
3052
3189
  keyFallbackDetected: "已检测到环境变量({hint})",
3053
3190
  keyFallbackDetectedHidden: "已检测到环境变量",
3054
3191
  keyFallbackUnchecked: "环境凭据状态尚未确认",
3192
+ keyHelp: "优先使用已保存的凭据。此处显示的环境后备按以下顺序排列:{env}。来源依次为启动环境、$cwd/.env、$QILIN_HOME/.env。",
3193
+ authHelp: "认证说明",
3055
3194
  customized: "自定义设置",
3056
3195
  baseUrl: "API 地址",
3057
- baseUrlDefault: "提供方默认",
3196
+ baseUrlDefault: "没有默认地址",
3058
3197
  baseUrlEnvironment: "提供方地址配置:{env}",
3059
3198
  baseUrlConfigured: "由提供方配置地址",
3199
+ baseUrlPlaceholder: "{url}",
3060
3200
  deepSeekBaseUrl: "https://api.deepseek.com/anthropic",
3061
3201
  deepSeekEndpointHint: "请填写与当前连接配置兼容的 API 地址。",
3062
3202
  models: "模型目录",
@@ -3087,6 +3227,8 @@ window.__ModuleLoader__.load({
3087
3227
  modelReasoningOffValuePlaceholder: "关闭思考",
3088
3228
  addModel: "添加模型",
3089
3229
  removeModel: "删除模型",
3230
+ reorderModel: "调整模型顺序",
3231
+ reorderModelHelp: "拖动手柄,或聚焦手柄后按上下方向键。",
3090
3232
  modelsEmpty: "模型选择器中将不显示任何模型;目录外 ID 仍可直接发送。",
3091
3233
  keyBlank: "请输入 API 密钥;留空则保持已存储的密钥。",
3092
3234
  keyBlankNew: "请输入 API 密钥;若该提供方以其他方式鉴权,可以留空。",
@@ -3127,6 +3269,7 @@ window.__ModuleLoader__.load({
3127
3269
  customBaseUrlInvalid: "请输入有效的 HTTP 或 HTTPS 地址。",
3128
3270
  customNeedsModels: "自定义提供方至少需要一个模型。",
3129
3271
  customBaseUrlPlaceholder: "https://gateway.example/v1",
3272
+ customAnthropicBaseUrlPlaceholder: "https://gateway.example",
3130
3273
  settingsPathUnresolvable: "无法解析设置路径",
3131
3274
  create: "创建提供方",
3132
3275
  creating: "创建中…",
@@ -3138,6 +3281,904 @@ window.__ModuleLoader__.load({
3138
3281
  keyRequired: "请输入 API 密钥后继续。"
3139
3282
  };
3140
3283
  //#endregion
3284
+ //#region ../../../vendor/cosmokit/src/misc.ts
3285
+ /** Return true when a value is `null` or `undefined`. */
3286
+ function isNullable(value) {
3287
+ return value === null || value === void 0;
3288
+ }
3289
+ /** Return true for non-array object values. */
3290
+ function isPlainObject(data) {
3291
+ return data && typeof data === "object" && !Array.isArray(data);
3292
+ }
3293
+ /** Filter object entries and return a new object. */
3294
+ function filterKeys(object, filter) {
3295
+ return Object.fromEntries(Object.entries(object).filter(([key, value]) => filter(key, value)));
3296
+ }
3297
+ /** Map object values while preserving the original key set. */
3298
+ function mapValues(object, transform) {
3299
+ return Object.fromEntries(Object.entries(object).map(([key, value]) => [key, transform(value, key)]));
3300
+ }
3301
+ /** Pick selected keys from an object, optionally including `undefined` values. */
3302
+ function pick(source, keys, forced) {
3303
+ if (!keys) return { ...source };
3304
+ const result = {};
3305
+ for (const key of keys) if (forced || source[key] !== void 0) result[key] = source[key];
3306
+ return result;
3307
+ }
3308
+ //#endregion
3309
+ //#region ../../../vendor/cosmokit/src/volatile.ts
3310
+ /** Shared config references used by schema validators and plugin runtimes. */
3311
+ const write = Symbol.for("cosmokit.volatile.write");
3312
+ function snapshot(value, ancestors = /* @__PURE__ */ new Set()) {
3313
+ if (typeof value === "function") throw new TypeError("volatile config cannot contain functions");
3314
+ if (value === null || typeof value !== "object") return value;
3315
+ if (ancestors.has(value)) throw new TypeError("volatile config cannot contain cycles");
3316
+ ancestors.add(value);
3317
+ try {
3318
+ if (Array.isArray(value)) return Object.freeze(value.map((item) => snapshot(item, ancestors)));
3319
+ if (Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) throw new TypeError("volatile config objects must be plain objects or arrays");
3320
+ return Object.freeze(Object.fromEntries(Object.entries(value).map(([key, item]) => [key, snapshot(item, ancestors)])));
3321
+ } finally {
3322
+ ancestors.delete(value);
3323
+ }
3324
+ }
3325
+ /**
3326
+ * Create a detached reference containing an immutable copy of the supplied data.
3327
+ * @param value - validated config data; class instances and functions are unsupported.
3328
+ * @returns a reference whose value is updated only by its owning runtime.
3329
+ */
3330
+ function createVolatile(value) {
3331
+ let current = snapshot(value);
3332
+ return Object.freeze({
3333
+ get: () => current,
3334
+ [write]: (value) => {
3335
+ current = value;
3336
+ }
3337
+ });
3338
+ }
3339
+ /**
3340
+ * Identify references across ESM/CJS copies of the shared library.
3341
+ * @param value - a parsed config value.
3342
+ * @returns whether the value implements the shared reference protocol.
3343
+ */
3344
+ function isVolatile(value) {
3345
+ return typeof value === "object" && value !== null && write in value;
3346
+ }
3347
+ //#endregion
3348
+ //#region ../../../vendor/cosmokit/src/types.ts
3349
+ /** Test values using `instanceof` with a `toStringTag` fallback. */
3350
+ function is(type, value) {
3351
+ if (arguments.length === 1) return (value) => is(type, value);
3352
+ return type in globalThis && value instanceof globalThis[type] || Object.prototype.toString.call(value).slice(8, -1) === type;
3353
+ }
3354
+ function isArrayBufferLike(value) {
3355
+ return is("ArrayBuffer", value) || is("SharedArrayBuffer", value);
3356
+ }
3357
+ function isArrayBufferSource(value) {
3358
+ return isArrayBufferLike(value) || ArrayBuffer.isView(value);
3359
+ }
3360
+ let Binary;
3361
+ (function(_Binary) {
3362
+ _Binary.is = isArrayBufferLike;
3363
+ _Binary.isSource = isArrayBufferSource;
3364
+ function fromSource(source) {
3365
+ if (ArrayBuffer.isView(source)) return source.buffer.slice(source.byteOffset, source.byteOffset + source.byteLength);
3366
+ else return source;
3367
+ }
3368
+ _Binary.fromSource = fromSource;
3369
+ function toBase64(source) {
3370
+ source = fromSource(source);
3371
+ if (typeof Buffer !== "undefined") return Buffer.from(source).toString("base64");
3372
+ let binary = "";
3373
+ const bytes = new Uint8Array(source);
3374
+ for (let i = 0; i < bytes.byteLength; i++) binary += String.fromCharCode(bytes[i]);
3375
+ return btoa(binary);
3376
+ }
3377
+ _Binary.toBase64 = toBase64;
3378
+ function fromBase64(source) {
3379
+ if (typeof Buffer !== "undefined") return fromSource(Buffer.from(source, "base64"));
3380
+ return Uint8Array.from(atob(source), (c) => c.charCodeAt(0));
3381
+ }
3382
+ _Binary.fromBase64 = fromBase64;
3383
+ function toHex(source) {
3384
+ source = fromSource(source);
3385
+ if (typeof Buffer !== "undefined") return Buffer.from(source).toString("hex");
3386
+ return Array.from(new Uint8Array(source), (byte) => byte.toString(16).padStart(2, "0")).join("");
3387
+ }
3388
+ _Binary.toHex = toHex;
3389
+ function fromHex(source) {
3390
+ if (typeof Buffer !== "undefined") return fromSource(Buffer.from(source, "hex"));
3391
+ const hex = source.length % 2 === 0 ? source : source.slice(0, source.length - 1);
3392
+ const buffer = [];
3393
+ for (let i = 0; i < hex.length; i += 2) buffer.push(parseInt(`${hex[i]}${hex[i + 1]}`, 16));
3394
+ return Uint8Array.from(buffer).buffer;
3395
+ }
3396
+ _Binary.fromHex = fromHex;
3397
+ })(Binary || (Binary = {}));
3398
+ Binary.fromBase64;
3399
+ Binary.toBase64;
3400
+ Binary.fromHex;
3401
+ Binary.toHex;
3402
+ /** Deep-clone common JavaScript values while preserving prototypes and cycles. */
3403
+ function clone(source, refs = /* @__PURE__ */ new Map()) {
3404
+ if (!source || typeof source !== "object") return source;
3405
+ if (is("Date", source)) return new Date(source.valueOf());
3406
+ if (is("RegExp", source)) return new RegExp(source.source, source.flags);
3407
+ if (isArrayBufferLike(source)) return source.slice(0);
3408
+ if (ArrayBuffer.isView(source)) return source.buffer.slice(source.byteOffset, source.byteOffset + source.byteLength);
3409
+ const cached = refs.get(source);
3410
+ if (cached) return cached;
3411
+ if (Array.isArray(source)) {
3412
+ const result = [];
3413
+ refs.set(source, result);
3414
+ source.forEach((value, index) => {
3415
+ result[index] = Reflect.apply(clone, null, [value, refs]);
3416
+ });
3417
+ return result;
3418
+ }
3419
+ const result = Object.create(Object.getPrototypeOf(source));
3420
+ refs.set(source, result);
3421
+ for (const key of Reflect.ownKeys(source)) {
3422
+ const descriptor = { ...Reflect.getOwnPropertyDescriptor(source, key) };
3423
+ if ("value" in descriptor) descriptor.value = Reflect.apply(clone, null, [descriptor.value, refs]);
3424
+ Reflect.defineProperty(result, key, descriptor);
3425
+ }
3426
+ return result;
3427
+ }
3428
+ /**
3429
+ * Compare values recursively, treating two volatile references as equal regardless of value.
3430
+ * Strict comparison distinguishes null/undefined, treats opaque objects by identity,
3431
+ * compares URLs by normalized href, treats array holes as undefined, and considers distinct cyclic structures unequal.
3432
+ * @param a - first value.
3433
+ * @param b - second value.
3434
+ * @param strict - whether to require strict data equality outside volatile references.
3435
+ * @returns whether the values compare equal.
3436
+ */
3437
+ function deepEqual(a, b, strict) {
3438
+ const ancestors = /* @__PURE__ */ new Set();
3439
+ function compare(a, b) {
3440
+ if (a === b) return true;
3441
+ if (isVolatile(a) || isVolatile(b)) return isVolatile(a) && isVolatile(b);
3442
+ if (!strict && isNullable(a) && isNullable(b)) return true;
3443
+ if (typeof a !== typeof b || typeof a !== "object" || !a || !b) return false;
3444
+ if (ancestors.has(a)) return false;
3445
+ function check(test, then) {
3446
+ return test(a) ? test(b) ? then(a, b) : false : test(b) ? false : void 0;
3447
+ }
3448
+ ancestors.add(a);
3449
+ try {
3450
+ return check(Array.isArray, (a, b) => {
3451
+ if (a.length !== b.length) return false;
3452
+ for (let index = 0; index < a.length; index++) if (!compare(a[index], b[index])) return false;
3453
+ return true;
3454
+ }) ?? check(is("Date"), (a, b) => a.valueOf() === b.valueOf()) ?? check(is("URL"), (a, b) => a.href === b.href) ?? check(is("RegExp"), (a, b) => a.source === b.source && a.flags === b.flags) ?? check(isArrayBufferLike, (a, b) => {
3455
+ if (a.byteLength !== b.byteLength) return false;
3456
+ const viewA = new Uint8Array(a);
3457
+ const viewB = new Uint8Array(b);
3458
+ for (let i = 0; i < viewA.length; i++) if (viewA[i] !== viewB[i]) return false;
3459
+ return true;
3460
+ }) ?? ((!strict || [a, b].every((value) => Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null)) && Object.keys({
3461
+ ...a,
3462
+ ...b
3463
+ }).every((key) => compare(a[key], b[key])));
3464
+ } finally {
3465
+ ancestors.delete(a);
3466
+ }
3467
+ }
3468
+ return compare(a, b);
3469
+ }
3470
+ //#endregion
3471
+ //#region ../../../vendor/cosmokit/src/time.ts
3472
+ let Time;
3473
+ (function(_Time) {
3474
+ _Time.millisecond = 1;
3475
+ const second = _Time.second = 1e3;
3476
+ const minute = _Time.minute = second * 60;
3477
+ const hour = _Time.hour = minute * 60;
3478
+ const day = _Time.day = hour * 24;
3479
+ const week = _Time.week = day * 7;
3480
+ let timezoneOffset = (/* @__PURE__ */ new Date()).getTimezoneOffset();
3481
+ function setTimezoneOffset(offset) {
3482
+ timezoneOffset = offset;
3483
+ }
3484
+ _Time.setTimezoneOffset = setTimezoneOffset;
3485
+ function getTimezoneOffset() {
3486
+ return timezoneOffset;
3487
+ }
3488
+ _Time.getTimezoneOffset = getTimezoneOffset;
3489
+ function getDateNumber(date = /* @__PURE__ */ new Date(), offset) {
3490
+ if (typeof date === "number") date = new Date(date);
3491
+ if (offset === void 0) offset = timezoneOffset;
3492
+ return Math.floor((date.valueOf() / minute - offset) / 1440);
3493
+ }
3494
+ _Time.getDateNumber = getDateNumber;
3495
+ function fromDateNumber(value, offset) {
3496
+ const date = new Date(value * day);
3497
+ if (offset === void 0) offset = timezoneOffset;
3498
+ return new Date(+date + offset * minute);
3499
+ }
3500
+ _Time.fromDateNumber = fromDateNumber;
3501
+ const numeric = /\d+(?:\.\d+)?/.source;
3502
+ const timeRegExp = new RegExp(`^${[
3503
+ "w(?:eek(?:s)?)?",
3504
+ "d(?:ay(?:s)?)?",
3505
+ "h(?:our(?:s)?)?",
3506
+ "m(?:in(?:ute)?(?:s)?)?",
3507
+ "s(?:ec(?:ond)?(?:s)?)?"
3508
+ ].map((unit) => `(${numeric}${unit})?`).join("")}$`);
3509
+ function parseTime(source) {
3510
+ const capture = timeRegExp.exec(source);
3511
+ if (!capture) return 0;
3512
+ return (parseFloat(capture[1]) * week || 0) + (parseFloat(capture[2]) * day || 0) + (parseFloat(capture[3]) * hour || 0) + (parseFloat(capture[4]) * minute || 0) + (parseFloat(capture[5]) * second || 0);
3513
+ }
3514
+ _Time.parseTime = parseTime;
3515
+ function parseDate(date) {
3516
+ const parsed = parseTime(date);
3517
+ if (parsed) date = Date.now() + parsed;
3518
+ else if (/^\d{1,2}(:\d{1,2}){1,2}$/.test(date)) date = `${(/* @__PURE__ */ new Date()).toLocaleDateString()}-${date}`;
3519
+ else if (/^\d{1,2}-\d{1,2}-\d{1,2}(:\d{1,2}){1,2}$/.test(date)) date = `${(/* @__PURE__ */ new Date()).getFullYear()}-${date}`;
3520
+ return date ? new Date(date) : /* @__PURE__ */ new Date();
3521
+ }
3522
+ _Time.parseDate = parseDate;
3523
+ function format(ms) {
3524
+ const abs = Math.abs(ms);
3525
+ if (abs >= day - hour / 2) return Math.round(ms / day) + "d";
3526
+ else if (abs >= hour - minute / 2) return Math.round(ms / hour) + "h";
3527
+ else if (abs >= minute - second / 2) return Math.round(ms / minute) + "m";
3528
+ else if (abs >= second) return Math.round(ms / second) + "s";
3529
+ return ms + "ms";
3530
+ }
3531
+ _Time.format = format;
3532
+ function toDigits(source, length = 2) {
3533
+ return source.toString().padStart(length, "0");
3534
+ }
3535
+ _Time.toDigits = toDigits;
3536
+ function template(template, time = /* @__PURE__ */ new Date()) {
3537
+ return template.replace("yyyy", time.getFullYear().toString()).replace("yy", time.getFullYear().toString().slice(2)).replace("MM", toDigits(time.getMonth() + 1)).replace("dd", toDigits(time.getDate())).replace("hh", toDigits(time.getHours())).replace("mm", toDigits(time.getMinutes())).replace("ss", toDigits(time.getSeconds())).replace("SSS", toDigits(time.getMilliseconds(), 3));
3538
+ }
3539
+ _Time.template = template;
3540
+ })(Time || (Time = {}));
3541
+ //#endregion
3542
+ //#region ../../../vendor/schemastery/src/index.ts
3543
+ const kSchema = Symbol.for("schemastery");
3544
+ const kValidationError = Symbol.for("ValidationError");
3545
+ globalThis.__schemastery_index__ ??= 0;
3546
+ globalThis.__schemastery_refs__ = void 0;
3547
+ var ValidationError = class extends TypeError {
3548
+ options;
3549
+ name = "ValidationError";
3550
+ constructor(message, options) {
3551
+ let prefix = "$";
3552
+ for (const segment of options.path || []) if (typeof segment === "string") prefix += "." + segment;
3553
+ else if (typeof segment === "number") prefix += "[" + segment + "]";
3554
+ else if (typeof segment === "symbol") prefix += `[Symbol(${segment.toString()})]`;
3555
+ if (prefix.startsWith(".")) prefix = prefix.slice(1);
3556
+ super((prefix === "$" ? "" : `${prefix} `) + message);
3557
+ this.options = options;
3558
+ }
3559
+ static is(error) {
3560
+ return !!error?.[kValidationError];
3561
+ }
3562
+ };
3563
+ Object.defineProperty(ValidationError.prototype, kValidationError, { value: true });
3564
+ const Schema = function(options) {
3565
+ const schema = function(data, options = {}) {
3566
+ return Schema.resolve(data, schema, options)[0];
3567
+ };
3568
+ if (options.refs) {
3569
+ const refs = mapValues(options.refs, (options) => new Schema(options));
3570
+ const getRef = (uid) => refs[uid];
3571
+ for (const key in refs) {
3572
+ const options = refs[key];
3573
+ options.sKey = getRef(options.sKey);
3574
+ options.inner = getRef(options.inner);
3575
+ options.list = options.list && options.list.map(getRef);
3576
+ options.dict = options.dict && mapValues(options.dict, getRef);
3577
+ }
3578
+ return refs[options.uid];
3579
+ }
3580
+ Object.assign(schema, options);
3581
+ if (typeof schema.callback === "string") try {
3582
+ schema.callback = new Function("return " + schema.callback)();
3583
+ } catch {}
3584
+ Object.defineProperty(schema, "uid", { value: globalThis.__schemastery_index__++ });
3585
+ Object.setPrototypeOf(schema, Schema.prototype);
3586
+ schema.meta ||= {};
3587
+ schema.toString = schema.toString.bind(schema);
3588
+ return schema;
3589
+ };
3590
+ Schema.prototype = Object.create(Function.prototype);
3591
+ Schema.prototype[kSchema] = true;
3592
+ Object.defineProperty(Schema.prototype, "~standard", { get() {
3593
+ return {
3594
+ version: 1,
3595
+ vendor: "schemastery",
3596
+ validate: (value) => {
3597
+ try {
3598
+ return { value: Schema.resolve(value, this, {})[0] };
3599
+ } catch (error) {
3600
+ if (ValidationError.is(error)) return { issues: [{
3601
+ message: error.message,
3602
+ path: error.options.path
3603
+ }] };
3604
+ throw error;
3605
+ }
3606
+ }
3607
+ };
3608
+ } });
3609
+ Schema.ValidationError = ValidationError;
3610
+ Schema.prototype.toJSON = function toJSON() {
3611
+ if (globalThis.__schemastery_refs__) {
3612
+ globalThis.__schemastery_refs__[this.uid] ??= JSON.parse(JSON.stringify({ ...this }));
3613
+ return this.uid;
3614
+ }
3615
+ globalThis.__schemastery_refs__ = { [this.uid]: { ...this } };
3616
+ globalThis.__schemastery_refs__[this.uid] = JSON.parse(JSON.stringify({ ...this }));
3617
+ const result = {
3618
+ uid: this.uid,
3619
+ refs: globalThis.__schemastery_refs__
3620
+ };
3621
+ globalThis.__schemastery_refs__ = void 0;
3622
+ return result;
3623
+ };
3624
+ Schema.prototype.set = function set(key, value) {
3625
+ this.dict[key] = value;
3626
+ return this;
3627
+ };
3628
+ Schema.prototype.push = function push(value) {
3629
+ this.list.push(value);
3630
+ return this;
3631
+ };
3632
+ function mergeDesc(original, messages) {
3633
+ const result = typeof original === "string" ? { "": original } : { ...original };
3634
+ for (const locale in messages) {
3635
+ const value = messages[locale];
3636
+ if (value?.$description || value?.$desc) result[locale] = value.$description || value.$desc;
3637
+ else if (typeof value === "string") result[locale] = value;
3638
+ }
3639
+ return result;
3640
+ }
3641
+ function getInner(value) {
3642
+ return value?.$value ?? value?.$inner;
3643
+ }
3644
+ function extractKeys(data) {
3645
+ return filterKeys(data ?? {}, (key) => !key.startsWith("$"));
3646
+ }
3647
+ Schema.prototype.i18n = function i18n(messages) {
3648
+ const schema = Schema(this);
3649
+ const desc = mergeDesc(schema.meta.description, messages);
3650
+ if (Object.keys(desc).length) schema.meta.description = desc;
3651
+ if (schema.dict) schema.dict = mapValues(schema.dict, (inner, key) => {
3652
+ return inner.i18n(mapValues(messages, (data) => getInner(data)?.[key] ?? data?.[key]));
3653
+ });
3654
+ if (schema.list) schema.list = schema.list.map((inner, index) => {
3655
+ return inner.i18n(mapValues(messages, (data = {}) => {
3656
+ if (Array.isArray(getInner(data))) return getInner(data)[index];
3657
+ if (Array.isArray(data)) return data[index];
3658
+ return extractKeys(data);
3659
+ }));
3660
+ });
3661
+ if (schema.inner) schema.inner = schema.inner.i18n(mapValues(messages, (data) => {
3662
+ if (getInner(data)) return getInner(data);
3663
+ return extractKeys(data);
3664
+ }));
3665
+ if (schema.sKey) schema.sKey = schema.sKey.i18n(mapValues(messages, (data) => data?.$key));
3666
+ return schema;
3667
+ };
3668
+ Schema.prototype.extra = function extra(key, value) {
3669
+ const schema = Schema(this);
3670
+ schema.meta = {
3671
+ ...schema.meta,
3672
+ [key]: value
3673
+ };
3674
+ return schema;
3675
+ };
3676
+ for (const key of [
3677
+ "required",
3678
+ "disabled",
3679
+ "collapse",
3680
+ "hidden",
3681
+ "loose"
3682
+ ]) Object.assign(Schema.prototype, { [key](value = true) {
3683
+ const schema = Schema(this);
3684
+ schema.meta = {
3685
+ ...schema.meta,
3686
+ [key]: value
3687
+ };
3688
+ return schema;
3689
+ } });
3690
+ Schema.prototype.deprecated = function deprecated() {
3691
+ const schema = Schema(this);
3692
+ schema.meta.badges ||= [];
3693
+ schema.meta.badges.push({
3694
+ text: "deprecated",
3695
+ type: "danger"
3696
+ });
3697
+ return schema;
3698
+ };
3699
+ Schema.prototype.experimental = function experimental() {
3700
+ const schema = Schema(this);
3701
+ schema.meta.badges ||= [];
3702
+ schema.meta.badges.push({
3703
+ text: "experimental",
3704
+ type: "warning"
3705
+ });
3706
+ return schema;
3707
+ };
3708
+ Schema.prototype.pattern = function pattern(regexp) {
3709
+ const schema = Schema(this);
3710
+ const pattern = pick(regexp, ["source", "flags"]);
3711
+ schema.meta = {
3712
+ ...schema.meta,
3713
+ pattern
3714
+ };
3715
+ return schema;
3716
+ };
3717
+ Schema.prototype.simplify = function simplify(value) {
3718
+ if (isVolatile(value)) value = value.get();
3719
+ if (deepEqual(value, this.meta.default, this.type === "dict")) return null;
3720
+ if (isNullable(value)) return value;
3721
+ if (this.type === "object" || this.type === "dict") {
3722
+ const result = {};
3723
+ for (const key in value) {
3724
+ const item = (this.type === "object" ? this.dict[key] : this.inner)?.simplify(value[key]);
3725
+ if (this.type === "dict" || !isNullable(item)) result[key] = item;
3726
+ }
3727
+ if (deepEqual(result, this.meta.default, this.type === "dict")) return null;
3728
+ return result;
3729
+ } else if (this.type === "array" || this.type === "tuple") {
3730
+ const result = [];
3731
+ value.forEach((value, index) => {
3732
+ const schema = this.type === "array" ? this.inner : this.list[index];
3733
+ const item = schema ? schema.simplify(value) : value;
3734
+ result.push(item);
3735
+ });
3736
+ return result;
3737
+ } else if (this.type === "intersect") {
3738
+ const result = {};
3739
+ for (const item of this.list) Object.assign(result, item.simplify(value));
3740
+ return result;
3741
+ } else if (this.type === "union") for (const schema of this.list) try {
3742
+ Schema.resolve(value, schema, {});
3743
+ return schema.simplify(value);
3744
+ } catch {}
3745
+ return value;
3746
+ };
3747
+ Schema.prototype.toString = function toString(inline) {
3748
+ return formatters[this.type]?.(this, inline) ?? `Schema<${this.type}>`;
3749
+ };
3750
+ Schema.prototype.role = function role(role, extra) {
3751
+ const schema = Schema(this);
3752
+ schema.meta = {
3753
+ ...schema.meta,
3754
+ role,
3755
+ extra
3756
+ };
3757
+ return schema;
3758
+ };
3759
+ for (const key of [
3760
+ "default",
3761
+ "link",
3762
+ "comment",
3763
+ "description",
3764
+ "max",
3765
+ "min",
3766
+ "step"
3767
+ ]) Object.assign(Schema.prototype, { [key](value) {
3768
+ const schema = Schema(this);
3769
+ schema.meta = {
3770
+ ...schema.meta,
3771
+ [key]: value
3772
+ };
3773
+ return schema;
3774
+ } });
3775
+ Schema.prototype.volatile = function volatile() {
3776
+ if (this.meta.volatile) throw new TypeError("volatile schema is already wrapped");
3777
+ return this.extra("volatile", true);
3778
+ };
3779
+ const resolvers = {};
3780
+ const checkedVolatile = Symbol("checked-volatile-schema");
3781
+ function validateVolatileSchema(schema, path = [], blocked = false, seen = /* @__PURE__ */ new Map()) {
3782
+ const states = seen.get(schema) ?? /* @__PURE__ */ new Set();
3783
+ if (states.has(blocked)) return;
3784
+ states.add(blocked);
3785
+ seen.set(schema, states);
3786
+ if (schema.meta?.volatile && blocked) throw new ValidationError("volatile fields require a fixed object path without an enclosing volatile field", { path });
3787
+ const nested = blocked || !!schema.meta?.volatile;
3788
+ if (schema.dict) for (const [key, child] of Object.entries(schema.dict)) validateVolatileSchema(child, [...path, key], nested, seen);
3789
+ if (schema.sKey) validateVolatileSchema(schema.sKey, [...path, "<key>"], true, seen);
3790
+ if (schema.inner && (schema.type !== "lazy" || schema.inner[kSchema])) validateVolatileSchema(schema.inner, [...path, "*"], true, seen);
3791
+ if (schema.list) for (let index = 0; index < schema.list.length; index++) validateVolatileSchema(schema.list[index], [...path, String(index)], true, seen);
3792
+ }
3793
+ Schema.extend = function extend(type, resolve) {
3794
+ resolvers[type] = resolve;
3795
+ };
3796
+ Schema.resolve = function resolve(data, schema, options = {}, strict = false) {
3797
+ if (!schema) return [data];
3798
+ if (!options[checkedVolatile]) {
3799
+ validateVolatileSchema(schema, options.path);
3800
+ options = {
3801
+ ...options,
3802
+ [checkedVolatile]: true
3803
+ };
3804
+ }
3805
+ if (schema.meta?.volatile) {
3806
+ const inner = Schema(schema);
3807
+ inner.meta = {
3808
+ ...schema.meta,
3809
+ volatile: false
3810
+ };
3811
+ const [value, adapted] = Schema.resolve(data, inner, options, strict);
3812
+ try {
3813
+ return [createVolatile(value), adapted];
3814
+ } catch (error) {
3815
+ throw new ValidationError(error instanceof Error ? error.message : String(error), options);
3816
+ }
3817
+ }
3818
+ if (options.ignore?.(data, schema)) return [data];
3819
+ if (isNullable(data) && schema.type !== "lazy") {
3820
+ if (schema.meta.required) throw new ValidationError(`missing required value`, options);
3821
+ let current = schema;
3822
+ let fallback = schema.meta.default;
3823
+ while (current?.type === "intersect" && isNullable(fallback)) {
3824
+ current = current.list[0];
3825
+ fallback = current?.meta.default;
3826
+ }
3827
+ if (isNullable(fallback)) return [data];
3828
+ data = clone(fallback);
3829
+ }
3830
+ const callback = resolvers[schema.type];
3831
+ if (!callback) throw new ValidationError(`unsupported type "${schema.type}"`, options);
3832
+ try {
3833
+ return callback(data, schema, options, strict);
3834
+ } catch (error) {
3835
+ if (!schema.meta.loose) throw error;
3836
+ return [schema.meta.default];
3837
+ }
3838
+ };
3839
+ Schema.from = function from(source) {
3840
+ if (isNullable(source)) return Schema.any();
3841
+ else if ([
3842
+ "string",
3843
+ "number",
3844
+ "boolean"
3845
+ ].includes(typeof source)) return Schema.const(source).required();
3846
+ else if (source[kSchema]) return source;
3847
+ else if (typeof source === "function") switch (source) {
3848
+ case String: return Schema.string().required();
3849
+ case Number: return Schema.number().required();
3850
+ case Boolean: return Schema.boolean().required();
3851
+ case Function: return Schema.function().required();
3852
+ default: return Schema.is(source).required();
3853
+ }
3854
+ else throw new TypeError(`cannot infer schema from ${source}`);
3855
+ };
3856
+ Schema.lazy = function lazy(builder) {
3857
+ const toJSON = () => {
3858
+ if (!schema.inner[kSchema]) {
3859
+ schema.inner = schema.builder();
3860
+ schema.inner.meta = {
3861
+ ...schema.meta,
3862
+ ...schema.inner.meta
3863
+ };
3864
+ }
3865
+ return schema.inner.toJSON();
3866
+ };
3867
+ const schema = new Schema({
3868
+ type: "lazy",
3869
+ builder,
3870
+ inner: { toJSON }
3871
+ });
3872
+ return schema;
3873
+ };
3874
+ Schema.natural = function natural() {
3875
+ return Schema.number().step(1).min(0);
3876
+ };
3877
+ Schema.percent = function percent() {
3878
+ return Schema.number().step(.01).min(0).max(1).role("slider");
3879
+ };
3880
+ Schema.date = function date() {
3881
+ return Schema.union([Schema.is(Date), Schema.transform(Schema.string().role("datetime"), (value, options) => {
3882
+ const date = new Date(value);
3883
+ if (isNaN(+date)) throw new ValidationError(`invalid date "${value}"`, options);
3884
+ return date;
3885
+ }, true)]);
3886
+ };
3887
+ Schema.regExp = function regExp(flag = "") {
3888
+ return Schema.union([Schema.is(RegExp), Schema.transform(Schema.string().role("regexp", { flag }), (value, options) => {
3889
+ try {
3890
+ return new RegExp(value, flag);
3891
+ } catch (e) {
3892
+ throw new ValidationError(e.message, options);
3893
+ }
3894
+ }, true)]);
3895
+ };
3896
+ Schema.arrayBuffer = function arrayBuffer(encoding) {
3897
+ return Schema.union([
3898
+ Schema.is(ArrayBuffer),
3899
+ Schema.is(SharedArrayBuffer),
3900
+ Schema.transform(Schema.any(), (value, options) => {
3901
+ if (Binary.isSource(value)) return Binary.fromSource(value);
3902
+ throw new ValidationError(`expected ArrayBufferSource but got ${value}`, options);
3903
+ }, true),
3904
+ ...encoding ? [Schema.transform(Schema.string(), (value, options) => {
3905
+ try {
3906
+ return encoding === "base64" ? Binary.fromBase64(value) : Binary.fromHex(value);
3907
+ } catch (e) {
3908
+ throw new ValidationError(e.message, options);
3909
+ }
3910
+ }, true)] : []
3911
+ ]);
3912
+ };
3913
+ Schema.extend("lazy", (data, schema, options, strict) => {
3914
+ if (!schema.inner[kSchema]) {
3915
+ schema.inner = schema.builder();
3916
+ schema.inner.meta = {
3917
+ ...schema.meta,
3918
+ ...schema.inner.meta
3919
+ };
3920
+ validateVolatileSchema(schema.inner, options.path, true);
3921
+ }
3922
+ return Schema.resolve(data, schema.inner, options, strict);
3923
+ });
3924
+ Schema.extend("any", (data) => {
3925
+ return [data];
3926
+ });
3927
+ Schema.extend("never", (data, _, options) => {
3928
+ throw new ValidationError(`expected nullable but got ${data}`, options);
3929
+ });
3930
+ Schema.extend("const", (data, { value }, options) => {
3931
+ if (deepEqual(data, value)) return [value];
3932
+ throw new ValidationError(`expected ${value} but got ${data}`, options);
3933
+ });
3934
+ function checkWithinRange(data, meta, description, options, skipMin = false) {
3935
+ const { max = Infinity, min = -Infinity } = meta;
3936
+ if (data > max) throw new ValidationError(`expected ${description} <= ${max} but got ${data}`, options);
3937
+ if (data < min && !skipMin) throw new ValidationError(`expected ${description} >= ${min} but got ${data}`, options);
3938
+ }
3939
+ Schema.extend("string", (data, { meta }, options) => {
3940
+ if (typeof data !== "string") throw new ValidationError(`expected string but got ${data}`, options);
3941
+ if (meta.pattern) {
3942
+ const regexp = new RegExp(meta.pattern.source, meta.pattern.flags);
3943
+ if (!regexp.test(data)) throw new ValidationError(`expect string to match regexp ${regexp}`, options);
3944
+ }
3945
+ checkWithinRange(data.length, meta, "string length", options);
3946
+ return [data];
3947
+ });
3948
+ function decimalShift(data, digits) {
3949
+ const str = data.toString();
3950
+ if (str.includes("e")) return data * Math.pow(10, digits);
3951
+ const index = str.indexOf(".");
3952
+ if (index === -1) return data * Math.pow(10, digits);
3953
+ const frac = str.slice(index + 1);
3954
+ const integer = str.slice(0, index);
3955
+ if (frac.length <= digits) return +(integer + frac.padEnd(digits, "0"));
3956
+ return +(integer + frac.slice(0, digits) + "." + frac.slice(digits));
3957
+ }
3958
+ function isMultipleOf(data, min, step) {
3959
+ step = Math.abs(step);
3960
+ if (!/^\d+\.\d+$/.test(step.toString())) return (data - min) % step === 0;
3961
+ const index = step.toString().indexOf(".");
3962
+ const digits = step.toString().slice(index + 1).length;
3963
+ return Math.abs(decimalShift(data, digits) - decimalShift(min, digits)) % decimalShift(step, digits) === 0;
3964
+ }
3965
+ Schema.extend("number", (data, { meta }, options) => {
3966
+ if (typeof data !== "number") throw new ValidationError(`expected number but got ${data}`, options);
3967
+ checkWithinRange(data, meta, "number", options);
3968
+ const { step } = meta;
3969
+ if (step && !isMultipleOf(data, meta.min ?? 0, step)) throw new ValidationError(`expected number multiple of ${step} but got ${data}`, options);
3970
+ return [data];
3971
+ });
3972
+ Schema.extend("boolean", (data, _, options) => {
3973
+ if (typeof data === "boolean") return [data];
3974
+ throw new ValidationError(`expected boolean but got ${data}`, options);
3975
+ });
3976
+ Schema.extend("bitset", (data, { bits, meta }, options) => {
3977
+ let value = 0, keys = [];
3978
+ if (typeof data === "number") {
3979
+ value = data;
3980
+ for (const key in bits) if (data & bits[key]) keys.push(key);
3981
+ } else if (Array.isArray(data)) {
3982
+ keys = data;
3983
+ for (const key of keys) {
3984
+ if (typeof key !== "string") throw new ValidationError(`expected string but got ${key}`, options);
3985
+ if (key in bits) value |= bits[key];
3986
+ }
3987
+ } else throw new ValidationError(`expected number or array but got ${data}`, options);
3988
+ if (value === meta.default) return [value];
3989
+ return [value, keys];
3990
+ });
3991
+ Schema.extend("function", (data, _, options) => {
3992
+ if (typeof data === "function") return [data];
3993
+ throw new ValidationError(`expected function but got ${data}`, options);
3994
+ });
3995
+ Schema.extend("is", (data, { constructor }, options) => {
3996
+ if (typeof constructor === "function") {
3997
+ if (data instanceof constructor) return [data];
3998
+ throw new ValidationError(`expected ${constructor.name} but got ${data}`, options);
3999
+ } else {
4000
+ if (isNullable(data)) throw new ValidationError(`expected ${constructor} but got ${data}`, options);
4001
+ let prototype = Object.getPrototypeOf(data);
4002
+ while (prototype) {
4003
+ if (prototype.constructor?.name === constructor) return [data];
4004
+ prototype = Object.getPrototypeOf(prototype);
4005
+ }
4006
+ throw new ValidationError(`expected ${constructor} but got ${data}`, options);
4007
+ }
4008
+ });
4009
+ function property(data, key, schema, options) {
4010
+ try {
4011
+ const [value, adapted] = Schema.resolve(data[key], schema, {
4012
+ ...options,
4013
+ path: [...options.path || [], key]
4014
+ });
4015
+ if (adapted !== void 0) data[key] = adapted;
4016
+ return value;
4017
+ } catch (e) {
4018
+ if (!options?.autofix) throw e;
4019
+ delete data[key];
4020
+ return schema.meta.volatile ? createVolatile(schema.meta.default) : schema.meta.default;
4021
+ }
4022
+ }
4023
+ Schema.extend("array", (data, { inner, meta }, options) => {
4024
+ if (!Array.isArray(data)) throw new ValidationError(`expected array but got ${data}`, options);
4025
+ checkWithinRange(data.length, meta, "array length", options, !isNullable(inner.meta.default));
4026
+ return [data.map((_, index) => property(data, index, inner, options))];
4027
+ });
4028
+ Schema.extend("dict", (data, { inner, sKey }, options, strict) => {
4029
+ if (!isPlainObject(data)) throw new ValidationError(`expected object but got ${data}`, options);
4030
+ const result = {};
4031
+ for (const key in data) {
4032
+ let rKey;
4033
+ try {
4034
+ rKey = Schema.resolve(key, sKey, options)[0];
4035
+ } catch (error) {
4036
+ if (strict) continue;
4037
+ throw error;
4038
+ }
4039
+ result[rKey] = property(data, key, inner, options);
4040
+ data[rKey] = data[key];
4041
+ if (key !== rKey) delete data[key];
4042
+ }
4043
+ return [result];
4044
+ });
4045
+ Schema.extend("tuple", (data, { list }, options, strict) => {
4046
+ if (!Array.isArray(data)) throw new ValidationError(`expected array but got ${data}`, options);
4047
+ const result = list.map((inner, index) => property(data, index, inner, options));
4048
+ if (strict) return [result];
4049
+ result.push(...data.slice(list.length));
4050
+ return [result];
4051
+ });
4052
+ function merge(result, data) {
4053
+ for (const key in data) {
4054
+ if (key in result) continue;
4055
+ result[key] = data[key];
4056
+ }
4057
+ }
4058
+ Schema.extend("object", (data, { dict }, options, strict) => {
4059
+ if (!isPlainObject(data)) throw new ValidationError(`expected object but got ${data}`, options);
4060
+ const result = {};
4061
+ for (const key in dict) {
4062
+ const value = property(data, key, dict[key], options);
4063
+ if (!isNullable(value) || key in data) result[key] = value;
4064
+ }
4065
+ if (!strict) merge(result, data);
4066
+ return [result];
4067
+ });
4068
+ Schema.extend("union", (data, { list, toString }, options, strict) => {
4069
+ const messages = [];
4070
+ for (const inner of list) try {
4071
+ return Schema.resolve(data, inner, options, strict);
4072
+ } catch (error) {
4073
+ messages.push(error);
4074
+ }
4075
+ throw new ValidationError(`expected ${toString()} but got ${JSON.stringify(data)}`, options);
4076
+ });
4077
+ Schema.extend("intersect", (data, { list, toString }, options, strict) => {
4078
+ if (!list.length) return [data];
4079
+ let result;
4080
+ for (const inner of list) {
4081
+ const value = Schema.resolve(data, inner, options, true)[0];
4082
+ if (isNullable(value)) continue;
4083
+ if (isNullable(result)) result = value;
4084
+ else if (typeof result !== typeof value) throw new ValidationError(`expected ${toString()} but got ${JSON.stringify(data)}`, options);
4085
+ else if (typeof value === "object") merge(result ??= {}, value);
4086
+ else if (result !== value) throw new ValidationError(`expected ${toString()} but got ${JSON.stringify(data)}`, options);
4087
+ }
4088
+ if (!strict && isPlainObject(data)) merge(result, data);
4089
+ return [result];
4090
+ });
4091
+ Schema.extend("transform", (data, { inner, callback, preserve }, options) => {
4092
+ const [result, adapted = data] = Schema.resolve(data, inner, options, true);
4093
+ if (preserve) return [callback(result)];
4094
+ else return [callback(result), callback(adapted)];
4095
+ });
4096
+ const formatters = {};
4097
+ function defineMethod(name, keys, format) {
4098
+ formatters[name] = format;
4099
+ Object.assign(Schema, { [name](...args) {
4100
+ const schema = new Schema({ type: name });
4101
+ keys.forEach((key, index) => {
4102
+ switch (key) {
4103
+ case "sKey":
4104
+ schema.sKey = args[index] ?? Schema.string();
4105
+ break;
4106
+ case "inner":
4107
+ schema.inner = Schema.from(args[index]);
4108
+ break;
4109
+ case "list":
4110
+ schema.list = args[index].map(Schema.from);
4111
+ break;
4112
+ case "dict":
4113
+ schema.dict = mapValues(args[index], Schema.from);
4114
+ break;
4115
+ case "bits":
4116
+ schema.bits = {};
4117
+ for (const key in args[index]) {
4118
+ if (typeof args[index][key] !== "number") continue;
4119
+ schema.bits[key] = args[index][key];
4120
+ }
4121
+ break;
4122
+ case "callback": {
4123
+ const callback = schema.callback = args[index];
4124
+ callback["toJSON"] ||= () => callback.toString();
4125
+ break;
4126
+ }
4127
+ case "constructor": {
4128
+ const constructor = schema.constructor = args[index];
4129
+ if (typeof constructor === "function") constructor["toJSON"] ||= () => constructor["name"];
4130
+ break;
4131
+ }
4132
+ default: schema[key] = args[index];
4133
+ }
4134
+ });
4135
+ if (name === "object" || name === "dict") schema.meta.default = {};
4136
+ else if (name === "array" || name === "tuple") schema.meta.default = [];
4137
+ else if (name === "bitset") schema.meta.default = 0;
4138
+ return schema;
4139
+ } });
4140
+ }
4141
+ defineMethod("is", ["constructor"], ({ constructor }) => {
4142
+ if (typeof constructor === "function") return constructor.name;
4143
+ else return constructor;
4144
+ });
4145
+ defineMethod("any", [], () => "any");
4146
+ defineMethod("never", [], () => "never");
4147
+ defineMethod("const", ["value"], ({ value }) => typeof value === "string" ? JSON.stringify(value) : value);
4148
+ defineMethod("string", [], () => "string");
4149
+ defineMethod("number", [], () => "number");
4150
+ defineMethod("boolean", [], () => "boolean");
4151
+ defineMethod("bitset", ["bits"], () => "bitset");
4152
+ defineMethod("function", [], () => "function");
4153
+ defineMethod("array", ["inner"], ({ inner }) => `${inner.toString(true)}[]`);
4154
+ defineMethod("dict", ["inner", "sKey"], ({ inner, sKey }) => `{ [key: ${sKey.toString()}]: ${inner.toString()} }`);
4155
+ defineMethod("tuple", ["list"], ({ list }) => `[${list.map((inner) => inner.toString()).join(", ")}]`);
4156
+ defineMethod("object", ["dict"], ({ dict }) => {
4157
+ if (Object.keys(dict).length === 0) return "{}";
4158
+ return `{ ${Object.entries(dict).map(([key, inner]) => {
4159
+ return `${key}${inner.meta.required ? "" : "?"}: ${inner.toString()}`;
4160
+ }).join(", ")} }`;
4161
+ });
4162
+ defineMethod("union", ["list"], ({ list }, inline) => {
4163
+ const result = list.map(({ toString: format }) => format()).join(" | ");
4164
+ return inline ? `(${result})` : result;
4165
+ });
4166
+ defineMethod("intersect", ["list"], ({ list }) => {
4167
+ return `${list.map((inner) => inner.toString(true)).join(" & ")}`;
4168
+ });
4169
+ defineMethod("transform", [
4170
+ "inner",
4171
+ "callback",
4172
+ "preserve"
4173
+ ], ({ inner }, isInner) => inner.toString(isInner));
4174
+ //#endregion
4175
+ //#region lib/types/onboarding-config.js
4176
+ /** Public page-bootstrap options shared by the Host and Client halves. */
4177
+ /** Validate Host configuration and its public page-bootstrap payload. */
4178
+ const Config = Schema.object({ credentialOnboarding: Schema.boolean().default(true) });
4179
+ /** Page-global key carrying only the public onboarding options. */
4180
+ const ONBOARDING_CONFIG_GLOBAL = "__QILIN_MODELS_ONBOARDING__";
4181
+ //#endregion
3141
4182
  //#region lib/types/client/index.js
3142
4183
  /** Dictionary namespace owned by this plugin. */
3143
4184
  const NS = "settings.models";
@@ -3172,6 +4213,8 @@ window.__ModuleLoader__.load({
3172
4213
  * @param ctx - client root context.
3173
4214
  */
3174
4215
  function apply(ctx) {
4216
+ const payload = globalThis[ONBOARDING_CONFIG_GLOBAL];
4217
+ const configured = Config(payload === void 0 ? {} : payload);
3175
4218
  ctx.effect(() => ctx.locale.register(NS, {
3176
4219
  zh,
3177
4220
  en
@@ -3227,7 +4270,7 @@ window.__ModuleLoader__.load({
3227
4270
  }
3228
4271
  }
3229
4272
  }, ModelsSection));
3230
- ctx.slots.inject("settings.onboarding", () => ctx.slots.register({
4273
+ if (configured.credentialOnboarding) ctx.slots.inject("settings.onboarding", () => ctx.slots.register({
3231
4274
  name: "settings.onboarding",
3232
4275
  id: "deepseek-official",
3233
4276
  order: 0,