@primero.ai/temporal-graph-tools 1.2.0 → 1.3.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/README.md +3 -1
- package/dist/examples/mastra-ai-workflow/activities/classify-outage-with-ai.d.ts +1 -1
- package/dist/examples/mastra-ai-workflow/activities/classify-outage-with-ai.d.ts.map +1 -1
- package/dist/examples/mastra-ai-workflow/activities/classify-outage-with-ai.js +21 -29
- package/dist/examples/mastra-ai-workflow/activities/draft-response-with-ai.d.ts +1 -1
- package/dist/examples/mastra-ai-workflow/activities/draft-response-with-ai.d.ts.map +1 -1
- package/dist/examples/mastra-ai-workflow/activities/draft-response-with-ai.js +11 -25
- package/dist/examples/mastra-ai-workflow/activities/enrich-outage-description.d.ts +1 -1
- package/dist/examples/mastra-ai-workflow/activities/enrich-outage-description.d.ts.map +1 -1
- package/dist/examples/mastra-ai-workflow/activities/enrich-outage-description.js +2 -13
- package/dist/examples/mastra-ai-workflow/activities/index.d.ts +2 -2
- package/dist/examples/mastra-ai-workflow/activities/index.d.ts.map +1 -1
- package/dist/examples/mastra-ai-workflow/activities/submit-response.d.ts +1 -1
- package/dist/examples/mastra-ai-workflow/activities/submit-response.d.ts.map +1 -1
- package/dist/examples/mastra-ai-workflow/activities/submit-response.js +5 -14
- package/dist/examples/mastra-ai-workflow/activities/take-ticket.d.ts +1 -1
- package/dist/examples/mastra-ai-workflow/activities/take-ticket.d.ts.map +1 -1
- package/dist/examples/mastra-ai-workflow/activities/take-ticket.js +6 -15
- package/dist/examples/mastra-ai-workflow/workflow.d.ts +3 -0
- package/dist/examples/mastra-ai-workflow/workflow.d.ts.map +1 -0
- package/dist/examples/mastra-ai-workflow/workflow.js +95 -0
- package/dist/examples/trigger-mastra-workflow.js +11 -16
- package/dist/examples/worker.d.ts.map +1 -1
- package/dist/examples/worker.js +25 -16
- package/dist/src/bundler.d.ts +9 -2
- package/dist/src/bundler.d.ts.map +1 -1
- package/dist/src/bundler.js +84 -8
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -0
- package/dist/src/mastra/agent-wrapper.d.ts +2 -2
- package/dist/src/mastra/agent-wrapper.d.ts.map +1 -1
- package/dist/src/mastra/agent-wrapper.js +1 -1
- package/dist/src/mastra/create-activity-with-mastra.d.ts +1 -0
- package/dist/src/mastra/create-activity-with-mastra.d.ts.map +1 -1
- package/dist/src/mastra/create-activity-with-mastra.js +11 -7
- package/dist/src/mastra/with-mastra-agent.d.ts +12 -0
- package/dist/src/mastra/with-mastra-agent.d.ts.map +1 -0
- package/dist/src/mastra/with-mastra-agent.js +4 -0
- package/dist/src/mastra/workflow-compiler.d.ts +23 -0
- package/dist/src/mastra/workflow-compiler.d.ts.map +1 -0
- package/dist/src/mastra/workflow-compiler.js +132 -0
- package/dist/src/workflow/collection.d.ts.map +1 -1
- package/package.json +17 -18
- package/dist/examples/mastra-ai-workflow/workflows.d.ts +0 -2
- package/dist/examples/mastra-ai-workflow/workflows.d.ts.map +0 -1
- package/dist/examples/mastra-ai-workflow/workflows.js +0 -11
- package/dist/examples/mastra-example.d.ts +0 -2
- package/dist/examples/mastra-example.d.ts.map +0 -1
- package/dist/examples/mastra-example.js +0 -103
- package/dist/examples/normal-workflow/activities.d.ts +0 -34
- package/dist/examples/normal-workflow/activities.d.ts.map +0 -1
- package/dist/examples/normal-workflow/activities.js +0 -38
- package/dist/examples/normal-workflow/workflows.d.ts +0 -3
- package/dist/examples/normal-workflow/workflows.d.ts.map +0 -1
- package/dist/examples/normal-workflow/workflows.js +0 -14
- package/dist/examples/trigger-normal-workflow.d.ts +0 -2
- package/dist/examples/trigger-normal-workflow.d.ts.map +0 -1
- package/dist/examples/trigger-normal-workflow.js +0 -43
package/dist/src/bundler.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { createHash } from 'node:crypto';
|
|
3
|
-
import { mkdtemp, rm, writeFile } from 'node:fs/promises';
|
|
1
|
+
import { createHash, createHmac, timingSafeEqual } from 'node:crypto';
|
|
4
2
|
import { existsSync } from 'node:fs';
|
|
3
|
+
import { mkdtemp, rm, writeFile } from 'node:fs/promises';
|
|
5
4
|
import { createRequire } from 'node:module';
|
|
6
5
|
import { tmpdir } from 'node:os';
|
|
6
|
+
import { isAbsolute, join, resolve } from 'node:path';
|
|
7
|
+
import { compileMastraWorkflow, } from './mastra/workflow-compiler.js';
|
|
7
8
|
import { buildWorkflowBundleCode } from './workflow-bundler.js';
|
|
8
9
|
import { collectWorkflowBuildResults } from './workflow/collection.js';
|
|
9
10
|
let cachedEsbuild;
|
|
@@ -27,11 +28,12 @@ async function loadEsbuild() {
|
|
|
27
28
|
throw createLoadError(error);
|
|
28
29
|
}
|
|
29
30
|
}
|
|
30
|
-
export async function loadActivitiesFromBundle(bundle) {
|
|
31
|
+
export async function loadActivitiesFromBundle(bundle, options = {}) {
|
|
31
32
|
if (!bundle || typeof bundle.code !== 'string' || bundle.code.trim().length === 0) {
|
|
32
33
|
throw new Error('Activity bundle code must be a non-empty string.');
|
|
33
34
|
}
|
|
34
35
|
verifyActivityBundleIntegrity(bundle);
|
|
36
|
+
verifyActivityBundleSignature(bundle, options);
|
|
35
37
|
const source = ensureActivityInlineSourceMap(bundle.code, bundle.map);
|
|
36
38
|
const tempPrefix = process.platform === 'win32'
|
|
37
39
|
? join(process.cwd(), '.temporal-graph-tools-')
|
|
@@ -73,9 +75,10 @@ export async function bundleWorkflows(plans, options) {
|
|
|
73
75
|
if (plans.length === 0) {
|
|
74
76
|
throw new Error('bundleWorkflows requires at least one workflow plan.');
|
|
75
77
|
}
|
|
78
|
+
const normalizedPlans = plans.map((plan, index) => normalizeWorkflowPlan(plan, index));
|
|
76
79
|
const seenWorkflowNames = new Set();
|
|
77
|
-
for (let index = 0; index <
|
|
78
|
-
const plan =
|
|
80
|
+
for (let index = 0; index < normalizedPlans.length; index += 1) {
|
|
81
|
+
const plan = normalizedPlans[index];
|
|
79
82
|
const workflowName = typeof plan.workflowName === 'string' ? plan.workflowName.trim() : '';
|
|
80
83
|
if (workflowName.length === 0) {
|
|
81
84
|
throw new Error(`Workflow plan at index ${index} is missing a valid workflowName. Provide workflowName when building workflows.`);
|
|
@@ -85,7 +88,7 @@ export async function bundleWorkflows(plans, options) {
|
|
|
85
88
|
}
|
|
86
89
|
seenWorkflowNames.add(workflowName);
|
|
87
90
|
}
|
|
88
|
-
const collection = collectWorkflowBuildResults(
|
|
91
|
+
const collection = collectWorkflowBuildResults(normalizedPlans);
|
|
89
92
|
const activityBundle = await bundleActivitiesWithEsbuild(collection.activities, options === null || options === void 0 ? void 0 : options.activityBundle);
|
|
90
93
|
const filename = (_a = options === null || options === void 0 ? void 0 : options.filename) !== null && _a !== void 0 ? _a : createBundleFilename(collection.workflows);
|
|
91
94
|
const code = await buildWorkflowBundleCode(collection.workflows, filename);
|
|
@@ -94,6 +97,42 @@ export async function bundleWorkflows(plans, options) {
|
|
|
94
97
|
workflowBundle: { code },
|
|
95
98
|
};
|
|
96
99
|
}
|
|
100
|
+
function normalizeWorkflowPlan(plan, index) {
|
|
101
|
+
if (isWorkflowBuildResult(plan)) {
|
|
102
|
+
return plan;
|
|
103
|
+
}
|
|
104
|
+
if (isMastraWorkflowCompilationInput(plan)) {
|
|
105
|
+
return compileMastraWorkflow(plan.workflow, plan.options);
|
|
106
|
+
}
|
|
107
|
+
if (isMastraWorkflowLike(plan)) {
|
|
108
|
+
return compileMastraWorkflow(plan);
|
|
109
|
+
}
|
|
110
|
+
throw new Error(`Unsupported workflow plan at index ${index}.`);
|
|
111
|
+
}
|
|
112
|
+
function isWorkflowBuildResult(value) {
|
|
113
|
+
if (typeof value !== 'object' || value === null) {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
const candidate = value;
|
|
117
|
+
return (typeof candidate.workflowName === 'string' &&
|
|
118
|
+
typeof candidate.workflowSource === 'string' &&
|
|
119
|
+
typeof candidate.activities === 'object' &&
|
|
120
|
+
candidate.activities !== null);
|
|
121
|
+
}
|
|
122
|
+
function isMastraWorkflowCompilationInput(value) {
|
|
123
|
+
if (typeof value !== 'object' || value === null) {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
const candidate = value;
|
|
127
|
+
return typeof candidate.workflow === 'object' && candidate.workflow !== null;
|
|
128
|
+
}
|
|
129
|
+
function isMastraWorkflowLike(value) {
|
|
130
|
+
if (typeof value !== 'object' || value === null) {
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
const candidate = value;
|
|
134
|
+
return Array.isArray(candidate.stepGraph);
|
|
135
|
+
}
|
|
97
136
|
function createBundleFilename(workflows) {
|
|
98
137
|
const baseName = workflows
|
|
99
138
|
.map((workflow) => workflow.workflowName)
|
|
@@ -154,11 +193,14 @@ async function bundleActivitiesWithEsbuild(bundles, options = {}) {
|
|
|
154
193
|
if (!jsFile) {
|
|
155
194
|
throw new Error('Failed to generate activities bundle.');
|
|
156
195
|
}
|
|
196
|
+
const signingKey = normalizeSigningKey(options.signingKey);
|
|
197
|
+
const integrity = createIntegrityHash(jsFile.text);
|
|
157
198
|
return {
|
|
158
199
|
filename,
|
|
159
200
|
code: jsFile.text,
|
|
160
201
|
...(mapFile ? { map: mapFile.text } : {}),
|
|
161
|
-
integrity
|
|
202
|
+
integrity,
|
|
203
|
+
...(signingKey ? { signature: createBundleSignature(jsFile.text, signingKey) } : {}),
|
|
162
204
|
};
|
|
163
205
|
}
|
|
164
206
|
function normalizeActivityEntrypoints(cwd, entrypoints) {
|
|
@@ -279,6 +321,17 @@ function createIntegrityHash(code) {
|
|
|
279
321
|
const digest = createHash('sha256').update(code, 'utf8').digest('base64');
|
|
280
322
|
return `sha256-${digest}`;
|
|
281
323
|
}
|
|
324
|
+
function normalizeSigningKey(value) {
|
|
325
|
+
if (typeof value !== 'string') {
|
|
326
|
+
return undefined;
|
|
327
|
+
}
|
|
328
|
+
const trimmed = value.trim();
|
|
329
|
+
return trimmed.length > 0 ? trimmed : undefined;
|
|
330
|
+
}
|
|
331
|
+
function createBundleSignature(code, signingKey) {
|
|
332
|
+
const digest = createHmac('sha256', signingKey).update(code, 'utf8').digest('base64');
|
|
333
|
+
return `hmac-sha256-${digest}`;
|
|
334
|
+
}
|
|
282
335
|
function verifyActivityBundleIntegrity(bundle) {
|
|
283
336
|
if (bundle.integrity) {
|
|
284
337
|
const expected = bundle.integrity.trim();
|
|
@@ -290,3 +343,26 @@ function verifyActivityBundleIntegrity(bundle) {
|
|
|
290
343
|
}
|
|
291
344
|
throw new Error('Activity bundle is missing integrity metadata. Regenerate with bundleWorkflows().');
|
|
292
345
|
}
|
|
346
|
+
function verifyActivityBundleSignature(bundle, options) {
|
|
347
|
+
const signature = typeof bundle.signature === 'string' ? bundle.signature.trim() : '';
|
|
348
|
+
if (signature.length === 0) {
|
|
349
|
+
throw new Error('Unsigned activity bundle rejected. Use bundleWorkflows({ activityBundle: { signingKey } }) and pass verificationKey to loadActivitiesFromBundle().');
|
|
350
|
+
}
|
|
351
|
+
const verificationKey = normalizeSigningKey(options.verificationKey);
|
|
352
|
+
if (!verificationKey) {
|
|
353
|
+
throw new Error('Activity bundle is signed but verificationKey was not provided to loadActivitiesFromBundle().');
|
|
354
|
+
}
|
|
355
|
+
if (!isValidSignatureFormat(signature)) {
|
|
356
|
+
throw new Error('Activity bundle signature has an invalid format.');
|
|
357
|
+
}
|
|
358
|
+
const expected = createBundleSignature(bundle.code, verificationKey);
|
|
359
|
+
const expectedBuffer = Buffer.from(expected, 'utf8');
|
|
360
|
+
const receivedBuffer = Buffer.from(signature, 'utf8');
|
|
361
|
+
if (expectedBuffer.length !== receivedBuffer.length ||
|
|
362
|
+
!timingSafeEqual(expectedBuffer, receivedBuffer)) {
|
|
363
|
+
throw new Error('Activity bundle signature mismatch. Refusing to execute untrusted bundle code.');
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
function isValidSignatureFormat(signature) {
|
|
367
|
+
return /^hmac-sha256-[A-Za-z0-9+/=]+$/.test(signature);
|
|
368
|
+
}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -5,4 +5,6 @@ export { collectWorkflowBuildResults } from './workflow/collection.js';
|
|
|
5
5
|
export * from './bundler.js';
|
|
6
6
|
export * from './mastra/agent-wrapper.js';
|
|
7
7
|
export * from './mastra/create-activity-with-mastra.js';
|
|
8
|
+
export * from './mastra/with-mastra-agent.js';
|
|
9
|
+
export * from './mastra/workflow-compiler.js';
|
|
8
10
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/src/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAA;AAC9E,cAAc,uBAAuB,CAAA;AACrC,OAAO,EAAE,2BAA2B,EAAE,MAAM,0BAA0B,CAAA;AACtE,cAAc,cAAc,CAAA;AAC5B,cAAc,2BAA2B,CAAA;AACzC,cAAc,yCAAyC,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAA;AAC9E,cAAc,uBAAuB,CAAA;AACrC,OAAO,EAAE,2BAA2B,EAAE,MAAM,0BAA0B,CAAA;AACtE,cAAc,cAAc,CAAA;AAC5B,cAAc,2BAA2B,CAAA;AACzC,cAAc,yCAAyC,CAAA;AACvD,cAAc,+BAA+B,CAAA;AAC7C,cAAc,+BAA+B,CAAA"}
|
package/dist/src/index.js
CHANGED
|
@@ -5,3 +5,5 @@ export { collectWorkflowBuildResults } from './workflow/collection.js';
|
|
|
5
5
|
export * from './bundler.js';
|
|
6
6
|
export * from './mastra/agent-wrapper.js';
|
|
7
7
|
export * from './mastra/create-activity-with-mastra.js';
|
|
8
|
+
export * from './mastra/with-mastra-agent.js';
|
|
9
|
+
export * from './mastra/workflow-compiler.js';
|
|
@@ -5,12 +5,12 @@ export type AgentConstructorInput = ConstructorParameters<typeof MastraAgent>[0]
|
|
|
5
5
|
export type AgentRuntimeContext = {
|
|
6
6
|
initializedAgent?: AnyAgent;
|
|
7
7
|
};
|
|
8
|
-
export type
|
|
8
|
+
export type InvokeStructuredAgentOptions<Schema extends z.ZodTypeAny> = {
|
|
9
9
|
agentInput: AgentConstructorInput;
|
|
10
10
|
context: AgentRuntimeContext;
|
|
11
11
|
prompt: string;
|
|
12
12
|
schema: Schema;
|
|
13
13
|
};
|
|
14
|
-
export declare function
|
|
14
|
+
export declare function invokeStructuredAgent<Schema extends z.ZodTypeAny>(options: InvokeStructuredAgentOptions<Schema>): Promise<z.infer<Schema>>;
|
|
15
15
|
export {};
|
|
16
16
|
//# sourceMappingURL=agent-wrapper.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-wrapper.d.ts","sourceRoot":"","sources":["../../../src/mastra/agent-wrapper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,IAAI,WAAW,EAAE,MAAM,oBAAoB,CAAA;AACzD,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAE5B,KAAK,QAAQ,GAAG,YAAY,CAAC,OAAO,WAAW,CAAC,CAAA;AAEhD,MAAM,MAAM,qBAAqB,GAAG,qBAAqB,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC,CAAA;AAEhF,MAAM,MAAM,mBAAmB,GAAG;IAChC,gBAAgB,CAAC,EAAE,QAAQ,CAAA;CAC5B,CAAA;AAED,MAAM,MAAM,
|
|
1
|
+
{"version":3,"file":"agent-wrapper.d.ts","sourceRoot":"","sources":["../../../src/mastra/agent-wrapper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,IAAI,WAAW,EAAE,MAAM,oBAAoB,CAAA;AACzD,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAE5B,KAAK,QAAQ,GAAG,YAAY,CAAC,OAAO,WAAW,CAAC,CAAA;AAEhD,MAAM,MAAM,qBAAqB,GAAG,qBAAqB,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC,CAAA;AAEhF,MAAM,MAAM,mBAAmB,GAAG;IAChC,gBAAgB,CAAC,EAAE,QAAQ,CAAA;CAC5B,CAAA;AAED,MAAM,MAAM,4BAA4B,CAAC,MAAM,SAAS,CAAC,CAAC,UAAU,IAAI;IACtE,UAAU,EAAE,qBAAqB,CAAA;IACjC,OAAO,EAAE,mBAAmB,CAAA;IAC5B,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAED,wBAAsB,qBAAqB,CAAC,MAAM,SAAS,CAAC,CAAC,UAAU,EACrE,OAAO,EAAE,4BAA4B,CAAC,MAAM,CAAC,GAC5C,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAY1B"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Agent as MastraAgent } from '@mastra/core/agent';
|
|
2
|
-
export async function
|
|
2
|
+
export async function invokeStructuredAgent(options) {
|
|
3
3
|
var _a;
|
|
4
4
|
const { agentInput, context, prompt, schema } = options;
|
|
5
5
|
const agent = (_a = context.initializedAgent) !== null && _a !== void 0 ? _a : new MastraAgent(agentInput);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-activity-with-mastra.d.ts","sourceRoot":"","sources":["../../../src/mastra/create-activity-with-mastra.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAC5B,OAAO,
|
|
1
|
+
{"version":3,"file":"create-activity-with-mastra.d.ts","sourceRoot":"","sources":["../../../src/mastra/create-activity-with-mastra.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAC5B,OAAO,EAGL,KAAK,cAAc,EACnB,KAAK,2BAA2B,EAChC,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,aAAa,CAAA;AACpB,OAAO,EAEL,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACzB,MAAM,oBAAoB,CAAA;AAE3B,KAAK,WAAW,GAAG;IACjB,UAAU,EAAE,qBAAqB,CAAA;IACjC,YAAY,CAAC,EAAE,mBAAmB,CAAA;CACnC,CAAA;AAED,KAAK,8BAA8B,CAAC,MAAM,IAAI;IAC5C,KAAK,EAAE,MAAM,CAAA;IACb,aAAa,CAAC,EAAE,aAAa,CAAA;IAC7B,KAAK,EAAE,CAAC,MAAM,SAAS,CAAC,CAAC,UAAU,EAAE,OAAO,EAAE;QAC5C,UAAU,CAAC,EAAE,qBAAqB,CAAA;QAClC,MAAM,EAAE,MAAM,CAAA;QACd,MAAM,EAAE,MAAM,CAAA;KACf,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAA;CAC/B,CAAA;AAED,KAAK,mCAAmC,CAAC,EAAE,SAAS,MAAM,IAAI;IAC5D,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,GAAG,SAAS,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC9E,eAAe,CAAC,EAAE,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAA;CACjD,CAAA;AAED,MAAM,MAAM,wCAAwC,GAClD,mCAAmC,CAAC,MAAM,CAAC,GAAG;IAC5C,EAAE,CAAC,EAAE,SAAS,CAAA;CACf,CAAA;AAEH,MAAM,MAAM,qCAAqC,CAAC,EAAE,SAAS,MAAM,IACjE,mCAAmC,CAAC,EAAE,CAAC,GAAG;IACxC,EAAE,EAAE,EAAE,CAAA;CACP,CAAA;AAEH,KAAK,qBAAqB,CAAC,MAAM,EAAE,OAAO,IAAI,CAC5C,OAAO,EAAE,8BAA8B,CAAC,MAAM,CAAC,KAC5C,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;AAE/B,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,OAAO,EACtD,OAAO,EAAE,wCAAwC,EACjD,OAAO,EAAE,qBAAqB,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9C,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAClC,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,SAAS,MAAM,EACzE,OAAO,EAAE,qCAAqC,CAAC,EAAE,CAAC,EAClD,OAAO,EAAE,qBAAqB,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9C,2BAA2B,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,CAAC,CAAA"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createActivity, wrapActivityWithMastraContext, } from '../types.js';
|
|
2
|
-
import {
|
|
2
|
+
import { invokeStructuredAgent, } from './agent-wrapper.js';
|
|
3
3
|
export function createActivityWithMastra(options, handler) {
|
|
4
4
|
var _a, _b;
|
|
5
5
|
const sharedRuntimeContext = (_a = options.mastraInput) === null || _a === void 0 ? void 0 : _a.agentContext;
|
|
@@ -8,12 +8,14 @@ export function createActivityWithMastra(options, handler) {
|
|
|
8
8
|
return handler({
|
|
9
9
|
input,
|
|
10
10
|
mastraContext,
|
|
11
|
-
agent: async ({ prompt, schema }) => {
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
agent: async ({ agentInput, prompt, schema }) => {
|
|
12
|
+
var _a;
|
|
13
|
+
const resolvedAgentInput = agentInput !== null && agentInput !== void 0 ? agentInput : (_a = options.mastraInput) === null || _a === void 0 ? void 0 : _a.agentInput;
|
|
14
|
+
if (!resolvedAgentInput) {
|
|
15
|
+
throw new Error('createActivityWithMastra: provide agentInput in options.mastraInput or context.agent({ agentInput, ... }).');
|
|
14
16
|
}
|
|
15
|
-
return
|
|
16
|
-
agentInput:
|
|
17
|
+
return invokeStructuredAgent({
|
|
18
|
+
agentInput: resolvedAgentInput,
|
|
17
19
|
context: runtimeContext,
|
|
18
20
|
prompt,
|
|
19
21
|
schema,
|
|
@@ -32,7 +34,9 @@ export function createActivityWithMastra(options, handler) {
|
|
|
32
34
|
return createActivity(wrappedActivity);
|
|
33
35
|
}
|
|
34
36
|
const config = {
|
|
35
|
-
...(hasInlineConfig
|
|
37
|
+
...(hasInlineConfig
|
|
38
|
+
? Object.fromEntries(inlineConfigEntries)
|
|
39
|
+
: {}),
|
|
36
40
|
...(options.id !== undefined ? { id: options.id } : {}),
|
|
37
41
|
};
|
|
38
42
|
return createActivity(wrappedActivity, config);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { z } from 'zod';
|
|
2
|
+
import type { CreateActivity } from '../types.js';
|
|
3
|
+
import { type AgentConstructorInput } from './agent-wrapper.js';
|
|
4
|
+
export declare function wrapActivityWithMastraAgent<TInput, TOutput>(handler: (context: {
|
|
5
|
+
input: TInput;
|
|
6
|
+
agent: <Schema extends z.ZodTypeAny>(options: {
|
|
7
|
+
agentInput: AgentConstructorInput;
|
|
8
|
+
prompt: string;
|
|
9
|
+
schema: Schema;
|
|
10
|
+
}) => Promise<z.infer<Schema>>;
|
|
11
|
+
}) => TOutput | Promise<TOutput>): CreateActivity<TInput, TOutput>;
|
|
12
|
+
//# sourceMappingURL=with-mastra-agent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"with-mastra-agent.d.ts","sourceRoot":"","sources":["../../../src/mastra/with-mastra-agent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAC5B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AACjD,OAAO,EAAE,KAAK,qBAAqB,EAAE,MAAM,oBAAoB,CAAA;AAG/D,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,OAAO,EACzD,OAAO,EAAE,CAAC,OAAO,EAAE;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,CAAC,MAAM,SAAS,CAAC,CAAC,UAAU,EAAE,OAAO,EAAE;QAC5C,UAAU,EAAE,qBAAqB,CAAA;QACjC,MAAM,EAAE,MAAM,CAAA;QACd,MAAM,EAAE,MAAM,CAAA;KACf,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAA;CAC/B,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,GAC/B,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,CAEjC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type TemporalWorkflowBuildOptions, type WorkflowBuildResult } from '../types.js';
|
|
2
|
+
export type MastraWorkflowLike = {
|
|
3
|
+
id?: string;
|
|
4
|
+
engineType?: string;
|
|
5
|
+
stepGraph: Array<Record<string, unknown>>;
|
|
6
|
+
};
|
|
7
|
+
export type CompileMastraWorkflowOptions = Omit<TemporalWorkflowBuildOptions, 'workflowName'> & {
|
|
8
|
+
workflowName?: string;
|
|
9
|
+
stepActivities?: Record<string, unknown>;
|
|
10
|
+
/**
|
|
11
|
+
* @warning Unsafe fallback mode.
|
|
12
|
+
* When true, missing step activities are executed through a synthetic wrapper that calls `step.execute()`
|
|
13
|
+
* with a partial context object. This may be incompatible with complex Mastra steps.
|
|
14
|
+
* Prefer providing explicit `stepActivities` for every step.
|
|
15
|
+
*/
|
|
16
|
+
allowUnsafeStepExecuteFallback?: boolean;
|
|
17
|
+
};
|
|
18
|
+
export type MastraWorkflowCompilationInput = {
|
|
19
|
+
workflow: MastraWorkflowLike;
|
|
20
|
+
options?: CompileMastraWorkflowOptions;
|
|
21
|
+
};
|
|
22
|
+
export declare function compileMastraWorkflow(workflow: MastraWorkflowLike, options?: CompileMastraWorkflowOptions): WorkflowBuildResult;
|
|
23
|
+
//# sourceMappingURL=workflow-compiler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-compiler.d.ts","sourceRoot":"","sources":["../../../src/mastra/workflow-compiler.ts"],"names":[],"mappings":"AAEA,OAAO,EAIL,KAAK,4BAA4B,EACjC,KAAK,mBAAmB,EACzB,MAAM,aAAa,CAAA;AAQpB,MAAM,MAAM,kBAAkB,GAAG;IAC/B,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;CAC1C,CAAA;AAED,MAAM,MAAM,4BAA4B,GAAG,IAAI,CAAC,4BAA4B,EAAE,cAAc,CAAC,GAAG;IAC9F,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACxC;;;;;OAKG;IACH,8BAA8B,CAAC,EAAE,OAAO,CAAA;CACzC,CAAA;AAED,MAAM,MAAM,8BAA8B,GAAG;IAC3C,QAAQ,EAAE,kBAAkB,CAAA;IAC5B,OAAO,CAAC,EAAE,4BAA4B,CAAA;CACvC,CAAA;AAED,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,GAAE,4BAAiC,GACzC,mBAAmB,CA+DrB"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { WritableStream } from 'node:stream/web';
|
|
2
|
+
import { RequestContext } from '@mastra/core/request-context';
|
|
3
|
+
import { createActivity, } from '../types.js';
|
|
4
|
+
import { createWorkflowBuilder } from '../workflow/builder.js';
|
|
5
|
+
export function compileMastraWorkflow(workflow, options = {}) {
|
|
6
|
+
if (!workflow || !Array.isArray(workflow.stepGraph)) {
|
|
7
|
+
throw new Error('compileMastraWorkflow requires a valid Mastra workflow with stepGraph.');
|
|
8
|
+
}
|
|
9
|
+
const workflowName = resolveWorkflowName(workflow, options.workflowName);
|
|
10
|
+
let builder = createWorkflowBuilder({
|
|
11
|
+
workflowName,
|
|
12
|
+
...(options.activitiesImportPath ? { activitiesImportPath: options.activitiesImportPath } : {}),
|
|
13
|
+
...(options.proxyOptions ? { proxyOptions: options.proxyOptions } : {}),
|
|
14
|
+
});
|
|
15
|
+
workflow.stepGraph.forEach((entry, stageIndex) => {
|
|
16
|
+
if (entry.type === 'step' && isMastraStepLike(entry.step)) {
|
|
17
|
+
const reference = resolveStepReference(workflow, entry.step, options.stepActivities, options.allowUnsafeStepExecuteFallback === true);
|
|
18
|
+
builder = builder.then(reference);
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
if (entry.type === 'parallel' && Array.isArray(entry.steps)) {
|
|
22
|
+
const references = entry.steps.map((child, branchIndex) => {
|
|
23
|
+
if (typeof child !== 'object' ||
|
|
24
|
+
child === null ||
|
|
25
|
+
child.type !== 'step' ||
|
|
26
|
+
!isMastraStepLike(child.step)) {
|
|
27
|
+
const childType = typeof child === 'object' && child !== null
|
|
28
|
+
? String(child.type)
|
|
29
|
+
: typeof child;
|
|
30
|
+
throw new Error(`Unsupported Mastra parallel child type '${childType}' at stage ${stageIndex}, branch ${branchIndex}.`);
|
|
31
|
+
}
|
|
32
|
+
return resolveStepReference(workflow, child.step, options.stepActivities, options.allowUnsafeStepExecuteFallback === true);
|
|
33
|
+
});
|
|
34
|
+
builder = builder.parallel(references);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
throw new Error(`Unsupported Mastra step graph entry type '${String(entry.type)}' at stage ${stageIndex}.`);
|
|
38
|
+
});
|
|
39
|
+
return builder.commit();
|
|
40
|
+
}
|
|
41
|
+
function isMastraStepLike(value) {
|
|
42
|
+
if (typeof value !== 'object' || value === null) {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
const step = value;
|
|
46
|
+
return typeof step.id === 'string' && typeof step.execute === 'function';
|
|
47
|
+
}
|
|
48
|
+
function resolveWorkflowName(workflow, explicitName) {
|
|
49
|
+
const explicit = typeof explicitName === 'string' ? explicitName.trim() : '';
|
|
50
|
+
if (explicit.length > 0) {
|
|
51
|
+
return explicit;
|
|
52
|
+
}
|
|
53
|
+
const workflowId = typeof workflow.id === 'string' ? workflow.id.trim() : '';
|
|
54
|
+
if (workflowId.length > 0) {
|
|
55
|
+
return sanitizeWorkflowName(workflowId);
|
|
56
|
+
}
|
|
57
|
+
return 'mastraTemporalWorkflow';
|
|
58
|
+
}
|
|
59
|
+
function sanitizeWorkflowName(candidate) {
|
|
60
|
+
const cleaned = candidate.replace(/[^A-Za-z0-9_$]/g, '_');
|
|
61
|
+
const startsValid = /^[A-Za-z_$]/.test(cleaned);
|
|
62
|
+
const base = startsValid ? cleaned : `workflow_${cleaned}`;
|
|
63
|
+
if (base.length > 0 && !/^_+$/.test(base)) {
|
|
64
|
+
return base;
|
|
65
|
+
}
|
|
66
|
+
return 'mastraTemporalWorkflow';
|
|
67
|
+
}
|
|
68
|
+
function resolveStepReference(workflow, step, stepActivities, allowUnsafeStepExecuteFallback) {
|
|
69
|
+
var _a;
|
|
70
|
+
const configured = stepActivities === null || stepActivities === void 0 ? void 0 : stepActivities[step.id];
|
|
71
|
+
if (typeof configured === 'function') {
|
|
72
|
+
return createActivity(configured, { id: step.id });
|
|
73
|
+
}
|
|
74
|
+
if (isConfiguredActivityReference(configured)) {
|
|
75
|
+
return createActivity(configured.activity, {
|
|
76
|
+
...((_a = configured.config) !== null && _a !== void 0 ? _a : {}),
|
|
77
|
+
id: step.id,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
if (!allowUnsafeStepExecuteFallback) {
|
|
81
|
+
throw new Error(`compileMastraWorkflow requires stepActivities['${step.id}'] to be provided. ` +
|
|
82
|
+
`Automatic fallback execution is disabled by default for safety. ` +
|
|
83
|
+
`If you must use it, set allowUnsafeStepExecuteFallback: true.`);
|
|
84
|
+
}
|
|
85
|
+
const fallbackActivity = createMastraStepActivity(workflow, step);
|
|
86
|
+
return createActivity(fallbackActivity, { id: step.id });
|
|
87
|
+
}
|
|
88
|
+
function isConfiguredActivityReference(value) {
|
|
89
|
+
if (typeof value !== 'object' || value === null) {
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
const candidate = value;
|
|
93
|
+
return typeof candidate.activity === 'function';
|
|
94
|
+
}
|
|
95
|
+
function createMastraStepActivity(workflow, step) {
|
|
96
|
+
const workflowId = typeof workflow.id === 'string' && workflow.id.trim().length > 0
|
|
97
|
+
? workflow.id
|
|
98
|
+
: 'mastra-workflow';
|
|
99
|
+
return async (input) => {
|
|
100
|
+
var _a;
|
|
101
|
+
const requestContext = new RequestContext();
|
|
102
|
+
const abortController = new AbortController();
|
|
103
|
+
const runId = `temporal-${step.id}-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
|
|
104
|
+
const writer = new WritableStream();
|
|
105
|
+
const executeArgs = {
|
|
106
|
+
runId,
|
|
107
|
+
workflowId,
|
|
108
|
+
inputData: input,
|
|
109
|
+
requestContext,
|
|
110
|
+
mastra: undefined,
|
|
111
|
+
state: {},
|
|
112
|
+
setState: async () => { },
|
|
113
|
+
retryCount: 0,
|
|
114
|
+
tracingContext: {},
|
|
115
|
+
getInitData: () => input,
|
|
116
|
+
getStepResult: () => undefined,
|
|
117
|
+
suspend: () => {
|
|
118
|
+
throw new Error(`Mastra step '${step.id}' requested suspend(), which is not supported in Temporal activity compilation.`);
|
|
119
|
+
},
|
|
120
|
+
bail: (result) => result,
|
|
121
|
+
abort: () => {
|
|
122
|
+
throw new Error(`Mastra step '${step.id}' requested abort(), which is not supported in Temporal activity compilation.`);
|
|
123
|
+
},
|
|
124
|
+
engine: (_a = workflow.engineType) !== null && _a !== void 0 ? _a : 'default',
|
|
125
|
+
abortSignal: abortController.signal,
|
|
126
|
+
writer,
|
|
127
|
+
outputWriter: undefined,
|
|
128
|
+
validateSchemas: true,
|
|
129
|
+
};
|
|
130
|
+
return step.execute(executeArgs);
|
|
131
|
+
};
|
|
132
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collection.d.ts","sourceRoot":"","sources":["../../../src/workflow/collection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,mBAAmB,EACnB,6BAA6B,EAE9B,MAAM,aAAa,CAAA;AAGpB,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,SAAS,mBAAmB,EAAE,GACtC,6BAA6B,
|
|
1
|
+
{"version":3,"file":"collection.d.ts","sourceRoot":"","sources":["../../../src/workflow/collection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,mBAAmB,EACnB,6BAA6B,EAE9B,MAAM,aAAa,CAAA;AAGpB,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,SAAS,mBAAmB,EAAE,GACtC,6BAA6B,CAgE/B"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@primero.ai/temporal-graph-tools",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Utilities for working with DAG workflows.",
|
|
5
5
|
"keywords": [],
|
|
6
6
|
"homepage": "https://github.com/primero-ai/temporal-graph-tools#readme",
|
|
@@ -70,39 +70,38 @@
|
|
|
70
70
|
"worker": "bun with-env tsx examples/worker.ts",
|
|
71
71
|
"deps:update": "bun x npm-check-updates -ui -ws",
|
|
72
72
|
"trigger-mastra-workflow": "bun with-env bun examples/trigger-mastra-workflow.ts",
|
|
73
|
-
"trigger-normal-workflow": "bun with-env bun examples/trigger-normal-workflow.ts",
|
|
74
73
|
"clean": "rm -rf node_modules dist"
|
|
75
74
|
},
|
|
76
75
|
"dependencies": {
|
|
77
76
|
"@ai-sdk/openai": "^3.0.30",
|
|
78
77
|
"@mastra/core": "^1.4.0",
|
|
79
|
-
"@temporalio/activity": "^1.
|
|
80
|
-
"@temporalio/client": "1.
|
|
81
|
-
"@temporalio/worker": "1.
|
|
82
|
-
"@temporalio/workflow": "1.
|
|
83
|
-
"lodash": "^4.17.
|
|
84
|
-
"zod": "4.
|
|
78
|
+
"@temporalio/activity": "^1.15.0",
|
|
79
|
+
"@temporalio/client": "1.15.0",
|
|
80
|
+
"@temporalio/worker": "1.15.0",
|
|
81
|
+
"@temporalio/workflow": "1.15.0",
|
|
82
|
+
"lodash": "^4.17.23",
|
|
83
|
+
"zod": "4.3.6"
|
|
85
84
|
},
|
|
86
85
|
"devDependencies": {
|
|
87
86
|
"@types/lodash": "^4.17.23",
|
|
88
|
-
"tsx": "^4.
|
|
89
|
-
"@eslint/js": "^
|
|
90
|
-
"dotenv": "^17.
|
|
87
|
+
"tsx": "^4.21.0",
|
|
88
|
+
"@eslint/js": "^10.0.1",
|
|
89
|
+
"dotenv": "^17.3.1",
|
|
91
90
|
"dotenv-cli": "^11.0.0",
|
|
92
|
-
"@ianvs/prettier-plugin-sort-imports": "^4.7.
|
|
93
|
-
"@types/node": "^25.
|
|
94
|
-
"esbuild": "^0.27.
|
|
95
|
-
"eslint": "^
|
|
91
|
+
"@ianvs/prettier-plugin-sort-imports": "^4.7.1",
|
|
92
|
+
"@types/node": "^25.2.3",
|
|
93
|
+
"esbuild": "^0.27.3",
|
|
94
|
+
"eslint": "^10.0.0",
|
|
96
95
|
"eslint-import-resolver-typescript": "^4.4.4",
|
|
97
96
|
"eslint-plugin-import": "^2.32.0",
|
|
98
|
-
"prettier": "^3.8.
|
|
97
|
+
"prettier": "^3.8.1",
|
|
99
98
|
"prettier-plugin-tailwindcss": "^0.7.2",
|
|
100
99
|
"typescript": "^5.9.3",
|
|
101
|
-
"typescript-eslint": "^8.
|
|
100
|
+
"typescript-eslint": "^8.56.0"
|
|
102
101
|
},
|
|
103
102
|
"engines": {
|
|
104
103
|
"node": ">=18"
|
|
105
104
|
},
|
|
106
105
|
"module": "dist/src/index.js",
|
|
107
|
-
"packageManager": "bun@1.3.
|
|
106
|
+
"packageManager": "bun@1.3.9"
|
|
108
107
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"workflows.d.ts","sourceRoot":"","sources":["../../../examples/mastra-ai-workflow/workflows.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,8BAA8B,gEAQhC,CAAA"}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { createWorkflowBuilder } from '@primero.ai/temporal-graph-tools';
|
|
2
|
-
import { classifyOutageWithAi, draftResponseWithAi, enrichOutageDescription, submitResponse, takeTicket, } from './activities';
|
|
3
|
-
export const builderMastraAiSupportWorkflow = createWorkflowBuilder({
|
|
4
|
-
workflowName: 'mastraAiSupportWorkflow',
|
|
5
|
-
proxyOptions: { startToCloseTimeout: '2 minutes' },
|
|
6
|
-
})
|
|
7
|
-
.then(takeTicket)
|
|
8
|
-
.parallel([classifyOutageWithAi, enrichOutageDescription])
|
|
9
|
-
.then(draftResponseWithAi)
|
|
10
|
-
.then(submitResponse)
|
|
11
|
-
.commit();
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mastra-example.d.ts","sourceRoot":"","sources":["../../examples/mastra-example.ts"],"names":[],"mappings":""}
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
import { createActivity, createWorkflowBuilder, wrapActivityWithMastraContext, } from '@primero.ai/temporal-graph-tools';
|
|
2
|
-
function withMastraLogging(id, activity) {
|
|
3
|
-
return createActivity(wrapActivityWithMastraContext(activity, async ({ context, execute }) => {
|
|
4
|
-
var _a, _b;
|
|
5
|
-
if (context) {
|
|
6
|
-
console.log(`[mastra] workflow=${context.workflow.name} node=${context.node.key} type=${context.node.stageType} stage=${context.node.stageIndex} previous=${(_b = (_a = context.previousNode) === null || _a === void 0 ? void 0 : _a.key) !== null && _b !== void 0 ? _b : 'none'}`);
|
|
7
|
-
}
|
|
8
|
-
return execute();
|
|
9
|
-
}), { id });
|
|
10
|
-
}
|
|
11
|
-
const normalizeLead = withMastraLogging('normalizeLead', async (input) => {
|
|
12
|
-
const normalizedEmail = input.email.trim().toLowerCase();
|
|
13
|
-
return {
|
|
14
|
-
id: normalizedEmail.split('@')[0],
|
|
15
|
-
name: input.name.trim(),
|
|
16
|
-
email: normalizedEmail,
|
|
17
|
-
};
|
|
18
|
-
});
|
|
19
|
-
const scoreLead = withMastraLogging('scoreLead', async (lead) => {
|
|
20
|
-
const score = lead.email.endsWith('.edu') ? 82 : 64;
|
|
21
|
-
return { lead, score };
|
|
22
|
-
});
|
|
23
|
-
const createCrmTask = withMastraLogging('createCrmTask', async ({ lead, score }) => {
|
|
24
|
-
return { taskId: `crm-${lead.id}-${score}`, queued: true };
|
|
25
|
-
});
|
|
26
|
-
const notifySales = withMastraLogging('notifySales', async ({ lead, score }) => {
|
|
27
|
-
console.log(`[sales] lead=${lead.email} score=${score}`);
|
|
28
|
-
return { channel: 'slack', sent: true };
|
|
29
|
-
});
|
|
30
|
-
const finalizeLead = withMastraLogging('finalizeLead', async (result) => {
|
|
31
|
-
console.log(`[finalize] task=${result.createCrmTask.taskId} notify=${result.notifySales.sent}`);
|
|
32
|
-
return { completed: true };
|
|
33
|
-
});
|
|
34
|
-
const builderMastra = createWorkflowBuilder({
|
|
35
|
-
workflowName: 'mastraLeadWorkflow',
|
|
36
|
-
proxyOptions: { startToCloseTimeout: '2 minutes' },
|
|
37
|
-
})
|
|
38
|
-
.then(normalizeLead)
|
|
39
|
-
.then(scoreLead)
|
|
40
|
-
.parallel([createCrmTask, notifySales])
|
|
41
|
-
.then(finalizeLead)
|
|
42
|
-
.commit();
|
|
43
|
-
function makeContext(workflowName, totalStages, node, previousNode) {
|
|
44
|
-
return {
|
|
45
|
-
workflow: { name: workflowName },
|
|
46
|
-
graph: { totalStages },
|
|
47
|
-
node,
|
|
48
|
-
previousNode,
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
async function runLocalDryRun() {
|
|
52
|
-
console.log(`Workflow: ${builderMastra.workflowName}`);
|
|
53
|
-
console.log('\nGenerated workflow source:\n');
|
|
54
|
-
console.log(builderMastra.workflowSource);
|
|
55
|
-
const totalStages = 4;
|
|
56
|
-
const workflowName = builderMastra.workflowName;
|
|
57
|
-
const input = { name: ' Ada Lovelace ', email: 'Ada@Example.com ' };
|
|
58
|
-
const step0Node = {
|
|
59
|
-
key: 'normalizeLead',
|
|
60
|
-
stageIndex: 0,
|
|
61
|
-
stageType: 'step',
|
|
62
|
-
};
|
|
63
|
-
const normalized = await normalizeLead.activity(input, makeContext(workflowName, totalStages, step0Node, null));
|
|
64
|
-
const step1Node = {
|
|
65
|
-
key: 'scoreLead',
|
|
66
|
-
stageIndex: 1,
|
|
67
|
-
stageType: 'step',
|
|
68
|
-
};
|
|
69
|
-
const scored = await scoreLead.activity(normalized, makeContext(workflowName, totalStages, step1Node, step0Node));
|
|
70
|
-
const parallelNodeA = {
|
|
71
|
-
key: 'createCrmTask',
|
|
72
|
-
stageIndex: 2,
|
|
73
|
-
stageType: 'parallel',
|
|
74
|
-
branchIndex: 0,
|
|
75
|
-
};
|
|
76
|
-
const parallelNodeB = {
|
|
77
|
-
key: 'notifySales',
|
|
78
|
-
stageIndex: 2,
|
|
79
|
-
stageType: 'parallel',
|
|
80
|
-
branchIndex: 1,
|
|
81
|
-
};
|
|
82
|
-
const [crmTask, salesMessage] = await Promise.all([
|
|
83
|
-
createCrmTask.activity(scored, makeContext(workflowName, totalStages, parallelNodeA, step1Node)),
|
|
84
|
-
notifySales.activity(scored, makeContext(workflowName, totalStages, parallelNodeB, step1Node)),
|
|
85
|
-
]);
|
|
86
|
-
const step3Node = {
|
|
87
|
-
key: 'finalizeLead',
|
|
88
|
-
stageIndex: 3,
|
|
89
|
-
stageType: 'step',
|
|
90
|
-
};
|
|
91
|
-
const parallelAggregateNode = {
|
|
92
|
-
key: 'parallel_2',
|
|
93
|
-
stageIndex: 2,
|
|
94
|
-
stageType: 'parallel',
|
|
95
|
-
};
|
|
96
|
-
const finalResult = await finalizeLead.activity({ createCrmTask: crmTask, notifySales: salesMessage }, makeContext(workflowName, totalStages, step3Node, parallelAggregateNode));
|
|
97
|
-
console.log('\nDry run result:');
|
|
98
|
-
console.log(finalResult);
|
|
99
|
-
}
|
|
100
|
-
runLocalDryRun().catch((error) => {
|
|
101
|
-
console.error('Mastra example failed:', error);
|
|
102
|
-
process.exitCode = 1;
|
|
103
|
-
});
|