@serviceme/devtools-shared 0.4.6 → 0.4.8

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/dist/index.d.ts CHANGED
@@ -40,7 +40,7 @@
40
40
  * pre-fill baseUrl / displayName / default model list without
41
41
  * requiring the user to look up endpoint docs.
42
42
  */
43
- type ProviderType = "openai-compatible" | "anthropic-compatible" | "minimax" | "deepseek" | "kimi" | "zhipu" | "stepfun" | "siliconflow" | "openrouter" | "novita" | "agnes" | "vscode-builtin";
43
+ type ProviderType = "openai-compatible" | "anthropic-compatible" | "minimax" | "deepseek" | "kimi" | "zhipu" | "stepfun" | "siliconflow" | "openrouter" | "novita" | "agnes" | "medalsoft" | "vscode-builtin";
44
44
  /**
45
45
  * Curated metadata for named, well-known models. Used as a
46
46
  * **fallback** when a `ProviderModel` entry omits one of the
@@ -87,6 +87,17 @@ interface CuratedModelMetadata {
87
87
  priceCategory: ModelPriceCategory;
88
88
  /** Thinking-dropdown schema (omit = no thinking dropdown). */
89
89
  thinkingSchema?: Exclude<ModelThinkingSchema, "none">;
90
+ /**
91
+ * Whether the endpoint additionally accepts the `reasoning_effort`
92
+ * field (Zhipu official OpenAPI: "仅 GLM-5.2 及其以上模型支持",
93
+ * fetched 2026-08-19). Distinct from {@link thinkingSchema}: the
94
+ * 3-level dropdown rides every GLM-4.5+ model (thinking switch
95
+ * on/off), while the effort field is a 5.2+ extra that older
96
+ * endpoints may reject. Consumed by the OpenAI adapter to gate the
97
+ * `reasoning_effort` wire field (mirrors `supportsReasoningEffort`
98
+ * in `docs/references/GLM-for-copilot-main/src/consts.ts`).
99
+ */
100
+ supportsReasoningEffort?: boolean;
90
101
  /**
91
102
  * Context-window token caps. Centralized here (rather than as
92
103
  * magic numbers scattered across `BUILTIN_PROVIDER_PRESETS` call
@@ -194,6 +205,29 @@ interface ProviderModel {
194
205
  */
195
206
  thinkingSchema?: ModelThinkingSchema;
196
207
  }
208
+ /**
209
+ * Per-model vision handling mode (BYOM-depth #3).
210
+ *
211
+ * Borrowed from
212
+ * `docs/references/GLM-for-copilot-main/src/types.ts:167`
213
+ * (`ModelVisionMode = 'proxy' | 'native' | 'mcp'`). v1 ships
214
+ * `native` + `mcp`; `proxy` is reserved for v2 (the recursive-
215
+ * chat vision model description has its own design pass).
216
+ *
217
+ * - `native` (default) — image bytes are passed inline to the
218
+ * adapter, which translates them to the vendor's native
219
+ * wire shape (OpenAI `image_url`, Anthropic `source.base64`).
220
+ * Existing v0 behaviour; byte-identical to the pre-BYOM-depth
221
+ * path.
222
+ * - `mcp` — image bytes are persisted to
223
+ * `<globalStorageUri>/images/<sha256>.<ext>` and the user
224
+ * message is rewritten with a `[Image attached at local file:
225
+ * <path>]` placeholder + a system preamble telling the model
226
+ * to use an image-capable MCP tool to read the file. Useful
227
+ * for text-only models and self-hosted gateways where inline
228
+ * base64 is undesirable.
229
+ */
230
+ type ProviderVisionMode = "native" | "mcp";
197
231
  /**
198
232
  * Persisted provider configuration. `apiKeyRef` is the SecretStorage
199
233
  * key; the actual key never appears in this object after creation
@@ -232,6 +266,16 @@ interface ProviderConfig {
232
266
  * Ignored for non-minimax providers.
233
267
  */
234
268
  minimaxBillingType?: "token_plan" | "pay_as_you_go";
269
+ /**
270
+ * Per-provider vision handling mode (BYOM-depth #3). Defaults
271
+ * to `"native"` when absent — the existing v0 behaviour,
272
+ * byte-identical to the pre-BYOM-depth path. Set to `"mcp"`
273
+ * to route image-bearing requests through the on-disk
274
+ * placeholder path (useful for text-only models and self-
275
+ * hosted gateways). See {@link ProviderVisionMode} for the
276
+ * full contract.
277
+ */
278
+ visionMode?: ProviderVisionMode;
235
279
  /** Created / updated timestamps (informational) */
236
280
  createdAt: string;
237
281
  updatedAt: string;
@@ -408,6 +452,63 @@ interface ProviderBaseUrlPreset {
408
452
  baseUrl: string;
409
453
  }
410
454
 
455
+ /**
456
+ * Wire protocol implied by a `baseUrl`.
457
+ *
458
+ * Used to disambiguate the same vendor's two coexisting endpoints
459
+ * (OpenAI-compatible vs Anthropic-compatible) when the user picks
460
+ * a baseUrl from the ProvidersTab dropdown. Today the only
461
+ * commonly-ambiguous vendor is **Zhipu / 智谱**:
462
+ *
463
+ * - `https://open.bigmodel.cn/api/paas/v4` → openai
464
+ * - `https://open.bigmodel.cn/api/coding/paas/v4` → openai
465
+ * - `https://open.bigmodel.cn/api/anthropic` → anthropic
466
+ * - `https://api.z.ai/api/paas/v4` → openai
467
+ * - `https://api.z.ai/api/coding/paas/v4` → openai
468
+ * - `https://api.z.ai/api/anthropic` → anthropic
469
+ *
470
+ * The reference plugin (`docs/references/GLM-for-copilot-main`)
471
+ * encodes this as an `EndpointPreset` enum literal; we encode it
472
+ * as a path heuristic on the baseUrl. Trade-off: a typo'd path
473
+ * that says "anthropic" would mis-classify, but the same
474
+ * `PROVIDER_BASE_URL_PRESETS.zhipu` dropdown that exposes the
475
+ * Anthropic option ALSO labels it `国内 · Coding Plan · Anthropic 协议`
476
+ * so the user has visual confirmation; a typo in path without
477
+ * matching dropdown is unlikely.
478
+ *
479
+ * Detection rule: a `/anthropic` (or `/anthropic/...`) segment
480
+ * anywhere in the URL **path** — case-insensitive. Hostname
481
+ * matches (e.g. `api.anthropic.com`) are intentionally ignored:
482
+ * we do not currently support routing to Anthropic's own
483
+ * production API (their models are first-class VSCode features).
484
+ */
485
+ type ProviderWireProtocol = "openai" | "anthropic";
486
+ declare function protocolForBaseUrl(baseUrl: string): ProviderWireProtocol;
487
+ /**
488
+ * Resolve the actual `ProviderType` whose adapter should handle a
489
+ * request with the given `configuredType` + `baseUrl`.
490
+ *
491
+ * Most of the time this is just `configuredType`. The exception is
492
+ * the named `zhipu` provider with an Anthropic-protocol baseUrl
493
+ * (`/api/anthropic`); we route it through the `anthropic-compatible`
494
+ * adapter so the URL construction appends `/v1/messages` instead of
495
+ * the OpenAI `/v1/chat/completions`. Without this, the OpenAIAdapter
496
+ * would build `.../api/anthropic/chat/completions` and GLM would
497
+ * 404 (the Anthropic-compatible endpoint only serves
498
+ * `.../api/anthropic/v1/messages`).
499
+ *
500
+ * `minimax` is intentionally NOT in the override list because the
501
+ * curated preset is `https://api.minimaxi.com/anthropic` (already
502
+ * Anthropic-protocol), and the `minimax` case in the adapter
503
+ * factory already wires AnthropicAdapter unconditionally.
504
+ *
505
+ * Everything else (deepseek / kimi / stepfun / agnes / openrouter /
506
+ * novita / openai-compatible / anthropic-compatible) returns
507
+ * `configuredType` unchanged — these vendors don't publish an
508
+ * alternate-protocol endpoint on the same host.
509
+ */
510
+ declare function effectiveAdapterType(configuredType: ProviderType, baseUrl: string): ProviderType;
511
+
411
512
  /**
412
513
  * Provider-type → known baseUrl candidates (e.g. mainland-China vs.
413
514
  * global endpoints for the same vendor, like Agnes/MiniMax/DeepSeek).
@@ -437,6 +538,20 @@ declare const PROVIDER_CACHE_CONTROL_METADATA: Readonly<Record<ProviderType, Pro
437
538
  */
438
539
  declare function isProviderCacheControlAware(type: ProviderType): boolean;
439
540
 
541
+ /**
542
+ * Map of namespaced model ids (used by aggregator platforms like
543
+ * SiliconFlow and Novita) to their primary entry. **Exported** so
544
+ * downstream code (e.g. the "Pick from preset" dropdown in
545
+ * ProvidersTab) can identify which entries in `MODEL_METADATA` are
546
+ * aliases vs primary curated ids — listing aliases would
547
+ * duplicate primaries in the UI.
548
+ *
549
+ * **Read-only by design.** Don't mutate; if you need to add a new
550
+ * aggregator alias, do it here so the merged `MODEL_METADATA`
551
+ * auto-tracks the primary.
552
+ */
553
+ declare const NAMESPACE_ALIASES: Readonly<Record<string, string>>;
554
+ declare const NAMESPACE_ALIAS_FAMILY: Readonly<Record<string, string>>;
440
555
  declare const MODEL_METADATA: Readonly<Record<string, CuratedModelMetadata>>;
441
556
  /**
442
557
  * Look up curated metadata for a model by its un-qualified id
@@ -451,19 +566,248 @@ declare function lookupModelMetadata(modelId: string): CuratedModelMetadata | un
451
566
  * Resolve the currency for a baseUrl. Strict hostname match —
452
567
  * `api.minimaxi.com` and `api.minimaxi.cn` map to CNY (the China
453
568
  * platform), `api.minimax.io` maps to USD (the global platform),
454
- * `api.deepseek.com` maps to CNY (DeepSeek's regional pricing is
455
- * published in CNY on the public docs even though the API is
456
- * global), everything else falls back to USD. The match is
457
- * exact-host so a typo in the hostname never silently flips
458
- * currency.
569
+ * everything else falls back to USD (the global default). The
570
+ * match is exact-host so a typo in the hostname never silently
571
+ * flips currency. The earlier 2026-08-18 draft also mapped
572
+ * `api.deepseek.com` to CNY, but that was wrong: DeepSeek's
573
+ * international `.com` endpoint publishes USD prices for global
574
+ * accounts (per https://api-docs.deepseek.com/quick_start/pricing/,
575
+ * which lists both $ and ¥ on the same page, with the $ block
576
+ * corresponding to the .com endpoint). The CNY-priced alternative
577
+ * is the China-domestic region, not the international `.com`
578
+ * host, so the currency now follows the project default (USD)
579
+ * via the catch-all below.
459
580
  */
460
581
  declare function currencyForBaseUrl(baseUrl: string): "USD" | "CNY";
461
582
 
462
- declare const BUILTIN_PROVIDER_PRESETS: Readonly<Record<"minimax" | "deepseek" | "kimi" | "zhipu" | "stepfun" | "siliconflow" | "openrouter" | "novita" | "agnes", {
583
+ /**
584
+ * Default configuration snippets shipped with named vendor types.
585
+ *
586
+ * When the user picks `minimax` / `deepseek` / `agnes` in the
587
+ * ProvidersTab, the form pre-fills `displayName` + `baseUrl` + a
588
+ * starter `models` list from this table. The user still has to
589
+ * paste their own `apiKey` (always empty by default — secrets
590
+ * never ship with the extension).
591
+ *
592
+ * Keep `baseUrl` here in sync with the upstream vendor docs.
593
+ *
594
+ * Adapter routing (see `apps/extension/src/services/providers/adapters/index.ts`):
595
+ * - minimax: Anthropic-compatible at `https://api.minimaxi.com/anthropic`
596
+ * → routed to AnthropicAdapter
597
+ * - deepseek: OpenAI-compatible at `https://api.deepseek.com/v1`
598
+ * → routed to OpenAIAdapter (the /anthropic surface v3 exposed
599
+ * is no longer documented for v4)
600
+ * - agnes: OpenAI-compatible at `https://apihub.agnes-ai.com/v1`
601
+ * → routed to OpenAIAdapter
602
+ * - medalsoft: OpenAI-compatible internal gateway at
603
+ * `https://llm.proxy.alio.wang/v1` → routed to OpenAIAdapter
604
+ * (empty starter model list — populate via "Fetch from API")
605
+ *
606
+ * Earlier iterations of the minimax default 401'd on the team; do
607
+ * NOT swap minimax back to one of these without checking with the
608
+ * user first:
609
+ * - `https://agent.minimaxi.com/mavis/api/v1/llm/v1` (opencode.json
610
+ * proxy URL — AnthropicAdapter would double-prefix /v1 to it)
611
+ * - `https://agent.minimaxi.com/v1` (OpenAI-compat
612
+ * variant — user tried this in commit 8bd867c then asked to
613
+ * revert in 71faf6e-era because it 401'd as well)
614
+ */
615
+ /**
616
+ * Build a `ProviderModel` preset entry by joining the static
617
+ * context-window numbers (token caps are user-visible and depend
618
+ * on the wire-protocol spec, not the curated metadata) with the
619
+ * curated metadata in `MODEL_METADATA` (detail / capabilities /
620
+ * pricing / thinking). The user can override any field in the
621
+ * ProvidersTab form; the curated values are just the starter
622
+ * defaults so the picker shows the cost column + thinking
623
+ * dropdown out of the box for the named vendors.
624
+ *
625
+ * Pricing block is selected to match `baseUrl`'s currency (via
626
+ * `currencyForBaseUrl`): CNY for `open.bigmodel.cn` /
627
+ * `api.moonshot.cn` / etc., USD for `api.z.ai` / `openrouter.ai` /
628
+ * etc. Falls back to USD for unrecognised hosts. The caller is
629
+ * expected to pass a real `baseUrl` — when adding a brand-new
630
+ * provider the host is already known (came from the
631
+ * `PROVIDER_BASE_URL_PRESETS` dropdown or user-typed); the empty
632
+ * `""` default picks USD as a safe fallback.
633
+ */
634
+ declare function buildPresetModel(id: string, displayName: string, baseUrl?: string): ProviderModel;
635
+ /**
636
+ * Union a model row returned by the "Fetch from API" flow with its
637
+ * curated preset metadata, when the id matches an entry in
638
+ * `MODEL_METADATA`. The API typically returns just `id` (sometimes
639
+ * `displayName`); the user expects the picker's `detail` / `pricing`
640
+ * / `capabilities` / `maxInputTokens` columns to be filled in for
641
+ * any model we curate, not blank.
642
+ *
643
+ * Precedence (TDD-pinned 2026-08-19, see
644
+ * `test/unionProviderModelWithPreset.test.mjs`):
645
+ *
646
+ * • **Preset wins** for the curated fields: `detail`,
647
+ * `capabilities`, `pricing`, `priceCategory`, `thinkingSchema`,
648
+ * `maxInputTokens`, `maxOutputTokens`. These are the values we
649
+ * maintain by hand and trust more than what the API publishes,
650
+ * which is often missing or stale (e.g. the OpenAI `/v1/models`
651
+ * endpoint does not return pricing or token caps; DeepSeek's
652
+ * `GET /models` likewise returns id + owned_by only).
653
+ * • **Fetched wins** for `id` (the API is the source of truth for
654
+ * what the endpoint actually exposes — a stale preset could list
655
+ * a model the user no longer has access to).
656
+ * • **`displayName`** — the 2026-08-19 follow-up: fetched wins
657
+ * when set, the preset's curated `displayName` (from
658
+ * `BUILTIN_PROVIDER_PRESETS`, see
659
+ * `getPresetModelDisplayName`) fills in when fetched omits it
660
+ * or sends an empty string. Without this fallback, the picker
661
+ * would render the bare id (`deepseek-v4-flash`) as the model
662
+ * name right after the fetch result lands — the user picked
663
+ * "Fetch from API" because they wanted the live catalog, but
664
+ * the friendly label they would have seen if they'd picked
665
+ * the vendor from the named-vendor `<select>` should also
666
+ * surface here. Empty string is treated the same as missing
667
+ * (a blank label in the picker is strictly worse than the
668
+ * curated friendly name).
669
+ * • **No preset match** → returns the fetched model unchanged
670
+ * (custom / aggregator-only models stay bare; the user fills
671
+ * in detail / pricing by hand).
672
+ *
673
+ * `baseUrl` is consulted to pick the right currency for `pricing`
674
+ * (CNY for `open.bigmodel.cn` / `api.moonshot.cn` / etc., USD
675
+ * otherwise — see `currencyForBaseUrl`). Pass the form's current
676
+ * `editing.baseUrl`; that is the same baseUrl the row was just
677
+ * fetched from, so the resolved currency matches what the user
678
+ * will see in the picker. Empty / unset baseUrl → USD fallback.
679
+ *
680
+ * Namespaced ids (e.g. `deepseek-ai/DeepSeek-V4-Pro` on
681
+ * SiliconFlow) resolve transparently — `MODEL_METADATA` aliases
682
+ * the primary entry's metadata reference under every namespace key,
683
+ * so `lookupModelMetadata("deepseek-ai/DeepSeek-V4-Pro")` returns
684
+ * the same object as `lookupModelMetadata("deepseek-v4-pro")`.
685
+ */
686
+ declare function unionProviderModelWithPreset(fetched: ProviderModel, baseUrl: string): ProviderModel;
687
+ /**
688
+ * One entry in the "Pick from preset" dropdown shown next to the
689
+ * "+ Add model" button in ProvidersTab.
690
+ */
691
+ interface PresetModelListing {
692
+ /** Canonical (primary, non-alias) model id; safe to feed to {@link buildPresetModel}. */
693
+ id: string;
694
+ /** Short human label; the dropdown option text. */
695
+ displayName: string;
696
+ /** Vendor family bucket — drives the `<optgroup>` grouping. */
697
+ vendorFamily: string;
698
+ }
699
+ /**
700
+ * The list of vendor family groups shown in the preset dropdown.
701
+ * Order is intentional (most common presets first):
702
+ * 1. GLM (Zhipu / 智谱) — the user explicitly asked us to
703
+ * support 4-channel endpoints; GLM has the richest preset
704
+ * list (15+ models) so it gets the top slot.
705
+ * 2. DeepSeek / Kimi / StepFun / MiniMax — the other named
706
+ * vendors with curated presets.
707
+ * 3. Agnes / Qwen — the smaller curated lists.
708
+ * 4. Aggregators (SiliconFlow / Novita / OpenRouter) — listed
709
+ * last because users on aggregators usually type the namespaced
710
+ * id by hand rather than reach for a curated dropdown.
711
+ */
712
+ declare const PRESET_MODEL_FAMILIES: readonly string[];
713
+ /**
714
+ * The "Pick from preset" dropdown options — every curated primary
715
+ * entry in `MODEL_METADATA` PLUS every alias tagged with an
716
+ * aggregator family in `NAMESPACE_ALIAS_FAMILY`. Grouped by
717
+ * vendor family. Sorted alphabetically within each family so the
718
+ * dropdown order is stable across runs.
719
+ *
720
+ * Two alias flavours exist in `NAMESPACE_ALIASES`:
721
+ * - **Aggregator aliases** (SiliconFlow `deepseek-ai/…`,
722
+ * Novita `zai/…` / `deepseek/…`, etc.) — KEPT in the list so
723
+ * the dropdown surfaces the namespaced ids aggregator users
724
+ * actually need to type. They are routed to the matching
725
+ * aggregator <optgroup> via `NAMESPACE_ALIAS_FAMILY`.
726
+ * - **Historical / naming aliases** (e.g. the Zhipu
727
+ * `glm-4-flashx-250414` rebrand of `glm-4-flashx`) — DROPPED
728
+ * because they're duplicates of an existing primary entry
729
+ * that already appears in the dropdown. Users with the
730
+ * historical id already in their settings.json keep
731
+ * working at the chat-registration layer
732
+ * (see `MODEL_METADATA`'s alias merge) — the dropdown just
733
+ * doesn't surface a redundant second option.
734
+ *
735
+ * The filter rule is the inverse of the aggregator tag presence:
736
+ * any alias with a `NAMESPACE_ALIAS_FAMILY` entry is kept, every
737
+ * other alias is filtered. The pinning test
738
+ * `test/listPresetModelGroups.test.mjs` asserts this 1:1 mapping
739
+ * between the two structures.
740
+ *
741
+ * Used by `ProvidersTab.tsx` to render the `<select>` next to the
742
+ * "+ Add model" button. Selecting an option calls
743
+ * `buildPresetModel(id, displayName, baseUrl)` and appends the
744
+ * resulting `ProviderModel` to the editing list. The `displayName`
745
+ * mirrors the model id verbatim (the canonical form is what users
746
+ * see in /v1/models, what VSCode's chat picker surfaces, and what
747
+ * the existing `BUILTIN_PROVIDER_PRESETS` pre-fills); the user can
748
+ * still rename the field after picking — this is just a starter
749
+ * label.
750
+ */
751
+ declare const LISTABLE_PRESET_MODELS: readonly PresetModelListing[];
752
+ /**
753
+ * Group {@link LISTABLE_PRESET_MODELS} by `vendorFamily`, preserving
754
+ * the order declared in {@link PRESET_MODEL_FAMILIES} (most-common
755
+ * first). Empty families are dropped so the dropdown only shows
756
+ * groups that actually have entries.
757
+ *
758
+ * Returns: array of `{ family, entries }` — the shape a UI
759
+ * `<select>` renderer expects when building `<optgroup>`s.
760
+ */
761
+ interface PresetModelFamilyGroup {
762
+ family: string;
763
+ entries: readonly PresetModelListing[];
764
+ }
765
+ declare function listPresetModelGroups(): readonly PresetModelFamilyGroup[];
766
+ declare const BUILTIN_PROVIDER_PRESETS: Readonly<Record<"minimax" | "deepseek" | "kimi" | "zhipu" | "stepfun" | "siliconflow" | "openrouter" | "novita" | "agnes" | "medalsoft", {
463
767
  displayName: string;
464
768
  baseUrl: string;
465
769
  models: ProviderModel[];
466
770
  }>>;
771
+ /**
772
+ * Look up the curated friendly displayName for a model id. Two
773
+ * sources, in priority order:
774
+ *
775
+ * 1. **Explicit map** (`PRESET_MODEL_DISPLAY_NAMES`, derived from
776
+ * `BUILTIN_PROVIDER_PRESETS` at module load). Curated by hand;
777
+ * wins when present so a curated prettier name
778
+ * (e.g. "DeepSeek V4 Flash" for `deepseek-v4-flash`) is
779
+ * always preferred over whatever the detail's prefix would
780
+ * produce.
781
+ * 2. **`MODEL_METADATA.detail` fallback** (2026-08-19 follow-up).
782
+ * For ids that are in `MODEL_METADATA` (have curated pricing
783
+ * / capabilities) but NOT in any vendor preset — e.g.
784
+ * `glm-4.7-flash`, `glm-4.5v`, `glm-5v-turbo`, `glm-4.6v` —
785
+ * derive the display name from the `detail` field by
786
+ * splitting on the first ` — ` and keeping the left half.
787
+ * This restores friendly labels for models the v1 lookup
788
+ * missed (the user-reported case: `glm-4.7-flash` came
789
+ * back from "Fetch from API" without a display name
790
+ * because it was excluded from the Zhipu preset on
791
+ * 2026-08-18, but its detail field already said
792
+ * "GLM-4.7 Flash — 完全免费(200K 上下文)").
793
+ *
794
+ * Returns `undefined` for:
795
+ * • ids that aren't in `BUILTIN_PROVIDER_PRESETS` AND aren't in
796
+ * `MODEL_METADATA` (genuinely custom / aggregator-only
797
+ * models the user added by hand — the consumer falls back
798
+ * to the literal fetched id)
799
+ * • ids in `MODEL_METADATA` whose `detail` is empty /
800
+ * whitespace, or whose detail has no ` — ` boundary and the
801
+ * whole string is the qualifier (defensive — every entry
802
+ * today has a usable detail).
803
+ *
804
+ * Used by `unionProviderModelWithPreset` to fill in the
805
+ * `displayName` field when the API payload omits it — the
806
+ * picker's model name column then renders "DeepSeek V4 Flash"
807
+ * or "GLM-4.7 Flash" instead of the bare id right after the
808
+ * fetch result lands.
809
+ */
810
+ declare function getPresetModelDisplayName(id: string): string | undefined;
467
811
  /**
468
812
  * Look up the default config (displayName / baseUrl / models) for a
469
813
  * named vendor type. Returns `null` for the `-compatible` family —
@@ -1017,6 +1361,8 @@ declare enum WebviewMessageType {
1017
1361
  SetProviderOrder = "setProviderOrder",
1018
1362
  TestProvider = "testProvider",
1019
1363
  ProviderTestResultMessage = "providerTestResult",
1364
+ TestProviderModel = "testProviderModel",
1365
+ ProviderTestModelResultMessage = "providerTestModelResult",
1020
1366
  DefaultProviderChanged = "defaultProviderChanged",
1021
1367
  FetchProviderModels = "fetchProviderModels",
1022
1368
  FetchProviderModelsResult = "fetchProviderModelsResult",
@@ -1391,4 +1737,4 @@ declare function asAbortSignal(input: unknown): AbortSignal | undefined;
1391
1737
  */
1392
1738
  declare function safeJson<T>(text: string, fallback: T): T;
1393
1739
 
1394
- export { type AIModelConfig, type AIModelInfo, type AgentPermissionSummary, type AgentToolPermission, type AgentToolRiskLevel, BUILTIN_PROVIDER_PRESETS, type BalanceEntry, type BridgeLinkMode, type BridgeLinkedSkill, type BridgeRepoEntry, type BridgeRepoSyncPull, type BridgeSkillKind, type BridgeSkillRepoEntry, type BridgeSkillRepoFile, type ByomProviderToggles, ByomSettingsResponse, type ByomSettingsSnapshot, type ByomTogglePayload, CERTIFICATE_BUNDLE_FORMATS, CachedServerUrlResponse, type CachedServerUrlSnapshot, type CertificateBundleEnvironmentSupport, type CertificateBundleFormat, type CertificateBundleFormatDescriptor, type CodingPlanUsage, type CommandPayload, type CuratedModelMetadata, type DeepseekBalanceEntry, type DeepseekUsage, type DownloadCertificateBundleRequest, type DownloadCertificateBundleResponse, GIT_REMOTE_HOST_ALIASES, type GenericBalanceUsage, GetByomSettings, GetCachedServerUrl, GetServerProxyState, GetUtilityModels, type GitHubOrgMembershipCheckResult, type GitHubOrgMembershipStatus, type GitHubUser, type GithubCopilotCliPayload, type HttpRequestPayload, type ILogger, type LinkedSkillPayloadEntry, LogLevel, MODEL_METADATA, type MinimaxUsage, type ModelDetail, type ModelPriceCategory, type ModelPricing, type ModelThinkingSchema, PROVIDER_BASE_URL_PRESETS, PROVIDER_CACHE_CONTROL_METADATA, type ProviderBaseUrlPreset, type ProviderCacheControlMetadata, type ProviderConfig, type ProviderModel, type ProviderMutationPayload, type ProviderTestResult, type ProviderType, type ProviderUsageData, type ProviderUsageKind, type ProviderUsageResult, type ProvidersResponsePayload, type PublicProvider, type ScheduledTask, type ScheduledTaskType, type ScheduledTaskV1, type ScheduledTasksConfig, type ScheduledTasksLogFile, type ServerProxyAllowOverridePayload, type ServerProxySnapshot, ServerProxyStateResponse, type ServerProxySupportMode, type ServerProxyTogglePayload, SetCacheControlEnabled, SetServerProxyAllowOverride, SetServerProxyEnabled, type ShellPayload, type TaskExecutionLog, type TaskExecutionState, type TaskExecutionStatus, type TaskPayload, type TaskRunStatus, type TaskWorkspaceRef, UpdateUtilityModels, type UpdateUtilityModelsPayload, type UsageWindow, type UtilityModelScope, type UtilityModelsEffective, UtilityModelsResponse, type UtilityModelsSnapshot, type UtilityModelsSource, type WebviewInboundMessage, WebviewMessageType, __internal, asAbortSignal, buildGitHubLocalEmail, checkGitHubOrgMembership, createConsoleLogger, currencyForBaseUrl, fetchGitHubUser, getBuiltinProviderPreset, getGitHubOrgMembership, getProviderBaseUrlPresets, isGitHubLocalEmail, isProviderCacheControlAware, isValidCanonicalSlug, lookupModelMetadata, normalizeCanonicalSlug, normalizeErrorForLog, normalizeGitUrl, parsePayload, resolvePrimaryEmail, safeJson };
1740
+ export { type AIModelConfig, type AIModelInfo, type AgentPermissionSummary, type AgentToolPermission, type AgentToolRiskLevel, BUILTIN_PROVIDER_PRESETS, type BalanceEntry, type BridgeLinkMode, type BridgeLinkedSkill, type BridgeRepoEntry, type BridgeRepoSyncPull, type BridgeSkillKind, type BridgeSkillRepoEntry, type BridgeSkillRepoFile, type ByomProviderToggles, ByomSettingsResponse, type ByomSettingsSnapshot, type ByomTogglePayload, CERTIFICATE_BUNDLE_FORMATS, CachedServerUrlResponse, type CachedServerUrlSnapshot, type CertificateBundleEnvironmentSupport, type CertificateBundleFormat, type CertificateBundleFormatDescriptor, type CodingPlanUsage, type CommandPayload, type CuratedModelMetadata, type DeepseekBalanceEntry, type DeepseekUsage, type DownloadCertificateBundleRequest, type DownloadCertificateBundleResponse, GIT_REMOTE_HOST_ALIASES, type GenericBalanceUsage, GetByomSettings, GetCachedServerUrl, GetServerProxyState, GetUtilityModels, type GitHubOrgMembershipCheckResult, type GitHubOrgMembershipStatus, type GitHubUser, type GithubCopilotCliPayload, type HttpRequestPayload, type ILogger, LISTABLE_PRESET_MODELS, type LinkedSkillPayloadEntry, LogLevel, MODEL_METADATA, type MinimaxUsage, type ModelDetail, type ModelPriceCategory, type ModelPricing, type ModelThinkingSchema, NAMESPACE_ALIASES, NAMESPACE_ALIAS_FAMILY, PRESET_MODEL_FAMILIES, PROVIDER_BASE_URL_PRESETS, PROVIDER_CACHE_CONTROL_METADATA, type PresetModelFamilyGroup, type PresetModelListing, type ProviderBaseUrlPreset, type ProviderCacheControlMetadata, type ProviderConfig, type ProviderModel, type ProviderMutationPayload, type ProviderTestResult, type ProviderType, type ProviderUsageData, type ProviderUsageKind, type ProviderUsageResult, type ProviderVisionMode, type ProviderWireProtocol, type ProvidersResponsePayload, type PublicProvider, type ScheduledTask, type ScheduledTaskType, type ScheduledTaskV1, type ScheduledTasksConfig, type ScheduledTasksLogFile, type ServerProxyAllowOverridePayload, type ServerProxySnapshot, ServerProxyStateResponse, type ServerProxySupportMode, type ServerProxyTogglePayload, SetCacheControlEnabled, SetServerProxyAllowOverride, SetServerProxyEnabled, type ShellPayload, type TaskExecutionLog, type TaskExecutionState, type TaskExecutionStatus, type TaskPayload, type TaskRunStatus, type TaskWorkspaceRef, UpdateUtilityModels, type UpdateUtilityModelsPayload, type UsageWindow, type UtilityModelScope, type UtilityModelsEffective, UtilityModelsResponse, type UtilityModelsSnapshot, type UtilityModelsSource, type WebviewInboundMessage, WebviewMessageType, __internal, asAbortSignal, buildGitHubLocalEmail, buildPresetModel, checkGitHubOrgMembership, createConsoleLogger, currencyForBaseUrl, effectiveAdapterType, fetchGitHubUser, getBuiltinProviderPreset, getGitHubOrgMembership, getPresetModelDisplayName, getProviderBaseUrlPresets, isGitHubLocalEmail, isProviderCacheControlAware, isValidCanonicalSlug, listPresetModelGroups, lookupModelMetadata, normalizeCanonicalSlug, normalizeErrorForLog, normalizeGitUrl, parsePayload, protocolForBaseUrl, resolvePrimaryEmail, safeJson, unionProviderModelWithPreset };