@vertesia/workflow 1.5.0-dev.20260714.072725Z → 1.5.0-dev.20260722.120446Z
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/activities/generateDocumentProperties.d.ts +54 -13
- package/lib/activities/generateDocumentProperties.d.ts.map +1 -1
- package/lib/activities/generateDocumentProperties.js +109 -34
- package/lib/activities/generateDocumentProperties.js.map +1 -1
- package/lib/activities/generateEmbeddings.d.ts.map +1 -1
- package/lib/activities/generateEmbeddings.js +14 -22
- package/lib/activities/generateEmbeddings.js.map +1 -1
- package/lib/activities/generateOrAssignContentType.d.ts +6 -16
- package/lib/activities/generateOrAssignContentType.d.ts.map +1 -1
- package/lib/activities/generateOrAssignContentType.js +70 -19
- package/lib/activities/generateOrAssignContentType.js.map +1 -1
- package/lib/activities/media/exec.d.ts +60 -0
- package/lib/activities/media/exec.d.ts.map +1 -0
- package/lib/activities/media/exec.js +212 -0
- package/lib/activities/media/exec.js.map +1 -0
- package/lib/activities/media/prepareAudio.d.ts.map +1 -1
- package/lib/activities/media/prepareAudio.js +7 -6
- package/lib/activities/media/prepareAudio.js.map +1 -1
- package/lib/activities/media/prepareVideo.d.ts +5 -0
- package/lib/activities/media/prepareVideo.d.ts.map +1 -1
- package/lib/activities/media/prepareVideo.js +37 -13
- package/lib/activities/media/prepareVideo.js.map +1 -1
- package/lib/activities/media/probeMediaStreams.d.ts.map +1 -1
- package/lib/activities/media/probeMediaStreams.js +7 -6
- package/lib/activities/media/probeMediaStreams.js.map +1 -1
- package/lib/activities/renditions/generateVideoRendition.d.ts.map +1 -1
- package/lib/activities/renditions/generateVideoRendition.js +7 -5
- package/lib/activities/renditions/generateVideoRendition.js.map +1 -1
- package/lib/dsl/dsl-workflow.js +3 -0
- package/lib/dsl/dsl-workflow.js.map +1 -1
- package/lib/dsl/dslProxyActivities.d.ts +1 -0
- package/lib/dsl/dslProxyActivities.d.ts.map +1 -1
- package/lib/dsl/dslProxyActivities.js +9 -0
- package/lib/dsl/dslProxyActivities.js.map +1 -1
- package/lib/errors.d.ts.map +1 -1
- package/lib/errors.js +5 -0
- package/lib/errors.js.map +1 -1
- package/lib/workflows-bundle.js +16111 -6668
- package/package.json +17 -16
- package/src/activities/generateDocumentProperties.test.ts +642 -0
- package/src/activities/generateDocumentProperties.ts +187 -43
- package/src/activities/generateEmbeddings.test.ts +114 -0
- package/src/activities/generateEmbeddings.ts +17 -24
- package/src/activities/generateOrAssignContentType.test.ts +196 -0
- package/src/activities/generateOrAssignContentType.ts +115 -30
- package/src/activities/media/exec.test.ts +194 -0
- package/src/activities/media/exec.ts +265 -0
- package/src/activities/media/prepareAudio.ts +12 -7
- package/src/activities/media/prepareVideo.test.ts +27 -0
- package/src/activities/media/prepareVideo.ts +54 -18
- package/src/activities/media/probeMediaStreams.test.ts +7 -8
- package/src/activities/media/probeMediaStreams.ts +11 -7
- package/src/activities/renditions/generateVideoRendition.ts +12 -6
- package/src/dsl/dsl-workflow.test.ts +4 -0
- package/src/dsl/dsl-workflow.ts +3 -0
- package/src/dsl/dslProxyActivities.test.ts +23 -0
- package/src/dsl/dslProxyActivities.ts +11 -0
- package/src/errors.ts +5 -0
|
@@ -1,16 +1,18 @@
|
|
|
1
|
-
import { execFile as execFileCallback } from 'node:child_process';
|
|
2
1
|
import fs from 'node:fs';
|
|
3
2
|
import os from 'node:os';
|
|
4
3
|
import path from 'node:path';
|
|
5
|
-
import { promisify } from 'node:util';
|
|
6
4
|
import { log } from '@temporalio/activity';
|
|
7
5
|
import type { DSLActivityExecutionPayload, DSLActivitySpec } from '@vertesia/common';
|
|
8
6
|
import { setupActivity } from '../../dsl/setup/ActivityContext.js';
|
|
9
7
|
import { DocumentNotFoundError, WorkflowParamNotFoundError } from '../../errors.js';
|
|
10
8
|
import { saveBlobToTempFile } from '../../utils/blobs.js';
|
|
11
9
|
import { type ImageRenditionParams, uploadRenditionPages } from '../../utils/renditions.js';
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
import {
|
|
11
|
+
execActivityFile,
|
|
12
|
+
execActivityFileWithProgress,
|
|
13
|
+
initializeActivityCommandDeadline,
|
|
14
|
+
rethrowIfActivityStopped,
|
|
15
|
+
} from '../media/exec.js';
|
|
14
16
|
|
|
15
17
|
interface GenerateVideoRenditionParams extends ImageRenditionParams {}
|
|
16
18
|
|
|
@@ -32,7 +34,7 @@ interface VideoMetadata {
|
|
|
32
34
|
async function getVideoMetadata(videoPath: string): Promise<VideoMetadata> {
|
|
33
35
|
try {
|
|
34
36
|
const args = ['-v', 'quiet', '-print_format', 'json', '-show_format', '-show_streams', videoPath];
|
|
35
|
-
const { stdout } = await
|
|
37
|
+
const { stdout } = await execActivityFile('ffprobe', args);
|
|
36
38
|
const metadata = JSON.parse(stdout.toString()) as {
|
|
37
39
|
streams?: Array<{ codec_type?: string; width?: number; height?: number }>;
|
|
38
40
|
format?: { duration?: string };
|
|
@@ -45,6 +47,7 @@ async function getVideoMetadata(videoPath: string): Promise<VideoMetadata> {
|
|
|
45
47
|
|
|
46
48
|
return { duration, width, height };
|
|
47
49
|
} catch (error) {
|
|
50
|
+
rethrowIfActivityStopped(error);
|
|
48
51
|
log.error(`Failed to get video metadata: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
49
52
|
throw new Error(`Failed to probe video metadata: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
50
53
|
}
|
|
@@ -79,7 +82,7 @@ async function generateThumbnail(
|
|
|
79
82
|
];
|
|
80
83
|
log.info(`Generating thumbnail at ${timestamp}s`, { command: 'ffmpeg', args: command });
|
|
81
84
|
try {
|
|
82
|
-
const { stderr } = await
|
|
85
|
+
const { stderr } = await execActivityFileWithProgress('ffmpeg', command);
|
|
83
86
|
const stderrText = stderr.toString();
|
|
84
87
|
|
|
85
88
|
// Log any warnings from ffmpeg
|
|
@@ -96,6 +99,7 @@ async function generateThumbnail(
|
|
|
96
99
|
return undefined;
|
|
97
100
|
}
|
|
98
101
|
} catch (error) {
|
|
102
|
+
rethrowIfActivityStopped(error);
|
|
99
103
|
log.error(
|
|
100
104
|
`Failed to generate thumbnail at ${timestamp}s: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
101
105
|
);
|
|
@@ -104,6 +108,7 @@ async function generateThumbnail(
|
|
|
104
108
|
}
|
|
105
109
|
|
|
106
110
|
export async function generateVideoRendition(payload: DSLActivityExecutionPayload<GenerateVideoRenditionParams>) {
|
|
111
|
+
initializeActivityCommandDeadline();
|
|
107
112
|
const { client, objectId, params: originParams } = await setupActivity<GenerateVideoRenditionParams>(payload);
|
|
108
113
|
|
|
109
114
|
// Fix: Use maxHeightWidth if max_hw is not provided
|
|
@@ -209,6 +214,7 @@ export async function generateVideoRendition(payload: DSLActivityExecutionPayloa
|
|
|
209
214
|
requestedCount: thumbnailCount,
|
|
210
215
|
});
|
|
211
216
|
} catch (error) {
|
|
217
|
+
rethrowIfActivityStopped(error);
|
|
212
218
|
log.error(`Error generating thumbnails for video: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
213
219
|
throw new Error(`Failed to generate thumbnails for video: ${objectId}`);
|
|
214
220
|
} finally {
|
|
@@ -8,6 +8,7 @@ describe('Workflow DSL', () => {
|
|
|
8
8
|
{},
|
|
9
9
|
{
|
|
10
10
|
startToCloseTimeout: 1000,
|
|
11
|
+
heartbeatTimeout: 600,
|
|
11
12
|
scheduleToCloseTimeout: 2000,
|
|
12
13
|
scheduleToStartTimeout: 3000,
|
|
13
14
|
retry: {
|
|
@@ -21,6 +22,7 @@ describe('Workflow DSL', () => {
|
|
|
21
22
|
),
|
|
22
23
|
).toEqual({
|
|
23
24
|
startToCloseTimeout: 1000,
|
|
25
|
+
heartbeatTimeout: 600,
|
|
24
26
|
scheduleToCloseTimeout: 2000,
|
|
25
27
|
scheduleToStartTimeout: 3000,
|
|
26
28
|
retry: {
|
|
@@ -38,6 +40,7 @@ describe('Workflow DSL', () => {
|
|
|
38
40
|
computeActivityOptions(
|
|
39
41
|
{
|
|
40
42
|
startToCloseTimeout: 100,
|
|
43
|
+
heartbeatTimeout: 600,
|
|
41
44
|
},
|
|
42
45
|
{
|
|
43
46
|
startToCloseTimeout: 1000,
|
|
@@ -54,6 +57,7 @@ describe('Workflow DSL', () => {
|
|
|
54
57
|
),
|
|
55
58
|
).toEqual({
|
|
56
59
|
startToCloseTimeout: `100ms`, // custom value
|
|
60
|
+
heartbeatTimeout: '600ms',
|
|
57
61
|
scheduleToCloseTimeout: 2000,
|
|
58
62
|
scheduleToStartTimeout: 3000,
|
|
59
63
|
retry: {
|
package/src/dsl/dsl-workflow.ts
CHANGED
|
@@ -603,6 +603,9 @@ function convertDSLActivityOptions(options?: DSLActivityOptions): ActivityOption
|
|
|
603
603
|
if (options.startToCloseTimeout) {
|
|
604
604
|
result.startToCloseTimeout = ms(options.startToCloseTimeout as StringValue);
|
|
605
605
|
}
|
|
606
|
+
if (options.heartbeatTimeout) {
|
|
607
|
+
result.heartbeatTimeout = ms(options.heartbeatTimeout as StringValue);
|
|
608
|
+
}
|
|
606
609
|
if (options.scheduleToCloseTimeout) {
|
|
607
610
|
result.scheduleToCloseTimeout = ms(options.scheduleToCloseTimeout as StringValue);
|
|
608
611
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { stripWorkflowContinuationFromVars } from './dslProxyActivities.js';
|
|
3
|
+
|
|
4
|
+
describe('stripWorkflowContinuationFromVars', () => {
|
|
5
|
+
it('removes continue-as-new state from activity vars', () => {
|
|
6
|
+
const vars = {
|
|
7
|
+
interaction: 'sys:AppDeveloper',
|
|
8
|
+
_continuation: {
|
|
9
|
+
conversationState: { large: true },
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
expect(stripWorkflowContinuationFromVars(vars)).toEqual({
|
|
14
|
+
interaction: 'sys:AppDeveloper',
|
|
15
|
+
});
|
|
16
|
+
expect(vars).toHaveProperty('_continuation');
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('returns primitive and array vars unchanged', () => {
|
|
20
|
+
expect(stripWorkflowContinuationFromVars(undefined)).toBeUndefined();
|
|
21
|
+
expect(stripWorkflowContinuationFromVars(['a'])).toEqual(['a']);
|
|
22
|
+
});
|
|
23
|
+
});
|
|
@@ -14,6 +14,16 @@ export type DslSimplifiedActivityFunction<ParamsT extends object = Record<string
|
|
|
14
14
|
params: ParamsT,
|
|
15
15
|
) => Promise<ReturnT>;
|
|
16
16
|
|
|
17
|
+
export function stripWorkflowContinuationFromVars<T>(vars: T): T {
|
|
18
|
+
if (!vars || typeof vars !== 'object' || Array.isArray(vars) || !('_continuation' in vars)) {
|
|
19
|
+
return vars;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const rest = { ...(vars as Record<string, unknown>) };
|
|
23
|
+
delete rest._continuation;
|
|
24
|
+
return rest as T;
|
|
25
|
+
}
|
|
26
|
+
|
|
17
27
|
export function dslProxyActivities<ActivitiesT extends object>(workflowName: string, options: ActivityOptions = {}) {
|
|
18
28
|
type DslActivities = {
|
|
19
29
|
[K in keyof ActivitiesT]: ActivitiesT[K] extends DslActivityFunction<infer ParamsT, infer ReturnT>
|
|
@@ -34,6 +44,7 @@ export function dslProxyActivities<ActivitiesT extends object>(workflowName: str
|
|
|
34
44
|
return (payload: WorkflowExecutionPayload, params: Record<string, unknown>) => {
|
|
35
45
|
return activityFn({
|
|
36
46
|
...payload,
|
|
47
|
+
vars: stripWorkflowContinuationFromVars(payload.vars),
|
|
37
48
|
activity: {
|
|
38
49
|
name: prop as string,
|
|
39
50
|
},
|
package/src/errors.ts
CHANGED
|
@@ -116,4 +116,9 @@ export const WF_NON_RETRYABLE_ERRORS = [
|
|
|
116
116
|
'TokenExpiredError',
|
|
117
117
|
'ZenoClientNotFoundError',
|
|
118
118
|
'WorkflowExecutionError',
|
|
119
|
+
// Temporal raises NotFoundError when an activity isn't registered on the worker
|
|
120
|
+
// (e.g. a new tool whose activity barrel export was missed). Retrying can never
|
|
121
|
+
// make it appear within a worker version, and the retried failure carries the
|
|
122
|
+
// full activity list which blows the payload size limit — so fail fast.
|
|
123
|
+
'NotFoundError',
|
|
119
124
|
];
|