From f13bde1e035b0c4c9376b07cdbe88b81edb11707 Mon Sep 17 00:00:00 2001
From: nitin <142569587+ehconitin@users.noreply.github.com>
Date: Tue, 14 Jul 2026 01:51:39 +0530
Subject: [PATCH] Align call recorder vocabulary with core dialect (#22831)
Part 1/5 of splitting #22739 into a reviewable stack.
Mechanical renames only, no behavior change:
- `ingestion` -> `import` across data/domain/flows
(`completeCallRecordingIngestion` -> `completeCallRecordingImport`,
`ingestCallRecordingMedia` -> `importCallRecordingMedia`,
`reconcileCallRecordingTranscriptArtifact` ->
`importCallRecordingTranscript`, ...)
- `reapOrphanedCallRecorders` -> `cleanupOrphanedRecallBots`
- `ensureCallRecorder` -> `scheduleRecallBotForCallRecording`,
`healCallRecordingsMissingBot` ->
`scheduleRecallBotsForPendingCallRecordings`
- `extractRecallBotConvergence` -> `extractRecallBotSyncState`
- formatting drift in touched files
Next in the stack: Recall API hardening, billing charge verification,
divergence-scoped sync crons, webhook artifact continuation.
---
.../components/TranscriptEntryListItem.tsx | 4 +-
...call-recorder-recording-retention-hours.ts | 2 +-
...=> complete-call-recording-import.test.ts} | 10 ++--
...=> complete-call-recording-import.util.ts} | 2 +-
...-call-recording-summaries-backfill.util.ts | 11 +++--
...ract-conference-link-url-from-text.test.ts | 5 +-
...is-call-recording-import-complete.test.ts} | 24 +++++-----
...ld-complete-call-recording-import.test.ts} | 20 ++++----
.../domain/build-bot-image.util.ts | 10 ++--
...-recall-bot-automatic-video-output.util.ts | 3 +-
...is-call-recording-import-complete.util.ts} | 2 +-
...atus-code-to-call-recording-status.util.ts | 2 +-
...ld-complete-call-recording-import.util.ts} | 6 +--
...s => cleanup-orphaned-recall-bots.test.ts} | 32 ++++++-------
...complete-and-charge-call-recording.test.ts | 12 ++---
.../converge-diverged-call-recordings.test.ts | 22 ++++-----
.../__tests__/handle-recall-webhook.test.ts | 24 +++++-----
...ts => import-call-recording-media.test.ts} | 28 +++++------
.../__tests__/reconcile-call-recorder.test.ts | 2 +-
...-bots-for-pending-call-recordings.test.ts} | 24 +++++-----
...s => cleanup-orphaned-recall-bots.util.ts} | 10 ++--
...complete-and-charge-call-recording.util.ts | 4 +-
.../converge-diverged-call-recordings.util.ts | 26 +++++-----
.../flows/handle-recall-webhook.util.ts | 28 +++++------
...ts => import-call-recording-media.util.ts} | 32 ++++++-------
...-call-recording-transcript-result.type.ts} | 2 +-
... import-call-recording-transcript.util.ts} | 10 ++--
.../persist-call-recording-progress.util.ts | 12 ++---
.../flows/reconcile-call-recorder.util.ts | 4 +-
...ule-recall-bot-for-call-recording.util.ts} | 2 +-
...-bots-for-pending-call-recordings.util.ts} | 18 +++----
... => extract-recall-bot-sync-state.test.ts} | 48 +++++++++----------
... => extract-recall-bot-sync-state.util.ts} | 6 +--
.../recall-api/recall-bot-api-request.util.ts | 2 +-
.../reconcile-stale-bot-state.ts | 48 +++++++++----------
35 files changed, 247 insertions(+), 250 deletions(-)
rename packages/twenty-apps/public/call-recorder/src/logic-functions/data/__tests__/{complete-call-recording-ingestion.test.ts => complete-call-recording-import.test.ts} (80%)
rename packages/twenty-apps/public/call-recorder/src/logic-functions/data/{complete-call-recording-ingestion.util.ts => complete-call-recording-import.util.ts} (92%)
rename packages/twenty-apps/public/call-recorder/src/logic-functions/domain/__tests__/{is-call-recording-ingestion-complete.test.ts => is-call-recording-import-complete.test.ts} (82%)
rename packages/twenty-apps/public/call-recorder/src/logic-functions/domain/__tests__/{should-complete-call-recording-ingestion.test.ts => should-complete-call-recording-import.test.ts} (86%)
rename packages/twenty-apps/public/call-recorder/src/logic-functions/domain/{is-call-recording-ingestion-complete.util.ts => is-call-recording-import-complete.util.ts} (94%)
rename packages/twenty-apps/public/call-recorder/src/logic-functions/domain/{should-complete-call-recording-ingestion.util.ts => should-complete-call-recording-import.util.ts} (85%)
rename packages/twenty-apps/public/call-recorder/src/logic-functions/flows/__tests__/{reap-orphaned-call-recorders.test.ts => cleanup-orphaned-recall-bots.test.ts} (91%)
rename packages/twenty-apps/public/call-recorder/src/logic-functions/flows/__tests__/{ingest-call-recording-media.test.ts => import-call-recording-media.test.ts} (94%)
rename packages/twenty-apps/public/call-recorder/src/logic-functions/flows/__tests__/{heal-call-recordings-missing-bot.test.ts => schedule-recall-bots-for-pending-call-recordings.test.ts} (88%)
rename packages/twenty-apps/public/call-recorder/src/logic-functions/flows/{reap-orphaned-call-recorders.util.ts => cleanup-orphaned-recall-bots.util.ts} (93%)
rename packages/twenty-apps/public/call-recorder/src/logic-functions/flows/{ingest-call-recording-media.util.ts => import-call-recording-media.util.ts} (87%)
rename packages/twenty-apps/public/call-recorder/src/logic-functions/flows/{reconcile-call-recording-transcript-artifact-result.type.ts => import-call-recording-transcript-result.type.ts} (84%)
rename packages/twenty-apps/public/call-recorder/src/logic-functions/flows/{reconcile-call-recording-transcript-artifact.util.ts => import-call-recording-transcript.util.ts} (93%)
rename packages/twenty-apps/public/call-recorder/src/logic-functions/flows/{ensure-call-recorder.util.ts => schedule-recall-bot-for-call-recording.util.ts} (98%)
rename packages/twenty-apps/public/call-recorder/src/logic-functions/flows/{heal-call-recordings-missing-bot.util.ts => schedule-recall-bots-for-pending-call-recordings.util.ts} (78%)
rename packages/twenty-apps/public/call-recorder/src/logic-functions/recall-api/__tests__/{extract-recall-bot-convergence.test.ts => extract-recall-bot-sync-state.test.ts} (74%)
rename packages/twenty-apps/public/call-recorder/src/logic-functions/recall-api/{extract-recall-bot-convergence.util.ts => extract-recall-bot-sync-state.util.ts} (97%)
diff --git a/packages/twenty-apps/public/call-recorder/src/front-components/components/TranscriptEntryListItem.tsx b/packages/twenty-apps/public/call-recorder/src/front-components/components/TranscriptEntryListItem.tsx
index 40fd0a304b..50367f3574 100644
--- a/packages/twenty-apps/public/call-recorder/src/front-components/components/TranscriptEntryListItem.tsx
+++ b/packages/twenty-apps/public/call-recorder/src/front-components/components/TranscriptEntryListItem.tsx
@@ -13,9 +13,7 @@ import { formatSecondsAsClockTimestamp } from 'src/logic-functions/utils/format-
const StyledEntry = styled.div<{ $isActive: boolean }>`
align-items: flex-start;
background: ${({ $isActive }) =>
- $isActive
- ? themeCssVariables.background.transparent.blue
- : 'transparent'};
+ $isActive ? themeCssVariables.background.transparent.blue : 'transparent'};
border-radius: ${() => themeCssVariables.border.radius.sm};
box-sizing: border-box;
display: flex;
diff --git a/packages/twenty-apps/public/call-recorder/src/logic-functions/constants/default-call-recorder-recording-retention-hours.ts b/packages/twenty-apps/public/call-recorder/src/logic-functions/constants/default-call-recorder-recording-retention-hours.ts
index f1a8cbfdf5..4204e56430 100644
--- a/packages/twenty-apps/public/call-recorder/src/logic-functions/constants/default-call-recorder-recording-retention-hours.ts
+++ b/packages/twenty-apps/public/call-recorder/src/logic-functions/constants/default-call-recorder-recording-retention-hours.ts
@@ -1,2 +1,2 @@
-// Twenty stores ingested recording artifacts, so Recall.ai media is temporary. Keep the default below Recall.ai's 168-hour free storage window.
+// Twenty stores imported recording artifacts, so Recall.ai media is temporary. Keep the default below Recall.ai's 168-hour free storage window.
export const DEFAULT_CALL_RECORDER_RECORDING_RETENTION_HOURS = 166;
diff --git a/packages/twenty-apps/public/call-recorder/src/logic-functions/data/__tests__/complete-call-recording-ingestion.test.ts b/packages/twenty-apps/public/call-recorder/src/logic-functions/data/__tests__/complete-call-recording-import.test.ts
similarity index 80%
rename from packages/twenty-apps/public/call-recorder/src/logic-functions/data/__tests__/complete-call-recording-ingestion.test.ts
rename to packages/twenty-apps/public/call-recorder/src/logic-functions/data/__tests__/complete-call-recording-import.test.ts
index 820f7d3b3a..3cfb493aa8 100644
--- a/packages/twenty-apps/public/call-recorder/src/logic-functions/data/__tests__/complete-call-recording-ingestion.test.ts
+++ b/packages/twenty-apps/public/call-recorder/src/logic-functions/data/__tests__/complete-call-recording-import.test.ts
@@ -1,8 +1,8 @@
import { describe, expect, it, vi } from 'vitest';
-import { completeCallRecordingIngestion } from 'src/logic-functions/data/complete-call-recording-ingestion.util';
+import { completeCallRecordingImport } from 'src/logic-functions/data/complete-call-recording-import.util';
-describe('completeCallRecordingIngestion', () => {
+describe('completeCallRecordingImport', () => {
it('guards the flip with non-terminal statuses and returns true when the row is claimed', async () => {
let capturedArgs: { filter: unknown; data: unknown } | undefined;
const mutation = vi.fn(async (mutationArg: any) => {
@@ -11,7 +11,7 @@ describe('completeCallRecordingIngestion', () => {
return { updateCallRecordings: [{ id: 'call-recording-1' }] };
});
- const claimed = await completeCallRecordingIngestion(
+ const claimed = await completeCallRecordingImport(
{ mutation } as never,
{
id: 'call-recording-1',
@@ -30,7 +30,7 @@ describe('completeCallRecordingIngestion', () => {
it('returns false when the row was already COMPLETED, so the loser cannot charge', async () => {
const mutation = vi.fn(async () => ({ updateCallRecordings: [] }));
- const claimed = await completeCallRecordingIngestion(
+ const claimed = await completeCallRecordingImport(
{ mutation } as never,
{
id: 'call-recording-1',
@@ -43,7 +43,7 @@ describe('completeCallRecordingIngestion', () => {
it('returns false when the API omits the result list', async () => {
const mutation = vi.fn(async () => ({}));
- const claimed = await completeCallRecordingIngestion(
+ const claimed = await completeCallRecordingImport(
{ mutation } as never,
{
id: 'call-recording-1',
diff --git a/packages/twenty-apps/public/call-recorder/src/logic-functions/data/complete-call-recording-ingestion.util.ts b/packages/twenty-apps/public/call-recorder/src/logic-functions/data/complete-call-recording-import.util.ts
similarity index 92%
rename from packages/twenty-apps/public/call-recorder/src/logic-functions/data/complete-call-recording-ingestion.util.ts
rename to packages/twenty-apps/public/call-recorder/src/logic-functions/data/complete-call-recording-import.util.ts
index 659c601af9..a844806331 100644
--- a/packages/twenty-apps/public/call-recorder/src/logic-functions/data/complete-call-recording-ingestion.util.ts
+++ b/packages/twenty-apps/public/call-recorder/src/logic-functions/data/complete-call-recording-import.util.ts
@@ -3,7 +3,7 @@ import { type CoreApiClient } from 'twenty-client-sdk/core';
import { CallRecordingStatus } from 'src/logic-functions/constants/call-recording-status';
import { NON_TERMINAL_CALL_RECORDING_STATUSES } from 'src/logic-functions/constants/non-terminal-call-recording-statuses';
-export const completeCallRecordingIngestion = async (
+export const completeCallRecordingImport = async (
client: CoreApiClient,
{ id }: { id: string },
): Promise => {
diff --git a/packages/twenty-apps/public/call-recorder/src/logic-functions/data/request-call-recording-summaries-backfill.util.ts b/packages/twenty-apps/public/call-recorder/src/logic-functions/data/request-call-recording-summaries-backfill.util.ts
index 27b5f42faf..9037f8652b 100644
--- a/packages/twenty-apps/public/call-recorder/src/logic-functions/data/request-call-recording-summaries-backfill.util.ts
+++ b/packages/twenty-apps/public/call-recorder/src/logic-functions/data/request-call-recording-summaries-backfill.util.ts
@@ -1,8 +1,9 @@
import { GENERATE_CALL_RECORDING_SUMMARIES_ROUTE_PATH } from 'src/constants/generate-call-recording-summaries-route-path';
import { postToOwnRoute } from 'src/logic-functions/data/post-to-own-route.util';
-export const requestCallRecordingSummariesBackfill = async (): Promise =>
- postToOwnRoute({
- path: GENERATE_CALL_RECORDING_SUMMARIES_ROUTE_PATH,
- body: {},
- });
+export const requestCallRecordingSummariesBackfill =
+ async (): Promise =>
+ postToOwnRoute({
+ path: GENERATE_CALL_RECORDING_SUMMARIES_ROUTE_PATH,
+ body: {},
+ });
diff --git a/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/__tests__/extract-conference-link-url-from-text.test.ts b/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/__tests__/extract-conference-link-url-from-text.test.ts
index 4307e1dfad..bbf87db52a 100644
--- a/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/__tests__/extract-conference-link-url-from-text.test.ts
+++ b/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/__tests__/extract-conference-link-url-from-text.test.ts
@@ -64,7 +64,10 @@ describe('extractConferenceLinkUrlFromText', () => {
});
it.each([
- ['a non-conferencing URL', 'Agenda: https://docs.google.com/document/d/abc'],
+ [
+ 'a non-conferencing URL',
+ 'Agenda: https://docs.google.com/document/d/abc',
+ ],
['a Zoom marketing page URL', 'Learn more at https://zoom.us/pricing'],
['plain text without links', 'Conference Room A'],
['an empty string', ''],
diff --git a/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/__tests__/is-call-recording-ingestion-complete.test.ts b/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/__tests__/is-call-recording-import-complete.test.ts
similarity index 82%
rename from packages/twenty-apps/public/call-recorder/src/logic-functions/domain/__tests__/is-call-recording-ingestion-complete.test.ts
rename to packages/twenty-apps/public/call-recorder/src/logic-functions/domain/__tests__/is-call-recording-import-complete.test.ts
index 11e00d23ca..5a991693d2 100644
--- a/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/__tests__/is-call-recording-ingestion-complete.test.ts
+++ b/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/__tests__/is-call-recording-import-complete.test.ts
@@ -1,15 +1,15 @@
import { describe, expect, it } from 'vitest';
-import { isCallRecordingIngestionComplete } from 'src/logic-functions/domain/is-call-recording-ingestion-complete.util';
+import { isCallRecordingImportComplete } from 'src/logic-functions/domain/is-call-recording-import-complete.util';
const AUDIO_VALUE = [{ fileId: 'file-audio-1', label: 'audio.mp3' }];
const VIDEO_VALUE = [{ fileId: 'file-video-1', label: 'video.mp4' }];
const TRANSCRIPT_CONTENT = [{ participant: { id: 1 }, words: [] }];
-describe('isCallRecordingIngestionComplete', () => {
+describe('isCallRecordingImportComplete', () => {
it('is complete when transcript content and both media files are present', () => {
expect(
- isCallRecordingIngestionComplete({
+ isCallRecordingImportComplete({
transcript: TRANSCRIPT_CONTENT,
audio: AUDIO_VALUE,
video: VIDEO_VALUE,
@@ -20,7 +20,7 @@ describe('isCallRecordingIngestionComplete', () => {
it('is incomplete while the transcript holds a marker', () => {
expect(
- isCallRecordingIngestionComplete({
+ isCallRecordingImportComplete({
transcript: {
recallTranscriptId: 'recall-transcript-1',
status: 'PENDING',
@@ -34,7 +34,7 @@ describe('isCallRecordingIngestionComplete', () => {
it('is incomplete when the transcript is unset', () => {
expect(
- isCallRecordingIngestionComplete({
+ isCallRecordingImportComplete({
transcript: null,
audio: AUDIO_VALUE,
video: VIDEO_VALUE,
@@ -45,7 +45,7 @@ describe('isCallRecordingIngestionComplete', () => {
it('is incomplete while any media field is empty', () => {
expect(
- isCallRecordingIngestionComplete({
+ isCallRecordingImportComplete({
transcript: TRANSCRIPT_CONTENT,
audio: undefined,
video: VIDEO_VALUE,
@@ -53,7 +53,7 @@ describe('isCallRecordingIngestionComplete', () => {
}),
).toBe(false);
expect(
- isCallRecordingIngestionComplete({
+ isCallRecordingImportComplete({
transcript: TRANSCRIPT_CONTENT,
audio: AUDIO_VALUE,
video: [],
@@ -64,7 +64,7 @@ describe('isCallRecordingIngestionComplete', () => {
it('treats a media file skipped for size as resolved', () => {
expect(
- isCallRecordingIngestionComplete({
+ isCallRecordingImportComplete({
transcript: TRANSCRIPT_CONTENT,
audio: AUDIO_VALUE,
video: undefined,
@@ -72,7 +72,7 @@ describe('isCallRecordingIngestionComplete', () => {
}),
).toBe(true);
expect(
- isCallRecordingIngestionComplete({
+ isCallRecordingImportComplete({
transcript: TRANSCRIPT_CONTENT,
audio: undefined,
video: VIDEO_VALUE,
@@ -80,7 +80,7 @@ describe('isCallRecordingIngestionComplete', () => {
}),
).toBe(true);
expect(
- isCallRecordingIngestionComplete({
+ isCallRecordingImportComplete({
transcript: TRANSCRIPT_CONTENT,
audio: undefined,
video: undefined,
@@ -91,7 +91,7 @@ describe('isCallRecordingIngestionComplete', () => {
it('does not let a size marker excuse the other missing artifact', () => {
expect(
- isCallRecordingIngestionComplete({
+ isCallRecordingImportComplete({
transcript: TRANSCRIPT_CONTENT,
audio: undefined,
video: VIDEO_VALUE,
@@ -102,7 +102,7 @@ describe('isCallRecordingIngestionComplete', () => {
it('ignores unrelated failure reasons', () => {
expect(
- isCallRecordingIngestionComplete({
+ isCallRecordingImportComplete({
transcript: TRANSCRIPT_CONTENT,
audio: AUDIO_VALUE,
video: undefined,
diff --git a/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/__tests__/should-complete-call-recording-ingestion.test.ts b/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/__tests__/should-complete-call-recording-import.test.ts
similarity index 86%
rename from packages/twenty-apps/public/call-recorder/src/logic-functions/domain/__tests__/should-complete-call-recording-ingestion.test.ts
rename to packages/twenty-apps/public/call-recorder/src/logic-functions/domain/__tests__/should-complete-call-recording-import.test.ts
index bae388da11..d95db419dc 100644
--- a/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/__tests__/should-complete-call-recording-ingestion.test.ts
+++ b/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/__tests__/should-complete-call-recording-import.test.ts
@@ -1,16 +1,16 @@
import { describe, expect, it } from 'vitest';
import { CallRecordingStatus } from 'src/logic-functions/constants/call-recording-status';
-import { shouldCompleteCallRecordingIngestion } from 'src/logic-functions/domain/should-complete-call-recording-ingestion.util';
+import { shouldCompleteCallRecordingImport } from 'src/logic-functions/domain/should-complete-call-recording-import.util';
const filledTranscript = [{ participant: { id: 1 }, words: [] }];
const filledAudio = [{ fileId: 'file-audio-1', label: 'audio.mp3' }];
const filledVideo = [{ fileId: 'file-video-1', label: 'video.mp4' }];
-describe('shouldCompleteCallRecordingIngestion', () => {
+describe('shouldCompleteCallRecordingImport', () => {
it('requires complete artifacts and billable timestamps before completion', () => {
expect(
- shouldCompleteCallRecordingIngestion({
+ shouldCompleteCallRecordingImport({
current: {
status: CallRecordingStatus.PROCESSING,
startedAt: '2026-06-10T09:00:00.000Z',
@@ -24,7 +24,7 @@ describe('shouldCompleteCallRecordingIngestion', () => {
).toBe(true);
expect(
- shouldCompleteCallRecordingIngestion({
+ shouldCompleteCallRecordingImport({
current: {
status: CallRecordingStatus.PROCESSING,
endedAt: '2026-06-10T10:00:00.000Z',
@@ -37,7 +37,7 @@ describe('shouldCompleteCallRecordingIngestion', () => {
).toBe(false);
expect(
- shouldCompleteCallRecordingIngestion({
+ shouldCompleteCallRecordingImport({
current: {
status: CallRecordingStatus.PROCESSING,
transcript: filledTranscript,
@@ -52,7 +52,7 @@ describe('shouldCompleteCallRecordingIngestion', () => {
).toBe(true);
expect(
- shouldCompleteCallRecordingIngestion({
+ shouldCompleteCallRecordingImport({
current: {
status: CallRecordingStatus.PROCESSING,
startedAt: '2026-06-10T10:00:00.000Z',
@@ -68,7 +68,7 @@ describe('shouldCompleteCallRecordingIngestion', () => {
it('completes when a missing media file is marked too large', () => {
expect(
- shouldCompleteCallRecordingIngestion({
+ shouldCompleteCallRecordingImport({
current: {
status: CallRecordingStatus.PROCESSING,
startedAt: '2026-06-10T09:00:00.000Z',
@@ -83,7 +83,7 @@ describe('shouldCompleteCallRecordingIngestion', () => {
).toBe(true);
expect(
- shouldCompleteCallRecordingIngestion({
+ shouldCompleteCallRecordingImport({
current: {
status: CallRecordingStatus.PROCESSING,
startedAt: '2026-06-10T09:00:00.000Z',
@@ -99,7 +99,7 @@ describe('shouldCompleteCallRecordingIngestion', () => {
it('does not complete a persisted failed recording', () => {
expect(
- shouldCompleteCallRecordingIngestion({
+ shouldCompleteCallRecordingImport({
current: {
status: CallRecordingStatus.FAILED,
startedAt: '2026-06-10T09:00:00.000Z',
@@ -115,7 +115,7 @@ describe('shouldCompleteCallRecordingIngestion', () => {
it('does not complete when the incoming update marks the recording as failed', () => {
expect(
- shouldCompleteCallRecordingIngestion({
+ shouldCompleteCallRecordingImport({
current: {
status: CallRecordingStatus.PROCESSING,
startedAt: '2026-06-10T09:00:00.000Z',
diff --git a/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/build-bot-image.util.ts b/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/build-bot-image.util.ts
index 396e2f3a2d..0362de4d84 100644
--- a/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/build-bot-image.util.ts
+++ b/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/build-bot-image.util.ts
@@ -107,13 +107,9 @@ const composeJpeg = ({
.jpeg({ quality, mozjpeg: true })
.toBuffer();
-const buildRecordingStatusBadge = (
- sharp: SharpFactory,
-): Promise => {
- const badgeCornerRadius =
- RECALL_BOT_IMAGE_RECORDING_STATUS_BADGE_HEIGHT / 2;
- const recordingDotCenter =
- RECALL_BOT_IMAGE_RECORDING_STATUS_BADGE_HEIGHT / 2;
+const buildRecordingStatusBadge = (sharp: SharpFactory): Promise => {
+ const badgeCornerRadius = RECALL_BOT_IMAGE_RECORDING_STATUS_BADGE_HEIGHT / 2;
+ const recordingDotCenter = RECALL_BOT_IMAGE_RECORDING_STATUS_BADGE_HEIGHT / 2;
const recordingDotRadius =
RECALL_BOT_IMAGE_RECORDING_STATUS_BADGE_DOT_DIAMETER / 2;
const recordingStatusTextBaseline =
diff --git a/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/build-recall-bot-automatic-video-output.util.ts b/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/build-recall-bot-automatic-video-output.util.ts
index 3826e1a636..59b536f30c 100644
--- a/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/build-recall-bot-automatic-video-output.util.ts
+++ b/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/build-recall-bot-automatic-video-output.util.ts
@@ -32,8 +32,7 @@ export const buildRecallBotAutomaticVideoOutput = async (): Promise<
logoBuffer,
background,
withRecordingStatusBadge: true,
- })) ??
- notRecordingImage;
+ })) ?? notRecordingImage;
return {
in_call_recording: { kind: 'jpeg', b64_data: recordingImage },
diff --git a/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/is-call-recording-ingestion-complete.util.ts b/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/is-call-recording-import-complete.util.ts
similarity index 94%
rename from packages/twenty-apps/public/call-recorder/src/logic-functions/domain/is-call-recording-ingestion-complete.util.ts
rename to packages/twenty-apps/public/call-recorder/src/logic-functions/domain/is-call-recording-import-complete.util.ts
index 0bc970bcb7..6bc0d8ddb1 100644
--- a/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/is-call-recording-ingestion-complete.util.ts
+++ b/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/is-call-recording-import-complete.util.ts
@@ -4,7 +4,7 @@ import { type FilesFieldValue } from 'src/logic-functions/types/files-field-valu
import { parseMediaFileTooLargeMarkers } from 'src/logic-functions/domain/parse-media-file-too-large-markers.util';
import { parseTranscriptMarker } from 'src/logic-functions/domain/parse-transcript-marker.util';
-export const isCallRecordingIngestionComplete = ({
+export const isCallRecordingImportComplete = ({
transcript,
audio,
video,
diff --git a/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/map-recall-status-code-to-call-recording-status.util.ts b/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/map-recall-status-code-to-call-recording-status.util.ts
index 9af31afc32..aee5e3b413 100644
--- a/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/map-recall-status-code-to-call-recording-status.util.ts
+++ b/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/map-recall-status-code-to-call-recording-status.util.ts
@@ -11,7 +11,7 @@ export const mapRecallStatusCodeToCallRecordingStatus = (
case 'recording_permission_allowed':
case 'in_call_recording':
return CallRecordingStatus.RECORDING;
- // 'done' stays PROCESSING: COMPLETED is set only after all artifacts are ingested.
+ // 'done' stays PROCESSING: COMPLETED is set only after all artifacts are imported.
case 'call_ended':
case 'analysis_done':
case 'done':
diff --git a/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/should-complete-call-recording-ingestion.util.ts b/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/should-complete-call-recording-import.util.ts
similarity index 85%
rename from packages/twenty-apps/public/call-recorder/src/logic-functions/domain/should-complete-call-recording-ingestion.util.ts
rename to packages/twenty-apps/public/call-recorder/src/logic-functions/domain/should-complete-call-recording-import.util.ts
index cf1c711401..c6a25f94e3 100644
--- a/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/should-complete-call-recording-ingestion.util.ts
+++ b/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/should-complete-call-recording-import.util.ts
@@ -1,10 +1,10 @@
import { CallRecordingStatus } from 'src/logic-functions/constants/call-recording-status';
import { type FilesFieldValue } from 'src/logic-functions/types/files-field-value.type';
import { computeCallRecordingCharge } from 'src/logic-functions/domain/compute-call-recording-charge.util';
-import { isCallRecordingIngestionComplete } from 'src/logic-functions/domain/is-call-recording-ingestion-complete.util';
+import { isCallRecordingImportComplete } from 'src/logic-functions/domain/is-call-recording-import-complete.util';
import { type CallRecordingUpdateFields } from 'src/logic-functions/types/call-recording-update-fields.type';
-export const shouldCompleteCallRecordingIngestion = ({
+export const shouldCompleteCallRecordingImport = ({
current,
updateData,
}: {
@@ -26,7 +26,7 @@ export const shouldCompleteCallRecordingIngestion = ({
startedAt: updateData.startedAt ?? current.startedAt,
endedAt: updateData.endedAt ?? current.endedAt,
}) !== undefined &&
- isCallRecordingIngestionComplete({
+ isCallRecordingImportComplete({
transcript: updateData.transcript ?? current.transcript,
audio: updateData.audio ?? current.audio,
video: updateData.video ?? current.video,
diff --git a/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/__tests__/reap-orphaned-call-recorders.test.ts b/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/__tests__/cleanup-orphaned-recall-bots.test.ts
similarity index 91%
rename from packages/twenty-apps/public/call-recorder/src/logic-functions/flows/__tests__/reap-orphaned-call-recorders.test.ts
rename to packages/twenty-apps/public/call-recorder/src/logic-functions/flows/__tests__/cleanup-orphaned-recall-bots.test.ts
index c46d7f47c3..33270ab0b9 100644
--- a/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/__tests__/reap-orphaned-call-recorders.test.ts
+++ b/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/__tests__/cleanup-orphaned-recall-bots.test.ts
@@ -1,7 +1,7 @@
import { type CoreApiClient } from 'twenty-client-sdk/core';
import { beforeEach, describe, expect, it, vi } from 'vitest';
-import { reapOrphanedCallRecorders } from 'src/logic-functions/flows/reap-orphaned-call-recorders.util';
+import { cleanupOrphanedRecallBots } from 'src/logic-functions/flows/cleanup-orphaned-recall-bots.util';
const listScheduledRecallBotsMock = vi.hoisted(() => vi.fn());
const cancelRecallBotMock = vi.hoisted(() => vi.fn());
@@ -89,7 +89,7 @@ const buildCurrentWorkspaceBot = ({
twentyWorkspaceId: CURRENT_WORKSPACE_ID,
});
-describe('reapOrphanedCallRecorders', () => {
+describe('cleanupOrphanedRecallBots', () => {
beforeEach(() => {
vi.spyOn(console, 'warn').mockImplementation(() => {});
getCurrentWorkspaceIdMock.mockReset();
@@ -112,7 +112,7 @@ describe('reapOrphanedCallRecorders', () => {
],
});
- const result = await reapOrphanedCallRecorders({
+ const result = await cleanupOrphanedRecallBots({
client: buildClient([
{
id: 'call-recording-1',
@@ -142,7 +142,7 @@ describe('reapOrphanedCallRecorders', () => {
],
});
- const result = await reapOrphanedCallRecorders({
+ const result = await cleanupOrphanedRecallBots({
client: buildClient([
{
id: 'call-recording-1',
@@ -178,7 +178,7 @@ describe('reapOrphanedCallRecorders', () => {
],
});
- const result = await reapOrphanedCallRecorders({
+ const result = await cleanupOrphanedRecallBots({
client: buildClient([
{
id: 'call-recording-1',
@@ -211,7 +211,7 @@ describe('reapOrphanedCallRecorders', () => {
],
});
- const result = await reapOrphanedCallRecorders({
+ const result = await cleanupOrphanedRecallBots({
client: buildClient([]),
joinAtAfter: JOIN_AT_AFTER,
joinAtBefore: JOIN_AT_BEFORE,
@@ -234,7 +234,7 @@ describe('reapOrphanedCallRecorders', () => {
],
});
- const result = await reapOrphanedCallRecorders({
+ const result = await cleanupOrphanedRecallBots({
client: buildClient([
{
id: 'call-recording-1',
@@ -259,7 +259,7 @@ describe('reapOrphanedCallRecorders', () => {
bots: [buildBot({ id: 'unrelated-bot' })],
});
- const result = await reapOrphanedCallRecorders({
+ const result = await cleanupOrphanedRecallBots({
client: buildClient([]),
joinAtAfter: JOIN_AT_AFTER,
joinAtBefore: JOIN_AT_BEFORE,
@@ -283,7 +283,7 @@ describe('reapOrphanedCallRecorders', () => {
],
});
- const result = await reapOrphanedCallRecorders({
+ const result = await cleanupOrphanedRecallBots({
client: buildClient([]),
joinAtAfter: JOIN_AT_AFTER,
joinAtBefore: JOIN_AT_BEFORE,
@@ -308,7 +308,7 @@ describe('reapOrphanedCallRecorders', () => {
],
});
- const result = await reapOrphanedCallRecorders({
+ const result = await cleanupOrphanedRecallBots({
client: buildClient([]),
joinAtAfter: JOIN_AT_AFTER,
joinAtBefore: JOIN_AT_BEFORE,
@@ -332,7 +332,7 @@ describe('reapOrphanedCallRecorders', () => {
],
});
- const result = await reapOrphanedCallRecorders({
+ const result = await cleanupOrphanedRecallBots({
client: buildClient([]),
joinAtAfter: JOIN_AT_AFTER,
joinAtBefore: JOIN_AT_BEFORE,
@@ -363,7 +363,7 @@ describe('reapOrphanedCallRecorders', () => {
errorMessage: 'Recall API responded with HTTP 409',
});
- const result = await reapOrphanedCallRecorders({
+ const result = await cleanupOrphanedRecallBots({
client: buildClient([]),
joinAtAfter: JOIN_AT_AFTER,
joinAtBefore: JOIN_AT_BEFORE,
@@ -378,14 +378,14 @@ describe('reapOrphanedCallRecorders', () => {
});
});
- it('reports nothing reaped when listing Recall bots fails', async () => {
+ it('reports nothing canceled when listing Recall bots fails', async () => {
listScheduledRecallBotsMock.mockResolvedValue({
ok: false,
status: 500,
errorMessage: 'Recall API responded with HTTP 500',
});
- const result = await reapOrphanedCallRecorders({
+ const result = await cleanupOrphanedRecallBots({
client: buildClient([]),
joinAtAfter: JOIN_AT_AFTER,
joinAtBefore: JOIN_AT_BEFORE,
@@ -398,7 +398,7 @@ describe('reapOrphanedCallRecorders', () => {
expect(cancelRecallBotMock).not.toHaveBeenCalled();
});
- it('skips reaping when the current workspace cannot be resolved', async () => {
+ it('skips cancellation when the current workspace cannot be resolved', async () => {
getCurrentWorkspaceIdMock.mockReturnValue(undefined);
listScheduledRecallBotsMock.mockResolvedValue({
ok: true,
@@ -410,7 +410,7 @@ describe('reapOrphanedCallRecorders', () => {
],
});
- const result = await reapOrphanedCallRecorders({
+ const result = await cleanupOrphanedRecallBots({
client: buildClient([]),
joinAtAfter: JOIN_AT_AFTER,
joinAtBefore: JOIN_AT_BEFORE,
diff --git a/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/__tests__/complete-and-charge-call-recording.test.ts b/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/__tests__/complete-and-charge-call-recording.test.ts
index 42c48e63cf..b44f4604c9 100644
--- a/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/__tests__/complete-and-charge-call-recording.test.ts
+++ b/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/__tests__/complete-and-charge-call-recording.test.ts
@@ -1,12 +1,12 @@
import { beforeEach, describe, expect, it, vi } from 'vitest';
-const completeCallRecordingIngestionMock = vi.hoisted(() => vi.fn());
+const completeCallRecordingImportMock = vi.hoisted(() => vi.fn());
const chargeCompletedCallRecordingMock = vi.hoisted(() => vi.fn());
vi.mock(
- 'src/logic-functions/data/complete-call-recording-ingestion.util',
+ 'src/logic-functions/data/complete-call-recording-import.util',
() => ({
- completeCallRecordingIngestion: completeCallRecordingIngestionMock,
+ completeCallRecordingImport: completeCallRecordingImportMock,
}),
);
@@ -25,7 +25,7 @@ describe('completeAndChargeCallRecording', () => {
});
it('charges exactly once when this path wins the completion claim', async () => {
- completeCallRecordingIngestionMock.mockResolvedValue(true);
+ completeCallRecordingImportMock.mockResolvedValue(true);
const claimed = await completeAndChargeCallRecording({} as never, {
id: 'call-recording-1',
@@ -34,7 +34,7 @@ describe('completeAndChargeCallRecording', () => {
});
expect(claimed).toBe(true);
- expect(completeCallRecordingIngestionMock).toHaveBeenCalledWith(
+ expect(completeCallRecordingImportMock).toHaveBeenCalledWith(
{},
{ id: 'call-recording-1' },
);
@@ -47,7 +47,7 @@ describe('completeAndChargeCallRecording', () => {
});
it('does not charge when another path already completed the recording', async () => {
- completeCallRecordingIngestionMock.mockResolvedValue(false);
+ completeCallRecordingImportMock.mockResolvedValue(false);
const claimed = await completeAndChargeCallRecording({} as never, {
id: 'call-recording-1',
diff --git a/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/__tests__/converge-diverged-call-recordings.test.ts b/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/__tests__/converge-diverged-call-recordings.test.ts
index 660e969574..3747012adf 100644
--- a/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/__tests__/converge-diverged-call-recordings.test.ts
+++ b/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/__tests__/converge-diverged-call-recordings.test.ts
@@ -7,7 +7,7 @@ const getRecallBotMock = vi.hoisted(() => vi.fn());
const listRecallTranscriptsMock = vi.hoisted(() => vi.fn());
const createAsyncRecallTranscriptMock = vi.hoisted(() => vi.fn());
const downloadTranscriptMock = vi.hoisted(() => vi.fn());
-const ingestCallRecordingMediaMock = vi.hoisted(() => vi.fn());
+const importCallRecordingMediaMock = vi.hoisted(() => vi.fn());
const chargeCompletedCallRecordingMock = vi.hoisted(() => vi.fn());
vi.mock('src/logic-functions/recall-api/get-recall-bot.util', () => ({
@@ -29,8 +29,8 @@ vi.mock('src/logic-functions/flows/download-transcript.util', () => ({
downloadTranscript: downloadTranscriptMock,
}));
-vi.mock('src/logic-functions/flows/ingest-call-recording-media.util', () => ({
- ingestCallRecordingMedia: ingestCallRecordingMediaMock,
+vi.mock('src/logic-functions/flows/import-call-recording-media.util', () => ({
+ importCallRecordingMedia: importCallRecordingMediaMock,
}));
vi.mock(
@@ -115,8 +115,8 @@ describe('convergeDivergedCallRecordings', () => {
});
downloadTranscriptMock.mockReset();
downloadTranscriptMock.mockResolvedValue({ outcome: 'pending' });
- ingestCallRecordingMediaMock.mockReset();
- ingestCallRecordingMediaMock.mockResolvedValue({});
+ importCallRecordingMediaMock.mockReset();
+ importCallRecordingMediaMock.mockResolvedValue({});
chargeCompletedCallRecordingMock.mockReset();
chargeCompletedCallRecordingMock.mockResolvedValue(undefined);
});
@@ -149,7 +149,7 @@ describe('convergeDivergedCallRecordings', () => {
expect(getRecallBotMock).toHaveBeenCalledWith({
externalBotId: 'recall-bot-1',
});
- expect(ingestCallRecordingMediaMock).toHaveBeenCalledWith({
+ expect(importCallRecordingMediaMock).toHaveBeenCalledWith({
callRecordingId: 'call-recording-1',
externalRecordingId: 'recall-recording-1',
hasAudio: false,
@@ -201,7 +201,7 @@ describe('convergeDivergedCallRecordings', () => {
});
expect(listRecallTranscriptsMock).not.toHaveBeenCalled();
- expect(ingestCallRecordingMediaMock).not.toHaveBeenCalled();
+ expect(importCallRecordingMediaMock).not.toHaveBeenCalled();
expect(client.mutations).toEqual([
{
id: 'call-recording-1',
@@ -230,7 +230,7 @@ describe('convergeDivergedCallRecordings', () => {
],
},
});
- ingestCallRecordingMediaMock.mockResolvedValue({
+ importCallRecordingMediaMock.mockResolvedValue({
audio: [{ fileId: 'file-audio-1', label: 'audio.mp3' }],
video: [{ fileId: 'file-video-1', label: 'video.mp4' }],
});
@@ -295,7 +295,7 @@ describe('convergeDivergedCallRecordings', () => {
],
},
});
- ingestCallRecordingMediaMock.mockResolvedValue({
+ importCallRecordingMediaMock.mockResolvedValue({
audio: [{ fileId: 'file-audio-1', label: 'audio.mp3' }],
callRecorderFailureReason: 'video_file_too_large',
});
@@ -368,7 +368,7 @@ describe('convergeDivergedCallRecordings', () => {
now: NOW,
});
- expect(ingestCallRecordingMediaMock).toHaveBeenCalledWith({
+ expect(importCallRecordingMediaMock).toHaveBeenCalledWith({
callRecordingId: 'call-recording-1',
externalRecordingId: 'recall-recording-1',
hasAudio: true,
@@ -404,7 +404,7 @@ describe('convergeDivergedCallRecordings', () => {
],
},
});
- ingestCallRecordingMediaMock.mockResolvedValue({
+ importCallRecordingMediaMock.mockResolvedValue({
audio: [{ fileId: 'file-audio-1', label: 'audio.mp3' }],
callRecorderFailureReason: 'video_file_too_large',
});
diff --git a/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/__tests__/handle-recall-webhook.test.ts b/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/__tests__/handle-recall-webhook.test.ts
index d21742945a..d02acc7c13 100644
--- a/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/__tests__/handle-recall-webhook.test.ts
+++ b/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/__tests__/handle-recall-webhook.test.ts
@@ -25,7 +25,7 @@ const getRecallBotMock = vi.hoisted(() => vi.fn());
const listRecallTranscriptsMock = vi.hoisted(() => vi.fn());
const createAsyncRecallTranscriptMock = vi.hoisted(() => vi.fn());
const retrieveRecallTranscriptMock = vi.hoisted(() => vi.fn());
-const ingestCallRecordingMediaMock = vi.hoisted(() => vi.fn());
+const importCallRecordingMediaMock = vi.hoisted(() => vi.fn());
const chargeCompletedCallRecordingMock = vi.hoisted(() => vi.fn());
vi.mock('src/logic-functions/recall-api/get-recall-bot.util', () => ({
@@ -50,8 +50,8 @@ vi.mock(
}),
);
-vi.mock('src/logic-functions/flows/ingest-call-recording-media.util', () => ({
- ingestCallRecordingMedia: ingestCallRecordingMediaMock,
+vi.mock('src/logic-functions/flows/import-call-recording-media.util', () => ({
+ importCallRecordingMedia: importCallRecordingMediaMock,
}));
vi.mock(
@@ -168,8 +168,8 @@ describe('handleRecallWebhook', () => {
status: null,
errorMessage: 'transcript retrieval disabled in test',
});
- ingestCallRecordingMediaMock.mockReset();
- ingestCallRecordingMediaMock.mockResolvedValue({});
+ importCallRecordingMediaMock.mockReset();
+ importCallRecordingMediaMock.mockResolvedValue({});
chargeCompletedCallRecordingMock.mockReset();
chargeCompletedCallRecordingMock.mockResolvedValue(undefined);
});
@@ -882,12 +882,12 @@ describe('handleRecallWebhook', () => {
]);
});
- it('ingests media on recording.done and completes once all artifacts are present', async () => {
+ it('imports media on recording.done and completes once all artifacts are present', async () => {
getRecallBotMock.mockResolvedValue({
ok: true,
bot: { id: 'recall-bot-1' },
});
- ingestCallRecordingMediaMock.mockResolvedValue({
+ importCallRecordingMediaMock.mockResolvedValue({
audio: [{ fileId: 'file-audio-1', label: 'audio.mp3' }],
video: [{ fileId: 'file-video-1', label: 'video.mp4' }],
});
@@ -908,7 +908,7 @@ describe('handleRecallWebhook', () => {
body: buildRecordingDoneWebhookBody(),
});
- expect(ingestCallRecordingMediaMock).toHaveBeenCalledWith({
+ expect(importCallRecordingMediaMock).toHaveBeenCalledWith({
callRecordingId: 'call-recording-1',
externalRecordingId: 'recall-recording-1',
hasAudio: false,
@@ -941,7 +941,7 @@ describe('handleRecallWebhook', () => {
ok: true,
bot: { id: 'recall-bot-1' },
});
- ingestCallRecordingMediaMock.mockResolvedValue({
+ importCallRecordingMediaMock.mockResolvedValue({
audio: [{ fileId: 'file-audio-1', label: 'audio.mp3' }],
callRecorderFailureReason: 'video_file_too_large',
});
@@ -995,7 +995,7 @@ describe('handleRecallWebhook', () => {
ok: true,
bot: { id: 'recall-bot-1' },
});
- ingestCallRecordingMediaMock.mockResolvedValue({
+ importCallRecordingMediaMock.mockResolvedValue({
audio: [{ fileId: 'file-audio-1', label: 'audio.mp3' }],
callRecorderFailureReason: 'video_file_too_large',
});
@@ -1045,7 +1045,7 @@ describe('handleRecallWebhook', () => {
ok: true,
bot: { id: 'recall-bot-1' },
});
- ingestCallRecordingMediaMock.mockResolvedValue({
+ importCallRecordingMediaMock.mockResolvedValue({
audio: [{ fileId: 'file-audio-1', label: 'audio.mp3' }],
});
createAsyncRecallTranscriptMock.mockResolvedValue({
@@ -1135,7 +1135,7 @@ describe('handleRecallWebhook', () => {
expect(chargeCompletedCallRecordingMock).not.toHaveBeenCalled();
});
- it('completes and charges on transcript.done when media is already ingested', async () => {
+ it('completes and charges on transcript.done when media is already imported', async () => {
const transcriptContent = [
{
participant: { id: 1, name: 'Alice' },
diff --git a/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/__tests__/ingest-call-recording-media.test.ts b/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/__tests__/import-call-recording-media.test.ts
similarity index 94%
rename from packages/twenty-apps/public/call-recorder/src/logic-functions/flows/__tests__/ingest-call-recording-media.test.ts
rename to packages/twenty-apps/public/call-recorder/src/logic-functions/flows/__tests__/import-call-recording-media.test.ts
index 08a8372fe3..80824fda56 100644
--- a/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/__tests__/ingest-call-recording-media.test.ts
+++ b/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/__tests__/import-call-recording-media.test.ts
@@ -2,7 +2,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { CALL_RECORDING_VIDEO_FIELD_UNIVERSAL_IDENTIFIER } from 'src/constants/call-recording-video-field-universal-identifier';
import { CALL_RECORDER_MAX_MEDIA_FILE_SIZE_MB_ENV_VAR_NAME } from 'src/logic-functions/constants/call-recorder-max-media-file-size-mb-env-var-name';
-import { ingestCallRecordingMedia } from 'src/logic-functions/flows/ingest-call-recording-media.util';
+import { importCallRecordingMedia } from 'src/logic-functions/flows/import-call-recording-media.util';
const mutationMock = vi.hoisted(() => vi.fn());
const getRecallRecordingMock = vi.hoisted(() => vi.fn());
@@ -147,7 +147,7 @@ const getUploadBridgeCall = (fileName: string) =>
([uploadInput]) => uploadInput.fileName === fileName,
);
-describe('ingestCallRecordingMedia', () => {
+describe('importCallRecordingMedia', () => {
beforeEach(() => {
vi.spyOn(console, 'warn').mockImplementation(() => {});
vi.spyOn(console, 'log').mockImplementation(() => {});
@@ -179,7 +179,7 @@ describe('ingestCallRecordingMedia', () => {
});
it('streams and uploads every missing artifact', async () => {
- const updateFields = await ingestCallRecordingMedia({
+ const updateFields = await importCallRecordingMedia({
callRecordingId: 'call-recording-1',
externalRecordingId: 'recall-recording-1',
hasAudio: false,
@@ -211,7 +211,7 @@ describe('ingestCallRecordingMedia', () => {
});
it('declares the presigned upload with the download size, folder and field identifier', async () => {
- await ingestCallRecordingMedia({
+ await importCallRecordingMedia({
callRecordingId: 'call-recording-1',
externalRecordingId: 'recall-recording-1',
hasAudio: true,
@@ -241,7 +241,7 @@ describe('ingestCallRecordingMedia', () => {
});
it('skips artifacts already on the record', async () => {
- const updateFields = await ingestCallRecordingMedia({
+ const updateFields = await importCallRecordingMedia({
callRecordingId: 'call-recording-1',
externalRecordingId: 'recall-recording-1',
hasAudio: false,
@@ -255,7 +255,7 @@ describe('ingestCallRecordingMedia', () => {
});
it('does not fetch the recording when both artifacts are present', async () => {
- const updateFields = await ingestCallRecordingMedia({
+ const updateFields = await importCallRecordingMedia({
callRecordingId: 'call-recording-1',
externalRecordingId: 'recall-recording-1',
hasAudio: true,
@@ -289,7 +289,7 @@ describe('ingestCallRecordingMedia', () => {
},
});
- const updateFields = await ingestCallRecordingMedia({
+ const updateFields = await importCallRecordingMedia({
callRecordingId: 'call-recording-1',
externalRecordingId: 'recall-recording-1',
hasAudio: false,
@@ -318,7 +318,7 @@ describe('ingestCallRecordingMedia', () => {
},
});
- const updateFields = await ingestCallRecordingMedia({
+ const updateFields = await importCallRecordingMedia({
callRecordingId: 'call-recording-1',
externalRecordingId: 'recall-recording-1',
hasAudio: false,
@@ -343,7 +343,7 @@ describe('ingestCallRecordingMedia', () => {
recording: { id: 'recall-recording-1' },
});
- const updateFields = await ingestCallRecordingMedia({
+ const updateFields = await importCallRecordingMedia({
callRecordingId: 'call-recording-1',
externalRecordingId: 'recall-recording-1',
hasAudio: false,
@@ -361,7 +361,7 @@ describe('ingestCallRecordingMedia', () => {
errorMessage: 'recording boom',
});
- const updateFields = await ingestCallRecordingMedia({
+ const updateFields = await importCallRecordingMedia({
callRecordingId: 'call-recording-1',
externalRecordingId: 'recall-recording-1',
hasAudio: false,
@@ -388,7 +388,7 @@ describe('ingestCallRecordingMedia', () => {
},
});
- const updateFields = await ingestCallRecordingMedia({
+ const updateFields = await importCallRecordingMedia({
callRecordingId: 'call-recording-1',
externalRecordingId: 'recall-recording-1',
hasAudio: false,
@@ -421,7 +421,7 @@ describe('ingestCallRecordingMedia', () => {
},
});
- const updateFields = await ingestCallRecordingMedia({
+ const updateFields = await importCallRecordingMedia({
callRecordingId: 'call-recording-1',
externalRecordingId: 'recall-recording-1',
hasAudio: false,
@@ -445,7 +445,7 @@ describe('ingestCallRecordingMedia', () => {
},
});
- const updateFields = await ingestCallRecordingMedia({
+ const updateFields = await importCallRecordingMedia({
callRecordingId: 'call-recording-1',
externalRecordingId: 'recall-recording-1',
hasAudio: false,
@@ -471,7 +471,7 @@ describe('ingestCallRecordingMedia', () => {
},
});
- const updateFields = await ingestCallRecordingMedia({
+ const updateFields = await importCallRecordingMedia({
callRecordingId: 'call-recording-1',
externalRecordingId: 'recall-recording-1',
hasAudio: true,
diff --git a/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/__tests__/reconcile-call-recorder.test.ts b/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/__tests__/reconcile-call-recorder.test.ts
index fb6e7f65e5..e5524b6734 100644
--- a/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/__tests__/reconcile-call-recorder.test.ts
+++ b/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/__tests__/reconcile-call-recorder.test.ts
@@ -929,7 +929,7 @@ describe('reconcileCallRecorderForCalendarEventIds', () => {
expect(rescheduleRecallBotMock).toHaveBeenCalledWith(
expect.objectContaining({ externalBotId: 'recall-bot-stale' }),
);
- // The event path no longer re-creates the bot; the stale id is cleared and the cron heals the botless row.
+ // The event path no longer re-creates the bot; the stale id is cleared and the cron schedules a bot for the pending row.
expect(scheduleRecallBotMock).not.toHaveBeenCalled();
expect(client.callRecordings).toEqual([
expect.objectContaining({
diff --git a/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/__tests__/heal-call-recordings-missing-bot.test.ts b/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/__tests__/schedule-recall-bots-for-pending-call-recordings.test.ts
similarity index 88%
rename from packages/twenty-apps/public/call-recorder/src/logic-functions/flows/__tests__/heal-call-recordings-missing-bot.test.ts
rename to packages/twenty-apps/public/call-recorder/src/logic-functions/flows/__tests__/schedule-recall-bots-for-pending-call-recordings.test.ts
index 4d732bd9c1..edbd5332e3 100644
--- a/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/__tests__/heal-call-recordings-missing-bot.test.ts
+++ b/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/__tests__/schedule-recall-bots-for-pending-call-recordings.test.ts
@@ -1,7 +1,7 @@
import { type CoreApiClient } from 'twenty-client-sdk/core';
import { beforeEach, describe, expect, it, vi } from 'vitest';
-import { healCallRecordingsMissingBot } from 'src/logic-functions/flows/heal-call-recordings-missing-bot.util';
+import { scheduleRecallBotsForPendingCallRecordings } from 'src/logic-functions/flows/schedule-recall-bots-for-pending-call-recordings.util';
const scheduleRecallBotMock = vi.hoisted(() => vi.fn());
const getCurrentWorkspaceIdMock = vi.hoisted(() => vi.fn());
@@ -108,7 +108,7 @@ const buildConnection = (nodes: Node[]) => ({
edges: nodes.map((node) => ({ node })),
});
-const buildBotlessCallRecording = (
+const buildPendingCallRecording = (
overrides: Partial = {},
): CallRecordingNode => ({
id: 'call-recording-1',
@@ -130,7 +130,7 @@ const buildCalendarEvent = (
...overrides,
});
-describe('healCallRecordingsMissingBot', () => {
+describe('scheduleRecallBotsForPendingCallRecordings', () => {
beforeEach(() => {
vi.spyOn(console, 'warn').mockImplementation(() => {});
getCurrentWorkspaceIdMock.mockReset();
@@ -142,13 +142,13 @@ describe('healCallRecordingsMissingBot', () => {
});
});
- it('schedules a bot and writes the id for an upcoming botless recording', async () => {
+ it('schedules a bot and writes the id for an upcoming pending recording', async () => {
const client = new FakeCoreApiClient({
- callRecordings: [buildBotlessCallRecording()],
+ callRecordings: [buildPendingCallRecording()],
calendarEvents: [buildCalendarEvent()],
});
- const result = await healCallRecordingsMissingBot({
+ const result = await scheduleRecallBotsForPendingCallRecordings({
client: client as unknown as CoreApiClient,
now: NOW,
});
@@ -172,11 +172,11 @@ describe('healCallRecordingsMissingBot', () => {
errorMessage: 'Recall API responded with HTTP 500',
});
const client = new FakeCoreApiClient({
- callRecordings: [buildBotlessCallRecording()],
+ callRecordings: [buildPendingCallRecording()],
calendarEvents: [buildCalendarEvent()],
});
- const result = await healCallRecordingsMissingBot({
+ const result = await scheduleRecallBotsForPendingCallRecordings({
client: client as unknown as CoreApiClient,
now: NOW,
});
@@ -188,7 +188,7 @@ describe('healCallRecordingsMissingBot', () => {
it('skips a recording whose meeting has already ended', async () => {
const client = new FakeCoreApiClient({
- callRecordings: [buildBotlessCallRecording()],
+ callRecordings: [buildPendingCallRecording()],
calendarEvents: [
buildCalendarEvent({
startsAt: PAST_STARTS_AT,
@@ -197,7 +197,7 @@ describe('healCallRecordingsMissingBot', () => {
],
});
- const result = await healCallRecordingsMissingBot({
+ const result = await scheduleRecallBotsForPendingCallRecordings({
client: client as unknown as CoreApiClient,
now: NOW,
});
@@ -209,12 +209,12 @@ describe('healCallRecordingsMissingBot', () => {
it('does nothing when every scheduled recording already has a bot', async () => {
const client = new FakeCoreApiClient({
callRecordings: [
- buildBotlessCallRecording({ externalBotId: 'recall-bot-existing' }),
+ buildPendingCallRecording({ externalBotId: 'recall-bot-existing' }),
],
calendarEvents: [buildCalendarEvent()],
});
- const result = await healCallRecordingsMissingBot({
+ const result = await scheduleRecallBotsForPendingCallRecordings({
client: client as unknown as CoreApiClient,
now: NOW,
});
diff --git a/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/reap-orphaned-call-recorders.util.ts b/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/cleanup-orphaned-recall-bots.util.ts
similarity index 93%
rename from packages/twenty-apps/public/call-recorder/src/logic-functions/flows/reap-orphaned-call-recorders.util.ts
rename to packages/twenty-apps/public/call-recorder/src/logic-functions/flows/cleanup-orphaned-recall-bots.util.ts
index 42445a3aa7..57448b498f 100644
--- a/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/reap-orphaned-call-recorders.util.ts
+++ b/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/cleanup-orphaned-recall-bots.util.ts
@@ -14,13 +14,13 @@ import {
type RecallScheduledBot,
} from 'src/logic-functions/recall-api/list-scheduled-recall-bots.util';
-export type ReapOrphanedCallRecordersResult = {
+export type CleanupOrphanedRecallBotsResult = {
scannedBotCount: number;
canceledExternalBotIds: string[];
};
// Bots no open CallRecording request claims would still join; cancel them on Recall.
-export const reapOrphanedCallRecorders = async ({
+export const cleanupOrphanedRecallBots = async ({
client,
joinAtAfter,
joinAtBefore,
@@ -28,7 +28,7 @@ export const reapOrphanedCallRecorders = async ({
client: CoreApiClient;
joinAtAfter: string;
joinAtBefore: string;
-}): Promise => {
+}): Promise => {
const listResult = await listScheduledRecallBots({
joinAtAfter,
joinAtBefore,
@@ -36,7 +36,7 @@ export const reapOrphanedCallRecorders = async ({
if (!listResult.ok) {
console.warn(
- `[call-recorder] failed to list Recall bots for orphan reaping: ${listResult.errorMessage}`,
+ `[call-recorder] failed to list Recall bots for orphan cancellation: ${listResult.errorMessage}`,
);
return { scannedBotCount: 0, canceledExternalBotIds: [] };
@@ -46,7 +46,7 @@ export const reapOrphanedCallRecorders = async ({
if (isUndefined(currentWorkspaceId)) {
console.warn(
- '[call-recorder] cannot reap orphaned Recall bots: workspace id unavailable',
+ '[call-recorder] cannot cancel orphaned Recall bots: workspace id unavailable',
);
return {
diff --git a/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/complete-and-charge-call-recording.util.ts b/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/complete-and-charge-call-recording.util.ts
index 1c1dff964b..a0ea7a7210 100644
--- a/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/complete-and-charge-call-recording.util.ts
+++ b/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/complete-and-charge-call-recording.util.ts
@@ -1,6 +1,6 @@
import { type CoreApiClient } from 'twenty-client-sdk/core';
-import { completeCallRecordingIngestion } from 'src/logic-functions/data/complete-call-recording-ingestion.util';
+import { completeCallRecordingImport } from 'src/logic-functions/data/complete-call-recording-import.util';
import { chargeCompletedCallRecording } from 'src/logic-functions/flows/charge-completed-call-recording.util';
export const completeAndChargeCallRecording = async (
@@ -15,7 +15,7 @@ export const completeAndChargeCallRecording = async (
endedAt: string | undefined;
},
): Promise => {
- const claimed = await completeCallRecordingIngestion(client, { id });
+ const claimed = await completeCallRecordingImport(client, { id });
if (claimed) {
await chargeCompletedCallRecording({
diff --git a/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/converge-diverged-call-recordings.util.ts b/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/converge-diverged-call-recordings.util.ts
index 019fe609a7..37856aed26 100644
--- a/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/converge-diverged-call-recordings.util.ts
+++ b/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/converge-diverged-call-recordings.util.ts
@@ -7,22 +7,22 @@ import { NON_TERMINAL_CALL_RECORDING_STATUSES } from 'src/logic-functions/consta
import { TWENTY_PAGE_SIZE } from 'src/logic-functions/constants/twenty-page-size';
import { type FilesFieldValue } from 'src/logic-functions/types/files-field-value.type';
import {
- extractRecallBotConvergence,
- type RecallBotConvergence,
-} from 'src/logic-functions/recall-api/extract-recall-bot-convergence.util';
+ extractRecallBotSyncState,
+ type RecallBotSyncState,
+} from 'src/logic-functions/recall-api/extract-recall-bot-sync-state.util';
import {
fetchAllNodes,
type ConnectionPage,
} from 'src/logic-functions/data/fetch-all-nodes.util';
import { getRecallBot } from 'src/logic-functions/recall-api/get-recall-bot.util';
-import { ingestCallRecordingMedia } from 'src/logic-functions/flows/ingest-call-recording-media.util';
+import { importCallRecordingMedia } from 'src/logic-functions/flows/import-call-recording-media.util';
import { isCallRecordingStatusDowngrade } from 'src/logic-functions/domain/is-call-recording-status-downgrade.util';
import { isNonEmptyString } from 'src/logic-functions/utils/is-non-empty-string.util';
import { parseTranscriptMarker } from 'src/logic-functions/domain/parse-transcript-marker.util';
import { persistCallRecordingProgress } from 'src/logic-functions/flows/persist-call-recording-progress.util';
-import { reconcileCallRecordingTranscriptArtifact } from 'src/logic-functions/flows/reconcile-call-recording-transcript-artifact.util';
+import { importCallRecordingTranscript } from 'src/logic-functions/flows/import-call-recording-transcript.util';
import { type ConvergeDivergedCallRecordingsResult } from 'src/logic-functions/flows/converge-diverged-call-recordings-result.type';
-import { shouldCompleteCallRecordingIngestion } from 'src/logic-functions/domain/should-complete-call-recording-ingestion.util';
+import { shouldCompleteCallRecordingImport } from 'src/logic-functions/domain/should-complete-call-recording-import.util';
import { updateCallRecording } from 'src/logic-functions/data/update-call-recording.util';
import { type CallRecordingUpdateFields } from 'src/logic-functions/types/call-recording-update-fields.type';
@@ -251,7 +251,7 @@ const convergeCallRecording = async ({
return;
}
- const convergence = extractRecallBotConvergence(botResult.bot);
+ const convergence = extractRecallBotSyncState(botResult.bot);
const updateData = buildConvergenceFieldUpdates({ candidate, convergence });
const externalRecordingId =
@@ -259,7 +259,7 @@ const convergeCallRecording = async ({
if (convergence.isRecallRecordingDone && !isUndefined(externalRecordingId)) {
const transcriptArtifactResult =
- await reconcileCallRecordingTranscriptArtifact({
+ await importCallRecordingTranscript({
callRecordingId: candidate.id,
currentStatus: candidate.status,
externalRecordingId,
@@ -273,7 +273,7 @@ const convergeCallRecording = async ({
result.requestedTranscriptCallRecordingIds.push(candidate.id);
}
- const mediaIngestionUpdate = await ingestCallRecordingMedia({
+ const mediaIngestionUpdate = await importCallRecordingMedia({
callRecordingId: candidate.id,
externalRecordingId,
hasAudio: isNonEmptyArray(candidate.audio),
@@ -299,12 +299,12 @@ const convergeCallRecording = async ({
Object.assign(updateData, terminalArtifactGateFailureUpdate);
}
- const completesIngestion = shouldCompleteCallRecordingIngestion({
+ const completesImport = shouldCompleteCallRecordingImport({
current: candidate,
updateData,
});
- if (Object.keys(updateData).length === 0 && !completesIngestion) {
+ if (Object.keys(updateData).length === 0 && !completesImport) {
return;
}
@@ -323,7 +323,7 @@ const buildConvergenceFieldUpdates = ({
convergence,
}: {
candidate: DivergedCallRecordingCandidate;
- convergence: RecallBotConvergence;
+ convergence: RecallBotSyncState;
}): CallRecordingUpdateFields => {
const updateData: CallRecordingUpdateFields = {};
@@ -373,7 +373,7 @@ const buildTerminalArtifactGateFailureUpdate = ({
updateData,
}: {
candidate: DivergedCallRecordingCandidate;
- convergence: RecallBotConvergence;
+ convergence: RecallBotSyncState;
externalRecordingId: string | undefined;
updateData: CallRecordingUpdateFields;
}): TerminalArtifactGateFailureUpdate | undefined => {
diff --git a/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/handle-recall-webhook.util.ts b/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/handle-recall-webhook.util.ts
index d6e332b910..347fb2311d 100644
--- a/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/handle-recall-webhook.util.ts
+++ b/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/handle-recall-webhook.util.ts
@@ -6,10 +6,10 @@ import { type FilesFieldValue } from 'src/logic-functions/types/files-field-valu
import { buildFailedTranscriptMarker } from 'src/logic-functions/domain/build-failed-transcript-marker.util';
import { buildTranscriptFailureReason } from 'src/logic-functions/domain/build-transcript-failure-reason.util';
import { downloadTranscript } from 'src/logic-functions/flows/download-transcript.util';
-import { extractRecallBotConvergence } from 'src/logic-functions/recall-api/extract-recall-bot-convergence.util';
+import { extractRecallBotSyncState } from 'src/logic-functions/recall-api/extract-recall-bot-sync-state.util';
import { getRecallBot } from 'src/logic-functions/recall-api/get-recall-bot.util';
import { getString } from 'src/logic-functions/utils/get-string.util';
-import { ingestCallRecordingMedia } from 'src/logic-functions/flows/ingest-call-recording-media.util';
+import { importCallRecordingMedia } from 'src/logic-functions/flows/import-call-recording-media.util';
import { isCallRecordingStatusDowngrade } from 'src/logic-functions/domain/is-call-recording-status-downgrade.util';
import { isRecallRecordingDoneSignal } from 'src/logic-functions/domain/is-recall-recording-done-signal.util';
import { mapRecallStatusCodeToCallRecordingStatus } from 'src/logic-functions/domain/map-recall-status-code-to-call-recording-status.util';
@@ -20,7 +20,7 @@ import {
} from 'src/logic-functions/recall-api/parse-recall-webhook-event.util';
import { parseTranscriptMarker } from 'src/logic-functions/domain/parse-transcript-marker.util';
import { persistCallRecordingProgress } from 'src/logic-functions/flows/persist-call-recording-progress.util';
-import { reconcileCallRecordingTranscriptArtifact } from 'src/logic-functions/flows/reconcile-call-recording-transcript-artifact.util';
+import { importCallRecordingTranscript } from 'src/logic-functions/flows/import-call-recording-transcript.util';
import { updateCallRecording } from 'src/logic-functions/data/update-call-recording.util';
import { type CallRecordingUpdateFields } from 'src/logic-functions/types/call-recording-update-fields.type';
@@ -197,16 +197,16 @@ const handleRecallStatusEvent = async ({
callRecordingStatus,
});
- const mediaIngestionUpdate = await buildMediaIngestionUpdate({
+ const mediaImportUpdate = await buildMediaImportUpdate({
callRecording,
externalRecordingId: externalRecordingIdResolution.externalRecordingId,
});
if (updateData.status === CallRecordingStatus.FAILED) {
- delete mediaIngestionUpdate.callRecorderFailureReason;
+ delete mediaImportUpdate.callRecorderFailureReason;
}
- Object.assign(updateData, mediaIngestionUpdate);
+ Object.assign(updateData, mediaImportUpdate);
const terminalArtifactGateFailureUpdate =
buildTerminalArtifactGateFailureUpdate({
@@ -222,7 +222,7 @@ const handleRecallStatusEvent = async ({
}
}
- const { completesIngestion } = await persistCallRecordingProgress(client, {
+ const { completesImport } = await persistCallRecordingProgress(client, {
id: callRecording.id,
current: callRecording,
updateData,
@@ -234,7 +234,7 @@ const handleRecallStatusEvent = async ({
webhookEvent,
callRecording,
updateData,
- callRecordingStatus: completesIngestion
+ callRecordingStatus: completesImport
? CallRecordingStatus.COMPLETED
: (updateData.status ?? callRecordingStatus),
});
@@ -244,7 +244,7 @@ const handleRecallStatusEvent = async ({
status: 'updated',
event,
callRecordingId: callRecording.id,
- callRecordingStatus: completesIngestion
+ callRecordingStatus: completesImport
? CallRecordingStatus.COMPLETED
: (updateData.status ?? callRecordingStatus),
};
@@ -539,7 +539,7 @@ const hasReachableTranscript = (transcript: unknown): boolean => {
const isTranscriptUnset = (callRecording: MatchedCallRecording): boolean =>
isUndefined(callRecording.transcript);
-const buildMediaIngestionUpdate = async ({
+const buildMediaImportUpdate = async ({
callRecording,
externalRecordingId,
}: {
@@ -560,13 +560,13 @@ const buildMediaIngestionUpdate = async ({
if (isUndefined(externalRecordingId)) {
console.warn(
- `[call-recorder] cannot ingest media for call recording ${callRecording.id}: no Recall recording id available`,
+ `[call-recorder] cannot import media for call recording ${callRecording.id}: no Recall recording id available`,
);
return {};
}
- return ingestCallRecordingMedia({
+ return importCallRecordingMedia({
callRecordingId: callRecording.id,
externalRecordingId,
hasAudio,
@@ -590,7 +590,7 @@ const buildTranscriptArtifactUpdate = async ({
}
const transcriptArtifactResult =
- await reconcileCallRecordingTranscriptArtifact({
+ await importCallRecordingTranscript({
callRecordingId: callRecording.id,
currentStatus: callRecording.status,
externalRecordingId,
@@ -641,7 +641,7 @@ const fetchExternalRecordingIdFromRecallBot = async (
}
return {
- externalRecordingId: extractRecallBotConvergence(botResult.bot)
+ externalRecordingId: extractRecallBotSyncState(botResult.bot)
.externalRecordingId,
providerLookupFailed: false,
};
diff --git a/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/ingest-call-recording-media.util.ts b/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/import-call-recording-media.util.ts
similarity index 87%
rename from packages/twenty-apps/public/call-recorder/src/logic-functions/flows/ingest-call-recording-media.util.ts
rename to packages/twenty-apps/public/call-recorder/src/logic-functions/flows/import-call-recording-media.util.ts
index 144ad7ee08..c28c9512ec 100644
--- a/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/ingest-call-recording-media.util.ts
+++ b/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/import-call-recording-media.util.ts
@@ -20,8 +20,8 @@ type CallRecordingMediaUpdateFields = Pick<
'audio' | 'video' | 'callRecorderFailureReason'
>;
-type IngestMediaArtifactResult =
- | { outcome: 'ingested'; files: CallRecordingMediaFile[] }
+type ImportMediaArtifactResult =
+ | { outcome: 'imported'; files: CallRecordingMediaFile[] }
| { outcome: 'too-large' }
| { outcome: 'failed' };
@@ -38,7 +38,7 @@ type MediaUploadTarget = {
const MEDIA_DOWNLOAD_TIMEOUT_MS = 120_000;
const MEDIA_FILE_FOLDER = 'FilesField';
-export const ingestCallRecordingMedia = async ({
+export const importCallRecordingMedia = async ({
callRecordingId,
externalRecordingId,
hasAudio,
@@ -57,7 +57,7 @@ export const ingestCallRecordingMedia = async ({
if (!recordingResult.ok) {
console.warn(
- `[call-recorder] failed to fetch Recall recording ${externalRecordingId} while ingesting media for call recording ${callRecordingId}: ${recordingResult.errorMessage}`,
+ `[call-recorder] failed to fetch Recall recording ${externalRecordingId} while importing media for call recording ${callRecordingId}: ${recordingResult.errorMessage}`,
);
return {};
@@ -71,7 +71,7 @@ export const ingestCallRecordingMedia = async ({
const tooLargeFailureReasons: string[] = [];
if (!hasVideo && !isUndefined(mediaUrls.videoUrl)) {
- const video = await ingestMediaArtifact({
+ const video = await importMediaArtifact({
callRecordingId,
metadataClient,
url: mediaUrls.videoUrl,
@@ -81,7 +81,7 @@ export const ingestCallRecordingMedia = async ({
maxMediaFileSizeBytes,
});
- if (video.outcome === 'ingested') {
+ if (video.outcome === 'imported') {
updateFields.video = video.files;
}
@@ -91,7 +91,7 @@ export const ingestCallRecordingMedia = async ({
}
if (!hasAudio && !isUndefined(mediaUrls.audioUrl)) {
- const audio = await ingestMediaArtifact({
+ const audio = await importMediaArtifact({
callRecordingId,
metadataClient,
url: mediaUrls.audioUrl,
@@ -101,7 +101,7 @@ export const ingestCallRecordingMedia = async ({
maxMediaFileSizeBytes,
});
- if (audio.outcome === 'ingested') {
+ if (audio.outcome === 'imported') {
updateFields.audio = audio.files;
}
@@ -117,7 +117,7 @@ export const ingestCallRecordingMedia = async ({
return updateFields;
};
-const ingestMediaArtifact = async ({
+const importMediaArtifact = async ({
callRecordingId,
metadataClient,
url,
@@ -131,7 +131,7 @@ const ingestMediaArtifact = async ({
fileName: string;
fieldMetadataUniversalIdentifier: string;
maxMediaFileSizeBytes: number;
-}): Promise => {
+}): Promise => {
try {
const download = await openMediaDownload({
callRecordingId,
@@ -142,7 +142,7 @@ const ingestMediaArtifact = async ({
if (download.outcome === 'too-large') {
console.warn(
- `[call-recorder] media-ingestion phase=artifact-too-large callRecordingId=${callRecordingId} fileName=${fileName} sizeBytes=${download.sizeBytes} maxMediaFileSizeBytes=${maxMediaFileSizeBytes}`,
+ `[call-recorder] media-import phase=artifact-too-large callRecordingId=${callRecordingId} fileName=${fileName} sizeBytes=${download.sizeBytes} maxMediaFileSizeBytes=${maxMediaFileSizeBytes}`,
);
return { outcome: 'too-large' };
@@ -158,12 +158,12 @@ const ingestMediaArtifact = async ({
});
return {
- outcome: 'ingested',
+ outcome: 'imported',
files: [{ fileId, label: fileName }],
};
} catch (error) {
console.warn(
- `[call-recorder] failed to ingest ${fileName} for call recording ${callRecordingId}: ${error instanceof Error ? error.message : String(error)}`,
+ `[call-recorder] failed to import ${fileName} for call recording ${callRecordingId}: ${error instanceof Error ? error.message : String(error)}`,
);
return { outcome: 'failed' };
@@ -189,7 +189,7 @@ const openMediaDownload = async ({
);
console.log(
- `[call-recorder] media-ingestion phase=artifact-download-response callRecordingId=${callRecordingId} fileName=${fileName} responseStatus=${response.status} contentLengthBytes=${contentLengthBytes ?? 'unknown'} ${formatMemoryUsageForLog()}`,
+ `[call-recorder] media-import phase=artifact-download-response callRecordingId=${callRecordingId} fileName=${fileName} responseStatus=${response.status} contentLengthBytes=${contentLengthBytes ?? 'unknown'} ${formatMemoryUsageForLog()}`,
);
if (!response.ok) {
@@ -260,7 +260,7 @@ const uploadMediaStreamToStorage = async ({
});
console.log(
- `[call-recorder] media-ingestion phase=artifact-upload-start callRecordingId=${callRecordingId} fileName=${fileName} declaredBytes=${sizeBytes} ${formatMemoryUsageForLog()}`,
+ `[call-recorder] media-import phase=artifact-upload-start callRecordingId=${callRecordingId} fileName=${fileName} declaredBytes=${sizeBytes} ${formatMemoryUsageForLog()}`,
);
await putMediaDownloadBodyToUploadTarget({
@@ -288,7 +288,7 @@ const cancelMediaDownloadBody = async ({
await body.cancel().catch((error) => {
console.warn(
- `[call-recorder] media-ingestion phase=download-body-cancel-failed callRecordingId=${callRecordingId} fileName=${fileName}: ${error instanceof Error ? error.message : String(error)}`,
+ `[call-recorder] media-import phase=download-body-cancel-failed callRecordingId=${callRecordingId} fileName=${fileName}: ${error instanceof Error ? error.message : String(error)}`,
);
});
};
diff --git a/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/reconcile-call-recording-transcript-artifact-result.type.ts b/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/import-call-recording-transcript-result.type.ts
similarity index 84%
rename from packages/twenty-apps/public/call-recorder/src/logic-functions/flows/reconcile-call-recording-transcript-artifact-result.type.ts
rename to packages/twenty-apps/public/call-recorder/src/logic-functions/flows/import-call-recording-transcript-result.type.ts
index 1c8ab638e4..7d8cfee05f 100644
--- a/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/reconcile-call-recording-transcript-artifact-result.type.ts
+++ b/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/import-call-recording-transcript-result.type.ts
@@ -5,7 +5,7 @@ type CallRecordingTranscriptArtifactUpdateFields = Pick<
'callRecorderFailureReason' | 'status' | 'transcript'
>;
-export type ReconcileCallRecordingTranscriptArtifactResult = {
+export type ImportCallRecordingTranscriptResult = {
updateData: CallRecordingTranscriptArtifactUpdateFields;
requestedTranscript: boolean;
};
diff --git a/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/reconcile-call-recording-transcript-artifact.util.ts b/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/import-call-recording-transcript.util.ts
similarity index 93%
rename from packages/twenty-apps/public/call-recorder/src/logic-functions/flows/reconcile-call-recording-transcript-artifact.util.ts
rename to packages/twenty-apps/public/call-recorder/src/logic-functions/flows/import-call-recording-transcript.util.ts
index c50aa5e8f9..3dbdc0f456 100644
--- a/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/reconcile-call-recording-transcript-artifact.util.ts
+++ b/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/import-call-recording-transcript.util.ts
@@ -10,12 +10,12 @@ import { createAsyncRecallTranscript } from 'src/logic-functions/recall-api/crea
import { listRecallTranscripts } from 'src/logic-functions/recall-api/list-recall-transcripts.util';
import { type RecallTranscriptSummary } from 'src/logic-functions/recall-api/recall-transcript-summary.type';
import { downloadTranscript } from 'src/logic-functions/flows/download-transcript.util';
-import { type ReconcileCallRecordingTranscriptArtifactResult } from 'src/logic-functions/flows/reconcile-call-recording-transcript-artifact-result.type';
+import { type ImportCallRecordingTranscriptResult } from 'src/logic-functions/flows/import-call-recording-transcript-result.type';
type CallRecordingTranscriptArtifactUpdateFields =
- ReconcileCallRecordingTranscriptArtifactResult['updateData'];
+ ImportCallRecordingTranscriptResult['updateData'];
-export const reconcileCallRecordingTranscriptArtifact = async ({
+export const importCallRecordingTranscript = async ({
callRecordingId,
currentStatus,
externalRecordingId,
@@ -27,7 +27,7 @@ export const reconcileCallRecordingTranscriptArtifact = async ({
externalRecordingId: string;
requestedAt: string;
transcript: unknown;
-}): Promise => {
+}): Promise => {
const existingTranscriptMarker = parseTranscriptMarker(transcript);
if (
@@ -149,7 +149,7 @@ export const reconcileCallRecordingTranscriptArtifact = async ({
};
const buildEmptyTranscriptArtifactResult =
- (): ReconcileCallRecordingTranscriptArtifactResult => ({
+ (): ImportCallRecordingTranscriptResult => ({
updateData: {},
requestedTranscript: false,
});
diff --git a/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/persist-call-recording-progress.util.ts b/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/persist-call-recording-progress.util.ts
index 17fab2679a..b7ba7041bc 100644
--- a/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/persist-call-recording-progress.util.ts
+++ b/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/persist-call-recording-progress.util.ts
@@ -2,7 +2,7 @@ import { type CoreApiClient } from 'twenty-client-sdk/core';
import { type FilesFieldValue } from 'src/logic-functions/types/files-field-value.type';
import { completeAndChargeCallRecording } from 'src/logic-functions/flows/complete-and-charge-call-recording.util';
-import { shouldCompleteCallRecordingIngestion } from 'src/logic-functions/domain/should-complete-call-recording-ingestion.util';
+import { shouldCompleteCallRecordingImport } from 'src/logic-functions/domain/should-complete-call-recording-import.util';
import { updateCallRecording } from 'src/logic-functions/data/update-call-recording.util';
import { type CallRecordingUpdateFields } from 'src/logic-functions/types/call-recording-update-fields.type';
@@ -27,16 +27,16 @@ export const persistCallRecordingProgress = async (
current: PersistCallRecordingProgressCurrent;
updateData: CallRecordingUpdateFields;
},
-): Promise<{ completesIngestion: boolean }> => {
- const completesIngestion = shouldCompleteCallRecordingIngestion({
+): Promise<{ completesImport: boolean }> => {
+ const completesImport = shouldCompleteCallRecordingImport({
current,
updateData,
});
- if (!completesIngestion) {
+ if (!completesImport) {
await updateCallRecording(client, { id, data: updateData });
- return { completesIngestion: false };
+ return { completesImport: false };
}
// Strip status so COMPLETED is written only by the atomic claim — its single winner bills once.
@@ -54,5 +54,5 @@ export const persistCallRecordingProgress = async (
endedAt: updateData.endedAt ?? current.endedAt,
});
- return { completesIngestion: true };
+ return { completesImport: true };
};
diff --git a/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/reconcile-call-recorder.util.ts b/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/reconcile-call-recorder.util.ts
index 9767a6f3a8..2f9302bb1e 100644
--- a/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/reconcile-call-recorder.util.ts
+++ b/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/reconcile-call-recorder.util.ts
@@ -16,7 +16,7 @@ import {
createCallRecording,
type ScheduledCallRecordingFields,
} from 'src/logic-functions/data/create-call-recording.util';
-import { ensureCallRecorder } from 'src/logic-functions/flows/ensure-call-recorder.util';
+import { scheduleRecallBotForCallRecording } from 'src/logic-functions/flows/schedule-recall-bot-for-call-recording.util';
import { fetchCalendarEventsByIds } from 'src/logic-functions/data/fetch-calendar-events-by-ids.util';
import { fetchCalendarEventsByStartsAtValues } from 'src/logic-functions/data/fetch-calendar-events-by-starts-at-values.util';
import { findCallRecordingsByCalendarEventIds } from 'src/logic-functions/data/find-call-recordings-by-calendar-event-ids.util';
@@ -345,7 +345,7 @@ const createPolicyManagedCallRecording = async ({
}
// Winning the deterministic-id insert elects this run as the single writer that creates the bot.
- const didScheduleBot = await ensureCallRecorder(client, {
+ const didScheduleBot = await scheduleRecallBotForCallRecording(client, {
callRecording: {
id: callRecordingId,
...scheduledFields,
diff --git a/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/ensure-call-recorder.util.ts b/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/schedule-recall-bot-for-call-recording.util.ts
similarity index 98%
rename from packages/twenty-apps/public/call-recorder/src/logic-functions/flows/ensure-call-recorder.util.ts
rename to packages/twenty-apps/public/call-recorder/src/logic-functions/flows/schedule-recall-bot-for-call-recording.util.ts
index 459f9d3d46..08974ced45 100644
--- a/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/ensure-call-recorder.util.ts
+++ b/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/schedule-recall-bot-for-call-recording.util.ts
@@ -12,7 +12,7 @@ import { scheduleRecallBot } from 'src/logic-functions/recall-api/schedule-recal
import { updateCallRecording } from 'src/logic-functions/data/update-call-recording.util';
// The sole place a Recall bot is created. Only the deterministic-create winner and the stale-state cron call it, so one writer per meeting POSTs exactly one bot.
-export const ensureCallRecorder = async (
+export const scheduleRecallBotForCallRecording = async (
client: CoreApiClient,
{ callRecording, calendarEvent }: MeetingRecording,
): Promise => {
diff --git a/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/heal-call-recordings-missing-bot.util.ts b/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/schedule-recall-bots-for-pending-call-recordings.util.ts
similarity index 78%
rename from packages/twenty-apps/public/call-recorder/src/logic-functions/flows/heal-call-recordings-missing-bot.util.ts
rename to packages/twenty-apps/public/call-recorder/src/logic-functions/flows/schedule-recall-bots-for-pending-call-recordings.util.ts
index b550619da2..abb93485bb 100644
--- a/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/heal-call-recordings-missing-bot.util.ts
+++ b/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/schedule-recall-bots-for-pending-call-recordings.util.ts
@@ -2,28 +2,28 @@ import { isUndefined } from '@sniptt/guards';
import { type CoreApiClient } from 'twenty-client-sdk/core';
import { type CalendarEventRecord } from 'src/logic-functions/types/calendar-event-record.type';
-import { ensureCallRecorder } from 'src/logic-functions/flows/ensure-call-recorder.util';
+import { scheduleRecallBotForCallRecording } from 'src/logic-functions/flows/schedule-recall-bot-for-call-recording.util';
import { fetchCalendarEventsByIds } from 'src/logic-functions/data/fetch-calendar-events-by-ids.util';
import { findOpenScheduledCallRecordings } from 'src/logic-functions/data/find-open-scheduled-call-recordings.util';
import { getUniqueSortedIds } from 'src/logic-functions/utils/get-unique-sorted-ids.util';
-export type HealCallRecordingsMissingBotResult = {
+export type ScheduleRecallBotsForPendingCallRecordingsResult = {
scheduledCallRecordingIds: string[];
};
// Closes the create-winner crash gap: a run that inserted the row but died before POSTing leaves a botless recording, and the cron is the single writer that re-POSTs it.
-export const healCallRecordingsMissingBot = async ({
+export const scheduleRecallBotsForPendingCallRecordings = async ({
client,
now,
}: {
client: CoreApiClient;
now: Date;
-}): Promise => {
- const botlessCallRecordings = (
+}): Promise => {
+ const pendingCallRecordings = (
await findOpenScheduledCallRecordings(client)
).filter((callRecording) => isUndefined(callRecording.externalBotId));
- if (botlessCallRecordings.length === 0) {
+ if (pendingCallRecordings.length === 0) {
return { scheduledCallRecordingIds: [] };
}
@@ -32,7 +32,7 @@ export const healCallRecordingsMissingBot = async ({
await fetchCalendarEventsByIds(
client,
getUniqueSortedIds(
- botlessCallRecordings.map(
+ pendingCallRecordings.map(
(callRecording) => callRecording.calendarEventId,
),
),
@@ -41,7 +41,7 @@ export const healCallRecordingsMissingBot = async ({
);
const scheduledCallRecordingIds: string[] = [];
- for (const callRecording of botlessCallRecordings) {
+ for (const callRecording of pendingCallRecordings) {
const calendarEvent = isUndefined(callRecording.calendarEventId)
? undefined
: calendarEventsById.get(callRecording.calendarEventId);
@@ -50,7 +50,7 @@ export const healCallRecordingsMissingBot = async ({
continue;
}
- const didScheduleCallRecorder = await ensureCallRecorder(client, {
+ const didScheduleCallRecorder = await scheduleRecallBotForCallRecording(client, {
callRecording,
calendarEvent,
});
diff --git a/packages/twenty-apps/public/call-recorder/src/logic-functions/recall-api/__tests__/extract-recall-bot-convergence.test.ts b/packages/twenty-apps/public/call-recorder/src/logic-functions/recall-api/__tests__/extract-recall-bot-sync-state.test.ts
similarity index 74%
rename from packages/twenty-apps/public/call-recorder/src/logic-functions/recall-api/__tests__/extract-recall-bot-convergence.test.ts
rename to packages/twenty-apps/public/call-recorder/src/logic-functions/recall-api/__tests__/extract-recall-bot-sync-state.test.ts
index 0b2ece8240..22ed42fa6c 100644
--- a/packages/twenty-apps/public/call-recorder/src/logic-functions/recall-api/__tests__/extract-recall-bot-convergence.test.ts
+++ b/packages/twenty-apps/public/call-recorder/src/logic-functions/recall-api/__tests__/extract-recall-bot-sync-state.test.ts
@@ -1,10 +1,10 @@
import { describe, expect, it } from 'vitest';
-import { extractRecallBotConvergence } from 'src/logic-functions/recall-api/extract-recall-bot-convergence.util';
+import { extractRecallBotSyncState } from 'src/logic-functions/recall-api/extract-recall-bot-sync-state.util';
-describe('extractRecallBotConvergence', () => {
+describe('extractRecallBotSyncState', () => {
it('maps the latest status change code to a call recording status', () => {
- const convergence = extractRecallBotConvergence({
+ const syncState = extractRecallBotSyncState({
status_changes: [
{ code: 'joining_call', created_at: '2026-01-01T12:58:00.000Z' },
{ code: 'in_call_recording', created_at: '2026-01-01T13:02:00.000Z' },
@@ -13,13 +13,13 @@ describe('extractRecallBotConvergence', () => {
],
});
- // COMPLETED is reserved for full artifact ingestion, never bot state.
- expect(convergence.status).toBe('PROCESSING');
- expect(convergence.isRecallRecordingDone).toBe(true);
+ // COMPLETED is reserved for full artifact import, never bot state.
+ expect(syncState.status).toBe('PROCESSING');
+ expect(syncState.isRecallRecordingDone).toBe(true);
});
it('uses created_at to find the latest status when Recall returns status changes out of order', () => {
- const convergence = extractRecallBotConvergence({
+ const syncState = extractRecallBotSyncState({
status_changes: [
{ code: 'done', created_at: '2026-01-01T14:05:00.000Z' },
{ code: 'joining_call', created_at: '2026-01-01T12:58:00.000Z' },
@@ -27,11 +27,11 @@ describe('extractRecallBotConvergence', () => {
],
});
- expect(convergence.status).toBe('PROCESSING');
+ expect(syncState.status).toBe('PROCESSING');
});
it('prefers recording-object timestamps over status change entries', () => {
- const convergence = extractRecallBotConvergence({
+ const syncState = extractRecallBotSyncState({
status_changes: [
{ code: 'in_call_recording', created_at: '2026-01-01T13:02:30.000Z' },
{ code: 'call_ended', created_at: '2026-01-01T14:00:30.000Z' },
@@ -45,7 +45,7 @@ describe('extractRecallBotConvergence', () => {
],
});
- expect(convergence).toEqual({
+ expect(syncState).toEqual({
status: 'PROCESSING',
failureReason: undefined,
startedAt: '2026-01-01T13:02:00.000Z',
@@ -56,7 +56,7 @@ describe('extractRecallBotConvergence', () => {
});
it('falls back to status change timestamps when recordings carry none', () => {
- const convergence = extractRecallBotConvergence({
+ const syncState = extractRecallBotSyncState({
status_changes: [
{ code: 'in_call_recording', created_at: '2026-01-01T13:02:00.000Z' },
{ code: 'call_ended', created_at: '2026-01-01T14:00:00.000Z' },
@@ -64,7 +64,7 @@ describe('extractRecallBotConvergence', () => {
recordings: [{ id: 'recall-recording-1' }],
});
- expect(convergence).toEqual({
+ expect(syncState).toEqual({
status: 'PROCESSING',
failureReason: undefined,
startedAt: '2026-01-01T13:02:00.000Z',
@@ -75,7 +75,7 @@ describe('extractRecallBotConvergence', () => {
});
it('normalizes microsecond-precision Recall timestamps to millisecond ISO', () => {
- const convergence = extractRecallBotConvergence({
+ const syncState = extractRecallBotSyncState({
status_changes: [
{ code: 'done', created_at: '2026-06-10T12:20:00.123456+00:00' },
],
@@ -88,12 +88,12 @@ describe('extractRecallBotConvergence', () => {
],
});
- expect(convergence.startedAt).toBe('2026-06-10T11:02:28.281Z');
- expect(convergence.endedAt).toBe('2026-06-10T12:17:28.281Z');
+ expect(syncState.startedAt).toBe('2026-06-10T11:02:28.281Z');
+ expect(syncState.endedAt).toBe('2026-06-10T12:17:28.281Z');
});
it('returns nothing derivable from an empty bot response', () => {
- expect(extractRecallBotConvergence({})).toEqual({
+ expect(extractRecallBotSyncState({})).toEqual({
status: undefined,
failureReason: undefined,
startedAt: undefined,
@@ -104,7 +104,7 @@ describe('extractRecallBotConvergence', () => {
});
it('skips malformed status change entries', () => {
- const convergence = extractRecallBotConvergence({
+ const syncState = extractRecallBotSyncState({
status_changes: [
null,
'not-an-object',
@@ -114,7 +114,7 @@ describe('extractRecallBotConvergence', () => {
recordings: 'not-an-array',
});
- expect(convergence).toEqual({
+ expect(syncState).toEqual({
status: 'RECORDING',
failureReason: undefined,
startedAt: '2026-01-01T13:02:00.000Z',
@@ -125,7 +125,7 @@ describe('extractRecallBotConvergence', () => {
});
it('carries the failing Recall status code as the failure reason', () => {
- const convergence = extractRecallBotConvergence({
+ const syncState = extractRecallBotSyncState({
status_changes: [
{ code: 'joining_call', created_at: '2026-01-01T12:58:00.000Z' },
{
@@ -135,19 +135,19 @@ describe('extractRecallBotConvergence', () => {
],
});
- expect(convergence.status).toBe('FAILED');
- expect(convergence.failureReason).toBe('recording_permission_denied');
+ expect(syncState.status).toBe('FAILED');
+ expect(syncState.failureReason).toBe('recording_permission_denied');
});
it('leaves the status undefined for unknown latest codes', () => {
- const convergence = extractRecallBotConvergence({
+ const syncState = extractRecallBotSyncState({
status_changes: [
{ code: 'in_call_recording', created_at: '2026-01-01T13:02:00.000Z' },
{ code: 'some_future_code', created_at: '2026-01-01T13:30:00.000Z' },
],
});
- expect(convergence.status).toBeUndefined();
- expect(convergence.startedAt).toBe('2026-01-01T13:02:00.000Z');
+ expect(syncState.status).toBeUndefined();
+ expect(syncState.startedAt).toBe('2026-01-01T13:02:00.000Z');
});
});
diff --git a/packages/twenty-apps/public/call-recorder/src/logic-functions/recall-api/extract-recall-bot-convergence.util.ts b/packages/twenty-apps/public/call-recorder/src/logic-functions/recall-api/extract-recall-bot-sync-state.util.ts
similarity index 97%
rename from packages/twenty-apps/public/call-recorder/src/logic-functions/recall-api/extract-recall-bot-convergence.util.ts
rename to packages/twenty-apps/public/call-recorder/src/logic-functions/recall-api/extract-recall-bot-sync-state.util.ts
index d6af6a3a16..8ebc92e373 100644
--- a/packages/twenty-apps/public/call-recorder/src/logic-functions/recall-api/extract-recall-bot-convergence.util.ts
+++ b/packages/twenty-apps/public/call-recorder/src/logic-functions/recall-api/extract-recall-bot-sync-state.util.ts
@@ -6,7 +6,7 @@ import { getString } from 'src/logic-functions/utils/get-string.util';
import { mapRecallStatusCodeToCallRecordingStatus } from 'src/logic-functions/domain/map-recall-status-code-to-call-recording-status.util';
import { normalizeRecallTimestamp } from 'src/logic-functions/recall-api/normalize-recall-timestamp.util';
-export type RecallBotConvergence = {
+export type RecallBotSyncState = {
status: CallRecordingStatus | undefined;
failureReason: string | undefined;
startedAt: string | undefined;
@@ -21,9 +21,9 @@ type RecallBotStatusChange = {
};
// Derives the state a full webhook history would have produced from GET /bot.
-export const extractRecallBotConvergence = (
+export const extractRecallBotSyncState = (
bot: Record,
-): RecallBotConvergence => {
+): RecallBotSyncState => {
const statusChanges = extractStatusChanges(bot);
const latestStatusChange = getLatestStatusChange(statusChanges);
const status = mapRecallStatusCodeToCallRecordingStatus(
diff --git a/packages/twenty-apps/public/call-recorder/src/logic-functions/recall-api/recall-bot-api-request.util.ts b/packages/twenty-apps/public/call-recorder/src/logic-functions/recall-api/recall-bot-api-request.util.ts
index 62374f7f4b..9f91a4938f 100644
--- a/packages/twenty-apps/public/call-recorder/src/logic-functions/recall-api/recall-bot-api-request.util.ts
+++ b/packages/twenty-apps/public/call-recorder/src/logic-functions/recall-api/recall-bot-api-request.util.ts
@@ -25,7 +25,7 @@ type RecallBotApiRequestResult =
errorMessage: string;
};
-// Bot creates tolerate retries because duplicates stay unclaimed and get reaped.
+// Bot creates tolerate retries because duplicates stay unclaimed and get canceled.
// Callers that cannot retry idempotently can lower maxAttempts.
export const recallBotApiRequest = async (
requestArgs: RecallBotApiRequestArgs,
diff --git a/packages/twenty-apps/public/call-recorder/src/logic-functions/reconcile-stale-bot-state.ts b/packages/twenty-apps/public/call-recorder/src/logic-functions/reconcile-stale-bot-state.ts
index 23a7924fe6..8c77e997b8 100644
--- a/packages/twenty-apps/public/call-recorder/src/logic-functions/reconcile-stale-bot-state.ts
+++ b/packages/twenty-apps/public/call-recorder/src/logic-functions/reconcile-stale-bot-state.ts
@@ -6,17 +6,17 @@ import { STALE_BOT_STATE_CRON_PATTERN } from 'src/logic-functions/constants/stal
import { convergeDivergedCallRecordings } from 'src/logic-functions/flows/converge-diverged-call-recordings.util';
import { type ConvergeDivergedCallRecordingsResult } from 'src/logic-functions/flows/converge-diverged-call-recordings-result.type';
import {
- healCallRecordingsMissingBot,
- type HealCallRecordingsMissingBotResult,
-} from 'src/logic-functions/flows/heal-call-recordings-missing-bot.util';
+ scheduleRecallBotsForPendingCallRecordings,
+ type ScheduleRecallBotsForPendingCallRecordingsResult,
+} from 'src/logic-functions/flows/schedule-recall-bots-for-pending-call-recordings.util';
import {
- reapOrphanedCallRecorders,
- type ReapOrphanedCallRecordersResult,
-} from 'src/logic-functions/flows/reap-orphaned-call-recorders.util';
+ cleanupOrphanedRecallBots,
+ type CleanupOrphanedRecallBotsResult,
+} from 'src/logic-functions/flows/cleanup-orphaned-recall-bots.util';
// Every unwanted bot passes through this join_at window before it can attend.
-const REAPER_JOIN_AT_LOOKBACK_HOURS = 4;
-const REAPER_JOIN_AT_LOOKAHEAD_HOURS = 24;
+const CLEANUP_JOIN_AT_LOOKBACK_HOURS = 4;
+const CLEANUP_JOIN_AT_LOOKAHEAD_HOURS = 24;
type StepFailure = { error: string };
@@ -24,51 +24,51 @@ const reconcileStaleBotStateHandler = async (): Promise