feat(config): add background task circuit breaker settings
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -3699,6 +3699,32 @@
|
|||||||
"syncPollTimeoutMs": {
|
"syncPollTimeoutMs": {
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"minimum": 60000
|
"minimum": 60000
|
||||||
|
},
|
||||||
|
"maxToolCalls": {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 10,
|
||||||
|
"maximum": 9007199254740991
|
||||||
|
},
|
||||||
|
"circuitBreaker": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"maxToolCalls": {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 10,
|
||||||
|
"maximum": 9007199254740991
|
||||||
|
},
|
||||||
|
"windowSize": {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 5,
|
||||||
|
"maximum": 9007199254740991
|
||||||
|
},
|
||||||
|
"repetitionThresholdPercent": {
|
||||||
|
"type": "number",
|
||||||
|
"exclusiveMinimum": 0,
|
||||||
|
"maximum": 100
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
import { describe, expect, test } from "bun:test"
|
||||||
|
import { ZodError } from "zod/v4"
|
||||||
|
import { BackgroundTaskConfigSchema } from "./background-task"
|
||||||
|
|
||||||
|
describe("BackgroundTaskConfigSchema.circuitBreaker", () => {
|
||||||
|
describe("#given valid circuit breaker settings", () => {
|
||||||
|
test("#when parsed #then returns nested config", () => {
|
||||||
|
const result = BackgroundTaskConfigSchema.parse({
|
||||||
|
circuitBreaker: {
|
||||||
|
maxToolCalls: 150,
|
||||||
|
windowSize: 10,
|
||||||
|
repetitionThresholdPercent: 70,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(result.circuitBreaker).toEqual({
|
||||||
|
maxToolCalls: 150,
|
||||||
|
windowSize: 10,
|
||||||
|
repetitionThresholdPercent: 70,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("#given windowSize below minimum", () => {
|
||||||
|
test("#when parsed #then throws ZodError", () => {
|
||||||
|
let thrownError: unknown
|
||||||
|
|
||||||
|
try {
|
||||||
|
BackgroundTaskConfigSchema.parse({
|
||||||
|
circuitBreaker: {
|
||||||
|
windowSize: 4,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
thrownError = error
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(thrownError).toBeInstanceOf(ZodError)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("#given repetitionThresholdPercent is zero", () => {
|
||||||
|
test("#when parsed #then throws ZodError", () => {
|
||||||
|
let thrownError: unknown
|
||||||
|
|
||||||
|
try {
|
||||||
|
BackgroundTaskConfigSchema.parse({
|
||||||
|
circuitBreaker: {
|
||||||
|
repetitionThresholdPercent: 0,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
thrownError = error
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(thrownError).toBeInstanceOf(ZodError)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -1,5 +1,11 @@
|
|||||||
import { z } from "zod"
|
import { z } from "zod"
|
||||||
|
|
||||||
|
const CircuitBreakerConfigSchema = z.object({
|
||||||
|
maxToolCalls: z.number().int().min(10).optional(),
|
||||||
|
windowSize: z.number().int().min(5).optional(),
|
||||||
|
repetitionThresholdPercent: z.number().gt(0).max(100).optional(),
|
||||||
|
})
|
||||||
|
|
||||||
export const BackgroundTaskConfigSchema = z.object({
|
export const BackgroundTaskConfigSchema = z.object({
|
||||||
defaultConcurrency: z.number().min(1).optional(),
|
defaultConcurrency: z.number().min(1).optional(),
|
||||||
providerConcurrency: z.record(z.string(), z.number().min(0)).optional(),
|
providerConcurrency: z.record(z.string(), z.number().min(0)).optional(),
|
||||||
@@ -13,6 +19,7 @@ export const BackgroundTaskConfigSchema = z.object({
|
|||||||
syncPollTimeoutMs: z.number().min(60000).optional(),
|
syncPollTimeoutMs: z.number().min(60000).optional(),
|
||||||
/** Maximum tool calls per subagent task before circuit breaker triggers (default: 200, minimum: 10). Prevents runaway loops from burning unlimited tokens. */
|
/** Maximum tool calls per subagent task before circuit breaker triggers (default: 200, minimum: 10). Prevents runaway loops from burning unlimited tokens. */
|
||||||
maxToolCalls: z.number().int().min(10).optional(),
|
maxToolCalls: z.number().int().min(10).optional(),
|
||||||
|
circuitBreaker: CircuitBreakerConfigSchema.optional(),
|
||||||
})
|
})
|
||||||
|
|
||||||
export type BackgroundTaskConfig = z.infer<typeof BackgroundTaskConfigSchema>
|
export type BackgroundTaskConfig = z.infer<typeof BackgroundTaskConfigSchema>
|
||||||
|
|||||||
Reference in New Issue
Block a user