dsh-provider-qoder 0.4.0 → 0.4.2
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 +13 -23
- package/README_CN.md +13 -26
- package/lib/client.js +674 -252
- package/lib/index.d.ts +11 -51
- package/lib/index.js +282 -69
- package/package.json +19 -16
package/lib/client.js
CHANGED
|
@@ -14,6 +14,160 @@ 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
|
+
/** Clone a model catalog entry, detaching any contextOptions object. */
|
|
73
|
+
function cloneCatalogModel(model) {
|
|
74
|
+
return {
|
|
75
|
+
...model,
|
|
76
|
+
...model.contextOptions !== void 0 ? { contextOptions: { ...model.contextOptions } } : {}
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/** Carry subscriber context choices only while the refreshed catalog supports them. */
|
|
80
|
+
function mergeAdvertisedContext(remembered, advertised, updated) {
|
|
81
|
+
const merged = { ...updated };
|
|
82
|
+
delete merged.contextOptions;
|
|
83
|
+
delete merged.contextTier;
|
|
84
|
+
if (advertised.contextOptions !== void 0) merged.contextOptions = { ...advertised.contextOptions };
|
|
85
|
+
const tier = selectedContextTier({
|
|
86
|
+
contextTier: remembered.contextTier,
|
|
87
|
+
contextOptions: merged.contextOptions
|
|
88
|
+
});
|
|
89
|
+
if (tier !== void 0) {
|
|
90
|
+
merged.contextTier = tier.key;
|
|
91
|
+
merged.contextWindow = tier.tokenCount;
|
|
92
|
+
} else if (advertised.contextWindow !== void 0) merged.contextWindow = remembered.contextTier !== void 0 ? advertised.contextWindow : Math.min(remembered.contextWindow ?? advertised.contextWindow, advertised.contextWindow);
|
|
93
|
+
return merged;
|
|
94
|
+
}
|
|
95
|
+
const defaultMaxTokens = 32768;
|
|
96
|
+
const defaultModels = [
|
|
97
|
+
{
|
|
98
|
+
id: "cmodel",
|
|
99
|
+
name: "Cantus (Qoder)",
|
|
100
|
+
description: "Default Global Qoder subscription model for quick validation",
|
|
101
|
+
contextWindow: 1e6,
|
|
102
|
+
maxTokens: defaultMaxTokens,
|
|
103
|
+
supportsImages: true
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
id: "auto",
|
|
107
|
+
name: "Qoder Auto",
|
|
108
|
+
description: "Server-routed Global Qoder model pool",
|
|
109
|
+
contextWindow: 18e4,
|
|
110
|
+
maxTokens: defaultMaxTokens,
|
|
111
|
+
supportsImages: true
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
id: "ultimate",
|
|
115
|
+
name: "Qoder Ultimate",
|
|
116
|
+
description: "Highest-capability Global Qoder model pool",
|
|
117
|
+
contextWindow: 1e6,
|
|
118
|
+
maxTokens: defaultMaxTokens,
|
|
119
|
+
supportsImages: true
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
id: "performance",
|
|
123
|
+
name: "Qoder Performance",
|
|
124
|
+
description: "Performance-oriented Global Qoder model pool",
|
|
125
|
+
contextWindow: 1e6,
|
|
126
|
+
maxTokens: defaultMaxTokens,
|
|
127
|
+
supportsImages: true
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
id: "efficient",
|
|
131
|
+
name: "Qoder Efficient",
|
|
132
|
+
description: "Efficiency-oriented Global Qoder model pool",
|
|
133
|
+
contextWindow: 18e4,
|
|
134
|
+
maxTokens: defaultMaxTokens,
|
|
135
|
+
supportsImages: true
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
id: "lite",
|
|
139
|
+
name: "Qoder Lite",
|
|
140
|
+
description: "Basic Global Qoder model pool",
|
|
141
|
+
contextWindow: 18e4,
|
|
142
|
+
maxTokens: defaultMaxTokens
|
|
143
|
+
}
|
|
144
|
+
];
|
|
145
|
+
//#endregion
|
|
146
|
+
//#region src/client/credential-operations.ts
|
|
147
|
+
function regionOf(value) {
|
|
148
|
+
if (typeof value !== "object" || value === null) return "global";
|
|
149
|
+
return value.region === "china" ? "china" : "global";
|
|
150
|
+
}
|
|
151
|
+
function modelsOf(section, region) {
|
|
152
|
+
const scoped = section?.modelsByRegion?.[region];
|
|
153
|
+
return Array.isArray(scoped) ? scoped : defaultModels.map((model) => ({ ...model }));
|
|
154
|
+
}
|
|
155
|
+
function reconcileQoderModels(known, discovered) {
|
|
156
|
+
const availableIds = new Set(discovered.map((model) => model.id));
|
|
157
|
+
const unavailable = known.filter((model) => !availableIds.has(model.id)).map(cloneCatalogModel);
|
|
158
|
+
const previous = new Map(known.map((model) => [model.id, model]));
|
|
159
|
+
const reconciled = discovered.map((model) => {
|
|
160
|
+
const remembered = previous.get(model.id);
|
|
161
|
+
if (remembered === void 0) return cloneCatalogModel(model);
|
|
162
|
+
return mergeAdvertisedContext(remembered, model, model);
|
|
163
|
+
});
|
|
164
|
+
return {
|
|
165
|
+
catalog: [...reconciled, ...unavailable],
|
|
166
|
+
selected: reconciled,
|
|
167
|
+
unavailableIds: new Set(unavailable.map((model) => model.id))
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
//#endregion
|
|
17
171
|
//#region src/client/locales.ts
|
|
18
172
|
const zh = {
|
|
19
173
|
nav: "Qoder",
|
|
@@ -52,7 +206,15 @@ window.__ModuleLoader__.load({
|
|
|
52
206
|
modelsRequired: "至少需要保留一个模型。",
|
|
53
207
|
modelUnavailable: "不可用",
|
|
54
208
|
modelRate: "{value}x",
|
|
209
|
+
modelRateFree: "免费",
|
|
210
|
+
modelRateDiscount: "{value}x(原 {original}x)",
|
|
55
211
|
modelRateUnknown: "倍率未知",
|
|
212
|
+
contextTierLabel: "上下文",
|
|
213
|
+
contextTierDefaultSuffix: "(默认)",
|
|
214
|
+
contextTierHint: "选择该模型使用的上下文档位;更大的档位会同时提升 DSH 的上下文预算并改变 Qoder 请求使用的档位。",
|
|
215
|
+
contextSelectFailed: "上下文切换失败,请重试。",
|
|
216
|
+
contextSelectTitle: "选择上下文大小",
|
|
217
|
+
contextSelectMenuHeader: "上下文容量",
|
|
56
218
|
accountTitle: "Qoder",
|
|
57
219
|
accountLoading: "正在读取账号与额度…",
|
|
58
220
|
accountFailed: "无法读取账号信息与额度。",
|
|
@@ -115,7 +277,15 @@ window.__ModuleLoader__.load({
|
|
|
115
277
|
modelsRequired: "Keep at least one model.",
|
|
116
278
|
modelUnavailable: "Unavailable",
|
|
117
279
|
modelRate: "{value}x",
|
|
280
|
+
modelRateFree: "Free",
|
|
281
|
+
modelRateDiscount: "{value}x (was {original}x)",
|
|
118
282
|
modelRateUnknown: "Rate unknown",
|
|
283
|
+
contextTierLabel: "Context",
|
|
284
|
+
contextTierDefaultSuffix: " (default)",
|
|
285
|
+
contextTierHint: "Select the context tier for this model. A larger tier raises the DSH context budget and changes the tier the Qoder request uses.",
|
|
286
|
+
contextSelectFailed: "Could not change the context window. Please retry.",
|
|
287
|
+
contextSelectTitle: "Select context window size",
|
|
288
|
+
contextSelectMenuHeader: "Context Capacity",
|
|
119
289
|
accountTitle: "Qoder",
|
|
120
290
|
accountLoading: "Reading account and quota…",
|
|
121
291
|
accountFailed: "Could not read account details or quota.",
|
|
@@ -193,13 +363,13 @@ window.__ModuleLoader__.load({
|
|
|
193
363
|
}
|
|
194
364
|
//#endregion
|
|
195
365
|
//#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) {
|
|
366
|
+
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}";
|
|
367
|
+
const tagId$1 = "dsh-provider-qoder/QoderCredentialCard.module.css";
|
|
368
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
|
|
199
369
|
const tag = document.createElement("style");
|
|
200
370
|
tag.dataset.plugin = "dsh-provider-qoder";
|
|
201
|
-
tag.dataset.pluginCss = tagId;
|
|
202
|
-
tag.textContent = css;
|
|
371
|
+
tag.dataset.pluginCss = tagId$1;
|
|
372
|
+
tag.textContent = css$1;
|
|
203
373
|
document.head.appendChild(tag);
|
|
204
374
|
}
|
|
205
375
|
var QoderCredentialCard_module_css_default = {
|
|
@@ -234,12 +404,19 @@ window.__ModuleLoader__.load({
|
|
|
234
404
|
"modelBadge": "SRqrhW_modelBadge",
|
|
235
405
|
"modelCatalog": "SRqrhW_modelCatalog",
|
|
236
406
|
"modelCatalogHead": "SRqrhW_modelCatalogHead",
|
|
407
|
+
"modelCatalogHeadCompact": "SRqrhW_modelCatalogHeadCompact",
|
|
237
408
|
"modelCatalogMeta": "SRqrhW_modelCatalogMeta",
|
|
238
409
|
"modelCatalogTitle": "SRqrhW_modelCatalogTitle",
|
|
239
410
|
"modelChoice": "SRqrhW_modelChoice",
|
|
411
|
+
"modelChoiceHead": "SRqrhW_modelChoiceHead",
|
|
240
412
|
"modelChoiceName": "SRqrhW_modelChoiceName",
|
|
241
413
|
"modelList": "SRqrhW_modelList",
|
|
242
414
|
"modelRate": "SRqrhW_modelRate",
|
|
415
|
+
"modelSummaryBadge": "SRqrhW_modelSummaryBadge",
|
|
416
|
+
"modelTier": "SRqrhW_modelTier",
|
|
417
|
+
"modelTierHint": "SRqrhW_modelTierHint",
|
|
418
|
+
"modelTierLabel": "SRqrhW_modelTierLabel",
|
|
419
|
+
"modelTierSelect": "SRqrhW_modelTierSelect",
|
|
243
420
|
"modelUnavailable": "SRqrhW_modelUnavailable",
|
|
244
421
|
"orgTag": "SRqrhW_orgTag",
|
|
245
422
|
"planBadge": "SRqrhW_planBadge",
|
|
@@ -271,6 +448,159 @@ window.__ModuleLoader__.load({
|
|
|
271
448
|
"userNameRow": "SRqrhW_userNameRow"
|
|
272
449
|
};
|
|
273
450
|
//#endregion
|
|
451
|
+
//#region src/client/QoderModelCatalog.tsx
|
|
452
|
+
function validateModelCatalog(models) {
|
|
453
|
+
return models.length === 0 ? "modelsRequired" : void 0;
|
|
454
|
+
}
|
|
455
|
+
function QoderModelCatalog(props) {
|
|
456
|
+
const { operations, models, disabled, fetchDisabled, hideTitle, onChange, t } = props;
|
|
457
|
+
const [fetching, setFetching] = (0, react.useState)(false);
|
|
458
|
+
const [failure, setFailure] = (0, react.useState)();
|
|
459
|
+
const [catalog, setCatalog] = (0, react.useState)();
|
|
460
|
+
const [unavailableIds, setUnavailableIds] = (0, react.useState)(/* @__PURE__ */ new Set());
|
|
461
|
+
const displayedModels = catalog ?? models;
|
|
462
|
+
const selectedIds = (0, react.useMemo)(() => new Set(models.map((model) => model.id)), [models]);
|
|
463
|
+
const fetchModels = async () => {
|
|
464
|
+
setFetching(true);
|
|
465
|
+
setFailure(void 0);
|
|
466
|
+
const result = await operations.discoverModels();
|
|
467
|
+
setFetching(false);
|
|
468
|
+
if (!result.ok) {
|
|
469
|
+
setFailure(result.error.message || t("modelsFetchFailed"));
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
472
|
+
const reconciled = reconcileQoderModels(catalog ?? models, result.value);
|
|
473
|
+
setCatalog(reconciled.catalog);
|
|
474
|
+
setUnavailableIds(reconciled.unavailableIds);
|
|
475
|
+
onChange(reconciled.selected);
|
|
476
|
+
};
|
|
477
|
+
const toggleModel = (id, enabled) => {
|
|
478
|
+
if (unavailableIds.has(id)) return;
|
|
479
|
+
const source = catalog ?? models;
|
|
480
|
+
if (catalog === void 0) setCatalog(source);
|
|
481
|
+
const nextSelected = new Set(selectedIds);
|
|
482
|
+
if (enabled) nextSelected.add(id);
|
|
483
|
+
else nextSelected.delete(id);
|
|
484
|
+
onChange(source.filter((model) => nextSelected.has(model.id) && !unavailableIds.has(model.id)));
|
|
485
|
+
};
|
|
486
|
+
const changeContextTier = (id, tierKey) => {
|
|
487
|
+
const source = catalog ?? models;
|
|
488
|
+
if (catalog === void 0) setCatalog(source);
|
|
489
|
+
const apply = (model) => {
|
|
490
|
+
if (model.id !== id) return model;
|
|
491
|
+
const tokenCount = model.contextOptions?.[tierKey]?.tokenCount;
|
|
492
|
+
if (typeof tokenCount !== "number" || !Number.isFinite(tokenCount) || tokenCount <= 0) return model;
|
|
493
|
+
return {
|
|
494
|
+
...model,
|
|
495
|
+
contextTier: tierKey,
|
|
496
|
+
contextWindow: tokenCount
|
|
497
|
+
};
|
|
498
|
+
};
|
|
499
|
+
const nextCatalog = source.map(apply);
|
|
500
|
+
setCatalog(nextCatalog);
|
|
501
|
+
onChange(models.map(apply));
|
|
502
|
+
};
|
|
503
|
+
const renderRate = (model) => {
|
|
504
|
+
if (model.isFree || model.priceFactor === 0) return t("modelRateFree");
|
|
505
|
+
if (model.priceFactor === void 0) return t("modelRateUnknown");
|
|
506
|
+
const current = formatRateFactor(model.priceFactor);
|
|
507
|
+
if (model.originalPriceFactor !== void 0 && model.originalPriceFactor > model.priceFactor) return t("modelRateDiscount", {
|
|
508
|
+
value: current,
|
|
509
|
+
original: formatRateFactor(model.originalPriceFactor)
|
|
510
|
+
});
|
|
511
|
+
return t("modelRate", { value: current });
|
|
512
|
+
};
|
|
513
|
+
const tieredModels = displayedModels.filter((model) => contextTiersOf(model).length > 1);
|
|
514
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
515
|
+
className: QoderCredentialCard_module_css_default.modelCatalog,
|
|
516
|
+
"aria-label": t("modelsTitle"),
|
|
517
|
+
children: [
|
|
518
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
519
|
+
className: hideTitle ? QoderCredentialCard_module_css_default.modelCatalogHeadCompact : QoderCredentialCard_module_css_default.modelCatalogHead,
|
|
520
|
+
children: [!hideTitle ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", {
|
|
521
|
+
className: QoderCredentialCard_module_css_default.modelCatalogTitle,
|
|
522
|
+
children: t("modelsTitle")
|
|
523
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
524
|
+
className: QoderCredentialCard_module_css_default.modelCatalogMeta,
|
|
525
|
+
children: t("modelsEnabled", { count: models.length })
|
|
526
|
+
})] }) : null, /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
527
|
+
type: "button",
|
|
528
|
+
className: QoderCredentialCard_module_css_default.linkButton,
|
|
529
|
+
disabled: disabled || fetching || Boolean(fetchDisabled),
|
|
530
|
+
onClick: () => {
|
|
531
|
+
fetchModels();
|
|
532
|
+
},
|
|
533
|
+
children: fetching ? t("modelsFetching") : t("modelsFetch")
|
|
534
|
+
})]
|
|
535
|
+
}),
|
|
536
|
+
failure ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
537
|
+
className: QoderCredentialCard_module_css_default.error,
|
|
538
|
+
role: "alert",
|
|
539
|
+
children: failure
|
|
540
|
+
}) : null,
|
|
541
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
542
|
+
className: QoderCredentialCard_module_css_default.modelList,
|
|
543
|
+
children: displayedModels.map((model) => {
|
|
544
|
+
const unavailable = unavailableIds.has(model.id);
|
|
545
|
+
const tiers = contextTiersOf(model);
|
|
546
|
+
const fallbackTier = tiers.find((tier) => tier.isDefault) ?? tiers[tiers.length - 1];
|
|
547
|
+
const selectedTier = resolveContextTier(model)?.key ?? fallbackTier?.key;
|
|
548
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
549
|
+
className: `${QoderCredentialCard_module_css_default.modelChoice} ${unavailable ? QoderCredentialCard_module_css_default.modelUnavailable : ""}`,
|
|
550
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
551
|
+
className: QoderCredentialCard_module_css_default.modelChoiceHead,
|
|
552
|
+
children: [
|
|
553
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
554
|
+
type: "checkbox",
|
|
555
|
+
checked: !unavailable && selectedIds.has(model.id),
|
|
556
|
+
disabled: disabled || unavailable,
|
|
557
|
+
onChange: (event) => {
|
|
558
|
+
toggleModel(model.id, event.currentTarget.checked);
|
|
559
|
+
}
|
|
560
|
+
}),
|
|
561
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
562
|
+
className: QoderCredentialCard_module_css_default.modelChoiceName,
|
|
563
|
+
children: model.name
|
|
564
|
+
}),
|
|
565
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
566
|
+
className: QoderCredentialCard_module_css_default.modelRate,
|
|
567
|
+
children: renderRate(model)
|
|
568
|
+
}),
|
|
569
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", { children: model.id }),
|
|
570
|
+
unavailable ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
571
|
+
className: QoderCredentialCard_module_css_default.modelBadge,
|
|
572
|
+
children: t("modelUnavailable")
|
|
573
|
+
}) : null
|
|
574
|
+
]
|
|
575
|
+
}), tiers.length > 1 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
576
|
+
className: QoderCredentialCard_module_css_default.modelTier,
|
|
577
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
578
|
+
className: QoderCredentialCard_module_css_default.modelTierLabel,
|
|
579
|
+
children: t("contextTierLabel")
|
|
580
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
|
|
581
|
+
className: QoderCredentialCard_module_css_default.modelTierSelect,
|
|
582
|
+
value: selectedTier ?? "",
|
|
583
|
+
disabled: disabled || unavailable || !selectedIds.has(model.id),
|
|
584
|
+
onChange: (event) => {
|
|
585
|
+
changeContextTier(model.id, event.currentTarget.value);
|
|
586
|
+
},
|
|
587
|
+
children: tiers.map((tier) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
588
|
+
value: tier.key,
|
|
589
|
+
children: tier.isDefault ? `${formatContextTokens(tier.tokenCount)}${t("contextTierDefaultSuffix")}` : formatContextTokens(tier.tokenCount)
|
|
590
|
+
}, tier.key))
|
|
591
|
+
})]
|
|
592
|
+
}) : null]
|
|
593
|
+
}, model.id);
|
|
594
|
+
})
|
|
595
|
+
}),
|
|
596
|
+
tieredModels.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
597
|
+
className: QoderCredentialCard_module_css_default.modelTierHint,
|
|
598
|
+
children: t("contextTierHint")
|
|
599
|
+
}) : null
|
|
600
|
+
]
|
|
601
|
+
});
|
|
602
|
+
}
|
|
603
|
+
//#endregion
|
|
274
604
|
//#region src/client/QoderAccountCard.tsx
|
|
275
605
|
function formatResetDate(dateStr) {
|
|
276
606
|
if (!dateStr) return void 0;
|
|
@@ -292,6 +622,7 @@ window.__ModuleLoader__.load({
|
|
|
292
622
|
const [accountState, setAccountState] = (0, react.useState)({ status: "idle" });
|
|
293
623
|
const [refreshing, setRefreshing] = (0, react.useState)(false);
|
|
294
624
|
const [credentialRevision, setCredentialRevision] = (0, react.useState)(0);
|
|
625
|
+
const [modelSaveError, setModelSaveError] = (0, react.useState)();
|
|
295
626
|
const latestAccountRequest = (0, react.useRef)(0);
|
|
296
627
|
const modelSnapshot = (0, react.useSyncExternalStore)(operations.subscribeModels, operations.getModelSnapshot, operations.getModelSnapshot);
|
|
297
628
|
const loadCredential = (0, react.useCallback)(async () => {
|
|
@@ -412,9 +743,12 @@ window.__ModuleLoader__.load({
|
|
|
412
743
|
}, key);
|
|
413
744
|
};
|
|
414
745
|
const renderAccount = () => {
|
|
415
|
-
if (!configured) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("
|
|
416
|
-
className: QoderCredentialCard_module_css_default.
|
|
417
|
-
children:
|
|
746
|
+
if (!configured) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
747
|
+
className: QoderCredentialCard_module_css_default.accountSection,
|
|
748
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
749
|
+
className: QoderCredentialCard_module_css_default.accountEmptyText,
|
|
750
|
+
children: t("accountCredentialHint")
|
|
751
|
+
})
|
|
418
752
|
});
|
|
419
753
|
if (accountState.status === "loading") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
420
754
|
className: QoderCredentialCard_module_css_default.accountSection,
|
|
@@ -585,6 +919,54 @@ window.__ModuleLoader__.load({
|
|
|
585
919
|
]
|
|
586
920
|
});
|
|
587
921
|
};
|
|
922
|
+
const currentRegion = regionOf(modelSnapshot.value);
|
|
923
|
+
const currentModels = modelsOf(modelSnapshot.value, currentRegion);
|
|
924
|
+
const canModifyModels = modelSnapshot.status === "ready" && modelSnapshot.writable;
|
|
925
|
+
const handleModelsChange = async (models) => {
|
|
926
|
+
if (!canModifyModels) return;
|
|
927
|
+
setModelSaveError(void 0);
|
|
928
|
+
const failure = validateModelCatalog(models);
|
|
929
|
+
if (failure) {
|
|
930
|
+
setModelSaveError(t(failure));
|
|
931
|
+
return;
|
|
932
|
+
}
|
|
933
|
+
if (!await operations.storeModels(currentRegion, models)) setModelSaveError(t("saveFailed"));
|
|
934
|
+
};
|
|
935
|
+
const renderModelCatalogSection = () => {
|
|
936
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
|
|
937
|
+
className: QoderCredentialCard_module_css_default.customized,
|
|
938
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("summary", {
|
|
939
|
+
className: QoderCredentialCard_module_css_default.customizedSummary,
|
|
940
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("modelsTitle") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
941
|
+
className: QoderCredentialCard_module_css_default.modelSummaryBadge,
|
|
942
|
+
children: t("modelsEnabled", { count: currentModels.length })
|
|
943
|
+
})]
|
|
944
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
945
|
+
className: QoderCredentialCard_module_css_default.customizedBody,
|
|
946
|
+
children: [modelSnapshot.status === "loading" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
947
|
+
className: QoderCredentialCard_module_css_default.hint,
|
|
948
|
+
children: t("modelsLoading")
|
|
949
|
+
}) : modelSnapshot.status === "unavailable" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
950
|
+
className: QoderCredentialCard_module_css_default.error,
|
|
951
|
+
children: t("modelsUnavailable")
|
|
952
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(QoderModelCatalog, {
|
|
953
|
+
operations,
|
|
954
|
+
models: currentModels,
|
|
955
|
+
disabled: !canModifyModels,
|
|
956
|
+
fetchDisabled: !configured,
|
|
957
|
+
hideTitle: true,
|
|
958
|
+
t,
|
|
959
|
+
onChange: (models) => {
|
|
960
|
+
handleModelsChange(models);
|
|
961
|
+
}
|
|
962
|
+
}), modelSaveError ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
963
|
+
className: QoderCredentialCard_module_css_default.error,
|
|
964
|
+
role: "alert",
|
|
965
|
+
children: modelSaveError
|
|
966
|
+
}) : null]
|
|
967
|
+
})]
|
|
968
|
+
});
|
|
969
|
+
};
|
|
588
970
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
589
971
|
className: QoderCredentialCard_module_css_default.credential,
|
|
590
972
|
"aria-label": t("accountTitle"),
|
|
@@ -600,215 +982,25 @@ window.__ModuleLoader__.load({
|
|
|
600
982
|
})]
|
|
601
983
|
}),
|
|
602
984
|
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
|
-
})
|
|
985
|
+
renderWebSearchSection(),
|
|
986
|
+
renderModelCatalogSection()
|
|
773
987
|
]
|
|
774
988
|
});
|
|
775
989
|
}
|
|
776
990
|
//#endregion
|
|
777
991
|
//#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 defaultModels.map((model) => ({ ...model }));
|
|
785
|
-
}
|
|
786
|
-
function regionOf(value) {
|
|
787
|
-
if (typeof value !== "object" || value === null) return "global";
|
|
788
|
-
return value.region === "china" ? "china" : "global";
|
|
789
|
-
}
|
|
790
992
|
function QoderCredentialCard({ operations, t }) {
|
|
791
993
|
const [state, setState] = (0, react.useState)({ status: "loading" });
|
|
792
994
|
const [editing, setEditing] = (0, react.useState)(false);
|
|
793
995
|
const [draft, setDraft] = (0, react.useState)("");
|
|
794
996
|
const [regionDraft, setRegionDraft] = (0, react.useState)("global");
|
|
795
997
|
const [regionDirty, setRegionDirty] = (0, react.useState)(false);
|
|
796
|
-
const [modelDraft, setModelDraft] = (0, react.useState)([]);
|
|
797
|
-
const [modelsDirty, setModelsDirty] = (0, react.useState)(false);
|
|
798
998
|
const [mutation, setMutation] = (0, react.useState)();
|
|
799
999
|
const [notice, setNotice] = (0, react.useState)();
|
|
800
1000
|
const modelSnapshot = (0, react.useSyncExternalStore)(operations.subscribeModels, operations.getModelSnapshot, operations.getModelSnapshot);
|
|
801
1001
|
(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
|
-
]);
|
|
1002
|
+
if (modelSnapshot.status === "ready" && !regionDirty) setRegionDraft(regionOf(modelSnapshot.value));
|
|
1003
|
+
}, [modelSnapshot, regionDirty]);
|
|
812
1004
|
const load = (0, react.useCallback)(async () => {
|
|
813
1005
|
const info = await operations.describe();
|
|
814
1006
|
setState(info === void 0 ? { status: "failed" } : {
|
|
@@ -845,20 +1037,17 @@ window.__ModuleLoader__.load({
|
|
|
845
1037
|
const writable = state.info.writable;
|
|
846
1038
|
const busy = mutation !== void 0;
|
|
847
1039
|
const normalized = draft.trim();
|
|
848
|
-
const
|
|
849
|
-
const modelWritable = modelSnapshot.status === "ready" && modelSnapshot.writable;
|
|
1040
|
+
const canModifyRegion = modelSnapshot.status === "ready" && modelSnapshot.writable;
|
|
850
1041
|
const currentRegion = regionOf(modelSnapshot.value);
|
|
851
1042
|
const closeEditor = () => {
|
|
852
1043
|
setDraft("");
|
|
853
|
-
setModelDraft(modelsOf(modelSnapshot.value, regionOf(modelSnapshot.value)));
|
|
854
1044
|
setRegionDraft(regionOf(modelSnapshot.value));
|
|
855
|
-
setModelsDirty(false);
|
|
856
1045
|
setRegionDirty(false);
|
|
857
1046
|
setNotice(void 0);
|
|
858
1047
|
setEditing(false);
|
|
859
1048
|
};
|
|
860
1049
|
const save = async () => {
|
|
861
|
-
if (busy || !
|
|
1050
|
+
if (busy || !regionDirty && normalized.length === 0 || regionDirty && !canModifyRegion) return;
|
|
862
1051
|
setMutation("saving");
|
|
863
1052
|
setNotice(void 0);
|
|
864
1053
|
if (regionDirty) {
|
|
@@ -869,14 +1058,6 @@ window.__ModuleLoader__.load({
|
|
|
869
1058
|
}
|
|
870
1059
|
setRegionDirty(false);
|
|
871
1060
|
}
|
|
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
1061
|
if (normalized.length === 0 || await operations.store(normalized)) {
|
|
881
1062
|
setDraft("");
|
|
882
1063
|
setNotice("saved");
|
|
@@ -957,11 +1138,9 @@ window.__ModuleLoader__.load({
|
|
|
957
1138
|
role: "radio",
|
|
958
1139
|
"aria-checked": regionDraft === "global",
|
|
959
1140
|
className: `${QoderCredentialCard_module_css_default.regionOption} ${regionDraft === "global" ? QoderCredentialCard_module_css_default.regionOptionActive : ""}`,
|
|
960
|
-
disabled: !
|
|
1141
|
+
disabled: !canModifyRegion || busy,
|
|
961
1142
|
onClick: () => {
|
|
962
1143
|
setRegionDraft("global");
|
|
963
|
-
setModelDraft(modelsOf(modelSnapshot.value, "global"));
|
|
964
|
-
setModelsDirty(false);
|
|
965
1144
|
setRegionDirty(true);
|
|
966
1145
|
},
|
|
967
1146
|
children: t("regionGlobal")
|
|
@@ -970,11 +1149,9 @@ window.__ModuleLoader__.load({
|
|
|
970
1149
|
role: "radio",
|
|
971
1150
|
"aria-checked": regionDraft === "china",
|
|
972
1151
|
className: `${QoderCredentialCard_module_css_default.regionOption} ${regionDraft === "china" ? QoderCredentialCard_module_css_default.regionOptionActive : ""}`,
|
|
973
|
-
disabled: !
|
|
1152
|
+
disabled: !canModifyRegion || busy,
|
|
974
1153
|
onClick: () => {
|
|
975
1154
|
setRegionDraft("china");
|
|
976
|
-
setModelDraft(modelsOf(modelSnapshot.value, "china"));
|
|
977
|
-
setModelsDirty(false);
|
|
978
1155
|
setRegionDirty(true);
|
|
979
1156
|
},
|
|
980
1157
|
children: t("regionChina")
|
|
@@ -1001,34 +1178,6 @@ window.__ModuleLoader__.load({
|
|
|
1001
1178
|
role: "alert",
|
|
1002
1179
|
children: t("readOnly")
|
|
1003
1180
|
}) : 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
1181
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1033
1182
|
className: QoderCredentialCard_module_css_default.actions,
|
|
1034
1183
|
children: [
|
|
@@ -1051,7 +1200,7 @@ window.__ModuleLoader__.load({
|
|
|
1051
1200
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1052
1201
|
type: "button",
|
|
1053
1202
|
className: QoderCredentialCard_module_css_default.primary,
|
|
1054
|
-
disabled: busy || !
|
|
1203
|
+
disabled: busy || !regionDirty && normalized.length === 0 || regionDirty && !canModifyRegion || normalized.length > 0 && !writable,
|
|
1055
1204
|
onClick: () => {
|
|
1056
1205
|
save();
|
|
1057
1206
|
},
|
|
@@ -1064,6 +1213,225 @@ window.__ModuleLoader__.load({
|
|
|
1064
1213
|
]
|
|
1065
1214
|
});
|
|
1066
1215
|
}
|
|
1216
|
+
//#endregion
|
|
1217
|
+
//#region src/dsh/provider.ts
|
|
1218
|
+
/** DSH model provider route, matching the plugin package name. */
|
|
1219
|
+
const QODER_PROVIDER_ID = "dsh-provider-qoder";
|
|
1220
|
+
//#endregion
|
|
1221
|
+
//#region src/client/context-selection.ts
|
|
1222
|
+
function isQoderProvider(provider) {
|
|
1223
|
+
return [
|
|
1224
|
+
QODER_PROVIDER_ID,
|
|
1225
|
+
"qoder-official",
|
|
1226
|
+
"qoder",
|
|
1227
|
+
"qoder-subscription"
|
|
1228
|
+
].includes(provider ?? "");
|
|
1229
|
+
}
|
|
1230
|
+
function historicalContextWindow(current, lastUsed, contextWindow) {
|
|
1231
|
+
return current.provider === lastUsed?.provider && current.model === lastUsed?.model ? contextWindow : void 0;
|
|
1232
|
+
}
|
|
1233
|
+
/** Composer selections belong to the current session; model defaults live in settings. */
|
|
1234
|
+
async function saveContextSelection(operations, sessionId, region, modelId, tierKey) {
|
|
1235
|
+
try {
|
|
1236
|
+
return await operations.setSessionTier?.(sessionId, modelId, tierKey, region) ? "saved" : "session-failed";
|
|
1237
|
+
} catch {
|
|
1238
|
+
return "session-failed";
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
//#endregion
|
|
1242
|
+
//#region \0dsh-css:/home/runner/work/dsh-provider-qoder/dsh-provider-qoder/src/client/QoderContextSelect.module.css.mjs
|
|
1243
|
+
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-menu-surface-fill);min-width:180px;backdrop-filter:var(--dsw-menu-backdrop-filter);border:1px solid var(--dsw-alias-border-l1);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}";
|
|
1244
|
+
const tagId = "dsh-provider-qoder/QoderContextSelect.module.css";
|
|
1245
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
1246
|
+
const tag = document.createElement("style");
|
|
1247
|
+
tag.dataset.plugin = "dsh-provider-qoder";
|
|
1248
|
+
tag.dataset.pluginCss = tagId;
|
|
1249
|
+
tag.textContent = css;
|
|
1250
|
+
document.head.appendChild(tag);
|
|
1251
|
+
}
|
|
1252
|
+
var QoderContextSelect_module_css_default = {
|
|
1253
|
+
"check": "hiDrJa_check",
|
|
1254
|
+
"chevron": "hiDrJa_chevron",
|
|
1255
|
+
"chevronOpen": "hiDrJa_chevronOpen",
|
|
1256
|
+
"error": "hiDrJa_error",
|
|
1257
|
+
"fadeIn": "hiDrJa_fadeIn",
|
|
1258
|
+
"icon": "hiDrJa_icon",
|
|
1259
|
+
"label": "hiDrJa_label",
|
|
1260
|
+
"menu": "hiDrJa_menu",
|
|
1261
|
+
"menuHeader": "hiDrJa_menuHeader",
|
|
1262
|
+
"option": "hiDrJa_option",
|
|
1263
|
+
"optionInfo": "hiDrJa_optionInfo",
|
|
1264
|
+
"optionSelected": "hiDrJa_optionSelected",
|
|
1265
|
+
"root": "hiDrJa_root",
|
|
1266
|
+
"tag": "hiDrJa_tag",
|
|
1267
|
+
"trigger": "hiDrJa_trigger",
|
|
1268
|
+
"triggerActive": "hiDrJa_triggerActive"
|
|
1269
|
+
};
|
|
1270
|
+
//#endregion
|
|
1271
|
+
//#region src/client/QoderContextSelect.tsx
|
|
1272
|
+
function QoderContextSelect(props) {
|
|
1273
|
+
const { directory, operations, t, sessionId, useProjection } = props;
|
|
1274
|
+
const [open, setOpen] = (0, react.useState)(false);
|
|
1275
|
+
const [manualTiers, setManualTiers] = (0, react.useState)({});
|
|
1276
|
+
const [pending, setPending] = (0, react.useState)(false);
|
|
1277
|
+
const [error, setError] = (0, react.useState)(null);
|
|
1278
|
+
const saving = (0, react.useRef)(false);
|
|
1279
|
+
const rootRef = (0, react.useRef)(null);
|
|
1280
|
+
const directoryState = (0, react.useSyncExternalStore)((fn) => directory ? directory.subscribe(fn) : () => () => {}, () => directory ? directory.getSnapshot() : null);
|
|
1281
|
+
const modelSnapshot = (0, react.useSyncExternalStore)((fn) => operations ? operations.subscribeModels(fn) : () => () => {}, () => operations ? operations.getModelSnapshot() : null);
|
|
1282
|
+
(0, react.useEffect)(() => {
|
|
1283
|
+
if (!open) return;
|
|
1284
|
+
const handleClickOutside = (e) => {
|
|
1285
|
+
if (rootRef.current && !rootRef.current.contains(e.target)) setOpen(false);
|
|
1286
|
+
};
|
|
1287
|
+
const handleKeyDown = (e) => {
|
|
1288
|
+
if (e.key === "Escape") setOpen(false);
|
|
1289
|
+
};
|
|
1290
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
1291
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
1292
|
+
return () => {
|
|
1293
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
1294
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
1295
|
+
};
|
|
1296
|
+
}, [open]);
|
|
1297
|
+
const modelProj = useProjection ? useProjection("modelSelection") : void 0;
|
|
1298
|
+
const pressure = useProjection ? useProjection("contextPressure") : void 0;
|
|
1299
|
+
if (!operations) return null;
|
|
1300
|
+
const projectedCurrent = modelProj?.next ?? modelProj?.lastUsed;
|
|
1301
|
+
const current = directoryState?.current ?? (projectedCurrent?.model ? {
|
|
1302
|
+
provider: projectedCurrent.provider ?? "dsh-provider-qoder",
|
|
1303
|
+
model: projectedCurrent.model
|
|
1304
|
+
} : null);
|
|
1305
|
+
if (!current) return null;
|
|
1306
|
+
const region = regionOf(modelSnapshot?.value);
|
|
1307
|
+
const models = modelsOf(modelSnapshot?.value, region);
|
|
1308
|
+
const currentModelId = current.model.includes("/") ? current.model.split("/")[1] : current.model;
|
|
1309
|
+
const currentProviderId = current.provider ?? (current.model.includes("/") ? current.model.split("/")[0] : void 0);
|
|
1310
|
+
const activeModel = models.find((m) => m.id === currentModelId || m.id === current.model);
|
|
1311
|
+
if (!isQoderProvider(currentProviderId) || !activeModel) return null;
|
|
1312
|
+
const tiers = contextTiersOf(activeModel);
|
|
1313
|
+
if (tiers.length <= 1) return null;
|
|
1314
|
+
const sessionKey = sessionId ? JSON.stringify([
|
|
1315
|
+
region,
|
|
1316
|
+
sessionId,
|
|
1317
|
+
activeModel.id
|
|
1318
|
+
]) : void 0;
|
|
1319
|
+
const historicalWindow = operations.canRestoreContextHistory?.() === false ? void 0 : historicalContextWindow(current, modelProj?.lastUsed, pressure?.contextWindow);
|
|
1320
|
+
const currentTier = resolveContextTier(activeModel, sessionKey ? manualTiers[sessionKey] : void 0, historicalWindow);
|
|
1321
|
+
if (!currentTier) return null;
|
|
1322
|
+
const selectedTierKey = currentTier.key;
|
|
1323
|
+
const selectTier = async (tierKey) => {
|
|
1324
|
+
setOpen(false);
|
|
1325
|
+
if (!sessionId || !sessionKey || saving.current) return;
|
|
1326
|
+
if (tierKey === selectedTierKey && error?.key !== sessionKey) return;
|
|
1327
|
+
saving.current = true;
|
|
1328
|
+
setPending(true);
|
|
1329
|
+
setError(null);
|
|
1330
|
+
try {
|
|
1331
|
+
if (await saveContextSelection(operations, sessionId, region, activeModel.id, tierKey) === "saved") setManualTiers((prev) => ({
|
|
1332
|
+
...prev,
|
|
1333
|
+
[sessionKey]: tierKey
|
|
1334
|
+
}));
|
|
1335
|
+
else setError({ key: sessionKey });
|
|
1336
|
+
} finally {
|
|
1337
|
+
saving.current = false;
|
|
1338
|
+
setPending(false);
|
|
1339
|
+
}
|
|
1340
|
+
};
|
|
1341
|
+
const defaultSuffix = t ? t("contextTierDefaultSuffix").replace(/[()()]/g, "") : "默认";
|
|
1342
|
+
const selectTitle = t ? t("contextSelectTitle") : "选择上下文大小";
|
|
1343
|
+
const menuHeader = t ? t("contextSelectMenuHeader") : "上下文容量";
|
|
1344
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1345
|
+
className: QoderContextSelect_module_css_default.root,
|
|
1346
|
+
ref: rootRef,
|
|
1347
|
+
children: [
|
|
1348
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
1349
|
+
type: "button",
|
|
1350
|
+
className: `${QoderContextSelect_module_css_default.trigger} ${open ? QoderContextSelect_module_css_default.triggerActive : ""}`,
|
|
1351
|
+
disabled: pending || !sessionId,
|
|
1352
|
+
"aria-expanded": open,
|
|
1353
|
+
"aria-label": selectTitle,
|
|
1354
|
+
title: `${selectTitle}: ${formatContextTokens(currentTier.tokenCount)}`,
|
|
1355
|
+
onClick: () => setOpen((prev) => !prev),
|
|
1356
|
+
children: [
|
|
1357
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1358
|
+
className: QoderContextSelect_module_css_default.icon,
|
|
1359
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
1360
|
+
width: "14",
|
|
1361
|
+
height: "14",
|
|
1362
|
+
viewBox: "0 0 16 16",
|
|
1363
|
+
fill: "currentColor",
|
|
1364
|
+
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" })
|
|
1365
|
+
})
|
|
1366
|
+
}),
|
|
1367
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1368
|
+
className: QoderContextSelect_module_css_default.label,
|
|
1369
|
+
children: formatContextTokens(currentTier.tokenCount)
|
|
1370
|
+
}),
|
|
1371
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1372
|
+
className: `${QoderContextSelect_module_css_default.chevron} ${open ? QoderContextSelect_module_css_default.chevronOpen : ""}`,
|
|
1373
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
1374
|
+
width: "10",
|
|
1375
|
+
height: "10",
|
|
1376
|
+
viewBox: "0 0 12 12",
|
|
1377
|
+
fill: "none",
|
|
1378
|
+
stroke: "currentColor",
|
|
1379
|
+
strokeWidth: "1.5",
|
|
1380
|
+
strokeLinecap: "round",
|
|
1381
|
+
strokeLinejoin: "round",
|
|
1382
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M3 4.5L6 7.5L9 4.5" })
|
|
1383
|
+
})
|
|
1384
|
+
})
|
|
1385
|
+
]
|
|
1386
|
+
}),
|
|
1387
|
+
error && error.key === sessionKey && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1388
|
+
role: "alert",
|
|
1389
|
+
className: QoderContextSelect_module_css_default.error,
|
|
1390
|
+
children: t ? t("contextSelectFailed") : "contextSelectFailed"
|
|
1391
|
+
}),
|
|
1392
|
+
open && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1393
|
+
className: QoderContextSelect_module_css_default.menu,
|
|
1394
|
+
role: "menu",
|
|
1395
|
+
"aria-label": selectTitle,
|
|
1396
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1397
|
+
className: QoderContextSelect_module_css_default.menuHeader,
|
|
1398
|
+
children: menuHeader
|
|
1399
|
+
}), tiers.map((tier) => {
|
|
1400
|
+
const isSelected = tier.key === selectedTierKey;
|
|
1401
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
1402
|
+
type: "button",
|
|
1403
|
+
role: "menuitemradio",
|
|
1404
|
+
"aria-checked": isSelected,
|
|
1405
|
+
className: `${QoderContextSelect_module_css_default.option} ${isSelected ? QoderContextSelect_module_css_default.optionSelected : ""}`,
|
|
1406
|
+
onClick: () => {
|
|
1407
|
+
selectTier(tier.key);
|
|
1408
|
+
},
|
|
1409
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1410
|
+
className: QoderContextSelect_module_css_default.optionInfo,
|
|
1411
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: formatContextTokens(tier.tokenCount) }), tier.isDefault && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1412
|
+
className: QoderContextSelect_module_css_default.tag,
|
|
1413
|
+
children: defaultSuffix
|
|
1414
|
+
})]
|
|
1415
|
+
}), isSelected && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1416
|
+
className: QoderContextSelect_module_css_default.check,
|
|
1417
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
1418
|
+
width: "14",
|
|
1419
|
+
height: "14",
|
|
1420
|
+
viewBox: "0 0 16 16",
|
|
1421
|
+
fill: "none",
|
|
1422
|
+
stroke: "currentColor",
|
|
1423
|
+
strokeWidth: "2",
|
|
1424
|
+
strokeLinecap: "round",
|
|
1425
|
+
strokeLinejoin: "round",
|
|
1426
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M3.5 8.5L6.5 11.5L12.5 4.5" })
|
|
1427
|
+
})
|
|
1428
|
+
})]
|
|
1429
|
+
}, tier.key);
|
|
1430
|
+
})]
|
|
1431
|
+
})
|
|
1432
|
+
]
|
|
1433
|
+
});
|
|
1434
|
+
}
|
|
1067
1435
|
/**
|
|
1068
1436
|
* Absolute Fetch-route prefix. Connection mounts its shared, authenticated API
|
|
1069
1437
|
* channel at `/api`, and every exact Fetch route lives directly below it.
|
|
@@ -1183,6 +1551,21 @@ window.__ModuleLoader__.load({
|
|
|
1183
1551
|
}), "provider-qoder: credential copy");
|
|
1184
1552
|
const credentials = ctx.remote.credentials;
|
|
1185
1553
|
const rpc = createQoderRpcCaller();
|
|
1554
|
+
let historyRegion;
|
|
1555
|
+
let historyRegionChanged = false;
|
|
1556
|
+
const readModelSnapshot = () => {
|
|
1557
|
+
const snapshot = modelScope.getSnapshot();
|
|
1558
|
+
if (snapshot.value) {
|
|
1559
|
+
const region = snapshot.value.region ?? "global";
|
|
1560
|
+
if (historyRegion !== void 0 && historyRegion !== region) historyRegionChanged = true;
|
|
1561
|
+
historyRegion = region;
|
|
1562
|
+
}
|
|
1563
|
+
return snapshot;
|
|
1564
|
+
};
|
|
1565
|
+
readModelSnapshot();
|
|
1566
|
+
ctx.effect(() => modelScope.subscribe(() => {
|
|
1567
|
+
readModelSnapshot();
|
|
1568
|
+
}), "provider-qoder: context history region");
|
|
1186
1569
|
const operations = {
|
|
1187
1570
|
describe: async () => {
|
|
1188
1571
|
try {
|
|
@@ -1207,14 +1590,16 @@ window.__ModuleLoader__.load({
|
|
|
1207
1590
|
}
|
|
1208
1591
|
},
|
|
1209
1592
|
getAccount: async (force) => await rpc.call("account", { force }),
|
|
1210
|
-
getModelSnapshot:
|
|
1593
|
+
getModelSnapshot: readModelSnapshot,
|
|
1594
|
+
canRestoreContextHistory: () => !historyRegionChanged,
|
|
1211
1595
|
subscribeModels: (listener) => modelScope.subscribe(listener),
|
|
1212
1596
|
storeModels: async (region, models) => {
|
|
1213
1597
|
try {
|
|
1214
1598
|
const current = modelScope.getSnapshot().value;
|
|
1599
|
+
const clonedModels = models.map(cloneCatalogModel);
|
|
1215
1600
|
return await modelScope.set("modelsByRegion", {
|
|
1216
1601
|
...current?.modelsByRegion,
|
|
1217
|
-
[region]:
|
|
1602
|
+
[region]: clonedModels
|
|
1218
1603
|
}) !== false;
|
|
1219
1604
|
} catch {
|
|
1220
1605
|
return false;
|
|
@@ -1235,6 +1620,18 @@ window.__ModuleLoader__.load({
|
|
|
1235
1620
|
}
|
|
1236
1621
|
},
|
|
1237
1622
|
discoverModels: async () => await rpc.call("models", {}),
|
|
1623
|
+
setSessionTier: async (sessionId, modelId, tierKey, region) => {
|
|
1624
|
+
try {
|
|
1625
|
+
return (await rpc.call("sessionTier", {
|
|
1626
|
+
sessionId,
|
|
1627
|
+
modelId,
|
|
1628
|
+
tierKey,
|
|
1629
|
+
region
|
|
1630
|
+
})).ok;
|
|
1631
|
+
} catch {
|
|
1632
|
+
return false;
|
|
1633
|
+
}
|
|
1634
|
+
},
|
|
1238
1635
|
subscribe: (listener) => ctx.remote.$on("credentials/reference-updated", (ref) => {
|
|
1239
1636
|
if (ref === "QODER_MANAGED_CREDENTIAL") listener();
|
|
1240
1637
|
})
|
|
@@ -1271,6 +1668,31 @@ window.__ModuleLoader__.load({
|
|
|
1271
1668
|
activeLocale
|
|
1272
1669
|
})
|
|
1273
1670
|
}, QoderCredentialCard));
|
|
1671
|
+
ctx.inject([
|
|
1672
|
+
"modelDirectories",
|
|
1673
|
+
"sessions",
|
|
1674
|
+
"remote.session"
|
|
1675
|
+
], (scope) => {
|
|
1676
|
+
scope.slots.inject("conversation.input.right", () => scope.slots.register({
|
|
1677
|
+
name: "conversation.input.right",
|
|
1678
|
+
id: "qoder-context-select",
|
|
1679
|
+
order: 10,
|
|
1680
|
+
inject: (sessionId) => {
|
|
1681
|
+
let directory = void 0;
|
|
1682
|
+
try {
|
|
1683
|
+
const modelDirectories = scope.get("modelDirectories");
|
|
1684
|
+
directory = sessionId && modelDirectories ? modelDirectories.directoryFor(sessionId)?.store : void 0;
|
|
1685
|
+
} catch {}
|
|
1686
|
+
return {
|
|
1687
|
+
sessionId,
|
|
1688
|
+
directory,
|
|
1689
|
+
operations,
|
|
1690
|
+
t,
|
|
1691
|
+
activeLocale
|
|
1692
|
+
};
|
|
1693
|
+
}
|
|
1694
|
+
}, QoderContextSelect));
|
|
1695
|
+
});
|
|
1274
1696
|
}
|
|
1275
1697
|
//#endregion
|
|
1276
1698
|
exports.apply = apply;
|