dsh-connect-trae 3.7.0 → 3.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.d.ts CHANGED
@@ -61,6 +61,29 @@ declare function traeStorageCandidates(platform?: NodeJS.Platform, home?: string
61
61
  //#region src/region.d.ts
62
62
  /** Storage/routing bucket: the CN service or the international (ai) service. */
63
63
  type TraeRegion = 'cn' | 'ai';
64
+ /**
65
+ * One section of the plugin card: a provider the user can switch, bind an
66
+ * account to, and pick models for, INDEPENDENTLY.
67
+ *
68
+ * A panel is not a region. `cn` and `ai` happen to be one-to-one with regions,
69
+ * but the CN enterprise pool shares the `cn` credential while billing a
70
+ * different account and serving a different roster — it needs its own switch,
71
+ * its own account binding and its own model selection, which is exactly what a
72
+ * panel is. Keeping panels a separate concept from regions is what lets
73
+ * `enterprise` be handled by the same settings plumbing with no new storage
74
+ * shape: each panel is just one more slot in the `regions` map.
75
+ */
76
+ type TraePanel = 'cn' | 'ai' | 'enterprise';
77
+ /** Every panel, in card tab order. */
78
+ declare const TRAE_PANELS: readonly TraePanel[];
79
+ /** The region whose credential/account pool a panel draws on. */
80
+ declare function regionOfPanel(panel: TraePanel): TraeRegion;
81
+ /** The provider id a panel publishes. */
82
+ declare function providerOfPanel(panel: TraePanel): string;
83
+ /** The panel that owns a provider id, or undefined for an unknown id. */
84
+ declare function panelOfProvider(provider: string): TraePanel | undefined;
85
+ /** Narrow a stored settings key to a panel. */
86
+ declare function panelOfKey(value: unknown): TraePanel | undefined;
64
87
  /** One region's upstream gateway bases. */
65
88
  interface TraeRegionGateways {
66
89
  /** Chat + agent API base (the `llm_utils_chat` / raw-chat family). */
@@ -191,8 +214,15 @@ declare function traeInputModalities(model: Pick<TraeModelInfo, 'input'>): TraeI
191
214
  * (wire resolution, callable-key filtering) must keep matching the
192
215
  * undecorated name; only the model rows handed to DSH (adapter catalog and
193
216
  * model discovery) use this decorated name.
217
+ *
218
+ * `withRate` is false for the ENTERPRISE panel. The multiplier is a
219
+ * consumer-pool figure — personal credits per token, read from the consumer
220
+ * directory — and the tenant pool does not bill against it, so printing it in
221
+ * the model picker would price a model the tenant is not charged for. The rate
222
+ * is part of the NAME that reaches DSH, which is why this is a parameter here
223
+ * and not a rendering decision downstream.
194
224
  */
195
- declare function traeModelDisplayName(model: Pick<TraeModelInfo, 'name' | 'creditMultiplier'>): string;
225
+ declare function traeModelDisplayName(model: Pick<TraeModelInfo, 'name' | 'creditMultiplier'>, withRate?: boolean): string;
196
226
  /** Apply the user's explicit image opt-ins plus Trae's own multimodal flag. */
197
227
  declare function applyImageSelection(models: readonly TraeModelInfo[], selected: ReadonlySet<string>): TraeModelInfo[];
198
228
  /** One row from `get_detail_param`: the authoritative llm_utils_chat wire id + display name. */
@@ -435,11 +465,29 @@ interface TraeShim {
435
465
  ready: Promise<void>;
436
466
  baseUrl(): string;
437
467
  token(): string;
468
+ /** Bearer secret of one named route (defaults to the first route). */
469
+ tokenOf(label?: string): string;
438
470
  close(): Promise<void>;
439
471
  }
472
+ /** One bearer-authenticated chat route served by the shim. */
473
+ interface TraeShimRoute {
474
+ /** Stable label used to look the route's secret up (`solo` | `enterprise`). */
475
+ label: string;
476
+ client: TraeUpstreamClient;
477
+ }
440
478
  interface TraeShimOptions {
441
479
  catalog: TraeCatalog;
442
- client: TraeUpstreamClient;
480
+ /**
481
+ * Single-route form, kept for the existing call sites and tests.
482
+ *
483
+ * A shim serves exactly as many chat routes as the region publishes provider
484
+ * ids, and they must not be interchangeable: the consumer and enterprise
485
+ * pools bill different accounts, so the route is chosen by the bearer token
486
+ * the adapter was built with, and an unknown token is rejected rather than
487
+ * defaulting to "some" pool.
488
+ */
489
+ client?: TraeUpstreamClient;
490
+ routes?: readonly TraeShimRoute[];
443
491
  logger?: ShimLogger;
444
492
  }
445
493
  declare function createTraeShim(options: TraeShimOptions): TraeShim;
@@ -447,16 +495,45 @@ declare function createTraeShim(options: TraeShimOptions): TraeShim;
447
495
  //#region src/adapter.d.ts
448
496
  /** Provider route this bundle owns for the domestic (CN) gateway. */
449
497
  declare const TRAE_PROVIDER = "trae";
498
+ /**
499
+ * Provider route this bundle owns for the CN **enterprise (tenant)** gateway.
500
+ *
501
+ * A separate provider id, not a mode switch, because the two pools bill
502
+ * differently: a tenant account (`tob_online`) is served by BOTH gateways with
503
+ * the SAME credential, and only the enterprise one draws on the enterprise
504
+ * pool. Exposing one id would force a per-call guess about who pays.
505
+ *
506
+ * It never falls back to the consumer pool: picking this provider is the user
507
+ * saying "bill the tenant", so a refusal is reported as an error instead of
508
+ * being silently re-run against the personal quota.
509
+ */
510
+ declare const TRAE_ENTERPRISE_PROVIDER = "trae-enterprise";
450
511
  /**
451
512
  * Provider route this bundle owns for the international (trae.ai) gateway.
452
513
  * Named `-global` to match the plugin family's convention (`workbuddy-global`);
453
514
  * the internal region bucket stays `ai`, which is the gateway/protocol name.
454
515
  */
455
516
  declare const TRAE_AI_PROVIDER = "trae-global";
456
- /** The provider id each region registers as. */
517
+ /** The provider ids one region publishes, in model-picker order. */
518
+ declare const TRAE_PROVIDER_IDS: Readonly<Record<TraeRegion, readonly string[]>>;
519
+ /** Each region's default (first) provider id. */
457
520
  declare const TRAE_PROVIDERS: Readonly<Record<TraeRegion, string>>;
521
+ /**
522
+ * Which chat pool a provider bills against.
523
+ *
524
+ * `trae` and `trae-global` keep the behaviour they always had (the consumer
525
+ * SOLO pool); `trae-enterprise` is the only id that reaches the tenant gateway.
526
+ */
527
+ type TraeProviderRoute = 'solo' | 'enterprise';
528
+ declare const TRAE_PROVIDER_ROUTES: Readonly<Record<string, TraeProviderRoute>>;
529
+ /** Chat pool a provider id bills against; `undefined` for an unknown id. */
530
+ declare function routeOfTraeProvider(provider: string): TraeProviderRoute | undefined;
458
531
  /** Human-readable provider names, shown in the DSH model picker. */
459
532
  declare const TRAE_PROVIDER_DISPLAY_NAMES: Readonly<Record<TraeRegion, string>>;
533
+ /** Display name per provider id (the region table above only names the default). */
534
+ declare const TRAE_PROVIDER_ID_DISPLAY_NAMES: Readonly<Record<string, string>>;
535
+ /** Display name of a provider id. */
536
+ declare function displayNameOfTraeProvider(provider: string): string;
460
537
  /** Region a provider route id belongs to. */
461
538
  declare function regionOfTraeProvider(provider: string): TraeRegion | undefined;
462
539
  declare const TRAE_STREAM_IDLE_TIMEOUT_MS = 300000;
@@ -553,6 +630,14 @@ interface TraeAdapterOptions {
553
630
  provider?: string;
554
631
  /** pi-ai provider name and profile display name; defaults to the CN name. */
555
632
  displayName?: string;
633
+ /**
634
+ * Bearer secret this provider presents to the shim.
635
+ *
636
+ * A region can publish more than one provider (consumer + enterprise), and
637
+ * the shim picks the billing pool from that bearer. Defaults to the shim's
638
+ * first route, which keeps the single-provider case unchanged.
639
+ */
640
+ secret?: string;
556
641
  resolveAttachments?: () => AttachmentStore | undefined;
557
642
  /**
558
643
  * Override the resolved pi-ai generation (see {@link withContextAdaptation});
@@ -573,6 +658,19 @@ interface TraeCredential {
573
658
  refreshToken?: string;
574
659
  userId: string;
575
660
  accountName?: string;
661
+ /**
662
+ * Trae tenant this account belongs to (`account.tenant_id`, e.g. `272193024`
663
+ * for a `tob_online` enterprise), absent for a personal account.
664
+ *
665
+ * This is what decides whether the ENTERPRISE pool can serve the account at
666
+ * all. The tenant gateway accepts any CN token for its DIRECTORY read — a
667
+ * personal account gets the full 49-model roster back — so "the roster
668
+ * loaded" proves nothing about billing rights. Its chat endpoint is what
669
+ * refuses: a personal account answers `4019` (risk control), a tenant account
670
+ * streams normally. Because the two are indistinguishable from the roster,
671
+ * the account list itself has to carry the flag.
672
+ */
673
+ tenantId?: string;
576
674
  host: string;
577
675
  /**
578
676
  * Region claim from the decrypted storage document (`userRegion.region`,
@@ -603,6 +701,27 @@ interface TraeCredentialStoreOptions {
603
701
  * stores run side by side without seeing each other's accounts.
604
702
  */
605
703
  region?: TraeRegion;
704
+ /**
705
+ * Only consider credentials that belong to a Trae tenant.
706
+ *
707
+ * The enterprise panel's store runs with this on: a personal account cannot
708
+ * bill that pool, and because the tenant gateway still serves it a directory,
709
+ * binding it here would fail only at the first chat (`4019`). With the flag
710
+ * set, an explicit binding to a personal account falls through to the preferred
711
+ * TENANT account instead of being silently honoured.
712
+ */
713
+ requireTenant?: boolean;
714
+ /**
715
+ * Withhold TENANT (enterprise) accounts from this store's account list.
716
+ *
717
+ * Set on the consumer panels: an enterprise login belongs to the enterprise
718
+ * panel, and offering it here would let a tenant account be bound to the
719
+ * personal pool without the user ever seeing which pool they picked. A
720
+ * machine that has ONLY a tenant login still resolves it — an empty list must
721
+ * not turn a working install into "signed out" — so the filter is applied to
722
+ * the OFFERED list, never to the resolved credential.
723
+ */
724
+ hideTenantAccounts?: boolean;
606
725
  /** Legacy single-copy path read as a migration source; injectable for tests. */
607
726
  legacyOwnPath?: string;
608
727
  refresh: (credential: TraeCredential) => Promise<TraeRefreshOutcome>;
@@ -612,6 +731,16 @@ interface TraeAccountChoice {
612
731
  id: string;
613
732
  accountName: string;
614
733
  edition: TraeEdition;
734
+ /**
735
+ * Whether this account may bill the CN ENTERPRISE pool.
736
+ *
737
+ * Derived from the credential's own tenant claim, because nothing else can
738
+ * tell: the tenant gateway answers a directory read for ANY CN token, so a
739
+ * personal account looks perfectly serviceable right up to its first chat,
740
+ * which it answers with `4019`. The enterprise panel filters its account list
741
+ * and its default binding on this flag.
742
+ */
743
+ enterprise: boolean;
615
744
  /** Routing bucket of this account (`cn` | `ai`), derived from its credential. */
616
745
  region: TraeRegion;
617
746
  source: 'desktop' | 'dsh' | 'cli';
@@ -649,11 +778,23 @@ declare function traeOwnAuthPath(region: TraeRegion): string;
649
778
  */
650
779
  declare function legacyTraeOwnAuthPath(): string;
651
780
  declare function normalizeTraeCredential(raw: unknown, edition: TraeEdition, source: TraeCredential['source']): TraeCredential | undefined;
781
+ /**
782
+ * Whether this account belongs to a Trae tenant, i.e. may bill the enterprise
783
+ * pool.
784
+ *
785
+ * Evidence (2026-10-17, live): the tenant's own account carries
786
+ * `account.tenant_id` / `tenant_name` and `scope: 'saas'`; the personal SOLO
787
+ * account carries neither and reports `scope: 'marscode'`. Only the tenant one
788
+ * streams on the enterprise gateway — the other answers `4019` risk control.
789
+ */
790
+ declare function isEnterpriseAccount(credential: Pick<TraeCredential, 'tenantId'> | undefined): boolean;
652
791
  declare class TraeCredentialStore {
653
792
  private storagePathOverride;
654
793
  private edition;
655
794
  private accountId;
656
795
  private readonly region;
796
+ private readonly requireTenant;
797
+ private readonly hideTenantAccounts;
657
798
  private readonly ownPathExplicit;
658
799
  private readonly legacyOwnPath;
659
800
  private readonly legacyOwnPathExplicit;
@@ -713,7 +854,55 @@ declare class TraeCredentialStore {
713
854
  * binding itself already fell through to the live account.
714
855
  */
715
856
  liveLogin(): Promise<TraeAccountChoice | undefined>;
857
+ /**
858
+ * The accounts this store is willing to OFFER.
859
+ *
860
+ * Scoped to who this store may bill:
861
+ * - a consumer store withholds tenant accounts (the enterprise pool is a
862
+ * separate tab and a separate billing decision), and
863
+ * - a tenant store withholds personal accounts (they cannot bill that
864
+ * pool; the tenant gateway answers their chat with 4019).
865
+ *
866
+ * Either filter backs off when it would hide EVERYTHING, so a machine whose
867
+ * only login is on the other side keeps working instead of reading as
868
+ * "signed out".
869
+ */
870
+ private offered;
716
871
  accounts(): Promise<TraeAccountChoice[]>;
872
+ /**
873
+ * The credential this store bills, given every credential it can see.
874
+ *
875
+ * This is the ONE resolution rule, and it exists so that `current()` and
876
+ * `accounts()` cannot disagree: `current()` applies it to `readAll()`, and
877
+ * `accounts()` applies the SAME verdict to decide which row reads as
878
+ * `selected`. Deriving that flag independently is exactly how the two drifted
879
+ * apart — and a card that marks a different account than the one the chat
880
+ * bills is worse than no card at all, because a press that "saves the
881
+ * selected account" then rewrites the binding to the account that was only
882
+ * ever DISPLAYED.
883
+ *
884
+ * Order of business:
885
+ * 1. No binding — the detected default (`preferred`) is in use, chosen from
886
+ * the OFFERED list rather than from every login on the machine. A
887
+ * consumer store that withholds tenant accounts must not default its
888
+ * billing to the tenant pool merely because that login sorts first;
889
+ * withholding is a billing decision, not a display detail.
890
+ * 2. A binding — honour it verbatim, even when the OFFERED list hides that
891
+ * account. Resolution is never scoped by `hideTenantAccounts`: the user's
892
+ * explicit choice outranks a display filter.
893
+ * 3. A tenant-scoped store cannot bill through a personal account, and the
894
+ * tenant gateway only reveals that at the first chat (`4019`). Honour the
895
+ * binding when it is eligible; otherwise fall back to the preferred
896
+ * tenant account, which is the one the user's enterprise tab is meant to
897
+ * use.
898
+ * 4. A saved account can disappear when Trae replaces its local login. Do
899
+ * NOT silently fall back to a different account: that would bill a
900
+ * different account than the one the user explicitly selected. Return
901
+ * undefined so the caller surfaces "no signed-in account" and the user
902
+ * can re-select, instead of the plugin quietly switching accounts behind
903
+ * their back.
904
+ */
905
+ private inUse;
717
906
  current(): Promise<TraeCredential | undefined>;
718
907
  /**
719
908
  * The stored credential of one specific account, without changing which
@@ -1524,9 +1713,22 @@ interface TraeSoloClientOptions {
1524
1713
  credential(): Promise<TraeCredential>;
1525
1714
  identity(): Promise<TraeIdentity>;
1526
1715
  baseUrl?: string;
1716
+ /**
1717
+ * Which chat gateway this client is pinned to. Omitted = `solo`, the consumer
1718
+ * pool. `enterprise` targets the tenant-billed `console.enterprise` gateway
1719
+ * and stamps the per-call `session_id` it requires (see
1720
+ * {@link TRAE_ENTERPRISE_HOST}).
1721
+ *
1722
+ * Pinned per CLIENT, never chosen per call: a turn must not be able to drift
1723
+ * from the pool the user picked, so the route is fixed when the provider is
1724
+ * built and every request that client makes stays on it.
1725
+ */
1726
+ route?: TraeChatRoute;
1527
1727
  fetchImpl?: typeof fetch;
1528
1728
  log?: (message: string, detail?: unknown) => void;
1529
1729
  }
1730
+ /** Which chat pool a client is pinned to. */
1731
+ type TraeChatRoute = 'solo' | 'enterprise';
1530
1732
  declare class TraeSoloUpstreamClient {
1531
1733
  private readonly options;
1532
1734
  private readonly fetchImpl;
@@ -1547,9 +1749,22 @@ declare class TraeSoloUpstreamClient {
1547
1749
  /** Merge one function's config list into the shared catalogue (first wins). */
1548
1750
  private collectModels;
1549
1751
  chatStream(bodyJson: string, signal?: AbortSignal, functionName?: string): Promise<TraeChatResult>;
1752
+ /** Chat gateway for this client's pinned route. */
1753
+ private chatBaseOf;
1550
1754
  }
1551
1755
  //#endregion
1552
1756
  //#region src/solo-bridge.d.ts
1757
+ /**
1758
+ * One upstream failure as Trae reports it inside a 200 SSE body: an `error`
1759
+ * event, or any event carrying a `code` at or above Trae's error band.
1760
+ */
1761
+ interface TraeFailure {
1762
+ code?: number;
1763
+ message: string;
1764
+ extra?: unknown;
1765
+ }
1766
+ /** A readable message for an in-stream Trae failure, with its code preserved. */
1767
+ declare function describeTraeFailure(failure: TraeFailure): string;
1553
1768
  /** Convert Trae's named SSE events into OpenAI chat-completion SSE chunks. */
1554
1769
  declare function bridgeTraeSoloStream(response: Response, model: string): Response;
1555
1770
  /**
@@ -1863,13 +2078,13 @@ declare const TRAE_REGIONS: readonly TraeRegion[];
1863
2078
  * Address one region's status route. The two regions are separate provider
1864
2079
  * stacks; every card request carries the region whose tab the user is on.
1865
2080
  */
1866
- declare function withTraeRegion(path: string, region: TraeRegion): string;
2081
+ declare function withTraeRegion(path: string, panel: TraePanel): string;
1867
2082
  /**
1868
2083
  * Read the region parameter off a status-route URL. Absent means the domestic
1869
2084
  * tab (`cn`); a present-but-unknown value returns undefined so the route can
1870
2085
  * answer 400 instead of guessing.
1871
2086
  */
1872
- declare function regionOfTraeStatusUrl(url: string): TraeRegion | undefined;
2087
+ declare function regionOfTraeStatusUrl(url: string): TraePanel | undefined;
1873
2088
  /** One credit pack and its remaining credit. */
1874
2089
  interface TraeWebCreditAccount {
1875
2090
  displayDesc: string;
@@ -2031,6 +2246,13 @@ interface TraeWebAccount {
2031
2246
  id: string;
2032
2247
  accountName: string;
2033
2248
  edition: 'cn' | 'sg' | 'solo' | 'solo-sg';
2249
+ /**
2250
+ * Whether this account belongs to a Trae tenant, i.e. may bill the enterprise
2251
+ * pool. The enterprise tab lists only these, because the tenant gateway
2252
+ * serves a directory to any CN token but refuses a personal account's chat
2253
+ * with `4019` — so nothing else reveals the difference until a turn fails.
2254
+ */
2255
+ enterprise: boolean;
2034
2256
  /** Routing bucket of this account, derived from its credential. */
2035
2257
  region: TraeRegion;
2036
2258
  source: 'desktop' | 'dsh' | 'cli';
@@ -2166,7 +2388,7 @@ declare function followAppLoginEnabled(configured: unknown): boolean;
2166
2388
  * region's picks. Tolerates any stored shape (absent, non-object) by starting
2167
2389
  * from an empty document.
2168
2390
  */
2169
- declare function nextRegionSlots<Slot extends object>(regions: unknown, region: TraeRegion, slot: Slot): Record<string, unknown>;
2391
+ declare function nextRegionSlots<Slot extends object>(regions: unknown, panel: TraePanel, slot: Slot): Record<string, unknown>;
2170
2392
  /**
2171
2393
  * Whether one region's provider is switched on. Opt-out semantics: only an
2172
2394
  * explicit `false` disables it, so a config written before this switch existed
@@ -2177,7 +2399,7 @@ declare function nextRegionSlots<Slot extends object>(regions: unknown, region:
2177
2399
  * `value` may be the whole settings section or the `regions` map (see
2178
2400
  * {@link regionsMapOf}).
2179
2401
  */
2180
- declare function regionEnabledOf(value: unknown, region: TraeRegion): boolean;
2402
+ declare function regionEnabledOf(value: unknown, panel: TraePanel): boolean;
2181
2403
  /**
2182
2404
  * Build the next `regions` settings value for a provider on/off toggle. ONLY
2183
2405
  * the target region's `enabled` flag changes: every other field of that slot
@@ -2194,7 +2416,7 @@ declare function regionEnabledOf(value: unknown, region: TraeRegion): boolean;
2194
2416
  * value is always the `regions` map, i.e. exactly what `settingsScope.set(
2195
2417
  * 'regions', ...)` needs.
2196
2418
  */
2197
- declare function nextRegionEnabled(value: unknown, region: TraeRegion, enabled: boolean): Record<string, unknown>;
2419
+ declare function nextRegionEnabled(value: unknown, panel: TraePanel, enabled: boolean): Record<string, unknown>;
2198
2420
  /**
2199
2421
  * The two seats this region's credit readout can occupy.
2200
2422
  *
@@ -2227,7 +2449,7 @@ type TraeCreditPosition = 'composer' | 'stats';
2227
2449
  * `value` may be the whole settings section or the `regions` map (see
2228
2450
  * {@link regionsMapOf}).
2229
2451
  */
2230
- declare function regionCreditPositionOf(value: unknown, region: TraeRegion): TraeCreditPosition;
2452
+ declare function regionCreditPositionOf(value: unknown, panel: TraePanel): TraeCreditPosition;
2231
2453
  /**
2232
2454
  * Build the next `regions` settings value for one region's credit seat.
2233
2455
  *
@@ -2239,7 +2461,7 @@ declare function regionCreditPositionOf(value: unknown, region: TraeRegion): Tra
2239
2461
  * value is always the `regions` map, i.e. exactly what `settingsScope.set(
2240
2462
  * 'regions', ...)` needs.
2241
2463
  */
2242
- declare function nextRegionCreditPosition(value: unknown, region: TraeRegion, position: TraeCreditPosition): Record<string, unknown>;
2464
+ declare function nextRegionCreditPosition(value: unknown, panel: TraePanel, position: TraeCreditPosition): Record<string, unknown>;
2243
2465
  /** Subscription status of an international (ai) account, rendered instead of the CN credit packs. */
2244
2466
  interface TraeWebPayStatus {
2245
2467
  isDollarUsageBilling: boolean;
@@ -2294,6 +2516,15 @@ type TraeWebUsage = {
2294
2516
  };
2295
2517
  credits?: TraeWebCredits;
2296
2518
  creditsError?: string;
2519
+ /**
2520
+ * Set when this panel has no readable balance by design, rather than by
2521
+ * failure. Only `enterprise` does: a tenant's spend is not reported by any
2522
+ * endpoint the plugin can reach (every tenant quota path answers 404), so
2523
+ * the figure exists solely in the enterprise console. The card must say so
2524
+ * instead of rendering the consumer packs, which belong to the personal
2525
+ * balance and would be read as the tenant's.
2526
+ */
2527
+ creditsUnavailable?: 'enterprise';
2297
2528
  /**
2298
2529
  * Present only when the bound account is out of credit AND another account
2299
2530
  * on this machine has some (issue #25). The card then offers a one-click
@@ -2328,35 +2559,35 @@ type TraeWebUsage = {
2328
2559
  //#endregion
2329
2560
  //#region src/web-status.d.ts
2330
2561
  /**
2331
- * Constructor dependencies. Everything region-specific is addressed by the
2332
- * region the request names: the two regions are separate provider stacks, so
2562
+ * Constructor dependencies. Everything panel-specific is addressed by the
2563
+ * panel the request names: the two regions are separate provider stacks, so
2333
2564
  * the card must be served the directory, selection, and credits of the tab the
2334
2565
  * user is on.
2335
2566
  */
2336
2567
  interface TraeUsageRouteOptions {
2337
- /** The region-scoped credential store backing each region's requests. */
2338
- store(region: TraeRegion): TraeCredentialStore;
2339
- /** The region-scoped usage client (CN work credits / international pay status). */
2340
- client(region: TraeRegion): TraeUsageClient;
2568
+ /** The panel-scoped credential store backing each region's requests. */
2569
+ store(panel: TraePanel): TraeCredentialStore;
2570
+ /** The panel-scoped usage client (CN work credits / international pay status). */
2571
+ client(panel: TraePanel): TraeUsageClient;
2341
2572
  /**
2342
2573
  * CN credit balances of an account OTHER than the bound one, read without
2343
2574
  * changing which account is bound (issue #25). Optional: when absent the
2344
2575
  * exhausted-account hint is simply not offered.
2345
2576
  */
2346
- creditsOfAccount?(region: TraeRegion, accountId: string): Promise<TraeWebCredits | undefined>;
2577
+ creditsOfAccount?(panel: TraePanel, accountId: string): Promise<TraeWebCredits | undefined>;
2347
2578
  /**
2348
2579
  * Per-account status for one row of the card's account table: CN → check-in
2349
2580
  * + balances, ai → subscription. Read without changing which account is
2350
2581
  * bound. Optional: when absent the account rows show no check-in/credits/
2351
2582
  * subscription figures (the table still lists each account and its switch).
2352
2583
  */
2353
- accountStateOf?(region: TraeRegion, accountId: string): Promise<TraeWebAccountState | undefined>;
2584
+ accountStateOf?(panel: TraePanel, accountId: string): Promise<TraeWebAccountState | undefined>;
2354
2585
  /**
2355
2586
  * Claim today's check-in reward for ONE named account, without moving the
2356
2587
  * binding. Optional: absent means the per-row claim button is disabled (the
2357
2588
  * check-in surface simply is not offered).
2358
2589
  */
2359
- claimCheckinOf?(region: TraeRegion, accountId: string): Promise<{
2590
+ claimCheckinOf?(panel: TraePanel, accountId: string): Promise<{
2360
2591
  claim: TraeCheckinClaim;
2361
2592
  checkin: TraeCheckinStatus;
2362
2593
  } | undefined>;
@@ -2367,24 +2598,24 @@ interface TraeUsageRouteOptions {
2367
2598
  * Read-only — the HOST never rebinds from this value; the follow is a
2368
2599
  * settings write, made by the card or by the host's follow switch.
2369
2600
  */
2370
- liveLogin?(region: TraeRegion): Promise<TraeWebAppLogin | undefined>;
2601
+ liveLogin?(panel: TraePanel): Promise<TraeWebAppLogin | undefined>;
2371
2602
  /** The requested region's last-refreshed raw directory (one entry per upstream model). */
2372
- displayModels(region: TraeRegion): readonly TraeModelInfo[];
2373
- /** The user's model selection in the requested region, stored as model id (= Trae name). */
2374
- enabledModelIds(region: TraeRegion): readonly string[];
2603
+ displayModels(panel: TraePanel): readonly TraeModelInfo[];
2604
+ /** The user's model selection in the requested panel, stored as model id (= Trae name). */
2605
+ enabledModelIds(panel: TraePanel): readonly string[];
2375
2606
  /**
2376
2607
  * Whether the requested region's provider is currently offered to DSH. The
2377
2608
  * card renders this as the tab's on/off checkbox, so the switch reflects the
2378
2609
  * committed settings value rather than a local guess.
2379
2610
  */
2380
- regionEnabled(region: TraeRegion): boolean;
2611
+ regionEnabled(panel: TraePanel): boolean;
2381
2612
  /** Re-read one region's live directory from the upstream. */
2382
- discoverModels?(region: TraeRegion, signal?: AbortSignal): Promise<readonly TraeModelInfo[]>;
2613
+ discoverModels?(panel: TraePanel, signal?: AbortSignal): Promise<readonly TraeModelInfo[]>;
2383
2614
  /**
2384
2615
  * Test the given model ids for availability, one real (minimal) chat call
2385
2616
  * each. Present only when the region's chat path is wired.
2386
2617
  */
2387
- probeModels?(region: TraeRegion, ids: readonly string[]): Promise<{
2618
+ probeModels?(panel: TraePanel, ids: readonly string[]): Promise<{
2388
2619
  results: {
2389
2620
  id: string;
2390
2621
  verdict: string;
@@ -2392,17 +2623,17 @@ interface TraeUsageRouteOptions {
2392
2623
  }[];
2393
2624
  skipped?: string[];
2394
2625
  }>;
2395
- /** Raw-Chat capability state of the requested region. */
2396
- rawDiagnostic?(region: TraeRegion): TraeRawDiagnostic;
2626
+ /** Raw-Chat capability state of the requested panel. */
2627
+ rawDiagnostic?(panel: TraePanel): TraeRawDiagnostic;
2397
2628
  }
2398
2629
  /**
2399
- * Assemble one region's card document. `region` is the tab the card is on; the
2400
- * region-scoped store already answers with only that region's accounts, so the
2630
+ * Assemble one region's card document. `panel` is the tab the card is on; the
2631
+ * panel-scoped store already answers with only that region's accounts, so the
2401
2632
  * document's model slots and account list are that region's by construction.
2402
2633
  * Sign-in state is read-only; credit is a live billing answer whose failure
2403
2634
  * degrades to `creditsError` rather than failing the whole document.
2404
2635
  */
2405
- declare function traeWebUsage(deps: TraeUsageRouteOptions, region: TraeRegion): Promise<TraeWebUsage>;
2636
+ declare function traeWebUsage(deps: TraeUsageRouteOptions, panel: TraePanel): Promise<TraeWebUsage>;
2406
2637
  /** Mount the GET usage route on an optional webServer context. */
2407
2638
  declare function registerTraeUsageRoute(ctx: Context$1, deps: TraeUsageRouteOptions): void;
2408
2639
  //#endregion
@@ -2550,7 +2781,7 @@ interface Config {
2550
2781
  * Per-region account selections, keyed `cn` | `ai`. Each region's tab writes
2551
2782
  * its own slot; tokens remain outside settings.
2552
2783
  */
2553
- accounts?: Partial<Record<TraeRegion, string>>;
2784
+ accounts?: Partial<Record<TraePanel, string>>;
2554
2785
  /**
2555
2786
  * Show the credit readout in the composer tool row: `Trae CN · <n>`, rendered
2556
2787
  * ONLY while the session's selected model belongs to this plugin, clickable
@@ -2593,7 +2824,7 @@ interface Config {
2593
2824
  * expose different rosters, so each keeps its own directory and selection
2594
2825
  * and switching accounts never drops the other region's picks.
2595
2826
  */
2596
- regions?: Partial<Record<TraeRegion, TraeRegionState>>;
2827
+ regions?: Partial<Record<TraePanel, TraeRegionState>>;
2597
2828
  /**
2598
2829
  * @deprecated Legacy single-slot fields from before the region split. They
2599
2830
  * predate international support and are read as the CN region's state when
@@ -2610,24 +2841,36 @@ interface Config {
2610
2841
  models?: TraeModelInfo[];
2611
2842
  }
2612
2843
  /**
2613
- * One region's saved state. A config written before the region split has only
2844
+ * One panel's saved state. A config written before the region split has only
2614
2845
  * the flat fields: those were always captured from the CN endpoint (the
2615
2846
  * plugin had no international support), so they are read as the CN state and
2616
2847
  * only when no explicit CN slot exists. The ai region never inherits them —
2617
2848
  * that inheritance is exactly the bug where a stale CN directory would be
2618
2849
  * intersected with the international catalog and silently drop the user's
2619
2850
  * picks (the same failure workbuddy fixed with its region split).
2851
+ *
2852
+ * Keyed by PANEL (`cn` | `enterprise` | `ai`), because each panel carries its
2853
+ * own switch, account binding and model selection. `enterprise` has no legacy
2854
+ * equivalent: it starts from an EMPTY state (its own directory, its own model
2855
+ * picks) and never inherits CN's, so switching it on cannot silently activate
2856
+ * a model list the user never chose for the tenant pool.
2620
2857
  */
2621
- declare function regionStateOf(config: Config, region: TraeRegion): TraeRegionState;
2858
+ declare function regionStateOf(config: Config, panel: TraePanel): TraeRegionState;
2622
2859
  /**
2623
- * Whether one region's provider is switched on (issue #11). Opt-out semantics:
2860
+ * Whether one panel's provider is switched on (issue #11). Opt-out semantics:
2624
2861
  * only an explicit `false` disables it, so every config written before this
2625
2862
  * switch existed — including the pre-region-split flat fields, which never
2626
2863
  * carry `enabled` — keeps both providers running exactly as before. The card
2627
2864
  * reads the same rule through `regionEnabledOf`, so the two halves can never
2628
2865
  * disagree about a region's state.
2866
+ *
2867
+ * The ENTERPRISE panel is the one deliberate exception: it defaults OFF. A
2868
+ * consumer-only account (`tenant 7o2d894p7dr0o4`) cannot use that pool at all,
2869
+ * so opting every existing user into a second CN provider would put a route in
2870
+ * their model picker that fails on first use. It is switched on from its card
2871
+ * tab, by someone whose account actually belongs to a tenant.
2629
2872
  */
2630
- declare function regionEnabled(config: Config, region: TraeRegion): boolean;
2873
+ declare function regionEnabled(config: Config, panel: TraePanel): boolean;
2631
2874
  /**
2632
2875
  * WHERE one region's credit readout sits (learned from workbuddy #62).
2633
2876
  *
@@ -2658,4 +2901,4 @@ declare function asVolatile<S>(schema: S): S;
2658
2901
  declare const Config: z<Config>;
2659
2902
  declare function apply(ctx: Context$1, config: Config): void;
2660
2903
  //#endregion
2661
- export { Config, FALLBACK_TRAE_MODELS, FALLBACK_TRAE_MODELS_AI, type PiAiGeneration, type PiAiRuntimeInfo, REGION_GATEWAYS, type RawChatDelta, type RawChatMessage, type RawChatTool, SseDecoder, type SseEvent, TRAE_ACCOUNT_STATUS_PATH, TRAE_AI_PROVIDER, TRAE_CHECKIN_PATH, TRAE_CN_AGENT_TASK_PATH, TRAE_CN_TITLE_PATH, TRAE_MODELS_TEST_PATH, TRAE_MODEL_DETAIL_FUNCTIONS, TRAE_MODEL_DETAIL_PATH, TRAE_PAY_BASE, TRAE_PROBE_TIMEOUT_MS, TRAE_PROVIDER, TRAE_PROVIDERS, TRAE_PROVIDER_DISPLAY_NAMES, TRAE_RAW_CHAT_V1_PATH, TRAE_RAW_CHAT_V2_PATH, TRAE_REASONING_EFFORTS, TRAE_REGIONS, TRAE_REGION_PARAM, TRAE_SETTINGS_NS, TRAE_SOLO_CHAT_PATH, TRAE_SOLO_FUNCTION, TRAE_SOLO_MODELS_PATH, TRAE_SOLO_REMOTE_BASE, TRAE_STATE_DB_FILENAME, TRAE_STREAM_IDLE_TIMEOUT_MS, TRAE_USAGE_PATH, TRAE_VERSION_CODE_FALLBACK, type TraeActivityRule, type TraeAdapter, type TraeCachedModelConfig, TraeCatalog, type TraeChatResult, type TraeCheckinClaim, type TraeCheckinStatus, type TraeContextBudget, type TraeCredential, TraeCredentialStore, TraeDelegatingUpstreamClient, type TraeDiscoveredModel, type TraeDiscoveredReasoning, type TraeEdition, TraeFallbackUpstreamClient, type TraeFallbackUpstreamOptions, type TraeFusionRawChatEnvelope, TraeGatedUpstreamClient, type TraeGatedUpstreamOptions, type TraeIdentity, type TraeInputModality, type TraeModelDetailRequest, type TraeModelInfo, type TraeModelProbeVerdict, type TraeModelsTestResponse, type TraeObservedModelConfig, type TraeProbeResult, type TraeProbeVerdict, TraeRawCapabilityController, type TraeRawCapabilityControllerOptions, type TraeRawCapabilitySnapshot, TraeRawCapabilityState, type TraeRawChatBehaviorConfig, type TraeRawChatCapability, type TraeRawChatClientOptions, type TraeRawChatConfig, type TraeRawChatFailureReason, type TraeRawChatRuntimeConfig, TraeRawChatUpstreamClient, type TraeRawDiagnostic, type TraeRawDiagnosticState, type TraeRawGateway, type TraeRawGatewayOptions, type TraeRawResolverResult, type TraeReasoningCapability, type TraeReasoningEffort, type TraeRefreshDevice, type TraeRegion, type TraeRegionGateways, TraeRegionState, type TraeShim, TraeSoloBridge, type TraeSoloClientOptions, TraeSoloRemoteCatalogClient, type TraeSoloRemoteCatalogOptions, TraeSoloUpstreamClient, type TraeStorageCandidate, type TraeStreamEvent, type TraeUpstreamClient, TraeUsageClient, type TraeUsageOptions, type TraeUsagePack, type TraeUsageRouteOptions, type TraeUsageSnapshot, type TraeUsageSummary, type TraeUsageView, type TraeWebAccountState, type TraeWebActivity, type TraeWebAppLogin, type TraeWebCheckin, type TraeWebCheckinClaim, type TraeWebCredits, type TraeWebUsage, type TraeWireModel, UnconfiguredTraeUpstreamClient, adaptLegacyPiAiContext, adaptModernPiAiContext, apply, applyContextBudgets, applyImageSelection, applyReasoningEffort, asVolatile, bridgeTraeSoloStream, buildTraeAgentTaskBody, buildTraeCnHeaders, buildTraeFusionRawChatEnvelope, buildTraeModelDetailRequest, buildTraeRawChatDraft, buildTraeRawChatRuntimeConfig, classifyProbeError, classifyProbeResult, classifyTraeRawChatFailure, configuredAccountsOf, createTraeAdapter, createTraeRawGateway, createTraeShim, creditPosition, decidePiAiGeneration, decodeRawChatChunk, decodeTraeEvent, decryptTraeStorageValue, deriveCatalog, describeIdShape, describeNameShape, discoveredCatalog, fallbackModelsFor, followAppLoginEnabled, generationOf, hashTraeRawChatArg, identityHeaders, inject, legacyTraeOwnAuthPath, maskUserPath, mergeTraeModelSources, name, nextRegionCreditPosition, nextRegionEnabled, nextRegionSlots, normalizeTraeCredential, normalizeTraeVersionCode, parseObservedModelConfig, parseReasoningCapability, parseTraeAuthValue, parseTraeCachedModel, parseTraeModelExtraConfigLogLine, parseTraeRawChatBehaviorConfig, parseTraeRemoteModel, parseTraeStorageDocument, piAiRuntimeInfo, pickTraeStorageIdentity, prepareSoloBody, probeBody, probeModelsSequentially, probeOneModel, probeTraeRawChatCapability, rawCapabilityDiagnostic, rawCapabilityFingerprint, readTraeCachedModel, readTraeCliIdentity, readTraeIdentity, refreshTraeCredential, regionCreditPositionOf, regionEnabled, regionEnabledOf, regionOfCredential, regionOfEdition, regionOfHost, regionOfTraeProvider, regionOfTraeStatusUrl, regionOfUserRegion, regionStateOf, registerTraeUsageRoute, resolveTraeIdentity, resolveTraeRawRuntime, sanitizeCatalog, settingsNamespaceOf, traeEndpoint, traeInputModalities, traeModelDisplayName, traeOwnAuthPath, traeRawChatExtraInfo, traeStateDatabaseCandidates, traeStorageCandidates, traeWebUsage, traeWindowsAppNames, unwrapVolatile, unwrapVolatileDeep, withContextAdaptation, withTraeRegion };
2904
+ export { Config, FALLBACK_TRAE_MODELS, FALLBACK_TRAE_MODELS_AI, type PiAiGeneration, type PiAiRuntimeInfo, REGION_GATEWAYS, type RawChatDelta, type RawChatMessage, type RawChatTool, SseDecoder, type SseEvent, TRAE_ACCOUNT_STATUS_PATH, TRAE_AI_PROVIDER, TRAE_CHECKIN_PATH, TRAE_CN_AGENT_TASK_PATH, TRAE_CN_TITLE_PATH, TRAE_ENTERPRISE_PROVIDER, TRAE_MODELS_TEST_PATH, TRAE_MODEL_DETAIL_FUNCTIONS, TRAE_MODEL_DETAIL_PATH, TRAE_PANELS, TRAE_PAY_BASE, TRAE_PROBE_TIMEOUT_MS, TRAE_PROVIDER, TRAE_PROVIDERS, TRAE_PROVIDER_DISPLAY_NAMES, TRAE_PROVIDER_IDS, TRAE_PROVIDER_ID_DISPLAY_NAMES, TRAE_PROVIDER_ROUTES, TRAE_RAW_CHAT_V1_PATH, TRAE_RAW_CHAT_V2_PATH, TRAE_REASONING_EFFORTS, TRAE_REGIONS, TRAE_REGION_PARAM, TRAE_SETTINGS_NS, TRAE_SOLO_CHAT_PATH, TRAE_SOLO_FUNCTION, TRAE_SOLO_MODELS_PATH, TRAE_SOLO_REMOTE_BASE, TRAE_STATE_DB_FILENAME, TRAE_STREAM_IDLE_TIMEOUT_MS, TRAE_USAGE_PATH, TRAE_VERSION_CODE_FALLBACK, type TraeActivityRule, type TraeAdapter, type TraeCachedModelConfig, TraeCatalog, type TraeChatResult, type TraeCheckinClaim, type TraeCheckinStatus, type TraeContextBudget, type TraeCredential, TraeCredentialStore, TraeDelegatingUpstreamClient, type TraeDiscoveredModel, type TraeDiscoveredReasoning, type TraeEdition, type TraeFailure, TraeFallbackUpstreamClient, type TraeFallbackUpstreamOptions, type TraeFusionRawChatEnvelope, TraeGatedUpstreamClient, type TraeGatedUpstreamOptions, type TraeIdentity, type TraeInputModality, type TraeModelDetailRequest, type TraeModelInfo, type TraeModelProbeVerdict, type TraeModelsTestResponse, type TraeObservedModelConfig, type TraePanel, type TraeProbeResult, type TraeProbeVerdict, type TraeProviderRoute, TraeRawCapabilityController, type TraeRawCapabilityControllerOptions, type TraeRawCapabilitySnapshot, TraeRawCapabilityState, type TraeRawChatBehaviorConfig, type TraeRawChatCapability, type TraeRawChatClientOptions, type TraeRawChatConfig, type TraeRawChatFailureReason, type TraeRawChatRuntimeConfig, TraeRawChatUpstreamClient, type TraeRawDiagnostic, type TraeRawDiagnosticState, type TraeRawGateway, type TraeRawGatewayOptions, type TraeRawResolverResult, type TraeReasoningCapability, type TraeReasoningEffort, type TraeRefreshDevice, type TraeRegion, type TraeRegionGateways, TraeRegionState, type TraeShim, TraeSoloBridge, type TraeSoloClientOptions, TraeSoloRemoteCatalogClient, type TraeSoloRemoteCatalogOptions, TraeSoloUpstreamClient, type TraeStorageCandidate, type TraeStreamEvent, type TraeUpstreamClient, TraeUsageClient, type TraeUsageOptions, type TraeUsagePack, type TraeUsageRouteOptions, type TraeUsageSnapshot, type TraeUsageSummary, type TraeUsageView, type TraeWebAccountState, type TraeWebActivity, type TraeWebAppLogin, type TraeWebCheckin, type TraeWebCheckinClaim, type TraeWebCredits, type TraeWebUsage, type TraeWireModel, UnconfiguredTraeUpstreamClient, adaptLegacyPiAiContext, adaptModernPiAiContext, apply, applyContextBudgets, applyImageSelection, applyReasoningEffort, asVolatile, bridgeTraeSoloStream, buildTraeAgentTaskBody, buildTraeCnHeaders, buildTraeFusionRawChatEnvelope, buildTraeModelDetailRequest, buildTraeRawChatDraft, buildTraeRawChatRuntimeConfig, classifyProbeError, classifyProbeResult, classifyTraeRawChatFailure, configuredAccountsOf, createTraeAdapter, createTraeRawGateway, createTraeShim, creditPosition, decidePiAiGeneration, decodeRawChatChunk, decodeTraeEvent, decryptTraeStorageValue, deriveCatalog, describeIdShape, describeNameShape, describeTraeFailure, discoveredCatalog, displayNameOfTraeProvider, fallbackModelsFor, followAppLoginEnabled, generationOf, hashTraeRawChatArg, identityHeaders, inject, isEnterpriseAccount, legacyTraeOwnAuthPath, maskUserPath, mergeTraeModelSources, name, nextRegionCreditPosition, nextRegionEnabled, nextRegionSlots, normalizeTraeCredential, normalizeTraeVersionCode, panelOfKey, panelOfProvider, parseObservedModelConfig, parseReasoningCapability, parseTraeAuthValue, parseTraeCachedModel, parseTraeModelExtraConfigLogLine, parseTraeRawChatBehaviorConfig, parseTraeRemoteModel, parseTraeStorageDocument, piAiRuntimeInfo, pickTraeStorageIdentity, prepareSoloBody, probeBody, probeModelsSequentially, probeOneModel, probeTraeRawChatCapability, providerOfPanel, rawCapabilityDiagnostic, rawCapabilityFingerprint, readTraeCachedModel, readTraeCliIdentity, readTraeIdentity, refreshTraeCredential, regionCreditPositionOf, regionEnabled, regionEnabledOf, regionOfCredential, regionOfEdition, regionOfHost, regionOfPanel, regionOfTraeProvider, regionOfTraeStatusUrl, regionOfUserRegion, regionStateOf, registerTraeUsageRoute, resolveTraeIdentity, resolveTraeRawRuntime, routeOfTraeProvider, sanitizeCatalog, settingsNamespaceOf, traeEndpoint, traeInputModalities, traeModelDisplayName, traeOwnAuthPath, traeRawChatExtraInfo, traeStateDatabaseCandidates, traeStorageCandidates, traeWebUsage, traeWindowsAppNames, unwrapVolatile, unwrapVolatileDeep, withContextAdaptation, withTraeRegion };