Add Claude context window selection support#1422
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Autofix Details
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Context window menu unreachable behind early return guard
- Updated the early return guard in TraitsMenuContent to also check
contextWindowOptions.length <= 1, ensuring the context window radio group is reachable even when effort and thinkingEnabled are both null.
- Updated the early return guard in TraitsMenuContent to also check
Or push these changes by commenting:
@cursor push b6a7381f01
Preview (b6a7381f01)
diff --git a/apps/web/src/components/chat/TraitsPicker.tsx b/apps/web/src/components/chat/TraitsPicker.tsx
--- a/apps/web/src/components/chat/TraitsPicker.tsx
+++ b/apps/web/src/components/chat/TraitsPicker.tsx
@@ -217,7 +217,7 @@
],
);
- if (effort === null && thinkingEnabled === null) {
+ if (effort === null && thinkingEnabled === null && contextWindowOptions.length <= 1) {
return null;
}- Add context window options to Claude model capabilities and normalization - Surface the setting in the web traits picker and persist it in drafts - Resolve API model IDs with context window suffixes for Claude requests
- Store context window options as semantic values - Centralize API model-id resolution for Claude selections - Update UI and shared tests for new default handling
- Extend server and test model capability shapes with `contextWindowOptions` - Update chat picker fixtures to match the new shared model contract
7c27621 to
60610ce
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
Autofix Details
Bugbot Autofix prepared fixes for both issues found in the latest run.
- ✅ Fixed: Wrong default context window in shared model data
- Moved
isDefault: truefrom the"1m"entry to the"200k"entry inMODEL_OPTIONS_BY_PROVIDERfor bothclaude-opus-4-6andclaude-sonnet-4-6, matching the server-sideClaudeProvider.tsdefinitions.
- Moved
- ✅ Fixed: Client normalization strips contextWindow before server dispatch
- Added
contextWindowresolution logic tonormalizeClaudeModelOptionsWithCapabilitiesso non-default context window selections are preserved and dispatched to the server.
- Added
Or push these changes by commenting:
@cursor push 49f47e3aae
Preview (49f47e3aae)
diff --git a/apps/web/src/providerModels.ts b/apps/web/src/providerModels.ts
--- a/apps/web/src/providerModels.ts
+++ b/apps/web/src/providerModels.ts
@@ -8,7 +8,9 @@
type ServerProviderModel,
} from "@t3tools/contracts";
import {
+ getDefaultContextWindow,
getDefaultEffort,
+ hasContextWindowOption,
hasEffortLevel,
normalizeModelSlug,
trimOrNull,
@@ -108,10 +110,19 @@
const thinking =
caps.supportsThinkingToggle && modelOptions?.thinking === false ? false : undefined;
const fastMode = caps.supportsFastMode && modelOptions?.fastMode === true ? true : undefined;
+ const rawContextWindow = modelOptions?.contextWindow;
+ const defaultContextWindow = getDefaultContextWindow(caps);
+ const contextWindow =
+ rawContextWindow &&
+ rawContextWindow !== defaultContextWindow &&
+ hasContextWindowOption(caps, rawContextWindow)
+ ? rawContextWindow
+ : undefined;
const nextOptions: ClaudeModelOptions = {
...(thinking === false ? { thinking: false } : {}),
...(effort ? { effort } : {}),
...(fastMode ? { fastMode: true } : {}),
+ ...(contextWindow ? { contextWindow } : {}),
};
return Object.keys(nextOptions).length > 0 ? nextOptions : undefined;
}
diff --git a/packages/contracts/src/model.ts b/packages/contracts/src/model.ts
--- a/packages/contracts/src/model.ts
+++ b/packages/contracts/src/model.ts
@@ -176,8 +176,8 @@
supportsFastMode: true,
supportsThinkingToggle: false,
contextWindowOptions: [
- { value: "200k", label: "200k" },
- { value: "1m", label: "1M", isDefault: true },
+ { value: "200k", label: "200k", isDefault: true },
+ { value: "1m", label: "1M" },
],
promptInjectedEffortLevels: ["ultrathink"],
},
@@ -195,8 +195,8 @@
supportsFastMode: false,
supportsThinkingToggle: false,
contextWindowOptions: [
- { value: "200k", label: "200k" },
- { value: "1m", label: "1M", isDefault: true },
+ { value: "200k", label: "200k", isDefault: true },
+ { value: "1m", label: "1M" },
],
promptInjectedEffortLevels: ["ultrathink"],
},- Allow arbitrary model strings across client and shared model code - Normalize Claude context-window options through shared helpers - Update shared model tests for the revised capability handling
- Suppress the picker when effort, thinking, and context window controls are all unavailable - Keep shared model tests aligned with the current contract imports
|
Bugbot Autofix prepared fixes for both issues found in the latest run.
Or push these changes by commenting: Preview (ea54ac641d)diff --git a/apps/server/src/git/Layers/ClaudeTextGeneration.ts b/apps/server/src/git/Layers/ClaudeTextGeneration.ts
--- a/apps/server/src/git/Layers/ClaudeTextGeneration.ts
+++ b/apps/server/src/git/Layers/ClaudeTextGeneration.ts
@@ -104,7 +104,10 @@
"--json-schema",
jsonSchemaStr,
"--model",
- resolveApiModelId(modelSelection),
+ resolveApiModelId({
+ ...modelSelection,
+ options: normalizedOptions ?? {},
+ }),
...(normalizedOptions?.effort ? ["--effort", normalizedOptions.effort] : []),
...(Object.keys(settings).length > 0 ? ["--settings", JSON.stringify(settings)] : []),
"--dangerously-skip-permissions",
diff --git a/apps/server/src/provider/Layers/ClaudeAdapter.ts b/apps/server/src/provider/Layers/ClaudeAdapter.ts
--- a/apps/server/src/provider/Layers/ClaudeAdapter.ts
+++ b/apps/server/src/provider/Layers/ClaudeAdapter.ts
@@ -44,6 +44,7 @@
hasEffortLevel,
applyClaudePromptEffortPrefix,
resolveApiModelId,
+ resolveContextWindow,
trimOrNull,
} from "@t3tools/shared/model";
import {
@@ -2732,9 +2733,15 @@
const claudeBinaryPath = claudeSettings.binaryPath;
const modelSelection =
input.modelSelection?.provider === "claudeAgent" ? input.modelSelection : undefined;
- const apiModelId = modelSelection ? resolveApiModelId(modelSelection) : undefined;
+ const caps = getClaudeModelCapabilities(modelSelection?.model);
+ const contextWindow = resolveContextWindow(caps, modelSelection?.options?.contextWindow);
+ const apiModelId = modelSelection
+ ? resolveApiModelId({
+ ...modelSelection,
+ options: { ...modelSelection.options, contextWindow },
+ })
+ : undefined;
const requestedEffort = trimOrNull(modelSelection?.options?.effort ?? null);
- const caps = getClaudeModelCapabilities(modelSelection?.model);
const effort =
requestedEffort && hasEffortLevel(caps, requestedEffort) ? requestedEffort : null;
const fastMode = modelSelection?.options?.fastMode === true && caps.supportsFastMode;
@@ -2899,7 +2906,15 @@
}
if (modelSelection?.model) {
- const apiModelId = resolveApiModelId(modelSelection);
+ const turnCaps = getClaudeModelCapabilities(modelSelection.model);
+ const turnContextWindow = resolveContextWindow(
+ turnCaps,
+ modelSelection.options?.contextWindow,
+ );
+ const apiModelId = resolveApiModelId({
+ ...modelSelection,
+ options: { ...modelSelection.options, contextWindow: turnContextWindow },
+ });
yield* Effect.tryPromise({
try: () => context.query.setModel(apiModelId),
catch: (cause) => toRequestError(input.threadId, "turn/setModel", cause),
diff --git a/packages/contracts/src/model.ts b/packages/contracts/src/model.ts
--- a/packages/contracts/src/model.ts
+++ b/packages/contracts/src/model.ts
@@ -36,7 +36,7 @@
export type EffortOption = typeof EffortOption.Type;
export const ContextWindowOption = Schema.Struct({
- value: Schema.String,
+ value: TrimmedNonEmptyString,
label: TrimmedNonEmptyString,
isDefault: Schema.optional(Schema.Boolean),
}); |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
There are 3 total unresolved issues (including 2 from previous reviews).
Autofix Details
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Context window not validated against model capabilities before use
- Added optional ModelCapabilities parameter to resolveApiModelId that uses resolveContextWindow to validate the context window against model capabilities, preventing invalid model IDs like claude-haiku-4-5[1m] when a stale contextWindow option carries over from a model that supports 1M context.
Or push these changes by commenting:
@cursor push bb8241aabe
Preview (bb8241aabe)
diff --git a/apps/server/src/git/Layers/ClaudeTextGeneration.ts b/apps/server/src/git/Layers/ClaudeTextGeneration.ts
--- a/apps/server/src/git/Layers/ClaudeTextGeneration.ts
+++ b/apps/server/src/git/Layers/ClaudeTextGeneration.ts
@@ -27,7 +27,10 @@
sanitizePrTitle,
toJsonSchemaObject,
} from "../Utils.ts";
-import { normalizeClaudeModelOptions } from "../../provider/Layers/ClaudeProvider.ts";
+import {
+ getClaudeModelCapabilities,
+ normalizeClaudeModelOptions,
+} from "../../provider/Layers/ClaudeProvider.ts";
import { ServerSettingsService } from "../../serverSettings.ts";
const CLAUDE_TIMEOUT_MS = 180_000;
@@ -104,7 +107,7 @@
"--json-schema",
jsonSchemaStr,
"--model",
- resolveApiModelId(modelSelection),
+ resolveApiModelId(modelSelection, getClaudeModelCapabilities(modelSelection.model)),
...(normalizedOptions?.effort ? ["--effort", normalizedOptions.effort] : []),
...(Object.keys(settings).length > 0 ? ["--settings", JSON.stringify(settings)] : []),
"--dangerously-skip-permissions",
diff --git a/apps/server/src/provider/Layers/ClaudeAdapter.ts b/apps/server/src/provider/Layers/ClaudeAdapter.ts
--- a/apps/server/src/provider/Layers/ClaudeAdapter.ts
+++ b/apps/server/src/provider/Layers/ClaudeAdapter.ts
@@ -2732,9 +2732,9 @@
const claudeBinaryPath = claudeSettings.binaryPath;
const modelSelection =
input.modelSelection?.provider === "claudeAgent" ? input.modelSelection : undefined;
- const apiModelId = modelSelection ? resolveApiModelId(modelSelection) : undefined;
+ const caps = getClaudeModelCapabilities(modelSelection?.model);
+ const apiModelId = modelSelection ? resolveApiModelId(modelSelection, caps) : undefined;
const requestedEffort = trimOrNull(modelSelection?.options?.effort ?? null);
- const caps = getClaudeModelCapabilities(modelSelection?.model);
const effort =
requestedEffort && hasEffortLevel(caps, requestedEffort) ? requestedEffort : null;
const fastMode = modelSelection?.options?.fastMode === true && caps.supportsFastMode;
@@ -2899,7 +2899,8 @@
}
if (modelSelection?.model) {
- const apiModelId = resolveApiModelId(modelSelection);
+ const caps = getClaudeModelCapabilities(modelSelection.model);
+ const apiModelId = resolveApiModelId(modelSelection, caps);
yield* Effect.tryPromise({
try: () => context.query.setModel(apiModelId),
catch: (cause) => toRequestError(input.threadId, "turn/setModel", cause),
diff --git a/packages/shared/src/model.test.ts b/packages/shared/src/model.test.ts
--- a/packages/shared/src/model.test.ts
+++ b/packages/shared/src/model.test.ts
@@ -179,6 +179,39 @@
).toBe("claude-opus-4-6");
});
+ it("strips unsupported context window when capabilities are provided", () => {
+ const haikuCaps: ModelCapabilities = {
+ reasoningEffortLevels: [],
+ supportsFastMode: false,
+ supportsThinkingToggle: true,
+ contextWindowOptions: [],
+ promptInjectedEffortLevels: [],
+ };
+ expect(
+ resolveApiModelId(
+ {
+ provider: "claudeAgent",
+ model: "claude-haiku-4-5",
+ options: { contextWindow: "1m" },
+ },
+ haikuCaps,
+ ),
+ ).toBe("claude-haiku-4-5");
+ });
+
+ it("appends suffix when capabilities confirm support", () => {
+ expect(
+ resolveApiModelId(
+ {
+ provider: "claudeAgent",
+ model: "claude-opus-4-6",
+ options: { contextWindow: "1m" },
+ },
+ claudeCaps,
+ ),
+ ).toBe("claude-opus-4-6[1m]");
+ });
+
it("returns the model as-is for Codex selections", () => {
expect(resolveApiModelId({ provider: "codex", model: "gpt-5.4" })).toBe("gpt-5.4");
});
diff --git a/packages/shared/src/model.ts b/packages/shared/src/model.ts
--- a/packages/shared/src/model.ts
+++ b/packages/shared/src/model.ts
@@ -130,10 +130,14 @@
return trimmed || null;
}
-export function resolveApiModelId(modelSelection: ModelSelection): string {
+export function resolveApiModelId(
+ modelSelection: ModelSelection,
+ capabilities?: ModelCapabilities,
+): string {
switch (modelSelection.provider) {
case "claudeAgent": {
- const contextWindow = modelSelection.options?.contextWindow;
+ const raw = modelSelection.options?.contextWindow;
+ const contextWindow = capabilities ? resolveContextWindow(capabilities, raw) : raw;
switch (contextWindow) {
case "1m":
return `${modelSelection.model}[1m]`;- Pass model capabilities into Claude API model resolution - Avoid appending unsupported context-window suffixes - Add coverage for unsupported Claude context-window selections
- Make Claude models resolve to the default 1M API suffix when no context window is set - Update shared model tests and built-in Claude capabilities to reflect 1M as default
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Autofix Details
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Default context window flag is on wrong option
- Moved
isDefault: truefrom the1moption to the200koption on both claude-opus-4-6 and claude-sonnet-4-6 models, so the [1m] suffix is only appended when a user explicitly selects 1M context window.
- Moved
Or push these changes by commenting:
@cursor push e394a7c27a
Preview (e394a7c27a)
diff --git a/apps/server/src/provider/Layers/ClaudeProvider.ts b/apps/server/src/provider/Layers/ClaudeProvider.ts
--- a/apps/server/src/provider/Layers/ClaudeProvider.ts
+++ b/apps/server/src/provider/Layers/ClaudeProvider.ts
@@ -48,8 +48,8 @@
supportsFastMode: true,
supportsThinkingToggle: false,
contextWindowOptions: [
- { value: "200k", label: "200k" },
- { value: "1m", label: "1M", isDefault: true },
+ { value: "200k", label: "200k", isDefault: true },
+ { value: "1m", label: "1M" },
],
promptInjectedEffortLevels: ["ultrathink"],
} satisfies ModelCapabilities,
@@ -68,8 +68,8 @@
supportsFastMode: false,
supportsThinkingToggle: false,
contextWindowOptions: [
- { value: "200k", label: "200k" },
- { value: "1m", label: "1M", isDefault: true },
+ { value: "200k", label: "200k", isDefault: true },
+ { value: "1m", label: "1M" },
],
promptInjectedEffortLevels: ["ultrathink"],
} satisfies ModelCapabilities,
diff --git a/packages/shared/src/model.test.ts b/packages/shared/src/model.test.ts
--- a/packages/shared/src/model.test.ts
+++ b/packages/shared/src/model.test.ts
@@ -36,8 +36,8 @@
supportsFastMode: false,
supportsThinkingToggle: false,
contextWindowOptions: [
- { value: "200k", label: "200k" },
- { value: "1m", label: "1M", isDefault: true },
+ { value: "200k", label: "200k", isDefault: true },
+ { value: "1m", label: "1M" },
],
promptInjectedEffortLevels: ["ultrathink"],
};
@@ -117,7 +117,7 @@
describe("context window helpers", () => {
it("reads default context window", () => {
- expect(getDefaultContextWindow(claudeCaps)).toBe("1m");
+ expect(getDefaultContextWindow(claudeCaps)).toBe("200k");
});
it("returns null for models without context window options", () => {
@@ -142,17 +142,16 @@
).toBe("claude-opus-4-6[1m]");
});
- it("applies default context window suffix when contextWindow is not set", () => {
- // 1m is the default for claudeCaps, so [1m] suffix should be applied
+ it("returns the model as-is when contextWindow is not set (200k default)", () => {
expect(
resolveApiModelId({ provider: "claudeAgent", model: "claude-opus-4-6" }, claudeCaps),
- ).toBe("claude-opus-4-6[1m]");
+ ).toBe("claude-opus-4-6");
expect(
resolveApiModelId(
{ provider: "claudeAgent", model: "claude-opus-4-6", options: {} },
claudeCaps,
),
- ).toBe("claude-opus-4-6[1m]");
+ ).toBe("claude-opus-4-6");
});
it("returns the model as-is for explicit 200k (no suffix needed)", () => {
@@ -165,13 +164,13 @@
});
it("falls back to default when context window value is unsupported", () => {
- // bogus is not in contextWindowOptions, so falls back to default (1m)
+ // bogus is not in contextWindowOptions, so falls back to default (200k)
expect(
resolveApiModelId(
{ provider: "claudeAgent", model: "claude-opus-4-6", options: { contextWindow: "bogus" } },
claudeCaps,
),
- ).toBe("claude-opus-4-6[1m]");
+ ).toBe("claude-opus-4-6");
});
it("returns the model as-is when model has no context window options", () => {- Add shared effort/context-window resolution helpers - Simplify Claude and Codex normalization paths - Update UI defaults and model-id handling tests
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Normalization functions no longer strip default effort values
- Added normalizeEffort() helper that strips effort when it matches the model default, and replaced resolveEffort() with normalizeEffort() in all four normalization functions so they correctly return undefined for all-default configurations.
Or push these changes by commenting:
@cursor push 11be973bfc
Preview (11be973bfc)
diff --git a/apps/server/src/provider/Layers/ClaudeProvider.ts b/apps/server/src/provider/Layers/ClaudeProvider.ts
--- a/apps/server/src/provider/Layers/ClaudeProvider.ts
+++ b/apps/server/src/provider/Layers/ClaudeProvider.ts
@@ -9,7 +9,7 @@
} from "@t3tools/contracts";
import { Effect, Equal, Layer, Option, Result, Stream } from "effect";
import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process";
-import { resolveContextWindow, resolveEffort } from "@t3tools/shared/model";
+import { normalizeEffort, resolveContextWindow } from "@t3tools/shared/model";
import {
buildServerProvider,
@@ -101,7 +101,7 @@
modelOptions: ClaudeModelOptions | null | undefined,
): ClaudeModelOptions | undefined {
const caps = getClaudeModelCapabilities(model);
- const effort = resolveEffort(caps, modelOptions?.effort);
+ const effort = normalizeEffort(caps, modelOptions?.effort);
const thinking =
caps.supportsThinkingToggle && modelOptions?.thinking === false ? false : undefined;
const fastMode = caps.supportsFastMode && modelOptions?.fastMode === true ? true : undefined;
diff --git a/apps/server/src/provider/Layers/CodexProvider.ts b/apps/server/src/provider/Layers/CodexProvider.ts
--- a/apps/server/src/provider/Layers/CodexProvider.ts
+++ b/apps/server/src/provider/Layers/CodexProvider.ts
@@ -10,7 +10,7 @@
} from "@t3tools/contracts";
import { Effect, Equal, FileSystem, Layer, Option, Path, Result, Stream } from "effect";
import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process";
-import { resolveEffort } from "@t3tools/shared/model";
+import { normalizeEffort } from "@t3tools/shared/model";
import {
buildServerProvider,
@@ -157,7 +157,7 @@
modelOptions: CodexModelOptions | null | undefined,
): CodexModelOptions | undefined {
const caps = getCodexModelCapabilities(model);
- const reasoningEffort = resolveEffort(caps, modelOptions?.reasoningEffort);
+ const reasoningEffort = normalizeEffort(caps, modelOptions?.reasoningEffort);
const fastModeEnabled = modelOptions?.fastMode === true;
const nextOptions: CodexModelOptions = {
...(reasoningEffort
diff --git a/apps/web/src/providerModels.ts b/apps/web/src/providerModels.ts
--- a/apps/web/src/providerModels.ts
+++ b/apps/web/src/providerModels.ts
@@ -7,7 +7,7 @@
type ServerProvider,
type ServerProviderModel,
} from "@t3tools/contracts";
-import { normalizeModelSlug, resolveContextWindow, resolveEffort } from "@t3tools/shared/model";
+import { normalizeEffort, normalizeModelSlug, resolveContextWindow } from "@t3tools/shared/model";
const EMPTY_CAPABILITIES: ModelCapabilities = {
reasoningEffortLevels: [],
@@ -74,7 +74,7 @@
caps: ModelCapabilities,
modelOptions: CodexModelOptions | null | undefined,
): CodexModelOptions | undefined {
- const reasoningEffort = resolveEffort(caps, modelOptions?.reasoningEffort);
+ const reasoningEffort = normalizeEffort(caps, modelOptions?.reasoningEffort);
const fastModeEnabled = modelOptions?.fastMode === true;
const nextOptions: CodexModelOptions = {
...(reasoningEffort
@@ -89,7 +89,7 @@
caps: ModelCapabilities,
modelOptions: ClaudeModelOptions | null | undefined,
): ClaudeModelOptions | undefined {
- const effort = resolveEffort(caps, modelOptions?.effort);
+ const effort = normalizeEffort(caps, modelOptions?.effort);
const thinking =
caps.supportsThinkingToggle && modelOptions?.thinking === false ? false : undefined;
const fastMode = caps.supportsFastMode && modelOptions?.fastMode === true ? true : undefined;
diff --git a/packages/shared/src/model.ts b/packages/shared/src/model.ts
--- a/packages/shared/src/model.ts
+++ b/packages/shared/src/model.ts
@@ -50,6 +50,20 @@
return defaultValue ?? undefined;
}
+/**
+ * Resolve effort for normalization: returns the effort only when it differs
+ * from the model's default. Used by normalization functions that need to strip
+ * defaults to keep stored/dispatched options minimal.
+ */
+export function normalizeEffort(
+ caps: ModelCapabilities,
+ raw: string | null | undefined,
+): string | undefined {
+ const resolved = resolveEffort(caps, raw);
+ const defaultValue = getDefaultEffort(caps);
+ return resolved && resolved !== defaultValue ? resolved : undefined;
+}
+
// ── Context window helpers ───────────────────────────────────────────
/** Check whether a capabilities object includes a given context window value. */- keep explicit default effort when composing Codex and Claude dispatch options - update adapter expectations for Sonnet 4.6 fallback behavior
Reverts all 10 commits pulled from upstream (add5f34 through 1ae20fa) including our local classifySqliteError fix. Upstream introduced a classifySqliteError import that does not exist in [email protected]. Reverting until upstream resolves the version mismatch. Reverted commits: - 1ae20fa fix(persistence): revert classifySqliteError to SqlError({ cause, message }) - 23b3f0c Refactor Codex adapter lifecycle helpers (pingdotgg#1478) - e08cea3 Improve drain semantics via STM in DrainableWorker (pingdotgg#1474) - 83eb396 fix(threads): Keep active-turn runtime errors from ending sessions (pingdotgg#1261) - 59a383e Add Effect.fn refactor checklist (pingdotgg#1476) - fb72607 fix(claude): avoid resetting the Claude model on every turn (pingdotgg#1466) - d8a485e Support gh pr checkout pull request references (pingdotgg#1457) - 02989fe fix(web): improve chat header badge and title flex distribution (pingdotgg#1309) - 648f067 Add VS Code Insiders and VSCodium to Open In editor picker (pingdotgg#1392) - add5f34 Add Claude context window selection support (pingdotgg#1422)
Includes: server settings refactor (pingdotgg#1421), Claude text generation (pingdotgg#1323), security bootstrap fd (pingdotgg#1398), context window selection (pingdotgg#1422), editor picker updates (pingdotgg#1392). Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>


Summary
Testing
bun fmt,bun lint,bun typecheck, andbun run testbefore merge.Note
Medium Risk
Moderate risk because it changes how Claude model options are normalized and how the model id/effort are sent to the Claude CLI/SDK, which could affect session configuration and request behavior across server and web.
Overview
Adds Claude context window selection as a first-class capability (
contextWindowOptions) and option (ClaudeModelOptions.contextWindow), plus shared helpers (resolveContextWindow,getDefaultContextWindow,resolveEffort,resolveApiModelId) to consistently resolve defaults/unsupported values.Updates server Claude integrations (
ClaudeAdapter,ClaudeTextGeneration) to use the resolved API model id (e.g. appending[1m]) and to fall back to default effort when unsupported, while keeping prompt-injected efforts (likeultrathink) as prompt prefixes.Extends the web composer traits UI to show a Context Window picker for supported Claude models, persists the selection in drafts, and relaxes model slug typing from
ModelSlugtostring; tests are updated/added to cover the new normalization and dispatch behavior.Written by Cursor Bugbot for commit c661417. This will update automatically on new commits. Configure here.
Note
Add context window selection support for Claude models in the traits picker
contextWindowOptionsto Claude model capabilities (Opus 4.6 and Sonnet 4.6 support200kand1m, defaulting to1m; Haiku 4.5 has none) via ClaudeProvider.ts.resolveApiModelIdin shared/model.ts which appends a context-window suffix (e.g.[1m]) to the Claude model slug when a non-default context window is selected, and passes it to the Claude SDK and CLI.resolveEffortand context window helpers (getDefaultContextWindow,hasContextWindowOption,resolveContextWindow) to replace scattered manual default checks throughout the codebase.modelOptionsForDispatchpayloads.Macroscope summarized c661417.