@assistkick/create 1.9.0 → 1.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/scaffolder.d.ts +12 -1
- package/dist/src/scaffolder.js +40 -3
- package/dist/src/scaffolder.js.map +1 -1
- package/package.json +1 -1
- package/templates/assistkick-product-system/package.json +1 -1
- package/templates/assistkick-product-system/packages/backend/package.json +1 -0
- package/templates/assistkick-product-system/packages/backend/src/mcp/permission_mcp_server.ts +196 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/agents.ts +31 -7
- package/templates/assistkick-product-system/packages/backend/src/routes/auth.ts +15 -12
- package/templates/assistkick-product-system/packages/backend/src/routes/chat_files.test.ts +95 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/chat_files.ts +97 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/chat_permission.ts +94 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/chat_sessions.ts +189 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/chat_upload.test.ts +131 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/chat_upload.ts +94 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/files.test.ts +12 -3
- package/templates/assistkick-product-system/packages/backend/src/routes/files.ts +2 -2
- package/templates/assistkick-product-system/packages/backend/src/routes/git.ts +391 -23
- package/templates/assistkick-product-system/packages/backend/src/routes/git_branches.test.ts +306 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/git_connect.test.ts +133 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/pipeline.ts +66 -9
- package/templates/assistkick-product-system/packages/backend/src/routes/preview.ts +204 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/projects.test.ts +205 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/projects.ts +37 -9
- package/templates/assistkick-product-system/packages/backend/src/routes/skills.test.ts +139 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/skills.ts +95 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/terminal.ts +5 -4
- package/templates/assistkick-product-system/packages/backend/src/routes/users.ts +4 -4
- package/templates/assistkick-product-system/packages/backend/src/routes/video.ts +8 -8
- package/templates/assistkick-product-system/packages/backend/src/routes/workflow_groups.ts +5 -5
- package/templates/assistkick-product-system/packages/backend/src/routes/workflows.ts +6 -6
- package/templates/assistkick-product-system/packages/backend/src/server.ts +107 -27
- package/templates/assistkick-product-system/packages/backend/src/services/agent_service.test.ts +105 -203
- package/templates/assistkick-product-system/packages/backend/src/services/agent_service.ts +76 -266
- package/templates/assistkick-product-system/packages/backend/src/services/chat_cli_bridge.test.ts +427 -0
- package/templates/assistkick-product-system/packages/backend/src/services/chat_cli_bridge.ts +345 -0
- package/templates/assistkick-product-system/packages/backend/src/services/chat_message_repository.test.ts +170 -0
- package/templates/assistkick-product-system/packages/backend/src/services/chat_message_repository.ts +106 -0
- package/templates/assistkick-product-system/packages/backend/src/services/chat_session_service.test.ts +217 -0
- package/templates/assistkick-product-system/packages/backend/src/services/chat_session_service.ts +188 -0
- package/templates/assistkick-product-system/packages/backend/src/services/chat_ws_handler.test.ts +1243 -0
- package/templates/assistkick-product-system/packages/backend/src/services/chat_ws_handler.ts +894 -0
- package/templates/assistkick-product-system/packages/backend/src/services/coherence-review.ts +3 -3
- package/templates/assistkick-product-system/packages/backend/src/services/dev_command_detector.test.ts +85 -0
- package/templates/assistkick-product-system/packages/backend/src/services/dev_command_detector.ts +54 -0
- package/templates/assistkick-product-system/packages/backend/src/services/email_service.ts +13 -10
- package/templates/assistkick-product-system/packages/backend/src/services/init.ts +11 -3
- package/templates/assistkick-product-system/packages/backend/src/services/invitation_service.ts +1 -1
- package/templates/assistkick-product-system/packages/backend/src/services/password_reset_service.ts +1 -1
- package/templates/assistkick-product-system/packages/backend/src/services/permission_service.test.ts +243 -0
- package/templates/assistkick-product-system/packages/backend/src/services/permission_service.ts +259 -0
- package/templates/assistkick-product-system/packages/backend/src/services/preview_server_manager.test.ts +172 -0
- package/templates/assistkick-product-system/packages/backend/src/services/preview_server_manager.ts +225 -0
- package/templates/assistkick-product-system/packages/backend/src/services/project_service.test.ts +29 -0
- package/templates/assistkick-product-system/packages/backend/src/services/project_service.ts +17 -0
- package/templates/assistkick-product-system/packages/backend/src/services/project_workspace_service.test.ts +255 -0
- package/templates/assistkick-product-system/packages/backend/src/services/project_workspace_service.ts +300 -25
- package/templates/assistkick-product-system/packages/backend/src/services/pty_session_manager.test.ts +44 -0
- package/templates/assistkick-product-system/packages/backend/src/services/pty_session_manager.ts +62 -7
- package/templates/assistkick-product-system/packages/backend/src/services/ssh_key_service.test.ts +77 -6
- package/templates/assistkick-product-system/packages/backend/src/services/ssh_key_service.ts +149 -14
- package/templates/assistkick-product-system/packages/backend/src/services/terminal_ws_handler.ts +2 -1
- package/templates/assistkick-product-system/packages/backend/src/services/title_generator_service.test.ts +45 -0
- package/templates/assistkick-product-system/packages/backend/src/services/title_generator_service.ts +157 -0
- package/templates/assistkick-product-system/packages/backend/src/services/tts_service.ts +4 -3
- package/templates/assistkick-product-system/packages/backend/src/services/video_render_service.ts +3 -3
- package/templates/assistkick-product-system/packages/frontend/package.json +5 -0
- package/templates/assistkick-product-system/packages/frontend/src/App.tsx +2 -0
- package/templates/assistkick-product-system/packages/frontend/src/api/client.ts +336 -5
- package/templates/assistkick-product-system/packages/frontend/src/components/AgentsView.tsx +192 -12
- package/templates/assistkick-product-system/packages/frontend/src/components/AttachmentPreviewList.tsx +98 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/AutocompleteDropdown.tsx +65 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ChatAttachButton.tsx +56 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ChatDropZone.tsx +80 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ChatMessageBubble.tsx +155 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ChatMessageContent.tsx +182 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ChatMessageInput.tsx +233 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ChatSessionSidebar.tsx +218 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ChatStopButton.tsx +32 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ChatTodoSidebar.tsx +113 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ChatView.tsx +842 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/CommitMessageModal.tsx +82 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/DiagramOverlay.tsx +160 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/EditorTabBar.tsx +5 -5
- package/templates/assistkick-product-system/packages/frontend/src/components/FileTree.tsx +9 -10
- package/templates/assistkick-product-system/packages/frontend/src/components/FileTreeInlineInput.tsx +5 -5
- package/templates/assistkick-product-system/packages/frontend/src/components/FilesView.tsx +112 -41
- package/templates/assistkick-product-system/packages/frontend/src/components/GraphLegend.tsx +2 -2
- package/templates/assistkick-product-system/packages/frontend/src/components/HighlightedText.tsx +87 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ImageLightbox.tsx +192 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/KanbanView.tsx +2 -2
- package/templates/assistkick-product-system/packages/frontend/src/components/MentionPill.tsx +33 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/MermaidBlock.tsx +148 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/PermissionDialog.tsx +91 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/PermissionModeSelector.tsx +229 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ProjectSelector.tsx +249 -83
- package/templates/assistkick-product-system/packages/frontend/src/components/QueuedMessageBubble.tsx +38 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/SidePanel.tsx +212 -117
- package/templates/assistkick-product-system/packages/frontend/src/components/SystemPromptAccordion.tsx +48 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/TaskIcon.tsx +11 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/TerminalView.tsx +25 -9
- package/templates/assistkick-product-system/packages/frontend/src/components/ToolDiffView.tsx +114 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ToolResultCard.tsx +87 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ToolUseCard.tsx +149 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/Toolbar.tsx +25 -8
- package/templates/assistkick-product-system/packages/frontend/src/components/UnifiedGitWidget.tsx +722 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/GroupNode.tsx +2 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/NodePalette.tsx +2 -1
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/ProgrammableNode.tsx +178 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/WorkflowCanvas.tsx +3 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/WorkflowMonitorModal.tsx +103 -9
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/monitor_nodes.tsx +26 -2
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/workflow_types.ts +42 -1
- package/templates/assistkick-product-system/packages/frontend/src/hooks/useDocumentTitle.ts +11 -0
- package/templates/assistkick-product-system/packages/frontend/src/hooks/useProjects.ts +1 -0
- package/templates/assistkick-product-system/packages/frontend/src/hooks/use_chat_stream.ts +826 -0
- package/templates/assistkick-product-system/packages/frontend/src/hooks/use_file_tree_cache.ts +69 -0
- package/templates/assistkick-product-system/packages/frontend/src/hooks/use_mention_autocomplete.ts +284 -0
- package/templates/assistkick-product-system/packages/frontend/src/lib/attachment_manager.test.ts +183 -0
- package/templates/assistkick-product-system/packages/frontend/src/lib/attachment_manager.ts +150 -0
- package/templates/assistkick-product-system/packages/frontend/src/lib/chat_message_helpers.test.ts +305 -0
- package/templates/assistkick-product-system/packages/frontend/src/lib/chat_message_helpers.ts +113 -0
- package/templates/assistkick-product-system/packages/frontend/src/lib/context_usage_helpers.test.ts +157 -0
- package/templates/assistkick-product-system/packages/frontend/src/lib/context_usage_helpers.ts +95 -0
- package/templates/assistkick-product-system/packages/frontend/src/lib/mermaid_helpers.test.ts +65 -0
- package/templates/assistkick-product-system/packages/frontend/src/lib/mermaid_helpers.ts +110 -0
- package/templates/assistkick-product-system/packages/frontend/src/lib/message_queue.ts +66 -0
- package/templates/assistkick-product-system/packages/frontend/src/lib/tool_use_summary.test.ts +124 -0
- package/templates/assistkick-product-system/packages/frontend/src/lib/tool_use_summary.ts +112 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/AgentsRoute.tsx +2 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/ChatRoute.tsx +8 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/CoherenceRoute.tsx +2 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/DashboardLayout.tsx +0 -4
- package/templates/assistkick-product-system/packages/frontend/src/routes/DesignSystemRoute.tsx +2 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/FilesRoute.tsx +2 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/GraphRoute.tsx +2 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/KanbanRoute.tsx +2 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/TerminalRoute.tsx +2 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/UsersRoute.tsx +2 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/VideographyRoute.tsx +2 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/WorkflowsRoute.tsx +2 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/accept_invitation.tsx +2 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/forgot_password.tsx +2 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/login.tsx +2 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/register.tsx +2 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/reset_password.tsx +2 -0
- package/templates/assistkick-product-system/packages/frontend/src/stores/useAttachmentStore.ts +66 -0
- package/templates/assistkick-product-system/packages/frontend/src/stores/useChatSessionStore.ts +107 -0
- package/templates/assistkick-product-system/packages/frontend/src/stores/useMessageQueueStore.ts +110 -0
- package/templates/assistkick-product-system/packages/frontend/src/stores/usePreviewStore.ts +78 -0
- package/templates/assistkick-product-system/packages/frontend/src/stores/useProjectStore.ts +7 -0
- package/templates/assistkick-product-system/packages/frontend/src/stores/useSidePanelStore.ts +6 -1
- package/templates/assistkick-product-system/packages/frontend/src/styles/index.css +30 -357
- package/templates/assistkick-product-system/packages/frontend/src/utils/parse_node_markdown.test.ts +115 -0
- package/templates/assistkick-product-system/packages/frontend/src/utils/parse_node_markdown.ts +91 -0
- package/templates/assistkick-product-system/packages/frontend/src/utils/preview_utils.test.ts +30 -0
- package/templates/assistkick-product-system/packages/frontend/src/utils/preview_utils.ts +3 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0015_magenta_jazinda.sql +1 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0016_giant_xorn.sql +1 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0017_sloppy_mentor.sql +6 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0018_vengeful_kabuki.sql +9 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0019_careful_sentinels.sql +8 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0020_clever_spot.sql +27 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0021_graceful_hex.sql +1 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0022_short_kingpin.sql +1 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0023_ambiguous_sharon_carter.sql +1 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0024_fat_unus.sql +1 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0015_snapshot.json +1552 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0016_snapshot.json +1560 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0017_snapshot.json +1598 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0018_snapshot.json +1657 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0019_snapshot.json +1709 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0020_snapshot.json +1733 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0021_snapshot.json +1740 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0022_snapshot.json +1755 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0023_snapshot.json +1762 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0024_snapshot.json +1769 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/_journal.json +70 -0
- package/templates/assistkick-product-system/packages/shared/db/schema.ts +40 -1
- package/templates/assistkick-product-system/packages/shared/lib/claude-service.test.ts +236 -0
- package/templates/assistkick-product-system/packages/shared/lib/claude-service.ts +46 -5
- package/templates/assistkick-product-system/packages/shared/lib/git_workflow.ts +65 -39
- package/templates/assistkick-product-system/packages/shared/lib/programmable_node_executor.test.ts +173 -0
- package/templates/assistkick-product-system/packages/shared/lib/programmable_node_executor.ts +213 -0
- package/templates/assistkick-product-system/packages/shared/lib/validator.test.ts +70 -0
- package/templates/assistkick-product-system/packages/shared/lib/validator.ts +17 -1
- package/templates/assistkick-product-system/packages/shared/lib/workflow_engine.test.ts +803 -27
- package/templates/assistkick-product-system/packages/shared/lib/workflow_engine.ts +502 -68
- package/templates/assistkick-product-system/packages/shared/lib/workflow_orchestrator.ts +4 -4
- package/templates/assistkick-product-system/packages/shared/package.json +2 -1
- package/templates/assistkick-product-system/packages/shared/test_fixtures/hanging_stream.mjs +46 -0
- package/templates/assistkick-product-system/packages/shared/tools/add_node.test.ts +44 -0
- package/templates/assistkick-product-system/packages/shared/tools/add_node.ts +7 -0
- package/templates/assistkick-product-system/packages/shared/tools/remove_node.ts +2 -1
- package/templates/assistkick-product-system/packages/shared/tools/resolve_question.ts +2 -1
- package/templates/assistkick-product-system/packages/shared/tools/update_node.ts +2 -1
- package/templates/assistkick-product-system/tests/message_queue.test.ts +178 -0
- package/templates/assistkick-product-system/tests/message_queue_per_session.test.ts +143 -0
- package/templates/skills/assistkick-bootstrap/SKILL.md +26 -26
- package/templates/skills/assistkick-code-reviewer/SKILL.md +45 -46
- package/templates/skills/assistkick-db-explorer/SKILL.md +13 -13
- package/templates/skills/assistkick-debugger/SKILL.md +23 -23
- package/templates/skills/assistkick-developer/SKILL.md +59 -63
- package/templates/skills/assistkick-interview/SKILL.md +26 -26
- package/templates/skills/assistkick-video-composition-agent/SKILL.md +231 -0
- package/templates/skills/assistkick-video-script-writer/SKILL.md +136 -0
package/templates/assistkick-product-system/packages/frontend/src/components/ChatSessionSidebar.tsx
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ChatSessionSidebar — session list for Chat v2, mirroring the terminal sidebar pattern.
|
|
3
|
+
* Displays all chat sessions for the current project, allows creating new sessions,
|
|
4
|
+
* renaming, and deleting existing ones.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import React, { useEffect, useCallback, useState, useRef } from 'react';
|
|
8
|
+
import { useChatSessionStore } from '../stores/useChatSessionStore';
|
|
9
|
+
import type { ChatSession } from '../stores/useChatSessionStore';
|
|
10
|
+
import { useProjectStore } from '../stores/useProjectStore';
|
|
11
|
+
import { Button } from './ds/Button';
|
|
12
|
+
import { IconButton } from './ds/IconButton';
|
|
13
|
+
import { X, Plus, Pencil, Check } from 'lucide-react';
|
|
14
|
+
|
|
15
|
+
interface ChatSessionSidebarProps {
|
|
16
|
+
visible: boolean;
|
|
17
|
+
onSelectSession: (session: ChatSession) => void;
|
|
18
|
+
onNewSessionCreated?: (session: ChatSession) => void;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function ChatSessionSidebar({ visible, onSelectSession, onNewSessionCreated }: ChatSessionSidebarProps) {
|
|
22
|
+
const sessions = useChatSessionStore((s) => s.sessions);
|
|
23
|
+
const activeSessionId = useChatSessionStore((s) => s.activeSessionId);
|
|
24
|
+
const loading = useChatSessionStore((s) => s.loading);
|
|
25
|
+
const fetchSessions = useChatSessionStore((s) => s.fetchSessions);
|
|
26
|
+
const selectSession = useChatSessionStore((s) => s.selectSession);
|
|
27
|
+
const createSession = useChatSessionStore((s) => s.createSession);
|
|
28
|
+
const renameSession = useChatSessionStore((s) => s.renameSession);
|
|
29
|
+
const deleteSession = useChatSessionStore((s) => s.deleteSession);
|
|
30
|
+
|
|
31
|
+
const selectedProjectId = useProjectStore((s) => s.selectedProjectId);
|
|
32
|
+
|
|
33
|
+
const [creating, setCreating] = useState(false);
|
|
34
|
+
const [editingId, setEditingId] = useState<string | null>(null);
|
|
35
|
+
const [editName, setEditName] = useState('');
|
|
36
|
+
const editInputRef = useRef<HTMLInputElement>(null);
|
|
37
|
+
|
|
38
|
+
// Load sessions when visible and project changes
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
if (visible && selectedProjectId) {
|
|
41
|
+
fetchSessions(selectedProjectId);
|
|
42
|
+
}
|
|
43
|
+
}, [visible, selectedProjectId, fetchSessions]);
|
|
44
|
+
|
|
45
|
+
// Focus the edit input when entering rename mode
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
if (editingId && editInputRef.current) {
|
|
48
|
+
editInputRef.current.focus();
|
|
49
|
+
editInputRef.current.select();
|
|
50
|
+
}
|
|
51
|
+
}, [editingId]);
|
|
52
|
+
|
|
53
|
+
const handleSelectSession = useCallback(
|
|
54
|
+
(session: ChatSession) => {
|
|
55
|
+
selectSession(session.id);
|
|
56
|
+
onSelectSession(session);
|
|
57
|
+
},
|
|
58
|
+
[selectSession, onSelectSession],
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
const handleCreateSession = useCallback(async () => {
|
|
62
|
+
if (!selectedProjectId || creating) return;
|
|
63
|
+
setCreating(true);
|
|
64
|
+
try {
|
|
65
|
+
const session = await createSession(selectedProjectId);
|
|
66
|
+
if (onNewSessionCreated) {
|
|
67
|
+
onNewSessionCreated(session);
|
|
68
|
+
} else {
|
|
69
|
+
onSelectSession(session);
|
|
70
|
+
}
|
|
71
|
+
} catch {
|
|
72
|
+
// silently ignore
|
|
73
|
+
} finally {
|
|
74
|
+
setCreating(false);
|
|
75
|
+
}
|
|
76
|
+
}, [selectedProjectId, creating, createSession, onSelectSession, onNewSessionCreated]);
|
|
77
|
+
|
|
78
|
+
const handleDeleteSession = useCallback(
|
|
79
|
+
async (sessionId: string, e: React.MouseEvent) => {
|
|
80
|
+
e.stopPropagation();
|
|
81
|
+
if (!selectedProjectId) return;
|
|
82
|
+
try {
|
|
83
|
+
await deleteSession(sessionId, selectedProjectId);
|
|
84
|
+
} catch {
|
|
85
|
+
// silently ignore
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
[selectedProjectId, deleteSession],
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
const handleStartRename = useCallback(
|
|
92
|
+
(session: ChatSession, e: React.MouseEvent) => {
|
|
93
|
+
e.stopPropagation();
|
|
94
|
+
setEditingId(session.id);
|
|
95
|
+
setEditName(session.name);
|
|
96
|
+
},
|
|
97
|
+
[],
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
const handleConfirmRename = useCallback(
|
|
101
|
+
async (sessionId: string) => {
|
|
102
|
+
const trimmed = editName.trim();
|
|
103
|
+
if (trimmed) {
|
|
104
|
+
try {
|
|
105
|
+
await renameSession(sessionId, trimmed);
|
|
106
|
+
} catch {
|
|
107
|
+
// silently ignore
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
setEditingId(null);
|
|
111
|
+
setEditName('');
|
|
112
|
+
},
|
|
113
|
+
[editName, renameSession],
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
const handleRenameKeyDown = useCallback(
|
|
117
|
+
(sessionId: string, e: React.KeyboardEvent) => {
|
|
118
|
+
if (e.key === 'Enter') {
|
|
119
|
+
handleConfirmRename(sessionId);
|
|
120
|
+
} else if (e.key === 'Escape') {
|
|
121
|
+
setEditingId(null);
|
|
122
|
+
setEditName('');
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
[handleConfirmRename],
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
return (
|
|
129
|
+
<div className="flex flex-col w-[280px] min-w-[280px] border-r border-edge bg-surface-alt overflow-hidden">
|
|
130
|
+
<div className="px-3 py-2.5 text-[11px] font-mono uppercase tracking-widest text-content-muted border-b border-edge shrink-0">
|
|
131
|
+
Chat Sessions
|
|
132
|
+
</div>
|
|
133
|
+
<div className="flex-1 overflow-y-auto">
|
|
134
|
+
{!loading && sessions.length === 0 && (
|
|
135
|
+
<div className="px-3 py-4 text-xs text-content-muted font-mono">No sessions yet</div>
|
|
136
|
+
)}
|
|
137
|
+
{sessions.map((session) => (
|
|
138
|
+
<div
|
|
139
|
+
key={session.id}
|
|
140
|
+
className={`flex flex-col px-2.5 py-2 cursor-pointer border-b border-edge relative hover:bg-tab-hover${
|
|
141
|
+
session.id === activeSessionId
|
|
142
|
+
? ' bg-tab-active border-l-2 border-l-accent pl-2'
|
|
143
|
+
: ''
|
|
144
|
+
}`}
|
|
145
|
+
onClick={() => handleSelectSession(session)}
|
|
146
|
+
>
|
|
147
|
+
{editingId === session.id ? (
|
|
148
|
+
<div className="flex items-center gap-1 pr-5">
|
|
149
|
+
<input
|
|
150
|
+
ref={editInputRef}
|
|
151
|
+
type="text"
|
|
152
|
+
value={editName}
|
|
153
|
+
onChange={(e) => setEditName(e.target.value)}
|
|
154
|
+
onKeyDown={(e) => handleRenameKeyDown(session.id, e)}
|
|
155
|
+
onBlur={() => handleConfirmRename(session.id)}
|
|
156
|
+
className="flex-1 min-w-0 bg-surface border border-edge rounded px-1.5 py-0.5 text-xs font-mono text-content outline-none focus:border-accent"
|
|
157
|
+
onClick={(e) => e.stopPropagation()}
|
|
158
|
+
/>
|
|
159
|
+
<IconButton
|
|
160
|
+
label="Confirm rename"
|
|
161
|
+
variant="accent"
|
|
162
|
+
size="sm"
|
|
163
|
+
onClick={(e) => {
|
|
164
|
+
e.stopPropagation();
|
|
165
|
+
handleConfirmRename(session.id);
|
|
166
|
+
}}
|
|
167
|
+
>
|
|
168
|
+
<Check size={10} strokeWidth={2} />
|
|
169
|
+
</IconButton>
|
|
170
|
+
</div>
|
|
171
|
+
) : (
|
|
172
|
+
<>
|
|
173
|
+
<div className="text-xs font-mono text-content whitespace-nowrap overflow-hidden text-ellipsis pr-12">
|
|
174
|
+
{session.name}
|
|
175
|
+
</div>
|
|
176
|
+
<div className="text-[11px] text-content-muted font-mono whitespace-nowrap overflow-hidden text-ellipsis pr-12 mt-0.5">
|
|
177
|
+
{new Date(session.updatedAt).toLocaleDateString()}
|
|
178
|
+
</div>
|
|
179
|
+
<div className="absolute top-2 right-2 flex items-center gap-0.5">
|
|
180
|
+
<IconButton
|
|
181
|
+
label="Rename session"
|
|
182
|
+
variant="ghost"
|
|
183
|
+
size="sm"
|
|
184
|
+
onClick={(e) => handleStartRename(session, e)}
|
|
185
|
+
>
|
|
186
|
+
<Pencil size={10} strokeWidth={2} />
|
|
187
|
+
</IconButton>
|
|
188
|
+
<IconButton
|
|
189
|
+
label="Delete session"
|
|
190
|
+
variant="danger"
|
|
191
|
+
size="sm"
|
|
192
|
+
onClick={(e) => handleDeleteSession(session.id, e)}
|
|
193
|
+
>
|
|
194
|
+
<X size={10} strokeWidth={2} />
|
|
195
|
+
</IconButton>
|
|
196
|
+
</div>
|
|
197
|
+
</>
|
|
198
|
+
)}
|
|
199
|
+
</div>
|
|
200
|
+
))}
|
|
201
|
+
</div>
|
|
202
|
+
|
|
203
|
+
{/* New session button */}
|
|
204
|
+
<div className="flex flex-col gap-1.5 p-2.5 border-t border-edge shrink-0">
|
|
205
|
+
<Button
|
|
206
|
+
variant="primary"
|
|
207
|
+
size="sm"
|
|
208
|
+
icon={!creating ? <Plus size={12} strokeWidth={2} /> : undefined}
|
|
209
|
+
className="w-full"
|
|
210
|
+
onClick={handleCreateSession}
|
|
211
|
+
disabled={creating || !selectedProjectId}
|
|
212
|
+
>
|
|
213
|
+
{creating ? '...' : 'New Chat'}
|
|
214
|
+
</Button>
|
|
215
|
+
</div>
|
|
216
|
+
</div>
|
|
217
|
+
);
|
|
218
|
+
}
|
package/templates/assistkick-product-system/packages/frontend/src/components/ChatStopButton.tsx
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ChatStopButton — shown while Claude is actively streaming a response.
|
|
3
|
+
* Clicking it sends a stop_stream WebSocket message that kills the CLI subprocess.
|
|
4
|
+
* The partial response and triggering user message are discarded (handled by useChatStream).
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { Square } from 'lucide-react';
|
|
8
|
+
import { Button } from './ds/Button';
|
|
9
|
+
|
|
10
|
+
interface ChatStopButtonProps {
|
|
11
|
+
/** Whether Claude is currently streaming a response */
|
|
12
|
+
streaming: boolean;
|
|
13
|
+
/** Callback to send the stop_stream message */
|
|
14
|
+
onStop: () => void;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function ChatStopButton({ streaming, onStop }: ChatStopButtonProps) {
|
|
18
|
+
if (!streaming) return null;
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<Button
|
|
22
|
+
variant="danger"
|
|
23
|
+
size="sm"
|
|
24
|
+
icon={<Square size={10} strokeWidth={2.5} fill="currentColor" />}
|
|
25
|
+
onClick={onStop}
|
|
26
|
+
aria-label="Stop response"
|
|
27
|
+
title="Stop response — discards partial reply and restores your message"
|
|
28
|
+
>
|
|
29
|
+
Stop
|
|
30
|
+
</Button>
|
|
31
|
+
);
|
|
32
|
+
}
|
package/templates/assistkick-product-system/packages/frontend/src/components/ChatTodoSidebar.tsx
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ChatTodoSidebar — displays the current task list extracted from
|
|
3
|
+
* TodoWrite tool_use blocks in the chat stream. Shown as a sidebar
|
|
4
|
+
* panel beside the chat messages area.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { useMemo } from 'react';
|
|
8
|
+
import { CheckCircle2, Circle, Loader2 } from 'lucide-react';
|
|
9
|
+
import type { ChatMessage } from '../hooks/use_chat_stream';
|
|
10
|
+
|
|
11
|
+
interface TodoItem {
|
|
12
|
+
content: string;
|
|
13
|
+
status: 'pending' | 'in_progress' | 'completed';
|
|
14
|
+
activeForm: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface ChatTodoSidebarProps {
|
|
18
|
+
messages: ChatMessage[];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Extract the latest TodoWrite list from the chat messages.
|
|
23
|
+
* Scans all assistant messages in reverse to find the most recent
|
|
24
|
+
* TodoWrite tool_use block with a valid todos array.
|
|
25
|
+
*/
|
|
26
|
+
const extractTodos = (messages: ChatMessage[]): TodoItem[] | null => {
|
|
27
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
28
|
+
const msg = messages[i];
|
|
29
|
+
if (msg.role !== 'assistant') continue;
|
|
30
|
+
|
|
31
|
+
// Scan content blocks in reverse within the message
|
|
32
|
+
for (let j = msg.content.length - 1; j >= 0; j--) {
|
|
33
|
+
const block = msg.content[j];
|
|
34
|
+
if (block.type === 'tool_use' && block.name === 'TodoWrite') {
|
|
35
|
+
const todos = block.input?.todos;
|
|
36
|
+
if (Array.isArray(todos) && todos.length > 0) {
|
|
37
|
+
return todos as TodoItem[];
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return null;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const statusIcon = (status: TodoItem['status']) => {
|
|
46
|
+
switch (status) {
|
|
47
|
+
case 'completed':
|
|
48
|
+
return <CheckCircle2 size={14} className="text-green-400 shrink-0" />;
|
|
49
|
+
case 'in_progress':
|
|
50
|
+
return <Loader2 size={14} className="text-accent shrink-0 animate-spin" />;
|
|
51
|
+
case 'pending':
|
|
52
|
+
default:
|
|
53
|
+
return <Circle size={14} className="text-content-muted shrink-0" />;
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export function ChatTodoSidebar({ messages }: ChatTodoSidebarProps) {
|
|
58
|
+
const todos = useMemo(() => extractTodos(messages), [messages]);
|
|
59
|
+
|
|
60
|
+
if (!todos || todos.length === 0) return null;
|
|
61
|
+
|
|
62
|
+
const completed = todos.filter(t => t.status === 'completed').length;
|
|
63
|
+
const total = todos.length;
|
|
64
|
+
const progressPct = total > 0 ? Math.round((completed / total) * 100) : 0;
|
|
65
|
+
|
|
66
|
+
return (
|
|
67
|
+
<div className="w-[280px] shrink-0 h-full flex flex-col border-l border-edge bg-surface overflow-hidden">
|
|
68
|
+
{/* Header */}
|
|
69
|
+
<div className="px-3 py-2 border-b border-edge shrink-0">
|
|
70
|
+
<div className="flex items-center justify-between">
|
|
71
|
+
<span className="text-[12px] font-mono font-medium text-content">Tasks</span>
|
|
72
|
+
<span className="text-[11px] font-mono text-content-muted">
|
|
73
|
+
{completed}/{total}
|
|
74
|
+
</span>
|
|
75
|
+
</div>
|
|
76
|
+
{/* Progress bar */}
|
|
77
|
+
<div className="mt-1.5 h-1 bg-edge rounded-full overflow-hidden">
|
|
78
|
+
<div
|
|
79
|
+
className="h-full bg-green-400 rounded-full transition-all duration-300"
|
|
80
|
+
style={{ width: `${progressPct}%` }}
|
|
81
|
+
/>
|
|
82
|
+
</div>
|
|
83
|
+
</div>
|
|
84
|
+
|
|
85
|
+
{/* Todo list */}
|
|
86
|
+
<div className="flex-1 overflow-y-auto px-2 py-2 space-y-0.5">
|
|
87
|
+
{todos.map((todo, idx) => (
|
|
88
|
+
<div
|
|
89
|
+
key={idx}
|
|
90
|
+
className={`flex items-start gap-2 px-2 py-1.5 rounded-md transition-colors ${
|
|
91
|
+
todo.status === 'in_progress'
|
|
92
|
+
? 'bg-accent/10'
|
|
93
|
+
: todo.status === 'completed'
|
|
94
|
+
? 'opacity-60'
|
|
95
|
+
: ''
|
|
96
|
+
}`}
|
|
97
|
+
>
|
|
98
|
+
<div className="mt-0.5">{statusIcon(todo.status)}</div>
|
|
99
|
+
<span className={`text-[12px] font-mono leading-tight ${
|
|
100
|
+
todo.status === 'completed'
|
|
101
|
+
? 'text-content-muted line-through'
|
|
102
|
+
: todo.status === 'in_progress'
|
|
103
|
+
? 'text-content'
|
|
104
|
+
: 'text-content-secondary'
|
|
105
|
+
}`}>
|
|
106
|
+
{todo.status === 'in_progress' ? todo.activeForm : todo.content}
|
|
107
|
+
</span>
|
|
108
|
+
</div>
|
|
109
|
+
))}
|
|
110
|
+
</div>
|
|
111
|
+
</div>
|
|
112
|
+
);
|
|
113
|
+
}
|