feat: add automatic greeting upon connection (#42)
CI / Lint & Test (push) Successful in 14m0s
CI / Build Linux (push) Successful in 16m33s
CI / Build Windows (cross-compile) (push) Successful in 26m23s
Security Scan and Upload / Security & DefectDojo Upload (push) Successful in 1m5s

### Explanation

_No response_

### Issue

Closes #23

### Attestations

- [ ] I have read and agree to the [Code of Conduct](https://docs.nhcarrigan.com/community/coc/)
- [ ] I have read and agree to the [Community Guidelines](https://docs.nhcarrigan.com/community/guide/).
- [ ] My contribution complies with the [Contributor Covenant](https://docs.nhcarrigan.com/dev/covenant/).

### Dependencies

- [ ] I have pinned the dependencies to a specific patch version.

### Style

- [ ] I have run the linter and resolved any errors.
- [ ] My pull request uses an appropriate title, matching the conventional commit standards.
- [ ] My scope of feat/fix/chore/etc. correctly matches the nature of changes in my pull request.

### Tests

- [ ] My contribution adds new code, and I have added tests to cover it.
- [ ] My contribution modifies existing code, and I have updated the tests to reflect these changes.
- [ ] All new and existing tests pass locally with my changes.
- [ ] Code coverage remains at or above the configured threshold.

### Documentation

_No response_

### Versioning

_No response_

Reviewed-on: #42
Co-authored-by: Naomi Carrigan <commits@nhcarrigan.com>
Co-committed-by: Naomi Carrigan <commits@nhcarrigan.com>
This commit was merged in pull request #42.
This commit is contained in:
2026-01-16 15:10:28 -08:00
committed by Naomi Carrigan
parent 2220c26c5e
commit ac84366716
5 changed files with 123 additions and 2 deletions
+45 -1
View File
@@ -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,46 @@ interface StateChangePayload {
tool_name: string | null;
}
function getTimeOfDay(): string {
const hour = new Date().getHours();
if (hour >= 5 && hour < 12) {
return "morning";
} else if (hour >= 12 && hour < 17) {
return "afternoon";
} else if (hour >= 17 && hour < 21) {
return "evening";
} else {
return "late night";
}
}
function generateGreetingPrompt(): string {
const timeOfDay = getTimeOfDay();
return `[System: A new session has started. It's currently ${timeOfDay}. Please greet the user warmly and briefly. Keep it short - just 1-2 sentences.]`;
}
async function sendGreeting() {
const config = configStore.getConfig();
if (!config.greeting_enabled) {
return;
}
const greetingPrompt = config.greeting_custom_prompt?.trim() || generateGreetingPrompt();
// Don't show the system prompt in the UI - just trigger Claude to respond
characterState.setState("thinking");
try {
await invoke("send_prompt", { message: greetingPrompt });
} catch (error) {
console.error("Failed to send greeting:", error);
claudeStore.addLine("error", `Failed to send greeting: ${error}`);
characterState.setTemporaryState("error", 3000);
}
}
interface OutputPayload {
line_type: string;
content: string;
@@ -16,13 +58,15 @@ interface OutputPayload {
}
export async function initializeTauriListeners() {
await listen<string>("claude:connection", (event) => {
await listen<string>("claude:connection", async (event) => {
const status = event.payload as ConnectionStatus;
claudeStore.setConnectionStatus(status);
if (status === "connected") {
claudeStore.addLine("system", "Connected to Claude Code");
characterState.setState("idle");
// Send greeting when connection is established
await sendGreeting();
} else if (status === "disconnected") {
claudeStore.addLine("system", "Disconnected from Claude Code");
characterState.setState("idle");