fix: route deepseek through opencode
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { codexSubmitRoutingRecommendationForTest } from "./src/code-queue";
|
||||
import { codexSubmitModelRegistryForTest, codexSubmitRoutingRecommendationForTest } from "./src/code-queue";
|
||||
|
||||
type JsonRecord = Record<string, unknown>;
|
||||
|
||||
@@ -53,16 +53,30 @@ export function runCodeQueueSubmitRoutingContract(): JsonRecord {
|
||||
assertCondition(runtime.recommendedModel === "gpt-5.5", "runtime/core work should recommend GPT-5.5", runtime);
|
||||
|
||||
const medium = codexSubmitRoutingRecommendationForTest(mediumPrompt, "deepseek");
|
||||
assertCondition(medium.route === "deepseek-codex", "medium bounded frontend work should recommend DeepSeek", medium);
|
||||
assertCondition(medium.recommendedRunner === "codex", "DeepSeek work should use Codex runner", medium);
|
||||
assertCondition(medium.route === "deepseek-opencode", "medium bounded frontend work should recommend DeepSeek/OpenCode", medium);
|
||||
assertCondition(medium.recommendedRunner === "opencode", "DeepSeek work should use OpenCode runner", medium);
|
||||
assertCondition(medium.recommendedModel === "deepseek-chat", "DeepSeek candidate should recommend deepseek-chat", medium);
|
||||
assertCondition(asRecord(medium.riskControls).mediumComplexityCandidate === true, "medium prompt should satisfy medium complexity controls", medium);
|
||||
assertCondition(asRecord(medium.explicitRequest).model === "deepseek-chat", "explicit deepseek alias should normalize to deepseek-chat", medium);
|
||||
assertCondition(asRecord(medium.explicitRequest).runner === "opencode", "explicit deepseek alias should route to OpenCode", medium);
|
||||
const policyContract = asRecord(medium.policyContract);
|
||||
assertCondition(asRecord(policyContract.concurrency).gpt55Routine === 5, "policy contract should expose GPT-5.5 routine concurrency", policyContract);
|
||||
assertCondition(asRecord(policyContract.concurrency).gpt55BurstMax === 10, "policy contract should expose GPT-5.5 burst concurrency", policyContract);
|
||||
assertCondition(asRecord(policyContract.concurrency).minimaxSimpleMax === 10, "policy contract should expose MiniMax simple concurrency", policyContract);
|
||||
assertCondition(asRecord(policyContract.concurrency).deepseekMediumDefault === 5, "policy contract should expose DeepSeek medium default concurrency", policyContract);
|
||||
const modelTiers = asRecord(policyContract).modelTiers as unknown[];
|
||||
assertCondition(Array.isArray(modelTiers), "policy contract should expose model tiers", policyContract);
|
||||
const deepseekTier = modelTiers.map(asRecord).find((tier) => tier.model === "deepseek-chat");
|
||||
assertCondition(deepseekTier?.runner === "opencode", "DeepSeek policy tier should use OpenCode", policyContract);
|
||||
|
||||
const registry = codexSubmitModelRegistryForTest(["gpt-5.5", "deepseek", "minimax-m2.7"]);
|
||||
const modelPorts = asRecord(registry.modelPorts);
|
||||
assertCondition(modelPorts["deepseek-chat"] === "opencode", "modelPorts should route deepseek-chat to OpenCode", registry);
|
||||
assertCondition(modelPorts["minimax-m2.7"] === "opencode", "modelPorts should keep MiniMax on OpenCode", registry);
|
||||
assertCondition(modelPorts["gpt-5.5"] === "codex", "modelPorts should keep default GPT on Codex", registry);
|
||||
assertCondition(registry.opencodeModels.includes("deepseek-chat"), "opencodeModels should include deepseek-chat", registry);
|
||||
assertCondition(registry.opencodeModels.includes("minimax-m2.7"), "opencodeModels should include MiniMax", registry);
|
||||
assertCondition(registry.codexModels.includes("gpt-5.5"), "codexModels should include default GPT", registry);
|
||||
|
||||
const commanderOnly = codexSubmitRoutingRecommendationForTest(commanderOnlyPrompt);
|
||||
assertCondition(commanderOnly.route === "commander-human-only", "prod restart/secrets/DB work should be commander-only", commanderOnly);
|
||||
@@ -80,7 +94,8 @@ export function runCodeQueueSubmitRoutingContract(): JsonRecord {
|
||||
checks: [
|
||||
"low-risk self-contained prompts recommend minimax-m2.7/OpenCode",
|
||||
"runtime/core work recommends GPT-5.5/Codex",
|
||||
"medium bounded frontend work recommends deepseek-chat/Codex",
|
||||
"medium bounded frontend work recommends deepseek-chat/OpenCode",
|
||||
"model registry maps deepseek-chat and minimax-m2.7 to OpenCode and GPT-5.5 to Codex",
|
||||
"dry-run policy contract exposes model-tier concurrency",
|
||||
"prod/restart/secret/DB work is commander-only",
|
||||
"explicit --model mismatch is visible and payload is unchanged",
|
||||
|
||||
+31
-10
@@ -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),
|
||||
|
||||
Reference in New Issue
Block a user