Menu
Commit c759797b
c759797bd0868d3d4edafef701bd09699f30b37d by Ólafur Búi Ólafsson
- CHANGELOG.md +5 -0
- Cargo.toml +1 -1
- VERSION +1 -1
- assets/themes.json +1 -0
- src/main.rs +11 -0
- src/routes/agent_os.css +66 -0
- src/routes/agent_view.rs +6 -0
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 28a14f2..57b93e9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,11 @@ All notable changes to this project are documented here. Format: Keep a Changelo
## [Unreleased]
+## [0.1.2] - 2026-06-29
+
+- Add suite theme picker to agent console: serve /themes.json registry + mount the Framework theme selector (17 themes, all families) in the sidebar Account section, matching every other AkurAI-Framework app.
+
+
## [0.1.1] - 2026-06-29
- Remove AI-slop 'Agent surfaces' from agent console: delete Tasks, Projects, AGY context, Notes, Passvault, Cron, Curator pages + the dead Tools launcher (all hardcoded placeholder content, no real data). Console nav is now Chat / Kanban / Run details. Also: repo-wide rustfmt + clippy cleanup.
diff --git a/Cargo.toml b/Cargo.toml
index 2fda114..93cd32a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "akurai-idp"
-version = "0.1.1"
+version = "0.1.2"
edition = "2024"
description = "Lightweight Rust OIDC/OAuth2 identity provider for AkurAI — replaces 96MB Node process"
license = "MIT"
diff --git a/VERSION b/VERSION
index 17e51c3..d917d3e 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.1.1
+0.1.2
diff --git a/assets/themes.json b/assets/themes.json
new file mode 100644
index 0000000..bd4f1fa
--- /dev/null
+++ b/assets/themes.json
@@ -0,0 +1 @@
+[{"slug":"akurai","family":"AkurAI","label":"AkurAI","variant":"dark"},{"slug":"akurai-light","family":"AkurAI","label":"AkurAI Light","variant":"light"},{"slug":"claude-code","family":"Claude Code","label":"Claude Code","variant":"dark"},{"slug":"claude-code-light","family":"Claude Code","label":"Claude Code Light","variant":"light"},{"slug":"nord","family":"Nord","label":"Nord","variant":"dark"},{"slug":"nord-light","family":"Nord","label":"Nord Light","variant":"light"},{"slug":"catppuccin-mocha","family":"Catppuccin","label":"Catppuccin Mocha","variant":"dark"},{"slug":"catppuccin-latte","family":"Catppuccin","label":"Catppuccin Latte","variant":"light"},{"slug":"solarized-dark","family":"Solarized","label":"Solarized Dark","variant":"dark"},{"slug":"solarized-light","family":"Solarized","label":"Solarized Light","variant":"light"},{"slug":"gruvbox-dark","family":"Gruvbox","label":"Gruvbox dark, medium","variant":"dark"},{"slug":"gruvbox-light","family":"Gruvbox","label":"Gruvbox light, medium","variant":"light"},{"slug":"tokyo-night","family":"Tokyo Night","label":"Tokyo Night Dark","variant":"dark"},{"slug":"tokyo-night-light","family":"Tokyo Night","label":"Tokyo Night Light","variant":"light"},{"slug":"rose-pine","family":"Rosé Pine","label":"Rosé Pine","variant":"dark"},{"slug":"rose-pine-dawn","family":"Rosé Pine","label":"Rosé Pine Dawn","variant":"light"},{"slug":"dracula","family":"Dracula","label":"Dracula","variant":"dark"}]
diff --git a/src/main.rs b/src/main.rs
index 8b42325..28f858f 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -29,6 +29,7 @@ const FAVICON_SVG: &[u8] = include_bytes!("../assets/favicon.svg");
const APPLE_TOUCH_ICON_PNG: &[u8] = include_bytes!("../assets/apple-touch-icon.png");
const THEME_JS: &[u8] = include_bytes!("../assets/theme.js");
const THEMES_CSS: &[u8] = include_bytes!("../assets/themes.css");
+const THEMES_JSON: &[u8] = include_bytes!("../assets/themes.json");
const LANG_JS: &[u8] = include_bytes!("../assets/lang.js");
const AGENT_JS: &[u8] = include_bytes!("../assets/agent.js");
@@ -99,6 +100,7 @@ async fn main() {
.route("/apple-touch-icon.png", get(serve_apple_touch_icon))
.route("/theme.js", get(serve_theme_js))
.route("/themes.css", get(serve_themes_css))
+ .route("/themes.json", get(serve_themes_json))
.route("/lang.js", get(serve_lang_js))
.route("/agent.js", get(serve_agent_js))
// Health check
@@ -229,6 +231,15 @@ async fn serve_themes_css() -> Response<Body> {
.unwrap()
}
+async fn serve_themes_json() -> Response<Body> {
+ Response::builder()
+ .status(StatusCode::OK)
+ .header(header::CONTENT_TYPE, "application/json; charset=utf-8")
+ .header(header::CACHE_CONTROL, "public, max-age=3600")
+ .body(Body::from(THEMES_JSON.to_vec()))
+ .unwrap()
+}
+
async fn serve_lang_js() -> Response<Body> {
Response::builder()
.status(StatusCode::OK)
diff --git a/src/routes/agent_os.css b/src/routes/agent_os.css
index f6299ba..7915b9f 100644
--- a/src/routes/agent_os.css
+++ b/src/routes/agent_os.css
@@ -148,6 +148,72 @@ body {
font-weight: 650;
}
+/* Suite theme picker — theme.js mounts a <select.theme-select> into the slot.
+ Token-driven so it re-themes with everything else. */
+.agent-theme-row {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 8px;
+ padding: 7px 10px;
+}
+
+.agent-theme-label {
+ flex: 0 0 auto;
+ color: var(--muted);
+ font-size: 13px;
+}
+
+.agent-theme-row .theme-picker {
+ display: inline-flex;
+ align-items: center;
+ min-width: 0;
+}
+
+.theme-select {
+ appearance: none;
+ -webkit-appearance: none;
+ min-width: 0;
+ max-width: 150px;
+ font: inherit;
+ font-size: 12px;
+ font-weight: 500;
+ color: var(--fg);
+ background: var(--panel);
+ border: 1px solid var(--soft-border);
+ border-radius: 8px;
+ padding: 6px 26px 6px 10px;
+ cursor: pointer;
+ line-height: 1.2;
+ background-image: linear-gradient(45deg, transparent 50%, var(--muted) 50%),
+ linear-gradient(135deg, var(--muted) 50%, transparent 50%);
+ background-position: calc(100% - 14px) center, calc(100% - 9px) center;
+ background-size: 5px 5px, 5px 5px;
+ background-repeat: no-repeat;
+ transition: border-color 0.15s ease, background-color 0.15s ease;
+}
+
+.theme-select:hover {
+ border-color: var(--border-2);
+}
+
+.theme-select:focus-visible {
+ outline: 2px solid var(--accent);
+ outline-offset: 1px;
+}
+
+.theme-select optgroup {
+ color: var(--fg);
+ background: var(--panel);
+ font-weight: 700;
+}
+
+.theme-select option {
+ color: var(--fg);
+ background: var(--panel);
+ font-weight: 500;
+}
+
.agent-modebar,
.agent-nav {
display: grid;
diff --git a/src/routes/agent_view.rs b/src/routes/agent_view.rs
index bec5762..aa627f9 100644
--- a/src/routes/agent_view.rs
+++ b/src/routes/agent_view.rs
@@ -69,6 +69,10 @@ fn agent_page_body(
<div class="agent-section agent-account">
<h2>Account</h2>
<a href="/account">AkurAI ID</a>
+ <div class="agent-theme-row">
+ <span class="agent-theme-label">Theme</span>
+ <span class="theme-picker" data-theme-picker></span>
+ </div>
</div>
</aside>
@@ -398,6 +402,8 @@ mod tests {
assert!(html.contains("data-agent-prompt"));
assert!(html.contains("approval.request"));
assert!(html.contains("tool_call"));
+ // Suite theme picker slot present so theme.js can mount the selector.
+ assert!(html.contains("data-theme-picker"));
}
#[test]