Skip to content

Commit 8605076

Browse files
committed
docs: document models config serialization tests
1 parent c1b54fe commit 8605076

6 files changed

Lines changed: 23 additions & 0 deletions

src/agents/models-config.providers.stepfun.test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// Verifies StepFun standard and Step Plan catalog pairing across regions.
12
import { mkdtempSync } from "node:fs";
23
import { tmpdir } from "node:os";
34
import { join } from "node:path";
@@ -37,6 +38,7 @@ function buildStepFunCatalog(params: {
3738
profileId?: string;
3839
env?: NodeJS.ProcessEnv;
3940
}): ModelProviderConfig | null {
41+
// Region can be explicit, profile-tagged, or env-inferred; catalog ids stay paired.
4042
if (!params.apiKey) {
4143
return null;
4244
}
@@ -75,6 +77,7 @@ function inferRegionFromBaseUrl(baseUrl: string | undefined): StepFunRegion | un
7577
}
7678

7779
function inferRegionFromProfileId(profileId: string | undefined): StepFunRegion | undefined {
80+
// Auth profile suffixes are the lightweight region signal for paired providers.
7881
if (!profileId) {
7982
return undefined;
8083
}
@@ -183,6 +186,7 @@ describe("StepFun provider catalog", () => {
183186
}),
184187
};
185188
const pairedStandard = buildStepFunCatalog({
189+
// Paired surfaces should converge on the same regional host family.
186190
surface: "standard",
187191
apiKey: "test-stepfun-key",
188192
explicitBaseUrl: resolveDefaultBaseUrl(

src/agents/models-config.providers.vercel-ai-gateway.test.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
// Verifies Vercel AI Gateway auth marker resolution from env and profiles.
12
import { beforeAll, describe, expect, it, vi } from "vitest";
23

34
let NON_ENV_SECRETREF_MARKER: typeof import("./model-auth-markers.js").NON_ENV_SECRETREF_MARKER;
45
let createProviderAuthResolver: typeof import("./models-config.providers.secrets.js").createProviderAuthResolver;
56

67
async function loadModules() {
8+
// This file needs the real auth resolver after other provider tests install mocks.
79
vi.doUnmock("../plugins/manifest-registry.js");
810
vi.doUnmock("../plugins/provider-runtime.js");
911
vi.doUnmock("../secrets/provider-env-vars.js");
@@ -47,6 +49,7 @@ describe("vercel-ai-gateway provider resolution", () => {
4749
});
4850

4951
const auth = resolveAuth("vercel-ai-gateway");
52+
// Persist the env marker, not the resolved plaintext profile key.
5053
expect(auth.apiKey).toBe("AI_GATEWAY_API_KEY");
5154
expect(auth.mode).toBe("api_key");
5255
expect(auth.source).toBe("profile");

src/agents/models-config.runtime-source-snapshot.test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// Verifies generated models.json preserves source secret markers from runtime snapshots.
12
import { afterAll, afterEach, beforeAll, describe, expect, it, vi } from "vitest";
23
import type { OpenClawConfig } from "../config/types.openclaw.js";
34
import { createFixtureSuite } from "../test-utils/fixture-suite.js";
@@ -90,6 +91,7 @@ function createOpenAiApiKeySourceConfig(): OpenClawConfig {
9091
}
9192

9293
function createOpenAiApiKeyRuntimeConfig(): OpenClawConfig {
94+
// Runtime config simulates already-resolved secrets that must not be persisted.
9395
return {
9496
models: {
9597
providers: {
@@ -224,6 +226,7 @@ async function planGeneratedProviders(params: {
224226
config: OpenClawConfig;
225227
sourceConfigForSecrets: OpenClawConfig;
226228
}) {
229+
// Planner assertions avoid filesystem noise for marker-projection cases.
227230
const plan = await planOpenClawModelsJsonWithDeps(
228231
{
229232
cfg: params.config,
@@ -250,6 +253,7 @@ async function planGeneratedProviders(params: {
250253
function expectOpenAiHeaderMarkers(
251254
providers: Record<string, { headers?: Record<string, string> }>,
252255
) {
256+
// Env header refs keep their id; non-env refs collapse to the shared sentinel.
253257
expect(providers.openai?.headers?.Authorization).toBe(
254258
"secretref-env:OPENAI_HEADER_TOKEN", // pragma: allowlist secret
255259
);

src/agents/models-config.skips-writing-models-json-no-env-token.test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// Verifies models.json generation skips env-gated providers until auth exists.
12
import fs from "node:fs/promises";
23
import path from "node:path";
34
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
@@ -24,6 +25,7 @@ vi.mock("./auth-profiles/external-cli-sync.js", () => ({
2425

2526
vi.mock("./models-config.providers.js", async () => {
2627
function createImplicitProvider(baseUrl: string): ModelsProviderConfig {
28+
// Shared implicit-provider fixture keeps generated-provider expectations compact.
2729
return {
2830
baseUrl,
2931
api: "openai-completions",
@@ -106,6 +108,7 @@ type ParsedProviderConfig = {
106108
async function readGeneratedProviders(
107109
agentDir: string,
108110
): Promise<Record<string, ParsedProviderConfig>> {
111+
// Generated plugin catalogs are separate files but part of the effective provider set.
109112
const raw = await fs.readFile(path.join(agentDir, "models.json"), "utf8");
110113
const parsed = JSON.parse(raw) as { providers?: Record<string, ParsedProviderConfig> };
111114
const providers = { ...parsed.providers };
@@ -142,6 +145,7 @@ async function runEnvProviderCase(params: {
142145
providerKey: "minimax" | "synthetic";
143146
expectedApiKeyRef: string;
144147
}) {
148+
// Mutate one env var at a time so auth-gated provider generation stays isolated.
145149
const previousValue = process.env[params.envVar];
146150
process.env[params.envVar] = params.envValue;
147151
try {

src/agents/models-config.uses-first-github-copilot-profile-env-tokens.test.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// Verifies GitHub Copilot profile token fallback and implicit provider planning.
12
import { describe, expect, it, vi } from "vitest";
23
import {
34
planOpenClawModelsJson,
@@ -251,6 +252,7 @@ describe("models-config", () => {
251252
function createCopilotImplicitResolver(
252253
provider: ProviderConfig,
253254
): ResolveImplicitProvidersForModelsJson {
255+
// Models planner receives implicit Copilot providers from the auth exchange layer.
254256
return async () => ({ "github-copilot": provider });
255257
}
256258

@@ -272,6 +274,7 @@ async function planCopilotWithImplicitProvider(params: { provider: ProviderConfi
272274
function expectCopilotProviderFromPlan(
273275
plan: Awaited<ReturnType<typeof planCopilotWithImplicitProvider>>,
274276
) {
277+
// Keep assertions on the emitted provider payload, not planner implementation details.
275278
expect(plan.action).toBe("write");
276279
const parsed =
277280
plan.action === "write"

src/agents/models-config.write-serialization.test.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// Verifies models.json writes, plugin catalog writes, and ready-cache serialization.
12
import fs from "node:fs/promises";
23
import path from "node:path";
34
import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
@@ -29,6 +30,7 @@ let clearCurrentPluginMetadataSnapshot: typeof import("../plugins/current-plugin
2930
let setCurrentPluginMetadataSnapshot: typeof import("../plugins/current-plugin-metadata-snapshot.js").setCurrentPluginMetadataSnapshot;
3031

3132
function createPluginMetadataSnapshot(workspaceDir: string): PluginMetadataSnapshot {
33+
// Minimal process snapshot used to prove when metadata may be reused.
3234
const policyHash = resolveInstalledPluginIndexPolicyHash({});
3335
return {
3436
policyHash,
@@ -72,6 +74,7 @@ function createPluginMetadataSnapshot(workspaceDir: string): PluginMetadataSnaps
7274
}
7375

7476
async function expectMissingPath(operation: Promise<unknown>) {
77+
// Filesystem deletion assertions should fail on the errno, not path text.
7578
let error: NodeJS.ErrnoException | undefined;
7679
try {
7780
await operation;
@@ -87,6 +90,7 @@ function planParamsAt(callIndex: number): {
8790
providerDiscoveryTimeoutMs?: number;
8891
workspaceDir?: string;
8992
} {
93+
// Planner call shape is the contract between ensureOpenClawModelsJson and planning.
9094
const call = planOpenClawModelsJsonMock.mock.calls[callIndex];
9195
if (!call) {
9296
throw new Error(`expected models planner call #${callIndex + 1}`);
@@ -397,6 +401,7 @@ describe("models-config write serialization", () => {
397401
let modelsWriteCount = 0;
398402
writePrivateStoreTextWriteMock.mockImplementation(
399403
async (params: { filePath: string; rootDir: string; content: string | Uint8Array }) => {
404+
// Hold both writes at the store boundary to prove the outer serializer works.
400405
const isModelsWrite = path.basename(params.filePath) === "models.json";
401406
if (isModelsWrite) {
402407
modelsWriteCount += 1;

0 commit comments

Comments
 (0)