1
0
Эх сурвалжийг харах

feat(core): support percentage compaction buffer

Ryan Vogel 1 сар өмнө
parent
commit
21da80678a

+ 5 - 1
packages/core/src/config/compaction.ts

@@ -7,9 +7,13 @@ export class Keep extends Schema.Class<Keep>("ConfigV2.Compaction.Keep")({
   tokens: NonNegativeInt.pipe(Schema.optional),
 }) {}
 
+export class BufferPercent extends Schema.Class<BufferPercent>("ConfigV2.Compaction.BufferPercent")({
+  percent: Schema.Finite.check(Schema.isGreaterThanOrEqualTo(0), Schema.isLessThanOrEqualTo(100)),
+}) {}
+
 export class Info extends Schema.Class<Info>("ConfigV2.Compaction")({
   auto: Schema.Boolean.pipe(Schema.optional),
   prune: Schema.Boolean.pipe(Schema.optional),
   keep: Keep.pipe(Schema.optional),
-  buffer: NonNegativeInt.pipe(Schema.optional),
+  buffer: Schema.Union([NonNegativeInt, BufferPercent]).pipe(Schema.optional),
 }) {}

+ 3 - 2
packages/core/src/session/compaction.ts

@@ -52,7 +52,7 @@ type Entry = {
 
 type Settings = {
   readonly auto: boolean
-  readonly buffer: number
+  readonly buffer: number | { readonly percent: number }
   readonly tokens: number
 }
 
@@ -227,9 +227,10 @@ export const make = (dependencies: Dependencies) => {
     const context = input.model.route.defaults.limits?.context
     if (context === undefined || context <= 0) return false
     const output = input.request.generation?.maxTokens ?? input.model.route.defaults.limits?.output ?? 0
+    const buffer = typeof config.buffer === "number" ? config.buffer : context * (config.buffer.percent / 100)
     if (
       estimate({ system: input.request.system, messages: input.request.messages, tools: input.request.tools }) <=
-      context - Math.max(output, config.buffer)
+      context - Math.max(output, buffer)
     )
       return false
     return yield* compactAfterOverflow(input)

+ 11 - 0
packages/core/test/config/config.test.ts

@@ -4,6 +4,7 @@ import { describe, expect } from "bun:test"
 import { Effect, Layer, Schema } from "effect"
 import { FastCheck } from "effect/testing"
 import { Config } from "@opencode-ai/core/config"
+import { ConfigCompaction } from "@opencode-ai/core/config/compaction"
 import { ConfigProvider } from "@opencode-ai/core/config/provider"
 import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder"
 import { LayerNode } from "@opencode-ai/core/effect/layer-node"
@@ -52,6 +53,16 @@ const provider = {
 }
 
 describe("Config", () => {
+  it.effect("accepts token and percentage compaction buffers", () =>
+    Effect.sync(() => {
+      expect(Schema.decodeUnknownSync(ConfigCompaction.Info)({ buffer: 20_000 }).buffer).toBe(20_000)
+      expect(Schema.decodeUnknownSync(ConfigCompaction.Info)({ buffer: { percent: 10 } }).buffer).toEqual({
+        percent: 10,
+      })
+      expect(() => Schema.decodeUnknownSync(ConfigCompaction.Info)({ buffer: { percent: 101 } })).toThrow()
+    }),
+  )
+
   it.effect("returns the latest defined scalar from priority-ordered documents", () =>
     Effect.sync(() => {
       const entries = [

+ 1 - 1
packages/core/test/session-runner.test.ts

@@ -217,7 +217,7 @@ const config = Layer.succeed(
           type: "document",
           info: new Config.Info({
             compaction: new ConfigCompaction.Info({
-              buffer: 3_000,
+              buffer: new ConfigCompaction.BufferPercent({ percent: 75 }),
               keep: new ConfigCompaction.Keep({ tokens: 1_000 }),
             }),
           }),