@speakai/mcp-server 1.0.6 → 1.0.9

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 (3) hide show
  1. package/README.md +416 -159
  2. package/dist/index.js +2447 -92
  3. package/package.json +11 -4
package/dist/index.js CHANGED
@@ -67,10 +67,10 @@ async function authenticate() {
67
67
  process.stderr.write("[speakai-mcp] Authenticated successfully\n");
68
68
  }
69
69
  } catch (err) {
70
- process.stderr.write(
71
- `[speakai-mcp] Authentication failed: ${err instanceof Error ? err.message : err}
72
- `
73
- );
70
+ const message = err instanceof Error ? err.message : String(err);
71
+ process.stderr.write(`[speakai-mcp] Authentication failed: ${message}
72
+ `);
73
+ throw new Error(`Authentication failed: ${message}`);
74
74
  }
75
75
  }
76
76
  async function refreshAccessToken() {
@@ -154,6 +154,9 @@ var init_client = __esm({
154
154
  (response) => response,
155
155
  async (error) => {
156
156
  const originalRequest = error.config;
157
+ if (!originalRequest) {
158
+ return Promise.reject(error);
159
+ }
157
160
  const retryCount = originalRequest._retryCount ?? 0;
158
161
  if (error.response?.status === 401 && retryCount < 2) {
159
162
  originalRequest._retryCount = retryCount + 1;
@@ -169,6 +172,899 @@ var init_client = __esm({
169
172
  }
170
173
  });
171
174
 
175
+ // node_modules/@speakai/shared/dist/enums/activities.js
176
+ var ActivityType;
177
+ var init_activities = __esm({
178
+ "node_modules/@speakai/shared/dist/enums/activities.js"() {
179
+ "use strict";
180
+ (function(ActivityType2) {
181
+ ActivityType2["MEDIA_ANALYSIS"] = "mediaAnalysis";
182
+ ActivityType2["MEDIA_TRANSCRIPTION"] = "mediaTranscription";
183
+ ActivityType2["TEXT_NOTE_ANALYZED"] = "textNoteAnalyzed";
184
+ ActivityType2["RECORDING_RECEIVED"] = "recordingReceived";
185
+ ActivityType2["RECORDER_CREATED"] = "recorderCreated";
186
+ ActivityType2["MEETING_ASSISTANT"] = "meetingAssistant";
187
+ })(ActivityType || (ActivityType = {}));
188
+ }
189
+ });
190
+
191
+ // node_modules/@speakai/shared/dist/enums/auth.js
192
+ var SSOType, DevicePlatform;
193
+ var init_auth = __esm({
194
+ "node_modules/@speakai/shared/dist/enums/auth.js"() {
195
+ "use strict";
196
+ (function(SSOType2) {
197
+ SSOType2["GOOGLE"] = "google";
198
+ SSOType2["MICROSOFT"] = "microsoft";
199
+ SSOType2["APPLE"] = "apple";
200
+ SSOType2["FACEBOOK"] = "facebook";
201
+ })(SSOType || (SSOType = {}));
202
+ (function(DevicePlatform2) {
203
+ DevicePlatform2["IOS"] = "ios";
204
+ DevicePlatform2["ANDROID"] = "android";
205
+ DevicePlatform2["WEB"] = "web";
206
+ DevicePlatform2["ELECTRON"] = "electron";
207
+ DevicePlatform2["API"] = "api";
208
+ })(DevicePlatform || (DevicePlatform = {}));
209
+ }
210
+ });
211
+
212
+ // node_modules/@speakai/shared/dist/enums/automation.js
213
+ var AutomationTrigger, AutomationAction, AutomationRunType, AutomationScheduleTimePeriod, AssistantType;
214
+ var init_automation = __esm({
215
+ "node_modules/@speakai/shared/dist/enums/automation.js"() {
216
+ "use strict";
217
+ (function(AutomationTrigger2) {
218
+ AutomationTrigger2["FOLDERS"] = "folders";
219
+ AutomationTrigger2["TAGS"] = "tags";
220
+ AutomationTrigger2["KEYWORDS"] = "keywords";
221
+ })(AutomationTrigger || (AutomationTrigger = {}));
222
+ (function(AutomationAction2) {
223
+ AutomationAction2["MAGIC_PROMPT"] = "magic-prompt";
224
+ AutomationAction2["TRANSLATION"] = "translation";
225
+ })(AutomationAction || (AutomationAction = {}));
226
+ (function(AutomationRunType2) {
227
+ AutomationRunType2["INSTANT"] = "instant";
228
+ AutomationRunType2["SCHEDULE"] = "schedule";
229
+ })(AutomationRunType || (AutomationRunType = {}));
230
+ (function(AutomationScheduleTimePeriod2) {
231
+ AutomationScheduleTimePeriod2["TODAY"] = "today";
232
+ AutomationScheduleTimePeriod2["YESTERDAY"] = "yesterday";
233
+ AutomationScheduleTimePeriod2["LAST_7_DAYS"] = "last7days";
234
+ AutomationScheduleTimePeriod2["LAST_14_DAYS"] = "last14days";
235
+ AutomationScheduleTimePeriod2["THIS_WEEK"] = "thisWeek";
236
+ })(AutomationScheduleTimePeriod || (AutomationScheduleTimePeriod = {}));
237
+ (function(AssistantType2) {
238
+ AssistantType2["RESEARCHER"] = "researcher";
239
+ AssistantType2["MARKETER"] = "marketer";
240
+ AssistantType2["SALES"] = "sales";
241
+ AssistantType2["GENERAL"] = "general";
242
+ AssistantType2["RECRUITER"] = "recruiter";
243
+ AssistantType2["CUSTOM"] = "custom";
244
+ })(AssistantType || (AssistantType = {}));
245
+ }
246
+ });
247
+
248
+ // node_modules/@speakai/shared/dist/enums/calendar.js
249
+ var CalendarType, EventStatus, AutoJoinStatus;
250
+ var init_calendar = __esm({
251
+ "node_modules/@speakai/shared/dist/enums/calendar.js"() {
252
+ "use strict";
253
+ (function(CalendarType2) {
254
+ CalendarType2["GOOGLE"] = "google";
255
+ CalendarType2["OUTLOOK"] = "outlook";
256
+ })(CalendarType || (CalendarType = {}));
257
+ (function(EventStatus2) {
258
+ EventStatus2["CONFIRMED"] = "confirmed";
259
+ EventStatus2["CANCELLED"] = "cancelled";
260
+ })(EventStatus || (EventStatus = {}));
261
+ (function(AutoJoinStatus2) {
262
+ AutoJoinStatus2["NONE"] = "none";
263
+ AutoJoinStatus2["INVITE_ASSISTANT"] = "inviteAssistant";
264
+ AutoJoinStatus2["ALL_MEETINGS"] = "allMeetings";
265
+ AutoJoinStatus2["HOST"] = "host";
266
+ AutoJoinStatus2["SPEAK_TEAM_MEMBERS_NOT_HOST"] = "speakTeamMembersNotHost";
267
+ })(AutoJoinStatus || (AutoJoinStatus = {}));
268
+ }
269
+ });
270
+
271
+ // node_modules/@speakai/shared/dist/enums/clip.js
272
+ var ClipState, ClipGenerationSource;
273
+ var init_clip = __esm({
274
+ "node_modules/@speakai/shared/dist/enums/clip.js"() {
275
+ "use strict";
276
+ (function(ClipState2) {
277
+ ClipState2["QUEUED"] = "queued";
278
+ ClipState2["PROCESSING"] = "processing";
279
+ ClipState2["COMPLETED"] = "completed";
280
+ ClipState2["FAILED"] = "failed";
281
+ })(ClipState || (ClipState = {}));
282
+ (function(ClipGenerationSource2) {
283
+ ClipGenerationSource2["MANUAL"] = "manual";
284
+ ClipGenerationSource2["CHAT"] = "chat";
285
+ ClipGenerationSource2["AI"] = "ai";
286
+ })(ClipGenerationSource || (ClipGenerationSource = {}));
287
+ }
288
+ });
289
+
290
+ // node_modules/@speakai/shared/dist/enums/domain.js
291
+ var ServiceType, VerificationStatus;
292
+ var init_domain = __esm({
293
+ "node_modules/@speakai/shared/dist/enums/domain.js"() {
294
+ "use strict";
295
+ (function(ServiceType2) {
296
+ ServiceType2["RECORDER"] = "recorder";
297
+ ServiceType2["PLAYER"] = "player";
298
+ ServiceType2["LIBRARY"] = "library";
299
+ })(ServiceType || (ServiceType = {}));
300
+ (function(VerificationStatus2) {
301
+ VerificationStatus2["PENDING"] = "pending";
302
+ VerificationStatus2["VERIFIED"] = "verified";
303
+ VerificationStatus2["FAILED"] = "failed";
304
+ VerificationStatus2["ACTIVE"] = "active";
305
+ })(VerificationStatus || (VerificationStatus = {}));
306
+ }
307
+ });
308
+
309
+ // node_modules/@speakai/shared/dist/enums/embed.js
310
+ var EmbedType, ImageSelectionType;
311
+ var init_embed = __esm({
312
+ "node_modules/@speakai/shared/dist/enums/embed.js"() {
313
+ "use strict";
314
+ (function(EmbedType2) {
315
+ EmbedType2["MEDIA_PLAYER"] = "mediaPlayer";
316
+ EmbedType2["REPOSITORY"] = "repository";
317
+ })(EmbedType || (EmbedType = {}));
318
+ (function(ImageSelectionType2) {
319
+ ImageSelectionType2["LOGO"] = "logo";
320
+ ImageSelectionType2["BACKGROUND_IMG"] = "backgroundImg";
321
+ ImageSelectionType2["MEETING_ASSISTANT"] = "meetingAssistant";
322
+ })(ImageSelectionType || (ImageSelectionType = {}));
323
+ }
324
+ });
325
+
326
+ // node_modules/@speakai/shared/dist/enums/export.js
327
+ var ExportFormatType;
328
+ var init_export = __esm({
329
+ "node_modules/@speakai/shared/dist/enums/export.js"() {
330
+ "use strict";
331
+ (function(ExportFormatType2) {
332
+ ExportFormatType2["CSV"] = "csv";
333
+ ExportFormatType2["CSV_INSIGHTS"] = "csv-insights";
334
+ ExportFormatType2["CSV_TRANSCRIPT"] = "csv-transcript";
335
+ ExportFormatType2["CSV_TRANSCRIPT_WITH_SENTIMENT"] = "csv-transcript-sentiment";
336
+ ExportFormatType2["CSV_TEXT_WITH_SENTIMENT"] = "csv-text-sentiment";
337
+ ExportFormatType2["DOCX"] = "docx";
338
+ ExportFormatType2["HTML"] = "html";
339
+ ExportFormatType2["JSON"] = "json";
340
+ ExportFormatType2["PDF"] = "pdf";
341
+ ExportFormatType2["SOURCEFILE"] = "sourceFile";
342
+ ExportFormatType2["SRT"] = "srt";
343
+ ExportFormatType2["TTML"] = "ttml";
344
+ ExportFormatType2["TXT"] = "txt";
345
+ ExportFormatType2["VTT"] = "vtt";
346
+ ExportFormatType2["MP4"] = "mp4";
347
+ })(ExportFormatType || (ExportFormatType = {}));
348
+ }
349
+ });
350
+
351
+ // node_modules/@speakai/shared/dist/enums/fields.js
352
+ var FieldType, AllowedValuesMode, DefaultViewColumn;
353
+ var init_fields = __esm({
354
+ "node_modules/@speakai/shared/dist/enums/fields.js"() {
355
+ "use strict";
356
+ (function(FieldType2) {
357
+ FieldType2["TEXT"] = "text";
358
+ FieldType2["URL"] = "url";
359
+ FieldType2["BOOLEAN"] = "boolean";
360
+ FieldType2["DATE"] = "date";
361
+ FieldType2["DATETIME"] = "datetime";
362
+ FieldType2["NUMBER"] = "number";
363
+ FieldType2["CURRENCY"] = "currency";
364
+ })(FieldType || (FieldType = {}));
365
+ (function(AllowedValuesMode2) {
366
+ AllowedValuesMode2["SINGLE"] = "single";
367
+ AllowedValuesMode2["MULTIPLE"] = "multiple";
368
+ })(AllowedValuesMode || (AllowedValuesMode = {}));
369
+ (function(DefaultViewColumn2) {
370
+ DefaultViewColumn2["NAME"] = "name";
371
+ DefaultViewColumn2["DURATION"] = "duration";
372
+ DefaultViewColumn2["TAGS"] = "tags";
373
+ DefaultViewColumn2["SENTIMENT"] = "sentiment";
374
+ DefaultViewColumn2["DATETIME"] = "datetime";
375
+ DefaultViewColumn2["SIZE"] = "size";
376
+ DefaultViewColumn2["MEDIA_TYPE"] = "mediaType";
377
+ DefaultViewColumn2["CREATED_AT"] = "createdAt";
378
+ DefaultViewColumn2["UPDATED_AT"] = "updatedAt";
379
+ })(DefaultViewColumn || (DefaultViewColumn = {}));
380
+ }
381
+ });
382
+
383
+ // node_modules/@speakai/shared/dist/enums/filter.js
384
+ var FilterFieldName, FilterOperator, FilterCondition;
385
+ var init_filter = __esm({
386
+ "node_modules/@speakai/shared/dist/enums/filter.js"() {
387
+ "use strict";
388
+ (function(FilterFieldName2) {
389
+ FilterFieldName2["CATEGORY"] = "category";
390
+ FilterFieldName2["FOLDER_ID"] = "folderId";
391
+ FilterFieldName2["MEDIA_ID"] = "mediaId";
392
+ FilterFieldName2["MEDIA_TYPE"] = "mediaType";
393
+ FilterFieldName2["SENTIMENT_NEGATIVE"] = "sentimentNegative";
394
+ FilterFieldName2["SENTIMENT_POSITIVE"] = "sentimentPositive";
395
+ FilterFieldName2["SPEAKER"] = "speaker";
396
+ FilterFieldName2["TAGS"] = "tags";
397
+ FilterFieldName2["RECORDER_ID"] = "recorderId";
398
+ FilterFieldName2["FIELDS"] = "fields";
399
+ })(FilterFieldName || (FilterFieldName = {}));
400
+ (function(FilterOperator2) {
401
+ FilterOperator2["INCLUDE"] = "include";
402
+ FilterOperator2["NOT_INCLUDE"] = "notInclude";
403
+ FilterOperator2["CONTAIN"] = "contain";
404
+ FilterOperator2["NOT_CONTAIN"] = "notContain";
405
+ FilterOperator2["GREATER_THAN"] = "greaterThan";
406
+ FilterOperator2["LESS_THAN"] = "lessThan";
407
+ })(FilterOperator || (FilterOperator = {}));
408
+ (function(FilterCondition2) {
409
+ FilterCondition2["AND"] = "and";
410
+ FilterCondition2["OR"] = "or";
411
+ })(FilterCondition || (FilterCondition = {}));
412
+ }
413
+ });
414
+
415
+ // node_modules/@speakai/shared/dist/enums/media.js
416
+ var MediaType, MediaState, MediaPrivacyMode, MediaInsightType, MediaInsightStatus, MediaProcessType;
417
+ var init_media = __esm({
418
+ "node_modules/@speakai/shared/dist/enums/media.js"() {
419
+ "use strict";
420
+ (function(MediaType2) {
421
+ MediaType2["AUDIO"] = "audio";
422
+ MediaType2["VIDEO"] = "video";
423
+ MediaType2["TEXT"] = "text";
424
+ MediaType2["MEDIA"] = "media";
425
+ MediaType2["CSV"] = "csv";
426
+ })(MediaType || (MediaType = {}));
427
+ (function(MediaState3) {
428
+ MediaState3["NOT_UPLOADED"] = "notUploaded";
429
+ MediaState3["UPLOADED"] = "uploaded";
430
+ MediaState3["QUEUED"] = "queued";
431
+ MediaState3["PENDING_PAYMENT"] = "pendingPayment";
432
+ MediaState3["PREPARING"] = "preparing";
433
+ MediaState3["PREPARING_TRANSCRIPTION"] = "preparingTranscription";
434
+ MediaState3["PROCESSING"] = "processing";
435
+ MediaState3["TRANSLATION"] = "translation";
436
+ MediaState3["PREPARING_ANALYSIS"] = "preparingAnalysis";
437
+ MediaState3["PROCESSED"] = "processed";
438
+ MediaState3["DUBBING"] = "dubbing";
439
+ MediaState3["FAILED"] = "failed";
440
+ MediaState3["COMPLETE"] = "complete";
441
+ MediaState3["LIVE_TRANSCRIPT"] = "liveTranscript";
442
+ })(MediaState || (MediaState = {}));
443
+ (function(MediaPrivacyMode2) {
444
+ MediaPrivacyMode2["PUBLIC"] = "public";
445
+ MediaPrivacyMode2["PRIVATE"] = "private";
446
+ })(MediaPrivacyMode || (MediaPrivacyMode = {}));
447
+ (function(MediaInsightType2) {
448
+ MediaInsightType2["Arts"] = "arts";
449
+ MediaInsightType2["Brands"] = "brands";
450
+ MediaInsightType2["Cardinals"] = "cardinals";
451
+ MediaInsightType2["Dates"] = "dates";
452
+ MediaInsightType2["Events"] = "events";
453
+ MediaInsightType2["Geopolitical"] = "geopolitical";
454
+ MediaInsightType2["Keywords"] = "keywords";
455
+ MediaInsightType2["Languages"] = "languages";
456
+ MediaInsightType2["Laws"] = "laws";
457
+ MediaInsightType2["Locations"] = "locations";
458
+ MediaInsightType2["Money"] = "money";
459
+ MediaInsightType2["Nationalities"] = "nationalities";
460
+ MediaInsightType2["Ordinals"] = "ordinals";
461
+ MediaInsightType2["People"] = "people";
462
+ MediaInsightType2["Percentages"] = "percentages";
463
+ MediaInsightType2["Products"] = "products";
464
+ MediaInsightType2["Quantities"] = "quantities";
465
+ MediaInsightType2["Times"] = "times";
466
+ MediaInsightType2["Topics"] = "topics";
467
+ MediaInsightType2["Transcript"] = "transcript";
468
+ MediaInsightType2["Addresses"] = "addresses";
469
+ })(MediaInsightType || (MediaInsightType = {}));
470
+ (function(MediaInsightStatus2) {
471
+ MediaInsightStatus2["PENDING"] = "pending";
472
+ MediaInsightStatus2["PROCESSING"] = "processing";
473
+ MediaInsightStatus2["COMPLETED"] = "completed";
474
+ MediaInsightStatus2["FAILED"] = "failed";
475
+ MediaInsightStatus2["KILLED"] = "killed";
476
+ })(MediaInsightStatus || (MediaInsightStatus = {}));
477
+ (function(MediaProcessType2) {
478
+ MediaProcessType2["TRANSCRIPTION"] = "transcription";
479
+ MediaProcessType2["DUBBING"] = "dubbing";
480
+ MediaProcessType2["TRANSLATION"] = "translation";
481
+ })(MediaProcessType || (MediaProcessType = {}));
482
+ }
483
+ });
484
+
485
+ // node_modules/@speakai/shared/dist/enums/meeting.js
486
+ var MeetingPlatform, MeetingStatus, MeetingRecordingMode, ScreenShareRecordingMode, MeetingSummarySettings, MediaPlayerSettings, MeetingFilterEventCondition, MeetingAttendeeType, MeetingAssistantEventSource;
487
+ var init_meeting = __esm({
488
+ "node_modules/@speakai/shared/dist/enums/meeting.js"() {
489
+ "use strict";
490
+ (function(MeetingPlatform2) {
491
+ MeetingPlatform2["GOOGLE_MEET"] = "googleMeet";
492
+ MeetingPlatform2["ZOOM"] = "zoom";
493
+ MeetingPlatform2["MICROSOFT_TEAMS"] = "microsoftTeams";
494
+ MeetingPlatform2["WEBEX"] = "webex";
495
+ })(MeetingPlatform || (MeetingPlatform = {}));
496
+ (function(MeetingStatus2) {
497
+ MeetingStatus2["WILL_JOIN"] = "willJoin";
498
+ MeetingStatus2["SCHEDULED"] = "scheduled";
499
+ MeetingStatus2["READY"] = "ready";
500
+ MeetingStatus2["JOINING_CALL"] = "joiningCall";
501
+ MeetingStatus2["IN_WAITING_ROOM"] = "inWaitingRoom";
502
+ MeetingStatus2["IN_CALL_NOT_RECORDING"] = "inCallNotRecording";
503
+ MeetingStatus2["RECORDING_PERMISSION_DENIED"] = "recordingPermissionDenied";
504
+ MeetingStatus2["IN_CALL_RECORDING"] = "inCallRecording";
505
+ MeetingStatus2["CALL_ENDED"] = "callEnded";
506
+ MeetingStatus2["DONE"] = "done";
507
+ MeetingStatus2["FATAL"] = "fatal";
508
+ MeetingStatus2["ANALYSIS_DONE"] = "analysisDone";
509
+ MeetingStatus2["PAUSED"] = "paused";
510
+ MeetingStatus2["RESUMED"] = "resumed";
511
+ MeetingStatus2["CANCELLED"] = "cancelled";
512
+ MeetingStatus2["NOT_INVITED"] = "notInvited";
513
+ })(MeetingStatus || (MeetingStatus = {}));
514
+ (function(MeetingRecordingMode2) {
515
+ MeetingRecordingMode2["SPEAKER_VIEW"] = "speakerView";
516
+ MeetingRecordingMode2["GALLERY_VIEW"] = "galleryView";
517
+ MeetingRecordingMode2["GALLERY_VIEW_V2"] = "galleryViewV2";
518
+ MeetingRecordingMode2["AUDIO_ONLY"] = "audioOnly";
519
+ })(MeetingRecordingMode || (MeetingRecordingMode = {}));
520
+ (function(ScreenShareRecordingMode2) {
521
+ ScreenShareRecordingMode2["HIDE"] = "hide";
522
+ ScreenShareRecordingMode2["BESIDE"] = "beside";
523
+ ScreenShareRecordingMode2["OVERLAP"] = "overlap";
524
+ })(ScreenShareRecordingMode || (ScreenShareRecordingMode = {}));
525
+ (function(MeetingSummarySettings2) {
526
+ MeetingSummarySettings2["SELF"] = "self";
527
+ MeetingSummarySettings2["ALL_ATTENDEES"] = "allAttendees";
528
+ MeetingSummarySettings2["NONE"] = "none";
529
+ })(MeetingSummarySettings || (MeetingSummarySettings = {}));
530
+ (function(MediaPlayerSettings2) {
531
+ MediaPlayerSettings2["ALL_ATTENDEES"] = "allAttendees";
532
+ MediaPlayerSettings2["TEAM_MEMBERS"] = "teamMembers";
533
+ MediaPlayerSettings2["FOLDER_TEAM_MEMBERS"] = "folderTeamMembers";
534
+ MediaPlayerSettings2["SELF"] = "self";
535
+ MediaPlayerSettings2["NONE"] = "none";
536
+ })(MediaPlayerSettings || (MediaPlayerSettings = {}));
537
+ (function(MeetingFilterEventCondition2) {
538
+ MeetingFilterEventCondition2["CONTAINS"] = "contains";
539
+ MeetingFilterEventCondition2["EQUALS"] = "equals";
540
+ })(MeetingFilterEventCondition || (MeetingFilterEventCondition = {}));
541
+ (function(MeetingAttendeeType2) {
542
+ MeetingAttendeeType2["HOST"] = "host";
543
+ MeetingAttendeeType2["ASSISTANT"] = "assistant";
544
+ MeetingAttendeeType2["SELF"] = "self";
545
+ MeetingAttendeeType2["GUEST"] = "guest";
546
+ })(MeetingAttendeeType || (MeetingAttendeeType = {}));
547
+ (function(MeetingAssistantEventSource2) {
548
+ MeetingAssistantEventSource2["INSTANT"] = "instant";
549
+ MeetingAssistantEventSource2["ASSISTANT"] = "assistant";
550
+ })(MeetingAssistantEventSource || (MeetingAssistantEventSource = {}));
551
+ }
552
+ });
553
+
554
+ // node_modules/@speakai/shared/dist/enums/notification.js
555
+ var NotificationType, NotificationAction;
556
+ var init_notification = __esm({
557
+ "node_modules/@speakai/shared/dist/enums/notification.js"() {
558
+ "use strict";
559
+ (function(NotificationType2) {
560
+ NotificationType2["CLIP"] = "clip";
561
+ NotificationType2["AUDIO"] = "audio";
562
+ NotificationType2["ACCOUNT"] = "account";
563
+ NotificationType2["AUTOMATION"] = "automation";
564
+ NotificationType2["EMBED"] = "embed";
565
+ NotificationType2["INTEGRATION"] = "integration";
566
+ NotificationType2["MAGIC_PROMPT"] = "magic prompt";
567
+ NotificationType2["MEDIA"] = "media";
568
+ NotificationType2["PAYMENT"] = "payment";
569
+ NotificationType2["PRESENTATION"] = "presentation";
570
+ NotificationType2["RECORDER"] = "recorder";
571
+ NotificationType2["SURVEY"] = "survey";
572
+ NotificationType2["SUBSCRIPTION"] = "subscription";
573
+ NotificationType2["TEAM"] = "team";
574
+ NotificationType2["TEXT"] = "text";
575
+ NotificationType2["TRANSCRIPTION"] = "transcription";
576
+ NotificationType2["TRANSLATE"] = "translate";
577
+ NotificationType2["VIDEO"] = "video";
578
+ NotificationType2["ZAPIER"] = "zapier";
579
+ NotificationType2["MEETING_ASSISTANT"] = "meeting assistant";
580
+ NotificationType2["GOOGLE_CALENDAR"] = "google calendar";
581
+ NotificationType2["OUTLOOK_CALENDAR"] = "outlook calendar";
582
+ NotificationType2["AUTO_RELOAD"] = "auto reload";
583
+ NotificationType2["FOLDER"] = "folder";
584
+ NotificationType2["FIELDS"] = "fields";
585
+ NotificationType2["ASSISTANT_TEMPLATE"] = "assistant template";
586
+ })(NotificationType || (NotificationType = {}));
587
+ (function(NotificationAction2) {
588
+ NotificationAction2["ANALYZED"] = "analyzed";
589
+ NotificationAction2["CREATED"] = "created";
590
+ NotificationAction2["CREDIT"] = "credit";
591
+ NotificationAction2["DEBIT"] = "debit";
592
+ NotificationAction2["DELETED"] = "deleted";
593
+ NotificationAction2["EXPORT"] = "export";
594
+ NotificationAction2["PAID"] = "paid";
595
+ NotificationAction2["UPDATED"] = "updated";
596
+ NotificationAction2["UPLOADED"] = "uploaded";
597
+ NotificationAction2["ERROR"] = "error";
598
+ NotificationAction2["FAILED"] = "failed";
599
+ NotificationAction2["CLONED"] = "cloned";
600
+ })(NotificationAction || (NotificationAction = {}));
601
+ }
602
+ });
603
+
604
+ // node_modules/@speakai/shared/dist/enums/prompt.js
605
+ var PromptState, MessageRole, PromptSource, ToolName, FileType;
606
+ var init_prompt = __esm({
607
+ "node_modules/@speakai/shared/dist/enums/prompt.js"() {
608
+ "use strict";
609
+ (function(PromptState2) {
610
+ PromptState2["INITIATED"] = "initiated";
611
+ PromptState2["PREPARING"] = "preparing";
612
+ PromptState2["PROCESSING"] = "processing";
613
+ PromptState2["FAILED"] = "failed";
614
+ PromptState2["PENDING_PAYMENT"] = "pendingPayment";
615
+ PromptState2["COMPLETED"] = "completed";
616
+ PromptState2["CANCELLED"] = "cancelled";
617
+ PromptState2["EXPIRED"] = "expired";
618
+ PromptState2["IN_PROGRESS"] = "inProgress";
619
+ PromptState2["STREAMING"] = "streaming";
620
+ })(PromptState || (PromptState = {}));
621
+ (function(MessageRole2) {
622
+ MessageRole2["SYSTEM"] = "system";
623
+ MessageRole2["USER"] = "user";
624
+ MessageRole2["ASSISTANT"] = "assistant";
625
+ })(MessageRole || (MessageRole = {}));
626
+ (function(PromptSource2) {
627
+ PromptSource2["FOLDER"] = "folder";
628
+ PromptSource2["MEDIA_FILES"] = "mediaFiles";
629
+ PromptSource2["CSV_FILE"] = "csvFile";
630
+ PromptSource2["KNOWLEDGE_BASE"] = "knowledgeBase";
631
+ PromptSource2["EXPLORE_ANALYTICS"] = "exploreAnalytics";
632
+ })(PromptSource || (PromptSource = {}));
633
+ (function(ToolName2) {
634
+ ToolName2["OPEN_SUPPORT"] = "open_support";
635
+ ToolName2["CREATE_CLIP"] = "create_clip";
636
+ ToolName2["UPDATE_SPEAKERS"] = "update_speakers";
637
+ ToolName2["UPDATE_TRANSCRIPTION"] = "update_transcription";
638
+ ToolName2["SEARCH_MEDIA"] = "search_media";
639
+ ToolName2["GENERATE_CHART"] = "generate_chart";
640
+ ToolName2["EXPORT_TRANSCRIPTION"] = "export_transcription";
641
+ ToolName2["COMPARE_MEDIA"] = "compare_media";
642
+ })(ToolName || (ToolName = {}));
643
+ (function(FileType2) {
644
+ FileType2["IMAGE"] = "image";
645
+ FileType2["CSV"] = "csv";
646
+ FileType2["PDF"] = "pdf";
647
+ FileType2["DOCX"] = "docx";
648
+ FileType2["TXT"] = "txt";
649
+ FileType2["ZIP"] = "zip";
650
+ })(FileType || (FileType = {}));
651
+ }
652
+ });
653
+
654
+ // node_modules/@speakai/shared/dist/enums/recorder.js
655
+ var RecorderAnswerType, RecorderUploadType, RecordingFeedbackRating;
656
+ var init_recorder = __esm({
657
+ "node_modules/@speakai/shared/dist/enums/recorder.js"() {
658
+ "use strict";
659
+ (function(RecorderAnswerType2) {
660
+ RecorderAnswerType2["Single"] = "single";
661
+ RecorderAnswerType2["Multiple"] = "multiple";
662
+ RecorderAnswerType2["Checkbox"] = "checkbox";
663
+ RecorderAnswerType2["Radiobutton"] = "radiobutton";
664
+ RecorderAnswerType2["Dropdownlist"] = "dropdownlist";
665
+ RecorderAnswerType2["Date"] = "date";
666
+ RecorderAnswerType2["Time"] = "time";
667
+ RecorderAnswerType2["Datetime"] = "datetime";
668
+ })(RecorderAnswerType || (RecorderAnswerType = {}));
669
+ (function(RecorderUploadType2) {
670
+ RecorderUploadType2["RECORD"] = "record";
671
+ RecorderUploadType2["FILE"] = "file";
672
+ RecorderUploadType2["YOUTUBE"] = "youtube";
673
+ RecorderUploadType2["LIVE_RECORD"] = "live-record";
674
+ })(RecorderUploadType || (RecorderUploadType = {}));
675
+ (function(RecordingFeedbackRating2) {
676
+ RecordingFeedbackRating2["POSITIVE"] = "positive";
677
+ RecordingFeedbackRating2["NEGATIVE"] = "negative";
678
+ })(RecordingFeedbackRating || (RecordingFeedbackRating = {}));
679
+ }
680
+ });
681
+
682
+ // node_modules/@speakai/shared/dist/enums/subscription.js
683
+ var SubscriptionStatus, SubscriptionDuration;
684
+ var init_subscription = __esm({
685
+ "node_modules/@speakai/shared/dist/enums/subscription.js"() {
686
+ "use strict";
687
+ (function(SubscriptionStatus2) {
688
+ SubscriptionStatus2["Active"] = "active";
689
+ SubscriptionStatus2["Paused"] = "paused";
690
+ SubscriptionStatus2["PendingReview"] = "pendingReview";
691
+ SubscriptionStatus2["PendingCancellation"] = "pendingCancellation";
692
+ SubscriptionStatus2["Cancelled"] = "cancelled";
693
+ SubscriptionStatus2["PendingPayment"] = "pendingPayment";
694
+ })(SubscriptionStatus || (SubscriptionStatus = {}));
695
+ (function(SubscriptionDuration2) {
696
+ SubscriptionDuration2["Monthly"] = "monthly";
697
+ SubscriptionDuration2["2Months"] = "2months";
698
+ SubscriptionDuration2["3Months"] = "3months";
699
+ SubscriptionDuration2["6Months"] = "6months";
700
+ SubscriptionDuration2["9Months"] = "9months";
701
+ SubscriptionDuration2["Yearly"] = "yearly";
702
+ })(SubscriptionDuration || (SubscriptionDuration = {}));
703
+ }
704
+ });
705
+
706
+ // node_modules/@speakai/shared/dist/enums/team.js
707
+ var TeamInviteStatus;
708
+ var init_team = __esm({
709
+ "node_modules/@speakai/shared/dist/enums/team.js"() {
710
+ "use strict";
711
+ (function(TeamInviteStatus2) {
712
+ TeamInviteStatus2["ACTIVE"] = "active";
713
+ TeamInviteStatus2["EXPIRED"] = "expired";
714
+ TeamInviteStatus2["REVOKED"] = "revoked";
715
+ TeamInviteStatus2["EXHAUSTED"] = "exhausted";
716
+ })(TeamInviteStatus || (TeamInviteStatus = {}));
717
+ }
718
+ });
719
+
720
+ // node_modules/@speakai/shared/dist/enums/transcription.js
721
+ var TranscriptionEngine, TranscriptionJobState, TranscriptionJobRevisionState;
722
+ var init_transcription = __esm({
723
+ "node_modules/@speakai/shared/dist/enums/transcription.js"() {
724
+ "use strict";
725
+ (function(TranscriptionEngine2) {
726
+ TranscriptionEngine2["AZURE"] = "azure";
727
+ TranscriptionEngine2["ASSEMBLY"] = "assembly";
728
+ TranscriptionEngine2["DEEPGRAM"] = "deepgram";
729
+ TranscriptionEngine2["AWS"] = "aws";
730
+ })(TranscriptionEngine || (TranscriptionEngine = {}));
731
+ (function(TranscriptionJobState2) {
732
+ TranscriptionJobState2["Initiate"] = "initiate";
733
+ TranscriptionJobState2["PendingPayment"] = "pendingPayment";
734
+ TranscriptionJobState2["InQueue"] = "inQueue";
735
+ TranscriptionJobState2["PendingEdition"] = "pendingEdition";
736
+ TranscriptionJobState2["PendingQAReview"] = "pendingQAReview";
737
+ TranscriptionJobState2["PendingUserReview"] = "pendingUserReview";
738
+ TranscriptionJobState2["Complete"] = "complete";
739
+ TranscriptionJobState2["Failed"] = "failed";
740
+ })(TranscriptionJobState || (TranscriptionJobState = {}));
741
+ (function(TranscriptionJobRevisionState2) {
742
+ TranscriptionJobRevisionState2["Approved"] = "approved";
743
+ TranscriptionJobRevisionState2["BeingEdited"] = "beingEdited";
744
+ TranscriptionJobRevisionState2["BeingQAReviewed"] = "beingQAReviewed";
745
+ TranscriptionJobRevisionState2["PendingQAReview"] = "pendingQAReview";
746
+ TranscriptionJobRevisionState2["PendingUserReview"] = "pendingUserReview";
747
+ TranscriptionJobRevisionState2["Rejected"] = "rejected";
748
+ })(TranscriptionJobRevisionState || (TranscriptionJobRevisionState = {}));
749
+ }
750
+ });
751
+
752
+ // node_modules/@speakai/shared/dist/enums/transaction.js
753
+ var TransactionSource, TransactionType, TransactionStatus;
754
+ var init_transaction = __esm({
755
+ "node_modules/@speakai/shared/dist/enums/transaction.js"() {
756
+ "use strict";
757
+ (function(TransactionSource2) {
758
+ TransactionSource2["STRIPE"] = "stripe";
759
+ TransactionSource2["PADDLE"] = "paddle";
760
+ TransactionSource2["REVENUECAT_IOS"] = "ios";
761
+ TransactionSource2["REVENUECAT_ANDROID"] = "android";
762
+ TransactionSource2["REVENUECAT_STRIPE"] = "revenuecat_stripe";
763
+ TransactionSource2["BALANCE"] = "balance";
764
+ TransactionSource2["MANUAL"] = "manual";
765
+ })(TransactionSource || (TransactionSource = {}));
766
+ (function(TransactionType2) {
767
+ TransactionType2["SUBSCRIPTION"] = "subscription";
768
+ TransactionType2["ONE_TIME"] = "one_time";
769
+ TransactionType2["USAGE"] = "usage";
770
+ TransactionType2["REFUND"] = "refund";
771
+ TransactionType2["BALANCE_ADD"] = "balance_add";
772
+ TransactionType2["AUTO_RELOAD"] = "auto_reload";
773
+ })(TransactionType || (TransactionType = {}));
774
+ (function(TransactionStatus2) {
775
+ TransactionStatus2["PENDING"] = "pending";
776
+ TransactionStatus2["PROCESSING"] = "processing";
777
+ TransactionStatus2["SUCCEEDED"] = "succeeded";
778
+ TransactionStatus2["FAILED"] = "failed";
779
+ TransactionStatus2["REFUNDED"] = "refunded";
780
+ TransactionStatus2["CANCELLED"] = "cancelled";
781
+ })(TransactionStatus || (TransactionStatus = {}));
782
+ }
783
+ });
784
+
785
+ // node_modules/@speakai/shared/dist/enums/translation.js
786
+ var TranslationState, DubbingState;
787
+ var init_translation = __esm({
788
+ "node_modules/@speakai/shared/dist/enums/translation.js"() {
789
+ "use strict";
790
+ (function(TranslationState2) {
791
+ TranslationState2["NOTFOUND"] = "notFound";
792
+ TranslationState2["INITIATE"] = "initiate";
793
+ TranslationState2["PENDING_TRANSCRIPTION"] = "pendingTranscription";
794
+ TranslationState2["PENDING_PAYMENT"] = "pendingPayment";
795
+ TranslationState2["PROCESSING"] = "processing";
796
+ TranslationState2["DUBBING"] = "dubbing";
797
+ TranslationState2["COMPLETE"] = "complete";
798
+ TranslationState2["FAILED"] = "failed";
799
+ })(TranslationState || (TranslationState = {}));
800
+ (function(DubbingState2) {
801
+ DubbingState2["DUBBING"] = "dubbing";
802
+ DubbingState2["UPLOADING"] = "uploading";
803
+ DubbingState2["COMPLETE"] = "complete";
804
+ DubbingState2["FAILED"] = "failed";
805
+ })(DubbingState || (DubbingState = {}));
806
+ }
807
+ });
808
+
809
+ // node_modules/@speakai/shared/dist/enums/user.js
810
+ var UserRole, UserPermissionType, UserActionType;
811
+ var init_user = __esm({
812
+ "node_modules/@speakai/shared/dist/enums/user.js"() {
813
+ "use strict";
814
+ (function(UserRole2) {
815
+ UserRole2["ADMIN"] = "admin";
816
+ UserRole2["OWNER"] = "owner";
817
+ UserRole2["MEMBER"] = "member";
818
+ })(UserRole || (UserRole = {}));
819
+ (function(UserPermissionType2) {
820
+ UserPermissionType2["FOLDER"] = "folder";
821
+ UserPermissionType2["RECORDER"] = "recorder";
822
+ UserPermissionType2["MEDIA"] = "media";
823
+ UserPermissionType2["PAYMENT"] = "payment";
824
+ UserPermissionType2["TEAM_MANAGEMENT"] = "teamManagement";
825
+ UserPermissionType2["DEVELOPER"] = "developer";
826
+ UserPermissionType2["PROFILE_SETTINGS"] = "profileSettings";
827
+ UserPermissionType2["MEETING_ASSISTANT"] = "meetingAssistant";
828
+ })(UserPermissionType || (UserPermissionType = {}));
829
+ (function(UserActionType2) {
830
+ UserActionType2["CREATE"] = "create";
831
+ UserActionType2["DOWNLOAD"] = "download";
832
+ UserActionType2["UPDATE"] = "update";
833
+ UserActionType2["EDIT"] = "edit";
834
+ UserActionType2["DELETE"] = "delete";
835
+ UserActionType2["SHARE"] = "share";
836
+ UserActionType2["ASSIGN"] = "assign";
837
+ UserActionType2["MANAGE_CARDS"] = "manageCards";
838
+ UserActionType2["MANAGE_INVOICES"] = "manageInvoices";
839
+ UserActionType2["MANAGE_MEMBERS"] = "manageMembers";
840
+ UserActionType2["MANAGE_GROUPS"] = "manageGroups";
841
+ UserActionType2["ACCESS_KEYS"] = "accessKeys";
842
+ UserActionType2["ACCOUNT_PREFERENCES"] = "accountPreferences";
843
+ UserActionType2["ACCOUNT_CUSTOMIZATION"] = "accountCustomization";
844
+ UserActionType2["DATA_MANAGEMENT"] = "dataManagement";
845
+ UserActionType2["CUSTOMIZE_ASSISTANT"] = "customizeAssistant";
846
+ UserActionType2["SHARE_MEETINGS"] = "shareMeetings";
847
+ UserActionType2["ROUTE_MEETINGS"] = "routeMeetings";
848
+ UserActionType2["EXCLUDE_MEETINGS"] = "excludeMeetings";
849
+ UserActionType2["GLOBAL_SETTINGS"] = "globalSettings";
850
+ UserActionType2["ACCESS_ALL"] = "accessAll";
851
+ })(UserActionType || (UserActionType = {}));
852
+ }
853
+ });
854
+
855
+ // node_modules/@speakai/shared/dist/enums/webhook.js
856
+ var WebhookEvent, WebhookEventSource;
857
+ var init_webhook = __esm({
858
+ "node_modules/@speakai/shared/dist/enums/webhook.js"() {
859
+ "use strict";
860
+ (function(WebhookEvent2) {
861
+ WebhookEvent2["embed_recorder.created"] = "embed_recorder.created";
862
+ WebhookEvent2["embed_recorder.deleted"] = "embed_recorder.deleted";
863
+ WebhookEvent2["embed_recorder.recording_received"] = "embed_recorder.recording_received";
864
+ WebhookEvent2["media.analyzed"] = "media.analyzed";
865
+ WebhookEvent2["media.created"] = "media.created";
866
+ WebhookEvent2["media.deleted"] = "media.deleted";
867
+ WebhookEvent2["media.failed"] = "media.failed";
868
+ WebhookEvent2["media.reanalyzed"] = "media.reanalyzed";
869
+ WebhookEvent2["media.updated"] = "media.updated";
870
+ WebhookEvent2["text.analyzed"] = "text.analyzed";
871
+ WebhookEvent2["text.created"] = "text.created";
872
+ WebhookEvent2["text.deleted"] = "text.deleted";
873
+ WebhookEvent2["text.failed"] = "text.failed";
874
+ WebhookEvent2["text.reanalyzed"] = "text.reanalyzed";
875
+ WebhookEvent2["meeting_assistant.status"] = "meeting_assistant.status";
876
+ WebhookEvent2["chat.status"] = "chat.status";
877
+ WebhookEvent2["csv.uploaded"] = "csv.uploaded";
878
+ WebhookEvent2["csv.failed"] = "csv.failed";
879
+ })(WebhookEvent || (WebhookEvent = {}));
880
+ (function(WebhookEventSource2) {
881
+ WebhookEventSource2["SPEAK"] = "speak";
882
+ WebhookEventSource2["ZAPIER"] = "zapier";
883
+ })(WebhookEventSource || (WebhookEventSource = {}));
884
+ }
885
+ });
886
+
887
+ // node_modules/@speakai/shared/dist/enums/index.js
888
+ var init_enums = __esm({
889
+ "node_modules/@speakai/shared/dist/enums/index.js"() {
890
+ "use strict";
891
+ init_activities();
892
+ init_auth();
893
+ init_automation();
894
+ init_calendar();
895
+ init_clip();
896
+ init_domain();
897
+ init_embed();
898
+ init_export();
899
+ init_fields();
900
+ init_filter();
901
+ init_media();
902
+ init_meeting();
903
+ init_notification();
904
+ init_prompt();
905
+ init_recorder();
906
+ init_subscription();
907
+ init_team();
908
+ init_transcription();
909
+ init_transaction();
910
+ init_translation();
911
+ init_user();
912
+ init_webhook();
913
+ }
914
+ });
915
+
916
+ // node_modules/@speakai/shared/dist/interfaces/api.js
917
+ var init_api = __esm({
918
+ "node_modules/@speakai/shared/dist/interfaces/api.js"() {
919
+ "use strict";
920
+ }
921
+ });
922
+
923
+ // node_modules/@speakai/shared/dist/interfaces/media.js
924
+ var init_media2 = __esm({
925
+ "node_modules/@speakai/shared/dist/interfaces/media.js"() {
926
+ "use strict";
927
+ }
928
+ });
929
+
930
+ // node_modules/@speakai/shared/dist/interfaces/transcript.js
931
+ var init_transcript = __esm({
932
+ "node_modules/@speakai/shared/dist/interfaces/transcript.js"() {
933
+ "use strict";
934
+ }
935
+ });
936
+
937
+ // node_modules/@speakai/shared/dist/interfaces/text.js
938
+ var init_text = __esm({
939
+ "node_modules/@speakai/shared/dist/interfaces/text.js"() {
940
+ "use strict";
941
+ }
942
+ });
943
+
944
+ // node_modules/@speakai/shared/dist/interfaces/folder.js
945
+ var init_folder = __esm({
946
+ "node_modules/@speakai/shared/dist/interfaces/folder.js"() {
947
+ "use strict";
948
+ }
949
+ });
950
+
951
+ // node_modules/@speakai/shared/dist/interfaces/recorder.js
952
+ var init_recorder2 = __esm({
953
+ "node_modules/@speakai/shared/dist/interfaces/recorder.js"() {
954
+ "use strict";
955
+ }
956
+ });
957
+
958
+ // node_modules/@speakai/shared/dist/interfaces/embed.js
959
+ var init_embed2 = __esm({
960
+ "node_modules/@speakai/shared/dist/interfaces/embed.js"() {
961
+ "use strict";
962
+ }
963
+ });
964
+
965
+ // node_modules/@speakai/shared/dist/interfaces/automation.js
966
+ var init_automation2 = __esm({
967
+ "node_modules/@speakai/shared/dist/interfaces/automation.js"() {
968
+ "use strict";
969
+ }
970
+ });
971
+
972
+ // node_modules/@speakai/shared/dist/interfaces/webhook.js
973
+ var init_webhook2 = __esm({
974
+ "node_modules/@speakai/shared/dist/interfaces/webhook.js"() {
975
+ "use strict";
976
+ }
977
+ });
978
+
979
+ // node_modules/@speakai/shared/dist/interfaces/field.js
980
+ var init_field = __esm({
981
+ "node_modules/@speakai/shared/dist/interfaces/field.js"() {
982
+ "use strict";
983
+ }
984
+ });
985
+
986
+ // node_modules/@speakai/shared/dist/interfaces/meeting.js
987
+ var init_meeting2 = __esm({
988
+ "node_modules/@speakai/shared/dist/interfaces/meeting.js"() {
989
+ "use strict";
990
+ }
991
+ });
992
+
993
+ // node_modules/@speakai/shared/dist/interfaces/export.js
994
+ var init_export2 = __esm({
995
+ "node_modules/@speakai/shared/dist/interfaces/export.js"() {
996
+ "use strict";
997
+ }
998
+ });
999
+
1000
+ // node_modules/@speakai/shared/dist/interfaces/prompt.js
1001
+ var init_prompt2 = __esm({
1002
+ "node_modules/@speakai/shared/dist/interfaces/prompt.js"() {
1003
+ "use strict";
1004
+ }
1005
+ });
1006
+
1007
+ // node_modules/@speakai/shared/dist/interfaces/user.js
1008
+ var init_user2 = __esm({
1009
+ "node_modules/@speakai/shared/dist/interfaces/user.js"() {
1010
+ "use strict";
1011
+ }
1012
+ });
1013
+
1014
+ // node_modules/@speakai/shared/dist/interfaces/subscription.js
1015
+ var init_subscription2 = __esm({
1016
+ "node_modules/@speakai/shared/dist/interfaces/subscription.js"() {
1017
+ "use strict";
1018
+ }
1019
+ });
1020
+
1021
+ // node_modules/@speakai/shared/dist/interfaces/calendar.js
1022
+ var init_calendar2 = __esm({
1023
+ "node_modules/@speakai/shared/dist/interfaces/calendar.js"() {
1024
+ "use strict";
1025
+ }
1026
+ });
1027
+
1028
+ // node_modules/@speakai/shared/dist/interfaces/category.js
1029
+ var init_category = __esm({
1030
+ "node_modules/@speakai/shared/dist/interfaces/category.js"() {
1031
+ "use strict";
1032
+ }
1033
+ });
1034
+
1035
+ // node_modules/@speakai/shared/dist/interfaces/index.js
1036
+ var init_interfaces = __esm({
1037
+ "node_modules/@speakai/shared/dist/interfaces/index.js"() {
1038
+ "use strict";
1039
+ init_api();
1040
+ init_media2();
1041
+ init_transcript();
1042
+ init_text();
1043
+ init_folder();
1044
+ init_recorder2();
1045
+ init_embed2();
1046
+ init_automation2();
1047
+ init_webhook2();
1048
+ init_field();
1049
+ init_meeting2();
1050
+ init_export2();
1051
+ init_prompt2();
1052
+ init_user2();
1053
+ init_subscription2();
1054
+ init_calendar2();
1055
+ init_category();
1056
+ }
1057
+ });
1058
+
1059
+ // node_modules/@speakai/shared/dist/index.js
1060
+ var init_dist = __esm({
1061
+ "node_modules/@speakai/shared/dist/index.js"() {
1062
+ "use strict";
1063
+ init_enums();
1064
+ init_interfaces();
1065
+ }
1066
+ });
1067
+
172
1068
  // src/tools/media.ts
173
1069
  var media_exports = {};
174
1070
  __export(media_exports, {
@@ -178,7 +1074,7 @@ function register(server, client) {
178
1074
  const api = client ?? speakClient;
179
1075
  server.tool(
180
1076
  "get_signed_upload_url",
181
- "Get a pre-signed S3 URL for direct media file upload. Use this before uploading a file directly to Speak AI storage.",
1077
+ "Get a pre-signed S3 URL for direct file upload to Speak AI storage. After getting the URL, PUT your file to it, then call upload_media with the S3 URL. For a simpler workflow, use upload_local_file instead which handles all steps automatically.",
182
1078
  {
183
1079
  isVideo: import_zod.z.boolean().describe("Set true for video files, false for audio files"),
184
1080
  filename: import_zod.z.string().min(1).describe("Original filename including extension"),
@@ -204,11 +1100,11 @@ function register(server, client) {
204
1100
  );
205
1101
  server.tool(
206
1102
  "upload_media",
207
- "Upload a media file to Speak AI by providing a publicly accessible URL. Speak AI will fetch and process the file asynchronously.",
1103
+ "Upload media from a publicly accessible URL. Processing is asynchronous \u2014 after uploading, use get_media_status to poll until state is 'processed' (typically 1-3 minutes for audio under 60 min), then use get_transcript and get_media_insights to retrieve results. For a single call that handles everything, use upload_and_analyze instead. For local files, use upload_local_file.",
208
1104
  {
209
1105
  name: import_zod.z.string().min(1).describe("Display name for the media file"),
210
1106
  url: import_zod.z.string().describe("Publicly accessible URL of the media file (or pre-signed S3 URL)"),
211
- mediaType: import_zod.z.enum(["audio", "video"]).describe('Type of media: "audio" or "video"'),
1107
+ mediaType: import_zod.z.enum([MediaType.AUDIO, MediaType.VIDEO]).describe('Type of media: "audio" or "video"'),
212
1108
  description: import_zod.z.string().optional().describe("Description of the media file"),
213
1109
  sourceLanguage: import_zod.z.string().optional().describe('BCP-47 language code for transcription, e.g. "en-US" or "he-IL"'),
214
1110
  tags: import_zod.z.string().optional().describe("Comma-separated tags for the media"),
@@ -239,11 +1135,11 @@ function register(server, client) {
239
1135
  );
240
1136
  server.tool(
241
1137
  "list_media",
242
- "List all media files in the workspace with optional filtering, pagination, and sorting.",
1138
+ "List and search media files in the workspace with filtering, pagination, and sorting. Use filterName for text search, mediaType to filter by audio/video/text, folderId for folder-specific results, and from/to for date ranges. Returns mediaIds you can pass to get_transcript, get_media_insights, or ask_magic_prompt. For deep full-text search across transcripts, use search_media instead.",
243
1139
  {
244
- mediaType: import_zod.z.enum(["audio", "video", "text"]).optional().describe('Filter by media type: "audio", "video", or "text"'),
245
- page: import_zod.z.number().int().positive().optional().describe("Page number for pagination (default: 1)"),
246
- pageSize: import_zod.z.number().int().positive().optional().describe("Number of results per page (default: 20)"),
1140
+ mediaType: import_zod.z.enum([MediaType.AUDIO, MediaType.VIDEO, MediaType.TEXT]).optional().describe('Filter by media type: "audio", "video", or "text"'),
1141
+ page: import_zod.z.number().int().min(0).optional().describe("Page number for pagination (0-based, default: 0)"),
1142
+ pageSize: import_zod.z.number().int().min(1).max(500).optional().describe("Number of results per page (default: 20, max: 500)"),
247
1143
  sortBy: import_zod.z.string().optional().describe('Sort field and direction, e.g. "createdAt:desc" or "name:asc"'),
248
1144
  filterMedia: import_zod.z.number().int().optional().describe("Filter: 0=Uploaded, 1=Assigned, 2=Both (default: 2)"),
249
1145
  filterName: import_zod.z.string().optional().describe("Filter media by partial name match"),
@@ -270,7 +1166,7 @@ function register(server, client) {
270
1166
  );
271
1167
  server.tool(
272
1168
  "get_media_insights",
273
- "Retrieve AI-generated insights for a media file, including topics, sentiment, action items, and summaries.",
1169
+ "Retrieve AI-generated insights for a processed media file \u2014 topics, sentiment, keywords, action items, summaries, and more. The media must be in 'processed' state (check with get_media_status first). For asking custom questions about a media file, use ask_magic_prompt instead.",
274
1170
  {
275
1171
  mediaId: import_zod.z.string().min(1).describe("Unique identifier of the media file")
276
1172
  },
@@ -292,7 +1188,7 @@ function register(server, client) {
292
1188
  );
293
1189
  server.tool(
294
1190
  "get_transcript",
295
- "Retrieve the full transcript for a media file, including speaker labels and timestamps.",
1191
+ "Retrieve the full transcript for a processed media file with speaker labels and timestamps. The media must be in 'processed' state. Use update_transcript_speakers to rename speaker labels after reviewing. For subtitle-formatted output, use get_captions instead.",
296
1192
  {
297
1193
  mediaId: import_zod.z.string().min(1).describe("Unique identifier of the media file")
298
1194
  },
@@ -328,7 +1224,7 @@ function register(server, client) {
328
1224
  try {
329
1225
  const result = await api.put(
330
1226
  `/v1/media/speakers/${mediaId}`,
331
- speakers
1227
+ { speakers }
332
1228
  );
333
1229
  return {
334
1230
  content: [
@@ -345,7 +1241,7 @@ function register(server, client) {
345
1241
  );
346
1242
  server.tool(
347
1243
  "get_media_status",
348
- "Check the processing status of a media file (e.g. pending, transcribing, completed, failed).",
1244
+ "Check the processing status of a media file. States: pending \u2192 transcribing \u2192 analyzing \u2192 processed (or failed). Poll this after upload_media until state is 'processed', then use get_transcript and get_media_insights to retrieve results.",
349
1245
  {
350
1246
  mediaId: import_zod.z.string().min(1).describe("Unique identifier of the media file")
351
1247
  },
@@ -416,13 +1312,120 @@ function register(server, client) {
416
1312
  }
417
1313
  }
418
1314
  );
1315
+ server.tool(
1316
+ "get_captions",
1317
+ "Get captions for a media file. Captions are separate from full transcripts and are formatted for display/subtitles.",
1318
+ {
1319
+ mediaId: import_zod.z.string().min(1).describe("Unique identifier of the media file")
1320
+ },
1321
+ async ({ mediaId }) => {
1322
+ try {
1323
+ const result = await api.get(`/v1/media/caption/${mediaId}`);
1324
+ return {
1325
+ content: [
1326
+ { type: "text", text: JSON.stringify(result.data, null, 2) }
1327
+ ]
1328
+ };
1329
+ } catch (err) {
1330
+ return {
1331
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
1332
+ isError: true
1333
+ };
1334
+ }
1335
+ }
1336
+ );
1337
+ server.tool(
1338
+ "list_supported_languages",
1339
+ "List all languages supported for transcription. Use the language codes when uploading media with a specific sourceLanguage.",
1340
+ {},
1341
+ async () => {
1342
+ try {
1343
+ const result = await api.get("/v1/media/supportedLanguages");
1344
+ return {
1345
+ content: [
1346
+ { type: "text", text: JSON.stringify(result.data, null, 2) }
1347
+ ]
1348
+ };
1349
+ } catch (err) {
1350
+ return {
1351
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
1352
+ isError: true
1353
+ };
1354
+ }
1355
+ }
1356
+ );
1357
+ server.tool(
1358
+ "get_media_statistics",
1359
+ "Get workspace-level media statistics \u2014 total counts, processing status breakdown, storage usage, etc.",
1360
+ {},
1361
+ async () => {
1362
+ try {
1363
+ const result = await api.get("/v1/media/statistics");
1364
+ return {
1365
+ content: [
1366
+ { type: "text", text: JSON.stringify(result.data, null, 2) }
1367
+ ]
1368
+ };
1369
+ } catch (err) {
1370
+ return {
1371
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
1372
+ isError: true
1373
+ };
1374
+ }
1375
+ }
1376
+ );
1377
+ server.tool(
1378
+ "toggle_media_favorite",
1379
+ "Mark or unmark a media file as a favorite for quick access.",
1380
+ {
1381
+ mediaId: import_zod.z.string().min(1).describe("Unique identifier of the media file")
1382
+ },
1383
+ async (body) => {
1384
+ try {
1385
+ const result = await api.post("/v1/media/favorites", body);
1386
+ return {
1387
+ content: [
1388
+ { type: "text", text: JSON.stringify(result.data, null, 2) }
1389
+ ]
1390
+ };
1391
+ } catch (err) {
1392
+ return {
1393
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
1394
+ isError: true
1395
+ };
1396
+ }
1397
+ }
1398
+ );
1399
+ server.tool(
1400
+ "reanalyze_media",
1401
+ "Re-run AI analysis on a media file using the latest models. Use this after Speak AI has updated its analysis capabilities or if the original analysis was incomplete.",
1402
+ {
1403
+ mediaId: import_zod.z.string().min(1).describe("Unique identifier of the media file to re-analyze")
1404
+ },
1405
+ async ({ mediaId }) => {
1406
+ try {
1407
+ const result = await api.post(`/v1/media/reanalyze/${mediaId}`, {});
1408
+ return {
1409
+ content: [
1410
+ { type: "text", text: JSON.stringify(result.data, null, 2) }
1411
+ ]
1412
+ };
1413
+ } catch (err) {
1414
+ return {
1415
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
1416
+ isError: true
1417
+ };
1418
+ }
1419
+ }
1420
+ );
419
1421
  }
420
1422
  var import_zod;
421
- var init_media = __esm({
1423
+ var init_media3 = __esm({
422
1424
  "src/tools/media.ts"() {
423
1425
  "use strict";
424
1426
  import_zod = require("zod");
425
1427
  init_client();
1428
+ init_dist();
426
1429
  }
427
1430
  });
428
1431
 
@@ -542,7 +1545,7 @@ function register2(server, client) {
542
1545
  );
543
1546
  }
544
1547
  var import_zod2;
545
- var init_text = __esm({
1548
+ var init_text2 = __esm({
546
1549
  "src/tools/text.ts"() {
547
1550
  "use strict";
548
1551
  import_zod2 = require("zod");
@@ -763,8 +1766,8 @@ function register4(server, client) {
763
1766
  "list_folders",
764
1767
  "List all folders in the workspace with pagination and sorting.",
765
1768
  {
766
- page: import_zod4.z.number().int().optional().describe("Page number (0-based)"),
767
- pageSize: import_zod4.z.number().int().optional().describe("Results per page"),
1769
+ page: import_zod4.z.number().int().min(0).optional().describe("Page number (0-based, default: 0)"),
1770
+ pageSize: import_zod4.z.number().int().min(1).max(500).optional().describe("Results per page (default: 20, max: 500)"),
768
1771
  sortBy: import_zod4.z.string().optional().describe('Sort field and direction, e.g. "createdAt:desc"')
769
1772
  },
770
1773
  async (params) => {
@@ -958,8 +1961,8 @@ function register5(server, client) {
958
1961
  "list_recorders",
959
1962
  "List all recorders/surveys in the workspace.",
960
1963
  {
961
- page: import_zod5.z.number().int().optional().describe("Page number (0-based)"),
962
- pageSize: import_zod5.z.number().int().optional().describe("Results per page"),
1964
+ page: import_zod5.z.number().int().min(0).optional().describe("Page number (0-based, default: 0)"),
1965
+ pageSize: import_zod5.z.number().int().min(1).max(500).optional().describe("Results per page (default: 20, max: 500)"),
963
1966
  sortBy: import_zod5.z.string().optional().describe('Sort field, e.g. "createdAt:desc"')
964
1967
  },
965
1968
  async (params) => {
@@ -1120,7 +2123,7 @@ function register5(server, client) {
1120
2123
  );
1121
2124
  }
1122
2125
  var import_zod5;
1123
- var init_recorder = __esm({
2126
+ var init_recorder3 = __esm({
1124
2127
  "src/tools/recorder.ts"() {
1125
2128
  "use strict";
1126
2129
  import_zod5 = require("zod");
@@ -1221,7 +2224,7 @@ function register6(server, client) {
1221
2224
  );
1222
2225
  }
1223
2226
  var import_zod6;
1224
- var init_embed = __esm({
2227
+ var init_embed3 = __esm({
1225
2228
  "src/tools/embed.ts"() {
1226
2229
  "use strict";
1227
2230
  import_zod6 = require("zod");
@@ -1237,12 +2240,243 @@ __export(prompt_exports, {
1237
2240
  function register7(server, client) {
1238
2241
  const api = client ?? speakClient;
1239
2242
  server.tool(
1240
- "list_prompts",
1241
- "List all available Magic Prompt templates for AI-powered questions about your media.",
1242
- {},
1243
- async () => {
2243
+ "ask_magic_prompt",
2244
+ [
2245
+ "Ask an AI-powered question about your media using Speak AI's Magic Prompt.",
2246
+ "Supports querying a single file, multiple files, entire folders, or your whole workspace.",
2247
+ "Pass mediaIds for specific files, folderIds for entire folders, or omit both to search across all media.",
2248
+ "Use assistantType to get specialized responses (e.g., 'researcher' for academic analysis, 'sales' for deal insights).",
2249
+ "To continue a conversation, pass the promptId from a previous response.",
2250
+ "Returns a promptId \u2014 save it to continue the conversation with follow-up questions."
2251
+ ].join(" "),
2252
+ {
2253
+ prompt: import_zod7.z.string().min(1).describe("The question or prompt to ask about the media"),
2254
+ mediaIds: import_zod7.z.array(import_zod7.z.string()).optional().describe("Array of media IDs to query. Omit along with folderIds to search across all media in your workspace."),
2255
+ folderIds: import_zod7.z.array(import_zod7.z.string()).optional().describe("Array of folder IDs to scope the query to. Omit along with mediaIds to search across all media."),
2256
+ folderId: import_zod7.z.string().optional().describe("Single folder ID to scope the query to. Use folderIds for multiple folders."),
2257
+ assistantType: import_zod7.z.enum(Object.values(AssistantType)).optional().describe("Assistant persona: 'general' (default), 'researcher' (academic), 'marketer' (content), 'sales' (deals), 'recruiter' (hiring). Use 'custom' with assistantTemplateId."),
2258
+ assistantTemplateId: import_zod7.z.string().optional().describe("Required when assistantType is 'custom'. ID of a custom assistant template from list_prompts."),
2259
+ promptId: import_zod7.z.string().optional().describe("ID of an existing conversation to continue. Pass this to maintain chat context across multiple questions."),
2260
+ speakers: import_zod7.z.array(import_zod7.z.string()).optional().describe("Filter to specific speaker IDs from the transcript"),
2261
+ tags: import_zod7.z.array(import_zod7.z.string()).optional().describe("Filter media by tags"),
2262
+ startDate: import_zod7.z.string().optional().describe("Start date for date range filter (ISO 8601, e.g., '2025-01-01')"),
2263
+ endDate: import_zod7.z.string().optional().describe("End date for date range filter (ISO 8601, e.g., '2025-03-31')"),
2264
+ isIndividualPrompt: import_zod7.z.boolean().optional().describe("When true, processes each media file separately instead of combining context. Useful for comparing responses across files.")
2265
+ },
2266
+ async (params) => {
2267
+ try {
2268
+ const result = await api.post("/v1/prompt", params);
2269
+ return {
2270
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
2271
+ };
2272
+ } catch (err) {
2273
+ return {
2274
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
2275
+ isError: true
2276
+ };
2277
+ }
2278
+ }
2279
+ );
2280
+ server.tool(
2281
+ "retry_magic_prompt",
2282
+ "Retry a failed or incomplete Magic Prompt response. Use when a previous ask_magic_prompt call returned an error or incomplete answer.",
2283
+ {
2284
+ promptId: import_zod7.z.string().min(1).describe("ID of the conversation containing the failed message"),
2285
+ messageId: import_zod7.z.string().min(1).describe("ID of the specific message to retry")
2286
+ },
2287
+ async (body) => {
2288
+ try {
2289
+ const result = await api.post("/v1/prompt/retry", body);
2290
+ return {
2291
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
2292
+ };
2293
+ } catch (err) {
2294
+ return {
2295
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
2296
+ isError: true
2297
+ };
2298
+ }
2299
+ }
2300
+ );
2301
+ server.tool(
2302
+ "get_chat_history",
2303
+ "Get a list of recent Magic Prompt conversations. Returns conversation summaries with promptIds that can be used to continue conversations via ask_magic_prompt or retrieve full messages via get_chat_messages.",
2304
+ {
2305
+ limit: import_zod7.z.number().int().positive().optional().describe("Number of recent conversations to return (default: 10)")
2306
+ },
2307
+ async ({ limit }) => {
2308
+ try {
2309
+ const result = await api.get("/v1/prompt/history", {
2310
+ params: limit ? { limit } : void 0
2311
+ });
2312
+ return {
2313
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
2314
+ };
2315
+ } catch (err) {
2316
+ return {
2317
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
2318
+ isError: true
2319
+ };
2320
+ }
2321
+ }
2322
+ );
2323
+ server.tool(
2324
+ "get_chat_messages",
2325
+ "Get full message history for conversations. Can filter by promptId for a specific conversation, by media/folder, or search across all chat messages. Returns questions, answers, references, and metadata.",
2326
+ {
2327
+ promptId: import_zod7.z.string().optional().describe("Filter to a specific conversation by its ID"),
2328
+ folderId: import_zod7.z.string().optional().describe("Filter messages by folder ID"),
2329
+ mediaIds: import_zod7.z.string().optional().describe("Filter by media IDs (comma-separated)"),
2330
+ query: import_zod7.z.string().optional().describe("Search text in prompts and answers"),
2331
+ page: import_zod7.z.number().int().min(0).optional().describe("Page number for pagination (0-based, default: 0)"),
2332
+ pageSize: import_zod7.z.number().int().min(1).max(500).optional().describe("Results per page (default: 25, max: 500)")
2333
+ },
2334
+ async (params) => {
2335
+ try {
2336
+ const result = await api.get("/v1/prompt/messages", { params });
2337
+ return {
2338
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
2339
+ };
2340
+ } catch (err) {
2341
+ return {
2342
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
2343
+ isError: true
2344
+ };
2345
+ }
2346
+ }
2347
+ );
2348
+ server.tool(
2349
+ "delete_chat_message",
2350
+ "Delete a specific chat message from conversation history.",
2351
+ {
2352
+ promptId: import_zod7.z.string().min(1).describe("ID of the message to delete")
2353
+ },
2354
+ async ({ promptId }) => {
2355
+ try {
2356
+ const result = await api.delete(`/v1/prompt/message/${promptId}`);
2357
+ return {
2358
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
2359
+ };
2360
+ } catch (err) {
2361
+ return {
2362
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
2363
+ isError: true
2364
+ };
2365
+ }
2366
+ }
2367
+ );
2368
+ server.tool(
2369
+ "list_prompts",
2370
+ "List all available Magic Prompt templates. Use template IDs with ask_magic_prompt's assistantTemplateId parameter when using assistantType 'custom'.",
2371
+ {},
2372
+ async () => {
2373
+ try {
2374
+ const result = await api.get("/v1/prompt");
2375
+ return {
2376
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
2377
+ };
2378
+ } catch (err) {
2379
+ return {
2380
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
2381
+ isError: true
2382
+ };
2383
+ }
2384
+ }
2385
+ );
2386
+ server.tool(
2387
+ "get_favorite_prompts",
2388
+ "Get all prompts and answers that have been marked as favorites. Useful for finding saved insights and important AI-generated analysis.",
2389
+ {},
2390
+ async () => {
2391
+ try {
2392
+ const result = await api.get("/v1/prompt/favorites");
2393
+ return {
2394
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
2395
+ };
2396
+ } catch (err) {
2397
+ return {
2398
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
2399
+ isError: true
2400
+ };
2401
+ }
2402
+ }
2403
+ );
2404
+ server.tool(
2405
+ "toggle_prompt_favorite",
2406
+ "Mark or unmark a chat message as a favorite for easy retrieval later.",
2407
+ {
2408
+ promptId: import_zod7.z.string().min(1).describe("ID of the conversation"),
2409
+ messageId: import_zod7.z.string().min(1).describe("ID of the specific message to favorite/unfavorite"),
2410
+ isFavorite: import_zod7.z.boolean().describe("true to mark as favorite, false to remove")
2411
+ },
2412
+ async (body) => {
2413
+ try {
2414
+ const result = await api.post("/v1/prompt/favorites", body);
2415
+ return {
2416
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
2417
+ };
2418
+ } catch (err) {
2419
+ return {
2420
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
2421
+ isError: true
2422
+ };
2423
+ }
2424
+ }
2425
+ );
2426
+ server.tool(
2427
+ "update_chat_title",
2428
+ "Update the title of a chat conversation for easier identification in history.",
2429
+ {
2430
+ promptId: import_zod7.z.string().min(1).describe("ID of the conversation to rename"),
2431
+ title: import_zod7.z.string().min(1).describe("New title for the conversation")
2432
+ },
2433
+ async ({ promptId, title }) => {
2434
+ try {
2435
+ const result = await api.put(`/v1/prompt/${promptId}`, { title });
2436
+ return {
2437
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
2438
+ };
2439
+ } catch (err) {
2440
+ return {
2441
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
2442
+ isError: true
2443
+ };
2444
+ }
2445
+ }
2446
+ );
2447
+ server.tool(
2448
+ "submit_chat_feedback",
2449
+ "Submit feedback on a chat response (thumbs up/down). Helps improve AI answer quality.",
2450
+ {
2451
+ promptId: import_zod7.z.string().min(1).describe("ID of the conversation"),
2452
+ messageId: import_zod7.z.string().min(1).describe("ID of the message to rate"),
2453
+ score: import_zod7.z.number().describe("Feedback score: 1 for thumbs up, -1 for thumbs down"),
2454
+ reason: import_zod7.z.string().optional().describe("Optional explanation for the feedback")
2455
+ },
2456
+ async (body) => {
2457
+ try {
2458
+ const result = await api.post("/v1/prompt/feedback", body);
2459
+ return {
2460
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
2461
+ };
2462
+ } catch (err) {
2463
+ return {
2464
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
2465
+ isError: true
2466
+ };
2467
+ }
2468
+ }
2469
+ );
2470
+ server.tool(
2471
+ "get_chat_statistics",
2472
+ "Get usage statistics for Magic Prompt / chat. Returns metrics on prompt usage, optionally filtered by date range.",
2473
+ {
2474
+ startDate: import_zod7.z.string().optional().describe("Start date for stats (ISO 8601)"),
2475
+ endDate: import_zod7.z.string().optional().describe("End date for stats (ISO 8601)")
2476
+ },
2477
+ async (params) => {
1244
2478
  try {
1245
- const result = await api.get("/v1/prompt");
2479
+ const result = await api.get("/v1/prompt/statistics", { params });
1246
2480
  return {
1247
2481
  content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
1248
2482
  };
@@ -1255,16 +2489,14 @@ function register7(server, client) {
1255
2489
  }
1256
2490
  );
1257
2491
  server.tool(
1258
- "ask_magic_prompt",
1259
- "Ask an AI-powered question about a specific media file using Speak AI's Magic Prompt.",
2492
+ "export_chat_answer",
2493
+ "Export a Magic Prompt conversation or answer. Useful for saving AI-generated summaries, reports, or analysis results.",
1260
2494
  {
1261
- mediaId: import_zod7.z.string().min(1).describe("Unique identifier of the media file to query"),
1262
- prompt: import_zod7.z.string().min(1).describe("The question or prompt to ask about the media"),
1263
- promptId: import_zod7.z.string().optional().describe("ID of a predefined prompt template to use")
2495
+ promptId: import_zod7.z.string().min(1).describe("ID of the conversation to export")
1264
2496
  },
1265
2497
  async (body) => {
1266
2498
  try {
1267
- const result = await api.post("/v1/prompt", body);
2499
+ const result = await api.post("/v1/prompt/export", body);
1268
2500
  return {
1269
2501
  content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
1270
2502
  };
@@ -1278,11 +2510,12 @@ function register7(server, client) {
1278
2510
  );
1279
2511
  }
1280
2512
  var import_zod7;
1281
- var init_prompt = __esm({
2513
+ var init_prompt3 = __esm({
1282
2514
  "src/tools/prompt.ts"() {
1283
2515
  "use strict";
1284
2516
  import_zod7 = require("zod");
1285
2517
  init_client();
2518
+ init_dist();
1286
2519
  }
1287
2520
  });
1288
2521
 
@@ -1299,8 +2532,8 @@ function register8(server, client) {
1299
2532
  {
1300
2533
  platformType: import_zod8.z.string().optional().describe("Filter by platform (e.g. zoom, teams, meet)"),
1301
2534
  meetingStatus: import_zod8.z.string().optional().describe("Filter by status (e.g. scheduled, completed, cancelled)"),
1302
- page: import_zod8.z.number().int().optional().describe("Page number (0-based)"),
1303
- pageSize: import_zod8.z.number().int().optional().describe("Results per page")
2535
+ page: import_zod8.z.number().int().min(0).optional().describe("Page number (0-based, default: 0)"),
2536
+ pageSize: import_zod8.z.number().int().min(1).max(500).optional().describe("Results per page (default: 20, max: 500)")
1304
2537
  },
1305
2538
  async (params) => {
1306
2539
  try {
@@ -1392,7 +2625,7 @@ function register8(server, client) {
1392
2625
  );
1393
2626
  }
1394
2627
  var import_zod8;
1395
- var init_meeting = __esm({
2628
+ var init_meeting3 = __esm({
1396
2629
  "src/tools/meeting.ts"() {
1397
2630
  "use strict";
1398
2631
  import_zod8 = require("zod");
@@ -1492,7 +2725,7 @@ function register9(server, client) {
1492
2725
  );
1493
2726
  }
1494
2727
  var import_zod9;
1495
- var init_fields = __esm({
2728
+ var init_fields2 = __esm({
1496
2729
  "src/tools/fields.ts"() {
1497
2730
  "use strict";
1498
2731
  import_zod9 = require("zod");
@@ -1727,6 +2960,400 @@ var init_webhooks = __esm({
1727
2960
  }
1728
2961
  });
1729
2962
 
2963
+ // src/tools/analytics.ts
2964
+ var analytics_exports = {};
2965
+ __export(analytics_exports, {
2966
+ register: () => register12
2967
+ });
2968
+ function register12(server, client) {
2969
+ const api = client ?? speakClient;
2970
+ server.tool(
2971
+ "search_media",
2972
+ [
2973
+ "Deep search across all media transcripts, insights, and metadata.",
2974
+ "Returns matching media with sentiment data, tags, and content excerpts.",
2975
+ "Use this to find specific topics, keywords, or themes across your entire library.",
2976
+ "For filtering by media type, folder, tags, or speakers, use the filterList parameter.",
2977
+ "Results are scoped by date range \u2014 defaults to current month if not specified."
2978
+ ].join(" "),
2979
+ {
2980
+ query: import_zod12.z.string().min(1).describe("Search query \u2014 searches across transcripts, insights, and metadata"),
2981
+ startDate: import_zod12.z.string().optional().describe("Start date for search range (ISO 8601). Defaults to start of current month."),
2982
+ endDate: import_zod12.z.string().optional().describe("End date for search range (ISO 8601). Defaults to now."),
2983
+ filterList: import_zod12.z.array(
2984
+ import_zod12.z.object({
2985
+ fieldName: import_zod12.z.enum(Object.values(FilterFieldName)).describe("Field to filter on"),
2986
+ fieldOperator: import_zod12.z.enum(Object.values(FilterOperator)).describe("Filter operator"),
2987
+ fieldValue: import_zod12.z.array(import_zod12.z.string()).describe("Values to filter by"),
2988
+ fieldCondition: import_zod12.z.enum(Object.values(FilterCondition)).describe("Condition linking multiple filters")
2989
+ })
2990
+ ).optional().describe("Advanced filters for narrowing search results by tags, speakers, media type, sentiment, folder, etc.")
2991
+ },
2992
+ async (params) => {
2993
+ try {
2994
+ const result = await api.post("/v1/analytics/search", params);
2995
+ return {
2996
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
2997
+ };
2998
+ } catch (err) {
2999
+ return {
3000
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
3001
+ isError: true
3002
+ };
3003
+ }
3004
+ }
3005
+ );
3006
+ }
3007
+ var import_zod12;
3008
+ var init_analytics = __esm({
3009
+ "src/tools/analytics.ts"() {
3010
+ "use strict";
3011
+ import_zod12 = require("zod");
3012
+ init_client();
3013
+ init_dist();
3014
+ }
3015
+ });
3016
+
3017
+ // src/tools/clips.ts
3018
+ var clips_exports = {};
3019
+ __export(clips_exports, {
3020
+ register: () => register13
3021
+ });
3022
+ function register13(server, client) {
3023
+ const api = client ?? speakClient;
3024
+ server.tool(
3025
+ "create_clip",
3026
+ [
3027
+ "Create a highlight clip from one or more media files by specifying time ranges.",
3028
+ `Clips are processed asynchronously (states: ${Object.values(ClipState).join(", ")}) \u2014 use get_clips to check status.`,
3029
+ "Maximum total clip duration is 30 minutes.",
3030
+ "Use multiple timeRanges to stitch segments from different media files together."
3031
+ ].join(" "),
3032
+ {
3033
+ title: import_zod13.z.string().min(1).describe("Title for the clip"),
3034
+ mediaType: import_zod13.z.enum([MediaType.AUDIO, MediaType.VIDEO]).describe("Output media type"),
3035
+ timeRanges: import_zod13.z.array(
3036
+ import_zod13.z.object({
3037
+ mediaId: import_zod13.z.string().min(1).describe("Source media file ID"),
3038
+ startTime: import_zod13.z.number().min(0).describe("Start time in seconds"),
3039
+ endTime: import_zod13.z.number().min(0).describe("End time in seconds (must be > startTime)")
3040
+ })
3041
+ ).min(1).describe("Array of time ranges to include in the clip. Each specifies a source media and start/end times."),
3042
+ description: import_zod13.z.string().optional().describe("Description of the clip"),
3043
+ tags: import_zod13.z.array(import_zod13.z.string()).optional().describe("Tags for the clip"),
3044
+ mergeStrategy: import_zod13.z.enum(["CONCATENATE"]).optional().describe("How to merge multiple segments (default: CONCATENATE)")
3045
+ },
3046
+ async (body) => {
3047
+ try {
3048
+ const result = await api.post("/v1/clips", body);
3049
+ return {
3050
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
3051
+ };
3052
+ } catch (err) {
3053
+ return {
3054
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
3055
+ isError: true
3056
+ };
3057
+ }
3058
+ }
3059
+ );
3060
+ server.tool(
3061
+ "get_clips",
3062
+ "List clips, optionally filtered by folder or media files. If clipId is provided, returns a single clip with its download URL (when processed).",
3063
+ {
3064
+ clipId: import_zod13.z.string().optional().describe("Get a specific clip by ID"),
3065
+ folderId: import_zod13.z.string().optional().describe("Filter clips by folder ID"),
3066
+ mediaIds: import_zod13.z.array(import_zod13.z.string()).optional().describe("Filter clips by source media file IDs")
3067
+ },
3068
+ async ({ clipId, ...params }) => {
3069
+ try {
3070
+ const url = clipId ? `/v1/clips/${clipId}` : "/v1/clips";
3071
+ const result = await api.get(url, { params });
3072
+ return {
3073
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
3074
+ };
3075
+ } catch (err) {
3076
+ return {
3077
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
3078
+ isError: true
3079
+ };
3080
+ }
3081
+ }
3082
+ );
3083
+ server.tool(
3084
+ "update_clip",
3085
+ "Update a clip's title, description, or tags.",
3086
+ {
3087
+ clipId: import_zod13.z.string().min(1).describe("ID of the clip to update"),
3088
+ title: import_zod13.z.string().optional().describe("New title"),
3089
+ description: import_zod13.z.string().optional().describe("New description"),
3090
+ tags: import_zod13.z.array(import_zod13.z.string()).optional().describe("New tags")
3091
+ },
3092
+ async ({ clipId, ...body }) => {
3093
+ try {
3094
+ const result = await api.put(`/v1/clips/${clipId}`, body);
3095
+ return {
3096
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
3097
+ };
3098
+ } catch (err) {
3099
+ return {
3100
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
3101
+ isError: true
3102
+ };
3103
+ }
3104
+ }
3105
+ );
3106
+ server.tool(
3107
+ "delete_clip",
3108
+ "Permanently delete a clip and its associated media file.",
3109
+ {
3110
+ clipId: import_zod13.z.string().min(1).describe("ID of the clip to delete")
3111
+ },
3112
+ async ({ clipId }) => {
3113
+ try {
3114
+ const result = await api.delete(`/v1/clips/${clipId}`);
3115
+ return {
3116
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
3117
+ };
3118
+ } catch (err) {
3119
+ return {
3120
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
3121
+ isError: true
3122
+ };
3123
+ }
3124
+ }
3125
+ );
3126
+ }
3127
+ var import_zod13;
3128
+ var init_clips = __esm({
3129
+ "src/tools/clips.ts"() {
3130
+ "use strict";
3131
+ import_zod13 = require("zod");
3132
+ init_client();
3133
+ init_dist();
3134
+ }
3135
+ });
3136
+
3137
+ // src/media-utils.ts
3138
+ function isVideoFile(filePath) {
3139
+ return VIDEO_EXTENSIONS.includes(path.extname(filePath).toLowerCase());
3140
+ }
3141
+ function getMimeType(filePath) {
3142
+ const ext = path.extname(filePath).toLowerCase();
3143
+ const isVideo = isVideoFile(filePath);
3144
+ if (ext === ".mp4") return isVideo ? "video/mp4" : "audio/mp4";
3145
+ if (ext === ".webm") return isVideo ? "video/webm" : "audio/webm";
3146
+ return MIME_TYPES[ext] ?? (isVideo ? "video/mp4" : "audio/mpeg");
3147
+ }
3148
+ function detectMediaType(filePath) {
3149
+ return isVideoFile(filePath) ? "video" : "audio";
3150
+ }
3151
+ var path, VIDEO_EXTENSIONS, MIME_TYPES;
3152
+ var init_media_utils = __esm({
3153
+ "src/media-utils.ts"() {
3154
+ "use strict";
3155
+ path = __toESM(require("path"));
3156
+ VIDEO_EXTENSIONS = [".mp4", ".mov", ".avi", ".mkv", ".webm", ".wmv"];
3157
+ MIME_TYPES = {
3158
+ ".mp3": "audio/mpeg",
3159
+ ".m4a": "audio/mp4",
3160
+ ".wav": "audio/wav",
3161
+ ".ogg": "audio/ogg",
3162
+ ".flac": "audio/flac",
3163
+ ".mov": "video/quicktime",
3164
+ ".avi": "video/x-msvideo",
3165
+ ".mkv": "video/x-matroska",
3166
+ ".wmv": "video/x-ms-wmv"
3167
+ };
3168
+ }
3169
+ });
3170
+
3171
+ // src/tools/workflows.ts
3172
+ var workflows_exports = {};
3173
+ __export(workflows_exports, {
3174
+ register: () => register14
3175
+ });
3176
+ function register14(server, client) {
3177
+ const api = client ?? speakClient;
3178
+ server.tool(
3179
+ "upload_and_analyze",
3180
+ [
3181
+ "Upload media from a URL, wait for processing to complete, then return the transcript and AI insights \u2014 all in one call.",
3182
+ "This is a convenience tool that combines upload_media + polling get_media_status + get_transcript + get_media_insights.",
3183
+ "Processing typically takes 1-3 minutes for audio under 60 minutes.",
3184
+ "Use this when you want the full analysis result without managing the polling loop yourself."
3185
+ ].join(" "),
3186
+ {
3187
+ url: import_zod14.z.string().describe("Publicly accessible URL of the media file"),
3188
+ name: import_zod14.z.string().optional().describe("Display name for the media (defaults to filename from URL)"),
3189
+ mediaType: import_zod14.z.enum([MediaType.AUDIO, MediaType.VIDEO]).optional().describe("Media type (default: audio)"),
3190
+ sourceLanguage: import_zod14.z.string().optional().describe("BCP-47 language code (e.g., 'en-US', 'he-IL')"),
3191
+ folderId: import_zod14.z.string().optional().describe("Folder ID to place the media in"),
3192
+ tags: import_zod14.z.string().optional().describe("Comma-separated tags")
3193
+ },
3194
+ async (params) => {
3195
+ try {
3196
+ const uploadBody = {
3197
+ name: params.name ?? params.url.split("/").pop()?.split("?")[0] ?? "Upload",
3198
+ url: params.url,
3199
+ mediaType: params.mediaType ?? "audio"
3200
+ };
3201
+ if (params.sourceLanguage) uploadBody.sourceLanguage = params.sourceLanguage;
3202
+ if (params.folderId) uploadBody.folderId = params.folderId;
3203
+ if (params.tags) uploadBody.tags = params.tags;
3204
+ const uploadRes = await api.post("/v1/media/upload", uploadBody);
3205
+ const mediaId = uploadRes.data?.data?.mediaId;
3206
+ if (!mediaId) {
3207
+ return {
3208
+ content: [{ type: "text", text: `Error: Upload succeeded but no mediaId returned.
3209
+ ${JSON.stringify(uploadRes.data, null, 2)}` }],
3210
+ isError: true
3211
+ };
3212
+ }
3213
+ let state = uploadRes.data?.data?.state;
3214
+ let attempts = 0;
3215
+ while (state !== MediaState.PROCESSED && state !== MediaState.FAILED && attempts < MAX_POLL_ATTEMPTS) {
3216
+ await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));
3217
+ const statusRes = await api.get(`/v1/media/status/${mediaId}`);
3218
+ state = statusRes.data?.data?.state;
3219
+ attempts++;
3220
+ }
3221
+ if (state === MediaState.FAILED) {
3222
+ return {
3223
+ content: [{ type: "text", text: `Error: Processing failed for media ${mediaId}` }],
3224
+ isError: true
3225
+ };
3226
+ }
3227
+ if (state !== MediaState.PROCESSED) {
3228
+ return {
3229
+ content: [{ type: "text", text: `Timeout: Media ${mediaId} is still processing (state: ${state}). Use get_media_status to check later.` }],
3230
+ isError: true
3231
+ };
3232
+ }
3233
+ const [transcriptRes, insightsRes] = await Promise.all([
3234
+ api.get(`/v1/media/transcript/${mediaId}`),
3235
+ api.get(`/v1/media/insight/${mediaId}`)
3236
+ ]);
3237
+ const result = {
3238
+ mediaId,
3239
+ state: "processed",
3240
+ transcript: transcriptRes.data?.data,
3241
+ insights: insightsRes.data?.data
3242
+ };
3243
+ return {
3244
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
3245
+ };
3246
+ } catch (err) {
3247
+ return {
3248
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
3249
+ isError: true
3250
+ };
3251
+ }
3252
+ }
3253
+ );
3254
+ server.tool(
3255
+ "upload_local_file",
3256
+ [
3257
+ "Upload a local file to Speak AI for transcription and analysis.",
3258
+ "Reads the file from disk, gets a pre-signed S3 URL, uploads the file, then creates the media entry.",
3259
+ "Works with any audio or video file on the local filesystem.",
3260
+ "After upload, use get_media_status to poll for completion, then get_transcript and get_media_insights."
3261
+ ].join(" "),
3262
+ {
3263
+ filePath: import_zod14.z.string().describe("Absolute path to the local audio or video file"),
3264
+ name: import_zod14.z.string().optional().describe("Display name (defaults to filename)"),
3265
+ mediaType: import_zod14.z.enum([MediaType.AUDIO, MediaType.VIDEO]).optional().describe("Media type (auto-detected from extension if omitted)"),
3266
+ sourceLanguage: import_zod14.z.string().optional().describe("BCP-47 language code (e.g., 'en-US')"),
3267
+ folderId: import_zod14.z.string().optional().describe("Folder ID to place the media in"),
3268
+ tags: import_zod14.z.string().optional().describe("Comma-separated tags")
3269
+ },
3270
+ async (params) => {
3271
+ try {
3272
+ const filePath = params.filePath;
3273
+ if (!fs.existsSync(filePath)) {
3274
+ return {
3275
+ content: [{ type: "text", text: `Error: File not found: ${filePath}` }],
3276
+ isError: true
3277
+ };
3278
+ }
3279
+ const filename = path2.basename(filePath);
3280
+ const isVideo = isVideoFile(filePath);
3281
+ const mediaType = params.mediaType ?? detectMediaType(filePath);
3282
+ const mimeType = getMimeType(filePath);
3283
+ const signedRes = await api.get("/v1/media/upload/signedurl", {
3284
+ params: { isVideo, filename, mimeType }
3285
+ });
3286
+ const signedData = signedRes.data?.data;
3287
+ const uploadUrl = signedData?.signedUrl ?? signedData?.url;
3288
+ const s3Key = signedData?.key ?? signedData?.s3Key;
3289
+ if (!uploadUrl) {
3290
+ return {
3291
+ content: [{ type: "text", text: `Error: Could not get signed upload URL.
3292
+ ${JSON.stringify(signedRes.data, null, 2)}` }],
3293
+ isError: true
3294
+ };
3295
+ }
3296
+ const fileBuffer = fs.readFileSync(filePath);
3297
+ const axios2 = (await import("axios")).default;
3298
+ await axios2.put(uploadUrl, fileBuffer, {
3299
+ headers: {
3300
+ "Content-Type": mimeType
3301
+ },
3302
+ maxBodyLength: Infinity,
3303
+ maxContentLength: Infinity
3304
+ });
3305
+ const createBody = {
3306
+ name: params.name ?? filename,
3307
+ url: uploadUrl.split("?")[0],
3308
+ // S3 URL without query params
3309
+ mediaType
3310
+ };
3311
+ if (s3Key) createBody.s3Key = s3Key;
3312
+ if (params.sourceLanguage) createBody.sourceLanguage = params.sourceLanguage;
3313
+ if (params.folderId) createBody.folderId = params.folderId;
3314
+ if (params.tags) createBody.tags = params.tags;
3315
+ const createRes = await api.post("/v1/media/upload", createBody);
3316
+ const data = createRes.data?.data;
3317
+ return {
3318
+ content: [
3319
+ {
3320
+ type: "text",
3321
+ text: JSON.stringify(
3322
+ {
3323
+ mediaId: data?.mediaId,
3324
+ state: data?.state,
3325
+ message: `File uploaded successfully. Use get_media_status to poll until state is 'processed', then use get_transcript and get_media_insights.`
3326
+ },
3327
+ null,
3328
+ 2
3329
+ )
3330
+ }
3331
+ ]
3332
+ };
3333
+ } catch (err) {
3334
+ return {
3335
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
3336
+ isError: true
3337
+ };
3338
+ }
3339
+ }
3340
+ );
3341
+ }
3342
+ var import_zod14, fs, path2, POLL_INTERVAL_MS, MAX_POLL_ATTEMPTS;
3343
+ var init_workflows = __esm({
3344
+ "src/tools/workflows.ts"() {
3345
+ "use strict";
3346
+ import_zod14 = require("zod");
3347
+ init_client();
3348
+ init_dist();
3349
+ fs = __toESM(require("fs"));
3350
+ path2 = __toESM(require("path"));
3351
+ init_media_utils();
3352
+ POLL_INTERVAL_MS = 5e3;
3353
+ MAX_POLL_ATTEMPTS = 120;
3354
+ }
3355
+ });
3356
+
1730
3357
  // src/tools/index.ts
1731
3358
  var tools_exports = {};
1732
3359
  __export(tools_exports, {
@@ -1741,30 +3368,285 @@ var modules;
1741
3368
  var init_tools = __esm({
1742
3369
  "src/tools/index.ts"() {
1743
3370
  "use strict";
1744
- init_media();
1745
- init_text();
1746
- init_exports();
1747
- init_folders();
1748
- init_recorder();
1749
- init_embed();
1750
- init_prompt();
1751
- init_meeting();
1752
- init_fields();
1753
- init_automations();
1754
- init_webhooks();
1755
- modules = [
1756
- media_exports,
1757
- text_exports,
1758
- exports_exports,
1759
- folders_exports,
1760
- recorder_exports,
1761
- embed_exports,
1762
- prompt_exports,
1763
- meeting_exports,
1764
- fields_exports,
1765
- automations_exports,
1766
- webhooks_exports
1767
- ];
3371
+ init_media3();
3372
+ init_text2();
3373
+ init_exports();
3374
+ init_folders();
3375
+ init_recorder3();
3376
+ init_embed3();
3377
+ init_prompt3();
3378
+ init_meeting3();
3379
+ init_fields2();
3380
+ init_automations();
3381
+ init_webhooks();
3382
+ init_analytics();
3383
+ init_clips();
3384
+ init_workflows();
3385
+ modules = [
3386
+ media_exports,
3387
+ text_exports,
3388
+ exports_exports,
3389
+ folders_exports,
3390
+ recorder_exports,
3391
+ embed_exports,
3392
+ prompt_exports,
3393
+ meeting_exports,
3394
+ fields_exports,
3395
+ automations_exports,
3396
+ webhooks_exports,
3397
+ analytics_exports,
3398
+ clips_exports,
3399
+ workflows_exports
3400
+ ];
3401
+ }
3402
+ });
3403
+
3404
+ // src/resources.ts
3405
+ var resources_exports = {};
3406
+ __export(resources_exports, {
3407
+ registerResources: () => registerResources
3408
+ });
3409
+ function registerResources(server, client) {
3410
+ const api = client ?? speakClient;
3411
+ server.resource(
3412
+ "media-library",
3413
+ "speakai://media",
3414
+ { description: "List of all media files in your Speak AI workspace" },
3415
+ async () => {
3416
+ try {
3417
+ const result = await api.get("/v1/media", {
3418
+ params: { page: 0, pageSize: 50, sortBy: "createdAt:desc", filterMedia: 2 }
3419
+ });
3420
+ return {
3421
+ contents: [
3422
+ {
3423
+ uri: "speakai://media",
3424
+ mimeType: "application/json",
3425
+ text: JSON.stringify(result.data?.data, null, 2)
3426
+ }
3427
+ ]
3428
+ };
3429
+ } catch {
3430
+ return { contents: [] };
3431
+ }
3432
+ }
3433
+ );
3434
+ server.resource(
3435
+ "folders",
3436
+ "speakai://folders",
3437
+ { description: "List of all folders in your Speak AI workspace" },
3438
+ async () => {
3439
+ try {
3440
+ const result = await api.get("/v1/folder", {
3441
+ params: { page: 0, pageSize: 100, sortBy: "createdAt:desc" }
3442
+ });
3443
+ return {
3444
+ contents: [
3445
+ {
3446
+ uri: "speakai://folders",
3447
+ mimeType: "application/json",
3448
+ text: JSON.stringify(result.data?.data, null, 2)
3449
+ }
3450
+ ]
3451
+ };
3452
+ } catch {
3453
+ return { contents: [] };
3454
+ }
3455
+ }
3456
+ );
3457
+ server.resource(
3458
+ "supported-languages",
3459
+ "speakai://languages",
3460
+ { description: "List of supported transcription languages" },
3461
+ async () => {
3462
+ try {
3463
+ const result = await api.get("/v1/media/supportedLanguages");
3464
+ return {
3465
+ contents: [
3466
+ {
3467
+ uri: "speakai://languages",
3468
+ mimeType: "application/json",
3469
+ text: JSON.stringify(result.data?.data, null, 2)
3470
+ }
3471
+ ]
3472
+ };
3473
+ } catch {
3474
+ return { contents: [] };
3475
+ }
3476
+ }
3477
+ );
3478
+ server.resource(
3479
+ "transcript",
3480
+ new import_mcp.ResourceTemplate("speakai://media/{mediaId}/transcript", { list: void 0 }),
3481
+ { description: "Full transcript for a specific media file" },
3482
+ async (uri, { mediaId }) => {
3483
+ try {
3484
+ const result = await api.get(`/v1/media/transcript/${mediaId}`);
3485
+ return {
3486
+ contents: [
3487
+ {
3488
+ uri: uri.href,
3489
+ mimeType: "application/json",
3490
+ text: JSON.stringify(result.data?.data, null, 2)
3491
+ }
3492
+ ]
3493
+ };
3494
+ } catch {
3495
+ return { contents: [] };
3496
+ }
3497
+ }
3498
+ );
3499
+ server.resource(
3500
+ "insights",
3501
+ new import_mcp.ResourceTemplate("speakai://media/{mediaId}/insights", { list: void 0 }),
3502
+ { description: "AI-generated insights for a specific media file" },
3503
+ async (uri, { mediaId }) => {
3504
+ try {
3505
+ const result = await api.get(`/v1/media/insight/${mediaId}`);
3506
+ return {
3507
+ contents: [
3508
+ {
3509
+ uri: uri.href,
3510
+ mimeType: "application/json",
3511
+ text: JSON.stringify(result.data?.data, null, 2)
3512
+ }
3513
+ ]
3514
+ };
3515
+ } catch {
3516
+ return { contents: [] };
3517
+ }
3518
+ }
3519
+ );
3520
+ }
3521
+ var import_mcp;
3522
+ var init_resources = __esm({
3523
+ "src/resources.ts"() {
3524
+ "use strict";
3525
+ import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
3526
+ init_client();
3527
+ }
3528
+ });
3529
+
3530
+ // src/prompts.ts
3531
+ var prompts_exports = {};
3532
+ __export(prompts_exports, {
3533
+ registerPrompts: () => registerPrompts
3534
+ });
3535
+ function registerPrompts(server) {
3536
+ server.prompt(
3537
+ "analyze-meeting",
3538
+ "Upload a meeting recording and get a full analysis \u2014 transcript, insights, action items, and key takeaways.",
3539
+ {
3540
+ url: import_zod15.z.string().describe("URL of the meeting recording"),
3541
+ name: import_zod15.z.string().optional().describe("Meeting name (optional)")
3542
+ },
3543
+ async ({ url, name }) => ({
3544
+ messages: [
3545
+ {
3546
+ role: "user",
3547
+ content: {
3548
+ type: "text",
3549
+ text: [
3550
+ `Please analyze this meeting recording:`,
3551
+ ``,
3552
+ `1. Upload "${name ?? "Meeting"}" from: ${url}`,
3553
+ `2. Wait for processing to complete`,
3554
+ `3. Get the full transcript and AI insights`,
3555
+ `4. Summarize:`,
3556
+ ` - Key discussion points`,
3557
+ ` - Action items with owners (if identifiable from speakers)`,
3558
+ ` - Decisions made`,
3559
+ ` - Open questions or follow-ups needed`,
3560
+ ` - Overall sentiment`,
3561
+ ``,
3562
+ `Use upload_and_analyze to handle the upload and processing in one step.`
3563
+ ].join("\n")
3564
+ }
3565
+ }
3566
+ ]
3567
+ })
3568
+ );
3569
+ server.prompt(
3570
+ "research-across-media",
3571
+ "Search for themes, patterns, or topics across multiple recordings or your entire media library.",
3572
+ {
3573
+ topic: import_zod15.z.string().describe("The topic, theme, or question to research"),
3574
+ folder: import_zod15.z.string().optional().describe("Folder ID to scope the research (optional)")
3575
+ },
3576
+ async ({ topic, folder }) => ({
3577
+ messages: [
3578
+ {
3579
+ role: "user",
3580
+ content: {
3581
+ type: "text",
3582
+ text: [
3583
+ `Research this topic across my media library: "${topic}"`,
3584
+ ``,
3585
+ folder ? `Scope: folder ${folder}` : `Scope: entire workspace`,
3586
+ ``,
3587
+ `Steps:`,
3588
+ `1. Use search_media to find relevant media matching this topic`,
3589
+ `2. For the most relevant results, use ask_magic_prompt with the matching mediaIds to ask: "${topic}"`,
3590
+ `3. Synthesize findings across all results:`,
3591
+ ` - Common themes and patterns`,
3592
+ ` - Notable quotes or data points`,
3593
+ ` - Contradictions or differing perspectives`,
3594
+ ` - Trends over time (if date range is available)`,
3595
+ ``,
3596
+ `Present a research summary with citations (media name + timestamp where possible).`
3597
+ ].join("\n")
3598
+ }
3599
+ }
3600
+ ]
3601
+ })
3602
+ );
3603
+ server.prompt(
3604
+ "meeting-brief",
3605
+ "Prepare a brief from recent meetings \u2014 pull transcripts, extract decisions, and summarize open items.",
3606
+ {
3607
+ days: import_zod15.z.string().optional().describe("Number of days to look back (default: 7)"),
3608
+ folder: import_zod15.z.string().optional().describe("Folder ID to scope to (optional)")
3609
+ },
3610
+ async ({ days, folder }) => {
3611
+ const lookback = parseInt(days ?? "7");
3612
+ const fromDate = /* @__PURE__ */ new Date();
3613
+ fromDate.setDate(fromDate.getDate() - lookback);
3614
+ return {
3615
+ messages: [
3616
+ {
3617
+ role: "user",
3618
+ content: {
3619
+ type: "text",
3620
+ text: [
3621
+ `Prepare a meeting brief from the last ${lookback} days.`,
3622
+ ``,
3623
+ folder ? `Scope: folder ${folder}` : `Scope: all media`,
3624
+ `Date range: ${fromDate.toISOString().split("T")[0]} to today`,
3625
+ ``,
3626
+ `Steps:`,
3627
+ `1. Use list_media to find recent recordings (from: ${fromDate.toISOString().split("T")[0]})`,
3628
+ `2. For each meeting, use get_media_insights to get summaries and action items`,
3629
+ `3. Compile a brief with:`,
3630
+ ` - Summary of each meeting (2-3 sentences)`,
3631
+ ` - All action items consolidated (grouped by owner if possible)`,
3632
+ ` - Key decisions made across meetings`,
3633
+ ` - Open questions or unresolved topics`,
3634
+ ` - Upcoming items that were mentioned`,
3635
+ ``,
3636
+ `Format as a clean, scannable document.`
3637
+ ].join("\n")
3638
+ }
3639
+ }
3640
+ ]
3641
+ };
3642
+ }
3643
+ );
3644
+ }
3645
+ var import_zod15;
3646
+ var init_prompts = __esm({
3647
+ "src/prompts.ts"() {
3648
+ "use strict";
3649
+ import_zod15 = require("zod");
1768
3650
  }
1769
3651
  });
1770
3652
 
@@ -1895,7 +3777,7 @@ function createCli() {
1895
3777
  const program = new import_commander.Command();
1896
3778
  program.name("speakai-mcp").description(
1897
3779
  "Speak AI CLI & MCP Server \u2014 transcribe, analyze, and manage media from the command line"
1898
- ).version("1.0.0");
3780
+ ).version("2.0.0");
1899
3781
  const config = program.command("config").description("Manage configuration");
1900
3782
  config.command("set-key").description("Set your Speak AI API key").argument("[key]", "API key (omit for interactive prompt)").action(async (key) => {
1901
3783
  if (!key) {
@@ -1935,12 +3817,146 @@ function createCli() {
1935
3817
  );
1936
3818
  }
1937
3819
  });
3820
+ config.command("test").description("Validate your API key and test connectivity").action(async () => {
3821
+ const key = resolveApiKey();
3822
+ resolveBaseUrl();
3823
+ if (!key) {
3824
+ printError('No API key configured. Run "speakai-mcp config set-key" or set SPEAK_API_KEY.');
3825
+ process.exit(1);
3826
+ }
3827
+ try {
3828
+ const axios2 = (await import("axios")).default;
3829
+ const baseUrl = process.env.SPEAK_BASE_URL ?? "https://api.speakai.co";
3830
+ const res = await axios2.post(
3831
+ `${baseUrl}/v1/auth/accessToken`,
3832
+ {},
3833
+ { headers: { "Content-Type": "application/json", "x-speakai-key": key } }
3834
+ );
3835
+ if (res.data?.data?.accessToken) {
3836
+ printSuccess("API key is valid. Connection successful.");
3837
+ } else {
3838
+ printError("Unexpected response \u2014 key may be invalid.");
3839
+ process.exit(1);
3840
+ }
3841
+ } catch (err) {
3842
+ printError(`Authentication failed: ${err.response?.data?.message ?? err.message}`);
3843
+ process.exit(1);
3844
+ }
3845
+ });
1938
3846
  config.command("set-url").description("Set custom API base URL").argument("<url>", "Base URL (e.g. https://api.speakai.co)").action((url) => {
1939
3847
  const cfg = loadConfig();
1940
3848
  cfg.baseUrl = url;
1941
3849
  saveConfig(cfg);
1942
3850
  printSuccess(`Base URL set to ${url}`);
1943
3851
  });
3852
+ program.command("init").description("Interactive setup \u2014 configure API key and auto-detect MCP clients").action(async () => {
3853
+ const rl = (0, import_readline.createInterface)({ input: process.stdin, output: process.stdout });
3854
+ const ask = (q) => new Promise((resolve) => rl.question(q, (a) => resolve(a.trim())));
3855
+ console.log("\n Speak AI MCP Server \u2014 Setup\n");
3856
+ const existingKey = resolveApiKey();
3857
+ let key = existingKey;
3858
+ if (existingKey) {
3859
+ console.log(` API key: ${existingKey.slice(0, 8)}... (already configured)`);
3860
+ const change = await ask(" Change it? (y/N) ");
3861
+ if (change.toLowerCase() === "y") key = "";
3862
+ }
3863
+ if (!key) {
3864
+ key = await ask(" Enter your Speak AI API key: ");
3865
+ if (!key) {
3866
+ printError("No key provided.");
3867
+ rl.close();
3868
+ process.exit(1);
3869
+ }
3870
+ }
3871
+ process.stdout.write(" Validating...");
3872
+ try {
3873
+ const axios2 = (await import("axios")).default;
3874
+ const baseUrl = process.env.SPEAK_BASE_URL ?? "https://api.speakai.co";
3875
+ const res = await axios2.post(
3876
+ `${baseUrl}/v1/auth/accessToken`,
3877
+ {},
3878
+ { headers: { "Content-Type": "application/json", "x-speakai-key": key } }
3879
+ );
3880
+ if (!res.data?.data?.accessToken) throw new Error("Invalid response");
3881
+ console.log(" valid!\n");
3882
+ } catch {
3883
+ console.log(" failed!");
3884
+ printError("API key is invalid. Get your key at https://app.speakai.co/developers/apikeys");
3885
+ rl.close();
3886
+ process.exit(1);
3887
+ }
3888
+ const cfg = loadConfig();
3889
+ cfg.apiKey = key;
3890
+ saveConfig(cfg);
3891
+ printSuccess(`API key saved to ${getConfigPath()}`);
3892
+ const os2 = await import("os");
3893
+ const fs3 = await import("fs");
3894
+ const pathMod = await import("path");
3895
+ const home = os2.homedir();
3896
+ const clients = [
3897
+ {
3898
+ name: "Claude Desktop",
3899
+ configPath: process.platform === "darwin" ? pathMod.join(home, "Library/Application Support/Claude/claude_desktop_config.json") : pathMod.join(home, "AppData/Roaming/Claude/claude_desktop_config.json"),
3900
+ exists: false
3901
+ },
3902
+ {
3903
+ name: "Cursor",
3904
+ configPath: pathMod.join(home, ".cursor/mcp.json"),
3905
+ exists: false
3906
+ },
3907
+ {
3908
+ name: "Windsurf",
3909
+ configPath: pathMod.join(home, ".windsurf/mcp.json"),
3910
+ exists: false
3911
+ },
3912
+ {
3913
+ name: "VS Code",
3914
+ configPath: pathMod.join(home, ".vscode/mcp.json"),
3915
+ exists: false
3916
+ }
3917
+ ];
3918
+ for (const c of clients) {
3919
+ const dir = pathMod.dirname(c.configPath);
3920
+ c.exists = fs3.existsSync(dir);
3921
+ }
3922
+ const detected = clients.filter((c) => c.exists);
3923
+ if (detected.length > 0) {
3924
+ console.log("\n Detected MCP clients:");
3925
+ for (const c of detected) {
3926
+ console.log(` - ${c.name}`);
3927
+ }
3928
+ const configure = await ask("\n Auto-configure MCP server in these clients? (Y/n) ");
3929
+ if (configure.toLowerCase() !== "n") {
3930
+ const mcpEntry = {
3931
+ command: "npx",
3932
+ args: ["-y", "@speakai/mcp-server"],
3933
+ env: { SPEAK_API_KEY: key }
3934
+ };
3935
+ for (const c of detected) {
3936
+ try {
3937
+ let config2 = {};
3938
+ if (fs3.existsSync(c.configPath)) {
3939
+ config2 = JSON.parse(fs3.readFileSync(c.configPath, "utf-8"));
3940
+ }
3941
+ const servers = config2.mcpServers ?? {};
3942
+ servers["speak-ai"] = mcpEntry;
3943
+ config2.mcpServers = servers;
3944
+ const dir = pathMod.dirname(c.configPath);
3945
+ if (!fs3.existsSync(dir)) fs3.mkdirSync(dir, { recursive: true });
3946
+ fs3.writeFileSync(c.configPath, JSON.stringify(config2, null, 2) + "\n");
3947
+ printSuccess(`Configured ${c.name}: ${c.configPath}`);
3948
+ } catch (err) {
3949
+ printError(`Failed to configure ${c.name}: ${err.message}`);
3950
+ }
3951
+ }
3952
+ }
3953
+ }
3954
+ console.log("\n For Claude Code, run:");
3955
+ console.log(` export SPEAK_API_KEY="your-api-key"`);
3956
+ console.log(" claude mcp add speak-ai -- npx -y @speakai/mcp-server\n");
3957
+ rl.close();
3958
+ printSuccess("Setup complete! You're ready to go.");
3959
+ });
1944
3960
  program.command("list-media").alias("ls").description("List media files").option("-t, --type <type>", "Filter by type (audio, video, text)").option("-p, --page <n>", "Page number (0-based)", "0").option("-s, --page-size <n>", "Results per page", "20").option("--sort <field>", "Sort field", "createdAt:desc").option("-f, --folder <id>", "Filter by folder ID").option("-n, --name <filter>", "Filter by name").option("--favorites", "Show only favorites").option("--json", "Output raw JSON").action(async (opts) => {
1945
3961
  requireApiKey();
1946
3962
  const client = await getClient();
@@ -2056,41 +4072,89 @@ function createCli() {
2056
4072
  process.exit(1);
2057
4073
  }
2058
4074
  });
2059
- program.command("upload").description("Upload media from a URL").argument("<url>", "Publicly accessible media URL").option("-n, --name <name>", "Display name").option("-t, --type <type>", "Media type (audio or video)", "audio").option("-l, --language <lang>", "Source language (BCP-47)", "en-US").option("-f, --folder <id>", "Destination folder ID").option("--tags <tags>", "Comma-separated tags").option("--wait", "Wait for processing to complete").option("--json", "Output raw JSON").action(async (url, opts) => {
4075
+ program.command("upload").description("Upload media from a URL or local file").argument("<source>", "Media URL or local file path").option("-n, --name <name>", "Display name").option("-t, --type <type>", "Media type (audio or video)").option("-l, --language <lang>", "Source language (BCP-47)", "en-US").option("-f, --folder <id>", "Destination folder ID").option("--tags <tags>", "Comma-separated tags").option("--wait", "Wait for processing to complete").option("--json", "Output raw JSON").action(async (source, opts) => {
2060
4076
  requireApiKey();
2061
4077
  const client = await getClient();
2062
4078
  try {
2063
- const body = {
2064
- name: opts.name ?? url.split("/").pop()?.split("?")[0] ?? "Upload",
2065
- url,
2066
- mediaType: opts.type,
2067
- sourceLanguage: opts.language
2068
- };
2069
- if (opts.folder) body.folderId = opts.folder;
2070
- if (opts.tags) body.tags = opts.tags;
2071
- const res = await client.post("/v1/media/upload", body);
2072
- const data = res.data?.data;
2073
- if (opts.json && !opts.wait) {
2074
- printJson(data);
2075
- return;
4079
+ const fs3 = await import("fs");
4080
+ const pathMod = await import("path");
4081
+ const isLocalFile = fs3.existsSync(source);
4082
+ let mediaId;
4083
+ let state;
4084
+ if (isLocalFile) {
4085
+ const filename = pathMod.basename(source);
4086
+ const isVideo = isVideoFile(source);
4087
+ const mediaType = opts.type ?? detectMediaType(source);
4088
+ const mimeType = getMimeType(source);
4089
+ const signedRes = await client.get("/v1/media/upload/signedurl", {
4090
+ params: { isVideo, filename, mimeType }
4091
+ });
4092
+ const signedData = signedRes.data?.data;
4093
+ const uploadUrl = signedData?.signedUrl ?? signedData?.url;
4094
+ if (!uploadUrl) {
4095
+ printError("Could not get signed upload URL");
4096
+ process.exit(1);
4097
+ }
4098
+ process.stdout.write("Uploading...");
4099
+ const fileBuffer = fs3.readFileSync(source);
4100
+ const axios2 = (await import("axios")).default;
4101
+ await axios2.put(uploadUrl, fileBuffer, {
4102
+ headers: { "Content-Type": mimeType },
4103
+ maxBodyLength: Infinity,
4104
+ maxContentLength: Infinity
4105
+ });
4106
+ console.log(" done");
4107
+ const createBody = {
4108
+ name: opts.name ?? filename,
4109
+ url: uploadUrl.split("?")[0],
4110
+ mediaType,
4111
+ sourceLanguage: opts.language
4112
+ };
4113
+ if (opts.folder) createBody.folderId = opts.folder;
4114
+ if (opts.tags) createBody.tags = opts.tags;
4115
+ const res = await client.post("/v1/media/upload", createBody);
4116
+ const data = res.data?.data;
4117
+ mediaId = data?.mediaId;
4118
+ state = data?.state;
4119
+ } else {
4120
+ const body = {
4121
+ name: opts.name ?? source.split("/").pop()?.split("?")[0] ?? "Upload",
4122
+ url: source,
4123
+ mediaType: opts.type ?? "audio",
4124
+ sourceLanguage: opts.language
4125
+ };
4126
+ if (opts.folder) body.folderId = opts.folder;
4127
+ if (opts.tags) body.tags = opts.tags;
4128
+ const res = await client.post("/v1/media/upload", body);
4129
+ const data = res.data?.data;
4130
+ if (opts.json && !opts.wait) {
4131
+ printJson(data);
4132
+ return;
4133
+ }
4134
+ mediaId = data?.mediaId;
4135
+ state = data?.state;
2076
4136
  }
2077
- const mediaId = data?.mediaId;
2078
- printSuccess(`Uploaded: ${mediaId} (state: ${data?.state})`);
4137
+ printSuccess(`Uploaded: ${mediaId} (state: ${state})`);
2079
4138
  if (opts.wait && mediaId) {
2080
4139
  process.stdout.write("Processing");
2081
- let status = data?.state;
2082
- while (status !== "processed" && status !== "failed") {
4140
+ let attempts = 0;
4141
+ const maxAttempts = 120;
4142
+ while (state !== "processed" && state !== "failed" && attempts < maxAttempts) {
2083
4143
  await new Promise((r) => setTimeout(r, 5e3));
2084
4144
  process.stdout.write(".");
2085
4145
  const statusRes = await client.get(`/v1/media/status/${mediaId}`);
2086
- status = statusRes.data?.data?.state;
4146
+ state = statusRes.data?.data?.state;
4147
+ attempts++;
2087
4148
  }
2088
4149
  console.log();
2089
- if (status === "processed") {
4150
+ if (state === "processed") {
2090
4151
  printSuccess(`Done! Media ${mediaId} is ready.`);
2091
- } else {
4152
+ } else if (state === "failed") {
2092
4153
  printError(`Processing failed for ${mediaId}`);
2093
4154
  process.exit(1);
4155
+ } else {
4156
+ printError(`Timeout: ${mediaId} still processing (state: ${state}). Check with: speakai-mcp status ${mediaId}`);
4157
+ process.exit(1);
2094
4158
  }
2095
4159
  }
2096
4160
  } catch (err) {
@@ -2201,26 +4265,291 @@ function createCli() {
2201
4265
  process.exit(1);
2202
4266
  }
2203
4267
  });
2204
- program.command("ask").description("Ask an AI question about a media file").argument("<mediaId>", "Media file ID").argument("<prompt>", "Your question").option("--assistant <type>", "Assistant type (general, researcher, marketer, sales, recruiter)", "general").option("--json", "Output raw JSON").action(async (mediaId, prompt, opts) => {
4268
+ program.command("ask").description("Ask an AI question about media files, folders, or your entire workspace").argument("<prompt>", "Your question").argument("[mediaId]", "Optional media file ID (shorthand for -m <id>)").option("-m, --media <ids...>", "Media file IDs to query (space-separated)").option("-f, --folder <ids...>", "Folder IDs to scope the query to").option("--assistant <type>", "Assistant type (general, researcher, marketer, sales, recruiter)", "general").option("--speakers <ids...>", "Filter by speaker IDs").option("--tags <tags...>", "Filter by tags").option("--from <date>", "Start date (ISO 8601)").option("--to <date>", "End date (ISO 8601)").option("--individual", "Process each media file separately").option("--continue <promptId>", "Continue an existing conversation").option("--json", "Output raw JSON").action(async (prompt, mediaId, opts) => {
2205
4269
  requireApiKey();
2206
4270
  const client = await getClient();
2207
4271
  try {
2208
- const res = await client.post("/v1/prompt", {
2209
- mediaIds: [mediaId],
4272
+ const body = {
2210
4273
  prompt,
2211
4274
  assistantType: opts.assistant
2212
- });
4275
+ };
4276
+ if (mediaId) body.mediaIds = [mediaId];
4277
+ if (opts.media) body.mediaIds = opts.media;
4278
+ if (opts.folder) body.folderIds = opts.folder;
4279
+ if (opts.speakers) body.speakers = opts.speakers;
4280
+ if (opts.tags) body.tags = opts.tags;
4281
+ if (opts.from) body.startDate = opts.from;
4282
+ if (opts.to) body.endDate = opts.to;
4283
+ if (opts.individual) body.isIndividualPrompt = true;
4284
+ if (opts.continue) body.promptId = opts.continue;
4285
+ const res = await client.post("/v1/prompt", body);
2213
4286
  const data = res.data?.data;
2214
4287
  if (opts.json) {
2215
4288
  printJson(data);
2216
4289
  } else {
2217
4290
  console.log(data?.answer ?? data?.message ?? JSON.stringify(data, null, 2));
4291
+ if (data?.promptId) {
4292
+ console.log(`
4293
+ (conversation: ${data.promptId} \u2014 use --continue to follow up)`);
4294
+ }
4295
+ }
4296
+ } catch (err) {
4297
+ printError(err.response?.data?.message ?? err.message);
4298
+ process.exit(1);
4299
+ }
4300
+ });
4301
+ program.command("chat-history").description("List past Magic Prompt conversations").option("--json", "Output raw JSON").action(async (opts) => {
4302
+ requireApiKey();
4303
+ const client = await getClient();
4304
+ try {
4305
+ const res = await client.get("/v1/prompt/history");
4306
+ const data = res.data?.data;
4307
+ if (opts.json) {
4308
+ printJson(data);
4309
+ return;
4310
+ }
4311
+ const items = Array.isArray(data) ? data : data?.prompts ?? data?.history ?? [];
4312
+ printTable(items, [
4313
+ { key: "_id", label: "ID", width: 26 },
4314
+ { key: "title", label: "Title", width: 40 },
4315
+ { key: "createdAt", label: "Created", width: 20 }
4316
+ ]);
4317
+ } catch (err) {
4318
+ printError(err.response?.data?.message ?? err.message);
4319
+ process.exit(1);
4320
+ }
4321
+ });
4322
+ program.command("search").description("Search across all media transcripts, insights, and metadata").argument("<query>", "Search query").option("--from <date>", "Start date (ISO 8601, defaults to start of month)").option("--to <date>", "End date (ISO 8601, defaults to now)").option("--json", "Output raw JSON").action(async (query, opts) => {
4323
+ requireApiKey();
4324
+ const client = await getClient();
4325
+ try {
4326
+ const body = { query };
4327
+ if (opts.from) body.startDate = opts.from;
4328
+ if (opts.to) body.endDate = opts.to;
4329
+ const res = await client.post("/v1/analytics/search", body);
4330
+ const data = res.data?.data;
4331
+ if (opts.json) {
4332
+ printJson(data);
4333
+ return;
4334
+ }
4335
+ const items = Array.isArray(data) ? data : data?.results ?? data?.mediaNodes ?? [];
4336
+ if (Array.isArray(items) && items.length > 0) {
4337
+ console.log(`Found ${items.length} result(s)
4338
+ `);
4339
+ printTable(items, [
4340
+ { key: "_id", label: "ID", width: 14 },
4341
+ { key: "name", label: "Name", width: 35 },
4342
+ { key: "mediaType", label: "Type", width: 6 },
4343
+ { key: "tags", label: "Tags", width: 20 }
4344
+ ]);
4345
+ } else {
4346
+ printJson(data);
4347
+ }
4348
+ } catch (err) {
4349
+ printError(err.response?.data?.message ?? err.message);
4350
+ process.exit(1);
4351
+ }
4352
+ });
4353
+ program.command("clips").description("List clips, optionally for a specific media file").option("-m, --media <ids...>", "Filter by source media IDs").option("-f, --folder <id>", "Filter by folder ID").option("--json", "Output raw JSON").action(async (opts) => {
4354
+ requireApiKey();
4355
+ const client = await getClient();
4356
+ try {
4357
+ const params = {};
4358
+ if (opts.media) params.mediaIds = opts.media;
4359
+ if (opts.folder) params.folderId = opts.folder;
4360
+ const res = await client.get("/v1/clips", { params });
4361
+ const data = res.data?.data;
4362
+ if (opts.json) {
4363
+ printJson(data);
4364
+ return;
4365
+ }
4366
+ const items = Array.isArray(data) ? data : data?.clips ?? [];
4367
+ printTable(items, [
4368
+ { key: "clipId", label: "ID", width: 14 },
4369
+ { key: "title", label: "Title", width: 30 },
4370
+ { key: "state", label: "Status", width: 12 },
4371
+ { key: "duration", label: "Duration", width: 10 },
4372
+ { key: "createdAt", label: "Created", width: 20 }
4373
+ ]);
4374
+ } catch (err) {
4375
+ printError(err.response?.data?.message ?? err.message);
4376
+ process.exit(1);
4377
+ }
4378
+ });
4379
+ program.command("clip").description("Create a clip from a media file").argument("<mediaId>", "Source media file ID").requiredOption("--start <seconds>", "Start time in seconds").requiredOption("--end <seconds>", "End time in seconds").option("-n, --name <title>", "Clip title", "Clip").option("-t, --type <type>", "Media type (audio or video)", "audio").option("--description <text>", "Clip description").option("--tags <tags...>", "Tags for the clip").option("--json", "Output raw JSON").action(async (mediaId, opts) => {
4380
+ requireApiKey();
4381
+ const client = await getClient();
4382
+ try {
4383
+ const body = {
4384
+ title: opts.name,
4385
+ mediaType: opts.type,
4386
+ timeRanges: [
4387
+ {
4388
+ mediaId,
4389
+ startTime: parseFloat(opts.start),
4390
+ endTime: parseFloat(opts.end)
4391
+ }
4392
+ ]
4393
+ };
4394
+ if (opts.description) body.description = opts.description;
4395
+ if (opts.tags) body.tags = opts.tags;
4396
+ const res = await client.post("/v1/clips", body);
4397
+ const data = res.data?.data;
4398
+ if (opts.json) {
4399
+ printJson(data);
4400
+ } else {
4401
+ printSuccess(`Clip created: ${data?.clipId ?? data?._id ?? "OK"} (processing...)`);
4402
+ }
4403
+ } catch (err) {
4404
+ printError(err.response?.data?.message ?? err.message);
4405
+ process.exit(1);
4406
+ }
4407
+ });
4408
+ program.command("delete").description("Delete a media file").argument("<mediaId>", "Media file ID to delete").action(async (mediaId) => {
4409
+ requireApiKey();
4410
+ const client = await getClient();
4411
+ try {
4412
+ await client.delete(`/v1/media/${mediaId}`);
4413
+ printSuccess(`Deleted: ${mediaId}`);
4414
+ } catch (err) {
4415
+ printError(err.response?.data?.message ?? err.message);
4416
+ process.exit(1);
4417
+ }
4418
+ });
4419
+ program.command("update").description("Update media metadata").argument("<mediaId>", "Media file ID to update").option("-n, --name <name>", "New display name").option("-d, --description <text>", "New description").option("--tags <tags...>", "New tags").option("-f, --folder <id>", "Move to folder ID").option("--json", "Output raw JSON").action(async (mediaId, opts) => {
4420
+ requireApiKey();
4421
+ const client = await getClient();
4422
+ try {
4423
+ const body = {};
4424
+ if (opts.name) body.name = opts.name;
4425
+ if (opts.description) body.description = opts.description;
4426
+ if (opts.tags) body.tags = opts.tags;
4427
+ if (opts.folder) body.folderId = opts.folder;
4428
+ if (Object.keys(body).length === 0) {
4429
+ printError("Provide at least one field to update (--name, --description, --tags, --folder)");
4430
+ process.exit(1);
4431
+ }
4432
+ const res = await client.put(`/v1/media/${mediaId}`, body);
4433
+ const data = res.data?.data;
4434
+ if (opts.json) {
4435
+ printJson(data);
4436
+ } else {
4437
+ printSuccess(`Updated: ${mediaId}`);
4438
+ }
4439
+ } catch (err) {
4440
+ printError(err.response?.data?.message ?? err.message);
4441
+ process.exit(1);
4442
+ }
4443
+ });
4444
+ program.command("create-folder").description("Create a new folder").argument("<name>", "Folder name").option("--json", "Output raw JSON").action(async (name, opts) => {
4445
+ requireApiKey();
4446
+ const client = await getClient();
4447
+ try {
4448
+ const res = await client.post("/v1/folder", { name });
4449
+ const data = res.data?.data;
4450
+ if (opts.json) {
4451
+ printJson(data);
4452
+ } else {
4453
+ printSuccess(`Folder created: ${data?._id ?? "OK"} \u2014 ${name}`);
4454
+ }
4455
+ } catch (err) {
4456
+ printError(err.response?.data?.message ?? err.message);
4457
+ process.exit(1);
4458
+ }
4459
+ });
4460
+ program.command("favorites").description("Toggle favorite status for a media file").argument("<mediaId>", "Media file ID").action(async (mediaId) => {
4461
+ requireApiKey();
4462
+ const client = await getClient();
4463
+ try {
4464
+ const res = await client.post("/v1/media/favorites", { mediaId });
4465
+ const data = res.data?.data;
4466
+ printSuccess(data?.message ?? `Favorite toggled for ${mediaId}`);
4467
+ } catch (err) {
4468
+ printError(err.response?.data?.message ?? err.message);
4469
+ process.exit(1);
4470
+ }
4471
+ });
4472
+ program.command("stats").description("Show workspace media statistics").option("--json", "Output raw JSON").action(async (opts) => {
4473
+ requireApiKey();
4474
+ const client = await getClient();
4475
+ try {
4476
+ const res = await client.get("/v1/media/statistics");
4477
+ const data = res.data?.data;
4478
+ if (opts.json) {
4479
+ printJson(data);
4480
+ return;
4481
+ }
4482
+ const total = data?.totalCount ?? data?.total ?? "\u2014";
4483
+ const audio = data?.audioCount ?? data?.audio ?? "\u2014";
4484
+ const video = data?.videoCount ?? data?.video ?? "\u2014";
4485
+ const text = data?.textCount ?? data?.text ?? "\u2014";
4486
+ console.log(`Total media: ${total}`);
4487
+ console.log(` Audio: ${audio}`);
4488
+ console.log(` Video: ${video}`);
4489
+ console.log(` Text: ${text}`);
4490
+ if (data?.totalDuration) {
4491
+ const hrs = Math.round(data.totalDuration / 3600 * 10) / 10;
4492
+ console.log(`Duration: ${hrs}h total`);
4493
+ }
4494
+ if (data?.totalSize) {
4495
+ const gb = Math.round(data.totalSize / (1024 * 1024 * 1024) * 100) / 100;
4496
+ console.log(`Storage: ${gb} GB`);
4497
+ }
4498
+ } catch (err) {
4499
+ printError(err.response?.data?.message ?? err.message);
4500
+ process.exit(1);
4501
+ }
4502
+ });
4503
+ program.command("languages").description("List supported transcription languages").option("--json", "Output raw JSON").action(async (opts) => {
4504
+ requireApiKey();
4505
+ const client = await getClient();
4506
+ try {
4507
+ const res = await client.get("/v1/media/supportedLanguages");
4508
+ const data = res.data?.data;
4509
+ if (opts.json) {
4510
+ printJson(data);
4511
+ } else {
4512
+ const langs = Array.isArray(data) ? data : data?.languages ?? [];
4513
+ for (const lang of langs) {
4514
+ const name = typeof lang === "string" ? lang : lang.name ?? lang.code ?? JSON.stringify(lang);
4515
+ console.log(` ${name}`);
4516
+ }
4517
+ }
4518
+ } catch (err) {
4519
+ printError(err.response?.data?.message ?? err.message);
4520
+ process.exit(1);
4521
+ }
4522
+ });
4523
+ program.command("captions").description("Get captions for a media file").argument("<mediaId>", "Media file ID").option("--json", "Output raw JSON").action(async (mediaId, opts) => {
4524
+ requireApiKey();
4525
+ const client = await getClient();
4526
+ try {
4527
+ const res = await client.get(`/v1/media/caption/${mediaId}`);
4528
+ const data = res.data?.data;
4529
+ if (opts.json) {
4530
+ printJson(data);
4531
+ } else {
4532
+ const captions = Array.isArray(data) ? data : data?.captions ?? [];
4533
+ for (const cap of captions) {
4534
+ console.log(cap.text ?? cap);
4535
+ }
2218
4536
  }
2219
4537
  } catch (err) {
2220
4538
  printError(err.response?.data?.message ?? err.message);
2221
4539
  process.exit(1);
2222
4540
  }
2223
4541
  });
4542
+ program.command("reanalyze").description("Re-run AI analysis on a media file with latest models").argument("<mediaId>", "Media file ID").action(async (mediaId) => {
4543
+ requireApiKey();
4544
+ const client = await getClient();
4545
+ try {
4546
+ await client.get(`/v1/media/reanalyze/${mediaId}`);
4547
+ printSuccess(`Re-analysis started for ${mediaId}`);
4548
+ } catch (err) {
4549
+ printError(err.response?.data?.message ?? err.message);
4550
+ process.exit(1);
4551
+ }
4552
+ });
2224
4553
  program.command("schedule-meeting").description("Schedule AI assistant to join a meeting").argument("<url>", "Meeting URL (Zoom, Meet, Teams)").option("-t, --title <title>", "Meeting title").option("-d, --date <datetime>", "Meeting date/time (ISO 8601, omit to join now)").option("-l, --language <lang>", "Meeting language", "en-US").option("--json", "Output raw JSON").action(async (url, opts) => {
2225
4554
  requireApiKey();
2226
4555
  const client = await getClient();
@@ -2257,6 +4586,7 @@ var init_cli = __esm({
2257
4586
  import_readline = require("readline");
2258
4587
  init_config();
2259
4588
  init_format();
4589
+ init_media_utils();
2260
4590
  }
2261
4591
  });
2262
4592
 
@@ -2265,14 +4595,19 @@ var index_exports = {};
2265
4595
  __export(index_exports, {
2266
4596
  createSpeakClient: () => createSpeakClient,
2267
4597
  formatAxiosError: () => formatAxiosError,
2268
- registerAllTools: () => registerAllTools
4598
+ registerAllTools: () => registerAllTools,
4599
+ registerPrompts: () => registerPrompts,
4600
+ registerResources: () => registerResources
2269
4601
  });
2270
4602
  module.exports = __toCommonJS(index_exports);
2271
4603
  init_tools();
4604
+ init_resources();
4605
+ init_prompts();
2272
4606
  init_client();
2273
4607
  var args = process.argv.slice(2);
2274
4608
  var cliCommands = [
2275
4609
  "config",
4610
+ "init",
2276
4611
  "list-media",
2277
4612
  "ls",
2278
4613
  "get-transcript",
@@ -2286,6 +4621,18 @@ var cliCommands = [
2286
4621
  "list-folders",
2287
4622
  "folders",
2288
4623
  "ask",
4624
+ "chat-history",
4625
+ "search",
4626
+ "delete",
4627
+ "update",
4628
+ "create-folder",
4629
+ "favorites",
4630
+ "stats",
4631
+ "languages",
4632
+ "captions",
4633
+ "reanalyze",
4634
+ "clips",
4635
+ "clip",
2289
4636
  "schedule-meeting",
2290
4637
  "help"
2291
4638
  ];
@@ -2306,12 +4653,18 @@ if (isCliMode) {
2306
4653
  import("@modelcontextprotocol/sdk/server/mcp.js").then(({ McpServer }) => {
2307
4654
  import("@modelcontextprotocol/sdk/server/stdio.js").then(
2308
4655
  ({ StdioServerTransport }) => {
2309
- Promise.resolve().then(() => (init_tools(), tools_exports)).then(({ registerAllTools: registerAllTools2 }) => {
4656
+ Promise.all([
4657
+ Promise.resolve().then(() => (init_tools(), tools_exports)),
4658
+ Promise.resolve().then(() => (init_resources(), resources_exports)),
4659
+ Promise.resolve().then(() => (init_prompts(), prompts_exports))
4660
+ ]).then(([{ registerAllTools: registerAllTools2 }, { registerResources: registerResources2 }, { registerPrompts: registerPrompts2 }]) => {
2310
4661
  const server = new McpServer({
2311
4662
  name: "speak-ai",
2312
4663
  version: "1.0.0"
2313
4664
  });
2314
4665
  registerAllTools2(server);
4666
+ registerResources2(server);
4667
+ registerPrompts2(server);
2315
4668
  const transport = new StdioServerTransport();
2316
4669
  server.connect(transport).then(() => {
2317
4670
  process.stderr.write(
@@ -2327,5 +4680,7 @@ if (isCliMode) {
2327
4680
  0 && (module.exports = {
2328
4681
  createSpeakClient,
2329
4682
  formatAxiosError,
2330
- registerAllTools
4683
+ registerAllTools,
4684
+ registerPrompts,
4685
+ registerResources
2331
4686
  });