@raindrop-ai/wizard 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 (135) hide show
  1. package/LICENSE +47 -0
  2. package/dist/bin.d.ts +2 -0
  3. package/dist/bin.js +117 -0
  4. package/dist/bin.js.map +1 -0
  5. package/dist/src/docs/browser.md +105 -0
  6. package/dist/src/docs/python.md +618 -0
  7. package/dist/src/docs/typescript.md +584 -0
  8. package/dist/src/docs/vercel-ai-sdk.md +304 -0
  9. package/dist/src/lib/agent-interface.d.ts +46 -0
  10. package/dist/src/lib/agent-interface.js +292 -0
  11. package/dist/src/lib/agent-interface.js.map +1 -0
  12. package/dist/src/lib/agent-prompts.d.ts +10 -0
  13. package/dist/src/lib/agent-prompts.js +49 -0
  14. package/dist/src/lib/agent-prompts.js.map +1 -0
  15. package/dist/src/lib/config.d.ts +39 -0
  16. package/dist/src/lib/config.js +549 -0
  17. package/dist/src/lib/config.js.map +1 -0
  18. package/dist/src/lib/constants.d.ts +27 -0
  19. package/dist/src/lib/constants.js +165 -0
  20. package/dist/src/lib/constants.js.map +1 -0
  21. package/dist/src/lib/handlers.d.ts +68 -0
  22. package/dist/src/lib/handlers.js +420 -0
  23. package/dist/src/lib/handlers.js.map +1 -0
  24. package/dist/src/lib/integration-testing.d.ts +44 -0
  25. package/dist/src/lib/integration-testing.js +123 -0
  26. package/dist/src/lib/integration-testing.js.map +1 -0
  27. package/dist/src/lib/mcp.d.ts +14 -0
  28. package/dist/src/lib/mcp.js +134 -0
  29. package/dist/src/lib/mcp.js.map +1 -0
  30. package/dist/src/lib/sdk-messages.d.ts +17 -0
  31. package/dist/src/lib/sdk-messages.js +278 -0
  32. package/dist/src/lib/sdk-messages.js.map +1 -0
  33. package/dist/src/lib/wizard.d.ts +6 -0
  34. package/dist/src/lib/wizard.js +131 -0
  35. package/dist/src/lib/wizard.js.map +1 -0
  36. package/dist/src/run.d.ts +8 -0
  37. package/dist/src/run.js +53 -0
  38. package/dist/src/run.js.map +1 -0
  39. package/dist/src/ui/App.d.ts +15 -0
  40. package/dist/src/ui/App.js +27 -0
  41. package/dist/src/ui/App.js.map +1 -0
  42. package/dist/src/ui/cancellation.d.ts +14 -0
  43. package/dist/src/ui/cancellation.js +17 -0
  44. package/dist/src/ui/cancellation.js.map +1 -0
  45. package/dist/src/ui/components/ClarifyingQuestionsPrompt.d.ts +17 -0
  46. package/dist/src/ui/components/ClarifyingQuestionsPrompt.js +359 -0
  47. package/dist/src/ui/components/ClarifyingQuestionsPrompt.js.map +1 -0
  48. package/dist/src/ui/components/ContinuePrompt.d.ts +14 -0
  49. package/dist/src/ui/components/ContinuePrompt.js +23 -0
  50. package/dist/src/ui/components/ContinuePrompt.js.map +1 -0
  51. package/dist/src/ui/components/DiffDisplay.d.ts +18 -0
  52. package/dist/src/ui/components/DiffDisplay.js +110 -0
  53. package/dist/src/ui/components/DiffDisplay.js.map +1 -0
  54. package/dist/src/ui/components/FeedbackSelectPrompt.d.ts +20 -0
  55. package/dist/src/ui/components/FeedbackSelectPrompt.js +132 -0
  56. package/dist/src/ui/components/FeedbackSelectPrompt.js.map +1 -0
  57. package/dist/src/ui/components/HistoryItemDisplay.d.ts +14 -0
  58. package/dist/src/ui/components/HistoryItemDisplay.js +140 -0
  59. package/dist/src/ui/components/HistoryItemDisplay.js.map +1 -0
  60. package/dist/src/ui/components/Logo.d.ts +10 -0
  61. package/dist/src/ui/components/Logo.js +47 -0
  62. package/dist/src/ui/components/Logo.js.map +1 -0
  63. package/dist/src/ui/components/OrgInfoBox.d.ts +11 -0
  64. package/dist/src/ui/components/OrgInfoBox.js +16 -0
  65. package/dist/src/ui/components/OrgInfoBox.js.map +1 -0
  66. package/dist/src/ui/components/PendingPrompt.d.ts +18 -0
  67. package/dist/src/ui/components/PendingPrompt.js +57 -0
  68. package/dist/src/ui/components/PendingPrompt.js.map +1 -0
  69. package/dist/src/ui/components/PersistentTextInput.d.ts +21 -0
  70. package/dist/src/ui/components/PersistentTextInput.js +117 -0
  71. package/dist/src/ui/components/PersistentTextInput.js.map +1 -0
  72. package/dist/src/ui/components/PlanApprovalPrompt.d.ts +19 -0
  73. package/dist/src/ui/components/PlanApprovalPrompt.js +62 -0
  74. package/dist/src/ui/components/PlanApprovalPrompt.js.map +1 -0
  75. package/dist/src/ui/components/PromptContainer.d.ts +14 -0
  76. package/dist/src/ui/components/PromptContainer.js +18 -0
  77. package/dist/src/ui/components/PromptContainer.js.map +1 -0
  78. package/dist/src/ui/components/SelectPrompt.d.ts +14 -0
  79. package/dist/src/ui/components/SelectPrompt.js +62 -0
  80. package/dist/src/ui/components/SelectPrompt.js.map +1 -0
  81. package/dist/src/ui/components/SpinnerDisplay.d.ts +13 -0
  82. package/dist/src/ui/components/SpinnerDisplay.js +11 -0
  83. package/dist/src/ui/components/SpinnerDisplay.js.map +1 -0
  84. package/dist/src/ui/components/ToolApprovalPrompt.d.ts +14 -0
  85. package/dist/src/ui/components/ToolApprovalPrompt.js +142 -0
  86. package/dist/src/ui/components/ToolApprovalPrompt.js.map +1 -0
  87. package/dist/src/ui/components/ToolCallDisplay.d.ts +14 -0
  88. package/dist/src/ui/components/ToolCallDisplay.js +83 -0
  89. package/dist/src/ui/components/ToolCallDisplay.js.map +1 -0
  90. package/dist/src/ui/components/WriteKeyDisplay.d.ts +15 -0
  91. package/dist/src/ui/components/WriteKeyDisplay.js +13 -0
  92. package/dist/src/ui/components/WriteKeyDisplay.js.map +1 -0
  93. package/dist/src/ui/contexts/WizardContext.d.ts +210 -0
  94. package/dist/src/ui/contexts/WizardContext.js +362 -0
  95. package/dist/src/ui/contexts/WizardContext.js.map +1 -0
  96. package/dist/src/ui/hooks/useCancellation.d.ts +15 -0
  97. package/dist/src/ui/hooks/useCancellation.js +25 -0
  98. package/dist/src/ui/hooks/useCancellation.js.map +1 -0
  99. package/dist/src/ui/render.d.ts +34 -0
  100. package/dist/src/ui/render.js +94 -0
  101. package/dist/src/ui/render.js.map +1 -0
  102. package/dist/src/ui/types.d.ts +184 -0
  103. package/dist/src/ui/types.js +6 -0
  104. package/dist/src/ui/types.js.map +1 -0
  105. package/dist/src/utils/clack-utils.d.ts +13 -0
  106. package/dist/src/utils/clack-utils.js +131 -0
  107. package/dist/src/utils/clack-utils.js.map +1 -0
  108. package/dist/src/utils/debug.d.ts +13 -0
  109. package/dist/src/utils/debug.js +47 -0
  110. package/dist/src/utils/debug.js.map +1 -0
  111. package/dist/src/utils/environment.d.ts +5 -0
  112. package/dist/src/utils/environment.js +131 -0
  113. package/dist/src/utils/environment.js.map +1 -0
  114. package/dist/src/utils/logging.d.ts +9 -0
  115. package/dist/src/utils/logging.js +38 -0
  116. package/dist/src/utils/logging.js.map +1 -0
  117. package/dist/src/utils/oauth.d.ts +12 -0
  118. package/dist/src/utils/oauth.js +497 -0
  119. package/dist/src/utils/oauth.js.map +1 -0
  120. package/dist/src/utils/package-json-types.d.ts +44 -0
  121. package/dist/src/utils/package-json-types.js +6 -0
  122. package/dist/src/utils/package-json-types.js.map +1 -0
  123. package/dist/src/utils/package-json.d.ts +19 -0
  124. package/dist/src/utils/package-json.js +22 -0
  125. package/dist/src/utils/package-json.js.map +1 -0
  126. package/dist/src/utils/session.d.ts +2 -0
  127. package/dist/src/utils/session.js +87 -0
  128. package/dist/src/utils/session.js.map +1 -0
  129. package/dist/src/utils/types.d.ts +61 -0
  130. package/dist/src/utils/types.js +2 -0
  131. package/dist/src/utils/types.js.map +1 -0
  132. package/dist/src/utils/ui.d.ts +120 -0
  133. package/dist/src/utils/ui.js +164 -0
  134. package/dist/src/utils/ui.js.map +1 -0
  135. package/package.json +140 -0
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Clarifying questions prompt component.
3
+ * Displays questions from the AskUserQuestion tool and collects answers.
4
+ * Styled with a stepper progress bar showing question headers.
5
+ * Features inline text input for the "Type something" option.
6
+ */
7
+ import React from 'react';
8
+ import type { ClarifyingQuestionsProps } from '../types.js';
9
+ interface ClarifyingQuestionsPromptComponentProps {
10
+ props: ClarifyingQuestionsProps;
11
+ }
12
+ /**
13
+ * Clarifying questions prompt for the AskUserQuestion tool.
14
+ * Supports single-select, multi-select, and inline free-text input.
15
+ */
16
+ export declare function ClarifyingQuestionsPrompt({ props, }: ClarifyingQuestionsPromptComponentProps): React.ReactElement;
17
+ export default ClarifyingQuestionsPrompt;
@@ -0,0 +1,359 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * Clarifying questions prompt component.
4
+ * Displays questions from the AskUserQuestion tool and collects answers.
5
+ * Styled with a stepper progress bar showing question headers.
6
+ * Features inline text input for the "Type something" option.
7
+ */
8
+ import { useState, useMemo, useCallback, useEffect } from 'react';
9
+ import { Box, Text, useInput } from 'ink';
10
+ import TextInput from 'ink-text-input';
11
+ import { useWizard } from '../contexts/WizardContext.js';
12
+ import { PromptContainer } from './PromptContainer.js';
13
+ /**
14
+ * Stepper progress bar component showing question headers with status indicators.
15
+ */
16
+ function StepperProgress({ questions, currentIndex, answers, }) {
17
+ // Add "Submit" as the final step
18
+ const steps = [...questions.map((q) => q.header), 'Submit'];
19
+ return (_jsx(Box, { marginBottom: 1, children: steps.map((header, idx) => {
20
+ const isCompleted = idx < currentIndex ||
21
+ (idx < questions.length && answers[questions[idx].question]);
22
+ const isCurrent = idx === currentIndex;
23
+ // Determine the marker
24
+ let marker;
25
+ if (isCompleted && !isCurrent) {
26
+ marker = '✓';
27
+ }
28
+ else if (isCurrent) {
29
+ marker = '●';
30
+ }
31
+ else {
32
+ marker = '○';
33
+ }
34
+ // Determine colors
35
+ const markerColor = isCompleted ? 'green' : isCurrent ? 'cyan' : 'gray';
36
+ const textColor = isCurrent ? 'cyan' : isCompleted ? undefined : 'gray';
37
+ const textDim = !isCurrent && !isCompleted;
38
+ return (_jsxs(Box, { children: [idx > 0 && _jsx(Text, { color: "gray", children: " \u2501\u2501\u2501 " }), _jsxs(Box, { children: [_jsx(Text, { color: markerColor, children: marker }), _jsxs(Text, { color: textColor, dimColor: textDim, children: [' ', header] })] })] }, idx));
39
+ }) }));
40
+ }
41
+ /**
42
+ * Clarifying questions prompt for the AskUserQuestion tool.
43
+ * Supports single-select, multi-select, and inline free-text input.
44
+ */
45
+ export function ClarifyingQuestionsPrompt({ props, }) {
46
+ const { questions } = props;
47
+ const { state, actions } = useWizard();
48
+ const { resolvePending, addItem } = actions;
49
+ const { agentState } = state;
50
+ // Track current question index
51
+ const [currentQuestionIndex, setCurrentQuestionIndex] = useState(0);
52
+ // Track answers for each question
53
+ const [answers, setAnswers] = useState({});
54
+ // Track multi-select selections for current question
55
+ const [multiSelections, setMultiSelections] = useState([]);
56
+ // Track highlighted item index
57
+ const [highlightedIndex, setHighlightedIndex] = useState(0);
58
+ // Track custom text value for "Type something" option
59
+ const [customText, setCustomText] = useState('');
60
+ // Track if we're in typing mode (when Type something is selected and user is typing)
61
+ const [isTypingMode, setIsTypingMode] = useState(false);
62
+ // Track if we're in review mode (after all questions answered)
63
+ const [isReviewMode, setIsReviewMode] = useState(false);
64
+ // Track highlighted option in review mode (0 = Submit, 1 = Cancel)
65
+ const [reviewHighlightedIndex, setReviewHighlightedIndex] = useState(0);
66
+ const currentQuestion = questions[currentQuestionIndex];
67
+ const isLastQuestion = currentQuestionIndex === questions.length - 1;
68
+ const isMultiSelect = currentQuestion?.multiSelect ?? false;
69
+ // Get regular option values (needed before handleCustomTextSubmit)
70
+ const regularOptionValues = useMemo(() => {
71
+ if (!currentQuestion)
72
+ return new Set();
73
+ return new Set(currentQuestion.options.map((opt) => opt.label));
74
+ }, [currentQuestion]);
75
+ // Get custom entries (values in multiSelections that aren't regular options)
76
+ const customEntries = useMemo(() => {
77
+ return multiSelections.filter((v) => !regularOptionValues.has(v));
78
+ }, [multiSelections, regularOptionValues]);
79
+ // Build list items for current question
80
+ const items = useMemo(() => {
81
+ if (!currentQuestion)
82
+ return [];
83
+ const questionItems = currentQuestion.options.map((opt) => ({
84
+ label: opt.label,
85
+ value: opt.label,
86
+ description: opt.description,
87
+ }));
88
+ // Add "Type something" option for free-text input
89
+ questionItems.push({
90
+ label: 'Type something',
91
+ value: '__OTHER__',
92
+ });
93
+ // Add "Submit" option for multi-select (always visible)
94
+ if (isMultiSelect) {
95
+ questionItems.push({
96
+ label: 'Submit',
97
+ value: '__SUBMIT__',
98
+ });
99
+ }
100
+ return questionItems;
101
+ }, [currentQuestion, isMultiSelect, multiSelections]);
102
+ // Auto-enter typing mode when "Type something" is highlighted
103
+ useEffect(() => {
104
+ // Only auto-enter typing mode if:
105
+ // 1. Not already in typing mode
106
+ // 2. Not in review mode
107
+ // 3. "Type something" is highlighted
108
+ // 4. No custom entries exist yet (for multi-select)
109
+ if (!isTypingMode &&
110
+ !isReviewMode &&
111
+ items[highlightedIndex]?.value === '__OTHER__' &&
112
+ customEntries.length === 0) {
113
+ setIsTypingMode(true);
114
+ }
115
+ }, [
116
+ highlightedIndex,
117
+ items,
118
+ isTypingMode,
119
+ isReviewMode,
120
+ customEntries.length,
121
+ ]);
122
+ // Move to next question or go to review
123
+ const proceedToNext = useCallback((answer) => {
124
+ const newAnswers = {
125
+ ...answers,
126
+ [currentQuestion.question]: answer,
127
+ };
128
+ setAnswers(newAnswers);
129
+ if (isLastQuestion) {
130
+ // All questions answered, go to review mode
131
+ setIsReviewMode(true);
132
+ setReviewHighlightedIndex(0);
133
+ }
134
+ else {
135
+ // Move to next question
136
+ setCurrentQuestionIndex((idx) => idx + 1);
137
+ setMultiSelections([]);
138
+ setHighlightedIndex(0);
139
+ setCustomText('');
140
+ setIsTypingMode(false);
141
+ }
142
+ }, [answers, currentQuestion, isLastQuestion]);
143
+ // Submit final answers
144
+ const submitAnswers = useCallback(() => {
145
+ // Add history item showing questions and answers
146
+ addItem({
147
+ type: 'clarifying-questions-result',
148
+ text: "User answered Raindrop wizard's questions:",
149
+ questionsAndAnswers: questions.map((q) => ({
150
+ question: q.question,
151
+ answer: answers[q.question] || '(no answer)',
152
+ })),
153
+ });
154
+ const result = {
155
+ questions,
156
+ answers,
157
+ };
158
+ resolvePending(result);
159
+ }, [questions, answers, resolvePending, addItem]);
160
+ // Cancel and return empty answers, interrupting the agent
161
+ const cancelAnswers = useCallback(() => {
162
+ // Add history item indicating user declined
163
+ addItem({
164
+ type: 'declined-questions',
165
+ text: 'User declined to answer questions',
166
+ });
167
+ // Interrupt the agent
168
+ if (agentState.queryHandle?.interrupt) {
169
+ void agentState.queryHandle.interrupt();
170
+ }
171
+ const result = {
172
+ questions,
173
+ answers: {},
174
+ };
175
+ resolvePending(result);
176
+ }, [questions, resolvePending, addItem, agentState.queryHandle]);
177
+ // Handle custom text submission from TextInput
178
+ const handleCustomTextSubmit = useCallback((value) => {
179
+ if (!value.trim())
180
+ return;
181
+ const trimmedValue = value.trim();
182
+ if (isMultiSelect) {
183
+ // Multi-select: Replace any existing custom entries with the new value
184
+ // This ensures only the latest typed value is kept, not multiple versions
185
+ if (multiSelections.includes(trimmedValue)) {
186
+ // Same value already exists - toggle it off
187
+ setMultiSelections((prev) => prev.filter((v) => v !== trimmedValue));
188
+ }
189
+ else {
190
+ // New value - remove old custom entries and add the new one
191
+ setMultiSelections((prev) => {
192
+ const withoutOldCustom = prev.filter((v) => regularOptionValues.has(v));
193
+ return [...withoutOldCustom, trimmedValue];
194
+ });
195
+ }
196
+ // Don't clear text - keep it for further editing or submit
197
+ }
198
+ else {
199
+ // Single-select: Submit immediately with the typed value
200
+ proceedToNext(trimmedValue);
201
+ }
202
+ }, [isMultiSelect, multiSelections, regularOptionValues, proceedToNext]);
203
+ // Handle keyboard navigation and selection
204
+ useInput((input, key) => {
205
+ // Ctrl+C always cancels/declines questions (no matter what mode we're in)
206
+ if (key.ctrl && input === 'c') {
207
+ cancelAnswers();
208
+ return;
209
+ }
210
+ // Review mode has its own navigation
211
+ if (isReviewMode) {
212
+ if (key.escape) {
213
+ // Go back to last question
214
+ setIsReviewMode(false);
215
+ setHighlightedIndex(0);
216
+ return;
217
+ }
218
+ if (key.upArrow) {
219
+ setReviewHighlightedIndex((idx) => Math.max(0, idx - 1));
220
+ return;
221
+ }
222
+ if (key.downArrow) {
223
+ setReviewHighlightedIndex((idx) => Math.min(1, idx + 1));
224
+ return;
225
+ }
226
+ if (key.return) {
227
+ if (reviewHighlightedIndex === 0) {
228
+ submitAnswers();
229
+ }
230
+ else {
231
+ cancelAnswers();
232
+ }
233
+ return;
234
+ }
235
+ return;
236
+ }
237
+ // Escape handling - always active
238
+ if (key.escape) {
239
+ if (isTypingMode) {
240
+ // Exit typing mode
241
+ setIsTypingMode(false);
242
+ }
243
+ else if (currentQuestionIndex > 0) {
244
+ // Go back to previous question
245
+ setCurrentQuestionIndex((idx) => idx - 1);
246
+ setMultiSelections([]);
247
+ setHighlightedIndex(0);
248
+ setCustomText('');
249
+ }
250
+ else {
251
+ // On first question, cancel entirely
252
+ cancelAnswers();
253
+ }
254
+ return;
255
+ }
256
+ // Arrow keys - exit typing mode and navigate
257
+ if (key.upArrow) {
258
+ if (isTypingMode) {
259
+ setIsTypingMode(false);
260
+ }
261
+ setHighlightedIndex((idx) => Math.max(0, idx - 1));
262
+ return;
263
+ }
264
+ if (key.downArrow) {
265
+ if (isTypingMode) {
266
+ setIsTypingMode(false);
267
+ }
268
+ setHighlightedIndex((idx) => Math.min(items.length - 1, idx + 1));
269
+ return;
270
+ }
271
+ // Skip other keys when typing - TextInput handles them
272
+ if (isTypingMode) {
273
+ return;
274
+ }
275
+ // Enter to select
276
+ if (key.return) {
277
+ const selectedItem = items[highlightedIndex];
278
+ if (!selectedItem)
279
+ return;
280
+ if (selectedItem.value === '__OTHER__') {
281
+ if (isMultiSelect && customEntries.length > 0) {
282
+ // Already has custom entries - toggle (clear) them to uncheck
283
+ setMultiSelections((prev) => prev.filter((v) => !customEntries.includes(v)));
284
+ setCustomText('');
285
+ return;
286
+ }
287
+ // No custom entries yet - enter typing mode
288
+ setIsTypingMode(true);
289
+ return;
290
+ }
291
+ if (selectedItem.value === '__SUBMIT__') {
292
+ // Submit with all checked selections only
293
+ if (multiSelections.length > 0) {
294
+ proceedToNext(multiSelections.join(', '));
295
+ }
296
+ return;
297
+ }
298
+ if (isMultiSelect) {
299
+ // Toggle selection for multi-select
300
+ setMultiSelections((prev) => {
301
+ if (prev.includes(selectedItem.value)) {
302
+ return prev.filter((v) => v !== selectedItem.value);
303
+ }
304
+ return [...prev, selectedItem.value];
305
+ });
306
+ }
307
+ else {
308
+ // Single select - proceed immediately
309
+ proceedToNext(selectedItem.value);
310
+ }
311
+ }
312
+ });
313
+ // Render a single list item
314
+ const renderItem = (item, index) => {
315
+ const isHighlighted = index === highlightedIndex;
316
+ const isSelected = multiSelections.includes(item.value);
317
+ const isTypeOption = item.value === '__OTHER__';
318
+ const isSubmitOption = item.value === '__SUBMIT__';
319
+ const displayNumber = index + 1;
320
+ // Indicator (removed for cleaner UI)
321
+ const indicator = ' ';
322
+ // For "Type something" option with inline text input
323
+ if (isTypeOption) {
324
+ // Show checkbox only for multi-select
325
+ const hasCustomEntries = customEntries.length > 0;
326
+ const checkbox = isMultiSelect
327
+ ? hasCustomEntries
328
+ ? '[✓] '
329
+ : '[ ] '
330
+ : '';
331
+ return (_jsxs(Box, { children: [_jsxs(Text, { color: isHighlighted ? 'cyan' : undefined, children: [indicator, displayNumber, ". ", checkbox] }), isTypingMode || customText ? (_jsx(TextInput, { value: customText, onChange: setCustomText, onSubmit: handleCustomTextSubmit, focus: isTypingMode, placeholder: "" })) : (_jsx(Text, { color: isHighlighted ? 'cyan' : undefined, children: item.label }))] }, item.value));
332
+ }
333
+ // Submit option
334
+ if (isSubmitOption) {
335
+ const canSubmit = multiSelections.length > 0;
336
+ const textColor = isHighlighted
337
+ ? 'cyan'
338
+ : !canSubmit
339
+ ? 'gray'
340
+ : 'green';
341
+ // Calculate spacing to align with checkbox brackets (same as "N. " where N is the number)
342
+ const numberSpacing = `${displayNumber}. `;
343
+ return (_jsx(Box, { children: _jsxs(Text, { color: textColor, bold: true, children: [indicator, ' '.repeat(numberSpacing.length), "Submit"] }) }, item.value));
344
+ }
345
+ // Regular option - show checkbox for multi-select mode
346
+ const checkbox = isMultiSelect ? (isSelected ? '[✓] ' : '[ ] ') : '';
347
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { color: isHighlighted ? 'cyan' : undefined, children: [indicator, displayNumber, ". ", checkbox, item.label] }), item.description && (_jsx(Box, { marginLeft: 4, children: _jsx(Text, { dimColor: true, children: item.description }) }))] }, item.value));
348
+ };
349
+ if (!currentQuestion && !isReviewMode) {
350
+ return (_jsx(Box, { children: _jsx(Text, { color: "red", children: "No questions to display" }) }));
351
+ }
352
+ // Review mode - show all answers and confirm
353
+ if (isReviewMode) {
354
+ return (_jsxs(PromptContainer, { children: [_jsx(StepperProgress, { questions: questions, currentIndex: questions.length, answers: answers }), _jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, children: "Review your answers" }) }), _jsx(Box, { flexDirection: "column", marginBottom: 1, children: questions.map((q) => (_jsxs(Box, { flexDirection: "column", marginLeft: 1, children: [_jsxs(Box, { children: [_jsx(Text, { color: "blue", children: "\u25CF " }), _jsx(Text, { children: q.question })] }), _jsx(Box, { marginLeft: 2, children: _jsx(Text, { color: "green", children: answers[q.question] || '(no answer)' }) })] }, q.question))) }), _jsx(Box, { marginBottom: 1, children: _jsx(Text, { children: "Ready to submit your answers?" }) }), _jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { children: _jsxs(Text, { color: reviewHighlightedIndex === 0 ? 'cyan' : 'green', bold: true, children: [reviewHighlightedIndex === 0 ? '› ' : ' ', "1. Submit answers"] }) }), _jsx(Box, { children: _jsxs(Text, { color: reviewHighlightedIndex === 1 ? 'cyan' : undefined, children: [reviewHighlightedIndex === 1 ? '› ' : ' ', "2. Cancel"] }) })] })] }));
355
+ }
356
+ return (_jsxs(PromptContainer, { children: [_jsx(StepperProgress, { questions: questions, currentIndex: currentQuestionIndex, answers: answers }), _jsx(Box, { marginBottom: 1, children: _jsx(Text, { children: currentQuestion.question }) }), _jsx(Box, { flexDirection: "column", children: items.map((item, index) => renderItem(item, index)) })] }));
357
+ }
358
+ export default ClarifyingQuestionsPrompt;
359
+ //# sourceMappingURL=ClarifyingQuestionsPrompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ClarifyingQuestionsPrompt.js","sourceRoot":"","sources":["../../../../src/ui/components/ClarifyingQuestionsPrompt.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n * Clarifying questions prompt component.\n * Displays questions from the AskUserQuestion tool and collects answers.\n * Styled with a stepper progress bar showing question headers.\n * Features inline text input for the \"Type something\" option.\n */\n\nimport React, { useState, useMemo, useCallback, useEffect } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport TextInput from 'ink-text-input';\nimport { useWizard } from '../contexts/WizardContext.js';\nimport { PromptContainer } from './PromptContainer.js';\nimport type {\n ClarifyingQuestionsProps,\n ClarifyingQuestionsResult,\n ClarifyingQuestion,\n} from '../types.js';\n\ninterface ClarifyingQuestionsPromptComponentProps {\n props: ClarifyingQuestionsProps;\n}\n\ninterface ListItem {\n label: string;\n value: string;\n description?: string;\n}\n\n/**\n * Stepper progress bar component showing question headers with status indicators.\n */\nfunction StepperProgress({\n questions,\n currentIndex,\n answers,\n}: {\n questions: ClarifyingQuestion[];\n currentIndex: number;\n answers: Record<string, string>;\n}): React.ReactElement {\n // Add \"Submit\" as the final step\n const steps = [...questions.map((q) => q.header), 'Submit'];\n\n return (\n <Box marginBottom={1}>\n {steps.map((header, idx) => {\n const isCompleted =\n idx < currentIndex ||\n (idx < questions.length && answers[questions[idx].question]);\n const isCurrent = idx === currentIndex;\n\n // Determine the marker\n let marker: string;\n if (isCompleted && !isCurrent) {\n marker = '✓';\n } else if (isCurrent) {\n marker = '●';\n } else {\n marker = '○';\n }\n\n // Determine colors\n const markerColor = isCompleted ? 'green' : isCurrent ? 'cyan' : 'gray';\n const textColor = isCurrent ? 'cyan' : isCompleted ? undefined : 'gray';\n const textDim = !isCurrent && !isCompleted;\n\n return (\n <Box key={idx}>\n {/* Connector line before (except first) */}\n {idx > 0 && <Text color=\"gray\"> ━━━ </Text>}\n {/* Marker and label */}\n <Box>\n <Text color={markerColor}>{marker}</Text>\n <Text color={textColor} dimColor={textDim}>\n {' '}\n {header}\n </Text>\n </Box>\n </Box>\n );\n })}\n </Box>\n );\n}\n\n/**\n * Clarifying questions prompt for the AskUserQuestion tool.\n * Supports single-select, multi-select, and inline free-text input.\n */\nexport function ClarifyingQuestionsPrompt({\n props,\n}: ClarifyingQuestionsPromptComponentProps): React.ReactElement {\n const { questions } = props;\n const { state, actions } = useWizard();\n const { resolvePending, addItem } = actions;\n const { agentState } = state;\n\n // Track current question index\n const [currentQuestionIndex, setCurrentQuestionIndex] = useState(0);\n // Track answers for each question\n const [answers, setAnswers] = useState<Record<string, string>>({});\n // Track multi-select selections for current question\n const [multiSelections, setMultiSelections] = useState<string[]>([]);\n // Track highlighted item index\n const [highlightedIndex, setHighlightedIndex] = useState(0);\n // Track custom text value for \"Type something\" option\n const [customText, setCustomText] = useState('');\n // Track if we're in typing mode (when Type something is selected and user is typing)\n const [isTypingMode, setIsTypingMode] = useState(false);\n // Track if we're in review mode (after all questions answered)\n const [isReviewMode, setIsReviewMode] = useState(false);\n // Track highlighted option in review mode (0 = Submit, 1 = Cancel)\n const [reviewHighlightedIndex, setReviewHighlightedIndex] = useState(0);\n\n const currentQuestion = questions[currentQuestionIndex];\n const isLastQuestion = currentQuestionIndex === questions.length - 1;\n const isMultiSelect = currentQuestion?.multiSelect ?? false;\n\n // Get regular option values (needed before handleCustomTextSubmit)\n const regularOptionValues = useMemo(() => {\n if (!currentQuestion) return new Set<string>();\n return new Set(currentQuestion.options.map((opt) => opt.label));\n }, [currentQuestion]);\n\n // Get custom entries (values in multiSelections that aren't regular options)\n const customEntries = useMemo(() => {\n return multiSelections.filter((v) => !regularOptionValues.has(v));\n }, [multiSelections, regularOptionValues]);\n\n // Build list items for current question\n const items: ListItem[] = useMemo(() => {\n if (!currentQuestion) return [];\n\n const questionItems: ListItem[] = currentQuestion.options.map((opt) => ({\n label: opt.label,\n value: opt.label,\n description: opt.description,\n }));\n\n // Add \"Type something\" option for free-text input\n questionItems.push({\n label: 'Type something',\n value: '__OTHER__',\n });\n\n // Add \"Submit\" option for multi-select (always visible)\n if (isMultiSelect) {\n questionItems.push({\n label: 'Submit',\n value: '__SUBMIT__',\n });\n }\n\n return questionItems;\n }, [currentQuestion, isMultiSelect, multiSelections]);\n\n // Auto-enter typing mode when \"Type something\" is highlighted\n useEffect(() => {\n // Only auto-enter typing mode if:\n // 1. Not already in typing mode\n // 2. Not in review mode\n // 3. \"Type something\" is highlighted\n // 4. No custom entries exist yet (for multi-select)\n if (\n !isTypingMode &&\n !isReviewMode &&\n items[highlightedIndex]?.value === '__OTHER__' &&\n customEntries.length === 0\n ) {\n setIsTypingMode(true);\n }\n }, [\n highlightedIndex,\n items,\n isTypingMode,\n isReviewMode,\n customEntries.length,\n ]);\n\n // Move to next question or go to review\n const proceedToNext = useCallback(\n (answer: string) => {\n const newAnswers = {\n ...answers,\n [currentQuestion.question]: answer,\n };\n setAnswers(newAnswers);\n\n if (isLastQuestion) {\n // All questions answered, go to review mode\n setIsReviewMode(true);\n setReviewHighlightedIndex(0);\n } else {\n // Move to next question\n setCurrentQuestionIndex((idx) => idx + 1);\n setMultiSelections([]);\n setHighlightedIndex(0);\n setCustomText('');\n setIsTypingMode(false);\n }\n },\n [answers, currentQuestion, isLastQuestion],\n );\n\n // Submit final answers\n const submitAnswers = useCallback(() => {\n // Add history item showing questions and answers\n addItem({\n type: 'clarifying-questions-result',\n text: \"User answered Raindrop wizard's questions:\",\n questionsAndAnswers: questions.map((q) => ({\n question: q.question,\n answer: answers[q.question] || '(no answer)',\n })),\n });\n\n const result: ClarifyingQuestionsResult = {\n questions,\n answers,\n };\n resolvePending(result);\n }, [questions, answers, resolvePending, addItem]);\n\n // Cancel and return empty answers, interrupting the agent\n const cancelAnswers = useCallback(() => {\n // Add history item indicating user declined\n addItem({\n type: 'declined-questions',\n text: 'User declined to answer questions',\n });\n\n // Interrupt the agent\n if (agentState.queryHandle?.interrupt) {\n void agentState.queryHandle.interrupt();\n }\n\n const result: ClarifyingQuestionsResult = {\n questions,\n answers: {},\n };\n resolvePending(result);\n }, [questions, resolvePending, addItem, agentState.queryHandle]);\n\n // Handle custom text submission from TextInput\n const handleCustomTextSubmit = useCallback(\n (value: string) => {\n if (!value.trim()) return;\n\n const trimmedValue = value.trim();\n\n if (isMultiSelect) {\n // Multi-select: Replace any existing custom entries with the new value\n // This ensures only the latest typed value is kept, not multiple versions\n if (multiSelections.includes(trimmedValue)) {\n // Same value already exists - toggle it off\n setMultiSelections((prev) => prev.filter((v) => v !== trimmedValue));\n } else {\n // New value - remove old custom entries and add the new one\n setMultiSelections((prev) => {\n const withoutOldCustom = prev.filter((v) =>\n regularOptionValues.has(v),\n );\n return [...withoutOldCustom, trimmedValue];\n });\n }\n // Don't clear text - keep it for further editing or submit\n } else {\n // Single-select: Submit immediately with the typed value\n proceedToNext(trimmedValue);\n }\n },\n [isMultiSelect, multiSelections, regularOptionValues, proceedToNext],\n );\n\n // Handle keyboard navigation and selection\n useInput((input, key) => {\n // Ctrl+C always cancels/declines questions (no matter what mode we're in)\n if (key.ctrl && input === 'c') {\n cancelAnswers();\n return;\n }\n\n // Review mode has its own navigation\n if (isReviewMode) {\n if (key.escape) {\n // Go back to last question\n setIsReviewMode(false);\n setHighlightedIndex(0);\n return;\n }\n if (key.upArrow) {\n setReviewHighlightedIndex((idx) => Math.max(0, idx - 1));\n return;\n }\n if (key.downArrow) {\n setReviewHighlightedIndex((idx) => Math.min(1, idx + 1));\n return;\n }\n if (key.return) {\n if (reviewHighlightedIndex === 0) {\n submitAnswers();\n } else {\n cancelAnswers();\n }\n return;\n }\n return;\n }\n\n // Escape handling - always active\n if (key.escape) {\n if (isTypingMode) {\n // Exit typing mode\n setIsTypingMode(false);\n } else if (currentQuestionIndex > 0) {\n // Go back to previous question\n setCurrentQuestionIndex((idx) => idx - 1);\n setMultiSelections([]);\n setHighlightedIndex(0);\n setCustomText('');\n } else {\n // On first question, cancel entirely\n cancelAnswers();\n }\n return;\n }\n\n // Arrow keys - exit typing mode and navigate\n if (key.upArrow) {\n if (isTypingMode) {\n setIsTypingMode(false);\n }\n setHighlightedIndex((idx) => Math.max(0, idx - 1));\n return;\n }\n if (key.downArrow) {\n if (isTypingMode) {\n setIsTypingMode(false);\n }\n setHighlightedIndex((idx) => Math.min(items.length - 1, idx + 1));\n return;\n }\n\n // Skip other keys when typing - TextInput handles them\n if (isTypingMode) {\n return;\n }\n\n // Enter to select\n if (key.return) {\n const selectedItem = items[highlightedIndex];\n if (!selectedItem) return;\n\n if (selectedItem.value === '__OTHER__') {\n if (isMultiSelect && customEntries.length > 0) {\n // Already has custom entries - toggle (clear) them to uncheck\n setMultiSelections((prev) =>\n prev.filter((v) => !customEntries.includes(v)),\n );\n setCustomText('');\n return;\n }\n // No custom entries yet - enter typing mode\n setIsTypingMode(true);\n return;\n }\n\n if (selectedItem.value === '__SUBMIT__') {\n // Submit with all checked selections only\n if (multiSelections.length > 0) {\n proceedToNext(multiSelections.join(', '));\n }\n return;\n }\n\n if (isMultiSelect) {\n // Toggle selection for multi-select\n setMultiSelections((prev) => {\n if (prev.includes(selectedItem.value)) {\n return prev.filter((v) => v !== selectedItem.value);\n }\n return [...prev, selectedItem.value];\n });\n } else {\n // Single select - proceed immediately\n proceedToNext(selectedItem.value);\n }\n }\n });\n\n // Render a single list item\n const renderItem = (item: ListItem, index: number) => {\n const isHighlighted = index === highlightedIndex;\n const isSelected = multiSelections.includes(item.value);\n const isTypeOption = item.value === '__OTHER__';\n const isSubmitOption = item.value === '__SUBMIT__';\n const displayNumber = index + 1;\n\n // Indicator (removed for cleaner UI)\n const indicator = ' ';\n\n // For \"Type something\" option with inline text input\n if (isTypeOption) {\n // Show checkbox only for multi-select\n const hasCustomEntries = customEntries.length > 0;\n const checkbox = isMultiSelect\n ? hasCustomEntries\n ? '[✓] '\n : '[ ] '\n : '';\n\n return (\n <Box key={item.value}>\n <Text color={isHighlighted ? 'cyan' : undefined}>\n {indicator}\n {displayNumber}. {checkbox}\n </Text>\n {isTypingMode || customText ? (\n <TextInput\n value={customText}\n onChange={setCustomText}\n onSubmit={handleCustomTextSubmit}\n focus={isTypingMode}\n placeholder=\"\"\n />\n ) : (\n <Text color={isHighlighted ? 'cyan' : undefined}>{item.label}</Text>\n )}\n </Box>\n );\n }\n\n // Submit option\n if (isSubmitOption) {\n const canSubmit = multiSelections.length > 0;\n const textColor = isHighlighted\n ? 'cyan'\n : !canSubmit\n ? 'gray'\n : 'green';\n // Calculate spacing to align with checkbox brackets (same as \"N. \" where N is the number)\n const numberSpacing = `${displayNumber}. `;\n return (\n <Box key={item.value}>\n <Text color={textColor} bold>\n {indicator}\n {' '.repeat(numberSpacing.length)}Submit\n </Text>\n </Box>\n );\n }\n\n // Regular option - show checkbox for multi-select mode\n const checkbox = isMultiSelect ? (isSelected ? '[✓] ' : '[ ] ') : '';\n\n return (\n <Box key={item.value} flexDirection=\"column\">\n <Text color={isHighlighted ? 'cyan' : undefined}>\n {indicator}\n {displayNumber}. {checkbox}\n {item.label}\n </Text>\n {item.description && (\n <Box marginLeft={4}>\n <Text dimColor>{item.description}</Text>\n </Box>\n )}\n </Box>\n );\n };\n\n if (!currentQuestion && !isReviewMode) {\n return (\n <Box>\n <Text color=\"red\">No questions to display</Text>\n </Box>\n );\n }\n\n // Review mode - show all answers and confirm\n if (isReviewMode) {\n return (\n <PromptContainer>\n {/* Stepper progress bar - show Submit as current */}\n <StepperProgress\n questions={questions}\n currentIndex={questions.length}\n answers={answers}\n />\n\n {/* Review header */}\n <Box marginBottom={1}>\n <Text bold>Review your answers</Text>\n </Box>\n\n {/* List all questions and answers */}\n <Box flexDirection=\"column\" marginBottom={1}>\n {questions.map((q) => (\n <Box key={q.question} flexDirection=\"column\" marginLeft={1}>\n <Box>\n <Text color=\"blue\">● </Text>\n <Text>{q.question}</Text>\n </Box>\n <Box marginLeft={2}>\n <Text color=\"green\">\n {answers[q.question] || '(no answer)'}\n </Text>\n </Box>\n </Box>\n ))}\n </Box>\n\n {/* Confirmation prompt */}\n <Box marginBottom={1}>\n <Text>Ready to submit your answers?</Text>\n </Box>\n\n {/* Submit/Cancel options */}\n <Box flexDirection=\"column\">\n <Box>\n <Text\n color={reviewHighlightedIndex === 0 ? 'cyan' : 'green'}\n bold\n >\n {reviewHighlightedIndex === 0 ? '› ' : ' '}1. Submit answers\n </Text>\n </Box>\n <Box>\n <Text color={reviewHighlightedIndex === 1 ? 'cyan' : undefined}>\n {reviewHighlightedIndex === 1 ? '› ' : ' '}2. Cancel\n </Text>\n </Box>\n </Box>\n </PromptContainer>\n );\n }\n\n return (\n <PromptContainer>\n {/* Stepper progress bar */}\n <StepperProgress\n questions={questions}\n currentIndex={currentQuestionIndex}\n answers={answers}\n />\n\n {/* Question text */}\n <Box marginBottom={1}>\n <Text>{currentQuestion.question}</Text>\n </Box>\n\n {/* Options list */}\n <Box flexDirection=\"column\">\n {items.map((item, index) => renderItem(item, index))}\n </Box>\n </PromptContainer>\n );\n}\n\nexport default ClarifyingQuestionsPrompt;\n"]}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Continue button prompt component.
3
+ * Shows a message and waits for user to press Enter to continue.
4
+ */
5
+ import React from 'react';
6
+ interface ContinuePromptProps {
7
+ message: string;
8
+ buttonLabel?: string;
9
+ }
10
+ /**
11
+ * Continue button prompt that waits for Enter key
12
+ */
13
+ export declare function ContinuePrompt({ message, buttonLabel, }: ContinuePromptProps): React.ReactElement;
14
+ export default ContinuePrompt;
@@ -0,0 +1,23 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ import { Box, Text, useInput } from 'ink';
3
+ import { useWizardActions } from '../contexts/WizardContext.js';
4
+ import { CANCEL_SYMBOL } from '../cancellation.js';
5
+ import { PromptContainer } from './PromptContainer.js';
6
+ /**
7
+ * Continue button prompt that waits for Enter key
8
+ */
9
+ export function ContinuePrompt({ message, buttonLabel = 'Continue', }) {
10
+ const { resolvePending, addItem } = useWizardActions();
11
+ useInput((input, key) => {
12
+ if (key.ctrl && input === 'c') {
13
+ resolvePending(CANCEL_SYMBOL);
14
+ return;
15
+ }
16
+ if (key.return) {
17
+ resolvePending(true);
18
+ }
19
+ });
20
+ return (_jsx(PromptContainer, { children: _jsxs(Box, { children: [_jsxs(Text, { color: "cyan", bold: true, children: ["\u203A", ' '] }), _jsx(Text, { color: "cyan", children: message })] }) }));
21
+ }
22
+ export default ContinuePrompt;
23
+ //# sourceMappingURL=ContinuePrompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ContinuePrompt.js","sourceRoot":"","sources":["../../../../src/ui/components/ContinuePrompt.tsx"],"names":[],"mappings":";AAMA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAOvD;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,EAC7B,OAAO,EACP,WAAW,GAAG,UAAU,GACJ;IACpB,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,GAAG,gBAAgB,EAAE,CAAC;IAEvD,QAAQ,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QACtB,IAAI,GAAG,CAAC,IAAI,IAAI,KAAK,KAAK,GAAG,EAAE,CAAC;YAC9B,cAAc,CAAC,aAAa,CAAC,CAAC;YAC9B,OAAO;QACT,CAAC;QAED,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;YACf,cAAc,CAAC,IAAI,CAAC,CAAC;QACvB,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,CACL,KAAC,eAAe,cACd,MAAC,GAAG,eACF,MAAC,IAAI,IAAC,KAAK,EAAC,MAAM,EAAC,IAAI,6BACnB,GAAG,IACA,EACP,KAAC,IAAI,IAAC,KAAK,EAAC,MAAM,YAAE,OAAO,GAAQ,IAC/B,GACU,CACnB,CAAC;AACJ,CAAC;AAED,eAAe,cAAc,CAAC","sourcesContent":["/**\n * Continue button prompt component.\n * Shows a message and waits for user to press Enter to continue.\n */\n\nimport React from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport { useWizardActions } from '../contexts/WizardContext.js';\nimport { CANCEL_SYMBOL } from '../cancellation.js';\nimport { PromptContainer } from './PromptContainer.js';\n\ninterface ContinuePromptProps {\n message: string;\n buttonLabel?: string;\n}\n\n/**\n * Continue button prompt that waits for Enter key\n */\nexport function ContinuePrompt({\n message,\n buttonLabel = 'Continue',\n}: ContinuePromptProps): React.ReactElement {\n const { resolvePending, addItem } = useWizardActions();\n\n useInput((input, key) => {\n if (key.ctrl && input === 'c') {\n resolvePending(CANCEL_SYMBOL);\n return;\n }\n\n if (key.return) {\n resolvePending(true);\n }\n });\n\n return (\n <PromptContainer>\n <Box>\n <Text color=\"cyan\" bold>\n ›{' '}\n </Text>\n <Text color=\"cyan\">{message}</Text>\n </Box>\n </PromptContainer>\n );\n}\n\nexport default ContinuePrompt;\n"]}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Diff display component for showing file changes.
3
+ * Renders unified diff format with syntax highlighting.
4
+ */
5
+ import React from 'react';
6
+ interface DiffDisplayProps {
7
+ /** The diff content in unified diff format */
8
+ diffContent: string;
9
+ /** The filename being modified */
10
+ fileName?: string;
11
+ /** Maximum height in lines (for scrollable content) */
12
+ maxHeight?: number;
13
+ }
14
+ /**
15
+ * Display a unified diff with colored lines
16
+ */
17
+ export declare function DiffDisplay({ diffContent, fileName, maxHeight, }: DiffDisplayProps): React.ReactElement;
18
+ export default DiffDisplay;
@@ -0,0 +1,110 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * Diff display component for showing file changes.
4
+ * Renders unified diff format with syntax highlighting.
5
+ */
6
+ import { useMemo } from 'react';
7
+ import { Box, Text, useStdout } from 'ink';
8
+ /**
9
+ * Parse unified diff format into structured lines
10
+ */
11
+ function parseDiff(diffContent) {
12
+ const lines = diffContent.split('\n');
13
+ const result = [];
14
+ let newLineNumber = 0;
15
+ const hunkHeaderRegex = /^@@ -\d+,?\d* \+(\d+),?\d* @@/;
16
+ for (const line of lines) {
17
+ // Skip git header lines
18
+ if (line.startsWith('diff --git') || line.startsWith('index ')) {
19
+ continue;
20
+ }
21
+ // File header lines
22
+ if (line.startsWith('--- ') || line.startsWith('+++ ')) {
23
+ // result.push({ type: 'header', content: line }); // Skip file header lines
24
+ continue;
25
+ }
26
+ // Hunk header
27
+ const hunkMatch = line.match(hunkHeaderRegex);
28
+ if (hunkMatch) {
29
+ newLineNumber = parseInt(hunkMatch[1], 10) - 1;
30
+ result.push({ type: 'hunk', content: line });
31
+ continue;
32
+ }
33
+ // Added line
34
+ if (line.startsWith('+')) {
35
+ newLineNumber++;
36
+ result.push({
37
+ type: 'add',
38
+ lineNumber: newLineNumber,
39
+ content: line.substring(1),
40
+ });
41
+ continue;
42
+ }
43
+ // Deleted line
44
+ if (line.startsWith('-')) {
45
+ result.push({
46
+ type: 'del',
47
+ content: line.substring(1),
48
+ });
49
+ continue;
50
+ }
51
+ // Context line
52
+ if (line.startsWith(' ')) {
53
+ newLineNumber++;
54
+ result.push({
55
+ type: 'context',
56
+ lineNumber: newLineNumber,
57
+ content: line.substring(1),
58
+ });
59
+ continue;
60
+ }
61
+ }
62
+ return result;
63
+ }
64
+ /**
65
+ * Display a unified diff with colored lines
66
+ */
67
+ export function DiffDisplay({ diffContent, fileName, maxHeight, }) {
68
+ const { stdout } = useStdout();
69
+ const terminalWidth = stdout?.columns || 80;
70
+ const parsedLines = useMemo(() => {
71
+ if (!diffContent || typeof diffContent !== 'string') {
72
+ return [];
73
+ }
74
+ return parseDiff(diffContent);
75
+ }, [diffContent]);
76
+ // Calculate gutter width based on max line number
77
+ const maxLineNum = useMemo(() => {
78
+ return Math.max(0, ...parsedLines
79
+ .filter((l) => l.lineNumber !== undefined)
80
+ .map((l) => l.lineNumber));
81
+ }, [parsedLines]);
82
+ const gutterWidth = Math.max(4, maxLineNum.toString().length + 1);
83
+ if (parsedLines.length === 0) {
84
+ return (_jsx(Box, { children: _jsx(Text, { dimColor: true, children: "No changes to display" }) }));
85
+ }
86
+ // Limit lines if maxHeight is specified
87
+ const displayLines = maxHeight
88
+ ? parsedLines.slice(0, maxHeight)
89
+ : parsedLines;
90
+ const truncated = maxHeight && parsedLines.length > maxHeight;
91
+ return (_jsxs(Box, { flexDirection: "column", width: terminalWidth, children: [fileName && (_jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, color: "cyan", children: fileName }) })), displayLines.map((line, index) => {
92
+ const key = `diff-line-${index}`;
93
+ switch (line.type) {
94
+ case 'header':
95
+ return (_jsx(Box, { children: _jsx(Text, { dimColor: true, children: line.content }) }, key));
96
+ case 'hunk':
97
+ return (_jsx(Box, { marginTop: 1, children: _jsx(Text, { color: "cyan", children: line.content }) }, key));
98
+ case 'add':
99
+ return (_jsxs(Box, { children: [_jsx(Text, { dimColor: true, children: (line.lineNumber?.toString() || '').padStart(gutterWidth) }), _jsxs(Text, { color: "green", backgroundColor: "greenBright", children: [' ', "+", ' '] }), _jsx(Text, { color: "green", children: line.content })] }, key));
100
+ case 'del':
101
+ return (_jsxs(Box, { children: [_jsx(Text, { dimColor: true, children: ''.padStart(gutterWidth) }), _jsxs(Text, { color: "red", backgroundColor: "redBright", children: [' ', "-", ' '] }), _jsx(Text, { color: "red", children: line.content })] }, key));
102
+ case 'context':
103
+ return (_jsxs(Box, { children: [_jsx(Text, { dimColor: true, children: (line.lineNumber?.toString() || '').padStart(gutterWidth) }), _jsx(Text, { children: " " }), _jsx(Text, { children: line.content })] }, key));
104
+ default:
105
+ return null;
106
+ }
107
+ }), truncated && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: ["... ", parsedLines.length - (maxHeight || 0), " more lines"] }) }))] }));
108
+ }
109
+ export default DiffDisplay;
110
+ //# sourceMappingURL=DiffDisplay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DiffDisplay.js","sourceRoot":"","sources":["../../../../src/ui/components/DiffDisplay.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n * Diff display component for showing file changes.\n * Renders unified diff format with syntax highlighting.\n */\n\nimport React, { useMemo } from 'react';\nimport { Box, Text, useStdout } from 'ink';\n\ninterface DiffLine {\n type: 'add' | 'del' | 'context' | 'hunk' | 'header';\n lineNumber?: number;\n content: string;\n}\n\ninterface DiffDisplayProps {\n /** The diff content in unified diff format */\n diffContent: string;\n /** The filename being modified */\n fileName?: string;\n /** Maximum height in lines (for scrollable content) */\n maxHeight?: number;\n}\n\n/**\n * Parse unified diff format into structured lines\n */\nfunction parseDiff(diffContent: string): DiffLine[] {\n const lines = diffContent.split('\\n');\n const result: DiffLine[] = [];\n let newLineNumber = 0;\n const hunkHeaderRegex = /^@@ -\\d+,?\\d* \\+(\\d+),?\\d* @@/;\n\n for (const line of lines) {\n // Skip git header lines\n if (line.startsWith('diff --git') || line.startsWith('index ')) {\n continue;\n }\n\n // File header lines\n if (line.startsWith('--- ') || line.startsWith('+++ ')) {\n // result.push({ type: 'header', content: line }); // Skip file header lines\n continue;\n }\n\n // Hunk header\n const hunkMatch = line.match(hunkHeaderRegex);\n if (hunkMatch) {\n newLineNumber = parseInt(hunkMatch[1], 10) - 1;\n result.push({ type: 'hunk', content: line });\n continue;\n }\n\n // Added line\n if (line.startsWith('+')) {\n newLineNumber++;\n result.push({\n type: 'add',\n lineNumber: newLineNumber,\n content: line.substring(1),\n });\n continue;\n }\n\n // Deleted line\n if (line.startsWith('-')) {\n result.push({\n type: 'del',\n content: line.substring(1),\n });\n continue;\n }\n\n // Context line\n if (line.startsWith(' ')) {\n newLineNumber++;\n result.push({\n type: 'context',\n lineNumber: newLineNumber,\n content: line.substring(1),\n });\n continue;\n }\n }\n\n return result;\n}\n\n/**\n * Display a unified diff with colored lines\n */\nexport function DiffDisplay({\n diffContent,\n fileName,\n maxHeight,\n}: DiffDisplayProps): React.ReactElement {\n const { stdout } = useStdout();\n const terminalWidth = stdout?.columns || 80;\n\n const parsedLines = useMemo(() => {\n if (!diffContent || typeof diffContent !== 'string') {\n return [];\n }\n return parseDiff(diffContent);\n }, [diffContent]);\n\n // Calculate gutter width based on max line number\n const maxLineNum = useMemo(() => {\n return Math.max(\n 0,\n ...parsedLines\n .filter((l) => l.lineNumber !== undefined)\n .map((l) => l.lineNumber as number),\n );\n }, [parsedLines]);\n const gutterWidth = Math.max(4, maxLineNum.toString().length + 1);\n\n if (parsedLines.length === 0) {\n return (\n <Box>\n <Text dimColor>No changes to display</Text>\n </Box>\n );\n }\n\n // Limit lines if maxHeight is specified\n const displayLines = maxHeight\n ? parsedLines.slice(0, maxHeight)\n : parsedLines;\n const truncated = maxHeight && parsedLines.length > maxHeight;\n\n return (\n <Box flexDirection=\"column\" width={terminalWidth}>\n {/* File name header */}\n {fileName && (\n <Box marginBottom={1}>\n <Text bold color=\"cyan\">\n {fileName}\n </Text>\n </Box>\n )}\n\n {/* Diff lines */}\n {displayLines.map((line, index) => {\n const key = `diff-line-${index}`;\n\n switch (line.type) {\n case 'header':\n return (\n <Box key={key}>\n <Text dimColor>{line.content}</Text>\n </Box>\n );\n\n case 'hunk':\n return (\n <Box key={key} marginTop={1}>\n <Text color=\"cyan\">{line.content}</Text>\n </Box>\n );\n\n case 'add':\n return (\n <Box key={key}>\n <Text dimColor>\n {(line.lineNumber?.toString() || '').padStart(gutterWidth)}\n </Text>\n <Text color=\"green\" backgroundColor=\"greenBright\">\n {' '}\n +{' '}\n </Text>\n <Text color=\"green\">{line.content}</Text>\n </Box>\n );\n\n case 'del':\n return (\n <Box key={key}>\n <Text dimColor>{''.padStart(gutterWidth)}</Text>\n <Text color=\"red\" backgroundColor=\"redBright\">\n {' '}\n -{' '}\n </Text>\n <Text color=\"red\">{line.content}</Text>\n </Box>\n );\n\n case 'context':\n return (\n <Box key={key}>\n <Text dimColor>\n {(line.lineNumber?.toString() || '').padStart(gutterWidth)}\n </Text>\n <Text> </Text>\n <Text>{line.content}</Text>\n </Box>\n );\n\n default:\n return null;\n }\n })}\n\n {/* Truncation indicator */}\n {truncated && (\n <Box marginTop={1}>\n <Text dimColor>\n ... {parsedLines.length - (maxHeight || 0)} more lines\n </Text>\n </Box>\n )}\n </Box>\n );\n}\n\nexport default DiffDisplay;\n"]}