From 10b89a3b5552ef66bac163e24b7fcb9afd3c11eb Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 2 May 2026 05:46:03 +0100 Subject: [PATCH] refactor: remove parent fork config knob --- CHANGELOG.md | 2 +- docs/.generated/config-baseline.sha256 | 4 +- docs/gateway/config-agents.md | 4 - .../session-management-compaction.md | 2 +- src/agents/subagent-spawn.test-helpers.ts | 11 +-- src/agents/subagent-spawn.ts | 1 - src/auto-reply/reply/session-fork.ts | 20 +--- src/auto-reply/reply/session.test.ts | 93 +------------------ src/auto-reply/reply/session.ts | 1 - .../shared/legacy-config-migrate.test.ts | 18 ++++ ...egacy-config-migrations.runtime.session.ts | 25 +++++ src/config/schema.base.generated.ts | 13 --- src/config/schema.help.ts | 2 - src/config/schema.labels.ts | 1 - .../session-parent-fork-config-keys.test.ts | 28 ++++++ src/config/types.base.ts | 8 -- ...ema.session-maintenance-extensions.test.ts | 13 --- src/config/zod-schema.session.ts | 2 - 18 files changed, 80 insertions(+), 168 deletions(-) create mode 100644 src/config/session-parent-fork-config-keys.test.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index f875fddf882..a887a1d86df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5808,7 +5808,7 @@ Docs: https://docs.openclaw.ai - Slack/Threading: when `replyToMode="all"` auto-threads top-level Slack DMs, seed the thread session key from the message `ts` so the initial message and later replies share the same isolated `:thread:` session instead of falling back to base DM context. (#26849) Thanks @calder-sandy. - Agents/Subagents delivery: refactor subagent completion announce dispatch into an explicit queue/direct/fallback state machine, recover outbound channel-plugin resolution in cold/stale plugin-registry states across announce/message/gateway send paths, finalize cleanup bookkeeping when announce flow rejects, and treat Telegram sends without `message_id` as delivery failures (instead of false-success `"unknown"` IDs). (#26867, #25961, #26803, #25069, #26741) Thanks @SmithLabsLLC and @docaohieu2808. - Telegram/Webhook: pre-initialize webhook bots, switch webhook processing to callback-mode JSON handling, and preserve full near-limit payload reads under delayed handlers to prevent webhook request hangs and dropped updates. (#26156). -- Slack/Session threads: prevent oversized parent-session inheritance from silently bricking new thread sessions, surface embedded context-overflow empty-result failures to users, and share the PI parent-fork fallback between channel threads and subagents. The legacy `session.parentForkMaxTokens` compatibility guard remains available but is no longer the preferred tuning surface. (#26912) Thanks @markshields-tl. +- Slack/Session threads: prevent oversized parent-session inheritance from silently bricking new thread sessions, surface embedded context-overflow empty-result failures to users, and share the PI parent-fork fallback between channel threads and subagents. The old `session.parentForkMaxTokens` tuning surface is removed; `openclaw doctor --fix` strips it from legacy configs. (#26912) Thanks @markshields-tl. - Cron/Message multi-account routing: honor explicit `delivery.accountId` for isolated cron delivery resolution, and when `message.send` omits `accountId`, fall back to the sending agent's bound channel account instead of defaulting to the global account. (#27015, #26975) Thanks @lbo728 and @stakeswky. - Gateway/Message media roots: thread `agentId` through gateway `send` RPC and prefer explicit `agentId` over session/default resolution so non-default agent workspace media sends no longer fail with `LocalMediaAccessError`; added regression coverage for agent precedence and blank-agent fallback. (#23249) Thanks @Sid-Qin. - Followups/Routing: when explicit origin routing fails, allow same-channel fallback dispatch (while still blocking cross-channel fallback) so followup replies do not get dropped on transient origin-adapter failures. (#26109) Thanks @Sid-Qin. diff --git a/docs/.generated/config-baseline.sha256 b/docs/.generated/config-baseline.sha256 index ebc365c18de..23c54309dc5 100644 --- a/docs/.generated/config-baseline.sha256 +++ b/docs/.generated/config-baseline.sha256 @@ -1,4 +1,4 @@ -f40d6dea3b81c42d5af9e340f091d34b9e39321d171fade6115da594ba90522f config-baseline.json -40b1f91714d6f17e2718ea5d34c135550f5a39fe47f781cddc153cf3a59fe2e7 config-baseline.core.json +0020a49cdf07b79fddfed9584f10323ef77e3ca5c7f907d441c1f2e3f45932c9 config-baseline.json +8193fd771c9fa50e77c71ff69d41015e6dc02d140182ceea3baaa17713f04b18 config-baseline.core.json f42329d45c095881bd226bdb192c235980658fd250606d0c0badc2b12f12f5d3 config-baseline.channel.json af71b84b2411d8ccabcc6e09de0ee41f8212ff9869a6677698b6e7e3afdfaa47 config-baseline.plugin.json diff --git a/docs/gateway/config-agents.md b/docs/gateway/config-agents.md index 27695bcdc80..6bebcc11748 100644 --- a/docs/gateway/config-agents.md +++ b/docs/gateway/config-agents.md @@ -1210,10 +1210,6 @@ See [Multi-Agent Sandbox & Tools](/tools/multi-agent-sandbox-tools) for preceden - **`identityLinks`**: map canonical ids to provider-prefixed peers for cross-channel session sharing. Dock commands such as `/dock_discord` use the same map to switch the active session's reply route to another linked channel peer; see [Channel docking](/concepts/channel-docking). - **`reset`**: primary reset policy. `daily` resets at `atHour` local time; `idle` resets after `idleMinutes`. When both configured, whichever expires first wins. Daily reset freshness uses the session row's `sessionStartedAt`; idle reset freshness uses `lastInteractionAt`. Background/system-event writes such as heartbeat, cron wakeups, exec notifications, and gateway bookkeeping can update `updatedAt`, but they do not keep daily/idle sessions fresh. - **`resetByType`**: per-type overrides (`direct`, `group`, `thread`). Legacy `dm` accepted as alias for `direct`. -- **`parentForkMaxTokens`**: deprecated compatibility guard for the historical parent fork ceiling (default `100000`). - - Channel thread sessions and subagent `context="fork"` now use the same parent fork decision path. - - When the active parent branch is too large, OpenClaw starts with isolated context instead of failing or inheriting unusable history. - - Set `0` only if you intentionally want to disable this guard. - **`mainKey`**: legacy field. Runtime always uses `"main"` for the main direct-chat bucket. - **`agentToAgent.maxPingPongTurns`**: maximum reply-back turns between agents during agent-to-agent exchanges (integer, range: `0`–`5`). `0` disables ping-pong chaining. - **`sendPolicy`**: match by `channel`, `chatType` (`direct|group|channel`, with legacy `dm` alias), `keyPrefix`, or `rawKeyPrefix`. First deny wins. diff --git a/docs/reference/session-management-compaction.md b/docs/reference/session-management-compaction.md index 68ce3c3505d..f6f8712392a 100644 --- a/docs/reference/session-management-compaction.md +++ b/docs/reference/session-management-compaction.md @@ -148,7 +148,7 @@ Rules of thumb: - **Daily reset** (default 4:00 AM local time on the gateway host) creates a new `sessionId` on the next message after the reset boundary. - **Idle expiry** (`session.reset.idleMinutes` or legacy `session.idleMinutes`) creates a new `sessionId` when a message arrives after the idle window. When daily + idle are both configured, whichever expires first wins. - **System events** (heartbeat, cron wakeups, exec notifications, gateway bookkeeping) may mutate the session row but do not extend daily/idle reset freshness. Reset rollover discards queued system-event notices for the previous session before the fresh prompt is built. -- **Parent fork policy** uses PI's active branch when creating a thread or subagent fork. If that branch is too large, OpenClaw starts the child with isolated context instead of failing or inheriting unusable history. The legacy `session.parentForkMaxTokens` key remains as a deprecated compatibility guard; set `0` only if you intentionally want to disable it. +- **Parent fork policy** uses PI's active branch when creating a thread or subagent fork. If that branch is too large, OpenClaw starts the child with isolated context instead of failing or inheriting unusable history. The sizing policy is automatic; legacy `session.parentForkMaxTokens` config is removed by `openclaw doctor --fix`. Implementation detail: the decision happens in `initSessionState()` in `src/auto-reply/reply/session.ts`. diff --git a/src/agents/subagent-spawn.test-helpers.ts b/src/agents/subagent-spawn.test-helpers.ts index 28074f3d540..3d3a5b2cefc 100644 --- a/src/agents/subagent-spawn.test-helpers.ts +++ b/src/agents/subagent-spawn.test-helpers.ts @@ -184,15 +184,8 @@ export async function loadSubagentSpawnModuleForTest(params: { resolveContextEngine: params.resolveContextEngineMock ?? (async () => ({})), resolveParentForkDecision: params.resolveParentForkDecisionMock ?? - (async (forkParams: { - cfg?: { session?: { parentForkMaxTokens?: unknown } }; - parentEntry?: { totalTokens?: unknown }; - }) => { - const configured = forkParams.cfg?.session?.parentForkMaxTokens; - const maxTokens = - typeof configured === "number" && Number.isFinite(configured) && configured >= 0 - ? Math.floor(configured) - : 100_000; + (async (forkParams: { parentEntry?: { totalTokens?: unknown } }) => { + const maxTokens = 100_000; const parentTokens = typeof forkParams.parentEntry?.totalTokens === "number" && Number.isFinite(forkParams.parentEntry.totalTokens) diff --git a/src/agents/subagent-spawn.ts b/src/agents/subagent-spawn.ts index 3e6f7525245..fba5ffe0992 100644 --- a/src/agents/subagent-spawn.ts +++ b/src/agents/subagent-spawn.ts @@ -364,7 +364,6 @@ async function prepareSubagentSessionContext(params: { ); } const forkDecision = await subagentSpawnDeps.resolveParentForkDecision({ - cfg: params.cfg, parentEntry, storePath: parentTarget.storePath, }); diff --git a/src/auto-reply/reply/session-fork.ts b/src/auto-reply/reply/session-fork.ts index 737d9a1ad6b..b8ea340da02 100644 --- a/src/auto-reply/reply/session-fork.ts +++ b/src/auto-reply/reply/session-fork.ts @@ -1,5 +1,4 @@ import type { SessionEntry } from "../../config/sessions/types.js"; -import type { OpenClawConfig } from "../../config/types.openclaw.js"; /** * Default max parent token count beyond which thread/session parent forking is skipped. @@ -28,19 +27,6 @@ function loadSessionForkRuntime(): Promise= 0) { - return Math.floor(configured); - } - return DEFAULT_PARENT_FORK_MAX_TOKENS; -} - export function formatParentForkTooLargeMessage(params: { parentTokens: number; maxTokens: number; @@ -52,14 +38,10 @@ export function formatParentForkTooLargeMessage(params: { } export async function resolveParentForkDecision(params: { - cfg: OpenClawConfig; parentEntry: SessionEntry; storePath: string; }): Promise { - const maxTokens = resolveParentForkMaxTokens(params.cfg); - if (maxTokens <= 0) { - return { status: "fork", maxTokens }; - } + const maxTokens = DEFAULT_PARENT_FORK_MAX_TOKENS; const parentTokens = await resolveParentForkTokenCount({ parentEntry: params.parentEntry, storePath: params.storePath, diff --git a/src/auto-reply/reply/session.test.ts b/src/auto-reply/reply/session.test.ts index d342a6f633c..461ebef2f58 100644 --- a/src/auto-reply/reply/session.test.ts +++ b/src/auto-reply/reply/session.test.ts @@ -52,19 +52,8 @@ vi.mock("./session-fork.js", () => ({ sessionForkMocks.forkSessionFromParent(...args), resolveParentForkTokenCount: (...args: [{ parentEntry: SessionEntry; storePath: string }]) => sessionForkMocks.resolveParentForkTokenCount(...args), - resolveParentForkDecision: async (params: { - cfg: { session?: { parentForkMaxTokens?: unknown } }; - parentEntry: SessionEntry; - storePath: string; - }) => { - const configured = params.cfg.session?.parentForkMaxTokens; - const maxTokens = - typeof configured === "number" && Number.isFinite(configured) && configured >= 0 - ? Math.floor(configured) - : 100_000; - if (maxTokens <= 0) { - return { status: "fork", maxTokens }; - } + resolveParentForkDecision: async (params: { parentEntry: SessionEntry; storePath: string }) => { + const maxTokens = 100_000; const parentTokens = await sessionForkMocks.resolveParentForkTokenCount({ parentEntry: params.parentEntry, storePath: params.storePath, @@ -625,84 +614,6 @@ describe("initSessionState thread forking", () => { expect(sessionForkMocks.forkSessionFromParent).not.toHaveBeenCalled(); }); - it("respects session.parentForkMaxTokens override", async () => { - const root = await makeCaseDir("openclaw-thread-session-overflow-override-"); - const sessionsDir = path.join(root, "sessions"); - await fs.mkdir(sessionsDir); - - const parentSessionId = "parent-override"; - const parentSessionFile = path.join(sessionsDir, "parent.jsonl"); - const header = { - type: "session", - version: 3, - id: parentSessionId, - timestamp: new Date().toISOString(), - cwd: process.cwd(), - }; - const message = { - type: "message", - id: "m1", - parentId: null, - timestamp: new Date().toISOString(), - message: { role: "user", content: "Parent prompt" }, - }; - const assistantMessage = { - type: "message", - id: "m2", - parentId: "m1", - timestamp: new Date().toISOString(), - message: { role: "assistant", content: "Parent reply" }, - }; - await fs.writeFile( - parentSessionFile, - `${JSON.stringify(header)}\n${JSON.stringify(message)}\n${JSON.stringify(assistantMessage)}\n`, - "utf-8", - ); - - const storePath = path.join(root, "sessions.json"); - const parentSessionKey = "agent:main:slack:channel:c1"; - await writeSessionStoreFast(storePath, { - [parentSessionKey]: { - sessionId: parentSessionId, - sessionFile: parentSessionFile, - updatedAt: Date.now(), - totalTokens: 170_000, - }, - }); - - const cfg = { - session: { - store: storePath, - parentForkMaxTokens: 200_000, - }, - } as OpenClawConfig; - - const threadSessionKey = "agent:main:slack:channel:c1:thread:789"; - const result = await initSessionState({ - ctx: { - Body: "Thread reply", - SessionKey: threadSessionKey, - ParentSessionKey: parentSessionKey, - }, - cfg, - commandAuthorized: true, - }); - - expect(result.sessionEntry.forkedFromParent).toBe(true); - expect(result.sessionEntry.sessionFile).toBeTruthy(); - const forkedContent = await fs.readFile(result.sessionEntry.sessionFile ?? "", "utf-8"); - const headerLine = forkedContent.split(/\r?\n/).find((line) => line.trim().length > 0); - if (!headerLine) { - throw new Error("Missing session header"); - } - const parsedHeader = JSON.parse(headerLine) as { parentSession?: string }; - const expectedParentSession = await fs.realpath(parentSessionFile); - const actualParentSession = parsedHeader.parentSession - ? await fs.realpath(parsedHeader.parentSession) - : undefined; - expect(actualParentSession).toBe(expectedParentSession); - }); - it("records topic-specific session files when MessageThreadId is present", async () => { const root = await makeCaseDir("openclaw-topic-session-"); const storePath = path.join(root, "sessions.json"); diff --git a/src/auto-reply/reply/session.ts b/src/auto-reply/reply/session.ts index f12cf6f8298..877f8d0b44e 100644 --- a/src/auto-reply/reply/session.ts +++ b/src/auto-reply/reply/session.ts @@ -701,7 +701,6 @@ export async function initSessionState(params: { ) { const parentEntry = sessionStore[parentSessionKey]; const forkDecision = await resolveParentForkDecision({ - cfg, parentEntry, storePath, }); diff --git a/src/commands/doctor/shared/legacy-config-migrate.test.ts b/src/commands/doctor/shared/legacy-config-migrate.test.ts index 0a92548891b..2e9b13b92cc 100644 --- a/src/commands/doctor/shared/legacy-config-migrate.test.ts +++ b/src/commands/doctor/shared/legacy-config-migrate.test.ts @@ -41,6 +41,24 @@ describe("legacy session maintenance migrate", () => { }); }); +describe("legacy session parent fork migrate", () => { + it("removes legacy session.parentForkMaxTokens", () => { + const res = migrateLegacyConfigForTest({ + session: { + store: "sessions.json", + parentForkMaxTokens: 200_000, + }, + }); + + expect(res.config?.session).toEqual({ + store: "sessions.json", + }); + expect(res.changes).toContain( + "Removed session.parentForkMaxTokens; parent fork sizing is automatic.", + ); + }); +}); + describe("legacy thread binding spawn migrate", () => { it("moves matching split spawn flags to unified spawnSessions", () => { const res = migrateLegacyConfigForTest({ diff --git a/src/commands/doctor/shared/legacy-config-migrations.runtime.session.ts b/src/commands/doctor/shared/legacy-config-migrations.runtime.session.ts index 2626eae3ec7..9caef58b541 100644 --- a/src/commands/doctor/shared/legacy-config-migrations.runtime.session.ts +++ b/src/commands/doctor/shared/legacy-config-migrations.runtime.session.ts @@ -10,6 +10,11 @@ function hasLegacyRotateBytes(value: unknown): boolean { return Boolean(maintenance && Object.prototype.hasOwnProperty.call(maintenance, "rotateBytes")); } +function hasLegacyParentForkMaxTokens(value: unknown): boolean { + const session = getRecord(value); + return Boolean(session && Object.prototype.hasOwnProperty.call(session, "parentForkMaxTokens")); +} + const LEGACY_SESSION_MAINTENANCE_ROTATE_BYTES_RULE: LegacyConfigRule = { path: ["session", "maintenance"], message: @@ -17,6 +22,13 @@ const LEGACY_SESSION_MAINTENANCE_ROTATE_BYTES_RULE: LegacyConfigRule = { match: hasLegacyRotateBytes, }; +const LEGACY_SESSION_PARENT_FORK_MAX_TOKENS_RULE: LegacyConfigRule = { + path: ["session"], + message: + 'session.parentForkMaxTokens was removed; parent fork sizing is automatic. Run "openclaw doctor --fix" to remove it.', + match: hasLegacyParentForkMaxTokens, +}; + export const LEGACY_CONFIG_MIGRATIONS_RUNTIME_SESSION: LegacyConfigMigrationSpec[] = [ defineLegacyConfigMigration({ id: "session.maintenance.rotateBytes", @@ -31,4 +43,17 @@ export const LEGACY_CONFIG_MIGRATIONS_RUNTIME_SESSION: LegacyConfigMigrationSpec changes.push("Removed deprecated session.maintenance.rotateBytes."); }, }), + defineLegacyConfigMigration({ + id: "session.parentForkMaxTokens", + describe: "Remove legacy session.parentForkMaxTokens", + legacyRules: [LEGACY_SESSION_PARENT_FORK_MAX_TOKENS_RULE], + apply: (raw, changes) => { + const session = getRecord(raw.session); + if (!session || !Object.prototype.hasOwnProperty.call(session, "parentForkMaxTokens")) { + return; + } + delete session.parentForkMaxTokens; + changes.push("Removed session.parentForkMaxTokens; parent fork sizing is automatic."); + }, + }), ]; diff --git a/src/config/schema.base.generated.ts b/src/config/schema.base.generated.ts index a82b02c21b0..22ab4ed553c 100644 --- a/src/config/schema.base.generated.ts +++ b/src/config/schema.base.generated.ts @@ -20692,14 +20692,6 @@ export const GENERATED_BASE_CONFIG_SCHEMA: BaseConfigSchemaResponse = { description: 'Controls typing behavior timing: "never", "instant", "thinking", or "message" based emission points. Keep conservative modes in high-volume channels to avoid unnecessary typing noise.', }, - parentForkMaxTokens: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - title: "Deprecated Session Parent Fork Max Tokens", - description: - "Deprecated compatibility guard for the historical parent-session fork ceiling. OpenClaw now shares the parent fork decision between channel threads and subagents and falls back to isolated context when the active parent branch is too large; set 0 only to disable that guard intentionally.", - }, mainKey: { type: "string", title: "Session Main Key", @@ -27841,11 +27833,6 @@ export const GENERATED_BASE_CONFIG_SCHEMA: BaseConfigSchemaResponse = { help: 'Controls typing behavior timing: "never", "instant", "thinking", or "message" based emission points. Keep conservative modes in high-volume channels to avoid unnecessary typing noise.', tags: ["storage"], }, - "session.parentForkMaxTokens": { - label: "Deprecated Session Parent Fork Max Tokens", - help: "Deprecated compatibility guard for the historical parent-session fork ceiling. OpenClaw now shares the parent fork decision between channel threads and subagents and falls back to isolated context when the active parent branch is too large; set 0 only to disable that guard intentionally.", - tags: ["security", "auth", "performance", "storage"], - }, "session.mainKey": { label: "Session Main Key", help: 'Overrides the canonical main session key used for continuity when dmScope or routing logic points to "main". Use a stable value only if you intentionally need custom session anchoring.', diff --git a/src/config/schema.help.ts b/src/config/schema.help.ts index d14b6ad6db0..ea4b5548a85 100644 --- a/src/config/schema.help.ts +++ b/src/config/schema.help.ts @@ -1427,8 +1427,6 @@ export const FIELD_HELP: Record = { "Controls interval for repeated typing indicators while replies are being prepared in typing-capable channels. Increase to reduce chatty updates or decrease for more active typing feedback.", "session.typingMode": 'Controls typing behavior timing: "never", "instant", "thinking", or "message" based emission points. Keep conservative modes in high-volume channels to avoid unnecessary typing noise.', - "session.parentForkMaxTokens": - "Deprecated compatibility guard for the historical parent-session fork ceiling. OpenClaw now shares the parent fork decision between channel threads and subagents and falls back to isolated context when the active parent branch is too large; set 0 only to disable that guard intentionally.", "session.mainKey": 'Overrides the canonical main session key used for continuity when dmScope or routing logic points to "main". Use a stable value only if you intentionally need custom session anchoring.', "session.sendPolicy": diff --git a/src/config/schema.labels.ts b/src/config/schema.labels.ts index 412f2448c7c..4684a0dac0b 100644 --- a/src/config/schema.labels.ts +++ b/src/config/schema.labels.ts @@ -706,7 +706,6 @@ export const FIELD_LABELS: Record = { "session.store": "Session Store Path", "session.typingIntervalSeconds": "Session Typing Interval (seconds)", "session.typingMode": "Session Typing Mode", - "session.parentForkMaxTokens": "Deprecated Session Parent Fork Max Tokens", "session.mainKey": "Session Main Key", "session.sendPolicy": "Session Send Policy", "session.sendPolicy.default": "Session Send Policy Default Action", diff --git a/src/config/session-parent-fork-config-keys.test.ts b/src/config/session-parent-fork-config-keys.test.ts new file mode 100644 index 00000000000..7b3bc4588dc --- /dev/null +++ b/src/config/session-parent-fork-config-keys.test.ts @@ -0,0 +1,28 @@ +import { describe, expect, it } from "vitest"; +import { validateConfigObjectRaw } from "./validation.js"; + +describe("session parent fork config keys", () => { + it("rejects legacy session.parentForkMaxTokens with doctor guidance", () => { + const result = validateConfigObjectRaw({ + session: { + parentForkMaxTokens: 200_000, + }, + }); + + expect(result.ok).toBe(false); + if (result.ok) { + return; + } + expect(result.issues).toContainEqual( + expect.objectContaining({ + path: "session", + message: expect.stringContaining("session.parentForkMaxTokens was removed"), + }), + ); + expect(result.issues).toContainEqual( + expect.objectContaining({ + message: expect.stringContaining('Run "openclaw doctor --fix"'), + }), + ); + }); +}); diff --git a/src/config/types.base.ts b/src/config/types.base.ts index 31e05d802a9..8523fe53bc3 100644 --- a/src/config/types.base.ts +++ b/src/config/types.base.ts @@ -181,14 +181,6 @@ export type SessionConfig = { store?: string; typingIntervalSeconds?: number; typingMode?: TypingMode; - /** - * @deprecated Compatibility guard for the historical parent fork ceiling. - * OpenClaw now uses a shared parent fork decision path for channel threads - * and subagents, and falls back to isolated context when the active parent - * branch is too large. Set to 0 only if you intentionally want to disable - * that compatibility guard. - */ - parentForkMaxTokens?: number; mainKey?: string; sendPolicy?: SessionSendPolicyConfig; agentToAgent?: { diff --git a/src/config/zod-schema.session-maintenance-extensions.test.ts b/src/config/zod-schema.session-maintenance-extensions.test.ts index 9a26d07525d..6efe8b39907 100644 --- a/src/config/zod-schema.session-maintenance-extensions.test.ts +++ b/src/config/zod-schema.session-maintenance-extensions.test.ts @@ -14,19 +14,6 @@ describe("SessionSchema maintenance extensions", () => { ).not.toThrow(); }); - it("accepts deprecated parentForkMaxTokens including 0 to disable the guard", () => { - expect(() => SessionSchema.parse({ parentForkMaxTokens: 100_000 })).not.toThrow(); - expect(() => SessionSchema.parse({ parentForkMaxTokens: 0 })).not.toThrow(); - }); - - it("rejects negative parentForkMaxTokens", () => { - expect(() => - SessionSchema.parse({ - parentForkMaxTokens: -1, - }), - ).toThrow(/parentForkMaxTokens/i); - }); - it("accepts disabling reset archive cleanup", () => { expect(() => SessionSchema.parse({ diff --git a/src/config/zod-schema.session.ts b/src/config/zod-schema.session.ts index 7ef92ee1ddf..191d58f07c0 100644 --- a/src/config/zod-schema.session.ts +++ b/src/config/zod-schema.session.ts @@ -53,8 +53,6 @@ export const SessionSchema = z store: z.string().optional(), typingIntervalSeconds: z.number().int().positive().optional(), typingMode: TypingModeSchema.optional(), - /** @deprecated Compatibility guard for the historical parent fork ceiling. */ - parentForkMaxTokens: z.number().int().nonnegative().optional(), mainKey: z.string().optional(), sendPolicy: SessionSendPolicySchema.optional(), agentToAgent: z