From 7427865e46c737fe774f31d946ed6b9e6e6c000f Mon Sep 17 00:00:00 2001 From: Timmy Date: Tue, 31 Mar 2026 11:33:41 +0100 Subject: [PATCH] Adding more slash commands --- frontend/src/components/Chat.tsx | 14 +++++++----- frontend/src/slashCommands.ts | 38 ++++++++++++++++++++++++++++++++ server/src/rebuild.rs | 31 +++++++++++++++++++++++--- 3 files changed, 74 insertions(+), 9 deletions(-) diff --git a/frontend/src/components/Chat.tsx b/frontend/src/components/Chat.tsx index 1ca6a423..1e73e51a 100644 --- a/frontend/src/components/Chat.tsx +++ b/frontend/src/components/Chat.tsx @@ -617,12 +617,6 @@ export function Chat({ projectPath, onCloseProject, oauthStatus = null }: ChatPr const sendMessage = async (messageText: string) => { if (!messageText.trim()) return; - // /help — show available slash commands overlay - if (/^\/help\s*$/i.test(messageText)) { - setShowHelp(true); - return; - } - // /reset — clear session and message history without LLM if (/^\/reset\s*$/i.test(messageText)) { setMessages([]); @@ -659,6 +653,14 @@ export function Chat({ projectPath, onCloseProject, oauthStatus = null }: ChatPr "overview", "rebuild", "loc", + "help", + "ambient", + "htop", + "rmtree", + "timer", + "unblock", + "unreleased", + "setup", ]); if (knownCommands.has(cmd)) { diff --git a/frontend/src/slashCommands.ts b/frontend/src/slashCommands.ts index 7718626d..f23f35d1 100644 --- a/frontend/src/slashCommands.ts +++ b/frontend/src/slashCommands.ts @@ -50,10 +50,48 @@ export const SLASH_COMMANDS: SlashCommand[] = [ name: "/overview ", description: "Show the implementation summary for a merged story.", }, + { + name: "/ambient", + description: "Toggle ambient mode: `/ambient on` or `/ambient off`.", + }, + { + name: "/htop", + description: + "Show live system and agent process dashboard: `/htop`, `/htop 10m`, `/htop stop`.", + }, + { + name: "/loc", + description: + "Show top source files by line count: `/loc` (top 10), `/loc `, or `/loc `.", + }, + { + name: "/rmtree ", + description: + "Delete the worktree for a story without removing it from the pipeline.", + }, { name: "/rebuild", description: "Rebuild the server binary and restart.", }, + { + name: "/timer", + description: + "Schedule a deferred agent start: `/timer `, `/timer list`, `/timer cancel `.", + }, + { + name: "/unblock ", + description: + "Reset a blocked story: clears blocked flag and resets retry count.", + }, + { + name: "/unreleased", + description: "Show stories merged to master since the last release tag.", + }, + { + name: "/setup", + description: + "Show setup wizard progress; or `/setup confirm` / `/setup skip` / `/setup retry` to drive the wizard.", + }, { name: "/reset", description: diff --git a/server/src/rebuild.rs b/server/src/rebuild.rs index 9ea3eb2d..5139a801 100644 --- a/server/src/rebuild.rs +++ b/server/src/rebuild.rs @@ -123,7 +123,32 @@ pub async fn rebuild_and_restart( workspace_root.display() ); - // 3. Build the server binary, matching the current build profile so the + // 3. Rebuild the frontend bundle so rust-embed picks up the latest assets. + let frontend_dir = workspace_root.join("frontend"); + if frontend_dir.join("package.json").exists() { + slog!("[rebuild] Building frontend"); + let fe_output = tokio::task::spawn_blocking({ + let frontend_dir = frontend_dir.clone(); + move || { + std::process::Command::new("npm") + .args(["run", "build"]) + .current_dir(&frontend_dir) + .output() + } + }) + .await + .map_err(|e| format!("Frontend build task panicked: {e}"))? + .map_err(|e| format!("Failed to run npm run build: {e}"))?; + + if !fe_output.status.success() { + let stderr = String::from_utf8_lossy(&fe_output.stderr); + slog!("[rebuild] Frontend build failed:\n{stderr}"); + return Err(format!("Frontend build failed:\n{stderr}")); + } + slog!("[rebuild] Frontend build succeeded"); + } + + // 4. Build the server binary, matching the current build profile so the // re-exec via current_exe() picks up the new binary. let build_args: Vec<&str> = if cfg!(debug_assertions) { vec!["build", "-p", "storkit"] @@ -152,14 +177,14 @@ pub async fn rebuild_and_restart( slog!("[rebuild] Build succeeded, re-execing with new binary"); - // 4. Send shutdown notification before replacing the process so that chat + // 5. Send shutdown notification before replacing the process so that chat // participants know the bot is going offline. Best-effort only — we // do not abort the rebuild if the send fails. if let Some(n) = notifier { n.notify(ShutdownReason::Rebuild).await; } - // 5. Re-exec with the new binary. + // 6. Re-exec with the new binary. // Use the cargo output path rather than current_exe() so that rebuilds // inside Docker work correctly — the running binary may be installed at // /usr/local/bin/storkit (read-only) while cargo writes the new binary