@contractspec/integration.providers-impls 3.8.8 → 3.8.10
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.
- package/dist/analytics.js +1 -2
- package/dist/calendar.js +1 -2
- package/dist/database.js +1 -2
- package/dist/email.js +1 -2
- package/dist/embedding.js +1 -2
- package/dist/health.js +1 -2
- package/dist/impls/async-event-queue.js +1 -48
- package/dist/impls/composio-fallback-resolver.js +1 -579
- package/dist/impls/composio-mcp.js +1 -163
- package/dist/impls/composio-proxies.js +1 -310
- package/dist/impls/composio-sdk.js +1 -77
- package/dist/impls/composio-types.js +1 -53
- package/dist/impls/elevenlabs-voice.js +1 -104
- package/dist/impls/fal-voice.js +1 -117
- package/dist/impls/fathom-meeting-recorder.js +2 -289
- package/dist/impls/fathom-meeting-recorder.mapper.js +1 -107
- package/dist/impls/fathom-meeting-recorder.utils.js +1 -74
- package/dist/impls/fathom-meeting-recorder.webhooks.js +1 -31
- package/dist/impls/fireflies-meeting-recorder.js +5 -203
- package/dist/impls/fireflies-meeting-recorder.queries.js +4 -14
- package/dist/impls/fireflies-meeting-recorder.utils.js +1 -44
- package/dist/impls/gcs-storage.js +1 -99
- package/dist/impls/gmail-inbound.js +1 -229
- package/dist/impls/gmail-outbound.js +25 -137
- package/dist/impls/google-calendar.js +1 -193
- package/dist/impls/gradium-voice.js +1 -95
- package/dist/impls/granola-meeting-recorder.js +3 -514
- package/dist/impls/granola-meeting-recorder.mcp.js +1 -280
- package/dist/impls/health/base-health-provider.js +1 -617
- package/dist/impls/health/hybrid-health-providers.js +1 -1089
- package/dist/impls/health/official-health-providers.js +1 -969
- package/dist/impls/health/provider-normalizers.js +1 -288
- package/dist/impls/health/providers.js +1 -1095
- package/dist/impls/health-provider-factory.js +1 -1309
- package/dist/impls/index.js +42 -7448
- package/dist/impls/jira.js +1 -126
- package/dist/impls/linear.js +1 -85
- package/dist/impls/messaging-github.js +1 -111
- package/dist/impls/messaging-slack.js +1 -81
- package/dist/impls/messaging-telegram.js +1 -48
- package/dist/impls/messaging-whatsapp-meta.js +1 -53
- package/dist/impls/messaging-whatsapp-twilio.js +1 -83
- package/dist/impls/mistral-conversational.js +2 -477
- package/dist/impls/mistral-conversational.session.js +2 -207
- package/dist/impls/mistral-embedding.js +1 -45
- package/dist/impls/mistral-llm.js +1 -271
- package/dist/impls/mistral-stt.js +1 -168
- package/dist/impls/notion.js +1 -162
- package/dist/impls/posthog-reader.js +1 -161
- package/dist/impls/posthog-utils.js +1 -40
- package/dist/impls/posthog.js +1 -324
- package/dist/impls/postmark-email.js +1 -62
- package/dist/impls/powens-client.js +1 -197
- package/dist/impls/powens-openbanking.js +1 -428
- package/dist/impls/provider-factory.js +18 -6268
- package/dist/impls/qdrant-vector.js +1 -80
- package/dist/impls/stripe-payments.js +1 -230
- package/dist/impls/supabase-psql.js +1 -152
- package/dist/impls/supabase-vector.js +9 -298
- package/dist/impls/tldv-meeting-recorder.js +2 -147
- package/dist/impls/twilio-sms.js +1 -67
- package/dist/index.js +42 -7495
- package/dist/llm.js +1 -2
- package/dist/meeting-recorder.js +1 -2
- package/dist/messaging.js +1 -2
- package/dist/node/analytics.js +1 -2
- package/dist/node/calendar.js +1 -2
- package/dist/node/database.js +1 -2
- package/dist/node/email.js +1 -2
- package/dist/node/embedding.js +1 -2
- package/dist/node/health.js +1 -2
- package/dist/node/impls/async-event-queue.js +1 -49
- package/dist/node/impls/composio-fallback-resolver.js +1 -580
- package/dist/node/impls/composio-mcp.js +1 -164
- package/dist/node/impls/composio-proxies.js +1 -311
- package/dist/node/impls/composio-sdk.js +1 -78
- package/dist/node/impls/composio-types.js +1 -54
- package/dist/node/impls/elevenlabs-voice.js +1 -105
- package/dist/node/impls/fal-voice.js +1 -118
- package/dist/node/impls/fathom-meeting-recorder.js +2 -290
- package/dist/node/impls/fathom-meeting-recorder.mapper.js +1 -108
- package/dist/node/impls/fathom-meeting-recorder.utils.js +1 -75
- package/dist/node/impls/fathom-meeting-recorder.webhooks.js +1 -32
- package/dist/node/impls/fireflies-meeting-recorder.js +5 -204
- package/dist/node/impls/fireflies-meeting-recorder.queries.js +4 -15
- package/dist/node/impls/fireflies-meeting-recorder.utils.js +1 -45
- package/dist/node/impls/gcs-storage.js +1 -100
- package/dist/node/impls/gmail-inbound.js +1 -230
- package/dist/node/impls/gmail-outbound.js +25 -138
- package/dist/node/impls/google-calendar.js +1 -194
- package/dist/node/impls/gradium-voice.js +1 -96
- package/dist/node/impls/granola-meeting-recorder.js +3 -515
- package/dist/node/impls/granola-meeting-recorder.mcp.js +1 -281
- package/dist/node/impls/health/base-health-provider.js +1 -618
- package/dist/node/impls/health/hybrid-health-providers.js +1 -1090
- package/dist/node/impls/health/official-health-providers.js +1 -970
- package/dist/node/impls/health/provider-normalizers.js +1 -289
- package/dist/node/impls/health/providers.js +1 -1096
- package/dist/node/impls/health-provider-factory.js +1 -1310
- package/dist/node/impls/index.js +42 -7449
- package/dist/node/impls/jira.js +1 -127
- package/dist/node/impls/linear.js +1 -86
- package/dist/node/impls/messaging-github.js +1 -112
- package/dist/node/impls/messaging-slack.js +1 -82
- package/dist/node/impls/messaging-telegram.js +1 -49
- package/dist/node/impls/messaging-whatsapp-meta.js +1 -54
- package/dist/node/impls/messaging-whatsapp-twilio.js +1 -84
- package/dist/node/impls/mistral-conversational.js +2 -478
- package/dist/node/impls/mistral-conversational.session.js +2 -208
- package/dist/node/impls/mistral-embedding.js +1 -46
- package/dist/node/impls/mistral-llm.js +1 -272
- package/dist/node/impls/mistral-stt.js +1 -169
- package/dist/node/impls/notion.js +1 -163
- package/dist/node/impls/posthog-reader.js +1 -162
- package/dist/node/impls/posthog-utils.js +1 -41
- package/dist/node/impls/posthog.js +1 -325
- package/dist/node/impls/postmark-email.js +1 -63
- package/dist/node/impls/powens-client.js +1 -198
- package/dist/node/impls/powens-openbanking.js +1 -429
- package/dist/node/impls/provider-factory.js +18 -6269
- package/dist/node/impls/qdrant-vector.js +1 -81
- package/dist/node/impls/stripe-payments.js +1 -231
- package/dist/node/impls/supabase-psql.js +1 -153
- package/dist/node/impls/supabase-vector.js +9 -299
- package/dist/node/impls/tldv-meeting-recorder.js +2 -148
- package/dist/node/impls/twilio-sms.js +1 -68
- package/dist/node/index.js +42 -7496
- package/dist/node/llm.js +1 -2
- package/dist/node/meeting-recorder.js +1 -2
- package/dist/node/messaging.js +1 -2
- package/dist/node/openbanking.js +1 -2
- package/dist/node/payments.js +1 -2
- package/dist/node/project-management.js +1 -2
- package/dist/node/secrets/provider.js +1 -14
- package/dist/node/sms.js +1 -2
- package/dist/node/storage.js +1 -2
- package/dist/node/vector-store.js +1 -2
- package/dist/node/voice.js +1 -2
- package/dist/openbanking.js +1 -2
- package/dist/payments.js +1 -2
- package/dist/project-management.js +1 -2
- package/dist/secrets/provider.js +1 -13
- package/dist/sms.js +1 -2
- package/dist/storage.js +1 -2
- package/dist/vector-store.js +1 -2
- package/dist/voice.js +1 -2
- package/package.json +17 -17
|
@@ -1,105 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
3
|
-
|
|
4
|
-
// src/impls/elevenlabs-voice.ts
|
|
5
|
-
import { ElevenLabsClient } from "@elevenlabs/elevenlabs-js";
|
|
6
|
-
var FORMAT_MAP = {
|
|
7
|
-
mp3: "mp3_44100_128",
|
|
8
|
-
wav: "pcm_44100",
|
|
9
|
-
ogg: "mp3_44100_128",
|
|
10
|
-
pcm: "pcm_16000",
|
|
11
|
-
opus: "mp3_44100_128"
|
|
12
|
-
};
|
|
13
|
-
var SAMPLE_RATE = {
|
|
14
|
-
mp3_22050_32: 22050,
|
|
15
|
-
mp3_44100_32: 44100,
|
|
16
|
-
mp3_44100_64: 44100,
|
|
17
|
-
mp3_44100_96: 44100,
|
|
18
|
-
mp3_44100_128: 44100,
|
|
19
|
-
mp3_44100_192: 44100,
|
|
20
|
-
pcm_16000: 16000,
|
|
21
|
-
pcm_22050: 22050,
|
|
22
|
-
pcm_24000: 24000,
|
|
23
|
-
pcm_44100: 44100,
|
|
24
|
-
ulaw_8000: 8000
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
class ElevenLabsVoiceProvider {
|
|
28
|
-
client;
|
|
29
|
-
defaultVoiceId;
|
|
30
|
-
modelId;
|
|
31
|
-
constructor(options) {
|
|
32
|
-
this.client = options.client ?? new ElevenLabsClient({
|
|
33
|
-
apiKey: options.apiKey
|
|
34
|
-
});
|
|
35
|
-
this.defaultVoiceId = options.defaultVoiceId;
|
|
36
|
-
this.modelId = options.modelId;
|
|
37
|
-
}
|
|
38
|
-
async listVoices() {
|
|
39
|
-
const response = await this.client.voices.getAll();
|
|
40
|
-
return (response.voices ?? []).map((voice) => ({
|
|
41
|
-
id: voice.voiceId ?? "",
|
|
42
|
-
name: voice.name ?? "",
|
|
43
|
-
description: voice.description ?? undefined,
|
|
44
|
-
language: voice.labels?.language ?? undefined,
|
|
45
|
-
metadata: {
|
|
46
|
-
category: voice.category ?? "",
|
|
47
|
-
...voice.previewUrl ? { previewUrl: voice.previewUrl } : {},
|
|
48
|
-
...(() => {
|
|
49
|
-
const { language, ...rest } = voice.labels ?? {};
|
|
50
|
-
return rest;
|
|
51
|
-
})()
|
|
52
|
-
}
|
|
53
|
-
}));
|
|
54
|
-
}
|
|
55
|
-
async synthesize(input) {
|
|
56
|
-
const voiceId = input.voiceId ?? this.defaultVoiceId;
|
|
57
|
-
if (!voiceId) {
|
|
58
|
-
throw new Error("Voice ID is required for ElevenLabs synthesis.");
|
|
59
|
-
}
|
|
60
|
-
const formatKey = input.format ?? "mp3";
|
|
61
|
-
const outputFormat = FORMAT_MAP[formatKey] ?? FORMAT_MAP.mp3;
|
|
62
|
-
const sampleRate = input.sampleRateHz ?? SAMPLE_RATE[outputFormat] ?? SAMPLE_RATE.mp3_44100_128 ?? 44100;
|
|
63
|
-
const voiceSettings = input.stability != null || input.style != null ? {
|
|
64
|
-
...input.stability != null ? { stability: input.stability } : {},
|
|
65
|
-
...input.style != null ? { style: input.style } : {}
|
|
66
|
-
} : undefined;
|
|
67
|
-
const stream = await this.client.textToSpeech.convert(voiceId, {
|
|
68
|
-
text: input.text,
|
|
69
|
-
modelId: this.modelId,
|
|
70
|
-
outputFormat,
|
|
71
|
-
voiceSettings
|
|
72
|
-
});
|
|
73
|
-
const rawAudio = await readWebStream(stream);
|
|
74
|
-
return {
|
|
75
|
-
audio: {
|
|
76
|
-
data: rawAudio,
|
|
77
|
-
format: formatKey,
|
|
78
|
-
sampleRateHz: sampleRate
|
|
79
|
-
}
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
async function readWebStream(stream) {
|
|
84
|
-
const reader = stream.getReader();
|
|
85
|
-
const chunks = [];
|
|
86
|
-
while (true) {
|
|
87
|
-
const { done, value } = await reader.read();
|
|
88
|
-
if (done)
|
|
89
|
-
break;
|
|
90
|
-
if (value) {
|
|
91
|
-
chunks.push(value);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
const length = chunks.reduce((total, chunk) => total + chunk.length, 0);
|
|
95
|
-
const result = new Uint8Array(length);
|
|
96
|
-
let offset = 0;
|
|
97
|
-
for (const chunk of chunks) {
|
|
98
|
-
result.set(chunk, offset);
|
|
99
|
-
offset += chunk.length;
|
|
100
|
-
}
|
|
101
|
-
return result;
|
|
102
|
-
}
|
|
103
|
-
export {
|
|
104
|
-
ElevenLabsVoiceProvider
|
|
105
|
-
};
|
|
1
|
+
import{createRequire as d}from"node:module";var _=d(import.meta.url);import{ElevenLabsClient as m}from"@elevenlabs/elevenlabs-js";var l={mp3:"mp3_44100_128",wav:"pcm_44100",ogg:"mp3_44100_128",pcm:"pcm_16000",opus:"mp3_44100_128"},c={mp3_22050_32:22050,mp3_44100_32:44100,mp3_44100_64:44100,mp3_44100_96:44100,mp3_44100_128:44100,mp3_44100_192:44100,pcm_16000:16000,pcm_22050:22050,pcm_24000:24000,pcm_44100:44100,ulaw_8000:8000};class p{client;defaultVoiceId;modelId;constructor(e){this.client=e.client??new m({apiKey:e.apiKey}),this.defaultVoiceId=e.defaultVoiceId,this.modelId=e.modelId}async listVoices(){return((await this.client.voices.getAll()).voices??[]).map((t)=>({id:t.voiceId??"",name:t.name??"",description:t.description??void 0,language:t.labels?.language??void 0,metadata:{category:t.category??"",...t.previewUrl?{previewUrl:t.previewUrl}:{},...(()=>{let{language:s,...a}=t.labels??{};return a})()}}))}async synthesize(e){let t=e.voiceId??this.defaultVoiceId;if(!t)throw Error("Voice ID is required for ElevenLabs synthesis.");let s=e.format??"mp3",a=l[s]??l.mp3,o=e.sampleRateHz??c[a]??c.mp3_44100_128??44100,i=e.stability!=null||e.style!=null?{...e.stability!=null?{stability:e.stability}:{},...e.style!=null?{style:e.style}:{}}:void 0,r=await this.client.textToSpeech.convert(t,{text:e.text,modelId:this.modelId,outputFormat:a,voiceSettings:i});return{audio:{data:await u(r),format:s,sampleRateHz:o}}}}async function u(e){let t=e.getReader(),s=[];while(!0){let{done:r,value:n}=await t.read();if(r)break;if(n)s.push(n)}let a=s.reduce((r,n)=>r+n.length,0),o=new Uint8Array(a),i=0;for(let r of s)o.set(r,i),i+=r.length;return o}export{p as ElevenLabsVoiceProvider};
|
|
@@ -1,118 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
3
|
-
|
|
4
|
-
// src/impls/fal-voice.ts
|
|
5
|
-
import { createFalClient } from "@fal-ai/client";
|
|
6
|
-
var DEFAULT_MODEL_ID = "fal-ai/chatterbox/text-to-speech";
|
|
7
|
-
|
|
8
|
-
class FalVoiceProvider {
|
|
9
|
-
client;
|
|
10
|
-
modelId;
|
|
11
|
-
defaultVoiceUrl;
|
|
12
|
-
defaultExaggeration;
|
|
13
|
-
defaultTemperature;
|
|
14
|
-
defaultCfg;
|
|
15
|
-
pollIntervalMs;
|
|
16
|
-
constructor(options) {
|
|
17
|
-
this.client = options.client ?? createFalClient({
|
|
18
|
-
credentials: options.apiKey
|
|
19
|
-
});
|
|
20
|
-
this.modelId = options.modelId ?? DEFAULT_MODEL_ID;
|
|
21
|
-
this.defaultVoiceUrl = options.defaultVoiceUrl;
|
|
22
|
-
this.defaultExaggeration = options.defaultExaggeration;
|
|
23
|
-
this.defaultTemperature = options.defaultTemperature;
|
|
24
|
-
this.defaultCfg = options.defaultCfg;
|
|
25
|
-
this.pollIntervalMs = options.pollIntervalMs;
|
|
26
|
-
}
|
|
27
|
-
async listVoices() {
|
|
28
|
-
const voices = [
|
|
29
|
-
{
|
|
30
|
-
id: "default",
|
|
31
|
-
name: "Default Chatterbox Voice",
|
|
32
|
-
description: "Uses the default model voice (or configured default reference audio URL).",
|
|
33
|
-
metadata: {
|
|
34
|
-
modelId: this.modelId
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
];
|
|
38
|
-
if (this.defaultVoiceUrl) {
|
|
39
|
-
voices.push({
|
|
40
|
-
id: this.defaultVoiceUrl,
|
|
41
|
-
name: "Configured Reference Voice",
|
|
42
|
-
description: "Reference voice configured at provider setup and used when voiceId is default.",
|
|
43
|
-
previewUrl: this.defaultVoiceUrl,
|
|
44
|
-
metadata: {
|
|
45
|
-
modelId: this.modelId,
|
|
46
|
-
source: "config.defaultVoiceUrl"
|
|
47
|
-
}
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
return voices;
|
|
51
|
-
}
|
|
52
|
-
async synthesize(input) {
|
|
53
|
-
const referenceVoiceUrl = resolveVoiceUrl(input.voiceId, this.defaultVoiceUrl);
|
|
54
|
-
const result = await this.client.subscribe(this.modelId, {
|
|
55
|
-
input: {
|
|
56
|
-
text: input.text,
|
|
57
|
-
...referenceVoiceUrl ? { audio_url: referenceVoiceUrl } : {},
|
|
58
|
-
...this.defaultExaggeration != null ? { exaggeration: this.defaultExaggeration } : {},
|
|
59
|
-
...this.defaultTemperature != null ? { temperature: this.defaultTemperature } : {},
|
|
60
|
-
...this.defaultCfg != null ? { cfg: this.defaultCfg } : {}
|
|
61
|
-
},
|
|
62
|
-
pollInterval: this.pollIntervalMs
|
|
63
|
-
});
|
|
64
|
-
const audioUrl = extractAudioUrl(result.data);
|
|
65
|
-
if (!audioUrl) {
|
|
66
|
-
throw new Error("Fal synthesis completed without an audio URL in response.");
|
|
67
|
-
}
|
|
68
|
-
const response = await fetch(audioUrl);
|
|
69
|
-
if (!response.ok) {
|
|
70
|
-
throw new Error(`Fal audio download failed (${response.status}).`);
|
|
71
|
-
}
|
|
72
|
-
const rawAudio = new Uint8Array(await response.arrayBuffer());
|
|
73
|
-
const format = input.format ?? inferFormatFromUrl(audioUrl) ?? "wav";
|
|
74
|
-
return {
|
|
75
|
-
audio: {
|
|
76
|
-
data: rawAudio,
|
|
77
|
-
format,
|
|
78
|
-
sampleRateHz: input.sampleRateHz ?? 24000
|
|
79
|
-
}
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
function resolveVoiceUrl(voiceId, defaultVoiceUrl) {
|
|
84
|
-
if (!voiceId || voiceId === "default")
|
|
85
|
-
return defaultVoiceUrl;
|
|
86
|
-
if (isHttpUrl(voiceId))
|
|
87
|
-
return voiceId;
|
|
88
|
-
throw new Error('Fal voiceId must be "default" or a public reference audio URL.');
|
|
89
|
-
}
|
|
90
|
-
function extractAudioUrl(output) {
|
|
91
|
-
if (output.audio?.url)
|
|
92
|
-
return output.audio.url;
|
|
93
|
-
if (typeof output.audio_url === "string")
|
|
94
|
-
return output.audio_url;
|
|
95
|
-
if (typeof output.url === "string")
|
|
96
|
-
return output.url;
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
function inferFormatFromUrl(url) {
|
|
100
|
-
const normalized = url.toLowerCase();
|
|
101
|
-
if (normalized.endsWith(".wav"))
|
|
102
|
-
return "wav";
|
|
103
|
-
if (normalized.endsWith(".mp3"))
|
|
104
|
-
return "mp3";
|
|
105
|
-
if (normalized.endsWith(".ogg"))
|
|
106
|
-
return "ogg";
|
|
107
|
-
if (normalized.endsWith(".opus"))
|
|
108
|
-
return "opus";
|
|
109
|
-
if (normalized.endsWith(".pcm"))
|
|
110
|
-
return "pcm";
|
|
111
|
-
return;
|
|
112
|
-
}
|
|
113
|
-
function isHttpUrl(value) {
|
|
114
|
-
return value.startsWith("https://") || value.startsWith("http://");
|
|
115
|
-
}
|
|
116
|
-
export {
|
|
117
|
-
FalVoiceProvider
|
|
118
|
-
};
|
|
1
|
+
import{createRequire as o}from"node:module";var g=o(import.meta.url);import{createFalClient as d}from"@fal-ai/client";var u="fal-ai/chatterbox/text-to-speech";class s{client;modelId;defaultVoiceUrl;defaultExaggeration;defaultTemperature;defaultCfg;pollIntervalMs;constructor(e){this.client=e.client??d({credentials:e.apiKey}),this.modelId=e.modelId??u,this.defaultVoiceUrl=e.defaultVoiceUrl,this.defaultExaggeration=e.defaultExaggeration,this.defaultTemperature=e.defaultTemperature,this.defaultCfg=e.defaultCfg,this.pollIntervalMs=e.pollIntervalMs}async listVoices(){let e=[{id:"default",name:"Default Chatterbox Voice",description:"Uses the default model voice (or configured default reference audio URL).",metadata:{modelId:this.modelId}}];if(this.defaultVoiceUrl)e.push({id:this.defaultVoiceUrl,name:"Configured Reference Voice",description:"Reference voice configured at provider setup and used when voiceId is default.",previewUrl:this.defaultVoiceUrl,metadata:{modelId:this.modelId,source:"config.defaultVoiceUrl"}});return e}async synthesize(e){let t=f(e.voiceId,this.defaultVoiceUrl),a=await this.client.subscribe(this.modelId,{input:{text:e.text,...t?{audio_url:t}:{},...this.defaultExaggeration!=null?{exaggeration:this.defaultExaggeration}:{},...this.defaultTemperature!=null?{temperature:this.defaultTemperature}:{},...this.defaultCfg!=null?{cfg:this.defaultCfg}:{}},pollInterval:this.pollIntervalMs}),r=c(a.data);if(!r)throw Error("Fal synthesis completed without an audio URL in response.");let i=await fetch(r);if(!i.ok)throw Error(`Fal audio download failed (${i.status}).`);let n=new Uint8Array(await i.arrayBuffer()),l=e.format??m(r)??"wav";return{audio:{data:n,format:l,sampleRateHz:e.sampleRateHz??24000}}}}function f(e,t){if(!e||e==="default")return t;if(h(e))return e;throw Error('Fal voiceId must be "default" or a public reference audio URL.')}function c(e){if(e.audio?.url)return e.audio.url;if(typeof e.audio_url==="string")return e.audio_url;if(typeof e.url==="string")return e.url;return}function m(e){let t=e.toLowerCase();if(t.endsWith(".wav"))return"wav";if(t.endsWith(".mp3"))return"mp3";if(t.endsWith(".ogg"))return"ogg";if(t.endsWith(".opus"))return"opus";if(t.endsWith(".pcm"))return"pcm";return}function h(e){return e.startsWith("https://")||e.startsWith("http://")}export{s as FalVoiceProvider};
|
|
@@ -1,290 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
// src/impls/fathom-meeting-recorder.utils.ts
|
|
5
|
-
function extractItems(page) {
|
|
6
|
-
if (Array.isArray(page.items))
|
|
7
|
-
return page.items;
|
|
8
|
-
if (Array.isArray(page.data)) {
|
|
9
|
-
return page.data;
|
|
10
|
-
}
|
|
11
|
-
return [];
|
|
12
|
-
}
|
|
13
|
-
function extractNextCursor(page) {
|
|
14
|
-
return page.nextCursor ?? page.next_cursor ?? undefined;
|
|
15
|
-
}
|
|
16
|
-
function mapInvitee(invitee) {
|
|
17
|
-
const email = invitee.email;
|
|
18
|
-
const name = invitee.name;
|
|
19
|
-
if (!email && !name)
|
|
20
|
-
return;
|
|
21
|
-
return {
|
|
22
|
-
email,
|
|
23
|
-
name,
|
|
24
|
-
role: "attendee",
|
|
25
|
-
isExternal: invitee.is_external
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
function matchRecordingId(meeting, targetId) {
|
|
29
|
-
return meeting.recordingId === targetId;
|
|
30
|
-
}
|
|
31
|
-
function durationSeconds(start, end) {
|
|
32
|
-
if (!start || !end)
|
|
33
|
-
return;
|
|
34
|
-
const startDate = start instanceof Date ? start : new Date(start);
|
|
35
|
-
const endDate = end instanceof Date ? end : new Date(end);
|
|
36
|
-
if (Number.isNaN(startDate.valueOf()) || Number.isNaN(endDate.valueOf())) {
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
return Math.max(0, (endDate.valueOf() - startDate.valueOf()) / 1000);
|
|
40
|
-
}
|
|
41
|
-
function mapTranscriptSegment(segment, index) {
|
|
42
|
-
return {
|
|
43
|
-
index,
|
|
44
|
-
speakerName: segment.speaker?.display_name ?? undefined,
|
|
45
|
-
speakerEmail: segment.speaker?.matched_calendar_invitee_email ?? undefined,
|
|
46
|
-
text: segment.text,
|
|
47
|
-
startTimeMs: parseTimestamp(segment.timestamp)
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
function parseTimestamp(value) {
|
|
51
|
-
const parts = value.split(":").map((part) => Number(part));
|
|
52
|
-
if (parts.length !== 3 || parts.some((part) => Number.isNaN(part))) {
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
const [hours = 0, minutes = 0, seconds = 0] = parts;
|
|
56
|
-
return (hours * 3600 + minutes * 60 + seconds) * 1000;
|
|
57
|
-
}
|
|
58
|
-
async function safeReadError(response) {
|
|
59
|
-
try {
|
|
60
|
-
const data = await response.json();
|
|
61
|
-
return data?.message ?? response.statusText;
|
|
62
|
-
} catch {
|
|
63
|
-
return response.statusText;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// src/impls/fathom-meeting-recorder.mapper.ts
|
|
68
|
-
var mapFathomMeetingInvites = (invitees) => {
|
|
69
|
-
return invitees.map((invitee) => ({
|
|
70
|
-
...invitee,
|
|
71
|
-
name: invitee.name ?? undefined,
|
|
72
|
-
email: invitee.email ?? undefined
|
|
73
|
-
}));
|
|
74
|
-
};
|
|
75
|
-
function mapFathomMeeting(meeting, params) {
|
|
76
|
-
const connectionId = params.connectionId ?? "unknown";
|
|
77
|
-
return {
|
|
78
|
-
id: meeting.recordingId.toString(),
|
|
79
|
-
tenantId: params.tenantId,
|
|
80
|
-
connectionId,
|
|
81
|
-
externalId: meeting.recordingId.toString(),
|
|
82
|
-
title: meeting.title ?? meeting.meetingTitle,
|
|
83
|
-
organizer: meeting.recordedBy ? {
|
|
84
|
-
name: meeting.recordedBy.name ?? undefined,
|
|
85
|
-
email: meeting.recordedBy.email ?? undefined,
|
|
86
|
-
role: "organizer"
|
|
87
|
-
} : undefined,
|
|
88
|
-
invitees: meeting.calendarInvitees.length ? mapFathomMeetingInvites(meeting.calendarInvitees) : undefined,
|
|
89
|
-
participants: meeting.calendarInvitees.length ? mapFathomMeetingInvites(meeting.calendarInvitees) : undefined,
|
|
90
|
-
scheduledStartAt: meeting.scheduledStartTime?.toISOString(),
|
|
91
|
-
scheduledEndAt: meeting.scheduledEndTime?.toISOString(),
|
|
92
|
-
recordingStartAt: meeting.recordingStartTime?.toISOString(),
|
|
93
|
-
recordingEndAt: meeting.recordingEndTime?.toISOString(),
|
|
94
|
-
durationSeconds: durationSeconds(meeting.recordingStartTime, meeting.recordingEndTime),
|
|
95
|
-
meetingUrl: meeting.url ?? undefined,
|
|
96
|
-
shareUrl: meeting.shareUrl ?? undefined,
|
|
97
|
-
transcriptAvailable: Array.isArray(meeting.transcript),
|
|
98
|
-
sourcePlatform: "fathom",
|
|
99
|
-
language: meeting.transcriptLanguage,
|
|
100
|
-
metadata: {
|
|
101
|
-
calendarInviteesDomainsType: meeting.calendarInviteesDomainsType
|
|
102
|
-
}
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// src/impls/fathom-meeting-recorder.webhooks.ts
|
|
107
|
-
import { TriggeredFor } from "fathom-typescript/sdk/models/operations";
|
|
108
|
-
function normalizeWebhookHeaders(headers) {
|
|
109
|
-
const normalized = {};
|
|
110
|
-
for (const [key, value] of Object.entries(headers)) {
|
|
111
|
-
if (value == null)
|
|
112
|
-
continue;
|
|
113
|
-
const normalizedKey = key.toLowerCase();
|
|
114
|
-
if (Array.isArray(value)) {
|
|
115
|
-
if (value.length === 0)
|
|
116
|
-
continue;
|
|
117
|
-
normalized[normalizedKey] = value.join(", ");
|
|
118
|
-
} else {
|
|
119
|
-
normalized[normalizedKey] = value;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
return normalized;
|
|
123
|
-
}
|
|
124
|
-
function normalizeTriggeredFor(values) {
|
|
125
|
-
if (!values)
|
|
126
|
-
return;
|
|
127
|
-
const allowed = new Set(Object.values(TriggeredFor));
|
|
128
|
-
const normalized = values.map((value) => value.trim()).filter((value) => allowed.has(value));
|
|
129
|
-
return normalized.length ? normalized : undefined;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// src/impls/fathom-meeting-recorder.ts
|
|
133
|
-
import { Fathom } from "fathom-typescript";
|
|
134
|
-
import { TriggeredFor as TriggeredFor2 } from "fathom-typescript/sdk/models/operations";
|
|
135
|
-
var DEFAULT_BASE_URL = "https://api.fathom.ai/external/v1";
|
|
136
|
-
|
|
137
|
-
class FathomMeetingRecorderProvider {
|
|
138
|
-
client;
|
|
139
|
-
apiKey;
|
|
140
|
-
baseUrl;
|
|
141
|
-
includeTranscript;
|
|
142
|
-
includeSummary;
|
|
143
|
-
includeActionItems;
|
|
144
|
-
includeCrmMatches;
|
|
145
|
-
triggeredFor;
|
|
146
|
-
webhookSecret;
|
|
147
|
-
maxPages;
|
|
148
|
-
constructor(options) {
|
|
149
|
-
this.apiKey = options.apiKey;
|
|
150
|
-
this.baseUrl = options.baseUrl ?? DEFAULT_BASE_URL;
|
|
151
|
-
this.includeTranscript = options.includeTranscript ?? false;
|
|
152
|
-
this.includeSummary = options.includeSummary ?? false;
|
|
153
|
-
this.includeActionItems = options.includeActionItems ?? false;
|
|
154
|
-
this.includeCrmMatches = options.includeCrmMatches ?? false;
|
|
155
|
-
this.triggeredFor = options.triggeredFor;
|
|
156
|
-
this.webhookSecret = options.webhookSecret;
|
|
157
|
-
this.maxPages = options.maxPages ?? 5;
|
|
158
|
-
this.client = options.client ?? new Fathom({
|
|
159
|
-
serverURL: this.baseUrl,
|
|
160
|
-
security: {
|
|
161
|
-
apiKeyAuth: this.apiKey
|
|
162
|
-
}
|
|
163
|
-
});
|
|
164
|
-
}
|
|
165
|
-
async listMeetings(params) {
|
|
166
|
-
const request = {
|
|
167
|
-
cursor: params.cursor,
|
|
168
|
-
createdAfter: params.from,
|
|
169
|
-
createdBefore: params.to,
|
|
170
|
-
includeTranscript: params.includeTranscript ?? this.includeTranscript,
|
|
171
|
-
includeSummary: params.includeSummary ?? this.includeSummary,
|
|
172
|
-
includeActionItems: this.includeActionItems,
|
|
173
|
-
includeCrmMatches: this.includeCrmMatches
|
|
174
|
-
};
|
|
175
|
-
const result = await this.client.listMeetings(request);
|
|
176
|
-
let firstPage;
|
|
177
|
-
for await (const page of result) {
|
|
178
|
-
firstPage = page;
|
|
179
|
-
break;
|
|
180
|
-
}
|
|
181
|
-
if (!firstPage) {
|
|
182
|
-
return { meetings: [] };
|
|
183
|
-
}
|
|
184
|
-
const rawItems = extractItems(firstPage);
|
|
185
|
-
const meetings = rawItems.map((meeting) => mapFathomMeeting(meeting, params));
|
|
186
|
-
return {
|
|
187
|
-
meetings,
|
|
188
|
-
nextCursor: extractNextCursor(firstPage) ?? undefined,
|
|
189
|
-
hasMore: Boolean(extractNextCursor(firstPage))
|
|
190
|
-
};
|
|
191
|
-
}
|
|
192
|
-
async getMeeting(params) {
|
|
193
|
-
const result = await this.client.listMeetings({
|
|
194
|
-
includeTranscript: params.includeTranscript ?? this.includeTranscript,
|
|
195
|
-
includeSummary: params.includeSummary ?? this.includeSummary,
|
|
196
|
-
includeActionItems: this.includeActionItems,
|
|
197
|
-
includeCrmMatches: this.includeCrmMatches
|
|
198
|
-
});
|
|
199
|
-
let pageCount = 0;
|
|
200
|
-
const targetId = Number.parseInt(params.meetingId, 10);
|
|
201
|
-
for await (const page of result) {
|
|
202
|
-
pageCount += 1;
|
|
203
|
-
const match = extractItems(page).find((meeting) => matchRecordingId(meeting, targetId));
|
|
204
|
-
if (match) {
|
|
205
|
-
return mapFathomMeeting(match, params);
|
|
206
|
-
}
|
|
207
|
-
if (pageCount >= this.maxPages) {
|
|
208
|
-
break;
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
throw new Error(`Fathom meeting "${targetId}" not found.`);
|
|
212
|
-
}
|
|
213
|
-
async getTranscript(params) {
|
|
214
|
-
const response = await this.request(`/recordings/${encodeURIComponent(params.meetingId)}/transcript`);
|
|
215
|
-
if (!Array.isArray(response.transcript)) {
|
|
216
|
-
throw new Error("Fathom transcript response did not include transcript.");
|
|
217
|
-
}
|
|
218
|
-
const segments = response.transcript.map((segment, index) => mapTranscriptSegment(segment, index));
|
|
219
|
-
return {
|
|
220
|
-
id: params.meetingId,
|
|
221
|
-
meetingId: params.meetingId,
|
|
222
|
-
tenantId: params.tenantId,
|
|
223
|
-
connectionId: params.connectionId ?? "unknown",
|
|
224
|
-
externalId: params.meetingId,
|
|
225
|
-
format: "segments",
|
|
226
|
-
text: segments.map((segment) => segment.text).join(`
|
|
227
|
-
`),
|
|
228
|
-
segments,
|
|
229
|
-
metadata: {
|
|
230
|
-
provider: "fathom"
|
|
231
|
-
},
|
|
232
|
-
raw: response.transcript
|
|
233
|
-
};
|
|
234
|
-
}
|
|
235
|
-
async parseWebhook(request) {
|
|
236
|
-
const payload = request.parsedBody ?? JSON.parse(request.rawBody);
|
|
237
|
-
const body = payload;
|
|
238
|
-
const recordingId = body.recording_id ?? body.recordingId ?? body.meeting_id ?? body.meetingId;
|
|
239
|
-
const verified = this.webhookSecret ? await this.verifyWebhook(request) : undefined;
|
|
240
|
-
return {
|
|
241
|
-
providerKey: "meeting-recorder.fathom",
|
|
242
|
-
eventType: body.event_type ?? body.eventType,
|
|
243
|
-
meetingId: recordingId,
|
|
244
|
-
recordingId,
|
|
245
|
-
verified,
|
|
246
|
-
payload
|
|
247
|
-
};
|
|
248
|
-
}
|
|
249
|
-
async verifyWebhook(request) {
|
|
250
|
-
if (!this.webhookSecret)
|
|
251
|
-
return true;
|
|
252
|
-
const headers = normalizeWebhookHeaders(request.headers);
|
|
253
|
-
try {
|
|
254
|
-
return Boolean(Fathom.verifyWebhook(this.webhookSecret, headers, request.rawBody));
|
|
255
|
-
} catch {
|
|
256
|
-
return false;
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
async registerWebhook(registration) {
|
|
260
|
-
const triggeredFor = normalizeTriggeredFor(registration.triggeredFor) ?? normalizeTriggeredFor(this.triggeredFor) ?? [TriggeredFor2.MyRecordings];
|
|
261
|
-
const webhook = await this.client.createWebhook({
|
|
262
|
-
destinationUrl: registration.url,
|
|
263
|
-
includeTranscript: registration.includeTranscript ?? true,
|
|
264
|
-
includeSummary: registration.includeSummary ?? false,
|
|
265
|
-
includeActionItems: registration.includeActionItems ?? false,
|
|
266
|
-
includeCrmMatches: registration.includeCrmMatches ?? false,
|
|
267
|
-
triggeredFor
|
|
268
|
-
});
|
|
269
|
-
return {
|
|
270
|
-
id: webhook.id,
|
|
271
|
-
secret: webhook.secret
|
|
272
|
-
};
|
|
273
|
-
}
|
|
274
|
-
async request(path) {
|
|
275
|
-
const response = await fetch(`${this.baseUrl}${path}`, {
|
|
276
|
-
headers: {
|
|
277
|
-
"Content-Type": "application/json",
|
|
278
|
-
"X-Api-Key": this.apiKey
|
|
279
|
-
}
|
|
280
|
-
});
|
|
281
|
-
if (!response.ok) {
|
|
282
|
-
const message = await safeReadError(response);
|
|
283
|
-
throw new Error(`Fathom API error (${response.status}): ${message}`);
|
|
284
|
-
}
|
|
285
|
-
return await response.json();
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
export {
|
|
289
|
-
FathomMeetingRecorderProvider
|
|
290
|
-
};
|
|
1
|
+
import{createRequire as N}from"node:module";var E=N(import.meta.url);function u(n){if(Array.isArray(n.items))return n.items;if(Array.isArray(n.data))return n.data;return[]}function f(n){return n.nextCursor??n.next_cursor??void 0}function m(n){let{email:e,name:t}=n;if(!e&&!t)return;return{email:e,name:t,role:"attendee",isExternal:n.is_external}}function l(n,e){return n.recordingId===e}function S(n,e){if(!n||!e)return;let t=n instanceof Date?n:new Date(n),d=e instanceof Date?e:new Date(e);if(Number.isNaN(t.valueOf())||Number.isNaN(d.valueOf()))return;return Math.max(0,(d.valueOf()-t.valueOf())/1000)}function I(n,e){return{index:e,speakerName:n.speaker?.display_name??void 0,speakerEmail:n.speaker?.matched_calendar_invitee_email??void 0,text:n.text,startTimeMs:A(n.timestamp)}}function A(n){let e=n.split(":").map((r)=>Number(r));if(e.length!==3||e.some((r)=>Number.isNaN(r)))return;let[t=0,d=0,i=0]=e;return(t*3600+d*60+i)*1000}async function x(n){try{return(await n.json())?.message??n.statusText}catch{return n.statusText}}var h=(n)=>{return n.map((e)=>({...e,name:e.name??void 0,email:e.email??void 0}))};function a(n,e){let t=e.connectionId??"unknown";return{id:n.recordingId.toString(),tenantId:e.tenantId,connectionId:t,externalId:n.recordingId.toString(),title:n.title??n.meetingTitle,organizer:n.recordedBy?{name:n.recordedBy.name??void 0,email:n.recordedBy.email??void 0,role:"organizer"}:void 0,invitees:n.calendarInvitees.length?h(n.calendarInvitees):void 0,participants:n.calendarInvitees.length?h(n.calendarInvitees):void 0,scheduledStartAt:n.scheduledStartTime?.toISOString(),scheduledEndAt:n.scheduledEndTime?.toISOString(),recordingStartAt:n.recordingStartTime?.toISOString(),recordingEndAt:n.recordingEndTime?.toISOString(),durationSeconds:S(n.recordingStartTime,n.recordingEndTime),meetingUrl:n.url??void 0,shareUrl:n.shareUrl??void 0,transcriptAvailable:Array.isArray(n.transcript),sourcePlatform:"fathom",language:n.transcriptLanguage,metadata:{calendarInviteesDomainsType:n.calendarInviteesDomainsType}}}import{TriggeredFor as D}from"fathom-typescript/sdk/models/operations";function o(n){let e={};for(let[t,d]of Object.entries(n)){if(d==null)continue;let i=t.toLowerCase();if(Array.isArray(d)){if(d.length===0)continue;e[i]=d.join(", ")}else e[i]=d}return e}function M(n){if(!n)return;let e=new Set(Object.values(D)),t=n.map((d)=>d.trim()).filter((d)=>e.has(d));return t.length?t:void 0}import{Fathom as T}from"fathom-typescript";import{TriggeredFor as y}from"fathom-typescript/sdk/models/operations";var O="https://api.fathom.ai/external/v1";class P{client;apiKey;baseUrl;includeTranscript;includeSummary;includeActionItems;includeCrmMatches;triggeredFor;webhookSecret;maxPages;constructor(n){this.apiKey=n.apiKey,this.baseUrl=n.baseUrl??O,this.includeTranscript=n.includeTranscript??!1,this.includeSummary=n.includeSummary??!1,this.includeActionItems=n.includeActionItems??!1,this.includeCrmMatches=n.includeCrmMatches??!1,this.triggeredFor=n.triggeredFor,this.webhookSecret=n.webhookSecret,this.maxPages=n.maxPages??5,this.client=n.client??new T({serverURL:this.baseUrl,security:{apiKeyAuth:this.apiKey}})}async listMeetings(n){let e={cursor:n.cursor,createdAfter:n.from,createdBefore:n.to,includeTranscript:n.includeTranscript??this.includeTranscript,includeSummary:n.includeSummary??this.includeSummary,includeActionItems:this.includeActionItems,includeCrmMatches:this.includeCrmMatches},t=await this.client.listMeetings(e),d;for await(let c of t){d=c;break}if(!d)return{meetings:[]};return{meetings:u(d).map((c)=>a(c,n)),nextCursor:f(d)??void 0,hasMore:Boolean(f(d))}}async getMeeting(n){let e=await this.client.listMeetings({includeTranscript:n.includeTranscript??this.includeTranscript,includeSummary:n.includeSummary??this.includeSummary,includeActionItems:this.includeActionItems,includeCrmMatches:this.includeCrmMatches}),t=0,d=Number.parseInt(n.meetingId,10);for await(let i of e){t+=1;let r=u(i).find((c)=>l(c,d));if(r)return a(r,n);if(t>=this.maxPages)break}throw Error(`Fathom meeting "${d}" not found.`)}async getTranscript(n){let e=await this.request(`/recordings/${encodeURIComponent(n.meetingId)}/transcript`);if(!Array.isArray(e.transcript))throw Error("Fathom transcript response did not include transcript.");let t=e.transcript.map((d,i)=>I(d,i));return{id:n.meetingId,meetingId:n.meetingId,tenantId:n.tenantId,connectionId:n.connectionId??"unknown",externalId:n.meetingId,format:"segments",text:t.map((d)=>d.text).join(`
|
|
2
|
+
`),segments:t,metadata:{provider:"fathom"},raw:e.transcript}}async parseWebhook(n){let e=n.parsedBody??JSON.parse(n.rawBody),t=e,d=t.recording_id??t.recordingId??t.meeting_id??t.meetingId,i=this.webhookSecret?await this.verifyWebhook(n):void 0;return{providerKey:"meeting-recorder.fathom",eventType:t.event_type??t.eventType,meetingId:d,recordingId:d,verified:i,payload:e}}async verifyWebhook(n){if(!this.webhookSecret)return!0;let e=o(n.headers);try{return Boolean(T.verifyWebhook(this.webhookSecret,e,n.rawBody))}catch{return!1}}async registerWebhook(n){let e=M(n.triggeredFor)??M(this.triggeredFor)??[y.MyRecordings],t=await this.client.createWebhook({destinationUrl:n.url,includeTranscript:n.includeTranscript??!0,includeSummary:n.includeSummary??!1,includeActionItems:n.includeActionItems??!1,includeCrmMatches:n.includeCrmMatches??!1,triggeredFor:e});return{id:t.id,secret:t.secret}}async request(n){let e=await fetch(`${this.baseUrl}${n}`,{headers:{"Content-Type":"application/json","X-Api-Key":this.apiKey}});if(!e.ok){let t=await x(e);throw Error(`Fathom API error (${e.status}): ${t}`)}return await e.json()}}export{P as FathomMeetingRecorderProvider};
|
|
@@ -1,108 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
3
|
-
|
|
4
|
-
// src/impls/fathom-meeting-recorder.utils.ts
|
|
5
|
-
function extractItems(page) {
|
|
6
|
-
if (Array.isArray(page.items))
|
|
7
|
-
return page.items;
|
|
8
|
-
if (Array.isArray(page.data)) {
|
|
9
|
-
return page.data;
|
|
10
|
-
}
|
|
11
|
-
return [];
|
|
12
|
-
}
|
|
13
|
-
function extractNextCursor(page) {
|
|
14
|
-
return page.nextCursor ?? page.next_cursor ?? undefined;
|
|
15
|
-
}
|
|
16
|
-
function mapInvitee(invitee) {
|
|
17
|
-
const email = invitee.email;
|
|
18
|
-
const name = invitee.name;
|
|
19
|
-
if (!email && !name)
|
|
20
|
-
return;
|
|
21
|
-
return {
|
|
22
|
-
email,
|
|
23
|
-
name,
|
|
24
|
-
role: "attendee",
|
|
25
|
-
isExternal: invitee.is_external
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
function matchRecordingId(meeting, targetId) {
|
|
29
|
-
return meeting.recordingId === targetId;
|
|
30
|
-
}
|
|
31
|
-
function durationSeconds(start, end) {
|
|
32
|
-
if (!start || !end)
|
|
33
|
-
return;
|
|
34
|
-
const startDate = start instanceof Date ? start : new Date(start);
|
|
35
|
-
const endDate = end instanceof Date ? end : new Date(end);
|
|
36
|
-
if (Number.isNaN(startDate.valueOf()) || Number.isNaN(endDate.valueOf())) {
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
return Math.max(0, (endDate.valueOf() - startDate.valueOf()) / 1000);
|
|
40
|
-
}
|
|
41
|
-
function mapTranscriptSegment(segment, index) {
|
|
42
|
-
return {
|
|
43
|
-
index,
|
|
44
|
-
speakerName: segment.speaker?.display_name ?? undefined,
|
|
45
|
-
speakerEmail: segment.speaker?.matched_calendar_invitee_email ?? undefined,
|
|
46
|
-
text: segment.text,
|
|
47
|
-
startTimeMs: parseTimestamp(segment.timestamp)
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
function parseTimestamp(value) {
|
|
51
|
-
const parts = value.split(":").map((part) => Number(part));
|
|
52
|
-
if (parts.length !== 3 || parts.some((part) => Number.isNaN(part))) {
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
const [hours = 0, minutes = 0, seconds = 0] = parts;
|
|
56
|
-
return (hours * 3600 + minutes * 60 + seconds) * 1000;
|
|
57
|
-
}
|
|
58
|
-
async function safeReadError(response) {
|
|
59
|
-
try {
|
|
60
|
-
const data = await response.json();
|
|
61
|
-
return data?.message ?? response.statusText;
|
|
62
|
-
} catch {
|
|
63
|
-
return response.statusText;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// src/impls/fathom-meeting-recorder.mapper.ts
|
|
68
|
-
var mapFathomMeetingInvites = (invitees) => {
|
|
69
|
-
return invitees.map((invitee) => ({
|
|
70
|
-
...invitee,
|
|
71
|
-
name: invitee.name ?? undefined,
|
|
72
|
-
email: invitee.email ?? undefined
|
|
73
|
-
}));
|
|
74
|
-
};
|
|
75
|
-
function mapFathomMeeting(meeting, params) {
|
|
76
|
-
const connectionId = params.connectionId ?? "unknown";
|
|
77
|
-
return {
|
|
78
|
-
id: meeting.recordingId.toString(),
|
|
79
|
-
tenantId: params.tenantId,
|
|
80
|
-
connectionId,
|
|
81
|
-
externalId: meeting.recordingId.toString(),
|
|
82
|
-
title: meeting.title ?? meeting.meetingTitle,
|
|
83
|
-
organizer: meeting.recordedBy ? {
|
|
84
|
-
name: meeting.recordedBy.name ?? undefined,
|
|
85
|
-
email: meeting.recordedBy.email ?? undefined,
|
|
86
|
-
role: "organizer"
|
|
87
|
-
} : undefined,
|
|
88
|
-
invitees: meeting.calendarInvitees.length ? mapFathomMeetingInvites(meeting.calendarInvitees) : undefined,
|
|
89
|
-
participants: meeting.calendarInvitees.length ? mapFathomMeetingInvites(meeting.calendarInvitees) : undefined,
|
|
90
|
-
scheduledStartAt: meeting.scheduledStartTime?.toISOString(),
|
|
91
|
-
scheduledEndAt: meeting.scheduledEndTime?.toISOString(),
|
|
92
|
-
recordingStartAt: meeting.recordingStartTime?.toISOString(),
|
|
93
|
-
recordingEndAt: meeting.recordingEndTime?.toISOString(),
|
|
94
|
-
durationSeconds: durationSeconds(meeting.recordingStartTime, meeting.recordingEndTime),
|
|
95
|
-
meetingUrl: meeting.url ?? undefined,
|
|
96
|
-
shareUrl: meeting.shareUrl ?? undefined,
|
|
97
|
-
transcriptAvailable: Array.isArray(meeting.transcript),
|
|
98
|
-
sourcePlatform: "fathom",
|
|
99
|
-
language: meeting.transcriptLanguage,
|
|
100
|
-
metadata: {
|
|
101
|
-
calendarInviteesDomainsType: meeting.calendarInviteesDomainsType
|
|
102
|
-
}
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
export {
|
|
106
|
-
mapFathomMeetingInvites,
|
|
107
|
-
mapFathomMeeting
|
|
108
|
-
};
|
|
1
|
+
import{createRequire as s}from"node:module";var m=s(import.meta.url);function l(e){if(Array.isArray(e.items))return e.items;if(Array.isArray(e.data))return e.data;return[]}function g(e){return e.nextCursor??e.next_cursor??void 0}function p(e){let{email:t,name:n}=e;if(!t&&!n)return;return{email:t,name:n,role:"attendee",isExternal:e.is_external}}function h(e,t){return e.recordingId===t}function i(e,t){if(!e||!t)return;let n=e instanceof Date?e:new Date(e),r=t instanceof Date?t:new Date(t);if(Number.isNaN(n.valueOf())||Number.isNaN(r.valueOf()))return;return Math.max(0,(r.valueOf()-n.valueOf())/1000)}function M(e,t){return{index:t,speakerName:e.speaker?.display_name??void 0,speakerEmail:e.speaker?.matched_calendar_invitee_email??void 0,text:e.text,startTimeMs:c(e.timestamp)}}function c(e){let t=e.split(":").map((a)=>Number(a));if(t.length!==3||t.some((a)=>Number.isNaN(a)))return;let[n=0,r=0,d=0]=t;return(n*3600+r*60+d)*1000}async function I(e){try{return(await e.json())?.message??e.statusText}catch{return e.statusText}}var o=(e)=>{return e.map((t)=>({...t,name:t.name??void 0,email:t.email??void 0}))};function y(e,t){let n=t.connectionId??"unknown";return{id:e.recordingId.toString(),tenantId:t.tenantId,connectionId:n,externalId:e.recordingId.toString(),title:e.title??e.meetingTitle,organizer:e.recordedBy?{name:e.recordedBy.name??void 0,email:e.recordedBy.email??void 0,role:"organizer"}:void 0,invitees:e.calendarInvitees.length?o(e.calendarInvitees):void 0,participants:e.calendarInvitees.length?o(e.calendarInvitees):void 0,scheduledStartAt:e.scheduledStartTime?.toISOString(),scheduledEndAt:e.scheduledEndTime?.toISOString(),recordingStartAt:e.recordingStartTime?.toISOString(),recordingEndAt:e.recordingEndTime?.toISOString(),durationSeconds:i(e.recordingStartTime,e.recordingEndTime),meetingUrl:e.url??void 0,shareUrl:e.shareUrl??void 0,transcriptAvailable:Array.isArray(e.transcript),sourcePlatform:"fathom",language:e.transcriptLanguage,metadata:{calendarInviteesDomainsType:e.calendarInviteesDomainsType}}}export{o as mapFathomMeetingInvites,y as mapFathomMeeting};
|