@outputai/core 0.14.1-next.ff4e07b.0 → 0.15.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@outputai/core",
3
- "version": "0.14.1-next.ff4e07b.0",
3
+ "version": "0.15.0",
4
4
  "description": "The core module of the output framework",
5
5
  "type": "module",
6
6
  "engines": {
@@ -46,8 +46,8 @@
46
46
  "output-copy-assets": "./bin/copy_assets.js"
47
47
  },
48
48
  "dependencies": {
49
- "@aws-sdk/client-s3": "3.1136.0",
50
- "@aws-sdk/lib-storage": "3.1136.0",
49
+ "@aws-sdk/client-s3": "3.1138.0",
50
+ "@aws-sdk/lib-storage": "3.1138.0",
51
51
  "@babel/generator": "7.29.1",
52
52
  "@babel/parser": "7.29.9",
53
53
  "@babel/traverse": "7.29.0",
@@ -59,11 +59,11 @@
59
59
  "@temporalio/worker": "1.24.0",
60
60
  "@temporalio/workflow": "1.24.0",
61
61
  "folder-hash": "4.1.3",
62
- "js-yaml": "4.3.2",
62
+ "js-yaml": "5.4.2",
63
63
  "json-stream-stringify": "3.1.7",
64
64
  "redis": "5.12.1",
65
65
  "stacktrace-parser": "0.1.11",
66
- "undici": "8.10.2",
66
+ "undici": "8.11.0",
67
67
  "winston": "3.19.0"
68
68
  },
69
69
  "peerDependencies": {
@@ -0,0 +1,25 @@
1
+ const serializeValue = value => typeof value?.toISOString === 'function' ? value.toISOString() : value;
2
+
3
+ /**
4
+ * Converts Datetime (Date) search attribute values to ISO strings so the result survives JSON and structured-clone boundaries identically.
5
+ *
6
+ * @param {Record<string, unknown[]>} [searchAttributes] Temporal untyped search attributes
7
+ * @returns {Record<string, Array<string|number|boolean>>|undefined} Undefined when there are no attributes
8
+ */
9
+ export const serializeSearchAttributes = searchAttributes =>
10
+ Object.keys( searchAttributes ?? {} ).length ?
11
+ Object.fromEntries( Object.entries( searchAttributes ).map( ( [ k, values ] ) => [ k, values.map( serializeValue ) ] ) ) :
12
+ undefined;
13
+
14
+ const isSystemAttribute = name => name.startsWith( 'Temporal' ) || name === 'BuildIds';
15
+
16
+ /**
17
+ * Drops Temporal system search attributes so the rest can be forwarded to child workflows.
18
+ *
19
+ * @param {Record<string, unknown[]>} [searchAttributes] Temporal untyped search attributes
20
+ * @returns {Record<string, unknown[]>|undefined} Undefined when nothing remains
21
+ */
22
+ export const inheritableSearchAttributes = searchAttributes => {
23
+ const entries = Object.entries( searchAttributes ?? {} ).filter( ( [ k ] ) => !isSystemAttribute( k ) );
24
+ return entries.length ? Object.fromEntries( entries ) : undefined;
25
+ };
@@ -1,3 +1,5 @@
1
+ import { serializeSearchAttributes } from './search_attributes.js';
2
+
1
3
  export const createWorkflowDetails = info => ( {
2
4
  attempt: info.attempt,
3
5
  continuedFromExecutionRunId: info.continuedFromExecutionRunId,
@@ -8,5 +10,6 @@ export const createWorkflowDetails = info => ( {
8
10
  runStartTime: info.runStartTime.getTime(),
9
11
  startTime: info.startTime.getTime(),
10
12
  workflowId: info.workflowId,
11
- workflowType: info.workflowType
13
+ workflowType: info.workflowType,
14
+ searchAttributes: serializeSearchAttributes( info.searchAttributes )
12
15
  } );
@@ -77,6 +77,12 @@ export interface WorkflowDetails {
77
77
  * Starts at 1 and increments for every retry if there is a `retryPolicy`
78
78
  */
79
79
  attempt: number;
80
+ /**
81
+ * Temporal search attributes set on this workflow execution, if any. Datetime values are ISO strings.
82
+ * Uses the untyped form because `typedSearchAttributes` does not survive the sink/activity-header
83
+ * serialization boundary (https://github.com/temporalio/sdk-typescript/issues/1635).
84
+ */
85
+ searchAttributes?: Record<string, string[] | number[] | boolean[]>;
80
86
  }
81
87
 
82
88
  /**
@@ -2,6 +2,7 @@
2
2
  import { proxyActivities, inWorkflowContext, executeChild, workflowInfo, uuid4, ParentClosePolicy, upsertMemo } from '@temporalio/workflow';
3
3
  import { WorkflowValidator } from './validations/index.js';
4
4
  import { toUrlSafeBase64 } from '#helpers/string';
5
+ import { inheritableSearchAttributes } from '#helpers/search_attributes';
5
6
  import { WorkflowContext } from '#helpers/workflow_context';
6
7
  import { deepMerge } from '#helpers/object';
7
8
  import { defaultOptions } from './workflow_activity_options.js';
@@ -48,7 +49,7 @@ export function workflow( { name, description, inputSchema, outputSchema, fn, op
48
49
  );
49
50
  }
50
51
 
51
- const { workflowId, runId, memo, root } = workflowInfo();
52
+ const { workflowId, runId, memo, root, searchAttributes } = workflowInfo();
52
53
  const isRoot = !root;
53
54
 
54
55
  checkGlobalContextContamination( runId );
@@ -59,7 +60,14 @@ export function workflow( { name, description, inputSchema, outputSchema, fn, op
59
60
  const parentClosePolicy = ParentClosePolicy[invocationOptions?.detached ? 'ABANDON' : 'TERMINATE'];
60
61
  const childWorkflowId = `${workflowId}-${toUrlSafeBase64( uuid4() )}`;
61
62
  const args = [ input, { activityOptions: invocationOptions?.activityOptions } ];
62
- return executeChild( name, { args, workflowId: childWorkflowId, parentClosePolicy, memo } );
63
+ const childSearchAttributes = inheritableSearchAttributes( searchAttributes );
64
+ return executeChild( name, {
65
+ args,
66
+ workflowId: childWorkflowId,
67
+ parentClosePolicy,
68
+ memo,
69
+ ...( childSearchAttributes && { searchAttributes: childSearchAttributes } )
70
+ } );
63
71
  }
64
72
 
65
73
  // Resolve the activity options: invocation options > definition options > parent options > default options, then enforce final SDK options