fix: 接入 dsflash-go model catalog

This commit is contained in:
Codex
2026-06-08 23:31:33 +08:00
parent 1bd65a4d1a
commit 6dd8c75528
27 changed files with 485 additions and 123 deletions
+6 -5
View File
@@ -9,7 +9,7 @@ export interface BackendProfileSpec {
transport: "stdio";
command: "codex app-server --listen stdio://";
status: "registered";
requiredSecretKeys: ["auth.json", "config.toml"];
requiredSecretKeys: readonly string[];
defaultSecretName: string;
profileIsolation: "profile-scoped-codex-home";
description: string;
@@ -59,7 +59,7 @@ const builtinBackendProfileSpecs: readonly BackendProfileSpec[] = [
transport: "stdio",
command: "codex app-server --listen stdio://",
status: "registered",
requiredSecretKeys: ["auth.json", "config.toml"],
requiredSecretKeys: ["auth.json", "config.toml", "model-catalog.json"],
defaultSecretName: "agentrun-v01-provider-dsflash-go",
profileIsolation: "profile-scoped-codex-home",
description: "DeepSeek V4 Flash profile through OpenCode Zen Go Moon Bridge",
@@ -142,7 +142,7 @@ export function backendCapabilities(): JsonRecord[] {
return builtinBackendProfileSpecs.map(backendCapability);
}
export function backendCapabilitiesSqlValues(profiles?: readonly BackendProfile[]): string {
export function backendCapabilitiesSqlValues(profiles?: readonly BackendProfile[], options: { requiredSecretKeysByProfile?: Record<string, readonly string[]> } = {}): string {
const specs = profiles
? profiles.map((profile) => {
const spec = backendProfileSpec(profile);
@@ -151,13 +151,14 @@ export function backendCapabilitiesSqlValues(profiles?: readonly BackendProfile[
})
: builtinBackendProfileSpecs;
return specs.map((spec) => {
const requiredSecretKeys = options.requiredSecretKeysByProfile?.[spec.profile] ?? spec.requiredSecretKeys;
const capabilities = JSON.stringify({
backendKind: spec.backendKind,
protocol: spec.protocol,
transport: spec.transport,
command: spec.command,
requiredSecretKeys: spec.requiredSecretKeys,
defaultSecretRef: { name: spec.defaultSecretName, keys: spec.requiredSecretKeys },
requiredSecretKeys,
defaultSecretRef: { name: spec.defaultSecretName, keys: requiredSecretKeys },
profileIsolation: spec.profileIsolation,
description: spec.description,
});
+52
View File
@@ -0,0 +1,52 @@
import type { JsonRecord } from "./types.js";
export const dsflashGoModelSlug = "deepseek-v4-flash";
export const dsflashGoModelCatalogFile = "model-catalog.json";
export const dsflashGoRuntimeModelCatalogPath = "/home/agentrun/.codex-dsflash-go/model-catalog.json";
const dsflashGoModelCatalog: JsonRecord = {
models: [
{
slug: dsflashGoModelSlug,
display_name: "DeepSeek V4 Flash via OpenCode Zen Go",
description: "DeepSeek V4 Flash exposed to Codex through OpenCode Zen Go and a Responses-compatible Moon Bridge profile.",
default_reasoning_level: "xhigh",
supported_reasoning_levels: [
{ effort: "low", description: "Fast responses with lighter reasoning" },
{ effort: "medium", description: "Balanced reasoning" },
{ effort: "high", description: "Deep reasoning" },
{ effort: "xhigh", description: "Maximum reasoning" },
],
shell_type: "shell_command",
visibility: "list",
supported_in_api: true,
priority: 0,
additional_speed_tiers: [],
service_tiers: [],
availability_nux: null,
upgrade: null,
base_instructions: "You are Codex, a coding agent based on DeepSeek V4 Flash. You and the user share one workspace, and your job is to collaborate with them until their goal is genuinely handled.",
model_messages: {},
supports_reasoning_summaries: true,
default_reasoning_summary: "auto",
support_verbosity: false,
apply_patch_tool_type: "freeform",
web_search_tool_type: "text_and_image",
truncation_policy: { mode: "tokens", limit: 10000 },
supports_parallel_tool_calls: true,
supports_image_detail_original: false,
context_window: 1_000_000,
max_context_window: 1_000_000,
auto_compact_token_limit: 900_000,
effective_context_window_percent: 95,
experimental_supported_tools: [],
input_modalities: ["text"],
supports_search_tool: false,
},
],
};
export function dsflashGoModelCatalogJson(): string {
return `${JSON.stringify(dsflashGoModelCatalog, null, 2)}\n`;
}
+1
View File
@@ -20,6 +20,7 @@ export type FailureKind =
| "provider-auth-failed"
| "provider-rate-limited"
| "provider-invalid-tool-call"
| "provider-compact-unsupported"
| "provider-unavailable"
| "infra-failed"
| "session-store-evicted"
+6 -8
View File
@@ -185,18 +185,16 @@ export function validateExecutionPolicy(record: JsonRecord): ExecutionPolicy {
if (typeof timeout !== "number" || !Number.isFinite(timeout) || timeout <= 0) throw new AgentRunError("schema-invalid", "executionPolicy.timeoutMs must be a positive number", { httpStatus: 400 });
const secretScope = asRecord(record.secretScope ?? {}, "executionPolicy.secretScope");
if (secretScope.allowCredentialEcho !== undefined && secretScope.allowCredentialEcho !== false) throw new AgentRunError("tenant-policy-denied", "allowCredentialEcho must be false", { httpStatus: 403 });
const providerCredentials = Array.isArray(secretScope.providerCredentials) ? secretScope.providerCredentials : [];
for (const credential of providerCredentials) {
const rawProviderCredentials = Array.isArray(secretScope.providerCredentials) ? secretScope.providerCredentials : [];
const providerCredentials: NonNullable<ExecutionPolicy["secretScope"]["providerCredentials"]> = [];
for (const credential of rawProviderCredentials) {
const item = asRecord(credential, "providerCredential");
const profile = typeof item.profile === "string" ? item.profile.trim() : "";
if (profile.length === 0) throw new AgentRunError("schema-invalid", "provider credential profile is required", { httpStatus: 400 });
if (!isBackendProfile(profile)) throw new AgentRunError("schema-invalid", `provider credential profile ${profile} must be a lowercase slug`, { httpStatus: 400, details: { pattern: backendProfilePatternText } });
const secretRef = asRecord(item.secretRef, "providerCredential.secretRef");
if (typeof secretRef.name !== "string" || secretRef.name.length === 0) throw new AgentRunError("schema-invalid", "provider credential secretRef.name is required", { httpStatus: 400 });
const keys = Array.isArray(secretRef.keys) ? secretRef.keys : [];
for (const requiredKey of backendProfileSpec(profile)?.requiredSecretKeys ?? []) {
if (!keys.includes(requiredKey)) throw new AgentRunError("schema-invalid", `provider credential ${profile} secretRef.keys must include ${requiredKey}`, { httpStatus: 400 });
}
const secretRef = validateSecretRef(asRecord(item.secretRef, "providerCredential.secretRef"));
const keys = [...new Set([...(secretRef.keys ?? []), ...(backendProfileSpec(profile)?.requiredSecretKeys ?? [])])];
providerCredentials.push({ profile, secretRef: { ...secretRef, ...(keys.length > 0 ? { keys } : {}) } });
}
const toolCredentials = validateToolCredentials(secretScope.toolCredentials);
const secretScopeResult: ExecutionPolicy["secretScope"] = { allowCredentialEcho: false };