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,33 +0,0 @@
1
- import { saveMedia } from '../store.js';
2
- export class ElevenLabsSfxGenerator {
3
- apiKey;
4
- id = 'elevenlabs-sfx';
5
- name = 'ElevenLabs Sound Effects';
6
- supportedTypes = ['audio'];
7
- constructor(apiKey) {
8
- this.apiKey = apiKey;
9
- }
10
- async generate(type, prompt, options) {
11
- if (type !== 'audio')
12
- throw new Error('ElevenLabs SFX only supports audio generation');
13
- const response = await fetch('https://api.elevenlabs.io/v1/sound-generation', {
14
- method: 'POST',
15
- headers: {
16
- 'xi-api-key': this.apiKey,
17
- 'Content-Type': 'application/json',
18
- },
19
- body: JSON.stringify({
20
- text: prompt.slice(0, 500),
21
- duration_seconds: options?.duration,
22
- }),
23
- signal: AbortSignal.timeout(60000),
24
- });
25
- if (!response.ok) {
26
- const err = await response.text();
27
- throw new Error(`ElevenLabs SFX error ${response.status}: ${err.slice(0, 200)}`);
28
- }
29
- const buffer = Buffer.from(await response.arrayBuffer());
30
- const filePath = saveMedia(buffer, 'mp3', 'generated-sfx.mp3');
31
- return { filePath, mimeType: 'audio/mpeg' };
32
- }
33
- }
@@ -1,9 +0,0 @@
1
- import type { MediaGenerator, MediaType, GenerateOptions, GenerateResult } from '../types.js';
2
- export declare class KlingGenerator implements MediaGenerator {
3
- private apiKey;
4
- readonly id = "kling";
5
- readonly name = "Kling AI";
6
- readonly supportedTypes: MediaType[];
7
- constructor(apiKey: string);
8
- generate(type: MediaType, prompt: string, options?: GenerateOptions): Promise<GenerateResult>;
9
- }
@@ -1,47 +0,0 @@
1
- import { saveMedia } from '../store.js';
2
- import { pollForCompletion } from './poll-util.js';
3
- export class KlingGenerator {
4
- apiKey;
5
- id = 'kling';
6
- name = 'Kling AI';
7
- supportedTypes = ['video'];
8
- constructor(apiKey) {
9
- this.apiKey = apiKey;
10
- }
11
- async generate(type, prompt, options) {
12
- if (type !== 'video')
13
- throw new Error('Kling only supports video generation');
14
- const response = await fetch('https://api.klingai.com/v1/videos/text2video', {
15
- method: 'POST',
16
- headers: {
17
- Authorization: `Bearer ${this.apiKey}`,
18
- 'Content-Type': 'application/json',
19
- },
20
- body: JSON.stringify({
21
- prompt: prompt.slice(0, 2500),
22
- duration: options?.duration || 5,
23
- model_name: 'kling-v1',
24
- }),
25
- signal: AbortSignal.timeout(30000),
26
- });
27
- if (!response.ok) {
28
- const err = await response.text();
29
- throw new Error(`Kling error ${response.status}: ${err.slice(0, 200)}`);
30
- }
31
- const { data } = (await response.json());
32
- // Poll for completion
33
- const headers = { Authorization: `Bearer ${this.apiKey}` };
34
- const videoUrl = await pollForCompletion({
35
- statusUrl: `https://api.klingai.com/v1/videos/text2video/${data.task_id}`,
36
- headers,
37
- isComplete: (d) => d.data.task_status === 'succeed' && !!d.data.task_result?.videos[0],
38
- isFailed: (d) => (d.data.task_status === 'failed' ? 'generation failed' : null),
39
- getResultUrl: (d) => d.data.task_result.videos[0].url,
40
- label: 'Kling',
41
- });
42
- const videoResp = await fetch(videoUrl, { signal: AbortSignal.timeout(60000) });
43
- const buffer = Buffer.from(await videoResp.arrayBuffer());
44
- const filePath = saveMedia(buffer, 'mp4', 'generated-video.mp4');
45
- return { filePath, mimeType: 'video/mp4' };
46
- }
47
- }
@@ -1,10 +0,0 @@
1
- import type { MediaGenerator, MediaType, GenerateOptions, GenerateResult } from '../types.js';
2
- export declare class LyriaGenerator implements MediaGenerator {
3
- private apiKey;
4
- private model;
5
- readonly id = "lyria";
6
- readonly name = "Google Lyria";
7
- readonly supportedTypes: MediaType[];
8
- constructor(apiKey: string, model?: string);
9
- generate(type: MediaType, prompt: string, options?: GenerateOptions): Promise<GenerateResult>;
10
- }
@@ -1,41 +0,0 @@
1
- import { saveMedia } from '../store.js';
2
- export class LyriaGenerator {
3
- apiKey;
4
- model;
5
- id = 'lyria';
6
- name = 'Google Lyria';
7
- supportedTypes = ['music'];
8
- constructor(apiKey, model = 'lyria-3-clip') {
9
- this.apiKey = apiKey;
10
- this.model = model;
11
- }
12
- async generate(type, prompt, options) {
13
- if (type !== 'music')
14
- throw new Error('Lyria only supports music generation');
15
- const useProModel = (options?.duration && options.duration > 30) || this.model.includes('pro');
16
- const modelId = useProModel ? 'lyria-3-pro' : 'lyria-3-clip';
17
- const response = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/${modelId}:generateContent?key=${this.apiKey}`, {
18
- method: 'POST',
19
- headers: { 'Content-Type': 'application/json' },
20
- body: JSON.stringify({
21
- contents: [{ parts: [{ text: prompt.slice(0, 2000) }] }],
22
- generationConfig: {
23
- responseModalities: ['AUDIO'],
24
- },
25
- }),
26
- signal: AbortSignal.timeout(300000), // 5 min for full songs
27
- });
28
- if (!response.ok) {
29
- const err = await response.text();
30
- throw new Error(`Lyria error ${response.status}: ${err.slice(0, 200)}`);
31
- }
32
- const data = (await response.json());
33
- const audioPart = data.candidates?.[0]?.content?.parts?.find((p) => p.inlineData);
34
- if (!audioPart?.inlineData?.data) {
35
- throw new Error('Lyria returned no audio data');
36
- }
37
- const buffer = Buffer.from(audioPart.inlineData.data, 'base64');
38
- const filePath = saveMedia(buffer, 'mp3', 'generated-music.mp3');
39
- return { filePath, mimeType: 'audio/mpeg' };
40
- }
41
- }
@@ -1,10 +0,0 @@
1
- import type { MediaGenerator, MediaType, GenerateOptions, GenerateResult } from '../types.js';
2
- export declare class NanoBananaGenerator implements MediaGenerator {
3
- private apiKey;
4
- private model;
5
- readonly id = "nano-banana";
6
- readonly name = "Google Nano Banana";
7
- readonly supportedTypes: MediaType[];
8
- constructor(apiKey: string, model?: string);
9
- generate(type: MediaType, prompt: string, _options?: GenerateOptions): Promise<GenerateResult>;
10
- }
@@ -1,45 +0,0 @@
1
- import { saveMedia } from '../store.js';
2
- export class NanoBananaGenerator {
3
- apiKey;
4
- model;
5
- id = 'nano-banana';
6
- name = 'Google Nano Banana';
7
- supportedTypes = ['image'];
8
- constructor(apiKey, model = 'gemini-2.5-flash-image') {
9
- this.apiKey = apiKey;
10
- this.model = model;
11
- }
12
- async generate(type, prompt, _options) {
13
- if (type !== 'image')
14
- throw new Error('Nano Banana only supports image generation');
15
- // Gemini image generation API
16
- const response = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/${this.model}:generateContent?key=${this.apiKey}`, {
17
- method: 'POST',
18
- headers: { 'Content-Type': 'application/json' },
19
- body: JSON.stringify({
20
- contents: [{ parts: [{ text: prompt.slice(0, 2000) }] }],
21
- generationConfig: {
22
- responseModalities: ['IMAGE'],
23
- imageGenerationConfig: {
24
- numberOfImages: 1,
25
- },
26
- },
27
- }),
28
- signal: AbortSignal.timeout(120000),
29
- });
30
- if (!response.ok) {
31
- const err = await response.text();
32
- throw new Error(`Nano Banana error ${response.status}: ${err.slice(0, 200)}`);
33
- }
34
- const data = (await response.json());
35
- const imagePart = data.candidates?.[0]?.content?.parts?.find((p) => p.inlineData);
36
- if (!imagePart?.inlineData?.data) {
37
- throw new Error('Nano Banana returned no image data');
38
- }
39
- const buffer = Buffer.from(imagePart.inlineData.data, 'base64');
40
- const mimeType = imagePart.inlineData.mimeType || 'image/png';
41
- const ext = mimeType.includes('jpeg') ? 'jpg' : 'png';
42
- const filePath = saveMedia(buffer, ext, `generated-image.${ext}`);
43
- return { filePath, mimeType };
44
- }
45
- }
@@ -1,12 +0,0 @@
1
- interface PollOptions<T = unknown> {
2
- statusUrl: string;
3
- headers: Record<string, string>;
4
- isComplete: (data: T) => boolean;
5
- isFailed: (data: T) => string | null;
6
- getResultUrl: (data: T) => string;
7
- interval?: number;
8
- maxAttempts?: number;
9
- label?: string;
10
- }
11
- export declare function pollForCompletion<T = unknown>(opts: PollOptions<T>): Promise<string>;
12
- export {};
@@ -1,22 +0,0 @@
1
- import { logger } from '../../util/logger.js';
2
- export async function pollForCompletion(opts) {
3
- const { statusUrl, headers, isComplete, isFailed, getResultUrl, interval = 5000, maxAttempts = 60, label = 'API', } = opts;
4
- for (let i = 0; i < maxAttempts; i++) {
5
- await new Promise((r) => setTimeout(r, interval));
6
- const resp = await fetch(statusUrl, { headers, signal: AbortSignal.timeout(10000) });
7
- if (!resp.ok) {
8
- logger.warn(`[${label}] Poll failed: ${resp.status}`);
9
- if (resp.status >= 400 && resp.status < 500) {
10
- throw new Error(`${label} API error: ${resp.status}`);
11
- }
12
- continue;
13
- }
14
- const data = (await resp.json());
15
- const failMsg = isFailed(data);
16
- if (failMsg)
17
- throw new Error(`${label} generation failed: ${failMsg}`);
18
- if (isComplete(data))
19
- return getResultUrl(data);
20
- }
21
- throw new Error(`${label} generation timed out after ${(maxAttempts * interval) / 1000}s`);
22
- }
@@ -1,9 +0,0 @@
1
- import type { MediaGenerator, MediaType, GenerateOptions, GenerateResult } from '../types.js';
2
- export declare class RecraftGenerator implements MediaGenerator {
3
- private apiKey;
4
- readonly id = "recraft";
5
- readonly name = "Recraft (Images + Vectors)";
6
- readonly supportedTypes: MediaType[];
7
- constructor(apiKey: string);
8
- generate(type: MediaType, prompt: string, options?: GenerateOptions): Promise<GenerateResult>;
9
- }
@@ -1,52 +0,0 @@
1
- import { saveMedia } from '../store.js';
2
- export class RecraftGenerator {
3
- apiKey;
4
- id = 'recraft';
5
- name = 'Recraft (Images + Vectors)';
6
- supportedTypes = ['image']; // SVG vectors are still "images"
7
- constructor(apiKey) {
8
- this.apiKey = apiKey;
9
- }
10
- async generate(type, prompt, options) {
11
- if (type !== 'image')
12
- throw new Error('Recraft only supports image/vector generation');
13
- const isVector = options?.format === 'svg' || options?.style === 'vector';
14
- const endpoint = isVector
15
- ? 'https://external.api.recraft.ai/v1/images/generations'
16
- : 'https://external.api.recraft.ai/v1/images/generations';
17
- const response = await fetch(endpoint, {
18
- method: 'POST',
19
- headers: {
20
- Authorization: `Bearer ${this.apiKey}`,
21
- 'Content-Type': 'application/json',
22
- },
23
- body: JSON.stringify({
24
- prompt: prompt.slice(0, 2000),
25
- model: isVector ? 'recraftv4' : 'recraftv4',
26
- response_format: isVector ? 'url' : 'b64_json',
27
- style: isVector ? 'vector_illustration' : options?.style || 'realistic_image',
28
- size: options?.width && options?.height ? `${options.width}x${options.height}` : '1024x1024',
29
- }),
30
- signal: AbortSignal.timeout(120000),
31
- });
32
- if (!response.ok) {
33
- const err = await response.text();
34
- throw new Error(`Recraft error ${response.status}: ${err.slice(0, 200)}`);
35
- }
36
- const data = (await response.json());
37
- const image = data.data?.[0];
38
- if (isVector && image?.url) {
39
- // Download SVG from URL
40
- const svgResp = await fetch(image.url, { signal: AbortSignal.timeout(30000) });
41
- const svgBuffer = Buffer.from(await svgResp.arrayBuffer());
42
- const filePath = saveMedia(svgBuffer, 'svg', 'generated-vector.svg');
43
- return { filePath, mimeType: 'image/svg+xml' };
44
- }
45
- else if (image?.b64_json) {
46
- const buffer = Buffer.from(image.b64_json, 'base64');
47
- const filePath = saveMedia(buffer, 'png', 'generated-image.png');
48
- return { filePath, mimeType: 'image/png' };
49
- }
50
- throw new Error('Recraft returned no image data');
51
- }
52
- }
@@ -1,9 +0,0 @@
1
- import type { MediaGenerator, MediaType, GenerateOptions, GenerateResult } from '../types.js';
2
- export declare class RunwayGenerator implements MediaGenerator {
3
- private apiKey;
4
- readonly id = "runway";
5
- readonly name = "Runway Gen-3";
6
- readonly supportedTypes: MediaType[];
7
- constructor(apiKey: string);
8
- generate(type: MediaType, prompt: string, options?: GenerateOptions): Promise<GenerateResult>;
9
- }
@@ -1,49 +0,0 @@
1
- import { saveMedia } from '../store.js';
2
- import { pollForCompletion } from './poll-util.js';
3
- export class RunwayGenerator {
4
- apiKey;
5
- id = 'runway';
6
- name = 'Runway Gen-3';
7
- supportedTypes = ['video'];
8
- constructor(apiKey) {
9
- this.apiKey = apiKey;
10
- }
11
- async generate(type, prompt, options) {
12
- if (type !== 'video')
13
- throw new Error('Runway only supports video generation');
14
- // Start generation
15
- const startResponse = await fetch('https://api.runwayml.com/v1/image_to_video', {
16
- method: 'POST',
17
- headers: {
18
- Authorization: `Bearer ${this.apiKey}`,
19
- 'Content-Type': 'application/json',
20
- 'X-Runway-Version': '2024-11-06',
21
- },
22
- body: JSON.stringify({
23
- model: 'gen3a_turbo',
24
- promptText: prompt.slice(0, 2000),
25
- duration: options?.duration || 5,
26
- }),
27
- signal: AbortSignal.timeout(30000),
28
- });
29
- if (!startResponse.ok) {
30
- const err = await startResponse.text();
31
- throw new Error(`Runway error ${startResponse.status}: ${err.slice(0, 200)}`);
32
- }
33
- const { id: taskId } = (await startResponse.json());
34
- // Poll for completion (max 5 minutes)
35
- const headers = { Authorization: `Bearer ${this.apiKey}`, 'X-Runway-Version': '2024-11-06' };
36
- const videoUrl = await pollForCompletion({
37
- statusUrl: `https://api.runwayml.com/v1/tasks/${taskId}`,
38
- headers,
39
- isComplete: (data) => data.status === 'SUCCEEDED' && !!data.output?.[0],
40
- isFailed: (data) => (data.status === 'FAILED' ? 'generation failed' : null),
41
- getResultUrl: (data) => data.output[0],
42
- label: 'Runway',
43
- });
44
- const videoResponse = await fetch(videoUrl, { signal: AbortSignal.timeout(60000) });
45
- const buffer = Buffer.from(await videoResponse.arrayBuffer());
46
- const filePath = saveMedia(buffer, 'mp4', 'generated-video.mp4');
47
- return { filePath, mimeType: 'video/mp4', durationMs: (options?.duration || 5) * 1000 };
48
- }
49
- }
@@ -1,9 +0,0 @@
1
- import type { MediaGenerator, MediaType, GenerateOptions, GenerateResult } from '../types.js';
2
- export declare class StableDiffusionGenerator implements MediaGenerator {
3
- private apiKey;
4
- readonly id = "stable-diffusion";
5
- readonly name = "Stable Diffusion (Stability AI)";
6
- readonly supportedTypes: MediaType[];
7
- constructor(apiKey: string);
8
- generate(type: MediaType, prompt: string, options?: GenerateOptions): Promise<GenerateResult>;
9
- }
@@ -1,35 +0,0 @@
1
- import { saveMedia } from '../store.js';
2
- export class StableDiffusionGenerator {
3
- apiKey;
4
- id = 'stable-diffusion';
5
- name = 'Stable Diffusion (Stability AI)';
6
- supportedTypes = ['image'];
7
- constructor(apiKey) {
8
- this.apiKey = apiKey;
9
- }
10
- async generate(type, prompt, options) {
11
- if (type !== 'image')
12
- throw new Error('Stable Diffusion only supports image generation');
13
- const formData = new FormData();
14
- formData.append('prompt', prompt.slice(0, 10000));
15
- if (options?.style)
16
- formData.append('style_preset', options.style);
17
- formData.append('output_format', 'png');
18
- const response = await fetch('https://api.stability.ai/v2beta/stable-image/generate/core', {
19
- method: 'POST',
20
- headers: {
21
- Authorization: `Bearer ${this.apiKey}`,
22
- Accept: 'image/*',
23
- },
24
- body: formData,
25
- signal: AbortSignal.timeout(120000),
26
- });
27
- if (!response.ok) {
28
- const err = await response.text();
29
- throw new Error(`Stability AI error ${response.status}: ${err.slice(0, 200)}`);
30
- }
31
- const buffer = Buffer.from(await response.arrayBuffer());
32
- const filePath = saveMedia(buffer, 'png', 'generated-image.png');
33
- return { filePath, mimeType: 'image/png' };
34
- }
35
- }
@@ -1,9 +0,0 @@
1
- import type { MediaGenerator, MediaType, GenerateOptions, GenerateResult } from '../types.js';
2
- export declare class VeoGenerator implements MediaGenerator {
3
- private apiKey;
4
- readonly id = "veo";
5
- readonly name = "Google Veo";
6
- readonly supportedTypes: MediaType[];
7
- constructor(apiKey: string);
8
- generate(type: MediaType, prompt: string, options?: GenerateOptions): Promise<GenerateResult>;
9
- }
@@ -1,32 +0,0 @@
1
- import { saveMedia } from '../store.js';
2
- export class VeoGenerator {
3
- apiKey;
4
- id = 'veo';
5
- name = 'Google Veo';
6
- supportedTypes = ['video'];
7
- constructor(apiKey) {
8
- this.apiKey = apiKey;
9
- }
10
- async generate(type, prompt, options) {
11
- if (type !== 'video')
12
- throw new Error('Veo only supports video generation');
13
- // Use Gemini API for Veo access
14
- const response = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/veo-2.0-generate-001:predict?key=${this.apiKey}`, {
15
- method: 'POST',
16
- headers: { 'Content-Type': 'application/json' },
17
- body: JSON.stringify({
18
- instances: [{ prompt: prompt.slice(0, 2000) }],
19
- parameters: { sampleCount: 1, durationSeconds: options?.duration || 5 },
20
- }),
21
- signal: AbortSignal.timeout(300000), // 5 min timeout for video
22
- });
23
- if (!response.ok) {
24
- const err = await response.text();
25
- throw new Error(`Veo error ${response.status}: ${err.slice(0, 200)}`);
26
- }
27
- const data = (await response.json());
28
- const buffer = Buffer.from(data.predictions[0].bytesBase64Encoded, 'base64');
29
- const filePath = saveMedia(buffer, 'mp4', 'generated-video.mp4');
30
- return { filePath, mimeType: 'video/mp4', durationMs: (options?.duration || 5) * 1000 };
31
- }
32
- }
@@ -1,6 +0,0 @@
1
- export type { MediaGenerator, MediaType, GenerateOptions, GenerateResult } from './types.js';
2
- export { createMediaGenerator } from './factory.js';
3
- export { saveMedia, cleanupMedia, ensureMediaDir, isOversized } from './store.js';
4
- import type { MediaGenerator } from './types.js';
5
- import type { MediaGeneratorConfig } from '../types.js';
6
- export declare function initMediaGenerators(configs?: MediaGeneratorConfig[]): MediaGenerator[];
@@ -1,8 +0,0 @@
1
- export { createMediaGenerator } from './factory.js';
2
- export { saveMedia, cleanupMedia, ensureMediaDir, isOversized } from './store.js';
3
- import { createMediaGenerator } from './factory.js';
4
- export function initMediaGenerators(configs) {
5
- if (!configs || configs.length === 0)
6
- return [];
7
- return configs.map((c) => createMediaGenerator(c)).filter((g) => g !== null);
8
- }
@@ -1,8 +0,0 @@
1
- import type { MediaGenerator } from './types.js';
2
- /**
3
- * Discover and load community media generator packages from node_modules.
4
- * Convention: packages named `beecork-media-<name>` must export a default
5
- * class implementing the MediaGenerator interface.
6
- */
7
- export declare function loadCommunityGenerators(apiKeys?: Record<string, string>): Promise<MediaGenerator[]>;
8
- //# sourceMappingURL=loader.d.ts.map
@@ -1,46 +0,0 @@
1
- import fs from 'node:fs';
2
- import path from 'node:path';
3
- import { logger } from '../util/logger.js';
4
- const MEDIA_PREFIX = 'beecork-media-';
5
- /**
6
- * Discover and load community media generator packages from node_modules.
7
- * Convention: packages named `beecork-media-<name>` must export a default
8
- * class implementing the MediaGenerator interface.
9
- */
10
- export async function loadCommunityGenerators(apiKeys) {
11
- const generators = [];
12
- const searchPaths = [path.join(process.cwd(), 'node_modules')];
13
- for (const searchPath of searchPaths) {
14
- if (!fs.existsSync(searchPath))
15
- continue;
16
- try {
17
- for (const dir of fs.readdirSync(searchPath)) {
18
- if (!dir.startsWith(MEDIA_PREFIX))
19
- continue;
20
- try {
21
- const pkgPath = path.join(searchPath, dir);
22
- const pkgJson = JSON.parse(fs.readFileSync(path.join(pkgPath, 'package.json'), 'utf-8'));
23
- const entryPath = path.join(pkgPath, pkgJson.main || 'index.js');
24
- if (!fs.existsSync(entryPath))
25
- continue;
26
- const module = await import(entryPath);
27
- const GeneratorClass = module.default || module[Object.keys(module)[0]];
28
- if (!GeneratorClass || typeof GeneratorClass !== 'function')
29
- continue;
30
- const name = dir.slice(MEDIA_PREFIX.length);
31
- const instance = new GeneratorClass(apiKeys?.[name]);
32
- if (!instance.id || !instance.name || typeof instance.generate !== 'function')
33
- continue;
34
- generators.push(instance);
35
- logger.info(`Community media generator loaded: ${instance.name} (${instance.id})`);
36
- }
37
- catch (err) {
38
- logger.warn(`Failed to load community generator ${dir}:`, err);
39
- }
40
- }
41
- }
42
- catch { }
43
- }
44
- return generators;
45
- }
46
- //# sourceMappingURL=loader.js.map
@@ -1,17 +0,0 @@
1
- /** Ensure media directory exists */
2
- export declare function ensureMediaDir(): string;
3
- /** Save a buffer to the media directory with a unique filename */
4
- export declare function saveMedia(buffer: Buffer, extension: string, originalName?: string): string;
5
- /** Check if a file exceeds the size limit */
6
- export declare function isOversized(sizeBytes: number, maxSizeMb?: number): boolean;
7
- /** Clean up expired media files */
8
- export declare function cleanupMedia(ttlMs?: number): number;
9
- /** Get the media directory path */
10
- export declare function getMediaDir(): string;
11
- /**
12
- * Resolve a file path and confirm it lives inside the beecork media directory.
13
- * Throws otherwise. Used at trust boundaries (MCP tools, voice transcription)
14
- * where a caller could otherwise hand us an arbitrary path to read or upload.
15
- * Returns the resolved (absolute) path on success.
16
- */
17
- export declare function assertInsideMediaDir(filePath: string): string;
@@ -1,69 +0,0 @@
1
- import fs from 'node:fs';
2
- import path from 'node:path';
3
- import { getBeecorkHome } from '../util/paths.js';
4
- import { logger } from '../util/logger.js';
5
- const MEDIA_DIR = path.join(getBeecorkHome(), 'media');
6
- const DEFAULT_TTL_MS = 10 * 60 * 1000; // 10 minutes
7
- const DEFAULT_MAX_SIZE_MB = 25;
8
- /** Ensure media directory exists */
9
- export function ensureMediaDir() {
10
- fs.mkdirSync(MEDIA_DIR, { recursive: true });
11
- return MEDIA_DIR;
12
- }
13
- /** Save a buffer to the media directory with a unique filename */
14
- export function saveMedia(buffer, extension, originalName) {
15
- ensureMediaDir();
16
- const timestamp = Date.now();
17
- const safeName = originalName
18
- ? originalName.replace(/[\/\\]/g, '_').replace(/\.\./g, '_')
19
- : undefined;
20
- const name = safeName ? `${timestamp}-${safeName}` : `${timestamp}.${extension}`;
21
- const filePath = path.join(MEDIA_DIR, name);
22
- fs.writeFileSync(filePath, buffer);
23
- return filePath;
24
- }
25
- /** Check if a file exceeds the size limit */
26
- export function isOversized(sizeBytes, maxSizeMb = DEFAULT_MAX_SIZE_MB) {
27
- return sizeBytes > maxSizeMb * 1024 * 1024;
28
- }
29
- /** Clean up expired media files */
30
- export function cleanupMedia(ttlMs = DEFAULT_TTL_MS) {
31
- if (!fs.existsSync(MEDIA_DIR))
32
- return 0;
33
- const now = Date.now();
34
- let cleaned = 0;
35
- for (const file of fs.readdirSync(MEDIA_DIR)) {
36
- const filePath = path.join(MEDIA_DIR, file);
37
- try {
38
- const stat = fs.statSync(filePath);
39
- if (now - stat.mtimeMs > ttlMs) {
40
- fs.unlinkSync(filePath);
41
- cleaned++;
42
- }
43
- }
44
- catch {
45
- /* file may have been deleted by another process */
46
- }
47
- }
48
- if (cleaned > 0)
49
- logger.info(`Media cleanup: removed ${cleaned} expired files`);
50
- return cleaned;
51
- }
52
- /** Get the media directory path */
53
- export function getMediaDir() {
54
- return MEDIA_DIR;
55
- }
56
- /**
57
- * Resolve a file path and confirm it lives inside the beecork media directory.
58
- * Throws otherwise. Used at trust boundaries (MCP tools, voice transcription)
59
- * where a caller could otherwise hand us an arbitrary path to read or upload.
60
- * Returns the resolved (absolute) path on success.
61
- */
62
- export function assertInsideMediaDir(filePath) {
63
- const resolved = path.resolve(filePath);
64
- const root = path.resolve(MEDIA_DIR) + path.sep;
65
- if (!resolved.startsWith(root)) {
66
- throw new Error(`filePath must be inside the beecork media directory (${MEDIA_DIR})`);
67
- }
68
- return resolved;
69
- }