Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions packages/coding-agent/src/modes/agents-view/agents-view-mode.ts
Comment thread
macroscopeapp[bot] marked this conversation as resolved.
Resolved
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ type AgentsViewRunResult = { type: "exit" } | { type: "open"; summary: SessionSu
type AgentsViewPersistentState = {
selectedRowIdentity?: string;
selectedSessionKey?: AgentsViewSelectionKey;
expandedSubagentParents?: string[];
statusMessage?: string;
initialPromptsSent?: boolean;
// Gathered once and reused across agents-view instances so the notices survive
Expand Down Expand Up @@ -232,8 +233,19 @@ export async function runAgentsViewMode(options: AgentsViewModeOptions): Promise
if (result.type === "exit") {
return;
}
persistentState.selectedRowIdentity = getSummaryIdentity(result.summary);
persistentState.selectedSessionKey = getAgentsViewSelectionKey(result.summary);
if (result.subagent) {
Comment thread
macroscopeapp[bot] marked this conversation as resolved.
Resolved
// Returning from a subagent reopens the agents view with its parent's
// list expanded and that subagent reselected.
persistentState.selectedRowIdentity = getSummaryIdentity(result.subagent);
persistentState.selectedSessionKey = getAgentsViewSelectionKey(result.subagent);
const parentIdentity = getSummaryIdentity(result.summary);
persistentState.expandedSubagentParents = [
...new Set([...(persistentState.expandedSubagentParents ?? []), parentIdentity]),
];
} else {
persistentState.selectedRowIdentity = getSummaryIdentity(result.summary);
persistentState.selectedSessionKey = getAgentsViewSelectionKey(result.summary);
}

let opened: { connection: DaemonAgentConnection; summary: SessionSummary } | undefined;
try {
Expand Down Expand Up @@ -324,6 +336,7 @@ class AgentsViewMode implements Component, Focusable {
this.selectedRowIdentity = persistentState.selectedRowIdentity;
this.selectedSessionKey = persistentState.selectedSessionKey;
this.selectedActiveSessionId = persistentState.selectedSessionKey?.activeSessionId;
this.expandedSubagentParents = new Set(persistentState.expandedSubagentParents ?? []);
this.keybindings = KeybindingsManager.create();
setKeybindings(this.keybindings);
setRegisteredThemes(options.uiServices.getThemes());
Expand Down Expand Up @@ -743,6 +756,7 @@ class AgentsViewMode implements Component, Focusable {
/** Rebuild rows from the last fetched summaries, keeping selection on the same row. */
private rebuildRows(): void {
const selectedIdentity = this.rows[this.selectedIndex]?.identity;
this.persistentState.expandedSubagentParents = [...this.expandedSubagentParents];
this.rows = buildAgentsViewRows(
this.lastVisibleSummaries,
this.expandedSubagentParents,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,7 @@ export class ChildAgentDetailComponent implements Component, Focusable {
private toolsExpanded = false;
private killConfirmExpiresAt = 0;
private killConfirmTimer: ReturnType<typeof setTimeout> | undefined;
private backHintLabel = "back to chat";

onCancel?: () => void;
onToggleToolsExpanded?: () => void;
Expand All @@ -613,6 +614,10 @@ export class ChildAgentDetailComponent implements Component, Focusable {
this.rebuildTranscriptComponents();
}

setBackHintLabel(label: string): void {
this.backHintLabel = label;
}

setToolsExpanded(expanded: boolean): void {
this.toolsExpanded = expanded;
for (const component of this.transcriptComponents) {
Expand Down Expand Up @@ -848,7 +853,7 @@ export class ChildAgentDetailComponent implements Component, Focusable {
? theme.fg("error", `${keyText("app.agents.delete", { primaryOnly: true }).trim()} again to stop`)
: keyAction("app.agents.delete", "stop", { primaryOnly: true });
return hintLine(
[keyAction("app.agents.back", "back to chat", { primaryOnly: true }), expandAction, stopAction],
[keyAction("app.agents.back", this.backHintLabel, { primaryOnly: true }), expandAction, stopAction],
width,
);
}
Expand Down
30 changes: 24 additions & 6 deletions packages/coding-agent/src/modes/interactive/interactive-mode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,7 @@ export class InteractiveMode {
private childAgentNodes: ChildAgentInspectorNode[] = [];
private childAgentDetailNodeId: string | undefined;
private childAgentPanelMode: "detail" | undefined;
private enteredSessionViaSubagentDetail = false;

// Tool output expansion state
private toolOutputExpanded = false;
Expand Down Expand Up @@ -686,7 +687,13 @@ export class InteractiveMode {
getHideThinkingBlock: () => this.hideThinkingBlock,
getHiddenThinkingLabel: () => this.hiddenThinkingLabel,
});
this.childAgentDetail.onCancel = () => this.closeChildAgentPanel({ selectNodeId: this.childAgentDetailNodeId });
this.childAgentDetail.onCancel = () => {
if (this.options.returnToAgentsView && this.enteredSessionViaSubagentDetail) {
void this.returnToAgentsView();
return;
}
this.closeChildAgentPanel({ selectNodeId: this.childAgentDetailNodeId });
};
this.childAgentDetail.onToggleToolsExpanded = () => this.toggleToolOutputExpansion();
this.childAgentDetail.onKill = (nodeId) => void this.killChildAgent(nodeId);
this.widgetContainerAbove = new Container();
Expand Down Expand Up @@ -978,11 +985,18 @@ export class InteractiveMode {

// Jump straight into a subagent's read-only detail view when the agents
// view opened this session targeting one of its subagents.
if (this.options.initialSubagentNodeId && !this.openChildAgentDetail(this.options.initialSubagentNodeId)) {
// The subagent can finish and get released between the agents view
// listing it and this session attaching; say so instead of silently
// landing in the parent chat.
this.showStatus("Subagent already finished; showing its parent session");
if (this.options.initialSubagentNodeId) {
if (this.openChildAgentDetail(this.options.initialSubagentNodeId)) {
if (this.options.returnToAgentsView) {
this.enteredSessionViaSubagentDetail = true;
this.childAgentDetail.setBackHintLabel("back to agents");
}
} else {
// The subagent can finish and get released between the agents view
// listing it and this session attaching; say so instead of silently
// landing in the parent chat.
this.showStatus("Subagent already finished; showing its parent session");
}
}

// Set up theme file watcher
Expand Down Expand Up @@ -3105,6 +3119,8 @@ export class InteractiveMode {
// Re-render queued previews cleared on panel entry; the queue may still hold messages.
this.updatePendingMessagesDisplay();
this.childAgentDetailNodeId = undefined;
this.enteredSessionViaSubagentDetail = false;
this.childAgentDetail.setBackHintLabel("back to chat");
this.childAgentDetail.setNode(undefined);
}
this.childAgentPanelMode = undefined;
Expand Down Expand Up @@ -4652,6 +4668,8 @@ export class InteractiveMode {
private closeChildAgentPanel(options: { selectNodeId?: string } = {}): void {
this.childAgentPanelMode = undefined;
this.childAgentDetailNodeId = undefined;
this.enteredSessionViaSubagentDetail = false;
Comment thread
cursor[bot] marked this conversation as resolved.
Resolved
this.childAgentDetail.setBackHintLabel("back to chat");
this.childAgentDetail.setNode(undefined);
this.childAgentSummary.setHidden(false);
this.restoreMainAgentView();
Expand Down
14 changes: 12 additions & 2 deletions packages/coding-agent/test/daemon-list-format.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,19 @@ describe("formatSessionListTable", () => {
const table = stripAnsi(
formatSessionListTable(
[
makeSummary({ name: "sleep", id: "019e71ec-e08a-75a9-b573-fc10e9f8380f", lifecycle: "archived", activity: "idle" }),
makeSummary({
name: "sleep",
id: "019e71ec-e08a-75a9-b573-fc10e9f8380f",
lifecycle: "archived",
activity: "idle",
}),
makeSummary({ name: "tool", id: "ccccddddeeee", lifecycle: "live", activity: "working" }),
makeSummary({ name: "crash", id: "019e71ec-e08a-75a9-b573-abcdef123456", lifecycle: "archived", activity: "idle" }),
makeSummary({
name: "crash",
id: "019e71ec-e08a-75a9-b573-abcdef123456",
lifecycle: "archived",
activity: "idle",
}),
makeSummary({ name: "idle", id: "bbbbccccdddd", lifecycle: "live", activity: "idle" }),
makeSummary({ name: "model", id: "ddddeeeeffff", lifecycle: "live", activity: "working" }),
makeSummary({
Expand Down
Loading