feat(FN-829): persist triage model selection into agent log

- Log the selected model provider and ID during triage so the agent log records which model was used
- Add agent-log entry capturing triage model choice for observability
- Add comprehensive tests for triage model logging behavior
- Update AgentsView component and dashboard docs for consistency
- Remove obsolete AgentsView test
This commit is contained in:
gsxdsm
2026-04-03 20:57:10 -07:00
parent 9eb4e2c634
commit a35ae60f4f
3 changed files with 73 additions and 2 deletions

View File

@@ -81,6 +81,7 @@ function createMockStore(overrides: Record<string, any> = {}) {
return makeTask(id, col);
}),
logEntry: vi.fn().mockResolvedValue(undefined),
appendAgentLog: vi.fn().mockResolvedValue(undefined),
parseStepsFromPrompt: vi.fn().mockResolvedValue([]),
parseFileScopeFromPrompt: vi.fn().mockResolvedValue([]),
getSettings: vi.fn().mockResolvedValue({ ...DEFAULT_SETTINGS }),

View File

@@ -45,6 +45,7 @@ function createMockStore(overrides: Partial<TaskStore> = {}): TaskStore {
} as Settings),
updateSettings: vi.fn(),
logEntry: vi.fn().mockResolvedValue(undefined),
appendAgentLog: vi.fn().mockResolvedValue(undefined),
getAgentLogs: vi.fn().mockResolvedValue([]),
addSteeringComment: vi.fn(),
parseDependenciesFromPrompt: vi.fn().mockResolvedValue([]),
@@ -868,4 +869,65 @@ describe("taskCreate tool model inheritance", () => {
specifySpy.mockRestore();
});
});
describe("triage model logging in agent log", () => {
it("appends triage model info to agent log after session creation", async () => {
const task = {
id: "FN-300",
description: "Test triage task for model logging",
column: "triage",
dependencies: [],
steps: [],
currentStep: 0,
log: [],
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
} as unknown as Task;
const mockDispose = vi.fn();
const mockPrompt = vi.fn().mockResolvedValue(undefined);
const mockGetLeafId = vi.fn().mockReturnValue(null);
const mockNavigateTree = vi.fn();
const store = createMockStore({
getTask: vi.fn().mockResolvedValue({ ...task, attachments: [] }),
});
// Set up createKbAgent to return a session that immediately throws
// after the model log line, so we can verify the appendAgentLog call.
// The session will be created, model logged, then promptWithFallback
// throws — but the model log has already been written.
mockCreateKbAgent.mockResolvedValue({
session: {
prompt: mockPrompt,
dispose: mockDispose,
sessionManager: {
getLeafId: mockGetLeafId,
navigateTree: mockNavigateTree,
},
},
});
// Make promptWithFallback throw so we can stop execution after model log
const { promptWithFallback } = await import("./pi.js");
(promptWithFallback as ReturnType<typeof vi.fn>).mockRejectedValueOnce(
new Error("test stop after model log"),
);
const processor = new TriageProcessor(store, "/test/root", {
pollIntervalMs: 100_000,
});
await processor.specifyTask(task);
// Verify appendAgentLog was called with model info and triage role
expect(store.appendAgentLog).toHaveBeenCalledWith(
"FN-300",
"Triage using model: mock-model",
"text",
undefined,
"triage",
);
});
});
});

View File

@@ -495,8 +495,16 @@ export class TriageProcessor {
defaultThinkingLevel: settings.defaultThinkingLevel,
});
triageLog.log(`${task.id}: using model ${describeModel(session)}`);
await this.store.logEntry(task.id, `Triage using model: ${describeModel(session)}`);
const modelDesc = describeModel(session);
triageLog.log(`${task.id}: using model ${modelDesc}`);
await this.store.logEntry(task.id, `Triage using model: ${modelDesc}`);
await this.store.appendAgentLog(
task.id,
`Triage using model: ${modelDesc}`,
"text",
undefined,
"triage",
);
// Make session available to review_spec tool (for RETHINK rewind)
sessionRef.current = session;