@jingyi0605/codingns4dsh 0.2.1-rc.2 → 0.2.1-rc.3
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/README.en.md +6 -4
- package/README.md +6 -6
- package/data/build/dist/bootstrap/dsh-connection-adapter.d.ts +1 -1
- package/data/build/dist/bootstrap/index.d.ts +1 -1
- package/data/build/dist/client/bundle.js +5306 -493
- package/data/build/dist/client/bundle.js.map +1 -1
- package/data/build/dist/client/client.magpie-model-tag.js +155 -5
- package/data/build/dist/client/client.magpie-model-tag.js.map +1 -1
- package/data/build/dist/client/client.native-workspace-store.js +30 -4
- package/data/build/dist/client/client.native-workspace-store.js.map +1 -1
- package/data/build/dist/client/client.transport.js +725 -48
- package/data/build/dist/client/client.transport.js.map +1 -1
- package/data/build/dist/client/desktop-assistant.js +931 -185
- package/data/build/dist/client/feature-requirement.d.ts +43 -0
- package/data/build/dist/client/feature-requirement.d.ts.map +1 -0
- package/data/build/dist/client/feature-requirement.js +105 -0
- package/data/build/dist/client/feature-requirement.js.map +1 -0
- package/data/build/dist/client/features/index.d.ts +1 -0
- package/data/build/dist/client/features/index.d.ts.map +1 -1
- package/data/build/dist/client/features/index.js +3 -0
- package/data/build/dist/client/features/index.js.map +1 -1
- package/data/build/dist/client/features/magpie-management-controls.d.ts +46 -0
- package/data/build/dist/client/features/magpie-management-controls.d.ts.map +1 -0
- package/data/build/dist/client/features/magpie-management-controls.js +759 -0
- package/data/build/dist/client/features/magpie-management-controls.js.map +1 -0
- package/data/build/dist/client/features/magpie-management-page.d.ts +124 -0
- package/data/build/dist/client/features/magpie-management-page.d.ts.map +1 -0
- package/data/build/dist/client/features/magpie-management-page.js +1256 -0
- package/data/build/dist/client/features/magpie-management-page.js.map +1 -0
- package/data/build/dist/client/features/magpie-management.d.ts +7 -0
- package/data/build/dist/client/features/magpie-management.d.ts.map +1 -0
- package/data/build/dist/client/features/magpie-management.js +154 -0
- package/data/build/dist/client/features/magpie-management.js.map +1 -0
- package/data/build/dist/client/features/magpie-mark.d.ts +10 -0
- package/data/build/dist/client/features/magpie-mark.d.ts.map +1 -0
- package/data/build/dist/client/features/magpie-mark.js +21 -0
- package/data/build/dist/client/features/magpie-mark.js.map +1 -0
- package/data/build/dist/client/features/magpie-provider-logo.d.ts +11 -0
- package/data/build/dist/client/features/magpie-provider-logo.d.ts.map +1 -0
- package/data/build/dist/client/features/magpie-provider-logo.js +35 -0
- package/data/build/dist/client/features/magpie-provider-logo.js.map +1 -0
- package/data/build/dist/client/features/subscription-quota-groups.d.ts +193 -0
- package/data/build/dist/client/features/subscription-quota-groups.d.ts.map +1 -0
- package/data/build/dist/client/features/subscription-quota-groups.js +548 -0
- package/data/build/dist/client/features/subscription-quota-groups.js.map +1 -0
- package/data/build/dist/client/git-management.d.ts.map +1 -1
- package/data/build/dist/client/git-management.js +11 -9
- package/data/build/dist/client/git-management.js.map +1 -1
- package/data/build/dist/client/git-panel-styles.js +1 -0
- package/data/build/dist/client/git-panel-styles.js.map +1 -1
- package/data/build/dist/client/index.d.ts +1 -1
- package/data/build/dist/client/index.d.ts.map +1 -1
- package/data/build/dist/client/index.js +1 -1
- package/data/build/dist/client/index.js.map +1 -1
- package/data/build/dist/client/locale.d.ts.map +1 -1
- package/data/build/dist/client/locale.js +7 -0
- package/data/build/dist/client/locale.js.map +1 -1
- package/data/build/dist/client/locales/magpie.d.ts +4 -0
- package/data/build/dist/client/locales/magpie.d.ts.map +1 -0
- package/data/build/dist/client/locales/magpie.js +622 -0
- package/data/build/dist/client/locales/magpie.js.map +1 -0
- package/data/build/dist/client/locales/usage.d.ts.map +1 -1
- package/data/build/dist/client/locales/usage.js +52 -0
- package/data/build/dist/client/locales/usage.js.map +1 -1
- package/data/build/dist/client/magpie-model-tag.d.ts +9 -1
- package/data/build/dist/client/magpie-model-tag.d.ts.map +1 -1
- package/data/build/dist/client/magpie-model-tag.js +15 -3
- package/data/build/dist/client/magpie-model-tag.js.map +1 -1
- package/data/build/dist/client/provider-icons.d.ts +8 -0
- package/data/build/dist/client/provider-icons.d.ts.map +1 -1
- package/data/build/dist/client/provider-icons.js +122 -2
- package/data/build/dist/client/provider-icons.js.map +1 -1
- package/data/build/dist/client/settings-bridge.d.ts +1 -0
- package/data/build/dist/client/settings-bridge.d.ts.map +1 -1
- package/data/build/dist/client/settings-bridge.js +29 -10
- package/data/build/dist/client/settings-bridge.js.map +1 -1
- package/data/build/dist/client/settings-section.d.ts.map +1 -1
- package/data/build/dist/client/settings-section.js +21 -3
- package/data/build/dist/client/settings-section.js.map +1 -1
- package/data/build/dist/client/style.css +224 -221
- package/data/build/dist/client/subscription-slot.d.ts +20 -0
- package/data/build/dist/client/subscription-slot.d.ts.map +1 -1
- package/data/build/dist/client/subscription-slot.js +321 -18
- package/data/build/dist/client/subscription-slot.js.map +1 -1
- package/data/build/dist/dsh-capabilities/client/global-panel-adapter.d.ts +27 -0
- package/data/build/dist/dsh-capabilities/client/global-panel-adapter.d.ts.map +1 -0
- package/data/build/dist/dsh-capabilities/client/global-panel-adapter.js +109 -0
- package/data/build/dist/dsh-capabilities/client/global-panel-adapter.js.map +1 -0
- package/data/build/dist/dsh-capabilities/host/session-title-adapter.d.ts +2 -1
- package/data/build/dist/dsh-capabilities/host/session-title-adapter.d.ts.map +1 -1
- package/data/build/dist/dsh-capabilities/host/session-title-adapter.js +32 -2
- package/data/build/dist/dsh-capabilities/host/session-title-adapter.js.map +1 -1
- package/data/build/dist/dsh-capabilities/matrix.d.ts.map +1 -1
- package/data/build/dist/dsh-capabilities/matrix.js +12 -11
- package/data/build/dist/dsh-capabilities/matrix.js.map +1 -1
- package/data/build/dist/dsh-capabilities/routes.d.ts.map +1 -1
- package/data/build/dist/dsh-capabilities/routes.js +12 -9
- package/data/build/dist/dsh-capabilities/routes.js.map +1 -1
- package/data/build/dist/dsh-capabilities/types.d.ts +1 -1
- package/data/build/dist/dsh-capabilities/types.d.ts.map +1 -1
- package/data/build/dist/dsh-capabilities/types.js.map +1 -1
- package/data/build/dist/host/cli-adapters/acp-cli-driver.d.ts +27 -0
- package/data/build/dist/host/cli-adapters/acp-cli-driver.d.ts.map +1 -1
- package/data/build/dist/host/cli-adapters/acp-cli-driver.js +88 -13
- package/data/build/dist/host/cli-adapters/acp-cli-driver.js.map +1 -1
- package/data/build/dist/host/cli-adapters/codex-driver.d.ts +10 -0
- package/data/build/dist/host/cli-adapters/codex-driver.d.ts.map +1 -1
- package/data/build/dist/host/cli-adapters/codex-driver.js +32 -1
- package/data/build/dist/host/cli-adapters/codex-driver.js.map +1 -1
- package/data/build/dist/host/cli-adapters/command-code-acp-loader.d.ts +6 -5
- package/data/build/dist/host/cli-adapters/command-code-acp-loader.d.ts.map +1 -1
- package/data/build/dist/host/cli-adapters/command-code-acp-loader.js +72 -12
- package/data/build/dist/host/cli-adapters/command-code-acp-loader.js.map +1 -1
- package/data/build/dist/host/cli-adapters/command-code-driver.d.ts.map +1 -1
- package/data/build/dist/host/cli-adapters/command-code-driver.js +26 -1
- package/data/build/dist/host/cli-adapters/command-code-driver.js.map +1 -1
- package/data/build/dist/host/cli-adapters/dsh-message-projector.d.ts.map +1 -1
- package/data/build/dist/host/cli-adapters/dsh-message-projector.js +15 -2
- package/data/build/dist/host/cli-adapters/dsh-message-projector.js.map +1 -1
- package/data/build/dist/host/cli-adapters/feature.d.ts +13 -0
- package/data/build/dist/host/cli-adapters/feature.d.ts.map +1 -1
- package/data/build/dist/host/cli-adapters/feature.js +390 -6
- package/data/build/dist/host/cli-adapters/feature.js.map +1 -1
- package/data/build/dist/host/cli-adapters/grok-driver.js +5 -0
- package/data/build/dist/host/cli-adapters/grok-driver.js.map +1 -1
- package/data/build/dist/host/cli-adapters/magpie-detection.d.ts +72 -0
- package/data/build/dist/host/cli-adapters/magpie-detection.d.ts.map +1 -0
- package/data/build/dist/host/cli-adapters/magpie-detection.js +298 -0
- package/data/build/dist/host/cli-adapters/magpie-detection.js.map +1 -0
- package/data/build/dist/host/cli-adapters/magpie-management.d.ts +50 -0
- package/data/build/dist/host/cli-adapters/magpie-management.d.ts.map +1 -0
- package/data/build/dist/host/cli-adapters/magpie-management.js +1268 -0
- package/data/build/dist/host/cli-adapters/magpie-management.js.map +1 -0
- package/data/build/dist/host/cli-adapters/magpie-update.d.ts +59 -0
- package/data/build/dist/host/cli-adapters/magpie-update.d.ts.map +1 -0
- package/data/build/dist/host/cli-adapters/magpie-update.js +249 -0
- package/data/build/dist/host/cli-adapters/magpie-update.js.map +1 -0
- package/data/build/dist/host/cli-adapters/magpie-usage.d.ts +66 -8
- package/data/build/dist/host/cli-adapters/magpie-usage.d.ts.map +1 -1
- package/data/build/dist/host/cli-adapters/magpie-usage.js +846 -122
- package/data/build/dist/host/cli-adapters/magpie-usage.js.map +1 -1
- package/data/build/dist/host/cli-adapters/magpie-web.d.ts +54 -0
- package/data/build/dist/host/cli-adapters/magpie-web.d.ts.map +1 -0
- package/data/build/dist/host/cli-adapters/magpie-web.js +407 -0
- package/data/build/dist/host/cli-adapters/magpie-web.js.map +1 -0
- package/data/build/dist/host/cli-adapters/process-utils.d.ts +2 -0
- package/data/build/dist/host/cli-adapters/process-utils.d.ts.map +1 -1
- package/data/build/dist/host/cli-adapters/process-utils.js +4 -0
- package/data/build/dist/host/cli-adapters/process-utils.js.map +1 -1
- package/data/build/dist/host/dsh-gateway-feature.d.ts.map +1 -1
- package/data/build/dist/host/dsh-gateway-feature.js +26 -3
- package/data/build/dist/host/dsh-gateway-feature.js.map +1 -1
- package/data/build/dist/host/features/host-status.d.ts +25 -0
- package/data/build/dist/host/features/host-status.d.ts.map +1 -1
- package/data/build/dist/host/features/host-status.js +60 -6
- package/data/build/dist/host/features/host-status.js.map +1 -1
- package/data/build/dist/host/features/lan-access-dsh.d.ts.map +1 -1
- package/data/build/dist/host/features/lan-access-dsh.js +61 -10
- package/data/build/dist/host/features/lan-access-dsh.js.map +1 -1
- package/data/build/dist/host/features/session-translation-protection.d.ts.map +1 -1
- package/data/build/dist/host/features/session-translation-protection.js +2 -1
- package/data/build/dist/host/features/session-translation-protection.js.map +1 -1
- package/data/build/dist/host/lan-access-dsh.d.ts.map +1 -1
- package/data/build/dist/host/lan-access-dsh.js +6 -2
- package/data/build/dist/host/lan-access-dsh.js.map +1 -1
- package/data/build/dist/host/modules/pwa/pwa-session-notifications.js +2 -1
- package/data/build/dist/host/modules/pwa/pwa-session-notifications.js.map +1 -1
- package/data/build/dist/host/rpc.d.ts +15 -2
- package/data/build/dist/host/rpc.d.ts.map +1 -1
- package/data/build/dist/host/rpc.js +47 -6
- package/data/build/dist/host/rpc.js.map +1 -1
- package/data/build/dist/host/settings.d.ts.map +1 -1
- package/data/build/dist/host/settings.js +5 -0
- package/data/build/dist/host/settings.js.map +1 -1
- package/data/build/dist/shared/contracts/config.d.ts +18 -0
- package/data/build/dist/shared/contracts/config.d.ts.map +1 -1
- package/data/build/dist/shared/contracts/config.js +8 -0
- package/data/build/dist/shared/contracts/config.js.map +1 -1
- package/data/build/dist/shared/contracts/errors.d.ts +2 -2
- package/data/build/dist/shared/contracts/feature.d.ts +7 -0
- package/data/build/dist/shared/contracts/feature.d.ts.map +1 -1
- package/data/build/dist/shared/contracts/magpie-management.d.ts +395 -0
- package/data/build/dist/shared/contracts/magpie-management.d.ts.map +1 -0
- package/data/build/dist/shared/contracts/magpie-management.js +2 -0
- package/data/build/dist/shared/contracts/magpie-management.js.map +1 -0
- package/data/build/dist/shared/contracts/subscription.d.ts +75 -1
- package/data/build/dist/shared/contracts/subscription.d.ts.map +1 -1
- package/data/build/dist/shared/contracts/subscription.js.map +1 -1
- package/data/build/dist/shared/contracts/version.d.ts +4 -4
- package/data/build/dist/shared/contracts/version.js +3 -3
- package/data/build/dist/shared/index.d.ts +2 -1
- package/data/build/dist/shared/index.d.ts.map +1 -1
- package/data/build/dist/shared/index.js +1 -1
- package/data/build/dist/shared/index.js.map +1 -1
- package/data/build/dist/shared/session-title.d.ts.map +1 -1
- package/data/build/dist/shared/session-title.js +10 -4
- package/data/build/dist/shared/session-title.js.map +1 -1
- package/package.json +29 -29
- package/profile/README.md +2 -2
- package/profile/package.json +3 -3
- package/profile/version.json +3 -3
- package/version.json +3 -3
|
@@ -33,9 +33,29 @@ export declare function calculateMagpiePopoverPlacement(rootLeft: number, viewpo
|
|
|
33
33
|
readonly left: number;
|
|
34
34
|
readonly width: number;
|
|
35
35
|
};
|
|
36
|
+
/**
|
|
37
|
+
* 移动端订阅入口只保留图标,完整数据仍可在点击后的弹层中查看。
|
|
38
|
+
* 弹层高度上限固定为浏览器可视高度的 75%:先写 `vh` 兜底,再由 `dvh` 覆盖,
|
|
39
|
+
* 使移动端工具栏收展后仍按真实可视区计算;超出部分在弹层内部纵向滚动。
|
|
40
|
+
*/
|
|
41
|
+
export declare const SUBSCRIPTION_RESPONSIVE_CSS = "@media (max-width: 768px){.codingns4dsh-subscription-trigger{gap:0!important;padding-left:4px!important;padding-right:4px!important}.codingns4dsh-subscription-label,.codingns4dsh-subscription-value{display:none!important}.codingns4dsh-subscription-popover{position:fixed!important;left:12px!important;right:12px!important;bottom:48px!important;width:auto!important;min-width:0!important;max-width:none!important;max-height:75vh!important;max-height:75dvh!important;overflow-x:hidden!important;overflow-y:auto!important;overscroll-behavior:contain!important;box-sizing:border-box!important}}";
|
|
36
42
|
/** 在 DSH 原生步骤统计左侧显示当前 Agent 的订阅余量。 */
|
|
37
43
|
export declare function registerSubscriptionSlot(slots: SlotRegistry, rpc: CodingNsRpcClient, getRefreshIntervalMins?: () => number, locale?: CodingNsLocale): () => void;
|
|
38
44
|
declare function CommandCodeSubscriptionSlot(props: SubscriptionSlotProps): ReactElement | null;
|
|
45
|
+
/**
|
|
46
|
+
* 路由标题栏的“查看请求”入口:按钮、模态框与读取状态放在同一个子组件里。
|
|
47
|
+
*
|
|
48
|
+
* 弹层内容本身不持有 Hook(无浏览器测试会直接展开内容树),因此这里只由
|
|
49
|
+
* `MagpieRoutePanel` 渲染元素,真正的状态留在本组件内部。模态框内的请求明细
|
|
50
|
+
* 直接复用管理页的 `RequestsPage`,只把会话筛选固定为当前会话。
|
|
51
|
+
*/
|
|
52
|
+
export declare function MagpieRouteRequests({ rpc, sessionId, sessionName, agent, t }: {
|
|
53
|
+
readonly rpc: CodingNsRpcClient;
|
|
54
|
+
readonly sessionId: string | null;
|
|
55
|
+
readonly sessionName: string | null;
|
|
56
|
+
readonly agent: string;
|
|
57
|
+
readonly t: CodingNsTranslator;
|
|
58
|
+
}): ReactElement;
|
|
39
59
|
export declare function ProviderBalancePopover({ usage, providerName, t, nowMs }: {
|
|
40
60
|
readonly usage: ProviderBalanceUsage;
|
|
41
61
|
readonly providerName: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subscription-slot.d.ts","sourceRoot":"","sources":["../../../../src/client/subscription-slot.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAa,MAAM,OAAO,CAAA;AACpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4CAA4C,CAAA;AAG9E,OAAO,KAAK,EAA6G,uBAAuB,
|
|
1
|
+
{"version":3,"file":"subscription-slot.d.ts","sourceRoot":"","sources":["../../../../src/client/subscription-slot.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAa,MAAM,OAAO,CAAA;AACpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4CAA4C,CAAA;AAG9E,OAAO,KAAK,EAA6G,uBAAuB,EAAmH,oBAAoB,EAAsD,MAAM,qCAAqC,CAAA;AAGxX,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAE5D,OAAO,EAAoD,KAAK,cAAc,EAAE,KAAK,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAmB5H,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAGrD,OAAO,QAAQ,kCAAkC,CAAC;IAChD,UAAU,oBAAoB;QAC5B,SAAS,EAAE,MAAM,CAAA;KAClB;CACF;AAED,KAAK,eAAe,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,QAAQ,KAAK,QAAQ,CAAA;AAE7F,UAAU,qBAAqB;IAC7B,QAAQ,CAAC,GAAG,EAAE,iBAAiB,CAAA;IAC/B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,UAAU,CAAC,EAAE,eAAe,CAAA;IACrC,oCAAoC;IACpC,QAAQ,CAAC,sBAAsB,CAAC,EAAE,MAAM,MAAM,CAAA;IAC9C,6CAA6C;IAC7C,QAAQ,CAAC,MAAM,CAAC,EAAE,cAAc,CAAA;CACjC;AAeD;;;GAGG;AACH,KAAK,UAAU,GAAG,GAAG,CAAC,MAAM,EAAE;IAAE,QAAQ,CAAC,KAAK,EAAE,uBAAuB,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CAAA;AASvG,sCAAsC;AACtC,wBAAgB,gCAAgC,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,QAAQ,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAG/I;AAoBD,wBAAgB,+BAA+B,CAAC,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAMtK;AAED;;;;GAIG;AACH,eAAO,MAAM,2BAA2B,mlBAAmlB,CAAA;AAW3nB,sCAAsC;AACtC,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,EAAE,iBAAiB,EAAE,sBAAsB,CAAC,EAAE,MAAM,MAAM,EAAE,MAAM,CAAC,EAAE,cAAc,GAAG,MAAM,IAAI,CAehK;AAED,iBAAS,2BAA2B,CAAC,KAAK,EAAE,qBAAqB,GAAG,YAAY,GAAG,IAAI,CA4YtF;AA4RD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;IAC7E,QAAQ,CAAC,GAAG,EAAE,iBAAiB,CAAA;IAC/B,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACjC,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IACnC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,CAAC,EAAE,kBAAkB,CAAA;CAC/B,GAAG,YAAY,CAoFf;AAyeD,wBAAgB,sBAAsB,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE;IAAE,QAAQ,CAAC,KAAK,EAAE,oBAAoB,CAAC;IAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,CAAC,EAAE,kBAAkB,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,YAAY,CA+CvN;AA4gBD,OAAO,EAAE,2BAA2B,EAAE,CAAA;AACtC,eAAO,MAAM,mCAAmC,iCAA2B,CAAA"}
|
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
import { startSerialPolling } from './serial-polling.js';
|
|
2
|
-
import { createElement, useEffect, useLayoutEffect, useRef, useState } from 'react';
|
|
2
|
+
import { createElement, Fragment, useEffect, useLayoutEffect, useRef, useState } from 'react';
|
|
3
3
|
import { isSubscriptionUsageFresh } from '../shared/contracts/subscription.js';
|
|
4
4
|
import { DEFAULT_SUBSCRIPTION_USAGE_SETTINGS } from '../shared/contracts/config.js';
|
|
5
5
|
import { callCliRpc } from './cli-catalog.js';
|
|
6
6
|
import { resolveCodingNsTranslator, useCodingNsTranslator } from './locale.js';
|
|
7
7
|
import { providerIconUrl } from './provider-icons.js';
|
|
8
|
+
import { MagpieProviderLogo } from './features/magpie-provider-logo.js';
|
|
9
|
+
import { MAGPIE_REQUESTS_PAGE_SIZE, RequestsPage, installMagpiePageStyles } from './features/magpie-management-page.js';
|
|
10
|
+
import { createQuotaAccountBlock, createQuotaGroupHeader, formatQuotaCredits, formatQuotaNumber, groupQuotasByProvider, readWindowCreditBalance, resolveQuotaBalanceLabel, resolveQuotaCreditBalance, } from './features/subscription-quota-groups.js';
|
|
8
11
|
import { subscribeSessionAdapters } from './session-adapter-cache.js';
|
|
9
12
|
import { loadCliSessionConfig } from './cli-session-config-cache.js';
|
|
10
13
|
import { dshPopupSurfaceStyle, dshSettingsButtonStyle, dshSettingsPrimaryButtonStyle, dshThemeColor } from './theme.js';
|
|
11
|
-
import { useDismissOnOutsidePointer } from './popup-dismiss.js';
|
|
14
|
+
import { backdropPointerDownHandler, useDismissOnOutsidePointer } from './popup-dismiss.js';
|
|
15
|
+
import { callCodingNsRpcResult } from './rpc-call.js';
|
|
12
16
|
import { uiFontSize } from './font-scale.js';
|
|
13
17
|
const SUBSCRIPTION_STYLE_ID = 'codingns4dsh-subscription-responsive-style';
|
|
14
18
|
/**
|
|
@@ -57,6 +61,7 @@ function loadUsage(rpc, key, payload) {
|
|
|
57
61
|
/** 图标重置按钮的悬停/按下/聚焦/禁用只能由注入样式表表达,内联样式无法命中伪类。 */
|
|
58
62
|
const RESET_BUTTON_CSS = '.codingns4dsh-subscription-reset{display:inline-flex;align-items:center;justify-content:center;flex:none;width:26px;height:26px;padding:0;border:1px solid var(--dsw-alias-border-l2,#d9d9d9);border-radius:50%;background:transparent;color:var(--dsw-alias-label-secondary,GrayText);cursor:pointer;transition:background .15s ease,color .15s ease}.codingns4dsh-subscription-reset:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover,rgba(127,127,127,.08));color:var(--dsw-alias-label-primary,CanvasText)}.codingns4dsh-subscription-reset:active:not(:disabled){background:var(--dsw-alias-interactive-bg-active,rgba(127,127,127,.14))}.codingns4dsh-subscription-reset:focus-visible{outline:none;box-shadow:0 0 0 var(--dsw-focus-ring-width,2px) var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary,#1677ff))}.codingns4dsh-subscription-reset:disabled{opacity:.4;cursor:not-allowed}@media (prefers-reduced-motion: reduce){.codingns4dsh-subscription-reset{transition:none}}';
|
|
59
63
|
const MAGPIE_ROUTE_CSS = '@keyframes codingns4dsh-magpie-route-pulse{0%{transform:translateY(-120%);opacity:0}20%{opacity:1}80%{opacity:1}100%{transform:translateY(320%);opacity:0}}@keyframes codingns4dsh-magpie-route-breathe{0%,100%{box-shadow:0 0 0 0 rgba(22,119,255,0)}50%{box-shadow:0 0 0 4px rgba(22,119,255,.16)}}@keyframes codingns4dsh-magpie-route-step{from{opacity:0;transform:translateY(4px) scale(.98)}to{opacity:1;transform:translateY(0) scale(1)}}.codingns4dsh-magpie-route-pulse{animation:codingns4dsh-magpie-route-pulse 1.8s ease-in-out infinite}.codingns4dsh-magpie-route-node-active{animation:codingns4dsh-magpie-route-breathe 2s ease-in-out infinite}.codingns4dsh-magpie-route-step{animation:codingns4dsh-magpie-route-step .38s cubic-bezier(.2,.75,.25,1) both;transition:background .16s ease}.codingns4dsh-magpie-route-step:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(127,127,127,.07))}.codingns4dsh-magpie-route-step:hover .codingns4dsh-magpie-route-node{box-shadow:0 0 0 1px var(--dsw-alias-state-business-primary,#1677ff),0 0 0 4px rgba(22,119,255,.1)}.codingns4dsh-magpie-route-node{transition:box-shadow .16s ease}.codingns4dsh-magpie-tab:focus-visible{outline:none;box-shadow:0 0 0 2px var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary,#1677ff)) inset}@media (prefers-reduced-motion:reduce){.codingns4dsh-magpie-route-pulse,.codingns4dsh-magpie-route-node-active,.codingns4dsh-magpie-route-step,.codingns4dsh-magpie-route-node{animation:none;transition:none}}';
|
|
64
|
+
const MAGPIE_REQUESTS_CSS = '.codingns4dsh-magpie-route-requests:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(127,127,127,.08));color:var(--dsw-alias-label-primary,CanvasText)}.codingns4dsh-magpie-route-requests:focus-visible,.codingns4dsh-magpie-requests-close:focus-visible,.codingns4dsh-magpie-requests-retry:focus-visible{outline:none;box-shadow:0 0 0 2px var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary,#1677ff))}.codingns4dsh-magpie-requests-close:hover,.codingns4dsh-magpie-requests-retry:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(127,127,127,.08));color:var(--dsw-alias-label-primary,CanvasText)}.codingns4dsh-magpie-requests-dialog:focus,.codingns4dsh-magpie-requests-dialog:focus-visible{outline:none}.codingns4dsh-magpie-requests-body{flex:1 1 auto;min-height:0;overflow:auto;overscroll-behavior:contain}.codingns4dsh-magpie-requests-view{display:block!important;width:100%;height:auto!important;min-height:0;padding-left:0!important;background:transparent}.codingns4dsh-magpie-requests-view .codingns-magpie-view{max-width:none;padding:0}@media (max-width:768px){.codingns4dsh-magpie-requests-overlay{align-items:flex-end!important;padding:12px!important}.codingns4dsh-magpie-requests-dialog{width:100%!important;max-height:78vh!important;max-height:78dvh!important}}@media (prefers-reduced-motion:reduce){.codingns4dsh-magpie-route-requests{transition:none}}';
|
|
60
65
|
export function calculateMagpiePopoverPlacement(rootLeft, viewportWidth, sidebarLeft) {
|
|
61
66
|
const margin = 12;
|
|
62
67
|
const boundary = Math.min(viewportWidth - margin, sidebarLeft === null ? viewportWidth - margin : sidebarLeft - margin);
|
|
@@ -64,14 +69,19 @@ export function calculateMagpiePopoverPlacement(rootLeft, viewportWidth, sidebar
|
|
|
64
69
|
const left = Math.max(margin, Math.min(rootLeft, boundary - width));
|
|
65
70
|
return { left: left - rootLeft, width };
|
|
66
71
|
}
|
|
67
|
-
/**
|
|
72
|
+
/**
|
|
73
|
+
* 移动端订阅入口只保留图标,完整数据仍可在点击后的弹层中查看。
|
|
74
|
+
* 弹层高度上限固定为浏览器可视高度的 75%:先写 `vh` 兜底,再由 `dvh` 覆盖,
|
|
75
|
+
* 使移动端工具栏收展后仍按真实可视区计算;超出部分在弹层内部纵向滚动。
|
|
76
|
+
*/
|
|
77
|
+
export const SUBSCRIPTION_RESPONSIVE_CSS = '@media (max-width: 768px){.codingns4dsh-subscription-trigger{gap:0!important;padding-left:4px!important;padding-right:4px!important}.codingns4dsh-subscription-label,.codingns4dsh-subscription-value{display:none!important}.codingns4dsh-subscription-popover{position:fixed!important;left:12px!important;right:12px!important;bottom:48px!important;width:auto!important;min-width:0!important;max-width:none!important;max-height:75vh!important;max-height:75dvh!important;overflow-x:hidden!important;overflow-y:auto!important;overscroll-behavior:contain!important;box-sizing:border-box!important}}';
|
|
68
78
|
function installSubscriptionStyles() {
|
|
69
79
|
if (typeof document === 'undefined' || document.querySelector(`style[data-plugin-css="${SUBSCRIPTION_STYLE_ID}"]`) !== null)
|
|
70
80
|
return;
|
|
71
81
|
const style = document.createElement('style');
|
|
72
82
|
style.dataset.plugin = 'codingns4dsh';
|
|
73
83
|
style.dataset.pluginCss = SUBSCRIPTION_STYLE_ID;
|
|
74
|
-
style.textContent =
|
|
84
|
+
style.textContent = SUBSCRIPTION_RESPONSIVE_CSS + RESET_BUTTON_CSS + MAGPIE_ROUTE_CSS + MAGPIE_REQUESTS_CSS;
|
|
75
85
|
document.head.appendChild(style);
|
|
76
86
|
}
|
|
77
87
|
/** 在 DSH 原生步骤统计左侧显示当前 Agent 的订阅余量。 */
|
|
@@ -101,6 +111,14 @@ function CommandCodeSubscriptionSlot(props) {
|
|
|
101
111
|
const [open, setOpen] = useState(false);
|
|
102
112
|
const [loading, setLoading] = useState(false);
|
|
103
113
|
const [magpieTab, setMagpieTab] = useState('usage');
|
|
114
|
+
// 多账号厂商默认只展开会话实际使用的账号;展开状态挂在根组件上,
|
|
115
|
+
// 弹层内容本身不持有 Hook,便于无浏览器的组件测试直接展开内容树。
|
|
116
|
+
const [expandedQuotaGroups, setExpandedQuotaGroups] = useState([]);
|
|
117
|
+
const toggleQuotaGroup = (provider) => {
|
|
118
|
+
setExpandedQuotaGroups((current) => current.includes(provider)
|
|
119
|
+
? current.filter((item) => item !== provider)
|
|
120
|
+
: [...current, provider]);
|
|
121
|
+
};
|
|
104
122
|
const [magpiePlacement, setMagpiePlacement] = useState({ left: 0, width: 400 });
|
|
105
123
|
const [clock, setClock] = useState(() => Date.now());
|
|
106
124
|
const rootRef = useRef(null);
|
|
@@ -184,6 +202,9 @@ function CommandCodeSubscriptionSlot(props) {
|
|
|
184
202
|
return;
|
|
185
203
|
}
|
|
186
204
|
let active = true;
|
|
205
|
+
// 未解析的 Magpie 配额必须快速补读:官方余额一旦抢先显示,用户要等到下一次
|
|
206
|
+
// 轮询(默认 5 分钟)或整页刷新才会切到 Magpie。
|
|
207
|
+
let upstreamUnresolved = false;
|
|
187
208
|
setEligible(false);
|
|
188
209
|
setSnapshot(null);
|
|
189
210
|
setAdapterId(null);
|
|
@@ -249,6 +270,7 @@ function CommandCodeSubscriptionSlot(props) {
|
|
|
249
270
|
: await loadUsage(props.rpc, cacheKey, payload);
|
|
250
271
|
if (next !== null)
|
|
251
272
|
subscriptionUsageCache.set(cacheKey, { usage: next, capturedAt: Date.now() });
|
|
273
|
+
upstreamUnresolved = shouldResolveMagpieQuota(next?.magpie);
|
|
252
274
|
if (active)
|
|
253
275
|
setSnapshot(next);
|
|
254
276
|
}
|
|
@@ -267,7 +289,11 @@ function CommandCodeSubscriptionSlot(props) {
|
|
|
267
289
|
}
|
|
268
290
|
};
|
|
269
291
|
const intervalMins = props.getRefreshIntervalMins?.() ?? DEFAULT_SUBSCRIPTION_USAGE_SETTINGS.refreshIntervalMins;
|
|
270
|
-
const
|
|
292
|
+
const pollIntervalMs = Math.max(0, intervalMins) * 60_000;
|
|
293
|
+
const poll = startSerialPolling(refresh, pollIntervalMs, {
|
|
294
|
+
timeoutMs: 30_000,
|
|
295
|
+
getIntervalMs: () => upstreamUnresolved ? Math.min(pollIntervalMs, MAGPIE_QUOTA_RETRY_MS) : pollIntervalMs,
|
|
296
|
+
});
|
|
271
297
|
refreshRef.current = poll.refresh;
|
|
272
298
|
return () => {
|
|
273
299
|
active = false;
|
|
@@ -341,7 +367,7 @@ function CommandCodeSubscriptionSlot(props) {
|
|
|
341
367
|
return null;
|
|
342
368
|
if (snapshot.magpie !== null) {
|
|
343
369
|
const magpie = snapshot.magpie;
|
|
344
|
-
const
|
|
370
|
+
const readout = resolveMagpieTriggerReadout(magpie);
|
|
345
371
|
const label = t('usage.magpieUsageLabel');
|
|
346
372
|
return createElement('div', { ref: rootRef, style: subscriptionRootStyle }, createElement('button', {
|
|
347
373
|
type: 'button',
|
|
@@ -356,9 +382,17 @@ function CommandCodeSubscriptionSlot(props) {
|
|
|
356
382
|
width: 20,
|
|
357
383
|
height: 20,
|
|
358
384
|
style: magpieTriggerImageStyle,
|
|
359
|
-
})),
|
|
360
|
-
|
|
361
|
-
|
|
385
|
+
})), createMagpieTriggerReadout(readout, t)), open && createElement(MagpieUsagePopover, {
|
|
386
|
+
rpc: props.rpc,
|
|
387
|
+
usage: magpie,
|
|
388
|
+
t,
|
|
389
|
+
tab: magpieTab,
|
|
390
|
+
onTabChange: setMagpieTab,
|
|
391
|
+
expandedGroups: expandedQuotaGroups,
|
|
392
|
+
onToggleGroup: toggleQuotaGroup,
|
|
393
|
+
placement: magpiePlacement,
|
|
394
|
+
popoverRef: magpiePopoverRef,
|
|
395
|
+
}));
|
|
362
396
|
}
|
|
363
397
|
const usage = snapshot.providerUsage;
|
|
364
398
|
// 未拿到真实订阅数据时不占用底部栏空间;加载状态不能伪装成订阅存在。
|
|
@@ -439,7 +473,7 @@ function CommandCodeSubscriptionSlot(props) {
|
|
|
439
473
|
dialogRef: resetDialogRef,
|
|
440
474
|
}));
|
|
441
475
|
}
|
|
442
|
-
function MagpieUsagePopover({ usage, t, tab = 'usage', onTabChange = () => { }, placement = { left: 0, width: 400 }, popoverRef }) {
|
|
476
|
+
function MagpieUsagePopover({ rpc, usage, t, tab = 'usage', onTabChange = () => { }, expandedGroups = [], onToggleGroup = () => { }, placement = { left: 0, width: 400 }, popoverRef }) {
|
|
443
477
|
const aggregateRows = usage.aggregate === null ? [] : [
|
|
444
478
|
[t('usage.magpieRequests'), formatMagpieNumber(usage.aggregate.calls)],
|
|
445
479
|
[t('usage.magpieErrors'), formatMagpieNumber(usage.aggregate.errors)],
|
|
@@ -489,12 +523,12 @@ function MagpieUsagePopover({ usage, t, tab = 'usage', onTabChange = () => { },
|
|
|
489
523
|
'aria-labelledby': `codingns4dsh-magpie-tab-${tab}`,
|
|
490
524
|
style: magpieTabPanelStyle,
|
|
491
525
|
}, tab === 'usage' ? MagpieUsagePanel({ usage, aggregateRows, sessionRows, t })
|
|
492
|
-
: MagpieRoutePanel({ usage, quotas, t })));
|
|
526
|
+
: MagpieRoutePanel({ rpc, usage, quotas, t, expandedGroups, onToggleGroup })));
|
|
493
527
|
}
|
|
494
528
|
function MagpieUsagePanel({ usage, aggregateRows, sessionRows, t }) {
|
|
495
529
|
return createElement('div', undefined, createElement('section', { style: magpieUsageSectionStyle }, createElement('strong', { style: magpieSectionTitleStyle }, t('usage.magpieAggregateTitle')), usage.usageStatus === 'available'
|
|
496
530
|
? createMagpieRows(aggregateRows)
|
|
497
|
-
: createElement('div', { style: magpieMutedTextStyle }, t('usage.magpieUsageUnavailable'))), createElement('section', { style: magpieUsageSectionStyle }, createElement('strong', { style: magpieSectionTitleStyle }, t('usage.magpieSessionTitle')), usage.sessionId !== null && createElement('div', { style: magpieSessionIdentityStyle }, createElement('span', undefined, t('usage.magpieAgent', { agent: usage.agent })), createElement('code', { style: magpieSessionIdStyle }, usage.sessionId)), usage.session === null
|
|
531
|
+
: createElement('div', { style: magpieMutedTextStyle }, t('usage.magpieUsageUnavailable'))), createElement('section', { style: magpieUsageSectionStyle }, createElement('strong', { style: magpieSectionTitleStyle }, t('usage.magpieSessionTitle')), usage.sessionId !== null && createElement('div', { style: magpieSessionIdentityStyle }, createElement('span', undefined, t('usage.magpieAgent', { agent: usage.agent })), usage.sessionName !== undefined && createElement('strong', { style: magpieSessionNameStyle, title: usage.sessionName }, usage.sessionName), createElement('code', { style: magpieSessionIdStyle }, usage.sessionId)), usage.session === null
|
|
498
532
|
? createElement('div', { style: magpieMutedTextStyle }, usage.sessionId === null ? t('usage.magpieSessionIdUnavailable') : t('usage.magpieSessionNoUsage'))
|
|
499
533
|
: createMagpieRows(sessionRows)));
|
|
500
534
|
}
|
|
@@ -512,16 +546,33 @@ function createMagpieProviderBadges(usage, style) {
|
|
|
512
546
|
return createElement('span', { style }, ...providers.map((provider) => createElement('span', { key: provider, style: magpieProviderBadgeStyle }, provider)));
|
|
513
547
|
}
|
|
514
548
|
function createMagpieQuotaCard(quota, t, index) {
|
|
515
|
-
return createElement('div', { key: `${quota.provider}-${quota.user ?? 'account'}-${index}`, style: magpieQuotaCardStyle }, createElement('div', { style: magpieQuotaCardHeadingStyle }, createElement('span', { style: magpieQuotaNameStyle }, quota.alias ?? quota.name), createElement('span', { style: magpieQuotaHeadingMetaStyle }, quota.plan ?? quota.provider)), (quota.user !== null || quota.balance !== null) && createElement('div', { style: magpieQuotaIdentityStyle }, quota.user !== null && createElement('span', { title: quota.user }, t('usage.magpieQuotaAccount', { account: quota.user })), quota.balance !== null && createElement('span', undefined, t('usage.magpieQuotaBalance', { balance: quota.balance }))), quota.windows.length === 0
|
|
549
|
+
return createElement('div', { key: `${quota.provider}-${quota.user ?? 'account'}-${index}`, style: magpieQuotaCardStyle }, createElement('div', { style: magpieQuotaCardHeadingStyle }, createElement('span', { style: magpieQuotaNameWithLogoStyle }, createElement(MagpieProviderLogo, { identities: [quota.provider, quota.name], logoDataUrl: quota.logoDataUrl, size: 20, className: 'codingns4dsh-magpie-quota-logo', fallback: 'none' }), createElement('span', { style: magpieQuotaNameStyle }, quota.alias ?? quota.name)), createElement('span', { style: magpieQuotaHeadingMetaStyle }, quota.plan ?? quota.provider)), (quota.user !== null || quota.balance !== null) && createElement('div', { style: magpieQuotaIdentityStyle }, quota.user !== null && createElement('span', { title: quota.user }, t('usage.magpieQuotaAccount', { account: quota.user })), quota.balance !== null && createElement('span', undefined, t('usage.magpieQuotaBalance', { balance: quota.balance }))), quota.windows.length === 0
|
|
516
550
|
? createElement('div', { style: magpieQuotaMetaStyle }, t('usage.magpieQuotaNoWindows'))
|
|
517
551
|
: quota.windows.map((window, windowIndex) => {
|
|
518
552
|
const remaining = window.remainingPercent;
|
|
553
|
+
// 积分窗口(WorkBuddy 的 `0 / 350`)按数量读更准确:百分比在这里没有意义。
|
|
554
|
+
const credits = formatQuotaWindowCredits(window);
|
|
519
555
|
const amount = window.display ?? (window.amount !== null && window.limit !== null ? `${window.amount} / ${window.limit}${window.unit === null ? '' : ` ${window.unit}`}` : null);
|
|
520
|
-
return createElement('div', { key: `${window.name}-${windowIndex}`, style: magpieQuotaWindowStyle }, createElement('div', { style: windowHeadingStyle }, createElement('span', undefined, window.name),
|
|
556
|
+
return createElement('div', { key: `${window.name}-${windowIndex}`, style: magpieQuotaWindowStyle }, createElement('div', { style: windowHeadingStyle }, createElement('span', undefined, window.name), credits !== null
|
|
557
|
+
? createElement('strong', undefined, credits)
|
|
558
|
+
: remaining === null ? amount : createElement('strong', undefined, `${formatPercent(remaining)}%`)),
|
|
559
|
+
// 积分窗口用满格数量条展示已用比例,避免"0% 还能用"的误读。
|
|
560
|
+
remaining !== null && createElement('div', { role: 'progressbar', 'aria-label': t('usage.magpieQuotaRemaining', { name: window.name, percent: formatPercent(remaining) }), 'aria-valuemin': 0, 'aria-valuemax': 100, 'aria-valuenow': remaining, style: barStyle }, createElement('span', { style: { ...barFillStyle, width: `${remaining}%` } })), (amount !== null || window.resetsAt !== null) && createElement('div', { style: magpieQuotaFooterStyle }, amount !== null && createElement('span', undefined, amount), window.resetsAt !== null && createElement('span', undefined, t('usage.magpieQuotaResets', { time: formatMagpieTimestamp(window.resetsAt) }))));
|
|
521
561
|
}));
|
|
522
562
|
}
|
|
523
|
-
|
|
563
|
+
/**
|
|
564
|
+
* 单个窗口若是按积分计量,返回"剩余 / 上限"文本;普通百分比窗口返回 null。
|
|
565
|
+
*
|
|
566
|
+
* 卡片会为每个窗口单独调用一次,所以这里按窗口自治判断,不依赖账号整体状态。
|
|
567
|
+
*/
|
|
568
|
+
function formatQuotaWindowCredits(window) {
|
|
569
|
+
const credits = readWindowCreditBalance(window);
|
|
570
|
+
return credits === null ? null : formatQuotaCredits(credits);
|
|
571
|
+
}
|
|
572
|
+
function MagpieRoutePanel({ rpc, usage, quotas, t, expandedGroups, onToggleGroup }) {
|
|
524
573
|
const route = usage.route;
|
|
574
|
+
const groups = groupQuotasByProvider(quotas);
|
|
575
|
+
const sessionAccount = route?.providerAccount ?? null;
|
|
525
576
|
const quotaMessage = magpieQuotaUnavailableMessage(usage, quotas, t);
|
|
526
577
|
const routeStatus = usage.routeStatus === 'no-route'
|
|
527
578
|
? t('usage.magpieRouteNoRequests')
|
|
@@ -543,7 +594,32 @@ function MagpieRoutePanel({ usage, quotas, t }) {
|
|
|
543
594
|
];
|
|
544
595
|
return createElement('div', undefined, createElement('section', { style: magpieSectionStyle }, createElement('div', { style: magpieQuotaHeadingStyle }, createElement('strong', { style: magpieSectionTitleStyle }, t('usage.magpieQuotaTitle')), createMagpieProviderBadges(usage, magpieProviderBadgesStyle)), quotaMessage !== null
|
|
545
596
|
? createElement('div', { style: magpieEmptyStateStyle }, quotaMessage)
|
|
546
|
-
:
|
|
597
|
+
: groups.map((group) => {
|
|
598
|
+
const expanded = expandedGroups.includes(group.provider);
|
|
599
|
+
const multiple = group.accounts.length > 1;
|
|
600
|
+
return createElement('div', { key: group.provider, style: magpieQuotaCardStyle }, createQuotaGroupHeader({
|
|
601
|
+
group,
|
|
602
|
+
t,
|
|
603
|
+
expanded,
|
|
604
|
+
onToggle: multiple ? () => onToggleGroup(group.provider) : null,
|
|
605
|
+
}), group.accounts.map((quota, index) => createElement('div', { key: `${group.provider}-${quota.user ?? 'account'}-${index}` }, createQuotaAccountBlock(quota, {
|
|
606
|
+
t,
|
|
607
|
+
nowMs: Date.now(),
|
|
608
|
+
// 单账号厂商由组头承担名称,账号块不再重复。
|
|
609
|
+
showAccountName: multiple,
|
|
610
|
+
// 组未展开时只留会话账号的明细,其余账号折叠成余量行。
|
|
611
|
+
compact: multiple && !expanded && quota.active !== true && (sessionAccount === null || quota.user !== sessionAccount),
|
|
612
|
+
fallbackName: group.name === '' ? group.provider : group.name,
|
|
613
|
+
}))));
|
|
614
|
+
})), createElement('section', { style: magpieSectionStyle }, createElement('div', { style: magpieRouteHeadingStyle }, createElement('strong', { style: magpieSectionTitleStyle }, t('usage.magpieRouteTitle')), route !== null && createElement('div', { style: magpieRouteHeadingActionsStyle },
|
|
615
|
+
// “查看请求”入口与状态徽标同高、同排:入口在左,状态在右。
|
|
616
|
+
createElement(MagpieRouteRequests, {
|
|
617
|
+
rpc,
|
|
618
|
+
sessionId: usage.sessionId,
|
|
619
|
+
sessionName: usage.sessionName ?? null,
|
|
620
|
+
agent: usage.agent,
|
|
621
|
+
t,
|
|
622
|
+
}), createElement('span', { className: active ? 'codingns4dsh-magpie-route-node-active' : undefined, style: magpieRouteStatusStyle }, createElement('span', { style: magpieRouteStatusDotStyle }), createElement('strong', undefined, route.done === true ? t('usage.magpieRouteComplete') : route.done === false ? t('usage.magpieRouteRunning').replace(/\s*·\s*$/u, '') : route.status ?? '--')))), route === null
|
|
547
623
|
? createElement('div', { style: magpieEmptyStateStyle }, routeStatus)
|
|
548
624
|
: createElement('div', { style: magpieRouteHeroStyle }, createElement('div', { style: magpieRouteTrackStyle, 'aria-label': t('usage.magpieRouteFlowTitle'), role: 'list' }, ...routeStages.map(([label, model], index) => createElement('div', {
|
|
549
625
|
key: `step-${index}`,
|
|
@@ -552,6 +628,165 @@ function MagpieRoutePanel({ usage, quotas, t }) {
|
|
|
552
628
|
style: { ...magpieRouteTrackItemStyle, animationDelay: `${index * 90}ms` },
|
|
553
629
|
}, createElement('div', { style: magpieRouteMarkerColumnStyle, 'aria-hidden': true }, createElement('div', { className: 'codingns4dsh-magpie-route-node', style: magpieRouteNodeStyle }, createElement('span', { style: magpieRouteNodeDotStyle })), index < routeStages.length - 1 && createElement('div', { style: magpieRouteConnectorStyle }, active && createElement('span', { className: 'codingns4dsh-magpie-route-pulse', style: magpieRoutePulseStyle }))), createElement('div', { style: magpieRouteStageCopyStyle }, createElement('span', { style: magpieRouteStageLabelStyle }, label), createElement('strong', { style: magpieRouteStageValueStyle, title: model }, model))))), routeRows.length > 0 && createElement('div', { style: magpieRouteMetaStyle }, ...routeRows.filter((row) => row[1] !== null).map(([label, value]) => createElement('div', { key: label, style: magpieRouteMetaItemStyle }, createElement('span', { style: magpieRouteMetaLabelStyle }, label), createElement('strong', { style: magpieRouteMetaValueStyle, title: value }, value)))), route.tries.length > 0 && createElement('div', { style: magpieAttemptsStyle }, ...route.tries.map((attempt, index) => createElement('div', { key: `${attempt.model ?? 'model'}-${index}`, style: magpieAttemptRowStyle }, createElement('span', { style: magpieAttemptModelStyle }, attempt.model ?? t('usage.magpieUnknownModel')), attempt.failed && createElement('span', { style: magpieFailedStyle }, t('usage.magpieFallback'))))))));
|
|
554
630
|
}
|
|
631
|
+
/**
|
|
632
|
+
* 路由标题栏的“查看请求”入口:按钮、模态框与读取状态放在同一个子组件里。
|
|
633
|
+
*
|
|
634
|
+
* 弹层内容本身不持有 Hook(无浏览器测试会直接展开内容树),因此这里只由
|
|
635
|
+
* `MagpieRoutePanel` 渲染元素,真正的状态留在本组件内部。模态框内的请求明细
|
|
636
|
+
* 直接复用管理页的 `RequestsPage`,只把会话筛选固定为当前会话。
|
|
637
|
+
*/
|
|
638
|
+
export function MagpieRouteRequests({ rpc, sessionId, sessionName, agent, t }) {
|
|
639
|
+
const enabled = canReadMagpieSessionRequests(sessionId, agent);
|
|
640
|
+
const [open, setOpen] = useState(false);
|
|
641
|
+
const [page, setPage] = useState(null);
|
|
642
|
+
const [offset, setOffset] = useState(0);
|
|
643
|
+
const [loading, setLoading] = useState(false);
|
|
644
|
+
const [error, setError] = useState(false);
|
|
645
|
+
const [reloadKey, setReloadKey] = useState(0);
|
|
646
|
+
const controllerRef = useRef(null);
|
|
647
|
+
useEffect(() => {
|
|
648
|
+
if (!open || !enabled)
|
|
649
|
+
return;
|
|
650
|
+
const controller = new AbortController();
|
|
651
|
+
controllerRef.current = controller;
|
|
652
|
+
setLoading(true);
|
|
653
|
+
setError(false);
|
|
654
|
+
void readMagpieSessionRequestPage(rpc, sessionId, agent, offset, controller.signal).then((next) => {
|
|
655
|
+
if (controller.signal.aborted)
|
|
656
|
+
return;
|
|
657
|
+
if (next === null) {
|
|
658
|
+
setError(true);
|
|
659
|
+
return;
|
|
660
|
+
}
|
|
661
|
+
setPage(next);
|
|
662
|
+
}).catch(() => {
|
|
663
|
+
if (!controller.signal.aborted)
|
|
664
|
+
setError(true);
|
|
665
|
+
}).finally(() => {
|
|
666
|
+
if (!controller.signal.aborted)
|
|
667
|
+
setLoading(false);
|
|
668
|
+
});
|
|
669
|
+
return () => {
|
|
670
|
+
controller.abort();
|
|
671
|
+
if (controllerRef.current === controller)
|
|
672
|
+
controllerRef.current = null;
|
|
673
|
+
};
|
|
674
|
+
}, [open, enabled, offset, reloadKey, rpc, sessionId, agent]);
|
|
675
|
+
// 模态框覆盖整个视口,Esc 是移动端之外唯一的键盘关闭方式。
|
|
676
|
+
useEffect(() => {
|
|
677
|
+
if (!open || typeof document === 'undefined')
|
|
678
|
+
return;
|
|
679
|
+
// 捕获阶段拦截 Esc:只关闭模态框,不再让底部弹层的关闭监听把整个弹层一起收起。
|
|
680
|
+
const onKeyDown = (event) => {
|
|
681
|
+
if (event.key !== 'Escape')
|
|
682
|
+
return;
|
|
683
|
+
event.stopPropagation();
|
|
684
|
+
setOpen(false);
|
|
685
|
+
};
|
|
686
|
+
document.addEventListener('keydown', onKeyDown, true);
|
|
687
|
+
return () => document.removeEventListener('keydown', onKeyDown, true);
|
|
688
|
+
}, [open]);
|
|
689
|
+
const close = () => {
|
|
690
|
+
controllerRef.current?.abort();
|
|
691
|
+
controllerRef.current = null;
|
|
692
|
+
setOpen(false);
|
|
693
|
+
};
|
|
694
|
+
const openRequests = () => {
|
|
695
|
+
controllerRef.current?.abort();
|
|
696
|
+
setPage(null);
|
|
697
|
+
setOffset(0);
|
|
698
|
+
setError(false);
|
|
699
|
+
setLoading(true);
|
|
700
|
+
// 请求明细复用管理页组件,需要先装上管理页自己的样式表。
|
|
701
|
+
installMagpiePageStyles();
|
|
702
|
+
setOpen(true);
|
|
703
|
+
};
|
|
704
|
+
return createElement(Fragment, undefined, enabled && createElement('button', {
|
|
705
|
+
type: 'button',
|
|
706
|
+
className: 'codingns4dsh-magpie-route-requests',
|
|
707
|
+
onClick: openRequests,
|
|
708
|
+
'aria-haspopup': 'dialog',
|
|
709
|
+
title: t('usage.magpieViewRequests'),
|
|
710
|
+
style: magpieRouteRequestsButtonStyle,
|
|
711
|
+
}, t('usage.magpieViewRequests')), enabled && open && createElement(MagpieSessionRequestsDialog, {
|
|
712
|
+
sessionId,
|
|
713
|
+
sessionName,
|
|
714
|
+
agent,
|
|
715
|
+
page,
|
|
716
|
+
offset,
|
|
717
|
+
loading,
|
|
718
|
+
error,
|
|
719
|
+
t,
|
|
720
|
+
onClose: close,
|
|
721
|
+
onOffsetChange: setOffset,
|
|
722
|
+
onRetry: () => { setLoading(true); setError(false); setReloadKey((value) => value + 1); },
|
|
723
|
+
}));
|
|
724
|
+
}
|
|
725
|
+
/** Host 只接受小写 Agent ID;会话与 Agent 必须成对出现,缺一不可。 */
|
|
726
|
+
function canReadMagpieSessionRequests(sessionId, agent) {
|
|
727
|
+
return sessionId !== null && sessionId.trim() !== '' && sessionId.length <= 512 && /^[a-z0-9][a-z0-9-]*$/u.test(agent);
|
|
728
|
+
}
|
|
729
|
+
/** 只读取今天的会话请求,与路由卡片和“当前 Agent 会话”用量保持同一时间口径。 */
|
|
730
|
+
async function readMagpieSessionRequestPage(rpc, sessionId, agent, offset, signal) {
|
|
731
|
+
const result = await callCodingNsRpcResult(rpc, 'magpie/usage/requests', {
|
|
732
|
+
period: 'today',
|
|
733
|
+
offset,
|
|
734
|
+
limit: MAGPIE_REQUESTS_PAGE_SIZE,
|
|
735
|
+
sessionId,
|
|
736
|
+
sessionAgent: agent,
|
|
737
|
+
}, signal);
|
|
738
|
+
if (!result.ok)
|
|
739
|
+
throw new Error(result.error.message);
|
|
740
|
+
const value = result.value;
|
|
741
|
+
return isRecord(value) && Array.isArray(value.items)
|
|
742
|
+
? value
|
|
743
|
+
: null;
|
|
744
|
+
}
|
|
745
|
+
/**
|
|
746
|
+
* 请求模态框:外壳(遮罩、标题、关闭)由弹层提供,明细直接复用管理页的请求用量视图。
|
|
747
|
+
*
|
|
748
|
+
* 管理页视图自带统计条、桌面表格 / 移动卡片、分页和空状态,这里只负责把会话固定住,
|
|
749
|
+
* 不再维护一套重复的请求卡片渲染。
|
|
750
|
+
*/
|
|
751
|
+
function MagpieSessionRequestsDialog({ sessionId, sessionName, agent, page, offset, loading, error, t, onClose, onOffsetChange, onRetry }) {
|
|
752
|
+
return createElement('div', {
|
|
753
|
+
className: 'codingns4dsh-magpie-requests-overlay',
|
|
754
|
+
role: 'presentation',
|
|
755
|
+
style: magpieRequestsOverlayStyle,
|
|
756
|
+
// 只有按在遮罩自身时才关闭;从内容内部按下再拖到遮罩上不会误关。
|
|
757
|
+
onPointerDown: backdropPointerDownHandler(onClose),
|
|
758
|
+
}, createElement('div', {
|
|
759
|
+
role: 'dialog',
|
|
760
|
+
'aria-modal': true,
|
|
761
|
+
'aria-label': t('usage.magpieRequestsTitle'),
|
|
762
|
+
className: 'codingns4dsh-magpie-requests-dialog',
|
|
763
|
+
tabIndex: -1,
|
|
764
|
+
autoFocus: true,
|
|
765
|
+
style: magpieRequestsDialogStyle,
|
|
766
|
+
}, createElement('div', { style: magpieRequestsHeadingStyle }, createElement('strong', { style: magpieRequestsTitleStyle }, t('usage.magpieRequestsTitle')), createElement('div', { style: magpieRequestsHeadingActionsStyle }, error && createElement('button', {
|
|
767
|
+
type: 'button',
|
|
768
|
+
className: 'codingns4dsh-magpie-requests-retry',
|
|
769
|
+
onClick: onRetry,
|
|
770
|
+
style: magpieRequestsRetryStyle,
|
|
771
|
+
}, t('magpie.refresh')), createElement('button', {
|
|
772
|
+
type: 'button',
|
|
773
|
+
className: 'codingns4dsh-magpie-requests-close',
|
|
774
|
+
onClick: onClose,
|
|
775
|
+
'aria-label': t('usage.magpieRequestsClose'),
|
|
776
|
+
style: magpieRequestsCloseStyle,
|
|
777
|
+
}, '×'))), createElement('div', { className: 'codingns4dsh-magpie-requests-body', style: magpieRequestsBodyStyle },
|
|
778
|
+
// `.codingns-magpie-page` 提供管理页的 `--mp-*` 主题变量;外层样式再把它压进弹层尺寸。
|
|
779
|
+
createElement('div', { className: 'codingns-magpie-page codingns4dsh-magpie-requests-view' }, createElement(RequestsPage, {
|
|
780
|
+
page,
|
|
781
|
+
loading,
|
|
782
|
+
error,
|
|
783
|
+
selectedSession: { id: sessionId, agent, ...(sessionName === null ? {} : { dshSessionName: sessionName }) },
|
|
784
|
+
offset,
|
|
785
|
+
onOffsetChange,
|
|
786
|
+
onClearSession: null,
|
|
787
|
+
t,
|
|
788
|
+
})))));
|
|
789
|
+
}
|
|
555
790
|
function createMagpieRows(rows) {
|
|
556
791
|
if (rows.length === 0)
|
|
557
792
|
return createElement('div', { style: magpieMutedTextStyle }, '--');
|
|
@@ -954,8 +1189,26 @@ function createModelRow(model, unit) {
|
|
|
954
1189
|
function resolveDisplayWindow(usage) {
|
|
955
1190
|
return usage.primary ?? usage.secondary ?? usage.monthly;
|
|
956
1191
|
}
|
|
1192
|
+
/** 配额解析完成前的补读间隔;与弹层打开时的路由读取共用串行轮询。 */
|
|
1193
|
+
const MAGPIE_QUOTA_RETRY_MS = 3_000;
|
|
1194
|
+
/**
|
|
1195
|
+
* Magpie 用量入口是否还需要带路由补读。
|
|
1196
|
+
*
|
|
1197
|
+
* Host 会为「已确认属于 Magpie、但会话身份还没写进账本」的模型下发带会话数据的
|
|
1198
|
+
* `provider-unavailable` 占位快照;还在启动中的网关则是 `unavailable`。
|
|
1199
|
+
* 两种状态都表示上游未知,必须按 `MAGPIE_QUOTA_RETRY_MS` 快速重新解析,否则首屏
|
|
1200
|
+
* 会一直停在官方余额或 Magpie 标签上,直到整页刷新。
|
|
1201
|
+
*
|
|
1202
|
+
* 上游已解析(`provider-unavailable` 但 `upstreamProvider` 有值,例如该厂商本来
|
|
1203
|
+
* 就不上报任何配额窗口)不再补读——再读也只是重复确认同一个结论。没有上游信息的
|
|
1204
|
+
* 占位快照才有资格要求补读,Host 也只在这种情况下才下发它。
|
|
1205
|
+
*/
|
|
957
1206
|
function shouldResolveMagpieQuota(usage) {
|
|
958
|
-
|
|
1207
|
+
if (usage === null || usage === undefined)
|
|
1208
|
+
return false;
|
|
1209
|
+
if (usage.quotaStatus !== 'available')
|
|
1210
|
+
return usage.upstreamProvider === null;
|
|
1211
|
+
return usage.sessionId !== null && usage.session !== null && usage.quotas.length === 0;
|
|
959
1212
|
}
|
|
960
1213
|
function resolveMagpieQuotaRemaining(usage) {
|
|
961
1214
|
if (usage.quotaStatus !== 'available')
|
|
@@ -968,6 +1221,41 @@ function resolveMagpieQuotaRemaining(usage) {
|
|
|
968
1221
|
}
|
|
969
1222
|
return null;
|
|
970
1223
|
}
|
|
1224
|
+
function resolveMagpieTriggerReadout(usage) {
|
|
1225
|
+
const remaining = resolveMagpieQuotaRemaining(usage);
|
|
1226
|
+
if (remaining !== null)
|
|
1227
|
+
return { kind: 'ring', percent: remaining };
|
|
1228
|
+
const quotas = usage.quotas ?? [];
|
|
1229
|
+
const balance = resolveQuotaBalanceLabel(quotas);
|
|
1230
|
+
if (balance !== null)
|
|
1231
|
+
return { kind: 'money', text: balance };
|
|
1232
|
+
const credits = resolveQuotaCreditsLabel(quotas);
|
|
1233
|
+
if (credits !== null)
|
|
1234
|
+
return { kind: 'credits', text: credits };
|
|
1235
|
+
return { kind: 'label' };
|
|
1236
|
+
}
|
|
1237
|
+
/** 积分余额的展示文本:只给数量,单位放在 title 里,不占用底部栏宽度。 */
|
|
1238
|
+
function resolveQuotaCreditsLabel(quotas) {
|
|
1239
|
+
for (const quota of quotas) {
|
|
1240
|
+
const credits = resolveQuotaCreditBalance(quota);
|
|
1241
|
+
if (credits === null || !(credits.remaining > 0))
|
|
1242
|
+
continue;
|
|
1243
|
+
return formatQuotaNumber(credits.remaining);
|
|
1244
|
+
}
|
|
1245
|
+
return null;
|
|
1246
|
+
}
|
|
1247
|
+
function createMagpieTriggerReadout(readout, t) {
|
|
1248
|
+
switch (readout.kind) {
|
|
1249
|
+
case 'ring':
|
|
1250
|
+
return createRemainingRing(readout.percent);
|
|
1251
|
+
case 'money':
|
|
1252
|
+
return createElement('span', { className: 'codingns4dsh-subscription-value', style: magpieBalanceStyle, title: t('usage.accountBalance') }, readout.text);
|
|
1253
|
+
case 'credits':
|
|
1254
|
+
return createElement('span', { className: 'codingns4dsh-subscription-value', style: magpieBalanceStyle, title: t('usage.creditBalanceLabel') }, readout.text);
|
|
1255
|
+
default:
|
|
1256
|
+
return createElement('span', { className: 'codingns4dsh-subscription-label', style: subscriptionLabelStyle }, t('usage.magpieShortLabel'));
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
971
1259
|
function selectDeepseekBalance(usage) {
|
|
972
1260
|
return usage.balances.find((balance) => balance.currency.toUpperCase() === 'USD') ?? usage.balances[0] ?? null;
|
|
973
1261
|
}
|
|
@@ -1103,6 +1391,8 @@ function formatCreditBalance(value) {
|
|
|
1103
1391
|
const subscriptionRootStyle = { position: 'relative', minWidth: 0, display: 'inline-flex', alignItems: 'center' };
|
|
1104
1392
|
const subscriptionTriggerStyle = { display: 'inline-flex', alignItems: 'center', gap: 6, height: 28, border: 0, borderRadius: 14, padding: '0 8px 0 4px', color: dshThemeColor.labelSecondary, background: 'transparent', cursor: 'pointer', fontSize: uiFontSize(13), lineHeight: '20px' };
|
|
1105
1393
|
const subscriptionLabelStyle = { whiteSpace: 'nowrap' };
|
|
1394
|
+
// 余额金额与积分和百分比环并排/替换显示:数字用等宽字形,避免刷新时抖动。
|
|
1395
|
+
const magpieBalanceStyle = { display: 'inline-flex', alignItems: 'center', whiteSpace: 'nowrap', color: dshThemeColor.labelSecondary, fontSize: uiFontSize(12), fontWeight: 600, fontVariantNumeric: 'tabular-nums' };
|
|
1106
1396
|
const magpieTriggerIconStyle = { display: 'inline-flex', width: 20, height: 20, alignItems: 'center', justifyContent: 'center', overflow: 'hidden', borderRadius: 6, background: dshThemeColor.surfaceSubtle };
|
|
1107
1397
|
const magpieTriggerImageStyle = { display: 'block', width: '100%', height: '100%', objectFit: 'cover' };
|
|
1108
1398
|
const magpieMutedTextStyle = { color: dshThemeColor.labelTertiary, fontSize: uiFontSize(12), lineHeight: '17px', overflowWrap: 'anywhere' };
|
|
@@ -1122,6 +1412,7 @@ const magpieStatStyle = { display: 'grid', alignContent: 'space-between', gap: 1
|
|
|
1122
1412
|
const magpieStatLabelStyle = { minWidth: 0, color: dshThemeColor.labelTertiary, fontSize: uiFontSize(10), lineHeight: '13px', overflowWrap: 'anywhere' };
|
|
1123
1413
|
const magpieRowValueStyle = { color: dshThemeColor.labelPrimary, fontSize: uiFontSize(14), fontWeight: 650, lineHeight: '18px', textAlign: 'right', overflowWrap: 'anywhere' };
|
|
1124
1414
|
const magpieSessionIdentityStyle = { display: 'flex', flexWrap: 'wrap', alignItems: 'baseline', gap: '2px 10px', minWidth: 0, color: dshThemeColor.labelSecondary, fontSize: uiFontSize(12), lineHeight: '16px' };
|
|
1415
|
+
const magpieSessionNameStyle = { maxWidth: '100%', overflow: 'hidden', color: dshThemeColor.labelPrimary, fontSize: uiFontSize(12), fontWeight: 650, textOverflow: 'ellipsis', whiteSpace: 'nowrap' };
|
|
1125
1416
|
const magpieSessionIdStyle = { flex: '1 1 120px', minWidth: 0, color: dshThemeColor.labelTertiary, fontSize: uiFontSize(10), lineHeight: '14px', whiteSpace: 'normal', overflowWrap: 'anywhere' };
|
|
1126
1417
|
const magpieAttemptsStyle = { display: 'grid', gap: 5, paddingTop: 6 };
|
|
1127
1418
|
const magpieAttemptRowStyle = { display: 'flex', justifyContent: 'space-between', gap: 14, fontSize: uiFontSize(12) };
|
|
@@ -1133,6 +1424,7 @@ const magpieProviderBadgeStyle = { flex: 'none', maxWidth: 220, overflow: 'hidde
|
|
|
1133
1424
|
const magpieEmptyStateStyle = { display: 'grid', placeItems: 'center', minHeight: 36, padding: '8px 10px', color: dshThemeColor.labelTertiary, fontSize: uiFontSize(12), lineHeight: '17px', textAlign: 'center' };
|
|
1134
1425
|
const magpieQuotaCardStyle = { display: 'grid', gap: 5, marginTop: 7, padding: '9px 10px', border: `1px solid ${dshThemeColor.border}`, borderRadius: 9, background: dshThemeColor.surfaceSubtle };
|
|
1135
1426
|
const magpieQuotaCardHeadingStyle = { display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', gap: 10 };
|
|
1427
|
+
const magpieQuotaNameWithLogoStyle = { display: 'inline-flex', alignItems: 'center', gap: 6, minWidth: 0, overflow: 'hidden' };
|
|
1136
1428
|
const magpieQuotaNameStyle = { minWidth: 0, overflow: 'hidden', color: dshThemeColor.labelPrimary, fontSize: uiFontSize(13), fontWeight: 650, textOverflow: 'ellipsis', whiteSpace: 'nowrap' };
|
|
1137
1429
|
const magpieQuotaHeadingMetaStyle = { flex: 'none', maxWidth: 160, overflow: 'hidden', color: dshThemeColor.labelTertiary, fontSize: uiFontSize(11), textOverflow: 'ellipsis', whiteSpace: 'nowrap' };
|
|
1138
1430
|
const magpieQuotaIdentityStyle = { display: 'flex', flexWrap: 'wrap', gap: '3px 12px', color: dshThemeColor.labelTertiary, fontSize: uiFontSize(11), lineHeight: '15px', overflowWrap: 'anywhere' };
|
|
@@ -1141,7 +1433,7 @@ const magpieQuotaWindowStyle = { display: 'grid', gap: 4, paddingTop: 3 };
|
|
|
1141
1433
|
const magpieQuotaFooterStyle = { display: 'flex', justifyContent: 'space-between', flexWrap: 'wrap', gap: '3px 10px', color: dshThemeColor.labelTertiary, fontSize: uiFontSize(11), lineHeight: '15px' };
|
|
1142
1434
|
const magpieRouteHeadingStyle = { display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 10 };
|
|
1143
1435
|
const magpieRouteHeroStyle = { display: 'grid', gap: 11, padding: '12px 13px', border: `1px solid ${dshThemeColor.border}`, borderRadius: 12, background: `linear-gradient(145deg, ${dshThemeColor.surfaceSubtle}, transparent)` };
|
|
1144
|
-
const magpieRouteStatusStyle = { display: 'inline-flex', alignItems: 'center', gap: 6, width: 'fit-content', padding: '3px 8px', borderRadius: 999, background: dshThemeColor.surfaceSubtle, color: dshThemeColor.labelSecondary, fontSize: uiFontSize(11), whiteSpace: 'nowrap' };
|
|
1436
|
+
const magpieRouteStatusStyle = { display: 'inline-flex', alignItems: 'center', gap: 6, width: 'fit-content', boxSizing: 'border-box', padding: '3px 8px', borderRadius: 999, background: dshThemeColor.surfaceSubtle, color: dshThemeColor.labelSecondary, fontSize: uiFontSize(11), lineHeight: '15px', whiteSpace: 'nowrap' };
|
|
1145
1437
|
const magpieRouteStatusDotStyle = { width: 8, height: 8, borderRadius: '50%', background: dshThemeColor.accent };
|
|
1146
1438
|
const magpieRouteTrackStyle = { display: 'grid', gap: 0, minWidth: 0, padding: '3px 0' };
|
|
1147
1439
|
const magpieRouteTrackItemStyle = { display: 'grid', gridTemplateColumns: '18px minmax(0, 1fr)', alignItems: 'start', gap: 12, minWidth: 0, padding: '5px 8px', margin: '0 -8px', borderRadius: 8 };
|
|
@@ -1157,6 +1449,17 @@ const magpieRouteMetaStyle = { display: 'grid', gridTemplateColumns: 'repeat(2,
|
|
|
1157
1449
|
const magpieRouteMetaItemStyle = { display: 'grid', alignContent: 'start', gap: 3, minWidth: 0, padding: '6px 8px', border: `1px solid ${dshThemeColor.border}`, borderRadius: 8, background: dshThemeColor.menuBackground };
|
|
1158
1450
|
const magpieRouteMetaLabelStyle = { color: dshThemeColor.labelTertiary, fontSize: uiFontSize(10), lineHeight: '13px' };
|
|
1159
1451
|
const magpieRouteMetaValueStyle = { color: dshThemeColor.labelSecondary, fontSize: uiFontSize(11), fontWeight: 550, lineHeight: '15px', overflowWrap: 'anywhere' };
|
|
1452
|
+
// 请求入口与请求模态框:入口与状态徽标同高并排在标题栏,模态框覆盖视口并在内部滚动。
|
|
1453
|
+
const magpieRouteHeadingActionsStyle = { display: 'inline-flex', alignItems: 'center', gap: 8, minWidth: 0 };
|
|
1454
|
+
const magpieRouteRequestsButtonStyle = { flex: 'none', display: 'inline-flex', alignItems: 'center', gap: 4, boxSizing: 'border-box', padding: '2px 8px', border: `1px solid ${dshThemeColor.border}`, borderRadius: 999, background: dshThemeColor.menuBackground, color: dshThemeColor.labelSecondary, fontFamily: 'inherit', fontSize: uiFontSize(11), lineHeight: '15px', cursor: 'pointer', whiteSpace: 'nowrap', transition: 'background .15s ease,color .15s ease' };
|
|
1455
|
+
const magpieRequestsOverlayStyle = { position: 'fixed', inset: 0, zIndex: 1500, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 16, boxSizing: 'border-box', background: dshThemeColor.overlay };
|
|
1456
|
+
const magpieRequestsDialogStyle = { ...dshPopupSurfaceStyle, display: 'flex', flexDirection: 'column', gap: 10, width: 'min(96vw, 1320px)', maxHeight: 'min(88vh, 820px)', boxSizing: 'border-box', padding: 14, borderRadius: 14 };
|
|
1457
|
+
const magpieRequestsHeadingStyle = { display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 12, paddingBottom: 10, borderBottom: `1px solid ${dshThemeColor.border}` };
|
|
1458
|
+
const magpieRequestsHeadingActionsStyle = { display: 'inline-flex', alignItems: 'center', gap: 8, flex: 'none' };
|
|
1459
|
+
const magpieRequestsTitleStyle = { fontSize: uiFontSize(15), lineHeight: '20px' };
|
|
1460
|
+
const magpieRequestsCloseStyle = { flex: 'none', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', width: 28, height: 28, padding: 0, border: 0, borderRadius: '50%', background: 'transparent', color: dshThemeColor.labelSecondary, fontSize: uiFontSize(18), lineHeight: 1, cursor: 'pointer' };
|
|
1461
|
+
const magpieRequestsBodyStyle = { flex: '1 1 auto', minHeight: 0, overflowY: 'auto', overscrollBehavior: 'contain' };
|
|
1462
|
+
const magpieRequestsRetryStyle = { padding: '5px 12px', border: `1px solid ${dshThemeColor.border}`, borderRadius: 999, background: dshThemeColor.menuBackground, color: dshThemeColor.labelSecondary, fontFamily: 'inherit', fontSize: uiFontSize(11), lineHeight: '15px', cursor: 'pointer' };
|
|
1160
1463
|
const sub2apiIdentityStyle = { display: 'inline-flex', alignItems: 'center', gap: 5, whiteSpace: 'nowrap', fontVariantNumeric: 'tabular-nums' };
|
|
1161
1464
|
const sub2apiLogoStyle = { display: 'block', borderRadius: 4, objectFit: 'contain' };
|
|
1162
1465
|
const deepseekBalanceIdentityStyle = { display: 'inline-flex', alignItems: 'center', gap: 5, whiteSpace: 'nowrap', fontVariantNumeric: 'tabular-nums' };
|