dsh-connect-trae 4.2.0 → 4.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +63 -0
- package/README.en.md +1 -0
- package/README.md +1 -0
- package/lib/client.js +836 -413
- package/package.json +3 -2
package/lib/client.js
CHANGED
|
@@ -18,6 +18,11 @@ window.__ModuleLoader__.load({
|
|
|
18
18
|
function regionOfPanel(panel) {
|
|
19
19
|
return panel === "ai" ? "ai" : "cn";
|
|
20
20
|
}
|
|
21
|
+
/** The provider id a panel publishes. */
|
|
22
|
+
function providerOfPanel(panel) {
|
|
23
|
+
if (panel === "enterprise") return "trae-enterprise";
|
|
24
|
+
return panel === "ai" ? "trae-global" : "trae";
|
|
25
|
+
}
|
|
21
26
|
//#endregion
|
|
22
27
|
//#region src/status-paths.ts
|
|
23
28
|
/** Plugin-owned usage endpoint consumed by its browser half. */
|
|
@@ -556,6 +561,45 @@ window.__ModuleLoader__.load({
|
|
|
556
561
|
.dsm-trae-tab-switch{flex:none;margin-left:auto;padding-left:10px;border-left:1px solid var(--dsw-alias-border-l1,rgba(127,127,127,.24))}
|
|
557
562
|
.dsm-trae-tab-dot{display:inline-block;width:7px;height:7px;border-radius:50%;margin-right:7px;vertical-align:baseline}
|
|
558
563
|
.dsm-trae-tab-hint{margin:0;padding:0 2px;color:var(--dsw-alias-label-tertiary,#999);font-size:12px;line-height:18px}
|
|
564
|
+
/* SECTION TABS: the card's own top-level split (account / models / diagnostics).
|
|
565
|
+
*
|
|
566
|
+
* Deliberately NOT the boxed chips above. Those are the REGION scope — a
|
|
567
|
+
* three-way choice of which PROVIDER this whole card is about, each chip
|
|
568
|
+
* carrying its own on/off switch — while these are panels of ONE document, the
|
|
569
|
+
* shape a reader already knows from the app's own settings window. Two rows of
|
|
570
|
+
* boxes would read as one six-way choice.
|
|
571
|
+
*
|
|
572
|
+
* The hidden ATTRIBUTE on each panel is what does the work: an inactive panel
|
|
573
|
+
* stays MOUNTED, so switching back does not refetch, a half-filled model draft
|
|
574
|
+
* survives the trip, and the account pool keeps its log. It also takes the
|
|
575
|
+
* inactive panel out of the accessibility tree, which is exactly what
|
|
576
|
+
* role="tabpanel" wants — unlike display:none reached by a CSS class, the user
|
|
577
|
+
* agent's own rule for [hidden] cannot be overridden by a later declaration. */
|
|
578
|
+
.dsm-trae-panels{display:flex;align-items:stretch;gap:2px;margin:4px 0 0;border-bottom:1px solid var(--dsw-alias-border-l1,rgba(127,127,127,.24))}
|
|
579
|
+
.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}
|
|
580
|
+
.dsm-trae-panel-tab:hover:not(.dsm-trae-panel-tab-active){color:var(--dsw-alias-label-primary,#e6e6e6)}
|
|
581
|
+
.dsm-trae-panel-tab:focus-visible{outline:2px solid var(--dsw-alias-brand-primary,#5686fe);outline-offset:1px}
|
|
582
|
+
.dsm-trae-panel-tab-active{color:var(--dsw-alias-label-primary,#e6e6e6);border-bottom-color:var(--dsw-alias-brand-primary,#5686fe)}
|
|
583
|
+
/* No top margin of its own: the strip above already carries a border, and the
|
|
584
|
+
card's 16px stack gap would double the separation. */
|
|
585
|
+
.dsm-trae-panel{margin-top:0}
|
|
586
|
+
/* DIAGNOSTICS: a two-column fact table rather than prose. Each row is one thing
|
|
587
|
+
* the card actually READ, so a bug report can quote a line instead of
|
|
588
|
+
* paraphrasing the UI. No control lives here on purpose — a diagnostics panel
|
|
589
|
+
* that can change settings is a settings panel with a worse name. */
|
|
590
|
+
.dsm-trae-diag{display:flex;flex-direction:column;border:1px solid var(--dsw-alias-border-l2,#36373b);border-radius:10px;overflow:hidden;background:var(--dsw-alias-bg-layer-2,#232529)}
|
|
591
|
+
.dsm-trae-diag-row{display:flex;align-items:baseline;justify-content:space-between;gap:16px;padding:8px 12px}
|
|
592
|
+
.dsm-trae-diag-row+.dsm-trae-diag-row{border-top:1px solid var(--dsw-alias-border-l1,rgba(127,127,127,.24))}
|
|
593
|
+
.dsm-trae-diag-label{flex:none;color:var(--dsw-alias-label-tertiary,#999);font-size:12px;line-height:18px}
|
|
594
|
+
.dsm-trae-diag-value{min-width:0;color:var(--dsw-alias-label-primary,#e6e6e6);font-size:12px;line-height:18px;text-align:right;overflow-wrap:anywhere}
|
|
595
|
+
.dsm-trae-diag-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}
|
|
596
|
+
/* A failure line, in the same warn tone the card already uses for an expiring
|
|
597
|
+
credit — NOT a hand-rolled amber. The token set the card asks DSH for is
|
|
598
|
+
audited by the card-styles spec (every name must be one the host actually
|
|
599
|
+
defines), so this deliberately names state-warn-primary rather than the
|
|
600
|
+
sibling card's label-caution, which this suite has never verified. */
|
|
601
|
+
.dsm-trae-diag-bad{color:var(--dsw-alias-state-warn-primary,#b45309)}
|
|
602
|
+
.dsm-trae-diag-hint{margin:10px 0 0;color:var(--dsw-alias-label-tertiary,#999);font-size:12px;line-height:18px}
|
|
559
603
|
.dsm-trae-credits-unavailable{margin:10px 0 0;padding:10px 12px;border:1px solid var(--dsw-alias-border-l2,#3a3d45);border-radius:10px;color:var(--dsw-alias-label-secondary,#c6c9d0);font-size:12px;line-height:18px;background:var(--dsw-alias-bg-layer-3,#2a2c33)}
|
|
560
604
|
.dsm-trae-account-value-muted{color:var(--dsw-alias-label-secondary,#c6c9d0);font-size:12px}
|
|
561
605
|
.dsm-trae-tab-off-notice{margin:0;padding:10px 12px;border:1px solid var(--dsw-alias-border-l2,#3a3d45);border-radius:10px;color:var(--dsw-alias-label-secondary,#c6c9d0);font-size:12px;line-height:18px;background:var(--dsw-alias-bg-layer-3,#2a2c33)}
|
|
@@ -738,6 +782,17 @@ window.__ModuleLoader__.load({
|
|
|
738
782
|
.dsm-trae-models-head{display:flex;align-items:center;justify-content:space-between;gap:12px}
|
|
739
783
|
.dsm-trae-models-title{margin:0;color:var(--dsw-alias-label-primary,#e6e6e6);font-size:14px;font-weight:600;line-height:20px}
|
|
740
784
|
.dsm-trae-models-summary{margin:2px 0 0;color:var(--dsw-alias-label-tertiary,#999);font-size:12px;line-height:18px}
|
|
785
|
+
/* EVERY model is on the page — no inner scroller, no max-height.
|
|
786
|
+
*
|
|
787
|
+
* A capped list with its own scrollbar was tried and rejected by the user: it
|
|
788
|
+
* turned a settings section into a little window that has to be scrolled inside
|
|
789
|
+
* a page that already scrolls, and put the models a user is looking for behind a
|
|
790
|
+
* gesture that does not match the rest of the card. The section is allowed to be
|
|
791
|
+
* as tall as the catalog is; the card's own page scroll is the only scroll.
|
|
792
|
+
*
|
|
793
|
+
* overflow:hidden is for the rounded border only (so the row hairlines cannot
|
|
794
|
+
* paint outside the radius). It is deliberately NOT auto: nothing here clips
|
|
795
|
+
* content vertically. */
|
|
741
796
|
.dsm-trae-model-list{display:flex;flex-direction:column;border:1px solid var(--dsw-alias-border-l2,#36373b);border-radius:10px;overflow:hidden}
|
|
742
797
|
.dsm-trae-model{display:grid;grid-template-columns:minmax(0,1fr);gap:7px;padding:10px 12px;background:var(--dsw-alias-bg-layer-2,#232529);transition:opacity .16s}
|
|
743
798
|
.dsm-trae-model-disabled{opacity:.55}
|
|
@@ -2928,6 +2983,418 @@ window.__ModuleLoader__.load({
|
|
|
2928
2983
|
});
|
|
2929
2984
|
}
|
|
2930
2985
|
//#endregion
|
|
2986
|
+
//#region src/client/display.ts
|
|
2987
|
+
/** A group-separated integer, in the reader's own locale. */
|
|
2988
|
+
function formatNumber(value) {
|
|
2989
|
+
return new Intl.NumberFormat(void 0, {
|
|
2990
|
+
minimumFractionDigits: 0,
|
|
2991
|
+
maximumFractionDigits: 0
|
|
2992
|
+
}).format(value);
|
|
2993
|
+
}
|
|
2994
|
+
/** A date and time, in the reader's own locale. */
|
|
2995
|
+
function formatDateTime(value) {
|
|
2996
|
+
return new Intl.DateTimeFormat(void 0, {
|
|
2997
|
+
year: "numeric",
|
|
2998
|
+
month: "2-digit",
|
|
2999
|
+
day: "2-digit",
|
|
3000
|
+
hour: "2-digit",
|
|
3001
|
+
minute: "2-digit"
|
|
3002
|
+
}).format(new Date(value));
|
|
3003
|
+
}
|
|
3004
|
+
/**
|
|
3005
|
+
* The colour of a status dot, as an inline style.
|
|
3006
|
+
*
|
|
3007
|
+
* Inline rather than a class because the colour IS the value (signed-in / error
|
|
3008
|
+
* / signed-out); a class per state would be three names that say the same thing.
|
|
3009
|
+
*/
|
|
3010
|
+
function dotStyle(status) {
|
|
3011
|
+
return { background: status === "signed-in" ? "var(--dsw-alias-state-success-primary, #22a06b)" : status === "error" ? "var(--dsw-alias-state-error-primary, #d92d20)" : "var(--dsw-alias-label-dimmed, #9aa0a6)" };
|
|
3012
|
+
}
|
|
3013
|
+
/** How close a refresh token must be to lapsing before the card warns, in days. */
|
|
3014
|
+
const REFRESH_WARN_DAYS = 30;
|
|
3015
|
+
/**
|
|
3016
|
+
* The refresh-token warning for one account, or undefined when there is nothing
|
|
3017
|
+
* worth saying.
|
|
3018
|
+
*
|
|
3019
|
+
* The access token renews itself every few minutes, so its own expiry answers
|
|
3020
|
+
* "when does this need attention" with "never, until the refresh token lapses".
|
|
3021
|
+
* The refresh token is therefore the only honest countdown on this card, and it
|
|
3022
|
+
* has to be shown BEFORE it runs out: once it lapses the plugin cannot renew at
|
|
3023
|
+
* all and the only recovery is signing in to Trae again, which a user who has
|
|
3024
|
+
* been reading "auto-renewal" for months has no reason to expect.
|
|
3025
|
+
*
|
|
3026
|
+
* Three tones, matching the credit-expiry notice: `lapsed` (renewal already
|
|
3027
|
+
* dead), `soon` (inside the warning window), and nothing otherwise — a healthy
|
|
3028
|
+
* token must not add a line to every account row forever.
|
|
3029
|
+
*/
|
|
3030
|
+
function refreshTokenWarning(expiresAtMs, nowMs, t, formatTime) {
|
|
3031
|
+
if (expiresAtMs === void 0) return void 0;
|
|
3032
|
+
const text = formatTime(expiresAtMs);
|
|
3033
|
+
if (expiresAtMs <= nowMs) return {
|
|
3034
|
+
tone: "lapsed",
|
|
3035
|
+
text: t("row.refreshTokenLapsed", { expiresAt: text })
|
|
3036
|
+
};
|
|
3037
|
+
const days = Math.ceil((expiresAtMs - nowMs) / 864e5);
|
|
3038
|
+
if (days > REFRESH_WARN_DAYS) return void 0;
|
|
3039
|
+
return {
|
|
3040
|
+
tone: "soon",
|
|
3041
|
+
text: t("row.refreshTokenExpiring", {
|
|
3042
|
+
expiresAt: text,
|
|
3043
|
+
days
|
|
3044
|
+
})
|
|
3045
|
+
};
|
|
3046
|
+
}
|
|
3047
|
+
//#endregion
|
|
3048
|
+
//#region src/client/TraeAccountPanel.tsx
|
|
3049
|
+
/**
|
|
3050
|
+
* A warning that credit is about to lapse.
|
|
3051
|
+
*
|
|
3052
|
+
* The balance alone cannot express this: a pack lapsing in an hour and one
|
|
3053
|
+
* lapsing next month both render as "150", so a user watching only the total
|
|
3054
|
+
* loses the first one silently. The notice names the amount, the pack count and
|
|
3055
|
+
* the soonest expiry, and escalates 7d → 24h → already-lapsed.
|
|
3056
|
+
*
|
|
3057
|
+
* Renders nothing when the upstream reported no end times at all — absence of
|
|
3058
|
+
* expiry data is not evidence that nothing lapses, so the component stays silent
|
|
3059
|
+
* rather than reassuring.
|
|
3060
|
+
*/
|
|
3061
|
+
function ExpiryNotice({ expiry, t }) {
|
|
3062
|
+
const { expired, within24h, within7d } = expiry;
|
|
3063
|
+
let message;
|
|
3064
|
+
let soonest;
|
|
3065
|
+
let tone;
|
|
3066
|
+
if (within24h.packs > 0) {
|
|
3067
|
+
message = t("row.expiryWarningSoon", {
|
|
3068
|
+
total: formatNumber(within24h.total),
|
|
3069
|
+
packs: String(within24h.packs)
|
|
3070
|
+
});
|
|
3071
|
+
soonest = within24h.earliestExpiresAtMs;
|
|
3072
|
+
tone = "dsm-trae-expiry-soon";
|
|
3073
|
+
} else if (within7d.packs > 0) {
|
|
3074
|
+
message = t("row.expiryWarningWeek", {
|
|
3075
|
+
total: formatNumber(within7d.total),
|
|
3076
|
+
packs: String(within7d.packs)
|
|
3077
|
+
});
|
|
3078
|
+
soonest = within7d.earliestExpiresAtMs;
|
|
3079
|
+
tone = "dsm-trae-expiry-week";
|
|
3080
|
+
} else if (expired.packs > 0) {
|
|
3081
|
+
message = t("row.expiryWarningLapsed", {
|
|
3082
|
+
total: formatNumber(expired.total),
|
|
3083
|
+
packs: String(expired.packs)
|
|
3084
|
+
});
|
|
3085
|
+
tone = "dsm-trae-expiry-lapsed";
|
|
3086
|
+
} else return null;
|
|
3087
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3088
|
+
className: `dsm-trae-expiry ${tone}`,
|
|
3089
|
+
role: "status",
|
|
3090
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: message }), soonest === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3091
|
+
className: "dsm-trae-expiry-detail",
|
|
3092
|
+
children: t("row.expiryEarliest", { time: formatDateTime(soonest) })
|
|
3093
|
+
})]
|
|
3094
|
+
});
|
|
3095
|
+
}
|
|
3096
|
+
/** The CN check-in cell for one row: an outcome once there is nothing left to do. */
|
|
3097
|
+
function ClaimCell({ claim, onClaim, t }) {
|
|
3098
|
+
if (!claim.claimable) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3099
|
+
className: "dsm-trae-account-checkin-state",
|
|
3100
|
+
children: claim.settled === "claimed" ? t("row.poolCheckedIn") : t("row.poolDeviceUsed")
|
|
3101
|
+
});
|
|
3102
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3103
|
+
type: "button",
|
|
3104
|
+
className: "dsm-trae-account-checkin",
|
|
3105
|
+
disabled: claim.disabled,
|
|
3106
|
+
title: claim.title,
|
|
3107
|
+
onClick: onClaim,
|
|
3108
|
+
children: claim.label
|
|
3109
|
+
});
|
|
3110
|
+
}
|
|
3111
|
+
/**
|
|
3112
|
+
* The account section: preferences, the roster, the pool, and every notice about
|
|
3113
|
+
* the credential.
|
|
3114
|
+
*
|
|
3115
|
+
* Everything here commits ON THE CLICK (the preference boxes write themselves,
|
|
3116
|
+
* the check-in claims immediately, the pool saves through its own footer). That
|
|
3117
|
+
* is precisely why this section has no 「保存」 of its own — the model catalog,
|
|
3118
|
+
* which does, lives in its own section.
|
|
3119
|
+
*/
|
|
3120
|
+
function TraeAccountPanel({ t, settingsScope, panel, status, statusLabel, credentialRegionIsAi, regionOn, showPointsInMainUi, onToggleShowPoints, creditPosition, onCreditPositionChange, savingPreferences, creditsLabelId, creditsHintId, rows, busy, rescanNote, onRescan, switchingAccount, onSwitchAccount, onClaim, onTransferChanged, poolDetails, poolClaims, models, deviceClaimed, onPoolChanged, onPoolRefresh, creditsUnavailable, creditsExpiry, alternatives, onSwitchToAlternative }) {
|
|
3121
|
+
const writable = settingsScope?.getSnapshot().writable === true;
|
|
3122
|
+
const signedIn = status.status === "signed-in";
|
|
3123
|
+
const accounts = signedIn ? status.accounts : [];
|
|
3124
|
+
const pool = signedIn ? status.pool : void 0;
|
|
3125
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
3126
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3127
|
+
className: "dsm-trae-prefs",
|
|
3128
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
3129
|
+
className: "dsm-trae-pref",
|
|
3130
|
+
title: t(credentialRegionIsAi ? "row.showPointsInMainUiHintAi" : "row.showPointsInMainUiHint"),
|
|
3131
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
3132
|
+
type: "checkbox",
|
|
3133
|
+
className: "dsm-trae-pref-check",
|
|
3134
|
+
checked: showPointsInMainUi,
|
|
3135
|
+
disabled: !writable || savingPreferences,
|
|
3136
|
+
"aria-describedby": creditsHintId,
|
|
3137
|
+
onChange: (event) => {
|
|
3138
|
+
onToggleShowPoints(event.currentTarget.checked);
|
|
3139
|
+
}
|
|
3140
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3141
|
+
className: "dsm-trae-pref-copy",
|
|
3142
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3143
|
+
className: "dsm-trae-pref-label",
|
|
3144
|
+
id: creditsLabelId,
|
|
3145
|
+
children: t("row.showPointsInMainUi")
|
|
3146
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3147
|
+
className: "dsm-trae-pref-hint",
|
|
3148
|
+
id: creditsHintId,
|
|
3149
|
+
children: t(credentialRegionIsAi ? "row.showPointsInMainUiHintAi" : "row.showPointsInMainUiHint")
|
|
3150
|
+
})]
|
|
3151
|
+
})]
|
|
3152
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
|
|
3153
|
+
className: "dsm-trae-pref dsm-trae-credit-position-pref",
|
|
3154
|
+
title: t("row.creditPositionHint"),
|
|
3155
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3156
|
+
className: "dsm-trae-pref-copy",
|
|
3157
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3158
|
+
className: "dsm-trae-pref-lead",
|
|
3159
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3160
|
+
className: "dsm-trae-pref-label",
|
|
3161
|
+
children: t("row.creditPositionLabel")
|
|
3162
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
3163
|
+
className: "dsm-trae-credit-position",
|
|
3164
|
+
value: regionOn ? creditPosition : "composer",
|
|
3165
|
+
disabled: !regionOn || !writable || savingPreferences,
|
|
3166
|
+
"aria-label": t("row.creditPositionAria", { region: panel === "cn" ? t("row.tabCn") : panel === "enterprise" ? t("row.tabEnterprise") : t("row.tabAi") }),
|
|
3167
|
+
onChange: (event) => {
|
|
3168
|
+
onCreditPositionChange(event.currentTarget.value === "stats" ? "stats" : "composer");
|
|
3169
|
+
},
|
|
3170
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
3171
|
+
value: "composer",
|
|
3172
|
+
children: t("row.creditPositionComposer")
|
|
3173
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
3174
|
+
value: "stats",
|
|
3175
|
+
children: t("row.creditPositionStats")
|
|
3176
|
+
})]
|
|
3177
|
+
})]
|
|
3178
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3179
|
+
className: "dsm-trae-pref-hint",
|
|
3180
|
+
children: t("row.creditPositionHint")
|
|
3181
|
+
})]
|
|
3182
|
+
})
|
|
3183
|
+
})]
|
|
3184
|
+
}),
|
|
3185
|
+
pool !== void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
3186
|
+
className: "dsm-trae-accounts",
|
|
3187
|
+
"aria-label": t("row.accountsTitle"),
|
|
3188
|
+
children: [
|
|
3189
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3190
|
+
className: "dsm-trae-accounts-head",
|
|
3191
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
|
|
3192
|
+
className: "dsm-trae-accounts-title",
|
|
3193
|
+
children: t("row.accountsTitle")
|
|
3194
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
3195
|
+
className: "dsm-trae-accounts-hint",
|
|
3196
|
+
children: t("row.accountsHint")
|
|
3197
|
+
})] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3198
|
+
type: "button",
|
|
3199
|
+
className: "dsm-btn dsm-btn-outline",
|
|
3200
|
+
disabled: busy,
|
|
3201
|
+
onClick: onRescan,
|
|
3202
|
+
children: busy ? t("row.accountsScanning") : t("row.refreshTokens")
|
|
3203
|
+
})]
|
|
3204
|
+
}),
|
|
3205
|
+
!signedIn || accounts.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3206
|
+
className: "dsm-trae-usage-account",
|
|
3207
|
+
role: "status",
|
|
3208
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3209
|
+
className: "dsm-trae-usage-account-copy",
|
|
3210
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3211
|
+
className: "dsm-trae-usage-status",
|
|
3212
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3213
|
+
"aria-hidden": "true",
|
|
3214
|
+
className: "dsm-trae-usage-dot",
|
|
3215
|
+
style: dotStyle(status.status)
|
|
3216
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: statusLabel })]
|
|
3217
|
+
}), signedIn ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3218
|
+
className: "dsm-trae-usage-expiry",
|
|
3219
|
+
children: t("row.tokenExpiry", { expiresAt: formatDateTime(status.tokenExpiresAtMs) })
|
|
3220
|
+
}) : null]
|
|
3221
|
+
})
|
|
3222
|
+
}) : null,
|
|
3223
|
+
status.status !== "error" && rows.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3224
|
+
className: `dsm-trae-account-table${credentialRegionIsAi ? "" : " dsm-trae-account-table-checkin"}`,
|
|
3225
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3226
|
+
className: "dsm-trae-account-row dsm-trae-account-row-head",
|
|
3227
|
+
role: "row",
|
|
3228
|
+
children: [
|
|
3229
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("row.accountColumnAccount") }),
|
|
3230
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("row.accountColumnValue") }),
|
|
3231
|
+
credentialRegionIsAi ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("row.accountColumnCheckin") }),
|
|
3232
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {})
|
|
3233
|
+
]
|
|
3234
|
+
}), rows.map((row) => {
|
|
3235
|
+
const warning = refreshTokenWarning(row.refreshExpiresAtMs, Date.now(), t, formatDateTime);
|
|
3236
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3237
|
+
className: `dsm-trae-account-row${row.current ? " dsm-trae-account-row-current" : ""}`,
|
|
3238
|
+
role: "row",
|
|
3239
|
+
children: [
|
|
3240
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3241
|
+
className: "dsm-trae-account-who",
|
|
3242
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3243
|
+
"aria-hidden": "true",
|
|
3244
|
+
className: "dsm-trae-usage-dot",
|
|
3245
|
+
style: dotStyle(row.selected ? "signed-in" : "signed-out")
|
|
3246
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3247
|
+
className: "dsm-trae-account-name",
|
|
3248
|
+
children: [
|
|
3249
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("b", { children: row.accountName }),
|
|
3250
|
+
row.current ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3251
|
+
className: "dsm-trae-account-badge",
|
|
3252
|
+
children: t("row.accountCurrentBadge")
|
|
3253
|
+
}) : null,
|
|
3254
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3255
|
+
className: "dsm-trae-account-meta",
|
|
3256
|
+
children: row.meta
|
|
3257
|
+
}),
|
|
3258
|
+
warning === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3259
|
+
className: `dsm-trae-refresh-warn dsm-trae-refresh-warn-${warning.tone}`,
|
|
3260
|
+
role: "status",
|
|
3261
|
+
children: warning.text
|
|
3262
|
+
}),
|
|
3263
|
+
row.error === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3264
|
+
className: "dsm-trae-account-note",
|
|
3265
|
+
role: "alert",
|
|
3266
|
+
children: row.error
|
|
3267
|
+
})
|
|
3268
|
+
]
|
|
3269
|
+
})]
|
|
3270
|
+
}),
|
|
3271
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3272
|
+
className: "dsm-trae-account-worth",
|
|
3273
|
+
children: row.value
|
|
3274
|
+
}),
|
|
3275
|
+
credentialRegionIsAi ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3276
|
+
className: "dsm-trae-account-checkin-cell",
|
|
3277
|
+
children: row.claim === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ClaimCell, {
|
|
3278
|
+
claim: row.claim,
|
|
3279
|
+
t,
|
|
3280
|
+
onClaim: () => {
|
|
3281
|
+
onClaim(row.id);
|
|
3282
|
+
}
|
|
3283
|
+
})
|
|
3284
|
+
}),
|
|
3285
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3286
|
+
className: "dsm-trae-account-actions",
|
|
3287
|
+
children: row.current ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3288
|
+
type: "button",
|
|
3289
|
+
className: "dsm-btn dsm-btn-outline dsm-trae-account-switch",
|
|
3290
|
+
disabled: switchingAccount || !writable,
|
|
3291
|
+
onClick: () => {
|
|
3292
|
+
onSwitchAccount(row.id);
|
|
3293
|
+
},
|
|
3294
|
+
children: switchingAccount ? t("row.accountSwitching") : t("row.accountSwitch")
|
|
3295
|
+
})
|
|
3296
|
+
})
|
|
3297
|
+
]
|
|
3298
|
+
}, row.id);
|
|
3299
|
+
})]
|
|
3300
|
+
}) : null,
|
|
3301
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(AccountTransfer, {
|
|
3302
|
+
t,
|
|
3303
|
+
region: panel === "ai" ? "ai" : "cn",
|
|
3304
|
+
accounts: accounts.map((account) => ({
|
|
3305
|
+
id: account.id,
|
|
3306
|
+
accountName: account.accountName
|
|
3307
|
+
})),
|
|
3308
|
+
onChanged: onTransferChanged
|
|
3309
|
+
})
|
|
3310
|
+
]
|
|
3311
|
+
}),
|
|
3312
|
+
signedIn && creditsUnavailable === "enterprise" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
3313
|
+
className: "dsm-trae-credits-unavailable",
|
|
3314
|
+
role: "note",
|
|
3315
|
+
children: t("row.enterpriseCreditsNotice")
|
|
3316
|
+
}) : null,
|
|
3317
|
+
signedIn && alternatives !== void 0 && alternatives.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3318
|
+
className: "dsm-trae-usage-alternative",
|
|
3319
|
+
role: "status",
|
|
3320
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
|
|
3321
|
+
className: "dsm-trae-usage-alternative-text",
|
|
3322
|
+
children: [
|
|
3323
|
+
t("row.creditsExhausted", { account: status.accountName }),
|
|
3324
|
+
" ",
|
|
3325
|
+
t("row.creditsAlternative", { accounts: alternatives.map((alt) => `${alt.accountName}(${t(`row.edition${alt.edition === "cn" ? "Cn" : alt.edition === "sg" ? "Sg" : alt.edition === "solo" ? "Solo" : "SoloSg"}`)}:${formatNumber(alt.workAvailable + alt.generalAvailable)})`).join("、") })
|
|
3326
|
+
]
|
|
3327
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3328
|
+
type: "button",
|
|
3329
|
+
className: "dsm-trae-usage-switch-button",
|
|
3330
|
+
disabled: switchingAccount || !writable,
|
|
3331
|
+
onClick: () => {
|
|
3332
|
+
const [target] = alternatives;
|
|
3333
|
+
if (target !== void 0) onSwitchToAlternative(target.id);
|
|
3334
|
+
},
|
|
3335
|
+
children: t("row.creditsAlternativeSwitch")
|
|
3336
|
+
})]
|
|
3337
|
+
}) : null,
|
|
3338
|
+
signedIn && creditsExpiry !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ExpiryNotice, {
|
|
3339
|
+
expiry: creditsExpiry,
|
|
3340
|
+
t
|
|
3341
|
+
}) : null,
|
|
3342
|
+
rescanNote === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
3343
|
+
className: "dsm-trae-usage-note",
|
|
3344
|
+
role: "status",
|
|
3345
|
+
children: rescanNote
|
|
3346
|
+
}),
|
|
3347
|
+
signedIn ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
3348
|
+
pool !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AccountPool, {
|
|
3349
|
+
panel,
|
|
3350
|
+
pool,
|
|
3351
|
+
models,
|
|
3352
|
+
t,
|
|
3353
|
+
settingsScope,
|
|
3354
|
+
topActions: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3355
|
+
type: "button",
|
|
3356
|
+
className: "dsm-btn dsm-btn-outline",
|
|
3357
|
+
disabled: busy,
|
|
3358
|
+
onClick: onRescan,
|
|
3359
|
+
children: busy ? t("row.accountsScanning") : t("row.poolRescan")
|
|
3360
|
+
}),
|
|
3361
|
+
tools: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3362
|
+
className: "dsm-trae-pool-tool-row",
|
|
3363
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3364
|
+
className: "dsm-trae-pool-tool-label",
|
|
3365
|
+
children: t("row.poolToolsLabel")
|
|
3366
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AccountTransfer, {
|
|
3367
|
+
t,
|
|
3368
|
+
hideLabel: true,
|
|
3369
|
+
region: panel === "ai" ? "ai" : "cn",
|
|
3370
|
+
accounts: accounts.map((account) => ({
|
|
3371
|
+
id: account.id,
|
|
3372
|
+
accountName: account.accountName
|
|
3373
|
+
})),
|
|
3374
|
+
onChanged: onTransferChanged
|
|
3375
|
+
})]
|
|
3376
|
+
}),
|
|
3377
|
+
details: poolDetails,
|
|
3378
|
+
claims: pool.checkinSupported === true ? poolClaims : void 0,
|
|
3379
|
+
onClaim,
|
|
3380
|
+
deviceClaimed,
|
|
3381
|
+
onBind: onSwitchAccount,
|
|
3382
|
+
bindingBusy: switchingAccount,
|
|
3383
|
+
onChanged: onPoolChanged,
|
|
3384
|
+
onRefresh: onPoolRefresh
|
|
3385
|
+
}) : null,
|
|
3386
|
+
status.checkin !== void 0 && !status.checkin.enabled ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
3387
|
+
className: "dsm-trae-usage-error",
|
|
3388
|
+
children: t("row.checkinDisabled")
|
|
3389
|
+
}) : null,
|
|
3390
|
+
status.checkinError === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
3391
|
+
className: "dsm-trae-usage-error",
|
|
3392
|
+
children: t("row.checkinError", { message: status.checkinError })
|
|
3393
|
+
})
|
|
3394
|
+
] }) : null
|
|
3395
|
+
] });
|
|
3396
|
+
}
|
|
3397
|
+
//#endregion
|
|
2931
3398
|
//#region src/client/plan-text.ts
|
|
2932
3399
|
/**
|
|
2933
3400
|
* The international region's "what plan is this account on" text.
|
|
@@ -3023,55 +3490,6 @@ window.__ModuleLoader__.load({
|
|
|
3023
3490
|
document.head.appendChild(styleTag);
|
|
3024
3491
|
}
|
|
3025
3492
|
}
|
|
3026
|
-
function formatNumber(value) {
|
|
3027
|
-
return new Intl.NumberFormat(void 0, {
|
|
3028
|
-
minimumFractionDigits: 0,
|
|
3029
|
-
maximumFractionDigits: 0
|
|
3030
|
-
}).format(value);
|
|
3031
|
-
}
|
|
3032
|
-
function formatDateTime(value) {
|
|
3033
|
-
return new Intl.DateTimeFormat(void 0, {
|
|
3034
|
-
year: "numeric",
|
|
3035
|
-
month: "2-digit",
|
|
3036
|
-
day: "2-digit",
|
|
3037
|
-
hour: "2-digit",
|
|
3038
|
-
minute: "2-digit"
|
|
3039
|
-
}).format(new Date(value));
|
|
3040
|
-
}
|
|
3041
|
-
/** How close a refresh token must be to lapsing before the card warns, in days. */
|
|
3042
|
-
const REFRESH_WARN_DAYS = 30;
|
|
3043
|
-
/**
|
|
3044
|
-
* The refresh-token warning for one account, or undefined when there is nothing
|
|
3045
|
-
* worth saying.
|
|
3046
|
-
*
|
|
3047
|
-
* The access token renews itself every few minutes, so its own expiry answers
|
|
3048
|
-
* "when does this need attention" with "never, until the refresh token lapses".
|
|
3049
|
-
* The refresh token is therefore the only honest countdown on this card, and it
|
|
3050
|
-
* has to be shown BEFORE it runs out: once it lapses the plugin cannot renew at
|
|
3051
|
-
* all and the only recovery is signing in to Trae again, which a user who has
|
|
3052
|
-
* been reading "auto-renewal" for months has no reason to expect.
|
|
3053
|
-
*
|
|
3054
|
-
* Three tones, matching the credit-expiry notice: `lapsed` (renewal already
|
|
3055
|
-
* dead), `soon` (inside the warning window), and nothing otherwise — a healthy
|
|
3056
|
-
* token must not add a line to every account row forever.
|
|
3057
|
-
*/
|
|
3058
|
-
function refreshTokenWarning(expiresAtMs, nowMs, t, formatTime) {
|
|
3059
|
-
if (expiresAtMs === void 0) return void 0;
|
|
3060
|
-
const text = formatTime(expiresAtMs);
|
|
3061
|
-
if (expiresAtMs <= nowMs) return {
|
|
3062
|
-
tone: "lapsed",
|
|
3063
|
-
text: t("row.refreshTokenLapsed", { expiresAt: text })
|
|
3064
|
-
};
|
|
3065
|
-
const days = Math.ceil((expiresAtMs - nowMs) / 864e5);
|
|
3066
|
-
if (days > REFRESH_WARN_DAYS) return void 0;
|
|
3067
|
-
return {
|
|
3068
|
-
tone: "soon",
|
|
3069
|
-
text: t("row.refreshTokenExpiring", {
|
|
3070
|
-
expiresAt: text,
|
|
3071
|
-
days
|
|
3072
|
-
})
|
|
3073
|
-
};
|
|
3074
|
-
}
|
|
3075
3493
|
function formatCapacity(value, unknown) {
|
|
3076
3494
|
if (value === void 0) return unknown;
|
|
3077
3495
|
if (value >= 1e6 && value % 1e6 === 0) return `${value / 1e6}M`;
|
|
@@ -3167,56 +3585,6 @@ window.__ModuleLoader__.load({
|
|
|
3167
3585
|
})
|
|
3168
3586
|
});
|
|
3169
3587
|
}
|
|
3170
|
-
function dotStyle(status) {
|
|
3171
|
-
return { background: status === "signed-in" ? "var(--dsw-alias-state-success-primary, #22a06b)" : status === "error" ? "var(--dsw-alias-state-error-primary, #d92d20)" : "var(--dsw-alias-label-dimmed, #9aa0a6)" };
|
|
3172
|
-
}
|
|
3173
|
-
/**
|
|
3174
|
-
* A warning that credit is about to lapse.
|
|
3175
|
-
*
|
|
3176
|
-
* The balance alone cannot express this: a pack lapsing in an hour and one
|
|
3177
|
-
* lapsing next month both render as "150", so a user watching only the total
|
|
3178
|
-
* loses the first one silently. The notice names the amount, the pack count and
|
|
3179
|
-
* the soonest expiry, and escalates 7d → 24h → already-lapsed.
|
|
3180
|
-
*
|
|
3181
|
-
* Renders nothing when the upstream reported no end times at all — absence of
|
|
3182
|
-
* expiry data is not evidence that nothing lapses, so the component stays
|
|
3183
|
-
* silent rather than reassuring.
|
|
3184
|
-
*/
|
|
3185
|
-
function ExpiryNotice({ expiry, t, formatNumber: fmt, formatDateTime: fmtTime }) {
|
|
3186
|
-
const { expired, within24h, within7d } = expiry;
|
|
3187
|
-
let message;
|
|
3188
|
-
let soonest;
|
|
3189
|
-
let tone;
|
|
3190
|
-
if (within24h.packs > 0) {
|
|
3191
|
-
message = t("row.expiryWarningSoon", {
|
|
3192
|
-
total: fmt(within24h.total),
|
|
3193
|
-
packs: String(within24h.packs)
|
|
3194
|
-
});
|
|
3195
|
-
soonest = within24h.earliestExpiresAtMs;
|
|
3196
|
-
tone = "dsm-trae-expiry-soon";
|
|
3197
|
-
} else if (within7d.packs > 0) {
|
|
3198
|
-
message = t("row.expiryWarningWeek", {
|
|
3199
|
-
total: fmt(within7d.total),
|
|
3200
|
-
packs: String(within7d.packs)
|
|
3201
|
-
});
|
|
3202
|
-
soonest = within7d.earliestExpiresAtMs;
|
|
3203
|
-
tone = "dsm-trae-expiry-week";
|
|
3204
|
-
} else if (expired.packs > 0) {
|
|
3205
|
-
message = t("row.expiryWarningLapsed", {
|
|
3206
|
-
total: fmt(expired.total),
|
|
3207
|
-
packs: String(expired.packs)
|
|
3208
|
-
});
|
|
3209
|
-
tone = "dsm-trae-expiry-lapsed";
|
|
3210
|
-
} else return null;
|
|
3211
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3212
|
-
className: `dsm-trae-expiry ${tone}`,
|
|
3213
|
-
role: "status",
|
|
3214
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: message }), soonest === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3215
|
-
className: "dsm-trae-expiry-detail",
|
|
3216
|
-
children: t("row.expiryEarliest", { time: fmtTime(soonest) })
|
|
3217
|
-
})]
|
|
3218
|
-
});
|
|
3219
|
-
}
|
|
3220
3588
|
/** Render Trae sign-in state and the total usage summary as one expandable card. */
|
|
3221
3589
|
function TraeUsageCard({ t, settingsScope, view }) {
|
|
3222
3590
|
if (t === void 0) throw new Error("Trae usage card requires its translation function");
|
|
@@ -3224,6 +3592,27 @@ window.__ModuleLoader__.load({
|
|
|
3224
3592
|
/** The region whose tab is on screen; each tab is its own provider stack. */
|
|
3225
3593
|
const [activeRegion, setActiveRegion] = (0, react.useState)("cn");
|
|
3226
3594
|
/**
|
|
3595
|
+
* Which of the card's three sections is on screen (learned from the sibling
|
|
3596
|
+
* `dsh-connect-workbuddy` card, whose settings page split for the same
|
|
3597
|
+
* reason).
|
|
3598
|
+
*
|
|
3599
|
+
* The card had grown into one long column mixing two unrelated jobs —
|
|
3600
|
+
* operating an account (who serves, how much is left, the check-in, the pool)
|
|
3601
|
+
* and editing the catalog (which models, image input, context budget) — and
|
|
3602
|
+
* the two do not even commit the same way: an account change lands on the
|
|
3603
|
+
* click, a catalog change is a draft until 「保存」. One column therefore put
|
|
3604
|
+
* the save button screens away from what it saves.
|
|
3605
|
+
*
|
|
3606
|
+
* The region row above stays the SCOPE (which provider this whole card is
|
|
3607
|
+
* about); these tabs are the sections of that one scope. Only the ACTIVE
|
|
3608
|
+
* section is visible, and the others stay MOUNTED through the `hidden`
|
|
3609
|
+
* attribute, so switching back never refetches, a half-filled model draft
|
|
3610
|
+
* survives the trip, and the pool keeps its log. `hidden` also takes the
|
|
3611
|
+
* inactive panel out of the accessibility tree, which is exactly what
|
|
3612
|
+
* `role="tabpanel"` wants.
|
|
3613
|
+
*/
|
|
3614
|
+
const [panel, setPanel] = (0, react.useState)("accounts");
|
|
3615
|
+
/**
|
|
3227
3616
|
* Last-known usage per region, so tab dots survive tab switches.
|
|
3228
3617
|
*
|
|
3229
3618
|
* A region is ABSENT until something has been read for it (issue #77). It used
|
|
@@ -3571,6 +3960,16 @@ window.__ModuleLoader__.load({
|
|
|
3571
3960
|
accounts: []
|
|
3572
3961
|
};
|
|
3573
3962
|
/**
|
|
3963
|
+
* Whether the ACTIVE panel has a usable sign-in.
|
|
3964
|
+
*
|
|
3965
|
+
* The section tabs render only here: a signed-out card is one screen of
|
|
3966
|
+
* instructions ("sign in once in the Trae app" plus the probed paths), and
|
|
3967
|
+
* splitting that into panels would hide the only thing it has to say behind a
|
|
3968
|
+
* tab the user cannot see the point of. The sibling WorkBuddy card made the
|
|
3969
|
+
* same call for the same reason.
|
|
3970
|
+
*/
|
|
3971
|
+
const signedIn = status.status === "signed-in";
|
|
3972
|
+
/**
|
|
3574
3973
|
* Clear in-flight claim state when the tab changes. `activeRegion` is a single
|
|
3575
3974
|
* value across both tabs, so a switch must not leave one row's claim spinning
|
|
3576
3975
|
* under the other tab.
|
|
@@ -4262,23 +4661,63 @@ window.__ModuleLoader__.load({
|
|
|
4262
4661
|
settled: claimed ? "claimed" : deviceSpent ? "device" : void 0
|
|
4263
4662
|
};
|
|
4264
4663
|
};
|
|
4265
|
-
|
|
4266
|
-
|
|
4267
|
-
|
|
4268
|
-
|
|
4269
|
-
|
|
4270
|
-
|
|
4271
|
-
|
|
4272
|
-
|
|
4273
|
-
|
|
4274
|
-
|
|
4275
|
-
|
|
4276
|
-
|
|
4277
|
-
|
|
4278
|
-
|
|
4279
|
-
|
|
4280
|
-
|
|
4281
|
-
|
|
4664
|
+
/**
|
|
4665
|
+
* The account roster, ALREADY JUDGED — one row per locally detected sign-in.
|
|
4666
|
+
*
|
|
4667
|
+
* Every verdict the table draws is decided here rather than in the section
|
|
4668
|
+
* component, because each one is a rule with a write or a Host answer behind
|
|
4669
|
+
* it: which account is serving (the document's own `accountId`, or the
|
|
4670
|
+
* roster's `selected` flag when signed out), what an account is worth
|
|
4671
|
+
* (`rowValue`, judged by CREDENTIAL region so the enterprise panel reads CN
|
|
4672
|
+
* balances), and whether a row may claim (`claimViewOf`, which knows the
|
|
4673
|
+
* device-wide check-in rule). A section that re-derived any of them could
|
|
4674
|
+
* disagree with the pool table below it, which reads the same three answers.
|
|
4675
|
+
*/
|
|
4676
|
+
const accountRows = status.status === "error" ? [] : (status.accounts ?? []).map((account) => {
|
|
4677
|
+
const current = status.status === "signed-in" ? account.id === status.accountId : account.selected === true;
|
|
4678
|
+
const state = accountStatusByRegion[activeRegion][account.id];
|
|
4679
|
+
const error = claimErrorByRegion[activeRegion][account.id];
|
|
4680
|
+
return {
|
|
4681
|
+
id: account.id,
|
|
4682
|
+
accountName: account.accountName,
|
|
4683
|
+
current,
|
|
4684
|
+
selected: account.selected === true,
|
|
4685
|
+
meta: `${editionLabel(account.edition)} · ${sourceLabel(account.source)}`,
|
|
4686
|
+
value: rowValue(state),
|
|
4687
|
+
refreshExpiresAtMs: account.refreshExpiresAtMs,
|
|
4688
|
+
error: error === void 0 ? void 0 : t("row.checkinError", { message: error }),
|
|
4689
|
+
claim: isCnPool ? (() => {
|
|
4690
|
+
const view = claimViewOf(account.id, state);
|
|
4691
|
+
return {
|
|
4692
|
+
label: view.label,
|
|
4693
|
+
title: view.title,
|
|
4694
|
+
disabled: view.disabled,
|
|
4695
|
+
busy: view.busy,
|
|
4696
|
+
claimable: view.claimable,
|
|
4697
|
+
settled: view.settled
|
|
4698
|
+
};
|
|
4699
|
+
})() : void 0
|
|
4700
|
+
};
|
|
4701
|
+
});
|
|
4702
|
+
/**
|
|
4703
|
+
* The pool's per-row details, joined from the roster above by id.
|
|
4704
|
+
*
|
|
4705
|
+
* The pool document carries the accounts but not their edition, source or
|
|
4706
|
+
* refresh-token countdown, so those three are spliced in here — by the same
|
|
4707
|
+
* `editionLabel` / `sourceLabel` / `refreshTokenWarning` the roster uses, so
|
|
4708
|
+
* one account cannot read "国内版 · 桌面端" in one table and something else in
|
|
4709
|
+
* the next.
|
|
4710
|
+
*/
|
|
4711
|
+
const poolDetails = Object.fromEntries((status.status === "signed-in" ? status.accounts : []).map((account) => {
|
|
4712
|
+
const warn = refreshTokenWarning(account.refreshExpiresAtMs, Date.now(), t, formatDateTime);
|
|
4713
|
+
return [account.id, {
|
|
4714
|
+
meta: `${editionLabel(account.edition)} · ${sourceLabel(account.source)}`,
|
|
4715
|
+
...warn === void 0 ? {} : {
|
|
4716
|
+
warn: warn.text,
|
|
4717
|
+
warnTone: warn.tone
|
|
4718
|
+
}
|
|
4719
|
+
}];
|
|
4720
|
+
}));
|
|
4282
4721
|
const label = loading ? t("row.accountsLoading") : status.status === "signed-in" ? t("row.signedIn", { accountName: status.accountName }) : status.status === "error" ? t("row.requestFailed") : t("row.signedOut");
|
|
4283
4722
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
|
|
4284
4723
|
className: `dsm-plugin-card${open ? " dsm-plugin-card-open" : ""}`,
|
|
@@ -4372,324 +4811,127 @@ window.__ModuleLoader__.load({
|
|
|
4372
4811
|
role: "status",
|
|
4373
4812
|
children: t("row.tabOffNotice")
|
|
4374
4813
|
}),
|
|
4375
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4376
|
-
className: "dsm-trae-
|
|
4377
|
-
|
|
4378
|
-
|
|
4379
|
-
title: t(isCnPool ? "row.showPointsInMainUiHint" : "row.showPointsInMainUiHintAi"),
|
|
4380
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
4381
|
-
type: "checkbox",
|
|
4382
|
-
className: "dsm-trae-pref-check",
|
|
4383
|
-
checked: settingsEdits.showPointsInMainUi,
|
|
4384
|
-
disabled: settingsScope?.getSnapshot().writable !== true || savingSettings,
|
|
4385
|
-
"aria-describedby": creditsHintId,
|
|
4386
|
-
onChange: (event) => {
|
|
4387
|
-
writePreference("showPointsInMainUi", event.currentTarget.checked);
|
|
4388
|
-
}
|
|
4389
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
4390
|
-
className: "dsm-trae-pref-copy",
|
|
4391
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4392
|
-
className: "dsm-trae-pref-label",
|
|
4393
|
-
id: creditsLabelId,
|
|
4394
|
-
children: t("row.showPointsInMainUi")
|
|
4395
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4396
|
-
className: "dsm-trae-pref-hint",
|
|
4397
|
-
id: creditsHintId,
|
|
4398
|
-
children: t(isCnPool ? "row.showPointsInMainUiHint" : "row.showPointsInMainUiHintAi")
|
|
4399
|
-
})]
|
|
4400
|
-
})]
|
|
4401
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
|
|
4402
|
-
className: "dsm-trae-pref dsm-trae-credit-position-pref",
|
|
4403
|
-
title: t("row.creditPositionHint"),
|
|
4404
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
4405
|
-
className: "dsm-trae-pref-copy",
|
|
4406
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
4407
|
-
className: "dsm-trae-pref-lead",
|
|
4408
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4409
|
-
className: "dsm-trae-pref-label",
|
|
4410
|
-
children: t("row.creditPositionLabel")
|
|
4411
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
4412
|
-
className: "dsm-trae-credit-position",
|
|
4413
|
-
value: activeRegionOn ? creditPositionOn(activeRegion) : "composer",
|
|
4414
|
-
disabled: !activeRegionOn || settingsScope?.getSnapshot().writable !== true || savingSettings,
|
|
4415
|
-
"aria-label": t("row.creditPositionAria", { region: activeRegion === "cn" ? t("row.tabCn") : activeRegion === "enterprise" ? t("row.tabEnterprise") : t("row.tabAi") }),
|
|
4416
|
-
onChange: (event) => {
|
|
4417
|
-
changeCreditPosition(activeRegion, event.currentTarget.value === "stats" ? "stats" : "composer");
|
|
4418
|
-
},
|
|
4419
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
4420
|
-
value: "composer",
|
|
4421
|
-
children: t("row.creditPositionComposer")
|
|
4422
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
4423
|
-
value: "stats",
|
|
4424
|
-
children: t("row.creditPositionStats")
|
|
4425
|
-
})]
|
|
4426
|
-
})]
|
|
4427
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4428
|
-
className: "dsm-trae-pref-hint",
|
|
4429
|
-
children: t("row.creditPositionHint")
|
|
4430
|
-
})]
|
|
4431
|
-
})
|
|
4432
|
-
})]
|
|
4433
|
-
}),
|
|
4434
|
-
status.status === "signed-in" && status.pool !== void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
4435
|
-
className: "dsm-trae-accounts",
|
|
4436
|
-
"aria-label": t("row.accountsTitle"),
|
|
4814
|
+
signedIn ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4815
|
+
className: "dsm-trae-panels",
|
|
4816
|
+
role: "tablist",
|
|
4817
|
+
"aria-label": t("row.panelAria"),
|
|
4437
4818
|
children: [
|
|
4438
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
4439
|
-
|
|
4440
|
-
|
|
4441
|
-
|
|
4442
|
-
|
|
4443
|
-
|
|
4444
|
-
|
|
4445
|
-
|
|
4446
|
-
|
|
4447
|
-
|
|
4448
|
-
|
|
4449
|
-
disabled: busy,
|
|
4450
|
-
onClick: () => {
|
|
4451
|
-
rescanAccounts();
|
|
4452
|
-
},
|
|
4453
|
-
children: busy ? t("row.accountsScanning") : t("row.refreshTokens")
|
|
4454
|
-
})]
|
|
4819
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4820
|
+
type: "button",
|
|
4821
|
+
role: "tab",
|
|
4822
|
+
id: "dsm-trae-tab-accounts",
|
|
4823
|
+
"aria-controls": "dsm-trae-panel-accounts",
|
|
4824
|
+
"aria-selected": panel === "accounts",
|
|
4825
|
+
className: `dsm-trae-panel-tab${panel === "accounts" ? " dsm-trae-panel-tab-active" : ""}`,
|
|
4826
|
+
onClick: () => {
|
|
4827
|
+
setPanel("accounts");
|
|
4828
|
+
},
|
|
4829
|
+
children: t("row.panelAccounts")
|
|
4455
4830
|
}),
|
|
4456
|
-
|
|
4457
|
-
|
|
4458
|
-
role: "
|
|
4459
|
-
|
|
4460
|
-
|
|
4461
|
-
|
|
4462
|
-
|
|
4463
|
-
|
|
4464
|
-
|
|
4465
|
-
|
|
4466
|
-
|
|
4467
|
-
|
|
4468
|
-
|
|
4469
|
-
|
|
4470
|
-
|
|
4471
|
-
|
|
4472
|
-
|
|
4473
|
-
|
|
4474
|
-
|
|
4475
|
-
|
|
4476
|
-
|
|
4477
|
-
|
|
4478
|
-
|
|
4479
|
-
children: [
|
|
4480
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("row.accountColumnAccount") }),
|
|
4481
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("row.accountColumnValue") }),
|
|
4482
|
-
isCnPool ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("row.accountColumnCheckin") }) : null,
|
|
4483
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {})
|
|
4484
|
-
]
|
|
4485
|
-
}), status.accounts.map((account) => {
|
|
4486
|
-
const current = status.status === "signed-in" ? account.id === status.accountId : account.selected === true;
|
|
4487
|
-
const state = accountStatusByRegion[activeRegion][account.id];
|
|
4488
|
-
const error = claimErrorByRegion[activeRegion][account.id];
|
|
4489
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4490
|
-
className: `dsm-trae-account-row${current ? " dsm-trae-account-row-current" : ""}`,
|
|
4491
|
-
role: "row",
|
|
4492
|
-
children: [
|
|
4493
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
4494
|
-
className: "dsm-trae-account-who",
|
|
4495
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4496
|
-
"aria-hidden": "true",
|
|
4497
|
-
className: "dsm-trae-usage-dot",
|
|
4498
|
-
style: dotStyle(account.selected ? "signed-in" : "signed-out")
|
|
4499
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
4500
|
-
className: "dsm-trae-account-name",
|
|
4501
|
-
children: [
|
|
4502
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("b", { children: account.accountName }),
|
|
4503
|
-
current ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4504
|
-
className: "dsm-trae-account-badge",
|
|
4505
|
-
children: t("row.accountCurrentBadge")
|
|
4506
|
-
}) : null,
|
|
4507
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
4508
|
-
className: "dsm-trae-account-meta",
|
|
4509
|
-
children: [
|
|
4510
|
-
editionLabel(account.edition),
|
|
4511
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("i", {
|
|
4512
|
-
"aria-hidden": "true",
|
|
4513
|
-
children: "·"
|
|
4514
|
-
}),
|
|
4515
|
-
sourceLabel(account.source)
|
|
4516
|
-
]
|
|
4517
|
-
}),
|
|
4518
|
-
(() => {
|
|
4519
|
-
const warning = refreshTokenWarning(account.refreshExpiresAtMs, Date.now(), t, formatDateTime);
|
|
4520
|
-
return warning === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4521
|
-
className: `dsm-trae-refresh-warn dsm-trae-refresh-warn-${warning.tone}`,
|
|
4522
|
-
role: "status",
|
|
4523
|
-
children: warning.text
|
|
4524
|
-
});
|
|
4525
|
-
})(),
|
|
4526
|
-
error === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4527
|
-
className: "dsm-trae-account-note",
|
|
4528
|
-
role: "alert",
|
|
4529
|
-
children: t("row.checkinError", { message: error })
|
|
4530
|
-
})
|
|
4531
|
-
]
|
|
4532
|
-
})]
|
|
4533
|
-
}),
|
|
4534
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4535
|
-
className: "dsm-trae-account-worth",
|
|
4536
|
-
children: rowValue(state)
|
|
4537
|
-
}),
|
|
4538
|
-
isCnPool ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4539
|
-
className: "dsm-trae-account-checkin-cell",
|
|
4540
|
-
children: checkinControl(account, state)
|
|
4541
|
-
}) : null,
|
|
4542
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4543
|
-
className: "dsm-trae-account-actions",
|
|
4544
|
-
children: current ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4545
|
-
type: "button",
|
|
4546
|
-
className: "dsm-btn dsm-btn-outline dsm-trae-account-switch",
|
|
4547
|
-
disabled: switchingAccount || settingsScope?.getSnapshot()?.writable !== true,
|
|
4548
|
-
onClick: () => {
|
|
4549
|
-
switchAccount(account.id);
|
|
4550
|
-
},
|
|
4551
|
-
children: switchingAccount ? t("row.accountSwitching") : t("row.accountSwitch")
|
|
4552
|
-
})
|
|
4553
|
-
})
|
|
4554
|
-
]
|
|
4555
|
-
}, account.id);
|
|
4556
|
-
})]
|
|
4557
|
-
}) : null,
|
|
4558
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(AccountTransfer, {
|
|
4559
|
-
t,
|
|
4560
|
-
region: activeRegion === "ai" ? "ai" : "cn",
|
|
4561
|
-
accounts: status.status === "signed-in" ? status.accounts.map((account) => ({
|
|
4562
|
-
id: account.id,
|
|
4563
|
-
accountName: account.accountName
|
|
4564
|
-
})) : [],
|
|
4565
|
-
onChanged: async () => {
|
|
4566
|
-
const fresh = await refreshUsage(activeRegion);
|
|
4567
|
-
if (fresh !== void 0) setStatusByRegion((current) => ({
|
|
4568
|
-
...current,
|
|
4569
|
-
[activeRegion]: fresh
|
|
4570
|
-
}));
|
|
4571
|
-
}
|
|
4831
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4832
|
+
type: "button",
|
|
4833
|
+
role: "tab",
|
|
4834
|
+
id: "dsm-trae-tab-models",
|
|
4835
|
+
"aria-controls": "dsm-trae-panel-models",
|
|
4836
|
+
"aria-selected": panel === "models",
|
|
4837
|
+
className: `dsm-trae-panel-tab${panel === "models" ? " dsm-trae-panel-tab-active" : ""}`,
|
|
4838
|
+
onClick: () => {
|
|
4839
|
+
setPanel("models");
|
|
4840
|
+
},
|
|
4841
|
+
children: t("row.panelModels")
|
|
4842
|
+
}),
|
|
4843
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4844
|
+
type: "button",
|
|
4845
|
+
role: "tab",
|
|
4846
|
+
id: "dsm-trae-tab-diag",
|
|
4847
|
+
"aria-controls": "dsm-trae-panel-diag",
|
|
4848
|
+
"aria-selected": panel === "diag",
|
|
4849
|
+
className: `dsm-trae-panel-tab${panel === "diag" ? " dsm-trae-panel-tab-active" : ""}`,
|
|
4850
|
+
onClick: () => {
|
|
4851
|
+
setPanel("diag");
|
|
4852
|
+
},
|
|
4853
|
+
children: t("row.panelDiag")
|
|
4572
4854
|
})
|
|
4573
4855
|
]
|
|
4574
|
-
}),
|
|
4575
|
-
status.status === "signed-in" && status.creditsUnavailable === "enterprise" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4576
|
-
className: "dsm-trae-credits-unavailable",
|
|
4577
|
-
role: "note",
|
|
4578
|
-
children: t("row.enterpriseCreditsNotice")
|
|
4579
|
-
}) : null,
|
|
4580
|
-
status.status === "signed-in" && status.alternatives !== void 0 && status.alternatives.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4581
|
-
className: "dsm-trae-usage-alternative",
|
|
4582
|
-
role: "status",
|
|
4583
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
|
|
4584
|
-
className: "dsm-trae-usage-alternative-text",
|
|
4585
|
-
children: [
|
|
4586
|
-
t("row.creditsExhausted", { account: status.accountName }),
|
|
4587
|
-
" ",
|
|
4588
|
-
t("row.creditsAlternative", { accounts: status.alternatives.map((alt) => `${alt.accountName}(${t(`row.edition${alt.edition === "cn" ? "Cn" : alt.edition === "sg" ? "Sg" : alt.edition === "solo" ? "Solo" : "SoloSg"}`)}:${formatNumber(alt.workAvailable + alt.generalAvailable)})`).join("、") })
|
|
4589
|
-
]
|
|
4590
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4591
|
-
type: "button",
|
|
4592
|
-
className: "dsm-trae-usage-switch-button",
|
|
4593
|
-
disabled: switchingAccount || settingsScope?.getSnapshot()?.writable !== true,
|
|
4594
|
-
onClick: () => {
|
|
4595
|
-
const target = status.alternatives?.[0];
|
|
4596
|
-
if (target !== void 0) switchAccount(target.id);
|
|
4597
|
-
},
|
|
4598
|
-
children: t("row.creditsAlternativeSwitch")
|
|
4599
|
-
})]
|
|
4600
|
-
}) : null,
|
|
4601
|
-
status.status === "signed-in" && status.credits?.expiry !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ExpiryNotice, {
|
|
4602
|
-
expiry: status.credits.expiry,
|
|
4603
|
-
t,
|
|
4604
|
-
formatNumber,
|
|
4605
|
-
formatDateTime
|
|
4606
4856
|
}) : null,
|
|
4607
|
-
|
|
4608
|
-
className: "dsm-trae-
|
|
4609
|
-
role: "
|
|
4610
|
-
|
|
4611
|
-
|
|
4612
|
-
|
|
4613
|
-
|
|
4614
|
-
panel: activeRegion,
|
|
4615
|
-
pool: status.pool,
|
|
4616
|
-
models: visibleModels,
|
|
4857
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4858
|
+
className: "dsm-trae-panel",
|
|
4859
|
+
role: "tabpanel",
|
|
4860
|
+
id: "dsm-trae-panel-accounts",
|
|
4861
|
+
"aria-labelledby": "dsm-trae-tab-accounts",
|
|
4862
|
+
hidden: signedIn && panel !== "accounts",
|
|
4863
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TraeAccountPanel, {
|
|
4617
4864
|
t,
|
|
4618
4865
|
settingsScope,
|
|
4619
|
-
|
|
4620
|
-
|
|
4621
|
-
|
|
4622
|
-
|
|
4623
|
-
|
|
4624
|
-
|
|
4625
|
-
|
|
4626
|
-
|
|
4627
|
-
}
|
|
4628
|
-
|
|
4629
|
-
|
|
4630
|
-
|
|
4631
|
-
|
|
4632
|
-
|
|
4633
|
-
|
|
4634
|
-
|
|
4635
|
-
|
|
4636
|
-
|
|
4637
|
-
|
|
4638
|
-
|
|
4639
|
-
|
|
4640
|
-
|
|
4641
|
-
|
|
4642
|
-
|
|
4643
|
-
|
|
4644
|
-
|
|
4645
|
-
[activeRegion]: fresh
|
|
4646
|
-
}));
|
|
4647
|
-
}
|
|
4648
|
-
})]
|
|
4649
|
-
}),
|
|
4650
|
-
details: Object.fromEntries(status.accounts.map((account) => {
|
|
4651
|
-
const warn = refreshTokenWarning(account.refreshExpiresAtMs, Date.now(), t, formatDateTime);
|
|
4652
|
-
return [account.id, {
|
|
4653
|
-
meta: `${editionLabel(account.edition)} · ${sourceLabel(account.source)}`,
|
|
4654
|
-
...warn === void 0 ? {} : {
|
|
4655
|
-
warn: warn.text,
|
|
4656
|
-
warnTone: warn.tone
|
|
4657
|
-
}
|
|
4658
|
-
}];
|
|
4659
|
-
})),
|
|
4660
|
-
claims: status.pool.checkinSupported === true ? Object.fromEntries(status.accounts.map((account) => [account.id, claimViewOf(account.id, accountStatusByRegion[activeRegion][account.id])])) : void 0,
|
|
4866
|
+
panel: activeRegion,
|
|
4867
|
+
status,
|
|
4868
|
+
statusLabel: label,
|
|
4869
|
+
credentialRegionIsAi,
|
|
4870
|
+
regionOn: activeRegionOn,
|
|
4871
|
+
showPointsInMainUi: settingsEdits.showPointsInMainUi,
|
|
4872
|
+
onToggleShowPoints: (value) => {
|
|
4873
|
+
writePreference("showPointsInMainUi", value);
|
|
4874
|
+
},
|
|
4875
|
+
creditPosition: creditPositionOn(activeRegion),
|
|
4876
|
+
onCreditPositionChange: (position) => {
|
|
4877
|
+
changeCreditPosition(activeRegion, position);
|
|
4878
|
+
},
|
|
4879
|
+
savingPreferences: savingSettings,
|
|
4880
|
+
creditsLabelId,
|
|
4881
|
+
creditsHintId,
|
|
4882
|
+
rows: accountRows,
|
|
4883
|
+
busy,
|
|
4884
|
+
rescanNote,
|
|
4885
|
+
onRescan: () => {
|
|
4886
|
+
rescanAccounts();
|
|
4887
|
+
},
|
|
4888
|
+
switchingAccount,
|
|
4889
|
+
onSwitchAccount: (accountId) => {
|
|
4890
|
+
switchAccount(accountId);
|
|
4891
|
+
},
|
|
4661
4892
|
onClaim: (accountId) => {
|
|
4662
4893
|
claimFor(accountId);
|
|
4663
4894
|
},
|
|
4664
|
-
|
|
4665
|
-
|
|
4666
|
-
|
|
4895
|
+
onTransferChanged: async () => {
|
|
4896
|
+
const fresh = await refreshUsage(activeRegion);
|
|
4897
|
+
if (fresh !== void 0) setStatusByRegion((current) => ({
|
|
4898
|
+
...current,
|
|
4899
|
+
[activeRegion]: fresh
|
|
4900
|
+
}));
|
|
4667
4901
|
},
|
|
4668
|
-
|
|
4669
|
-
|
|
4902
|
+
poolDetails,
|
|
4903
|
+
poolClaims: status.status === "signed-in" && status.pool?.checkinSupported === true ? Object.fromEntries(status.accounts.map((account) => [account.id, claimViewOf(account.id, accountStatusByRegion[activeRegion][account.id])])) : void 0,
|
|
4904
|
+
models: visibleModels,
|
|
4905
|
+
deviceClaimed: deviceClaimedToday,
|
|
4906
|
+
onPoolChanged: async () => {
|
|
4670
4907
|
const fresh = await refreshUsage(activeRegion);
|
|
4671
4908
|
if (fresh !== void 0) setStatusByRegion((current) => ({
|
|
4672
4909
|
...current,
|
|
4673
4910
|
[activeRegion]: fresh
|
|
4674
4911
|
}));
|
|
4675
4912
|
},
|
|
4676
|
-
|
|
4913
|
+
onPoolRefresh: async () => {
|
|
4677
4914
|
const fresh = await refreshUsage(activeRegion);
|
|
4678
4915
|
if (fresh !== void 0) setStatusByRegion((current) => ({
|
|
4679
4916
|
...current,
|
|
4680
4917
|
[activeRegion]: fresh
|
|
4681
4918
|
}));
|
|
4919
|
+
},
|
|
4920
|
+
creditsUnavailable: status.status === "signed-in" ? status.creditsUnavailable : void 0,
|
|
4921
|
+
creditsExpiry: status.status === "signed-in" ? status.credits?.expiry : void 0,
|
|
4922
|
+
alternatives: status.status === "signed-in" ? status.alternatives : void 0,
|
|
4923
|
+
onSwitchToAlternative: (accountId) => {
|
|
4924
|
+
switchAccount(accountId);
|
|
4682
4925
|
}
|
|
4683
|
-
})
|
|
4684
|
-
|
|
4685
|
-
|
|
4686
|
-
|
|
4687
|
-
|
|
4688
|
-
|
|
4689
|
-
|
|
4690
|
-
|
|
4691
|
-
|
|
4692
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
4926
|
+
})
|
|
4927
|
+
}),
|
|
4928
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4929
|
+
className: "dsm-trae-panel",
|
|
4930
|
+
role: "tabpanel",
|
|
4931
|
+
id: "dsm-trae-panel-models",
|
|
4932
|
+
"aria-labelledby": "dsm-trae-tab-models",
|
|
4933
|
+
hidden: !signedIn || panel !== "models",
|
|
4934
|
+
children: signedIn ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
4693
4935
|
className: "dsm-trae-models",
|
|
4694
4936
|
"aria-label": t("row.modelsTitle"),
|
|
4695
4937
|
children: [
|
|
@@ -4883,8 +5125,143 @@ window.__ModuleLoader__.load({
|
|
|
4883
5125
|
})]
|
|
4884
5126
|
})
|
|
4885
5127
|
]
|
|
4886
|
-
})
|
|
4887
|
-
|
|
5128
|
+
}) }) : null
|
|
5129
|
+
}),
|
|
5130
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5131
|
+
className: "dsm-trae-panel",
|
|
5132
|
+
role: "tabpanel",
|
|
5133
|
+
id: "dsm-trae-panel-diag",
|
|
5134
|
+
"aria-labelledby": "dsm-trae-tab-diag",
|
|
5135
|
+
hidden: !signedIn || panel !== "diag",
|
|
5136
|
+
children: status.status !== "signed-in" || panel !== "diag" ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5137
|
+
className: "dsm-trae-diag",
|
|
5138
|
+
children: [
|
|
5139
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5140
|
+
className: "dsm-trae-diag-row",
|
|
5141
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5142
|
+
className: "dsm-trae-diag-label",
|
|
5143
|
+
children: t("row.diagRegion")
|
|
5144
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5145
|
+
className: "dsm-trae-diag-value",
|
|
5146
|
+
children: activeRegion === "cn" ? t("row.tabCn") : activeRegion === "enterprise" ? t("row.tabEnterprise") : t("row.tabAi")
|
|
5147
|
+
})]
|
|
5148
|
+
}),
|
|
5149
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5150
|
+
className: "dsm-trae-diag-row",
|
|
5151
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5152
|
+
className: "dsm-trae-diag-label",
|
|
5153
|
+
children: t("row.diagProvider")
|
|
5154
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5155
|
+
className: "dsm-trae-diag-value dsm-trae-diag-mono",
|
|
5156
|
+
children: providerOfPanel(activeRegion)
|
|
5157
|
+
})]
|
|
5158
|
+
}),
|
|
5159
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5160
|
+
className: "dsm-trae-diag-row",
|
|
5161
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5162
|
+
className: "dsm-trae-diag-label",
|
|
5163
|
+
children: t("row.diagAccount")
|
|
5164
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5165
|
+
className: "dsm-trae-diag-value",
|
|
5166
|
+
children: status.accountName
|
|
5167
|
+
})]
|
|
5168
|
+
}),
|
|
5169
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5170
|
+
className: "dsm-trae-diag-row",
|
|
5171
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5172
|
+
className: "dsm-trae-diag-label",
|
|
5173
|
+
children: t("row.diagToken")
|
|
5174
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5175
|
+
className: "dsm-trae-diag-value dsm-trae-diag-mono",
|
|
5176
|
+
children: formatDateTime(status.tokenExpiresAtMs)
|
|
5177
|
+
})]
|
|
5178
|
+
}),
|
|
5179
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5180
|
+
className: "dsm-trae-diag-row",
|
|
5181
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5182
|
+
className: "dsm-trae-diag-label",
|
|
5183
|
+
children: t("row.diagRefresh")
|
|
5184
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5185
|
+
className: "dsm-trae-diag-value dsm-trae-diag-mono",
|
|
5186
|
+
children: status.refreshExpiresAtMs === void 0 ? t("row.diagRefreshNone") : formatDateTime(status.refreshExpiresAtMs)
|
|
5187
|
+
})]
|
|
5188
|
+
}),
|
|
5189
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5190
|
+
className: "dsm-trae-diag-row",
|
|
5191
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5192
|
+
className: "dsm-trae-diag-label",
|
|
5193
|
+
children: t("row.diagCatalog")
|
|
5194
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5195
|
+
className: "dsm-trae-diag-value",
|
|
5196
|
+
children: formatNumber(status.models.length)
|
|
5197
|
+
})]
|
|
5198
|
+
}),
|
|
5199
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5200
|
+
className: "dsm-trae-diag-row",
|
|
5201
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5202
|
+
className: "dsm-trae-diag-label",
|
|
5203
|
+
children: t("row.diagEnabled")
|
|
5204
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5205
|
+
className: "dsm-trae-diag-value",
|
|
5206
|
+
children: formatNumber(status.enabledModelIds.length)
|
|
5207
|
+
})]
|
|
5208
|
+
}),
|
|
5209
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5210
|
+
className: "dsm-trae-diag-row",
|
|
5211
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5212
|
+
className: "dsm-trae-diag-label",
|
|
5213
|
+
children: t("row.diagPool")
|
|
5214
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5215
|
+
className: "dsm-trae-diag-value",
|
|
5216
|
+
children: status.pool === void 0 ? t("row.diagPoolOff") : status.pool.enabled ? t("row.diagPoolOn", { count: status.pool.effectiveMemberAccountIds?.length ?? status.pool.accounts.length }) : t("row.diagPoolOff")
|
|
5217
|
+
})]
|
|
5218
|
+
}),
|
|
5219
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5220
|
+
className: "dsm-trae-diag-row",
|
|
5221
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5222
|
+
className: "dsm-trae-diag-label",
|
|
5223
|
+
children: t("row.diagCheckin")
|
|
5224
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5225
|
+
className: "dsm-trae-diag-value",
|
|
5226
|
+
children: status.checkin !== void 0 || status.pool?.checkinSupported === true ? t("row.diagCheckinOn") : t("row.diagCheckinOff")
|
|
5227
|
+
})]
|
|
5228
|
+
}),
|
|
5229
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5230
|
+
className: "dsm-trae-diag-row",
|
|
5231
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5232
|
+
className: "dsm-trae-diag-label",
|
|
5233
|
+
children: t("row.diagRaw")
|
|
5234
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5235
|
+
className: "dsm-trae-diag-value dsm-trae-diag-mono",
|
|
5236
|
+
children: status.rawChat === void 0 ? t("row.diagRawOff") : status.rawChat.state
|
|
5237
|
+
})]
|
|
5238
|
+
}),
|
|
5239
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5240
|
+
className: "dsm-trae-diag-row",
|
|
5241
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5242
|
+
className: "dsm-trae-diag-label",
|
|
5243
|
+
children: t("row.diagFailures")
|
|
5244
|
+
}), (() => {
|
|
5245
|
+
const failures = [];
|
|
5246
|
+
if (status.creditsError !== void 0) failures.push(status.creditsError);
|
|
5247
|
+
if (status.payStatusError !== void 0) failures.push(status.payStatusError);
|
|
5248
|
+
if (status.checkinError !== void 0) failures.push(status.checkinError);
|
|
5249
|
+
if (writeError !== void 0) failures.push(writeError);
|
|
5250
|
+
return failures.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5251
|
+
className: "dsm-trae-diag-value",
|
|
5252
|
+
children: t("row.diagNoFailures")
|
|
5253
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5254
|
+
className: "dsm-trae-diag-value dsm-trae-diag-bad dsm-trae-diag-mono",
|
|
5255
|
+
children: failures.join(" · ")
|
|
5256
|
+
});
|
|
5257
|
+
})()]
|
|
5258
|
+
})
|
|
5259
|
+
]
|
|
5260
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5261
|
+
className: "dsm-trae-diag-hint",
|
|
5262
|
+
children: t("row.diagHint")
|
|
5263
|
+
})] })
|
|
5264
|
+
}),
|
|
4888
5265
|
status.status === "signed-out" && loading ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4889
5266
|
className: "dsm-trae-usage-text",
|
|
4890
5267
|
role: "status",
|
|
@@ -5634,6 +6011,29 @@ window.__ModuleLoader__.load({
|
|
|
5634
6011
|
"row.tabSwitchHint": "Turns this provider off: its models leave the DSH picker. Account and settings are kept.",
|
|
5635
6012
|
"row.tabSwitchAria": "Offer the {region} provider to DSH",
|
|
5636
6013
|
"row.tabOffNotice": "This provider is off: its models are not offered to DSH. Account and settings are kept.",
|
|
6014
|
+
"row.panelAria": "Card sections",
|
|
6015
|
+
"row.panelAccounts": "Account",
|
|
6016
|
+
"row.panelModels": "Models",
|
|
6017
|
+
"row.panelDiag": "Diagnostics",
|
|
6018
|
+
"row.diagRegion": "Panel",
|
|
6019
|
+
"row.diagProvider": "Provider id",
|
|
6020
|
+
"row.diagAccount": "Serving account",
|
|
6021
|
+
"row.diagToken": "Access token expires",
|
|
6022
|
+
"row.diagRefresh": "Re-sign-in deadline",
|
|
6023
|
+
"row.diagRefreshNone": "this credential carries none",
|
|
6024
|
+
"row.diagCatalog": "Models in catalog",
|
|
6025
|
+
"row.diagEnabled": "Models enabled",
|
|
6026
|
+
"row.diagPool": "Account pool",
|
|
6027
|
+
"row.diagPoolOn": "on · {count} account(s)",
|
|
6028
|
+
"row.diagPoolOff": "off",
|
|
6029
|
+
"row.diagCheckin": "Daily check-in",
|
|
6030
|
+
"row.diagCheckinOn": "supported",
|
|
6031
|
+
"row.diagCheckinOff": "not offered here",
|
|
6032
|
+
"row.diagRaw": "Raw chat channel",
|
|
6033
|
+
"row.diagRawOff": "not checked",
|
|
6034
|
+
"row.diagFailures": "Last reported failure",
|
|
6035
|
+
"row.diagNoFailures": "none",
|
|
6036
|
+
"row.diagHint": "Everything above is read-only and can be quoted verbatim into a bug report. The values are this panel’s own last refresh, not a summary of it.",
|
|
5637
6037
|
"row.settingsWriteFailed": "The setting was not saved: {message}",
|
|
5638
6038
|
"row.signedOut": "Not signed in",
|
|
5639
6039
|
"row.signedOutHint": "Sign in once in the Trae desktop app; this plugin follows that sign-in automatically.",
|
|
@@ -5960,6 +6360,29 @@ window.__ModuleLoader__.load({
|
|
|
5960
6360
|
"row.tabSwitchHint": "关闭该供应商:其模型不再提供给 DSH;账号与设置保留,可随时恢复。",
|
|
5961
6361
|
"row.tabSwitchAria": "是否向 DSH 提供{region}供应商",
|
|
5962
6362
|
"row.tabOffNotice": "该供应商已关闭,模型不会提供给 DSH。账号与设置均已保留。",
|
|
6363
|
+
"row.panelAria": "卡片分栏",
|
|
6364
|
+
"row.panelAccounts": "账号",
|
|
6365
|
+
"row.panelModels": "模型",
|
|
6366
|
+
"row.panelDiag": "诊断",
|
|
6367
|
+
"row.diagRegion": "面板",
|
|
6368
|
+
"row.diagProvider": "供应商 id",
|
|
6369
|
+
"row.diagAccount": "服务账号",
|
|
6370
|
+
"row.diagToken": "访问令牌到期",
|
|
6371
|
+
"row.diagRefresh": "重新登录最后期限",
|
|
6372
|
+
"row.diagRefreshNone": "该凭据不携带",
|
|
6373
|
+
"row.diagCatalog": "目录模型数",
|
|
6374
|
+
"row.diagEnabled": "已启用模型数",
|
|
6375
|
+
"row.diagPool": "账号池",
|
|
6376
|
+
"row.diagPoolOn": "已开启 · {count} 个账号",
|
|
6377
|
+
"row.diagPoolOff": "未开启",
|
|
6378
|
+
"row.diagCheckin": "每日签到",
|
|
6379
|
+
"row.diagCheckinOn": "支持",
|
|
6380
|
+
"row.diagCheckinOff": "本面板不提供",
|
|
6381
|
+
"row.diagRaw": "Raw 会话通道",
|
|
6382
|
+
"row.diagRawOff": "未检测",
|
|
6383
|
+
"row.diagFailures": "最近一次报错",
|
|
6384
|
+
"row.diagNoFailures": "无",
|
|
6385
|
+
"row.diagHint": "以上全部只读,可整段原样贴进反馈。数值来自本面板最近一次刷新,不是概括。",
|
|
5963
6386
|
"row.settingsWriteFailed": "设置未能保存:{message}",
|
|
5964
6387
|
"row.signedOut": "未登录",
|
|
5965
6388
|
"row.signedOutHint": "在 Trae 桌面 App 里登录一次即可,插件会自动跟随当前登录的账号。",
|