@contentgrowth/llm-service 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -189,19 +189,174 @@ function ChatHeader({
189
189
  }
190
190
 
191
191
  // src/ui/react/components/ChatInputArea.tsx
192
- var import_react4 = require("react");
192
+ var import_react5 = require("react");
193
+ var import_outline2 = require("@heroicons/react/24/outline");
194
+
195
+ // src/ui/react/components/VoiceInputButton.tsx
193
196
  var import_outline = require("@heroicons/react/24/outline");
194
197
 
195
- // src/ui/react/hooks/useAudioRecorder.ts
198
+ // src/ui/react/hooks/useDragCancel.ts
196
199
  var import_react2 = require("react");
200
+ var useDragCancel = ({
201
+ onCancel,
202
+ onCommit,
203
+ isListening,
204
+ threshold = 50,
205
+ direction = "up"
206
+ }) => {
207
+ const [isDragging, setIsDragging] = (0, import_react2.useState)(false);
208
+ const [isPressed, setIsPressed] = (0, import_react2.useState)(false);
209
+ const startPosRef = (0, import_react2.useRef)(null);
210
+ const handlePointerDown = (0, import_react2.useCallback)((e) => {
211
+ startPosRef.current = { x: e.clientX, y: e.clientY };
212
+ e.currentTarget.setPointerCapture(e.pointerId);
213
+ setIsPressed(true);
214
+ setIsDragging(false);
215
+ }, []);
216
+ const handlePointerMove = (0, import_react2.useCallback)((e) => {
217
+ if (!startPosRef.current || !isListening) return;
218
+ const deltaY = e.clientY - startPosRef.current.y;
219
+ const deltaX = e.clientX - startPosRef.current.x;
220
+ let shouldTrigger = false;
221
+ if (direction === "up") {
222
+ shouldTrigger = deltaY < -threshold;
223
+ } else {
224
+ const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
225
+ shouldTrigger = distance > threshold;
226
+ }
227
+ if (shouldTrigger) {
228
+ setIsDragging(true);
229
+ } else {
230
+ setIsDragging(false);
231
+ }
232
+ }, [isListening, threshold, direction]);
233
+ const handlePointerUp = (0, import_react2.useCallback)((e) => {
234
+ if (!startPosRef.current) return;
235
+ const deltaY = e.clientY - startPosRef.current.y;
236
+ const deltaX = e.clientX - startPosRef.current.x;
237
+ let isCancelled = false;
238
+ if (direction === "up") {
239
+ isCancelled = deltaY < -threshold;
240
+ } else {
241
+ const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
242
+ isCancelled = distance > threshold;
243
+ }
244
+ if (isListening && isCancelled) {
245
+ onCancel();
246
+ } else {
247
+ onCommit();
248
+ }
249
+ startPosRef.current = null;
250
+ setIsDragging(false);
251
+ setIsPressed(false);
252
+ e.currentTarget.releasePointerCapture(e.pointerId);
253
+ }, [isListening, threshold, direction, onCancel, onCommit]);
254
+ const handlePointerCancel = (0, import_react2.useCallback)((e) => {
255
+ startPosRef.current = null;
256
+ setIsDragging(false);
257
+ setIsPressed(false);
258
+ }, []);
259
+ return {
260
+ handlers: {
261
+ onPointerDown: handlePointerDown,
262
+ onPointerMove: handlePointerMove,
263
+ onPointerUp: handlePointerUp,
264
+ onPointerCancel: handlePointerCancel
265
+ },
266
+ isDragging,
267
+ isPressed
268
+ };
269
+ };
270
+
271
+ // src/ui/react/components/VoiceInputButton.tsx
272
+ var import_jsx_runtime5 = require("react/jsx-runtime");
273
+ var VoiceInputButton = ({
274
+ voiceConfig,
275
+ voiceTrigger,
276
+ isTranscribing,
277
+ setVoiceTrigger,
278
+ setShowDebug,
279
+ tapCountRef,
280
+ customRecorder,
281
+ startRecording,
282
+ stopRecording
283
+ }) => {
284
+ const { handlers, isDragging, isPressed } = useDragCancel({
285
+ isListening: !!voiceTrigger,
286
+ onCancel: () => {
287
+ var _a;
288
+ console.log("[ChatInputArea] Gesture Cancel");
289
+ customRecorder.cancel();
290
+ setVoiceTrigger(null);
291
+ (_a = voiceConfig == null ? void 0 : voiceConfig.onVoiceEnd) == null ? void 0 : _a.call(voiceConfig);
292
+ },
293
+ onCommit: () => {
294
+ const now = Date.now();
295
+ if (now - tapCountRef.current.lastTap < 500) {
296
+ tapCountRef.current.count++;
297
+ } else {
298
+ tapCountRef.current.count = 1;
299
+ }
300
+ tapCountRef.current.lastTap = now;
301
+ if (tapCountRef.current.count >= 5) {
302
+ setShowDebug((prev) => !prev);
303
+ tapCountRef.current.count = 0;
304
+ stopRecording();
305
+ return;
306
+ }
307
+ if (voiceTrigger) {
308
+ stopRecording();
309
+ } else if (!isTranscribing) {
310
+ startRecording("click");
311
+ }
312
+ },
313
+ threshold: 30
314
+ });
315
+ let btnClass = "text-gray-500 border-gray-300 bg-white hover:text-gray-700 hover:bg-gray-100";
316
+ let icon = /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_outline.MicrophoneIcon, { className: "w-5 h-5" });
317
+ if (isTranscribing) {
318
+ btnClass = "text-white border-indigo-500 bg-indigo-600 scale-110 shadow-lg cursor-wait";
319
+ icon = /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "animate-spin w-5 h-5 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("svg", { className: "w-5 h-5 text-white", viewBox: "0 0 24 24", children: [
320
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4", fill: "none" }),
321
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" })
322
+ ] }) });
323
+ } else if (voiceTrigger) {
324
+ btnClass = "text-white border-orange-400 bg-orange-500 scale-110 shadow-lg animate-pulse";
325
+ }
326
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "relative flex flex-col items-center", children: [
327
+ voiceTrigger && !isTranscribing && isPressed && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: `absolute bottom-full mb-4 left-0 px-3 py-2 rounded-full text-xs font-semibold whitespace-nowrap shadow-xl transition-all duration-200 z-50 flex items-center gap-2 pointer-events-none transform
328
+ ${isDragging ? "bg-red-500 text-white scale-110" : "bg-white text-red-500 border border-red-100"}`, children: [
329
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: `transition-transform duration-300 ${isDragging ? "rotate-180" : ""}`, children: isDragging ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_outline.XMarkIcon, { className: "w-4 h-4" }) : "\u2191" }),
330
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: isDragging ? "Release to Cancel" : "Drag here to cancel" }),
331
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: `absolute top-full left-4 -translate-x-1/2 border-8 border-transparent transition-colors duration-200
332
+ ${isDragging ? "border-t-red-500" : "border-t-white"}` })
333
+ ] }),
334
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
335
+ "button",
336
+ {
337
+ type: "button",
338
+ ...handlers,
339
+ className: `mb-1 p-2 rounded-full transition-all duration-300 flex-shrink-0 border touch-none select-none ${btnClass}`,
340
+ disabled: isTranscribing,
341
+ title: isTranscribing ? "Transcribing..." : isDragging ? "Release to Cancel" : voiceTrigger ? "Stop Recording" : "Start Voice Input",
342
+ children: icon
343
+ }
344
+ )
345
+ ] });
346
+ };
347
+
348
+ // src/ui/react/hooks/useAudioRecorder.ts
349
+ var import_react3 = require("react");
197
350
  var useAudioRecorder = (onStop) => {
198
- const [isRecording, setIsRecording] = (0, import_react2.useState)(false);
199
- const [isSimulated, setIsSimulated] = (0, import_react2.useState)(false);
200
- const [blob, setBlob] = (0, import_react2.useState)(null);
201
- const [error, setError] = (0, import_react2.useState)(null);
202
- const mediaRecorderRef = (0, import_react2.useRef)(null);
203
- const chunksRef = (0, import_react2.useRef)([]);
204
- const start = (0, import_react2.useCallback)(async () => {
351
+ const [isRecording, setIsRecording] = (0, import_react3.useState)(false);
352
+ const [isSimulated, setIsSimulated] = (0, import_react3.useState)(false);
353
+ const [blob, setBlob] = (0, import_react3.useState)(null);
354
+ const [error, setError] = (0, import_react3.useState)(null);
355
+ const mediaRecorderRef = (0, import_react3.useRef)(null);
356
+ const chunksRef = (0, import_react3.useRef)([]);
357
+ const cancelledRef = (0, import_react3.useRef)(false);
358
+ const start = (0, import_react3.useCallback)(async () => {
359
+ cancelledRef.current = false;
205
360
  try {
206
361
  if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
207
362
  if (process.env.NODE_ENV === "development") {
@@ -228,6 +383,14 @@ var useAudioRecorder = (onStop) => {
228
383
  }
229
384
  };
230
385
  mediaRecorder.onstop = () => {
386
+ if (cancelledRef.current) {
387
+ console.log("[useAudioRecorder] Recording cancelled, discarding data.");
388
+ setIsRecording(false);
389
+ stream.getTracks().forEach((track) => {
390
+ track.stop();
391
+ });
392
+ return;
393
+ }
231
394
  const audioBlob = new Blob(chunksRef.current, { type: "audio/webm" });
232
395
  setBlob(audioBlob);
233
396
  setIsRecording(false);
@@ -244,7 +407,7 @@ var useAudioRecorder = (onStop) => {
244
407
  setError(e.message || "Microphone access denied");
245
408
  }
246
409
  }, [onStop]);
247
- const stop = (0, import_react2.useCallback)(() => {
410
+ const stop = (0, import_react3.useCallback)(() => {
248
411
  if (isSimulated) {
249
412
  setIsRecording(false);
250
413
  setIsSimulated(false);
@@ -257,20 +420,32 @@ var useAudioRecorder = (onStop) => {
257
420
  mediaRecorderRef.current.stop();
258
421
  }
259
422
  }, [isSimulated, onStop]);
423
+ const cancel = (0, import_react3.useCallback)(() => {
424
+ cancelledRef.current = true;
425
+ if (isSimulated) {
426
+ setIsRecording(false);
427
+ setIsSimulated(false);
428
+ return;
429
+ }
430
+ if (mediaRecorderRef.current && mediaRecorderRef.current.state !== "inactive") {
431
+ mediaRecorderRef.current.stop();
432
+ }
433
+ }, [isSimulated]);
260
434
  return {
261
435
  isRecording,
262
436
  isSimulated,
263
437
  start,
264
438
  stop,
439
+ cancel,
265
440
  blob,
266
441
  error
267
442
  };
268
443
  };
269
444
 
270
445
  // src/ui/react/hooks/useProactiveResize.ts
271
- var import_react3 = require("react");
446
+ var import_react4 = require("react");
272
447
  function useProactiveResize(textareaRef, measurementRef, value, disabled) {
273
- (0, import_react3.useEffect)(() => {
448
+ (0, import_react4.useEffect)(() => {
274
449
  if (!textareaRef.current || !measurementRef.current) return;
275
450
  const styles = window.getComputedStyle(textareaRef.current);
276
451
  measurementRef.current.style.width = styles.width;
@@ -289,8 +464,8 @@ function useProactiveResize(textareaRef, measurementRef, value, disabled) {
289
464
  }
290
465
 
291
466
  // src/ui/react/components/ChatInputArea.tsx
292
- var import_jsx_runtime5 = require("react/jsx-runtime");
293
- var ChatInputArea = (0, import_react4.forwardRef)(({
467
+ var import_jsx_runtime6 = require("react/jsx-runtime");
468
+ var ChatInputArea = (0, import_react5.forwardRef)(({
294
469
  onSubmit,
295
470
  isSending,
296
471
  showInputForm,
@@ -306,15 +481,15 @@ var ChatInputArea = (0, import_react4.forwardRef)(({
306
481
  defaultInputMode = "text"
307
482
  }, ref) => {
308
483
  var _a, _b, _c, _d;
309
- const [internalMessage, setInternalMessage] = (0, import_react4.useState)("");
310
- const [voiceTrigger, setVoiceTrigger] = (0, import_react4.useState)(null);
311
- const [isTranscribing, setIsTranscribing] = (0, import_react4.useState)(false);
312
- const [voiceError, setVoiceError] = (0, import_react4.useState)(null);
313
- const [isFocused, setIsFocused] = (0, import_react4.useState)(false);
314
- const [showDebug, setShowDebug] = (0, import_react4.useState)(false);
315
- const [logs, setLogs] = (0, import_react4.useState)([]);
316
- const tapCountRef = (0, import_react4.useRef)({ count: 0, lastTap: 0 });
317
- (0, import_react4.useEffect)(() => {
484
+ const [internalMessage, setInternalMessage] = (0, import_react5.useState)("");
485
+ const [voiceTrigger, setVoiceTrigger] = (0, import_react5.useState)(null);
486
+ const [isTranscribing, setIsTranscribing] = (0, import_react5.useState)(false);
487
+ const [voiceError, setVoiceError] = (0, import_react5.useState)(null);
488
+ const [isFocused, setIsFocused] = (0, import_react5.useState)(false);
489
+ const [showDebug, setShowDebug] = (0, import_react5.useState)(false);
490
+ const [logs, setLogs] = (0, import_react5.useState)([]);
491
+ const tapCountRef = (0, import_react5.useRef)({ count: 0, lastTap: 0 });
492
+ (0, import_react5.useEffect)(() => {
318
493
  const originalLog = console.log;
319
494
  const originalWarn = console.warn;
320
495
  const originalError = console.error;
@@ -347,17 +522,17 @@ var ChatInputArea = (0, import_react4.forwardRef)(({
347
522
  console.error = originalError;
348
523
  };
349
524
  }, []);
350
- const copyLogs = (0, import_react4.useCallback)(() => {
525
+ const copyLogs = (0, import_react5.useCallback)(() => {
351
526
  navigator.clipboard.writeText(logs.join("\n")).then(() => alert("Logs copied to clipboard")).catch((err) => console.error("Failed to copy logs", err));
352
527
  }, [logs]);
353
- const textareaRef = (0, import_react4.useRef)(null);
354
- const measurementRef = (0, import_react4.useRef)(null);
355
- const pendingSelectionRef = (0, import_react4.useRef)(null);
528
+ const textareaRef = (0, import_react5.useRef)(null);
529
+ const measurementRef = (0, import_react5.useRef)(null);
530
+ const pendingSelectionRef = (0, import_react5.useRef)(null);
356
531
  const isControlled = value !== void 0;
357
532
  const message = isControlled ? value : internalMessage;
358
- const messageRef = (0, import_react4.useRef)(message);
533
+ const messageRef = (0, import_react5.useRef)(message);
359
534
  messageRef.current = message;
360
- (0, import_react4.useLayoutEffect)(() => {
535
+ (0, import_react5.useLayoutEffect)(() => {
361
536
  if (pendingSelectionRef.current && textareaRef.current) {
362
537
  const { start, end } = pendingSelectionRef.current;
363
538
  textareaRef.current.focus();
@@ -365,18 +540,18 @@ var ChatInputArea = (0, import_react4.forwardRef)(({
365
540
  pendingSelectionRef.current = null;
366
541
  }
367
542
  }, [message]);
368
- const onChangeRef = (0, import_react4.useRef)(onChange);
369
- (0, import_react4.useEffect)(() => {
543
+ const onChangeRef = (0, import_react5.useRef)(onChange);
544
+ (0, import_react5.useEffect)(() => {
370
545
  onChangeRef.current = onChange;
371
546
  }, [onChange]);
372
547
  const { voice: globalVoice } = useChatConfig();
373
548
  const isVoiceEnabled = (_a = globalVoice == null ? void 0 : globalVoice.enabled) != null ? _a : !!propVoiceConfig;
374
549
  const voiceConfig = isVoiceEnabled ? propVoiceConfig || (globalVoice == null ? void 0 : globalVoice.config) : void 0;
375
- const voiceConfigRef = (0, import_react4.useRef)(voiceConfig);
376
- (0, import_react4.useEffect)(() => {
550
+ const voiceConfigRef = (0, import_react5.useRef)(voiceConfig);
551
+ (0, import_react5.useEffect)(() => {
377
552
  voiceConfigRef.current = voiceConfig;
378
553
  }, [voiceConfig]);
379
- const triggerChange = (0, import_react4.useCallback)((newValue) => {
554
+ const triggerChange = (0, import_react5.useCallback)((newValue) => {
380
555
  setVoiceError(null);
381
556
  if (isControlled && onChangeRef.current) {
382
557
  const syntheticEvent = {
@@ -390,7 +565,7 @@ var ChatInputArea = (0, import_react4.forwardRef)(({
390
565
  }, [isControlled]);
391
566
  const isInputDisabled = (currentTask == null ? void 0 : currentTask.complete) || (lastInteractiveMessage == null ? void 0 : lastInteractiveMessage.interactive) && (((_b = lastInteractiveMessage == null ? void 0 : lastInteractiveMessage.interactiveData) == null ? void 0 : _b.function) === "form" && !(lastInteractiveMessage == null ? void 0 : lastInteractiveMessage.isResponseSubmitted) || ((_c = lastInteractiveMessage == null ? void 0 : lastInteractiveMessage.interactiveData) == null ? void 0 : _c.function) === "confirm" && !(lastInteractiveMessage == null ? void 0 : lastInteractiveMessage.isResponseSubmitted));
392
567
  useProactiveResize(textareaRef, measurementRef, message, isInputDisabled || !!voiceTrigger);
393
- const insertTextAtCursor = (0, import_react4.useCallback)((text) => {
568
+ const insertTextAtCursor = (0, import_react5.useCallback)((text) => {
394
569
  const textarea = textareaRef.current;
395
570
  const currentVal = messageRef.current || "";
396
571
  if (!textarea) {
@@ -408,12 +583,12 @@ var ChatInputArea = (0, import_react4.forwardRef)(({
408
583
  pendingSelectionRef.current = { start: selectionStart, end: selectionEnd };
409
584
  triggerChange(newText);
410
585
  }, [triggerChange]);
411
- const handleVoiceResult = (0, import_react4.useCallback)((text, isFinal) => {
586
+ const handleVoiceResult = (0, import_react5.useCallback)((text, isFinal) => {
412
587
  if (isFinal) {
413
588
  insertTextAtCursor(text);
414
589
  }
415
590
  }, [insertTextAtCursor]);
416
- const handleVoiceEnd = (0, import_react4.useCallback)(() => {
591
+ const handleVoiceEnd = (0, import_react5.useCallback)(() => {
417
592
  var _a2, _b2;
418
593
  setVoiceTrigger(null);
419
594
  (_b2 = (_a2 = voiceConfigRef.current) == null ? void 0 : _a2.onVoiceEnd) == null ? void 0 : _b2.call(_a2);
@@ -445,7 +620,7 @@ var ChatInputArea = (0, import_react4.forwardRef)(({
445
620
  setIsTranscribing(false);
446
621
  }
447
622
  });
448
- (0, import_react4.useImperativeHandle)(ref, () => ({
623
+ (0, import_react5.useImperativeHandle)(ref, () => ({
449
624
  focus: () => {
450
625
  var _a2;
451
626
  (_a2 = textareaRef.current) == null ? void 0 : _a2.focus();
@@ -524,62 +699,43 @@ var ChatInputArea = (0, import_react4.forwardRef)(({
524
699
  if (!showInputForm) {
525
700
  return null;
526
701
  }
527
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex flex-col w-full relative", children: [
528
- showDebug && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "absolute bottom-full left-0 right-0 mb-2 p-2 bg-black/80 text-green-400 text-xs font-mono h-48 overflow-y-auto rounded z-50 pointer-events-auto", children: [
529
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex justify-between items-center bg-gray-800 p-1 mb-1", children: [
530
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "Debug Logs" }),
531
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex gap-2", children: [
532
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { onClick: copyLogs, className: "text-white hover:text-blue-400", title: "Copy Logs", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_outline.Square2StackIcon, { className: "w-4 h-4" }) }),
533
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { onClick: () => {
702
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex flex-col w-full relative", children: [
703
+ showDebug && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "absolute bottom-full left-0 right-0 mb-2 p-2 bg-black/80 text-green-400 text-xs font-mono h-48 overflow-y-auto rounded z-50 pointer-events-auto", children: [
704
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex justify-between items-center bg-gray-800 p-1 mb-1", children: [
705
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "Debug Logs" }),
706
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex gap-2", children: [
707
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { onClick: copyLogs, className: "text-white hover:text-blue-400", title: "Copy Logs", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_outline2.Square2StackIcon, { className: "w-4 h-4" }) }),
708
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { onClick: () => {
534
709
  copyLogs();
535
710
  setShowDebug(false);
536
- }, className: "text-white hover:text-red-400", title: "Copy & Close", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_outline.XMarkIcon, { className: "w-4 h-4" }) })
711
+ }, className: "text-white hover:text-red-400", title: "Copy & Close", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_outline2.XMarkIcon, { className: "w-4 h-4" }) })
537
712
  ] })
538
713
  ] }),
539
- logs.map((log, i) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mb-0.5 border-b border-gray-700/50 pb-0.5 break-all", children: log }, i)),
540
- logs.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { children: "No logs yet..." })
714
+ logs.map((log, i) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "mb-0.5 border-b border-gray-700/50 pb-0.5 break-all", children: log }, i)),
715
+ logs.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { children: "No logs yet..." })
541
716
  ] }),
542
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center gap-2", children: [
543
- voiceConfig && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
544
- "button",
717
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-2", children: [
718
+ voiceConfig && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
719
+ VoiceInputButton,
545
720
  {
546
- type: "button",
547
- onClick: () => {
548
- const now = Date.now();
549
- if (now - tapCountRef.current.lastTap < 500) {
550
- tapCountRef.current.count++;
551
- } else {
552
- tapCountRef.current.count = 1;
553
- }
554
- tapCountRef.current.lastTap = now;
555
- if (tapCountRef.current.count >= 5) {
556
- setShowDebug((prev) => !prev);
557
- tapCountRef.current.count = 0;
558
- stopRecording();
559
- return;
560
- }
561
- if (voiceTrigger) {
562
- stopRecording();
563
- } else if (!isTranscribing) {
564
- startRecording("click");
565
- }
566
- },
567
- className: `mb-1 p-2 rounded-full transition-all duration-300 flex-shrink-0 border ${isTranscribing ? "text-white border-indigo-500 bg-indigo-600 scale-110 shadow-lg" : voiceTrigger ? "text-white border-orange-400 bg-orange-500 scale-110 shadow-lg" : "text-gray-500 border-gray-300 bg-white hover:text-gray-700 hover:bg-gray-100"} ${voiceTrigger ? "animate-pulse" : ""} ${isTranscribing ? "cursor-wait" : ""}`,
568
- disabled: isTranscribing,
569
- title: isTranscribing ? "Transcribing..." : voiceTrigger ? "Stop Recording" : "Start Voice Input",
570
- children: isTranscribing ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "animate-spin w-5 h-5 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("svg", { className: "w-5 h-5 text-white", viewBox: "0 0 24 24", children: [
571
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4", fill: "none" }),
572
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" })
573
- ] }) }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_outline.MicrophoneIcon, { className: "w-5 h-5" })
721
+ voiceConfig,
722
+ voiceTrigger,
723
+ isTranscribing,
724
+ setVoiceTrigger,
725
+ setShowDebug,
726
+ tapCountRef,
727
+ customRecorder,
728
+ startRecording,
729
+ stopRecording
574
730
  }
575
731
  ),
576
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
732
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
577
733
  "div",
578
734
  {
579
735
  tabIndex: -1,
580
736
  className: `flex-1 flex items-center border border-gray-300 rounded-lg overflow-hidden outline-none bg-white min-h-[42px] mb-1 transition-all ${voiceTrigger ? "ring-2 ring-orange-100 border-orange-300" : "focus-within:ring-2 focus-within:ring-blue-500 focus-within:border-blue-500"}`,
581
737
  children: [
582
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
738
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
583
739
  "span",
584
740
  {
585
741
  ref: measurementRef,
@@ -587,7 +743,7 @@ var ChatInputArea = (0, import_react4.forwardRef)(({
587
743
  style: { fontSize: "1rem" }
588
744
  }
589
745
  ),
590
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
746
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
591
747
  "textarea",
592
748
  {
593
749
  ref: textareaRef,
@@ -612,8 +768,8 @@ var ChatInputArea = (0, import_react4.forwardRef)(({
612
768
  className: `flex-grow px-4 py-2 outline-none text-gray-700 placeholder-gray-500 resize-none leading-6 w-full ${isInputDisabled ? "bg-gray-100 cursor-not-allowed" : "bg-transparent"} ${voiceTrigger || isTranscribing ? "cursor-default" : ""}`
613
769
  }
614
770
  ),
615
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "relative mx-2 flex-shrink-0", children: [
616
- isSending && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "absolute -inset-1", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
771
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "relative mx-2 flex-shrink-0", children: [
772
+ isSending && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "absolute -inset-1", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
617
773
  "svg",
618
774
  {
619
775
  className: "animate-spin h-full w-full text-blue-500 opacity-75",
@@ -621,7 +777,7 @@ var ChatInputArea = (0, import_react4.forwardRef)(({
621
777
  fill: "none",
622
778
  viewBox: "0 0 24 24",
623
779
  children: [
624
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
780
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
625
781
  "circle",
626
782
  {
627
783
  className: "opacity-25",
@@ -632,7 +788,7 @@ var ChatInputArea = (0, import_react4.forwardRef)(({
632
788
  strokeWidth: "4"
633
789
  }
634
790
  ),
635
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
791
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
636
792
  "path",
637
793
  {
638
794
  className: "opacity-75",
@@ -643,7 +799,7 @@ var ChatInputArea = (0, import_react4.forwardRef)(({
643
799
  ]
644
800
  }
645
801
  ) }),
646
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
802
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
647
803
  "button",
648
804
  {
649
805
  type: "button",
@@ -658,7 +814,7 @@ var ChatInputArea = (0, import_react4.forwardRef)(({
658
814
  disabled: (currentTask == null ? void 0 : currentTask.complete) || isSending && !onStop || isInputDisabled,
659
815
  className: `relative z-10 text-white rounded-full p-2 transition-colors duration-200 disabled:bg-gray-400 disabled:cursor-not-allowed ${isSending && onStop ? "bg-red-500 hover:bg-red-600" : "bg-blue-600 hover:bg-blue-700"}`,
660
816
  title: isSending && onStop ? "Stop generating" : "Send message",
661
- children: isSending ? onStop ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_outline.StopIcon, { className: "h-5 w-5" }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "w-5 h-5" }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_outline.PaperAirplaneIcon, { className: "h-5 w-5" })
817
+ children: isSending ? onStop ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_outline2.StopIcon, { className: "h-5 w-5" }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "w-5 h-5" }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_outline2.PaperAirplaneIcon, { className: "h-5 w-5" })
662
818
  }
663
819
  )
664
820
  ] })
@@ -666,19 +822,19 @@ var ChatInputArea = (0, import_react4.forwardRef)(({
666
822
  }
667
823
  )
668
824
  ] }),
669
- inputHint && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "text-sm text-red-500 bg-red-50 py-1 px-4 rounded-lg mt-1", children: inputHint }),
670
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "ml-[46px] mb-2 mt-0.5 min-h-[0.75rem]", style: { marginLeft: "48px" }, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: `text-[10px] leading-tight transition-all duration-200 ${voiceError ? "text-red-500" : isTranscribing ? "text-indigo-600 font-bold" : voiceTrigger ? "text-orange-600 font-medium" : "text-gray-400"}`, children: voiceError ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "flex items-center gap-1 font-semibold italic", children: [
825
+ inputHint && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "text-sm text-red-500 bg-red-50 py-1 px-4 rounded-lg mt-1", children: inputHint }),
826
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "ml-[46px] mb-2 mt-0.5 min-h-[0.75rem]", style: { marginLeft: "48px" }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: `text-[10px] leading-tight transition-all duration-200 ${voiceError ? "text-red-500" : isTranscribing ? "text-indigo-600 font-bold" : voiceTrigger ? "text-orange-600 font-medium" : "text-gray-400"}`, children: voiceError ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "flex items-center gap-1 font-semibold italic", children: [
671
827
  "Error: ",
672
828
  voiceError
673
- ] }) : isTranscribing ? "Transcribing... please wait" : voiceTrigger ? "Transcribing, please wait..." : voiceTrigger ? "Listening... tap mic icon again to stop" : hintText || (voiceConfig ? "Type in text or tap mic icon to talk" : "Type your message...") }) })
829
+ ] }) : isTranscribing ? "Transcribing... please wait" : voiceTrigger ? "Listening... Tap again to stop" : hintText || (voiceConfig ? "Type in text or tap mic icon to talk" : "Type your message...") }) })
674
830
  ] });
675
831
  });
676
832
  ChatInputArea.displayName = "ChatInputArea";
677
833
 
678
834
  // src/ui/react/components/TapToTalk.tsx
679
- var import_react5 = __toESM(require("react"), 1);
680
- var import_outline2 = require("@heroicons/react/24/outline");
681
- var import_jsx_runtime6 = require("react/jsx-runtime");
835
+ var import_react6 = __toESM(require("react"), 1);
836
+ var import_outline3 = require("@heroicons/react/24/outline");
837
+ var import_jsx_runtime7 = require("react/jsx-runtime");
682
838
  var TapToTalk = ({
683
839
  onResult,
684
840
  voiceConfig: propVoiceConfig,
@@ -691,13 +847,13 @@ var TapToTalk = ({
691
847
  var _a;
692
848
  const globalConfig = useChatConfig();
693
849
  const voiceConfig = propVoiceConfig || ((_a = globalConfig.voice) == null ? void 0 : _a.config);
694
- const [isTranscribing, setIsTranscribing] = (0, import_react5.useState)(false);
695
- const [voiceTrigger, setVoiceTrigger] = (0, import_react5.useState)(null);
696
- const [errorMsg, setErrorMsg] = (0, import_react5.useState)(null);
697
- const [showDebug, setShowDebug] = (0, import_react5.useState)(false);
698
- const [logs, setLogs] = (0, import_react5.useState)([]);
699
- const tapCountRef = (0, import_react5.useRef)({ count: 0, lastTap: 0 });
700
- import_react5.default.useEffect(() => {
850
+ const [isTranscribing, setIsTranscribing] = (0, import_react6.useState)(false);
851
+ const [voiceTrigger, setVoiceTrigger] = (0, import_react6.useState)(null);
852
+ const [errorMsg, setErrorMsg] = (0, import_react6.useState)(null);
853
+ const [showDebug, setShowDebug] = (0, import_react6.useState)(false);
854
+ const [logs, setLogs] = (0, import_react6.useState)([]);
855
+ const tapCountRef = (0, import_react6.useRef)({ count: 0, lastTap: 0 });
856
+ import_react6.default.useEffect(() => {
701
857
  const originalLog = console.log;
702
858
  const originalWarn = console.warn;
703
859
  const originalError = console.error;
@@ -730,10 +886,10 @@ var TapToTalk = ({
730
886
  console.error = originalError;
731
887
  };
732
888
  }, []);
733
- const copyLogs = (0, import_react5.useCallback)(() => {
889
+ const copyLogs = (0, import_react6.useCallback)(() => {
734
890
  navigator.clipboard.writeText(logs.join("\n")).then(() => alert("Logs copied to clipboard")).catch((err) => console.error("Failed to copy logs", err));
735
891
  }, [logs]);
736
- const handleVoiceEnd = (0, import_react5.useCallback)(() => {
892
+ const handleVoiceEnd = (0, import_react6.useCallback)(() => {
737
893
  setVoiceTrigger(null);
738
894
  }, []);
739
895
  const customRecorder = useAudioRecorder(async (blob) => {
@@ -765,7 +921,7 @@ var TapToTalk = ({
765
921
  });
766
922
  const isListening = !!voiceTrigger || customRecorder.isRecording;
767
923
  const isActive = isListening || isTranscribing;
768
- const processingRef = (0, import_react5.useRef)(false);
924
+ const processingRef = (0, import_react6.useRef)(false);
769
925
  const toggleVoice = async () => {
770
926
  var _a2, _b, _c;
771
927
  if (processingRef.current) {
@@ -822,54 +978,75 @@ var TapToTalk = ({
822
978
  }, 300);
823
979
  }
824
980
  };
981
+ const { handlers, isDragging, isPressed } = useDragCancel({
982
+ isListening: !!voiceTrigger,
983
+ onCancel: () => {
984
+ var _a2;
985
+ console.log("[TapToTalk] Gesture Cancel");
986
+ customRecorder.cancel();
987
+ setVoiceTrigger(null);
988
+ (_a2 = voiceConfig == null ? void 0 : voiceConfig.onVoiceEnd) == null ? void 0 : _a2.call(voiceConfig);
989
+ },
990
+ onCommit: () => {
991
+ toggleVoice();
992
+ },
993
+ threshold: 30
994
+ });
825
995
  let bgColor = accentColor;
826
996
  let label = "Tap to Talk";
827
- let Icon = /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_outline2.MicrophoneIcon, { className: "h-5 w-5" });
997
+ let Icon = /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_outline3.MicrophoneIcon, { className: "h-5 w-5" });
828
998
  if (isListening) {
829
999
  bgColor = "bg-orange-500";
830
- label = "Listening ... Tap to stop";
831
- Icon = /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_outline2.MicrophoneIcon, { className: "h-5 w-5 animate-pulse" });
1000
+ label = "Listening... Tap again to stop";
1001
+ Icon = /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_outline3.MicrophoneIcon, { className: "h-5 w-5 animate-pulse" });
832
1002
  } else if (isTranscribing) {
833
1003
  bgColor = "bg-indigo-600";
834
1004
  label = "Transcribing ...";
835
- Icon = /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("svg", { className: "animate-spin h-5 w-5 text-white", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", children: [
836
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
837
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" })
1005
+ Icon = /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("svg", { className: "animate-spin h-5 w-5 text-white", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", children: [
1006
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
1007
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" })
838
1008
  ] });
839
1009
  }
840
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex flex-col w-full relative", children: [
841
- showDebug && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "absolute bottom-full left-0 right-0 mb-2 p-2 bg-black/80 text-green-400 text-xs font-mono h-48 overflow-y-auto rounded z-50 pointer-events-auto", children: [
842
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex justify-between items-center bg-gray-800 p-1 mb-1", children: [
843
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "Debug Logs" }),
844
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex gap-2", children: [
845
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { onClick: (e) => {
1010
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-col w-full relative items-center", children: [
1011
+ isListening && !isTranscribing && isPressed && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: `absolute bottom-full mb-6 left-1/2 -translate-x-1/2 px-4 py-2 rounded-full text-sm font-semibold whitespace-nowrap shadow-xl transition-all duration-200 z-50 flex items-center gap-2 pointer-events-none transform
1012
+ ${isDragging ? "bg-red-500 text-white scale-110" : "bg-white text-red-500 border border-red-100"}`, children: [
1013
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: `transition-transform duration-300 ${isDragging ? "rotate-180" : ""}`, children: isDragging ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_outline3.XMarkIcon, { className: "w-5 h-5" }) : "\u2191" }),
1014
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: isDragging ? "Release to Cancel" : "Drag here to cancel" }),
1015
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: `absolute top-full left-1/2 -translate-x-1/2 border-8 border-transparent transition-colors duration-200
1016
+ ${isDragging ? "border-t-red-500" : "border-t-white"}` })
1017
+ ] }),
1018
+ showDebug && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "absolute bottom-full left-0 right-0 mb-2 p-2 bg-black/80 text-green-400 text-xs font-mono h-48 overflow-y-auto rounded z-50 pointer-events-auto", children: [
1019
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex justify-between items-center bg-gray-800 p-1 mb-1", children: [
1020
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "Debug Logs" }),
1021
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex gap-2", children: [
1022
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { onClick: (e) => {
846
1023
  e.stopPropagation();
847
1024
  copyLogs();
848
- }, className: "text-white hover:text-blue-400", title: "Copy Logs", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_outline2.Square2StackIcon, { className: "w-4 h-4" }) }),
849
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { onClick: (e) => {
1025
+ }, className: "text-white hover:text-blue-400", title: "Copy Logs", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_outline3.Square2StackIcon, { className: "w-4 h-4" }) }),
1026
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { onClick: (e) => {
850
1027
  e.stopPropagation();
851
1028
  copyLogs();
852
1029
  setShowDebug(false);
853
- }, className: "text-white hover:text-red-400", title: "Copy & Close", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_outline2.XMarkIcon, { className: "w-4 h-4" }) })
1030
+ }, className: "text-white hover:text-red-400", title: "Copy & Close", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_outline3.XMarkIcon, { className: "w-4 h-4" }) })
854
1031
  ] })
855
1032
  ] }),
856
- logs.map((log, i) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "mb-0.5 border-b border-gray-700/50 pb-0.5 break-all", children: log }, i)),
857
- logs.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { children: "No logs yet..." })
1033
+ logs.map((log, i) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "mb-0.5 border-b border-gray-700/50 pb-0.5 break-all", children: log }, i)),
1034
+ logs.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { children: "No logs yet..." })
858
1035
  ] }),
859
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1036
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
860
1037
  "button",
861
1038
  {
862
- onClick: toggleVoice,
1039
+ ...handlers,
863
1040
  disabled: disabled || isTranscribing && !isListening,
864
- className: `flex items-center justify-center gap-3 px-6 py-3 rounded-xl transition-all duration-300 w-full font-medium shadow-md active:scale-[0.98]
1041
+ className: `flex items-center justify-center gap-3 px-6 py-3 rounded-xl transition-all duration-300 w-full font-medium shadow-md touch-none select-none
865
1042
  ${bgColor} text-white
866
1043
  ${disabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer"}
867
1044
  ${className}`,
868
1045
  title: label,
869
1046
  children: [
870
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "flex items-center justify-center shrink-0", children: Icon }),
871
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "truncate", children: label }),
872
- errorMsg && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-[10px] bg-white/20 px-1.5 py-0.5 rounded text-red-100 animate-in fade-in slide-in-from-right-1", children: errorMsg })
1047
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "flex items-center justify-center shrink-0", children: Icon }),
1048
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "truncate", children: label }),
1049
+ errorMsg && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-[10px] bg-white/20 px-1.5 py-0.5 rounded text-red-100 animate-in fade-in slide-in-from-right-1", children: errorMsg })
873
1050
  ]
874
1051
  }
875
1052
  )
@@ -877,17 +1054,17 @@ var TapToTalk = ({
877
1054
  };
878
1055
 
879
1056
  // src/ui/react/components/ChatMessageList.tsx
880
- var import_react9 = require("react");
1057
+ var import_react10 = require("react");
881
1058
 
882
1059
  // src/ui/react/components/interactive/ConfirmInteraction.tsx
883
- var import_react6 = require("react");
884
- var import_jsx_runtime7 = require("react/jsx-runtime");
1060
+ var import_react7 = require("react");
1061
+ var import_jsx_runtime8 = require("react/jsx-runtime");
885
1062
  var ConfirmInteraction = ({
886
1063
  parameters,
887
1064
  onResponse,
888
1065
  isResponseSubmitted
889
1066
  }) => {
890
- const [selectedOption, setSelectedOption] = (0, import_react6.useState)(null);
1067
+ const [selectedOption, setSelectedOption] = (0, import_react7.useState)(null);
891
1068
  const params = parameters;
892
1069
  const { yesPrompt, noPrompt } = params;
893
1070
  console.log("[ConfirmInteraction] Parameters:", params);
@@ -896,8 +1073,8 @@ var ConfirmInteraction = ({
896
1073
  setSelectedOption(buttonText);
897
1074
  onResponse(value);
898
1075
  };
899
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "mt-2 mb-4", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex space-x-2", children: [
900
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1076
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "mt-2 mb-4", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex space-x-2", children: [
1077
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
901
1078
  "button",
902
1079
  {
903
1080
  onClick: () => handleOptionClick(true, yesPrompt),
@@ -906,7 +1083,7 @@ var ConfirmInteraction = ({
906
1083
  children: yesPrompt
907
1084
  }
908
1085
  ),
909
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1086
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
910
1087
  "button",
911
1088
  {
912
1089
  onClick: () => handleOptionClick(false, noPrompt),
@@ -920,19 +1097,19 @@ var ConfirmInteraction = ({
920
1097
  var ConfirmInteraction_default = ConfirmInteraction;
921
1098
 
922
1099
  // src/ui/react/components/interactive/SelectInteraction.tsx
923
- var import_react7 = require("react");
924
- var import_jsx_runtime8 = require("react/jsx-runtime");
1100
+ var import_react8 = require("react");
1101
+ var import_jsx_runtime9 = require("react/jsx-runtime");
925
1102
  var SelectInteraction = ({
926
1103
  parameters,
927
1104
  onResponse,
928
1105
  isResponseSubmitted,
929
1106
  message
930
1107
  }) => {
931
- const [selectedOption, setSelectedOption] = (0, import_react7.useState)(null);
932
- const [customOption, setCustomOption] = (0, import_react7.useState)(null);
1108
+ const [selectedOption, setSelectedOption] = (0, import_react8.useState)(null);
1109
+ const [customOption, setCustomOption] = (0, import_react8.useState)(null);
933
1110
  const params = parameters;
934
1111
  const { question, options, placeholder } = params;
935
- (0, import_react7.useEffect)(() => {
1112
+ (0, import_react8.useEffect)(() => {
936
1113
  if (isResponseSubmitted && (message == null ? void 0 : message.responseValue)) {
937
1114
  const responseValueStr = String(message.responseValue);
938
1115
  setSelectedOption(responseValueStr);
@@ -947,8 +1124,8 @@ var SelectInteraction = ({
947
1124
  setCustomOption(null);
948
1125
  onResponse(option);
949
1126
  };
950
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "mt-2 mb-4", children: [
951
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "flex flex-wrap gap-2", children: options.map((option, index) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1127
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "mt-2 mb-4", children: [
1128
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "flex flex-wrap gap-2", children: options.map((option, index) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
952
1129
  "button",
953
1130
  {
954
1131
  onClick: () => handleOptionClick(option),
@@ -958,9 +1135,9 @@ var SelectInteraction = ({
958
1135
  },
959
1136
  index
960
1137
  )) }),
961
- customOption && isResponseSubmitted && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "mt-2 text-sm text-amber-600 bg-amber-50 p-2 rounded", children: [
1138
+ customOption && isResponseSubmitted && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "mt-2 text-sm text-amber-600 bg-amber-50 p-2 rounded", children: [
962
1139
  "User provided custom option: ",
963
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "font-semibold", children: [
1140
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { className: "font-semibold", children: [
964
1141
  '"',
965
1142
  customOption,
966
1143
  '"'
@@ -971,20 +1148,20 @@ var SelectInteraction = ({
971
1148
  var SelectInteraction_default = SelectInteraction;
972
1149
 
973
1150
  // src/ui/react/components/interactive/FormInteraction.tsx
974
- var import_react8 = require("react");
1151
+ var import_react9 = require("react");
975
1152
  var import_lucide_react = require("lucide-react");
976
- var import_jsx_runtime9 = require("react/jsx-runtime");
1153
+ var import_jsx_runtime10 = require("react/jsx-runtime");
977
1154
  var FormInteraction = ({
978
1155
  parameters,
979
1156
  onResponse,
980
1157
  isResponseSubmitted,
981
1158
  submittedValues
982
1159
  }) => {
983
- const [isModalOpen, setIsModalOpen] = (0, import_react8.useState)(false);
984
- const [formValues, setFormValues] = (0, import_react8.useState)({});
985
- const [isExpanded, setIsExpanded] = (0, import_react8.useState)(false);
986
- const [parsedFields, setParsedFields] = (0, import_react8.useState)([]);
987
- const formButtonsRef = (0, import_react8.useRef)(null);
1160
+ const [isModalOpen, setIsModalOpen] = (0, import_react9.useState)(false);
1161
+ const [formValues, setFormValues] = (0, import_react9.useState)({});
1162
+ const [isExpanded, setIsExpanded] = (0, import_react9.useState)(false);
1163
+ const [parsedFields, setParsedFields] = (0, import_react9.useState)([]);
1164
+ const formButtonsRef = (0, import_react9.useRef)(null);
988
1165
  const parseParameters = () => {
989
1166
  const { prompt, description, submitText = "Submit", cancelText = "Cancel" } = parameters;
990
1167
  let fieldsArray = [];
@@ -1045,7 +1222,7 @@ var FormInteraction = ({
1045
1222
  };
1046
1223
  };
1047
1224
  const params = parseParameters();
1048
- (0, import_react8.useEffect)(() => {
1225
+ (0, import_react9.useEffect)(() => {
1049
1226
  const processedParams = parseParameters();
1050
1227
  setParsedFields(processedParams.fields);
1051
1228
  const initialValues = {};
@@ -1063,7 +1240,7 @@ var FormInteraction = ({
1063
1240
  setIsModalOpen(true);
1064
1241
  }
1065
1242
  }, [parameters, isResponseSubmitted]);
1066
- (0, import_react8.useEffect)(() => {
1243
+ (0, import_react9.useEffect)(() => {
1067
1244
  if (isModalOpen && formButtonsRef.current) {
1068
1245
  setTimeout(() => {
1069
1246
  var _a;
@@ -1093,12 +1270,12 @@ var FormInteraction = ({
1093
1270
  case "email":
1094
1271
  case "number":
1095
1272
  case "password":
1096
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "mb-4 flex items-center space-x-4", children: [
1097
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("label", { htmlFor: name, className: "text-sm font-medium text-gray-700 min-w-[120px]", children: [
1273
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "mb-4 flex items-center space-x-4", children: [
1274
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("label", { htmlFor: name, className: "text-sm font-medium text-gray-700 min-w-[120px]", children: [
1098
1275
  label,
1099
- required && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "text-red-500", children: "*" })
1276
+ required && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-red-500", children: "*" })
1100
1277
  ] }),
1101
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1278
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1102
1279
  "input",
1103
1280
  {
1104
1281
  type: type === "string" ? "text" : type,
@@ -1114,12 +1291,12 @@ var FormInteraction = ({
1114
1291
  )
1115
1292
  ] }, name);
1116
1293
  case "textarea":
1117
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "mb-4 flex items-start space-x-4", children: [
1118
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("label", { htmlFor: name, className: "text-sm font-medium text-gray-700 min-w-[120px] pt-2", children: [
1294
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "mb-4 flex items-start space-x-4", children: [
1295
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("label", { htmlFor: name, className: "text-sm font-medium text-gray-700 min-w-[120px] pt-2", children: [
1119
1296
  label,
1120
- required && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "text-red-500", children: "*" })
1297
+ required && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-red-500", children: "*" })
1121
1298
  ] }),
1122
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1299
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1123
1300
  "textarea",
1124
1301
  {
1125
1302
  id: name,
@@ -1135,12 +1312,12 @@ var FormInteraction = ({
1135
1312
  )
1136
1313
  ] }, name);
1137
1314
  case "select":
1138
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "mb-4 flex items-center space-x-4", children: [
1139
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("label", { htmlFor: name, className: "text-sm font-medium text-gray-700 min-w-[120px]", children: [
1315
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "mb-4 flex items-center space-x-4", children: [
1316
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("label", { htmlFor: name, className: "text-sm font-medium text-gray-700 min-w-[120px]", children: [
1140
1317
  label,
1141
- required && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "text-red-500", children: "*" })
1318
+ required && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-red-500", children: "*" })
1142
1319
  ] }),
1143
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
1320
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
1144
1321
  "select",
1145
1322
  {
1146
1323
  id: name,
@@ -1151,17 +1328,17 @@ var FormInteraction = ({
1151
1328
  disabled: isResponseSubmitted,
1152
1329
  className: "flex-1 px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500",
1153
1330
  children: [
1154
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("option", { value: "", disabled: true, children: placeholder || "Select an option" }),
1155
- options == null ? void 0 : options.map((option, index) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("option", { value: option, children: option }, index))
1331
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: "", disabled: true, children: placeholder || "Select an option" }),
1332
+ options == null ? void 0 : options.map((option, index) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: option, children: option }, index))
1156
1333
  ]
1157
1334
  }
1158
1335
  )
1159
1336
  ] }, name);
1160
1337
  case "checkbox":
1161
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "mb-4 flex items-center space-x-4", children: [
1162
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "min-w-[120px]" }),
1163
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex items-center", children: [
1164
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1338
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "mb-4 flex items-center space-x-4", children: [
1339
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "min-w-[120px]" }),
1340
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center", children: [
1341
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1165
1342
  "input",
1166
1343
  {
1167
1344
  type: "checkbox",
@@ -1174,20 +1351,20 @@ var FormInteraction = ({
1174
1351
  className: "h-4 w-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500"
1175
1352
  }
1176
1353
  ),
1177
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("label", { htmlFor: name, className: "ml-2 text-sm text-gray-700", children: [
1354
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("label", { htmlFor: name, className: "ml-2 text-sm text-gray-700", children: [
1178
1355
  label,
1179
- required && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "text-red-500", children: "*" })
1356
+ required && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-red-500", children: "*" })
1180
1357
  ] })
1181
1358
  ] })
1182
1359
  ] }, name);
1183
1360
  case "radio":
1184
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "mb-4 flex space-x-4", children: [
1185
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "text-sm font-medium text-gray-700 min-w-[120px] pt-2", children: [
1361
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "mb-4 flex space-x-4", children: [
1362
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "text-sm font-medium text-gray-700 min-w-[120px] pt-2", children: [
1186
1363
  label,
1187
- required && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "text-red-500", children: "*" })
1364
+ required && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-red-500", children: "*" })
1188
1365
  ] }),
1189
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "flex-1 space-y-2", children: options == null ? void 0 : options.map((option, index) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex items-center", children: [
1190
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1366
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "flex-1 space-y-2", children: options == null ? void 0 : options.map((option, index) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center", children: [
1367
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1191
1368
  "input",
1192
1369
  {
1193
1370
  id: `${name}-${index}`,
@@ -1201,7 +1378,7 @@ var FormInteraction = ({
1201
1378
  className: "h-4 w-4 text-blue-600 border-gray-300 focus:ring-blue-500"
1202
1379
  }
1203
1380
  ),
1204
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("label", { htmlFor: `${name}-${index}`, className: "ml-2 text-sm text-gray-700", children: option })
1381
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("label", { htmlFor: `${name}-${index}`, className: "ml-2 text-sm text-gray-700", children: option })
1205
1382
  ] }, index)) })
1206
1383
  ] }, name);
1207
1384
  default:
@@ -1209,27 +1386,27 @@ var FormInteraction = ({
1209
1386
  }
1210
1387
  };
1211
1388
  if (isResponseSubmitted) {
1212
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "mt-2 bg-gray-50 p-3 rounded-md border border-gray-200", children: [
1213
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex justify-between items-center cursor-pointer", onClick: () => setIsExpanded(!isExpanded), children: [
1214
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { className: "font-medium text-gray-700", children: [
1389
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "mt-2 bg-gray-50 p-3 rounded-md border border-gray-200", children: [
1390
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex justify-between items-center cursor-pointer", onClick: () => setIsExpanded(!isExpanded), children: [
1391
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "font-medium text-gray-700", children: [
1215
1392
  isExpanded ? "Hide" : "Show",
1216
1393
  " Form Responses"
1217
1394
  ] }),
1218
- isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_lucide_react.ChevronUpIcon, { className: "h-5 w-5 text-gray-500" }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_lucide_react.ChevronDownIcon, { className: "h-5 w-5 text-gray-500" })
1395
+ isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react.ChevronUpIcon, { className: "h-5 w-5 text-gray-500" }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react.ChevronDownIcon, { className: "h-5 w-5 text-gray-500" })
1219
1396
  ] }),
1220
- isExpanded && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "mt-2 space-y-2", children: parsedFields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex", children: [
1221
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { className: "text-sm font-medium text-gray-600 mr-2", children: [
1397
+ isExpanded && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "mt-2 space-y-2", children: parsedFields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex", children: [
1398
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "text-sm font-medium text-gray-600 mr-2", children: [
1222
1399
  field.label,
1223
1400
  ":"
1224
1401
  ] }),
1225
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "text-sm text-gray-800", children: typeof (submittedValues == null ? void 0 : submittedValues[field.name]) === "boolean" ? submittedValues[field.name] ? "Yes" : "No" : (submittedValues == null ? void 0 : submittedValues[field.name]) || "Not provided" })
1402
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-sm text-gray-800", children: typeof (submittedValues == null ? void 0 : submittedValues[field.name]) === "boolean" ? submittedValues[field.name] ? "Yes" : "No" : (submittedValues == null ? void 0 : submittedValues[field.name]) || "Not provided" })
1226
1403
  ] }, field.name)) })
1227
1404
  ] });
1228
1405
  }
1229
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "mt-2", children: isModalOpen && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "p-4", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("form", { onSubmit: handleSubmit, className: "mt-4", children: [
1406
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "mt-2", children: isModalOpen && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "p-4", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("form", { onSubmit: handleSubmit, className: "mt-4", children: [
1230
1407
  parsedFields.map((field) => renderField(field)),
1231
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { ref: formButtonsRef, className: "flex justify-end mt-4 space-x-2", children: [
1232
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1408
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { ref: formButtonsRef, className: "flex justify-end mt-4 space-x-2", children: [
1409
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1233
1410
  "button",
1234
1411
  {
1235
1412
  type: "button",
@@ -1239,7 +1416,7 @@ var FormInteraction = ({
1239
1416
  children: params.cancelText
1240
1417
  }
1241
1418
  ),
1242
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1419
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1243
1420
  "button",
1244
1421
  {
1245
1422
  type: "submit",
@@ -1254,12 +1431,12 @@ var FormInteraction = ({
1254
1431
  var FormInteraction_default = FormInteraction;
1255
1432
 
1256
1433
  // src/ui/react/components/interactive/PresentInteraction.tsx
1257
- var import_jsx_runtime10 = require("react/jsx-runtime");
1434
+ var import_jsx_runtime11 = require("react/jsx-runtime");
1258
1435
  var ReactMarkdown2;
1259
1436
  try {
1260
1437
  ReactMarkdown2 = require("react-markdown");
1261
1438
  } catch (error) {
1262
- ReactMarkdown2 = ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "whitespace-pre-wrap", children });
1439
+ ReactMarkdown2 = ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "whitespace-pre-wrap", children });
1263
1440
  }
1264
1441
  var PresentInteraction = ({
1265
1442
  parameters
@@ -1297,15 +1474,15 @@ var PresentInteraction = ({
1297
1474
  }
1298
1475
  };
1299
1476
  const styles = getLevelStyles();
1300
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: `mt-2 mb-4 p-4 ${styles.container} border rounded-md`, children: [
1301
- title && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: `font-medium ${styles.title} mb-2`, children: title }),
1302
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: `text-sm ${styles.content}`, children: format === "markdown" ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ReactMarkdown2, { className: "prose prose-sm max-w-none", children: content }) : format === "html" ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { dangerouslySetInnerHTML: { __html: content } }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "whitespace-pre-wrap", children: content }) })
1477
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: `mt-2 mb-4 p-4 ${styles.container} border rounded-md`, children: [
1478
+ title && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: `font-medium ${styles.title} mb-2`, children: title }),
1479
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: `text-sm ${styles.content}`, children: format === "markdown" ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ReactMarkdown2, { className: "prose prose-sm max-w-none", children: content }) : format === "html" ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { dangerouslySetInnerHTML: { __html: content } }) : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "whitespace-pre-wrap", children: content }) })
1303
1480
  ] });
1304
1481
  };
1305
1482
  var PresentInteraction_default = PresentInteraction;
1306
1483
 
1307
1484
  // src/ui/react/components/interactive/InteractiveMessageHandler.tsx
1308
- var import_jsx_runtime11 = require("react/jsx-runtime");
1485
+ var import_jsx_runtime12 = require("react/jsx-runtime");
1309
1486
  var InteractiveMessageHandler = ({
1310
1487
  message,
1311
1488
  onResponse,
@@ -1316,7 +1493,7 @@ var InteractiveMessageHandler = ({
1316
1493
  const submittedResponse = parentMessage == null ? void 0 : parentMessage.responseValue;
1317
1494
  switch (functionType) {
1318
1495
  case "confirm":
1319
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1496
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1320
1497
  ConfirmInteraction_default,
1321
1498
  {
1322
1499
  parameters,
@@ -1325,7 +1502,7 @@ var InteractiveMessageHandler = ({
1325
1502
  }
1326
1503
  );
1327
1504
  case "select":
1328
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1505
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1329
1506
  SelectInteraction_default,
1330
1507
  {
1331
1508
  parameters,
@@ -1335,7 +1512,7 @@ var InteractiveMessageHandler = ({
1335
1512
  }
1336
1513
  );
1337
1514
  case "form":
1338
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1515
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1339
1516
  FormInteraction_default,
1340
1517
  {
1341
1518
  parameters,
@@ -1345,7 +1522,7 @@ var InteractiveMessageHandler = ({
1345
1522
  }
1346
1523
  );
1347
1524
  case "present":
1348
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1525
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1349
1526
  PresentInteraction_default,
1350
1527
  {
1351
1528
  parameters
@@ -1361,8 +1538,8 @@ var InteractiveMessageHandler = ({
1361
1538
  var InteractiveMessageHandler_default = InteractiveMessageHandler;
1362
1539
 
1363
1540
  // src/ui/react/components/ChatMessageList.tsx
1364
- var import_outline3 = require("@heroicons/react/24/outline");
1365
- var import_jsx_runtime12 = require("react/jsx-runtime");
1541
+ var import_outline4 = require("@heroicons/react/24/outline");
1542
+ var import_jsx_runtime13 = require("react/jsx-runtime");
1366
1543
  var ChatMessageList = ({
1367
1544
  chatHistory,
1368
1545
  isProcessing,
@@ -1371,10 +1548,10 @@ var ChatMessageList = ({
1371
1548
  getContextExample,
1372
1549
  onInteractiveResponse
1373
1550
  }) => {
1374
- const chatContainerRef = (0, import_react9.useRef)(null);
1375
- const lastMessageRef = (0, import_react9.useRef)(null);
1376
- const processingIndicatorRef = (0, import_react9.useRef)(null);
1377
- (0, import_react9.useEffect)(() => {
1551
+ const chatContainerRef = (0, import_react10.useRef)(null);
1552
+ const lastMessageRef = (0, import_react10.useRef)(null);
1553
+ const processingIndicatorRef = (0, import_react10.useRef)(null);
1554
+ (0, import_react10.useEffect)(() => {
1378
1555
  if (isProcessing && processingIndicatorRef.current) {
1379
1556
  processingIndicatorRef.current.scrollIntoView({ behavior: "smooth" });
1380
1557
  return;
@@ -1390,15 +1567,15 @@ var ChatMessageList = ({
1390
1567
  onInteractiveResponse(messageId, response);
1391
1568
  }
1392
1569
  };
1393
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
1570
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1394
1571
  "div",
1395
1572
  {
1396
1573
  ref: chatContainerRef,
1397
1574
  className: "flex-1 overflow-y-auto p-4 space-y-8 bg-gray-50",
1398
1575
  children: [
1399
- chatHistory.length === 0 && !isProcessing && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "text-center py-8", children: [
1400
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("h3", { className: "text-lg font-medium text-gray-700 mb-2", children: "How can I help you today?" }),
1401
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("p", { className: "text-sm text-gray-500 mb-4", children: [
1576
+ chatHistory.length === 0 && !isProcessing && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "text-center py-8", children: [
1577
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("h3", { className: "text-lg font-medium text-gray-700 mb-2", children: "How can I help you today?" }),
1578
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("p", { className: "text-sm text-gray-500 mb-4", children: [
1402
1579
  "Try asking me something like ",
1403
1580
  getContextExample()
1404
1581
  ] })
@@ -1407,14 +1584,14 @@ var ChatMessageList = ({
1407
1584
  const isLastMessage = index === chatHistory.length - 1;
1408
1585
  const isUser = message.role === "user";
1409
1586
  const isError = message.role === "error";
1410
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
1587
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1411
1588
  "div",
1412
1589
  {
1413
1590
  ref: isLastMessage ? lastMessageRef : void 0,
1414
1591
  className: `flex flex-col w-full ${isUser ? "items-end" : "items-start"}`,
1415
1592
  children: [
1416
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "text-xs text-gray-400 mb-1 px-1", children: message.timestamp ? `${isUser ? "Sent" : "Received"} at ${new Date(message.timestamp).toLocaleString()}` : "" }),
1417
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "w-full", children: message.interactive && message.interactiveData ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: `max-w-[85%] ${isUser ? "ml-auto" : "mr-auto"}`, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1593
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "text-xs text-gray-400 mb-1 px-1", children: message.timestamp ? `${isUser ? "Sent" : "Received"} at ${new Date(message.timestamp).toLocaleString()}` : "" }),
1594
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "w-full", children: message.interactive && message.interactiveData ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: `max-w-[85%] ${isUser ? "ml-auto" : "mr-auto"}`, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1418
1595
  InteractiveMessageHandler_default,
1419
1596
  {
1420
1597
  message: message.interactiveData,
@@ -1426,16 +1603,16 @@ var ChatMessageList = ({
1426
1603
  isResponseSubmitted: !!message.isResponseSubmitted,
1427
1604
  parentMessage: message
1428
1605
  }
1429
- ) }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1606
+ ) }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1430
1607
  MessageBubble,
1431
1608
  {
1432
1609
  message,
1433
1610
  isUser
1434
1611
  }
1435
1612
  ) }),
1436
- isUser && message.interactive && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex items-center mt-1 space-x-1 text-xs text-gray-500 italic", children: [
1437
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_outline3.InformationCircleIcon, { className: "h-3 w-3 text-blue-400" }),
1438
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { children: [
1613
+ isUser && message.interactive && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center mt-1 space-x-1 text-xs text-gray-500 italic", children: [
1614
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_outline4.InformationCircleIcon, { className: "h-3 w-3 text-blue-400" }),
1615
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { children: [
1439
1616
  message.request === "form" && "Response to form submission",
1440
1617
  message.request === "select" && "Response to selection prompt",
1441
1618
  message.request === "confirm" && "Response to confirmation prompt"
@@ -1446,29 +1623,29 @@ var ChatMessageList = ({
1446
1623
  message.id || `message-${index}`
1447
1624
  );
1448
1625
  }),
1449
- isProcessing && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1626
+ isProcessing && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1450
1627
  "div",
1451
1628
  {
1452
1629
  ref: processingIndicatorRef,
1453
1630
  className: "flex justify-start my-4",
1454
- children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "bg-white text-gray-800 border border-gray-200 rounded-lg px-4 py-2 max-w-[85%]", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex items-center", children: [
1455
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "text-sm", children: processingHint }),
1456
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "ml-2 flex space-x-1", children: [
1457
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "h-2 w-2 bg-gray-400 rounded-full animate-bounce", style: { animationDelay: "0ms" } }),
1458
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "h-2 w-2 bg-gray-400 rounded-full animate-bounce", style: { animationDelay: "150ms" } }),
1459
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "h-2 w-2 bg-gray-400 rounded-full animate-bounce", style: { animationDelay: "300ms" } })
1631
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "bg-white text-gray-800 border border-gray-200 rounded-lg px-4 py-2 max-w-[85%]", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center", children: [
1632
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "text-sm", children: processingHint }),
1633
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { className: "ml-2 flex space-x-1", children: [
1634
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "h-2 w-2 bg-gray-400 rounded-full animate-bounce", style: { animationDelay: "0ms" } }),
1635
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "h-2 w-2 bg-gray-400 rounded-full animate-bounce", style: { animationDelay: "150ms" } }),
1636
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "h-2 w-2 bg-gray-400 rounded-full animate-bounce", style: { animationDelay: "300ms" } })
1460
1637
  ] })
1461
1638
  ] }) })
1462
1639
  }
1463
1640
  ),
1464
- currentTask && !currentTask.complete && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "mt-4 bg-blue-50 border border-blue-100 rounded-lg p-3", children: [
1465
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "text-sm text-blue-800 mb-1", children: [
1641
+ currentTask && !currentTask.complete && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "mt-4 bg-blue-50 border border-blue-100 rounded-lg p-3", children: [
1642
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "text-sm text-blue-800 mb-1", children: [
1466
1643
  "Task in progress: Step ",
1467
1644
  currentTask.currentStep,
1468
1645
  " of ",
1469
1646
  currentTask.steps
1470
1647
  ] }),
1471
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "w-full bg-blue-200 rounded-full h-2", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1648
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "w-full bg-blue-200 rounded-full h-2", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1472
1649
  "div",
1473
1650
  {
1474
1651
  className: "bg-blue-500 h-2 rounded-full",
@@ -1483,34 +1660,34 @@ var ChatMessageList = ({
1483
1660
 
1484
1661
  // src/ui/react/components/ConnectionStatus.tsx
1485
1662
  var import_lucide_react2 = require("lucide-react");
1486
- var import_jsx_runtime13 = require("react/jsx-runtime");
1663
+ var import_jsx_runtime14 = require("react/jsx-runtime");
1487
1664
  var ConnectionStatus = ({
1488
1665
  connectionStatus,
1489
1666
  onReconnect
1490
1667
  }) => {
1491
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "bg-amber-100 connection-status flex items-center justify-between px-4 py-1 text-xs", children: [
1492
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "text-gray-700 font-medium", children: "You are talking with your personal Content Strategist" }),
1493
- connectionStatus === "connected" && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center text-green-600", children: [
1494
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react2.Wifi, { className: "w-3 h-3 mr-1" }),
1495
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children: "Connected" })
1668
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "bg-amber-100 connection-status flex items-center justify-between px-4 py-1 text-xs", children: [
1669
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "text-gray-700 font-medium", children: "You are talking with your personal Content Strategist" }),
1670
+ connectionStatus === "connected" && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex items-center text-green-600", children: [
1671
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react2.Wifi, { className: "w-3 h-3 mr-1" }),
1672
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: "Connected" })
1496
1673
  ] }),
1497
- connectionStatus === "reconnecting" && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center text-amber-600", children: [
1498
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react2.RefreshCw, { className: "w-3 h-3 mr-1 animate-spin" }),
1499
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children: "Reconnecting..." })
1674
+ connectionStatus === "reconnecting" && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex items-center text-amber-600", children: [
1675
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react2.RefreshCw, { className: "w-3 h-3 mr-1 animate-spin" }),
1676
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: "Reconnecting..." })
1500
1677
  ] }),
1501
- connectionStatus === "disconnected" && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center gap-2", children: [
1502
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "text-red-600 flex items-center", children: [
1503
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react2.WifiOff, { className: "w-3 h-3 mr-1" }),
1504
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children: "Disconnected" })
1678
+ connectionStatus === "disconnected" && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex items-center gap-2", children: [
1679
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "text-red-600 flex items-center", children: [
1680
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react2.WifiOff, { className: "w-3 h-3 mr-1" }),
1681
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: "Disconnected" })
1505
1682
  ] }),
1506
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1683
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
1507
1684
  "button",
1508
1685
  {
1509
1686
  onClick: onReconnect,
1510
1687
  className: "text-blue-600 hover:text-blue-800 flex items-center",
1511
1688
  children: [
1512
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react2.RefreshCw, { className: "w-3 h-3 mr-1" }),
1513
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children: "Reconnect" })
1689
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react2.RefreshCw, { className: "w-3 h-3 mr-1" }),
1690
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: "Reconnect" })
1514
1691
  ]
1515
1692
  }
1516
1693
  )
@@ -1519,7 +1696,7 @@ var ConnectionStatus = ({
1519
1696
  };
1520
1697
 
1521
1698
  // src/ui/react/components/Spinner.tsx
1522
- var import_jsx_runtime14 = require("react/jsx-runtime");
1699
+ var import_jsx_runtime15 = require("react/jsx-runtime");
1523
1700
  var Spinner = ({
1524
1701
  size = "md",
1525
1702
  className = "",
@@ -1531,7 +1708,7 @@ var Spinner = ({
1531
1708
  lg: "h-8 w-8",
1532
1709
  xl: "h-12 w-12"
1533
1710
  };
1534
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
1711
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
1535
1712
  "svg",
1536
1713
  {
1537
1714
  className: `animate-spin ${sizeClasses[size]} ${color} ${className}`,
@@ -1539,7 +1716,7 @@ var Spinner = ({
1539
1716
  fill: "none",
1540
1717
  viewBox: "0 0 24 24",
1541
1718
  children: [
1542
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1719
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1543
1720
  "circle",
1544
1721
  {
1545
1722
  className: "opacity-25",
@@ -1550,7 +1727,7 @@ var Spinner = ({
1550
1727
  strokeWidth: "4"
1551
1728
  }
1552
1729
  ),
1553
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1730
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1554
1731
  "path",
1555
1732
  {
1556
1733
  className: "opacity-75",