@qilin-agent/client-ui-settings-models 3.1.5 → 3.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.i18n.yaml +6 -6
- package/README.md +13 -3
- package/README.zh.md +13 -3
- package/lib/client.js +1476 -113
- package/lib/index.js +24 -4
- package/lib/types/client/ApiKeyInput.d.ts +17 -0
- package/lib/types/client/CustomProviderCard.d.ts +13 -5
- package/lib/types/client/ModelListEditor.d.ts +13 -0
- package/lib/types/client/ModelReasoningEfforts.d.ts +43 -0
- package/lib/types/client/ModelRow.d.ts +2 -0
- package/lib/types/client/ProviderEditor.d.ts +25 -6
- package/lib/types/client/index.d.ts +4 -2
- package/lib/types/client/locales.d.ts +24 -3
- package/lib/types/client/operations.d.ts +1 -7
- package/lib/types/client/store.d.ts +27 -4
- package/lib/types/index.d.ts +10 -3
- package/lib/types/onboarding-config.d.ts +16 -0
- package/package.json +18 -13
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_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_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_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:.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}";
|
|
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");
|
|
@@ -96,11 +96,15 @@ window.__ModuleLoader__.load({
|
|
|
96
96
|
"fetchDialog": "PF5DZW_fetchDialog",
|
|
97
97
|
"field": "PF5DZW_field",
|
|
98
98
|
"fieldLabel": "PF5DZW_fieldLabel",
|
|
99
|
+
"helpButton": "PF5DZW_helpButton",
|
|
99
100
|
"hiddenLabel": "PF5DZW_hiddenLabel",
|
|
100
101
|
"iconButton": "PF5DZW_iconButton",
|
|
101
102
|
"iconButtonDanger": "PF5DZW_iconButtonDanger",
|
|
102
103
|
"input": "PF5DZW_input",
|
|
103
104
|
"intro": "PF5DZW_intro",
|
|
105
|
+
"keyInput": "PF5DZW_keyInput",
|
|
106
|
+
"keyInputFilled": "PF5DZW_keyInputFilled",
|
|
107
|
+
"keyToggle": "PF5DZW_keyToggle",
|
|
104
108
|
"linkButton": "PF5DZW_linkButton",
|
|
105
109
|
"modelAdvanced": "PF5DZW_modelAdvanced",
|
|
106
110
|
"modelCatalog": "PF5DZW_modelCatalog",
|
|
@@ -115,6 +119,11 @@ window.__ModuleLoader__.load({
|
|
|
115
119
|
"modelInputTypes": "PF5DZW_modelInputTypes",
|
|
116
120
|
"modelList": "PF5DZW_modelList",
|
|
117
121
|
"modelListHead": "PF5DZW_modelListHead",
|
|
122
|
+
"modelReasoning": "PF5DZW_modelReasoning",
|
|
123
|
+
"modelReasoningHead": "PF5DZW_modelReasoningHead",
|
|
124
|
+
"modelReasoningLabel": "PF5DZW_modelReasoningLabel",
|
|
125
|
+
"modelReasoningRow": "PF5DZW_modelReasoningRow",
|
|
126
|
+
"modelReasoningValueInput": "PF5DZW_modelReasoningValueInput",
|
|
118
127
|
"modelRow": "PF5DZW_modelRow",
|
|
119
128
|
"notice": "PF5DZW_notice",
|
|
120
129
|
"primaryButton": "PF5DZW_primaryButton",
|
|
@@ -134,6 +143,55 @@ window.__ModuleLoader__.load({
|
|
|
134
143
|
"title": "PF5DZW_title"
|
|
135
144
|
};
|
|
136
145
|
//#endregion
|
|
146
|
+
//#region lib/types/client/ApiKeyInput.js
|
|
147
|
+
/** Write-only credential input with the same reveal behavior as masked conversation text. */
|
|
148
|
+
const EYE_CONTOUR = "M1.5 8C2.9 5.25 5.25 3.5 8 3.5C10.75 3.5 13.1 5.25 14.5 8C13.1 10.75 10.75 12.5 8 12.5C5.25 12.5 2.9 10.75 1.5 8Z";
|
|
149
|
+
const EYE_PATH = `${EYE_CONTOUR}M10 8C10 9.1 9.1 10 8 10C6.9 10 6 9.1 6 8C6 6.9 6.9 6 8 6C9.1 6 10 6.9 10 8Z`;
|
|
150
|
+
const EYE_OFF_PATH = `${EYE_CONTOUR}M2.5 2.5L13.5 13.5`;
|
|
151
|
+
/**
|
|
152
|
+
* Reveal only a nonempty draft; a different value starts masked, as in SecretText.
|
|
153
|
+
* @param props - current draft, input attributes, and translated control labels.
|
|
154
|
+
* @returns a password input with an optional reveal button.
|
|
155
|
+
*/
|
|
156
|
+
function ApiKeyInput({ value, t, ...props }) {
|
|
157
|
+
const [revealedValue, setRevealedValue] = (0, react.useState)();
|
|
158
|
+
const revealed = value.length > 0 && revealedValue === value;
|
|
159
|
+
return (0, react_jsx_runtime.jsxs)("div", {
|
|
160
|
+
className: ModelsSection_module_css_default["keyInput"],
|
|
161
|
+
children: [(0, react_jsx_runtime.jsx)("input", {
|
|
162
|
+
...props,
|
|
163
|
+
className: `${ModelsSection_module_css_default["input"]} ${value.length > 0 ? ModelsSection_module_css_default["keyInputFilled"] : ""}`,
|
|
164
|
+
type: revealed ? "text" : "password",
|
|
165
|
+
autoComplete: "new-password",
|
|
166
|
+
value,
|
|
167
|
+
onChange: (event) => {
|
|
168
|
+
setRevealedValue(void 0);
|
|
169
|
+
props.onChange?.(event);
|
|
170
|
+
}
|
|
171
|
+
}), value.length === 0 ? null : (0, react_jsx_runtime.jsx)("button", {
|
|
172
|
+
type: "button",
|
|
173
|
+
className: ModelsSection_module_css_default["keyToggle"],
|
|
174
|
+
"aria-label": t(revealed ? "keyHide" : "keyReveal"),
|
|
175
|
+
"aria-pressed": revealed,
|
|
176
|
+
disabled: props.disabled,
|
|
177
|
+
onClick: () => {
|
|
178
|
+
setRevealedValue(revealed ? void 0 : value);
|
|
179
|
+
},
|
|
180
|
+
children: (0, react_jsx_runtime.jsx)("svg", {
|
|
181
|
+
width: "16",
|
|
182
|
+
height: "16",
|
|
183
|
+
viewBox: "0 0 16 16",
|
|
184
|
+
fill: "none",
|
|
185
|
+
stroke: "currentColor",
|
|
186
|
+
strokeWidth: 1.3,
|
|
187
|
+
strokeLinecap: "round",
|
|
188
|
+
"aria-hidden": "true",
|
|
189
|
+
children: (0, react_jsx_runtime.jsx)("path", { d: revealed ? EYE_OFF_PATH : EYE_PATH })
|
|
190
|
+
})
|
|
191
|
+
})]
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
//#endregion
|
|
137
195
|
//#region lib/types/client/EditorFooter.js
|
|
138
196
|
/**
|
|
139
197
|
* Render one provider card's action row.
|
|
@@ -198,6 +256,224 @@ window.__ModuleLoader__.load({
|
|
|
198
256
|
});
|
|
199
257
|
}
|
|
200
258
|
//#endregion
|
|
259
|
+
//#region lib/types/client/ModelReasoningEfforts.js
|
|
260
|
+
/** Reasoning-level declarations for a model on a hand-declared pi-ai route. */
|
|
261
|
+
/** Levels a model offers when the switch is turned on, where the schema lists them: Off plus the common OpenAI-compatible trio. */
|
|
262
|
+
const INITIAL_LEVELS = [
|
|
263
|
+
"off",
|
|
264
|
+
"low",
|
|
265
|
+
"medium",
|
|
266
|
+
"high"
|
|
267
|
+
];
|
|
268
|
+
/** The wire value a level sends unless its row says otherwise; `null` is the Off entry that sends nothing. */
|
|
269
|
+
function defaultValue(level) {
|
|
270
|
+
return level === "off" ? null : level;
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Whether pi-ai accepts a stored value: a non-empty string, or nothing for Off.
|
|
274
|
+
* @param level - the declared level.
|
|
275
|
+
* @param wire - the value stored for it.
|
|
276
|
+
* @returns whether the adapter would resolve the entry.
|
|
277
|
+
*/
|
|
278
|
+
function acceptedValue(level, wire) {
|
|
279
|
+
return typeof wire === "string" ? wire.length > 0 : wire === null && level === "off";
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Read the declared levels from a row in their stored order, including a key
|
|
283
|
+
* the offered levels do not name, so an edit never drops it.
|
|
284
|
+
* @param model - model row as drafted.
|
|
285
|
+
* @returns the entries; empty for a valueless field, which pi-ai refuses, and
|
|
286
|
+
* `undefined` when the field is absent or `false`.
|
|
287
|
+
*/
|
|
288
|
+
function readEfforts(model) {
|
|
289
|
+
const value = model["reasoningEfforts"];
|
|
290
|
+
if (value === null) return [];
|
|
291
|
+
if (typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
292
|
+
return Object.entries(value);
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Replace a row's declared levels, preserving every other field.
|
|
296
|
+
* @param model - model row as drafted.
|
|
297
|
+
* @param entries - the levels to write in row order, or `undefined` to remove the field.
|
|
298
|
+
* @returns the replacement row.
|
|
299
|
+
*/
|
|
300
|
+
function withEfforts(model, entries) {
|
|
301
|
+
const next = { ...model };
|
|
302
|
+
if (entries === void 0) {
|
|
303
|
+
Reflect.deleteProperty(next, "reasoningEfforts");
|
|
304
|
+
return next;
|
|
305
|
+
}
|
|
306
|
+
next["reasoningEfforts"] = Object.fromEntries(entries);
|
|
307
|
+
return next;
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Mirror the pi-ai refusals of a hand-declared `reasoningEfforts`, so a card
|
|
311
|
+
* names the row instead of failing at the write.
|
|
312
|
+
* @param value - drafted `models` value, or `undefined` while inherited.
|
|
313
|
+
* @returns the first refused row, or `undefined` when the adapter will accept every row.
|
|
314
|
+
*/
|
|
315
|
+
function validateReasoningEfforts(value) {
|
|
316
|
+
for (const [index, model] of modelDrafts(value).entries()) {
|
|
317
|
+
const entries = readEfforts(model);
|
|
318
|
+
if (entries === void 0) continue;
|
|
319
|
+
if (entries.some(([level, wire]) => !acceptedValue(level, wire))) return {
|
|
320
|
+
index,
|
|
321
|
+
key: "modelReasoningValueRequired"
|
|
322
|
+
};
|
|
323
|
+
if (!entries.some(([level]) => level !== "off")) return {
|
|
324
|
+
index,
|
|
325
|
+
key: "modelReasoningNeedsLevel"
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Edit the `reasoningEfforts` a hand-declared pi-ai model offers: a switch,
|
|
331
|
+
* then one row per level pairing the level with the value sent for it. Every
|
|
332
|
+
* row is read from the model, so a reused instance shows its new model.
|
|
333
|
+
* @param props - model declaration and row replacement action.
|
|
334
|
+
* @returns the reasoning-level group.
|
|
335
|
+
*/
|
|
336
|
+
function ModelReasoningEfforts({ model, levels, position, disabled, t, onChange }) {
|
|
337
|
+
const entries = readEfforts(model);
|
|
338
|
+
const [typing, setTyping] = (0, react.useState)(void 0);
|
|
339
|
+
const label = `${t("modelReasoning")} ${String(position)}`;
|
|
340
|
+
const used = entries?.map(([level]) => level) ?? [];
|
|
341
|
+
const write = (next) => {
|
|
342
|
+
onChange(withEfforts(model, next));
|
|
343
|
+
};
|
|
344
|
+
const replaceAt = (current, index, entry) => current.map((existing, at) => at === index ? entry : existing);
|
|
345
|
+
const changeLevel = (current, index, from, wire, to) => {
|
|
346
|
+
write(replaceAt(current, index, [to, typeof wire === "string" && wire.length > 0 && wire !== from && from !== "off" && to !== "off" ? wire : defaultValue(to)]));
|
|
347
|
+
};
|
|
348
|
+
const addLevel = (current) => {
|
|
349
|
+
const highest = Math.max(-1, ...used.map((level) => levels.indexOf(level)));
|
|
350
|
+
const level = levels.find((candidate, index) => index > highest && !used.includes(candidate)) ?? levels.find((candidate) => !used.includes(candidate));
|
|
351
|
+
/* v8 ignore next -- the add button is disabled once every level has a row */
|
|
352
|
+
if (level === void 0) return;
|
|
353
|
+
write([...current, [level, defaultValue(level)]]);
|
|
354
|
+
};
|
|
355
|
+
const editValue = (current, index, level, text) => {
|
|
356
|
+
setTyping({
|
|
357
|
+
level,
|
|
358
|
+
text
|
|
359
|
+
});
|
|
360
|
+
const trimmed = text.trim();
|
|
361
|
+
write(replaceAt(current, index, [level, trimmed.length === 0 ? defaultValue(level) : trimmed]));
|
|
362
|
+
};
|
|
363
|
+
const leaveValue = (current, index, level, wire) => {
|
|
364
|
+
setTyping(void 0);
|
|
365
|
+
if (!acceptedValue(level, wire)) write(replaceAt(current, index, [level, defaultValue(level)]));
|
|
366
|
+
};
|
|
367
|
+
const choicesFor = (level) => [...levels.includes(level) ? [] : [level], ...levels.filter((choice) => choice === level || !used.includes(choice))];
|
|
368
|
+
const initialEntries = INITIAL_LEVELS.filter((level) => levels.includes(level)).map((level) => [level, defaultValue(level)]);
|
|
369
|
+
const refused = entries?.some(([level, wire]) => !acceptedValue(level, wire)) === true;
|
|
370
|
+
const missingLevel = entries !== void 0 && !used.some((level) => level !== "off");
|
|
371
|
+
return (0, react_jsx_runtime.jsxs)("div", {
|
|
372
|
+
className: ModelsSection_module_css_default["modelReasoning"],
|
|
373
|
+
role: "group",
|
|
374
|
+
"aria-label": label,
|
|
375
|
+
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
376
|
+
className: ModelsSection_module_css_default["modelReasoningHead"],
|
|
377
|
+
children: [(0, react_jsx_runtime.jsxs)("span", {
|
|
378
|
+
className: `${ModelsSection_module_css_default["modelFieldLabel"]} ${ModelsSection_module_css_default["modelReasoningLabel"]}`,
|
|
379
|
+
children: [t("modelReasoning"), (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.Tooltip, {
|
|
380
|
+
label: t("modelReasoningHelpText"),
|
|
381
|
+
side: "right",
|
|
382
|
+
delayMs: 0,
|
|
383
|
+
focusDelayMs: 0,
|
|
384
|
+
portal: true,
|
|
385
|
+
openOnClick: true,
|
|
386
|
+
children: (0, react_jsx_runtime.jsx)("button", {
|
|
387
|
+
type: "button",
|
|
388
|
+
className: ModelsSection_module_css_default["helpButton"],
|
|
389
|
+
"aria-label": t("modelReasoningHelp"),
|
|
390
|
+
children: "?"
|
|
391
|
+
})
|
|
392
|
+
})]
|
|
393
|
+
}), (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.Switch, {
|
|
394
|
+
checked: entries !== void 0,
|
|
395
|
+
label,
|
|
396
|
+
disabled,
|
|
397
|
+
onChange: (on) => {
|
|
398
|
+
write(on ? initialEntries : void 0);
|
|
399
|
+
}
|
|
400
|
+
})]
|
|
401
|
+
}), entries === void 0 ? null : (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
402
|
+
entries.length > 0 ? (0, react_jsx_runtime.jsxs)("div", {
|
|
403
|
+
className: ModelsSection_module_css_default["modelReasoningRow"],
|
|
404
|
+
"aria-hidden": "true",
|
|
405
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
406
|
+
className: ModelsSection_module_css_default["modelFieldLabel"],
|
|
407
|
+
children: t("modelReasoningLevel")
|
|
408
|
+
}), (0, react_jsx_runtime.jsx)("span", {
|
|
409
|
+
className: ModelsSection_module_css_default["modelFieldLabel"],
|
|
410
|
+
children: t("modelReasoningValue")
|
|
411
|
+
})]
|
|
412
|
+
}) : null,
|
|
413
|
+
entries.map(([level, wire], index) => (0, react_jsx_runtime.jsxs)("div", {
|
|
414
|
+
className: ModelsSection_module_css_default["modelReasoningRow"],
|
|
415
|
+
children: [
|
|
416
|
+
(0, react_jsx_runtime.jsx)("select", {
|
|
417
|
+
className: `${ModelsSection_module_css_default["input"]} ${ModelsSection_module_css_default["selectInput"]}`,
|
|
418
|
+
value: level,
|
|
419
|
+
"aria-label": `${t("modelReasoningLevel")} ${String(index + 1)}`,
|
|
420
|
+
disabled,
|
|
421
|
+
onChange: (event) => {
|
|
422
|
+
changeLevel(entries, index, level, wire, event.target.value);
|
|
423
|
+
},
|
|
424
|
+
children: choicesFor(level).map((choice) => (0, react_jsx_runtime.jsx)("option", {
|
|
425
|
+
value: choice,
|
|
426
|
+
children: choice
|
|
427
|
+
}, choice))
|
|
428
|
+
}),
|
|
429
|
+
(0, react_jsx_runtime.jsx)("input", {
|
|
430
|
+
className: `${ModelsSection_module_css_default["input"]} ${ModelsSection_module_css_default["modelReasoningValueInput"]}`,
|
|
431
|
+
type: "text",
|
|
432
|
+
value: typing?.level === level ? typing.text : typeof wire === "string" ? wire : "",
|
|
433
|
+
placeholder: level === "off" ? t("modelReasoningOffValuePlaceholder") : level,
|
|
434
|
+
"aria-label": `${level} ${t("modelReasoningValue")}`,
|
|
435
|
+
"aria-invalid": !acceptedValue(level, wire),
|
|
436
|
+
disabled: disabled || level === "off",
|
|
437
|
+
onChange: (event) => {
|
|
438
|
+
editValue(entries, index, level, event.target.value);
|
|
439
|
+
},
|
|
440
|
+
onBlur: () => {
|
|
441
|
+
leaveValue(entries, index, level, wire);
|
|
442
|
+
}
|
|
443
|
+
}),
|
|
444
|
+
(0, react_jsx_runtime.jsx)("button", {
|
|
445
|
+
type: "button",
|
|
446
|
+
className: `${ModelsSection_module_css_default["iconButton"]} ${ModelsSection_module_css_default["iconButtonDanger"]}`,
|
|
447
|
+
"aria-label": `${t("modelReasoningRemove")} ${level}`,
|
|
448
|
+
title: t("modelReasoningRemove"),
|
|
449
|
+
disabled,
|
|
450
|
+
onClick: () => {
|
|
451
|
+
write(entries.filter((_entry, at) => at !== index));
|
|
452
|
+
},
|
|
453
|
+
children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconTrashOutlineRegular, { size: 14 })
|
|
454
|
+
})
|
|
455
|
+
]
|
|
456
|
+
}, index)),
|
|
457
|
+
refused ? (0, react_jsx_runtime.jsx)("p", {
|
|
458
|
+
className: ModelsSection_module_css_default["error"],
|
|
459
|
+
children: t("modelReasoningValueRequired")
|
|
460
|
+
}) : missingLevel ? (0, react_jsx_runtime.jsx)("p", {
|
|
461
|
+
className: ModelsSection_module_css_default["error"],
|
|
462
|
+
children: t("modelReasoningNeedsLevel")
|
|
463
|
+
}) : null,
|
|
464
|
+
(0, react_jsx_runtime.jsxs)("button", {
|
|
465
|
+
type: "button",
|
|
466
|
+
className: ModelsSection_module_css_default["addModelButton"],
|
|
467
|
+
disabled: disabled || levels.every((level) => used.includes(level)),
|
|
468
|
+
onClick: () => {
|
|
469
|
+
addLevel(entries);
|
|
470
|
+
},
|
|
471
|
+
children: [(0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconPlusOutlineRegular, { size: 14 }), t("modelReasoningAdd")]
|
|
472
|
+
})
|
|
473
|
+
] })]
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
//#endregion
|
|
201
477
|
//#region lib/types/client/ModelRow.js
|
|
202
478
|
/**
|
|
203
479
|
* Render consistent model identity, capacity, and input-type controls.
|
|
@@ -231,7 +507,7 @@ window.__ModuleLoader__.load({
|
|
|
231
507
|
"aria-expanded": props.expanded,
|
|
232
508
|
title: t("modelAdvanced"),
|
|
233
509
|
onClick: props.onToggle,
|
|
234
|
-
children: props.expanded ? (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.
|
|
510
|
+
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, {})
|
|
235
511
|
}),
|
|
236
512
|
(0, react_jsx_runtime.jsx)("button", {
|
|
237
513
|
type: "button",
|
|
@@ -240,38 +516,49 @@ window.__ModuleLoader__.load({
|
|
|
240
516
|
title: t("removeModel"),
|
|
241
517
|
disabled,
|
|
242
518
|
onClick: props.onRemove,
|
|
243
|
-
children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.
|
|
519
|
+
children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconTrashOutlineRegular, { size: 14 })
|
|
244
520
|
})
|
|
245
521
|
]
|
|
246
522
|
}), props.expanded ? (0, react_jsx_runtime.jsxs)("div", {
|
|
247
523
|
className: ModelsSection_module_css_default["modelAdvanced"],
|
|
248
|
-
children: [
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
524
|
+
children: [
|
|
525
|
+
["contextWindow", "maxTokens"].map((field) => (0, react_jsx_runtime.jsxs)("label", {
|
|
526
|
+
className: ModelsSection_module_css_default["modelField"],
|
|
527
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
528
|
+
className: ModelsSection_module_css_default["modelFieldLabel"],
|
|
529
|
+
children: t(field)
|
|
530
|
+
}), (0, react_jsx_runtime.jsx)("input", {
|
|
531
|
+
className: ModelsSection_module_css_default["input"],
|
|
532
|
+
type: "text",
|
|
533
|
+
inputMode: "numeric",
|
|
534
|
+
value: props[field].value,
|
|
535
|
+
placeholder: props[field].placeholder,
|
|
536
|
+
"aria-label": `${t(field)} ${String(position)}`,
|
|
537
|
+
disabled,
|
|
538
|
+
onChange: (event) => {
|
|
539
|
+
props[field].onChange(event.target.value);
|
|
540
|
+
},
|
|
541
|
+
onBlur: props[field].onBlur
|
|
542
|
+
})]
|
|
543
|
+
}, field)),
|
|
544
|
+
(0, react_jsx_runtime.jsx)(ModelInputTypes, {
|
|
545
|
+
model,
|
|
546
|
+
field: props.inputField,
|
|
547
|
+
position,
|
|
548
|
+
fallback: props.inputFallback,
|
|
549
|
+
disabled: disabled || props.inputLoading === true,
|
|
550
|
+
t,
|
|
551
|
+
onChange: props.onChange
|
|
552
|
+
}),
|
|
553
|
+
props.reasoningLevels !== void 0 && props.reasoningLevels.length > 0 ? (0, react_jsx_runtime.jsx)(ModelReasoningEfforts, {
|
|
554
|
+
model,
|
|
555
|
+
levels: props.reasoningLevels,
|
|
556
|
+
position,
|
|
260
557
|
disabled,
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
})]
|
|
266
|
-
}, field)), (0, react_jsx_runtime.jsx)(ModelInputTypes, {
|
|
267
|
-
model,
|
|
268
|
-
field: props.inputField,
|
|
269
|
-
position,
|
|
270
|
-
fallback: props.inputFallback,
|
|
271
|
-
disabled: disabled || props.inputLoading === true,
|
|
272
|
-
t,
|
|
273
|
-
onChange: props.onChange
|
|
274
|
-
})]
|
|
558
|
+
t,
|
|
559
|
+
onChange: props.onChange
|
|
560
|
+
}) : null
|
|
561
|
+
]
|
|
275
562
|
}) : null]
|
|
276
563
|
});
|
|
277
564
|
}
|
|
@@ -511,7 +798,7 @@ window.__ModuleLoader__.load({
|
|
|
511
798
|
onClick: () => {
|
|
512
799
|
props.onChange([...props.models.map((model) => ({ ...model })), { id: "" }]);
|
|
513
800
|
},
|
|
514
|
-
children: [(0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.
|
|
801
|
+
children: [(0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconPlusOutlineRegular, { size: 14 }), props.t("addModel")]
|
|
515
802
|
})
|
|
516
803
|
]
|
|
517
804
|
});
|
|
@@ -584,9 +871,12 @@ window.__ModuleLoader__.load({
|
|
|
584
871
|
* @returns the model-list editor.
|
|
585
872
|
*/
|
|
586
873
|
function ModelListEditor(props) {
|
|
587
|
-
const { models, onChange, probe, operations, t, disabled } = props;
|
|
874
|
+
const { models, onChange, probe, operations, t, disabled, onBusyChange } = props;
|
|
588
875
|
const { catalogProvider } = props;
|
|
589
876
|
const [busy, setBusy] = (0, react.useState)(false);
|
|
877
|
+
(0, react.useEffect)(() => {
|
|
878
|
+
onBusyChange(busy);
|
|
879
|
+
}, [busy, onBusyChange]);
|
|
590
880
|
const [failure, setFailure] = (0, react.useState)(void 0);
|
|
591
881
|
const [inheritedCatalog, setInheritedCatalog] = (0, react.useState)(void 0);
|
|
592
882
|
(0, react.useEffect)(() => {
|
|
@@ -765,6 +1055,7 @@ window.__ModuleLoader__.load({
|
|
|
765
1055
|
inputField: "input",
|
|
766
1056
|
inputFallback: inputDefaults.get(textOf(model, "id")) ?? props.defaultInput,
|
|
767
1057
|
inputLoading: catalogProvider !== void 0 && catalog === void 0,
|
|
1058
|
+
reasoningLevels: props.reasoningLevels,
|
|
768
1059
|
expanded: expanded.has(index),
|
|
769
1060
|
disabled,
|
|
770
1061
|
t,
|
|
@@ -810,7 +1101,7 @@ window.__ModuleLoader__.load({
|
|
|
810
1101
|
onClick: () => {
|
|
811
1102
|
onChange([...models, { id: "" }]);
|
|
812
1103
|
},
|
|
813
|
-
children: [(0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.
|
|
1104
|
+
children: [(0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconPlusOutlineRegular, { size: 14 }), t("addModel")]
|
|
814
1105
|
}),
|
|
815
1106
|
failure !== void 0 ? (0, react_jsx_runtime.jsx)("p", {
|
|
816
1107
|
className: ModelsSection_module_css_default["error"],
|
|
@@ -908,6 +1199,9 @@ window.__ModuleLoader__.load({
|
|
|
908
1199
|
settingsPath: [...entry.settingsPath],
|
|
909
1200
|
active: active.has(entry.provider),
|
|
910
1201
|
...entry.declared === void 0 ? {} : { declared: entry.declared },
|
|
1202
|
+
...entry.defaultBaseURL === void 0 ? {} : { defaultBaseURL: entry.defaultBaseURL },
|
|
1203
|
+
...entry.baseURLEnv === void 0 ? {} : { baseURLEnv: entry.baseURLEnv },
|
|
1204
|
+
...entry.nativeAuth === void 0 ? {} : { nativeAuth: entry.nativeAuth },
|
|
911
1205
|
...entry.error === void 0 ? {} : { error: entry.error }
|
|
912
1206
|
}));
|
|
913
1207
|
for (const provider of registered) {
|
|
@@ -951,6 +1245,26 @@ window.__ModuleLoader__.load({
|
|
|
951
1245
|
if (list?.type !== "union" || list.list === void 0) return [];
|
|
952
1246
|
return list.list.map((entry) => entry.value).filter((value) => typeof value === "string");
|
|
953
1247
|
}
|
|
1248
|
+
/**
|
|
1249
|
+
* The reasoning levels a hand-declared route's models may declare, read out of
|
|
1250
|
+
* the owning namespace's own schema for the same reason as
|
|
1251
|
+
* {@link protocolChoices}: the levels the page offers and the keys the
|
|
1252
|
+
* adapter accepts in `reasoningEfforts` come from the same `Config`.
|
|
1253
|
+
* @param namespace - the namespace view whose schema declares the profile shape.
|
|
1254
|
+
* @param schema - settings schema operations.
|
|
1255
|
+
* @returns the levels in the schema's escalation order, or an empty list when the schema has none.
|
|
1256
|
+
*/
|
|
1257
|
+
function reasoningLevelChoices(namespace, schema) {
|
|
1258
|
+
if (namespace === void 0) return [];
|
|
1259
|
+
const path = [
|
|
1260
|
+
"providers",
|
|
1261
|
+
PROBE_ROUTE,
|
|
1262
|
+
"models",
|
|
1263
|
+
"0",
|
|
1264
|
+
"reasoningEfforts"
|
|
1265
|
+
];
|
|
1266
|
+
return (((schema.nodeAtPath(schema.rehydrate(namespace.schema), path)?.list ?? []).find((branch) => branch.type === "dict")?.sKey)?.list ?? []).map((entry) => entry.value).filter((value) => typeof value === "string");
|
|
1267
|
+
}
|
|
954
1268
|
/** The credential reference a resolved profile names (its `apiKeyEnv` field). */
|
|
955
1269
|
function apiKeyEnvOf(namespace, path, schema) {
|
|
956
1270
|
if (namespace === void 0) return void 0;
|
|
@@ -975,6 +1289,8 @@ window.__ModuleLoader__.load({
|
|
|
975
1289
|
});
|
|
976
1290
|
/** Latest load wins; an older response never overwrites a newer one. */
|
|
977
1291
|
generation = 0;
|
|
1292
|
+
/** Callers follow the current refresh's outcome, including callers whose read was superseded. */
|
|
1293
|
+
pendingLoads = /* @__PURE__ */ new Set();
|
|
978
1294
|
/**
|
|
979
1295
|
* @param ctx - the page plugin's context, whose `remote.llm` and
|
|
980
1296
|
* `remote.credentials` namespaces carry the directory and credential reads.
|
|
@@ -991,11 +1307,28 @@ window.__ModuleLoader__.load({
|
|
|
991
1307
|
* settings answer in parallel, then one batched credential describe over
|
|
992
1308
|
* every referenced ref. Provider failure or absence of an initial settings
|
|
993
1309
|
* answer keeps the last good rows and surfaces an error; a failed settings
|
|
994
|
-
* refresh reuses the mirror's held view.
|
|
995
|
-
*
|
|
1310
|
+
* refresh reuses the mirror's held view. Concurrent callers resolve only
|
|
1311
|
+
* after the current refresh publishes its ready or error snapshot.
|
|
1312
|
+
* @returns resolution after the current snapshot is published.
|
|
1313
|
+
* @throws the current read's unexpected rejection; superseded rejections are ignored.
|
|
996
1314
|
*/
|
|
997
|
-
|
|
1315
|
+
load() {
|
|
1316
|
+
const pending = Promise.withResolvers();
|
|
1317
|
+
this.pendingLoads.add(pending);
|
|
998
1318
|
const generation = ++this.generation;
|
|
1319
|
+
this.read(generation).then(() => {
|
|
1320
|
+
this.settleLoads(generation, (load) => {
|
|
1321
|
+
load.resolve();
|
|
1322
|
+
});
|
|
1323
|
+
}, (error) => {
|
|
1324
|
+
this.settleLoads(generation, (load) => {
|
|
1325
|
+
load.reject(error);
|
|
1326
|
+
});
|
|
1327
|
+
});
|
|
1328
|
+
return pending.promise;
|
|
1329
|
+
}
|
|
1330
|
+
/** Publish one joined answer; stale answers leave the current refresh in charge. */
|
|
1331
|
+
async read(generation) {
|
|
999
1332
|
this.store.update((s) => {
|
|
1000
1333
|
s.status = "loading";
|
|
1001
1334
|
s.error = null;
|
|
@@ -1005,17 +1338,20 @@ window.__ModuleLoader__.load({
|
|
|
1005
1338
|
this.ctx.remote.llm.listConfigurableProviders(),
|
|
1006
1339
|
this.describeFace.ensure()
|
|
1007
1340
|
]);
|
|
1341
|
+
if (generation !== this.generation) return;
|
|
1008
1342
|
if (!registered.ok) {
|
|
1009
|
-
this.failLoad(
|
|
1343
|
+
this.failLoad(registered.error.message);
|
|
1010
1344
|
return;
|
|
1011
1345
|
}
|
|
1012
1346
|
if (!declared.ok) {
|
|
1013
|
-
this.failLoad(
|
|
1347
|
+
this.failLoad(declared.error.message);
|
|
1014
1348
|
return;
|
|
1015
1349
|
}
|
|
1016
1350
|
const mirrored = this.describeFace.getSnapshot();
|
|
1017
1351
|
if (mirrored.view === void 0) {
|
|
1018
|
-
|
|
1352
|
+
/* v8 ignore next -- SettingsDescribeFace.ensure settles with a view or the read's error */
|
|
1353
|
+
if (mirrored.error === null) throw new Error("settings describe settled with neither a view nor an error");
|
|
1354
|
+
this.failLoad(mirrored.error);
|
|
1019
1355
|
return;
|
|
1020
1356
|
}
|
|
1021
1357
|
const providers = joinProviderDirectory(registered.value, declared.value);
|
|
@@ -1032,14 +1368,20 @@ window.__ModuleLoader__.load({
|
|
|
1032
1368
|
credential: void 0
|
|
1033
1369
|
};
|
|
1034
1370
|
});
|
|
1035
|
-
const refs = [...new Set(rows.
|
|
1036
|
-
|
|
1371
|
+
const refs = [...new Set(rows.flatMap((row) => row.apiKeyEnv === void 0 ? [deriveKeyRef(row.entry.provider), ...row.entry.nativeAuth?.env ?? []] : [row.apiKeyEnv]))];
|
|
1372
|
+
const credentials = {};
|
|
1037
1373
|
let credentialError = null;
|
|
1038
|
-
|
|
1039
|
-
const response = await this.ctx.remote.credentials.describe(refs);
|
|
1040
|
-
if (response.ok) credentials
|
|
1041
|
-
else
|
|
1374
|
+
for (let index = 0; index < refs.length; index += 64) {
|
|
1375
|
+
const response = await this.ctx.remote.credentials.describe(refs.slice(index, index + 64));
|
|
1376
|
+
if (response.ok) Object.assign(credentials, response.value);
|
|
1377
|
+
else {
|
|
1378
|
+
credentialError = response.error.message;
|
|
1379
|
+
break;
|
|
1380
|
+
}
|
|
1042
1381
|
}
|
|
1382
|
+
/* v8 ignore next -- the credential describe answers in one promise, so a read
|
|
1383
|
+
* superseded at the earlier generation check never reaches this second guard;
|
|
1384
|
+
* it stays for a future multi-batch describe where supersede windows reopen. */
|
|
1043
1385
|
if (generation !== this.generation) return;
|
|
1044
1386
|
this.store.update((s) => {
|
|
1045
1387
|
s.status = "ready";
|
|
@@ -1052,15 +1394,25 @@ window.__ModuleLoader__.load({
|
|
|
1052
1394
|
return {
|
|
1053
1395
|
...row,
|
|
1054
1396
|
...named === void 0 ? {} : { credential: named },
|
|
1055
|
-
...derived === void 0 ? {} : { derivedCredential: derived }
|
|
1397
|
+
...derived === void 0 ? {} : { derivedCredential: derived },
|
|
1398
|
+
...credentialError === null ? { credentialChecks: Object.fromEntries((row.apiKeyEnv === void 0 ? row.entry.nativeAuth?.env ?? [] : [row.apiKeyEnv]).flatMap((ref) => {
|
|
1399
|
+
const info = credentials[ref];
|
|
1400
|
+
return info === void 0 ? [] : [[ref, info]];
|
|
1401
|
+
})) } : {}
|
|
1056
1402
|
};
|
|
1057
1403
|
});
|
|
1058
1404
|
s.namespaces = namespaces;
|
|
1059
1405
|
});
|
|
1060
1406
|
}
|
|
1061
|
-
/**
|
|
1062
|
-
|
|
1407
|
+
/** Settle callers only while this read still owns the current refresh. */
|
|
1408
|
+
settleLoads(generation, settle) {
|
|
1063
1409
|
if (generation !== this.generation) return;
|
|
1410
|
+
const pending = [...this.pendingLoads];
|
|
1411
|
+
this.pendingLoads.clear();
|
|
1412
|
+
for (const load of pending) settle(load);
|
|
1413
|
+
}
|
|
1414
|
+
/** Publish one load's failure text; the caller checked the current generation. */
|
|
1415
|
+
failLoad(message) {
|
|
1064
1416
|
this.store.update((s) => {
|
|
1065
1417
|
s.status = "error";
|
|
1066
1418
|
s.error = message;
|
|
@@ -1162,11 +1514,12 @@ window.__ModuleLoader__.load({
|
|
|
1162
1514
|
* and at least one model — are required here rather than at load, so the
|
|
1163
1515
|
* failure names the field while the user is still looking at it.
|
|
1164
1516
|
*
|
|
1165
|
-
* There is deliberately no reasoning-effort control, here or
|
|
1166
|
-
* card: effort is a per-MODEL capability, and the models under
|
|
1167
|
-
* disagree about it, so a provider-scoped control can only be set
|
|
1168
|
-
* some of them reject.
|
|
1169
|
-
*
|
|
1517
|
+
* There is deliberately no provider-scoped reasoning-effort control, here or
|
|
1518
|
+
* on the editor card: effort is a per-MODEL capability, and the models under
|
|
1519
|
+
* one provider disagree about it, so a provider-scoped control can only be set
|
|
1520
|
+
* to a value some of them reject. Each model row of a hand-declared route
|
|
1521
|
+
* declares its own `reasoningEfforts` instead, and the composer's model picker
|
|
1522
|
+
* offers each model those levels.
|
|
1170
1523
|
*/
|
|
1171
1524
|
/** The settings namespace a hand-declared provider is written into. */
|
|
1172
1525
|
const NS$1 = "llm-pi-ai";
|
|
@@ -1193,7 +1546,7 @@ window.__ModuleLoader__.load({
|
|
|
1193
1546
|
* @returns the creation card.
|
|
1194
1547
|
*/
|
|
1195
1548
|
function CustomProviderCard(props) {
|
|
1196
|
-
const { taken, protocols, operations, t } = props;
|
|
1549
|
+
const { taken, protocols, reasoningLevels, operations, t, onBusyChange } = props;
|
|
1197
1550
|
const [openedAt] = (0, react.useState)(() => props.revision);
|
|
1198
1551
|
const [route, setRoute] = (0, react.useState)("");
|
|
1199
1552
|
const [displayName, setDisplayName] = (0, react.useState)("");
|
|
@@ -1202,6 +1555,14 @@ window.__ModuleLoader__.load({
|
|
|
1202
1555
|
const [keyDraft, setKeyDraft] = (0, react.useState)("");
|
|
1203
1556
|
const [models, setModels] = (0, react.useState)([]);
|
|
1204
1557
|
const [busy, setBusy] = (0, react.useState)(false);
|
|
1558
|
+
const [listBusy, setListBusy] = (0, react.useState)(false);
|
|
1559
|
+
(0, react.useEffect)(() => {
|
|
1560
|
+
onBusyChange?.(busy || listBusy);
|
|
1561
|
+
}, [
|
|
1562
|
+
busy,
|
|
1563
|
+
listBusy,
|
|
1564
|
+
onBusyChange
|
|
1565
|
+
]);
|
|
1205
1566
|
const [failure, setFailure] = (0, react.useState)(void 0);
|
|
1206
1567
|
/**
|
|
1207
1568
|
* The profile write landed. Only the key write can still be outstanding, so
|
|
@@ -1216,7 +1577,7 @@ window.__ModuleLoader__.load({
|
|
|
1216
1577
|
const routeTaken = taken.includes(route);
|
|
1217
1578
|
const normalizedBaseURL = baseURL.trim();
|
|
1218
1579
|
const baseUrlInvalid = baseURL.length > 0 && !isHttpUrl(normalizedBaseURL);
|
|
1219
|
-
const modelFailure = validateDeepSeekModels(models);
|
|
1580
|
+
const modelFailure = validateDeepSeekModels(models) ?? validateReasoningEfforts(models);
|
|
1220
1581
|
const keyFailure = apiKeyFailure(keyDraft);
|
|
1221
1582
|
const keyValue = keyDraft.trim();
|
|
1222
1583
|
const ready = route.length > 0 && !routeInvalid && !routeTaken && normalizedBaseURL.length > 0 && !baseUrlInvalid && models.length > 0 && modelFailure === void 0 && keyFailure === void 0;
|
|
@@ -1320,7 +1681,7 @@ window.__ModuleLoader__.load({
|
|
|
1320
1681
|
className: ModelsSection_module_css_default["input"],
|
|
1321
1682
|
type: "text",
|
|
1322
1683
|
value: baseURL,
|
|
1323
|
-
placeholder: t("customBaseUrlPlaceholder"),
|
|
1684
|
+
placeholder: t(protocol === "anthropic-messages" ? "customAnthropicBaseUrlPlaceholder" : "customBaseUrlPlaceholder"),
|
|
1324
1685
|
"aria-label": t("baseUrl"),
|
|
1325
1686
|
"aria-invalid": baseUrlInvalid,
|
|
1326
1687
|
disabled: profileDisabled,
|
|
@@ -1359,10 +1720,8 @@ window.__ModuleLoader__.load({
|
|
|
1359
1720
|
className: ModelsSection_module_css_default["fieldLabel"],
|
|
1360
1721
|
children: t("keyInput")
|
|
1361
1722
|
}),
|
|
1362
|
-
(0, react_jsx_runtime.jsx)(
|
|
1363
|
-
|
|
1364
|
-
type: "password",
|
|
1365
|
-
autoComplete: "off",
|
|
1723
|
+
(0, react_jsx_runtime.jsx)(ApiKeyInput, {
|
|
1724
|
+
t,
|
|
1366
1725
|
value: keyDraft,
|
|
1367
1726
|
placeholder: t("keyPlaceholder"),
|
|
1368
1727
|
"aria-label": t("keyInput"),
|
|
@@ -1380,6 +1739,7 @@ window.__ModuleLoader__.load({
|
|
|
1380
1739
|
(0, react_jsx_runtime.jsx)(ModelListEditor, {
|
|
1381
1740
|
models,
|
|
1382
1741
|
onChange: setModels,
|
|
1742
|
+
reasoningLevels,
|
|
1383
1743
|
probe: {
|
|
1384
1744
|
settingsNs: NS$1,
|
|
1385
1745
|
baseURL: normalizedBaseURL,
|
|
@@ -1389,7 +1749,8 @@ window.__ModuleLoader__.load({
|
|
|
1389
1749
|
probeBlocked: baseUrlInvalid ? "customBaseUrlInvalid" : keyFailure === "keyBlank" ? "keyBlankNew" : keyFailure,
|
|
1390
1750
|
operations,
|
|
1391
1751
|
t,
|
|
1392
|
-
disabled: profileDisabled
|
|
1752
|
+
disabled: profileDisabled,
|
|
1753
|
+
onBusyChange: setListBusy
|
|
1393
1754
|
}),
|
|
1394
1755
|
failure !== void 0 ? (0, react_jsx_runtime.jsx)("p", {
|
|
1395
1756
|
className: ModelsSection_module_css_default["error"],
|
|
@@ -1430,11 +1791,12 @@ window.__ModuleLoader__.load({
|
|
|
1430
1791
|
* display name and wire protocol of a pi-ai route the adapter does not ship —
|
|
1431
1792
|
* the two fields the create card asked that route for, editable here for the
|
|
1432
1793
|
* same reason).
|
|
1433
|
-
*
|
|
1434
|
-
* the
|
|
1435
|
-
*
|
|
1436
|
-
*
|
|
1437
|
-
*
|
|
1794
|
+
* There is deliberately no provider-scoped reasoning-effort control, here or
|
|
1795
|
+
* on the editor card: effort is a per-MODEL capability, and the models under
|
|
1796
|
+
* one provider disagree about it, so a provider-scoped control can only be set
|
|
1797
|
+
* to a value some of them reject. Each model row of a hand-declared route
|
|
1798
|
+
* declares its own `reasoningEfforts` instead, and the composer's model picker
|
|
1799
|
+
* offers each model those levels. Everything else stays
|
|
1438
1800
|
* owned by `settings.yaml`. Profile edits land as minimal `settings.mutate`
|
|
1439
1801
|
* path ops against the stored section — the card names only the fields it can
|
|
1440
1802
|
* see instead of rebuilding the whole subtree from a partial descriptor.
|
|
@@ -1493,8 +1855,16 @@ window.__ModuleLoader__.load({
|
|
|
1493
1855
|
const { namespace, schema, settingsPath, operations, t } = props;
|
|
1494
1856
|
const [draft, setDraft] = (0, react.useState)(() => draftAt(schema, namespace, settingsPath));
|
|
1495
1857
|
const [keyDraft, setKeyDraft] = (0, react.useState)("");
|
|
1496
|
-
const [keyState, setKeyState] = (0, react.useState)(void 0);
|
|
1497
1858
|
const [busy, setBusy] = (0, react.useState)(false);
|
|
1859
|
+
const [listBusy, setListBusy] = (0, react.useState)(false);
|
|
1860
|
+
const { onBusyChange } = props;
|
|
1861
|
+
(0, react.useEffect)(() => {
|
|
1862
|
+
onBusyChange?.(busy || listBusy);
|
|
1863
|
+
}, [
|
|
1864
|
+
busy,
|
|
1865
|
+
listBusy,
|
|
1866
|
+
onBusyChange
|
|
1867
|
+
]);
|
|
1498
1868
|
const [failure, setFailure] = (0, react.useState)(void 0);
|
|
1499
1869
|
const [committedOriginal, setCommittedOriginal] = (0, react.useState)(() => schema.getPath(namespace.user, settingsPath));
|
|
1500
1870
|
const [expectedRevision, setExpectedRevision] = (0, react.useState)(() => namespace.revision);
|
|
@@ -1513,17 +1883,6 @@ window.__ModuleLoader__.load({
|
|
|
1513
1883
|
namespace,
|
|
1514
1884
|
schema
|
|
1515
1885
|
]);
|
|
1516
|
-
(0, react.useEffect)(() => {
|
|
1517
|
-
let stale = false;
|
|
1518
|
-
setKeyState(void 0);
|
|
1519
|
-
operations.describeCredential(keyRef).then((described) => {
|
|
1520
|
-
if (stale) return;
|
|
1521
|
-
setKeyState(described);
|
|
1522
|
-
});
|
|
1523
|
-
return () => {
|
|
1524
|
-
stale = true;
|
|
1525
|
-
};
|
|
1526
|
-
}, [operations, keyRef]);
|
|
1527
1886
|
const stringAt = (source, key) => {
|
|
1528
1887
|
const value = schema.getPath(source, [key]);
|
|
1529
1888
|
return typeof value === "string" && value.trim().length > 0 ? value : void 0;
|
|
@@ -1532,7 +1891,15 @@ window.__ModuleLoader__.load({
|
|
|
1532
1891
|
const value = next === void 0 || next.trim().length === 0 ? void 0 : next;
|
|
1533
1892
|
setDraft((current) => value === void 0 ? schema.deletePath(current, [key]) : schema.setPath(current, [key], value));
|
|
1534
1893
|
};
|
|
1535
|
-
const
|
|
1894
|
+
const reasoningLevels = (0, react.useMemo)(() => layout === "pi-ai" && props.declared === true ? reasoningLevelChoices(namespace, schema) : [], [
|
|
1895
|
+
layout,
|
|
1896
|
+
props.declared,
|
|
1897
|
+
namespace,
|
|
1898
|
+
schema
|
|
1899
|
+
]);
|
|
1900
|
+
const editsReasoning = reasoningLevels.length > 0;
|
|
1901
|
+
const validateModels = (value) => validateDeepSeekModels(value) ?? (editsReasoning ? validateReasoningEfforts(value) : void 0);
|
|
1902
|
+
const modelFailure = validateModels(schema.getPath(draft, ["models"]));
|
|
1536
1903
|
const keyFailure = apiKeyFailure(keyDraft);
|
|
1537
1904
|
const keyValue = keyDraft.trim();
|
|
1538
1905
|
const shownKeyFailure = (props.credentialRequired === true && keyDraft.length > 0 && keyValue.length === 0 ? "keyRequired" : void 0) ?? keyFailure;
|
|
@@ -1555,7 +1922,7 @@ window.__ModuleLoader__.load({
|
|
|
1555
1922
|
const ns = namespace.ns;
|
|
1556
1923
|
const next = layout === "pi-ai" && stringAt(draft, "apiKeyEnv") === void 0 && stringAt(fallback, "apiKeyEnv") === void 0 && keyValue.length > 0 ? schema.setPath(draft, ["apiKeyEnv"], keyRef) : draft;
|
|
1557
1924
|
if (props.credentialOnly !== true) {
|
|
1558
|
-
const failure =
|
|
1925
|
+
const failure = validateModels(schema.getPath(next, ["models"]));
|
|
1559
1926
|
/* v8 ignore next 3 -- unreachable from the card: the same failure disables submit */
|
|
1560
1927
|
if (failure !== void 0) return `${t("model")} ${String(failure.index + 1)}: ${t(failure.key)}`;
|
|
1561
1928
|
}
|
|
@@ -1605,7 +1972,6 @@ window.__ModuleLoader__.load({
|
|
|
1605
1972
|
props.t("settingsPathUnresolvable")
|
|
1606
1973
|
]
|
|
1607
1974
|
});
|
|
1608
|
-
const keyLocked = keyState?.writable === false;
|
|
1609
1975
|
/**
|
|
1610
1976
|
* The catalog beneath the user layer: what the composition entry pinned, or
|
|
1611
1977
|
* else the schema default that `resolve` would supply. The effective value
|
|
@@ -1629,7 +1995,38 @@ window.__ModuleLoader__.load({
|
|
|
1629
1995
|
const defaultContextWindow = schema.getPath(fallback, ["defaultContextWindow"]);
|
|
1630
1996
|
const defaultMaxTokens = schema.getPath(fallback, ["maxTokens"]);
|
|
1631
1997
|
const defaultInput = schema.getPath(fallback, ["defaultInput"]);
|
|
1632
|
-
const
|
|
1998
|
+
const baseURL = stringAt(fallback, "baseURL") ?? props.defaultBaseURL;
|
|
1999
|
+
const endpointEnv = props.baseURLEnv ?? [];
|
|
2000
|
+
const endpointHint = family === "deepseek" ? t("deepSeekEndpointHint") : baseURL === void 0 && endpointEnv.length > 0 ? t("baseUrlEnvironment").replace("{env}", () => endpointEnv.join(", ")) : void 0;
|
|
2001
|
+
const namedRef = stringAt(fallback, "apiKeyEnv");
|
|
2002
|
+
const nativeAuth = namedRef === void 0 ? props.nativeAuth : void 0;
|
|
2003
|
+
const authRefs = namedRef === void 0 ? (nativeAuth?.env ?? []).filter((ref) => !endpointEnv.includes(ref)) : [namedRef];
|
|
2004
|
+
const visibleRefs = authRefs.filter((ref) => !ref.toLowerCase().includes("oauth"));
|
|
2005
|
+
const keyHint = visibleRefs[0];
|
|
2006
|
+
const checkedRefs = authRefs.map((ref) => [ref, props.credentialChecks?.[ref] ?? (ref === namedRef ? props.credential : void 0)]);
|
|
2007
|
+
const detected = checkedRefs.find(([, info]) => info?.configured === true);
|
|
2008
|
+
const detectedRef = detected?.[0];
|
|
2009
|
+
const detectedVisibleRef = detectedRef === void 0 || !visibleRefs.includes(detectedRef) ? void 0 : detectedRef;
|
|
2010
|
+
const missingRefs = checkedRefs.length > 0 && checkedRefs.every(([, info]) => info?.configured === false);
|
|
2011
|
+
const savedCredential = detected?.[1]?.source === "file";
|
|
2012
|
+
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);
|
|
2013
|
+
const keyHelp = visibleRefs.length === 0 ? void 0 : t("keyHelp").replace("{env}", () => visibleRefs.join(" / "));
|
|
2014
|
+
const authHelp = keyHelp === void 0 ? null : (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.Tooltip, {
|
|
2015
|
+
label: keyHelp,
|
|
2016
|
+
side: "right",
|
|
2017
|
+
delayMs: 0,
|
|
2018
|
+
focusDelayMs: 0,
|
|
2019
|
+
portal: true,
|
|
2020
|
+
openOnClick: true,
|
|
2021
|
+
children: (0, react_jsx_runtime.jsx)("button", {
|
|
2022
|
+
type: "button",
|
|
2023
|
+
className: ModelsSection_module_css_default["helpButton"],
|
|
2024
|
+
"aria-label": t("authHelp"),
|
|
2025
|
+
children: "?"
|
|
2026
|
+
})
|
|
2027
|
+
});
|
|
2028
|
+
const keylessNativeAuth = nativeAuth?.env.length === 0 && nativeAuth.oauth;
|
|
2029
|
+
const keyPlaceholder = keyHint === void 0 || props.credentialRequired === true ? t("keyPlaceholder") : t(savedCredential ? "keyPlaceholderSaved" : "keyPlaceholderFallback").replace("{hint}", () => keyHint);
|
|
1633
2030
|
/** What both family editors take: the rows, whose layer owns them, and the two writes. */
|
|
1634
2031
|
const catalogProps = {
|
|
1635
2032
|
models,
|
|
@@ -1643,28 +2040,32 @@ window.__ModuleLoader__.load({
|
|
|
1643
2040
|
setDraft((current) => schema.deletePath(current, ["models"]));
|
|
1644
2041
|
}
|
|
1645
2042
|
};
|
|
1646
|
-
return (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
2043
|
+
return (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [keylessNativeAuth ? null : (0, react_jsx_runtime.jsxs)("div", {
|
|
1647
2044
|
className: ModelsSection_module_css_default["field"],
|
|
1648
2045
|
children: [
|
|
1649
|
-
(0, react_jsx_runtime.
|
|
2046
|
+
(0, react_jsx_runtime.jsxs)("span", {
|
|
1650
2047
|
className: ModelsSection_module_css_default["fieldLabel"],
|
|
1651
|
-
children: t("keyInput")
|
|
2048
|
+
children: [t("keyInput"), authHelp]
|
|
1652
2049
|
}),
|
|
1653
|
-
(0, react_jsx_runtime.jsx)(
|
|
1654
|
-
|
|
1655
|
-
type: "password",
|
|
1656
|
-
autoComplete: "off",
|
|
2050
|
+
(0, react_jsx_runtime.jsx)(ApiKeyInput, {
|
|
2051
|
+
t,
|
|
1657
2052
|
value: keyDraft,
|
|
1658
2053
|
placeholder: keyPlaceholder,
|
|
1659
2054
|
"aria-label": t("keyInput"),
|
|
1660
2055
|
"aria-invalid": shownKeyFailure !== void 0,
|
|
2056
|
+
"aria-describedby": credentialHint === void 0 ? void 0 : `${props.provider}-credential-hint`,
|
|
1661
2057
|
required: props.credentialRequired === true,
|
|
1662
2058
|
autoFocus: props.autoFocusCredential === true,
|
|
1663
|
-
disabled
|
|
2059
|
+
disabled,
|
|
1664
2060
|
onChange: (event) => {
|
|
1665
2061
|
setKeyDraft(event.target.value);
|
|
1666
2062
|
}
|
|
1667
2063
|
}),
|
|
2064
|
+
credentialHint === void 0 ? null : (0, react_jsx_runtime.jsx)("p", {
|
|
2065
|
+
id: `${props.provider}-credential-hint`,
|
|
2066
|
+
className: ModelsSection_module_css_default[missingRefs ? "notice" : detectedRef === void 0 ? "advancedHint" : "savedNotice"],
|
|
2067
|
+
children: credentialHint
|
|
2068
|
+
}),
|
|
1668
2069
|
shownKeyFailure === void 0 ? null : (0, react_jsx_runtime.jsx)("p", {
|
|
1669
2070
|
className: ModelsSection_module_css_default["error"],
|
|
1670
2071
|
children: t(shownKeyFailure)
|
|
@@ -1706,19 +2107,19 @@ window.__ModuleLoader__.load({
|
|
|
1706
2107
|
className: ModelsSection_module_css_default["input"],
|
|
1707
2108
|
type: "text",
|
|
1708
2109
|
value: stringAt(draft, "baseURL") ?? "",
|
|
1709
|
-
placeholder: family === "deepseek" ? t("deepSeekBaseUrl") :
|
|
1710
|
-
"aria-describedby":
|
|
2110
|
+
placeholder: family === "deepseek" ? t("deepSeekBaseUrl") : baseURL === void 0 ? t(endpointEnv.length > 0 ? "baseUrlConfigured" : "baseUrlDefault") : t("baseUrlPlaceholder").replace("{url}", () => baseURL),
|
|
2111
|
+
"aria-describedby": endpointHint === void 0 ? void 0 : `${props.provider}-endpoint-hint`,
|
|
1711
2112
|
"aria-label": t("baseUrl"),
|
|
1712
2113
|
disabled,
|
|
1713
2114
|
onChange: (event) => {
|
|
1714
2115
|
setField("baseURL", event.target.value === "" ? void 0 : event.target.value);
|
|
1715
2116
|
}
|
|
1716
2117
|
}),
|
|
1717
|
-
|
|
2118
|
+
endpointHint === void 0 ? null : (0, react_jsx_runtime.jsx)("span", {
|
|
1718
2119
|
id: `${props.provider}-endpoint-hint`,
|
|
1719
2120
|
className: ModelsSection_module_css_default["advancedHint"],
|
|
1720
|
-
children:
|
|
1721
|
-
})
|
|
2121
|
+
children: endpointHint
|
|
2122
|
+
})
|
|
1722
2123
|
]
|
|
1723
2124
|
}),
|
|
1724
2125
|
ownsIdentity ? (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -1750,10 +2151,12 @@ window.__ModuleLoader__.load({
|
|
|
1750
2151
|
}) : (0, react_jsx_runtime.jsx)(ModelListEditor, {
|
|
1751
2152
|
...catalogProps,
|
|
1752
2153
|
catalogProvider: props.declared === true ? void 0 : props.provider,
|
|
2154
|
+
reasoningLevels,
|
|
1753
2155
|
defaultInput: Array.isArray(defaultInput) ? defaultInput : void 0,
|
|
1754
2156
|
probe,
|
|
1755
2157
|
probeBlocked: keyFailure,
|
|
1756
|
-
operations
|
|
2158
|
+
operations,
|
|
2159
|
+
onBusyChange: setListBusy
|
|
1757
2160
|
})
|
|
1758
2161
|
]
|
|
1759
2162
|
})]
|
|
@@ -1795,6 +2198,7 @@ window.__ModuleLoader__.load({
|
|
|
1795
2198
|
props.onClose(false);
|
|
1796
2199
|
},
|
|
1797
2200
|
onSubmit: () => {
|
|
2201
|
+
props.onSubmitCredential?.();
|
|
1798
2202
|
apply();
|
|
1799
2203
|
}
|
|
1800
2204
|
})
|
|
@@ -1817,12 +2221,17 @@ window.__ModuleLoader__.load({
|
|
|
1817
2221
|
* re-renders from pushed invalidations or the post-apply reload.
|
|
1818
2222
|
*/
|
|
1819
2223
|
/** Render an editor for either the setup posture or an expanded provider row. */
|
|
1820
|
-
function renderProviderEditor({ target, ...props }) {
|
|
2224
|
+
function renderProviderEditor({ target, row, ...props }) {
|
|
1821
2225
|
return (0, react_jsx_runtime.jsx)(ProviderEditor, {
|
|
1822
2226
|
provider: target.provider,
|
|
1823
2227
|
displayName: target.displayName,
|
|
1824
2228
|
settingsPath: target.settingsPath,
|
|
1825
2229
|
...target.declared === true ? { declared: true } : {},
|
|
2230
|
+
...target.defaultBaseURL === void 0 ? {} : { defaultBaseURL: target.defaultBaseURL },
|
|
2231
|
+
...target.baseURLEnv === void 0 ? {} : { baseURLEnv: target.baseURLEnv },
|
|
2232
|
+
...target.nativeAuth === void 0 ? {} : { nativeAuth: target.nativeAuth },
|
|
2233
|
+
...row.credential === void 0 ? {} : { credential: row.credential },
|
|
2234
|
+
...row.credentialChecks === void 0 ? {} : { credentialChecks: row.credentialChecks },
|
|
1826
2235
|
...props
|
|
1827
2236
|
});
|
|
1828
2237
|
}
|
|
@@ -1882,7 +2291,10 @@ window.__ModuleLoader__.load({
|
|
|
1882
2291
|
settingsNs: row.entry.settingsNs,
|
|
1883
2292
|
settingsPath: row.entry.settingsPath,
|
|
1884
2293
|
...credentialRef === void 0 ? {} : { credentialRef },
|
|
1885
|
-
...row.entry.declared === true ? { declared: true } : {}
|
|
2294
|
+
...row.entry.declared === true ? { declared: true } : {},
|
|
2295
|
+
...row.entry.defaultBaseURL === void 0 ? {} : { defaultBaseURL: row.entry.defaultBaseURL },
|
|
2296
|
+
...row.entry.baseURLEnv === void 0 ? {} : { baseURLEnv: row.entry.baseURLEnv },
|
|
2297
|
+
...row.entry.nativeAuth === void 0 ? {} : { nativeAuth: row.entry.nativeAuth }
|
|
1886
2298
|
};
|
|
1887
2299
|
}
|
|
1888
2300
|
/** Stable visible and accessible identity for one provider target. */
|
|
@@ -1926,6 +2338,8 @@ window.__ModuleLoader__.load({
|
|
|
1926
2338
|
const [deleteFailure, setDeleteFailure] = (0, react.useState)(void 0);
|
|
1927
2339
|
const [savedTarget, setSavedTarget] = (0, react.useState)(void 0);
|
|
1928
2340
|
const [declaring, setDeclaring] = (0, react.useState)(false);
|
|
2341
|
+
/** Whether the add card's editor has a write or an interrogation in flight. */
|
|
2342
|
+
const [addBusy, setAddBusy] = (0, react.useState)(false);
|
|
1929
2343
|
const [dismissedSetup, setDismissedSetup] = (0, react.useState)(() => /* @__PURE__ */ new Set());
|
|
1930
2344
|
const announceSaved = (target) => {
|
|
1931
2345
|
controller.load().then(() => {
|
|
@@ -1936,6 +2350,7 @@ window.__ModuleLoader__.load({
|
|
|
1936
2350
|
setEditing(void 0);
|
|
1937
2351
|
setAdding(false);
|
|
1938
2352
|
setDeclaring(false);
|
|
2353
|
+
setAddBusy(false);
|
|
1939
2354
|
if (changed) announceSaved(target);
|
|
1940
2355
|
};
|
|
1941
2356
|
/**
|
|
@@ -2011,6 +2426,7 @@ window.__ModuleLoader__.load({
|
|
|
2011
2426
|
const addNamespace = addTarget === void 0 ? void 0 : state.namespaces.get(addTarget.settingsNs);
|
|
2012
2427
|
const addRow = addTarget === void 0 ? void 0 : state.rows.find((row) => row.entry.provider === addTarget.provider);
|
|
2013
2428
|
const protocols = protocolChoices(state.namespaces.get("llm-pi-ai"), schema);
|
|
2429
|
+
const reasoningLevels = reasoningLevelChoices(state.namespaces.get("llm-pi-ai"), schema);
|
|
2014
2430
|
return (0, react_jsx_runtime.jsxs)("div", {
|
|
2015
2431
|
className: ModelsSection_module_css_default["section"],
|
|
2016
2432
|
children: [
|
|
@@ -2050,6 +2466,7 @@ window.__ModuleLoader__.load({
|
|
|
2050
2466
|
error,
|
|
2051
2467
|
renderProviderEditor({
|
|
2052
2468
|
target,
|
|
2469
|
+
row,
|
|
2053
2470
|
namespace,
|
|
2054
2471
|
schema,
|
|
2055
2472
|
operations,
|
|
@@ -2135,6 +2552,7 @@ window.__ModuleLoader__.load({
|
|
|
2135
2552
|
}, { entryKey: row.entry.settingsNs }),
|
|
2136
2553
|
open ? renderProviderEditor({
|
|
2137
2554
|
target,
|
|
2555
|
+
row,
|
|
2138
2556
|
namespace,
|
|
2139
2557
|
schema,
|
|
2140
2558
|
operations,
|
|
@@ -2162,6 +2580,7 @@ window.__ModuleLoader__.load({
|
|
|
2162
2580
|
className: `${ModelsSection_module_css_default["input"]} ${ModelsSection_module_css_default["selectInput"]}`,
|
|
2163
2581
|
value: addTarget.provider,
|
|
2164
2582
|
"aria-label": t("provider"),
|
|
2583
|
+
disabled: addBusy,
|
|
2165
2584
|
onChange: (event) => {
|
|
2166
2585
|
const row = addable.find((candidate) => candidate.entry.provider === event.target.value);
|
|
2167
2586
|
/* v8 ignore next -- the select only lists addable rows */
|
|
@@ -2181,12 +2600,17 @@ window.__ModuleLoader__.load({
|
|
|
2181
2600
|
namespace: addNamespace,
|
|
2182
2601
|
schema,
|
|
2183
2602
|
settingsPath: addTarget.settingsPath,
|
|
2603
|
+
...addTarget.defaultBaseURL === void 0 ? {} : { defaultBaseURL: addTarget.defaultBaseURL },
|
|
2604
|
+
...addTarget.baseURLEnv === void 0 ? {} : { baseURLEnv: addTarget.baseURLEnv },
|
|
2605
|
+
...addTarget.nativeAuth === void 0 ? {} : { nativeAuth: addTarget.nativeAuth },
|
|
2606
|
+
...addRow?.credentialChecks === void 0 ? {} : { credentialChecks: addRow.credentialChecks },
|
|
2184
2607
|
operations,
|
|
2185
2608
|
t,
|
|
2186
2609
|
readOnly: !state.writable,
|
|
2187
2610
|
onClose: (changed) => {
|
|
2188
2611
|
closeEditor(changed, addTarget);
|
|
2189
|
-
}
|
|
2612
|
+
},
|
|
2613
|
+
onBusyChange: setAddBusy
|
|
2190
2614
|
}, addTarget.provider),
|
|
2191
2615
|
addRow === void 0 ? null : renderSlot("settings.models.provider-card", {
|
|
2192
2616
|
provider: addRow.entry,
|
|
@@ -2199,6 +2623,7 @@ window.__ModuleLoader__.load({
|
|
|
2199
2623
|
children: (0, react_jsx_runtime.jsx)(CustomProviderCard, {
|
|
2200
2624
|
taken: state.rows.map((row) => row.entry.provider),
|
|
2201
2625
|
protocols,
|
|
2626
|
+
reasoningLevels,
|
|
2202
2627
|
/* v8 ignore next -- the card only opens from a button disabled without this namespace */
|
|
2203
2628
|
revision: state.namespaces.get("llm-pi-ai")?.revision ?? 0,
|
|
2204
2629
|
operations,
|
|
@@ -2225,7 +2650,7 @@ window.__ModuleLoader__.load({
|
|
|
2225
2650
|
setAdding(true);
|
|
2226
2651
|
setEditing(targetOf(first));
|
|
2227
2652
|
},
|
|
2228
|
-
children: [(0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.
|
|
2653
|
+
children: [(0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconPlusOutlineRegular, { size: 14 }), t("add")]
|
|
2229
2654
|
}), state.namespaces.has("llm-pi-ai") && (0, react_jsx_runtime.jsxs)("button", {
|
|
2230
2655
|
type: "button",
|
|
2231
2656
|
className: ModelsSection_module_css_default["addButton"],
|
|
@@ -2238,7 +2663,7 @@ window.__ModuleLoader__.load({
|
|
|
2238
2663
|
setEditing(void 0);
|
|
2239
2664
|
setDeclaring(true);
|
|
2240
2665
|
},
|
|
2241
|
-
children: [(0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.
|
|
2666
|
+
children: [(0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconPlusOutlineRegular, { size: 14 }), t("customAdd")]
|
|
2242
2667
|
})]
|
|
2243
2668
|
})
|
|
2244
2669
|
}),
|
|
@@ -2441,10 +2866,6 @@ window.__ModuleLoader__.load({
|
|
|
2441
2866
|
*/
|
|
2442
2867
|
function createModelsOperations(ctx) {
|
|
2443
2868
|
return {
|
|
2444
|
-
describeCredential: async (ref) => {
|
|
2445
|
-
const response = await ctx.remote.credentials.describe([ref]);
|
|
2446
|
-
return response.ok ? response.value[ref] : void 0;
|
|
2447
|
-
},
|
|
2448
2869
|
storeCredential: async (ref, value) => {
|
|
2449
2870
|
const response = await ctx.remote.credentials.set(ref, value);
|
|
2450
2871
|
return response.ok ? void 0 : response.error.message;
|
|
@@ -2529,13 +2950,23 @@ window.__ModuleLoader__.load({
|
|
|
2529
2950
|
conflict: "Someone else changed these settings while this card was open. Close it and reopen to edit the current values.",
|
|
2530
2951
|
retry: "Retry",
|
|
2531
2952
|
keyInput: "API key",
|
|
2953
|
+
keyReveal: "Show secret",
|
|
2954
|
+
keyHide: "Hide secret",
|
|
2532
2955
|
keyPlaceholder: "Enter your API key",
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2956
|
+
keyPlaceholderFallback: "Leave blank to use env as auth ({hint})",
|
|
2957
|
+
keyPlaceholderSaved: "Leave blank to use saved credentials",
|
|
2958
|
+
keyFallbackMissing: "Env var not detected. Enter an API key, or configure {hint} in your env.",
|
|
2959
|
+
keyFallbackDetected: "Env var detected. ({hint})",
|
|
2960
|
+
keyFallbackDetectedHidden: "Env var detected.",
|
|
2961
|
+
keyFallbackUnchecked: "Environment credential status has not been confirmed.",
|
|
2962
|
+
keyHelp: "Saved credentials are used first. Environment fallbacks shown here, in order: {env}. Sources are launch environment, $cwd/.env, then $QILIN_HOME/.env.",
|
|
2963
|
+
authHelp: "Authentication details",
|
|
2536
2964
|
customized: "Customized settings",
|
|
2537
2965
|
baseUrl: "Base URL",
|
|
2538
|
-
baseUrlDefault: "
|
|
2966
|
+
baseUrlDefault: "No default endpoint",
|
|
2967
|
+
baseUrlEnvironment: "Provider endpoint configuration: {env}",
|
|
2968
|
+
baseUrlConfigured: "Provider-configured endpoint",
|
|
2969
|
+
baseUrlPlaceholder: "{url}",
|
|
2539
2970
|
deepSeekBaseUrl: "https://api.deepseek.com/anthropic",
|
|
2540
2971
|
deepSeekEndpointHint: "Use an endpoint compatible with the configured connection.",
|
|
2541
2972
|
models: "Models",
|
|
@@ -2554,6 +2985,16 @@ window.__ModuleLoader__.load({
|
|
|
2554
2985
|
modelInputTypes: "Input types",
|
|
2555
2986
|
modelInputText: "Text",
|
|
2556
2987
|
modelInputImage: "Image",
|
|
2988
|
+
modelReasoning: "Reasoning levels",
|
|
2989
|
+
modelReasoningLevel: "Level",
|
|
2990
|
+
modelReasoningValue: "API value",
|
|
2991
|
+
modelReasoningHelp: "About reasoning levels",
|
|
2992
|
+
modelReasoningHelpText: "The API value is sent in the request's reasoning-effort field, such as OpenAI's reasoning_effort. It defaults to the level name; where the model provider's API documentation specifies a different value, follow it. Off turns reasoning off and needs no value; a value already written in the configuration is kept and sent.",
|
|
2993
|
+
modelReasoningNeedsLevel: "Add at least one level besides Off, or turn reasoning levels off.",
|
|
2994
|
+
modelReasoningValueRequired: "Every level besides Off needs an API value, and no value can be empty.",
|
|
2995
|
+
modelReasoningAdd: "Add level",
|
|
2996
|
+
modelReasoningRemove: "Delete level",
|
|
2997
|
+
modelReasoningOffValuePlaceholder: "Turns reasoning off",
|
|
2557
2998
|
addModel: "Add model",
|
|
2558
2999
|
removeModel: "Delete model",
|
|
2559
3000
|
modelsEmpty: "No models will be shown in the selector. Unlisted IDs can still be sent directly.",
|
|
@@ -2596,6 +3037,7 @@ window.__ModuleLoader__.load({
|
|
|
2596
3037
|
customBaseUrlInvalid: "Enter a valid HTTP or HTTPS URL.",
|
|
2597
3038
|
customNeedsModels: "A custom provider needs at least one model.",
|
|
2598
3039
|
customBaseUrlPlaceholder: "https://gateway.example/v1",
|
|
3040
|
+
customAnthropicBaseUrlPlaceholder: "https://gateway.example",
|
|
2599
3041
|
settingsPathUnresolvable: "unresolvable settings path",
|
|
2600
3042
|
create: "Create provider",
|
|
2601
3043
|
creating: "Creating…",
|
|
@@ -2634,13 +3076,23 @@ window.__ModuleLoader__.load({
|
|
|
2634
3076
|
conflict: "这张卡片打开期间,这些设置已被其他地方改动。请关闭后重新打开,在当前值上编辑。",
|
|
2635
3077
|
retry: "重试",
|
|
2636
3078
|
keyInput: "API 密钥",
|
|
3079
|
+
keyReveal: "显示密钥",
|
|
3080
|
+
keyHide: "隐藏密钥",
|
|
2637
3081
|
keyPlaceholder: "输入 API 密钥",
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
3082
|
+
keyPlaceholderFallback: "留空使用环境认证({hint})",
|
|
3083
|
+
keyPlaceholderSaved: "留空使用已保存凭据",
|
|
3084
|
+
keyFallbackMissing: "未检测到环境变量。请填写 API 密钥,或设置环境变量 {hint}。",
|
|
3085
|
+
keyFallbackDetected: "已检测到环境变量({hint})",
|
|
3086
|
+
keyFallbackDetectedHidden: "已检测到环境变量",
|
|
3087
|
+
keyFallbackUnchecked: "环境凭据状态尚未确认",
|
|
3088
|
+
keyHelp: "优先使用已保存的凭据。此处显示的环境后备按以下顺序排列:{env}。来源依次为启动环境、$cwd/.env、$QILIN_HOME/.env。",
|
|
3089
|
+
authHelp: "认证说明",
|
|
2641
3090
|
customized: "自定义设置",
|
|
2642
3091
|
baseUrl: "API 地址",
|
|
2643
|
-
baseUrlDefault: "
|
|
3092
|
+
baseUrlDefault: "没有默认地址",
|
|
3093
|
+
baseUrlEnvironment: "提供方地址配置:{env}",
|
|
3094
|
+
baseUrlConfigured: "由提供方配置地址",
|
|
3095
|
+
baseUrlPlaceholder: "{url}",
|
|
2644
3096
|
deepSeekBaseUrl: "https://api.deepseek.com/anthropic",
|
|
2645
3097
|
deepSeekEndpointHint: "请填写与当前连接配置兼容的 API 地址。",
|
|
2646
3098
|
models: "模型目录",
|
|
@@ -2659,6 +3111,16 @@ window.__ModuleLoader__.load({
|
|
|
2659
3111
|
modelInputTypes: "输入类型",
|
|
2660
3112
|
modelInputText: "文本",
|
|
2661
3113
|
modelInputImage: "图片",
|
|
3114
|
+
modelReasoning: "推理等级",
|
|
3115
|
+
modelReasoningLevel: "档位",
|
|
3116
|
+
modelReasoningValue: "API 参数值",
|
|
3117
|
+
modelReasoningHelp: "推理等级说明",
|
|
3118
|
+
modelReasoningHelpText: "API 参数值会写入请求的推理强度字段(如 OpenAI 的 reasoning_effort),默认与档位名相同;如有不同,以模型提供商的 API 文档为准。Off 表示关闭思考,不需要填写参数值;配置中已写入的值会保留并发送。",
|
|
3119
|
+
modelReasoningNeedsLevel: "至少添加一个 Off 以外的档位;不需要思考请关闭推理等级。",
|
|
3120
|
+
modelReasoningValueRequired: "Off 以外的档位都需要填写 API 参数值,且参数值不能为空字符串。",
|
|
3121
|
+
modelReasoningAdd: "添加档位",
|
|
3122
|
+
modelReasoningRemove: "删除档位",
|
|
3123
|
+
modelReasoningOffValuePlaceholder: "关闭思考",
|
|
2662
3124
|
addModel: "添加模型",
|
|
2663
3125
|
removeModel: "删除模型",
|
|
2664
3126
|
modelsEmpty: "模型选择器中将不显示任何模型;目录外 ID 仍可直接发送。",
|
|
@@ -2701,6 +3163,7 @@ window.__ModuleLoader__.load({
|
|
|
2701
3163
|
customBaseUrlInvalid: "请输入有效的 HTTP 或 HTTPS 地址。",
|
|
2702
3164
|
customNeedsModels: "自定义提供方至少需要一个模型。",
|
|
2703
3165
|
customBaseUrlPlaceholder: "https://gateway.example/v1",
|
|
3166
|
+
customAnthropicBaseUrlPlaceholder: "https://gateway.example",
|
|
2704
3167
|
settingsPathUnresolvable: "无法解析设置路径",
|
|
2705
3168
|
create: "创建提供方",
|
|
2706
3169
|
creating: "创建中…",
|
|
@@ -2712,6 +3175,904 @@ window.__ModuleLoader__.load({
|
|
|
2712
3175
|
keyRequired: "请输入 API 密钥后继续。"
|
|
2713
3176
|
};
|
|
2714
3177
|
//#endregion
|
|
3178
|
+
//#region ../../../vendor/cosmokit/src/misc.ts
|
|
3179
|
+
/** Return true when a value is `null` or `undefined`. */
|
|
3180
|
+
function isNullable(value) {
|
|
3181
|
+
return value === null || value === void 0;
|
|
3182
|
+
}
|
|
3183
|
+
/** Return true for non-array object values. */
|
|
3184
|
+
function isPlainObject(data) {
|
|
3185
|
+
return data && typeof data === "object" && !Array.isArray(data);
|
|
3186
|
+
}
|
|
3187
|
+
/** Filter object entries and return a new object. */
|
|
3188
|
+
function filterKeys(object, filter) {
|
|
3189
|
+
return Object.fromEntries(Object.entries(object).filter(([key, value]) => filter(key, value)));
|
|
3190
|
+
}
|
|
3191
|
+
/** Map object values while preserving the original key set. */
|
|
3192
|
+
function mapValues(object, transform) {
|
|
3193
|
+
return Object.fromEntries(Object.entries(object).map(([key, value]) => [key, transform(value, key)]));
|
|
3194
|
+
}
|
|
3195
|
+
/** Pick selected keys from an object, optionally including `undefined` values. */
|
|
3196
|
+
function pick(source, keys, forced) {
|
|
3197
|
+
if (!keys) return { ...source };
|
|
3198
|
+
const result = {};
|
|
3199
|
+
for (const key of keys) if (forced || source[key] !== void 0) result[key] = source[key];
|
|
3200
|
+
return result;
|
|
3201
|
+
}
|
|
3202
|
+
//#endregion
|
|
3203
|
+
//#region ../../../vendor/cosmokit/src/volatile.ts
|
|
3204
|
+
/** Shared config references used by schema validators and plugin runtimes. */
|
|
3205
|
+
const write = Symbol.for("cosmokit.volatile.write");
|
|
3206
|
+
function snapshot(value, ancestors = /* @__PURE__ */ new Set()) {
|
|
3207
|
+
if (typeof value === "function") throw new TypeError("volatile config cannot contain functions");
|
|
3208
|
+
if (value === null || typeof value !== "object") return value;
|
|
3209
|
+
if (ancestors.has(value)) throw new TypeError("volatile config cannot contain cycles");
|
|
3210
|
+
ancestors.add(value);
|
|
3211
|
+
try {
|
|
3212
|
+
if (Array.isArray(value)) return Object.freeze(value.map((item) => snapshot(item, ancestors)));
|
|
3213
|
+
if (Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) throw new TypeError("volatile config objects must be plain objects or arrays");
|
|
3214
|
+
return Object.freeze(Object.fromEntries(Object.entries(value).map(([key, item]) => [key, snapshot(item, ancestors)])));
|
|
3215
|
+
} finally {
|
|
3216
|
+
ancestors.delete(value);
|
|
3217
|
+
}
|
|
3218
|
+
}
|
|
3219
|
+
/**
|
|
3220
|
+
* Create a detached reference containing an immutable copy of the supplied data.
|
|
3221
|
+
* @param value - validated config data; class instances and functions are unsupported.
|
|
3222
|
+
* @returns a reference whose value is updated only by its owning runtime.
|
|
3223
|
+
*/
|
|
3224
|
+
function createVolatile(value) {
|
|
3225
|
+
let current = snapshot(value);
|
|
3226
|
+
return Object.freeze({
|
|
3227
|
+
get: () => current,
|
|
3228
|
+
[write]: (value) => {
|
|
3229
|
+
current = value;
|
|
3230
|
+
}
|
|
3231
|
+
});
|
|
3232
|
+
}
|
|
3233
|
+
/**
|
|
3234
|
+
* Identify references across ESM/CJS copies of the shared library.
|
|
3235
|
+
* @param value - a parsed config value.
|
|
3236
|
+
* @returns whether the value implements the shared reference protocol.
|
|
3237
|
+
*/
|
|
3238
|
+
function isVolatile(value) {
|
|
3239
|
+
return typeof value === "object" && value !== null && write in value;
|
|
3240
|
+
}
|
|
3241
|
+
//#endregion
|
|
3242
|
+
//#region ../../../vendor/cosmokit/src/types.ts
|
|
3243
|
+
/** Test values using `instanceof` with a `toStringTag` fallback. */
|
|
3244
|
+
function is(type, value) {
|
|
3245
|
+
if (arguments.length === 1) return (value) => is(type, value);
|
|
3246
|
+
return type in globalThis && value instanceof globalThis[type] || Object.prototype.toString.call(value).slice(8, -1) === type;
|
|
3247
|
+
}
|
|
3248
|
+
function isArrayBufferLike(value) {
|
|
3249
|
+
return is("ArrayBuffer", value) || is("SharedArrayBuffer", value);
|
|
3250
|
+
}
|
|
3251
|
+
function isArrayBufferSource(value) {
|
|
3252
|
+
return isArrayBufferLike(value) || ArrayBuffer.isView(value);
|
|
3253
|
+
}
|
|
3254
|
+
let Binary;
|
|
3255
|
+
(function(_Binary) {
|
|
3256
|
+
_Binary.is = isArrayBufferLike;
|
|
3257
|
+
_Binary.isSource = isArrayBufferSource;
|
|
3258
|
+
function fromSource(source) {
|
|
3259
|
+
if (ArrayBuffer.isView(source)) return source.buffer.slice(source.byteOffset, source.byteOffset + source.byteLength);
|
|
3260
|
+
else return source;
|
|
3261
|
+
}
|
|
3262
|
+
_Binary.fromSource = fromSource;
|
|
3263
|
+
function toBase64(source) {
|
|
3264
|
+
source = fromSource(source);
|
|
3265
|
+
if (typeof Buffer !== "undefined") return Buffer.from(source).toString("base64");
|
|
3266
|
+
let binary = "";
|
|
3267
|
+
const bytes = new Uint8Array(source);
|
|
3268
|
+
for (let i = 0; i < bytes.byteLength; i++) binary += String.fromCharCode(bytes[i]);
|
|
3269
|
+
return btoa(binary);
|
|
3270
|
+
}
|
|
3271
|
+
_Binary.toBase64 = toBase64;
|
|
3272
|
+
function fromBase64(source) {
|
|
3273
|
+
if (typeof Buffer !== "undefined") return fromSource(Buffer.from(source, "base64"));
|
|
3274
|
+
return Uint8Array.from(atob(source), (c) => c.charCodeAt(0));
|
|
3275
|
+
}
|
|
3276
|
+
_Binary.fromBase64 = fromBase64;
|
|
3277
|
+
function toHex(source) {
|
|
3278
|
+
source = fromSource(source);
|
|
3279
|
+
if (typeof Buffer !== "undefined") return Buffer.from(source).toString("hex");
|
|
3280
|
+
return Array.from(new Uint8Array(source), (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
3281
|
+
}
|
|
3282
|
+
_Binary.toHex = toHex;
|
|
3283
|
+
function fromHex(source) {
|
|
3284
|
+
if (typeof Buffer !== "undefined") return fromSource(Buffer.from(source, "hex"));
|
|
3285
|
+
const hex = source.length % 2 === 0 ? source : source.slice(0, source.length - 1);
|
|
3286
|
+
const buffer = [];
|
|
3287
|
+
for (let i = 0; i < hex.length; i += 2) buffer.push(parseInt(`${hex[i]}${hex[i + 1]}`, 16));
|
|
3288
|
+
return Uint8Array.from(buffer).buffer;
|
|
3289
|
+
}
|
|
3290
|
+
_Binary.fromHex = fromHex;
|
|
3291
|
+
})(Binary || (Binary = {}));
|
|
3292
|
+
Binary.fromBase64;
|
|
3293
|
+
Binary.toBase64;
|
|
3294
|
+
Binary.fromHex;
|
|
3295
|
+
Binary.toHex;
|
|
3296
|
+
/** Deep-clone common JavaScript values while preserving prototypes and cycles. */
|
|
3297
|
+
function clone(source, refs = /* @__PURE__ */ new Map()) {
|
|
3298
|
+
if (!source || typeof source !== "object") return source;
|
|
3299
|
+
if (is("Date", source)) return new Date(source.valueOf());
|
|
3300
|
+
if (is("RegExp", source)) return new RegExp(source.source, source.flags);
|
|
3301
|
+
if (isArrayBufferLike(source)) return source.slice(0);
|
|
3302
|
+
if (ArrayBuffer.isView(source)) return source.buffer.slice(source.byteOffset, source.byteOffset + source.byteLength);
|
|
3303
|
+
const cached = refs.get(source);
|
|
3304
|
+
if (cached) return cached;
|
|
3305
|
+
if (Array.isArray(source)) {
|
|
3306
|
+
const result = [];
|
|
3307
|
+
refs.set(source, result);
|
|
3308
|
+
source.forEach((value, index) => {
|
|
3309
|
+
result[index] = Reflect.apply(clone, null, [value, refs]);
|
|
3310
|
+
});
|
|
3311
|
+
return result;
|
|
3312
|
+
}
|
|
3313
|
+
const result = Object.create(Object.getPrototypeOf(source));
|
|
3314
|
+
refs.set(source, result);
|
|
3315
|
+
for (const key of Reflect.ownKeys(source)) {
|
|
3316
|
+
const descriptor = { ...Reflect.getOwnPropertyDescriptor(source, key) };
|
|
3317
|
+
if ("value" in descriptor) descriptor.value = Reflect.apply(clone, null, [descriptor.value, refs]);
|
|
3318
|
+
Reflect.defineProperty(result, key, descriptor);
|
|
3319
|
+
}
|
|
3320
|
+
return result;
|
|
3321
|
+
}
|
|
3322
|
+
/**
|
|
3323
|
+
* Compare values recursively, treating two volatile references as equal regardless of value.
|
|
3324
|
+
* Strict comparison distinguishes null/undefined, treats opaque objects by identity,
|
|
3325
|
+
* compares URLs by normalized href, treats array holes as undefined, and considers distinct cyclic structures unequal.
|
|
3326
|
+
* @param a - first value.
|
|
3327
|
+
* @param b - second value.
|
|
3328
|
+
* @param strict - whether to require strict data equality outside volatile references.
|
|
3329
|
+
* @returns whether the values compare equal.
|
|
3330
|
+
*/
|
|
3331
|
+
function deepEqual(a, b, strict) {
|
|
3332
|
+
const ancestors = /* @__PURE__ */ new Set();
|
|
3333
|
+
function compare(a, b) {
|
|
3334
|
+
if (a === b) return true;
|
|
3335
|
+
if (isVolatile(a) || isVolatile(b)) return isVolatile(a) && isVolatile(b);
|
|
3336
|
+
if (!strict && isNullable(a) && isNullable(b)) return true;
|
|
3337
|
+
if (typeof a !== typeof b || typeof a !== "object" || !a || !b) return false;
|
|
3338
|
+
if (ancestors.has(a)) return false;
|
|
3339
|
+
function check(test, then) {
|
|
3340
|
+
return test(a) ? test(b) ? then(a, b) : false : test(b) ? false : void 0;
|
|
3341
|
+
}
|
|
3342
|
+
ancestors.add(a);
|
|
3343
|
+
try {
|
|
3344
|
+
return check(Array.isArray, (a, b) => {
|
|
3345
|
+
if (a.length !== b.length) return false;
|
|
3346
|
+
for (let index = 0; index < a.length; index++) if (!compare(a[index], b[index])) return false;
|
|
3347
|
+
return true;
|
|
3348
|
+
}) ?? 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) => {
|
|
3349
|
+
if (a.byteLength !== b.byteLength) return false;
|
|
3350
|
+
const viewA = new Uint8Array(a);
|
|
3351
|
+
const viewB = new Uint8Array(b);
|
|
3352
|
+
for (let i = 0; i < viewA.length; i++) if (viewA[i] !== viewB[i]) return false;
|
|
3353
|
+
return true;
|
|
3354
|
+
}) ?? ((!strict || [a, b].every((value) => Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null)) && Object.keys({
|
|
3355
|
+
...a,
|
|
3356
|
+
...b
|
|
3357
|
+
}).every((key) => compare(a[key], b[key])));
|
|
3358
|
+
} finally {
|
|
3359
|
+
ancestors.delete(a);
|
|
3360
|
+
}
|
|
3361
|
+
}
|
|
3362
|
+
return compare(a, b);
|
|
3363
|
+
}
|
|
3364
|
+
//#endregion
|
|
3365
|
+
//#region ../../../vendor/cosmokit/src/time.ts
|
|
3366
|
+
let Time;
|
|
3367
|
+
(function(_Time) {
|
|
3368
|
+
_Time.millisecond = 1;
|
|
3369
|
+
const second = _Time.second = 1e3;
|
|
3370
|
+
const minute = _Time.minute = second * 60;
|
|
3371
|
+
const hour = _Time.hour = minute * 60;
|
|
3372
|
+
const day = _Time.day = hour * 24;
|
|
3373
|
+
const week = _Time.week = day * 7;
|
|
3374
|
+
let timezoneOffset = (/* @__PURE__ */ new Date()).getTimezoneOffset();
|
|
3375
|
+
function setTimezoneOffset(offset) {
|
|
3376
|
+
timezoneOffset = offset;
|
|
3377
|
+
}
|
|
3378
|
+
_Time.setTimezoneOffset = setTimezoneOffset;
|
|
3379
|
+
function getTimezoneOffset() {
|
|
3380
|
+
return timezoneOffset;
|
|
3381
|
+
}
|
|
3382
|
+
_Time.getTimezoneOffset = getTimezoneOffset;
|
|
3383
|
+
function getDateNumber(date = /* @__PURE__ */ new Date(), offset) {
|
|
3384
|
+
if (typeof date === "number") date = new Date(date);
|
|
3385
|
+
if (offset === void 0) offset = timezoneOffset;
|
|
3386
|
+
return Math.floor((date.valueOf() / minute - offset) / 1440);
|
|
3387
|
+
}
|
|
3388
|
+
_Time.getDateNumber = getDateNumber;
|
|
3389
|
+
function fromDateNumber(value, offset) {
|
|
3390
|
+
const date = new Date(value * day);
|
|
3391
|
+
if (offset === void 0) offset = timezoneOffset;
|
|
3392
|
+
return new Date(+date + offset * minute);
|
|
3393
|
+
}
|
|
3394
|
+
_Time.fromDateNumber = fromDateNumber;
|
|
3395
|
+
const numeric = /\d+(?:\.\d+)?/.source;
|
|
3396
|
+
const timeRegExp = new RegExp(`^${[
|
|
3397
|
+
"w(?:eek(?:s)?)?",
|
|
3398
|
+
"d(?:ay(?:s)?)?",
|
|
3399
|
+
"h(?:our(?:s)?)?",
|
|
3400
|
+
"m(?:in(?:ute)?(?:s)?)?",
|
|
3401
|
+
"s(?:ec(?:ond)?(?:s)?)?"
|
|
3402
|
+
].map((unit) => `(${numeric}${unit})?`).join("")}$`);
|
|
3403
|
+
function parseTime(source) {
|
|
3404
|
+
const capture = timeRegExp.exec(source);
|
|
3405
|
+
if (!capture) return 0;
|
|
3406
|
+
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);
|
|
3407
|
+
}
|
|
3408
|
+
_Time.parseTime = parseTime;
|
|
3409
|
+
function parseDate(date) {
|
|
3410
|
+
const parsed = parseTime(date);
|
|
3411
|
+
if (parsed) date = Date.now() + parsed;
|
|
3412
|
+
else if (/^\d{1,2}(:\d{1,2}){1,2}$/.test(date)) date = `${(/* @__PURE__ */ new Date()).toLocaleDateString()}-${date}`;
|
|
3413
|
+
else if (/^\d{1,2}-\d{1,2}-\d{1,2}(:\d{1,2}){1,2}$/.test(date)) date = `${(/* @__PURE__ */ new Date()).getFullYear()}-${date}`;
|
|
3414
|
+
return date ? new Date(date) : /* @__PURE__ */ new Date();
|
|
3415
|
+
}
|
|
3416
|
+
_Time.parseDate = parseDate;
|
|
3417
|
+
function format(ms) {
|
|
3418
|
+
const abs = Math.abs(ms);
|
|
3419
|
+
if (abs >= day - hour / 2) return Math.round(ms / day) + "d";
|
|
3420
|
+
else if (abs >= hour - minute / 2) return Math.round(ms / hour) + "h";
|
|
3421
|
+
else if (abs >= minute - second / 2) return Math.round(ms / minute) + "m";
|
|
3422
|
+
else if (abs >= second) return Math.round(ms / second) + "s";
|
|
3423
|
+
return ms + "ms";
|
|
3424
|
+
}
|
|
3425
|
+
_Time.format = format;
|
|
3426
|
+
function toDigits(source, length = 2) {
|
|
3427
|
+
return source.toString().padStart(length, "0");
|
|
3428
|
+
}
|
|
3429
|
+
_Time.toDigits = toDigits;
|
|
3430
|
+
function template(template, time = /* @__PURE__ */ new Date()) {
|
|
3431
|
+
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));
|
|
3432
|
+
}
|
|
3433
|
+
_Time.template = template;
|
|
3434
|
+
})(Time || (Time = {}));
|
|
3435
|
+
//#endregion
|
|
3436
|
+
//#region ../../../vendor/schemastery/src/index.ts
|
|
3437
|
+
const kSchema = Symbol.for("schemastery");
|
|
3438
|
+
const kValidationError = Symbol.for("ValidationError");
|
|
3439
|
+
globalThis.__schemastery_index__ ??= 0;
|
|
3440
|
+
globalThis.__schemastery_refs__ = void 0;
|
|
3441
|
+
var ValidationError = class extends TypeError {
|
|
3442
|
+
options;
|
|
3443
|
+
name = "ValidationError";
|
|
3444
|
+
constructor(message, options) {
|
|
3445
|
+
let prefix = "$";
|
|
3446
|
+
for (const segment of options.path || []) if (typeof segment === "string") prefix += "." + segment;
|
|
3447
|
+
else if (typeof segment === "number") prefix += "[" + segment + "]";
|
|
3448
|
+
else if (typeof segment === "symbol") prefix += `[Symbol(${segment.toString()})]`;
|
|
3449
|
+
if (prefix.startsWith(".")) prefix = prefix.slice(1);
|
|
3450
|
+
super((prefix === "$" ? "" : `${prefix} `) + message);
|
|
3451
|
+
this.options = options;
|
|
3452
|
+
}
|
|
3453
|
+
static is(error) {
|
|
3454
|
+
return !!error?.[kValidationError];
|
|
3455
|
+
}
|
|
3456
|
+
};
|
|
3457
|
+
Object.defineProperty(ValidationError.prototype, kValidationError, { value: true });
|
|
3458
|
+
const Schema = function(options) {
|
|
3459
|
+
const schema = function(data, options = {}) {
|
|
3460
|
+
return Schema.resolve(data, schema, options)[0];
|
|
3461
|
+
};
|
|
3462
|
+
if (options.refs) {
|
|
3463
|
+
const refs = mapValues(options.refs, (options) => new Schema(options));
|
|
3464
|
+
const getRef = (uid) => refs[uid];
|
|
3465
|
+
for (const key in refs) {
|
|
3466
|
+
const options = refs[key];
|
|
3467
|
+
options.sKey = getRef(options.sKey);
|
|
3468
|
+
options.inner = getRef(options.inner);
|
|
3469
|
+
options.list = options.list && options.list.map(getRef);
|
|
3470
|
+
options.dict = options.dict && mapValues(options.dict, getRef);
|
|
3471
|
+
}
|
|
3472
|
+
return refs[options.uid];
|
|
3473
|
+
}
|
|
3474
|
+
Object.assign(schema, options);
|
|
3475
|
+
if (typeof schema.callback === "string") try {
|
|
3476
|
+
schema.callback = new Function("return " + schema.callback)();
|
|
3477
|
+
} catch {}
|
|
3478
|
+
Object.defineProperty(schema, "uid", { value: globalThis.__schemastery_index__++ });
|
|
3479
|
+
Object.setPrototypeOf(schema, Schema.prototype);
|
|
3480
|
+
schema.meta ||= {};
|
|
3481
|
+
schema.toString = schema.toString.bind(schema);
|
|
3482
|
+
return schema;
|
|
3483
|
+
};
|
|
3484
|
+
Schema.prototype = Object.create(Function.prototype);
|
|
3485
|
+
Schema.prototype[kSchema] = true;
|
|
3486
|
+
Object.defineProperty(Schema.prototype, "~standard", { get() {
|
|
3487
|
+
return {
|
|
3488
|
+
version: 1,
|
|
3489
|
+
vendor: "schemastery",
|
|
3490
|
+
validate: (value) => {
|
|
3491
|
+
try {
|
|
3492
|
+
return { value: Schema.resolve(value, this, {})[0] };
|
|
3493
|
+
} catch (error) {
|
|
3494
|
+
if (ValidationError.is(error)) return { issues: [{
|
|
3495
|
+
message: error.message,
|
|
3496
|
+
path: error.options.path
|
|
3497
|
+
}] };
|
|
3498
|
+
throw error;
|
|
3499
|
+
}
|
|
3500
|
+
}
|
|
3501
|
+
};
|
|
3502
|
+
} });
|
|
3503
|
+
Schema.ValidationError = ValidationError;
|
|
3504
|
+
Schema.prototype.toJSON = function toJSON() {
|
|
3505
|
+
if (globalThis.__schemastery_refs__) {
|
|
3506
|
+
globalThis.__schemastery_refs__[this.uid] ??= JSON.parse(JSON.stringify({ ...this }));
|
|
3507
|
+
return this.uid;
|
|
3508
|
+
}
|
|
3509
|
+
globalThis.__schemastery_refs__ = { [this.uid]: { ...this } };
|
|
3510
|
+
globalThis.__schemastery_refs__[this.uid] = JSON.parse(JSON.stringify({ ...this }));
|
|
3511
|
+
const result = {
|
|
3512
|
+
uid: this.uid,
|
|
3513
|
+
refs: globalThis.__schemastery_refs__
|
|
3514
|
+
};
|
|
3515
|
+
globalThis.__schemastery_refs__ = void 0;
|
|
3516
|
+
return result;
|
|
3517
|
+
};
|
|
3518
|
+
Schema.prototype.set = function set(key, value) {
|
|
3519
|
+
this.dict[key] = value;
|
|
3520
|
+
return this;
|
|
3521
|
+
};
|
|
3522
|
+
Schema.prototype.push = function push(value) {
|
|
3523
|
+
this.list.push(value);
|
|
3524
|
+
return this;
|
|
3525
|
+
};
|
|
3526
|
+
function mergeDesc(original, messages) {
|
|
3527
|
+
const result = typeof original === "string" ? { "": original } : { ...original };
|
|
3528
|
+
for (const locale in messages) {
|
|
3529
|
+
const value = messages[locale];
|
|
3530
|
+
if (value?.$description || value?.$desc) result[locale] = value.$description || value.$desc;
|
|
3531
|
+
else if (typeof value === "string") result[locale] = value;
|
|
3532
|
+
}
|
|
3533
|
+
return result;
|
|
3534
|
+
}
|
|
3535
|
+
function getInner(value) {
|
|
3536
|
+
return value?.$value ?? value?.$inner;
|
|
3537
|
+
}
|
|
3538
|
+
function extractKeys(data) {
|
|
3539
|
+
return filterKeys(data ?? {}, (key) => !key.startsWith("$"));
|
|
3540
|
+
}
|
|
3541
|
+
Schema.prototype.i18n = function i18n(messages) {
|
|
3542
|
+
const schema = Schema(this);
|
|
3543
|
+
const desc = mergeDesc(schema.meta.description, messages);
|
|
3544
|
+
if (Object.keys(desc).length) schema.meta.description = desc;
|
|
3545
|
+
if (schema.dict) schema.dict = mapValues(schema.dict, (inner, key) => {
|
|
3546
|
+
return inner.i18n(mapValues(messages, (data) => getInner(data)?.[key] ?? data?.[key]));
|
|
3547
|
+
});
|
|
3548
|
+
if (schema.list) schema.list = schema.list.map((inner, index) => {
|
|
3549
|
+
return inner.i18n(mapValues(messages, (data = {}) => {
|
|
3550
|
+
if (Array.isArray(getInner(data))) return getInner(data)[index];
|
|
3551
|
+
if (Array.isArray(data)) return data[index];
|
|
3552
|
+
return extractKeys(data);
|
|
3553
|
+
}));
|
|
3554
|
+
});
|
|
3555
|
+
if (schema.inner) schema.inner = schema.inner.i18n(mapValues(messages, (data) => {
|
|
3556
|
+
if (getInner(data)) return getInner(data);
|
|
3557
|
+
return extractKeys(data);
|
|
3558
|
+
}));
|
|
3559
|
+
if (schema.sKey) schema.sKey = schema.sKey.i18n(mapValues(messages, (data) => data?.$key));
|
|
3560
|
+
return schema;
|
|
3561
|
+
};
|
|
3562
|
+
Schema.prototype.extra = function extra(key, value) {
|
|
3563
|
+
const schema = Schema(this);
|
|
3564
|
+
schema.meta = {
|
|
3565
|
+
...schema.meta,
|
|
3566
|
+
[key]: value
|
|
3567
|
+
};
|
|
3568
|
+
return schema;
|
|
3569
|
+
};
|
|
3570
|
+
for (const key of [
|
|
3571
|
+
"required",
|
|
3572
|
+
"disabled",
|
|
3573
|
+
"collapse",
|
|
3574
|
+
"hidden",
|
|
3575
|
+
"loose"
|
|
3576
|
+
]) Object.assign(Schema.prototype, { [key](value = true) {
|
|
3577
|
+
const schema = Schema(this);
|
|
3578
|
+
schema.meta = {
|
|
3579
|
+
...schema.meta,
|
|
3580
|
+
[key]: value
|
|
3581
|
+
};
|
|
3582
|
+
return schema;
|
|
3583
|
+
} });
|
|
3584
|
+
Schema.prototype.deprecated = function deprecated() {
|
|
3585
|
+
const schema = Schema(this);
|
|
3586
|
+
schema.meta.badges ||= [];
|
|
3587
|
+
schema.meta.badges.push({
|
|
3588
|
+
text: "deprecated",
|
|
3589
|
+
type: "danger"
|
|
3590
|
+
});
|
|
3591
|
+
return schema;
|
|
3592
|
+
};
|
|
3593
|
+
Schema.prototype.experimental = function experimental() {
|
|
3594
|
+
const schema = Schema(this);
|
|
3595
|
+
schema.meta.badges ||= [];
|
|
3596
|
+
schema.meta.badges.push({
|
|
3597
|
+
text: "experimental",
|
|
3598
|
+
type: "warning"
|
|
3599
|
+
});
|
|
3600
|
+
return schema;
|
|
3601
|
+
};
|
|
3602
|
+
Schema.prototype.pattern = function pattern(regexp) {
|
|
3603
|
+
const schema = Schema(this);
|
|
3604
|
+
const pattern = pick(regexp, ["source", "flags"]);
|
|
3605
|
+
schema.meta = {
|
|
3606
|
+
...schema.meta,
|
|
3607
|
+
pattern
|
|
3608
|
+
};
|
|
3609
|
+
return schema;
|
|
3610
|
+
};
|
|
3611
|
+
Schema.prototype.simplify = function simplify(value) {
|
|
3612
|
+
if (isVolatile(value)) value = value.get();
|
|
3613
|
+
if (deepEqual(value, this.meta.default, this.type === "dict")) return null;
|
|
3614
|
+
if (isNullable(value)) return value;
|
|
3615
|
+
if (this.type === "object" || this.type === "dict") {
|
|
3616
|
+
const result = {};
|
|
3617
|
+
for (const key in value) {
|
|
3618
|
+
const item = (this.type === "object" ? this.dict[key] : this.inner)?.simplify(value[key]);
|
|
3619
|
+
if (this.type === "dict" || !isNullable(item)) result[key] = item;
|
|
3620
|
+
}
|
|
3621
|
+
if (deepEqual(result, this.meta.default, this.type === "dict")) return null;
|
|
3622
|
+
return result;
|
|
3623
|
+
} else if (this.type === "array" || this.type === "tuple") {
|
|
3624
|
+
const result = [];
|
|
3625
|
+
value.forEach((value, index) => {
|
|
3626
|
+
const schema = this.type === "array" ? this.inner : this.list[index];
|
|
3627
|
+
const item = schema ? schema.simplify(value) : value;
|
|
3628
|
+
result.push(item);
|
|
3629
|
+
});
|
|
3630
|
+
return result;
|
|
3631
|
+
} else if (this.type === "intersect") {
|
|
3632
|
+
const result = {};
|
|
3633
|
+
for (const item of this.list) Object.assign(result, item.simplify(value));
|
|
3634
|
+
return result;
|
|
3635
|
+
} else if (this.type === "union") for (const schema of this.list) try {
|
|
3636
|
+
Schema.resolve(value, schema, {});
|
|
3637
|
+
return schema.simplify(value);
|
|
3638
|
+
} catch {}
|
|
3639
|
+
return value;
|
|
3640
|
+
};
|
|
3641
|
+
Schema.prototype.toString = function toString(inline) {
|
|
3642
|
+
return formatters[this.type]?.(this, inline) ?? `Schema<${this.type}>`;
|
|
3643
|
+
};
|
|
3644
|
+
Schema.prototype.role = function role(role, extra) {
|
|
3645
|
+
const schema = Schema(this);
|
|
3646
|
+
schema.meta = {
|
|
3647
|
+
...schema.meta,
|
|
3648
|
+
role,
|
|
3649
|
+
extra
|
|
3650
|
+
};
|
|
3651
|
+
return schema;
|
|
3652
|
+
};
|
|
3653
|
+
for (const key of [
|
|
3654
|
+
"default",
|
|
3655
|
+
"link",
|
|
3656
|
+
"comment",
|
|
3657
|
+
"description",
|
|
3658
|
+
"max",
|
|
3659
|
+
"min",
|
|
3660
|
+
"step"
|
|
3661
|
+
]) Object.assign(Schema.prototype, { [key](value) {
|
|
3662
|
+
const schema = Schema(this);
|
|
3663
|
+
schema.meta = {
|
|
3664
|
+
...schema.meta,
|
|
3665
|
+
[key]: value
|
|
3666
|
+
};
|
|
3667
|
+
return schema;
|
|
3668
|
+
} });
|
|
3669
|
+
Schema.prototype.volatile = function volatile() {
|
|
3670
|
+
if (this.meta.volatile) throw new TypeError("volatile schema is already wrapped");
|
|
3671
|
+
return this.extra("volatile", true);
|
|
3672
|
+
};
|
|
3673
|
+
const resolvers = {};
|
|
3674
|
+
const checkedVolatile = Symbol("checked-volatile-schema");
|
|
3675
|
+
function validateVolatileSchema(schema, path = [], blocked = false, seen = /* @__PURE__ */ new Map()) {
|
|
3676
|
+
const states = seen.get(schema) ?? /* @__PURE__ */ new Set();
|
|
3677
|
+
if (states.has(blocked)) return;
|
|
3678
|
+
states.add(blocked);
|
|
3679
|
+
seen.set(schema, states);
|
|
3680
|
+
if (schema.meta?.volatile && blocked) throw new ValidationError("volatile fields require a fixed object path without an enclosing volatile field", { path });
|
|
3681
|
+
const nested = blocked || !!schema.meta?.volatile;
|
|
3682
|
+
if (schema.dict) for (const [key, child] of Object.entries(schema.dict)) validateVolatileSchema(child, [...path, key], nested, seen);
|
|
3683
|
+
if (schema.sKey) validateVolatileSchema(schema.sKey, [...path, "<key>"], true, seen);
|
|
3684
|
+
if (schema.inner && (schema.type !== "lazy" || schema.inner[kSchema])) validateVolatileSchema(schema.inner, [...path, "*"], true, seen);
|
|
3685
|
+
if (schema.list) for (let index = 0; index < schema.list.length; index++) validateVolatileSchema(schema.list[index], [...path, String(index)], true, seen);
|
|
3686
|
+
}
|
|
3687
|
+
Schema.extend = function extend(type, resolve) {
|
|
3688
|
+
resolvers[type] = resolve;
|
|
3689
|
+
};
|
|
3690
|
+
Schema.resolve = function resolve(data, schema, options = {}, strict = false) {
|
|
3691
|
+
if (!schema) return [data];
|
|
3692
|
+
if (!options[checkedVolatile]) {
|
|
3693
|
+
validateVolatileSchema(schema, options.path);
|
|
3694
|
+
options = {
|
|
3695
|
+
...options,
|
|
3696
|
+
[checkedVolatile]: true
|
|
3697
|
+
};
|
|
3698
|
+
}
|
|
3699
|
+
if (schema.meta?.volatile) {
|
|
3700
|
+
const inner = Schema(schema);
|
|
3701
|
+
inner.meta = {
|
|
3702
|
+
...schema.meta,
|
|
3703
|
+
volatile: false
|
|
3704
|
+
};
|
|
3705
|
+
const [value, adapted] = Schema.resolve(data, inner, options, strict);
|
|
3706
|
+
try {
|
|
3707
|
+
return [createVolatile(value), adapted];
|
|
3708
|
+
} catch (error) {
|
|
3709
|
+
throw new ValidationError(error instanceof Error ? error.message : String(error), options);
|
|
3710
|
+
}
|
|
3711
|
+
}
|
|
3712
|
+
if (options.ignore?.(data, schema)) return [data];
|
|
3713
|
+
if (isNullable(data) && schema.type !== "lazy") {
|
|
3714
|
+
if (schema.meta.required) throw new ValidationError(`missing required value`, options);
|
|
3715
|
+
let current = schema;
|
|
3716
|
+
let fallback = schema.meta.default;
|
|
3717
|
+
while (current?.type === "intersect" && isNullable(fallback)) {
|
|
3718
|
+
current = current.list[0];
|
|
3719
|
+
fallback = current?.meta.default;
|
|
3720
|
+
}
|
|
3721
|
+
if (isNullable(fallback)) return [data];
|
|
3722
|
+
data = clone(fallback);
|
|
3723
|
+
}
|
|
3724
|
+
const callback = resolvers[schema.type];
|
|
3725
|
+
if (!callback) throw new ValidationError(`unsupported type "${schema.type}"`, options);
|
|
3726
|
+
try {
|
|
3727
|
+
return callback(data, schema, options, strict);
|
|
3728
|
+
} catch (error) {
|
|
3729
|
+
if (!schema.meta.loose) throw error;
|
|
3730
|
+
return [schema.meta.default];
|
|
3731
|
+
}
|
|
3732
|
+
};
|
|
3733
|
+
Schema.from = function from(source) {
|
|
3734
|
+
if (isNullable(source)) return Schema.any();
|
|
3735
|
+
else if ([
|
|
3736
|
+
"string",
|
|
3737
|
+
"number",
|
|
3738
|
+
"boolean"
|
|
3739
|
+
].includes(typeof source)) return Schema.const(source).required();
|
|
3740
|
+
else if (source[kSchema]) return source;
|
|
3741
|
+
else if (typeof source === "function") switch (source) {
|
|
3742
|
+
case String: return Schema.string().required();
|
|
3743
|
+
case Number: return Schema.number().required();
|
|
3744
|
+
case Boolean: return Schema.boolean().required();
|
|
3745
|
+
case Function: return Schema.function().required();
|
|
3746
|
+
default: return Schema.is(source).required();
|
|
3747
|
+
}
|
|
3748
|
+
else throw new TypeError(`cannot infer schema from ${source}`);
|
|
3749
|
+
};
|
|
3750
|
+
Schema.lazy = function lazy(builder) {
|
|
3751
|
+
const toJSON = () => {
|
|
3752
|
+
if (!schema.inner[kSchema]) {
|
|
3753
|
+
schema.inner = schema.builder();
|
|
3754
|
+
schema.inner.meta = {
|
|
3755
|
+
...schema.meta,
|
|
3756
|
+
...schema.inner.meta
|
|
3757
|
+
};
|
|
3758
|
+
}
|
|
3759
|
+
return schema.inner.toJSON();
|
|
3760
|
+
};
|
|
3761
|
+
const schema = new Schema({
|
|
3762
|
+
type: "lazy",
|
|
3763
|
+
builder,
|
|
3764
|
+
inner: { toJSON }
|
|
3765
|
+
});
|
|
3766
|
+
return schema;
|
|
3767
|
+
};
|
|
3768
|
+
Schema.natural = function natural() {
|
|
3769
|
+
return Schema.number().step(1).min(0);
|
|
3770
|
+
};
|
|
3771
|
+
Schema.percent = function percent() {
|
|
3772
|
+
return Schema.number().step(.01).min(0).max(1).role("slider");
|
|
3773
|
+
};
|
|
3774
|
+
Schema.date = function date() {
|
|
3775
|
+
return Schema.union([Schema.is(Date), Schema.transform(Schema.string().role("datetime"), (value, options) => {
|
|
3776
|
+
const date = new Date(value);
|
|
3777
|
+
if (isNaN(+date)) throw new ValidationError(`invalid date "${value}"`, options);
|
|
3778
|
+
return date;
|
|
3779
|
+
}, true)]);
|
|
3780
|
+
};
|
|
3781
|
+
Schema.regExp = function regExp(flag = "") {
|
|
3782
|
+
return Schema.union([Schema.is(RegExp), Schema.transform(Schema.string().role("regexp", { flag }), (value, options) => {
|
|
3783
|
+
try {
|
|
3784
|
+
return new RegExp(value, flag);
|
|
3785
|
+
} catch (e) {
|
|
3786
|
+
throw new ValidationError(e.message, options);
|
|
3787
|
+
}
|
|
3788
|
+
}, true)]);
|
|
3789
|
+
};
|
|
3790
|
+
Schema.arrayBuffer = function arrayBuffer(encoding) {
|
|
3791
|
+
return Schema.union([
|
|
3792
|
+
Schema.is(ArrayBuffer),
|
|
3793
|
+
Schema.is(SharedArrayBuffer),
|
|
3794
|
+
Schema.transform(Schema.any(), (value, options) => {
|
|
3795
|
+
if (Binary.isSource(value)) return Binary.fromSource(value);
|
|
3796
|
+
throw new ValidationError(`expected ArrayBufferSource but got ${value}`, options);
|
|
3797
|
+
}, true),
|
|
3798
|
+
...encoding ? [Schema.transform(Schema.string(), (value, options) => {
|
|
3799
|
+
try {
|
|
3800
|
+
return encoding === "base64" ? Binary.fromBase64(value) : Binary.fromHex(value);
|
|
3801
|
+
} catch (e) {
|
|
3802
|
+
throw new ValidationError(e.message, options);
|
|
3803
|
+
}
|
|
3804
|
+
}, true)] : []
|
|
3805
|
+
]);
|
|
3806
|
+
};
|
|
3807
|
+
Schema.extend("lazy", (data, schema, options, strict) => {
|
|
3808
|
+
if (!schema.inner[kSchema]) {
|
|
3809
|
+
schema.inner = schema.builder();
|
|
3810
|
+
schema.inner.meta = {
|
|
3811
|
+
...schema.meta,
|
|
3812
|
+
...schema.inner.meta
|
|
3813
|
+
};
|
|
3814
|
+
validateVolatileSchema(schema.inner, options.path, true);
|
|
3815
|
+
}
|
|
3816
|
+
return Schema.resolve(data, schema.inner, options, strict);
|
|
3817
|
+
});
|
|
3818
|
+
Schema.extend("any", (data) => {
|
|
3819
|
+
return [data];
|
|
3820
|
+
});
|
|
3821
|
+
Schema.extend("never", (data, _, options) => {
|
|
3822
|
+
throw new ValidationError(`expected nullable but got ${data}`, options);
|
|
3823
|
+
});
|
|
3824
|
+
Schema.extend("const", (data, { value }, options) => {
|
|
3825
|
+
if (deepEqual(data, value)) return [value];
|
|
3826
|
+
throw new ValidationError(`expected ${value} but got ${data}`, options);
|
|
3827
|
+
});
|
|
3828
|
+
function checkWithinRange(data, meta, description, options, skipMin = false) {
|
|
3829
|
+
const { max = Infinity, min = -Infinity } = meta;
|
|
3830
|
+
if (data > max) throw new ValidationError(`expected ${description} <= ${max} but got ${data}`, options);
|
|
3831
|
+
if (data < min && !skipMin) throw new ValidationError(`expected ${description} >= ${min} but got ${data}`, options);
|
|
3832
|
+
}
|
|
3833
|
+
Schema.extend("string", (data, { meta }, options) => {
|
|
3834
|
+
if (typeof data !== "string") throw new ValidationError(`expected string but got ${data}`, options);
|
|
3835
|
+
if (meta.pattern) {
|
|
3836
|
+
const regexp = new RegExp(meta.pattern.source, meta.pattern.flags);
|
|
3837
|
+
if (!regexp.test(data)) throw new ValidationError(`expect string to match regexp ${regexp}`, options);
|
|
3838
|
+
}
|
|
3839
|
+
checkWithinRange(data.length, meta, "string length", options);
|
|
3840
|
+
return [data];
|
|
3841
|
+
});
|
|
3842
|
+
function decimalShift(data, digits) {
|
|
3843
|
+
const str = data.toString();
|
|
3844
|
+
if (str.includes("e")) return data * Math.pow(10, digits);
|
|
3845
|
+
const index = str.indexOf(".");
|
|
3846
|
+
if (index === -1) return data * Math.pow(10, digits);
|
|
3847
|
+
const frac = str.slice(index + 1);
|
|
3848
|
+
const integer = str.slice(0, index);
|
|
3849
|
+
if (frac.length <= digits) return +(integer + frac.padEnd(digits, "0"));
|
|
3850
|
+
return +(integer + frac.slice(0, digits) + "." + frac.slice(digits));
|
|
3851
|
+
}
|
|
3852
|
+
function isMultipleOf(data, min, step) {
|
|
3853
|
+
step = Math.abs(step);
|
|
3854
|
+
if (!/^\d+\.\d+$/.test(step.toString())) return (data - min) % step === 0;
|
|
3855
|
+
const index = step.toString().indexOf(".");
|
|
3856
|
+
const digits = step.toString().slice(index + 1).length;
|
|
3857
|
+
return Math.abs(decimalShift(data, digits) - decimalShift(min, digits)) % decimalShift(step, digits) === 0;
|
|
3858
|
+
}
|
|
3859
|
+
Schema.extend("number", (data, { meta }, options) => {
|
|
3860
|
+
if (typeof data !== "number") throw new ValidationError(`expected number but got ${data}`, options);
|
|
3861
|
+
checkWithinRange(data, meta, "number", options);
|
|
3862
|
+
const { step } = meta;
|
|
3863
|
+
if (step && !isMultipleOf(data, meta.min ?? 0, step)) throw new ValidationError(`expected number multiple of ${step} but got ${data}`, options);
|
|
3864
|
+
return [data];
|
|
3865
|
+
});
|
|
3866
|
+
Schema.extend("boolean", (data, _, options) => {
|
|
3867
|
+
if (typeof data === "boolean") return [data];
|
|
3868
|
+
throw new ValidationError(`expected boolean but got ${data}`, options);
|
|
3869
|
+
});
|
|
3870
|
+
Schema.extend("bitset", (data, { bits, meta }, options) => {
|
|
3871
|
+
let value = 0, keys = [];
|
|
3872
|
+
if (typeof data === "number") {
|
|
3873
|
+
value = data;
|
|
3874
|
+
for (const key in bits) if (data & bits[key]) keys.push(key);
|
|
3875
|
+
} else if (Array.isArray(data)) {
|
|
3876
|
+
keys = data;
|
|
3877
|
+
for (const key of keys) {
|
|
3878
|
+
if (typeof key !== "string") throw new ValidationError(`expected string but got ${key}`, options);
|
|
3879
|
+
if (key in bits) value |= bits[key];
|
|
3880
|
+
}
|
|
3881
|
+
} else throw new ValidationError(`expected number or array but got ${data}`, options);
|
|
3882
|
+
if (value === meta.default) return [value];
|
|
3883
|
+
return [value, keys];
|
|
3884
|
+
});
|
|
3885
|
+
Schema.extend("function", (data, _, options) => {
|
|
3886
|
+
if (typeof data === "function") return [data];
|
|
3887
|
+
throw new ValidationError(`expected function but got ${data}`, options);
|
|
3888
|
+
});
|
|
3889
|
+
Schema.extend("is", (data, { constructor }, options) => {
|
|
3890
|
+
if (typeof constructor === "function") {
|
|
3891
|
+
if (data instanceof constructor) return [data];
|
|
3892
|
+
throw new ValidationError(`expected ${constructor.name} but got ${data}`, options);
|
|
3893
|
+
} else {
|
|
3894
|
+
if (isNullable(data)) throw new ValidationError(`expected ${constructor} but got ${data}`, options);
|
|
3895
|
+
let prototype = Object.getPrototypeOf(data);
|
|
3896
|
+
while (prototype) {
|
|
3897
|
+
if (prototype.constructor?.name === constructor) return [data];
|
|
3898
|
+
prototype = Object.getPrototypeOf(prototype);
|
|
3899
|
+
}
|
|
3900
|
+
throw new ValidationError(`expected ${constructor} but got ${data}`, options);
|
|
3901
|
+
}
|
|
3902
|
+
});
|
|
3903
|
+
function property(data, key, schema, options) {
|
|
3904
|
+
try {
|
|
3905
|
+
const [value, adapted] = Schema.resolve(data[key], schema, {
|
|
3906
|
+
...options,
|
|
3907
|
+
path: [...options.path || [], key]
|
|
3908
|
+
});
|
|
3909
|
+
if (adapted !== void 0) data[key] = adapted;
|
|
3910
|
+
return value;
|
|
3911
|
+
} catch (e) {
|
|
3912
|
+
if (!options?.autofix) throw e;
|
|
3913
|
+
delete data[key];
|
|
3914
|
+
return schema.meta.volatile ? createVolatile(schema.meta.default) : schema.meta.default;
|
|
3915
|
+
}
|
|
3916
|
+
}
|
|
3917
|
+
Schema.extend("array", (data, { inner, meta }, options) => {
|
|
3918
|
+
if (!Array.isArray(data)) throw new ValidationError(`expected array but got ${data}`, options);
|
|
3919
|
+
checkWithinRange(data.length, meta, "array length", options, !isNullable(inner.meta.default));
|
|
3920
|
+
return [data.map((_, index) => property(data, index, inner, options))];
|
|
3921
|
+
});
|
|
3922
|
+
Schema.extend("dict", (data, { inner, sKey }, options, strict) => {
|
|
3923
|
+
if (!isPlainObject(data)) throw new ValidationError(`expected object but got ${data}`, options);
|
|
3924
|
+
const result = {};
|
|
3925
|
+
for (const key in data) {
|
|
3926
|
+
let rKey;
|
|
3927
|
+
try {
|
|
3928
|
+
rKey = Schema.resolve(key, sKey, options)[0];
|
|
3929
|
+
} catch (error) {
|
|
3930
|
+
if (strict) continue;
|
|
3931
|
+
throw error;
|
|
3932
|
+
}
|
|
3933
|
+
result[rKey] = property(data, key, inner, options);
|
|
3934
|
+
data[rKey] = data[key];
|
|
3935
|
+
if (key !== rKey) delete data[key];
|
|
3936
|
+
}
|
|
3937
|
+
return [result];
|
|
3938
|
+
});
|
|
3939
|
+
Schema.extend("tuple", (data, { list }, options, strict) => {
|
|
3940
|
+
if (!Array.isArray(data)) throw new ValidationError(`expected array but got ${data}`, options);
|
|
3941
|
+
const result = list.map((inner, index) => property(data, index, inner, options));
|
|
3942
|
+
if (strict) return [result];
|
|
3943
|
+
result.push(...data.slice(list.length));
|
|
3944
|
+
return [result];
|
|
3945
|
+
});
|
|
3946
|
+
function merge(result, data) {
|
|
3947
|
+
for (const key in data) {
|
|
3948
|
+
if (key in result) continue;
|
|
3949
|
+
result[key] = data[key];
|
|
3950
|
+
}
|
|
3951
|
+
}
|
|
3952
|
+
Schema.extend("object", (data, { dict }, options, strict) => {
|
|
3953
|
+
if (!isPlainObject(data)) throw new ValidationError(`expected object but got ${data}`, options);
|
|
3954
|
+
const result = {};
|
|
3955
|
+
for (const key in dict) {
|
|
3956
|
+
const value = property(data, key, dict[key], options);
|
|
3957
|
+
if (!isNullable(value) || key in data) result[key] = value;
|
|
3958
|
+
}
|
|
3959
|
+
if (!strict) merge(result, data);
|
|
3960
|
+
return [result];
|
|
3961
|
+
});
|
|
3962
|
+
Schema.extend("union", (data, { list, toString }, options, strict) => {
|
|
3963
|
+
const messages = [];
|
|
3964
|
+
for (const inner of list) try {
|
|
3965
|
+
return Schema.resolve(data, inner, options, strict);
|
|
3966
|
+
} catch (error) {
|
|
3967
|
+
messages.push(error);
|
|
3968
|
+
}
|
|
3969
|
+
throw new ValidationError(`expected ${toString()} but got ${JSON.stringify(data)}`, options);
|
|
3970
|
+
});
|
|
3971
|
+
Schema.extend("intersect", (data, { list, toString }, options, strict) => {
|
|
3972
|
+
if (!list.length) return [data];
|
|
3973
|
+
let result;
|
|
3974
|
+
for (const inner of list) {
|
|
3975
|
+
const value = Schema.resolve(data, inner, options, true)[0];
|
|
3976
|
+
if (isNullable(value)) continue;
|
|
3977
|
+
if (isNullable(result)) result = value;
|
|
3978
|
+
else if (typeof result !== typeof value) throw new ValidationError(`expected ${toString()} but got ${JSON.stringify(data)}`, options);
|
|
3979
|
+
else if (typeof value === "object") merge(result ??= {}, value);
|
|
3980
|
+
else if (result !== value) throw new ValidationError(`expected ${toString()} but got ${JSON.stringify(data)}`, options);
|
|
3981
|
+
}
|
|
3982
|
+
if (!strict && isPlainObject(data)) merge(result, data);
|
|
3983
|
+
return [result];
|
|
3984
|
+
});
|
|
3985
|
+
Schema.extend("transform", (data, { inner, callback, preserve }, options) => {
|
|
3986
|
+
const [result, adapted = data] = Schema.resolve(data, inner, options, true);
|
|
3987
|
+
if (preserve) return [callback(result)];
|
|
3988
|
+
else return [callback(result), callback(adapted)];
|
|
3989
|
+
});
|
|
3990
|
+
const formatters = {};
|
|
3991
|
+
function defineMethod(name, keys, format) {
|
|
3992
|
+
formatters[name] = format;
|
|
3993
|
+
Object.assign(Schema, { [name](...args) {
|
|
3994
|
+
const schema = new Schema({ type: name });
|
|
3995
|
+
keys.forEach((key, index) => {
|
|
3996
|
+
switch (key) {
|
|
3997
|
+
case "sKey":
|
|
3998
|
+
schema.sKey = args[index] ?? Schema.string();
|
|
3999
|
+
break;
|
|
4000
|
+
case "inner":
|
|
4001
|
+
schema.inner = Schema.from(args[index]);
|
|
4002
|
+
break;
|
|
4003
|
+
case "list":
|
|
4004
|
+
schema.list = args[index].map(Schema.from);
|
|
4005
|
+
break;
|
|
4006
|
+
case "dict":
|
|
4007
|
+
schema.dict = mapValues(args[index], Schema.from);
|
|
4008
|
+
break;
|
|
4009
|
+
case "bits":
|
|
4010
|
+
schema.bits = {};
|
|
4011
|
+
for (const key in args[index]) {
|
|
4012
|
+
if (typeof args[index][key] !== "number") continue;
|
|
4013
|
+
schema.bits[key] = args[index][key];
|
|
4014
|
+
}
|
|
4015
|
+
break;
|
|
4016
|
+
case "callback": {
|
|
4017
|
+
const callback = schema.callback = args[index];
|
|
4018
|
+
callback["toJSON"] ||= () => callback.toString();
|
|
4019
|
+
break;
|
|
4020
|
+
}
|
|
4021
|
+
case "constructor": {
|
|
4022
|
+
const constructor = schema.constructor = args[index];
|
|
4023
|
+
if (typeof constructor === "function") constructor["toJSON"] ||= () => constructor["name"];
|
|
4024
|
+
break;
|
|
4025
|
+
}
|
|
4026
|
+
default: schema[key] = args[index];
|
|
4027
|
+
}
|
|
4028
|
+
});
|
|
4029
|
+
if (name === "object" || name === "dict") schema.meta.default = {};
|
|
4030
|
+
else if (name === "array" || name === "tuple") schema.meta.default = [];
|
|
4031
|
+
else if (name === "bitset") schema.meta.default = 0;
|
|
4032
|
+
return schema;
|
|
4033
|
+
} });
|
|
4034
|
+
}
|
|
4035
|
+
defineMethod("is", ["constructor"], ({ constructor }) => {
|
|
4036
|
+
if (typeof constructor === "function") return constructor.name;
|
|
4037
|
+
else return constructor;
|
|
4038
|
+
});
|
|
4039
|
+
defineMethod("any", [], () => "any");
|
|
4040
|
+
defineMethod("never", [], () => "never");
|
|
4041
|
+
defineMethod("const", ["value"], ({ value }) => typeof value === "string" ? JSON.stringify(value) : value);
|
|
4042
|
+
defineMethod("string", [], () => "string");
|
|
4043
|
+
defineMethod("number", [], () => "number");
|
|
4044
|
+
defineMethod("boolean", [], () => "boolean");
|
|
4045
|
+
defineMethod("bitset", ["bits"], () => "bitset");
|
|
4046
|
+
defineMethod("function", [], () => "function");
|
|
4047
|
+
defineMethod("array", ["inner"], ({ inner }) => `${inner.toString(true)}[]`);
|
|
4048
|
+
defineMethod("dict", ["inner", "sKey"], ({ inner, sKey }) => `{ [key: ${sKey.toString()}]: ${inner.toString()} }`);
|
|
4049
|
+
defineMethod("tuple", ["list"], ({ list }) => `[${list.map((inner) => inner.toString()).join(", ")}]`);
|
|
4050
|
+
defineMethod("object", ["dict"], ({ dict }) => {
|
|
4051
|
+
if (Object.keys(dict).length === 0) return "{}";
|
|
4052
|
+
return `{ ${Object.entries(dict).map(([key, inner]) => {
|
|
4053
|
+
return `${key}${inner.meta.required ? "" : "?"}: ${inner.toString()}`;
|
|
4054
|
+
}).join(", ")} }`;
|
|
4055
|
+
});
|
|
4056
|
+
defineMethod("union", ["list"], ({ list }, inline) => {
|
|
4057
|
+
const result = list.map(({ toString: format }) => format()).join(" | ");
|
|
4058
|
+
return inline ? `(${result})` : result;
|
|
4059
|
+
});
|
|
4060
|
+
defineMethod("intersect", ["list"], ({ list }) => {
|
|
4061
|
+
return `${list.map((inner) => inner.toString(true)).join(" & ")}`;
|
|
4062
|
+
});
|
|
4063
|
+
defineMethod("transform", [
|
|
4064
|
+
"inner",
|
|
4065
|
+
"callback",
|
|
4066
|
+
"preserve"
|
|
4067
|
+
], ({ inner }, isInner) => inner.toString(isInner));
|
|
4068
|
+
//#endregion
|
|
4069
|
+
//#region lib/types/onboarding-config.js
|
|
4070
|
+
/** Public page-bootstrap options shared by the Host and Client halves. */
|
|
4071
|
+
/** Validate Host configuration and its public page-bootstrap payload. */
|
|
4072
|
+
const Config = Schema.object({ credentialOnboarding: Schema.boolean().default(true) });
|
|
4073
|
+
/** Page-global key carrying only the public onboarding options. */
|
|
4074
|
+
const ONBOARDING_CONFIG_GLOBAL = "__QILIN_MODELS_ONBOARDING__";
|
|
4075
|
+
//#endregion
|
|
2715
4076
|
//#region lib/types/client/index.js
|
|
2716
4077
|
/** Dictionary namespace owned by this plugin. */
|
|
2717
4078
|
const NS = "settings.models";
|
|
@@ -2746,6 +4107,8 @@ window.__ModuleLoader__.load({
|
|
|
2746
4107
|
* @param ctx - client root context.
|
|
2747
4108
|
*/
|
|
2748
4109
|
function apply(ctx) {
|
|
4110
|
+
const payload = globalThis[ONBOARDING_CONFIG_GLOBAL];
|
|
4111
|
+
const configured = Config(payload === void 0 ? {} : payload);
|
|
2749
4112
|
ctx.effect(() => ctx.locale.register(NS, {
|
|
2750
4113
|
zh,
|
|
2751
4114
|
en
|
|
@@ -2801,7 +4164,7 @@ window.__ModuleLoader__.load({
|
|
|
2801
4164
|
}
|
|
2802
4165
|
}
|
|
2803
4166
|
}, ModelsSection));
|
|
2804
|
-
ctx.slots.inject("settings.onboarding", () => ctx.slots.register({
|
|
4167
|
+
if (configured.credentialOnboarding) ctx.slots.inject("settings.onboarding", () => ctx.slots.register({
|
|
2805
4168
|
name: "settings.onboarding",
|
|
2806
4169
|
id: "deepseek-official",
|
|
2807
4170
|
order: 0,
|