Merge nucleic/calm-yarn-robin-cmec into dev
This commit is contained in:
@@ -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`.
|
||||
|
||||
Reference in New Issue
Block a user