mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-07-21 02:05:45 +00:00
* feat(subagents): show runtime metadata on task cards * fix(subagents): stop task-card render loop and dedupe model fetches Address code review on the runtime-metadata cards: - P1 render loop: the terminal ToolMessage is re-parsed on every MessageList render and always carries modelName/usage, so the presence-based setTasks condition fired a fresh state object each render -> "Maximum update depth exceeded". computeNextSubtask now returns a value-compared `changed` flag and a pure subtaskNotification() routes terminal transitions through the deferred after-render path while skipping no-op re-parses. - Per-card useModels refetch: add staleTime: Infinity to the ["models"] query so every subtask card shares one /api/models fetch instead of refetching on each mount. * make format * refactor(subagents): dedupe token-usage validators + tidy event narrowing Address PR review follow-ups: - DRY: extract one shared token-usage validator per side. Backend status_contract.normalize_token_usage() now backs both the terminal ToolMessage metadata and the subagent.step/.end run events (step_events.py), and frontend messages/usage.normalizeTokenUsage() backs both the live task_running event (lifecycle.ts) and the terminal ToolMessage metadata (subtask-result.ts). Prevents the input/output/ total_tokens validation from drifting across the four former copies. - Nit: onCustomEvent narrows event.type once instead of re-checking the object shape per branch; the redundant task_started early-return (already validated by taskEventToSubtaskUpdate) is dropped.
43 lines
1.0 KiB
TypeScript
43 lines
1.0 KiB
TypeScript
import { describe, expect, it } from "@rstest/core";
|
|
|
|
import { taskEventToSubtaskUpdate } from "@/core/tasks/lifecycle";
|
|
|
|
describe("taskEventToSubtaskUpdate", () => {
|
|
it("maps a task-start event to the effective model for that task", () => {
|
|
expect(
|
|
taskEventToSubtaskUpdate({
|
|
type: "task_started",
|
|
task_id: "call-1",
|
|
description: "Research auth",
|
|
model_name: "claude-3-7-sonnet",
|
|
}),
|
|
).toEqual({
|
|
id: "call-1",
|
|
modelName: "claude-3-7-sonnet",
|
|
});
|
|
});
|
|
|
|
it("maps a running event to its cumulative token snapshot", () => {
|
|
expect(
|
|
taskEventToSubtaskUpdate({
|
|
type: "task_running",
|
|
task_id: "call-1",
|
|
model_name: "claude-3-7-sonnet",
|
|
usage: {
|
|
input_tokens: 100,
|
|
output_tokens: 20,
|
|
total_tokens: 120,
|
|
},
|
|
}),
|
|
).toEqual({
|
|
id: "call-1",
|
|
modelName: "claude-3-7-sonnet",
|
|
usage: {
|
|
inputTokens: 100,
|
|
outputTokens: 20,
|
|
totalTokens: 120,
|
|
},
|
|
});
|
|
});
|
|
});
|