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
package/dist/types.d.ts DELETED
@@ -1,225 +0,0 @@
1
- export interface TelegramConfig {
2
- token: string;
3
- allowedUserIds: number[];
4
- adminUserId?: number;
5
- }
6
- export interface ClaudeCodeConfig {
7
- bin: string;
8
- defaultFlags: string[];
9
- maxBudgetUsd?: number;
10
- computerUse?: boolean;
11
- /** Hard timeout per subprocess turn. Default 30 min. Set to 0 to disable. */
12
- maxRuntimeMs?: number;
13
- /**
14
- * Startup watchdog: kill (and retry once) a subprocess that produces ZERO
15
- * events this long after spawn. A healthy claude emits its init event within
16
- * seconds; prolonged total silence means it wedged on a stalled network
17
- * socket (DNS/connection blip with no client-side timeout). Default 2 min.
18
- * Set to 0 to disable. Disarms on the first event, so it never fires
19
- * mid-task — long-running tools are unaffected.
20
- */
21
- silentTimeoutMs?: number;
22
- }
23
- export interface MemoryConfig {
24
- dbPath: string;
25
- }
26
- export interface TabConfig {
27
- workingDir: string;
28
- }
29
- export interface TabTemplate {
30
- workingDir?: string;
31
- systemPrompt?: string;
32
- }
33
- export interface WhatsAppConfig {
34
- enabled: boolean;
35
- mode: 'baileys';
36
- sessionPath: string;
37
- allowedNumbers: string[];
38
- /** Optional admin phone number. Defaults to allowedNumbers[0]. */
39
- adminNumber?: string;
40
- }
41
- export interface VoiceConfig {
42
- sttProvider: 'whisper-api' | 'none';
43
- sttApiKey?: string;
44
- ttsProvider: 'openai' | 'elevenlabs' | 'none';
45
- ttsApiKey?: string;
46
- ttsVoice?: string;
47
- replyMode: 'text' | 'voice' | 'both';
48
- }
49
- export interface DiscordConfig {
50
- token: string;
51
- allowedUserIds?: string[];
52
- /** Optional admin user ID. Defaults to allowedUserIds[0]. */
53
- adminUserId?: string;
54
- }
55
- /**
56
- * Webhook channel auth semantics:
57
- *
58
- * - When both `authToken` and `hmacSecret` are configured, EITHER mode
59
- * satisfies authentication (OR semantics). A valid Bearer token is enough
60
- * even if the HMAC signature is missing. There is no AND mode today.
61
- * - Replay protection is NOT implemented. Callers must keep their payloads
62
- * idempotent — see L10 in the audit. Acceptable while the server binds to
63
- * 127.0.0.1 only; revisit if remote exposure becomes a thing.
64
- * - `allowUnauthLocalhost` is the explicit opt-in to run with no auth at all.
65
- * Useful for `curl localhost` from a trusted shell, but on a multi-user
66
- * host any local process can inject prompts into your tabs.
67
- */
68
- export interface WebhookConfig {
69
- enabled: boolean;
70
- port: number;
71
- authToken?: string;
72
- hmacSecret?: string;
73
- /** Set to true to skip the fail-secure auth check at start. NOT recommended on shared hosts. */
74
- allowUnauthLocalhost?: boolean;
75
- }
76
- export interface GroupConfig {
77
- activationMode: 'mention' | 'reply' | 'keyword' | 'always';
78
- maxResponsesPerMinute: number;
79
- tabPerGroup: boolean;
80
- keywords?: string[];
81
- }
82
- /**
83
- * Discriminated union of notification provider configs. The `type` field
84
- * narrows which fields are required so callers get full type safety instead
85
- * of treating every field as optional. createNotificationProvider switches
86
- * exhaustively on `type`.
87
- */
88
- export type NotificationConfig = {
89
- type: 'pushover';
90
- userKey: string;
91
- appToken: string;
92
- } | {
93
- type: 'ntfy';
94
- topic: string;
95
- server?: string;
96
- } | {
97
- type: 'webhook';
98
- url: string;
99
- headers?: Record<string, string>;
100
- };
101
- export interface MediaGeneratorConfig {
102
- provider: string;
103
- apiKey?: string;
104
- model?: string;
105
- style?: string;
106
- }
107
- /** A media file attached to a message. Shared by channels + util/text + media. */
108
- export interface MediaAttachment {
109
- type: 'image' | 'audio' | 'video' | 'document' | 'voice';
110
- mimeType: string;
111
- filePath: string;
112
- fileName?: string;
113
- caption?: string;
114
- }
115
- export interface BeecorkConfig {
116
- telegram: TelegramConfig;
117
- whatsapp?: WhatsAppConfig;
118
- webhook?: WebhookConfig;
119
- discord?: DiscordConfig;
120
- claudeCode: ClaudeCodeConfig;
121
- tabs: Record<string, TabConfig>;
122
- tabTemplates?: Record<string, TabTemplate>;
123
- memory: MemoryConfig;
124
- /** Directories to scan for projects on startup (defaults to ~/Coding, ~/Projects, etc.) */
125
- projectScanPaths: string[];
126
- voice?: VoiceConfig;
127
- groups?: GroupConfig;
128
- notifications?: NotificationConfig[];
129
- mediaGenerators?: MediaGeneratorConfig[];
130
- communityChannels?: string[];
131
- /** Capability packs enabled via `beecork capabilities enable`. Owned by src/capabilities. */
132
- capabilities?: import('./capabilities/types.js').EnabledCapability[];
133
- deployment: 'local' | 'vps';
134
- }
135
- export type TabStatus = 'idle' | 'running' | 'error' | 'stopped';
136
- export interface Tab {
137
- id: string;
138
- name: string;
139
- sessionId: string;
140
- status: TabStatus;
141
- workingDir: string;
142
- createdAt: string;
143
- lastActivityAt: string;
144
- pid: number | null;
145
- systemPrompt: string | null;
146
- }
147
- export interface StreamInit {
148
- type: 'system';
149
- subtype: 'init';
150
- session_id: string;
151
- tools: string[];
152
- mcp_servers: string[];
153
- model: string;
154
- }
155
- export interface StreamContentText {
156
- type: 'text';
157
- text: string;
158
- }
159
- export interface StreamContentToolUse {
160
- type: 'tool_use';
161
- id: string;
162
- name: string;
163
- input: Record<string, unknown>;
164
- }
165
- export interface StreamContentToolResult {
166
- type: 'tool_result';
167
- tool_use_id: string;
168
- content: string;
169
- }
170
- export type StreamContentBlock = StreamContentText | StreamContentToolUse | StreamContentToolResult;
171
- export interface StreamAssistant {
172
- type: 'assistant';
173
- message: {
174
- id: string;
175
- role: 'assistant';
176
- content: StreamContentBlock[];
177
- stop_reason: string;
178
- usage: StreamUsage;
179
- };
180
- session_id: string;
181
- }
182
- export interface StreamResult {
183
- type: 'result';
184
- subtype: 'success' | 'error' | 'error_during_execution';
185
- is_error: boolean;
186
- duration_ms: number;
187
- result?: string;
188
- errors?: string[];
189
- session_id: string;
190
- total_cost_usd?: number;
191
- usage?: StreamUsage;
192
- }
193
- export interface StreamUsage {
194
- input_tokens: number;
195
- output_tokens: number;
196
- cache_creation_input_tokens: number;
197
- cache_read_input_tokens: number;
198
- }
199
- export type StreamEvent = StreamInit | StreamAssistant | StreamResult;
200
- export type TaskScheduleType = 'at' | 'every' | 'cron';
201
- export type TaskPayloadType = 'agentTurn' | 'systemEvent';
202
- export interface Task {
203
- id: string;
204
- name: string;
205
- scheduleType: TaskScheduleType;
206
- schedule: string;
207
- tabName: string;
208
- message: string;
209
- payloadType: TaskPayloadType;
210
- enabled: boolean;
211
- createdAt: string;
212
- lastRunAt: string | null;
213
- nextRunAt: string | null;
214
- }
215
- export interface Memory {
216
- id: number;
217
- content: string;
218
- tabName: string | null;
219
- createdAt: string;
220
- source: 'tool' | 'auto';
221
- }
222
- export interface CircuitBreakerConfig {
223
- maxRepeats: number;
224
- windowSize: number;
225
- }
package/dist/types.js DELETED
@@ -1,3 +0,0 @@
1
- // ─── Config ───
2
- export {};
3
- // Channel interface: see src/channels/types.ts
@@ -1,2 +0,0 @@
1
- export { resolveUser, registerUser, linkIdentity, listUsers, hasAdmin } from './service.js';
2
- export type { User } from './service.js';
@@ -1 +0,0 @@
1
- export { resolveUser, registerUser, linkIdentity, listUsers, hasAdmin } from './service.js';
@@ -1,17 +0,0 @@
1
- export interface User {
2
- id: string;
3
- name: string;
4
- role: 'admin' | 'user';
5
- budgetUsd: number | null;
6
- createdAt: string;
7
- }
8
- /** Get or create a user from a channel identity */
9
- export declare function resolveUser(channelId: string, peerId: string): User | null;
10
- /** Register a new user */
11
- export declare function registerUser(name: string, channelId: string, peerId: string, role?: 'admin' | 'user'): User;
12
- /** Link an additional channel identity to an existing user */
13
- export declare function linkIdentity(userId: string, channelId: string, peerId: string): boolean;
14
- /** Get all users */
15
- export declare function listUsers(): User[];
16
- /** Check if any admin exists */
17
- export declare function hasAdmin(): boolean;
@@ -1,46 +0,0 @@
1
- import { v4 as uuidv4 } from 'uuid';
2
- import { getDb } from '../db/index.js';
3
- import { logger } from '../util/logger.js';
4
- function rowToUser(row) {
5
- return { id: row.id, name: row.name, role: row.role, budgetUsd: row.budget_usd, createdAt: row.created_at };
6
- }
7
- /** Get or create a user from a channel identity */
8
- export function resolveUser(channelId, peerId) {
9
- const db = getDb();
10
- const identity = db.prepare('SELECT user_id FROM identities WHERE channel_id = ? AND peer_id = ?').get(channelId, peerId);
11
- if (!identity)
12
- return null;
13
- const row = db.prepare('SELECT * FROM users WHERE id = ?').get(identity.user_id);
14
- return row ? rowToUser(row) : null;
15
- }
16
- /** Register a new user */
17
- export function registerUser(name, channelId, peerId, role = 'user') {
18
- const db = getDb();
19
- const id = uuidv4();
20
- db.prepare('INSERT INTO users (id, name, role) VALUES (?, ?, ?)').run(id, name, role);
21
- db.prepare('INSERT INTO identities (user_id, channel_id, peer_id) VALUES (?, ?, ?)').run(id, channelId, peerId);
22
- logger.info(`User registered: ${name} (${role}) via ${channelId}:${peerId}`);
23
- return { id, name, role, budgetUsd: null, createdAt: new Date().toISOString() };
24
- }
25
- /** Link an additional channel identity to an existing user */
26
- export function linkIdentity(userId, channelId, peerId) {
27
- const db = getDb();
28
- try {
29
- db.prepare('INSERT INTO identities (user_id, channel_id, peer_id) VALUES (?, ?, ?)').run(userId, channelId, peerId);
30
- return true;
31
- }
32
- catch {
33
- return false; // Already linked or conflict
34
- }
35
- }
36
- /** Get all users */
37
- export function listUsers() {
38
- const db = getDb();
39
- return db.prepare('SELECT * FROM users ORDER BY created_at').all().map(rowToUser);
40
- }
41
- /** Check if any admin exists */
42
- export function hasAdmin() {
43
- const db = getDb();
44
- const row = db.prepare("SELECT COUNT(*) as c FROM users WHERE role = 'admin'").get();
45
- return row.c > 0;
46
- }
@@ -1,43 +0,0 @@
1
- /**
2
- * Auto-heal install-path divergence between the CLI (this process) and the
3
- * running daemon. Triggered both from the npm postinstall hook and from the
4
- * CLI entry on every invocation — both paths converge here so the policy is
5
- * single-sourced and idempotent.
6
- *
7
- * What "divergence" means:
8
- * The daemon's launchd plist (or systemd unit) hard-codes an absolute path
9
- * to dist/daemon.js. If `npm install -g beecork@<new>` lands in a different
10
- * npm prefix than the one the unit file points at, the daemon keeps running
11
- * the old code while the CLI shows the new version. Bug reports get
12
- * misdiagnosed because the user thinks both are on the new version.
13
- *
14
- * What this function does:
15
- * 1. Rewrite the unit file's daemon path if it doesn't point at us.
16
- * 2. SIGTERM the running daemon (KeepAlive / Restart=always brings it back
17
- * on the new code) only when its runtime.json shows it was launched from
18
- * a different install root than ours.
19
- *
20
- * Returns a Result describing what happened, for the caller to surface (or not)
21
- * to the user. The auto-heal NEVER throws — failures degrade to {action:'skip'}.
22
- */
23
- export interface HealResult {
24
- action: 'noop' | 'rewrote-unit' | 'signaled-daemon' | 'rewrote-and-signaled' | 'skip';
25
- reason?: string;
26
- unitPath?: string;
27
- oldDaemonScript?: string;
28
- newDaemonScript?: string;
29
- }
30
- export declare function autoHealInstall(fromFileUrl: string): HealResult;
31
- /**
32
- * Extract the daemon-script absolute path from a launchd plist or systemd unit.
33
- * Returns null if the file shape isn't recognized — caller treats that as "skip".
34
- *
35
- * launchd: looks inside <key>ProgramArguments</key><array> for the .js entry.
36
- * systemd: looks for ExecStart=<node> <daemon.js> on a single line.
37
- */
38
- export declare function extractDaemonScript(content: string): string | null;
39
- /** Rewrite-only variant used by tests and the postinstall hook in dry-run mode. */
40
- export declare function rewriteUnitDaemonScript(unitPath: string, newDaemonScript: string): {
41
- rewrote: boolean;
42
- oldDaemonScript: string | null;
43
- };
@@ -1,107 +0,0 @@
1
- import fs from 'node:fs';
2
- import { findInstallRoot, getDaemonScript, readRuntimeInfo, isPidAlive, getServiceUnitPath, } from './install-info.js';
3
- export function autoHealInstall(fromFileUrl) {
4
- try {
5
- const currentRoot = findInstallRoot(fromFileUrl);
6
- const currentDaemonScript = getDaemonScript(currentRoot);
7
- const unitPath = getServiceUnitPath();
8
- if (!unitPath || !fs.existsSync(unitPath)) {
9
- // No installed service — beecork has been npm-installed but `beecork setup` (or
10
- // equivalent) hasn't been run yet. Nothing to heal.
11
- return { action: 'skip', reason: 'no service unit file present' };
12
- }
13
- const unitContent = fs.readFileSync(unitPath, 'utf-8');
14
- const oldDaemonScript = extractDaemonScript(unitContent);
15
- let rewroteUnit = false;
16
- if (oldDaemonScript && oldDaemonScript !== currentDaemonScript) {
17
- // Validate the new path actually exists before rewriting — never break the daemon
18
- // by pointing it at a missing file.
19
- if (!fs.existsSync(currentDaemonScript)) {
20
- return { action: 'skip', reason: `current install missing daemon: ${currentDaemonScript}` };
21
- }
22
- const next = unitContent.split(oldDaemonScript).join(currentDaemonScript);
23
- const tmp = unitPath + '.tmp';
24
- fs.writeFileSync(tmp, next);
25
- fs.renameSync(tmp, unitPath);
26
- rewroteUnit = true;
27
- }
28
- // Restart the daemon if it's currently running from a stale install. This is
29
- // separate from the unit-file rewrite so we also catch the case where the unit
30
- // file is already current but the running process predates the latest install.
31
- const runtime = readRuntimeInfo();
32
- let signaledDaemon = false;
33
- if (runtime && runtime.installRoot !== currentRoot && isPidAlive(runtime.pid)) {
34
- try {
35
- process.kill(runtime.pid, 'SIGTERM');
36
- signaledDaemon = true;
37
- }
38
- catch {
39
- // Permission denied (different user, or already gone). Surface as skip;
40
- // we still rewrote the unit file so the next start picks up the new path.
41
- }
42
- }
43
- if (rewroteUnit && signaledDaemon) {
44
- return {
45
- action: 'rewrote-and-signaled',
46
- unitPath,
47
- oldDaemonScript: oldDaemonScript,
48
- newDaemonScript: currentDaemonScript,
49
- };
50
- }
51
- if (rewroteUnit)
52
- return {
53
- action: 'rewrote-unit',
54
- unitPath,
55
- oldDaemonScript: oldDaemonScript,
56
- newDaemonScript: currentDaemonScript,
57
- };
58
- if (signaledDaemon)
59
- return { action: 'signaled-daemon', unitPath };
60
- return { action: 'noop' };
61
- }
62
- catch (err) {
63
- return { action: 'skip', reason: err instanceof Error ? err.message : String(err) };
64
- }
65
- }
66
- /**
67
- * Extract the daemon-script absolute path from a launchd plist or systemd unit.
68
- * Returns null if the file shape isn't recognized — caller treats that as "skip".
69
- *
70
- * launchd: looks inside <key>ProgramArguments</key><array> for the .js entry.
71
- * systemd: looks for ExecStart=<node> <daemon.js> on a single line.
72
- */
73
- export function extractDaemonScript(content) {
74
- // launchd plist: pull the second <string> inside ProgramArguments
75
- const launchdMatch = content.match(/<key>\s*ProgramArguments\s*<\/key>\s*<array>([\s\S]*?)<\/array>/);
76
- if (launchdMatch) {
77
- const args = Array.from(launchdMatch[1].matchAll(/<string>([^<]+)<\/string>/g)).map((m) => m[1]);
78
- const jsArg = args.find((a) => a.endsWith('daemon.js'));
79
- if (jsArg)
80
- return jsArg;
81
- }
82
- // systemd unit: ExecStart=<node> <daemon.js> [args...]
83
- const systemdMatch = content.match(/^ExecStart\s*=\s*(.+)$/m);
84
- if (systemdMatch) {
85
- const parts = systemdMatch[1].split(/\s+/);
86
- const jsArg = parts.find((p) => p.endsWith('daemon.js'));
87
- if (jsArg)
88
- return jsArg;
89
- }
90
- return null;
91
- }
92
- /** Rewrite-only variant used by tests and the postinstall hook in dry-run mode. */
93
- export function rewriteUnitDaemonScript(unitPath, newDaemonScript) {
94
- if (!fs.existsSync(unitPath))
95
- return { rewrote: false, oldDaemonScript: null };
96
- const content = fs.readFileSync(unitPath, 'utf-8');
97
- const oldDaemonScript = extractDaemonScript(content);
98
- if (!oldDaemonScript)
99
- return { rewrote: false, oldDaemonScript: null };
100
- if (oldDaemonScript === newDaemonScript)
101
- return { rewrote: false, oldDaemonScript };
102
- const next = content.split(oldDaemonScript).join(newDaemonScript);
103
- const tmp = unitPath + '.tmp';
104
- fs.writeFileSync(tmp, next);
105
- fs.renameSync(tmp, unitPath);
106
- return { rewrote: true, oldDaemonScript };
107
- }
@@ -1,37 +0,0 @@
1
- /**
2
- * Metadata the daemon writes to ~/.beecork/runtime.json at startup so the CLI
3
- * (and postinstall hook) can detect when daemon and CLI are running from
4
- * different physical installs of beecork — the most common silent-staleness
5
- * mode after `npm install -g beecork@<new>` lands in a prefix the daemon's
6
- * launchd plist doesn't point at.
7
- */
8
- export interface RuntimeInfo {
9
- pid: number;
10
- version: string;
11
- /** The package root: <prefix>/lib/node_modules/beecork. Single canonical key. */
12
- installRoot: string;
13
- /** Absolute path to dist/daemon.js — derived from installRoot. */
14
- daemonScript: string;
15
- /** ISO timestamp. */
16
- startedAt: string;
17
- /** process.version (e.g. "v20.11.0") */
18
- nodeVersion: string;
19
- }
20
- /**
21
- * Walk up from a given file (typically import.meta.url) to find the directory
22
- * containing package.json — i.e. the beecork install root. Works for both:
23
- * - source dev runs (.../src/util/install-info.ts → .../ )
24
- * - built/installed runs (.../dist/util/install-info.js → .../ )
25
- */
26
- export declare function findInstallRoot(fromFileUrl: string): string;
27
- export declare function getDaemonScript(installRoot: string): string;
28
- export declare function writeRuntimeInfo(info: RuntimeInfo): void;
29
- export declare function readRuntimeInfo(): RuntimeInfo | null;
30
- export declare function removeRuntimeInfo(): void;
31
- export declare function isPidAlive(pid: number): boolean;
32
- /**
33
- * Cross-platform path to the service-manager unit file that launches the daemon.
34
- * Returns null if beecork doesn't manage one on this OS (currently Windows uses
35
- * Task Scheduler and is out of scope for the auto-heal flow).
36
- */
37
- export declare function getServiceUnitPath(): string | null;
@@ -1,80 +0,0 @@
1
- import fs from 'node:fs';
2
- import path from 'node:path';
3
- import os from 'node:os';
4
- import { fileURLToPath } from 'node:url';
5
- import { getRuntimeInfoPath } from './paths.js';
6
- /**
7
- * Walk up from a given file (typically import.meta.url) to find the directory
8
- * containing package.json — i.e. the beecork install root. Works for both:
9
- * - source dev runs (.../src/util/install-info.ts → .../ )
10
- * - built/installed runs (.../dist/util/install-info.js → .../ )
11
- */
12
- export function findInstallRoot(fromFileUrl) {
13
- const fromPath = fileURLToPath(fromFileUrl);
14
- let dir = path.dirname(fromPath);
15
- for (let i = 0; i < 6; i++) {
16
- if (fs.existsSync(path.join(dir, 'package.json')))
17
- return dir;
18
- const parent = path.dirname(dir);
19
- if (parent === dir)
20
- break;
21
- dir = parent;
22
- }
23
- throw new Error(`Could not locate beecork install root walking up from ${fromPath}`);
24
- }
25
- export function getDaemonScript(installRoot) {
26
- return path.join(installRoot, 'dist', 'daemon.js');
27
- }
28
- export function writeRuntimeInfo(info) {
29
- const filePath = getRuntimeInfoPath();
30
- // Atomic-ish write: temp + rename so a partial write never confuses a reader.
31
- const tmp = filePath + '.tmp';
32
- fs.writeFileSync(tmp, JSON.stringify(info, null, 2));
33
- fs.renameSync(tmp, filePath);
34
- }
35
- export function readRuntimeInfo() {
36
- const filePath = getRuntimeInfoPath();
37
- if (!fs.existsSync(filePath))
38
- return null;
39
- try {
40
- const data = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
41
- if (typeof data?.pid === 'number' && typeof data?.installRoot === 'string') {
42
- return data;
43
- }
44
- return null;
45
- }
46
- catch {
47
- return null;
48
- }
49
- }
50
- export function removeRuntimeInfo() {
51
- const filePath = getRuntimeInfoPath();
52
- try {
53
- fs.unlinkSync(filePath);
54
- }
55
- catch {
56
- /* not present, fine */
57
- }
58
- }
59
- export function isPidAlive(pid) {
60
- try {
61
- process.kill(pid, 0);
62
- return true;
63
- }
64
- catch {
65
- return false;
66
- }
67
- }
68
- /**
69
- * Cross-platform path to the service-manager unit file that launches the daemon.
70
- * Returns null if beecork doesn't manage one on this OS (currently Windows uses
71
- * Task Scheduler and is out of scope for the auto-heal flow).
72
- */
73
- export function getServiceUnitPath() {
74
- const home = os.homedir();
75
- if (process.platform === 'darwin')
76
- return path.join(home, 'Library', 'LaunchAgents', 'com.beecork.daemon.plist');
77
- if (process.platform === 'linux')
78
- return path.join(home, '.config', 'systemd', 'user', 'beecork.service');
79
- return null;
80
- }
@@ -1,18 +0,0 @@
1
- type LogLevel = 'debug' | 'info' | 'warn' | 'error';
2
- declare class Logger {
3
- private minLevel;
4
- private logFile;
5
- private stream;
6
- private bytesWritten;
7
- setLevel(level: LogLevel): void;
8
- setLogFile(name: string): void;
9
- private write;
10
- debug(msg: string, ...args: unknown[]): void;
11
- info(msg: string, ...args: unknown[]): void;
12
- warn(msg: string, ...args: unknown[]): void;
13
- error(msg: string, ...args: unknown[]): void;
14
- private checkRotation;
15
- close(): void;
16
- }
17
- export declare const logger: Logger;
18
- export {};