惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
T
Troy Hunt's Blog
Scott Helme
Scott Helme
T
Threat Research - Cisco Blogs
T
Tenable Blog
L
LINUX DO - 热门话题
V
Visual Studio Blog
I
Intezer
Blog — PlanetScale
Blog — PlanetScale
Cisco Talos Blog
Cisco Talos Blog
A
Arctic Wolf
C
Cyber Attacks, Cyber Crime and Cyber Security
F
Fortinet All Blogs
aimingoo的专栏
aimingoo的专栏
Know Your Adversary
Know Your Adversary
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
N
Netflix TechBlog - Medium
SecWiki News
SecWiki News
I
InfoQ
Microsoft Security Blog
Microsoft Security Blog
Project Zero
Project Zero
W
WeLiveSecurity
Microsoft Azure Blog
Microsoft Azure Blog
A
About on SuperTechFans
Recorded Future
Recorded Future
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Vercel News
Vercel News
S
Securelist
Spread Privacy
Spread Privacy
L
LangChain Blog
云风的 BLOG
云风的 BLOG
G
Google Developers Blog
MongoDB | Blog
MongoDB | Blog
Google DeepMind News
Google DeepMind News
Recent Commits to openclaw:main
Recent Commits to openclaw:main
D
Darknet – Hacking Tools, Hacker News & Cyber Security
C
CERT Recently Published Vulnerability Notes
罗磊的独立博客
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
The Last Watchdog
The Last Watchdog
Attack and Defense Labs
Attack and Defense Labs
博客园 - 司徒正美
Help Net Security
Help Net Security
L
Lohrmann on Cybersecurity
人人都是产品经理
人人都是产品经理
Forbes - Security
Forbes - Security
Hacker News - Newest:
Hacker News - Newest: "LLM"
PCI Perspectives
PCI Perspectives
博客园 - 【当耐特】
T
Tor Project blog

Recent Commits to openclaw:main

test: merge chat side-result checks · openclaw/openclaw@ddd2c2a test: merge cron history checks · openclaw/openclaw@f7eb746 test: merge responsive navigation shell checks · openclaw/openclaw@c2e4b47 docs(changelog): add codex oauth fixes · openclaw/openclaw@628e6cd test: merge navigation routing cases · openclaw/openclaw@5d8cecb Tests: mock channel registry bundled fallback · openclaw/openclaw@2b08233 Secrets: avoid broad web search discovery for single plugin config · openclaw/openclaw@a464f59 test: merge config view browser checks · openclaw/openclaw@20cf511 fix(status): align oauth health with runtime · openclaw/openclaw@eed7116 feat: add macOS screen snapshots for monitor preview (#67954) thanks … · openclaw/openclaw@f377db1 fix: report shared auth scopes in hello-ok (#67810) thanks @BunsDev · openclaw/openclaw@0b6c39b Auto-reply: avoid eager bundled route fallback · openclaw/openclaw@3ea1bf4 Tests: narrow session binding contract setup · openclaw/openclaw@54e4e16 fix(macOS): enable undo/redo in webchat composer text input (#34962) · openclaw/openclaw@00951dc Tests: speed up channel setup promotion · openclaw/openclaw@82b529a Docs: refresh agent instructions · openclaw/openclaw@5775fe2 fix(auth): serialize OAuth refresh across agents to fix #26322 (#67876) · openclaw/openclaw@8e79080 test: allow ollama public surface boundary test · openclaw/openclaw@7d4f1a6 Docs: add test performance guardrails · openclaw/openclaw@89706d3 Tests: restore context-engine usage proof · openclaw/openclaw@e4c4f95 Tests: slim context engine runtime coverage · openclaw/openclaw@74c198f ci: retry failed custom checkouts · openclaw/openclaw@0ee5baf test: trim duplicate provider auth onboarding cases · openclaw/openclaw@1ffc02e matrix: fix sessions_spawn --thread subagent session spawning (#67643) · openclaw/openclaw@1ce2596 test: reduce auth choice fixture churn · openclaw/openclaw@857b9cd test: mock health status config boundaries · openclaw/openclaw@9d5ab4a test: mock onboard config io boundary · openclaw/openclaw@299694d test: mock legacy state plugin boundaries · openclaw/openclaw@2713089 test: mock channel install boundaries · openclaw/openclaw@b945248 test: mock doctor preview channel boundaries · openclaw/openclaw@b1a3ad4 test: trim doctor command hotspots · openclaw/openclaw@c66f16a test: isolate agent auth and spawn hotspots · openclaw/openclaw@9285935 test: stabilize MCP startup disposal race · openclaw/openclaw@dd9d2eb test: merge browser contract server suites · openclaw/openclaw@5817a76 test: narrow ollama provider discovery setup · openclaw/openclaw@a0d9598 build: declare qa-lab aimock runtime dependency · openclaw/openclaw@24431e5 test: speed up safe-bins exec harness · openclaw/openclaw@ee856ab test: preserve tool helpers in embedded runner mocks · openclaw/openclaw@acd86a0 refactor: move memory embeddings into provider plugins · openclaw/openclaw@77e6e4c test: reuse system-run temp fixtures · openclaw/openclaw@7e9ff0f test: trim hotspot wait overhead · openclaw/openclaw@12a59b0 Check: avoid duplicate boundary prep · openclaw/openclaw@baf11b8 test: reduce hotspot fixture overhead · openclaw/openclaw@3a59edd feat(ui): overhaul settings and slash command UX (#67819) thanks @Bun… · openclaw/openclaw@2cfb660 QA Matrix: exit cleanly on failure · openclaw/openclaw@42805d2 QA Matrix: isolate scenario coverage · openclaw/openclaw@7e659e1 Matrix: refresh crypto bootstrap state · openclaw/openclaw@94081d8 QA Lab: add provider registry · openclaw/openclaw@bb7e982 Matrix: add plugin changelog · openclaw/openclaw@4acab55 test: trim more hotspot overhead · openclaw/openclaw@f485311 test: trim remaining hotspot tests · openclaw/openclaw@6ba8626 test: narrow hotspot mocks · openclaw/openclaw@dbc8179 test: isolate gemini embedding request helpers · openclaw/openclaw@cd330f5 test: trim memory and mcp hotspots · openclaw/openclaw@fd48dfa test: slim provider registry mocks · openclaw/openclaw@2e08c77 test: harden Parallels update smoke · openclaw/openclaw@1a98090 feat: default Anthropic to Opus 4.7 · openclaw/openclaw@628b454 fix: harden node-host shell payload mutability checks · openclaw/openclaw@75c551e fix: land node-host approval binding for native binaries (#66731) (th… · openclaw/openclaw@29919bb CI: add daily schedule to CodeQL workflow (#67645) · openclaw/openclaw@69d25f5 fix(gateway): capture config hash after plugin auto-enable to prevent… · openclaw/openclaw@8c11210 fix: repair sanitized replay tool results before send (#67620) (thank… · openclaw/openclaw@c3c7a99 fix: restrict HTML timeout short-circuit to transient statuses · openclaw/openclaw@de129a6 fix: keep TUI watchdog bound to active run (#67401) (thanks @xantorres) · openclaw/openclaw@3525273 Gateway/skills: dedupe skills prefix-match + drop dead fallback on log · openclaw/openclaw@d7f489f Extensions/lmstudio: back off inference preload after consecutive fai… · openclaw/openclaw@b555214 TUI/streaming: add watchdog that resets the activity indicator after … · openclaw/openclaw@f44ab20 Agents/tool-loop: enable unknown-tool stream guard by default · openclaw/openclaw@36ed367 Gateway/skills: invalidate session skills snapshot on config write · openclaw/openclaw@b23d59a fix: classify HTML provider error pages correctly (#67642) (thanks @s… · openclaw/openclaw@e588e90 fix(skills): remove unused model-usage import (#67641) · openclaw/openclaw@55f05df docs(changelog): credit codex fix superseded PRs · openclaw/openclaw@e485f24 fix(openai-codex): normalize stale transport metadata in resolution a… · openclaw/openclaw@90801ba CI: pin Docker-related GitHub Actions (#67632) · openclaw/openclaw@f697b01 Android: modernize WebView and discovery API usage (#67627) · openclaw/openclaw@44a6e50 fix(deps): bump hono to 4.12.14 and @hono/node-server to 1.19.14 (GHS… · openclaw/openclaw@fbccc18 fix(deps): bump dompurify to 3.4.0 (#67614) · openclaw/openclaw@2c2dc00 CI: add explicit permissions to all workflow jobs (fixes code-scannin… · openclaw/openclaw@01b7516 fix: register bundled TTS providers and route overrides correctly (#6… · openclaw/openclaw@6ea3cdd fix: align host tilde paths with OS home (#62804) (thanks @stainlu) · openclaw/openclaw@ecfaf64 fix: flush creds queue before reconnect socket open (#67464) (thanks … · openclaw/openclaw@405c63f fix: strip standalone <function> tool call tags from visible text (#6… · openclaw/openclaw@78df859 fix(agents): preserve cli session metadata before transcript persist … · openclaw/openclaw@898fd04 docs(changelog): move cli transcript entry · openclaw/openclaw@c1817c6 fix(agents): normalize cli transcript api field · openclaw/openclaw@3a3fae0 docs(changelog): note cli transcript persistence · openclaw/openclaw@6c343f1 fix(agents): persist cli transcript turns · openclaw/openclaw@b8ef507 fix(msteams): harden security-sensitive flows (#65841) · openclaw/openclaw@c56b56e [Dashboard] Fix exec approval modal overflow for long command content… · openclaw/openclaw@053c5b0 Docs: remove QA changelog entry · openclaw/openclaw@7fd5771 QA: fix private runtime source loading (#67428) · openclaw/openclaw@d5933af docs(gateway): correct protocol.md schema path, hello-ok example, aut… · openclaw/openclaw@489404d CI: pin Node 22 runners to 22.18.0 · openclaw/openclaw@4ffa621 models.authStatus: normalize provider ids + tighten env-backed escape… · openclaw/openclaw@f2fdb9d Update CHANGELOG.md · openclaw/openclaw@7694a92 test(parallels): clean up npm update guard jobs · openclaw/openclaw@045ea7b Plugins: prefer scanDir override paths · openclaw/openclaw@b2974da fix(dreaming): default storage.mode to "separate" so phase blocks sto… · openclaw/openclaw@8c392f0 fix(memory-core): skip dreaming transcript ingestion via session stor… · openclaw/openclaw@a1b01f0 fix: dedupe replayed exec.finished node events (#67281) · openclaw/openclaw@5dcf526
fix: clamp xAI live gateway thinking · openclaw/openclaw@e9987ff
steipete · 2026-05-06 · via Recent Commits to openclaw:main

@@ -3,7 +3,12 @@ import fs from "node:fs/promises";

33

import { createServer } from "node:net";

44

import os from "node:os";

55

import path from "node:path";

6-

import type { Api, Model } from "@mariozechner/pi-ai";

6+

import {

7+

clampThinkingLevel,

8+

type Api,

9+

type Model,

10+

type ModelThinkingLevel,

11+

} from "@mariozechner/pi-ai";

712

import { afterEach, describe, expect, it } from "vitest";

813

import { resolveAgentWorkspaceDir, resolveDefaultAgentDir } from "../agents/agent-scope.js";

914

import { ensureAuthProfileStore, saveAuthProfileStore } from "../agents/auth-profiles/store.js";

@@ -36,6 +41,7 @@ import { clearRuntimeConfigSnapshot, getRuntimeConfig } from "../config/io.js";

3641

import type { ModelsConfig, ModelProviderConfig, OpenClawConfig } from "../config/types.js";

3742

import { isTruthyEnvValue } from "../infra/env.js";

3843

import { normalizeGoogleModelId } from "../plugin-sdk/google-model-id.js";

44+

import { resolveProviderThinkingProfile } from "../plugins/provider-runtime.js";

3945

import { DEFAULT_AGENT_ID } from "../routing/session-key.js";

4046

import { stripAssistantInternalScaffolding } from "../shared/text/assistant-visible-text.js";

4147

import { GATEWAY_CLIENT_MODES, GATEWAY_CLIENT_NAMES } from "../utils/message-channel.js";

@@ -587,6 +593,95 @@ describe("resolveGatewayLiveMaxModels", () => {

587593

});

588594

});

589595596+

function createGatewayLiveTestModel(provider: string, id: string): Model<Api> {

597+

return {

598+

provider,

599+

id,

600+

name: id,

601+

api: "openai-responses",

602+

input: ["text"],

603+

cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },

604+

contextWindow: 1_000,

605+

maxTokens: 100,

606+

reasoning: false,

607+

} as Model<Api>;

608+

}

609+610+

describe("resolveExplicitLiveModelCandidates", () => {

611+

it("uses targeted registry lookup for explicit provider/model filters", () => {

612+

const model = createGatewayLiveTestModel("xai", "grok-4.3");

613+

const matcher = createLiveTargetMatcher({

614+

providerFilter: new Set(["xai"]),

615+

modelFilter: new Set(["xai/grok-4.3"]),

616+

env: {},

617+

});

618+

const candidates = resolveExplicitLiveModelCandidates({

619+

modelRegistry: {

620+

find(provider, modelId) {

621+

expect(provider).toBe("xai");

622+

expect(modelId).toBe("grok-4.3");

623+

return model;

624+

},

625+

getAll() {

626+

throw new Error("explicit model lookup should not enumerate registry");

627+

},

628+

},

629+

modelFilter: new Set(["xai/grok-4.3"]),

630+

providerFilter: new Set(["xai"]),

631+

targetMatcher: matcher,

632+

});

633+634+

expect(candidates).toEqual([model]);

635+

});

636+637+

it("falls back to enumeration for ambiguous model-only filters", () => {

638+

const matcher = createLiveTargetMatcher({

639+

providerFilter: null,

640+

modelFilter: new Set(["grok-4.3"]),

641+

env: {},

642+

});

643+644+

expect(

645+

resolveExplicitLiveModelCandidates({

646+

modelRegistry: {

647+

find() {

648+

throw new Error("ambiguous model-only lookup should not use direct find");

649+

},

650+

getAll() {

651+

return [];

652+

},

653+

},

654+

modelFilter: new Set(["grok-4.3"]),

655+

providerFilter: null,

656+

targetMatcher: matcher,

657+

}),

658+

).toBeNull();

659+

});

660+

});

661+662+

describe("resolveGatewayLiveModelThinkingLevel", () => {

663+

it("clamps requested thinking to levels supported by model metadata", () => {

664+

expect(

665+

resolveGatewayLiveModelThinkingLevel({

666+

cfg: {},

667+

model: {

668+

...createGatewayLiveTestModel("xai", "grok-4.3"),

669+

reasoning: true,

670+

thinkingLevelMap: {

671+

off: null,

672+

minimal: null,

673+

low: null,

674+

medium: null,

675+

high: null,

676+

xhigh: null,

677+

},

678+

},

679+

requestedLevel: "low",

680+

}),

681+

).toBe("off");

682+

});

683+

});

684+590685

function isGoogleModelNotFoundText(text: string): boolean {

591686

const trimmed = text.trim();

592687

if (!trimmed) {

@@ -1281,6 +1376,101 @@ type GatewayModelSuiteParams = {

12811376

providerOverrides?: Record<string, ModelProviderConfig>;

12821377

};

128313781379+

type LiveModelRegistry = {

1380+

find(provider: string, modelId: string): Model<Api> | null | undefined;

1381+

getAll(): Array<Model<Api>>;

1382+

};

1383+1384+

function parseExplicitLiveModelRef(

1385+

raw: string,

1386+

providerFilter: Set<string> | null,

1387+

): { provider: string; modelId: string } | null {

1388+

const trimmed = raw.trim();

1389+

if (!trimmed) {

1390+

return null;

1391+

}

1392+

const slash = trimmed.indexOf("/");

1393+

if (slash !== -1) {

1394+

const provider = normalizeProviderId(trimmed.slice(0, slash));

1395+

const modelId = trimmed.slice(slash + 1).trim();

1396+

return provider && modelId ? { provider, modelId } : null;

1397+

}

1398+

if (!providerFilter || providerFilter.size !== 1) {

1399+

return null;

1400+

}

1401+

const [provider] = [...providerFilter];

1402+

return provider ? { provider: normalizeProviderId(provider), modelId: trimmed } : null;

1403+

}

1404+1405+

function resolveExplicitLiveModelCandidates(params: {

1406+

modelRegistry: LiveModelRegistry;

1407+

modelFilter: Set<string> | null;

1408+

providerFilter: Set<string> | null;

1409+

targetMatcher: ReturnType<typeof createLiveTargetMatcher>;

1410+

}): Array<Model<Api>> | null {

1411+

if (!params.modelFilter || params.modelFilter.size === 0) {

1412+

return null;

1413+

}

1414+

const candidates: Array<Model<Api>> = [];

1415+

const seen = new Set<string>();

1416+

for (const raw of params.modelFilter) {

1417+

const ref = parseExplicitLiveModelRef(raw, params.providerFilter);

1418+

if (!ref) {

1419+

return null;

1420+

}

1421+

const model = params.modelRegistry.find(ref.provider, ref.modelId);

1422+

if (!model) {

1423+

return null;

1424+

}

1425+

if (

1426+

!params.targetMatcher.matchesProvider(model.provider) ||

1427+

!params.targetMatcher.matchesModel(model.provider, model.id)

1428+

) {

1429+

return null;

1430+

}

1431+

const key = `${normalizeProviderId(model.provider)}/${model.id.toLowerCase()}`;

1432+

if (!seen.has(key)) {

1433+

seen.add(key);

1434+

candidates.push(model);

1435+

}

1436+

}

1437+

return candidates;

1438+

}

1439+1440+

function resolveGatewayLiveModelThinkingLevel(params: {

1441+

cfg: OpenClawConfig;

1442+

model: Model<Api>;

1443+

requestedLevel: string;

1444+

}): string {

1445+

const { model, requestedLevel } = params;

1446+

const normalized = requestedLevel.trim() as ModelThinkingLevel;

1447+

if (!["off", "minimal", "low", "medium", "high", "xhigh"].includes(normalized)) {

1448+

return requestedLevel;

1449+

}

1450+

const profile = resolveProviderThinkingProfile({

1451+

provider: model.provider,

1452+

config: params.cfg,

1453+

context: {

1454+

provider: model.provider,

1455+

modelId: model.id,

1456+

reasoning: model.reasoning,

1457+

},

1458+

});

1459+

if (profile) {

1460+

const levelIds = profile.levels.map((level) => level.id);

1461+

if (levelIds.includes(normalized)) {

1462+

return normalized;

1463+

}

1464+

if (profile.defaultLevel) {

1465+

return profile.defaultLevel;

1466+

}

1467+

if (levelIds.length === 1) {

1468+

return levelIds[0] ?? requestedLevel;

1469+

}

1470+

}

1471+

return clampThinkingLevel(model, normalized);

1472+

}

1473+12841474

function buildLiveGatewayConfig(params: {

12851475

cfg: OpenClawConfig;

12861476

candidates: Array<Model<Api>>;

@@ -1549,6 +1739,14 @@ async function runGatewayModelSuite(params: GatewayModelSuiteParams) {

15491739

for (const [index, model] of params.candidates.entries()) {

15501740

const modelKey = `${model.provider}/${model.id}`;

15511741

const progressLabel = `[${params.label}] ${index + 1}/${total} ${modelKey}`;

1742+

const thinkingLevel = resolveGatewayLiveModelThinkingLevel({

1743+

cfg: params.cfg,

1744+

model,

1745+

requestedLevel: params.thinkingLevel,

1746+

});

1747+

if (thinkingLevel !== params.thinkingLevel) {

1748+

logProgress(`${progressLabel}: thinking ${params.thinkingLevel} -> ${thinkingLevel}`);

1749+

}

15521750

// Use a separate session per model: live providers can finalize late after

15531751

// skip/retry paths, and a reset on a reused key does not isolate those

15541752

// delayed transcript writes from the next model probe.

@@ -1589,7 +1787,7 @@ async function runGatewayModelSuite(params: GatewayModelSuiteParams) {

15891787

modelKey,

15901788

message:

15911789

"Explain in 2-3 sentences how the JavaScript event loop handles microtasks vs macrotasks. Must mention both words: microtask and macrotask.",

1592-

thinkingLevel: params.thinkingLevel,

1790+

thinkingLevel,

15931791

context: `${progressLabel}: prompt`,

15941792

});

15951793

if (!text) {

@@ -1601,7 +1799,7 @@ async function runGatewayModelSuite(params: GatewayModelSuiteParams) {

16011799

modelKey,

16021800

message:

16031801

"Explain in 2-3 sentences how the JavaScript event loop handles microtasks vs macrotasks. Must mention both words: microtask and macrotask.",

1604-

thinkingLevel: params.thinkingLevel,

1802+

thinkingLevel,

16051803

context: `${progressLabel}: prompt-retry`,

16061804

});

16071805

}

@@ -1650,7 +1848,7 @@ async function runGatewayModelSuite(params: GatewayModelSuiteParams) {

16501848

modelKey,

16511849

message:

16521850

"Answer in exactly two short sentences. Include the exact lowercase words microtask and macrotask. No bullets.",

1653-

thinkingLevel: params.thinkingLevel,

1851+

thinkingLevel,

16541852

context: `${progressLabel}: prompt-keyword-retry`,

16551853

});

16561854

if (retryText) {

@@ -1697,7 +1895,7 @@ async function runGatewayModelSuite(params: GatewayModelSuiteParams) {

16971895

: "OpenClaw live tool probe (local, safe): " +

16981896

`use the tool named \`read\` (or \`Read\`) with JSON arguments {"path":"${toolProbePath}"}. ` +

16991897

"Then reply with the two nonce values you read (include both).",

1700-

thinkingLevel: params.thinkingLevel,

1898+

thinkingLevel,

17011899

context: `${progressLabel}: tool-read`,

17021900

});

17031901

if (

@@ -1768,7 +1966,7 @@ async function runGatewayModelSuite(params: GatewayModelSuiteParams) {

17681966

`mkdir -p "${tempDir}" && printf '%s' '${nonceC}' > "${toolWritePath}". ` +

17691967

`Then use the tool named \`read\` (or \`Read\`) with JSON arguments {"path":"${toolWritePath}"}. ` +

17701968

"Finally reply including the nonce text you read back.",

1771-

thinkingLevel: params.thinkingLevel,

1969+

thinkingLevel,

17721970

context: `${progressLabel}: tool-exec`,

17731971

});

17741972

if (

@@ -1836,7 +2034,7 @@ async function runGatewayModelSuite(params: GatewayModelSuiteParams) {

18362034

content: imageBase64,

18372035

},

18382036

],

1839-

thinkingLevel: params.thinkingLevel,

2037+

thinkingLevel,

18402038

context: `${progressLabel}: image`,

18412039

});

18422040

if (

@@ -1883,7 +2081,7 @@ async function runGatewayModelSuite(params: GatewayModelSuiteParams) {

18832081

idempotencyKey: `idem-${runId2}-1`,

18842082

modelKey,

18852083

message: `Call the tool named \`read\` (or \`Read\`) on "${toolProbePath}". Do not write any other text.`,

1886-

thinkingLevel: params.thinkingLevel,

2084+

thinkingLevel,

18872085

context: `${progressLabel}: tool-only-regression-first`,

18882086

});

18892087

assertNoReasoningTags({

@@ -1899,7 +2097,7 @@ async function runGatewayModelSuite(params: GatewayModelSuiteParams) {

18992097

idempotencyKey: `idem-${runId2}-2`,

19002098

modelKey,

19012099

message: `Now answer: what are the values of nonceA and nonceB in "${toolProbePath}"? Reply with exactly: ${nonceA} ${nonceB}.`,

1902-

thinkingLevel: params.thinkingLevel,

2100+

thinkingLevel,

19032101

context: `${progressLabel}: tool-only-regression-second`,

19042102

});

19052103

assertNoReasoningTags({

@@ -1919,7 +2117,7 @@ async function runGatewayModelSuite(params: GatewayModelSuiteParams) {

19192117

sessionKey,

19202118

modelKey,

19212119

label: progressLabel,

1922-

thinkingLevel: params.thinkingLevel,

2120+

thinkingLevel,

19232121

});

19242122

}

19252123

return "done";

@@ -2171,7 +2369,6 @@ describeLive("gateway live (dev agent, profile keys)", () => {

21712369

const agentDir = resolveDefaultAgentDir(cfg);

21722370

const authStorage = discoverAuthStorage(agentDir);

21732371

const modelRegistry = discoverModels(authStorage, agentDir);

2174-

const all = modelRegistry.getAll();

2175237221762373

const rawModels = process.env.OPENCLAW_LIVE_GATEWAY_MODELS?.trim();

21772374

const useModern = !rawModels || rawModels === "modern" || rawModels === "all";

@@ -2184,18 +2381,29 @@ describeLive("gateway live (dev agent, profile keys)", () => {

21842381

config: cfg,

21852382

env: process.env,

21862383

});

2187-

const wanted = filter

2188-

? all.filter((m) => targetMatcher.matchesModel(m.provider, m.id))

2189-

: all.filter(

2190-

(m) =>

2191-

!shouldExcludeProviderFromDefaultHighSignalLiveSweep({

2192-

provider: m.provider,

2193-

useExplicitModels: useExplicit,

2194-

providerFilter: PROVIDERS,

2195-

config: cfg,

2196-

env: process.env,

2197-

}) && isHighSignalLiveModelRef({ provider: m.provider, id: m.id }),

2198-

);

2384+

let wanted = useExplicit

2385+

? resolveExplicitLiveModelCandidates({

2386+

modelRegistry,

2387+

modelFilter: filter,

2388+

providerFilter: PROVIDERS,

2389+

targetMatcher,

2390+

})

2391+

: null;

2392+

if (!wanted) {

2393+

const all = modelRegistry.getAll();

2394+

wanted = filter

2395+

? all.filter((m) => targetMatcher.matchesModel(m.provider, m.id))

2396+

: all.filter(

2397+

(m) =>

2398+

!shouldExcludeProviderFromDefaultHighSignalLiveSweep({

2399+

provider: m.provider,

2400+

useExplicitModels: useExplicit,

2401+

providerFilter: PROVIDERS,

2402+

config: cfg,

2403+

env: process.env,

2404+

}) && isHighSignalLiveModelRef({ provider: m.provider, id: m.id }),

2405+

);

2406+

}

2199240722002408

const candidates: Array<Model<Api>> = [];

22012409

const skipped: Array<{ model: string; error: string }> = [];