fix: route deepseek through opencode

This commit is contained in:
Codex
2026-05-21 10:30:17 +00:00
parent 27d0ddff51
commit 8b8b74e953
14 changed files with 133 additions and 43 deletions
+31 -10
View File
@@ -3,6 +3,7 @@ import { runCommand } from "./command";
import { type UniDeskConfig, repoRoot, rootPath } from "./config";
import { coreInternalFetch } from "./microservices";
import { previewJson } from "./preview";
import { codeAgentPortForModel, codeModelPorts as sharedCodeModelPorts, defaultCodeModels as sharedDefaultCodeModels, opencodeModels as sharedOpencodeModels } from "../../src/components/microservices/code-queue/src/code-agent/common";
const defaultToolLimit = 8;
const defaultTraceLimit = 80;
@@ -60,7 +61,7 @@ interface CodexSubmitOptions {
dryRun: boolean;
}
type SubmitRoute = "minimax-opencode" | "deepseek-codex" | "gpt-5.5-codex" | "commander-human-only";
type SubmitRoute = "minimax-opencode" | "deepseek-opencode" | "gpt-5.5-codex" | "commander-human-only";
type SubmitRouteSignalSeverity = "info" | "warning" | "block";
interface SubmitRouteSignal {
@@ -626,10 +627,25 @@ function normalizeSubmitModel(value: string | null | undefined): string {
return raw;
}
function submitModelRegistry(models: string[] = sharedDefaultCodeModels): {
codeModels: string[];
codexModels: string[];
opencodeModels: string[];
modelPorts: Record<string, "codex" | "opencode">;
} {
const codeModels = Array.from(new Set(models.map((model) => normalizeSubmitModel(model)).filter(Boolean)));
return {
codeModels,
codexModels: codeModels.filter((model) => codeAgentPortForModel(model) === "codex"),
opencodeModels: sharedOpencodeModels(codeModels),
modelPorts: sharedCodeModelPorts(codeModels),
};
}
function submitRunnerForModel(model: string | null | undefined): "opencode" | "codex" | null {
const normalized = normalizeSubmitModel(model);
if (normalized.length === 0) return null;
return normalized === minimaxSubmitModel ? "opencode" : "codex";
return normalized === minimaxSubmitModel || normalized === deepseekSubmitModel ? "opencode" : "codex";
}
function regexEvidence(text: string, patterns: RegExp[], limit = 6): string[] {
@@ -667,7 +683,7 @@ function submitPolicyContract(): SubmitRoutingRecommendation["policyContract"] {
return {
selectionPrinciples: [
"Use GPT-5.5 for high-risk, runtime/core, security, CI/CD, deploy, release, and final quality calls.",
"Use DeepSeek for self-contained medium-complexity work with limited write scope and verifiable tests.",
"Use DeepSeek/OpenCode for self-contained medium-complexity work with limited write scope and verifiable tests.",
"Use MiniMax only for simple, low-risk, self-contained work with external evidence and commander review.",
"Keep prod restart, secret access, DB writes, destructive Git, and running-task control with the commander or human.",
],
@@ -686,7 +702,7 @@ function submitPolicyContract(): SubmitRoutingRecommendation["policyContract"] {
},
{
model: deepseekSubmitModel,
runner: "codex",
runner: "opencode",
taskRisk: "medium-complexity",
requiredGuards: ["self-contained prompt", "limited write scope", "contract/unit verification", "commander review"],
},
@@ -844,17 +860,17 @@ function submitRoutingRecommendation(options: CodexSubmitOptions): SubmitRouting
confidence = "high";
reason = "This task touches runtime/core/cross-module or release-governance surfaces, so it should stay on GPT-5.5.";
} else if (mediumComplexityCandidate) {
route = "deepseek-codex";
recommendedRunner = "codex";
route = "deepseek-opencode";
recommendedRunner = "opencode";
recommendedModel = deepseekSubmitModel;
confidence = "high";
reason = "The prompt looks self-contained, medium-complexity, and verifiable without production/state privileges; it is a DeepSeek/Codex candidate after commander review.";
reason = "The prompt looks self-contained, medium-complexity, and verifiable without production/state privileges; it is a DeepSeek/OpenCode candidate after commander review.";
} else if (mediumComplexityEvidence.length > 0 && issueIsNotOnlySource && noProdRestartSecretOrDbWrite && noRuntimeCoreOrReleaseWork) {
route = "deepseek-codex";
recommendedRunner = "codex";
route = "deepseek-opencode";
recommendedRunner = "opencode";
recommendedModel = deepseekSubmitModel;
confidence = "medium";
reason = "The prompt has medium-complexity signals, but the commander should tighten self-contained context, write scope, and verification requirements before relying on DeepSeek.";
reason = "The prompt has medium-complexity signals, but the commander should tighten self-contained context, write scope, and verification requirements before relying on DeepSeek/OpenCode.";
} else if (promptSelfContained && issueIsNotOnlySource && evidenceRequiredByPrompt && lowRiskEvidence.length > 0) {
route = "minimax-opencode";
recommendedRunner = "opencode";
@@ -2829,6 +2845,10 @@ export function codexSubmitRoutingRecommendationForTest(prompt: string, model?:
});
}
export function codexSubmitModelRegistryForTest(models: string[] = sharedDefaultCodeModels): ReturnType<typeof submitModelRegistry> {
return submitModelRegistry(models);
}
function codexSubmitTask(args: string[]): unknown {
const options = parseSubmitOptions(args);
const payload = submitPayload(options);
@@ -2837,6 +2857,7 @@ function codexSubmitTask(args: string[]): unknown {
ok: true,
dryRun: true,
routingRecommendation: submitRoutingRecommendation(options),
modelRegistry: submitModelRegistry(),
request: {
...payload,
prompt: textView(options.prompt, true, 3000),