@geenius/ai-workflow 0.1.0 → 0.5.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.
Files changed (159) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.md +69 -1
  3. package/package.json +60 -27
  4. package/packages/convex/dist/index.d.ts +363 -0
  5. package/packages/convex/dist/index.js +200 -0
  6. package/packages/convex/dist/index.js.map +1 -0
  7. package/packages/react/dist/index.d.ts +514 -0
  8. package/packages/react/dist/index.js +2633 -0
  9. package/packages/react/dist/index.js.map +1 -0
  10. package/packages/react-css/{src/styles.css → dist/index.css} +107 -253
  11. package/packages/react-css/dist/index.css.map +1 -0
  12. package/packages/react-css/dist/index.d.ts +533 -0
  13. package/packages/react-css/dist/index.js +2620 -0
  14. package/packages/react-css/dist/index.js.map +1 -0
  15. package/packages/shared/dist/index.d.ts +1305 -0
  16. package/packages/shared/dist/index.js +1594 -0
  17. package/packages/shared/dist/index.js.map +1 -0
  18. package/packages/solidjs/dist/index.d.ts +492 -0
  19. package/packages/solidjs/dist/index.js +2552 -0
  20. package/packages/solidjs/dist/index.js.map +1 -0
  21. package/packages/solidjs-css/{src/styles.css → dist/index.css} +107 -253
  22. package/packages/solidjs-css/dist/index.css.map +1 -0
  23. package/packages/solidjs-css/dist/index.d.ts +509 -0
  24. package/packages/solidjs-css/dist/index.js +2493 -0
  25. package/packages/solidjs-css/dist/index.js.map +1 -0
  26. package/.changeset/config.json +0 -11
  27. package/.github/CODEOWNERS +0 -1
  28. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -16
  29. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -11
  30. package/.github/PULL_REQUEST_TEMPLATE.md +0 -10
  31. package/.github/dependabot.yml +0 -11
  32. package/.github/workflows/ci.yml +0 -23
  33. package/.github/workflows/release.yml +0 -29
  34. package/.nvmrc +0 -1
  35. package/.project/ACCOUNT.yaml +0 -4
  36. package/.project/IDEAS.yaml +0 -7
  37. package/.project/PROJECT.yaml +0 -11
  38. package/.project/ROADMAP.yaml +0 -15
  39. package/CODE_OF_CONDUCT.md +0 -16
  40. package/CONTRIBUTING.md +0 -26
  41. package/SECURITY.md +0 -15
  42. package/SUPPORT.md +0 -8
  43. package/packages/convex/README.md +0 -1
  44. package/packages/convex/package.json +0 -12
  45. package/packages/convex/src/convex.config.ts +0 -3
  46. package/packages/convex/src/index.ts +0 -3
  47. package/packages/convex/src/mutations.ts +0 -36
  48. package/packages/convex/src/queries.ts +0 -19
  49. package/packages/convex/src/schema.ts +0 -24
  50. package/packages/convex/tsconfig.json +0 -25
  51. package/packages/react/README.md +0 -1
  52. package/packages/react/package.json +0 -46
  53. package/packages/react/src/components/ApprovalModal.tsx +0 -47
  54. package/packages/react/src/components/StepConfigPanel.tsx +0 -67
  55. package/packages/react/src/components/StepConnector.tsx +0 -47
  56. package/packages/react/src/components/StepNode.tsx +0 -38
  57. package/packages/react/src/components/StepPalette.tsx +0 -48
  58. package/packages/react/src/components/WorkflowCanvas.tsx +0 -42
  59. package/packages/react/src/components/WorkflowRunPanel.tsx +0 -64
  60. package/packages/react/src/components/WorkflowToolbar.tsx +0 -43
  61. package/packages/react/src/components/index.ts +0 -9
  62. package/packages/react/src/hooks/index.ts +0 -10
  63. package/packages/react/src/hooks/useApprovalGate.ts +0 -59
  64. package/packages/react/src/hooks/useWorkflow.ts +0 -39
  65. package/packages/react/src/hooks/useWorkflowBuilder.ts +0 -121
  66. package/packages/react/src/hooks/useWorkflowRun.ts +0 -75
  67. package/packages/react/src/hooks/useWorkflowStep.ts +0 -52
  68. package/packages/react/src/hooks/useWorkflowTemplates.ts +0 -54
  69. package/packages/react/src/index.ts +0 -16
  70. package/packages/react/src/pages/WorkflowBuilderPage.tsx +0 -81
  71. package/packages/react/src/pages/WorkflowRunsPage.tsx +0 -59
  72. package/packages/react/src/pages/index.ts +0 -3
  73. package/packages/react/tsconfig.json +0 -1
  74. package/packages/react/tsup.config.ts +0 -7
  75. package/packages/react-css/README.md +0 -1
  76. package/packages/react-css/package.json +0 -44
  77. package/packages/react-css/src/components/ApprovalModal.tsx +0 -6
  78. package/packages/react-css/src/components/StepConfigPanel.tsx +0 -7
  79. package/packages/react-css/src/components/StepConnector.tsx +0 -6
  80. package/packages/react-css/src/components/StepNode.tsx +0 -7
  81. package/packages/react-css/src/components/StepPalette.tsx +0 -6
  82. package/packages/react-css/src/components/WorkflowCanvas.tsx +0 -6
  83. package/packages/react-css/src/components/WorkflowRunPanel.tsx +0 -9
  84. package/packages/react-css/src/components/WorkflowToolbar.tsx +0 -4
  85. package/packages/react-css/src/components/index.ts +0 -9
  86. package/packages/react-css/src/hooks/index.ts +0 -3
  87. package/packages/react-css/src/hooks/useWorkflow.ts +0 -39
  88. package/packages/react-css/src/hooks/useWorkflowBuilder.ts +0 -121
  89. package/packages/react-css/src/index.ts +0 -7
  90. package/packages/react-css/src/pages/WorkflowBuilderPage.tsx +0 -16
  91. package/packages/react-css/src/pages/WorkflowRunsPage.tsx +0 -6
  92. package/packages/react-css/src/pages/index.ts +0 -3
  93. package/packages/react-css/tsconfig.json +0 -26
  94. package/packages/react-css/tsup.config.ts +0 -2
  95. package/packages/shared/README.md +0 -1
  96. package/packages/shared/package.json +0 -56
  97. package/packages/shared/src/__tests__/ai-workflow.test.ts +0 -217
  98. package/packages/shared/src/config.ts +0 -49
  99. package/packages/shared/src/convex/index.ts +0 -2
  100. package/packages/shared/src/convex/schemas.ts +0 -42
  101. package/packages/shared/src/engine.test.ts +0 -1
  102. package/packages/shared/src/engine.ts +0 -295
  103. package/packages/shared/src/index.ts +0 -43
  104. package/packages/shared/src/steps.ts +0 -68
  105. package/packages/shared/src/templates.ts +0 -172
  106. package/packages/shared/src/types.ts +0 -237
  107. package/packages/shared/src/utils/cost.ts +0 -79
  108. package/packages/shared/src/utils/dag.ts +0 -133
  109. package/packages/shared/src/utils/index.ts +0 -5
  110. package/packages/shared/src/utils/interpolation.ts +0 -53
  111. package/packages/shared/src/validators.ts +0 -215
  112. package/packages/shared/tsconfig.json +0 -1
  113. package/packages/shared/tsup.config.ts +0 -5
  114. package/packages/shared/vitest.config.ts +0 -4
  115. package/packages/solidjs/README.md +0 -1
  116. package/packages/solidjs/package.json +0 -45
  117. package/packages/solidjs/src/components/ApprovalModal.tsx +0 -18
  118. package/packages/solidjs/src/components/StepConfigPanel.tsx +0 -14
  119. package/packages/solidjs/src/components/StepConnector.tsx +0 -11
  120. package/packages/solidjs/src/components/StepNode.tsx +0 -12
  121. package/packages/solidjs/src/components/StepPalette.tsx +0 -22
  122. package/packages/solidjs/src/components/WorkflowCanvas.tsx +0 -23
  123. package/packages/solidjs/src/components/WorkflowRunPanel.tsx +0 -18
  124. package/packages/solidjs/src/components/WorkflowToolbar.tsx +0 -13
  125. package/packages/solidjs/src/components/index.ts +0 -9
  126. package/packages/solidjs/src/index.ts +0 -7
  127. package/packages/solidjs/src/pages/WorkflowBuilderPage.tsx +0 -37
  128. package/packages/solidjs/src/pages/WorkflowRunsPage.tsx +0 -20
  129. package/packages/solidjs/src/pages/index.ts +0 -3
  130. package/packages/solidjs/src/primitives/createApprovalGate.ts +0 -29
  131. package/packages/solidjs/src/primitives/createWorkflow.ts +0 -28
  132. package/packages/solidjs/src/primitives/createWorkflowBuilder.ts +0 -56
  133. package/packages/solidjs/src/primitives/createWorkflowRun.ts +0 -32
  134. package/packages/solidjs/src/primitives/createWorkflowStep.ts +0 -23
  135. package/packages/solidjs/src/primitives/createWorkflowTemplates.ts +0 -28
  136. package/packages/solidjs/src/primitives/index.ts +0 -8
  137. package/packages/solidjs/tsconfig.json +0 -1
  138. package/packages/solidjs/tsup.config.ts +0 -7
  139. package/packages/solidjs-css/README.md +0 -1
  140. package/packages/solidjs-css/package.json +0 -43
  141. package/packages/solidjs-css/src/components/ApprovalModal.tsx +0 -6
  142. package/packages/solidjs-css/src/components/StepConfigPanel.tsx +0 -7
  143. package/packages/solidjs-css/src/components/StepConnector.tsx +0 -6
  144. package/packages/solidjs-css/src/components/StepNode.tsx +0 -7
  145. package/packages/solidjs-css/src/components/StepPalette.tsx +0 -7
  146. package/packages/solidjs-css/src/components/WorkflowCanvas.tsx +0 -7
  147. package/packages/solidjs-css/src/components/WorkflowRunPanel.tsx +0 -8
  148. package/packages/solidjs-css/src/components/WorkflowToolbar.tsx +0 -5
  149. package/packages/solidjs-css/src/components/index.ts +0 -9
  150. package/packages/solidjs-css/src/index.ts +0 -7
  151. package/packages/solidjs-css/src/pages/WorkflowBuilderPage.tsx +0 -2
  152. package/packages/solidjs-css/src/pages/WorkflowRunsPage.tsx +0 -7
  153. package/packages/solidjs-css/src/pages/index.ts +0 -3
  154. package/packages/solidjs-css/src/primitives/createWorkflow.ts +0 -28
  155. package/packages/solidjs-css/src/primitives/createWorkflowBuilder.ts +0 -56
  156. package/packages/solidjs-css/src/primitives/index.ts +0 -1
  157. package/packages/solidjs-css/tsconfig.json +0 -27
  158. package/packages/solidjs-css/tsup.config.ts +0 -2
  159. package/pnpm-workspace.yaml +0 -2
@@ -1,42 +0,0 @@
1
- // @geenius-ai-workflow/react — components/WorkflowCanvas.tsx
2
- import type { WorkflowDefinition, WorkflowStepDef } from '@geenius-ai-workflow/shared'
3
- import { StepNode } from './StepNode'
4
- import { StepConnector } from './StepConnector'
5
-
6
- export interface WorkflowCanvasProps {
7
- definition: WorkflowDefinition
8
- selectedStepId: string | null
9
- onSelectStep: (id: string | null) => void
10
- onMoveStep?: (stepId: string, pos: { x: number; y: number }) => void
11
- }
12
-
13
- export function WorkflowCanvas({ definition, selectedStepId, onSelectStep, onMoveStep }: WorkflowCanvasProps) {
14
- return (
15
- <div data-workflow="canvas" role="application" aria-label="Workflow canvas">
16
- <svg data-workflow="connections-layer" style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }}>
17
- {definition.connections.map((conn, i) => {
18
- const from = definition.steps.find(s => s.id === conn.fromStepId)
19
- const to = definition.steps.find(s => s.id === conn.toStepId)
20
- if (!from?.position || !to?.position) return null
21
- return <StepConnector key={i} from={from.position} to={to.position} label={conn.label} />
22
- })}
23
- </svg>
24
- <div data-workflow="nodes-layer">
25
- {definition.steps.map(step => (
26
- <StepNode
27
- key={step.id}
28
- step={step}
29
- isSelected={selectedStepId === step.id}
30
- onClick={() => onSelectStep(step.id === selectedStepId ? null : step.id)}
31
- />
32
- ))}
33
- </div>
34
- {definition.steps.length === 0 && (
35
- <div data-workflow="canvas-empty">
36
- <p data-workflow="empty-title">No steps yet</p>
37
- <p data-workflow="empty-hint">Drag steps from the palette or use a template</p>
38
- </div>
39
- )}
40
- </div>
41
- )
42
- }
@@ -1,64 +0,0 @@
1
- // @geenius-ai-workflow/react — components/WorkflowRunPanel.tsx
2
- import type { WorkflowRun, StepResult } from '@geenius-ai-workflow/shared'
3
- import { formatCost } from '@geenius-ai-workflow/shared'
4
-
5
- export interface WorkflowRunPanelProps {
6
- run: WorkflowRun | null
7
- isRunning: boolean
8
- onCancel?: () => void
9
- }
10
-
11
- const STATUS_ICONS: Record<string, string> = {
12
- pending: '⏳', running: '🔄', completed: '✅', failed: '❌', skipped: '⏭️', 'waiting-approval': '👤',
13
- }
14
-
15
- export function WorkflowRunPanel({ run, isRunning, onCancel }: WorkflowRunPanelProps) {
16
- if (!run) {
17
- return (
18
- <div data-workflow="run-panel">
19
- <div data-workflow="run-empty"><p>No active run. Click "Run" to execute the workflow.</p></div>
20
- </div>
21
- )
22
- }
23
-
24
- const completedCount = run.stepResults.filter(s => s.status === 'completed').length
25
- const totalCount = run.stepResults.length
26
- const progress = totalCount > 0 ? Math.round((completedCount / totalCount) * 100) : 0
27
- const totalCost = run.stepResults.reduce((sum, s) => sum + (s.costUsd ?? 0), 0)
28
- const totalTokens = run.stepResults.reduce((sum, s) => sum + (s.tokens ?? 0), 0)
29
- const duration = (run.completedAt ?? Date.now()) - run.startedAt
30
-
31
- return (
32
- <div data-workflow="run-panel" data-status={run.status}>
33
- <div data-workflow="run-header">
34
- <h3 data-workflow="run-title">
35
- {STATUS_ICONS[run.status]} Run {run.status}
36
- </h3>
37
- {isRunning && onCancel && (
38
- <button data-workflow="run-cancel" onClick={onCancel}>⏹ Cancel</button>
39
- )}
40
- </div>
41
- <div data-workflow="run-progress">
42
- <div data-workflow="run-progress-bar">
43
- <div data-workflow="run-progress-fill" style={{ width: `${progress}%` }} />
44
- </div>
45
- <span data-workflow="run-progress-text">{completedCount}/{totalCount} steps ({progress}%)</span>
46
- </div>
47
- <div data-workflow="run-stats">
48
- <span data-workflow="run-stat">⏱ {(duration / 1000).toFixed(1)}s</span>
49
- {totalTokens > 0 && <span data-workflow="run-stat">🪙 {totalTokens.toLocaleString()} tokens</span>}
50
- {totalCost > 0 && <span data-workflow="run-stat">💰 {formatCost(totalCost)}</span>}
51
- </div>
52
- {run.error && <div data-workflow="run-error" role="alert">{run.error}</div>}
53
- <ul data-workflow="run-steps">
54
- {run.stepResults.map(r => (
55
- <li key={r.stepId} data-workflow="run-step-item" data-status={r.status}>
56
- <span data-workflow="run-step-icon">{STATUS_ICONS[r.status]}</span>
57
- <span data-workflow="run-step-name">{r.stepName}</span>
58
- <span data-workflow="run-step-duration">{r.durationMs}ms</span>
59
- </li>
60
- ))}
61
- </ul>
62
- </div>
63
- )
64
- }
@@ -1,43 +0,0 @@
1
- // @geenius-ai-workflow/react — components/WorkflowToolbar.tsx
2
-
3
- export interface WorkflowToolbarProps {
4
- workflowName: string
5
- isDirty: boolean
6
- isRunning: boolean
7
- canUndo: boolean
8
- canRedo: boolean
9
- onSave: () => void
10
- onRun: () => void
11
- onCancel?: () => void
12
- onUndo: () => void
13
- onRedo: () => void
14
- onExport?: () => void
15
- }
16
-
17
- export function WorkflowToolbar(props: WorkflowToolbarProps) {
18
- return (
19
- <div data-workflow="toolbar" role="toolbar" aria-label="Workflow actions">
20
- <div data-workflow="toolbar-left">
21
- <h2 data-workflow="toolbar-title">{props.workflowName}</h2>
22
- {props.isDirty && <span data-workflow="toolbar-dirty">●</span>}
23
- </div>
24
- <div data-workflow="toolbar-center">
25
- <button data-workflow="toolbar-btn" onClick={props.onUndo} disabled={!props.canUndo} title="Undo">↶</button>
26
- <button data-workflow="toolbar-btn" onClick={props.onRedo} disabled={!props.canRedo} title="Redo">↷</button>
27
- </div>
28
- <div data-workflow="toolbar-right">
29
- {props.onExport && (
30
- <button data-workflow="toolbar-btn-secondary" onClick={props.onExport}>📤 Export</button>
31
- )}
32
- <button data-workflow="toolbar-btn-secondary" onClick={props.onSave} disabled={!props.isDirty}>
33
- 💾 Save
34
- </button>
35
- {props.isRunning ? (
36
- <button data-workflow="toolbar-btn-danger" onClick={props.onCancel}>⏹ Stop</button>
37
- ) : (
38
- <button data-workflow="toolbar-btn-primary" onClick={props.onRun}>▶ Run</button>
39
- )}
40
- </div>
41
- </div>
42
- )
43
- }
@@ -1,9 +0,0 @@
1
- // @geenius-ai-workflow/react — components/index.ts
2
- export { WorkflowCanvas, type WorkflowCanvasProps } from './WorkflowCanvas'
3
- export { StepNode, type StepNodeProps } from './StepNode'
4
- export { StepConnector, type StepConnectorProps } from './StepConnector'
5
- export { StepConfigPanel, type StepConfigPanelProps } from './StepConfigPanel'
6
- export { WorkflowRunPanel, type WorkflowRunPanelProps } from './WorkflowRunPanel'
7
- export { ApprovalModal, type ApprovalModalProps } from './ApprovalModal'
8
- export { WorkflowToolbar, type WorkflowToolbarProps } from './WorkflowToolbar'
9
- export { StepPalette, type StepPaletteProps } from './StepPalette'
@@ -1,10 +0,0 @@
1
- // @geenius-ai-workflow/react — src/hooks/index.ts
2
- export { useWorkflow } from './useWorkflow'
3
- export type { UseWorkflowOptions } from './useWorkflow'
4
- export { useWorkflowBuilder } from './useWorkflowBuilder'
5
- export { useWorkflowRun } from './useWorkflowRun'
6
- export type { UseWorkflowRunOptions } from './useWorkflowRun'
7
- export { useWorkflowStep } from './useWorkflowStep'
8
- export { useApprovalGate } from './useApprovalGate'
9
- export type { ApprovalRequest } from './useApprovalGate'
10
- export { useWorkflowTemplates } from './useWorkflowTemplates'
@@ -1,59 +0,0 @@
1
- // @geenius-ai-workflow/react — src/hooks/useApprovalGate.ts
2
- import { useState, useCallback } from 'react'
3
-
4
- export interface ApprovalRequest {
5
- id: string
6
- stepId: string
7
- message: string
8
- requestedAt: number
9
- approvers?: string[]
10
- }
11
-
12
- export function useApprovalGate() {
13
- const [pendingApprovals, setPendingApprovals] = useState<ApprovalRequest[]>([])
14
- const [history, setHistory] = useState<Array<ApprovalRequest & { decision: 'approved' | 'rejected'; decidedAt: number }>>([])
15
-
16
- const requestApproval = useCallback((stepId: string, message: string, approvers?: string[]) => {
17
- const request: ApprovalRequest = {
18
- id: `approval_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`,
19
- stepId,
20
- message,
21
- requestedAt: Date.now(),
22
- approvers,
23
- }
24
- setPendingApprovals(prev => [...prev, request])
25
- return request.id
26
- }, [])
27
-
28
- const approve = useCallback((approvalId: string) => {
29
- setPendingApprovals(prev => {
30
- const request = prev.find(a => a.id === approvalId)
31
- if (request) {
32
- setHistory(h => [...h, { ...request, decision: 'approved', decidedAt: Date.now() }])
33
- }
34
- return prev.filter(a => a.id !== approvalId)
35
- })
36
- }, [])
37
-
38
- const reject = useCallback((approvalId: string) => {
39
- setPendingApprovals(prev => {
40
- const request = prev.find(a => a.id === approvalId)
41
- if (request) {
42
- setHistory(h => [...h, { ...request, decision: 'rejected', decidedAt: Date.now() }])
43
- }
44
- return prev.filter(a => a.id !== approvalId)
45
- })
46
- }, [])
47
-
48
- const clearHistory = useCallback(() => setHistory([]), [])
49
-
50
- return {
51
- pendingApprovals,
52
- history,
53
- hasPending: pendingApprovals.length > 0,
54
- requestApproval,
55
- approve,
56
- reject,
57
- clearHistory,
58
- }
59
- }
@@ -1,39 +0,0 @@
1
- // @geenius-ai-workflow/react — src/hooks/useWorkflow.ts
2
- import { useState, useCallback } from 'react'
3
- import type { WorkflowDefinition, WorkflowRun, StepResult } from '@geenius-ai-workflow/shared'
4
- import { WorkflowEngine } from '@geenius-ai-workflow/shared'
5
- import type { WorkflowEngineOptions } from '@geenius-ai-workflow/shared'
6
-
7
- export interface UseWorkflowOptions extends WorkflowEngineOptions { }
8
-
9
- export function useWorkflow(options: UseWorkflowOptions) {
10
- const [run, setRun] = useState<WorkflowRun | null>(null)
11
- const [isRunning, setIsRunning] = useState(false)
12
- const [error, setError] = useState<Error | null>(null)
13
- const [stepResults, setStepResults] = useState<StepResult[]>([])
14
-
15
- const engine = new WorkflowEngine({
16
- ...options,
17
- onStepComplete: (result) => {
18
- setStepResults(prev => [...prev, result])
19
- options.onStepComplete?.(result)
20
- },
21
- })
22
-
23
- const execute = useCallback(async (definition: WorkflowDefinition, input?: Record<string, unknown>) => {
24
- setIsRunning(true); setError(null); setStepResults([])
25
- try {
26
- const result = await engine.execute(definition, input)
27
- setRun(result)
28
- return result
29
- } catch (err) {
30
- const e = err instanceof Error ? err : new Error(String(err))
31
- setError(e); throw e
32
- } finally { setIsRunning(false) }
33
- }, [])
34
-
35
- const cancel = useCallback(() => engine.cancel(), [])
36
- const reset = useCallback(() => { setRun(null); setError(null); setStepResults([]) }, [])
37
-
38
- return { execute, cancel, run, isRunning, error, stepResults, reset }
39
- }
@@ -1,121 +0,0 @@
1
- // @geenius-ai-workflow/react — src/hooks/useWorkflowBuilder.ts
2
- import { useState, useCallback } from 'react'
3
- import type { WorkflowDefinition, WorkflowStepDef, StepConnection, WorkflowBuilderState } from '@geenius-ai-workflow/shared'
4
-
5
- const emptyDef = (): WorkflowDefinition => ({
6
- id: crypto.randomUUID?.() ?? String(Date.now()),
7
- name: 'New Workflow',
8
- version: 1,
9
- status: 'draft',
10
- steps: [],
11
- connections: [],
12
- createdBy: '',
13
- createdAt: Date.now(),
14
- updatedAt: Date.now(),
15
- })
16
-
17
- export function useWorkflowBuilder(initial?: Partial<WorkflowDefinition>) {
18
- const [state, setState] = useState<WorkflowBuilderState>({
19
- definition: { ...emptyDef(), ...initial },
20
- selectedStepId: null,
21
- isDirty: false,
22
- undoStack: [],
23
- redoStack: [],
24
- })
25
-
26
- const pushUndo = useCallback(() => {
27
- setState(prev => ({ ...prev, undoStack: [...prev.undoStack.slice(-20), prev.definition], redoStack: [] }))
28
- }, [])
29
-
30
- const addStep = useCallback((step: WorkflowStepDef) => {
31
- pushUndo()
32
- setState(prev => ({
33
- ...prev,
34
- isDirty: true,
35
- definition: { ...prev.definition, steps: [...prev.definition.steps, step], updatedAt: Date.now() },
36
- }))
37
- }, [pushUndo])
38
-
39
- const removeStep = useCallback((stepId: string) => {
40
- pushUndo()
41
- setState(prev => ({
42
- ...prev,
43
- isDirty: true,
44
- definition: {
45
- ...prev.definition,
46
- steps: prev.definition.steps.filter(s => s.id !== stepId),
47
- connections: prev.definition.connections.filter(c => c.fromStepId !== stepId && c.toStepId !== stepId),
48
- updatedAt: Date.now(),
49
- },
50
- selectedStepId: prev.selectedStepId === stepId ? null : prev.selectedStepId,
51
- }))
52
- }, [pushUndo])
53
-
54
- const updateStep = useCallback((stepId: string, updates: Partial<WorkflowStepDef>) => {
55
- pushUndo()
56
- setState(prev => ({
57
- ...prev,
58
- isDirty: true,
59
- definition: {
60
- ...prev.definition,
61
- steps: prev.definition.steps.map(s => s.id === stepId ? { ...s, ...updates } : s),
62
- updatedAt: Date.now(),
63
- },
64
- }))
65
- }, [pushUndo])
66
-
67
- const addConnection = useCallback((conn: StepConnection) => {
68
- pushUndo()
69
- setState(prev => ({
70
- ...prev,
71
- isDirty: true,
72
- definition: { ...prev.definition, connections: [...prev.definition.connections, conn], updatedAt: Date.now() },
73
- }))
74
- }, [pushUndo])
75
-
76
- const removeConnection = useCallback((fromStepId: string, toStepId: string) => {
77
- pushUndo()
78
- setState(prev => ({
79
- ...prev,
80
- isDirty: true,
81
- definition: {
82
- ...prev.definition,
83
- connections: prev.definition.connections.filter(c => !(c.fromStepId === fromStepId && c.toStepId === toStepId)),
84
- updatedAt: Date.now(),
85
- },
86
- }))
87
- }, [pushUndo])
88
-
89
- const selectStep = useCallback((stepId: string | null) => setState(prev => ({ ...prev, selectedStepId: stepId })), [])
90
-
91
- const undo = useCallback(() => {
92
- setState(prev => {
93
- if (prev.undoStack.length === 0) return prev
94
- const previous = prev.undoStack[prev.undoStack.length - 1]
95
- return { ...prev, definition: previous, undoStack: prev.undoStack.slice(0, -1), redoStack: [prev.definition, ...prev.redoStack] }
96
- })
97
- }, [])
98
-
99
- const redo = useCallback(() => {
100
- setState(prev => {
101
- if (prev.redoStack.length === 0) return prev
102
- const next = prev.redoStack[0]
103
- return { ...prev, definition: next, undoStack: [...prev.undoStack, prev.definition], redoStack: prev.redoStack.slice(1) }
104
- })
105
- }, [])
106
-
107
- const setDefinition = useCallback((def: WorkflowDefinition) => {
108
- setState(prev => ({ ...prev, definition: def, isDirty: false, undoStack: [], redoStack: [] }))
109
- }, [])
110
-
111
- return {
112
- definition: state.definition,
113
- selectedStepId: state.selectedStepId,
114
- isDirty: state.isDirty,
115
- canUndo: state.undoStack.length > 0,
116
- canRedo: state.redoStack.length > 0,
117
- addStep, removeStep, updateStep,
118
- addConnection, removeConnection,
119
- selectStep, undo, redo, setDefinition,
120
- }
121
- }
@@ -1,75 +0,0 @@
1
- // @geenius-ai-workflow/react — src/hooks/useWorkflowRun.ts
2
- import { useState, useCallback, useRef, useEffect } from 'react'
3
- import type { WorkflowRun, StepResult, RunStatus } from '@geenius-ai-workflow/shared'
4
-
5
- export interface UseWorkflowRunOptions {
6
- /** Poll interval for checking run status (ms) */
7
- pollIntervalMs?: number
8
- /** Callback when a step completes */
9
- onStepComplete?: (result: StepResult) => void
10
- /** Callback when the run finishes */
11
- onRunComplete?: (run: WorkflowRun) => void
12
- }
13
-
14
- export function useWorkflowRun(options: UseWorkflowRunOptions = {}) {
15
- const [run, setRun] = useState<WorkflowRun | null>(null)
16
- const [currentStepIndex, setCurrentStepIndex] = useState(0)
17
- const [completedSteps, setCompletedSteps] = useState<StepResult[]>([])
18
- const [status, setStatus] = useState<RunStatus>('pending')
19
- const [progress, setProgress] = useState(0)
20
- const [error, setError] = useState<string | null>(null)
21
- const timerRef = useRef<ReturnType<typeof setInterval> | null>(null)
22
-
23
- const trackRun = useCallback((workflowRun: WorkflowRun) => {
24
- setRun(workflowRun)
25
- setStatus(workflowRun.status)
26
- setCurrentStepIndex(workflowRun.currentStepIndex)
27
- setCompletedSteps(workflowRun.stepResults)
28
- setError(workflowRun.error ?? null)
29
-
30
- const total = workflowRun.stepResults.length
31
- const done = workflowRun.stepResults.filter(s => s.status === 'completed' || s.status === 'skipped').length
32
- setProgress(total > 0 ? Math.round((done / total) * 100) : 0)
33
-
34
- if (workflowRun.status === 'completed' || workflowRun.status === 'failed') {
35
- options.onRunComplete?.(workflowRun)
36
- }
37
- }, [options.onRunComplete])
38
-
39
- const updateStep = useCallback((result: StepResult) => {
40
- setCompletedSteps(prev => {
41
- const existing = prev.findIndex(s => s.stepId === result.stepId)
42
- if (existing >= 0) {
43
- const updated = [...prev]
44
- updated[existing] = result
45
- return updated
46
- }
47
- return [...prev, result]
48
- })
49
- setCurrentStepIndex(prev => prev + 1)
50
- options.onStepComplete?.(result)
51
- }, [options.onStepComplete])
52
-
53
- const reset = useCallback(() => {
54
- setRun(null)
55
- setCurrentStepIndex(0)
56
- setCompletedSteps([])
57
- setStatus('pending')
58
- setProgress(0)
59
- setError(null)
60
- if (timerRef.current) clearInterval(timerRef.current)
61
- }, [])
62
-
63
- useEffect(() => {
64
- return () => { if (timerRef.current) clearInterval(timerRef.current) }
65
- }, [])
66
-
67
- return {
68
- run, status, currentStepIndex, completedSteps,
69
- progress, error,
70
- trackRun, updateStep, reset,
71
- isRunning: status === 'running',
72
- isComplete: status === 'completed',
73
- isFailed: status === 'failed',
74
- }
75
- }
@@ -1,52 +0,0 @@
1
- // @geenius-ai-workflow/react — src/hooks/useWorkflowStep.ts
2
- import { useState, useCallback, useMemo } from 'react'
3
- import type { WorkflowStepDef, StepResult, StepStatus, StepConfig } from '@geenius-ai-workflow/shared'
4
-
5
- export function useWorkflowStep(stepDef: WorkflowStepDef) {
6
- const [status, setStatus] = useState<StepStatus>('pending')
7
- const [output, setOutput] = useState<unknown>(null)
8
- const [error, setError] = useState<string | null>(null)
9
- const [durationMs, setDurationMs] = useState(0)
10
-
11
- const updateFromResult = useCallback((result: StepResult) => {
12
- setStatus(result.status)
13
- setOutput(result.output ?? null)
14
- setError(result.error ?? null)
15
- setDurationMs(result.durationMs)
16
- }, [])
17
-
18
- const reset = useCallback(() => {
19
- setStatus('pending')
20
- setOutput(null)
21
- setError(null)
22
- setDurationMs(0)
23
- }, [])
24
-
25
- const icon = useMemo(() => {
26
- const map: Record<string, string> = {
27
- 'llm-call': '🤖', 'transform': '⚙️', 'condition': '🔀',
28
- 'human-approval': '👤', 'webhook': '🌐', 'delay': '⏱️',
29
- 'parallel': '⚡', 'loop': '🔄', 'sub-workflow': '📋', 'custom': '🔧',
30
- }
31
- return map[stepDef.type] ?? '📦'
32
- }, [stepDef.type])
33
-
34
- const statusColor = useMemo(() => {
35
- const map: Record<StepStatus, string> = {
36
- pending: 'gray', running: 'blue', completed: 'green',
37
- failed: 'red', skipped: 'orange', 'waiting-approval': 'purple',
38
- }
39
- return map[status]
40
- }, [status])
41
-
42
- return {
43
- stepDef, status, output, error, durationMs,
44
- icon, statusColor,
45
- updateFromResult, reset,
46
- isComplete: status === 'completed',
47
- isRunning: status === 'running',
48
- isFailed: status === 'failed',
49
- isWaiting: status === 'waiting-approval',
50
- config: stepDef.config as StepConfig,
51
- }
52
- }
@@ -1,54 +0,0 @@
1
- // @geenius-ai-workflow/react — src/hooks/useWorkflowTemplates.ts
2
- import { useState, useCallback, useMemo } from 'react'
3
- import type { WorkflowDefinition } from '@geenius-ai-workflow/shared'
4
- import { WORKFLOW_TEMPLATES, getTemplate, getTemplatesByCategory } from '@geenius-ai-workflow/shared'
5
- import type { WorkflowTemplate } from '@geenius-ai-workflow/shared'
6
-
7
- export function useWorkflowTemplates(userId: string) {
8
- const [selectedTemplateId, setSelectedTemplateId] = useState<string | null>(null)
9
- const [filterCategory, setFilterCategory] = useState<WorkflowTemplate['category'] | 'all'>('all')
10
- const [searchQuery, setSearchQuery] = useState('')
11
-
12
- const filteredTemplates = useMemo(() => {
13
- let templates = filterCategory === 'all' ? WORKFLOW_TEMPLATES : getTemplatesByCategory(filterCategory)
14
- if (searchQuery.trim()) {
15
- const q = searchQuery.toLowerCase()
16
- templates = templates.filter(t =>
17
- t.name.toLowerCase().includes(q) ||
18
- t.description.toLowerCase().includes(q) ||
19
- t.tags.some(tag => tag.includes(q))
20
- )
21
- }
22
- return templates
23
- }, [filterCategory, searchQuery])
24
-
25
- const selectedTemplate = useMemo(
26
- () => selectedTemplateId ? getTemplate(selectedTemplateId) ?? null : null,
27
- [selectedTemplateId],
28
- )
29
-
30
- const createFromTemplate = useCallback((templateId: string): WorkflowDefinition | null => {
31
- const template = getTemplate(templateId)
32
- if (!template) return null
33
- return template.create(userId)
34
- }, [userId])
35
-
36
- const categories = useMemo(
37
- () => [...new Set(WORKFLOW_TEMPLATES.map(t => t.category))],
38
- [],
39
- )
40
-
41
- return {
42
- templates: filteredTemplates,
43
- allTemplates: WORKFLOW_TEMPLATES,
44
- selectedTemplate,
45
- selectedTemplateId,
46
- categories,
47
- filterCategory,
48
- searchQuery,
49
- setSelectedTemplateId,
50
- setFilterCategory,
51
- setSearchQuery,
52
- createFromTemplate,
53
- }
54
- }
@@ -1,16 +0,0 @@
1
- // @geenius-ai-workflow/react — src/index.ts
2
- export type {
3
- WorkflowStatus, RunStatus, StepStatus, StepType,
4
- WorkflowDefinition, WorkflowStepDef, StepConfig,
5
- WorkflowRun, StepResult, WorkflowBuilderState,
6
- } from '@geenius-ai-workflow/shared'
7
- export { WorkflowEngine, WORKFLOW_TEMPLATES, validateWorkflow } from '@geenius-ai-workflow/shared'
8
-
9
- // Hooks
10
- export * from './hooks'
11
-
12
- // Components
13
- export * from './components'
14
-
15
- // Pages
16
- export * from './pages'
@@ -1,81 +0,0 @@
1
- // @geenius-ai-workflow/react — pages/WorkflowBuilderPage.tsx
2
- import { useCallback } from 'react'
3
- import type { StepType, WorkflowStepDef } from '@geenius-ai-workflow/shared'
4
- import { WorkflowEngine } from '@geenius-ai-workflow/shared'
5
- import type { WorkflowEngineOptions } from '@geenius-ai-workflow/shared'
6
- import { useWorkflowBuilder } from '../hooks/useWorkflowBuilder'
7
- import { useWorkflowRun } from '../hooks/useWorkflowRun'
8
- import { WorkflowCanvas } from '../components/WorkflowCanvas'
9
- import { WorkflowToolbar } from '../components/WorkflowToolbar'
10
- import { StepPalette } from '../components/StepPalette'
11
- import { StepConfigPanel } from '../components/StepConfigPanel'
12
- import { WorkflowRunPanel } from '../components/WorkflowRunPanel'
13
-
14
- export interface WorkflowBuilderPageProps {
15
- engineOptions: WorkflowEngineOptions
16
- onSave?: (def: any) => void
17
- }
18
-
19
- export function WorkflowBuilderPage({ engineOptions, onSave }: WorkflowBuilderPageProps) {
20
- const builder = useWorkflowBuilder()
21
- const runTracker = useWorkflowRun()
22
-
23
- const handleAddStep = useCallback((type: StepType) => {
24
- const id = `step_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`
25
- const step: WorkflowStepDef = {
26
- id,
27
- name: `New ${type} step`,
28
- type,
29
- config: { type } as any,
30
- position: { x: 100 + builder.definition.steps.length * 250, y: 200 },
31
- }
32
- builder.addStep(step)
33
- }, [builder])
34
-
35
- const handleRun = useCallback(async () => {
36
- const engine = new WorkflowEngine({
37
- ...engineOptions,
38
- onStepComplete: (result) => { runTracker.updateStep(result) },
39
- })
40
- const result = await engine.execute(builder.definition)
41
- runTracker.trackRun(result)
42
- }, [builder.definition, engineOptions, runTracker])
43
-
44
- return (
45
- <div data-workflow="builder-page">
46
- <WorkflowToolbar
47
- workflowName={builder.definition.name}
48
- isDirty={builder.isDirty}
49
- isRunning={runTracker.isRunning}
50
- canUndo={builder.canUndo}
51
- canRedo={builder.canRedo}
52
- onSave={() => onSave?.(builder.definition)}
53
- onRun={handleRun}
54
- onUndo={builder.undo}
55
- onRedo={builder.redo}
56
- />
57
- <div data-workflow="builder-layout">
58
- <StepPalette onAddStep={handleAddStep} />
59
- <WorkflowCanvas
60
- definition={builder.definition}
61
- selectedStepId={builder.selectedStepId}
62
- onSelectStep={builder.selectStep}
63
- />
64
- {builder.selectedStepId && (() => {
65
- const step = builder.definition.steps.find(s => s.id === builder.selectedStepId)
66
- return step ? (
67
- <StepConfigPanel
68
- step={step}
69
- onUpdate={builder.updateStep}
70
- onDelete={builder.removeStep}
71
- onClose={() => builder.selectStep(null)}
72
- />
73
- ) : null
74
- })()}
75
- {runTracker.run && (
76
- <WorkflowRunPanel run={runTracker.run} isRunning={runTracker.isRunning} />
77
- )}
78
- </div>
79
- </div>
80
- )
81
- }