@eddyskywalker/dsh-chatgpt-subscription 0.35.0 → 0.36.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +34 -0
- package/README.md +6 -6
- package/lib/client.js +2064 -179
- package/lib/client.js.map +1 -1
- package/lib/index.js +206 -55
- package/lib/types/client/antigravity/AntigravitySection.d.ts.map +1 -1
- package/lib/types/client/claude/ClaudeSection.d.ts.map +1 -1
- package/lib/types/client/claude/useClaudeSection.d.ts.map +1 -1
- package/lib/types/client/cline-pass/ClinePassComposerQuota.d.ts +5 -2
- package/lib/types/client/cline-pass/ClinePassComposerQuota.d.ts.map +1 -1
- package/lib/types/client/cline-pass/ClinePassSection.d.ts.map +1 -1
- package/lib/types/client/cline-pass/api.d.ts +21 -1
- package/lib/types/client/cline-pass/api.d.ts.map +1 -1
- package/lib/types/client/command-code/CommandCodeSection.d.ts.map +1 -1
- package/lib/types/client/common/line-locale.d.ts +21 -0
- package/lib/types/client/common/line-locale.d.ts.map +1 -0
- package/lib/types/client/glm-coding-plan/GlmCodingPlanSection.d.ts.map +1 -1
- package/lib/types/client/glm-coding-plan/locales.d.ts +2 -2
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/kimi-code/KimiCodeSection.d.ts.map +1 -1
- package/lib/types/client/kimi-code/KimiModelCapabilities.d.ts.map +1 -1
- package/lib/types/client/kimi-code/locales.d.ts +2 -2
- package/lib/types/client/locales-ru/account-pool.d.ts +11 -0
- package/lib/types/client/locales-ru/account-pool.d.ts.map +1 -0
- package/lib/types/client/locales-ru/antigravity.d.ts +10 -0
- package/lib/types/client/locales-ru/antigravity.d.ts.map +1 -0
- package/lib/types/client/locales-ru/claude.d.ts +3 -0
- package/lib/types/client/locales-ru/claude.d.ts.map +1 -0
- package/lib/types/client/locales-ru/cline-pass.d.ts +11 -0
- package/lib/types/client/locales-ru/cline-pass.d.ts.map +1 -0
- package/lib/types/client/locales-ru/command-code.d.ts +9 -0
- package/lib/types/client/locales-ru/command-code.d.ts.map +1 -0
- package/lib/types/client/locales-ru/glm-coding-plan.d.ts +10 -0
- package/lib/types/client/locales-ru/glm-coding-plan.d.ts.map +1 -0
- package/lib/types/client/locales-ru/hub.d.ts +3 -0
- package/lib/types/client/locales-ru/hub.d.ts.map +1 -0
- package/lib/types/client/locales-ru/index.d.ts +27 -0
- package/lib/types/client/locales-ru/index.d.ts.map +1 -0
- package/lib/types/client/locales-ru/kimi-code.d.ts +10 -0
- package/lib/types/client/locales-ru/kimi-code.d.ts.map +1 -0
- package/lib/types/client/locales-ru/minimax-code.d.ts +9 -0
- package/lib/types/client/locales-ru/minimax-code.d.ts.map +1 -0
- package/lib/types/client/locales-ru/ollama.d.ts +10 -0
- package/lib/types/client/locales-ru/ollama.d.ts.map +1 -0
- package/lib/types/client/locales-ru/opendesign.d.ts +10 -0
- package/lib/types/client/locales-ru/opendesign.d.ts.map +1 -0
- package/lib/types/client/locales-ru/progress-updates.d.ts +8 -0
- package/lib/types/client/locales-ru/progress-updates.d.ts.map +1 -0
- package/lib/types/client/locales-ru/qoder.d.ts +11 -0
- package/lib/types/client/locales-ru/qoder.d.ts.map +1 -0
- package/lib/types/client/locales-ru/step-code.d.ts +9 -0
- package/lib/types/client/locales-ru/step-code.d.ts.map +1 -0
- package/lib/types/client/minimax-code/locales.d.ts +2 -2
- package/lib/types/client/ollama/OllamaSection.d.ts.map +1 -1
- package/lib/types/client/opendesign/OpenDesignSection.d.ts +4 -3
- package/lib/types/client/opendesign/OpenDesignSection.d.ts.map +1 -1
- package/lib/types/client/opendesign/locales.d.ts +108 -42
- package/lib/types/client/opendesign/locales.d.ts.map +1 -1
- package/lib/types/client/opendesign/styles.d.ts.map +1 -1
- package/lib/types/client/qoder/QoderSection.d.ts +2 -1
- package/lib/types/client/qoder/QoderSection.d.ts.map +1 -1
- package/lib/types/client/qoder/locales.d.ts +1 -1
- package/lib/types/client/step-code/StepCodeSection.d.ts.map +1 -1
- package/lib/types/client/step-code/locales.d.ts +2 -2
- package/lib/types/host/cline-pass/routes.d.ts +27 -3
- package/lib/types/host/cline-pass/routes.d.ts.map +1 -1
- package/lib/types/host/opendesign/client.d.ts +53 -0
- package/lib/types/host/opendesign/client.d.ts.map +1 -1
- package/lib/types/host/opendesign/routes.d.ts +4 -3
- package/lib/types/host/opendesign/routes.d.ts.map +1 -1
- package/lib/types/host/opendesign/types.d.ts +10 -0
- package/lib/types/host/opendesign/types.d.ts.map +1 -1
- package/lib/types/shared/cline-pass-contracts.d.ts +7 -0
- package/lib/types/shared/cline-pass-contracts.d.ts.map +1 -1
- package/lib/types/shared/opendesign-contracts.d.ts +35 -2
- package/lib/types/shared/opendesign-contracts.d.ts.map +1 -1
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -2860,6 +2860,82 @@ window.__ModuleLoader__.load({
|
|
|
2860
2860
|
"en-US": en$12
|
|
2861
2861
|
};
|
|
2862
2862
|
//#endregion
|
|
2863
|
+
//#region src/client/common/line-locale.ts
|
|
2864
|
+
/**
|
|
2865
|
+
* Locale plumbing shared by the provider detail pages.
|
|
2866
|
+
*
|
|
2867
|
+
* Every card used to render its `zh` dictionary object directly, which pinned
|
|
2868
|
+
* the whole page to Chinese whatever the active locale was: the dictionaries
|
|
2869
|
+
* carry a complete English half, but nothing ever asked the locale service for
|
|
2870
|
+
* it. A card now renders a dictionary-shaped view of the registered namespace
|
|
2871
|
+
* instead — same property access (`t.signIn`), but each read goes through the
|
|
2872
|
+
* registry, so the active locale (and any language pack registered later)
|
|
2873
|
+
* decides the text.
|
|
2874
|
+
*
|
|
2875
|
+
* The view keeps the fallback's own keys, in its own order, and resolves every
|
|
2876
|
+
* value lazily on read: the object identity is stable per namespace + fallback,
|
|
2877
|
+
* so a card can keep passing `t` into helpers, while the strings still follow a
|
|
2878
|
+
* locale switch without remounting.
|
|
2879
|
+
*/
|
|
2880
|
+
const NOOP_SUBSCRIBE = () => () => {};
|
|
2881
|
+
const ZERO_REVISION = () => 0;
|
|
2882
|
+
let runtime;
|
|
2883
|
+
let subscribe = NOOP_SUBSCRIBE;
|
|
2884
|
+
let revision = ZERO_REVISION;
|
|
2885
|
+
const bound = /* @__PURE__ */ new Map();
|
|
2886
|
+
/**
|
|
2887
|
+
* Hand the client locale runtime to this module.
|
|
2888
|
+
*
|
|
2889
|
+
* Called once from the plugin entry, before any card mounts. Rendering without
|
|
2890
|
+
* it (unit tests that mount a card bare) keeps the dictionary's own values,
|
|
2891
|
+
* which is what those tests assert against.
|
|
2892
|
+
*
|
|
2893
|
+
* @param locale - the plugin context's locale runtime.
|
|
2894
|
+
*/
|
|
2895
|
+
function installLineLocale(locale) {
|
|
2896
|
+
runtime = locale;
|
|
2897
|
+
subscribe = typeof locale?.subscribe === "function" ? (listener) => locale.subscribe(listener) : NOOP_SUBSCRIBE;
|
|
2898
|
+
revision = typeof locale?.getSnapshot === "function" ? () => locale.getSnapshot().revision : ZERO_REVISION;
|
|
2899
|
+
bound.clear();
|
|
2900
|
+
}
|
|
2901
|
+
/** Bound translator of one namespace, or `undefined` when no locale service exists. */
|
|
2902
|
+
function translatorOf(ns) {
|
|
2903
|
+
if (runtime === void 0) return void 0;
|
|
2904
|
+
const cached = bound.get(ns);
|
|
2905
|
+
if (cached !== void 0) return cached;
|
|
2906
|
+
let translate;
|
|
2907
|
+
try {
|
|
2908
|
+
translate = runtime.bind(ns);
|
|
2909
|
+
} catch {
|
|
2910
|
+
return;
|
|
2911
|
+
}
|
|
2912
|
+
bound.set(ns, translate);
|
|
2913
|
+
return translate;
|
|
2914
|
+
}
|
|
2915
|
+
/**
|
|
2916
|
+
* Dictionary-shaped view of one namespace, resolved through the active locale.
|
|
2917
|
+
*
|
|
2918
|
+
* @param ns - the namespace the card registered its dictionaries under.
|
|
2919
|
+
* @param fallback - the card's own `zh` dictionary: source of the key set and
|
|
2920
|
+
* of the value used when no locale service is installed.
|
|
2921
|
+
* @returns the same key shape as `fallback`, with values read at render time.
|
|
2922
|
+
*/
|
|
2923
|
+
function useLineDict(ns, fallback) {
|
|
2924
|
+
(0, react.useSyncExternalStore)(subscribe, revision, revision);
|
|
2925
|
+
return (0, react.useMemo)(() => liveDict(ns, fallback), [ns, fallback]);
|
|
2926
|
+
}
|
|
2927
|
+
/** Build the lazy dictionary view: one enumerable getter per fallback key. */
|
|
2928
|
+
function liveDict(ns, fallback) {
|
|
2929
|
+
const translate = translatorOf(ns);
|
|
2930
|
+
const view = {};
|
|
2931
|
+
for (const key of Object.keys(fallback)) Object.defineProperty(view, key, {
|
|
2932
|
+
enumerable: true,
|
|
2933
|
+
configurable: false,
|
|
2934
|
+
get: () => translate === void 0 ? fallback[key] : translate(key)
|
|
2935
|
+
});
|
|
2936
|
+
return view;
|
|
2937
|
+
}
|
|
2938
|
+
//#endregion
|
|
2863
2939
|
//#region src/client/antigravity/AntigravitySection.tsx
|
|
2864
2940
|
const api$14 = createLineApi("/antigravity/api", "Antigravity");
|
|
2865
2941
|
/** A gap in human units, so the idle reading is legible without arithmetic. */
|
|
@@ -2893,7 +2969,7 @@ window.__ModuleLoader__.load({
|
|
|
2893
2969
|
const [savingModel, setSavingModel] = (0, react.useState)(null);
|
|
2894
2970
|
/** Follow-up poll owed while the host refreshes the quota behind an answer. */
|
|
2895
2971
|
const quotaFollowUp = (0, react.useRef)(null);
|
|
2896
|
-
const t = zh$12;
|
|
2972
|
+
const t = useLineDict(NS_ANTIGRAVITY, zh$12);
|
|
2897
2973
|
const notifyChange = (0, react.useCallback)(() => {
|
|
2898
2974
|
onModelChange?.();
|
|
2899
2975
|
loadModelDirectory?.();
|
|
@@ -3631,7 +3707,7 @@ window.__ModuleLoader__.load({
|
|
|
3631
3707
|
const [apiKey, setApiKey] = (0, react.useState)("");
|
|
3632
3708
|
/** Follow-up poll owed while the host refreshes the quota behind an answer. */
|
|
3633
3709
|
const quotaFollowUp = (0, react.useRef)(null);
|
|
3634
|
-
const t = zh$11;
|
|
3710
|
+
const t = useLineDict(NS_COMMAND_CODE, zh$11);
|
|
3635
3711
|
const notifyChange = (0, react.useCallback)(() => {
|
|
3636
3712
|
onModelChange?.();
|
|
3637
3713
|
loadModelDirectory?.();
|
|
@@ -4475,7 +4551,6 @@ window.__ModuleLoader__.load({
|
|
|
4475
4551
|
* Capabilities are now short tags in their own columns, with the per-model
|
|
4476
4552
|
* detail kept in a hover title.
|
|
4477
4553
|
*/
|
|
4478
|
-
const t = zh$10;
|
|
4479
4554
|
/**
|
|
4480
4555
|
* Render one quota multiplier the way the official table states it: "2x", "3x".
|
|
4481
4556
|
*
|
|
@@ -4486,6 +4561,7 @@ window.__ModuleLoader__.load({
|
|
|
4486
4561
|
return `${value}x`;
|
|
4487
4562
|
}
|
|
4488
4563
|
function KimiModelCapabilities({ models }) {
|
|
4564
|
+
const t = useLineDict(NS_KIMI_CODE, zh$10);
|
|
4489
4565
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4490
4566
|
className: "dsha-cap-table",
|
|
4491
4567
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("table", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", { children: [
|
|
@@ -4554,12 +4630,15 @@ window.__ModuleLoader__.load({
|
|
|
4554
4630
|
return `${(cents / 100).toFixed(2)} ${code}`;
|
|
4555
4631
|
}
|
|
4556
4632
|
}
|
|
4557
|
-
|
|
4558
|
-
|
|
4559
|
-
|
|
4560
|
-
|
|
4561
|
-
|
|
4562
|
-
|
|
4633
|
+
function effortLabel(effort, t) {
|
|
4634
|
+
switch (effort) {
|
|
4635
|
+
case "low": return t.effortLow;
|
|
4636
|
+
case "high": return t.effortHigh;
|
|
4637
|
+
case "max": return t.effortMax;
|
|
4638
|
+
case "none": return t.effortNone;
|
|
4639
|
+
default: return effort;
|
|
4640
|
+
}
|
|
4641
|
+
}
|
|
4563
4642
|
/** Human label for the last request's prefix-drift cause. */
|
|
4564
4643
|
function driftLabel(cause, t) {
|
|
4565
4644
|
switch (cause) {
|
|
@@ -4584,7 +4663,7 @@ window.__ModuleLoader__.load({
|
|
|
4584
4663
|
const [connectionNotice, setConnectionNotice] = (0, react.useState)(null);
|
|
4585
4664
|
/** Follow-up poll owed while the host refreshes the quota behind an answer. */
|
|
4586
4665
|
const quotaFollowUp = (0, react.useRef)(null);
|
|
4587
|
-
const t = zh$10;
|
|
4666
|
+
const t = useLineDict(NS_KIMI_CODE, zh$10);
|
|
4588
4667
|
const notifyChange = (0, react.useCallback)(() => {
|
|
4589
4668
|
onModelChange?.();
|
|
4590
4669
|
loadModelDirectory?.();
|
|
@@ -5176,7 +5255,7 @@ window.__ModuleLoader__.load({
|
|
|
5176
5255
|
children: t.defaultEffortAuto
|
|
5177
5256
|
}), KIMI_CODE_REASONING_EFFORTS.map((effort) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5178
5257
|
value: effort,
|
|
5179
|
-
children:
|
|
5258
|
+
children: effortLabel(effort, t)
|
|
5180
5259
|
}, effort))]
|
|
5181
5260
|
})]
|
|
5182
5261
|
}),
|
|
@@ -8532,15 +8611,15 @@ window.__ModuleLoader__.load({
|
|
|
8532
8611
|
* (host 由随包目录生成,客户端不从模型名推断任何能力)。
|
|
8533
8612
|
*/
|
|
8534
8613
|
/** 区域的人类可读名,登录与 adopt 两条入口的结果都要说清楚落在哪一区。 */
|
|
8535
|
-
function regionLabel$1(region) {
|
|
8536
|
-
return region === "cn" ?
|
|
8614
|
+
function regionLabel$1(region, t) {
|
|
8615
|
+
return region === "cn" ? t.regionCn : t.regionIntl;
|
|
8537
8616
|
}
|
|
8538
8617
|
function GlmCodingPlanSection({ onModelChange } = {}) {
|
|
8539
8618
|
const { state, derived, actions } = useGlmCodingPlanSection({ onModelChange });
|
|
8540
8619
|
const { status, loading, busy, error, connection, adoptResult, pasteValue, region, pasteOpen, contextDrafts, savingModel } = state;
|
|
8541
8620
|
const { accounts, models, contextModels, overrideCount, login, quota, authenticated, poolLabels } = derived;
|
|
8542
8621
|
const { setRegion, login: startLogin, cancelLogin, submitPaste, setPasteValue, togglePaste, adopt, clearAdoptResult, accountAction, setStrategy, toggleModel, setAllModels, saveContextWindow, resetContextWindow, resetAllContextWindows, updateContextDraft, refreshQuota, refreshCatalog, testConnection } = actions;
|
|
8543
|
-
const t = zh$8;
|
|
8622
|
+
const t = useLineDict(NS_GLM_CODING_PLAN, zh$8);
|
|
8544
8623
|
if (loading) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
8545
8624
|
className: "dsha-page",
|
|
8546
8625
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
@@ -8599,7 +8678,7 @@ window.__ModuleLoader__.load({
|
|
|
8599
8678
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
8600
8679
|
className: "dsha-btn dsha-btn-primary",
|
|
8601
8680
|
disabled: busy !== null,
|
|
8602
|
-
"aria-label": `${t.addAccount}(${regionLabel$1(region)})`,
|
|
8681
|
+
"aria-label": `${t.addAccount}(${regionLabel$1(region, t)})`,
|
|
8603
8682
|
onClick: () => void startLogin(region),
|
|
8604
8683
|
children: busy === `login:${region}` ? t.authorizing : t.addAccount
|
|
8605
8684
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
@@ -8614,7 +8693,7 @@ window.__ModuleLoader__.load({
|
|
|
8614
8693
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
8615
8694
|
t.region,
|
|
8616
8695
|
": ",
|
|
8617
|
-
regionLabel$1(account.region)
|
|
8696
|
+
regionLabel$1(account.region, t)
|
|
8618
8697
|
] }),
|
|
8619
8698
|
account.accountName ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: account.accountName }) : null,
|
|
8620
8699
|
account.organizationId ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
@@ -8701,7 +8780,7 @@ window.__ModuleLoader__.load({
|
|
|
8701
8780
|
className: "dsha-row",
|
|
8702
8781
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
8703
8782
|
className: "dsha-value",
|
|
8704
|
-
children: adoptResult.adopted ? t.adoptAdopted.replace("{region}", regionLabel$1(adoptResult.region ?? region)) : adoptResult.reason === void 0 ? t.adoptNoAttempt : `${adoptReasonText$2(adoptResult.reason, t)} ${t.adoptFallback}`
|
|
8783
|
+
children: adoptResult.adopted ? t.adoptAdopted.replace("{region}", regionLabel$1(adoptResult.region ?? region, t)) : adoptResult.reason === void 0 ? t.adoptNoAttempt : `${adoptReasonText$2(adoptResult.reason, t)} ${t.adoptFallback}`
|
|
8705
8784
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
8706
8785
|
className: "dsha-btn",
|
|
8707
8786
|
disabled: busy !== null,
|
|
@@ -9277,7 +9356,7 @@ window.__ModuleLoader__.load({
|
|
|
9277
9356
|
const [connection, setConnection] = (0, react.useState)(null);
|
|
9278
9357
|
/** Follow-up poll owed while the host refreshes the quota behind an answer. */
|
|
9279
9358
|
const quotaFollowUp = (0, react.useRef)(null);
|
|
9280
|
-
const t = zh$7;
|
|
9359
|
+
const t = useLineDict(NS_CLAUDE, zh$7);
|
|
9281
9360
|
const notifyChange = (0, react.useCallback)(() => {
|
|
9282
9361
|
onModelChange?.();
|
|
9283
9362
|
loadModelDirectory?.();
|
|
@@ -9749,7 +9828,7 @@ window.__ModuleLoader__.load({
|
|
|
9749
9828
|
const { status, loading, busy, error, flow, connection, pasteValue, contextDrafts, savingModel } = state;
|
|
9750
9829
|
const { accounts, hasAdopted, contextModels, overrideCount, quota, windows, poolLabels } = derived;
|
|
9751
9830
|
const { login, cancelLogin, submitPaste, adopt, stopImporting, accountAction, setStrategy, relogin, refreshQuota, refreshCatalog, testConnection, toggleModel, setAllModels, updateEffort, updateCacheTtl, saveContextWindow, resetContextWindow, resetAllContextWindows, updateContextDraft, setPasteValue } = actions;
|
|
9752
|
-
const t = zh$7;
|
|
9831
|
+
const t = useLineDict(NS_CLAUDE, zh$7);
|
|
9753
9832
|
if (loading) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
9754
9833
|
className: "dsha-page",
|
|
9755
9834
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
@@ -10574,7 +10653,7 @@ window.__ModuleLoader__.load({
|
|
|
10574
10653
|
const setEffort = (0, react.useCallback)((value) => {
|
|
10575
10654
|
run("effort", () => API$4.setDefaultReasoningEffort(value === "" ? null : value));
|
|
10576
10655
|
}, [run]);
|
|
10577
|
-
const t = zh$6;
|
|
10656
|
+
const t = useLineDict(NS_OLLAMA, zh$6);
|
|
10578
10657
|
const pool = status?.pool;
|
|
10579
10658
|
const models = status?.models ?? [];
|
|
10580
10659
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [
|
|
@@ -11953,7 +12032,7 @@ window.__ModuleLoader__.load({
|
|
|
11953
12032
|
const { status, loading, busy, error, connection, adoptResult, pasteValue, profile, pasteOpen, contextDrafts, savingModel, quotaAccount, quotaPassword, quotaToken } = state;
|
|
11954
12033
|
const { accounts, models, contextModels, overrideCount, login, quota, authenticated, poolLabels, cache, cacheHitRatio: hitRatio, quotaCredential } = derived;
|
|
11955
12034
|
const { setProfile, login: startLogin, cancelLogin, submitPaste, setPasteValue, togglePaste, adopt, clearAdoptResult, accountAction, setStrategy, toggleModel, setAllModels, saveContextWindow, resetContextWindow, resetAllContextWindows, updateContextDraft, setDefaultReasoningEffort, setCacheRequestParams, refreshQuota, refreshCatalog, testConnection, setQuotaAccount, setQuotaPassword, setQuotaToken, submitQuotaPassword, submitQuotaToken, clearQuotaCredential } = actions;
|
|
11956
|
-
const t = zh$5;
|
|
12035
|
+
const t = useLineDict(NS_STEP_CODE, zh$5);
|
|
11957
12036
|
if (loading) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
11958
12037
|
className: "dsha-page",
|
|
11959
12038
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
@@ -12722,14 +12801,37 @@ window.__ModuleLoader__.load({
|
|
|
12722
12801
|
//#region src/client/cline-pass/api.ts
|
|
12723
12802
|
const api$7 = createLineApi(CLINE_PASS_ROUTE_PREFIX, "Cline Pass");
|
|
12724
12803
|
/**
|
|
12804
|
+
* Whether the host is refreshing the quota behind this answer.
|
|
12805
|
+
*
|
|
12806
|
+
* The field is optional by contract, because a host built before it existed
|
|
12807
|
+
* answers without it. Every caller only ever compares it to `true`, so "absent"
|
|
12808
|
+
* and "false" read the same — nothing is in flight — and a stale host degrades to
|
|
12809
|
+
* plain polling instead of crashing. Kept as one reader so that convention lives
|
|
12810
|
+
* in a single place rather than being re-derived at each call site.
|
|
12811
|
+
*/
|
|
12812
|
+
function quotaRefreshingOf(status) {
|
|
12813
|
+
return status.quotaRefreshing === true;
|
|
12814
|
+
}
|
|
12815
|
+
/**
|
|
12725
12816
|
* The Cline Pass settings API, as the card uses it.
|
|
12726
12817
|
*
|
|
12727
12818
|
* Deliberately the same envelope and the same fetch shape every other provider
|
|
12728
12819
|
* section uses, so the shared account-pool card and this helper read alike.
|
|
12729
12820
|
*/
|
|
12730
12821
|
var ClinePassApi = class {
|
|
12731
|
-
|
|
12732
|
-
|
|
12822
|
+
/**
|
|
12823
|
+
* One status read.
|
|
12824
|
+
*
|
|
12825
|
+
* A plain call is the GET the first paint, the 60 s poll and the composer
|
|
12826
|
+
* badge use: it is cheap and never fans out one upstream request per account.
|
|
12827
|
+
* `refresh` is the forced path — the same POST /usage the card's own button
|
|
12828
|
+
* drives — and the host answers it with `{ usage, status }`; only the status
|
|
12829
|
+
* half is returned, because every caller renders a status card rather than the
|
|
12830
|
+
* raw quota payload.
|
|
12831
|
+
*/
|
|
12832
|
+
status(refresh = false) {
|
|
12833
|
+
if (!refresh) return api$7.get("/status");
|
|
12834
|
+
return api$7.post("/usage", {}).then((outcome) => outcome.status);
|
|
12733
12835
|
}
|
|
12734
12836
|
updateSettings(patch) {
|
|
12735
12837
|
return api$7.post("/settings", patch).then(() => this.status());
|
|
@@ -13107,7 +13209,14 @@ window.__ModuleLoader__.load({
|
|
|
13107
13209
|
//#endregion
|
|
13108
13210
|
//#region src/client/cline-pass/ClinePassSection.tsx
|
|
13109
13211
|
const API$3 = new ClinePassApi();
|
|
13110
|
-
|
|
13212
|
+
/**
|
|
13213
|
+
* How often an open card re-reads the quota.
|
|
13214
|
+
*
|
|
13215
|
+
* The same 60 s every other line's card and composer badge uses: a window that
|
|
13216
|
+
* moves on a multi-hour scale does not need a faster poll, and a slower one
|
|
13217
|
+
* would leave a card visibly stale after the user spends a request.
|
|
13218
|
+
*/
|
|
13219
|
+
const QUOTA_POLL_MS = 6e4;
|
|
13111
13220
|
function detail$1(error) {
|
|
13112
13221
|
return error instanceof Error ? error.message : String(error);
|
|
13113
13222
|
}
|
|
@@ -13153,19 +13262,46 @@ window.__ModuleLoader__.load({
|
|
|
13153
13262
|
const [settingsForm, setSettingsForm] = (0, react.useState)(null);
|
|
13154
13263
|
const [history, setHistory] = (0, react.useState)(null);
|
|
13155
13264
|
const [loginFlow, setLoginFlow] = (0, react.useState)(null);
|
|
13156
|
-
|
|
13265
|
+
/** Follow-up poll owed while the host refreshes the quota behind an answer. */
|
|
13266
|
+
const quotaFollowUp = (0, react.useRef)(null);
|
|
13267
|
+
/**
|
|
13268
|
+
* One status read; `quiet` is every read nobody pressed a button for.
|
|
13269
|
+
*
|
|
13270
|
+
* A quiet read is silent on purpose: it never paints an error and never clears
|
|
13271
|
+
* one, so a poll that fails while a user reads the page, or types into a
|
|
13272
|
+
* settings field, does not change what is on screen. The manual actions below
|
|
13273
|
+
* still report their own failures loudly. The draft guards inside the two
|
|
13274
|
+
* setters are what keep a background answer from overwriting typed text.
|
|
13275
|
+
*/
|
|
13276
|
+
const loadStatus = (0, react.useCallback)(async (quiet = false) => {
|
|
13157
13277
|
try {
|
|
13158
13278
|
const next = await API$3.status();
|
|
13159
13279
|
setStatus(next);
|
|
13160
13280
|
setSettingsForm((current) => current ?? (next.settings === void 0 ? null : settingsFormOf$1(next)));
|
|
13161
|
-
setError(null);
|
|
13281
|
+
if (!quiet) setError(null);
|
|
13282
|
+
quotaFollowUp.current ??= createQuotaFollowUp();
|
|
13283
|
+
quotaFollowUp.current.observe(quotaRefreshingOf(next), () => {
|
|
13284
|
+
loadStatus(true);
|
|
13285
|
+
});
|
|
13162
13286
|
} catch (cause) {
|
|
13163
|
-
setError(detail$1(cause));
|
|
13287
|
+
if (!quiet) setError(detail$1(cause));
|
|
13164
13288
|
}
|
|
13165
13289
|
}, []);
|
|
13166
13290
|
(0, react.useEffect)(() => {
|
|
13167
|
-
|
|
13168
|
-
}, [
|
|
13291
|
+
loadStatus();
|
|
13292
|
+
}, [loadStatus]);
|
|
13293
|
+
(0, react.useEffect)(() => {
|
|
13294
|
+
const refreshWhenVisible = () => {
|
|
13295
|
+
if (document.visibilityState === "visible") loadStatus(true);
|
|
13296
|
+
};
|
|
13297
|
+
document.addEventListener("visibilitychange", refreshWhenVisible);
|
|
13298
|
+
const timer = window.setInterval(refreshWhenVisible, QUOTA_POLL_MS);
|
|
13299
|
+
return () => {
|
|
13300
|
+
window.clearInterval(timer);
|
|
13301
|
+
document.removeEventListener("visibilitychange", refreshWhenVisible);
|
|
13302
|
+
quotaFollowUp.current?.cancel();
|
|
13303
|
+
};
|
|
13304
|
+
}, [loadStatus]);
|
|
13169
13305
|
(0, react.useEffect)(() => {
|
|
13170
13306
|
if (status === null) return;
|
|
13171
13307
|
setDrafts((current) => {
|
|
@@ -13193,12 +13329,12 @@ window.__ModuleLoader__.load({
|
|
|
13193
13329
|
if (next.status === "complete") {
|
|
13194
13330
|
setNotice(zh$4.loginComplete.replace("{account}", next.accountAlias === "" ? "Cline Pass" : next.accountAlias));
|
|
13195
13331
|
setShowKeyForm(false);
|
|
13196
|
-
|
|
13332
|
+
loadStatus();
|
|
13197
13333
|
} else if (next.status === "failed") setError(zh$4.loginFailed.replace("{detail}", next.error));
|
|
13198
13334
|
}).catch((cause) => setError(detail$1(cause)));
|
|
13199
13335
|
}, Math.max(2, flow.intervalSeconds) * 1e3);
|
|
13200
13336
|
return () => window.clearInterval(timer);
|
|
13201
|
-
}, [loginFlow,
|
|
13337
|
+
}, [loginFlow, loadStatus]);
|
|
13202
13338
|
const startLogin = (0, react.useCallback)(() => {
|
|
13203
13339
|
setBusy("login");
|
|
13204
13340
|
setError(null);
|
|
@@ -13390,7 +13526,8 @@ window.__ModuleLoader__.load({
|
|
|
13390
13526
|
setNotice(zh$4.restartRequired);
|
|
13391
13527
|
}).catch((cause) => setError(detail$1(cause))).finally(() => setBusy(null));
|
|
13392
13528
|
}, [status, applyStatus]);
|
|
13393
|
-
const t = zh$4;
|
|
13529
|
+
const t = useLineDict(NS_CLINE_PASS, zh$4);
|
|
13530
|
+
const errorPrefix = t.error.split("{detail}")[0] ?? "";
|
|
13394
13531
|
const pool = status?.pool;
|
|
13395
13532
|
const accounts = (0, react.useMemo)(() => {
|
|
13396
13533
|
const raw = pool?.accounts ?? [];
|
|
@@ -13478,7 +13615,7 @@ window.__ModuleLoader__.load({
|
|
|
13478
13615
|
error !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
|
|
13479
13616
|
className: "dsha-notice",
|
|
13480
13617
|
style: { color: "var(--dsha-danger, #c0392b)" },
|
|
13481
|
-
children: [
|
|
13618
|
+
children: [errorPrefix, error]
|
|
13482
13619
|
}),
|
|
13483
13620
|
notice !== null && notice !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
13484
13621
|
className: "dsha-notice",
|
|
@@ -15315,15 +15452,15 @@ window.__ModuleLoader__.load({
|
|
|
15315
15452
|
* `defaultMaxTokens`),客户端不按模型名推断任何一项。与 OpenDesign 卡同一写法:
|
|
15316
15453
|
* 数据一行,散文进折叠区。
|
|
15317
15454
|
*/
|
|
15318
|
-
function qoderModelRowHint(model) {
|
|
15319
|
-
return `${formatTokenCount(model.contextWindow)} · ${model.supportsImages ? "text+image" : "text"} · ${model.reasoningEfforts.length === 0 ?
|
|
15455
|
+
function qoderModelRowHint(model, t = zh$3) {
|
|
15456
|
+
return `${formatTokenCount(model.contextWindow)} · ${model.supportsImages ? "text+image" : "text"} · ${model.reasoningEfforts.length === 0 ? t.modelRowNoEfforts : t.modelRowEfforts.replace("{list}", model.reasoningEfforts.join("/"))} · ${t.modelRowOutput.replace("{cap}", formatTokenCount(model.defaultMaxTokens))}`;
|
|
15320
15457
|
}
|
|
15321
15458
|
function QoderSection({ onModelChange } = {}) {
|
|
15322
15459
|
const { state, derived, actions } = useQoderSection({ onModelChange });
|
|
15323
15460
|
const { status, loading, busy, error, connection, adoptResult, pasteValue, region, pasteOpen, contextDrafts, savingModel } = state;
|
|
15324
15461
|
const { accounts, models, contextModels, overrideCount, login, quota, authenticated, poolLabels, cache, cacheHitRatio: hitRatio } = derived;
|
|
15325
15462
|
const { setRegion, login: startLogin, cancelLogin, submitPaste, setPasteValue, togglePaste, adopt, clearAdoptResult, accountAction, setStrategy, toggleModel, setAllModels, saveContextWindow, resetContextWindow, resetAllContextWindows, updateContextDraft, setDefaultReasoningEffort, refreshQuota, refreshCatalog, testConnection } = actions;
|
|
15326
|
-
const t = zh$3;
|
|
15463
|
+
const t = useLineDict(NS_QODER, zh$3);
|
|
15327
15464
|
if (loading) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
15328
15465
|
className: "dsha-page",
|
|
15329
15466
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
@@ -15645,7 +15782,7 @@ window.__ModuleLoader__.load({
|
|
|
15645
15782
|
items: models.map((model) => ({
|
|
15646
15783
|
id: model.id,
|
|
15647
15784
|
name: model.name,
|
|
15648
|
-
hint: qoderModelRowHint(model),
|
|
15785
|
+
hint: qoderModelRowHint(model, t),
|
|
15649
15786
|
enabled: model.enabled
|
|
15650
15787
|
})),
|
|
15651
15788
|
busy: busy !== null,
|
|
@@ -15969,18 +16106,29 @@ window.__ModuleLoader__.load({
|
|
|
15969
16106
|
saveSettings: "保存设置",
|
|
15970
16107
|
savingSettings: "保存中...",
|
|
15971
16108
|
limitsSection: "说明",
|
|
15972
|
-
usageSection: "
|
|
15973
|
-
usageHint: "
|
|
15974
|
-
usageRefresh: "
|
|
16109
|
+
usageSection: "套餐与额度",
|
|
16110
|
+
usageHint: "套餐档位和额度来自账号的账单摘要;浏览器授权登录的账号带控制 Key,可直接读,打开本页会自动读一次。粘贴的 API Key 没有控制 Key,请在控制台查看。",
|
|
16111
|
+
usageRefresh: "刷新额度",
|
|
15975
16112
|
usageRefreshing: "刷新中...",
|
|
15976
|
-
usageEmpty: "
|
|
15977
|
-
usageUnavailable: "
|
|
15978
|
-
usageBalance: "
|
|
16113
|
+
usageEmpty: "尚未读取额度。",
|
|
16114
|
+
usageUnavailable: "读不到额度:{detail}",
|
|
16115
|
+
usageBalance: "钱包余额 ${amount}",
|
|
15979
16116
|
usageReadAt: "读取于 {time}",
|
|
16117
|
+
usagePlan: "套餐 {plan}",
|
|
16118
|
+
usagePlanActive: "生效中",
|
|
16119
|
+
usagePlanInactive: "状态 {status}",
|
|
16120
|
+
usagePeriod: "本周期 {start} → {end}",
|
|
16121
|
+
usageSubscriptionCredits: "订阅额度 {credits} credits(${usd})",
|
|
16122
|
+
usageRechargeCredits: "充值额度 {credits} credits(${usd})",
|
|
16123
|
+
usageTotalCredits: "可用合计 {credits} credits(${usd})",
|
|
16124
|
+
usageTodayConsumed: "今日消耗 ${amount}",
|
|
16125
|
+
usageTotalConsumed: "累计消耗 ${amount}",
|
|
16126
|
+
usageUsageCount: "计费请求 {count} 次",
|
|
16127
|
+
usagePlanUnknown: "已读取额度,但上游未返回套餐档位。",
|
|
15980
16128
|
limitKey: "凭据存储在系统加密凭据库中,界面从不显示 Key 本身。",
|
|
15981
16129
|
limitGateway: "请求由 OpenDesign 网关服务,实际上游由网关决定。",
|
|
15982
16130
|
limitRoute: "模型路由按 provider id 抢占:若已有其他插件占用 opendesign,本卡仍可配置,但请求由对方服务。",
|
|
15983
|
-
limitQuota: "
|
|
16131
|
+
limitQuota: "套餐与额度读取只覆盖浏览器授权登录的账号;粘贴的 API Key 没有控制 Key,请在 OpenDesign Cloud 控制台查看用量。"
|
|
15984
16132
|
};
|
|
15985
16133
|
const en$2 = {
|
|
15986
16134
|
...accountPoolEn,
|
|
@@ -16055,18 +16203,29 @@ window.__ModuleLoader__.load({
|
|
|
16055
16203
|
saveSettings: "Save settings",
|
|
16056
16204
|
savingSettings: "Saving...",
|
|
16057
16205
|
limitsSection: "Notes",
|
|
16058
|
-
usageSection: "
|
|
16059
|
-
usageHint: "
|
|
16060
|
-
usageRefresh: "Refresh
|
|
16206
|
+
usageSection: "Plan and credits",
|
|
16207
|
+
usageHint: "The plan tier and credits come from the account's billing summary. Browser-signed-in accounts carry a control key and are read here automatically when this page opens; a pasted API key has none — check the console for it.",
|
|
16208
|
+
usageRefresh: "Refresh plan & credits",
|
|
16061
16209
|
usageRefreshing: "Refreshing...",
|
|
16062
|
-
usageEmpty: "No
|
|
16063
|
-
usageUnavailable: "Could not read the
|
|
16064
|
-
usageBalance: "
|
|
16210
|
+
usageEmpty: "No plan or credit reading yet.",
|
|
16211
|
+
usageUnavailable: "Could not read the plan and credits: {detail}",
|
|
16212
|
+
usageBalance: "Wallet balance ${amount}",
|
|
16065
16213
|
usageReadAt: "Read at {time}",
|
|
16214
|
+
usagePlan: "Plan {plan}",
|
|
16215
|
+
usagePlanActive: "active",
|
|
16216
|
+
usagePlanInactive: "status {status}",
|
|
16217
|
+
usagePeriod: "Period {start} → {end}",
|
|
16218
|
+
usageSubscriptionCredits: "Subscription credits {credits} (${usd})",
|
|
16219
|
+
usageRechargeCredits: "Top-up credits {credits} (${usd})",
|
|
16220
|
+
usageTotalCredits: "Total available {credits} credits (${usd})",
|
|
16221
|
+
usageTodayConsumed: "Consumed today ${amount}",
|
|
16222
|
+
usageTotalConsumed: "Consumed in total ${amount}",
|
|
16223
|
+
usageUsageCount: "Billed requests: {count}",
|
|
16224
|
+
usagePlanUnknown: "Credits were read, but the upstream named no plan tier.",
|
|
16066
16225
|
limitKey: "API keys live in the OS credential store; the card never shows the key itself.",
|
|
16067
16226
|
limitGateway: "Requests are served by the OpenDesign gateway, which chooses the actual upstream.",
|
|
16068
16227
|
limitRoute: "The route is claimed by provider id: if another plugin already serves opendesign, this card still configures the line but that provider answers the requests.",
|
|
16069
|
-
limitQuota: "
|
|
16228
|
+
limitQuota: "Plan and credit reads cover browser-signed-in accounts only; a pasted API key has no control key, so see usage in the OpenDesign Cloud console."
|
|
16070
16229
|
};
|
|
16071
16230
|
const dictionaries$2 = {
|
|
16072
16231
|
zh: zh$2,
|
|
@@ -16077,10 +16236,47 @@ window.__ModuleLoader__.load({
|
|
|
16077
16236
|
//#endregion
|
|
16078
16237
|
//#region src/client/opendesign/OpenDesignSection.tsx
|
|
16079
16238
|
const API$2 = new OpenDesignApi();
|
|
16080
|
-
const ERROR_DETAIL = zh$2.error.split("{detail}")[0] ?? "";
|
|
16081
16239
|
function detail(error) {
|
|
16082
16240
|
return error instanceof Error ? error.message : String(error);
|
|
16083
16241
|
}
|
|
16242
|
+
/**
|
|
16243
|
+
* The tier as the card spells it.
|
|
16244
|
+
*
|
|
16245
|
+
* The service answers lower case (`go`, `plus`, …); a single capitalized word
|
|
16246
|
+
* is what the plan cards on the pricing page use, and it keeps the row from
|
|
16247
|
+
* reading like a machine token next to "浏览器授权".
|
|
16248
|
+
*/
|
|
16249
|
+
function planName(plan) {
|
|
16250
|
+
if (plan === void 0 || plan === "") return "";
|
|
16251
|
+
return plan.slice(0, 1).toUpperCase() + plan.slice(1);
|
|
16252
|
+
}
|
|
16253
|
+
/** Integer credits with digit grouping; an absent figure stays absent. */
|
|
16254
|
+
function formatCredits(value) {
|
|
16255
|
+
if (value === null) return "—";
|
|
16256
|
+
const amount = Number(value);
|
|
16257
|
+
if (!Number.isSafeInteger(amount)) return value;
|
|
16258
|
+
try {
|
|
16259
|
+
return amount.toLocaleString();
|
|
16260
|
+
} catch {
|
|
16261
|
+
return value;
|
|
16262
|
+
}
|
|
16263
|
+
}
|
|
16264
|
+
/** A USD figure the service already strings, or the honest dash. */
|
|
16265
|
+
function formatUsd(value) {
|
|
16266
|
+
return value === null ? "—" : value;
|
|
16267
|
+
}
|
|
16268
|
+
/** ISO instant as the card's date, or the honest dash. */
|
|
16269
|
+
function formatIso(value) {
|
|
16270
|
+
if (value === null) return "—";
|
|
16271
|
+
const parsed = Date.parse(value);
|
|
16272
|
+
return Number.isFinite(parsed) ? formatAccountDate(parsed) : "—";
|
|
16273
|
+
}
|
|
16274
|
+
/** Subscription state in words; `active` is the one state worth naming plainly. */
|
|
16275
|
+
function planState(billing, labels) {
|
|
16276
|
+
const status = billing.status !== "" ? billing.status : billing.entitlementStatus;
|
|
16277
|
+
if (status === "" || status === "active") return labels.usagePlanActive;
|
|
16278
|
+
return labels.usagePlanInactive.replace("{status}", status);
|
|
16279
|
+
}
|
|
16084
16280
|
function settingsFormOf(status) {
|
|
16085
16281
|
return {
|
|
16086
16282
|
baseURL: status.settings.baseURL,
|
|
@@ -16091,14 +16287,88 @@ window.__ModuleLoader__.load({
|
|
|
16091
16287
|
};
|
|
16092
16288
|
}
|
|
16093
16289
|
/**
|
|
16290
|
+
* One account's plan and credit facts.
|
|
16291
|
+
*
|
|
16292
|
+
* Deliberately numbers, not a percentage bar: the summary states what is left
|
|
16293
|
+
* (subscription credits, top-up credits) and what was consumed, but not the
|
|
16294
|
+
* grant those figures are a share of, and this card does not invent a total to
|
|
16295
|
+
* divide by. A failed wallet read still shows the billing figures, because they
|
|
16296
|
+
* are different surfaces of the same account.
|
|
16297
|
+
*/
|
|
16298
|
+
function UsageCard(props) {
|
|
16299
|
+
const { entry, labels } = props;
|
|
16300
|
+
const billing = entry.billing;
|
|
16301
|
+
const credits = (creditsValue, usdValue) => ({
|
|
16302
|
+
credits: formatCredits(creditsValue),
|
|
16303
|
+
usd: formatUsd(usdValue)
|
|
16304
|
+
});
|
|
16305
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
16306
|
+
className: "dshod-quota",
|
|
16307
|
+
children: [
|
|
16308
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
16309
|
+
className: "dshod-quota-head",
|
|
16310
|
+
children: [
|
|
16311
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
16312
|
+
className: "dshod-quota-account",
|
|
16313
|
+
children: entry.alias
|
|
16314
|
+
}),
|
|
16315
|
+
billing !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
16316
|
+
className: "dshod-quota-plan",
|
|
16317
|
+
children: labels.usagePlan.replace("{plan}", planName(billing.plan))
|
|
16318
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
16319
|
+
className: "dshod-quota-status",
|
|
16320
|
+
children: planState(billing, labels)
|
|
16321
|
+
})] }),
|
|
16322
|
+
billing === void 0 && entry.ok && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
16323
|
+
className: "dshod-quota-status",
|
|
16324
|
+
children: labels.usagePlanUnknown
|
|
16325
|
+
})
|
|
16326
|
+
]
|
|
16327
|
+
}),
|
|
16328
|
+
billing !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(billing.periodStart !== null || billing.periodEnd !== null) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
16329
|
+
className: "dshod-quota-meta",
|
|
16330
|
+
children: labels.usagePeriod.replace("{start}", formatIso(billing.periodStart)).replace("{end}", formatIso(billing.periodEnd))
|
|
16331
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
16332
|
+
className: "dshod-quota-grid",
|
|
16333
|
+
children: [
|
|
16334
|
+
(() => {
|
|
16335
|
+
const value = credits(billing.subscriptionCredits, billing.subscriptionCreditsUsd);
|
|
16336
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: labels.usageSubscriptionCredits.replace("{credits}", value.credits).replace("{usd}", value.usd) });
|
|
16337
|
+
})(),
|
|
16338
|
+
(() => {
|
|
16339
|
+
const value = credits(billing.rechargeCredits, billing.rechargeCreditsUsd);
|
|
16340
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: labels.usageRechargeCredits.replace("{credits}", value.credits).replace("{usd}", value.usd) });
|
|
16341
|
+
})(),
|
|
16342
|
+
(() => {
|
|
16343
|
+
const value = credits(billing.totalAvailableCredits, billing.totalAvailableCreditsUsd);
|
|
16344
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: labels.usageTotalCredits.replace("{credits}", value.credits).replace("{usd}", value.usd) });
|
|
16345
|
+
})(),
|
|
16346
|
+
billing.todayConsumedUsd !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: labels.usageTodayConsumed.replace("{amount}", billing.todayConsumedUsd) }),
|
|
16347
|
+
billing.totalConsumedUsd !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: labels.usageTotalConsumed.replace("{amount}", billing.totalConsumedUsd) }),
|
|
16348
|
+
billing.usageCount !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: labels.usageUsageCount.replace("{count}", String(billing.usageCount)) })
|
|
16349
|
+
]
|
|
16350
|
+
})] }),
|
|
16351
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
16352
|
+
className: "dshod-quota-meta",
|
|
16353
|
+
children: [entry.balanceUsd !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [labels.usageBalance.replace("{amount}", entry.balanceUsd), " · "] }), labels.usageReadAt.replace("{time}", formatAccountDate(entry.fetchedAt))]
|
|
16354
|
+
}),
|
|
16355
|
+
!entry.ok && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
16356
|
+
className: "dshod-warning",
|
|
16357
|
+
children: labels.usageUnavailable.replace("{detail}", entry.error)
|
|
16358
|
+
})
|
|
16359
|
+
]
|
|
16360
|
+
});
|
|
16361
|
+
}
|
|
16362
|
+
/**
|
|
16094
16363
|
* The OpenDesign tab.
|
|
16095
16364
|
*
|
|
16096
16365
|
* The account card, its badges and the rotation picker are the shared
|
|
16097
16366
|
* {@link AccountPoolSection}, so this line looks like every other provider tab
|
|
16098
16367
|
* by construction. What is written here is only what is genuinely OpenDesign's:
|
|
16099
|
-
* pasting a console-issued API key
|
|
16100
|
-
*
|
|
16101
|
-
*
|
|
16368
|
+
* pasting a console-issued API key, the catalog sync, and the plan/credit card
|
|
16369
|
+
* fed by the billing summary. That summary needs a control key, which only a
|
|
16370
|
+
* browser sign-in issues: a pasted key gets the explanation, never an invented
|
|
16371
|
+
* figure.
|
|
16102
16372
|
*/
|
|
16103
16373
|
function OpenDesignSection(props) {
|
|
16104
16374
|
const [status, setStatus] = (0, react.useState)(null);
|
|
@@ -16125,6 +16395,33 @@ window.__ModuleLoader__.load({
|
|
|
16125
16395
|
(0, react.useEffect)(() => {
|
|
16126
16396
|
reload();
|
|
16127
16397
|
}, [reload]);
|
|
16398
|
+
const autoUsageRead = (0, react.useRef)(false);
|
|
16399
|
+
/**
|
|
16400
|
+
* Read plan/credits + wallet for every account that has a control key.
|
|
16401
|
+
*
|
|
16402
|
+
* The card fires this once when it opens. Status only carries readings taken
|
|
16403
|
+
* during this host process, so without it a fresh page shows "尚未读取" until
|
|
16404
|
+
* the user finds the refresh button — which is exactly how the plan and the
|
|
16405
|
+
* credits came to look missing. Silent mode raises no banner: a pool whose
|
|
16406
|
+
* only account is a pasted key has nothing to read, and that is already
|
|
16407
|
+
* explained in the section hint.
|
|
16408
|
+
*/
|
|
16409
|
+
const loadUsage = (0, react.useCallback)(async (silent) => {
|
|
16410
|
+
try {
|
|
16411
|
+
const outcome = await API$2.readUsage();
|
|
16412
|
+
setStatus(outcome.status);
|
|
16413
|
+
if (!silent) setNotice(outcome.usage.accounts.some((account) => account.ok) ? "" : zh$2.usageEmpty);
|
|
16414
|
+
} catch (cause) {
|
|
16415
|
+
if (!silent) setError(detail(cause));
|
|
16416
|
+
}
|
|
16417
|
+
}, []);
|
|
16418
|
+
(0, react.useEffect)(() => {
|
|
16419
|
+
if (status === null || autoUsageRead.current) return;
|
|
16420
|
+
if (!status.pool.accounts.some((account) => account.authKind === "oauth")) return;
|
|
16421
|
+
autoUsageRead.current = true;
|
|
16422
|
+
if (status.usage !== null) return;
|
|
16423
|
+
loadUsage(true);
|
|
16424
|
+
}, [status, loadUsage]);
|
|
16128
16425
|
(0, react.useEffect)(() => {
|
|
16129
16426
|
if (status === null) return;
|
|
16130
16427
|
setDrafts((current) => {
|
|
@@ -16334,7 +16631,8 @@ window.__ModuleLoader__.load({
|
|
|
16334
16631
|
setNotice(zh$2.saved);
|
|
16335
16632
|
}).catch((cause) => setError(detail(cause))).finally(() => setBusy(null));
|
|
16336
16633
|
}, [settingsForm, applyStatus]);
|
|
16337
|
-
const t = zh$2;
|
|
16634
|
+
const t = useLineDict(NS_OPENDESIGN, zh$2);
|
|
16635
|
+
const errorPrefix = t.error.split("{detail}")[0] ?? "";
|
|
16338
16636
|
const pool = status?.pool;
|
|
16339
16637
|
const accounts = pool?.accounts ?? [];
|
|
16340
16638
|
const models = status?.models ?? [];
|
|
@@ -16362,7 +16660,7 @@ window.__ModuleLoader__.load({
|
|
|
16362
16660
|
error !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
|
|
16363
16661
|
className: "dsha-notice",
|
|
16364
16662
|
style: { color: "var(--dsha-danger, #c0392b)" },
|
|
16365
|
-
children: [
|
|
16663
|
+
children: [errorPrefix, error]
|
|
16366
16664
|
}),
|
|
16367
16665
|
notice !== null && notice !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
16368
16666
|
className: "dsha-notice",
|
|
@@ -16400,8 +16698,10 @@ window.__ModuleLoader__.load({
|
|
|
16400
16698
|
}),
|
|
16401
16699
|
renderDetails: (account) => {
|
|
16402
16700
|
const reading = status?.usage?.accounts.find((entry) => entry.accountId === account.id);
|
|
16701
|
+
const plan = planName(reading?.billing?.plan ?? account.plan);
|
|
16702
|
+
const state = reading?.billing === void 0 ? "" : ` · ${planState(reading.billing, t)}`;
|
|
16403
16703
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
16404
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [account.authKind === "oauth" ? t.oauthAccount : t.apiKeyAccount,
|
|
16704
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [account.authKind === "oauth" ? t.oauthAccount : t.apiKeyAccount, plan !== "" ? ` · ${plan}${state}` : ""] }),
|
|
16405
16705
|
reading !== void 0 && reading.ok && reading.balanceUsd !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
16406
16706
|
t.usageBalance.replace("{amount}", reading.balanceUsd),
|
|
16407
16707
|
" · ",
|
|
@@ -16573,6 +16873,33 @@ window.__ModuleLoader__.load({
|
|
|
16573
16873
|
})
|
|
16574
16874
|
]
|
|
16575
16875
|
}),
|
|
16876
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
16877
|
+
className: "dsha-group",
|
|
16878
|
+
children: [
|
|
16879
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
16880
|
+
className: "dsha-grouphead",
|
|
16881
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t.usageSection }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
16882
|
+
className: "dsha-btn",
|
|
16883
|
+
disabled: busyAny,
|
|
16884
|
+
onClick: refreshUsage,
|
|
16885
|
+
children: busy === "usage" ? t.usageRefreshing : t.usageRefresh
|
|
16886
|
+
})]
|
|
16887
|
+
}),
|
|
16888
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
16889
|
+
className: "dsha-muted",
|
|
16890
|
+
style: { fontSize: 12 },
|
|
16891
|
+
children: t.usageHint
|
|
16892
|
+
}),
|
|
16893
|
+
(status?.usage === null || status?.usage === void 0) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
16894
|
+
className: "dsha-empty",
|
|
16895
|
+
children: t.usageEmpty
|
|
16896
|
+
}),
|
|
16897
|
+
(status?.usage?.accounts ?? []).map((entry) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(UsageCard, {
|
|
16898
|
+
entry,
|
|
16899
|
+
labels: t
|
|
16900
|
+
}, entry.accountId))
|
|
16901
|
+
]
|
|
16902
|
+
}),
|
|
16576
16903
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
16577
16904
|
className: "dsha-group",
|
|
16578
16905
|
children: [
|
|
@@ -16671,37 +16998,6 @@ window.__ModuleLoader__.load({
|
|
|
16671
16998
|
})
|
|
16672
16999
|
]
|
|
16673
17000
|
}),
|
|
16674
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
16675
|
-
className: "dsha-group",
|
|
16676
|
-
children: [
|
|
16677
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
16678
|
-
className: "dsha-grouphead",
|
|
16679
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t.usageSection }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
16680
|
-
className: "dsha-btn",
|
|
16681
|
-
disabled: busyAny,
|
|
16682
|
-
onClick: refreshUsage,
|
|
16683
|
-
children: busy === "usage" ? t.usageRefreshing : t.usageRefresh
|
|
16684
|
-
})]
|
|
16685
|
-
}),
|
|
16686
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
16687
|
-
className: "dsha-muted",
|
|
16688
|
-
style: { fontSize: 12 },
|
|
16689
|
-
children: t.usageHint
|
|
16690
|
-
}),
|
|
16691
|
-
(status?.usage === null || status?.usage === void 0) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
16692
|
-
className: "dsha-empty",
|
|
16693
|
-
children: t.usageEmpty
|
|
16694
|
-
}),
|
|
16695
|
-
status?.usage !== null && status?.usage !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: status.usage.accounts.filter((account) => !account.ok).map((account) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
|
|
16696
|
-
className: "dshod-warning",
|
|
16697
|
-
children: [
|
|
16698
|
-
account.alias,
|
|
16699
|
-
": ",
|
|
16700
|
-
t.usageUnavailable.replace("{detail}", account.error)
|
|
16701
|
-
]
|
|
16702
|
-
}, account.accountId)) })
|
|
16703
|
-
]
|
|
16704
|
-
}),
|
|
16705
17001
|
settingsForm !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
16706
17002
|
className: "dsha-group",
|
|
16707
17003
|
children: [
|
|
@@ -17772,6 +18068,1670 @@ window.__ModuleLoader__.load({
|
|
|
17772
18068
|
}
|
|
17773
18069
|
};
|
|
17774
18070
|
//#endregion
|
|
18071
|
+
//#region src/client/progress-updates/locales.ts
|
|
18072
|
+
/**
|
|
18073
|
+
* 「进展更新」在 locale 服务里的命名空间。
|
|
18074
|
+
*
|
|
18075
|
+
* 跟着本插件其余线路的命名习惯走(`dsh-kimi-code`、`dsh-step-code`、`dsh-ollama`
|
|
18076
|
+
* ……都是「dsh-<线路>」):新线路并入本插件的字典体系,而不是另开一个与包名无关
|
|
18077
|
+
* 的命名空间。
|
|
18078
|
+
*/
|
|
18079
|
+
const NS_PROGRESS_UPDATES = "dsh-progress-updates";
|
|
18080
|
+
/**
|
|
18081
|
+
* 中文文案。
|
|
18082
|
+
*
|
|
18083
|
+
* 键名沿用本插件其余字典的扁平驼峰(`hubTitle`、`imageToolRunning` 那一套),
|
|
18084
|
+
* 不另起一套点号命名——同一份 index.tsx 里两种命名风格会让「这条键属于哪张表」
|
|
18085
|
+
* 变成要靠记忆的事。
|
|
18086
|
+
*/
|
|
18087
|
+
const zh = {
|
|
18088
|
+
/** 设置页导航里的那一格,也是侧栏页签的标题。 */
|
|
18089
|
+
navTitle: "进展更新",
|
|
18090
|
+
progressTitle: "进展更新",
|
|
18091
|
+
/** 右侧栏 guide 卡片标题下的一行说明。 */
|
|
18092
|
+
progressGuideNote: "agent 汇报的每一步进展,都收在这里",
|
|
18093
|
+
markdownCopy: "复制",
|
|
18094
|
+
markdownCopied: "已复制",
|
|
18095
|
+
markdownFootnotes: "脚注",
|
|
18096
|
+
progressLatest: "最新",
|
|
18097
|
+
progressCount: "共 {n} 条",
|
|
18098
|
+
progressExpand: "展开这条进展",
|
|
18099
|
+
progressCollapse: "收起这条进展",
|
|
18100
|
+
progressEmptyTitle: "还没有进展更新",
|
|
18101
|
+
progressEmptyHint: "agent 开始多步任务后,会在这里汇报它进行到哪一步。",
|
|
18102
|
+
rowPending: "进展更新",
|
|
18103
|
+
rowRunning: "进行中",
|
|
18104
|
+
rowDone: "已汇报",
|
|
18105
|
+
rowError: "未发出",
|
|
18106
|
+
rowExpand: "展开这条进展的详情",
|
|
18107
|
+
rowCollapse: "收起这条进展的详情",
|
|
18108
|
+
settingsHint: "进展更新会让 agent 在多步任务中主动汇报进度。打开面板可以看它到目前为止的全部汇报。",
|
|
18109
|
+
settingsOpen: "打开进展面板",
|
|
18110
|
+
settingsEnabledName: "进展更新",
|
|
18111
|
+
settingsEnabledNote: "让 agent 在对话中发布进展更新",
|
|
18112
|
+
settingsThresholdName: "催促阈值",
|
|
18113
|
+
settingsThresholdNote: "连续这么多轮没有进展时,提醒 agent 汇报一次",
|
|
18114
|
+
settingsPanelName: "进展面板",
|
|
18115
|
+
settingsPanelNote: "在右侧栏查看本次会话的全部进展",
|
|
18116
|
+
settingsUnavailable: "这项设置当前不可修改(宿主没有开放配置表单)",
|
|
18117
|
+
settingsSaveFailed: "保存失败,请稍后再试"
|
|
18118
|
+
};
|
|
18119
|
+
/** 英文对照,键集与 zh 完全一致。 */
|
|
18120
|
+
const en = {
|
|
18121
|
+
navTitle: "Progress updates",
|
|
18122
|
+
progressTitle: "Progress updates",
|
|
18123
|
+
progressGuideNote: "Every step the agent reports, collected here",
|
|
18124
|
+
markdownCopy: "Copy",
|
|
18125
|
+
markdownCopied: "Copied",
|
|
18126
|
+
markdownFootnotes: "Footnotes",
|
|
18127
|
+
progressLatest: "Latest",
|
|
18128
|
+
progressCount: "{n} total",
|
|
18129
|
+
progressExpand: "Expand this update",
|
|
18130
|
+
progressCollapse: "Collapse this update",
|
|
18131
|
+
progressEmptyTitle: "No progress updates yet",
|
|
18132
|
+
progressEmptyHint: "Once the agent starts multi-step work, it reports how far it has got right here.",
|
|
18133
|
+
rowPending: "Progress update",
|
|
18134
|
+
rowRunning: "Reporting",
|
|
18135
|
+
rowDone: "Reported",
|
|
18136
|
+
rowError: "Not reported",
|
|
18137
|
+
rowExpand: "Expand this progress update",
|
|
18138
|
+
rowCollapse: "Collapse this progress update",
|
|
18139
|
+
settingsHint: "Progress updates let the agent report how far multi-step work has got. Open the panel to read everything it has reported so far.",
|
|
18140
|
+
settingsOpen: "Open progress panel",
|
|
18141
|
+
settingsEnabledName: "Progress updates",
|
|
18142
|
+
settingsEnabledNote: "Let the agent post progress updates in the conversation",
|
|
18143
|
+
settingsThresholdName: "Nudge threshold",
|
|
18144
|
+
settingsThresholdNote: "Remind the agent after this many rounds without an update",
|
|
18145
|
+
settingsPanelName: "Progress panel",
|
|
18146
|
+
settingsPanelNote: "See every update from this session in the right sidebar",
|
|
18147
|
+
settingsUnavailable: "This setting cannot be changed right now (the host serves no config form)",
|
|
18148
|
+
settingsSaveFailed: "Could not save. Try again in a moment."
|
|
18149
|
+
};
|
|
18150
|
+
/** 与其余线路同形的字典包(四个内置语言 id 都指向那两份)。 */
|
|
18151
|
+
const dictionaries = {
|
|
18152
|
+
zh,
|
|
18153
|
+
"zh-CN": zh,
|
|
18154
|
+
en,
|
|
18155
|
+
"en-US": en
|
|
18156
|
+
};
|
|
18157
|
+
//#endregion
|
|
18158
|
+
//#region src/client/locales-ru/account-pool.ts
|
|
18159
|
+
const accountPoolRu = {
|
|
18160
|
+
accountPool: "Аккаунты",
|
|
18161
|
+
addAccount: "Добавить аккаунт",
|
|
18162
|
+
accountCount: "Аккаунтов в системе: {count}",
|
|
18163
|
+
primaryAccount: "Основной",
|
|
18164
|
+
activeAccount: "Используется",
|
|
18165
|
+
setPrimary: "Сделать основным",
|
|
18166
|
+
deleteAccount: "Удалить",
|
|
18167
|
+
cooling: "В паузе",
|
|
18168
|
+
cooldownLeft: "осталось {minutes} мин",
|
|
18169
|
+
cooldownRemaining: "осталось {minutes} мин {seconds} с",
|
|
18170
|
+
cooldownRemainingSeconds: "осталось {seconds} с",
|
|
18171
|
+
clearCooldown: "Сбросить паузу",
|
|
18172
|
+
needsRelogin: "Нужен повторный вход",
|
|
18173
|
+
relogin: "Войти заново",
|
|
18174
|
+
rotationStrategy: "Порядок переключения",
|
|
18175
|
+
strategySequential: "По очереди (основной первым, переключение при 429)",
|
|
18176
|
+
strategyRoundRobin: "По кругу (равномерно между аккаунтами)",
|
|
18177
|
+
strategySticky: "Закрепление (держать текущий аккаунт до лимита)",
|
|
18178
|
+
noAccounts: "Аккаунтов пока нет. Нажмите «Добавить аккаунт», чтобы авторизоваться.",
|
|
18179
|
+
email: "Почта",
|
|
18180
|
+
expires: "Токен истекает",
|
|
18181
|
+
lastUsed: "Последний вызов",
|
|
18182
|
+
accountId: "ID аккаунта",
|
|
18183
|
+
accountQuota: "Квота",
|
|
18184
|
+
quotaNone: "Квота ещё не прочитана",
|
|
18185
|
+
quotaSnapshot: "Снимок {time}",
|
|
18186
|
+
quotaResets: "Сброс",
|
|
18187
|
+
quotaExhausted: "Исчерпано",
|
|
18188
|
+
quotaWindow: "Окно лимита",
|
|
18189
|
+
quotaUsed: "использовано",
|
|
18190
|
+
quotaFactsScope: "Это данные текущего аккаунта; прогресс каждого аккаунта виден на его карточке выше.",
|
|
18191
|
+
composerLabel: "Квота"
|
|
18192
|
+
};
|
|
18193
|
+
//#endregion
|
|
18194
|
+
//#region src/client/locales-ru/antigravity.ts
|
|
18195
|
+
const dictionary$12 = {
|
|
18196
|
+
...accountPoolRu,
|
|
18197
|
+
title: "Antigravity",
|
|
18198
|
+
pageDesc: "Войдите в Google Antigravity / Cloud Code Assist и смотрите общую квоту текущего аккаунта.",
|
|
18199
|
+
account: "Вход выполнен",
|
|
18200
|
+
signedIn: "Вход выполнен",
|
|
18201
|
+
signedOut: "Вход не выполнен",
|
|
18202
|
+
accountPool: "Аккаунты",
|
|
18203
|
+
addAccount: "Добавить аккаунт",
|
|
18204
|
+
primaryAccount: "Основной",
|
|
18205
|
+
activeAccount: "Используется",
|
|
18206
|
+
setPrimary: "Сделать основным",
|
|
18207
|
+
deleteAccount: "Удалить",
|
|
18208
|
+
cooling: "В паузе",
|
|
18209
|
+
clearCooldown: "Сбросить паузу",
|
|
18210
|
+
rotationStrategy: "Порядок переключения",
|
|
18211
|
+
strategySequential: "По очереди (основной первым, переключение при 429)",
|
|
18212
|
+
strategyRoundRobin: "По кругу (равномерно между аккаунтами)",
|
|
18213
|
+
strategySticky: "Закрепление (держать текущий аккаунт до лимита)",
|
|
18214
|
+
noAccounts: "Аккаунтов пока нет. Нажмите «Добавить аккаунт», чтобы авторизоваться.",
|
|
18215
|
+
plan: "Тариф",
|
|
18216
|
+
accountId: "ID аккаунта",
|
|
18217
|
+
expires: "Токен истекает",
|
|
18218
|
+
signInAgain: "Войти заново",
|
|
18219
|
+
refreshToken: "Обновить токен",
|
|
18220
|
+
signOut: "Выйти",
|
|
18221
|
+
signIn: "Войти",
|
|
18222
|
+
signingIn: "Вход…",
|
|
18223
|
+
connection: "Подключение",
|
|
18224
|
+
modelsHint: "Отмеченные модели появятся в списке моделей диалога DSH; если снять все отметки или выключить переключатель на карточке обзора, провайдер скроется из списка.",
|
|
18225
|
+
modelsSection: "Модели",
|
|
18226
|
+
selectAll: "Выбрать все",
|
|
18227
|
+
unselectAll: "Снять все",
|
|
18228
|
+
enhanced: "Дополнительные возможности",
|
|
18229
|
+
defaultReasoningEffort: "Уровень рассуждений по умолчанию",
|
|
18230
|
+
defaultReasoningEffortHint: "Уровень рассуждений для моделей, которые его поддерживают, когда в диалоге он не задан явно.",
|
|
18231
|
+
defaultEffortAuto: "По умолчанию у провайдера",
|
|
18232
|
+
contextWindowSection: "Контекстное окно модели",
|
|
18233
|
+
contextWindowHint: "По умолчанию — как в спецификации модели; можно задать свою ёмкость, которую DSH использует при сжатии и определении переполнения (например, 1M, 512K, 200K).",
|
|
18234
|
+
contextWindowReset: "Вернуть значение по умолчанию",
|
|
18235
|
+
contextWindowResetAll: "Вернуть все значения",
|
|
18236
|
+
contextWindowResetAllConfirm: "Вернуть к значениям по умолчанию все изменённые контекстные окна?",
|
|
18237
|
+
contextWindowNoneEnabled: "Ни одна модель не отмечена. Отметьте её выше — и здесь появятся настройки её контекстного окна.",
|
|
18238
|
+
save: "Сохранить",
|
|
18239
|
+
saved: "Сохранено",
|
|
18240
|
+
saving: "Сохранение…",
|
|
18241
|
+
cacheSection: "Кеш",
|
|
18242
|
+
cacheDesc: "Кеш Antigravity сопоставляется сервисом неявно — клиент не передаёт ни одного поля управления кешем, — поэтому единственное доказательство его работы — доля ответа, прочитанная из кеша. Ниже сообщается только о полном промахе и о том, сколько клиент простаивал перед ним: кеш истекает по времени простоя, а каждый новый ход меняет диалог, так что сообщать о каждом изменении значило бы сообщать одно и то же. Счётчики живут в памяти и раздельны по сессиям.",
|
|
18243
|
+
cacheEmpty: "В этом процессе ещё не было запросов с отчётом о расходе.",
|
|
18244
|
+
cacheHitRatio: "Доля попаданий в кеш",
|
|
18245
|
+
cacheCached: "Токены из кеша",
|
|
18246
|
+
cacheFresh: "Новые токены",
|
|
18247
|
+
cacheRequests: "Запросы",
|
|
18248
|
+
cacheMiss: "Последний полный промах",
|
|
18249
|
+
cacheMissIdle: "Простой перед промахом",
|
|
18250
|
+
cacheDriftNone: "Префикс не менялся",
|
|
18251
|
+
cacheDriftContents: "Изменилось содержимое диалога",
|
|
18252
|
+
cacheDriftSystemInstruction: "Изменилась системная инструкция",
|
|
18253
|
+
cacheDriftTools: "Изменился список инструментов",
|
|
18254
|
+
cacheDriftSessionId: "Изменился идентификатор сессии",
|
|
18255
|
+
cacheDriftNewSession: "Первый запрос этой сессии",
|
|
18256
|
+
quotaSection: "Расход и квота",
|
|
18257
|
+
quotaDesc: "Данные из сервиса квот Google Cloud Code Assist; обновляются не чаще раза в 60 секунд, пока страница открыта.",
|
|
18258
|
+
refreshQuota: "Обновить квоту",
|
|
18259
|
+
refreshingQuota: "Обновление…",
|
|
18260
|
+
quotaEmpty: "Данных о квоте пока нет — нажмите «Обновить квоту», чтобы повторить.",
|
|
18261
|
+
googleValidation: "Подтвердите аккаунт в Google",
|
|
18262
|
+
resetPrefix: "Сброс: {time}",
|
|
18263
|
+
resetUnavailable: "Сброс: н/д",
|
|
18264
|
+
resetNow: "сейчас",
|
|
18265
|
+
timeDayHour: "{days} д {hours} ч",
|
|
18266
|
+
timeHourMin: "{hours} ч {minutes} мин",
|
|
18267
|
+
timeMin: "{minutes} мин",
|
|
18268
|
+
updatedAt: "Обновлено: {time}",
|
|
18269
|
+
loading: "Загрузка…",
|
|
18270
|
+
loginFailed: "Вход не выполнен",
|
|
18271
|
+
tokens: "токены"
|
|
18272
|
+
};
|
|
18273
|
+
//#endregion
|
|
18274
|
+
//#region src/client/locales-ru/claude.ts
|
|
18275
|
+
/**
|
|
18276
|
+
* Russian dictionary for the Claude subscription tab.
|
|
18277
|
+
*
|
|
18278
|
+
* Key set and order mirror the `zh` source; meaning follows `en`. The shared
|
|
18279
|
+
* account-pool labels come from `./account-pool.ts`, with the same overrides the
|
|
18280
|
+
* source applies on top of them.
|
|
18281
|
+
*/
|
|
18282
|
+
const dictionary$11 = {
|
|
18283
|
+
...accountPoolRu,
|
|
18284
|
+
title: "Claude (подписка)",
|
|
18285
|
+
pageDesc: "Войдите в подписку Claude Pro/Max и управляйте моделями, уровнями рассуждений, контекстными окнами и квотой.",
|
|
18286
|
+
account: "Аккаунт",
|
|
18287
|
+
signedIn: "Вход выполнен",
|
|
18288
|
+
signedOut: "Вход не выполнен",
|
|
18289
|
+
email: "Почта",
|
|
18290
|
+
plan: "Тариф",
|
|
18291
|
+
planUnknown: "—",
|
|
18292
|
+
subscriptionType: "Тип подписки",
|
|
18293
|
+
source: "Источник",
|
|
18294
|
+
sourceManaged: "Вход в этом плагине",
|
|
18295
|
+
sourceClaudeCode: "Локальный Claude Code",
|
|
18296
|
+
adoptedBadge: "Импортированный снимок",
|
|
18297
|
+
signIn: "Войти в Claude",
|
|
18298
|
+
signInSection: "Вход",
|
|
18299
|
+
signInAgain: "Войти заново",
|
|
18300
|
+
signingIn: "Запускаем вход…",
|
|
18301
|
+
cancelSignIn: "Отменить вход",
|
|
18302
|
+
openAuthorizeUrl: "Открыть страницу авторизации",
|
|
18303
|
+
authorizeUrl: "Ссылка авторизации",
|
|
18304
|
+
redirectUri: "Адрес возврата",
|
|
18305
|
+
loginModeManual: "Ручной режим: браузерного возврата нет, поэтому вставьте код со страницы после авторизации в поле ниже.",
|
|
18306
|
+
loginModeLoopback: "Режим локального возврата: после авторизации браузер сам вернётся на локальный адрес.",
|
|
18307
|
+
loginFallbackReason: "Локальный возврат недоступен, включён ручной режим: {detail}",
|
|
18308
|
+
loginWaiting: "Ждём завершения авторизации в браузере…",
|
|
18309
|
+
loginExchanging: "Обмениваем токен…",
|
|
18310
|
+
loginComplete: "Вход выполнен",
|
|
18311
|
+
loginFailed: "Вход не удался",
|
|
18312
|
+
manualPasteSection: "Вставить код авторизации",
|
|
18313
|
+
manualPasteHint: "Вставьте код из адресной строки браузера (или весь URL возврата), чтобы завершить вход. В ручном режиме браузерного возврата нет — это единственный путь.",
|
|
18314
|
+
manualPastePlaceholder: "code#state или полный URL возврата",
|
|
18315
|
+
manualPasteSubmit: "Отправить код",
|
|
18316
|
+
manualPasteSubmitting: "Отправляем…",
|
|
18317
|
+
importClaudeCode: "Импортировать вход локального Claude Code",
|
|
18318
|
+
importing: "Импорт…",
|
|
18319
|
+
stopImporting: "Остановить импорт",
|
|
18320
|
+
connection: "Соединение",
|
|
18321
|
+
testConnection: "Проверить соединение",
|
|
18322
|
+
testingConnection: "Проверяем…",
|
|
18323
|
+
testSuccess: "Соединение в порядке",
|
|
18324
|
+
testLatency: "отклик {ms} мс",
|
|
18325
|
+
testFailed: "Соединение не удалось: {detail}",
|
|
18326
|
+
testRetryable: "можно повторить",
|
|
18327
|
+
testNotRetryable: "повтор невозможен",
|
|
18328
|
+
routeOwned: "Маршрут моделей обслуживает этот плагин",
|
|
18329
|
+
routeConflict: "Маршрут моделей уже занят другим провайдером: {detail}. Удалите дублирующего провайдера в настройках DSH и повторите.",
|
|
18330
|
+
modelsSection: "Модели",
|
|
18331
|
+
modelsHint: "Модель попадает в список выбора модели на странице диалога, только если она отмечена.",
|
|
18332
|
+
refreshCatalog: "Обновить каталог моделей",
|
|
18333
|
+
refreshingCatalog: "Обновляем…",
|
|
18334
|
+
selectAll: "Выбрать все",
|
|
18335
|
+
unselectAll: "Снять все",
|
|
18336
|
+
capImage: "Изображения",
|
|
18337
|
+
capNoImage: "Только текст",
|
|
18338
|
+
capThinkingOff: "Рассуждения можно отключить",
|
|
18339
|
+
thinkingModeMidConvo: "Рассуждения в середине диалога",
|
|
18340
|
+
thinkingModeAdaptive: "Адаптивные рассуждения",
|
|
18341
|
+
thinkingModeBudget: "Рассуждения с бюджетом",
|
|
18342
|
+
thinkingModeNone: "Без рассуждений",
|
|
18343
|
+
enhanced: "Рассуждения",
|
|
18344
|
+
defaultReasoningEffort: "Уровень рассуждений по умолчанию",
|
|
18345
|
+
defaultReasoningEffortHint: "В списке все уровни, которые встречаются в каталоге (включая xhigh); какие уровни принимает каждая модель, видно ниже — Host отправляет тот, что поддерживает сама модель.",
|
|
18346
|
+
defaultEffortAuto: "Значение модели по умолчанию",
|
|
18347
|
+
cacheTtl: "Время жизни кеша промпта",
|
|
18348
|
+
cacheTtlHint: "Anthropic предлагает две ступени: 5 минут и 1 час. Пока подписка расходует лимит тарифа, официальный Claude Code держит час для основного диалога; после исчерпания тарифа и перехода на оплату по расходу он возвращается к пяти минутам. Запись на час дороже, для коротких сессий она не окупается.",
|
|
18349
|
+
cacheTtlSubscription: "Как у официального (в подписке по умолчанию 1 ч)",
|
|
18350
|
+
cacheTtl1h: "1 час",
|
|
18351
|
+
cacheTtl5m: "5 минут",
|
|
18352
|
+
effortLow: "Низкий (low)",
|
|
18353
|
+
effortMedium: "Средний (medium)",
|
|
18354
|
+
effortHigh: "Высокий (high)",
|
|
18355
|
+
effortXHigh: "Очень высокий (xhigh)",
|
|
18356
|
+
effortMax: "Максимальный (max)",
|
|
18357
|
+
modelLadders: "Уровни по моделям",
|
|
18358
|
+
modelLadderNone: "Эта модель не принимает уровень рассуждений",
|
|
18359
|
+
contextWindowSection: "Контекстное окно модели",
|
|
18360
|
+
contextWindowHint: "По умолчанию берётся длина контекста из каталога, сохранённое переопределение важнее. Сброс к умолчанию удаляет переопределение, и Host снова берёт значение каталога.",
|
|
18361
|
+
contextWindowReset: "Сбросить к умолчанию",
|
|
18362
|
+
contextWindowResetAll: "Сбросить все",
|
|
18363
|
+
contextWindowResetAllConfirm: "Сбросить контекстные окна всех изменённых моделей к значениям по умолчанию?",
|
|
18364
|
+
contextWindowNoneEnabled: "Ни одна модель не отмечена. Отметьте модель выше, и здесь появятся её настройки контекстного окна.",
|
|
18365
|
+
contextWindowInvalid: "Недопустимый размер контекста: {value}",
|
|
18366
|
+
save: "Сохранить",
|
|
18367
|
+
saving: "Сохраняем…",
|
|
18368
|
+
tokens: "токены",
|
|
18369
|
+
quotaSection: "Расход и квота",
|
|
18370
|
+
quotaDesc: "Данные из эндпоинта расхода Claude и заголовков ответа; на видимой странице обновляются не чаще раза в 60 секунд. utilization — это процент использования, поэтому 0% — нормальное пустое состояние.",
|
|
18371
|
+
refreshQuota: "Обновить расход",
|
|
18372
|
+
refreshingQuota: "Обновляем…",
|
|
18373
|
+
quotaRefreshing: "Host обновляет квоту в фоне, цифры скоро появятся.",
|
|
18374
|
+
quotaEmpty: "Данных о квоте пока нет — нажмите «Обновить расход», чтобы повторить.",
|
|
18375
|
+
quotaSignedOut: "Вход не выполнен, расход прочитать нельзя.",
|
|
18376
|
+
quotaUnknown: "—",
|
|
18377
|
+
quotaUnknownHint: "Host не назвал число для этого окна, поэтому здесь пусто, а не ноль.",
|
|
18378
|
+
usedLabel: "Использовано",
|
|
18379
|
+
remainingLabel: "Осталось",
|
|
18380
|
+
left: "доступно",
|
|
18381
|
+
resetAt: "Сброс: {time}",
|
|
18382
|
+
resetUnknown: "время сброса неизвестно",
|
|
18383
|
+
updatedAt: "Обновлено: {time}",
|
|
18384
|
+
observedAt: "Последнее наблюдение: {time}",
|
|
18385
|
+
quotaError: "Не удалось прочитать квоту",
|
|
18386
|
+
extraUsage: "Дополнительный расход",
|
|
18387
|
+
extraUsageEnabled: "включён",
|
|
18388
|
+
extraUsageDisabled: "выключен",
|
|
18389
|
+
extraUsageLimit: "Месячный лимит",
|
|
18390
|
+
sourceUsage: "Источник: эндпоинт расхода",
|
|
18391
|
+
sourceHeaders: "Источник: заголовки ответа",
|
|
18392
|
+
quotaStatus: "Статус ограничений",
|
|
18393
|
+
quotaRepresentative: "Показательное окно",
|
|
18394
|
+
loading: "Загрузка…",
|
|
18395
|
+
now: "сейчас",
|
|
18396
|
+
copy: "Копировать",
|
|
18397
|
+
copied: "Скопировано"
|
|
18398
|
+
};
|
|
18399
|
+
//#endregion
|
|
18400
|
+
//#region src/client/locales-ru/cline-pass.ts
|
|
18401
|
+
const dictionary$10 = {
|
|
18402
|
+
...accountPoolRu,
|
|
18403
|
+
relogin: "Войти заново",
|
|
18404
|
+
needsRelogin: "Вход истёк",
|
|
18405
|
+
addAccount: "Добавить аккаунт",
|
|
18406
|
+
noAccounts: "Аккаунтов пока нет. Нажмите «Войти в Cline», чтобы авторизоваться в браузере, или «Использовать API-ключ», чтобы вставить старый ключ.",
|
|
18407
|
+
title: "Cline Pass",
|
|
18408
|
+
pageDesc: "Подключение подписки Cline Pass: вход в аккаунт Cline по коду устройства в браузере, пул аккаунтов с автопереключением, чтение квоты и переключение при сбое до первого токена.",
|
|
18409
|
+
login: "Войти в Cline",
|
|
18410
|
+
loggingIn: "Вход…",
|
|
18411
|
+
loginTitle: "Вход в аккаунт Cline",
|
|
18412
|
+
loginHint: "Откройте страницу входа в браузере и подтвердите код ниже; после подтверждения аккаунт сам попадёт в пул, вставлять ключ не нужно.",
|
|
18413
|
+
loginCode: "Код входа",
|
|
18414
|
+
loginOpen: "Открыть страницу входа",
|
|
18415
|
+
loginWaiting: "Ждём подтверждения в браузере…",
|
|
18416
|
+
loginCancel: "Отменить вход",
|
|
18417
|
+
loginIdle: "Вход ещё не начинался в этом процессе.",
|
|
18418
|
+
loginHaveAccounts: "В пуле уже {count} рабочих аккаунтов.",
|
|
18419
|
+
loginComplete: "Вход выполнен: {account}",
|
|
18420
|
+
loginCompleteNoAccount: "Предыдущий вход завершился, но в пуле сейчас нет рабочих аккаунтов.",
|
|
18421
|
+
loginFailed: "Вход не удался: {detail}",
|
|
18422
|
+
useApiKey: "Использовать API-ключ",
|
|
18423
|
+
oauthAccount: "Вход через OAuth",
|
|
18424
|
+
apiKeyAccount: "API-ключ",
|
|
18425
|
+
routeOwned: "Маршрут моделей обслуживает этот плагин",
|
|
18426
|
+
routeConflict: "Маршрут моделей уже занят другим провайдером: {detail}",
|
|
18427
|
+
error: "Действие не удалось: {detail}",
|
|
18428
|
+
keySection: "Добавить API-ключ",
|
|
18429
|
+
keyHint: "Создайте API-ключ на странице аккаунта Cline и вставьте его здесь. Ключи не истекают, отозвать их можно там же.",
|
|
18430
|
+
keyPlaceholder: "Вставьте API-ключ Cline Pass",
|
|
18431
|
+
keyAliasLabel: "Название (необязательно)",
|
|
18432
|
+
keyAliasPlaceholder: "например: основной, резервный",
|
|
18433
|
+
keyAliasHint: "Cline не сообщает данные аккаунта, поэтому несколько ключей различаются по названию.",
|
|
18434
|
+
keyBaseUrlLabel: "Переопределение шлюза (необязательно)",
|
|
18435
|
+
keyBaseUrlPlaceholder: "по умолчанию: https://api.cline.bot/api/v1",
|
|
18436
|
+
keySave: "Добавить",
|
|
18437
|
+
keySaving: "Добавление…",
|
|
18438
|
+
keyTest: "Проверить ключ",
|
|
18439
|
+
cancel: "Отмена",
|
|
18440
|
+
keyTesting: "Проверка…",
|
|
18441
|
+
keyTestOk: "Ключ работает ({ms} мс)",
|
|
18442
|
+
keyTestFailed: "Ключ отклонён: {detail}",
|
|
18443
|
+
testSavedKey: "Проверить",
|
|
18444
|
+
modelsSection: "Модели",
|
|
18445
|
+
modelsHint: "Список берётся из официального каталога подписки; перед первым использованием обновите его. Неотмеченные модели не появляются в выборе моделей.",
|
|
18446
|
+
modelCount: "Моделей: {count}",
|
|
18447
|
+
modelChecklistCount: "Выбрано {count} из {total}",
|
|
18448
|
+
selectAll: "Выбрать все",
|
|
18449
|
+
unselectAll: "Снять все",
|
|
18450
|
+
catalogSync: "Обновить каталог",
|
|
18451
|
+
catalogSyncing: "Обновление…",
|
|
18452
|
+
catalogNeverSynced: "Официальный каталог ещё не синхронизирован. Нажмите «Обновить каталог», чтобы получить модели, которые сейчас отдаёт подписка; до этого показывается только встроенная таблица.",
|
|
18453
|
+
catalogEmpty: "Официальный каталог не вернул ни одной модели.",
|
|
18454
|
+
noModels: "Нет доступных моделей.",
|
|
18455
|
+
catalogSources: "Источники каталога: {sources}",
|
|
18456
|
+
contextSection: "Контекстные окна",
|
|
18457
|
+
contextHint: "Показывается только для отмеченных моделей. Недопустимое значение приводит к ошибке и не сохраняется; «Вернуть по умолчанию» сбрасывает переопределение.",
|
|
18458
|
+
tokens: "токенов",
|
|
18459
|
+
contextSave: "Сохранить",
|
|
18460
|
+
contextOverridden: "переопределено",
|
|
18461
|
+
contextSaving: "Сохранение",
|
|
18462
|
+
contextReset: "Вернуть по умолчанию",
|
|
18463
|
+
contextResetAll: "Вернуть все по умолчанию",
|
|
18464
|
+
contextEmpty: "Отметьте хотя бы одну модель, чтобы настроить здесь её контекстное окно.",
|
|
18465
|
+
routingSection: "Каналы апстрима",
|
|
18466
|
+
routingHint: "Перед первым использованием модели нажмите «Зондировать», чтобы получить каналы, затем «Проверить», чтобы убедиться, что канал действительно применил закрепление. Нажатие на имя канала закрепляет его по порядку, ⊘ исключает канал.",
|
|
18467
|
+
probe: "Зондировать",
|
|
18468
|
+
probing: "Зондирование…",
|
|
18469
|
+
validate: "Проверить",
|
|
18470
|
+
validating: "Проверка…",
|
|
18471
|
+
testPin: "Тест",
|
|
18472
|
+
testingPin: "Тест…",
|
|
18473
|
+
savePin: "Сохранить закрепление",
|
|
18474
|
+
savingPin: "Сохранение…",
|
|
18475
|
+
resetPin: "Вернуть авто-маршрутизацию",
|
|
18476
|
+
pinAuto: "авто-маршрутизация",
|
|
18477
|
+
pinPinned: "Порядок закрепления: {list}",
|
|
18478
|
+
pinExcluded: "Исключено: {list}",
|
|
18479
|
+
pinMode: "Режим закрепления",
|
|
18480
|
+
sort: "Сортировка",
|
|
18481
|
+
sortNone: "Без сортировки",
|
|
18482
|
+
sortCost: "Сначала дешёвые",
|
|
18483
|
+
sortTtft: "Сначала быстрый первый токен",
|
|
18484
|
+
sortTps: "Сначала высокая пропускная способность",
|
|
18485
|
+
modeStrict: "Строгий (только закреплённые каналы)",
|
|
18486
|
+
modePreferred: "Предпочтительный (по порядку, при сбое — переключение)",
|
|
18487
|
+
noChannels: "Каналы ещё не обнаружены. Нажмите «Зондировать», чтобы получить список апстримов этой модели.",
|
|
18488
|
+
channelHint: "Нажмите на канал, чтобы добавить его в порядок закрепления; повторное нажатие убирает. ⊘ переключает исключение.",
|
|
18489
|
+
lastServed: "Последний раз обслужил {provider} ({ms} мс)",
|
|
18490
|
+
probedAt: "Зондирование {time}",
|
|
18491
|
+
pipeline: "Пайплайн: {pipeline}",
|
|
18492
|
+
notPinnable: "Эту модель сейчас нельзя закрепить",
|
|
18493
|
+
testServed: "Тест прошёл: обслужил {provider} ({ms} мс)",
|
|
18494
|
+
testFailed: "Тест не прошёл: {detail}",
|
|
18495
|
+
testTrace: "Попытки",
|
|
18496
|
+
warnings: "Предупреждения",
|
|
18497
|
+
probeResult: "Результат зондирования",
|
|
18498
|
+
validateSummary: "Проверка: доступно {ok} / с лимитом {limited} / не закрепляется {bad} / ошибка авторизации {auth} / неизвестно {unknown}",
|
|
18499
|
+
usageSection: "Официальная квота",
|
|
18500
|
+
usageHint: "Квота принадлежит аккаунту, а не линии. Обновление отправляет по одному запросу на каждый рабочий аккаунт.",
|
|
18501
|
+
usageRefresh: "Обновить квоту",
|
|
18502
|
+
usageRefreshing: "Обновление…",
|
|
18503
|
+
usageEmpty: "Квота ещё не читалась.",
|
|
18504
|
+
usageNone: "Данных о квоте пока нет",
|
|
18505
|
+
usageUnavailable: "Не удалось прочитать официальную квоту: {detail}",
|
|
18506
|
+
usageWindow: "{label}: использовано {percent}%",
|
|
18507
|
+
usageResets: "Сброс: {when}",
|
|
18508
|
+
historySection: "История запросов",
|
|
18509
|
+
historyHint: "Хранится только в памяти текущего процесса; после перезапуска список пуст.",
|
|
18510
|
+
historyRefresh: "Обновить историю",
|
|
18511
|
+
historyEmpty: "В этом процессе ещё нет записанных вызовов моделей.",
|
|
18512
|
+
historyCount: "Последние {count} из {total} вызовов",
|
|
18513
|
+
historyModel: "Модель",
|
|
18514
|
+
historyLatency: "первый токен / всего",
|
|
18515
|
+
historyTokens: "токены",
|
|
18516
|
+
historyError: "Ошибка",
|
|
18517
|
+
historyAccount: "Аккаунт",
|
|
18518
|
+
advancedSection: "Дополнительно",
|
|
18519
|
+
baseURL: "Шлюз по умолчанию",
|
|
18520
|
+
defaultContextWindow: "Контекстное окно по умолчанию",
|
|
18521
|
+
defaultMaxTokens: "Бюджет вывода по умолчанию",
|
|
18522
|
+
maxConcurrentRequests: "Потоков на аккаунт (0 = без ограничений)",
|
|
18523
|
+
streamIdleTimeoutMs: "Таймаут простоя потока (мс)",
|
|
18524
|
+
historyLimit: "Строк истории",
|
|
18525
|
+
exposeCatalog: "Показывать в выборе моделей дополнительные модели из каталога шлюза",
|
|
18526
|
+
exposeCatalogHint: "Если выключено, показываются только официальный каталог подписки и встроенная таблица.",
|
|
18527
|
+
pinSpelling: "Написание поля закрепления",
|
|
18528
|
+
pinSpellingBoth: "Отправлять оба написания (рекомендуется)",
|
|
18529
|
+
pinSpellingDetected: "Только обнаруженное написание",
|
|
18530
|
+
pinSpellingHint: "Шлюз может сменить пайплайн между запросами; при одном написании закрепление тихо перестаёт действовать.",
|
|
18531
|
+
exposeTools: "Регистрировать управляющие инструменты cline_pass_*",
|
|
18532
|
+
exposeToolsHint: "Их описания попадают в список инструментов каждого запроса, поэтому по умолчанию выключено. Изменение вступает в силу после перезапуска DSH.",
|
|
18533
|
+
saveSettings: "Сохранить настройки",
|
|
18534
|
+
savingSettings: "Сохранение…",
|
|
18535
|
+
saved: "Сохранено",
|
|
18536
|
+
restartRequired: "Сохранено; управляющие инструменты заработают после перезапуска DSH.",
|
|
18537
|
+
limitsSection: "Примечания",
|
|
18538
|
+
limitKey: "API-ключи лежат в системном хранилище учётных данных; карточка показывает только название.",
|
|
18539
|
+
limitGateway: "Запросы идут через шлюз Cline, и канал обслуживания выбирает он. Закрепление не гарантирует применения, поэтому карточка читает фактический канал обратно.",
|
|
18540
|
+
limitRoute: "Маршрут закрепляется за provider id: если cline-pass уже обслуживает другой плагин, эта карточка всё равно настраивает линию, но запросы выполняет он.",
|
|
18541
|
+
limitQuota: "Окна квоты приходят из шлюзового эндпоинта usage-limits; при сбое карточка оставляет прошлое чтение и показывает причину."
|
|
18542
|
+
};
|
|
18543
|
+
//#endregion
|
|
18544
|
+
//#region src/client/locales-ru/command-code.ts
|
|
18545
|
+
const dictionary$9 = {
|
|
18546
|
+
...accountPoolRu,
|
|
18547
|
+
title: "Command Code",
|
|
18548
|
+
pageDesc: "Войдите в Command Code и управляйте моделями, контекстными окнами и квотой.",
|
|
18549
|
+
account: "Аккаунт",
|
|
18550
|
+
signedIn: "Вход выполнен",
|
|
18551
|
+
signedOut: "Вход не выполнен",
|
|
18552
|
+
keyName: "Имя ключа",
|
|
18553
|
+
organization: "Организация",
|
|
18554
|
+
plan: "Тариф",
|
|
18555
|
+
planUnknown: "—",
|
|
18556
|
+
subscription: "Подписка",
|
|
18557
|
+
renews: "Продление",
|
|
18558
|
+
authenticatedAt: "Вход выполнен в",
|
|
18559
|
+
signIn: "Войти через браузер",
|
|
18560
|
+
signInAgain: "Войти заново",
|
|
18561
|
+
signingIn: "Вход…",
|
|
18562
|
+
signOut: "Выйти",
|
|
18563
|
+
cancelSignIn: "Отмена",
|
|
18564
|
+
openSignInPage: "Открыть страницу входа",
|
|
18565
|
+
apiKeySection: "Вставить API-ключ",
|
|
18566
|
+
apiKeyHint: "Создайте ключ в Command Code Studio и вставьте его сюда; это нужно, когда браузерный вход недоступен.",
|
|
18567
|
+
apiKeyPlaceholder: "API-ключ Command Code",
|
|
18568
|
+
apiKeySave: "Сохранить и проверить",
|
|
18569
|
+
apiKeySaving: "Проверка…",
|
|
18570
|
+
apiKeySaved: "Сохранено",
|
|
18571
|
+
connection: "Подключение",
|
|
18572
|
+
testConnection: "Проверить подключение",
|
|
18573
|
+
testingConnection: "Проверка…",
|
|
18574
|
+
routeOwned: "Маршрут моделей обслуживает этот плагин",
|
|
18575
|
+
routeConflict: "Маршрут моделей уже занят другим провайдером: {detail}. Удалите дублирующую конфигурацию провайдера в настройках DSH и перезагрузите.",
|
|
18576
|
+
modelsSection: "Модели",
|
|
18577
|
+
modelsHint: "Отмеченные модели появляются в списке моделей диалога DSH; если снять все отметки или выключить переключатель на карточке обзора, провайдер скроется из списка.",
|
|
18578
|
+
refreshCatalog: "Обновить каталог",
|
|
18579
|
+
refreshingCatalog: "Обновление…",
|
|
18580
|
+
catalogStale: "Каталог взят из кеша и может быть устаревшим; обновите, чтобы проверить",
|
|
18581
|
+
catalogFresh: "Каталог синхронизирован",
|
|
18582
|
+
zdrEnabled: "Запрошено нулевое хранение данных (ZDR); если подходящего маршрута нет, запрос завершится отказом, требования к приватности автоматически не снижаются.",
|
|
18583
|
+
selectAll: "Выбрать все",
|
|
18584
|
+
unselectAll: "Снять все",
|
|
18585
|
+
wireAnthropic: "Anthropic",
|
|
18586
|
+
wireOpenai: "OpenAI",
|
|
18587
|
+
wireResponses: "OpenAI Responses",
|
|
18588
|
+
enhanced: "Дополнительные возможности",
|
|
18589
|
+
defaultReasoningEffort: "Уровень рассуждений по умолчанию",
|
|
18590
|
+
defaultReasoningEffortHint: "Уровень рассуждений для моделей, которые его поддерживают, когда диалог не задаёт его явно. У моделей Anthropic он превращается в бюджет размышлений.",
|
|
18591
|
+
defaultEffortAuto: "По умолчанию у провайдера",
|
|
18592
|
+
contextWindowSection: "Контекстное окно модели",
|
|
18593
|
+
contextWindowHint: "По умолчанию берётся context length из каталога Command Code; можно задать свою ёмкость, которую DSH будет использовать при сжатии и определении переполнения (например, 1M, 512K, 200K).",
|
|
18594
|
+
contextWindowReset: "Вернуть значение по умолчанию",
|
|
18595
|
+
contextWindowResetAll: "Вернуть все значения",
|
|
18596
|
+
contextWindowResetAllConfirm: "Вернуть к значениям по умолчанию все изменённые контекстные окна?",
|
|
18597
|
+
contextWindowNoneEnabled: "Ни одна модель не отмечена. Отметьте её выше — и здесь появятся настройки её контекстного окна.",
|
|
18598
|
+
save: "Сохранить",
|
|
18599
|
+
saved: "Сохранено",
|
|
18600
|
+
saving: "Сохранение…",
|
|
18601
|
+
quotaSection: "Расход и квота",
|
|
18602
|
+
quotaDesc: "Читается из эндпоинтов аккаунта Command Code; обновляется не чаще раза в 60 секунд, пока страница открыта.",
|
|
18603
|
+
refreshQuota: "Обновить квоту",
|
|
18604
|
+
refreshingQuota: "Обновление…",
|
|
18605
|
+
quotaEmpty: "Данных о квоте пока нет — нажмите «Обновить квоту», чтобы повторить.",
|
|
18606
|
+
quotaCredits: "Остаток кредитов",
|
|
18607
|
+
quotaUnlimited: "Без ограничений",
|
|
18608
|
+
updatedAt: "Обновлено: {time}",
|
|
18609
|
+
loading: "Загрузка…",
|
|
18610
|
+
loginFailed: "Вход не выполнен",
|
|
18611
|
+
tokens: "токены"
|
|
18612
|
+
};
|
|
18613
|
+
//#endregion
|
|
18614
|
+
//#region src/client/locales-ru/glm-coding-plan.ts
|
|
18615
|
+
const dictionary$8 = {
|
|
18616
|
+
...accountPoolRu,
|
|
18617
|
+
title: "GLM (аккаунт ZCode)",
|
|
18618
|
+
pageDesc: "Вход аккаунтом ZCode подключает GLM Coding Plan (Китай — bigmodel.cn, международный — z.ai). Здесь же пул аккаунтов, квота тарифа и выбор моделей. Учётные данные двух регионов независимы, поэтому в одном пуле могут быть аккаунты обоих.",
|
|
18619
|
+
loading: "Загрузка…",
|
|
18620
|
+
region: "Регион",
|
|
18621
|
+
regionCn: "Китай (bigmodel.cn)",
|
|
18622
|
+
regionIntl: "Международный (z.ai)",
|
|
18623
|
+
regionHint: "Все способы входа в блоке аккаунтов ниже начинаются в выбранном здесь регионе: «Добавить аккаунт» откроет страницу авторизации этого региона, а «Импорт локального входа» и ручная вставка кода тоже попадут в него. Регион — свойство учётных данных: ключ, выпущенный в одном регионе, другой отвергнет, поэтому аккаунты двух регионов не взаимозаменяемы.",
|
|
18624
|
+
authorizing: "Авторизация…",
|
|
18625
|
+
loginIdle: "Вход ещё не начат.",
|
|
18626
|
+
loginHaveAccounts: "В пуле уже {count} аккаунтов, они готовы к работе. Чтобы добавить ещё, нажмите «Добавить аккаунт» выше.",
|
|
18627
|
+
loginPending: "Завершите вход и авторизацию в браузере — карточка продолжит сама.",
|
|
18628
|
+
loginComplete: "Вход выполнен, аккаунт добавлен в пул.",
|
|
18629
|
+
loginCompletedAt: "Вход завершён в {time}",
|
|
18630
|
+
loginCompleteNoAccount: "Этот вход завершился, но аккаунта в пуле больше нет (возможно, он удалён).",
|
|
18631
|
+
loginError: "Вход не выполнен.",
|
|
18632
|
+
loginRetryable: "Сбой можно повторить: запустите вход заново.",
|
|
18633
|
+
loginNotRetryable: "Сам этот сбой не пройдёт: проверьте, верно ли выбран регион и доступна ли сеть, затем запустите вход заново.",
|
|
18634
|
+
authorizeUrl: "Страница авторизации",
|
|
18635
|
+
openAuthorizeUrl: "Открыть страницу авторизации",
|
|
18636
|
+
pollEvery: "Результат опрашивается каждые {seconds} с.",
|
|
18637
|
+
loginExpiresAt: "Эта авторизация действует до {time}, после чего её нужно начать заново.",
|
|
18638
|
+
progress: "Прогресс",
|
|
18639
|
+
restartLogin: "Начать вход заново",
|
|
18640
|
+
cancelLogin: "Отменить вход",
|
|
18641
|
+
cancelLoginBusy: "Отмена…",
|
|
18642
|
+
manualPasteSection: "Вставить код вручную",
|
|
18643
|
+
manualPasteHint: "Если браузерный колбэк перехвачен или страница не отдаёт код, вставьте ниже код авторизации из колбэка ZCode, и обмен завершится. Этот путь — единственный способ довести вход до конца при недоступном колбэке, поэтому он есть всегда: свёрнут, пока вход не идёт, и сам раскрывается, как только тот начался (в процессе или с ошибкой).",
|
|
18644
|
+
manualPastePlaceholder: "Вставьте код (code=… или весь адрес колбэка)",
|
|
18645
|
+
manualPasteSubmit: "Отправить код",
|
|
18646
|
+
manualPasteSubmitting: "Обмен…",
|
|
18647
|
+
manualPasteEmpty: "Сначала вставьте код.",
|
|
18648
|
+
adopt: "Импортировать локальный вход ZCode",
|
|
18649
|
+
adopting: "Импорт…",
|
|
18650
|
+
adoptAdopted: "Локальный вход ZCode импортирован ({region}), повторный вход не нужен.",
|
|
18651
|
+
adoptNoAttempt: "На этой машине нет входа ZCode, который можно импортировать.",
|
|
18652
|
+
adoptNoCredentialsFile: "Файл учётных данных ZCode не найден (по умолчанию ~/.zcode/v2/credentials.json). Он появляется после установки клиента ZCode и одного входа в нём.",
|
|
18653
|
+
adoptSecretUnavailable: "Файл учётных данных есть, но на машине задан ZCODE_CREDENTIAL_SECRET, поэтому ключ расшифровки не вывести и вход из файла не прочитать.",
|
|
18654
|
+
adoptDecryptFailed: "Расшифровка не удалась: файл могли изменить или повредить.",
|
|
18655
|
+
adoptTokenExpired: "Вход ZCode истёк — войдите заново в клиенте ZCode и импортируйте ещё раз.",
|
|
18656
|
+
adoptExchangeFailed: "Не удалось обменять ключ Coding Plan: возможно, у аккаунта нет тарифа Coding Plan или нет права создавать ключ.",
|
|
18657
|
+
adoptNotAZcodeLogin: "В файле учётных данных нет входа ZCode, который знает эта линия (файл может принадлежать другому инструменту).",
|
|
18658
|
+
adoptFallback: "Импорт лишь избавляет от одного входа; сбой ничего не блокирует — воспользуйтесь входом в браузере или ручной вставкой кода.",
|
|
18659
|
+
adoptedBadge: "Импортированный вход",
|
|
18660
|
+
connection: "Подключение",
|
|
18661
|
+
testConnection: "Проверить подключение",
|
|
18662
|
+
testingConnection: "Проверка…",
|
|
18663
|
+
testSuccess: "Подключение работает",
|
|
18664
|
+
testSuccessAccount: "Подключение работает (аккаунт {account})",
|
|
18665
|
+
testSuccessModel: "Подключение работает ({model})",
|
|
18666
|
+
testFailed: "Проверка подключения не прошла",
|
|
18667
|
+
testFailedDetail: "Проверка подключения не прошла: {detail}",
|
|
18668
|
+
testLatency: "Отклик {ms} мс",
|
|
18669
|
+
routeOwned: "Маршрут моделей обслуживает этот плагин.",
|
|
18670
|
+
routeConflict: "Маршрут моделей уже занят другим провайдером: {detail}. Удалите дублирующую конфигурацию провайдера в настройках DSH и перезагрузите.",
|
|
18671
|
+
modelsSection: "Модели",
|
|
18672
|
+
modelsHint: "В выборе моделей диалога видны только отмеченные модели. Каталог и все сведения о возможностях берутся из встроенного каталога этой линии и никогда не выводятся из имени модели (GLM-5.3 и GLM-5.3-Flash различаются приёмом изображений, GLM-5.2 и GLM-5.3 — уровнями рассуждений). Каталог фильтруется по региону аккаунта; модель, запрошенная не из того региона, отклоняется на стороне провайдера.",
|
|
18673
|
+
modelsUnavailable: "Пока нет моделей для показа.",
|
|
18674
|
+
refreshCatalog: "Обновить каталог моделей",
|
|
18675
|
+
refreshingCatalog: "Обновление…",
|
|
18676
|
+
dismiss: "Понятно",
|
|
18677
|
+
selectAll: "Выбрать все",
|
|
18678
|
+
unselectAll: "Снять все",
|
|
18679
|
+
modelChecklistCount: "{count}/{total}",
|
|
18680
|
+
contextWindowSection: "Контекстное окно моделей",
|
|
18681
|
+
contextWindowHint: "Значения по умолчанию берутся из встроенного каталога (реальный предел контекста каждой модели). Можно задать свою ёмкость — её DSH использует при сжатии и определении переполнения; принимаются 1M, 512K, 200K и подобные.",
|
|
18682
|
+
contextWindowNoneEnabled: "Ни одна модель не отмечена. Отметьте её выше — и здесь появятся настройки её контекстного окна.",
|
|
18683
|
+
contextWindowReset: "Вернуть значение по умолчанию",
|
|
18684
|
+
contextWindowResetAll: "Вернуть все значения",
|
|
18685
|
+
tokens: "токены",
|
|
18686
|
+
save: "Сохранить",
|
|
18687
|
+
saving: "Сохранение…",
|
|
18688
|
+
saved: "Сохранено",
|
|
18689
|
+
invalidCapacity: "Неверный формат ёмкости: {value}",
|
|
18690
|
+
quotaSection: "Расход и квота",
|
|
18691
|
+
quotaDesc: "Данные из эндпоинта квоты Coding Plan; обновляются не чаще раза в 60 секунд, пока страница открыта.",
|
|
18692
|
+
quotaRefresh: "Обновить расход",
|
|
18693
|
+
quotaRefreshing: "Обновление…",
|
|
18694
|
+
quotaSignedOut: "Вход не выполнен — сначала завершите его выше.",
|
|
18695
|
+
quotaEmpty: "Данных о квоте пока нет — нажмите «Обновить расход», чтобы повторить.",
|
|
18696
|
+
quotaPlan: "Тариф",
|
|
18697
|
+
quotaPlanLevel: "Уровень",
|
|
18698
|
+
quotaRenews: "Продление",
|
|
18699
|
+
quotaReadAt: "Прочитано",
|
|
18700
|
+
quotaSources: "Источники",
|
|
18701
|
+
quotaRefreshingNote: "Квота обновляется в фоне; ниже — цифры последнего чтения.",
|
|
18702
|
+
quotaErrorLabel: "Не удалось прочитать квоту",
|
|
18703
|
+
quotaAllowance: "Тип лимита",
|
|
18704
|
+
quotaAllowancePlan: "Платный тариф",
|
|
18705
|
+
quotaAllowanceFreeTrial: "Бесплатный пробный лимит",
|
|
18706
|
+
quotaAllowanceUnknown: "Не определён",
|
|
18707
|
+
quotaAllowanceHint: "Источник лимита, определённый проверкой при входе. «Бесплатный пробный лимит» — это автоматически выдаваемый новым аккаунтам лимит: 8 млн токенов в день в течение 5 дней с первого использования."
|
|
18708
|
+
};
|
|
18709
|
+
//#endregion
|
|
18710
|
+
//#region src/client/locales-ru/hub.ts
|
|
18711
|
+
/**
|
|
18712
|
+
* Russian dictionary for the ChatGPT subscription hub (the overview screen).
|
|
18713
|
+
*
|
|
18714
|
+
* Key set and order mirror the `zh` source; meaning follows `en`. The shared
|
|
18715
|
+
* account-pool labels come from `./account-pool.ts`, with the same overrides the
|
|
18716
|
+
* source applies on top of them.
|
|
18717
|
+
*/
|
|
18718
|
+
const dictionary$7 = {
|
|
18719
|
+
...accountPoolRu,
|
|
18720
|
+
title: "ChatGPT",
|
|
18721
|
+
hubTitle: "Подписки",
|
|
18722
|
+
intro: "Войдите аккаунтом ChatGPT, чтобы использовать в DSH модели, доступные по подписке.",
|
|
18723
|
+
account: "Аккаунт",
|
|
18724
|
+
signedOut: "Вход не выполнен",
|
|
18725
|
+
signedIn: "Вход выполнен",
|
|
18726
|
+
plan: "Тариф",
|
|
18727
|
+
accountId: "ID аккаунта",
|
|
18728
|
+
expires: "Токен истекает",
|
|
18729
|
+
signIn: "Войти через ChatGPT",
|
|
18730
|
+
signInAgain: "Войти заново",
|
|
18731
|
+
cancel: "Отменить вход",
|
|
18732
|
+
signOut: "Выйти",
|
|
18733
|
+
refreshToken: "Обновить учётные данные",
|
|
18734
|
+
pending: "Завершите вход в браузере.",
|
|
18735
|
+
popupBlocked: "Браузер заблокировал окно входа — продолжите по ссылке ниже.",
|
|
18736
|
+
continueLogin: "Открыть страницу входа ChatGPT",
|
|
18737
|
+
loading: "Читаем состояние…",
|
|
18738
|
+
connection: "Соединение",
|
|
18739
|
+
testConnection: "Проверить соединение",
|
|
18740
|
+
testing: "Проверяем…",
|
|
18741
|
+
latency: "Последняя задержка",
|
|
18742
|
+
selectAll: "Выбрать все",
|
|
18743
|
+
unselectAll: "Снять все",
|
|
18744
|
+
models: "Доступные модели",
|
|
18745
|
+
modelsHint: "Отмеченные модели появляются в списке выбора модели на странице диалога; если снять все отметки или выключить переключатель выше, провайдер исчезнет из списка.",
|
|
18746
|
+
proxySettings: "Сетевой прокси",
|
|
18747
|
+
proxyMode: "Режим прокси",
|
|
18748
|
+
proxyModeHint: "GPT и Antigravity (Gemini) используют эти настройки прокси вместе; поддерживается автоопределение системного прокси, изменения действуют на последующие запросы.",
|
|
18749
|
+
proxyModeAuto: "Системный прокси (автоопределение)",
|
|
18750
|
+
proxyModeCustom: "Свой прокси",
|
|
18751
|
+
proxyModeDirect: "Напрямую (без прокси)",
|
|
18752
|
+
customProxyUrl: "Адрес своего прокси",
|
|
18753
|
+
customProxyUrlHint: "Поддерживаются адреса HTTP/HTTPS/SOCKS5, например http://127.0.0.1:7890",
|
|
18754
|
+
customProxyUrlPlaceholder: "например http://127.0.0.1:7890",
|
|
18755
|
+
saveProxyUrl: "Сохранить адрес прокси",
|
|
18756
|
+
proxyDetected: "Обнаружен системный прокси",
|
|
18757
|
+
proxyDetectedEffective: " (уже действует)",
|
|
18758
|
+
proxyNoneDetected: "Системный прокси не обнаружен, соединение напрямую",
|
|
18759
|
+
proxyDirectHint: "Все запросы идут напрямую, без прокси-сервера.",
|
|
18760
|
+
enhancements: "Дополнительные функции",
|
|
18761
|
+
fastMode: "Быстрый режим (скорость 1.5x)",
|
|
18762
|
+
fastModeHint: "Генерирует токены примерно в 1.5 раза быстрее; квота подписки Codex при этом расходуется в 2–2.5 раза быстрее.",
|
|
18763
|
+
outputVerbosity: "Подробность ответа",
|
|
18764
|
+
outputVerbosityHint: "Задаёт подробность итоговых ответов Codex и не влияет на глубину рассуждений. Значение по умолчанию как в официальном клиенте Codex (низкая).",
|
|
18765
|
+
verbosityLow: "Низкая (ответы короче)",
|
|
18766
|
+
verbosityMedium: "Средняя (баланс деталей и краткости)",
|
|
18767
|
+
verbosityHigh: "Высокая (больше деталей)",
|
|
18768
|
+
reasoningSummary: "Сводка рассуждений",
|
|
18769
|
+
reasoningSummaryHint: "Определяет, как ChatGPT пересказывает ход рассуждений; на глубину рассуждений не влияет. По умолчанию как в официальном клиенте Codex (без сводки, экономит квоту).",
|
|
18770
|
+
summaryAuto: "Авто (модель выбирает подробность)",
|
|
18771
|
+
summaryConcise: "Кратко (короткая сводка)",
|
|
18772
|
+
summaryDetailed: "Подробно (развёрнутая сводка)",
|
|
18773
|
+
summaryNone: "Нет (сводку не показывать)",
|
|
18774
|
+
searchProvider: "Источник поиска",
|
|
18775
|
+
searchProviderHint: "Выберите, использует ли веб-поиск DSH источник по умолчанию или источник Codex из текущей подписки ChatGPT (через прокси-туннель). В режиме выборки auto источник выборки следует этому выбору.",
|
|
18776
|
+
searchProviderDsh: "DSH по умолчанию",
|
|
18777
|
+
searchProviderCodex: "ChatGPT (через прокси-туннель)",
|
|
18778
|
+
fetchStatus: "Источник выборки (только чтение)",
|
|
18779
|
+
fetchStatusHint: "Эти данные сообщает Host, показаны только для чтения.",
|
|
18780
|
+
fetchConfiguredProvider: "Настроенный провайдер выборки",
|
|
18781
|
+
fetchProviderDshDefault: "DSH по умолчанию (Host не закрепляет провайдер выборки)",
|
|
18782
|
+
switcherState: "Состояние переключателя выборки",
|
|
18783
|
+
switcherStateIdle: "Простой (выбор ещё не применён)",
|
|
18784
|
+
switcherStateApplying: "Применяется (Host переключает web-провайдера)",
|
|
18785
|
+
switcherStateApplied: "Применено",
|
|
18786
|
+
switcherStateMissing: "Нет web-сервиса для переключения",
|
|
18787
|
+
switcherStateFailed: "Переключение не удалось, проверьте журнал Host",
|
|
18788
|
+
fetchMode: "Режим выборки",
|
|
18789
|
+
fetchModeAuto: "auto (выбирает плагин, если есть прокси или выбран источник поиска ChatGPT)",
|
|
18790
|
+
fetchModePlugin: "plugin (всегда выбирает этот плагин)",
|
|
18791
|
+
fetchModeDsh: "dsh (оставить исходный источник выборки DSH)",
|
|
18792
|
+
fetchMaxBodyChars: "Лимит тела в плагине",
|
|
18793
|
+
fetchMaxResponseBytes: "Лимит ответа в плагине",
|
|
18794
|
+
characters: "символов",
|
|
18795
|
+
bytes: "байт",
|
|
18796
|
+
fetchLimitsInactive: "Действуют, только когда выборку делает плагин; исходный источник выборки DSH эти два лимита не использует.",
|
|
18797
|
+
fetchConfigSource: "Режим и лимиты меняются в Config плагина, а не в этих настройках; они вступают в силу после перезагрузки плагина или перезапуска DSH.",
|
|
18798
|
+
providerDefault: "Значение провайдера по умолчанию",
|
|
18799
|
+
contextWindows: "Контекстные окна моделей",
|
|
18800
|
+
contextWindowsHint: "Перечислены только модели, отмеченные в «Доступные модели». По умолчанию берётся значение каталога (384K для серии GPT-6, до 872K; у остальных до 1M) — DSH использует его для сжатия и определения переполнения. Можно вводить значения вида 872K и 512K, а изменённую модель можно сбросить отдельно или все сразу.",
|
|
18801
|
+
contextWindow: "Контекстное окно",
|
|
18802
|
+
contextWindowInvalid: "Контекстное окно должно быть положительным целым в пределах модели (для серии GPT-6 — 872K, у остальных 1M); допускаются суффиксы K и M.",
|
|
18803
|
+
contextWindowReset: "Сбросить к умолчанию",
|
|
18804
|
+
contextWindowResetAll: "Сбросить все",
|
|
18805
|
+
contextWindowResetAllConfirm: "Сбросить контекстные окна всех изменённых моделей к значениям по умолчанию?",
|
|
18806
|
+
contextWindowsNoneEnabled: "Ни одна модель не отмечена. Отметьте модель в «Доступные модели» выше, и здесь появятся её настройки контекстного окна.",
|
|
18807
|
+
saveContextWindow: "Сохранить контекстное окно",
|
|
18808
|
+
save: "Сохранить",
|
|
18809
|
+
tokens: "токены",
|
|
18810
|
+
quickQuota: "Показывать быстрый расход у поля ввода",
|
|
18811
|
+
quickQuotaHint: "Показывается, только когда в текущей сессии выбрана модель codex-chatgpt.",
|
|
18812
|
+
quota: "Расход и лимиты",
|
|
18813
|
+
quotaIntro: "Данные из сервиса расхода ChatGPT Codex; на видимой странице обновляются не чаще раза в минуту.",
|
|
18814
|
+
refreshQuota: "Обновить расход",
|
|
18815
|
+
refreshing: "Обновляем…",
|
|
18816
|
+
noQuota: "Тариф не вернул ни одного окна лимита для показа.",
|
|
18817
|
+
quotaSignedOut: "Войдите, чтобы увидеть лимиты подписки.",
|
|
18818
|
+
stale: "Показаны данные последнего успешного запроса.",
|
|
18819
|
+
updated: "Обновлено",
|
|
18820
|
+
primary: "Основное окно",
|
|
18821
|
+
secondary: "Дополнительное окно",
|
|
18822
|
+
limitWindow: "лимит",
|
|
18823
|
+
used: "использовано",
|
|
18824
|
+
remaining: "осталось",
|
|
18825
|
+
available: "Доступно",
|
|
18826
|
+
unavailable: "Недоступно",
|
|
18827
|
+
unlimited: "Без лимита",
|
|
18828
|
+
credits: "Credits",
|
|
18829
|
+
monthlySpend: "Месячный контроль расходов",
|
|
18830
|
+
resetCredits: "Сбросы",
|
|
18831
|
+
resetCreditExpires: "Истекает",
|
|
18832
|
+
useResetCredit: "Использовать сброс",
|
|
18833
|
+
usingResetCredit: "Используем…",
|
|
18834
|
+
useResetCreditConfirm: "Один сброс будет потрачен сразу, а подходящие окна лимита Codex сбросятся. Продолжить?",
|
|
18835
|
+
resetCreditUsed: "Сброс использован, данные о расходе обновлены.",
|
|
18836
|
+
spendControlReached: "Месячный контроль расходов сработал, новые вызовы по подписке могут быть ограничены.",
|
|
18837
|
+
limit: "Лимит",
|
|
18838
|
+
exhausted: "Квота исчерпана",
|
|
18839
|
+
resets: "Сброс",
|
|
18840
|
+
quickQuotaLabel: "Codex осталось",
|
|
18841
|
+
quickQuotaLoading: "Расход…",
|
|
18842
|
+
imageToolRunning: "Генерируем изображение",
|
|
18843
|
+
imageToolDone: "Изображение готово",
|
|
18844
|
+
imageToolFailed: "Не удалось создать изображение",
|
|
18845
|
+
image: "Изображение",
|
|
18846
|
+
openImage: "Открыть изображение",
|
|
18847
|
+
openNamedImage: "Открыть {name}",
|
|
18848
|
+
imageLoading: "Загружаем изображение…",
|
|
18849
|
+
imageLoadFailed: "Изображение не загрузилось, нажмите, чтобы повторить",
|
|
18850
|
+
imagePreviewClose: "Закрыть",
|
|
18851
|
+
imagePreviewOpenOriginal: "Открыть оригинал",
|
|
18852
|
+
retry: "Повторить",
|
|
18853
|
+
unknown: "Неизвестно",
|
|
18854
|
+
hubBack: "Подписки",
|
|
18855
|
+
hubOverviewHint: "Выберите провайдера, чтобы управлять аккаунтами, моделями и квотой; переключатель справа решает, показывать ли его в списке моделей.",
|
|
18856
|
+
hubAccountCount: "Аккаунтов: {count}",
|
|
18857
|
+
hubNoAccounts: "Аккаунтов пока нет — откройте, чтобы добавить",
|
|
18858
|
+
hubStateEnabled: "Включён",
|
|
18859
|
+
hubStateDisabled: "Выключен",
|
|
18860
|
+
hubModelsEnabled: "Доступно моделей: {count}",
|
|
18861
|
+
hubModelsEnabledOfTotal: "Доступно {count}/{total} моделей",
|
|
18862
|
+
hubStatusFailed: "Не удалось прочитать состояние",
|
|
18863
|
+
hubSwitchOn: "Включить {name}",
|
|
18864
|
+
hubSwitchOff: "Выключить {name}",
|
|
18865
|
+
hubCardLabel: "{name}, {annotation}",
|
|
18866
|
+
hubUpdateCheck: "Проверить обновления",
|
|
18867
|
+
hubUpdateChecking: "Проверяем…",
|
|
18868
|
+
hubUpdateApply: "Обновить до v{version}",
|
|
18869
|
+
hubUpdateApplying: "Обновляем…",
|
|
18870
|
+
hubUpdateUpToDate: "Уже последняя версия {version}",
|
|
18871
|
+
hubUpdateLatestWithUnknownCurrent: "Последняя версия {version}, текущая неизвестна",
|
|
18872
|
+
hubUpdateAvailable: "Доступна версия {version}, у вас {current}",
|
|
18873
|
+
hubUpdateInstalled: "Установлена v{version}, нужен перезапуск Host",
|
|
18874
|
+
hubUpdateInstalledReplaced: "Старая версия удалена, установлена v{version}, нужен перезапуск Host",
|
|
18875
|
+
hubUpdateInstalledLive: "Установлена v{version}, уже действует, перезапуск не нужен",
|
|
18876
|
+
hubUpdateInstalledReplacedLive: "Старая версия удалена, установлена v{version}, уже действует, перезапуск не нужен",
|
|
18877
|
+
hubUpdateFailedRestored: "Обновление не удалось, восстановлена v{version}",
|
|
18878
|
+
hubUpdateFailedRollbackFailed: "Обновление не удалось, и прежнюю версию поставить обратно не получилось — плагин может быть недоступен",
|
|
18879
|
+
hubUpdateFailedRollbackSkipped: "Обновление не удалось, и автоматически вернуть прежнюю версию нельзя — плагин мог быть удалён",
|
|
18880
|
+
hubUpdateDevelopmentInstall: "Доступна версия {version}; эта копия установлена локальной ссылкой и сама не обновится",
|
|
18881
|
+
hubUpdatePluginManagerMissing: "Доступна версия {version}; Host не предоставил pluginManager для установки",
|
|
18882
|
+
hubUpdateManualOnly: "Доступна версия {version}; этот способ установки не обновляется сам",
|
|
18883
|
+
hubUpdateCheckFailed: "Проверка не удалась: реестр npm недоступен, проверьте сеть или прокси",
|
|
18884
|
+
hubUpdateCommandLabel: "Команда для ручного обновления",
|
|
18885
|
+
localCodexLoginImport: "Импортировать вход локального Codex CLI",
|
|
18886
|
+
localCodexLoginImporting: "Импорт…",
|
|
18887
|
+
stopImporting: "Остановить импорт всех локальных входов",
|
|
18888
|
+
stopImportingLabel: "Остановить импорт всех локальных входов (сейчас {count})",
|
|
18889
|
+
stopImportingBusy: "Останавливаем импорт…",
|
|
18890
|
+
stopImportingHint: "Остановка лишь заставляет плагин забыть копию входа локального CLI; собственный файл входа Codex CLI не удаляется и не меняется. Пул аккаунтов не позволяет удалять заимствованные учётные данные по одному, поэтому здесь импорт останавливается сразу для всех.",
|
|
18891
|
+
modelChecklistCount: "Включено {count}/{total}"
|
|
18892
|
+
};
|
|
18893
|
+
//#endregion
|
|
18894
|
+
//#region src/client/locales-ru/kimi-code.ts
|
|
18895
|
+
const dictionary$6 = {
|
|
18896
|
+
...accountPoolRu,
|
|
18897
|
+
title: "Kimi Code",
|
|
18898
|
+
pageDesc: "Вход в подписку Kimi Code: модели, уровень рассуждений, контекстные окна и квота.",
|
|
18899
|
+
account: "Аккаунт",
|
|
18900
|
+
signedIn: "Вход выполнен",
|
|
18901
|
+
signedOut: "Вход не выполнен",
|
|
18902
|
+
nickname: "Никнейм",
|
|
18903
|
+
email: "Почта",
|
|
18904
|
+
plan: "Тариф",
|
|
18905
|
+
planUnknown: "—",
|
|
18906
|
+
region: "Регион",
|
|
18907
|
+
regionMainland: "Материковый Китай (kimi.com)",
|
|
18908
|
+
regionGlobal: "Мир (kimi.ai)",
|
|
18909
|
+
authenticatedAt: "Время входа",
|
|
18910
|
+
refreshRejected: "Токен обновления отклонён — войдите заново.",
|
|
18911
|
+
signIn: "Войти по коду устройства",
|
|
18912
|
+
signInAgain: "Войти заново",
|
|
18913
|
+
signingIn: "Вход…",
|
|
18914
|
+
signOut: "Выйти",
|
|
18915
|
+
cancelSignIn: "Отмена",
|
|
18916
|
+
deviceCodeSection: "Авторизация по коду устройства",
|
|
18917
|
+
deviceCodeHint: "Откройте ссылку ниже в браузере (код пользователя уже подставлен) и подтвердите её тем же аккаунтом.",
|
|
18918
|
+
openSignInPage: "Открыть страницу входа",
|
|
18919
|
+
copyCode: "Скопировать код пользователя",
|
|
18920
|
+
copied: "Скопировано",
|
|
18921
|
+
userCode: "Код пользователя",
|
|
18922
|
+
codeExpires: "Действует до",
|
|
18923
|
+
waitingAuthorization: "Ждём подтверждения в браузере…",
|
|
18924
|
+
requestingCode: "Запрашиваем код устройства…",
|
|
18925
|
+
connection: "Подключение",
|
|
18926
|
+
oauthHost: "Хост OAuth",
|
|
18927
|
+
codingEndpoint: "Эндпоинт моделей",
|
|
18928
|
+
testConnection: "Проверить подключение",
|
|
18929
|
+
testingConnection: "Проверка…",
|
|
18930
|
+
testSuccess: "Подключение в порядке",
|
|
18931
|
+
testFailed: "Подключение не удалось: Kimi Code не принял сохранённые учётные данные",
|
|
18932
|
+
routeOwned: "Маршрут моделей обслуживает этот плагин",
|
|
18933
|
+
routeConflict: "Маршрут моделей уже занят другим провайдером: {detail}. Удалите дублирующую конфигурацию провайдера в настройках DSH и повторите.",
|
|
18934
|
+
modelsSection: "Модели",
|
|
18935
|
+
modelsHint: "Отмеченные модели появляются в списке выбора модели в диалоге; если снять все отметки или выключить переключатель на карточке обзора, провайдер скроется из списка.",
|
|
18936
|
+
refreshCatalog: "Обновить каталог",
|
|
18937
|
+
refreshingCatalog: "Обновление…",
|
|
18938
|
+
selectAll: "Выбрать все",
|
|
18939
|
+
unselectAll: "Снять все",
|
|
18940
|
+
wireAnthropic: "Anthropic",
|
|
18941
|
+
wireOpenai: "OpenAI",
|
|
18942
|
+
capVideo: "Видео*",
|
|
18943
|
+
capDynamicTools: "Динамические инструменты",
|
|
18944
|
+
capImageOnly: "Изображения",
|
|
18945
|
+
capNone: "—",
|
|
18946
|
+
capVideoFootnote: "* Видео подключается инструментом kimi_attach_video (абсолютный локальный путь или ссылка http(s)); вставка и загрузка по-прежнему принимают только изображения.",
|
|
18947
|
+
capabilitiesTitle: "Возможности",
|
|
18948
|
+
capColMedia: "Мультимодальность",
|
|
18949
|
+
capColTools: "Динамические инструменты",
|
|
18950
|
+
capColNotes: "Примечания",
|
|
18951
|
+
capPlan: "Нужен тариф: {plan}",
|
|
18952
|
+
capInputCap: "Лимит ввода {tokens}",
|
|
18953
|
+
capNoTools: "Без инструментов",
|
|
18954
|
+
speedRegular: "Обычная",
|
|
18955
|
+
speedHighspeed: "Ускоренная (~6×)",
|
|
18956
|
+
quotaCost: "Множитель квоты",
|
|
18957
|
+
minimumPlan: "Нужный тариф",
|
|
18958
|
+
enhanced: "Рассуждения",
|
|
18959
|
+
defaultReasoningEffort: "Уровень рассуждений по умолчанию",
|
|
18960
|
+
defaultReasoningEffortHint: "Kimi Code принимает только low / high / max; none отключает рассуждения. Смена уровня сбрасывает кеш контекста, поэтому в пределах сессии держите его неизменным.",
|
|
18961
|
+
cacheTtl: "Время жизни кеша контекста",
|
|
18962
|
+
cacheTtlHint: "Kimi кеширует префиксы автоматически, здесь выбирается время записи. Запись на 1 ч стоит примерно вдвое дороже записи на 5 мин и окупается, только если тот же префикс перечитывается в течение часа. Уровень фиксируется при первой записи и позже не меняется. Пустое значение — поле не отправляется, решает Kimi (измеренное время жизни — примерно 5–30 минут). Выбирайте по паузе между ходами: если она обычно короче ~30 минут, оставьте пусто или 5 минут; для сессий с долгим простоем, например диспетчера, ждущего субагентов, — 1 час.",
|
|
18963
|
+
cacheTtlDefault: "Не задавать (по умолчанию Kimi)",
|
|
18964
|
+
cacheTtl5m: "5 минут",
|
|
18965
|
+
cacheTtl1h: "1 час",
|
|
18966
|
+
defaultEffortAuto: "Как в модели по умолчанию",
|
|
18967
|
+
effortLow: "Низкий",
|
|
18968
|
+
effortHigh: "Высокий",
|
|
18969
|
+
effortMax: "Максимальный",
|
|
18970
|
+
effortNone: "Рассуждения выкл.",
|
|
18971
|
+
contextWindowSection: "Контекстное окно модели",
|
|
18972
|
+
contextWindowHint: "По умолчанию берётся длина контекста из каталога. У k3 окно 1M доступно только на тарифе Allegretto и выше, поэтому по умолчанию считается 256K; после апгрейда значение можно переопределить до 1M.",
|
|
18973
|
+
contextWindowPlan: "Полное контекстное окно требует тарифа {plan}",
|
|
18974
|
+
contextWindowReset: "Вернуть по умолчанию",
|
|
18975
|
+
contextWindowResetAll: "Вернуть все по умолчанию",
|
|
18976
|
+
contextWindowResetAllConfirm: "Вернуть все изменённые контекстные окна моделей к значениям по умолчанию?",
|
|
18977
|
+
contextWindowNoneEnabled: "Ни одна модель не отмечена. Отметьте модель выше — здесь появятся её настройки контекстного окна.",
|
|
18978
|
+
save: "Сохранить",
|
|
18979
|
+
saved: "Сохранено",
|
|
18980
|
+
saving: "Сохранение…",
|
|
18981
|
+
cacheSection: "Кеш и настройка K3",
|
|
18982
|
+
cacheDesc: "Префиксный кеш Kimi срабатывает сам по содержимому запроса, объявить его вручную нельзя, поэтому единственное свидетельство работы — доля чтений из кеша.",
|
|
18983
|
+
cacheEmpty: "В этом процессе ещё не было запросов с отчётом о расходе.",
|
|
18984
|
+
cacheHitRatio: "Доля попаданий в кеш",
|
|
18985
|
+
cacheCached: "Токены из кеша",
|
|
18986
|
+
cacheFresh: "Новые токены",
|
|
18987
|
+
cacheOutput: "Выходные токены",
|
|
18988
|
+
cacheRequests: "Запросы",
|
|
18989
|
+
cacheHint: "В пределах одной сессии: любое изменение системного промпта или списка инструментов сбрасывает весь префиксный кеш, поэтому держите набор инструментов стабильным, а новое добавляйте в конец — так доля попаданий выше.",
|
|
18990
|
+
cacheExpired: "Сессия простаивала дольше времени жизни кеша, поэтому следующий ход заново обработает около {tokens} токенов.",
|
|
18991
|
+
cacheDrift: "Состояние последнего префикса",
|
|
18992
|
+
cacheDriftFirst: "Первый запрос (кеш пуст)",
|
|
18993
|
+
cacheDriftStable: "Стабильно (префикс не менялся)",
|
|
18994
|
+
cacheDriftSystemPrompt: "Системный промпт изменился (кеш сброшен)",
|
|
18995
|
+
cacheDriftTools: "Список инструментов изменился (кеш сброшен)",
|
|
18996
|
+
cacheDriftCacheKey: "Ключ кеша изменился (переключение сессии)",
|
|
18997
|
+
cacheDriftColdKey: "Ключ кеша не отправлен (попадание невозможно)",
|
|
18998
|
+
preserveThinking: "Сохранение рассуждений (Preserved Thinking)",
|
|
18999
|
+
preserveOn: "Включено (официальное значение по умолчанию): reasoning_content сохраняется между ходами, многошаговые вызовы инструментов идут связнее, но токены рассуждений входят в вывод.",
|
|
19000
|
+
preserveOff: "Выключено: сервис не просят возвращать рассуждения. Отключается через DSH_KIMI_CODE_PRESERVE_THINKING=0.",
|
|
19001
|
+
outputCap: "Лимит вывода следует за контекстным окном, поэтому длинные рассуждения не обрезаются на 32K",
|
|
19002
|
+
quotaSection: "Расход и квота",
|
|
19003
|
+
quotaDesc: "Данные из аккаунтного API Kimi Code; пока страница открыта, обновление не чаще раза в 60 секунд.",
|
|
19004
|
+
refreshQuota: "Обновить расход",
|
|
19005
|
+
refreshingQuota: "Обновление…",
|
|
19006
|
+
quotaEmpty: "Данных о квоте пока нет — нажмите «Обновить расход», чтобы повторить.",
|
|
19007
|
+
quotaPlan: "Текущий тариф",
|
|
19008
|
+
quotaWallet: "Баланс пакета",
|
|
19009
|
+
quotaWalletLimit: "Месячный лимит",
|
|
19010
|
+
quotaWalletUsed: "Израсходовано за месяц",
|
|
19011
|
+
updatedAt: "Обновлено: {time}",
|
|
19012
|
+
resetAt: "Сброс: {time}",
|
|
19013
|
+
loading: "Загрузка…",
|
|
19014
|
+
loginFailed: "Вход не выполнен",
|
|
19015
|
+
requests: "запросов",
|
|
19016
|
+
tokens: "токенов"
|
|
19017
|
+
};
|
|
19018
|
+
//#endregion
|
|
19019
|
+
//#region src/client/locales-ru/minimax-code.ts
|
|
19020
|
+
const dictionary$5 = {
|
|
19021
|
+
...accountPoolRu,
|
|
19022
|
+
title: "MiniMax Code",
|
|
19023
|
+
pageDesc: "Вход в подписку MiniMax Code для программирования (OAuth по коду устройства) с переиспользованием локального входа MiniMax Code: управление аккаунтом, подключением и моделями.",
|
|
19024
|
+
account: "Аккаунт",
|
|
19025
|
+
signedIn: "Вход выполнен",
|
|
19026
|
+
signedOut: "Вход не выполнен",
|
|
19027
|
+
accountLabel: "Метка аккаунта",
|
|
19028
|
+
accountId: "ID аккаунта",
|
|
19029
|
+
email: "Email",
|
|
19030
|
+
region: "Регион",
|
|
19031
|
+
regionCn: "Материковый Китай (minimax.cn)",
|
|
19032
|
+
regionGlobal: "Международный (minimax.io)",
|
|
19033
|
+
expiresAt: "Токен истекает",
|
|
19034
|
+
expiresRemaining: "осталось {minutes} мин",
|
|
19035
|
+
expiresExpired: "Истёк",
|
|
19036
|
+
expiresHint: "Access-токен живёт около часа; Host обновляет его, когда срок истёк или апстрим отвечает 401. Если обновление отклонено, войдите заново в MiniMax Code.",
|
|
19037
|
+
signIn: "Войти в MiniMax Code",
|
|
19038
|
+
signingIn: "Запрашиваем код устройства…",
|
|
19039
|
+
signOut: "Выйти",
|
|
19040
|
+
cancelSignIn: "Отменить",
|
|
19041
|
+
deviceCodeSection: "Авторизация по коду устройства",
|
|
19042
|
+
deviceCodeHint: "Откройте ссылку ниже в браузере (код пользователя показан отдельно, его можно скопировать) и подтвердите авторизацию своим аккаунтом MiniMax.",
|
|
19043
|
+
userCode: "Код пользователя",
|
|
19044
|
+
copyCode: "Копировать код",
|
|
19045
|
+
copied: "Скопировано",
|
|
19046
|
+
openSignInPage: "Открыть страницу авторизации",
|
|
19047
|
+
codeExpires: "Код устройства истекает",
|
|
19048
|
+
codeMinutes: "осталось {minutes} мин",
|
|
19049
|
+
waitingAuthorization: "Ждём подтверждения в браузере…",
|
|
19050
|
+
loginFailed: "Вход не удался",
|
|
19051
|
+
loginExpired: "Код устройства истёк — начните вход заново.",
|
|
19052
|
+
loginDenied: "В авторизации отказано.",
|
|
19053
|
+
logoutOwnedByApp: "Этот вход принадлежит приложению MiniMax Code. Плагин переиспользует его и при необходимости продлевает на месте, но не отзывает и не удаляет (иначе вы выйдете из работающего приложения MiniMax Code). Выходите из аккаунта в самом приложении MiniMax Code.",
|
|
19054
|
+
connection: "Подключение",
|
|
19055
|
+
routeOwned: "Этот плагин обслуживает маршрут модели.",
|
|
19056
|
+
routeConflict: "Маршрут модели уже занят другим провайдером: {detail}. Удалите дублирующую конфигурацию провайдера в настройках DSH и перезагрузите.",
|
|
19057
|
+
testConnection: "Проверить подключение",
|
|
19058
|
+
testingConnection: "Проверка…",
|
|
19059
|
+
testSuccess: "Подключение в порядке",
|
|
19060
|
+
testSuccessModel: "Подключение в порядке ({model})",
|
|
19061
|
+
testFailed: "Подключение не удалось",
|
|
19062
|
+
modelsSection: "Модели",
|
|
19063
|
+
modelsHint: "Каталог моделей жёстко задан на этой линии (MiniMax Code не открывает /v1/models): доступно моделей — {count}. В списке выбора модели в чате видны только отмеченные; снятая отметка или выключенный «Включить этого провайдера» скрывают линию из списка.",
|
|
19064
|
+
modelsUnavailable: "Пока нет моделей для показа.",
|
|
19065
|
+
quotaSection: "Расход и квота",
|
|
19066
|
+
dailyCheckin: "Ежедневная отметка",
|
|
19067
|
+
checkinHint: "Отмечается учётными данными самой линии (тот же интерфейс, что у официального клиента MiniMax Code). Host отмечается один раз при запуске и перепроверяет каждые 10 минут, пока работает; день, в который процесс не запускался, не отмечается.",
|
|
19068
|
+
checkinAuto: "Автоотметка",
|
|
19069
|
+
checkinToday: "Отмечено сегодня {done}/{total}",
|
|
19070
|
+
checkinSkipped: "{count} пока нельзя",
|
|
19071
|
+
checkinFailed: "ошибок: {count}",
|
|
19072
|
+
checkinStreak: "Серия: {days} дн.",
|
|
19073
|
+
checkinClaimed: "+{points} кредитов за этот прогон",
|
|
19074
|
+
checkinLastRun: "Последний прогон: {time}",
|
|
19075
|
+
checkinNever: "Ещё не запускалось",
|
|
19076
|
+
checkinNow: "Отметиться сейчас",
|
|
19077
|
+
checkinRunning: "Отмечаемся…",
|
|
19078
|
+
quotaUnavailable: "Данных о расходе пока нет.",
|
|
19079
|
+
quotaNeedsApiKey: "Сервис отклонил этот вход для чтения расхода (эндпоинт официального клиента ждёт заголовки собственной атрибуции, а плагин по умолчанию их не подделывает). Смотрите расход Token Plan в полосе расхода консоли MiniMax; если такой размен вас устраивает, задайте DSH_MINIMAX_CODE_QUOTA_ATTRIBUTION=1 и повторите.",
|
|
19080
|
+
quotaUnreachable: "Расход временно не читается (эндпоинт расхода не ответил); повторим автоматически.",
|
|
19081
|
+
quotaTokenExpired: "Токен истёк как раз во время чтения расхода и уже продлевается автоматически. Аккаунт остаётся в состоянии входа, ничего делать не нужно.",
|
|
19082
|
+
quotaStale: "Ниже последний успешно прочитанный расход (это обновление не удалось); повторим автоматически.",
|
|
19083
|
+
quotaUsedShare: "израсходовано {percent}%",
|
|
19084
|
+
quotaRefresh: "Обновить расход",
|
|
19085
|
+
quotaRefreshing: "Обновление…",
|
|
19086
|
+
resetSection: "Сброс квоты",
|
|
19087
|
+
resetHint: "Карты сброса из подписки мгновенно сбрасывают лимит расхода. Выберите карту и подтвердите её расходование.",
|
|
19088
|
+
resetConfirm: "Выберите карту и подтвердите её расходование. После этого расход перечитается; диалог заново не отправляется.",
|
|
19089
|
+
resetAvailable: "Доступно карт сброса: {count}",
|
|
19090
|
+
resetNone: "Сейчас нет доступных карт сброса.",
|
|
19091
|
+
resetUnavailable: "Карты сброса сейчас не читаются (вход не выполнен или у аккаунта нет этой функции).",
|
|
19092
|
+
resetExpires: "Истекает {time}",
|
|
19093
|
+
resetUse: "Использовать",
|
|
19094
|
+
resetUsing: "Сбрасываем…",
|
|
19095
|
+
resetRefresh: "Обновить карты",
|
|
19096
|
+
resetRefreshing: "Читаем…",
|
|
19097
|
+
resetFlowTitle: "Последние 30 дней",
|
|
19098
|
+
resetFlowEmpty: "За последние 30 дней операций с картами сброса не было.",
|
|
19099
|
+
resetFlowGrant: "Выдана",
|
|
19100
|
+
resetFlowUse: "Использована",
|
|
19101
|
+
resetOutcomeSuccess: "Сброс выполнен.",
|
|
19102
|
+
resetOutcomeReplayed: "Эта карта уже использована; состояние лимита обновлено.",
|
|
19103
|
+
resetOutcomeUncertain: "Результат неопределён. Повторите с ТОЙ ЖЕ картой, чтобы убедиться: повтор не тратит вторую карту, а переход на другую карту — тратит.",
|
|
19104
|
+
resetOutcomeExpired: "Эта карта истекла и не может сбросить лимит; список обновлён.",
|
|
19105
|
+
resetOutcomeNotFound: "Такой карты нет или она больше не пригодна; список обновлён.",
|
|
19106
|
+
composerLabel: "Квота",
|
|
19107
|
+
selectAll: "Выбрать все",
|
|
19108
|
+
unselectAll: "Снять все",
|
|
19109
|
+
enhanced: "Расширенные",
|
|
19110
|
+
defaultReasoningEffort: "Уровень рассуждений по умолчанию",
|
|
19111
|
+
defaultReasoningEffortHint: "Сила рассуждений для моделей с рассуждениями, когда в диалоге уровень не выбран.",
|
|
19112
|
+
defaultEffortAuto: "Авто (по умолчанию у каждой модели)",
|
|
19113
|
+
contextWindowSection: "Контекстные окна моделей",
|
|
19114
|
+
contextWindowHint: "Значения по умолчанию берутся из каталога моделей шлюза подписки (реальный верхний предел каждой модели). Можно переопределить на свою ёмкость; это значение DSH использует при сжатии и определении переполнения. Принимаются 1M, 512K, 200K и подобные.",
|
|
19115
|
+
contextWindowNoneEnabled: "Ни одна модель не отмечена — выберите её в блоке «Модели» выше.",
|
|
19116
|
+
contextWindowReset: "Вернуть по умолчанию",
|
|
19117
|
+
contextWindowResetAll: "Вернуть все по умолчанию",
|
|
19118
|
+
tokens: "токены",
|
|
19119
|
+
save: "Сохранить",
|
|
19120
|
+
saving: "Сохранение…",
|
|
19121
|
+
invalidCapacity: "Неверный формат ёмкости: {value}",
|
|
19122
|
+
thinkingAlwaysOn: "Всегда включено (без уровней)",
|
|
19123
|
+
thinkingToggle: "Можно отключить",
|
|
19124
|
+
thinkingForced: "Принудительно включено (уровень выбирается)",
|
|
19125
|
+
capText: "Текст",
|
|
19126
|
+
capImage: "Изображение",
|
|
19127
|
+
loading: "Загрузка…",
|
|
19128
|
+
unknown: "—",
|
|
19129
|
+
videoToolTitle: "Видео",
|
|
19130
|
+
videoToolRunning: "Генерируем видео",
|
|
19131
|
+
videoToolDone: "Видео готово",
|
|
19132
|
+
videoToolFailed: "Генерация видео не удалась",
|
|
19133
|
+
videoGenerating: "Апстрим ещё генерирует — видео появится здесь, когда будет готово.",
|
|
19134
|
+
videoReading: "Читаем видео",
|
|
19135
|
+
videoTooLarge: "Видео превышает предел полного чтения файла {limit}; системный проигрыватель всё равно его откроет.",
|
|
19136
|
+
videoUnreadable: "Байты видео прочитать не удалось — файл могли переместить или удалить.",
|
|
19137
|
+
videoUnplayable: "Байты видео не открываются для воспроизведения.",
|
|
19138
|
+
videoNoMeta: "В этом вызове не сохранилось информации о видео, поэтому файл не найти.",
|
|
19139
|
+
videoChannelOff: "Канал чтения файлов здесь недоступен, поэтому воспроизведение невозможно.",
|
|
19140
|
+
videoFailed: "Эта генерация не удалась, воспроизводить нечего.",
|
|
19141
|
+
videoSize: "{size}",
|
|
19142
|
+
videoTitle: "Видео",
|
|
19143
|
+
videoCommandLabel: "Сгенерировать видео",
|
|
19144
|
+
videoCommandDesc: "Опишите клип, выберите параметры и заполните поле ввода",
|
|
19145
|
+
videoPresetGroup: "Пресеты",
|
|
19146
|
+
videoPresetCustom: "Свой…",
|
|
19147
|
+
videoPresetCustomDesc: "Открыть полную форму параметров",
|
|
19148
|
+
videoDialogTitle: "Сгенерировать видео",
|
|
19149
|
+
videoDialogDesc: "Форма заполняет поле ввода — проверьте текст перед отправкой",
|
|
19150
|
+
videoPromptLabel: "Описание",
|
|
19151
|
+
videoPromptPlaceholder: "Опишите клип, например «берег на закате, волны бьют о камни, медленная панорама»",
|
|
19152
|
+
videoPromptRequired: "Сначала заполните промпт",
|
|
19153
|
+
videoModelLabel: "Модель",
|
|
19154
|
+
videoRatioLabel: "Соотношение сторон",
|
|
19155
|
+
videoRatioLockedKeyframes: "Задан первый или последний кадр, поэтому соотношение фиксировано: adaptive",
|
|
19156
|
+
videoRatioLockedTextOnly: "Для текста без медиа adaptive недоступен: адаптировать не к чему",
|
|
19157
|
+
videoDurationLabel: "Длительность",
|
|
19158
|
+
videoDurationUnit: "с",
|
|
19159
|
+
videoResolutionLabel: "Разрешение",
|
|
19160
|
+
videoWatermarkLabel: "Водяной знак AIGC",
|
|
19161
|
+
videoMediaSection: "Референсные медиа",
|
|
19162
|
+
videoMediaHint: "Перетащите файл, вставьте путь или ссылку либо выберите через обзор",
|
|
19163
|
+
videoInputImageLabel: "Первый кадр",
|
|
19164
|
+
videoLastFrameLabel: "Последний кадр",
|
|
19165
|
+
videoReferenceImagesLabel: "Референсные изображения",
|
|
19166
|
+
videoReferenceVideosLabel: "Референсные видео",
|
|
19167
|
+
videoReferenceVideoDurationsLabel: "Длительность референсных видео",
|
|
19168
|
+
videoReferenceAudiosLabel: "Референсное аудио",
|
|
19169
|
+
videoMediaUnsupported: "{model} не принимает референсные изображения, видео или аудио",
|
|
19170
|
+
videoLastFrameUnsupported: "{model} не принимает изображение последнего кадра",
|
|
19171
|
+
videoTooManyImages: "Референсных изображений: {count}, принимается не больше {limit}",
|
|
19172
|
+
videoTooManyVideos: "Референсных видео: {count}, принимается не больше {limit}",
|
|
19173
|
+
videoTooManyAudios: "Референсных аудиофайлов: {count}, принимается не больше {limit}",
|
|
19174
|
+
videoTooManyTotal: "Референсных медиа всего: {count}, принимается не больше {limit}",
|
|
19175
|
+
videoDurationInvalid: "{model} не поддерживает {duration} с",
|
|
19176
|
+
videoMediaBrowse: "Обзор…",
|
|
19177
|
+
videoMediaAdd: "Добавить",
|
|
19178
|
+
videoMediaAddMore: "Добавить ещё",
|
|
19179
|
+
videoMediaManualPlaceholder: "Перетащите файл или введите путь / @файл рабочей области",
|
|
19180
|
+
videoMediaSuggestLabel: "Файлы рабочей области",
|
|
19181
|
+
videoMediaSuggestFolder: "каталог",
|
|
19182
|
+
videoMediaPaste: "Вставить",
|
|
19183
|
+
videoMediaDragHint: "Перетащите сюда",
|
|
19184
|
+
videoMediaDragActive: "Отпустите, чтобы добавить",
|
|
19185
|
+
videoMediaRemove: "Удалить {name}",
|
|
19186
|
+
videoMediaEmpty: "Файлов пока нет",
|
|
19187
|
+
videoMediaUrlRejected: "Сервис не будет читать эту ссылку — нужен локальный путь или адрес CDN MiniMax",
|
|
19188
|
+
videoReferenceVideoDurationOne: "Длительность {name}",
|
|
19189
|
+
videoReferenceVideoDurationPlaceholder: "секунд",
|
|
19190
|
+
videoReferenceVideoDurationWhy: "У видео по ссылке длину отсюда не прочитать; без неё отправку отклонят",
|
|
19191
|
+
videoUrlNeedsDuration: "Референсное видео задано ссылкой CDN — укажите ниже его длину в секундах",
|
|
19192
|
+
videoMediaNoPath: "У этого файла здесь нет локального пути — выберите его через обзор или вставьте путь.",
|
|
19193
|
+
videoTierLabel: "Уровень",
|
|
19194
|
+
videoAdvanced: "Дополнительные параметры",
|
|
19195
|
+
videoPromptFromComposer: "Взято из текста в поле ввода",
|
|
19196
|
+
videoSubmit: "Заполнить поле ввода",
|
|
19197
|
+
videoCancel: "Отмена",
|
|
19198
|
+
videoClose: "Закрыть",
|
|
19199
|
+
videoDraftFilled: "Параметры в поле ввода — отправьте, когда будете готовы",
|
|
19200
|
+
videoDraftFailed: "В этой сессии нет поля ввода, поэтому ничего не вставлено",
|
|
19201
|
+
videoNotMinimax: "Команда доступна только в сессии MiniMax Code",
|
|
19202
|
+
videoDefaultsSection: "Параметры видео по умолчанию",
|
|
19203
|
+
videoDefaultsHint: "Начальные значения формы /video; они только заполняют форму и ничего не генерируют",
|
|
19204
|
+
videoDefaultsSaved: "Сохранено",
|
|
19205
|
+
videoHistorySection: "История генераций видео",
|
|
19206
|
+
videoHistoryHint: "Последние генерации; хранятся только пути, содержимое видео не сохраняется",
|
|
19207
|
+
videoHistoryEmpty: "Генераций пока нет",
|
|
19208
|
+
videoHistoryUnavailable: "История видео сейчас не читается",
|
|
19209
|
+
videoHistoryRefresh: "Обновить",
|
|
19210
|
+
videoHistoryRefreshing: "Читаем…",
|
|
19211
|
+
videoHistoryAt: "{time}",
|
|
19212
|
+
videoHistoryMeta: "{model} · {ratio} · {duration} с · {size}",
|
|
19213
|
+
videoHistoryNoRatio: "соотношение не задано",
|
|
19214
|
+
videoHistoryStorage: "Хранится в {path}",
|
|
19215
|
+
videoHistoryEncrypted: "Зашифровано системным хранилищем учётных данных",
|
|
19216
|
+
videoHistoryPlain: "На этом хосте нет хранилища учётных данных; хранится в открытом виде"
|
|
19217
|
+
};
|
|
19218
|
+
//#endregion
|
|
19219
|
+
//#region src/client/locales-ru/ollama.ts
|
|
19220
|
+
const dictionary$4 = {
|
|
19221
|
+
...accountPoolRu,
|
|
19222
|
+
relogin: "Заменить ключ",
|
|
19223
|
+
needsRelogin: "Ключ отклонён",
|
|
19224
|
+
addAccount: "Добавить API-ключ",
|
|
19225
|
+
noAccounts: "API-ключей пока нет. Нажмите «Добавить API-ключ» и вставьте ключ с ollama.com.",
|
|
19226
|
+
title: "Ollama",
|
|
19227
|
+
pageDesc: "Подключите Ollama Cloud с несколькими API-ключами в пуле для ротации и переключения при сбоях.",
|
|
19228
|
+
routeOwned: "Маршрут моделей обслуживает этот плагин",
|
|
19229
|
+
routeConflict: "Маршрут моделей уже занят другим провайдером: {detail}",
|
|
19230
|
+
keySection: "Добавить API-ключ",
|
|
19231
|
+
keyHint: "Создайте ключ на https://ollama.com/settings/keys и вставьте его сюда. Ключи не истекают, отозвать их можно на той же странице.",
|
|
19232
|
+
keyPlaceholder: "Вставьте API-ключ Ollama",
|
|
19233
|
+
keyAliasLabel: "Метка (необязательно)",
|
|
19234
|
+
keyAliasPlaceholder: "например, основной, резервный",
|
|
19235
|
+
keyAliasHint: "Ollama не сообщает, какому аккаунту принадлежит ключ, поэтому ключи различают по метке.",
|
|
19236
|
+
keySave: "Добавить",
|
|
19237
|
+
keySaving: "Добавление…",
|
|
19238
|
+
modelsSection: "Модели",
|
|
19239
|
+
modelsHint: "Список приходит из Ollama «/api/tags» и следует за сервисом — вести его вручную не нужно.",
|
|
19240
|
+
catalogSync: "Синхронизировать список моделей",
|
|
19241
|
+
catalogSyncing: "Синхронизация…",
|
|
19242
|
+
catalogNeverSynced: "Список моделей ещё не синхронизирован. Нажмите «Синхронизировать список моделей» выше, чтобы получить модели, доступные вашему аккаунту: до этого список пуст, и линия не появится в выборе моделей.",
|
|
19243
|
+
catalogEmpty: "Ollama не вернула ни одной модели.",
|
|
19244
|
+
catalogNeedKey: "Сначала добавьте API-ключ, потом синхронизируйте список моделей.",
|
|
19245
|
+
catalogFailed: "Не удалось прочитать список моделей из Ollama.",
|
|
19246
|
+
modelCount: "Моделей: {count}",
|
|
19247
|
+
noModels: "Доступных моделей нет.",
|
|
19248
|
+
selectAll: "Выбрать все",
|
|
19249
|
+
unselectAll: "Снять все",
|
|
19250
|
+
noneSelected: "Модели не выбраны, поэтому эта линия не появится в выборе моделей.",
|
|
19251
|
+
enhanced: "Дополнительные возможности",
|
|
19252
|
+
defaultReasoningEffort: "Уровень рассуждений по умолчанию",
|
|
19253
|
+
defaultReasoningEffortHint: "Действует только на модели, которые принимают управление уровнем рассуждений. Допустимые уровни задаёт сама модель: семейство gpt-oss принимает low / medium / high, семейство deepseek-r1 — только включено или выключено, остальные управления не принимают, а Host сужает сохранённый уровень до допустимого для целевой модели. Выберите «Не задавать», чтобы каждая модель осталась на своём значении по умолчанию.",
|
|
19254
|
+
defaultEffortAuto: "Не задавать",
|
|
19255
|
+
limitsSection: "Документированные ограничения",
|
|
19256
|
+
limitsHint: "Ollama Cloud документирует эти ограничения; линия их не обходит:",
|
|
19257
|
+
limitNoStateful: "Нет Responses с сохранением состояния (только без состояния).",
|
|
19258
|
+
limitNoWebSearch: "Нет встроенного поиска в вебе через /v1/responses.",
|
|
19259
|
+
limitNoToolReplay: "Нет воспроизведения (replay) вызовов собственных инструментов.",
|
|
19260
|
+
limitUsage: "У Ollama нет API квоты и остатка баланса (upstream-issue #15132 и #15663 закрыты), поэтому карточка показывает, сколько израсходовано, но не сколько осталось.",
|
|
19261
|
+
wireNote: "Запросы идут через OpenAI-совместимую поверхность (/v1) и при необходимости откатываются на нативную (/api/chat).",
|
|
19262
|
+
lastModel: "Последняя модель",
|
|
19263
|
+
keyCreated: "Добавлен",
|
|
19264
|
+
error: "Действие не выполнено: {detail}",
|
|
19265
|
+
usageTitle: "Израсходовано всего",
|
|
19266
|
+
usageInput: "вход {tokens}",
|
|
19267
|
+
usageOutput: "выход {tokens}",
|
|
19268
|
+
usageRequests: "Запросов: {count}",
|
|
19269
|
+
usageNone: "Запросов ещё не было",
|
|
19270
|
+
usageHint: "Суммируется локально по счётчикам токенов, которые Ollama возвращает в каждом ответе."
|
|
19271
|
+
};
|
|
19272
|
+
//#endregion
|
|
19273
|
+
//#region src/client/locales-ru/opendesign.ts
|
|
19274
|
+
const dictionary$3 = {
|
|
19275
|
+
...accountPoolRu,
|
|
19276
|
+
relogin: "Добавить заново",
|
|
19277
|
+
needsRelogin: "API-ключ недействителен",
|
|
19278
|
+
addAccount: "Добавить API-ключ",
|
|
19279
|
+
noAccounts: "Аккаунтов пока нет. Нажмите «Добавить API-ключ» и вставьте ключ, созданный в консоли OpenDesign Cloud.",
|
|
19280
|
+
title: "OpenDesign",
|
|
19281
|
+
pageDesc: "Подключите подписку OpenDesign: создайте API-ключ в консоли Cloud и вставьте его сюда, чтобы вызывать её шлюз моделей за счёт кредитов тарифа. Аккаунты в пуле ротируются автоматически.",
|
|
19282
|
+
login: "Войти в аккаунт OpenDesign",
|
|
19283
|
+
loggingIn: "Вход…",
|
|
19284
|
+
loginHint: "Откройте страницу активации в браузере и подтвердите код ниже; аккаунт сам добавится в пул, вставлять ключ не нужно.",
|
|
19285
|
+
loginCode: "Код авторизации",
|
|
19286
|
+
loginOpen: "Открыть страницу активации",
|
|
19287
|
+
loginWaiting: "Ждём подтверждения в браузере…",
|
|
19288
|
+
loginCancel: "Отменить вход",
|
|
19289
|
+
loginIdle: "В этом процессе вход ещё не начинался.",
|
|
19290
|
+
loginHaveAccounts: "В пуле уже {count} рабочих аккаунтов.",
|
|
19291
|
+
loginComplete: "Вход выполнен: {account}",
|
|
19292
|
+
loginCompleteNoAccount: "Прошлый вход завершился, но рабочих аккаунтов в пуле сейчас нет.",
|
|
19293
|
+
loginFailed: "Вход не выполнен: {detail}",
|
|
19294
|
+
useApiKey: "Добавить API-ключ",
|
|
19295
|
+
oauthAccount: "Вход через браузер",
|
|
19296
|
+
apiKeyAccount: "API-ключ",
|
|
19297
|
+
routeOwned: "Маршрут моделей обслуживает этот плагин",
|
|
19298
|
+
routeConflict: "Маршрут моделей уже занят другим провайдером: {detail}",
|
|
19299
|
+
error: "Действие не выполнено: {detail}",
|
|
19300
|
+
saved: "Сохранено",
|
|
19301
|
+
keySection: "Добавить API-ключ",
|
|
19302
|
+
keyHint: "Создайте ключ в консоли OpenDesign Cloud (рабочее пространство → API Keys) и вставьте его сюда.",
|
|
19303
|
+
keyConsoleLink: "Открыть консоль OpenDesign Cloud",
|
|
19304
|
+
keyPlaceholder: "Вставьте API-ключ OpenDesign",
|
|
19305
|
+
keyAliasLabel: "Метка (необязательно)",
|
|
19306
|
+
keyAliasPlaceholder: "например, основной, резервный",
|
|
19307
|
+
keyAliasHint: "Шлюз не сообщает, какому аккаунту принадлежит ключ, поэтому ключи различают по метке.",
|
|
19308
|
+
keyBaseUrlLabel: "Свой адрес шлюза (необязательно)",
|
|
19309
|
+
keyBaseUrlPlaceholder: "по умолчанию: https://amr-link.open-design.ai/v1",
|
|
19310
|
+
keySave: "Добавить",
|
|
19311
|
+
keySaving: "Добавление…",
|
|
19312
|
+
keyTest: "Проверить ключ",
|
|
19313
|
+
cancel: "Отмена",
|
|
19314
|
+
keyTesting: "Проверка…",
|
|
19315
|
+
keyTestOk: "Ключ работает ({ms} мс, моделей доступно: {count})",
|
|
19316
|
+
keyTestFailed: "Ключ отклонён: {detail}",
|
|
19317
|
+
testSavedKey: "Проверить",
|
|
19318
|
+
modelsSection: "Модели",
|
|
19319
|
+
modelsHint: "Список начинается со встроенной таблицы; добавление ключа один раз синхронизирует живой каталог, доступный этому ключу, а кнопка обновления синхронизирует его снова. Неотмеченные модели в выборе моделей не появляются.",
|
|
19320
|
+
modelChecklistCount: "Выбрано {count} из {total}",
|
|
19321
|
+
selectAll: "Выбрать все",
|
|
19322
|
+
unselectAll: "Снять все",
|
|
19323
|
+
catalogSync: "Обновить каталог",
|
|
19324
|
+
catalogSyncing: "Обновление…",
|
|
19325
|
+
catalogNeverSynced: "Живой каталог ещё не синхронизирован, показана встроенная таблица. Добавление ключа синхронизирует его один раз автоматически; кнопка обновления — ещё раз.",
|
|
19326
|
+
catalogSyncedNote: "Живой каталог синхронизирован: моделей {count}.",
|
|
19327
|
+
noModels: "Доступных моделей нет.",
|
|
19328
|
+
pricingNote: "Цены — официальный публичный прайс (доллары США за 1 млн токенов, вход / выход).",
|
|
19329
|
+
contextSection: "Контекстные окна",
|
|
19330
|
+
contextHint: "Производитель не публикует контекстные окна по моделям, поэтому по умолчанию берётся 128k; здесь любую модель можно поправить. Неверное значение не сохраняется, а показывается ошибкой; восстановление сбрасывает переопределение.",
|
|
19331
|
+
tokens: "токены",
|
|
19332
|
+
contextSave: "Сохранить",
|
|
19333
|
+
contextOverridden: "переопределено",
|
|
19334
|
+
contextSaving: "Сохранение",
|
|
19335
|
+
contextReset: "Вернуть значение по умолчанию",
|
|
19336
|
+
contextResetAll: "Вернуть все значения",
|
|
19337
|
+
contextEmpty: "Отметьте хотя бы одну модель, чтобы настроить её контекстное окно.",
|
|
19338
|
+
advancedSection: "Дополнительно",
|
|
19339
|
+
baseURL: "Шлюз по умолчанию",
|
|
19340
|
+
defaultContextWindow: "Контекстное окно по умолчанию",
|
|
19341
|
+
defaultMaxTokens: "Бюджет вывода по умолчанию",
|
|
19342
|
+
maxConcurrentRequests: "Потоков на аккаунт (0 — без ограничения)",
|
|
19343
|
+
streamIdleTimeoutMs: "Таймаут простоя потока (мс)",
|
|
19344
|
+
saveSettings: "Сохранить настройки",
|
|
19345
|
+
savingSettings: "Сохранение…",
|
|
19346
|
+
limitsSection: "Примечания",
|
|
19347
|
+
usageSection: "Тариф и кредиты",
|
|
19348
|
+
usageHint: "Тариф и кредиты берутся из сводки по счёту; у аккаунтов, вошедших через браузер, есть контрольный ключ, и при открытии страницы они читаются автоматически. У вставленного API-ключа контрольного ключа нет — смотрите данные в консоли OpenDesign Cloud.",
|
|
19349
|
+
usageRefresh: "Обновить тариф и кредиты",
|
|
19350
|
+
usageRefreshing: "Обновление…",
|
|
19351
|
+
usageEmpty: "Тариф и кредиты ещё не читались.",
|
|
19352
|
+
usageUnavailable: "Не удалось прочитать тариф и кредиты: {detail}",
|
|
19353
|
+
usageBalance: "Баланс кошелька ${amount}",
|
|
19354
|
+
usageReadAt: "Прочитано {time}",
|
|
19355
|
+
usagePlan: "Тариф {plan}",
|
|
19356
|
+
usagePlanActive: "активен",
|
|
19357
|
+
usagePlanInactive: "статус {status}",
|
|
19358
|
+
usagePeriod: "Период {start} → {end}",
|
|
19359
|
+
usageSubscriptionCredits: "Кредиты подписки {credits} (${usd})",
|
|
19360
|
+
usageRechargeCredits: "Кредиты пополнения {credits} (${usd})",
|
|
19361
|
+
usageTotalCredits: "Всего доступно {credits} (${usd})",
|
|
19362
|
+
usageTodayConsumed: "Израсходовано сегодня ${amount}",
|
|
19363
|
+
usageTotalConsumed: "Израсходовано всего ${amount}",
|
|
19364
|
+
usageUsageCount: "Платных запросов: {count}",
|
|
19365
|
+
usagePlanUnknown: "Кредиты прочитаны, но сервис не указал тариф.",
|
|
19366
|
+
limitKey: "API-ключи хранятся в системном хранилище учётных данных; карточка никогда не показывает сам ключ.",
|
|
19367
|
+
limitGateway: "Запросы обслуживает шлюз OpenDesign, он же выбирает фактического провайдера.",
|
|
19368
|
+
limitRoute: "Маршрут занимается по provider id: если opendesign уже обслуживает другой плагин, эта карточка по-прежнему настраивает линию, но запросы выполняет тот провайдер.",
|
|
19369
|
+
limitQuota: "Тариф и кредиты читаются только у аккаунтов, вошедших через браузер; у вставленного API-ключа контрольного ключа нет, поэтому расход смотрите в консоли OpenDesign Cloud."
|
|
19370
|
+
};
|
|
19371
|
+
//#endregion
|
|
19372
|
+
//#region src/client/locales-ru/progress-updates.ts
|
|
19373
|
+
const dictionary$2 = {
|
|
19374
|
+
navTitle: "Ход работы",
|
|
19375
|
+
progressTitle: "Ход работы",
|
|
19376
|
+
progressGuideNote: "Каждый шаг, о котором сообщает агент, собирается здесь",
|
|
19377
|
+
markdownCopy: "Копировать",
|
|
19378
|
+
markdownCopied: "Скопировано",
|
|
19379
|
+
markdownFootnotes: "Сноски",
|
|
19380
|
+
progressLatest: "Последний",
|
|
19381
|
+
progressCount: "всего {n}",
|
|
19382
|
+
progressExpand: "Развернуть эту запись",
|
|
19383
|
+
progressCollapse: "Свернуть эту запись",
|
|
19384
|
+
progressEmptyTitle: "Записей о ходе работы пока нет",
|
|
19385
|
+
progressEmptyHint: "Когда агент начнёт многошаговую задачу, он будет сообщать здесь, на каком шаге находится.",
|
|
19386
|
+
rowPending: "Ход работы",
|
|
19387
|
+
rowRunning: "Сообщает",
|
|
19388
|
+
rowDone: "Сообщено",
|
|
19389
|
+
rowError: "Не отправлено",
|
|
19390
|
+
rowExpand: "Развернуть подробности записи",
|
|
19391
|
+
rowCollapse: "Свернуть подробности записи",
|
|
19392
|
+
settingsHint: "Ход работы позволяет агенту сообщать о продвижении многошаговой задачи. Откройте панель, чтобы прочитать всё, что он сообщил.",
|
|
19393
|
+
settingsOpen: "Открыть панель хода работы",
|
|
19394
|
+
settingsEnabledName: "Ход работы",
|
|
19395
|
+
settingsEnabledNote: "Разрешить агенту публиковать ход работы в диалоге",
|
|
19396
|
+
settingsThresholdName: "Порог напоминания",
|
|
19397
|
+
settingsThresholdNote: "Напомнить агенту после стольких раундов без отчёта",
|
|
19398
|
+
settingsPanelName: "Панель хода работы",
|
|
19399
|
+
settingsPanelNote: "Показывать все записи этой сессии в правой панели",
|
|
19400
|
+
settingsUnavailable: "Эту настройку сейчас нельзя изменить (Host не предоставляет форму настроек)",
|
|
19401
|
+
settingsSaveFailed: "Не удалось сохранить, попробуйте позже"
|
|
19402
|
+
};
|
|
19403
|
+
//#endregion
|
|
19404
|
+
//#region src/client/locales-ru/qoder.ts
|
|
19405
|
+
const dictionary$1 = {
|
|
19406
|
+
modelRowEfforts: "уровни {list}",
|
|
19407
|
+
modelRowNoEfforts: "без уровней",
|
|
19408
|
+
modelRowOutput: "вывод {cap}",
|
|
19409
|
+
...accountPoolRu,
|
|
19410
|
+
title: "Qoder (подписка)",
|
|
19411
|
+
pageDesc: "Подключение подписки Qoder (глобальная зона qoder.com / китайский сайт qoder.com.cn): пул аккаунтов, квота тарифа, расход кеша и выбор моделей. Регион — свойство учётных данных, токены двух регионов не взаимозаменяемы, поэтому в пуле могут быть аккаунты обоих.",
|
|
19412
|
+
loading: "Загрузка…",
|
|
19413
|
+
moreNotes: "Подробнее",
|
|
19414
|
+
region: "Регион",
|
|
19415
|
+
regionGlobal: "Глобальная зона (qoder.com)",
|
|
19416
|
+
regionCn: "Китайский сайт (qoder.com.cn)",
|
|
19417
|
+
regionHint: "Регион определяется только учётными данными; этот выбор задаёт лишь то, куда попадёт следующий вход. Эндпоинты двух регионов не взаимозаменяемы.",
|
|
19418
|
+
regionHintExtra: "В глобальной зоне есть вход по коду устройства в браузере и PAT; на китайском сайте потока устройства нет — только вставка PAT или импорт локальной сессии qodercli.",
|
|
19419
|
+
authorizing: "Авторизация…",
|
|
19420
|
+
loginIdle: "Вход ещё не начинался.",
|
|
19421
|
+
loginHaveAccounts: "В пуле уже {count} аккаунтов. Чтобы добавить ещё один, нажмите «Добавить аккаунт» выше.",
|
|
19422
|
+
loginPending: "Подтвердите авторизацию в браузере вручную — дальше карточка продолжит сама. Поток устройства не открывает локальный порт обратного вызова, процесс идёт на хосте.",
|
|
19423
|
+
loginComplete: "Вход выполнен, аккаунт добавлен в пул.",
|
|
19424
|
+
loginCompletedAt: "Завершено: {time}",
|
|
19425
|
+
loginCompleteNoAccount: "Вход завершился, но этого аккаунта в пуле уже нет (возможно, он удалён).",
|
|
19426
|
+
loginError: "Вход не выполнен.",
|
|
19427
|
+
loginRetryable: "Сбой можно повторить (ошибка транспорта или таймаут) — просто начните вход заново.",
|
|
19428
|
+
loginNotRetryable: "Сам этот сбой не пройдёт (нарушение протокола или отказ); проверьте сеть и выбранный регион, затем начните заново.",
|
|
19429
|
+
authorizeUrl: "Страница авторизации",
|
|
19430
|
+
openAuthorizeUrl: "Открыть страницу авторизации",
|
|
19431
|
+
pollEvery: "Статус входа опрашивается каждые {seconds} с.",
|
|
19432
|
+
loginExpiresAt: "Эта авторизация действует до {time}; после истечения вход нужно начать заново.",
|
|
19433
|
+
progress: "Прогресс",
|
|
19434
|
+
cancelLogin: "Отменить вход",
|
|
19435
|
+
cancelLoginBusy: "Отмена…",
|
|
19436
|
+
adopt: "Импортировать локальную сессию qodercli",
|
|
19437
|
+
adopting: "Импорт…",
|
|
19438
|
+
adoptAdopted: "Локальная сессия qodercli импортирована (регион: {region}).",
|
|
19439
|
+
adoptNoAttempt: "Импорт не выполнялся.",
|
|
19440
|
+
adoptFallback: "Вместо этого можно войти через браузер (глобальная зона) или вставить PAT.",
|
|
19441
|
+
adoptNoCredentialsFile: "На этой машине не найден файл учётных данных qodercli.",
|
|
19442
|
+
adoptInvalidCredentials: "Файл учётных данных qodercli не читается (пустой, повреждён или не расшифровался).",
|
|
19443
|
+
adoptUnsupportedShape: "Сохранённая сессия расшифровалась, но набор полей незнаком (апстрим мог измениться).",
|
|
19444
|
+
adoptNotAQoderLogin: "В этом файле нет рабочей сессии Qoder (нет access_token).",
|
|
19445
|
+
adoptRegionUnresolved: "Сессия расшифровалась, но userinfo ни одного региона не принимает этот токен (возможно, он истёк).",
|
|
19446
|
+
dismiss: "Понятно",
|
|
19447
|
+
manualPasteSection: "Вставить PAT вручную",
|
|
19448
|
+
manualPasteHint: "Создайте Personal Access Token (pt-…) на странице Integrations в аккаунте Qoder и вставьте его здесь. Он обменивается на короткоживущий job token; сам PAT хранится только в зашифрованном хранилище хоста и нужен для повторного обмена после истечения.",
|
|
19449
|
+
manualPastePlaceholder: "pt-…",
|
|
19450
|
+
manualPasteSubmit: "Вставить и войти",
|
|
19451
|
+
manualPasteSubmitting: "Обмен…",
|
|
19452
|
+
manualPasteEmpty: "Сначала вставьте PAT.",
|
|
19453
|
+
connection: "Подключение",
|
|
19454
|
+
routeOwned: "Маршрут провайдера обслуживает этот плагин.",
|
|
19455
|
+
routeConflict: "Маршрут провайдера занят другим адаптером: {detail}",
|
|
19456
|
+
testConnection: "Проверить подключение",
|
|
19457
|
+
testingConnection: "Проверка…",
|
|
19458
|
+
testSuccess: "Подключение в порядке",
|
|
19459
|
+
testLatency: "{ms} мс",
|
|
19460
|
+
testFailedDetail: "Подключение не удалось: {detail}",
|
|
19461
|
+
modelsSection: "Модели",
|
|
19462
|
+
modelsHint: "Каталог обнаруживается с апстрима сразу после входа; до входа показывается встроенная таблица возможностей.",
|
|
19463
|
+
modelsHintExtra: "Возможности (контекстное окно / ввод изображений / уровни рассуждений) берутся только из полей каталога, а не из имени модели; поле max_input_tokens в каталоге — устаревшее нижнее значение апстрима, и эта линия ему не верит: окно берётся из максимального варианта context_config.",
|
|
19464
|
+
modelsUnavailable: "Каталога моделей пока нет. Войдите и нажмите «Обновить каталог» выше.",
|
|
19465
|
+
refreshCatalog: "Обновить каталог",
|
|
19466
|
+
refreshingCatalog: "Обновление…",
|
|
19467
|
+
selectAll: "Все",
|
|
19468
|
+
unselectAll: "Ничего",
|
|
19469
|
+
modelChecklistCount: "Выбрано {count} из {total}",
|
|
19470
|
+
enabledModelIdsSemantics: "Если снять все отметки, все модели станут недоступны (это не «без фильтра»); чтобы вернуть все, нажмите «Все».",
|
|
19471
|
+
defaultEffort: "Уровень рассуждений по умолчанию",
|
|
19472
|
+
defaultEffortHint: "Используется, когда сессия не задаёт уровень; если у модели есть свой по умолчанию, главнее он.",
|
|
19473
|
+
defaultEffortHintExtra: "Апстрим объявляет уровни для каждой модели отдельно (ключи thinking_config в каталоге); выбранный здесь уровень сначала приводится к той лестнице, которую модель действительно принимает, поэтому неподдерживаемое значение не отправляется никогда.",
|
|
19474
|
+
defaultEffortModel: "Как у модели по умолчанию",
|
|
19475
|
+
effortMinimal: "minimal",
|
|
19476
|
+
effortLow: "low",
|
|
19477
|
+
effortMedium: "medium",
|
|
19478
|
+
effortHigh: "high",
|
|
19479
|
+
effortXHigh: "xhigh",
|
|
19480
|
+
effortMax: "max",
|
|
19481
|
+
contextWindowSection: "Контекстное окно",
|
|
19482
|
+
contextWindowHint: "Значения по умолчанию берутся из каталога (максимальный вариант context_config); здесь задаётся переопределение для отдельной модели.",
|
|
19483
|
+
contextWindowHintExtra: "Переопределение влияет только на локальное планирование (когда сжимать сессию) и не меняет реальное окно модели на апстриме.",
|
|
19484
|
+
contextWindowReset: "Вернуть по умолчанию",
|
|
19485
|
+
contextWindowResetAll: "Вернуть все по умолчанию",
|
|
19486
|
+
contextWindowNoneEnabled: "Отмеченных моделей нет.",
|
|
19487
|
+
tokens: "токенов",
|
|
19488
|
+
save: "Сохранить",
|
|
19489
|
+
saving: "Сохранение…",
|
|
19490
|
+
invalidCapacity: "Недопустимая ёмкость: {value}",
|
|
19491
|
+
quotaSection: "Квота",
|
|
19492
|
+
quotaDesc: "Квота читается из аккаунтного эндпоинта Qoder (непубличный личный эндпоинт, апстрим может его изменить). За период аккаунта он отдаёт три ёмкости: личная квота, докупленные Credits и ресурсный пакет организации.",
|
|
19493
|
+
quotaBucketPersonal: "Личная квота",
|
|
19494
|
+
quotaBucketAddOn: "Докупленные Credits",
|
|
19495
|
+
quotaBucketOrg: "Пакет организации",
|
|
19496
|
+
quotaRemaining: "остаток",
|
|
19497
|
+
quotaUsed: "использовано",
|
|
19498
|
+
quotaTotal: "всего",
|
|
19499
|
+
quotaExpiresAt: "Конец периода",
|
|
19500
|
+
quotaReadAt: "Прочитано",
|
|
19501
|
+
quotaRegion: "Регион",
|
|
19502
|
+
quotaRefresh: "Обновить квоту",
|
|
19503
|
+
quotaRefreshing: "Обновление…",
|
|
19504
|
+
quotaRefreshingNote: "Обновляем квоту в фоне…",
|
|
19505
|
+
quotaEmpty: "Квота ещё не прочитана.",
|
|
19506
|
+
quotaSignedOut: "Войдите, чтобы увидеть здесь квоту аккаунта.",
|
|
19507
|
+
quotaErrorLabel: "Не удалось прочитать квоту",
|
|
19508
|
+
quotaNoUnit: "",
|
|
19509
|
+
cacheSection: "Расход кеша",
|
|
19510
|
+
cacheStatScope: "Локальная статистика (в токенах, с начала работы процесса): она отвечает, насколько помог кеш, и не является счётом апстрима.",
|
|
19511
|
+
cacheDesc: "Qoder кеширует префиксы на сервере автоматически; попадания читаются из usage.prompt_tokens_details.cached_tokens (при отсутствии — из верхнеуровневого cached_tokens). У подписки нет публичной цены за токен, поэтому страница показывает только токены, без денег.",
|
|
19512
|
+
cacheEmpty: "Примеров пока нет. Отправьте сообщение — статистика появится здесь.",
|
|
19513
|
+
cacheHitRatio: "Доля попаданий в кеш",
|
|
19514
|
+
cacheHitRatioUnavailable: "—",
|
|
19515
|
+
cacheReadTokens: "Чтение из кеша",
|
|
19516
|
+
cacheMissedTokens: "Ввод без кеша",
|
|
19517
|
+
cacheWriteTokens: "Запись в кеш",
|
|
19518
|
+
cacheRequests: "Запросов в выборке",
|
|
19519
|
+
composerLabel: "Остаток квоты",
|
|
19520
|
+
quotaWindow: "Окно лимита"
|
|
19521
|
+
};
|
|
19522
|
+
//#endregion
|
|
19523
|
+
//#region src/client/locales-ru/step-code.ts
|
|
19524
|
+
const dictionary = {
|
|
19525
|
+
...accountPoolRu,
|
|
19526
|
+
title: "Step Code (подписка Step Plan)",
|
|
19527
|
+
pageDesc: "Подключение к StepFun по подписке Step Plan (Китай api.stepfun.com / международный api.stepfun.ai) или по API-ключу открытой платформы: пул аккаунтов, квота тарифа, расход кеша и выбор моделей. Регион — свойство учётных данных, и два региона несовместимы, поэтому в пуле могут быть аккаунты из обоих.",
|
|
19528
|
+
loading: "Загрузка…",
|
|
19529
|
+
moreNotes: "Подробнее",
|
|
19530
|
+
profile: "Тип учётных данных",
|
|
19531
|
+
profileStepPlan: "Step Plan, Китай (подписка, авторизация в браузере)",
|
|
19532
|
+
profileStepPlanOversea: "Step Plan, международный (подписка, авторизация в браузере)",
|
|
19533
|
+
profilePlatformCn: "Открытая платформа, Китай (API-ключ, оплата по токенам)",
|
|
19534
|
+
profilePlatformOversea: "Открытая платформа, международный (API-ключ, оплата по токенам)",
|
|
19535
|
+
profileHint: "Профиль сразу определяет три вещи: источник учётных данных, базовый домен моделей и регион, из которого читается центр разработчика.",
|
|
19536
|
+
profileHintExtra: "Четыре значения совпадают с официальными дословно, поэтому свободного ввода здесь нет; учётные данные не из своего региона апстрим отклоняет сразу.",
|
|
19537
|
+
region: "Регион",
|
|
19538
|
+
regionCn: "Китай (stepfun.com)",
|
|
19539
|
+
regionIntl: "Международный (stepfun.ai)",
|
|
19540
|
+
regionHint: "Регион однозначно задаётся профилем в учётных данных; страница лишь показывает, к какому региону относится текущий выбор, отдельно его не изменить.",
|
|
19541
|
+
authorizing: "Авторизация…",
|
|
19542
|
+
loginIdle: "Вход ещё не начат.",
|
|
19543
|
+
loginHaveAccounts: "В пуле уже есть готовых аккаунтов: {count}. Чтобы добавить ещё один, нажмите «Добавить аккаунт» выше.",
|
|
19544
|
+
loginPending: "Подтвердите авторизацию в браузере — карточка продолжит сама. Вход с облачным опросом не открывает локальный порт обратного вызова: процесс идёт на host.",
|
|
19545
|
+
loginComplete: "Вход выполнен, аккаунт добавлен в пул.",
|
|
19546
|
+
loginCompletedAt: "Вход выполнен: {time}",
|
|
19547
|
+
loginCompleteNoAccount: "Вход завершился, но этого аккаунта в пуле уже нет (возможно, его удалили).",
|
|
19548
|
+
loginError: "Вход не удался.",
|
|
19549
|
+
loginRetryable: "Этот сбой можно повторить (ошибка транспорта или 408/429/5xx) — просто начните вход заново.",
|
|
19550
|
+
loginNotRetryable: "Этот сбой сам не пройдёт (нарушение протокола или отказ пользователя); проверьте сеть и выбранный тип учётных данных и начните заново.",
|
|
19551
|
+
authorizeUrl: "Страница авторизации",
|
|
19552
|
+
openAuthorizeUrl: "Открыть страницу авторизации",
|
|
19553
|
+
pollEvery: "Результат входа запрашивается каждые {seconds} с.",
|
|
19554
|
+
loginExpiresAt: "Эта авторизация действует до {time}; после этого нужно начинать новую.",
|
|
19555
|
+
progress: "Прогресс",
|
|
19556
|
+
restartLogin: "Начать заново",
|
|
19557
|
+
cancelLogin: "Отменить вход",
|
|
19558
|
+
cancelLoginBusy: "Отмена…",
|
|
19559
|
+
manualPasteSection: "Вставить API-ключ платформы вручную",
|
|
19560
|
+
manualPasteHint: "Если браузера нет или через него не хочется — вставьте ниже API-ключ открытой платформы Step (это два типа учётных данных platform_*, оплата по токенам). Резервный путь просто свёрнут: это второй способ сделать то же самое, открывается по требованию.",
|
|
19561
|
+
manualPastePlaceholder: "Вставьте API-ключ платформы (sk-…)",
|
|
19562
|
+
manualPasteSubmit: "Отправить ключ",
|
|
19563
|
+
manualPasteSubmitting: "Отправка…",
|
|
19564
|
+
manualPasteEmpty: "Сначала вставьте API-ключ.",
|
|
19565
|
+
adopt: "Импортировать локальный вход stepcode",
|
|
19566
|
+
adopting: "Импорт…",
|
|
19567
|
+
adoptAdopted: "Локальный вход stepcode импортирован ({profile}); заново входить не нужно.",
|
|
19568
|
+
adoptNoAttempt: "Локального входа stepcode для импорта нет.",
|
|
19569
|
+
adoptNoCredentialsFile: "Файл учётных данных stepcode не найден (~/.stepcode/auth.json). Он появляется, когда клиент stepcode установлен и вход в него выполнен хотя бы раз.",
|
|
19570
|
+
adoptInvalidCredentials: "Файл учётных данных не читается или повреждён, импорт остановлен. Импорт только читает и никогда не перезаписывает файлы stepcode.",
|
|
19571
|
+
adoptUnsupportedShape: "Файл прочитан, но его форма не распознана; возможно, стоит обновить плагин.",
|
|
19572
|
+
adoptNotAStepcodeLogin: "Файл есть, но входа в Step в нём нет (в том же auth.json могут быть записи другого инструмента). Войдите через браузер или вставьте API-ключ платформы вручную.",
|
|
19573
|
+
adoptFallback: "Импорт лишь экономит один вход; его сбой линию не блокирует.",
|
|
19574
|
+
adoptedBadge: "Импортированный вход",
|
|
19575
|
+
connection: "Подключение",
|
|
19576
|
+
testConnection: "Проверить подключение",
|
|
19577
|
+
testingConnection: "Проверка…",
|
|
19578
|
+
testSuccess: "Подключение в порядке",
|
|
19579
|
+
testSuccessAccount: "Подключение в порядке (аккаунт {account})",
|
|
19580
|
+
testSuccessModel: "Подключение в порядке ({model})",
|
|
19581
|
+
testFailed: "Проверка подключения не удалась",
|
|
19582
|
+
testFailedDetail: "Проверка подключения не удалась: {detail}",
|
|
19583
|
+
testLatency: "Обмен {ms} мс",
|
|
19584
|
+
routeOwned: "Этот плагин обслуживает маршрут модели.",
|
|
19585
|
+
routeConflict: "Маршрут модели уже занят другим провайдером: {detail}. Удалите дублирующую конфигурацию провайдера в настройках DSH и перезагрузите.",
|
|
19586
|
+
modelsSection: "Модели",
|
|
19587
|
+
modelsHint: "В списке выбора модели в чате видны только отмеченные модели. Возможности никогда не выводятся из имени модели: каждое поле берётся из обнаруженного в рантайме каталога апстрима.",
|
|
19588
|
+
modelsHintExtra: "Поле без подтверждения показывает объявленное значение по умолчанию, а не догадку; каталог фильтруется по региону учётных данных, а модель, запрошенную не в своём регионе, апстрим отклоняет.",
|
|
19589
|
+
modelsUnavailable: "Пока нет моделей для показа (каталог обнаруживается по требованию — войдите или нажмите «Обновить каталог»).",
|
|
19590
|
+
refreshCatalog: "Обновить каталог",
|
|
19591
|
+
refreshingCatalog: "Обновление…",
|
|
19592
|
+
dismiss: "Понятно",
|
|
19593
|
+
selectAll: "Выбрать все",
|
|
19594
|
+
unselectAll: "Снять все",
|
|
19595
|
+
modelChecklistCount: "{count}/{total}",
|
|
19596
|
+
enabledModelIdsSemantics: "Как работает выбор: если снять все отметки, список станет пустым, а пустой список значит «без фильтра» — доступны все модели каталога (явный выбор — только непустой список). Чтобы действительно ограничить набор, отметьте только нужные модели.",
|
|
19597
|
+
defaultEffort: "Уровень рассуждений по умолчанию",
|
|
19598
|
+
defaultEffortHint: "Это словарь уровней линии; перед отправкой запрос приводится к лестнице, которую целевая модель действительно принимает, поэтому полный список не отправит модели с двумя уровнями неподдерживаемый.",
|
|
19599
|
+
defaultEffortHintExtra: "Приведение выполняется на host; вариант «уровень по умолчанию у каждой модели» оставляет каждую модель на её собственном уровне.",
|
|
19600
|
+
defaultEffortModel: "Уровень по умолчанию у каждой модели",
|
|
19601
|
+
effortMinimal: "Минимальный (minimal)",
|
|
19602
|
+
effortLow: "Низкий (low)",
|
|
19603
|
+
effortMedium: "Средний (medium)",
|
|
19604
|
+
effortHigh: "Высокий (high)",
|
|
19605
|
+
effortXHigh: "Очень высокий (xhigh)",
|
|
19606
|
+
effortMax: "Максимальный (max)",
|
|
19607
|
+
contextWindowSection: "Контекстные окна моделей",
|
|
19608
|
+
contextWindowHint: "Значения по умолчанию берутся из каталога апстрима (max_input_tokens, который сообщает каждая модель); можно переопределить ёмкостью, которую DSH использует при сжатии и определении переполнения. Поддерживаются записи 1M, 512K, 200K и подобные.",
|
|
19609
|
+
contextWindowHintExtra: "Эндпоинт не сообщает предел вывода, поэтому предел вывода по умолчанию равен контекстному окну.",
|
|
19610
|
+
contextWindowNoneEnabled: "Ни одна модель не отмечена. Отметьте модель выше, и здесь появится её контекстное окно.",
|
|
19611
|
+
contextWindowReset: "Вернуть по умолчанию",
|
|
19612
|
+
contextWindowResetAll: "Вернуть все по умолчанию",
|
|
19613
|
+
tokens: "токены",
|
|
19614
|
+
save: "Сохранить",
|
|
19615
|
+
saving: "Сохранение…",
|
|
19616
|
+
saved: "Сохранено",
|
|
19617
|
+
invalidCapacity: "Неверный формат ёмкости: {value}",
|
|
19618
|
+
quotaSection: "Расход и квота",
|
|
19619
|
+
quotaDesc: "Данные из центра разработчика Step (недокументированный эндпоинт: сначала логин и пароль открытой платформы обмениваются на Oasis-Token, затем им читается Dashboard). Это единственная точка риска по соответствию и стабильности на линии; неудачное чтение на запросы к моделям не влияет.",
|
|
19620
|
+
quotaRefresh: "Обновить расход",
|
|
19621
|
+
quotaRefreshing: "Обновление…",
|
|
19622
|
+
quotaSignedOut: "Вход не выполнен — сначала войдите выше.",
|
|
19623
|
+
quotaEmpty: "Данных о квоте пока нет — нажмите «Обновить расход», чтобы повторить.",
|
|
19624
|
+
quotaPlan: "Тариф",
|
|
19625
|
+
quotaPlanFamily: "plan_family",
|
|
19626
|
+
quotaRenews: "Продление",
|
|
19627
|
+
quotaReadAt: "Прочитано",
|
|
19628
|
+
quotaSources: "Источники",
|
|
19629
|
+
quotaRegion: "Регион чтения",
|
|
19630
|
+
quotaRefreshingNote: "Квота обновляется в фоне; ниже цифры последнего чтения.",
|
|
19631
|
+
quotaErrorLabel: "Не удалось прочитать квоту",
|
|
19632
|
+
quotaWindowNames: "Названия окон локализуются по длине окна (5 часов / 1 неделя / 1 месяц) и здесь не зашиты; прогресс каждого аккаунта рисуется в его карточке.",
|
|
19633
|
+
quotaUsed: "израсходовано",
|
|
19634
|
+
quotaResets: "Сброс",
|
|
19635
|
+
quotaNoReset: "апстрим не сообщил время сброса",
|
|
19636
|
+
quotaUsedUnknown: "апстрим не сообщил процент расхода",
|
|
19637
|
+
quotaKindWindowed: "Старый оконный тариф (5 часов / неделя)",
|
|
19638
|
+
quotaKindCredit: "Credit-пул",
|
|
19639
|
+
quotaKindUnknown: "Неопознанная форма тарифа",
|
|
19640
|
+
quotaKindHint: "Апстрим одновременно использует два поколения тарифов, и поколение определяется по структуре ответа (поля старых окон / credit_buckets), а не только по plan_family. Если не распознано ни одно, карточка так и говорит и не рисует ни одного индикатора.",
|
|
19641
|
+
quotaWindowFiveHour: "Окно 5 часов",
|
|
19642
|
+
quotaWindowWeekly: "Недельное окно",
|
|
19643
|
+
quotaWindowCredit: "Credit-пул",
|
|
19644
|
+
quotaBucketTotal: "Всего",
|
|
19645
|
+
quotaBucketRemaining: "Остаток",
|
|
19646
|
+
quotaBucketExpires: "Истекает",
|
|
19647
|
+
quotaBucketResets: "Сброс",
|
|
19648
|
+
quotaCredentialSection: "Учётные данные для квоты (центр разработчика)",
|
|
19649
|
+
quotaCredentialSource: "Источник",
|
|
19650
|
+
quotaCredentialFoot: "Эндпоинту квоты нужен Oasis-Token, и здесь показано только есть ли он и откуда взялся: сами учётные данные остаются на host и никогда не отдаются во фронтенд. Логин, пароль и токен попадают на host только в теле того запроса, который вы отправляете кнопкой: их не пишут в локальное хранилище, не кладут в URL, не логируют, и ни один эндпоинт не может их вернуть.",
|
|
19651
|
+
quotaCredentialNone: "Учётные данные для квоты не настроены, карточке квоты нечего читать.",
|
|
19652
|
+
quotaCredentialAuto: "Обмен по логину и паролю (auto)",
|
|
19653
|
+
quotaCredentialManual: "Вставлено вручную (manual)",
|
|
19654
|
+
quotaCredentialAccount: "Аккаунт входа",
|
|
19655
|
+
quotaCredentialExpires: "Истекает",
|
|
19656
|
+
quotaCredentialError: "Последнее чтение с ними не удалось",
|
|
19657
|
+
quotaCredentialPasswordSection: "Обменять логин и пароль на токен",
|
|
19658
|
+
quotaCredentialAccountPlaceholder: "Аккаунт открытой платформы Step (email или телефон)",
|
|
19659
|
+
quotaCredentialPasswordPlaceholder: "Пароль",
|
|
19660
|
+
quotaCredentialPasswordSubmit: "Обменять на токен",
|
|
19661
|
+
quotaCredentialPasswordSubmitting: "Обмен…",
|
|
19662
|
+
quotaCredentialAccountEmpty: "Сначала заполните аккаунт открытой платформы Step.",
|
|
19663
|
+
quotaCredentialPasswordEmpty: "Сначала заполните пароль.",
|
|
19664
|
+
quotaCredentialManualSection: "Вставить Oasis-Token вручную",
|
|
19665
|
+
quotaCredentialTokenPlaceholder: "Вставьте Oasis-Token (скопируйте из инструментов разработчика в браузере)",
|
|
19666
|
+
quotaCredentialTokenSubmit: "Отправить токен",
|
|
19667
|
+
quotaCredentialTokenSubmitting: "Отправка…",
|
|
19668
|
+
quotaCredentialTokenEmpty: "Сначала вставьте Oasis-Token.",
|
|
19669
|
+
quotaCredentialClear: "Очистить учётные данные квоты",
|
|
19670
|
+
quotaCredentialClearing: "Очистка…",
|
|
19671
|
+
cacheSection: "Расход кеша",
|
|
19672
|
+
cacheDesc: "На стороне Step работает автоматический префиксный кеш: достаточно длинный префикс даёт попадание, а у клиента нет ни параметров кеша, ни действия «запись». Поэтому реальное измерение здесь одно — чтение; запись всегда 0 и так и подписана.",
|
|
19673
|
+
cacheStatScope: "Эти цифры — локальный подсчёт DSH по запросам, которые сообщили расход на этой машине, а не счёт от апстрима.",
|
|
19674
|
+
cacheFieldOrder: "Порядок полей чтения",
|
|
19675
|
+
cacheReadTokens: "Прочитано из кеша",
|
|
19676
|
+
cacheMissedTokens: "Вход без попадания",
|
|
19677
|
+
cacheHitRatio: "Доля попаданий в кеш",
|
|
19678
|
+
cacheRequests: "Учтено запросов",
|
|
19679
|
+
cacheWriteNote: "Эта линия не сообщает о записи в кеш",
|
|
19680
|
+
cacheWriteNoteValue: "Токены записи",
|
|
19681
|
+
cacheWriteNoteHint: "Запись на этой линии всегда 0: у автоматического префиксного кеша нет действия «запись» и нет соответствующей статьи биллинга. Любая цифра, утверждающая, что здесь что-то записано в кеш, была бы выдумана, поэтому индикатор записи не рисуется.",
|
|
19682
|
+
cacheRequestParams: "Отправлять параметры кеша в запросах",
|
|
19683
|
+
cacheRequestParamsHint: "Сейчас параметры кеша не отправляются: на стороне Step автоматический префиксный кеш, и официальный клиент для Step их тоже не отправляет.",
|
|
19684
|
+
cacheRequestParamsNote: "Включение отправляет поля, которых нет в документации Step (официальный клиент жёстко привязывает отправку prompt_cache_key к api.openai.com); включайте, только проверив, что эндпоинт их принимает.",
|
|
19685
|
+
cacheRequestParamsOnHint: "Возможность включена: запросы несут параметры кеша. Step их не документирует, и официальный клиент для Step их тоже не отправляет.",
|
|
19686
|
+
cachePricingNote: "Цены за единицу не документированы (все четыре ключа cost в официальной таблице моделей равны 0), поэтому страница показывает только токены и никаких сумм.",
|
|
19687
|
+
cacheEmpty: "Ни один запрос на этой машине ещё не сообщил расход — проведите диалог и посмотрите снова.",
|
|
19688
|
+
cacheHitRatioUnavailable: "—"
|
|
19689
|
+
};
|
|
19690
|
+
/**
|
|
19691
|
+
* Register the Russian language and every dictionary it covers.
|
|
19692
|
+
*
|
|
19693
|
+
* The runtime lives in `locale`, which the client plugin already injects, so
|
|
19694
|
+
* this cannot be mounted without it.
|
|
19695
|
+
*
|
|
19696
|
+
* @param ctx - client plugin context owning the locale service.
|
|
19697
|
+
*/
|
|
19698
|
+
function installRussianLocale(ctx) {
|
|
19699
|
+
if (typeof ctx.locale?.addLanguage !== "function") return;
|
|
19700
|
+
ctx.effect(() => {
|
|
19701
|
+
try {
|
|
19702
|
+
return ctx.locale.addLanguage({
|
|
19703
|
+
id: "ru",
|
|
19704
|
+
label: "Русский",
|
|
19705
|
+
fallback: "en"
|
|
19706
|
+
});
|
|
19707
|
+
} catch {
|
|
19708
|
+
return () => {};
|
|
19709
|
+
}
|
|
19710
|
+
}, "dsh-chatgpt-subscription: ru language");
|
|
19711
|
+
const dictionaries = [
|
|
19712
|
+
[NS, dictionary$7],
|
|
19713
|
+
[NS_CLAUDE, dictionary$11],
|
|
19714
|
+
[NS_ANTIGRAVITY, dictionary$12],
|
|
19715
|
+
[NS_COMMAND_CODE, dictionary$9],
|
|
19716
|
+
[NS_KIMI_CODE, dictionary$6],
|
|
19717
|
+
[NS_MINIMAX_CODE, dictionary$5],
|
|
19718
|
+
[NS_GLM_CODING_PLAN, dictionary$8],
|
|
19719
|
+
[NS_OLLAMA, dictionary$4],
|
|
19720
|
+
[NS_STEP_CODE, dictionary],
|
|
19721
|
+
[NS_CLINE_PASS, dictionary$10],
|
|
19722
|
+
[NS_QODER, dictionary$1],
|
|
19723
|
+
[NS_OPENDESIGN, dictionary$3],
|
|
19724
|
+
[NS_PROGRESS_UPDATES, dictionary$2]
|
|
19725
|
+
];
|
|
19726
|
+
for (const [ns, dictionary] of dictionaries) ctx.effect(() => {
|
|
19727
|
+
try {
|
|
19728
|
+
return ctx.locale.register(ns, "ru", dictionary);
|
|
19729
|
+
} catch {
|
|
19730
|
+
return () => {};
|
|
19731
|
+
}
|
|
19732
|
+
}, `dsh-chatgpt-subscription: ru dictionary ${ns}`);
|
|
19733
|
+
}
|
|
19734
|
+
//#endregion
|
|
17775
19735
|
//#region src/client/common/plugin-style.ts
|
|
17776
19736
|
/**
|
|
17777
19737
|
* Shared installer for every stylesheet this plugin injects.
|
|
@@ -19565,8 +21525,11 @@ window.__ModuleLoader__.load({
|
|
|
19565
21525
|
*
|
|
19566
21526
|
* Quota follows the ACCOUNT, and a pool has several. The badge therefore shows
|
|
19567
21527
|
* the most-consumed window across the accounts the host has already read, which
|
|
19568
|
-
* is the one that will stop the next request first
|
|
19569
|
-
* read
|
|
21528
|
+
* is the one that will stop the next request first. Its own 60 s poll is a plain
|
|
21529
|
+
* read, so a poll never fans out one upstream call per account; only an explicit
|
|
21530
|
+
* click on the badge asks the host for the forced refresh, the same POST the
|
|
21531
|
+
* card's own "refresh usage" button drives — which is exactly what the shared
|
|
21532
|
+
* badge's `refresh` argument is for, and what this line used to drop.
|
|
19570
21533
|
*/
|
|
19571
21534
|
function ClinePassComposerQuota(props) {
|
|
19572
21535
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ComposerQuotaBadge, {
|
|
@@ -19574,7 +21537,7 @@ window.__ModuleLoader__.load({
|
|
|
19574
21537
|
loadModelDirectory: props.loadModelDirectory,
|
|
19575
21538
|
providerId: "cline-pass",
|
|
19576
21539
|
label: zh$4.composerLabel,
|
|
19577
|
-
readStatus: () => API$1.status(),
|
|
21540
|
+
readStatus: (refresh) => API$1.status(refresh),
|
|
19578
21541
|
selectFacts: selectClinePassFacts
|
|
19579
21542
|
});
|
|
19580
21543
|
}
|
|
@@ -19826,6 +21789,13 @@ window.__ModuleLoader__.load({
|
|
|
19826
21789
|
.dshod-paste{align-items:center;display:flex;flex-wrap:wrap;gap:8px;justify-content:space-between;margin-top:8px}
|
|
19827
21790
|
.dshod-paste-note{font-size:12px}
|
|
19828
21791
|
.dshod-warning{color:var(--dsw-alias-label-warning,#d9913b);font-size:12px}
|
|
21792
|
+
.dshod-quota{border:0.5px solid var(--dsw-alias-border-l2);border-radius:8px;display:flex;flex-direction:column;gap:6px;margin-top:8px;padding:10px 12px}
|
|
21793
|
+
.dshod-quota-head{align-items:baseline;display:flex;flex-wrap:wrap;gap:8px}
|
|
21794
|
+
.dshod-quota-account{color:var(--dsw-alias-label-primary);font-weight:600}
|
|
21795
|
+
.dshod-quota-plan{color:var(--dsw-alias-label-primary);font-size:12px}
|
|
21796
|
+
.dshod-quota-status{color:var(--dsw-alias-label-secondary);font-size:12px}
|
|
21797
|
+
.dshod-quota-meta{color:var(--dsw-alias-label-tertiary);font-size:12px}
|
|
21798
|
+
.dshod-quota-grid{color:var(--dsw-alias-label-secondary);display:grid;font-size:12px;gap:4px 16px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}
|
|
19829
21799
|
.dshod-adv-control{width:240px;max-width:100%;flex:none}
|
|
19830
21800
|
.dshod-adv-control.dsha-select{max-width:240px;min-width:240px;width:240px}
|
|
19831
21801
|
.dshod-adv-mono{font-family:ui-monospace,SFMono-Regular,Consolas,monospace}
|
|
@@ -48781,93 +50751,6 @@ window.__ModuleLoader__.load({
|
|
|
48781
50751
|
}) });
|
|
48782
50752
|
}
|
|
48783
50753
|
//#endregion
|
|
48784
|
-
//#region src/client/progress-updates/locales.ts
|
|
48785
|
-
/**
|
|
48786
|
-
* 「进展更新」在 locale 服务里的命名空间。
|
|
48787
|
-
*
|
|
48788
|
-
* 跟着本插件其余线路的命名习惯走(`dsh-kimi-code`、`dsh-step-code`、`dsh-ollama`
|
|
48789
|
-
* ……都是「dsh-<线路>」):新线路并入本插件的字典体系,而不是另开一个与包名无关
|
|
48790
|
-
* 的命名空间。
|
|
48791
|
-
*/
|
|
48792
|
-
const NS_PROGRESS_UPDATES = "dsh-progress-updates";
|
|
48793
|
-
/**
|
|
48794
|
-
* 中文文案。
|
|
48795
|
-
*
|
|
48796
|
-
* 键名沿用本插件其余字典的扁平驼峰(`hubTitle`、`imageToolRunning` 那一套),
|
|
48797
|
-
* 不另起一套点号命名——同一份 index.tsx 里两种命名风格会让「这条键属于哪张表」
|
|
48798
|
-
* 变成要靠记忆的事。
|
|
48799
|
-
*/
|
|
48800
|
-
const zh = {
|
|
48801
|
-
/** 设置页导航里的那一格,也是侧栏页签的标题。 */
|
|
48802
|
-
navTitle: "进展更新",
|
|
48803
|
-
progressTitle: "进展更新",
|
|
48804
|
-
/** 右侧栏 guide 卡片标题下的一行说明。 */
|
|
48805
|
-
progressGuideNote: "agent 汇报的每一步进展,都收在这里",
|
|
48806
|
-
markdownCopy: "复制",
|
|
48807
|
-
markdownCopied: "已复制",
|
|
48808
|
-
markdownFootnotes: "脚注",
|
|
48809
|
-
progressLatest: "最新",
|
|
48810
|
-
progressCount: "共 {n} 条",
|
|
48811
|
-
progressExpand: "展开这条进展",
|
|
48812
|
-
progressCollapse: "收起这条进展",
|
|
48813
|
-
progressEmptyTitle: "还没有进展更新",
|
|
48814
|
-
progressEmptyHint: "agent 开始多步任务后,会在这里汇报它进行到哪一步。",
|
|
48815
|
-
rowPending: "进展更新",
|
|
48816
|
-
rowRunning: "进行中",
|
|
48817
|
-
rowDone: "已汇报",
|
|
48818
|
-
rowError: "未发出",
|
|
48819
|
-
rowExpand: "展开这条进展的详情",
|
|
48820
|
-
rowCollapse: "收起这条进展的详情",
|
|
48821
|
-
settingsHint: "进展更新会让 agent 在多步任务中主动汇报进度。打开面板可以看它到目前为止的全部汇报。",
|
|
48822
|
-
settingsOpen: "打开进展面板",
|
|
48823
|
-
settingsEnabledName: "进展更新",
|
|
48824
|
-
settingsEnabledNote: "让 agent 在对话中发布进展更新",
|
|
48825
|
-
settingsThresholdName: "催促阈值",
|
|
48826
|
-
settingsThresholdNote: "连续这么多轮没有进展时,提醒 agent 汇报一次",
|
|
48827
|
-
settingsPanelName: "进展面板",
|
|
48828
|
-
settingsPanelNote: "在右侧栏查看本次会话的全部进展",
|
|
48829
|
-
settingsUnavailable: "这项设置当前不可修改(宿主没有开放配置表单)",
|
|
48830
|
-
settingsSaveFailed: "保存失败,请稍后再试"
|
|
48831
|
-
};
|
|
48832
|
-
/** 英文对照,键集与 zh 完全一致。 */
|
|
48833
|
-
const en = {
|
|
48834
|
-
navTitle: "Progress updates",
|
|
48835
|
-
progressTitle: "Progress updates",
|
|
48836
|
-
progressGuideNote: "Every step the agent reports, collected here",
|
|
48837
|
-
markdownCopy: "Copy",
|
|
48838
|
-
markdownCopied: "Copied",
|
|
48839
|
-
markdownFootnotes: "Footnotes",
|
|
48840
|
-
progressLatest: "Latest",
|
|
48841
|
-
progressCount: "{n} total",
|
|
48842
|
-
progressExpand: "Expand this update",
|
|
48843
|
-
progressCollapse: "Collapse this update",
|
|
48844
|
-
progressEmptyTitle: "No progress updates yet",
|
|
48845
|
-
progressEmptyHint: "Once the agent starts multi-step work, it reports how far it has got right here.",
|
|
48846
|
-
rowPending: "Progress update",
|
|
48847
|
-
rowRunning: "Reporting",
|
|
48848
|
-
rowDone: "Reported",
|
|
48849
|
-
rowError: "Not reported",
|
|
48850
|
-
rowExpand: "Expand this progress update",
|
|
48851
|
-
rowCollapse: "Collapse this progress update",
|
|
48852
|
-
settingsHint: "Progress updates let the agent report how far multi-step work has got. Open the panel to read everything it has reported so far.",
|
|
48853
|
-
settingsOpen: "Open progress panel",
|
|
48854
|
-
settingsEnabledName: "Progress updates",
|
|
48855
|
-
settingsEnabledNote: "Let the agent post progress updates in the conversation",
|
|
48856
|
-
settingsThresholdName: "Nudge threshold",
|
|
48857
|
-
settingsThresholdNote: "Remind the agent after this many rounds without an update",
|
|
48858
|
-
settingsPanelName: "Progress panel",
|
|
48859
|
-
settingsPanelNote: "See every update from this session in the right sidebar",
|
|
48860
|
-
settingsUnavailable: "This setting cannot be changed right now (the host serves no config form)",
|
|
48861
|
-
settingsSaveFailed: "Could not save. Try again in a moment."
|
|
48862
|
-
};
|
|
48863
|
-
/** 与其余线路同形的字典包(四个内置语言 id 都指向那两份)。 */
|
|
48864
|
-
const dictionaries = {
|
|
48865
|
-
zh,
|
|
48866
|
-
"zh-CN": zh,
|
|
48867
|
-
en,
|
|
48868
|
-
"en-US": en
|
|
48869
|
-
};
|
|
48870
|
-
//#endregion
|
|
48871
50754
|
//#region src/client/progress-updates/updates-panel.tsx
|
|
48872
50755
|
/**
|
|
48873
50756
|
* 进展更新面板:把 `progress_update` 工具产生的进展按时间顺序列出来。
|
|
@@ -50396,6 +52279,8 @@ window.__ModuleLoader__.load({
|
|
|
50396
52279
|
"remote.session"
|
|
50397
52280
|
];
|
|
50398
52281
|
function apply(ctx) {
|
|
52282
|
+
installLineLocale(ctx.locale);
|
|
52283
|
+
installRussianLocale(ctx);
|
|
50399
52284
|
ctx.effect(() => ctx.locale.register(NS, dictionaries$1), "dsh-chatgpt-subscription: dictionaries");
|
|
50400
52285
|
ctx.effect(() => installStyles(), "dsh-chatgpt-subscription: styles");
|
|
50401
52286
|
ctx.effect(() => {
|