@contractspec/lib.example-shared-ui 6.0.6 → 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.
Files changed (81) hide show
  1. package/.turbo/turbo-build.log +90 -84
  2. package/AGENTS.md +43 -25
  3. package/README.md +63 -35
  4. package/dist/EvolutionDashboard.js +9 -9
  5. package/dist/EvolutionSidebar.js +15 -15
  6. package/dist/LocalDataIndicator.js +3 -3
  7. package/dist/MarkdownView.d.ts +0 -7
  8. package/dist/MarkdownView.js +76 -172
  9. package/dist/PersonalizationInsights.js +12 -12
  10. package/dist/SaveToStudioButton.js +2 -2
  11. package/dist/SpecDrivenTemplateShell.d.ts +1 -1
  12. package/dist/SpecDrivenTemplateShell.js +10 -10
  13. package/dist/SpecEditorPanel.js +3 -3
  14. package/dist/TemplateShell.js +10 -10
  15. package/dist/browser/EvolutionDashboard.js +9 -9
  16. package/dist/browser/EvolutionSidebar.js +15 -15
  17. package/dist/browser/LocalDataIndicator.js +3 -3
  18. package/dist/browser/MarkdownView.js +76 -172
  19. package/dist/browser/PersonalizationInsights.js +12 -12
  20. package/dist/browser/SaveToStudioButton.js +2 -2
  21. package/dist/browser/SpecDrivenTemplateShell.js +10 -10
  22. package/dist/browser/SpecEditorPanel.js +3 -3
  23. package/dist/browser/TemplateShell.js +10 -10
  24. package/dist/browser/hooks/index.js +29 -29
  25. package/dist/browser/index.js +193 -286
  26. package/dist/browser/lib/component-registry.js +1 -1
  27. package/dist/browser/markdown/formatPresentationName.js +9 -0
  28. package/dist/browser/markdown/useMarkdownPresentation.js +65 -0
  29. package/dist/hooks/index.d.ts +3 -3
  30. package/dist/hooks/index.js +29 -29
  31. package/dist/index.d.ts +12 -11
  32. package/dist/index.js +193 -286
  33. package/dist/lib/component-registry.js +1 -1
  34. package/dist/markdown/formatPresentationName.d.ts +1 -0
  35. package/dist/markdown/formatPresentationName.js +10 -0
  36. package/dist/markdown/useMarkdownPresentation.d.ts +21 -0
  37. package/dist/markdown/useMarkdownPresentation.js +66 -0
  38. package/dist/node/EvolutionDashboard.js +9 -9
  39. package/dist/node/EvolutionSidebar.js +15 -15
  40. package/dist/node/LocalDataIndicator.js +3 -3
  41. package/dist/node/MarkdownView.js +76 -172
  42. package/dist/node/PersonalizationInsights.js +12 -12
  43. package/dist/node/SaveToStudioButton.js +2 -2
  44. package/dist/node/SpecDrivenTemplateShell.js +10 -10
  45. package/dist/node/SpecEditorPanel.js +3 -3
  46. package/dist/node/TemplateShell.js +10 -10
  47. package/dist/node/hooks/index.js +29 -29
  48. package/dist/node/index.js +193 -286
  49. package/dist/node/lib/component-registry.js +1 -1
  50. package/dist/node/markdown/formatPresentationName.js +9 -0
  51. package/dist/node/markdown/useMarkdownPresentation.js +65 -0
  52. package/dist/utils/index.d.ts +1 -1
  53. package/package.json +38 -11
  54. package/src/EvolutionDashboard.tsx +415 -415
  55. package/src/EvolutionSidebar.tsx +245 -245
  56. package/src/LocalDataIndicator.tsx +28 -28
  57. package/src/MarkdownView.tsx +119 -372
  58. package/src/OverlayContextProvider.tsx +272 -272
  59. package/src/PersonalizationInsights.tsx +232 -232
  60. package/src/SaveToStudioButton.tsx +51 -51
  61. package/src/SpecDrivenTemplateShell.tsx +59 -59
  62. package/src/SpecEditorPanel.tsx +138 -138
  63. package/src/TemplateShell.tsx +50 -50
  64. package/src/bundles/ExampleTemplateBundle.ts +78 -78
  65. package/src/hooks/index.ts +3 -3
  66. package/src/hooks/useBehaviorTracking.ts +252 -252
  67. package/src/hooks/useEvolution.ts +437 -437
  68. package/src/hooks/useRegistryTemplates.ts +42 -42
  69. package/src/hooks/useSpecContent.ts +214 -214
  70. package/src/hooks/useWorkflowComposer.ts +567 -567
  71. package/src/index.ts +12 -11
  72. package/src/lib/component-registry.tsx +40 -40
  73. package/src/lib/runtime-context.tsx +31 -31
  74. package/src/lib/types.ts +57 -57
  75. package/src/markdown/formatPresentationName.ts +9 -0
  76. package/src/markdown/useMarkdownPresentation.ts +107 -0
  77. package/src/overlay-types.ts +15 -15
  78. package/src/utils/fetchPresentationData.ts +13 -13
  79. package/src/utils/generateSpecFromTemplate.ts +29 -29
  80. package/src/utils/index.ts +1 -1
  81. 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
- 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;
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
- meta: {
31
- key: string;
32
- version: string;
33
- description?: string;
34
- };
35
- steps: ComposerWorkflowStep[];
36
- start: string;
37
- context?: Record<string, unknown>;
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
- tenantId?: string;
45
- role?: string;
46
- device?: string;
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
- id?: string;
54
- after?: string;
55
- before?: string;
56
- inject: ComposerWorkflowStep;
57
- when?: string;
58
- transitionTo?: string;
59
- transitionFrom?: string;
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
- workflow: string;
67
- baseVersion?: number;
68
- priority?: number;
69
- customSteps?: StepInjection[];
70
- hiddenSteps?: string[];
71
- metadata?: Record<string, unknown>;
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
- /** 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;
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
- templateId: TemplateId
105
+ templateId: TemplateId
106
106
  ): UseWorkflowComposerReturn {
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) => ` {
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
- .join(',\n');
203
+ )
204
+ .join(',\n');
205
205
 
206
- const extensionsCode =
207
- extensions.length > 0
208
- ? `
206
+ const extensionsCode =
207
+ extensions.length > 0
208
+ ? `
209
209
 
210
210
  // Extensions applied:
211
211
  ${extensions
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}
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
- }, [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
- };
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
- extension: WorkflowExtension,
257
- scope?: WorkflowExtensionScope
256
+ extension: WorkflowExtension,
257
+ scope?: WorkflowExtensionScope
258
258
  ): boolean {
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;
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
- workflow: WorkflowSpec,
278
- extension: WorkflowExtension
277
+ workflow: WorkflowSpec,
278
+ extension: WorkflowExtension
279
279
  ): WorkflowSpec {
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 };
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
- return str
319
- .replace(/[^a-zA-Z0-9]+(.)/g, (_, c) => c.toUpperCase())
320
- .replace(/^./, (c) => c.toLowerCase());
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
- 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] ?? [];
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
  }