Danger warning on approval cards (red card, reasons, no Always); file shelf in the top-left slot with 'На полку' after a drop

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
maksarsanjeev
2026-10-06 22:51:35 +03:00
parent 3857776111
commit 37c01f991a
9 changed files with 296 additions and 6 deletions
+19 -3
View File
@@ -298,11 +298,25 @@ struct ApprovalView: View {
var approval: ApprovalInfo? { state.pendingApproval }
var body: some View {
let danger = approval?.danger ?? []
ZStack {
CardBackground(wash: .amber)
CardBackground(wash: danger.isEmpty ? .amber : .red)
VStack(alignment: .leading, spacing: 5) {
AgentWho(task: state.focusTask, label: "просит разрешение")
CodeBlock(text: approval?.command ?? approval?.tool ?? "…")
if !danger.isEmpty {
HStack(alignment: .top, spacing: 5) {
Image(systemName: "exclamationmark.triangle.fill")
.font(.system(size: 10, weight: .bold))
Text("Опасно: " + danger.joined(separator: "; "))
.font(.system(size: 10.5, weight: .semibold))
.lineLimit(2)
.fixedSize(horizontal: false, vertical: true)
}
.foregroundColor(Color(hex: "#FF6B76"))
.padding(.horizontal, 8).padding(.vertical, 3)
.background(RoundedRectangle(cornerRadius: 6).fill(Color(hex: "#F4505E").opacity(0.14)))
}
HStack(spacing: 8) {
SecondaryButton("Запретить") {
HookServer.shared.sendApprovalDecision("deny")
@@ -310,8 +324,9 @@ struct ApprovalView: View {
PrimaryButton("Разрешить") {
HookServer.shared.sendApprovalDecision("allow")
}
// Codex rejects updatedPermissions, so "Always" is not offered
if approval?.pillId != "agent_codex" {
// Codex rejects updatedPermissions, so "Always" is not offered.
// Never for a dangerous command: one click must not save a destructive rule.
if approval?.pillId != "agent_codex" && danger.isEmpty {
SecondaryButton("Всегда") {
HookServer.shared.sendApprovalDecision("always")
}
@@ -922,6 +937,7 @@ struct ChooseView: View {
HStack(spacing: 8) {
PrimaryButton("Задать вопрос") { state.view = .prompt }
SecondaryButton("Отправить почтой") { state.view = .mail }
SecondaryButton("На полку") { state.shelveLastDrop() }
}
}
.padding(.leading, 98)