mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 09:20:43 +00:00
refactor: remove parent fork config knob
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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`.
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -364,7 +364,6 @@ async function prepareSubagentSessionContext(params: {
|
||||
);
|
||||
}
|
||||
const forkDecision = await subagentSpawnDeps.resolveParentForkDecision({
|
||||
cfg: params.cfg,
|
||||
parentEntry,
|
||||
storePath: parentTarget.storePath,
|
||||
});
|
||||
|
||||
@@ -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<typeof import("./session-fork.runtime
|
||||
return sessionForkRuntimePromise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated compatibility guard for deployments that explicitly tuned the
|
||||
* historical thread fork ceiling. New behavior should use the shared parent
|
||||
* fork decision helper so channel threads and subagents degrade the same way.
|
||||
*/
|
||||
export function resolveParentForkMaxTokens(cfg: OpenClawConfig): number {
|
||||
const configured = cfg.session?.parentForkMaxTokens;
|
||||
if (typeof configured === "number" && Number.isFinite(configured) && configured >= 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<ParentForkDecision> {
|
||||
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,
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -701,7 +701,6 @@ export async function initSessionState(params: {
|
||||
) {
|
||||
const parentEntry = sessionStore[parentSessionKey];
|
||||
const forkDecision = await resolveParentForkDecision({
|
||||
cfg,
|
||||
parentEntry,
|
||||
storePath,
|
||||
});
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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.");
|
||||
},
|
||||
}),
|
||||
];
|
||||
|
||||
@@ -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.',
|
||||
|
||||
@@ -1427,8 +1427,6 @@ export const FIELD_HELP: Record<string, string> = {
|
||||
"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":
|
||||
|
||||
@@ -706,7 +706,6 @@ export const FIELD_LABELS: Record<string, string> = {
|
||||
"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",
|
||||
|
||||
28
src/config/session-parent-fork-config-keys.test.ts
Normal file
28
src/config/session-parent-fork-config-keys.test.ts
Normal file
@@ -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"'),
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -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?: {
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user