fix(session): preserved auto-thinking level on classifier failure
- Kept the last successfully classified effort when a later classification fails. - Added regression coverage for the success-then-failure transition. Fixes #6877
This commit is contained in:
@@ -2,6 +2,10 @@
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Fixed
|
||||
|
||||
- Preserved the active auto-thinking effort when per-turn classification fails, avoiding an unnecessary full prompt-cache invalidation from reverting to the model's provisional default ([#6877](https://github.com/can1357/oh-my-pi/issues/6877)).
|
||||
|
||||
## [17.1.7] - 2026-07-27
|
||||
|
||||
### Fixed
|
||||
|
||||
@@ -581,9 +581,9 @@ export class ModelControls {
|
||||
|
||||
/**
|
||||
* Classify the current user turn and set the effective thinking level for it.
|
||||
* Bounded by a timeout + abort; on any failure (no smol model, timeout, parse
|
||||
* error) it falls back to the provisional concrete level and continues. Never
|
||||
* throws into the turn, and never clears `#autoThinking` (auto stays active).
|
||||
* Bounded by a timeout + abort; on failure it preserves the last classified
|
||||
* level, or uses the provisional concrete level before the first resolution.
|
||||
* Never throws into the turn, and never clears `#autoThinking`.
|
||||
*/
|
||||
async applyAutoThinkingLevel(promptText: string, generation: number): Promise<void> {
|
||||
const model = this.#model;
|
||||
@@ -625,7 +625,7 @@ export class ModelControls {
|
||||
|
||||
const effort = clampThinkingLevelToCeiling(
|
||||
model,
|
||||
resolved ?? resolveProvisionalAutoLevel(model),
|
||||
resolved ?? this.#autoResolvedLevel ?? resolveProvisionalAutoLevel(model),
|
||||
this.#thinkingLevelCeiling,
|
||||
);
|
||||
if (effort === undefined) return;
|
||||
|
||||
@@ -541,6 +541,34 @@ describe("AgentSession role model thinking behavior", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("preserves the resolved auto level when a later classification fails", async () => {
|
||||
const model = getAnthropicModelOrThrow("claude-sonnet-4-5");
|
||||
await createSession({
|
||||
initialModelId: model.id,
|
||||
initialThinkingLevel: Effort.High,
|
||||
modelRoles: { default: `${model.provider}/${model.id}` },
|
||||
});
|
||||
vi.spyOn(session.agent, "prompt").mockResolvedValue(undefined);
|
||||
vi.spyOn(autoThinkingClassifier, "classifyDifficulty")
|
||||
.mockResolvedValueOnce(Effort.Low)
|
||||
.mockRejectedValueOnce(new Error("classifier down"));
|
||||
|
||||
session.setThinkingLevel(AUTO_THINKING);
|
||||
await session.prompt("Handle a straightforward update");
|
||||
const receiptCount = session.sessionManager
|
||||
.getEntries()
|
||||
.filter(entry => entry.type === "thinking_level_change").length;
|
||||
await session.prompt("Investigate another update");
|
||||
|
||||
expect(session.configuredThinkingLevel()).toBe(AUTO_THINKING);
|
||||
expect(session.thinkingLevel).toBe(Effort.Low);
|
||||
expect(session.autoResolvedThinkingLevel()).toBe(Effort.Low);
|
||||
expect(session.agent.state.thinkingLevel).toBe(Effort.Low);
|
||||
expect(session.sessionManager.getEntries().filter(entry => entry.type === "thinking_level_change")).toHaveLength(
|
||||
receiptCount,
|
||||
);
|
||||
});
|
||||
|
||||
it("skips classification for synthetic turns", async () => {
|
||||
const model = getAnthropicModelOrThrow("claude-sonnet-4-5");
|
||||
await createSession({
|
||||
|
||||
Reference in New Issue
Block a user