@assistkick/create 1.10.0 → 1.12.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 (209) 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 +390 -22
  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 +129 -8
  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/migrate.ts +82 -0
  159. package/templates/assistkick-product-system/packages/shared/db/migrations/0000_outgoing_ultron.sql +277 -0
  160. package/templates/assistkick-product-system/packages/shared/db/migrations/0015_magenta_jazinda.sql +1 -0
  161. package/templates/assistkick-product-system/packages/shared/db/migrations/0016_giant_xorn.sql +1 -0
  162. package/templates/assistkick-product-system/packages/shared/db/migrations/0017_sloppy_mentor.sql +6 -0
  163. package/templates/assistkick-product-system/packages/shared/db/migrations/0018_vengeful_kabuki.sql +9 -0
  164. package/templates/assistkick-product-system/packages/shared/db/migrations/0019_careful_sentinels.sql +8 -0
  165. package/templates/assistkick-product-system/packages/shared/db/migrations/0020_clever_spot.sql +27 -0
  166. package/templates/assistkick-product-system/packages/shared/db/migrations/0021_graceful_hex.sql +1 -0
  167. package/templates/assistkick-product-system/packages/shared/db/migrations/0022_short_kingpin.sql +1 -0
  168. package/templates/assistkick-product-system/packages/shared/db/migrations/0023_ambiguous_sharon_carter.sql +1 -0
  169. package/templates/assistkick-product-system/packages/shared/db/migrations/0024_fat_unus.sql +1 -0
  170. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0000_snapshot.json +972 -22
  171. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0015_snapshot.json +1552 -0
  172. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0016_snapshot.json +1560 -0
  173. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0017_snapshot.json +1598 -0
  174. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0018_snapshot.json +1657 -0
  175. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0019_snapshot.json +1709 -0
  176. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0020_snapshot.json +1733 -0
  177. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0021_snapshot.json +1740 -0
  178. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0022_snapshot.json +1755 -0
  179. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0023_snapshot.json +1762 -0
  180. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0024_snapshot.json +1769 -0
  181. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/_journal.json +2 -100
  182. package/templates/assistkick-product-system/packages/shared/db/schema.ts +40 -1
  183. package/templates/assistkick-product-system/packages/shared/lib/claude-service.test.ts +236 -0
  184. package/templates/assistkick-product-system/packages/shared/lib/claude-service.ts +46 -5
  185. package/templates/assistkick-product-system/packages/shared/lib/git_workflow.ts +65 -39
  186. package/templates/assistkick-product-system/packages/shared/lib/programmable_node_executor.test.ts +173 -0
  187. package/templates/assistkick-product-system/packages/shared/lib/programmable_node_executor.ts +213 -0
  188. package/templates/assistkick-product-system/packages/shared/lib/validator.test.ts +70 -0
  189. package/templates/assistkick-product-system/packages/shared/lib/validator.ts +17 -1
  190. package/templates/assistkick-product-system/packages/shared/lib/workflow_engine.test.ts +803 -27
  191. package/templates/assistkick-product-system/packages/shared/lib/workflow_engine.ts +502 -68
  192. package/templates/assistkick-product-system/packages/shared/lib/workflow_orchestrator.ts +4 -4
  193. package/templates/assistkick-product-system/packages/shared/package.json +2 -1
  194. package/templates/assistkick-product-system/packages/shared/test_fixtures/hanging_stream.mjs +46 -0
  195. package/templates/assistkick-product-system/packages/shared/tools/add_node.test.ts +44 -0
  196. package/templates/assistkick-product-system/packages/shared/tools/add_node.ts +7 -0
  197. package/templates/assistkick-product-system/packages/shared/tools/remove_node.ts +2 -1
  198. package/templates/assistkick-product-system/packages/shared/tools/resolve_question.ts +2 -1
  199. package/templates/assistkick-product-system/packages/shared/tools/update_node.ts +2 -1
  200. package/templates/assistkick-product-system/tests/message_queue.test.ts +178 -0
  201. package/templates/assistkick-product-system/tests/message_queue_per_session.test.ts +143 -0
  202. package/templates/skills/assistkick-bootstrap/SKILL.md +26 -26
  203. package/templates/skills/assistkick-code-reviewer/SKILL.md +45 -46
  204. package/templates/skills/assistkick-db-explorer/SKILL.md +13 -13
  205. package/templates/skills/assistkick-debugger/SKILL.md +23 -23
  206. package/templates/skills/assistkick-developer/SKILL.md +59 -63
  207. package/templates/skills/assistkick-interview/SKILL.md +26 -26
  208. package/templates/skills/assistkick-video-composition-agent/SKILL.md +231 -0
  209. package/templates/skills/assistkick-video-script-writer/SKILL.md +136 -0
@@ -2,8 +2,10 @@ import React from 'react';
2
2
  import { Navigate } from 'react-router-dom';
3
3
  import { ResetPasswordPage } from '../pages/reset_password_page';
4
4
  import { useAuth } from '../hooks/useAuth';
5
+ import { useDocumentTitle } from '../hooks/useDocumentTitle';
5
6
 
6
7
  export function ResetPasswordRoute() {
8
+ useDocumentTitle('Reset Password');
7
9
  const { user, loading } = useAuth();
8
10
 
9
11
  if (loading) return null;
@@ -0,0 +1,66 @@
1
+ /**
2
+ * useAttachmentStore — Zustand store for Chat v2 file attachments.
3
+ *
4
+ * Wraps the pure AttachmentManager class for React integration.
5
+ * Manages files attached to the current message input, including
6
+ * upload state tracking and preview generation for images.
7
+ */
8
+
9
+ import { create } from 'zustand';
10
+ import { AttachmentManager, type Attachment } from '../lib/attachment_manager';
11
+
12
+ export type { Attachment } from '../lib/attachment_manager';
13
+
14
+ interface AttachmentState {
15
+ attachments: readonly Attachment[];
16
+ addUpload: (file: File, preview: string | null) => Attachment;
17
+ addWorkspaceFile: (path: string, name: string, size: number, mimeType: string) => Attachment;
18
+ markUploaded: (id: string, path: string) => void;
19
+ markUploadFailed: (id: string) => void;
20
+ remove: (id: string) => void;
21
+ clear: () => void;
22
+ getReadyPaths: () => string[];
23
+ hasUploading: () => boolean;
24
+ }
25
+
26
+ const mgr = new AttachmentManager();
27
+
28
+ export const useAttachmentStore = create<AttachmentState>((set) => ({
29
+ attachments: [],
30
+
31
+ addUpload: (file: File, preview: string | null) => {
32
+ const att = mgr.addUpload(file, preview);
33
+ set({ attachments: [...mgr.getAttachments()] });
34
+ return att;
35
+ },
36
+
37
+ addWorkspaceFile: (path: string, name: string, size: number, mimeType: string) => {
38
+ const att = mgr.addWorkspaceFile(path, name, size, mimeType);
39
+ set({ attachments: [...mgr.getAttachments()] });
40
+ return att;
41
+ },
42
+
43
+ markUploaded: (id: string, path: string) => {
44
+ mgr.markUploaded(id, path);
45
+ set({ attachments: [...mgr.getAttachments()] });
46
+ },
47
+
48
+ markUploadFailed: (id: string) => {
49
+ mgr.markUploadFailed(id);
50
+ set({ attachments: [...mgr.getAttachments()] });
51
+ },
52
+
53
+ remove: (id: string) => {
54
+ mgr.remove(id);
55
+ set({ attachments: [...mgr.getAttachments()] });
56
+ },
57
+
58
+ clear: () => {
59
+ mgr.clear();
60
+ set({ attachments: [] });
61
+ },
62
+
63
+ getReadyPaths: () => mgr.getReadyPaths(),
64
+
65
+ hasUploading: () => mgr.hasUploading(),
66
+ }));
@@ -0,0 +1,107 @@
1
+ import { create } from 'zustand';
2
+ import { apiClient } from '../api/client';
3
+
4
+ const ACTIVE_SESSION_STORAGE_KEY = 'assistkick_active_session_id';
5
+
6
+ export interface ChatSession {
7
+ id: string;
8
+ claudeSessionId: string;
9
+ projectId: string;
10
+ name: string;
11
+ permissionMode: string | null;
12
+ continuationContext: string | null;
13
+ systemPrompt: string | null;
14
+ contextUsageJson: string | null;
15
+ createdAt: string;
16
+ updatedAt: string;
17
+ }
18
+
19
+ interface ChatSessionState {
20
+ sessions: ChatSession[];
21
+ activeSessionId: string | null;
22
+ loading: boolean;
23
+
24
+ fetchSessions: (projectId: string) => Promise<ChatSession[]>;
25
+ selectSession: (id: string | null) => void;
26
+ createSession: (projectId: string) => Promise<ChatSession>;
27
+ renameSession: (id: string, name: string) => Promise<void>;
28
+ /** Update a session name locally without an API call (used by WS session_renamed). */
29
+ updateSessionName: (id: string, name: string) => void;
30
+ deleteSession: (id: string, projectId: string) => Promise<void>;
31
+ /** Compact current session and create a new continuation session. */
32
+ compactAndContinue: (sessionId: string, projectId: string) => Promise<ChatSession>;
33
+ }
34
+
35
+ export const useChatSessionStore = create<ChatSessionState>((set, get) => ({
36
+ sessions: [],
37
+ activeSessionId: localStorage.getItem(ACTIVE_SESSION_STORAGE_KEY),
38
+ loading: false,
39
+
40
+ fetchSessions: async (projectId: string) => {
41
+ set({ loading: true });
42
+ try {
43
+ const data = await apiClient.listChatSessions(projectId);
44
+ const sessions = data.sessions as ChatSession[];
45
+ set({ sessions, loading: false });
46
+ return sessions;
47
+ } catch {
48
+ set({ sessions: [], loading: false });
49
+ return [] as ChatSession[];
50
+ }
51
+ },
52
+
53
+ selectSession: (id: string | null) => {
54
+ if (id) {
55
+ localStorage.setItem(ACTIVE_SESSION_STORAGE_KEY, id);
56
+ } else {
57
+ localStorage.removeItem(ACTIVE_SESSION_STORAGE_KEY);
58
+ }
59
+ set({ activeSessionId: id });
60
+ },
61
+
62
+ createSession: async (projectId: string) => {
63
+ const data = await apiClient.createChatSession(projectId);
64
+ const session = data.session as ChatSession;
65
+ await get().fetchSessions(projectId);
66
+ localStorage.setItem(ACTIVE_SESSION_STORAGE_KEY, session.id);
67
+ set({ activeSessionId: session.id });
68
+ return session;
69
+ },
70
+
71
+ renameSession: async (id: string, name: string) => {
72
+ await apiClient.renameChatSession(id, name);
73
+ // Update in-place without refetching
74
+ set((state) => ({
75
+ sessions: state.sessions.map((s) =>
76
+ s.id === id ? { ...s, name } : s,
77
+ ),
78
+ }));
79
+ },
80
+
81
+ updateSessionName: (id: string, name: string) => {
82
+ set((state) => ({
83
+ sessions: state.sessions.map((s) =>
84
+ s.id === id ? { ...s, name } : s,
85
+ ),
86
+ }));
87
+ },
88
+
89
+ deleteSession: async (id: string, projectId: string) => {
90
+ await apiClient.deleteChatSession(id);
91
+ const { activeSessionId } = get();
92
+ if (activeSessionId === id) {
93
+ localStorage.removeItem(ACTIVE_SESSION_STORAGE_KEY);
94
+ set({ activeSessionId: null });
95
+ }
96
+ await get().fetchSessions(projectId);
97
+ },
98
+
99
+ compactAndContinue: async (sessionId: string, projectId: string) => {
100
+ const data = await apiClient.compactAndContinue(sessionId);
101
+ const session = data.session as ChatSession;
102
+ await get().fetchSessions(projectId);
103
+ localStorage.setItem(ACTIVE_SESSION_STORAGE_KEY, session.id);
104
+ set({ activeSessionId: session.id });
105
+ return session;
106
+ },
107
+ }));
@@ -0,0 +1,110 @@
1
+ /**
2
+ * useMessageQueueStore — Zustand store for Chat v2 message queuing.
3
+ *
4
+ * Wraps the pure MessageQueue class for React integration.
5
+ * Manages per-session queues of user messages that are enqueued while Claude
6
+ * is still responding. When the current CLI invocation completes, all
7
+ * queued messages for that session are drained, merged into a single prompt,
8
+ * and sent as the next invocation. Each queued message is displayed as a
9
+ * separate bubble in the UI with a pending/queued visual state.
10
+ *
11
+ * Queues are scoped per session ID — switching sessions shows only that
12
+ * session's queued messages.
13
+ */
14
+
15
+ import { create } from 'zustand';
16
+ import { MessageQueue, type QueuedMessage } from '../lib/message_queue';
17
+
18
+ export type { QueuedMessage } from '../lib/message_queue';
19
+
20
+ interface MessageQueueState {
21
+ /** The currently active session ID (controls which queue is visible). */
22
+ activeSessionId: string | null;
23
+ /** The visible queue for the active session. */
24
+ queue: QueuedMessage[];
25
+ /** Set the active session — updates the visible queue. */
26
+ setActiveSession: (sessionId: string | null) => void;
27
+ /** Enqueue a message to a specific session (defaults to active session). */
28
+ enqueue: (text: string, sessionId?: string) => void;
29
+ /** Remove a queued message from a specific session (defaults to active session). */
30
+ remove: (id: string, sessionId?: string) => void;
31
+ /** Clear all queued messages for a specific session (defaults to active session). */
32
+ clear: (sessionId?: string) => void;
33
+ /** Drain all queued messages for a specific session (defaults to active session). Returns the drained messages. */
34
+ drainAll: (sessionId?: string) => QueuedMessage[];
35
+ }
36
+
37
+ /** Per-session MessageQueue instances, keyed by session ID. */
38
+ const sessionQueues = new Map<string, MessageQueue>();
39
+
40
+ const getOrCreateQueue = (sessionId: string): MessageQueue => {
41
+ let mq = sessionQueues.get(sessionId);
42
+ if (!mq) {
43
+ mq = new MessageQueue();
44
+ sessionQueues.set(sessionId, mq);
45
+ }
46
+ return mq;
47
+ };
48
+
49
+ export const useMessageQueueStore = create<MessageQueueState>((set, get) => ({
50
+ activeSessionId: null,
51
+ queue: [],
52
+
53
+ setActiveSession: (sessionId: string | null) => {
54
+ const visibleQueue = sessionId
55
+ ? [...(getOrCreateQueue(sessionId).getQueue())]
56
+ : [];
57
+ set({ activeSessionId: sessionId, queue: visibleQueue });
58
+ },
59
+
60
+ enqueue: (text: string, sessionId?: string) => {
61
+ const targetId = sessionId ?? get().activeSessionId;
62
+ if (!targetId) return;
63
+
64
+ const mq = getOrCreateQueue(targetId);
65
+ mq.enqueue(text);
66
+
67
+ // Only update visible queue if targeting the active session
68
+ if (targetId === get().activeSessionId) {
69
+ set({ queue: [...mq.getQueue()] });
70
+ }
71
+ },
72
+
73
+ remove: (id: string, sessionId?: string) => {
74
+ const targetId = sessionId ?? get().activeSessionId;
75
+ if (!targetId) return;
76
+
77
+ const mq = getOrCreateQueue(targetId);
78
+ mq.remove(id);
79
+
80
+ if (targetId === get().activeSessionId) {
81
+ set({ queue: [...mq.getQueue()] });
82
+ }
83
+ },
84
+
85
+ clear: (sessionId?: string) => {
86
+ const targetId = sessionId ?? get().activeSessionId;
87
+ if (!targetId) return;
88
+
89
+ const mq = getOrCreateQueue(targetId);
90
+ mq.clear();
91
+
92
+ if (targetId === get().activeSessionId) {
93
+ set({ queue: [] });
94
+ }
95
+ },
96
+
97
+ drainAll: (sessionId?: string) => {
98
+ const targetId = sessionId ?? get().activeSessionId;
99
+ if (!targetId) return [];
100
+
101
+ const mq = getOrCreateQueue(targetId);
102
+ const drained = mq.drainAll();
103
+
104
+ if (targetId === get().activeSessionId) {
105
+ set({ queue: [] });
106
+ }
107
+
108
+ return drained;
109
+ },
110
+ }));
@@ -0,0 +1,78 @@
1
+ import { create } from 'zustand';
2
+ import { apiClient } from '../api/client';
3
+
4
+ export interface PreviewApp {
5
+ appName: string;
6
+ port: number;
7
+ projectDir: string;
8
+ command: string;
9
+ scriptName: string;
10
+ isPublic: boolean;
11
+ startedAt: string;
12
+ lastAccessedAt: string;
13
+ pid: number | undefined;
14
+ }
15
+
16
+ interface PreviewState {
17
+ apps: PreviewApp[];
18
+ loading: boolean;
19
+ pollIntervalId: ReturnType<typeof setInterval> | null;
20
+
21
+ fetchApps: () => Promise<void>;
22
+ startPolling: () => void;
23
+ stopPolling: () => void;
24
+ startPreview: (appName: string, projectId: string) => Promise<PreviewApp>;
25
+ stopPreview: (appName: string) => Promise<void>;
26
+ isRunning: (appName: string) => boolean;
27
+ }
28
+
29
+ const POLL_INTERVAL_MS = 5000;
30
+
31
+ export const usePreviewStore = create<PreviewState>((set, get) => ({
32
+ apps: [],
33
+ loading: false,
34
+ pollIntervalId: null,
35
+
36
+ fetchApps: async () => {
37
+ try {
38
+ const data = await apiClient.previewList();
39
+ set({ apps: data.apps, loading: false });
40
+ } catch {
41
+ set({ apps: [], loading: false });
42
+ }
43
+ },
44
+
45
+ startPolling: () => {
46
+ const existing = get().pollIntervalId;
47
+ if (existing) return;
48
+ // Fetch immediately, then poll
49
+ get().fetchApps();
50
+ const id = setInterval(() => get().fetchApps(), POLL_INTERVAL_MS);
51
+ set({ pollIntervalId: id });
52
+ },
53
+
54
+ stopPolling: () => {
55
+ const id = get().pollIntervalId;
56
+ if (id) {
57
+ clearInterval(id);
58
+ set({ pollIntervalId: null });
59
+ }
60
+ },
61
+
62
+ startPreview: async (appName, projectId) => {
63
+ set({ loading: true });
64
+ const data = await apiClient.previewStart(appName, projectId);
65
+ await get().fetchApps();
66
+ return data.app;
67
+ },
68
+
69
+ stopPreview: async (appName) => {
70
+ set({ loading: true });
71
+ await apiClient.previewStop(appName);
72
+ await get().fetchApps();
73
+ },
74
+
75
+ isRunning: (appName) => {
76
+ return get().apps.some(a => a.appName === appName);
77
+ },
78
+ }));
@@ -15,6 +15,7 @@ export interface Project {
15
15
  baseBranch: string | null;
16
16
  gitAuthMethod: string | null;
17
17
  sshPublicKey: string | null;
18
+ previewCommand: string | null;
18
19
  createdAt: string;
19
20
  updatedAt: string;
20
21
  }
@@ -28,6 +29,7 @@ interface ProjectState {
28
29
  selectProject: (id: string) => void;
29
30
  createProject: (name: string, type?: string) => Promise<Project>;
30
31
  renameProject: (id: string, name: string) => Promise<void>;
32
+ updatePreviewCommand: (id: string, previewCommand: string | null) => Promise<void>;
31
33
  archiveProject: (id: string) => Promise<void>;
32
34
  refetchProjects: () => Promise<Project[]>;
33
35
  }
@@ -78,6 +80,11 @@ export const useProjectStore = create<ProjectState>((set, get) => ({
78
80
  await get().refetchProjects();
79
81
  },
80
82
 
83
+ updatePreviewCommand: async (id, previewCommand) => {
84
+ await apiClient.updateProjectPreviewCommand(id, previewCommand);
85
+ await get().refetchProjects();
86
+ },
87
+
81
88
  archiveProject: async (id) => {
82
89
  await apiClient.archiveProject(id);
83
90
  const updated = await get().refetchProjects();
@@ -1,5 +1,6 @@
1
1
  import { create } from 'zustand';
2
2
  import { apiClient } from '../api/client';
3
+ import { parseNodeMarkdown, type ParsedNodeContent } from '../utils/parse_node_markdown';
3
4
 
4
5
  interface WorkSummary {
5
6
  cycle: number;
@@ -21,6 +22,7 @@ interface SidePanelState {
21
22
  isOpen: boolean;
22
23
  node: any | null;
23
24
  content: string;
25
+ parsedContent: ParsedNodeContent | null;
24
26
  workSummaries: WorkSummary[];
25
27
  expandedSummaries: boolean;
26
28
  tasks: Tasks | null;
@@ -36,6 +38,7 @@ export const useSidePanelStore = create<SidePanelState>((set) => ({
36
38
  isOpen: false,
37
39
  node: null,
38
40
  content: '',
41
+ parsedContent: null,
39
42
  workSummaries: [],
40
43
  expandedSummaries: false,
41
44
  tasks: null,
@@ -44,6 +47,7 @@ export const useSidePanelStore = create<SidePanelState>((set) => ({
44
47
  open: async (node: any) => {
45
48
  set({
46
49
  node,
50
+ parsedContent: null,
47
51
  workSummaries: [],
48
52
  expandedSummaries: false,
49
53
  tasks: null,
@@ -52,7 +56,8 @@ export const useSidePanelStore = create<SidePanelState>((set) => ({
52
56
 
53
57
  try {
54
58
  const detail = await apiClient.fetchNode(node.id);
55
- set({ content: detail.content, isOpen: true });
59
+ const parsed = parseNodeMarkdown(detail.content);
60
+ set({ content: detail.content, parsedContent: parsed, isOpen: true });
56
61
 
57
62
  if (node.type === 'feature' || node.id?.startsWith('feat_')) {
58
63
  try {