@assistkick/create 1.9.0 → 1.11.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/src/scaffolder.d.ts +12 -1
  2. package/dist/src/scaffolder.js +40 -3
  3. package/dist/src/scaffolder.js.map +1 -1
  4. package/package.json +1 -1
  5. package/templates/assistkick-product-system/package.json +1 -1
  6. package/templates/assistkick-product-system/packages/backend/package.json +1 -0
  7. package/templates/assistkick-product-system/packages/backend/src/mcp/permission_mcp_server.ts +196 -0
  8. package/templates/assistkick-product-system/packages/backend/src/routes/agents.ts +31 -7
  9. package/templates/assistkick-product-system/packages/backend/src/routes/auth.ts +15 -12
  10. package/templates/assistkick-product-system/packages/backend/src/routes/chat_files.test.ts +95 -0
  11. package/templates/assistkick-product-system/packages/backend/src/routes/chat_files.ts +97 -0
  12. package/templates/assistkick-product-system/packages/backend/src/routes/chat_permission.ts +94 -0
  13. package/templates/assistkick-product-system/packages/backend/src/routes/chat_sessions.ts +189 -0
  14. package/templates/assistkick-product-system/packages/backend/src/routes/chat_upload.test.ts +131 -0
  15. package/templates/assistkick-product-system/packages/backend/src/routes/chat_upload.ts +94 -0
  16. package/templates/assistkick-product-system/packages/backend/src/routes/files.test.ts +12 -3
  17. package/templates/assistkick-product-system/packages/backend/src/routes/files.ts +2 -2
  18. package/templates/assistkick-product-system/packages/backend/src/routes/git.ts +391 -23
  19. package/templates/assistkick-product-system/packages/backend/src/routes/git_branches.test.ts +306 -0
  20. package/templates/assistkick-product-system/packages/backend/src/routes/git_connect.test.ts +133 -0
  21. package/templates/assistkick-product-system/packages/backend/src/routes/pipeline.ts +66 -9
  22. package/templates/assistkick-product-system/packages/backend/src/routes/preview.ts +204 -0
  23. package/templates/assistkick-product-system/packages/backend/src/routes/projects.test.ts +205 -0
  24. package/templates/assistkick-product-system/packages/backend/src/routes/projects.ts +37 -9
  25. package/templates/assistkick-product-system/packages/backend/src/routes/skills.test.ts +139 -0
  26. package/templates/assistkick-product-system/packages/backend/src/routes/skills.ts +95 -0
  27. package/templates/assistkick-product-system/packages/backend/src/routes/terminal.ts +5 -4
  28. package/templates/assistkick-product-system/packages/backend/src/routes/users.ts +4 -4
  29. package/templates/assistkick-product-system/packages/backend/src/routes/video.ts +8 -8
  30. package/templates/assistkick-product-system/packages/backend/src/routes/workflow_groups.ts +5 -5
  31. package/templates/assistkick-product-system/packages/backend/src/routes/workflows.ts +6 -6
  32. package/templates/assistkick-product-system/packages/backend/src/server.ts +107 -27
  33. package/templates/assistkick-product-system/packages/backend/src/services/agent_service.test.ts +105 -203
  34. package/templates/assistkick-product-system/packages/backend/src/services/agent_service.ts +76 -266
  35. package/templates/assistkick-product-system/packages/backend/src/services/chat_cli_bridge.test.ts +427 -0
  36. package/templates/assistkick-product-system/packages/backend/src/services/chat_cli_bridge.ts +345 -0
  37. package/templates/assistkick-product-system/packages/backend/src/services/chat_message_repository.test.ts +170 -0
  38. package/templates/assistkick-product-system/packages/backend/src/services/chat_message_repository.ts +106 -0
  39. package/templates/assistkick-product-system/packages/backend/src/services/chat_session_service.test.ts +217 -0
  40. package/templates/assistkick-product-system/packages/backend/src/services/chat_session_service.ts +188 -0
  41. package/templates/assistkick-product-system/packages/backend/src/services/chat_ws_handler.test.ts +1243 -0
  42. package/templates/assistkick-product-system/packages/backend/src/services/chat_ws_handler.ts +894 -0
  43. package/templates/assistkick-product-system/packages/backend/src/services/coherence-review.ts +3 -3
  44. package/templates/assistkick-product-system/packages/backend/src/services/dev_command_detector.test.ts +85 -0
  45. package/templates/assistkick-product-system/packages/backend/src/services/dev_command_detector.ts +54 -0
  46. package/templates/assistkick-product-system/packages/backend/src/services/email_service.ts +13 -10
  47. package/templates/assistkick-product-system/packages/backend/src/services/init.ts +11 -3
  48. package/templates/assistkick-product-system/packages/backend/src/services/invitation_service.ts +1 -1
  49. package/templates/assistkick-product-system/packages/backend/src/services/password_reset_service.ts +1 -1
  50. package/templates/assistkick-product-system/packages/backend/src/services/permission_service.test.ts +243 -0
  51. package/templates/assistkick-product-system/packages/backend/src/services/permission_service.ts +259 -0
  52. package/templates/assistkick-product-system/packages/backend/src/services/preview_server_manager.test.ts +172 -0
  53. package/templates/assistkick-product-system/packages/backend/src/services/preview_server_manager.ts +225 -0
  54. package/templates/assistkick-product-system/packages/backend/src/services/project_service.test.ts +29 -0
  55. package/templates/assistkick-product-system/packages/backend/src/services/project_service.ts +17 -0
  56. package/templates/assistkick-product-system/packages/backend/src/services/project_workspace_service.test.ts +255 -0
  57. package/templates/assistkick-product-system/packages/backend/src/services/project_workspace_service.ts +300 -25
  58. package/templates/assistkick-product-system/packages/backend/src/services/pty_session_manager.test.ts +44 -0
  59. package/templates/assistkick-product-system/packages/backend/src/services/pty_session_manager.ts +62 -7
  60. package/templates/assistkick-product-system/packages/backend/src/services/ssh_key_service.test.ts +77 -6
  61. package/templates/assistkick-product-system/packages/backend/src/services/ssh_key_service.ts +149 -14
  62. package/templates/assistkick-product-system/packages/backend/src/services/terminal_ws_handler.ts +2 -1
  63. package/templates/assistkick-product-system/packages/backend/src/services/title_generator_service.test.ts +45 -0
  64. package/templates/assistkick-product-system/packages/backend/src/services/title_generator_service.ts +157 -0
  65. package/templates/assistkick-product-system/packages/backend/src/services/tts_service.ts +4 -3
  66. package/templates/assistkick-product-system/packages/backend/src/services/video_render_service.ts +3 -3
  67. package/templates/assistkick-product-system/packages/frontend/package.json +5 -0
  68. package/templates/assistkick-product-system/packages/frontend/src/App.tsx +2 -0
  69. package/templates/assistkick-product-system/packages/frontend/src/api/client.ts +336 -5
  70. package/templates/assistkick-product-system/packages/frontend/src/components/AgentsView.tsx +192 -12
  71. package/templates/assistkick-product-system/packages/frontend/src/components/AttachmentPreviewList.tsx +98 -0
  72. package/templates/assistkick-product-system/packages/frontend/src/components/AutocompleteDropdown.tsx +65 -0
  73. package/templates/assistkick-product-system/packages/frontend/src/components/ChatAttachButton.tsx +56 -0
  74. package/templates/assistkick-product-system/packages/frontend/src/components/ChatDropZone.tsx +80 -0
  75. package/templates/assistkick-product-system/packages/frontend/src/components/ChatMessageBubble.tsx +155 -0
  76. package/templates/assistkick-product-system/packages/frontend/src/components/ChatMessageContent.tsx +182 -0
  77. package/templates/assistkick-product-system/packages/frontend/src/components/ChatMessageInput.tsx +233 -0
  78. package/templates/assistkick-product-system/packages/frontend/src/components/ChatSessionSidebar.tsx +218 -0
  79. package/templates/assistkick-product-system/packages/frontend/src/components/ChatStopButton.tsx +32 -0
  80. package/templates/assistkick-product-system/packages/frontend/src/components/ChatTodoSidebar.tsx +113 -0
  81. package/templates/assistkick-product-system/packages/frontend/src/components/ChatView.tsx +842 -0
  82. package/templates/assistkick-product-system/packages/frontend/src/components/CommitMessageModal.tsx +82 -0
  83. package/templates/assistkick-product-system/packages/frontend/src/components/DiagramOverlay.tsx +160 -0
  84. package/templates/assistkick-product-system/packages/frontend/src/components/EditorTabBar.tsx +5 -5
  85. package/templates/assistkick-product-system/packages/frontend/src/components/FileTree.tsx +9 -10
  86. package/templates/assistkick-product-system/packages/frontend/src/components/FileTreeInlineInput.tsx +5 -5
  87. package/templates/assistkick-product-system/packages/frontend/src/components/FilesView.tsx +112 -41
  88. package/templates/assistkick-product-system/packages/frontend/src/components/GraphLegend.tsx +2 -2
  89. package/templates/assistkick-product-system/packages/frontend/src/components/HighlightedText.tsx +87 -0
  90. package/templates/assistkick-product-system/packages/frontend/src/components/ImageLightbox.tsx +192 -0
  91. package/templates/assistkick-product-system/packages/frontend/src/components/KanbanView.tsx +2 -2
  92. package/templates/assistkick-product-system/packages/frontend/src/components/MentionPill.tsx +33 -0
  93. package/templates/assistkick-product-system/packages/frontend/src/components/MermaidBlock.tsx +148 -0
  94. package/templates/assistkick-product-system/packages/frontend/src/components/PermissionDialog.tsx +91 -0
  95. package/templates/assistkick-product-system/packages/frontend/src/components/PermissionModeSelector.tsx +229 -0
  96. package/templates/assistkick-product-system/packages/frontend/src/components/ProjectSelector.tsx +249 -83
  97. package/templates/assistkick-product-system/packages/frontend/src/components/QueuedMessageBubble.tsx +38 -0
  98. package/templates/assistkick-product-system/packages/frontend/src/components/SidePanel.tsx +212 -117
  99. package/templates/assistkick-product-system/packages/frontend/src/components/SystemPromptAccordion.tsx +48 -0
  100. package/templates/assistkick-product-system/packages/frontend/src/components/TaskIcon.tsx +11 -0
  101. package/templates/assistkick-product-system/packages/frontend/src/components/TerminalView.tsx +25 -9
  102. package/templates/assistkick-product-system/packages/frontend/src/components/ToolDiffView.tsx +114 -0
  103. package/templates/assistkick-product-system/packages/frontend/src/components/ToolResultCard.tsx +87 -0
  104. package/templates/assistkick-product-system/packages/frontend/src/components/ToolUseCard.tsx +149 -0
  105. package/templates/assistkick-product-system/packages/frontend/src/components/Toolbar.tsx +25 -8
  106. package/templates/assistkick-product-system/packages/frontend/src/components/UnifiedGitWidget.tsx +722 -0
  107. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/GroupNode.tsx +2 -0
  108. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/NodePalette.tsx +2 -1
  109. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/ProgrammableNode.tsx +178 -0
  110. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/WorkflowCanvas.tsx +3 -0
  111. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/WorkflowMonitorModal.tsx +103 -9
  112. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/monitor_nodes.tsx +26 -2
  113. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/workflow_types.ts +42 -1
  114. package/templates/assistkick-product-system/packages/frontend/src/hooks/useDocumentTitle.ts +11 -0
  115. package/templates/assistkick-product-system/packages/frontend/src/hooks/useProjects.ts +1 -0
  116. package/templates/assistkick-product-system/packages/frontend/src/hooks/use_chat_stream.ts +826 -0
  117. package/templates/assistkick-product-system/packages/frontend/src/hooks/use_file_tree_cache.ts +69 -0
  118. package/templates/assistkick-product-system/packages/frontend/src/hooks/use_mention_autocomplete.ts +284 -0
  119. package/templates/assistkick-product-system/packages/frontend/src/lib/attachment_manager.test.ts +183 -0
  120. package/templates/assistkick-product-system/packages/frontend/src/lib/attachment_manager.ts +150 -0
  121. package/templates/assistkick-product-system/packages/frontend/src/lib/chat_message_helpers.test.ts +305 -0
  122. package/templates/assistkick-product-system/packages/frontend/src/lib/chat_message_helpers.ts +113 -0
  123. package/templates/assistkick-product-system/packages/frontend/src/lib/context_usage_helpers.test.ts +157 -0
  124. package/templates/assistkick-product-system/packages/frontend/src/lib/context_usage_helpers.ts +95 -0
  125. package/templates/assistkick-product-system/packages/frontend/src/lib/mermaid_helpers.test.ts +65 -0
  126. package/templates/assistkick-product-system/packages/frontend/src/lib/mermaid_helpers.ts +110 -0
  127. package/templates/assistkick-product-system/packages/frontend/src/lib/message_queue.ts +66 -0
  128. package/templates/assistkick-product-system/packages/frontend/src/lib/tool_use_summary.test.ts +124 -0
  129. package/templates/assistkick-product-system/packages/frontend/src/lib/tool_use_summary.ts +112 -0
  130. package/templates/assistkick-product-system/packages/frontend/src/routes/AgentsRoute.tsx +2 -0
  131. package/templates/assistkick-product-system/packages/frontend/src/routes/ChatRoute.tsx +8 -0
  132. package/templates/assistkick-product-system/packages/frontend/src/routes/CoherenceRoute.tsx +2 -0
  133. package/templates/assistkick-product-system/packages/frontend/src/routes/DashboardLayout.tsx +0 -4
  134. package/templates/assistkick-product-system/packages/frontend/src/routes/DesignSystemRoute.tsx +2 -0
  135. package/templates/assistkick-product-system/packages/frontend/src/routes/FilesRoute.tsx +2 -0
  136. package/templates/assistkick-product-system/packages/frontend/src/routes/GraphRoute.tsx +2 -0
  137. package/templates/assistkick-product-system/packages/frontend/src/routes/KanbanRoute.tsx +2 -0
  138. package/templates/assistkick-product-system/packages/frontend/src/routes/TerminalRoute.tsx +2 -0
  139. package/templates/assistkick-product-system/packages/frontend/src/routes/UsersRoute.tsx +2 -0
  140. package/templates/assistkick-product-system/packages/frontend/src/routes/VideographyRoute.tsx +2 -0
  141. package/templates/assistkick-product-system/packages/frontend/src/routes/WorkflowsRoute.tsx +2 -0
  142. package/templates/assistkick-product-system/packages/frontend/src/routes/accept_invitation.tsx +2 -0
  143. package/templates/assistkick-product-system/packages/frontend/src/routes/forgot_password.tsx +2 -0
  144. package/templates/assistkick-product-system/packages/frontend/src/routes/login.tsx +2 -0
  145. package/templates/assistkick-product-system/packages/frontend/src/routes/register.tsx +2 -0
  146. package/templates/assistkick-product-system/packages/frontend/src/routes/reset_password.tsx +2 -0
  147. package/templates/assistkick-product-system/packages/frontend/src/stores/useAttachmentStore.ts +66 -0
  148. package/templates/assistkick-product-system/packages/frontend/src/stores/useChatSessionStore.ts +107 -0
  149. package/templates/assistkick-product-system/packages/frontend/src/stores/useMessageQueueStore.ts +110 -0
  150. package/templates/assistkick-product-system/packages/frontend/src/stores/usePreviewStore.ts +78 -0
  151. package/templates/assistkick-product-system/packages/frontend/src/stores/useProjectStore.ts +7 -0
  152. package/templates/assistkick-product-system/packages/frontend/src/stores/useSidePanelStore.ts +6 -1
  153. package/templates/assistkick-product-system/packages/frontend/src/styles/index.css +30 -357
  154. package/templates/assistkick-product-system/packages/frontend/src/utils/parse_node_markdown.test.ts +115 -0
  155. package/templates/assistkick-product-system/packages/frontend/src/utils/parse_node_markdown.ts +91 -0
  156. package/templates/assistkick-product-system/packages/frontend/src/utils/preview_utils.test.ts +30 -0
  157. package/templates/assistkick-product-system/packages/frontend/src/utils/preview_utils.ts +3 -0
  158. package/templates/assistkick-product-system/packages/shared/db/migrations/0015_magenta_jazinda.sql +1 -0
  159. package/templates/assistkick-product-system/packages/shared/db/migrations/0016_giant_xorn.sql +1 -0
  160. package/templates/assistkick-product-system/packages/shared/db/migrations/0017_sloppy_mentor.sql +6 -0
  161. package/templates/assistkick-product-system/packages/shared/db/migrations/0018_vengeful_kabuki.sql +9 -0
  162. package/templates/assistkick-product-system/packages/shared/db/migrations/0019_careful_sentinels.sql +8 -0
  163. package/templates/assistkick-product-system/packages/shared/db/migrations/0020_clever_spot.sql +27 -0
  164. package/templates/assistkick-product-system/packages/shared/db/migrations/0021_graceful_hex.sql +1 -0
  165. package/templates/assistkick-product-system/packages/shared/db/migrations/0022_short_kingpin.sql +1 -0
  166. package/templates/assistkick-product-system/packages/shared/db/migrations/0023_ambiguous_sharon_carter.sql +1 -0
  167. package/templates/assistkick-product-system/packages/shared/db/migrations/0024_fat_unus.sql +1 -0
  168. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0015_snapshot.json +1552 -0
  169. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0016_snapshot.json +1560 -0
  170. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0017_snapshot.json +1598 -0
  171. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0018_snapshot.json +1657 -0
  172. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0019_snapshot.json +1709 -0
  173. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0020_snapshot.json +1733 -0
  174. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0021_snapshot.json +1740 -0
  175. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0022_snapshot.json +1755 -0
  176. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0023_snapshot.json +1762 -0
  177. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0024_snapshot.json +1769 -0
  178. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/_journal.json +70 -0
  179. package/templates/assistkick-product-system/packages/shared/db/schema.ts +40 -1
  180. package/templates/assistkick-product-system/packages/shared/lib/claude-service.test.ts +236 -0
  181. package/templates/assistkick-product-system/packages/shared/lib/claude-service.ts +46 -5
  182. package/templates/assistkick-product-system/packages/shared/lib/git_workflow.ts +65 -39
  183. package/templates/assistkick-product-system/packages/shared/lib/programmable_node_executor.test.ts +173 -0
  184. package/templates/assistkick-product-system/packages/shared/lib/programmable_node_executor.ts +213 -0
  185. package/templates/assistkick-product-system/packages/shared/lib/validator.test.ts +70 -0
  186. package/templates/assistkick-product-system/packages/shared/lib/validator.ts +17 -1
  187. package/templates/assistkick-product-system/packages/shared/lib/workflow_engine.test.ts +803 -27
  188. package/templates/assistkick-product-system/packages/shared/lib/workflow_engine.ts +502 -68
  189. package/templates/assistkick-product-system/packages/shared/lib/workflow_orchestrator.ts +4 -4
  190. package/templates/assistkick-product-system/packages/shared/package.json +2 -1
  191. package/templates/assistkick-product-system/packages/shared/test_fixtures/hanging_stream.mjs +46 -0
  192. package/templates/assistkick-product-system/packages/shared/tools/add_node.test.ts +44 -0
  193. package/templates/assistkick-product-system/packages/shared/tools/add_node.ts +7 -0
  194. package/templates/assistkick-product-system/packages/shared/tools/remove_node.ts +2 -1
  195. package/templates/assistkick-product-system/packages/shared/tools/resolve_question.ts +2 -1
  196. package/templates/assistkick-product-system/packages/shared/tools/update_node.ts +2 -1
  197. package/templates/assistkick-product-system/tests/message_queue.test.ts +178 -0
  198. package/templates/assistkick-product-system/tests/message_queue_per_session.test.ts +143 -0
  199. package/templates/skills/assistkick-bootstrap/SKILL.md +26 -26
  200. package/templates/skills/assistkick-code-reviewer/SKILL.md +45 -46
  201. package/templates/skills/assistkick-db-explorer/SKILL.md +13 -13
  202. package/templates/skills/assistkick-debugger/SKILL.md +23 -23
  203. package/templates/skills/assistkick-developer/SKILL.md +59 -63
  204. package/templates/skills/assistkick-interview/SKILL.md +26 -26
  205. package/templates/skills/assistkick-video-composition-agent/SKILL.md +231 -0
  206. package/templates/skills/assistkick-video-script-writer/SKILL.md +136 -0
@@ -1,3 +1,9 @@
1
+ export interface SkillInfo {
2
+ name: string;
3
+ description: string;
4
+ folderName: string;
5
+ }
6
+
1
7
  export interface VideoCompositionMeta {
2
8
  id: string;
3
9
  durationInFrames: number;
@@ -67,7 +73,10 @@ export interface NodeExecutionData {
67
73
  } | null;
68
74
  error: string | null;
69
75
  attempt: number;
76
+ cycle: number;
70
77
  toolCalls: ToolCallEntry[];
78
+ claudeSessionId: string | null;
79
+ processAlive: boolean;
71
80
  }
72
81
 
73
82
  export interface WorkflowMonitorData {
@@ -83,7 +92,7 @@ export interface WorkflowMonitorData {
83
92
  nodes: Array<{ id: string; type: string; position: { x: number; y: number }; data: Record<string, unknown> }>;
84
93
  edges: Array<{ id: string; source: string; target: string; sourceHandle?: string; data?: { label?: string } }>;
85
94
  };
86
- nodeExecutions: Record<string, NodeExecutionData>;
95
+ nodeExecutions: Record<string, NodeExecutionData[]>;
87
96
  }
88
97
 
89
98
  /**
@@ -370,6 +379,34 @@ export class ApiClient {
370
379
  return resp.json();
371
380
  };
372
381
 
382
+ stopNode = async (featureId: string, nodeId: string) => {
383
+ const resp = await this.fetchWithRefresh(`${this.baseUrl}/api/kanban/${featureId}/workflow/stop-node`, {
384
+ method: 'POST',
385
+ headers: { 'Content-Type': 'application/json' },
386
+ body: JSON.stringify({ nodeId }),
387
+ });
388
+ if (!resp.ok) {
389
+ let msg = `Failed to stop node: ${resp.status}`;
390
+ try { const err = await resp.json(); msg = err.error || msg; } catch { /* non-JSON response */ }
391
+ throw new Error(msg);
392
+ }
393
+ return resp.json();
394
+ };
395
+
396
+ continueNode = async (featureId: string, nodeId: string) => {
397
+ const resp = await this.fetchWithRefresh(`${this.baseUrl}/api/kanban/${featureId}/workflow/continue-node`, {
398
+ method: 'POST',
399
+ headers: { 'Content-Type': 'application/json' },
400
+ body: JSON.stringify({ nodeId }),
401
+ });
402
+ if (!resp.ok) {
403
+ let msg = `Failed to continue node: ${resp.status}`;
404
+ try { const err = await resp.json(); msg = err.error || msg; } catch { /* non-JSON response */ }
405
+ throw new Error(msg);
406
+ }
407
+ return resp.json();
408
+ };
409
+
373
410
  logout = async () => {
374
411
  const resp = await fetch(`${this.baseUrl}/api/auth/logout`, {
375
412
  method: 'POST',
@@ -511,6 +548,19 @@ export class ApiClient {
511
548
  return resp.json();
512
549
  };
513
550
 
551
+ updateProjectPreviewCommand = async (id: string, previewCommand: string | null) => {
552
+ const resp = await this.fetchWithRefresh(`${this.baseUrl}/api/projects/${id}`, {
553
+ method: 'PATCH',
554
+ headers: { 'Content-Type': 'application/json' },
555
+ body: JSON.stringify({ previewCommand: previewCommand ?? '' }),
556
+ });
557
+ if (!resp.ok) {
558
+ const data = await resp.json();
559
+ throw new Error(data.error || `Failed to update preview command: ${resp.status}`);
560
+ }
561
+ return resp.json();
562
+ };
563
+
514
564
  archiveProject = async (id: string) => {
515
565
  const resp = await this.fetchWithRefresh(`${this.baseUrl}/api/projects/${id}/archive`, {
516
566
  method: 'POST',
@@ -535,6 +585,40 @@ export class ApiClient {
535
585
  return resp.json();
536
586
  };
537
587
 
588
+ // --- Preview server management ---
589
+
590
+ previewStart = async (appName: string, projectId: string) => {
591
+ const resp = await this.fetchWithRefresh(`${this.baseUrl}/api/preview/start`, {
592
+ method: 'POST',
593
+ headers: { 'Content-Type': 'application/json' },
594
+ body: JSON.stringify({ appName, projectId }),
595
+ });
596
+ if (!resp.ok) {
597
+ const data = await resp.json();
598
+ throw new Error(data.error || `Failed to start preview: ${resp.status}`);
599
+ }
600
+ return resp.json();
601
+ };
602
+
603
+ previewStop = async (appName: string) => {
604
+ const resp = await this.fetchWithRefresh(`${this.baseUrl}/api/preview/stop`, {
605
+ method: 'POST',
606
+ headers: { 'Content-Type': 'application/json' },
607
+ body: JSON.stringify({ appName }),
608
+ });
609
+ if (!resp.ok) {
610
+ const data = await resp.json();
611
+ throw new Error(data.error || `Failed to stop preview: ${resp.status}`);
612
+ }
613
+ return resp.json();
614
+ };
615
+
616
+ previewList = async () => {
617
+ const resp = await this.fetchWithRefresh(`${this.baseUrl}/api/preview/list`);
618
+ if (!resp.ok) throw new Error(`Failed to list previews: ${resp.status}`);
619
+ return resp.json();
620
+ };
621
+
538
622
  // --- Git repository management ---
539
623
 
540
624
  getGitStatus = async (projectId: string) => {
@@ -639,11 +723,11 @@ export class ApiClient {
639
723
  return resp.json();
640
724
  };
641
725
 
642
- createTerminalSession = async (projectId: string, projectName: string) => {
726
+ createTerminalSession = async (projectId: string, projectName: string, sessionType: 'claude' | 'terminal' = 'claude') => {
643
727
  const resp = await this.fetchWithRefresh(`${this.baseUrl}/api/terminal/sessions`, {
644
728
  method: 'POST',
645
729
  headers: { 'Content-Type': 'application/json' },
646
- body: JSON.stringify({ projectId, projectName }),
730
+ body: JSON.stringify({ projectId, projectName, sessionType }),
647
731
  });
648
732
  if (!resp.ok) {
649
733
  const data = await resp.json();
@@ -696,7 +780,7 @@ export class ApiClient {
696
780
  return resp.json();
697
781
  };
698
782
 
699
- createAgent = async (data: { name: string; promptTemplate: string; projectId?: string }) => {
783
+ createAgent = async (data: { name: string; grounding: string; model?: string; skills?: string; projectId?: string }) => {
700
784
  const resp = await this.fetchWithRefresh(`${this.baseUrl}/api/agents`, {
701
785
  method: 'POST',
702
786
  headers: { 'Content-Type': 'application/json' },
@@ -709,7 +793,7 @@ export class ApiClient {
709
793
  return resp.json();
710
794
  };
711
795
 
712
- updateAgent = async (id: string, data: { name?: string; promptTemplate?: string }) => {
796
+ updateAgent = async (id: string, data: { name?: string; grounding?: string; model?: string; skills?: string }) => {
713
797
  const resp = await this.fetchWithRefresh(`${this.baseUrl}/api/agents/${id}`, {
714
798
  method: 'PUT',
715
799
  headers: { 'Content-Type': 'application/json' },
@@ -842,6 +926,21 @@ export class ApiClient {
842
926
  return resp.json();
843
927
  };
844
928
 
929
+ // --- Skills ---
930
+
931
+ fetchSkills = async (projectId: string): Promise<{ skills: SkillInfo[] }> => {
932
+ const resp = await this.fetchWithRefresh(`${this.baseUrl}/api/projects/${projectId}/skills`);
933
+ if (!resp.ok) throw new Error(`Failed to fetch skills: ${resp.status}`);
934
+ return resp.json();
935
+ };
936
+
937
+ /** Fetch available skills from the global skills directory (GET /api/skills). */
938
+ fetchAvailableSkills = async (): Promise<{ skills: Array<{ id: string; name: string; preview: string }> }> => {
939
+ const resp = await this.fetchWithRefresh(`${this.baseUrl}/api/skills`);
940
+ if (!resp.ok) throw new Error(`Failed to fetch available skills: ${resp.status}`);
941
+ return resp.json();
942
+ };
943
+
845
944
  // --- File system ---
846
945
 
847
946
  fetchFileTree = async (projectId: string) => {
@@ -906,6 +1005,131 @@ export class ApiClient {
906
1005
  return resp.json();
907
1006
  };
908
1007
 
1008
+ // --- Git branches ---
1009
+
1010
+ fetchGitBranches = async (projectId: string): Promise<{ current: string; local: string[]; remote: string[] }> => {
1011
+ const resp = await this.fetchWithRefresh(`${this.baseUrl}/api/projects/${projectId}/git/branches`);
1012
+ if (!resp.ok) {
1013
+ if (resp.status === 404) return { current: '', local: [], remote: [] };
1014
+ throw new Error(`Failed to fetch branches: ${resp.status}`);
1015
+ }
1016
+ return resp.json();
1017
+ };
1018
+
1019
+ checkoutBranch = async (projectId: string, branch: string, commitMessage?: string): Promise<any> => {
1020
+ const resp = await this.fetchWithRefresh(`${this.baseUrl}/api/projects/${projectId}/git/checkout`, {
1021
+ method: 'POST',
1022
+ headers: { 'Content-Type': 'application/json' },
1023
+ body: JSON.stringify({ branch, commitMessage }),
1024
+ });
1025
+ if (!resp.ok) {
1026
+ const data = await resp.json();
1027
+ if (data.dirty) throw Object.assign(new Error(data.error), { dirty: true });
1028
+ throw new Error(data.error || `Failed to checkout branch: ${resp.status}`);
1029
+ }
1030
+ return resp.json();
1031
+ };
1032
+
1033
+ createGitBranch = async (projectId: string, name: string): Promise<any> => {
1034
+ const resp = await this.fetchWithRefresh(`${this.baseUrl}/api/projects/${projectId}/git/branches`, {
1035
+ method: 'POST',
1036
+ headers: { 'Content-Type': 'application/json' },
1037
+ body: JSON.stringify({ name }),
1038
+ });
1039
+ if (!resp.ok) {
1040
+ const data = await resp.json();
1041
+ throw new Error(data.error || `Failed to create branch: ${resp.status}`);
1042
+ }
1043
+ return resp.json();
1044
+ };
1045
+
1046
+ deleteGitBranch = async (projectId: string, name: string): Promise<any> => {
1047
+ const resp = await this.fetchWithRefresh(`${this.baseUrl}/api/projects/${projectId}/git/branches`, {
1048
+ method: 'DELETE',
1049
+ headers: { 'Content-Type': 'application/json' },
1050
+ body: JSON.stringify({ name }),
1051
+ });
1052
+ if (!resp.ok) {
1053
+ const data = await resp.json();
1054
+ throw new Error(data.error || `Failed to delete branch: ${resp.status}`);
1055
+ }
1056
+ return resp.json();
1057
+ };
1058
+
1059
+ // --- Git remotes, fetch, pull, push ---
1060
+
1061
+ listGitRemotes = async (projectId: string): Promise<{ remotes: Array<{ name: string; url: string }> }> => {
1062
+ const resp = await this.fetchWithRefresh(`${this.baseUrl}/api/projects/${projectId}/git/remotes`);
1063
+ if (!resp.ok) {
1064
+ if (resp.status === 404) return { remotes: [] };
1065
+ throw new Error(`Failed to list remotes: ${resp.status}`);
1066
+ }
1067
+ return resp.json();
1068
+ };
1069
+
1070
+ addGitRemote = async (projectId: string, url: string, name: string = 'origin'): Promise<any> => {
1071
+ const resp = await this.fetchWithRefresh(`${this.baseUrl}/api/projects/${projectId}/git/remotes`, {
1072
+ method: 'POST',
1073
+ headers: { 'Content-Type': 'application/json' },
1074
+ body: JSON.stringify({ name, url }),
1075
+ });
1076
+ if (!resp.ok) {
1077
+ const data = await resp.json();
1078
+ throw new Error(data.error || `Failed to add remote: ${resp.status}`);
1079
+ }
1080
+ return resp.json();
1081
+ };
1082
+
1083
+ gitFetch = async (projectId: string, remote: string = 'origin'): Promise<{ ahead: number; behind: number }> => {
1084
+ const resp = await this.fetchWithRefresh(`${this.baseUrl}/api/projects/${projectId}/git/fetch`, {
1085
+ method: 'POST',
1086
+ headers: { 'Content-Type': 'application/json' },
1087
+ body: JSON.stringify({ remote }),
1088
+ });
1089
+ if (!resp.ok) {
1090
+ const data = await resp.json();
1091
+ throw new Error(data.error || `Failed to fetch: ${resp.status}`);
1092
+ }
1093
+ return resp.json();
1094
+ };
1095
+
1096
+ gitPull = async (projectId: string, force: boolean = false): Promise<{ ahead: number; behind: number }> => {
1097
+ const resp = await this.fetchWithRefresh(`${this.baseUrl}/api/projects/${projectId}/git/pull`, {
1098
+ method: 'POST',
1099
+ headers: { 'Content-Type': 'application/json' },
1100
+ body: JSON.stringify({ force }),
1101
+ });
1102
+ if (!resp.ok) {
1103
+ const data = await resp.json();
1104
+ throw new Error(data.error || `Failed to pull: ${resp.status}`);
1105
+ }
1106
+ return resp.json();
1107
+ };
1108
+
1109
+ gitPush = async (projectId: string): Promise<{ ahead: number; behind: number }> => {
1110
+ const resp = await this.fetchWithRefresh(`${this.baseUrl}/api/projects/${projectId}/git/push`, {
1111
+ method: 'POST',
1112
+ headers: { 'Content-Type': 'application/json' },
1113
+ });
1114
+ if (!resp.ok) {
1115
+ const data = await resp.json();
1116
+ throw new Error(data.error || `Failed to push: ${resp.status}`);
1117
+ }
1118
+ return resp.json();
1119
+ };
1120
+
1121
+ getAheadBehind = async (projectId: string): Promise<{ ahead: number; behind: number }> => {
1122
+ const resp = await this.fetchWithRefresh(`${this.baseUrl}/api/projects/${projectId}/git/ahead-behind`);
1123
+ if (!resp.ok) return { ahead: 0, behind: 0 };
1124
+ return resp.json();
1125
+ };
1126
+
1127
+ getInitialCommitStatus = async (projectId: string): Promise<{ onlyInitialCommit: boolean }> => {
1128
+ const resp = await this.fetchWithRefresh(`${this.baseUrl}/api/projects/${projectId}/git/initial-commit`);
1129
+ if (!resp.ok) return { onlyInitialCommit: true };
1130
+ return resp.json();
1131
+ };
1132
+
909
1133
  // --- Video / Remotion ---
910
1134
 
911
1135
  fetchVideoCompositions = async (): Promise<{ compositions: VideoCompositionMeta[] }> => {
@@ -972,6 +1196,113 @@ export class ApiClient {
972
1196
  }
973
1197
  return data;
974
1198
  };
1199
+
1200
+ // --- Chat v2 session management ---
1201
+
1202
+ listChatSessions = async (projectId: string) => {
1203
+ const resp = await this.fetchWithRefresh(
1204
+ `${this.baseUrl}/api/chat-sessions?projectId=${encodeURIComponent(projectId)}`,
1205
+ );
1206
+ if (!resp.ok) throw new Error(`Failed to list chat sessions: ${resp.status}`);
1207
+ return resp.json();
1208
+ };
1209
+
1210
+ createChatSession = async (projectId: string) => {
1211
+ const resp = await this.fetchWithRefresh(`${this.baseUrl}/api/chat-sessions`, {
1212
+ method: 'POST',
1213
+ headers: { 'Content-Type': 'application/json' },
1214
+ body: JSON.stringify({ projectId }),
1215
+ });
1216
+ if (!resp.ok) {
1217
+ const data = await resp.json();
1218
+ throw new Error(data.error || `Failed to create chat session: ${resp.status}`);
1219
+ }
1220
+ return resp.json();
1221
+ };
1222
+
1223
+ renameChatSession = async (sessionId: string, name: string) => {
1224
+ const resp = await this.fetchWithRefresh(
1225
+ `${this.baseUrl}/api/chat-sessions/${encodeURIComponent(sessionId)}`,
1226
+ {
1227
+ method: 'PATCH',
1228
+ headers: { 'Content-Type': 'application/json' },
1229
+ body: JSON.stringify({ name }),
1230
+ },
1231
+ );
1232
+ if (!resp.ok) {
1233
+ const data = await resp.json();
1234
+ throw new Error(data.error || `Failed to rename chat session: ${resp.status}`);
1235
+ }
1236
+ return resp.json();
1237
+ };
1238
+
1239
+ deleteChatSession = async (sessionId: string) => {
1240
+ const resp = await this.fetchWithRefresh(
1241
+ `${this.baseUrl}/api/chat-sessions/${encodeURIComponent(sessionId)}`,
1242
+ { method: 'DELETE' },
1243
+ );
1244
+ if (!resp.ok) {
1245
+ const data = await resp.json();
1246
+ throw new Error(data.error || `Failed to delete chat session: ${resp.status}`);
1247
+ }
1248
+ return resp.json();
1249
+ };
1250
+
1251
+ /** Compact a session and create a new continuation session. */
1252
+ compactAndContinue = async (sessionId: string) => {
1253
+ const resp = await this.fetchWithRefresh(
1254
+ `${this.baseUrl}/api/chat-sessions/${encodeURIComponent(sessionId)}/compact-continue`,
1255
+ { method: 'POST' },
1256
+ );
1257
+ if (!resp.ok) {
1258
+ const data = await resp.json();
1259
+ throw new Error(data.error || `Failed to compact session: ${resp.status}`);
1260
+ }
1261
+ return resp.json() as Promise<{
1262
+ session: {
1263
+ id: string;
1264
+ claudeSessionId: string;
1265
+ projectId: string;
1266
+ name: string;
1267
+ permissionMode: string | null;
1268
+ contextUsageJson: string | null;
1269
+ createdAt: string;
1270
+ updatedAt: string;
1271
+ };
1272
+ continuationPrompt: string;
1273
+ }>;
1274
+ };
1275
+
1276
+ // --- Chat v2 message history ---
1277
+
1278
+ /** Load persisted messages for a chat session. */
1279
+ listChatMessages = async (sessionId: string) => {
1280
+ const resp = await this.fetchWithRefresh(
1281
+ `${this.baseUrl}/api/chat-sessions/${encodeURIComponent(sessionId)}/messages`,
1282
+ );
1283
+ if (!resp.ok) throw new Error(`Failed to load chat messages: ${resp.status}`);
1284
+ return resp.json();
1285
+ };
1286
+
1287
+ // --- Chat v2 file upload ---
1288
+
1289
+ /**
1290
+ * Upload a file for chat attachment.
1291
+ * Accepts a base64-encoded file content and saves it to the project workspace.
1292
+ * Returns the relative path within the workspace.
1293
+ */
1294
+ uploadChatFile = async (projectId: string, fileName: string, base64Content: string): Promise<{ path: string }> => {
1295
+ const resp = await this.fetchWithRefresh(`${this.baseUrl}/api/chat-upload`, {
1296
+ method: 'POST',
1297
+ headers: { 'Content-Type': 'application/json' },
1298
+ body: JSON.stringify({ projectId, fileName, content: base64Content }),
1299
+ });
1300
+ if (!resp.ok) {
1301
+ const data = await resp.json();
1302
+ throw new Error(data.error || `Failed to upload file: ${resp.status}`);
1303
+ }
1304
+ return resp.json();
1305
+ };
975
1306
  }
976
1307
 
977
1308
  export const apiClient = new ApiClient();