mirror of
https://github.com/Kilo-Org/kilocode.git
synced 2026-09-19 01:51:21 +08:00
fix(vscode): keep background subagent cards collapsed and cap reasoning
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"kilo-code": patch
|
||||
---
|
||||
|
||||
Keep background subagent task cards collapsed and show their reasoning as a compact preview instead of expanding while the agent runs.
|
||||
@@ -162,6 +162,9 @@ export interface MessagePartProps {
|
||||
* lets that one nested item open instead of every file in the patch. */
|
||||
forceOpenFile?: string
|
||||
reasoningAutoCollapse?: boolean
|
||||
/** Show reasoning as a capped preview that starts open and never auto-expands
|
||||
* while streaming. Used for background subagent transcripts. */
|
||||
reasoningCapped?: boolean
|
||||
/** True when the stream has moved past this reasoning part. Encrypted
|
||||
* reasoning items hold every summary's `time.end` until the whole item
|
||||
* finishes, so the caller settles finished summaries from the part order. */
|
||||
@@ -1081,6 +1084,7 @@ export function Part(props: MessagePartProps) {
|
||||
forceOpen={props.forceOpen}
|
||||
forceOpenFile={props.forceOpenFile}
|
||||
reasoningAutoCollapse={props.reasoningAutoCollapse}
|
||||
reasoningCapped={props.reasoningCapped}
|
||||
settled={props.settled}
|
||||
showAssistantCopyPartID={props.showAssistantCopyPartID}
|
||||
showTurnDiffSummary={props.showTurnDiffSummary}
|
||||
@@ -1884,12 +1888,15 @@ PART_MAPPING["reasoning"] = function ReasoningPartDisplay(props: MessagePartProp
|
||||
|
||||
// Auto-collapse mode: streaming or streamed this session -> open (capped),
|
||||
// historical -> collapsed, unless the user toggled it. Expanded mode: open
|
||||
// unless the user explicitly collapsed this reasoning part.
|
||||
const initial = props.reasoningAutoCollapse
|
||||
? !userCollapsed.has(id) && (streamed.has(id) || userOpened.has(id))
|
||||
: !userCollapsed.has(id)
|
||||
// unless the user explicitly collapsed this reasoning part. Background
|
||||
// transcripts always start open in the capped preview so they stay compact.
|
||||
const capped = () => props.reasoningAutoCollapse || props.reasoningCapped
|
||||
const initial =
|
||||
props.reasoningAutoCollapse && !props.reasoningCapped
|
||||
? !userCollapsed.has(id) && (streamed.has(id) || userOpened.has(id))
|
||||
: !userCollapsed.has(id)
|
||||
const [open, setOpen] = createSignal(initial)
|
||||
const [manual, setManual] = createSignal(props.reasoningAutoCollapse && userOpened.has(id))
|
||||
const [manual, setManual] = createSignal(capped() && userOpened.has(id))
|
||||
const title = createMemo(() => {
|
||||
const value = view().title
|
||||
if (value) return value
|
||||
@@ -1908,7 +1915,7 @@ PART_MAPPING["reasoning"] = function ReasoningPartDisplay(props: MessagePartProp
|
||||
const track = (value: boolean) => {
|
||||
if (value) userCollapsed.delete(id)
|
||||
else rememberReasoningState(userCollapsed, id)
|
||||
if (props.reasoningAutoCollapse) {
|
||||
if (capped()) {
|
||||
if (value) rememberReasoningState(userOpened, id)
|
||||
else userOpened.delete(id)
|
||||
setManual(value)
|
||||
@@ -1924,7 +1931,7 @@ PART_MAPPING["reasoning"] = function ReasoningPartDisplay(props: MessagePartProp
|
||||
createEffect(() => {
|
||||
if (!props.forceOpen || open()) return
|
||||
userCollapsed.delete(id)
|
||||
if (props.reasoningAutoCollapse) {
|
||||
if (capped()) {
|
||||
rememberReasoningState(userOpened, id)
|
||||
setManual(true)
|
||||
}
|
||||
@@ -2007,7 +2014,7 @@ PART_MAPPING["reasoning"] = function ReasoningPartDisplay(props: MessagePartProp
|
||||
<div
|
||||
data-component="reasoning-part"
|
||||
data-streaming={!done() ? "" : undefined}
|
||||
data-auto-collapse={props.reasoningAutoCollapse ? "" : undefined}
|
||||
data-auto-collapse={capped() ? "" : undefined}
|
||||
data-manual={manual() ? "" : undefined}
|
||||
>
|
||||
<Show
|
||||
|
||||
@@ -1294,6 +1294,7 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper
|
||||
message.sessionID,
|
||||
message.title,
|
||||
this.getWorkspaceDirectory(message.parentSessionID),
|
||||
message.background === true,
|
||||
)
|
||||
break
|
||||
case "saveImage":
|
||||
|
||||
@@ -21,7 +21,7 @@ export class SubAgentViewerProvider implements vscode.Disposable {
|
||||
private readonly context: vscode.ExtensionContext,
|
||||
) {}
|
||||
|
||||
openPanel(sessionID: string, title?: string, directory?: string): void {
|
||||
openPanel(sessionID: string, title?: string, directory?: string, background?: boolean): void {
|
||||
const existing = this.panels.get(sessionID)
|
||||
if (existing) {
|
||||
if (directory) this.providers.get(sessionID)?.setSessionDirectory(sessionID, directory)
|
||||
@@ -61,7 +61,7 @@ export class SubAgentViewerProvider implements vscode.Disposable {
|
||||
if (msg.type !== "webviewReady") return
|
||||
readyDisposable.dispose()
|
||||
|
||||
provider.postMessage({ type: "viewSubAgentSession", sessionID })
|
||||
provider.postMessage({ type: "viewSubAgentSession", sessionID, background })
|
||||
void provider.loadMessages(sessionID)
|
||||
|
||||
try {
|
||||
|
||||
@@ -598,8 +598,8 @@ export async function activate(context: vscode.ExtensionContext) {
|
||||
),
|
||||
vscode.commands.registerCommand(
|
||||
"kilo-code.new.openSubAgentViewer",
|
||||
(sessionID: string, title?: string, directory?: string) => {
|
||||
subAgentViewerProvider.openPanel(sessionID, title, directory)
|
||||
(sessionID: string, title?: string, directory?: string, background?: boolean) => {
|
||||
subAgentViewerProvider.openPanel(sessionID, title, directory, background)
|
||||
},
|
||||
),
|
||||
vscode.commands.registerCommand("kilo-code.new.agentManager.previousSession", () => {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { describe, expect, it } from "bun:test"
|
||||
import {
|
||||
backgroundAgents,
|
||||
backgroundChildren,
|
||||
backgroundJobAgents,
|
||||
fitBackgroundAgents,
|
||||
showBackgroundAgent,
|
||||
@@ -73,6 +74,33 @@ describe("fitBackgroundAgents", () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe("backgroundChildren", () => {
|
||||
it("collects only children spawned with the background flag", () => {
|
||||
const tools = [
|
||||
taskPart({ id: "part_1", child: "ses_a", background: true }),
|
||||
taskPart({ id: "part_2", child: "ses_b", background: false }),
|
||||
taskPart({ id: "part_3", child: "ses_c" }),
|
||||
]
|
||||
|
||||
expect([...backgroundChildren(tools)]).toEqual(["ses_a"])
|
||||
})
|
||||
|
||||
it("reads the flag from either the state or the part metadata", () => {
|
||||
const tools = [
|
||||
taskPart({ id: "part_1", child: "ses_a", background: true }),
|
||||
taskPart({ id: "part_2", child: "ses_b", background: true, onPart: true }),
|
||||
]
|
||||
|
||||
expect([...backgroundChildren(tools)].sort()).toEqual(["ses_a", "ses_b"])
|
||||
})
|
||||
|
||||
it("ignores non-task tools and parts without a child session", () => {
|
||||
const bash = { id: "part_3", type: "tool", tool: "bash", state: { status: "running", input: {} } } as ToolPart
|
||||
|
||||
expect([...backgroundChildren([bash, taskPart({ id: "part_4", background: true })])]).toEqual([])
|
||||
})
|
||||
})
|
||||
|
||||
describe("backgroundAgents", () => {
|
||||
it("lists a running background agent from tool state metadata", () => {
|
||||
const tools = [taskPart({ child: "ses_child", background: true, description: "Audit deps", agent: "explore" })]
|
||||
|
||||
@@ -11,7 +11,7 @@ import { IconButton } from "@kilocode/kilo-ui/icon-button"
|
||||
import { createEffect, createMemo, on, type Accessor, type Component } from "solid-js"
|
||||
import { DataBridge } from "../src/App"
|
||||
import { ChatView } from "../src/components/chat"
|
||||
import { children } from "../src/components/chat/background-agents"
|
||||
import { children, backgroundChildren } from "../src/components/chat/background-agents"
|
||||
import { useLanguage } from "../src/context/language"
|
||||
import { SessionProvider, useSession, useSessionVisibility } from "../src/context/session"
|
||||
import { description, label, type Activity } from "../src/utils/session-activity"
|
||||
@@ -32,7 +32,7 @@ interface Props {
|
||||
onClosePanel: () => void
|
||||
}
|
||||
|
||||
const SubagentChat: Component<{ active: Accessor<string | undefined> }> = (props) => {
|
||||
const SubagentChat: Component<{ active: Accessor<string | undefined>; capped: Accessor<boolean> }> = (props) => {
|
||||
const session = useSession()
|
||||
|
||||
createEffect(
|
||||
@@ -44,12 +44,22 @@ const SubagentChat: Component<{ active: Accessor<string | undefined> }> = (props
|
||||
|
||||
return (
|
||||
<DataBridge>
|
||||
<ChatView readonly interactivePrompts={false} promptBoxId="agent-manager:subagent" />
|
||||
<ChatView
|
||||
readonly
|
||||
interactivePrompts={false}
|
||||
reasoningCapped={props.capped()}
|
||||
promptBoxId="agent-manager:subagent"
|
||||
/>
|
||||
</DataBridge>
|
||||
)
|
||||
}
|
||||
|
||||
const SubagentContent: Component<Props & { activity: (id: string) => Activity }> = (props) => {
|
||||
interface ContentProps extends Props {
|
||||
activity: (id: string) => Activity
|
||||
background: Accessor<ReadonlySet<string>>
|
||||
}
|
||||
|
||||
const SubagentContent: Component<ContentProps> = (props) => {
|
||||
const session = useSession()
|
||||
const language = useLanguage()
|
||||
const ids = () => props.tabs().map((tab) => tab.id)
|
||||
@@ -131,7 +141,7 @@ const SubagentContent: Component<Props & { activity: (id: string) => Activity }>
|
||||
}}
|
||||
/>
|
||||
<div class="am-subagent-chat">
|
||||
<SubagentChat active={props.active} />
|
||||
<SubagentChat active={props.active} capped={() => props.background().has(props.active() ?? "")} />
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
@@ -145,10 +155,15 @@ export const SubagentPanel: Component<Props> = (props) => {
|
||||
const id = session.currentSessionID()
|
||||
return id ? children(session.getSessionToolParts(id)) : []
|
||||
})
|
||||
// Background subagent transcripts show reasoning as a compact capped preview.
|
||||
const background = createMemo(() => {
|
||||
const id = session.currentSessionID()
|
||||
return id ? backgroundChildren(session.getSessionToolParts(id)) : new Set<string>()
|
||||
})
|
||||
return (
|
||||
<AgentAvatarPalette ids={siblings()}>
|
||||
<SessionProvider>
|
||||
<SubagentContent {...props} activity={session.activityFor} />
|
||||
<SubagentContent {...props} activity={session.activityFor} background={background} />
|
||||
</SessionProvider>
|
||||
</AgentAvatarPalette>
|
||||
)
|
||||
|
||||
@@ -14,6 +14,7 @@ import { ChatView } from "./components/chat"
|
||||
import { SidebarEmptyState } from "./components/chat/SidebarEmptyState"
|
||||
import { SidebarTopBar } from "./components/chat/SidebarTopBar"
|
||||
import { openSubagent } from "./components/chat/open-subagent"
|
||||
import { backgroundChildren } from "./components/chat/background-agents"
|
||||
import { registerExpandedTaskTool } from "./components/chat/TaskToolExpanded"
|
||||
import { registerVscodeToolOverrides } from "./components/chat/VscodeToolOverrides"
|
||||
import { useWorktreeMode } from "./context/worktree-mode"
|
||||
@@ -132,10 +133,12 @@ export const DataBridge: Component<{ children: any }> = (props) => {
|
||||
|
||||
const openAgent = (id: string, title?: string) => {
|
||||
const parent = session.sessions().find((item) => item.id === id)?.parentID ?? session.currentSessionID()
|
||||
const background = parent ? backgroundChildren(session.getSessionToolParts(parent)).has(id) : false
|
||||
openSubagent({
|
||||
sessionID: id,
|
||||
title,
|
||||
parentSessionID: parent,
|
||||
background,
|
||||
worktree: !!worktree,
|
||||
post: vscode.postMessage,
|
||||
})
|
||||
@@ -243,6 +246,7 @@ const AppContent: Component = () => {
|
||||
const [currentView, setCurrentView] = createSignal<ViewType>("newTask")
|
||||
const [settingsTab, setSettingsTab] = createSignal<string | undefined>()
|
||||
const [agentManagerProjectId, setAgentManagerProjectId] = createSignal<string | undefined>()
|
||||
const [subAgentCapped, setSubAgentCapped] = createSignal(false)
|
||||
const [migration, setMigration] = createSignal(false)
|
||||
const session = useSession()
|
||||
const tabs = useLocalTabs()
|
||||
@@ -345,6 +349,7 @@ const AppContent: Component = () => {
|
||||
handleForked(message)
|
||||
if (message?.type === "viewSubAgentSession" && message.sessionID) {
|
||||
console.log("[Kilo New] App: 🔍 viewSubAgentSession:", message.sessionID)
|
||||
setSubAgentCapped(message.background === true)
|
||||
session.setCurrentSessionID(message.sessionID)
|
||||
setCurrentView("subAgentViewer")
|
||||
}
|
||||
@@ -439,7 +444,7 @@ const AppContent: Component = () => {
|
||||
/>
|
||||
</Match>
|
||||
<Match when={currentView() === "subAgentViewer"}>
|
||||
<ChatView readonly />
|
||||
<ChatView readonly reasoningCapped={subAgentCapped()} />
|
||||
</Match>
|
||||
</Switch>
|
||||
}
|
||||
|
||||
@@ -117,6 +117,8 @@ interface AssistantMessageProps {
|
||||
highlight?: () => TimelineHighlight | undefined
|
||||
readonly?: boolean
|
||||
interactivePrompts?: boolean
|
||||
/** Show reasoning as a compact capped preview (background subagent transcripts). */
|
||||
reasoningCapped?: boolean
|
||||
}
|
||||
|
||||
type ToolStateProps = {
|
||||
@@ -364,6 +366,7 @@ export const AssistantMessage: Component<AssistantMessageProps> = (props) => {
|
||||
forceOpen={forceOpen()}
|
||||
forceOpenFile={forceOpen() ? props.forceOpenFile : undefined}
|
||||
reasoningAutoCollapse={display.reasoningAutoCollapse()}
|
||||
reasoningCapped={props.reasoningCapped}
|
||||
settled={settled()}
|
||||
feedback={props.feedback}
|
||||
throughput={throughputEl()}
|
||||
|
||||
@@ -196,6 +196,7 @@ export const BackgroundAgents: Component<{ readonly?: boolean }> = (props) => {
|
||||
sessionID: agent.id,
|
||||
title: agent.description,
|
||||
parentSessionID: session.currentSessionID(),
|
||||
background: true,
|
||||
worktree: !!worktree,
|
||||
post: vscode.postMessage,
|
||||
})
|
||||
|
||||
@@ -40,6 +40,8 @@ interface ChatViewProps {
|
||||
onForkMessage?: (sessionId: string, messageId: string) => void
|
||||
onForkSession?: (sessionId: string) => void
|
||||
readonly?: boolean
|
||||
/** Show reasoning as a compact capped preview (background subagent transcripts). */
|
||||
reasoningCapped?: boolean
|
||||
/** Whether this chat owns actionable prompt controls. Defaults to true. */
|
||||
interactivePrompts?: boolean
|
||||
/** When true, show the "Continue in Worktree" button. Defaults to true in the sidebar. */
|
||||
@@ -399,6 +401,7 @@ export const ChatView: Component<ChatViewProps> = (props) => {
|
||||
questions={standaloneQuestions}
|
||||
suggestions={standaloneSuggestions}
|
||||
readonly={props.readonly}
|
||||
reasoningCapped={props.reasoningCapped}
|
||||
interactivePrompts={ownsPrompts()}
|
||||
emptyState={props.emptyState}
|
||||
introduction={props.introduction}
|
||||
|
||||
@@ -96,6 +96,8 @@ interface MessageListProps {
|
||||
suggestions?: () => SuggestionRequest[]
|
||||
/** When true (subagent viewer), replace the welcome screen with an initializing indicator */
|
||||
readonly?: boolean
|
||||
/** Show reasoning as a compact capped preview (background subagent transcripts). */
|
||||
reasoningCapped?: boolean
|
||||
/** Whether inline questions and suggestions are actionable on this surface. */
|
||||
interactivePrompts?: boolean
|
||||
queuedDisabled?: boolean
|
||||
@@ -1362,6 +1364,7 @@ export const MessageList: Component<MessageListProps> = (props) => {
|
||||
activeSearchPartFile={activeKey() === row.key ? activeMatch()?.partFile : undefined}
|
||||
readonly={props.readonly}
|
||||
interactivePrompts={props.interactivePrompts}
|
||||
reasoningCapped={props.reasoningCapped}
|
||||
/>
|
||||
)}
|
||||
</Virtualizer>
|
||||
@@ -1382,6 +1385,7 @@ export const MessageList: Component<MessageListProps> = (props) => {
|
||||
activeSearchPartFile={activeKey() === key ? activeMatch()?.partFile : undefined}
|
||||
readonly={props.readonly}
|
||||
interactivePrompts={props.interactivePrompts}
|
||||
reasoningCapped={props.reasoningCapped}
|
||||
/>
|
||||
)}
|
||||
</For>
|
||||
@@ -1404,6 +1408,7 @@ export const MessageList: Component<MessageListProps> = (props) => {
|
||||
activeSearchPartFile={activeKey() === row.key ? activeMatch()?.partFile : undefined}
|
||||
readonly={props.readonly}
|
||||
interactivePrompts={props.interactivePrompts}
|
||||
reasoningCapped={props.reasoningCapped}
|
||||
/>
|
||||
)}
|
||||
</For>
|
||||
|
||||
@@ -59,6 +59,16 @@ const TaskToolRenderer: Component<ToolProps> = (props) => {
|
||||
)
|
||||
|
||||
const running = createMemo(() => taskRunning(props.status))
|
||||
// Background task cards stay collapsed: they must not auto-open or show the
|
||||
// "Starting..." status, which would flicker the transcript as the child runs.
|
||||
// The input carries `background` from the first part update; promoted tasks
|
||||
// only gain the state metadata flag later.
|
||||
const backgroundTask = createMemo(
|
||||
() =>
|
||||
props.input.background === true ||
|
||||
((props.partMetadata as Record<string, unknown> | undefined)?.background ??
|
||||
(props.metadata as Record<string, unknown> | undefined)?.background) === true,
|
||||
)
|
||||
const avatar = createMemo(() => {
|
||||
const id = childSessionId()
|
||||
return taskAvatarStatus(id, props.status, session.allStatusMap())
|
||||
@@ -77,6 +87,10 @@ const TaskToolRenderer: Component<ToolProps> = (props) => {
|
||||
{ defer: true },
|
||||
),
|
||||
)
|
||||
// Auto-open only once the call is running: while "pending" the streamed
|
||||
// input cannot yet tell a background task from a foreground one, and a
|
||||
// background card must never open on its own.
|
||||
const auto = () => props.status === "running" && !backgroundTask()
|
||||
// BasicTool's forceOpen effect only fires onOpenChange on a false->true
|
||||
// transition — a virtualized remount that starts with forceOpen already
|
||||
// true never transitions, so this local signal must also seed itself from
|
||||
@@ -86,10 +100,27 @@ const TaskToolRenderer: Component<ToolProps> = (props) => {
|
||||
initialOpen({
|
||||
tool: props.tool,
|
||||
partID: props.partID,
|
||||
defaultOpen: running(),
|
||||
defaultOpen: auto(),
|
||||
forceOpen: props.forceOpen,
|
||||
}),
|
||||
)
|
||||
// The open state is controlled so the card settles once the input arrives.
|
||||
// A stored preference, a search match, or a manual toggle wins over it.
|
||||
const [touched, setTouched] = createSignal(
|
||||
!!props.forceOpen || initialOpen({ tool: props.tool, partID: props.partID }) !== undefined,
|
||||
)
|
||||
const change = (value: boolean) => {
|
||||
setTouched(true)
|
||||
setOpen(value)
|
||||
}
|
||||
createEffect(() => {
|
||||
if (touched()) return
|
||||
if (backgroundTask()) {
|
||||
setOpen(false)
|
||||
return
|
||||
}
|
||||
if (props.status === "running") setOpen(true)
|
||||
})
|
||||
|
||||
let synced: string | undefined
|
||||
createEffect(() => {
|
||||
@@ -171,6 +202,7 @@ const TaskToolRenderer: Component<ToolProps> = (props) => {
|
||||
sessionID: id,
|
||||
title: description(),
|
||||
parentSessionID: session.currentSessionID(),
|
||||
background: backgroundTask(),
|
||||
worktree: !!worktree,
|
||||
post: vscode.postMessage,
|
||||
})
|
||||
@@ -240,14 +272,15 @@ const TaskToolRenderer: Component<ToolProps> = (props) => {
|
||||
tool={props.tool}
|
||||
partID={props.partID}
|
||||
trigger={trigger()}
|
||||
defaultOpen={running()}
|
||||
defaultOpen={auto()}
|
||||
open={open()}
|
||||
forceOpen={props.forceOpen}
|
||||
defer
|
||||
onOpenChange={setOpen}
|
||||
onOpenChange={change}
|
||||
>
|
||||
<div ref={viewport} onScroll={autoScroll.handleScroll} data-component="tool-output" data-scrollable>
|
||||
<div ref={content} data-component="task-tools">
|
||||
<Show when={running() && childToolCount() === 0}>
|
||||
<Show when={running() && childToolCount() === 0 && !backgroundTask()}>
|
||||
<div data-slot="task-tool-item" data-state="starting">
|
||||
<span data-slot="task-tool-title">{language.t("session.messages.taskStarting")}</span>
|
||||
</div>
|
||||
|
||||
@@ -31,6 +31,8 @@ interface TranscriptRowViewProps {
|
||||
activeSearchPartFile?: string
|
||||
readonly?: boolean
|
||||
interactivePrompts?: boolean
|
||||
/** Show reasoning as a compact capped preview (background subagent transcripts). */
|
||||
reasoningCapped?: boolean
|
||||
queuedDisabled?: boolean
|
||||
editDisabled?: boolean
|
||||
}
|
||||
@@ -113,6 +115,7 @@ export const TranscriptRowView: Component<TranscriptRowViewProps> = (props) => {
|
||||
highlight={props.highlight}
|
||||
readonly={props.readonly}
|
||||
interactivePrompts={props.interactivePrompts}
|
||||
reasoningCapped={props.reasoningCapped}
|
||||
feedback={{
|
||||
enabled: feedback.telemetryEnabled(),
|
||||
rating: feedback.getRating(row().message.id),
|
||||
|
||||
@@ -78,6 +78,18 @@ export function children(tools: ToolPart[]): string[] {
|
||||
return ids
|
||||
}
|
||||
|
||||
/** Child session IDs spawned as background jobs, which show a capped reasoning preview. */
|
||||
export function backgroundChildren(tools: ToolPart[]): Set<string> {
|
||||
const ids = new Set<string>()
|
||||
for (const part of tools) {
|
||||
if (part.tool !== "task") continue
|
||||
if (meta(part, "background") !== true) continue
|
||||
const id = text(meta(part, "sessionId"))
|
||||
if (id) ids.add(id)
|
||||
}
|
||||
return ids
|
||||
}
|
||||
|
||||
function working(status: SessionStatusInfo | undefined): boolean {
|
||||
return status?.type === "busy" || status?.type === "retry"
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@ interface OpenSubagent {
|
||||
sessionID: string
|
||||
title?: string
|
||||
parentSessionID?: string
|
||||
/** True for async background agents, whose reasoning shows a capped preview. */
|
||||
background?: boolean
|
||||
/** True inside Agent Manager, where the inspector replaces the editor tab. */
|
||||
worktree: boolean
|
||||
post: (message: WebviewMessage) => void
|
||||
@@ -32,5 +34,6 @@ export function openSubagent(input: OpenSubagent) {
|
||||
sessionID: input.sessionID,
|
||||
title: input.title,
|
||||
parentSessionID: input.parentSessionID,
|
||||
background: input.background,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1296,6 +1296,8 @@ export interface EnhancePromptErrorMessage {
|
||||
export interface ViewSubAgentSessionMessage {
|
||||
type: "viewSubAgentSession"
|
||||
sessionID: string
|
||||
/** True for async background agents, whose reasoning shows a capped preview. */
|
||||
background?: boolean
|
||||
}
|
||||
|
||||
export interface DiffViewerContextMessage {
|
||||
|
||||
@@ -1261,6 +1261,8 @@ export interface OpenSubAgentViewerRequest {
|
||||
sessionID: string
|
||||
title?: string
|
||||
parentSessionID?: string
|
||||
/** True for async background agents, whose reasoning shows a capped preview. */
|
||||
background?: boolean
|
||||
}
|
||||
|
||||
// Preview an image attachment in VS Code's built-in image viewer
|
||||
|
||||
Reference in New Issue
Block a user