@raindrop-ai/wizard 0.0.4 → 0.0.6
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/lib/agent-interface.d.ts +1 -1
- package/dist/src/lib/agent-interface.js +27 -6
- package/dist/src/lib/agent-interface.js.map +1 -1
- package/dist/src/lib/constants.d.ts +9 -8
- package/dist/src/lib/constants.js +14 -13
- package/dist/src/lib/constants.js.map +1 -1
- package/dist/src/lib/integration-testing.d.ts +1 -0
- package/dist/src/lib/integration-testing.js +58 -11
- package/dist/src/lib/integration-testing.js.map +1 -1
- package/dist/src/lib/wizard.js +6 -5
- package/dist/src/lib/wizard.js.map +1 -1
- package/dist/src/ui/components/FeedbackSelectPrompt.js +5 -3
- package/dist/src/ui/components/FeedbackSelectPrompt.js.map +1 -1
- package/dist/src/ui/types.d.ts +1 -0
- package/dist/src/ui/types.js.map +1 -1
- package/dist/src/utils/session.d.ts +1 -1
- package/dist/src/utils/session.js.map +1 -1
- package/package.json +3 -3
|
@@ -15,6 +15,7 @@ export interface AgentRunResult {
|
|
|
15
15
|
sessionId?: string;
|
|
16
16
|
handle: AgentQueryHandle;
|
|
17
17
|
completed: boolean;
|
|
18
|
+
support?: boolean;
|
|
18
19
|
}
|
|
19
20
|
/**
|
|
20
21
|
* Internal configuration object returned by initializeAgent
|
|
@@ -32,7 +33,6 @@ export declare function initializeAgent(config: AgentConfig, options: WizardOpti
|
|
|
32
33
|
*/
|
|
33
34
|
export interface RunAgentConfig {
|
|
34
35
|
spinnerMessage?: string;
|
|
35
|
-
successMessage?: string;
|
|
36
36
|
accessToken: string;
|
|
37
37
|
orgId: string;
|
|
38
38
|
onCompleteIntegration?: () => Promise<boolean | string>;
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { query } from '@anthropic-ai/claude-agent-sdk';
|
|
6
6
|
import { createRequire } from 'module';
|
|
7
|
+
import { existsSync, writeFileSync } from 'fs';
|
|
8
|
+
import os from 'os';
|
|
7
9
|
import path from 'path';
|
|
8
10
|
import { debug, initLogFile, LOG_FILE_PATH, logToFile, } from '../utils/debug.js';
|
|
9
11
|
import ui from '../utils/ui.js';
|
|
@@ -21,6 +23,18 @@ function getClaudeCodeExecutablePath() {
|
|
|
21
23
|
const sdkPackagePath = require.resolve('@anthropic-ai/claude-agent-sdk');
|
|
22
24
|
return path.join(path.dirname(sdkPackagePath), 'cli.js');
|
|
23
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* Ensure Claude CLI has a config file to read during startup.
|
|
28
|
+
* Some SDK/CLI versions error if ~/.claude.json is missing.
|
|
29
|
+
*/
|
|
30
|
+
function ensureClaudeConfigFileExists() {
|
|
31
|
+
const claudeConfigPath = path.join(os.homedir(), '.claude.json');
|
|
32
|
+
if (existsSync(claudeConfigPath)) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
writeFileSync(claudeConfigPath, '{}\n', { encoding: 'utf-8' });
|
|
36
|
+
logToFile('Created missing Claude config file:', claudeConfigPath);
|
|
37
|
+
}
|
|
24
38
|
/**
|
|
25
39
|
* Async queue for user messages.
|
|
26
40
|
* Messages are pushed by UI callbacks and consumed by the SDK as an async iterable.
|
|
@@ -85,6 +99,7 @@ export function initializeAgent(config, options) {
|
|
|
85
99
|
logToFile('Agent initialization starting');
|
|
86
100
|
logToFile('Install directory:', options.installDir);
|
|
87
101
|
try {
|
|
102
|
+
ensureClaudeConfigFileExists();
|
|
88
103
|
process.env.MAX_THINKING_TOKENS = '10000';
|
|
89
104
|
process.env.CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS = 'true';
|
|
90
105
|
// Set default subagent model to Sonnet
|
|
@@ -125,7 +140,7 @@ export function initializeAgent(config, options) {
|
|
|
125
140
|
* @returns Session ID and query handle for controlling the agent
|
|
126
141
|
*/
|
|
127
142
|
export async function runAgentLoop(agentConfig, prompt, options, config) {
|
|
128
|
-
const { spinnerMessage = 'Raindrop wizard is working...',
|
|
143
|
+
const { spinnerMessage = 'Raindrop wizard is working...', accessToken, orgId, onCompleteIntegration, } = config;
|
|
129
144
|
// Add header to indicate start of interactive agent phase
|
|
130
145
|
ui.addItem({ type: 'phase', text: '─── Agent ───' });
|
|
131
146
|
const cliPath = getClaudeCodeExecutablePath();
|
|
@@ -146,6 +161,7 @@ export async function runAgentLoop(agentConfig, prompt, options, config) {
|
|
|
146
161
|
let isSpinnerRunning = false;
|
|
147
162
|
let completed = false;
|
|
148
163
|
let shouldEndSession = false;
|
|
164
|
+
let supportRequested = false;
|
|
149
165
|
const spinner = ui.spinner();
|
|
150
166
|
// Track current spinner base message and when it last changed.
|
|
151
167
|
let currentSpinnerMsg = spinnerMessage;
|
|
@@ -324,6 +340,14 @@ export async function runAgentLoop(agentConfig, prompt, options, config) {
|
|
|
324
340
|
const completionDecision = onCompleteIntegration
|
|
325
341
|
? await onCompleteIntegration()
|
|
326
342
|
: true;
|
|
343
|
+
if (completionDecision === 'support') {
|
|
344
|
+
logToFile('User requested support - ending session');
|
|
345
|
+
completed = false;
|
|
346
|
+
supportRequested = true;
|
|
347
|
+
shouldEndSession = true;
|
|
348
|
+
inputQueue.close();
|
|
349
|
+
break;
|
|
350
|
+
}
|
|
327
351
|
if (typeof completionDecision === 'string') {
|
|
328
352
|
const feedbackPrompt = completionDecision.trim();
|
|
329
353
|
if (!feedbackPrompt) {
|
|
@@ -374,12 +398,9 @@ export async function runAgentLoop(agentConfig, prompt, options, config) {
|
|
|
374
398
|
}
|
|
375
399
|
ui.stopPersistentInput();
|
|
376
400
|
ui.setAgentState({ isRunning: false });
|
|
377
|
-
if (completed) {
|
|
378
|
-
spinner.stop(successMessage);
|
|
379
|
-
}
|
|
380
|
-
else if (isSpinnerRunning) {
|
|
401
|
+
if (completed || isSpinnerRunning) {
|
|
381
402
|
spinner.stop();
|
|
382
403
|
}
|
|
383
|
-
return { sessionId, handle, completed };
|
|
404
|
+
return { sessionId, handle, completed, support: supportRequested };
|
|
384
405
|
}
|
|
385
406
|
//# sourceMappingURL=agent-interface.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-interface.js","sourceRoot":"","sources":["../../../src/lib/agent-interface.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Shared agent interface for wizards\n * Uses Claude Agent SDK directly with streaming input support\n */\n\nimport { query, type SDKUserMessage } from '@anthropic-ai/claude-agent-sdk';\nimport { createRequire } from 'module';\nimport path from 'path';\nimport type { AgentQueryHandle } from '../ui/types.js';\nimport {\n debug,\n initLogFile,\n LOG_FILE_PATH,\n logToFile,\n} from '../utils/debug.js';\nimport type { WizardOptions } from '../utils/types.js';\nimport ui from '../utils/ui.js';\nimport {\n createAgentQueryHandle,\n createCanUseToolHandler,\n createPreToolUseHook,\n type PendingToolCall,\n type SessionInfo,\n} from './handlers.js';\nimport { createMcpServer } from './mcp.js';\nimport { processSDKMessage } from './sdk-messages.js';\n\n// Create a require function for ESM compatibility\nconst require = createRequire(import.meta.url);\n\n/**\n * Get the path to the bundled Claude Code CLI from the SDK package.\n * This ensures we use the SDK's bundled version rather than the user's installed Claude Code.\n */\nfunction getClaudeCodeExecutablePath(): string {\n // require.resolve finds the package's main entry, then we get cli.js from same dir\n const sdkPackagePath = require.resolve('@anthropic-ai/claude-agent-sdk');\n return path.join(path.dirname(sdkPackagePath), 'cli.js');\n}\n\n// Re-export AgentQueryHandle for external use\nexport type { AgentQueryHandle };\n\nexport type AgentConfig = {\n workingDirectory: string;\n};\n\n/**\n * Result from runAgentLoop including session ID and query handle\n */\nexport interface AgentRunResult {\n sessionId?: string;\n handle: AgentQueryHandle;\n completed: boolean;\n}\n\n/**\n * Internal configuration object returned by initializeAgent\n */\nexport type AgentRunConfig = {\n workingDirectory: string;\n model: string;\n};\n\ntype QueuedUserMessage = {\n type: 'user';\n message: {\n role: 'user';\n content: string;\n };\n};\n\ntype QueryMessage = {\n type?: string;\n session_id?: string;\n [key: string]: unknown;\n};\n\ntype QueryObject = AsyncIterable<QueryMessage> & {\n interrupt?: () => Promise<void>;\n};\n\n/**\n * Async queue for user messages.\n * Messages are pushed by UI callbacks and consumed by the SDK as an async iterable.\n */\nclass UserMessageQueue implements AsyncIterable<QueuedUserMessage> {\n private messages: QueuedUserMessage[] = [];\n\n private waitingResolver:\n | ((message: QueuedUserMessage | null) => void)\n | null = null;\n\n private closed = false;\n\n push(content: string): void {\n if (this.closed) {\n return;\n }\n\n const message: QueuedUserMessage = {\n type: 'user',\n message: {\n role: 'user',\n content,\n },\n };\n\n if (this.waitingResolver) {\n this.waitingResolver(message);\n this.waitingResolver = null;\n return;\n }\n\n this.messages.push(message);\n }\n\n hasPending(): boolean {\n return this.messages.length > 0;\n }\n\n close(): void {\n this.closed = true;\n if (this.waitingResolver) {\n this.waitingResolver(null);\n this.waitingResolver = null;\n }\n }\n\n async *[Symbol.asyncIterator](): AsyncIterableIterator<QueuedUserMessage> {\n while (!this.closed) {\n if (this.messages.length > 0) {\n const nextMessage = this.messages.shift();\n if (nextMessage) {\n yield nextMessage;\n }\n continue;\n }\n\n const nextMessage = await new Promise<QueuedUserMessage | null>(\n (resolve) => {\n this.waitingResolver = resolve;\n },\n );\n\n if (!nextMessage) {\n return;\n }\n\n yield nextMessage;\n }\n }\n}\n\n/**\n * Initialize agent configuration for the Claude agent\n */\nexport function initializeAgent(\n config: AgentConfig,\n options: WizardOptions,\n): AgentRunConfig {\n // Initialize log file for this run\n initLogFile();\n logToFile('Agent initialization starting');\n logToFile('Install directory:', options.installDir);\n\n try {\n process.env.MAX_THINKING_TOKENS = '10000';\n process.env.CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS = 'true';\n // Set default subagent model to Sonnet\n process.env.CLAUDE_CODE_SUBAGENT_MODEL = 'claude-sonnet-4-5-20250929';\n\n const agentRunConfig: AgentRunConfig = {\n workingDirectory: config.workingDirectory,\n model: 'sonnet',\n };\n\n logToFile('Agent config:', {\n workingDirectory: agentRunConfig.workingDirectory,\n });\n\n if (options.debug) {\n debug('Agent config:', {\n workingDirectory: agentRunConfig.workingDirectory,\n });\n }\n\n ui.addItem({\n type: 'step',\n text: `I'll keep verbose logs for this session at: ${LOG_FILE_PATH}`,\n });\n return agentRunConfig;\n } catch (error) {\n ui.addItem({\n type: 'error',\n text: `Failed to initialize agent: ${(error as Error).message}`,\n });\n logToFile('Agent initialization error:', error);\n debug('Agent initialization error:', error);\n throw error;\n }\n}\n\n/**\n * Configuration for runAgentLoop\n */\nexport interface RunAgentConfig {\n spinnerMessage?: string;\n successMessage?: string;\n accessToken: string;\n orgId: string;\n onCompleteIntegration?: () => Promise<boolean | string>;\n}\n\n/**\n * Execute an agent with the provided prompt and options.\n * Supports streaming input for user interruption and follow-up messages.\n * Uses a single long-lived SDK query fed by an async message queue.\n *\n * @returns Session ID and query handle for controlling the agent\n */\nexport async function runAgentLoop(\n agentConfig: AgentRunConfig,\n prompt: string,\n options: WizardOptions,\n config: RunAgentConfig,\n): Promise<AgentRunResult> {\n const {\n spinnerMessage = 'Raindrop wizard is working...',\n successMessage = 'Raindrop integration complete',\n accessToken,\n orgId,\n onCompleteIntegration,\n } = config;\n\n // Add header to indicate start of interactive agent phase\n ui.addItem({ type: 'phase', text: '─── Agent ───' });\n\n const cliPath = getClaudeCodeExecutablePath();\n logToFile('Starting agent run');\n logToFile('Claude Code executable:', cliPath);\n\n const startTime = Date.now();\n const inputQueue = new UserMessageQueue();\n inputQueue.push(prompt);\n\n const approvedFilesCache = new Set<string>();\n const collectedText: string[] = [];\n const pendingToolCalls = new Map<string, PendingToolCall>();\n\n const hasCompletedWorkRef = { value: false };\n const isInterruptingRef = { value: false };\n const waitingForUserInputRef = { value: false };\n const exitHintShownRef = { value: false };\n\n let sessionId: string | undefined;\n let queryObject: QueryObject | null = null;\n let isSpinnerRunning = false;\n let completed = false;\n let shouldEndSession = false;\n\n const spinner = ui.spinner();\n\n // Track current spinner base message and when it last changed.\n let currentSpinnerMsg = spinnerMessage;\n let lastActivityTime = Date.now();\n\n const updateSpinner = (msg: string) => {\n if (!isSpinnerRunning) return;\n currentSpinnerMsg = msg;\n lastActivityTime = Date.now();\n spinner.message(msg);\n };\n\n // Every second, if the agent has been silent for >= 10s, append a counting thinking indicator.\n // Pure JS interval — Ink only re-renders when the string actually changes.\n const thinkingTimer = setInterval(() => {\n if (!isSpinnerRunning) return;\n const idleS = Math.floor((Date.now() - lastActivityTime) / 1000);\n if (idleS >= 20) {\n const mins = Math.floor(idleS / 60);\n const secs = idleS % 60;\n const timeStr = mins > 0 ? `${mins}m ${secs}s` : `${secs}s`;\n spinner.message(`${currentSpinnerMsg} (thinking · ${timeStr})`);\n }\n }, 1000);\n\n const setAgentRunning = (isRunning: boolean) => {\n if (isRunning) {\n if (!isSpinnerRunning) {\n spinner.start(spinnerMessage);\n isSpinnerRunning = true;\n }\n ui.setAgentState({ isRunning: true });\n return;\n }\n\n if (isSpinnerRunning) {\n spinner.stop();\n isSpinnerRunning = false;\n }\n ui.setAgentState({ isRunning: false });\n };\n\n // Create MCP server with CompleteIntegration tool\n const toolsMcpServer = createMcpServer(hasCompletedWorkRef, {\n sessionId: options.sessionId,\n accessToken,\n orgId,\n installDir: agentConfig.workingDirectory,\n });\n\n // Session info for notifications\n const sessionInfo: SessionInfo = {\n sessionId: options.sessionId,\n accessToken,\n orgId,\n };\n\n const handle = createAgentQueryHandle({\n isInterruptingRef,\n waitingForUserInputRef,\n pendingToolCalls,\n getQueryObject: () => queryObject,\n sendMessage: (message: string) => {\n inputQueue.push(message);\n },\n });\n\n const startPersistentInput = (placeholder?: string) => {\n ui.startPersistentInput({\n onSubmit: handlePersistentSubmit,\n onInterrupt: handlePersistentInterrupt,\n onCtrlC: handlePersistentCtrlC,\n placeholder,\n });\n };\n\n // Define callbacks for persistent input\n const handlePersistentSubmit = (message: string) => {\n const trimmedMessage = message.trim();\n if (!trimmedMessage) {\n return;\n }\n\n exitHintShownRef.value = false;\n\n ui.addItem({\n type: 'user-message',\n text: trimmedMessage,\n });\n\n handle.sendMessage(trimmedMessage);\n\n if (waitingForUserInputRef.value) {\n waitingForUserInputRef.value = false;\n isInterruptingRef.value = false;\n setAgentRunning(true);\n return;\n }\n\n if (!isInterruptingRef.value) {\n logToFile(\n 'User submitted message while agent is running - interrupting current turn',\n );\n void handle.interrupt(true);\n }\n };\n\n const handlePersistentInterrupt = () => {\n logToFile('User requested interrupt (Esc)');\n setAgentRunning(false);\n void handle.interrupt();\n };\n\n const handlePersistentCtrlC = () => {\n logToFile('User pressed Ctrl+C');\n\n // If already interrupted and exit hint was shown, exit immediately\n if (\n (isInterruptingRef.value || waitingForUserInputRef.value) &&\n exitHintShownRef.value\n ) {\n logToFile('Second Ctrl+C - exiting');\n ui.stopPersistentInput();\n ui.exit();\n // Small delay to allow UI to clean up before exit\n setTimeout(() => process.exit(130), 100);\n return;\n }\n\n // If already interrupted but hint not shown yet, show hint and clear input\n if (isInterruptingRef.value || waitingForUserInputRef.value) {\n logToFile('First Ctrl+C while interrupted - showing exit hint');\n exitHintShownRef.value = true;\n ui.stopPersistentInput();\n startPersistentInput('Press Ctrl+C again to exit');\n return;\n }\n\n // Not interrupted yet - treat as normal interrupt\n logToFile('First Ctrl+C - triggering interrupt');\n setAgentRunning(false);\n void handle.interrupt();\n };\n\n startPersistentInput();\n setAgentRunning(true);\n\n queryObject = query({\n prompt: inputQueue as unknown as AsyncIterable<SDKUserMessage>,\n options: {\n model: agentConfig.model,\n cwd: agentConfig.workingDirectory,\n permissionMode: 'default',\n mcpServers: {\n 'raindrop-wizard': toolsMcpServer,\n },\n systemPrompt: '{WIZARD_SYSTEM_PROMPT}',\n env: { ...process.env },\n canUseTool: createCanUseToolHandler(approvedFilesCache),\n hooks: {\n PreToolUse: [{ hooks: [createPreToolUseHook(sessionInfo)] }],\n },\n stderr: (data: string) => {\n logToFile('CLI stderr:', data);\n if (options.debug) {\n debug('CLI stderr:', data);\n }\n },\n },\n }) as QueryObject;\n\n // Update agent state\n ui.setAgentState({\n isRunning: true,\n queryHandle: handle,\n });\n\n try {\n for await (const message of queryObject) {\n // Capture session_id from any message\n if (message.session_id && !sessionId) {\n sessionId = message.session_id;\n ui.setAgentState({ sessionId });\n }\n\n // If we were waiting for user input but got a new message,\n // the queued message has started processing.\n if (\n waitingForUserInputRef.value &&\n !isInterruptingRef.value &&\n message.type !== 'result'\n ) {\n waitingForUserInputRef.value = false;\n isInterruptingRef.value = false;\n setAgentRunning(true);\n }\n\n processSDKMessage(\n message,\n options,\n collectedText,\n pendingToolCalls,\n isInterruptingRef.value,\n { updateSpinner, baseSpinnerMessage: spinnerMessage },\n );\n\n if (message.type !== 'result') {\n continue;\n }\n\n if (hasCompletedWorkRef.value) {\n setAgentRunning(false);\n ui.stopPersistentInput();\n\n const completionDecision = onCompleteIntegration\n ? await onCompleteIntegration()\n : true;\n\n if (typeof completionDecision === 'string') {\n const feedbackPrompt = completionDecision.trim();\n if (!feedbackPrompt) {\n logToFile('Received empty feedback prompt - ending session');\n completed = false;\n shouldEndSession = true;\n inputQueue.close();\n break;\n }\n\n logToFile('Received testing feedback - queueing feedback prompt');\n hasCompletedWorkRef.value = false;\n waitingForUserInputRef.value = false;\n isInterruptingRef.value = false;\n handle.sendMessage(feedbackPrompt);\n startPersistentInput();\n setAgentRunning(true);\n continue;\n }\n\n completed = completionDecision;\n shouldEndSession = true;\n inputQueue.close();\n break;\n }\n\n // Turn ended without completion. If there are no queued messages,\n // we are waiting for the user to submit the next one.\n isInterruptingRef.value = false;\n\n if (!inputQueue.hasPending()) {\n waitingForUserInputRef.value = true;\n setAgentRunning(false);\n } else {\n waitingForUserInputRef.value = false;\n setAgentRunning(true);\n }\n }\n } finally {\n inputQueue.close();\n clearInterval(thinkingTimer);\n }\n\n const durationMs = Date.now() - startTime;\n logToFile(`Agent session completed in ${Math.round(durationMs / 1000)}s`);\n logToFile('Session ID:', sessionId);\n logToFile('Completion status:', hasCompletedWorkRef.value);\n\n if (!shouldEndSession && hasCompletedWorkRef.value) {\n // Fallback: if stream ended after completion, mark as completed.\n completed = true;\n }\n\n ui.stopPersistentInput();\n ui.setAgentState({ isRunning: false });\n\n if (completed) {\n spinner.stop(successMessage);\n } else if (isSpinnerRunning) {\n spinner.stop();\n }\n\n return { sessionId, handle, completed };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"agent-interface.js","sourceRoot":"","sources":["../../../src/lib/agent-interface.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Shared agent interface for wizards\n * Uses Claude Agent SDK directly with streaming input support\n */\n\nimport { query, type SDKUserMessage } from '@anthropic-ai/claude-agent-sdk';\nimport { createRequire } from 'module';\nimport { existsSync, writeFileSync } from 'fs';\nimport os from 'os';\nimport path from 'path';\nimport type { AgentQueryHandle } from '../ui/types.js';\nimport {\n debug,\n initLogFile,\n LOG_FILE_PATH,\n logToFile,\n} from '../utils/debug.js';\nimport type { WizardOptions } from '../utils/types.js';\nimport ui from '../utils/ui.js';\nimport {\n createAgentQueryHandle,\n createCanUseToolHandler,\n createPreToolUseHook,\n type PendingToolCall,\n type SessionInfo,\n} from './handlers.js';\nimport { createMcpServer } from './mcp.js';\nimport { processSDKMessage } from './sdk-messages.js';\n\n// Create a require function for ESM compatibility\nconst require = createRequire(import.meta.url);\n\n/**\n * Get the path to the bundled Claude Code CLI from the SDK package.\n * This ensures we use the SDK's bundled version rather than the user's installed Claude Code.\n */\nfunction getClaudeCodeExecutablePath(): string {\n // require.resolve finds the package's main entry, then we get cli.js from same dir\n const sdkPackagePath = require.resolve('@anthropic-ai/claude-agent-sdk');\n return path.join(path.dirname(sdkPackagePath), 'cli.js');\n}\n\n/**\n * Ensure Claude CLI has a config file to read during startup.\n * Some SDK/CLI versions error if ~/.claude.json is missing.\n */\nfunction ensureClaudeConfigFileExists(): void {\n const claudeConfigPath = path.join(os.homedir(), '.claude.json');\n if (existsSync(claudeConfigPath)) {\n return;\n }\n\n writeFileSync(claudeConfigPath, '{}\\n', { encoding: 'utf-8' });\n logToFile('Created missing Claude config file:', claudeConfigPath);\n}\n\n// Re-export AgentQueryHandle for external use\nexport type { AgentQueryHandle };\n\nexport type AgentConfig = {\n workingDirectory: string;\n};\n\n/**\n * Result from runAgentLoop including session ID and query handle\n */\nexport interface AgentRunResult {\n sessionId?: string;\n handle: AgentQueryHandle;\n completed: boolean;\n support?: boolean;\n}\n\n/**\n * Internal configuration object returned by initializeAgent\n */\nexport type AgentRunConfig = {\n workingDirectory: string;\n model: string;\n};\n\ntype QueuedUserMessage = {\n type: 'user';\n message: {\n role: 'user';\n content: string;\n };\n};\n\ntype QueryMessage = {\n type?: string;\n session_id?: string;\n [key: string]: unknown;\n};\n\ntype QueryObject = AsyncIterable<QueryMessage> & {\n interrupt?: () => Promise<void>;\n};\n\n/**\n * Async queue for user messages.\n * Messages are pushed by UI callbacks and consumed by the SDK as an async iterable.\n */\nclass UserMessageQueue implements AsyncIterable<QueuedUserMessage> {\n private messages: QueuedUserMessage[] = [];\n\n private waitingResolver:\n | ((message: QueuedUserMessage | null) => void)\n | null = null;\n\n private closed = false;\n\n push(content: string): void {\n if (this.closed) {\n return;\n }\n\n const message: QueuedUserMessage = {\n type: 'user',\n message: {\n role: 'user',\n content,\n },\n };\n\n if (this.waitingResolver) {\n this.waitingResolver(message);\n this.waitingResolver = null;\n return;\n }\n\n this.messages.push(message);\n }\n\n hasPending(): boolean {\n return this.messages.length > 0;\n }\n\n close(): void {\n this.closed = true;\n if (this.waitingResolver) {\n this.waitingResolver(null);\n this.waitingResolver = null;\n }\n }\n\n async *[Symbol.asyncIterator](): AsyncIterableIterator<QueuedUserMessage> {\n while (!this.closed) {\n if (this.messages.length > 0) {\n const nextMessage = this.messages.shift();\n if (nextMessage) {\n yield nextMessage;\n }\n continue;\n }\n\n const nextMessage = await new Promise<QueuedUserMessage | null>(\n (resolve) => {\n this.waitingResolver = resolve;\n },\n );\n\n if (!nextMessage) {\n return;\n }\n\n yield nextMessage;\n }\n }\n}\n\n/**\n * Initialize agent configuration for the Claude agent\n */\nexport function initializeAgent(\n config: AgentConfig,\n options: WizardOptions,\n): AgentRunConfig {\n // Initialize log file for this run\n initLogFile();\n logToFile('Agent initialization starting');\n logToFile('Install directory:', options.installDir);\n\n try {\n ensureClaudeConfigFileExists();\n process.env.MAX_THINKING_TOKENS = '10000';\n process.env.CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS = 'true';\n // Set default subagent model to Sonnet\n process.env.CLAUDE_CODE_SUBAGENT_MODEL = 'claude-sonnet-4-5-20250929';\n\n const agentRunConfig: AgentRunConfig = {\n workingDirectory: config.workingDirectory,\n model: 'sonnet',\n };\n\n logToFile('Agent config:', {\n workingDirectory: agentRunConfig.workingDirectory,\n });\n\n if (options.debug) {\n debug('Agent config:', {\n workingDirectory: agentRunConfig.workingDirectory,\n });\n }\n\n ui.addItem({\n type: 'step',\n text: `I'll keep verbose logs for this session at: ${LOG_FILE_PATH}`,\n });\n return agentRunConfig;\n } catch (error) {\n ui.addItem({\n type: 'error',\n text: `Failed to initialize agent: ${(error as Error).message}`,\n });\n logToFile('Agent initialization error:', error);\n debug('Agent initialization error:', error);\n throw error;\n }\n}\n\n/**\n * Configuration for runAgentLoop\n */\nexport interface RunAgentConfig {\n spinnerMessage?: string;\n accessToken: string;\n orgId: string;\n onCompleteIntegration?: () => Promise<boolean | string>;\n}\n\n/**\n * Execute an agent with the provided prompt and options.\n * Supports streaming input for user interruption and follow-up messages.\n * Uses a single long-lived SDK query fed by an async message queue.\n *\n * @returns Session ID and query handle for controlling the agent\n */\nexport async function runAgentLoop(\n agentConfig: AgentRunConfig,\n prompt: string,\n options: WizardOptions,\n config: RunAgentConfig,\n): Promise<AgentRunResult> {\n const {\n spinnerMessage = 'Raindrop wizard is working...',\n accessToken,\n orgId,\n onCompleteIntegration,\n } = config;\n\n // Add header to indicate start of interactive agent phase\n ui.addItem({ type: 'phase', text: '─── Agent ───' });\n\n const cliPath = getClaudeCodeExecutablePath();\n logToFile('Starting agent run');\n logToFile('Claude Code executable:', cliPath);\n\n const startTime = Date.now();\n const inputQueue = new UserMessageQueue();\n inputQueue.push(prompt);\n\n const approvedFilesCache = new Set<string>();\n const collectedText: string[] = [];\n const pendingToolCalls = new Map<string, PendingToolCall>();\n\n const hasCompletedWorkRef = { value: false };\n const isInterruptingRef = { value: false };\n const waitingForUserInputRef = { value: false };\n const exitHintShownRef = { value: false };\n\n let sessionId: string | undefined;\n let queryObject: QueryObject | null = null;\n let isSpinnerRunning = false;\n let completed = false;\n let shouldEndSession = false;\n let supportRequested = false;\n\n const spinner = ui.spinner();\n\n // Track current spinner base message and when it last changed.\n let currentSpinnerMsg = spinnerMessage;\n let lastActivityTime = Date.now();\n\n const updateSpinner = (msg: string) => {\n if (!isSpinnerRunning) return;\n currentSpinnerMsg = msg;\n lastActivityTime = Date.now();\n spinner.message(msg);\n };\n\n // Every second, if the agent has been silent for >= 10s, append a counting thinking indicator.\n // Pure JS interval — Ink only re-renders when the string actually changes.\n const thinkingTimer = setInterval(() => {\n if (!isSpinnerRunning) return;\n const idleS = Math.floor((Date.now() - lastActivityTime) / 1000);\n if (idleS >= 20) {\n const mins = Math.floor(idleS / 60);\n const secs = idleS % 60;\n const timeStr = mins > 0 ? `${mins}m ${secs}s` : `${secs}s`;\n spinner.message(`${currentSpinnerMsg} (thinking · ${timeStr})`);\n }\n }, 1000);\n\n const setAgentRunning = (isRunning: boolean) => {\n if (isRunning) {\n if (!isSpinnerRunning) {\n spinner.start(spinnerMessage);\n isSpinnerRunning = true;\n }\n ui.setAgentState({ isRunning: true });\n return;\n }\n\n if (isSpinnerRunning) {\n spinner.stop();\n isSpinnerRunning = false;\n }\n ui.setAgentState({ isRunning: false });\n };\n\n // Create MCP server with CompleteIntegration tool\n const toolsMcpServer = createMcpServer(hasCompletedWorkRef, {\n sessionId: options.sessionId,\n accessToken,\n orgId,\n installDir: agentConfig.workingDirectory,\n });\n\n // Session info for notifications\n const sessionInfo: SessionInfo = {\n sessionId: options.sessionId,\n accessToken,\n orgId,\n };\n\n const handle = createAgentQueryHandle({\n isInterruptingRef,\n waitingForUserInputRef,\n pendingToolCalls,\n getQueryObject: () => queryObject,\n sendMessage: (message: string) => {\n inputQueue.push(message);\n },\n });\n\n const startPersistentInput = (placeholder?: string) => {\n ui.startPersistentInput({\n onSubmit: handlePersistentSubmit,\n onInterrupt: handlePersistentInterrupt,\n onCtrlC: handlePersistentCtrlC,\n placeholder,\n });\n };\n\n // Define callbacks for persistent input\n const handlePersistentSubmit = (message: string) => {\n const trimmedMessage = message.trim();\n if (!trimmedMessage) {\n return;\n }\n\n exitHintShownRef.value = false;\n\n ui.addItem({\n type: 'user-message',\n text: trimmedMessage,\n });\n\n handle.sendMessage(trimmedMessage);\n\n if (waitingForUserInputRef.value) {\n waitingForUserInputRef.value = false;\n isInterruptingRef.value = false;\n setAgentRunning(true);\n return;\n }\n\n if (!isInterruptingRef.value) {\n logToFile(\n 'User submitted message while agent is running - interrupting current turn',\n );\n void handle.interrupt(true);\n }\n };\n\n const handlePersistentInterrupt = () => {\n logToFile('User requested interrupt (Esc)');\n setAgentRunning(false);\n void handle.interrupt();\n };\n\n const handlePersistentCtrlC = () => {\n logToFile('User pressed Ctrl+C');\n\n // If already interrupted and exit hint was shown, exit immediately\n if (\n (isInterruptingRef.value || waitingForUserInputRef.value) &&\n exitHintShownRef.value\n ) {\n logToFile('Second Ctrl+C - exiting');\n ui.stopPersistentInput();\n ui.exit();\n // Small delay to allow UI to clean up before exit\n setTimeout(() => process.exit(130), 100);\n return;\n }\n\n // If already interrupted but hint not shown yet, show hint and clear input\n if (isInterruptingRef.value || waitingForUserInputRef.value) {\n logToFile('First Ctrl+C while interrupted - showing exit hint');\n exitHintShownRef.value = true;\n ui.stopPersistentInput();\n startPersistentInput('Press Ctrl+C again to exit');\n return;\n }\n\n // Not interrupted yet - treat as normal interrupt\n logToFile('First Ctrl+C - triggering interrupt');\n setAgentRunning(false);\n void handle.interrupt();\n };\n\n startPersistentInput();\n setAgentRunning(true);\n\n queryObject = query({\n prompt: inputQueue as unknown as AsyncIterable<SDKUserMessage>,\n options: {\n model: agentConfig.model,\n cwd: agentConfig.workingDirectory,\n permissionMode: 'default',\n mcpServers: {\n 'raindrop-wizard': toolsMcpServer,\n },\n systemPrompt: '{WIZARD_SYSTEM_PROMPT}',\n env: { ...process.env },\n canUseTool: createCanUseToolHandler(approvedFilesCache),\n hooks: {\n PreToolUse: [{ hooks: [createPreToolUseHook(sessionInfo)] }],\n },\n stderr: (data: string) => {\n logToFile('CLI stderr:', data);\n if (options.debug) {\n debug('CLI stderr:', data);\n }\n },\n },\n }) as QueryObject;\n\n // Update agent state\n ui.setAgentState({\n isRunning: true,\n queryHandle: handle,\n });\n\n try {\n for await (const message of queryObject) {\n // Capture session_id from any message\n if (message.session_id && !sessionId) {\n sessionId = message.session_id;\n ui.setAgentState({ sessionId });\n }\n\n // If we were waiting for user input but got a new message,\n // the queued message has started processing.\n if (\n waitingForUserInputRef.value &&\n !isInterruptingRef.value &&\n message.type !== 'result'\n ) {\n waitingForUserInputRef.value = false;\n isInterruptingRef.value = false;\n setAgentRunning(true);\n }\n\n processSDKMessage(\n message,\n options,\n collectedText,\n pendingToolCalls,\n isInterruptingRef.value,\n { updateSpinner, baseSpinnerMessage: spinnerMessage },\n );\n\n if (message.type !== 'result') {\n continue;\n }\n\n if (hasCompletedWorkRef.value) {\n setAgentRunning(false);\n ui.stopPersistentInput();\n\n const completionDecision = onCompleteIntegration\n ? await onCompleteIntegration()\n : true;\n\n if (completionDecision === 'support') {\n logToFile('User requested support - ending session');\n completed = false;\n supportRequested = true;\n shouldEndSession = true;\n inputQueue.close();\n break;\n }\n\n if (typeof completionDecision === 'string') {\n const feedbackPrompt = completionDecision.trim();\n if (!feedbackPrompt) {\n logToFile('Received empty feedback prompt - ending session');\n completed = false;\n shouldEndSession = true;\n inputQueue.close();\n break;\n }\n\n logToFile('Received testing feedback - queueing feedback prompt');\n hasCompletedWorkRef.value = false;\n waitingForUserInputRef.value = false;\n isInterruptingRef.value = false;\n handle.sendMessage(feedbackPrompt);\n startPersistentInput();\n setAgentRunning(true);\n continue;\n }\n\n completed = completionDecision;\n shouldEndSession = true;\n inputQueue.close();\n break;\n }\n\n // Turn ended without completion. If there are no queued messages,\n // we are waiting for the user to submit the next one.\n isInterruptingRef.value = false;\n\n if (!inputQueue.hasPending()) {\n waitingForUserInputRef.value = true;\n setAgentRunning(false);\n } else {\n waitingForUserInputRef.value = false;\n setAgentRunning(true);\n }\n }\n } finally {\n inputQueue.close();\n clearInterval(thinkingTimer);\n }\n\n const durationMs = Date.now() - startTime;\n logToFile(`Agent session completed in ${Math.round(durationMs / 1000)}s`);\n logToFile('Session ID:', sessionId);\n logToFile('Completion status:', hasCompletedWorkRef.value);\n\n if (!shouldEndSession && hasCompletedWorkRef.value) {\n // Fallback: if stream ended after completion, mark as completed.\n completed = true;\n }\n\n ui.stopPersistentInput();\n ui.setAgentState({ isRunning: false });\n\n if (completed || isSpinnerRunning) {\n spinner.stop();\n }\n\n return { sessionId, handle, completed, support: supportRequested };\n}\n"]}
|
|
@@ -7,14 +7,15 @@ export declare function getIntegrationDescription(type: string): string;
|
|
|
7
7
|
export declare const IS_DEV: boolean;
|
|
8
8
|
export declare const ISSUES_URL = "https://github.com/raindrop/wizard/issues";
|
|
9
9
|
export declare const CALLBACK_PORT = 8259;
|
|
10
|
-
export declare const
|
|
11
|
-
export declare const
|
|
12
|
-
export declare const WRITE_KEY_ENDPOINT
|
|
13
|
-
export declare const EVENTS_LIST_ENDPOINT
|
|
14
|
-
export declare const ANTHROPIC_BASE_URL
|
|
15
|
-
export declare const SESSION_START_ENDPOINT
|
|
16
|
-
export declare const SESSION_UPDATE_ENDPOINT
|
|
17
|
-
export declare const SESSION_COMPLETE_ENDPOINT
|
|
10
|
+
export declare const APP_URL: string;
|
|
11
|
+
export declare const RAINDROP_API_URL: string;
|
|
12
|
+
export declare const WRITE_KEY_ENDPOINT: string;
|
|
13
|
+
export declare const EVENTS_LIST_ENDPOINT: string;
|
|
14
|
+
export declare const ANTHROPIC_BASE_URL: string;
|
|
15
|
+
export declare const SESSION_START_ENDPOINT: string;
|
|
16
|
+
export declare const SESSION_UPDATE_ENDPOINT: string;
|
|
17
|
+
export declare const SESSION_COMPLETE_ENDPOINT: string;
|
|
18
|
+
export declare const SUPPORT_ENDPOINT: string;
|
|
18
19
|
/**
|
|
19
20
|
* Spinner message shown during wizard execution
|
|
20
21
|
*/
|
|
@@ -19,19 +19,20 @@ export function getIntegrationDescription(type) {
|
|
|
19
19
|
export const IS_DEV = ['test', 'development'].includes(process.env.NODE_ENV ?? '');
|
|
20
20
|
export const ISSUES_URL = 'https://github.com/raindrop/wizard/issues';
|
|
21
21
|
export const CALLBACK_PORT = 8259;
|
|
22
|
-
const
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
export const WRITE_KEY_ENDPOINT = `${
|
|
30
|
-
export const EVENTS_LIST_ENDPOINT = `${
|
|
31
|
-
export const ANTHROPIC_BASE_URL = `${
|
|
32
|
-
export const SESSION_START_ENDPOINT = `${
|
|
33
|
-
export const SESSION_UPDATE_ENDPOINT = `${
|
|
34
|
-
export const SESSION_COMPLETE_ENDPOINT = `${
|
|
22
|
+
const useLocalUrls = ['1', 'true'].includes((process.env.RAINDROP_USE_LOCAL ?? '').toLowerCase());
|
|
23
|
+
export const APP_URL = useLocalUrls
|
|
24
|
+
? 'http://localhost:5173'
|
|
25
|
+
: 'https://app.raindrop.ai';
|
|
26
|
+
export const RAINDROP_API_URL = useLocalUrls
|
|
27
|
+
? 'http://localhost:3000'
|
|
28
|
+
: 'https://api.dawnai.com';
|
|
29
|
+
export const WRITE_KEY_ENDPOINT = `${RAINDROP_API_URL}/api/cli/users/key`;
|
|
30
|
+
export const EVENTS_LIST_ENDPOINT = `${RAINDROP_API_URL}/api/cli/events/list`;
|
|
31
|
+
export const ANTHROPIC_BASE_URL = `${RAINDROP_API_URL}/api/cli`;
|
|
32
|
+
export const SESSION_START_ENDPOINT = `${RAINDROP_API_URL}/api/cli/session/init`;
|
|
33
|
+
export const SESSION_UPDATE_ENDPOINT = `${RAINDROP_API_URL}/api/cli/session/update`;
|
|
34
|
+
export const SESSION_COMPLETE_ENDPOINT = `${RAINDROP_API_URL}/api/cli/session/complete`;
|
|
35
|
+
export const SUPPORT_ENDPOINT = `${RAINDROP_API_URL}/api/cli/support`;
|
|
35
36
|
/**
|
|
36
37
|
* Spinner message shown during wizard execution
|
|
37
38
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/lib/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,WAIX;AAJD,WAAY,WAAW;IACrB,gCAAiB,CAAA;IACjB,wCAAyB,CAAA;IACzB,4CAA6B,CAAA;AAC/B,CAAC,EAJW,WAAW,KAAX,WAAW,QAItB;AAED,MAAM,UAAU,yBAAyB,CAAC,IAAY;IACpD,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,WAAW,CAAC,MAAM;YACrB,OAAO,cAAc,CAAC;QACxB,KAAK,WAAW,CAAC,UAAU;YACzB,OAAO,kBAAkB,CAAC;QAC5B,KAAK,WAAW,CAAC,WAAW;YAC1B,OAAO,mBAAmB,CAAC;QAC7B;YACE,MAAM,IAAI,KAAK,CAAC,uBAAuB,IAAI,EAAE,CAAC,CAAC;IACnD,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,QAAQ,CACpD,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAC3B,CAAC;AAEF,MAAM,CAAC,MAAM,UAAU,GAAG,2CAA2C,CAAC;AAEtE,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,CAAC;AAClC,MAAM,
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/lib/constants.ts"],"names":[],"mappings":"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","sourcesContent":["export enum Integration {\n python = 'python',\n typescript = 'typescript',\n vercelAiSdk = 'vercel-ai-sdk',\n}\n\nexport function getIntegrationDescription(type: string): string {\n switch (type) {\n case Integration.python:\n return 'a Python SDK';\n case Integration.typescript:\n return 'a TypeScript SDK';\n case Integration.vercelAiSdk:\n return 'the Vercel AI SDK';\n default:\n throw new Error(`Unknown integration ${type}`);\n }\n}\n\nexport const IS_DEV = ['test', 'development'].includes(\n process.env.NODE_ENV ?? '',\n);\n\nexport const ISSUES_URL = 'https://github.com/raindrop/wizard/issues';\n\nexport const CALLBACK_PORT = 8259;\nconst useLocalUrls = ['1', 'true'].includes(\n (process.env.RAINDROP_USE_LOCAL ?? '').toLowerCase(),\n);\n\nexport const APP_URL = useLocalUrls\n ? 'http://localhost:5173'\n : 'https://app.raindrop.ai';\nexport const RAINDROP_API_URL = useLocalUrls\n ? 'http://localhost:3000'\n : 'https://api.dawnai.com';\nexport const WRITE_KEY_ENDPOINT = `${RAINDROP_API_URL}/api/cli/users/key`;\nexport const EVENTS_LIST_ENDPOINT = `${RAINDROP_API_URL}/api/cli/events/list`;\nexport const ANTHROPIC_BASE_URL = `${RAINDROP_API_URL}/api/cli`;\nexport const SESSION_START_ENDPOINT = `${RAINDROP_API_URL}/api/cli/session/init`;\nexport const SESSION_UPDATE_ENDPOINT = `${RAINDROP_API_URL}/api/cli/session/update`;\nexport const SESSION_COMPLETE_ENDPOINT = `${RAINDROP_API_URL}/api/cli/session/complete`;\nexport const SUPPORT_ENDPOINT = `${RAINDROP_API_URL}/api/cli/support`;\n\n/**\n * Spinner message shown during wizard execution\n */\nexport const SPINNER_MESSAGE = 'Raindrop wizard is working...';\n\n/**\n * Safe bash command patterns that can be auto-approved without user confirmation.\n * Uses simple prefix matching with optional * wildcard at the end.\n *\n * NOTE: Package manager install/build/run commands are NOT auto-approved and require user confirmation.\n */\nexport const SAFE_BASH_PATTERNS: string[] = [\n // === Package Managers - Read-only commands ===\n 'npm ls*',\n 'npm outdated*',\n 'npm audit*',\n\n 'pip list*',\n 'pip show*',\n 'pip freeze*',\n\n 'poetry show*',\n\n 'uv pip list*',\n\n 'cargo check*',\n 'cargo clippy*',\n 'cargo fmt*',\n\n 'go fmt*',\n\n // === Type Checking / Linting / Formatting ===\n 'tsc*',\n 'eslint *',\n 'prettier *',\n 'biome *',\n 'mypy *',\n 'python -m mypy*',\n 'ruff *',\n 'black *',\n 'flake8 *',\n 'pylint *',\n 'pyright*',\n 'rubocop*',\n 'rustfmt*',\n 'gofmt*',\n 'swiftlint*',\n 'ktlint*',\n\n // === Build Tools ===\n 'make',\n 'make build*',\n 'make test*',\n 'make lint*',\n 'make check*',\n 'cmake *',\n 'gradle build*',\n 'gradle test*',\n './gradlew build*',\n './gradlew test*',\n 'mvn compile*',\n 'mvn test*',\n 'mvn package*',\n\n // === Testing ===\n 'jest*',\n 'vitest*',\n 'mocha*',\n 'pytest*',\n 'python -m pytest*',\n 'npx playwright test*',\n 'npx cypress run*',\n 'npx jest*',\n 'npx vitest*',\n\n // === Git (read-only operations) ===\n 'git status*',\n 'git diff*',\n 'git log*',\n 'git show*',\n 'git branch*',\n 'git fetch*',\n 'git remote -v*',\n 'git ls-files*',\n 'git rev-parse*',\n\n // === File/Directory Info (read-only) ===\n 'ls *',\n 'ls',\n 'cat *',\n 'head *',\n 'tail *',\n 'less *',\n 'find *',\n 'grep *',\n 'rg *',\n 'ag *',\n 'tree*',\n 'pwd',\n 'wc *',\n 'file *',\n 'stat *',\n 'du *',\n 'df *',\n\n // === Environment/System Info ===\n 'which *',\n 'whereis *',\n 'type *',\n 'command -v *',\n 'node --version*',\n 'node -v*',\n 'npm --version*',\n 'npm -v*',\n 'python --version*',\n 'python -V*',\n 'python3 --version*',\n '*--version',\n '*-v',\n '*-V',\n 'env',\n 'printenv*',\n 'echo *',\n 'uname*',\n 'hostname',\n 'whoami',\n 'date',\n 'uptime',\n\n // === Docker (read-only / safe) ===\n 'docker ps*',\n 'docker images*',\n 'docker logs*',\n 'docker inspect*',\n 'docker-compose ps*',\n 'docker-compose logs*',\n 'docker build*',\n 'docker compose build*',\n 'docker compose up*',\n\n // === Directory Navigation ===\n 'cd *',\n 'pushd *',\n 'popd',\n];\n"]}
|
|
@@ -38,6 +38,7 @@ export interface ReceivedEvent {
|
|
|
38
38
|
* Returns:
|
|
39
39
|
* - true: integration looks good, finish
|
|
40
40
|
* - false: stop without retry (e.g., user cancelled)
|
|
41
|
+
* - 'support': user contacted support, end session without warning
|
|
41
42
|
* - string: feedback prompt to send back to the agent for another iteration
|
|
42
43
|
*/
|
|
43
44
|
export declare function testIntegration(options: WizardOptions, writeKey: string, accessToken: string, orgId: string): Promise<boolean | string>;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import Chalk from 'chalk';
|
|
2
|
-
// chalk v2 types don't work well with ESM default imports
|
|
3
|
-
const chalk = Chalk;
|
|
4
|
-
import ui from '../utils/ui.js';
|
|
5
2
|
import { logToFile } from '../utils/debug.js';
|
|
6
|
-
import { EVENTS_LIST_ENDPOINT } from './constants.js';
|
|
7
|
-
import { buildTestFeedbackMessage } from './agent-prompts.js';
|
|
8
3
|
import { sendSessionComplete } from '../utils/session.js';
|
|
4
|
+
import ui from '../utils/ui.js';
|
|
5
|
+
import { buildTestFeedbackMessage } from './agent-prompts.js';
|
|
6
|
+
import { EVENTS_LIST_ENDPOINT, SUPPORT_ENDPOINT } from './constants.js';
|
|
7
|
+
// chalk v2 types don't work well with ESM default imports
|
|
8
|
+
const chalk = Chalk;
|
|
9
9
|
const POLL_INTERVAL_MS = 2000;
|
|
10
10
|
/**
|
|
11
11
|
* Fetch events from the API endpoint, filtered by wizard session ID
|
|
@@ -24,7 +24,7 @@ async function fetchEvents(accessToken, wizardSessionId) {
|
|
|
24
24
|
}
|
|
25
25
|
// API returns an array of events directly
|
|
26
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 })));
|
|
27
|
+
logToFile(`fetchEvents: received ${events?.length ?? 0} events`, events?.map((e) => ({ id: e.id, name: e.name, isPending: e.isPending })));
|
|
28
28
|
return events || [];
|
|
29
29
|
}
|
|
30
30
|
catch (error) {
|
|
@@ -37,6 +37,7 @@ async function fetchEvents(accessToken, wizardSessionId) {
|
|
|
37
37
|
* Returns:
|
|
38
38
|
* - true: integration looks good, finish
|
|
39
39
|
* - false: stop without retry (e.g., user cancelled)
|
|
40
|
+
* - 'support': user contacted support, end session without warning
|
|
40
41
|
* - string: feedback prompt to send back to the agent for another iteration
|
|
41
42
|
*/
|
|
42
43
|
export async function testIntegration(options, writeKey, accessToken, orgId) {
|
|
@@ -92,7 +93,10 @@ export async function testIntegration(options, writeKey, accessToken, orgId) {
|
|
|
92
93
|
}
|
|
93
94
|
})();
|
|
94
95
|
// Wait for user to finish testing via Ink's input system
|
|
95
|
-
const keyPressResult = await ui.continuePrompt({
|
|
96
|
+
const keyPressResult = await ui.continuePrompt({
|
|
97
|
+
message: 'Press any key when done testing...',
|
|
98
|
+
anyKey: true,
|
|
99
|
+
});
|
|
96
100
|
// Stop polling and spinner
|
|
97
101
|
isPolling = false;
|
|
98
102
|
testSpinner.stop();
|
|
@@ -107,10 +111,15 @@ export async function testIntegration(options, writeKey, accessToken, orgId) {
|
|
|
107
111
|
const result = await ui.feedbackSelect({
|
|
108
112
|
message: 'Do the results look good?',
|
|
109
113
|
options: [
|
|
110
|
-
{ value:
|
|
114
|
+
{ value: 'yes', label: 'Yes, looks good - proceed' },
|
|
115
|
+
{
|
|
116
|
+
value: 'feedback',
|
|
117
|
+
label: 'No, I will provide feedback to the agent',
|
|
118
|
+
allowTextInput: true,
|
|
119
|
+
},
|
|
111
120
|
{
|
|
112
|
-
value:
|
|
113
|
-
label: 'No,
|
|
121
|
+
value: 'support',
|
|
122
|
+
label: 'No, contact Raindrop support',
|
|
114
123
|
allowTextInput: true,
|
|
115
124
|
},
|
|
116
125
|
],
|
|
@@ -122,10 +131,34 @@ export async function testIntegration(options, writeKey, accessToken, orgId) {
|
|
|
122
131
|
return false;
|
|
123
132
|
}
|
|
124
133
|
// User selected "Yes, looks good"
|
|
125
|
-
if (result.type === 'option' && result.value ===
|
|
134
|
+
if (result.type === 'option' && result.value === 'yes') {
|
|
126
135
|
await sendSessionComplete(options.sessionId, 'success', accessToken, orgId);
|
|
127
136
|
return true;
|
|
128
137
|
}
|
|
138
|
+
// User typed a message and selected "No, contact Raindrop support"
|
|
139
|
+
if (result.type === 'text' && result.option === 'support') {
|
|
140
|
+
const supportSpinner = ui.spinner();
|
|
141
|
+
supportSpinner.start('Contacting Raindrop support...');
|
|
142
|
+
let didSupportRequestSucceed = true;
|
|
143
|
+
try {
|
|
144
|
+
await sendSupportRequest(accessToken, options.sessionId, result.value);
|
|
145
|
+
await sendSessionComplete(options.sessionId, 'support', accessToken, orgId, result.value);
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
didSupportRequestSucceed = false;
|
|
149
|
+
logToFile('Failed to send support request:', error);
|
|
150
|
+
}
|
|
151
|
+
finally {
|
|
152
|
+
supportSpinner.stop();
|
|
153
|
+
}
|
|
154
|
+
ui.addItem({
|
|
155
|
+
type: 'response',
|
|
156
|
+
text: didSupportRequestSucceed
|
|
157
|
+
? 'Sorry our wizard did not work! Hang tight! The Raindrop team will reach out ASAP to help you finish your integration.'
|
|
158
|
+
: "Error contacting Raindrop support. Please contact the Raindrop team at support@raindrop.ai and they'll reply ASAP to help you finish your integration.",
|
|
159
|
+
});
|
|
160
|
+
return 'support';
|
|
161
|
+
}
|
|
129
162
|
if (result.type !== 'text' || !result.value.trim()) {
|
|
130
163
|
return false;
|
|
131
164
|
}
|
|
@@ -136,4 +169,18 @@ export async function testIntegration(options, writeKey, accessToken, orgId) {
|
|
|
136
169
|
const feedbackPrompt = buildTestFeedbackMessage(receivedEvents, userFeedback);
|
|
137
170
|
return feedbackPrompt;
|
|
138
171
|
}
|
|
172
|
+
async function sendSupportRequest(accessToken, sessionId, message) {
|
|
173
|
+
const response = await fetch(SUPPORT_ENDPOINT, {
|
|
174
|
+
method: 'POST',
|
|
175
|
+
headers: {
|
|
176
|
+
Authorization: `Bearer ${accessToken}`,
|
|
177
|
+
'Content-Type': 'application/json',
|
|
178
|
+
'x-wizard-session': sessionId,
|
|
179
|
+
},
|
|
180
|
+
body: JSON.stringify({ message }),
|
|
181
|
+
});
|
|
182
|
+
if (!response.ok) {
|
|
183
|
+
throw new Error(`Support request failed: ${response.status}`);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
139
186
|
//# 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 { 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"]}
|
|
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';\nimport { logToFile } from '../utils/debug.js';\nimport { sendSessionComplete } from '../utils/session.js';\nimport type { WizardOptions } from '../utils/types.js';\nimport ui from '../utils/ui.js';\nimport { buildTestFeedbackMessage } from './agent-prompts.js';\nimport { EVENTS_LIST_ENDPOINT, SUPPORT_ENDPOINT } from './constants.js';\n\n// chalk v2 types don't work well with ESM default imports\nconst chalk = Chalk as any;\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(\n `fetchEvents: GET ${EVENTS_LIST_ENDPOINT} (session: ${wizardSessionId})`,\n );\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(\n `fetchEvents: received ${events?.length ?? 0} events`,\n events?.map((e) => ({ id: e.id, name: e.name, isPending: e.isPending })),\n );\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 * - 'support': user contacted support, end session without warning\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({\n message: 'Press any key when done testing...',\n anyKey: true,\n });\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: 'yes', label: 'Yes, looks good - proceed' },\n {\n value: 'feedback',\n label: 'No, I will provide feedback to the agent',\n allowTextInput: true,\n },\n {\n value: 'support',\n label: 'No, contact Raindrop support',\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 === 'yes') {\n await sendSessionComplete(options.sessionId, 'success', accessToken, orgId);\n return true;\n }\n\n // User typed a message and selected \"No, contact Raindrop support\"\n if (result.type === 'text' && result.option === 'support') {\n const supportSpinner = ui.spinner();\n supportSpinner.start('Contacting Raindrop support...');\n let didSupportRequestSucceed = true;\n try {\n await sendSupportRequest(accessToken, options.sessionId, result.value);\n await sendSessionComplete(options.sessionId, 'support', accessToken, orgId, result.value);\n } catch (error) {\n didSupportRequestSucceed = false;\n logToFile('Failed to send support request:', error);\n } finally {\n supportSpinner.stop();\n }\n ui.addItem({\n type: 'response',\n text: didSupportRequestSucceed\n ? 'Sorry our wizard did not work! Hang tight! The Raindrop team will reach out ASAP to help you finish your integration.'\n : \"Error contacting Raindrop support. Please contact the Raindrop team at support@raindrop.ai and they'll reply ASAP to help you finish your integration.\",\n });\n return 'support';\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(\n options.sessionId,\n 'failure',\n accessToken,\n orgId,\n userFeedback,\n );\n\n // Build feedback prompt for agent\n const feedbackPrompt = buildTestFeedbackMessage(receivedEvents, userFeedback);\n\n return feedbackPrompt;\n}\n\nasync function sendSupportRequest(\n accessToken: string,\n sessionId: string,\n message: string,\n): Promise<void> {\n const response = await fetch(SUPPORT_ENDPOINT, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${accessToken}`,\n 'Content-Type': 'application/json',\n 'x-wizard-session': sessionId,\n },\n body: JSON.stringify({ message }),\n });\n\n if (!response.ok) {\n throw new Error(`Support request failed: ${response.status}`);\n }\n}\n"]}
|
package/dist/src/lib/wizard.js
CHANGED
|
@@ -94,7 +94,6 @@ export async function runWizard(options) {
|
|
|
94
94
|
}, options);
|
|
95
95
|
const agentResult = await runAgentLoop(agent, `Your WIZARD SESSION ID is ${options.sessionId}. Begin the integration.`, options, {
|
|
96
96
|
spinnerMessage: SPINNER_MESSAGE,
|
|
97
|
-
successMessage: 'Raindrop integration complete',
|
|
98
97
|
accessToken: token.token,
|
|
99
98
|
orgId: token.orgId.toString(),
|
|
100
99
|
onCompleteIntegration: async () => {
|
|
@@ -104,10 +103,12 @@ export async function runWizard(options) {
|
|
|
104
103
|
},
|
|
105
104
|
});
|
|
106
105
|
if (!agentResult.completed) {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
106
|
+
if (!agentResult.support) {
|
|
107
|
+
ui.addItem({
|
|
108
|
+
type: 'warning',
|
|
109
|
+
text: 'Integration session ended before confirmation. You can rerun the wizard to continue.',
|
|
110
|
+
});
|
|
111
|
+
}
|
|
111
112
|
return;
|
|
112
113
|
}
|
|
113
114
|
// Build outro message
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wizard.js","sourceRoot":"","sources":["../../../src/lib/wizard.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"wizard.js","sourceRoot":"","sources":["../../../src/lib/wizard.ts"],"names":[],"mappings":"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","sourcesContent":["import Chalk from 'chalk';\nimport clipboardy from 'clipboardy';\nimport {\n askForWizardLogin,\n confirmContinueIfNoOrDirtyGitRepo,\n} from '../utils/clack-utils.js';\nimport { enableDebugLogs } from '../utils/debug.js';\nimport { saveWriteKeyToEnv } from '../utils/environment.js';\nimport { getOrgWriteKey } from '../utils/oauth.js';\nimport type { WizardOptions } from '../utils/types.js';\nimport ui from '../utils/ui.js';\nimport { initializeAgent, runAgentLoop } from './agent-interface.js';\nimport { ANTHROPIC_BASE_URL, SPINNER_MESSAGE } from './constants.js';\nimport { testIntegration } from './integration-testing.js';\n\n// chalk v2 types don't work well with ESM default imports\nconst chalk = Chalk as any;\n\n/**\n * Unified wizard powered by the universal agent runner.\n * The agent will detect the integration type and load appropriate documentation.\n */\nexport async function runWizard(options: WizardOptions): Promise<void> {\n if (options.debug) {\n enableDebugLogs();\n }\n\n // Check if the current directory is a git repository and has uncommitted or untracked changes; prompt the user to continue if so.\n await confirmContinueIfNoOrDirtyGitRepo(options);\n\n const token = await askForWizardLogin();\n\n // Set the wizard JWT in process.env for the SDK\n process.env.ANTHROPIC_AUTH_TOKEN = token.token;\n\n const writeKeySpinner = ui.spinner();\n writeKeySpinner.start('Retrieving your Raindrop write key...');\n\n let writeKey: string;\n try {\n const result = await getOrgWriteKey(token.token);\n writeKey = result.writeKey;\n } catch (error) {\n writeKeySpinner.stop('Failed to retrieve write key');\n ui.addItem({\n type: 'error',\n text: `Error: ${error instanceof Error ? error.message : String(error)}`,\n });\n throw error;\n }\n\n writeKeySpinner.stop();\n\n // Show org info and write key in a beautiful box\n ui.addItem({\n type: 'org-info',\n text: 'Organization info',\n orgName: token.orgName,\n writeKey,\n });\n\n // Prompt user for what to do with the write key\n const writeKeyAction = await ui.feedbackSelect({\n message: `What would you like to do with your ${chalk.cyan(\n 'RAINDROP_WRITE_KEY',\n )}?`,\n options: [\n { value: 'add-env', label: 'Add to .env' },\n { value: 'copy', label: 'Copy to clipboard' },\n { value: 'continue', label: 'Continue' },\n ],\n skipHistory: true,\n });\n\n // Determine the label for the history item based on action taken\n let writeKeyLabel: string | undefined;\n\n if (writeKeyAction.type === 'option') {\n if (writeKeyAction.value === 'add-env') {\n try {\n await saveWriteKeyToEnv(writeKey, options.installDir);\n writeKeyLabel = 'saved to .env';\n } catch (error) {\n ui.addItem({\n type: 'error',\n text: `Failed to add write key to .env: ${\n error instanceof Error ? error.message : String(error)\n }`,\n });\n }\n } else if (writeKeyAction.value === 'copy') {\n try {\n await clipboardy.write(`RAINDROP_WRITE_KEY=${writeKey}`);\n writeKeyLabel = 'copied to clipboard';\n } catch (error) {\n ui.addItem({\n type: 'error',\n text: `Failed to copy to clipboard: ${\n error instanceof Error ? error.message : String(error)\n }`,\n });\n }\n }\n // For 'continue', writeKeyLabel remains undefined\n }\n\n process.env.ANTHROPIC_BASE_URL = ANTHROPIC_BASE_URL;\n process.env.ANTHROPIC_AUTH_TOKEN = token.token;\n process.env.ANTHROPIC_CUSTOM_HEADERS = `x-wizard-session: ${options.sessionId}`;\n\n // Initialize agent\n const agent = initializeAgent(\n {\n workingDirectory: options.installDir,\n },\n options,\n );\n\n const agentResult = await runAgentLoop(\n agent,\n `Your WIZARD SESSION ID is ${options.sessionId}. Begin the integration.`,\n options,\n {\n spinnerMessage: SPINNER_MESSAGE,\n accessToken: token.token,\n orgId: token.orgId.toString(),\n onCompleteIntegration: async () => {\n // Ensure persistent input is stopped before testing phase\n ui.stopPersistentInput();\n return testIntegration(options, writeKey, token.token, token.orgId.toString());\n },\n },\n );\n\n if (!agentResult.completed) {\n if (!agentResult.support) {\n ui.addItem({\n type: 'warning',\n text: 'Integration session ended before confirmation. You can rerun the wizard to continue.',\n });\n }\n return;\n }\n\n // Build outro message\n const nextSteps = [\n 'Configure your API key in environment variables for deployment',\n 'Start using Raindrop in your application',\n ].filter(Boolean);\n\n const outroMessage = `${chalk.white('Raindrop successfully integrated')}\n\n${chalk.yellow('Next steps:')}\n${nextSteps.map((step) => `• ${step}`).join('\\n')}\n\nLearn more: ${chalk.cyan('https://www.raindrop.ai/docs')}\n${chalk.dim(\n 'Note: The Raindrop wizard uses an LLM agent to analyze and modify your project. Please review the changes made.',\n)}`;\n\n ui.addItem({ type: 'success', text: outroMessage });\n}\n"]}
|
|
@@ -58,15 +58,17 @@ export function FeedbackSelectPrompt({ options, onResult, standalone = true, })
|
|
|
58
58
|
const handleTextSubmit = useCallback((text) => {
|
|
59
59
|
if (!text.trim())
|
|
60
60
|
return;
|
|
61
|
-
|
|
62
|
-
|
|
61
|
+
const currentOption = options.options[highlightedIndex];
|
|
62
|
+
submitResult({ type: 'text', value: text.trim(), option: currentOption.value });
|
|
63
|
+
}, [submitResult, options.options, highlightedIndex]);
|
|
63
64
|
// Handle keyboard input
|
|
64
65
|
useInput((input, key) => {
|
|
65
66
|
// Handle Ctrl+C cancellation
|
|
66
67
|
if (key.ctrl && input === 'c') {
|
|
67
68
|
if (onResult) {
|
|
68
69
|
// Embedded mode (e.g., plan approval) - treat as rejection/interrupt
|
|
69
|
-
|
|
70
|
+
const currentOption = options.options[highlightedIndex];
|
|
71
|
+
submitResult({ type: 'text', value: 'interrupted', option: currentOption.value });
|
|
70
72
|
}
|
|
71
73
|
else if (standalone) {
|
|
72
74
|
// Standalone mode - cancel via CANCEL_SYMBOL
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FeedbackSelectPrompt.js","sourceRoot":"","sources":["../../../../src/ui/components/FeedbackSelectPrompt.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n * Feedback select prompt component.\n * A reusable select prompt where one option can enable inline text input.\n * Used by PlanApprovalPrompt and test-server for \"yes/no with feedback\" patterns.\n */\n\nimport React, { useState, useCallback, useEffect } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport TextInput from 'ink-text-input';\nimport { useWizard } from '../contexts/WizardContext.js';\nimport { PromptContainer } from './PromptContainer.js';\nimport { CANCEL_SYMBOL } from '../cancellation.js';\nimport type {\n FeedbackSelectOptions,\n FeedbackSelectResult,\n FeedbackSelectOption,\n} from '../types.js';\n\ninterface FeedbackSelectPromptProps<T> {\n options: FeedbackSelectOptions<T>;\n /** Optional callback for when result is ready (used by PlanApprovalPrompt) */\n onResult?: (result: FeedbackSelectResult<T>) => void;\n /** If true, this component manages its own resolution via WizardContext */\n standalone?: boolean;\n}\n\n/**\n * Feedback select prompt that supports inline text input for specific options.\n * Can be used standalone (resolves via WizardContext) or embedded (via onResult callback).\n */\nexport function FeedbackSelectPrompt<T>({\n options,\n onResult,\n standalone = true,\n}: FeedbackSelectPromptProps<T>): React.ReactElement {\n const { actions, state } = useWizard();\n const { resolvePending, addItem } = actions;\n const { terminalSize } = state;\n\n const [highlightedIndex, setHighlightedIndex] = useState(0);\n const [isTypingMode, setIsTypingMode] = useState(false);\n const [customText, setCustomText] = useState('');\n\n // Auto-enter typing mode when a text input option is highlighted\n useEffect(() => {\n const selectedOption = options.options[highlightedIndex];\n if (!isTypingMode && selectedOption?.allowTextInput) {\n setIsTypingMode(true);\n }\n }, [highlightedIndex, options.options, isTypingMode]);\n\n // Handle submitting a result\n const submitResult = useCallback(\n (result: FeedbackSelectResult<T>) => {\n if (onResult) {\n // Embedded mode - call the callback\n onResult(result);\n } else if (standalone) {\n // Standalone mode - resolve via context\n // Only add to history if skipHistory is not true\n if (!options.skipHistory) {\n addItem({\n type: 'select-result',\n text: options.message,\n label:\n result.type === 'option'\n ? options.options.find((o) => o.value === result.value)?.label ||\n String(result.value)\n : result.value,\n });\n }\n resolvePending(result);\n }\n },\n [onResult, standalone, addItem, resolvePending, options],\n );\n\n // Handle selecting a regular option\n const handleOptionSelect = useCallback(\n (option: FeedbackSelectOption<T>) => {\n submitResult({ type: 'option', value: option.value });\n },\n [submitResult],\n );\n\n // Handle submitting text input\n const handleTextSubmit = useCallback(\n (text: string) => {\n if (!text.trim()) return;\n submitResult({ type: 'text', value: text.trim() });\n },\n [submitResult],\n );\n\n // Handle keyboard input\n useInput(\n (input, key) => {\n // Handle Ctrl+C cancellation\n if (key.ctrl && input === 'c') {\n if (onResult) {\n // Embedded mode (e.g., plan approval) - treat as rejection/interrupt\n submitResult({ type: 'text', value: 'interrupted' });\n } else if (standalone) {\n // Standalone mode - cancel via CANCEL_SYMBOL\n if (!options.skipHistory) {\n addItem({\n type: 'select-result',\n text: options.message,\n label: '(cancelled)',\n });\n }\n resolvePending(CANCEL_SYMBOL);\n }\n return;\n }\n\n // Escape handling\n if (key.escape) {\n if (isTypingMode) {\n setIsTypingMode(false);\n }\n return;\n }\n\n // Arrow navigation - must come before isTypingMode check so arrows can exit typing mode\n if (key.upArrow) {\n if (isTypingMode) {\n setIsTypingMode(false);\n }\n setHighlightedIndex((idx) => Math.max(0, idx - 1));\n return;\n }\n if (key.downArrow) {\n if (isTypingMode) {\n setIsTypingMode(false);\n }\n setHighlightedIndex((idx) =>\n Math.min(options.options.length - 1, idx + 1),\n );\n return;\n }\n\n // Skip other keys when typing - TextInput handles them\n if (isTypingMode) {\n return;\n }\n\n // Enter to select\n if (key.return) {\n const selected = options.options[highlightedIndex];\n if (selected.allowTextInput) {\n setIsTypingMode(true);\n } else {\n handleOptionSelect(selected);\n }\n }\n },\n { isActive: true },\n );\n\n return (\n <PromptContainer>\n {/* Message */}\n <Box marginBottom={1}>\n <Text>{options.message}</Text>\n </Box>\n\n {/* Options */}\n <Box flexDirection=\"column\">\n {options.options.map((option, index) => {\n const isHighlighted = index === highlightedIndex;\n const isTextOption = option.allowTextInput;\n const optionPrefix = `${index + 1}. `;\n const optionContentWidth = Math.max(\n 1,\n terminalSize.width - optionPrefix.length,\n );\n\n // Text input option in typing mode\n if (isTextOption && isTypingMode && index === highlightedIndex) {\n return (\n <Box key={index} width={terminalSize.width}>\n <Text color=\"cyan\">{optionPrefix}</Text>\n <Box width={optionContentWidth}>\n <TextInput\n value={customText}\n onChange={setCustomText}\n onSubmit={handleTextSubmit}\n focus={true}\n placeholder=\"\"\n />\n </Box>\n </Box>\n );\n }\n\n // Regular option display\n return (\n <Box key={index} width={terminalSize.width}>\n <Text color={isHighlighted ? 'cyan' : undefined} wrap=\"truncate-end\">\n {optionPrefix}\n {option.label}\n </Text>\n </Box>\n );\n })}\n </Box>\n </PromptContainer>\n );\n}\n\nexport default FeedbackSelectPrompt;\n"]}
|
|
1
|
+
{"version":3,"file":"FeedbackSelectPrompt.js","sourceRoot":"","sources":["../../../../src/ui/components/FeedbackSelectPrompt.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n * Feedback select prompt component.\n * A reusable select prompt where one option can enable inline text input.\n * Used by PlanApprovalPrompt and test-server for \"yes/no with feedback\" patterns.\n */\n\nimport React, { useState, useCallback, useEffect } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport TextInput from 'ink-text-input';\nimport { useWizard } from '../contexts/WizardContext.js';\nimport { PromptContainer } from './PromptContainer.js';\nimport { CANCEL_SYMBOL } from '../cancellation.js';\nimport type {\n FeedbackSelectOptions,\n FeedbackSelectResult,\n FeedbackSelectOption,\n} from '../types.js';\n\ninterface FeedbackSelectPromptProps<T> {\n options: FeedbackSelectOptions<T>;\n /** Optional callback for when result is ready (used by PlanApprovalPrompt) */\n onResult?: (result: FeedbackSelectResult<T>) => void;\n /** If true, this component manages its own resolution via WizardContext */\n standalone?: boolean;\n}\n\n/**\n * Feedback select prompt that supports inline text input for specific options.\n * Can be used standalone (resolves via WizardContext) or embedded (via onResult callback).\n */\nexport function FeedbackSelectPrompt<T>({\n options,\n onResult,\n standalone = true,\n}: FeedbackSelectPromptProps<T>): React.ReactElement {\n const { actions, state } = useWizard();\n const { resolvePending, addItem } = actions;\n const { terminalSize } = state;\n\n const [highlightedIndex, setHighlightedIndex] = useState(0);\n const [isTypingMode, setIsTypingMode] = useState(false);\n const [customText, setCustomText] = useState('');\n\n // Auto-enter typing mode when a text input option is highlighted\n useEffect(() => {\n const selectedOption = options.options[highlightedIndex];\n if (!isTypingMode && selectedOption?.allowTextInput) {\n setIsTypingMode(true);\n }\n }, [highlightedIndex, options.options, isTypingMode]);\n\n // Handle submitting a result\n const submitResult = useCallback(\n (result: FeedbackSelectResult<T>) => {\n if (onResult) {\n // Embedded mode - call the callback\n onResult(result);\n } else if (standalone) {\n // Standalone mode - resolve via context\n // Only add to history if skipHistory is not true\n if (!options.skipHistory) {\n addItem({\n type: 'select-result',\n text: options.message,\n label:\n result.type === 'option'\n ? options.options.find((o) => o.value === result.value)?.label ||\n String(result.value)\n : result.value,\n });\n }\n resolvePending(result);\n }\n },\n [onResult, standalone, addItem, resolvePending, options],\n );\n\n // Handle selecting a regular option\n const handleOptionSelect = useCallback(\n (option: FeedbackSelectOption<T>) => {\n submitResult({ type: 'option', value: option.value });\n },\n [submitResult],\n );\n\n // Handle submitting text input\n const handleTextSubmit = useCallback(\n (text: string) => {\n if (!text.trim()) return;\n const currentOption = options.options[highlightedIndex];\n submitResult({ type: 'text', value: text.trim(), option: currentOption.value });\n },\n [submitResult, options.options, highlightedIndex],\n );\n\n // Handle keyboard input\n useInput(\n (input, key) => {\n // Handle Ctrl+C cancellation\n if (key.ctrl && input === 'c') {\n if (onResult) {\n // Embedded mode (e.g., plan approval) - treat as rejection/interrupt\n const currentOption = options.options[highlightedIndex];\n submitResult({ type: 'text', value: 'interrupted', option: currentOption.value });\n } else if (standalone) {\n // Standalone mode - cancel via CANCEL_SYMBOL\n if (!options.skipHistory) {\n addItem({\n type: 'select-result',\n text: options.message,\n label: '(cancelled)',\n });\n }\n resolvePending(CANCEL_SYMBOL);\n }\n return;\n }\n\n // Escape handling\n if (key.escape) {\n if (isTypingMode) {\n setIsTypingMode(false);\n }\n return;\n }\n\n // Arrow navigation - must come before isTypingMode check so arrows can exit typing mode\n if (key.upArrow) {\n if (isTypingMode) {\n setIsTypingMode(false);\n }\n setHighlightedIndex((idx) => Math.max(0, idx - 1));\n return;\n }\n if (key.downArrow) {\n if (isTypingMode) {\n setIsTypingMode(false);\n }\n setHighlightedIndex((idx) =>\n Math.min(options.options.length - 1, idx + 1),\n );\n return;\n }\n\n // Skip other keys when typing - TextInput handles them\n if (isTypingMode) {\n return;\n }\n\n // Enter to select\n if (key.return) {\n const selected = options.options[highlightedIndex];\n if (selected.allowTextInput) {\n setIsTypingMode(true);\n } else {\n handleOptionSelect(selected);\n }\n }\n },\n { isActive: true },\n );\n\n return (\n <PromptContainer>\n {/* Message */}\n <Box marginBottom={1}>\n <Text>{options.message}</Text>\n </Box>\n\n {/* Options */}\n <Box flexDirection=\"column\">\n {options.options.map((option, index) => {\n const isHighlighted = index === highlightedIndex;\n const isTextOption = option.allowTextInput;\n const optionPrefix = `${index + 1}. `;\n const optionContentWidth = Math.max(\n 1,\n terminalSize.width - optionPrefix.length,\n );\n\n // Text input option in typing mode\n if (isTextOption && isTypingMode && index === highlightedIndex) {\n return (\n <Box key={index} width={terminalSize.width}>\n <Text color=\"cyan\">{optionPrefix}</Text>\n <Box width={optionContentWidth}>\n <TextInput\n value={customText}\n onChange={setCustomText}\n onSubmit={handleTextSubmit}\n focus={true}\n placeholder=\"\"\n />\n </Box>\n </Box>\n );\n }\n\n // Regular option display\n return (\n <Box key={index} width={terminalSize.width}>\n <Text color={isHighlighted ? 'cyan' : undefined} wrap=\"truncate-end\">\n {optionPrefix}\n {option.label}\n </Text>\n </Box>\n );\n })}\n </Box>\n </PromptContainer>\n );\n}\n\nexport default FeedbackSelectPrompt;\n"]}
|
package/dist/src/ui/types.d.ts
CHANGED
package/dist/src/ui/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/ui/types.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/**\n * Type definitions for ink-based UI components\n * Maintains API compatibility with clack\n */\n\nexport interface SelectOption<T> {\n value: T;\n label: string;\n hint?: string;\n}\n\nexport interface SelectOptions<T> {\n message: string;\n options: Array<SelectOption<T>>;\n initialValue?: T;\n}\n\nexport interface TextOptions {\n message: string;\n placeholder?: string;\n defaultValue?: string;\n initialValue?: string;\n validate?: (value: string) => string | void;\n}\n\nexport interface SpinnerInstance {\n start: (msg?: string) => void;\n stop: (msg?: string) => void;\n message: (msg: string) => void;\n}\n\nexport interface LogFunctions {\n info: (msg: string) => void;\n warn: (msg: string) => void;\n error: (msg: string) => void;\n success: (msg: string) => void;\n step: (msg: string) => void;\n}\n\n// ============================================================================\n// Tool Approval Types\n// ============================================================================\n\n/**\n * Tool approval result - returned to the SDK's canUseTool callback\n */\nexport type ToolApprovalResult =\n | { behavior: 'allow'; updatedInput: Record<string, unknown>; allowAllEdits?: boolean; allowAllForFile?: string; allowAllForCommandPattern?: string }\n | { behavior: 'deny'; message: string };\n\n/**\n * Props for tool approval prompts\n */\nexport interface ToolApprovalProps {\n toolName: string;\n input: Record<string, unknown>;\n /** For file edits, the diff content */\n diffContent?: string;\n /** For file edits, the filename */\n fileName?: string;\n /** Description of the tool action */\n description?: string;\n}\n\n// ============================================================================\n// Clarifying Questions Types (AskUserQuestion tool)\n// ============================================================================\n\n/**\n * A single question option from the SDK\n */\nexport interface QuestionOption {\n label: string;\n description: string;\n}\n\n/**\n * A single clarifying question from the SDK\n */\nexport interface ClarifyingQuestion {\n question: string;\n header: string;\n options: QuestionOption[];\n multiSelect: boolean;\n}\n\n/**\n * Props for clarifying questions prompts\n */\nexport interface ClarifyingQuestionsProps {\n questions: ClarifyingQuestion[];\n}\n\n/**\n * Result from clarifying questions - returned to the SDK\n */\nexport interface ClarifyingQuestionsResult {\n questions: ClarifyingQuestion[];\n answers: Record<string, string>;\n}\n\n// ============================================================================\n// Plan Approval Types (ExitPlanMode tool)\n// ============================================================================\n\n/**\n * Props for plan approval prompts\n */\nexport interface PlanApprovalProps {\n planContent: string;\n}\n\n/**\n * Result from plan approval - returned to the handler\n */\nexport interface PlanApprovalResult {\n approved: boolean;\n feedback?: string; // Present only if approved: false\n}\n\n// ============================================================================\n// Persistent Input Types\n// ============================================================================\n\n/**\n * Props for unified text input component.\n * Handles both callback mode (during agent execution) and context mode (standalone prompts).\n * Note: Spinner is managed separately via ui.spinner().\n */\nexport interface PersistentInputProps {\n placeholder?: string;\n /** Message to show above the input */\n message?: string;\n /** Default value for the input */\n defaultValue?: string;\n /** Validation function - return error message or void */\n validate?: (value: string) => string | void;\n /** Callback when user submits - if not provided, uses resolvePending from context */\n onSubmit?: (message: string) => void | Promise<void>;\n /** Callback when user presses Esc - if not provided, uses resolvePending from context */\n onInterrupt?: () => void;\n /** Callback when user presses Ctrl+C - if not provided, falls back to onInterrupt */\n onCtrlC?: () => void;\n}\n\n// ============================================================================\n// Feedback Select Types (Select with inline text input option)\n// ============================================================================\n\n/**\n * An option in a feedback select prompt\n */\nexport interface FeedbackSelectOption<T> {\n value: T;\n label: string;\n /** If true, selecting this option enables inline text input */\n allowTextInput?: boolean;\n}\n\n/**\n * Props for feedback select prompts\n */\nexport interface FeedbackSelectOptions<T> {\n message: string;\n options: Array<FeedbackSelectOption<T>>;\n /** If true, don't add this prompt's result to history */\n skipHistory?: boolean;\n}\n\n/**\n * Result from feedback select - either an option was selected or text was entered\n */\nexport type FeedbackSelectResult<T> =\n | { type: 'option'; value: T }\n | { type: 'text'; value: string };\n\n// ============================================================================\n// Continue Button Types\n// ============================================================================\n\n/**\n * Props for continue button prompts\n */\nexport interface ContinuePromptOptions {\n message: string;\n buttonLabel?: string;\n /** If true, resolve on any keypress instead of requiring Enter */\n anyKey?: boolean;\n}\n\n// ============================================================================\n// Tool Call Display Types\n// ============================================================================\n\n/**\n * Status of a tool call\n */\nexport type ToolCallStatus =\n | 'pending'\n | 'executing'\n | 'success'\n | 'error'\n | 'denied'\n | 'interrupted';\n\n/**\n * A tool call to display in history\n */\nexport interface ToolCallInfo {\n toolName: string;\n description?: string;\n status: ToolCallStatus;\n input?: Record<string, unknown>;\n result?: string;\n error?: string;\n /** For file edits, the diff content */\n diffContent?: string;\n /** For file edits, the filename */\n fileName?: string;\n}\n\n// ============================================================================\n// Agent Query Handle\n// ============================================================================\n\n/**\n * Handle to control an active agent query\n */\nexport interface AgentQueryHandle {\n /** Interrupt the current agent execution */\n interrupt: (fromUserMessage?: boolean) => Promise<void>;\n /** Queue a user message for the active conversation */\n sendMessage: (message: string) => void;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/ui/types.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/**\n * Type definitions for ink-based UI components\n * Maintains API compatibility with clack\n */\n\nexport interface SelectOption<T> {\n value: T;\n label: string;\n hint?: string;\n}\n\nexport interface SelectOptions<T> {\n message: string;\n options: Array<SelectOption<T>>;\n initialValue?: T;\n}\n\nexport interface TextOptions {\n message: string;\n placeholder?: string;\n defaultValue?: string;\n initialValue?: string;\n validate?: (value: string) => string | void;\n}\n\nexport interface SpinnerInstance {\n start: (msg?: string) => void;\n stop: (msg?: string) => void;\n message: (msg: string) => void;\n}\n\nexport interface LogFunctions {\n info: (msg: string) => void;\n warn: (msg: string) => void;\n error: (msg: string) => void;\n success: (msg: string) => void;\n step: (msg: string) => void;\n}\n\n// ============================================================================\n// Tool Approval Types\n// ============================================================================\n\n/**\n * Tool approval result - returned to the SDK's canUseTool callback\n */\nexport type ToolApprovalResult =\n | { behavior: 'allow'; updatedInput: Record<string, unknown>; allowAllEdits?: boolean; allowAllForFile?: string; allowAllForCommandPattern?: string }\n | { behavior: 'deny'; message: string };\n\n/**\n * Props for tool approval prompts\n */\nexport interface ToolApprovalProps {\n toolName: string;\n input: Record<string, unknown>;\n /** For file edits, the diff content */\n diffContent?: string;\n /** For file edits, the filename */\n fileName?: string;\n /** Description of the tool action */\n description?: string;\n}\n\n// ============================================================================\n// Clarifying Questions Types (AskUserQuestion tool)\n// ============================================================================\n\n/**\n * A single question option from the SDK\n */\nexport interface QuestionOption {\n label: string;\n description: string;\n}\n\n/**\n * A single clarifying question from the SDK\n */\nexport interface ClarifyingQuestion {\n question: string;\n header: string;\n options: QuestionOption[];\n multiSelect: boolean;\n}\n\n/**\n * Props for clarifying questions prompts\n */\nexport interface ClarifyingQuestionsProps {\n questions: ClarifyingQuestion[];\n}\n\n/**\n * Result from clarifying questions - returned to the SDK\n */\nexport interface ClarifyingQuestionsResult {\n questions: ClarifyingQuestion[];\n answers: Record<string, string>;\n}\n\n// ============================================================================\n// Plan Approval Types (ExitPlanMode tool)\n// ============================================================================\n\n/**\n * Props for plan approval prompts\n */\nexport interface PlanApprovalProps {\n planContent: string;\n}\n\n/**\n * Result from plan approval - returned to the handler\n */\nexport interface PlanApprovalResult {\n approved: boolean;\n feedback?: string; // Present only if approved: false\n}\n\n// ============================================================================\n// Persistent Input Types\n// ============================================================================\n\n/**\n * Props for unified text input component.\n * Handles both callback mode (during agent execution) and context mode (standalone prompts).\n * Note: Spinner is managed separately via ui.spinner().\n */\nexport interface PersistentInputProps {\n placeholder?: string;\n /** Message to show above the input */\n message?: string;\n /** Default value for the input */\n defaultValue?: string;\n /** Validation function - return error message or void */\n validate?: (value: string) => string | void;\n /** Callback when user submits - if not provided, uses resolvePending from context */\n onSubmit?: (message: string) => void | Promise<void>;\n /** Callback when user presses Esc - if not provided, uses resolvePending from context */\n onInterrupt?: () => void;\n /** Callback when user presses Ctrl+C - if not provided, falls back to onInterrupt */\n onCtrlC?: () => void;\n}\n\n// ============================================================================\n// Feedback Select Types (Select with inline text input option)\n// ============================================================================\n\n/**\n * An option in a feedback select prompt\n */\nexport interface FeedbackSelectOption<T> {\n value: T;\n label: string;\n /** If true, selecting this option enables inline text input */\n allowTextInput?: boolean;\n}\n\n/**\n * Props for feedback select prompts\n */\nexport interface FeedbackSelectOptions<T> {\n message: string;\n options: Array<FeedbackSelectOption<T>>;\n /** If true, don't add this prompt's result to history */\n skipHistory?: boolean;\n}\n\n/**\n * Result from feedback select - either an option was selected or text was entered\n */\nexport type FeedbackSelectResult<T> =\n | { type: 'option'; value: T }\n | { type: 'text'; value: string; option: T };\n\n// ============================================================================\n// Continue Button Types\n// ============================================================================\n\n/**\n * Props for continue button prompts\n */\nexport interface ContinuePromptOptions {\n message: string;\n buttonLabel?: string;\n /** If true, resolve on any keypress instead of requiring Enter */\n anyKey?: boolean;\n}\n\n// ============================================================================\n// Tool Call Display Types\n// ============================================================================\n\n/**\n * Status of a tool call\n */\nexport type ToolCallStatus =\n | 'pending'\n | 'executing'\n | 'success'\n | 'error'\n | 'denied'\n | 'interrupted';\n\n/**\n * A tool call to display in history\n */\nexport interface ToolCallInfo {\n toolName: string;\n description?: string;\n status: ToolCallStatus;\n input?: Record<string, unknown>;\n result?: string;\n error?: string;\n /** For file edits, the diff content */\n diffContent?: string;\n /** For file edits, the filename */\n fileName?: string;\n}\n\n// ============================================================================\n// Agent Query Handle\n// ============================================================================\n\n/**\n * Handle to control an active agent query\n */\nexport interface AgentQueryHandle {\n /** Interrupt the current agent execution */\n interrupt: (fromUserMessage?: boolean) => Promise<void>;\n /** Queue a user message for the active conversation */\n sendMessage: (message: string) => void;\n}\n"]}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export declare function sendSessionInit(sessionId: string, setupDetails: string, accessToken: string, orgId: string): void;
|
|
2
2
|
export declare function sendSessionUpdate(sessionId: string, plan: string, accessToken: string, orgId: string): void;
|
|
3
|
-
export declare function sendSessionComplete(sessionId: string, status: 'success' | 'failure', accessToken: string, orgId: string, feedback?: string): Promise<void>;
|
|
3
|
+
export declare function sendSessionComplete(sessionId: string, status: 'success' | 'failure' | 'support', accessToken: string, orgId: string, feedback?: string): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../../src/utils/session.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../../src/utils/session.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n SESSION_START_ENDPOINT,\n SESSION_UPDATE_ENDPOINT,\n SESSION_COMPLETE_ENDPOINT,\n} from '../lib/constants.js';\nimport { logToFile, debug } from './debug.js';\n\nexport function sendSessionInit(\n sessionId: string,\n setupDetails: string,\n accessToken: string,\n orgId: string,\n): void {\n debug('→ Sending session init notification');\n\n const makeRequest = async () => {\n logToFile('Sending session init:', {\n endpoint: SESSION_START_ENDPOINT,\n sessionId,\n orgId,\n setupDetailsLength: setupDetails?.length || 0,\n hasAccessToken: !!accessToken,\n });\n\n const response = await fetch(SESSION_START_ENDPOINT, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${accessToken}`,\n 'Content-Type': 'application/json',\n 'x-wizard-session': sessionId,\n 'x-org-id': orgId,\n },\n body: JSON.stringify({\n setupDetails,\n }),\n });\n\n logToFile('Session init response:', {\n status: response.status,\n statusText: response.statusText,\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unable to read error');\n logToFile('Session init failed:', errorText);\n debug(`✗ Session init failed: ${response.status}`);\n } else {\n debug('✓ Session init notification sent');\n }\n\n return response;\n };\n\n // Fire and forget - don't await\n void makeRequest().catch((error) => {\n logToFile('Session init error:', error);\n // Silently fail - this is a non-critical notification\n });\n}\n\nexport function sendSessionUpdate(\n sessionId: string,\n plan: string,\n accessToken: string,\n orgId: string,\n): void {\n debug('→ Sending session update notification');\n\n const makeRequest = async () => {\n logToFile('Sending session update:', {\n endpoint: SESSION_UPDATE_ENDPOINT,\n sessionId,\n orgId,\n planLength: plan?.length || 0,\n hasAccessToken: !!accessToken,\n });\n\n const response = await fetch(SESSION_UPDATE_ENDPOINT, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${accessToken}`,\n 'Content-Type': 'application/json',\n 'x-wizard-session': sessionId,\n 'x-org-id': orgId,\n },\n body: JSON.stringify({\n plan,\n }),\n });\n\n logToFile('Session update response:', {\n status: response.status,\n statusText: response.statusText,\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unable to read error');\n logToFile('Session update failed:', errorText);\n debug(`✗ Session update failed: ${response.status}`);\n } else {\n debug('✓ Session update notification sent');\n }\n\n return response;\n };\n\n // Fire and forget - don't await\n void makeRequest().catch((error) => {\n logToFile('Session update error:', error);\n // Silently fail - this is a non-critical update\n });\n}\n\nexport async function sendSessionComplete(\n sessionId: string,\n status: 'success' | 'failure' | 'support',\n accessToken: string,\n orgId: string,\n feedback?: string,\n): Promise<void> {\n debug('→ Sending session complete notification');\n\n const makeRequest = async () => {\n logToFile('Sending session complete:', {\n endpoint: SESSION_COMPLETE_ENDPOINT,\n sessionId,\n orgId,\n status,\n hasFeedback: !!feedback,\n });\n\n const response = await fetch(SESSION_COMPLETE_ENDPOINT, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${accessToken}`,\n 'Content-Type': 'application/json',\n 'x-wizard-session': sessionId,\n 'x-org-id': orgId,\n },\n body: JSON.stringify({ status, feedback }),\n });\n\n logToFile('Session complete response:', {\n status: response.status,\n statusText: response.statusText,\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unable to read error');\n logToFile('Session complete failed:', errorText);\n debug(`✗ Session complete failed: ${response.status}`);\n } else {\n debug('✓ Session complete notification sent');\n }\n\n return response;\n };\n\n await makeRequest().catch((error) => {\n logToFile('Session complete error:', error);\n // Silently fail - this is a non-critical notification\n });\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@raindrop-ai/wizard",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"homepage": "https://github.com/raindrop/wizard",
|
|
6
6
|
"repository": "https://github.com/raindrop/wizard",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"definition": "dist/index.d.ts"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@anthropic-ai/claude-agent-sdk": "0.2.
|
|
37
|
+
"@anthropic-ai/claude-agent-sdk": "0.2.50",
|
|
38
38
|
"@inkkit/ink-markdown": "^1.0.0",
|
|
39
39
|
"chalk": "^2.4.1",
|
|
40
40
|
"clipboardy": "^4.0.0",
|
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
"typescript": "^5.0.4"
|
|
82
82
|
},
|
|
83
83
|
"engines": {
|
|
84
|
-
"node": ">=
|
|
84
|
+
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
|
85
85
|
},
|
|
86
86
|
"packageManager": "yarn@1.22.22",
|
|
87
87
|
"scripts": {
|