@eddyskywalker/dsh-chatgpt-subscription 0.41.1 → 0.43.0
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/CHANGELOG.md +77 -0
- package/README.md +1 -0
- package/lib/client.js +445 -476
- package/lib/client.js.map +1 -1
- package/lib/index.js +632 -219
- package/lib/types/client/command-code/CommandCodeComposerQuota.d.ts.map +1 -1
- package/lib/types/client/common/format.d.ts +16 -0
- package/lib/types/client/common/format.d.ts.map +1 -1
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/kimi-code/KimiCodeComposerQuota.d.ts.map +1 -1
- package/lib/types/client/kimi-code/KimiCodeSection.d.ts.map +1 -1
- package/lib/types/client/kimi-code/KimiQuotaCard.d.ts.map +1 -1
- package/lib/types/client/kimi-code/locales.d.ts +41 -14
- package/lib/types/client/kimi-code/locales.d.ts.map +1 -1
- package/lib/types/client/kimi-code/styles.d.ts.map +1 -1
- package/lib/types/client/locales-ru/hub.d.ts.map +1 -1
- package/lib/types/client/locales-ru/kimi-code.d.ts.map +1 -1
- package/lib/types/client/locales-ru/opendesign.d.ts.map +1 -1
- package/lib/types/client/locales.d.ts +1 -27
- package/lib/types/client/locales.d.ts.map +1 -1
- package/lib/types/client/opendesign/OpenDesignSection.d.ts.map +1 -1
- package/lib/types/client/opendesign/locales.d.ts +12 -0
- package/lib/types/client/opendesign/locales.d.ts.map +1 -1
- package/lib/types/compat.d.ts +1 -1
- package/lib/types/host/claude/types.d.ts +7 -1
- package/lib/types/host/claude/types.d.ts.map +1 -1
- package/lib/types/host/compaction-route/index.d.ts +16 -1
- package/lib/types/host/compaction-route/index.d.ts.map +1 -1
- package/lib/types/host/glm-coding-plan/types.d.ts +5 -1
- package/lib/types/host/glm-coding-plan/types.d.ts.map +1 -1
- package/lib/types/host/kimi-code/account-pool.d.ts +26 -1
- package/lib/types/host/kimi-code/account-pool.d.ts.map +1 -1
- package/lib/types/host/kimi-code/client.d.ts +24 -0
- package/lib/types/host/kimi-code/client.d.ts.map +1 -1
- package/lib/types/host/kimi-code/model-catalog.d.ts.map +1 -1
- package/lib/types/host/kimi-code/oauth.d.ts +16 -0
- package/lib/types/host/kimi-code/oauth.d.ts.map +1 -1
- package/lib/types/host/kimi-code/routes.d.ts.map +1 -1
- package/lib/types/host/opendesign/adapter.d.ts +11 -13
- package/lib/types/host/opendesign/adapter.d.ts.map +1 -1
- package/lib/types/host/opendesign/catalog.d.ts +14 -0
- package/lib/types/host/opendesign/catalog.d.ts.map +1 -1
- package/lib/types/host/opendesign/line.d.ts +17 -6
- package/lib/types/host/opendesign/line.d.ts.map +1 -1
- package/lib/types/host/opendesign/routes.d.ts.map +1 -1
- package/lib/types/host/opendesign/token-store.d.ts +91 -4
- package/lib/types/host/opendesign/token-store.d.ts.map +1 -1
- package/lib/types/host/opendesign/types.d.ts.map +1 -1
- package/lib/types/host/qoder/types.d.ts +6 -1
- package/lib/types/host/qoder/types.d.ts.map +1 -1
- package/lib/types/host/step-code/types.d.ts +5 -1
- package/lib/types/host/step-code/types.d.ts.map +1 -1
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/shared/opendesign-contracts.d.ts +24 -1
- package/lib/types/shared/opendesign-contracts.d.ts.map +1 -1
- package/package.json +1 -1
- package/lib/types/client/CompactionRouteBundleConfig.d.ts +0 -19
- package/lib/types/client/CompactionRouteBundleConfig.d.ts.map +0 -1
package/lib/client.js
CHANGED
|
@@ -146,11 +146,11 @@ window.__ModuleLoader__.load({
|
|
|
146
146
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
147
147
|
className: "dsh-codex-composer-quota",
|
|
148
148
|
"data-level": quota === null ? "normal" : quota.remainingPercent <= 5 ? "danger" : quota.remainingPercent <= 20 ? "warning" : "normal",
|
|
149
|
-
"aria-label": quota === null ? t("quickQuotaLoading") : `${t("quickQuotaLabel")}: ${formatPercent$
|
|
150
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("quickQuotaLabel") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: quota === null ? loading ? t("quickQuotaLoading") : "—" : formatPercent$
|
|
149
|
+
"aria-label": quota === null ? t("quickQuotaLoading") : `${t("quickQuotaLabel")}: ${formatPercent$2(quota.remainingPercent)}`,
|
|
150
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("quickQuotaLabel") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: quota === null ? loading ? t("quickQuotaLoading") : "—" : formatPercent$2(quota.remainingPercent) })]
|
|
151
151
|
});
|
|
152
152
|
}
|
|
153
|
-
function formatPercent$
|
|
153
|
+
function formatPercent$2(value) {
|
|
154
154
|
return `${new Intl.NumberFormat(void 0, { maximumFractionDigits: 0 }).format(value)}%`;
|
|
155
155
|
}
|
|
156
156
|
//#endregion
|
|
@@ -1147,6 +1147,26 @@ window.__ModuleLoader__.load({
|
|
|
1147
1147
|
if (value >= 1e3) return Math.round(value / 1e3) + "k";
|
|
1148
1148
|
return String(value);
|
|
1149
1149
|
}
|
|
1150
|
+
/**
|
|
1151
|
+
* A share as a person reads it: at most `digits` decimals, no trailing zeros.
|
|
1152
|
+
*
|
|
1153
|
+
* The formatting has to happen on the RESULT rather than on its inputs. Most
|
|
1154
|
+
* percentages on these cards are a remainder — `100 - used` — and that
|
|
1155
|
+
* subtraction is exactly where binary floating point shows up: `100 - 8.04` is
|
|
1156
|
+
* `91.96000000000001`, `100 - 0.0007 * 100` is `99.93` but `100 - 0.0014 * 100`
|
|
1157
|
+
* is `99.86` only because it happens to land on a friendly neighbour. String
|
|
1158
|
+
* interpolation of the difference therefore prints a long tail for roughly a
|
|
1159
|
+
* third of all two-decimal inputs, which reads as "sometimes" — and no amount of
|
|
1160
|
+
* rounding the used share beforehand fixes a subtraction done afterwards.
|
|
1161
|
+
*
|
|
1162
|
+
* Anything non-finite renders as `0`, because every caller has already decided
|
|
1163
|
+
* the window is measured; this is the last line of defence, not a claim.
|
|
1164
|
+
*/
|
|
1165
|
+
function formatPercent$1(value, digits = 2) {
|
|
1166
|
+
if (!Number.isFinite(value)) return "0";
|
|
1167
|
+
const factor = 10 ** Math.min(6, Math.max(0, Math.trunc(digits)));
|
|
1168
|
+
return String(Math.round(value * factor) / factor);
|
|
1169
|
+
}
|
|
1150
1170
|
/** A stamp in the reader's own locale, or an em dash when there is none. */
|
|
1151
1171
|
function formatDate$1(ms) {
|
|
1152
1172
|
if (ms === void 0 || ms === null || !Number.isFinite(ms) || ms <= 0) return "—";
|
|
@@ -4631,6 +4651,195 @@ window.__ModuleLoader__.load({
|
|
|
4631
4651
|
});
|
|
4632
4652
|
}
|
|
4633
4653
|
//#endregion
|
|
4654
|
+
//#region src/client/CompactionRouteCard.tsx
|
|
4655
|
+
/**
|
|
4656
|
+
* Choose the model an automatic compaction summarizes on.
|
|
4657
|
+
*
|
|
4658
|
+
* The route lives in this plugin's preferences and is applied by the host's
|
|
4659
|
+
* `llm/stream` listener, so a saved choice takes effect on the next compaction
|
|
4660
|
+
* without a restart. Both selects are needed together: a model id alone belongs
|
|
4661
|
+
* to no route.
|
|
4662
|
+
*
|
|
4663
|
+
* The picker loads its directory on demand rather than on mount: opening the
|
|
4664
|
+
* settings page must not cost a request to every line (that page is opened for
|
|
4665
|
+
* unrelated reasons all the time), and the card already knows the saved route
|
|
4666
|
+
* from the status it was rendered with.
|
|
4667
|
+
*/
|
|
4668
|
+
function CompactionRouteCard({ api, preferences, disabled = false, labels, onSaved }) {
|
|
4669
|
+
const [picking, setPicking] = (0, react.useState)(false);
|
|
4670
|
+
const [candidates, setCandidates] = (0, react.useState)(null);
|
|
4671
|
+
const [loadError, setLoadError] = (0, react.useState)(null);
|
|
4672
|
+
const [provider, setProvider] = (0, react.useState)("");
|
|
4673
|
+
const [model, setModel] = (0, react.useState)("");
|
|
4674
|
+
const [busy, setBusy] = (0, react.useState)(false);
|
|
4675
|
+
const [notice, setNotice] = (0, react.useState)(null);
|
|
4676
|
+
const [error, setError] = (0, react.useState)(null);
|
|
4677
|
+
const load = (0, react.useCallback)(async () => {
|
|
4678
|
+
try {
|
|
4679
|
+
const value = await api.compactionCandidates();
|
|
4680
|
+
setCandidates(value);
|
|
4681
|
+
setLoadError(null);
|
|
4682
|
+
} catch (cause) {
|
|
4683
|
+
setLoadError(cause instanceof Error ? cause.message : String(cause));
|
|
4684
|
+
}
|
|
4685
|
+
}, [api]);
|
|
4686
|
+
(0, react.useEffect)(() => {
|
|
4687
|
+
if (picking && candidates === null) load();
|
|
4688
|
+
}, [
|
|
4689
|
+
picking,
|
|
4690
|
+
candidates,
|
|
4691
|
+
load
|
|
4692
|
+
]);
|
|
4693
|
+
(0, react.useEffect)(() => {
|
|
4694
|
+
const saved = preferences?.compactionRoute ?? null;
|
|
4695
|
+
if (saved === null) return;
|
|
4696
|
+
setProvider((current) => current === "" ? saved.provider : current);
|
|
4697
|
+
setModel((current) => current === "" ? saved.model : current);
|
|
4698
|
+
}, [preferences?.compactionRoute]);
|
|
4699
|
+
const providers = candidates?.providers ?? [];
|
|
4700
|
+
const models = providers.find((entry) => entry.id === provider)?.models ?? [];
|
|
4701
|
+
const selected = models.find((entry) => entry.id === model);
|
|
4702
|
+
const savedProvider = preferences?.compactionRoute?.provider ?? "";
|
|
4703
|
+
const savedModel = preferences?.compactionRoute?.model ?? "";
|
|
4704
|
+
const canSave = provider !== "" && model !== "" && (provider !== savedProvider || model !== savedModel) && !busy && !disabled;
|
|
4705
|
+
const providerOptions = savedProvider === "" || providers.some((entry) => entry.id === savedProvider) ? providers : [{
|
|
4706
|
+
id: savedProvider,
|
|
4707
|
+
name: savedProvider
|
|
4708
|
+
}, ...providers];
|
|
4709
|
+
const modelOptions = model !== "" && !models.some((entry) => entry.id === model) ? [{
|
|
4710
|
+
id: model,
|
|
4711
|
+
name: model,
|
|
4712
|
+
modalities: []
|
|
4713
|
+
}, ...models] : models;
|
|
4714
|
+
const currentLabel = savedProvider === "" ? labels.follow : `${savedProvider} / ${savedModel}`;
|
|
4715
|
+
const save = async (target) => {
|
|
4716
|
+
setBusy(true);
|
|
4717
|
+
setError(null);
|
|
4718
|
+
setNotice(null);
|
|
4719
|
+
try {
|
|
4720
|
+
onSaved(await api.updatePreferences({ compactionRoute: target }));
|
|
4721
|
+
setNotice(labels.saved);
|
|
4722
|
+
setPicking(false);
|
|
4723
|
+
} catch (cause) {
|
|
4724
|
+
setError(cause instanceof Error ? cause.message : String(cause));
|
|
4725
|
+
} finally {
|
|
4726
|
+
setBusy(false);
|
|
4727
|
+
}
|
|
4728
|
+
};
|
|
4729
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
4730
|
+
className: "dsha-group",
|
|
4731
|
+
children: [
|
|
4732
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4733
|
+
className: "dsha-grouphead",
|
|
4734
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: labels.title })
|
|
4735
|
+
}),
|
|
4736
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4737
|
+
className: "dsha-muted",
|
|
4738
|
+
children: labels.hint
|
|
4739
|
+
}),
|
|
4740
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4741
|
+
className: "dsha-pref-row",
|
|
4742
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: currentLabel }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4743
|
+
className: "dsha-btn",
|
|
4744
|
+
type: "button",
|
|
4745
|
+
disabled: busy || disabled,
|
|
4746
|
+
onClick: () => setPicking((current) => !current),
|
|
4747
|
+
children: labels.change
|
|
4748
|
+
})]
|
|
4749
|
+
}),
|
|
4750
|
+
picking ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
4751
|
+
loadError !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4752
|
+
className: "dsh-codex-error",
|
|
4753
|
+
role: "alert",
|
|
4754
|
+
children: loadError
|
|
4755
|
+
}) : null,
|
|
4756
|
+
candidates !== null && providers.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4757
|
+
className: "dsh-codex-empty",
|
|
4758
|
+
children: labels.empty
|
|
4759
|
+
}) : null,
|
|
4760
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4761
|
+
className: "dsha-pref-row",
|
|
4762
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: labels.provider }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
4763
|
+
className: "dsha-select",
|
|
4764
|
+
"aria-label": labels.provider,
|
|
4765
|
+
value: provider,
|
|
4766
|
+
disabled: busy || disabled,
|
|
4767
|
+
onChange: (event) => {
|
|
4768
|
+
setProvider(event.currentTarget.value);
|
|
4769
|
+
setModel("");
|
|
4770
|
+
},
|
|
4771
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
4772
|
+
value: "",
|
|
4773
|
+
children: "—"
|
|
4774
|
+
}), providerOptions.map((entry) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
4775
|
+
value: entry.id,
|
|
4776
|
+
children: entry.name
|
|
4777
|
+
}, entry.id))]
|
|
4778
|
+
})]
|
|
4779
|
+
}),
|
|
4780
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4781
|
+
className: "dsha-pref-row",
|
|
4782
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: labels.model }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
4783
|
+
className: "dsha-select",
|
|
4784
|
+
"aria-label": labels.model,
|
|
4785
|
+
value: model,
|
|
4786
|
+
disabled: busy || disabled || provider === "",
|
|
4787
|
+
onChange: (event) => setModel(event.currentTarget.value),
|
|
4788
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
4789
|
+
value: "",
|
|
4790
|
+
children: "—"
|
|
4791
|
+
}), modelOptions.map((entry) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
4792
|
+
value: entry.id,
|
|
4793
|
+
children: entry.name
|
|
4794
|
+
}, entry.id))]
|
|
4795
|
+
})]
|
|
4796
|
+
}),
|
|
4797
|
+
selected !== void 0 && selected.modalities.length > 0 && !selected.modalities.includes("video") ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4798
|
+
className: "dsh-codex-warning",
|
|
4799
|
+
children: labels.noVideo
|
|
4800
|
+
}) : null,
|
|
4801
|
+
selected !== void 0 && selected.modalities.length > 0 && !selected.modalities.includes("image") ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4802
|
+
className: "dsh-codex-warning",
|
|
4803
|
+
children: labels.noImage
|
|
4804
|
+
}) : null,
|
|
4805
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4806
|
+
className: "dsha-actions",
|
|
4807
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4808
|
+
className: "dsha-btn dsha-btn-primary",
|
|
4809
|
+
type: "button",
|
|
4810
|
+
disabled: !canSave,
|
|
4811
|
+
onClick: () => void save({
|
|
4812
|
+
provider,
|
|
4813
|
+
model
|
|
4814
|
+
}),
|
|
4815
|
+
children: labels.save
|
|
4816
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4817
|
+
className: "dsha-btn",
|
|
4818
|
+
type: "button",
|
|
4819
|
+
disabled: busy || disabled || savedProvider === "",
|
|
4820
|
+
onClick: () => void save(null),
|
|
4821
|
+
children: labels.clear
|
|
4822
|
+
})]
|
|
4823
|
+
})
|
|
4824
|
+
] }) : null,
|
|
4825
|
+
notice !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4826
|
+
className: "dsh-codex-success",
|
|
4827
|
+
role: "status",
|
|
4828
|
+
children: notice
|
|
4829
|
+
}) : null,
|
|
4830
|
+
error !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
|
|
4831
|
+
className: "dsh-codex-error",
|
|
4832
|
+
role: "alert",
|
|
4833
|
+
children: [
|
|
4834
|
+
labels.failed,
|
|
4835
|
+
": ",
|
|
4836
|
+
error
|
|
4837
|
+
]
|
|
4838
|
+
}) : null
|
|
4839
|
+
]
|
|
4840
|
+
});
|
|
4841
|
+
}
|
|
4842
|
+
//#endregion
|
|
4634
4843
|
//#region src/client/kimi-code/locales.ts
|
|
4635
4844
|
const NS_KIMI_CODE = "dsh-kimi-code";
|
|
4636
4845
|
const zh$10 = {
|
|
@@ -4731,11 +4940,7 @@ window.__ModuleLoader__.load({
|
|
|
4731
4940
|
cacheOutput: "输出 tokens",
|
|
4732
4941
|
cacheRequests: "请求数",
|
|
4733
4942
|
cacheWrite: "缓存写入",
|
|
4734
|
-
cacheWrite5m: "5 分钟档",
|
|
4735
|
-
cacheWrite1h: "1 小时档",
|
|
4736
|
-
cacheWriteHint: "写入是独立计费项:1h 写入单价约为 5m 的两倍,命中后会按原 TTL 续期。分档显示 0 表示服务端没有回报该档的写入数(响应头缺失就是静默),不等于该档确实没写入。",
|
|
4737
4943
|
unknownMetric: "暂无",
|
|
4738
|
-
cacheHint: "同一会话内:系统提示与工具列表一旦变化会使缓存整体失效,因此保持工具集合稳定、把新增内容追加在末尾,命中率最高。",
|
|
4739
4944
|
cacheExpired: "本会话已空闲超过缓存有效期,下一轮将重新处理约 {tokens} 个 token。",
|
|
4740
4945
|
cacheDrift: "最近前缀状态",
|
|
4741
4946
|
cacheDriftFirst: "首个请求(缓存为空)",
|
|
@@ -4786,7 +4991,20 @@ window.__ModuleLoader__.load({
|
|
|
4786
4991
|
loading: "加载中...",
|
|
4787
4992
|
loginFailed: "登录失败",
|
|
4788
4993
|
requests: "次请求",
|
|
4789
|
-
tokens: "tokens"
|
|
4994
|
+
tokens: "tokens",
|
|
4995
|
+
compactionRoute: "压缩模型",
|
|
4996
|
+
compactionRouteHint: "自动压缩时由哪个模型来写摘要(仅对本线路的会话生效)。留空则继续用会话自己的模型,也就继续消耗这条线路的额度。",
|
|
4997
|
+
compactionRouteProvider: "线路",
|
|
4998
|
+
compactionRouteModel: "模型",
|
|
4999
|
+
compactionRouteSave: "保存",
|
|
5000
|
+
compactionRouteClear: "恢复会话模型",
|
|
5001
|
+
compactionRouteChange: "设置",
|
|
5002
|
+
compactionRouteFollow: "跟随会话模型(默认)",
|
|
5003
|
+
compactionRouteSaved: "已保存,下次压缩生效。",
|
|
5004
|
+
compactionRouteFailed: "保存失败",
|
|
5005
|
+
compactionRouteNoVideo: "该模型不接受视频:含视频的会话会回落到会话模型完成压缩。",
|
|
5006
|
+
compactionRouteNoImage: "该模型不接受图片:摘要里的截图会被替换为占位文本。",
|
|
5007
|
+
compactionRouteEmpty: "没有可用的线路——先登录任意一条线路再回来设置。"
|
|
4790
5008
|
};
|
|
4791
5009
|
const en$10 = {
|
|
4792
5010
|
...accountPoolEn,
|
|
@@ -4887,11 +5105,7 @@ window.__ModuleLoader__.load({
|
|
|
4887
5105
|
cacheOutput: "Output tokens",
|
|
4888
5106
|
cacheRequests: "Requests",
|
|
4889
5107
|
cacheWrite: "Cache writes",
|
|
4890
|
-
cacheWrite5m: "5-minute tier",
|
|
4891
|
-
cacheWrite1h: "1-hour tier",
|
|
4892
|
-
cacheWriteHint: "A write is billed separately: a 1h write costs about twice a 5m one, and a hit renews the entry under its original TTL. A tier showing 0 means the service did not report a write for it (a missing response header is silence), not that nothing was written there.",
|
|
4893
5108
|
unknownMetric: "n/a",
|
|
4894
|
-
cacheHint: "Within one session: any change to the system prompt or the tool list invalidates the whole prefix cache, so keep the tool set stable and append new material at the tail for the best hit rate.",
|
|
4895
5109
|
cacheDrift: "Last prefix state",
|
|
4896
5110
|
cacheDriftFirst: "First request (cache cold)",
|
|
4897
5111
|
cacheDriftStable: "Stable (prefix unchanged)",
|
|
@@ -4941,7 +5155,20 @@ window.__ModuleLoader__.load({
|
|
|
4941
5155
|
loading: "Loading...",
|
|
4942
5156
|
loginFailed: "Sign-in failed",
|
|
4943
5157
|
requests: "requests",
|
|
4944
|
-
tokens: "tokens"
|
|
5158
|
+
tokens: "tokens",
|
|
5159
|
+
compactionRoute: "Compaction model",
|
|
5160
|
+
compactionRouteHint: "Which model writes the summary when the context is compacted — it applies to sessions on this line only. Leave it unset to keep the conversation's own model, and this line's quota.",
|
|
5161
|
+
compactionRouteProvider: "Line",
|
|
5162
|
+
compactionRouteModel: "Model",
|
|
5163
|
+
compactionRouteSave: "Save",
|
|
5164
|
+
compactionRouteClear: "Use the conversation model",
|
|
5165
|
+
compactionRouteChange: "Change",
|
|
5166
|
+
compactionRouteFollow: "Follows the conversation model (default)",
|
|
5167
|
+
compactionRouteSaved: "Saved; it applies to the next compaction.",
|
|
5168
|
+
compactionRouteFailed: "Save failed",
|
|
5169
|
+
compactionRouteNoVideo: "This model takes no video: a session that carries video falls back to the conversation model.",
|
|
5170
|
+
compactionRouteNoImage: "This model takes no images: screenshots become placeholder text in the summary.",
|
|
5171
|
+
compactionRouteEmpty: "No route is available — sign in to one first."
|
|
4945
5172
|
};
|
|
4946
5173
|
const dictionaries$10 = {
|
|
4947
5174
|
zh: zh$10,
|
|
@@ -5213,10 +5440,12 @@ window.__ModuleLoader__.load({
|
|
|
5213
5440
|
const SHORT_PER_WEEK = 5;
|
|
5214
5441
|
/** 5 小时窗口在月额度里的份数。 */
|
|
5215
5442
|
const SHORT_PER_MONTH = 25;
|
|
5216
|
-
/**
|
|
5443
|
+
/** 提示条箭头离气泡两端的最小距离,免得圆角把三角切掉。 */
|
|
5444
|
+
const ARROW_INSET = 12;
|
|
5445
|
+
/** 百分比,最多两位小数;非有限数不画。舍入规则放在共享的 `formatPercent`。 */
|
|
5217
5446
|
function percentText$2(value) {
|
|
5218
5447
|
if (!Number.isFinite(value)) return "0%";
|
|
5219
|
-
return `${
|
|
5448
|
+
return `${formatPercent$1(value)}%`;
|
|
5220
5449
|
}
|
|
5221
5450
|
/** `YYYY-MM-DD HH:mm`,本地时区;令牌到期用它,年份不能省。 */
|
|
5222
5451
|
function dateText(ms) {
|
|
@@ -5306,6 +5535,43 @@ window.__ModuleLoader__.load({
|
|
|
5306
5535
|
const timer = window.setInterval(() => setClock(Date.now()), 3e4);
|
|
5307
5536
|
return () => window.clearInterval(timer);
|
|
5308
5537
|
}, [shortReset]);
|
|
5538
|
+
const tipPercent = Math.max(0, Math.min(100, totalPercent));
|
|
5539
|
+
const barRef = (0, react.useRef)(null);
|
|
5540
|
+
const tipRef = (0, react.useRef)(null);
|
|
5541
|
+
const [tipPlacement, setTipPlacement] = (0, react.useState)({
|
|
5542
|
+
shift: 0,
|
|
5543
|
+
arrowPx: null
|
|
5544
|
+
});
|
|
5545
|
+
(0, react.useEffect)(() => {
|
|
5546
|
+
const wrap = barRef.current;
|
|
5547
|
+
const tip = tipRef.current;
|
|
5548
|
+
if (wrap === null || tip === null) return void 0;
|
|
5549
|
+
const place = () => {
|
|
5550
|
+
const width = wrap.clientWidth;
|
|
5551
|
+
const bubble = tip.offsetWidth;
|
|
5552
|
+
if (width <= 0 || bubble <= 0) {
|
|
5553
|
+
setTipPlacement({
|
|
5554
|
+
shift: 0,
|
|
5555
|
+
arrowPx: null
|
|
5556
|
+
});
|
|
5557
|
+
return;
|
|
5558
|
+
}
|
|
5559
|
+
const half = bubble / 2;
|
|
5560
|
+
const anchor = width * tipPercent / 100;
|
|
5561
|
+
const clamped = Math.min(Math.max(anchor, half), Math.max(half, width - half));
|
|
5562
|
+
const arrow = Math.min(Math.max(anchor - (clamped - half), ARROW_INSET), bubble - ARROW_INSET);
|
|
5563
|
+
setTipPlacement({
|
|
5564
|
+
shift: Math.round((clamped - anchor) * 10) / 10,
|
|
5565
|
+
arrowPx: Math.round(arrow * 10) / 10
|
|
5566
|
+
});
|
|
5567
|
+
};
|
|
5568
|
+
place();
|
|
5569
|
+
if (typeof ResizeObserver === "undefined") return void 0;
|
|
5570
|
+
const observer = new ResizeObserver(place);
|
|
5571
|
+
observer.observe(wrap);
|
|
5572
|
+
observer.observe(tip);
|
|
5573
|
+
return () => observer.disconnect();
|
|
5574
|
+
}, [tipPercent]);
|
|
5309
5575
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5310
5576
|
className: "dsha-kq",
|
|
5311
5577
|
children: [
|
|
@@ -5357,6 +5623,8 @@ window.__ModuleLoader__.load({
|
|
|
5357
5623
|
}),
|
|
5358
5624
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5359
5625
|
className: "dsha-kq-barwrap",
|
|
5626
|
+
ref: barRef,
|
|
5627
|
+
style: { "--kq-tip-x": `${tipPercent}%` },
|
|
5360
5628
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5361
5629
|
className: "dsha-kq-meter dsha-kq-meter--total",
|
|
5362
5630
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
@@ -5371,6 +5639,11 @@ window.__ModuleLoader__.load({
|
|
|
5371
5639
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5372
5640
|
className: "dsha-kq-tip",
|
|
5373
5641
|
role: "tooltip",
|
|
5642
|
+
ref: tipRef,
|
|
5643
|
+
style: {
|
|
5644
|
+
"--kq-tip-shift": `${tipPlacement.shift}px`,
|
|
5645
|
+
...tipPlacement.arrowPx === null ? {} : { "--kq-tip-arrow": `${tipPlacement.arrowPx}px` }
|
|
5646
|
+
},
|
|
5374
5647
|
children: t.kqTip.replace("{pct}", percentText$2(totalPercent))
|
|
5375
5648
|
})]
|
|
5376
5649
|
}),
|
|
@@ -5416,19 +5689,6 @@ window.__ModuleLoader__.load({
|
|
|
5416
5689
|
//#endregion
|
|
5417
5690
|
//#region src/client/kimi-code/KimiCodeSection.tsx
|
|
5418
5691
|
const api$12 = createLineApi("/kimi-code/api", "Kimi Code");
|
|
5419
|
-
/** Money the service reports in minor units, rendered in its own currency. */
|
|
5420
|
-
function formatMoney(cents, currency) {
|
|
5421
|
-
if (cents === null) return "—";
|
|
5422
|
-
const code = currency ?? "USD";
|
|
5423
|
-
try {
|
|
5424
|
-
return new Intl.NumberFormat(void 0, {
|
|
5425
|
-
style: "currency",
|
|
5426
|
-
currency: code
|
|
5427
|
-
}).format(cents / 100);
|
|
5428
|
-
} catch {
|
|
5429
|
-
return `${(cents / 100).toFixed(2)} ${code}`;
|
|
5430
|
-
}
|
|
5431
|
-
}
|
|
5432
5692
|
/**
|
|
5433
5693
|
* One token count as the card prints it.
|
|
5434
5694
|
*
|
|
@@ -5461,6 +5721,8 @@ window.__ModuleLoader__.load({
|
|
|
5461
5721
|
const [savingModel, setSavingModel] = (0, react.useState)(null);
|
|
5462
5722
|
const [copied, setCopied] = (0, react.useState)(false);
|
|
5463
5723
|
const [connectionNotice, setConnectionNotice] = (0, react.useState)(null);
|
|
5724
|
+
const [subscriptionApi] = (0, react.useState)(() => new SubscriptionApi());
|
|
5725
|
+
const [compactionPreferences, setCompactionPreferences] = (0, react.useState)(null);
|
|
5464
5726
|
/** Follow-up poll owed while the host refreshes the quota behind an answer. */
|
|
5465
5727
|
const quotaFollowUp = (0, react.useRef)(null);
|
|
5466
5728
|
const t = useLineDict(NS_KIMI_CODE, zh$10);
|
|
@@ -5484,6 +5746,16 @@ window.__ModuleLoader__.load({
|
|
|
5484
5746
|
setLoading(false);
|
|
5485
5747
|
}
|
|
5486
5748
|
}, []);
|
|
5749
|
+
(0, react.useEffect)(() => {
|
|
5750
|
+
let live = true;
|
|
5751
|
+
subscriptionApi.status().then((answer) => {
|
|
5752
|
+
const preferences = answer?.preferences;
|
|
5753
|
+
if (live && preferences !== void 0 && preferences !== null) setCompactionPreferences(preferences);
|
|
5754
|
+
}).catch(() => void 0);
|
|
5755
|
+
return () => {
|
|
5756
|
+
live = false;
|
|
5757
|
+
};
|
|
5758
|
+
}, [subscriptionApi]);
|
|
5487
5759
|
(0, react.useEffect)(() => {
|
|
5488
5760
|
loadStatus();
|
|
5489
5761
|
const refreshWhenVisible = () => {
|
|
@@ -5782,7 +6054,7 @@ window.__ModuleLoader__.load({
|
|
|
5782
6054
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5783
6055
|
className: "dsha-page",
|
|
5784
6056
|
children: [
|
|
5785
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
6057
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(AccountPoolSection, {
|
|
5786
6058
|
accounts: status?.accounts ?? [],
|
|
5787
6059
|
activeAccountId: status?.activeAccountId,
|
|
5788
6060
|
rotationStrategy: status?.rotationStrategy ?? "sequential",
|
|
@@ -5806,59 +6078,74 @@ window.__ModuleLoader__.load({
|
|
|
5806
6078
|
now,
|
|
5807
6079
|
labels: t
|
|
5808
6080
|
}),
|
|
5809
|
-
children:
|
|
5810
|
-
|
|
5811
|
-
|
|
5812
|
-
|
|
5813
|
-
|
|
5814
|
-
|
|
5815
|
-
|
|
5816
|
-
|
|
5817
|
-
|
|
5818
|
-
|
|
5819
|
-
|
|
5820
|
-
|
|
5821
|
-
|
|
5822
|
-
|
|
5823
|
-
|
|
5824
|
-
|
|
5825
|
-
|
|
5826
|
-
|
|
5827
|
-
|
|
5828
|
-
|
|
5829
|
-
|
|
5830
|
-
|
|
5831
|
-
target: "_blank",
|
|
5832
|
-
rel: "noreferrer noopener",
|
|
5833
|
-
children: flow.verificationUriComplete
|
|
5834
|
-
}),
|
|
5835
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5836
|
-
className: "dsha-row",
|
|
5837
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5838
|
-
className: "dsha-label",
|
|
5839
|
-
children: t.codeExpires
|
|
5840
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5841
|
-
className: "dsha-value",
|
|
5842
|
-
children: formatDate$1(flow?.expiresAt)
|
|
5843
|
-
})]
|
|
5844
|
-
}),
|
|
5845
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5846
|
-
className: "dsha-actions",
|
|
5847
|
-
children: [flow?.verificationUriComplete && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
|
|
5848
|
-
className: "dsha-btn",
|
|
6081
|
+
children: [
|
|
6082
|
+
loginPending && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6083
|
+
className: "dsha-device-box",
|
|
6084
|
+
children: [
|
|
6085
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t.deviceCodeSection }),
|
|
6086
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
6087
|
+
className: "dsha-muted",
|
|
6088
|
+
children: t.deviceCodeHint
|
|
6089
|
+
}),
|
|
6090
|
+
flow?.userCode && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6091
|
+
className: "dsha-code-row",
|
|
6092
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6093
|
+
className: "dsha-code",
|
|
6094
|
+
children: flow.userCode
|
|
6095
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
6096
|
+
className: "dsha-btn",
|
|
6097
|
+
onClick: () => void handleCopyCode(),
|
|
6098
|
+
children: copied ? t.copied : t.copyCode
|
|
6099
|
+
})]
|
|
6100
|
+
}),
|
|
6101
|
+
flow?.verificationUriComplete && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
|
|
6102
|
+
className: "dsha-link",
|
|
5849
6103
|
href: flow.verificationUriComplete,
|
|
5850
6104
|
target: "_blank",
|
|
5851
6105
|
rel: "noreferrer noopener",
|
|
5852
|
-
children:
|
|
5853
|
-
}),
|
|
5854
|
-
|
|
5855
|
-
|
|
5856
|
-
|
|
5857
|
-
|
|
5858
|
-
|
|
6106
|
+
children: flow.verificationUriComplete
|
|
6107
|
+
}),
|
|
6108
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6109
|
+
className: "dsha-row",
|
|
6110
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6111
|
+
className: "dsha-label",
|
|
6112
|
+
children: t.codeExpires
|
|
6113
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6114
|
+
className: "dsha-value",
|
|
6115
|
+
children: formatDate$1(flow?.expiresAt)
|
|
6116
|
+
})]
|
|
6117
|
+
}),
|
|
6118
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6119
|
+
className: "dsha-actions",
|
|
6120
|
+
children: [flow?.verificationUriComplete && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
|
|
6121
|
+
className: "dsha-btn",
|
|
6122
|
+
href: flow.verificationUriComplete,
|
|
6123
|
+
target: "_blank",
|
|
6124
|
+
rel: "noreferrer noopener",
|
|
6125
|
+
children: t.openSignInPage
|
|
6126
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
6127
|
+
className: "dsha-btn",
|
|
6128
|
+
disabled: busy !== null,
|
|
6129
|
+
onClick: () => void handleCancelLogin(),
|
|
6130
|
+
children: t.cancelSignIn
|
|
6131
|
+
})]
|
|
6132
|
+
})
|
|
6133
|
+
]
|
|
6134
|
+
}),
|
|
6135
|
+
status?.quotaError != null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
6136
|
+
className: "dsha-notice",
|
|
6137
|
+
children: status.quotaError
|
|
6138
|
+
}),
|
|
6139
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6140
|
+
className: "dsha-actions",
|
|
6141
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
6142
|
+
className: "dsha-btn",
|
|
6143
|
+
disabled: busy !== null || !status?.authenticated,
|
|
6144
|
+
onClick: () => void handleRefreshQuota(),
|
|
6145
|
+
children: busy === "quota" ? t.refreshingQuota : t.refreshQuota
|
|
5859
6146
|
})
|
|
5860
|
-
|
|
5861
|
-
|
|
6147
|
+
})
|
|
6148
|
+
]
|
|
5862
6149
|
}),
|
|
5863
6150
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
5864
6151
|
className: "dsha-group",
|
|
@@ -5980,33 +6267,35 @@ window.__ModuleLoader__.load({
|
|
|
5980
6267
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5981
6268
|
className: "dsha-label",
|
|
5982
6269
|
children: t.cacheWrite
|
|
5983
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.
|
|
6270
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5984
6271
|
className: "dsha-value",
|
|
5985
|
-
children:
|
|
5986
|
-
tokenCount(status.cache.cacheWriteTokens, t),
|
|
5987
|
-
" · ",
|
|
5988
|
-
t.cacheWrite5m,
|
|
5989
|
-
" ",
|
|
5990
|
-
tokenCount(status.cache.cacheWrite5mTokens, t),
|
|
5991
|
-
" · ",
|
|
5992
|
-
t.cacheWrite1h,
|
|
5993
|
-
" ",
|
|
5994
|
-
tokenCount(status.cache.cacheWrite1hTokens, t)
|
|
5995
|
-
]
|
|
6272
|
+
children: tokenCount(status.cache.cacheWriteTokens, t)
|
|
5996
6273
|
})]
|
|
5997
|
-
}),
|
|
5998
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5999
|
-
className: "dsha-muted",
|
|
6000
|
-
children: t.cacheWriteHint
|
|
6001
|
-
}),
|
|
6002
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
6003
|
-
className: "dsha-muted",
|
|
6004
|
-
children: t.cacheHint
|
|
6005
6274
|
})
|
|
6006
6275
|
]
|
|
6007
6276
|
})
|
|
6008
6277
|
]
|
|
6009
6278
|
}),
|
|
6279
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(CompactionRouteCard, {
|
|
6280
|
+
api: subscriptionApi,
|
|
6281
|
+
preferences: compactionPreferences,
|
|
6282
|
+
labels: {
|
|
6283
|
+
title: t.compactionRoute,
|
|
6284
|
+
hint: t.compactionRouteHint,
|
|
6285
|
+
provider: t.compactionRouteProvider,
|
|
6286
|
+
model: t.compactionRouteModel,
|
|
6287
|
+
save: t.compactionRouteSave,
|
|
6288
|
+
clear: t.compactionRouteClear,
|
|
6289
|
+
change: t.compactionRouteChange,
|
|
6290
|
+
follow: t.compactionRouteFollow,
|
|
6291
|
+
saved: t.compactionRouteSaved,
|
|
6292
|
+
failed: t.compactionRouteFailed,
|
|
6293
|
+
noVideo: t.compactionRouteNoVideo,
|
|
6294
|
+
noImage: t.compactionRouteNoImage,
|
|
6295
|
+
empty: t.compactionRouteEmpty
|
|
6296
|
+
},
|
|
6297
|
+
onSaved: setCompactionPreferences
|
|
6298
|
+
}),
|
|
6010
6299
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
6011
6300
|
className: "dsha-group",
|
|
6012
6301
|
children: [
|
|
@@ -6144,69 +6433,6 @@ window.__ModuleLoader__.load({
|
|
|
6144
6433
|
})
|
|
6145
6434
|
]
|
|
6146
6435
|
}),
|
|
6147
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
6148
|
-
className: "dsha-group",
|
|
6149
|
-
children: [
|
|
6150
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6151
|
-
className: "dsha-grouphead",
|
|
6152
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t.quotaSection }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
6153
|
-
className: "dsha-btn",
|
|
6154
|
-
disabled: busy !== null || !status?.authenticated,
|
|
6155
|
-
onClick: () => void handleRefreshQuota(),
|
|
6156
|
-
children: busy === "quota" ? t.refreshingQuota : t.refreshQuota
|
|
6157
|
-
})]
|
|
6158
|
-
}),
|
|
6159
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
6160
|
-
className: "dsha-muted",
|
|
6161
|
-
children: t.quotaDesc
|
|
6162
|
-
}),
|
|
6163
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
6164
|
-
className: "dsha-muted",
|
|
6165
|
-
children: t.quotaFactsScope
|
|
6166
|
-
}),
|
|
6167
|
-
status?.quotaError && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
6168
|
-
className: "dsha-notice",
|
|
6169
|
-
children: status.quotaError
|
|
6170
|
-
}),
|
|
6171
|
-
!status?.authenticated ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6172
|
-
className: "dsha-empty",
|
|
6173
|
-
children: t.signedOut
|
|
6174
|
-
}) : quota === null || quota === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6175
|
-
className: "dsha-empty",
|
|
6176
|
-
children: busy === "quota" ? t.refreshingQuota : t.quotaEmpty
|
|
6177
|
-
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6178
|
-
className: "dsha-quota-card",
|
|
6179
|
-
children: [
|
|
6180
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6181
|
-
className: "dsha-quota-title",
|
|
6182
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t.quotaPlan }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: quota.planName || t.planUnknown })]
|
|
6183
|
-
}),
|
|
6184
|
-
quota.extraUsage !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6185
|
-
className: "dsha-meter-wrap",
|
|
6186
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6187
|
-
className: "dsha-meter-label",
|
|
6188
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t.quotaWallet }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: formatMoney(quota.extraUsage.balanceCents, quota.extraUsage.currency) })]
|
|
6189
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6190
|
-
className: "dsha-meter-meta",
|
|
6191
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: formatMoney(quota.extraUsage.totalCents, quota.extraUsage.currency) }), quota.extraUsage.monthlyChargeLimitEnabled && quota.extraUsage.monthlyChargeLimitCents !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
6192
|
-
t.quotaWalletLimit,
|
|
6193
|
-
": ",
|
|
6194
|
-
formatMoney(quota.extraUsage.monthlyChargeLimitCents, quota.extraUsage.currency)
|
|
6195
|
-
] })]
|
|
6196
|
-
})]
|
|
6197
|
-
}),
|
|
6198
|
-
quota.windows.length === 0 && quota.extraUsage === null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6199
|
-
className: "dsha-empty",
|
|
6200
|
-
children: t.quotaEmpty
|
|
6201
|
-
}),
|
|
6202
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6203
|
-
className: "dsha-timestamp",
|
|
6204
|
-
children: t.updatedAt.replace("{time}", new Date(quota.fetchedAt).toLocaleString())
|
|
6205
|
-
})
|
|
6206
|
-
]
|
|
6207
|
-
})
|
|
6208
|
-
]
|
|
6209
|
-
}),
|
|
6210
6436
|
error && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6211
6437
|
className: "dsha-error",
|
|
6212
6438
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: error })
|
|
@@ -17154,6 +17380,8 @@ window.__ModuleLoader__.load({
|
|
|
17154
17380
|
catalogSyncedNote: "实时目录已同步 {count} 个模型。",
|
|
17155
17381
|
noModels: "暂无可用模型。",
|
|
17156
17382
|
pricingNote: "价格为官方公开价目(美元 / 每百万 token,输入 / 输出)。",
|
|
17383
|
+
unservedBadge: "套餐不支持",
|
|
17384
|
+
unservedHint: "当前套餐不提供的模型默认隐藏,勾选后会强制显示。",
|
|
17157
17385
|
contextSection: "上下文窗口",
|
|
17158
17386
|
contextHint: "官方未公布各模型的上下文窗口:默认按 128k 处理,可在这里按模型修正。留空或保存无效值会提示错误;恢复默认会清掉覆盖值。",
|
|
17159
17387
|
tokens: "tokens",
|
|
@@ -17260,6 +17488,8 @@ window.__ModuleLoader__.load({
|
|
|
17260
17488
|
catalogSyncedNote: "Live catalog synced: {count} model(s).",
|
|
17261
17489
|
noModels: "No models available.",
|
|
17262
17490
|
pricingNote: "Prices are the official public list (USD per 1M tokens, input / output).",
|
|
17491
|
+
unservedBadge: "Not in plan",
|
|
17492
|
+
unservedHint: "Models the current plan does not serve stay hidden by default; checking one here forces it to show.",
|
|
17263
17493
|
contextSection: "Context windows",
|
|
17264
17494
|
contextHint: "The vendor publishes no per-model context windows, so models default to 128k; correct any model here. An invalid value is reported rather than saved; restoring clears the override.",
|
|
17265
17495
|
tokens: "tokens",
|
|
@@ -17362,6 +17592,19 @@ window.__ModuleLoader__.load({
|
|
|
17362
17592
|
return Math.min(100, Math.max(0, value));
|
|
17363
17593
|
}
|
|
17364
17594
|
/**
|
|
17595
|
+
* Whether the plan the gateway bills for withholds this model.
|
|
17596
|
+
*
|
|
17597
|
+
* The host adds `served: false` to a catalog entry the current plan does not
|
|
17598
|
+
* provide. Such a row stays listed — unchecking it is what hides it, and
|
|
17599
|
+
* checking it is how a user forces it visible — so the card labels it rather
|
|
17600
|
+
* than dropping it. The field is optional: `true` and an absent field both mean
|
|
17601
|
+
* served, so the badge and the note never appear for them and every row renders
|
|
17602
|
+
* exactly as it did before this marker existed.
|
|
17603
|
+
*/
|
|
17604
|
+
function unserved(model) {
|
|
17605
|
+
return model.served === false;
|
|
17606
|
+
}
|
|
17607
|
+
/**
|
|
17365
17608
|
* A window's length in the words the service sold it in.
|
|
17366
17609
|
*
|
|
17367
17610
|
* A policy states seconds, and the tier's windows are round days and hours:
|
|
@@ -18104,6 +18347,11 @@ window.__ModuleLoader__.load({
|
|
|
18104
18347
|
style: { fontSize: 12 },
|
|
18105
18348
|
children: t.modelsHint
|
|
18106
18349
|
}),
|
|
18350
|
+
models.some(unserved) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
18351
|
+
className: "dsha-muted",
|
|
18352
|
+
style: { fontSize: 12 },
|
|
18353
|
+
children: t.unservedHint
|
|
18354
|
+
}),
|
|
18107
18355
|
status !== null && models.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
18108
18356
|
className: "dsha-empty",
|
|
18109
18357
|
children: t.noModels
|
|
@@ -18115,12 +18363,15 @@ window.__ModuleLoader__.load({
|
|
|
18115
18363
|
children: t.catalogNeverSynced
|
|
18116
18364
|
}),
|
|
18117
18365
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModelChecklist, {
|
|
18118
|
-
items: models.map((model) =>
|
|
18119
|
-
|
|
18120
|
-
|
|
18121
|
-
|
|
18122
|
-
|
|
18123
|
-
|
|
18366
|
+
items: models.map((model) => {
|
|
18367
|
+
const hint = model.hint ?? `${formatCapacity$1(model.contextWindow)} · ${model.input.join("+")}${model.reasoning ? " · reasoning" : ""}`;
|
|
18368
|
+
return {
|
|
18369
|
+
id: model.id,
|
|
18370
|
+
name: model.name,
|
|
18371
|
+
hint: unserved(model) ? `${hint} · ${t.unservedBadge}` : hint,
|
|
18372
|
+
enabled: model.enabled
|
|
18373
|
+
};
|
|
18374
|
+
}),
|
|
18124
18375
|
busy: busyAny,
|
|
18125
18376
|
onToggle: (id, enabled) => toggleModel(id, enabled),
|
|
18126
18377
|
onToggleAll: (enabled) => setAllModels(enabled),
|
|
@@ -18900,259 +19151,6 @@ window.__ModuleLoader__.load({
|
|
|
18900
19151
|
});
|
|
18901
19152
|
}
|
|
18902
19153
|
//#endregion
|
|
18903
|
-
//#region src/client/CompactionRouteCard.tsx
|
|
18904
|
-
/**
|
|
18905
|
-
* Choose the model an automatic compaction summarizes on.
|
|
18906
|
-
*
|
|
18907
|
-
* The route lives in this plugin's preferences and is applied by the host's
|
|
18908
|
-
* `llm/stream` listener, so a saved choice takes effect on the next compaction
|
|
18909
|
-
* without a restart. Both selects are needed together: a model id alone belongs
|
|
18910
|
-
* to no route.
|
|
18911
|
-
*
|
|
18912
|
-
* The picker loads its directory on demand rather than on mount: opening the
|
|
18913
|
-
* settings page must not cost a request to every line (that page is opened for
|
|
18914
|
-
* unrelated reasons all the time), and the card already knows the saved route
|
|
18915
|
-
* from the status it was rendered with.
|
|
18916
|
-
*/
|
|
18917
|
-
function CompactionRouteCard({ api, preferences, disabled = false, labels, onSaved }) {
|
|
18918
|
-
const [picking, setPicking] = (0, react.useState)(false);
|
|
18919
|
-
const [candidates, setCandidates] = (0, react.useState)(null);
|
|
18920
|
-
const [loadError, setLoadError] = (0, react.useState)(null);
|
|
18921
|
-
const [provider, setProvider] = (0, react.useState)("");
|
|
18922
|
-
const [model, setModel] = (0, react.useState)("");
|
|
18923
|
-
const [busy, setBusy] = (0, react.useState)(false);
|
|
18924
|
-
const [notice, setNotice] = (0, react.useState)(null);
|
|
18925
|
-
const [error, setError] = (0, react.useState)(null);
|
|
18926
|
-
const load = (0, react.useCallback)(async () => {
|
|
18927
|
-
try {
|
|
18928
|
-
const value = await api.compactionCandidates();
|
|
18929
|
-
setCandidates(value);
|
|
18930
|
-
setLoadError(null);
|
|
18931
|
-
} catch (cause) {
|
|
18932
|
-
setLoadError(cause instanceof Error ? cause.message : String(cause));
|
|
18933
|
-
}
|
|
18934
|
-
}, [api]);
|
|
18935
|
-
(0, react.useEffect)(() => {
|
|
18936
|
-
if (picking && candidates === null) load();
|
|
18937
|
-
}, [
|
|
18938
|
-
picking,
|
|
18939
|
-
candidates,
|
|
18940
|
-
load
|
|
18941
|
-
]);
|
|
18942
|
-
(0, react.useEffect)(() => {
|
|
18943
|
-
const saved = preferences?.compactionRoute ?? null;
|
|
18944
|
-
if (saved === null) return;
|
|
18945
|
-
setProvider((current) => current === "" ? saved.provider : current);
|
|
18946
|
-
setModel((current) => current === "" ? saved.model : current);
|
|
18947
|
-
}, [preferences?.compactionRoute]);
|
|
18948
|
-
const providers = candidates?.providers ?? [];
|
|
18949
|
-
const models = providers.find((entry) => entry.id === provider)?.models ?? [];
|
|
18950
|
-
const selected = models.find((entry) => entry.id === model);
|
|
18951
|
-
const savedProvider = preferences?.compactionRoute?.provider ?? "";
|
|
18952
|
-
const savedModel = preferences?.compactionRoute?.model ?? "";
|
|
18953
|
-
const canSave = provider !== "" && model !== "" && (provider !== savedProvider || model !== savedModel) && !busy && !disabled;
|
|
18954
|
-
const providerOptions = savedProvider === "" || providers.some((entry) => entry.id === savedProvider) ? providers : [{
|
|
18955
|
-
id: savedProvider,
|
|
18956
|
-
name: savedProvider
|
|
18957
|
-
}, ...providers];
|
|
18958
|
-
const modelOptions = model !== "" && !models.some((entry) => entry.id === model) ? [{
|
|
18959
|
-
id: model,
|
|
18960
|
-
name: model,
|
|
18961
|
-
modalities: []
|
|
18962
|
-
}, ...models] : models;
|
|
18963
|
-
const currentLabel = savedProvider === "" ? labels.follow : `${savedProvider} / ${savedModel}`;
|
|
18964
|
-
const save = async (target) => {
|
|
18965
|
-
setBusy(true);
|
|
18966
|
-
setError(null);
|
|
18967
|
-
setNotice(null);
|
|
18968
|
-
try {
|
|
18969
|
-
onSaved(await api.updatePreferences({ compactionRoute: target }));
|
|
18970
|
-
setNotice(labels.saved);
|
|
18971
|
-
setPicking(false);
|
|
18972
|
-
} catch (cause) {
|
|
18973
|
-
setError(cause instanceof Error ? cause.message : String(cause));
|
|
18974
|
-
} finally {
|
|
18975
|
-
setBusy(false);
|
|
18976
|
-
}
|
|
18977
|
-
};
|
|
18978
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
18979
|
-
className: "dsha-group",
|
|
18980
|
-
children: [
|
|
18981
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
18982
|
-
className: "dsha-grouphead",
|
|
18983
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: labels.title })
|
|
18984
|
-
}),
|
|
18985
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
18986
|
-
className: "dsha-muted",
|
|
18987
|
-
children: labels.hint
|
|
18988
|
-
}),
|
|
18989
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
18990
|
-
className: "dsha-pref-row",
|
|
18991
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: currentLabel }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
18992
|
-
className: "dsha-btn",
|
|
18993
|
-
type: "button",
|
|
18994
|
-
disabled: busy || disabled,
|
|
18995
|
-
onClick: () => setPicking((current) => !current),
|
|
18996
|
-
children: labels.change
|
|
18997
|
-
})]
|
|
18998
|
-
}),
|
|
18999
|
-
picking ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
19000
|
-
loadError !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
19001
|
-
className: "dsh-codex-error",
|
|
19002
|
-
role: "alert",
|
|
19003
|
-
children: loadError
|
|
19004
|
-
}) : null,
|
|
19005
|
-
candidates !== null && providers.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
19006
|
-
className: "dsh-codex-empty",
|
|
19007
|
-
children: labels.empty
|
|
19008
|
-
}) : null,
|
|
19009
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
19010
|
-
className: "dsha-pref-row",
|
|
19011
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: labels.provider }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
19012
|
-
className: "dsha-select",
|
|
19013
|
-
"aria-label": labels.provider,
|
|
19014
|
-
value: provider,
|
|
19015
|
-
disabled: busy || disabled,
|
|
19016
|
-
onChange: (event) => {
|
|
19017
|
-
setProvider(event.currentTarget.value);
|
|
19018
|
-
setModel("");
|
|
19019
|
-
},
|
|
19020
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
19021
|
-
value: "",
|
|
19022
|
-
children: "—"
|
|
19023
|
-
}), providerOptions.map((entry) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
19024
|
-
value: entry.id,
|
|
19025
|
-
children: entry.name
|
|
19026
|
-
}, entry.id))]
|
|
19027
|
-
})]
|
|
19028
|
-
}),
|
|
19029
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
19030
|
-
className: "dsha-pref-row",
|
|
19031
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: labels.model }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
19032
|
-
className: "dsha-select",
|
|
19033
|
-
"aria-label": labels.model,
|
|
19034
|
-
value: model,
|
|
19035
|
-
disabled: busy || disabled || provider === "",
|
|
19036
|
-
onChange: (event) => setModel(event.currentTarget.value),
|
|
19037
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
19038
|
-
value: "",
|
|
19039
|
-
children: "—"
|
|
19040
|
-
}), modelOptions.map((entry) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
19041
|
-
value: entry.id,
|
|
19042
|
-
children: entry.name
|
|
19043
|
-
}, entry.id))]
|
|
19044
|
-
})]
|
|
19045
|
-
}),
|
|
19046
|
-
selected !== void 0 && selected.modalities.length > 0 && !selected.modalities.includes("video") ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
19047
|
-
className: "dsh-codex-warning",
|
|
19048
|
-
children: labels.noVideo
|
|
19049
|
-
}) : null,
|
|
19050
|
-
selected !== void 0 && selected.modalities.length > 0 && !selected.modalities.includes("image") ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
19051
|
-
className: "dsh-codex-warning",
|
|
19052
|
-
children: labels.noImage
|
|
19053
|
-
}) : null,
|
|
19054
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
19055
|
-
className: "dsha-actions",
|
|
19056
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
19057
|
-
className: "dsha-btn dsha-btn-primary",
|
|
19058
|
-
type: "button",
|
|
19059
|
-
disabled: !canSave,
|
|
19060
|
-
onClick: () => void save({
|
|
19061
|
-
provider,
|
|
19062
|
-
model
|
|
19063
|
-
}),
|
|
19064
|
-
children: labels.save
|
|
19065
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
19066
|
-
className: "dsha-btn",
|
|
19067
|
-
type: "button",
|
|
19068
|
-
disabled: busy || disabled || savedProvider === "",
|
|
19069
|
-
onClick: () => void save(null),
|
|
19070
|
-
children: labels.clear
|
|
19071
|
-
})]
|
|
19072
|
-
})
|
|
19073
|
-
] }) : null,
|
|
19074
|
-
notice !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
19075
|
-
className: "dsh-codex-success",
|
|
19076
|
-
role: "status",
|
|
19077
|
-
children: notice
|
|
19078
|
-
}) : null,
|
|
19079
|
-
error !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
|
|
19080
|
-
className: "dsh-codex-error",
|
|
19081
|
-
role: "alert",
|
|
19082
|
-
children: [
|
|
19083
|
-
labels.failed,
|
|
19084
|
-
": ",
|
|
19085
|
-
error
|
|
19086
|
-
]
|
|
19087
|
-
}) : null
|
|
19088
|
-
]
|
|
19089
|
-
});
|
|
19090
|
-
}
|
|
19091
|
-
//#endregion
|
|
19092
|
-
//#region src/client/CompactionRouteBundleConfig.tsx
|
|
19093
|
-
/**
|
|
19094
|
-
* Compaction-model settings on this plugin's own page in the DSH plugin
|
|
19095
|
-
* manager.
|
|
19096
|
-
*
|
|
19097
|
-
* The setting is cross-line, so it does not belong inside any one provider's
|
|
19098
|
-
* tab: the plugin's page is where an operator configures *this plugin*, and the
|
|
19099
|
-
* bundle-config slot places it between the package description and the rows the
|
|
19100
|
-
* bundle declares.
|
|
19101
|
-
*
|
|
19102
|
-
* The slot is keyed by the bundle's package name, so the page dispatches it for
|
|
19103
|
-
* this package only — no subject filter is needed. It also renders its
|
|
19104
|
-
* occupants in the `summary` view (a one-liner beside the card); bundle
|
|
19105
|
-
* configuration has nothing to say there and renders null.
|
|
19106
|
-
*
|
|
19107
|
-
* @module dsh-chatgpt-subscription/compaction-route-bundle-config
|
|
19108
|
-
*/
|
|
19109
|
-
/** The package whose page this entry configures. */
|
|
19110
|
-
const COMPACTION_ROUTE_PACKAGE = "@eddyskywalker/dsh-chatgpt-subscription";
|
|
19111
|
-
/**
|
|
19112
|
-
* Render the compaction-model card on this package's bundle page only.
|
|
19113
|
-
*
|
|
19114
|
-
* Split in two so the hooks below never mount for the summary view: that view
|
|
19115
|
-
* is a one-liner drawn beside the card, and fetching this plugin's preferences
|
|
19116
|
-
* for it would be a request nobody asked for.
|
|
19117
|
-
*/
|
|
19118
|
-
function CompactionRouteBundleConfig(props) {
|
|
19119
|
-
if (props.view !== "page") return null;
|
|
19120
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(OwnedSection, { t: props.t });
|
|
19121
|
-
}
|
|
19122
|
-
function OwnedSection({ t }) {
|
|
19123
|
-
const [preferences, setPreferences] = (0, react.useState)(null);
|
|
19124
|
-
const [api] = (0, react.useState)(() => new SubscriptionApi());
|
|
19125
|
-
(0, react.useEffect)(() => {
|
|
19126
|
-
let live = true;
|
|
19127
|
-
api.status().then((status) => {
|
|
19128
|
-
if (live) setPreferences(status.preferences);
|
|
19129
|
-
}).catch(() => void 0);
|
|
19130
|
-
return () => {
|
|
19131
|
-
live = false;
|
|
19132
|
-
};
|
|
19133
|
-
}, [api]);
|
|
19134
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CompactionRouteCard, {
|
|
19135
|
-
api,
|
|
19136
|
-
preferences,
|
|
19137
|
-
labels: {
|
|
19138
|
-
title: t("compactionRoute"),
|
|
19139
|
-
hint: t("compactionRouteHint"),
|
|
19140
|
-
provider: t("compactionRouteProvider"),
|
|
19141
|
-
model: t("compactionRouteModel"),
|
|
19142
|
-
save: t("compactionRouteSave"),
|
|
19143
|
-
clear: t("compactionRouteClear"),
|
|
19144
|
-
change: t("compactionRouteChange"),
|
|
19145
|
-
follow: t("compactionRouteFollow"),
|
|
19146
|
-
saved: t("compactionRouteSaved"),
|
|
19147
|
-
failed: t("compactionRouteFailed"),
|
|
19148
|
-
noVideo: t("compactionRouteNoVideo"),
|
|
19149
|
-
noImage: t("compactionRouteNoImage"),
|
|
19150
|
-
empty: t("compactionRouteEmpty")
|
|
19151
|
-
},
|
|
19152
|
-
onSaved: setPreferences
|
|
19153
|
-
});
|
|
19154
|
-
}
|
|
19155
|
-
//#endregion
|
|
19156
19154
|
//#region src/client/locales.ts
|
|
19157
19155
|
const NS = "dsh-chatgpt-subscription";
|
|
19158
19156
|
const dictionaries$1 = {
|
|
@@ -19190,19 +19188,6 @@ window.__ModuleLoader__.load({
|
|
|
19190
19188
|
proxyModeAuto: "系统代理(自动检测)",
|
|
19191
19189
|
proxyModeCustom: "自定义代理",
|
|
19192
19190
|
proxyModeDirect: "直连(禁用代理)",
|
|
19193
|
-
compactionRoute: "压缩模型",
|
|
19194
|
-
compactionRouteHint: "自动压缩时由哪个模型来写摘要。留空则继续用会话自己的模型,也就继续消耗那条线路的额度。",
|
|
19195
|
-
compactionRouteProvider: "线路",
|
|
19196
|
-
compactionRouteModel: "模型",
|
|
19197
|
-
compactionRouteSave: "保存",
|
|
19198
|
-
compactionRouteClear: "恢复会话模型",
|
|
19199
|
-
compactionRouteChange: "设置",
|
|
19200
|
-
compactionRouteFollow: "跟随会话模型(默认)",
|
|
19201
|
-
compactionRouteSaved: "已保存,下次压缩生效。",
|
|
19202
|
-
compactionRouteFailed: "保存失败",
|
|
19203
|
-
compactionRouteNoVideo: "该模型不接受视频:含视频的会话会回落到会话模型完成压缩。",
|
|
19204
|
-
compactionRouteNoImage: "该模型不接受图片:摘要里的截图会被替换为占位文本。",
|
|
19205
|
-
compactionRouteEmpty: "没有可用的线路——先登录任意一条线路再回来设置。",
|
|
19206
19191
|
customProxyUrl: "自定义代理地址",
|
|
19207
19192
|
customProxyUrlHint: "支持 HTTP/HTTPS/SOCKS5 代理地址,例如 http://127.0.0.1:7890",
|
|
19208
19193
|
customProxyUrlPlaceholder: "例如: http://127.0.0.1:7890",
|
|
@@ -19400,19 +19385,6 @@ window.__ModuleLoader__.load({
|
|
|
19400
19385
|
proxyModeAuto: "System Proxy (Auto-detect)",
|
|
19401
19386
|
proxyModeCustom: "Custom Proxy",
|
|
19402
19387
|
proxyModeDirect: "Direct (No Proxy)",
|
|
19403
|
-
compactionRoute: "Compaction model",
|
|
19404
|
-
compactionRouteHint: "Which model writes the summary when the context is compacted. Leave it unset to keep the conversation's own model — and that line's quota.",
|
|
19405
|
-
compactionRouteProvider: "Line",
|
|
19406
|
-
compactionRouteModel: "Model",
|
|
19407
|
-
compactionRouteSave: "Save",
|
|
19408
|
-
compactionRouteClear: "Use the conversation model",
|
|
19409
|
-
compactionRouteChange: "Change",
|
|
19410
|
-
compactionRouteFollow: "Follows the conversation model (default)",
|
|
19411
|
-
compactionRouteSaved: "Saved; it applies to the next compaction.",
|
|
19412
|
-
compactionRouteFailed: "Save failed",
|
|
19413
|
-
compactionRouteNoVideo: "This model takes no video: a session that carries video falls back to the conversation model.",
|
|
19414
|
-
compactionRouteNoImage: "This model takes no images: screenshots become placeholder text in the summary.",
|
|
19415
|
-
compactionRouteEmpty: "No route is available — sign in to one first.",
|
|
19416
19388
|
customProxyUrl: "Custom Proxy URL",
|
|
19417
19389
|
customProxyUrlHint: "Supports HTTP/HTTPS/SOCKS5 proxy URLs, e.g. http://127.0.0.1:7890",
|
|
19418
19390
|
customProxyUrlPlaceholder: "e.g. http://127.0.0.1:7890",
|
|
@@ -20290,19 +20262,6 @@ window.__ModuleLoader__.load({
|
|
|
20290
20262
|
proxyModeAuto: "Системный прокси (автоопределение)",
|
|
20291
20263
|
proxyModeCustom: "Свой прокси",
|
|
20292
20264
|
proxyModeDirect: "Напрямую (без прокси)",
|
|
20293
|
-
compactionRoute: "Модель сжатия",
|
|
20294
|
-
compactionRouteHint: "Какая модель пишет сводку при сжатии контекста. Если не выбрана, используется модель диалога — и её лимит.",
|
|
20295
|
-
compactionRouteProvider: "Линия",
|
|
20296
|
-
compactionRouteModel: "Модель",
|
|
20297
|
-
compactionRouteSave: "Сохранить",
|
|
20298
|
-
compactionRouteClear: "Модель диалога",
|
|
20299
|
-
compactionRouteChange: "Изменить",
|
|
20300
|
-
compactionRouteFollow: "Как в диалоге (по умолчанию)",
|
|
20301
|
-
compactionRouteSaved: "Сохранено; применится при следующем сжатии.",
|
|
20302
|
-
compactionRouteFailed: "Не удалось сохранить",
|
|
20303
|
-
compactionRouteNoVideo: "Модель не принимает видео: диалог с видео вернётся к модели диалога.",
|
|
20304
|
-
compactionRouteNoImage: "Модель не принимает изображения: скриншоты в сводке станут текстом-заглушкой.",
|
|
20305
|
-
compactionRouteEmpty: "Нет доступных линий — сначала войдите в любую.",
|
|
20306
20265
|
customProxyUrl: "Адрес своего прокси",
|
|
20307
20266
|
customProxyUrlHint: "Поддерживаются адреса HTTP/HTTPS/SOCKS5, например http://127.0.0.1:7890",
|
|
20308
20267
|
customProxyUrlPlaceholder: "например http://127.0.0.1:7890",
|
|
@@ -20566,11 +20525,7 @@ window.__ModuleLoader__.load({
|
|
|
20566
20525
|
cacheOutput: "Выходные токены",
|
|
20567
20526
|
cacheRequests: "Запросы",
|
|
20568
20527
|
cacheWrite: "Запись в кеш",
|
|
20569
|
-
cacheWrite5m: "Уровень 5 минут",
|
|
20570
|
-
cacheWrite1h: "Уровень 1 час",
|
|
20571
|
-
cacheWriteHint: "Запись — отдельная статья биллинга: запись на 1 ч стоит примерно вдвое дороже записи на 5 мин, а попадание продлевает её по исходному TTL. 0 на уровне означает, что сервис не сообщил запись для этого уровня (отсутствующий заголовок — молчание), а не то, что там ничего не записали.",
|
|
20572
20528
|
unknownMetric: "нет данных",
|
|
20573
|
-
cacheHint: "В пределах одной сессии: любое изменение системного промпта или списка инструментов сбрасывает весь префиксный кеш, поэтому держите набор инструментов стабильным, а новое добавляйте в конец — так доля попаданий выше.",
|
|
20574
20529
|
cacheExpired: "Сессия простаивала дольше времени жизни кеша, поэтому следующий ход заново обработает около {tokens} токенов.",
|
|
20575
20530
|
cacheDrift: "Состояние последнего префикса",
|
|
20576
20531
|
cacheDriftFirst: "Первый запрос (кеш пуст)",
|
|
@@ -20621,7 +20576,20 @@ window.__ModuleLoader__.load({
|
|
|
20621
20576
|
loading: "Загрузка…",
|
|
20622
20577
|
loginFailed: "Вход не выполнен",
|
|
20623
20578
|
requests: "запросов",
|
|
20624
|
-
tokens: "токенов"
|
|
20579
|
+
tokens: "токенов",
|
|
20580
|
+
compactionRoute: "Модель сжатия",
|
|
20581
|
+
compactionRouteHint: "Какая модель пишет сводку при сжатии контекста — только для диалогов этой линии. Если не выбрана, используется модель диалога — и её лимит.",
|
|
20582
|
+
compactionRouteProvider: "Линия",
|
|
20583
|
+
compactionRouteModel: "Модель",
|
|
20584
|
+
compactionRouteSave: "Сохранить",
|
|
20585
|
+
compactionRouteClear: "Модель диалога",
|
|
20586
|
+
compactionRouteChange: "Изменить",
|
|
20587
|
+
compactionRouteFollow: "Как в диалоге (по умолчанию)",
|
|
20588
|
+
compactionRouteSaved: "Сохранено; применится при следующем сжатии.",
|
|
20589
|
+
compactionRouteFailed: "Не удалось сохранить",
|
|
20590
|
+
compactionRouteNoVideo: "Модель не принимает видео: диалог с видео вернётся к модели диалога.",
|
|
20591
|
+
compactionRouteNoImage: "Модель не принимает изображения: скриншоты в сводке станут текстом-заглушкой.",
|
|
20592
|
+
compactionRouteEmpty: "Нет доступных линий — сначала войдите в любую."
|
|
20625
20593
|
};
|
|
20626
20594
|
//#endregion
|
|
20627
20595
|
//#region src/client/locales-ru/minimax-code.ts
|
|
@@ -20934,6 +20902,8 @@ window.__ModuleLoader__.load({
|
|
|
20934
20902
|
catalogSyncedNote: "Живой каталог синхронизирован: моделей {count}.",
|
|
20935
20903
|
noModels: "Доступных моделей нет.",
|
|
20936
20904
|
pricingNote: "Цены — официальный публичный прайс (доллары США за 1 млн токенов, вход / выход).",
|
|
20905
|
+
unservedBadge: "Нет в тарифе",
|
|
20906
|
+
unservedHint: "Модели, которых нет в текущем тарифе, по умолчанию скрыты; отметьте их здесь, чтобы показать принудительно.",
|
|
20937
20907
|
contextSection: "Контекстные окна",
|
|
20938
20908
|
contextHint: "Производитель не публикует контекстные окна по моделям, поэтому по умолчанию берётся 128k; здесь любую модель можно поправить. Неверное значение не сохраняется, а показывается ошибкой; восстановление сбрасывает переопределение.",
|
|
20939
20909
|
tokens: "токены",
|
|
@@ -22039,9 +22009,10 @@ window.__ModuleLoader__.load({
|
|
|
22039
22009
|
const window = [...quota.windows ?? []].sort((a, b) => (a.windowDurationMins ?? Infinity) - (b.windowDurationMins ?? Infinity))[0];
|
|
22040
22010
|
if (window !== void 0) {
|
|
22041
22011
|
const remaining = Math.max(0, 100 - window.usedPercent);
|
|
22012
|
+
const remainingText = formatPercent$1(remaining);
|
|
22042
22013
|
return {
|
|
22043
|
-
text: `${
|
|
22044
|
-
tooltip: `[Command Code] ${window.label}: ${
|
|
22014
|
+
text: `${remainingText}%`,
|
|
22015
|
+
tooltip: `[Command Code] ${window.label}: ${remainingText}% left`,
|
|
22045
22016
|
level: quotaLevel(remaining)
|
|
22046
22017
|
};
|
|
22047
22018
|
}
|
|
@@ -22100,9 +22071,10 @@ window.__ModuleLoader__.load({
|
|
|
22100
22071
|
const window = [...quota.windows ?? []].filter((candidate) => candidate.windowDurationMins !== null).sort((a, b) => (a.windowDurationMins ?? Infinity) - (b.windowDurationMins ?? Infinity))[0] ?? quota.windows[0];
|
|
22101
22072
|
if (window !== void 0) {
|
|
22102
22073
|
const remaining = Math.max(0, 100 - window.usedPercent);
|
|
22074
|
+
const remainingText = formatPercent$1(remaining);
|
|
22103
22075
|
return {
|
|
22104
|
-
text: `${
|
|
22105
|
-
tooltip: `[Kimi Code] ${window.label}: ${
|
|
22076
|
+
text: `${remainingText}%`,
|
|
22077
|
+
tooltip: `[Kimi Code] ${window.label}: ${remainingText}% left`,
|
|
22106
22078
|
level: quotaLevel(remaining)
|
|
22107
22079
|
};
|
|
22108
22080
|
}
|
|
@@ -22244,9 +22216,11 @@ window.__ModuleLoader__.load({
|
|
|
22244
22216
|
.dsha-kq-seg{border-radius:999px;display:block;height:100%;transition:width .9s cubic-bezier(.22,.61,.36,1)}
|
|
22245
22217
|
.dsha-kq-seg--recent{background:var(--kq-code)}
|
|
22246
22218
|
.dsha-kq-seg--rest{background:var(--kq-rest)}
|
|
22247
|
-
.dsha-kq-tip{background:var(--kq-tip-bg);border-radius:10px;bottom:calc(100% + 10px);color:var(--dsw-alias-bg-base,#fff);font-size:13px;line-height:1;opacity:0;padding:9px 14px;pointer-events:none;position:absolute;
|
|
22248
|
-
|
|
22249
|
-
|
|
22219
|
+
.dsha-kq-tip{background:var(--kq-tip-bg);border-radius:10px;bottom:calc(100% + 10px);color:var(--dsw-alias-bg-base,#fff);font-size:13px;line-height:1;left:var(--kq-tip-x,50%);opacity:0;padding:9px 14px;pointer-events:none;position:absolute;transform:translate(calc(-50% + var(--kq-tip-shift,0px)),4px);transition:opacity .16s ease-out,transform .16s ease-out;white-space:nowrap}
|
|
22220
|
+
/* 箭头不跟气泡的位移走:气泡被 --kq-tip-shift 收回卡片内时,箭头按
|
|
22221
|
+
--kq-tip-arrow 单独挪回「已用段末端」在气泡里的位置,所以它指的一直是那个数字。 */
|
|
22222
|
+
.dsha-kq-tip::after{border:6px solid transparent;border-top-color:var(--kq-tip-bg);content:"";left:var(--kq-tip-arrow,50%);margin-left:-6px;position:absolute;top:100%}
|
|
22223
|
+
.dsha-kq-barwrap:hover .dsha-kq-tip{opacity:1;transform:translate(calc(-50% + var(--kq-tip-shift,0px)),0)}
|
|
22250
22224
|
.dsha-kq-legend{align-items:center;color:var(--kq-fg-2);column-gap:16px;display:flex;flex-wrap:wrap;font-size:13px;margin-top:11px;row-gap:6px}
|
|
22251
22225
|
.dsha-kq-legend-item{align-items:center;display:inline-flex;gap:6px;white-space:nowrap}
|
|
22252
22226
|
.dsha-kq-legend-note{color:var(--kq-fg-3);white-space:nowrap}
|
|
@@ -54204,11 +54178,6 @@ window.__ModuleLoader__.load({
|
|
|
54204
54178
|
label: () => t("hubTitle"),
|
|
54205
54179
|
locale: NS
|
|
54206
54180
|
}, ProviderHubSectionWrapper));
|
|
54207
|
-
ctx.slots.inject("plugins.bundle.config", () => ctx.slots.register({
|
|
54208
|
-
name: "plugins.bundle.config",
|
|
54209
|
-
key: COMPACTION_ROUTE_PACKAGE,
|
|
54210
|
-
locale: NS
|
|
54211
|
-
}, CompactionRouteBundleConfig));
|
|
54212
54181
|
ctx.slots.inject("conversation.input.right", () => ctx.slots.register({
|
|
54213
54182
|
name: "conversation.input.right",
|
|
54214
54183
|
id: "codex-subscription-quota",
|