@geenius/ai-workflow 0.1.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/.changeset/config.json +11 -0
- package/.github/CODEOWNERS +1 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +16 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +11 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +10 -0
- package/.github/dependabot.yml +11 -0
- package/.github/workflows/ci.yml +23 -0
- package/.github/workflows/release.yml +29 -0
- package/.nvmrc +1 -0
- package/.project/ACCOUNT.yaml +4 -0
- package/.project/IDEAS.yaml +7 -0
- package/.project/PROJECT.yaml +11 -0
- package/.project/ROADMAP.yaml +15 -0
- package/CHANGELOG.md +11 -0
- package/CODE_OF_CONDUCT.md +16 -0
- package/CONTRIBUTING.md +26 -0
- package/LICENSE +21 -0
- package/README.md +1 -0
- package/SECURITY.md +15 -0
- package/SUPPORT.md +8 -0
- package/package.json +74 -0
- package/packages/convex/README.md +1 -0
- package/packages/convex/package.json +12 -0
- package/packages/convex/src/convex.config.ts +3 -0
- package/packages/convex/src/index.ts +3 -0
- package/packages/convex/src/mutations.ts +36 -0
- package/packages/convex/src/queries.ts +19 -0
- package/packages/convex/src/schema.ts +24 -0
- package/packages/convex/tsconfig.json +25 -0
- package/packages/react/README.md +1 -0
- package/packages/react/package.json +46 -0
- package/packages/react/src/components/ApprovalModal.tsx +47 -0
- package/packages/react/src/components/StepConfigPanel.tsx +67 -0
- package/packages/react/src/components/StepConnector.tsx +47 -0
- package/packages/react/src/components/StepNode.tsx +38 -0
- package/packages/react/src/components/StepPalette.tsx +48 -0
- package/packages/react/src/components/WorkflowCanvas.tsx +42 -0
- package/packages/react/src/components/WorkflowRunPanel.tsx +64 -0
- package/packages/react/src/components/WorkflowToolbar.tsx +43 -0
- package/packages/react/src/components/index.ts +9 -0
- package/packages/react/src/hooks/index.ts +10 -0
- package/packages/react/src/hooks/useApprovalGate.ts +59 -0
- package/packages/react/src/hooks/useWorkflow.ts +39 -0
- package/packages/react/src/hooks/useWorkflowBuilder.ts +121 -0
- package/packages/react/src/hooks/useWorkflowRun.ts +75 -0
- package/packages/react/src/hooks/useWorkflowStep.ts +52 -0
- package/packages/react/src/hooks/useWorkflowTemplates.ts +54 -0
- package/packages/react/src/index.ts +16 -0
- package/packages/react/src/pages/WorkflowBuilderPage.tsx +81 -0
- package/packages/react/src/pages/WorkflowRunsPage.tsx +59 -0
- package/packages/react/src/pages/index.ts +3 -0
- package/packages/react/tsconfig.json +1 -0
- package/packages/react/tsup.config.ts +7 -0
- package/packages/react-css/README.md +1 -0
- package/packages/react-css/package.json +44 -0
- package/packages/react-css/src/components/ApprovalModal.tsx +6 -0
- package/packages/react-css/src/components/StepConfigPanel.tsx +7 -0
- package/packages/react-css/src/components/StepConnector.tsx +6 -0
- package/packages/react-css/src/components/StepNode.tsx +7 -0
- package/packages/react-css/src/components/StepPalette.tsx +6 -0
- package/packages/react-css/src/components/WorkflowCanvas.tsx +6 -0
- package/packages/react-css/src/components/WorkflowRunPanel.tsx +9 -0
- package/packages/react-css/src/components/WorkflowToolbar.tsx +4 -0
- package/packages/react-css/src/components/index.ts +9 -0
- package/packages/react-css/src/hooks/index.ts +3 -0
- package/packages/react-css/src/hooks/useWorkflow.ts +39 -0
- package/packages/react-css/src/hooks/useWorkflowBuilder.ts +121 -0
- package/packages/react-css/src/index.ts +7 -0
- package/packages/react-css/src/pages/WorkflowBuilderPage.tsx +16 -0
- package/packages/react-css/src/pages/WorkflowRunsPage.tsx +6 -0
- package/packages/react-css/src/pages/index.ts +3 -0
- package/packages/react-css/src/styles.css +945 -0
- package/packages/react-css/tsconfig.json +26 -0
- package/packages/react-css/tsup.config.ts +2 -0
- package/packages/shared/README.md +1 -0
- package/packages/shared/package.json +56 -0
- package/packages/shared/src/__tests__/ai-workflow.test.ts +217 -0
- package/packages/shared/src/config.ts +49 -0
- package/packages/shared/src/convex/index.ts +2 -0
- package/packages/shared/src/convex/schemas.ts +42 -0
- package/packages/shared/src/engine.test.ts +1 -0
- package/packages/shared/src/engine.ts +295 -0
- package/packages/shared/src/index.ts +43 -0
- package/packages/shared/src/steps.ts +68 -0
- package/packages/shared/src/templates.ts +172 -0
- package/packages/shared/src/types.ts +237 -0
- package/packages/shared/src/utils/cost.ts +79 -0
- package/packages/shared/src/utils/dag.ts +133 -0
- package/packages/shared/src/utils/index.ts +5 -0
- package/packages/shared/src/utils/interpolation.ts +53 -0
- package/packages/shared/src/validators.ts +215 -0
- package/packages/shared/tsconfig.json +1 -0
- package/packages/shared/tsup.config.ts +5 -0
- package/packages/shared/vitest.config.ts +4 -0
- package/packages/solidjs/README.md +1 -0
- package/packages/solidjs/package.json +45 -0
- package/packages/solidjs/src/components/ApprovalModal.tsx +18 -0
- package/packages/solidjs/src/components/StepConfigPanel.tsx +14 -0
- package/packages/solidjs/src/components/StepConnector.tsx +11 -0
- package/packages/solidjs/src/components/StepNode.tsx +12 -0
- package/packages/solidjs/src/components/StepPalette.tsx +22 -0
- package/packages/solidjs/src/components/WorkflowCanvas.tsx +23 -0
- package/packages/solidjs/src/components/WorkflowRunPanel.tsx +18 -0
- package/packages/solidjs/src/components/WorkflowToolbar.tsx +13 -0
- package/packages/solidjs/src/components/index.ts +9 -0
- package/packages/solidjs/src/index.ts +7 -0
- package/packages/solidjs/src/pages/WorkflowBuilderPage.tsx +37 -0
- package/packages/solidjs/src/pages/WorkflowRunsPage.tsx +20 -0
- package/packages/solidjs/src/pages/index.ts +3 -0
- package/packages/solidjs/src/primitives/createApprovalGate.ts +29 -0
- package/packages/solidjs/src/primitives/createWorkflow.ts +28 -0
- package/packages/solidjs/src/primitives/createWorkflowBuilder.ts +56 -0
- package/packages/solidjs/src/primitives/createWorkflowRun.ts +32 -0
- package/packages/solidjs/src/primitives/createWorkflowStep.ts +23 -0
- package/packages/solidjs/src/primitives/createWorkflowTemplates.ts +28 -0
- package/packages/solidjs/src/primitives/index.ts +8 -0
- package/packages/solidjs/tsconfig.json +1 -0
- package/packages/solidjs/tsup.config.ts +7 -0
- package/packages/solidjs-css/README.md +1 -0
- package/packages/solidjs-css/package.json +43 -0
- package/packages/solidjs-css/src/components/ApprovalModal.tsx +6 -0
- package/packages/solidjs-css/src/components/StepConfigPanel.tsx +7 -0
- package/packages/solidjs-css/src/components/StepConnector.tsx +6 -0
- package/packages/solidjs-css/src/components/StepNode.tsx +7 -0
- package/packages/solidjs-css/src/components/StepPalette.tsx +7 -0
- package/packages/solidjs-css/src/components/WorkflowCanvas.tsx +7 -0
- package/packages/solidjs-css/src/components/WorkflowRunPanel.tsx +8 -0
- package/packages/solidjs-css/src/components/WorkflowToolbar.tsx +5 -0
- package/packages/solidjs-css/src/components/index.ts +9 -0
- package/packages/solidjs-css/src/index.ts +7 -0
- package/packages/solidjs-css/src/pages/WorkflowBuilderPage.tsx +2 -0
- package/packages/solidjs-css/src/pages/WorkflowRunsPage.tsx +7 -0
- package/packages/solidjs-css/src/pages/index.ts +3 -0
- package/packages/solidjs-css/src/primitives/createWorkflow.ts +28 -0
- package/packages/solidjs-css/src/primitives/createWorkflowBuilder.ts +56 -0
- package/packages/solidjs-css/src/primitives/index.ts +1 -0
- package/packages/solidjs-css/src/styles.css +945 -0
- package/packages/solidjs-css/tsconfig.json +27 -0
- package/packages/solidjs-css/tsup.config.ts +2 -0
- package/pnpm-workspace.yaml +2 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "bundler",
|
|
6
|
+
"declaration": true,
|
|
7
|
+
"declarationMap": true,
|
|
8
|
+
"sourceMap": true,
|
|
9
|
+
"outDir": "./dist",
|
|
10
|
+
"rootDir": "./src",
|
|
11
|
+
"strict": true,
|
|
12
|
+
"esModuleInterop": true,
|
|
13
|
+
"skipLibCheck": true,
|
|
14
|
+
"forceConsistentCasingInFileNames": true,
|
|
15
|
+
"resolveJsonModule": true,
|
|
16
|
+
"isolatedModules": true,
|
|
17
|
+
"jsx": "react-jsx"
|
|
18
|
+
},
|
|
19
|
+
"include": [
|
|
20
|
+
"src"
|
|
21
|
+
],
|
|
22
|
+
"exclude": [
|
|
23
|
+
"node_modules",
|
|
24
|
+
"dist"
|
|
25
|
+
]
|
|
26
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# ✦ @geenius-ai-workflow/shared\n\n> Geenius AI Workflow — Shared types, engine & Convex schema\n\n---\n\n## Overview\nBuilt with Steve Jobs-level minimalism and Jony Ive-level craftsmanship, this package is designed to deliver unparalleled developer experience (DX) and rock-solid performance.\n\n## Installation\n\n```bash\npnpm add @geenius-ai-workflow/shared\n```\n\n## Usage\n\n```typescript\nimport { init } from '@geenius-ai-workflow/shared';\n\n// Initialize the module with absolute precision\ninit({\n mode: 'premium',\n});\n```\n\n## Architecture\n- **Zero-config**: It just works.\n- **Strictly Typed**: Fully written in TypeScript for flawless IntelliSense.\n- **Framework Agnostic**: seamlessly integrates into the Geenius ecosystem.\n\n---\n\n*Designed by Antigravity HQ*\n
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@geenius-ai-workflow/shared",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"description": "Geenius AI Workflow \u2014 Shared types, engine & Convex schema",
|
|
7
|
+
"author": "Antigravity HQ",
|
|
8
|
+
"license": "MIT",
|
|
9
|
+
"main": "./dist/index.js",
|
|
10
|
+
"module": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"import": "./dist/index.js"
|
|
16
|
+
},
|
|
17
|
+
"./engine": {
|
|
18
|
+
"types": "./dist/engine.d.ts",
|
|
19
|
+
"import": "./dist/engine.js"
|
|
20
|
+
},
|
|
21
|
+
"./steps": {
|
|
22
|
+
"types": "./dist/steps.d.ts",
|
|
23
|
+
"import": "./dist/steps.js"
|
|
24
|
+
},
|
|
25
|
+
"./convex": {
|
|
26
|
+
"types": "./dist/convex/index.d.ts",
|
|
27
|
+
"import": "./dist/convex/index.js"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"files": [
|
|
31
|
+
"dist",
|
|
32
|
+
"src"
|
|
33
|
+
],
|
|
34
|
+
"scripts": {
|
|
35
|
+
"build": "tsup",
|
|
36
|
+
"clean": "rm -rf dist",
|
|
37
|
+
"type-check": "tsc --noEmit",
|
|
38
|
+
"prepublishOnly": "pnpm clean && pnpm build",
|
|
39
|
+
"test": "vitest run",
|
|
40
|
+
"test:watch": "vitest"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"zod": "^3.23.0"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"tsup": "^8.5.1",
|
|
47
|
+
"typescript": "~6.0.2",
|
|
48
|
+
"vitest": "^4.0.0"
|
|
49
|
+
},
|
|
50
|
+
"engines": {
|
|
51
|
+
"node": ">=20.0.0"
|
|
52
|
+
},
|
|
53
|
+
"publishConfig": {
|
|
54
|
+
"access": "public"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
// @geenius-ai-workflow/shared — src/__tests__/ai-workflow.test.ts
|
|
2
|
+
import { describe, it, expect } from 'vitest'
|
|
3
|
+
import { WorkflowEngine } from '../engine'
|
|
4
|
+
import { llmStep, transformStep, conditionStep, linearWorkflow, delayStep } from '../steps'
|
|
5
|
+
import { interpolate, extractVariables, detectCycle, topoSort } from '../utils'
|
|
6
|
+
import { validateWorkflow } from '../validators'
|
|
7
|
+
import { WORKFLOW_TEMPLATES, getTemplate } from '../templates'
|
|
8
|
+
|
|
9
|
+
// ─── WorkflowEngine ───────────────────────────────────────────────────────────
|
|
10
|
+
|
|
11
|
+
describe('WorkflowEngine', () => {
|
|
12
|
+
it('executes a linear workflow', async () => {
|
|
13
|
+
const engine = new WorkflowEngine({
|
|
14
|
+
callLLM: async () => ({ content: 'AI Result' }),
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
const { steps, connections } = linearWorkflow('Test', [
|
|
18
|
+
llmStep('Step 1', { systemPrompt: 'Sys', userPromptTemplate: 'User', outputVar: 'out1' }),
|
|
19
|
+
transformStep('Step 2', { expression: 'out1.toUpperCase()', inputVars: ['out1'], outputVar: 'out2' }),
|
|
20
|
+
])
|
|
21
|
+
|
|
22
|
+
const run = await engine.execute({
|
|
23
|
+
id: 'test', name: 'Test', version: 1, status: 'active',
|
|
24
|
+
steps, connections, createdBy: 'test', createdAt: 0, updatedAt: 0,
|
|
25
|
+
}, {})
|
|
26
|
+
|
|
27
|
+
expect(run.status).toBe('completed')
|
|
28
|
+
expect(run.variables.out1).toBe('AI Result')
|
|
29
|
+
expect(run.variables.out2).toBe('AI RESULT')
|
|
30
|
+
expect(run.stepResults).toHaveLength(2)
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
it('handles conditional branching (false path)', async () => {
|
|
34
|
+
const engine = new WorkflowEngine({
|
|
35
|
+
callLLM: async () => ({ content: 'Small' }),
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
const step1 = llmStep('Check', { systemPrompt: '...', userPromptTemplate: '...', outputVar: 'val' })
|
|
39
|
+
// Create branch steps first so we have their IDs
|
|
40
|
+
const bigStep = transformStep('Big Result', { expression: '"BIG"', inputVars: [], outputVar: 'res' })
|
|
41
|
+
const smallStep = transformStep('Small Result', { expression: '"SMALL"', inputVars: [], outputVar: 'res' })
|
|
42
|
+
const cond = conditionStep('Branch', {
|
|
43
|
+
expression: 'val === "Big"',
|
|
44
|
+
trueStepId: bigStep.id,
|
|
45
|
+
falseStepId: smallStep.id,
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
const run = await engine.execute({
|
|
49
|
+
id: 'test', name: 'Test', version: 1, status: 'active',
|
|
50
|
+
steps: [step1, cond, bigStep, smallStep],
|
|
51
|
+
connections: [
|
|
52
|
+
{ fromStepId: step1.id, toStepId: cond.id },
|
|
53
|
+
{ fromStepId: cond.id, toStepId: bigStep.id, label: 'true' },
|
|
54
|
+
{ fromStepId: cond.id, toStepId: smallStep.id, label: 'false' },
|
|
55
|
+
],
|
|
56
|
+
createdBy: 'test', createdAt: 0, updatedAt: 0,
|
|
57
|
+
}, {})
|
|
58
|
+
|
|
59
|
+
expect(run.status).toBe('completed')
|
|
60
|
+
expect(run.variables.res).toBe('SMALL')
|
|
61
|
+
expect(run.stepResults.find(s => s.stepId === bigStep.id)?.status).toBe('skipped')
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
it('fails with invalid workflow (no steps)', async () => {
|
|
65
|
+
const engine = new WorkflowEngine({
|
|
66
|
+
callLLM: async () => ({ content: 'x' }),
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
const run = await engine.execute({
|
|
70
|
+
id: 'empty', name: 'Empty', version: 1, status: 'active',
|
|
71
|
+
steps: [], connections: [], createdBy: 'test', createdAt: 0, updatedAt: 0,
|
|
72
|
+
}, {})
|
|
73
|
+
|
|
74
|
+
// An empty workflow completes immediately with no steps executed
|
|
75
|
+
expect(run.stepResults).toHaveLength(0)
|
|
76
|
+
})
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
// ─── Step Factories ──────────────────────────────────────────────────────────
|
|
80
|
+
|
|
81
|
+
describe('Step factories', () => {
|
|
82
|
+
it('llmStep creates a step with llm-call type', () => {
|
|
83
|
+
const step = llmStep('My LLM', { systemPrompt: 'sys', userPromptTemplate: 'user', outputVar: 'result' })
|
|
84
|
+
expect(step.type).toBe('llm-call')
|
|
85
|
+
expect(step.name).toBe('My LLM')
|
|
86
|
+
expect(typeof step.id).toBe('string')
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
it('transformStep creates a step with transform type', () => {
|
|
90
|
+
const step = transformStep('My Transform', { expression: 'x + 1', inputVars: ['x'], outputVar: 'y' })
|
|
91
|
+
expect(step.type).toBe('transform')
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
it('delayStep creates a step with delay type', () => {
|
|
95
|
+
const step = delayStep('Wait', 1000)
|
|
96
|
+
expect(step.type).toBe('delay')
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
it('linearWorkflow creates sequential connections', () => {
|
|
100
|
+
const s1 = llmStep('A', { systemPrompt: '', userPromptTemplate: '', outputVar: 'a' })
|
|
101
|
+
const s2 = llmStep('B', { systemPrompt: '', userPromptTemplate: '', outputVar: 'b' })
|
|
102
|
+
const { steps, connections } = linearWorkflow('Flow', [s1, s2])
|
|
103
|
+
expect(steps).toHaveLength(2)
|
|
104
|
+
expect(connections).toHaveLength(1)
|
|
105
|
+
expect(connections[0].fromStepId).toBe(s1.id)
|
|
106
|
+
expect(connections[0].toStepId).toBe(s2.id)
|
|
107
|
+
})
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
// ─── Interpolation ───────────────────────────────────────────────────────────
|
|
111
|
+
|
|
112
|
+
describe('interpolate', () => {
|
|
113
|
+
it('replaces {{var}} placeholders', () => {
|
|
114
|
+
const result = interpolate('Hello {{name}}!', { name: 'World' })
|
|
115
|
+
expect(result).toBe('Hello World!')
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
it('supports dot-path access', () => {
|
|
119
|
+
const result = interpolate('{{user.name}}', { user: { name: 'Mehdi' } })
|
|
120
|
+
expect(result).toBe('Mehdi')
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
it('leaves missing vars as empty string', () => {
|
|
124
|
+
const result = interpolate('{{missing}}', {})
|
|
125
|
+
expect(result).not.toContain('{{missing}}')
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
it('extractVariables finds all placeholders', () => {
|
|
129
|
+
const vars = extractVariables('Hello {{name}}, you have {{count}} messages')
|
|
130
|
+
expect(vars).toContain('name')
|
|
131
|
+
expect(vars).toContain('count')
|
|
132
|
+
expect(vars).toHaveLength(2)
|
|
133
|
+
})
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
// ─── DAG utilities ───────────────────────────────────────────────────────────
|
|
137
|
+
|
|
138
|
+
describe('DAG utilities', () => {
|
|
139
|
+
it('detectCycle returns null for a valid DAG', () => {
|
|
140
|
+
const nodeIds = ['a', 'b', 'c']
|
|
141
|
+
const edges = [{ from: 'a', to: 'b' }, { from: 'b', to: 'c' }]
|
|
142
|
+
expect(detectCycle(nodeIds, edges)).toBeNull()
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
it('detectCycle detects a cycle', () => {
|
|
146
|
+
const nodeIds = ['a', 'b', 'c']
|
|
147
|
+
const edges = [{ from: 'a', to: 'b' }, { from: 'b', to: 'c' }, { from: 'c', to: 'a' }]
|
|
148
|
+
expect(detectCycle(nodeIds, edges)).not.toBeNull()
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
it('topoSort returns valid topological order', () => {
|
|
152
|
+
const nodeIds = ['a', 'b', 'c']
|
|
153
|
+
const edges = [{ from: 'a', to: 'b' }, { from: 'b', to: 'c' }]
|
|
154
|
+
const order = topoSort(nodeIds, edges)
|
|
155
|
+
expect(order.indexOf('a')).toBeLessThan(order.indexOf('b'))
|
|
156
|
+
expect(order.indexOf('b')).toBeLessThan(order.indexOf('c'))
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
it('topoSort throws on cyclic graph', () => {
|
|
160
|
+
const nodeIds = ['a', 'b', 'c']
|
|
161
|
+
const edges = [{ from: 'a', to: 'b' }, { from: 'b', to: 'c' }, { from: 'c', to: 'a' }]
|
|
162
|
+
expect(() => topoSort(nodeIds, edges)).toThrow()
|
|
163
|
+
})
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
// ─── Validators ──────────────────────────────────────────────────────────────
|
|
167
|
+
|
|
168
|
+
describe('validateWorkflow', () => {
|
|
169
|
+
it('validates a workflow with a valid step', () => {
|
|
170
|
+
const step = llmStep('My Step', { systemPrompt: 'sys', userPromptTemplate: 'user', outputVar: 'result' })
|
|
171
|
+
const wf = {
|
|
172
|
+
id: 'test',
|
|
173
|
+
name: 'Test Workflow',
|
|
174
|
+
version: 1,
|
|
175
|
+
status: 'active' as const,
|
|
176
|
+
steps: [step],
|
|
177
|
+
connections: [],
|
|
178
|
+
createdBy: 'user',
|
|
179
|
+
createdAt: Date.now(),
|
|
180
|
+
updatedAt: Date.now(),
|
|
181
|
+
}
|
|
182
|
+
const result = validateWorkflow(wf)
|
|
183
|
+
expect(result.success).toBe(true)
|
|
184
|
+
})
|
|
185
|
+
|
|
186
|
+
it('rejects a workflow with no steps', () => {
|
|
187
|
+
const wf = {
|
|
188
|
+
id: 'empty',
|
|
189
|
+
name: 'Empty Workflow',
|
|
190
|
+
version: 1,
|
|
191
|
+
status: 'active' as const,
|
|
192
|
+
steps: [],
|
|
193
|
+
connections: [],
|
|
194
|
+
createdBy: 'user',
|
|
195
|
+
createdAt: Date.now(),
|
|
196
|
+
updatedAt: Date.now(),
|
|
197
|
+
}
|
|
198
|
+
const result = validateWorkflow(wf)
|
|
199
|
+
expect(result.success).toBe(false)
|
|
200
|
+
})
|
|
201
|
+
})
|
|
202
|
+
|
|
203
|
+
// ─── Templates ───────────────────────────────────────────────────────────────
|
|
204
|
+
|
|
205
|
+
describe('WORKFLOW_TEMPLATES', () => {
|
|
206
|
+
it('is a non-empty array', () => {
|
|
207
|
+
expect(Array.isArray(WORKFLOW_TEMPLATES)).toBe(true)
|
|
208
|
+
expect(WORKFLOW_TEMPLATES.length).toBeGreaterThan(0)
|
|
209
|
+
})
|
|
210
|
+
|
|
211
|
+
it('getTemplate returns a template by id', () => {
|
|
212
|
+
const first = WORKFLOW_TEMPLATES[0]
|
|
213
|
+
const found = getTemplate(first.id)
|
|
214
|
+
expect(found).toBeDefined()
|
|
215
|
+
expect(found?.id).toBe(first.id)
|
|
216
|
+
})
|
|
217
|
+
})
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Configuration factory for Geenius AI Workflow
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export interface ConfigureWorkflowOptions {
|
|
6
|
+
maxSteps?: number
|
|
7
|
+
maxExecutionTimeMs?: number
|
|
8
|
+
maxRetries?: number
|
|
9
|
+
defaultTimeout?: number
|
|
10
|
+
enableLogging?: boolean
|
|
11
|
+
enableMetrics?: boolean
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Configure the workflow system with execution options
|
|
16
|
+
* @param options Configuration options for workflows
|
|
17
|
+
* @returns WorkflowConfig object ready for use
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* const config = configureWorkflow({
|
|
21
|
+
* maxSteps: 50,
|
|
22
|
+
* maxExecutionTimeMs: 3600000,
|
|
23
|
+
* maxRetries: 3,
|
|
24
|
+
* enableMetrics: true,
|
|
25
|
+
* })
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export function configureWorkflow(options: ConfigureWorkflowOptions = {}) {
|
|
29
|
+
return {
|
|
30
|
+
maxSteps: options.maxSteps ?? 100,
|
|
31
|
+
maxExecutionTimeMs: options.maxExecutionTimeMs ?? 3600000, // 1 hour
|
|
32
|
+
maxRetries: options.maxRetries ?? 3,
|
|
33
|
+
defaultTimeout: options.defaultTimeout ?? 30000, // 30 seconds
|
|
34
|
+
enableLogging: options.enableLogging ?? true,
|
|
35
|
+
enableMetrics: options.enableMetrics ?? false,
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Default workflow configuration
|
|
41
|
+
*/
|
|
42
|
+
export const defaultWorkflowConfig = {
|
|
43
|
+
maxSteps: 100,
|
|
44
|
+
maxExecutionTimeMs: 3600000,
|
|
45
|
+
maxRetries: 3,
|
|
46
|
+
defaultTimeout: 30000,
|
|
47
|
+
enableLogging: true,
|
|
48
|
+
enableMetrics: false,
|
|
49
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// @geenius-ai-workflow/shared — src/convex/schemas.ts
|
|
2
|
+
export const workflowsTable = {
|
|
3
|
+
name: { type: 'string' as const },
|
|
4
|
+
description: { type: 'string' as const, optional: true as const },
|
|
5
|
+
version: { type: 'number' as const },
|
|
6
|
+
status: { type: 'string' as const },
|
|
7
|
+
definitionJson: { type: 'string' as const },
|
|
8
|
+
createdBy: { type: 'string' as const },
|
|
9
|
+
tags: { type: 'string' as const, optional: true as const },
|
|
10
|
+
createdAt: { type: 'number' as const },
|
|
11
|
+
updatedAt: { type: 'number' as const },
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const workflowRunsTable = {
|
|
15
|
+
workflowId: { type: 'string' as const },
|
|
16
|
+
workflowVersion: { type: 'number' as const },
|
|
17
|
+
status: { type: 'string' as const },
|
|
18
|
+
inputJson: { type: 'string' as const },
|
|
19
|
+
variablesJson: { type: 'string' as const },
|
|
20
|
+
currentStepIndex: { type: 'number' as const },
|
|
21
|
+
error: { type: 'string' as const, optional: true as const },
|
|
22
|
+
triggeredBy: { type: 'string' as const },
|
|
23
|
+
startedAt: { type: 'number' as const },
|
|
24
|
+
completedAt: { type: 'number' as const, optional: true as const },
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const workflowStepResultsTable = {
|
|
28
|
+
runId: { type: 'string' as const },
|
|
29
|
+
stepId: { type: 'string' as const },
|
|
30
|
+
stepName: { type: 'string' as const },
|
|
31
|
+
type: { type: 'string' as const },
|
|
32
|
+
status: { type: 'string' as const },
|
|
33
|
+
outputJson: { type: 'string' as const, optional: true as const },
|
|
34
|
+
error: { type: 'string' as const, optional: true as const },
|
|
35
|
+
durationMs: { type: 'number' as const },
|
|
36
|
+
tokens: { type: 'number' as const, optional: true as const },
|
|
37
|
+
costUsd: { type: 'number' as const, optional: true as const },
|
|
38
|
+
startedAt: { type: 'number' as const },
|
|
39
|
+
completedAt: { type: 'number' as const, optional: true as const },
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export const workflowTables = { workflows: workflowsTable, workflowRuns: workflowRunsTable, workflowStepResults: workflowStepResultsTable }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
// This file has been superseded by src/__tests__/ai-workflow.test.ts — please use that file instead.
|