dsh-connect-trae 4.9.1 → 4.14.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +417 -5
- package/README.en.md +16 -0
- package/README.md +15 -0
- package/docs/assets/dsh-connect-trae-composer-credits.png +0 -0
- package/docs/assets/dsh-connect-trae-sidebar-page.png +0 -0
- package/docs/assets/dsh-connect-trae-usage-card.png +0 -0
- package/lib/client.js +1082 -427
- package/lib/index.d.ts +18 -0
- package/lib/index.js +164 -12
- package/package.json +8 -1
package/lib/client.js
CHANGED
|
@@ -7,6 +7,253 @@ window.__ModuleLoader__.load({
|
|
|
7
7
|
let react = require("react");
|
|
8
8
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
9
9
|
let react_dom = require("react-dom");
|
|
10
|
+
//#region src/client/series-layout.ts
|
|
11
|
+
/** 同系列的公共布局规则。两个桥接插件同步维护此文件,功能专属样式留在 styles.ts。 */
|
|
12
|
+
function seriesLayoutCss(plugin) {
|
|
13
|
+
const p = `.dsm-${plugin}`;
|
|
14
|
+
const u = `${p}-usage`;
|
|
15
|
+
const members = plugin === "trae" ? `${p}-pool-card` : `${p}-pool-members`;
|
|
16
|
+
const memberHead = plugin === "trae" ? `${p}-pool-card-head` : `${p}-pool-members-head`;
|
|
17
|
+
const memberTitle = plugin === "trae" ? `${p}-pool-card-title` : `${p}-pool-members-title`;
|
|
18
|
+
const memberActions = plugin === "trae" ? `${p}-pool-card-tools` : `${p}-pool-members-actions`;
|
|
19
|
+
const saveBar = plugin === "trae" ? `${p}-pool-save-row` : `${p}-pool-save-bar`;
|
|
20
|
+
return `
|
|
21
|
+
${p}-page{font-family:inherit;--dsm-series-sticky-top:-28px}
|
|
22
|
+
${p}-page${p}-page{height:calc(100% - 16px);margin-bottom:16px;padding:28px clamp(24px,4vw,48px) 48px;gap:20px}
|
|
23
|
+
${u} ${p}-pool-auto-checkin-status{margin:0;font-size:12px;line-height:18px;color:var(--dsw-alias-label-secondary,#777)}
|
|
24
|
+
${p}-page-desc{font-size:13px;line-height:20px;color:var(--dsw-alias-label-tertiary,#999)}
|
|
25
|
+
${u} ${p}-pool-auto-checkin{display:flex;flex-direction:column;gap:6px;margin-top:8px}
|
|
26
|
+
${p}-page>*{width:100%;max-width:860px;min-width:0}
|
|
27
|
+
${u}{gap:16px;font-size:13px;line-height:1.5;min-width:0}
|
|
28
|
+
${u} .dsm-btn{box-sizing:border-box;font:inherit;font-size:13px;line-height:20px;padding:5px 14px;border-radius:8px;min-height:32px}
|
|
29
|
+
${u} .dsm-btn-outline{background:transparent;border-color:var(--dsw-alias-border-l2,#777);color:var(--dsw-alias-label-secondary,#999)}
|
|
30
|
+
${u} ${p}-tabs{display:flex;gap:8px}
|
|
31
|
+
${u} ${p}-tab-cell{flex:1;min-width:0;padding:8px 12px;border-radius:10px}
|
|
32
|
+
${u} ${p}-panels{position:sticky;top:var(--dsm-series-sticky-top,0px);z-index:2;display:flex;gap:2px;margin:4px 0 0;padding:8px 0 0;border-bottom:1px solid var(--dsw-alias-border-l1,#777);background:var(--dsw-alias-bg-layer-2,#24262c)}
|
|
33
|
+
/* 吸顶背景覆盖卡片两侧内边距,顶部偏移抵消滚动容器的顶部内边距。 */
|
|
34
|
+
${p}-page-body ${u} ${p}-panels{margin-inline:0;padding:8px 0;border:0;border-bottom:1px solid var(--dsw-alias-border-l2,#777);border-radius:0;background:var(--dsw-alias-bg-layer-3,#202126)}
|
|
35
|
+
${p}-page[data-tabs-stuck="true"] ${p}-panels{margin-inline:-20px;padding-inline:20px;border-top:1px solid var(--dsw-alias-border-l2,#777);box-shadow:0 3px 6px rgba(0,0,0,.06)}
|
|
36
|
+
${u} ${p}-panel-tab{font-size:13px;font-weight:600;line-height:20px;padding:7px 11px}
|
|
37
|
+
${u} ${p}-panel{margin-top:0;min-width:0}
|
|
38
|
+
${u} ${p}-models-summary,${u} ${p}-panel-note{margin:2px 0 0;font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary,#999)}
|
|
39
|
+
${u} ${p}-free-quota-warn{font-weight:600}
|
|
40
|
+
/* 说明段落的间距由容器统一控制,避免与卡片的纵向 gap 叠加。 */
|
|
41
|
+
${u} ${p}-region-summary{display:flex;flex-direction:column;gap:2px}
|
|
42
|
+
${u} ${p}-region-summary ${p}-models-summary{margin:0}
|
|
43
|
+
/* 页签底边已经分隔账号区,不在账号池顶部重复画线。 */
|
|
44
|
+
${u} #dsm-${plugin}-panel-accounts ${p}-pool{border-top:0;padding-top:0}
|
|
45
|
+
|
|
46
|
+
${u} ${p}-pool{display:flex;flex-direction:column;gap:12px;margin:0;padding:14px 0 0;border-top:1px solid var(--dsw-alias-border-l2,#777)}
|
|
47
|
+
${u} ${p}-pool-head{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}
|
|
48
|
+
${u} ${p}-pool-title{margin:0;font-size:13px;font-weight:600;line-height:18px}
|
|
49
|
+
${u} ${plugin === "trae" ? `${p}-pool-current` : `${p}-pool-current-badge`}{margin-left:auto;max-width:100%;overflow-wrap:anywhere;white-space:normal;padding:2px 8px;border-radius:999px;border:1px solid var(--dsw-alias-border-l2,#777);font-size:11px;font-weight:500;line-height:16px;background:var(--dsw-alias-bg-layer-2,#24262c);color:var(--dsw-alias-label-secondary,#999)}
|
|
50
|
+
${u} ${p}-pool-settings${p}-pool-modebar{padding:12px 14px;gap:8px;border:1px solid var(--dsw-alias-border-l2,#777);border-radius:12px;background:color-mix(in srgb,var(--dsw-alias-brand-primary,#cf795b) 5%,var(--dsw-alias-bg-layer-2,#24262c))}
|
|
51
|
+
${u} ${p}-pool-modebar-row{display:flex;align-items:center;gap:10px;flex-wrap:wrap;min-height:20px}
|
|
52
|
+
${u} ${p}-pool-modebar-label{font-size:13px;font-weight:600;line-height:20px}
|
|
53
|
+
${u} ${p}-pool-modebar-state{padding:1px 9px;font-size:12px;line-height:18px;border-radius:999px;color:var(--dsw-alias-label-secondary,#999);border:1px solid var(--dsw-alias-border-l2,#777);background:var(--dsw-alias-bg-layer-2,#24262c)}
|
|
54
|
+
${u} ${p}-pool-note,${u} ${p}-pool-modebar ${p}-pool-note{margin:0;font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary,#999)}
|
|
55
|
+
${u} ${members}{display:flex;flex-direction:column;gap:0;min-width:0;border:1px solid var(--dsw-alias-border-l2,#777);border-radius:12px;background:var(--dsw-alias-bg-layer-2,#24262c);overflow:hidden}
|
|
56
|
+
${u} ${memberHead}{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:12px;padding:14px 14px 12px}
|
|
57
|
+
${u} ${memberTitle}{margin:0;font-size:13px;font-weight:600;line-height:18px;color:var(--dsw-alias-label-primary,#eee)}
|
|
58
|
+
${u} ${memberHead} ${p}-pool-note{margin-top:4px}
|
|
59
|
+
${u} ${memberActions}{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
|
|
60
|
+
${u} ${memberActions} .dsm-btn{padding:5px 14px;font-size:13px;line-height:20px}
|
|
61
|
+
${u} ${p}-pool-count,${u} ${memberActions} ${p}-pool-hint{font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary,#999)}
|
|
62
|
+
${u} ${members} ${p}-pool-actions{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:8px;padding:0 14px 12px}
|
|
63
|
+
${u} ${p}-pool-actions-end{margin-left:auto}
|
|
64
|
+
${u} ${members} ${p}-pool-action-note{margin:0;padding:0 14px 12px;font-size:12px;line-height:18px}
|
|
65
|
+
${u} ${members} ${p}-pool-table{border:0;border-top:1px solid var(--dsw-alias-border-l1,#777);border-radius:0}
|
|
66
|
+
${u} ${p}-pool-row{padding:10px 14px;align-items:start;font-size:13px;line-height:18px}
|
|
67
|
+
${u} ${p}-pool-row-head{padding:8px 14px;font-size:11px;line-height:16px;align-items:center}
|
|
68
|
+
${u} ${p}-pool-row-current{background:color-mix(in srgb,var(--dsw-alias-brand-primary,#cf795b) 5%,var(--dsw-alias-bg-layer-2,#24262c));box-shadow:inset 3px 0 0 var(--dsw-alias-brand-primary,#cf795b)}
|
|
69
|
+
${u} ${p}-pool-row-actions .dsm-btn{min-height:26px;padding:2px 10px;font-size:12px;line-height:20px}
|
|
70
|
+
${u} ${p}-pool-settings-wrap{display:flex;flex-direction:column;gap:10px;border-top:1px solid var(--dsw-alias-border-l2,#777);padding-top:14px}
|
|
71
|
+
${u} ${p}-pool-settings{border-radius:12px;gap:0}
|
|
72
|
+
${u} ${p}-pool-settings-wrap :is(h3,h4){margin:0;font-size:13px;font-weight:600;line-height:18px;color:var(--dsw-alias-label-primary,#eee)}
|
|
73
|
+
${u} ${p}-pool-set-ctl select{box-sizing:border-box;width:240px;min-width:0;max-width:100%}
|
|
74
|
+
${u} ${p}-pool-set{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:12px 14px}
|
|
75
|
+
${u} ${p}-pool-set-copy{flex:1;min-width:0;gap:3px}
|
|
76
|
+
${u} ${p}-pool-set-copy b{font-size:13px;font-weight:500;line-height:18px}
|
|
77
|
+
${u} ${p}-pool-set-copy span{font-size:12px;line-height:18px}
|
|
78
|
+
${u} ${p}-models-title{font-size:13px;line-height:18px;font-weight:600}
|
|
79
|
+
${u} ${p}-model-list{border-radius:12px}
|
|
80
|
+
${u} ${p}-model{padding:12px 14px;gap:8px}
|
|
81
|
+
${u} ${p}-model-name{font-size:13px;line-height:20px}
|
|
82
|
+
${u} ${p}-model-actions,${u} ${p}-pool-save-row{gap:12px;padding-top:12px}
|
|
83
|
+
/* 保存栏以整个账号池为粘附范围,避免被更多设置的短父级截住。 */
|
|
84
|
+
${u} ${p}-pool-settings-wrap{display:contents}
|
|
85
|
+
${u} ${saveBar}{position:sticky;bottom:0;z-index:2;isolation:isolate;padding-bottom:12px;background:var(--dsw-alias-bg-layer-3,#202126)}
|
|
86
|
+
/* 滚动容器底部的内边距也属于可见区域,负偏移让背景覆盖到视口底边。 */
|
|
87
|
+
${p}-page ${saveBar}{bottom:-48px}
|
|
88
|
+
${p}-page ${saveBar}[data-save-stuck="true"]{margin-inline:-20px;padding-inline:20px;border-top:1px solid var(--dsw-alias-border-l2,#777);border-bottom:1px solid var(--dsw-alias-border-l2,#777);border-radius:0;box-shadow:0 -3px 6px rgba(0,0,0,.06)}
|
|
89
|
+
|
|
90
|
+
${u} #dsm-${plugin}-panel-capabilities:not([hidden]){display:flex;flex-direction:column;gap:14px}
|
|
91
|
+
${u} ${p}-prefs{gap:14px;padding:0}
|
|
92
|
+
${u} ${p}-pref{font-size:13px;line-height:18px;gap:10px}
|
|
93
|
+
${u} ${p}-pref-hint{font-size:12px;line-height:18px}
|
|
94
|
+
${u} ${p}-draw-image{margin:0;gap:10px;font-size:13px;line-height:18px}
|
|
95
|
+
${u} ${p}-draw-image>span{display:flex;flex-direction:column;gap:3px}
|
|
96
|
+
${u} ${p}-draw-image-hint{font-size:12px;line-height:18px}
|
|
97
|
+
${u} ${p}-pool-table{container-type:inline-size}
|
|
98
|
+
${u} ${p}-pool-current-tag{border:1px solid var(--dsw-alias-border-l2,#777);background:var(--dsw-alias-bg-layer-2,#24262c);color:var(--dsw-alias-label-secondary,#999)}
|
|
99
|
+
@container(max-width:700px){
|
|
100
|
+
${u} ${p}-pool-row{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 12px;padding:10px 12px}
|
|
101
|
+
${u} ${p}-pool-row-head{display:none}
|
|
102
|
+
${u} ${p}-pool-account{flex:1 1 auto;min-width:0}
|
|
103
|
+
${u} ${p}-pool-row-actions{flex:1 1 100%;justify-content:flex-start;padding-top:4px}
|
|
104
|
+
}
|
|
105
|
+
/* 自动签到、设备参数和 SDK 是功能差异;沿用公共间距,不移除控件。 */
|
|
106
|
+
${u} ${p}-device-mode{margin:0;padding:0 14px 12px}
|
|
107
|
+
${u} ${p}-pool .sw{width:36px;height:20px}
|
|
108
|
+
${u} ${p}-pool .sw-track::after{top:2px;left:2px;width:16px;height:16px;background:var(--dsw-alias-bg-layer-3,#fff)}
|
|
109
|
+
${u} ${p}-pool .sw input:checked+.sw-track::after{transform:translateX(16px)}
|
|
110
|
+
@media(max-width:600px){
|
|
111
|
+
${p}-page${p}-page{padding:20px 16px 32px;--dsm-series-sticky-top:-20px}
|
|
112
|
+
${p}-page ${saveBar}{bottom:-32px}
|
|
113
|
+
${u} ${memberHead}{align-items:flex-start}
|
|
114
|
+
${u} ${memberActions}{flex-wrap:wrap}
|
|
115
|
+
${u} ${p}-pool-set{flex-wrap:wrap}
|
|
116
|
+
${u} ${p}-pool-set-ctl{max-width:100%;flex-wrap:wrap}
|
|
117
|
+
${u} ${p}-pool-set-ctl select{min-width:0;max-width:100%}
|
|
118
|
+
}
|
|
119
|
+
`;
|
|
120
|
+
}
|
|
121
|
+
/** 根据页签与保存栏的实际吸附位置显示边界。 */
|
|
122
|
+
function updateStickyTabs(page) {
|
|
123
|
+
const tabs = page.querySelector("[role=\"tablist\"][class$=\"-panels\"]");
|
|
124
|
+
const stuck = tabs !== null && page.scrollTop > 0 && tabs.getBoundingClientRect().top <= page.getBoundingClientRect().top + 1;
|
|
125
|
+
page.dataset.tabsStuck = String(stuck);
|
|
126
|
+
const viewportBottom = page.getBoundingClientRect().bottom;
|
|
127
|
+
for (const bar of Array.from(page.querySelectorAll("[class$=\"-pool-save-row\"],[class$=\"-pool-save-bar\"]"))) {
|
|
128
|
+
const visible = bar.getClientRects().length > 0;
|
|
129
|
+
const bottom = Number.parseFloat(getComputedStyle(bar).bottom) || 0;
|
|
130
|
+
bar.dataset.saveStuck = String(visible && Math.abs(bar.getBoundingClientRect().bottom + bottom - viewportBottom) <= 1);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
//#endregion
|
|
134
|
+
//#region src/client/icon.ts
|
|
135
|
+
/**
|
|
136
|
+
* Plugin icon (LD brand logo, 64px) shared across the same-family plugins.
|
|
137
|
+
* Same data URI used by `dsh-subagent-default-model` so the external image
|
|
138
|
+
* stays consistent.
|
|
139
|
+
*/
|
|
140
|
+
const TRAE_PLUGIN_ICON = "data:image/png;base64,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";
|
|
141
|
+
//#endregion
|
|
142
|
+
//#region src/client/plugin-icon.tsx
|
|
143
|
+
const storageKey = "dsh-connect-trae.icon-style";
|
|
144
|
+
const changeEvent = storageKey + ".changed";
|
|
145
|
+
/**
|
|
146
|
+
* Appearance is local to this browser; account and provider settings are untouched.
|
|
147
|
+
*
|
|
148
|
+
* THE DEFAULT IS THIS PLUGIN'S OWN ICON ('original'), not the Claude skin.
|
|
149
|
+
*
|
|
150
|
+
* This shipped the other way round at first — an unset preference read as
|
|
151
|
+
* 'claude' — which meant every new user got a re-drawn silhouette before they
|
|
152
|
+
* had asked for anything, and the plugin's own artwork was the option they had
|
|
153
|
+
* to go find. A preference whose unset state is the non-default is a poor
|
|
154
|
+
* default: it makes the product's identity something you have to opt back into.
|
|
155
|
+
*
|
|
156
|
+
* An explicit 'claude' in storage still wins, so anyone who already chose the
|
|
157
|
+
* skin keeps it. Only the ABSENT case changed.
|
|
158
|
+
*/
|
|
159
|
+
function iconStyleSnapshot() {
|
|
160
|
+
try {
|
|
161
|
+
return window.localStorage.getItem(storageKey) === "claude" ? "claude" : "original";
|
|
162
|
+
} catch {
|
|
163
|
+
return "original";
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
function subscribe(listener) {
|
|
167
|
+
const onStorage = (event) => {
|
|
168
|
+
if (event.key === storageKey || event.key === null) listener();
|
|
169
|
+
};
|
|
170
|
+
window.addEventListener(changeEvent, listener);
|
|
171
|
+
window.addEventListener("storage", onStorage);
|
|
172
|
+
return () => {
|
|
173
|
+
window.removeEventListener(changeEvent, listener);
|
|
174
|
+
window.removeEventListener("storage", onStorage);
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
function setIconStyle(value) {
|
|
178
|
+
window.localStorage.setItem(storageKey, value);
|
|
179
|
+
window.dispatchEvent(new Event(changeEvent));
|
|
180
|
+
}
|
|
181
|
+
function PluginIcon(props) {
|
|
182
|
+
const saved = (0, react.useSyncExternalStore)(subscribe, iconStyleSnapshot, () => "original");
|
|
183
|
+
const variant = props.variant ?? saved;
|
|
184
|
+
const shared = {
|
|
185
|
+
className: props.className,
|
|
186
|
+
width: props.size ?? 16,
|
|
187
|
+
height: props.size ?? 16,
|
|
188
|
+
style: {
|
|
189
|
+
...props.style,
|
|
190
|
+
flexShrink: 0
|
|
191
|
+
},
|
|
192
|
+
"aria-hidden": true
|
|
193
|
+
};
|
|
194
|
+
if (variant === "original") return (0, react.createElement)("img", {
|
|
195
|
+
...shared,
|
|
196
|
+
src: TRAE_PLUGIN_ICON,
|
|
197
|
+
alt: ""
|
|
198
|
+
});
|
|
199
|
+
return (0, react.createElement)("svg", {
|
|
200
|
+
...shared,
|
|
201
|
+
viewBox: "0 0 24 24",
|
|
202
|
+
fill: "currentColor",
|
|
203
|
+
"data-icon-style": "claude",
|
|
204
|
+
"data-plugin-icon": "trae"
|
|
205
|
+
}, (0, react.createElement)("path", { d: "M4.5 5.5h3v11h3l3-3v4l-2 2h-7z" }), (0, react.createElement)("path", { d: "M10.5 5.5H15a7 7 0 0 1 0 14h-2v-3h2a4 4 0 0 0 0-8h-1.5v2l-3 3z" }));
|
|
206
|
+
}
|
|
207
|
+
/** Each choice previews the real icon and immediately persists its selection. */
|
|
208
|
+
function IconStylePreference({ t }) {
|
|
209
|
+
const selected = (0, react.useSyncExternalStore)(subscribe, iconStyleSnapshot, () => "original");
|
|
210
|
+
const [error, setError] = (0, react.useState)(false);
|
|
211
|
+
return (0, react.createElement)("div", { className: "dsm-icon-preference" }, (0, react.createElement)("div", { className: "dsm-icon-preference-copy" }, (0, react.createElement)("b", null, t("row.iconStyleLabel")), (0, react.createElement)("span", null, t("row.iconStyleHint"))), (0, react.createElement)("div", {
|
|
212
|
+
className: "dsm-icon-choices",
|
|
213
|
+
role: "radiogroup",
|
|
214
|
+
"aria-label": t("row.iconStyleLabel")
|
|
215
|
+
}, ...["claude", "original"].map((variant) => (0, react.createElement)("button", {
|
|
216
|
+
key: variant,
|
|
217
|
+
type: "button",
|
|
218
|
+
role: "radio",
|
|
219
|
+
"aria-checked": selected === variant,
|
|
220
|
+
tabIndex: selected === variant ? 0 : -1,
|
|
221
|
+
onKeyDown: (event) => {
|
|
222
|
+
if (![
|
|
223
|
+
"ArrowLeft",
|
|
224
|
+
"ArrowRight",
|
|
225
|
+
"ArrowUp",
|
|
226
|
+
"ArrowDown",
|
|
227
|
+
"Home",
|
|
228
|
+
"End"
|
|
229
|
+
].includes(event.key)) return;
|
|
230
|
+
event.preventDefault();
|
|
231
|
+
const next = event.key === "Home" ? "claude" : event.key === "End" ? "original" : variant === "claude" ? "original" : "claude";
|
|
232
|
+
try {
|
|
233
|
+
setIconStyle(next);
|
|
234
|
+
setError(false);
|
|
235
|
+
(event.currentTarget.parentElement?.querySelectorAll("[role=radio]")[next === "claude" ? 0 : 1])?.focus();
|
|
236
|
+
} catch {
|
|
237
|
+
setError(true);
|
|
238
|
+
}
|
|
239
|
+
},
|
|
240
|
+
onClick: () => {
|
|
241
|
+
try {
|
|
242
|
+
setIconStyle(variant);
|
|
243
|
+
setError(false);
|
|
244
|
+
} catch {
|
|
245
|
+
setError(true);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}, (0, react.createElement)(PluginIcon, {
|
|
249
|
+
variant,
|
|
250
|
+
size: 20
|
|
251
|
+
}), t(variant === "claude" ? "row.iconStyleClaude" : "row.iconStyleOriginal")))), error ? (0, react.createElement)("p", {
|
|
252
|
+
role: "alert",
|
|
253
|
+
className: "dsm-icon-save-error"
|
|
254
|
+
}, t("row.iconStyleSaveFailed")) : null);
|
|
255
|
+
}
|
|
256
|
+
//#endregion
|
|
10
257
|
//#region src/region.ts
|
|
11
258
|
/** Every panel, in card tab order. */
|
|
12
259
|
const TRAE_PANELS = [
|
|
@@ -937,14 +1184,6 @@ window.__ModuleLoader__.load({
|
|
|
937
1184
|
}
|
|
938
1185
|
}
|
|
939
1186
|
//#endregion
|
|
940
|
-
//#region src/client/icon.ts
|
|
941
|
-
/**
|
|
942
|
-
* Plugin icon (LD brand logo, 64px) shared across the LaoDing plugin family.
|
|
943
|
-
* Same data URI used by `dsh-subagent-default-model` so the external image
|
|
944
|
-
* stays consistent.
|
|
945
|
-
*/
|
|
946
|
-
const TRAE_PLUGIN_ICON = "data:image/png;base64,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";
|
|
947
|
-
//#endregion
|
|
948
1187
|
//#region src/client/styles.ts
|
|
949
1188
|
/**
|
|
950
1189
|
* Client styles for the Trae plugin card.
|
|
@@ -953,6 +1192,16 @@ window.__ModuleLoader__.load({
|
|
|
953
1192
|
* button primitives, same `--dsw-alias-*` token palette).
|
|
954
1193
|
*/
|
|
955
1194
|
const TRAE_CARD_CSS = `
|
|
1195
|
+
.dsm-icon-preference{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:12px;padding:12px 0;color:var(--dsw-alias-label-primary,#e6e6e6)}
|
|
1196
|
+
.dsm-icon-preference-copy{display:flex;flex-direction:column;gap:4px;flex:1;min-width:180px;font-size:13px}
|
|
1197
|
+
.dsm-icon-preference-copy>span{font-size:12px;line-height:1.5;color:var(--dsw-alias-label-tertiary,#999)}
|
|
1198
|
+
.dsm-icon-choices{display:flex;flex-wrap:wrap;gap:6px}
|
|
1199
|
+
.dsm-icon-choices>button{appearance:none;display:inline-flex;align-items:center;gap:8px;font:inherit;font-size:12px;line-height:20px;color:inherit;background:transparent;border:1px solid var(--dsw-alias-border-l2,#777);border-radius:8px;padding:7px 10px;cursor:pointer}
|
|
1200
|
+
.dsm-icon-choices>button[aria-checked="true"]{border-color:var(--dsw-alias-brand-primary,#cf795b);background:var(--dsw-alias-bg-layer-2,#25262b)}
|
|
1201
|
+
.dsm-icon-choices>button:focus-visible{outline:2px solid var(--dsw-alias-brand-primary,#cf795b);outline-offset:2px}
|
|
1202
|
+
.dsm-icon-save-error{flex-basis:100%;margin:0;color:var(--dsw-alias-state-error-primary,#c33);font-size:12px}
|
|
1203
|
+
.dsm-trae-pool-auto-checkin{display:flex;flex-direction:column;gap:6px;margin-top:8px}
|
|
1204
|
+
.dsm-trae-pool-auto-checkin-status{margin:0;font-size:12px;line-height:18px;color:var(--dsw-alias-label-secondary,#999)}
|
|
956
1205
|
.dsm-plugin-card{border:1px solid var(--dsw-alias-border-l2,#36373b);background:var(--dsw-alias-bg-layer-3,#202126);border-radius:12px;list-style:none;transition:border-color .16s,background .16s}
|
|
957
1206
|
.dsm-plugin-card:hover{border-color:var(--dsw-alias-label-dimmed,#777)}
|
|
958
1207
|
.dsm-plugin-card-open{background:var(--dsw-alias-bg-layer-2,#25262b);border-color:var(--dsw-alias-label-dimmed,#777)}
|
|
@@ -1047,7 +1296,7 @@ window.__ModuleLoader__.load({
|
|
|
1047
1296
|
* 作用域,在卡片上留下两个回归)。卡片与整页没有"外壳的滚动列",那里的分栏条
|
|
1048
1297
|
* 跟着内容正常滚走即可;sticky 在没有滚动祖先时不会生效,却会把底色带进来——
|
|
1049
1298
|
* 而底色取 layer-2,卡片本身是 layer-3,色差在卡片上就成了一条浅色带。 */
|
|
1050
|
-
.dsm-trae-section .dsm-trae-panels{position:sticky;top:-1px;z-index:2;background:var(--dsw-alias-bg-layer-2,#24262c)}
|
|
1299
|
+
.dsm-trae-section .dsm-trae-usage .dsm-trae-panels{position:sticky;top:-1px;z-index:2;padding:0;background:var(--dsw-alias-bg-layer-2,#24262c)}
|
|
1051
1300
|
.dsm-trae-panel-tab{appearance:none;font:inherit;cursor:pointer;border:0;background:transparent;padding:7px 11px;margin-bottom:-1px;border-bottom:2px solid transparent;color:var(--dsw-alias-label-tertiary,#999);font-size:13px;font-weight:600;line-height:20px;white-space:nowrap;transition:color .15s,border-color .15s}
|
|
1052
1301
|
.dsm-trae-panel-tab:hover:not(.dsm-trae-panel-tab-active){color:var(--dsw-alias-label-primary,#e6e6e6)}
|
|
1053
1302
|
.dsm-trae-panel-tab:focus-visible{outline:2px solid var(--dsw-alias-brand-primary,#5686fe);outline-offset:1px}
|
|
@@ -1055,6 +1304,12 @@ window.__ModuleLoader__.load({
|
|
|
1055
1304
|
/* No top margin of its own: the strip above already carries a border, and the
|
|
1056
1305
|
card's 16px stack gap would double the separation. */
|
|
1057
1306
|
.dsm-trae-panel{margin-top:0}
|
|
1307
|
+
/* The one-line note at the top of a section that holds controls but no Save
|
|
1308
|
+
* button. A section with switches and no footer is the first thing a reader
|
|
1309
|
+
* doubts — "did that press stick?" — so the note answers it before the doubt
|
|
1310
|
+
* forms, and it is styled as a muted paragraph rather than a warning because
|
|
1311
|
+
* "takes effect immediately" is a fact, not a caveat. */
|
|
1312
|
+
.dsm-trae-panel-note{margin:0 0 4px;padding:0;font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary,#9aa0a8)}
|
|
1058
1313
|
/* DIAGNOSTICS: a two-column fact table rather than prose. Each row is one thing
|
|
1059
1314
|
* the card actually READ, so a bug report can quote a line instead of
|
|
1060
1315
|
* paraphrasing the UI. No control lives here on purpose — a diagnostics panel
|
|
@@ -1100,6 +1355,20 @@ window.__ModuleLoader__.load({
|
|
|
1100
1355
|
.dsm-trae-prefs{display:flex;flex-direction:column;gap:14px;padding:2px 2px 0}
|
|
1101
1356
|
.dsm-trae-pref{display:flex;align-items:flex-start;gap:10px;font-size:13px;line-height:18px;color:var(--dsw-alias-label-secondary,#c6c9d0);cursor:pointer}
|
|
1102
1357
|
.dsm-trae-pref input{flex:none;cursor:pointer;accent-color:var(--dsw-alias-brand-primary,#5686fe)}
|
|
1358
|
+
/* The icon picker inside the 「能力」 list.
|
|
1359
|
+
*
|
|
1360
|
+
* It is a shared component (plugin-icon.tsx) that also renders standalone, so
|
|
1361
|
+
* its own rule carries a 12px block padding for that standalone use. Inside the
|
|
1362
|
+
* prefs column that padding doubles up with the container's 14px gap and the row
|
|
1363
|
+
* drifts away from its three neighbours, which are bare lines with no padding of
|
|
1364
|
+
* their own. Strip it here rather than in the shared rule: the standalone
|
|
1365
|
+
* spacing is still correct wherever else this component is mounted.
|
|
1366
|
+
*
|
|
1367
|
+
* min-width:0 on the copy because the labels here are Chinese sentences, not the
|
|
1368
|
+
* short English words the 180px floor was chosen for; without it a long hint
|
|
1369
|
+
* pushes the two icon buttons out of the 564px column instead of wrapping. */
|
|
1370
|
+
.dsm-trae-prefs .dsm-icon-preference{padding:0;align-items:flex-start}
|
|
1371
|
+
.dsm-trae-prefs .dsm-icon-preference-copy{min-width:0}
|
|
1103
1372
|
.dsm-trae-pref-check{inline-size:15px;block-size:15px;margin:3px 0 0}
|
|
1104
1373
|
/* The label and its explanation used to run together as one wrapped blob
|
|
1105
1374
|
("在输入框工具栏显示积分读数 在输入框工具栏显示可点击读数…"), which is what made
|
|
@@ -1171,7 +1440,7 @@ window.__ModuleLoader__.load({
|
|
|
1171
1440
|
/* The account rows: two lines each 鈥?who the account is, then what it is worth
|
|
1172
1441
|
鈥?with the one action that applies to THAT row on the right. A four-column
|
|
1173
1442
|
table was the wrong instrument here: every field demanded its own header, the
|
|
1174
|
-
columns drifted with the content (
|
|
1443
|
+
columns drifted with the content (a short nickname vs a full expiry stamp), and the
|
|
1175
1444
|
bound row repeated its "in use" badge in two different columns. */
|
|
1176
1445
|
/* The account table, shaped like the sibling WorkBuddy card's pool table: a
|
|
1177
1446
|
bordered container, a tinted header row, and one grid row per account whose
|
|
@@ -1432,9 +1701,21 @@ window.__ModuleLoader__.load({
|
|
|
1432
1701
|
.dsm-trae-model-effort-select:disabled{opacity:.6;cursor:not-allowed}
|
|
1433
1702
|
.dsm-trae-model-image{display:inline-flex;align-items:center;gap:4px;color:var(--dsw-alias-label-secondary,#c6c9d0);font-size:11px;line-height:16px;cursor:pointer}
|
|
1434
1703
|
.dsm-trae-model-image input{margin:0;accent-color:var(--dsw-alias-brand-primary,#5686fe)}
|
|
1704
|
+
/* The context-budget control: one select per row, not a row of radios.
|
|
1705
|
+
*
|
|
1706
|
+
* The fieldset stays as the grouping element — it carries the accessible name
|
|
1707
|
+
* and the hint title, and a select has no group of its own. flex:none keeps
|
|
1708
|
+
* it from stealing width from the model name, which is the thing that has to
|
|
1709
|
+
* stay readable on a 564px column.
|
|
1710
|
+
*
|
|
1711
|
+
* The select width is FIXED rather than content-sized: with 2-3 options the
|
|
1712
|
+
* widest label dictates the width, and a per-row width made the list ragged
|
|
1713
|
+
* (a 3-option row's control was visibly wider than its neighbours). */
|
|
1435
1714
|
.dsm-trae-context-budget{display:flex;align-items:center;justify-content:flex-end;gap:12px;flex:none;margin:0;padding:0;border:0;color:var(--dsw-alias-label-secondary,#c6c9d0);font-size:11px;line-height:16px}
|
|
1436
1715
|
.dsm-trae-context-budget label{display:inline-flex;align-items:center;gap:4px;cursor:pointer}
|
|
1437
1716
|
.dsm-trae-context-budget input{margin:0;accent-color:var(--dsw-alias-brand-primary,#5686fe)}
|
|
1717
|
+
.dsm-trae-context-select{flex:none;width:96px;max-width:none;padding:2px 6px;font:inherit;font-size:11px;line-height:16px;color:var(--dsw-alias-label-primary,#e6e6e6);background:var(--dsw-alias-bg-layer-3,#2a2c33);border:1px solid var(--dsw-alias-border-l2,#3a3d45);border-radius:7px;cursor:pointer}
|
|
1718
|
+
.dsm-trae-context-select:disabled{cursor:default;opacity:.6}
|
|
1438
1719
|
.dsm-trae-model-capability-note{margin:0;color:var(--dsw-alias-label-tertiary,#999);font-size:12px;line-height:18px}
|
|
1439
1720
|
.dsm-trae-model-actions{display:flex;align-items:center;justify-content:space-between;gap:12px;border-top:1px solid var(--dsw-alias-border-l2,#36373b);padding-top:12px}
|
|
1440
1721
|
.dsm-trae-model-actions-buttons{display:flex;align-items:center;justify-content:flex-end;gap:8px}
|
|
@@ -1615,7 +1896,7 @@ window.__ModuleLoader__.load({
|
|
|
1615
1896
|
* 这张卡同时画在三处,宽度与窗口毫无关系:输入框卡片、整页版(上限 860px)、
|
|
1616
1897
|
* 以及设置面板的内容列(1400px 屏上是 564px)。本文件里所有 @media 断点测的
|
|
1617
1898
|
* 都是**视口**,所以在设置面板里它们永远不触发——564px 的列拿到了五列桌面表格,
|
|
1618
|
-
* 每个单元格都在截断(实测账号列被压到 76px
|
|
1899
|
+
* 每个单元格都在截断(实测账号列被压到 76px,一个 9 位数字账号名只剩前 5 个字符)。
|
|
1619
1900
|
*
|
|
1620
1901
|
* container-type:inline-size 让下面的断点改测**这张表**的宽度,那才是行真正要
|
|
1621
1902
|
* 塞进去的宽度。
|
|
@@ -1641,7 +1922,23 @@ window.__ModuleLoader__.load({
|
|
|
1641
1922
|
reads as a selection control, and the checkbox beside it already is one. */
|
|
1642
1923
|
.dsm-trae-pool-row-current{background:rgba(86,134,254,.07);box-shadow:inset 3px 0 0 var(--dsw-alias-brand-primary,#5686fe)}
|
|
1643
1924
|
.dsm-trae-pool-row-ghost{opacity:.7}
|
|
1644
|
-
|
|
1925
|
+
/* The row's buttons: RIGHT side of the row, pulled there by the auto margin
|
|
1926
|
+
* (learned from dsh-connect-workbuddy, which had the same complaint).
|
|
1927
|
+
*
|
|
1928
|
+
* WHY THE AUTO MARGIN AND NOT JUST justify-content. In the wide grid this cell
|
|
1929
|
+
* IS the last track, so justify-content:flex-end was enough. But in the
|
|
1930
|
+
* NARROW form the row becomes a wrapping flex line, and this cell is a sibling
|
|
1931
|
+
* of the account line rather than a track beside it -- so it claimed a line of
|
|
1932
|
+
* its own and the row spent a whole line on two small buttons.
|
|
1933
|
+
*
|
|
1934
|
+
* margin-inline-start:auto moves it to the END of whatever line has room. In
|
|
1935
|
+
* the narrow form that is the account line, which is the SHORTEST line in the
|
|
1936
|
+
* row, so the buttons land beside the account name where the eye already is
|
|
1937
|
+
* instead of under it.
|
|
1938
|
+
*
|
|
1939
|
+
* flex:none is load-bearing: the account name may truncate, the buttons may
|
|
1940
|
+
* not, and a shrunken button is unclickable. */
|
|
1941
|
+
.dsm-trae-pool-row-actions{display:flex;flex-wrap:wrap;gap:6px;justify-content:flex-end;flex:none;margin-inline-start:auto}
|
|
1645
1942
|
.dsm-trae-pool-account{display:grid;grid-template-columns:auto minmax(0,1fr);align-items:center;gap:2px 8px;min-width:0}
|
|
1646
1943
|
.dsm-trae-pool-check{display:inline-flex;align-items:center;flex:none;grid-column:1;grid-row:1;cursor:pointer}
|
|
1647
1944
|
.dsm-trae-pool-check input{flex:none;margin:0;cursor:pointer;accent-color:var(--dsw-alias-brand-primary,#5686fe)}
|
|
@@ -1719,20 +2016,55 @@ window.__ModuleLoader__.load({
|
|
|
1719
2016
|
*
|
|
1720
2017
|
* .dsm-trae-pool-row-head 隐藏:它的标签描述的是已经不存在的轨道。 */
|
|
1721
2018
|
@container (max-width:700px){
|
|
1722
|
-
|
|
2019
|
+
/* The dsm-trae-usage hop is load-bearing: series-layout.ts appends a
|
|
2020
|
+
dsm-trae-usage dsm-trae-pool-row rule inside this same container query, and
|
|
2021
|
+
at 0,2,0 it beat the plain dsm-trae-pool-row below (0,1,0). Measured after
|
|
2022
|
+
the 4.14.0 merge: display came back as flex, rows grew 75 -> 111px and the
|
|
2023
|
+
check-in fell to line 2 again, while the grid COLUMN rules still applied —
|
|
2024
|
+
a half-applied layout, which is why it looked like a padding problem rather
|
|
2025
|
+
than a specificity one. */
|
|
2026
|
+
.dsm-trae-usage .dsm-trae-pool-row{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 12px;padding:var(--dsm-trae-pool-pad-y) 12px}
|
|
1723
2027
|
.dsm-trae-pool-row-head{display:none}
|
|
1724
|
-
.
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
2028
|
+
/* TWO ROWS, EXPLICITLY PLACED. Not "let flex wrap and hope".
|
|
2029
|
+
*
|
|
2030
|
+
* 每一行账号只有两行:
|
|
2031
|
+
*
|
|
2032
|
+
* 第一行 [勾选 + 账号名 + 标签] [签到状态 + 按钮] [积分]
|
|
2033
|
+
* 第二行 [状态 · 测得时间 · 来源] [测速] [删除]
|
|
2034
|
+
*
|
|
2035
|
+
* 以前是 flex-wrap,由内容决定怎么折——结果是同一个表格里的行落在不同的
|
|
2036
|
+
* 位置(实测三行分别占地 4 / 4 / 3 个纵向位置),有的积分被挤到中间(x=588)。
|
|
2037
|
+
* 网格把每个事实钉在一个格子里:无论账号名多长,积分永远停在同一右缘,
|
|
2038
|
+
* 「签到」永远和名字同一行。
|
|
2039
|
+
*
|
|
2040
|
+
* 列的含义:
|
|
2041
|
+
* 1fr —— 会伸缩的那一列(账号名、状态)。
|
|
2042
|
+
* auto —— 签到:宽度由文字决定(「已签到」「未签到」「本设备今日已用」)。
|
|
2043
|
+
* auto —— 积分:贴在右缘,flex:none,不许被压缩。
|
|
2044
|
+
*
|
|
2045
|
+
* 积分为什么单独成列而不是跟在名字后面:余额是这一行里唯一会被**跨行横向比对**
|
|
2046
|
+
* 的数字(「哪个账号还剩得多」),而跟着名字走时三行分别落在 593 / 614 / 498,
|
|
2047
|
+
* 眼睛没法竖着扫。等宽字形让小数点也对齐。
|
|
2048
|
+
*
|
|
2049
|
+
* 状态那一格(probe)独占第二行:它讲的是「能不能用」,与「还剩多少」不是同一个
|
|
2050
|
+
* 问题;按钮也放在第二行,因为第一行已经有三个事实,再塞两个按钮会把账号名压窄。 */
|
|
2051
|
+
.dsm-trae-usage .dsm-trae-pool-row:not(.dsm-trae-pool-row-head){
|
|
2052
|
+
display:grid;grid-template-columns:minmax(0,1fr) auto auto;
|
|
2053
|
+
align-items:center;gap:4px 10px}
|
|
2054
|
+
.dsm-trae-pool-account{grid-column:1;grid-row:1;display:flex;flex-wrap:wrap;align-items:baseline;gap:2px 8px;min-width:0}
|
|
2055
|
+
.dsm-trae-pool-checkin{grid-column:2;grid-row:1;justify-self:end;flex:none}
|
|
2056
|
+
.dsm-trae-pool-credit{grid-column:3;grid-row:1;justify-self:end;flex:none;flex-direction:row;align-items:baseline;gap:2px 8px;text-align:right;font-variant-numeric:tabular-nums}
|
|
2057
|
+
.dsm-trae-pool-probe{grid-column:1;grid-row:2;min-width:0}
|
|
2058
|
+
/* Spans from the check-in column to the edge: the buttons sit under the figures
|
|
2059
|
+
they act on, flush with the credit above them. */
|
|
2060
|
+
.dsm-trae-pool-row-actions{grid-column:2/-1;grid-row:2;justify-self:end;justify-content:flex-end;margin-inline-start:0;padding-top:0}
|
|
1729
2061
|
/* THE PROBE CELL'S OWN COLUMN, collapsed to one line.
|
|
1730
2062
|
*
|
|
1731
2063
|
* 这一条是最容易漏掉的:.dsm-trae-pool-probe 只是个 min-width:0 的外层包装,
|
|
1732
2064
|
* 真正竖排的是它内部的 .dsm-trae-pool-probe-cell(flex-direction:column)。
|
|
1733
2065
|
* 只改外层包装的话,状态列仍然一句一行,被挤成「正常 / 测得 3 天前 / 来自测速 /
|
|
1734
2066
|
* upstream answered」四行——旁边只有 12px 间距,整行高度就被这一格撑到 100px
|
|
1735
|
-
*
|
|
2067
|
+
* 以上,账号名也跟着被压窄(实测截成前几个字符「用户7」)。
|
|
1736
2068
|
*
|
|
1737
2069
|
* 改成横排并允许在自己内部换行:这四个事实读起来本来就是一句话
|
|
1738
2070
|
* (「正常 · 测得 3 天前 · 来自测速 · upstream answered」),宽时从左排到右,
|
|
@@ -1742,7 +2074,7 @@ window.__ModuleLoader__.load({
|
|
|
1742
2074
|
*
|
|
1743
2075
|
* 宽的时候它是个三行网格(名字 / 标签 / 探针时间),第一列固定给勾选框。
|
|
1744
2076
|
* 在窄列里这三行没有理由继续各占一行——它们本来就是一句话
|
|
1745
|
-
* (「
|
|
2077
|
+
* (「demo-usr · 已在池中 · 测试于 11/03, 06:35」),横排后名字与这两条短事实
|
|
1746
2078
|
* 共享一行,只有真的放不下时才折行。勾选框仍然排在最前,并保持垂直居中对齐
|
|
1747
2079
|
* 到第一行基线(align-self:baseline 会让它沉到行底)。 */
|
|
1748
2080
|
.dsm-trae-pool-account{display:flex;flex-wrap:wrap;align-items:baseline;gap:2px 8px}
|
|
@@ -1806,7 +2138,7 @@ window.__ModuleLoader__.load({
|
|
|
1806
2138
|
.dsm-trae-section-title{margin:0;font-size:15px;font-weight:600;line-height:22px}
|
|
1807
2139
|
.dsm-trae-section-desc{margin:0;font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary,#999)}
|
|
1808
2140
|
.dsm-trae-panel-icon{display:block;border-radius:4px;flex:none}
|
|
1809
|
-
|
|
2141
|
+
` + seriesLayoutCss("trae");
|
|
1810
2142
|
/**
|
|
1811
2143
|
* Composer-row readout styles, injected by the readout itself.
|
|
1812
2144
|
*
|
|
@@ -2360,6 +2692,7 @@ window.__ModuleLoader__.load({
|
|
|
2360
2692
|
const base = regionPoolOf(settingsScope?.getSnapshot().value, panel);
|
|
2361
2693
|
return {
|
|
2362
2694
|
enabled: base.enabled === true,
|
|
2695
|
+
autoCheckin: base.autoCheckin === true,
|
|
2363
2696
|
targetModelId: base.targetModelId ?? pool.targetModelId ?? pool.staleTargetModelId ?? "",
|
|
2364
2697
|
memberAccountIds: [...base.memberAccountIds ?? []],
|
|
2365
2698
|
probeInputTokens: numberOr(base.probeInputTokens, numberOr(pool.probeInputTokens, 0))
|
|
@@ -2383,6 +2716,7 @@ window.__ModuleLoader__.load({
|
|
|
2383
2716
|
*/
|
|
2384
2717
|
const probeSupported = typeof pool.probeInputTokens === "number";
|
|
2385
2718
|
const [enabled, setEnabled] = (0, react.useState)(saved.enabled);
|
|
2719
|
+
const [autoCheckin, setAutoCheckin] = (0, react.useState)(saved.autoCheckin);
|
|
2386
2720
|
const [targetModelId, setTargetModelId] = (0, react.useState)(saved.targetModelId ?? "");
|
|
2387
2721
|
const [probeInputTokens, setProbeInputTokens] = (0, react.useState)(saved.probeInputTokens);
|
|
2388
2722
|
const [selected, setSelected] = (0, react.useState)(() => new Set(saved.memberAccountIds ?? []));
|
|
@@ -2434,8 +2768,11 @@ window.__ModuleLoader__.load({
|
|
|
2434
2768
|
pool,
|
|
2435
2769
|
knownIds
|
|
2436
2770
|
]);
|
|
2437
|
-
const dirty = enabled !== saved.enabled || (targetModelId ?? "") !== (saved.targetModelId ?? "") || probeSupported && probeInputTokens !== saved.probeInputTokens || !sameIds([...selected], saved.memberAccountIds);
|
|
2771
|
+
const dirty = enabled !== saved.enabled || autoCheckin !== saved.autoCheckin || (targetModelId ?? "") !== (saved.targetModelId ?? "") || probeSupported && probeInputTokens !== saved.probeInputTokens || !sameIds([...selected], saved.memberAccountIds);
|
|
2438
2772
|
const writable = settingsScope?.getSnapshot().writable === true;
|
|
2773
|
+
(0, react.useEffect)(() => {
|
|
2774
|
+
setAutoCheckin(saved.autoCheckin);
|
|
2775
|
+
}, [panel, saved.autoCheckin]);
|
|
2439
2776
|
const savedMemberKey = (0, react.useMemo)(() => [...saved.memberAccountIds ?? []].sort().join("\0"), [saved]);
|
|
2440
2777
|
(0, react.useEffect)(() => {
|
|
2441
2778
|
setEnabled(saved.enabled);
|
|
@@ -2473,6 +2810,7 @@ window.__ModuleLoader__.load({
|
|
|
2473
2810
|
const selectNone = () => setSelected(/* @__PURE__ */ new Set());
|
|
2474
2811
|
const discard = () => {
|
|
2475
2812
|
setEnabled(saved.enabled);
|
|
2813
|
+
setAutoCheckin(saved.autoCheckin);
|
|
2476
2814
|
setTargetModelId(saved.targetModelId ?? "");
|
|
2477
2815
|
setProbeInputTokens(saved.probeInputTokens);
|
|
2478
2816
|
setSelected(new Set(saved.memberAccountIds ?? []));
|
|
@@ -2487,13 +2825,14 @@ window.__ModuleLoader__.load({
|
|
|
2487
2825
|
try {
|
|
2488
2826
|
const next = {
|
|
2489
2827
|
enabled,
|
|
2828
|
+
autoCheckin,
|
|
2490
2829
|
...targetModelId === "" ? {} : { targetModelId },
|
|
2491
2830
|
memberAccountIds: [...selected],
|
|
2492
2831
|
...probeSupported ? { probeInputTokens } : {}
|
|
2493
2832
|
};
|
|
2494
2833
|
await writeSettingsField(settingsScope, "regions", nextRegionPool(settingsScope.getSnapshot().value, panel, next), (readBack) => {
|
|
2495
2834
|
const readPool = regionPoolOf(readBack, panel);
|
|
2496
|
-
return readPool.enabled === (next.enabled ?? false) && sameIds(readPool.memberAccountIds, next.memberAccountIds) && (readPool.targetModelId ?? "") === (next.targetModelId ?? "") && (!probeSupported || (readPool.probeInputTokens ?? 0) === probeInputTokens);
|
|
2835
|
+
return readPool.autoCheckin === next.autoCheckin && readPool.enabled === (next.enabled ?? false) && sameIds(readPool.memberAccountIds, next.memberAccountIds) && (readPool.targetModelId ?? "") === (next.targetModelId ?? "") && (!probeSupported || (readPool.probeInputTokens ?? 0) === probeInputTokens);
|
|
2497
2836
|
});
|
|
2498
2837
|
pushLog("ok", t("row.poolLogSaved"));
|
|
2499
2838
|
onChanged?.();
|
|
@@ -2770,39 +3109,82 @@ window.__ModuleLoader__.load({
|
|
|
2770
3109
|
}),
|
|
2771
3110
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2772
3111
|
className: "dsm-trae-pool-settings dsm-trae-pool-modebar",
|
|
2773
|
-
children: [
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
3112
|
+
children: [
|
|
3113
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3114
|
+
className: "dsm-trae-pool-modebar-row",
|
|
3115
|
+
children: [
|
|
3116
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
|
|
3117
|
+
className: "dsm-trae-switch dsm-trae-switch-pill",
|
|
3118
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
3119
|
+
type: "checkbox",
|
|
3120
|
+
checked: enabled,
|
|
3121
|
+
disabled: busy !== void 0 || !writable,
|
|
3122
|
+
"aria-label": t("row.poolEnabled"),
|
|
3123
|
+
onChange: (e) => {
|
|
3124
|
+
setEnabled(e.target.checked);
|
|
3125
|
+
}
|
|
3126
|
+
})
|
|
3127
|
+
}),
|
|
3128
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("b", {
|
|
3129
|
+
className: "dsm-trae-pool-modebar-label",
|
|
3130
|
+
children: t("row.poolEnabled")
|
|
3131
|
+
}),
|
|
3132
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3133
|
+
className: "dsm-trae-pool-modebar-state",
|
|
3134
|
+
children: pool.enabled === true ? t("row.poolModeAuto") : t("row.poolModeManual")
|
|
3135
|
+
}),
|
|
3136
|
+
dirty ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3137
|
+
className: "dsm-trae-pool-dirty",
|
|
3138
|
+
role: "status",
|
|
3139
|
+
children: t("row.poolDirty")
|
|
3140
|
+
}) : null
|
|
3141
|
+
]
|
|
3142
|
+
}),
|
|
3143
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
|
|
3144
|
+
className: "dsm-trae-pool-note",
|
|
3145
|
+
children: [
|
|
3146
|
+
t("row.poolEnabledHint"),
|
|
3147
|
+
" ",
|
|
3148
|
+
t("row.poolFailoverHint")
|
|
3149
|
+
]
|
|
3150
|
+
}),
|
|
3151
|
+
panel === "cn" && pool.checkinSupported && typeof pool.autoCheckin === "boolean" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3152
|
+
className: "dsm-trae-pool-auto-checkin",
|
|
3153
|
+
children: [
|
|
3154
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3155
|
+
className: "dsm-trae-pool-modebar-row",
|
|
3156
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
|
|
3157
|
+
className: "dsm-trae-switch dsm-trae-switch-pill",
|
|
3158
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
3159
|
+
type: "checkbox",
|
|
3160
|
+
checked: autoCheckin,
|
|
3161
|
+
disabled: busy !== void 0 || !writable,
|
|
3162
|
+
"aria-label": t("row.poolAutoCheckin"),
|
|
3163
|
+
onChange: (event) => {
|
|
3164
|
+
setAutoCheckin(event.target.checked);
|
|
3165
|
+
}
|
|
3166
|
+
})
|
|
3167
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("b", {
|
|
3168
|
+
className: "dsm-trae-pool-modebar-label",
|
|
3169
|
+
children: t("row.poolAutoCheckin")
|
|
3170
|
+
})]
|
|
3171
|
+
}),
|
|
3172
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
3173
|
+
className: "dsm-trae-pool-note",
|
|
3174
|
+
children: t("row.poolAutoCheckinHint")
|
|
3175
|
+
}),
|
|
3176
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
3177
|
+
className: "dsm-trae-pool-note",
|
|
3178
|
+
children: t("row.poolAutoCheckinDeviceHint")
|
|
3179
|
+
}),
|
|
3180
|
+
pool.autoCheckin === true ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
3181
|
+
className: "dsm-trae-pool-auto-checkin-status",
|
|
3182
|
+
role: "status",
|
|
3183
|
+
children: pool.autoCheckinState?.deviceBlocked === true ? t("row.poolAutoCheckinDeviceDone") : pool.autoCheckinState !== void 0 ? t(pool.autoCheckinState.failures > 0 ? "row.poolAutoCheckinRetry" : "row.poolAutoCheckinProgress", { count: pool.autoCheckinState.done }) : t("row.poolAutoCheckinWaiting")
|
|
3184
|
+
}) : null
|
|
3185
|
+
]
|
|
3186
|
+
}) : null
|
|
3187
|
+
]
|
|
2806
3188
|
}),
|
|
2807
3189
|
pool.enabled === true && serving !== void 0 && serving.member !== true ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2808
3190
|
className: "dsm-trae-pool-note dsm-trae-pool-serving-note",
|
|
@@ -4027,96 +4409,97 @@ window.__ModuleLoader__.load({
|
|
|
4027
4409
|
* is precisely why this section has no 「保存」 of its own — the model catalog,
|
|
4028
4410
|
* which does, lives in its own section.
|
|
4029
4411
|
*/
|
|
4030
|
-
function TraeAccountPanel({ t, settingsScope, panel, status, statusLabel, credentialRegionIsAi, regionOn, showPointsInMainUi, onToggleShowPoints, creditPosition, onCreditPositionChange, sidebarPanelOn, sidebarPanelBusy, onToggleSidebarPanel, savingPreferences, creditsLabelId, creditsHintId, rows, busy, rescanNote, onRescan, switchingAccount, onSwitchAccount, onClaim, onTransferChanged, poolDetails, poolClaims, models, deviceClaimed, onPoolChanged, onPoolRefresh, creditsUnavailable, creditsExpiry, alternatives, onSwitchToAlternative }) {
|
|
4412
|
+
function TraeAccountPanel({ t, settingsScope, panel, status, statusLabel, credentialRegionIsAi, regionOn, showPointsInMainUi, onToggleShowPoints, creditPosition, onCreditPositionChange, sidebarPanelOn, sidebarPanelBusy, onToggleSidebarPanel, savingPreferences, creditsLabelId, creditsHintId, rows, busy, rescanNote, onRescan, switchingAccount, onSwitchAccount, onClaim, onTransferChanged, poolDetails, poolClaims, models = [], deviceClaimed = false, onPoolChanged = () => {}, onPoolRefresh = () => {}, creditsUnavailable, creditsExpiry, alternatives, onSwitchToAlternative, section = "all" }) {
|
|
4031
4413
|
const writable = settingsScope?.getSnapshot().writable === true;
|
|
4032
4414
|
const signedIn = status.status === "signed-in";
|
|
4033
4415
|
const accounts = signedIn ? status.accounts : [];
|
|
4034
4416
|
const pool = signedIn ? status.pool : void 0;
|
|
4035
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
|
|
4047
|
-
|
|
4048
|
-
|
|
4049
|
-
|
|
4050
|
-
|
|
4051
|
-
|
|
4052
|
-
|
|
4053
|
-
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
children: t(credentialRegionIsAi ? "row.showPointsInMainUiHintAi" : "row.showPointsInMainUiHint")
|
|
4061
|
-
})]
|
|
4417
|
+
if (section === "prefs") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4418
|
+
className: "dsm-trae-prefs",
|
|
4419
|
+
children: [
|
|
4420
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
4421
|
+
className: "dsm-trae-pref",
|
|
4422
|
+
title: t(credentialRegionIsAi ? "row.showPointsInMainUiHintAi" : "row.showPointsInMainUiHint"),
|
|
4423
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
4424
|
+
type: "checkbox",
|
|
4425
|
+
className: "dsm-trae-pref-check",
|
|
4426
|
+
checked: showPointsInMainUi,
|
|
4427
|
+
disabled: !writable || savingPreferences,
|
|
4428
|
+
"aria-describedby": creditsHintId,
|
|
4429
|
+
onChange: (event) => {
|
|
4430
|
+
onToggleShowPoints(event.currentTarget.checked);
|
|
4431
|
+
}
|
|
4432
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
4433
|
+
className: "dsm-trae-pref-copy",
|
|
4434
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4435
|
+
className: "dsm-trae-pref-label",
|
|
4436
|
+
id: creditsLabelId,
|
|
4437
|
+
children: t("row.showPointsInMainUi")
|
|
4438
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4439
|
+
className: "dsm-trae-pref-hint",
|
|
4440
|
+
id: creditsHintId,
|
|
4441
|
+
children: t(credentialRegionIsAi ? "row.showPointsInMainUiHintAi" : "row.showPointsInMainUiHint")
|
|
4062
4442
|
})]
|
|
4063
|
-
})
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
|
|
4071
|
-
|
|
4072
|
-
className: "dsm-trae-pref-label",
|
|
4073
|
-
children: t("row.creditPositionLabel")
|
|
4074
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
4075
|
-
className: "dsm-trae-credit-position",
|
|
4076
|
-
value: regionOn ? creditPosition : "composer",
|
|
4077
|
-
disabled: !regionOn || !writable || savingPreferences,
|
|
4078
|
-
"aria-label": t("row.creditPositionAria", { region: panel === "cn" ? t("row.tabCn") : panel === "enterprise" ? t("row.tabEnterprise") : t("row.tabAi") }),
|
|
4079
|
-
onChange: (event) => {
|
|
4080
|
-
onCreditPositionChange(event.currentTarget.value === "stats" ? "stats" : "composer");
|
|
4081
|
-
},
|
|
4082
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
4083
|
-
value: "composer",
|
|
4084
|
-
children: t("row.creditPositionComposer")
|
|
4085
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
4086
|
-
value: "stats",
|
|
4087
|
-
children: t("row.creditPositionStats")
|
|
4088
|
-
})]
|
|
4089
|
-
})]
|
|
4090
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4091
|
-
className: "dsm-trae-pref-hint",
|
|
4092
|
-
children: t("row.creditPositionHint")
|
|
4093
|
-
})]
|
|
4094
|
-
})
|
|
4095
|
-
}),
|
|
4096
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
4097
|
-
className: "dsm-trae-pref",
|
|
4098
|
-
title: t("row.sidebarPanelHint"),
|
|
4099
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
4100
|
-
type: "checkbox",
|
|
4101
|
-
className: "dsm-trae-pref-check",
|
|
4102
|
-
checked: sidebarPanelOn,
|
|
4103
|
-
disabled: sidebarPanelBusy || savingPreferences,
|
|
4104
|
-
onChange: (event) => {
|
|
4105
|
-
onToggleSidebarPanel(event.currentTarget.checked);
|
|
4106
|
-
}
|
|
4107
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
4108
|
-
className: "dsm-trae-pref-copy",
|
|
4443
|
+
})]
|
|
4444
|
+
}),
|
|
4445
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
|
|
4446
|
+
className: "dsm-trae-pref dsm-trae-credit-position-pref",
|
|
4447
|
+
title: t("row.creditPositionHint"),
|
|
4448
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
4449
|
+
className: "dsm-trae-pref-copy",
|
|
4450
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
4451
|
+
className: "dsm-trae-pref-lead",
|
|
4109
4452
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4110
4453
|
className: "dsm-trae-pref-label",
|
|
4111
|
-
children: t("row.
|
|
4112
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.
|
|
4113
|
-
className: "dsm-trae-
|
|
4114
|
-
|
|
4454
|
+
children: t("row.creditPositionLabel")
|
|
4455
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
4456
|
+
className: "dsm-trae-credit-position",
|
|
4457
|
+
value: regionOn ? creditPosition : "composer",
|
|
4458
|
+
disabled: !regionOn || !writable || savingPreferences,
|
|
4459
|
+
"aria-label": t("row.creditPositionAria", { region: panel === "cn" ? t("row.tabCn") : panel === "enterprise" ? t("row.tabEnterprise") : t("row.tabAi") }),
|
|
4460
|
+
onChange: (event) => {
|
|
4461
|
+
onCreditPositionChange(event.currentTarget.value === "stats" ? "stats" : "composer");
|
|
4462
|
+
},
|
|
4463
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
4464
|
+
value: "composer",
|
|
4465
|
+
children: t("row.creditPositionComposer")
|
|
4466
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
4467
|
+
value: "stats",
|
|
4468
|
+
children: t("row.creditPositionStats")
|
|
4469
|
+
})]
|
|
4115
4470
|
})]
|
|
4471
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4472
|
+
className: "dsm-trae-pref-hint",
|
|
4473
|
+
children: t("row.creditPositionHint")
|
|
4116
4474
|
})]
|
|
4117
4475
|
})
|
|
4118
|
-
|
|
4119
|
-
|
|
4476
|
+
}),
|
|
4477
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
4478
|
+
className: "dsm-trae-pref",
|
|
4479
|
+
title: t("row.sidebarPanelHint"),
|
|
4480
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
4481
|
+
type: "checkbox",
|
|
4482
|
+
className: "dsm-trae-pref-check",
|
|
4483
|
+
checked: sidebarPanelOn,
|
|
4484
|
+
disabled: sidebarPanelBusy || savingPreferences,
|
|
4485
|
+
onChange: (event) => {
|
|
4486
|
+
onToggleSidebarPanel(event.currentTarget.checked);
|
|
4487
|
+
}
|
|
4488
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
4489
|
+
className: "dsm-trae-pref-copy",
|
|
4490
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4491
|
+
className: "dsm-trae-pref-label",
|
|
4492
|
+
children: t("row.sidebarPanelLabel")
|
|
4493
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4494
|
+
className: "dsm-trae-pref-hint",
|
|
4495
|
+
children: t("row.sidebarPanelHint")
|
|
4496
|
+
})]
|
|
4497
|
+
})]
|
|
4498
|
+
}),
|
|
4499
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconStylePreference, { t })
|
|
4500
|
+
]
|
|
4501
|
+
}) });
|
|
4502
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
4120
4503
|
pool !== void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
4121
4504
|
className: "dsm-trae-accounts",
|
|
4122
4505
|
"aria-label": t("row.accountsTitle"),
|
|
@@ -4322,9 +4705,9 @@ window.__ModuleLoader__.load({
|
|
|
4322
4705
|
className: "dsm-trae-usage-error",
|
|
4323
4706
|
children: t("row.checkinDisabled")
|
|
4324
4707
|
}) : null,
|
|
4325
|
-
status.checkinError === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4708
|
+
status.checkinError === void 0 || status.checkin?.checkedIn === true || status.checkin?.didCheckedIn === true || status.pool?.autoCheckinState?.deviceBlocked === true ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4326
4709
|
className: "dsm-trae-usage-error",
|
|
4327
|
-
children: t("row.
|
|
4710
|
+
children: t("row.checkinStatusError", { message: status.checkinError })
|
|
4328
4711
|
})
|
|
4329
4712
|
] }) : null
|
|
4330
4713
|
] });
|
|
@@ -5244,7 +5627,6 @@ window.__ModuleLoader__.load({
|
|
|
5244
5627
|
if (mounted.current) {
|
|
5245
5628
|
const message = error instanceof Error ? error.message : t("row.requestFailed");
|
|
5246
5629
|
setRescanNote(t("row.accountsRescanFailed", { message }));
|
|
5247
|
-
setWriteError(message);
|
|
5248
5630
|
}
|
|
5249
5631
|
} finally {
|
|
5250
5632
|
if (mounted.current) setBusy(false);
|
|
@@ -6148,9 +6530,22 @@ window.__ModuleLoader__.load({
|
|
|
6148
6530
|
}, item);
|
|
6149
6531
|
})
|
|
6150
6532
|
}),
|
|
6151
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
6152
|
-
className: "dsm-trae-
|
|
6153
|
-
children:
|
|
6533
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6534
|
+
className: "dsm-trae-region-summary",
|
|
6535
|
+
children: [
|
|
6536
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
6537
|
+
className: "dsm-trae-models-summary dsm-trae-tab-hint",
|
|
6538
|
+
children: t("row.tabHint")
|
|
6539
|
+
}),
|
|
6540
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
6541
|
+
className: "dsm-trae-models-summary",
|
|
6542
|
+
children: t("row.tabCredentialHint")
|
|
6543
|
+
}),
|
|
6544
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
6545
|
+
className: "dsm-trae-models-summary dsm-trae-free-quota-warn",
|
|
6546
|
+
children: t("row.tabFreeQuotaWarn")
|
|
6547
|
+
})
|
|
6548
|
+
]
|
|
6154
6549
|
}),
|
|
6155
6550
|
writeError === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
6156
6551
|
className: "dsm-trae-usage-error",
|
|
@@ -6191,6 +6586,18 @@ window.__ModuleLoader__.load({
|
|
|
6191
6586
|
},
|
|
6192
6587
|
children: t("row.panelModels")
|
|
6193
6588
|
}),
|
|
6589
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
6590
|
+
type: "button",
|
|
6591
|
+
role: "tab",
|
|
6592
|
+
id: "dsm-trae-tab-capabilities",
|
|
6593
|
+
"aria-controls": "dsm-trae-panel-capabilities",
|
|
6594
|
+
"aria-selected": panel === "capabilities",
|
|
6595
|
+
className: `dsm-trae-panel-tab${panel === "capabilities" ? " dsm-trae-panel-tab-active" : ""}`,
|
|
6596
|
+
onClick: () => {
|
|
6597
|
+
setPanel("capabilities");
|
|
6598
|
+
},
|
|
6599
|
+
children: t("row.panelCapabilities")
|
|
6600
|
+
}),
|
|
6194
6601
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
6195
6602
|
type: "button",
|
|
6196
6603
|
role: "tab",
|
|
@@ -6214,6 +6621,7 @@ window.__ModuleLoader__.load({
|
|
|
6214
6621
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TraeAccountPanel, {
|
|
6215
6622
|
t,
|
|
6216
6623
|
settingsScope,
|
|
6624
|
+
section: "accounts",
|
|
6217
6625
|
panel: activeRegion,
|
|
6218
6626
|
status,
|
|
6219
6627
|
statusLabel: label,
|
|
@@ -6281,6 +6689,68 @@ window.__ModuleLoader__.load({
|
|
|
6281
6689
|
}
|
|
6282
6690
|
})
|
|
6283
6691
|
}),
|
|
6692
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6693
|
+
className: "dsm-trae-panel",
|
|
6694
|
+
role: "tabpanel",
|
|
6695
|
+
id: "dsm-trae-panel-capabilities",
|
|
6696
|
+
"aria-labelledby": "dsm-trae-tab-capabilities",
|
|
6697
|
+
hidden: signedIn && panel !== "capabilities",
|
|
6698
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
6699
|
+
className: "dsm-trae-panel-note",
|
|
6700
|
+
children: t("row.panelCapabilitiesHint")
|
|
6701
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TraeAccountPanel, {
|
|
6702
|
+
t,
|
|
6703
|
+
settingsScope,
|
|
6704
|
+
section: "prefs",
|
|
6705
|
+
panel: activeRegion,
|
|
6706
|
+
status,
|
|
6707
|
+
statusLabel: label,
|
|
6708
|
+
credentialRegionIsAi,
|
|
6709
|
+
regionOn: activeRegionOn,
|
|
6710
|
+
showPointsInMainUi: settingsEdits.showPointsInMainUi,
|
|
6711
|
+
onToggleShowPoints: (value) => {
|
|
6712
|
+
writePreference("showPointsInMainUi", value);
|
|
6713
|
+
},
|
|
6714
|
+
creditPosition: creditPositionOn(activeRegion),
|
|
6715
|
+
onCreditPositionChange: (position) => {
|
|
6716
|
+
changeCreditPosition(activeRegion, position);
|
|
6717
|
+
},
|
|
6718
|
+
sidebarPanelOn,
|
|
6719
|
+
sidebarPanelBusy,
|
|
6720
|
+
onToggleSidebarPanel: (value) => {
|
|
6721
|
+
writeSidebarPanel(value);
|
|
6722
|
+
},
|
|
6723
|
+
savingPreferences: savingSettings,
|
|
6724
|
+
creditsLabelId,
|
|
6725
|
+
creditsHintId,
|
|
6726
|
+
rows: accountRows,
|
|
6727
|
+
busy,
|
|
6728
|
+
rescanNote,
|
|
6729
|
+
onRescan: () => {
|
|
6730
|
+
rescanAccounts();
|
|
6731
|
+
},
|
|
6732
|
+
switchingAccount,
|
|
6733
|
+
onSwitchAccount: (accountId) => {
|
|
6734
|
+
switchAccount(accountId);
|
|
6735
|
+
},
|
|
6736
|
+
onClaim: (accountId) => {
|
|
6737
|
+
claimFor(accountId);
|
|
6738
|
+
},
|
|
6739
|
+
onTransferChanged: async () => {
|
|
6740
|
+
const fresh = await refreshUsage(activeRegion);
|
|
6741
|
+
if (fresh !== void 0) setStatusByRegion((current) => ({
|
|
6742
|
+
...current,
|
|
6743
|
+
[activeRegion]: fresh
|
|
6744
|
+
}));
|
|
6745
|
+
},
|
|
6746
|
+
creditsUnavailable: status.status === "signed-in" ? status.creditsUnavailable : void 0,
|
|
6747
|
+
creditsExpiry: status.status === "signed-in" ? status.credits?.expiry : void 0,
|
|
6748
|
+
alternatives: status.status === "signed-in" ? status.alternatives : void 0,
|
|
6749
|
+
onSwitchToAlternative: (accountId) => {
|
|
6750
|
+
switchAccount(accountId);
|
|
6751
|
+
}
|
|
6752
|
+
})]
|
|
6753
|
+
}),
|
|
6284
6754
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6285
6755
|
className: "dsm-trae-panel",
|
|
6286
6756
|
role: "tabpanel",
|
|
@@ -6484,19 +6954,25 @@ window.__ModuleLoader__.load({
|
|
|
6484
6954
|
className: "dsm-trae-context-budget",
|
|
6485
6955
|
"aria-label": t("row.contextBudget"),
|
|
6486
6956
|
title: t("row.contextBudgetHint"),
|
|
6487
|
-
children:
|
|
6957
|
+
children: (() => {
|
|
6958
|
+
const options = contextBudgetOptions(model);
|
|
6488
6959
|
const selectable = model.maxContextWindow !== void 0;
|
|
6489
|
-
const
|
|
6490
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.
|
|
6491
|
-
|
|
6492
|
-
|
|
6493
|
-
|
|
6960
|
+
const current = activeContextBudgets[model.id] ?? model.contextWindow;
|
|
6961
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
|
|
6962
|
+
className: "dsm-trae-context-select",
|
|
6963
|
+
"aria-label": t("row.contextBudget"),
|
|
6964
|
+
title: t("row.contextBudgetHint"),
|
|
6965
|
+
value: current === void 0 ? "" : String(current),
|
|
6494
6966
|
disabled: !selectable || settingsScope?.getSnapshot().writable !== true || saving,
|
|
6495
|
-
onChange: () => {
|
|
6496
|
-
setContextBudget(model.id,
|
|
6497
|
-
}
|
|
6498
|
-
|
|
6499
|
-
|
|
6967
|
+
onChange: (event) => {
|
|
6968
|
+
setContextBudget(model.id, Number(event.currentTarget.value));
|
|
6969
|
+
},
|
|
6970
|
+
children: options.map((option) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
6971
|
+
value: String(option),
|
|
6972
|
+
children: formatCapacity(option, t("row.modelUnknown"))
|
|
6973
|
+
}, option))
|
|
6974
|
+
});
|
|
6975
|
+
})()
|
|
6500
6976
|
})]
|
|
6501
6977
|
})]
|
|
6502
6978
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -6878,11 +7354,7 @@ window.__ModuleLoader__.load({
|
|
|
6878
7354
|
className: "dsm-trae-page-back-caret"
|
|
6879
7355
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("row.pageBack") })]
|
|
6880
7356
|
}),
|
|
6881
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("
|
|
6882
|
-
className: "dsm-trae-page-icon",
|
|
6883
|
-
src: TRAE_PLUGIN_ICON,
|
|
6884
|
-
alt: ""
|
|
6885
|
-
}),
|
|
7357
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(PluginIcon, { className: "dsm-trae-page-icon" }),
|
|
6886
7358
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6887
7359
|
className: "dsm-trae-page-title",
|
|
6888
7360
|
children: title
|
|
@@ -6919,6 +7391,14 @@ window.__ModuleLoader__.load({
|
|
|
6919
7391
|
}) : null;
|
|
6920
7392
|
if (pageSurface) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6921
7393
|
className: "dsm-trae-page",
|
|
7394
|
+
onScroll: (event) => {
|
|
7395
|
+
updateStickyTabs(event.currentTarget);
|
|
7396
|
+
},
|
|
7397
|
+
ref: (page) => {
|
|
7398
|
+
if (page !== null) requestAnimationFrame(() => {
|
|
7399
|
+
updateStickyTabs(page);
|
|
7400
|
+
});
|
|
7401
|
+
},
|
|
6922
7402
|
children: [
|
|
6923
7403
|
pageHead,
|
|
6924
7404
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
@@ -6954,11 +7434,7 @@ window.__ModuleLoader__.load({
|
|
|
6954
7434
|
setCardOpen(!open);
|
|
6955
7435
|
},
|
|
6956
7436
|
children: [
|
|
6957
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("
|
|
6958
|
-
className: "dsm-plugin-card-icon",
|
|
6959
|
-
src: TRAE_PLUGIN_ICON,
|
|
6960
|
-
alt: ""
|
|
6961
|
-
}),
|
|
7437
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(PluginIcon, { className: "dsm-plugin-card-icon" }),
|
|
6962
7438
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
6963
7439
|
className: "dsm-plugin-card-head",
|
|
6964
7440
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
@@ -7993,41 +8469,178 @@ window.__ModuleLoader__.load({
|
|
|
7993
8469
|
/** The shipped slot whose store seat is the settings shell's state handle. */
|
|
7994
8470
|
const SETTINGS_SLOT = "sidebar.settings";
|
|
7995
8471
|
/**
|
|
7996
|
-
*
|
|
7997
|
-
* plugin's section.
|
|
8472
|
+
* The sidebar's settings trigger: dialog semantics plus an expanded state.
|
|
7998
8473
|
*
|
|
7999
|
-
*
|
|
8000
|
-
*
|
|
8001
|
-
*
|
|
8002
|
-
*
|
|
8003
|
-
*
|
|
8474
|
+
* Both attributes are load-bearing. `aria-haspopup="dialog"` identifies it as
|
|
8475
|
+
* the thing that opens the panel; `aria-expanded` is how route 2 tells an open
|
|
8476
|
+
* panel from a closed one WITHOUT clicking, because clicking a trigger that is
|
|
8477
|
+
* already expanded CLOSES the dialog — a jump that would read as the settings
|
|
8478
|
+
* window flickering shut.
|
|
8479
|
+
*/
|
|
8480
|
+
const SETTINGS_TRIGGER_SELECTOR = "button[aria-haspopup=\"dialog\"][aria-expanded]";
|
|
8481
|
+
/**
|
|
8482
|
+
* Budget for "panel mounted + nav row rendered".
|
|
8483
|
+
*
|
|
8484
|
+
* The panel mounts synchronously on the click, but the nav rows' labels wait
|
|
8485
|
+
* for a locale snapshot, so a same-frame query is often one tick too early.
|
|
8486
|
+
* Five attempts over ~300ms covers one layout pass while staying under the
|
|
8487
|
+
* threshold where a user starts to think the press did nothing.
|
|
8488
|
+
*/
|
|
8489
|
+
const RETRY_DELAYS_MS = [
|
|
8490
|
+
0,
|
|
8491
|
+
60,
|
|
8492
|
+
70,
|
|
8493
|
+
80,
|
|
8494
|
+
90
|
|
8495
|
+
];
|
|
8496
|
+
function defaultSchedule(run, ms) {
|
|
8497
|
+
try {
|
|
8498
|
+
window.setTimeout(run, ms);
|
|
8499
|
+
} catch {
|
|
8500
|
+
run();
|
|
8501
|
+
}
|
|
8502
|
+
}
|
|
8503
|
+
/**
|
|
8504
|
+
* Find the settings nav row whose label is this plugin's.
|
|
8505
|
+
*
|
|
8506
|
+
* Trimmed equality, not `includes`: 「dsh-connect-trae」 is a SUBSTRING of
|
|
8507
|
+
* nothing here, but 「模型」 is a substring of 「模型与预设」 on a differently
|
|
8508
|
+
* worded shell, and a loose match would click the wrong row.
|
|
8509
|
+
*/
|
|
8510
|
+
function findSectionRow(scope, label) {
|
|
8511
|
+
const want = label.trim();
|
|
8512
|
+
if (want === "") return void 0;
|
|
8513
|
+
return Array.from(scope.querySelectorAll("button")).find((button) => (button.textContent ?? "").trim() === want);
|
|
8514
|
+
}
|
|
8515
|
+
/**
|
|
8516
|
+
* Route 1: open this plugin's section through the shell's store seat.
|
|
8517
|
+
*
|
|
8518
|
+
* @returns `'opened'` when the dialog is on the right section, `'shell'` when
|
|
8519
|
+
* the dialog opened but is NOT preselected (route 2 can still click the row),
|
|
8520
|
+
* and `undefined` when the seat is absent or unusable.
|
|
8004
8521
|
*/
|
|
8005
|
-
function
|
|
8006
|
-
|
|
8007
|
-
|
|
8522
|
+
function openThroughStoreSeat(get, sectionId) {
|
|
8523
|
+
let slots;
|
|
8524
|
+
try {
|
|
8525
|
+
slots = get("slots");
|
|
8526
|
+
} catch {
|
|
8527
|
+
return;
|
|
8528
|
+
}
|
|
8529
|
+
if (slots === void 0 || typeof slots.entries !== "function") return void 0;
|
|
8008
8530
|
let seat;
|
|
8009
8531
|
try {
|
|
8010
8532
|
seat = slots.entries(SETTINGS_SLOT)[0]?.store;
|
|
8011
8533
|
} catch {
|
|
8012
|
-
return
|
|
8534
|
+
return;
|
|
8013
8535
|
}
|
|
8014
|
-
if (seat === null || typeof seat !== "object") return
|
|
8536
|
+
if (seat === null || typeof seat !== "object") return void 0;
|
|
8015
8537
|
const handle = seat;
|
|
8016
|
-
if (typeof handle.create !== "function") return
|
|
8538
|
+
if (typeof handle.create !== "function") return void 0;
|
|
8017
8539
|
try {
|
|
8018
8540
|
const instance = handle.create();
|
|
8019
8541
|
const openSection = instance?.actions?.openSection;
|
|
8020
8542
|
if (typeof openSection === "function") {
|
|
8021
|
-
openSection(
|
|
8022
|
-
return
|
|
8543
|
+
openSection(sectionId);
|
|
8544
|
+
return "opened";
|
|
8023
8545
|
}
|
|
8024
8546
|
const open = instance?.actions?.open;
|
|
8025
8547
|
if (typeof open === "function") {
|
|
8026
8548
|
open();
|
|
8027
|
-
return
|
|
8549
|
+
return "shell";
|
|
8028
8550
|
}
|
|
8029
8551
|
} catch {}
|
|
8030
|
-
|
|
8552
|
+
}
|
|
8553
|
+
/**
|
|
8554
|
+
* Open this plugin's settings page — the wide Settings dialog, on THIS
|
|
8555
|
+
* plugin's section.
|
|
8556
|
+
*
|
|
8557
|
+
* ## Two routes, best first (the shape borrowed from dsh-connect-workbuddy 5.20.4)
|
|
8558
|
+
*
|
|
8559
|
+
* 1. **The shell's store seat** — one call, exact, no timing:
|
|
8560
|
+
* `slots.entries(SETTINGS_SLOT)[0].store.create().actions.openSection(id)`.
|
|
8561
|
+
* 2. **Driving the chrome** — click the sidebar's settings trigger, wait for the
|
|
8562
|
+
* panel, then click this plugin's nav row by its label.
|
|
8563
|
+
*
|
|
8564
|
+
* Route 1 is strictly better where it exists: `openSection(id)` sets `activeId`
|
|
8565
|
+
* AND `open` in one action, so there is no window in which the dialog is open
|
|
8566
|
+
* on the wrong section, no retry loop, and no dependency on the nav row's
|
|
8567
|
+
* localized text. Route 2 is kept because the host range this plugin declares
|
|
8568
|
+
* spans shell lines that may predate the seat; deleting it would trade a
|
|
8569
|
+
* working fallback for nothing.
|
|
8570
|
+
*
|
|
8571
|
+
* ## Why both routes are needed even now
|
|
8572
|
+
*
|
|
8573
|
+
* A seat that carries `open()` but not `openSection()` is a real shell shape
|
|
8574
|
+
* (the store gained `openSection` after `open`). Returning `true` on that seat —
|
|
8575
|
+
* which 4.9.x did — claimed success while leaving the user on the shell's
|
|
8576
|
+
* default section, so the button appeared to do something other than what its
|
|
8577
|
+
* label promised. Handing back `'shell'` and continuing to route 2 is what
|
|
8578
|
+
* makes the button land on the page it names on EVERY shell.
|
|
8579
|
+
*
|
|
8580
|
+
* ## Why the probe happens per PRESS, not during `apply`
|
|
8581
|
+
*
|
|
8582
|
+
* The seat belongs to ANOTHER bundle whose apply order is not ours to assume.
|
|
8583
|
+
* Probing once during `apply()` would capture `undefined` on a host whose
|
|
8584
|
+
* settings bundle applied later, leaving the button dead for the whole session.
|
|
8585
|
+
* `entries()` answers `[]` for an undeclared slot, so a per-press probe is
|
|
8586
|
+
* stateless and always current — the same reason the caller passes `softGet`.
|
|
8587
|
+
*
|
|
8588
|
+
* ## Why it never throws
|
|
8589
|
+
*
|
|
8590
|
+
* Every path runs from a RENDER path (a click handler in the credits popover).
|
|
8591
|
+
* A throw here would take out the whole readout rather than one button, so each
|
|
8592
|
+
* stage swallows its own failure and the jump degrades to a silent no-op when
|
|
8593
|
+
* the shell has a different shape.
|
|
8594
|
+
*
|
|
8595
|
+
* @param get - the entry's soft service probe (`ctx.get`), which returns
|
|
8596
|
+
* `undefined` for an absent service instead of throwing. Called HERE, on every
|
|
8597
|
+
* invocation, so a service that appears after `apply` is still found.
|
|
8598
|
+
* @param options - label thunk (required for route 2) plus test seams.
|
|
8599
|
+
* @returns whether a route was taken. `false` means `onGiveUp` already ran or
|
|
8600
|
+
* there was nothing to fall back to.
|
|
8601
|
+
*/
|
|
8602
|
+
function openPluginSettingsPage(get, options) {
|
|
8603
|
+
const { doc = document, label } = options;
|
|
8604
|
+
const schedule = options.schedule ?? defaultSchedule;
|
|
8605
|
+
let seatResult;
|
|
8606
|
+
try {
|
|
8607
|
+
seatResult = openThroughStoreSeat(get, TRAE_SETTINGS_ID);
|
|
8608
|
+
} catch {
|
|
8609
|
+
seatResult = void 0;
|
|
8610
|
+
}
|
|
8611
|
+
if (seatResult === "opened") return true;
|
|
8612
|
+
try {
|
|
8613
|
+
if (doc.querySelector("[data-shortcut-modal=\"settings\"]") === null) {
|
|
8614
|
+
const collapsed = Array.from(doc.querySelectorAll(SETTINGS_TRIGGER_SELECTOR)).find((button) => button.getAttribute("aria-expanded") !== "true");
|
|
8615
|
+
if (collapsed === void 0) {
|
|
8616
|
+
try {
|
|
8617
|
+
options.onGiveUp?.();
|
|
8618
|
+
} catch {}
|
|
8619
|
+
return false;
|
|
8620
|
+
}
|
|
8621
|
+
collapsed.click();
|
|
8622
|
+
}
|
|
8623
|
+
let clicked = false;
|
|
8624
|
+
let remaining = RETRY_DELAYS_MS.length;
|
|
8625
|
+
for (const delay of RETRY_DELAYS_MS) schedule(() => {
|
|
8626
|
+
if (clicked) return;
|
|
8627
|
+
remaining -= 1;
|
|
8628
|
+
try {
|
|
8629
|
+
const row = findSectionRow(doc.querySelector("[data-shortcut-modal=\"settings\"]") ?? doc, label());
|
|
8630
|
+
if (row !== void 0) {
|
|
8631
|
+
clicked = true;
|
|
8632
|
+
row.click();
|
|
8633
|
+
return;
|
|
8634
|
+
}
|
|
8635
|
+
} catch {}
|
|
8636
|
+
if (remaining === 0) try {
|
|
8637
|
+
options.onGiveUp?.();
|
|
8638
|
+
} catch {}
|
|
8639
|
+
}, delay);
|
|
8640
|
+
return true;
|
|
8641
|
+
} catch {
|
|
8642
|
+
return false;
|
|
8643
|
+
}
|
|
8031
8644
|
}
|
|
8032
8645
|
//#endregion
|
|
8033
8646
|
//#region src/client/locales.ts
|
|
@@ -8037,46 +8650,64 @@ window.__ModuleLoader__.load({
|
|
|
8037
8650
|
* two plugins share one external-presentation language.
|
|
8038
8651
|
*/
|
|
8039
8652
|
const en = {
|
|
8040
|
-
"row.
|
|
8041
|
-
"row.
|
|
8653
|
+
"row.tabCredentialHint": "Domestic and enterprise providers share Trae CN credentials and save account bindings separately.",
|
|
8654
|
+
"row.tabFreeQuotaWarn": "Free models can still encounter upstream request limits or busy responses.",
|
|
8655
|
+
"row.poolFailoverHint": "Trae also tries another account after server failures. Invalid requests and model permission refusals are reported directly.",
|
|
8656
|
+
"row.iconStyleLabel": "Icon style",
|
|
8657
|
+
"row.iconStyleHint": "Updates the sidebar and page icons immediately. Saved separately for this plugin in this browser.",
|
|
8658
|
+
"row.iconStyleClaude": "Claude style",
|
|
8659
|
+
"row.iconStyleOriginal": "Default icon",
|
|
8660
|
+
"row.iconStyleSaveFailed": "The browser could not save the icon preference. Please check site storage permissions.",
|
|
8661
|
+
"row.poolAutoCheckinDeviceHint": "Trae limits daily rewards per device, so some members may not receive a reward.",
|
|
8662
|
+
"row.checkinStatusError": "Could not read today's check-in status: {message}",
|
|
8663
|
+
"row.poolAutoCheckinDeviceDone": "Today: this device has reached its daily reward limit.",
|
|
8664
|
+
"row.poolAutoCheckinRetry": "Today: {count} accounts checked in. Failed requests will retry automatically.",
|
|
8665
|
+
"row.poolAutoCheckinProgress": "Today: {count} accounts checked in.",
|
|
8666
|
+
"row.poolAutoCheckinWaiting": "Waiting for the next background check.",
|
|
8667
|
+
"row.poolAutoCheckin": "Check in automatically each day",
|
|
8668
|
+
"row.poolAutoCheckinHint": "Enable and save to claim daily rewards for selected domestic personal accounts while DSH is running. After a restart, the plugin checks today's progress before processing remaining accounts. Failed attempts retry automatically.",
|
|
8669
|
+
"row.title": "Trae credits & models",
|
|
8670
|
+
"row.desc": "Use Trae domestic, enterprise and global models in DSH. Manage accounts, select models, view credits and claim daily check-in rewards. Refreshing the model catalog also updates credit multipliers.",
|
|
8042
8671
|
"row.expand": "Expand",
|
|
8043
8672
|
"row.collapse": "Collapse",
|
|
8044
8673
|
"row.tabCn": "Domestic",
|
|
8045
8674
|
"row.tabEnterprise": "Enterprise",
|
|
8046
8675
|
"row.tabAi": "Global",
|
|
8047
|
-
"row.tabHint": "
|
|
8676
|
+
"row.tabHint": "Domestic, enterprise and global versions can be enabled together. Use the version tabs above to view and manage each version's accounts, credits and models.",
|
|
8048
8677
|
"row.tabEnterpriseHint": "Enterprise bills the tenant pool of the same Trae CN account instead of the personal one. It never falls back: a refusal is reported as an error rather than quietly spending personal credits.",
|
|
8049
|
-
"row.tabSwitchHint": "
|
|
8678
|
+
"row.tabSwitchHint": "Uncheck to switch this provider off. Its models disappear from the DSH model picker; your account, credits, and model settings are kept and return when you check it again.",
|
|
8050
8679
|
"row.tabSwitchAria": "Offer the {region} provider to DSH",
|
|
8051
|
-
"row.tabOffNotice": "This provider is off
|
|
8680
|
+
"row.tabOffNotice": "This provider is switched off. None of its models are offered to DSH. Your account, credits, and model settings are kept. Check the box above the tab to bring it back.",
|
|
8052
8681
|
"row.panelAria": "Card sections",
|
|
8053
8682
|
"row.panelAccounts": "Account",
|
|
8683
|
+
"row.panelCapabilities": "Capabilities",
|
|
8684
|
+
"row.panelCapabilitiesHint": "What the plugin may do on your behalf. These switches take effect on the click — there is no Save button for them.",
|
|
8054
8685
|
"row.panelModels": "Models",
|
|
8055
8686
|
"row.panelDiag": "Diagnostics",
|
|
8056
|
-
"row.diagRegion": "
|
|
8687
|
+
"row.diagRegion": "Region",
|
|
8057
8688
|
"row.diagProvider": "Provider id",
|
|
8058
8689
|
"row.diagAccount": "Serving account",
|
|
8059
|
-
"row.diagToken": "
|
|
8690
|
+
"row.diagToken": "Sign-in expires",
|
|
8060
8691
|
"row.diagRefresh": "Re-sign-in deadline",
|
|
8061
8692
|
"row.diagRefreshNone": "this credential carries none",
|
|
8062
|
-
"row.diagCatalog": "Models in catalog",
|
|
8063
|
-
"row.diagEnabled": "
|
|
8693
|
+
"row.diagCatalog": "Models in the catalog",
|
|
8694
|
+
"row.diagEnabled": "Enabled models",
|
|
8064
8695
|
"row.diagPool": "Account pool",
|
|
8065
|
-
"row.diagPoolOn": "on · {count}
|
|
8696
|
+
"row.diagPoolOn": "on · {count} accounts",
|
|
8066
8697
|
"row.diagPoolOff": "off",
|
|
8067
8698
|
"row.diagCheckin": "Daily check-in",
|
|
8068
8699
|
"row.diagCheckinOn": "supported",
|
|
8069
8700
|
"row.diagCheckinOff": "not offered here",
|
|
8070
8701
|
"row.diagRaw": "Raw chat channel",
|
|
8071
8702
|
"row.diagRawOff": "not checked",
|
|
8072
|
-
"row.diagFailures": "Last
|
|
8073
|
-
"row.diagNoFailures": "
|
|
8703
|
+
"row.diagFailures": "Last failure",
|
|
8704
|
+
"row.diagNoFailures": "Nothing reported.",
|
|
8074
8705
|
"row.diagQuarantine": "Quarantined copies",
|
|
8075
8706
|
"row.diagQuarantineNone": "none",
|
|
8076
|
-
"row.diagHint": "
|
|
8707
|
+
"row.diagHint": "These values come from this panel's latest refresh. Remove account identifiers and personal information in local paths before sharing a report.",
|
|
8077
8708
|
"row.settingsWriteFailed": "The setting was not saved: {message}",
|
|
8078
8709
|
"row.signedOut": "Not signed in",
|
|
8079
|
-
"row.signedOutHint": "Sign in
|
|
8710
|
+
"row.signedOutHint": "Sign in to the Trae desktop app, then click Detect accounts again to save a plugin-owned credential copy.",
|
|
8080
8711
|
"row.unsupportedRegionTitle": "US region is not supported yet",
|
|
8081
8712
|
"row.unsupportedRegionHint": "A Trae account on this machine belongs to the United States region (userRegion \"US\" / host *.traeapi.us). This build does not serve that region, so the account is NOT used and no request is sent to the Singapore gateway — signing in again changes nothing. Use a CN or Singapore account (or the Trae CN build) in this panel.",
|
|
8082
8713
|
"row.diagUnsupportedRegion": "Unsupported region",
|
|
@@ -8084,7 +8715,7 @@ window.__ModuleLoader__.load({
|
|
|
8084
8715
|
"row.searchedHint": "No sign-in was found. These locations were probed; if your Trae stores its login elsewhere, please report the path.",
|
|
8085
8716
|
"row.searchedMore": "Show {count} more",
|
|
8086
8717
|
"row.quarantineTitle": "Quarantined credential copies",
|
|
8087
|
-
"row.quarantineHint": "
|
|
8718
|
+
"row.quarantineHint": "The plugin could not read a credential copy and renamed the file to preserve it. Inspect that file if you need to recover accounts. Delete it only after confirming that it is no longer needed.",
|
|
8088
8719
|
"row.quarantineAccounts": "{count} account(s)",
|
|
8089
8720
|
"row.quarantineAccountsUnknown": "account count unreadable",
|
|
8090
8721
|
"row.quarantineBytes": "{bytes} bytes",
|
|
@@ -8094,7 +8725,7 @@ window.__ModuleLoader__.load({
|
|
|
8094
8725
|
"row.sourceDesktop": "desktop app",
|
|
8095
8726
|
"row.sourceCli": "Trae CLI",
|
|
8096
8727
|
"row.signedIn": "Signed in: {accountName}",
|
|
8097
|
-
"row.tokenExpiry": "Access token expires {expiresAt}
|
|
8728
|
+
"row.tokenExpiry": "Access token expires at {expiresAt}; the plugin will attempt to renew it automatically",
|
|
8098
8729
|
"row.refreshTokenExpiring": "Sign in to Trae again by {expiresAt} ({days} day(s) left) — automatic renewal stops after that.",
|
|
8099
8730
|
"row.refreshTokenLapsed": "Automatic renewal has stopped: the Trae sign-in expired {expiresAt}. Sign in to Trae again to restore it.",
|
|
8100
8731
|
"row.requestFailed": "Request failed",
|
|
@@ -8130,26 +8761,26 @@ window.__ModuleLoader__.load({
|
|
|
8130
8761
|
"row.refreshCredits": "Refresh usage",
|
|
8131
8762
|
"row.refreshing": "Refreshing…",
|
|
8132
8763
|
"row.accountsTitle": "Trae account",
|
|
8133
|
-
"row.accountsHint": "
|
|
8134
|
-
"row.transferTitle": "
|
|
8135
|
-
"row.transferExport": "Export
|
|
8136
|
-
"row.transferImport": "Import
|
|
8764
|
+
"row.accountsHint": "On refresh, the plugin saves copies of detected Trae credentials. Refresh after signing in to a new account, before another sign-in replaces credentials that have not yet been copied.",
|
|
8765
|
+
"row.transferTitle": "Export / import accounts",
|
|
8766
|
+
"row.transferExport": "Export accounts",
|
|
8767
|
+
"row.transferImport": "Import accounts",
|
|
8137
8768
|
"row.transferCancel": "Cancel",
|
|
8138
8769
|
"row.transferSelectAll": "Select all",
|
|
8139
|
-
"row.transferExportPick": "Choose
|
|
8140
|
-
"row.transferExportConfirm": "Export {count}",
|
|
8141
|
-
"row.transferExported": "Exported {count} account
|
|
8142
|
-
"row.transferExporting": "
|
|
8770
|
+
"row.transferExportPick": "Choose the accounts to export ({total} available):",
|
|
8771
|
+
"row.transferExportConfirm": "Export {count} account(s)",
|
|
8772
|
+
"row.transferExported": "Exported {count} account(s) to {fileName}.",
|
|
8773
|
+
"row.transferExporting": "Exporting…",
|
|
8143
8774
|
"row.transferImportPick": "This file holds {total} record(s). Ticked records are added as plugin-owned copies; the Trae app is not touched.",
|
|
8144
|
-
"row.transferImportConfirm": "Import {count}",
|
|
8775
|
+
"row.transferImportConfirm": "Import {count} account(s)",
|
|
8145
8776
|
"row.transferImported": "Imported {imported} account copy/copies, skipped {skipped}.",
|
|
8146
8777
|
"row.transferImporting": "Importing…",
|
|
8147
8778
|
"row.transferReading": "Reading the file…",
|
|
8148
|
-
"row.transferHint": "
|
|
8779
|
+
"row.transferHint": "Export accounts to a JSON file or import accounts from one. The file contains login credentials; restrict access to it. Accounts from other regions are skipped during import.",
|
|
8149
8780
|
"row.transferError": "Import/export failed: {message}",
|
|
8150
8781
|
"row.transferVeilHint": "The account list refreshes when this finishes.",
|
|
8151
8782
|
"row.transferUnnamed": "Unnamed account",
|
|
8152
|
-
"row.transferNoToken": "no token
|
|
8783
|
+
"row.transferNoToken": "no token in this record",
|
|
8153
8784
|
"row.accountsRescan": "Detect accounts again",
|
|
8154
8785
|
"row.accountsScanning": "Detecting…",
|
|
8155
8786
|
"row.accountsLoading": "Loading your accounts…",
|
|
@@ -8162,7 +8793,7 @@ window.__ModuleLoader__.load({
|
|
|
8162
8793
|
"row.accountColumnCheckin": "Check-in",
|
|
8163
8794
|
"row.accountBalance": "{credits} credits",
|
|
8164
8795
|
"row.balanceConsoleOnly": "In the enterprise console",
|
|
8165
|
-
"row.enterpriseCreditsNotice": "
|
|
8796
|
+
"row.enterpriseCreditsNotice": "The plugin cannot currently read the tenant balance. Check console.enterprise.trae.cn. Personal credits are omitted here to avoid presenting them as enterprise quota.",
|
|
8166
8797
|
"row.sourceDsh": "plugin copy",
|
|
8167
8798
|
"row.modelsTitle": "Models",
|
|
8168
8799
|
"row.modelsSummary": "{count} enabled",
|
|
@@ -8176,7 +8807,7 @@ window.__ModuleLoader__.load({
|
|
|
8176
8807
|
"row.modelsViewLabel": "Model scope",
|
|
8177
8808
|
"row.modelsViewCommon": "Common channels · {count}",
|
|
8178
8809
|
"row.modelsViewAll": "All · {count}",
|
|
8179
|
-
"row.modelsViewCommonHint": "Models
|
|
8810
|
+
"row.modelsViewCommonHint": "Models offered through solo_work_remote or solo_work_lite.",
|
|
8180
8811
|
"row.modelsViewAllHint": "Also includes models only offered by a specialist channel: solo_coder, chat_v3, solo_agent_remote.",
|
|
8181
8812
|
"row.modelsViewShowAll": "Show all",
|
|
8182
8813
|
"row.modelsSearchOutsideView": "No match for 「{query}」 on the common channels; the full catalog has {count}.",
|
|
@@ -8190,20 +8821,20 @@ window.__ModuleLoader__.load({
|
|
|
8190
8821
|
"row.modelsTestEnabled": "Test enabled models",
|
|
8191
8822
|
"row.modelsTestAll": "Test all models",
|
|
8192
8823
|
"row.modelsTesting": "Testing {done}/{total}…",
|
|
8193
|
-
"row.modelsTestHint": "
|
|
8194
|
-
"row.modelsTestAllHint": "
|
|
8824
|
+
"row.modelsTestHint": "Send a minimal test request to each enabled model and show its result. Each request is billed at that model's rate.",
|
|
8825
|
+
"row.modelsTestAllHint": "Test every model in this panel's catalog, including disabled models. Each request is billed at that model's rate.",
|
|
8195
8826
|
"row.showPointsInMainUi": "Show credits in the composer row",
|
|
8196
|
-
"row.showPointsInMainUiHint": "
|
|
8827
|
+
"row.showPointsInMainUiHint": "Show a clickable Trae readout at the selected position, including when another provider's model is selected. Click it to view account details.",
|
|
8197
8828
|
"row.drawImage": "Let the model draw images (trae_draw_image)",
|
|
8198
8829
|
"row.drawImageHint": "Adds a trae_draw_image tool to this panel: the model can generate one image when you ask for one, at this account's real credit cost (measured ~8.8 for 1920x1920 on Trae CN). Off by default — while this is unticked the tool does not exist, so the model cannot spend credits on its own.",
|
|
8199
8830
|
"row.drawImageHintEnterprise": "Not available on the enterprise panel: that path bills through the tenant gateway and has not been verified.",
|
|
8200
|
-
"row.drawImageHintAi": "
|
|
8201
|
-
"row.showPointsInMainUiHintAi": "
|
|
8831
|
+
"row.drawImageHintAi": "Image generation and billing have not been verified for the global provider, so the tool is unavailable here. Use the domestic panel for image generation.",
|
|
8832
|
+
"row.showPointsInMainUiHintAi": "Show the global plan at the selected position, including when a model from another provider is selected.",
|
|
8202
8833
|
"row.creditPositionLabel": "position",
|
|
8203
8834
|
"row.creditPositionComposer": "composer toolbar",
|
|
8204
8835
|
"row.creditPositionStats": "below the input box",
|
|
8205
8836
|
"row.creditPositionAria": "Credit readout position for {region}",
|
|
8206
|
-
"row.creditPositionHint": "
|
|
8837
|
+
"row.creditPositionHint": "The default position is on the model picker row. If another connector occupies the same position, the readout loaded later moves left automatically. Choose below the input box to show it beside the round, step and token statistics.",
|
|
8207
8838
|
"composer.switchTo": "Switch to {account}",
|
|
8208
8839
|
"composer.noAccounts": "No account in this region",
|
|
8209
8840
|
"composer.panelTitle": "Trae credits",
|
|
@@ -8245,11 +8876,11 @@ window.__ModuleLoader__.load({
|
|
|
8245
8876
|
"row.settingsDirty": "Unsaved changes",
|
|
8246
8877
|
"row.modelsTestEmpty": "Enable at least one model first.",
|
|
8247
8878
|
"row.contextAllMid": "Switch all to 500K",
|
|
8248
|
-
"row.contextAllMidHint": "
|
|
8879
|
+
"row.contextAllMidHint": "Set the DSH context budget to 500K for models in this panel with a Max window of at least 500K. Other models keep their current values. Click Save to apply.",
|
|
8249
8880
|
"row.contextAllMax": "Switch all to Max",
|
|
8250
|
-
"row.contextAllMaxHint": "
|
|
8881
|
+
"row.contextAllMaxHint": "Set each model with a Max window to that maximum DSH context budget. Other models keep their current values. Click Save to apply.",
|
|
8251
8882
|
"row.contextAllDefault": "Restore default context",
|
|
8252
|
-
"row.contextAllDefaultHint": "
|
|
8883
|
+
"row.contextAllDefaultHint": "Clear this panel's custom context budgets and use the Trae catalog defaults. Click Save to apply.",
|
|
8253
8884
|
"row.modelsTestError": "Test failed: {message}",
|
|
8254
8885
|
"row.modelsTestDone": "{available} of {total} answered.",
|
|
8255
8886
|
"row.probeAvailable": "works",
|
|
@@ -8284,21 +8915,21 @@ window.__ModuleLoader__.load({
|
|
|
8284
8915
|
"row.modelCapabilityPending": "Image input follows Trae's own multimodal flag, plus anything you tick yourself.",
|
|
8285
8916
|
"row.poolTitle": "Account pool",
|
|
8286
8917
|
"row.poolEnabled": "Enable the account pool",
|
|
8287
|
-
"row.poolEnabledHint": "
|
|
8918
|
+
"row.poolEnabledHint": "When enabled, the plugin selects accounts automatically and tries another account after account rate limits, depleted credits or account failures. When disabled, select the account to use from the account list.",
|
|
8288
8919
|
"row.poolCurrentHeader": "Billing now: {account}",
|
|
8289
8920
|
"row.poolModeAuto": "pool picks",
|
|
8290
8921
|
"row.poolModeManual": "you pick",
|
|
8291
8922
|
"row.poolMember": "in pool",
|
|
8292
|
-
"row.poolNotMember": "
|
|
8293
|
-
"row.poolBusyHint": "
|
|
8294
|
-
"row.poolTestAll": "Test
|
|
8923
|
+
"row.poolNotMember": "Not in pool",
|
|
8924
|
+
"row.poolBusyHint": "Running one account at a time…",
|
|
8925
|
+
"row.poolTestAll": "Test selected",
|
|
8295
8926
|
"row.poolTesting": "Testing…",
|
|
8296
|
-
"row.poolOffNotice": "The pool is off
|
|
8297
|
-
"row.poolNoCandidate": "No
|
|
8927
|
+
"row.poolOffNotice": "The pool is off and requests use the bound account. Enable the switch above and save to let the pool select accounts.",
|
|
8928
|
+
"row.poolNoCandidate": "No account in this pool can be used right now.",
|
|
8298
8929
|
"row.poolNoCandidateEmpty": "No pool members are selected yet.",
|
|
8299
|
-
"row.poolNoCandidateEmptyHint": "
|
|
8930
|
+
"row.poolNoCandidateEmptyHint": "Select accounts below and save the pool settings to add them to the pool.",
|
|
8300
8931
|
"row.poolNoCandidateUnusable": "Every selected member is unavailable right now.",
|
|
8301
|
-
"row.poolNoCandidateHint": "
|
|
8932
|
+
"row.poolNoCandidateHint": "Requests will try the saved account binding while the pool has no usable member. Member status: ",
|
|
8302
8933
|
"row.poolServingOutside": "{account} is billing right now but is not in the pool — until a member becomes available, requests fall back to the saved selection.",
|
|
8303
8934
|
"row.poolMembersTitle": "Accounts in this pool",
|
|
8304
8935
|
"row.poolRescan": "Re-detect accounts",
|
|
@@ -8309,59 +8940,59 @@ window.__ModuleLoader__.load({
|
|
|
8309
8940
|
"row.poolSettingsNote": "Preferences below take effect when you save; test results are written by the plugin and are not affected by that button.",
|
|
8310
8941
|
"row.poolSelectedCount": "Selected {count} / {total}",
|
|
8311
8942
|
"row.poolNoCopyTag": "no copy here",
|
|
8312
|
-
"row.poolCopyFile": "
|
|
8313
|
-
"row.poolNoCopyTestHint": "
|
|
8314
|
-
"row.poolSelectAll": "
|
|
8315
|
-
"row.poolSelectNone": "
|
|
8943
|
+
"row.poolCopyFile": "The plugin keeps {count} credential copies in {path}. Refreshing creates copies for newly detected logins and retains existing copies.",
|
|
8944
|
+
"row.poolNoCopyTestHint": "The plugin cannot read credentials for this account. Sign in again in Trae and detect accounts, or remove it from the pool.",
|
|
8945
|
+
"row.poolSelectAll": "Select all",
|
|
8946
|
+
"row.poolSelectNone": "Clear all",
|
|
8316
8947
|
"row.poolColumnAccount": "Account",
|
|
8317
8948
|
"row.poolColumnCredits": "Credits",
|
|
8318
8949
|
"row.poolColumnProbe": "Status",
|
|
8319
8950
|
"row.poolColumnCheckin": "Check-in",
|
|
8320
|
-
"row.poolGeneralLabel": "
|
|
8321
|
-
"row.poolWorkHint": "
|
|
8951
|
+
"row.poolGeneralLabel": "Credits",
|
|
8952
|
+
"row.poolWorkHint": "DSH chat uses the credits balance. Work credits cannot be used for these requests.",
|
|
8322
8953
|
"row.poolCreditNone": "—",
|
|
8323
|
-
"row.poolTestedAt": "
|
|
8324
|
-
"row.poolNeverTested": "
|
|
8325
|
-
"row.poolRetryAt": "
|
|
8954
|
+
"row.poolTestedAt": "Tested {at}",
|
|
8955
|
+
"row.poolNeverTested": "Untested",
|
|
8956
|
+
"row.poolRetryAt": "Retry after {at}",
|
|
8326
8957
|
"row.poolRetryUnknown": "retry time unknown",
|
|
8327
|
-
"row.poolTargetCurrentPreferred": "Current: your choice
|
|
8328
|
-
"row.poolTargetCurrentFree": "Current: free model
|
|
8329
|
-
"row.poolTargetStale": "
|
|
8958
|
+
"row.poolTargetCurrentPreferred": "Current: {model} (your choice).",
|
|
8959
|
+
"row.poolTargetCurrentFree": "Current: {model} (auto-picked free model).",
|
|
8960
|
+
"row.poolTargetStale": "The target model you saved is no longer offered: {model}",
|
|
8330
8961
|
"row.poolTargetStaleOption": "{model} (no longer offered)",
|
|
8331
|
-
"row.poolTargetStaleClear": "
|
|
8962
|
+
"row.poolTargetStaleClear": "Switch back to automatic",
|
|
8332
8963
|
"row.poolTargetNone": "No free model available for this panel",
|
|
8333
|
-
"row.poolTargetNoneHint": "
|
|
8334
|
-
"row.poolActionNoteTestNone": "No free model
|
|
8335
|
-
"row.poolActionNoteNoMembers": "
|
|
8336
|
-
"row.poolTargetAutoOption": "
|
|
8337
|
-
"row.poolTargetLabel": "
|
|
8338
|
-
"row.poolTargetHint": "
|
|
8339
|
-
"row.poolProbeSizeLabel": "
|
|
8340
|
-
"row.poolProbeSizeHint": "
|
|
8964
|
+
"row.poolTargetNoneHint": "Automatic selection uses free models only. Refresh the catalog or select a test model manually. Paid models spend the tested account's credits.",
|
|
8965
|
+
"row.poolActionNoteTestNone": "No free model was found in this panel. Select a target model before testing accounts.",
|
|
8966
|
+
"row.poolActionNoteNoMembers": "Select accounts to test and save the pool settings.",
|
|
8967
|
+
"row.poolTargetAutoOption": "Auto-select a free model",
|
|
8968
|
+
"row.poolTargetLabel": "Account test model",
|
|
8969
|
+
"row.poolTargetHint": "Batch tests use this model. Auto selects this region's free model with the largest context window. Selecting a paid model spends credits from every account tested.",
|
|
8970
|
+
"row.poolProbeSizeLabel": "Test input size",
|
|
8971
|
+
"row.poolProbeSizeHint": "Choose an input length close to your conversations. A short test can succeed while a longer request encounters account limits. Longer tests cost more when the model charges for input.",
|
|
8341
8972
|
"row.poolProbeSizeDefault": "Minimal (default)",
|
|
8342
8973
|
"row.poolProbeSizeOption": "{wan}0k tokens",
|
|
8343
8974
|
"row.poolSettingsTitle": "More settings",
|
|
8344
8975
|
"row.poolMoreRulesTitle": "Account copies & saving rules",
|
|
8345
|
-
"row.poolManualAccountLabel": "
|
|
8976
|
+
"row.poolManualAccountLabel": "Account in use",
|
|
8346
8977
|
"row.poolManualAccountNone": "No account in effect",
|
|
8347
|
-
"row.poolDirty": "
|
|
8978
|
+
"row.poolDirty": "● Unsaved changes",
|
|
8348
8979
|
"row.poolSaved": "Save",
|
|
8349
8980
|
"row.poolSaving": "Saving…",
|
|
8350
|
-
"row.poolDiscard": "Discard",
|
|
8981
|
+
"row.poolDiscard": "Discard changes",
|
|
8351
8982
|
"row.poolSaveFailed": "Save failed: {message}",
|
|
8352
8983
|
"row.poolGhostMembers": "{count} saved member(s) no longer resolve to a local sign-in: {names}",
|
|
8353
|
-
"row.poolUnsavedMembers": "
|
|
8984
|
+
"row.poolUnsavedMembers": "Selection changed. Save to apply.",
|
|
8354
8985
|
"row.poolRowTest": "Test",
|
|
8355
8986
|
"row.poolLogTitle": "Activity",
|
|
8356
8987
|
"row.poolLogClear": "Clear",
|
|
8357
8988
|
"row.poolLogEmpty": "No pool activity yet.",
|
|
8358
|
-
"row.poolLogTestStart": "
|
|
8359
|
-
"row.poolLogTestRow": "{accountName}: {outcome}
|
|
8360
|
-
"row.poolLogTestRowMalformed": "{accountName}:
|
|
8361
|
-
"row.poolLogTestDone": "Test finished
|
|
8362
|
-
"row.poolLogBatchFailed": "
|
|
8363
|
-
"row.poolLogTimeout": "The test
|
|
8364
|
-
"row.poolSelectAria": "Include {accountName} in
|
|
8989
|
+
"row.poolLogTestStart": "Testing {count} account(s) against {model}",
|
|
8990
|
+
"row.poolLogTestRow": "{accountName}: {outcome}",
|
|
8991
|
+
"row.poolLogTestRowMalformed": "{accountName}: the host returned no result for this account",
|
|
8992
|
+
"row.poolLogTestDone": "Test finished; the pool was re-ranked",
|
|
8993
|
+
"row.poolLogBatchFailed": "Batch operation failed: {message}",
|
|
8994
|
+
"row.poolLogTimeout": "The account test timed out and was cancelled. Check the network before retrying. Error: {message}",
|
|
8995
|
+
"row.poolSelectAria": "Include {accountName} in this region's account pool",
|
|
8365
8996
|
"row.poolCheckedIn": "Checked in",
|
|
8366
8997
|
"row.poolNotCheckedIn": "Not checked in",
|
|
8367
8998
|
"row.poolCheckinUnknown": "Unknown",
|
|
@@ -8377,16 +9008,16 @@ window.__ModuleLoader__.load({
|
|
|
8377
9008
|
"row.poolProbeUnavailable": "unavailable",
|
|
8378
9009
|
"row.poolProbeNotFound": "not served",
|
|
8379
9010
|
"row.poolProbeFailed": "failed",
|
|
8380
|
-
"row.poolProbeSourceUnknown": "
|
|
8381
|
-
"row.poolProbeSourceLive": "
|
|
8382
|
-
"row.poolProbeSourceTest": "
|
|
9011
|
+
"row.poolProbeSourceUnknown": "source unknown",
|
|
9012
|
+
"row.poolProbeSourceLive": "hit by a live request",
|
|
9013
|
+
"row.poolProbeSourceTest": "tested",
|
|
8383
9014
|
"row.poolProbeModel": "model {model}",
|
|
8384
|
-
"row.poolProbeModelUnknown": "model
|
|
9015
|
+
"row.poolProbeModelUnknown": "model not recorded",
|
|
8385
9016
|
"row.poolExcludedUnusable": "unusable",
|
|
8386
9017
|
"row.poolTokenExpired": "sign-in expired",
|
|
8387
9018
|
"row.poolExcludedRateLimited": "rate limited",
|
|
8388
9019
|
"row.poolExcludedModelBusy": "model busy",
|
|
8389
|
-
"row.poolExcludedOutOfCredit": "
|
|
9020
|
+
"row.poolExcludedOutOfCredit": "Out of credits",
|
|
8390
9021
|
"row.poolExcludedCredentialRejected": "sign-in rejected",
|
|
8391
9022
|
"row.poolExcludedPolicyRejected": "policy rejected",
|
|
8392
9023
|
"row.poolExcludedPlanGated": "needs a higher plan",
|
|
@@ -8397,18 +9028,18 @@ window.__ModuleLoader__.load({
|
|
|
8397
9028
|
"row.poolAgoMin": "{n} min ago",
|
|
8398
9029
|
"row.poolAgoHour": "{n} h ago",
|
|
8399
9030
|
"row.poolAgoDay": "{n} d ago",
|
|
8400
|
-
"row.poolErrOrigin": "
|
|
8401
|
-
"row.poolErrUnavailable": "
|
|
9031
|
+
"row.poolErrOrigin": "Request origin validation failed; no pool action was executed",
|
|
9032
|
+
"row.poolErrUnavailable": "The account pool is not available in this build (or its batch route is missing). Restart the app; if it persists, the plugin needs reinstalling.",
|
|
8402
9033
|
"row.poolErrMethod": "the pool does not accept that request method",
|
|
8403
9034
|
"row.poolErrBadRequest": "the pool refused the request",
|
|
8404
|
-
"row.poolErrNoMembers": "
|
|
8405
|
-
"row.poolErrNoLiveMembers": "
|
|
9035
|
+
"row.poolErrNoMembers": "No accounts are selected for this pool. Select accounts below and save.",
|
|
9036
|
+
"row.poolErrNoLiveMembers": "The plugin cannot read valid login credentials for the selected accounts. Sign in to Trae again, or remove these accounts from the pool and save.",
|
|
8406
9037
|
"row.poolErrCheckinUnsupported": "this panel does not offer a daily check-in",
|
|
8407
9038
|
"row.poolErrTargetStale": "the saved target model is no longer offered",
|
|
8408
|
-
"row.poolErrNoFreeModel": "
|
|
9039
|
+
"row.poolErrNoFreeModel": "No free model is available in this region. Refresh the catalog or select a test model manually before retrying.",
|
|
8409
9040
|
"row.poolErrConflict": "the pool refused the request",
|
|
8410
9041
|
"row.poolErrGeneric": "pool request failed (HTTP {status})",
|
|
8411
|
-
"row.poolSettingsHint": "
|
|
9042
|
+
"row.poolSettingsHint": "These are preferences: they take effect when you save (same as the model list). Test results are written automatically and are not affected by this button.",
|
|
8412
9043
|
"row.poolLogSaved": "Pool settings saved.",
|
|
8413
9044
|
"row.poolLogSaveFailed": "Could not save the pool settings.",
|
|
8414
9045
|
"row.poolLogNoMembers": "Nothing to do — no pool members are selected.",
|
|
@@ -8425,8 +9056,8 @@ window.__ModuleLoader__.load({
|
|
|
8425
9056
|
"row.poolRowDeleted": "Deleted the credential copy of {accountName}.",
|
|
8426
9057
|
"row.poolDeleteStillSigned": "Deleted this plugin's copy of {accountName}, but it is still signed in to Trae, so the account itself is not gone. Sign out inside Trae to remove it from this machine.",
|
|
8427
9058
|
"row.poolRowDeletedSignedOut": "Deleted {accountName} and signed it out of {apps}.",
|
|
8428
|
-
"row.poolRowDeleteAppRunning": "
|
|
8429
|
-
"row.poolDeleteAppRunning": "
|
|
9059
|
+
"row.poolRowDeleteAppRunning": "{apps} is running and may overwrite login file changes. Quit those apps completely before deleting {accountName}.",
|
|
9060
|
+
"row.poolDeleteAppRunning": "No files were changed because {apps} is running and may overwrite login file changes. Quit those apps completely before deleting the account.",
|
|
8430
9061
|
"row.poolDeleteNoCopy": "There was no plugin copy of {accountName} left to delete — it only exists as a Trae app login, and that sign-out did not take effect.",
|
|
8431
9062
|
"row.poolRowDeleteStillSigned": "removed this copy, but {accountName} is still signed in to Trae",
|
|
8432
9063
|
"row.poolRowDeleteNoCopy": "{accountName} had no plugin copy — only its Trae app login",
|
|
@@ -8435,67 +9066,85 @@ window.__ModuleLoader__.load({
|
|
|
8435
9066
|
"nav.panel": "Trae",
|
|
8436
9067
|
"row.pageBack": "Back to conversation",
|
|
8437
9068
|
"row.sidebarPanelLabel": "Show Trae in the sidebar",
|
|
8438
|
-
"row.sidebarPanelHint": "
|
|
9069
|
+
"row.sidebarPanelHint": "Show the Trae settings entry in the sidebar, disabled by default. Changes take effect immediately; disabling it returns an open settings page to the conversation."
|
|
8439
9070
|
};
|
|
8440
9071
|
const zh = {
|
|
8441
|
-
"row.
|
|
8442
|
-
"row.
|
|
9072
|
+
"row.tabCredentialHint": "国内版与企业版共用 Trae CN 登录凭据,账号绑定分别保存。",
|
|
9073
|
+
"row.tabFreeQuotaWarn": "免费模型也可能遇到上游请求限制或服务繁忙。",
|
|
9074
|
+
"row.poolFailoverHint": "Trae 也会在服务端故障时尝试换号;参数错误和模型权限不足会直接显示报错。",
|
|
9075
|
+
"row.iconStyleLabel": "图标样式",
|
|
9076
|
+
"row.iconStyleHint": "立即更新侧边栏和页面图标,当前浏览器分别保存每个插件的选择。",
|
|
9077
|
+
"row.iconStyleClaude": "Claude 风格",
|
|
9078
|
+
"row.iconStyleOriginal": "默认图标",
|
|
9079
|
+
"row.iconStyleSaveFailed": "浏览器无法保存图标选择,请检查网站存储权限。",
|
|
9080
|
+
"row.poolAutoCheckinDeviceHint": "Trae 限制每台设备的每日奖励,部分成员可能无法领取。",
|
|
9081
|
+
"row.checkinStatusError": "无法读取今日签到状态:{message}",
|
|
9082
|
+
"row.poolAutoCheckinDeviceDone": "今日:本机的每日奖励领取次数已用完。",
|
|
9083
|
+
"row.poolAutoCheckinRetry": "今日:{count} 个账号已签,失败的请求将自动重试。",
|
|
9084
|
+
"row.poolAutoCheckinProgress": "今日:{count} 个账号已签。",
|
|
9085
|
+
"row.poolAutoCheckinWaiting": "等待下一次后台检查。",
|
|
9086
|
+
"row.poolAutoCheckin": "每天自动签到",
|
|
9087
|
+
"row.poolAutoCheckinHint": "开启并保存后,插件在 DSH 运行期间每天为所选国内版个人账号领取签到奖励。重启后,插件先检查当天的签到进度,再处理尚未签到的账号。失败时自动重试。",
|
|
9088
|
+
"row.title": "Trae 积分与模型",
|
|
9089
|
+
"row.desc": "在 DSH 中使用 Trae 国内版、企业版和国际版模型。可管理账号、选择模型、查询积分和领取每日签到奖励。刷新模型目录时,插件同时更新积分倍率。",
|
|
8443
9090
|
"row.expand": "展开",
|
|
8444
9091
|
"row.collapse": "收起",
|
|
8445
9092
|
"row.tabCn": "国内版",
|
|
8446
9093
|
"row.tabEnterprise": "企业版",
|
|
8447
9094
|
"row.tabAi": "国际版",
|
|
8448
|
-
"row.tabHint": "
|
|
8449
|
-
"row.tabEnterpriseHint": "
|
|
8450
|
-
"row.tabSwitchHint": "
|
|
8451
|
-
"row.tabSwitchAria": "
|
|
8452
|
-
"row.tabOffNotice": "
|
|
8453
|
-
"row.panelAria": "
|
|
9095
|
+
"row.tabHint": "国内版、企业版和国际版可同时启用。切换上方版本页签,可分别查看和管理各版本的账号、积分和模型。",
|
|
9096
|
+
"row.tabEnterpriseHint": "企业版请求使用 Trae CN 账号的租户额度,失败时直接显示错误,不会改用个人积分重试。",
|
|
9097
|
+
"row.tabSwitchHint": "关闭此开关后,插件会从模型列表中隐藏该区域的模型,并保留账号和设置。再次打开开关即可恢复。",
|
|
9098
|
+
"row.tabSwitchAria": "启用{region}模型",
|
|
9099
|
+
"row.tabOffNotice": "该区域已关闭,账号和设置已保留。勾选上方开关可恢复模型。",
|
|
9100
|
+
"row.panelAria": "卡片分区",
|
|
8454
9101
|
"row.panelAccounts": "账号",
|
|
9102
|
+
"row.panelCapabilities": "能力",
|
|
9103
|
+
"row.panelCapabilitiesHint": "插件可以替你做什么。这些开关点一下立即生效 —— 开关没有保存按钮。",
|
|
8455
9104
|
"row.panelModels": "模型",
|
|
8456
9105
|
"row.panelDiag": "诊断",
|
|
8457
|
-
"row.diagRegion": "
|
|
9106
|
+
"row.diagRegion": "区域",
|
|
8458
9107
|
"row.diagProvider": "供应商 id",
|
|
8459
|
-
"row.diagAccount": "
|
|
8460
|
-
"row.diagToken": "
|
|
9108
|
+
"row.diagAccount": "当前使用账号",
|
|
9109
|
+
"row.diagToken": "登录有效期至",
|
|
8461
9110
|
"row.diagRefresh": "重新登录最后期限",
|
|
8462
9111
|
"row.diagRefreshNone": "该凭据不携带",
|
|
8463
|
-
"row.diagCatalog": "
|
|
8464
|
-
"row.diagEnabled": "
|
|
9112
|
+
"row.diagCatalog": "目录中的模型",
|
|
9113
|
+
"row.diagEnabled": "已启用的模型",
|
|
8465
9114
|
"row.diagPool": "账号池",
|
|
8466
|
-
"row.diagPoolOn": "
|
|
8467
|
-
"row.diagPoolOff": "
|
|
9115
|
+
"row.diagPoolOn": "开启 · {count} 个账号",
|
|
9116
|
+
"row.diagPoolOff": "关闭",
|
|
8468
9117
|
"row.diagCheckin": "每日签到",
|
|
8469
9118
|
"row.diagCheckinOn": "支持",
|
|
8470
9119
|
"row.diagCheckinOff": "本面板不提供",
|
|
8471
9120
|
"row.diagRaw": "Raw 会话通道",
|
|
8472
9121
|
"row.diagRawOff": "未检测",
|
|
8473
|
-
"row.diagFailures": "
|
|
8474
|
-
"row.diagNoFailures": "
|
|
9122
|
+
"row.diagFailures": "最近一次失败",
|
|
9123
|
+
"row.diagNoFailures": "没有报错。",
|
|
8475
9124
|
"row.diagQuarantine": "损坏副本留存",
|
|
8476
9125
|
"row.diagQuarantineNone": "无",
|
|
8477
|
-
"row.diagHint": "
|
|
9126
|
+
"row.diagHint": "这里显示本面板最近一次刷新得到的状态,可用于问题反馈;分享前请隐去账号标识和本机路径中的个人信息。",
|
|
8478
9127
|
"row.settingsWriteFailed": "设置未能保存:{message}",
|
|
8479
9128
|
"row.signedOut": "未登录",
|
|
8480
|
-
"row.signedOutHint": "
|
|
9129
|
+
"row.signedOutHint": "请先登录 Trae 桌面端,再点击「重新检测账号」,将登录凭据保存为插件副本。",
|
|
8481
9130
|
"row.unsupportedRegionTitle": "美国区(US)暂不支持",
|
|
8482
|
-
"row.unsupportedRegionHint": "本机有一个 Trae 账号属于美国区(userRegion \"US\" / 主机 *.traeapi.us
|
|
9131
|
+
"row.unsupportedRegionHint": "本机有一个 Trae 账号属于美国区(userRegion \"US\" / 主机 *.traeapi.us)。本版本尚未支持该区,因此不会使用这个账号,也不会把请求发往新加坡网关。重新登录不会改变账号所属区域。请在该面板改用国内版或新加坡区账号(或使用 Trae 国内版客户端)。",
|
|
8483
9132
|
"row.diagUnsupportedRegion": "未支持的区域",
|
|
8484
9133
|
"row.searchedTitle": "已检查的路径",
|
|
8485
9134
|
"row.searchedHint": "未找到登录信息。以下是插件探测过的位置;如果你的 Trae 把登录信息存在别处,请把该路径反馈给我们。",
|
|
8486
9135
|
"row.searchedMore": "展开其余 {count} 条",
|
|
8487
9136
|
"row.quarantineTitle": "被隔离的账号副本",
|
|
8488
|
-
"row.quarantineHint": "
|
|
9137
|
+
"row.quarantineHint": "插件无法读取该账号副本,已将文件改名保留。需要恢复账号时请检查该文件;确认不再需要后,可自行删除留存文件。",
|
|
8489
9138
|
"row.quarantineAccounts": "含 {count} 个账号",
|
|
8490
9139
|
"row.quarantineAccountsUnknown": "账号数无法读取",
|
|
8491
9140
|
"row.quarantineBytes": "{bytes} 字节",
|
|
8492
9141
|
"row.reasonMissing": "文件不存在",
|
|
8493
9142
|
"row.reasonUnreadable": "无法读取",
|
|
8494
9143
|
"row.reasonInvalid": "格式无法识别",
|
|
8495
|
-
"row.sourceDesktop": "
|
|
9144
|
+
"row.sourceDesktop": "桌面端",
|
|
8496
9145
|
"row.sourceCli": "Trae CLI",
|
|
8497
9146
|
"row.signedIn": "已登录:{accountName}",
|
|
8498
|
-
"row.tokenExpiry": "
|
|
9147
|
+
"row.tokenExpiry": "访问令牌将于 {expiresAt} 过期,插件会尝试自动续期",
|
|
8499
9148
|
"row.refreshTokenExpiring": "请在 {expiresAt} 前重新登录一次 Trae(还剩 {days} 天),此后将无法自动续期。",
|
|
8500
9149
|
"row.refreshTokenLapsed": "自动续期已停止:Trae 登录凭据已于 {expiresAt} 过期。请重新登录一次 Trae 以恢复。",
|
|
8501
9150
|
"row.requestFailed": "请求失败",
|
|
@@ -8516,7 +9165,7 @@ window.__ModuleLoader__.load({
|
|
|
8516
9165
|
"row.checkinClaimed": "已领取",
|
|
8517
9166
|
"row.checkinRefused": "Trae 拒绝了本次签到(业务码 {code})",
|
|
8518
9167
|
"row.checkinError": "签到失败:{message}",
|
|
8519
|
-
"row.checkinDeviceSpent": "
|
|
9168
|
+
"row.checkinDeviceSpent": "Trae 每台设备每天只能签到一次。本机今日已签到,当前账号今天无法在本机领取。请换一台尚未签到的设备,或明天再试。",
|
|
8520
9169
|
"row.checkinDisabled": "该账号当前没有可用的签到活动。",
|
|
8521
9170
|
"row.checkinDeviceSpentShort": "本机已签",
|
|
8522
9171
|
"row.subscriptionLabel": "订阅状态",
|
|
@@ -8531,26 +9180,26 @@ window.__ModuleLoader__.load({
|
|
|
8531
9180
|
"row.refreshCredits": "刷新用量",
|
|
8532
9181
|
"row.refreshing": "正在刷新…",
|
|
8533
9182
|
"row.accountsTitle": "Trae 账号",
|
|
8534
|
-
"row.accountsHint": "
|
|
8535
|
-
"row.transferTitle": "
|
|
8536
|
-
"row.transferExport": "
|
|
8537
|
-
"row.transferImport": "
|
|
9183
|
+
"row.accountsHint": "插件刷新账号时会为检测到的 Trae 登录保存凭据副本。切换到新账号后请刷新一次,以免下次登录覆盖尚未保存的凭据。",
|
|
9184
|
+
"row.transferTitle": "导出 / 导入账号",
|
|
9185
|
+
"row.transferExport": "导出账号",
|
|
9186
|
+
"row.transferImport": "导入账号",
|
|
8538
9187
|
"row.transferCancel": "取消",
|
|
8539
9188
|
"row.transferSelectAll": "全选",
|
|
8540
|
-
"row.transferExportPick": "
|
|
8541
|
-
"row.transferExportConfirm": "导出 {count}
|
|
8542
|
-
"row.transferExported": "已导出 {count}
|
|
8543
|
-
"row.transferExporting": "
|
|
8544
|
-
"row.transferImportPick": "
|
|
8545
|
-
"row.transferImportConfirm": "导入 {count}
|
|
9189
|
+
"row.transferExportPick": "选择要导出的账号(共 {total} 个):",
|
|
9190
|
+
"row.transferExportConfirm": "导出 {count} 个账号",
|
|
9191
|
+
"row.transferExported": "已导出 {count} 个账号到 {fileName}。",
|
|
9192
|
+
"row.transferExporting": "正在导出…",
|
|
9193
|
+
"row.transferImportPick": "文件包含 {total} 条记录,请勾选要导入的账号。插件将保存为自己的凭据副本,不改动 Trae 应用登录。",
|
|
9194
|
+
"row.transferImportConfirm": "导入 {count} 个账号",
|
|
8546
9195
|
"row.transferImported": "已导入 {imported} 个账号副本,跳过 {skipped} 个。",
|
|
8547
9196
|
"row.transferImporting": "正在导入…",
|
|
8548
9197
|
"row.transferReading": "正在读取文件…",
|
|
8549
|
-
"row.transferHint": "
|
|
9198
|
+
"row.transferHint": "使用 JSON 文件导出账号,或将文件中的账号导入插件。文件包含登录凭据,请限制文件的访问权限。导入时会跳过其他区域的账号。",
|
|
8550
9199
|
"row.transferError": "导入/导出失败:{message}",
|
|
8551
9200
|
"row.transferVeilHint": "完成后账号列表会自动刷新。",
|
|
8552
9201
|
"row.transferUnnamed": "未命名账号",
|
|
8553
|
-
"row.transferNoToken": "
|
|
9202
|
+
"row.transferNoToken": "缺少登录凭据",
|
|
8554
9203
|
"row.accountsRescan": "重新检测账号",
|
|
8555
9204
|
"row.accountsScanning": "正在检测…",
|
|
8556
9205
|
"row.accountsLoading": "正在加载账号…",
|
|
@@ -8563,7 +9212,7 @@ window.__ModuleLoader__.load({
|
|
|
8563
9212
|
"row.accountColumnCheckin": "签到",
|
|
8564
9213
|
"row.accountBalance": "积分 {credits}",
|
|
8565
9214
|
"row.balanceConsoleOnly": "见企业版控制台",
|
|
8566
|
-
"row.enterpriseCreditsNotice": "
|
|
9215
|
+
"row.enterpriseCreditsNotice": "插件尚不能读取企业租户余额,请到企业版控制台 console.enterprise.trae.cn 查看。此处不显示个人积分,以免将其误认为企业额度。",
|
|
8567
9216
|
"row.sourceDsh": "插件副本",
|
|
8568
9217
|
"row.modelsTitle": "模型",
|
|
8569
9218
|
"row.modelsSummary": "已启用 {count} 个",
|
|
@@ -8577,7 +9226,7 @@ window.__ModuleLoader__.load({
|
|
|
8577
9226
|
"row.modelsViewLabel": "模型范围",
|
|
8578
9227
|
"row.modelsViewCommon": "常用通道 · {count}",
|
|
8579
9228
|
"row.modelsViewAll": "全部 · {count}",
|
|
8580
|
-
"row.modelsViewCommonHint": "
|
|
9229
|
+
"row.modelsViewCommonHint": "显示可通过 solo_work_remote 或 solo_work_lite 调用的模型。",
|
|
8581
9230
|
"row.modelsViewAllHint": "还包含只在专用通道提供的模型:solo_coder、chat_v3、solo_agent_remote。",
|
|
8582
9231
|
"row.modelsViewShowAll": "查看全部",
|
|
8583
9232
|
"row.modelsSearchOutsideView": "常用通道内没有匹配「{query}」的模型,全部目录里有 {count} 个。",
|
|
@@ -8587,24 +9236,24 @@ window.__ModuleLoader__.load({
|
|
|
8587
9236
|
"row.modelsChannelAgentRemote": "SOLO 智能体 · 远程",
|
|
8588
9237
|
"row.modelsChannelChatV3": "对话 · v3",
|
|
8589
9238
|
"row.modelsChannelCoder": "代码 · solo_coder",
|
|
8590
|
-
"row.modelsChannelDefault": "
|
|
8591
|
-
"row.modelsTestEnabled": "
|
|
8592
|
-
"row.modelsTestAll": "
|
|
8593
|
-
"row.modelsTesting": "
|
|
8594
|
-
"row.modelsTestHint": "
|
|
8595
|
-
"row.modelsTestAllHint": "
|
|
9239
|
+
"row.modelsChannelDefault": "未标注模式,使用 solo_work_lite",
|
|
9240
|
+
"row.modelsTestEnabled": "测试已启用模型",
|
|
9241
|
+
"row.modelsTestAll": "测试所有模型",
|
|
9242
|
+
"row.modelsTesting": "测试中 {done}/{total}…",
|
|
9243
|
+
"row.modelsTestHint": "向每个已启用模型发送最小测试请求,按模型费率消耗额度,并分别显示结果。",
|
|
9244
|
+
"row.modelsTestAllHint": "测试当前目录中的所有模型,包含未启用的模型;每次请求均按对应模型费率计费。",
|
|
8596
9245
|
"row.showPointsInMainUi": "在输入框工具栏显示积分读数",
|
|
8597
|
-
"row.showPointsInMainUiHint": "
|
|
8598
|
-
"row.showPointsInMainUiHintAi": "
|
|
9246
|
+
"row.showPointsInMainUiHint": "开启后在所选位置显示可点击读数:国内版为「Trae - CN · 余额」,国际版为「Trae 国际版 · 套餐」。选择其他供应商模型时仍可查看。",
|
|
9247
|
+
"row.showPointsInMainUiHintAi": "开启后在所选位置显示国际版套餐,选择其他供应商模型时仍可查看。",
|
|
8599
9248
|
"row.drawImage": "允许模型自主生图(trae_draw_image)",
|
|
8600
|
-
"row.drawImageHint": "
|
|
8601
|
-
"row.drawImageHintEnterprise": "
|
|
8602
|
-
"row.drawImageHintAi": "
|
|
9249
|
+
"row.drawImageHint": "开启后提供 trae_draw_image 工具,模型可按你的要求生成图片并消耗当前账号积分。国内版曾测得 1920x1920 图片约 8.8 积分,实际费用以上游扣费为准;默认关闭。",
|
|
9250
|
+
"row.drawImageHintEnterprise": "企业版的生图调用与计费尚未验证,因此暂不提供该功能。",
|
|
9251
|
+
"row.drawImageHintAi": "国际版的生图调用与计费尚未验证,因此暂不提供该功能;需要生图时请使用国内版面板。",
|
|
8603
9252
|
"row.creditPositionLabel": "显示位置",
|
|
8604
9253
|
"row.creditPositionComposer": "输入框工具栏",
|
|
8605
9254
|
"row.creditPositionStats": "输入框下方",
|
|
8606
9255
|
"row.creditPositionAria": "{region} 的积分显示位置",
|
|
8607
|
-
"row.creditPositionHint": "
|
|
9256
|
+
"row.creditPositionHint": "默认与模型选择同一行显示;遇到其他连接器占用排序位置时,后加载的读数自动向左排列。也可选择「输入框下方」,与轮次、步数和 token 统计同一行显示。",
|
|
8608
9257
|
"composer.switchTo": "切换到 {account}",
|
|
8609
9258
|
"composer.noAccounts": "该区域暂无账号",
|
|
8610
9259
|
"composer.panelTitle": "Trae 积分",
|
|
@@ -8646,11 +9295,11 @@ window.__ModuleLoader__.load({
|
|
|
8646
9295
|
"row.settingsDirty": "有未保存的修改",
|
|
8647
9296
|
"row.modelsTestEmpty": "请先启用至少一个模型。",
|
|
8648
9297
|
"row.contextAllMid": "整区切到 500K",
|
|
8649
|
-
"row.contextAllMidHint": "
|
|
9298
|
+
"row.contextAllMidHint": "将本面板中 Max 窗口不小于 500K 的模型设为 500K 上下文预算,其余模型保持原值;点击「保存」后生效。",
|
|
8650
9299
|
"row.contextAllMax": "整区切到 Max",
|
|
8651
|
-
"row.contextAllMaxHint": "
|
|
9300
|
+
"row.contextAllMaxHint": "将本面板中提供 Max 窗口的模型设为各自的最大上下文预算,其余模型保持原值;点击「保存」后生效。",
|
|
8652
9301
|
"row.contextAllDefault": "全部恢复默认上下文",
|
|
8653
|
-
"row.contextAllDefaultHint": "
|
|
9302
|
+
"row.contextAllDefaultHint": "清除本面板的自定义上下文预算,恢复使用 Trae 目录默认值;点击「保存」后生效。",
|
|
8654
9303
|
"row.modelsTestError": "测试失败:{message}",
|
|
8655
9304
|
"row.modelsTestDone": "{total} 个里有 {available} 个正常应答。",
|
|
8656
9305
|
"row.probeAvailable": "可用",
|
|
@@ -8672,7 +9321,7 @@ window.__ModuleLoader__.load({
|
|
|
8672
9321
|
"row.veilSaving": "正在保存更改…",
|
|
8673
9322
|
"row.modelContext": "最大上下文 {context}",
|
|
8674
9323
|
"row.contextBudget": "DSH 上下文预算",
|
|
8675
|
-
"row.contextBudgetHint": "
|
|
9324
|
+
"row.contextBudgetHint": "设置 DSH 组织请求时使用的上下文预算。插件不向上游发送窗口或 Max 模式参数,因此不会据此切换 Trae 的服务窗口。",
|
|
8676
9325
|
"row.modelOutput": "最大输出 {output}",
|
|
8677
9326
|
"row.modelImage": "图片",
|
|
8678
9327
|
"row.modelImageAuto": "已自动开启:Trae 把该模型标为多模态。",
|
|
@@ -8682,87 +9331,87 @@ window.__ModuleLoader__.load({
|
|
|
8682
9331
|
"row.modelReasoningFollowUpstream": "默认",
|
|
8683
9332
|
"row.modelReasoningFollowUpstreamNamed": "默认({effort})",
|
|
8684
9333
|
"row.modelUnknown": "未知",
|
|
8685
|
-
"row.modelCapabilityPending": "
|
|
9334
|
+
"row.modelCapabilityPending": "Trae 标注为多模态的模型会自动启用图片输入,也可手动为其他模型启用。",
|
|
8686
9335
|
"row.poolTitle": "账号池",
|
|
8687
9336
|
"row.poolEnabled": "启用账号池",
|
|
8688
|
-
"row.poolEnabledHint": "
|
|
9337
|
+
"row.poolEnabledHint": "开启后,插件自动选择账号;遇到账号限流、积分耗尽或账号故障时尝试换号。关闭后,请从账号列表中选择要使用的账号。",
|
|
8689
9338
|
"row.poolCurrentHeader": "当前计费:{account}",
|
|
8690
|
-
"row.poolModeAuto": "
|
|
8691
|
-
"row.poolModeManual": "
|
|
9339
|
+
"row.poolModeAuto": "自动选择",
|
|
9340
|
+
"row.poolModeManual": "手动选择",
|
|
8692
9341
|
"row.poolMember": "已在池中",
|
|
8693
|
-
"row.poolNotMember": "
|
|
8694
|
-
"row.poolBusyHint": "
|
|
8695
|
-
"row.poolTestAll": "
|
|
8696
|
-
"row.poolTesting": "
|
|
8697
|
-
"row.poolOffNotice": "
|
|
8698
|
-
"row.poolNoCandidate": "
|
|
8699
|
-
"row.poolNoCandidateEmpty": "
|
|
8700
|
-
"row.poolNoCandidateEmptyHint": "
|
|
9342
|
+
"row.poolNotMember": "未加入",
|
|
9343
|
+
"row.poolBusyHint": "插件正在处理所选账号…",
|
|
9344
|
+
"row.poolTestAll": "测试勾选的账号",
|
|
9345
|
+
"row.poolTesting": "测试中…",
|
|
9346
|
+
"row.poolOffNotice": "账号池已关闭,当前请求由绑定账号计费。开启上方开关后,插件按账号池规则选择账号。",
|
|
9347
|
+
"row.poolNoCandidate": "账号池里目前没有可用的账号。",
|
|
9348
|
+
"row.poolNoCandidateEmpty": "账号池尚未选择成员。",
|
|
9349
|
+
"row.poolNoCandidateEmptyHint": "请在下方勾选账号并保存,插件才会将其加入账号池。",
|
|
8701
9350
|
"row.poolNoCandidateUnusable": "所有已选成员当前均不可用。",
|
|
8702
|
-
"row.poolNoCandidateHint": "
|
|
8703
|
-
"row.poolServingOutside": "{account}
|
|
8704
|
-
"row.poolMembersTitle": "
|
|
9351
|
+
"row.poolNoCandidateHint": "账号池没有可用成员时,请求会尝试使用已保存的绑定账号。成员当前状态:",
|
|
9352
|
+
"row.poolServingOutside": "当前由未加入账号池的 {account} 计费,账号池恢复可用成员前会继续使用已保存的绑定账号。",
|
|
9353
|
+
"row.poolMembersTitle": "账号池成员",
|
|
8705
9354
|
"row.poolRescan": "重新检测账号",
|
|
8706
9355
|
"row.poolToolsLabel": "导出 / 导入账号",
|
|
8707
9356
|
"row.poolCreditExpiry": "{when} 过期",
|
|
8708
9357
|
"row.poolProbeMeasured": "测得 {when}",
|
|
8709
9358
|
"row.poolProbeAt": "测试于 {when}",
|
|
8710
|
-
"row.poolSettingsNote": "
|
|
9359
|
+
"row.poolSettingsNote": "修改下方设置后请点击「保存」;测试结果由插件单独保存。",
|
|
8711
9360
|
"row.poolSelectedCount": "已选 {count} / {total}",
|
|
8712
9361
|
"row.poolNoCopyTag": "本机无副本",
|
|
8713
|
-
"row.poolCopyFile": "
|
|
8714
|
-
"row.poolNoCopyTestHint": "
|
|
8715
|
-
"row.poolSelectAll": "
|
|
8716
|
-
"row.poolSelectNone": "
|
|
9362
|
+
"row.poolCopyFile": "当前共有 {count} 份账号副本,保存位置为 {path}。刷新账号时,插件为新登录创建副本,并保留已有副本。",
|
|
9363
|
+
"row.poolNoCopyTestHint": "插件无法读取该账号的登录凭据,请在 Trae 中重新登录后检测账号,或将其移出账号池。",
|
|
9364
|
+
"row.poolSelectAll": "全选",
|
|
9365
|
+
"row.poolSelectNone": "全不选",
|
|
8717
9366
|
"row.poolColumnAccount": "账号",
|
|
8718
9367
|
"row.poolColumnCredits": "积分",
|
|
8719
9368
|
"row.poolColumnProbe": "状态",
|
|
8720
9369
|
"row.poolColumnCheckin": "签到",
|
|
8721
|
-
"row.poolGeneralLabel": "
|
|
8722
|
-
"row.poolWorkHint": "
|
|
9370
|
+
"row.poolGeneralLabel": "积分",
|
|
9371
|
+
"row.poolWorkHint": "DSH 对话使用积分余额,不能使用工作积分。",
|
|
8723
9372
|
"row.poolCreditNone": "—",
|
|
8724
|
-
"row.poolTestedAt": "
|
|
8725
|
-
"row.poolNeverTested": "
|
|
8726
|
-
"row.poolRetryAt": "{at}
|
|
9373
|
+
"row.poolTestedAt": "测试于 {at}",
|
|
9374
|
+
"row.poolNeverTested": "未测试",
|
|
9375
|
+
"row.poolRetryAt": "{at} 后可重试",
|
|
8727
9376
|
"row.poolRetryUnknown": "重试时间未知",
|
|
8728
|
-
"row.poolTargetCurrentPreferred": "
|
|
8729
|
-
"row.poolTargetCurrentFree": "
|
|
8730
|
-
"row.poolTargetStale": "
|
|
9377
|
+
"row.poolTargetCurrentPreferred": "测试模型:{model}(手动选择)",
|
|
9378
|
+
"row.poolTargetCurrentFree": "测试模型:{model}(自动选择)",
|
|
9379
|
+
"row.poolTargetStale": "你保存的目标模型已不在目录中:{model}",
|
|
8731
9380
|
"row.poolTargetStaleOption": "{model}(已下架)",
|
|
8732
|
-
"row.poolTargetStaleClear": "
|
|
9381
|
+
"row.poolTargetStaleClear": "切回自动",
|
|
8733
9382
|
"row.poolTargetNone": "本面板暂无可用免费模型",
|
|
8734
|
-
"row.poolTargetNoneHint": "
|
|
8735
|
-
"row.poolActionNoteTestNone": "
|
|
8736
|
-
"row.poolActionNoteNoMembers": "
|
|
8737
|
-
"row.poolTargetAutoOption": "
|
|
8738
|
-
"row.poolTargetLabel": "
|
|
8739
|
-
"row.poolTargetHint": "
|
|
8740
|
-
"row.poolProbeSizeLabel": "
|
|
8741
|
-
"row.poolProbeSizeHint": "
|
|
9383
|
+
"row.poolTargetNoneHint": "自动模式仅选择免费模型,请刷新目录后重试,或手动选择测试模型;选择收费模型时会消耗被测账号积分。",
|
|
9384
|
+
"row.poolActionNoteTestNone": "本面板未找到免费模型,请选择目标模型后再测试账号。",
|
|
9385
|
+
"row.poolActionNoteNoMembers": "请勾选要测试的账号,并保存账号池设置。",
|
|
9386
|
+
"row.poolTargetAutoOption": "自动选择免费模型",
|
|
9387
|
+
"row.poolTargetLabel": "账号测试模型",
|
|
9388
|
+
"row.poolTargetHint": "批量测试使用此处选择的模型。选择「自动」时,插件使用该区域上下文窗口最大的免费模型;选择收费模型时,测试会消耗各被测账号的积分。",
|
|
9389
|
+
"row.poolProbeSizeLabel": "测试输入大小",
|
|
9390
|
+
"row.poolProbeSizeHint": "建议选择接近会话请求的输入长度。短请求通过测试后,较长的请求也可能触发账号限制。输入越长,收费模型的测试费用越高。",
|
|
8742
9391
|
"row.poolProbeSizeDefault": "最小请求(默认)",
|
|
8743
9392
|
"row.poolProbeSizeOption": "{wan} 万 token",
|
|
8744
9393
|
"row.poolSettingsTitle": "更多设置",
|
|
8745
9394
|
"row.poolMoreRulesTitle": "账号副本与保存规则",
|
|
8746
|
-
"row.poolManualAccountLabel": "
|
|
8747
|
-
"row.poolManualAccountNone": "
|
|
8748
|
-
"row.poolDirty": "
|
|
9395
|
+
"row.poolManualAccountLabel": "当前账号",
|
|
9396
|
+
"row.poolManualAccountNone": "当前没有生效的账号",
|
|
9397
|
+
"row.poolDirty": "● 有未保存的修改",
|
|
8749
9398
|
"row.poolSaved": "保存",
|
|
8750
9399
|
"row.poolSaving": "保存中…",
|
|
8751
|
-
"row.poolDiscard": "
|
|
9400
|
+
"row.poolDiscard": "放弃修改",
|
|
8752
9401
|
"row.poolSaveFailed": "保存失败:{message}",
|
|
8753
|
-
"row.poolGhostMembers": "{count}
|
|
8754
|
-
"row.poolUnsavedMembers": "
|
|
8755
|
-
"row.poolRowTest": "
|
|
9402
|
+
"row.poolGhostMembers": "无法读取 {count} 个已保存成员的登录凭据:{names}",
|
|
9403
|
+
"row.poolUnsavedMembers": "成员选择已修改,保存后生效",
|
|
9404
|
+
"row.poolRowTest": "测试",
|
|
8756
9405
|
"row.poolLogTitle": "活动记录",
|
|
8757
9406
|
"row.poolLogClear": "清空",
|
|
8758
9407
|
"row.poolLogEmpty": "暂无账号池活动。",
|
|
8759
|
-
"row.poolLogTestStart": "
|
|
8760
|
-
"row.poolLogTestRow": "{accountName}:{outcome}
|
|
8761
|
-
"row.poolLogTestRowMalformed": "{accountName}
|
|
8762
|
-
"row.poolLogTestDone": "
|
|
8763
|
-
"row.poolLogBatchFailed": "
|
|
8764
|
-
"row.poolLogTimeout": "
|
|
8765
|
-
"row.poolSelectAria": "把 {accountName}
|
|
9408
|
+
"row.poolLogTestStart": "开始测试 {count} 个账号 × {model}",
|
|
9409
|
+
"row.poolLogTestRow": "{accountName}:{outcome}",
|
|
9410
|
+
"row.poolLogTestRowMalformed": "{accountName}:服务端未返回测试结果",
|
|
9411
|
+
"row.poolLogTestDone": "测试完成,已更新可用账号列表",
|
|
9412
|
+
"row.poolLogBatchFailed": "批量操作失败:{message}",
|
|
9413
|
+
"row.poolLogTimeout": "测试超时后已取消,可以重新操作。请检查网络后重试,错误信息:{message}",
|
|
9414
|
+
"row.poolSelectAria": "把 {accountName} 加入本区域的账号池",
|
|
8766
9415
|
"row.poolCheckedIn": "已签到",
|
|
8767
9416
|
"row.poolNotCheckedIn": "未签到",
|
|
8768
9417
|
"row.poolCheckinUnknown": "未知",
|
|
@@ -8778,16 +9427,16 @@ window.__ModuleLoader__.load({
|
|
|
8778
9427
|
"row.poolProbeUnavailable": "不可用",
|
|
8779
9428
|
"row.poolProbeNotFound": "上游不提供",
|
|
8780
9429
|
"row.poolProbeFailed": "失败",
|
|
8781
|
-
"row.poolProbeSourceUnknown": "
|
|
8782
|
-
"row.poolProbeSourceLive": "
|
|
8783
|
-
"row.poolProbeSourceTest": "
|
|
9430
|
+
"row.poolProbeSourceUnknown": "来源未知",
|
|
9431
|
+
"row.poolProbeSourceLive": "对话请求",
|
|
9432
|
+
"row.poolProbeSourceTest": "手动测试",
|
|
8784
9433
|
"row.poolProbeModel": "模型 {model}",
|
|
8785
|
-
"row.poolProbeModelUnknown": "
|
|
9434
|
+
"row.poolProbeModelUnknown": "未记录模型",
|
|
8786
9435
|
"row.poolExcludedUnusable": "不可用",
|
|
8787
9436
|
"row.poolTokenExpired": "登录已失效",
|
|
8788
9437
|
"row.poolExcludedRateLimited": "被限流",
|
|
8789
9438
|
"row.poolExcludedModelBusy": "模型繁忙",
|
|
8790
|
-
"row.poolExcludedOutOfCredit": "
|
|
9439
|
+
"row.poolExcludedOutOfCredit": "积分耗尽",
|
|
8791
9440
|
"row.poolExcludedCredentialRejected": "登录凭据被拒",
|
|
8792
9441
|
"row.poolExcludedPolicyRejected": "被策略拒绝",
|
|
8793
9442
|
"row.poolExcludedPlanGated": "需要更高套餐",
|
|
@@ -8798,45 +9447,45 @@ window.__ModuleLoader__.load({
|
|
|
8798
9447
|
"row.poolAgoMin": "{n} 分钟前",
|
|
8799
9448
|
"row.poolAgoHour": "{n} 小时前",
|
|
8800
9449
|
"row.poolAgoDay": "{n} 天前",
|
|
8801
|
-
"row.poolErrOrigin": "
|
|
8802
|
-
"row.poolErrUnavailable": "
|
|
9450
|
+
"row.poolErrOrigin": "请求来源未通过验证,账号池未执行操作",
|
|
9451
|
+
"row.poolErrUnavailable": "账号池接口不可用,请重启 DSH;问题持续时请重新安装插件。",
|
|
8803
9452
|
"row.poolErrMethod": "账号池不接受该请求方法",
|
|
8804
9453
|
"row.poolErrBadRequest": "账号池拒绝了该请求",
|
|
8805
|
-
"row.poolErrNoMembers": "
|
|
8806
|
-
"row.poolErrNoLiveMembers": "
|
|
9454
|
+
"row.poolErrNoMembers": "请先在账号池中勾选账号并保存,再点击签到或测试按钮。",
|
|
9455
|
+
"row.poolErrNoLiveMembers": "插件无法读取所选账号的有效登录凭据。请重新登录这些账号,或将它们移出账号池后保存。",
|
|
8807
9456
|
"row.poolErrCheckinUnsupported": "本面板不提供每日签到",
|
|
8808
9457
|
"row.poolErrTargetStale": "已保存的目标模型已下架",
|
|
8809
|
-
"row.poolErrNoFreeModel": "
|
|
9458
|
+
"row.poolErrNoFreeModel": "当前区域没有可用的免费模型,请刷新目录,或手动选择测试模型后再试。",
|
|
8810
9459
|
"row.poolErrConflict": "账号池拒绝了该请求",
|
|
8811
9460
|
"row.poolErrGeneric": "账号池请求失败(HTTP {status})",
|
|
8812
|
-
"row.poolSettingsHint": "
|
|
9461
|
+
"row.poolSettingsHint": "修改账号池设置后,请点击保存。插件会单独保存测试结果。",
|
|
8813
9462
|
"row.poolLogSaved": "账号池设置已保存。",
|
|
8814
9463
|
"row.poolLogSaveFailed": "无法保存账号池设置。",
|
|
8815
|
-
"row.poolLogNoMembers": "
|
|
9464
|
+
"row.poolLogNoMembers": "尚未勾选账号池成员,未执行操作。",
|
|
8816
9465
|
"row.poolLogDiscarded": "已放弃未保存的账号池修改。",
|
|
8817
9466
|
"row.poolLogGeneric": "账号池未返回可用的结果",
|
|
8818
9467
|
"row.poolLogRowTesting": "正在测速 {accountName}…",
|
|
8819
9468
|
"row.poolLogTargetCleared": "测速目标已改回自动。",
|
|
8820
9469
|
"row.poolRowDelete": "删除",
|
|
8821
|
-
"row.poolRowDeleteAria": "
|
|
9470
|
+
"row.poolRowDeleteAria": "删除 {accountName} 的插件副本,并将该账号从 Trae 应用中退出登录",
|
|
8822
9471
|
"row.poolRowDeleting": "删除中…",
|
|
8823
9472
|
"row.poolGhostDeleteAria": "从本机删除已保存但无法登录的账号 {accountName}",
|
|
8824
9473
|
"row.poolRowDeleteError": "无法删除 {accountName}:{message}",
|
|
8825
9474
|
"row.poolRowDeleteFailed": "删除未得到确认",
|
|
8826
9475
|
"row.poolRowDeleted": "已删除 {accountName} 的凭据副本。",
|
|
8827
|
-
"row.poolDeleteStillSigned": "
|
|
9476
|
+
"row.poolDeleteStillSigned": "插件副本已删除,但 {accountName} 仍登录在 Trae 中;若要移除本机登录,请在 Trae 内退出该账号。",
|
|
8828
9477
|
"row.poolRowDeletedSignedOut": "已删除 {accountName},并将它从 {apps} 中退出登录。",
|
|
8829
|
-
"row.poolRowDeleteAppRunning": "
|
|
8830
|
-
"row.poolDeleteAppRunning": "
|
|
8831
|
-
"row.poolDeleteNoCopy": "{accountName}
|
|
9478
|
+
"row.poolRowDeleteAppRunning": "{apps} 正在运行,可能覆盖登录文件修改;请完全退出这些应用后,再删除 {accountName}。",
|
|
9479
|
+
"row.poolDeleteAppRunning": "为避免 {apps} 覆盖登录文件修改,本次未改动任何文件;请完全退出这些应用后再删除。",
|
|
9480
|
+
"row.poolDeleteNoCopy": "{accountName} 仅保留在 Trae 的登录状态中,本次退出登录未生效,因此没有删除任何插件副本。",
|
|
8832
9481
|
"row.poolRowDeleteStillSigned": "已删除副本,但 {accountName} 仍登录在 Trae 中",
|
|
8833
|
-
"row.poolRowDeleteNoCopy": "{accountName}
|
|
8834
|
-
"row.poolDeleteHint": "
|
|
9482
|
+
"row.poolRowDeleteNoCopy": "{accountName} 没有插件副本,仅保留在 Trae 应用登录状态中",
|
|
9483
|
+
"row.poolDeleteHint": "刷新账号时,插件会为新检测到的 Trae 登录保存副本,并保留已有副本。删除账号会移除副本、将账号从 Trae 退出登录,并为修改过的文件保留备份;操作前需完全退出相关 Trae 应用。如果退出登录未生效,插件会阻止该账号在保持登录期间再次导入。",
|
|
8835
9484
|
"row.cheer": "鼓励一下",
|
|
8836
9485
|
"nav.panel": "Trae",
|
|
8837
9486
|
"row.pageBack": "返回会话",
|
|
8838
9487
|
"row.sidebarPanelLabel": "在侧边栏显示 Trae",
|
|
8839
|
-
"row.sidebarPanelHint": "
|
|
9488
|
+
"row.sidebarPanelHint": "在侧边栏显示 Trae 设置入口,默认关闭。开关即时生效;关闭时,已打开的设置页会返回对话。"
|
|
8840
9489
|
};
|
|
8841
9490
|
//#endregion
|
|
8842
9491
|
//#region src/client/TraeModelLabel.tsx
|
|
@@ -9131,21 +9780,35 @@ window.__ModuleLoader__.load({
|
|
|
9131
9780
|
* different priority to shadow it (lowest renders)". Priority 0 is the DEFAULT,
|
|
9132
9781
|
* so it is the one value that is guaranteed to be contested.
|
|
9133
9782
|
*
|
|
9134
|
-
* WHY `-
|
|
9135
|
-
*
|
|
9136
|
-
*
|
|
9137
|
-
*
|
|
9138
|
-
*
|
|
9139
|
-
* dsh-connect-
|
|
9140
|
-
*
|
|
9141
|
-
*
|
|
9142
|
-
*
|
|
9143
|
-
*
|
|
9144
|
-
*
|
|
9145
|
-
*
|
|
9146
|
-
*
|
|
9147
|
-
*
|
|
9148
|
-
*
|
|
9783
|
+
* WHY `-102` AND NOT `-0.25`, WHICH THIS USED TO BE. The old value was picked
|
|
9784
|
+
* from a reading of the siblings that was WRONG — and the comment said so with
|
|
9785
|
+
* confidence, which is how a wrong reading survives a code review. Re-measured
|
|
9786
|
+
* from the three plugins' sources:
|
|
9787
|
+
*
|
|
9788
|
+
* dsh-connect-qoder-client priority -101 (active — lowest renders)
|
|
9789
|
+
* dsh-connect-workbuddy-client priority -100
|
|
9790
|
+
* dsh-connect-trae-client priority -0.25 ← never rendered
|
|
9791
|
+
*
|
|
9792
|
+
* The previous note claimed qoder `-1` and workbuddy `-0.5`, i.e. that `-0.25`
|
|
9793
|
+
* sat "between them". Both numbers were stale: the siblings had each moved DOWN
|
|
9794
|
+
* a hundred while this file still described the arrangement they had left. The
|
|
9795
|
+
* consequence was exactly the report that started this change — "the model
|
|
9796
|
+
* picker has no capsule" — because `-0.25` is the HIGHEST of the three, and a
|
|
9797
|
+
* `single` slot renders the LOWEST.
|
|
9798
|
+
*
|
|
9799
|
+
* `-102` is chosen to sit just under qoder, not at some far negative number
|
|
9800
|
+
* like `-1000`: this only needs the one seat, and a needlessly extreme value
|
|
9801
|
+
* would push any future plugin that picks a reasonable number behind us forever.
|
|
9802
|
+
* qoder made the same call when it took `-101` under workbuddy's `-100`.
|
|
9803
|
+
*
|
|
9804
|
+
* WHAT THIS COSTS. Winning a `single` slot means the losers do not render at
|
|
9805
|
+
* all here: qoder's own capsule disappears from the picker the moment this
|
|
9806
|
+
* registers. That is the documented trade-off of the slot, not a bug — and it
|
|
9807
|
+
* is why {@link TraeModelLabel} must reproduce the host's presentation (catalog
|
|
9808
|
+
* name plus the model's own badge) for anything that is not this plugin's
|
|
9809
|
+
* model, rather than drawing nothing for foreign rows. A picker whose every row
|
|
9810
|
+
* lost its name because a connector won the cell would be a much worse outcome
|
|
9811
|
+
* than a lost promotion chip.
|
|
9149
9812
|
*
|
|
9150
9813
|
* WHAT WINNING/HOLDING COSTS. This cell is `single`, so the other registrants'
|
|
9151
9814
|
* decorations on the rows this plugin claims are not composed. That is the
|
|
@@ -9163,7 +9826,7 @@ window.__ModuleLoader__.load({
|
|
|
9163
9826
|
* disposes its previous entry before every attempt. Priority alone would have
|
|
9164
9827
|
* made the throw rarer and harder to read, not absent.
|
|
9165
9828
|
*/
|
|
9166
|
-
const MODEL_LABEL_PRIORITY =
|
|
9829
|
+
const MODEL_LABEL_PRIORITY = -102;
|
|
9167
9830
|
/** The tone colours, mapped onto the same theme tokens the host's Tag paints. */
|
|
9168
9831
|
const HOST_BADGE_TONES = {
|
|
9169
9832
|
neutral: {
|
|
@@ -9407,7 +10070,7 @@ window.__ModuleLoader__.load({
|
|
|
9407
10070
|
* happens on every press and a shell that appears later is still found. See
|
|
9408
10071
|
* `settings-route.ts` for the finding that established which seam this is.
|
|
9409
10072
|
*/
|
|
9410
|
-
const onOpenSettings = () => openPluginSettingsPage(softGet);
|
|
10073
|
+
const onOpenSettings = () => openPluginSettingsPage(softGet, { label: () => t("nav.panel") });
|
|
9411
10074
|
const forms = softGet("configForms");
|
|
9412
10075
|
/**
|
|
9413
10076
|
* The card's settings scope, bound to whichever namespace the Host actually
|
|
@@ -9636,13 +10299,9 @@ window.__ModuleLoader__.load({
|
|
|
9636
10299
|
*/
|
|
9637
10300
|
function TraePanelIcon(props) {
|
|
9638
10301
|
const edge = typeof props.size === "number" && props.size > 0 ? props.size : 16;
|
|
9639
|
-
return (0, react.createElement)(
|
|
10302
|
+
return (0, react.createElement)(PluginIcon, {
|
|
9640
10303
|
className: "dsm-trae-panel-icon",
|
|
9641
|
-
|
|
9642
|
-
alt: "",
|
|
9643
|
-
width: edge,
|
|
9644
|
-
height: edge,
|
|
9645
|
-
"aria-hidden": "true"
|
|
10304
|
+
size: edge
|
|
9646
10305
|
});
|
|
9647
10306
|
}
|
|
9648
10307
|
/**
|
|
@@ -9664,14 +10323,10 @@ window.__ModuleLoader__.load({
|
|
|
9664
10323
|
*/
|
|
9665
10324
|
function SettingsSectionIcon(props) {
|
|
9666
10325
|
const edge = typeof props.size === "number" && props.size > 0 ? props.size : 16;
|
|
9667
|
-
return (0, react.createElement)(
|
|
10326
|
+
return (0, react.createElement)(PluginIcon, {
|
|
9668
10327
|
className: "dsm-trae-section-icon",
|
|
9669
|
-
|
|
9670
|
-
|
|
9671
|
-
width: edge,
|
|
9672
|
-
height: edge,
|
|
9673
|
-
style: { opacity: props.active === false ? .75 : 1 },
|
|
9674
|
-
"aria-hidden": "true"
|
|
10328
|
+
size: edge,
|
|
10329
|
+
style: { opacity: props.active === false ? .75 : 1 }
|
|
9675
10330
|
});
|
|
9676
10331
|
}
|
|
9677
10332
|
/**
|