summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorBrandon Smith <[email protected]>2026-01-15 01:35:16 -0600
committerGitHub <[email protected]>2026-01-15 01:35:16 -0600
commit8d720f9463e3d838064acc6a55055c76e2494fa2 (patch)
tree8f1ffa84d27e053d7c8221c9a329c6d54c11fe09
parent92931437c4ce48d2c4fdcad14067bff9a6f5d3ef (diff)
downloadopencode-8d720f9463e3d838064acc6a55055c76e2494fa2.tar.gz
opencode-8d720f9463e3d838064acc6a55055c76e2494fa2.zip
fix(opencode): add input limit for compaction (#8465)
-rw-r--r--packages/opencode/src/plugin/codex.ts32
-rw-r--r--packages/opencode/src/provider/models.ts1
-rw-r--r--packages/opencode/src/provider/provider.ts2
-rw-r--r--packages/opencode/src/session/compaction.ts2
-rw-r--r--packages/opencode/test/session/compaction.test.ts44
5 files changed, 47 insertions, 34 deletions
diff --git a/packages/opencode/src/plugin/codex.ts b/packages/opencode/src/plugin/codex.ts
index 91e66197f..fc172dad9 100644
--- a/packages/opencode/src/plugin/codex.ts
+++ b/packages/opencode/src/plugin/codex.ts
@@ -361,38 +361,6 @@ export async function CodexAuthPlugin(input: PluginInput): Promise<Hooks> {
}
}
- if (!provider.models["gpt-5.2-codex"]) {
- const model = {
- id: "gpt-5.2-codex",
- providerID: "openai",
- api: {
- id: "gpt-5.2-codex",
- url: "https://chatgpt.com/backend-api/codex",
- npm: "@ai-sdk/openai",
- },
- name: "GPT-5.2 Codex",
- capabilities: {
- temperature: false,
- reasoning: true,
- attachment: true,
- toolcall: true,
- input: { text: true, audio: false, image: true, video: false, pdf: false },
- output: { text: true, audio: false, image: false, video: false, pdf: false },
- interleaved: false,
- },
- cost: { input: 0, output: 0, cache: { read: 0, write: 0 } },
- limit: { context: 400000, output: 128000 },
- status: "active" as const,
- options: {},
- headers: {},
- release_date: "2025-12-18",
- variants: {} as Record<string, Record<string, any>>,
- family: "gpt-codex",
- }
- model.variants = ProviderTransform.variants(model)
- provider.models["gpt-5.2-codex"] = model
- }
-
// Zero out costs for Codex (included with ChatGPT subscription)
for (const model of Object.values(provider.models)) {
model.cost = {
diff --git a/packages/opencode/src/provider/models.ts b/packages/opencode/src/provider/models.ts
index 796dcb7c2..5aedce505 100644
--- a/packages/opencode/src/provider/models.ts
+++ b/packages/opencode/src/provider/models.ts
@@ -47,6 +47,7 @@ export namespace ModelsDev {
.optional(),
limit: z.object({
context: z.number(),
+ input: z.number().optional(),
output: z.number(),
}),
modalities: z
diff --git a/packages/opencode/src/provider/provider.ts b/packages/opencode/src/provider/provider.ts
index 69946afd8..9e2dd0ba0 100644
--- a/packages/opencode/src/provider/provider.ts
+++ b/packages/opencode/src/provider/provider.ts
@@ -557,6 +557,7 @@ export namespace Provider {
}),
limit: z.object({
context: z.number(),
+ input: z.number().optional(),
output: z.number(),
}),
status: z.enum(["alpha", "beta", "deprecated", "active"]),
@@ -619,6 +620,7 @@ export namespace Provider {
},
limit: {
context: model.limit.context,
+ input: model.limit.input,
output: model.limit.output,
},
capabilities: {
diff --git a/packages/opencode/src/session/compaction.ts b/packages/opencode/src/session/compaction.ts
index 42bab2eb9..ae6922128 100644
--- a/packages/opencode/src/session/compaction.ts
+++ b/packages/opencode/src/session/compaction.ts
@@ -34,7 +34,7 @@ export namespace SessionCompaction {
if (context === 0) return false
const count = input.tokens.input + input.tokens.cache.read + input.tokens.output
const output = Math.min(input.model.limit.output, SessionPrompt.OUTPUT_TOKEN_MAX) || SessionPrompt.OUTPUT_TOKEN_MAX
- const usable = context - output
+ const usable = input.model.limit.input || context - output
return count > usable
}
diff --git a/packages/opencode/test/session/compaction.test.ts b/packages/opencode/test/session/compaction.test.ts
index 9070428ea..2e9c09187 100644
--- a/packages/opencode/test/session/compaction.test.ts
+++ b/packages/opencode/test/session/compaction.test.ts
@@ -10,13 +10,19 @@ import type { Provider } from "../../src/provider/provider"
Log.init({ print: false })
-function createModel(opts: { context: number; output: number; cost?: Provider.Model["cost"] }): Provider.Model {
+function createModel(opts: {
+ context: number
+ output: number
+ input?: number
+ cost?: Provider.Model["cost"]
+}): Provider.Model {
return {
id: "test-model",
providerID: "test",
name: "Test",
limit: {
context: opts.context,
+ input: opts.input,
output: opts.output,
},
cost: opts.cost ?? { input: 0, output: 0, cache: { read: 0, write: 0 } },
@@ -70,6 +76,42 @@ describe("session.compaction.isOverflow", () => {
})
})
+ test("respects input limit for input caps", async () => {
+ await using tmp = await tmpdir()
+ await Instance.provide({
+ directory: tmp.path,
+ fn: async () => {
+ const model = createModel({ context: 400_000, input: 272_000, output: 128_000 })
+ const tokens = { input: 271_000, output: 1_000, reasoning: 0, cache: { read: 2_000, write: 0 } }
+ expect(await SessionCompaction.isOverflow({ tokens, model })).toBe(true)
+ },
+ })
+ })
+
+ test("returns false when input/output are within input caps", async () => {
+ await using tmp = await tmpdir()
+ await Instance.provide({
+ directory: tmp.path,
+ fn: async () => {
+ const model = createModel({ context: 400_000, input: 272_000, output: 128_000 })
+ const tokens = { input: 200_000, output: 20_000, reasoning: 0, cache: { read: 10_000, write: 0 } }
+ expect(await SessionCompaction.isOverflow({ tokens, model })).toBe(false)
+ },
+ })
+ })
+
+ test("returns false when output within limit with input caps", async () => {
+ await using tmp = await tmpdir()
+ await Instance.provide({
+ directory: tmp.path,
+ fn: async () => {
+ const model = createModel({ context: 200_000, input: 120_000, output: 10_000 })
+ const tokens = { input: 50_000, output: 9_999, reasoning: 0, cache: { read: 0, write: 0 } }
+ expect(await SessionCompaction.isOverflow({ tokens, model })).toBe(false)
+ },
+ })
+ })
+
test("returns false when model context limit is 0", async () => {
await using tmp = await tmpdir()
await Instance.provide({