docs: document models config tests · openclaw/openclaw@c318774
steipete
·
2026-06-05
·
via Recent Commits to openclaw:main
| Original file line number | Diff line number | Diff line change |
|---|
|
| 1 | +// Verifies models.json provider/model merge behavior and secret preservation. |
1 | 2 | import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; |
2 | 3 | import type { ExistingProviderConfig } from "./models-config.merge.js"; |
3 | 4 | import type { ProviderConfig } from "./models-config.providers.secrets.js"; |
@@ -8,6 +9,8 @@ let mergeProviders: typeof import("./models-config.merge.js").mergeProviders;
|
8 | 9 | let mergeWithExistingProviderSecrets: typeof import("./models-config.merge.js").mergeWithExistingProviderSecrets; |
9 | 10 | |
10 | 11 | async function loadMergeModules() { |
| 12 | +// Merge helpers depend on real manifest registry behavior; undo previous |
| 13 | +// mocks before importing the module under test. |
11 | 14 | vi.doUnmock("../plugins/manifest-registry.js"); |
12 | 15 | ({ NON_ENV_SECRETREF_MARKER } = await import("./model-auth-markers.js")); |
13 | 16 | ({ mergeProviderModels, mergeProviders, mergeWithExistingProviderSecrets } = |
@@ -212,6 +215,8 @@ describe("models-config merge helpers", () => {
|
212 | 215 | }); |
213 | 216 | |
214 | 217 | it("preserves non-empty existing apiKey and baseUrl from models.json", () => { |
| 218 | +// Existing local secrets win over regenerated provider config so planning |
| 219 | +// does not overwrite operator-owned credentials. |
215 | 220 | const merged = mergeWithExistingProviderSecrets({ |
216 | 221 | nextProviders: { |
217 | 222 | custom: createConfigProvider(), |
|
| Original file line number | Diff line number | Diff line change |
|---|
|
| 1 | +// Verifies explicit model reasoning overrides survive provider catalog merges. |
1 | 2 | import { describe, expect, it } from "vitest"; |
2 | 3 | import { mergeProviderModels, mergeProviders } from "./models-config.merge.js"; |
3 | 4 | import type { ProviderConfig } from "./models-config.providers.secrets.js"; |
@@ -40,6 +41,8 @@ function createMinimaxModelWithoutReasoning(): NonNullable<ProviderConfig["model
|
40 | 41 | function mergedMinimaxModel( |
41 | 42 | explicitModel: NonNullable<ProviderConfig["models"]>[number], |
42 | 43 | ): NonNullable<ProviderConfig["models"]>[number] | undefined { |
| 44 | +// Built-in MiniMax metadata currently advertises reasoning, while user |
| 45 | +// config may intentionally disable or omit it. |
43 | 46 | return mergeProviderModels( |
44 | 47 | createMinimaxProvider(createMinimaxModel({ reasoning: true })), |
45 | 48 | createMinimaxProvider(explicitModel), |
|
| Original file line number | Diff line number | Diff line change |
|---|
|
| 1 | +// Verifies provider auth aliases share trusted env/profile credentials. |
1 | 2 | import { beforeEach, describe, expect, it, vi } from "vitest"; |
2 | 3 | |
3 | 4 | let createProviderAuthResolver: typeof import("./models-config.providers.secrets.js").createProviderAuthResolver; |
@@ -87,6 +88,8 @@ function expectAuthResult(
|
87 | 88 | profileId?: string; |
88 | 89 | }, |
89 | 90 | ) { |
| 91 | +// Keep auth result assertions focused on persisted marker/source fields |
| 92 | +// rather than the whole resolver result shape. |
90 | 93 | expect(value.apiKey).toBe(expected.apiKey); |
91 | 94 | expect(value.mode).toBe(expected.mode); |
92 | 95 | expect(value.source).toBe(expected.source); |
@@ -151,6 +154,8 @@ describe("provider auth aliases", () => {
|
151 | 154 | }); |
152 | 155 | |
153 | 156 | it("ignores provider auth aliases from untrusted workspace plugins during runtime auth lookup", () => { |
| 157 | +// Workspace plugins cannot alias themselves to bundled provider auth and |
| 158 | +// inherit its credentials at runtime. |
154 | 159 | loadPluginManifestRegistry.mockReturnValue({ |
155 | 160 | plugins: [ |
156 | 161 | { |
|
| Original file line number | Diff line number | Diff line change |
|---|
|
| 1 | +// Verifies persisted provider auth markers preserve credential provenance. |
1 | 2 | import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; |
2 | 3 | import { captureEnv } from "../test-utils/env.js"; |
3 | 4 | |
@@ -53,6 +54,8 @@ beforeEach(() => {
|
53 | 54 | beforeAll(loadProviderAuthModules); |
54 | 55 | |
55 | 56 | function buildPairedApiKeyProviders(apiKey: string) { |
| 57 | +// Several generated provider pairs should carry the same persisted key |
| 58 | +// marker; this helper keeps those expectations identical. |
56 | 59 | return { |
57 | 60 | provider: { apiKey }, |
58 | 61 | paired: { apiKey }, |
@@ -86,6 +89,8 @@ describe("models-config provider auth provenance", () => {
|
86 | 89 | }); |
87 | 90 | |
88 | 91 | it("uses non-env marker for ref-managed profiles even when runtime plaintext is present", () => { |
| 92 | +// Ref-managed secrets may be resolved in memory, but models.json should |
| 93 | +// persist only a non-env marker so plaintext is not written back. |
89 | 94 | const byteplusApiKey = resolveApiKeyFromCredential({ |
90 | 95 | type: "api_key", |
91 | 96 | provider: "byteplus", |
@@ -141,6 +146,8 @@ describe("models-config provider auth provenance", () => {
|
141 | 146 | }); |
142 | 147 | |
143 | 148 | it("resolves plugin-owned synthetic auth through the provider hook", () => { |
| 149 | +// Plugin-owned synthetic auth can provide discovery keys while persisted |
| 150 | +// config still records a non-secret marker. |
144 | 151 | mockedResolveProviderSyntheticAuthWithPlugin.mockReturnValue({ |
145 | 152 | apiKey: "xai-plugin-key", |
146 | 153 | mode: "api-key", |
|
| Original file line number | Diff line number | Diff line change |
|---|
|
| 1 | +// Covers Cloudflare AI Gateway profile provenance and generated provider config. |
1 | 2 | import { describe, expect, it } from "vitest"; |
2 | 3 | import { captureEnv } from "../test-utils/env.js"; |
3 | 4 | import type { ApiKeyCredential } from "./auth-profiles/types.js"; |
@@ -19,6 +20,8 @@ function buildCloudflareAiGatewayCatalogProvider(params: {
|
19 | 20 | | undefined; |
20 | 21 | envApiKey?: string; |
21 | 22 | }) { |
| 23 | +// Cloudflare gateway providers require both account/gateway metadata and an |
| 24 | +// auth marker from the same profile/env source. |
22 | 25 | const apiKey = params.envApiKey?.trim() || resolveApiKeyFromCredential(params.credential)?.apiKey; |
23 | 26 | const accountId = params.credential?.metadata?.accountId?.trim(); |
24 | 27 | const gatewayId = params.credential?.metadata?.gatewayId?.trim(); |
@@ -35,6 +38,8 @@ function buildCloudflareAiGatewayCatalogProvider(params: {
|
35 | 38 | |
36 | 39 | describe("cloudflare-ai-gateway profile provenance", () => { |
37 | 40 | it("prefers env keyRef marker over runtime plaintext for persistence", () => { |
| 41 | +// Env-backed profile refs persist the env var name, not the runtime |
| 42 | +// plaintext value. |
38 | 43 | const envSnapshot = captureEnv(["CLOUDFLARE_AI_GATEWAY_API_KEY"]); |
39 | 44 | delete process.env.CLOUDFLARE_AI_GATEWAY_API_KEY; |
40 | 45 | try { |
|
| Original file line number | Diff line number | Diff line change |
|---|
|
| 1 | +// Verifies provider-owned Google Antigravity and Vertex model id normalization. |
1 | 2 | import { describe, expect, it, vi } from "vitest"; |
2 | 3 | import { normalizeProviderSpecificConfig } from "./models-config.providers.policy.js"; |
3 | 4 | import type { ProviderConfig } from "./models-config.providers.secrets.js"; |
4 | 5 | |
5 | 6 | vi.mock("../plugins/provider-runtime.js", () => { |
6 | 7 | function normalizeGoogleModelIdForProvider(provider: string, modelId: string): string { |
| 8 | +// Mirrors the provider plugin normalization contract used by config |
| 9 | +// planning without importing the bundled plugin runtime. |
7 | 10 | if (provider === "google-antigravity") { |
8 | 11 | return /^(gemini-3(?:[.-]1)?-pro)$/.test(modelId) ? `${modelId}-low` : modelId; |
9 | 12 | } |
@@ -65,6 +68,8 @@ function buildProvider(
|
65 | 68 | function normalizeProviderMap( |
66 | 69 | providers: Record<string, ProviderConfig>, |
67 | 70 | ): Record<string, ProviderConfig> { |
| 71 | +// Normalization should preserve object identity when no provider changed so |
| 72 | +// callers can cheaply detect no-op config planning. |
68 | 73 | let changed = false; |
69 | 74 | const next: Record<string, ProviderConfig> = {}; |
70 | 75 | for (const [providerKey, provider] of Object.entries(providers)) { |
|
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。