@moldable-ai/ui 0.2.17 → 0.2.19

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 (232) hide show
  1. package/dist/components/chat/chat-panel.d.ts +18 -12
  2. package/dist/components/chat/chat-panel.d.ts.map +1 -1
  3. package/dist/components/chat/chat-panel.js +73 -19
  4. package/dist/components/chat/index.d.ts +2 -1
  5. package/dist/components/chat/index.d.ts.map +1 -1
  6. package/dist/components/chat/index.js +2 -1
  7. package/dist/components/chat/model-effort-power-effects.d.ts +7 -0
  8. package/dist/components/chat/model-effort-power-effects.d.ts.map +1 -0
  9. package/dist/components/chat/model-effort-power-effects.js +54 -0
  10. package/dist/components/chat/model-effort-selector.d.ts +26 -0
  11. package/dist/components/chat/model-effort-selector.d.ts.map +1 -0
  12. package/dist/components/chat/model-effort-selector.js +179 -0
  13. package/dist/components/chat/model-effort-ultra-effects.d.ts +5 -0
  14. package/dist/components/chat/model-effort-ultra-effects.d.ts.map +1 -0
  15. package/dist/components/chat/model-effort-ultra-effects.js +56 -0
  16. package/dist/components/chat/tool-handlers.d.ts.map +1 -1
  17. package/dist/components/hardware/bluetooth-panel-helpers.d.ts +9 -0
  18. package/dist/components/hardware/bluetooth-panel-helpers.d.ts.map +1 -0
  19. package/dist/components/hardware/bluetooth-panel-helpers.js +37 -0
  20. package/dist/components/hardware/bluetooth-panel.d.ts +56 -0
  21. package/dist/components/hardware/bluetooth-panel.d.ts.map +1 -0
  22. package/dist/components/hardware/bluetooth-panel.js +470 -0
  23. package/dist/components/hardware/camera-preview.d.ts +39 -0
  24. package/dist/components/hardware/camera-preview.d.ts.map +1 -0
  25. package/dist/components/hardware/camera-preview.js +228 -0
  26. package/dist/components/hardware/capability-badge.d.ts +23 -0
  27. package/dist/components/hardware/capability-badge.d.ts.map +1 -0
  28. package/dist/components/hardware/capability-badge.js +39 -0
  29. package/dist/components/hardware/capability-matrix.d.ts +14 -0
  30. package/dist/components/hardware/capability-matrix.d.ts.map +1 -0
  31. package/dist/components/hardware/capability-matrix.js +97 -0
  32. package/dist/components/hardware/clipboard-button.d.ts +26 -0
  33. package/dist/components/hardware/clipboard-button.d.ts.map +1 -0
  34. package/dist/components/hardware/clipboard-button.js +114 -0
  35. package/dist/components/hardware/device-io-controls.d.ts +4 -0
  36. package/dist/components/hardware/device-io-controls.d.ts.map +1 -0
  37. package/dist/components/hardware/device-io-controls.js +28 -0
  38. package/dist/components/hardware/device-list.d.ts +20 -0
  39. package/dist/components/hardware/device-list.d.ts.map +1 -0
  40. package/dist/components/hardware/device-list.js +14 -0
  41. package/dist/components/hardware/display-map.d.ts +23 -0
  42. package/dist/components/hardware/display-map.d.ts.map +1 -0
  43. package/dist/components/hardware/display-map.js +114 -0
  44. package/dist/components/hardware/haptic-button.d.ts +26 -0
  45. package/dist/components/hardware/haptic-button.d.ts.map +1 -0
  46. package/dist/components/hardware/haptic-button.js +94 -0
  47. package/dist/components/hardware/hardware-panel.d.ts +11 -0
  48. package/dist/components/hardware/hardware-panel.d.ts.map +1 -0
  49. package/dist/components/hardware/hardware-panel.js +28 -0
  50. package/dist/components/hardware/hid-panel.d.ts +40 -0
  51. package/dist/components/hardware/hid-panel.d.ts.map +1 -0
  52. package/dist/components/hardware/hid-panel.js +373 -0
  53. package/dist/components/hardware/index.d.ts +27 -0
  54. package/dist/components/hardware/index.d.ts.map +1 -0
  55. package/dist/components/hardware/index.js +26 -0
  56. package/dist/components/hardware/live-indicator.d.ts +15 -0
  57. package/dist/components/hardware/live-indicator.d.ts.map +1 -0
  58. package/dist/components/hardware/live-indicator.js +26 -0
  59. package/dist/components/hardware/local-auth-button.d.ts +33 -0
  60. package/dist/components/hardware/local-auth-button.d.ts.map +1 -0
  61. package/dist/components/hardware/local-auth-button.js +115 -0
  62. package/dist/components/hardware/location-panel.d.ts +29 -0
  63. package/dist/components/hardware/location-panel.d.ts.map +1 -0
  64. package/dist/components/hardware/location-panel.js +154 -0
  65. package/dist/components/hardware/microphone-meter.d.ts +35 -0
  66. package/dist/components/hardware/microphone-meter.d.ts.map +1 -0
  67. package/dist/components/hardware/microphone-meter.js +244 -0
  68. package/dist/components/hardware/midi-monitor.d.ts +54 -0
  69. package/dist/components/hardware/midi-monitor.d.ts.map +1 -0
  70. package/dist/components/hardware/midi-monitor.js +534 -0
  71. package/dist/components/hardware/notification-panel.d.ts +24 -0
  72. package/dist/components/hardware/notification-panel.d.ts.map +1 -0
  73. package/dist/components/hardware/notification-panel.js +124 -0
  74. package/dist/components/hardware/power-blocker-controller.d.ts +19 -0
  75. package/dist/components/hardware/power-blocker-controller.d.ts.map +1 -0
  76. package/dist/components/hardware/power-blocker-controller.js +83 -0
  77. package/dist/components/hardware/power-panel.d.ts +67 -0
  78. package/dist/components/hardware/power-panel.d.ts.map +1 -0
  79. package/dist/components/hardware/power-panel.js +309 -0
  80. package/dist/components/hardware/readout.d.ts +10 -0
  81. package/dist/components/hardware/readout.d.ts.map +1 -0
  82. package/dist/components/hardware/readout.js +11 -0
  83. package/dist/components/hardware/screen-share-preview.d.ts +36 -0
  84. package/dist/components/hardware/screen-share-preview.d.ts.map +1 -0
  85. package/dist/components/hardware/screen-share-preview.js +191 -0
  86. package/dist/components/hardware/secure-storage-panel.d.ts +36 -0
  87. package/dist/components/hardware/secure-storage-panel.d.ts.map +1 -0
  88. package/dist/components/hardware/secure-storage-panel.js +193 -0
  89. package/dist/components/hardware/serial-console.d.ts +64 -0
  90. package/dist/components/hardware/serial-console.d.ts.map +1 -0
  91. package/dist/components/hardware/serial-console.js +399 -0
  92. package/dist/components/hardware/shortcut-recorder.d.ts +35 -0
  93. package/dist/components/hardware/shortcut-recorder.d.ts.map +1 -0
  94. package/dist/components/hardware/shortcut-recorder.js +217 -0
  95. package/dist/components/hardware/stream-log.d.ts +35 -0
  96. package/dist/components/hardware/stream-log.d.ts.map +1 -0
  97. package/dist/components/hardware/stream-log.js +65 -0
  98. package/dist/components/hardware/system-audio-monitor.d.ts +34 -0
  99. package/dist/components/hardware/system-audio-monitor.d.ts.map +1 -0
  100. package/dist/components/hardware/system-audio-monitor.js +275 -0
  101. package/dist/components/hardware/usb-panel.d.ts +54 -0
  102. package/dist/components/hardware/usb-panel.d.ts.map +1 -0
  103. package/dist/components/hardware/usb-panel.js +363 -0
  104. package/dist/components/hardware/use-capability.d.ts +20 -0
  105. package/dist/components/hardware/use-capability.d.ts.map +1 -0
  106. package/dist/components/hardware/use-capability.js +61 -0
  107. package/dist/components/ui/input-group.d.ts +1 -1
  108. package/dist/components/ui/slider.d.ts +4 -1
  109. package/dist/components/ui/slider.d.ts.map +1 -1
  110. package/dist/components/ui/slider.js +2 -2
  111. package/dist/index.d.ts +3 -1
  112. package/dist/index.d.ts.map +1 -1
  113. package/dist/index.js +5 -1
  114. package/dist/lib/commands.d.ts +59 -0
  115. package/dist/lib/commands.d.ts.map +1 -1
  116. package/dist/lib/commands.js +97 -0
  117. package/dist/lib/native-hardware/bluetooth-access.d.ts +14 -0
  118. package/dist/lib/native-hardware/bluetooth-access.d.ts.map +1 -0
  119. package/dist/lib/native-hardware/bluetooth-access.js +40 -0
  120. package/dist/lib/native-hardware/bluetooth-connection.d.ts +19 -0
  121. package/dist/lib/native-hardware/bluetooth-connection.d.ts.map +1 -0
  122. package/dist/lib/native-hardware/bluetooth-connection.js +88 -0
  123. package/dist/lib/native-hardware/bluetooth-gatt.d.ts +7 -0
  124. package/dist/lib/native-hardware/bluetooth-gatt.d.ts.map +1 -0
  125. package/dist/lib/native-hardware/bluetooth-gatt.js +77 -0
  126. package/dist/lib/native-hardware/bluetooth-internal.d.ts +10 -0
  127. package/dist/lib/native-hardware/bluetooth-internal.d.ts.map +1 -0
  128. package/dist/lib/native-hardware/bluetooth-internal.js +105 -0
  129. package/dist/lib/native-hardware/bluetooth-native-fallback.d.ts +33 -0
  130. package/dist/lib/native-hardware/bluetooth-native-fallback.d.ts.map +1 -0
  131. package/dist/lib/native-hardware/bluetooth-native-fallback.js +214 -0
  132. package/dist/lib/native-hardware/bluetooth-types.d.ts +85 -0
  133. package/dist/lib/native-hardware/bluetooth-types.d.ts.map +1 -0
  134. package/dist/lib/native-hardware/bluetooth-types.js +2 -0
  135. package/dist/lib/native-hardware/bluetooth.d.ts +7 -0
  136. package/dist/lib/native-hardware/bluetooth.d.ts.map +1 -0
  137. package/dist/lib/native-hardware/bluetooth.js +4 -0
  138. package/dist/lib/native-hardware/bridge.d.ts +23 -0
  139. package/dist/lib/native-hardware/bridge.d.ts.map +1 -0
  140. package/dist/lib/native-hardware/bridge.js +266 -0
  141. package/dist/lib/native-hardware/capabilities.d.ts +7 -0
  142. package/dist/lib/native-hardware/capabilities.d.ts.map +1 -0
  143. package/dist/lib/native-hardware/capabilities.js +95 -0
  144. package/dist/lib/native-hardware/clipboard.d.ts +11 -0
  145. package/dist/lib/native-hardware/clipboard.d.ts.map +1 -0
  146. package/dist/lib/native-hardware/clipboard.js +55 -0
  147. package/dist/lib/native-hardware/device-io-errors.d.ts +11 -0
  148. package/dist/lib/native-hardware/device-io-errors.d.ts.map +1 -0
  149. package/dist/lib/native-hardware/device-io-errors.js +82 -0
  150. package/dist/lib/native-hardware/displays.d.ts +38 -0
  151. package/dist/lib/native-hardware/displays.d.ts.map +1 -0
  152. package/dist/lib/native-hardware/displays.js +12 -0
  153. package/dist/lib/native-hardware/global-shortcuts.d.ts +86 -0
  154. package/dist/lib/native-hardware/global-shortcuts.d.ts.map +1 -0
  155. package/dist/lib/native-hardware/global-shortcuts.js +351 -0
  156. package/dist/lib/native-hardware/haptics.d.ts +25 -0
  157. package/dist/lib/native-hardware/haptics.d.ts.map +1 -0
  158. package/dist/lib/native-hardware/haptics.js +18 -0
  159. package/dist/lib/native-hardware/hid-native.d.ts +26 -0
  160. package/dist/lib/native-hardware/hid-native.d.ts.map +1 -0
  161. package/dist/lib/native-hardware/hid-native.js +229 -0
  162. package/dist/lib/native-hardware/hid.d.ts +52 -0
  163. package/dist/lib/native-hardware/hid.d.ts.map +1 -0
  164. package/dist/lib/native-hardware/hid.js +160 -0
  165. package/dist/lib/native-hardware/index.d.ts +38 -0
  166. package/dist/lib/native-hardware/index.d.ts.map +1 -0
  167. package/dist/lib/native-hardware/index.js +20 -0
  168. package/dist/lib/native-hardware/local-authentication.d.ts +32 -0
  169. package/dist/lib/native-hardware/local-authentication.d.ts.map +1 -0
  170. package/dist/lib/native-hardware/local-authentication.js +46 -0
  171. package/dist/lib/native-hardware/location.d.ts +49 -0
  172. package/dist/lib/native-hardware/location.d.ts.map +1 -0
  173. package/dist/lib/native-hardware/location.js +114 -0
  174. package/dist/lib/native-hardware/media-permissions.d.ts +28 -0
  175. package/dist/lib/native-hardware/media-permissions.d.ts.map +1 -0
  176. package/dist/lib/native-hardware/media-permissions.js +37 -0
  177. package/dist/lib/native-hardware/media.d.ts +17 -0
  178. package/dist/lib/native-hardware/media.d.ts.map +1 -0
  179. package/dist/lib/native-hardware/media.js +99 -0
  180. package/dist/lib/native-hardware/midi-access.d.ts +13 -0
  181. package/dist/lib/native-hardware/midi-access.d.ts.map +1 -0
  182. package/dist/lib/native-hardware/midi-access.js +66 -0
  183. package/dist/lib/native-hardware/midi-internal.d.ts +12 -0
  184. package/dist/lib/native-hardware/midi-internal.d.ts.map +1 -0
  185. package/dist/lib/native-hardware/midi-internal.js +88 -0
  186. package/dist/lib/native-hardware/midi-native-fallback.d.ts +27 -0
  187. package/dist/lib/native-hardware/midi-native-fallback.d.ts.map +1 -0
  188. package/dist/lib/native-hardware/midi-native-fallback.js +127 -0
  189. package/dist/lib/native-hardware/midi-ports.d.ts +6 -0
  190. package/dist/lib/native-hardware/midi-ports.d.ts.map +1 -0
  191. package/dist/lib/native-hardware/midi-ports.js +115 -0
  192. package/dist/lib/native-hardware/midi-types.d.ts +25 -0
  193. package/dist/lib/native-hardware/midi-types.d.ts.map +1 -0
  194. package/dist/lib/native-hardware/midi-types.js +1 -0
  195. package/dist/lib/native-hardware/midi.d.ts +6 -0
  196. package/dist/lib/native-hardware/midi.d.ts.map +1 -0
  197. package/dist/lib/native-hardware/midi.js +3 -0
  198. package/dist/lib/native-hardware/native-device-io.d.ts +28 -0
  199. package/dist/lib/native-hardware/native-device-io.d.ts.map +1 -0
  200. package/dist/lib/native-hardware/native-device-io.js +91 -0
  201. package/dist/lib/native-hardware/native-device-lifecycle.d.ts +13 -0
  202. package/dist/lib/native-hardware/native-device-lifecycle.d.ts.map +1 -0
  203. package/dist/lib/native-hardware/native-device-lifecycle.js +40 -0
  204. package/dist/lib/native-hardware/notifications.d.ts +38 -0
  205. package/dist/lib/native-hardware/notifications.d.ts.map +1 -0
  206. package/dist/lib/native-hardware/notifications.js +50 -0
  207. package/dist/lib/native-hardware/power-session.d.ts +113 -0
  208. package/dist/lib/native-hardware/power-session.d.ts.map +1 -0
  209. package/dist/lib/native-hardware/power-session.js +264 -0
  210. package/dist/lib/native-hardware/secure-storage.d.ts +36 -0
  211. package/dist/lib/native-hardware/secure-storage.d.ts.map +1 -0
  212. package/dist/lib/native-hardware/secure-storage.js +64 -0
  213. package/dist/lib/native-hardware/serial-native.d.ts +23 -0
  214. package/dist/lib/native-hardware/serial-native.d.ts.map +1 -0
  215. package/dist/lib/native-hardware/serial-native.js +181 -0
  216. package/dist/lib/native-hardware/serial.d.ts +76 -0
  217. package/dist/lib/native-hardware/serial.d.ts.map +1 -0
  218. package/dist/lib/native-hardware/serial.js +212 -0
  219. package/dist/lib/native-hardware/system-audio.d.ts +127 -0
  220. package/dist/lib/native-hardware/system-audio.d.ts.map +1 -0
  221. package/dist/lib/native-hardware/system-audio.js +330 -0
  222. package/dist/lib/native-hardware/types.d.ts +62 -0
  223. package/dist/lib/native-hardware/types.d.ts.map +1 -0
  224. package/dist/lib/native-hardware/types.js +27 -0
  225. package/dist/lib/native-hardware/usb-native.d.ts +39 -0
  226. package/dist/lib/native-hardware/usb-native.d.ts.map +1 -0
  227. package/dist/lib/native-hardware/usb-native.js +217 -0
  228. package/dist/lib/native-hardware/usb.d.ts +85 -0
  229. package/dist/lib/native-hardware/usb.d.ts.map +1 -0
  230. package/dist/lib/native-hardware/usb.js +222 -0
  231. package/package.json +1 -1
  232. package/src/styles/index.css +377 -0
@@ -3,10 +3,16 @@ import { type ChatImageAttachment, type ChatSlashCommandOption, type ChatSubmitM
3
3
  import { type ChatMessage } from './chat-message';
4
4
  import { type MessageCheckpoint } from './chat-messages';
5
5
  import { type ConversationMeta } from './conversation-history';
6
- import { type ModelOption } from './model-selector';
7
- import { type ReasoningEffortOption } from './reasoning-effort-selector';
6
+ import { type ModelEffortPresetOption, type ModelProviderOption } from './model-effort-selector';
8
7
  import { type ApprovalResponseHandler } from './tool-approval-context';
9
8
  type ChatStatus = 'ready' | 'submitted' | 'streaming' | 'error';
9
+ export type ChatAuthIssue = 'missing-api-key' | 'codex-oauth-expired';
10
+ type ChatAuthIssueInput = {
11
+ missingApiKey?: boolean;
12
+ authIssue?: ChatAuthIssue | null;
13
+ error?: Error | null;
14
+ };
15
+ export declare function resolveChatAuthIssue({ missingApiKey, authIssue, error, }: ChatAuthIssueInput): ChatAuthIssue | null;
10
16
  /**
11
17
  * Progress data for a running tool (command execution with streaming stdout/stderr)
12
18
  */
@@ -47,18 +53,16 @@ export interface ChatPanelProps {
47
53
  onStop?: () => void;
48
54
  /** Handle new chat */
49
55
  onNewChat?: () => void;
50
- /** Available models */
51
- models: ModelOption[];
56
+ /** Direct AI providers available from the user's authenticated accounts */
57
+ modelProviders: ModelProviderOption[];
58
+ /** Model and effort presets shown as slider stops */
59
+ modelEffortPresets: ModelEffortPresetOption[];
52
60
  /** Selected model ID */
53
61
  selectedModel: string;
54
- /** Handle model change */
55
- onModelChange: (modelId: string) => void;
56
- /** Available reasoning effort options (varies by model vendor) */
57
- reasoningEffortOptions?: ReasoningEffortOption[];
58
62
  /** Selected reasoning effort */
59
- selectedReasoningEffort?: string;
60
- /** Handle reasoning effort change */
61
- onReasoningEffortChange?: (effort: string) => void;
63
+ selectedReasoningEffort: string;
64
+ /** Handle one atomic model-and-effort preset change */
65
+ onModelEffortChange: (modelId: string, effort: string) => void;
62
66
  /** Conversation history */
63
67
  conversations?: ConversationMeta[];
64
68
  /** Current conversation ID */
@@ -87,6 +91,8 @@ export interface ChatPanelProps {
87
91
  error?: Error | null;
88
92
  /** Whether API keys are missing */
89
93
  missingApiKey?: boolean;
94
+ /** More specific auth issue to show in the setup prompt */
95
+ authIssue?: ChatAuthIssue | null;
90
96
  /** Callback to trigger API key setup */
91
97
  onAddApiKey?: () => void;
92
98
  /** Progress data for running tools (streaming stdout/stderr) */
@@ -137,6 +143,6 @@ export interface ChatPanelProps {
137
143
  /**
138
144
  * Floating chat panel with model selector
139
145
  */
140
- export declare function ChatPanel({ messages, status, isTurnInFlight, input, onInputChange, onSubmit, onStop, onNewChat, models, selectedModel, onModelChange, reasoningEffortOptions, selectedReasoningEffort, onReasoningEffortChange, conversations, currentConversationId, scrollToBottomSignal, onSelectConversation, onDeleteConversation, placeholder, welcomeMessage, isExpanded, onExpandedChange, isMinimized, onMinimizedChange, className, error, missingApiKey, onAddApiKey, toolProgress, onApprovalResponse, isEditingApp, onEditingAppChange, showEditingAppToggle, checkpoints, restoringMessageId, onRestoreCheckpoint, imageAttachments, onRemoveImageAttachment, isImageDropActive, queuedMessages, onRemoveQueuedMessage, onRetryQueuedMessage, onSteerQueuedMessage, onReorderQueuedMessages, onEditQueuedMessage, slashCommands, onSlashCommandSelect, isCompacting, compactedHistoryStartIndex, contextUsage, }: ChatPanelProps): import("react/jsx-runtime").JSX.Element;
146
+ export declare function ChatPanel({ messages, status, isTurnInFlight, input, onInputChange, onSubmit, onStop, onNewChat, modelProviders, modelEffortPresets, selectedModel, selectedReasoningEffort, onModelEffortChange, conversations, currentConversationId, scrollToBottomSignal, onSelectConversation, onDeleteConversation, placeholder, welcomeMessage, isExpanded, onExpandedChange, isMinimized, onMinimizedChange, className, error, missingApiKey, authIssue, onAddApiKey, toolProgress, onApprovalResponse, isEditingApp, onEditingAppChange, showEditingAppToggle, checkpoints, restoringMessageId, onRestoreCheckpoint, imageAttachments, onRemoveImageAttachment, isImageDropActive, queuedMessages, onRemoveQueuedMessage, onRetryQueuedMessage, onSteerQueuedMessage, onReorderQueuedMessages, onEditQueuedMessage, slashCommands, onSlashCommandSelect, isCompacting, compactedHistoryStartIndex, contextUsage, }: ChatPanelProps): import("react/jsx-runtime").JSX.Element;
141
147
  export {};
142
148
  //# sourceMappingURL=chat-panel.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"chat-panel.d.ts","sourceRoot":"","sources":["../../../src/components/chat/chat-panel.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"chat-panel.d.ts","sourceRoot":"","sources":["../../../src/components/chat/chat-panel.tsx"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- import { AlertCircle, ArrowDown, ChevronDown, ClipboardList, Code2, CornerDownRight, GripVertical, Image as ImageIcon, ListPlus, Pencil, Trash2, } from 'lucide-react';
3
+ import { AlertCircle, ArrowDown, ChevronDown, ClipboardList, Code2, CornerDownRight, ExternalLink, GripVertical, Image as ImageIcon, ListPlus, Pencil, Trash2, } from 'lucide-react';
4
4
  import { useCallback, useEffect, useMemo, useRef, useState, } from 'react';
5
5
  import { cn } from '../../lib/utils';
6
6
  import { Button } from '../ui/button';
@@ -10,8 +10,7 @@ import { ChatInput, } from './chat-input';
10
10
  import { CompactingMessage, ThinkingMessage, } from './chat-message';
11
11
  import { MessageRow, computeIsThinking, } from './chat-messages';
12
12
  import { ConversationHistory, } from './conversation-history';
13
- import { ModelSelector } from './model-selector';
14
- import { ReasoningEffortSelector, } from './reasoning-effort-selector';
13
+ import { ModelEffortSelector, } from './model-effort-selector';
15
14
  import { ToolApprovalProvider, } from './tool-approval-context';
16
15
  import { ToolProgressProvider } from './tool-progress-context';
17
16
  import { DndContext, KeyboardSensor, PointerSensor, closestCenter, useSensor, useSensors, } from '@dnd-kit/core';
@@ -19,6 +18,52 @@ import { SortableContext, sortableKeyboardCoordinates, useSortable, verticalList
19
18
  import { CSS } from '@dnd-kit/utilities';
20
19
  import { AnimatePresence, motion } from 'framer-motion';
21
20
  import { Virtualizer } from 'virtua';
21
+ const CODEX_OAUTH_ERROR_PATTERNS = [
22
+ 'codex oauth',
23
+ 'codex-oauth',
24
+ 'codex_oauth_json',
25
+ 'openai codex authentication',
26
+ 'openai/codex-responses',
27
+ 'chatgpt.com/backend-api/codex',
28
+ 'refresh_token_reused',
29
+ ];
30
+ const MISSING_API_KEY_ERROR_PATTERNS = [
31
+ 'api_key not configured',
32
+ 'api key not found',
33
+ 'api key required',
34
+ 'credential required in vault',
35
+ 'credential not configured in vault',
36
+ ];
37
+ const AUTH_PROMPT_COPY = {
38
+ 'missing-api-key': {
39
+ title: 'API key required',
40
+ description: 'Add an API key to Vault to start chatting with AI',
41
+ action: 'Add API key',
42
+ },
43
+ 'codex-oauth-expired': {
44
+ title: 'Refresh OpenAI Codex auth',
45
+ description: 'Open Settings > API Keys and reconnect OpenAI Codex to keep using Codex-backed OpenAI models.',
46
+ action: 'Reconnect OpenAI Codex',
47
+ },
48
+ };
49
+ function messageIncludesAny(message, patterns) {
50
+ const normalized = message.toLowerCase();
51
+ return patterns.some((pattern) => normalized.includes(pattern));
52
+ }
53
+ export function resolveChatAuthIssue({ missingApiKey, authIssue, error, }) {
54
+ if (authIssue)
55
+ return authIssue;
56
+ const message = error?.message ?? '';
57
+ if (messageIncludesAny(message, CODEX_OAUTH_ERROR_PATTERNS)) {
58
+ return 'codex-oauth-expired';
59
+ }
60
+ if (missingApiKey)
61
+ return 'missing-api-key';
62
+ if (messageIncludesAny(message, MISSING_API_KEY_ERROR_PATTERNS)) {
63
+ return 'missing-api-key';
64
+ }
65
+ return null;
66
+ }
22
67
  function clampPercent(value) {
23
68
  if (!Number.isFinite(value))
24
69
  return 0;
@@ -73,7 +118,7 @@ function QueuedMessageRow({ message, isResponding, onRetryQueuedMessage, onSteer
73
118
  /**
74
119
  * Floating chat panel with model selector
75
120
  */
76
- export function ChatPanel({ messages, status, isTurnInFlight, input, onInputChange, onSubmit, onStop, onNewChat, models, selectedModel, onModelChange, reasoningEffortOptions, selectedReasoningEffort, onReasoningEffortChange, conversations, currentConversationId, scrollToBottomSignal = 0, onSelectConversation, onDeleteConversation, placeholder = 'Ask anything...', welcomeMessage, isExpanded, onExpandedChange, isMinimized = false, onMinimizedChange, className, error, missingApiKey, onAddApiKey, toolProgress = {}, onApprovalResponse, isEditingApp = true, onEditingAppChange, showEditingAppToggle = false, checkpoints, restoringMessageId, onRestoreCheckpoint, imageAttachments = [], onRemoveImageAttachment, isImageDropActive = false, queuedMessages = [], onRemoveQueuedMessage, onRetryQueuedMessage, onSteerQueuedMessage, onReorderQueuedMessages, onEditQueuedMessage, slashCommands, onSlashCommandSelect, isCompacting = false, compactedHistoryStartIndex, contextUsage, }) {
121
+ export function ChatPanel({ messages, status, isTurnInFlight, input, onInputChange, onSubmit, onStop, onNewChat, modelProviders, modelEffortPresets, selectedModel, selectedReasoningEffort, onModelEffortChange, conversations, currentConversationId, scrollToBottomSignal = 0, onSelectConversation, onDeleteConversation, placeholder = 'Ask anything...', welcomeMessage, isExpanded, onExpandedChange, isMinimized = false, onMinimizedChange, className, error, missingApiKey, authIssue, onAddApiKey, toolProgress = {}, onApprovalResponse, isEditingApp = true, onEditingAppChange, showEditingAppToggle = false, checkpoints, restoringMessageId, onRestoreCheckpoint, imageAttachments = [], onRemoveImageAttachment, isImageDropActive = false, queuedMessages = [], onRemoveQueuedMessage, onRetryQueuedMessage, onSteerQueuedMessage, onReorderQueuedMessages, onEditQueuedMessage, slashCommands, onSlashCommandSelect, isCompacting = false, compactedHistoryStartIndex, contextUsage, }) {
77
122
  const inputRef = useRef(null);
78
123
  const scrollAreaRef = useRef(null);
79
124
  const viewportRef = useRef(null);
@@ -96,9 +141,7 @@ export function ChatPanel({ messages, status, isTurnInFlight, input, onInputChan
96
141
  }));
97
142
  const isResponding = status === 'streaming' || status === 'submitted';
98
143
  const controlsDisabled = isTurnInFlight ?? isResponding;
99
- const composerControls = (_jsxs(_Fragment, { children: [_jsx(ContextWindowIndicator, { usage: contextUsage }), _jsx(ModelSelector, { models: models, selectedModel: selectedModel, onModelChange: onModelChange, disabled: controlsDisabled, dropdownAlign: "end", dropdownSide: "top" }), reasoningEffortOptions &&
100
- selectedReasoningEffort &&
101
- onReasoningEffortChange && (_jsx(ReasoningEffortSelector, { options: reasoningEffortOptions, selectedEffort: selectedReasoningEffort, onEffortChange: onReasoningEffortChange, disabled: controlsDisabled, showLabel: true, dropdownAlign: "end", dropdownSide: "top" }))] }));
144
+ const composerControls = (_jsxs(_Fragment, { children: [_jsx(ContextWindowIndicator, { usage: contextUsage }), modelProviders.length > 0 && modelEffortPresets.length > 0 ? (_jsx(ModelEffortSelector, { providers: modelProviders, presets: modelEffortPresets, selectedModel: selectedModel, selectedReasoningEffort: selectedReasoningEffort, onSelectionChange: onModelEffortChange, disabled: controlsDisabled })) : null] }));
102
145
  // Capture the Radix viewport element so virtua can use it as the scroll container
103
146
  useEffect(() => {
104
147
  const scrollArea = scrollAreaRef.current;
@@ -137,12 +180,16 @@ export function ChatPanel({ messages, status, isTurnInFlight, input, onInputChan
137
180
  return () => clearTimeout(timer);
138
181
  }
139
182
  }, [isExpanded]);
140
- const showMissingApiKeyPrompt = missingApiKey ||
141
- (error &&
142
- (error.message?.includes('API_KEY not configured') ||
143
- error.message?.includes('credential required in Vault') ||
144
- error.message?.includes('credential not configured in Vault')));
145
- const submitDisabled = Boolean(showMissingApiKeyPrompt);
183
+ const resolvedAuthIssue = resolveChatAuthIssue({
184
+ missingApiKey,
185
+ authIssue,
186
+ error,
187
+ });
188
+ const authPromptCopy = resolvedAuthIssue
189
+ ? AUTH_PROMPT_COPY[resolvedAuthIssue]
190
+ : null;
191
+ const showAuthPrompt = Boolean(resolvedAuthIssue);
192
+ const submitDisabled = showAuthPrompt;
146
193
  const handleSubmit = useCallback((e, mode) => {
147
194
  e?.preventDefault();
148
195
  if (submitDisabled) {
@@ -219,7 +266,7 @@ export function ChatPanel({ messages, status, isTurnInFlight, input, onInputChan
219
266
  }, [isExpanded, onExpandedChange, onMinimizedChange]);
220
267
  const isStreaming = status === 'streaming' || status === 'submitted';
221
268
  const isThinking = useMemo(() => computeIsThinking(messages, status), [messages, status]);
222
- const showErrorMessage = Boolean(error) && status === 'error' && !showMissingApiKeyPrompt;
269
+ const showErrorMessage = Boolean(error) && status === 'error' && !showAuthPrompt;
223
270
  const lastMessageId = messages[messages.length - 1]?.id;
224
271
  const listItems = useMemo(() => {
225
272
  const items = [];
@@ -244,8 +291,8 @@ export function ChatPanel({ messages, status, isTurnInFlight, input, onInputChan
244
291
  if (isCompacting) {
245
292
  items.push({ key: 'compacting', kind: 'compacting' });
246
293
  }
247
- if (showMissingApiKeyPrompt) {
248
- items.push({ key: 'missing-api-key', kind: 'missing-api-key' });
294
+ if (showAuthPrompt) {
295
+ items.push({ key: 'auth-prompt', kind: 'auth-prompt' });
249
296
  }
250
297
  if (showErrorMessage) {
251
298
  items.push({ key: 'error', kind: 'error' });
@@ -257,7 +304,7 @@ export function ChatPanel({ messages, status, isTurnInFlight, input, onInputChan
257
304
  compactedHistoryStartIndex,
258
305
  messages,
259
306
  showErrorMessage,
260
- showMissingApiKeyPrompt,
307
+ showAuthPrompt,
261
308
  welcomeMessage,
262
309
  ]);
263
310
  const renderVirtualItem = useCallback((item) => {
@@ -274,14 +321,21 @@ export function ChatPanel({ messages, status, isTurnInFlight, input, onInputChan
274
321
  return (_jsx("div", { className: "px-2 pb-3", children: _jsx(ThinkingMessage, {}) }));
275
322
  case 'compacting':
276
323
  return (_jsx("div", { className: "px-2 pb-3", children: _jsx(CompactingMessage, {}) }));
277
- case 'missing-api-key':
278
- return (_jsx("div", { className: "px-2 pb-4", children: _jsxs("div", { className: "border-primary/30 bg-primary/5 mx-2 flex flex-col items-center gap-3 rounded-lg border p-4 text-center", children: [_jsx("div", { className: "bg-primary/10 flex size-10 items-center justify-center rounded-full", children: _jsx(AlertCircle, { className: "text-primary size-5" }) }), _jsxs("div", { children: [_jsx("p", { className: "text-foreground font-medium", children: "API key required" }), _jsx("p", { className: "text-muted-foreground mt-1 text-sm", children: "Add an API key to Vault to start chatting with AI" })] }), onAddApiKey && (_jsx(Button, { onClick: onAddApiKey, size: "sm", className: "cursor-pointer", children: "Add API key" }))] }) }));
324
+ case 'auth-prompt':
325
+ if (resolvedAuthIssue === 'codex-oauth-expired') {
326
+ return (_jsx("div", { className: "px-2 pb-4", children: _jsxs("div", { className: "bg-muted/30 mx-2 flex flex-col gap-3 rounded-lg p-4", children: [_jsx("div", { className: "flex items-start justify-between gap-3", children: _jsxs("div", { children: [_jsx("p", { className: "text-sm font-medium", children: authPromptCopy?.title ?? 'Refresh OpenAI Codex auth' }), _jsx("p", { className: "text-muted-foreground text-xs", children: authPromptCopy?.description ??
327
+ 'Open Settings > API Keys and reconnect OpenAI Codex.' })] }) }), onAddApiKey && (_jsxs(Button, { variant: "outline", className: "w-full cursor-pointer", onClick: onAddApiKey, children: [_jsx(ExternalLink, { className: "mr-2 size-4" }), authPromptCopy?.action ?? 'Reconnect OpenAI Codex'] }))] }) }));
328
+ }
329
+ return (_jsx("div", { className: "px-2 pb-4", children: _jsxs("div", { className: "border-primary/30 bg-primary/5 mx-2 flex flex-col items-center gap-3 rounded-lg border p-4 text-center", children: [_jsx("div", { className: "bg-primary/10 flex size-10 items-center justify-center rounded-full", children: _jsx(AlertCircle, { className: "text-primary size-5" }) }), _jsxs("div", { className: "max-w-sm", children: [_jsx("p", { className: "text-foreground font-medium", children: authPromptCopy?.title ?? 'Authentication required' }), _jsx("p", { className: "text-muted-foreground mt-1 text-sm", children: authPromptCopy?.description ??
330
+ 'Open settings to configure chat authentication.' })] }), onAddApiKey && (_jsx(Button, { onClick: onAddApiKey, size: "sm", className: "cursor-pointer", children: authPromptCopy?.action ?? 'Open settings' }))] }) }));
279
331
  case 'error':
280
332
  return (_jsx("div", { className: "px-2 pb-4", children: error && (_jsxs("div", { className: "border-destructive/30 bg-destructive/10 text-destructive mx-2 flex items-start gap-2 rounded-lg border p-3 text-sm", children: [_jsx(AlertCircle, { className: "mt-0.5 size-4 shrink-0" }), _jsxs("div", { className: "min-w-0", children: [_jsx("p", { className: "font-medium", children: "Request failed" }), _jsx("p", { className: "text-destructive/80 mt-0.5 break-words", children: error.message || 'An unknown error occurred' })] })] })) }));
281
333
  }
282
334
  }, [
283
335
  checkpoints,
284
336
  error,
337
+ authPromptCopy,
338
+ resolvedAuthIssue,
285
339
  isStreaming,
286
340
  lastMessageId,
287
341
  messages.length,
@@ -4,9 +4,10 @@ export { Messages, type MessageCheckpoint } from './chat-messages';
4
4
  export { CheckpointBadge, type CheckpointBadgeProps } from './checkpoint-badge';
5
5
  export { RestoreDialog, type CheckpointInfo, type RestoreDialogProps, } from './restore-dialog';
6
6
  export { ModelSelector, type ModelOption } from './model-selector';
7
+ export { ModelEffortSelector, resolveModelEffortPresetIndex, type ModelEffortPresetOption, type ModelProviderOption, } from './model-effort-selector';
7
8
  export { ReasoningEffortSelector, type ReasoningEffortOption, } from './reasoning-effort-selector';
8
9
  export { ConversationHistory, type ConversationMeta, } from './conversation-history';
9
- export { ChatPanel, type ChatContextUsage, type ChatPanelProps, type QueuedChatMessage, type ToolProgressData, } from './chat-panel';
10
+ export { ChatPanel, type ChatAuthIssue, type ChatContextUsage, type ChatPanelProps, type QueuedChatMessage, type ToolProgressData, resolveChatAuthIssue, } from './chat-panel';
10
11
  export { ThinkingTimeline, ThinkingTimelineMarker, type ThinkingTimelineItem, type ThinkingTimelineProps, } from './thinking-timeline';
11
12
  export { getToolHandler, DEFAULT_TOOL_HANDLERS, type ToolHandler, } from './tool-handlers';
12
13
  export { ToolProgressProvider, useToolProgress, useToolCallProgress, } from './tool-progress-context';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/chat/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,cAAc,GACpB,MAAM,cAAc,CAAA;AACrB,OAAO,EACL,iBAAiB,EACjB,OAAO,EACP,eAAe,EACf,KAAK,WAAW,EAChB,KAAK,eAAe,GACrB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EAAE,QAAQ,EAAE,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAClE,OAAO,EAAE,eAAe,EAAE,KAAK,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AAC/E,OAAO,EACL,aAAa,EACb,KAAK,cAAc,EACnB,KAAK,kBAAkB,GACxB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,aAAa,EAAE,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAClE,OAAO,EACL,uBAAuB,EACvB,KAAK,qBAAqB,GAC3B,MAAM,6BAA6B,CAAA;AACpC,OAAO,EACL,mBAAmB,EACnB,KAAK,gBAAgB,GACtB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EACL,SAAS,EACT,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,GACtB,MAAM,cAAc,CAAA;AACrB,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EACtB,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,GAC3B,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,KAAK,WAAW,GACjB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACL,oBAAoB,EACpB,eAAe,EACf,mBAAmB,GACpB,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACL,oBAAoB,EACpB,uBAAuB,EACvB,KAAK,uBAAuB,GAC7B,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,oBAAoB,EACpB,mBAAmB,EACnB,kBAAkB,EAClB,KAAK,iBAAiB,GACvB,MAAM,iBAAiB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/chat/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,cAAc,GACpB,MAAM,cAAc,CAAA;AACrB,OAAO,EACL,iBAAiB,EACjB,OAAO,EACP,eAAe,EACf,KAAK,WAAW,EAChB,KAAK,eAAe,GACrB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EAAE,QAAQ,EAAE,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAClE,OAAO,EAAE,eAAe,EAAE,KAAK,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AAC/E,OAAO,EACL,aAAa,EACb,KAAK,cAAc,EACnB,KAAK,kBAAkB,GACxB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,aAAa,EAAE,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAClE,OAAO,EACL,mBAAmB,EACnB,6BAA6B,EAC7B,KAAK,uBAAuB,EAC5B,KAAK,mBAAmB,GACzB,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACL,uBAAuB,EACvB,KAAK,qBAAqB,GAC3B,MAAM,6BAA6B,CAAA;AACpC,OAAO,EACL,mBAAmB,EACnB,KAAK,gBAAgB,GACtB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EACL,SAAS,EACT,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,oBAAoB,GACrB,MAAM,cAAc,CAAA;AACrB,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EACtB,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,GAC3B,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,KAAK,WAAW,GACjB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACL,oBAAoB,EACpB,eAAe,EACf,mBAAmB,GACpB,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACL,oBAAoB,EACpB,uBAAuB,EACvB,KAAK,uBAAuB,GAC7B,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,oBAAoB,EACpB,mBAAmB,EACnB,kBAAkB,EAClB,KAAK,iBAAiB,GACvB,MAAM,iBAAiB,CAAA"}
@@ -4,9 +4,10 @@ export { Messages } from './chat-messages';
4
4
  export { CheckpointBadge } from './checkpoint-badge';
5
5
  export { RestoreDialog, } from './restore-dialog';
6
6
  export { ModelSelector } from './model-selector';
7
+ export { ModelEffortSelector, resolveModelEffortPresetIndex, } from './model-effort-selector';
7
8
  export { ReasoningEffortSelector, } from './reasoning-effort-selector';
8
9
  export { ConversationHistory, } from './conversation-history';
9
- export { ChatPanel, } from './chat-panel';
10
+ export { ChatPanel, resolveChatAuthIssue, } from './chat-panel';
10
11
  export { ThinkingTimeline, ThinkingTimelineMarker, } from './thinking-timeline';
11
12
  export { getToolHandler, DEFAULT_TOOL_HANDLERS, } from './tool-handlers';
12
13
  export { ToolProgressProvider, useToolProgress, useToolCallProgress, } from './tool-progress-context';
@@ -0,0 +1,7 @@
1
+ export type ModelEffortPowerLevel = 'light' | 'medium' | 'high' | 'xhigh' | 'max';
2
+ export declare function ModelEffortRangeEffects({ level, reveal, }: {
3
+ level: ModelEffortPowerLevel;
4
+ reveal: boolean;
5
+ }): import("react/jsx-runtime").JSX.Element;
6
+ export declare function MaxThumbBurst(): import("react/jsx-runtime").JSX.Element;
7
+ //# sourceMappingURL=model-effort-power-effects.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-effort-power-effects.d.ts","sourceRoot":"","sources":["../../../src/components/chat/model-effort-power-effects.tsx"],"names":[],"mappings":"AAIA,MAAM,MAAM,qBAAqB,GAC7B,OAAO,GACP,QAAQ,GACR,MAAM,GACN,OAAO,GACP,KAAK,CAAA;AAsCT,wBAAgB,uBAAuB,CAAC,EACtC,KAAK,EACL,MAAM,GACP,EAAE;IACD,KAAK,EAAE,qBAAqB,CAAA;IAC5B,MAAM,EAAE,OAAO,CAAA;CAChB,2CA+BA;AAED,wBAAgB,aAAa,4CAuB5B"}
@@ -0,0 +1,54 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ const STREAM_PARTICLES = [
3
+ [18, 1.72, -0.22, 0.78, 0.72],
4
+ [72, 2.28, -1.64, 0.62, 0.9],
5
+ [42, 1.94, -0.78, 0.88, 0.82],
6
+ [27, 2.14, -1.92, 0.56, 0.66],
7
+ [64, 1.82, -0.46, 0.82, 0.94],
8
+ [83, 2.36, -1.14, 0.68, 0.76],
9
+ [36, 1.64, -1.42, 0.92, 0.86],
10
+ [57, 2.06, -0.08, 0.58, 0.7],
11
+ [21, 2.42, -2.18, 0.74, 0.88],
12
+ [76, 1.88, -0.96, 0.86, 0.8],
13
+ [48, 2.22, -1.78, 0.64, 0.96],
14
+ [31, 1.78, -0.58, 0.9, 0.74],
15
+ [68, 2.5, -2.36, 0.54, 0.84],
16
+ [88, 2, -1.28, 0.76, 0.68],
17
+ ];
18
+ const BURST_PARTICLES = [
19
+ [-32, -3],
20
+ [-28, -17],
21
+ [-19, -29],
22
+ [-5, -34],
23
+ [10, -32],
24
+ [24, -24],
25
+ [32, -11],
26
+ [35, 4],
27
+ [29, 19],
28
+ [18, 30],
29
+ [3, 35],
30
+ [-12, 32],
31
+ [-25, 24],
32
+ [-34, 11],
33
+ [20, -7],
34
+ [-16, 9],
35
+ ];
36
+ export function ModelEffortRangeEffects({ level, reveal, }) {
37
+ return (_jsxs("span", { "aria-hidden": "true", className: "model-effort-power-fill", "data-level": level, "data-reveal": level === 'max' && reveal, children: [_jsx("span", { className: "model-effort-power-field" }), _jsx("span", { className: "model-effort-power-particles", children: STREAM_PARTICLES.map(([top, duration, delay, opacity, scale], index) => (_jsx("span", { className: "model-effort-power-particle", style: {
38
+ top: `${top}%`,
39
+ '--particle-opacity': opacity,
40
+ '--particle-scale': scale,
41
+ animationDuration: `${duration}s`,
42
+ animationDelay: `${delay}s`,
43
+ } }, index))) })] }));
44
+ }
45
+ export function MaxThumbBurst() {
46
+ return (_jsx("span", { "aria-hidden": "true", className: "model-effort-max-burst", children: BURST_PARTICLES.map(([x, y], index) => (_jsx("span", { className: "model-effort-max-burst-particle", style: {
47
+ '--burst-x': `${x}px`,
48
+ '--burst-y': `${y}px`,
49
+ animationDelay: `${(index % 4) * 12}ms`,
50
+ backgroundColor: index % 3 === 0
51
+ ? 'var(--model-effort-blue)'
52
+ : 'var(--model-effort-purple)',
53
+ } }, index))) }));
54
+ }
@@ -0,0 +1,26 @@
1
+ import { type ReactNode } from 'react';
2
+ export type ModelProviderOption = {
3
+ id: string;
4
+ name: string;
5
+ icon: ReactNode;
6
+ };
7
+ export type ModelEffortPresetOption = {
8
+ id: string;
9
+ providerId: string;
10
+ modelId: string;
11
+ modelName: string;
12
+ effort: string;
13
+ effortLabel: string;
14
+ };
15
+ type ModelEffortSelectorProps = {
16
+ providers: ModelProviderOption[];
17
+ presets: ModelEffortPresetOption[];
18
+ selectedModel: string;
19
+ selectedReasoningEffort: string;
20
+ onSelectionChange: (modelId: string, effort: string) => void;
21
+ disabled?: boolean;
22
+ };
23
+ export declare function resolveModelEffortPresetIndex(presets: ModelEffortPresetOption[], selectedModel: string, selectedEffort: string): number;
24
+ export declare function ModelEffortSelector({ providers, presets, selectedModel, selectedReasoningEffort, onSelectionChange, disabled, }: ModelEffortSelectorProps): import("react/jsx-runtime").JSX.Element;
25
+ export {};
26
+ //# sourceMappingURL=model-effort-selector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-effort-selector.d.ts","sourceRoot":"","sources":["../../../src/components/chat/model-effort-selector.tsx"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,SAAS,EAKf,MAAM,OAAO,CAAA;AAcd,MAAM,MAAM,mBAAmB,GAAG;IAChC,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,SAAS,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,uBAAuB,GAAG;IACpC,EAAE,EAAE,MAAM,CAAA;IACV,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,KAAK,wBAAwB,GAAG;IAC9B,SAAS,EAAE,mBAAmB,EAAE,CAAA;IAChC,OAAO,EAAE,uBAAuB,EAAE,CAAA;IAClC,aAAa,EAAE,MAAM,CAAA;IACrB,uBAAuB,EAAE,MAAM,CAAA;IAC/B,iBAAiB,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;IAC5D,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AAED,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,uBAAuB,EAAE,EAClC,aAAa,EAAE,MAAM,EACrB,cAAc,EAAE,MAAM,GACrB,MAAM,CAWR;AAoCD,wBAAgB,mBAAmB,CAAC,EAClC,SAAS,EACT,OAAO,EACP,aAAa,EACb,uBAAuB,EACvB,iBAAiB,EACjB,QAAgB,GACjB,EAAE,wBAAwB,2CAiT1B"}
@@ -0,0 +1,179 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { ChevronDown, Zap } from 'lucide-react';
4
+ import { useEffect, useLayoutEffect, useRef, useState, } from 'react';
5
+ import { cn } from '../../lib/utils';
6
+ import { Button } from '../ui/button';
7
+ import { Popover, PopoverContent, PopoverTrigger } from '../ui/popover';
8
+ import { Slider } from '../ui/slider';
9
+ import { MaxThumbBurst, ModelEffortRangeEffects, } from './model-effort-power-effects';
10
+ const EXPANDED_TRIGGER_WIDTH = 252;
11
+ const TRIGGER_MOTION_MS = 320;
12
+ export function resolveModelEffortPresetIndex(presets, selectedModel, selectedEffort) {
13
+ const exactIndex = presets.findIndex((preset) => preset.modelId === selectedModel && preset.effort === selectedEffort);
14
+ if (exactIndex >= 0)
15
+ return exactIndex;
16
+ const sameModelIndex = presets.findIndex((preset) => preset.modelId === selectedModel);
17
+ return Math.max(sameModelIndex, 0);
18
+ }
19
+ function tickPosition(index, maxIndex) {
20
+ if (maxIndex <= 0)
21
+ return '14px';
22
+ const percentage = (index / maxIndex) * 100;
23
+ const thumbOffset = 14 - 28 * (percentage / 100);
24
+ return `calc(${percentage}% + ${thumbOffset}px)`;
25
+ }
26
+ function fillWidth(index, maxIndex) {
27
+ if (maxIndex <= 0)
28
+ return '13px';
29
+ const percentage = (index / maxIndex) * 100;
30
+ const thumbCenterFromInset = 13 - 28 * (percentage / 100);
31
+ return `calc(${percentage}% + ${thumbCenterFromInset}px)`;
32
+ }
33
+ function getPowerLevel(effort) {
34
+ switch (effort) {
35
+ case 'low':
36
+ return 'light';
37
+ case 'medium':
38
+ return 'medium';
39
+ case 'high':
40
+ return 'high';
41
+ case 'xhigh':
42
+ return 'xhigh';
43
+ case 'max':
44
+ case 'ultra':
45
+ return 'max';
46
+ default:
47
+ return null;
48
+ }
49
+ }
50
+ export function ModelEffortSelector({ providers, presets, selectedModel, selectedReasoningEffort, onSelectionChange, disabled = false, }) {
51
+ const [open, setOpen] = useState(false);
52
+ const [thumbMotionReady, setThumbMotionReady] = useState(false);
53
+ const [previewPresetIndex, setPreviewPresetIndex] = useState(null);
54
+ const [isDragging, setIsDragging] = useState(false);
55
+ const [maxBurstKey, setMaxBurstKey] = useState(0);
56
+ const [revealMax, setRevealMax] = useState(false);
57
+ const triggerRef = useRef(null);
58
+ const triggerAnimationRef = useRef(null);
59
+ const triggerMotionStartWidthRef = useRef(null);
60
+ const matchingPreset = presets.find((preset) => preset.modelId === selectedModel &&
61
+ preset.effort === selectedReasoningEffort) ?? presets.find((preset) => preset.modelId === selectedModel);
62
+ const activeProviderId = matchingPreset?.providerId ?? providers[0]?.id;
63
+ const activePresets = presets.filter((preset) => preset.providerId === activeProviderId);
64
+ const selectedPresetIndex = resolveModelEffortPresetIndex(activePresets, selectedModel, selectedReasoningEffort);
65
+ const visiblePresetIndex = previewPresetIndex !== null && activePresets[previewPresetIndex]
66
+ ? previewPresetIndex
67
+ : selectedPresetIndex;
68
+ const currentPreset = activePresets[visiblePresetIndex];
69
+ const isMaxPower = currentPreset?.effort === 'ultra' || currentPreset?.effort === 'max';
70
+ const powerLevel = getPowerLevel(currentPreset?.effort);
71
+ const maxPresetIndex = Math.max(activePresets.length - 1, 0);
72
+ const activeProviderIndex = Math.max(providers.findIndex((provider) => provider.id === activeProviderId), 0);
73
+ const showProviderToggle = providers.length > 1;
74
+ // Codex keeps thumb position motion disabled for the first 16ms after mount.
75
+ // That lets the selected stop render in place instead of sliding in as the
76
+ // popover opens, while retaining the same motion for later interactions.
77
+ useEffect(() => {
78
+ if (!open)
79
+ return;
80
+ const timeout = window.setTimeout(() => setThumbMotionReady(true), 16);
81
+ return () => window.clearTimeout(timeout);
82
+ }, [open]);
83
+ useLayoutEffect(() => {
84
+ const trigger = triggerRef.current;
85
+ const startWidth = triggerMotionStartWidthRef.current;
86
+ triggerMotionStartWidthRef.current = null;
87
+ if (!trigger || startWidth === null)
88
+ return;
89
+ triggerAnimationRef.current?.cancel();
90
+ const endWidth = trigger.getBoundingClientRect().width;
91
+ if (Math.abs(endWidth - startWidth) < 0.5 ||
92
+ window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
93
+ return;
94
+ }
95
+ const animation = trigger.animate([{ width: `${startWidth}px` }, { width: `${endWidth}px` }], {
96
+ duration: TRIGGER_MOTION_MS,
97
+ easing: 'cubic-bezier(.23,1,.32,1)',
98
+ });
99
+ triggerAnimationRef.current = animation;
100
+ animation.onfinish = () => {
101
+ if (triggerAnimationRef.current === animation) {
102
+ triggerAnimationRef.current = null;
103
+ }
104
+ };
105
+ }, [open]);
106
+ useEffect(() => () => {
107
+ triggerAnimationRef.current?.cancel();
108
+ }, []);
109
+ const preparePresetEffects = (nextPreset) => {
110
+ const nextIsMax = nextPreset?.effort === 'ultra' || nextPreset?.effort === 'max';
111
+ if (nextIsMax && !isMaxPower) {
112
+ setMaxBurstKey((key) => key + 1);
113
+ setRevealMax(true);
114
+ }
115
+ else if (!nextIsMax && isMaxPower) {
116
+ setRevealMax(false);
117
+ }
118
+ };
119
+ const handleOpenChange = (nextOpen) => {
120
+ const trigger = triggerRef.current;
121
+ if (trigger) {
122
+ triggerMotionStartWidthRef.current = trigger.getBoundingClientRect().width;
123
+ triggerAnimationRef.current?.cancel();
124
+ }
125
+ setThumbMotionReady(false);
126
+ setPreviewPresetIndex(null);
127
+ setIsDragging(false);
128
+ if (!nextOpen)
129
+ setRevealMax(false);
130
+ setOpen(nextOpen);
131
+ };
132
+ const handleProviderChange = (providerId) => {
133
+ if (providerId === activeProviderId)
134
+ return;
135
+ const nextPresets = presets.filter((preset) => preset.providerId === providerId);
136
+ if (nextPresets.length === 0)
137
+ return;
138
+ const progress = maxPresetIndex > 0 ? visiblePresetIndex / maxPresetIndex : 0;
139
+ const nextIndex = Math.round(progress * Math.max(nextPresets.length - 1, 0));
140
+ const nextPreset = nextPresets[nextIndex];
141
+ if (!nextPreset)
142
+ return;
143
+ preparePresetEffects(nextPreset);
144
+ setPreviewPresetIndex(null);
145
+ onSelectionChange(nextPreset.modelId, nextPreset.effort);
146
+ };
147
+ return (_jsxs(Popover, { open: open, onOpenChange: handleOpenChange, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs(Button, { ref: triggerRef, type: "button", variant: "ghost", size: "sm", disabled: disabled || !currentPreset, "aria-label": `Model and effort: ${currentPreset?.modelName ?? 'Unavailable'}, ${currentPreset?.effortLabel ?? 'Unavailable'}`, className: cn('text-foreground hover:bg-muted h-8 min-w-0 cursor-pointer gap-1.5 overflow-hidden rounded-full px-2.5 text-xs font-medium transition-colors', open ? 'max-w-none' : 'w-auto max-w-[220px]'), style: { width: open ? EXPANDED_TRIGGER_WIDTH : undefined }, children: [_jsx(Zap, { className: "size-4 shrink-0" }), _jsx("span", { className: "min-w-0 max-w-[110px] truncate", children: currentPreset?.modelName }), _jsx("span", { className: cn('shrink-0 font-normal transition-colors duration-300', isMaxPower ? 'text-model-effort-purple' : 'text-muted-foreground'), children: currentPreset?.effortLabel }), _jsx(ChevronDown, { className: "text-muted-foreground size-3 shrink-0" })] }) }), _jsxs(PopoverContent, { align: "end", side: "top", sideOffset: 8, collisionPadding: 12, className: "model-effort-popover rounded-2xl p-2.5 shadow-xl", style: { width: EXPANDED_TRIGGER_WIDTH }, children: [showProviderToggle ? (_jsxs("div", { className: "border-border bg-muted relative mx-auto mb-2.5 flex w-fit items-center rounded-full border p-0.5", role: "group", "aria-label": "AI provider", children: [_jsx("div", { "aria-hidden": "true", className: "bg-background absolute inset-y-0.5 left-0.5 w-12 rounded-full shadow-sm transition-transform duration-200 ease-out", style: {
148
+ transform: `translateX(${activeProviderIndex * 3}rem)`,
149
+ } }), providers.map((provider) => {
150
+ const active = provider.id === activeProviderId;
151
+ return (_jsx("button", { type: "button", onClick: () => handleProviderChange(provider.id), disabled: disabled, "aria-label": provider.name, "aria-pressed": active, className: cn('relative z-10 inline-flex h-8 w-12 cursor-pointer items-center justify-center rounded-full transition-opacity disabled:cursor-not-allowed disabled:opacity-50', active ? 'opacity-100' : 'opacity-45 hover:opacity-80'), children: _jsx("span", { className: "flex size-4 items-center justify-center [&>img]:size-4", children: provider.icon }) }, provider.id));
152
+ })] })) : null, _jsxs("div", { className: "text-muted-foreground flex items-center justify-between px-1 text-[11px] font-medium", children: [_jsx("span", { children: "Faster" }), _jsx("span", { children: "Smarter" })] }), _jsxs("div", { className: "relative mt-1.5 h-8", children: [_jsx(Slider, { "aria-label": "Model intelligence", value: [visiblePresetIndex], min: 0, max: maxPresetIndex, step: 1, disabled: disabled || activePresets.length === 0, onValueChange: ([nextIndex]) => {
153
+ if (typeof nextIndex === 'number') {
154
+ preparePresetEffects(activePresets[nextIndex]);
155
+ setPreviewPresetIndex(nextIndex);
156
+ }
157
+ }, onValueCommit: ([nextIndex]) => {
158
+ const nextPreset = activePresets[nextIndex ?? -1];
159
+ preparePresetEffects(nextPreset);
160
+ setPreviewPresetIndex(null);
161
+ if (nextPreset) {
162
+ onSelectionChange(nextPreset.modelId, nextPreset.effort);
163
+ }
164
+ }, onPointerDown: () => setIsDragging(true), onPointerUp: () => setIsDragging(false), onPointerCancel: () => setIsDragging(false), thumbContent: isMaxPower && revealMax && maxBurstKey > 0 ? (_jsx(MaxThumbBurst, {}, maxBurstKey)) : null, className: cn('[&_[data-slot=slider-thumb]]:border-foreground/20 [&_[data-slot=slider-track]]:border-border [&_[data-slot=slider-track]]:bg-foreground/10 h-8 [&>span:last-child]:z-20 [&>span:last-child]:transition-[left] [&>span:last-child]:ease-[cubic-bezier(.23,1,.32,1)] [&_[data-slot=slider-range]]:bg-transparent [&_[data-slot=slider-thumb]]:relative [&_[data-slot=slider-thumb]]:isolate [&_[data-slot=slider-thumb]]:z-20 [&_[data-slot=slider-thumb]]:size-7 [&_[data-slot=slider-thumb]]:border-[0.5px] [&_[data-slot=slider-thumb]]:bg-white [&_[data-slot=slider-thumb]]:shadow-[0_1px_4px_rgba(0,0,0,0.18)] [&_[data-slot=slider-thumb]]:hover:ring-0 [&_[data-slot=slider-track]]:h-6 [&_[data-slot=slider-track]]:border', !thumbMotionReady
165
+ ? '[&>span:last-child]:duration-0'
166
+ : isDragging
167
+ ? '[&>span:last-child]:duration-150'
168
+ : '[&>span:last-child]:duration-300') }), _jsx("div", { "aria-hidden": "true", className: cn('bg-model-effort-blue pointer-events-none absolute left-px top-[5px] z-[1] h-[22px] overflow-hidden rounded-full transition-[width] ease-[cubic-bezier(.23,1,.32,1)]', !thumbMotionReady
169
+ ? 'duration-0'
170
+ : isDragging
171
+ ? 'duration-150'
172
+ : 'duration-300'), style: { width: fillWidth(visiblePresetIndex, maxPresetIndex) }, children: powerLevel !== null ? (_jsx(ModelEffortRangeEffects, { level: powerLevel, reveal: revealMax }, powerLevel)) : null }), _jsx("div", { className: cn('pointer-events-none absolute inset-0 z-[1] transition-[opacity,transform] ease-[cubic-bezier(.23,1,.32,1)]', isMaxPower
173
+ ? 'scale-75 opacity-0 delay-100 duration-[400ms]'
174
+ : 'scale-100 opacity-100 duration-300'), "aria-hidden": true, children: activePresets.map((preset, index) => (_jsx("span", { className: cn('absolute top-1/2 size-1 -translate-x-1/2 -translate-y-1/2 rounded-full transition-[background-color,transform] duration-300 ease-[cubic-bezier(.23,1,.32,1)]', index <= visiblePresetIndex
175
+ ? powerLevel === 'light' || powerLevel === 'medium'
176
+ ? 'bg-model-effort-blue/45'
177
+ : 'bg-white/55'
178
+ : 'bg-muted-foreground/45'), style: { left: tickPosition(index, maxPresetIndex) } }, preset.id))) })] })] })] }));
179
+ }
@@ -0,0 +1,5 @@
1
+ export declare function UltraRangeEffects({ reveal }: {
2
+ reveal: boolean;
3
+ }): import("react/jsx-runtime").JSX.Element;
4
+ export declare function UltraThumbBurst(): import("react/jsx-runtime").JSX.Element;
5
+ //# sourceMappingURL=model-effort-ultra-effects.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-effort-ultra-effects.d.ts","sourceRoot":"","sources":["../../../src/components/chat/model-effort-ultra-effects.tsx"],"names":[],"mappings":"AAwCA,wBAAgB,iBAAiB,CAAC,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,2CAgChE;AAED,wBAAgB,eAAe,4CAuB9B"}