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