
























@@ -1,5 +1,6 @@
11import type { ModelDefinitionConfig } from "openclaw/plugin-sdk/provider-model-shared";
22import { createSubsystemLogger } from "openclaw/plugin-sdk/runtime-env";
3+import { fetchWithSsrFGuard } from "openclaw/plugin-sdk/ssrf-runtime";
34import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
4556const log = createSubsystemLogger("kilocode-models");
@@ -135,49 +136,56 @@ export async function discoverKilocodeModels(): Promise<ModelDefinitionConfig[]>
135136}
136137137138try {
138-const response = await fetch(KILOCODE_MODELS_URL, {
139-headers: { Accept: "application/json" },
140-signal: AbortSignal.timeout(DISCOVERY_TIMEOUT_MS),
139+const { response, release } = await fetchWithSsrFGuard({
140+url: KILOCODE_MODELS_URL,
141+init: {
142+headers: { Accept: "application/json" },
143+},
144+timeoutMs: DISCOVERY_TIMEOUT_MS,
145+auditContext: "kilocode.model_discovery",
141146});
142-143-if (!response.ok) {
144-log.warn(`Failed to discover models: HTTP ${response.status}, using static catalog`);
145-return buildStaticCatalog();
146-}
147-148-const data = (await response.json()) as GatewayModelsResponse;
149-if (!Array.isArray(data.data) || data.data.length === 0) {
150-log.warn("No models found from gateway API, using static catalog");
151-return buildStaticCatalog();
152-}
153-154-const models: ModelDefinitionConfig[] = [];
155-const discoveredIds = new Set<string>();
156-157-for (const entry of data.data) {
158-if (!entry || typeof entry !== "object") {
159-continue;
147+try {
148+if (!response.ok) {
149+log.warn(`Failed to discover models: HTTP ${response.status}, using static catalog`);
150+return buildStaticCatalog();
160151}
161-const id = typeof entry.id === "string" ? entry.id.trim() : "";
162-if (!id || discoveredIds.has(id)) {
163-continue;
152+153+const data = (await response.json()) as GatewayModelsResponse;
154+if (!Array.isArray(data.data) || data.data.length === 0) {
155+log.warn("No models found from gateway API, using static catalog");
156+return buildStaticCatalog();
164157}
165-try {
166-models.push(toModelDefinition(entry));
167-discoveredIds.add(id);
168-} catch (e) {
169-log.warn(`Skipping malformed model entry "${id}": ${String(e)}`);
158+159+const models: ModelDefinitionConfig[] = [];
160+const discoveredIds = new Set<string>();
161+162+for (const entry of data.data) {
163+if (!entry || typeof entry !== "object") {
164+continue;
165+}
166+const id = typeof entry.id === "string" ? entry.id.trim() : "";
167+if (!id || discoveredIds.has(id)) {
168+continue;
169+}
170+try {
171+models.push(toModelDefinition(entry));
172+discoveredIds.add(id);
173+} catch (e) {
174+log.warn(`Skipping malformed model entry "${id}": ${String(e)}`);
175+}
170176}
171-}
172177173-const staticModels = buildStaticCatalog();
174-for (const staticModel of staticModels) {
175-if (!discoveredIds.has(staticModel.id)) {
176-models.unshift(staticModel);
178+const staticModels = buildStaticCatalog();
179+for (const staticModel of staticModels) {
180+if (!discoveredIds.has(staticModel.id)) {
181+models.unshift(staticModel);
182+}
177183}
178-}
179184180-return models.length > 0 ? models : buildStaticCatalog();
185+return models.length > 0 ? models : buildStaticCatalog();
186+} finally {
187+await release();
188+}
181189} catch (error) {
182190log.warn(`Discovery failed: ${String(error)}, using static catalog`);
183191return buildStaticCatalog();
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。