create-keel-and-deck-app 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/index.js +76 -0
  2. package/package.json +23 -0
  3. package/template/index.html +12 -0
  4. package/template/package.json +41 -0
  5. package/template/src/App.tsx +193 -0
  6. package/template/src/hooks/use-session-events.ts +36 -0
  7. package/template/src/lib/tauri.ts +68 -0
  8. package/template/src/lib/types.ts +111 -0
  9. package/template/src/main.tsx +10 -0
  10. package/template/src/stores/agents.ts +65 -0
  11. package/template/src/stores/events.ts +27 -0
  12. package/template/src/stores/feeds.ts +34 -0
  13. package/template/src/stores/issues.ts +35 -0
  14. package/template/src/stores/memory.ts +30 -0
  15. package/template/src/stores/ui.ts +17 -0
  16. package/template/src/styles/globals.css +24 -0
  17. package/template/src-tauri/Cargo.toml +28 -0
  18. package/template/src-tauri/build.rs +3 -0
  19. package/template/src-tauri/capabilities/default.json +12 -0
  20. package/template/src-tauri/icons/.gitkeep +0 -0
  21. package/template/src-tauri/src/commands/channels.rs +119 -0
  22. package/template/src-tauri/src/commands/events.rs +43 -0
  23. package/template/src-tauri/src/commands/issues.rs +29 -0
  24. package/template/src-tauri/src/commands/memory.rs +52 -0
  25. package/template/src-tauri/src/commands/mod.rs +8 -0
  26. package/template/src-tauri/src/commands/projects.rs +38 -0
  27. package/template/src-tauri/src/commands/scheduler.rs +67 -0
  28. package/template/src-tauri/src/commands/sessions.rs +80 -0
  29. package/template/src-tauri/src/commands/workspace.rs +62 -0
  30. package/template/src-tauri/src/lib.rs +93 -0
  31. package/template/src-tauri/src/main.rs +6 -0
  32. package/template/src-tauri/src/workspace.rs +21 -0
  33. package/template/src-tauri/tauri.conf.json +30 -0
  34. package/template/tsconfig.json +21 -0
  35. package/template/vite.config.ts +17 -0
@@ -0,0 +1,62 @@
1
+ use keel_tauri::paths::expand_tilde;
2
+ use keel_tauri::state::AppState;
3
+ use serde::Serialize;
4
+ use tauri::State;
5
+
6
+ const KNOWN_FILES: &[(&str, &str)] = &[
7
+ ("CLAUDE.md", "Agent instructions and behavior rules"),
8
+ ];
9
+
10
+ #[derive(Serialize)]
11
+ pub struct WorkspaceFileInfo {
12
+ name: String,
13
+ description: String,
14
+ exists: bool,
15
+ }
16
+
17
+ #[tauri::command]
18
+ pub async fn list_workspace_files(
19
+ state: State<'_, AppState>,
20
+ project_id: String,
21
+ ) -> Result<Vec<WorkspaceFileInfo>, String> {
22
+ let project = state
23
+ .db
24
+ .get_project(&project_id)
25
+ .await
26
+ .map_err(|e| e.to_string())?
27
+ .ok_or_else(|| "Project not found".to_string())?;
28
+
29
+ let dir = expand_tilde(&project.folder_path);
30
+ let files = KNOWN_FILES
31
+ .iter()
32
+ .map(|(name, desc)| WorkspaceFileInfo {
33
+ name: name.to_string(),
34
+ description: desc.to_string(),
35
+ exists: dir.join(name).exists(),
36
+ })
37
+ .collect();
38
+
39
+ Ok(files)
40
+ }
41
+
42
+ #[tauri::command]
43
+ pub async fn read_workspace_file(
44
+ state: State<'_, AppState>,
45
+ project_id: String,
46
+ file_name: String,
47
+ ) -> Result<String, String> {
48
+ let project = state
49
+ .db
50
+ .get_project(&project_id)
51
+ .await
52
+ .map_err(|e| e.to_string())?
53
+ .ok_or_else(|| "Project not found".to_string())?;
54
+
55
+ // Only allow reading known files
56
+ if !KNOWN_FILES.iter().any(|(name, _)| *name == file_name) {
57
+ return Err(format!("Unknown workspace file: {file_name}"));
58
+ }
59
+
60
+ let path = expand_tilde(&project.folder_path).join(&file_name);
61
+ std::fs::read_to_string(&path).map_err(|e| format!("Failed to read {file_name}: {e}"))
62
+ }
@@ -0,0 +1,93 @@
1
+ mod commands;
2
+ mod workspace;
3
+
4
+ use keel_tauri::chat_session::ChatSessionState;
5
+ use keel_tauri::keel_db::Database;
6
+ use keel_tauri::keel_events::EventQueue;
7
+ use keel_tauri::keel_memory::MemoryStore;
8
+ use keel_tauri::keel_scheduler::Scheduler;
9
+ use keel_tauri::state::AppState;
10
+ use std::sync::Arc;
11
+ use tokio::sync::Mutex;
12
+
13
+ pub fn run() {
14
+ tauri::Builder::default()
15
+ .setup(|app| {
16
+ let data_dir = keel_tauri::keel_db::db::default_data_dir("{{APP_NAME_SNAKE}}");
17
+ let db_path = data_dir.join("{{APP_NAME_SNAKE}}.db");
18
+
19
+ let db = tauri::async_runtime::block_on(async {
20
+ Database::connect(&db_path)
21
+ .await
22
+ .expect("Failed to open database")
23
+ });
24
+
25
+ // Initialize memory store with its own connection to the same DB.
26
+ let memory_dir = data_dir.join("memories");
27
+ let memory_store = tauri::async_runtime::block_on(async {
28
+ let mem_db = libsql::Builder::new_local(&db_path)
29
+ .build()
30
+ .await
31
+ .expect("Failed to open memory DB connection");
32
+ let mem_conn = Arc::new(
33
+ mem_db.connect().expect("Failed to connect for memory store"),
34
+ );
35
+ MemoryStore::new_with_markdown_dir(mem_conn, memory_dir)
36
+ .await
37
+ .expect("Failed to initialize memory store")
38
+ });
39
+
40
+ // Initialize event queue.
41
+ let (_event_queue, queue_handle) = EventQueue::new();
42
+
43
+ // Initialize scheduler with queue handle.
44
+ let scheduler = Scheduler::new(queue_handle.clone());
45
+
46
+ // Chat session state for --resume support.
47
+ let chat_session = ChatSessionState::default();
48
+
49
+ app.manage(AppState {
50
+ db,
51
+ event_queue: Some(queue_handle),
52
+ scheduler: Some(Arc::new(Mutex::new(scheduler))),
53
+ });
54
+ app.manage(memory_store);
55
+ app.manage(chat_session);
56
+
57
+ Ok(())
58
+ })
59
+ .invoke_handler(tauri::generate_handler![
60
+ // Projects (agents)
61
+ commands::projects::list_projects,
62
+ commands::projects::create_project,
63
+ // Issues
64
+ commands::issues::list_issues,
65
+ commands::issues::create_issue,
66
+ // Sessions
67
+ commands::sessions::start_session,
68
+ commands::sessions::load_chat_feed,
69
+ // Workspace
70
+ commands::workspace::list_workspace_files,
71
+ commands::workspace::read_workspace_file,
72
+ // Memory
73
+ commands::memory::list_memories,
74
+ commands::memory::create_memory,
75
+ commands::memory::delete_memory,
76
+ commands::memory::search_memories,
77
+ // Events
78
+ commands::events::list_events,
79
+ // Scheduler
80
+ commands::scheduler::add_heartbeat,
81
+ commands::scheduler::remove_heartbeat,
82
+ commands::scheduler::add_cron,
83
+ commands::scheduler::remove_cron,
84
+ // Channels
85
+ commands::channels::list_channels,
86
+ commands::channels::add_channel,
87
+ commands::channels::remove_channel,
88
+ commands::channels::connect_channel,
89
+ commands::channels::disconnect_channel,
90
+ ])
91
+ .run(tauri::generate_context!())
92
+ .expect("error while running tauri application");
93
+ }
@@ -0,0 +1,6 @@
1
+ // Prevents additional console window on Windows in release.
2
+ #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
3
+
4
+ fn main() {
5
+ {{APP_NAME_SNAKE}}_lib::run();
6
+ }
@@ -0,0 +1,21 @@
1
+ use keel_tauri::paths::expand_tilde;
2
+ use keel_tauri::workspace::seed_file;
3
+
4
+ const CLAUDE_MD_TEMPLATE: &str = r#"# {{APP_NAME_TITLE}} Agent
5
+
6
+ ## Role
7
+ You are a helpful AI assistant.
8
+
9
+ ## Rules
10
+ - Be concise and direct
11
+ - Ask before making destructive changes
12
+ - Explain your reasoning when making decisions
13
+ "#;
14
+
15
+ /// Seed workspace files for a new agent. Creates the folder and writes
16
+ /// CLAUDE.md if it doesn't already exist.
17
+ pub fn seed_workspace(folder_path: &str) {
18
+ let dir = expand_tilde(folder_path);
19
+ std::fs::create_dir_all(&dir).ok();
20
+ seed_file(&dir, "CLAUDE.md", CLAUDE_MD_TEMPLATE);
21
+ }
@@ -0,0 +1,30 @@
1
+ {
2
+ "$schema": "https://raw.githubusercontent.com/nickelpack/tauri/v2/crates/tauri-config-schema/schema.json",
3
+ "productName": "{{APP_NAME_TITLE}}",
4
+ "identifier": "com.{{APP_NAME_SNAKE}}.app",
5
+ "build": {
6
+ "frontendDist": "../dist",
7
+ "devUrl": "http://localhost:1420",
8
+ "beforeDevCommand": "pnpm dev",
9
+ "beforeBuildCommand": "pnpm build"
10
+ },
11
+ "app": {
12
+ "withGlobalTauri": false,
13
+ "windows": [
14
+ {
15
+ "title": "{{APP_NAME_TITLE}}",
16
+ "width": 1200,
17
+ "height": 800,
18
+ "minWidth": 800,
19
+ "minHeight": 600,
20
+ "decorations": true,
21
+ "transparent": false,
22
+ "titleBarStyle": "Overlay"
23
+ }
24
+ ],
25
+ "security": {
26
+ "csp": null,
27
+ "capabilities": ["default"]
28
+ }
29
+ }
30
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2021",
4
+ "useDefineForClassFields": true,
5
+ "lib": ["ES2021", "DOM", "DOM.Iterable"],
6
+ "module": "ESNext",
7
+ "skipLibCheck": true,
8
+ "moduleResolution": "bundler",
9
+ "allowImportingTsExtensions": true,
10
+ "isolatedModules": true,
11
+ "moduleDetection": "force",
12
+ "noEmit": true,
13
+ "jsx": "react-jsx",
14
+ "strict": true,
15
+ "noUnusedLocals": true,
16
+ "noUnusedParameters": true,
17
+ "noFallthroughCasesInSwitch": true,
18
+ "noUncheckedSideEffectImports": true
19
+ },
20
+ "include": ["src"]
21
+ }
@@ -0,0 +1,17 @@
1
+ import { defineConfig } from "vite";
2
+ import react from "@vitejs/plugin-react";
3
+ import tailwindcss from "@tailwindcss/vite";
4
+
5
+ const host = process.env.TAURI_DEV_HOST;
6
+
7
+ export default defineConfig({
8
+ plugins: [react(), tailwindcss()],
9
+ clearScreen: false,
10
+ server: {
11
+ port: 1420,
12
+ strictPort: true,
13
+ host: host || false,
14
+ hmr: host ? { protocol: "ws", host, port: 1421 } : undefined,
15
+ watch: { ignored: ["**/src-tauri/**"] },
16
+ },
17
+ });