@raindrop-ai/wizard 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/dist/src/docs/claude-agent-sdk.mdx +382 -0
  2. package/dist/src/docs/{typescript.md → typescript.mdx} +8 -4
  3. package/dist/src/docs/vercel-ai-sdk.mdx +769 -0
  4. package/dist/src/lib/agent-interface.d.ts +4 -3
  5. package/dist/src/lib/agent-interface.js +290 -197
  6. package/dist/src/lib/agent-interface.js.map +1 -1
  7. package/dist/src/lib/constants.d.ts +1 -0
  8. package/dist/src/lib/constants.js +1 -0
  9. package/dist/src/lib/constants.js.map +1 -1
  10. package/dist/src/lib/handlers.d.ts +16 -8
  11. package/dist/src/lib/handlers.js +232 -118
  12. package/dist/src/lib/handlers.js.map +1 -1
  13. package/dist/src/lib/integration-testing.d.ts +5 -5
  14. package/dist/src/lib/integration-testing.js +28 -12
  15. package/dist/src/lib/integration-testing.js.map +1 -1
  16. package/dist/src/lib/mcp.d.ts +1 -1
  17. package/dist/src/lib/mcp.js +88 -49
  18. package/dist/src/lib/mcp.js.map +1 -1
  19. package/dist/src/lib/sdk-messages.d.ts +8 -1
  20. package/dist/src/lib/sdk-messages.js +83 -27
  21. package/dist/src/lib/sdk-messages.js.map +1 -1
  22. package/dist/src/lib/wizard.js +16 -20
  23. package/dist/src/lib/wizard.js.map +1 -1
  24. package/dist/src/ui/App.d.ts +5 -4
  25. package/dist/src/ui/App.js +12 -12
  26. package/dist/src/ui/App.js.map +1 -1
  27. package/dist/src/ui/components/ClarifyingQuestionsPrompt.js +4 -2
  28. package/dist/src/ui/components/ClarifyingQuestionsPrompt.js.map +1 -1
  29. package/dist/src/ui/components/ContinuePrompt.d.ts +3 -2
  30. package/dist/src/ui/components/ContinuePrompt.js +4 -4
  31. package/dist/src/ui/components/ContinuePrompt.js.map +1 -1
  32. package/dist/src/ui/components/DiffDisplay.js +16 -6
  33. package/dist/src/ui/components/DiffDisplay.js.map +1 -1
  34. package/dist/src/ui/components/FeedbackSelectPrompt.js +6 -3
  35. package/dist/src/ui/components/FeedbackSelectPrompt.js.map +1 -1
  36. package/dist/src/ui/components/HistoryItemDisplay.d.ts +5 -3
  37. package/dist/src/ui/components/HistoryItemDisplay.js +10 -9
  38. package/dist/src/ui/components/HistoryItemDisplay.js.map +1 -1
  39. package/dist/src/ui/components/Logo.js +19 -34
  40. package/dist/src/ui/components/Logo.js.map +1 -1
  41. package/dist/src/ui/components/OrgInfoBox.d.ts +2 -1
  42. package/dist/src/ui/components/OrgInfoBox.js +2 -4
  43. package/dist/src/ui/components/OrgInfoBox.js.map +1 -1
  44. package/dist/src/ui/components/PersistentTextInput.js +13 -11
  45. package/dist/src/ui/components/PersistentTextInput.js.map +1 -1
  46. package/dist/src/ui/components/PromptContainer.js +4 -8
  47. package/dist/src/ui/components/PromptContainer.js.map +1 -1
  48. package/dist/src/ui/components/ToolApprovalPrompt.js +4 -4
  49. package/dist/src/ui/components/ToolApprovalPrompt.js.map +1 -1
  50. package/dist/src/ui/components/WriteKeyDisplay.d.ts +1 -1
  51. package/dist/src/ui/components/WriteKeyDisplay.js +1 -1
  52. package/dist/src/ui/components/WriteKeyDisplay.js.map +1 -1
  53. package/dist/src/ui/contexts/WizardContext.d.ts +13 -5
  54. package/dist/src/ui/contexts/WizardContext.js +60 -20
  55. package/dist/src/ui/contexts/WizardContext.js.map +1 -1
  56. package/dist/src/ui/render.js +49 -5
  57. package/dist/src/ui/render.js.map +1 -1
  58. package/dist/src/ui/types.d.ts +4 -2
  59. package/dist/src/ui/types.js.map +1 -1
  60. package/dist/src/utils/oauth.js +0 -4
  61. package/dist/src/utils/oauth.js.map +1 -1
  62. package/dist/src/utils/session.d.ts +1 -0
  63. package/dist/src/utils/session.js +40 -1
  64. package/dist/src/utils/session.js.map +1 -1
  65. package/dist/src/utils/ui.d.ts +7 -2
  66. package/dist/src/utils/ui.js +9 -2
  67. package/dist/src/utils/ui.js.map +1 -1
  68. package/package.json +2 -1
  69. package/dist/src/docs/vercel-ai-sdk.md +0 -304
  70. /package/dist/src/docs/{browser.md → browser.mdx} +0 -0
  71. /package/dist/src/docs/{python.md → python.mdx} +0 -0
@@ -3,7 +3,8 @@ import { jsx as _jsx } from "react/jsx-runtime";
3
3
  * Central state management for the unified Ink wizard app.
4
4
  * Uses React Context to share state between all UI components.
5
5
  */
6
- import { createContext, useContext, useState, useCallback, useRef, useMemo, } from 'react';
6
+ import { createContext, useContext, useState, useCallback, useRef, useMemo, useEffect, } from 'react';
7
+ import { useStdout } from 'ink';
7
8
  import { SPINNER_MESSAGE } from '../../lib/constants.js';
8
9
  // Create the context with a null default (must be used within provider)
9
10
  const WizardContext = createContext(null);
@@ -33,6 +34,7 @@ export function useWizardActions() {
33
34
  * Provider component that manages all wizard state
34
35
  */
35
36
  export function WizardProvider({ children, onExit, }) {
37
+ const { stdout } = useStdout();
36
38
  // State
37
39
  const [history, setHistory] = useState([]);
38
40
  // Queue of pending items - processes one at a time, FIFO order
@@ -45,12 +47,44 @@ export function WizardProvider({ children, onExit, }) {
45
47
  });
46
48
  // Spinner state - separate from pendingItem so both can be visible
47
49
  const [activeSpinner, setActiveSpinner] = useState(null);
50
+ // Terminal size state for responsive rendering
51
+ const [terminalSize, setTerminalSize] = useState({
52
+ width: Math.max(1, stdout?.columns || 80),
53
+ height: Math.max(1, stdout?.rows || 24),
54
+ });
48
55
  // Persistent input config - stored separately, shown as fallback when queue is empty
49
56
  const [persistentInputConfig, setPersistentInputConfig] = useState(null);
50
57
  // Ref to store persistent input pending item - reuse same object to prevent re-renders
51
58
  const persistentInputItemRef = useRef(null);
59
+ // Ref to preserve in-progress persistent input text without triggering re-renders
60
+ const persistentInputValueRef = useRef('');
52
61
  // Ref to store the last valid pending item to prevent flickering
53
62
  const lastValidPendingItemRef = useRef(null);
63
+ // Listen for terminal resize events
64
+ useEffect(() => {
65
+ const handleResize = () => {
66
+ const nextWidth = Math.max(1, stdout?.columns || 80);
67
+ const nextHeight = Math.max(1, stdout?.rows || 24);
68
+ setTerminalSize((current) => {
69
+ if (current.width === nextWidth && current.height === nextHeight) {
70
+ return current;
71
+ }
72
+ return {
73
+ width: nextWidth,
74
+ height: nextHeight,
75
+ };
76
+ });
77
+ };
78
+ // Update terminal size on mount and when stdout changes
79
+ handleResize();
80
+ // Listen for resize events
81
+ if (stdout) {
82
+ stdout.on('resize', handleResize);
83
+ return () => {
84
+ stdout.off('resize', handleResize);
85
+ };
86
+ }
87
+ }, [stdout]);
54
88
  // Derive current pending item:
55
89
  // 1. If queue has items → show first item in queue
56
90
  // 2. If queue is empty AND persistent input is active → show persistent input
@@ -77,9 +111,7 @@ export function WizardProvider({ children, onExit, }) {
77
111
  persistentInputConfig.message &&
78
112
  currentRef.props.placeholder ===
79
113
  (persistentInputConfig.placeholder ??
80
- 'Type a message or press Esc to interrupt...') &&
81
- currentRef.props.defaultValue ===
82
- persistentInputConfig.value;
114
+ 'Type a message or press Esc to interrupt...');
83
115
  if (!propsMatch) {
84
116
  // Config changed, create new pending item
85
117
  persistentInputItemRef.current = {
@@ -91,7 +123,7 @@ export function WizardProvider({ children, onExit, }) {
91
123
  placeholder: persistentInputConfig.placeholder ??
92
124
  'Type a message or press Esc to interrupt...',
93
125
  message: persistentInputConfig.message,
94
- defaultValue: persistentInputConfig.value,
126
+ defaultValue: persistentInputValueRef.current,
95
127
  },
96
128
  // eslint-disable-next-line @typescript-eslint/no-empty-function
97
129
  resolve: () => { },
@@ -120,10 +152,16 @@ export function WizardProvider({ children, onExit, }) {
120
152
  const getNextId = useCallback(() => {
121
153
  return ++idCounter.current;
122
154
  }, []);
123
- // Add item to history (direct, like gemini-cli)
155
+ // Add item to history (direct, like gemini-cli). Returns the assigned ID.
124
156
  const addItem = useCallback((item) => {
125
- setHistory((prev) => [...prev, { ...item, id: getNextId() }]);
157
+ const id = getNextId();
158
+ setHistory((prev) => [...prev, { ...item, id }]);
159
+ return id;
126
160
  }, [getNextId]);
161
+ // Update an existing history item by ID
162
+ const updateItem = useCallback((id, updates) => {
163
+ setHistory((prev) => prev.map((item) => (item.id === id ? { ...item, ...updates } : item)));
164
+ }, []);
127
165
  // Deactivate all write-key items in history
128
166
  const deactivateWriteKeys = useCallback(() => {
129
167
  setHistory((prev) => prev.map((item) => item.type === 'write-key' && item.isActive
@@ -196,7 +234,7 @@ export function WizardProvider({ children, onExit, }) {
196
234
  setActiveSpinner(null);
197
235
  },
198
236
  message: (msg) => {
199
- setActiveSpinner(msg);
237
+ setActiveSpinner((prev) => (prev !== null ? msg : null));
200
238
  },
201
239
  };
202
240
  }, [addItem]);
@@ -272,12 +310,9 @@ export function WizardProvider({ children, onExit, }) {
272
310
  }, []);
273
311
  // Start persistent input mode - sets config so it shows as fallback when queue is empty
274
312
  const startPersistentInput = useCallback((config) => {
275
- // Store config - persistent input will automatically show when queue is empty
276
- // Preserve existing value if switching back to persistent input
277
- setPersistentInputConfig((prev) => ({
278
- ...config,
279
- value: prev?.value || '',
280
- }));
313
+ // Store config - persistent input will automatically show when queue is empty.
314
+ // The live input text is preserved separately in persistentInputValueRef.
315
+ setPersistentInputConfig(config);
281
316
  // Also store callbacks in agent state for external access if needed
282
317
  setAgentStateInternal((current) => ({
283
318
  ...current,
@@ -290,6 +325,7 @@ export function WizardProvider({ children, onExit, }) {
290
325
  // Stop persistent input mode - clears config so it no longer shows
291
326
  const stopPersistentInput = useCallback(() => {
292
327
  setPersistentInputConfig(null);
328
+ persistentInputValueRef.current = '';
293
329
  // Also clear the refs to prevent the input from lingering
294
330
  persistentInputItemRef.current = null;
295
331
  lastValidPendingItemRef.current = null;
@@ -300,11 +336,12 @@ export function WizardProvider({ children, onExit, }) {
300
336
  }, []);
301
337
  // Update persistent input value - allows PersistentTextInput to save its state
302
338
  const updatePersistentInputValue = useCallback((value) => {
303
- setPersistentInputConfig((prev) => {
304
- if (!prev)
305
- return prev;
306
- return { ...prev, value };
307
- });
339
+ persistentInputValueRef.current = value;
340
+ const currentPersistentItem = persistentInputItemRef.current;
341
+ if (currentPersistentItem?.type === 'persistent-input') {
342
+ // Keep the ref-backed pending item up to date for future remounts.
343
+ currentPersistentItem.props.defaultValue = value;
344
+ }
308
345
  }, []);
309
346
  // Update agent state
310
347
  const setAgentState = useCallback((state) => {
@@ -313,6 +350,7 @@ export function WizardProvider({ children, onExit, }) {
313
350
  // Combine actions
314
351
  const actions = useMemo(() => ({
315
352
  addItem,
353
+ updateItem,
316
354
  deactivateWriteKeys,
317
355
  select,
318
356
  text,
@@ -330,6 +368,7 @@ export function WizardProvider({ children, onExit, }) {
330
368
  setAgentState,
331
369
  }), [
332
370
  addItem,
371
+ updateItem,
333
372
  deactivateWriteKeys,
334
373
  select,
335
374
  text,
@@ -353,7 +392,8 @@ export function WizardProvider({ children, onExit, }) {
353
392
  shouldExit,
354
393
  agentState,
355
394
  activeSpinner,
356
- }), [history, pendingItem, shouldExit, agentState, activeSpinner]);
395
+ terminalSize,
396
+ }), [history, pendingItem, shouldExit, agentState, activeSpinner, terminalSize]);
357
397
  // Context value
358
398
  const contextValue = useMemo(() => ({ state, actions }), [state, actions]);
359
399
  return (_jsx(WizardContext.Provider, { value: contextValue, children: children }));
@@ -1 +1 @@
1
- {"version":3,"file":"WizardContext.js","sourceRoot":"","sources":["../../../../src/ui/contexts/WizardContext.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n * Central state management for the unified Ink wizard app.\n * Uses React Context to share state between all UI components.\n */\n\nimport React, {\n createContext,\n useContext,\n useState,\n useCallback,\n useRef,\n useMemo,\n type ReactNode,\n} from 'react';\nimport type {\n SelectOptions,\n TextOptions,\n SpinnerInstance,\n ToolApprovalProps,\n ToolApprovalResult,\n ClarifyingQuestionsProps,\n ClarifyingQuestionsResult,\n PlanApprovalProps,\n PlanApprovalResult,\n PersistentInputProps,\n ToolCallInfo,\n AgentQueryHandle,\n FeedbackSelectOptions,\n FeedbackSelectResult,\n ContinuePromptOptions,\n} from '../types.js';\nimport { SPINNER_MESSAGE } from '../../lib/constants.js';\n\n/**\n * Types of items that can appear in the history (Static section)\n */\nexport type HistoryItemType =\n | 'logo'\n | 'outro'\n | 'note'\n | 'cancel'\n | 'response'\n | 'warning'\n | 'error'\n | 'success'\n | 'step'\n | 'phase'\n | 'select-result'\n | 'text-result'\n | 'spinner-result'\n | 'tool-call'\n | 'agent-message'\n | 'user-message'\n | 'clarifying-questions-result'\n | 'declined-questions'\n | 'received-event'\n | 'plan-review'\n | 'plan-approved'\n | 'plan-rejected'\n | 'write-key'\n | 'org-info';\n\n/**\n * Data for received-event history items\n */\nexport interface ReceivedEventData {\n id: string;\n eventName: string;\n timestamp?: string;\n model?: string;\n userId?: string;\n input?: string;\n output?: string;\n}\n\n/**\n * A completed item that goes into the Static history\n */\nexport interface HistoryItem {\n id: number;\n type: HistoryItemType;\n text: string;\n /** Optional secondary content (e.g., selected option label) */\n label?: string;\n /** Optional hint/description */\n hint?: string;\n /** Title for note items */\n title?: string;\n /** For tool-call items, the tool call info */\n toolCall?: ToolCallInfo;\n /** For clarifying-questions-result items, the Q&A pairs */\n questionsAndAnswers?: Array<{ question: string; answer: string }>;\n /** For received-event items, the event data */\n receivedEvent?: ReceivedEventData;\n /** For plan-approved and plan-rejected items, the plan content */\n planContent?: string;\n /** For write-key items, the write key and install directory */\n writeKey?: string;\n installDir?: string;\n /** For write-key items, whether the component should be interactive */\n isActive?: boolean;\n /** For org-info items, the organization name */\n orgName?: string;\n}\n\n/**\n * Input type for adding history items (without id)\n */\nexport type HistoryItemInput = Omit<HistoryItem, 'id'>;\n\n/**\n * Types of pending prompts that can be active\n */\nexport type PendingItemType =\n | 'select'\n | 'text'\n | 'spinner'\n | 'tool-approval'\n | 'clarifying-questions'\n | 'plan-approval'\n | 'persistent-input'\n | 'feedback-select'\n | 'continue';\n\n/**\n * Spinner-specific props\n */\nexport interface SpinnerProps {\n message: string;\n}\n\n/**\n * All possible pending item props\n */\nexport type PendingItemProps =\n | SelectOptions<unknown>\n | TextOptions\n | SpinnerProps\n | ToolApprovalProps\n | ClarifyingQuestionsProps\n | PlanApprovalProps\n | PersistentInputProps\n | FeedbackSelectOptions<unknown>\n | ContinuePromptOptions;\n\n/**\n * A pending item represents an active prompt or spinner\n */\nexport interface PendingItem {\n type: PendingItemType;\n props: PendingItemProps;\n resolve: (value: unknown) => void;\n reject?: (error: Error) => void;\n}\n\n/**\n * Agent execution state\n */\nexport interface AgentState {\n /** Whether an agent is currently running */\n isRunning: boolean;\n /** Session ID for resuming */\n sessionId?: string;\n /** Handle to control the running agent */\n queryHandle?: AgentQueryHandle;\n /** Callbacks to restore persistent input after approval prompts */\n persistentInputCallbacks?: {\n onSubmit: (message: string) => void;\n onInterrupt: () => void;\n };\n}\n\n/**\n * Wizard state that's exposed via context\n */\nexport interface WizardState {\n /** Completed history items (rendered in Static) */\n history: HistoryItem[];\n /** Currently active prompt (rendered as pending) */\n pendingItem: PendingItem | null;\n /** Whether the app is ready to exit */\n shouldExit: boolean;\n /** Agent execution state */\n agentState: AgentState;\n /** Active spinner message (separate from pendingItem so both can be visible) */\n activeSpinner: string | null;\n}\n\n/**\n * Actions to modify wizard state\n */\nexport interface WizardActions {\n /** Add an item to history (like gemini-cli's addItem) */\n addItem: (item: HistoryItemInput) => void;\n\n /** Deactivate all write-key items in history */\n deactivateWriteKeys: () => void;\n\n /** Display a select prompt and return the selected value */\n select: <T>(options: SelectOptions<T>) => Promise<T | symbol>;\n\n /** Display a text input prompt and return the entered value */\n text: (options: TextOptions) => Promise<string | symbol>;\n\n /** Display a continue button prompt and wait for user to press Enter */\n continue: (options: ContinuePromptOptions) => Promise<boolean | symbol>;\n\n /** Display a spinner and return control methods */\n spinner: () => SpinnerInstance;\n\n /** Resolve the current pending item with a value */\n resolvePending: (value: unknown) => void;\n\n /** Mark the app as ready to exit */\n exit: () => void;\n\n // ========================================================================\n // Agent-related actions\n // ========================================================================\n\n /**\n * Show tool approval prompt (replaces persistent-input, restores after)\n * Used by canUseTool handler for tools that need user approval\n */\n toolApproval: (props: ToolApprovalProps) => Promise<ToolApprovalResult>;\n\n /**\n * Show clarifying questions prompt (replaces persistent-input, restores after)\n * Used by canUseTool handler for AskUserQuestion tool\n */\n clarifyingQuestions: (\n props: ClarifyingQuestionsProps,\n ) => Promise<ClarifyingQuestionsResult>;\n\n /**\n * Show plan approval prompt (replaces persistent-input, restores after)\n * Used by canUseTool handler for ExitPlanMode tool\n */\n planApproval: (props: PlanApprovalProps) => Promise<PlanApprovalResult>;\n\n /**\n * Show feedback select prompt (select with inline text input option)\n * Used for \"yes/no with feedback\" patterns\n */\n feedbackSelect: <T>(\n options: FeedbackSelectOptions<T>,\n ) => Promise<FeedbackSelectResult<T>>;\n\n /**\n * Start persistent input mode during agent execution\n * Sets pendingItem to persistent-input type\n */\n startPersistentInput: (config: {\n onSubmit: (message: string) => void;\n onInterrupt: () => void;\n onCtrlC?: () => void;\n message?: string;\n placeholder?: string;\n }) => void;\n\n /**\n * Stop persistent input mode\n * Clears pendingItem if it's persistent-input type\n */\n stopPersistentInput: () => void;\n\n /**\n * Update persistent input value\n * Allows PersistentTextInput to preserve its state across unmount/remount\n */\n updatePersistentInputValue: (value: string) => void;\n\n /**\n * Update agent state\n */\n setAgentState: (state: Partial<AgentState>) => void;\n}\n\n/**\n * Combined context type\n */\nexport interface WizardContextType {\n state: WizardState;\n actions: WizardActions;\n}\n\n// Create the context with a null default (must be used within provider)\nconst WizardContext = createContext<WizardContextType | null>(null);\n\n/**\n * Hook to access wizard state and actions\n */\nexport function useWizard(): WizardContextType {\n const context = useContext(WizardContext);\n if (!context) {\n throw new Error('useWizard must be used within a WizardProvider');\n }\n return context;\n}\n\n/**\n * Hook to access just the wizard state\n */\nexport function useWizardState(): WizardState {\n return useWizard().state;\n}\n\n/**\n * Hook to access just the wizard actions\n */\nexport function useWizardActions(): WizardActions {\n return useWizard().actions;\n}\n\n/**\n * Props for the WizardProvider\n */\ninterface WizardProviderProps {\n children: ReactNode;\n onExit?: () => void;\n}\n\n/**\n * Provider component that manages all wizard state\n */\nexport function WizardProvider({\n children,\n onExit,\n}: WizardProviderProps): React.ReactElement {\n // State\n const [history, setHistory] = useState<HistoryItem[]>([]);\n // Queue of pending items - processes one at a time, FIFO order\n // This allows multiple tool approvals to be queued without losing earlier ones\n // Note: persistent-input is NOT stored in queue, it's a fallback shown when queue is empty\n const [pendingQueue, setPendingQueue] = useState<PendingItem[]>([]);\n const [shouldExit, setShouldExit] = useState(false);\n const [agentState, setAgentStateInternal] = useState<AgentState>({\n isRunning: false,\n });\n // Spinner state - separate from pendingItem so both can be visible\n const [activeSpinner, setActiveSpinner] = useState<string | null>(null);\n\n // Persistent input config - stored separately, shown as fallback when queue is empty\n const [persistentInputConfig, setPersistentInputConfig] = useState<{\n onSubmit: (message: string) => void;\n onInterrupt: () => void;\n onCtrlC?: () => void;\n message?: string;\n placeholder?: string;\n value?: string; // Preserve value across unmount/remount\n } | null>(null);\n\n // Ref to store persistent input pending item - reuse same object to prevent re-renders\n const persistentInputItemRef = useRef<PendingItem | null>(null);\n\n // Ref to store the last valid pending item to prevent flickering\n const lastValidPendingItemRef = useRef<PendingItem | null>(null);\n\n // Derive current pending item:\n // 1. If queue has items → show first item in queue\n // 2. If queue is empty AND persistent input is active → show persistent input\n // 3. Otherwise → keep showing the last valid item to prevent flickering\n const pendingItem: PendingItem | null = useMemo(() => {\n let newPendingItem: PendingItem | null = null;\n\n // Priority 1: Items in queue\n if (pendingQueue.length > 0) {\n newPendingItem = pendingQueue[0];\n }\n // Priority 2: Persistent input (fallback when queue is empty)\n else if (persistentInputConfig) {\n // Reuse the same pending item object if the config hasn't changed\n // This prevents unnecessary re-renders when switching back to persistent input\n const currentRef = persistentInputItemRef.current;\n const propsMatch =\n currentRef &&\n (currentRef.props as PersistentInputProps).onSubmit ===\n persistentInputConfig.onSubmit &&\n (currentRef.props as PersistentInputProps).onInterrupt ===\n persistentInputConfig.onInterrupt &&\n (currentRef.props as PersistentInputProps).onCtrlC ===\n persistentInputConfig.onCtrlC &&\n (currentRef.props as PersistentInputProps).message ===\n persistentInputConfig.message &&\n (currentRef.props as PersistentInputProps).placeholder ===\n (persistentInputConfig.placeholder ??\n 'Type a message or press Esc to interrupt...') &&\n (currentRef.props as PersistentInputProps).defaultValue ===\n persistentInputConfig.value;\n\n if (!propsMatch) {\n // Config changed, create new pending item\n persistentInputItemRef.current = {\n type: 'persistent-input',\n props: {\n onSubmit: persistentInputConfig.onSubmit,\n onInterrupt: persistentInputConfig.onInterrupt,\n onCtrlC: persistentInputConfig.onCtrlC,\n placeholder:\n persistentInputConfig.placeholder ??\n 'Type a message or press Esc to interrupt...',\n message: persistentInputConfig.message,\n defaultValue: persistentInputConfig.value,\n } as PersistentInputProps,\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n resolve: () => {},\n };\n }\n newPendingItem = persistentInputItemRef.current;\n }\n\n // If we have a valid new pending item, update the ref and return it\n if (newPendingItem) {\n lastValidPendingItemRef.current = newPendingItem;\n return newPendingItem;\n }\n\n // If no new pending item but we have a last valid one, keep showing it to prevent flickering\n // This handles intermediate render states where pendingQueue might be temporarily empty\n if (lastValidPendingItemRef.current) {\n return lastValidPendingItemRef.current;\n }\n\n // No pending items at all\n persistentInputItemRef.current = null;\n lastValidPendingItemRef.current = null;\n return null;\n }, [pendingQueue, persistentInputConfig]);\n\n // Counter for unique IDs\n const idCounter = useRef(0);\n\n // Get next unique ID\n const getNextId = useCallback(() => {\n return ++idCounter.current;\n }, []);\n\n // Add item to history (direct, like gemini-cli)\n const addItem = useCallback(\n (item: HistoryItemInput) => {\n setHistory((prev) => [...prev, { ...item, id: getNextId() }]);\n },\n [getNextId],\n );\n\n // Deactivate all write-key items in history\n const deactivateWriteKeys = useCallback(() => {\n setHistory((prev) =>\n prev.map((item) =>\n item.type === 'write-key' && item.isActive\n ? { ...item, isActive: false }\n : item,\n ),\n );\n }, []);\n\n // Resolve current pending item and advance the queue\n const resolvePending = useCallback((value: unknown) => {\n // Clear the last valid pending item ref to prevent flickering/repeating the old question\n lastValidPendingItemRef.current = null;\n\n setPendingQueue((queue) => {\n if (queue.length > 0) {\n // Resolve the first item in the queue\n queue[0].resolve(value);\n // Return the queue without the first item (shift)\n return queue.slice(1);\n }\n return queue;\n });\n }, []);\n\n // Show select prompt - adds to queue\n const select = useCallback(\n <T,>(options: SelectOptions<T>): Promise<T | symbol> => {\n return new Promise((resolve) => {\n setPendingQueue((queue) => [\n ...queue,\n {\n type: 'select',\n props: options as SelectOptions<unknown>,\n resolve: resolve as (value: unknown) => void,\n },\n ]);\n });\n },\n [],\n );\n\n // Show text prompt - adds to queue\n const text = useCallback((options: TextOptions): Promise<string | symbol> => {\n return new Promise((resolve) => {\n setPendingQueue((queue) => [\n ...queue,\n {\n type: 'text',\n props: options,\n resolve: resolve as (value: unknown) => void,\n },\n ]);\n });\n }, []);\n\n // Show continue button prompt - adds to queue\n const continuePrompt = useCallback(\n (options: ContinuePromptOptions): Promise<boolean | symbol> => {\n return new Promise((resolve) => {\n setPendingQueue((queue) => [\n ...queue,\n {\n type: 'continue',\n props: options,\n resolve: resolve as (value: unknown) => void,\n },\n ]);\n });\n },\n [],\n );\n\n // Show spinner - uses separate activeSpinner state so it can be visible alongside pendingItem\n const spinner = useCallback((): SpinnerInstance => {\n return {\n start: (msg = '') => {\n setActiveSpinner(msg || SPINNER_MESSAGE);\n },\n stop: (msg = '') => {\n if (msg) {\n addItem({ type: 'spinner-result', text: msg });\n }\n setActiveSpinner(null);\n },\n message: (msg: string) => {\n setActiveSpinner(msg);\n },\n };\n }, [addItem]);\n\n // Exit the app\n const exit = useCallback(() => {\n setShouldExit(true);\n onExit?.();\n }, [onExit]);\n\n // ========================================================================\n // Agent-related actions\n // ========================================================================\n\n // Show tool approval prompt - adds to queue\n // Persistent input automatically shows when queue becomes empty (it's a fallback, not in queue)\n const toolApproval = useCallback(\n (props: ToolApprovalProps): Promise<ToolApprovalResult> => {\n return new Promise((resolve) => {\n setPendingQueue((queue) => [\n ...queue,\n {\n type: 'tool-approval',\n props,\n resolve: resolve as (value: unknown) => void,\n },\n ]);\n });\n },\n [],\n );\n\n // Show clarifying questions prompt - adds to queue\n // Persistent input automatically shows when queue becomes empty\n const clarifyingQuestions = useCallback(\n (props: ClarifyingQuestionsProps): Promise<ClarifyingQuestionsResult> => {\n return new Promise((resolve) => {\n setPendingQueue((queue) => [\n ...queue,\n {\n type: 'clarifying-questions',\n props,\n resolve: resolve as (value: unknown) => void,\n },\n ]);\n });\n },\n [],\n );\n\n // Show plan approval prompt - adds plan to history first (static), then adds selection to queue\n // Persistent input automatically shows when queue becomes empty\n const planApproval = useCallback(\n (props: PlanApprovalProps): Promise<PlanApprovalResult> => {\n // First, add the plan content to history so it's static and doesn't re-render\n addItem({\n type: 'plan-review',\n text: 'Ready to execute the plan?',\n planContent: props.planContent,\n });\n\n // Then show just the selection prompt as pending item\n return new Promise((resolve) => {\n setPendingQueue((queue) => [\n ...queue,\n {\n type: 'plan-approval',\n props,\n resolve: resolve as (value: unknown) => void,\n },\n ]);\n });\n },\n [addItem],\n );\n\n // Show feedback select prompt - adds to queue\n const feedbackSelect = useCallback(\n <T,>(\n options: FeedbackSelectOptions<T>,\n ): Promise<FeedbackSelectResult<T>> => {\n return new Promise((resolve) => {\n setPendingQueue((queue) => [\n ...queue,\n {\n type: 'feedback-select',\n props: options as FeedbackSelectOptions<unknown>,\n resolve: resolve as (value: unknown) => void,\n },\n ]);\n });\n },\n [],\n );\n\n // Start persistent input mode - sets config so it shows as fallback when queue is empty\n const startPersistentInput = useCallback(\n (config: {\n onSubmit: (message: string) => void;\n onInterrupt: () => void;\n onCtrlC?: () => void;\n message?: string;\n placeholder?: string;\n }) => {\n // Store config - persistent input will automatically show when queue is empty\n // Preserve existing value if switching back to persistent input\n setPersistentInputConfig((prev) => ({\n ...config,\n value: prev?.value || '',\n }));\n\n // Also store callbacks in agent state for external access if needed\n setAgentStateInternal((current) => ({\n ...current,\n persistentInputCallbacks: {\n onSubmit: config.onSubmit,\n onInterrupt: config.onInterrupt,\n },\n }));\n },\n [],\n );\n\n // Stop persistent input mode - clears config so it no longer shows\n const stopPersistentInput = useCallback(() => {\n setPersistentInputConfig(null);\n // Also clear the refs to prevent the input from lingering\n persistentInputItemRef.current = null;\n lastValidPendingItemRef.current = null;\n\n setAgentStateInternal((current) => ({\n ...current,\n persistentInputCallbacks: undefined,\n }));\n }, []);\n\n // Update persistent input value - allows PersistentTextInput to save its state\n const updatePersistentInputValue = useCallback((value: string) => {\n setPersistentInputConfig((prev) => {\n if (!prev) return prev;\n return { ...prev, value };\n });\n }, []);\n\n // Update agent state\n const setAgentState = useCallback((state: Partial<AgentState>) => {\n setAgentStateInternal((current) => ({ ...current, ...state }));\n }, []);\n\n // Combine actions\n const actions = useMemo<WizardActions>(\n () => ({\n addItem,\n deactivateWriteKeys,\n select,\n text,\n continue: continuePrompt,\n spinner,\n resolvePending,\n exit,\n toolApproval,\n clarifyingQuestions,\n planApproval,\n feedbackSelect,\n startPersistentInput,\n stopPersistentInput,\n updatePersistentInputValue,\n setAgentState,\n }),\n [\n addItem,\n deactivateWriteKeys,\n select,\n text,\n continuePrompt,\n spinner,\n resolvePending,\n exit,\n toolApproval,\n clarifyingQuestions,\n planApproval,\n feedbackSelect,\n startPersistentInput,\n stopPersistentInput,\n updatePersistentInputValue,\n setAgentState,\n ],\n );\n\n // Combine state\n const state = useMemo<WizardState>(\n () => ({\n history,\n pendingItem,\n shouldExit,\n agentState,\n activeSpinner,\n }),\n [history, pendingItem, shouldExit, agentState, activeSpinner],\n );\n\n // Context value\n const contextValue = useMemo<WizardContextType>(\n () => ({ state, actions }),\n [state, actions],\n );\n\n return (\n <WizardContext.Provider value={contextValue}>\n {children}\n </WizardContext.Provider>\n );\n}\n\nexport { WizardContext };\n"]}
1
+ {"version":3,"file":"WizardContext.js","sourceRoot":"","sources":["../../../../src/ui/contexts/WizardContext.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n * Central state management for the unified Ink wizard app.\n * Uses React Context to share state between all UI components.\n */\n\nimport React, {\n createContext,\n useContext,\n useState,\n useCallback,\n useRef,\n useMemo,\n useEffect,\n type ReactNode,\n} from 'react';\nimport { useStdout } from 'ink';\nimport type {\n SelectOptions,\n TextOptions,\n SpinnerInstance,\n ToolApprovalProps,\n ToolApprovalResult,\n ClarifyingQuestionsProps,\n ClarifyingQuestionsResult,\n PlanApprovalProps,\n PlanApprovalResult,\n PersistentInputProps,\n ToolCallInfo,\n AgentQueryHandle,\n FeedbackSelectOptions,\n FeedbackSelectResult,\n ContinuePromptOptions,\n} from '../types.js';\nimport { SPINNER_MESSAGE } from '../../lib/constants.js';\n\n/**\n * Types of items that can appear in history\n */\nexport type HistoryItemType =\n | 'logo'\n | 'outro'\n | 'note'\n | 'cancel'\n | 'response'\n | 'warning'\n | 'error'\n | 'success'\n | 'step'\n | 'phase'\n | 'select-result'\n | 'text-result'\n | 'spinner-result'\n | 'tool-call'\n | 'agent-message'\n | 'user-message'\n | 'clarifying-questions-result'\n | 'declined-questions'\n | 'received-event'\n | 'plan-review'\n | 'plan-approved'\n | 'plan-rejected'\n | 'write-key'\n | 'org-info';\n\n/**\n * Data for received-event history items\n */\nexport interface ReceivedEventData {\n id: string;\n eventName: string;\n timestamp?: string;\n model?: string;\n userId?: string;\n input?: string;\n output?: string;\n toolCallNames?: string[];\n}\n\n/**\n * A completed item that goes into history\n */\nexport interface HistoryItem {\n id: number;\n type: HistoryItemType;\n text: string;\n /** Optional secondary content (e.g., selected option label) */\n label?: string;\n /** Optional hint/description */\n hint?: string;\n /** Title for note items */\n title?: string;\n /** For tool-call items, the tool call info */\n toolCall?: ToolCallInfo;\n /** For clarifying-questions-result items, the Q&A pairs */\n questionsAndAnswers?: Array<{ question: string; answer: string }>;\n /** For received-event items, the event data */\n receivedEvent?: ReceivedEventData;\n /** For plan-approved and plan-rejected items, the plan content */\n planContent?: string;\n /** For write-key items, the write key and install directory */\n writeKey?: string;\n installDir?: string;\n /** For write-key items, whether the component should be interactive */\n isActive?: boolean;\n /** For org-info items, the organization name */\n orgName?: string;\n}\n\n/**\n * Input type for adding history items (without id)\n */\nexport type HistoryItemInput = Omit<HistoryItem, 'id'>;\n\n/**\n * Types of pending prompts that can be active\n */\nexport type PendingItemType =\n | 'select'\n | 'text'\n | 'spinner'\n | 'tool-approval'\n | 'clarifying-questions'\n | 'plan-approval'\n | 'persistent-input'\n | 'feedback-select'\n | 'continue';\n\n/**\n * Spinner-specific props\n */\nexport interface SpinnerProps {\n message: string;\n}\n\n/**\n * All possible pending item props\n */\nexport type PendingItemProps =\n | SelectOptions<unknown>\n | TextOptions\n | SpinnerProps\n | ToolApprovalProps\n | ClarifyingQuestionsProps\n | PlanApprovalProps\n | PersistentInputProps\n | FeedbackSelectOptions<unknown>\n | ContinuePromptOptions;\n\n/**\n * A pending item represents an active prompt or spinner\n */\nexport interface PendingItem {\n type: PendingItemType;\n props: PendingItemProps;\n resolve: (value: unknown) => void;\n reject?: (error: Error) => void;\n}\n\n/**\n * Agent execution state\n */\nexport interface AgentState {\n /** Whether an agent is currently running */\n isRunning: boolean;\n /** Session ID for resuming */\n sessionId?: string;\n /** Handle to control the running agent */\n queryHandle?: AgentQueryHandle;\n /** Callbacks to restore persistent input after approval prompts */\n persistentInputCallbacks?: {\n onSubmit: (message: string) => void;\n onInterrupt: () => void;\n };\n}\n\n/**\n * Wizard state that's exposed via context\n */\nexport interface WizardState {\n /** Completed history items */\n history: HistoryItem[];\n /** Currently active prompt (rendered as pending) */\n pendingItem: PendingItem | null;\n /** Whether the app is ready to exit */\n shouldExit: boolean;\n /** Agent execution state */\n agentState: AgentState;\n /** Active spinner message (separate from pendingItem so both can be visible) */\n activeSpinner: string | null;\n /** Terminal dimensions for responsive rendering */\n terminalSize: { width: number; height: number };\n}\n\n/**\n * Actions to modify wizard state\n */\nexport interface WizardActions {\n /** Add an item to history, returns the assigned item ID */\n addItem: (item: HistoryItemInput) => number;\n\n /** Update an existing history item by ID */\n updateItem: (id: number, updates: Partial<HistoryItemInput>) => void;\n\n /** Deactivate all write-key items in history */\n deactivateWriteKeys: () => void;\n\n /** Display a select prompt and return the selected value */\n select: <T>(options: SelectOptions<T>) => Promise<T | symbol>;\n\n /** Display a text input prompt and return the entered value */\n text: (options: TextOptions) => Promise<string | symbol>;\n\n /** Display a continue button prompt and wait for user to press Enter */\n continue: (options: ContinuePromptOptions) => Promise<boolean | symbol>;\n\n /** Display a spinner and return control methods */\n spinner: () => SpinnerInstance;\n\n /** Resolve the current pending item with a value */\n resolvePending: (value: unknown) => void;\n\n /** Mark the app as ready to exit */\n exit: () => void;\n\n // ========================================================================\n // Agent-related actions\n // ========================================================================\n\n /**\n * Show tool approval prompt (replaces persistent-input, restores after)\n * Used by canUseTool handler for tools that need user approval\n */\n toolApproval: (props: ToolApprovalProps) => Promise<ToolApprovalResult>;\n\n /**\n * Show clarifying questions prompt (replaces persistent-input, restores after)\n * Used by canUseTool handler for AskUserQuestion tool\n */\n clarifyingQuestions: (\n props: ClarifyingQuestionsProps,\n ) => Promise<ClarifyingQuestionsResult>;\n\n /**\n * Show plan approval prompt (replaces persistent-input, restores after)\n * Used by canUseTool handler for ExitPlanMode tool\n */\n planApproval: (props: PlanApprovalProps) => Promise<PlanApprovalResult>;\n\n /**\n * Show feedback select prompt (select with inline text input option)\n * Used for \"yes/no with feedback\" patterns\n */\n feedbackSelect: <T>(\n options: FeedbackSelectOptions<T>,\n ) => Promise<FeedbackSelectResult<T>>;\n\n /**\n * Start persistent input mode during agent execution\n * Sets pendingItem to persistent-input type\n */\n startPersistentInput: (config: {\n onSubmit: (message: string) => void;\n onInterrupt: () => void;\n onCtrlC?: () => void;\n message?: string;\n placeholder?: string;\n }) => void;\n\n /**\n * Stop persistent input mode\n * Clears pendingItem if it's persistent-input type\n */\n stopPersistentInput: () => void;\n\n /**\n * Update persistent input value\n * Allows PersistentTextInput to preserve its state across unmount/remount\n */\n updatePersistentInputValue: (value: string) => void;\n\n /**\n * Update agent state\n */\n setAgentState: (state: Partial<AgentState>) => void;\n}\n\n/**\n * Combined context type\n */\nexport interface WizardContextType {\n state: WizardState;\n actions: WizardActions;\n}\n\n// Create the context with a null default (must be used within provider)\nconst WizardContext = createContext<WizardContextType | null>(null);\n\n/**\n * Hook to access wizard state and actions\n */\nexport function useWizard(): WizardContextType {\n const context = useContext(WizardContext);\n if (!context) {\n throw new Error('useWizard must be used within a WizardProvider');\n }\n return context;\n}\n\n/**\n * Hook to access just the wizard state\n */\nexport function useWizardState(): WizardState {\n return useWizard().state;\n}\n\n/**\n * Hook to access just the wizard actions\n */\nexport function useWizardActions(): WizardActions {\n return useWizard().actions;\n}\n\n/**\n * Props for the WizardProvider\n */\ninterface WizardProviderProps {\n children: ReactNode;\n onExit?: () => void;\n}\n\n/**\n * Provider component that manages all wizard state\n */\nexport function WizardProvider({\n children,\n onExit,\n}: WizardProviderProps): React.ReactElement {\n const { stdout } = useStdout();\n\n // State\n const [history, setHistory] = useState<HistoryItem[]>([]);\n // Queue of pending items - processes one at a time, FIFO order\n // This allows multiple tool approvals to be queued without losing earlier ones\n // Note: persistent-input is NOT stored in queue, it's a fallback shown when queue is empty\n const [pendingQueue, setPendingQueue] = useState<PendingItem[]>([]);\n const [shouldExit, setShouldExit] = useState(false);\n const [agentState, setAgentStateInternal] = useState<AgentState>({\n isRunning: false,\n });\n // Spinner state - separate from pendingItem so both can be visible\n const [activeSpinner, setActiveSpinner] = useState<string | null>(null);\n // Terminal size state for responsive rendering\n const [terminalSize, setTerminalSize] = useState({\n width: Math.max(1, stdout?.columns || 80),\n height: Math.max(1, stdout?.rows || 24),\n });\n\n // Persistent input config - stored separately, shown as fallback when queue is empty\n const [persistentInputConfig, setPersistentInputConfig] = useState<{\n onSubmit: (message: string) => void;\n onInterrupt: () => void;\n onCtrlC?: () => void;\n message?: string;\n placeholder?: string;\n } | null>(null);\n\n // Ref to store persistent input pending item - reuse same object to prevent re-renders\n const persistentInputItemRef = useRef<PendingItem | null>(null);\n // Ref to preserve in-progress persistent input text without triggering re-renders\n const persistentInputValueRef = useRef('');\n\n // Ref to store the last valid pending item to prevent flickering\n const lastValidPendingItemRef = useRef<PendingItem | null>(null);\n\n // Listen for terminal resize events\n useEffect(() => {\n const handleResize = () => {\n const nextWidth = Math.max(1, stdout?.columns || 80);\n const nextHeight = Math.max(1, stdout?.rows || 24);\n\n setTerminalSize((current) => {\n if (current.width === nextWidth && current.height === nextHeight) {\n return current;\n }\n\n return {\n width: nextWidth,\n height: nextHeight,\n };\n });\n };\n\n // Update terminal size on mount and when stdout changes\n handleResize();\n\n // Listen for resize events\n if (stdout) {\n stdout.on('resize', handleResize);\n return () => {\n stdout.off('resize', handleResize);\n };\n }\n }, [stdout]);\n\n // Derive current pending item:\n // 1. If queue has items → show first item in queue\n // 2. If queue is empty AND persistent input is active → show persistent input\n // 3. Otherwise → keep showing the last valid item to prevent flickering\n const pendingItem: PendingItem | null = useMemo(() => {\n let newPendingItem: PendingItem | null = null;\n\n // Priority 1: Items in queue\n if (pendingQueue.length > 0) {\n newPendingItem = pendingQueue[0];\n }\n // Priority 2: Persistent input (fallback when queue is empty)\n else if (persistentInputConfig) {\n // Reuse the same pending item object if the config hasn't changed\n // This prevents unnecessary re-renders when switching back to persistent input\n const currentRef = persistentInputItemRef.current;\n const propsMatch =\n currentRef &&\n (currentRef.props as PersistentInputProps).onSubmit ===\n persistentInputConfig.onSubmit &&\n (currentRef.props as PersistentInputProps).onInterrupt ===\n persistentInputConfig.onInterrupt &&\n (currentRef.props as PersistentInputProps).onCtrlC ===\n persistentInputConfig.onCtrlC &&\n (currentRef.props as PersistentInputProps).message ===\n persistentInputConfig.message &&\n (currentRef.props as PersistentInputProps).placeholder ===\n (persistentInputConfig.placeholder ??\n 'Type a message or press Esc to interrupt...');\n\n if (!propsMatch) {\n // Config changed, create new pending item\n persistentInputItemRef.current = {\n type: 'persistent-input',\n props: {\n onSubmit: persistentInputConfig.onSubmit,\n onInterrupt: persistentInputConfig.onInterrupt,\n onCtrlC: persistentInputConfig.onCtrlC,\n placeholder:\n persistentInputConfig.placeholder ??\n 'Type a message or press Esc to interrupt...',\n message: persistentInputConfig.message,\n defaultValue: persistentInputValueRef.current,\n } as PersistentInputProps,\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n resolve: () => {},\n };\n }\n newPendingItem = persistentInputItemRef.current;\n }\n\n // If we have a valid new pending item, update the ref and return it\n if (newPendingItem) {\n lastValidPendingItemRef.current = newPendingItem;\n return newPendingItem;\n }\n\n // If no new pending item but we have a last valid one, keep showing it to prevent flickering\n // This handles intermediate render states where pendingQueue might be temporarily empty\n if (lastValidPendingItemRef.current) {\n return lastValidPendingItemRef.current;\n }\n\n // No pending items at all\n persistentInputItemRef.current = null;\n lastValidPendingItemRef.current = null;\n return null;\n }, [pendingQueue, persistentInputConfig]);\n\n // Counter for unique IDs\n const idCounter = useRef(0);\n\n // Get next unique ID\n const getNextId = useCallback(() => {\n return ++idCounter.current;\n }, []);\n\n // Add item to history (direct, like gemini-cli). Returns the assigned ID.\n const addItem = useCallback(\n (item: HistoryItemInput): number => {\n const id = getNextId();\n setHistory((prev) => [...prev, { ...item, id }]);\n return id;\n },\n [getNextId],\n );\n\n // Update an existing history item by ID\n const updateItem = useCallback(\n (id: number, updates: Partial<HistoryItemInput>) => {\n setHistory((prev) =>\n prev.map((item) => (item.id === id ? { ...item, ...updates } : item)),\n );\n },\n [],\n );\n\n // Deactivate all write-key items in history\n const deactivateWriteKeys = useCallback(() => {\n setHistory((prev) =>\n prev.map((item) =>\n item.type === 'write-key' && item.isActive\n ? { ...item, isActive: false }\n : item,\n ),\n );\n }, []);\n\n // Resolve current pending item and advance the queue\n const resolvePending = useCallback((value: unknown) => {\n // Clear the last valid pending item ref to prevent flickering/repeating the old question\n lastValidPendingItemRef.current = null;\n\n setPendingQueue((queue) => {\n if (queue.length > 0) {\n // Resolve the first item in the queue\n queue[0].resolve(value);\n // Return the queue without the first item (shift)\n return queue.slice(1);\n }\n return queue;\n });\n }, []);\n\n // Show select prompt - adds to queue\n const select = useCallback(\n <T,>(options: SelectOptions<T>): Promise<T | symbol> => {\n return new Promise((resolve) => {\n setPendingQueue((queue) => [\n ...queue,\n {\n type: 'select',\n props: options as SelectOptions<unknown>,\n resolve: resolve as (value: unknown) => void,\n },\n ]);\n });\n },\n [],\n );\n\n // Show text prompt - adds to queue\n const text = useCallback((options: TextOptions): Promise<string | symbol> => {\n return new Promise((resolve) => {\n setPendingQueue((queue) => [\n ...queue,\n {\n type: 'text',\n props: options,\n resolve: resolve as (value: unknown) => void,\n },\n ]);\n });\n }, []);\n\n // Show continue button prompt - adds to queue\n const continuePrompt = useCallback(\n (options: ContinuePromptOptions): Promise<boolean | symbol> => {\n return new Promise((resolve) => {\n setPendingQueue((queue) => [\n ...queue,\n {\n type: 'continue',\n props: options,\n resolve: resolve as (value: unknown) => void,\n },\n ]);\n });\n },\n [],\n );\n\n // Show spinner - uses separate activeSpinner state so it can be visible alongside pendingItem\n const spinner = useCallback((): SpinnerInstance => {\n return {\n start: (msg = '') => {\n setActiveSpinner(msg || SPINNER_MESSAGE);\n },\n stop: (msg = '') => {\n if (msg) {\n addItem({ type: 'spinner-result', text: msg });\n }\n setActiveSpinner(null);\n },\n message: (msg: string) => {\n setActiveSpinner((prev) => (prev !== null ? msg : null));\n },\n };\n }, [addItem]);\n\n // Exit the app\n const exit = useCallback(() => {\n setShouldExit(true);\n onExit?.();\n }, [onExit]);\n\n // ========================================================================\n // Agent-related actions\n // ========================================================================\n\n // Show tool approval prompt - adds to queue\n // Persistent input automatically shows when queue becomes empty (it's a fallback, not in queue)\n const toolApproval = useCallback(\n (props: ToolApprovalProps): Promise<ToolApprovalResult> => {\n return new Promise((resolve) => {\n setPendingQueue((queue) => [\n ...queue,\n {\n type: 'tool-approval',\n props,\n resolve: resolve as (value: unknown) => void,\n },\n ]);\n });\n },\n [],\n );\n\n // Show clarifying questions prompt - adds to queue\n // Persistent input automatically shows when queue becomes empty\n const clarifyingQuestions = useCallback(\n (props: ClarifyingQuestionsProps): Promise<ClarifyingQuestionsResult> => {\n return new Promise((resolve) => {\n setPendingQueue((queue) => [\n ...queue,\n {\n type: 'clarifying-questions',\n props,\n resolve: resolve as (value: unknown) => void,\n },\n ]);\n });\n },\n [],\n );\n\n // Show plan approval prompt - adds plan to history first (static), then adds selection to queue\n // Persistent input automatically shows when queue becomes empty\n const planApproval = useCallback(\n (props: PlanApprovalProps): Promise<PlanApprovalResult> => {\n // First, add the plan content to history so it's static and doesn't re-render\n addItem({\n type: 'plan-review',\n text: 'Ready to execute the plan?',\n planContent: props.planContent,\n });\n\n // Then show just the selection prompt as pending item\n return new Promise((resolve) => {\n setPendingQueue((queue) => [\n ...queue,\n {\n type: 'plan-approval',\n props,\n resolve: resolve as (value: unknown) => void,\n },\n ]);\n });\n },\n [addItem],\n );\n\n // Show feedback select prompt - adds to queue\n const feedbackSelect = useCallback(\n <T,>(\n options: FeedbackSelectOptions<T>,\n ): Promise<FeedbackSelectResult<T>> => {\n return new Promise((resolve) => {\n setPendingQueue((queue) => [\n ...queue,\n {\n type: 'feedback-select',\n props: options as FeedbackSelectOptions<unknown>,\n resolve: resolve as (value: unknown) => void,\n },\n ]);\n });\n },\n [],\n );\n\n // Start persistent input mode - sets config so it shows as fallback when queue is empty\n const startPersistentInput = useCallback(\n (config: {\n onSubmit: (message: string) => void;\n onInterrupt: () => void;\n onCtrlC?: () => void;\n message?: string;\n placeholder?: string;\n }) => {\n // Store config - persistent input will automatically show when queue is empty.\n // The live input text is preserved separately in persistentInputValueRef.\n setPersistentInputConfig(config);\n\n // Also store callbacks in agent state for external access if needed\n setAgentStateInternal((current) => ({\n ...current,\n persistentInputCallbacks: {\n onSubmit: config.onSubmit,\n onInterrupt: config.onInterrupt,\n },\n }));\n },\n [],\n );\n\n // Stop persistent input mode - clears config so it no longer shows\n const stopPersistentInput = useCallback(() => {\n setPersistentInputConfig(null);\n persistentInputValueRef.current = '';\n // Also clear the refs to prevent the input from lingering\n persistentInputItemRef.current = null;\n lastValidPendingItemRef.current = null;\n\n setAgentStateInternal((current) => ({\n ...current,\n persistentInputCallbacks: undefined,\n }));\n }, []);\n\n // Update persistent input value - allows PersistentTextInput to save its state\n const updatePersistentInputValue = useCallback((value: string) => {\n persistentInputValueRef.current = value;\n\n const currentPersistentItem = persistentInputItemRef.current;\n if (currentPersistentItem?.type === 'persistent-input') {\n // Keep the ref-backed pending item up to date for future remounts.\n (currentPersistentItem.props as PersistentInputProps).defaultValue = value;\n }\n }, []);\n\n // Update agent state\n const setAgentState = useCallback((state: Partial<AgentState>) => {\n setAgentStateInternal((current) => ({ ...current, ...state }));\n }, []);\n\n // Combine actions\n const actions = useMemo<WizardActions>(\n () => ({\n addItem,\n updateItem,\n deactivateWriteKeys,\n select,\n text,\n continue: continuePrompt,\n spinner,\n resolvePending,\n exit,\n toolApproval,\n clarifyingQuestions,\n planApproval,\n feedbackSelect,\n startPersistentInput,\n stopPersistentInput,\n updatePersistentInputValue,\n setAgentState,\n }),\n [\n addItem,\n updateItem,\n deactivateWriteKeys,\n select,\n text,\n continuePrompt,\n spinner,\n resolvePending,\n exit,\n toolApproval,\n clarifyingQuestions,\n planApproval,\n feedbackSelect,\n startPersistentInput,\n stopPersistentInput,\n updatePersistentInputValue,\n setAgentState,\n ],\n );\n\n // Combine state\n const state = useMemo<WizardState>(\n () => ({\n history,\n pendingItem,\n shouldExit,\n agentState,\n activeSpinner,\n terminalSize,\n }),\n [history, pendingItem, shouldExit, agentState, activeSpinner, terminalSize],\n );\n\n // Context value\n const contextValue = useMemo<WizardContextType>(\n () => ({ state, actions }),\n [state, actions],\n );\n\n return (\n <WizardContext.Provider value={contextValue}>\n {children}\n </WizardContext.Provider>\n );\n}\n\nexport { WizardContext };\n"]}
@@ -5,6 +5,7 @@ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
5
5
  */
6
6
  import React from 'react';
7
7
  import { render } from 'ink';
8
+ import ansiEscapes from 'ansi-escapes';
8
9
  import { WizardApp } from './App.js';
9
10
  import { WizardProvider, useWizardActions as useActions, } from './contexts/WizardContext.js';
10
11
  // Global reference to the current wizard actions
@@ -12,6 +13,37 @@ let currentActions = null;
12
13
  // Promise that resolves when actions are ready
13
14
  let actionsReadyResolve = null;
14
15
  let actionsReadyPromise = null;
16
+ /**
17
+ * Attach a resize listener that clears the render surface when terminal width
18
+ * shrinks. This prevents stale frame artifacts when wrapped content grows in
19
+ * visual line count after a shrink event.
20
+ */
21
+ function attachShrinkClearHandler(stdout, clear) {
22
+ if (!stdout) {
23
+ return () => undefined;
24
+ }
25
+ let previousWidth = stdout.columns || 80;
26
+ const handleResize = () => {
27
+ const currentWidth = stdout.columns || previousWidth || 80;
28
+ if (currentWidth < previousWidth) {
29
+ clear();
30
+ if (stdout.isTTY) {
31
+ stdout.write(ansiEscapes.clearTerminal);
32
+ }
33
+ }
34
+ previousWidth = currentWidth;
35
+ };
36
+ // Run before Ink's internal resize listener to clear stale frame state first.
37
+ if (typeof stdout.prependListener === 'function') {
38
+ stdout.prependListener('resize', handleResize);
39
+ }
40
+ else {
41
+ stdout.on('resize', handleResize);
42
+ }
43
+ return () => {
44
+ stdout.off('resize', handleResize);
45
+ };
46
+ }
15
47
  /**
16
48
  * Get the current wizard actions.
17
49
  * Returns null if the wizard hasn't been started yet.
@@ -61,16 +93,28 @@ export function startWizardUI() {
61
93
  const instance = render(_jsx(App, {}), {
62
94
  exitOnCtrlC: false, // We handle Ctrl+C in components
63
95
  });
96
+ const detachShrinkClearHandler = attachShrinkClearHandler(process.stdout, () => {
97
+ instance.clear();
98
+ });
99
+ let isDisposed = false;
100
+ const dispose = () => {
101
+ if (isDisposed) {
102
+ return;
103
+ }
104
+ isDisposed = true;
105
+ detachShrinkClearHandler();
106
+ currentActions = null;
107
+ actionsReadyPromise = null;
108
+ actionsReadyResolve = null;
109
+ instance.unmount();
110
+ };
64
111
  return {
65
112
  waitUntilExit: async () => {
66
113
  await exitPromise;
67
- instance.unmount();
114
+ dispose();
68
115
  },
69
116
  unmount: () => {
70
- currentActions = null;
71
- actionsReadyPromise = null;
72
- actionsReadyResolve = null;
73
- instance.unmount();
117
+ dispose();
74
118
  },
75
119
  clear: () => {
76
120
  instance.clear();
@@ -1 +1 @@
1
- {"version":3,"file":"render.js","sourceRoot":"","sources":["../../../src/ui/render.tsx"],"names":[],"mappings":";AAAA;;;GAGG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,MAAM,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrC,OAAO,EACL,cAAc,EACd,gBAAgB,IAAI,UAAU,GAE/B,MAAM,6BAA6B,CAAC;AAkBrC,iDAAiD;AACjD,IAAI,cAAc,GAAyB,IAAI,CAAC;AAEhD,+CAA+C;AAC/C,IAAI,mBAAmB,GAAwB,IAAI,CAAC;AACpD,IAAI,mBAAmB,GAAyB,IAAI,CAAC;AAErD;;;GAGG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO,cAAc,CAAC;AACxB,CAAC;AAED;;GAEG;AACH,SAAS,gBAAgB,CAAC,OAAsB;IAC9C,cAAc,GAAG,OAAO,CAAC;IACzB,uDAAuD;IACvD,IAAI,mBAAmB,EAAE,CAAC;QACxB,mBAAmB,EAAE,CAAC;QACtB,mBAAmB,GAAG,IAAI,CAAC;IAC7B,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,oBAAoB,CAAC,EAC5B,QAAQ,EACR,SAAS,GAIV;IACC,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAE7B,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,SAAS,CAAC,OAAO,CAAC,CAAC;IACrB,CAAC,EAAE,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC;IAEzB,OAAO,4BAAG,QAAQ,GAAI,CAAC;AACzB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa;IAC3B,2BAA2B;IAC3B,mBAAmB,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QAClD,mBAAmB,GAAG,OAAO,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,IAAI,WAAuB,CAAC;IAC5B,MAAM,WAAW,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QAChD,WAAW,GAAG,OAAO,CAAC;IACxB,CAAC,CAAC,CAAC;IAEH,MAAM,UAAU,GAAG,GAAG,EAAE;QACtB,WAAW,EAAE,CAAC;IAChB,CAAC,CAAC;IAEF,2DAA2D;IAC3D,MAAM,GAAG,GAAG,GAAG,EAAE,CAAC,CAChB,KAAC,cAAc,IAAC,MAAM,EAAE,UAAU,YAChC,KAAC,oBAAoB,IAAC,SAAS,EAAE,gBAAgB,YAC/C,KAAC,SAAS,KAAG,GACQ,GACR,CAClB,CAAC;IAEF,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAC,GAAG,KAAG,EAAE;QAC/B,WAAW,EAAE,KAAK,EAAE,iCAAiC;KACtD,CAAC,CAAC;IAEH,OAAO;QACL,aAAa,EAAE,KAAK,IAAI,EAAE;YACxB,MAAM,WAAW,CAAC;YAClB,QAAQ,CAAC,OAAO,EAAE,CAAC;QACrB,CAAC;QACD,OAAO,EAAE,GAAG,EAAE;YACZ,cAAc,GAAG,IAAI,CAAC;YACtB,mBAAmB,GAAG,IAAI,CAAC;YAC3B,mBAAmB,GAAG,IAAI,CAAC;YAC3B,QAAQ,CAAC,OAAO,EAAE,CAAC;QACrB,CAAC;QACD,KAAK,EAAE,GAAG,EAAE;YACV,QAAQ,CAAC,KAAK,EAAE,CAAC;QACnB,CAAC;QACD,IAAI,OAAO;YACT,OAAO,cAAc,CAAC;QACxB,CAAC;QACD,cAAc,EAAE,KAAK,IAAI,EAAE;YACzB,IAAI,mBAAmB,EAAE,CAAC;gBACxB,MAAM,mBAAmB,CAAC;YAC5B,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe;IAC7B,OAAO,cAAc,KAAK,IAAI,CAAC;AACjC,CAAC","sourcesContent":["/**\n * Single render entry point for the unified Ink app.\n * Only one render() call is made for the entire wizard session.\n */\n\nimport React from 'react';\nimport { render } from 'ink';\nimport { WizardApp } from './App.js';\nimport {\n WizardProvider,\n useWizardActions as useActions,\n type WizardActions,\n} from './contexts/WizardContext.js';\n\n/**\n * Instance returned by startWizardUI\n */\nexport interface WizardInstance {\n /** Wait for the wizard to exit */\n waitUntilExit: () => Promise<void>;\n /** Unmount the wizard UI */\n unmount: () => void;\n /** Clear the screen */\n clear: () => void;\n /** Get the wizard actions for programmatic control */\n actions: WizardActions | null;\n /** Wait for the wizard to be ready (actions available) */\n waitUntilReady: () => Promise<void>;\n}\n\n// Global reference to the current wizard actions\nlet currentActions: WizardActions | null = null;\n\n// Promise that resolves when actions are ready\nlet actionsReadyResolve: (() => void) | null = null;\nlet actionsReadyPromise: Promise<void> | null = null;\n\n/**\n * Get the current wizard actions.\n * Returns null if the wizard hasn't been started yet.\n */\nexport function getWizardActions(): WizardActions | null {\n return currentActions;\n}\n\n/**\n * Set the current wizard actions (called from WizardActionsCapture)\n */\nfunction setWizardActions(actions: WizardActions): void {\n currentActions = actions;\n // Resolve the ready promise when actions are available\n if (actionsReadyResolve) {\n actionsReadyResolve();\n actionsReadyResolve = null;\n }\n}\n\n/**\n * Component that captures actions from context and exposes them globally\n */\nfunction WizardActionsCapture({\n children,\n onActions,\n}: {\n children: React.ReactNode;\n onActions: (actions: WizardActions) => void;\n}): React.ReactElement {\n const actions = useActions();\n\n React.useEffect(() => {\n onActions(actions);\n }, [actions, onActions]);\n\n return <>{children}</>;\n}\n\n/**\n * Start the wizard UI with a single Ink render call.\n * All prompts and spinners will use this single instance.\n */\nexport function startWizardUI(): WizardInstance {\n // Create the ready promise\n actionsReadyPromise = new Promise<void>((resolve) => {\n actionsReadyResolve = resolve;\n });\n\n let resolveExit: () => void;\n const exitPromise = new Promise<void>((resolve) => {\n resolveExit = resolve;\n });\n\n const handleExit = () => {\n resolveExit();\n };\n\n // Create the app with WizardProvider that captures actions\n const App = () => (\n <WizardProvider onExit={handleExit}>\n <WizardActionsCapture onActions={setWizardActions}>\n <WizardApp />\n </WizardActionsCapture>\n </WizardProvider>\n );\n\n const instance = render(<App />, {\n exitOnCtrlC: false, // We handle Ctrl+C in components\n });\n\n return {\n waitUntilExit: async () => {\n await exitPromise;\n instance.unmount();\n },\n unmount: () => {\n currentActions = null;\n actionsReadyPromise = null;\n actionsReadyResolve = null;\n instance.unmount();\n },\n clear: () => {\n instance.clear();\n },\n get actions() {\n return currentActions;\n },\n waitUntilReady: async () => {\n if (actionsReadyPromise) {\n await actionsReadyPromise;\n }\n },\n };\n}\n\n/**\n * Check if the wizard UI is running\n */\nexport function isWizardRunning(): boolean {\n return currentActions !== null;\n}\n"]}
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../../../src/ui/render.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n * Single render entry point for the unified Ink app.\n * Only one render() call is made for the entire wizard session.\n */\n\nimport React from 'react';\nimport { render } from 'ink';\nimport ansiEscapes from 'ansi-escapes';\nimport { WizardApp } from './App.js';\nimport {\n WizardProvider,\n useWizardActions as useActions,\n type WizardActions,\n} from './contexts/WizardContext.js';\n\n/**\n * Instance returned by startWizardUI\n */\nexport interface WizardInstance {\n /** Wait for the wizard to exit */\n waitUntilExit: () => Promise<void>;\n /** Unmount the wizard UI */\n unmount: () => void;\n /** Clear the screen */\n clear: () => void;\n /** Get the wizard actions for programmatic control */\n actions: WizardActions | null;\n /** Wait for the wizard to be ready (actions available) */\n waitUntilReady: () => Promise<void>;\n}\n\n// Global reference to the current wizard actions\nlet currentActions: WizardActions | null = null;\n\n// Promise that resolves when actions are ready\nlet actionsReadyResolve: (() => void) | null = null;\nlet actionsReadyPromise: Promise<void> | null = null;\n\n/**\n * Attach a resize listener that clears the render surface when terminal width\n * shrinks. This prevents stale frame artifacts when wrapped content grows in\n * visual line count after a shrink event.\n */\nfunction attachShrinkClearHandler(\n stdout: NodeJS.WriteStream | undefined,\n clear: () => void,\n): () => void {\n if (!stdout) {\n return () => undefined;\n }\n\n let previousWidth = stdout.columns || 80;\n\n const handleResize = () => {\n const currentWidth = stdout.columns || previousWidth || 80;\n\n if (currentWidth < previousWidth) {\n clear();\n if (stdout.isTTY) {\n stdout.write(ansiEscapes.clearTerminal);\n }\n }\n\n previousWidth = currentWidth;\n };\n\n // Run before Ink's internal resize listener to clear stale frame state first.\n if (typeof stdout.prependListener === 'function') {\n stdout.prependListener('resize', handleResize);\n } else {\n stdout.on('resize', handleResize);\n }\n\n return () => {\n stdout.off('resize', handleResize);\n };\n}\n\n/**\n * Get the current wizard actions.\n * Returns null if the wizard hasn't been started yet.\n */\nexport function getWizardActions(): WizardActions | null {\n return currentActions;\n}\n\n/**\n * Set the current wizard actions (called from WizardActionsCapture)\n */\nfunction setWizardActions(actions: WizardActions): void {\n currentActions = actions;\n // Resolve the ready promise when actions are available\n if (actionsReadyResolve) {\n actionsReadyResolve();\n actionsReadyResolve = null;\n }\n}\n\n/**\n * Component that captures actions from context and exposes them globally\n */\nfunction WizardActionsCapture({\n children,\n onActions,\n}: {\n children: React.ReactNode;\n onActions: (actions: WizardActions) => void;\n}): React.ReactElement {\n const actions = useActions();\n\n React.useEffect(() => {\n onActions(actions);\n }, [actions, onActions]);\n\n return <>{children}</>;\n}\n\n/**\n * Start the wizard UI with a single Ink render call.\n * All prompts and spinners will use this single instance.\n */\nexport function startWizardUI(): WizardInstance {\n // Create the ready promise\n actionsReadyPromise = new Promise<void>((resolve) => {\n actionsReadyResolve = resolve;\n });\n\n let resolveExit: () => void;\n const exitPromise = new Promise<void>((resolve) => {\n resolveExit = resolve;\n });\n\n const handleExit = () => {\n resolveExit();\n };\n\n // Create the app with WizardProvider that captures actions\n const App = () => (\n <WizardProvider onExit={handleExit}>\n <WizardActionsCapture onActions={setWizardActions}>\n <WizardApp />\n </WizardActionsCapture>\n </WizardProvider>\n );\n\n const instance = render(<App />, {\n exitOnCtrlC: false, // We handle Ctrl+C in components\n });\n\n const detachShrinkClearHandler = attachShrinkClearHandler(\n process.stdout,\n () => {\n instance.clear();\n },\n );\n\n let isDisposed = false;\n const dispose = () => {\n if (isDisposed) {\n return;\n }\n\n isDisposed = true;\n detachShrinkClearHandler();\n currentActions = null;\n actionsReadyPromise = null;\n actionsReadyResolve = null;\n instance.unmount();\n };\n\n return {\n waitUntilExit: async () => {\n await exitPromise;\n dispose();\n },\n unmount: () => {\n dispose();\n },\n clear: () => {\n instance.clear();\n },\n get actions() {\n return currentActions;\n },\n waitUntilReady: async () => {\n if (actionsReadyPromise) {\n await actionsReadyPromise;\n }\n },\n };\n}\n\n/**\n * Check if the wizard UI is running\n */\nexport function isWizardRunning(): boolean {\n return currentActions !== null;\n}\n"]}
@@ -153,6 +153,8 @@ export type FeedbackSelectResult<T> = {
153
153
  export interface ContinuePromptOptions {
154
154
  message: string;
155
155
  buttonLabel?: string;
156
+ /** If true, resolve on any keypress instead of requiring Enter */
157
+ anyKey?: boolean;
156
158
  }
157
159
  /**
158
160
  * Status of a tool call
@@ -178,7 +180,7 @@ export interface ToolCallInfo {
178
180
  */
179
181
  export interface AgentQueryHandle {
180
182
  /** Interrupt the current agent execution */
181
- interrupt: () => Promise<void>;
182
- /** @deprecated No-op - use interrupt() then resume with a new prompt instead */
183
+ interrupt: (fromUserMessage?: boolean) => Promise<void>;
184
+ /** Queue a user message for the active conversation */
183
185
  sendMessage: (message: string) => void;
184
186
  }
@@ -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}\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: () => Promise<void>;\n /** @deprecated No-op - use interrupt() then resume with a new prompt instead */\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 };\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"]}
@@ -383,10 +383,6 @@ async function startCallbackServer(expectedState) {
383
383
  </div>
384
384
  <h1>Login Complete</h1>
385
385
  <p>You're all set! Return to your terminal.</p>
386
- <div class="terminal-hint">
387
- <span class="terminal-icon">></span>
388
- <span>Raindrop wizard is working<span class="blink">_</span></span>
389
- </div>
390
386
  </div>
391
387
  <div class="footer">
392
388
  <a href="https://raindrop.ai/docs" target="_blank">Need help? Check out our docs</a>