zubo 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 (222) hide show
  1. package/.github/workflows/ci.yml +35 -0
  2. package/README.md +149 -0
  3. package/bun.lock +216 -0
  4. package/desktop/README.md +57 -0
  5. package/desktop/package.json +12 -0
  6. package/desktop/src-tauri/Cargo.toml +25 -0
  7. package/desktop/src-tauri/build.rs +3 -0
  8. package/desktop/src-tauri/icons/README.md +17 -0
  9. package/desktop/src-tauri/icons/icon.png +0 -0
  10. package/desktop/src-tauri/src/main.rs +189 -0
  11. package/desktop/src-tauri/tauri.conf.json +68 -0
  12. package/docs/ROADMAP.md +490 -0
  13. package/migrations/001_init.sql +9 -0
  14. package/migrations/002_memory.sql +33 -0
  15. package/migrations/003_cron.sql +24 -0
  16. package/migrations/004_usage.sql +12 -0
  17. package/migrations/005_secrets.sql +8 -0
  18. package/migrations/006_agents.sql +1 -0
  19. package/migrations/007_workflows.sql +22 -0
  20. package/migrations/008_proactive.sql +24 -0
  21. package/migrations/009_uploads.sql +9 -0
  22. package/migrations/010_observability.sql +22 -0
  23. package/migrations/011_api_keys.sql +7 -0
  24. package/migrations/012_indexes.sql +5 -0
  25. package/migrations/013_budget.sql +11 -0
  26. package/migrations/014_usage_session_idx.sql +2 -0
  27. package/package.json +39 -0
  28. package/site/404.html +156 -0
  29. package/site/CNAME +1 -0
  30. package/site/docs/agents.html +294 -0
  31. package/site/docs/api.html +446 -0
  32. package/site/docs/channels.html +345 -0
  33. package/site/docs/cli.html +238 -0
  34. package/site/docs/config.html +1034 -0
  35. package/site/docs/index.html +433 -0
  36. package/site/docs/integrations.html +381 -0
  37. package/site/docs/memory.html +254 -0
  38. package/site/docs/security.html +375 -0
  39. package/site/docs/skills.html +322 -0
  40. package/site/docs.css +412 -0
  41. package/site/index.html +638 -0
  42. package/site/install.sh +98 -0
  43. package/site/logo.svg +1 -0
  44. package/site/og-image.png +0 -0
  45. package/site/robots.txt +4 -0
  46. package/site/script.js +361 -0
  47. package/site/sitemap.xml +63 -0
  48. package/site/skills.html +532 -0
  49. package/site/style.css +1686 -0
  50. package/src/agent/agents.ts +159 -0
  51. package/src/agent/compaction.ts +53 -0
  52. package/src/agent/context.ts +18 -0
  53. package/src/agent/delegate.ts +118 -0
  54. package/src/agent/loop.ts +318 -0
  55. package/src/agent/prompts.ts +111 -0
  56. package/src/agent/session.ts +87 -0
  57. package/src/agent/teams.ts +116 -0
  58. package/src/agent/workflow-executor.ts +192 -0
  59. package/src/agent/workflow.ts +175 -0
  60. package/src/channels/adapter.ts +21 -0
  61. package/src/channels/dashboard.html.ts +2969 -0
  62. package/src/channels/discord.ts +137 -0
  63. package/src/channels/optional-deps.d.ts +17 -0
  64. package/src/channels/router.ts +199 -0
  65. package/src/channels/signal.ts +133 -0
  66. package/src/channels/slack.ts +101 -0
  67. package/src/channels/telegram.ts +102 -0
  68. package/src/channels/utils.ts +18 -0
  69. package/src/channels/webchat.ts +1797 -0
  70. package/src/channels/whatsapp.ts +119 -0
  71. package/src/config/loader.ts +22 -0
  72. package/src/config/paths.ts +43 -0
  73. package/src/config/schema.ts +121 -0
  74. package/src/db/connection.ts +20 -0
  75. package/src/db/export.ts +148 -0
  76. package/src/db/migrations.ts +42 -0
  77. package/src/index.ts +261 -0
  78. package/src/llm/claude.ts +193 -0
  79. package/src/llm/factory.ts +115 -0
  80. package/src/llm/failover.ts +101 -0
  81. package/src/llm/openai-compat.ts +409 -0
  82. package/src/llm/provider.ts +83 -0
  83. package/src/llm/smart-router.ts +241 -0
  84. package/src/logs.ts +53 -0
  85. package/src/memory/chunker.ts +58 -0
  86. package/src/memory/document-parser.ts +115 -0
  87. package/src/memory/embedder.ts +235 -0
  88. package/src/memory/engine.ts +170 -0
  89. package/src/memory/fts-index.ts +55 -0
  90. package/src/memory/hybrid-search.ts +72 -0
  91. package/src/memory/store.ts +56 -0
  92. package/src/memory/vector-index.ts +72 -0
  93. package/src/model.ts +118 -0
  94. package/src/registry/cli.ts +43 -0
  95. package/src/registry/client.ts +54 -0
  96. package/src/registry/installer.ts +67 -0
  97. package/src/scheduler/briefing.ts +71 -0
  98. package/src/scheduler/cron.ts +258 -0
  99. package/src/scheduler/heartbeat.ts +58 -0
  100. package/src/scheduler/memory-triggers.ts +100 -0
  101. package/src/scheduler/natural-cron.ts +163 -0
  102. package/src/scheduler/proactive.ts +25 -0
  103. package/src/scheduler/recipes.ts +110 -0
  104. package/src/secrets/store.ts +64 -0
  105. package/src/setup.ts +413 -0
  106. package/src/skills.ts +293 -0
  107. package/src/start.ts +373 -0
  108. package/src/status.ts +165 -0
  109. package/src/tools/builtin/connect-service.ts +205 -0
  110. package/src/tools/builtin/cron.ts +126 -0
  111. package/src/tools/builtin/datetime.ts +36 -0
  112. package/src/tools/builtin/delegate-task.ts +81 -0
  113. package/src/tools/builtin/delegate.ts +42 -0
  114. package/src/tools/builtin/diagnose.ts +41 -0
  115. package/src/tools/builtin/google-oauth.ts +379 -0
  116. package/src/tools/builtin/manage-agents.ts +149 -0
  117. package/src/tools/builtin/manage-skills.ts +294 -0
  118. package/src/tools/builtin/manage-teams.ts +89 -0
  119. package/src/tools/builtin/manage-triggers.ts +94 -0
  120. package/src/tools/builtin/manage-workflows.ts +119 -0
  121. package/src/tools/builtin/memory-search.ts +38 -0
  122. package/src/tools/builtin/memory-write.ts +30 -0
  123. package/src/tools/builtin/run-workflow.ts +36 -0
  124. package/src/tools/builtin/secrets.ts +122 -0
  125. package/src/tools/builtin/skill-registry.ts +75 -0
  126. package/src/tools/builtin-integrations/api-helpers.ts +26 -0
  127. package/src/tools/builtin-integrations/github/github_issues/SKILL.md +56 -0
  128. package/src/tools/builtin-integrations/github/github_issues/handler.ts +108 -0
  129. package/src/tools/builtin-integrations/github/github_prs/SKILL.md +57 -0
  130. package/src/tools/builtin-integrations/github/github_prs/handler.ts +113 -0
  131. package/src/tools/builtin-integrations/github/github_repos/SKILL.md +37 -0
  132. package/src/tools/builtin-integrations/github/github_repos/handler.ts +88 -0
  133. package/src/tools/builtin-integrations/google/gmail/SKILL.md +51 -0
  134. package/src/tools/builtin-integrations/google/gmail/handler.ts +125 -0
  135. package/src/tools/builtin-integrations/google/google_calendar/SKILL.md +35 -0
  136. package/src/tools/builtin-integrations/google/google_calendar/handler.ts +105 -0
  137. package/src/tools/builtin-integrations/google/google_docs/SKILL.md +35 -0
  138. package/src/tools/builtin-integrations/google/google_docs/handler.ts +108 -0
  139. package/src/tools/builtin-integrations/google/google_drive/SKILL.md +39 -0
  140. package/src/tools/builtin-integrations/google/google_drive/handler.ts +106 -0
  141. package/src/tools/builtin-integrations/google/google_sheets/SKILL.md +36 -0
  142. package/src/tools/builtin-integrations/google/google_sheets/handler.ts +116 -0
  143. package/src/tools/builtin-integrations/jira/jira_boards/SKILL.md +21 -0
  144. package/src/tools/builtin-integrations/jira/jira_boards/handler.ts +74 -0
  145. package/src/tools/builtin-integrations/jira/jira_issues/SKILL.md +28 -0
  146. package/src/tools/builtin-integrations/jira/jira_issues/handler.ts +140 -0
  147. package/src/tools/builtin-integrations/linear/linear_issues/SKILL.md +30 -0
  148. package/src/tools/builtin-integrations/linear/linear_issues/handler.ts +75 -0
  149. package/src/tools/builtin-integrations/linear/linear_projects/SKILL.md +21 -0
  150. package/src/tools/builtin-integrations/linear/linear_projects/handler.ts +43 -0
  151. package/src/tools/builtin-integrations/notion/notion_databases/SKILL.md +39 -0
  152. package/src/tools/builtin-integrations/notion/notion_databases/handler.ts +83 -0
  153. package/src/tools/builtin-integrations/notion/notion_pages/SKILL.md +43 -0
  154. package/src/tools/builtin-integrations/notion/notion_pages/handler.ts +130 -0
  155. package/src/tools/builtin-integrations/notion/notion_search/SKILL.md +27 -0
  156. package/src/tools/builtin-integrations/notion/notion_search/handler.ts +69 -0
  157. package/src/tools/builtin-integrations/slack/slack_messages/SKILL.md +42 -0
  158. package/src/tools/builtin-integrations/slack/slack_messages/handler.ts +72 -0
  159. package/src/tools/builtin-integrations/twitter/twitter_posts/SKILL.md +24 -0
  160. package/src/tools/builtin-integrations/twitter/twitter_posts/handler.ts +133 -0
  161. package/src/tools/builtin-skills/file-read/SKILL.md +26 -0
  162. package/src/tools/builtin-skills/file-read/handler.ts +66 -0
  163. package/src/tools/builtin-skills/file-write/SKILL.md +30 -0
  164. package/src/tools/builtin-skills/file-write/handler.ts +64 -0
  165. package/src/tools/builtin-skills/http-request/SKILL.md +34 -0
  166. package/src/tools/builtin-skills/http-request/handler.ts +87 -0
  167. package/src/tools/builtin-skills/shell/SKILL.md +26 -0
  168. package/src/tools/builtin-skills/shell/handler.ts +96 -0
  169. package/src/tools/builtin-skills/url-fetch/SKILL.md +26 -0
  170. package/src/tools/builtin-skills/url-fetch/handler.ts +37 -0
  171. package/src/tools/builtin-skills/web-search/SKILL.md +26 -0
  172. package/src/tools/builtin-skills/web-search/handler.ts +50 -0
  173. package/src/tools/executor.ts +205 -0
  174. package/src/tools/integration-installer.ts +106 -0
  175. package/src/tools/permissions.ts +45 -0
  176. package/src/tools/registry.ts +39 -0
  177. package/src/tools/sandbox-runner.ts +56 -0
  178. package/src/tools/sandbox.ts +82 -0
  179. package/src/tools/skill-installer.ts +52 -0
  180. package/src/tools/skill-loader.ts +259 -0
  181. package/src/types/optional-deps.d.ts +23 -0
  182. package/src/util/auth.ts +121 -0
  183. package/src/util/costs.ts +59 -0
  184. package/src/util/error-buffer.ts +32 -0
  185. package/src/util/google-tokens.ts +180 -0
  186. package/src/util/logger.ts +73 -0
  187. package/src/util/perf-collector.ts +35 -0
  188. package/src/util/rate-limiter.ts +70 -0
  189. package/src/util/tokens.ts +17 -0
  190. package/src/voice/stt.ts +57 -0
  191. package/src/voice/tts.ts +103 -0
  192. package/tests/agent/session.test.ts +109 -0
  193. package/tests/agent-loop.test.ts +54 -0
  194. package/tests/auth.test.ts +89 -0
  195. package/tests/channels.test.ts +67 -0
  196. package/tests/compaction.test.ts +44 -0
  197. package/tests/config.test.ts +51 -0
  198. package/tests/costs.test.ts +19 -0
  199. package/tests/cron.test.ts +55 -0
  200. package/tests/db/export.test.ts +219 -0
  201. package/tests/executor.test.ts +144 -0
  202. package/tests/export.test.ts +137 -0
  203. package/tests/helpers/mock-llm.ts +34 -0
  204. package/tests/helpers/test-db.ts +74 -0
  205. package/tests/integration/chat-flow.test.ts +48 -0
  206. package/tests/integrations.test.ts +97 -0
  207. package/tests/memory/engine.test.ts +114 -0
  208. package/tests/memory-engine.test.ts +57 -0
  209. package/tests/permissions.test.ts +21 -0
  210. package/tests/rate-limiter.test.ts +70 -0
  211. package/tests/registry.test.ts +67 -0
  212. package/tests/router.test.ts +36 -0
  213. package/tests/session.test.ts +58 -0
  214. package/tests/skill-loader.test.ts +44 -0
  215. package/tests/tokens.test.ts +30 -0
  216. package/tests/tools/executor.test.ts +130 -0
  217. package/tests/util/auth.test.ts +75 -0
  218. package/tests/util/rate-limiter.test.ts +73 -0
  219. package/tests/voice.test.ts +60 -0
  220. package/tests/webchat.test.ts +88 -0
  221. package/tests/workflow.test.ts +38 -0
  222. package/tsconfig.json +16 -0
@@ -0,0 +1,189 @@
1
+ // Zubo Desktop — Tauri v2 entry point
2
+ // Spawns the Zubo backend (bun run src/index.ts start) and wraps it in a native window.
3
+
4
+ #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
5
+
6
+ use std::io::{BufRead, BufReader};
7
+ use std::process::{Child, Command, Stdio};
8
+ use std::sync::Mutex;
9
+
10
+ use tauri::{
11
+ image::Image,
12
+ menu::{MenuBuilder, MenuItemBuilder},
13
+ tray::TrayIconBuilder,
14
+ Emitter, Manager, RunEvent, WindowEvent,
15
+ };
16
+ use tauri_plugin_global_shortcut::{GlobalShortcutExt, Shortcut, ShortcutState};
17
+
18
+ /// Discover the port Zubo is listening on by reading its stdout.
19
+ /// Looks for a line containing "localhost:" followed by digits.
20
+ fn discover_port(reader: &mut BufReader<impl std::io::Read>) -> Option<u16> {
21
+ let mut buf = String::new();
22
+ // Read up to 50 lines looking for the port announcement
23
+ for _ in 0..50 {
24
+ buf.clear();
25
+ if reader.read_line(&mut buf).unwrap_or(0) == 0 {
26
+ break;
27
+ }
28
+ // Match patterns like "http://localhost:3000" or "localhost:3000"
29
+ if let Some(idx) = buf.find("localhost:") {
30
+ let after = &buf[idx + "localhost:".len()..];
31
+ let digits: String = after.chars().take_while(|c| c.is_ascii_digit()).collect();
32
+ if let Ok(port) = digits.parse::<u16>() {
33
+ return Some(port);
34
+ }
35
+ }
36
+ }
37
+ None
38
+ }
39
+
40
+ /// Spawn the Zubo backend process. The working directory is the project root
41
+ /// (one level above the `desktop/` folder).
42
+ fn spawn_zubo() -> (Child, u16) {
43
+ let project_root = std::env::current_dir()
44
+ .expect("cannot determine cwd")
45
+ .parent()
46
+ .map(|p| p.to_path_buf())
47
+ .unwrap_or_else(|| std::env::current_dir().unwrap());
48
+
49
+ let mut child = Command::new("bun")
50
+ .args(["run", "src/index.ts", "start"])
51
+ .current_dir(&project_root)
52
+ .stdout(Stdio::piped())
53
+ .stderr(Stdio::inherit())
54
+ .spawn()
55
+ .expect("failed to spawn Zubo process — is `bun` installed?");
56
+
57
+ let stdout = child.stdout.take().expect("failed to capture Zubo stdout");
58
+ let mut reader = BufReader::new(stdout);
59
+
60
+ let port = discover_port(&mut reader).unwrap_or_else(|| {
61
+ eprintln!("warn: could not discover Zubo port from stdout, falling back to 3000");
62
+ 3000
63
+ });
64
+
65
+ // Continue draining stdout in a background thread so the child process
66
+ // does not block on a full pipe buffer.
67
+ std::thread::spawn(move || {
68
+ let mut sink = String::new();
69
+ loop {
70
+ sink.clear();
71
+ match reader.read_line(&mut sink) {
72
+ Ok(0) | Err(_) => break,
73
+ _ => {} // discard
74
+ }
75
+ }
76
+ });
77
+
78
+ (child, port)
79
+ }
80
+
81
+ fn main() {
82
+ let (child, port) = spawn_zubo();
83
+ let child: Mutex<Option<Child>> = Mutex::new(Some(child));
84
+
85
+ let app = tauri::Builder::default()
86
+ .plugin(tauri_plugin_autostart::init(
87
+ tauri_plugin_autostart::MacosLauncher::LaunchAgent,
88
+ None,
89
+ ))
90
+ .plugin(tauri_plugin_notification::init())
91
+ .setup(move |app| {
92
+ // ── Main window ──────────────────────────────────────────
93
+ let url = format!("http://localhost:{}", port);
94
+ let window = tauri::WebviewWindowBuilder::new(
95
+ app,
96
+ "main",
97
+ tauri::WebviewUrl::External(url.parse().unwrap()),
98
+ )
99
+ .title("Zubo")
100
+ .inner_size(1000.0, 700.0)
101
+ .center()
102
+ .decorations(true)
103
+ .hidden_title(true)
104
+ .title_bar_style(tauri::TitleBarStyle::Transparent)
105
+ .build()?;
106
+
107
+ // ── System tray ──────────────────────────────────────────
108
+ let open_item = MenuItemBuilder::with_id("open", "Open Zubo").build(app)?;
109
+ let quit_item = MenuItemBuilder::with_id("quit", "Quit").build(app)?;
110
+ let tray_menu = MenuBuilder::new(app)
111
+ .item(&open_item)
112
+ .separator()
113
+ .item(&quit_item)
114
+ .build()?;
115
+
116
+ let _tray = TrayIconBuilder::new()
117
+ .icon(Image::from_bytes(include_bytes!("../icons/icon.png")).unwrap_or_else(|_| {
118
+ // Fallback: 1x1 transparent PNG if icon file is missing / invalid
119
+ Image::from_bytes(include_bytes!("../icons/icon.png"))
120
+ .expect("tray icon not found")
121
+ }))
122
+ .menu(&tray_menu)
123
+ .on_menu_event(move |app_handle, event| match event.id().as_ref() {
124
+ "open" => {
125
+ if let Some(w) = app_handle.get_webview_window("main") {
126
+ let _ = w.show();
127
+ let _ = w.set_focus();
128
+ }
129
+ }
130
+ "quit" => {
131
+ app_handle.exit(0);
132
+ }
133
+ _ => {}
134
+ })
135
+ .build(app)?;
136
+
137
+ // ── Global shortcut: Cmd+Shift+Z (macOS) / Ctrl+Shift+Z ─
138
+ let shortcut: Shortcut = if cfg!(target_os = "macos") {
139
+ "CmdOrCtrl+Shift+Z".parse().unwrap()
140
+ } else {
141
+ "Ctrl+Shift+Z".parse().unwrap()
142
+ };
143
+
144
+ let handle = app.handle().clone();
145
+ app.handle().plugin(
146
+ tauri_plugin_global_shortcut::Builder::new()
147
+ .with_handler(move |_app, _shortcut, event| {
148
+ if event.state() == ShortcutState::Pressed {
149
+ if let Some(w) = handle.get_webview_window("main") {
150
+ if w.is_visible().unwrap_or(false) {
151
+ let _ = w.hide();
152
+ } else {
153
+ let _ = w.show();
154
+ let _ = w.set_focus();
155
+ }
156
+ }
157
+ }
158
+ })
159
+ .build(),
160
+ )?;
161
+ app.global_shortcut().register(shortcut)?;
162
+
163
+ // ── Hide on close instead of quitting ────────────────────
164
+ let win = window.clone();
165
+ win.on_window_event(move |event| {
166
+ if let WindowEvent::CloseRequested { api, .. } = event {
167
+ api.prevent_close();
168
+ let _ = window.hide();
169
+ }
170
+ });
171
+
172
+ Ok(())
173
+ })
174
+ .build(tauri::generate_context!())
175
+ .expect("failed to build Tauri app");
176
+
177
+ app.run(move |_app_handle, event| {
178
+ if let RunEvent::ExitRequested { .. } = &event {
179
+ // Clean up the Zubo child process
180
+ if let Ok(mut guard) = child.lock() {
181
+ if let Some(ref mut c) = *guard {
182
+ let _ = c.kill();
183
+ let _ = c.wait();
184
+ }
185
+ *guard = None;
186
+ }
187
+ }
188
+ });
189
+ }
@@ -0,0 +1,68 @@
1
+ {
2
+ "$schema": "https://raw.githubusercontent.com/nickelpack/tauri/v2/packages/tauri/schema.json",
3
+ "productName": "Zubo",
4
+ "identifier": "com.zubo.desktop",
5
+ "version": "0.1.0",
6
+ "build": {
7
+ "frontendDist": "../dist",
8
+ "devUrl": "http://localhost:3000",
9
+ "beforeDevCommand": "",
10
+ "beforeBuildCommand": ""
11
+ },
12
+ "app": {
13
+ "withGlobalTauri": true,
14
+ "windows": [
15
+ {
16
+ "label": "main",
17
+ "title": "Zubo",
18
+ "width": 1000,
19
+ "height": 700,
20
+ "center": true,
21
+ "decorations": true,
22
+ "hiddenTitle": true,
23
+ "titleBarStyle": "Transparent",
24
+ "url": "http://localhost:3000"
25
+ }
26
+ ],
27
+ "trayIcon": {
28
+ "iconPath": "icons/icon.png",
29
+ "iconAsTemplate": true
30
+ },
31
+ "security": {
32
+ "csp": "default-src 'self'; connect-src 'self' http://localhost:* ws://localhost:*; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:"
33
+ }
34
+ },
35
+ "bundle": {
36
+ "active": true,
37
+ "targets": ["dmg", "msi", "appimage"],
38
+ "icon": [
39
+ "icons/32x32.png",
40
+ "icons/128x128.png",
41
+ "icons/128x128@2x.png",
42
+ "icons/icon.icns",
43
+ "icons/icon.ico"
44
+ ],
45
+ "macOS": {
46
+ "minimumSystemVersion": "10.15",
47
+ "frameworks": []
48
+ },
49
+ "windows": {
50
+ "wix": {
51
+ "language": "en-US"
52
+ }
53
+ },
54
+ "linux": {
55
+ "deb": {
56
+ "depends": ["libwebkit2gtk-4.1-0", "libgtk-3-0"]
57
+ }
58
+ }
59
+ },
60
+ "plugins": {
61
+ "autostart": {
62
+ "macosLauncher": "LaunchAgent",
63
+ "args": []
64
+ },
65
+ "global-shortcut": {},
66
+ "notification": {}
67
+ }
68
+ }