@contractspec/integration.workflow-devkit 0.1.1
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 +66 -0
- package/dist/agent-adapter.d.ts +35 -0
- package/dist/agent-adapter.js +80 -0
- package/dist/agent-adapter.test.d.ts +1 -0
- package/dist/browser/agent-adapter.js +79 -0
- package/dist/browser/chat-routes.js +100 -0
- package/dist/browser/compiler.js +177 -0
- package/dist/browser/helpers.js +80 -0
- package/dist/browser/index.js +479 -0
- package/dist/browser/next.js +8 -0
- package/dist/browser/runtime.js +180 -0
- package/dist/browser/types.js +0 -0
- package/dist/chat-routes.d.ts +37 -0
- package/dist/chat-routes.js +101 -0
- package/dist/chat-routes.test.d.ts +1 -0
- package/dist/compiler.d.ts +9 -0
- package/dist/compiler.js +178 -0
- package/dist/compiler.test.d.ts +1 -0
- package/dist/helpers.d.ts +8 -0
- package/dist/helpers.js +81 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +480 -0
- package/dist/next.d.ts +1 -0
- package/dist/next.js +9 -0
- package/dist/node/agent-adapter.js +79 -0
- package/dist/node/chat-routes.js +100 -0
- package/dist/node/compiler.js +177 -0
- package/dist/node/helpers.js +80 -0
- package/dist/node/index.js +479 -0
- package/dist/node/next.js +8 -0
- package/dist/node/runtime.js +180 -0
- package/dist/node/types.js +0 -0
- package/dist/runtime.d.ts +10 -0
- package/dist/runtime.js +181 -0
- package/dist/runtime.test.d.ts +1 -0
- package/dist/types.d.ts +97 -0
- package/dist/types.js +1 -0
- package/package.json +173 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { WorkflowApiLike, WorkflowRunLike } from './types';
|
|
2
|
+
export declare const WORKFLOW_RUN_ID_HEADER = "x-workflow-run-id";
|
|
3
|
+
export declare const WORKFLOW_STREAM_TAIL_INDEX_HEADER = "x-workflow-stream-tail-index";
|
|
4
|
+
export interface CreateWorkflowDevkitStartRouteOptions<TBody = unknown> {
|
|
5
|
+
buildArgs: (body: TBody, request: Request) => Promise<unknown[]> | unknown[];
|
|
6
|
+
createResponse?: (params: {
|
|
7
|
+
body: TBody;
|
|
8
|
+
run: WorkflowRunLike;
|
|
9
|
+
}) => Promise<Response> | Response;
|
|
10
|
+
workflow: (...args: unknown[]) => Promise<unknown>;
|
|
11
|
+
workflowApi?: Pick<WorkflowApiLike, 'start'>;
|
|
12
|
+
}
|
|
13
|
+
export interface CreateWorkflowDevkitFollowUpRouteOptions<TBody = unknown> {
|
|
14
|
+
buildPayload?: (body: TBody, request: Request) => Promise<unknown> | unknown;
|
|
15
|
+
resolveToken: (params: {
|
|
16
|
+
body: TBody;
|
|
17
|
+
request: Request;
|
|
18
|
+
runId: string;
|
|
19
|
+
}) => string;
|
|
20
|
+
workflowApi?: Pick<WorkflowApiLike, 'resumeHook'>;
|
|
21
|
+
}
|
|
22
|
+
export interface CreateWorkflowDevkitStreamRouteOptions {
|
|
23
|
+
workflowApi?: Pick<WorkflowApiLike, 'getRun'>;
|
|
24
|
+
}
|
|
25
|
+
export declare function createWorkflowDevkitStartRoute<TBody = unknown>(options: CreateWorkflowDevkitStartRouteOptions<TBody>): (request: Request) => Promise<Response>;
|
|
26
|
+
export declare function createWorkflowDevkitFollowUpRoute<TBody = unknown>(options: CreateWorkflowDevkitFollowUpRouteOptions<TBody>): (request: Request, context: {
|
|
27
|
+
params: {
|
|
28
|
+
id?: string;
|
|
29
|
+
runId?: string;
|
|
30
|
+
};
|
|
31
|
+
}) => Promise<Response>;
|
|
32
|
+
export declare function createWorkflowDevkitStreamRoute(options?: CreateWorkflowDevkitStreamRouteOptions): (request: Request, context: {
|
|
33
|
+
params: {
|
|
34
|
+
id?: string;
|
|
35
|
+
runId?: string;
|
|
36
|
+
};
|
|
37
|
+
}) => Promise<Response>;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// src/chat-routes.ts
|
|
3
|
+
import { createUIMessageStreamResponse } from "ai";
|
|
4
|
+
import { getRun, resumeHook, start } from "workflow/api";
|
|
5
|
+
var WORKFLOW_RUN_ID_HEADER = "x-workflow-run-id";
|
|
6
|
+
var WORKFLOW_STREAM_TAIL_INDEX_HEADER = "x-workflow-stream-tail-index";
|
|
7
|
+
function createWorkflowDevkitStartRoute(options) {
|
|
8
|
+
const workflowApi = options.workflowApi ?? { start };
|
|
9
|
+
return async (request) => {
|
|
10
|
+
const body = await request.json();
|
|
11
|
+
const args = await options.buildArgs(body, request);
|
|
12
|
+
const run = await workflowApi.start(options.workflow, args);
|
|
13
|
+
if (options.createResponse) {
|
|
14
|
+
return options.createResponse({ body, run });
|
|
15
|
+
}
|
|
16
|
+
if (!run.readable) {
|
|
17
|
+
return new Response(JSON.stringify({ runId: run.runId }), {
|
|
18
|
+
headers: {
|
|
19
|
+
"Content-Type": "application/json",
|
|
20
|
+
[WORKFLOW_RUN_ID_HEADER]: run.runId
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
return createUIMessageStreamResponse({
|
|
25
|
+
headers: {
|
|
26
|
+
[WORKFLOW_RUN_ID_HEADER]: run.runId
|
|
27
|
+
},
|
|
28
|
+
stream: run.readable
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function createWorkflowDevkitFollowUpRoute(options) {
|
|
33
|
+
const workflowApi = options.workflowApi ?? { resumeHook };
|
|
34
|
+
return async (request, context) => {
|
|
35
|
+
const runId = context.params.runId ?? context.params.id;
|
|
36
|
+
if (!runId) {
|
|
37
|
+
return new Response(JSON.stringify({ error: "Missing run id" }), {
|
|
38
|
+
status: 400
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
const body = await request.json();
|
|
42
|
+
const token = options.resolveToken({ body, request, runId });
|
|
43
|
+
const payload = options.buildPayload ? await options.buildPayload(body, request) : body;
|
|
44
|
+
await workflowApi.resumeHook(token, payload);
|
|
45
|
+
return new Response(JSON.stringify({ ok: true }), {
|
|
46
|
+
headers: {
|
|
47
|
+
"Content-Type": "application/json",
|
|
48
|
+
[WORKFLOW_RUN_ID_HEADER]: runId
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
function createWorkflowDevkitStreamRoute(options = {}) {
|
|
54
|
+
const workflowApi = options.workflowApi ?? { getRun };
|
|
55
|
+
return async (request, context) => {
|
|
56
|
+
const runId = context.params.runId ?? context.params.id;
|
|
57
|
+
if (!runId) {
|
|
58
|
+
return new Response(JSON.stringify({ error: "Missing run id" }), {
|
|
59
|
+
status: 400
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
const run = workflowApi.getRun(runId);
|
|
63
|
+
if (!run) {
|
|
64
|
+
return new Response(JSON.stringify({ error: "Workflow run not found" }), {
|
|
65
|
+
status: 404
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
const startIndex = readStartIndex(request.url);
|
|
69
|
+
const readable = run.getReadable ? run.getReadable({ startIndex }) : run.readable;
|
|
70
|
+
if (!readable) {
|
|
71
|
+
return new Response(JSON.stringify({ error: "Run has no readable stream" }), {
|
|
72
|
+
status: 404
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
const tailIndex = await readable.getTailIndex?.();
|
|
76
|
+
return createUIMessageStreamResponse({
|
|
77
|
+
headers: {
|
|
78
|
+
...tailIndex !== undefined ? {
|
|
79
|
+
[WORKFLOW_STREAM_TAIL_INDEX_HEADER]: String(tailIndex)
|
|
80
|
+
} : {}
|
|
81
|
+
},
|
|
82
|
+
stream: readable
|
|
83
|
+
});
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function readStartIndex(url) {
|
|
87
|
+
const parsed = new URL(url);
|
|
88
|
+
const rawStartIndex = parsed.searchParams.get("startIndex");
|
|
89
|
+
if (!rawStartIndex) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const parsedStartIndex = Number(rawStartIndex);
|
|
93
|
+
return Number.isFinite(parsedStartIndex) ? parsedStartIndex : undefined;
|
|
94
|
+
}
|
|
95
|
+
export {
|
|
96
|
+
createWorkflowDevkitStreamRoute,
|
|
97
|
+
createWorkflowDevkitStartRoute,
|
|
98
|
+
createWorkflowDevkitFollowUpRoute,
|
|
99
|
+
WORKFLOW_STREAM_TAIL_INDEX_HEADER,
|
|
100
|
+
WORKFLOW_RUN_ID_HEADER
|
|
101
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { WorkflowSpec } from '@contractspec/lib.contracts-spec/workflow';
|
|
2
|
+
import type { WorkflowDevkitCompilation, WorkflowDevkitGeneratedArtifacts } from './types';
|
|
3
|
+
export interface CompileWorkflowSpecToWorkflowDevkitOptions {
|
|
4
|
+
exportName: string;
|
|
5
|
+
specImportPath: string;
|
|
6
|
+
workflowFunctionName?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function compileWorkflowSpecToWorkflowDevkit(spec: WorkflowSpec): WorkflowDevkitCompilation;
|
|
9
|
+
export declare function generateWorkflowDevkitArtifacts(spec: WorkflowSpec, options: CompileWorkflowSpecToWorkflowDevkitOptions): WorkflowDevkitGeneratedArtifacts;
|
package/dist/compiler.js
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// src/helpers.ts
|
|
3
|
+
import { evaluateExpression } from "@contractspec/lib.contracts-spec/workflow";
|
|
4
|
+
function inferWorkflowDevkitBehavior(step) {
|
|
5
|
+
return step.runtime?.workflowDevkit?.behavior ?? step.type;
|
|
6
|
+
}
|
|
7
|
+
function resolveWorkflowDevkitEntryStepId(spec) {
|
|
8
|
+
const entryStepId = spec.definition.entryStepId ?? spec.definition.steps[0]?.id;
|
|
9
|
+
if (!entryStepId) {
|
|
10
|
+
throw new Error(`Workflow ${spec.meta.key}.v${spec.meta.version} does not define an entry step.`);
|
|
11
|
+
}
|
|
12
|
+
return entryStepId;
|
|
13
|
+
}
|
|
14
|
+
function resolveWorkflowDevkitRunIdentity(spec, runIdentity) {
|
|
15
|
+
if (runIdentity) {
|
|
16
|
+
return runIdentity;
|
|
17
|
+
}
|
|
18
|
+
const strategy = spec.runtime?.workflowDevkit?.runIdentity?.strategy ?? "meta-key-version";
|
|
19
|
+
const prefix = spec.runtime?.workflowDevkit?.runIdentity?.prefix;
|
|
20
|
+
const baseIdentity = strategy === "meta-key-version" ? `${spec.meta.key}.v${spec.meta.version}` : `${spec.meta.key}.v${spec.meta.version}`;
|
|
21
|
+
return prefix ? `${prefix}:${baseIdentity}` : baseIdentity;
|
|
22
|
+
}
|
|
23
|
+
function resolveWorkflowDevkitWaitToken(spec, step, runIdentity) {
|
|
24
|
+
const runtime = step.runtime?.workflowDevkit;
|
|
25
|
+
if (!runtime) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const explicitToken = runtime.hookWait?.token ?? runtime.webhookWait?.token ?? runtime.approvalWait?.token ?? runtime.streamSession?.followUpToken;
|
|
29
|
+
if (explicitToken) {
|
|
30
|
+
return explicitToken;
|
|
31
|
+
}
|
|
32
|
+
const tokenStrategy = spec.runtime?.workflowDevkit?.hookTokens?.strategy ?? "deterministic";
|
|
33
|
+
const prefix = spec.runtime?.workflowDevkit?.hookTokens?.prefix ?? spec.meta.key;
|
|
34
|
+
const stableStepId = sanitizeIdentifier(step.id);
|
|
35
|
+
if (tokenStrategy === "session-scoped") {
|
|
36
|
+
const resolvedRunIdentity = sanitizeIdentifier(resolveWorkflowDevkitRunIdentity(spec, runIdentity));
|
|
37
|
+
return `${prefix}:${resolvedRunIdentity}:${stableStepId}`;
|
|
38
|
+
}
|
|
39
|
+
if (tokenStrategy === "step-scoped") {
|
|
40
|
+
return `${prefix}:v${spec.meta.version}:${stableStepId}`;
|
|
41
|
+
}
|
|
42
|
+
return `${prefix}:${stableStepId}`;
|
|
43
|
+
}
|
|
44
|
+
function resolveWorkflowDevkitNextStepId(spec, step, data, input, output) {
|
|
45
|
+
const transitions = spec.definition.transitions.filter((transition) => transition.from === step.id);
|
|
46
|
+
for (const transition of transitions) {
|
|
47
|
+
if (evaluateExpression(transition.condition, {
|
|
48
|
+
data,
|
|
49
|
+
input,
|
|
50
|
+
output
|
|
51
|
+
})) {
|
|
52
|
+
return transition.to;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
function mergeWorkflowDevkitData(current, input, output) {
|
|
58
|
+
const next = { ...current };
|
|
59
|
+
if (isRecord(input)) {
|
|
60
|
+
Object.assign(next, input);
|
|
61
|
+
}
|
|
62
|
+
if (isRecord(output)) {
|
|
63
|
+
Object.assign(next, output);
|
|
64
|
+
}
|
|
65
|
+
return next;
|
|
66
|
+
}
|
|
67
|
+
function sanitizeIdentifier(value) {
|
|
68
|
+
return value.replace(/[^a-zA-Z0-9_-]+/g, "-");
|
|
69
|
+
}
|
|
70
|
+
function isRecord(value) {
|
|
71
|
+
return value != null && typeof value === "object" && !Array.isArray(value);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// src/compiler.ts
|
|
75
|
+
function compileWorkflowSpecToWorkflowDevkit(spec) {
|
|
76
|
+
return {
|
|
77
|
+
entryStepId: resolveWorkflowDevkitEntryStepId(spec),
|
|
78
|
+
hostTarget: spec.runtime?.workflowDevkit?.hostTarget ?? "generic",
|
|
79
|
+
hookTokenStrategy: spec.runtime?.workflowDevkit?.hookTokens?.strategy ?? "deterministic",
|
|
80
|
+
integrationMode: spec.runtime?.workflowDevkit?.integrationMode ?? "manual",
|
|
81
|
+
runIdentityStrategy: spec.runtime?.workflowDevkit?.runIdentity?.strategy ?? "meta-key-version",
|
|
82
|
+
specKey: spec.meta.key,
|
|
83
|
+
specVersion: spec.meta.version,
|
|
84
|
+
steps: spec.definition.steps.map((step) => ({
|
|
85
|
+
behavior: inferWorkflowDevkitBehavior(step),
|
|
86
|
+
id: step.id,
|
|
87
|
+
label: step.label,
|
|
88
|
+
operationRef: step.action?.operation ? `${step.action.operation.key}.v${step.action.operation.version}` : undefined,
|
|
89
|
+
runtime: step.runtime?.workflowDevkit,
|
|
90
|
+
transitions: spec.definition.transitions.filter((transition) => transition.from === step.id).map((transition) => ({
|
|
91
|
+
condition: transition.condition,
|
|
92
|
+
to: transition.to
|
|
93
|
+
})),
|
|
94
|
+
type: step.type,
|
|
95
|
+
waitToken: resolveWorkflowDevkitWaitToken(spec, step)
|
|
96
|
+
}))
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
function generateWorkflowDevkitArtifacts(spec, options) {
|
|
100
|
+
const compilation = compileWorkflowSpecToWorkflowDevkit(spec);
|
|
101
|
+
const workflowFunctionName = options.workflowFunctionName ?? `${sanitizeIdentifier(options.exportName)}WorkflowDevkit`;
|
|
102
|
+
return {
|
|
103
|
+
genericBootstrap: createGenericBootstrapTemplate(options.exportName, workflowFunctionName),
|
|
104
|
+
manifest: JSON.stringify(compilation, null, 2),
|
|
105
|
+
nextFollowUpRoute: createFollowUpRouteTemplate(workflowFunctionName),
|
|
106
|
+
nextStartRoute: createStartRouteTemplate(workflowFunctionName),
|
|
107
|
+
nextStreamRoute: createStreamRouteTemplate(),
|
|
108
|
+
workflowModule: createWorkflowModuleTemplate(options.exportName, options.specImportPath, workflowFunctionName)
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
function createGenericBootstrapTemplate(exportName, workflowFunctionName) {
|
|
112
|
+
return `import { ${workflowFunctionName} } from "./${sanitizeIdentifier(exportName)}.workflow-devkit";
|
|
113
|
+
|
|
114
|
+
export const ${sanitizeIdentifier(exportName)}WorkflowDevkitBootstrap = {
|
|
115
|
+
workflow: ${workflowFunctionName},
|
|
116
|
+
createBridge() {
|
|
117
|
+
return {
|
|
118
|
+
executeAutomationStep: async () => {
|
|
119
|
+
throw new Error("Provide executeAutomationStep in your generic host bridge.");
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
`;
|
|
125
|
+
}
|
|
126
|
+
function createStartRouteTemplate(workflowFunctionName) {
|
|
127
|
+
return `import { createWorkflowDevkitStartRoute } from "@contractspec/integration.workflow-devkit";
|
|
128
|
+
import { ${workflowFunctionName} } from "./workflow";
|
|
129
|
+
|
|
130
|
+
export const POST = createWorkflowDevkitStartRoute({
|
|
131
|
+
workflow: ${workflowFunctionName},
|
|
132
|
+
async buildArgs(body) {
|
|
133
|
+
return [body];
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
`;
|
|
137
|
+
}
|
|
138
|
+
function createFollowUpRouteTemplate(workflowFunctionName) {
|
|
139
|
+
return `import { createWorkflowDevkitFollowUpRoute } from "@contractspec/integration.workflow-devkit";
|
|
140
|
+
|
|
141
|
+
export const POST = createWorkflowDevkitFollowUpRoute({
|
|
142
|
+
resolveToken({ runId }) {
|
|
143
|
+
return \`${workflowFunctionName}:\${runId}\`;
|
|
144
|
+
},
|
|
145
|
+
});
|
|
146
|
+
`;
|
|
147
|
+
}
|
|
148
|
+
function createStreamRouteTemplate() {
|
|
149
|
+
return `import { createWorkflowDevkitStreamRoute } from "@contractspec/integration.workflow-devkit";
|
|
150
|
+
|
|
151
|
+
export const GET = createWorkflowDevkitStreamRoute();
|
|
152
|
+
`;
|
|
153
|
+
}
|
|
154
|
+
function createWorkflowModuleTemplate(exportName, specImportPath, workflowFunctionName) {
|
|
155
|
+
return `import { createHook, createWebhook, sleep } from "workflow";
|
|
156
|
+
import { runWorkflowSpecWithWorkflowDevkit } from "@contractspec/integration.workflow-devkit";
|
|
157
|
+
import { ${exportName} } from "${specImportPath}";
|
|
158
|
+
|
|
159
|
+
export async function ${workflowFunctionName}(input = {}, bridge = {}) {
|
|
160
|
+
"use workflow";
|
|
161
|
+
|
|
162
|
+
return runWorkflowSpecWithWorkflowDevkit({
|
|
163
|
+
spec: ${exportName},
|
|
164
|
+
initialData: input,
|
|
165
|
+
bridge,
|
|
166
|
+
primitives: {
|
|
167
|
+
sleep,
|
|
168
|
+
createHook,
|
|
169
|
+
createWebhook,
|
|
170
|
+
},
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
`;
|
|
174
|
+
}
|
|
175
|
+
export {
|
|
176
|
+
generateWorkflowDevkitArtifacts,
|
|
177
|
+
compileWorkflowSpecToWorkflowDevkit
|
|
178
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Step, WorkflowSpec } from '@contractspec/lib.contracts-spec/workflow';
|
|
2
|
+
export declare function inferWorkflowDevkitBehavior(step: Step): import("@contractspec/lib.contracts-spec/workflow").StepType | import("@contractspec/lib.contracts-spec/workflow").WorkflowDevkitStepBehavior;
|
|
3
|
+
export declare function resolveWorkflowDevkitEntryStepId(spec: WorkflowSpec): string;
|
|
4
|
+
export declare function resolveWorkflowDevkitRunIdentity(spec: WorkflowSpec, runIdentity?: string): string;
|
|
5
|
+
export declare function resolveWorkflowDevkitWaitToken(spec: WorkflowSpec, step: Step, runIdentity?: string): string | undefined;
|
|
6
|
+
export declare function resolveWorkflowDevkitNextStepId(spec: WorkflowSpec, step: Step, data: Record<string, unknown>, input?: unknown, output?: unknown): string | null;
|
|
7
|
+
export declare function mergeWorkflowDevkitData(current: Record<string, unknown>, input?: unknown, output?: unknown): Record<string, unknown>;
|
|
8
|
+
export declare function sanitizeIdentifier(value: string): string;
|
package/dist/helpers.js
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// src/helpers.ts
|
|
3
|
+
import { evaluateExpression } from "@contractspec/lib.contracts-spec/workflow";
|
|
4
|
+
function inferWorkflowDevkitBehavior(step) {
|
|
5
|
+
return step.runtime?.workflowDevkit?.behavior ?? step.type;
|
|
6
|
+
}
|
|
7
|
+
function resolveWorkflowDevkitEntryStepId(spec) {
|
|
8
|
+
const entryStepId = spec.definition.entryStepId ?? spec.definition.steps[0]?.id;
|
|
9
|
+
if (!entryStepId) {
|
|
10
|
+
throw new Error(`Workflow ${spec.meta.key}.v${spec.meta.version} does not define an entry step.`);
|
|
11
|
+
}
|
|
12
|
+
return entryStepId;
|
|
13
|
+
}
|
|
14
|
+
function resolveWorkflowDevkitRunIdentity(spec, runIdentity) {
|
|
15
|
+
if (runIdentity) {
|
|
16
|
+
return runIdentity;
|
|
17
|
+
}
|
|
18
|
+
const strategy = spec.runtime?.workflowDevkit?.runIdentity?.strategy ?? "meta-key-version";
|
|
19
|
+
const prefix = spec.runtime?.workflowDevkit?.runIdentity?.prefix;
|
|
20
|
+
const baseIdentity = strategy === "meta-key-version" ? `${spec.meta.key}.v${spec.meta.version}` : `${spec.meta.key}.v${spec.meta.version}`;
|
|
21
|
+
return prefix ? `${prefix}:${baseIdentity}` : baseIdentity;
|
|
22
|
+
}
|
|
23
|
+
function resolveWorkflowDevkitWaitToken(spec, step, runIdentity) {
|
|
24
|
+
const runtime = step.runtime?.workflowDevkit;
|
|
25
|
+
if (!runtime) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const explicitToken = runtime.hookWait?.token ?? runtime.webhookWait?.token ?? runtime.approvalWait?.token ?? runtime.streamSession?.followUpToken;
|
|
29
|
+
if (explicitToken) {
|
|
30
|
+
return explicitToken;
|
|
31
|
+
}
|
|
32
|
+
const tokenStrategy = spec.runtime?.workflowDevkit?.hookTokens?.strategy ?? "deterministic";
|
|
33
|
+
const prefix = spec.runtime?.workflowDevkit?.hookTokens?.prefix ?? spec.meta.key;
|
|
34
|
+
const stableStepId = sanitizeIdentifier(step.id);
|
|
35
|
+
if (tokenStrategy === "session-scoped") {
|
|
36
|
+
const resolvedRunIdentity = sanitizeIdentifier(resolveWorkflowDevkitRunIdentity(spec, runIdentity));
|
|
37
|
+
return `${prefix}:${resolvedRunIdentity}:${stableStepId}`;
|
|
38
|
+
}
|
|
39
|
+
if (tokenStrategy === "step-scoped") {
|
|
40
|
+
return `${prefix}:v${spec.meta.version}:${stableStepId}`;
|
|
41
|
+
}
|
|
42
|
+
return `${prefix}:${stableStepId}`;
|
|
43
|
+
}
|
|
44
|
+
function resolveWorkflowDevkitNextStepId(spec, step, data, input, output) {
|
|
45
|
+
const transitions = spec.definition.transitions.filter((transition) => transition.from === step.id);
|
|
46
|
+
for (const transition of transitions) {
|
|
47
|
+
if (evaluateExpression(transition.condition, {
|
|
48
|
+
data,
|
|
49
|
+
input,
|
|
50
|
+
output
|
|
51
|
+
})) {
|
|
52
|
+
return transition.to;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
function mergeWorkflowDevkitData(current, input, output) {
|
|
58
|
+
const next = { ...current };
|
|
59
|
+
if (isRecord(input)) {
|
|
60
|
+
Object.assign(next, input);
|
|
61
|
+
}
|
|
62
|
+
if (isRecord(output)) {
|
|
63
|
+
Object.assign(next, output);
|
|
64
|
+
}
|
|
65
|
+
return next;
|
|
66
|
+
}
|
|
67
|
+
function sanitizeIdentifier(value) {
|
|
68
|
+
return value.replace(/[^a-zA-Z0-9_-]+/g, "-");
|
|
69
|
+
}
|
|
70
|
+
function isRecord(value) {
|
|
71
|
+
return value != null && typeof value === "object" && !Array.isArray(value);
|
|
72
|
+
}
|
|
73
|
+
export {
|
|
74
|
+
sanitizeIdentifier,
|
|
75
|
+
resolveWorkflowDevkitWaitToken,
|
|
76
|
+
resolveWorkflowDevkitRunIdentity,
|
|
77
|
+
resolveWorkflowDevkitNextStepId,
|
|
78
|
+
resolveWorkflowDevkitEntryStepId,
|
|
79
|
+
mergeWorkflowDevkitData,
|
|
80
|
+
inferWorkflowDevkitBehavior
|
|
81
|
+
};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { WorkflowChatTransport } from '@workflow/ai';
|
|
2
|
+
export { createWorkflowDevkitAgentRuntimeAdapterBundle, defaultWorkflowDevkitAgentToken, InMemoryWorkflowDevkitCheckpointStore, InMemoryWorkflowDevkitSuspensionStore, } from './agent-adapter';
|
|
3
|
+
export { createWorkflowDevkitFollowUpRoute, createWorkflowDevkitStartRoute, createWorkflowDevkitStreamRoute, WORKFLOW_RUN_ID_HEADER, WORKFLOW_STREAM_TAIL_INDEX_HEADER, } from './chat-routes';
|
|
4
|
+
export { compileWorkflowSpecToWorkflowDevkit, generateWorkflowDevkitArtifacts, } from './compiler';
|
|
5
|
+
export * from './helpers';
|
|
6
|
+
export { withContractSpecWorkflow } from './next';
|
|
7
|
+
export { runWorkflowSpecWithWorkflowDevkit } from './runtime';
|
|
8
|
+
export type * from './types';
|