-
Notifications
You must be signed in to change notification settings - Fork 1.1k
fix(devin): apply explicit SWE-2 effort before model suffix #4445
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -84,6 +84,39 @@ function hasEffortSuffix(modelId: string): boolean { | |
| return parts.length > 1 && EFFORT_SUFFIXES.has(parts[parts.length - 1]!); | ||
| } | ||
|
|
||
| /** | ||
| * SWE-2 ships exactly three native lanes. Cognition spells them as the model id, | ||
| * not as a separate effort field, so an explicit caller effort has to be resolved | ||
| * to the UID before the suffix shortcut below accepts whatever the picker sent. | ||
| * | ||
| * Kept as a named table rather than an inline branch because EFFORT_SUFFIXES does | ||
| * not carry `ultra`, `off`, or `minimal`, so the two would drift apart silently. | ||
| * Values below Medium select Medium: SWE-2 has no lane under it, and rounding down | ||
| * to nothing would quietly disable its reasoning. | ||
| */ | ||
| const SWE2_EFFORT: Record<string, "medium" | "high" | "max"> = { | ||
| none: "medium", | ||
| off: "medium", | ||
| minimal: "medium", | ||
| low: "medium", | ||
| medium: "medium", | ||
| high: "high", | ||
| xhigh: "max", | ||
| ultra: "max", | ||
| max: "max", | ||
| }; | ||
|
|
||
| /** | ||
| * Resolve an explicit effort onto a SWE-2 lane, or undefined when this is not a | ||
| * SWE-2 id or the caller named no usable effort. Undefined leaves every existing | ||
| * path untouched, which is what keeps other model families on suffix precedence. | ||
| */ | ||
| function resolveSwe2Variant(modelId: string, reasoningEffort?: string): string | undefined { | ||
| if (!/^swe-2(?:-(?:medium|high|max))?$/.test(modelId)) return undefined; | ||
| const mapped = reasoningEffort ? SWE2_EFFORT[reasoningEffort.toLowerCase()] : undefined; | ||
| return mapped ? `swe-2-${mapped}` : undefined; | ||
| } | ||
|
|
||
| /** | ||
| * Resolve the wire model UID using the live catalog as the source of truth. | ||
| * Cognition's catalog lists most models with an effort suffix | ||
|
|
@@ -103,6 +136,11 @@ async function resolveWireModelUid( | |
| reasoningEffort?: string, | ||
| ): Promise<string> { | ||
| const modelId = normalizeDevinModelId(rawModelId); | ||
| // Explicit effort wins over a suffix the picker already baked into the id, so | ||
| // `swe-2-high` asked for at `medium` becomes `swe-2-medium` instead of ignoring | ||
| // the caller. Runs before the shortcut below, which would otherwise return early. | ||
| const swe2 = resolveSwe2Variant(modelId, reasoningEffort); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This changes behavior in AGENTS.md reference: src/AGENTS.md:L10-L11 Useful? React with 👍 / 👎. |
||
| if (swe2) return swe2; | ||
| if (hasEffortSuffix(modelId)) return modelId; | ||
| const catalog = await getCachedCatalog(apiKey, host); | ||
| if (catalog) { | ||
|
|
@@ -120,6 +158,13 @@ async function resolveWireModelUid( | |
| return `${modelId}-${effort}`; | ||
| } | ||
|
|
||
| /** | ||
| * Test seam. The resolver stays module-private because it reaches the catalog; | ||
| * exporting it under its bare name would make an async network-touching helper | ||
| * part of the adapter public API. Mirrors sanitizeToolDescriptionForCognitionForTests. | ||
| */ | ||
| export const resolveWireModelUidForTests = resolveWireModelUid; | ||
|
|
||
| export class DevinMissingCredentialError extends Error { | ||
| constructor() { | ||
| super("Devin live transport requires a Devin API key. Run ocx login devin to sign in with your Cognition/Devin account."); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Document the
higheffort mapping.The paragraph documents
medium, maximum aliases, and lower-effort clamping, but it omitshigh.resolveSwe2Variantmapshightoswe-2-high. Add this mapping so the documentation covers all native SWE-2 lanes.As per coding guidelines,
docs-site/must “Document current shipped or intentionally pending behavior.” As per path instructions, user-facing docs must stay synchronized with actual CLI/API behavior.🤖 Prompt for AI Agents
Sources: Coding guidelines, Path instructions