@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.
- package/LICENSE +47 -0
- package/dist/bin.d.ts +2 -0
- package/dist/bin.js +117 -0
- package/dist/bin.js.map +1 -0
- package/dist/src/docs/browser.md +105 -0
- package/dist/src/docs/python.md +618 -0
- package/dist/src/docs/typescript.md +584 -0
- package/dist/src/docs/vercel-ai-sdk.md +304 -0
- package/dist/src/lib/agent-interface.d.ts +46 -0
- package/dist/src/lib/agent-interface.js +292 -0
- package/dist/src/lib/agent-interface.js.map +1 -0
- package/dist/src/lib/agent-prompts.d.ts +10 -0
- package/dist/src/lib/agent-prompts.js +49 -0
- package/dist/src/lib/agent-prompts.js.map +1 -0
- package/dist/src/lib/config.d.ts +39 -0
- package/dist/src/lib/config.js +549 -0
- package/dist/src/lib/config.js.map +1 -0
- package/dist/src/lib/constants.d.ts +27 -0
- package/dist/src/lib/constants.js +165 -0
- package/dist/src/lib/constants.js.map +1 -0
- package/dist/src/lib/handlers.d.ts +68 -0
- package/dist/src/lib/handlers.js +420 -0
- package/dist/src/lib/handlers.js.map +1 -0
- package/dist/src/lib/integration-testing.d.ts +44 -0
- package/dist/src/lib/integration-testing.js +123 -0
- package/dist/src/lib/integration-testing.js.map +1 -0
- package/dist/src/lib/mcp.d.ts +14 -0
- package/dist/src/lib/mcp.js +134 -0
- package/dist/src/lib/mcp.js.map +1 -0
- package/dist/src/lib/sdk-messages.d.ts +17 -0
- package/dist/src/lib/sdk-messages.js +278 -0
- package/dist/src/lib/sdk-messages.js.map +1 -0
- package/dist/src/lib/wizard.d.ts +6 -0
- package/dist/src/lib/wizard.js +131 -0
- package/dist/src/lib/wizard.js.map +1 -0
- package/dist/src/run.d.ts +8 -0
- package/dist/src/run.js +53 -0
- package/dist/src/run.js.map +1 -0
- package/dist/src/ui/App.d.ts +15 -0
- package/dist/src/ui/App.js +27 -0
- package/dist/src/ui/App.js.map +1 -0
- package/dist/src/ui/cancellation.d.ts +14 -0
- package/dist/src/ui/cancellation.js +17 -0
- package/dist/src/ui/cancellation.js.map +1 -0
- package/dist/src/ui/components/ClarifyingQuestionsPrompt.d.ts +17 -0
- package/dist/src/ui/components/ClarifyingQuestionsPrompt.js +359 -0
- package/dist/src/ui/components/ClarifyingQuestionsPrompt.js.map +1 -0
- package/dist/src/ui/components/ContinuePrompt.d.ts +14 -0
- package/dist/src/ui/components/ContinuePrompt.js +23 -0
- package/dist/src/ui/components/ContinuePrompt.js.map +1 -0
- package/dist/src/ui/components/DiffDisplay.d.ts +18 -0
- package/dist/src/ui/components/DiffDisplay.js +110 -0
- package/dist/src/ui/components/DiffDisplay.js.map +1 -0
- package/dist/src/ui/components/FeedbackSelectPrompt.d.ts +20 -0
- package/dist/src/ui/components/FeedbackSelectPrompt.js +132 -0
- package/dist/src/ui/components/FeedbackSelectPrompt.js.map +1 -0
- package/dist/src/ui/components/HistoryItemDisplay.d.ts +14 -0
- package/dist/src/ui/components/HistoryItemDisplay.js +140 -0
- package/dist/src/ui/components/HistoryItemDisplay.js.map +1 -0
- package/dist/src/ui/components/Logo.d.ts +10 -0
- package/dist/src/ui/components/Logo.js +47 -0
- package/dist/src/ui/components/Logo.js.map +1 -0
- package/dist/src/ui/components/OrgInfoBox.d.ts +11 -0
- package/dist/src/ui/components/OrgInfoBox.js +16 -0
- package/dist/src/ui/components/OrgInfoBox.js.map +1 -0
- package/dist/src/ui/components/PendingPrompt.d.ts +18 -0
- package/dist/src/ui/components/PendingPrompt.js +57 -0
- package/dist/src/ui/components/PendingPrompt.js.map +1 -0
- package/dist/src/ui/components/PersistentTextInput.d.ts +21 -0
- package/dist/src/ui/components/PersistentTextInput.js +117 -0
- package/dist/src/ui/components/PersistentTextInput.js.map +1 -0
- package/dist/src/ui/components/PlanApprovalPrompt.d.ts +19 -0
- package/dist/src/ui/components/PlanApprovalPrompt.js +62 -0
- package/dist/src/ui/components/PlanApprovalPrompt.js.map +1 -0
- package/dist/src/ui/components/PromptContainer.d.ts +14 -0
- package/dist/src/ui/components/PromptContainer.js +18 -0
- package/dist/src/ui/components/PromptContainer.js.map +1 -0
- package/dist/src/ui/components/SelectPrompt.d.ts +14 -0
- package/dist/src/ui/components/SelectPrompt.js +62 -0
- package/dist/src/ui/components/SelectPrompt.js.map +1 -0
- package/dist/src/ui/components/SpinnerDisplay.d.ts +13 -0
- package/dist/src/ui/components/SpinnerDisplay.js +11 -0
- package/dist/src/ui/components/SpinnerDisplay.js.map +1 -0
- package/dist/src/ui/components/ToolApprovalPrompt.d.ts +14 -0
- package/dist/src/ui/components/ToolApprovalPrompt.js +142 -0
- package/dist/src/ui/components/ToolApprovalPrompt.js.map +1 -0
- package/dist/src/ui/components/ToolCallDisplay.d.ts +14 -0
- package/dist/src/ui/components/ToolCallDisplay.js +83 -0
- package/dist/src/ui/components/ToolCallDisplay.js.map +1 -0
- package/dist/src/ui/components/WriteKeyDisplay.d.ts +15 -0
- package/dist/src/ui/components/WriteKeyDisplay.js +13 -0
- package/dist/src/ui/components/WriteKeyDisplay.js.map +1 -0
- package/dist/src/ui/contexts/WizardContext.d.ts +210 -0
- package/dist/src/ui/contexts/WizardContext.js +362 -0
- package/dist/src/ui/contexts/WizardContext.js.map +1 -0
- package/dist/src/ui/hooks/useCancellation.d.ts +15 -0
- package/dist/src/ui/hooks/useCancellation.js +25 -0
- package/dist/src/ui/hooks/useCancellation.js.map +1 -0
- package/dist/src/ui/render.d.ts +34 -0
- package/dist/src/ui/render.js +94 -0
- package/dist/src/ui/render.js.map +1 -0
- package/dist/src/ui/types.d.ts +184 -0
- package/dist/src/ui/types.js +6 -0
- package/dist/src/ui/types.js.map +1 -0
- package/dist/src/utils/clack-utils.d.ts +13 -0
- package/dist/src/utils/clack-utils.js +131 -0
- package/dist/src/utils/clack-utils.js.map +1 -0
- package/dist/src/utils/debug.d.ts +13 -0
- package/dist/src/utils/debug.js +47 -0
- package/dist/src/utils/debug.js.map +1 -0
- package/dist/src/utils/environment.d.ts +5 -0
- package/dist/src/utils/environment.js +131 -0
- package/dist/src/utils/environment.js.map +1 -0
- package/dist/src/utils/logging.d.ts +9 -0
- package/dist/src/utils/logging.js +38 -0
- package/dist/src/utils/logging.js.map +1 -0
- package/dist/src/utils/oauth.d.ts +12 -0
- package/dist/src/utils/oauth.js +497 -0
- package/dist/src/utils/oauth.js.map +1 -0
- package/dist/src/utils/package-json-types.d.ts +44 -0
- package/dist/src/utils/package-json-types.js +6 -0
- package/dist/src/utils/package-json-types.js.map +1 -0
- package/dist/src/utils/package-json.d.ts +19 -0
- package/dist/src/utils/package-json.js +22 -0
- package/dist/src/utils/package-json.js.map +1 -0
- package/dist/src/utils/session.d.ts +2 -0
- package/dist/src/utils/session.js +87 -0
- package/dist/src/utils/session.js.map +1 -0
- package/dist/src/utils/types.d.ts +61 -0
- package/dist/src/utils/types.js +2 -0
- package/dist/src/utils/types.js.map +1 -0
- package/dist/src/utils/ui.d.ts +120 -0
- package/dist/src/utils/ui.js +164 -0
- package/dist/src/utils/ui.js.map +1 -0
- package/package.json +140 -0
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SDK message processing utilities
|
|
3
|
+
* Handles parsing and displaying SDK messages from the Claude agent
|
|
4
|
+
*/
|
|
5
|
+
import ui from '../utils/ui.js';
|
|
6
|
+
import { debug, logToFile } from '../utils/debug.js';
|
|
7
|
+
import { createTwoFilesPatch } from 'diff';
|
|
8
|
+
/** Internal SDK tools that should not be stored/displayed */
|
|
9
|
+
const INTERNAL_TOOLS = new Set([
|
|
10
|
+
'Task',
|
|
11
|
+
'AskUserQuestion',
|
|
12
|
+
'TodoWrite',
|
|
13
|
+
'mcp__raindrop-wizard__CompleteIntegration',
|
|
14
|
+
'mcp__raindrop-wizard__LoadPythonDocumentation',
|
|
15
|
+
'mcp__raindrop-wizard__LoadTypeScriptDocumentation',
|
|
16
|
+
'mcp__raindrop-wizard__LoadVercelAiSdkDocumentation',
|
|
17
|
+
'mcp__raindrop-wizard__LoadBrowserDocumentation',
|
|
18
|
+
'mcp__raindrop-wizard__InitializeSession',
|
|
19
|
+
'EnterPlanMode',
|
|
20
|
+
'ExitPlanMode',
|
|
21
|
+
]);
|
|
22
|
+
/**
|
|
23
|
+
* Generate a unified diff for Edit tool inputs (old_string -> new_string)
|
|
24
|
+
*/
|
|
25
|
+
function generateEditDiff(filePath, oldString, newString) {
|
|
26
|
+
return createTwoFilesPatch(filePath, filePath, oldString, newString, '', // old header
|
|
27
|
+
'', // new header
|
|
28
|
+
{ context: 3 });
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Extract summary for Edit tool (line changes)
|
|
32
|
+
*/
|
|
33
|
+
function extractEditSummary(input) {
|
|
34
|
+
const oldString = typeof input.old_string === 'string' ? input.old_string : '';
|
|
35
|
+
const newString = typeof input.new_string === 'string' ? input.new_string : '';
|
|
36
|
+
const oldLines = oldString ? oldString.split('\n').length : 0;
|
|
37
|
+
const newLines = newString ? newString.split('\n').length : 0;
|
|
38
|
+
const added = Math.max(0, newLines - oldLines);
|
|
39
|
+
const removed = Math.max(0, oldLines - newLines);
|
|
40
|
+
// Handle the case where lines are replaced (same count but different content)
|
|
41
|
+
if (added === 0 && removed === 0 && oldString !== newString) {
|
|
42
|
+
return `Updated ${oldLines} line${oldLines === 1 ? '' : 's'}`;
|
|
43
|
+
}
|
|
44
|
+
const parts = [];
|
|
45
|
+
if (added > 0)
|
|
46
|
+
parts.push(`Added ${added} line${added === 1 ? '' : 's'}`);
|
|
47
|
+
if (removed > 0)
|
|
48
|
+
parts.push(`removed ${removed} line${removed === 1 ? '' : 's'}`);
|
|
49
|
+
return parts.length > 0 ? parts.join(', ') : 'No changes';
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Extract summary for Write tool (lines written)
|
|
53
|
+
*/
|
|
54
|
+
function extractWriteSummary(input) {
|
|
55
|
+
const content = typeof input.content === 'string' ? input.content : '';
|
|
56
|
+
const lines = content ? content.split('\n').length : 0;
|
|
57
|
+
const fileName = typeof input.path === 'string' ? input.path.split('/').pop() : 'file';
|
|
58
|
+
return `Wrote ${lines} line${lines === 1 ? '' : 's'} to ${fileName}`;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Generate diff content and file name for Edit/Write tools
|
|
62
|
+
*/
|
|
63
|
+
function extractEditWriteInfo(toolName, input) {
|
|
64
|
+
const fileName = typeof input.file_path === 'string'
|
|
65
|
+
? input.file_path
|
|
66
|
+
: typeof input.path === 'string'
|
|
67
|
+
? input.path
|
|
68
|
+
: undefined;
|
|
69
|
+
if (toolName === 'Edit' && fileName) {
|
|
70
|
+
const oldString = typeof input.old_string === 'string' ? input.old_string : '';
|
|
71
|
+
const newString = typeof input.new_string === 'string' ? input.new_string : '';
|
|
72
|
+
const diffContent = generateEditDiff(fileName, oldString, newString);
|
|
73
|
+
return { diffContent, fileName };
|
|
74
|
+
}
|
|
75
|
+
if (toolName === 'Write' && fileName) {
|
|
76
|
+
const content = typeof input.content === 'string' ? input.content : '';
|
|
77
|
+
const diffContent = generateEditDiff(fileName, '', content);
|
|
78
|
+
return { diffContent, fileName };
|
|
79
|
+
}
|
|
80
|
+
return {};
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Extract result summary from tool result content
|
|
84
|
+
*/
|
|
85
|
+
export function extractResultSummary(toolName, resultContent, input) {
|
|
86
|
+
// Handle string content
|
|
87
|
+
const content = typeof resultContent === 'string'
|
|
88
|
+
? resultContent
|
|
89
|
+
: Array.isArray(resultContent)
|
|
90
|
+
? resultContent.map((c) => c.text || '').join('\n')
|
|
91
|
+
: '';
|
|
92
|
+
if (!content)
|
|
93
|
+
return undefined;
|
|
94
|
+
switch (toolName) {
|
|
95
|
+
case 'Glob': {
|
|
96
|
+
// Count non-empty lines (each line is a file path)
|
|
97
|
+
const lines = content
|
|
98
|
+
.trim()
|
|
99
|
+
.split('\n')
|
|
100
|
+
.filter((l) => l.trim());
|
|
101
|
+
return `Found ${lines.length} files`;
|
|
102
|
+
}
|
|
103
|
+
case 'Read': {
|
|
104
|
+
// Count lines in the file content
|
|
105
|
+
const lineCount = content.split('\n').length;
|
|
106
|
+
return `Read ${lineCount} lines`;
|
|
107
|
+
}
|
|
108
|
+
case 'Grep': {
|
|
109
|
+
// Count match lines
|
|
110
|
+
const lines = content
|
|
111
|
+
.trim()
|
|
112
|
+
.split('\n')
|
|
113
|
+
.filter((l) => l.trim());
|
|
114
|
+
return `Found ${lines.length} matches`;
|
|
115
|
+
}
|
|
116
|
+
case 'Edit': {
|
|
117
|
+
if (input) {
|
|
118
|
+
return extractEditSummary(input);
|
|
119
|
+
}
|
|
120
|
+
return undefined;
|
|
121
|
+
}
|
|
122
|
+
case 'Write': {
|
|
123
|
+
if (input) {
|
|
124
|
+
return extractWriteSummary(input);
|
|
125
|
+
}
|
|
126
|
+
return undefined;
|
|
127
|
+
}
|
|
128
|
+
default:
|
|
129
|
+
return undefined;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Process SDK messages and provide user feedback.
|
|
134
|
+
* Handles assistant text, tool use, tool results, and system messages.
|
|
135
|
+
*/
|
|
136
|
+
export function processSDKMessage(message, options, collectedText, pendingToolCalls, isInterrupting) {
|
|
137
|
+
logToFile(`SDK Message: ${message.type}`, JSON.stringify(message, null, 2));
|
|
138
|
+
if (options.debug) {
|
|
139
|
+
debug(`SDK Message type: ${message.type}`);
|
|
140
|
+
}
|
|
141
|
+
switch (message.type) {
|
|
142
|
+
case 'assistant': {
|
|
143
|
+
// Extract text content from assistant messages
|
|
144
|
+
const content = message.message?.content;
|
|
145
|
+
if (Array.isArray(content)) {
|
|
146
|
+
for (const block of content) {
|
|
147
|
+
if (block.type === 'text' && typeof block.text === 'string') {
|
|
148
|
+
collectedText.push(block.text);
|
|
149
|
+
// Add agent message to history for visibility
|
|
150
|
+
ui.addItem({
|
|
151
|
+
type: 'agent-message',
|
|
152
|
+
text: block.text,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
// Handle tool_use blocks - store pending, don't add to history yet
|
|
156
|
+
if (block.type === 'tool_use') {
|
|
157
|
+
const toolName = block.name || 'Unknown tool';
|
|
158
|
+
const toolInput = block.input || {};
|
|
159
|
+
const toolUseId = block.id;
|
|
160
|
+
logToFile(`Tool use requested: ${toolName} (id: ${toolUseId})`, toolInput);
|
|
161
|
+
// Skip storing/displaying internal SDK tools
|
|
162
|
+
if (INTERNAL_TOOLS.has(toolName)) {
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
// Store pending tool call to complete when result arrives
|
|
166
|
+
pendingToolCalls.set(toolUseId, {
|
|
167
|
+
toolName,
|
|
168
|
+
input: toolInput,
|
|
169
|
+
description: typeof toolInput.description === 'string'
|
|
170
|
+
? toolInput.description
|
|
171
|
+
: undefined,
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
break;
|
|
177
|
+
}
|
|
178
|
+
case 'user': {
|
|
179
|
+
// Tool results come as 'user' messages with tool_result content
|
|
180
|
+
const content = message.message?.content;
|
|
181
|
+
if (Array.isArray(content)) {
|
|
182
|
+
for (const block of content) {
|
|
183
|
+
if (block.type === 'tool_result') {
|
|
184
|
+
const toolUseId = block.tool_use_id;
|
|
185
|
+
const isError = block.is_error === true;
|
|
186
|
+
const resultContent = block.content;
|
|
187
|
+
logToFile(`Tool result for ${toolUseId}:`, {
|
|
188
|
+
isError,
|
|
189
|
+
content: resultContent,
|
|
190
|
+
});
|
|
191
|
+
// Look up the pending tool call
|
|
192
|
+
const pendingCall = pendingToolCalls.get(toolUseId);
|
|
193
|
+
if (pendingCall) {
|
|
194
|
+
pendingToolCalls.delete(toolUseId);
|
|
195
|
+
// Extract diff content and file name for Edit/Write tools
|
|
196
|
+
const { diffContent, fileName } = extractEditWriteInfo(pendingCall.toolName, pendingCall.input);
|
|
197
|
+
// Skip displaying Write tool calls for plan files
|
|
198
|
+
const isPlanWrite = pendingCall.toolName === 'Write' &&
|
|
199
|
+
fileName &&
|
|
200
|
+
fileName.includes('plans/');
|
|
201
|
+
if (isPlanWrite) {
|
|
202
|
+
// Don't add plan writes to history
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
// Extract result summary based on tool type
|
|
206
|
+
const resultSummary = extractResultSummary(pendingCall.toolName, resultContent, pendingCall.input);
|
|
207
|
+
// Add completed tool call to history
|
|
208
|
+
ui.addItem({
|
|
209
|
+
type: 'tool-call',
|
|
210
|
+
text: pendingCall.toolName,
|
|
211
|
+
toolCall: {
|
|
212
|
+
toolName: pendingCall.toolName,
|
|
213
|
+
status: isError ? 'error' : 'success',
|
|
214
|
+
input: pendingCall.input,
|
|
215
|
+
description: pendingCall.description,
|
|
216
|
+
result: resultSummary,
|
|
217
|
+
error: isError ? String(resultContent) : undefined,
|
|
218
|
+
diffContent,
|
|
219
|
+
fileName,
|
|
220
|
+
},
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
if (isError && options.debug) {
|
|
224
|
+
debug(`Tool error: ${resultContent}`);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
break;
|
|
230
|
+
}
|
|
231
|
+
case 'result': {
|
|
232
|
+
if (message.subtype === 'success') {
|
|
233
|
+
logToFile('Agent completed successfully');
|
|
234
|
+
if (typeof message.result === 'string') {
|
|
235
|
+
collectedText.push(message.result);
|
|
236
|
+
// Note: We intentionally don't display the result message here.
|
|
237
|
+
// The SDK's result.result field contains the same text as the last
|
|
238
|
+
// assistant message, which we already render above. Displaying both
|
|
239
|
+
// would cause duplicate output in the UI.
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
// Error result - suppress if it's an interrupt-related error
|
|
244
|
+
logToFile('Agent error result:', message.subtype);
|
|
245
|
+
if (message.errors && !isInterrupting) {
|
|
246
|
+
for (const err of message.errors) {
|
|
247
|
+
// Check if error is interrupt-related
|
|
248
|
+
const errStr = String(err);
|
|
249
|
+
const isInterruptError = errStr.includes('aborted') ||
|
|
250
|
+
errStr.includes('interrupted') ||
|
|
251
|
+
errStr.includes('403');
|
|
252
|
+
if (!isInterruptError) {
|
|
253
|
+
ui.addItem({ type: 'error', text: `Error: ${err}` });
|
|
254
|
+
}
|
|
255
|
+
logToFile('ERROR:', err);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
break;
|
|
260
|
+
}
|
|
261
|
+
case 'system': {
|
|
262
|
+
if (message.subtype === 'init') {
|
|
263
|
+
logToFile('Agent session initialized', {
|
|
264
|
+
model: message.model,
|
|
265
|
+
tools: message.tools?.length,
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
break;
|
|
269
|
+
}
|
|
270
|
+
default:
|
|
271
|
+
// Log other message types for debugging
|
|
272
|
+
if (options.debug) {
|
|
273
|
+
debug(`Unhandled message type: ${message.type}`);
|
|
274
|
+
}
|
|
275
|
+
break;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
//# sourceMappingURL=sdk-messages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sdk-messages.js","sourceRoot":"","sources":["../../../src/lib/sdk-messages.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * SDK message processing utilities\n * Handles parsing and displaying SDK messages from the Claude agent\n */\n\nimport ui from '../utils/ui.js';\nimport { debug, logToFile } from '../utils/debug.js';\nimport type { PendingToolCall } from './handlers.js';\nimport type { WizardOptions } from '../utils/types.js';\nimport { createTwoFilesPatch } from 'diff';\n\n// Using `any` because typed imports from ESM modules require import attributes\n// syntax which prettier cannot parse.\ntype SDKMessage = any;\n\n/** Internal SDK tools that should not be stored/displayed */\nconst INTERNAL_TOOLS = new Set([\n 'Task',\n 'AskUserQuestion',\n 'TodoWrite',\n 'mcp__raindrop-wizard__CompleteIntegration',\n 'mcp__raindrop-wizard__LoadPythonDocumentation',\n 'mcp__raindrop-wizard__LoadTypeScriptDocumentation',\n 'mcp__raindrop-wizard__LoadVercelAiSdkDocumentation',\n 'mcp__raindrop-wizard__LoadBrowserDocumentation',\n 'mcp__raindrop-wizard__InitializeSession',\n 'EnterPlanMode',\n 'ExitPlanMode',\n]);\n\n/**\n * Generate a unified diff for Edit tool inputs (old_string -> new_string)\n */\nfunction generateEditDiff(\n filePath: string,\n oldString: string,\n newString: string,\n): string {\n return createTwoFilesPatch(\n filePath,\n filePath,\n oldString,\n newString,\n '', // old header\n '', // new header\n { context: 3 }, // context lines\n );\n}\n\n/**\n * Extract summary for Edit tool (line changes)\n */\nfunction extractEditSummary(input: Record<string, unknown>): string {\n const oldString =\n typeof input.old_string === 'string' ? input.old_string : '';\n const newString =\n typeof input.new_string === 'string' ? input.new_string : '';\n\n const oldLines = oldString ? oldString.split('\\n').length : 0;\n const newLines = newString ? newString.split('\\n').length : 0;\n\n const added = Math.max(0, newLines - oldLines);\n const removed = Math.max(0, oldLines - newLines);\n\n // Handle the case where lines are replaced (same count but different content)\n if (added === 0 && removed === 0 && oldString !== newString) {\n return `Updated ${oldLines} line${oldLines === 1 ? '' : 's'}`;\n }\n\n const parts: string[] = [];\n if (added > 0) parts.push(`Added ${added} line${added === 1 ? '' : 's'}`);\n if (removed > 0)\n parts.push(`removed ${removed} line${removed === 1 ? '' : 's'}`);\n\n return parts.length > 0 ? parts.join(', ') : 'No changes';\n}\n\n/**\n * Extract summary for Write tool (lines written)\n */\nfunction extractWriteSummary(input: Record<string, unknown>): string {\n const content = typeof input.content === 'string' ? input.content : '';\n const lines = content ? content.split('\\n').length : 0;\n const fileName =\n typeof input.path === 'string' ? input.path.split('/').pop() : 'file';\n return `Wrote ${lines} line${lines === 1 ? '' : 's'} to ${fileName}`;\n}\n\n/**\n * Generate diff content and file name for Edit/Write tools\n */\nfunction extractEditWriteInfo(\n toolName: string,\n input: Record<string, unknown>,\n): { diffContent?: string; fileName?: string } {\n const fileName =\n typeof input.file_path === 'string'\n ? input.file_path\n : typeof input.path === 'string'\n ? input.path\n : undefined;\n\n if (toolName === 'Edit' && fileName) {\n const oldString =\n typeof input.old_string === 'string' ? input.old_string : '';\n const newString =\n typeof input.new_string === 'string' ? input.new_string : '';\n const diffContent = generateEditDiff(fileName, oldString, newString);\n return { diffContent, fileName };\n }\n\n if (toolName === 'Write' && fileName) {\n const content = typeof input.content === 'string' ? input.content : '';\n const diffContent = generateEditDiff(fileName, '', content);\n return { diffContent, fileName };\n }\n\n return {};\n}\n\n/**\n * Extract result summary from tool result content\n */\nexport function extractResultSummary(\n toolName: string,\n resultContent: unknown,\n input?: Record<string, unknown>,\n): string | undefined {\n // Handle string content\n const content =\n typeof resultContent === 'string'\n ? resultContent\n : Array.isArray(resultContent)\n ? resultContent.map((c: any) => c.text || '').join('\\n')\n : '';\n\n if (!content) return undefined;\n\n switch (toolName) {\n case 'Glob': {\n // Count non-empty lines (each line is a file path)\n const lines = content\n .trim()\n .split('\\n')\n .filter((l: string) => l.trim());\n return `Found ${lines.length} files`;\n }\n case 'Read': {\n // Count lines in the file content\n const lineCount = content.split('\\n').length;\n return `Read ${lineCount} lines`;\n }\n case 'Grep': {\n // Count match lines\n const lines = content\n .trim()\n .split('\\n')\n .filter((l: string) => l.trim());\n return `Found ${lines.length} matches`;\n }\n case 'Edit': {\n if (input) {\n return extractEditSummary(input);\n }\n return undefined;\n }\n case 'Write': {\n if (input) {\n return extractWriteSummary(input);\n }\n return undefined;\n }\n default:\n return undefined;\n }\n}\n\n/**\n * Process SDK messages and provide user feedback.\n * Handles assistant text, tool use, tool results, and system messages.\n */\nexport function processSDKMessage(\n message: SDKMessage,\n options: WizardOptions,\n collectedText: string[],\n pendingToolCalls: Map<string, PendingToolCall>,\n isInterrupting: boolean,\n): void {\n logToFile(`SDK Message: ${message.type}`, JSON.stringify(message, null, 2));\n\n if (options.debug) {\n debug(`SDK Message type: ${message.type}`);\n }\n\n switch (message.type) {\n case 'assistant': {\n // Extract text content from assistant messages\n const content = message.message?.content;\n if (Array.isArray(content)) {\n for (const block of content) {\n if (block.type === 'text' && typeof block.text === 'string') {\n collectedText.push(block.text);\n\n // Add agent message to history for visibility\n ui.addItem({\n type: 'agent-message',\n text: block.text,\n });\n }\n // Handle tool_use blocks - store pending, don't add to history yet\n if (block.type === 'tool_use') {\n const toolName = block.name || 'Unknown tool';\n const toolInput = block.input || {};\n const toolUseId = block.id;\n logToFile(\n `Tool use requested: ${toolName} (id: ${toolUseId})`,\n toolInput,\n );\n\n // Skip storing/displaying internal SDK tools\n if (INTERNAL_TOOLS.has(toolName)) {\n continue;\n }\n\n // Store pending tool call to complete when result arrives\n pendingToolCalls.set(toolUseId, {\n toolName,\n input: toolInput,\n description:\n typeof toolInput.description === 'string'\n ? toolInput.description\n : undefined,\n });\n }\n }\n }\n break;\n }\n\n case 'user': {\n // Tool results come as 'user' messages with tool_result content\n const content = message.message?.content;\n if (Array.isArray(content)) {\n for (const block of content) {\n if (block.type === 'tool_result') {\n const toolUseId = block.tool_use_id;\n const isError = block.is_error === true;\n const resultContent = block.content;\n\n logToFile(`Tool result for ${toolUseId}:`, {\n isError,\n content: resultContent,\n });\n\n // Look up the pending tool call\n const pendingCall = pendingToolCalls.get(toolUseId);\n if (pendingCall) {\n pendingToolCalls.delete(toolUseId);\n\n // Extract diff content and file name for Edit/Write tools\n const { diffContent, fileName } = extractEditWriteInfo(\n pendingCall.toolName,\n pendingCall.input,\n );\n\n // Skip displaying Write tool calls for plan files\n const isPlanWrite =\n pendingCall.toolName === 'Write' &&\n fileName &&\n fileName.includes('plans/');\n\n if (isPlanWrite) {\n // Don't add plan writes to history\n continue;\n }\n\n // Extract result summary based on tool type\n const resultSummary = extractResultSummary(\n pendingCall.toolName,\n resultContent,\n pendingCall.input,\n );\n\n // Add completed tool call to history\n ui.addItem({\n type: 'tool-call',\n text: pendingCall.toolName,\n toolCall: {\n toolName: pendingCall.toolName,\n status: isError ? 'error' : 'success',\n input: pendingCall.input,\n description: pendingCall.description,\n result: resultSummary,\n error: isError ? String(resultContent) : undefined,\n diffContent,\n fileName,\n },\n });\n }\n\n if (isError && options.debug) {\n debug(`Tool error: ${resultContent}`);\n }\n }\n }\n }\n break;\n }\n\n case 'result': {\n if (message.subtype === 'success') {\n logToFile('Agent completed successfully');\n if (typeof message.result === 'string') {\n collectedText.push(message.result);\n // Note: We intentionally don't display the result message here.\n // The SDK's result.result field contains the same text as the last\n // assistant message, which we already render above. Displaying both\n // would cause duplicate output in the UI.\n }\n } else {\n // Error result - suppress if it's an interrupt-related error\n logToFile('Agent error result:', message.subtype);\n if (message.errors && !isInterrupting) {\n for (const err of message.errors) {\n // Check if error is interrupt-related\n const errStr = String(err);\n const isInterruptError =\n errStr.includes('aborted') ||\n errStr.includes('interrupted') ||\n errStr.includes('403');\n if (!isInterruptError) {\n ui.addItem({ type: 'error', text: `Error: ${err}` });\n }\n logToFile('ERROR:', err);\n }\n }\n }\n break;\n }\n\n case 'system': {\n if (message.subtype === 'init') {\n logToFile('Agent session initialized', {\n model: message.model,\n tools: message.tools?.length,\n });\n }\n break;\n }\n\n default:\n // Log other message types for debugging\n if (options.debug) {\n debug(`Unhandled message type: ${message.type}`);\n }\n break;\n }\n}\n"]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { WizardOptions } from '../utils/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Unified wizard powered by the universal agent runner.
|
|
4
|
+
* The agent will detect the integration type and load appropriate documentation.
|
|
5
|
+
*/
|
|
6
|
+
export declare function runWizard(options: WizardOptions): Promise<void>;
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import Chalk from 'chalk';
|
|
2
|
+
import clipboardy from 'clipboardy';
|
|
3
|
+
import { askForWizardLogin, confirmContinueIfNoOrDirtyGitRepo, } from '../utils/clack-utils.js';
|
|
4
|
+
import { enableDebugLogs } from '../utils/debug.js';
|
|
5
|
+
import { saveWriteKeyToEnv } from '../utils/environment.js';
|
|
6
|
+
import { getOrgWriteKey } from '../utils/oauth.js';
|
|
7
|
+
import ui from '../utils/ui.js';
|
|
8
|
+
import { initializeAgent, runAgentLoop } from './agent-interface.js';
|
|
9
|
+
import { ANTHROPIC_BASE_URL, SPINNER_MESSAGE } from './constants.js';
|
|
10
|
+
import { testIntegration } from './integration-testing.js';
|
|
11
|
+
// chalk v2 types don't work well with ESM default imports
|
|
12
|
+
const chalk = Chalk;
|
|
13
|
+
/**
|
|
14
|
+
* Unified wizard powered by the universal agent runner.
|
|
15
|
+
* The agent will detect the integration type and load appropriate documentation.
|
|
16
|
+
*/
|
|
17
|
+
export async function runWizard(options) {
|
|
18
|
+
if (options.debug) {
|
|
19
|
+
enableDebugLogs();
|
|
20
|
+
}
|
|
21
|
+
// Check if the current directory is a git repository and has uncommitted or untracked changes; prompt the user to continue if so.
|
|
22
|
+
await confirmContinueIfNoOrDirtyGitRepo(options);
|
|
23
|
+
const token = await askForWizardLogin();
|
|
24
|
+
// Set the wizard JWT in process.env for the SDK
|
|
25
|
+
process.env.ANTHROPIC_AUTH_TOKEN = token.token;
|
|
26
|
+
const writeKeySpinner = ui.spinner();
|
|
27
|
+
writeKeySpinner.start('Retrieving your Raindrop write key...');
|
|
28
|
+
let writeKey;
|
|
29
|
+
try {
|
|
30
|
+
const result = await getOrgWriteKey(token.token);
|
|
31
|
+
writeKey = result.writeKey;
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
writeKeySpinner.stop('Failed to retrieve write key');
|
|
35
|
+
ui.addItem({
|
|
36
|
+
type: 'error',
|
|
37
|
+
text: `Error: ${error instanceof Error ? error.message : String(error)}`,
|
|
38
|
+
});
|
|
39
|
+
throw error;
|
|
40
|
+
}
|
|
41
|
+
writeKeySpinner.stop();
|
|
42
|
+
// Show org info and write key in a beautiful box
|
|
43
|
+
ui.addItem({
|
|
44
|
+
type: 'org-info',
|
|
45
|
+
text: 'Organization info',
|
|
46
|
+
orgName: token.orgName,
|
|
47
|
+
writeKey,
|
|
48
|
+
});
|
|
49
|
+
// Prompt user for what to do with the write key
|
|
50
|
+
const writeKeyAction = await ui.feedbackSelect({
|
|
51
|
+
message: `What would you like to do with your ${chalk.cyan('RAINDROP_WRITE_KEY')}?`,
|
|
52
|
+
options: [
|
|
53
|
+
{ value: 'add-env', label: 'Add to .env' },
|
|
54
|
+
{ value: 'copy', label: 'Copy to clipboard' },
|
|
55
|
+
{ value: 'continue', label: 'Continue' },
|
|
56
|
+
],
|
|
57
|
+
skipHistory: true,
|
|
58
|
+
});
|
|
59
|
+
// Determine the label for the history item based on action taken
|
|
60
|
+
let writeKeyLabel;
|
|
61
|
+
if (writeKeyAction.type === 'option') {
|
|
62
|
+
if (writeKeyAction.value === 'add-env') {
|
|
63
|
+
try {
|
|
64
|
+
await saveWriteKeyToEnv(writeKey, options.installDir);
|
|
65
|
+
writeKeyLabel = 'saved to .env';
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
ui.addItem({
|
|
69
|
+
type: 'error',
|
|
70
|
+
text: `Failed to add write key to .env: ${error instanceof Error ? error.message : String(error)}`,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
else if (writeKeyAction.value === 'copy') {
|
|
75
|
+
try {
|
|
76
|
+
await clipboardy.write(`RAINDROP_WRITE_KEY=${writeKey}`);
|
|
77
|
+
writeKeyLabel = 'copied to clipboard';
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
ui.addItem({
|
|
81
|
+
type: 'error',
|
|
82
|
+
text: `Failed to copy to clipboard: ${error instanceof Error ? error.message : String(error)}`,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// For 'continue', writeKeyLabel remains undefined
|
|
87
|
+
}
|
|
88
|
+
process.env.ANTHROPIC_BASE_URL = ANTHROPIC_BASE_URL;
|
|
89
|
+
process.env.ANTHROPIC_AUTH_TOKEN = token.token;
|
|
90
|
+
process.env.ANTHROPIC_CUSTOM_HEADERS = `x-wizard-session: ${options.sessionId}`;
|
|
91
|
+
// Initialize agent
|
|
92
|
+
const agent = initializeAgent({
|
|
93
|
+
workingDirectory: options.installDir,
|
|
94
|
+
}, options);
|
|
95
|
+
let prompt = 'begin';
|
|
96
|
+
let resume = undefined;
|
|
97
|
+
let shouldContinue = true;
|
|
98
|
+
while (shouldContinue) {
|
|
99
|
+
const agentResult = await runAgentLoop(agent, prompt, options, {
|
|
100
|
+
spinnerMessage: SPINNER_MESSAGE,
|
|
101
|
+
successMessage: 'Raindrop integration complete',
|
|
102
|
+
resume,
|
|
103
|
+
accessToken: token.token,
|
|
104
|
+
orgId: token.orgId.toString(),
|
|
105
|
+
});
|
|
106
|
+
// Ensure persistent input is stopped before testing phase
|
|
107
|
+
ui.stopPersistentInput();
|
|
108
|
+
const result = await testIntegration(options, writeKey, token.token);
|
|
109
|
+
if (result.shouldRetry && result.feedbackPrompt) {
|
|
110
|
+
prompt = result.feedbackPrompt;
|
|
111
|
+
resume = agentResult.sessionId;
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
shouldContinue = false;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
// Build outro message
|
|
118
|
+
const nextSteps = [
|
|
119
|
+
'Configure your API key in environment variables for deployment',
|
|
120
|
+
'Start using Raindrop in your application',
|
|
121
|
+
].filter(Boolean);
|
|
122
|
+
const outroMessage = `${chalk.white('Raindrop successfully integrated')}
|
|
123
|
+
|
|
124
|
+
${chalk.yellow('Next steps:')}
|
|
125
|
+
${nextSteps.map((step) => `• ${step}`).join('\n')}
|
|
126
|
+
|
|
127
|
+
Learn more: ${chalk.cyan('https://www.raindrop.ai/docs')}
|
|
128
|
+
${chalk.dim('Note: The Raindrop wizard uses an LLM agent to analyze and modify your project. Please review the changes made.')}`;
|
|
129
|
+
ui.addItem({ type: 'success', text: outroMessage });
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=wizard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wizard.js","sourceRoot":"","sources":["../../../src/lib/wizard.ts"],"names":[],"mappings":"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","sourcesContent":["import Chalk from 'chalk';\nimport clipboardy from 'clipboardy';\nimport {\n askForWizardLogin,\n confirmContinueIfNoOrDirtyGitRepo,\n} from '../utils/clack-utils.js';\nimport { enableDebugLogs } from '../utils/debug.js';\nimport { saveWriteKeyToEnv } from '../utils/environment.js';\nimport { getOrgWriteKey } from '../utils/oauth.js';\nimport type { WizardOptions } from '../utils/types.js';\nimport ui from '../utils/ui.js';\nimport { initializeAgent, runAgentLoop } from './agent-interface.js';\nimport { ANTHROPIC_BASE_URL, SPINNER_MESSAGE } from './constants.js';\nimport { testIntegration } from './integration-testing.js';\n\n// chalk v2 types don't work well with ESM default imports\nconst chalk = Chalk as any;\n\n/**\n * Unified wizard powered by the universal agent runner.\n * The agent will detect the integration type and load appropriate documentation.\n */\nexport async function runWizard(options: WizardOptions): Promise<void> {\n if (options.debug) {\n enableDebugLogs();\n }\n\n // Check if the current directory is a git repository and has uncommitted or untracked changes; prompt the user to continue if so.\n await confirmContinueIfNoOrDirtyGitRepo(options);\n\n const token = await askForWizardLogin();\n\n // Set the wizard JWT in process.env for the SDK\n process.env.ANTHROPIC_AUTH_TOKEN = token.token;\n\n const writeKeySpinner = ui.spinner();\n writeKeySpinner.start('Retrieving your Raindrop write key...');\n\n let writeKey: string;\n try {\n const result = await getOrgWriteKey(token.token);\n writeKey = result.writeKey;\n } catch (error) {\n writeKeySpinner.stop('Failed to retrieve write key');\n ui.addItem({\n type: 'error',\n text: `Error: ${error instanceof Error ? error.message : String(error)}`,\n });\n throw error;\n }\n\n writeKeySpinner.stop();\n\n // Show org info and write key in a beautiful box\n ui.addItem({\n type: 'org-info',\n text: 'Organization info',\n orgName: token.orgName,\n writeKey,\n });\n\n // Prompt user for what to do with the write key\n const writeKeyAction = await ui.feedbackSelect({\n message: `What would you like to do with your ${chalk.cyan(\n 'RAINDROP_WRITE_KEY',\n )}?`,\n options: [\n { value: 'add-env', label: 'Add to .env' },\n { value: 'copy', label: 'Copy to clipboard' },\n { value: 'continue', label: 'Continue' },\n ],\n skipHistory: true,\n });\n\n // Determine the label for the history item based on action taken\n let writeKeyLabel: string | undefined;\n\n if (writeKeyAction.type === 'option') {\n if (writeKeyAction.value === 'add-env') {\n try {\n await saveWriteKeyToEnv(writeKey, options.installDir);\n writeKeyLabel = 'saved to .env';\n } catch (error) {\n ui.addItem({\n type: 'error',\n text: `Failed to add write key to .env: ${\n error instanceof Error ? error.message : String(error)\n }`,\n });\n }\n } else if (writeKeyAction.value === 'copy') {\n try {\n await clipboardy.write(`RAINDROP_WRITE_KEY=${writeKey}`);\n writeKeyLabel = 'copied to clipboard';\n } catch (error) {\n ui.addItem({\n type: 'error',\n text: `Failed to copy to clipboard: ${\n error instanceof Error ? error.message : String(error)\n }`,\n });\n }\n }\n // For 'continue', writeKeyLabel remains undefined\n }\n\n process.env.ANTHROPIC_BASE_URL = ANTHROPIC_BASE_URL;\n process.env.ANTHROPIC_AUTH_TOKEN = token.token;\n process.env.ANTHROPIC_CUSTOM_HEADERS = `x-wizard-session: ${options.sessionId}`;\n\n // Initialize agent\n const agent = initializeAgent(\n {\n workingDirectory: options.installDir,\n },\n options,\n );\n\n let prompt = 'begin';\n let resume: string | undefined = undefined;\n let shouldContinue = true;\n\n while (shouldContinue) {\n const agentResult = await runAgentLoop(agent, prompt, options, {\n spinnerMessage: SPINNER_MESSAGE,\n successMessage: 'Raindrop integration complete',\n resume,\n accessToken: token.token,\n orgId: token.orgId.toString(),\n });\n\n // Ensure persistent input is stopped before testing phase\n ui.stopPersistentInput();\n\n const result = await testIntegration(options, writeKey, token.token);\n\n if (result.shouldRetry && result.feedbackPrompt) {\n prompt = result.feedbackPrompt;\n resume = agentResult.sessionId;\n } else {\n shouldContinue = false;\n }\n }\n\n // Build outro message\n const nextSteps = [\n 'Configure your API key in environment variables for deployment',\n 'Start using Raindrop in your application',\n ].filter(Boolean);\n\n const outroMessage = `${chalk.white('Raindrop successfully integrated')}\n\n${chalk.yellow('Next steps:')}\n${nextSteps.map((step) => `• ${step}`).join('\\n')}\n\nLearn more: ${chalk.cyan('https://www.raindrop.ai/docs')}\n${chalk.dim(\n 'Note: The Raindrop wizard uses an LLM agent to analyze and modify your project. Please review the changes made.',\n)}`;\n\n ui.addItem({ type: 'success', text: outroMessage });\n}\n"]}
|
package/dist/src/run.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { randomUUID } from 'crypto';
|
|
2
|
+
import { EventEmitter } from 'events';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { runWizard as runWizardImpl } from './lib/wizard.js';
|
|
5
|
+
import { readEnvironment } from './utils/environment.js';
|
|
6
|
+
import ui from './utils/ui.js';
|
|
7
|
+
EventEmitter.defaultMaxListeners = 50;
|
|
8
|
+
export async function runWizard(argv) {
|
|
9
|
+
const finalArgs = {
|
|
10
|
+
...argv,
|
|
11
|
+
...readEnvironment(),
|
|
12
|
+
};
|
|
13
|
+
let resolvedInstallDir;
|
|
14
|
+
if (finalArgs.installDir) {
|
|
15
|
+
if (path.isAbsolute(finalArgs.installDir)) {
|
|
16
|
+
resolvedInstallDir = finalArgs.installDir;
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
resolvedInstallDir = path.join(process.cwd(), finalArgs.installDir);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
resolvedInstallDir = process.cwd();
|
|
24
|
+
}
|
|
25
|
+
const wizardOptions = {
|
|
26
|
+
debug: finalArgs.debug ?? false,
|
|
27
|
+
forceInstall: finalArgs.forceInstall ?? false,
|
|
28
|
+
installDir: resolvedInstallDir,
|
|
29
|
+
default: finalArgs.default ?? false,
|
|
30
|
+
sessionId: randomUUID(),
|
|
31
|
+
compiledSetup: '', // Not used in unified wizard
|
|
32
|
+
};
|
|
33
|
+
ui.addItem({
|
|
34
|
+
type: 'phase',
|
|
35
|
+
text: '─── Setup ───',
|
|
36
|
+
});
|
|
37
|
+
ui.addItem({
|
|
38
|
+
type: 'response',
|
|
39
|
+
text: `Let's get Raindrop set up for your project.`,
|
|
40
|
+
});
|
|
41
|
+
try {
|
|
42
|
+
await runWizardImpl(wizardOptions);
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
ui.addItem({
|
|
46
|
+
type: 'error',
|
|
47
|
+
text: `Something went wrong. You can read the documentation at https://raindrop.ai/docs to set up Raindrop manually.`,
|
|
48
|
+
});
|
|
49
|
+
ui.addItem({ type: 'error', text: `error: ${String(error)}` });
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/run.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,SAAS,IAAI,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,MAAM,eAAe,CAAC;AAE/B,YAAY,CAAC,mBAAmB,GAAG,EAAE,CAAC;AAStC,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAU;IACxC,MAAM,SAAS,GAAG;QAChB,GAAG,IAAI;QACP,GAAG,eAAe,EAAE;KACrB,CAAC;IAEF,IAAI,kBAA0B,CAAC;IAC/B,IAAI,SAAS,CAAC,UAAU,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,CAAC;YAC1C,kBAAkB,GAAG,SAAS,CAAC,UAAU,CAAC;QAC5C,CAAC;aAAM,CAAC;YACN,kBAAkB,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,CAAC,UAAU,CAAC,CAAC;QACtE,CAAC;IACH,CAAC;SAAM,CAAC;QACN,kBAAkB,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IACrC,CAAC;IAED,MAAM,aAAa,GAAkB;QACnC,KAAK,EAAE,SAAS,CAAC,KAAK,IAAI,KAAK;QAC/B,YAAY,EAAE,SAAS,CAAC,YAAY,IAAI,KAAK;QAC7C,UAAU,EAAE,kBAAkB;QAC9B,OAAO,EAAE,SAAS,CAAC,OAAO,IAAI,KAAK;QACnC,SAAS,EAAE,UAAU,EAAE;QACvB,aAAa,EAAE,EAAE,EAAE,6BAA6B;KACjD,CAAC;IAEF,EAAE,CAAC,OAAO,CAAC;QACT,IAAI,EAAE,OAAO;QACb,IAAI,EAAE,eAAe;KACtB,CAAC,CAAC;IAEH,EAAE,CAAC,OAAO,CAAC;QACT,IAAI,EAAE,UAAU;QAChB,IAAI,EAAE,6CAA6C;KACpD,CAAC,CAAC;IAEH,IAAI,CAAC;QACH,MAAM,aAAa,CAAC,aAAa,CAAC,CAAC;IACrC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,EAAE,CAAC,OAAO,CAAC;YACT,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,+GAA+G;SACtH,CAAC,CAAC;QACH,EAAE,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;QAC/D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC","sourcesContent":["import type { WizardOptions } from './utils/types.js';\n\nimport { randomUUID } from 'crypto';\nimport { EventEmitter } from 'events';\nimport path from 'path';\nimport { runWizard as runWizardImpl } from './lib/wizard.js';\nimport { readEnvironment } from './utils/environment.js';\nimport ui from './utils/ui.js';\n\nEventEmitter.defaultMaxListeners = 50;\n\ntype Args = {\n debug?: boolean;\n forceInstall?: boolean;\n installDir?: string;\n default?: boolean;\n};\n\nexport async function runWizard(argv: Args) {\n const finalArgs = {\n ...argv,\n ...readEnvironment(),\n };\n\n let resolvedInstallDir: string;\n if (finalArgs.installDir) {\n if (path.isAbsolute(finalArgs.installDir)) {\n resolvedInstallDir = finalArgs.installDir;\n } else {\n resolvedInstallDir = path.join(process.cwd(), finalArgs.installDir);\n }\n } else {\n resolvedInstallDir = process.cwd();\n }\n\n const wizardOptions: WizardOptions = {\n debug: finalArgs.debug ?? false,\n forceInstall: finalArgs.forceInstall ?? false,\n installDir: resolvedInstallDir,\n default: finalArgs.default ?? false,\n sessionId: randomUUID(),\n compiledSetup: '', // Not used in unified wizard\n };\n\n ui.addItem({\n type: 'phase',\n text: '─── Setup ───',\n });\n\n ui.addItem({\n type: 'response',\n text: `Let's get Raindrop set up for your project.`,\n });\n\n try {\n await runWizardImpl(wizardOptions);\n } catch (error) {\n ui.addItem({\n type: 'error',\n text: `Something went wrong. You can read the documentation at https://raindrop.ai/docs to set up Raindrop manually.`,\n });\n ui.addItem({ type: 'error', text: `error: ${String(error)}` });\n process.exit(1);\n }\n}\n"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Main unified Ink app component.
|
|
3
|
+
* Uses the Static + pending items pattern for efficient rendering.
|
|
4
|
+
*
|
|
5
|
+
* Architecture:
|
|
6
|
+
* - <Static> renders completed history items once and "freezes" them
|
|
7
|
+
* - activeSpinner renders above the pending item when agent is working
|
|
8
|
+
* - pendingItem re-renders frequently during active prompts
|
|
9
|
+
*/
|
|
10
|
+
import React from 'react';
|
|
11
|
+
/**
|
|
12
|
+
* Main wizard app component
|
|
13
|
+
*/
|
|
14
|
+
export declare function WizardApp(): React.ReactElement;
|
|
15
|
+
export default WizardApp;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Main unified Ink app component.
|
|
4
|
+
* Uses the Static + pending items pattern for efficient rendering.
|
|
5
|
+
*
|
|
6
|
+
* Architecture:
|
|
7
|
+
* - <Static> renders completed history items once and "freezes" them
|
|
8
|
+
* - activeSpinner renders above the pending item when agent is working
|
|
9
|
+
* - pendingItem re-renders frequently during active prompts
|
|
10
|
+
*/
|
|
11
|
+
import { useMemo } from 'react';
|
|
12
|
+
import { Box, Static, Text } from 'ink';
|
|
13
|
+
import InkSpinner from 'ink-spinner';
|
|
14
|
+
import { useWizardState } from './contexts/WizardContext.js';
|
|
15
|
+
import { HistoryItemDisplay } from './components/HistoryItemDisplay.js';
|
|
16
|
+
import { PendingPrompt } from './components/PendingPrompt.js';
|
|
17
|
+
/**
|
|
18
|
+
* Main wizard app component
|
|
19
|
+
*/
|
|
20
|
+
export function WizardApp() {
|
|
21
|
+
const { history, pendingItem, activeSpinner } = useWizardState();
|
|
22
|
+
// Memoize history items to prevent unnecessary re-renders
|
|
23
|
+
const historyItems = useMemo(() => history.map((item) => (_jsx(Box, { marginBottom: 1, children: _jsx(HistoryItemDisplay, { item: item }) }, item.id))), [history]);
|
|
24
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Static, { items: historyItems, children: (item) => item }), activeSpinner && (_jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { color: "cyan", children: _jsx(InkSpinner, { type: "dots" }) }), _jsxs(Text, { children: [" ", activeSpinner] })] })), pendingItem && _jsx(PendingPrompt, { item: pendingItem }, pendingItem.type)] }));
|
|
25
|
+
}
|
|
26
|
+
export default WizardApp;
|
|
27
|
+
//# sourceMappingURL=App.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"App.js","sourceRoot":"","sources":["../../../src/ui/App.tsx"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;AAEH,OAAc,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AACxC,OAAO,UAAU,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AACxE,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAG9D;;GAEG;AACH,MAAM,UAAU,SAAS;IACvB,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,GAAG,cAAc,EAAE,CAAC;IAEjE,0DAA0D;IAC1D,MAAM,YAAY,GAAG,OAAO,CAC1B,GAAG,EAAE,CACH,OAAO,CAAC,GAAG,CAAC,CAAC,IAAiB,EAAE,EAAE,CAAC,CACjC,KAAC,GAAG,IAAe,YAAY,EAAE,CAAC,YAChC,KAAC,kBAAkB,IAAC,IAAI,EAAE,IAAI,GAAI,IAD1B,IAAI,CAAC,EAAE,CAEX,CACP,CAAC,EACJ,CAAC,OAAO,CAAC,CACV,CAAC;IAEF,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,aAEzB,KAAC,MAAM,IAAC,KAAK,EAAE,YAAY,YAAG,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,GAAU,EAGrD,aAAa,IAAI,CAChB,MAAC,GAAG,IAAC,YAAY,EAAE,CAAC,aAClB,KAAC,IAAI,IAAC,KAAK,EAAC,MAAM,YAChB,KAAC,UAAU,IAAC,IAAI,EAAC,MAAM,GAAG,GACrB,EACP,MAAC,IAAI,oBAAG,aAAa,IAAQ,IACzB,CACP,EAGA,WAAW,IAAI,KAAC,aAAa,IAAwB,IAAI,EAAE,WAAW,IAAnC,WAAW,CAAC,IAAI,CAAuB,IACvE,CACP,CAAC;AACJ,CAAC;AAED,eAAe,SAAS,CAAC","sourcesContent":["/**\n * Main unified Ink app component.\n * Uses the Static + pending items pattern for efficient rendering.\n *\n * Architecture:\n * - <Static> renders completed history items once and \"freezes\" them\n * - activeSpinner renders above the pending item when agent is working\n * - pendingItem re-renders frequently during active prompts\n */\n\nimport React, { useMemo } from 'react';\nimport { Box, Static, Text } from 'ink';\nimport InkSpinner from 'ink-spinner';\nimport { useWizardState } from './contexts/WizardContext.js';\nimport { HistoryItemDisplay } from './components/HistoryItemDisplay.js';\nimport { PendingPrompt } from './components/PendingPrompt.js';\nimport type { HistoryItem } from './contexts/WizardContext.js';\n\n/**\n * Main wizard app component\n */\nexport function WizardApp(): React.ReactElement {\n const { history, pendingItem, activeSpinner } = useWizardState();\n\n // Memoize history items to prevent unnecessary re-renders\n const historyItems = useMemo(\n () =>\n history.map((item: HistoryItem) => (\n <Box key={item.id} marginBottom={1}>\n <HistoryItemDisplay item={item} />\n </Box>\n )),\n [history],\n );\n\n return (\n <Box flexDirection=\"column\">\n {/* Static section: completed items rendered once */}\n <Static items={historyItems}>{(item) => item}</Static>\n\n {/* Spinner: shown above pending item when active */}\n {activeSpinner && (\n <Box marginBottom={1}>\n <Text color=\"cyan\">\n <InkSpinner type=\"dots\" />\n </Text>\n <Text> {activeSpinner}</Text>\n </Box>\n )}\n\n {/* Pending section: actively updating content */}\n {pendingItem && <PendingPrompt key={pendingItem.type} item={pendingItem} />}\n </Box>\n );\n}\n\nexport default WizardApp;\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cancellation utilities without ink dependency
|
|
3
|
+
* Can be imported synchronously in CommonJS context
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Symbol returned when user cancels an operation (Ctrl+C)
|
|
7
|
+
* Compatible with clack's cancellation symbol
|
|
8
|
+
*/
|
|
9
|
+
export declare const CANCEL_SYMBOL: unique symbol;
|
|
10
|
+
/**
|
|
11
|
+
* Type guard to check if a value is the cancellation symbol
|
|
12
|
+
* Maintains API compatibility with clack.isCancel()
|
|
13
|
+
*/
|
|
14
|
+
export declare function isCancel(value: unknown): value is symbol;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cancellation utilities without ink dependency
|
|
3
|
+
* Can be imported synchronously in CommonJS context
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Symbol returned when user cancels an operation (Ctrl+C)
|
|
7
|
+
* Compatible with clack's cancellation symbol
|
|
8
|
+
*/
|
|
9
|
+
export const CANCEL_SYMBOL = Symbol('ink:cancel');
|
|
10
|
+
/**
|
|
11
|
+
* Type guard to check if a value is the cancellation symbol
|
|
12
|
+
* Maintains API compatibility with clack.isCancel()
|
|
13
|
+
*/
|
|
14
|
+
export function isCancel(value) {
|
|
15
|
+
return value === CANCEL_SYMBOL;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=cancellation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cancellation.js","sourceRoot":"","sources":["../../../src/ui/cancellation.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC;AAElD;;;GAGG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAc;IACrC,OAAO,KAAK,KAAK,aAAa,CAAC;AACjC,CAAC","sourcesContent":["/**\n * Cancellation utilities without ink dependency\n * Can be imported synchronously in CommonJS context\n */\n\n/**\n * Symbol returned when user cancels an operation (Ctrl+C)\n * Compatible with clack's cancellation symbol\n */\nexport const CANCEL_SYMBOL = Symbol('ink:cancel');\n\n/**\n * Type guard to check if a value is the cancellation symbol\n * Maintains API compatibility with clack.isCancel()\n */\nexport function isCancel(value: unknown): value is symbol {\n return value === CANCEL_SYMBOL;\n}\n"]}
|