feat(core): promote top-level maxTurns to runConfig.max_turns at convert time

Wires the new top-level `maxTurns` field into the existing runtime configuration
pipeline so the value declared in agent frontmatter actually limits the agent's
turn budget at run time. When both the top-level `maxTurns` and the legacy
nested `runConfig.max_turns` are set, the top-level field wins (more specific
and matches the CC frontmatter shape upstream agent files use). When only the
nested field is set, behavior is unchanged.

Refs #4821 #4721 #4732
This commit is contained in:
LaZzyMan 2026-06-08 14:58:04 +08:00
parent 70889cba35
commit 9b903ee41a
2 changed files with 36 additions and 0 deletions

View file

@ -1862,6 +1862,38 @@ System prompt 3`);
expect(runtimeConfig.modelConfig).toEqual({});
});
// --- CC 2.1.168 maxTurns top-level promotion ---
it('should populate runConfig.max_turns from top-level maxTurns', async () => {
const cfg: SubagentConfig = { ...validConfig, maxTurns: 42 };
const runtimeConfig = await manager.convertToRuntimeConfig(cfg);
expect(runtimeConfig.runConfig.max_turns).toBe(42);
});
it('should prefer top-level maxTurns over nested runConfig.max_turns', async () => {
const cfg: SubagentConfig = {
...validConfig,
maxTurns: 99,
runConfig: { max_turns: 5 },
};
const runtimeConfig = await manager.convertToRuntimeConfig(cfg);
expect(runtimeConfig.runConfig.max_turns).toBe(99);
});
it('should fall back to nested runConfig.max_turns when maxTurns is unset', async () => {
const cfg: SubagentConfig = {
...validConfig,
runConfig: { max_turns: 7 },
};
const runtimeConfig = await manager.convertToRuntimeConfig(cfg);
expect(runtimeConfig.runConfig.max_turns).toBe(7);
});
it('should leave max_turns undefined when neither is set', async () => {
const runtimeConfig = await manager.convertToRuntimeConfig(validConfig);
expect(runtimeConfig.runConfig.max_turns).toBeUndefined();
});
});
describe('mergeConfigurations', () => {

View file

@ -853,6 +853,10 @@ export class SubagentManager {
const runConfig: RunConfig = {
...config.runConfig,
// Top-level CC-style `maxTurns` wins over legacy nested
// `runConfig.max_turns`. Both are kept for backward compatibility, but
// when both are set, the top-level field is the authoritative source.
...(config.maxTurns !== undefined ? { max_turns: config.maxTurns } : {}),
};
let toolConfig: ToolConfig | undefined;