dsh-connect-trae 4.10.0 → 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 +393 -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 +1053 -416
- 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
|
|
@@ -1627,7 +1896,7 @@ window.__ModuleLoader__.load({
|
|
|
1627
1896
|
* 这张卡同时画在三处,宽度与窗口毫无关系:输入框卡片、整页版(上限 860px)、
|
|
1628
1897
|
* 以及设置面板的内容列(1400px 屏上是 564px)。本文件里所有 @media 断点测的
|
|
1629
1898
|
* 都是**视口**,所以在设置面板里它们永远不触发——564px 的列拿到了五列桌面表格,
|
|
1630
|
-
* 每个单元格都在截断(实测账号列被压到 76px
|
|
1899
|
+
* 每个单元格都在截断(实测账号列被压到 76px,一个 9 位数字账号名只剩前 5 个字符)。
|
|
1631
1900
|
*
|
|
1632
1901
|
* container-type:inline-size 让下面的断点改测**这张表**的宽度,那才是行真正要
|
|
1633
1902
|
* 塞进去的宽度。
|
|
@@ -1653,7 +1922,23 @@ window.__ModuleLoader__.load({
|
|
|
1653
1922
|
reads as a selection control, and the checkbox beside it already is one. */
|
|
1654
1923
|
.dsm-trae-pool-row-current{background:rgba(86,134,254,.07);box-shadow:inset 3px 0 0 var(--dsw-alias-brand-primary,#5686fe)}
|
|
1655
1924
|
.dsm-trae-pool-row-ghost{opacity:.7}
|
|
1656
|
-
|
|
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}
|
|
1657
1942
|
.dsm-trae-pool-account{display:grid;grid-template-columns:auto minmax(0,1fr);align-items:center;gap:2px 8px;min-width:0}
|
|
1658
1943
|
.dsm-trae-pool-check{display:inline-flex;align-items:center;flex:none;grid-column:1;grid-row:1;cursor:pointer}
|
|
1659
1944
|
.dsm-trae-pool-check input{flex:none;margin:0;cursor:pointer;accent-color:var(--dsw-alias-brand-primary,#5686fe)}
|
|
@@ -1731,20 +2016,55 @@ window.__ModuleLoader__.load({
|
|
|
1731
2016
|
*
|
|
1732
2017
|
* .dsm-trae-pool-row-head 隐藏:它的标签描述的是已经不存在的轨道。 */
|
|
1733
2018
|
@container (max-width:700px){
|
|
1734
|
-
|
|
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}
|
|
1735
2027
|
.dsm-trae-pool-row-head{display:none}
|
|
1736
|
-
.
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
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}
|
|
1741
2061
|
/* THE PROBE CELL'S OWN COLUMN, collapsed to one line.
|
|
1742
2062
|
*
|
|
1743
2063
|
* 这一条是最容易漏掉的:.dsm-trae-pool-probe 只是个 min-width:0 的外层包装,
|
|
1744
2064
|
* 真正竖排的是它内部的 .dsm-trae-pool-probe-cell(flex-direction:column)。
|
|
1745
2065
|
* 只改外层包装的话,状态列仍然一句一行,被挤成「正常 / 测得 3 天前 / 来自测速 /
|
|
1746
2066
|
* upstream answered」四行——旁边只有 12px 间距,整行高度就被这一格撑到 100px
|
|
1747
|
-
*
|
|
2067
|
+
* 以上,账号名也跟着被压窄(实测截成前几个字符「用户7」)。
|
|
1748
2068
|
*
|
|
1749
2069
|
* 改成横排并允许在自己内部换行:这四个事实读起来本来就是一句话
|
|
1750
2070
|
* (「正常 · 测得 3 天前 · 来自测速 · upstream answered」),宽时从左排到右,
|
|
@@ -1754,7 +2074,7 @@ window.__ModuleLoader__.load({
|
|
|
1754
2074
|
*
|
|
1755
2075
|
* 宽的时候它是个三行网格(名字 / 标签 / 探针时间),第一列固定给勾选框。
|
|
1756
2076
|
* 在窄列里这三行没有理由继续各占一行——它们本来就是一句话
|
|
1757
|
-
* (「
|
|
2077
|
+
* (「demo-usr · 已在池中 · 测试于 11/03, 06:35」),横排后名字与这两条短事实
|
|
1758
2078
|
* 共享一行,只有真的放不下时才折行。勾选框仍然排在最前,并保持垂直居中对齐
|
|
1759
2079
|
* 到第一行基线(align-self:baseline 会让它沉到行底)。 */
|
|
1760
2080
|
.dsm-trae-pool-account{display:flex;flex-wrap:wrap;align-items:baseline;gap:2px 8px}
|
|
@@ -1818,7 +2138,7 @@ window.__ModuleLoader__.load({
|
|
|
1818
2138
|
.dsm-trae-section-title{margin:0;font-size:15px;font-weight:600;line-height:22px}
|
|
1819
2139
|
.dsm-trae-section-desc{margin:0;font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary,#999)}
|
|
1820
2140
|
.dsm-trae-panel-icon{display:block;border-radius:4px;flex:none}
|
|
1821
|
-
|
|
2141
|
+
` + seriesLayoutCss("trae");
|
|
1822
2142
|
/**
|
|
1823
2143
|
* Composer-row readout styles, injected by the readout itself.
|
|
1824
2144
|
*
|
|
@@ -2372,6 +2692,7 @@ window.__ModuleLoader__.load({
|
|
|
2372
2692
|
const base = regionPoolOf(settingsScope?.getSnapshot().value, panel);
|
|
2373
2693
|
return {
|
|
2374
2694
|
enabled: base.enabled === true,
|
|
2695
|
+
autoCheckin: base.autoCheckin === true,
|
|
2375
2696
|
targetModelId: base.targetModelId ?? pool.targetModelId ?? pool.staleTargetModelId ?? "",
|
|
2376
2697
|
memberAccountIds: [...base.memberAccountIds ?? []],
|
|
2377
2698
|
probeInputTokens: numberOr(base.probeInputTokens, numberOr(pool.probeInputTokens, 0))
|
|
@@ -2395,6 +2716,7 @@ window.__ModuleLoader__.load({
|
|
|
2395
2716
|
*/
|
|
2396
2717
|
const probeSupported = typeof pool.probeInputTokens === "number";
|
|
2397
2718
|
const [enabled, setEnabled] = (0, react.useState)(saved.enabled);
|
|
2719
|
+
const [autoCheckin, setAutoCheckin] = (0, react.useState)(saved.autoCheckin);
|
|
2398
2720
|
const [targetModelId, setTargetModelId] = (0, react.useState)(saved.targetModelId ?? "");
|
|
2399
2721
|
const [probeInputTokens, setProbeInputTokens] = (0, react.useState)(saved.probeInputTokens);
|
|
2400
2722
|
const [selected, setSelected] = (0, react.useState)(() => new Set(saved.memberAccountIds ?? []));
|
|
@@ -2446,8 +2768,11 @@ window.__ModuleLoader__.load({
|
|
|
2446
2768
|
pool,
|
|
2447
2769
|
knownIds
|
|
2448
2770
|
]);
|
|
2449
|
-
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);
|
|
2450
2772
|
const writable = settingsScope?.getSnapshot().writable === true;
|
|
2773
|
+
(0, react.useEffect)(() => {
|
|
2774
|
+
setAutoCheckin(saved.autoCheckin);
|
|
2775
|
+
}, [panel, saved.autoCheckin]);
|
|
2451
2776
|
const savedMemberKey = (0, react.useMemo)(() => [...saved.memberAccountIds ?? []].sort().join("\0"), [saved]);
|
|
2452
2777
|
(0, react.useEffect)(() => {
|
|
2453
2778
|
setEnabled(saved.enabled);
|
|
@@ -2485,6 +2810,7 @@ window.__ModuleLoader__.load({
|
|
|
2485
2810
|
const selectNone = () => setSelected(/* @__PURE__ */ new Set());
|
|
2486
2811
|
const discard = () => {
|
|
2487
2812
|
setEnabled(saved.enabled);
|
|
2813
|
+
setAutoCheckin(saved.autoCheckin);
|
|
2488
2814
|
setTargetModelId(saved.targetModelId ?? "");
|
|
2489
2815
|
setProbeInputTokens(saved.probeInputTokens);
|
|
2490
2816
|
setSelected(new Set(saved.memberAccountIds ?? []));
|
|
@@ -2499,13 +2825,14 @@ window.__ModuleLoader__.load({
|
|
|
2499
2825
|
try {
|
|
2500
2826
|
const next = {
|
|
2501
2827
|
enabled,
|
|
2828
|
+
autoCheckin,
|
|
2502
2829
|
...targetModelId === "" ? {} : { targetModelId },
|
|
2503
2830
|
memberAccountIds: [...selected],
|
|
2504
2831
|
...probeSupported ? { probeInputTokens } : {}
|
|
2505
2832
|
};
|
|
2506
2833
|
await writeSettingsField(settingsScope, "regions", nextRegionPool(settingsScope.getSnapshot().value, panel, next), (readBack) => {
|
|
2507
2834
|
const readPool = regionPoolOf(readBack, panel);
|
|
2508
|
-
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);
|
|
2509
2836
|
});
|
|
2510
2837
|
pushLog("ok", t("row.poolLogSaved"));
|
|
2511
2838
|
onChanged?.();
|
|
@@ -2782,39 +3109,82 @@ window.__ModuleLoader__.load({
|
|
|
2782
3109
|
}),
|
|
2783
3110
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2784
3111
|
className: "dsm-trae-pool-settings dsm-trae-pool-modebar",
|
|
2785
|
-
children: [
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
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
|
+
]
|
|
2818
3188
|
}),
|
|
2819
3189
|
pool.enabled === true && serving !== void 0 && serving.member !== true ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2820
3190
|
className: "dsm-trae-pool-note dsm-trae-pool-serving-note",
|
|
@@ -4039,96 +4409,97 @@ window.__ModuleLoader__.load({
|
|
|
4039
4409
|
* is precisely why this section has no 「保存」 of its own — the model catalog,
|
|
4040
4410
|
* which does, lives in its own section.
|
|
4041
4411
|
*/
|
|
4042
|
-
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" }) {
|
|
4043
4413
|
const writable = settingsScope?.getSnapshot().writable === true;
|
|
4044
4414
|
const signedIn = status.status === "signed-in";
|
|
4045
4415
|
const accounts = signedIn ? status.accounts : [];
|
|
4046
4416
|
const pool = signedIn ? status.pool : void 0;
|
|
4047
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.
|
|
4048
|
-
|
|
4049
|
-
|
|
4050
|
-
|
|
4051
|
-
|
|
4052
|
-
|
|
4053
|
-
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
4063
|
-
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
|
|
4071
|
-
|
|
4072
|
-
children: t(credentialRegionIsAi ? "row.showPointsInMainUiHintAi" : "row.showPointsInMainUiHint")
|
|
4073
|
-
})]
|
|
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")
|
|
4074
4442
|
})]
|
|
4075
|
-
})
|
|
4076
|
-
|
|
4077
|
-
|
|
4078
|
-
|
|
4079
|
-
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
|
|
4083
|
-
|
|
4084
|
-
className: "dsm-trae-pref-label",
|
|
4085
|
-
children: t("row.creditPositionLabel")
|
|
4086
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
4087
|
-
className: "dsm-trae-credit-position",
|
|
4088
|
-
value: regionOn ? creditPosition : "composer",
|
|
4089
|
-
disabled: !regionOn || !writable || savingPreferences,
|
|
4090
|
-
"aria-label": t("row.creditPositionAria", { region: panel === "cn" ? t("row.tabCn") : panel === "enterprise" ? t("row.tabEnterprise") : t("row.tabAi") }),
|
|
4091
|
-
onChange: (event) => {
|
|
4092
|
-
onCreditPositionChange(event.currentTarget.value === "stats" ? "stats" : "composer");
|
|
4093
|
-
},
|
|
4094
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
4095
|
-
value: "composer",
|
|
4096
|
-
children: t("row.creditPositionComposer")
|
|
4097
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
4098
|
-
value: "stats",
|
|
4099
|
-
children: t("row.creditPositionStats")
|
|
4100
|
-
})]
|
|
4101
|
-
})]
|
|
4102
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4103
|
-
className: "dsm-trae-pref-hint",
|
|
4104
|
-
children: t("row.creditPositionHint")
|
|
4105
|
-
})]
|
|
4106
|
-
})
|
|
4107
|
-
}),
|
|
4108
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
4109
|
-
className: "dsm-trae-pref",
|
|
4110
|
-
title: t("row.sidebarPanelHint"),
|
|
4111
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
4112
|
-
type: "checkbox",
|
|
4113
|
-
className: "dsm-trae-pref-check",
|
|
4114
|
-
checked: sidebarPanelOn,
|
|
4115
|
-
disabled: sidebarPanelBusy || savingPreferences,
|
|
4116
|
-
onChange: (event) => {
|
|
4117
|
-
onToggleSidebarPanel(event.currentTarget.checked);
|
|
4118
|
-
}
|
|
4119
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
4120
|
-
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",
|
|
4121
4452
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4122
4453
|
className: "dsm-trae-pref-label",
|
|
4123
|
-
children: t("row.
|
|
4124
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.
|
|
4125
|
-
className: "dsm-trae-
|
|
4126
|
-
|
|
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
|
+
})]
|
|
4127
4470
|
})]
|
|
4471
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4472
|
+
className: "dsm-trae-pref-hint",
|
|
4473
|
+
children: t("row.creditPositionHint")
|
|
4128
4474
|
})]
|
|
4129
4475
|
})
|
|
4130
|
-
|
|
4131
|
-
|
|
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: [
|
|
4132
4503
|
pool !== void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
4133
4504
|
className: "dsm-trae-accounts",
|
|
4134
4505
|
"aria-label": t("row.accountsTitle"),
|
|
@@ -4334,9 +4705,9 @@ window.__ModuleLoader__.load({
|
|
|
4334
4705
|
className: "dsm-trae-usage-error",
|
|
4335
4706
|
children: t("row.checkinDisabled")
|
|
4336
4707
|
}) : null,
|
|
4337
|
-
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", {
|
|
4338
4709
|
className: "dsm-trae-usage-error",
|
|
4339
|
-
children: t("row.
|
|
4710
|
+
children: t("row.checkinStatusError", { message: status.checkinError })
|
|
4340
4711
|
})
|
|
4341
4712
|
] }) : null
|
|
4342
4713
|
] });
|
|
@@ -5256,7 +5627,6 @@ window.__ModuleLoader__.load({
|
|
|
5256
5627
|
if (mounted.current) {
|
|
5257
5628
|
const message = error instanceof Error ? error.message : t("row.requestFailed");
|
|
5258
5629
|
setRescanNote(t("row.accountsRescanFailed", { message }));
|
|
5259
|
-
setWriteError(message);
|
|
5260
5630
|
}
|
|
5261
5631
|
} finally {
|
|
5262
5632
|
if (mounted.current) setBusy(false);
|
|
@@ -6160,9 +6530,22 @@ window.__ModuleLoader__.load({
|
|
|
6160
6530
|
}, item);
|
|
6161
6531
|
})
|
|
6162
6532
|
}),
|
|
6163
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
6164
|
-
className: "dsm-trae-
|
|
6165
|
-
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
|
+
]
|
|
6166
6549
|
}),
|
|
6167
6550
|
writeError === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
6168
6551
|
className: "dsm-trae-usage-error",
|
|
@@ -6203,6 +6586,18 @@ window.__ModuleLoader__.load({
|
|
|
6203
6586
|
},
|
|
6204
6587
|
children: t("row.panelModels")
|
|
6205
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
|
+
}),
|
|
6206
6601
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
6207
6602
|
type: "button",
|
|
6208
6603
|
role: "tab",
|
|
@@ -6226,6 +6621,7 @@ window.__ModuleLoader__.load({
|
|
|
6226
6621
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TraeAccountPanel, {
|
|
6227
6622
|
t,
|
|
6228
6623
|
settingsScope,
|
|
6624
|
+
section: "accounts",
|
|
6229
6625
|
panel: activeRegion,
|
|
6230
6626
|
status,
|
|
6231
6627
|
statusLabel: label,
|
|
@@ -6293,6 +6689,68 @@ window.__ModuleLoader__.load({
|
|
|
6293
6689
|
}
|
|
6294
6690
|
})
|
|
6295
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
|
+
}),
|
|
6296
6754
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6297
6755
|
className: "dsm-trae-panel",
|
|
6298
6756
|
role: "tabpanel",
|
|
@@ -6896,11 +7354,7 @@ window.__ModuleLoader__.load({
|
|
|
6896
7354
|
className: "dsm-trae-page-back-caret"
|
|
6897
7355
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("row.pageBack") })]
|
|
6898
7356
|
}),
|
|
6899
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("
|
|
6900
|
-
className: "dsm-trae-page-icon",
|
|
6901
|
-
src: TRAE_PLUGIN_ICON,
|
|
6902
|
-
alt: ""
|
|
6903
|
-
}),
|
|
7357
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(PluginIcon, { className: "dsm-trae-page-icon" }),
|
|
6904
7358
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6905
7359
|
className: "dsm-trae-page-title",
|
|
6906
7360
|
children: title
|
|
@@ -6937,6 +7391,14 @@ window.__ModuleLoader__.load({
|
|
|
6937
7391
|
}) : null;
|
|
6938
7392
|
if (pageSurface) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6939
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
|
+
},
|
|
6940
7402
|
children: [
|
|
6941
7403
|
pageHead,
|
|
6942
7404
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
@@ -6972,11 +7434,7 @@ window.__ModuleLoader__.load({
|
|
|
6972
7434
|
setCardOpen(!open);
|
|
6973
7435
|
},
|
|
6974
7436
|
children: [
|
|
6975
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("
|
|
6976
|
-
className: "dsm-plugin-card-icon",
|
|
6977
|
-
src: TRAE_PLUGIN_ICON,
|
|
6978
|
-
alt: ""
|
|
6979
|
-
}),
|
|
7437
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(PluginIcon, { className: "dsm-plugin-card-icon" }),
|
|
6980
7438
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
6981
7439
|
className: "dsm-plugin-card-head",
|
|
6982
7440
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
@@ -8011,41 +8469,178 @@ window.__ModuleLoader__.load({
|
|
|
8011
8469
|
/** The shipped slot whose store seat is the settings shell's state handle. */
|
|
8012
8470
|
const SETTINGS_SLOT = "sidebar.settings";
|
|
8013
8471
|
/**
|
|
8014
|
-
*
|
|
8015
|
-
* plugin's section.
|
|
8472
|
+
* The sidebar's settings trigger: dialog semantics plus an expanded state.
|
|
8016
8473
|
*
|
|
8017
|
-
*
|
|
8018
|
-
*
|
|
8019
|
-
*
|
|
8020
|
-
*
|
|
8021
|
-
*
|
|
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.
|
|
8022
8488
|
*/
|
|
8023
|
-
|
|
8024
|
-
|
|
8025
|
-
|
|
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.
|
|
8521
|
+
*/
|
|
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;
|
|
8026
8530
|
let seat;
|
|
8027
8531
|
try {
|
|
8028
8532
|
seat = slots.entries(SETTINGS_SLOT)[0]?.store;
|
|
8029
8533
|
} catch {
|
|
8030
|
-
return
|
|
8534
|
+
return;
|
|
8031
8535
|
}
|
|
8032
|
-
if (seat === null || typeof seat !== "object") return
|
|
8536
|
+
if (seat === null || typeof seat !== "object") return void 0;
|
|
8033
8537
|
const handle = seat;
|
|
8034
|
-
if (typeof handle.create !== "function") return
|
|
8538
|
+
if (typeof handle.create !== "function") return void 0;
|
|
8035
8539
|
try {
|
|
8036
8540
|
const instance = handle.create();
|
|
8037
8541
|
const openSection = instance?.actions?.openSection;
|
|
8038
8542
|
if (typeof openSection === "function") {
|
|
8039
|
-
openSection(
|
|
8040
|
-
return
|
|
8543
|
+
openSection(sectionId);
|
|
8544
|
+
return "opened";
|
|
8041
8545
|
}
|
|
8042
8546
|
const open = instance?.actions?.open;
|
|
8043
8547
|
if (typeof open === "function") {
|
|
8044
8548
|
open();
|
|
8045
|
-
return
|
|
8549
|
+
return "shell";
|
|
8046
8550
|
}
|
|
8047
8551
|
} catch {}
|
|
8048
|
-
|
|
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
|
+
}
|
|
8049
8644
|
}
|
|
8050
8645
|
//#endregion
|
|
8051
8646
|
//#region src/client/locales.ts
|
|
@@ -8055,46 +8650,64 @@ window.__ModuleLoader__.load({
|
|
|
8055
8650
|
* two plugins share one external-presentation language.
|
|
8056
8651
|
*/
|
|
8057
8652
|
const en = {
|
|
8058
|
-
"row.
|
|
8059
|
-
"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.",
|
|
8060
8671
|
"row.expand": "Expand",
|
|
8061
8672
|
"row.collapse": "Collapse",
|
|
8062
8673
|
"row.tabCn": "Domestic",
|
|
8063
8674
|
"row.tabEnterprise": "Enterprise",
|
|
8064
8675
|
"row.tabAi": "Global",
|
|
8065
|
-
"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.",
|
|
8066
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.",
|
|
8067
|
-
"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.",
|
|
8068
8679
|
"row.tabSwitchAria": "Offer the {region} provider to DSH",
|
|
8069
|
-
"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.",
|
|
8070
8681
|
"row.panelAria": "Card sections",
|
|
8071
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.",
|
|
8072
8685
|
"row.panelModels": "Models",
|
|
8073
8686
|
"row.panelDiag": "Diagnostics",
|
|
8074
|
-
"row.diagRegion": "
|
|
8687
|
+
"row.diagRegion": "Region",
|
|
8075
8688
|
"row.diagProvider": "Provider id",
|
|
8076
8689
|
"row.diagAccount": "Serving account",
|
|
8077
|
-
"row.diagToken": "
|
|
8690
|
+
"row.diagToken": "Sign-in expires",
|
|
8078
8691
|
"row.diagRefresh": "Re-sign-in deadline",
|
|
8079
8692
|
"row.diagRefreshNone": "this credential carries none",
|
|
8080
|
-
"row.diagCatalog": "Models in catalog",
|
|
8081
|
-
"row.diagEnabled": "
|
|
8693
|
+
"row.diagCatalog": "Models in the catalog",
|
|
8694
|
+
"row.diagEnabled": "Enabled models",
|
|
8082
8695
|
"row.diagPool": "Account pool",
|
|
8083
|
-
"row.diagPoolOn": "on · {count}
|
|
8696
|
+
"row.diagPoolOn": "on · {count} accounts",
|
|
8084
8697
|
"row.diagPoolOff": "off",
|
|
8085
8698
|
"row.diagCheckin": "Daily check-in",
|
|
8086
8699
|
"row.diagCheckinOn": "supported",
|
|
8087
8700
|
"row.diagCheckinOff": "not offered here",
|
|
8088
8701
|
"row.diagRaw": "Raw chat channel",
|
|
8089
8702
|
"row.diagRawOff": "not checked",
|
|
8090
|
-
"row.diagFailures": "Last
|
|
8091
|
-
"row.diagNoFailures": "
|
|
8703
|
+
"row.diagFailures": "Last failure",
|
|
8704
|
+
"row.diagNoFailures": "Nothing reported.",
|
|
8092
8705
|
"row.diagQuarantine": "Quarantined copies",
|
|
8093
8706
|
"row.diagQuarantineNone": "none",
|
|
8094
|
-
"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.",
|
|
8095
8708
|
"row.settingsWriteFailed": "The setting was not saved: {message}",
|
|
8096
8709
|
"row.signedOut": "Not signed in",
|
|
8097
|
-
"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.",
|
|
8098
8711
|
"row.unsupportedRegionTitle": "US region is not supported yet",
|
|
8099
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.",
|
|
8100
8713
|
"row.diagUnsupportedRegion": "Unsupported region",
|
|
@@ -8102,7 +8715,7 @@ window.__ModuleLoader__.load({
|
|
|
8102
8715
|
"row.searchedHint": "No sign-in was found. These locations were probed; if your Trae stores its login elsewhere, please report the path.",
|
|
8103
8716
|
"row.searchedMore": "Show {count} more",
|
|
8104
8717
|
"row.quarantineTitle": "Quarantined credential copies",
|
|
8105
|
-
"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.",
|
|
8106
8719
|
"row.quarantineAccounts": "{count} account(s)",
|
|
8107
8720
|
"row.quarantineAccountsUnknown": "account count unreadable",
|
|
8108
8721
|
"row.quarantineBytes": "{bytes} bytes",
|
|
@@ -8112,7 +8725,7 @@ window.__ModuleLoader__.load({
|
|
|
8112
8725
|
"row.sourceDesktop": "desktop app",
|
|
8113
8726
|
"row.sourceCli": "Trae CLI",
|
|
8114
8727
|
"row.signedIn": "Signed in: {accountName}",
|
|
8115
|
-
"row.tokenExpiry": "Access token expires {expiresAt}
|
|
8728
|
+
"row.tokenExpiry": "Access token expires at {expiresAt}; the plugin will attempt to renew it automatically",
|
|
8116
8729
|
"row.refreshTokenExpiring": "Sign in to Trae again by {expiresAt} ({days} day(s) left) — automatic renewal stops after that.",
|
|
8117
8730
|
"row.refreshTokenLapsed": "Automatic renewal has stopped: the Trae sign-in expired {expiresAt}. Sign in to Trae again to restore it.",
|
|
8118
8731
|
"row.requestFailed": "Request failed",
|
|
@@ -8148,26 +8761,26 @@ window.__ModuleLoader__.load({
|
|
|
8148
8761
|
"row.refreshCredits": "Refresh usage",
|
|
8149
8762
|
"row.refreshing": "Refreshing…",
|
|
8150
8763
|
"row.accountsTitle": "Trae account",
|
|
8151
|
-
"row.accountsHint": "
|
|
8152
|
-
"row.transferTitle": "
|
|
8153
|
-
"row.transferExport": "Export
|
|
8154
|
-
"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",
|
|
8155
8768
|
"row.transferCancel": "Cancel",
|
|
8156
8769
|
"row.transferSelectAll": "Select all",
|
|
8157
|
-
"row.transferExportPick": "Choose
|
|
8158
|
-
"row.transferExportConfirm": "Export {count}",
|
|
8159
|
-
"row.transferExported": "Exported {count} account
|
|
8160
|
-
"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…",
|
|
8161
8774
|
"row.transferImportPick": "This file holds {total} record(s). Ticked records are added as plugin-owned copies; the Trae app is not touched.",
|
|
8162
|
-
"row.transferImportConfirm": "Import {count}",
|
|
8775
|
+
"row.transferImportConfirm": "Import {count} account(s)",
|
|
8163
8776
|
"row.transferImported": "Imported {imported} account copy/copies, skipped {skipped}.",
|
|
8164
8777
|
"row.transferImporting": "Importing…",
|
|
8165
8778
|
"row.transferReading": "Reading the file…",
|
|
8166
|
-
"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.",
|
|
8167
8780
|
"row.transferError": "Import/export failed: {message}",
|
|
8168
8781
|
"row.transferVeilHint": "The account list refreshes when this finishes.",
|
|
8169
8782
|
"row.transferUnnamed": "Unnamed account",
|
|
8170
|
-
"row.transferNoToken": "no token
|
|
8783
|
+
"row.transferNoToken": "no token in this record",
|
|
8171
8784
|
"row.accountsRescan": "Detect accounts again",
|
|
8172
8785
|
"row.accountsScanning": "Detecting…",
|
|
8173
8786
|
"row.accountsLoading": "Loading your accounts…",
|
|
@@ -8180,7 +8793,7 @@ window.__ModuleLoader__.load({
|
|
|
8180
8793
|
"row.accountColumnCheckin": "Check-in",
|
|
8181
8794
|
"row.accountBalance": "{credits} credits",
|
|
8182
8795
|
"row.balanceConsoleOnly": "In the enterprise console",
|
|
8183
|
-
"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.",
|
|
8184
8797
|
"row.sourceDsh": "plugin copy",
|
|
8185
8798
|
"row.modelsTitle": "Models",
|
|
8186
8799
|
"row.modelsSummary": "{count} enabled",
|
|
@@ -8194,7 +8807,7 @@ window.__ModuleLoader__.load({
|
|
|
8194
8807
|
"row.modelsViewLabel": "Model scope",
|
|
8195
8808
|
"row.modelsViewCommon": "Common channels · {count}",
|
|
8196
8809
|
"row.modelsViewAll": "All · {count}",
|
|
8197
|
-
"row.modelsViewCommonHint": "Models
|
|
8810
|
+
"row.modelsViewCommonHint": "Models offered through solo_work_remote or solo_work_lite.",
|
|
8198
8811
|
"row.modelsViewAllHint": "Also includes models only offered by a specialist channel: solo_coder, chat_v3, solo_agent_remote.",
|
|
8199
8812
|
"row.modelsViewShowAll": "Show all",
|
|
8200
8813
|
"row.modelsSearchOutsideView": "No match for 「{query}」 on the common channels; the full catalog has {count}.",
|
|
@@ -8208,20 +8821,20 @@ window.__ModuleLoader__.load({
|
|
|
8208
8821
|
"row.modelsTestEnabled": "Test enabled models",
|
|
8209
8822
|
"row.modelsTestAll": "Test all models",
|
|
8210
8823
|
"row.modelsTesting": "Testing {done}/{total}…",
|
|
8211
|
-
"row.modelsTestHint": "
|
|
8212
|
-
"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.",
|
|
8213
8826
|
"row.showPointsInMainUi": "Show credits in the composer row",
|
|
8214
|
-
"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.",
|
|
8215
8828
|
"row.drawImage": "Let the model draw images (trae_draw_image)",
|
|
8216
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.",
|
|
8217
8830
|
"row.drawImageHintEnterprise": "Not available on the enterprise panel: that path bills through the tenant gateway and has not been verified.",
|
|
8218
|
-
"row.drawImageHintAi": "
|
|
8219
|
-
"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.",
|
|
8220
8833
|
"row.creditPositionLabel": "position",
|
|
8221
8834
|
"row.creditPositionComposer": "composer toolbar",
|
|
8222
8835
|
"row.creditPositionStats": "below the input box",
|
|
8223
8836
|
"row.creditPositionAria": "Credit readout position for {region}",
|
|
8224
|
-
"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.",
|
|
8225
8838
|
"composer.switchTo": "Switch to {account}",
|
|
8226
8839
|
"composer.noAccounts": "No account in this region",
|
|
8227
8840
|
"composer.panelTitle": "Trae credits",
|
|
@@ -8263,11 +8876,11 @@ window.__ModuleLoader__.load({
|
|
|
8263
8876
|
"row.settingsDirty": "Unsaved changes",
|
|
8264
8877
|
"row.modelsTestEmpty": "Enable at least one model first.",
|
|
8265
8878
|
"row.contextAllMid": "Switch all to 500K",
|
|
8266
|
-
"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.",
|
|
8267
8880
|
"row.contextAllMax": "Switch all to Max",
|
|
8268
|
-
"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.",
|
|
8269
8882
|
"row.contextAllDefault": "Restore default context",
|
|
8270
|
-
"row.contextAllDefaultHint": "
|
|
8883
|
+
"row.contextAllDefaultHint": "Clear this panel's custom context budgets and use the Trae catalog defaults. Click Save to apply.",
|
|
8271
8884
|
"row.modelsTestError": "Test failed: {message}",
|
|
8272
8885
|
"row.modelsTestDone": "{available} of {total} answered.",
|
|
8273
8886
|
"row.probeAvailable": "works",
|
|
@@ -8302,21 +8915,21 @@ window.__ModuleLoader__.load({
|
|
|
8302
8915
|
"row.modelCapabilityPending": "Image input follows Trae's own multimodal flag, plus anything you tick yourself.",
|
|
8303
8916
|
"row.poolTitle": "Account pool",
|
|
8304
8917
|
"row.poolEnabled": "Enable the account pool",
|
|
8305
|
-
"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.",
|
|
8306
8919
|
"row.poolCurrentHeader": "Billing now: {account}",
|
|
8307
8920
|
"row.poolModeAuto": "pool picks",
|
|
8308
8921
|
"row.poolModeManual": "you pick",
|
|
8309
8922
|
"row.poolMember": "in pool",
|
|
8310
|
-
"row.poolNotMember": "
|
|
8311
|
-
"row.poolBusyHint": "
|
|
8312
|
-
"row.poolTestAll": "Test
|
|
8923
|
+
"row.poolNotMember": "Not in pool",
|
|
8924
|
+
"row.poolBusyHint": "Running one account at a time…",
|
|
8925
|
+
"row.poolTestAll": "Test selected",
|
|
8313
8926
|
"row.poolTesting": "Testing…",
|
|
8314
|
-
"row.poolOffNotice": "The pool is off
|
|
8315
|
-
"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.",
|
|
8316
8929
|
"row.poolNoCandidateEmpty": "No pool members are selected yet.",
|
|
8317
|
-
"row.poolNoCandidateEmptyHint": "
|
|
8930
|
+
"row.poolNoCandidateEmptyHint": "Select accounts below and save the pool settings to add them to the pool.",
|
|
8318
8931
|
"row.poolNoCandidateUnusable": "Every selected member is unavailable right now.",
|
|
8319
|
-
"row.poolNoCandidateHint": "
|
|
8932
|
+
"row.poolNoCandidateHint": "Requests will try the saved account binding while the pool has no usable member. Member status: ",
|
|
8320
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.",
|
|
8321
8934
|
"row.poolMembersTitle": "Accounts in this pool",
|
|
8322
8935
|
"row.poolRescan": "Re-detect accounts",
|
|
@@ -8327,59 +8940,59 @@ window.__ModuleLoader__.load({
|
|
|
8327
8940
|
"row.poolSettingsNote": "Preferences below take effect when you save; test results are written by the plugin and are not affected by that button.",
|
|
8328
8941
|
"row.poolSelectedCount": "Selected {count} / {total}",
|
|
8329
8942
|
"row.poolNoCopyTag": "no copy here",
|
|
8330
|
-
"row.poolCopyFile": "
|
|
8331
|
-
"row.poolNoCopyTestHint": "
|
|
8332
|
-
"row.poolSelectAll": "
|
|
8333
|
-
"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",
|
|
8334
8947
|
"row.poolColumnAccount": "Account",
|
|
8335
8948
|
"row.poolColumnCredits": "Credits",
|
|
8336
8949
|
"row.poolColumnProbe": "Status",
|
|
8337
8950
|
"row.poolColumnCheckin": "Check-in",
|
|
8338
|
-
"row.poolGeneralLabel": "
|
|
8339
|
-
"row.poolWorkHint": "
|
|
8951
|
+
"row.poolGeneralLabel": "Credits",
|
|
8952
|
+
"row.poolWorkHint": "DSH chat uses the credits balance. Work credits cannot be used for these requests.",
|
|
8340
8953
|
"row.poolCreditNone": "—",
|
|
8341
|
-
"row.poolTestedAt": "
|
|
8342
|
-
"row.poolNeverTested": "
|
|
8343
|
-
"row.poolRetryAt": "
|
|
8954
|
+
"row.poolTestedAt": "Tested {at}",
|
|
8955
|
+
"row.poolNeverTested": "Untested",
|
|
8956
|
+
"row.poolRetryAt": "Retry after {at}",
|
|
8344
8957
|
"row.poolRetryUnknown": "retry time unknown",
|
|
8345
|
-
"row.poolTargetCurrentPreferred": "Current: your choice
|
|
8346
|
-
"row.poolTargetCurrentFree": "Current: free model
|
|
8347
|
-
"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}",
|
|
8348
8961
|
"row.poolTargetStaleOption": "{model} (no longer offered)",
|
|
8349
|
-
"row.poolTargetStaleClear": "
|
|
8962
|
+
"row.poolTargetStaleClear": "Switch back to automatic",
|
|
8350
8963
|
"row.poolTargetNone": "No free model available for this panel",
|
|
8351
|
-
"row.poolTargetNoneHint": "
|
|
8352
|
-
"row.poolActionNoteTestNone": "No free model
|
|
8353
|
-
"row.poolActionNoteNoMembers": "
|
|
8354
|
-
"row.poolTargetAutoOption": "
|
|
8355
|
-
"row.poolTargetLabel": "
|
|
8356
|
-
"row.poolTargetHint": "
|
|
8357
|
-
"row.poolProbeSizeLabel": "
|
|
8358
|
-
"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.",
|
|
8359
8972
|
"row.poolProbeSizeDefault": "Minimal (default)",
|
|
8360
8973
|
"row.poolProbeSizeOption": "{wan}0k tokens",
|
|
8361
8974
|
"row.poolSettingsTitle": "More settings",
|
|
8362
8975
|
"row.poolMoreRulesTitle": "Account copies & saving rules",
|
|
8363
|
-
"row.poolManualAccountLabel": "
|
|
8976
|
+
"row.poolManualAccountLabel": "Account in use",
|
|
8364
8977
|
"row.poolManualAccountNone": "No account in effect",
|
|
8365
|
-
"row.poolDirty": "
|
|
8978
|
+
"row.poolDirty": "● Unsaved changes",
|
|
8366
8979
|
"row.poolSaved": "Save",
|
|
8367
8980
|
"row.poolSaving": "Saving…",
|
|
8368
|
-
"row.poolDiscard": "Discard",
|
|
8981
|
+
"row.poolDiscard": "Discard changes",
|
|
8369
8982
|
"row.poolSaveFailed": "Save failed: {message}",
|
|
8370
8983
|
"row.poolGhostMembers": "{count} saved member(s) no longer resolve to a local sign-in: {names}",
|
|
8371
|
-
"row.poolUnsavedMembers": "
|
|
8984
|
+
"row.poolUnsavedMembers": "Selection changed. Save to apply.",
|
|
8372
8985
|
"row.poolRowTest": "Test",
|
|
8373
8986
|
"row.poolLogTitle": "Activity",
|
|
8374
8987
|
"row.poolLogClear": "Clear",
|
|
8375
8988
|
"row.poolLogEmpty": "No pool activity yet.",
|
|
8376
|
-
"row.poolLogTestStart": "
|
|
8377
|
-
"row.poolLogTestRow": "{accountName}: {outcome}
|
|
8378
|
-
"row.poolLogTestRowMalformed": "{accountName}:
|
|
8379
|
-
"row.poolLogTestDone": "Test finished
|
|
8380
|
-
"row.poolLogBatchFailed": "
|
|
8381
|
-
"row.poolLogTimeout": "The test
|
|
8382
|
-
"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",
|
|
8383
8996
|
"row.poolCheckedIn": "Checked in",
|
|
8384
8997
|
"row.poolNotCheckedIn": "Not checked in",
|
|
8385
8998
|
"row.poolCheckinUnknown": "Unknown",
|
|
@@ -8395,16 +9008,16 @@ window.__ModuleLoader__.load({
|
|
|
8395
9008
|
"row.poolProbeUnavailable": "unavailable",
|
|
8396
9009
|
"row.poolProbeNotFound": "not served",
|
|
8397
9010
|
"row.poolProbeFailed": "failed",
|
|
8398
|
-
"row.poolProbeSourceUnknown": "
|
|
8399
|
-
"row.poolProbeSourceLive": "
|
|
8400
|
-
"row.poolProbeSourceTest": "
|
|
9011
|
+
"row.poolProbeSourceUnknown": "source unknown",
|
|
9012
|
+
"row.poolProbeSourceLive": "hit by a live request",
|
|
9013
|
+
"row.poolProbeSourceTest": "tested",
|
|
8401
9014
|
"row.poolProbeModel": "model {model}",
|
|
8402
|
-
"row.poolProbeModelUnknown": "model
|
|
9015
|
+
"row.poolProbeModelUnknown": "model not recorded",
|
|
8403
9016
|
"row.poolExcludedUnusable": "unusable",
|
|
8404
9017
|
"row.poolTokenExpired": "sign-in expired",
|
|
8405
9018
|
"row.poolExcludedRateLimited": "rate limited",
|
|
8406
9019
|
"row.poolExcludedModelBusy": "model busy",
|
|
8407
|
-
"row.poolExcludedOutOfCredit": "
|
|
9020
|
+
"row.poolExcludedOutOfCredit": "Out of credits",
|
|
8408
9021
|
"row.poolExcludedCredentialRejected": "sign-in rejected",
|
|
8409
9022
|
"row.poolExcludedPolicyRejected": "policy rejected",
|
|
8410
9023
|
"row.poolExcludedPlanGated": "needs a higher plan",
|
|
@@ -8415,18 +9028,18 @@ window.__ModuleLoader__.load({
|
|
|
8415
9028
|
"row.poolAgoMin": "{n} min ago",
|
|
8416
9029
|
"row.poolAgoHour": "{n} h ago",
|
|
8417
9030
|
"row.poolAgoDay": "{n} d ago",
|
|
8418
|
-
"row.poolErrOrigin": "
|
|
8419
|
-
"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.",
|
|
8420
9033
|
"row.poolErrMethod": "the pool does not accept that request method",
|
|
8421
9034
|
"row.poolErrBadRequest": "the pool refused the request",
|
|
8422
|
-
"row.poolErrNoMembers": "
|
|
8423
|
-
"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.",
|
|
8424
9037
|
"row.poolErrCheckinUnsupported": "this panel does not offer a daily check-in",
|
|
8425
9038
|
"row.poolErrTargetStale": "the saved target model is no longer offered",
|
|
8426
|
-
"row.poolErrNoFreeModel": "
|
|
9039
|
+
"row.poolErrNoFreeModel": "No free model is available in this region. Refresh the catalog or select a test model manually before retrying.",
|
|
8427
9040
|
"row.poolErrConflict": "the pool refused the request",
|
|
8428
9041
|
"row.poolErrGeneric": "pool request failed (HTTP {status})",
|
|
8429
|
-
"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.",
|
|
8430
9043
|
"row.poolLogSaved": "Pool settings saved.",
|
|
8431
9044
|
"row.poolLogSaveFailed": "Could not save the pool settings.",
|
|
8432
9045
|
"row.poolLogNoMembers": "Nothing to do — no pool members are selected.",
|
|
@@ -8443,8 +9056,8 @@ window.__ModuleLoader__.load({
|
|
|
8443
9056
|
"row.poolRowDeleted": "Deleted the credential copy of {accountName}.",
|
|
8444
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.",
|
|
8445
9058
|
"row.poolRowDeletedSignedOut": "Deleted {accountName} and signed it out of {apps}.",
|
|
8446
|
-
"row.poolRowDeleteAppRunning": "
|
|
8447
|
-
"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.",
|
|
8448
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.",
|
|
8449
9062
|
"row.poolRowDeleteStillSigned": "removed this copy, but {accountName} is still signed in to Trae",
|
|
8450
9063
|
"row.poolRowDeleteNoCopy": "{accountName} had no plugin copy — only its Trae app login",
|
|
@@ -8453,67 +9066,85 @@ window.__ModuleLoader__.load({
|
|
|
8453
9066
|
"nav.panel": "Trae",
|
|
8454
9067
|
"row.pageBack": "Back to conversation",
|
|
8455
9068
|
"row.sidebarPanelLabel": "Show Trae in the sidebar",
|
|
8456
|
-
"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."
|
|
8457
9070
|
};
|
|
8458
9071
|
const zh = {
|
|
8459
|
-
"row.
|
|
8460
|
-
"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 国内版、企业版和国际版模型。可管理账号、选择模型、查询积分和领取每日签到奖励。刷新模型目录时,插件同时更新积分倍率。",
|
|
8461
9090
|
"row.expand": "展开",
|
|
8462
9091
|
"row.collapse": "收起",
|
|
8463
9092
|
"row.tabCn": "国内版",
|
|
8464
9093
|
"row.tabEnterprise": "企业版",
|
|
8465
9094
|
"row.tabAi": "国际版",
|
|
8466
|
-
"row.tabHint": "
|
|
8467
|
-
"row.tabEnterpriseHint": "
|
|
8468
|
-
"row.tabSwitchHint": "
|
|
8469
|
-
"row.tabSwitchAria": "
|
|
8470
|
-
"row.tabOffNotice": "
|
|
8471
|
-
"row.panelAria": "
|
|
9095
|
+
"row.tabHint": "国内版、企业版和国际版可同时启用。切换上方版本页签,可分别查看和管理各版本的账号、积分和模型。",
|
|
9096
|
+
"row.tabEnterpriseHint": "企业版请求使用 Trae CN 账号的租户额度,失败时直接显示错误,不会改用个人积分重试。",
|
|
9097
|
+
"row.tabSwitchHint": "关闭此开关后,插件会从模型列表中隐藏该区域的模型,并保留账号和设置。再次打开开关即可恢复。",
|
|
9098
|
+
"row.tabSwitchAria": "启用{region}模型",
|
|
9099
|
+
"row.tabOffNotice": "该区域已关闭,账号和设置已保留。勾选上方开关可恢复模型。",
|
|
9100
|
+
"row.panelAria": "卡片分区",
|
|
8472
9101
|
"row.panelAccounts": "账号",
|
|
9102
|
+
"row.panelCapabilities": "能力",
|
|
9103
|
+
"row.panelCapabilitiesHint": "插件可以替你做什么。这些开关点一下立即生效 —— 开关没有保存按钮。",
|
|
8473
9104
|
"row.panelModels": "模型",
|
|
8474
9105
|
"row.panelDiag": "诊断",
|
|
8475
|
-
"row.diagRegion": "
|
|
9106
|
+
"row.diagRegion": "区域",
|
|
8476
9107
|
"row.diagProvider": "供应商 id",
|
|
8477
|
-
"row.diagAccount": "
|
|
8478
|
-
"row.diagToken": "
|
|
9108
|
+
"row.diagAccount": "当前使用账号",
|
|
9109
|
+
"row.diagToken": "登录有效期至",
|
|
8479
9110
|
"row.diagRefresh": "重新登录最后期限",
|
|
8480
9111
|
"row.diagRefreshNone": "该凭据不携带",
|
|
8481
|
-
"row.diagCatalog": "
|
|
8482
|
-
"row.diagEnabled": "
|
|
9112
|
+
"row.diagCatalog": "目录中的模型",
|
|
9113
|
+
"row.diagEnabled": "已启用的模型",
|
|
8483
9114
|
"row.diagPool": "账号池",
|
|
8484
|
-
"row.diagPoolOn": "
|
|
8485
|
-
"row.diagPoolOff": "
|
|
9115
|
+
"row.diagPoolOn": "开启 · {count} 个账号",
|
|
9116
|
+
"row.diagPoolOff": "关闭",
|
|
8486
9117
|
"row.diagCheckin": "每日签到",
|
|
8487
9118
|
"row.diagCheckinOn": "支持",
|
|
8488
9119
|
"row.diagCheckinOff": "本面板不提供",
|
|
8489
9120
|
"row.diagRaw": "Raw 会话通道",
|
|
8490
9121
|
"row.diagRawOff": "未检测",
|
|
8491
|
-
"row.diagFailures": "
|
|
8492
|
-
"row.diagNoFailures": "
|
|
9122
|
+
"row.diagFailures": "最近一次失败",
|
|
9123
|
+
"row.diagNoFailures": "没有报错。",
|
|
8493
9124
|
"row.diagQuarantine": "损坏副本留存",
|
|
8494
9125
|
"row.diagQuarantineNone": "无",
|
|
8495
|
-
"row.diagHint": "
|
|
9126
|
+
"row.diagHint": "这里显示本面板最近一次刷新得到的状态,可用于问题反馈;分享前请隐去账号标识和本机路径中的个人信息。",
|
|
8496
9127
|
"row.settingsWriteFailed": "设置未能保存:{message}",
|
|
8497
9128
|
"row.signedOut": "未登录",
|
|
8498
|
-
"row.signedOutHint": "
|
|
9129
|
+
"row.signedOutHint": "请先登录 Trae 桌面端,再点击「重新检测账号」,将登录凭据保存为插件副本。",
|
|
8499
9130
|
"row.unsupportedRegionTitle": "美国区(US)暂不支持",
|
|
8500
|
-
"row.unsupportedRegionHint": "本机有一个 Trae 账号属于美国区(userRegion \"US\" / 主机 *.traeapi.us
|
|
9131
|
+
"row.unsupportedRegionHint": "本机有一个 Trae 账号属于美国区(userRegion \"US\" / 主机 *.traeapi.us)。本版本尚未支持该区,因此不会使用这个账号,也不会把请求发往新加坡网关。重新登录不会改变账号所属区域。请在该面板改用国内版或新加坡区账号(或使用 Trae 国内版客户端)。",
|
|
8501
9132
|
"row.diagUnsupportedRegion": "未支持的区域",
|
|
8502
9133
|
"row.searchedTitle": "已检查的路径",
|
|
8503
9134
|
"row.searchedHint": "未找到登录信息。以下是插件探测过的位置;如果你的 Trae 把登录信息存在别处,请把该路径反馈给我们。",
|
|
8504
9135
|
"row.searchedMore": "展开其余 {count} 条",
|
|
8505
9136
|
"row.quarantineTitle": "被隔离的账号副本",
|
|
8506
|
-
"row.quarantineHint": "
|
|
9137
|
+
"row.quarantineHint": "插件无法读取该账号副本,已将文件改名保留。需要恢复账号时请检查该文件;确认不再需要后,可自行删除留存文件。",
|
|
8507
9138
|
"row.quarantineAccounts": "含 {count} 个账号",
|
|
8508
9139
|
"row.quarantineAccountsUnknown": "账号数无法读取",
|
|
8509
9140
|
"row.quarantineBytes": "{bytes} 字节",
|
|
8510
9141
|
"row.reasonMissing": "文件不存在",
|
|
8511
9142
|
"row.reasonUnreadable": "无法读取",
|
|
8512
9143
|
"row.reasonInvalid": "格式无法识别",
|
|
8513
|
-
"row.sourceDesktop": "
|
|
9144
|
+
"row.sourceDesktop": "桌面端",
|
|
8514
9145
|
"row.sourceCli": "Trae CLI",
|
|
8515
9146
|
"row.signedIn": "已登录:{accountName}",
|
|
8516
|
-
"row.tokenExpiry": "
|
|
9147
|
+
"row.tokenExpiry": "访问令牌将于 {expiresAt} 过期,插件会尝试自动续期",
|
|
8517
9148
|
"row.refreshTokenExpiring": "请在 {expiresAt} 前重新登录一次 Trae(还剩 {days} 天),此后将无法自动续期。",
|
|
8518
9149
|
"row.refreshTokenLapsed": "自动续期已停止:Trae 登录凭据已于 {expiresAt} 过期。请重新登录一次 Trae 以恢复。",
|
|
8519
9150
|
"row.requestFailed": "请求失败",
|
|
@@ -8534,7 +9165,7 @@ window.__ModuleLoader__.load({
|
|
|
8534
9165
|
"row.checkinClaimed": "已领取",
|
|
8535
9166
|
"row.checkinRefused": "Trae 拒绝了本次签到(业务码 {code})",
|
|
8536
9167
|
"row.checkinError": "签到失败:{message}",
|
|
8537
|
-
"row.checkinDeviceSpent": "
|
|
9168
|
+
"row.checkinDeviceSpent": "Trae 每台设备每天只能签到一次。本机今日已签到,当前账号今天无法在本机领取。请换一台尚未签到的设备,或明天再试。",
|
|
8538
9169
|
"row.checkinDisabled": "该账号当前没有可用的签到活动。",
|
|
8539
9170
|
"row.checkinDeviceSpentShort": "本机已签",
|
|
8540
9171
|
"row.subscriptionLabel": "订阅状态",
|
|
@@ -8549,26 +9180,26 @@ window.__ModuleLoader__.load({
|
|
|
8549
9180
|
"row.refreshCredits": "刷新用量",
|
|
8550
9181
|
"row.refreshing": "正在刷新…",
|
|
8551
9182
|
"row.accountsTitle": "Trae 账号",
|
|
8552
|
-
"row.accountsHint": "
|
|
8553
|
-
"row.transferTitle": "
|
|
8554
|
-
"row.transferExport": "
|
|
8555
|
-
"row.transferImport": "
|
|
9183
|
+
"row.accountsHint": "插件刷新账号时会为检测到的 Trae 登录保存凭据副本。切换到新账号后请刷新一次,以免下次登录覆盖尚未保存的凭据。",
|
|
9184
|
+
"row.transferTitle": "导出 / 导入账号",
|
|
9185
|
+
"row.transferExport": "导出账号",
|
|
9186
|
+
"row.transferImport": "导入账号",
|
|
8556
9187
|
"row.transferCancel": "取消",
|
|
8557
9188
|
"row.transferSelectAll": "全选",
|
|
8558
|
-
"row.transferExportPick": "
|
|
8559
|
-
"row.transferExportConfirm": "导出 {count}
|
|
8560
|
-
"row.transferExported": "已导出 {count}
|
|
8561
|
-
"row.transferExporting": "
|
|
8562
|
-
"row.transferImportPick": "
|
|
8563
|
-
"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} 个账号",
|
|
8564
9195
|
"row.transferImported": "已导入 {imported} 个账号副本,跳过 {skipped} 个。",
|
|
8565
9196
|
"row.transferImporting": "正在导入…",
|
|
8566
9197
|
"row.transferReading": "正在读取文件…",
|
|
8567
|
-
"row.transferHint": "
|
|
9198
|
+
"row.transferHint": "使用 JSON 文件导出账号,或将文件中的账号导入插件。文件包含登录凭据,请限制文件的访问权限。导入时会跳过其他区域的账号。",
|
|
8568
9199
|
"row.transferError": "导入/导出失败:{message}",
|
|
8569
9200
|
"row.transferVeilHint": "完成后账号列表会自动刷新。",
|
|
8570
9201
|
"row.transferUnnamed": "未命名账号",
|
|
8571
|
-
"row.transferNoToken": "
|
|
9202
|
+
"row.transferNoToken": "缺少登录凭据",
|
|
8572
9203
|
"row.accountsRescan": "重新检测账号",
|
|
8573
9204
|
"row.accountsScanning": "正在检测…",
|
|
8574
9205
|
"row.accountsLoading": "正在加载账号…",
|
|
@@ -8581,7 +9212,7 @@ window.__ModuleLoader__.load({
|
|
|
8581
9212
|
"row.accountColumnCheckin": "签到",
|
|
8582
9213
|
"row.accountBalance": "积分 {credits}",
|
|
8583
9214
|
"row.balanceConsoleOnly": "见企业版控制台",
|
|
8584
|
-
"row.enterpriseCreditsNotice": "
|
|
9215
|
+
"row.enterpriseCreditsNotice": "插件尚不能读取企业租户余额,请到企业版控制台 console.enterprise.trae.cn 查看。此处不显示个人积分,以免将其误认为企业额度。",
|
|
8585
9216
|
"row.sourceDsh": "插件副本",
|
|
8586
9217
|
"row.modelsTitle": "模型",
|
|
8587
9218
|
"row.modelsSummary": "已启用 {count} 个",
|
|
@@ -8595,7 +9226,7 @@ window.__ModuleLoader__.load({
|
|
|
8595
9226
|
"row.modelsViewLabel": "模型范围",
|
|
8596
9227
|
"row.modelsViewCommon": "常用通道 · {count}",
|
|
8597
9228
|
"row.modelsViewAll": "全部 · {count}",
|
|
8598
|
-
"row.modelsViewCommonHint": "
|
|
9229
|
+
"row.modelsViewCommonHint": "显示可通过 solo_work_remote 或 solo_work_lite 调用的模型。",
|
|
8599
9230
|
"row.modelsViewAllHint": "还包含只在专用通道提供的模型:solo_coder、chat_v3、solo_agent_remote。",
|
|
8600
9231
|
"row.modelsViewShowAll": "查看全部",
|
|
8601
9232
|
"row.modelsSearchOutsideView": "常用通道内没有匹配「{query}」的模型,全部目录里有 {count} 个。",
|
|
@@ -8605,24 +9236,24 @@ window.__ModuleLoader__.load({
|
|
|
8605
9236
|
"row.modelsChannelAgentRemote": "SOLO 智能体 · 远程",
|
|
8606
9237
|
"row.modelsChannelChatV3": "对话 · v3",
|
|
8607
9238
|
"row.modelsChannelCoder": "代码 · solo_coder",
|
|
8608
|
-
"row.modelsChannelDefault": "
|
|
8609
|
-
"row.modelsTestEnabled": "
|
|
8610
|
-
"row.modelsTestAll": "
|
|
8611
|
-
"row.modelsTesting": "
|
|
8612
|
-
"row.modelsTestHint": "
|
|
8613
|
-
"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": "测试当前目录中的所有模型,包含未启用的模型;每次请求均按对应模型费率计费。",
|
|
8614
9245
|
"row.showPointsInMainUi": "在输入框工具栏显示积分读数",
|
|
8615
|
-
"row.showPointsInMainUiHint": "
|
|
8616
|
-
"row.showPointsInMainUiHintAi": "
|
|
9246
|
+
"row.showPointsInMainUiHint": "开启后在所选位置显示可点击读数:国内版为「Trae - CN · 余额」,国际版为「Trae 国际版 · 套餐」。选择其他供应商模型时仍可查看。",
|
|
9247
|
+
"row.showPointsInMainUiHintAi": "开启后在所选位置显示国际版套餐,选择其他供应商模型时仍可查看。",
|
|
8617
9248
|
"row.drawImage": "允许模型自主生图(trae_draw_image)",
|
|
8618
|
-
"row.drawImageHint": "
|
|
8619
|
-
"row.drawImageHintEnterprise": "
|
|
8620
|
-
"row.drawImageHintAi": "
|
|
9249
|
+
"row.drawImageHint": "开启后提供 trae_draw_image 工具,模型可按你的要求生成图片并消耗当前账号积分。国内版曾测得 1920x1920 图片约 8.8 积分,实际费用以上游扣费为准;默认关闭。",
|
|
9250
|
+
"row.drawImageHintEnterprise": "企业版的生图调用与计费尚未验证,因此暂不提供该功能。",
|
|
9251
|
+
"row.drawImageHintAi": "国际版的生图调用与计费尚未验证,因此暂不提供该功能;需要生图时请使用国内版面板。",
|
|
8621
9252
|
"row.creditPositionLabel": "显示位置",
|
|
8622
9253
|
"row.creditPositionComposer": "输入框工具栏",
|
|
8623
9254
|
"row.creditPositionStats": "输入框下方",
|
|
8624
9255
|
"row.creditPositionAria": "{region} 的积分显示位置",
|
|
8625
|
-
"row.creditPositionHint": "
|
|
9256
|
+
"row.creditPositionHint": "默认与模型选择同一行显示;遇到其他连接器占用排序位置时,后加载的读数自动向左排列。也可选择「输入框下方」,与轮次、步数和 token 统计同一行显示。",
|
|
8626
9257
|
"composer.switchTo": "切换到 {account}",
|
|
8627
9258
|
"composer.noAccounts": "该区域暂无账号",
|
|
8628
9259
|
"composer.panelTitle": "Trae 积分",
|
|
@@ -8664,11 +9295,11 @@ window.__ModuleLoader__.load({
|
|
|
8664
9295
|
"row.settingsDirty": "有未保存的修改",
|
|
8665
9296
|
"row.modelsTestEmpty": "请先启用至少一个模型。",
|
|
8666
9297
|
"row.contextAllMid": "整区切到 500K",
|
|
8667
|
-
"row.contextAllMidHint": "
|
|
9298
|
+
"row.contextAllMidHint": "将本面板中 Max 窗口不小于 500K 的模型设为 500K 上下文预算,其余模型保持原值;点击「保存」后生效。",
|
|
8668
9299
|
"row.contextAllMax": "整区切到 Max",
|
|
8669
|
-
"row.contextAllMaxHint": "
|
|
9300
|
+
"row.contextAllMaxHint": "将本面板中提供 Max 窗口的模型设为各自的最大上下文预算,其余模型保持原值;点击「保存」后生效。",
|
|
8670
9301
|
"row.contextAllDefault": "全部恢复默认上下文",
|
|
8671
|
-
"row.contextAllDefaultHint": "
|
|
9302
|
+
"row.contextAllDefaultHint": "清除本面板的自定义上下文预算,恢复使用 Trae 目录默认值;点击「保存」后生效。",
|
|
8672
9303
|
"row.modelsTestError": "测试失败:{message}",
|
|
8673
9304
|
"row.modelsTestDone": "{total} 个里有 {available} 个正常应答。",
|
|
8674
9305
|
"row.probeAvailable": "可用",
|
|
@@ -8690,7 +9321,7 @@ window.__ModuleLoader__.load({
|
|
|
8690
9321
|
"row.veilSaving": "正在保存更改…",
|
|
8691
9322
|
"row.modelContext": "最大上下文 {context}",
|
|
8692
9323
|
"row.contextBudget": "DSH 上下文预算",
|
|
8693
|
-
"row.contextBudgetHint": "
|
|
9324
|
+
"row.contextBudgetHint": "设置 DSH 组织请求时使用的上下文预算。插件不向上游发送窗口或 Max 模式参数,因此不会据此切换 Trae 的服务窗口。",
|
|
8694
9325
|
"row.modelOutput": "最大输出 {output}",
|
|
8695
9326
|
"row.modelImage": "图片",
|
|
8696
9327
|
"row.modelImageAuto": "已自动开启:Trae 把该模型标为多模态。",
|
|
@@ -8700,87 +9331,87 @@ window.__ModuleLoader__.load({
|
|
|
8700
9331
|
"row.modelReasoningFollowUpstream": "默认",
|
|
8701
9332
|
"row.modelReasoningFollowUpstreamNamed": "默认({effort})",
|
|
8702
9333
|
"row.modelUnknown": "未知",
|
|
8703
|
-
"row.modelCapabilityPending": "
|
|
9334
|
+
"row.modelCapabilityPending": "Trae 标注为多模态的模型会自动启用图片输入,也可手动为其他模型启用。",
|
|
8704
9335
|
"row.poolTitle": "账号池",
|
|
8705
9336
|
"row.poolEnabled": "启用账号池",
|
|
8706
|
-
"row.poolEnabledHint": "
|
|
9337
|
+
"row.poolEnabledHint": "开启后,插件自动选择账号;遇到账号限流、积分耗尽或账号故障时尝试换号。关闭后,请从账号列表中选择要使用的账号。",
|
|
8707
9338
|
"row.poolCurrentHeader": "当前计费:{account}",
|
|
8708
|
-
"row.poolModeAuto": "
|
|
8709
|
-
"row.poolModeManual": "
|
|
9339
|
+
"row.poolModeAuto": "自动选择",
|
|
9340
|
+
"row.poolModeManual": "手动选择",
|
|
8710
9341
|
"row.poolMember": "已在池中",
|
|
8711
|
-
"row.poolNotMember": "
|
|
8712
|
-
"row.poolBusyHint": "
|
|
8713
|
-
"row.poolTestAll": "
|
|
8714
|
-
"row.poolTesting": "
|
|
8715
|
-
"row.poolOffNotice": "
|
|
8716
|
-
"row.poolNoCandidate": "
|
|
8717
|
-
"row.poolNoCandidateEmpty": "
|
|
8718
|
-
"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": "请在下方勾选账号并保存,插件才会将其加入账号池。",
|
|
8719
9350
|
"row.poolNoCandidateUnusable": "所有已选成员当前均不可用。",
|
|
8720
|
-
"row.poolNoCandidateHint": "
|
|
8721
|
-
"row.poolServingOutside": "{account}
|
|
8722
|
-
"row.poolMembersTitle": "
|
|
9351
|
+
"row.poolNoCandidateHint": "账号池没有可用成员时,请求会尝试使用已保存的绑定账号。成员当前状态:",
|
|
9352
|
+
"row.poolServingOutside": "当前由未加入账号池的 {account} 计费,账号池恢复可用成员前会继续使用已保存的绑定账号。",
|
|
9353
|
+
"row.poolMembersTitle": "账号池成员",
|
|
8723
9354
|
"row.poolRescan": "重新检测账号",
|
|
8724
9355
|
"row.poolToolsLabel": "导出 / 导入账号",
|
|
8725
9356
|
"row.poolCreditExpiry": "{when} 过期",
|
|
8726
9357
|
"row.poolProbeMeasured": "测得 {when}",
|
|
8727
9358
|
"row.poolProbeAt": "测试于 {when}",
|
|
8728
|
-
"row.poolSettingsNote": "
|
|
9359
|
+
"row.poolSettingsNote": "修改下方设置后请点击「保存」;测试结果由插件单独保存。",
|
|
8729
9360
|
"row.poolSelectedCount": "已选 {count} / {total}",
|
|
8730
9361
|
"row.poolNoCopyTag": "本机无副本",
|
|
8731
|
-
"row.poolCopyFile": "
|
|
8732
|
-
"row.poolNoCopyTestHint": "
|
|
8733
|
-
"row.poolSelectAll": "
|
|
8734
|
-
"row.poolSelectNone": "
|
|
9362
|
+
"row.poolCopyFile": "当前共有 {count} 份账号副本,保存位置为 {path}。刷新账号时,插件为新登录创建副本,并保留已有副本。",
|
|
9363
|
+
"row.poolNoCopyTestHint": "插件无法读取该账号的登录凭据,请在 Trae 中重新登录后检测账号,或将其移出账号池。",
|
|
9364
|
+
"row.poolSelectAll": "全选",
|
|
9365
|
+
"row.poolSelectNone": "全不选",
|
|
8735
9366
|
"row.poolColumnAccount": "账号",
|
|
8736
9367
|
"row.poolColumnCredits": "积分",
|
|
8737
9368
|
"row.poolColumnProbe": "状态",
|
|
8738
9369
|
"row.poolColumnCheckin": "签到",
|
|
8739
|
-
"row.poolGeneralLabel": "
|
|
8740
|
-
"row.poolWorkHint": "
|
|
9370
|
+
"row.poolGeneralLabel": "积分",
|
|
9371
|
+
"row.poolWorkHint": "DSH 对话使用积分余额,不能使用工作积分。",
|
|
8741
9372
|
"row.poolCreditNone": "—",
|
|
8742
|
-
"row.poolTestedAt": "
|
|
8743
|
-
"row.poolNeverTested": "
|
|
8744
|
-
"row.poolRetryAt": "{at}
|
|
9373
|
+
"row.poolTestedAt": "测试于 {at}",
|
|
9374
|
+
"row.poolNeverTested": "未测试",
|
|
9375
|
+
"row.poolRetryAt": "{at} 后可重试",
|
|
8745
9376
|
"row.poolRetryUnknown": "重试时间未知",
|
|
8746
|
-
"row.poolTargetCurrentPreferred": "
|
|
8747
|
-
"row.poolTargetCurrentFree": "
|
|
8748
|
-
"row.poolTargetStale": "
|
|
9377
|
+
"row.poolTargetCurrentPreferred": "测试模型:{model}(手动选择)",
|
|
9378
|
+
"row.poolTargetCurrentFree": "测试模型:{model}(自动选择)",
|
|
9379
|
+
"row.poolTargetStale": "你保存的目标模型已不在目录中:{model}",
|
|
8749
9380
|
"row.poolTargetStaleOption": "{model}(已下架)",
|
|
8750
|
-
"row.poolTargetStaleClear": "
|
|
9381
|
+
"row.poolTargetStaleClear": "切回自动",
|
|
8751
9382
|
"row.poolTargetNone": "本面板暂无可用免费模型",
|
|
8752
|
-
"row.poolTargetNoneHint": "
|
|
8753
|
-
"row.poolActionNoteTestNone": "
|
|
8754
|
-
"row.poolActionNoteNoMembers": "
|
|
8755
|
-
"row.poolTargetAutoOption": "
|
|
8756
|
-
"row.poolTargetLabel": "
|
|
8757
|
-
"row.poolTargetHint": "
|
|
8758
|
-
"row.poolProbeSizeLabel": "
|
|
8759
|
-
"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": "建议选择接近会话请求的输入长度。短请求通过测试后,较长的请求也可能触发账号限制。输入越长,收费模型的测试费用越高。",
|
|
8760
9391
|
"row.poolProbeSizeDefault": "最小请求(默认)",
|
|
8761
9392
|
"row.poolProbeSizeOption": "{wan} 万 token",
|
|
8762
9393
|
"row.poolSettingsTitle": "更多设置",
|
|
8763
9394
|
"row.poolMoreRulesTitle": "账号副本与保存规则",
|
|
8764
|
-
"row.poolManualAccountLabel": "
|
|
8765
|
-
"row.poolManualAccountNone": "
|
|
8766
|
-
"row.poolDirty": "
|
|
9395
|
+
"row.poolManualAccountLabel": "当前账号",
|
|
9396
|
+
"row.poolManualAccountNone": "当前没有生效的账号",
|
|
9397
|
+
"row.poolDirty": "● 有未保存的修改",
|
|
8767
9398
|
"row.poolSaved": "保存",
|
|
8768
9399
|
"row.poolSaving": "保存中…",
|
|
8769
|
-
"row.poolDiscard": "
|
|
9400
|
+
"row.poolDiscard": "放弃修改",
|
|
8770
9401
|
"row.poolSaveFailed": "保存失败:{message}",
|
|
8771
|
-
"row.poolGhostMembers": "{count}
|
|
8772
|
-
"row.poolUnsavedMembers": "
|
|
8773
|
-
"row.poolRowTest": "
|
|
9402
|
+
"row.poolGhostMembers": "无法读取 {count} 个已保存成员的登录凭据:{names}",
|
|
9403
|
+
"row.poolUnsavedMembers": "成员选择已修改,保存后生效",
|
|
9404
|
+
"row.poolRowTest": "测试",
|
|
8774
9405
|
"row.poolLogTitle": "活动记录",
|
|
8775
9406
|
"row.poolLogClear": "清空",
|
|
8776
9407
|
"row.poolLogEmpty": "暂无账号池活动。",
|
|
8777
|
-
"row.poolLogTestStart": "
|
|
8778
|
-
"row.poolLogTestRow": "{accountName}:{outcome}
|
|
8779
|
-
"row.poolLogTestRowMalformed": "{accountName}
|
|
8780
|
-
"row.poolLogTestDone": "
|
|
8781
|
-
"row.poolLogBatchFailed": "
|
|
8782
|
-
"row.poolLogTimeout": "
|
|
8783
|
-
"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} 加入本区域的账号池",
|
|
8784
9415
|
"row.poolCheckedIn": "已签到",
|
|
8785
9416
|
"row.poolNotCheckedIn": "未签到",
|
|
8786
9417
|
"row.poolCheckinUnknown": "未知",
|
|
@@ -8796,16 +9427,16 @@ window.__ModuleLoader__.load({
|
|
|
8796
9427
|
"row.poolProbeUnavailable": "不可用",
|
|
8797
9428
|
"row.poolProbeNotFound": "上游不提供",
|
|
8798
9429
|
"row.poolProbeFailed": "失败",
|
|
8799
|
-
"row.poolProbeSourceUnknown": "
|
|
8800
|
-
"row.poolProbeSourceLive": "
|
|
8801
|
-
"row.poolProbeSourceTest": "
|
|
9430
|
+
"row.poolProbeSourceUnknown": "来源未知",
|
|
9431
|
+
"row.poolProbeSourceLive": "对话请求",
|
|
9432
|
+
"row.poolProbeSourceTest": "手动测试",
|
|
8802
9433
|
"row.poolProbeModel": "模型 {model}",
|
|
8803
|
-
"row.poolProbeModelUnknown": "
|
|
9434
|
+
"row.poolProbeModelUnknown": "未记录模型",
|
|
8804
9435
|
"row.poolExcludedUnusable": "不可用",
|
|
8805
9436
|
"row.poolTokenExpired": "登录已失效",
|
|
8806
9437
|
"row.poolExcludedRateLimited": "被限流",
|
|
8807
9438
|
"row.poolExcludedModelBusy": "模型繁忙",
|
|
8808
|
-
"row.poolExcludedOutOfCredit": "
|
|
9439
|
+
"row.poolExcludedOutOfCredit": "积分耗尽",
|
|
8809
9440
|
"row.poolExcludedCredentialRejected": "登录凭据被拒",
|
|
8810
9441
|
"row.poolExcludedPolicyRejected": "被策略拒绝",
|
|
8811
9442
|
"row.poolExcludedPlanGated": "需要更高套餐",
|
|
@@ -8816,45 +9447,45 @@ window.__ModuleLoader__.load({
|
|
|
8816
9447
|
"row.poolAgoMin": "{n} 分钟前",
|
|
8817
9448
|
"row.poolAgoHour": "{n} 小时前",
|
|
8818
9449
|
"row.poolAgoDay": "{n} 天前",
|
|
8819
|
-
"row.poolErrOrigin": "
|
|
8820
|
-
"row.poolErrUnavailable": "
|
|
9450
|
+
"row.poolErrOrigin": "请求来源未通过验证,账号池未执行操作",
|
|
9451
|
+
"row.poolErrUnavailable": "账号池接口不可用,请重启 DSH;问题持续时请重新安装插件。",
|
|
8821
9452
|
"row.poolErrMethod": "账号池不接受该请求方法",
|
|
8822
9453
|
"row.poolErrBadRequest": "账号池拒绝了该请求",
|
|
8823
|
-
"row.poolErrNoMembers": "
|
|
8824
|
-
"row.poolErrNoLiveMembers": "
|
|
9454
|
+
"row.poolErrNoMembers": "请先在账号池中勾选账号并保存,再点击签到或测试按钮。",
|
|
9455
|
+
"row.poolErrNoLiveMembers": "插件无法读取所选账号的有效登录凭据。请重新登录这些账号,或将它们移出账号池后保存。",
|
|
8825
9456
|
"row.poolErrCheckinUnsupported": "本面板不提供每日签到",
|
|
8826
9457
|
"row.poolErrTargetStale": "已保存的目标模型已下架",
|
|
8827
|
-
"row.poolErrNoFreeModel": "
|
|
9458
|
+
"row.poolErrNoFreeModel": "当前区域没有可用的免费模型,请刷新目录,或手动选择测试模型后再试。",
|
|
8828
9459
|
"row.poolErrConflict": "账号池拒绝了该请求",
|
|
8829
9460
|
"row.poolErrGeneric": "账号池请求失败(HTTP {status})",
|
|
8830
|
-
"row.poolSettingsHint": "
|
|
9461
|
+
"row.poolSettingsHint": "修改账号池设置后,请点击保存。插件会单独保存测试结果。",
|
|
8831
9462
|
"row.poolLogSaved": "账号池设置已保存。",
|
|
8832
9463
|
"row.poolLogSaveFailed": "无法保存账号池设置。",
|
|
8833
|
-
"row.poolLogNoMembers": "
|
|
9464
|
+
"row.poolLogNoMembers": "尚未勾选账号池成员,未执行操作。",
|
|
8834
9465
|
"row.poolLogDiscarded": "已放弃未保存的账号池修改。",
|
|
8835
9466
|
"row.poolLogGeneric": "账号池未返回可用的结果",
|
|
8836
9467
|
"row.poolLogRowTesting": "正在测速 {accountName}…",
|
|
8837
9468
|
"row.poolLogTargetCleared": "测速目标已改回自动。",
|
|
8838
9469
|
"row.poolRowDelete": "删除",
|
|
8839
|
-
"row.poolRowDeleteAria": "
|
|
9470
|
+
"row.poolRowDeleteAria": "删除 {accountName} 的插件副本,并将该账号从 Trae 应用中退出登录",
|
|
8840
9471
|
"row.poolRowDeleting": "删除中…",
|
|
8841
9472
|
"row.poolGhostDeleteAria": "从本机删除已保存但无法登录的账号 {accountName}",
|
|
8842
9473
|
"row.poolRowDeleteError": "无法删除 {accountName}:{message}",
|
|
8843
9474
|
"row.poolRowDeleteFailed": "删除未得到确认",
|
|
8844
9475
|
"row.poolRowDeleted": "已删除 {accountName} 的凭据副本。",
|
|
8845
|
-
"row.poolDeleteStillSigned": "
|
|
9476
|
+
"row.poolDeleteStillSigned": "插件副本已删除,但 {accountName} 仍登录在 Trae 中;若要移除本机登录,请在 Trae 内退出该账号。",
|
|
8846
9477
|
"row.poolRowDeletedSignedOut": "已删除 {accountName},并将它从 {apps} 中退出登录。",
|
|
8847
|
-
"row.poolRowDeleteAppRunning": "
|
|
8848
|
-
"row.poolDeleteAppRunning": "
|
|
8849
|
-
"row.poolDeleteNoCopy": "{accountName}
|
|
9478
|
+
"row.poolRowDeleteAppRunning": "{apps} 正在运行,可能覆盖登录文件修改;请完全退出这些应用后,再删除 {accountName}。",
|
|
9479
|
+
"row.poolDeleteAppRunning": "为避免 {apps} 覆盖登录文件修改,本次未改动任何文件;请完全退出这些应用后再删除。",
|
|
9480
|
+
"row.poolDeleteNoCopy": "{accountName} 仅保留在 Trae 的登录状态中,本次退出登录未生效,因此没有删除任何插件副本。",
|
|
8850
9481
|
"row.poolRowDeleteStillSigned": "已删除副本,但 {accountName} 仍登录在 Trae 中",
|
|
8851
|
-
"row.poolRowDeleteNoCopy": "{accountName}
|
|
8852
|
-
"row.poolDeleteHint": "
|
|
9482
|
+
"row.poolRowDeleteNoCopy": "{accountName} 没有插件副本,仅保留在 Trae 应用登录状态中",
|
|
9483
|
+
"row.poolDeleteHint": "刷新账号时,插件会为新检测到的 Trae 登录保存副本,并保留已有副本。删除账号会移除副本、将账号从 Trae 退出登录,并为修改过的文件保留备份;操作前需完全退出相关 Trae 应用。如果退出登录未生效,插件会阻止该账号在保持登录期间再次导入。",
|
|
8853
9484
|
"row.cheer": "鼓励一下",
|
|
8854
9485
|
"nav.panel": "Trae",
|
|
8855
9486
|
"row.pageBack": "返回会话",
|
|
8856
9487
|
"row.sidebarPanelLabel": "在侧边栏显示 Trae",
|
|
8857
|
-
"row.sidebarPanelHint": "
|
|
9488
|
+
"row.sidebarPanelHint": "在侧边栏显示 Trae 设置入口,默认关闭。开关即时生效;关闭时,已打开的设置页会返回对话。"
|
|
8858
9489
|
};
|
|
8859
9490
|
//#endregion
|
|
8860
9491
|
//#region src/client/TraeModelLabel.tsx
|
|
@@ -9149,21 +9780,35 @@ window.__ModuleLoader__.load({
|
|
|
9149
9780
|
* different priority to shadow it (lowest renders)". Priority 0 is the DEFAULT,
|
|
9150
9781
|
* so it is the one value that is guaranteed to be contested.
|
|
9151
9782
|
*
|
|
9152
|
-
* WHY `-
|
|
9153
|
-
*
|
|
9154
|
-
*
|
|
9155
|
-
*
|
|
9156
|
-
*
|
|
9157
|
-
* dsh-connect-
|
|
9158
|
-
*
|
|
9159
|
-
*
|
|
9160
|
-
*
|
|
9161
|
-
*
|
|
9162
|
-
*
|
|
9163
|
-
*
|
|
9164
|
-
*
|
|
9165
|
-
*
|
|
9166
|
-
*
|
|
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.
|
|
9167
9812
|
*
|
|
9168
9813
|
* WHAT WINNING/HOLDING COSTS. This cell is `single`, so the other registrants'
|
|
9169
9814
|
* decorations on the rows this plugin claims are not composed. That is the
|
|
@@ -9181,7 +9826,7 @@ window.__ModuleLoader__.load({
|
|
|
9181
9826
|
* disposes its previous entry before every attempt. Priority alone would have
|
|
9182
9827
|
* made the throw rarer and harder to read, not absent.
|
|
9183
9828
|
*/
|
|
9184
|
-
const MODEL_LABEL_PRIORITY =
|
|
9829
|
+
const MODEL_LABEL_PRIORITY = -102;
|
|
9185
9830
|
/** The tone colours, mapped onto the same theme tokens the host's Tag paints. */
|
|
9186
9831
|
const HOST_BADGE_TONES = {
|
|
9187
9832
|
neutral: {
|
|
@@ -9425,7 +10070,7 @@ window.__ModuleLoader__.load({
|
|
|
9425
10070
|
* happens on every press and a shell that appears later is still found. See
|
|
9426
10071
|
* `settings-route.ts` for the finding that established which seam this is.
|
|
9427
10072
|
*/
|
|
9428
|
-
const onOpenSettings = () => openPluginSettingsPage(softGet);
|
|
10073
|
+
const onOpenSettings = () => openPluginSettingsPage(softGet, { label: () => t("nav.panel") });
|
|
9429
10074
|
const forms = softGet("configForms");
|
|
9430
10075
|
/**
|
|
9431
10076
|
* The card's settings scope, bound to whichever namespace the Host actually
|
|
@@ -9654,13 +10299,9 @@ window.__ModuleLoader__.load({
|
|
|
9654
10299
|
*/
|
|
9655
10300
|
function TraePanelIcon(props) {
|
|
9656
10301
|
const edge = typeof props.size === "number" && props.size > 0 ? props.size : 16;
|
|
9657
|
-
return (0, react.createElement)(
|
|
10302
|
+
return (0, react.createElement)(PluginIcon, {
|
|
9658
10303
|
className: "dsm-trae-panel-icon",
|
|
9659
|
-
|
|
9660
|
-
alt: "",
|
|
9661
|
-
width: edge,
|
|
9662
|
-
height: edge,
|
|
9663
|
-
"aria-hidden": "true"
|
|
10304
|
+
size: edge
|
|
9664
10305
|
});
|
|
9665
10306
|
}
|
|
9666
10307
|
/**
|
|
@@ -9682,14 +10323,10 @@ window.__ModuleLoader__.load({
|
|
|
9682
10323
|
*/
|
|
9683
10324
|
function SettingsSectionIcon(props) {
|
|
9684
10325
|
const edge = typeof props.size === "number" && props.size > 0 ? props.size : 16;
|
|
9685
|
-
return (0, react.createElement)(
|
|
10326
|
+
return (0, react.createElement)(PluginIcon, {
|
|
9686
10327
|
className: "dsm-trae-section-icon",
|
|
9687
|
-
|
|
9688
|
-
|
|
9689
|
-
width: edge,
|
|
9690
|
-
height: edge,
|
|
9691
|
-
style: { opacity: props.active === false ? .75 : 1 },
|
|
9692
|
-
"aria-hidden": "true"
|
|
10328
|
+
size: edge,
|
|
10329
|
+
style: { opacity: props.active === false ? .75 : 1 }
|
|
9693
10330
|
});
|
|
9694
10331
|
}
|
|
9695
10332
|
/**
|