@assistkick/create 1.7.0 → 1.8.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 (200) hide show
  1. package/dist/bin/create.js +0 -0
  2. package/package.json +9 -7
  3. package/templates/assistkick-product-system/.env.example +1 -0
  4. package/templates/assistkick-product-system/local.db +0 -0
  5. package/templates/assistkick-product-system/package.json +4 -2
  6. package/templates/assistkick-product-system/packages/backend/package.json +2 -0
  7. package/templates/assistkick-product-system/packages/backend/src/routes/agents.ts +165 -0
  8. package/templates/assistkick-product-system/packages/backend/src/routes/files.test.ts +358 -0
  9. package/templates/assistkick-product-system/packages/backend/src/routes/files.ts +356 -0
  10. package/templates/assistkick-product-system/packages/backend/src/routes/git.ts +96 -1
  11. package/templates/assistkick-product-system/packages/backend/src/routes/graph.ts +1 -0
  12. package/templates/assistkick-product-system/packages/backend/src/routes/kanban.ts +43 -4
  13. package/templates/assistkick-product-system/packages/backend/src/routes/pipeline.ts +200 -84
  14. package/templates/assistkick-product-system/packages/backend/src/routes/projects.ts +6 -3
  15. package/templates/assistkick-product-system/packages/backend/src/routes/terminal.ts +53 -17
  16. package/templates/assistkick-product-system/packages/backend/src/routes/video.ts +218 -0
  17. package/templates/assistkick-product-system/packages/backend/src/routes/workflow_groups.ts +119 -0
  18. package/templates/assistkick-product-system/packages/backend/src/routes/workflows.ts +154 -0
  19. package/templates/assistkick-product-system/packages/backend/src/server.ts +81 -9
  20. package/templates/assistkick-product-system/packages/backend/src/services/agent_service.test.ts +489 -0
  21. package/templates/assistkick-product-system/packages/backend/src/services/agent_service.ts +416 -0
  22. package/templates/assistkick-product-system/packages/backend/src/services/bundle_service.test.ts +189 -0
  23. package/templates/assistkick-product-system/packages/backend/src/services/bundle_service.ts +182 -0
  24. package/templates/assistkick-product-system/packages/backend/src/services/init.ts +28 -78
  25. package/templates/assistkick-product-system/packages/backend/src/services/project_service.test.ts +16 -0
  26. package/templates/assistkick-product-system/packages/backend/src/services/project_service.ts +73 -2
  27. package/templates/assistkick-product-system/packages/backend/src/services/project_workspace_service.test.ts +4 -4
  28. package/templates/assistkick-product-system/packages/backend/src/services/project_workspace_service.ts +87 -11
  29. package/templates/assistkick-product-system/packages/backend/src/services/pty_session_manager.test.ts +210 -69
  30. package/templates/assistkick-product-system/packages/backend/src/services/pty_session_manager.ts +210 -215
  31. package/templates/assistkick-product-system/packages/backend/src/services/ssh_key_service.test.ts +162 -0
  32. package/templates/assistkick-product-system/packages/backend/src/services/ssh_key_service.ts +148 -0
  33. package/templates/assistkick-product-system/packages/backend/src/services/terminal_ws_handler.ts +11 -5
  34. package/templates/assistkick-product-system/packages/backend/src/services/tts_service.test.ts +64 -0
  35. package/templates/assistkick-product-system/packages/backend/src/services/tts_service.ts +134 -0
  36. package/templates/assistkick-product-system/packages/backend/src/services/video_render_service.test.ts +256 -0
  37. package/templates/assistkick-product-system/packages/backend/src/services/video_render_service.ts +258 -0
  38. package/templates/assistkick-product-system/packages/backend/src/services/workflow_group_service.ts +106 -0
  39. package/templates/assistkick-product-system/packages/backend/src/services/workflow_service.test.ts +275 -0
  40. package/templates/assistkick-product-system/packages/backend/src/services/workflow_service.ts +222 -0
  41. package/templates/assistkick-product-system/packages/frontend/package-lock.json +3455 -0
  42. package/templates/assistkick-product-system/packages/frontend/package.json +6 -0
  43. package/templates/assistkick-product-system/packages/frontend/src/App.tsx +8 -0
  44. package/templates/assistkick-product-system/packages/frontend/src/api/client.ts +456 -16
  45. package/templates/assistkick-product-system/packages/frontend/src/api/client_files.test.ts +172 -0
  46. package/templates/assistkick-product-system/packages/frontend/src/api/client_video.test.ts +238 -0
  47. package/templates/assistkick-product-system/packages/frontend/src/components/AgentsView.tsx +307 -0
  48. package/templates/assistkick-product-system/packages/frontend/src/components/CoherenceView.tsx +82 -66
  49. package/templates/assistkick-product-system/packages/frontend/src/components/CompositionPlaceholder.tsx +97 -0
  50. package/templates/assistkick-product-system/packages/frontend/src/components/DesignSystemView.tsx +20 -0
  51. package/templates/assistkick-product-system/packages/frontend/src/components/EditorTabBar.tsx +57 -0
  52. package/templates/assistkick-product-system/packages/frontend/src/components/FileTree.tsx +313 -0
  53. package/templates/assistkick-product-system/packages/frontend/src/components/FileTreeContextMenu.tsx +61 -0
  54. package/templates/assistkick-product-system/packages/frontend/src/components/FileTreeInlineInput.tsx +73 -0
  55. package/templates/assistkick-product-system/packages/frontend/src/components/FilesView.tsx +404 -0
  56. package/templates/assistkick-product-system/packages/frontend/src/components/GitRepoModal.tsx +187 -56
  57. package/templates/assistkick-product-system/packages/frontend/src/components/GraphLegend.tsx +71 -73
  58. package/templates/assistkick-product-system/packages/frontend/src/components/GraphSettings.tsx +8 -8
  59. package/templates/assistkick-product-system/packages/frontend/src/components/GraphView.tsx +1 -1
  60. package/templates/assistkick-product-system/packages/frontend/src/components/InviteUserDialog.tsx +15 -11
  61. package/templates/assistkick-product-system/packages/frontend/src/components/KanbanView.tsx +202 -171
  62. package/templates/assistkick-product-system/packages/frontend/src/components/LoginPage.tsx +14 -14
  63. package/templates/assistkick-product-system/packages/frontend/src/components/ProjectSelector.tsx +54 -33
  64. package/templates/assistkick-product-system/packages/frontend/src/components/QaIssueSheet.tsx +32 -49
  65. package/templates/assistkick-product-system/packages/frontend/src/components/SidePanel.tsx +43 -48
  66. package/templates/assistkick-product-system/packages/frontend/src/components/TerminalView.tsx +121 -52
  67. package/templates/assistkick-product-system/packages/frontend/src/components/Toolbar.tsx +20 -14
  68. package/templates/assistkick-product-system/packages/frontend/src/components/UsersView.tsx +52 -52
  69. package/templates/assistkick-product-system/packages/frontend/src/components/VideoGallery.tsx +313 -0
  70. package/templates/assistkick-product-system/packages/frontend/src/components/VideographyView.tsx +250 -0
  71. package/templates/assistkick-product-system/packages/frontend/src/components/WorkflowsView.tsx +474 -0
  72. package/templates/assistkick-product-system/packages/frontend/src/components/ds/AccentBorderList.tsx +53 -0
  73. package/templates/assistkick-product-system/packages/frontend/src/components/ds/Button.tsx +87 -0
  74. package/templates/assistkick-product-system/packages/frontend/src/components/ds/ButtonGroup.tsx +29 -0
  75. package/templates/assistkick-product-system/packages/frontend/src/components/ds/ButtonShowcase.tsx +221 -0
  76. package/templates/assistkick-product-system/packages/frontend/src/components/ds/CardGlass.tsx +141 -0
  77. package/templates/assistkick-product-system/packages/frontend/src/components/ds/CompletionRing.tsx +30 -0
  78. package/templates/assistkick-product-system/packages/frontend/src/components/ds/ContentCard.tsx +34 -0
  79. package/templates/assistkick-product-system/packages/frontend/src/components/ds/IconButton.tsx +74 -0
  80. package/templates/assistkick-product-system/packages/frontend/src/components/ds/KanbanCard.tsx +103 -87
  81. package/templates/assistkick-product-system/packages/frontend/src/components/ds/KanbanCardShowcase.tsx +9 -188
  82. package/templates/assistkick-product-system/packages/frontend/src/components/ds/Kbd.tsx +11 -0
  83. package/templates/assistkick-product-system/packages/frontend/src/components/ds/KindBadge.tsx +21 -0
  84. package/templates/assistkick-product-system/packages/frontend/src/components/ds/NavBarSidekick.tsx +81 -37
  85. package/templates/assistkick-product-system/packages/frontend/src/components/ds/SidePanelShowcase.tsx +370 -0
  86. package/templates/assistkick-product-system/packages/frontend/src/components/ds/SideSheet.tsx +64 -0
  87. package/templates/assistkick-product-system/packages/frontend/src/components/ds/StatusDot.tsx +18 -0
  88. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/CheckCardPositionNode.tsx +36 -0
  89. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/CheckCycleCountNode.tsx +60 -0
  90. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/EndNode.tsx +42 -0
  91. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/GroupNode.tsx +189 -0
  92. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/NodePalette.tsx +123 -0
  93. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/RunAgentNode.tsx +51 -0
  94. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/SetCardMetadataNode.tsx +53 -0
  95. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/StartNode.tsx +18 -0
  96. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/TransitionCardNode.tsx +59 -0
  97. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/WorkflowCanvas.tsx +335 -0
  98. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/WorkflowMonitorModal.tsx +634 -0
  99. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/autoLayout.ts +103 -0
  100. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/edgeColors.ts +35 -0
  101. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/monitor_nodes.tsx +208 -0
  102. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/workflow_types.test.ts +119 -0
  103. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/workflow_types.ts +107 -0
  104. package/templates/assistkick-product-system/packages/frontend/src/constants/graph.ts +13 -11
  105. package/templates/assistkick-product-system/packages/frontend/src/hooks/useAutoSave.ts +75 -0
  106. package/templates/assistkick-product-system/packages/frontend/src/hooks/useToast.tsx +16 -3
  107. package/templates/assistkick-product-system/packages/frontend/src/pages/accept_invitation_page.tsx +30 -27
  108. package/templates/assistkick-product-system/packages/frontend/src/pages/forgot_password_page.tsx +18 -15
  109. package/templates/assistkick-product-system/packages/frontend/src/pages/register_page.tsx +21 -18
  110. package/templates/assistkick-product-system/packages/frontend/src/pages/reset_password_page.tsx +28 -25
  111. package/templates/assistkick-product-system/packages/frontend/src/routes/AgentsRoute.tsx +6 -0
  112. package/templates/assistkick-product-system/packages/frontend/src/routes/CoherenceRoute.tsx +1 -1
  113. package/templates/assistkick-product-system/packages/frontend/src/routes/DashboardLayout.tsx +2 -2
  114. package/templates/assistkick-product-system/packages/frontend/src/routes/FilesRoute.tsx +13 -0
  115. package/templates/assistkick-product-system/packages/frontend/src/routes/GraphRoute.tsx +2 -2
  116. package/templates/assistkick-product-system/packages/frontend/src/routes/VideographyRoute.tsx +13 -0
  117. package/templates/assistkick-product-system/packages/frontend/src/routes/WorkflowsRoute.tsx +6 -0
  118. package/templates/assistkick-product-system/packages/frontend/src/stores/useProjectStore.ts +6 -3
  119. package/templates/assistkick-product-system/packages/frontend/src/stores/useSidePanelStore.ts +4 -4
  120. package/templates/assistkick-product-system/packages/frontend/src/styles/index.css +275 -3535
  121. package/templates/assistkick-product-system/packages/frontend/src/utils/auto_save_service.test.ts +167 -0
  122. package/templates/assistkick-product-system/packages/frontend/src/utils/auto_save_service.ts +101 -0
  123. package/templates/assistkick-product-system/packages/frontend/src/utils/composition_matcher.test.ts +42 -0
  124. package/templates/assistkick-product-system/packages/frontend/src/utils/composition_matcher.ts +17 -0
  125. package/templates/assistkick-product-system/packages/frontend/src/utils/file_utils.test.ts +145 -0
  126. package/templates/assistkick-product-system/packages/frontend/src/utils/file_utils.ts +42 -0
  127. package/templates/assistkick-product-system/packages/frontend/src/utils/task_status.test.ts +4 -10
  128. package/templates/assistkick-product-system/packages/frontend/src/utils/task_status.ts +19 -1
  129. package/templates/assistkick-product-system/packages/frontend/vite.config.ts +5 -0
  130. package/templates/assistkick-product-system/packages/shared/db/local.db +0 -0
  131. package/templates/assistkick-product-system/packages/shared/db/migrations/0004_tidy_matthew_murdock.sql +9 -0
  132. package/templates/assistkick-product-system/packages/shared/db/migrations/0005_mysterious_falcon.sql +692 -0
  133. package/templates/assistkick-product-system/packages/shared/db/migrations/0006_next_venom.sql +9 -0
  134. package/templates/assistkick-product-system/packages/shared/db/migrations/0007_deep_barracuda.sql +39 -0
  135. package/templates/assistkick-product-system/packages/shared/db/migrations/0008_puzzling_hannibal_king.sql +1 -0
  136. package/templates/assistkick-product-system/packages/shared/db/migrations/0009_amused_beast.sql +8 -0
  137. package/templates/assistkick-product-system/packages/shared/db/migrations/0010_spotty_moira_mactaggert.sql +9 -0
  138. package/templates/assistkick-product-system/packages/shared/db/migrations/0011_goofy_snowbird.sql +3 -0
  139. package/templates/assistkick-product-system/packages/shared/db/migrations/0011_supreme_doctor_octopus.sql +3 -0
  140. package/templates/assistkick-product-system/packages/shared/db/migrations/0013_reflective_prowler.sql +15 -0
  141. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0004_snapshot.json +921 -0
  142. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0005_snapshot.json +1042 -0
  143. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0006_snapshot.json +1101 -0
  144. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0007_snapshot.json +1336 -0
  145. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0008_snapshot.json +1275 -0
  146. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0009_snapshot.json +1327 -0
  147. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0010_snapshot.json +1393 -0
  148. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0011_snapshot.json +1436 -0
  149. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0013_snapshot.json +1538 -0
  150. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/_journal.json +70 -0
  151. package/templates/assistkick-product-system/packages/shared/db/schema.ts +113 -0
  152. package/templates/assistkick-product-system/packages/shared/lib/claude-service.ts +32 -7
  153. package/templates/assistkick-product-system/packages/shared/lib/constants.ts +9 -0
  154. package/templates/assistkick-product-system/packages/shared/lib/git_workflow.ts +12 -4
  155. package/templates/assistkick-product-system/packages/shared/lib/graph.ts +5 -0
  156. package/templates/assistkick-product-system/packages/shared/lib/workflow_engine.test.ts +1753 -0
  157. package/templates/assistkick-product-system/packages/shared/lib/workflow_engine.ts +1281 -0
  158. package/templates/assistkick-product-system/packages/shared/lib/workflow_orchestrator.ts +211 -0
  159. package/templates/assistkick-product-system/packages/shared/tools/add_node.test.ts +43 -0
  160. package/templates/assistkick-product-system/packages/shared/tools/add_node.ts +13 -2
  161. package/templates/assistkick-product-system/packages/shared/tools/get_kanban.ts +1 -1
  162. package/templates/assistkick-product-system/packages/shared/tools/migrate_epics.test.ts +226 -0
  163. package/templates/assistkick-product-system/packages/shared/tools/migrate_epics.ts +251 -0
  164. package/templates/assistkick-product-system/packages/shared/tools/update_node.ts +2 -2
  165. package/templates/assistkick-product-system/packages/shared/utils/hello_workflow.test.ts +10 -0
  166. package/templates/assistkick-product-system/packages/shared/utils/hello_workflow.ts +6 -0
  167. package/templates/assistkick-product-system/packages/video/Root.tsx +85 -0
  168. package/templates/assistkick-product-system/packages/video/components/email_scene.tsx +231 -0
  169. package/templates/assistkick-product-system/packages/video/components/outro_scene.tsx +153 -0
  170. package/templates/assistkick-product-system/packages/video/components/part_divider.tsx +90 -0
  171. package/templates/assistkick-product-system/packages/video/components/scene.tsx +226 -0
  172. package/templates/assistkick-product-system/packages/video/components/theme.ts +22 -0
  173. package/templates/assistkick-product-system/packages/video/components/title_scene.tsx +169 -0
  174. package/templates/assistkick-product-system/packages/video/components/video_split_layout.tsx +84 -0
  175. package/templates/assistkick-product-system/packages/video/compositions/.gitkeep +0 -0
  176. package/templates/assistkick-product-system/packages/video/index.ts +4 -0
  177. package/templates/assistkick-product-system/packages/video/package.json +28 -0
  178. package/templates/assistkick-product-system/packages/video/remotion.config.ts +11 -0
  179. package/templates/assistkick-product-system/packages/video/scripts/process_script.test.ts +326 -0
  180. package/templates/assistkick-product-system/packages/video/scripts/process_script.ts +630 -0
  181. package/templates/assistkick-product-system/packages/video/style.css +1 -0
  182. package/templates/assistkick-product-system/packages/video/tsconfig.json +18 -0
  183. package/templates/assistkick-product-system/tests/graph_legend.test.ts +2 -1
  184. package/templates/assistkick-product-system/tests/video_render_service.test.ts +179 -0
  185. package/templates/assistkick-product-system/tests/web_terminal.test.ts +219 -455
  186. package/templates/assistkick-product-system/tests/workflow_integration.test.ts +341 -0
  187. package/templates/skills/assistkick-developer/SKILL.md +3 -0
  188. package/templates/skills/assistkick-developer/references/react_development_guidelines.md +225 -0
  189. package/templates/skills/product-system/graph.json +1890 -0
  190. package/templates/skills/product-system/kanban.json +304 -0
  191. package/templates/skills/product-system/nodes/comp_001.md +56 -0
  192. package/templates/skills/product-system/nodes/comp_002.md +57 -0
  193. package/templates/skills/product-system/nodes/data_001.md +51 -0
  194. package/templates/skills/product-system/nodes/data_002.md +40 -0
  195. package/templates/skills/product-system/nodes/data_004.md +38 -0
  196. package/templates/skills/product-system/nodes/dec_001.md +34 -0
  197. package/templates/skills/product-system/nodes/dec_016.md +32 -0
  198. package/templates/skills/product-system/nodes/feat_008.md +30 -0
  199. package/templates/skills/video-composition-agent/SKILL.md +232 -0
  200. package/templates/skills/video-script-writer/SKILL.md +136 -0
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Workflow group routes — CRUD endpoints for reusable workflow groups.
3
+ * GET /api/workflow-groups — list groups (optional projectId query param)
4
+ * GET /api/workflow-groups/:id — get single group
5
+ * POST /api/workflow-groups — create group
6
+ * PUT /api/workflow-groups/:id — update group
7
+ * DELETE /api/workflow-groups/:id — delete group
8
+ */
9
+
10
+ import { Router } from 'express';
11
+ import type { WorkflowGroupService } from '../services/workflow_group_service.js';
12
+
13
+ interface WorkflowGroupRoutesDeps {
14
+ workflowGroupService: WorkflowGroupService;
15
+ log: (tag: string, ...args: any[]) => void;
16
+ }
17
+
18
+ export const createWorkflowGroupRoutes = ({ workflowGroupService, log }: WorkflowGroupRoutesDeps): Router => {
19
+ const router: Router = Router();
20
+
21
+ // GET /api/workflow-groups?projectId=...
22
+ router.get('/', async (req, res) => {
23
+ const projectId = req.query.projectId as string | undefined;
24
+ log('WORKFLOW_GROUPS', `GET /api/workflow-groups projectId=${projectId || 'none'}`);
25
+
26
+ try {
27
+ const groups = await workflowGroupService.list(projectId);
28
+ res.json({ groups });
29
+ } catch (err: any) {
30
+ log('WORKFLOW_GROUPS', `List groups failed: ${err.message}`);
31
+ res.status(500).json({ error: 'Failed to list workflow groups' });
32
+ }
33
+ });
34
+
35
+ // GET /api/workflow-groups/:id
36
+ router.get('/:id', async (req, res) => {
37
+ const { id } = req.params;
38
+ log('WORKFLOW_GROUPS', `GET /api/workflow-groups/${id}`);
39
+
40
+ try {
41
+ const group = await workflowGroupService.getById(id);
42
+ if (!group) {
43
+ res.status(404).json({ error: 'Workflow group not found' });
44
+ return;
45
+ }
46
+ res.json({ group });
47
+ } catch (err: any) {
48
+ log('WORKFLOW_GROUPS', `Get group failed: ${err.message}`);
49
+ res.status(500).json({ error: 'Failed to get workflow group' });
50
+ }
51
+ });
52
+
53
+ // POST /api/workflow-groups
54
+ router.post('/', async (req, res) => {
55
+ const { name, projectId, graphData } = req.body;
56
+ log('WORKFLOW_GROUPS', `POST /api/workflow-groups name="${name}"`);
57
+
58
+ if (!name || typeof name !== 'string' || !name.trim()) {
59
+ res.status(400).json({ error: 'Group name is required' });
60
+ return;
61
+ }
62
+
63
+ if (!graphData || typeof graphData !== 'string') {
64
+ res.status(400).json({ error: 'graphData is required (JSON string)' });
65
+ return;
66
+ }
67
+
68
+ try {
69
+ const group = await workflowGroupService.create({
70
+ name: name.trim(),
71
+ projectId: projectId || null,
72
+ graphData,
73
+ });
74
+ res.status(201).json({ group });
75
+ } catch (err: any) {
76
+ log('WORKFLOW_GROUPS', `Create group failed: ${err.message}`);
77
+ res.status(500).json({ error: 'Failed to create workflow group' });
78
+ }
79
+ });
80
+
81
+ // PUT /api/workflow-groups/:id
82
+ router.put('/:id', async (req, res) => {
83
+ const { id } = req.params;
84
+ const { name, graphData } = req.body;
85
+ log('WORKFLOW_GROUPS', `PUT /api/workflow-groups/${id}`);
86
+
87
+ try {
88
+ const group = await workflowGroupService.update(id, { name, graphData });
89
+ res.json({ group });
90
+ } catch (err: any) {
91
+ log('WORKFLOW_GROUPS', `Update group failed: ${err.message}`);
92
+ if (err.message === 'Workflow group not found') {
93
+ res.status(404).json({ error: err.message });
94
+ return;
95
+ }
96
+ res.status(500).json({ error: 'Failed to update workflow group' });
97
+ }
98
+ });
99
+
100
+ // DELETE /api/workflow-groups/:id
101
+ router.delete('/:id', async (req, res) => {
102
+ const { id } = req.params;
103
+ log('WORKFLOW_GROUPS', `DELETE /api/workflow-groups/${id}`);
104
+
105
+ try {
106
+ await workflowGroupService.delete(id);
107
+ res.json({ success: true });
108
+ } catch (err: any) {
109
+ log('WORKFLOW_GROUPS', `Delete group failed: ${err.message}`);
110
+ if (err.message === 'Workflow group not found') {
111
+ res.status(404).json({ error: err.message });
112
+ return;
113
+ }
114
+ res.status(500).json({ error: 'Failed to delete workflow group' });
115
+ }
116
+ });
117
+
118
+ return router;
119
+ };
@@ -0,0 +1,154 @@
1
+ /**
2
+ * Workflow routes — CRUD endpoints for workflow management.
3
+ * GET /api/workflows — list workflows (optional projectId query param)
4
+ * GET /api/workflows/:id — get single workflow with graph_data
5
+ * POST /api/workflows — create workflow
6
+ * PUT /api/workflows/:id — update workflow
7
+ * DELETE /api/workflows/:id — delete workflow (400 if active executions)
8
+ * POST /api/workflows/:id/set-default — mark workflow as default for its scope
9
+ */
10
+
11
+ import { Router } from 'express';
12
+ import type { WorkflowService } from '../services/workflow_service.js';
13
+
14
+ interface WorkflowRoutesDeps {
15
+ workflowService: WorkflowService;
16
+ log: (tag: string, ...args: any[]) => void;
17
+ }
18
+
19
+ export const createWorkflowRoutes = ({ workflowService, log }: WorkflowRoutesDeps): Router => {
20
+ const router: Router = Router();
21
+
22
+ // GET /api/workflows?projectId=...
23
+ router.get('/', async (req, res) => {
24
+ const projectId = req.query.projectId as string | undefined;
25
+ log('WORKFLOWS', `GET /api/workflows projectId=${projectId || 'none'}`);
26
+
27
+ try {
28
+ const workflowList = await workflowService.list(projectId);
29
+ res.json({ workflows: workflowList });
30
+ } catch (err: any) {
31
+ log('WORKFLOWS', `List workflows failed: ${err.message}`);
32
+ res.status(500).json({ error: 'Failed to list workflows' });
33
+ }
34
+ });
35
+
36
+ // GET /api/workflows/:id
37
+ router.get('/:id', async (req, res) => {
38
+ const { id } = req.params;
39
+ log('WORKFLOWS', `GET /api/workflows/${id}`);
40
+
41
+ try {
42
+ const workflow = await workflowService.getById(id);
43
+ if (!workflow) {
44
+ res.status(404).json({ error: 'Workflow not found' });
45
+ return;
46
+ }
47
+ res.json({ workflow });
48
+ } catch (err: any) {
49
+ log('WORKFLOWS', `Get workflow failed: ${err.message}`);
50
+ res.status(500).json({ error: 'Failed to get workflow' });
51
+ }
52
+ });
53
+
54
+ // POST /api/workflows
55
+ router.post('/', async (req, res) => {
56
+ const { name, description, projectId, featureType, graphData } = req.body;
57
+ log('WORKFLOWS', `POST /api/workflows name="${name}"`);
58
+
59
+ if (!name || typeof name !== 'string' || !name.trim()) {
60
+ res.status(400).json({ error: 'Workflow name is required' });
61
+ return;
62
+ }
63
+
64
+ if (!graphData || typeof graphData !== 'string') {
65
+ res.status(400).json({ error: 'graphData is required (JSON string)' });
66
+ return;
67
+ }
68
+
69
+ try {
70
+ const workflow = await workflowService.create({
71
+ name: name.trim(),
72
+ description: description || null,
73
+ projectId: projectId || null,
74
+ featureType: featureType || null,
75
+ graphData,
76
+ });
77
+ res.status(201).json({ workflow });
78
+ } catch (err: any) {
79
+ log('WORKFLOWS', `Create workflow failed: ${err.message}`);
80
+ res.status(500).json({ error: 'Failed to create workflow' });
81
+ }
82
+ });
83
+
84
+ // PUT /api/workflows/:id
85
+ router.put('/:id', async (req, res) => {
86
+ const { id } = req.params;
87
+ const { name, description, featureType, graphData } = req.body;
88
+ log('WORKFLOWS', `PUT /api/workflows/${id}`);
89
+
90
+ if (name !== undefined && (typeof name !== 'string' || !name.trim())) {
91
+ res.status(400).json({ error: 'Workflow name must be a non-empty string' });
92
+ return;
93
+ }
94
+
95
+ try {
96
+ const workflow = await workflowService.update(id, {
97
+ name: name?.trim(),
98
+ description,
99
+ featureType,
100
+ graphData,
101
+ });
102
+ res.json({ workflow });
103
+ } catch (err: any) {
104
+ log('WORKFLOWS', `Update workflow failed: ${err.message}`);
105
+ if (err.message === 'Workflow not found') {
106
+ res.status(404).json({ error: err.message });
107
+ return;
108
+ }
109
+ res.status(500).json({ error: 'Failed to update workflow' });
110
+ }
111
+ });
112
+
113
+ // DELETE /api/workflows/:id
114
+ router.delete('/:id', async (req, res) => {
115
+ const { id } = req.params;
116
+ log('WORKFLOWS', `DELETE /api/workflows/${id}`);
117
+
118
+ try {
119
+ await workflowService.delete(id);
120
+ res.json({ success: true });
121
+ } catch (err: any) {
122
+ log('WORKFLOWS', `Delete workflow failed: ${err.message}`);
123
+ if (err.message === 'Workflow not found') {
124
+ res.status(404).json({ error: err.message });
125
+ return;
126
+ }
127
+ if (err.message === 'Cannot delete a workflow with active executions') {
128
+ res.status(400).json({ error: err.message });
129
+ return;
130
+ }
131
+ res.status(500).json({ error: 'Failed to delete workflow' });
132
+ }
133
+ });
134
+
135
+ // POST /api/workflows/:id/set-default
136
+ router.post('/:id/set-default', async (req, res) => {
137
+ const { id } = req.params;
138
+ log('WORKFLOWS', `POST /api/workflows/${id}/set-default`);
139
+
140
+ try {
141
+ const workflow = await workflowService.setDefault(id);
142
+ res.json({ workflow });
143
+ } catch (err: any) {
144
+ log('WORKFLOWS', `Set default workflow failed: ${err.message}`);
145
+ if (err.message === 'Workflow not found') {
146
+ res.status(404).json({ error: err.message });
147
+ return;
148
+ }
149
+ res.status(500).json({ error: 'Failed to set default workflow' });
150
+ }
151
+ });
152
+
153
+ return router;
154
+ };
@@ -16,7 +16,7 @@ import { fileURLToPath } from 'node:url';
16
16
  import { existsSync } from 'node:fs';
17
17
  import { WebSocketServer } from 'ws';
18
18
  import * as pty from 'node-pty';
19
- import { initServices, log, githubAppService, workspaceService } from './services/init.js';
19
+ import { initServices, log, githubAppService, sshKeyService, workspaceService, workflowEngine, orchestrator, workflowService as initWorkflowService, workflowGroupService as initWorkflowGroupService } from './services/init.js';
20
20
  import { AuthService } from './services/auth_service.js';
21
21
  import { EmailService } from './services/email_service.js';
22
22
  import { PasswordResetService } from './services/password_reset_service.js';
@@ -33,9 +33,18 @@ import { createTerminalRoutes } from './routes/terminal.js';
33
33
  import { getDb } from '@assistkick/shared/lib/db.js';
34
34
  import graphRoutes from './routes/graph.js';
35
35
  import kanbanRoutes from './routes/kanban.js';
36
- import pipelineRoutes from './routes/pipeline.js';
36
+ import { createWorkflowExecutionRoutes } from './routes/pipeline.js';
37
37
  import coherenceRoutes from './routes/coherence.js';
38
38
  import { createGitRoutes } from './routes/git.js';
39
+ import { createFileRoutes } from './routes/files.js';
40
+ import { AgentService } from './services/agent_service.js';
41
+ import { createAgentRoutes } from './routes/agents.js';
42
+ import { createWorkflowRoutes } from './routes/workflows.js';
43
+ import { createWorkflowGroupRoutes } from './routes/workflow_groups.js';
44
+ import { TtsService } from './services/tts_service.js';
45
+ import { BundleService } from './services/bundle_service.js';
46
+ import { VideoRenderService } from './services/video_render_service.js';
47
+ import { createVideoRoutes } from './routes/video.js';
39
48
 
40
49
  const __dirname = dirname(fileURLToPath(import.meta.url));
41
50
  const DEFAULT_PORT = parseInt(process.env.PORT || '3000', 10);
@@ -70,8 +79,8 @@ app.use((req, res, next) => {
70
79
  const start = Date.now();
71
80
  res.on('finish', () => {
72
81
  const duration = Date.now() - start;
73
- // Skip noisy pipeline and orchestrator status polls
74
- if (req.originalUrl.endsWith('/pipeline') || req.originalUrl.endsWith('/orchestrator-status')) return;
82
+ // Skip noisy workflow-status and orchestrator status polls
83
+ if (req.originalUrl.endsWith('/workflow-status') || req.originalUrl.endsWith('/orchestrator-status')) return;
75
84
  log('HTTP', `${req.method} ${req.originalUrl} ${res.statusCode} ${duration}ms`);
76
85
  });
77
86
  next();
@@ -104,28 +113,91 @@ const projectRoutes = createProjectRoutes({ projectService, log });
104
113
  app.use('/api/projects', authMiddleware.requireAuth, projectRoutes);
105
114
 
106
115
  // Git repository routes (nested under /api/projects/:id/git)
107
- const gitRoutes = createGitRoutes({ projectService, githubAppService, workspaceService, log });
116
+ const gitRoutes = createGitRoutes({ projectService, githubAppService, workspaceService, sshKeyService, log });
108
117
  app.use('/api/projects/:id/git', authMiddleware.requireAuth, gitRoutes);
109
118
 
119
+ // File system routes (nested under /api/projects/:id/files)
120
+ const fileRoutes = createFileRoutes({ workspaceService, log });
121
+ app.use('/api/projects/:id/files', authMiddleware.requireAuth, fileRoutes);
122
+
123
+ // Agent management routes (authenticated)
124
+ const SKILLS_DIR = join(__dirname, '..', '..', '..', '..', '.claude', 'skills');
125
+ const agentService = new AgentService({
126
+ getDb,
127
+ log,
128
+ skillPaths: {
129
+ developer: join(SKILLS_DIR, 'assistkick-developer', 'SKILL.md'),
130
+ reviewer: join(SKILLS_DIR, 'assistkick-code-reviewer', 'SKILL.md'),
131
+ debugger: join(SKILLS_DIR, 'assistkick-debugger', 'SKILL.md'),
132
+ videoScriptWriter: join(SKILLS_DIR, 'video-script-writer', 'SKILL.md'),
133
+ videoCompositionAgent: join(SKILLS_DIR, 'video-composition-agent', 'SKILL.md'),
134
+ },
135
+ });
136
+ const agentRoutes = createAgentRoutes({ agentService, log });
137
+ app.use('/api/agents', authMiddleware.requireAuth, agentRoutes);
138
+
139
+ // Workflow management routes (authenticated)
140
+ const workflowRoutes = createWorkflowRoutes({ workflowService: initWorkflowService, log });
141
+ app.use('/api/workflows', authMiddleware.requireAuth, workflowRoutes);
142
+
143
+ // Workflow group routes (authenticated)
144
+ const workflowGroupRoutes = createWorkflowGroupRoutes({ workflowGroupService: initWorkflowGroupService, log });
145
+ app.use('/api/workflow-groups', authMiddleware.requireAuth, workflowGroupRoutes);
146
+
147
+ // Video routes (authenticated) — TTS audio generation, bundle management, compositions
148
+ const VIDEO_PACKAGE_DIR = join(__dirname, '..', '..', 'video');
149
+ const BUNDLE_OUTPUT_DIR = process.env.REMOTION_BUNDLE_DIR || join(__dirname, '..', '..', '..', '..', 'data', 'remotion-bundle');
150
+ const ttsService = new TtsService({
151
+ workspacesDir: process.env.WORKSPACES_DIR || join(__dirname, '..', '..', '..', '..', 'workspaces'),
152
+ videoPackageDir: VIDEO_PACKAGE_DIR,
153
+ log,
154
+ });
155
+ const bundleService = new BundleService({
156
+ videoPackageDir: VIDEO_PACKAGE_DIR,
157
+ bundleOutputDir: BUNDLE_OUTPUT_DIR,
158
+ log,
159
+ });
160
+ const videoRenderService = new VideoRenderService({
161
+ getDb,
162
+ workspacesDir: process.env.WORKSPACES_DIR || join(__dirname, '..', '..', '..', '..', 'workspaces'),
163
+ bundleOutputDir: BUNDLE_OUTPUT_DIR,
164
+ log,
165
+ });
166
+ const videoRoutes = createVideoRoutes({ ttsService, bundleService, videoRenderService, log });
167
+ app.use('/api/video', authMiddleware.requireAuth, videoRoutes);
168
+
110
169
  // Ensure default project exists and assign orphan nodes on startup
111
170
  projectService.ensureDefaultAndAssignOrphans().catch((err: any) => {
112
171
  log('STARTUP', `Failed to ensure default project: ${err.message}`);
113
172
  });
114
173
 
174
+ // Sync default agent prompts with latest SKILL.md + template code
175
+ agentService.syncDefaults().catch((err: any) => {
176
+ log('STARTUP', `Failed to sync default agents: ${err.message}`);
177
+ });
178
+
115
179
  // PTY session manager — initialized early so terminal REST routes can reference it
116
180
  // Resolve project root: from packages/backend/src → assistkick-product-system → repo root
117
181
  const PROJECT_ROOT = join(__dirname, '..', '..', '..', '..');
118
- const ptyManager = new PtySessionManager({ spawn: pty.spawn, log, projectRoot: PROJECT_ROOT });
182
+ const ptyManager = new PtySessionManager({ spawn: pty.spawn, log, projectRoot: PROJECT_ROOT, getDb });
119
183
 
120
184
  // Terminal session management REST routes (admin-only, auth required)
121
185
  const terminalRoutes = createTerminalRoutes({ ptyManager, log });
122
186
  app.use('/api/terminal', authMiddleware.requireAuth, terminalRoutes);
123
187
 
188
+ // Workflow execution routes (authenticated) — replaces old pipeline routes
189
+ const workflowExecRoutes = createWorkflowExecutionRoutes({
190
+ workflowEngine,
191
+ orchestrator,
192
+ workflowService: initWorkflowService,
193
+ log,
194
+ });
195
+
124
196
  // Protected API routes — require authentication
125
197
  app.use('/api', authMiddleware.requireAuth, graphRoutes);
126
198
  app.use('/api/kanban', authMiddleware.requireAuth, kanbanRoutes);
127
- app.use('/api/kanban', authMiddleware.requireAuth, pipelineRoutes);
128
- app.use('/api/pipeline', authMiddleware.requireAuth, pipelineRoutes);
199
+ app.use('/api/kanban', authMiddleware.requireAuth, workflowExecRoutes);
200
+ app.use('/api/pipeline', authMiddleware.requireAuth, workflowExecRoutes);
129
201
  app.use('/api/coherence', authMiddleware.requireAuth, coherenceRoutes);
130
202
 
131
203
  // Redirect favicon.ico to SVG favicon served from static files
@@ -154,7 +226,7 @@ server.on('upgrade', (req, socket, head) => {
154
226
 
155
227
  // Clean up PTY sessions on server shutdown
156
228
  process.on('SIGTERM', () => {
157
- ptyManager.destroyAll();
229
+ ptyManager.destroyAllPty();
158
230
  server.close();
159
231
  });
160
232