Merge nucleic/calm-yarn-robin-cmec into dev

This commit is contained in:
2026-07-18 00:33:08 -07:00
parent f8a0d690e3
commit 8f67ed6dd1
4 changed files with 46 additions and 0 deletions
@@ -0,0 +1,33 @@
import SwiftUI
import NucleicProtocol
/// Pretty rendering of an `ExitPlanMode` tool call — the phone echo of the Mac's `ExitPlanModeCard`.
/// The agent calls `ExitPlanMode` to present the plan it wrote on its way out of plan mode; the raw
/// tool card reads as escaped JSON with an unrendered Markdown blob, so instead we render the plan
/// body as formatted Markdown under a "Plan" header. The plan is on the call input, so the card
/// shows the moment the call arrives — before, and regardless of, the user's approval. Mirrors
/// `AskUserQuestionResultCard`'s accent-tinted card so a presented plan reads as a first-class moment.
struct ExitPlanModeCard: View {
let plan: ExitPlanMode.Plan
private var accent: Color { Palette.accent }
var body: some View {
VStack(alignment: .leading, spacing: 10) {
HStack(spacing: 8) {
Image(systemName: "list.bullet.clipboard")
.font(.caption).foregroundStyle(accent).frame(width: 15)
Text("Plan")
.font(.callout.weight(.medium))
Spacer(minLength: 0)
}
MarkdownText(markdown: plan.markdown)
.textSelection(.enabled)
}
.padding(.horizontal, 12).padding(.vertical, 10)
.frame(maxWidth: .infinity, alignment: .leading)
.background(accent.opacity(0.06))
.overlay(RoundedRectangle(cornerRadius: 8).strokeBorder(accent.opacity(0.16), lineWidth: 1))
.clipShape(RoundedRectangle(cornerRadius: 8))
}
}
@@ -581,6 +581,7 @@ enum ToolGlyph {
case "Task", "Agent", ToolGroup.orchestraSubagentToolName: return "person.2"
case "TodoWrite": return "checklist"
case "AskUserQuestion": return "questionmark.bubble"
case ExitPlanMode.toolName: return "list.bullet.clipboard"
case HostCommandSummary.hostExecToolName: return "desktopcomputer"
default: return "wrench.and.screwdriver"
}
@@ -115,6 +115,7 @@ struct ToolGroup: Equatable {
name == "Task" || name == "Agent" || name == Self.orchestraSubagentToolName
}
var isAskUserQuestion: Bool { name == "AskUserQuestion" }
var isExitPlanMode: Bool { name == ExitPlanMode.toolName }
/// The literal shell command a `Bash` call ran, if any (nil for every other tool). Used to
/// detect a git-commit pipeline that should read as a structured commit card at the row level,
@@ -24,6 +24,8 @@ struct TranscriptRow: View {
SubagentCard(group: group)
} else if let card = answeredQuestionCard(group) {
card
} else if let plan = planCard(group) {
plan
} else if let card = gitCommitRowCard(group) {
card
} else if group.isHostExec {
@@ -78,6 +80,15 @@ struct TranscriptRow: View {
return AskUserQuestionResultCard(questions: questions, answers: answers)
}
/// The plan an `ExitPlanMode` call presents, rendered as formatted Markdown rather than the
/// escaped-JSON blob the generic tool card would show — the phone echo of the Mac's `planCard`.
/// Nil for any other tool (which keeps the normal collapsible card) and for a call with no plan
/// text. The plan is on the call input, so it shows whether or not the user has approved it yet.
private func planCard(_ group: ToolGroup) -> ExitPlanModeCard? {
guard group.isExitPlanMode, let plan = ExitPlanMode.plan(from: group.input) else { return nil }
return ExitPlanModeCard(plan: plan)
}
/// A git-commit `Bash` pipeline rendered as the structured commit card the Mac shows at the row
/// level (subject + Markdown body + the new hash + "Show command"), or nil for any non-commit
/// call — which keeps the normal collapsible tool card. Mirrors the Mac's `gitCommitCard`.