mirror of
https://github.com/anomalyco/opencode.git
synced 2026-11-13 19:46:16 +03:00
feat(session-ui): show subagents ungrouped by default
This commit is contained in:
@@ -50,7 +50,7 @@ export const timelinePresets = [
|
||||
shell: { placement: "grouped", details: "collapsed" },
|
||||
edit: { placement: "grouped", details: "collapsed" },
|
||||
thinking: { placement: "grouped", details: "collapsed" },
|
||||
subagents: { placement: "grouped" },
|
||||
subagents: { placement: "separate" },
|
||||
notices: { placement: "grouped" },
|
||||
tools: { placement: "grouped" },
|
||||
commentary: { placement: "separate" },
|
||||
@@ -62,7 +62,7 @@ export const timelinePresets = [
|
||||
shell: { placement: "hidden", details: "collapsed" },
|
||||
edit: { placement: "grouped", details: "collapsed" },
|
||||
thinking: { placement: "hidden", details: "collapsed" },
|
||||
subagents: { placement: "grouped" },
|
||||
subagents: { placement: "separate" },
|
||||
notices: { placement: "hidden" },
|
||||
tools: { placement: "hidden" },
|
||||
commentary: { placement: "separate" },
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
webResearchDocument,
|
||||
} from "../storybook/current-session-fixtures"
|
||||
import { storyDocument, storyPatchFile, storyTool } from "../storybook/current-session-scenarios"
|
||||
import { timelinePresets } from "./detail"
|
||||
import { SessionTimeline } from "./session-timeline"
|
||||
|
||||
export default {
|
||||
@@ -75,6 +76,51 @@ export const DelegateFocusedTasks = {
|
||||
),
|
||||
}
|
||||
|
||||
const delegationDocument = storyDocument([
|
||||
storyTool("tool_delegation_glob", "glob", "completed", { pattern: "src/timeline/**/*.ts" }),
|
||||
storyTool("tool_delegation_grep", "grep", "completed", { pattern: "timelineDetail" }),
|
||||
storyTool("tool_delegation_read", "read", "completed", { path: "src/timeline/projection.ts" }),
|
||||
storyTool(
|
||||
"tool_delegation_explore",
|
||||
"subagent",
|
||||
"completed",
|
||||
{ agent: "explore", description: "Map the timeline grouping rules", prompt: "Find where tool rows are grouped." },
|
||||
{ output: "Grouping lives in the timeline projection.", metadata: { sessionID: "session_child_explore" } },
|
||||
),
|
||||
storyTool(
|
||||
"tool_delegation_review",
|
||||
"subagent",
|
||||
"completed",
|
||||
{ agent: "review", description: "Review the detail presets", prompt: "Check each timeline preset." },
|
||||
{ output: "Every preset is consistent.", metadata: { sessionID: "session_child_review" } },
|
||||
),
|
||||
storyTool("tool_delegation_read_tests", "read", "completed", { path: "src/timeline/rows-current.test.ts" }),
|
||||
storyTool("tool_delegation_grep_tests", "grep", "completed", { pattern: "subagent" }),
|
||||
storyTool(
|
||||
"tool_delegation_general",
|
||||
"subagent",
|
||||
"completed",
|
||||
{ agent: "general", description: "Run the focused timeline tests", prompt: "Run the timeline tests." },
|
||||
{ output: "All timeline tests pass.", metadata: { sessionID: "session_child_general" } },
|
||||
),
|
||||
{ type: "text", text: "Each delegated task keeps its own row while the reads and searches between them stay grouped." },
|
||||
])
|
||||
|
||||
export const DelegateBetweenTools = {
|
||||
args: { subagents: "separate" },
|
||||
argTypes: { subagents: { control: { type: "inline-radio" }, options: ["separate", "grouped"] } },
|
||||
render: (args: { subagents: "separate" | "grouped" }) => (
|
||||
<section class="mx-auto min-h-screen w-full max-w-[720px] bg-v2-background-bg-base p-6">
|
||||
<CurrentSessionProviders document={delegationDocument}>
|
||||
<SessionTimeline
|
||||
document={delegationDocument}
|
||||
timelineDetail={{ ...timelinePresets[2].value, subagents: { placement: args.subagents } }}
|
||||
/>
|
||||
</CurrentSessionProviders>
|
||||
</section>
|
||||
),
|
||||
}
|
||||
|
||||
function CodebaseExplorationStory() {
|
||||
const [state, setState] = createStore({ read: false, glob: false })
|
||||
|
||||
|
||||
@@ -1104,6 +1104,47 @@ describe("current session timeline rows", () => {
|
||||
])
|
||||
})
|
||||
|
||||
test.each([
|
||||
{
|
||||
name: "default",
|
||||
grouped: false,
|
||||
groups: [["context", "read", "grep"], ["part", "agent_1"], ["part", "agent_2"], ["context", "glob", "read_2"]],
|
||||
},
|
||||
{ name: "opted in", grouped: true, groups: [["context", "read", "grep", "agent_1", "agent_2", "glob", "read_2"]] },
|
||||
])("gives each subagent its own row unless subagent grouping is enabled ($name)", (input) => {
|
||||
const compact = timelinePresets.find((preset) => preset.id === "compact")!.value
|
||||
const rows = Timeline.constructSessionMessageRows(
|
||||
storyDocument([
|
||||
storyTool("read", "read", "completed", { path: "src/a.ts" }),
|
||||
storyTool("grep", "grep", "completed", { pattern: "agent" }),
|
||||
storyTool("agent_1", "subagent", "completed", { agent: "explore", description: "Map the code" }),
|
||||
storyTool("agent_2", "subagent", "completed", { agent: "general", description: "Check the tests" }),
|
||||
storyTool("glob", "glob", "completed", { pattern: "*.ts" }),
|
||||
storyTool("read_2", "read", "completed", { path: "src/b.ts" }),
|
||||
]).messages,
|
||||
true,
|
||||
{ type: "idle" },
|
||||
undefined,
|
||||
false,
|
||||
false,
|
||||
undefined,
|
||||
input.grouped ? { ...compact, subagents: { placement: "grouped" } } : compact,
|
||||
).rows
|
||||
|
||||
expect(
|
||||
rows.flatMap((row) =>
|
||||
!Predicate.isTagged(row, "AssistantPart")
|
||||
? []
|
||||
: [
|
||||
[
|
||||
row.group.type,
|
||||
...(row.group.type === "part" ? [row.group.ref] : row.group.refs).map((ref) => ref.partID),
|
||||
],
|
||||
],
|
||||
),
|
||||
).toEqual(input.groups.map((group) => [...group]))
|
||||
})
|
||||
|
||||
test("merges adjacent separate reads into one read row split by other parts", () => {
|
||||
const rows = Timeline.constructSessionMessageRows(
|
||||
storyDocument([
|
||||
|
||||
Reference in New Issue
Block a user