@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.
- package/dist/bin/create.js +0 -0
- package/package.json +9 -7
- package/templates/assistkick-product-system/.env.example +1 -0
- package/templates/assistkick-product-system/local.db +0 -0
- package/templates/assistkick-product-system/package.json +4 -2
- package/templates/assistkick-product-system/packages/backend/package.json +2 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/agents.ts +165 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/files.test.ts +358 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/files.ts +356 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/git.ts +96 -1
- package/templates/assistkick-product-system/packages/backend/src/routes/graph.ts +1 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/kanban.ts +61 -6
- package/templates/assistkick-product-system/packages/backend/src/routes/pipeline.ts +200 -84
- package/templates/assistkick-product-system/packages/backend/src/routes/projects.ts +6 -3
- package/templates/assistkick-product-system/packages/backend/src/routes/terminal.ts +53 -17
- package/templates/assistkick-product-system/packages/backend/src/routes/video.ts +218 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/workflow_groups.ts +119 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/workflows.ts +158 -0
- package/templates/assistkick-product-system/packages/backend/src/server.ts +60 -9
- package/templates/assistkick-product-system/packages/backend/src/services/agent_service.test.ts +489 -0
- package/templates/assistkick-product-system/packages/backend/src/services/agent_service.ts +416 -0
- package/templates/assistkick-product-system/packages/backend/src/services/bundle_service.test.ts +189 -0
- package/templates/assistkick-product-system/packages/backend/src/services/bundle_service.ts +182 -0
- package/templates/assistkick-product-system/packages/backend/src/services/init.ts +43 -77
- package/templates/assistkick-product-system/packages/backend/src/services/project_service.test.ts +16 -0
- package/templates/assistkick-product-system/packages/backend/src/services/project_service.ts +73 -2
- package/templates/assistkick-product-system/packages/backend/src/services/project_workspace_service.test.ts +4 -4
- package/templates/assistkick-product-system/packages/backend/src/services/project_workspace_service.ts +87 -11
- package/templates/assistkick-product-system/packages/backend/src/services/pty_session_manager.test.ts +210 -69
- package/templates/assistkick-product-system/packages/backend/src/services/pty_session_manager.ts +210 -215
- package/templates/assistkick-product-system/packages/backend/src/services/ssh_key_service.test.ts +162 -0
- package/templates/assistkick-product-system/packages/backend/src/services/ssh_key_service.ts +148 -0
- package/templates/assistkick-product-system/packages/backend/src/services/terminal_ws_handler.ts +11 -5
- package/templates/assistkick-product-system/packages/backend/src/services/tts_service.test.ts +64 -0
- package/templates/assistkick-product-system/packages/backend/src/services/tts_service.ts +134 -0
- package/templates/assistkick-product-system/packages/backend/src/services/video_render_service.test.ts +256 -0
- package/templates/assistkick-product-system/packages/backend/src/services/video_render_service.ts +258 -0
- package/templates/assistkick-product-system/packages/backend/src/services/workflow_group_service.ts +106 -0
- package/templates/assistkick-product-system/packages/backend/src/services/workflow_service.test.ts +275 -0
- package/templates/assistkick-product-system/packages/backend/src/services/workflow_service.ts +245 -0
- package/templates/assistkick-product-system/packages/frontend/package-lock.json +3455 -0
- package/templates/assistkick-product-system/packages/frontend/package.json +6 -0
- package/templates/assistkick-product-system/packages/frontend/src/App.tsx +8 -0
- package/templates/assistkick-product-system/packages/frontend/src/api/client.ts +458 -18
- package/templates/assistkick-product-system/packages/frontend/src/api/client_files.test.ts +172 -0
- package/templates/assistkick-product-system/packages/frontend/src/api/client_video.test.ts +238 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/AgentsView.tsx +307 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/CoherenceView.tsx +82 -66
- package/templates/assistkick-product-system/packages/frontend/src/components/CompositionPlaceholder.tsx +97 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/DesignSystemView.tsx +20 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/EditorTabBar.tsx +57 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/FileTree.tsx +313 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/FileTreeContextMenu.tsx +61 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/FileTreeInlineInput.tsx +73 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/FilesView.tsx +404 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/GitRepoModal.tsx +187 -56
- package/templates/assistkick-product-system/packages/frontend/src/components/GraphLegend.tsx +71 -73
- package/templates/assistkick-product-system/packages/frontend/src/components/GraphSettings.tsx +8 -8
- package/templates/assistkick-product-system/packages/frontend/src/components/GraphView.tsx +1 -1
- package/templates/assistkick-product-system/packages/frontend/src/components/InviteUserDialog.tsx +15 -11
- package/templates/assistkick-product-system/packages/frontend/src/components/IterationCommentModal.tsx +80 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/KanbanView.tsx +263 -167
- package/templates/assistkick-product-system/packages/frontend/src/components/LoginPage.tsx +14 -14
- package/templates/assistkick-product-system/packages/frontend/src/components/ProjectSelector.tsx +54 -33
- package/templates/assistkick-product-system/packages/frontend/src/components/QaIssueSheet.tsx +32 -49
- package/templates/assistkick-product-system/packages/frontend/src/components/SidePanel.tsx +43 -48
- package/templates/assistkick-product-system/packages/frontend/src/components/TerminalView.tsx +121 -52
- package/templates/assistkick-product-system/packages/frontend/src/components/Toolbar.tsx +20 -14
- package/templates/assistkick-product-system/packages/frontend/src/components/UsersView.tsx +52 -52
- package/templates/assistkick-product-system/packages/frontend/src/components/VideoGallery.tsx +313 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/VideographyView.tsx +250 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/WorkflowsView.tsx +474 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/AccentBorderList.tsx +53 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/Button.tsx +87 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/ButtonGroup.tsx +29 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/ButtonShowcase.tsx +221 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/CardGlass.tsx +141 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/CompletionRing.tsx +30 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/ContentCard.tsx +34 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/IconButton.tsx +74 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/KanbanCard.tsx +103 -87
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/KanbanCardShowcase.tsx +9 -188
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/Kbd.tsx +11 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/KindBadge.tsx +21 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/NavBarSidekick.tsx +81 -37
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/SidePanelShowcase.tsx +370 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/SideSheet.tsx +64 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/StatusDot.tsx +18 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/CheckCardPositionNode.tsx +36 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/CheckCycleCountNode.tsx +60 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/EndNode.tsx +42 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/GenerateTTSNode.tsx +52 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/GroupNode.tsx +189 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/NodePalette.tsx +123 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/RebuildBundleNode.tsx +20 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/RenderVideoNode.tsx +72 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/RunAgentNode.tsx +51 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/SetCardMetadataNode.tsx +53 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/StartNode.tsx +18 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/TransitionCardNode.tsx +59 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/WorkflowCanvas.tsx +341 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/WorkflowMonitorModal.tsx +643 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/autoLayout.ts +103 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/edgeColors.ts +35 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/monitor_nodes.tsx +246 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/workflow_types.test.ts +119 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/workflow_types.ts +136 -0
- package/templates/assistkick-product-system/packages/frontend/src/constants/graph.ts +13 -11
- package/templates/assistkick-product-system/packages/frontend/src/hooks/useAutoSave.ts +75 -0
- package/templates/assistkick-product-system/packages/frontend/src/hooks/useToast.tsx +16 -3
- package/templates/assistkick-product-system/packages/frontend/src/pages/accept_invitation_page.tsx +30 -27
- package/templates/assistkick-product-system/packages/frontend/src/pages/forgot_password_page.tsx +18 -15
- package/templates/assistkick-product-system/packages/frontend/src/pages/register_page.tsx +21 -18
- package/templates/assistkick-product-system/packages/frontend/src/pages/reset_password_page.tsx +28 -25
- package/templates/assistkick-product-system/packages/frontend/src/routes/AgentsRoute.tsx +6 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/CoherenceRoute.tsx +1 -1
- package/templates/assistkick-product-system/packages/frontend/src/routes/DashboardLayout.tsx +2 -2
- package/templates/assistkick-product-system/packages/frontend/src/routes/FilesRoute.tsx +13 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/GraphRoute.tsx +2 -2
- package/templates/assistkick-product-system/packages/frontend/src/routes/VideographyRoute.tsx +13 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/WorkflowsRoute.tsx +6 -0
- package/templates/assistkick-product-system/packages/frontend/src/stores/useProjectStore.ts +6 -3
- package/templates/assistkick-product-system/packages/frontend/src/stores/useSidePanelStore.ts +4 -4
- package/templates/assistkick-product-system/packages/frontend/src/styles/index.css +275 -3535
- package/templates/assistkick-product-system/packages/frontend/src/utils/auto_save_service.test.ts +167 -0
- package/templates/assistkick-product-system/packages/frontend/src/utils/auto_save_service.ts +101 -0
- package/templates/assistkick-product-system/packages/frontend/src/utils/composition_matcher.test.ts +42 -0
- package/templates/assistkick-product-system/packages/frontend/src/utils/composition_matcher.ts +17 -0
- package/templates/assistkick-product-system/packages/frontend/src/utils/file_utils.test.ts +145 -0
- package/templates/assistkick-product-system/packages/frontend/src/utils/file_utils.ts +42 -0
- package/templates/assistkick-product-system/packages/frontend/src/utils/task_status.test.ts +4 -10
- package/templates/assistkick-product-system/packages/frontend/src/utils/task_status.ts +19 -1
- package/templates/assistkick-product-system/packages/frontend/vite.config.ts +5 -0
- package/templates/assistkick-product-system/packages/shared/db/local.db +0 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0004_tidy_matthew_murdock.sql +9 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0005_mysterious_falcon.sql +692 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0006_next_venom.sql +9 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0007_deep_barracuda.sql +39 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0008_puzzling_hannibal_king.sql +1 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0009_amused_beast.sql +8 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0010_spotty_moira_mactaggert.sql +9 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0011_goofy_snowbird.sql +3 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0011_supreme_doctor_octopus.sql +3 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0013_reflective_prowler.sql +15 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0014_nifty_punisher.sql +15 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0004_snapshot.json +921 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0005_snapshot.json +1042 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0006_snapshot.json +1101 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0007_snapshot.json +1336 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0008_snapshot.json +1275 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0009_snapshot.json +1327 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0010_snapshot.json +1393 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0011_snapshot.json +1436 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0013_snapshot.json +1538 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0014_snapshot.json +1545 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/_journal.json +77 -0
- package/templates/assistkick-product-system/packages/shared/db/schema.ts +114 -0
- package/templates/assistkick-product-system/packages/shared/lib/claude-service.ts +32 -7
- package/templates/assistkick-product-system/packages/shared/lib/constants.ts +9 -0
- package/templates/assistkick-product-system/packages/shared/lib/git_workflow.ts +12 -4
- package/templates/assistkick-product-system/packages/shared/lib/graph.ts +5 -0
- package/templates/assistkick-product-system/packages/shared/lib/workflow_engine.test.ts +1999 -0
- package/templates/assistkick-product-system/packages/shared/lib/workflow_engine.ts +1437 -0
- package/templates/assistkick-product-system/packages/shared/lib/workflow_orchestrator.ts +211 -0
- package/templates/assistkick-product-system/packages/shared/tools/add_node.test.ts +43 -0
- package/templates/assistkick-product-system/packages/shared/tools/add_node.ts +13 -2
- package/templates/assistkick-product-system/packages/shared/tools/get_kanban.ts +1 -1
- package/templates/assistkick-product-system/packages/shared/tools/migrate_epics.test.ts +226 -0
- package/templates/assistkick-product-system/packages/shared/tools/migrate_epics.ts +251 -0
- package/templates/assistkick-product-system/packages/shared/tools/update_node.ts +2 -2
- package/templates/assistkick-product-system/packages/shared/utils/hello_workflow.test.ts +10 -0
- package/templates/assistkick-product-system/packages/shared/utils/hello_workflow.ts +6 -0
- package/templates/assistkick-product-system/packages/video/Root.tsx +85 -0
- package/templates/assistkick-product-system/packages/video/components/email_scene.tsx +231 -0
- package/templates/assistkick-product-system/packages/video/components/outro_scene.tsx +153 -0
- package/templates/assistkick-product-system/packages/video/components/part_divider.tsx +90 -0
- package/templates/assistkick-product-system/packages/video/components/scene.tsx +226 -0
- package/templates/assistkick-product-system/packages/video/components/theme.ts +22 -0
- package/templates/assistkick-product-system/packages/video/components/title_scene.tsx +169 -0
- package/templates/assistkick-product-system/packages/video/components/video_split_layout.tsx +84 -0
- package/templates/assistkick-product-system/packages/video/compositions/.gitkeep +0 -0
- package/templates/assistkick-product-system/packages/video/index.ts +4 -0
- package/templates/assistkick-product-system/packages/video/package.json +28 -0
- package/templates/assistkick-product-system/packages/video/remotion.config.ts +11 -0
- package/templates/assistkick-product-system/packages/video/scripts/process_script.test.ts +326 -0
- package/templates/assistkick-product-system/packages/video/scripts/process_script.ts +630 -0
- package/templates/assistkick-product-system/packages/video/style.css +1 -0
- package/templates/assistkick-product-system/packages/video/tsconfig.json +18 -0
- package/templates/assistkick-product-system/tests/graph_legend.test.ts +2 -1
- package/templates/assistkick-product-system/tests/video_render_service.test.ts +181 -0
- package/templates/assistkick-product-system/tests/web_terminal.test.ts +219 -455
- package/templates/assistkick-product-system/tests/workflow_integration.test.ts +341 -0
- package/templates/skills/assistkick-developer/SKILL.md +3 -0
- package/templates/skills/assistkick-developer/references/react_development_guidelines.md +225 -0
- package/templates/skills/product-system/graph.json +1890 -0
- package/templates/skills/product-system/kanban.json +304 -0
- package/templates/skills/product-system/nodes/comp_001.md +56 -0
- package/templates/skills/product-system/nodes/comp_002.md +57 -0
- package/templates/skills/product-system/nodes/data_001.md +51 -0
- package/templates/skills/product-system/nodes/data_002.md +40 -0
- package/templates/skills/product-system/nodes/data_004.md +38 -0
- package/templates/skills/product-system/nodes/dec_001.md +34 -0
- package/templates/skills/product-system/nodes/dec_016.md +32 -0
- package/templates/skills/product-system/nodes/feat_008.md +30 -0
- package/templates/skills/video-composition-agent/SKILL.md +232 -0
- 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
|
|
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
|
|
74
|
-
if (req.originalUrl.endsWith('/
|
|
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,
|
|
128
|
-
app.use('/api/pipeline', authMiddleware.requireAuth,
|
|
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.
|
|
208
|
+
ptyManager.destroyAllPty();
|
|
158
209
|
server.close();
|
|
159
210
|
});
|
|
160
211
|
|