beecork 1.7.1 → 2.0.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 (253) hide show
  1. package/README.md +52 -111
  2. package/dist/index.js +1394 -581
  3. package/package.json +26 -54
  4. package/dist/capabilities/index.d.ts +0 -3
  5. package/dist/capabilities/index.js +0 -2
  6. package/dist/capabilities/manager.d.ts +0 -13
  7. package/dist/capabilities/manager.js +0 -115
  8. package/dist/capabilities/packs.d.ts +0 -2
  9. package/dist/capabilities/packs.js +0 -54
  10. package/dist/capabilities/types.d.ts +0 -21
  11. package/dist/capabilities/types.js +0 -1
  12. package/dist/channels/admin.d.ts +0 -10
  13. package/dist/channels/admin.js +0 -20
  14. package/dist/channels/command-handler.d.ts +0 -19
  15. package/dist/channels/command-handler.js +0 -235
  16. package/dist/channels/discord.d.ts +0 -17
  17. package/dist/channels/discord.js +0 -266
  18. package/dist/channels/index.d.ts +0 -7
  19. package/dist/channels/index.js +0 -6
  20. package/dist/channels/loader.d.ts +0 -7
  21. package/dist/channels/loader.js +0 -87
  22. package/dist/channels/pipeline.d.ts +0 -50
  23. package/dist/channels/pipeline.js +0 -92
  24. package/dist/channels/registry.d.ts +0 -36
  25. package/dist/channels/registry.js +0 -80
  26. package/dist/channels/send-helpers.d.ts +0 -19
  27. package/dist/channels/send-helpers.js +0 -21
  28. package/dist/channels/telegram.d.ts +0 -47
  29. package/dist/channels/telegram.js +0 -649
  30. package/dist/channels/types.d.ts +0 -41
  31. package/dist/channels/types.js +0 -1
  32. package/dist/channels/voice-state.d.ts +0 -29
  33. package/dist/channels/voice-state.js +0 -45
  34. package/dist/channels/webhook.d.ts +0 -16
  35. package/dist/channels/webhook.js +0 -222
  36. package/dist/channels/whatsapp.d.ts +0 -28
  37. package/dist/channels/whatsapp.js +0 -323
  38. package/dist/cli/capabilities.d.ts +0 -3
  39. package/dist/cli/capabilities.js +0 -72
  40. package/dist/cli/channel.d.ts +0 -3
  41. package/dist/cli/channel.js +0 -202
  42. package/dist/cli/commands.d.ts +0 -15
  43. package/dist/cli/commands.js +0 -279
  44. package/dist/cli/doctor.d.ts +0 -1
  45. package/dist/cli/doctor.js +0 -208
  46. package/dist/cli/handoff.d.ts +0 -8
  47. package/dist/cli/handoff.js +0 -33
  48. package/dist/cli/helpers.d.ts +0 -2
  49. package/dist/cli/helpers.js +0 -21
  50. package/dist/cli/mcp.d.ts +0 -3
  51. package/dist/cli/mcp.js +0 -47
  52. package/dist/cli/media.d.ts +0 -2
  53. package/dist/cli/media.js +0 -125
  54. package/dist/cli/setup.d.ts +0 -1
  55. package/dist/cli/setup.js +0 -239
  56. package/dist/cli/store.d.ts +0 -3
  57. package/dist/cli/store.js +0 -108
  58. package/dist/config.d.ts +0 -11
  59. package/dist/config.js +0 -115
  60. package/dist/cron/scheduler.d.ts +0 -22
  61. package/dist/cron/scheduler.js +0 -220
  62. package/dist/cron/store.d.ts +0 -12
  63. package/dist/cron/store.js +0 -83
  64. package/dist/daemon.d.ts +0 -1
  65. package/dist/daemon.js +0 -345
  66. package/dist/dashboard/html.d.ts +0 -1
  67. package/dist/dashboard/html.js +0 -849
  68. package/dist/dashboard/routes.d.ts +0 -17
  69. package/dist/dashboard/routes.js +0 -623
  70. package/dist/dashboard/server.d.ts +0 -1
  71. package/dist/dashboard/server.js +0 -104
  72. package/dist/db/connection.d.ts +0 -29
  73. package/dist/db/connection.js +0 -37
  74. package/dist/db/index.d.ts +0 -14
  75. package/dist/db/index.js +0 -127
  76. package/dist/db/migrations.d.ts +0 -2
  77. package/dist/db/migrations.js +0 -384
  78. package/dist/delegation/manager.d.ts +0 -18
  79. package/dist/delegation/manager.js +0 -89
  80. package/dist/index.d.ts +0 -2
  81. package/dist/knowledge/index.d.ts +0 -2
  82. package/dist/knowledge/index.js +0 -1
  83. package/dist/knowledge/manager.d.ts +0 -17
  84. package/dist/knowledge/manager.js +0 -160
  85. package/dist/knowledge/types.d.ts +0 -7
  86. package/dist/knowledge/types.js +0 -1
  87. package/dist/machines/forwarder.d.ts +0 -7
  88. package/dist/machines/forwarder.js +0 -35
  89. package/dist/machines/index.d.ts +0 -1
  90. package/dist/machines/index.js +0 -1
  91. package/dist/machines/registry.d.ts +0 -15
  92. package/dist/machines/registry.js +0 -46
  93. package/dist/mcp/handlers.d.ts +0 -37
  94. package/dist/mcp/handlers.js +0 -520
  95. package/dist/mcp/server.d.ts +0 -2
  96. package/dist/mcp/server.js +0 -86
  97. package/dist/mcp/tool-definitions.d.ts +0 -1225
  98. package/dist/mcp/tool-definitions.js +0 -412
  99. package/dist/mcp/validate.d.ts +0 -23
  100. package/dist/mcp/validate.js +0 -65
  101. package/dist/media/factory.d.ts +0 -6
  102. package/dist/media/factory.js +0 -36
  103. package/dist/media/generators/dall-e.d.ts +0 -10
  104. package/dist/media/generators/dall-e.js +0 -41
  105. package/dist/media/generators/elevenlabs-music.d.ts +0 -9
  106. package/dist/media/generators/elevenlabs-music.js +0 -34
  107. package/dist/media/generators/elevenlabs-sfx.d.ts +0 -9
  108. package/dist/media/generators/elevenlabs-sfx.js +0 -33
  109. package/dist/media/generators/kling.d.ts +0 -9
  110. package/dist/media/generators/kling.js +0 -47
  111. package/dist/media/generators/lyria.d.ts +0 -10
  112. package/dist/media/generators/lyria.js +0 -41
  113. package/dist/media/generators/nano-banana.d.ts +0 -10
  114. package/dist/media/generators/nano-banana.js +0 -45
  115. package/dist/media/generators/poll-util.d.ts +0 -12
  116. package/dist/media/generators/poll-util.js +0 -22
  117. package/dist/media/generators/recraft.d.ts +0 -9
  118. package/dist/media/generators/recraft.js +0 -52
  119. package/dist/media/generators/runway.d.ts +0 -9
  120. package/dist/media/generators/runway.js +0 -49
  121. package/dist/media/generators/stable-diffusion.d.ts +0 -9
  122. package/dist/media/generators/stable-diffusion.js +0 -35
  123. package/dist/media/generators/veo.d.ts +0 -9
  124. package/dist/media/generators/veo.js +0 -32
  125. package/dist/media/index.d.ts +0 -6
  126. package/dist/media/index.js +0 -8
  127. package/dist/media/loader.d.ts +0 -8
  128. package/dist/media/loader.js +0 -46
  129. package/dist/media/store.d.ts +0 -17
  130. package/dist/media/store.js +0 -69
  131. package/dist/media/types.d.ts +0 -43
  132. package/dist/media/types.js +0 -1
  133. package/dist/memory/extractor.d.ts +0 -5
  134. package/dist/memory/extractor.js +0 -157
  135. package/dist/notifications/index.d.ts +0 -4
  136. package/dist/notifications/index.js +0 -21
  137. package/dist/notifications/ntfy.d.ts +0 -9
  138. package/dist/notifications/ntfy.js +0 -25
  139. package/dist/notifications/pushover.d.ts +0 -9
  140. package/dist/notifications/pushover.js +0 -26
  141. package/dist/notifications/types.d.ts +0 -5
  142. package/dist/notifications/types.js +0 -1
  143. package/dist/notifications/webhook-provider.d.ts +0 -9
  144. package/dist/notifications/webhook-provider.js +0 -24
  145. package/dist/observability/analytics.d.ts +0 -30
  146. package/dist/observability/analytics.js +0 -118
  147. package/dist/pipe/anthropic-client.d.ts +0 -9
  148. package/dist/pipe/anthropic-client.js +0 -50
  149. package/dist/pipe/brain.d.ts +0 -16
  150. package/dist/pipe/brain.js +0 -89
  151. package/dist/pipe/memory-store.d.ts +0 -8
  152. package/dist/pipe/memory-store.js +0 -39
  153. package/dist/pipe/project-scanner.d.ts +0 -6
  154. package/dist/pipe/project-scanner.js +0 -26
  155. package/dist/pipe/types.d.ts +0 -34
  156. package/dist/pipe/types.js +0 -1
  157. package/dist/projects/index.d.ts +0 -4
  158. package/dist/projects/index.js +0 -2
  159. package/dist/projects/manager.d.ts +0 -13
  160. package/dist/projects/manager.js +0 -166
  161. package/dist/projects/router.d.ts +0 -17
  162. package/dist/projects/router.js +0 -246
  163. package/dist/projects/types.d.ts +0 -19
  164. package/dist/projects/types.js +0 -1
  165. package/dist/service/install.d.ts +0 -4
  166. package/dist/service/install.js +0 -146
  167. package/dist/service/templates.d.ts +0 -4
  168. package/dist/service/templates.js +0 -52
  169. package/dist/service/windows.d.ts +0 -8
  170. package/dist/service/windows.js +0 -59
  171. package/dist/session/budget-guard.d.ts +0 -20
  172. package/dist/session/budget-guard.js +0 -31
  173. package/dist/session/circuit-breaker.d.ts +0 -19
  174. package/dist/session/circuit-breaker.js +0 -91
  175. package/dist/session/context-compactor.d.ts +0 -32
  176. package/dist/session/context-compactor.js +0 -45
  177. package/dist/session/context-monitor.d.ts +0 -15
  178. package/dist/session/context-monitor.js +0 -44
  179. package/dist/session/handoff.d.ts +0 -21
  180. package/dist/session/handoff.js +0 -50
  181. package/dist/session/manager.d.ts +0 -60
  182. package/dist/session/manager.js +0 -416
  183. package/dist/session/memory-store.d.ts +0 -29
  184. package/dist/session/memory-store.js +0 -45
  185. package/dist/session/message-queue.d.ts +0 -28
  186. package/dist/session/message-queue.js +0 -52
  187. package/dist/session/pending-dispatcher.d.ts +0 -31
  188. package/dist/session/pending-dispatcher.js +0 -120
  189. package/dist/session/pending-store.d.ts +0 -60
  190. package/dist/session/pending-store.js +0 -118
  191. package/dist/session/stale-session.d.ts +0 -31
  192. package/dist/session/stale-session.js +0 -45
  193. package/dist/session/subprocess.d.ts +0 -32
  194. package/dist/session/subprocess.js +0 -230
  195. package/dist/session/tab-store.d.ts +0 -28
  196. package/dist/session/tab-store.js +0 -78
  197. package/dist/session/tool-classifier.d.ts +0 -4
  198. package/dist/session/tool-classifier.js +0 -56
  199. package/dist/tasks/scheduler.d.ts +0 -45
  200. package/dist/tasks/scheduler.js +0 -329
  201. package/dist/tasks/store.d.ts +0 -11
  202. package/dist/tasks/store.js +0 -103
  203. package/dist/timeline/index.d.ts +0 -3
  204. package/dist/timeline/index.js +0 -2
  205. package/dist/timeline/logger.d.ts +0 -8
  206. package/dist/timeline/logger.js +0 -11
  207. package/dist/timeline/query.d.ts +0 -11
  208. package/dist/timeline/query.js +0 -67
  209. package/dist/timeline/types.d.ts +0 -12
  210. package/dist/timeline/types.js +0 -1
  211. package/dist/types.d.ts +0 -225
  212. package/dist/types.js +0 -3
  213. package/dist/users/index.d.ts +0 -2
  214. package/dist/users/index.js +0 -1
  215. package/dist/users/service.d.ts +0 -17
  216. package/dist/users/service.js +0 -46
  217. package/dist/util/auto-heal.d.ts +0 -43
  218. package/dist/util/auto-heal.js +0 -107
  219. package/dist/util/install-info.d.ts +0 -37
  220. package/dist/util/install-info.js +0 -80
  221. package/dist/util/logger.d.ts +0 -18
  222. package/dist/util/logger.js +0 -118
  223. package/dist/util/paths.d.ts +0 -13
  224. package/dist/util/paths.js +0 -55
  225. package/dist/util/platform.d.ts +0 -2
  226. package/dist/util/platform.js +0 -11
  227. package/dist/util/progress.d.ts +0 -34
  228. package/dist/util/progress.js +0 -133
  229. package/dist/util/rate-limiter.d.ts +0 -14
  230. package/dist/util/rate-limiter.js +0 -50
  231. package/dist/util/retry.d.ts +0 -2
  232. package/dist/util/retry.js +0 -18
  233. package/dist/util/text.d.ts +0 -32
  234. package/dist/util/text.js +0 -101
  235. package/dist/version.d.ts +0 -1
  236. package/dist/version.js +0 -4
  237. package/dist/voice/index.d.ts +0 -17
  238. package/dist/voice/index.js +0 -42
  239. package/dist/voice/stt.d.ts +0 -16
  240. package/dist/voice/stt.js +0 -57
  241. package/dist/voice/tts.d.ts +0 -23
  242. package/dist/voice/tts.js +0 -84
  243. package/dist/watchers/evaluator.d.ts +0 -5
  244. package/dist/watchers/evaluator.js +0 -45
  245. package/dist/watchers/index.d.ts +0 -4
  246. package/dist/watchers/index.js +0 -3
  247. package/dist/watchers/scheduler.d.ts +0 -20
  248. package/dist/watchers/scheduler.js +0 -183
  249. package/dist/watchers/store.d.ts +0 -10
  250. package/dist/watchers/store.js +0 -56
  251. package/dist/watchers/types.d.ts +0 -15
  252. package/dist/watchers/types.js +0 -1
  253. package/scripts/postinstall.mjs +0 -50
@@ -1,230 +0,0 @@
1
- import { spawn } from 'node:child_process';
2
- import fs from 'node:fs';
3
- import { v4 as uuidv4 } from 'uuid';
4
- import { logger } from '../util/logger.js';
5
- import { getMcpConfigPath } from '../util/paths.js';
6
- // Cache the MCP-config existence check. The file is created at setup time and
7
- // stable for the daemon's lifetime; we don't need to stat() it per spawn.
8
- let mcpConfigExistsCache = null;
9
- function mcpConfigExists() {
10
- if (mcpConfigExistsCache !== null)
11
- return mcpConfigExistsCache;
12
- mcpConfigExistsCache = fs.existsSync(getMcpConfigPath());
13
- return mcpConfigExistsCache;
14
- }
15
- /** Test-only — reset the existsSync cache between test runs that toggle the mock. */
16
- export function _resetMcpConfigExistsCacheForTests() {
17
- mcpConfigExistsCache = null;
18
- }
19
- const BEECORK_SYSTEM_PROMPT = `You are running inside Beecork, an always-on infrastructure for Claude Code.
20
-
21
- You have these special MCP tools available:
22
- - beecork_remember: Store important facts for future sessions (preferences, server addresses, decisions, outcomes)
23
- - beecork_recall: Search stored memories — ALWAYS call this at the start of complex tasks
24
- - beecork_task_create: Schedule recurring tasks (types: "at" for one-time, "every" for interval like "30m", "cron" for expressions like "0 9 * * 1")
25
- - beecork_task_list: List scheduled tasks
26
- - beecork_task_delete: Remove a scheduled task
27
- - beecork_tab_create: Create a new virtual tab for parallel work
28
- - beecork_tab_list: List all tabs
29
- - beecork_send_message: Send a message to another tab
30
- - beecork_notify: Send the user a notification mid-task without stopping
31
- - beecork_status: Check system status
32
-
33
- Guidelines:
34
- - You are running unattended. Be thorough and complete tasks fully.
35
- - Always call beecork_recall at the start of any task to check relevant memories.
36
- - Always call beecork_remember when you learn something important.
37
- - When asked for recurring tasks, use beecork_task_create.
38
- - Use beecork_notify for progress updates during long tasks.`;
39
- export class ClaudeSubprocess {
40
- tabName;
41
- workingDir;
42
- config;
43
- tabSystemPrompt;
44
- proc = null;
45
- buffer = '';
46
- killTimer = null;
47
- runtimeTimer = null;
48
- startupTimer = null;
49
- /**
50
- * Set when the startup watchdog kills a subprocess that never emitted a
51
- * single event — distinguishes a transient network/connection stall from a
52
- * normal exit or a real wall-clock overrun, so the manager can retry once.
53
- */
54
- killReason = null;
55
- sessionId;
56
- constructor(tabName, workingDir, config, sessionId, tabSystemPrompt) {
57
- this.tabName = tabName;
58
- this.workingDir = workingDir;
59
- this.config = config;
60
- this.tabSystemPrompt = tabSystemPrompt;
61
- this.sessionId = sessionId ?? uuidv4();
62
- }
63
- async send(prompt, callbacks, resume = false) {
64
- if (this.proc) {
65
- throw new Error(`Subprocess for tab "${this.tabName}" is already running`);
66
- }
67
- const args = this.buildArgs(prompt, resume);
68
- logger.debug(`[${this.tabName}] Spawning: ${this.config.claudeCode.bin} ${args.join(' ')}`);
69
- this.proc = spawn(this.config.claudeCode.bin, args, {
70
- cwd: this.workingDir,
71
- stdio: ['ignore', 'pipe', 'pipe'],
72
- env: { ...process.env },
73
- });
74
- const pid = this.proc.pid;
75
- logger.info(`[${this.tabName}] Claude subprocess started (PID: ${pid})`);
76
- this.proc.stdout.on('data', (chunk) => {
77
- this.buffer += chunk.toString();
78
- const lines = this.buffer.split('\n');
79
- this.buffer = lines.pop() || '';
80
- for (const line of lines) {
81
- if (!line.trim())
82
- continue;
83
- try {
84
- const event = JSON.parse(line);
85
- // First real event proves claude initialized and the socket is alive
86
- // — the startup-stall window is over, so disarm the watchdog for good.
87
- // It never re-arms, so legitimate multi-minute tool runs (which emit
88
- // nothing on stdout until the tool returns) are never killed.
89
- if (this.startupTimer) {
90
- clearTimeout(this.startupTimer);
91
- this.startupTimer = null;
92
- }
93
- callbacks.onEvent(event);
94
- }
95
- catch {
96
- // Non-JSON line (verbose debug output), skip
97
- logger.debug(`[${this.tabName}] non-json: ${line.slice(0, 200)}`);
98
- }
99
- }
100
- });
101
- this.proc.stderr.on('data', (chunk) => {
102
- const text = chunk.toString().trim();
103
- if (text) {
104
- // claude prints auth failures, rate limits, license issues, and other
105
- // operational errors to stderr. Surface at warn so they reach daemon.log
106
- // at the default level — debugging "why did claude exit?" otherwise
107
- // requires recompiling with a different log level.
108
- logger.warn(`[${this.tabName}] claude stderr: ${text.slice(0, 500)}`);
109
- }
110
- });
111
- this.proc.on('error', (err) => {
112
- this.proc = null;
113
- if (this.runtimeTimer) {
114
- clearTimeout(this.runtimeTimer);
115
- this.runtimeTimer = null;
116
- }
117
- if (this.startupTimer) {
118
- clearTimeout(this.startupTimer);
119
- this.startupTimer = null;
120
- }
121
- callbacks.onError(err);
122
- });
123
- this.proc.on('exit', (code) => {
124
- this.proc = null;
125
- if (this.killTimer) {
126
- clearTimeout(this.killTimer);
127
- this.killTimer = null;
128
- }
129
- if (this.runtimeTimer) {
130
- clearTimeout(this.runtimeTimer);
131
- this.runtimeTimer = null;
132
- }
133
- if (this.startupTimer) {
134
- clearTimeout(this.startupTimer);
135
- this.startupTimer = null;
136
- }
137
- logger.info(`[${this.tabName}] Claude subprocess exited (code: ${code})`);
138
- callbacks.onExit(code);
139
- });
140
- // Hard runtime cap so a wedged claude can't pin a tab forever.
141
- // Default 30 minutes. Disable by setting maxRuntimeMs to 0.
142
- const maxRuntimeMs = this.config.claudeCode.maxRuntimeMs ?? 30 * 60 * 1000;
143
- if (maxRuntimeMs > 0) {
144
- this.runtimeTimer = setTimeout(() => {
145
- if (!this.proc)
146
- return;
147
- logger.warn(`[${this.tabName}] Subprocess exceeded maxRuntimeMs (${maxRuntimeMs}ms) — killing`);
148
- callbacks.onError(new Error(`Subprocess timed out after ${Math.round(maxRuntimeMs / 1000)}s`));
149
- this.kill();
150
- }, maxRuntimeMs);
151
- }
152
- // Startup watchdog. A healthy claude emits its init event within seconds of
153
- // spawn. Total silence this long means it wedged on a stalled network socket
154
- // (DNS/connection blip with no client-side timeout) and would otherwise sit
155
- // idle until the 30-min maxRuntime kill. Unlike maxRuntime, this routes
156
- // through onExit (kill only, no onError) so the manager retries once. It is
157
- // disarmed on the first event, so it can only fire before claude initializes
158
- // — long-running tools, which emit nothing on stdout until they return, are
159
- // never affected.
160
- const silentTimeoutMs = this.config.claudeCode.silentTimeoutMs ?? 120_000;
161
- if (silentTimeoutMs > 0) {
162
- this.startupTimer = setTimeout(() => {
163
- if (!this.proc)
164
- return;
165
- logger.warn(`[${this.tabName}] No output ${silentTimeoutMs}ms after spawn — killing as silent network stall`);
166
- this.killReason = 'silent';
167
- this.kill();
168
- }, silentTimeoutMs);
169
- }
170
- }
171
- kill() {
172
- if (!this.proc)
173
- return;
174
- logger.info(`[${this.tabName}] Killing subprocess (PID: ${this.proc.pid})`);
175
- this.proc.kill('SIGTERM');
176
- const proc = this.proc;
177
- this.killTimer = setTimeout(() => {
178
- try {
179
- proc.kill('SIGKILL');
180
- }
181
- catch {
182
- /* already dead */
183
- }
184
- }, 5000);
185
- }
186
- get isRunning() {
187
- return this.proc !== null;
188
- }
189
- get pid() {
190
- return this.proc?.pid ?? null;
191
- }
192
- buildArgs(prompt, resume) {
193
- const args = [
194
- '-p',
195
- '--output-format',
196
- 'stream-json',
197
- '--verbose',
198
- ...this.config.claudeCode.defaultFlags,
199
- ];
200
- // Only add MCP config if the file exists. existsSync result is cached at
201
- // module scope — the path is stable for the daemon's lifetime, so doing
202
- // this once-per-process saves a syscall per claude spawn (every message,
203
- // every task firing, every watcher trigger).
204
- if (mcpConfigExists()) {
205
- args.push('--mcp-config', getMcpConfigPath());
206
- }
207
- // Inject Beecork system context so Claude knows about available tools
208
- if (!resume) {
209
- let systemPrompt = BEECORK_SYSTEM_PROMPT;
210
- if (this.tabSystemPrompt) {
211
- systemPrompt += `\n\n[Tab-specific instructions for "${this.tabName}"]\n${this.tabSystemPrompt}`;
212
- }
213
- args.push('--system-prompt', systemPrompt);
214
- }
215
- if (resume) {
216
- args.push('--resume', this.sessionId);
217
- }
218
- else {
219
- args.push('--session-id', this.sessionId);
220
- }
221
- if (this.config.claudeCode.computerUse) {
222
- args.push('--computer-use');
223
- }
224
- if (this.config.claudeCode.maxBudgetUsd) {
225
- args.push('--max-budget-usd', String(this.config.claudeCode.maxBudgetUsd));
226
- }
227
- args.push(prompt);
228
- return args;
229
- }
230
- }
@@ -1,28 +0,0 @@
1
- import type Database from 'better-sqlite3';
2
- import type { Tab, TabStatus } from '../types.js';
3
- /**
4
- * SQL helpers for the `tabs` table. Single place for any code that needs to
5
- * read/write tab rows. TabManager owns subprocess lifecycle; TabStore owns
6
- * the schema knowledge.
7
- *
8
- * All methods accept an optional `db` param so they're testable against an
9
- * in-memory database. The no-arg form uses the singleton.
10
- */
11
- export declare const TabStore: {
12
- listAll(db?: Database.Database): Tab[];
13
- findByName(name: string, db?: Database.Database): Tab | undefined;
14
- getIdByName(name: string, db?: Database.Database): string | undefined;
15
- countAll(db?: Database.Database): number;
16
- countRunning(db?: Database.Database): number;
17
- /** All tabs marked 'running' — used by daemon crash-recovery on startup. */
18
- findRunning(db?: Database.Database): Tab[];
19
- /** Most-recently-active tab — used by MCP to surface "current" context. */
20
- mostRecent(db?: Database.Database): Tab | undefined;
21
- setStatus(name: string, status: TabStatus, db?: Database.Database): void;
22
- setIdleById(id: string, db?: Database.Database): void;
23
- /** Used by MCP close-tab to nudge daemon recovery loop. */
24
- markRunningAsStopped(name: string, db?: Database.Database): void;
25
- setSystemPrompt(name: string, systemPrompt: string, db?: Database.Database): boolean;
26
- /** Delete a tab and all of its messages atomically. Returns true if it existed. */
27
- deleteWithMessages(name: string, db?: Database.Database): boolean;
28
- };
@@ -1,78 +0,0 @@
1
- import { getDb } from '../db/index.js';
2
- function rowToTab(row) {
3
- return {
4
- id: row.id,
5
- name: row.name,
6
- sessionId: row.session_id,
7
- status: row.status,
8
- workingDir: row.working_dir,
9
- createdAt: row.created_at,
10
- lastActivityAt: row.last_activity_at,
11
- pid: row.pid,
12
- systemPrompt: row.system_prompt,
13
- };
14
- }
15
- /**
16
- * SQL helpers for the `tabs` table. Single place for any code that needs to
17
- * read/write tab rows. TabManager owns subprocess lifecycle; TabStore owns
18
- * the schema knowledge.
19
- *
20
- * All methods accept an optional `db` param so they're testable against an
21
- * in-memory database. The no-arg form uses the singleton.
22
- */
23
- export const TabStore = {
24
- listAll(db = getDb()) {
25
- return db.prepare('SELECT * FROM tabs ORDER BY last_activity_at DESC').all().map(rowToTab);
26
- },
27
- findByName(name, db = getDb()) {
28
- const row = db.prepare('SELECT * FROM tabs WHERE name = ?').get(name);
29
- return row ? rowToTab(row) : undefined;
30
- },
31
- getIdByName(name, db = getDb()) {
32
- const row = db.prepare('SELECT id FROM tabs WHERE name = ?').get(name);
33
- return row?.id;
34
- },
35
- countAll(db = getDb()) {
36
- return db.prepare('SELECT COUNT(*) as c FROM tabs').get().c;
37
- },
38
- countRunning(db = getDb()) {
39
- return db.prepare("SELECT COUNT(*) as c FROM tabs WHERE status = 'running'").get().c;
40
- },
41
- /** All tabs marked 'running' — used by daemon crash-recovery on startup. */
42
- findRunning(db = getDb()) {
43
- return db.prepare("SELECT * FROM tabs WHERE status = 'running'").all().map(rowToTab);
44
- },
45
- /** Most-recently-active tab — used by MCP to surface "current" context. */
46
- mostRecent(db = getDb()) {
47
- const row = db.prepare('SELECT * FROM tabs ORDER BY last_activity_at DESC LIMIT 1').get();
48
- return row ? rowToTab(row) : undefined;
49
- },
50
- setStatus(name, status, db = getDb()) {
51
- db.prepare('UPDATE tabs SET status = ?, last_activity_at = ?, pid = NULL WHERE name = ?').run(status, new Date().toISOString(), name);
52
- },
53
- setIdleById(id, db = getDb()) {
54
- db.prepare("UPDATE tabs SET status = 'idle', pid = NULL WHERE id = ?").run(id);
55
- },
56
- /** Used by MCP close-tab to nudge daemon recovery loop. */
57
- markRunningAsStopped(name, db = getDb()) {
58
- db.prepare("UPDATE tabs SET status = 'stopped', pid = NULL WHERE name = ? AND status = 'running'").run(name);
59
- },
60
- setSystemPrompt(name, systemPrompt, db = getDb()) {
61
- const result = db
62
- .prepare('UPDATE tabs SET system_prompt = ? WHERE name = ?')
63
- .run(systemPrompt, name);
64
- return result.changes > 0;
65
- },
66
- /** Delete a tab and all of its messages atomically. Returns true if it existed. */
67
- deleteWithMessages(name, db = getDb()) {
68
- const id = this.getIdByName(name, db);
69
- if (!id)
70
- return false;
71
- const tx = db.transaction(() => {
72
- db.prepare('DELETE FROM messages WHERE tab_id = ?').run(id);
73
- db.prepare('DELETE FROM tabs WHERE id = ?').run(id);
74
- });
75
- tx();
76
- return true;
77
- },
78
- };
@@ -1,4 +0,0 @@
1
- /** Reserved for future approval mode implementation. Not currently wired into the runtime. */
2
- export type ToolRisk = 'safe' | 'dangerous';
3
- /** Classify a tool call as safe or dangerous */
4
- export declare function classifyTool(toolName: string, input: Record<string, unknown>): ToolRisk;
@@ -1,56 +0,0 @@
1
- const SAFE_TOOLS = new Set([
2
- 'Read', 'Glob', 'Grep', 'LSP', 'WebFetch', 'WebSearch',
3
- 'ToolSearch', 'TaskGet', 'TaskList',
4
- ]);
5
- const DANGEROUS_TOOLS = new Set([
6
- 'Write', 'Edit', 'NotebookEdit',
7
- 'TaskCreate', 'TaskUpdate', 'TaskStop',
8
- ]);
9
- const SAFE_BASH_PATTERNS = [
10
- /^(ls|cat|head|tail|wc|file|stat|which|type|echo|printf)\b/,
11
- /^git\s+(status|log|diff|show|branch|tag|remote)\b/,
12
- /^(pwd|whoami|hostname|date|uname|env|printenv)\b/,
13
- /^(find|grep|rg|fd|ag)\b/,
14
- /^(node|python|ruby|go)\s+--?(version|help)/,
15
- /^npm\s+(list|ls|view|info|outdated|audit)\b/,
16
- /^curl\s.*-X\s*GET\b/,
17
- /^curl\s+(?!.*-X\s*(POST|PUT|DELETE|PATCH))(?!.*--data)(?!.*-d\s)/,
18
- ];
19
- const DANGEROUS_BASH_PATTERNS = [
20
- /^rm\b/,
21
- /^(mv|cp)\b.*--?(force|f)\b/,
22
- /^chmod\b/,
23
- /^chown\b/,
24
- /^git\s+(push|reset|rebase|merge|checkout\s+--)\b/,
25
- /^(docker|kubectl|terraform|ansible)\b/,
26
- /^(sudo|su)\b/,
27
- /^npm\s+(publish|install|uninstall|link)\b/,
28
- /^(kill|killall|pkill)\b/,
29
- /^curl\s.*-X\s*(POST|PUT|DELETE|PATCH)\b/,
30
- ];
31
- /** Classify a tool call as safe or dangerous */
32
- export function classifyTool(toolName, input) {
33
- if (SAFE_TOOLS.has(toolName))
34
- return 'safe';
35
- if (DANGEROUS_TOOLS.has(toolName))
36
- return 'dangerous';
37
- // Bash tool: inspect the command
38
- if (toolName === 'Bash') {
39
- const command = String(input.command || '').trim();
40
- for (const pattern of SAFE_BASH_PATTERNS) {
41
- if (pattern.test(command))
42
- return 'safe';
43
- }
44
- for (const pattern of DANGEROUS_BASH_PATTERNS) {
45
- if (pattern.test(command))
46
- return 'dangerous';
47
- }
48
- // Default: unknown bash commands are dangerous
49
- return 'dangerous';
50
- }
51
- // MCP tools from external servers: default to dangerous
52
- if (toolName.startsWith('mcp__'))
53
- return 'dangerous';
54
- // Unknown tools: default to dangerous
55
- return 'dangerous';
56
- }
@@ -1,45 +0,0 @@
1
- import { exec } from 'node:child_process';
2
- import type { TabManager, NotifyCallback } from '../session/manager.js';
3
- export declare const execAsync: typeof exec.__promisify__;
4
- export declare class TaskScheduler {
5
- private tabManager;
6
- private onNotify;
7
- private nextRunAt;
8
- private running;
9
- private failureCounts;
10
- private stopping;
11
- private store;
12
- constructor(tabManager: TabManager, onNotify: NotifyCallback | null);
13
- /** Load all tasks from store and schedule them */
14
- loadAndSchedule(): void;
15
- /** Check for the reload signal file and reload if present */
16
- checkForReload(): void;
17
- /**
18
- * Fire any tasks whose nextRunAt has elapsed. Called every ~5s by the daemon
19
- * poll loop. This is the macOS-sleep-resilient replacement for setTimeout-driven
20
- * cron heartbeats — after a wake, the next tick catches all overdue tasks.
21
- */
22
- tick(): void;
23
- /** Stop the scheduler. In-flight fireJob promises are detached and resolve naturally. */
24
- stopAll(): void;
25
- /** Compute next run time in ms epoch, given a "from" anchor. Returns null if invalid. */
26
- private computeNextRun;
27
- private fireJob;
28
- /**
29
- * Track consecutive failures per task. After MAX_CONSECUTIVE_FAILURES the
30
- * task is auto-disabled in the DB and a single "auto-disabled" notification
31
- * is sent. Counter resets on the next successful fire.
32
- */
33
- private recordFailure;
34
- private handleSystemEvent;
35
- }
36
- /** Convert human interval (30m, 2h, 1d, 1h30m, 2w) to milliseconds */
37
- export declare function intervalToMs(interval: string): number | null;
38
- /** Convert human interval (30m, 2h, 1d, 1h30m, 2w) to cron expression */
39
- export declare function intervalToCron(interval: string): string | null;
40
- /**
41
- * Validate a schedule string for a given scheduleType. Returns an error string
42
- * on invalid input or null when valid. Used by MCP + dashboard before insert
43
- * so misconfigured tasks fail loud instead of silently never firing.
44
- */
45
- export declare function validateSchedule(scheduleType: string, schedule: string): string | null;