Skip to content

Commit 423b321

Browse files
committed
fix(agents): consume per-agent verboseDefault and elevatedDefault in directive resolution
Codex review on PR #74643 found that schema/types/docs accept `verboseDefault` and `elevatedDefault` per-agent (under `agents.list[]`), but the runtime resolver still falls back to global `agentCfg` defaults — `getReply` passes `cfg.agents?.defaults` as `agentCfg`, so per-agent values were stored but never read on actual replies. The reasoning/fastMode paths already consult `agentEntry` first; verbose and elevated did not. Wire the same agentEntry-first precedence for verbose and elevated: - `src/auto-reply/reply/directive-handling.levels.ts`: extend the `agentEntry` parameter type with `verboseDefault`/`elevatedDefault`, and check `agentEntry?.verboseDefault` and `agentEntry?.elevatedDefault` before falling back to `agentCfg?.*`. - `src/auto-reply/reply/get-reply-directives.ts`: same agentEntry-first fallback for `resolvedVerboseLevel` and `resolvedElevatedLevel`. Session and explicit-directive precedence preserved. Add 6 regression tests in `directive-handling.levels.test.ts`: - per-agent verboseDefault wins over agentCfg verboseDefault - agentCfg verboseDefault still applies when agentEntry is absent - session verboseLevel wins over per-agent verboseDefault - per-agent elevatedDefault wins over agentCfg elevatedDefault - agentCfg elevatedDefault still applies when agentEntry is absent - session elevatedLevel wins over per-agent elevatedDefault Refs #73680
1 parent ec802fe commit 423b321

3 files changed

Lines changed: 110 additions & 0 deletions

File tree

src/auto-reply/reply/directive-handling.levels.test.ts

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,4 +164,108 @@ describe("resolveCurrentDirectiveLevels", () => {
164164

165165
expect(result.currentReasoningLevel).toBe("off");
166166
});
167+
168+
// Regression for #73680 / PR #74643 P2: verbose and elevated defaults must
169+
// honor per-agent values from agentEntry before falling back to the global
170+
// agentCfg defaults; otherwise saving a per-agent value has no runtime effect.
171+
172+
it("prefers per-agent verboseDefault over agentCfg verboseDefault", async () => {
173+
const resolveDefaultThinkingLevel = vi.fn().mockResolvedValue("off");
174+
175+
const result = await resolveCurrentDirectiveLevels({
176+
sessionEntry: {},
177+
agentEntry: {
178+
verboseDefault: "high",
179+
},
180+
agentCfg: {
181+
verboseDefault: "low",
182+
},
183+
resolveDefaultThinkingLevel,
184+
});
185+
186+
expect(result.currentVerboseLevel).toBe("high");
187+
});
188+
189+
it("falls back to agentCfg verboseDefault when agent entry is absent", async () => {
190+
const resolveDefaultThinkingLevel = vi.fn().mockResolvedValue("off");
191+
192+
const result = await resolveCurrentDirectiveLevels({
193+
sessionEntry: {},
194+
agentCfg: {
195+
verboseDefault: "low",
196+
},
197+
resolveDefaultThinkingLevel,
198+
});
199+
200+
expect(result.currentVerboseLevel).toBe("low");
201+
});
202+
203+
it("prefers session verboseLevel over per-agent verboseDefault", async () => {
204+
const resolveDefaultThinkingLevel = vi.fn().mockResolvedValue("off");
205+
206+
const result = await resolveCurrentDirectiveLevels({
207+
sessionEntry: {
208+
verboseLevel: "low",
209+
},
210+
agentEntry: {
211+
verboseDefault: "high",
212+
},
213+
agentCfg: {
214+
verboseDefault: "off",
215+
},
216+
resolveDefaultThinkingLevel,
217+
});
218+
219+
expect(result.currentVerboseLevel).toBe("low");
220+
});
221+
222+
it("prefers per-agent elevatedDefault over agentCfg elevatedDefault", async () => {
223+
const resolveDefaultThinkingLevel = vi.fn().mockResolvedValue("off");
224+
225+
const result = await resolveCurrentDirectiveLevels({
226+
sessionEntry: {},
227+
agentEntry: {
228+
elevatedDefault: "on",
229+
},
230+
agentCfg: {
231+
elevatedDefault: "off",
232+
},
233+
resolveDefaultThinkingLevel,
234+
});
235+
236+
expect(result.currentElevatedLevel).toBe("on");
237+
});
238+
239+
it("falls back to agentCfg elevatedDefault when agent entry is absent", async () => {
240+
const resolveDefaultThinkingLevel = vi.fn().mockResolvedValue("off");
241+
242+
const result = await resolveCurrentDirectiveLevels({
243+
sessionEntry: {},
244+
agentCfg: {
245+
elevatedDefault: "off",
246+
},
247+
resolveDefaultThinkingLevel,
248+
});
249+
250+
expect(result.currentElevatedLevel).toBe("off");
251+
});
252+
253+
it("prefers session elevatedLevel over per-agent elevatedDefault", async () => {
254+
const resolveDefaultThinkingLevel = vi.fn().mockResolvedValue("off");
255+
256+
const result = await resolveCurrentDirectiveLevels({
257+
sessionEntry: {
258+
elevatedLevel: "off",
259+
},
260+
agentEntry: {
261+
elevatedDefault: "on",
262+
},
263+
agentCfg: {
264+
elevatedDefault: "on",
265+
},
266+
resolveDefaultThinkingLevel,
267+
});
268+
269+
expect(result.currentElevatedLevel).toBe("off");
270+
});
167271
});

src/auto-reply/reply/directive-handling.levels.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ export async function resolveCurrentDirectiveLevels(params: {
1111
agentEntry?: {
1212
fastModeDefault?: unknown;
1313
reasoningDefault?: unknown;
14+
verboseDefault?: unknown;
15+
elevatedDefault?: unknown;
1416
};
1517
agentCfg?: {
1618
thinkingDefault?: unknown;
@@ -39,6 +41,7 @@ export async function resolveCurrentDirectiveLevels(params: {
3941
: undefined;
4042
const currentVerboseLevel =
4143
(params.sessionEntry?.verboseLevel as VerboseLevel | undefined) ??
44+
(params.agentEntry?.verboseDefault as VerboseLevel | undefined) ??
4245
(params.agentCfg?.verboseDefault as VerboseLevel | undefined);
4346
const currentReasoningLevel =
4447
(params.sessionEntry?.reasoningLevel as ReasoningLevel | undefined) ??
@@ -47,6 +50,7 @@ export async function resolveCurrentDirectiveLevels(params: {
4750
"off";
4851
const currentElevatedLevel =
4952
(params.sessionEntry?.elevatedLevel as ElevatedLevel | undefined) ??
53+
(params.agentEntry?.elevatedDefault as ElevatedLevel | undefined) ??
5054
(params.agentCfg?.elevatedDefault as ElevatedLevel | undefined);
5155
return {
5256
currentThinkLevel,

src/auto-reply/reply/get-reply-directives.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,7 @@ export async function resolveReplyDirectives(params: {
431431
const resolvedVerboseLevel =
432432
directives.verboseLevel ??
433433
(targetSessionEntry?.verboseLevel as VerboseLevel | undefined) ??
434+
(agentEntry?.verboseDefault as VerboseLevel | undefined) ??
434435
(agentCfg?.verboseDefault as VerboseLevel | undefined);
435436
const configuredReasoningDefault =
436437
(agentEntry?.reasoningDefault as ReasoningLevel | undefined) ??
@@ -460,6 +461,7 @@ export async function resolveReplyDirectives(params: {
460461
const resolvedElevatedLevel = elevatedAllowed
461462
? (directives.elevatedLevel ??
462463
(targetSessionEntry?.elevatedLevel as ElevatedLevel | undefined) ??
464+
(agentEntry?.elevatedDefault as ElevatedLevel | undefined) ??
463465
(agentCfg?.elevatedDefault as ElevatedLevel | undefined) ??
464466
"on")
465467
: "off";

0 commit comments

Comments
 (0)