@raindrop-ai/wizard 0.0.10 → 0.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/docs/claude-agent-sdk.mdx +2 -2
- package/dist/src/docs/python.mdx +6 -0
- package/dist/src/docs/typescript.mdx +125 -28
- package/dist/src/lib/__tests__/sdk-messages.test.d.ts +4 -0
- package/dist/src/lib/__tests__/sdk-messages.test.js +296 -0
- package/dist/src/lib/__tests__/sdk-messages.test.js.map +1 -0
- package/dist/src/lib/agent-interface.js +40 -14
- package/dist/src/lib/agent-interface.js.map +1 -1
- package/dist/src/lib/agent-prompts.js +4 -1
- package/dist/src/lib/agent-prompts.js.map +1 -1
- package/dist/src/lib/constants.d.ts +7 -0
- package/dist/src/lib/constants.js +15 -0
- package/dist/src/lib/constants.js.map +1 -1
- package/dist/src/lib/handlers.js +21 -18
- package/dist/src/lib/handlers.js.map +1 -1
- package/dist/src/lib/sdk-messages.d.ts +41 -2
- package/dist/src/lib/sdk-messages.js +89 -41
- package/dist/src/lib/sdk-messages.js.map +1 -1
- package/dist/src/lib/wizard.js +1 -1
- package/dist/src/lib/wizard.js.map +1 -1
- package/dist/src/ui/components/ToolCallDisplay.js +30 -0
- package/dist/src/ui/components/ToolCallDisplay.js.map +1 -1
- package/dist/src/ui/contexts/WizardContext.d.ts +0 -11
- package/dist/src/ui/contexts/WizardContext.js +2 -19
- package/dist/src/ui/contexts/WizardContext.js.map +1 -1
- package/dist/src/utils/__mocks__/ui.d.ts +10 -0
- package/dist/src/utils/__mocks__/ui.js +7 -0
- package/dist/src/utils/__mocks__/ui.js.map +1 -0
- package/dist/src/utils/session.d.ts +22 -0
- package/dist/src/utils/session.js +67 -1
- package/dist/src/utils/session.js.map +1 -1
- package/package.json +16 -1
|
@@ -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 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/** Prefix for MCP tools (e.g. mcp__server__tool or mcp____server____tool). All are auto-approved and not shown in approval UI. */\nconst MCP_TOOL_PREFIX = 'mcp__';\n\n/**\n * Tools that are automatically approved without user confirmation.\n * MCP tools (name starts with mcp__) are approved via wildcard in PreToolUse.\n */\nconst AUTO_APPROVED_TOOLS = new Set(['EnterPlanMode']);\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 =\n 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 all MCP tools (mcp__*) and EnterPlanMode — no approval UI\n if (\n tool_name.startsWith(MCP_TOOL_PREFIX) ||\n AUTO_APPROVED_TOOLS.has(tool_name)\n ) {\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"]}
|
|
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 { MCP_TOOL_PREFIX, 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 * MCP tools (name starts with mcp__) are approved via wildcard in PreToolUse.\n */\nconst AUTO_APPROVED_TOOLS = new Set([\n 'EnterPlanMode',\n 'WebFetch',\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 =\n 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 WebSearch with domain restriction applied via updatedInput.\n // Keep this before the generic AUTO_APPROVED_TOOLS branch so WebSearch\n // still receives input hardening.\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 all MCP tools (mcp__*) and core auto-approved tools — no approval UI\n if (\n tool_name.startsWith(MCP_TOOL_PREFIX) ||\n AUTO_APPROVED_TOOLS.has(tool_name)\n ) {\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 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"]}
|
|
@@ -5,20 +5,59 @@
|
|
|
5
5
|
import type { WizardOptions } from '../utils/types.js';
|
|
6
6
|
import type { PendingToolCall } from './handlers.js';
|
|
7
7
|
type SDKMessage = any;
|
|
8
|
+
/**
|
|
9
|
+
* Return canned error display text from error string (extracts optional status code).
|
|
10
|
+
*/
|
|
11
|
+
export declare function getCannedErrorDisplayText(errorText: string): string;
|
|
8
12
|
/**
|
|
9
13
|
* Extract result summary from tool result content
|
|
10
14
|
*/
|
|
11
15
|
export declare function extractResultSummary(toolName: string, resultContent: unknown, input?: Record<string, unknown>): string | undefined;
|
|
12
16
|
/**
|
|
13
|
-
* Context passed into processSDKMessage for spinner updates.
|
|
17
|
+
* Context passed into processSDKMessage for spinner updates and optional error reporting.
|
|
14
18
|
*/
|
|
15
19
|
export interface SDKMessageContext {
|
|
16
20
|
updateSpinner: (msg: string) => void;
|
|
17
21
|
baseSpinnerMessage: string;
|
|
22
|
+
/** When set, errors (message.error) are reported to Slack with the agent run log path. */
|
|
23
|
+
onError?: {
|
|
24
|
+
wizardSessionId: string;
|
|
25
|
+
accessToken: string;
|
|
26
|
+
orgId: string;
|
|
27
|
+
/** Resolved absolute project path (e.g. /Users/.../project). */
|
|
28
|
+
workingDirectory: string;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Whether the most recently processed assistant message had any visible (text) content.
|
|
32
|
+
* Set by the caller from the return value of the previous processSDKMessage call.
|
|
33
|
+
* When false on a success result, we report to session/error and can queue a follow-up prompt.
|
|
34
|
+
*/
|
|
35
|
+
lastAssistantHadVisibleContent?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* When set, used to queue a follow-up user message so the agent continues (e.g. after
|
|
38
|
+
* last assistant had only thinking content). The prompt async iterable will yield this
|
|
39
|
+
* and the agent will run another turn.
|
|
40
|
+
*/
|
|
41
|
+
queueFollowUpPrompt?: (prompt: string) => void;
|
|
42
|
+
/**
|
|
43
|
+
* When true, the agent has already called CompleteIntegration and is transitioning to
|
|
44
|
+
* testing. Skip queuing [Wizard] Continue. since the testing phase will handle next steps.
|
|
45
|
+
*/
|
|
46
|
+
hasCompletedWork?: boolean;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Return value from processSDKMessage when the message was an assistant message.
|
|
50
|
+
* Caller should pass lastAssistantHadVisibleContent back in context on the next call.
|
|
51
|
+
*/
|
|
52
|
+
export interface ProcessSDKMessageResult {
|
|
53
|
+
lastAssistantHadVisibleContent?: boolean;
|
|
18
54
|
}
|
|
19
55
|
/**
|
|
20
56
|
* Process SDK messages and provide user feedback.
|
|
21
57
|
* Handles assistant text, tool use, tool results, and system messages.
|
|
58
|
+
* Returns lastAssistantHadVisibleContent when message type is 'assistant' so the caller
|
|
59
|
+
* can pass it back in context for the next call (used to show a fallback on success result
|
|
60
|
+
* when the last assistant had only thinking content).
|
|
22
61
|
*/
|
|
23
|
-
export declare function processSDKMessage(message: SDKMessage, options: WizardOptions,
|
|
62
|
+
export declare function processSDKMessage(message: SDKMessage, options: WizardOptions, pendingToolCalls: Map<string, PendingToolCall>, isInterrupting: boolean, context?: SDKMessageContext): ProcessSDKMessageResult | void;
|
|
24
63
|
export {};
|
|
@@ -4,20 +4,9 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { createTwoFilesPatch } from 'diff';
|
|
6
6
|
import { debug, logToFile } from '../utils/debug.js';
|
|
7
|
+
import { reportSessionError } from '../utils/session.js';
|
|
7
8
|
import ui from '../utils/ui.js';
|
|
8
|
-
|
|
9
|
-
const INTERNAL_TOOL_NAMES = new Set([
|
|
10
|
-
'Task',
|
|
11
|
-
'AskUserQuestion',
|
|
12
|
-
'TodoWrite',
|
|
13
|
-
'EnterPlanMode',
|
|
14
|
-
'ExitPlanMode',
|
|
15
|
-
]);
|
|
16
|
-
/** Prefix for MCP tools; all are internal (not shown in UI). Matches mcp__server__tool and mcp____... */
|
|
17
|
-
const MCP_TOOL_PREFIX = 'mcp__';
|
|
18
|
-
function isInternalTool(toolName) {
|
|
19
|
-
return (INTERNAL_TOOL_NAMES.has(toolName) || toolName.startsWith(MCP_TOOL_PREFIX));
|
|
20
|
-
}
|
|
9
|
+
import { ERROR_DISPLAY_MESSAGE, INTERNAL_TOOL_NAMES, MCP_TOOL_PREFIX, } from './constants.js';
|
|
21
10
|
/**
|
|
22
11
|
* Generate a unified diff for Edit tool inputs (old_string -> new_string)
|
|
23
12
|
*/
|
|
@@ -56,15 +45,28 @@ function extractWriteSummary(input) {
|
|
|
56
45
|
const fileName = typeof input.path === 'string' ? input.path.split('/').pop() : 'file';
|
|
57
46
|
return `Wrote ${lines} line${lines === 1 ? '' : 's'} to ${fileName}`;
|
|
58
47
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
*/
|
|
62
|
-
function extractEditWriteInfo(toolName, input) {
|
|
63
|
-
const fileName = typeof input.file_path === 'string'
|
|
48
|
+
function getToolFileName(input) {
|
|
49
|
+
return typeof input.file_path === 'string'
|
|
64
50
|
? input.file_path
|
|
65
51
|
: typeof input.path === 'string'
|
|
66
52
|
? input.path
|
|
67
53
|
: undefined;
|
|
54
|
+
}
|
|
55
|
+
function shouldHideToolCall(toolName, input) {
|
|
56
|
+
if (INTERNAL_TOOL_NAMES.has(toolName) || toolName.startsWith(MCP_TOOL_PREFIX)) {
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
if (toolName === 'Edit' || toolName === 'Write') {
|
|
60
|
+
const fileName = getToolFileName(input);
|
|
61
|
+
return Boolean(fileName && fileName.includes('plans/'));
|
|
62
|
+
}
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Generate diff content and file name for Edit/Write tools
|
|
67
|
+
*/
|
|
68
|
+
function extractEditWriteInfo(toolName, input) {
|
|
69
|
+
const fileName = getToolFileName(input);
|
|
68
70
|
if (toolName === 'Edit' && fileName) {
|
|
69
71
|
const oldString = typeof input.old_string === 'string' ? input.old_string : '';
|
|
70
72
|
const newString = typeof input.new_string === 'string' ? input.new_string : '';
|
|
@@ -78,6 +80,15 @@ function extractEditWriteInfo(toolName, input) {
|
|
|
78
80
|
}
|
|
79
81
|
return {};
|
|
80
82
|
}
|
|
83
|
+
/**
|
|
84
|
+
* Return canned error display text from error string (extracts optional status code).
|
|
85
|
+
*/
|
|
86
|
+
export function getCannedErrorDisplayText(errorText) {
|
|
87
|
+
const codeMatch = errorText.match(/^Error:\s*(\d+)/i) ||
|
|
88
|
+
errorText.match(/^API Error:\s*(\d+)/i);
|
|
89
|
+
const code = codeMatch?.[1];
|
|
90
|
+
return ERROR_DISPLAY_MESSAGE(code);
|
|
91
|
+
}
|
|
81
92
|
/**
|
|
82
93
|
* Extract result summary from tool result content
|
|
83
94
|
*/
|
|
@@ -160,8 +171,11 @@ function getToolSpinnerMessage(toolName, input) {
|
|
|
160
171
|
/**
|
|
161
172
|
* Process SDK messages and provide user feedback.
|
|
162
173
|
* Handles assistant text, tool use, tool results, and system messages.
|
|
174
|
+
* Returns lastAssistantHadVisibleContent when message type is 'assistant' so the caller
|
|
175
|
+
* can pass it back in context for the next call (used to show a fallback on success result
|
|
176
|
+
* when the last assistant had only thinking content).
|
|
163
177
|
*/
|
|
164
|
-
export function processSDKMessage(message, options,
|
|
178
|
+
export function processSDKMessage(message, options, pendingToolCalls, isInterrupting, context) {
|
|
165
179
|
logToFile(`SDK Message: ${message.type}`, JSON.stringify(message, null, 2));
|
|
166
180
|
if (options.debug) {
|
|
167
181
|
debug(`SDK Message type: ${message.type}`);
|
|
@@ -170,28 +184,38 @@ export function processSDKMessage(message, options, collectedText, pendingToolCa
|
|
|
170
184
|
case 'assistant': {
|
|
171
185
|
// Extract text content from assistant messages
|
|
172
186
|
const content = message.message?.content;
|
|
187
|
+
let hadVisibleContent = false;
|
|
173
188
|
if (Array.isArray(content)) {
|
|
174
189
|
for (const block of content) {
|
|
175
190
|
if (block.type === 'text' && typeof block.text === 'string') {
|
|
176
|
-
|
|
177
|
-
//
|
|
191
|
+
hadVisibleContent = true;
|
|
192
|
+
// If message.error and text looks like an error, report to Slack; use canned text in UI only for "unknown".
|
|
193
|
+
const isError = message.error != null && /(API )?Error/i.test(block.text);
|
|
194
|
+
const displayText = isError && message.error === 'unknown'
|
|
195
|
+
? getCannedErrorDisplayText(block.text)
|
|
196
|
+
: block.text;
|
|
197
|
+
if (isError && context?.onError && message.session_id) {
|
|
198
|
+
reportSessionError(block.text, message.session_id, context.onError);
|
|
199
|
+
}
|
|
178
200
|
ui.addItem({
|
|
179
201
|
type: 'agent-message',
|
|
180
|
-
text:
|
|
202
|
+
text: displayText,
|
|
181
203
|
});
|
|
182
204
|
// Reset spinner after assistant responds — "Analysing" after "Perfect!" looks wrong
|
|
183
205
|
if (context?.updateSpinner) {
|
|
184
206
|
context.updateSpinner(context.baseSpinnerMessage);
|
|
185
207
|
}
|
|
186
208
|
}
|
|
187
|
-
|
|
209
|
+
}
|
|
210
|
+
// Handle tool_use blocks - store pending, don't add to history yet
|
|
211
|
+
for (const block of content) {
|
|
188
212
|
if (block.type === 'tool_use') {
|
|
189
213
|
const toolName = block.name || 'Unknown tool';
|
|
190
|
-
const toolInput = block.input || {};
|
|
214
|
+
const toolInput = (block.input || {});
|
|
191
215
|
const toolUseId = block.id;
|
|
192
216
|
logToFile(`Tool use requested: ${toolName} (id: ${toolUseId})`, toolInput);
|
|
193
|
-
// Skip storing/displaying internal
|
|
194
|
-
if (
|
|
217
|
+
// Skip storing/displaying internal tools and plan-file edits
|
|
218
|
+
if (shouldHideToolCall(toolName, toolInput)) {
|
|
195
219
|
continue;
|
|
196
220
|
}
|
|
197
221
|
// Show tool as executing immediately (pretooluse)
|
|
@@ -219,7 +243,7 @@ export function processSDKMessage(message, options, collectedText, pendingToolCa
|
|
|
219
243
|
}
|
|
220
244
|
}
|
|
221
245
|
}
|
|
222
|
-
|
|
246
|
+
return { lastAssistantHadVisibleContent: hadVisibleContent };
|
|
223
247
|
}
|
|
224
248
|
case 'user': {
|
|
225
249
|
// Tool results come as 'user' messages with tool_result content
|
|
@@ -238,12 +262,12 @@ export function processSDKMessage(message, options, collectedText, pendingToolCa
|
|
|
238
262
|
const pendingCall = pendingToolCalls.get(toolUseId);
|
|
239
263
|
if (pendingCall) {
|
|
240
264
|
pendingToolCalls.delete(toolUseId);
|
|
241
|
-
//
|
|
242
|
-
|
|
243
|
-
// Skip displaying tool calls for plan files
|
|
244
|
-
if (fileName && fileName.includes('plans/')) {
|
|
265
|
+
// Skip displaying Edit/Write tool calls for plan files
|
|
266
|
+
if (shouldHideToolCall(pendingCall.toolName, pendingCall.input)) {
|
|
245
267
|
continue;
|
|
246
268
|
}
|
|
269
|
+
// Extract diff content and file name for Edit/Write tools
|
|
270
|
+
const { diffContent, fileName } = extractEditWriteInfo(pendingCall.toolName, pendingCall.input);
|
|
247
271
|
// Extract result summary based on tool type
|
|
248
272
|
const resultSummary = extractResultSummary(pendingCall.toolName, resultContent, pendingCall.input);
|
|
249
273
|
// Update the existing 'executing' history item with the final result (posttooluse)
|
|
@@ -291,29 +315,53 @@ export function processSDKMessage(message, options, collectedText, pendingToolCa
|
|
|
291
315
|
case 'result': {
|
|
292
316
|
if (message.subtype === 'success') {
|
|
293
317
|
logToFile('Agent completed successfully');
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
318
|
+
// When the last assistant message had only thinking content, report to session/error
|
|
319
|
+
const lastHadVisible = context?.lastAssistantHadVisibleContent !== false;
|
|
320
|
+
if (!lastHadVisible &&
|
|
321
|
+
!isInterrupting &&
|
|
322
|
+
!context?.hasCompletedWork &&
|
|
323
|
+
context?.onError &&
|
|
324
|
+
message.session_id) {
|
|
325
|
+
ui.addItem({
|
|
326
|
+
type: 'agent-message',
|
|
327
|
+
text: "I'm still thinking. Thank you for your patience.",
|
|
328
|
+
});
|
|
329
|
+
reportSessionError('Last assistant message did not have a text response.', message.session_id, context.onError);
|
|
330
|
+
context.queueFollowUpPrompt?.('[Wizard] Continue.');
|
|
300
331
|
}
|
|
301
332
|
}
|
|
302
333
|
else {
|
|
303
|
-
// Error result -
|
|
334
|
+
// Error result - collect non-interrupt errors, report once to session/error, show first in UI when not interrupting
|
|
304
335
|
logToFile('Agent error result:', message.subtype);
|
|
305
|
-
if (message.errors
|
|
336
|
+
if (message.errors) {
|
|
337
|
+
const reportableErrors = [];
|
|
338
|
+
let isFirstError = true;
|
|
306
339
|
for (const err of message.errors) {
|
|
307
|
-
// Check if error is interrupt-related
|
|
308
340
|
const errStr = String(err);
|
|
309
341
|
const isInterruptError = errStr.includes('aborted') ||
|
|
310
342
|
errStr.includes('interrupted') ||
|
|
311
343
|
errStr.includes('403');
|
|
312
344
|
if (!isInterruptError) {
|
|
313
|
-
|
|
345
|
+
reportableErrors.push(errStr);
|
|
346
|
+
if (!isInterrupting && isFirstError) {
|
|
347
|
+
ui.addItem({
|
|
348
|
+
type: 'error',
|
|
349
|
+
text: getCannedErrorDisplayText(errStr),
|
|
350
|
+
});
|
|
351
|
+
isFirstError = false;
|
|
352
|
+
}
|
|
314
353
|
}
|
|
315
354
|
logToFile('ERROR:', err);
|
|
316
355
|
}
|
|
356
|
+
if (reportableErrors.length > 0 &&
|
|
357
|
+
context?.onError &&
|
|
358
|
+
message.session_id) {
|
|
359
|
+
// Send raw error text; session/error route adds "Customer got the following error:" and code block
|
|
360
|
+
const combinedMessage = reportableErrors.length === 1
|
|
361
|
+
? reportableErrors[0]
|
|
362
|
+
: reportableErrors.join('\n\n');
|
|
363
|
+
reportSessionError(combinedMessage, message.session_id, context.onError);
|
|
364
|
+
}
|
|
317
365
|
}
|
|
318
366
|
}
|
|
319
367
|
break;
|
|
@@ -1 +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 { createTwoFilesPatch } from 'diff';\nimport { debug, logToFile } from '../utils/debug.js';\nimport type { WizardOptions } from '../utils/types.js';\nimport ui from '../utils/ui.js';\nimport type { PendingToolCall } from './handlers.js';\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 in the UI */\nconst INTERNAL_TOOL_NAMES = new Set([\n 'Task',\n 'AskUserQuestion',\n 'TodoWrite',\n 'EnterPlanMode',\n 'ExitPlanMode',\n]);\n\n/** Prefix for MCP tools; all are internal (not shown in UI). Matches mcp__server__tool and mcp____... */\nconst MCP_TOOL_PREFIX = 'mcp__';\n\nfunction isInternalTool(toolName: string): boolean {\n return (\n INTERNAL_TOOL_NAMES.has(toolName) || toolName.startsWith(MCP_TOOL_PREFIX)\n );\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 * Build a contextual spinner message based on the completed tool call.\n */\nfunction getToolSpinnerMessage(\n toolName: string,\n input: Record<string, unknown>,\n): string {\n switch (toolName) {\n case 'Grep':\n return `Analysing results`;\n case 'Read':\n return `Analysing`;\n case 'Bash':\n return `Analysing output`;\n case 'Edit':\n case 'Write':\n return `Working`;\n case 'Glob':\n return `Browsing files`;\n case 'WebSearch':\n return `Searching the web`;\n case 'WebFetch':\n return `Fetching documentation`;\n case 'EnterPlanMode':\n return `Planning`;\n default:\n if (toolName.startsWith('mcp__raindrop-wizard__Load')) {\n return `Loading Raindrop documentation`;\n }\n return `Working`;\n }\n}\n\n/**\n * Context passed into processSDKMessage for spinner updates.\n */\nexport interface SDKMessageContext {\n updateSpinner: (msg: string) => void;\n baseSpinnerMessage: string;\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 context?: SDKMessageContext,\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 // Reset spinner after assistant responds — \"Analysing\" after \"Perfect!\" looks wrong\n if (context?.updateSpinner) {\n context.updateSpinner(context.baseSpinnerMessage);\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 (including all mcp__* tools)\n if (isInternalTool(toolName)) {\n continue;\n }\n\n // Show tool as executing immediately (pretooluse)\n const historyItemId = ui.addItem({\n type: 'tool-call',\n text: toolName,\n toolCall: {\n toolName,\n status: 'executing',\n input: toolInput,\n description:\n typeof toolInput.description === 'string'\n ? toolInput.description\n : undefined,\n },\n });\n\n // Store pending tool call with history ID so we can update it on completion\n pendingToolCalls.set(toolUseId, {\n toolName,\n input: toolInput,\n description:\n typeof toolInput.description === 'string'\n ? toolInput.description\n : undefined,\n historyItemId,\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 tool calls for plan files\n if (fileName && fileName.includes('plans/')) {\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 // Update the existing 'executing' history item with the final result (posttooluse)\n const completedToolCall = {\n toolName: pendingCall.toolName,\n status: (isError ? 'error' : 'success') as 'error' | 'success',\n input: pendingCall.input,\n description: pendingCall.description,\n result: resultSummary,\n error: isError\n ? `Error: ${String(resultContent)\n .replace(/<\\/?tool_use_error>/g, '')\n .trim()}`\n : undefined,\n diffContent,\n fileName,\n };\n if (pendingCall.historyItemId !== undefined) {\n ui.updateItem(pendingCall.historyItemId, {\n type: 'tool-call',\n text: pendingCall.toolName,\n toolCall: completedToolCall,\n });\n } else {\n ui.addItem({\n type: 'tool-call',\n text: pendingCall.toolName,\n toolCall: completedToolCall,\n });\n }\n\n // Update spinner with contextual message after tool completes (skip errors)\n if (!isError && context?.updateSpinner) {\n context.updateSpinner(\n getToolSpinnerMessage(\n pendingCall.toolName,\n pendingCall.input,\n ),\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"]}
|
|
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 { createTwoFilesPatch } from 'diff';\nimport { debug, logToFile } from '../utils/debug.js';\nimport { reportSessionError } from '../utils/session.js';\nimport type { WizardOptions } from '../utils/types.js';\nimport ui from '../utils/ui.js';\nimport {\n ERROR_DISPLAY_MESSAGE,\n INTERNAL_TOOL_NAMES,\n MCP_TOOL_PREFIX,\n} from './constants.js';\nimport type { PendingToolCall } from './handlers.js';\n\n// Using `any` because typed imports from ESM modules require import attributes\n// syntax which prettier cannot parse.\ntype SDKMessage = any;\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\nfunction getToolFileName(input: Record<string, unknown>): string | undefined {\n return typeof input.file_path === 'string'\n ? input.file_path\n : typeof input.path === 'string'\n ? input.path\n : undefined;\n}\n\nfunction shouldHideToolCall(\n toolName: string,\n input: Record<string, unknown>,\n): boolean {\n if (INTERNAL_TOOL_NAMES.has(toolName) || toolName.startsWith(MCP_TOOL_PREFIX)) {\n return true;\n }\n\n if (toolName === 'Edit' || toolName === 'Write') {\n const fileName = getToolFileName(input);\n return Boolean(fileName && fileName.includes('plans/'));\n }\n\n return false;\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 = getToolFileName(input);\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 * Return canned error display text from error string (extracts optional status code).\n */\nexport function getCannedErrorDisplayText(errorText: string): string {\n const codeMatch =\n errorText.match(/^Error:\\s*(\\d+)/i) ||\n errorText.match(/^API Error:\\s*(\\d+)/i);\n const code = codeMatch?.[1];\n return ERROR_DISPLAY_MESSAGE(code);\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 * Build a contextual spinner message based on the completed tool call.\n */\nfunction getToolSpinnerMessage(\n toolName: string,\n input: Record<string, unknown>,\n): string {\n switch (toolName) {\n case 'Grep':\n return `Analysing results`;\n case 'Read':\n return `Analysing`;\n case 'Bash':\n return `Analysing output`;\n case 'Edit':\n case 'Write':\n return `Working`;\n case 'Glob':\n return `Browsing files`;\n case 'WebSearch':\n return `Searching the web`;\n case 'WebFetch':\n return `Fetching documentation`;\n case 'EnterPlanMode':\n return `Planning`;\n default:\n if (toolName.startsWith('mcp__raindrop-wizard__Load')) {\n return `Loading Raindrop documentation`;\n }\n return `Working`;\n }\n}\n\n/**\n * Context passed into processSDKMessage for spinner updates and optional error reporting.\n */\nexport interface SDKMessageContext {\n updateSpinner: (msg: string) => void;\n baseSpinnerMessage: string;\n /** When set, errors (message.error) are reported to Slack with the agent run log path. */\n onError?: {\n wizardSessionId: string;\n accessToken: string;\n orgId: string;\n /** Resolved absolute project path (e.g. /Users/.../project). */\n workingDirectory: string;\n };\n /**\n * Whether the most recently processed assistant message had any visible (text) content.\n * Set by the caller from the return value of the previous processSDKMessage call.\n * When false on a success result, we report to session/error and can queue a follow-up prompt.\n */\n lastAssistantHadVisibleContent?: boolean;\n /**\n * When set, used to queue a follow-up user message so the agent continues (e.g. after\n * last assistant had only thinking content). The prompt async iterable will yield this\n * and the agent will run another turn.\n */\n queueFollowUpPrompt?: (prompt: string) => void;\n /**\n * When true, the agent has already called CompleteIntegration and is transitioning to\n * testing. Skip queuing [Wizard] Continue. since the testing phase will handle next steps.\n */\n hasCompletedWork?: boolean;\n}\n\n/**\n * Return value from processSDKMessage when the message was an assistant message.\n * Caller should pass lastAssistantHadVisibleContent back in context on the next call.\n */\nexport interface ProcessSDKMessageResult {\n lastAssistantHadVisibleContent?: boolean;\n}\n\n/**\n * Process SDK messages and provide user feedback.\n * Handles assistant text, tool use, tool results, and system messages.\n * Returns lastAssistantHadVisibleContent when message type is 'assistant' so the caller\n * can pass it back in context for the next call (used to show a fallback on success result\n * when the last assistant had only thinking content).\n */\nexport function processSDKMessage(\n message: SDKMessage,\n options: WizardOptions,\n pendingToolCalls: Map<string, PendingToolCall>,\n isInterrupting: boolean,\n context?: SDKMessageContext,\n): ProcessSDKMessageResult | 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 let hadVisibleContent = false;\n if (Array.isArray(content)) {\n for (const block of content) {\n if (block.type === 'text' && typeof block.text === 'string') {\n hadVisibleContent = true;\n // If message.error and text looks like an error, report to Slack; use canned text in UI only for \"unknown\".\n const isError =\n message.error != null && /(API )?Error/i.test(block.text);\n const displayText =\n isError && message.error === 'unknown'\n ? getCannedErrorDisplayText(block.text)\n : block.text;\n\n if (isError && context?.onError && message.session_id) {\n reportSessionError(\n block.text,\n message.session_id as string,\n context.onError,\n );\n }\n\n ui.addItem({\n type: 'agent-message',\n text: displayText,\n });\n\n // Reset spinner after assistant responds — \"Analysing\" after \"Perfect!\" looks wrong\n if (context?.updateSpinner) {\n context.updateSpinner(context.baseSpinnerMessage);\n }\n }\n }\n // Handle tool_use blocks - store pending, don't add to history yet\n for (const block of content) {\n if (block.type === 'tool_use') {\n const toolName = block.name || 'Unknown tool';\n const toolInput = (block.input || {}) as Record<string, unknown>;\n const toolUseId = block.id;\n logToFile(\n `Tool use requested: ${toolName} (id: ${toolUseId})`,\n toolInput,\n );\n\n // Skip storing/displaying internal tools and plan-file edits\n if (shouldHideToolCall(toolName, toolInput)) {\n continue;\n }\n\n // Show tool as executing immediately (pretooluse)\n const historyItemId = ui.addItem({\n type: 'tool-call',\n text: toolName,\n toolCall: {\n toolName,\n status: 'executing',\n input: toolInput,\n description:\n typeof toolInput.description === 'string'\n ? toolInput.description\n : undefined,\n },\n });\n\n // Store pending tool call with history ID so we can update it on completion\n pendingToolCalls.set(toolUseId, {\n toolName,\n input: toolInput,\n description:\n typeof toolInput.description === 'string'\n ? toolInput.description\n : undefined,\n historyItemId,\n });\n }\n }\n }\n return { lastAssistantHadVisibleContent: hadVisibleContent };\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 // Skip displaying Edit/Write tool calls for plan files\n if (shouldHideToolCall(pendingCall.toolName, pendingCall.input)) {\n continue;\n }\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 // Extract result summary based on tool type\n const resultSummary = extractResultSummary(\n pendingCall.toolName,\n resultContent,\n pendingCall.input,\n );\n\n // Update the existing 'executing' history item with the final result (posttooluse)\n const completedToolCall = {\n toolName: pendingCall.toolName,\n status: (isError ? 'error' : 'success') as 'error' | 'success',\n input: pendingCall.input,\n description: pendingCall.description,\n result: resultSummary,\n error: isError\n ? `Error: ${String(resultContent)\n .replace(/<\\/?tool_use_error>/g, '')\n .trim()}`\n : undefined,\n diffContent,\n fileName,\n };\n if (pendingCall.historyItemId !== undefined) {\n ui.updateItem(pendingCall.historyItemId, {\n type: 'tool-call',\n text: pendingCall.toolName,\n toolCall: completedToolCall,\n });\n } else {\n ui.addItem({\n type: 'tool-call',\n text: pendingCall.toolName,\n toolCall: completedToolCall,\n });\n }\n\n // Update spinner with contextual message after tool completes (skip errors)\n if (!isError && context?.updateSpinner) {\n context.updateSpinner(\n getToolSpinnerMessage(\n pendingCall.toolName,\n pendingCall.input,\n ),\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 // When the last assistant message had only thinking content, report to session/error\n const lastHadVisible =\n context?.lastAssistantHadVisibleContent !== false;\n if (\n !lastHadVisible &&\n !isInterrupting &&\n !context?.hasCompletedWork &&\n context?.onError &&\n message.session_id\n ) {\n ui.addItem({\n type: 'agent-message',\n text: \"I'm still thinking. Thank you for your patience.\",\n });\n reportSessionError(\n 'Last assistant message did not have a text response.',\n message.session_id as string,\n context.onError,\n );\n context.queueFollowUpPrompt?.('[Wizard] Continue.');\n }\n } else {\n // Error result - collect non-interrupt errors, report once to session/error, show first in UI when not interrupting\n logToFile('Agent error result:', message.subtype);\n if (message.errors) {\n const reportableErrors: string[] = [];\n let isFirstError = true;\n for (const err of message.errors) {\n const errStr = String(err);\n const isInterruptError =\n errStr.includes('aborted') ||\n errStr.includes('interrupted') ||\n errStr.includes('403');\n if (!isInterruptError) {\n reportableErrors.push(errStr);\n if (!isInterrupting && isFirstError) {\n ui.addItem({\n type: 'error',\n text: getCannedErrorDisplayText(errStr),\n });\n isFirstError = false;\n }\n }\n logToFile('ERROR:', err);\n }\n if (\n reportableErrors.length > 0 &&\n context?.onError &&\n message.session_id\n ) {\n // Send raw error text; session/error route adds \"Customer got the following error:\" and code block\n const combinedMessage =\n reportableErrors.length === 1\n ? reportableErrors[0]\n : reportableErrors.join('\\n\\n');\n reportSessionError(\n combinedMessage,\n message.session_id as string,\n context.onError,\n );\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"]}
|
package/dist/src/lib/wizard.js
CHANGED
|
@@ -92,7 +92,7 @@ export async function runWizard(options) {
|
|
|
92
92
|
const agent = initializeAgent({
|
|
93
93
|
workingDirectory: options.installDir,
|
|
94
94
|
}, options);
|
|
95
|
-
const agentResult = await runAgentLoop(agent, `Your WIZARD SESSION ID is ${options.sessionId}. Begin the integration.`, options, {
|
|
95
|
+
const agentResult = await runAgentLoop(agent, `[Wizard] Your WIZARD SESSION ID is ${options.sessionId}. Begin the integration.`, options, {
|
|
96
96
|
spinnerMessage: SPINNER_MESSAGE,
|
|
97
97
|
accessToken: token.token,
|
|
98
98
|
orgId: token.orgId.toString(),
|