@contractspec/lib.example-shared-ui 6.0.5 → 6.0.7
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/.turbo/turbo-build.log +90 -84
- package/AGENTS.md +43 -25
- package/CHANGELOG.md +11 -0
- package/README.md +63 -35
- package/dist/EvolutionDashboard.js +9 -9
- package/dist/EvolutionSidebar.js +15 -15
- package/dist/LocalDataIndicator.js +3 -3
- package/dist/MarkdownView.d.ts +0 -7
- package/dist/MarkdownView.js +76 -172
- package/dist/PersonalizationInsights.js +12 -12
- package/dist/SaveToStudioButton.js +2 -2
- package/dist/SpecDrivenTemplateShell.d.ts +1 -1
- package/dist/SpecDrivenTemplateShell.js +10 -10
- package/dist/SpecEditorPanel.js +3 -3
- package/dist/TemplateShell.js +10 -10
- package/dist/browser/EvolutionDashboard.js +9 -9
- package/dist/browser/EvolutionSidebar.js +15 -15
- package/dist/browser/LocalDataIndicator.js +3 -3
- package/dist/browser/MarkdownView.js +76 -172
- package/dist/browser/PersonalizationInsights.js +12 -12
- package/dist/browser/SaveToStudioButton.js +2 -2
- package/dist/browser/SpecDrivenTemplateShell.js +10 -10
- package/dist/browser/SpecEditorPanel.js +3 -3
- package/dist/browser/TemplateShell.js +10 -10
- package/dist/browser/hooks/index.js +29 -29
- package/dist/browser/index.js +193 -286
- package/dist/browser/lib/component-registry.js +1 -1
- package/dist/browser/markdown/formatPresentationName.js +9 -0
- package/dist/browser/markdown/useMarkdownPresentation.js +65 -0
- package/dist/hooks/index.d.ts +3 -3
- package/dist/hooks/index.js +29 -29
- package/dist/index.d.ts +12 -11
- package/dist/index.js +193 -286
- package/dist/lib/component-registry.js +1 -1
- package/dist/markdown/formatPresentationName.d.ts +1 -0
- package/dist/markdown/formatPresentationName.js +10 -0
- package/dist/markdown/useMarkdownPresentation.d.ts +21 -0
- package/dist/markdown/useMarkdownPresentation.js +66 -0
- package/dist/node/EvolutionDashboard.js +9 -9
- package/dist/node/EvolutionSidebar.js +15 -15
- package/dist/node/LocalDataIndicator.js +3 -3
- package/dist/node/MarkdownView.js +76 -172
- package/dist/node/PersonalizationInsights.js +12 -12
- package/dist/node/SaveToStudioButton.js +2 -2
- package/dist/node/SpecDrivenTemplateShell.js +10 -10
- package/dist/node/SpecEditorPanel.js +3 -3
- package/dist/node/TemplateShell.js +10 -10
- package/dist/node/hooks/index.js +29 -29
- package/dist/node/index.js +193 -286
- package/dist/node/lib/component-registry.js +1 -1
- package/dist/node/markdown/formatPresentationName.js +9 -0
- package/dist/node/markdown/useMarkdownPresentation.js +65 -0
- package/dist/utils/index.d.ts +1 -1
- package/package.json +40 -13
- package/src/EvolutionDashboard.tsx +415 -415
- package/src/EvolutionSidebar.tsx +245 -245
- package/src/LocalDataIndicator.tsx +28 -28
- package/src/MarkdownView.tsx +119 -372
- package/src/OverlayContextProvider.tsx +272 -272
- package/src/PersonalizationInsights.tsx +232 -232
- package/src/SaveToStudioButton.tsx +51 -51
- package/src/SpecDrivenTemplateShell.tsx +59 -59
- package/src/SpecEditorPanel.tsx +138 -138
- package/src/TemplateShell.tsx +50 -50
- package/src/bundles/ExampleTemplateBundle.ts +78 -78
- package/src/hooks/index.ts +3 -3
- package/src/hooks/useBehaviorTracking.ts +252 -252
- package/src/hooks/useEvolution.ts +437 -437
- package/src/hooks/useRegistryTemplates.ts +42 -42
- package/src/hooks/useSpecContent.ts +214 -214
- package/src/hooks/useWorkflowComposer.ts +567 -567
- package/src/index.ts +12 -11
- package/src/lib/component-registry.tsx +40 -40
- package/src/lib/runtime-context.tsx +31 -31
- package/src/lib/types.ts +57 -57
- package/src/markdown/formatPresentationName.ts +9 -0
- package/src/markdown/useMarkdownPresentation.ts +107 -0
- package/src/overlay-types.ts +15 -15
- package/src/utils/fetchPresentationData.ts +13 -13
- package/src/utils/generateSpecFromTemplate.ts +29 -29
- package/src/utils/index.ts +1 -1
- package/tsconfig.json +8 -8
|
@@ -12,89 +12,89 @@ export type StepType = 'action' | 'decision' | 'wait' | 'parallel' | 'end';
|
|
|
12
12
|
* Workflow step definition
|
|
13
13
|
*/
|
|
14
14
|
export interface ComposerWorkflowStep {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
15
|
+
id: string;
|
|
16
|
+
name: string;
|
|
17
|
+
type: StepType;
|
|
18
|
+
description?: string;
|
|
19
|
+
next?: string | string[];
|
|
20
|
+
condition?: string;
|
|
21
|
+
timeout?: number;
|
|
22
|
+
retries?: number;
|
|
23
|
+
onError?: string;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
27
|
* Workflow spec definition
|
|
28
28
|
*/
|
|
29
29
|
export interface WorkflowSpec {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
30
|
+
meta: {
|
|
31
|
+
key: string;
|
|
32
|
+
version: string;
|
|
33
|
+
description?: string;
|
|
34
|
+
};
|
|
35
|
+
steps: ComposerWorkflowStep[];
|
|
36
|
+
start: string;
|
|
37
|
+
context?: Record<string, unknown>;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
/**
|
|
41
41
|
* Workflow extension scope
|
|
42
42
|
*/
|
|
43
43
|
export interface WorkflowExtensionScope {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
tenantId?: string;
|
|
45
|
+
role?: string;
|
|
46
|
+
device?: string;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
/**
|
|
50
50
|
* Step injection definition
|
|
51
51
|
*/
|
|
52
52
|
export interface StepInjection {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
53
|
+
id?: string;
|
|
54
|
+
after?: string;
|
|
55
|
+
before?: string;
|
|
56
|
+
inject: ComposerWorkflowStep;
|
|
57
|
+
when?: string;
|
|
58
|
+
transitionTo?: string;
|
|
59
|
+
transitionFrom?: string;
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
/**
|
|
63
63
|
* Workflow extension definition
|
|
64
64
|
*/
|
|
65
65
|
export interface WorkflowExtension extends WorkflowExtensionScope {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
66
|
+
workflow: string;
|
|
67
|
+
baseVersion?: number;
|
|
68
|
+
priority?: number;
|
|
69
|
+
customSteps?: StepInjection[];
|
|
70
|
+
hiddenSteps?: string[];
|
|
71
|
+
metadata?: Record<string, unknown>;
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
/**
|
|
75
75
|
* Hook return type
|
|
76
76
|
*/
|
|
77
77
|
export interface UseWorkflowComposerReturn {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
78
|
+
/** Current composed workflow */
|
|
79
|
+
workflow: WorkflowSpec | null;
|
|
80
|
+
/** Available base workflows */
|
|
81
|
+
baseWorkflows: WorkflowSpec[];
|
|
82
|
+
/** Current extensions */
|
|
83
|
+
extensions: WorkflowExtension[];
|
|
84
|
+
/** Select a base workflow */
|
|
85
|
+
selectWorkflow: (workflowName: string) => void;
|
|
86
|
+
/** Add an extension */
|
|
87
|
+
addExtension: (extension: WorkflowExtension) => void;
|
|
88
|
+
/** Remove an extension */
|
|
89
|
+
removeExtension: (workflowName: string, index: number) => void;
|
|
90
|
+
/** Compose workflow with current extensions */
|
|
91
|
+
compose: (scope?: WorkflowExtensionScope) => WorkflowSpec | null;
|
|
92
|
+
/** Generate TypeScript code for the spec editor */
|
|
93
|
+
generateSpecCode: () => string;
|
|
94
|
+
/** Loading state */
|
|
95
|
+
loading: boolean;
|
|
96
|
+
/** Error state */
|
|
97
|
+
error: string | null;
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
/**
|
|
@@ -102,121 +102,121 @@ export interface UseWorkflowComposerReturn {
|
|
|
102
102
|
* Provides workflow selection, extension management, and code generation.
|
|
103
103
|
*/
|
|
104
104
|
export function useWorkflowComposer(
|
|
105
|
-
|
|
105
|
+
templateId: TemplateId
|
|
106
106
|
): UseWorkflowComposerReturn {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
107
|
+
const [selectedWorkflow, setSelectedWorkflow] = useState<string | null>(null);
|
|
108
|
+
const [extensions, setExtensions] = useState<WorkflowExtension[]>([]);
|
|
109
|
+
const [loading, _setLoading] = useState(false);
|
|
110
|
+
const [error, _setError] = useState<string | null>(null);
|
|
111
|
+
|
|
112
|
+
// Get base workflows for the template
|
|
113
|
+
const baseWorkflows = useMemo(
|
|
114
|
+
() => getTemplateWorkflows(templateId),
|
|
115
|
+
[templateId]
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
// Auto-select first workflow
|
|
119
|
+
useEffect(() => {
|
|
120
|
+
const firstWorkflow = baseWorkflows[0];
|
|
121
|
+
if (baseWorkflows.length > 0 && !selectedWorkflow && firstWorkflow) {
|
|
122
|
+
setSelectedWorkflow(firstWorkflow.meta.key);
|
|
123
|
+
}
|
|
124
|
+
}, [baseWorkflows, selectedWorkflow]);
|
|
125
|
+
|
|
126
|
+
// Get current base workflow
|
|
127
|
+
const currentBase = useMemo(() => {
|
|
128
|
+
return baseWorkflows.find((w) => w.meta.key === selectedWorkflow) ?? null;
|
|
129
|
+
}, [baseWorkflows, selectedWorkflow]);
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Compose workflow with extensions
|
|
133
|
+
*/
|
|
134
|
+
const compose = useCallback(
|
|
135
|
+
(scope?: WorkflowExtensionScope): WorkflowSpec | null => {
|
|
136
|
+
if (!currentBase) return null;
|
|
137
|
+
|
|
138
|
+
const applicableExtensions = extensions
|
|
139
|
+
.filter((ext) => ext.workflow === currentBase.meta.key)
|
|
140
|
+
.filter((ext) => matchesScope(ext, scope))
|
|
141
|
+
.sort((a, b) => (a.priority ?? 0) - (b.priority ?? 0));
|
|
142
|
+
|
|
143
|
+
if (applicableExtensions.length === 0) {
|
|
144
|
+
return currentBase;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
let composedWorkflow = { ...currentBase, steps: [...currentBase.steps] };
|
|
148
|
+
|
|
149
|
+
for (const extension of applicableExtensions) {
|
|
150
|
+
composedWorkflow = applyExtension(composedWorkflow, extension);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return composedWorkflow;
|
|
154
|
+
},
|
|
155
|
+
[currentBase, extensions]
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
// Current composed workflow
|
|
159
|
+
const workflow = useMemo(() => compose(), [compose]);
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Select a base workflow
|
|
163
|
+
*/
|
|
164
|
+
const selectWorkflow = useCallback((workflowName: string) => {
|
|
165
|
+
setSelectedWorkflow(workflowName);
|
|
166
|
+
}, []);
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Add an extension
|
|
170
|
+
*/
|
|
171
|
+
const addExtension = useCallback((extension: WorkflowExtension) => {
|
|
172
|
+
setExtensions((prev) => [...prev, extension]);
|
|
173
|
+
}, []);
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Remove an extension
|
|
177
|
+
*/
|
|
178
|
+
const removeExtension = useCallback((workflowName: string, index: number) => {
|
|
179
|
+
setExtensions((prev) => {
|
|
180
|
+
const forWorkflow = prev.filter((e) => e.workflow === workflowName);
|
|
181
|
+
const others = prev.filter((e) => e.workflow !== workflowName);
|
|
182
|
+
forWorkflow.splice(index, 1);
|
|
183
|
+
return [...others, ...forWorkflow];
|
|
184
|
+
});
|
|
185
|
+
}, []);
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Generate TypeScript code for the spec editor
|
|
189
|
+
*/
|
|
190
|
+
const generateSpecCode = useCallback((): string => {
|
|
191
|
+
const composed = workflow;
|
|
192
|
+
if (!composed) {
|
|
193
|
+
return '// No workflow selected';
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const stepsCode = composed.steps
|
|
197
|
+
.map(
|
|
198
|
+
(step) => ` {
|
|
199
199
|
id: '${step.id}',
|
|
200
200
|
name: '${step.name}',
|
|
201
201
|
type: '${step.type}',${step.description ? `\n description: '${step.description}',` : ''}${step.next ? `\n next: ${JSON.stringify(step.next)},` : ''}${step.condition ? `\n condition: '${step.condition}',` : ''}${step.timeout ? `\n timeout: ${step.timeout},` : ''}${step.retries ? `\n retries: ${step.retries},` : ''}${step.onError ? `\n onError: '${step.onError}',` : ''}
|
|
202
202
|
}`
|
|
203
|
-
|
|
204
|
-
|
|
203
|
+
)
|
|
204
|
+
.join(',\n');
|
|
205
205
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
206
|
+
const extensionsCode =
|
|
207
|
+
extensions.length > 0
|
|
208
|
+
? `
|
|
209
209
|
|
|
210
210
|
// Extensions applied:
|
|
211
211
|
${extensions
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
212
|
+
.map(
|
|
213
|
+
(ext) =>
|
|
214
|
+
`// - ${ext.workflow} (priority: ${ext.priority ?? 0})${ext.customSteps?.length ? ` +${ext.customSteps.length} steps` : ''}${ext.hiddenSteps?.length ? ` -${ext.hiddenSteps.length} hidden` : ''}`
|
|
215
|
+
)
|
|
216
|
+
.join('\n')}`
|
|
217
|
+
: '';
|
|
218
|
+
|
|
219
|
+
return `// Workflow Spec: ${composed.meta.key} v${composed.meta.version}
|
|
220
220
|
// Generated from ${templateId} template
|
|
221
221
|
${extensionsCode}
|
|
222
222
|
|
|
@@ -233,438 +233,438 @@ ${stepsCode}
|
|
|
233
233
|
],${composed.context ? `\n context: ${JSON.stringify(composed.context, null, 2)},` : ''}
|
|
234
234
|
});
|
|
235
235
|
`;
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
236
|
+
}, [workflow, extensions, templateId]);
|
|
237
|
+
|
|
238
|
+
return {
|
|
239
|
+
workflow,
|
|
240
|
+
baseWorkflows,
|
|
241
|
+
extensions,
|
|
242
|
+
selectWorkflow,
|
|
243
|
+
addExtension,
|
|
244
|
+
removeExtension,
|
|
245
|
+
compose,
|
|
246
|
+
generateSpecCode,
|
|
247
|
+
loading,
|
|
248
|
+
error,
|
|
249
|
+
};
|
|
250
250
|
}
|
|
251
251
|
|
|
252
252
|
/**
|
|
253
253
|
* Check if extension matches the scope
|
|
254
254
|
*/
|
|
255
255
|
function matchesScope(
|
|
256
|
-
|
|
257
|
-
|
|
256
|
+
extension: WorkflowExtension,
|
|
257
|
+
scope?: WorkflowExtensionScope
|
|
258
258
|
): boolean {
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
259
|
+
if (!scope) return true;
|
|
260
|
+
|
|
261
|
+
if (extension.tenantId && extension.tenantId !== scope.tenantId) {
|
|
262
|
+
return false;
|
|
263
|
+
}
|
|
264
|
+
if (extension.role && extension.role !== scope.role) {
|
|
265
|
+
return false;
|
|
266
|
+
}
|
|
267
|
+
if (extension.device && extension.device !== scope.device) {
|
|
268
|
+
return false;
|
|
269
|
+
}
|
|
270
|
+
return true;
|
|
271
271
|
}
|
|
272
272
|
|
|
273
273
|
/**
|
|
274
274
|
* Apply extension to workflow
|
|
275
275
|
*/
|
|
276
276
|
function applyExtension(
|
|
277
|
-
|
|
278
|
-
|
|
277
|
+
workflow: WorkflowSpec,
|
|
278
|
+
extension: WorkflowExtension
|
|
279
279
|
): WorkflowSpec {
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
280
|
+
let steps = [...workflow.steps];
|
|
281
|
+
|
|
282
|
+
// Hide steps
|
|
283
|
+
if (extension.hiddenSteps) {
|
|
284
|
+
steps = steps.filter((s) => !extension.hiddenSteps?.includes(s.id));
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// Inject custom steps
|
|
288
|
+
if (extension.customSteps) {
|
|
289
|
+
for (const injection of extension.customSteps) {
|
|
290
|
+
const stepToInject = {
|
|
291
|
+
...injection.inject,
|
|
292
|
+
id: injection.id ?? injection.inject.id,
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
if (injection.after) {
|
|
296
|
+
const afterIndex = steps.findIndex((s) => s.id === injection.after);
|
|
297
|
+
if (afterIndex !== -1) {
|
|
298
|
+
steps.splice(afterIndex + 1, 0, stepToInject);
|
|
299
|
+
}
|
|
300
|
+
} else if (injection.before) {
|
|
301
|
+
const beforeIndex = steps.findIndex((s) => s.id === injection.before);
|
|
302
|
+
if (beforeIndex !== -1) {
|
|
303
|
+
steps.splice(beforeIndex, 0, stepToInject);
|
|
304
|
+
}
|
|
305
|
+
} else {
|
|
306
|
+
steps.push(stepToInject);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
return { ...workflow, steps };
|
|
312
312
|
}
|
|
313
313
|
|
|
314
314
|
/**
|
|
315
315
|
* Convert string to camelCase
|
|
316
316
|
*/
|
|
317
317
|
function toCamelCase(str: string): string {
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
318
|
+
return str
|
|
319
|
+
.replace(/[^a-zA-Z0-9]+(.)/g, (_, c) => c.toUpperCase())
|
|
320
|
+
.replace(/^./, (c) => c.toLowerCase());
|
|
321
321
|
}
|
|
322
322
|
|
|
323
323
|
/**
|
|
324
324
|
* Get template-specific workflows
|
|
325
325
|
*/
|
|
326
326
|
function getTemplateWorkflows(templateId: TemplateId): WorkflowSpec[] {
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
327
|
+
const templateWorkflows: Record<string, WorkflowSpec[]> = {
|
|
328
|
+
'crm-pipeline': [
|
|
329
|
+
{
|
|
330
|
+
meta: {
|
|
331
|
+
key: 'deal.qualification',
|
|
332
|
+
version: '1.0.0',
|
|
333
|
+
description: 'Deal qualification workflow',
|
|
334
|
+
},
|
|
335
|
+
start: 'lead-received',
|
|
336
|
+
steps: [
|
|
337
|
+
{
|
|
338
|
+
id: 'lead-received',
|
|
339
|
+
name: 'Lead Received',
|
|
340
|
+
type: 'action',
|
|
341
|
+
description: 'New lead enters the pipeline',
|
|
342
|
+
next: 'qualify-lead',
|
|
343
|
+
},
|
|
344
|
+
{
|
|
345
|
+
id: 'qualify-lead',
|
|
346
|
+
name: 'Qualify Lead',
|
|
347
|
+
type: 'decision',
|
|
348
|
+
description: 'Determine if lead meets qualification criteria',
|
|
349
|
+
next: ['qualified', 'disqualified'],
|
|
350
|
+
condition: 'lead.score >= threshold',
|
|
351
|
+
},
|
|
352
|
+
{
|
|
353
|
+
id: 'qualified',
|
|
354
|
+
name: 'Lead Qualified',
|
|
355
|
+
type: 'action',
|
|
356
|
+
next: 'assign-rep',
|
|
357
|
+
},
|
|
358
|
+
{
|
|
359
|
+
id: 'disqualified',
|
|
360
|
+
name: 'Lead Disqualified',
|
|
361
|
+
type: 'end',
|
|
362
|
+
},
|
|
363
|
+
{
|
|
364
|
+
id: 'assign-rep',
|
|
365
|
+
name: 'Assign Sales Rep',
|
|
366
|
+
type: 'action',
|
|
367
|
+
next: 'complete',
|
|
368
|
+
},
|
|
369
|
+
{
|
|
370
|
+
id: 'complete',
|
|
371
|
+
name: 'Workflow Complete',
|
|
372
|
+
type: 'end',
|
|
373
|
+
},
|
|
374
|
+
],
|
|
375
|
+
},
|
|
376
|
+
{
|
|
377
|
+
meta: {
|
|
378
|
+
key: 'deal.closing',
|
|
379
|
+
version: '1.0.0',
|
|
380
|
+
description: 'Deal closing workflow',
|
|
381
|
+
},
|
|
382
|
+
start: 'proposal-sent',
|
|
383
|
+
steps: [
|
|
384
|
+
{
|
|
385
|
+
id: 'proposal-sent',
|
|
386
|
+
name: 'Proposal Sent',
|
|
387
|
+
type: 'action',
|
|
388
|
+
next: 'wait-response',
|
|
389
|
+
},
|
|
390
|
+
{
|
|
391
|
+
id: 'wait-response',
|
|
392
|
+
name: 'Wait for Response',
|
|
393
|
+
type: 'wait',
|
|
394
|
+
timeout: 604800000, // 7 days
|
|
395
|
+
next: 'negotiate',
|
|
396
|
+
onError: 'follow-up',
|
|
397
|
+
},
|
|
398
|
+
{
|
|
399
|
+
id: 'follow-up',
|
|
400
|
+
name: 'Follow Up',
|
|
401
|
+
type: 'action',
|
|
402
|
+
next: 'wait-response',
|
|
403
|
+
retries: 3,
|
|
404
|
+
},
|
|
405
|
+
{
|
|
406
|
+
id: 'negotiate',
|
|
407
|
+
name: 'Negotiation',
|
|
408
|
+
type: 'action',
|
|
409
|
+
next: 'finalize',
|
|
410
|
+
},
|
|
411
|
+
{
|
|
412
|
+
id: 'finalize',
|
|
413
|
+
name: 'Finalize Deal',
|
|
414
|
+
type: 'decision',
|
|
415
|
+
next: ['won', 'lost'],
|
|
416
|
+
condition: 'deal.accepted',
|
|
417
|
+
},
|
|
418
|
+
{
|
|
419
|
+
id: 'won',
|
|
420
|
+
name: 'Deal Won',
|
|
421
|
+
type: 'end',
|
|
422
|
+
},
|
|
423
|
+
{
|
|
424
|
+
id: 'lost',
|
|
425
|
+
name: 'Deal Lost',
|
|
426
|
+
type: 'end',
|
|
427
|
+
},
|
|
428
|
+
],
|
|
429
|
+
},
|
|
430
|
+
],
|
|
431
|
+
'saas-boilerplate': [
|
|
432
|
+
{
|
|
433
|
+
meta: {
|
|
434
|
+
key: 'user.onboarding',
|
|
435
|
+
version: '1.0.0',
|
|
436
|
+
description: 'User onboarding workflow',
|
|
437
|
+
},
|
|
438
|
+
start: 'signup',
|
|
439
|
+
steps: [
|
|
440
|
+
{
|
|
441
|
+
id: 'signup',
|
|
442
|
+
name: 'User Signup',
|
|
443
|
+
type: 'action',
|
|
444
|
+
next: 'verify-email',
|
|
445
|
+
},
|
|
446
|
+
{
|
|
447
|
+
id: 'verify-email',
|
|
448
|
+
name: 'Verify Email',
|
|
449
|
+
type: 'wait',
|
|
450
|
+
timeout: 86400000, // 24 hours
|
|
451
|
+
next: 'profile-setup',
|
|
452
|
+
onError: 'resend-verification',
|
|
453
|
+
},
|
|
454
|
+
{
|
|
455
|
+
id: 'resend-verification',
|
|
456
|
+
name: 'Resend Verification',
|
|
457
|
+
type: 'action',
|
|
458
|
+
next: 'verify-email',
|
|
459
|
+
retries: 2,
|
|
460
|
+
},
|
|
461
|
+
{
|
|
462
|
+
id: 'profile-setup',
|
|
463
|
+
name: 'Setup Profile',
|
|
464
|
+
type: 'action',
|
|
465
|
+
next: 'onboarding-tour',
|
|
466
|
+
},
|
|
467
|
+
{
|
|
468
|
+
id: 'onboarding-tour',
|
|
469
|
+
name: 'Onboarding Tour',
|
|
470
|
+
type: 'action',
|
|
471
|
+
next: 'complete',
|
|
472
|
+
},
|
|
473
|
+
{
|
|
474
|
+
id: 'complete',
|
|
475
|
+
name: 'Onboarding Complete',
|
|
476
|
+
type: 'end',
|
|
477
|
+
},
|
|
478
|
+
],
|
|
479
|
+
},
|
|
480
|
+
],
|
|
481
|
+
'agent-console': [
|
|
482
|
+
{
|
|
483
|
+
meta: {
|
|
484
|
+
key: 'agent.execution',
|
|
485
|
+
version: '1.0.0',
|
|
486
|
+
description: 'Agent execution workflow',
|
|
487
|
+
},
|
|
488
|
+
start: 'receive-task',
|
|
489
|
+
steps: [
|
|
490
|
+
{
|
|
491
|
+
id: 'receive-task',
|
|
492
|
+
name: 'Receive Task',
|
|
493
|
+
type: 'action',
|
|
494
|
+
next: 'plan-execution',
|
|
495
|
+
},
|
|
496
|
+
{
|
|
497
|
+
id: 'plan-execution',
|
|
498
|
+
name: 'Plan Execution',
|
|
499
|
+
type: 'action',
|
|
500
|
+
next: 'execute-steps',
|
|
501
|
+
},
|
|
502
|
+
{
|
|
503
|
+
id: 'execute-steps',
|
|
504
|
+
name: 'Execute Steps',
|
|
505
|
+
type: 'parallel',
|
|
506
|
+
next: ['tool-call', 'observe', 'reason'],
|
|
507
|
+
},
|
|
508
|
+
{
|
|
509
|
+
id: 'tool-call',
|
|
510
|
+
name: 'Tool Call',
|
|
511
|
+
type: 'action',
|
|
512
|
+
next: 'evaluate',
|
|
513
|
+
},
|
|
514
|
+
{
|
|
515
|
+
id: 'observe',
|
|
516
|
+
name: 'Observe',
|
|
517
|
+
type: 'action',
|
|
518
|
+
next: 'evaluate',
|
|
519
|
+
},
|
|
520
|
+
{
|
|
521
|
+
id: 'reason',
|
|
522
|
+
name: 'Reason',
|
|
523
|
+
type: 'action',
|
|
524
|
+
next: 'evaluate',
|
|
525
|
+
},
|
|
526
|
+
{
|
|
527
|
+
id: 'evaluate',
|
|
528
|
+
name: 'Evaluate Result',
|
|
529
|
+
type: 'decision',
|
|
530
|
+
condition: 'task.isComplete',
|
|
531
|
+
next: ['complete', 'execute-steps'],
|
|
532
|
+
},
|
|
533
|
+
{
|
|
534
|
+
id: 'complete',
|
|
535
|
+
name: 'Task Complete',
|
|
536
|
+
type: 'end',
|
|
537
|
+
},
|
|
538
|
+
],
|
|
539
|
+
},
|
|
540
|
+
],
|
|
541
|
+
'todos-app': [
|
|
542
|
+
{
|
|
543
|
+
meta: {
|
|
544
|
+
key: 'task.lifecycle',
|
|
545
|
+
version: '1.0.0',
|
|
546
|
+
description: 'Task lifecycle workflow',
|
|
547
|
+
},
|
|
548
|
+
start: 'created',
|
|
549
|
+
steps: [
|
|
550
|
+
{
|
|
551
|
+
id: 'created',
|
|
552
|
+
name: 'Task Created',
|
|
553
|
+
type: 'action',
|
|
554
|
+
next: 'in-progress',
|
|
555
|
+
},
|
|
556
|
+
{
|
|
557
|
+
id: 'in-progress',
|
|
558
|
+
name: 'In Progress',
|
|
559
|
+
type: 'action',
|
|
560
|
+
next: 'review',
|
|
561
|
+
},
|
|
562
|
+
{
|
|
563
|
+
id: 'review',
|
|
564
|
+
name: 'Review',
|
|
565
|
+
type: 'decision',
|
|
566
|
+
condition: 'task.approved',
|
|
567
|
+
next: ['done', 'in-progress'],
|
|
568
|
+
},
|
|
569
|
+
{
|
|
570
|
+
id: 'done',
|
|
571
|
+
name: 'Done',
|
|
572
|
+
type: 'end',
|
|
573
|
+
},
|
|
574
|
+
],
|
|
575
|
+
},
|
|
576
|
+
],
|
|
577
|
+
'messaging-app': [
|
|
578
|
+
{
|
|
579
|
+
meta: {
|
|
580
|
+
key: 'message.delivery',
|
|
581
|
+
version: '1.0.0',
|
|
582
|
+
description: 'Message delivery workflow',
|
|
583
|
+
},
|
|
584
|
+
start: 'compose',
|
|
585
|
+
steps: [
|
|
586
|
+
{
|
|
587
|
+
id: 'compose',
|
|
588
|
+
name: 'Compose Message',
|
|
589
|
+
type: 'action',
|
|
590
|
+
next: 'send',
|
|
591
|
+
},
|
|
592
|
+
{
|
|
593
|
+
id: 'send',
|
|
594
|
+
name: 'Send Message',
|
|
595
|
+
type: 'action',
|
|
596
|
+
next: 'deliver',
|
|
597
|
+
},
|
|
598
|
+
{
|
|
599
|
+
id: 'deliver',
|
|
600
|
+
name: 'Deliver',
|
|
601
|
+
type: 'decision',
|
|
602
|
+
condition: 'recipient.online',
|
|
603
|
+
next: ['delivered', 'queue'],
|
|
604
|
+
},
|
|
605
|
+
{
|
|
606
|
+
id: 'queue',
|
|
607
|
+
name: 'Queue for Delivery',
|
|
608
|
+
type: 'wait',
|
|
609
|
+
next: 'deliver',
|
|
610
|
+
},
|
|
611
|
+
{
|
|
612
|
+
id: 'delivered',
|
|
613
|
+
name: 'Message Delivered',
|
|
614
|
+
type: 'action',
|
|
615
|
+
next: 'read',
|
|
616
|
+
},
|
|
617
|
+
{
|
|
618
|
+
id: 'read',
|
|
619
|
+
name: 'Message Read',
|
|
620
|
+
type: 'end',
|
|
621
|
+
},
|
|
622
|
+
],
|
|
623
|
+
},
|
|
624
|
+
],
|
|
625
|
+
'recipe-app-i18n': [
|
|
626
|
+
{
|
|
627
|
+
meta: {
|
|
628
|
+
key: 'recipe.creation',
|
|
629
|
+
version: '1.0.0',
|
|
630
|
+
description: 'Recipe creation workflow',
|
|
631
|
+
},
|
|
632
|
+
start: 'draft',
|
|
633
|
+
steps: [
|
|
634
|
+
{
|
|
635
|
+
id: 'draft',
|
|
636
|
+
name: 'Draft Recipe',
|
|
637
|
+
type: 'action',
|
|
638
|
+
next: 'add-ingredients',
|
|
639
|
+
},
|
|
640
|
+
{
|
|
641
|
+
id: 'add-ingredients',
|
|
642
|
+
name: 'Add Ingredients',
|
|
643
|
+
type: 'action',
|
|
644
|
+
next: 'add-steps',
|
|
645
|
+
},
|
|
646
|
+
{
|
|
647
|
+
id: 'add-steps',
|
|
648
|
+
name: 'Add Steps',
|
|
649
|
+
type: 'action',
|
|
650
|
+
next: 'review',
|
|
651
|
+
},
|
|
652
|
+
{
|
|
653
|
+
id: 'review',
|
|
654
|
+
name: 'Review Recipe',
|
|
655
|
+
type: 'decision',
|
|
656
|
+
condition: 'recipe.isComplete',
|
|
657
|
+
next: ['publish', 'draft'],
|
|
658
|
+
},
|
|
659
|
+
{
|
|
660
|
+
id: 'publish',
|
|
661
|
+
name: 'Publish Recipe',
|
|
662
|
+
type: 'end',
|
|
663
|
+
},
|
|
664
|
+
],
|
|
665
|
+
},
|
|
666
|
+
],
|
|
667
|
+
};
|
|
668
|
+
|
|
669
|
+
return templateWorkflows[templateId] ?? [];
|
|
670
670
|
}
|