@vertesia/workflow 1.5.0-dev.20260717.131047Z → 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/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/workflows-bundle.js +16277 -6846
- package/package.json +9 -9
- package/src/activities/generateDocumentProperties.test.ts +642 -0
- package/src/activities/generateDocumentProperties.ts +187 -43
- 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
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type ContentSource, type DSLActivityExecutionPayload, type DSLActivitySpec } from '@vertesia/common';
|
|
2
2
|
import { type TruncateSpec } from '../utils/tokens.js';
|
|
3
3
|
import { type InteractionExecutionParams } from './executeInteraction.js';
|
|
4
|
+
export type GenerateDocumentPropertiesSource = 'auto' | 'text' | 'vision' | 'mixed';
|
|
4
5
|
export interface GenerateDocumentPropertiesParams extends InteractionExecutionParams {
|
|
5
6
|
typesHint?: string[];
|
|
6
7
|
/**
|
|
@@ -8,25 +9,65 @@ export interface GenerateDocumentPropertiesParams extends InteractionExecutionPa
|
|
|
8
9
|
*/
|
|
9
10
|
truncate?: TruncateSpec;
|
|
10
11
|
interactionName?: string;
|
|
12
|
+
/**
|
|
13
|
+
* @deprecated Use source: 'mixed'. Accepted for backward compatibility with existing DSL callers.
|
|
14
|
+
*/
|
|
11
15
|
use_vision?: boolean;
|
|
16
|
+
source?: GenerateDocumentPropertiesSource;
|
|
17
|
+
instructions?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Scoped page-image evidence prepared by intake (`prepareVisionEvidence` scratch refs).
|
|
20
|
+
* When the param is PRESENT (even as an empty array) and the source calls for visual
|
|
21
|
+
* evidence, these refs are the ONLY visual evidence used — never the whole-object
|
|
22
|
+
* `store:{id}` ref, which resolves to ALL pages near-full-res through the rendition
|
|
23
|
+
* generate-and-poll path. An empty array means intake prepared no usable evidence
|
|
24
|
+
* (budget-impossible or no renderable source): extraction then runs text-only or fails
|
|
25
|
+
* with no-source instead of shipping an over-budget payload.
|
|
26
|
+
* Absent = legacy behavior for existing DSL callers.
|
|
27
|
+
*/
|
|
28
|
+
evidence_images?: ContentSource[];
|
|
29
|
+
/**
|
|
30
|
+
* Opt-in freshness guard. When true, the activity computes a fingerprint of the extraction
|
|
31
|
+
* inputs (content etag, type + its object schema, source, instructions, interaction name)
|
|
32
|
+
* and returns `{ status: 'skipped' }` without executing the interaction when the fingerprint
|
|
33
|
+
* stored by a previous successful extraction matches and the object already has non-empty
|
|
34
|
+
* properties. Defaults to false so shared DSL callers keep the always-extract behavior.
|
|
35
|
+
* `payload.vars.forceGeneration` bypasses the skip.
|
|
36
|
+
*/
|
|
37
|
+
skip_if_fresh?: boolean;
|
|
12
38
|
}
|
|
13
39
|
export interface GenerateDocumentProperties extends DSLActivitySpec<GenerateDocumentPropertiesParams> {
|
|
14
40
|
name: 'generateDocumentProperties';
|
|
15
41
|
}
|
|
16
|
-
export
|
|
17
|
-
status:
|
|
42
|
+
export type GenerateDocumentPropertiesResult = {
|
|
43
|
+
status: 'completed';
|
|
44
|
+
} | {
|
|
45
|
+
status: 'failed';
|
|
18
46
|
error: string;
|
|
19
|
-
document?: undefined;
|
|
20
|
-
message?: undefined;
|
|
21
47
|
} | {
|
|
22
48
|
document: string;
|
|
23
|
-
status:
|
|
49
|
+
status: 'skipped';
|
|
24
50
|
message: string;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Stable fingerprint of the inputs that determine the extraction output. Key order is fixed by
|
|
54
|
+
* the object literal so the hash is deterministic.
|
|
55
|
+
*/
|
|
56
|
+
export declare function computeExtractionFingerprint(input: {
|
|
57
|
+
content_etag?: string;
|
|
58
|
+
type_id?: string;
|
|
59
|
+
source: GenerateDocumentPropertiesSource;
|
|
60
|
+
instructions?: string;
|
|
61
|
+
interactionName: string;
|
|
62
|
+
/** The type's object_schema: a schema edit under the same type id must invalidate the fingerprint. */
|
|
63
|
+
object_schema?: unknown;
|
|
64
|
+
/** Scoped vision evidence refs: a different page/profile selection must invalidate the fingerprint.
|
|
65
|
+
* Undefined (legacy callers) keeps previously stored hashes valid. */
|
|
66
|
+
evidence?: string[];
|
|
67
|
+
/** The object's text etag: text can change under the same content etag (re-render,
|
|
68
|
+
* re-conversion, manual edit) and text-consuming extractions must invalidate.
|
|
69
|
+
* Undefined (vision-only callers) keeps previously stored hashes valid. */
|
|
70
|
+
text_etag?: string | null;
|
|
71
|
+
}): string;
|
|
72
|
+
export declare function generateDocumentProperties(payload: DSLActivityExecutionPayload<GenerateDocumentPropertiesParams>): Promise<GenerateDocumentPropertiesResult>;
|
|
32
73
|
//# sourceMappingURL=generateDocumentProperties.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generateDocumentProperties.d.ts","sourceRoot":"","sources":["../../src/activities/generateDocumentProperties.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"generateDocumentProperties.d.ts","sourceRoot":"","sources":["../../src/activities/generateDocumentProperties.ts"],"names":[],"mappings":"AACA,OAAO,EAEH,KAAK,aAAa,EAClB,KAAK,2BAA2B,EAChC,KAAK,eAAe,EAMvB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAE,KAAK,YAAY,EAAoB,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAkC,KAAK,0BAA0B,EAAE,MAAM,yBAAyB,CAAC;AAI1G,MAAM,MAAM,gCAAgC,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;AAapF,MAAM,WAAW,gCAAiC,SAAQ,0BAA0B;IAChF,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB;;OAEG;IACH,QAAQ,CAAC,EAAE,YAAY,CAAC;IAExB,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB,MAAM,CAAC,EAAE,gCAAgC,CAAC;IAE1C,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;;;;;;;OASG;IACH,eAAe,CAAC,EAAE,aAAa,EAAE,CAAC;IAElC;;;;;;;OAOG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CAC3B;AACD,MAAM,WAAW,0BAA2B,SAAQ,eAAe,CAAC,gCAAgC,CAAC;IACjG,IAAI,EAAE,4BAA4B,CAAC;CACtC;AACD,MAAM,MAAM,gCAAgC,GACtC;IAAE,MAAM,EAAE,WAAW,CAAA;CAAE,GACvB;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACnC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/D;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,KAAK,EAAE;IAChD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,gCAAgC,CAAC;IACzC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,sGAAsG;IACtG,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;2EACuE;IACvE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB;;gFAE4E;IAC5E,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B,GAAG,MAAM,CAaT;AAmCD,wBAAsB,0BAA0B,CAC5C,OAAO,EAAE,2BAA2B,CAAC,gCAAgC,CAAC,GACvE,OAAO,CAAC,gCAAgC,CAAC,CAgK3C"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { ApplicationFailure, log } from '@temporalio/activity';
|
|
2
|
+
import { mergePreservingNonExtractable, PDF_RENDITION_NAME, schemaForExtraction, } from '@vertesia/common';
|
|
2
3
|
import { setupActivity } from '../dsl/setup/ActivityContext.js';
|
|
4
|
+
import { md5 } from '../utils/blobs.js';
|
|
3
5
|
import { truncByMaxTokens } from '../utils/tokens.js';
|
|
4
6
|
import { executeInteractionFromActivity } from './executeInteraction.js';
|
|
5
7
|
const INT_EXTRACT_INFORMATION = 'sys:ExtractInformation';
|
|
@@ -9,44 +11,134 @@ function toRetryableError(error) {
|
|
|
9
11
|
}
|
|
10
12
|
return new Error(String(error));
|
|
11
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Stable fingerprint of the inputs that determine the extraction output. Key order is fixed by
|
|
16
|
+
* the object literal so the hash is deterministic.
|
|
17
|
+
*/
|
|
18
|
+
export function computeExtractionFingerprint(input) {
|
|
19
|
+
return md5(JSON.stringify({
|
|
20
|
+
content_etag: input.content_etag,
|
|
21
|
+
type_id: input.type_id,
|
|
22
|
+
source: input.source,
|
|
23
|
+
instructions: input.instructions,
|
|
24
|
+
interactionName: input.interactionName,
|
|
25
|
+
object_schema: input.object_schema,
|
|
26
|
+
...(input.evidence ? { evidence: input.evidence } : {}),
|
|
27
|
+
...(input.text_etag !== undefined ? { text_etag: input.text_etag } : {}),
|
|
28
|
+
}));
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* The fingerprint is persisted inside the generation run info of the last successful extraction
|
|
32
|
+
* (the server appends it to `metadata.generation_runs`). Other writers append runs without a
|
|
33
|
+
* fingerprint, so scan backwards for the most recent extraction entry.
|
|
34
|
+
*/
|
|
35
|
+
function getStoredExtractionFingerprint(metadata) {
|
|
36
|
+
const runs = metadata?.generation_runs;
|
|
37
|
+
if (!Array.isArray(runs)) {
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
for (let i = runs.length - 1; i >= 0; i--) {
|
|
41
|
+
if (runs[i]?.extraction_fingerprint) {
|
|
42
|
+
return runs[i].extraction_fingerprint;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
function getPdfRenditionContent(doc) {
|
|
48
|
+
const renditions = doc.metadata?.renditions;
|
|
49
|
+
if (!Array.isArray(renditions)) {
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
const pdfRendition = renditions.find((rendition) => typeof rendition === 'object' &&
|
|
53
|
+
rendition !== null &&
|
|
54
|
+
rendition.name === PDF_RENDITION_NAME &&
|
|
55
|
+
typeof rendition.content?.source === 'string');
|
|
56
|
+
return pdfRendition?.content;
|
|
57
|
+
}
|
|
12
58
|
export async function generateDocumentProperties(payload) {
|
|
13
59
|
const context = await setupActivity(payload);
|
|
14
60
|
const { params, client, objectId } = context;
|
|
15
61
|
const interactionName = params.interactionName ?? INT_EXTRACT_INFORMATION;
|
|
16
62
|
const project = await context.fetchProject();
|
|
17
|
-
const doc = await client.objects.retrieve(objectId, '+text');
|
|
63
|
+
const doc = await client.objects.retrieve(objectId, '+text +metadata +content');
|
|
18
64
|
const type = doc.type ? await client.types.catalog.resolve(doc.type) : undefined;
|
|
19
|
-
if (!doc?.text && !params.use_vision && !doc?.content?.type?.startsWith('image/')) {
|
|
20
|
-
log.warn(`Object ${objectId} not found or text is empty`);
|
|
21
|
-
return { status: 'failed', error: 'no-text' };
|
|
22
|
-
}
|
|
23
65
|
if (!type?.object_schema) {
|
|
24
66
|
log.info(`Object ${objectId} has no schema`);
|
|
25
67
|
return { document: objectId, status: 'skipped', message: 'no schema defined on type' };
|
|
26
68
|
}
|
|
69
|
+
const source = params.source ?? (params.use_vision ? 'mixed' : 'auto');
|
|
70
|
+
const evidenceProvided = Array.isArray(params.evidence_images);
|
|
71
|
+
const evidenceImages = params.evidence_images?.length ? params.evidence_images : undefined;
|
|
72
|
+
const extractionFingerprint = computeExtractionFingerprint({
|
|
73
|
+
content_etag: doc.content?.etag,
|
|
74
|
+
type_id: type.id,
|
|
75
|
+
source,
|
|
76
|
+
instructions: params.instructions,
|
|
77
|
+
interactionName,
|
|
78
|
+
object_schema: type.object_schema,
|
|
79
|
+
evidence: evidenceImages?.map((image) => image.source ?? image.name ?? ''),
|
|
80
|
+
// text may change under the same content etag; only vision-only extraction ignores it
|
|
81
|
+
text_etag: source === 'vision' ? undefined : (doc.text_etag ?? null),
|
|
82
|
+
});
|
|
83
|
+
if (params.skip_if_fresh && !payload.vars?.forceGeneration) {
|
|
84
|
+
const storedFingerprint = getStoredExtractionFingerprint(doc.metadata);
|
|
85
|
+
const hasProperties = !!doc.properties && Object.keys(doc.properties).length > 0;
|
|
86
|
+
if (storedFingerprint === extractionFingerprint && hasProperties) {
|
|
87
|
+
log.info(`Skipping property extraction for ${objectId}: extraction inputs unchanged`, {
|
|
88
|
+
extractionFingerprint,
|
|
89
|
+
});
|
|
90
|
+
return {
|
|
91
|
+
document: objectId,
|
|
92
|
+
status: 'skipped',
|
|
93
|
+
message: 'properties are fresh (extraction fingerprint matches)',
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
}
|
|
27
97
|
const getImageRef = () => {
|
|
28
98
|
if (doc.content?.type?.startsWith('image/')) {
|
|
29
99
|
return `store:${doc.id}`;
|
|
30
100
|
}
|
|
31
|
-
if (
|
|
101
|
+
if (doc.content?.type?.startsWith('application/pdf')) {
|
|
32
102
|
return `store:${doc.id}`;
|
|
33
103
|
}
|
|
104
|
+
const pdfRendition = getPdfRenditionContent(doc);
|
|
105
|
+
if (pdfRendition?.type?.startsWith('application/pdf')) {
|
|
106
|
+
return pdfRendition;
|
|
107
|
+
}
|
|
34
108
|
log.info(`Object ${objectId} is not an image or pdf`);
|
|
35
109
|
return undefined;
|
|
36
110
|
};
|
|
37
|
-
const
|
|
111
|
+
const hasRealText = !!doc.text?.trim();
|
|
112
|
+
const content = hasRealText && (source === 'auto' || source === 'text' || source === 'mixed')
|
|
113
|
+
? truncByMaxTokens(doc.text ?? '', params.truncate || 30000)
|
|
114
|
+
: undefined;
|
|
115
|
+
const needsVisualEvidence = source === 'vision' || source === 'mixed' || (source === 'auto' && !content);
|
|
116
|
+
// Scoped scratch page refs win over the whole-object store: ref (which resolves to ALL
|
|
117
|
+
// pages near-full-res through the rendition generate-and-poll path). A PRESENT param —
|
|
118
|
+
// even empty — disables the store-ref fallback entirely: intake decided what evidence
|
|
119
|
+
// (if any) may be sent.
|
|
120
|
+
const scopedImages = needsVisualEvidence ? evidenceImages : undefined;
|
|
121
|
+
const imageRef = needsVisualEvidence && !evidenceProvided ? getImageRef() : undefined;
|
|
122
|
+
if (!content && !imageRef && !scopedImages) {
|
|
123
|
+
log.warn(`Object ${objectId} has no text or supported vision source`);
|
|
124
|
+
return { status: 'failed', error: 'no-source' };
|
|
125
|
+
}
|
|
38
126
|
const promptData = {
|
|
39
127
|
content: content,
|
|
40
|
-
image:
|
|
128
|
+
image: imageRef,
|
|
129
|
+
images: scopedImages,
|
|
130
|
+
extraction_instructions: params.instructions,
|
|
41
131
|
human_context: project?.configuration?.human_context ?? undefined,
|
|
42
132
|
};
|
|
43
|
-
|
|
133
|
+
// Strip properties marked x-extract:false so constrained decoding cannot invent them.
|
|
134
|
+
const extractionSchema = schemaForExtraction(type.object_schema);
|
|
135
|
+
log.info(`Extracting information from object ${objectId} with type ${type.name}`, payload.debug_mode ? { params } : undefined);
|
|
44
136
|
let infoRes;
|
|
45
137
|
try {
|
|
46
138
|
infoRes = await executeInteractionFromActivity(client, interactionName, {
|
|
47
139
|
...params,
|
|
48
140
|
include_previous_error: true,
|
|
49
|
-
result_schema:
|
|
141
|
+
result_schema: extractionSchema,
|
|
50
142
|
validate_result: type.strict_mode,
|
|
51
143
|
}, promptData, payload.debug_mode ?? false);
|
|
52
144
|
}
|
|
@@ -73,36 +165,19 @@ export async function generateDocumentProperties(payload) {
|
|
|
73
165
|
}
|
|
74
166
|
throw error;
|
|
75
167
|
}
|
|
76
|
-
const getText = () => {
|
|
77
|
-
if (doc.text) {
|
|
78
|
-
return undefined;
|
|
79
|
-
}
|
|
80
|
-
let text = '';
|
|
81
|
-
const jsonResult = infoRes.result.object();
|
|
82
|
-
if (typeof jsonResult.title === 'string') {
|
|
83
|
-
text += `${jsonResult.title}\n`;
|
|
84
|
-
}
|
|
85
|
-
if (typeof jsonResult.description === 'string') {
|
|
86
|
-
text += jsonResult.description;
|
|
87
|
-
}
|
|
88
|
-
if (text) {
|
|
89
|
-
return text;
|
|
90
|
-
}
|
|
91
|
-
else {
|
|
92
|
-
return undefined;
|
|
93
|
-
}
|
|
94
|
-
};
|
|
95
168
|
log.info(`Extracted information from object ${objectId} with type ${type.name}`, { runId: infoRes.id });
|
|
169
|
+
const extracted = infoRes.result.object() ?? {};
|
|
170
|
+
const existing = doc.properties && typeof doc.properties === 'object' && !Array.isArray(doc.properties)
|
|
171
|
+
? doc.properties
|
|
172
|
+
: {};
|
|
173
|
+
const properties = mergePreservingNonExtractable(existing, extracted, type.object_schema);
|
|
96
174
|
await client.objects.update(doc.id, {
|
|
97
|
-
properties
|
|
98
|
-
...infoRes.result.object(),
|
|
99
|
-
...(doc.text_etag !== undefined ? { etag: doc.text_etag } : {}),
|
|
100
|
-
},
|
|
101
|
-
text: getText(),
|
|
175
|
+
properties,
|
|
102
176
|
generation_run_info: {
|
|
103
177
|
id: infoRes.id,
|
|
104
178
|
date: new Date().toISOString(),
|
|
105
179
|
model: infoRes.modelId ?? '',
|
|
180
|
+
extraction_fingerprint: extractionFingerprint,
|
|
106
181
|
},
|
|
107
182
|
}, { suppressWorkflows: true });
|
|
108
183
|
return { status: 'completed' };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generateDocumentProperties.js","sourceRoot":"","sources":["../../src/activities/generateDocumentProperties.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,GAAG,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"generateDocumentProperties.js","sourceRoot":"","sources":["../../src/activities/generateDocumentProperties.ts"],"names":[],"mappings":"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"}
|
|
@@ -29,26 +29,16 @@ export interface GenerateOrAssignContentTypeParams extends InteractionExecutionP
|
|
|
29
29
|
export interface GenerateOrAssignContentType extends DSLActivitySpec<GenerateOrAssignContentTypeParams> {
|
|
30
30
|
name: 'generateOrAssignContentType';
|
|
31
31
|
}
|
|
32
|
-
export
|
|
33
|
-
status:
|
|
32
|
+
export type GenerateOrAssignContentTypeResult = {
|
|
33
|
+
status: 'skipped';
|
|
34
34
|
message: string;
|
|
35
|
-
error?: undefined;
|
|
36
|
-
id?: undefined;
|
|
37
|
-
name?: undefined;
|
|
38
|
-
isNew?: undefined;
|
|
39
35
|
} | {
|
|
40
|
-
status:
|
|
41
|
-
error:
|
|
42
|
-
message?: undefined;
|
|
43
|
-
id?: undefined;
|
|
44
|
-
name?: undefined;
|
|
45
|
-
isNew?: undefined;
|
|
36
|
+
status: 'failed';
|
|
37
|
+
error: 'no-text';
|
|
46
38
|
} | {
|
|
47
39
|
id: string;
|
|
48
40
|
name: string;
|
|
49
41
|
isNew: boolean;
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
error?: undefined;
|
|
53
|
-
}>;
|
|
42
|
+
};
|
|
43
|
+
export declare function generateOrAssignContentType(payload: DSLActivityExecutionPayload<GenerateOrAssignContentTypeParams>): Promise<GenerateOrAssignContentTypeResult>;
|
|
54
44
|
//# sourceMappingURL=generateOrAssignContentType.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generateOrAssignContentType.d.ts","sourceRoot":"","sources":["../../src/activities/generateOrAssignContentType.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"generateOrAssignContentType.d.ts","sourceRoot":"","sources":["../../src/activities/generateOrAssignContentType.ts"],"names":[],"mappings":"AAEA,OAAO,EAIH,KAAK,2BAA2B,EAChC,KAAK,eAAe,EAIvB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,KAAK,YAAY,EAAoB,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAkC,KAAK,0BAA0B,EAAE,MAAM,yBAAyB,CAAC;AAkC1G,MAAM,WAAW,iCAAkC,SAAQ,0BAA0B;IACjF,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB;;OAEG;IACH,QAAQ,CAAC,EAAE,YAAY,CAAC;IAExB;;;OAGG;IACH,gBAAgB,CAAC,EAAE;QACf,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,qBAAqB,CAAC,EAAE,MAAM,CAAC;KAClC,CAAC;IAEF;;;OAGG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAE/B;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,2BAA4B,SAAQ,eAAe,CAAC,iCAAiC,CAAC;IACnG,IAAI,EAAE,6BAA6B,CAAC;CACvC;AAED,MAAM,MAAM,iCAAiC,GACvC;IACI,MAAM,EAAE,SAAS,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACnB,GACD;IACI,MAAM,EAAE,QAAQ,CAAC;IACjB,KAAK,EAAE,SAAS,CAAC;CACpB,GACD;IACI,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;CAClB,CAAC;AAiBR,wBAAsB,2BAA2B,CAC7C,OAAO,EAAE,2BAA2B,CAAC,iCAAiC,CAAC,GACxE,OAAO,CAAC,iCAAiC,CAAC,CA0L5C"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ApplicationFailure, log } from '@temporalio/activity';
|
|
2
|
-
import { ImageRenditionFormat, } from '@vertesia/common';
|
|
2
|
+
import { ImageRenditionFormat, PDF_RENDITION_NAME, } from '@vertesia/common';
|
|
3
3
|
import { setupActivity } from '../dsl/setup/ActivityContext.js';
|
|
4
4
|
import { truncByMaxTokens } from '../utils/tokens.js';
|
|
5
5
|
import { executeInteractionFromActivity } from './executeInteraction.js';
|
|
@@ -16,12 +16,23 @@ function toRetryableError(error) {
|
|
|
16
16
|
}
|
|
17
17
|
return new Error(String(error));
|
|
18
18
|
}
|
|
19
|
+
function getPdfRenditionContent(doc) {
|
|
20
|
+
const renditions = doc.metadata?.renditions;
|
|
21
|
+
if (!Array.isArray(renditions)) {
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
const pdfRendition = renditions.find((rendition) => typeof rendition === 'object' &&
|
|
25
|
+
rendition !== null &&
|
|
26
|
+
rendition.name === PDF_RENDITION_NAME &&
|
|
27
|
+
typeof rendition.content?.source === 'string');
|
|
28
|
+
return pdfRendition?.content;
|
|
29
|
+
}
|
|
19
30
|
export async function generateOrAssignContentType(payload) {
|
|
20
31
|
const context = await setupActivity(payload);
|
|
21
32
|
const { params, client, objectId } = context;
|
|
22
33
|
const interactionName = params.interactionNames?.selectDocumentType ?? INT_SELECT_DOCUMENT_TYPE;
|
|
23
34
|
log.debug(`SelectDocumentType for object: ${objectId}`, { payload });
|
|
24
|
-
const object = await client.objects.retrieve(objectId, '+text');
|
|
35
|
+
const object = await client.objects.retrieve(objectId, '+text +metadata +content');
|
|
25
36
|
//Expects object.type to be null on first ingestion of content
|
|
26
37
|
//User initiated Content Type change via the Composable UI,
|
|
27
38
|
//sets object.type to null when they let Composable choose for them.
|
|
@@ -33,10 +44,11 @@ export async function generateOrAssignContentType(payload) {
|
|
|
33
44
|
message: `Object already has a type: ${object.type.name}`,
|
|
34
45
|
};
|
|
35
46
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
47
|
+
const pdfRendition = getPdfRenditionContent(object);
|
|
48
|
+
const hasVisionSource = object.content?.type?.startsWith('image/') ||
|
|
49
|
+
object.content?.type?.startsWith('application/pdf') ||
|
|
50
|
+
!!pdfRendition?.type?.startsWith('application/pdf');
|
|
51
|
+
if (!object || (!object.text && !hasVisionSource)) {
|
|
40
52
|
log.info(`Object ${objectId} not found or text is empty and not an image`, {
|
|
41
53
|
object,
|
|
42
54
|
});
|
|
@@ -46,9 +58,12 @@ export async function generateOrAssignContentType(payload) {
|
|
|
46
58
|
schema: true,
|
|
47
59
|
});
|
|
48
60
|
//make a list of all existing types, and add hints if any
|
|
49
|
-
const existing_types = types.filter((t) => !['DocumentPart', 'Rendition'].includes(t.name));
|
|
61
|
+
const existing_types = types.filter((t) => !['DocumentPart', 'Rendition'].includes(t.name) && t.status !== 'draft');
|
|
50
62
|
const content = object.text ? truncByMaxTokens(object.text, params.truncate || 30000) : undefined;
|
|
51
63
|
const getImage = async () => {
|
|
64
|
+
if (pdfRendition?.type?.startsWith('application/pdf')) {
|
|
65
|
+
return pdfRendition;
|
|
66
|
+
}
|
|
52
67
|
if (object.content?.type?.includes('pdf') && object.text?.length && object.text?.length < 100) {
|
|
53
68
|
return `store:${objectId}`;
|
|
54
69
|
}
|
|
@@ -68,12 +83,35 @@ export async function generateOrAssignContentType(payload) {
|
|
|
68
83
|
}
|
|
69
84
|
};
|
|
70
85
|
const fileRef = await getImage();
|
|
71
|
-
|
|
72
|
-
|
|
86
|
+
// Slim catalog for the selection prompt: names + identification guidance only, NO schemas
|
|
87
|
+
// (design intake-v2 §3). The full list (with schemas) is still used for matching and for
|
|
88
|
+
// new-type generation below.
|
|
89
|
+
const selectionCatalog = existing_types.map((t) => ({
|
|
90
|
+
id: t.id,
|
|
91
|
+
name: t.name,
|
|
92
|
+
description: t.description,
|
|
93
|
+
guidance: t.intake?.identification?.guidance,
|
|
94
|
+
distinguish_from: t.intake?.identification?.distinguish_from,
|
|
95
|
+
}));
|
|
96
|
+
// Closed-world output: constrain the result to the eligible type names + 'other', which
|
|
97
|
+
// removes the exact-string-match fragility on the model's answer.
|
|
98
|
+
const selectionResultSchema = {
|
|
99
|
+
type: 'object',
|
|
100
|
+
properties: {
|
|
101
|
+
document_type: {
|
|
102
|
+
type: 'string',
|
|
103
|
+
enum: [...existing_types.map((t) => t.name), 'other'],
|
|
104
|
+
description: "Name of the matching document type, or 'other' when none matches.",
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
required: ['document_type'],
|
|
108
|
+
};
|
|
109
|
+
log.info('Execute SelectDocumentType interaction on content with \nexisting types - passing slim catalog: ' +
|
|
110
|
+
existing_types.filter((t) => !t.tags?.includes('system')).map((t) => t.name));
|
|
73
111
|
let res;
|
|
74
112
|
try {
|
|
75
|
-
res = await executeInteractionFromActivity(client, interactionName, params, {
|
|
76
|
-
existing_types,
|
|
113
|
+
res = await executeInteractionFromActivity(client, interactionName, { ...params, result_schema: selectionResultSchema }, {
|
|
114
|
+
existing_types: selectionCatalog,
|
|
77
115
|
content,
|
|
78
116
|
image: fileRef,
|
|
79
117
|
});
|
|
@@ -102,32 +140,45 @@ export async function generateOrAssignContentType(payload) {
|
|
|
102
140
|
log.debug(`Selected Content Type Result: ${JSON.stringify(jsonResult)}`);
|
|
103
141
|
//if type is not identified or not present in the database, generate a new type
|
|
104
142
|
let selectedType;
|
|
105
|
-
|
|
143
|
+
const existingMatch = existing_types.find((t) => t.name === jsonResult.document_type);
|
|
144
|
+
if (existingMatch) {
|
|
145
|
+
selectedType = { id: existingMatch.id, name: existingMatch.name, isNew: false };
|
|
146
|
+
}
|
|
106
147
|
if (!selectedType) {
|
|
107
148
|
if (params.allowNewContentTypes === false) {
|
|
108
149
|
// Type generation is disabled (handled separately, e.g. via the Studio Assistant), so
|
|
109
150
|
// fall back to the project's default type (or sys:GenericDocument) rather than leaving
|
|
110
|
-
// the document untyped.
|
|
151
|
+
// the document untyped. 'other' is the constrained schema's first-class no-match
|
|
152
|
+
// answer, not a selection defect — only warn on anything else.
|
|
153
|
+
if (jsonResult.document_type && jsonResult.document_type !== 'other') {
|
|
154
|
+
log.warn('Document type selection returned an ineligible or unknown type; assigning fallback', {
|
|
155
|
+
objectId,
|
|
156
|
+
selectedDocumentType: jsonResult.document_type,
|
|
157
|
+
eligibleTypes: existing_types.map((type) => type.name),
|
|
158
|
+
});
|
|
159
|
+
}
|
|
111
160
|
selectedType = await resolveFallbackType(context, params.fallbackTypeId, jsonResult.document_type);
|
|
112
161
|
}
|
|
113
162
|
else {
|
|
114
163
|
log.warn('Document type not identified: starting type generation');
|
|
115
164
|
const newType = await generateNewType(context, existing_types, content, fileRef);
|
|
116
|
-
selectedType = { id: newType.id, name: newType.name };
|
|
165
|
+
selectedType = { id: newType.id, name: newType.name, isNew: true };
|
|
117
166
|
}
|
|
118
167
|
}
|
|
119
168
|
if (!selectedType) {
|
|
120
169
|
log.error('Type not found: ', res.result);
|
|
121
170
|
throw new Error(`Type not found: ${jsonResult.document_type}`);
|
|
122
171
|
}
|
|
123
|
-
//
|
|
172
|
+
// Update object with selected type. Suppress workflow triggers: this is an intake-internal
|
|
173
|
+
// self-write — type updates now emit dirty.type and match the StandardIntake trigger, so an
|
|
174
|
+
// unsuppressed write here would recursively re-run intake on every type assignment.
|
|
124
175
|
await client.objects.update(objectId, {
|
|
125
176
|
type: selectedType.id,
|
|
126
|
-
});
|
|
177
|
+
}, { suppressWorkflows: true });
|
|
127
178
|
return {
|
|
128
179
|
id: selectedType.id,
|
|
129
180
|
name: selectedType.name,
|
|
130
|
-
isNew:
|
|
181
|
+
isNew: selectedType.isNew,
|
|
131
182
|
};
|
|
132
183
|
}
|
|
133
184
|
/**
|
|
@@ -142,7 +193,7 @@ async function resolveFallbackType(context, fallbackTypeId, selectedDocumentType
|
|
|
142
193
|
fallbackTypeId,
|
|
143
194
|
selectedDocumentType,
|
|
144
195
|
});
|
|
145
|
-
return { id: resolved.id ?? fallbackTypeId, name: resolved.name ?? fallbackTypeId };
|
|
196
|
+
return { id: resolved.id ?? fallbackTypeId, name: resolved.name ?? fallbackTypeId, isNew: false };
|
|
146
197
|
}
|
|
147
198
|
catch (error) {
|
|
148
199
|
log.warn('Configured default content type not resolvable; using GenericDocument', {
|
|
@@ -152,7 +203,7 @@ async function resolveFallbackType(context, fallbackTypeId, selectedDocumentType
|
|
|
152
203
|
}
|
|
153
204
|
}
|
|
154
205
|
log.info('Document type not identified; assigning GenericDocument fallback', { selectedDocumentType });
|
|
155
|
-
return { id: GENERIC_DOCUMENT_TYPE_ID, name: GENERIC_DOCUMENT_TYPE_NAME };
|
|
206
|
+
return { id: GENERIC_DOCUMENT_TYPE_ID, name: GENERIC_DOCUMENT_TYPE_NAME, isNew: false };
|
|
156
207
|
}
|
|
157
208
|
async function generateNewType(context, existing_types, content, fileRef) {
|
|
158
209
|
const { client, params } = context;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generateOrAssignContentType.js","sourceRoot":"","sources":["../../src/activities/generateOrAssignContentType.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"generateOrAssignContentType.js","sourceRoot":"","sources":["../../src/activities/generateOrAssignContentType.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { type ExecFileOptions } from 'node:child_process';
|
|
2
|
+
/** 10MB buffer for ffmpeg output. */
|
|
3
|
+
export declare const FFMPEG_MAX_BUFFER: number;
|
|
4
|
+
/**
|
|
5
|
+
* Anchor the child-process deadline at the moment the Activity starts, so every later command derives its timeout from a
|
|
6
|
+
* stable point regardless of how long input download took.
|
|
7
|
+
*/
|
|
8
|
+
export declare function initializeActivityCommandDeadline(): number;
|
|
9
|
+
/**
|
|
10
|
+
* Execute media tooling with Temporal cancellation propagated to the child process.
|
|
11
|
+
*
|
|
12
|
+
* Temporal can begin a retry after an attempt times out while the original worker process is still running. Passing the
|
|
13
|
+
* Activity cancellation signal prevents an orphaned ffmpeg process from competing with its retry for CPU.
|
|
14
|
+
*/
|
|
15
|
+
export declare function execActivityFile(command: string, args: string[], options?: ExecFileOptions): Promise<{
|
|
16
|
+
stdout: string;
|
|
17
|
+
stderr: string;
|
|
18
|
+
}>;
|
|
19
|
+
export interface ProgressAwareOptions {
|
|
20
|
+
/**
|
|
21
|
+
* Coarse upper bound on retained stdout/stderr, counted in UTF-16 code units (not UTF-8 bytes). ffmpeg output is
|
|
22
|
+
* ASCII-dominant so this closely tracks bytes; it only exists to keep captured output from growing without bound
|
|
23
|
+
* (older output is dropped — tail retained — rather than failing the command). Not a strict byte cap.
|
|
24
|
+
*/
|
|
25
|
+
maxBuffer?: number;
|
|
26
|
+
stallTimeoutMs?: number;
|
|
27
|
+
}
|
|
28
|
+
export interface ProgressTracker {
|
|
29
|
+
/** Feed a raw output chunk; returns true when a monotonic progress field advanced past its previous maximum. */
|
|
30
|
+
observe(chunk: string): boolean;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Track ffmpeg forward progress across arbitrarily-chunked output.
|
|
34
|
+
*
|
|
35
|
+
* Node delivers stream data in arbitrary slices, so a marker such as `frame=42` can arrive split across two chunks. The
|
|
36
|
+
* tracker buffers partial records until a `\r`/`\n` delimiter completes them, then reports advancement only when the
|
|
37
|
+
* parsed frame count or media timestamp exceeds the previous maximum — repeated identical stats from a wedged encoder do
|
|
38
|
+
* not count as progress.
|
|
39
|
+
*/
|
|
40
|
+
export declare function createFfmpegProgressTracker(): ProgressTracker;
|
|
41
|
+
/**
|
|
42
|
+
* Execute a long-running media command while enforcing a progress-stall watchdog on top of the Activity deadline and
|
|
43
|
+
* cancellation.
|
|
44
|
+
*
|
|
45
|
+
* The worker heartbeats every Activity on a fixed interval, so a wedged ffmpeg child that stops emitting progress would
|
|
46
|
+
* otherwise keep the Activity alive until its multi-hour Start-to-Close timeout. Watching ffmpeg's progress markers lets
|
|
47
|
+
* us terminate a stalled encode within `stallTimeoutMs` so Temporal retries it promptly (escalating to a faster preset
|
|
48
|
+
* on the next attempt). A stall is surfaced as a `killed` error so it propagates as an Activity failure via
|
|
49
|
+
* {@link rethrowIfActivityStopped} instead of being swallowed into a missing rendition.
|
|
50
|
+
*/
|
|
51
|
+
export declare function execActivityFileWithProgress(command: string, args: string[], { maxBuffer, stallTimeoutMs }?: ProgressAwareOptions): Promise<{
|
|
52
|
+
stdout: string;
|
|
53
|
+
stderr: string;
|
|
54
|
+
}>;
|
|
55
|
+
/**
|
|
56
|
+
* Re-throw errors that represent the Activity being stopped (cancellation, Start-to-Close timeout, or a progress-stall
|
|
57
|
+
* kill) so they are not swallowed by rendition fallback handling. Genuine tool failures still return `null` upstream.
|
|
58
|
+
*/
|
|
59
|
+
export declare function rethrowIfActivityStopped(error: unknown): void;
|
|
60
|
+
//# sourceMappingURL=exec.d.ts.map
|