@vertesia/workflow 1.0.0-dev.20260128.144200 → 1.0.0-dev.20260225.024852Z

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. package/lib/cjs/activities/advanced/createOrUpdateDocumentFromInteractionRun.js +1 -1
  2. package/lib/cjs/activities/advanced/createOrUpdateDocumentFromInteractionRun.js.map +1 -1
  3. package/lib/cjs/activities/chunkDocument.js +3 -1
  4. package/lib/cjs/activities/chunkDocument.js.map +1 -1
  5. package/lib/cjs/activities/extractDocumentText.js +56 -16
  6. package/lib/cjs/activities/extractDocumentText.js.map +1 -1
  7. package/lib/cjs/activities/generateDocumentProperties.js +4 -2
  8. package/lib/cjs/activities/generateDocumentProperties.js.map +1 -1
  9. package/lib/cjs/activities/generateEmbeddings.js +20 -10
  10. package/lib/cjs/activities/generateEmbeddings.js.map +1 -1
  11. package/lib/cjs/activities/generateOrAssignContentType.js +2 -2
  12. package/lib/cjs/activities/generateOrAssignContentType.js.map +1 -1
  13. package/lib/cjs/activities/index-dsl.js +7 -7
  14. package/lib/cjs/activities/index-dsl.js.map +1 -1
  15. package/lib/cjs/activities/media/saveGladiaTranscription.js +38 -24
  16. package/lib/cjs/activities/media/saveGladiaTranscription.js.map +1 -1
  17. package/lib/cjs/activities/media/transcribeMediaWithGladia.js +41 -24
  18. package/lib/cjs/activities/media/transcribeMediaWithGladia.js.map +1 -1
  19. package/lib/cjs/activities/notifyWebhook.js +11 -2
  20. package/lib/cjs/activities/notifyWebhook.js.map +1 -1
  21. package/lib/cjs/activities/renditions/generateImageRendition.js +2 -2
  22. package/lib/cjs/activities/renditions/generateImageRendition.js.map +1 -1
  23. package/lib/cjs/activities/setDocumentStatus.js +13 -2
  24. package/lib/cjs/activities/setDocumentStatus.js.map +1 -1
  25. package/lib/cjs/conversion/image.js +10 -10
  26. package/lib/cjs/conversion/image.js.map +1 -1
  27. package/lib/cjs/dsl/dsl-workflow.js +44 -7
  28. package/lib/cjs/dsl/dsl-workflow.js.map +1 -1
  29. package/lib/cjs/dsl/setup/ActivityContext.js +56 -0
  30. package/lib/cjs/dsl/setup/ActivityContext.js.map +1 -1
  31. package/lib/cjs/errors.js +11 -1
  32. package/lib/cjs/errors.js.map +1 -1
  33. package/lib/cjs/index.js +6 -5
  34. package/lib/cjs/index.js.map +1 -1
  35. package/lib/cjs/result-types.js.map +1 -1
  36. package/lib/cjs/utils/renditions.js +9 -5
  37. package/lib/cjs/utils/renditions.js.map +1 -1
  38. package/lib/cjs/utils/text-preview-utils.js +43 -0
  39. package/lib/cjs/utils/text-preview-utils.js.map +1 -0
  40. package/lib/esm/activities/advanced/createOrUpdateDocumentFromInteractionRun.js +1 -1
  41. package/lib/esm/activities/advanced/createOrUpdateDocumentFromInteractionRun.js.map +1 -1
  42. package/lib/esm/activities/chunkDocument.js +3 -1
  43. package/lib/esm/activities/chunkDocument.js.map +1 -1
  44. package/lib/esm/activities/extractDocumentText.js +56 -16
  45. package/lib/esm/activities/extractDocumentText.js.map +1 -1
  46. package/lib/esm/activities/generateDocumentProperties.js +4 -2
  47. package/lib/esm/activities/generateDocumentProperties.js.map +1 -1
  48. package/lib/esm/activities/generateEmbeddings.js +20 -10
  49. package/lib/esm/activities/generateEmbeddings.js.map +1 -1
  50. package/lib/esm/activities/generateOrAssignContentType.js +2 -2
  51. package/lib/esm/activities/generateOrAssignContentType.js.map +1 -1
  52. package/lib/esm/activities/index-dsl.js +3 -3
  53. package/lib/esm/activities/index-dsl.js.map +1 -1
  54. package/lib/esm/activities/media/saveGladiaTranscription.js +38 -24
  55. package/lib/esm/activities/media/saveGladiaTranscription.js.map +1 -1
  56. package/lib/esm/activities/media/transcribeMediaWithGladia.js +41 -24
  57. package/lib/esm/activities/media/transcribeMediaWithGladia.js.map +1 -1
  58. package/lib/esm/activities/notifyWebhook.js +11 -2
  59. package/lib/esm/activities/notifyWebhook.js.map +1 -1
  60. package/lib/esm/activities/renditions/generateImageRendition.js +2 -2
  61. package/lib/esm/activities/renditions/generateImageRendition.js.map +1 -1
  62. package/lib/esm/activities/setDocumentStatus.js +13 -2
  63. package/lib/esm/activities/setDocumentStatus.js.map +1 -1
  64. package/lib/esm/conversion/image.js +10 -10
  65. package/lib/esm/conversion/image.js.map +1 -1
  66. package/lib/esm/dsl/dsl-workflow.js +44 -7
  67. package/lib/esm/dsl/dsl-workflow.js.map +1 -1
  68. package/lib/esm/dsl/setup/ActivityContext.js +57 -1
  69. package/lib/esm/dsl/setup/ActivityContext.js.map +1 -1
  70. package/lib/esm/errors.js +9 -0
  71. package/lib/esm/errors.js.map +1 -1
  72. package/lib/esm/index.js +6 -5
  73. package/lib/esm/index.js.map +1 -1
  74. package/lib/esm/result-types.js.map +1 -1
  75. package/lib/esm/utils/renditions.js +9 -5
  76. package/lib/esm/utils/renditions.js.map +1 -1
  77. package/lib/esm/utils/text-preview-utils.js +38 -0
  78. package/lib/esm/utils/text-preview-utils.js.map +1 -0
  79. package/lib/tsconfig.tsbuildinfo +1 -1
  80. package/lib/types/activities/chunkDocument.d.ts.map +1 -1
  81. package/lib/types/activities/extractDocumentText.d.ts +1 -0
  82. package/lib/types/activities/extractDocumentText.d.ts.map +1 -1
  83. package/lib/types/activities/generateDocumentProperties.d.ts.map +1 -1
  84. package/lib/types/activities/generateEmbeddings.d.ts.map +1 -1
  85. package/lib/types/activities/index-dsl.d.ts +3 -3
  86. package/lib/types/activities/index-dsl.d.ts.map +1 -1
  87. package/lib/types/activities/media/saveGladiaTranscription.d.ts +1 -0
  88. package/lib/types/activities/media/saveGladiaTranscription.d.ts.map +1 -1
  89. package/lib/types/activities/media/transcribeMediaWithGladia.d.ts +1 -0
  90. package/lib/types/activities/media/transcribeMediaWithGladia.d.ts.map +1 -1
  91. package/lib/types/activities/setDocumentStatus.d.ts +1 -1
  92. package/lib/types/activities/setDocumentStatus.d.ts.map +1 -1
  93. package/lib/types/dsl/dsl-workflow.d.ts.map +1 -1
  94. package/lib/types/dsl/setup/ActivityContext.d.ts +32 -2
  95. package/lib/types/dsl/setup/ActivityContext.d.ts.map +1 -1
  96. package/lib/types/errors.d.ts +4 -0
  97. package/lib/types/errors.d.ts.map +1 -1
  98. package/lib/types/index.d.ts +6 -5
  99. package/lib/types/index.d.ts.map +1 -1
  100. package/lib/types/result-types.d.ts +5 -1
  101. package/lib/types/result-types.d.ts.map +1 -1
  102. package/lib/types/utils/renditions.d.ts +2 -0
  103. package/lib/types/utils/renditions.d.ts.map +1 -1
  104. package/lib/types/utils/text-preview-utils.d.ts +15 -0
  105. package/lib/types/utils/text-preview-utils.d.ts.map +1 -0
  106. package/lib/workflows-bundle.js +11747 -11141
  107. package/package.json +6 -7
  108. package/src/activities/advanced/createOrUpdateDocumentFromInteractionRun.ts +1 -1
  109. package/src/activities/chunkDocument.ts +3 -1
  110. package/src/activities/extractDocumentText.ts +85 -26
  111. package/src/activities/generateDocumentProperties.ts +4 -2
  112. package/src/activities/generateEmbeddings.ts +22 -14
  113. package/src/activities/generateOrAssignContentType.ts +2 -2
  114. package/src/activities/index-dsl.ts +4 -3
  115. package/src/activities/media/saveGladiaTranscription.test.ts +406 -0
  116. package/src/activities/media/saveGladiaTranscription.ts +41 -26
  117. package/src/activities/media/transcribeMediaWithGladia.test.ts +583 -0
  118. package/src/activities/media/transcribeMediaWithGladia.ts +46 -25
  119. package/src/activities/notifyWebhook.test.ts +121 -8
  120. package/src/activities/notifyWebhook.ts +10 -2
  121. package/src/activities/renditions/generateImageRendition.ts +2 -2
  122. package/src/activities/setDocumentStatus.ts +12 -4
  123. package/src/conversion/image.test.ts +1 -0
  124. package/src/conversion/image.ts +10 -10
  125. package/src/dsl/dsl-workflow.ts +57 -9
  126. package/src/dsl/setup/ActivityContext.ts +73 -0
  127. package/src/dsl.ts +1 -0
  128. package/src/errors.ts +15 -0
  129. package/src/index.ts +6 -5
  130. package/src/result-types.ts +5 -1
  131. package/src/utils/renditions.ts +11 -5
  132. package/src/utils/text-preview-utils.ts +62 -0
@@ -0,0 +1,406 @@
1
+ import { MockActivityEnvironment } from "@temporalio/testing";
2
+ import { ContentEventName, DSLActivityExecutionPayload } from "@vertesia/common";
3
+ import type { VertesiaClient } from "@vertesia/client";
4
+ import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
5
+ import type { ActivityContext, TextExtractionResult } from "@vertesia/workflow";
6
+ import { TextExtractionStatus } from "../../result-types.js";
7
+ import { saveGladiaTranscription, SaveGladiaTranscriptionParams } from "./saveGladiaTranscription.js";
8
+
9
+ // Mock setupActivity from the relative path used by the activity
10
+ vi.mock("../../dsl/setup/ActivityContext.js", async (importOriginal) => {
11
+ const actual = await importOriginal<typeof import("../../dsl/setup/ActivityContext.js")>();
12
+ return {
13
+ ...actual,
14
+ setupActivity: vi.fn(),
15
+ };
16
+ });
17
+
18
+ // Mock FetchClient as a constructor
19
+ vi.mock("@vertesia/api-fetch-client", async (importOriginal) => {
20
+ const actual = await importOriginal<typeof import("@vertesia/api-fetch-client")>();
21
+ return {
22
+ ...actual,
23
+ FetchClient: vi.fn(),
24
+ };
25
+ });
26
+
27
+ let testEnv: MockActivityEnvironment;
28
+
29
+ beforeAll(async () => {
30
+ testEnv = new MockActivityEnvironment();
31
+ });
32
+
33
+ beforeEach(() => {
34
+ vi.clearAllMocks();
35
+ });
36
+
37
+ // Helper function to create test payload
38
+ const createTestPayload = (
39
+ params: SaveGladiaTranscriptionParams,
40
+ objectId?: string,
41
+ fileInput?: { url: string; mimetype: string }
42
+ ): DSLActivityExecutionPayload<SaveGladiaTranscriptionParams> => {
43
+ return {
44
+ auth_token: process.env.VERTESIA_KEY || "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwOi8vbW9jay10b2tlbi1zZXJ2ZXIiLCJzdWIiOiJ0ZXN0In0.signature",
45
+ account_id: "test-account",
46
+ project_id: "test-project",
47
+ params,
48
+ config: {
49
+ studio_url: "http://mock-studio",
50
+ store_url: "http://mock-store",
51
+ },
52
+ workflow_name: "test-workflow",
53
+ event: ContentEventName.create,
54
+ objectIds: objectId ? [objectId] : [],
55
+ input: fileInput
56
+ ? { inputType: 'files' as const, files: [fileInput] }
57
+ : objectId
58
+ ? { inputType: 'objectIds' as const, objectIds: [objectId] }
59
+ : undefined,
60
+ vars: {},
61
+ activity: { name: "SaveGladiaTranscription", params }
62
+ };
63
+ };
64
+
65
+ // Mock Gladia transcription response
66
+ const mockGladiaTranscriptionResult = {
67
+ id: "test-transcription-id",
68
+ status: "done" as const,
69
+ result: {
70
+ metadata: {
71
+ audio_duration: 120.5,
72
+ number_of_distinct_channels: 1,
73
+ billing_time: 120,
74
+ transcription_time: 30,
75
+ },
76
+ transcription: {
77
+ full_transcript: "Hello world, this is a test transcription.",
78
+ languages: ["en"],
79
+ utterances: [
80
+ {
81
+ language: "en",
82
+ start: 0,
83
+ end: 2.5,
84
+ confidence: 0.95,
85
+ channel: 0,
86
+ speaker: 0,
87
+ text: "Hello world,"
88
+ },
89
+ {
90
+ language: "en",
91
+ start: 2.5,
92
+ end: 5.0,
93
+ confidence: 0.97,
94
+ channel: 0,
95
+ speaker: 0,
96
+ text: "this is a test transcription."
97
+ }
98
+ ],
99
+ },
100
+ },
101
+ };
102
+
103
+ describe("SaveGladiaTranscription", () => {
104
+ it("should save transcription in object mode", async () => {
105
+ const { setupActivity } = await import("../../dsl/setup/ActivityContext.js");
106
+ const { FetchClient } = await import("@vertesia/api-fetch-client");
107
+
108
+ // Mock FetchClient instance
109
+ const mockFetchClient = {
110
+ withHeaders: vi.fn().mockReturnThis(),
111
+ get: vi.fn().mockResolvedValue(mockGladiaTranscriptionResult),
112
+ };
113
+ vi.mocked(FetchClient).mockImplementation(function(this: any) {
114
+ return mockFetchClient as any;
115
+ });
116
+
117
+ // Mock client
118
+ const mockClient = {
119
+ projects: {
120
+ integrations: {
121
+ retrieve: vi.fn().mockResolvedValue({
122
+ enabled: true,
123
+ api_key: "test-api-key",
124
+ url: "https://api.gladia.io/v2",
125
+ }),
126
+ },
127
+ },
128
+ objects: {
129
+ retrieve: vi.fn().mockResolvedValue({
130
+ content: { etag: "test-etag" },
131
+ }),
132
+ update: vi.fn().mockResolvedValue({}),
133
+ },
134
+ } as unknown as VertesiaClient;
135
+
136
+ const params: SaveGladiaTranscriptionParams = {
137
+ gladiaTranscriptionId: "test-transcription-id",
138
+ };
139
+
140
+ // Mock setupActivity
141
+ vi.mocked(setupActivity).mockResolvedValue({
142
+ client: mockClient,
143
+ objectId: "test-object-id",
144
+ inputType: 'objectIds',
145
+ params,
146
+ } as unknown as ActivityContext<SaveGladiaTranscriptionParams>);
147
+
148
+ const payload = createTestPayload(params, "test-object-id");
149
+ const result: TextExtractionResult = await testEnv.run(saveGladiaTranscription, payload);
150
+
151
+ expect(result).toMatchObject({
152
+ hasText: true,
153
+ objectId: "test-object-id",
154
+ status: TextExtractionStatus.success,
155
+ });
156
+ expect(result.message).toContain("saved with 2 segments");
157
+ });
158
+
159
+ it("should handle transcription in file mode", async () => {
160
+ const { setupActivity } = await import("../../dsl/setup/ActivityContext.js");
161
+ const { FetchClient } = await import("@vertesia/api-fetch-client");
162
+
163
+ const mockFetchClient = {
164
+ withHeaders: vi.fn().mockReturnThis(),
165
+ get: vi.fn().mockResolvedValue(mockGladiaTranscriptionResult),
166
+ };
167
+ vi.mocked(FetchClient).mockImplementation(function(this: any) {
168
+ return mockFetchClient as any;
169
+ });
170
+
171
+ const mockClient = {
172
+ projects: {
173
+ integrations: {
174
+ retrieve: vi.fn().mockResolvedValue({
175
+ enabled: true,
176
+ api_key: "test-api-key",
177
+ url: "https://api.gladia.io/v2",
178
+ }),
179
+ },
180
+ },
181
+ files: {
182
+ uploadText: vi.fn().mockResolvedValue({}),
183
+ },
184
+ } as unknown as VertesiaClient;
185
+
186
+ const params: SaveGladiaTranscriptionParams = {
187
+ gladiaTranscriptionId: "test-transcription-id",
188
+ output_storage_path: "test-storage-path",
189
+ };
190
+
191
+ vi.mocked(setupActivity).mockResolvedValue({
192
+ client: mockClient,
193
+ file: { url: "gs://test-bucket/audio.mp3", mimetype: "audio/mpeg" },
194
+ inputType: 'files',
195
+ params,
196
+ } as unknown as ActivityContext<SaveGladiaTranscriptionParams>);
197
+
198
+ const payload = createTestPayload(
199
+ params,
200
+ undefined,
201
+ { url: "gs://test-bucket/audio.mp3", mimetype: "audio/mpeg" }
202
+ );
203
+ const result: TextExtractionResult = await testEnv.run(saveGladiaTranscription, payload);
204
+
205
+ expect(result).toMatchObject({
206
+ hasText: true,
207
+ objectId: "test-storage-path",
208
+ status: TextExtractionStatus.success,
209
+ });
210
+ expect(result.message).toContain("completed with 2 segments");
211
+ });
212
+
213
+ it("should handle Gladia integration not enabled", async () => {
214
+ const { setupActivity } = await import("../../dsl/setup/ActivityContext.js");
215
+
216
+ const mockClient = {
217
+ projects: {
218
+ integrations: {
219
+ retrieve: vi.fn().mockResolvedValue({
220
+ enabled: false,
221
+ }),
222
+ },
223
+ },
224
+ } as unknown as VertesiaClient;
225
+
226
+ const params: SaveGladiaTranscriptionParams = {
227
+ gladiaTranscriptionId: "test-transcription-id",
228
+ };
229
+
230
+ vi.mocked(setupActivity).mockResolvedValue({
231
+ client: mockClient,
232
+ objectId: "test-object-id",
233
+ inputType: 'objectIds',
234
+ params,
235
+ } as unknown as ActivityContext<SaveGladiaTranscriptionParams>);
236
+
237
+ const payload = createTestPayload(params, "test-object-id");
238
+ const result: TextExtractionResult = await testEnv.run(saveGladiaTranscription, payload);
239
+
240
+ expect(result).toMatchObject({
241
+ hasText: false,
242
+ objectId: "test-object-id",
243
+ status: TextExtractionStatus.error,
244
+ error: "Gladia integration not enabled",
245
+ });
246
+ });
247
+
248
+ it("should handle Gladia transcription error status", async () => {
249
+ const { setupActivity } = await import("../../dsl/setup/ActivityContext.js");
250
+ const { FetchClient } = await import("@vertesia/api-fetch-client");
251
+
252
+ const mockFetchClient = {
253
+ withHeaders: vi.fn().mockReturnThis(),
254
+ get: vi.fn().mockResolvedValue({
255
+ id: "test-transcription-id",
256
+ status: "error",
257
+ }),
258
+ };
259
+ vi.mocked(FetchClient).mockImplementation(function(this: any) {
260
+ return mockFetchClient as any;
261
+ });
262
+
263
+ const mockClient = {
264
+ projects: {
265
+ integrations: {
266
+ retrieve: vi.fn().mockResolvedValue({
267
+ enabled: true,
268
+ api_key: "test-api-key",
269
+ url: "https://api.gladia.io/v2",
270
+ }),
271
+ },
272
+ },
273
+ } as unknown as VertesiaClient;
274
+
275
+ const params: SaveGladiaTranscriptionParams = {
276
+ gladiaTranscriptionId: "test-transcription-id",
277
+ };
278
+
279
+ vi.mocked(setupActivity).mockResolvedValue({
280
+ client: mockClient,
281
+ objectId: "test-object-id",
282
+ inputType: 'objectIds',
283
+ params,
284
+ } as unknown as ActivityContext<SaveGladiaTranscriptionParams>);
285
+
286
+ const payload = createTestPayload(params, "test-object-id");
287
+ const result: TextExtractionResult = await testEnv.run(saveGladiaTranscription, payload);
288
+
289
+ expect(result).toMatchObject({
290
+ hasText: false,
291
+ objectId: "test-object-id",
292
+ status: TextExtractionStatus.error,
293
+ error: "Gladia transcription failed",
294
+ });
295
+ });
296
+
297
+ it("should handle Gladia transcription not ready", async () => {
298
+ const { setupActivity } = await import("../../dsl/setup/ActivityContext.js");
299
+ const { FetchClient } = await import("@vertesia/api-fetch-client");
300
+
301
+ const mockFetchClient = {
302
+ withHeaders: vi.fn().mockReturnThis(),
303
+ get: vi.fn().mockResolvedValue({
304
+ id: "test-transcription-id",
305
+ status: "processing",
306
+ }),
307
+ };
308
+ vi.mocked(FetchClient).mockImplementation(function(this: any) {
309
+ return mockFetchClient as any;
310
+ });
311
+
312
+ const mockClient = {
313
+ projects: {
314
+ integrations: {
315
+ retrieve: vi.fn().mockResolvedValue({
316
+ enabled: true,
317
+ api_key: "test-api-key",
318
+ url: "https://api.gladia.io/v2",
319
+ }),
320
+ },
321
+ },
322
+ } as unknown as VertesiaClient;
323
+
324
+ const params: SaveGladiaTranscriptionParams = {
325
+ gladiaTranscriptionId: "test-transcription-id",
326
+ };
327
+
328
+ vi.mocked(setupActivity).mockResolvedValue({
329
+ client: mockClient,
330
+ objectId: "test-object-id",
331
+ inputType: 'objectIds',
332
+ params,
333
+ } as unknown as ActivityContext<SaveGladiaTranscriptionParams>);
334
+
335
+ const payload = createTestPayload(params, "test-object-id");
336
+ const result: TextExtractionResult = await testEnv.run(saveGladiaTranscription, payload);
337
+
338
+ expect(result).toMatchObject({
339
+ hasText: false,
340
+ objectId: "test-object-id",
341
+ status: TextExtractionStatus.error,
342
+ });
343
+ expect(result.error).toContain("not ready: processing");
344
+ });
345
+
346
+ it("should handle empty transcript", async () => {
347
+ const { setupActivity } = await import("../../dsl/setup/ActivityContext.js");
348
+ const { FetchClient } = await import("@vertesia/api-fetch-client");
349
+
350
+ const mockFetchClient = {
351
+ withHeaders: vi.fn().mockReturnThis(),
352
+ get: vi.fn().mockResolvedValue({
353
+ ...mockGladiaTranscriptionResult,
354
+ result: {
355
+ ...mockGladiaTranscriptionResult.result,
356
+ transcription: {
357
+ full_transcript: "",
358
+ languages: [],
359
+ utterances: [],
360
+ },
361
+ },
362
+ }),
363
+ };
364
+ vi.mocked(FetchClient).mockImplementation(function(this: any) {
365
+ return mockFetchClient as any;
366
+ });
367
+
368
+ const mockClient = {
369
+ projects: {
370
+ integrations: {
371
+ retrieve: vi.fn().mockResolvedValue({
372
+ enabled: true,
373
+ api_key: "test-api-key",
374
+ url: "https://api.gladia.io/v2",
375
+ }),
376
+ },
377
+ },
378
+ objects: {
379
+ retrieve: vi.fn().mockResolvedValue({
380
+ content: { etag: "test-etag" },
381
+ }),
382
+ update: vi.fn().mockResolvedValue({}),
383
+ },
384
+ } as unknown as VertesiaClient;
385
+
386
+ const params: SaveGladiaTranscriptionParams = {
387
+ gladiaTranscriptionId: "test-transcription-id",
388
+ };
389
+
390
+ vi.mocked(setupActivity).mockResolvedValue({
391
+ client: mockClient,
392
+ objectId: "test-object-id",
393
+ inputType: 'objectIds',
394
+ params,
395
+ } as unknown as ActivityContext<SaveGladiaTranscriptionParams>);
396
+
397
+ const payload = createTestPayload(params, "test-object-id");
398
+ const result: TextExtractionResult = await testEnv.run(saveGladiaTranscription, payload);
399
+
400
+ expect(result).toMatchObject({
401
+ hasText: false,
402
+ objectId: "test-object-id",
403
+ status: TextExtractionStatus.success,
404
+ });
405
+ });
406
+ });
@@ -6,6 +6,7 @@ import { TextExtractionResult, TextExtractionStatus } from "../../result-types.j
6
6
 
7
7
  export interface SaveGladiaTranscriptionParams {
8
8
  gladiaTranscriptionId: string;
9
+ output_storage_path?: string;
9
10
  }
10
11
 
11
12
  export interface SaveGladiaTranscription extends DSLActivitySpec<SaveGladiaTranscriptionParams> {
@@ -19,13 +20,14 @@ const GLADIA_URL = "https://api.gladia.io/v2";
19
20
  * This activity is called after transcribeMedia completes via webhook callback.
20
21
  */
21
22
  export async function saveGladiaTranscription(payload: DSLActivityExecutionPayload<SaveGladiaTranscriptionParams>): Promise<TextExtractionResult> {
22
- const { params, client, objectId } = await setupActivity<SaveGladiaTranscriptionParams>(payload);
23
+ const context = await setupActivity<SaveGladiaTranscriptionParams>(payload);
24
+ const { params, client, inputType } = context;
23
25
 
24
26
  const gladiaConfig = await client.projects.integrations.retrieve(payload.project_id, SupportedIntegrations.gladia) as GladiaConfiguration | undefined;
25
27
  if (!gladiaConfig || !gladiaConfig.enabled) {
26
28
  return {
27
29
  hasText: false,
28
- objectId,
30
+ objectId: inputType === 'objectIds' ? context.objectId : undefined,
29
31
  status: TextExtractionStatus.error,
30
32
  error: "Gladia integration not enabled",
31
33
  };
@@ -34,56 +36,69 @@ export async function saveGladiaTranscription(payload: DSLActivityExecutionPaylo
34
36
  const gladiaClient = new FetchClient(gladiaConfig.url ?? GLADIA_URL);
35
37
  gladiaClient.withHeaders({ "x-gladia-key": gladiaConfig.api_key });
36
38
 
37
- log.info(`Fetching transcription result from Gladia`, { objectId, transcriptionId: params.gladiaTranscriptionId });
39
+ log.info(`Fetching transcription result from Gladia`, { transcriptionId: params.gladiaTranscriptionId });
38
40
 
39
41
  const transcriptionResult = await gladiaClient.get(`/transcription/${params.gladiaTranscriptionId}`) as GladiaTranscriptionResult;
40
42
 
43
+ // Determine storage identifier based on input type
44
+ const storageId = inputType === 'objectIds' ? context.objectId : params.output_storage_path;
45
+
41
46
  if (transcriptionResult.status === 'error') {
42
- log.error(`Gladia transcription failed`, { objectId, error: transcriptionResult });
47
+ log.error(`Gladia transcription failed`, { error: transcriptionResult });
43
48
  return {
44
49
  hasText: false,
45
- objectId,
50
+ objectId: inputType === 'objectIds' ? context.objectId : undefined,
51
+ file: inputType === 'files' ? {
52
+ source_url: context.file.url,
53
+ } : undefined,
46
54
  status: TextExtractionStatus.error,
47
55
  error: "Gladia transcription failed",
48
56
  };
49
57
  }
50
58
 
51
59
  if (transcriptionResult.status !== 'done') {
52
- log.warn(`Gladia transcription not ready`, { objectId, status: transcriptionResult.status });
60
+ log.warn(`Gladia transcription not ready`, { storageId, status: transcriptionResult.status });
53
61
  return {
54
62
  hasText: false,
55
- objectId,
63
+ objectId: storageId,
56
64
  status: TextExtractionStatus.error,
57
65
  error: `Gladia transcription not ready: ${transcriptionResult.status}`,
58
66
  };
59
67
  }
60
68
 
61
- const object = await client.objects.retrieve(objectId, "+text");
62
-
63
69
  const segments = processUtterances(transcriptionResult.result.transcription.utterances);
64
70
  const fullText = transcriptionResult.result.transcription.full_transcript;
65
71
 
66
- await client.objects.update(objectId, {
67
- text: fullText,
68
- text_etag: object.content?.etag,
69
- transcript: {
70
- segments,
71
- etag: object.content?.etag
72
- },
73
- metadata: {
74
- ...object.metadata,
75
- duration: transcriptionResult.result.metadata.audio_duration,
76
- languages: transcriptionResult.result.transcription.languages
77
- } as AudioMetadata | VideoMetadata
78
- });
79
-
80
- log.info(`Saved transcription for object`, { objectId, textLength: fullText?.length, segmentCount: segments.length });
72
+ if (inputType === 'objectIds') {
73
+ // Object mode: save to object store
74
+ const objectId = context.objectId;
75
+ const object = await client.objects.retrieve(objectId, "+text");
76
+
77
+ await client.objects.update(objectId, {
78
+ text: fullText,
79
+ text_etag: object.content?.etag,
80
+ transcript: {
81
+ segments,
82
+ etag: object.content?.etag
83
+ },
84
+ metadata: {
85
+ ...object.metadata,
86
+ duration: transcriptionResult.result.metadata.audio_duration,
87
+ languages: transcriptionResult.result.transcription.languages
88
+ } as AudioMetadata | VideoMetadata
89
+ });
90
+
91
+ log.info(`Saved transcription for object`, { objectId, textLength: fullText?.length, segmentCount: segments.length });
92
+ } else {
93
+ // File mode: don't save to object, just log
94
+ log.info(`Transcription completed (file mode, not saved to object)`, { storageId, textLength: fullText?.length, segmentCount: segments.length });
95
+ }
81
96
 
82
97
  return {
83
98
  hasText: (fullText?.length ?? 0) > 0,
84
- objectId,
99
+ objectId: storageId,
85
100
  status: TextExtractionStatus.success,
86
- message: `Transcription saved with ${segments.length} segments`
101
+ message: `Transcription ${inputType === 'objectIds' ? 'saved' : 'completed'} with ${segments.length} segments`
87
102
  };
88
103
  }
89
104