@assistkick/create 1.10.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 +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/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
@@ -0,0 +1,87 @@
1
+ /**
2
+ * ToolResultCard — displays a tool result as a collapsible accordion card
3
+ * in the chat stream. Collapsed by default, showing a brief summary.
4
+ * Expands to reveal the full tool output.
5
+ */
6
+
7
+ import { useState } from 'react';
8
+ import { ChevronDown, ChevronRight } from 'lucide-react';
9
+ import type { ToolResultBlock } from '../hooks/use_chat_stream';
10
+
11
+ interface ToolResultCardProps {
12
+ result: ToolResultBlock;
13
+ /** Tool name for display context (e.g. "Read", "Bash") */
14
+ toolName?: string;
15
+ }
16
+
17
+ /** Normalize content to a string — handles string, array-of-blocks, or other shapes. */
18
+ const contentToString = (content: ToolResultBlock['content']): string => {
19
+ if (!content) return '';
20
+ if (typeof content === 'string') return content;
21
+ if (Array.isArray(content)) {
22
+ return (content as Array<Record<string, unknown>>)
23
+ .filter(c => typeof c.text === 'string')
24
+ .map(c => c.text as string)
25
+ .join('\n');
26
+ }
27
+ return String(content);
28
+ };
29
+
30
+ /** Generate a brief summary of the result for the collapsed view. */
31
+ const summarizeResult = (result: ToolResultBlock, toolName?: string): string => {
32
+ const prefix = result.isError ? '✗ Error' : '✓ Result';
33
+ const label = toolName ? `${prefix} from ${toolName}` : prefix;
34
+
35
+ const text = contentToString(result.content);
36
+ if (!text) return `${label}: (empty)`;
37
+
38
+ // Show first meaningful line, truncated
39
+ const firstLine = text.split('\n').find(l => l.trim()) ?? '';
40
+ const MAX = 100;
41
+ const preview = firstLine.length > MAX ? `${firstLine.slice(0, MAX)}…` : firstLine;
42
+ return preview ? `${label}: ${preview}` : label;
43
+ };
44
+
45
+ export const ToolResultCard = ({ result, toolName }: ToolResultCardProps) => {
46
+ const [expanded, setExpanded] = useState(false);
47
+ const summary = summarizeResult(result, toolName);
48
+
49
+ return (
50
+ <div className="rounded-lg border border-edge bg-surface-alt overflow-hidden my-1">
51
+ <button
52
+ type="button"
53
+ onClick={() => setExpanded(prev => !prev)}
54
+ className="flex w-full items-center gap-2 px-3 py-2 text-left hover:bg-surface-raised/50 transition-colors cursor-pointer"
55
+ >
56
+ <span className="shrink-0 text-sm" aria-hidden="true">
57
+ {result.isError ? '❌' : '📤'}
58
+ </span>
59
+ <span
60
+ className={`text-[12px] font-mono flex-1 truncate ${
61
+ result.isError ? 'text-error' : 'text-content-secondary'
62
+ }`}
63
+ >
64
+ {summary}
65
+ </span>
66
+ {expanded
67
+ ? <ChevronDown size={13} className="text-content-muted shrink-0" />
68
+ : <ChevronRight size={13} className="text-content-muted shrink-0" />}
69
+ </button>
70
+
71
+ {expanded && (
72
+ <div className="border-t border-edge px-3 py-2">
73
+ <div className="text-[10px] font-mono text-content-muted uppercase tracking-wider mb-1">
74
+ {result.isError ? 'Error' : 'Output'}
75
+ </div>
76
+ <pre
77
+ className={`text-[12px] font-mono whitespace-pre-wrap break-words m-0 max-h-[400px] overflow-y-auto ${
78
+ result.isError ? 'text-error' : 'text-content-secondary'
79
+ }`}
80
+ >
81
+ {contentToString(result.content) || '(empty)'}
82
+ </pre>
83
+ </div>
84
+ )}
85
+ </div>
86
+ );
87
+ };
@@ -0,0 +1,149 @@
1
+ /**
2
+ * ToolUseCard — displays a Claude tool invocation as a collapsible card
3
+ * in the chat stream. Shows tool name and a brief summary when collapsed;
4
+ * expands to reveal the full tool input.
5
+ *
6
+ * Follows the design system: surface-alt background, edge borders,
7
+ * content-secondary text, monospace font at 13px.
8
+ */
9
+
10
+ import { useState } from 'react';
11
+ import { ChevronDown, ChevronRight } from 'lucide-react';
12
+ import { summarizeToolUse, toolIcon } from '../lib/tool_use_summary';
13
+ import { ToolDiffView } from './ToolDiffView';
14
+ import type { ToolResultBlock } from '../hooks/use_chat_stream';
15
+
16
+ interface ToolUseCardProps {
17
+ name: string;
18
+ input: Record<string, unknown>;
19
+ isStreaming?: boolean;
20
+ result?: ToolResultBlock;
21
+ }
22
+
23
+ /**
24
+ * Format tool input as indented JSON for the expanded view.
25
+ * Omits very large string values (e.g. file contents) to keep the card readable.
26
+ */
27
+ const formatInput = (input: Record<string, unknown>): string => {
28
+ const MAX_STRING_LEN = 500;
29
+
30
+ const replacer = (_key: string, value: unknown): unknown => {
31
+ if (typeof value === 'string' && value.length > MAX_STRING_LEN) {
32
+ return `${value.slice(0, MAX_STRING_LEN)}… (${value.length} chars)`;
33
+ }
34
+ return value;
35
+ };
36
+
37
+ return JSON.stringify(input, replacer, 2);
38
+ };
39
+
40
+ /** Normalize result content to a string — handles string, array-of-blocks, or other shapes. */
41
+ const contentToString = (content: ToolResultBlock['content']): string => {
42
+ if (!content) return '';
43
+ if (typeof content === 'string') return content;
44
+ if (Array.isArray(content)) {
45
+ return (content as Array<Record<string, unknown>>)
46
+ .filter(c => typeof c.text === 'string')
47
+ .map(c => c.text as string)
48
+ .join('\n');
49
+ }
50
+ return String(content);
51
+ };
52
+
53
+ type ViewTab = 'humanized' | 'raw';
54
+
55
+ const hasHumanizedView = (name: string): boolean => name === 'Edit' || name === 'Write';
56
+
57
+ export const ToolUseCard = ({ name, input, isStreaming, result }: ToolUseCardProps) => {
58
+ const [expanded, setExpanded] = useState(false);
59
+ const [viewTab, setViewTab] = useState<ViewTab>('humanized');
60
+ const summary = summarizeToolUse(name, input);
61
+ const icon = toolIcon(name);
62
+
63
+ // Build collapsed summary: include result status indicator
64
+ const resultIcon = result
65
+ ? result.isError ? '✗' : '✓'
66
+ : null;
67
+
68
+ return (
69
+ <div className="rounded-lg border border-edge bg-surface-alt overflow-hidden my-1">
70
+ <button
71
+ type="button"
72
+ onClick={() => setExpanded(prev => !prev)}
73
+ className="flex w-full items-center gap-2 px-3 py-2 text-left hover:bg-surface-raised/50 transition-colors cursor-pointer"
74
+ >
75
+ <span className="shrink-0 text-sm" aria-hidden="true">{icon}</span>
76
+ <span className="text-[12px] font-mono text-content-secondary flex-1 truncate">
77
+ {resultIcon && (
78
+ <span className={`mr-1.5 ${result?.isError ? 'text-error' : 'text-green-400'}`}>
79
+ {resultIcon}
80
+ </span>
81
+ )}
82
+ {summary}
83
+ </span>
84
+ {isStreaming && (
85
+ <span className="shrink-0 w-1.5 h-1.5 rounded-full bg-accent animate-pulse" />
86
+ )}
87
+ {expanded
88
+ ? <ChevronDown size={13} className="text-content-muted shrink-0" />
89
+ : <ChevronRight size={13} className="text-content-muted shrink-0" />}
90
+ </button>
91
+
92
+ {expanded && (
93
+ <div className="border-t border-edge">
94
+ {/* Tab bar for Edit/Write tools */}
95
+ {hasHumanizedView(name) && (
96
+ <div className="flex gap-0 border-b border-edge">
97
+ {(['humanized', 'raw'] as const).map(tab => (
98
+ <button
99
+ key={tab}
100
+ type="button"
101
+ onClick={() => setViewTab(tab)}
102
+ className={`px-3 py-1.5 text-[11px] font-mono uppercase tracking-wider transition-colors cursor-pointer ${
103
+ viewTab === tab
104
+ ? 'text-accent border-b-2 border-accent -mb-px'
105
+ : 'text-content-muted hover:text-content-secondary'
106
+ }`}
107
+ >
108
+ {tab === 'humanized' ? 'Humanized' : 'Raw'}
109
+ </button>
110
+ ))}
111
+ </div>
112
+ )}
113
+
114
+ {/* Tool input — humanized or raw */}
115
+ {hasHumanizedView(name) && viewTab === 'humanized' ? (
116
+ <div className="px-3 py-2">
117
+ <ToolDiffView toolName={name as 'Edit' | 'Write'} input={input} />
118
+ </div>
119
+ ) : (
120
+ <div className="px-3 py-2">
121
+ <div className="text-[10px] font-mono text-content-muted uppercase tracking-wider mb-1">
122
+ Input
123
+ </div>
124
+ <pre className="text-[12px] font-mono text-content-secondary whitespace-pre-wrap break-words m-0 max-h-[300px] overflow-y-auto">
125
+ {formatInput(input)}
126
+ </pre>
127
+ </div>
128
+ )}
129
+
130
+ {/* Tool output — shown inline when result is available */}
131
+ {result && (
132
+ <div className="border-t border-edge px-3 py-2">
133
+ <div className="text-[10px] font-mono text-content-muted uppercase tracking-wider mb-1">
134
+ {result.isError ? 'Error' : 'Output'}
135
+ </div>
136
+ <pre
137
+ className={`text-[12px] font-mono whitespace-pre-wrap break-words m-0 max-h-[400px] overflow-y-auto ${
138
+ result.isError ? 'text-error' : 'text-content-secondary'
139
+ }`}
140
+ >
141
+ {contentToString(result.content) || '(empty)'}
142
+ </pre>
143
+ </div>
144
+ )}
145
+ </div>
146
+ )}
147
+ </div>
148
+ );
149
+ };
@@ -1,21 +1,21 @@
1
1
  import React, { useCallback, useEffect } from 'react';
2
2
  import { useLocation, useNavigate } from 'react-router-dom';
3
3
  import {
4
- Columns3, MessageSquare, Network, ShieldCheck, Palette, Users, Bot, Workflow,
5
- FolderOpen, Maximize, Settings, Sun, Moon, Video,
4
+ Columns3, MessageSquare, MessagesSquare, Network, ShieldCheck, Palette, Users, Bot, Workflow,
5
+ FolderOpen, Maximize, Settings, Sun, Moon, Video, Terminal,
6
6
  } from 'lucide-react';
7
7
  import { NavBarSidekick } from './ds/NavBarSidekick';
8
8
  import type { NavItem } from './ds/NavBarSidekick';
9
9
  import { ProjectSelector } from './ProjectSelector';
10
10
  import { useProjectStore } from '../stores/useProjectStore';
11
+ import { usePreviewStore } from '../stores/usePreviewStore';
11
12
  import { useGraphStore } from '../stores/useGraphStore';
12
13
  import { useGraphUIStore } from '../stores/useGraphUIStore';
13
- import { useGitModalStore } from '../stores/useGitModalStore';
14
14
  import { useTheme } from '../hooks/useTheme';
15
15
  import { useAuth } from '../hooks/useAuth';
16
16
  import { apiClient } from '../api/client';
17
17
 
18
- const VALID_TABS = new Set(['graph', 'kanban', 'coherence', 'users', 'terminal', 'agents', 'workflows', 'design-system', 'files', 'videography']);
18
+ const VALID_TABS = new Set(['graph', 'kanban', 'coherence', 'users', 'terminal', 'chat', 'agents', 'workflows', 'design-system', 'files', 'videography']);
19
19
 
20
20
  function tabFromPath(pathname: string): string {
21
21
  const seg = pathname.replace(/^\//, '');
@@ -26,7 +26,8 @@ const ICON_PROPS = { size: 14, strokeWidth: 2 } as const;
26
26
 
27
27
  const TAB_ITEMS: NavItem[] = [
28
28
  { id: 'kanban', label: 'Kanban', icon: <Columns3 {...ICON_PROPS} />, description: 'Board view of features', href: '/kanban' },
29
- { id: 'terminal', label: 'Chat', icon: <MessageSquare {...ICON_PROPS} />, description: 'AI assistant terminal', href: '/terminal' },
29
+ { id: 'terminal', label: 'Terminal', icon: <Terminal {...ICON_PROPS} />, description: 'AI assistant terminal', href: '/terminal' },
30
+ { id: 'chat', label: 'Chat', icon: <MessagesSquare {...ICON_PROPS} />, description: 'Chat v2 web interface', href: '/chat' },
30
31
  { id: 'graph', label: 'Graph', icon: <Network {...ICON_PROPS} />, description: 'Knowledge graph visualization', href: '/graph' },
31
32
  { id: 'coherence', label: 'Coherence', icon: <ShieldCheck {...ICON_PROPS} />, description: 'Coherence analysis', href: '/coherence' },
32
33
  { id: 'agents', label: 'Agents', icon: <Bot {...ICON_PROPS} />, description: 'Manage agent prompts', href: '/agents' },
@@ -60,15 +61,27 @@ export function Toolbar() {
60
61
  const selectProject = useProjectStore((s) => s.selectProject);
61
62
  const createProject = useProjectStore((s) => s.createProject);
62
63
  const renameProject = useProjectStore((s) => s.renameProject);
64
+ const updatePreviewCommand = useProjectStore((s) => s.updatePreviewCommand);
63
65
  const archiveProject = useProjectStore((s) => s.archiveProject);
64
66
 
67
+ const previewApps = usePreviewStore((s) => s.apps);
68
+ const previewLoading = usePreviewStore((s) => s.loading);
69
+ const startPreview = usePreviewStore((s) => s.startPreview);
70
+ const stopPreview = usePreviewStore((s) => s.stopPreview);
71
+ const startPolling = usePreviewStore((s) => s.startPolling);
72
+ const stopPolling = usePreviewStore((s) => s.stopPolling);
73
+
74
+ // Start polling preview status on mount, stop on unmount
75
+ useEffect(() => {
76
+ startPolling();
77
+ return () => stopPolling();
78
+ }, [startPolling, stopPolling]);
79
+
65
80
  const graphData = useGraphStore((s) => s.graphData);
66
81
  const onFit = useGraphUIStore((s) => s.onFit);
67
82
  const settingsOpen = useGraphUIStore((s) => s.settingsOpen);
68
83
  const onSettingsToggle = useGraphUIStore((s) => s.onSettingsToggle);
69
84
 
70
- const openGitModal = useGitModalStore((s) => s.open);
71
-
72
85
  const completeness = graphData
73
86
  ? Math.round((graphData.nodes.reduce((acc: number, n: any) => acc + (n.completeness || 0), 0) / Math.max(graphData.nodes.length, 1)) * 100)
74
87
  : 0;
@@ -117,8 +130,12 @@ export function Toolbar() {
117
130
  onSelect={selectProject}
118
131
  onCreate={createProject}
119
132
  onRename={renameProject}
133
+ onUpdatePreviewCommand={updatePreviewCommand}
120
134
  onArchive={archiveProject}
121
- onOpenGitModal={openGitModal}
135
+ previewApps={previewApps}
136
+ onPreviewStart={startPreview}
137
+ onPreviewStop={stopPreview}
138
+ previewLoading={previewLoading}
122
139
  />
123
140
  }
124
141
  center={