@raindrop-ai/wizard 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. package/LICENSE +47 -0
  2. package/dist/bin.d.ts +2 -0
  3. package/dist/bin.js +117 -0
  4. package/dist/bin.js.map +1 -0
  5. package/dist/src/docs/browser.md +105 -0
  6. package/dist/src/docs/python.md +618 -0
  7. package/dist/src/docs/typescript.md +584 -0
  8. package/dist/src/docs/vercel-ai-sdk.md +304 -0
  9. package/dist/src/lib/agent-interface.d.ts +46 -0
  10. package/dist/src/lib/agent-interface.js +292 -0
  11. package/dist/src/lib/agent-interface.js.map +1 -0
  12. package/dist/src/lib/agent-prompts.d.ts +10 -0
  13. package/dist/src/lib/agent-prompts.js +49 -0
  14. package/dist/src/lib/agent-prompts.js.map +1 -0
  15. package/dist/src/lib/config.d.ts +39 -0
  16. package/dist/src/lib/config.js +549 -0
  17. package/dist/src/lib/config.js.map +1 -0
  18. package/dist/src/lib/constants.d.ts +27 -0
  19. package/dist/src/lib/constants.js +165 -0
  20. package/dist/src/lib/constants.js.map +1 -0
  21. package/dist/src/lib/handlers.d.ts +68 -0
  22. package/dist/src/lib/handlers.js +420 -0
  23. package/dist/src/lib/handlers.js.map +1 -0
  24. package/dist/src/lib/integration-testing.d.ts +44 -0
  25. package/dist/src/lib/integration-testing.js +123 -0
  26. package/dist/src/lib/integration-testing.js.map +1 -0
  27. package/dist/src/lib/mcp.d.ts +14 -0
  28. package/dist/src/lib/mcp.js +134 -0
  29. package/dist/src/lib/mcp.js.map +1 -0
  30. package/dist/src/lib/sdk-messages.d.ts +17 -0
  31. package/dist/src/lib/sdk-messages.js +278 -0
  32. package/dist/src/lib/sdk-messages.js.map +1 -0
  33. package/dist/src/lib/wizard.d.ts +6 -0
  34. package/dist/src/lib/wizard.js +131 -0
  35. package/dist/src/lib/wizard.js.map +1 -0
  36. package/dist/src/run.d.ts +8 -0
  37. package/dist/src/run.js +53 -0
  38. package/dist/src/run.js.map +1 -0
  39. package/dist/src/ui/App.d.ts +15 -0
  40. package/dist/src/ui/App.js +27 -0
  41. package/dist/src/ui/App.js.map +1 -0
  42. package/dist/src/ui/cancellation.d.ts +14 -0
  43. package/dist/src/ui/cancellation.js +17 -0
  44. package/dist/src/ui/cancellation.js.map +1 -0
  45. package/dist/src/ui/components/ClarifyingQuestionsPrompt.d.ts +17 -0
  46. package/dist/src/ui/components/ClarifyingQuestionsPrompt.js +359 -0
  47. package/dist/src/ui/components/ClarifyingQuestionsPrompt.js.map +1 -0
  48. package/dist/src/ui/components/ContinuePrompt.d.ts +14 -0
  49. package/dist/src/ui/components/ContinuePrompt.js +23 -0
  50. package/dist/src/ui/components/ContinuePrompt.js.map +1 -0
  51. package/dist/src/ui/components/DiffDisplay.d.ts +18 -0
  52. package/dist/src/ui/components/DiffDisplay.js +110 -0
  53. package/dist/src/ui/components/DiffDisplay.js.map +1 -0
  54. package/dist/src/ui/components/FeedbackSelectPrompt.d.ts +20 -0
  55. package/dist/src/ui/components/FeedbackSelectPrompt.js +132 -0
  56. package/dist/src/ui/components/FeedbackSelectPrompt.js.map +1 -0
  57. package/dist/src/ui/components/HistoryItemDisplay.d.ts +14 -0
  58. package/dist/src/ui/components/HistoryItemDisplay.js +140 -0
  59. package/dist/src/ui/components/HistoryItemDisplay.js.map +1 -0
  60. package/dist/src/ui/components/Logo.d.ts +10 -0
  61. package/dist/src/ui/components/Logo.js +47 -0
  62. package/dist/src/ui/components/Logo.js.map +1 -0
  63. package/dist/src/ui/components/OrgInfoBox.d.ts +11 -0
  64. package/dist/src/ui/components/OrgInfoBox.js +16 -0
  65. package/dist/src/ui/components/OrgInfoBox.js.map +1 -0
  66. package/dist/src/ui/components/PendingPrompt.d.ts +18 -0
  67. package/dist/src/ui/components/PendingPrompt.js +57 -0
  68. package/dist/src/ui/components/PendingPrompt.js.map +1 -0
  69. package/dist/src/ui/components/PersistentTextInput.d.ts +21 -0
  70. package/dist/src/ui/components/PersistentTextInput.js +117 -0
  71. package/dist/src/ui/components/PersistentTextInput.js.map +1 -0
  72. package/dist/src/ui/components/PlanApprovalPrompt.d.ts +19 -0
  73. package/dist/src/ui/components/PlanApprovalPrompt.js +62 -0
  74. package/dist/src/ui/components/PlanApprovalPrompt.js.map +1 -0
  75. package/dist/src/ui/components/PromptContainer.d.ts +14 -0
  76. package/dist/src/ui/components/PromptContainer.js +18 -0
  77. package/dist/src/ui/components/PromptContainer.js.map +1 -0
  78. package/dist/src/ui/components/SelectPrompt.d.ts +14 -0
  79. package/dist/src/ui/components/SelectPrompt.js +62 -0
  80. package/dist/src/ui/components/SelectPrompt.js.map +1 -0
  81. package/dist/src/ui/components/SpinnerDisplay.d.ts +13 -0
  82. package/dist/src/ui/components/SpinnerDisplay.js +11 -0
  83. package/dist/src/ui/components/SpinnerDisplay.js.map +1 -0
  84. package/dist/src/ui/components/ToolApprovalPrompt.d.ts +14 -0
  85. package/dist/src/ui/components/ToolApprovalPrompt.js +142 -0
  86. package/dist/src/ui/components/ToolApprovalPrompt.js.map +1 -0
  87. package/dist/src/ui/components/ToolCallDisplay.d.ts +14 -0
  88. package/dist/src/ui/components/ToolCallDisplay.js +83 -0
  89. package/dist/src/ui/components/ToolCallDisplay.js.map +1 -0
  90. package/dist/src/ui/components/WriteKeyDisplay.d.ts +15 -0
  91. package/dist/src/ui/components/WriteKeyDisplay.js +13 -0
  92. package/dist/src/ui/components/WriteKeyDisplay.js.map +1 -0
  93. package/dist/src/ui/contexts/WizardContext.d.ts +210 -0
  94. package/dist/src/ui/contexts/WizardContext.js +362 -0
  95. package/dist/src/ui/contexts/WizardContext.js.map +1 -0
  96. package/dist/src/ui/hooks/useCancellation.d.ts +15 -0
  97. package/dist/src/ui/hooks/useCancellation.js +25 -0
  98. package/dist/src/ui/hooks/useCancellation.js.map +1 -0
  99. package/dist/src/ui/render.d.ts +34 -0
  100. package/dist/src/ui/render.js +94 -0
  101. package/dist/src/ui/render.js.map +1 -0
  102. package/dist/src/ui/types.d.ts +184 -0
  103. package/dist/src/ui/types.js +6 -0
  104. package/dist/src/ui/types.js.map +1 -0
  105. package/dist/src/utils/clack-utils.d.ts +13 -0
  106. package/dist/src/utils/clack-utils.js +131 -0
  107. package/dist/src/utils/clack-utils.js.map +1 -0
  108. package/dist/src/utils/debug.d.ts +13 -0
  109. package/dist/src/utils/debug.js +47 -0
  110. package/dist/src/utils/debug.js.map +1 -0
  111. package/dist/src/utils/environment.d.ts +5 -0
  112. package/dist/src/utils/environment.js +131 -0
  113. package/dist/src/utils/environment.js.map +1 -0
  114. package/dist/src/utils/logging.d.ts +9 -0
  115. package/dist/src/utils/logging.js +38 -0
  116. package/dist/src/utils/logging.js.map +1 -0
  117. package/dist/src/utils/oauth.d.ts +12 -0
  118. package/dist/src/utils/oauth.js +497 -0
  119. package/dist/src/utils/oauth.js.map +1 -0
  120. package/dist/src/utils/package-json-types.d.ts +44 -0
  121. package/dist/src/utils/package-json-types.js +6 -0
  122. package/dist/src/utils/package-json-types.js.map +1 -0
  123. package/dist/src/utils/package-json.d.ts +19 -0
  124. package/dist/src/utils/package-json.js +22 -0
  125. package/dist/src/utils/package-json.js.map +1 -0
  126. package/dist/src/utils/session.d.ts +2 -0
  127. package/dist/src/utils/session.js +87 -0
  128. package/dist/src/utils/session.js.map +1 -0
  129. package/dist/src/utils/types.d.ts +61 -0
  130. package/dist/src/utils/types.js +2 -0
  131. package/dist/src/utils/types.js.map +1 -0
  132. package/dist/src/utils/ui.d.ts +120 -0
  133. package/dist/src/utils/ui.js +164 -0
  134. package/dist/src/utils/ui.js.map +1 -0
  135. package/package.json +140 -0
@@ -0,0 +1,362 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ /**
3
+ * Central state management for the unified Ink wizard app.
4
+ * Uses React Context to share state between all UI components.
5
+ */
6
+ import { createContext, useContext, useState, useCallback, useRef, useMemo, } from 'react';
7
+ import { SPINNER_MESSAGE } from '../../lib/constants.js';
8
+ // Create the context with a null default (must be used within provider)
9
+ const WizardContext = createContext(null);
10
+ /**
11
+ * Hook to access wizard state and actions
12
+ */
13
+ export function useWizard() {
14
+ const context = useContext(WizardContext);
15
+ if (!context) {
16
+ throw new Error('useWizard must be used within a WizardProvider');
17
+ }
18
+ return context;
19
+ }
20
+ /**
21
+ * Hook to access just the wizard state
22
+ */
23
+ export function useWizardState() {
24
+ return useWizard().state;
25
+ }
26
+ /**
27
+ * Hook to access just the wizard actions
28
+ */
29
+ export function useWizardActions() {
30
+ return useWizard().actions;
31
+ }
32
+ /**
33
+ * Provider component that manages all wizard state
34
+ */
35
+ export function WizardProvider({ children, onExit, }) {
36
+ // State
37
+ const [history, setHistory] = useState([]);
38
+ // Queue of pending items - processes one at a time, FIFO order
39
+ // This allows multiple tool approvals to be queued without losing earlier ones
40
+ // Note: persistent-input is NOT stored in queue, it's a fallback shown when queue is empty
41
+ const [pendingQueue, setPendingQueue] = useState([]);
42
+ const [shouldExit, setShouldExit] = useState(false);
43
+ const [agentState, setAgentStateInternal] = useState({
44
+ isRunning: false,
45
+ });
46
+ // Spinner state - separate from pendingItem so both can be visible
47
+ const [activeSpinner, setActiveSpinner] = useState(null);
48
+ // Persistent input config - stored separately, shown as fallback when queue is empty
49
+ const [persistentInputConfig, setPersistentInputConfig] = useState(null);
50
+ // Ref to store persistent input pending item - reuse same object to prevent re-renders
51
+ const persistentInputItemRef = useRef(null);
52
+ // Ref to store the last valid pending item to prevent flickering
53
+ const lastValidPendingItemRef = useRef(null);
54
+ // Derive current pending item:
55
+ // 1. If queue has items → show first item in queue
56
+ // 2. If queue is empty AND persistent input is active → show persistent input
57
+ // 3. Otherwise → keep showing the last valid item to prevent flickering
58
+ const pendingItem = useMemo(() => {
59
+ let newPendingItem = null;
60
+ // Priority 1: Items in queue
61
+ if (pendingQueue.length > 0) {
62
+ newPendingItem = pendingQueue[0];
63
+ }
64
+ // Priority 2: Persistent input (fallback when queue is empty)
65
+ else if (persistentInputConfig) {
66
+ // Reuse the same pending item object if the config hasn't changed
67
+ // This prevents unnecessary re-renders when switching back to persistent input
68
+ const currentRef = persistentInputItemRef.current;
69
+ const propsMatch = currentRef &&
70
+ currentRef.props.onSubmit ===
71
+ persistentInputConfig.onSubmit &&
72
+ currentRef.props.onInterrupt ===
73
+ persistentInputConfig.onInterrupt &&
74
+ currentRef.props.onCtrlC ===
75
+ persistentInputConfig.onCtrlC &&
76
+ currentRef.props.message ===
77
+ persistentInputConfig.message &&
78
+ currentRef.props.placeholder ===
79
+ (persistentInputConfig.placeholder ??
80
+ 'Type a message or press Esc to interrupt...') &&
81
+ currentRef.props.defaultValue ===
82
+ persistentInputConfig.value;
83
+ if (!propsMatch) {
84
+ // Config changed, create new pending item
85
+ persistentInputItemRef.current = {
86
+ type: 'persistent-input',
87
+ props: {
88
+ onSubmit: persistentInputConfig.onSubmit,
89
+ onInterrupt: persistentInputConfig.onInterrupt,
90
+ onCtrlC: persistentInputConfig.onCtrlC,
91
+ placeholder: persistentInputConfig.placeholder ??
92
+ 'Type a message or press Esc to interrupt...',
93
+ message: persistentInputConfig.message,
94
+ defaultValue: persistentInputConfig.value,
95
+ },
96
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
97
+ resolve: () => { },
98
+ };
99
+ }
100
+ newPendingItem = persistentInputItemRef.current;
101
+ }
102
+ // If we have a valid new pending item, update the ref and return it
103
+ if (newPendingItem) {
104
+ lastValidPendingItemRef.current = newPendingItem;
105
+ return newPendingItem;
106
+ }
107
+ // If no new pending item but we have a last valid one, keep showing it to prevent flickering
108
+ // This handles intermediate render states where pendingQueue might be temporarily empty
109
+ if (lastValidPendingItemRef.current) {
110
+ return lastValidPendingItemRef.current;
111
+ }
112
+ // No pending items at all
113
+ persistentInputItemRef.current = null;
114
+ lastValidPendingItemRef.current = null;
115
+ return null;
116
+ }, [pendingQueue, persistentInputConfig]);
117
+ // Counter for unique IDs
118
+ const idCounter = useRef(0);
119
+ // Get next unique ID
120
+ const getNextId = useCallback(() => {
121
+ return ++idCounter.current;
122
+ }, []);
123
+ // Add item to history (direct, like gemini-cli)
124
+ const addItem = useCallback((item) => {
125
+ setHistory((prev) => [...prev, { ...item, id: getNextId() }]);
126
+ }, [getNextId]);
127
+ // Deactivate all write-key items in history
128
+ const deactivateWriteKeys = useCallback(() => {
129
+ setHistory((prev) => prev.map((item) => item.type === 'write-key' && item.isActive
130
+ ? { ...item, isActive: false }
131
+ : item));
132
+ }, []);
133
+ // Resolve current pending item and advance the queue
134
+ const resolvePending = useCallback((value) => {
135
+ // Clear the last valid pending item ref to prevent flickering/repeating the old question
136
+ lastValidPendingItemRef.current = null;
137
+ setPendingQueue((queue) => {
138
+ if (queue.length > 0) {
139
+ // Resolve the first item in the queue
140
+ queue[0].resolve(value);
141
+ // Return the queue without the first item (shift)
142
+ return queue.slice(1);
143
+ }
144
+ return queue;
145
+ });
146
+ }, []);
147
+ // Show select prompt - adds to queue
148
+ const select = useCallback((options) => {
149
+ return new Promise((resolve) => {
150
+ setPendingQueue((queue) => [
151
+ ...queue,
152
+ {
153
+ type: 'select',
154
+ props: options,
155
+ resolve: resolve,
156
+ },
157
+ ]);
158
+ });
159
+ }, []);
160
+ // Show text prompt - adds to queue
161
+ const text = useCallback((options) => {
162
+ return new Promise((resolve) => {
163
+ setPendingQueue((queue) => [
164
+ ...queue,
165
+ {
166
+ type: 'text',
167
+ props: options,
168
+ resolve: resolve,
169
+ },
170
+ ]);
171
+ });
172
+ }, []);
173
+ // Show continue button prompt - adds to queue
174
+ const continuePrompt = useCallback((options) => {
175
+ return new Promise((resolve) => {
176
+ setPendingQueue((queue) => [
177
+ ...queue,
178
+ {
179
+ type: 'continue',
180
+ props: options,
181
+ resolve: resolve,
182
+ },
183
+ ]);
184
+ });
185
+ }, []);
186
+ // Show spinner - uses separate activeSpinner state so it can be visible alongside pendingItem
187
+ const spinner = useCallback(() => {
188
+ return {
189
+ start: (msg = '') => {
190
+ setActiveSpinner(msg || SPINNER_MESSAGE);
191
+ },
192
+ stop: (msg = '') => {
193
+ if (msg) {
194
+ addItem({ type: 'spinner-result', text: msg });
195
+ }
196
+ setActiveSpinner(null);
197
+ },
198
+ message: (msg) => {
199
+ setActiveSpinner(msg);
200
+ },
201
+ };
202
+ }, [addItem]);
203
+ // Exit the app
204
+ const exit = useCallback(() => {
205
+ setShouldExit(true);
206
+ onExit?.();
207
+ }, [onExit]);
208
+ // ========================================================================
209
+ // Agent-related actions
210
+ // ========================================================================
211
+ // Show tool approval prompt - adds to queue
212
+ // Persistent input automatically shows when queue becomes empty (it's a fallback, not in queue)
213
+ const toolApproval = useCallback((props) => {
214
+ return new Promise((resolve) => {
215
+ setPendingQueue((queue) => [
216
+ ...queue,
217
+ {
218
+ type: 'tool-approval',
219
+ props,
220
+ resolve: resolve,
221
+ },
222
+ ]);
223
+ });
224
+ }, []);
225
+ // Show clarifying questions prompt - adds to queue
226
+ // Persistent input automatically shows when queue becomes empty
227
+ const clarifyingQuestions = useCallback((props) => {
228
+ return new Promise((resolve) => {
229
+ setPendingQueue((queue) => [
230
+ ...queue,
231
+ {
232
+ type: 'clarifying-questions',
233
+ props,
234
+ resolve: resolve,
235
+ },
236
+ ]);
237
+ });
238
+ }, []);
239
+ // Show plan approval prompt - adds plan to history first (static), then adds selection to queue
240
+ // Persistent input automatically shows when queue becomes empty
241
+ const planApproval = useCallback((props) => {
242
+ // First, add the plan content to history so it's static and doesn't re-render
243
+ addItem({
244
+ type: 'plan-review',
245
+ text: 'Ready to execute the plan?',
246
+ planContent: props.planContent,
247
+ });
248
+ // Then show just the selection prompt as pending item
249
+ return new Promise((resolve) => {
250
+ setPendingQueue((queue) => [
251
+ ...queue,
252
+ {
253
+ type: 'plan-approval',
254
+ props,
255
+ resolve: resolve,
256
+ },
257
+ ]);
258
+ });
259
+ }, [addItem]);
260
+ // Show feedback select prompt - adds to queue
261
+ const feedbackSelect = useCallback((options) => {
262
+ return new Promise((resolve) => {
263
+ setPendingQueue((queue) => [
264
+ ...queue,
265
+ {
266
+ type: 'feedback-select',
267
+ props: options,
268
+ resolve: resolve,
269
+ },
270
+ ]);
271
+ });
272
+ }, []);
273
+ // Start persistent input mode - sets config so it shows as fallback when queue is empty
274
+ 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
+ }));
281
+ // Also store callbacks in agent state for external access if needed
282
+ setAgentStateInternal((current) => ({
283
+ ...current,
284
+ persistentInputCallbacks: {
285
+ onSubmit: config.onSubmit,
286
+ onInterrupt: config.onInterrupt,
287
+ },
288
+ }));
289
+ }, []);
290
+ // Stop persistent input mode - clears config so it no longer shows
291
+ const stopPersistentInput = useCallback(() => {
292
+ setPersistentInputConfig(null);
293
+ // Also clear the refs to prevent the input from lingering
294
+ persistentInputItemRef.current = null;
295
+ lastValidPendingItemRef.current = null;
296
+ setAgentStateInternal((current) => ({
297
+ ...current,
298
+ persistentInputCallbacks: undefined,
299
+ }));
300
+ }, []);
301
+ // Update persistent input value - allows PersistentTextInput to save its state
302
+ const updatePersistentInputValue = useCallback((value) => {
303
+ setPersistentInputConfig((prev) => {
304
+ if (!prev)
305
+ return prev;
306
+ return { ...prev, value };
307
+ });
308
+ }, []);
309
+ // Update agent state
310
+ const setAgentState = useCallback((state) => {
311
+ setAgentStateInternal((current) => ({ ...current, ...state }));
312
+ }, []);
313
+ // Combine actions
314
+ const actions = useMemo(() => ({
315
+ addItem,
316
+ deactivateWriteKeys,
317
+ select,
318
+ text,
319
+ continue: continuePrompt,
320
+ spinner,
321
+ resolvePending,
322
+ exit,
323
+ toolApproval,
324
+ clarifyingQuestions,
325
+ planApproval,
326
+ feedbackSelect,
327
+ startPersistentInput,
328
+ stopPersistentInput,
329
+ updatePersistentInputValue,
330
+ setAgentState,
331
+ }), [
332
+ addItem,
333
+ deactivateWriteKeys,
334
+ select,
335
+ text,
336
+ continuePrompt,
337
+ spinner,
338
+ resolvePending,
339
+ exit,
340
+ toolApproval,
341
+ clarifyingQuestions,
342
+ planApproval,
343
+ feedbackSelect,
344
+ startPersistentInput,
345
+ stopPersistentInput,
346
+ updatePersistentInputValue,
347
+ setAgentState,
348
+ ]);
349
+ // Combine state
350
+ const state = useMemo(() => ({
351
+ history,
352
+ pendingItem,
353
+ shouldExit,
354
+ agentState,
355
+ activeSpinner,
356
+ }), [history, pendingItem, shouldExit, agentState, activeSpinner]);
357
+ // Context value
358
+ const contextValue = useMemo(() => ({ state, actions }), [state, actions]);
359
+ return (_jsx(WizardContext.Provider, { value: contextValue, children: children }));
360
+ }
361
+ export { WizardContext };
362
+ //# sourceMappingURL=WizardContext.js.map
@@ -0,0 +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"]}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * React hook for handling Ctrl+C cancellation in Ink components
3
+ * This file has ink dependencies and should only be imported dynamically
4
+ *
5
+ * Note: We don't import useInput at the top level to avoid loading ink
6
+ * before it's needed. Instead, we export a factory function.
7
+ */
8
+ export { CANCEL_SYMBOL, isCancel } from '../cancellation.js';
9
+ /**
10
+ * Create a cancellation handler hook that uses ink's useInput
11
+ * This must be called after ink is dynamically imported
12
+ * @param useInput - The useInput hook from ink
13
+ * @param onCancel - Callback to invoke when user presses Ctrl+C
14
+ */
15
+ export declare function createCancellationHandler(useInput: any): (onCancel: () => void) => void;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * React hook for handling Ctrl+C cancellation in Ink components
3
+ * This file has ink dependencies and should only be imported dynamically
4
+ *
5
+ * Note: We don't import useInput at the top level to avoid loading ink
6
+ * before it's needed. Instead, we export a factory function.
7
+ */
8
+ // Re-export for convenience in components
9
+ export { CANCEL_SYMBOL, isCancel } from '../cancellation.js';
10
+ /**
11
+ * Create a cancellation handler hook that uses ink's useInput
12
+ * This must be called after ink is dynamically imported
13
+ * @param useInput - The useInput hook from ink
14
+ * @param onCancel - Callback to invoke when user presses Ctrl+C
15
+ */
16
+ export function createCancellationHandler(useInput) {
17
+ return function useCancellation(onCancel) {
18
+ useInput((input, key) => {
19
+ if (key.ctrl && input === 'c') {
20
+ onCancel();
21
+ }
22
+ });
23
+ };
24
+ }
25
+ //# sourceMappingURL=useCancellation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useCancellation.js","sourceRoot":"","sources":["../../../../src/ui/hooks/useCancellation.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,0CAA0C;AAC1C,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE7D;;;;;GAKG;AACH,MAAM,UAAU,yBAAyB,CAAC,QAAa;IACrD,OAAO,SAAS,eAAe,CAAC,QAAoB;QAClD,QAAQ,CAAC,CAAC,KAAa,EAAE,GAAQ,EAAE,EAAE;YACnC,IAAI,GAAG,CAAC,IAAI,IAAI,KAAK,KAAK,GAAG,EAAE,CAAC;gBAC9B,QAAQ,EAAE,CAAC;YACb,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC","sourcesContent":["/**\n * React hook for handling Ctrl+C cancellation in Ink components\n * This file has ink dependencies and should only be imported dynamically\n *\n * Note: We don't import useInput at the top level to avoid loading ink\n * before it's needed. Instead, we export a factory function.\n */\n\n// Re-export for convenience in components\nexport { CANCEL_SYMBOL, isCancel } from '../cancellation.js';\n\n/**\n * Create a cancellation handler hook that uses ink's useInput\n * This must be called after ink is dynamically imported\n * @param useInput - The useInput hook from ink\n * @param onCancel - Callback to invoke when user presses Ctrl+C\n */\nexport function createCancellationHandler(useInput: any) {\n return function useCancellation(onCancel: () => void): void {\n useInput((input: string, key: any) => {\n if (key.ctrl && input === 'c') {\n onCancel();\n }\n });\n };\n}\n"]}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Single render entry point for the unified Ink app.
3
+ * Only one render() call is made for the entire wizard session.
4
+ */
5
+ import { type WizardActions } from './contexts/WizardContext.js';
6
+ /**
7
+ * Instance returned by startWizardUI
8
+ */
9
+ export interface WizardInstance {
10
+ /** Wait for the wizard to exit */
11
+ waitUntilExit: () => Promise<void>;
12
+ /** Unmount the wizard UI */
13
+ unmount: () => void;
14
+ /** Clear the screen */
15
+ clear: () => void;
16
+ /** Get the wizard actions for programmatic control */
17
+ actions: WizardActions | null;
18
+ /** Wait for the wizard to be ready (actions available) */
19
+ waitUntilReady: () => Promise<void>;
20
+ }
21
+ /**
22
+ * Get the current wizard actions.
23
+ * Returns null if the wizard hasn't been started yet.
24
+ */
25
+ export declare function getWizardActions(): WizardActions | null;
26
+ /**
27
+ * Start the wizard UI with a single Ink render call.
28
+ * All prompts and spinners will use this single instance.
29
+ */
30
+ export declare function startWizardUI(): WizardInstance;
31
+ /**
32
+ * Check if the wizard UI is running
33
+ */
34
+ export declare function isWizardRunning(): boolean;
@@ -0,0 +1,94 @@
1
+ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
2
+ /**
3
+ * Single render entry point for the unified Ink app.
4
+ * Only one render() call is made for the entire wizard session.
5
+ */
6
+ import React from 'react';
7
+ import { render } from 'ink';
8
+ import { WizardApp } from './App.js';
9
+ import { WizardProvider, useWizardActions as useActions, } from './contexts/WizardContext.js';
10
+ // Global reference to the current wizard actions
11
+ let currentActions = null;
12
+ // Promise that resolves when actions are ready
13
+ let actionsReadyResolve = null;
14
+ let actionsReadyPromise = null;
15
+ /**
16
+ * Get the current wizard actions.
17
+ * Returns null if the wizard hasn't been started yet.
18
+ */
19
+ export function getWizardActions() {
20
+ return currentActions;
21
+ }
22
+ /**
23
+ * Set the current wizard actions (called from WizardActionsCapture)
24
+ */
25
+ function setWizardActions(actions) {
26
+ currentActions = actions;
27
+ // Resolve the ready promise when actions are available
28
+ if (actionsReadyResolve) {
29
+ actionsReadyResolve();
30
+ actionsReadyResolve = null;
31
+ }
32
+ }
33
+ /**
34
+ * Component that captures actions from context and exposes them globally
35
+ */
36
+ function WizardActionsCapture({ children, onActions, }) {
37
+ const actions = useActions();
38
+ React.useEffect(() => {
39
+ onActions(actions);
40
+ }, [actions, onActions]);
41
+ return _jsx(_Fragment, { children: children });
42
+ }
43
+ /**
44
+ * Start the wizard UI with a single Ink render call.
45
+ * All prompts and spinners will use this single instance.
46
+ */
47
+ export function startWizardUI() {
48
+ // Create the ready promise
49
+ actionsReadyPromise = new Promise((resolve) => {
50
+ actionsReadyResolve = resolve;
51
+ });
52
+ let resolveExit;
53
+ const exitPromise = new Promise((resolve) => {
54
+ resolveExit = resolve;
55
+ });
56
+ const handleExit = () => {
57
+ resolveExit();
58
+ };
59
+ // Create the app with WizardProvider that captures actions
60
+ const App = () => (_jsx(WizardProvider, { onExit: handleExit, children: _jsx(WizardActionsCapture, { onActions: setWizardActions, children: _jsx(WizardApp, {}) }) }));
61
+ const instance = render(_jsx(App, {}), {
62
+ exitOnCtrlC: false, // We handle Ctrl+C in components
63
+ });
64
+ return {
65
+ waitUntilExit: async () => {
66
+ await exitPromise;
67
+ instance.unmount();
68
+ },
69
+ unmount: () => {
70
+ currentActions = null;
71
+ actionsReadyPromise = null;
72
+ actionsReadyResolve = null;
73
+ instance.unmount();
74
+ },
75
+ clear: () => {
76
+ instance.clear();
77
+ },
78
+ get actions() {
79
+ return currentActions;
80
+ },
81
+ waitUntilReady: async () => {
82
+ if (actionsReadyPromise) {
83
+ await actionsReadyPromise;
84
+ }
85
+ },
86
+ };
87
+ }
88
+ /**
89
+ * Check if the wizard UI is running
90
+ */
91
+ export function isWizardRunning() {
92
+ return currentActions !== null;
93
+ }
94
+ //# sourceMappingURL=render.js.map
@@ -0,0 +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"]}