From b9f80a87b5ae4f18eba4ca246401d9ae5f176f53 Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Sun, 8 Mar 2026 02:22:21 +0900 Subject: [PATCH] feat(background-task): add spawn limit config fields Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus --- assets/oh-my-opencode.schema.json | 10 +++++ src/config/schema/background-task.test.ts | 48 +++++++++++++++++++++++ src/config/schema/background-task.ts | 2 + 3 files changed, 60 insertions(+) diff --git a/assets/oh-my-opencode.schema.json b/assets/oh-my-opencode.schema.json index a8710453c..3c5dae067 100644 --- a/assets/oh-my-opencode.schema.json +++ b/assets/oh-my-opencode.schema.json @@ -3678,6 +3678,16 @@ "minimum": 0 } }, + "maxDepth": { + "type": "integer", + "minimum": 1, + "maximum": 9007199254740991 + }, + "maxDescendants": { + "type": "integer", + "minimum": 1, + "maximum": 9007199254740991 + }, "staleTimeoutMs": { "type": "number", "minimum": 60000 diff --git a/src/config/schema/background-task.test.ts b/src/config/schema/background-task.test.ts index 2ca225864..9bd6c74de 100644 --- a/src/config/schema/background-task.test.ts +++ b/src/config/schema/background-task.test.ts @@ -3,6 +3,54 @@ import { ZodError } from "zod/v4" import { BackgroundTaskConfigSchema } from "./background-task" describe("BackgroundTaskConfigSchema", () => { + describe("maxDepth", () => { + describe("#given valid maxDepth (3)", () => { + test("#when parsed #then returns correct value", () => { + const result = BackgroundTaskConfigSchema.parse({ maxDepth: 3 }) + + expect(result.maxDepth).toBe(3) + }) + }) + + describe("#given maxDepth below minimum (0)", () => { + test("#when parsed #then throws ZodError", () => { + let thrownError: unknown + + try { + BackgroundTaskConfigSchema.parse({ maxDepth: 0 }) + } catch (error) { + thrownError = error + } + + expect(thrownError).toBeInstanceOf(ZodError) + }) + }) + }) + + describe("maxDescendants", () => { + describe("#given valid maxDescendants (50)", () => { + test("#when parsed #then returns correct value", () => { + const result = BackgroundTaskConfigSchema.parse({ maxDescendants: 50 }) + + expect(result.maxDescendants).toBe(50) + }) + }) + + describe("#given maxDescendants below minimum (0)", () => { + test("#when parsed #then throws ZodError", () => { + let thrownError: unknown + + try { + BackgroundTaskConfigSchema.parse({ maxDescendants: 0 }) + } catch (error) { + thrownError = error + } + + expect(thrownError).toBeInstanceOf(ZodError) + }) + }) + }) + describe("syncPollTimeoutMs", () => { describe("#given valid syncPollTimeoutMs (120000)", () => { test("#when parsed #then returns correct value", () => { diff --git a/src/config/schema/background-task.ts b/src/config/schema/background-task.ts index b955de6b5..f53a67f6c 100644 --- a/src/config/schema/background-task.ts +++ b/src/config/schema/background-task.ts @@ -4,6 +4,8 @@ export const BackgroundTaskConfigSchema = z.object({ defaultConcurrency: z.number().min(1).optional(), providerConcurrency: z.record(z.string(), z.number().min(0)).optional(), modelConcurrency: z.record(z.string(), z.number().min(0)).optional(), + maxDepth: z.number().int().min(1).optional(), + maxDescendants: z.number().int().min(1).optional(), /** Stale timeout in milliseconds - interrupt tasks with no activity for this duration (default: 180000 = 3 minutes, minimum: 60000 = 1 minute) */ staleTimeoutMs: z.number().min(60000).optional(), /** Timeout for tasks that never received any progress update, falling back to startedAt (default: 600000 = 10 minutes, minimum: 60000 = 1 minute) */