@4djs/assistant 0.0.0 → 0.0.1

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 (188) hide show
  1. package/dist/core/chat-activity.d.ts +19 -0
  2. package/dist/core/chat-activity.d.ts.map +1 -0
  3. package/dist/core/chat-commands.d.ts +33 -0
  4. package/dist/core/chat-commands.d.ts.map +1 -0
  5. package/dist/core/chat-history.d.ts +14 -0
  6. package/dist/core/chat-history.d.ts.map +1 -0
  7. package/dist/core/chat-reply-suggestions-parse.d.ts +20 -0
  8. package/dist/core/chat-reply-suggestions-parse.d.ts.map +1 -0
  9. package/dist/core/code-highlight.d.ts +3 -0
  10. package/dist/core/code-highlight.d.ts.map +1 -0
  11. package/dist/core/create-assistant-store.d.ts +33 -0
  12. package/dist/core/create-assistant-store.d.ts.map +1 -0
  13. package/dist/core/fetch-suggested-prompts.d.ts +11 -0
  14. package/dist/core/fetch-suggested-prompts.d.ts.map +1 -0
  15. package/dist/core/index.d.ts +19 -0
  16. package/dist/core/index.d.ts.map +1 -0
  17. package/dist/core/index.js +2876 -0
  18. package/dist/core/interactive-tools/choices.d.ts +22 -0
  19. package/dist/core/interactive-tools/choices.d.ts.map +1 -0
  20. package/dist/core/interactive-tools/confirmation.d.ts +15 -0
  21. package/dist/core/interactive-tools/confirmation.d.ts.map +1 -0
  22. package/dist/core/interactive-tools/constants.d.ts +6 -0
  23. package/dist/core/interactive-tools/constants.d.ts.map +1 -0
  24. package/dist/core/interactive-tools/execute.d.ts +11 -0
  25. package/dist/core/interactive-tools/execute.d.ts.map +1 -0
  26. package/dist/core/interactive-tools/index.d.ts +7 -0
  27. package/dist/core/interactive-tools/index.d.ts.map +1 -0
  28. package/dist/core/interactive-tools/suggestions.d.ts +13 -0
  29. package/dist/core/interactive-tools/suggestions.d.ts.map +1 -0
  30. package/dist/core/interactive-tools/waiters.d.ts +4 -0
  31. package/dist/core/interactive-tools/waiters.d.ts.map +1 -0
  32. package/dist/core/llm-chat.d.ts +96 -0
  33. package/dist/core/llm-chat.d.ts.map +1 -0
  34. package/dist/core/llm-config.d.ts +24 -0
  35. package/dist/core/llm-config.d.ts.map +1 -0
  36. package/dist/core/llm-models.d.ts +14 -0
  37. package/dist/core/llm-models.d.ts.map +1 -0
  38. package/dist/core/llm-provider.d.ts +13 -0
  39. package/dist/core/llm-provider.d.ts.map +1 -0
  40. package/dist/core/llm-settings-storage.d.ts +47 -0
  41. package/dist/core/llm-settings-storage.d.ts.map +1 -0
  42. package/dist/core/llm-sse.d.ts +13 -0
  43. package/dist/core/llm-sse.d.ts.map +1 -0
  44. package/dist/core/llm-types.d.ts +49 -0
  45. package/dist/core/llm-types.d.ts.map +1 -0
  46. package/dist/core/markdown-utils.d.ts +3 -0
  47. package/dist/core/markdown-utils.d.ts.map +1 -0
  48. package/dist/core/prepare-markdown.d.ts +7 -0
  49. package/dist/core/prepare-markdown.d.ts.map +1 -0
  50. package/dist/core/types.d.ts +74 -0
  51. package/dist/core/types.d.ts.map +1 -0
  52. package/dist/index.css +1195 -0
  53. package/dist/index.js +184948 -0
  54. package/dist/react/Assistant.d.ts +10 -0
  55. package/dist/react/Assistant.d.ts.map +1 -0
  56. package/dist/react/components/HighlightedJsonCode.d.ts +6 -0
  57. package/dist/react/components/HighlightedJsonCode.d.ts.map +1 -0
  58. package/dist/react/components/MarkdownContent.d.ts +10 -0
  59. package/dist/react/components/MarkdownContent.d.ts.map +1 -0
  60. package/dist/react/components/MarkdownEditor.d.ts +11 -0
  61. package/dist/react/components/MarkdownEditor.d.ts.map +1 -0
  62. package/dist/react/components/MermaidDiagram.d.ts +8 -0
  63. package/dist/react/components/MermaidDiagram.d.ts.map +1 -0
  64. package/dist/react/components/ModelSelector.d.ts +8 -0
  65. package/dist/react/components/ModelSelector.d.ts.map +1 -0
  66. package/dist/react/components/chat/AssistantErrorCallout.d.ts +11 -0
  67. package/dist/react/components/chat/AssistantErrorCallout.d.ts.map +1 -0
  68. package/dist/react/components/chat/ChatActivity.d.ts +8 -0
  69. package/dist/react/components/chat/ChatActivity.d.ts.map +1 -0
  70. package/dist/react/components/chat/ChatComposer.d.ts +36 -0
  71. package/dist/react/components/chat/ChatComposer.d.ts.map +1 -0
  72. package/dist/react/components/chat/ChatEmptyState.d.ts +10 -0
  73. package/dist/react/components/chat/ChatEmptyState.d.ts.map +1 -0
  74. package/dist/react/components/chat/ChatInteractivePrompt/choices-prompt.d.ts +7 -0
  75. package/dist/react/components/chat/ChatInteractivePrompt/choices-prompt.d.ts.map +1 -0
  76. package/dist/react/components/chat/ChatInteractivePrompt/confirmation-prompt.d.ts +7 -0
  77. package/dist/react/components/chat/ChatInteractivePrompt/confirmation-prompt.d.ts.map +1 -0
  78. package/dist/react/components/chat/ChatInteractivePrompt/index.d.ts +7 -0
  79. package/dist/react/components/chat/ChatInteractivePrompt/index.d.ts.map +1 -0
  80. package/dist/react/components/chat/ChatInteractivePrompt/shell.d.ts +13 -0
  81. package/dist/react/components/chat/ChatInteractivePrompt/shell.d.ts.map +1 -0
  82. package/dist/react/components/chat/ChatInteractivePrompt/utils.d.ts +4 -0
  83. package/dist/react/components/chat/ChatInteractivePrompt/utils.d.ts.map +1 -0
  84. package/dist/react/components/chat/ChatMessage.d.ts +11 -0
  85. package/dist/react/components/chat/ChatMessage.d.ts.map +1 -0
  86. package/dist/react/components/chat/ChatMessageScroll.d.ts +8 -0
  87. package/dist/react/components/chat/ChatMessageScroll.d.ts.map +1 -0
  88. package/dist/react/components/chat/ChatReplySuggestions.d.ts +9 -0
  89. package/dist/react/components/chat/ChatReplySuggestions.d.ts.map +1 -0
  90. package/dist/react/components/chat/ComposerCommandMenu.d.ts +10 -0
  91. package/dist/react/components/chat/ComposerCommandMenu.d.ts.map +1 -0
  92. package/dist/react/components/chat/LlmSettingsStrip.d.ts +7 -0
  93. package/dist/react/components/chat/LlmSettingsStrip.d.ts.map +1 -0
  94. package/dist/react/components/chat/LlmSetupPrompt.d.ts +7 -0
  95. package/dist/react/components/chat/LlmSetupPrompt.d.ts.map +1 -0
  96. package/dist/react/components/chat/LlmUnavailableBanner.d.ts +6 -0
  97. package/dist/react/components/chat/LlmUnavailableBanner.d.ts.map +1 -0
  98. package/dist/react/components/chat/SuggestedPromptsList.d.ts +14 -0
  99. package/dist/react/components/chat/SuggestedPromptsList.d.ts.map +1 -0
  100. package/dist/react/components/chat/SuggestedPromptsStrip.d.ts +11 -0
  101. package/dist/react/components/chat/SuggestedPromptsStrip.d.ts.map +1 -0
  102. package/dist/react/components/chat/SystemPromptField.d.ts +10 -0
  103. package/dist/react/components/chat/SystemPromptField.d.ts.map +1 -0
  104. package/dist/react/components/highlighted-code.d.ts +8 -0
  105. package/dist/react/components/highlighted-code.d.ts.map +1 -0
  106. package/dist/react/context.d.ts +11 -0
  107. package/dist/react/context.d.ts.map +1 -0
  108. package/dist/react/hooks/use-composer-commands.d.ts +21 -0
  109. package/dist/react/hooks/use-composer-commands.d.ts.map +1 -0
  110. package/dist/react/hooks/use-suggested-prompts.d.ts +29 -0
  111. package/dist/react/hooks/use-suggested-prompts.d.ts.map +1 -0
  112. package/dist/react/index.d.ts +17 -0
  113. package/dist/react/index.d.ts.map +1 -0
  114. package/dist/react/lib/parse-assistant-error.d.ts +9 -0
  115. package/dist/react/lib/parse-assistant-error.d.ts.map +1 -0
  116. package/dist/react/lib/prompt-icons.d.ts +5 -0
  117. package/dist/react/lib/prompt-icons.d.ts.map +1 -0
  118. package/dist/react/types.d.ts +69 -0
  119. package/dist/react/types.d.ts.map +1 -0
  120. package/dist/react/utils/cn.d.ts +2 -0
  121. package/dist/react/utils/cn.d.ts.map +1 -0
  122. package/package.json +16 -5
  123. package/src/core/chat-activity.ts +0 -107
  124. package/src/core/chat-commands.ts +0 -173
  125. package/src/core/chat-history.ts +0 -113
  126. package/src/core/chat-reply-suggestions-parse.ts +0 -119
  127. package/src/core/code-highlight.ts +0 -20
  128. package/src/core/create-assistant-store.ts +0 -639
  129. package/src/core/fetch-suggested-prompts.ts +0 -53
  130. package/src/core/index.ts +0 -125
  131. package/src/core/interactive-tools/choices.ts +0 -155
  132. package/src/core/interactive-tools/confirmation.ts +0 -63
  133. package/src/core/interactive-tools/constants.ts +0 -22
  134. package/src/core/interactive-tools/execute.ts +0 -70
  135. package/src/core/interactive-tools/index.ts +0 -41
  136. package/src/core/interactive-tools/suggestions.ts +0 -87
  137. package/src/core/interactive-tools/waiters.ts +0 -55
  138. package/src/core/llm-chat.ts +0 -686
  139. package/src/core/llm-config.ts +0 -101
  140. package/src/core/llm-models.ts +0 -96
  141. package/src/core/llm-provider.ts +0 -99
  142. package/src/core/llm-settings-storage.ts +0 -331
  143. package/src/core/llm-sse.ts +0 -166
  144. package/src/core/llm-types.ts +0 -52
  145. package/src/core/markdown-utils.ts +0 -11
  146. package/src/core/prepare-markdown.ts +0 -38
  147. package/src/core/types.ts +0 -86
  148. package/src/css.d.ts +0 -1
  149. package/src/react/Assistant.tsx +0 -358
  150. package/src/react/components/HighlightedJsonCode.tsx +0 -24
  151. package/src/react/components/MarkdownContent.tsx +0 -98
  152. package/src/react/components/MarkdownEditor.tsx +0 -60
  153. package/src/react/components/MermaidDiagram.tsx +0 -139
  154. package/src/react/components/ModelSelector.tsx +0 -243
  155. package/src/react/components/chat/AssistantErrorCallout.tsx +0 -79
  156. package/src/react/components/chat/ChatActivity.tsx +0 -274
  157. package/src/react/components/chat/ChatComposer.tsx +0 -189
  158. package/src/react/components/chat/ChatEmptyState.tsx +0 -145
  159. package/src/react/components/chat/ChatInteractivePrompt/choices-prompt.tsx +0 -262
  160. package/src/react/components/chat/ChatInteractivePrompt/confirmation-prompt.tsx +0 -97
  161. package/src/react/components/chat/ChatInteractivePrompt/index.tsx +0 -60
  162. package/src/react/components/chat/ChatInteractivePrompt/shell.tsx +0 -60
  163. package/src/react/components/chat/ChatInteractivePrompt/utils.ts +0 -14
  164. package/src/react/components/chat/ChatMessage.tsx +0 -150
  165. package/src/react/components/chat/ChatMessageScroll.tsx +0 -116
  166. package/src/react/components/chat/ChatReplySuggestions.tsx +0 -231
  167. package/src/react/components/chat/ComposerCommandMenu.tsx +0 -69
  168. package/src/react/components/chat/LlmSettingsStrip.tsx +0 -348
  169. package/src/react/components/chat/LlmSetupPrompt.tsx +0 -58
  170. package/src/react/components/chat/LlmUnavailableBanner.tsx +0 -11
  171. package/src/react/components/chat/SuggestedPromptsList.tsx +0 -121
  172. package/src/react/components/chat/SuggestedPromptsStrip.tsx +0 -72
  173. package/src/react/components/chat/SystemPromptField.tsx +0 -107
  174. package/src/react/components/highlighted-code.tsx +0 -107
  175. package/src/react/context.tsx +0 -72
  176. package/src/react/hooks/use-composer-commands.ts +0 -129
  177. package/src/react/hooks/use-suggested-prompts.ts +0 -128
  178. package/src/react/index.ts +0 -39
  179. package/src/react/lib/parse-assistant-error.ts +0 -96
  180. package/src/react/lib/prompt-icons.ts +0 -40
  181. package/src/react/types.ts +0 -83
  182. package/src/react/utils/cn.ts +0 -5
  183. package/test/buildLlmHistory.test.ts +0 -95
  184. package/test/llm-config.test.ts +0 -72
  185. package/test/llmSettingsStorage.test.ts +0 -121
  186. package/test/parse-assistant-error.test.ts +0 -24
  187. package/tsconfig.json +0 -8
  188. /package/{src/styles/assistant.css → dist/styles.css} +0 -0
@@ -1,116 +0,0 @@
1
- import { ArrowDown } from "lucide-react";
2
- import {
3
- type ReactNode,
4
- useCallback,
5
- useEffect,
6
- useRef,
7
- useState,
8
- } from "react";
9
-
10
- const SCROLL_BOTTOM_THRESHOLD = 48;
11
-
12
- function isNearBottom(viewport: HTMLDivElement): boolean {
13
- return (
14
- viewport.scrollHeight - viewport.scrollTop - viewport.clientHeight <=
15
- SCROLL_BOTTOM_THRESHOLD
16
- );
17
- }
18
-
19
- interface ChatMessageScrollProps {
20
- children: ReactNode;
21
- dependencyKey: string;
22
- }
23
-
24
- export function ChatMessageScroll({
25
- children,
26
- dependencyKey,
27
- }: ChatMessageScrollProps) {
28
- const scrollContainerRef = useRef<HTMLDivElement>(null);
29
- const contentRef = useRef<HTMLDivElement>(null);
30
- const stickToBottomRef = useRef(true);
31
- const [showScrollDown, setShowScrollDown] = useState(false);
32
-
33
- const updateScrollState = useCallback(() => {
34
- const viewport = scrollContainerRef.current;
35
- if (!viewport) return;
36
- const atBottom = isNearBottom(viewport);
37
- setShowScrollDown(!atBottom);
38
- stickToBottomRef.current = atBottom;
39
- }, []);
40
-
41
- const scrollToBottom = useCallback((behavior: ScrollBehavior = "smooth") => {
42
- const viewport = scrollContainerRef.current;
43
- if (!viewport) return;
44
- viewport.scrollTo({ top: viewport.scrollHeight, behavior });
45
- stickToBottomRef.current = true;
46
- setShowScrollDown(false);
47
- }, []);
48
-
49
- const handleContentResize = useCallback(() => {
50
- const viewport = scrollContainerRef.current;
51
- if (!viewport) return;
52
- if (stickToBottomRef.current) {
53
- viewport.scrollTo({ top: viewport.scrollHeight, behavior: "auto" });
54
- setShowScrollDown(false);
55
- return;
56
- }
57
- updateScrollState();
58
- }, [updateScrollState]);
59
-
60
- useEffect(() => {
61
- const content = contentRef.current;
62
- if (!content) return;
63
- const resizeObserver = new ResizeObserver(handleContentResize);
64
- resizeObserver.observe(content);
65
- return () => resizeObserver.disconnect();
66
- }, [handleContentResize]);
67
-
68
- useEffect(() => {
69
- const viewport = scrollContainerRef.current;
70
- if (!viewport) return;
71
- updateScrollState();
72
- viewport.addEventListener("scroll", updateScrollState, { passive: true });
73
- return () => viewport.removeEventListener("scroll", updateScrollState);
74
- }, [updateScrollState]);
75
-
76
- useEffect(() => {
77
- const viewport = scrollContainerRef.current;
78
- if (!viewport) return;
79
- void dependencyKey;
80
- if (!stickToBottomRef.current) {
81
- updateScrollState();
82
- return;
83
- }
84
- viewport.scrollTo({
85
- top: viewport.scrollHeight,
86
- behavior: "auto",
87
- });
88
- setShowScrollDown(false);
89
- }, [dependencyKey, updateScrollState]);
90
-
91
- return (
92
- <div className="relative h-0 min-h-0 flex-1">
93
- <div
94
- ref={scrollContainerRef}
95
- className="h-full overflow-x-hidden overflow-y-auto overscroll-contain bg-[var(--overlay-subtle)]"
96
- aria-live="polite"
97
- >
98
- <div ref={contentRef} className="assistant-message-list">
99
- {children}
100
- <div aria-hidden className="h-px shrink-0" />
101
- </div>
102
- </div>
103
- {showScrollDown ? (
104
- <button
105
- type="button"
106
- className="assistant-scroll-down"
107
- aria-label="Scroll to bottom"
108
- title="Scroll to bottom"
109
- onClick={() => scrollToBottom("smooth")}
110
- >
111
- <ArrowDown size={16} aria-hidden />
112
- </button>
113
- ) : null}
114
- </div>
115
- );
116
- }
@@ -1,231 +0,0 @@
1
- import { ArrowUpRight, PenLine } from "lucide-react";
2
- import { useEffect } from "react";
3
- import {
4
- type ParsedSuggestion,
5
- parseSuggestionText,
6
- splitToolValues,
7
- } from "../../../core/chat-reply-suggestions-parse.ts";
8
- import type { ReplySuggestions } from "../../../core/interactive-tools/index.ts";
9
- import { cn } from "../../utils/cn.ts";
10
-
11
- type ChatReplySuggestionsProps = {
12
- suggestions: ReplySuggestions;
13
- disabled?: boolean;
14
- onSelect: (reply: string) => void;
15
- };
16
-
17
- function fieldBadgeLabel(label: string): string {
18
- switch (label.toLowerCase()) {
19
- case "model":
20
- return "Model";
21
- case "enabled":
22
- return "Status";
23
- case "tools":
24
- return "Tools";
25
- case "dataclass":
26
- return "Dataclass";
27
- case "filter":
28
- return "Filter";
29
- default:
30
- return label;
31
- }
32
- }
33
-
34
- function StructuredSuggestionRow({
35
- suggestion,
36
- index,
37
- disabled,
38
- onSelect,
39
- }: {
40
- suggestion: Extract<ParsedSuggestion, { kind: "structured" }>;
41
- index: number;
42
- disabled?: boolean;
43
- onSelect: () => void;
44
- }) {
45
- const toolsField = suggestion.fields.find(
46
- (field) => field.label.toLowerCase() === "tools",
47
- );
48
- const metaFields = suggestion.fields.filter(
49
- (field) => field.label.toLowerCase() !== "tools",
50
- );
51
- const toolNames = toolsField ? splitToolValues(toolsField.value) : [];
52
-
53
- return (
54
- <button
55
- type="button"
56
- disabled={disabled}
57
- className="assistant-reply-option assistant-reply-option--structured group"
58
- onClick={onSelect}
59
- >
60
- <span className="assistant-reply-option__index" aria-hidden>
61
- {index + 1}
62
- </span>
63
- <span className="assistant-reply-option__body">
64
- <span className="assistant-reply-option__label">
65
- {suggestion.title}
66
- </span>
67
- {suggestion.description ? (
68
- <span className="assistant-reply-option__meta">
69
- {suggestion.description}
70
- </span>
71
- ) : null}
72
- {(metaFields.length > 0 || toolNames.length > 0) && (
73
- <span className="assistant-reply-option__badges">
74
- {metaFields.map((field) => (
75
- <span
76
- key={`${field.label}-${field.value}`}
77
- className="assistant-reply-badge"
78
- >
79
- <span className="assistant-reply-badge__label">
80
- {fieldBadgeLabel(field.label)}
81
- </span>
82
- <span className="assistant-reply-badge__value">
83
- {field.value}
84
- </span>
85
- </span>
86
- ))}
87
- {toolNames.map((tool) => (
88
- <span key={tool} className="assistant-reply-tool">
89
- {tool}
90
- </span>
91
- ))}
92
- </span>
93
- )}
94
- </span>
95
- <ArrowUpRight
96
- className="assistant-reply-option__arrow size-3.5 shrink-0"
97
- aria-hidden
98
- />
99
- </button>
100
- );
101
- }
102
-
103
- function CompactSuggestionRow({
104
- text,
105
- index,
106
- disabled,
107
- custom,
108
- onSelect,
109
- }: {
110
- text: string;
111
- index: number;
112
- disabled?: boolean;
113
- custom?: boolean;
114
- onSelect: () => void;
115
- }) {
116
- return (
117
- <button
118
- type="button"
119
- disabled={disabled}
120
- className={cn(
121
- "assistant-reply-option group",
122
- custom && "assistant-reply-option--custom",
123
- )}
124
- onClick={onSelect}
125
- >
126
- <span className="assistant-reply-option__index" aria-hidden>
127
- {index + 1}
128
- </span>
129
- <span className="assistant-reply-option__body">
130
- {custom ? (
131
- <span className="assistant-reply-option__custom">
132
- <PenLine className="size-3 shrink-0" aria-hidden />
133
- <span>{text}</span>
134
- </span>
135
- ) : (
136
- <span className="assistant-reply-option__label">{text}</span>
137
- )}
138
- </span>
139
- <ArrowUpRight
140
- className="assistant-reply-option__arrow size-3.5 shrink-0"
141
- aria-hidden
142
- />
143
- </button>
144
- );
145
- }
146
-
147
- export function ChatReplySuggestions({
148
- suggestions,
149
- disabled,
150
- onSelect,
151
- }: ChatReplySuggestionsProps) {
152
- const parsed = suggestions.suggestions.map((text) => ({
153
- raw: text,
154
- parsed: parseSuggestionText(text),
155
- }));
156
-
157
- useEffect(() => {
158
- if (disabled) return;
159
-
160
- function onKeyDown(event: KeyboardEvent) {
161
- if (!/^[1-9]$/.test(event.key)) return;
162
-
163
- const index = Number(event.key) - 1;
164
- const target = suggestions.suggestions[index];
165
- if (!target) return;
166
-
167
- const active = document.activeElement;
168
- if (
169
- active instanceof HTMLElement &&
170
- (active.tagName === "INPUT" ||
171
- active.tagName === "TEXTAREA" ||
172
- active.isContentEditable)
173
- ) {
174
- return;
175
- }
176
-
177
- event.preventDefault();
178
- onSelect(target);
179
- }
180
-
181
- window.addEventListener("keydown", onKeyDown);
182
- return () => window.removeEventListener("keydown", onKeyDown);
183
- }, [disabled, onSelect, suggestions.suggestions]);
184
-
185
- return (
186
- <fieldset className="assistant-reply-suggestions border-0 p-0 m-0 min-w-0">
187
- <legend className="sr-only">Suggested replies</legend>
188
- <div className="assistant-reply-suggestions__panel">
189
- <div className="assistant-reply-suggestions__list">
190
- {parsed.map((entry, index) => {
191
- if (entry.parsed.kind === "structured") {
192
- return (
193
- <StructuredSuggestionRow
194
- key={entry.raw}
195
- suggestion={
196
- entry.parsed as Extract<
197
- ParsedSuggestion,
198
- { kind: "structured" }
199
- >
200
- }
201
- index={index}
202
- disabled={disabled}
203
- onSelect={() => onSelect(entry.raw)}
204
- />
205
- );
206
- }
207
-
208
- return (
209
- <CompactSuggestionRow
210
- key={entry.raw}
211
- text={entry.raw}
212
- index={index}
213
- disabled={disabled}
214
- custom={entry.parsed.kind === "custom"}
215
- onSelect={() => onSelect(entry.raw)}
216
- />
217
- );
218
- })}
219
- </div>
220
- <p className="assistant-reply-suggestions__hint">
221
- <kbd className="assistant-reply-kbd">1</kbd>
222
- <span aria-hidden>–</span>
223
- <kbd className="assistant-reply-kbd">
224
- {suggestions.suggestions.length}
225
- </kbd>
226
- <span>to pick · or type below</span>
227
- </p>
228
- </div>
229
- </fieldset>
230
- );
231
- }
@@ -1,69 +0,0 @@
1
- import { Terminal } from "lucide-react";
2
- import type { ChatCommandSuggestion } from "../../../core/chat-commands.ts";
3
- import { cn } from "../../utils/cn.ts";
4
-
5
- interface ComposerCommandMenuProps {
6
- commands: ChatCommandSuggestion[];
7
- selectedIndex: number;
8
- onSelect: (command: ChatCommandSuggestion) => void;
9
- className?: string;
10
- }
11
-
12
- export function ComposerCommandMenu({
13
- commands,
14
- selectedIndex,
15
- onSelect,
16
- className,
17
- }: ComposerCommandMenuProps) {
18
- if (commands.length === 0) {
19
- return null;
20
- }
21
-
22
- return (
23
- <div
24
- className={cn("composer-command-menu", className)}
25
- role="listbox"
26
- aria-label="Composer commands"
27
- >
28
- <div className="composer-command-menu__header">Commands</div>
29
- <ul className="composer-command-menu__list">
30
- {commands.map((command, index) => {
31
- const active = index === selectedIndex;
32
-
33
- return (
34
- <li key={command.name} role="presentation">
35
- <button
36
- type="button"
37
- role="option"
38
- aria-selected={active}
39
- className={cn(
40
- "composer-command-menu__item",
41
- active && "composer-command-menu__item--active",
42
- )}
43
- onMouseDown={(event) => {
44
- event.preventDefault();
45
- onSelect(command);
46
- }}
47
- >
48
- <Terminal
49
- className="composer-command-menu__icon"
50
- size={14}
51
- strokeWidth={2}
52
- aria-hidden
53
- />
54
- <span className="min-w-0">
55
- <span className="composer-command-menu__usage">
56
- {command.usage}
57
- </span>
58
- <span className="composer-command-menu__description">
59
- {command.description}
60
- </span>
61
- </span>
62
- </button>
63
- </li>
64
- );
65
- })}
66
- </ul>
67
- </div>
68
- );
69
- }