@raindrop-ai/wizard 0.0.1 → 0.0.2

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 (71) hide show
  1. package/dist/src/docs/claude-agent-sdk.mdx +382 -0
  2. package/dist/src/docs/{typescript.md → typescript.mdx} +8 -4
  3. package/dist/src/docs/vercel-ai-sdk.mdx +769 -0
  4. package/dist/src/lib/agent-interface.d.ts +4 -3
  5. package/dist/src/lib/agent-interface.js +290 -197
  6. package/dist/src/lib/agent-interface.js.map +1 -1
  7. package/dist/src/lib/constants.d.ts +1 -0
  8. package/dist/src/lib/constants.js +1 -0
  9. package/dist/src/lib/constants.js.map +1 -1
  10. package/dist/src/lib/handlers.d.ts +16 -8
  11. package/dist/src/lib/handlers.js +232 -118
  12. package/dist/src/lib/handlers.js.map +1 -1
  13. package/dist/src/lib/integration-testing.d.ts +5 -5
  14. package/dist/src/lib/integration-testing.js +28 -12
  15. package/dist/src/lib/integration-testing.js.map +1 -1
  16. package/dist/src/lib/mcp.d.ts +1 -1
  17. package/dist/src/lib/mcp.js +88 -49
  18. package/dist/src/lib/mcp.js.map +1 -1
  19. package/dist/src/lib/sdk-messages.d.ts +8 -1
  20. package/dist/src/lib/sdk-messages.js +83 -27
  21. package/dist/src/lib/sdk-messages.js.map +1 -1
  22. package/dist/src/lib/wizard.js +16 -20
  23. package/dist/src/lib/wizard.js.map +1 -1
  24. package/dist/src/ui/App.d.ts +5 -4
  25. package/dist/src/ui/App.js +12 -12
  26. package/dist/src/ui/App.js.map +1 -1
  27. package/dist/src/ui/components/ClarifyingQuestionsPrompt.js +4 -2
  28. package/dist/src/ui/components/ClarifyingQuestionsPrompt.js.map +1 -1
  29. package/dist/src/ui/components/ContinuePrompt.d.ts +3 -2
  30. package/dist/src/ui/components/ContinuePrompt.js +4 -4
  31. package/dist/src/ui/components/ContinuePrompt.js.map +1 -1
  32. package/dist/src/ui/components/DiffDisplay.js +16 -6
  33. package/dist/src/ui/components/DiffDisplay.js.map +1 -1
  34. package/dist/src/ui/components/FeedbackSelectPrompt.js +6 -3
  35. package/dist/src/ui/components/FeedbackSelectPrompt.js.map +1 -1
  36. package/dist/src/ui/components/HistoryItemDisplay.d.ts +5 -3
  37. package/dist/src/ui/components/HistoryItemDisplay.js +10 -9
  38. package/dist/src/ui/components/HistoryItemDisplay.js.map +1 -1
  39. package/dist/src/ui/components/Logo.js +19 -34
  40. package/dist/src/ui/components/Logo.js.map +1 -1
  41. package/dist/src/ui/components/OrgInfoBox.d.ts +2 -1
  42. package/dist/src/ui/components/OrgInfoBox.js +2 -4
  43. package/dist/src/ui/components/OrgInfoBox.js.map +1 -1
  44. package/dist/src/ui/components/PersistentTextInput.js +13 -11
  45. package/dist/src/ui/components/PersistentTextInput.js.map +1 -1
  46. package/dist/src/ui/components/PromptContainer.js +4 -8
  47. package/dist/src/ui/components/PromptContainer.js.map +1 -1
  48. package/dist/src/ui/components/ToolApprovalPrompt.js +4 -4
  49. package/dist/src/ui/components/ToolApprovalPrompt.js.map +1 -1
  50. package/dist/src/ui/components/WriteKeyDisplay.d.ts +1 -1
  51. package/dist/src/ui/components/WriteKeyDisplay.js +1 -1
  52. package/dist/src/ui/components/WriteKeyDisplay.js.map +1 -1
  53. package/dist/src/ui/contexts/WizardContext.d.ts +13 -5
  54. package/dist/src/ui/contexts/WizardContext.js +60 -20
  55. package/dist/src/ui/contexts/WizardContext.js.map +1 -1
  56. package/dist/src/ui/render.js +49 -5
  57. package/dist/src/ui/render.js.map +1 -1
  58. package/dist/src/ui/types.d.ts +4 -2
  59. package/dist/src/ui/types.js.map +1 -1
  60. package/dist/src/utils/oauth.js +0 -4
  61. package/dist/src/utils/oauth.js.map +1 -1
  62. package/dist/src/utils/session.d.ts +1 -0
  63. package/dist/src/utils/session.js +40 -1
  64. package/dist/src/utils/session.js.map +1 -1
  65. package/dist/src/utils/ui.d.ts +7 -2
  66. package/dist/src/utils/ui.js +9 -2
  67. package/dist/src/utils/ui.js.map +1 -1
  68. package/package.json +2 -1
  69. package/dist/src/docs/vercel-ai-sdk.md +0 -304
  70. /package/dist/src/docs/{browser.md → browser.mdx} +0 -0
  71. /package/dist/src/docs/{python.md → python.mdx} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"handlers.js","sourceRoot":"","sources":["../../../src/lib/handlers.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Tool approval handlers for the Claude agent\n * Handles UI integration for tool approvals and clarifying questions\n */\n\nimport ui from '../utils/ui.js';\nimport type { ToolApprovalResult, AgentQueryHandle } from '../ui/types.js';\nimport { logToFile } from '../utils/debug.js';\nimport { createTwoFilesPatch } from 'diff';\nimport { SAFE_BASH_PATTERNS } from './constants.js';\nimport { sendSessionUpdate } from '../utils/session.js';\n\n// ============================================================================\n// Session-wide Approval Tracking\n// ============================================================================\n\n/**\n * Set of file paths that have been granted blanket approval for the session.\n * When a file is in this set, Edit/Write operations on it are auto-approved.\n */\nconst approvedFilesForSession = new Set<string>();\n\n/**\n * Set of command patterns that have been granted blanket approval for the session.\n * When a command matches a pattern in this set, Bash operations are auto-approved.\n * Patterns use simple prefix matching (e.g., \"npm install\" matches \"npm install axios\").\n */\nconst approvedCommandPatternsForSession = new Set<string>();\n\n/**\n * Clear all session-wide file approvals.\n * Useful when starting a new session or resetting permissions.\n */\nexport function clearApprovedFiles(): void {\n approvedFilesForSession.clear();\n logToFile('Cleared all approved files for session');\n}\n\n/**\n * Clear all session-wide command pattern approvals.\n * Useful when starting a new session or resetting permissions.\n */\nexport function clearApprovedCommandPatterns(): void {\n approvedCommandPatternsForSession.clear();\n logToFile('Cleared all approved command patterns for session');\n}\n\n/**\n * Get the list of currently approved files (for debugging/display purposes)\n */\nexport function getApprovedFiles(): string[] {\n return Array.from(approvedFilesForSession);\n}\n\n/**\n * Get the list of currently approved command patterns (for debugging/display purposes)\n */\nexport function getApprovedCommandPatterns(): string[] {\n return Array.from(approvedCommandPatternsForSession);\n}\n\n/**\n * Extract the command pattern from a bash command for session approval.\n * Returns the base command with the first argument(s) to match similar commands.\n * Examples:\n * \"npm install axios\" -> \"npm install\"\n * \"npm run build\" -> \"npm run\"\n * \"pip install requests\" -> \"pip install\"\n * \"yarn add lodash\" -> \"yarn add\"\n */\nfunction extractCommandPattern(command: string): string {\n const trimmed = command.trim();\n const parts = trimmed.split(/\\s+/);\n\n // For package managers with subcommands, include the subcommand\n if (parts.length >= 2) {\n const [cmd, subcmd] = parts;\n // Common package managers\n if (\n ['npm', 'yarn', 'bun', 'pip', 'pip3', 'poetry', 'cargo', 'go'].includes(cmd)\n ) {\n return `${cmd} ${subcmd}`;\n }\n }\n\n // For other commands, just return the first part\n return parts[0] || trimmed;\n}\n\n/**\n * Check if a bash command matches any approved command pattern for the session.\n */\nfunction isCommandApprovedForSession(command: string): boolean {\n const pattern = extractCommandPattern(command);\n return approvedCommandPatternsForSession.has(pattern);\n}\n\n// ============================================================================\n// Pending Tool Call Types\n// ============================================================================\n\n/**\n * Pending tool call info stored while waiting for result\n */\nexport interface PendingToolCall {\n toolName: string;\n input: Record<string, unknown>;\n description?: string;\n}\n\n// ============================================================================\n// Agent Query Handle Factory\n// ============================================================================\n\n/**\n * Dependencies required for creating an AgentQueryHandle\n */\nexport interface AgentQueryHandleDeps {\n isInterruptingRef: { value: boolean };\n waitingForUserInputRef: { value: boolean };\n pendingToolCalls: Map<string, PendingToolCall>;\n getQueryObject: () => { interrupt?: () => Promise<void> } | null;\n}\n\n/**\n * Create an AgentQueryHandle for external control of the agent.\n * Handles interrupts by marking pending tool calls (keeps persistent input running).\n */\nexport function createAgentQueryHandle(\n deps: AgentQueryHandleDeps,\n): AgentQueryHandle {\n const {\n isInterruptingRef,\n waitingForUserInputRef,\n pendingToolCalls,\n getQueryObject,\n } = deps;\n\n return {\n interrupt: async () => {\n logToFile('Soft interrupt requested (Esc)');\n\n // If already interrupted, don't add another \"Interrupted\" item\n if (isInterruptingRef.value || waitingForUserInputRef.value) {\n logToFile('Already interrupted - ignoring duplicate interrupt request');\n return;\n }\n\n isInterruptingRef.value = true;\n waitingForUserInputRef.value = true;\n\n // Mark all pending tool calls as interrupted and show them in history\n if (pendingToolCalls.size > 0) {\n for (const [toolUseId, pendingCall] of pendingToolCalls) {\n ui.addItem({\n type: 'tool-call',\n text: pendingCall.toolName,\n toolCall: {\n toolName: pendingCall.toolName,\n status: 'interrupted',\n input: pendingCall.input,\n description: pendingCall.description,\n },\n });\n pendingToolCalls.delete(toolUseId);\n }\n } else {\n // Only show generic \"Interrupted\" if no pending tool calls to display\n ui.addItem({\n type: 'error',\n text: 'Interrupted',\n });\n }\n\n // Note: Don't stop persistent input here - keep it visible for user to type their message\n // The spinner will be stopped separately, and the input remains for user to submit\n\n // Call SDK interrupt\n const queryObject = getQueryObject();\n if (queryObject?.interrupt) {\n logToFile('Calling queryObject.interrupt()');\n await queryObject.interrupt();\n logToFile('queryObject.interrupt() completed');\n } else {\n logToFile('No queryObject.interrupt available');\n }\n },\n sendMessage: () => {\n // No-op: use interrupt + resume pattern instead of streaming messages\n logToFile(\n 'sendMessage called but not supported - use interrupt and resume',\n );\n },\n };\n}\n\n// ============================================================================\n// Enhanced canUseTool Handler with UI Integration\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 // createTwoFilesPatch generates a unified diff\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 * Handle tool approval request by showing approval UI\n */\nasync function handleToolApproval(\n toolName: string,\n input: Record<string, unknown>,\n approvedFilesCache?: Set<string>,\n): Promise<ToolApprovalResult> {\n logToFile('Showing tool approval UI:', { toolName, input });\n\n // Extract file path\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 // Check if this file has been approved for all edits\n if (\n approvedFilesCache &&\n fileName &&\n (toolName === 'Edit' || toolName === 'Write') &&\n approvedFilesCache.has(fileName)\n ) {\n logToFile('Auto-approving edit to previously approved file:', fileName);\n return {\n behavior: 'allow',\n updatedInput: input,\n };\n }\n\n // Stop spinner while waiting for user approval\n const spinner = ui.spinner();\n spinner.stop();\n\n // Generate diff content for file modification tools\n let diffContent: string | undefined;\n if (\n toolName === 'Edit' &&\n typeof input.old_string === 'string' &&\n typeof input.new_string === 'string' &&\n fileName\n ) {\n // Edit: show old -> new diff\n diffContent = generateEditDiff(\n fileName,\n input.old_string,\n input.new_string,\n );\n } else if (\n toolName === 'Write' &&\n typeof input.content === 'string' &&\n fileName\n ) {\n // Write: show content as all additions (empty -> content)\n diffContent = generateEditDiff(fileName, '', input.content);\n } else if (typeof input.file_diff === 'string') {\n // Use pre-generated diff if available\n diffContent = input.file_diff;\n }\n\n // Build props for the approval prompt\n const props = {\n toolName,\n input,\n description:\n typeof input.description === 'string' ? input.description : undefined,\n diffContent,\n fileName,\n };\n\n try {\n const result = await ui.toolApproval(props);\n logToFile('Tool approval result:', result);\n\n // If user chose \"allow all edits to this file\", add to both caches\n if (result.behavior === 'allow' && 'allowAllForFile' in result && result.allowAllForFile) {\n approvedFilesForSession.add(result.allowAllForFile);\n logToFile('Added file to approved list:', result.allowAllForFile);\n }\n if (\n result.behavior === 'allow' &&\n result.allowAllEdits &&\n fileName &&\n approvedFilesCache\n ) {\n logToFile('Adding file to approved files cache:', fileName);\n approvedFilesCache.add(fileName);\n }\n\n // If user selected \"allow all for this command pattern\", add to approved set\n if (\n result.behavior === 'allow' &&\n 'allowAllForCommandPattern' in result &&\n result.allowAllForCommandPattern\n ) {\n approvedCommandPatternsForSession.add(result.allowAllForCommandPattern);\n logToFile('Added command pattern to approved list:', result.allowAllForCommandPattern);\n }\n\n // Restart spinner after user responds\n spinner.start();\n\n return result;\n } catch (error) {\n logToFile('Error in tool approval:', error);\n return {\n behavior: 'deny',\n message: 'Failed to get user approval',\n };\n }\n}\n\n/**\n * Handle the AskUserQuestion tool by showing clarifying questions UI.\n * Input already contains { questions: [...] } in the correct format.\n * Returns { questions, answers } as expected by the SDK.\n */\nasync function handleClarifyingQuestions(\n input: Record<string, unknown>,\n): Promise<ToolApprovalResult> {\n logToFile('Handling AskUserQuestion:', input);\n\n // Stop spinner while waiting for user input\n const spinner = ui.spinner();\n spinner.stop();\n\n try {\n // Input is already in ClarifyingQuestionsProps format\n const result = await ui.clarifyingQuestions(input as any);\n logToFile('Clarifying questions result:', result);\n\n // Restart spinner after user responds\n spinner.start();\n\n // Return questions + answers as expected by SDK\n return {\n behavior: 'allow',\n updatedInput: {\n questions: result.questions,\n answers: result.answers,\n },\n };\n } catch (error) {\n logToFile('Error in clarifying questions:', error);\n return {\n behavior: 'deny',\n message: 'Failed to get user answers',\n };\n }\n}\n\n/**\n * Session info for notifications\n */\nexport interface SessionInfo {\n sessionId: string;\n accessToken: string;\n orgId: string;\n}\n\n/**\n * Handle the ExitPlanMode tool by showing plan approval UI.\n * Input contains { plan: \"...\" } with the plan in markdown format.\n * If user approves, returns allow. If user rejects, returns deny with feedback.\n */\nasync function handlePlanApproval(\n input: Record<string, unknown>,\n sessionInfo?: SessionInfo,\n): Promise<ToolApprovalResult> {\n logToFile('Handling ExitPlanMode:', input);\n\n const planContent = typeof input.plan === 'string' ? input.plan : '';\n\n // Stop spinner while waiting for user approval\n const spinner = ui.spinner();\n spinner.stop();\n\n try {\n const result = await ui.planApproval({ planContent });\n logToFile('Plan approval result:', result);\n\n // Restart spinner after user responds\n spinner.start();\n\n if (result.approved) {\n // Send session update with approved plan\n if (sessionInfo) {\n sendSessionUpdate(\n sessionInfo.sessionId,\n planContent,\n sessionInfo.accessToken,\n sessionInfo.orgId,\n );\n }\n\n // User approved the plan - allow the tool\n return {\n behavior: 'allow',\n updatedInput: input,\n };\n } else {\n // User rejected with feedback - deny the tool\n return {\n behavior: 'deny',\n message: result.feedback || 'User rejected plan',\n };\n }\n } catch (error) {\n logToFile('Error in plan approval:', error);\n return {\n behavior: 'deny',\n message: 'Failed to get user response',\n };\n }\n}\n\n/**\n * Tools that are automatically approved without user confirmation\n */\nconst AUTO_APPROVED_TOOLS = new Set([\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]);\n\n/**\n * Check if a bash command matches a safe pattern and can be auto-approved.\n */\nfunction isSafeBashCommand(command: string): boolean {\n const trimmed = command.trim();\n return SAFE_BASH_PATTERNS.some((pattern) => {\n if (pattern.startsWith('*')) {\n // Suffix match (e.g., '*--version')\n return trimmed.endsWith(pattern.slice(1));\n } else if (pattern.endsWith('*')) {\n // Prefix match (e.g., 'npm install*')\n return trimmed.startsWith(pattern.slice(0, -1));\n } else {\n // Exact match\n return trimmed === pattern;\n }\n });\n}\n\n/**\n * Create a canUseTool handler that integrates with the UI for approvals.\n * - Handles AskUserQuestion by showing clarifying questions UI\n * - Handles ExitPlanMode by showing plan approval UI\n * - Handles WebSearch by restricting to allowed domains\n * - Shows approval UI for other tools\n * - Supports caching file approvals for \"allow all edits to this file\"\n */\nexport function createCanUseToolHandler(\n sessionInfo?: SessionInfo,\n approvedFilesCache?: Set<string>,\n) {\n return async (\n toolName: string,\n input: unknown,\n ): Promise<ToolApprovalResult> => {\n const inputRecord = input as Record<string, unknown>;\n logToFile('canUseTool called:', { toolName, input: inputRecord });\n\n if (AUTO_APPROVED_TOOLS.has(toolName)) {\n return {\n behavior: 'allow',\n updatedInput: inputRecord,\n };\n }\n\n // Auto-approve safe bash commands\n if (toolName === 'Bash' && typeof inputRecord.command === 'string') {\n // Check if command matches safe patterns\n if (isSafeBashCommand(inputRecord.command)) {\n logToFile('Auto-approving safe bash command:', inputRecord.command);\n return {\n behavior: 'allow',\n updatedInput: inputRecord,\n };\n }\n\n // Check if command pattern has been approved for the session\n if (isCommandApprovedForSession(inputRecord.command)) {\n logToFile(\n 'Auto-approving bash command based on session approval:',\n inputRecord.command,\n );\n return {\n behavior: 'allow',\n updatedInput: inputRecord,\n };\n }\n }\n\n // Handle WebSearch by adding allowed domains restriction\n if (toolName === 'WebSearch') {\n return {\n behavior: 'allow',\n updatedInput: {\n ...inputRecord,\n allowed_domains: ['raindrop.ai/docs', 'ai-sdk.dev/docs/'],\n },\n };\n }\n\n // Handle AskUserQuestion specially\n if (toolName === 'AskUserQuestion') {\n return handleClarifyingQuestions(inputRecord);\n }\n\n // Handle ExitPlanMode specially\n if (toolName === 'ExitPlanMode') {\n return handlePlanApproval(inputRecord, sessionInfo);\n }\n\n // Check if file has been granted blanket approval for this session\n if (toolName === 'Edit' || toolName === 'Write') {\n const fileName =\n typeof inputRecord.file_path === 'string'\n ? inputRecord.file_path\n : typeof inputRecord.path === 'string'\n ? inputRecord.path\n : undefined;\n\n if (fileName && approvedFilesForSession.has(fileName)) {\n logToFile('Auto-approving edit to previously approved file:', fileName);\n return {\n behavior: 'allow',\n updatedInput: inputRecord,\n };\n }\n }\n\n // Show approval UI for other tools\n return handleToolApproval(toolName, inputRecord, approvedFilesCache);\n };\n}\n"]}
1
+ {"version":3,"file":"handlers.js","sourceRoot":"","sources":["../../../src/lib/handlers.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Tool approval handlers for the Claude agent\n * Handles UI integration for tool approvals and clarifying questions\n */\n\nimport type { HookInput, HookJSONOutput } from '@anthropic-ai/claude-agent-sdk';\nimport { createTwoFilesPatch } from 'diff';\nimport type { AgentQueryHandle, ToolApprovalResult } from '../ui/types.js';\nimport { logToFile } from '../utils/debug.js';\nimport { sendSessionUpdate } from '../utils/session.js';\nimport ui from '../utils/ui.js';\nimport { SAFE_BASH_PATTERNS } from './constants.js';\n\n// ============================================================================\n// Session-wide Approval Tracking\n// ============================================================================\n\n/**\n * Set of file paths that have been granted blanket approval for the session.\n * When a file is in this set, Edit/Write operations on it are auto-approved.\n */\nconst approvedFilesForSession = new Set<string>();\n\n/**\n * Set of command patterns that have been granted blanket approval for the session.\n * When a command matches a pattern in this set, Bash operations are auto-approved.\n * Patterns use simple prefix matching (e.g., \"npm install\" matches \"npm install axios\").\n */\nconst approvedCommandPatternsForSession = new Set<string>();\n\n/**\n * Clear all session-wide file approvals.\n * Useful when starting a new session or resetting permissions.\n */\nexport function clearApprovedFiles(): void {\n approvedFilesForSession.clear();\n logToFile('Cleared all approved files for session');\n}\n\n/**\n * Clear all session-wide command pattern approvals.\n * Useful when starting a new session or resetting permissions.\n */\nexport function clearApprovedCommandPatterns(): void {\n approvedCommandPatternsForSession.clear();\n logToFile('Cleared all approved command patterns for session');\n}\n\n/**\n * Get the list of currently approved files (for debugging/display purposes)\n */\nexport function getApprovedFiles(): string[] {\n return Array.from(approvedFilesForSession);\n}\n\n/**\n * Get the list of currently approved command patterns (for debugging/display purposes)\n */\nexport function getApprovedCommandPatterns(): string[] {\n return Array.from(approvedCommandPatternsForSession);\n}\n\n/**\n * Extract the command pattern from a bash command for session approval.\n * Returns the base command with the first argument(s) to match similar commands.\n * Examples:\n * \"npm install axios\" -> \"npm install\"\n * \"npm run build\" -> \"npm run\"\n * \"pip install requests\" -> \"pip install\"\n * \"yarn add lodash\" -> \"yarn add\"\n */\nfunction extractCommandPattern(command: string): string {\n const trimmed = command.trim();\n const parts = trimmed.split(/\\s+/);\n\n // For package managers with subcommands, include the subcommand\n if (parts.length >= 2) {\n const [cmd, subcmd] = parts;\n // Common package managers\n if (\n ['npm', 'yarn', 'bun', 'pip', 'pip3', 'poetry', 'cargo', 'go'].includes(\n cmd,\n )\n ) {\n return `${cmd} ${subcmd}`;\n }\n }\n\n // For other commands, just return the first part\n return parts[0] || trimmed;\n}\n\n/**\n * Check if a bash command matches any approved command pattern for the session.\n */\nfunction isCommandApprovedForSession(command: string): boolean {\n const pattern = extractCommandPattern(command);\n return approvedCommandPatternsForSession.has(pattern);\n}\n\n// ============================================================================\n// Pending Tool Call Types\n// ============================================================================\n\n/**\n * Pending tool call info stored while waiting for result\n */\nexport interface PendingToolCall {\n toolName: string;\n input: Record<string, unknown>;\n description?: string;\n /** ID of the 'executing' history item, used to update it on completion/interrupt */\n historyItemId?: number;\n}\n\n// ============================================================================\n// Agent Query Handle Factory\n// ============================================================================\n\n/**\n * Dependencies required for creating an AgentQueryHandle\n */\nexport interface AgentQueryHandleDeps {\n isInterruptingRef: { value: boolean };\n waitingForUserInputRef: { value: boolean };\n pendingToolCalls: Map<string, PendingToolCall>;\n getQueryObject: () => { interrupt?: () => Promise<void> } | null;\n sendMessage: (message: string) => void;\n}\n\n/**\n * Create an AgentQueryHandle for external control of the agent.\n * Handles interrupts by marking pending tool calls (keeps persistent input running).\n */\nexport function createAgentQueryHandle(\n deps: AgentQueryHandleDeps,\n): AgentQueryHandle {\n const {\n isInterruptingRef,\n waitingForUserInputRef,\n pendingToolCalls,\n getQueryObject,\n sendMessage,\n } = deps;\n\n return {\n interrupt: async (fromUserMessage?: boolean) => {\n logToFile('Soft interrupt requested (Esc)');\n\n // If already interrupted, don't add another \"Interrupted\" item\n if (isInterruptingRef.value || waitingForUserInputRef.value) {\n logToFile('Already interrupted - ignoring duplicate interrupt request');\n return;\n }\n\n isInterruptingRef.value = true;\n waitingForUserInputRef.value = true;\n\n // Mark all pending tool calls as interrupted and show them in history\n if (pendingToolCalls.size > 0) {\n for (const [toolUseId, pendingCall] of pendingToolCalls) {\n const interruptedToolCall = {\n toolName: pendingCall.toolName,\n status: 'interrupted' as const,\n input: pendingCall.input,\n description: pendingCall.description,\n };\n if (pendingCall.historyItemId !== undefined) {\n ui.updateItem(pendingCall.historyItemId, {\n type: 'tool-call',\n text: pendingCall.toolName,\n toolCall: interruptedToolCall,\n });\n } else {\n ui.addItem({\n type: 'tool-call',\n text: pendingCall.toolName,\n toolCall: interruptedToolCall,\n });\n }\n pendingToolCalls.delete(toolUseId);\n }\n } else if (!fromUserMessage) {\n // No pending tool calls and not interrupted by a user message - show generic indicator\n ui.addItem({\n type: 'error',\n text: 'Interrupted',\n });\n }\n\n // Note: Don't stop persistent input here - keep it visible for user to type their message\n // The spinner will be stopped separately, and the input remains for user to submit\n\n // Call SDK interrupt\n const queryObject = getQueryObject();\n if (queryObject?.interrupt) {\n logToFile('Calling queryObject.interrupt()');\n await queryObject.interrupt();\n logToFile('queryObject.interrupt() completed');\n } else {\n logToFile('No queryObject.interrupt available');\n }\n },\n sendMessage: (message: string) => {\n const trimmedMessage = message.trim();\n if (!trimmedMessage) {\n return;\n }\n logToFile('Queueing user message for active session');\n sendMessage(trimmedMessage);\n },\n };\n}\n\n// ============================================================================\n// Enhanced canUseTool Handler with UI Integration\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 // createTwoFilesPatch generates a unified diff\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 * Handle tool approval request by showing approval UI\n */\nasync function handleToolApproval(\n toolName: string,\n input: Record<string, unknown>,\n approvedFilesCache?: Set<string>,\n): Promise<ToolApprovalResult> {\n logToFile('Showing tool approval UI:', { toolName, input });\n\n // Extract file path\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 // Check if this file has been approved for all edits\n if (\n approvedFilesCache &&\n fileName &&\n (toolName === 'Edit' || toolName === 'Write') &&\n approvedFilesCache.has(fileName)\n ) {\n logToFile('Auto-approving edit to previously approved file:', fileName);\n return {\n behavior: 'allow',\n updatedInput: input,\n };\n }\n\n // Stop spinner while waiting for user approval\n const spinner = ui.spinner();\n spinner.stop();\n\n // Generate diff content for file modification tools\n let diffContent: string | undefined;\n if (\n toolName === 'Edit' &&\n typeof input.old_string === 'string' &&\n typeof input.new_string === 'string' &&\n fileName\n ) {\n // Edit: show old -> new diff\n diffContent = generateEditDiff(\n fileName,\n input.old_string,\n input.new_string,\n );\n } else if (\n toolName === 'Write' &&\n typeof input.content === 'string' &&\n fileName\n ) {\n // Write: show content as all additions (empty -> content)\n diffContent = generateEditDiff(fileName, '', input.content);\n } else if (typeof input.file_diff === 'string') {\n // Use pre-generated diff if available\n diffContent = input.file_diff;\n }\n\n // Build props for the approval prompt\n const props = {\n toolName,\n input,\n description:\n typeof input.description === 'string' ? input.description : undefined,\n diffContent,\n fileName,\n };\n\n try {\n const result = await ui.toolApproval(props);\n logToFile('Tool approval result:', result);\n\n // If user chose \"allow all edits to this file\", add to both caches\n if (\n result.behavior === 'allow' &&\n 'allowAllForFile' in result &&\n result.allowAllForFile\n ) {\n approvedFilesForSession.add(result.allowAllForFile);\n logToFile('Added file to approved list:', result.allowAllForFile);\n }\n if (\n result.behavior === 'allow' &&\n result.allowAllEdits &&\n fileName &&\n approvedFilesCache\n ) {\n logToFile('Adding file to approved files cache:', fileName);\n approvedFilesCache.add(fileName);\n }\n\n // If user selected \"allow all for this command pattern\", add to approved set\n if (\n result.behavior === 'allow' &&\n 'allowAllForCommandPattern' in result &&\n result.allowAllForCommandPattern\n ) {\n approvedCommandPatternsForSession.add(result.allowAllForCommandPattern);\n logToFile(\n 'Added command pattern to approved list:',\n result.allowAllForCommandPattern,\n );\n }\n\n // Restart spinner after user responds\n spinner.start();\n\n return result;\n } catch (error) {\n logToFile('Error in tool approval:', error);\n return {\n behavior: 'deny',\n message: 'Failed to get user approval',\n };\n }\n}\n\n/**\n * Handle the AskUserQuestion tool by showing clarifying questions UI.\n * Input already contains { questions: [...] } in the correct format.\n * Returns { questions, answers } as expected by the SDK.\n */\nasync function handleClarifyingQuestions(\n input: Record<string, unknown>,\n): Promise<ToolApprovalResult> {\n logToFile('Handling AskUserQuestion:', input);\n\n // Stop spinner while waiting for user input\n const spinner = ui.spinner();\n spinner.stop();\n\n try {\n // Input is already in ClarifyingQuestionsProps format\n const result = await ui.clarifyingQuestions(input as any);\n logToFile('Clarifying questions result:', result);\n\n // Restart spinner after user responds\n spinner.start();\n\n // Return questions + answers as expected by SDK\n return {\n behavior: 'allow',\n updatedInput: {\n questions: result.questions,\n answers: result.answers,\n },\n };\n } catch (error) {\n logToFile('Error in clarifying questions:', error);\n return {\n behavior: 'deny',\n message: 'Failed to get user answers',\n };\n }\n}\n\n/**\n * Session info for notifications\n */\nexport interface SessionInfo {\n sessionId: string;\n accessToken: string;\n orgId: string;\n}\n\n/**\n * Handle the ExitPlanMode tool by showing plan approval UI.\n * Input contains { plan: \"...\" } with the plan in markdown format.\n * If user approves, returns allow. If user rejects, returns deny with feedback.\n */\nasync function handlePlanApproval(\n input: Record<string, unknown>,\n sessionInfo?: SessionInfo,\n): Promise<ToolApprovalResult> {\n logToFile('Handling ExitPlanMode:', input);\n\n const planContent = typeof input.plan === 'string' ? input.plan : '';\n\n // Send session update with plan content\n if (sessionInfo) {\n sendSessionUpdate(\n sessionInfo.sessionId,\n planContent,\n sessionInfo.accessToken,\n sessionInfo.orgId,\n );\n }\n\n return {\n behavior: 'allow',\n updatedInput: input,\n };\n}\n\n/**\n * Tools that are automatically approved without user confirmation\n */\nconst AUTO_APPROVED_TOOLS = new Set([\n 'mcp__raindrop-wizard__CompleteIntegration',\n 'mcp__raindrop-wizard__LoadDocumentation',\n 'mcp__raindrop-wizard__InitializeSession',\n 'EnterPlanMode',\n]);\n\n/**\n * Patterns indicating a file path or glob likely targets secret/credential files.\n * Used to auto-deny Read/Glob/Grep operations on sensitive files.\n */\nconst SECRET_PATH_PATTERNS: RegExp[] = [\n /\\.env(\\.|$)/, // .env, .env.local, .env.production, etc.\n /\\bsecrets?\\b/i, // secrets.json, secret.yaml, etc.\n /\\bcredentials?\\b/i, // credentials.json, credential.yaml\n /private[._-]?key/i, // private_key.pem, privatekey.pem\n /\\.pem$/i, // PEM certificates/keys\n /\\.key$/i, // Key files (e.g. myapp.key, certificate.key)\n /\\.p12$/i, // PKCS12 keystores\n /\\.pfx$/i, // PFX keystores\n /\\bid_rsa\\b/, // SSH private keys\n /\\bid_ed25519\\b/, // SSH private keys\n /\\bid_ecdsa\\b/, // SSH private keys\n /\\.netrc$/, // .netrc files\n /serviceaccount.*\\.json$/i, // GCP service account keys\n];\n\nconst SECRET_PATH_ALLOWLIST: RegExp[] = [\n /\\.env\\.example$/, // .env.example is safe to read\n];\n\n/**\n * Returns true if a file path or glob pattern likely targets a secrets file.\n */\nfunction isSecretPath(value: string): boolean {\n if (SECRET_PATH_ALLOWLIST.some((re) => re.test(value))) return false;\n return SECRET_PATH_PATTERNS.some((re) => re.test(value));\n}\n\n/**\n * Check if a Read/Glob/Grep input targets a secrets file and should be denied.\n * For Grep, only the file-targeting fields (path, glob) are checked — not the\n * search pattern itself.\n */\nfunction targetsSecretFile(\n toolName: string,\n input: Record<string, unknown>,\n): boolean {\n if (toolName === 'Read' || toolName === 'Edit' || toolName === 'Write') {\n const filePath = typeof input.file_path === 'string'\n ? input.file_path\n : typeof input.path === 'string'\n ? input.path\n : '';\n return isSecretPath(filePath);\n }\n if (toolName === 'NotebookEdit') {\n const notebookPath =\n typeof input.notebook_path === 'string' ? input.notebook_path : '';\n return isSecretPath(notebookPath);\n }\n if (toolName === 'Glob') {\n const pattern = typeof input.pattern === 'string' ? input.pattern : '';\n const path = typeof input.path === 'string' ? input.path : '';\n return isSecretPath(pattern) || isSecretPath(path);\n }\n if (toolName === 'Grep') {\n const path = typeof input.path === 'string' ? input.path : '';\n const glob = typeof input.glob === 'string' ? input.glob : '';\n return isSecretPath(path) || isSecretPath(glob);\n }\n return false;\n}\n\n/**\n * Returns true if a bash command string references a secret/credential file.\n * Splits on shell delimiters and checks each token against SECRET_PATH_PATTERNS.\n */\nfunction bashCommandTargetsSecretFile(command: string): boolean {\n const tokens = command.split(/[\\s|;&<>]+/);\n for (const token of tokens) {\n // Strip surrounding quotes\n const cleaned = token.replace(/^['\"]|['\"]$/g, '');\n if (cleaned && !cleaned.startsWith('-') && isSecretPath(cleaned)) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * PreToolUse hook that handles all silent auto-approve/deny decisions.\n * Fires for every tool call before canUseTool, so this is the right place\n * for decisions that don't require user interaction.\n * Returns { continue: true } for tools that need canUseTool (UI interaction).\n */\nexport function createPreToolUseHook(sessionInfo?: SessionInfo) {\n return async (input: HookInput): Promise<HookJSONOutput> => {\n if (input.hook_event_name !== 'PreToolUse') return { continue: true };\n const { tool_name, tool_input } = input;\n const inp = (tool_input ?? {}) as Record<string, unknown>;\n\n // Block secret file access for all relevant tools\n if (\n targetsSecretFile(tool_name, inp) ||\n (tool_name === 'Bash' &&\n typeof inp.command === 'string' &&\n bashCommandTargetsSecretFile(inp.command))\n ) {\n logToFile(\n `PreToolUse: blocking ${tool_name} - secret file pattern detected`,\n inp,\n );\n return {\n hookSpecificOutput: {\n hookEventName: 'PreToolUse',\n permissionDecision: 'deny',\n permissionDecisionReason:\n 'Reading or writing secret or credential files is not allowed.',\n },\n };\n }\n\n // Auto-approve internal MCP tools and EnterPlanMode\n if (AUTO_APPROVED_TOOLS.has(tool_name)) {\n return {\n hookSpecificOutput: {\n hookEventName: 'PreToolUse',\n permissionDecision: 'allow',\n },\n };\n }\n\n // Auto-approve read-only file tools\n if (tool_name === 'Read' || tool_name === 'Glob' || tool_name === 'Grep') {\n return {\n hookSpecificOutput: {\n hookEventName: 'PreToolUse',\n permissionDecision: 'allow',\n },\n };\n }\n\n // Auto-approve safe or session-approved bash commands\n if (tool_name === 'Bash' && typeof inp.command === 'string') {\n if (\n isSafeBashCommand(inp.command) ||\n isCommandApprovedForSession(inp.command)\n ) {\n logToFile('PreToolUse: auto-approving bash command:', inp.command);\n return {\n hookSpecificOutput: {\n hookEventName: 'PreToolUse',\n permissionDecision: 'allow',\n },\n };\n }\n }\n\n // Auto-approve WebSearch with domain restriction applied via updatedInput\n if (tool_name === 'WebSearch') {\n return {\n hookSpecificOutput: {\n hookEventName: 'PreToolUse',\n permissionDecision: 'allow',\n updatedInput: {\n ...inp,\n allowed_domains: ['raindrop.ai/docs', 'ai-sdk.dev/docs/'],\n },\n },\n };\n }\n\n // Auto-approve ExitPlanMode and fire session update\n if (tool_name === 'ExitPlanMode') {\n const planContent = typeof inp.plan === 'string' ? inp.plan : '';\n if (sessionInfo) {\n sendSessionUpdate(\n sessionInfo.sessionId,\n planContent,\n sessionInfo.accessToken,\n sessionInfo.orgId,\n );\n }\n return {\n hookSpecificOutput: {\n hookEventName: 'PreToolUse',\n permissionDecision: 'allow',\n permissionDecisionReason: 'System automatically approved.',\n },\n };\n }\n\n // Auto-approve edits to files that were already approved this session\n if (tool_name === 'Edit' || tool_name === 'Write') {\n const fileName =\n typeof inp.file_path === 'string'\n ? inp.file_path\n : typeof inp.path === 'string'\n ? inp.path\n : undefined;\n if (fileName && approvedFilesForSession.has(fileName)) {\n logToFile(\n 'PreToolUse: auto-approving edit to session-approved file:',\n fileName,\n );\n return {\n hookSpecificOutput: {\n hookEventName: 'PreToolUse',\n permissionDecision: 'allow',\n },\n };\n }\n }\n\n // Anything else needs user interaction — let canUseTool handle it\n return {};\n };\n}\n\n/**\n * Check if a bash command matches a safe pattern and can be auto-approved.\n */\nfunction isSafeBashCommand(command: string): boolean {\n const trimmed = command.trim();\n return SAFE_BASH_PATTERNS.some((pattern) => {\n if (pattern.startsWith('*')) {\n // Suffix match (e.g., '*--version')\n return trimmed.endsWith(pattern.slice(1));\n } else if (pattern.endsWith('*')) {\n // Prefix match (e.g., 'npm install*')\n return trimmed.startsWith(pattern.slice(0, -1));\n } else {\n // Exact match\n return trimmed === pattern;\n }\n });\n}\n\n/**\n * Create a canUseTool handler for tools that require user interaction.\n * Auto-approve/deny logic lives in createPreToolUseHook instead.\n * This handler is only reached for tools that PreToolUse passes through.\n */\nexport function createCanUseToolHandler(approvedFilesCache?: Set<string>) {\n return async (\n toolName: string,\n input: unknown,\n ): Promise<ToolApprovalResult> => {\n const inputRecord = input as Record<string, unknown>;\n logToFile('canUseTool called:', { toolName, input: inputRecord });\n\n // Handle AskUserQuestion specially\n if (toolName === 'AskUserQuestion') {\n return handleClarifyingQuestions(inputRecord);\n }\n\n // ExitPlanMode is auto-approved (session update already fired in PreToolUse hook)\n if (toolName === 'ExitPlanMode') {\n return { behavior: 'allow', updatedInput: inputRecord };\n }\n\n // Show approval UI for all other tools\n return handleToolApproval(toolName, inputRecord, approvedFilesCache);\n };\n}\n"]}
@@ -35,10 +35,10 @@ export interface ReceivedEvent {
35
35
  }
36
36
  /**
37
37
  * Test the integration by polling the events list endpoint.
38
- * Returns feedbackPrompt if user wants to retry, otherwise shouldRetry is false.
38
+ * Returns:
39
+ * - true: integration looks good, finish
40
+ * - false: stop without retry (e.g., user cancelled)
41
+ * - string: feedback prompt to send back to the agent for another iteration
39
42
  */
40
- export declare function testIntegration(options: WizardOptions, writeKey: string, accessToken: string): Promise<{
41
- shouldRetry: boolean;
42
- feedbackPrompt?: string;
43
- }>;
43
+ export declare function testIntegration(options: WizardOptions, writeKey: string, accessToken: string, orgId: string): Promise<boolean | string>;
44
44
  export {};
@@ -3,14 +3,15 @@ import Chalk from 'chalk';
3
3
  const chalk = Chalk;
4
4
  import ui from '../utils/ui.js';
5
5
  import { logToFile } from '../utils/debug.js';
6
- import { waitForUserKeyPress } from '../utils/clack-utils.js';
7
6
  import { EVENTS_LIST_ENDPOINT } from './constants.js';
8
7
  import { buildTestFeedbackMessage } from './agent-prompts.js';
8
+ import { sendSessionComplete } from '../utils/session.js';
9
9
  const POLL_INTERVAL_MS = 2000;
10
10
  /**
11
11
  * Fetch events from the API endpoint, filtered by wizard session ID
12
12
  */
13
13
  async function fetchEvents(accessToken, wizardSessionId) {
14
+ logToFile(`fetchEvents: GET ${EVENTS_LIST_ENDPOINT} (session: ${wizardSessionId})`);
14
15
  try {
15
16
  const response = await fetch(EVENTS_LIST_ENDPOINT, {
16
17
  headers: {
@@ -23,18 +24,22 @@ async function fetchEvents(accessToken, wizardSessionId) {
23
24
  }
24
25
  // API returns an array of events directly
25
26
  const events = (await response.json());
27
+ logToFile(`fetchEvents: received ${events?.length ?? 0} events`, events?.map(e => ({ id: e.id, name: e.name, isPending: e.isPending })));
26
28
  return events || [];
27
29
  }
28
30
  catch (error) {
29
- logToFile('Error fetching events:', error);
31
+ logToFile('fetchEvents error:', error);
30
32
  return [];
31
33
  }
32
34
  }
33
35
  /**
34
36
  * Test the integration by polling the events list endpoint.
35
- * Returns feedbackPrompt if user wants to retry, otherwise shouldRetry is false.
37
+ * Returns:
38
+ * - true: integration looks good, finish
39
+ * - false: stop without retry (e.g., user cancelled)
40
+ * - string: feedback prompt to send back to the agent for another iteration
36
41
  */
37
- export async function testIntegration(options, writeKey, accessToken) {
42
+ export async function testIntegration(options, writeKey, accessToken, orgId) {
38
43
  const receivedEvents = [];
39
44
  const seenEventIds = new Set();
40
45
  let isPolling = true;
@@ -44,8 +49,7 @@ export async function testIntegration(options, writeKey, accessToken) {
44
49
  ui.stopPersistentInput();
45
50
  const testSpinner = ui.spinner();
46
51
  testSpinner.start(String(chalk.cyan('Test your integration: ')) +
47
- String(chalk.dim('Interact with your AI. Events will appear above. ')) +
48
- String(chalk.yellow('Press any key when done testing...')));
52
+ String(chalk.dim('Interact with your AI. Events will appear above.')));
49
53
  // Start polling in the background
50
54
  void (async () => {
51
55
  while (isPolling) {
@@ -79,6 +83,7 @@ export async function testIntegration(options, writeKey, accessToken) {
79
83
  userId: event.userId,
80
84
  input: event.aiData?.input,
81
85
  output: event.aiData?.output,
86
+ toolCallNames: event.toolCallNames,
82
87
  },
83
88
  });
84
89
  }
@@ -86,14 +91,16 @@ export async function testIntegration(options, writeKey, accessToken) {
86
91
  await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
87
92
  }
88
93
  })();
89
- // Wait for user to finish testing (ensure input is stopped)
90
- ui.stopPersistentInput();
91
- await waitForUserKeyPress();
94
+ // Wait for user to finish testing via Ink's input system
95
+ const keyPressResult = await ui.continuePrompt({ message: 'Press any key when done testing...', anyKey: true });
92
96
  // Stop polling and spinner
93
97
  isPolling = false;
94
98
  testSpinner.stop();
95
99
  // Let pollPromise finish in the background - no need to wait
96
100
  logToFile(`Polling stopped, received ${receivedEvents.length} events`);
101
+ if (ui.isCancel(keyPressResult)) {
102
+ return false;
103
+ }
97
104
  // Ensure persistent input is stopped before showing feedback prompt
98
105
  ui.stopPersistentInput();
99
106
  // Ask if results look good (with inline text input for feedback)
@@ -110,14 +117,23 @@ export async function testIntegration(options, writeKey, accessToken) {
110
117
  });
111
118
  // Ensure persistent input stays stopped after feedback prompt resolves
112
119
  ui.stopPersistentInput();
120
+ // User cancelled the prompt
121
+ if (ui.isCancel(result)) {
122
+ return false;
123
+ }
113
124
  // User selected "Yes, looks good"
114
125
  if (result.type === 'option' && result.value === true) {
115
- return { shouldRetry: false };
126
+ await sendSessionComplete(options.sessionId, 'success', accessToken, orgId);
127
+ return true;
128
+ }
129
+ if (result.type !== 'text' || !result.value.trim()) {
130
+ return false;
116
131
  }
117
132
  // User typed feedback
118
- const userFeedback = result.value;
133
+ const userFeedback = result.value.trim();
134
+ await sendSessionComplete(options.sessionId, 'failure', accessToken, orgId, userFeedback);
119
135
  // Build feedback prompt for agent
120
136
  const feedbackPrompt = buildTestFeedbackMessage(receivedEvents, userFeedback);
121
- return { shouldRetry: true, feedbackPrompt };
137
+ return feedbackPrompt;
122
138
  }
123
139
  //# sourceMappingURL=integration-testing.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"integration-testing.js","sourceRoot":"","sources":["../../../src/lib/integration-testing.ts"],"names":[],"mappings":"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","sourcesContent":["import Chalk from 'chalk';\n\n// chalk v2 types don't work well with ESM default imports\nconst chalk = Chalk as any;\nimport ui from '../utils/ui.js';\nimport { logToFile } from '../utils/debug.js';\nimport { waitForUserKeyPress } from '../utils/clack-utils.js';\nimport { EVENTS_LIST_ENDPOINT } from './constants.js';\nimport { buildTestFeedbackMessage } from './agent-prompts.js';\nimport type { WizardOptions } from '../utils/types.js';\n\nconst POLL_INTERVAL_MS = 2000;\n\n/**\n * Event format from the events list API\n */\ninterface ApiEvent {\n id: string;\n name?: string;\n timestamp?: string;\n receivedAt?: string;\n userId?: string;\n customEventId?: string;\n isPending?: boolean;\n properties?: Record<string, unknown>;\n aiData?: {\n input?: string;\n output?: string;\n model?: string;\n convoId?: string | null;\n };\n topics?: unknown[];\n inputAttachments?: unknown[];\n outputAttachments?: unknown[];\n signals?: unknown[];\n errorSpans?: unknown[];\n toolCalls?: unknown[];\n toolCallNames?: string[];\n [key: string]: unknown;\n}\n\n/**\n * Wrapper for received events\n */\nexport interface ReceivedEvent {\n url: string;\n data: ApiEvent;\n}\n\n/**\n * Fetch events from the API endpoint, filtered by wizard session ID\n */\nasync function fetchEvents(\n accessToken: string,\n wizardSessionId: string,\n): Promise<ApiEvent[]> {\n try {\n const response = await fetch(EVENTS_LIST_ENDPOINT, {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n 'x-wizard-session': wizardSessionId,\n },\n });\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n // API returns an array of events directly\n const events = (await response.json()) as ApiEvent[];\n return events || [];\n } catch (error) {\n logToFile('Error fetching events:', error);\n return [];\n }\n}\n\n/**\n * Test the integration by polling the events list endpoint.\n * Returns feedbackPrompt if user wants to retry, otherwise shouldRetry is false.\n */\nexport async function testIntegration(\n options: WizardOptions,\n writeKey: string,\n accessToken: string,\n): Promise<{ shouldRetry: boolean; feedbackPrompt?: string }> {\n const receivedEvents: ReceivedEvent[] = [];\n const seenEventIds = new Set<string>();\n let isPolling = true;\n\n // Add header to indicate start of testing phase\n ui.addItem({ type: 'phase', text: '─── Testing ───' });\n\n // Ensure persistent input is hidden during testing\n ui.stopPersistentInput();\n\n const testSpinner = ui.spinner();\n testSpinner.start(\n String(chalk.cyan('Test your integration: ')) +\n String(chalk.dim('Interact with your AI. Events will appear above. ')) +\n String(chalk.yellow('Press any key when done testing...')),\n );\n\n // Start polling in the background\n void (async () => {\n while (isPolling) {\n const events = await fetchEvents(accessToken, options.sessionId);\n\n for (const event of events) {\n // Skip events we've already seen\n if (event.id && seenEventIds.has(event.id)) {\n continue;\n }\n\n // Skip pending events (they don't have output yet)\n if (event.isPending === true) {\n continue;\n }\n\n if (event.id) {\n seenEventIds.add(event.id);\n }\n\n // Store full event data for feedback\n receivedEvents.push({ url: EVENTS_LIST_ENDPOINT, data: event });\n\n // DEBUG: Log raw event\n logToFile('========== RAW_EVENT_DEBUG ==========');\n logToFile(JSON.stringify(event, null, 2));\n logToFile('=====================================');\n\n ui.addItem({\n type: 'received-event',\n text: event.name || 'unknown',\n receivedEvent: {\n id: event.id,\n eventName: event.name || 'unknown',\n timestamp: event.timestamp,\n model: event.aiData?.model,\n userId: event.userId,\n input: event.aiData?.input,\n output: event.aiData?.output,\n },\n });\n }\n\n // Wait before next poll\n await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));\n }\n })();\n\n // Wait for user to finish testing (ensure input is stopped)\n ui.stopPersistentInput();\n await waitForUserKeyPress();\n\n // Stop polling and spinner\n isPolling = false;\n testSpinner.stop();\n // Let pollPromise finish in the background - no need to wait\n\n logToFile(`Polling stopped, received ${receivedEvents.length} events`);\n\n // Ensure persistent input is stopped before showing feedback prompt\n ui.stopPersistentInput();\n\n // Ask if results look good (with inline text input for feedback)\n const result = await ui.feedbackSelect({\n message: 'Do the results look good?',\n options: [\n { value: true, label: 'Yes, looks good - proceed' },\n {\n value: false,\n label: 'No, I need to provide feedback',\n allowTextInput: true,\n },\n ],\n });\n\n // Ensure persistent input stays stopped after feedback prompt resolves\n ui.stopPersistentInput();\n\n // User selected \"Yes, looks good\"\n if (result.type === 'option' && result.value === true) {\n return { shouldRetry: false };\n }\n\n // User typed feedback\n const userFeedback = result.value as string;\n\n // Build feedback prompt for agent\n const feedbackPrompt = buildTestFeedbackMessage(receivedEvents, userFeedback);\n\n return { shouldRetry: true, feedbackPrompt };\n}\n"]}
1
+ {"version":3,"file":"integration-testing.js","sourceRoot":"","sources":["../../../src/lib/integration-testing.ts"],"names":[],"mappings":"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","sourcesContent":["import Chalk from 'chalk';\n\n// chalk v2 types don't work well with ESM default imports\nconst chalk = Chalk as any;\nimport ui from '../utils/ui.js';\nimport { logToFile } from '../utils/debug.js';\nimport { EVENTS_LIST_ENDPOINT } from './constants.js';\nimport { buildTestFeedbackMessage } from './agent-prompts.js';\nimport { sendSessionComplete } from '../utils/session.js';\nimport type { WizardOptions } from '../utils/types.js';\n\nconst POLL_INTERVAL_MS = 2000;\n\n/**\n * Event format from the events list API\n */\ninterface ApiEvent {\n id: string;\n name?: string;\n timestamp?: string;\n receivedAt?: string;\n userId?: string;\n customEventId?: string;\n isPending?: boolean;\n properties?: Record<string, unknown>;\n aiData?: {\n input?: string;\n output?: string;\n model?: string;\n convoId?: string | null;\n };\n topics?: unknown[];\n inputAttachments?: unknown[];\n outputAttachments?: unknown[];\n signals?: unknown[];\n errorSpans?: unknown[];\n toolCalls?: unknown[];\n toolCallNames?: string[];\n [key: string]: unknown;\n}\n\n/**\n * Wrapper for received events\n */\nexport interface ReceivedEvent {\n url: string;\n data: ApiEvent;\n}\n\n/**\n * Fetch events from the API endpoint, filtered by wizard session ID\n */\nasync function fetchEvents(\n accessToken: string,\n wizardSessionId: string,\n): Promise<ApiEvent[]> {\n logToFile(`fetchEvents: GET ${EVENTS_LIST_ENDPOINT} (session: ${wizardSessionId})`);\n try {\n const response = await fetch(EVENTS_LIST_ENDPOINT, {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n 'x-wizard-session': wizardSessionId,\n },\n });\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n // API returns an array of events directly\n const events = (await response.json()) as ApiEvent[];\n logToFile(`fetchEvents: received ${events?.length ?? 0} events`, events?.map(e => ({ id: e.id, name: e.name, isPending: e.isPending })));\n return events || [];\n } catch (error) {\n logToFile('fetchEvents error:', error);\n return [];\n }\n}\n\n/**\n * Test the integration by polling the events list endpoint.\n * Returns:\n * - true: integration looks good, finish\n * - false: stop without retry (e.g., user cancelled)\n * - string: feedback prompt to send back to the agent for another iteration\n */\nexport async function testIntegration(\n options: WizardOptions,\n writeKey: string,\n accessToken: string,\n orgId: string,\n): Promise<boolean | string> {\n const receivedEvents: ReceivedEvent[] = [];\n const seenEventIds = new Set<string>();\n let isPolling = true;\n\n // Add header to indicate start of testing phase\n ui.addItem({ type: 'phase', text: '─── Testing ───' });\n\n // Ensure persistent input is hidden during testing\n ui.stopPersistentInput();\n\n const testSpinner = ui.spinner();\n testSpinner.start(\n String(chalk.cyan('Test your integration: ')) +\n String(chalk.dim('Interact with your AI. Events will appear above.')),\n );\n\n // Start polling in the background\n void (async () => {\n while (isPolling) {\n const events = await fetchEvents(accessToken, options.sessionId);\n\n for (const event of events) {\n // Skip events we've already seen\n if (event.id && seenEventIds.has(event.id)) {\n continue;\n }\n\n // Skip pending events (they don't have output yet)\n if (event.isPending === true) {\n continue;\n }\n\n if (event.id) {\n seenEventIds.add(event.id);\n }\n\n // Store full event data for feedback\n receivedEvents.push({ url: EVENTS_LIST_ENDPOINT, data: event });\n\n // DEBUG: Log raw event\n logToFile('========== RAW_EVENT_DEBUG ==========');\n logToFile(JSON.stringify(event, null, 2));\n logToFile('=====================================');\n\n ui.addItem({\n type: 'received-event',\n text: event.name || 'unknown',\n receivedEvent: {\n id: event.id,\n eventName: event.name || 'unknown',\n timestamp: event.timestamp,\n model: event.aiData?.model,\n userId: event.userId,\n input: event.aiData?.input,\n output: event.aiData?.output,\n toolCallNames: event.toolCallNames as string[] | undefined,\n },\n });\n }\n\n // Wait before next poll\n await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));\n }\n })();\n\n // Wait for user to finish testing via Ink's input system\n const keyPressResult = await ui.continuePrompt({ message: 'Press any key when done testing...', anyKey: true });\n\n // Stop polling and spinner\n isPolling = false;\n testSpinner.stop();\n // Let pollPromise finish in the background - no need to wait\n\n logToFile(`Polling stopped, received ${receivedEvents.length} events`);\n\n if (ui.isCancel(keyPressResult)) {\n return false;\n }\n\n // Ensure persistent input is stopped before showing feedback prompt\n ui.stopPersistentInput();\n\n // Ask if results look good (with inline text input for feedback)\n const result = await ui.feedbackSelect({\n message: 'Do the results look good?',\n options: [\n { value: true, label: 'Yes, looks good - proceed' },\n {\n value: false,\n label: 'No, I need to provide feedback',\n allowTextInput: true,\n },\n ],\n });\n\n // Ensure persistent input stays stopped after feedback prompt resolves\n ui.stopPersistentInput();\n\n // User cancelled the prompt\n if (ui.isCancel(result)) {\n return false;\n }\n\n // User selected \"Yes, looks good\"\n if (result.type === 'option' && result.value === true) {\n await sendSessionComplete(options.sessionId, 'success', accessToken, orgId);\n return true;\n }\n\n if (result.type !== 'text' || !result.value.trim()) {\n return false;\n }\n\n // User typed feedback\n const userFeedback = result.value.trim();\n\n await sendSessionComplete(options.sessionId, 'failure', accessToken, orgId, userFeedback);\n\n // Build feedback prompt for agent\n const feedbackPrompt = buildTestFeedbackMessage(receivedEvents, userFeedback);\n\n return feedbackPrompt;\n}\n"]}
@@ -4,7 +4,7 @@
4
4
  /**
5
5
  * Create an in-process MCP server with the CompleteIntegration tool
6
6
  */
7
- export declare function createCompletionMcpServer(hasCompletedWorkRef: {
7
+ export declare function createMcpServer(hasCompletedWorkRef: {
8
8
  value: boolean;
9
9
  }, sessionContext: {
10
10
  sessionId: string;
@@ -2,20 +2,51 @@
2
2
  * MCP server utilities for the Claude agent
3
3
  */
4
4
  import { createSdkMcpServer, tool } from '@anthropic-ai/claude-agent-sdk';
5
- import { logToFile } from '../utils/debug.js';
6
5
  import * as fs from 'fs';
7
6
  import * as path from 'path';
8
7
  import { fileURLToPath } from 'url';
9
8
  import { z } from 'zod';
10
- import { collectPythonSetupDetails, collectTypeScriptSetupDetails, } from './config.js';
9
+ import { logToFile } from '../utils/debug.js';
11
10
  import { sendSessionInit } from '../utils/session.js';
11
+ import { collectPythonSetupDetails, collectTypeScriptSetupDetails, } from './config.js';
12
12
  const __filename = fileURLToPath(import.meta.url);
13
13
  const __dirname = path.dirname(__filename);
14
+ const DOCS_FILE_BY_INTEGRATION_TYPE = {
15
+ python: 'python.mdx',
16
+ typescript: 'typescript.mdx',
17
+ 'vercel-ai-sdk': 'vercel-ai-sdk.mdx',
18
+ browser: 'browser.mdx',
19
+ 'claude-agent-sdk': 'claude-agent-sdk.mdx',
20
+ 'opencode-sdk': 'opencode-sdk.mdx',
21
+ };
22
+ const INTEGRATION_TYPE_ALIASES = {
23
+ 'typescript sdk': 'typescript',
24
+ 'typescript_sdk': 'typescript',
25
+ 'browser sdk': 'browser',
26
+ 'browser_sdk': 'browser',
27
+ 'edge runtime': 'browser',
28
+ 'edge-runtime': 'browser',
29
+ 'vercel ai sdk': 'vercel-ai-sdk',
30
+ 'vercel_ai_sdk': 'vercel-ai-sdk',
31
+ 'claude agent sdk': 'claude-agent-sdk',
32
+ 'claude_agent_sdk': 'claude-agent-sdk',
33
+ 'opencode sdk': 'opencode-sdk',
34
+ 'opencode ai sdk': 'opencode-sdk',
35
+ 'opencode_ai_sdk': 'opencode-sdk',
36
+ };
37
+ const SUPPORTED_INTEGRATION_TYPES = Object.keys(DOCS_FILE_BY_INTEGRATION_TYPE);
38
+ function normalizeIntegrationType(integrationType) {
39
+ const normalized = integrationType.trim().toLowerCase();
40
+ if (normalized in DOCS_FILE_BY_INTEGRATION_TYPE) {
41
+ return normalized;
42
+ }
43
+ return INTEGRATION_TYPE_ALIASES[normalized] ?? null;
44
+ }
14
45
  /**
15
46
  * Create an in-process MCP server with the CompleteIntegration tool
16
47
  */
17
- export function createCompletionMcpServer(hasCompletedWorkRef, sessionContext) {
18
- const completionTool = tool('CompleteIntegration', 'Signals that the Raindrop integration is complete. Call this tool ONLY after you have: 1) Successfully installed the Raindrop package, 2) Integrated Raindrop into all relevant LLM API call sites, and 3) Verified the project builds/runs without errors.', {}, // No input parameters
48
+ export function createMcpServer(hasCompletedWorkRef, sessionContext) {
49
+ const completionTool = tool('CompleteIntegration', 'Signals that the Raindrop integration is complete. Call this tool ONLY after you have confirmed that: 1) the Raindrop package is successfully installed, 2) Raindrop is integrated into user-facing AI features, and 3) Verified the project builds/runs without errors.', {}, // No input parameters
19
50
  (_args, _extra) => {
20
51
  logToFile('Agent called CompleteIntegration tool - integration is complete');
21
52
  // Set the completion flag
@@ -29,36 +60,40 @@ export function createCompletionMcpServer(hasCompletedWorkRef, sessionContext) {
29
60
  ],
30
61
  };
31
62
  });
32
- const loadPythonDocsTool = tool('LoadPythonDocumentation', 'Load the Python SDK documentation for Raindrop integration', {}, async (_args, _extra) => {
33
- const docsPath = path.resolve(__dirname, '../../src/docs/python.md');
34
- logToFile(`Loading Python docs from: ${docsPath}`);
35
- const docs = await fs.promises.readFile(docsPath, 'utf-8');
36
- const processedDocs = docs.replace(/__WIZARD_SESSION_UUID__/g, sessionContext.sessionId);
37
- return {
38
- content: [{ type: 'text', text: processedDocs }],
39
- };
40
- });
41
- const loadTypeScriptDocsTool = tool('LoadTypeScriptDocumentation', 'Load the TypeScript SDK documentation for Raindrop integration', {}, async (_args, _extra) => {
42
- const docsPath = path.resolve(__dirname, '../../src/docs/typescript.md');
43
- logToFile(`Loading TypeScript docs from: ${docsPath}`);
44
- const docs = await fs.promises.readFile(docsPath, 'utf-8');
45
- const processedDocs = docs.replace(/__WIZARD_SESSION_UUID__/g, sessionContext.sessionId);
46
- return {
47
- content: [{ type: 'text', text: processedDocs }],
48
- };
49
- });
50
- const loadVercelAiSdkDocsTool = tool('LoadVercelAiSdkDocumentation', 'Load the Vercel AI SDK (OpenTelemetry-based) documentation for Raindrop integration', {}, async (_args, _extra) => {
51
- const docsPath = path.resolve(__dirname, '../../src/docs/vercel-ai-sdk.md');
52
- logToFile(`Loading Vercel AI SDK docs from: ${docsPath}`);
53
- const docs = await fs.promises.readFile(docsPath, 'utf-8');
54
- const processedDocs = docs.replace(/__WIZARD_SESSION_UUID__/g, sessionContext.sessionId);
55
- return {
56
- content: [{ type: 'text', text: processedDocs }],
57
- };
58
- });
59
- const loadBrowserDocsTool = tool('LoadBrowserDocumentation', 'Load the Browser SDK documentation for Raindrop integration in edge runtime/browser environments', {}, async (_args, _extra) => {
60
- const docsPath = path.resolve(__dirname, '../../src/docs/browser.md');
61
- logToFile(`Loading Browser SDK docs from: ${docsPath}`);
63
+ const loadDocumentationTool = tool('LoadDocumentation', 'Load Raindrop documentation for a specific integration type', {
64
+ integrationType: z
65
+ .string()
66
+ .optional()
67
+ .describe('The integration type to load docs for: python, typescript, vercel-ai-sdk, browser, claude-agent-sdk, or opencode-sdk'),
68
+ interactionType: z
69
+ .string()
70
+ .optional()
71
+ .describe('Alias for integrationType for backward compatibility'),
72
+ }, async (args, _extra) => {
73
+ const requestedIntegrationType = args.integrationType || args.interactionType;
74
+ if (!requestedIntegrationType) {
75
+ return {
76
+ content: [
77
+ {
78
+ type: 'text',
79
+ text: `Missing integration type. Supported values: ${SUPPORTED_INTEGRATION_TYPES.join(', ')}`,
80
+ },
81
+ ],
82
+ };
83
+ }
84
+ const normalizedIntegrationType = normalizeIntegrationType(requestedIntegrationType);
85
+ if (!normalizedIntegrationType) {
86
+ return {
87
+ content: [
88
+ {
89
+ type: 'text',
90
+ text: `Unsupported integration type: ${requestedIntegrationType}. Supported values: ${SUPPORTED_INTEGRATION_TYPES.join(', ')}`,
91
+ },
92
+ ],
93
+ };
94
+ }
95
+ const docsPath = path.resolve(__dirname, '../../src/docs', DOCS_FILE_BY_INTEGRATION_TYPE[normalizedIntegrationType]);
96
+ logToFile(`Loading ${normalizedIntegrationType} docs from: ${docsPath}`);
62
97
  const docs = await fs.promises.readFile(docsPath, 'utf-8');
63
98
  const processedDocs = docs.replace(/__WIZARD_SESSION_UUID__/g, sessionContext.sessionId);
64
99
  return {
@@ -68,22 +103,33 @@ export function createCompletionMcpServer(hasCompletedWorkRef, sessionContext) {
68
103
  const initializeSessionTool = tool('InitializeSession', 'Initialize session context for the integration. Call this immediately after confirming the integration type with the user and BEFORE loading documentation.', {
69
104
  integrationType: z
70
105
  .string()
71
- .describe('The detected integration type: python, typescript, vercel-ai-sdk, or browser'),
106
+ .optional()
107
+ .describe('The detected integration type: python, typescript, vercel-ai-sdk, browser, claude-agent-sdk, or opencode-sdk'),
108
+ interactionType: z
109
+ .string()
110
+ .optional()
111
+ .describe('Alias for integrationType for backward compatibility'),
72
112
  }, async (args, _extra) => {
73
- logToFile(`InitializeSession called with integrationType: ${args.integrationType}`);
113
+ const requestedIntegrationType = args.integrationType || args.interactionType;
114
+ logToFile(`InitializeSession called with integrationType: ${requestedIntegrationType}`);
74
115
  try {
75
116
  // Collect setup details based on integration type
76
117
  let details = [];
77
- if (args.integrationType === 'python') {
118
+ const normalizedIntegrationType = requestedIntegrationType
119
+ ? normalizeIntegrationType(requestedIntegrationType)
120
+ : null;
121
+ if (normalizedIntegrationType === 'python') {
78
122
  details = await collectPythonSetupDetails(sessionContext.installDir);
79
123
  }
80
- else if (args.integrationType === 'typescript' ||
81
- args.integrationType === 'vercel-ai-sdk' ||
82
- args.integrationType === 'browser') {
124
+ else if (normalizedIntegrationType === 'typescript' ||
125
+ normalizedIntegrationType === 'vercel-ai-sdk' ||
126
+ normalizedIntegrationType === 'browser' ||
127
+ normalizedIntegrationType === 'claude-agent-sdk' ||
128
+ normalizedIntegrationType === 'opencode-sdk') {
83
129
  details = await collectTypeScriptSetupDetails(sessionContext.installDir);
84
130
  }
85
131
  else {
86
- logToFile(`Unknown integration type: ${args.integrationType}, defaulting to TypeScript setup details`);
132
+ logToFile(`Unknown or missing integration type: ${requestedIntegrationType}, defaulting to TypeScript setup details`);
87
133
  details = await collectTypeScriptSetupDetails(sessionContext.installDir);
88
134
  }
89
135
  // Format setup details into the expected string format
@@ -121,14 +167,7 @@ export function createCompletionMcpServer(hasCompletedWorkRef, sessionContext) {
121
167
  return createSdkMcpServer({
122
168
  name: 'raindrop-wizard',
123
169
  version: '1.0.0',
124
- tools: [
125
- completionTool,
126
- loadPythonDocsTool,
127
- loadTypeScriptDocsTool,
128
- loadVercelAiSdkDocsTool,
129
- loadBrowserDocsTool,
130
- initializeSessionTool,
131
- ],
170
+ tools: [completionTool, loadDocumentationTool, initializeSessionTool],
132
171
  });
133
172
  }
134
173
  //# sourceMappingURL=mcp.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"mcp.js","sourceRoot":"","sources":["../../../src/lib/mcp.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * MCP server utilities for the Claude agent\n */\n\nimport { createSdkMcpServer, tool } from '@anthropic-ai/claude-agent-sdk';\nimport { logToFile } from '../utils/debug.js';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { fileURLToPath } from 'url';\nimport { z } from 'zod';\nimport {\n collectPythonSetupDetails,\n collectTypeScriptSetupDetails,\n type SetupDetail,\n} from './config.js';\nimport { sendSessionInit } from '../utils/session.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\n/**\n * Create an in-process MCP server with the CompleteIntegration tool\n */\nexport function createCompletionMcpServer(\n hasCompletedWorkRef: {\n value: boolean;\n },\n sessionContext: {\n sessionId: string;\n accessToken: string;\n orgId: string;\n installDir: string;\n },\n): any {\n const completionTool = tool(\n 'CompleteIntegration',\n 'Signals that the Raindrop integration is complete. Call this tool ONLY after you have: 1) Successfully installed the Raindrop package, 2) Integrated Raindrop into all relevant LLM API call sites, and 3) Verified the project builds/runs without errors.',\n {}, // No input parameters\n (_args: Record<string, never>, _extra: unknown): any => {\n logToFile(\n 'Agent called CompleteIntegration tool - integration is complete',\n );\n\n // Set the completion flag\n hasCompletedWorkRef.value = true;\n\n return {\n content: [\n {\n type: 'text',\n text: 'Integration completion acknowledged. Transitioning to testing phase...',\n },\n ],\n };\n },\n );\n\n const loadPythonDocsTool = tool(\n 'LoadPythonDocumentation',\n 'Load the Python SDK documentation for Raindrop integration',\n {},\n async (_args: Record<string, never>, _extra: unknown): Promise<any> => {\n const docsPath = path.resolve(__dirname, '../../src/docs/python.md');\n logToFile(`Loading Python docs from: ${docsPath}`);\n const docs = await fs.promises.readFile(docsPath, 'utf-8');\n const processedDocs = docs.replace(\n /__WIZARD_SESSION_UUID__/g,\n sessionContext.sessionId,\n );\n return {\n content: [{ type: 'text', text: processedDocs }],\n };\n },\n );\n\n const loadTypeScriptDocsTool = tool(\n 'LoadTypeScriptDocumentation',\n 'Load the TypeScript SDK documentation for Raindrop integration',\n {},\n async (_args: Record<string, never>, _extra: unknown): Promise<any> => {\n const docsPath = path.resolve(__dirname, '../../src/docs/typescript.md');\n logToFile(`Loading TypeScript docs from: ${docsPath}`);\n const docs = await fs.promises.readFile(docsPath, 'utf-8');\n const processedDocs = docs.replace(\n /__WIZARD_SESSION_UUID__/g,\n sessionContext.sessionId,\n );\n return {\n content: [{ type: 'text', text: processedDocs }],\n };\n },\n );\n\n const loadVercelAiSdkDocsTool = tool(\n 'LoadVercelAiSdkDocumentation',\n 'Load the Vercel AI SDK (OpenTelemetry-based) documentation for Raindrop integration',\n {},\n async (_args: Record<string, never>, _extra: unknown): Promise<any> => {\n const docsPath = path.resolve(\n __dirname,\n '../../src/docs/vercel-ai-sdk.md',\n );\n logToFile(`Loading Vercel AI SDK docs from: ${docsPath}`);\n const docs = await fs.promises.readFile(docsPath, 'utf-8');\n const processedDocs = docs.replace(\n /__WIZARD_SESSION_UUID__/g,\n sessionContext.sessionId,\n );\n return {\n content: [{ type: 'text', text: processedDocs }],\n };\n },\n );\n\n const loadBrowserDocsTool = tool(\n 'LoadBrowserDocumentation',\n 'Load the Browser SDK documentation for Raindrop integration in edge runtime/browser environments',\n {},\n async (_args: Record<string, never>, _extra: unknown): Promise<any> => {\n const docsPath = path.resolve(__dirname, '../../src/docs/browser.md');\n logToFile(`Loading Browser SDK docs from: ${docsPath}`);\n const docs = await fs.promises.readFile(docsPath, 'utf-8');\n const processedDocs = docs.replace(\n /__WIZARD_SESSION_UUID__/g,\n sessionContext.sessionId,\n );\n return {\n content: [{ type: 'text', text: processedDocs }],\n };\n },\n );\n\n const initializeSessionTool = tool(\n 'InitializeSession',\n 'Initialize session context for the integration. Call this immediately after confirming the integration type with the user and BEFORE loading documentation.',\n {\n integrationType: z\n .string()\n .describe(\n 'The detected integration type: python, typescript, vercel-ai-sdk, or browser',\n ),\n },\n async (\n args: { integrationType: string },\n _extra: unknown,\n ): Promise<any> => {\n logToFile(\n `InitializeSession called with integrationType: ${args.integrationType}`,\n );\n\n try {\n // Collect setup details based on integration type\n let details: SetupDetail[] = [];\n\n if (args.integrationType === 'python') {\n details = await collectPythonSetupDetails(sessionContext.installDir);\n } else if (\n args.integrationType === 'typescript' ||\n args.integrationType === 'vercel-ai-sdk' ||\n args.integrationType === 'browser'\n ) {\n details = await collectTypeScriptSetupDetails(\n sessionContext.installDir,\n );\n } else {\n logToFile(\n `Unknown integration type: ${args.integrationType}, defaulting to TypeScript setup details`,\n );\n details = await collectTypeScriptSetupDetails(\n sessionContext.installDir,\n );\n }\n\n // Format setup details into the expected string format\n const compiledSetup = details\n .map((d) => `=== ${d.filename} ===\\n${d.content}`)\n .join('\\n\\n');\n\n logToFile(\n `Collected ${details.length} setup details, total length: ${compiledSetup.length}`,\n );\n\n // Send session init with the setup details\n sendSessionInit(\n sessionContext.sessionId,\n compiledSetup,\n sessionContext.accessToken,\n sessionContext.orgId,\n );\n\n logToFile('InitializeSession completed successfully');\n\n return {\n content: [\n {\n type: 'text',\n text: 'Session initialized successfully. You may now proceed to load documentation.',\n },\n ],\n };\n } catch (error) {\n // Log error but still return success to allow wizard to continue\n logToFile('Error in InitializeSession:', error);\n\n // Still send session init with minimal details\n sendSessionInit(\n sessionContext.sessionId,\n '',\n sessionContext.accessToken,\n sessionContext.orgId,\n );\n\n return {\n content: [\n {\n type: 'text',\n text: 'Session initialized with partial details. You may proceed to load documentation.',\n },\n ],\n };\n }\n },\n );\n\n return createSdkMcpServer({\n name: 'raindrop-wizard',\n version: '1.0.0',\n tools: [\n completionTool,\n loadPythonDocsTool,\n loadTypeScriptDocsTool,\n loadVercelAiSdkDocsTool,\n loadBrowserDocsTool,\n initializeSessionTool,\n ],\n });\n}\n"]}
1
+ {"version":3,"file":"mcp.js","sourceRoot":"","sources":["../../../src/lib/mcp.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * MCP server utilities for the Claude agent\n */\n\nimport { createSdkMcpServer, tool } from '@anthropic-ai/claude-agent-sdk';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { fileURLToPath } from 'url';\nimport { z } from 'zod';\nimport { logToFile } from '../utils/debug.js';\nimport { sendSessionInit } from '../utils/session.js';\nimport {\n collectPythonSetupDetails,\n collectTypeScriptSetupDetails,\n type SetupDetail,\n} from './config.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\nconst DOCS_FILE_BY_INTEGRATION_TYPE = {\n python: 'python.mdx',\n typescript: 'typescript.mdx',\n 'vercel-ai-sdk': 'vercel-ai-sdk.mdx',\n browser: 'browser.mdx',\n 'claude-agent-sdk': 'claude-agent-sdk.mdx',\n 'opencode-sdk': 'opencode-sdk.mdx',\n} as const;\n\ntype SupportedIntegrationType = keyof typeof DOCS_FILE_BY_INTEGRATION_TYPE;\n\nconst INTEGRATION_TYPE_ALIASES: Record<string, SupportedIntegrationType> = {\n 'typescript sdk': 'typescript',\n 'typescript_sdk': 'typescript',\n 'browser sdk': 'browser',\n 'browser_sdk': 'browser',\n 'edge runtime': 'browser',\n 'edge-runtime': 'browser',\n 'vercel ai sdk': 'vercel-ai-sdk',\n 'vercel_ai_sdk': 'vercel-ai-sdk',\n 'claude agent sdk': 'claude-agent-sdk',\n 'claude_agent_sdk': 'claude-agent-sdk',\n 'opencode sdk': 'opencode-sdk',\n 'opencode ai sdk': 'opencode-sdk',\n 'opencode_ai_sdk': 'opencode-sdk',\n};\n\nconst SUPPORTED_INTEGRATION_TYPES = Object.keys(\n DOCS_FILE_BY_INTEGRATION_TYPE,\n) as SupportedIntegrationType[];\n\nfunction normalizeIntegrationType(\n integrationType: string,\n): SupportedIntegrationType | null {\n const normalized = integrationType.trim().toLowerCase();\n if (normalized in DOCS_FILE_BY_INTEGRATION_TYPE) {\n return normalized as SupportedIntegrationType;\n }\n return INTEGRATION_TYPE_ALIASES[normalized] ?? null;\n}\n\n/**\n * Create an in-process MCP server with the CompleteIntegration tool\n */\nexport function createMcpServer(\n hasCompletedWorkRef: {\n value: boolean;\n },\n sessionContext: {\n sessionId: string;\n accessToken: string;\n orgId: string;\n installDir: string;\n },\n): any {\n const completionTool = tool(\n 'CompleteIntegration',\n 'Signals that the Raindrop integration is complete. Call this tool ONLY after you have confirmed that: 1) the Raindrop package is successfully installed, 2) Raindrop is integrated into user-facing AI features, and 3) Verified the project builds/runs without errors.',\n {}, // No input parameters\n (_args: Record<string, never>, _extra: unknown): any => {\n logToFile(\n 'Agent called CompleteIntegration tool - integration is complete',\n );\n\n // Set the completion flag\n hasCompletedWorkRef.value = true;\n\n return {\n content: [\n {\n type: 'text',\n text: 'Integration completion acknowledged. Transitioning to testing phase...',\n },\n ],\n };\n },\n );\n\n const loadDocumentationTool = tool(\n 'LoadDocumentation',\n 'Load Raindrop documentation for a specific integration type',\n {\n integrationType: z\n .string()\n .optional()\n .describe(\n 'The integration type to load docs for: python, typescript, vercel-ai-sdk, browser, claude-agent-sdk, or opencode-sdk',\n ),\n interactionType: z\n .string()\n .optional()\n .describe('Alias for integrationType for backward compatibility'),\n },\n async (\n args: { integrationType?: string; interactionType?: string },\n _extra: unknown,\n ): Promise<any> => {\n const requestedIntegrationType =\n args.integrationType || args.interactionType;\n if (!requestedIntegrationType) {\n return {\n content: [\n {\n type: 'text',\n text: `Missing integration type. Supported values: ${SUPPORTED_INTEGRATION_TYPES.join(\n ', ',\n )}`,\n },\n ],\n };\n }\n\n const normalizedIntegrationType = normalizeIntegrationType(\n requestedIntegrationType,\n );\n if (!normalizedIntegrationType) {\n return {\n content: [\n {\n type: 'text',\n text: `Unsupported integration type: ${requestedIntegrationType}. Supported values: ${SUPPORTED_INTEGRATION_TYPES.join(\n ', ',\n )}`,\n },\n ],\n };\n }\n\n const docsPath = path.resolve(\n __dirname,\n '../../src/docs',\n DOCS_FILE_BY_INTEGRATION_TYPE[normalizedIntegrationType],\n );\n logToFile(`Loading ${normalizedIntegrationType} docs from: ${docsPath}`);\n const docs = await fs.promises.readFile(docsPath, 'utf-8');\n const processedDocs = docs.replace(\n /__WIZARD_SESSION_UUID__/g,\n sessionContext.sessionId,\n );\n return {\n content: [{ type: 'text', text: processedDocs }],\n };\n },\n );\n\n const initializeSessionTool = tool(\n 'InitializeSession',\n 'Initialize session context for the integration. Call this immediately after confirming the integration type with the user and BEFORE loading documentation.',\n {\n integrationType: z\n .string()\n .optional()\n .describe(\n 'The detected integration type: python, typescript, vercel-ai-sdk, browser, claude-agent-sdk, or opencode-sdk',\n ),\n interactionType: z\n .string()\n .optional()\n .describe('Alias for integrationType for backward compatibility'),\n },\n async (\n args: { integrationType?: string; interactionType?: string },\n _extra: unknown,\n ): Promise<any> => {\n const requestedIntegrationType =\n args.integrationType || args.interactionType;\n logToFile(\n `InitializeSession called with integrationType: ${requestedIntegrationType}`,\n );\n\n try {\n // Collect setup details based on integration type\n let details: SetupDetail[] = [];\n const normalizedIntegrationType = requestedIntegrationType\n ? normalizeIntegrationType(requestedIntegrationType)\n : null;\n\n if (normalizedIntegrationType === 'python') {\n details = await collectPythonSetupDetails(sessionContext.installDir);\n } else if (\n normalizedIntegrationType === 'typescript' ||\n normalizedIntegrationType === 'vercel-ai-sdk' ||\n normalizedIntegrationType === 'browser' ||\n normalizedIntegrationType === 'claude-agent-sdk' ||\n normalizedIntegrationType === 'opencode-sdk'\n ) {\n details = await collectTypeScriptSetupDetails(\n sessionContext.installDir,\n );\n } else {\n logToFile(\n `Unknown or missing integration type: ${requestedIntegrationType}, defaulting to TypeScript setup details`,\n );\n details = await collectTypeScriptSetupDetails(\n sessionContext.installDir,\n );\n }\n\n // Format setup details into the expected string format\n const compiledSetup = details\n .map((d) => `=== ${d.filename} ===\\n${d.content}`)\n .join('\\n\\n');\n\n logToFile(\n `Collected ${details.length} setup details, total length: ${compiledSetup.length}`,\n );\n\n // Send session init with the setup details\n sendSessionInit(\n sessionContext.sessionId,\n compiledSetup,\n sessionContext.accessToken,\n sessionContext.orgId,\n );\n\n logToFile('InitializeSession completed successfully');\n\n return {\n content: [\n {\n type: 'text',\n text: 'Session initialized successfully. You may now proceed to load documentation.',\n },\n ],\n };\n } catch (error) {\n // Log error but still return success to allow wizard to continue\n logToFile('Error in InitializeSession:', error);\n\n // Still send session init with minimal details\n sendSessionInit(\n sessionContext.sessionId,\n '',\n sessionContext.accessToken,\n sessionContext.orgId,\n );\n\n return {\n content: [\n {\n type: 'text',\n text: 'Session initialized with partial details. You may proceed to load documentation.',\n },\n ],\n };\n }\n },\n );\n\n return createSdkMcpServer({\n name: 'raindrop-wizard',\n version: '1.0.0',\n tools: [completionTool, loadDocumentationTool, initializeSessionTool],\n });\n}\n"]}
@@ -9,9 +9,16 @@ type SDKMessage = any;
9
9
  * Extract result summary from tool result content
10
10
  */
11
11
  export declare function extractResultSummary(toolName: string, resultContent: unknown, input?: Record<string, unknown>): string | undefined;
12
+ /**
13
+ * Context passed into processSDKMessage for spinner updates.
14
+ */
15
+ export interface SDKMessageContext {
16
+ updateSpinner: (msg: string) => void;
17
+ baseSpinnerMessage: string;
18
+ }
12
19
  /**
13
20
  * Process SDK messages and provide user feedback.
14
21
  * Handles assistant text, tool use, tool results, and system messages.
15
22
  */
16
- export declare function processSDKMessage(message: SDKMessage, options: WizardOptions, collectedText: string[], pendingToolCalls: Map<string, PendingToolCall>, isInterrupting: boolean): void;
23
+ export declare function processSDKMessage(message: SDKMessage, options: WizardOptions, collectedText: string[], pendingToolCalls: Map<string, PendingToolCall>, isInterrupting: boolean, context?: SDKMessageContext): void;
17
24
  export {};