@apteva/apteva-kit 0.1.129 → 0.1.130

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -3370,7 +3370,7 @@ var getSpeechRecognition = () => {
3370
3370
  if (typeof window === "undefined") return null;
3371
3371
  return window.SpeechRecognition || window.webkitSpeechRecognition || null;
3372
3372
  };
3373
- function Composer({ onSendMessage, placeholder = "Type a message...", disabled = false, isLoading = false, onStop, onFileUpload, onSwitchMode, speechToText }) {
3373
+ function Composer({ onSendMessage, placeholder = "Type a message...", disabled = false, isLoading = false, onStop, onFileUpload, onSwitchMode, speechToText, enableVoice = false, voiceState = "idle", voicePartialTranscript = "", voiceDuration = 0, onVoiceStart, onVoiceStop }) {
3374
3374
  const [text, setText] = _react.useState.call(void 0, "");
3375
3375
  const [showMenu, setShowMenu] = _react.useState.call(void 0, false);
3376
3376
  const [pendingFiles, setPendingFiles] = _react.useState.call(void 0, []);
@@ -3663,6 +3663,31 @@ function Composer({ onSendMessage, placeholder = "Type a message...", disabled =
3663
3663
  const gridCols = hasMic ? "auto 1fr auto auto" : "auto 1fr auto";
3664
3664
  const gridAreas = isRecording ? '"plus waveform waveform stop"' : isMultiLine ? hasMic ? '"textarea textarea textarea textarea" "plus . mic send"' : '"textarea textarea textarea" "plus . send"' : hasMic ? '"plus textarea mic send"' : '"plus textarea send"';
3665
3665
  const gridColsRecording = "auto 1fr auto";
3666
+ const voiceActive = voiceState === "active" || voiceState === "connecting";
3667
+ const formatVoiceDuration = (s) => {
3668
+ const m = Math.floor(s / 60);
3669
+ const sec = s % 60;
3670
+ return `${m}:${sec.toString().padStart(2, "0")}`;
3671
+ };
3672
+ const showMicButton = enableVoice && !text.trim() && pendingFiles.length === 0 && !isLoading && !voiceActive;
3673
+ if (voiceActive) {
3674
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "px-4 py-3 relative", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "apteva-voice-overlay", children: [
3675
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "apteva-voice-transcript-area", children: voicePartialTranscript ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "apteva-voice-partial", children: voicePartialTranscript }) : voiceState === "connecting" ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "apteva-voice-connecting", children: "Connecting..." }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "apteva-voice-listening", children: "Listening..." }) }),
3676
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "apteva-voice-controls", children: [
3677
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "apteva-voice-duration", children: formatVoiceDuration(voiceDuration) }),
3678
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3679
+ "button",
3680
+ {
3681
+ onClick: onVoiceStop,
3682
+ className: "apteva-voice-stop-btn",
3683
+ title: "Stop voice mode",
3684
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "rect", { x: "3", y: "3", width: "10", height: "10", rx: "1", fill: "currentColor" }) })
3685
+ }
3686
+ )
3687
+ ] }),
3688
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "apteva-voice-indicator", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: `apteva-voice-pulse ${voiceState === "active" ? "apteva-voice-pulse-active" : ""}` }) })
3689
+ ] }) });
3690
+ }
3666
3691
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "px-4 py-3 relative", children: [
3667
3692
  fileError && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "apteva-file-error", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "apteva-file-error-content", children: [
3668
3693
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }),
@@ -3806,6 +3831,18 @@ function Composer({ onSendMessage, placeholder = "Type a message...", disabled =
3806
3831
  title: "Stop generation",
3807
3832
  children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "rect", { x: "2", y: "2", width: "10", height: "10", rx: "1", fill: "currentColor" }) })
3808
3833
  }
3834
+ ) : showMicButton ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3835
+ "button",
3836
+ {
3837
+ onClick: onVoiceStart,
3838
+ className: "apteva-composer-voice-btn w-8 h-8 rounded-lg flex items-center justify-center transition-all flex-shrink-0",
3839
+ title: "Start voice mode",
3840
+ children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
3841
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M12 1a3 3 0 00-3 3v8a3 3 0 006 0V4a3 3 0 00-3-3z", fill: "currentColor" }),
3842
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M19 10v2a7 7 0 01-14 0v-2", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }),
3843
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M12 19v4M8 23h8", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" })
3844
+ ] })
3845
+ }
3809
3846
  ) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3810
3847
  "button",
3811
3848
  {
@@ -4366,6 +4403,261 @@ function PersistentWidgetPanel({ widgets, onAction }) {
4366
4403
  ] });
4367
4404
  }
4368
4405
 
4406
+ // src/hooks/useVoiceSession.ts
4407
+
4408
+
4409
+ // src/utils/audio-utils.ts
4410
+ function float32ToInt16(float32Array) {
4411
+ const int16Array = new Int16Array(float32Array.length);
4412
+ for (let i = 0; i < float32Array.length; i++) {
4413
+ const s = Math.max(-1, Math.min(1, float32Array[i]));
4414
+ int16Array[i] = s < 0 ? s * 32768 : s * 32767;
4415
+ }
4416
+ return int16Array;
4417
+ }
4418
+ function int16ToBase64(int16Array) {
4419
+ const uint8Array = new Uint8Array(int16Array.buffer);
4420
+ let binary = "";
4421
+ for (let i = 0; i < uint8Array.length; i++) {
4422
+ binary += String.fromCharCode(uint8Array[i]);
4423
+ }
4424
+ return btoa(binary);
4425
+ }
4426
+ function base64ToFloat32(base64) {
4427
+ const binaryString = atob(base64);
4428
+ const int16Array = new Int16Array(binaryString.length / 2);
4429
+ for (let i = 0; i < int16Array.length; i++) {
4430
+ int16Array[i] = binaryString.charCodeAt(i * 2 + 1) << 8 | binaryString.charCodeAt(i * 2);
4431
+ }
4432
+ const float32Array = new Float32Array(int16Array.length);
4433
+ for (let i = 0; i < int16Array.length; i++) {
4434
+ float32Array[i] = int16Array[i] / (int16Array[i] < 0 ? 32768 : 32767);
4435
+ }
4436
+ return float32Array;
4437
+ }
4438
+ function resampleAudio(inputData, inputSampleRate, outputSampleRate) {
4439
+ if (inputSampleRate === outputSampleRate) {
4440
+ return inputData;
4441
+ }
4442
+ const ratio = inputSampleRate / outputSampleRate;
4443
+ const outputLength = Math.floor(inputData.length / ratio);
4444
+ const output = new Float32Array(outputLength);
4445
+ for (let i = 0; i < outputLength; i++) {
4446
+ const srcIndex = i * ratio;
4447
+ const srcIndexFloor = Math.floor(srcIndex);
4448
+ const srcIndexCeil = Math.min(srcIndexFloor + 1, inputData.length - 1);
4449
+ const t = srcIndex - srcIndexFloor;
4450
+ output[i] = inputData[srcIndexFloor] * (1 - t) + inputData[srcIndexCeil] * t;
4451
+ }
4452
+ return output;
4453
+ }
4454
+
4455
+ // src/hooks/useVoiceSession.ts
4456
+ function useVoiceSession(config) {
4457
+ const [state, setState] = _react.useState.call(void 0, "idle");
4458
+ const [partialTranscript, setPartialTranscript] = _react.useState.call(void 0, "");
4459
+ const [duration, setDuration] = _react.useState.call(void 0, 0);
4460
+ const wsRef = _react.useRef.call(void 0, null);
4461
+ const captureCtxRef = _react.useRef.call(void 0, null);
4462
+ const playbackCtxRef = _react.useRef.call(void 0, null);
4463
+ const mediaStreamRef = _react.useRef.call(void 0, null);
4464
+ const processorRef = _react.useRef.call(void 0, null);
4465
+ const nextPlayTimeRef = _react.useRef.call(void 0, 0);
4466
+ const durationIntervalRef = _react.useRef.call(void 0, null);
4467
+ const startTimeRef = _react.useRef.call(void 0, 0);
4468
+ const configRef = _react.useRef.call(void 0, config);
4469
+ configRef.current = config;
4470
+ const cleanup = _react.useCallback.call(void 0, () => {
4471
+ if (durationIntervalRef.current) {
4472
+ clearInterval(durationIntervalRef.current);
4473
+ durationIntervalRef.current = null;
4474
+ }
4475
+ if (processorRef.current) {
4476
+ processorRef.current.disconnect();
4477
+ processorRef.current = null;
4478
+ }
4479
+ if (mediaStreamRef.current) {
4480
+ mediaStreamRef.current.getTracks().forEach((t) => t.stop());
4481
+ mediaStreamRef.current = null;
4482
+ }
4483
+ if (captureCtxRef.current) {
4484
+ try {
4485
+ captureCtxRef.current.close();
4486
+ } catch (_) {
4487
+ }
4488
+ captureCtxRef.current = null;
4489
+ }
4490
+ if (playbackCtxRef.current) {
4491
+ try {
4492
+ playbackCtxRef.current.close();
4493
+ } catch (_) {
4494
+ }
4495
+ playbackCtxRef.current = null;
4496
+ }
4497
+ if (wsRef.current) {
4498
+ try {
4499
+ wsRef.current.close();
4500
+ } catch (_) {
4501
+ }
4502
+ wsRef.current = null;
4503
+ }
4504
+ nextPlayTimeRef.current = 0;
4505
+ setPartialTranscript("");
4506
+ setDuration(0);
4507
+ }, []);
4508
+ _react.useEffect.call(void 0, () => {
4509
+ return () => {
4510
+ cleanup();
4511
+ };
4512
+ }, [cleanup]);
4513
+ const playAudioChunk = _react.useCallback.call(void 0, (base64Audio) => {
4514
+ if (!playbackCtxRef.current) {
4515
+ playbackCtxRef.current = new AudioContext({ sampleRate: 24e3 });
4516
+ }
4517
+ const ctx = playbackCtxRef.current;
4518
+ if (ctx.state === "suspended") {
4519
+ ctx.resume();
4520
+ }
4521
+ const float32Data = base64ToFloat32(base64Audio);
4522
+ const audioBuffer = ctx.createBuffer(1, float32Data.length, 24e3);
4523
+ audioBuffer.getChannelData(0).set(float32Data);
4524
+ const source = ctx.createBufferSource();
4525
+ source.buffer = audioBuffer;
4526
+ source.connect(ctx.destination);
4527
+ const currentTime = ctx.currentTime;
4528
+ const startTime = Math.max(currentTime, nextPlayTimeRef.current);
4529
+ source.start(startTime);
4530
+ nextPlayTimeRef.current = startTime + audioBuffer.duration;
4531
+ }, []);
4532
+ const handleMessage = _react.useCallback.call(void 0, (msg) => {
4533
+ const cfg = configRef.current;
4534
+ switch (msg.type) {
4535
+ case "session_created":
4536
+ setState("active");
4537
+ startTimeRef.current = Date.now();
4538
+ durationIntervalRef.current = setInterval(() => {
4539
+ setDuration(Math.floor((Date.now() - startTimeRef.current) / 1e3));
4540
+ }, 1e3);
4541
+ break;
4542
+ case "audio_delta":
4543
+ if (_optionalChain([msg, 'access', _93 => _93.data, 'optionalAccess', _94 => _94.chunk])) {
4544
+ playAudioChunk(msg.data.chunk);
4545
+ }
4546
+ break;
4547
+ case "transcript":
4548
+ if (msg.data) {
4549
+ if (msg.data.partial) {
4550
+ setPartialTranscript(msg.data.content);
4551
+ } else {
4552
+ setPartialTranscript("");
4553
+ _optionalChain([cfg, 'access', _95 => _95.onTranscript, 'optionalCall', _96 => _96({
4554
+ id: `vt-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`,
4555
+ role: msg.data.role,
4556
+ content: msg.data.content,
4557
+ partial: false,
4558
+ timestamp: /* @__PURE__ */ new Date()
4559
+ })]);
4560
+ }
4561
+ }
4562
+ break;
4563
+ case "tool_call":
4564
+ if (msg.data) {
4565
+ nextPlayTimeRef.current = 0;
4566
+ _optionalChain([cfg, 'access', _97 => _97.onTranscript, 'optionalCall', _98 => _98({
4567
+ id: `vt-tool-${Date.now()}`,
4568
+ role: "system",
4569
+ content: `Using ${msg.data.name}...`,
4570
+ partial: false,
4571
+ timestamp: /* @__PURE__ */ new Date()
4572
+ })]);
4573
+ }
4574
+ break;
4575
+ case "tool_result":
4576
+ if (msg.data) {
4577
+ nextPlayTimeRef.current = 0;
4578
+ }
4579
+ break;
4580
+ case "error":
4581
+ setState("error");
4582
+ _optionalChain([cfg, 'access', _99 => _99.onError, 'optionalCall', _100 => _100(new Error(_optionalChain([msg, 'access', _101 => _101.data, 'optionalAccess', _102 => _102.message]) || "Voice session error"))]);
4583
+ break;
4584
+ }
4585
+ }, [playAudioChunk]);
4586
+ const startCapture = _react.useCallback.call(void 0, async () => {
4587
+ const ws = wsRef.current;
4588
+ if (!ws) return;
4589
+ try {
4590
+ captureCtxRef.current = new AudioContext();
4591
+ const nativeSampleRate = captureCtxRef.current.sampleRate;
4592
+ mediaStreamRef.current = await navigator.mediaDevices.getUserMedia({ audio: true });
4593
+ const source = captureCtxRef.current.createMediaStreamSource(mediaStreamRef.current);
4594
+ processorRef.current = captureCtxRef.current.createScriptProcessor(2048, 1, 1);
4595
+ processorRef.current.onaudioprocess = (e) => {
4596
+ if (!ws || ws.readyState !== WebSocket.OPEN) return;
4597
+ const inputData = e.inputBuffer.getChannelData(0);
4598
+ const resampledData = resampleAudio(inputData, nativeSampleRate, 16e3);
4599
+ const int16Data = float32ToInt16(resampledData);
4600
+ const base64Data = int16ToBase64(int16Data);
4601
+ ws.send(JSON.stringify({
4602
+ type: "audio",
4603
+ data: { chunk: base64Data }
4604
+ }));
4605
+ };
4606
+ source.connect(processorRef.current);
4607
+ processorRef.current.connect(captureCtxRef.current.destination);
4608
+ } catch (e) {
4609
+ _optionalChain([configRef, 'access', _103 => _103.current, 'access', _104 => _104.onError, 'optionalCall', _105 => _105(new Error("Microphone access denied"))]);
4610
+ cleanup();
4611
+ setState("idle");
4612
+ }
4613
+ }, [cleanup]);
4614
+ const start = _react.useCallback.call(void 0, () => {
4615
+ if (state !== "idle") return;
4616
+ setState("connecting");
4617
+ const protocol = window.location.protocol === "https:" ? "wss:" : "ws:";
4618
+ const wsUrl = `${protocol}//${window.location.host}${config.apiUrl}/voice`;
4619
+ const ws = new WebSocket(wsUrl);
4620
+ wsRef.current = ws;
4621
+ ws.onopen = () => {
4622
+ const provider = configRef.current.provider || "openai";
4623
+ const voice = configRef.current.voice || "ash";
4624
+ ws.send(JSON.stringify({
4625
+ type: "start",
4626
+ data: { provider, voice }
4627
+ }));
4628
+ startCapture();
4629
+ };
4630
+ ws.onmessage = (event) => {
4631
+ try {
4632
+ const msg = JSON.parse(event.data);
4633
+ handleMessage(msg);
4634
+ } catch (_) {
4635
+ }
4636
+ };
4637
+ ws.onerror = () => {
4638
+ setState("error");
4639
+ _optionalChain([configRef, 'access', _106 => _106.current, 'access', _107 => _107.onError, 'optionalCall', _108 => _108(new Error("WebSocket connection failed"))]);
4640
+ };
4641
+ ws.onclose = () => {
4642
+ cleanup();
4643
+ setState("idle");
4644
+ };
4645
+ }, [state, config.apiUrl, startCapture, handleMessage, cleanup]);
4646
+ const stop = _react.useCallback.call(void 0, () => {
4647
+ cleanup();
4648
+ setState("idle");
4649
+ }, [cleanup]);
4650
+ const sendText = _react.useCallback.call(void 0, (text) => {
4651
+ const ws = wsRef.current;
4652
+ if (!ws || ws.readyState !== WebSocket.OPEN) return;
4653
+ ws.send(JSON.stringify({
4654
+ type: "text",
4655
+ data: { content: text }
4656
+ }));
4657
+ }, []);
4658
+ return { state, partialTranscript, duration, start, stop, sendText };
4659
+ }
4660
+
4369
4661
  // src/components/Chat/Chat.tsx
4370
4662
 
4371
4663
  var Chat = _react.forwardRef.call(void 0, function Chat2({
@@ -4418,6 +4710,10 @@ var Chat = _react.forwardRef.call(void 0, function Chat2({
4418
4710
  onWidgetRender,
4419
4711
  // Speech to text
4420
4712
  speechToText,
4713
+ // Realtime voice
4714
+ enableVoice = false,
4715
+ voiceProvider,
4716
+ voiceId,
4421
4717
  className
4422
4718
  }, ref) {
4423
4719
  const [messages, setMessages] = _react.useState.call(void 0, initialMessages);
@@ -4438,6 +4734,23 @@ var Chat = _react.forwardRef.call(void 0, function Chat2({
4438
4734
  const [internalPlanMode, setInternalPlanMode] = _react.useState.call(void 0, planMode);
4439
4735
  const [showSettingsMenu, setShowSettingsMenu] = _react.useState.call(void 0, false);
4440
4736
  const fileInputRef = _react.useRef.call(void 0, null);
4737
+ const handleVoiceTranscript = _react.useCallback.call(void 0, (entry) => {
4738
+ const msg = {
4739
+ id: entry.id,
4740
+ role: entry.role === "system" ? "assistant" : entry.role,
4741
+ content: entry.content,
4742
+ timestamp: entry.timestamp,
4743
+ metadata: entry.role === "system" ? { isVoiceSystem: true } : { isVoice: true }
4744
+ };
4745
+ setMessages((prev) => [...prev, msg]);
4746
+ }, []);
4747
+ const voice = useVoiceSession({
4748
+ apiUrl: apiUrl || "",
4749
+ provider: voiceProvider,
4750
+ voice: voiceId,
4751
+ onTranscript: handleVoiceTranscript,
4752
+ onError
4753
+ });
4441
4754
  const [persistentWidgets, setPersistentWidgets] = _react.useState.call(void 0, /* @__PURE__ */ new Map());
4442
4755
  const updatePersistentWidgets = _react.useCallback.call(void 0, (msgs) => {
4443
4756
  setPersistentWidgets((prev) => {
@@ -4493,7 +4806,7 @@ ${widgetContext}` : widgetContext;
4493
4806
  }, [apiUrl, apiKey]);
4494
4807
  _react.useEffect.call(void 0, () => {
4495
4808
  if (threadId) {
4496
- _optionalChain([onThreadChange, 'optionalCall', _93 => _93(threadId)]);
4809
+ _optionalChain([onThreadChange, 'optionalCall', _109 => _109(threadId)]);
4497
4810
  }
4498
4811
  }, [threadId, onThreadChange]);
4499
4812
  _react.useEffect.call(void 0, () => {
@@ -4511,7 +4824,7 @@ ${widgetContext}` : widgetContext;
4511
4824
  }, [showSettingsMenu]);
4512
4825
  const handleModeChange = (newMode) => {
4513
4826
  setMode(newMode);
4514
- _optionalChain([onModeChange, 'optionalCall', _94 => _94(newMode)]);
4827
+ _optionalChain([onModeChange, 'optionalCall', _110 => _110(newMode)]);
4515
4828
  if (newMode === "command") {
4516
4829
  setCommandState("idle");
4517
4830
  setCommandResult(null);
@@ -4520,8 +4833,8 @@ ${widgetContext}` : widgetContext;
4520
4833
  };
4521
4834
  const defaultPlaceholder = mode === "chat" ? "Type a message..." : "Enter your command...";
4522
4835
  const handleWidgetAction = _react.useCallback.call(void 0, (action) => {
4523
- _optionalChain([onAction, 'optionalCall', _95 => _95(action)]);
4524
- if (action.type === "submit" && _optionalChain([action, 'access', _96 => _96.payload, 'optionalAccess', _97 => _97.formData])) {
4836
+ _optionalChain([onAction, 'optionalCall', _111 => _111(action)]);
4837
+ if (action.type === "submit" && _optionalChain([action, 'access', _112 => _112.payload, 'optionalAccess', _113 => _113.formData])) {
4525
4838
  const formData = action.payload.formData;
4526
4839
  const lines = [];
4527
4840
  for (const [key, value] of Object.entries(formData)) {
@@ -4560,7 +4873,7 @@ ${widgetContext}` : widgetContext;
4560
4873
  metadata: hasFiles ? { attachments } : void 0
4561
4874
  };
4562
4875
  setMessages((prev) => [...prev, userMessage]);
4563
- _optionalChain([onMessageSent, 'optionalCall', _98 => _98(userMessage)]);
4876
+ _optionalChain([onMessageSent, 'optionalCall', _114 => _114(userMessage)]);
4564
4877
  }
4565
4878
  setIsLoading(true);
4566
4879
  try {
@@ -4628,7 +4941,7 @@ ${widgetContext}` : widgetContext;
4628
4941
  responseThreadId = chunk.thread_id;
4629
4942
  if (!currentThreadId) {
4630
4943
  setCurrentThreadId(chunk.thread_id);
4631
- _optionalChain([onThreadChange, 'optionalCall', _99 => _99(chunk.thread_id)]);
4944
+ _optionalChain([onThreadChange, 'optionalCall', _115 => _115(chunk.thread_id)]);
4632
4945
  }
4633
4946
  }
4634
4947
  break;
@@ -4660,7 +4973,7 @@ ${widgetContext}` : widgetContext;
4660
4973
  contentSegments.push({ type: "tool", id: chunk.tool_id, name: displayName, status: "preparing" });
4661
4974
  toolInputBuffers[chunk.tool_id] = "";
4662
4975
  setChatToolName(displayName);
4663
- _optionalChain([onToolCall, 'optionalCall', _100 => _100(chunk.tool_name, chunk.tool_id)]);
4976
+ _optionalChain([onToolCall, 'optionalCall', _116 => _116(chunk.tool_name, chunk.tool_id)]);
4664
4977
  updateMessage();
4665
4978
  }
4666
4979
  break;
@@ -4720,7 +5033,7 @@ ${widgetContext}` : widgetContext;
4720
5033
  toolSegment.result = chunk.content;
4721
5034
  toolSegment.status = "completed";
4722
5035
  toolSegment.isReceiving = false;
4723
- _optionalChain([onToolResult, 'optionalCall', _101 => _101(toolSegment.name, chunk.content)]);
5036
+ _optionalChain([onToolResult, 'optionalCall', _117 => _117(toolSegment.name, chunk.content)]);
4724
5037
  }
4725
5038
  setChatToolName(null);
4726
5039
  updateMessage();
@@ -4764,7 +5077,7 @@ ${widgetContext}` : widgetContext;
4764
5077
  });
4765
5078
  if (threadId2 && threadId2 !== currentThreadId) {
4766
5079
  setCurrentThreadId(threadId2);
4767
- _optionalChain([onThreadChange, 'optionalCall', _102 => _102(threadId2)]);
5080
+ _optionalChain([onThreadChange, 'optionalCall', _118 => _118(threadId2)]);
4768
5081
  }
4769
5082
  setIsLoading(false);
4770
5083
  setCurrentRequestId(null);
@@ -4788,7 +5101,7 @@ ${widgetContext}` : widgetContext;
4788
5101
  setIsLoading(false);
4789
5102
  setCurrentRequestId(null);
4790
5103
  setChatToolName(null);
4791
- _optionalChain([onError, 'optionalCall', _103 => _103(error)]);
5104
+ _optionalChain([onError, 'optionalCall', _119 => _119(error)]);
4792
5105
  }
4793
5106
  );
4794
5107
  }
@@ -4801,7 +5114,7 @@ ${widgetContext}` : widgetContext;
4801
5114
  metadata: { error: true }
4802
5115
  };
4803
5116
  setMessages((prev) => [...prev, errorMessage]);
4804
- _optionalChain([onError, 'optionalCall', _104 => _104(error instanceof Error ? error : new Error("Unknown error"))]);
5117
+ _optionalChain([onError, 'optionalCall', _120 => _120(error instanceof Error ? error : new Error("Unknown error"))]);
4805
5118
  } finally {
4806
5119
  setIsLoading(false);
4807
5120
  }
@@ -4847,7 +5160,7 @@ ${planningInstruction}` : planningInstruction;
4847
5160
  const error = err instanceof Error ? err : new Error("Failed to generate plan");
4848
5161
  setCommandError(error);
4849
5162
  setCommandState("error");
4850
- _optionalChain([onError, 'optionalCall', _105 => _105(error)]);
5163
+ _optionalChain([onError, 'optionalCall', _121 => _121(error)]);
4851
5164
  }
4852
5165
  }
4853
5166
  return;
@@ -4880,12 +5193,12 @@ ${planningInstruction}` : planningInstruction;
4880
5193
  setCommandResult(result);
4881
5194
  setCommandState("success");
4882
5195
  setProgress(100);
4883
- _optionalChain([onComplete, 'optionalCall', _106 => _106(result)]);
5196
+ _optionalChain([onComplete, 'optionalCall', _122 => _122(result)]);
4884
5197
  },
4885
5198
  (error) => {
4886
5199
  setCommandError(error);
4887
5200
  setCommandState("error");
4888
- _optionalChain([onError, 'optionalCall', _107 => _107(error)]);
5201
+ _optionalChain([onError, 'optionalCall', _123 => _123(error)]);
4889
5202
  }
4890
5203
  );
4891
5204
  } else {
@@ -4898,7 +5211,7 @@ ${planningInstruction}` : planningInstruction;
4898
5211
  setCommandResult(result);
4899
5212
  setCommandState("success");
4900
5213
  setProgress(100);
4901
- _optionalChain([onComplete, 'optionalCall', _108 => _108(result)]);
5214
+ _optionalChain([onComplete, 'optionalCall', _124 => _124(result)]);
4902
5215
  }
4903
5216
  } else {
4904
5217
  const commandInstruction = `CRITICAL COMMAND MODE: Maximum 10 words per response. Execute the command immediately. Make reasonable assumptions based on context. Use sensible defaults for missing details. DO NOT ask questions unless something is truly impossible without user input (e.g., missing required password). State what you're doing or the result. Examples: "Analyzing customer data from last quarter..." or "Created 5 new database entries successfully" or "Search complete: found 12 matching results". NO greetings, NO filler words, NO clarification requests. Action/result only.`;
@@ -4928,16 +5241,16 @@ ${commandInstruction}` : commandInstruction;
4928
5241
  const displayName = chunk.tool_display_name || chunk.tool_name;
4929
5242
  lastToolName = chunk.tool_name;
4930
5243
  setCurrentToolName(displayName);
4931
- _optionalChain([onToolCall, 'optionalCall', _109 => _109(chunk.tool_name, chunk.tool_id || "")]);
5244
+ _optionalChain([onToolCall, 'optionalCall', _125 => _125(chunk.tool_name, chunk.tool_id || "")]);
4932
5245
  accumulatedContent = "";
4933
5246
  setStreamedContent("");
4934
5247
  } else if (chunk.type === "tool_result") {
4935
- _optionalChain([onToolResult, 'optionalCall', _110 => _110(lastToolName, chunk.content)]);
5248
+ _optionalChain([onToolResult, 'optionalCall', _126 => _126(lastToolName, chunk.content)]);
4936
5249
  setCurrentToolName(null);
4937
5250
  } else if (chunk.type === "thread_id" && chunk.thread_id) {
4938
5251
  if (!currentThreadId) {
4939
5252
  setCurrentThreadId(chunk.thread_id);
4940
- _optionalChain([onThreadChange, 'optionalCall', _111 => _111(chunk.thread_id)]);
5253
+ _optionalChain([onThreadChange, 'optionalCall', _127 => _127(chunk.thread_id)]);
4941
5254
  }
4942
5255
  } else if (chunk.type === "request_id" && chunk.request_id) {
4943
5256
  setCurrentRequestId(chunk.request_id);
@@ -4953,13 +5266,13 @@ ${commandInstruction}` : commandInstruction;
4953
5266
  setCommandState("success");
4954
5267
  setProgress(100);
4955
5268
  setCurrentRequestId(null);
4956
- _optionalChain([onComplete, 'optionalCall', _112 => _112(result)]);
5269
+ _optionalChain([onComplete, 'optionalCall', _128 => _128(result)]);
4957
5270
  },
4958
5271
  (error) => {
4959
5272
  setCommandError(error);
4960
5273
  setCommandState("error");
4961
5274
  setCurrentRequestId(null);
4962
- _optionalChain([onError, 'optionalCall', _113 => _113(error)]);
5275
+ _optionalChain([onError, 'optionalCall', _129 => _129(error)]);
4963
5276
  }
4964
5277
  );
4965
5278
  } else {
@@ -4979,14 +5292,14 @@ ${commandInstruction}` : commandInstruction;
4979
5292
  setCommandResult(result);
4980
5293
  setCommandState("success");
4981
5294
  setProgress(100);
4982
- _optionalChain([onComplete, 'optionalCall', _114 => _114(result)]);
5295
+ _optionalChain([onComplete, 'optionalCall', _130 => _130(result)]);
4983
5296
  }
4984
5297
  }
4985
5298
  } catch (err) {
4986
5299
  const error = err instanceof Error ? err : new Error("Unknown error");
4987
5300
  setCommandError(error);
4988
5301
  setCommandState("error");
4989
- _optionalChain([onError, 'optionalCall', _115 => _115(error)]);
5302
+ _optionalChain([onError, 'optionalCall', _131 => _131(error)]);
4990
5303
  }
4991
5304
  };
4992
5305
  const resetCommand = () => {
@@ -5040,8 +5353,8 @@ ${planToExecute}`;
5040
5353
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "apteva-chat-title", children: headerTitle }),
5041
5354
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: cn(
5042
5355
  "apteva-chat-status",
5043
- isLoading ? chatToolName ? "apteva-chat-status-tool" : "apteva-chat-status-thinking" : "apteva-chat-status-ready"
5044
- ), children: isLoading ? chatToolName ? `Using ${chatToolName}...` : "Thinking..." : "Ready" })
5356
+ voice.state === "active" ? "apteva-chat-status-voice" : voice.state === "connecting" ? "apteva-chat-status-thinking" : isLoading ? chatToolName ? "apteva-chat-status-tool" : "apteva-chat-status-thinking" : "apteva-chat-status-ready"
5357
+ ), children: voice.state === "active" ? "Voice active" : voice.state === "connecting" ? "Connecting voice..." : isLoading ? chatToolName ? `Using ${chatToolName}...` : "Thinking..." : "Ready" })
5045
5358
  ] })
5046
5359
  ] }) }),
5047
5360
  mode === "chat" && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
@@ -5074,7 +5387,13 @@ ${planToExecute}`;
5074
5387
  onStop: handleStop,
5075
5388
  onFileUpload,
5076
5389
  onSwitchMode: showModeToggle ? () => handleModeChange("command") : void 0,
5077
- speechToText
5390
+ speechToText,
5391
+ enableVoice,
5392
+ voiceState: voice.state,
5393
+ voicePartialTranscript: voice.partialTranscript,
5394
+ voiceDuration: voice.duration,
5395
+ onVoiceStart: voice.start,
5396
+ onVoiceStop: voice.stop
5078
5397
  }
5079
5398
  )
5080
5399
  ] }),
@@ -5086,8 +5405,8 @@ ${planToExecute}`;
5086
5405
  executeCommand(text, files);
5087
5406
  },
5088
5407
  state: commandState,
5089
- response: _optionalChain([commandResult, 'optionalAccess', _116 => _116.data, 'optionalAccess', _117 => _117.summary]) || _optionalChain([commandResult, 'optionalAccess', _118 => _118.message]),
5090
- error: _optionalChain([commandError, 'optionalAccess', _119 => _119.message]),
5408
+ response: _optionalChain([commandResult, 'optionalAccess', _132 => _132.data, 'optionalAccess', _133 => _133.summary]) || _optionalChain([commandResult, 'optionalAccess', _134 => _134.message]),
5409
+ error: _optionalChain([commandError, 'optionalAccess', _135 => _135.message]),
5091
5410
  plan,
5092
5411
  streamedContent,
5093
5412
  toolName: currentToolName,
@@ -5255,13 +5574,13 @@ ${planningInstruction}` : planningInstruction;
5255
5574
  const error2 = err instanceof Error ? err : new Error("Failed to generate plan");
5256
5575
  setError(error2);
5257
5576
  setState("error");
5258
- _optionalChain([onError, 'optionalCall', _120 => _120(error2)]);
5577
+ _optionalChain([onError, 'optionalCall', _136 => _136(error2)]);
5259
5578
  });
5260
5579
  } catch (err) {
5261
5580
  const error2 = err instanceof Error ? err : new Error("Failed to generate plan");
5262
5581
  setError(error2);
5263
5582
  setState("error");
5264
- _optionalChain([onError, 'optionalCall', _121 => _121(error2)]);
5583
+ _optionalChain([onError, 'optionalCall', _137 => _137(error2)]);
5265
5584
  }
5266
5585
  }
5267
5586
  return;
@@ -5272,7 +5591,7 @@ ${planningInstruction}` : planningInstruction;
5272
5591
  setStreamedContent("");
5273
5592
  setCommand("");
5274
5593
  setUploadedFiles([]);
5275
- _optionalChain([onStart, 'optionalCall', _122 => _122()]);
5594
+ _optionalChain([onStart, 'optionalCall', _138 => _138()]);
5276
5595
  try {
5277
5596
  if (useMock) {
5278
5597
  if (enableStreaming) {
@@ -5283,16 +5602,16 @@ ${planningInstruction}` : planningInstruction;
5283
5602
  if (chunk.type === "token" && chunk.content) {
5284
5603
  accumulatedContent += chunk.content;
5285
5604
  setStreamedContent(accumulatedContent);
5286
- _optionalChain([onChunk, 'optionalCall', _123 => _123(chunk.content)]);
5605
+ _optionalChain([onChunk, 'optionalCall', _139 => _139(chunk.content)]);
5287
5606
  const estimatedProgress = Math.min(Math.round(accumulatedContent.length / 10), 90);
5288
5607
  setProgress(estimatedProgress);
5289
- _optionalChain([onProgress, 'optionalCall', _124 => _124(estimatedProgress)]);
5608
+ _optionalChain([onProgress, 'optionalCall', _140 => _140(estimatedProgress)]);
5290
5609
  } else if (chunk.type === "widget" && chunk.widget) {
5291
5610
  const widget = chunk.widget;
5292
5611
  setResult((prev) => ({
5293
5612
  success: true,
5294
- data: _optionalChain([prev, 'optionalAccess', _125 => _125.data]) || {},
5295
- widgets: [..._optionalChain([prev, 'optionalAccess', _126 => _126.widgets]) || [], widget],
5613
+ data: _optionalChain([prev, 'optionalAccess', _141 => _141.data]) || {},
5614
+ widgets: [..._optionalChain([prev, 'optionalAccess', _142 => _142.widgets]) || [], widget],
5296
5615
  message: accumulatedContent || "Command executed successfully"
5297
5616
  }));
5298
5617
  }
@@ -5312,19 +5631,19 @@ ${planningInstruction}` : planningInstruction;
5312
5631
  setResult(result2);
5313
5632
  setState("success");
5314
5633
  setProgress(100);
5315
- _optionalChain([onComplete, 'optionalCall', _127 => _127(result2)]);
5634
+ _optionalChain([onComplete, 'optionalCall', _143 => _143(result2)]);
5316
5635
  },
5317
5636
  (error2) => {
5318
5637
  setError(error2);
5319
5638
  setState("error");
5320
- _optionalChain([onError, 'optionalCall', _128 => _128(error2)]);
5639
+ _optionalChain([onError, 'optionalCall', _144 => _144(error2)]);
5321
5640
  }
5322
5641
  );
5323
5642
  } else {
5324
5643
  const progressInterval = setInterval(() => {
5325
5644
  setProgress((prev) => {
5326
5645
  const next = Math.min(prev + 10, 90);
5327
- _optionalChain([onProgress, 'optionalCall', _129 => _129(next)]);
5646
+ _optionalChain([onProgress, 'optionalCall', _145 => _145(next)]);
5328
5647
  return next;
5329
5648
  });
5330
5649
  }, 200);
@@ -5348,7 +5667,7 @@ ${planningInstruction}` : planningInstruction;
5348
5667
  setResult(result2);
5349
5668
  setState("success");
5350
5669
  setProgress(100);
5351
- _optionalChain([onComplete, 'optionalCall', _130 => _130(result2)]);
5670
+ _optionalChain([onComplete, 'optionalCall', _146 => _146(result2)]);
5352
5671
  }
5353
5672
  } else {
5354
5673
  if (enableStreaming) {
@@ -5394,16 +5713,16 @@ ${commandInstruction}` : commandInstruction;
5394
5713
  if (chunk.type === "token" && chunk.content) {
5395
5714
  accumulatedContent += chunk.content;
5396
5715
  setStreamedContent(accumulatedContent);
5397
- _optionalChain([onChunk, 'optionalCall', _131 => _131(chunk.content)]);
5716
+ _optionalChain([onChunk, 'optionalCall', _147 => _147(chunk.content)]);
5398
5717
  const estimatedProgress = Math.min(Math.round(accumulatedContent.length / 10), 90);
5399
5718
  setProgress(estimatedProgress);
5400
- _optionalChain([onProgress, 'optionalCall', _132 => _132(estimatedProgress)]);
5719
+ _optionalChain([onProgress, 'optionalCall', _148 => _148(estimatedProgress)]);
5401
5720
  } else if (chunk.type === "widget" && chunk.widget) {
5402
5721
  const widget = chunk.widget;
5403
5722
  setResult((prev) => ({
5404
5723
  success: true,
5405
- data: _optionalChain([prev, 'optionalAccess', _133 => _133.data]) || {},
5406
- widgets: [..._optionalChain([prev, 'optionalAccess', _134 => _134.widgets]) || [], widget],
5724
+ data: _optionalChain([prev, 'optionalAccess', _149 => _149.data]) || {},
5725
+ widgets: [..._optionalChain([prev, 'optionalAccess', _150 => _150.widgets]) || [], widget],
5407
5726
  message: accumulatedContent || "Command executed successfully"
5408
5727
  }));
5409
5728
  }
@@ -5423,20 +5742,20 @@ ${commandInstruction}` : commandInstruction;
5423
5742
  setResult(result2);
5424
5743
  setState("success");
5425
5744
  setProgress(100);
5426
- _optionalChain([onComplete, 'optionalCall', _135 => _135(result2)]);
5745
+ _optionalChain([onComplete, 'optionalCall', _151 => _151(result2)]);
5427
5746
  },
5428
5747
  (error2) => {
5429
5748
  const err = error2 instanceof Error ? error2 : new Error("Unknown error");
5430
5749
  setError(err);
5431
5750
  setState("error");
5432
- _optionalChain([onError, 'optionalCall', _136 => _136(err)]);
5751
+ _optionalChain([onError, 'optionalCall', _152 => _152(err)]);
5433
5752
  }
5434
5753
  );
5435
5754
  } else {
5436
5755
  const progressInterval = setInterval(() => {
5437
5756
  setProgress((prev) => {
5438
5757
  const next = Math.min(prev + 10, 90);
5439
- _optionalChain([onProgress, 'optionalCall', _137 => _137(next)]);
5758
+ _optionalChain([onProgress, 'optionalCall', _153 => _153(next)]);
5440
5759
  return next;
5441
5760
  });
5442
5761
  }, 200);
@@ -5492,14 +5811,14 @@ ${commandInstruction}` : commandInstruction;
5492
5811
  setResult(result2);
5493
5812
  setState("success");
5494
5813
  setProgress(100);
5495
- _optionalChain([onComplete, 'optionalCall', _138 => _138(result2)]);
5814
+ _optionalChain([onComplete, 'optionalCall', _154 => _154(result2)]);
5496
5815
  }
5497
5816
  }
5498
5817
  } catch (err) {
5499
5818
  const error2 = err instanceof Error ? err : new Error("Unknown error");
5500
5819
  setError(error2);
5501
5820
  setState("error");
5502
- _optionalChain([onError, 'optionalCall', _139 => _139(error2)]);
5821
+ _optionalChain([onError, 'optionalCall', _155 => _155(error2)]);
5503
5822
  }
5504
5823
  };
5505
5824
  const resetCommand = () => {
@@ -5532,14 +5851,14 @@ ${planToExecute}`;
5532
5851
  };
5533
5852
  const handleFileSelect = async (e) => {
5534
5853
  if (e.target.files && e.target.files.length > 0) {
5535
- _optionalChain([onFileUpload, 'optionalCall', _140 => _140(e.target.files)]);
5854
+ _optionalChain([onFileUpload, 'optionalCall', _156 => _156(e.target.files)]);
5536
5855
  const files = [];
5537
5856
  for (let i = 0; i < e.target.files.length; i++) {
5538
5857
  const file = e.target.files[i];
5539
5858
  const reader = new FileReader();
5540
5859
  await new Promise((resolve) => {
5541
5860
  reader.onload = (event) => {
5542
- if (_optionalChain([event, 'access', _141 => _141.target, 'optionalAccess', _142 => _142.result])) {
5861
+ if (_optionalChain([event, 'access', _157 => _157.target, 'optionalAccess', _158 => _158.result])) {
5543
5862
  const fullDataUrl = event.target.result;
5544
5863
  const base64Data = fullDataUrl.split(",")[1];
5545
5864
  if (file.type.startsWith("image/")) {
@@ -5633,7 +5952,7 @@ ${planToExecute}`;
5633
5952
  enableFileUpload && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5634
5953
  "button",
5635
5954
  {
5636
- onClick: () => _optionalChain([fileInputRef, 'access', _143 => _143.current, 'optionalAccess', _144 => _144.click, 'call', _145 => _145()]),
5955
+ onClick: () => _optionalChain([fileInputRef, 'access', _159 => _159.current, 'optionalAccess', _160 => _160.click, 'call', _161 => _161()]),
5637
5956
  className: "w-8 h-8 rounded-lg flex items-center justify-center transition-all flex-shrink-0 !text-neutral-500 dark:!text-neutral-500 hover:bg-neutral-100 dark:hover:bg-neutral-800",
5638
5957
  title: "Attach file",
5639
5958
  children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M8.4 2.8L4.4 6.8C3.736 7.464 3.736 8.536 4.4 9.2C5.064 9.864 6.136 9.864 6.8 9.2L11.6 4.4C12.704 3.296 12.704 1.504 11.6 0.4C10.496 -0.704 8.704 -0.704 7.6 0.4L2.8 5.2C1.256 6.744 1.256 9.256 2.8 10.8C4.344 12.344 6.856 12.344 8.4 10.8L12.4 6.8", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round", transform: "translate(1.6, 2.4)" }) })
@@ -5852,7 +6171,7 @@ ${planToExecute}`;
5852
6171
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { className: "w-5 h-5 text-red-600 mt-0.5 flex-shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }),
5853
6172
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { children: [
5854
6173
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { className: "text-sm font-semibold text-red-800 dark:text-red-400", children: "Error" }),
5855
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-red-700 dark:text-red-300 text-sm mt-1", children: _optionalChain([error, 'optionalAccess', _146 => _146.message]) })
6174
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-red-700 dark:text-red-300 text-sm mt-1", children: _optionalChain([error, 'optionalAccess', _162 => _162.message]) })
5856
6175
  ] })
5857
6176
  ] }) }),
5858
6177
  allowInput && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
@@ -5880,7 +6199,7 @@ ${planToExecute}`;
5880
6199
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-green-700 dark:text-green-300 text-sm", children: "Command executed successfully" })
5881
6200
  ] })
5882
6201
  ] }),
5883
- _optionalChain([result, 'access', _147 => _147.data, 'optionalAccess', _148 => _148.summary]) && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "text-neutral-700 dark:text-neutral-300 text-sm leading-relaxed whitespace-pre-line", children: result.data.summary }),
6202
+ _optionalChain([result, 'access', _163 => _163.data, 'optionalAccess', _164 => _164.summary]) && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "text-neutral-700 dark:text-neutral-300 text-sm leading-relaxed whitespace-pre-line", children: result.data.summary }),
5884
6203
  result.widgets && result.widgets.length > 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "space-y-3", children: result.widgets.map((widget) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5885
6204
  WidgetRenderer,
5886
6205
  {
@@ -5931,7 +6250,7 @@ ${planToExecute}`;
5931
6250
  enableFileUpload && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5932
6251
  "button",
5933
6252
  {
5934
- onClick: () => _optionalChain([fileInputRef, 'access', _149 => _149.current, 'optionalAccess', _150 => _150.click, 'call', _151 => _151()]),
6253
+ onClick: () => _optionalChain([fileInputRef, 'access', _165 => _165.current, 'optionalAccess', _166 => _166.click, 'call', _167 => _167()]),
5935
6254
  className: "w-8 h-8 rounded-lg flex items-center justify-center transition-all flex-shrink-0 !text-neutral-500 dark:!text-neutral-500 hover:bg-neutral-100 dark:hover:bg-neutral-800",
5936
6255
  title: "Attach file",
5937
6256
  children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M8.4 2.8L4.4 6.8C3.736 7.464 3.736 8.536 4.4 9.2C5.064 9.864 6.136 9.864 6.8 9.2L11.6 4.4C12.704 3.296 12.704 1.504 11.6 0.4C10.496 -0.704 8.704 -0.704 7.6 0.4L2.8 5.2C1.256 6.744 1.256 9.256 2.8 10.8C4.344 12.344 6.856 12.344 8.4 10.8L12.4 6.8", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round", transform: "translate(1.6, 2.4)" }) })
@@ -6117,25 +6436,25 @@ function Prompt({
6117
6436
  const newValue = e.target.value;
6118
6437
  if (!maxLength || newValue.length <= maxLength) {
6119
6438
  setValue(newValue);
6120
- _optionalChain([onChange, 'optionalCall', _152 => _152(newValue)]);
6439
+ _optionalChain([onChange, 'optionalCall', _168 => _168(newValue)]);
6121
6440
  }
6122
6441
  };
6123
6442
  const handleSubmit = async () => {
6124
6443
  if (value.length < minLength) return;
6125
- _optionalChain([onSubmit, 'optionalCall', _153 => _153(value)]);
6444
+ _optionalChain([onSubmit, 'optionalCall', _169 => _169(value)]);
6126
6445
  setIsLoading(true);
6127
6446
  try {
6128
6447
  if (useMock) {
6129
6448
  await new Promise((resolve) => setTimeout(resolve, 1500));
6130
6449
  const mockResult = `Enhanced version: ${value} [AI-generated content]`;
6131
- _optionalChain([onResult, 'optionalCall', _154 => _154(mockResult)]);
6450
+ _optionalChain([onResult, 'optionalCall', _170 => _170(mockResult)]);
6132
6451
  setValue("");
6133
6452
  } else {
6134
6453
  const response = await aptevaClient.chat({
6135
6454
  agent_id: agentId,
6136
6455
  message: value
6137
6456
  });
6138
- _optionalChain([onResult, 'optionalCall', _155 => _155(response.message)]);
6457
+ _optionalChain([onResult, 'optionalCall', _171 => _171(response.message)]);
6139
6458
  setValue("");
6140
6459
  }
6141
6460
  } catch (error) {
@@ -6230,7 +6549,7 @@ function Stream({
6230
6549
  }, [autoStart]);
6231
6550
  const startStreaming = async () => {
6232
6551
  setIsStreaming(true);
6233
- _optionalChain([onStart, 'optionalCall', _156 => _156()]);
6552
+ _optionalChain([onStart, 'optionalCall', _172 => _172()]);
6234
6553
  try {
6235
6554
  if (useMock) {
6236
6555
  const mockText = "This is a simulated streaming response from the AI agent. In a real implementation, this would stream data from your backend API. The text appears word by word to simulate the streaming effect. You can customize the typing speed and styling based on your needs.";
@@ -6238,13 +6557,13 @@ function Stream({
6238
6557
  mockText,
6239
6558
  (chunk) => {
6240
6559
  setText((prev) => prev + chunk);
6241
- _optionalChain([onChunk, 'optionalCall', _157 => _157(chunk)]);
6560
+ _optionalChain([onChunk, 'optionalCall', _173 => _173(chunk)]);
6242
6561
  },
6243
6562
  typingSpeed
6244
6563
  );
6245
6564
  setIsComplete(true);
6246
6565
  setIsStreaming(false);
6247
- _optionalChain([onComplete, 'optionalCall', _158 => _158(text + mockText)]);
6566
+ _optionalChain([onComplete, 'optionalCall', _174 => _174(text + mockText)]);
6248
6567
  } else {
6249
6568
  let accumulatedText = "";
6250
6569
  await aptevaClient.chatStream(
@@ -6257,24 +6576,24 @@ function Stream({
6257
6576
  if (chunk.type === "token" && chunk.content) {
6258
6577
  accumulatedText += chunk.content;
6259
6578
  setText(accumulatedText);
6260
- _optionalChain([onChunk, 'optionalCall', _159 => _159(chunk.content)]);
6579
+ _optionalChain([onChunk, 'optionalCall', _175 => _175(chunk.content)]);
6261
6580
  }
6262
6581
  },
6263
6582
  () => {
6264
6583
  setIsComplete(true);
6265
6584
  setIsStreaming(false);
6266
- _optionalChain([onComplete, 'optionalCall', _160 => _160(accumulatedText)]);
6585
+ _optionalChain([onComplete, 'optionalCall', _176 => _176(accumulatedText)]);
6267
6586
  },
6268
6587
  (error) => {
6269
6588
  const err = error instanceof Error ? error : new Error("Streaming error");
6270
- _optionalChain([onError, 'optionalCall', _161 => _161(err)]);
6589
+ _optionalChain([onError, 'optionalCall', _177 => _177(err)]);
6271
6590
  setIsStreaming(false);
6272
6591
  }
6273
6592
  );
6274
6593
  }
6275
6594
  } catch (error) {
6276
6595
  const err = error instanceof Error ? error : new Error("Streaming error");
6277
- _optionalChain([onError, 'optionalCall', _162 => _162(err)]);
6596
+ _optionalChain([onError, 'optionalCall', _178 => _178(err)]);
6278
6597
  setIsStreaming(false);
6279
6598
  }
6280
6599
  };
@@ -6366,7 +6685,7 @@ function ThreadList({
6366
6685
  }) {
6367
6686
  const [searchQuery, setSearchQuery] = _react.useState.call(void 0, "");
6368
6687
  const filteredThreads = threads.filter(
6369
- (thread) => thread.title.toLowerCase().includes(searchQuery.toLowerCase()) || _optionalChain([thread, 'access', _163 => _163.preview, 'optionalAccess', _164 => _164.toLowerCase, 'call', _165 => _165(), 'access', _166 => _166.includes, 'call', _167 => _167(searchQuery.toLowerCase())])
6688
+ (thread) => thread.title.toLowerCase().includes(searchQuery.toLowerCase()) || _optionalChain([thread, 'access', _179 => _179.preview, 'optionalAccess', _180 => _180.toLowerCase, 'call', _181 => _181(), 'access', _182 => _182.includes, 'call', _183 => _183(searchQuery.toLowerCase())])
6370
6689
  );
6371
6690
  const groupedThreads = groupBy === "date" ? groupThreadsByDate(filteredThreads) : { All: filteredThreads };
6372
6691
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col h-full", children: [
@@ -6388,8 +6707,8 @@ function ThreadList({
6388
6707
  {
6389
6708
  thread,
6390
6709
  isActive: thread.id === currentThreadId,
6391
- onSelect: () => _optionalChain([onThreadSelect, 'optionalCall', _168 => _168(thread.id)]),
6392
- onDelete: () => _optionalChain([onThreadDelete, 'optionalCall', _169 => _169(thread.id)])
6710
+ onSelect: () => _optionalChain([onThreadSelect, 'optionalCall', _184 => _184(thread.id)]),
6711
+ onDelete: () => _optionalChain([onThreadDelete, 'optionalCall', _185 => _185(thread.id)])
6393
6712
  },
6394
6713
  thread.id
6395
6714
  ))
@@ -6451,7 +6770,7 @@ function Threads({
6451
6770
  threads.slice(0, 5).map((thread) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6452
6771
  "button",
6453
6772
  {
6454
- onClick: () => _optionalChain([onThreadSelect, 'optionalCall', _170 => _170(thread.id)]),
6773
+ onClick: () => _optionalChain([onThreadSelect, 'optionalCall', _186 => _186(thread.id)]),
6455
6774
  className: cn(
6456
6775
  "px-4 py-2 whitespace-nowrap font-medium transition-colors",
6457
6776
  thread.id === currentThreadId ? "border-b-2 border-apteva-500 text-apteva-500" : "text-neutral-600 hover:text-neutral-900"
@@ -6636,7 +6955,7 @@ function TabsLayout({ node, renderNode }) {
6636
6955
  var STRUCTURAL_KEYS = /* @__PURE__ */ new Set(["type", "id", "layout", "props", "children", "actions", "metadata", "isStreaming"]);
6637
6956
  function normalizeNode(n) {
6638
6957
  let node = { ...n };
6639
- if (node.type === "widget" && _optionalChain([node, 'access', _171 => _171.props, 'optionalAccess', _172 => _172.widget])) {
6958
+ if (node.type === "widget" && _optionalChain([node, 'access', _187 => _187.props, 'optionalAccess', _188 => _188.widget])) {
6640
6959
  node.type = node.props.widget;
6641
6960
  const { widget: _, ...rest } = node.props;
6642
6961
  node.props = rest;
@@ -6774,10 +7093,10 @@ function AutoInterface({
6774
7093
  ].filter(Boolean).join("\n\n");
6775
7094
  const updateInterface = _react.useCallback.call(void 0, (newSpec) => {
6776
7095
  setInterfaceSpec(newSpec);
6777
- _optionalChain([onInterfaceChange, 'optionalCall', _173 => _173(newSpec)]);
7096
+ _optionalChain([onInterfaceChange, 'optionalCall', _189 => _189(newSpec)]);
6778
7097
  }, [onInterfaceChange]);
6779
7098
  const handleAction = _react.useCallback.call(void 0, (action) => {
6780
- _optionalChain([onAction, 'optionalCall', _174 => _174(action)]);
7099
+ _optionalChain([onAction, 'optionalCall', _190 => _190(action)]);
6781
7100
  if (chatRef.current) {
6782
7101
  chatRef.current.sendMessage(
6783
7102
  `[Action: ${action.type} on widget ${action.widgetId || "unknown"}. Payload: ${JSON.stringify(action.payload)}]`
@@ -6785,7 +7104,7 @@ function AutoInterface({
6785
7104
  }
6786
7105
  }, [onAction]);
6787
7106
  const handleMessageComplete = _react.useCallback.call(void 0, (result) => {
6788
- if (!_optionalChain([result, 'optionalAccess', _175 => _175.data])) return;
7107
+ if (!_optionalChain([result, 'optionalAccess', _191 => _191.data])) return;
6789
7108
  const text = typeof result.data === "string" ? result.data : result.data.message || "";
6790
7109
  console.log("[AutoInterface] Chat message complete, text (" + text.length + " chars):", text.substring(0, 300));
6791
7110
  const parsed = parseInterfaceFromText(text);
@@ -6825,7 +7144,7 @@ function AutoInterface({
6825
7144
  }).catch((err) => {
6826
7145
  if (cancelled) return;
6827
7146
  console.error("[AutoInterface] Initial generation failed:", err);
6828
- _optionalChain([onError, 'optionalCall', _176 => _176(err instanceof Error ? err : new Error(String(err)))]);
7147
+ _optionalChain([onError, 'optionalCall', _192 => _192(err instanceof Error ? err : new Error(String(err)))]);
6829
7148
  setIsGenerating(false);
6830
7149
  });
6831
7150
  return () => {
@@ -6991,7 +7310,7 @@ function useInterfaceAI({
6991
7310
  }
6992
7311
  const sendMessage = _react.useCallback.call(void 0, async (message) => {
6993
7312
  accumulatedTextRef.current = "";
6994
- _optionalChain([onStreamStart, 'optionalCall', _177 => _177()]);
7313
+ _optionalChain([onStreamStart, 'optionalCall', _193 => _193()]);
6995
7314
  const systemPrompt = [
6996
7315
  generateInterfaceContext(),
6997
7316
  context || ""
@@ -7014,27 +7333,27 @@ function useInterfaceAI({
7014
7333
  accumulatedTextRef.current += chunk.content || "";
7015
7334
  const parsed = parseInterfaceFromText(accumulatedTextRef.current);
7016
7335
  if (parsed) {
7017
- _optionalChain([onInterface, 'optionalCall', _178 => _178(parsed)]);
7336
+ _optionalChain([onInterface, 'optionalCall', _194 => _194(parsed)]);
7018
7337
  }
7019
7338
  const updates = parseUpdatesFromText(accumulatedTextRef.current);
7020
7339
  if (updates.length > 0) {
7021
- _optionalChain([onUpdates, 'optionalCall', _179 => _179(updates)]);
7340
+ _optionalChain([onUpdates, 'optionalCall', _195 => _195(updates)]);
7022
7341
  }
7023
7342
  }
7024
7343
  },
7025
7344
  // onComplete
7026
7345
  () => {
7027
- _optionalChain([onStreamEnd, 'optionalCall', _180 => _180()]);
7346
+ _optionalChain([onStreamEnd, 'optionalCall', _196 => _196()]);
7028
7347
  },
7029
7348
  // onError
7030
7349
  (error) => {
7031
- _optionalChain([onError, 'optionalCall', _181 => _181(error)]);
7032
- _optionalChain([onStreamEnd, 'optionalCall', _182 => _182()]);
7350
+ _optionalChain([onError, 'optionalCall', _197 => _197(error)]);
7351
+ _optionalChain([onStreamEnd, 'optionalCall', _198 => _198()]);
7033
7352
  }
7034
7353
  );
7035
7354
  } catch (error) {
7036
- _optionalChain([onError, 'optionalCall', _183 => _183(error instanceof Error ? error : new Error("Unknown error"))]);
7037
- _optionalChain([onStreamEnd, 'optionalCall', _184 => _184()]);
7355
+ _optionalChain([onError, 'optionalCall', _199 => _199(error instanceof Error ? error : new Error("Unknown error"))]);
7356
+ _optionalChain([onStreamEnd, 'optionalCall', _200 => _200()]);
7038
7357
  }
7039
7358
  }, [agentId, context, onInterface, onUpdates, onError, onStreamStart, onStreamEnd]);
7040
7359
  return {