diff --git a/src-tauri/src/config.rs b/src-tauri/src/config.rs index 29fc620..00cd3bd 100644 --- a/src-tauri/src/config.rs +++ b/src-tauri/src/config.rs @@ -40,6 +40,16 @@ pub struct HikariConfig { #[serde(default)] pub theme: Theme, + + #[serde(default = "default_greeting_enabled")] + pub greeting_enabled: bool, + + #[serde(default)] + pub greeting_custom_prompt: Option, +} + +fn default_greeting_enabled() -> bool { + true } #[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)] @@ -63,6 +73,8 @@ mod tests { assert!(config.mcp_servers_json.is_none()); assert!(config.auto_granted_tools.is_empty()); assert_eq!(config.theme, Theme::Dark); + assert!(!config.greeting_enabled); + assert!(config.greeting_custom_prompt.is_none()); } #[test] @@ -74,6 +86,8 @@ mod tests { mcp_servers_json: None, auto_granted_tools: vec!["Read".to_string(), "Glob".to_string()], theme: Theme::Light, + greeting_enabled: true, + greeting_custom_prompt: Some("Hello!".to_string()), }; let json = serde_json::to_string(&config).unwrap(); @@ -83,6 +97,8 @@ mod tests { assert_eq!(deserialized.custom_instructions, config.custom_instructions); assert_eq!(deserialized.auto_granted_tools, config.auto_granted_tools); assert_eq!(deserialized.theme, Theme::Light); + assert!(deserialized.greeting_enabled); + assert_eq!(deserialized.greeting_custom_prompt, Some("Hello!".to_string())); } #[test] diff --git a/src/lib/components/ConfigSidebar.svelte b/src/lib/components/ConfigSidebar.svelte index bb09d8c..fe53587 100644 --- a/src/lib/components/ConfigSidebar.svelte +++ b/src/lib/components/ConfigSidebar.svelte @@ -9,6 +9,8 @@ mcp_servers_json: null, auto_granted_tools: [], theme: "dark", + greeting_enabled: true, + greeting_custom_prompt: null, }); let isOpen = $state(false); @@ -220,6 +222,44 @@ + +
+

+ Greeting +

+ + +
+ +

+ Automatically greet you when a session starts with time-based messages +

+
+ + + {#if config.greeting_enabled} +
+ + +
+ {/if} +
+

diff --git a/src/lib/stores/config.ts b/src/lib/stores/config.ts index 2a2d63a..7d5aa45 100644 --- a/src/lib/stores/config.ts +++ b/src/lib/stores/config.ts @@ -10,6 +10,8 @@ export interface HikariConfig { mcp_servers_json: string | null; auto_granted_tools: string[]; theme: Theme; + greeting_enabled: boolean; + greeting_custom_prompt: string | null; } const defaultConfig: HikariConfig = { @@ -19,6 +21,8 @@ const defaultConfig: HikariConfig = { mcp_servers_json: null, auto_granted_tools: [], theme: "dark", + greeting_enabled: true, + greeting_custom_prompt: null, }; function createConfigStore() { diff --git a/src/lib/tauri.ts b/src/lib/tauri.ts index bc0cd4f..5688590 100644 --- a/src/lib/tauri.ts +++ b/src/lib/tauri.ts @@ -1,6 +1,8 @@ import { listen } from "@tauri-apps/api/event"; +import { invoke } from "@tauri-apps/api/core"; import { claudeStore } from "$lib/stores/claude"; import { characterState } from "$lib/stores/character"; +import { configStore } from "$lib/stores/config"; import type { ConnectionStatus, PermissionPromptEvent } from "$lib/types/messages"; import type { CharacterState } from "$lib/types/states"; @@ -9,6 +11,36 @@ interface StateChangePayload { tool_name: string | null; } +function generateTimeBasedGreeting(): string { + const hour = new Date().getHours(); + + if (hour >= 5 && hour < 12) { + return "Good morning! How can I help you today?"; + } else if (hour >= 12 && hour < 17) { + return "Good afternoon! What are we working on?"; + } else if (hour >= 17 && hour < 21) { + return "Good evening! Ready to get some work done?"; + } else { + return "Working late? I'm here to help!"; + } +} + +async function sendGreeting() { + const config = configStore.getConfig(); + + if (!config.greeting_enabled) { + return; + } + + const greetingPrompt = config.greeting_custom_prompt?.trim() || generateTimeBasedGreeting(); + + try { + await invoke("send_prompt", { message: greetingPrompt }); + } catch (error) { + console.error("Failed to send greeting:", error); + } +} + interface OutputPayload { line_type: string; content: string; @@ -69,9 +101,11 @@ export async function initializeTauriListeners() { // no-op }); - await listen("claude:session", (event) => { + await listen("claude:session", async (event) => { claudeStore.setSessionId(event.payload); claudeStore.addLine("system", `Session: ${event.payload.substring(0, 8)}...`); + + await sendGreeting(); }); await listen("claude:cwd", (event) => {