@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.
Files changed (140) hide show
  1. package/.changeset/config.json +11 -0
  2. package/.github/CODEOWNERS +1 -0
  3. package/.github/ISSUE_TEMPLATE/bug_report.md +16 -0
  4. package/.github/ISSUE_TEMPLATE/feature_request.md +11 -0
  5. package/.github/PULL_REQUEST_TEMPLATE.md +10 -0
  6. package/.github/dependabot.yml +11 -0
  7. package/.github/workflows/ci.yml +23 -0
  8. package/.github/workflows/release.yml +29 -0
  9. package/.nvmrc +1 -0
  10. package/.project/ACCOUNT.yaml +4 -0
  11. package/.project/IDEAS.yaml +7 -0
  12. package/.project/PROJECT.yaml +11 -0
  13. package/.project/ROADMAP.yaml +15 -0
  14. package/CHANGELOG.md +11 -0
  15. package/CODE_OF_CONDUCT.md +16 -0
  16. package/CONTRIBUTING.md +26 -0
  17. package/LICENSE +21 -0
  18. package/README.md +1 -0
  19. package/SECURITY.md +15 -0
  20. package/SUPPORT.md +8 -0
  21. package/package.json +74 -0
  22. package/packages/convex/README.md +1 -0
  23. package/packages/convex/package.json +12 -0
  24. package/packages/convex/src/convex.config.ts +3 -0
  25. package/packages/convex/src/index.ts +3 -0
  26. package/packages/convex/src/mutations.ts +36 -0
  27. package/packages/convex/src/queries.ts +19 -0
  28. package/packages/convex/src/schema.ts +24 -0
  29. package/packages/convex/tsconfig.json +25 -0
  30. package/packages/react/README.md +1 -0
  31. package/packages/react/package.json +46 -0
  32. package/packages/react/src/components/ApprovalModal.tsx +47 -0
  33. package/packages/react/src/components/StepConfigPanel.tsx +67 -0
  34. package/packages/react/src/components/StepConnector.tsx +47 -0
  35. package/packages/react/src/components/StepNode.tsx +38 -0
  36. package/packages/react/src/components/StepPalette.tsx +48 -0
  37. package/packages/react/src/components/WorkflowCanvas.tsx +42 -0
  38. package/packages/react/src/components/WorkflowRunPanel.tsx +64 -0
  39. package/packages/react/src/components/WorkflowToolbar.tsx +43 -0
  40. package/packages/react/src/components/index.ts +9 -0
  41. package/packages/react/src/hooks/index.ts +10 -0
  42. package/packages/react/src/hooks/useApprovalGate.ts +59 -0
  43. package/packages/react/src/hooks/useWorkflow.ts +39 -0
  44. package/packages/react/src/hooks/useWorkflowBuilder.ts +121 -0
  45. package/packages/react/src/hooks/useWorkflowRun.ts +75 -0
  46. package/packages/react/src/hooks/useWorkflowStep.ts +52 -0
  47. package/packages/react/src/hooks/useWorkflowTemplates.ts +54 -0
  48. package/packages/react/src/index.ts +16 -0
  49. package/packages/react/src/pages/WorkflowBuilderPage.tsx +81 -0
  50. package/packages/react/src/pages/WorkflowRunsPage.tsx +59 -0
  51. package/packages/react/src/pages/index.ts +3 -0
  52. package/packages/react/tsconfig.json +1 -0
  53. package/packages/react/tsup.config.ts +7 -0
  54. package/packages/react-css/README.md +1 -0
  55. package/packages/react-css/package.json +44 -0
  56. package/packages/react-css/src/components/ApprovalModal.tsx +6 -0
  57. package/packages/react-css/src/components/StepConfigPanel.tsx +7 -0
  58. package/packages/react-css/src/components/StepConnector.tsx +6 -0
  59. package/packages/react-css/src/components/StepNode.tsx +7 -0
  60. package/packages/react-css/src/components/StepPalette.tsx +6 -0
  61. package/packages/react-css/src/components/WorkflowCanvas.tsx +6 -0
  62. package/packages/react-css/src/components/WorkflowRunPanel.tsx +9 -0
  63. package/packages/react-css/src/components/WorkflowToolbar.tsx +4 -0
  64. package/packages/react-css/src/components/index.ts +9 -0
  65. package/packages/react-css/src/hooks/index.ts +3 -0
  66. package/packages/react-css/src/hooks/useWorkflow.ts +39 -0
  67. package/packages/react-css/src/hooks/useWorkflowBuilder.ts +121 -0
  68. package/packages/react-css/src/index.ts +7 -0
  69. package/packages/react-css/src/pages/WorkflowBuilderPage.tsx +16 -0
  70. package/packages/react-css/src/pages/WorkflowRunsPage.tsx +6 -0
  71. package/packages/react-css/src/pages/index.ts +3 -0
  72. package/packages/react-css/src/styles.css +945 -0
  73. package/packages/react-css/tsconfig.json +26 -0
  74. package/packages/react-css/tsup.config.ts +2 -0
  75. package/packages/shared/README.md +1 -0
  76. package/packages/shared/package.json +56 -0
  77. package/packages/shared/src/__tests__/ai-workflow.test.ts +217 -0
  78. package/packages/shared/src/config.ts +49 -0
  79. package/packages/shared/src/convex/index.ts +2 -0
  80. package/packages/shared/src/convex/schemas.ts +42 -0
  81. package/packages/shared/src/engine.test.ts +1 -0
  82. package/packages/shared/src/engine.ts +295 -0
  83. package/packages/shared/src/index.ts +43 -0
  84. package/packages/shared/src/steps.ts +68 -0
  85. package/packages/shared/src/templates.ts +172 -0
  86. package/packages/shared/src/types.ts +237 -0
  87. package/packages/shared/src/utils/cost.ts +79 -0
  88. package/packages/shared/src/utils/dag.ts +133 -0
  89. package/packages/shared/src/utils/index.ts +5 -0
  90. package/packages/shared/src/utils/interpolation.ts +53 -0
  91. package/packages/shared/src/validators.ts +215 -0
  92. package/packages/shared/tsconfig.json +1 -0
  93. package/packages/shared/tsup.config.ts +5 -0
  94. package/packages/shared/vitest.config.ts +4 -0
  95. package/packages/solidjs/README.md +1 -0
  96. package/packages/solidjs/package.json +45 -0
  97. package/packages/solidjs/src/components/ApprovalModal.tsx +18 -0
  98. package/packages/solidjs/src/components/StepConfigPanel.tsx +14 -0
  99. package/packages/solidjs/src/components/StepConnector.tsx +11 -0
  100. package/packages/solidjs/src/components/StepNode.tsx +12 -0
  101. package/packages/solidjs/src/components/StepPalette.tsx +22 -0
  102. package/packages/solidjs/src/components/WorkflowCanvas.tsx +23 -0
  103. package/packages/solidjs/src/components/WorkflowRunPanel.tsx +18 -0
  104. package/packages/solidjs/src/components/WorkflowToolbar.tsx +13 -0
  105. package/packages/solidjs/src/components/index.ts +9 -0
  106. package/packages/solidjs/src/index.ts +7 -0
  107. package/packages/solidjs/src/pages/WorkflowBuilderPage.tsx +37 -0
  108. package/packages/solidjs/src/pages/WorkflowRunsPage.tsx +20 -0
  109. package/packages/solidjs/src/pages/index.ts +3 -0
  110. package/packages/solidjs/src/primitives/createApprovalGate.ts +29 -0
  111. package/packages/solidjs/src/primitives/createWorkflow.ts +28 -0
  112. package/packages/solidjs/src/primitives/createWorkflowBuilder.ts +56 -0
  113. package/packages/solidjs/src/primitives/createWorkflowRun.ts +32 -0
  114. package/packages/solidjs/src/primitives/createWorkflowStep.ts +23 -0
  115. package/packages/solidjs/src/primitives/createWorkflowTemplates.ts +28 -0
  116. package/packages/solidjs/src/primitives/index.ts +8 -0
  117. package/packages/solidjs/tsconfig.json +1 -0
  118. package/packages/solidjs/tsup.config.ts +7 -0
  119. package/packages/solidjs-css/README.md +1 -0
  120. package/packages/solidjs-css/package.json +43 -0
  121. package/packages/solidjs-css/src/components/ApprovalModal.tsx +6 -0
  122. package/packages/solidjs-css/src/components/StepConfigPanel.tsx +7 -0
  123. package/packages/solidjs-css/src/components/StepConnector.tsx +6 -0
  124. package/packages/solidjs-css/src/components/StepNode.tsx +7 -0
  125. package/packages/solidjs-css/src/components/StepPalette.tsx +7 -0
  126. package/packages/solidjs-css/src/components/WorkflowCanvas.tsx +7 -0
  127. package/packages/solidjs-css/src/components/WorkflowRunPanel.tsx +8 -0
  128. package/packages/solidjs-css/src/components/WorkflowToolbar.tsx +5 -0
  129. package/packages/solidjs-css/src/components/index.ts +9 -0
  130. package/packages/solidjs-css/src/index.ts +7 -0
  131. package/packages/solidjs-css/src/pages/WorkflowBuilderPage.tsx +2 -0
  132. package/packages/solidjs-css/src/pages/WorkflowRunsPage.tsx +7 -0
  133. package/packages/solidjs-css/src/pages/index.ts +3 -0
  134. package/packages/solidjs-css/src/primitives/createWorkflow.ts +28 -0
  135. package/packages/solidjs-css/src/primitives/createWorkflowBuilder.ts +56 -0
  136. package/packages/solidjs-css/src/primitives/index.ts +1 -0
  137. package/packages/solidjs-css/src/styles.css +945 -0
  138. package/packages/solidjs-css/tsconfig.json +27 -0
  139. package/packages/solidjs-css/tsup.config.ts +2 -0
  140. package/pnpm-workspace.yaml +2 -0
@@ -0,0 +1,32 @@
1
+ // @geenius-ai-workflow/solidjs β€” src/primitives/createWorkflowRun.ts
2
+ import { createSignal } from 'solid-js'
3
+ import type { WorkflowRun, StepResult, RunStatus } from '@geenius-ai-workflow/shared'
4
+
5
+ export function createWorkflowRun() {
6
+ const [run, setRun] = createSignal<WorkflowRun | null>(null)
7
+ const [status, setStatus] = createSignal<RunStatus>('pending')
8
+ const [currentStepIndex, setCurrentStepIndex] = createSignal(0)
9
+ const [completedSteps, setCompletedSteps] = createSignal<StepResult[]>([])
10
+ const [progress, setProgress] = createSignal(0)
11
+ const [error, setError] = createSignal<string | null>(null)
12
+
13
+ const trackRun = (wfRun: WorkflowRun) => {
14
+ setRun(wfRun); setStatus(wfRun.status); setCurrentStepIndex(wfRun.currentStepIndex)
15
+ setCompletedSteps(wfRun.stepResults); setError(wfRun.error ?? null)
16
+ const done = wfRun.stepResults.filter(s => s.status === 'completed' || s.status === 'skipped').length
17
+ setProgress(wfRun.stepResults.length > 0 ? Math.round((done / wfRun.stepResults.length) * 100) : 0)
18
+ }
19
+
20
+ const updateStep = (result: StepResult) => {
21
+ setCompletedSteps(prev => {
22
+ const idx = prev.findIndex(s => s.stepId === result.stepId)
23
+ if (idx >= 0) { const u = [...prev]; u[idx] = result; return u }
24
+ return [...prev, result]
25
+ })
26
+ setCurrentStepIndex(prev => prev + 1)
27
+ }
28
+
29
+ const reset = () => { setRun(null); setStatus('pending'); setCurrentStepIndex(0); setCompletedSteps([]); setProgress(0); setError(null) }
30
+
31
+ return { run, status, currentStepIndex, completedSteps, progress, error, trackRun, updateStep, reset, isRunning: () => status() === 'running', isComplete: () => status() === 'completed', isFailed: () => status() === 'failed' }
32
+ }
@@ -0,0 +1,23 @@
1
+ // @geenius-ai-workflow/solidjs β€” src/primitives/createWorkflowStep.ts
2
+ import { createSignal, createMemo } from 'solid-js'
3
+ import type { WorkflowStepDef, StepResult, StepStatus, StepConfig } from '@geenius-ai-workflow/shared'
4
+
5
+ const STEP_ICONS: Record<string, string> = { 'llm-call': 'πŸ€–', transform: 'βš™οΈ', condition: 'πŸ”€', 'human-approval': 'πŸ‘€', webhook: '🌐', delay: '⏱️', parallel: '⚑', loop: 'πŸ”„', 'sub-workflow': 'πŸ“‹', custom: 'πŸ”§' }
6
+
7
+ export function createWorkflowStep(stepDef: WorkflowStepDef) {
8
+ const [status, setStatus] = createSignal<StepStatus>('pending')
9
+ const [output, setOutput] = createSignal<unknown>(null)
10
+ const [error, setError] = createSignal<string | null>(null)
11
+ const [durationMs, setDurationMs] = createSignal(0)
12
+
13
+ const icon = createMemo(() => STEP_ICONS[stepDef.type] ?? 'πŸ“¦')
14
+ const statusColor = createMemo(() => {
15
+ const m: Record<StepStatus, string> = { pending: 'gray', running: 'blue', completed: 'green', failed: 'red', skipped: 'orange', 'waiting-approval': 'purple' }
16
+ return m[status()]
17
+ })
18
+
19
+ const updateFromResult = (result: StepResult) => { setStatus(result.status); setOutput(result.output ?? null); setError(result.error ?? null); setDurationMs(result.durationMs) }
20
+ const reset = () => { setStatus('pending'); setOutput(null); setError(null); setDurationMs(0) }
21
+
22
+ return { stepDef, status, output, error, durationMs, icon, statusColor, updateFromResult, reset, isComplete: () => status() === 'completed', isRunning: () => status() === 'running', isFailed: () => status() === 'failed', isWaiting: () => status() === 'waiting-approval', config: stepDef.config as StepConfig }
23
+ }
@@ -0,0 +1,28 @@
1
+ // @geenius-ai-workflow/solidjs β€” src/primitives/createWorkflowTemplates.ts
2
+ import { createSignal, createMemo } from 'solid-js'
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 createWorkflowTemplates(userId: string) {
8
+ const [selectedTemplateId, setSelectedTemplateId] = createSignal<string | null>(null)
9
+ const [filterCategory, setFilterCategory] = createSignal<WorkflowTemplate['category'] | 'all'>('all')
10
+ const [searchQuery, setSearchQuery] = createSignal('')
11
+
12
+ const filteredTemplates = createMemo(() => {
13
+ let templates = filterCategory() === 'all' ? WORKFLOW_TEMPLATES : getTemplatesByCategory(filterCategory() as WorkflowTemplate['category'])
14
+ const q = searchQuery().toLowerCase()
15
+ if (q) templates = templates.filter(t => t.name.toLowerCase().includes(q) || t.description.toLowerCase().includes(q) || t.tags.some(tag => tag.includes(q)))
16
+ return templates
17
+ })
18
+
19
+ const selectedTemplate = createMemo(() => { const id = selectedTemplateId(); return id ? getTemplate(id) ?? null : null })
20
+
21
+ const createFromTemplate = (templateId: string): WorkflowDefinition | null => {
22
+ const tpl = getTemplate(templateId); return tpl ? tpl.create(userId) : null
23
+ }
24
+
25
+ const categories = createMemo(() => [...new Set(WORKFLOW_TEMPLATES.map(t => t.category))])
26
+
27
+ return { templates: filteredTemplates, allTemplates: WORKFLOW_TEMPLATES, selectedTemplate, selectedTemplateId, categories, filterCategory, searchQuery, setSelectedTemplateId, setFilterCategory, setSearchQuery, createFromTemplate }
28
+ }
@@ -0,0 +1,8 @@
1
+ // @geenius-ai-workflow/solidjs β€” src/primitives/index.ts
2
+ export { createWorkflow } from './createWorkflow'
3
+ export { createWorkflowBuilder } from './createWorkflowBuilder'
4
+ export { createWorkflowRun } from './createWorkflowRun'
5
+ export { createWorkflowStep } from './createWorkflowStep'
6
+ export { createApprovalGate } from './createApprovalGate'
7
+ export type { ApprovalRequest } from './createApprovalGate'
8
+ export { createWorkflowTemplates } from './createWorkflowTemplates'
@@ -0,0 +1 @@
1
+ {"compilerOptions":{"target":"ES2022","module":"ESNext","moduleResolution":"bundler","jsx":"preserve","jsxImportSource":"solid-js","declaration":true,"declarationMap":true,"sourceMap":true,"outDir":"./dist","rootDir":"./src","strict":true,"esModuleInterop":true,"skipLibCheck":true,"forceConsistentCasingInFileNames":true,"resolveJsonModule":true,"isolatedModules":true},"include":["src"],"exclude":["node_modules","dist"]}
@@ -0,0 +1,7 @@
1
+ import { defineConfig } from 'tsup'
2
+ export default defineConfig({
3
+ entry: { index: 'src/index.ts' },
4
+ format: ['esm'], dts: true, clean: true, sourcemap: true,
5
+ external: ['solid-js', '@geenius-ai-workflow/shared'],
6
+ esbuildOptions(options) { options.jsx = 'preserve' },
7
+ })
@@ -0,0 +1 @@
1
+ # ✦ @geenius-ai-workflow/solidjs-css\n\n> Geenius AI Workflow β€” SolidJS primitives (vanilla CSS variant)\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/solidjs-css\n```\n\n## Usage\n\n```typescript\nimport { init } from '@geenius-ai-workflow/solidjs-css';\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,43 @@
1
+ {
2
+ "name": "@geenius-ai-workflow/solidjs-css",
3
+ "version": "0.1.0",
4
+ "description": "Geenius AI Workflow β€” SolidJS primitives (vanilla CSS variant)",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.mjs",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.js",
13
+ "types": "./dist/index.d.ts"
14
+ }
15
+ },
16
+ "scripts": {
17
+ "build": "tsup",
18
+ "lint": "tsc --noEmit",
19
+ "clean": "rm -rf dist"
20
+ },
21
+ "files": [
22
+ "dist"
23
+ ],
24
+ "publishConfig": {
25
+ "access": "public"
26
+ },
27
+ "peerDependencies": {
28
+ "solid-js": ">=1.6.0"
29
+ },
30
+ "dependencies": {
31
+ "@geenius-ai-workflow/shared": "workspace:*"
32
+ },
33
+ "devDependencies": {
34
+ "solid-js": "^1.9.5",
35
+ "tsup": "^8.5.1",
36
+ "typescript": "~5.9.3"
37
+ },
38
+ "author": "Antigravity HQ",
39
+ "license": "MIT",
40
+ "engines": {
41
+ "node": ">=20.0.0"
42
+ }
43
+ }
@@ -0,0 +1,6 @@
1
+ // @geenius-ai-workflow/solidjs-css β€” components/ApprovalModal.tsx
2
+ import { Show, For } from 'solid-js'
3
+ import type { ApprovalRequest } from '../primitives'
4
+ export function ApprovalModal(props: { request: ApprovalRequest | null; onApprove: (id: string) => void; onReject: (id: string) => void }) {
5
+ return (<Show when={props.request}>{(req) => (<div role="dialog" aria-modal="true"><div class="ai-workflow__approval-overlay" /><div class="ai-workflow__approval-dialog"><div class="ai-workflow__approval-header"><span class="ai-workflow__approval-icon">πŸ‘€</span><h3 class="ai-workflow__approval-title">Approval Required</h3></div><div><p class="ai-workflow__approval-message">{req().message}</p><Show when={req().approvers && req().approvers!.length > 0}><div><For each={req().approvers!}>{(a) => <span class="ai-workflow__approval-approver-badge">{a}</span>}</For></div></Show></div><div class="ai-workflow__approval-actions"><button class="ai-workflow__approval-reject" onClick={() => props.onReject(req().id)}>βœ• Reject</button><button class="ai-workflow__approval-approve" onClick={() => props.onApprove(req().id)}>βœ“ Approve</button></div></div></div>)}</Show>)
6
+ }
@@ -0,0 +1,7 @@
1
+ // @geenius-ai-workflow/solidjs-css β€” components/StepConfigPanel.tsx
2
+ import { createSignal } from 'solid-js'
3
+ import type { WorkflowStepDef } from '@geenius-ai-workflow/shared'
4
+ export function StepConfigPanel(props: { step: WorkflowStepDef; onUpdate: (id: string, u: Partial<WorkflowStepDef>) => void; onDelete: (id: string) => void; onClose: () => void }) {
5
+ const [name, setName] = createSignal(props.step.name)
6
+ return (<div class="ai-workflow__config-panel" role="complementary"><div class="ai-workflow__config-header"><h3 class="ai-workflow__config-title">Configure Step</h3><button class="ai-workflow__config-close" onClick={props.onClose}>βœ•</button></div><div class="ai-workflow__config-body"><label class="ai-workflow__config-label">Step Name<input class="ai-workflow__config-input" value={name()} onInput={(e) => setName(e.currentTarget.value)} onBlur={() => { if (name().trim() && name() !== props.step.name) props.onUpdate(props.step.id, { name: name().trim() }) }} /></label><div class="ai-workflow__config-field"><span class="ai-workflow__config-field-label">Type</span><span class="ai-workflow__config-field-value">{props.step.type}</span></div><pre class="ai-workflow__config-json-view">{JSON.stringify(props.step.config, null, 2)}</pre></div><div><button class="ai-workflow__config-delete" onClick={() => { props.onDelete(props.step.id); props.onClose() }}>πŸ—‘ Delete</button></div></div>)
7
+ }
@@ -0,0 +1,6 @@
1
+ // @geenius-ai-workflow/solidjs-css β€” components/StepConnector.tsx
2
+ const W = 200, H = 80
3
+ export function StepConnector(props: { from: { x: number; y: number }; to: { x: number; y: number }; label?: string; isActive?: boolean }) {
4
+ const x1 = () => props.from.x + W, y1 = () => props.from.y + H / 2, x2 = () => props.to.x, y2 = () => props.to.y + H / 2, mx = () => (x1() + x2()) / 2
5
+ return (<g class="ai-workflow__connector"><path d={`M ${x1()} ${y1()} C ${mx()} ${y1()}, ${mx()} ${y2()}, ${x2()} ${y2()}`} fill="none" stroke={props.isActive ? 'oklch(0.7 0.2 145)' : 'oklch(0.5 0.02 260)'} stroke-width={props.isActive ? 3 : 2} />{props.label && <text x={mx()} y={(y1() + y2()) / 2 - 8} text-anchor="middle" fill="oklch(0.7 0.02 260)" font-size="12">{props.label}</text>}</g>)
6
+ }
@@ -0,0 +1,7 @@
1
+ // @geenius-ai-workflow/solidjs-css β€” components/StepNode.tsx
2
+ import type { WorkflowStepDef, StepType } from '@geenius-ai-workflow/shared'
3
+ const ICONS: Record<StepType, string> = { 'llm-call': 'πŸ€–', transform: 'βš™οΈ', condition: 'πŸ”€', 'human-approval': 'πŸ‘€', webhook: '🌐', delay: '⏱️', parallel: '⚑', loop: 'πŸ”„', 'sub-workflow': 'πŸ“‹', custom: 'πŸ”§' }
4
+ export function StepNode(props: { step: WorkflowStepDef; isSelected?: boolean; status?: string; onClick?: () => void }) {
5
+ const cls = () => ['ai-workflow__step-node', props.isSelected && 'ai-workflow__step-node--selected', props.status && `ai-workflow__step-node--${props.status}`].filter(Boolean).join(' ')
6
+ return (<div class={cls()} role="button" tabIndex={0} onClick={props.onClick} style={props.step.position ? { position: 'absolute', left: `${props.step.position.x}px`, top: `${props.step.position.y}px` } : undefined}><div class="ai-workflow__step-header"><span class="ai-workflow__step-icon">{ICONS[props.step.type]}</span><span class="ai-workflow__step-name">{props.step.name}</span></div><div class="ai-workflow__step-type-badge">{props.step.type}</div></div>)
7
+ }
@@ -0,0 +1,7 @@
1
+ // @geenius-ai-workflow/solidjs-css β€” components/StepPalette.tsx
2
+ import { For } from 'solid-js'
3
+ import type { StepType } from '@geenius-ai-workflow/shared'
4
+ const ITEMS: Array<{ type: StepType; label: string; icon: string; desc: string }> = [{ type: 'llm-call', label: 'LLM Call', icon: 'πŸ€–', desc: 'Call an AI model' },{ type: 'transform', label: 'Transform', icon: 'βš™οΈ', desc: 'Transform data' },{ type: 'condition', label: 'Condition', icon: 'πŸ”€', desc: 'If/else branching' },{ type: 'human-approval', label: 'Approval', icon: 'πŸ‘€', desc: 'Human approval gate' },{ type: 'webhook', label: 'Webhook', icon: '🌐', desc: 'HTTP request' },{ type: 'delay', label: 'Delay', icon: '⏱️', desc: 'Wait' },{ type: 'parallel', label: 'Parallel', icon: '⚑', desc: 'Run in parallel' },{ type: 'loop', label: 'Loop', icon: 'πŸ”„', desc: 'Iterate' },{ type: 'sub-workflow', label: 'Sub-workflow', icon: 'πŸ“‹', desc: 'Run another workflow' },{ type: 'custom', label: 'Custom', icon: 'πŸ”§', desc: 'Custom handler' }]
5
+ export function StepPalette(props: { onAddStep: (t: StepType) => void }) {
6
+ return (<div class="ai-workflow__step-palette" role="list"><h3 class="ai-workflow__palette-title">Steps</h3><For each={ITEMS}>{(item) => <button class="ai-workflow__palette-item" onClick={() => props.onAddStep(item.type)}><span class="ai-workflow__palette-icon">{item.icon}</span><div class="ai-workflow__palette-info"><span class="ai-workflow__palette-label">{item.label}</span><span class="ai-workflow__palette-desc">{item.desc}</span></div></button>}</For></div>)
7
+ }
@@ -0,0 +1,7 @@
1
+ // @geenius-ai-workflow/solidjs-css β€” components/WorkflowCanvas.tsx
2
+ import { For, Show } from 'solid-js'
3
+ import type { WorkflowDefinition } from '@geenius-ai-workflow/shared'
4
+ import { StepNode } from './StepNode'; import { StepConnector } from './StepConnector'
5
+ export function WorkflowCanvas(props: { definition: WorkflowDefinition; selectedStepId: string | null; onSelectStep: (id: string | null) => void }) {
6
+ return (<div class="ai-workflow__canvas" role="application"><svg style={{ position: 'absolute', inset: '0', 'pointer-events': 'none' }}><For each={props.definition.connections}>{(conn) => { const f = () => props.definition.steps.find(s => s.id === conn.fromStepId); const t = () => props.definition.steps.find(s => s.id === conn.toStepId); return <Show when={f()?.position && t()?.position}><StepConnector from={f()!.position!} to={t()!.position!} label={conn.label} /></Show> }}</For></svg><div><For each={props.definition.steps}>{(step) => <StepNode step={step} isSelected={props.selectedStepId === step.id} onClick={() => props.onSelectStep(step.id === props.selectedStepId ? null : step.id)} />}</For></div><Show when={props.definition.steps.length === 0}><div class="ai-workflow__canvas-empty"><p>No steps yet</p></div></Show></div>)
7
+ }
@@ -0,0 +1,8 @@
1
+ // @geenius-ai-workflow/solidjs-css β€” components/WorkflowRunPanel.tsx
2
+ import { Show, For } from 'solid-js'
3
+ import type { WorkflowRun } from '@geenius-ai-workflow/shared'
4
+ import { formatCost } from '@geenius-ai-workflow/shared'
5
+ const SI: Record<string, string> = { pending: '⏳', running: 'πŸ”„', completed: 'βœ…', failed: '❌', skipped: '⏭️', 'waiting-approval': 'πŸ‘€' }
6
+ export function WorkflowRunPanel(props: { run: WorkflowRun | null; isRunning: boolean; onCancel?: () => void }) {
7
+ return (<div class="ai-workflow__run-panel"><Show when={!props.run}><div class="ai-workflow__run-empty"><p>No active run.</p></div></Show><Show when={props.run}>{(r) => { const done = () => r().stepResults.filter(s => s.status === 'completed').length; const total = () => r().stepResults.length; const pct = () => total() > 0 ? Math.round((done() / total()) * 100) : 0; const cost = () => r().stepResults.reduce((s, x) => s + (x.costUsd ?? 0), 0); return (<><div class="ai-workflow__run-header"><h3 class="ai-workflow__run-title">{SI[r().status]} Run {r().status}</h3><Show when={props.isRunning && props.onCancel}><button class="ai-workflow__run-cancel" onClick={props.onCancel}>⏹ Cancel</button></Show></div><div class="ai-workflow__run-progress"><div class="ai-workflow__run-progress-bar"><div class="ai-workflow__run-progress-fill" style={{ width: `${pct()}%` }} /></div><span class="ai-workflow__run-progress-text">{done()}/{total()} ({pct()}%)</span></div><Show when={cost() > 0}><span class="ai-workflow__run-stat">πŸ’° {formatCost(cost())}</span></Show><Show when={r().error}><div class="ai-workflow__run-error">{r().error}</div></Show><ul class="ai-workflow__run-steps"><For each={r().stepResults}>{(sr) => <li class="ai-workflow__run-step-item" data-status={sr.status}><span>{SI[sr.status]}</span><span>{sr.stepName}</span><span>{sr.durationMs}ms</span></li>}</For></ul></>)}}</Show></div>)
8
+ }
@@ -0,0 +1,5 @@
1
+ // @geenius-ai-workflow/solidjs-css β€” components/WorkflowToolbar.tsx
2
+ import { Show } from 'solid-js'
3
+ export function WorkflowToolbar(props: { workflowName: string; isDirty: boolean; isRunning: boolean; canUndo: boolean; canRedo: boolean; onSave: () => void; onRun: () => void; onCancel?: () => void; onUndo: () => void; onRedo: () => void }) {
4
+ return (<div class="ai-workflow__toolbar" role="toolbar"><div class="ai-workflow__toolbar-left"><h2 class="ai-workflow__toolbar-title">{props.workflowName}</h2><Show when={props.isDirty}><span class="ai-workflow__toolbar-dirty">●</span></Show></div><div class="ai-workflow__toolbar-center"><button class="ai-workflow__toolbar-btn" onClick={props.onUndo} disabled={!props.canUndo}>β†Ά</button><button class="ai-workflow__toolbar-btn" onClick={props.onRedo} disabled={!props.canRedo}>β†·</button></div><div class="ai-workflow__toolbar-right"><button class="ai-workflow__toolbar-btn-secondary" onClick={props.onSave} disabled={!props.isDirty}>πŸ’Ύ Save</button><Show when={props.isRunning} fallback={<button class="ai-workflow__toolbar-btn-primary" onClick={props.onRun}>β–Ά Run</button>}><button class="ai-workflow__toolbar-btn-danger" onClick={props.onCancel}>⏹ Stop</button></Show></div></div>)
5
+ }
@@ -0,0 +1,9 @@
1
+ // @geenius-ai-workflow/solidjs-css β€” components/index.ts
2
+ export { WorkflowCanvas } from './WorkflowCanvas'
3
+ export { StepNode } from './StepNode'
4
+ export { StepConnector } from './StepConnector'
5
+ export { StepConfigPanel } from './StepConfigPanel'
6
+ export { WorkflowRunPanel } from './WorkflowRunPanel'
7
+ export { ApprovalModal } from './ApprovalModal'
8
+ export { WorkflowToolbar } from './WorkflowToolbar'
9
+ export { StepPalette } from './StepPalette'
@@ -0,0 +1,7 @@
1
+ // @geenius-ai-workflow/solidjs-css β€” src/index.ts
2
+ import './styles.css'
3
+ export type { WorkflowDefinition, WorkflowStepDef, WorkflowRun, StepResult } from '@geenius-ai-workflow/shared'
4
+ export { WorkflowEngine, WORKFLOW_TEMPLATES } from '@geenius-ai-workflow/shared'
5
+ export * from './primitives'
6
+ export * from './components'
7
+ export * from './pages'
@@ -0,0 +1,2 @@
1
+ // @geenius-ai-workflow/solidjs-css β€” pages/WorkflowBuilderPage.tsx
2
+ export { WorkflowBuilderPage } from '@geenius-ai-workflow/solidjs'
@@ -0,0 +1,7 @@
1
+ // @geenius-ai-workflow/solidjs-css β€” pages/WorkflowRunsPage.tsx
2
+ import { For, Show } from 'solid-js'
3
+ import type { WorkflowRun } from '@geenius-ai-workflow/shared'
4
+ const SI: Record<string, string> = { pending: '⏳', running: 'πŸ”„', completed: 'βœ…', failed: '❌', cancelled: 'β›”', paused: '⏸️' }
5
+ export function WorkflowRunsPage(props: { runs: WorkflowRun[]; onSelectRun?: (id: string) => void }) {
6
+ return (<div><div class="ai-workflow__runs-header"><h1 class="ai-workflow__runs-title">Workflow Runs</h1><span class="ai-workflow__runs-count">{props.runs.length} runs</span></div><Show when={props.runs.length > 0} fallback={<div class="ai-workflow__runs-empty"><p>No runs yet.</p></div>}><div role="list"><For each={props.runs}>{(run) => <div class="ai-workflow__run-card" role="listitem" onClick={() => props.onSelectRun?.(run.id)}><div class="ai-workflow__run-card-header"><span class="ai-workflow__run-card-status">{SI[run.status]} {run.status}</span><span class="ai-workflow__run-card-id">{run.id.slice(0, 8)}…</span></div><div class="ai-workflow__run-card-meta"><span>{run.stepResults.filter(s => s.status === 'completed').length}/{run.stepResults.length} steps</span></div><Show when={run.error}><p class="ai-workflow__run-card-error">{run.error}</p></Show></div>}</For></div></Show></div>)
7
+ }
@@ -0,0 +1,3 @@
1
+ // @geenius-ai-workflow/solidjs-css β€” pages/index.ts
2
+ export { WorkflowBuilderPage } from './WorkflowBuilderPage'
3
+ export { WorkflowRunsPage } from './WorkflowRunsPage'
@@ -0,0 +1,28 @@
1
+ // @geenius-ai-workflow/solidjs β€” src/primitives/createWorkflow.ts
2
+ import { createSignal } from 'solid-js'
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 CreateWorkflowOptions extends WorkflowEngineOptions { }
8
+
9
+ export function createWorkflow(options: CreateWorkflowOptions) {
10
+ const [run, setRun] = createSignal<WorkflowRun | null>(null)
11
+ const [isRunning, setIsRunning] = createSignal(false)
12
+ const [error, setError] = createSignal<Error | null>(null)
13
+ const [stepResults, setStepResults] = createSignal<StepResult[]>([])
14
+
15
+ const engine = new WorkflowEngine({
16
+ ...options,
17
+ onStepComplete: (result) => { setStepResults(prev => [...prev, result]); options.onStepComplete?.(result) },
18
+ })
19
+
20
+ const execute = async (definition: WorkflowDefinition, input?: Record<string, unknown>) => {
21
+ setIsRunning(true); setError(null); setStepResults([])
22
+ try { const res = await engine.execute(definition, input); setRun(res); return res }
23
+ catch (err) { const e = err instanceof Error ? err : new Error(String(err)); setError(e); throw e }
24
+ finally { setIsRunning(false) }
25
+ }
26
+
27
+ return { execute, cancel: () => engine.cancel(), run, isRunning, error, stepResults, reset: () => { setRun(null); setError(null); setStepResults([]) } }
28
+ }
@@ -0,0 +1,56 @@
1
+ // @geenius-ai-workflow/solidjs β€” src/primitives/createWorkflowBuilder.ts
2
+ import { createSignal } from 'solid-js'
3
+ import type { WorkflowDefinition, WorkflowStepDef, StepConnection, WorkflowBuilderState } from '@geenius-ai-workflow/shared'
4
+
5
+ const emptyDef = (): WorkflowDefinition => ({
6
+ id: crypto.randomUUID?.() ?? String(Date.now()), name: 'New Workflow', version: 1, status: 'draft',
7
+ steps: [], connections: [], createdBy: '', createdAt: Date.now(), updatedAt: Date.now(),
8
+ })
9
+
10
+ export function createWorkflowBuilder(initial?: Partial<WorkflowDefinition>) {
11
+ const [state, setState] = createSignal<WorkflowBuilderState>({
12
+ definition: { ...emptyDef(), ...initial }, selectedStepId: null, isDirty: false, undoStack: [], redoStack: [],
13
+ })
14
+
15
+ const pushUndo = () => setState(prev => ({ ...prev, undoStack: [...prev.undoStack.slice(-20), prev.definition], redoStack: [] }))
16
+
17
+ const addStep = (step: WorkflowStepDef) => {
18
+ pushUndo(); setState(prev => ({ ...prev, isDirty: true, definition: { ...prev.definition, steps: [...prev.definition.steps, step], updatedAt: Date.now() } }))
19
+ }
20
+
21
+ const removeStep = (stepId: string) => {
22
+ pushUndo(); setState(prev => ({
23
+ ...prev, isDirty: true,
24
+ definition: { ...prev.definition, steps: prev.definition.steps.filter(s => s.id !== stepId), connections: prev.definition.connections.filter(c => c.fromStepId !== stepId && c.toStepId !== stepId), updatedAt: Date.now() },
25
+ selectedStepId: prev.selectedStepId === stepId ? null : prev.selectedStepId,
26
+ }))
27
+ }
28
+
29
+ const updateStep = (stepId: string, updates: Partial<WorkflowStepDef>) => {
30
+ pushUndo(); setState(prev => ({ ...prev, isDirty: true, definition: { ...prev.definition, steps: prev.definition.steps.map(s => s.id === stepId ? { ...s, ...updates } : s), updatedAt: Date.now() } }))
31
+ }
32
+
33
+ const addConnection = (conn: StepConnection) => {
34
+ pushUndo(); setState(prev => ({ ...prev, isDirty: true, definition: { ...prev.definition, connections: [...prev.definition.connections, conn], updatedAt: Date.now() } }))
35
+ }
36
+
37
+ const removeConnection = (fromStepId: string, toStepId: string) => {
38
+ pushUndo(); setState(prev => ({ ...prev, isDirty: true, definition: { ...prev.definition, connections: prev.definition.connections.filter(c => !(c.fromStepId === fromStepId && c.toStepId === toStepId)), updatedAt: Date.now() } }))
39
+ }
40
+
41
+ const selectStep = (stepId: string | null) => setState(prev => ({ ...prev, selectedStepId: stepId }))
42
+
43
+ const undo = () => setState(prev => {
44
+ if (prev.undoStack.length === 0) return prev
45
+ return { ...prev, definition: prev.undoStack[prev.undoStack.length - 1], undoStack: prev.undoStack.slice(0, -1), redoStack: [prev.definition, ...prev.redoStack] }
46
+ })
47
+
48
+ const redo = () => setState(prev => {
49
+ if (prev.redoStack.length === 0) return prev
50
+ return { ...prev, definition: prev.redoStack[0], undoStack: [...prev.undoStack, prev.definition], redoStack: prev.redoStack.slice(1) }
51
+ })
52
+
53
+ const setDefinition = (def: WorkflowDefinition) => setState({ definition: def, selectedStepId: null, isDirty: false, undoStack: [], redoStack: [] })
54
+
55
+ return { state, addStep, removeStep, updateStep, addConnection, removeConnection, selectStep, undo, redo, setDefinition }
56
+ }
@@ -0,0 +1 @@
1
+ export * from '@geenius-ai-workflow/solidjs';