Merge nucleic/rustic-north-koala into dev

This commit is contained in:
2026-06-16 00:11:11 -07:00
parent 136a22eb89
commit d2817f60fa
2 changed files with 35 additions and 6 deletions
@@ -33,13 +33,19 @@ struct ApprovalCardView: View {
.background(approval.risk.color.opacity(0.2), in: Capsule())
.foregroundStyle(approval.risk.color)
}
Text(approval.input.compactSummary)
// Full, untruncated content in a bounded scroll view — the user must be
// able to read exactly what they are granting, so long commands/paths/inputs
// scroll instead of being clipped to a few lines.
if !approval.input.approvalDetail.isEmpty {
ScrollView([.horizontal, .vertical]) {
Text(approval.input.approvalDetail)
.font(.caption.monospaced())
.lineLimit(8)
.textSelection(.enabled)
.padding(8)
.frame(maxWidth: .infinity, alignment: .leading)
}
.frame(maxWidth: .infinity, maxHeight: 200, alignment: .leading)
.background(Color(.secondarySystemBackground), in: RoundedRectangle(cornerRadius: 8))
}
if requiresBiometric && !biometricPassed {
Button {
@@ -82,4 +82,27 @@ extension JSONValue {
case .null: return "null"
}
}
/// The full, **untruncated** content of a tool input for the approval card —
/// the user must see exactly what they are granting before allowing. Unlike
/// `compactSummary` (a one-line gist that drops values for complex objects) this
/// returns the primary field verbatim, falling back to the pretty-printed input
/// so nothing is hidden. The caller scrolls; it never clips.
var approvalDetail: String {
switch self {
case .string(let s): return s
case .object(let o):
if let primary = o["command"]?.stringValue
?? o["file_path"]?.stringValue
?? o["path"]?.stringValue
?? o["notebook_path"]?.stringValue
?? o["url"]?.stringValue
?? o["query"]?.stringValue {
return primary
}
return o.isEmpty ? "" : prettyString()
case .null: return ""
default: return prettyString()
}
}
}