@assistkick/create 1.6.0 → 1.8.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 (214) hide show
  1. package/package.json +2 -2
  2. package/templates/assistkick-product-system/.env.example +1 -0
  3. package/templates/assistkick-product-system/local.db +0 -0
  4. package/templates/assistkick-product-system/package.json +4 -2
  5. package/templates/assistkick-product-system/packages/backend/package.json +2 -0
  6. package/templates/assistkick-product-system/packages/backend/src/routes/agents.ts +165 -0
  7. package/templates/assistkick-product-system/packages/backend/src/routes/files.test.ts +358 -0
  8. package/templates/assistkick-product-system/packages/backend/src/routes/files.ts +356 -0
  9. package/templates/assistkick-product-system/packages/backend/src/routes/git.ts +96 -1
  10. package/templates/assistkick-product-system/packages/backend/src/routes/graph.ts +1 -0
  11. package/templates/assistkick-product-system/packages/backend/src/routes/kanban.ts +43 -4
  12. package/templates/assistkick-product-system/packages/backend/src/routes/pipeline.ts +200 -84
  13. package/templates/assistkick-product-system/packages/backend/src/routes/projects.ts +6 -3
  14. package/templates/assistkick-product-system/packages/backend/src/routes/terminal.ts +53 -17
  15. package/templates/assistkick-product-system/packages/backend/src/routes/video.ts +218 -0
  16. package/templates/assistkick-product-system/packages/backend/src/routes/workflow_groups.ts +119 -0
  17. package/templates/assistkick-product-system/packages/backend/src/routes/workflows.ts +154 -0
  18. package/templates/assistkick-product-system/packages/backend/src/server.ts +81 -9
  19. package/templates/assistkick-product-system/packages/backend/src/services/agent_service.test.ts +489 -0
  20. package/templates/assistkick-product-system/packages/backend/src/services/agent_service.ts +416 -0
  21. package/templates/assistkick-product-system/packages/backend/src/services/bundle_service.test.ts +189 -0
  22. package/templates/assistkick-product-system/packages/backend/src/services/bundle_service.ts +182 -0
  23. package/templates/assistkick-product-system/packages/backend/src/services/init.ts +28 -78
  24. package/templates/assistkick-product-system/packages/backend/src/services/project_service.test.ts +16 -0
  25. package/templates/assistkick-product-system/packages/backend/src/services/project_service.ts +73 -2
  26. package/templates/assistkick-product-system/packages/backend/src/services/project_workspace_service.test.ts +4 -4
  27. package/templates/assistkick-product-system/packages/backend/src/services/project_workspace_service.ts +87 -11
  28. package/templates/assistkick-product-system/packages/backend/src/services/pty_session_manager.test.ts +210 -69
  29. package/templates/assistkick-product-system/packages/backend/src/services/pty_session_manager.ts +210 -215
  30. package/templates/assistkick-product-system/packages/backend/src/services/ssh_key_service.test.ts +162 -0
  31. package/templates/assistkick-product-system/packages/backend/src/services/ssh_key_service.ts +148 -0
  32. package/templates/assistkick-product-system/packages/backend/src/services/terminal_ws_handler.ts +11 -5
  33. package/templates/assistkick-product-system/packages/backend/src/services/tts_service.test.ts +64 -0
  34. package/templates/assistkick-product-system/packages/backend/src/services/tts_service.ts +134 -0
  35. package/templates/assistkick-product-system/packages/backend/src/services/video_render_service.test.ts +256 -0
  36. package/templates/assistkick-product-system/packages/backend/src/services/video_render_service.ts +258 -0
  37. package/templates/assistkick-product-system/packages/backend/src/services/workflow_group_service.ts +106 -0
  38. package/templates/assistkick-product-system/packages/backend/src/services/workflow_service.test.ts +275 -0
  39. package/templates/assistkick-product-system/packages/backend/src/services/workflow_service.ts +222 -0
  40. package/templates/assistkick-product-system/packages/frontend/index.html +3 -0
  41. package/templates/assistkick-product-system/packages/frontend/package-lock.json +800 -11
  42. package/templates/assistkick-product-system/packages/frontend/package.json +11 -1
  43. package/templates/assistkick-product-system/packages/frontend/src/App.tsx +24 -7
  44. package/templates/assistkick-product-system/packages/frontend/src/api/client.ts +456 -16
  45. package/templates/assistkick-product-system/packages/frontend/src/api/client_files.test.ts +172 -0
  46. package/templates/assistkick-product-system/packages/frontend/src/api/client_video.test.ts +238 -0
  47. package/templates/assistkick-product-system/packages/frontend/src/components/AgentsView.tsx +307 -0
  48. package/templates/assistkick-product-system/packages/frontend/src/components/CoherenceView.tsx +82 -66
  49. package/templates/assistkick-product-system/packages/frontend/src/components/CompositionPlaceholder.tsx +97 -0
  50. package/templates/assistkick-product-system/packages/frontend/src/components/DesignSystemView.tsx +383 -0
  51. package/templates/assistkick-product-system/packages/frontend/src/components/EditorTabBar.tsx +57 -0
  52. package/templates/assistkick-product-system/packages/frontend/src/components/FileTree.tsx +313 -0
  53. package/templates/assistkick-product-system/packages/frontend/src/components/FileTreeContextMenu.tsx +61 -0
  54. package/templates/assistkick-product-system/packages/frontend/src/components/FileTreeInlineInput.tsx +73 -0
  55. package/templates/assistkick-product-system/packages/frontend/src/components/FilesView.tsx +404 -0
  56. package/templates/assistkick-product-system/packages/frontend/src/components/GitRepoModal.tsx +193 -64
  57. package/templates/assistkick-product-system/packages/frontend/src/components/GraphLegend.tsx +71 -73
  58. package/templates/assistkick-product-system/packages/frontend/src/components/GraphSettings.tsx +8 -8
  59. package/templates/assistkick-product-system/packages/frontend/src/components/GraphView.tsx +1 -1
  60. package/templates/assistkick-product-system/packages/frontend/src/components/InviteUserDialog.tsx +15 -11
  61. package/templates/assistkick-product-system/packages/frontend/src/components/KanbanView.tsx +226 -291
  62. package/templates/assistkick-product-system/packages/frontend/src/components/LoginPage.tsx +14 -14
  63. package/templates/assistkick-product-system/packages/frontend/src/components/ProjectSelector.tsx +54 -33
  64. package/templates/assistkick-product-system/packages/frontend/src/components/QaIssueSheet.tsx +40 -66
  65. package/templates/assistkick-product-system/packages/frontend/src/components/SidePanel.tsx +55 -115
  66. package/templates/assistkick-product-system/packages/frontend/src/components/TerminalView.tsx +121 -52
  67. package/templates/assistkick-product-system/packages/frontend/src/components/Toolbar.tsx +155 -77
  68. package/templates/assistkick-product-system/packages/frontend/src/components/UsersView.tsx +52 -52
  69. package/templates/assistkick-product-system/packages/frontend/src/components/VideoGallery.tsx +313 -0
  70. package/templates/assistkick-product-system/packages/frontend/src/components/VideographyView.tsx +250 -0
  71. package/templates/assistkick-product-system/packages/frontend/src/components/WorkflowsView.tsx +474 -0
  72. package/templates/assistkick-product-system/packages/frontend/src/components/ds/AccentBorderList.tsx +53 -0
  73. package/templates/assistkick-product-system/packages/frontend/src/components/ds/Button.tsx +87 -0
  74. package/templates/assistkick-product-system/packages/frontend/src/components/ds/ButtonGroup.tsx +29 -0
  75. package/templates/assistkick-product-system/packages/frontend/src/components/ds/ButtonShowcase.tsx +221 -0
  76. package/templates/assistkick-product-system/packages/frontend/src/components/ds/CardGlass.tsx +141 -0
  77. package/templates/assistkick-product-system/packages/frontend/src/components/ds/CompletionRing.tsx +30 -0
  78. package/templates/assistkick-product-system/packages/frontend/src/components/ds/ContentCard.tsx +34 -0
  79. package/templates/assistkick-product-system/packages/frontend/src/components/ds/IconButton.tsx +74 -0
  80. package/templates/assistkick-product-system/packages/frontend/src/components/ds/KanbanCard.tsx +270 -0
  81. package/templates/assistkick-product-system/packages/frontend/src/components/ds/KanbanCardShowcase.tsx +37 -0
  82. package/templates/assistkick-product-system/packages/frontend/src/components/ds/Kbd.tsx +11 -0
  83. package/templates/assistkick-product-system/packages/frontend/src/components/ds/KindBadge.tsx +21 -0
  84. package/templates/assistkick-product-system/packages/frontend/src/components/ds/NavBarSidekick.tsx +207 -0
  85. package/templates/assistkick-product-system/packages/frontend/src/components/ds/SidePanelShowcase.tsx +370 -0
  86. package/templates/assistkick-product-system/packages/frontend/src/components/ds/SideSheet.tsx +64 -0
  87. package/templates/assistkick-product-system/packages/frontend/src/components/ds/StatusDot.tsx +18 -0
  88. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/CheckCardPositionNode.tsx +36 -0
  89. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/CheckCycleCountNode.tsx +60 -0
  90. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/EndNode.tsx +42 -0
  91. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/GroupNode.tsx +189 -0
  92. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/NodePalette.tsx +123 -0
  93. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/RunAgentNode.tsx +51 -0
  94. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/SetCardMetadataNode.tsx +53 -0
  95. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/StartNode.tsx +18 -0
  96. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/TransitionCardNode.tsx +59 -0
  97. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/WorkflowCanvas.tsx +335 -0
  98. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/WorkflowMonitorModal.tsx +634 -0
  99. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/autoLayout.ts +103 -0
  100. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/edgeColors.ts +35 -0
  101. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/monitor_nodes.tsx +208 -0
  102. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/workflow_types.test.ts +119 -0
  103. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/workflow_types.ts +107 -0
  104. package/templates/assistkick-product-system/packages/frontend/src/constants/graph.ts +13 -11
  105. package/templates/assistkick-product-system/packages/frontend/src/hooks/useAutoSave.ts +75 -0
  106. package/templates/assistkick-product-system/packages/frontend/src/hooks/useGraph.ts +6 -21
  107. package/templates/assistkick-product-system/packages/frontend/src/hooks/useProjects.ts +15 -80
  108. package/templates/assistkick-product-system/packages/frontend/src/hooks/useToast.tsx +16 -3
  109. package/templates/assistkick-product-system/packages/frontend/src/pages/accept_invitation_page.tsx +30 -27
  110. package/templates/assistkick-product-system/packages/frontend/src/pages/forgot_password_page.tsx +18 -15
  111. package/templates/assistkick-product-system/packages/frontend/src/pages/register_page.tsx +21 -18
  112. package/templates/assistkick-product-system/packages/frontend/src/pages/reset_password_page.tsx +28 -25
  113. package/templates/assistkick-product-system/packages/frontend/src/routes/AgentsRoute.tsx +6 -0
  114. package/templates/assistkick-product-system/packages/frontend/src/routes/CoherenceRoute.tsx +19 -0
  115. package/templates/assistkick-product-system/packages/frontend/src/routes/DashboardLayout.tsx +54 -0
  116. package/templates/assistkick-product-system/packages/frontend/src/routes/DesignSystemRoute.tsx +6 -0
  117. package/templates/assistkick-product-system/packages/frontend/src/routes/FilesRoute.tsx +13 -0
  118. package/templates/assistkick-product-system/packages/frontend/src/routes/GraphRoute.tsx +93 -0
  119. package/templates/assistkick-product-system/packages/frontend/src/routes/KanbanRoute.tsx +30 -0
  120. package/templates/assistkick-product-system/packages/frontend/src/routes/TerminalRoute.tsx +9 -0
  121. package/templates/assistkick-product-system/packages/frontend/src/routes/UsersRoute.tsx +6 -0
  122. package/templates/assistkick-product-system/packages/frontend/src/routes/VideographyRoute.tsx +13 -0
  123. package/templates/assistkick-product-system/packages/frontend/src/routes/WorkflowsRoute.tsx +6 -0
  124. package/templates/assistkick-product-system/packages/frontend/src/stores/useGitModalStore.ts +14 -0
  125. package/templates/assistkick-product-system/packages/frontend/src/stores/useGraphStore.ts +36 -0
  126. package/templates/assistkick-product-system/packages/frontend/src/stores/useGraphUIStore.ts +25 -0
  127. package/templates/assistkick-product-system/packages/frontend/src/stores/useProjectStore.ts +90 -0
  128. package/templates/assistkick-product-system/packages/frontend/src/stores/useQaSheetStore.ts +27 -0
  129. package/templates/assistkick-product-system/packages/frontend/src/stores/useSidePanelStore.ts +76 -0
  130. package/templates/assistkick-product-system/packages/frontend/src/styles/index.css +336 -3632
  131. package/templates/assistkick-product-system/packages/frontend/src/utils/auto_save_service.test.ts +167 -0
  132. package/templates/assistkick-product-system/packages/frontend/src/utils/auto_save_service.ts +101 -0
  133. package/templates/assistkick-product-system/packages/frontend/src/utils/composition_matcher.test.ts +42 -0
  134. package/templates/assistkick-product-system/packages/frontend/src/utils/composition_matcher.ts +17 -0
  135. package/templates/assistkick-product-system/packages/frontend/src/utils/file_utils.test.ts +145 -0
  136. package/templates/assistkick-product-system/packages/frontend/src/utils/file_utils.ts +42 -0
  137. package/templates/assistkick-product-system/packages/frontend/src/utils/task_status.test.ts +4 -10
  138. package/templates/assistkick-product-system/packages/frontend/src/utils/task_status.ts +19 -1
  139. package/templates/assistkick-product-system/packages/frontend/vite.config.ts +7 -1
  140. package/templates/assistkick-product-system/packages/shared/db/local.db +0 -0
  141. package/templates/assistkick-product-system/packages/shared/db/migrations/0004_tidy_matthew_murdock.sql +9 -0
  142. package/templates/assistkick-product-system/packages/shared/db/migrations/0005_mysterious_falcon.sql +692 -0
  143. package/templates/assistkick-product-system/packages/shared/db/migrations/0006_next_venom.sql +9 -0
  144. package/templates/assistkick-product-system/packages/shared/db/migrations/0007_deep_barracuda.sql +39 -0
  145. package/templates/assistkick-product-system/packages/shared/db/migrations/0008_puzzling_hannibal_king.sql +1 -0
  146. package/templates/assistkick-product-system/packages/shared/db/migrations/0009_amused_beast.sql +8 -0
  147. package/templates/assistkick-product-system/packages/shared/db/migrations/0010_spotty_moira_mactaggert.sql +9 -0
  148. package/templates/assistkick-product-system/packages/shared/db/migrations/0011_goofy_snowbird.sql +3 -0
  149. package/templates/assistkick-product-system/packages/shared/db/migrations/0011_supreme_doctor_octopus.sql +3 -0
  150. package/templates/assistkick-product-system/packages/shared/db/migrations/0013_reflective_prowler.sql +15 -0
  151. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0004_snapshot.json +921 -0
  152. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0005_snapshot.json +1042 -0
  153. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0006_snapshot.json +1101 -0
  154. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0007_snapshot.json +1336 -0
  155. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0008_snapshot.json +1275 -0
  156. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0009_snapshot.json +1327 -0
  157. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0010_snapshot.json +1393 -0
  158. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0011_snapshot.json +1436 -0
  159. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0013_snapshot.json +1538 -0
  160. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/_journal.json +70 -0
  161. package/templates/assistkick-product-system/packages/shared/db/schema.ts +113 -0
  162. package/templates/assistkick-product-system/packages/shared/lib/claude-service.ts +32 -7
  163. package/templates/assistkick-product-system/packages/shared/lib/constants.ts +9 -0
  164. package/templates/assistkick-product-system/packages/shared/lib/git_workflow.ts +12 -4
  165. package/templates/assistkick-product-system/packages/shared/lib/graph.ts +16 -5
  166. package/templates/assistkick-product-system/packages/shared/lib/workflow_engine.test.ts +1753 -0
  167. package/templates/assistkick-product-system/packages/shared/lib/workflow_engine.ts +1281 -0
  168. package/templates/assistkick-product-system/packages/shared/lib/workflow_orchestrator.ts +211 -0
  169. package/templates/assistkick-product-system/packages/shared/tools/add_node.test.ts +43 -0
  170. package/templates/assistkick-product-system/packages/shared/tools/add_node.ts +13 -2
  171. package/templates/assistkick-product-system/packages/shared/tools/get_kanban.ts +1 -1
  172. package/templates/assistkick-product-system/packages/shared/tools/migrate_epics.test.ts +226 -0
  173. package/templates/assistkick-product-system/packages/shared/tools/migrate_epics.ts +251 -0
  174. package/templates/assistkick-product-system/packages/shared/tools/update_node.ts +2 -2
  175. package/templates/assistkick-product-system/packages/shared/utils/hello_workflow.test.ts +10 -0
  176. package/templates/assistkick-product-system/packages/shared/utils/hello_workflow.ts +6 -0
  177. package/templates/assistkick-product-system/packages/video/Root.tsx +85 -0
  178. package/templates/assistkick-product-system/packages/video/components/email_scene.tsx +231 -0
  179. package/templates/assistkick-product-system/packages/video/components/outro_scene.tsx +153 -0
  180. package/templates/assistkick-product-system/packages/video/components/part_divider.tsx +90 -0
  181. package/templates/assistkick-product-system/packages/video/components/scene.tsx +226 -0
  182. package/templates/assistkick-product-system/packages/video/components/theme.ts +22 -0
  183. package/templates/assistkick-product-system/packages/video/components/title_scene.tsx +169 -0
  184. package/templates/assistkick-product-system/packages/video/components/video_split_layout.tsx +84 -0
  185. package/templates/assistkick-product-system/packages/video/compositions/.gitkeep +0 -0
  186. package/templates/assistkick-product-system/packages/video/index.ts +4 -0
  187. package/templates/assistkick-product-system/packages/video/package.json +28 -0
  188. package/templates/assistkick-product-system/packages/video/remotion.config.ts +11 -0
  189. package/templates/assistkick-product-system/packages/video/scripts/process_script.test.ts +326 -0
  190. package/templates/assistkick-product-system/packages/video/scripts/process_script.ts +630 -0
  191. package/templates/assistkick-product-system/packages/video/style.css +1 -0
  192. package/templates/assistkick-product-system/packages/video/tsconfig.json +18 -0
  193. package/templates/assistkick-product-system/tests/graph_legend.test.ts +2 -1
  194. package/templates/assistkick-product-system/tests/video_render_service.test.ts +179 -0
  195. package/templates/assistkick-product-system/tests/web_terminal.test.ts +219 -455
  196. package/templates/assistkick-product-system/tests/workflow_integration.test.ts +341 -0
  197. package/templates/skills/assistkick-bootstrap/SKILL.md +3 -3
  198. package/templates/skills/assistkick-code-reviewer/SKILL.md +2 -2
  199. package/templates/skills/assistkick-debugger/SKILL.md +2 -2
  200. package/templates/skills/assistkick-developer/SKILL.md +6 -3
  201. package/templates/skills/assistkick-developer/references/react_development_guidelines.md +225 -0
  202. package/templates/skills/assistkick-interview/SKILL.md +2 -2
  203. package/templates/skills/product-system/graph.json +1890 -0
  204. package/templates/skills/product-system/kanban.json +304 -0
  205. package/templates/skills/product-system/nodes/comp_001.md +56 -0
  206. package/templates/skills/product-system/nodes/comp_002.md +57 -0
  207. package/templates/skills/product-system/nodes/data_001.md +51 -0
  208. package/templates/skills/product-system/nodes/data_002.md +40 -0
  209. package/templates/skills/product-system/nodes/data_004.md +38 -0
  210. package/templates/skills/product-system/nodes/dec_001.md +34 -0
  211. package/templates/skills/product-system/nodes/dec_016.md +32 -0
  212. package/templates/skills/product-system/nodes/feat_008.md +30 -0
  213. package/templates/skills/video-composition-agent/SKILL.md +232 -0
  214. package/templates/skills/video-script-writer/SKILL.md +136 -0
@@ -1,86 +1,164 @@
1
- import React from 'react';
1
+ import React, { useCallback, useEffect } from 'react';
2
+ import { useLocation, useNavigate } from 'react-router-dom';
3
+ import {
4
+ Columns3, MessageSquare, Network, ShieldCheck, Palette, Users, Bot, Workflow,
5
+ FolderOpen, Maximize, Settings, Sun, Moon, Video,
6
+ } from 'lucide-react';
7
+ import { NavBarSidekick } from './ds/NavBarSidekick';
8
+ import type { NavItem } from './ds/NavBarSidekick';
2
9
  import { ProjectSelector } from './ProjectSelector';
3
- import type { Project } from '../hooks/useProjects';
4
-
5
- interface ToolbarProps {
6
- activeTab: string;
7
- onTabChange: (tab: string) => void;
8
- completeness: number;
9
- onFit: () => void;
10
- onSettingsToggle: () => void;
11
- settingsOpen: boolean;
12
- theme: string;
13
- onThemeToggle: () => void;
14
- isAdmin?: boolean;
15
- onLogout: () => void;
16
- projects: Project[];
17
- selectedProjectId: string | null;
18
- onProjectSelect: (id: string) => void;
19
- onProjectCreate: (name: string) => Promise<any>;
20
- onProjectRename: (id: string, name: string) => Promise<void>;
21
- onProjectArchive: (id: string) => Promise<void>;
22
- onOpenGitModal?: (project: Project) => void;
10
+ import { useProjectStore } from '../stores/useProjectStore';
11
+ import { useGraphStore } from '../stores/useGraphStore';
12
+ import { useGraphUIStore } from '../stores/useGraphUIStore';
13
+ import { useGitModalStore } from '../stores/useGitModalStore';
14
+ import { useTheme } from '../hooks/useTheme';
15
+ import { useAuth } from '../hooks/useAuth';
16
+ import { apiClient } from '../api/client';
17
+
18
+ const VALID_TABS = new Set(['graph', 'kanban', 'coherence', 'users', 'terminal', 'agents', 'workflows', 'design-system', 'files', 'videography']);
19
+
20
+ function tabFromPath(pathname: string): string {
21
+ const seg = pathname.replace(/^\//, '');
22
+ return VALID_TABS.has(seg) ? seg : 'kanban';
23
23
  }
24
24
 
25
- export function Toolbar({
26
- activeTab, onTabChange, completeness, onFit,
27
- onSettingsToggle, settingsOpen, theme, onThemeToggle, isAdmin, onLogout,
28
- projects, selectedProjectId, onProjectSelect, onProjectCreate, onProjectRename, onProjectArchive, onOpenGitModal,
29
- }: ToolbarProps) {
30
- const tabs = ['kanban', 'terminal', 'graph', 'coherence'];
31
- if (isAdmin) {
32
- tabs.push('users');
33
- }
25
+ const ICON_PROPS = { size: 14, strokeWidth: 2 } as const;
26
+
27
+ const TAB_ITEMS: NavItem[] = [
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' },
30
+ { id: 'graph', label: 'Graph', icon: <Network {...ICON_PROPS} />, description: 'Knowledge graph visualization', href: '/graph' },
31
+ { id: 'coherence', label: 'Coherence', icon: <ShieldCheck {...ICON_PROPS} />, description: 'Coherence analysis', href: '/coherence' },
32
+ { id: 'agents', label: 'Agents', icon: <Bot {...ICON_PROPS} />, description: 'Manage agent prompts', href: '/agents' },
33
+ { id: 'workflows', label: 'Workflows', icon: <Workflow {...ICON_PROPS} />, description: 'Visual workflow builder', href: '/workflows' },
34
+ { id: 'files', label: 'Files', icon: <FolderOpen {...ICON_PROPS} />, description: 'Browse and edit project files', href: '/files' },
35
+ { id: 'design-system', label: 'Design System', icon: <Palette {...ICON_PROPS} />, description: 'Living style guide', href: '/design-system' },
36
+ ];
37
+
38
+ const VIDEOGRAPHY_ITEM: NavItem = { id: 'videography', label: 'Videography', icon: <Video {...ICON_PROPS} />, description: 'Video production pipeline', href: '/videography' };
39
+ const ADMIN_ITEM: NavItem = { id: 'users', label: 'Users', icon: <Users {...ICON_PROPS} />, description: 'User management', href: '/users' };
40
+
41
+ const iconBtnClass = (active?: boolean) => [
42
+ 'flex h-8 w-8 items-center justify-center rounded-lg border',
43
+ 'transition-all duration-150 cursor-pointer outline-none',
44
+ active
45
+ ? 'border-accent/40 bg-accent/10 text-accent'
46
+ : 'border-edge text-content-muted hover:border-content/20 hover:text-content',
47
+ ].join(' ');
48
+
49
+ export function Toolbar() {
50
+ const navigate = useNavigate();
51
+ const location = useLocation();
52
+ const activeTab = tabFromPath(location.pathname);
53
+
54
+ const { theme, toggleTheme } = useTheme();
55
+ const { user } = useAuth();
56
+ const isAdmin = user?.role === 'admin';
57
+
58
+ const projects = useProjectStore((s) => s.projects);
59
+ const selectedProjectId = useProjectStore((s) => s.selectedProjectId);
60
+ const selectProject = useProjectStore((s) => s.selectProject);
61
+ const createProject = useProjectStore((s) => s.createProject);
62
+ const renameProject = useProjectStore((s) => s.renameProject);
63
+ const archiveProject = useProjectStore((s) => s.archiveProject);
64
+
65
+ const graphData = useGraphStore((s) => s.graphData);
66
+ const onFit = useGraphUIStore((s) => s.onFit);
67
+ const settingsOpen = useGraphUIStore((s) => s.settingsOpen);
68
+ const onSettingsToggle = useGraphUIStore((s) => s.onSettingsToggle);
69
+
70
+ const openGitModal = useGitModalStore((s) => s.open);
71
+
72
+ const completeness = graphData
73
+ ? Math.round((graphData.nodes.reduce((acc: number, n: any) => acc + (n.completeness || 0), 0) / Math.max(graphData.nodes.length, 1)) * 100)
74
+ : 0;
75
+
76
+ const selectedProject = projects.find(p => p.id === selectedProjectId);
77
+ const isVideoProject = selectedProject?.type === 'video';
78
+
79
+ const items = [
80
+ ...TAB_ITEMS,
81
+ ...(isVideoProject ? [VIDEOGRAPHY_ITEM] : []),
82
+ ...(isAdmin ? [ADMIN_ITEM] : []),
83
+ ];
84
+
85
+ const handleLogout = useCallback(async () => {
86
+ try {
87
+ await apiClient.logout();
88
+ } catch {
89
+ // ignore
90
+ }
91
+ navigate('/login', { replace: true });
92
+ }, [navigate]);
34
93
 
35
- const tabLabels: Record<string, string> = { terminal: 'Chat' };
94
+ // Global '/' shortcut the NavBarSidekick handles its own cmd palette UI,
95
+ // but we wire the keyboard shortcut at the toolbar level for page-wide reach
96
+ useEffect(() => {
97
+ const handler = (e: KeyboardEvent) => {
98
+ if (e.key === '/' && !(e.target instanceof HTMLInputElement) && !(e.target instanceof HTMLTextAreaElement)) {
99
+ // Let the NavBarSidekick's own button handle it via a simulated click
100
+ const btn = document.querySelector('[data-cmd-trigger]') as HTMLButtonElement | null;
101
+ if (btn) { e.preventDefault(); btn.click(); }
102
+ }
103
+ };
104
+ document.addEventListener('keydown', handler);
105
+ return () => document.removeEventListener('keydown', handler);
106
+ }, []);
36
107
 
37
108
  return (
38
- <div className="toolbar">
39
- <div className="tab-bar">
40
- <ProjectSelector
41
- projects={projects}
42
- selectedProjectId={selectedProjectId}
43
- onSelect={onProjectSelect}
44
- onCreate={onProjectCreate}
45
- onRename={onProjectRename}
46
- onArchive={onProjectArchive}
47
- onOpenGitModal={onOpenGitModal}
48
- />
49
- {tabs.map(tab => (
50
- <button
51
- key={tab}
52
- className={`tab-btn${activeTab === tab ? ' active' : ''}`}
53
- onClick={() => onTabChange(tab)}
54
- >
55
- {tabLabels[tab] || tab.charAt(0).toUpperCase() + tab.slice(1)}
56
- </button>
57
- ))}
58
- </div>
59
-
60
- <div className="toolbar-spacer" />
61
-
62
- <div className="completeness-bar">
63
- <span>Completeness</span>
64
- <div className="completeness-track">
65
- <div className="completeness-fill" style={{ width: `${completeness}%` }} />
66
- </div>
67
- <span>{completeness}%</span>
68
- </div>
69
-
70
- <button className="toolbar-btn" onClick={onFit} title="Fit graph to viewport">Fit</button>
71
- <button
72
- className={`toolbar-btn settings-gear-btn${settingsOpen ? ' active' : ''}`}
73
- onClick={onSettingsToggle}
74
- title="Graph settings"
75
- >
76
- &#9881;
77
- </button>
78
- <button className="theme-toggle" onClick={onThemeToggle} title="Toggle theme">
79
- {theme === 'dark' ? '\u2600' : '\u263E'}
80
- </button>
81
- <button className="toolbar-btn logout-btn" onClick={onLogout} title="Logout">
82
- Logout
83
- </button>
109
+ <div className="border-b border-edge">
110
+ <NavBarSidekick
111
+ items={items}
112
+ activeId={activeTab}
113
+ brand={
114
+ <ProjectSelector
115
+ projects={projects}
116
+ selectedProjectId={selectedProjectId}
117
+ onSelect={selectProject}
118
+ onCreate={createProject}
119
+ onRename={renameProject}
120
+ onArchive={archiveProject}
121
+ onOpenGitModal={openGitModal}
122
+ />
123
+ }
124
+ center={
125
+ <div className="flex items-center justify-end gap-2 text-[11px] text-content-muted">
126
+ <span className="hidden lg:inline uppercase tracking-wider font-medium">Completeness</span>
127
+ <div className="w-20 h-1.5 rounded-full bg-completeness-bg overflow-hidden">
128
+ <div
129
+ className="h-full rounded-full bg-completeness-fill transition-all duration-300"
130
+ style={{ width: `${completeness}%` }}
131
+ />
132
+ </div>
133
+ <span className="font-mono text-[11px] text-content-secondary w-8 text-right">{completeness}%</span>
134
+ </div>
135
+ }
136
+ actions={
137
+ <div className="flex items-center gap-1.5">
138
+ <button onClick={() => onFit?.()} title="Fit graph to viewport" className={iconBtnClass()}>
139
+ <Maximize size={14} strokeWidth={2} />
140
+ </button>
141
+ <button onClick={onSettingsToggle} title="Graph settings" className={iconBtnClass(settingsOpen)}>
142
+ <Settings size={14} strokeWidth={2} />
143
+ </button>
144
+ <div className="h-5 w-px bg-edge mx-1" />
145
+ </div>
146
+ }
147
+ trailing={
148
+ <div className="flex items-center gap-1.5">
149
+ <button onClick={toggleTheme} title="Toggle theme" className={iconBtnClass()}>
150
+ {theme === 'dark' ? <Sun size={14} strokeWidth={2} /> : <Moon size={14} strokeWidth={2} />}
151
+ </button>
152
+ <button
153
+ onClick={handleLogout}
154
+ title="Logout"
155
+ className="flex h-8 w-8 items-center justify-center rounded-full bg-accent text-[11px] font-bold text-surface cursor-pointer outline-none hover:opacity-90 transition-opacity"
156
+ >
157
+ {user?.email?.slice(0, 2).toUpperCase() || 'U'}
158
+ </button>
159
+ </div>
160
+ }
161
+ />
84
162
  </div>
85
163
  );
86
164
  }
@@ -110,43 +110,43 @@ export function UsersView({ visible }: UsersViewProps) {
110
110
  if (!visible) return null;
111
111
 
112
112
  return (
113
- <div className="users-view">
114
- <div className="users-view-header">
115
- <h2>User Management</h2>
116
- <button className="users-invite-btn" onClick={() => setInviteOpen(true)}>
113
+ <div className="p-6 max-w-[900px] mx-auto text-content">
114
+ <div className="flex justify-between items-center mb-5">
115
+ <h2 className="text-xl font-semibold">User Management</h2>
116
+ <button className="bg-accent text-white border-none rounded-md px-4 py-2 text-sm cursor-pointer font-mono hover:opacity-90" onClick={() => setInviteOpen(true)}>
117
117
  + Invite User
118
118
  </button>
119
119
  </div>
120
120
 
121
- {error && <div className="users-error">{error}<button className="users-error-dismiss" onClick={() => setError('')}>&times;</button></div>}
121
+ {error && <div className="bg-[rgba(255,107,107,0.15)] text-error px-3.5 py-2.5 rounded-md mb-4 text-sm flex justify-between items-center">{error}<button className="bg-none border-none text-error text-lg cursor-pointer px-1" onClick={() => setError('')}>&times;</button></div>}
122
122
 
123
123
  {loading ? (
124
- <div className="users-loading">Loading...</div>
124
+ <div className="text-content-secondary py-10 text-center">Loading...</div>
125
125
  ) : (
126
126
  <>
127
- <section className="users-section">
128
- <h3>Registered Users ({users.length})</h3>
129
- <table className="users-table">
127
+ <section className="mb-7">
128
+ <h3 className="text-[15px] font-semibold text-content-secondary mb-2.5">Registered Users ({users.length})</h3>
129
+ <table className="w-full border-collapse text-sm font-mono">
130
130
  <thead>
131
131
  <tr>
132
- <th>Email</th>
133
- <th>Role</th>
134
- <th>Created</th>
135
- <th></th>
132
+ <th className="text-left px-3 py-2 border-b border-edge text-content-muted font-medium text-xs uppercase tracking-wide">Email</th>
133
+ <th className="text-left px-3 py-2 border-b border-edge text-content-muted font-medium text-xs uppercase tracking-wide">Role</th>
134
+ <th className="text-left px-3 py-2 border-b border-edge text-content-muted font-medium text-xs uppercase tracking-wide">Created</th>
135
+ <th className="text-left px-3 py-2 border-b border-edge text-content-muted font-medium text-xs uppercase tracking-wide"></th>
136
136
  </tr>
137
137
  </thead>
138
138
  <tbody>
139
139
  {users.map(u => (
140
- <tr key={u.id} className={u.id === currentUser?.id ? 'users-current-row' : ''}>
141
- <td>{u.email}</td>
142
- <td><span className={`users-role-badge users-role-${u.role}`}>{u.role}</span></td>
143
- <td>{formatDate(u.createdAt)}</td>
144
- <td>
140
+ <tr key={u.id} className={`hover:bg-surface-raised ${u.id === currentUser?.id ? 'bg-surface-alt' : ''}`}>
141
+ <td className="px-3 py-2.5 border-b border-edge text-content">{u.email}</td>
142
+ <td className="px-3 py-2.5 border-b border-edge text-content"><span className={`inline-block px-2 py-0.5 rounded text-xs font-medium ${u.role === 'admin' ? 'bg-[rgba(77,171,247,0.15)] text-accent' : 'bg-surface-raised text-content-secondary'}`}>{u.role}</span></td>
143
+ <td className="px-3 py-2.5 border-b border-edge text-content">{formatDate(u.createdAt)}</td>
144
+ <td className="px-3 py-2.5 border-b border-edge text-content">
145
145
  {u.id === currentUser?.id ? (
146
- <span className="users-you-badge">you</span>
146
+ <span className="text-xs text-content-muted italic">you</span>
147
147
  ) : (
148
148
  <button
149
- className="users-delete-btn"
149
+ className="bg-none border border-edge text-error rounded px-2.5 py-1 text-xs cursor-pointer font-mono hover:bg-[rgba(255,107,107,0.1)] hover:border-error disabled:opacity-50 disabled:cursor-not-allowed"
150
150
  onClick={() => handleDeleteUser(u.id, u.email)}
151
151
  disabled={deletingId === u.id}
152
152
  title={`Delete ${u.email}`}
@@ -161,31 +161,31 @@ export function UsersView({ visible }: UsersViewProps) {
161
161
  </table>
162
162
  </section>
163
163
 
164
- <section className="users-section">
165
- <h3>Pending Invitations ({pendingInvitations.length})</h3>
164
+ <section className="mb-7">
165
+ <h3 className="text-[15px] font-semibold text-content-secondary mb-2.5">Pending Invitations ({pendingInvitations.length})</h3>
166
166
  {pendingInvitations.length === 0 ? (
167
- <p className="users-empty">No pending invitations.</p>
167
+ <p className="text-content-muted text-sm py-3">No pending invitations.</p>
168
168
  ) : (
169
- <table className="users-table">
169
+ <table className="w-full border-collapse text-sm font-mono">
170
170
  <thead>
171
171
  <tr>
172
- <th>Email</th>
173
- <th>Invited By</th>
174
- <th>Sent</th>
175
- <th>Expires</th>
176
- <th></th>
172
+ <th className="text-left px-3 py-2 border-b border-edge text-content-muted font-medium text-xs uppercase tracking-wide">Email</th>
173
+ <th className="text-left px-3 py-2 border-b border-edge text-content-muted font-medium text-xs uppercase tracking-wide">Invited By</th>
174
+ <th className="text-left px-3 py-2 border-b border-edge text-content-muted font-medium text-xs uppercase tracking-wide">Sent</th>
175
+ <th className="text-left px-3 py-2 border-b border-edge text-content-muted font-medium text-xs uppercase tracking-wide">Expires</th>
176
+ <th className="text-left px-3 py-2 border-b border-edge text-content-muted font-medium text-xs uppercase tracking-wide"></th>
177
177
  </tr>
178
178
  </thead>
179
179
  <tbody>
180
180
  {pendingInvitations.map(inv => (
181
- <tr key={inv.id}>
182
- <td>{inv.email}</td>
183
- <td>{inv.invitedByEmail}</td>
184
- <td>{formatDate(inv.createdAt)}</td>
185
- <td>{formatDate(inv.expiresAt)}</td>
186
- <td>
181
+ <tr key={inv.id} className="hover:bg-surface-raised">
182
+ <td className="px-3 py-2.5 border-b border-edge text-content">{inv.email}</td>
183
+ <td className="px-3 py-2.5 border-b border-edge text-content">{inv.invitedByEmail}</td>
184
+ <td className="px-3 py-2.5 border-b border-edge text-content">{formatDate(inv.createdAt)}</td>
185
+ <td className="px-3 py-2.5 border-b border-edge text-content">{formatDate(inv.expiresAt)}</td>
186
+ <td className="px-3 py-2.5 border-b border-edge text-content">
187
187
  <button
188
- className="users-delete-btn"
188
+ className="bg-none border border-edge text-error rounded px-2.5 py-1 text-xs cursor-pointer font-mono hover:bg-[rgba(255,107,107,0.1)] hover:border-error disabled:opacity-50 disabled:cursor-not-allowed"
189
189
  onClick={() => handleDeleteInvitation(inv.id, inv.email)}
190
190
  disabled={deletingId === inv.id}
191
191
  title={`Cancel invitation for ${inv.email}`}
@@ -201,32 +201,32 @@ export function UsersView({ visible }: UsersViewProps) {
201
201
  </section>
202
202
 
203
203
  {pastInvitations.length > 0 && (
204
- <section className="users-section">
205
- <h3>Past Invitations ({pastInvitations.length})</h3>
206
- <table className="users-table">
204
+ <section className="mb-7">
205
+ <h3 className="text-[15px] font-semibold text-content-secondary mb-2.5">Past Invitations ({pastInvitations.length})</h3>
206
+ <table className="w-full border-collapse text-sm font-mono">
207
207
  <thead>
208
208
  <tr>
209
- <th>Email</th>
210
- <th>Invited By</th>
211
- <th>Status</th>
212
- <th>Date</th>
213
- <th></th>
209
+ <th className="text-left px-3 py-2 border-b border-edge text-content-muted font-medium text-xs uppercase tracking-wide">Email</th>
210
+ <th className="text-left px-3 py-2 border-b border-edge text-content-muted font-medium text-xs uppercase tracking-wide">Invited By</th>
211
+ <th className="text-left px-3 py-2 border-b border-edge text-content-muted font-medium text-xs uppercase tracking-wide">Status</th>
212
+ <th className="text-left px-3 py-2 border-b border-edge text-content-muted font-medium text-xs uppercase tracking-wide">Date</th>
213
+ <th className="text-left px-3 py-2 border-b border-edge text-content-muted font-medium text-xs uppercase tracking-wide"></th>
214
214
  </tr>
215
215
  </thead>
216
216
  <tbody>
217
217
  {pastInvitations.map(inv => (
218
- <tr key={inv.id} className="users-past-row">
219
- <td>{inv.email}</td>
220
- <td>{inv.invitedByEmail}</td>
221
- <td>
222
- <span className={`users-status-badge ${inv.acceptedAt ? 'users-status-accepted' : 'users-status-expired'}`}>
218
+ <tr key={inv.id} className="opacity-70 hover:bg-surface-raised">
219
+ <td className="px-3 py-2.5 border-b border-edge text-content">{inv.email}</td>
220
+ <td className="px-3 py-2.5 border-b border-edge text-content">{inv.invitedByEmail}</td>
221
+ <td className="px-3 py-2.5 border-b border-edge text-content">
222
+ <span className={`inline-block px-2 py-0.5 rounded text-xs font-medium ${inv.acceptedAt ? 'bg-[rgba(105,219,124,0.15)] text-completeness-fill' : 'bg-[rgba(255,107,107,0.15)] text-error'}`}>
223
223
  {inv.acceptedAt ? 'Accepted' : 'Expired'}
224
224
  </span>
225
225
  </td>
226
- <td>{formatDate(inv.acceptedAt || inv.expiresAt)}</td>
227
- <td>
226
+ <td className="px-3 py-2.5 border-b border-edge text-content">{formatDate(inv.acceptedAt || inv.expiresAt)}</td>
227
+ <td className="px-3 py-2.5 border-b border-edge text-content">
228
228
  <button
229
- className="users-delete-btn"
229
+ className="bg-none border border-edge text-error rounded px-2.5 py-1 text-xs cursor-pointer font-mono hover:bg-[rgba(255,107,107,0.1)] hover:border-error disabled:opacity-50 disabled:cursor-not-allowed"
230
230
  onClick={() => handleDeleteInvitation(inv.id, inv.email)}
231
231
  disabled={deletingId === inv.id}
232
232
  title={`Delete invitation record for ${inv.email}`}