dsh-provider-qoder 0.3.2 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -3
- package/README_CN.md +1 -2
- package/lib/client.js +708 -260
- package/lib/index.d.ts +9 -9
- package/lib/index.js +238 -64
- package/package.json +32 -33
package/lib/client.js
CHANGED
|
@@ -14,6 +14,112 @@ window.__ModuleLoader__.load({
|
|
|
14
14
|
return source === "env" || source?.endsWith("-env") === true;
|
|
15
15
|
}
|
|
16
16
|
//#endregion
|
|
17
|
+
//#region src/qoder/catalog.ts
|
|
18
|
+
function positiveNumber(value) {
|
|
19
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : void 0;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Provider-advertised context tiers of one model, smallest first. A tier without
|
|
23
|
+
* a usable capacity cannot be selected and is dropped.
|
|
24
|
+
*/
|
|
25
|
+
function contextTiersOf(model) {
|
|
26
|
+
const options = model.contextOptions;
|
|
27
|
+
if (options === void 0) return [];
|
|
28
|
+
return Object.entries(options).flatMap(([key, value]) => {
|
|
29
|
+
const tokenCount = value.tokenCount;
|
|
30
|
+
return typeof tokenCount === "number" && Number.isFinite(tokenCount) && tokenCount > 0 ? [{
|
|
31
|
+
key,
|
|
32
|
+
tokenCount,
|
|
33
|
+
isDefault: value.isDefault === true
|
|
34
|
+
}] : [];
|
|
35
|
+
}).sort((left, right) => left.tokenCount - right.tokenCount);
|
|
36
|
+
}
|
|
37
|
+
/** Resolve a usable selection consistently for the composer and adapter. */
|
|
38
|
+
function resolveContextTier(model, manualTier, historicalWindow) {
|
|
39
|
+
const tiers = contextTiersOf(model);
|
|
40
|
+
return tiers.find((tier) => tier.key === manualTier) ?? tiers.find((tier) => tier.tokenCount === historicalWindow) ?? tiers.find((tier) => tier.key === model.contextTier) ?? tiers.find((tier) => tier.tokenCount === model.contextWindow) ?? (model.contextWindow === void 0 ? tiers.find((tier) => tier.isDefault) : void 0);
|
|
41
|
+
}
|
|
42
|
+
/** Compact capacity label, e.g. `200K` or `1M`. */
|
|
43
|
+
function formatContextTokens(tokenCount) {
|
|
44
|
+
if (tokenCount >= 1e6) {
|
|
45
|
+
const millions = tokenCount / 1e6;
|
|
46
|
+
return `${Number.isInteger(millions) ? millions : millions.toFixed(1)}M`;
|
|
47
|
+
}
|
|
48
|
+
if (tokenCount >= 1e3) {
|
|
49
|
+
const thousands = tokenCount / 1e3;
|
|
50
|
+
return `${Number.isInteger(thousands) ? thousands : thousands.toFixed(1)}K`;
|
|
51
|
+
}
|
|
52
|
+
return String(tokenCount);
|
|
53
|
+
}
|
|
54
|
+
/** Format a price factor number to string (e.g. 1 -> '1', 1.6 -> '1.6', 0.5 -> '0.5', 1.25 -> '1.25'). */
|
|
55
|
+
function formatRateFactor(value) {
|
|
56
|
+
const rounded = Number(value.toFixed(2));
|
|
57
|
+
return String(rounded);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* The provider-advertised context tier the subscriber selected, when the
|
|
61
|
+
* provider still advertises that tier with a usable capacity.
|
|
62
|
+
*/
|
|
63
|
+
function selectedContextTier(model) {
|
|
64
|
+
const key = model.contextTier;
|
|
65
|
+
if (typeof key !== "string" || key.length === 0) return void 0;
|
|
66
|
+
const tokenCount = positiveNumber(model.contextOptions?.[key]?.tokenCount);
|
|
67
|
+
return tokenCount === void 0 ? void 0 : {
|
|
68
|
+
key,
|
|
69
|
+
tokenCount
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
const defaultMaxTokens = 32768;
|
|
73
|
+
const defaultModels = [
|
|
74
|
+
{
|
|
75
|
+
id: "cmodel",
|
|
76
|
+
name: "Cantus (Qoder)",
|
|
77
|
+
description: "Default Global Qoder subscription model for quick validation",
|
|
78
|
+
contextWindow: 1e6,
|
|
79
|
+
maxTokens: defaultMaxTokens,
|
|
80
|
+
supportsImages: true
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
id: "auto",
|
|
84
|
+
name: "Qoder Auto",
|
|
85
|
+
description: "Server-routed Global Qoder model pool",
|
|
86
|
+
contextWindow: 18e4,
|
|
87
|
+
maxTokens: defaultMaxTokens,
|
|
88
|
+
supportsImages: true
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
id: "ultimate",
|
|
92
|
+
name: "Qoder Ultimate",
|
|
93
|
+
description: "Highest-capability Global Qoder model pool",
|
|
94
|
+
contextWindow: 1e6,
|
|
95
|
+
maxTokens: defaultMaxTokens,
|
|
96
|
+
supportsImages: true
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
id: "performance",
|
|
100
|
+
name: "Qoder Performance",
|
|
101
|
+
description: "Performance-oriented Global Qoder model pool",
|
|
102
|
+
contextWindow: 1e6,
|
|
103
|
+
maxTokens: defaultMaxTokens,
|
|
104
|
+
supportsImages: true
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
id: "efficient",
|
|
108
|
+
name: "Qoder Efficient",
|
|
109
|
+
description: "Efficiency-oriented Global Qoder model pool",
|
|
110
|
+
contextWindow: 18e4,
|
|
111
|
+
maxTokens: defaultMaxTokens,
|
|
112
|
+
supportsImages: true
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
id: "lite",
|
|
116
|
+
name: "Qoder Lite",
|
|
117
|
+
description: "Basic Global Qoder model pool",
|
|
118
|
+
contextWindow: 18e4,
|
|
119
|
+
maxTokens: defaultMaxTokens
|
|
120
|
+
}
|
|
121
|
+
];
|
|
122
|
+
//#endregion
|
|
17
123
|
//#region src/client/locales.ts
|
|
18
124
|
const zh = {
|
|
19
125
|
nav: "Qoder",
|
|
@@ -52,7 +158,16 @@ window.__ModuleLoader__.load({
|
|
|
52
158
|
modelsRequired: "至少需要保留一个模型。",
|
|
53
159
|
modelUnavailable: "不可用",
|
|
54
160
|
modelRate: "{value}x",
|
|
161
|
+
modelRateFree: "免费",
|
|
162
|
+
modelRateDiscount: "{value}x(原 {original}x)",
|
|
55
163
|
modelRateUnknown: "倍率未知",
|
|
164
|
+
contextTierLabel: "上下文",
|
|
165
|
+
contextTierDefaultSuffix: "(默认)",
|
|
166
|
+
contextTierHint: "选择该模型使用的上下文档位;更大的档位会同时提升 DSH 的上下文预算并改变 Qoder 请求使用的档位。",
|
|
167
|
+
contextSelectFailed: "上下文切换失败,请重试。",
|
|
168
|
+
contextDefaultFailed: "当前会话已切换,但新会话默认值保存失败。",
|
|
169
|
+
contextSelectTitle: "选择上下文大小",
|
|
170
|
+
contextSelectMenuHeader: "上下文容量",
|
|
56
171
|
accountTitle: "Qoder",
|
|
57
172
|
accountLoading: "正在读取账号与额度…",
|
|
58
173
|
accountFailed: "无法读取账号信息与额度。",
|
|
@@ -115,7 +230,16 @@ window.__ModuleLoader__.load({
|
|
|
115
230
|
modelsRequired: "Keep at least one model.",
|
|
116
231
|
modelUnavailable: "Unavailable",
|
|
117
232
|
modelRate: "{value}x",
|
|
233
|
+
modelRateFree: "Free",
|
|
234
|
+
modelRateDiscount: "{value}x (was {original}x)",
|
|
118
235
|
modelRateUnknown: "Rate unknown",
|
|
236
|
+
contextTierLabel: "Context",
|
|
237
|
+
contextTierDefaultSuffix: " (default)",
|
|
238
|
+
contextTierHint: "Select the context tier for this model. A larger tier raises the DSH context budget and changes the tier the Qoder request uses.",
|
|
239
|
+
contextSelectFailed: "Could not change the context window. Please retry.",
|
|
240
|
+
contextDefaultFailed: "Session updated, but the default for new sessions could not be saved.",
|
|
241
|
+
contextSelectTitle: "Select context window size",
|
|
242
|
+
contextSelectMenuHeader: "Context Capacity",
|
|
119
243
|
accountTitle: "Qoder",
|
|
120
244
|
accountLoading: "Reading account and quota…",
|
|
121
245
|
accountFailed: "Could not read account details or quota.",
|
|
@@ -192,14 +316,57 @@ window.__ModuleLoader__.load({
|
|
|
192
316
|
}
|
|
193
317
|
}
|
|
194
318
|
//#endregion
|
|
319
|
+
//#region src/client/credential-operations.ts
|
|
320
|
+
function reconcileQoderModels(known, discovered) {
|
|
321
|
+
const availableIds = new Set(discovered.map((model) => model.id));
|
|
322
|
+
const unavailable = known.filter((model) => !availableIds.has(model.id)).map((model) => ({
|
|
323
|
+
...model,
|
|
324
|
+
...model.contextOptions !== void 0 ? { contextOptions: { ...model.contextOptions } } : {}
|
|
325
|
+
}));
|
|
326
|
+
const previous = new Map(known.map((model) => [model.id, model]));
|
|
327
|
+
const reconciled = discovered.map((model) => {
|
|
328
|
+
const remembered = previous.get(model.id);
|
|
329
|
+
if (remembered === void 0) return {
|
|
330
|
+
...model,
|
|
331
|
+
...model.contextOptions !== void 0 ? { contextOptions: { ...model.contextOptions } } : {}
|
|
332
|
+
};
|
|
333
|
+
const carried = selectedContextTier({
|
|
334
|
+
contextTier: remembered.contextTier,
|
|
335
|
+
contextOptions: model.contextOptions ?? remembered.contextOptions
|
|
336
|
+
});
|
|
337
|
+
const options = model.contextOptions ?? remembered.contextOptions;
|
|
338
|
+
const clonedOptions = options !== void 0 ? { contextOptions: { ...options } } : {};
|
|
339
|
+
if (carried !== void 0) return {
|
|
340
|
+
...model,
|
|
341
|
+
...clonedOptions,
|
|
342
|
+
contextTier: carried.key,
|
|
343
|
+
contextWindow: carried.tokenCount
|
|
344
|
+
};
|
|
345
|
+
const budget = remembered.contextWindow;
|
|
346
|
+
return budget === void 0 || model.contextWindow === void 0 ? {
|
|
347
|
+
...model,
|
|
348
|
+
...clonedOptions
|
|
349
|
+
} : {
|
|
350
|
+
...model,
|
|
351
|
+
...clonedOptions,
|
|
352
|
+
contextWindow: Math.min(budget, model.contextWindow)
|
|
353
|
+
};
|
|
354
|
+
});
|
|
355
|
+
return {
|
|
356
|
+
catalog: [...reconciled, ...unavailable],
|
|
357
|
+
selected: reconciled,
|
|
358
|
+
unavailableIds: new Set(unavailable.map((model) => model.id))
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
//#endregion
|
|
195
362
|
//#region \0dsh-css:/home/runner/work/dsh-provider-qoder/dsh-provider-qoder/src/client/QoderCredentialCard.module.css.mjs
|
|
196
|
-
const css = ".SRqrhW_credential{color:var(--dsw-alias-label-primary);border-radius:10px;margin-top:12px}.SRqrhW_credential p{margin:8px 0 0}.SRqrhW_credentialEditor{box-sizing:border-box;border:1px solid var(--dsw-alias-border-l2);border-radius:12px;flex-direction:column;gap:12px;padding:12px 14px;display:flex}.SRqrhW_credentialRowHead{align-items:center;gap:10px;display:flex}.SRqrhW_credentialIdentity{align-items:center;gap:6px;min-width:0;display:inline-flex}.SRqrhW_credentialName{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:500;line-height:22px}.SRqrhW_credentialDot{box-sizing:border-box;border-radius:50%;flex:none;width:8px;height:8px;display:inline-block}.SRqrhW_credentialDotConfigured{background:var(--dsw-alias-state-success-primary)}.SRqrhW_credentialDotMissing{background:var(--dsw-alias-state-error-primary)}.SRqrhW_regionBadge{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-secondary);border-radius:4px;align-items:center;padding:1px 6px;font-size:11px;font-weight:500;line-height:16px;display:inline-flex}.SRqrhW_regionSelector{flex-direction:column;gap:8px;margin-bottom:14px;display:flex}.SRqrhW_regionGroup{gap:8px;display:flex}.SRqrhW_regionOption{border:1px solid var(--dsw-alias-border-l2);cursor:pointer;background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-secondary);user-select:none;border-radius:8px;align-items:center;gap:6px;padding:6px 12px;font-size:12px;line-height:18px;transition:all .12s;display:inline-flex}.SRqrhW_regionOption:hover:not(.SRqrhW_regionOptionDisabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.SRqrhW_credential button.SRqrhW_regionOptionActive{border-color:var(--dsw-alias-brand-primary);background:var(--dsw-alias-interactive-bg-selected);color:var(--dsw-alias-brand-primary);font-weight:500}.SRqrhW_regionOptionDisabled{cursor:not-allowed;opacity:.5}.SRqrhW_editButton{box-sizing:border-box;font:inherit;background:0 0;margin-left:auto;font-size:12px;line-height:18px;border:1px solid var(--dsw-alias-border-l2)!important;border-radius:14px!important;height:28px!important;padding:0 10px!important}.SRqrhW_editButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-solid)}.SRqrhW_editor{background:var(--dsw-alias-bg-module-platform);border-radius:12px;padding:14px 16px}.SRqrhW_customized{border-top:1px solid var(--dsw-alias-border-l2);margin-top:14px;padding-top:10px}.SRqrhW_customizedSummary{cursor:pointer;width:fit-content;color:var(--dsw-alias-label-secondary);border-radius:6px;align-items:center;gap:6px;margin-left:-4px;padding:2px 4px;font-size:12px;font-weight:500;line-height:18px;list-style:none;display:flex}.SRqrhW_customizedSummary::-webkit-details-marker{display:none}.SRqrhW_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)}.SRqrhW_customized[open]>.SRqrhW_customizedSummary:before{transform:rotate(45deg)translate(-1px,-1px)}.SRqrhW_customizedBody{padding-top:12px}.SRqrhW_modelCatalog,.SRqrhW_modelList{flex-direction:column;gap:10px;display:flex}.SRqrhW_modelCatalogHead{justify-content:space-between;align-items:flex-start;gap:12px;display:flex}.SRqrhW_modelCatalogTitle{color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:500;line-height:18px}.SRqrhW_modelCatalogMeta{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px;margin:2px 0 0!important}.SRqrhW_linkButton{box-sizing:border-box;font:inherit;background:0 0;font-size:12px;line-height:18px;border:none!important;border-radius:14px!important;height:28px!important;padding:0 10px!important}.SRqrhW_linkButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.SRqrhW_modelChoice{cursor:pointer;border-radius:6px;grid-template-columns:auto minmax(0,1fr) auto auto auto;align-items:center;gap:8px;padding:6px 8px;font-size:13px;display:grid}.SRqrhW_modelChoice:hover{background:var(--dsw-alias-interactive-bg-hover)}.SRqrhW_modelChoiceName{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.SRqrhW_modelChoice code{color:var(--dsw-alias-label-tertiary);font-size:11px}.SRqrhW_modelRate{min-width:34px;color:var(--dsw-alias-brand-primary);text-align:right;font-size:12px;font-weight:600}.SRqrhW_modelUnavailable{cursor:not-allowed;opacity:.55}.SRqrhW_modelBadge{color:var(--dsw-alias-state-error-primary);font-size:11px}@media (prefers-reduced-motion:reduce){.SRqrhW_customizedSummary:before{transition:none}}.SRqrhW_head{justify-content:space-between;align-items:center;gap:12px;margin-bottom:20px;display:flex}.SRqrhW_heading{margin:0;font-size:18px;font-weight:600}.SRqrhW_status{color:var(--dsw-alias-label-secondary);font-size:12px}.SRqrhW_configured,.SRqrhW_success{color:var(--dsw-alias-state-success-primary)}.SRqrhW_label{color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:500;line-height:18px;display:block}.SRqrhW_input{box-sizing:border-box;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);width:100%;height:32px;color:var(--dsw-alias-label-primary);border-radius:8px;outline:none;margin-top:6px;padding:0 10px}.SRqrhW_input:focus{border-color:var(--dsw-alias-brand-primary)}.SRqrhW_input::placeholder{color:var(--dsw-alias-label-dimmed)}.SRqrhW_input:disabled{cursor:not-allowed;opacity:.4}.SRqrhW_hint{color:var(--dsw-alias-label-secondary);font-size:12px}.SRqrhW_actions{justify-content:flex-end;gap:8px;margin-top:14px;display:flex}.SRqrhW_credential button{cursor:pointer;height:32px;color:var(--dsw-alias-label-primary);border:1px solid #0000;border-radius:16px;padding:0 12px}.SRqrhW_credential button:disabled{cursor:not-allowed;opacity:.4}.SRqrhW_primary{background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-foreground)!important}.SRqrhW_primary:hover:not(:disabled){background:var(--dsw-alias-button-primary-hover)}.SRqrhW_secondary{background:0 0;border-color:var(--dsw-alias-border-l2)!important}.SRqrhW_secondary:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.SRqrhW_danger{background:0 0;border-color:var(--dsw-alias-state-error-primary)!important;color:var(--dsw-alias-state-error-primary)!important}.SRqrhW_danger:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger)}.SRqrhW_error{color:var(--dsw-alias-state-error-primary);font-size:12px}.SRqrhW_success{font-size:12px}.SRqrhW_accountSection{background:var(--dsw-alias-bg-module-platform);border-radius:8px;flex-direction:column;gap:10px;margin-top:12px;padding:12px;display:flex}.SRqrhW_accountHead{justify-content:space-between;align-items:center;gap:8px;display:flex}.SRqrhW_userInfo{align-items:center;gap:10px;min-width:0;display:flex}.SRqrhW_avatar{background:var(--dsw-alias-brand-primary);width:32px;height:32px;color:var(--dsw-alias-label-primary-foreground);text-transform:uppercase;border-radius:50%;flex-shrink:0;justify-content:center;align-items:center;font-size:14px;font-weight:600;display:flex}.SRqrhW_userDetails{flex-direction:column;gap:2px;min-width:0;display:flex}.SRqrhW_userName{color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;font-size:13px;font-weight:600;overflow:hidden}.SRqrhW_userEmail{color:var(--dsw-alias-label-tertiary);text-overflow:ellipsis;white-space:nowrap;font-size:11px;overflow:hidden}.SRqrhW_refreshBtn{border:1px solid var(--dsw-alias-border-l2)!important;height:26px!important;color:var(--dsw-alias-label-secondary)!important;background:0 0!important;border-radius:13px!important;padding:0 8px!important;font-size:12px!important}.SRqrhW_refreshBtn:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)!important}.SRqrhW_quotaBlock{border-top:1px solid var(--dsw-alias-border-l2);flex-direction:column;gap:6px;padding-top:8px;display:flex}.SRqrhW_quotaHeader{justify-content:space-between;align-items:center;gap:8px;display:flex}.SRqrhW_quotaLabel{color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:600}.SRqrhW_quotaTop{justify-content:space-between;align-items:baseline;gap:8px;font-size:12px;display:flex}.SRqrhW_quotaTop strong{color:var(--dsw-alias-brand-primary);font-size:13px}.SRqrhW_quotaDescription{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:16px;margin:0!important}.SRqrhW_quotaProgress{background:var(--dsw-alias-border-l3);width:100%;height:6px;accent-color:var(--dsw-alias-brand-primary);-webkit-appearance:none;appearance:none;border:0;border-radius:999px;overflow:hidden}.SRqrhW_quotaProgress::-webkit-progress-bar{background:var(--dsw-alias-border-l3);border-radius:999px}.SRqrhW_quotaProgress::-webkit-progress-value{background:var(--dsw-alias-brand-primary);border-radius:999px}.SRqrhW_quotaProgress::-moz-progress-bar{background:var(--dsw-alias-brand-primary);border-radius:999px}.SRqrhW_quotaMeta{color:var(--dsw-alias-label-tertiary);justify-content:space-between;align-items:center;gap:8px;font-size:11px;display:flex}.SRqrhW_accountLoadingText,.SRqrhW_accountEmptyText{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px}.SRqrhW_userNameRow{align-items:center;gap:8px;display:flex}.SRqrhW_planBadge{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-brand-primary);border-radius:4px;align-items:center;padding:1px 6px;font-size:11px;font-weight:600;line-height:16px;display:inline-flex}.SRqrhW_orgTag{color:var(--dsw-alias-label-tertiary);font-size:11px}.SRqrhW_suspendedBanner{background:var(--dsw-alias-state-error-subtle,#ff4d4f1a);color:var(--dsw-alias-state-error-primary);border-radius:6px;align-items:center;gap:6px;margin-bottom:8px;padding:6px 10px;font-size:12px;display:flex}.SRqrhW_searchModeSection{border-top:1px solid var(--dsw-alias-border-l2);flex-direction:column;gap:8px;margin-top:16px;padding-top:14px;display:flex}.SRqrhW_searchModeHintText{color:var(--dsw-alias-label-secondary);margin:4px 0 0;font-size:12px;line-height:18px}";
|
|
197
|
-
const tagId = "dsh-provider-qoder/QoderCredentialCard.module.css";
|
|
198
|
-
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
363
|
+
const css$1 = ".SRqrhW_credential{color:var(--dsw-alias-label-primary);border-radius:10px;margin-top:12px}.SRqrhW_credential p{margin:8px 0 0}.SRqrhW_credentialEditor{box-sizing:border-box;border:.5px solid var(--dsw-alias-border-l2);border-radius:var(--dsw-radius-xl,12px);flex-direction:column;gap:12px;padding:12px 14px;display:flex}.SRqrhW_credentialRowHead{align-items:center;gap:10px;display:flex}.SRqrhW_credentialIdentity{align-items:center;gap:6px;min-width:0;display:inline-flex}.SRqrhW_credentialName{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:500;line-height:22px}.SRqrhW_credentialDot{box-sizing:border-box;border-radius:50%;flex:none;width:8px;height:8px;display:inline-block}.SRqrhW_credentialDotConfigured{background:var(--dsw-alias-state-success-primary)}.SRqrhW_credentialDotMissing{background:var(--dsw-alias-state-error-primary)}.SRqrhW_regionBadge{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-secondary);border-radius:4px;align-items:center;padding:1px 6px;font-size:11px;font-weight:500;line-height:16px;display:inline-flex}.SRqrhW_regionSelector{flex-direction:column;gap:8px;margin-bottom:14px;display:flex}.SRqrhW_regionGroup{gap:8px;display:flex}.SRqrhW_regionOption{border:1px solid var(--dsw-alias-border-l2);cursor:pointer;background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-secondary);user-select:none;border-radius:8px;align-items:center;gap:6px;padding:6px 12px;font-size:12px;line-height:18px;transition:all .12s;display:inline-flex}.SRqrhW_regionOption:hover:not(.SRqrhW_regionOptionDisabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.SRqrhW_credential button.SRqrhW_regionOptionActive{border-color:var(--dsw-alias-brand-primary);background:var(--dsw-alias-interactive-bg-selected);color:var(--dsw-alias-brand-primary);font-weight:500}.SRqrhW_regionOptionDisabled{cursor:not-allowed;opacity:.5}.SRqrhW_editButton{box-sizing:border-box;font:inherit;background:0 0;margin-left:auto;font-size:12px;line-height:18px;border:1px solid var(--dsw-alias-border-l2)!important;border-radius:14px!important;height:28px!important;padding:0 10px!important}.SRqrhW_editButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-solid)}.SRqrhW_editor{background:var(--dsw-alias-bg-module-platform);border-radius:12px;padding:14px 16px}.SRqrhW_customized{border:.5px solid var(--dsw-alias-border-l2);border-radius:var(--dsw-radius-xl,12px);background:var(--dsw-alias-bg-module-platform);margin-top:12px;transition:all .12s;overflow:hidden}.SRqrhW_customizedSummary{box-sizing:border-box;border-radius:var(--dsw-radius-xl,12px);cursor:pointer;width:100%;color:var(--dsw-alias-label-primary);user-select:none;align-items:center;gap:8px;margin:0;padding:12px 14px;font-size:13px;font-weight:600;line-height:18px;list-style:none;transition:background .12s;display:flex}.SRqrhW_customizedSummary:hover{background:var(--dsw-alias-interactive-bg-hover)}.SRqrhW_modelSummaryBadge{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-tertiary);border-radius:4px;align-items:center;padding:1px 6px;font-size:11px;font-weight:400;line-height:16px;display:inline-flex}.SRqrhW_customizedSummary::-webkit-details-marker{display:none}.SRqrhW_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)}.SRqrhW_customized[open]>.SRqrhW_customizedSummary:before{transform:rotate(45deg)translate(-1px,-1px)}.SRqrhW_customized[open]>.SRqrhW_customizedSummary{border-bottom:.5px solid var(--dsw-alias-border-l2);border-bottom-right-radius:0;border-bottom-left-radius:0}.SRqrhW_customizedBody{padding:12px 14px 14px}.SRqrhW_modelCatalog{flex-direction:column;gap:10px;display:flex}.SRqrhW_modelList{flex-direction:column;gap:10px;max-height:360px;padding-right:4px;display:flex;overflow-y:auto}.SRqrhW_modelList::-webkit-scrollbar{width:4px}.SRqrhW_modelList::-webkit-scrollbar-thumb{background:var(--dsw-alias-border-l3);border-radius:2px}.SRqrhW_modelCatalogHead{justify-content:space-between;align-items:flex-start;gap:12px;display:flex}.SRqrhW_modelCatalogHeadCompact{justify-content:flex-end;align-items:center;gap:12px;display:flex}.SRqrhW_modelCatalogTitle{color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:500;line-height:18px}.SRqrhW_modelCatalogMeta{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px;margin:2px 0 0!important}.SRqrhW_linkButton{box-sizing:border-box;font:inherit;background:0 0;font-size:12px;line-height:18px;border:none!important;border-radius:14px!important;height:28px!important;padding:0 10px!important}.SRqrhW_linkButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.SRqrhW_modelChoice{border-radius:6px;flex-direction:column;gap:4px;padding:6px 8px;font-size:13px;display:flex}.SRqrhW_modelChoice:hover{background:var(--dsw-alias-interactive-bg-hover)}.SRqrhW_modelChoiceHead{cursor:pointer;grid-template-columns:auto minmax(0,1fr) auto auto auto;align-items:center;gap:8px;display:grid}.SRqrhW_modelTier{align-items:center;gap:8px;padding-left:24px;display:flex}.SRqrhW_modelTierLabel{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:18px}.SRqrhW_modelTierSelect{box-sizing:border-box;background:var(--dsw-alias-bg-layer-1);height:24px;color:inherit;font:inherit;cursor:pointer;border:0;border-radius:6px;padding:0 6px;font-size:12px}.SRqrhW_modelTierHint{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:18px;margin:0!important}.SRqrhW_modelChoiceName{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.SRqrhW_modelChoice code{color:var(--dsw-alias-label-tertiary);font-size:11px}.SRqrhW_modelRate{min-width:34px;color:var(--dsw-alias-brand-primary);text-align:right;font-size:12px;font-weight:600}.SRqrhW_modelUnavailable{cursor:not-allowed;opacity:.55}.SRqrhW_modelBadge{color:var(--dsw-alias-state-error-primary);font-size:11px}@media (prefers-reduced-motion:reduce){.SRqrhW_customizedSummary:before{transition:none}}.SRqrhW_head{justify-content:space-between;align-items:center;gap:12px;margin-bottom:20px;display:flex}.SRqrhW_heading{margin:0;font-size:18px;font-weight:600}.SRqrhW_status{color:var(--dsw-alias-label-secondary);font-size:12px}.SRqrhW_configured,.SRqrhW_success{color:var(--dsw-alias-state-success-primary)}.SRqrhW_label{color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:500;line-height:18px;display:block}.SRqrhW_input{box-sizing:border-box;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);width:100%;height:32px;color:var(--dsw-alias-label-primary);border-radius:8px;outline:none;margin-top:6px;padding:0 10px}.SRqrhW_input:focus{border-color:var(--dsw-alias-brand-primary)}.SRqrhW_input::placeholder{color:var(--dsw-alias-label-dimmed)}.SRqrhW_input:disabled{cursor:not-allowed;opacity:.4}.SRqrhW_hint{color:var(--dsw-alias-label-secondary);font-size:12px}.SRqrhW_actions{justify-content:flex-end;gap:8px;margin-top:14px;display:flex}.SRqrhW_credential button{cursor:pointer;height:32px;color:var(--dsw-alias-label-primary);border:1px solid #0000;border-radius:16px;padding:0 12px}.SRqrhW_credential button:disabled{cursor:not-allowed;opacity:.4}.SRqrhW_primary{background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-foreground)!important}.SRqrhW_primary:hover:not(:disabled){background:var(--dsw-alias-button-primary-hover)}.SRqrhW_secondary{background:0 0;border-color:var(--dsw-alias-border-l2)!important}.SRqrhW_secondary:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.SRqrhW_danger{background:0 0;border-color:var(--dsw-alias-state-error-primary)!important;color:var(--dsw-alias-state-error-primary)!important}.SRqrhW_danger:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger)}.SRqrhW_error{color:var(--dsw-alias-state-error-primary);font-size:12px}.SRqrhW_success{font-size:12px}.SRqrhW_accountSection{border:.5px solid var(--dsw-alias-border-l2);border-radius:var(--dsw-radius-xl,12px);background:var(--dsw-alias-bg-module-platform);flex-direction:column;gap:10px;margin-top:12px;padding:12px 14px;display:flex}.SRqrhW_accountHead{justify-content:space-between;align-items:center;gap:8px;display:flex}.SRqrhW_userInfo{align-items:center;gap:10px;min-width:0;display:flex}.SRqrhW_avatar{background:var(--dsw-alias-brand-primary);width:32px;height:32px;color:var(--dsw-alias-label-primary-foreground);text-transform:uppercase;border-radius:50%;flex-shrink:0;justify-content:center;align-items:center;font-size:14px;font-weight:600;display:flex}.SRqrhW_userDetails{flex-direction:column;gap:2px;min-width:0;display:flex}.SRqrhW_userName{color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;font-size:13px;font-weight:600;overflow:hidden}.SRqrhW_userEmail{color:var(--dsw-alias-label-tertiary);text-overflow:ellipsis;white-space:nowrap;font-size:11px;overflow:hidden}.SRqrhW_refreshBtn{border:1px solid var(--dsw-alias-border-l2)!important;height:26px!important;color:var(--dsw-alias-label-secondary)!important;background:0 0!important;border-radius:13px!important;padding:0 8px!important;font-size:12px!important}.SRqrhW_refreshBtn:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)!important}.SRqrhW_quotaBlock{border-top:1px solid var(--dsw-alias-border-l2);flex-direction:column;gap:6px;padding-top:8px;display:flex}.SRqrhW_quotaHeader{justify-content:space-between;align-items:center;gap:8px;display:flex}.SRqrhW_quotaLabel{color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:600}.SRqrhW_quotaTop{justify-content:space-between;align-items:baseline;gap:8px;font-size:12px;display:flex}.SRqrhW_quotaTop strong{color:var(--dsw-alias-brand-primary);font-size:13px}.SRqrhW_quotaDescription{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:16px;margin:0!important}.SRqrhW_quotaProgress{background:var(--dsw-alias-border-l3);width:100%;height:6px;accent-color:var(--dsw-alias-brand-primary);-webkit-appearance:none;appearance:none;border:0;border-radius:999px;overflow:hidden}.SRqrhW_quotaProgress::-webkit-progress-bar{background:var(--dsw-alias-border-l3);border-radius:999px}.SRqrhW_quotaProgress::-webkit-progress-value{background:var(--dsw-alias-brand-primary);border-radius:999px}.SRqrhW_quotaProgress::-moz-progress-bar{background:var(--dsw-alias-brand-primary);border-radius:999px}.SRqrhW_quotaMeta{color:var(--dsw-alias-label-tertiary);justify-content:space-between;align-items:center;gap:8px;font-size:11px;display:flex}.SRqrhW_accountLoadingText,.SRqrhW_accountEmptyText{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px}.SRqrhW_userNameRow{align-items:center;gap:8px;display:flex}.SRqrhW_planBadge{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-brand-primary);border-radius:4px;align-items:center;padding:1px 6px;font-size:11px;font-weight:600;line-height:16px;display:inline-flex}.SRqrhW_orgTag{color:var(--dsw-alias-label-tertiary);font-size:11px}.SRqrhW_suspendedBanner{background:var(--dsw-alias-state-error-subtle,#ff4d4f1a);color:var(--dsw-alias-state-error-primary);border-radius:6px;align-items:center;gap:6px;margin-bottom:8px;padding:6px 10px;font-size:12px;display:flex}.SRqrhW_searchModeSection{border:.5px solid var(--dsw-alias-border-l2);border-radius:var(--dsw-radius-xl,12px);background:var(--dsw-alias-bg-module-platform);flex-direction:column;gap:10px;margin-top:12px;padding:12px 14px;display:flex}.SRqrhW_searchModeHintText{color:var(--dsw-alias-label-secondary);margin:4px 0 0;font-size:12px;line-height:18px}";
|
|
364
|
+
const tagId$1 = "dsh-provider-qoder/QoderCredentialCard.module.css";
|
|
365
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
|
|
199
366
|
const tag = document.createElement("style");
|
|
200
367
|
tag.dataset.plugin = "dsh-provider-qoder";
|
|
201
|
-
tag.dataset.pluginCss = tagId;
|
|
202
|
-
tag.textContent = css;
|
|
368
|
+
tag.dataset.pluginCss = tagId$1;
|
|
369
|
+
tag.textContent = css$1;
|
|
203
370
|
document.head.appendChild(tag);
|
|
204
371
|
}
|
|
205
372
|
var QoderCredentialCard_module_css_default = {
|
|
@@ -234,12 +401,19 @@ window.__ModuleLoader__.load({
|
|
|
234
401
|
"modelBadge": "SRqrhW_modelBadge",
|
|
235
402
|
"modelCatalog": "SRqrhW_modelCatalog",
|
|
236
403
|
"modelCatalogHead": "SRqrhW_modelCatalogHead",
|
|
404
|
+
"modelCatalogHeadCompact": "SRqrhW_modelCatalogHeadCompact",
|
|
237
405
|
"modelCatalogMeta": "SRqrhW_modelCatalogMeta",
|
|
238
406
|
"modelCatalogTitle": "SRqrhW_modelCatalogTitle",
|
|
239
407
|
"modelChoice": "SRqrhW_modelChoice",
|
|
408
|
+
"modelChoiceHead": "SRqrhW_modelChoiceHead",
|
|
240
409
|
"modelChoiceName": "SRqrhW_modelChoiceName",
|
|
241
410
|
"modelList": "SRqrhW_modelList",
|
|
242
411
|
"modelRate": "SRqrhW_modelRate",
|
|
412
|
+
"modelSummaryBadge": "SRqrhW_modelSummaryBadge",
|
|
413
|
+
"modelTier": "SRqrhW_modelTier",
|
|
414
|
+
"modelTierHint": "SRqrhW_modelTierHint",
|
|
415
|
+
"modelTierLabel": "SRqrhW_modelTierLabel",
|
|
416
|
+
"modelTierSelect": "SRqrhW_modelTierSelect",
|
|
243
417
|
"modelUnavailable": "SRqrhW_modelUnavailable",
|
|
244
418
|
"orgTag": "SRqrhW_orgTag",
|
|
245
419
|
"planBadge": "SRqrhW_planBadge",
|
|
@@ -271,6 +445,159 @@ window.__ModuleLoader__.load({
|
|
|
271
445
|
"userNameRow": "SRqrhW_userNameRow"
|
|
272
446
|
};
|
|
273
447
|
//#endregion
|
|
448
|
+
//#region src/client/QoderModelCatalog.tsx
|
|
449
|
+
function validateModelCatalog(models) {
|
|
450
|
+
return models.length === 0 ? "modelsRequired" : void 0;
|
|
451
|
+
}
|
|
452
|
+
function QoderModelCatalog(props) {
|
|
453
|
+
const { operations, models, disabled, fetchDisabled, hideTitle, onChange, t } = props;
|
|
454
|
+
const [fetching, setFetching] = (0, react.useState)(false);
|
|
455
|
+
const [failure, setFailure] = (0, react.useState)();
|
|
456
|
+
const [catalog, setCatalog] = (0, react.useState)();
|
|
457
|
+
const [unavailableIds, setUnavailableIds] = (0, react.useState)(/* @__PURE__ */ new Set());
|
|
458
|
+
const displayedModels = catalog ?? models;
|
|
459
|
+
const selectedIds = (0, react.useMemo)(() => new Set(models.map((model) => model.id)), [models]);
|
|
460
|
+
const fetchModels = async () => {
|
|
461
|
+
setFetching(true);
|
|
462
|
+
setFailure(void 0);
|
|
463
|
+
const result = await operations.discoverModels();
|
|
464
|
+
setFetching(false);
|
|
465
|
+
if (!result.ok) {
|
|
466
|
+
setFailure(result.error.message || t("modelsFetchFailed"));
|
|
467
|
+
return;
|
|
468
|
+
}
|
|
469
|
+
const reconciled = reconcileQoderModels(catalog ?? models, result.value);
|
|
470
|
+
setCatalog(reconciled.catalog);
|
|
471
|
+
setUnavailableIds(reconciled.unavailableIds);
|
|
472
|
+
onChange(reconciled.selected);
|
|
473
|
+
};
|
|
474
|
+
const toggleModel = (id, enabled) => {
|
|
475
|
+
if (unavailableIds.has(id)) return;
|
|
476
|
+
const source = catalog ?? models;
|
|
477
|
+
if (catalog === void 0) setCatalog(source);
|
|
478
|
+
const nextSelected = new Set(selectedIds);
|
|
479
|
+
if (enabled) nextSelected.add(id);
|
|
480
|
+
else nextSelected.delete(id);
|
|
481
|
+
onChange(source.filter((model) => nextSelected.has(model.id) && !unavailableIds.has(model.id)));
|
|
482
|
+
};
|
|
483
|
+
const changeContextTier = (id, tierKey) => {
|
|
484
|
+
const source = catalog ?? models;
|
|
485
|
+
if (catalog === void 0) setCatalog(source);
|
|
486
|
+
const apply = (model) => {
|
|
487
|
+
if (model.id !== id) return model;
|
|
488
|
+
const tokenCount = model.contextOptions?.[tierKey]?.tokenCount;
|
|
489
|
+
if (typeof tokenCount !== "number" || !Number.isFinite(tokenCount) || tokenCount <= 0) return model;
|
|
490
|
+
return {
|
|
491
|
+
...model,
|
|
492
|
+
contextTier: tierKey,
|
|
493
|
+
contextWindow: tokenCount
|
|
494
|
+
};
|
|
495
|
+
};
|
|
496
|
+
const nextCatalog = source.map(apply);
|
|
497
|
+
setCatalog(nextCatalog);
|
|
498
|
+
onChange(models.map(apply));
|
|
499
|
+
};
|
|
500
|
+
const renderRate = (model) => {
|
|
501
|
+
if (model.isFree || model.priceFactor === 0) return t("modelRateFree");
|
|
502
|
+
if (model.priceFactor === void 0) return t("modelRateUnknown");
|
|
503
|
+
const current = formatRateFactor(model.priceFactor);
|
|
504
|
+
if (model.originalPriceFactor !== void 0 && model.originalPriceFactor > model.priceFactor) return t("modelRateDiscount", {
|
|
505
|
+
value: current,
|
|
506
|
+
original: formatRateFactor(model.originalPriceFactor)
|
|
507
|
+
});
|
|
508
|
+
return t("modelRate", { value: current });
|
|
509
|
+
};
|
|
510
|
+
const tieredModels = displayedModels.filter((model) => contextTiersOf(model).length > 1);
|
|
511
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
512
|
+
className: QoderCredentialCard_module_css_default.modelCatalog,
|
|
513
|
+
"aria-label": t("modelsTitle"),
|
|
514
|
+
children: [
|
|
515
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
516
|
+
className: hideTitle ? QoderCredentialCard_module_css_default.modelCatalogHeadCompact : QoderCredentialCard_module_css_default.modelCatalogHead,
|
|
517
|
+
children: [!hideTitle ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", {
|
|
518
|
+
className: QoderCredentialCard_module_css_default.modelCatalogTitle,
|
|
519
|
+
children: t("modelsTitle")
|
|
520
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
521
|
+
className: QoderCredentialCard_module_css_default.modelCatalogMeta,
|
|
522
|
+
children: t("modelsEnabled", { count: models.length })
|
|
523
|
+
})] }) : null, /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
524
|
+
type: "button",
|
|
525
|
+
className: QoderCredentialCard_module_css_default.linkButton,
|
|
526
|
+
disabled: disabled || fetching || Boolean(fetchDisabled),
|
|
527
|
+
onClick: () => {
|
|
528
|
+
fetchModels();
|
|
529
|
+
},
|
|
530
|
+
children: fetching ? t("modelsFetching") : t("modelsFetch")
|
|
531
|
+
})]
|
|
532
|
+
}),
|
|
533
|
+
failure ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
534
|
+
className: QoderCredentialCard_module_css_default.error,
|
|
535
|
+
role: "alert",
|
|
536
|
+
children: failure
|
|
537
|
+
}) : null,
|
|
538
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
539
|
+
className: QoderCredentialCard_module_css_default.modelList,
|
|
540
|
+
children: displayedModels.map((model) => {
|
|
541
|
+
const unavailable = unavailableIds.has(model.id);
|
|
542
|
+
const tiers = contextTiersOf(model);
|
|
543
|
+
const fallbackTier = tiers.find((tier) => tier.isDefault) ?? tiers[tiers.length - 1];
|
|
544
|
+
const selectedTier = resolveContextTier(model)?.key ?? fallbackTier?.key;
|
|
545
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
546
|
+
className: `${QoderCredentialCard_module_css_default.modelChoice} ${unavailable ? QoderCredentialCard_module_css_default.modelUnavailable : ""}`,
|
|
547
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
548
|
+
className: QoderCredentialCard_module_css_default.modelChoiceHead,
|
|
549
|
+
children: [
|
|
550
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
551
|
+
type: "checkbox",
|
|
552
|
+
checked: !unavailable && selectedIds.has(model.id),
|
|
553
|
+
disabled: disabled || unavailable,
|
|
554
|
+
onChange: (event) => {
|
|
555
|
+
toggleModel(model.id, event.currentTarget.checked);
|
|
556
|
+
}
|
|
557
|
+
}),
|
|
558
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
559
|
+
className: QoderCredentialCard_module_css_default.modelChoiceName,
|
|
560
|
+
children: model.name
|
|
561
|
+
}),
|
|
562
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
563
|
+
className: QoderCredentialCard_module_css_default.modelRate,
|
|
564
|
+
children: renderRate(model)
|
|
565
|
+
}),
|
|
566
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", { children: model.id }),
|
|
567
|
+
unavailable ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
568
|
+
className: QoderCredentialCard_module_css_default.modelBadge,
|
|
569
|
+
children: t("modelUnavailable")
|
|
570
|
+
}) : null
|
|
571
|
+
]
|
|
572
|
+
}), tiers.length > 1 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
573
|
+
className: QoderCredentialCard_module_css_default.modelTier,
|
|
574
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
575
|
+
className: QoderCredentialCard_module_css_default.modelTierLabel,
|
|
576
|
+
children: t("contextTierLabel")
|
|
577
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
|
|
578
|
+
className: QoderCredentialCard_module_css_default.modelTierSelect,
|
|
579
|
+
value: selectedTier ?? "",
|
|
580
|
+
disabled: disabled || unavailable || !selectedIds.has(model.id),
|
|
581
|
+
onChange: (event) => {
|
|
582
|
+
changeContextTier(model.id, event.currentTarget.value);
|
|
583
|
+
},
|
|
584
|
+
children: tiers.map((tier) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
585
|
+
value: tier.key,
|
|
586
|
+
children: tier.isDefault ? `${formatContextTokens(tier.tokenCount)}${t("contextTierDefaultSuffix")}` : formatContextTokens(tier.tokenCount)
|
|
587
|
+
}, tier.key))
|
|
588
|
+
})]
|
|
589
|
+
}) : null]
|
|
590
|
+
}, model.id);
|
|
591
|
+
})
|
|
592
|
+
}),
|
|
593
|
+
tieredModels.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
594
|
+
className: QoderCredentialCard_module_css_default.modelTierHint,
|
|
595
|
+
children: t("contextTierHint")
|
|
596
|
+
}) : null
|
|
597
|
+
]
|
|
598
|
+
});
|
|
599
|
+
}
|
|
600
|
+
//#endregion
|
|
274
601
|
//#region src/client/QoderAccountCard.tsx
|
|
275
602
|
function formatResetDate(dateStr) {
|
|
276
603
|
if (!dateStr) return void 0;
|
|
@@ -283,6 +610,18 @@ window.__ModuleLoader__.load({
|
|
|
283
610
|
minute: "2-digit"
|
|
284
611
|
});
|
|
285
612
|
}
|
|
613
|
+
function modelsOf$1(value, selectedRegion) {
|
|
614
|
+
if (typeof value !== "object" || value === null) return defaultModels.map((model) => ({ ...model }));
|
|
615
|
+
const section = value;
|
|
616
|
+
const region = selectedRegion ?? (section.region === "china" ? "china" : "global");
|
|
617
|
+
const scoped = section.modelsByRegion?.[region];
|
|
618
|
+
if (Array.isArray(scoped)) return scoped;
|
|
619
|
+
return defaultModels.map((model) => ({ ...model }));
|
|
620
|
+
}
|
|
621
|
+
function regionOf$1(value) {
|
|
622
|
+
if (typeof value !== "object" || value === null) return "global";
|
|
623
|
+
return value.region === "china" ? "china" : "global";
|
|
624
|
+
}
|
|
286
625
|
/**
|
|
287
626
|
* Settings card for the Qoder subscription: credential state, subscriber
|
|
288
627
|
* profile, and every quota block the provider reports.
|
|
@@ -292,6 +631,7 @@ window.__ModuleLoader__.load({
|
|
|
292
631
|
const [accountState, setAccountState] = (0, react.useState)({ status: "idle" });
|
|
293
632
|
const [refreshing, setRefreshing] = (0, react.useState)(false);
|
|
294
633
|
const [credentialRevision, setCredentialRevision] = (0, react.useState)(0);
|
|
634
|
+
const [modelSaveError, setModelSaveError] = (0, react.useState)();
|
|
295
635
|
const latestAccountRequest = (0, react.useRef)(0);
|
|
296
636
|
const modelSnapshot = (0, react.useSyncExternalStore)(operations.subscribeModels, operations.getModelSnapshot, operations.getModelSnapshot);
|
|
297
637
|
const loadCredential = (0, react.useCallback)(async () => {
|
|
@@ -412,9 +752,12 @@ window.__ModuleLoader__.load({
|
|
|
412
752
|
}, key);
|
|
413
753
|
};
|
|
414
754
|
const renderAccount = () => {
|
|
415
|
-
if (!configured) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("
|
|
416
|
-
className: QoderCredentialCard_module_css_default.
|
|
417
|
-
children:
|
|
755
|
+
if (!configured) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
756
|
+
className: QoderCredentialCard_module_css_default.accountSection,
|
|
757
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
758
|
+
className: QoderCredentialCard_module_css_default.accountEmptyText,
|
|
759
|
+
children: t("accountCredentialHint")
|
|
760
|
+
})
|
|
418
761
|
});
|
|
419
762
|
if (accountState.status === "loading") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
420
763
|
className: QoderCredentialCard_module_css_default.accountSection,
|
|
@@ -585,6 +928,54 @@ window.__ModuleLoader__.load({
|
|
|
585
928
|
]
|
|
586
929
|
});
|
|
587
930
|
};
|
|
931
|
+
const currentRegion = regionOf$1(modelSnapshot.value);
|
|
932
|
+
const currentModels = modelsOf$1(modelSnapshot.value, currentRegion);
|
|
933
|
+
const canModifyModels = modelSnapshot.status === "ready" && modelSnapshot.writable;
|
|
934
|
+
const handleModelsChange = async (models) => {
|
|
935
|
+
if (!canModifyModels) return;
|
|
936
|
+
setModelSaveError(void 0);
|
|
937
|
+
const failure = validateModelCatalog(models);
|
|
938
|
+
if (failure) {
|
|
939
|
+
setModelSaveError(t(failure));
|
|
940
|
+
return;
|
|
941
|
+
}
|
|
942
|
+
if (!await operations.storeModels(currentRegion, models)) setModelSaveError(t("saveFailed"));
|
|
943
|
+
};
|
|
944
|
+
const renderModelCatalogSection = () => {
|
|
945
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
|
|
946
|
+
className: QoderCredentialCard_module_css_default.customized,
|
|
947
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("summary", {
|
|
948
|
+
className: QoderCredentialCard_module_css_default.customizedSummary,
|
|
949
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("modelsTitle") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
950
|
+
className: QoderCredentialCard_module_css_default.modelSummaryBadge,
|
|
951
|
+
children: t("modelsEnabled", { count: currentModels.length })
|
|
952
|
+
})]
|
|
953
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
954
|
+
className: QoderCredentialCard_module_css_default.customizedBody,
|
|
955
|
+
children: [modelSnapshot.status === "loading" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
956
|
+
className: QoderCredentialCard_module_css_default.hint,
|
|
957
|
+
children: t("modelsLoading")
|
|
958
|
+
}) : modelSnapshot.status === "unavailable" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
959
|
+
className: QoderCredentialCard_module_css_default.error,
|
|
960
|
+
children: t("modelsUnavailable")
|
|
961
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(QoderModelCatalog, {
|
|
962
|
+
operations,
|
|
963
|
+
models: currentModels,
|
|
964
|
+
disabled: !canModifyModels,
|
|
965
|
+
fetchDisabled: !configured,
|
|
966
|
+
hideTitle: true,
|
|
967
|
+
t,
|
|
968
|
+
onChange: (models) => {
|
|
969
|
+
handleModelsChange(models);
|
|
970
|
+
}
|
|
971
|
+
}), modelSaveError ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
972
|
+
className: QoderCredentialCard_module_css_default.error,
|
|
973
|
+
role: "alert",
|
|
974
|
+
children: modelSaveError
|
|
975
|
+
}) : null]
|
|
976
|
+
})]
|
|
977
|
+
});
|
|
978
|
+
};
|
|
588
979
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
589
980
|
className: QoderCredentialCard_module_css_default.credential,
|
|
590
981
|
"aria-label": t("accountTitle"),
|
|
@@ -600,189 +991,13 @@ window.__ModuleLoader__.load({
|
|
|
600
991
|
})]
|
|
601
992
|
}),
|
|
602
993
|
renderAccount(),
|
|
603
|
-
renderWebSearchSection()
|
|
604
|
-
|
|
605
|
-
});
|
|
606
|
-
}
|
|
607
|
-
//#endregion
|
|
608
|
-
//#region src/qoder/catalog.ts
|
|
609
|
-
const defaultMaxTokens = 32768;
|
|
610
|
-
const defaultModels = [
|
|
611
|
-
{
|
|
612
|
-
id: "cmodel",
|
|
613
|
-
name: "Cantus (Qoder)",
|
|
614
|
-
description: "Default Global Qoder subscription model for quick validation",
|
|
615
|
-
contextWindow: 1e6,
|
|
616
|
-
maxTokens: defaultMaxTokens,
|
|
617
|
-
supportsImages: true
|
|
618
|
-
},
|
|
619
|
-
{
|
|
620
|
-
id: "auto",
|
|
621
|
-
name: "Qoder Auto",
|
|
622
|
-
description: "Server-routed Global Qoder model pool",
|
|
623
|
-
contextWindow: 18e4,
|
|
624
|
-
maxTokens: defaultMaxTokens,
|
|
625
|
-
supportsImages: true
|
|
626
|
-
},
|
|
627
|
-
{
|
|
628
|
-
id: "ultimate",
|
|
629
|
-
name: "Qoder Ultimate",
|
|
630
|
-
description: "Highest-capability Global Qoder model pool",
|
|
631
|
-
contextWindow: 1e6,
|
|
632
|
-
maxTokens: defaultMaxTokens,
|
|
633
|
-
supportsImages: true
|
|
634
|
-
},
|
|
635
|
-
{
|
|
636
|
-
id: "performance",
|
|
637
|
-
name: "Qoder Performance",
|
|
638
|
-
description: "Performance-oriented Global Qoder model pool",
|
|
639
|
-
contextWindow: 1e6,
|
|
640
|
-
maxTokens: defaultMaxTokens,
|
|
641
|
-
supportsImages: true
|
|
642
|
-
},
|
|
643
|
-
{
|
|
644
|
-
id: "efficient",
|
|
645
|
-
name: "Qoder Efficient",
|
|
646
|
-
description: "Efficiency-oriented Global Qoder model pool",
|
|
647
|
-
contextWindow: 18e4,
|
|
648
|
-
maxTokens: defaultMaxTokens,
|
|
649
|
-
supportsImages: true
|
|
650
|
-
},
|
|
651
|
-
{
|
|
652
|
-
id: "lite",
|
|
653
|
-
name: "Qoder Lite",
|
|
654
|
-
description: "Basic Global Qoder model pool",
|
|
655
|
-
contextWindow: 18e4,
|
|
656
|
-
maxTokens: defaultMaxTokens
|
|
657
|
-
}
|
|
658
|
-
];
|
|
659
|
-
//#endregion
|
|
660
|
-
//#region src/client/credential-operations.ts
|
|
661
|
-
function reconcileQoderModels(known, discovered) {
|
|
662
|
-
const availableIds = new Set(discovered.map((model) => model.id));
|
|
663
|
-
const unavailable = known.filter((model) => !availableIds.has(model.id));
|
|
664
|
-
const previous = new Map(known.map((model) => [model.id, model]));
|
|
665
|
-
const reconciled = discovered.map((model) => {
|
|
666
|
-
const budget = previous.get(model.id)?.contextWindow;
|
|
667
|
-
return budget === void 0 || model.contextWindow === void 0 ? model : {
|
|
668
|
-
...model,
|
|
669
|
-
contextWindow: Math.min(budget, model.contextWindow)
|
|
670
|
-
};
|
|
671
|
-
});
|
|
672
|
-
return {
|
|
673
|
-
catalog: [...reconciled, ...unavailable],
|
|
674
|
-
selected: reconciled,
|
|
675
|
-
unavailableIds: new Set(unavailable.map((model) => model.id))
|
|
676
|
-
};
|
|
677
|
-
}
|
|
678
|
-
//#endregion
|
|
679
|
-
//#region src/client/QoderModelCatalog.tsx
|
|
680
|
-
function validateModelCatalog(models) {
|
|
681
|
-
return models.length === 0 ? "modelsRequired" : void 0;
|
|
682
|
-
}
|
|
683
|
-
function QoderModelCatalog(props) {
|
|
684
|
-
const { operations, models, disabled, onChange, t } = props;
|
|
685
|
-
const [fetching, setFetching] = (0, react.useState)(false);
|
|
686
|
-
const [failure, setFailure] = (0, react.useState)();
|
|
687
|
-
const [catalog, setCatalog] = (0, react.useState)();
|
|
688
|
-
const [unavailableIds, setUnavailableIds] = (0, react.useState)(/* @__PURE__ */ new Set());
|
|
689
|
-
const displayedModels = catalog ?? models;
|
|
690
|
-
const selectedIds = (0, react.useMemo)(() => new Set(models.map((model) => model.id)), [models]);
|
|
691
|
-
const fetchModels = async () => {
|
|
692
|
-
setFetching(true);
|
|
693
|
-
setFailure(void 0);
|
|
694
|
-
const result = await operations.discoverModels();
|
|
695
|
-
setFetching(false);
|
|
696
|
-
if (!result.ok) {
|
|
697
|
-
setFailure(result.error.message || t("modelsFetchFailed"));
|
|
698
|
-
return;
|
|
699
|
-
}
|
|
700
|
-
const reconciled = reconcileQoderModels(catalog ?? models, result.value);
|
|
701
|
-
setCatalog(reconciled.catalog);
|
|
702
|
-
setUnavailableIds(reconciled.unavailableIds);
|
|
703
|
-
onChange(reconciled.selected);
|
|
704
|
-
};
|
|
705
|
-
const toggleModel = (id, enabled) => {
|
|
706
|
-
if (unavailableIds.has(id)) return;
|
|
707
|
-
const source = catalog ?? models;
|
|
708
|
-
if (catalog === void 0) setCatalog(source);
|
|
709
|
-
const nextSelected = new Set(selectedIds);
|
|
710
|
-
if (enabled) nextSelected.add(id);
|
|
711
|
-
else nextSelected.delete(id);
|
|
712
|
-
onChange(source.filter((model) => nextSelected.has(model.id) && !unavailableIds.has(model.id)));
|
|
713
|
-
};
|
|
714
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
715
|
-
className: QoderCredentialCard_module_css_default.modelCatalog,
|
|
716
|
-
"aria-label": t("modelsTitle"),
|
|
717
|
-
children: [
|
|
718
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
719
|
-
className: QoderCredentialCard_module_css_default.modelCatalogHead,
|
|
720
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", {
|
|
721
|
-
className: QoderCredentialCard_module_css_default.modelCatalogTitle,
|
|
722
|
-
children: t("modelsTitle")
|
|
723
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
724
|
-
className: QoderCredentialCard_module_css_default.modelCatalogMeta,
|
|
725
|
-
children: t("modelsEnabled", { count: models.length })
|
|
726
|
-
})] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
727
|
-
type: "button",
|
|
728
|
-
className: QoderCredentialCard_module_css_default.linkButton,
|
|
729
|
-
disabled: disabled || fetching,
|
|
730
|
-
onClick: () => {
|
|
731
|
-
fetchModels();
|
|
732
|
-
},
|
|
733
|
-
children: fetching ? t("modelsFetching") : t("modelsFetch")
|
|
734
|
-
})]
|
|
735
|
-
}),
|
|
736
|
-
failure ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
737
|
-
className: QoderCredentialCard_module_css_default.error,
|
|
738
|
-
role: "alert",
|
|
739
|
-
children: failure
|
|
740
|
-
}) : null,
|
|
741
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
742
|
-
className: QoderCredentialCard_module_css_default.modelList,
|
|
743
|
-
children: displayedModels.map((model) => {
|
|
744
|
-
const unavailable = unavailableIds.has(model.id);
|
|
745
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
746
|
-
className: `${QoderCredentialCard_module_css_default.modelChoice} ${unavailable ? QoderCredentialCard_module_css_default.modelUnavailable : ""}`,
|
|
747
|
-
children: [
|
|
748
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
749
|
-
type: "checkbox",
|
|
750
|
-
checked: !unavailable && selectedIds.has(model.id),
|
|
751
|
-
disabled: disabled || unavailable,
|
|
752
|
-
onChange: (event) => {
|
|
753
|
-
toggleModel(model.id, event.currentTarget.checked);
|
|
754
|
-
}
|
|
755
|
-
}),
|
|
756
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
757
|
-
className: QoderCredentialCard_module_css_default.modelChoiceName,
|
|
758
|
-
children: model.name
|
|
759
|
-
}),
|
|
760
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
761
|
-
className: QoderCredentialCard_module_css_default.modelRate,
|
|
762
|
-
children: model.priceFactor === void 0 ? t("modelRateUnknown") : t("modelRate", { value: model.priceFactor })
|
|
763
|
-
}),
|
|
764
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", { children: model.id }),
|
|
765
|
-
unavailable ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
766
|
-
className: QoderCredentialCard_module_css_default.modelBadge,
|
|
767
|
-
children: t("modelUnavailable")
|
|
768
|
-
}) : null
|
|
769
|
-
]
|
|
770
|
-
}, model.id);
|
|
771
|
-
})
|
|
772
|
-
})
|
|
994
|
+
renderWebSearchSection(),
|
|
995
|
+
renderModelCatalogSection()
|
|
773
996
|
]
|
|
774
997
|
});
|
|
775
998
|
}
|
|
776
999
|
//#endregion
|
|
777
1000
|
//#region src/client/QoderCredentialCard.tsx
|
|
778
|
-
function modelsOf(value, selectedRegion) {
|
|
779
|
-
if (typeof value !== "object" || value === null) return [];
|
|
780
|
-
const section = value;
|
|
781
|
-
const region = selectedRegion ?? (section.region === "china" ? "china" : "global");
|
|
782
|
-
const scoped = section.modelsByRegion?.[region];
|
|
783
|
-
if (Array.isArray(scoped)) return scoped;
|
|
784
|
-
return region === (section.region === "china" ? "china" : "global") && Array.isArray(section.models) ? section.models : defaultModels.map((model) => ({ ...model }));
|
|
785
|
-
}
|
|
786
1001
|
function regionOf(value) {
|
|
787
1002
|
if (typeof value !== "object" || value === null) return "global";
|
|
788
1003
|
return value.region === "china" ? "china" : "global";
|
|
@@ -793,22 +1008,12 @@ window.__ModuleLoader__.load({
|
|
|
793
1008
|
const [draft, setDraft] = (0, react.useState)("");
|
|
794
1009
|
const [regionDraft, setRegionDraft] = (0, react.useState)("global");
|
|
795
1010
|
const [regionDirty, setRegionDirty] = (0, react.useState)(false);
|
|
796
|
-
const [modelDraft, setModelDraft] = (0, react.useState)([]);
|
|
797
|
-
const [modelsDirty, setModelsDirty] = (0, react.useState)(false);
|
|
798
1011
|
const [mutation, setMutation] = (0, react.useState)();
|
|
799
1012
|
const [notice, setNotice] = (0, react.useState)();
|
|
800
1013
|
const modelSnapshot = (0, react.useSyncExternalStore)(operations.subscribeModels, operations.getModelSnapshot, operations.getModelSnapshot);
|
|
801
1014
|
(0, react.useEffect)(() => {
|
|
802
|
-
if (modelSnapshot.status === "ready")
|
|
803
|
-
|
|
804
|
-
if (!regionDirty) setRegionDraft(regionOf(modelSnapshot.value));
|
|
805
|
-
}
|
|
806
|
-
}, [
|
|
807
|
-
modelSnapshot,
|
|
808
|
-
modelsDirty,
|
|
809
|
-
regionDirty,
|
|
810
|
-
regionDraft
|
|
811
|
-
]);
|
|
1015
|
+
if (modelSnapshot.status === "ready" && !regionDirty) setRegionDraft(regionOf(modelSnapshot.value));
|
|
1016
|
+
}, [modelSnapshot, regionDirty]);
|
|
812
1017
|
const load = (0, react.useCallback)(async () => {
|
|
813
1018
|
const info = await operations.describe();
|
|
814
1019
|
setState(info === void 0 ? { status: "failed" } : {
|
|
@@ -845,20 +1050,17 @@ window.__ModuleLoader__.load({
|
|
|
845
1050
|
const writable = state.info.writable;
|
|
846
1051
|
const busy = mutation !== void 0;
|
|
847
1052
|
const normalized = draft.trim();
|
|
848
|
-
const
|
|
849
|
-
const modelWritable = modelSnapshot.status === "ready" && modelSnapshot.writable;
|
|
1053
|
+
const canModifyRegion = modelSnapshot.status === "ready" && modelSnapshot.writable;
|
|
850
1054
|
const currentRegion = regionOf(modelSnapshot.value);
|
|
851
1055
|
const closeEditor = () => {
|
|
852
1056
|
setDraft("");
|
|
853
|
-
setModelDraft(modelsOf(modelSnapshot.value, regionOf(modelSnapshot.value)));
|
|
854
1057
|
setRegionDraft(regionOf(modelSnapshot.value));
|
|
855
|
-
setModelsDirty(false);
|
|
856
1058
|
setRegionDirty(false);
|
|
857
1059
|
setNotice(void 0);
|
|
858
1060
|
setEditing(false);
|
|
859
1061
|
};
|
|
860
1062
|
const save = async () => {
|
|
861
|
-
if (busy || !
|
|
1063
|
+
if (busy || !regionDirty && normalized.length === 0 || regionDirty && !canModifyRegion) return;
|
|
862
1064
|
setMutation("saving");
|
|
863
1065
|
setNotice(void 0);
|
|
864
1066
|
if (regionDirty) {
|
|
@@ -869,14 +1071,6 @@ window.__ModuleLoader__.load({
|
|
|
869
1071
|
}
|
|
870
1072
|
setRegionDirty(false);
|
|
871
1073
|
}
|
|
872
|
-
if (modelsDirty) {
|
|
873
|
-
if (!await operations.storeModels(regionDraft, modelDraft)) {
|
|
874
|
-
setNotice("saveFailed");
|
|
875
|
-
setMutation(void 0);
|
|
876
|
-
return;
|
|
877
|
-
}
|
|
878
|
-
setModelsDirty(false);
|
|
879
|
-
}
|
|
880
1074
|
if (normalized.length === 0 || await operations.store(normalized)) {
|
|
881
1075
|
setDraft("");
|
|
882
1076
|
setNotice("saved");
|
|
@@ -957,11 +1151,9 @@ window.__ModuleLoader__.load({
|
|
|
957
1151
|
role: "radio",
|
|
958
1152
|
"aria-checked": regionDraft === "global",
|
|
959
1153
|
className: `${QoderCredentialCard_module_css_default.regionOption} ${regionDraft === "global" ? QoderCredentialCard_module_css_default.regionOptionActive : ""}`,
|
|
960
|
-
disabled: !
|
|
1154
|
+
disabled: !canModifyRegion || busy,
|
|
961
1155
|
onClick: () => {
|
|
962
1156
|
setRegionDraft("global");
|
|
963
|
-
setModelDraft(modelsOf(modelSnapshot.value, "global"));
|
|
964
|
-
setModelsDirty(false);
|
|
965
1157
|
setRegionDirty(true);
|
|
966
1158
|
},
|
|
967
1159
|
children: t("regionGlobal")
|
|
@@ -970,11 +1162,9 @@ window.__ModuleLoader__.load({
|
|
|
970
1162
|
role: "radio",
|
|
971
1163
|
"aria-checked": regionDraft === "china",
|
|
972
1164
|
className: `${QoderCredentialCard_module_css_default.regionOption} ${regionDraft === "china" ? QoderCredentialCard_module_css_default.regionOptionActive : ""}`,
|
|
973
|
-
disabled: !
|
|
1165
|
+
disabled: !canModifyRegion || busy,
|
|
974
1166
|
onClick: () => {
|
|
975
1167
|
setRegionDraft("china");
|
|
976
|
-
setModelDraft(modelsOf(modelSnapshot.value, "china"));
|
|
977
|
-
setModelsDirty(false);
|
|
978
1168
|
setRegionDirty(true);
|
|
979
1169
|
},
|
|
980
1170
|
children: t("regionChina")
|
|
@@ -1001,34 +1191,6 @@ window.__ModuleLoader__.load({
|
|
|
1001
1191
|
role: "alert",
|
|
1002
1192
|
children: t("readOnly")
|
|
1003
1193
|
}) : null,
|
|
1004
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
|
|
1005
|
-
className: QoderCredentialCard_module_css_default.customized,
|
|
1006
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("summary", {
|
|
1007
|
-
className: QoderCredentialCard_module_css_default.customizedSummary,
|
|
1008
|
-
children: t("customized")
|
|
1009
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1010
|
-
className: QoderCredentialCard_module_css_default.customizedBody,
|
|
1011
|
-
children: [modelSnapshot.status === "loading" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1012
|
-
className: QoderCredentialCard_module_css_default.hint,
|
|
1013
|
-
children: t("modelsLoading")
|
|
1014
|
-
}) : modelSnapshot.status === "unavailable" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1015
|
-
className: QoderCredentialCard_module_css_default.error,
|
|
1016
|
-
children: t("modelsUnavailable")
|
|
1017
|
-
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(QoderModelCatalog, {
|
|
1018
|
-
operations,
|
|
1019
|
-
models: modelDraft,
|
|
1020
|
-
disabled: !modelWritable || busy,
|
|
1021
|
-
t,
|
|
1022
|
-
onChange: (models) => {
|
|
1023
|
-
setModelDraft(models);
|
|
1024
|
-
setModelsDirty(true);
|
|
1025
|
-
}
|
|
1026
|
-
}), modelSnapshot.status === "ready" && modelFailure !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1027
|
-
className: QoderCredentialCard_module_css_default.error,
|
|
1028
|
-
children: t(modelFailure)
|
|
1029
|
-
}) : null]
|
|
1030
|
-
})]
|
|
1031
|
-
}),
|
|
1032
1194
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1033
1195
|
className: QoderCredentialCard_module_css_default.actions,
|
|
1034
1196
|
children: [
|
|
@@ -1051,7 +1213,7 @@ window.__ModuleLoader__.load({
|
|
|
1051
1213
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1052
1214
|
type: "button",
|
|
1053
1215
|
className: QoderCredentialCard_module_css_default.primary,
|
|
1054
|
-
disabled: busy || !
|
|
1216
|
+
disabled: busy || !regionDirty && normalized.length === 0 || regionDirty && !canModifyRegion || normalized.length > 0 && !writable,
|
|
1055
1217
|
onClick: () => {
|
|
1056
1218
|
save();
|
|
1057
1219
|
},
|
|
@@ -1064,6 +1226,250 @@ window.__ModuleLoader__.load({
|
|
|
1064
1226
|
]
|
|
1065
1227
|
});
|
|
1066
1228
|
}
|
|
1229
|
+
//#endregion
|
|
1230
|
+
//#region src/dsh/provider.ts
|
|
1231
|
+
/** DSH model provider route, matching the plugin package name. */
|
|
1232
|
+
const QODER_PROVIDER_ID = "dsh-provider-qoder";
|
|
1233
|
+
//#endregion
|
|
1234
|
+
//#region src/client/context-selection.ts
|
|
1235
|
+
function isQoderProvider(provider) {
|
|
1236
|
+
return [
|
|
1237
|
+
QODER_PROVIDER_ID,
|
|
1238
|
+
"qoder-official",
|
|
1239
|
+
"qoder",
|
|
1240
|
+
"qoder-subscription"
|
|
1241
|
+
].includes(provider ?? "");
|
|
1242
|
+
}
|
|
1243
|
+
function modelsOf(section, region, _legacyRegion) {
|
|
1244
|
+
const scoped = section?.modelsByRegion?.[region];
|
|
1245
|
+
if (scoped !== void 0) return scoped;
|
|
1246
|
+
return defaultModels.map((model) => ({ ...model }));
|
|
1247
|
+
}
|
|
1248
|
+
function historicalContextWindow(current, lastUsed, contextWindow) {
|
|
1249
|
+
return current.provider === lastUsed?.provider && current.model === lastUsed?.model ? contextWindow : void 0;
|
|
1250
|
+
}
|
|
1251
|
+
/** A failed session write must not change defaults; a failed default write is a partial success. */
|
|
1252
|
+
async function saveContextSelection(operations, sessionId, region, modelId, tierKey, legacyRegion) {
|
|
1253
|
+
try {
|
|
1254
|
+
if (!await operations.setSessionTier?.(sessionId, modelId, tierKey, region)) return "session-failed";
|
|
1255
|
+
} catch {
|
|
1256
|
+
return "session-failed";
|
|
1257
|
+
}
|
|
1258
|
+
try {
|
|
1259
|
+
const models = modelsOf(operations.getModelSnapshot().value, region, legacyRegion);
|
|
1260
|
+
const model = models.find((candidate) => candidate.id === modelId);
|
|
1261
|
+
const tier = model && contextTiersOf(model).find((candidate) => candidate.key === tierKey);
|
|
1262
|
+
if (!tier) return "default-failed";
|
|
1263
|
+
const updated = models.map((candidate) => candidate.id === modelId ? {
|
|
1264
|
+
...candidate,
|
|
1265
|
+
contextTier: tierKey,
|
|
1266
|
+
contextWindow: tier.tokenCount
|
|
1267
|
+
} : candidate);
|
|
1268
|
+
return await operations.storeModels(region, updated) ? "saved" : "default-failed";
|
|
1269
|
+
} catch {
|
|
1270
|
+
return "default-failed";
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
//#endregion
|
|
1274
|
+
//#region \0dsh-css:/home/runner/work/dsh-provider-qoder/dsh-provider-qoder/src/client/QoderContextSelect.module.css.mjs
|
|
1275
|
+
const css = ".hiDrJa_root{align-items:center;display:inline-flex;position:relative}.hiDrJa_trigger{height:28px;color:var(--dsw-alias-label-secondary);cursor:pointer;user-select:none;background:0 0;border:none;border-radius:24px;outline:none;align-items:center;gap:4px;padding:0 8px;font-size:13px;font-weight:500;line-height:20px;transition:background .12s,color .12s;display:flex}.hiDrJa_trigger:hover,.hiDrJa_triggerActive{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.hiDrJa_trigger:focus-visible{box-shadow:0 0 0 2px var(--dsw-alias-border-l3)}.hiDrJa_icon{color:var(--dsw-alias-label-caption);justify-content:center;align-items:center;display:inline-flex}.hiDrJa_label{white-space:nowrap}.hiDrJa_chevron{color:var(--dsw-alias-label-caption);align-items:center;transition:transform .12s;display:inline-flex}.hiDrJa_chevronOpen{transform:rotate(180deg)}.hiDrJa_menu{z-index:1100;background:var(--dsw-specific-menu);border:1px solid var(--dsw-alias-border-l1);min-width:180px;box-shadow:var(--dsw-elevation-prominent);color:var(--dsw-alias-label-primary);border-radius:14px;flex-direction:column;padding:4px;animation:.12s hiDrJa_fadeIn;display:flex;position:absolute;bottom:calc(100% + 8px);right:0}@keyframes hiDrJa_fadeIn{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}.hiDrJa_menuHeader{text-transform:uppercase;letter-spacing:.5px;color:var(--dsw-alias-label-tertiary);border-bottom:1px solid var(--dsw-alias-border-l1);margin-bottom:4px;padding:6px 10px 4px;font-size:11px;font-weight:600}.hiDrJa_option{box-sizing:border-box;width:100%;color:inherit;cursor:pointer;text-align:left;background:0 0;border:none;border-radius:8px;justify-content:space-between;align-items:center;gap:8px;padding:6px 10px;font-size:13px;line-height:20px;transition:background .1s;display:flex}.hiDrJa_option:hover{background:var(--dsw-alias-interactive-bg-hover)}.hiDrJa_optionSelected{color:var(--dsw-alias-state-brand);font-weight:600}.hiDrJa_optionInfo{align-items:center;gap:6px;display:flex}.hiDrJa_tag{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-caption);border-radius:4px;padding:1px 5px;font-size:11px;font-weight:500}.hiDrJa_check{color:var(--dsw-alias-state-brand);align-items:center;font-size:12px;display:inline-flex}.hiDrJa_error{color:var(--dsw-alias-label-primary);max-width:240px;font-size:12px}";
|
|
1276
|
+
const tagId = "dsh-provider-qoder/QoderContextSelect.module.css";
|
|
1277
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
1278
|
+
const tag = document.createElement("style");
|
|
1279
|
+
tag.dataset.plugin = "dsh-provider-qoder";
|
|
1280
|
+
tag.dataset.pluginCss = tagId;
|
|
1281
|
+
tag.textContent = css;
|
|
1282
|
+
document.head.appendChild(tag);
|
|
1283
|
+
}
|
|
1284
|
+
var QoderContextSelect_module_css_default = {
|
|
1285
|
+
"check": "hiDrJa_check",
|
|
1286
|
+
"chevron": "hiDrJa_chevron",
|
|
1287
|
+
"chevronOpen": "hiDrJa_chevronOpen",
|
|
1288
|
+
"error": "hiDrJa_error",
|
|
1289
|
+
"fadeIn": "hiDrJa_fadeIn",
|
|
1290
|
+
"icon": "hiDrJa_icon",
|
|
1291
|
+
"label": "hiDrJa_label",
|
|
1292
|
+
"menu": "hiDrJa_menu",
|
|
1293
|
+
"menuHeader": "hiDrJa_menuHeader",
|
|
1294
|
+
"option": "hiDrJa_option",
|
|
1295
|
+
"optionInfo": "hiDrJa_optionInfo",
|
|
1296
|
+
"optionSelected": "hiDrJa_optionSelected",
|
|
1297
|
+
"root": "hiDrJa_root",
|
|
1298
|
+
"tag": "hiDrJa_tag",
|
|
1299
|
+
"trigger": "hiDrJa_trigger",
|
|
1300
|
+
"triggerActive": "hiDrJa_triggerActive"
|
|
1301
|
+
};
|
|
1302
|
+
//#endregion
|
|
1303
|
+
//#region src/client/QoderContextSelect.tsx
|
|
1304
|
+
function QoderContextSelect(props) {
|
|
1305
|
+
const { directory, operations, t, sessionId, useProjection } = props;
|
|
1306
|
+
const [open, setOpen] = (0, react.useState)(false);
|
|
1307
|
+
const [manualTiers, setManualTiers] = (0, react.useState)({});
|
|
1308
|
+
const [pending, setPending] = (0, react.useState)(false);
|
|
1309
|
+
const [error, setError] = (0, react.useState)(null);
|
|
1310
|
+
const saving = (0, react.useRef)(false);
|
|
1311
|
+
const legacyRegion = (0, react.useRef)(void 0);
|
|
1312
|
+
const rootRef = (0, react.useRef)(null);
|
|
1313
|
+
const directoryState = (0, react.useSyncExternalStore)((fn) => directory ? directory.subscribe(fn) : () => () => {}, () => directory ? directory.getSnapshot() : null);
|
|
1314
|
+
const modelSnapshot = (0, react.useSyncExternalStore)((fn) => operations ? operations.subscribeModels(fn) : () => () => {}, () => operations ? operations.getModelSnapshot() : null);
|
|
1315
|
+
(0, react.useEffect)(() => {
|
|
1316
|
+
if (!open) return;
|
|
1317
|
+
const handleClickOutside = (e) => {
|
|
1318
|
+
if (rootRef.current && !rootRef.current.contains(e.target)) setOpen(false);
|
|
1319
|
+
};
|
|
1320
|
+
const handleKeyDown = (e) => {
|
|
1321
|
+
if (e.key === "Escape") setOpen(false);
|
|
1322
|
+
};
|
|
1323
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
1324
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
1325
|
+
return () => {
|
|
1326
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
1327
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
1328
|
+
};
|
|
1329
|
+
}, [open]);
|
|
1330
|
+
const modelProj = useProjection ? useProjection("modelSelection") : void 0;
|
|
1331
|
+
const pressure = useProjection ? useProjection("contextPressure") : void 0;
|
|
1332
|
+
if (!operations) return null;
|
|
1333
|
+
const projectedCurrent = modelProj?.next ?? modelProj?.lastUsed;
|
|
1334
|
+
const current = directoryState?.current ?? (projectedCurrent?.model ? {
|
|
1335
|
+
provider: projectedCurrent.provider ?? "dsh-provider-qoder",
|
|
1336
|
+
model: projectedCurrent.model
|
|
1337
|
+
} : null);
|
|
1338
|
+
if (!current) return null;
|
|
1339
|
+
const region = modelSnapshot?.value?.region === "china" ? "china" : "global";
|
|
1340
|
+
if (legacyRegion.current === void 0 && modelSnapshot?.value) legacyRegion.current = region;
|
|
1341
|
+
const models = modelsOf(modelSnapshot?.value, region, legacyRegion.current ?? region);
|
|
1342
|
+
const currentModelId = current.model.includes("/") ? current.model.split("/")[1] : current.model;
|
|
1343
|
+
const currentProviderId = current.provider ?? (current.model.includes("/") ? current.model.split("/")[0] : void 0);
|
|
1344
|
+
const activeModel = models.find((m) => m.id === currentModelId || m.id === current.model);
|
|
1345
|
+
if (!isQoderProvider(currentProviderId) || !activeModel) return null;
|
|
1346
|
+
const tiers = contextTiersOf(activeModel);
|
|
1347
|
+
if (tiers.length <= 1) return null;
|
|
1348
|
+
const sessionKey = sessionId ? JSON.stringify([
|
|
1349
|
+
region,
|
|
1350
|
+
sessionId,
|
|
1351
|
+
activeModel.id
|
|
1352
|
+
]) : void 0;
|
|
1353
|
+
const historicalWindow = operations.canRestoreContextHistory?.() === false ? void 0 : historicalContextWindow(current, modelProj?.lastUsed, pressure?.contextWindow);
|
|
1354
|
+
const currentTier = resolveContextTier(activeModel, sessionKey ? manualTiers[sessionKey] : void 0, historicalWindow);
|
|
1355
|
+
if (!currentTier) return null;
|
|
1356
|
+
const selectedTierKey = currentTier.key;
|
|
1357
|
+
const selectTier = async (tierKey) => {
|
|
1358
|
+
setOpen(false);
|
|
1359
|
+
if (!sessionId || !sessionKey || saving.current) return;
|
|
1360
|
+
if (tierKey === selectedTierKey && error?.key !== sessionKey) return;
|
|
1361
|
+
saving.current = true;
|
|
1362
|
+
setPending(true);
|
|
1363
|
+
setError(null);
|
|
1364
|
+
try {
|
|
1365
|
+
const result = await saveContextSelection(operations, sessionId, region, activeModel.id, tierKey, legacyRegion.current ?? region);
|
|
1366
|
+
if (result !== "session-failed") setManualTiers((prev) => ({
|
|
1367
|
+
...prev,
|
|
1368
|
+
[sessionKey]: tierKey
|
|
1369
|
+
}));
|
|
1370
|
+
if (result !== "saved") setError({
|
|
1371
|
+
key: sessionKey,
|
|
1372
|
+
message: result === "session-failed" ? "contextSelectFailed" : "contextDefaultFailed"
|
|
1373
|
+
});
|
|
1374
|
+
} finally {
|
|
1375
|
+
saving.current = false;
|
|
1376
|
+
setPending(false);
|
|
1377
|
+
}
|
|
1378
|
+
};
|
|
1379
|
+
const defaultSuffix = t ? t("contextTierDefaultSuffix").replace(/[()()]/g, "") : "默认";
|
|
1380
|
+
const selectTitle = t ? t("contextSelectTitle") : "选择上下文大小";
|
|
1381
|
+
const menuHeader = t ? t("contextSelectMenuHeader") : "上下文容量";
|
|
1382
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1383
|
+
className: QoderContextSelect_module_css_default.root,
|
|
1384
|
+
ref: rootRef,
|
|
1385
|
+
children: [
|
|
1386
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
1387
|
+
type: "button",
|
|
1388
|
+
className: `${QoderContextSelect_module_css_default.trigger} ${open ? QoderContextSelect_module_css_default.triggerActive : ""}`,
|
|
1389
|
+
disabled: pending || !sessionId,
|
|
1390
|
+
"aria-expanded": open,
|
|
1391
|
+
"aria-label": selectTitle,
|
|
1392
|
+
title: `${selectTitle}: ${formatContextTokens(currentTier.tokenCount)}`,
|
|
1393
|
+
onClick: () => setOpen((prev) => !prev),
|
|
1394
|
+
children: [
|
|
1395
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1396
|
+
className: QoderContextSelect_module_css_default.icon,
|
|
1397
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
1398
|
+
width: "14",
|
|
1399
|
+
height: "14",
|
|
1400
|
+
viewBox: "0 0 16 16",
|
|
1401
|
+
fill: "currentColor",
|
|
1402
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M2 4.5A2.5 2.5 0 0 1 4.5 2h7A2.5 2.5 0 0 1 14 4.5v7a2.5 2.5 0 0 1-2.5 2.5h-7A2.5 2.5 0 0 1 2 11.5v-7zm2.5-1A1.5 1.5 0 0 0 3 4.5v7A1.5 1.5 0 0 0 4.5 13h7a1.5 1.5 0 0 0 1.5-1.5v-7A1.5 1.5 0 0 0 11.5 3.5h-7zM5 6h6v1H5V6zm0 3h4v1H5V9z" })
|
|
1403
|
+
})
|
|
1404
|
+
}),
|
|
1405
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1406
|
+
className: QoderContextSelect_module_css_default.label,
|
|
1407
|
+
children: formatContextTokens(currentTier.tokenCount)
|
|
1408
|
+
}),
|
|
1409
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1410
|
+
className: `${QoderContextSelect_module_css_default.chevron} ${open ? QoderContextSelect_module_css_default.chevronOpen : ""}`,
|
|
1411
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
1412
|
+
width: "10",
|
|
1413
|
+
height: "10",
|
|
1414
|
+
viewBox: "0 0 12 12",
|
|
1415
|
+
fill: "none",
|
|
1416
|
+
stroke: "currentColor",
|
|
1417
|
+
strokeWidth: "1.5",
|
|
1418
|
+
strokeLinecap: "round",
|
|
1419
|
+
strokeLinejoin: "round",
|
|
1420
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M3 4.5L6 7.5L9 4.5" })
|
|
1421
|
+
})
|
|
1422
|
+
})
|
|
1423
|
+
]
|
|
1424
|
+
}),
|
|
1425
|
+
error && error.key === sessionKey && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1426
|
+
role: "alert",
|
|
1427
|
+
className: QoderContextSelect_module_css_default.error,
|
|
1428
|
+
children: t ? t(error.message) : error.message
|
|
1429
|
+
}),
|
|
1430
|
+
open && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1431
|
+
className: QoderContextSelect_module_css_default.menu,
|
|
1432
|
+
role: "menu",
|
|
1433
|
+
"aria-label": selectTitle,
|
|
1434
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1435
|
+
className: QoderContextSelect_module_css_default.menuHeader,
|
|
1436
|
+
children: menuHeader
|
|
1437
|
+
}), tiers.map((tier) => {
|
|
1438
|
+
const isSelected = tier.key === selectedTierKey;
|
|
1439
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
1440
|
+
type: "button",
|
|
1441
|
+
role: "menuitemradio",
|
|
1442
|
+
"aria-checked": isSelected,
|
|
1443
|
+
className: `${QoderContextSelect_module_css_default.option} ${isSelected ? QoderContextSelect_module_css_default.optionSelected : ""}`,
|
|
1444
|
+
onClick: () => {
|
|
1445
|
+
selectTier(tier.key);
|
|
1446
|
+
},
|
|
1447
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1448
|
+
className: QoderContextSelect_module_css_default.optionInfo,
|
|
1449
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: formatContextTokens(tier.tokenCount) }), tier.isDefault && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1450
|
+
className: QoderContextSelect_module_css_default.tag,
|
|
1451
|
+
children: defaultSuffix
|
|
1452
|
+
})]
|
|
1453
|
+
}), isSelected && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1454
|
+
className: QoderContextSelect_module_css_default.check,
|
|
1455
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
1456
|
+
width: "14",
|
|
1457
|
+
height: "14",
|
|
1458
|
+
viewBox: "0 0 16 16",
|
|
1459
|
+
fill: "none",
|
|
1460
|
+
stroke: "currentColor",
|
|
1461
|
+
strokeWidth: "2",
|
|
1462
|
+
strokeLinecap: "round",
|
|
1463
|
+
strokeLinejoin: "round",
|
|
1464
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M3.5 8.5L6.5 11.5L12.5 4.5" })
|
|
1465
|
+
})
|
|
1466
|
+
})]
|
|
1467
|
+
}, tier.key);
|
|
1468
|
+
})]
|
|
1469
|
+
})
|
|
1470
|
+
]
|
|
1471
|
+
});
|
|
1472
|
+
}
|
|
1067
1473
|
/**
|
|
1068
1474
|
* Absolute Fetch-route prefix. Connection mounts its shared, authenticated API
|
|
1069
1475
|
* channel at `/api`, and every exact Fetch route lives directly below it.
|
|
@@ -1166,24 +1572,15 @@ window.__ModuleLoader__.load({
|
|
|
1166
1572
|
"slots",
|
|
1167
1573
|
"locale",
|
|
1168
1574
|
"remote",
|
|
1169
|
-
"remote.credentials"
|
|
1575
|
+
"remote.credentials",
|
|
1576
|
+
"configForms"
|
|
1170
1577
|
];
|
|
1171
1578
|
const fill = (text, values) => {
|
|
1172
1579
|
if (!values) return text;
|
|
1173
1580
|
return Object.entries(values).reduce((next, [key, value]) => next.replace(new RegExp(`\\{${key}\\}`, "g"), String(value)), text);
|
|
1174
1581
|
};
|
|
1175
1582
|
function apply(ctx) {
|
|
1176
|
-
|
|
1177
|
-
if (configForms) {
|
|
1178
|
-
mount(ctx, configForms.get(settingsNamespace));
|
|
1179
|
-
return;
|
|
1180
|
-
}
|
|
1181
|
-
const settingsScope = ctx.get?.("settingsScope");
|
|
1182
|
-
if (settingsScope) {
|
|
1183
|
-
mount(ctx, settingsScope.bind({ namespace: settingsNamespace }));
|
|
1184
|
-
return;
|
|
1185
|
-
}
|
|
1186
|
-
console.warn("[provider-qoder] Neither configForms nor settingsScope available; settings panel will not mount");
|
|
1583
|
+
mount(ctx, ctx.configForms.get(settingsNamespace));
|
|
1187
1584
|
}
|
|
1188
1585
|
function mount(ctx, modelScope) {
|
|
1189
1586
|
ctx.effect(() => ctx.locale.register(localeNamespace, {
|
|
@@ -1192,6 +1589,21 @@ window.__ModuleLoader__.load({
|
|
|
1192
1589
|
}), "provider-qoder: credential copy");
|
|
1193
1590
|
const credentials = ctx.remote.credentials;
|
|
1194
1591
|
const rpc = createQoderRpcCaller();
|
|
1592
|
+
let historyRegion;
|
|
1593
|
+
let historyRegionChanged = false;
|
|
1594
|
+
const readModelSnapshot = () => {
|
|
1595
|
+
const snapshot = modelScope.getSnapshot();
|
|
1596
|
+
if (snapshot.value) {
|
|
1597
|
+
const region = snapshot.value.region ?? "global";
|
|
1598
|
+
if (historyRegion !== void 0 && historyRegion !== region) historyRegionChanged = true;
|
|
1599
|
+
historyRegion = region;
|
|
1600
|
+
}
|
|
1601
|
+
return snapshot;
|
|
1602
|
+
};
|
|
1603
|
+
readModelSnapshot();
|
|
1604
|
+
ctx.effect(() => modelScope.subscribe(() => {
|
|
1605
|
+
readModelSnapshot();
|
|
1606
|
+
}), "provider-qoder: context history region");
|
|
1195
1607
|
const operations = {
|
|
1196
1608
|
describe: async () => {
|
|
1197
1609
|
try {
|
|
@@ -1216,14 +1628,19 @@ window.__ModuleLoader__.load({
|
|
|
1216
1628
|
}
|
|
1217
1629
|
},
|
|
1218
1630
|
getAccount: async (force) => await rpc.call("account", { force }),
|
|
1219
|
-
getModelSnapshot:
|
|
1631
|
+
getModelSnapshot: readModelSnapshot,
|
|
1632
|
+
canRestoreContextHistory: () => !historyRegionChanged,
|
|
1220
1633
|
subscribeModels: (listener) => modelScope.subscribe(listener),
|
|
1221
1634
|
storeModels: async (region, models) => {
|
|
1222
1635
|
try {
|
|
1223
1636
|
const current = modelScope.getSnapshot().value;
|
|
1637
|
+
const clonedModels = models.map((m) => ({
|
|
1638
|
+
...m,
|
|
1639
|
+
...m.contextOptions !== void 0 ? { contextOptions: { ...m.contextOptions } } : {}
|
|
1640
|
+
}));
|
|
1224
1641
|
return await modelScope.set("modelsByRegion", {
|
|
1225
1642
|
...current?.modelsByRegion,
|
|
1226
|
-
[region]:
|
|
1643
|
+
[region]: clonedModels
|
|
1227
1644
|
}) !== false;
|
|
1228
1645
|
} catch {
|
|
1229
1646
|
return false;
|
|
@@ -1244,6 +1661,18 @@ window.__ModuleLoader__.load({
|
|
|
1244
1661
|
}
|
|
1245
1662
|
},
|
|
1246
1663
|
discoverModels: async () => await rpc.call("models", {}),
|
|
1664
|
+
setSessionTier: async (sessionId, modelId, tierKey, region) => {
|
|
1665
|
+
try {
|
|
1666
|
+
return (await rpc.call("sessionTier", {
|
|
1667
|
+
sessionId,
|
|
1668
|
+
modelId,
|
|
1669
|
+
tierKey,
|
|
1670
|
+
region
|
|
1671
|
+
})).ok;
|
|
1672
|
+
} catch {
|
|
1673
|
+
return false;
|
|
1674
|
+
}
|
|
1675
|
+
},
|
|
1247
1676
|
subscribe: (listener) => ctx.remote.$on("credentials/reference-updated", (ref) => {
|
|
1248
1677
|
if (ref === "QODER_MANAGED_CREDENTIAL") listener();
|
|
1249
1678
|
})
|
|
@@ -1280,6 +1709,25 @@ window.__ModuleLoader__.load({
|
|
|
1280
1709
|
activeLocale
|
|
1281
1710
|
})
|
|
1282
1711
|
}, QoderCredentialCard));
|
|
1712
|
+
ctx.slots.inject("conversation.input.right", () => ctx.slots.register({
|
|
1713
|
+
name: "conversation.input.right",
|
|
1714
|
+
id: "qoder-context-select",
|
|
1715
|
+
order: 10,
|
|
1716
|
+
inject: (sessionId) => {
|
|
1717
|
+
let directory = void 0;
|
|
1718
|
+
try {
|
|
1719
|
+
const modelDirectories = ctx.get("modelDirectories");
|
|
1720
|
+
directory = sessionId && modelDirectories ? modelDirectories.directoryFor(sessionId)?.store : void 0;
|
|
1721
|
+
} catch {}
|
|
1722
|
+
return {
|
|
1723
|
+
sessionId,
|
|
1724
|
+
directory,
|
|
1725
|
+
operations,
|
|
1726
|
+
t,
|
|
1727
|
+
activeLocale
|
|
1728
|
+
};
|
|
1729
|
+
}
|
|
1730
|
+
}, QoderContextSelect));
|
|
1283
1731
|
}
|
|
1284
1732
|
//#endregion
|
|
1285
1733
|
exports.apply = apply;
|