Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
22 changes: 14 additions & 8 deletions DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ use the close transition and return to `idle`.
reveals a small speech-bubble terminal affordance. The companion never walks,
slides, or bobs in idle; only the intentional gaze state changes.
Clicking either Miku herself or that bubble begins the terminal transition.
- In terminal state, the bubble opens as a coding-agent workspace: the centered
MikuCode mark gives way to prompt history, a provider/approval composer, and
- In terminal state, the bubble opens as a coding-agent workspace: a compact
MikuCode logo mark gives way to prompt history, a provider/approval composer, and
a terminal toggle. Codex and Claude support `Plan`, `Accept`, and `Auto`;
the workspace only records a request after its token-matched PTY delivery.
The terminal toggle reveals that same local PTY inside the bubble—never a
Expand All @@ -44,11 +44,17 @@ use the close transition and return to `idle`.
companion at the floating layer; it only returns behind other apps after the
app itself loses focus, and never quits MikuCode.
- The workspace header is an agent-workspace cue, not a toolbar: it contains
the app name, an embedded-terminal toggle, and one close control. The
composer is the only persistent input surface. Command-F opens the only
the logo mark, local-shell status, an embedded-terminal toggle, and one close
control. The composer is a measured bottom dock: provider and approval chips
remain distinct from a full-width prompt field and labelled send action at all
supported bubble sizes. Codex uses a cool gray signal, Claude orange, and
Plan/Accept/Auto each retain distinct semantic colors. Command-F opens the only
transient terminal text field: a compact in-bubble finder. Command-G and
Shift-Command-G navigate its case-insensitive matches across output pages;
Escape restores terminal focus and removes the finder.
- The speech-bubble tail owns a reserved header inset; terminal and close controls
never sit beneath it, and the focused-Miku close target begins after a fixed gap
beyond the workspace frame. No interactive target is allowed to overlap another.
- The speech bubble resizes directly from its edges and corners. Its frame stays
inside a 24-point display inset and preserves a minimum right-side Miku rail;
native directional cursors expose the otherwise unobtrusive resize targets.
Expand All @@ -71,10 +77,10 @@ snapshot persist on close and restore on the next launch.
## Visual tokens

The visual system uses a 4-point spacing base. Idle is transparent; active
surfaces use flat dark sky-blue tones, a translucent cyan rim, a restrained
teal shadow, and white terminal text. The header uses compact rounded app type
with small monospaced agent labels, making the surface read as a coding-agent
workspace rather than a generic terminal emulator. The app icon is a separate
surfaces use flat dark sky-blue tones, a translucent cyan rim with a slow opacity
pulse, a restrained teal shadow, and white terminal text. The header uses modern
SF app type with small monospaced agent labels, making the surface read as a
coding-agent workspace rather than a generic terminal emulator. The app icon is a separate
terminal-and-Miku asset; the desktop companion contains only the 2D Miku
character. Idle artwork stays centered and still above a subtle teal ground
shadow. Its only idle motion is an intentional crossfade to an attentive gaze
Expand Down
34 changes: 34 additions & 0 deletions Sources/MikuCodeApp/Agent/AgentWorkspaceModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,24 @@ enum AgentProvider: String, CaseIterable, Identifiable {
}
}

var tint: Color {
switch self {
case .codex: Color(red: 0.720, green: 0.780, blue: 0.860)
case .claude: Color(red: 1.000, green: 0.590, blue: 0.300)
case .pi: Color(red: 0.740, green: 0.520, blue: 1.000)
case .openCode: Color(red: 0.400, green: 0.880, blue: 0.650)
}
}

var symbol: String {
switch self {
case .codex: "circle.hexagongrid.fill"
case .claude: "sun.max.fill"
case .pi: "circle.grid.cross.fill"
case .openCode: "chevron.left.forwardslash.chevron.right"
}
}

var supportsApproval: Bool {
self == .codex || self == .claude
}
Expand All @@ -37,6 +55,22 @@ enum AgentApproval: String, CaseIterable, Identifiable {
case .auto: "Auto"
}
}

var tint: Color {
switch self {
case .plan: Color(red: 0.640, green: 0.610, blue: 1.000)
case .accept: Color(red: 0.310, green: 0.820, blue: 1.000)
case .auto: Color(red: 1.000, green: 0.690, blue: 0.300)
}
}

var symbol: String {
switch self {
case .plan: "map.fill"
case .accept: "checkmark.shield.fill"
case .auto: "bolt.fill"
}
}
}

struct AgentRunRequest: Equatable {
Expand Down
Loading