@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/HighlightedText.tsx
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HighlightedText — splits text around case-insensitive search matches
|
|
3
|
+
* and wraps each match in a <mark> tag for visual highlighting.
|
|
4
|
+
*
|
|
5
|
+
* When searchQuery is empty or absent, renders children as-is.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { ReactNode } from 'react';
|
|
9
|
+
|
|
10
|
+
interface HighlightedTextProps {
|
|
11
|
+
text: string;
|
|
12
|
+
searchQuery: string;
|
|
13
|
+
/** Index of the currently focused match (0-based global index across all messages). -1 = none. */
|
|
14
|
+
activeMatchIndex?: number;
|
|
15
|
+
/** The starting global index offset for matches within this text. */
|
|
16
|
+
matchIndexOffset?: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function HighlightedText({
|
|
20
|
+
text,
|
|
21
|
+
searchQuery,
|
|
22
|
+
activeMatchIndex = -1,
|
|
23
|
+
matchIndexOffset = 0,
|
|
24
|
+
}: HighlightedTextProps) {
|
|
25
|
+
if (!searchQuery) return <>{text}</>;
|
|
26
|
+
|
|
27
|
+
const query = searchQuery.toLowerCase();
|
|
28
|
+
const parts: ReactNode[] = [];
|
|
29
|
+
let remaining = text;
|
|
30
|
+
let localIdx = 0;
|
|
31
|
+
|
|
32
|
+
while (remaining.length > 0) {
|
|
33
|
+
const lowerRemaining = remaining.toLowerCase();
|
|
34
|
+
const matchPos = lowerRemaining.indexOf(query);
|
|
35
|
+
|
|
36
|
+
if (matchPos === -1) {
|
|
37
|
+
parts.push(remaining);
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Text before the match
|
|
42
|
+
if (matchPos > 0) {
|
|
43
|
+
parts.push(remaining.slice(0, matchPos));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const matchedText = remaining.slice(matchPos, matchPos + searchQuery.length);
|
|
47
|
+
const globalIdx = matchIndexOffset + localIdx;
|
|
48
|
+
const isActive = globalIdx === activeMatchIndex;
|
|
49
|
+
|
|
50
|
+
parts.push(
|
|
51
|
+
<mark
|
|
52
|
+
key={`${matchIndexOffset}-${localIdx}`}
|
|
53
|
+
className={
|
|
54
|
+
isActive
|
|
55
|
+
? 'bg-accent text-surface rounded-sm px-[1px]'
|
|
56
|
+
: 'bg-accent/30 text-content rounded-sm px-[1px]'
|
|
57
|
+
}
|
|
58
|
+
data-search-match={globalIdx}
|
|
59
|
+
>
|
|
60
|
+
{matchedText}
|
|
61
|
+
</mark>,
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
remaining = remaining.slice(matchPos + searchQuery.length);
|
|
65
|
+
localIdx++;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return <>{parts}</>;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Count the number of case-insensitive occurrences of `query` in `text`.
|
|
73
|
+
*/
|
|
74
|
+
export function countMatches(text: string, query: string): number {
|
|
75
|
+
if (!query) return 0;
|
|
76
|
+
const lower = text.toLowerCase();
|
|
77
|
+
const q = query.toLowerCase();
|
|
78
|
+
let count = 0;
|
|
79
|
+
let pos = 0;
|
|
80
|
+
while (true) {
|
|
81
|
+
const idx = lower.indexOf(q, pos);
|
|
82
|
+
if (idx === -1) break;
|
|
83
|
+
count++;
|
|
84
|
+
pos = idx + q.length;
|
|
85
|
+
}
|
|
86
|
+
return count;
|
|
87
|
+
}
|
package/templates/assistkick-product-system/packages/frontend/src/components/ImageLightbox.tsx
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ImageLightbox — fullscreen overlay for viewing chat images.
|
|
3
|
+
*
|
|
4
|
+
* Features:
|
|
5
|
+
* - Fullscreen dark backdrop with the image centered
|
|
6
|
+
* - Prev/next navigation when multiple images are present
|
|
7
|
+
* - Zoom via mouse wheel, pan by dragging when zoomed
|
|
8
|
+
* - Closes on Escape, clicking the backdrop, or the close button
|
|
9
|
+
* - Keyboard navigation: Arrow Left/Right for prev/next
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { useState, useCallback, useEffect, useRef } from 'react';
|
|
13
|
+
import { createPortal } from 'react-dom';
|
|
14
|
+
import { X, ChevronLeft, ChevronRight } from 'lucide-react';
|
|
15
|
+
|
|
16
|
+
export interface LightboxImage {
|
|
17
|
+
src: string;
|
|
18
|
+
alt: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface ImageLightboxProps {
|
|
22
|
+
images: LightboxImage[];
|
|
23
|
+
initialIndex: number;
|
|
24
|
+
onClose: () => void;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const MIN_ZOOM = 1;
|
|
28
|
+
const MAX_ZOOM = 5;
|
|
29
|
+
const ZOOM_STEP = 0.3;
|
|
30
|
+
|
|
31
|
+
export function ImageLightbox({ images, initialIndex, onClose }: ImageLightboxProps) {
|
|
32
|
+
const [currentIndex, setCurrentIndex] = useState(initialIndex);
|
|
33
|
+
const [zoom, setZoom] = useState(1);
|
|
34
|
+
const [pan, setPan] = useState({ x: 0, y: 0 });
|
|
35
|
+
const [dragging, setDragging] = useState(false);
|
|
36
|
+
const dragStart = useRef({ x: 0, y: 0 });
|
|
37
|
+
const panStart = useRef({ x: 0, y: 0 });
|
|
38
|
+
|
|
39
|
+
const hasMultiple = images.length > 1;
|
|
40
|
+
|
|
41
|
+
const resetTransform = useCallback(() => {
|
|
42
|
+
setZoom(1);
|
|
43
|
+
setPan({ x: 0, y: 0 });
|
|
44
|
+
}, []);
|
|
45
|
+
|
|
46
|
+
const goNext = useCallback(() => {
|
|
47
|
+
if (!hasMultiple) return;
|
|
48
|
+
resetTransform();
|
|
49
|
+
setCurrentIndex((prev) => (prev + 1) % images.length);
|
|
50
|
+
}, [hasMultiple, images.length, resetTransform]);
|
|
51
|
+
|
|
52
|
+
const goPrev = useCallback(() => {
|
|
53
|
+
if (!hasMultiple) return;
|
|
54
|
+
resetTransform();
|
|
55
|
+
setCurrentIndex((prev) => (prev - 1 + images.length) % images.length);
|
|
56
|
+
}, [hasMultiple, images.length, resetTransform]);
|
|
57
|
+
|
|
58
|
+
// Keyboard handling
|
|
59
|
+
useEffect(() => {
|
|
60
|
+
const handler = (e: KeyboardEvent) => {
|
|
61
|
+
if (e.key === 'Escape') {
|
|
62
|
+
onClose();
|
|
63
|
+
} else if (e.key === 'ArrowRight') {
|
|
64
|
+
goNext();
|
|
65
|
+
} else if (e.key === 'ArrowLeft') {
|
|
66
|
+
goPrev();
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
window.addEventListener('keydown', handler);
|
|
70
|
+
return () => window.removeEventListener('keydown', handler);
|
|
71
|
+
}, [onClose, goNext, goPrev]);
|
|
72
|
+
|
|
73
|
+
// Mouse wheel zoom
|
|
74
|
+
const handleWheel = useCallback((e: React.WheelEvent) => {
|
|
75
|
+
e.preventDefault();
|
|
76
|
+
setZoom((prev) => {
|
|
77
|
+
const next = prev + (e.deltaY < 0 ? ZOOM_STEP : -ZOOM_STEP);
|
|
78
|
+
const clamped = Math.max(MIN_ZOOM, Math.min(MAX_ZOOM, next));
|
|
79
|
+
if (clamped === 1) setPan({ x: 0, y: 0 });
|
|
80
|
+
return clamped;
|
|
81
|
+
});
|
|
82
|
+
}, []);
|
|
83
|
+
|
|
84
|
+
// Pan handling
|
|
85
|
+
const handleMouseDown = useCallback((e: React.MouseEvent) => {
|
|
86
|
+
if (zoom <= 1) return;
|
|
87
|
+
e.preventDefault();
|
|
88
|
+
setDragging(true);
|
|
89
|
+
dragStart.current = { x: e.clientX, y: e.clientY };
|
|
90
|
+
panStart.current = { ...pan };
|
|
91
|
+
}, [zoom, pan]);
|
|
92
|
+
|
|
93
|
+
const handleMouseMove = useCallback((e: React.MouseEvent) => {
|
|
94
|
+
if (!dragging) return;
|
|
95
|
+
setPan({
|
|
96
|
+
x: panStart.current.x + (e.clientX - dragStart.current.x),
|
|
97
|
+
y: panStart.current.y + (e.clientY - dragStart.current.y),
|
|
98
|
+
});
|
|
99
|
+
}, [dragging]);
|
|
100
|
+
|
|
101
|
+
const handleMouseUp = useCallback(() => {
|
|
102
|
+
setDragging(false);
|
|
103
|
+
}, []);
|
|
104
|
+
|
|
105
|
+
// Click on backdrop closes
|
|
106
|
+
const handleBackdropClick = useCallback((e: React.MouseEvent) => {
|
|
107
|
+
if (e.target === e.currentTarget) {
|
|
108
|
+
onClose();
|
|
109
|
+
}
|
|
110
|
+
}, [onClose]);
|
|
111
|
+
|
|
112
|
+
const current = images[currentIndex];
|
|
113
|
+
if (!current) return null;
|
|
114
|
+
|
|
115
|
+
const content = (
|
|
116
|
+
<div
|
|
117
|
+
className="fixed inset-0 z-50 flex items-center justify-center bg-black/90"
|
|
118
|
+
onClick={handleBackdropClick}
|
|
119
|
+
onMouseMove={handleMouseMove}
|
|
120
|
+
onMouseUp={handleMouseUp}
|
|
121
|
+
onMouseLeave={handleMouseUp}
|
|
122
|
+
role="dialog"
|
|
123
|
+
aria-label="Image lightbox"
|
|
124
|
+
>
|
|
125
|
+
{/* Close button */}
|
|
126
|
+
<button
|
|
127
|
+
type="button"
|
|
128
|
+
className="absolute top-4 right-4 z-10 p-2 rounded-full bg-black/50 hover:bg-black/70 text-white transition-colors cursor-pointer border-none"
|
|
129
|
+
onClick={onClose}
|
|
130
|
+
aria-label="Close lightbox"
|
|
131
|
+
>
|
|
132
|
+
<X size={20} />
|
|
133
|
+
</button>
|
|
134
|
+
|
|
135
|
+
{/* Image counter */}
|
|
136
|
+
{hasMultiple && (
|
|
137
|
+
<span className="absolute top-4 left-1/2 -translate-x-1/2 z-10 text-[13px] font-mono text-white/70 bg-black/50 px-3 py-1 rounded-full">
|
|
138
|
+
{currentIndex + 1} / {images.length}
|
|
139
|
+
</span>
|
|
140
|
+
)}
|
|
141
|
+
|
|
142
|
+
{/* Previous button */}
|
|
143
|
+
{hasMultiple && (
|
|
144
|
+
<button
|
|
145
|
+
type="button"
|
|
146
|
+
className="absolute left-4 top-1/2 -translate-y-1/2 z-10 p-2 rounded-full bg-black/50 hover:bg-black/70 text-white transition-colors cursor-pointer border-none"
|
|
147
|
+
onClick={goPrev}
|
|
148
|
+
aria-label="Previous image"
|
|
149
|
+
>
|
|
150
|
+
<ChevronLeft size={24} />
|
|
151
|
+
</button>
|
|
152
|
+
)}
|
|
153
|
+
|
|
154
|
+
{/* Next button */}
|
|
155
|
+
{hasMultiple && (
|
|
156
|
+
<button
|
|
157
|
+
type="button"
|
|
158
|
+
className="absolute right-4 top-1/2 -translate-y-1/2 z-10 p-2 rounded-full bg-black/50 hover:bg-black/70 text-white transition-colors cursor-pointer border-none"
|
|
159
|
+
onClick={goNext}
|
|
160
|
+
aria-label="Next image"
|
|
161
|
+
>
|
|
162
|
+
<ChevronRight size={24} />
|
|
163
|
+
</button>
|
|
164
|
+
)}
|
|
165
|
+
|
|
166
|
+
{/* Image */}
|
|
167
|
+
<div
|
|
168
|
+
className="max-w-[90vw] max-h-[90vh] overflow-hidden select-none"
|
|
169
|
+
onWheel={handleWheel}
|
|
170
|
+
onMouseDown={handleMouseDown}
|
|
171
|
+
style={{ cursor: zoom > 1 ? (dragging ? 'grabbing' : 'grab') : 'default' }}
|
|
172
|
+
>
|
|
173
|
+
<img
|
|
174
|
+
src={current.src}
|
|
175
|
+
alt={current.alt}
|
|
176
|
+
className="max-w-[90vw] max-h-[90vh] object-contain transition-transform duration-100"
|
|
177
|
+
style={{
|
|
178
|
+
transform: `scale(${zoom}) translate(${pan.x / zoom}px, ${pan.y / zoom}px)`,
|
|
179
|
+
}}
|
|
180
|
+
draggable={false}
|
|
181
|
+
/>
|
|
182
|
+
</div>
|
|
183
|
+
|
|
184
|
+
{/* Image name */}
|
|
185
|
+
<span className="absolute bottom-4 left-1/2 -translate-x-1/2 z-10 text-[12px] font-mono text-white/60 bg-black/50 px-3 py-1 rounded-full max-w-[60vw] truncate">
|
|
186
|
+
{current.alt}
|
|
187
|
+
</span>
|
|
188
|
+
</div>
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
return createPortal(content, document.body);
|
|
192
|
+
}
|
|
@@ -225,11 +225,11 @@ export function KanbanView({ graphData, projectId, onCardClick, onIssuesClick }:
|
|
|
225
225
|
setDraggedCard(featureId);
|
|
226
226
|
e.dataTransfer.effectAllowed = 'move';
|
|
227
227
|
e.dataTransfer.setData('text/plain', featureId);
|
|
228
|
-
(e.target as HTMLElement).classList.add('
|
|
228
|
+
(e.target as HTMLElement).classList.add('opacity-40');
|
|
229
229
|
};
|
|
230
230
|
|
|
231
231
|
const handleDragEnd = (e: React.DragEvent) => {
|
|
232
|
-
(e.target as HTMLElement).classList.remove('
|
|
232
|
+
(e.target as HTMLElement).classList.remove('opacity-40');
|
|
233
233
|
setDraggedCard(null);
|
|
234
234
|
setDragOverColumn(null);
|
|
235
235
|
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MentionPill — renders a detected @file or /skill mention as a removable pill.
|
|
3
|
+
* Shows an icon, the mention value, and an X button for removal.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { X, FileText, Terminal } from 'lucide-react';
|
|
7
|
+
import type { Mention } from '../hooks/use_mention_autocomplete';
|
|
8
|
+
|
|
9
|
+
interface MentionPillProps {
|
|
10
|
+
mention: Mention;
|
|
11
|
+
onRemove: (mention: Mention) => void;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const MentionPill = ({ mention, onRemove }: MentionPillProps) => {
|
|
15
|
+
return (
|
|
16
|
+
<span className="inline-flex items-center gap-1 px-2 py-0.5 bg-accent/10 border border-accent/20 rounded text-[11px] font-mono text-accent">
|
|
17
|
+
{mention.type === 'file' ? (
|
|
18
|
+
<FileText size={10} className="shrink-0" />
|
|
19
|
+
) : (
|
|
20
|
+
<Terminal size={10} className="shrink-0" />
|
|
21
|
+
)}
|
|
22
|
+
<span className="truncate max-w-[200px]">{mention.displayValue}</span>
|
|
23
|
+
<button
|
|
24
|
+
type="button"
|
|
25
|
+
className="ml-0.5 text-accent/60 hover:text-accent cursor-pointer bg-transparent border-none p-0 leading-none"
|
|
26
|
+
onClick={() => onRemove(mention)}
|
|
27
|
+
tabIndex={-1}
|
|
28
|
+
>
|
|
29
|
+
<X size={10} />
|
|
30
|
+
</button>
|
|
31
|
+
</span>
|
|
32
|
+
);
|
|
33
|
+
};
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MermaidBlock — renders a mermaid code block as an inline SVG diagram.
|
|
3
|
+
*
|
|
4
|
+
* Lazily loads the mermaid library on first render. Respects dark/light theme.
|
|
5
|
+
* Falls back to raw source with error indicator on syntax errors.
|
|
6
|
+
* Provides an enlarge button to open the diagram fullscreen.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { useState, useEffect, useRef, useCallback } from 'react';
|
|
10
|
+
import { Maximize2, AlertTriangle } from 'lucide-react';
|
|
11
|
+
import { DiagramOverlay } from './DiagramOverlay';
|
|
12
|
+
import { resolveMermaidTheme, getDesignSystemThemeVariables } from '../lib/mermaid_helpers';
|
|
13
|
+
|
|
14
|
+
type MermaidApi = typeof import('mermaid').default;
|
|
15
|
+
|
|
16
|
+
let mermaidInstance: MermaidApi | null = null;
|
|
17
|
+
let mermaidLoadPromise: Promise<MermaidApi> | null = null;
|
|
18
|
+
|
|
19
|
+
const loadMermaid = (): Promise<MermaidApi> => {
|
|
20
|
+
if (mermaidInstance) return Promise.resolve(mermaidInstance);
|
|
21
|
+
if (mermaidLoadPromise) return mermaidLoadPromise;
|
|
22
|
+
|
|
23
|
+
mermaidLoadPromise = import('mermaid').then((mod) => {
|
|
24
|
+
mermaidInstance = mod.default;
|
|
25
|
+
mermaidInstance.initialize({ startOnLoad: false, securityLevel: 'strict' });
|
|
26
|
+
return mermaidInstance;
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
return mermaidLoadPromise;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
let renderCounter = 0;
|
|
33
|
+
|
|
34
|
+
interface MermaidBlockProps {
|
|
35
|
+
code: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export const MermaidBlock = ({ code }: MermaidBlockProps) => {
|
|
39
|
+
const [svgHtml, setSvgHtml] = useState<string | null>(null);
|
|
40
|
+
const [error, setError] = useState<string | null>(null);
|
|
41
|
+
const [loading, setLoading] = useState(true);
|
|
42
|
+
const [overlayOpen, setOverlayOpen] = useState(false);
|
|
43
|
+
const containerRef = useRef<HTMLDivElement>(null);
|
|
44
|
+
|
|
45
|
+
const renderDiagram = useCallback(async () => {
|
|
46
|
+
setLoading(true);
|
|
47
|
+
setError(null);
|
|
48
|
+
setSvgHtml(null);
|
|
49
|
+
|
|
50
|
+
try {
|
|
51
|
+
const mermaid = await loadMermaid();
|
|
52
|
+
const theme = resolveMermaidTheme(document.documentElement.getAttribute('data-theme'));
|
|
53
|
+
|
|
54
|
+
mermaid.initialize({
|
|
55
|
+
startOnLoad: false,
|
|
56
|
+
securityLevel: 'strict',
|
|
57
|
+
theme,
|
|
58
|
+
themeVariables: getDesignSystemThemeVariables(),
|
|
59
|
+
flowchart: { padding: 16, nodeSpacing: 60, rankSpacing: 60 },
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
const id = `mermaid-${Date.now()}-${renderCounter++}`;
|
|
63
|
+
const { svg } = await mermaid.render(id, code.trim());
|
|
64
|
+
setSvgHtml(svg);
|
|
65
|
+
} catch (err) {
|
|
66
|
+
const message = err instanceof Error ? err.message : 'Failed to render diagram';
|
|
67
|
+
setError(message);
|
|
68
|
+
} finally {
|
|
69
|
+
setLoading(false);
|
|
70
|
+
}
|
|
71
|
+
}, [code]);
|
|
72
|
+
|
|
73
|
+
useEffect(() => {
|
|
74
|
+
renderDiagram();
|
|
75
|
+
}, [renderDiagram]);
|
|
76
|
+
|
|
77
|
+
// Re-render on theme change
|
|
78
|
+
useEffect(() => {
|
|
79
|
+
const observer = new MutationObserver((mutations) => {
|
|
80
|
+
for (const mutation of mutations) {
|
|
81
|
+
if (mutation.attributeName === 'data-theme') {
|
|
82
|
+
renderDiagram();
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
observer.observe(document.documentElement, { attributes: true });
|
|
89
|
+
return () => observer.disconnect();
|
|
90
|
+
}, [renderDiagram]);
|
|
91
|
+
|
|
92
|
+
const openOverlay = useCallback(() => {
|
|
93
|
+
setOverlayOpen(true);
|
|
94
|
+
}, []);
|
|
95
|
+
|
|
96
|
+
const closeOverlay = useCallback(() => {
|
|
97
|
+
setOverlayOpen(false);
|
|
98
|
+
}, []);
|
|
99
|
+
|
|
100
|
+
if (loading) {
|
|
101
|
+
return (
|
|
102
|
+
<div className="flex items-center justify-center py-6 px-4 rounded-md bg-surface-raised text-content-secondary text-xs font-mono">
|
|
103
|
+
Rendering diagram…
|
|
104
|
+
</div>
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (error) {
|
|
109
|
+
return (
|
|
110
|
+
<div className="rounded-md border border-edge overflow-hidden">
|
|
111
|
+
<div className="flex items-center gap-1.5 px-3 py-1.5 bg-surface-raised text-xs text-amber-400 border-b border-edge">
|
|
112
|
+
<AlertTriangle size={13} />
|
|
113
|
+
<span>Mermaid rendering error</span>
|
|
114
|
+
</div>
|
|
115
|
+
<pre className="bg-surface-raised py-2.5 px-3 overflow-x-auto text-xs leading-normal font-mono text-content m-0">
|
|
116
|
+
{code}
|
|
117
|
+
</pre>
|
|
118
|
+
</div>
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return (
|
|
123
|
+
<>
|
|
124
|
+
<div
|
|
125
|
+
ref={containerRef}
|
|
126
|
+
className="mermaid-diagram relative group rounded-md border border-edge overflow-hidden bg-surface-raised"
|
|
127
|
+
>
|
|
128
|
+
<div
|
|
129
|
+
className="p-5 overflow-x-auto [&_svg]:max-w-full [&_svg]:h-auto"
|
|
130
|
+
dangerouslySetInnerHTML={{ __html: svgHtml! }}
|
|
131
|
+
/>
|
|
132
|
+
<button
|
|
133
|
+
type="button"
|
|
134
|
+
onClick={openOverlay}
|
|
135
|
+
className="absolute top-2 right-2 p-1.5 rounded bg-surface/80 border border-edge text-content-secondary
|
|
136
|
+
opacity-0 group-hover:opacity-100 transition-opacity cursor-pointer hover:text-content hover:bg-surface"
|
|
137
|
+
aria-label="Enlarge diagram"
|
|
138
|
+
>
|
|
139
|
+
<Maximize2 size={14} />
|
|
140
|
+
</button>
|
|
141
|
+
</div>
|
|
142
|
+
|
|
143
|
+
{overlayOpen && svgHtml && (
|
|
144
|
+
<DiagramOverlay svgHtml={svgHtml} onClose={closeOverlay} />
|
|
145
|
+
)}
|
|
146
|
+
</>
|
|
147
|
+
);
|
|
148
|
+
};
|
package/templates/assistkick-product-system/packages/frontend/src/components/PermissionDialog.tsx
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PermissionDialog — modal shown when Claude CLI requests permission to use a tool.
|
|
3
|
+
* Offers three choices: Allow once, Allow for this session, Allow always.
|
|
4
|
+
* Also offers a Deny option.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import React, { useCallback } from 'react';
|
|
8
|
+
|
|
9
|
+
export type PermissionDecision = 'allow_once' | 'allow_session' | 'allow_always' | 'deny';
|
|
10
|
+
|
|
11
|
+
export interface PermissionRequestData {
|
|
12
|
+
requestId: string;
|
|
13
|
+
toolName: string;
|
|
14
|
+
input: Record<string, unknown>;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface PermissionDialogProps {
|
|
18
|
+
request: PermissionRequestData | null;
|
|
19
|
+
onRespond: (requestId: string, decision: PermissionDecision) => void;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function PermissionDialog({ request, onRespond }: PermissionDialogProps) {
|
|
23
|
+
const handleDecision = useCallback((decision: PermissionDecision) => {
|
|
24
|
+
if (!request) return;
|
|
25
|
+
onRespond(request.requestId, decision);
|
|
26
|
+
}, [request, onRespond]);
|
|
27
|
+
|
|
28
|
+
if (!request) return null;
|
|
29
|
+
|
|
30
|
+
const inputSummary = Object.keys(request.input).length > 0
|
|
31
|
+
? JSON.stringify(request.input, null, 2)
|
|
32
|
+
: null;
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-[1000]">
|
|
36
|
+
<div
|
|
37
|
+
className="bg-surface border border-edge rounded-xl p-6 w-[480px] max-w-[90vw] shadow-[0_8px_32px_rgba(0,0,0,0.3)]"
|
|
38
|
+
onClick={e => e.stopPropagation()}
|
|
39
|
+
>
|
|
40
|
+
<div className="flex items-center gap-2 mb-4">
|
|
41
|
+
<div className="w-2 h-2 rounded-full bg-[#f5a623] animate-pulse" />
|
|
42
|
+
<h2 className="m-0 text-lg text-content font-mono">Permission Required</h2>
|
|
43
|
+
</div>
|
|
44
|
+
|
|
45
|
+
<p className="text-sm text-content-secondary mb-3 font-mono">
|
|
46
|
+
Claude wants to use the following tool:
|
|
47
|
+
</p>
|
|
48
|
+
|
|
49
|
+
<div className="bg-surface-raised border border-edge rounded-lg px-4 py-3 mb-4">
|
|
50
|
+
<div className="font-mono text-sm text-accent font-semibold">{request.toolName}</div>
|
|
51
|
+
{inputSummary && (
|
|
52
|
+
<pre className="mt-2 text-xs text-content-secondary font-mono whitespace-pre-wrap break-words max-h-[200px] overflow-y-auto m-0">
|
|
53
|
+
{inputSummary}
|
|
54
|
+
</pre>
|
|
55
|
+
)}
|
|
56
|
+
</div>
|
|
57
|
+
|
|
58
|
+
<div className="flex flex-col gap-2">
|
|
59
|
+
<button
|
|
60
|
+
className="w-full h-9 bg-transparent border border-accent rounded text-accent font-mono text-[13px] cursor-pointer transition-[background,color] duration-150 hover:bg-accent hover:text-white"
|
|
61
|
+
onClick={() => handleDecision('allow_once')}
|
|
62
|
+
type="button"
|
|
63
|
+
>
|
|
64
|
+
Allow once
|
|
65
|
+
</button>
|
|
66
|
+
<button
|
|
67
|
+
className="w-full h-9 bg-transparent border border-accent rounded text-accent font-mono text-[13px] cursor-pointer transition-[background,color] duration-150 hover:bg-accent hover:text-white"
|
|
68
|
+
onClick={() => handleDecision('allow_session')}
|
|
69
|
+
type="button"
|
|
70
|
+
>
|
|
71
|
+
Allow for this session
|
|
72
|
+
</button>
|
|
73
|
+
<button
|
|
74
|
+
className="w-full h-9 bg-transparent border border-accent rounded text-accent font-mono text-[13px] cursor-pointer transition-[background,color] duration-150 hover:bg-accent hover:text-white"
|
|
75
|
+
onClick={() => handleDecision('allow_always')}
|
|
76
|
+
type="button"
|
|
77
|
+
>
|
|
78
|
+
Allow always for this tool
|
|
79
|
+
</button>
|
|
80
|
+
<button
|
|
81
|
+
className="w-full h-9 bg-transparent border border-error rounded text-error font-mono text-[13px] cursor-pointer transition-[background,color] duration-150 hover:bg-error hover:text-white mt-1"
|
|
82
|
+
onClick={() => handleDecision('deny')}
|
|
83
|
+
type="button"
|
|
84
|
+
>
|
|
85
|
+
Deny
|
|
86
|
+
</button>
|
|
87
|
+
</div>
|
|
88
|
+
</div>
|
|
89
|
+
</div>
|
|
90
|
+
);
|
|
91
|
+
}
|