@paymanai/payman-ask-sdk 4.0.4 → 4.0.6

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.mjs CHANGED
@@ -221,6 +221,43 @@ function initSentryIfNeeded(dsn) {
221
221
  }
222
222
  });
223
223
  }
224
+
225
+ // src/utils/feedbackClient.ts
226
+ var NEGATIVE_FEEDBACK_REASONS = [
227
+ { value: "NOT_FACTUALLY_CORRECT", label: "Not factually correct" },
228
+ { value: "INCOMPLETE_RESPONSE", label: "Incomplete response" },
229
+ { value: "DID_NOT_FOLLOW_REQUEST", label: "Did not follow my request" },
230
+ { value: "OVERACTIVE_REFUSAL", label: "Refused unnecessarily" },
231
+ { value: "ISSUE_WITH_THOUGHT_PROCESS", label: "Issue with reasoning" },
232
+ { value: "REPORT_CONTENT", label: "Report content" },
233
+ { value: "OTHER", label: "Other" }
234
+ ];
235
+ async function submitAskFeedback({
236
+ baseUrl,
237
+ headers,
238
+ executionId,
239
+ feedback,
240
+ details,
241
+ signal
242
+ }) {
243
+ const base = baseUrl.replace(/\/+$/, "");
244
+ const resp = await fetch(
245
+ `${base}/api/ask/executions/${encodeURIComponent(executionId)}/feedback`,
246
+ {
247
+ method: "POST",
248
+ headers: {
249
+ "Content-Type": "application/json",
250
+ Accept: "application/json",
251
+ ...headers ?? {}
252
+ },
253
+ body: JSON.stringify(details ? { feedback, details } : { feedback }),
254
+ signal
255
+ }
256
+ );
257
+ if (!resp.ok) {
258
+ throw new Error(`Feedback failed: ${resp.status} ${resp.statusText}`);
259
+ }
260
+ }
224
261
  function ImageLightbox({
225
262
  src,
226
263
  alt = "",
@@ -1683,6 +1720,143 @@ function ThinkingBlockV2({
1683
1720
  ) }) })
1684
1721
  ] });
1685
1722
  }
1723
+ var MAX_DETAILS_CHARS = 2e3;
1724
+ function FeedbackReasonModal({
1725
+ open,
1726
+ onClose,
1727
+ onSubmit
1728
+ }) {
1729
+ const [reason, setReason] = useState(
1730
+ NEGATIVE_FEEDBACK_REASONS[0].value
1731
+ );
1732
+ const [details, setDetails] = useState("");
1733
+ const [submitting, setSubmitting] = useState(false);
1734
+ const [error, setError] = useState(null);
1735
+ useEffect(() => {
1736
+ if (open) {
1737
+ setReason(NEGATIVE_FEEDBACK_REASONS[0].value);
1738
+ setDetails("");
1739
+ setError(null);
1740
+ setSubmitting(false);
1741
+ }
1742
+ }, [open]);
1743
+ const handleKeyDown = useCallback(
1744
+ (event) => {
1745
+ if (event.key === "Escape") onClose();
1746
+ },
1747
+ [onClose]
1748
+ );
1749
+ useEffect(() => {
1750
+ if (!open || typeof document === "undefined") return;
1751
+ document.addEventListener("keydown", handleKeyDown);
1752
+ const previousOverflow = document.body.style.overflow;
1753
+ document.body.style.overflow = "hidden";
1754
+ return () => {
1755
+ document.removeEventListener("keydown", handleKeyDown);
1756
+ document.body.style.overflow = previousOverflow;
1757
+ };
1758
+ }, [handleKeyDown, open]);
1759
+ const handleSubmit = async () => {
1760
+ setSubmitting(true);
1761
+ setError(null);
1762
+ try {
1763
+ await onSubmit(reason, details.trim() ? details.trim() : void 0);
1764
+ onClose();
1765
+ } catch (e) {
1766
+ setError(e instanceof Error ? e.message : "Could not send feedback");
1767
+ setSubmitting(false);
1768
+ }
1769
+ };
1770
+ return /* @__PURE__ */ jsx(AnimatePresence, { children: open ? /* @__PURE__ */ jsx(
1771
+ motion.div,
1772
+ {
1773
+ className: "payman-v2-feedback-modal-backdrop",
1774
+ initial: { opacity: 0 },
1775
+ animate: { opacity: 1 },
1776
+ exit: { opacity: 0 },
1777
+ transition: { duration: 0.18 },
1778
+ onClick: onClose,
1779
+ role: "presentation",
1780
+ children: /* @__PURE__ */ jsxs(
1781
+ motion.div,
1782
+ {
1783
+ initial: { opacity: 0, y: 12, scale: 0.98 },
1784
+ animate: { opacity: 1, y: 0, scale: 1 },
1785
+ exit: { opacity: 0, y: 8, scale: 0.98 },
1786
+ transition: { duration: 0.2, ease: [0.16, 1, 0.3, 1] },
1787
+ className: "payman-v2-feedback-modal-dialog",
1788
+ onClick: (event) => event.stopPropagation(),
1789
+ role: "dialog",
1790
+ "aria-modal": "true",
1791
+ "aria-labelledby": "payman-v2-feedback-title",
1792
+ children: [
1793
+ /* @__PURE__ */ jsx(
1794
+ "h2",
1795
+ {
1796
+ id: "payman-v2-feedback-title",
1797
+ className: "payman-v2-feedback-modal-title",
1798
+ children: "Tell us what went wrong"
1799
+ }
1800
+ ),
1801
+ /* @__PURE__ */ jsx(
1802
+ "label",
1803
+ {
1804
+ className: "payman-v2-feedback-modal-label",
1805
+ htmlFor: "payman-v2-feedback-reason",
1806
+ children: "What was the issue?"
1807
+ }
1808
+ ),
1809
+ /* @__PURE__ */ jsx(
1810
+ "select",
1811
+ {
1812
+ id: "payman-v2-feedback-reason",
1813
+ className: "payman-v2-feedback-modal-select",
1814
+ value: reason,
1815
+ onChange: (e) => setReason(e.target.value),
1816
+ disabled: submitting,
1817
+ children: NEGATIVE_FEEDBACK_REASONS.map((r) => /* @__PURE__ */ jsx("option", { value: r.value, children: r.label }, r.value))
1818
+ }
1819
+ ),
1820
+ /* @__PURE__ */ jsx(
1821
+ "textarea",
1822
+ {
1823
+ className: "payman-v2-feedback-modal-textarea",
1824
+ placeholder: "Add details (optional)",
1825
+ value: details,
1826
+ maxLength: MAX_DETAILS_CHARS,
1827
+ onChange: (e) => setDetails(e.target.value),
1828
+ disabled: submitting
1829
+ }
1830
+ ),
1831
+ error ? /* @__PURE__ */ jsx("p", { className: "payman-v2-feedback-modal-error", children: error }) : null,
1832
+ /* @__PURE__ */ jsxs("div", { className: "payman-v2-feedback-modal-actions", children: [
1833
+ /* @__PURE__ */ jsx(
1834
+ "button",
1835
+ {
1836
+ type: "button",
1837
+ onClick: onClose,
1838
+ disabled: submitting,
1839
+ className: "payman-v2-feedback-modal-btn payman-v2-feedback-modal-btn-secondary",
1840
+ children: "Cancel"
1841
+ }
1842
+ ),
1843
+ /* @__PURE__ */ jsx(
1844
+ "button",
1845
+ {
1846
+ type: "button",
1847
+ onClick: handleSubmit,
1848
+ disabled: submitting,
1849
+ className: "payman-v2-feedback-modal-btn payman-v2-feedback-modal-btn-primary",
1850
+ children: submitting ? "Sending\u2026" : "Submit"
1851
+ }
1852
+ )
1853
+ ] })
1854
+ ]
1855
+ }
1856
+ )
1857
+ }
1858
+ ) : null });
1859
+ }
1686
1860
  var RESPONSE_SPEED = {
1687
1861
  normal: [2, 4],
1688
1862
  fast: 1,
@@ -1765,12 +1939,26 @@ function AssistantMessageV2({
1765
1939
  message,
1766
1940
  onImageClick,
1767
1941
  onExecutionTraceClick,
1768
- onFeedback,
1942
+ onSubmitFeedback,
1769
1943
  actions,
1770
1944
  typingSpeed = 4
1771
1945
  }) {
1772
1946
  const [copied, setCopied] = useState(false);
1773
1947
  const [activeFeedback, setActiveFeedback] = useState(null);
1948
+ const [reasonModalOpen, setReasonModalOpen] = useState(false);
1949
+ const canSubmitFeedback = !!onSubmitFeedback && !!message.executionId;
1950
+ const handlePositiveFeedback = () => {
1951
+ if (!canSubmitFeedback || activeFeedback === "up") return;
1952
+ const previous = activeFeedback;
1953
+ setActiveFeedback("up");
1954
+ Promise.resolve(
1955
+ onSubmitFeedback?.({
1956
+ messageId: message.id,
1957
+ executionId: message.executionId,
1958
+ feedback: "POSITIVE"
1959
+ })
1960
+ ).catch(() => setActiveFeedback(previous));
1961
+ };
1774
1962
  const [toast, setToast] = useState(null);
1775
1963
  const copyResetTimerRef = useRef(null);
1776
1964
  const toastTimerRef = useRef(null);
@@ -2010,14 +2198,10 @@ function AssistantMessageV2({
2010
2198
  children: copied ? /* @__PURE__ */ jsx(Check, { style: { width: 16, height: 16 } }) : /* @__PURE__ */ jsx(Copy, { style: { width: 16, height: 16 } })
2011
2199
  }
2012
2200
  ) }),
2013
- showThumbsUp && /* @__PURE__ */ jsx(ActionTooltipV2, { label: "Good response", children: /* @__PURE__ */ jsx(
2201
+ showThumbsUp && canSubmitFeedback && /* @__PURE__ */ jsx(ActionTooltipV2, { label: "Good response", children: /* @__PURE__ */ jsx(
2014
2202
  "button",
2015
2203
  {
2016
- onClick: () => {
2017
- const next = activeFeedback === "up" ? null : "up";
2018
- setActiveFeedback(next);
2019
- if (next) onFeedback?.({ messageId: message.id, feedback: "up" });
2020
- },
2204
+ onClick: handlePositiveFeedback,
2021
2205
  className: cn(
2022
2206
  "payman-v2-assistant-msg-action-btn",
2023
2207
  activeFeedback === "up" && "payman-v2-assistant-msg-action-btn-active"
@@ -2026,14 +2210,10 @@ function AssistantMessageV2({
2026
2210
  children: /* @__PURE__ */ jsx(ThumbsUp, { style: { width: 15, height: 15 } })
2027
2211
  }
2028
2212
  ) }),
2029
- showThumbsDown && /* @__PURE__ */ jsx(ActionTooltipV2, { label: "Bad response", children: /* @__PURE__ */ jsx(
2213
+ showThumbsDown && canSubmitFeedback && /* @__PURE__ */ jsx(ActionTooltipV2, { label: "Bad response", children: /* @__PURE__ */ jsx(
2030
2214
  "button",
2031
2215
  {
2032
- onClick: () => {
2033
- const next = activeFeedback === "down" ? null : "down";
2034
- setActiveFeedback(next);
2035
- if (next) onFeedback?.({ messageId: message.id, feedback: "down" });
2036
- },
2216
+ onClick: () => setReasonModalOpen(true),
2037
2217
  className: cn(
2038
2218
  "payman-v2-assistant-msg-action-btn",
2039
2219
  activeFeedback === "down" && "payman-v2-assistant-msg-action-btn-active"
@@ -2053,7 +2233,23 @@ function AssistantMessageV2({
2053
2233
  ) }),
2054
2234
  totalElapsedLabel && /* @__PURE__ */ jsx("span", { className: "payman-v2-assistant-msg-elapsed", children: totalElapsedLabel })
2055
2235
  ] })
2056
- ] })
2236
+ ] }),
2237
+ /* @__PURE__ */ jsx(
2238
+ FeedbackReasonModal,
2239
+ {
2240
+ open: reasonModalOpen,
2241
+ onClose: () => setReasonModalOpen(false),
2242
+ onSubmit: async (reason, details) => {
2243
+ await onSubmitFeedback?.({
2244
+ messageId: message.id,
2245
+ executionId: message.executionId,
2246
+ feedback: reason,
2247
+ details
2248
+ });
2249
+ setActiveFeedback("down");
2250
+ }
2251
+ }
2252
+ )
2057
2253
  ] });
2058
2254
  }
2059
2255
  var DEFAULT_MAX_LENGTH = 6;
@@ -2334,7 +2530,7 @@ var MessageListV2 = forwardRef(
2334
2530
  onApproveAction,
2335
2531
  onRejectAction,
2336
2532
  onResendAction,
2337
- onMessageFeedback,
2533
+ onSubmitFeedback,
2338
2534
  typingSpeed = 4
2339
2535
  }, ref) {
2340
2536
  const scrollRef = useRef(null);
@@ -2474,7 +2670,7 @@ var MessageListV2 = forwardRef(
2474
2670
  message,
2475
2671
  onImageClick,
2476
2672
  onExecutionTraceClick,
2477
- onFeedback: onMessageFeedback,
2673
+ onSubmitFeedback,
2478
2674
  actions: messageActions?.assistantMessageActions,
2479
2675
  typingSpeed
2480
2676
  }
@@ -3242,6 +3438,316 @@ function ImageLightboxV2({ src, alt, onClose }) {
3242
3438
  document.body
3243
3439
  );
3244
3440
  }
3441
+ var PRE_PIPELINE_STEPS = /* @__PURE__ */ new Set([
3442
+ "record_execution",
3443
+ "resolve_provider",
3444
+ "resolve_mcp_servers",
3445
+ "build_pipeline",
3446
+ "load_skill_index"
3447
+ ]);
3448
+ function stepColor(step) {
3449
+ if (step.status === "failed") return "#ef4444";
3450
+ if (PRE_PIPELINE_STEPS.has(step.step)) return "#f59e0b";
3451
+ return "#3b82f6";
3452
+ }
3453
+ function formatMs(ms) {
3454
+ if (ms == null) return "\u2014";
3455
+ if (ms < 1e3) return `${ms} ms`;
3456
+ return `${(ms / 1e3).toFixed(2)} s`;
3457
+ }
3458
+ function TraceTimelineModal({
3459
+ open,
3460
+ onClose,
3461
+ executionId,
3462
+ apiBaseUrl,
3463
+ apiHeaders
3464
+ }) {
3465
+ const [trace, setTrace] = useState(null);
3466
+ const [loading, setLoading] = useState(false);
3467
+ const [error, setError] = useState(null);
3468
+ useEffect(() => {
3469
+ if (!open || !executionId) return;
3470
+ const ctrl = new AbortController();
3471
+ setLoading(true);
3472
+ setError(null);
3473
+ setTrace(null);
3474
+ const base = apiBaseUrl.replace(/\/+$/, "");
3475
+ fetch(`${base}/api/ask/executions/${encodeURIComponent(executionId)}/trace`, {
3476
+ method: "GET",
3477
+ headers: { Accept: "application/json", ...apiHeaders },
3478
+ signal: ctrl.signal
3479
+ }).then(async (resp) => {
3480
+ if (!resp.ok) {
3481
+ throw new Error(`Trace fetch failed: ${resp.status} ${resp.statusText}`);
3482
+ }
3483
+ return resp.json();
3484
+ }).then((data) => setTrace(data)).catch((e) => {
3485
+ if (e.name === "AbortError") return;
3486
+ setError(e instanceof Error ? e.message : "Trace fetch failed");
3487
+ }).finally(() => setLoading(false));
3488
+ return () => ctrl.abort();
3489
+ }, [open, executionId, apiBaseUrl, apiHeaders]);
3490
+ const totalMs = useMemo(() => {
3491
+ if (!trace) return 0;
3492
+ const meta = trace.runMetadata?.totalTimeMs;
3493
+ if (typeof meta === "number" && meta > 0) return meta;
3494
+ const starts = trace.pipelineSteps.map((s) => s.startTime);
3495
+ const ends = trace.pipelineSteps.map((s) => s.endTime ?? s.startTime).filter((t) => typeof t === "number");
3496
+ if (starts.length === 0 || ends.length === 0) return 0;
3497
+ return Math.max(...ends) - Math.min(...starts);
3498
+ }, [trace]);
3499
+ const accountedMs = useMemo(
3500
+ () => (trace?.pipelineSteps ?? []).reduce(
3501
+ (sum, s) => sum + (s.durationMs ?? 0),
3502
+ 0
3503
+ ),
3504
+ [trace]
3505
+ );
3506
+ const unaccountedMs = Math.max(totalMs - accountedMs, 0);
3507
+ if (typeof document === "undefined") return null;
3508
+ return createPortal(
3509
+ /* @__PURE__ */ jsx(AnimatePresence, { children: open && /* @__PURE__ */ jsx(
3510
+ motion.div,
3511
+ {
3512
+ initial: { opacity: 0 },
3513
+ animate: { opacity: 1 },
3514
+ exit: { opacity: 0 },
3515
+ transition: { duration: 0.15 },
3516
+ onClick: onClose,
3517
+ style: {
3518
+ position: "fixed",
3519
+ inset: 0,
3520
+ background: "rgba(0,0,0,0.45)",
3521
+ zIndex: 9999,
3522
+ display: "flex",
3523
+ alignItems: "center",
3524
+ justifyContent: "center",
3525
+ padding: 24
3526
+ },
3527
+ children: /* @__PURE__ */ jsxs(
3528
+ motion.div,
3529
+ {
3530
+ initial: { y: 12, opacity: 0 },
3531
+ animate: { y: 0, opacity: 1 },
3532
+ exit: { y: 12, opacity: 0 },
3533
+ transition: { duration: 0.18 },
3534
+ onClick: (e) => e.stopPropagation(),
3535
+ style: {
3536
+ background: "#0b1220",
3537
+ color: "#e5e7eb",
3538
+ borderRadius: 12,
3539
+ width: "100%",
3540
+ maxWidth: 760,
3541
+ maxHeight: "85vh",
3542
+ overflow: "auto",
3543
+ boxShadow: "0 20px 60px rgba(0,0,0,0.45)",
3544
+ fontFamily: "ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, sans-serif"
3545
+ },
3546
+ children: [
3547
+ /* @__PURE__ */ jsxs(
3548
+ "header",
3549
+ {
3550
+ style: {
3551
+ display: "flex",
3552
+ alignItems: "center",
3553
+ justifyContent: "space-between",
3554
+ padding: "14px 18px",
3555
+ borderBottom: "1px solid rgba(255,255,255,0.08)"
3556
+ },
3557
+ children: [
3558
+ /* @__PURE__ */ jsxs("div", { children: [
3559
+ /* @__PURE__ */ jsx("div", { style: { fontSize: 14, fontWeight: 600 }, children: "Execution trace" }),
3560
+ /* @__PURE__ */ jsx(
3561
+ "div",
3562
+ {
3563
+ style: {
3564
+ fontSize: 11,
3565
+ opacity: 0.6,
3566
+ marginTop: 2,
3567
+ fontFamily: "ui-monospace, SFMono-Regular, monospace"
3568
+ },
3569
+ children: executionId ?? ""
3570
+ }
3571
+ )
3572
+ ] }),
3573
+ /* @__PURE__ */ jsx(
3574
+ "button",
3575
+ {
3576
+ onClick: onClose,
3577
+ "aria-label": "Close",
3578
+ style: {
3579
+ background: "transparent",
3580
+ border: 0,
3581
+ color: "#e5e7eb",
3582
+ cursor: "pointer",
3583
+ padding: 6,
3584
+ borderRadius: 6
3585
+ },
3586
+ children: /* @__PURE__ */ jsx(X, { style: { width: 18, height: 18 } })
3587
+ }
3588
+ )
3589
+ ]
3590
+ }
3591
+ ),
3592
+ /* @__PURE__ */ jsxs("div", { style: { padding: 18 }, children: [
3593
+ loading && /* @__PURE__ */ jsx("div", { style: { opacity: 0.7, fontSize: 13 }, children: "Loading trace\u2026" }),
3594
+ error && /* @__PURE__ */ jsx(
3595
+ "div",
3596
+ {
3597
+ style: {
3598
+ color: "#fca5a5",
3599
+ fontSize: 13,
3600
+ whiteSpace: "pre-wrap"
3601
+ },
3602
+ children: error
3603
+ }
3604
+ ),
3605
+ trace && !loading && !error && /* @__PURE__ */ jsx(
3606
+ TimelineBars,
3607
+ {
3608
+ trace,
3609
+ totalMs,
3610
+ unaccountedMs
3611
+ }
3612
+ )
3613
+ ] })
3614
+ ]
3615
+ }
3616
+ )
3617
+ }
3618
+ ) }),
3619
+ document.body
3620
+ );
3621
+ }
3622
+ function TimelineBars({
3623
+ trace,
3624
+ totalMs,
3625
+ unaccountedMs
3626
+ }) {
3627
+ const bars = trace.pipelineSteps.map((step) => {
3628
+ const duration = step.durationMs ?? 0;
3629
+ const widthPct = totalMs > 0 ? duration / totalMs * 100 : 0;
3630
+ const llmMs = step.llmCall?.durationMs ?? null;
3631
+ return /* @__PURE__ */ jsxs("div", { style: { marginBottom: 8 }, children: [
3632
+ /* @__PURE__ */ jsxs(
3633
+ "div",
3634
+ {
3635
+ style: {
3636
+ display: "flex",
3637
+ justifyContent: "space-between",
3638
+ fontSize: 12,
3639
+ marginBottom: 4,
3640
+ fontFamily: "ui-monospace, SFMono-Regular, monospace"
3641
+ },
3642
+ children: [
3643
+ /* @__PURE__ */ jsxs("span", { children: [
3644
+ step.step,
3645
+ step.status === "failed" && /* @__PURE__ */ jsx("span", { style: { color: "#fca5a5", marginLeft: 6 }, children: "(failed)" })
3646
+ ] }),
3647
+ /* @__PURE__ */ jsxs("span", { style: { opacity: 0.75 }, children: [
3648
+ formatMs(duration),
3649
+ llmMs != null && /* @__PURE__ */ jsxs("span", { style: { marginLeft: 8, opacity: 0.6 }, children: [
3650
+ "(LLM ",
3651
+ formatMs(llmMs),
3652
+ ")"
3653
+ ] })
3654
+ ] })
3655
+ ]
3656
+ }
3657
+ ),
3658
+ /* @__PURE__ */ jsx(
3659
+ "div",
3660
+ {
3661
+ style: {
3662
+ height: 8,
3663
+ background: "rgba(255,255,255,0.06)",
3664
+ borderRadius: 4,
3665
+ overflow: "hidden"
3666
+ },
3667
+ children: /* @__PURE__ */ jsx(
3668
+ "div",
3669
+ {
3670
+ style: {
3671
+ height: "100%",
3672
+ width: `${Math.max(widthPct, 0.3)}%`,
3673
+ background: stepColor(step),
3674
+ transition: "width 0.2s ease"
3675
+ }
3676
+ }
3677
+ )
3678
+ }
3679
+ )
3680
+ ] }, `${step.step}-${step.startTime}`);
3681
+ });
3682
+ return /* @__PURE__ */ jsxs("div", { children: [
3683
+ bars,
3684
+ unaccountedMs > 0 && /* @__PURE__ */ jsxs("div", { style: { marginBottom: 8 }, children: [
3685
+ /* @__PURE__ */ jsxs(
3686
+ "div",
3687
+ {
3688
+ style: {
3689
+ display: "flex",
3690
+ justifyContent: "space-between",
3691
+ fontSize: 12,
3692
+ marginBottom: 4,
3693
+ fontFamily: "ui-monospace, SFMono-Regular, monospace",
3694
+ opacity: 0.7
3695
+ },
3696
+ children: [
3697
+ /* @__PURE__ */ jsx("span", { children: "(unaccounted)" }),
3698
+ /* @__PURE__ */ jsx("span", { children: formatMs(unaccountedMs) })
3699
+ ]
3700
+ }
3701
+ ),
3702
+ /* @__PURE__ */ jsx(
3703
+ "div",
3704
+ {
3705
+ style: {
3706
+ height: 8,
3707
+ background: "rgba(255,255,255,0.06)",
3708
+ borderRadius: 4,
3709
+ overflow: "hidden"
3710
+ },
3711
+ children: /* @__PURE__ */ jsx(
3712
+ "div",
3713
+ {
3714
+ style: {
3715
+ height: "100%",
3716
+ width: `${unaccountedMs / Math.max(totalMs, 1) * 100}%`,
3717
+ background: "repeating-linear-gradient(45deg, rgba(255,255,255,0.18) 0 4px, transparent 4px 8px)"
3718
+ }
3719
+ }
3720
+ )
3721
+ }
3722
+ )
3723
+ ] }),
3724
+ /* @__PURE__ */ jsxs(
3725
+ "div",
3726
+ {
3727
+ style: {
3728
+ marginTop: 14,
3729
+ paddingTop: 12,
3730
+ borderTop: "1px solid rgba(255,255,255,0.08)",
3731
+ fontSize: 12,
3732
+ display: "flex",
3733
+ justifyContent: "space-between",
3734
+ opacity: 0.85
3735
+ },
3736
+ children: [
3737
+ /* @__PURE__ */ jsxs("span", { children: [
3738
+ trace.pipelineSteps.length,
3739
+ " step",
3740
+ trace.pipelineSteps.length === 1 ? "" : "s"
3741
+ ] }),
3742
+ /* @__PURE__ */ jsxs("span", { style: { fontFamily: "ui-monospace, SFMono-Regular, monospace" }, children: [
3743
+ "total: ",
3744
+ formatMs(totalMs)
3745
+ ] })
3746
+ ]
3747
+ }
3748
+ )
3749
+ ] });
3750
+ }
3245
3751
  var DEFAULT_USER_ACTION_STATE = {
3246
3752
  request: null,
3247
3753
  result: null};
@@ -3432,12 +3938,39 @@ var PaymanChatInner = forwardRef(function PaymanChatInner2({
3432
3938
  ]
3433
3939
  );
3434
3940
  const {
3435
- onExecutionTraceClick,
3941
+ onExecutionTraceClick: rawOnExecutionTraceClick,
3436
3942
  onResetSession,
3437
3943
  onUploadImageClick,
3438
3944
  onAttachFileClick,
3439
3945
  onMessageFeedback
3440
3946
  } = callbacks;
3947
+ const [debugTraceExecutionId, setDebugTraceExecutionId] = useState(null);
3948
+ const handleSubmitFeedback = useCallback(
3949
+ async ({ messageId, executionId, feedback, details }) => {
3950
+ if (!executionId) {
3951
+ throw new Error("Cannot submit feedback before the response completes");
3952
+ }
3953
+ await submitAskFeedback({
3954
+ baseUrl: config.api.baseUrl,
3955
+ headers: config.api.headers,
3956
+ executionId,
3957
+ feedback,
3958
+ details
3959
+ });
3960
+ onMessageFeedback?.({
3961
+ messageId,
3962
+ feedback: feedback === "POSITIVE" ? "up" : "down"
3963
+ });
3964
+ },
3965
+ [config.api.baseUrl, config.api.headers, onMessageFeedback]
3966
+ );
3967
+ const onExecutionTraceClick = useMemo(() => {
3968
+ if (!config.debug) return rawOnExecutionTraceClick;
3969
+ return (data) => {
3970
+ rawOnExecutionTraceClick?.(data);
3971
+ if (data.executionId) setDebugTraceExecutionId(data.executionId);
3972
+ };
3973
+ }, [config.debug, rawOnExecutionTraceClick]);
3441
3974
  const performResetSession = useCallback(() => {
3442
3975
  resetToEmptyStateRef.current = true;
3443
3976
  setEditingMessageId(null);
@@ -3495,6 +4028,7 @@ var PaymanChatInner = forwardRef(function PaymanChatInner2({
3495
4028
  showEmptyStateIcon = true,
3496
4029
  emptyStateComponent,
3497
4030
  showResetSession = false,
4031
+ enableDeepModeToggle = true,
3498
4032
  showAttachmentButton = true,
3499
4033
  showUploadImageButton = true,
3500
4034
  showAttachFileButton = true,
@@ -3550,6 +4084,7 @@ var PaymanChatInner = forwardRef(function PaymanChatInner2({
3550
4084
  stopRecording();
3551
4085
  };
3552
4086
  const isV2InputDisabled = !isSessionParamsConfigured || disableInput;
4087
+ const effectiveAnalysisMode = enableDeepModeToggle ? analysisMode : "fast";
3553
4088
  const isEmpty = messages.length === 0;
3554
4089
  if (isChatDisabled) {
3555
4090
  if (disabledComponent) {
@@ -3608,7 +4143,7 @@ var PaymanChatInner = forwardRef(function PaymanChatInner2({
3608
4143
  if (isRecording) stopRecording();
3609
4144
  if (text.trim() && !disableInput && isSessionParamsConfigured) {
3610
4145
  setEditingMessageId(null);
3611
- void sendMessage(text.trim(), { analysisMode });
4146
+ void sendMessage(text.trim(), { analysisMode: effectiveAnalysisMode });
3612
4147
  }
3613
4148
  };
3614
4149
  const handleVoicePress = useCallback(async () => {
@@ -3635,7 +4170,9 @@ var PaymanChatInner = forwardRef(function PaymanChatInner2({
3635
4170
  (message) => message.id === messageId && message.role === "user"
3636
4171
  );
3637
4172
  if (!targetMessage?.content.trim()) return;
3638
- void sendMessage(targetMessage.content.trim(), { analysisMode });
4173
+ void sendMessage(targetMessage.content.trim(), {
4174
+ analysisMode: effectiveAnalysisMode
4175
+ });
3639
4176
  const bump = () => messageListV2Ref.current?.scrollToBottom("instant");
3640
4177
  requestAnimationFrame(() => {
3641
4178
  bump();
@@ -3643,7 +4180,7 @@ var PaymanChatInner = forwardRef(function PaymanChatInner2({
3643
4180
  window.setTimeout(bump, 120);
3644
4181
  });
3645
4182
  });
3646
- }, [isWaitingForResponse, messages, sendMessage, analysisMode]);
4183
+ }, [isWaitingForResponse, messages, sendMessage, effectiveAnalysisMode]);
3647
4184
  const handleClearEditing = useCallback(() => {
3648
4185
  setEditingMessageId(null);
3649
4186
  }, []);
@@ -3722,8 +4259,8 @@ var PaymanChatInner = forwardRef(function PaymanChatInner2({
3722
4259
  onAttachFileClick,
3723
4260
  editingMessageId,
3724
4261
  onClearEditing: handleClearEditing,
3725
- analysisMode,
3726
- onAnalysisModeChange: setAnalysisMode,
4262
+ analysisMode: enableDeepModeToggle ? analysisMode : void 0,
4263
+ onAnalysisModeChange: enableDeepModeToggle ? setAnalysisMode : void 0,
3727
4264
  slashCommands
3728
4265
  }
3729
4266
  )
@@ -3763,7 +4300,7 @@ var PaymanChatInner = forwardRef(function PaymanChatInner2({
3763
4300
  onResendAction: isUserActionSupported ? async () => {
3764
4301
  await resendOtp();
3765
4302
  } : void 0,
3766
- onMessageFeedback
4303
+ onSubmitFeedback: handleSubmitFeedback
3767
4304
  }
3768
4305
  ),
3769
4306
  /* @__PURE__ */ jsx(
@@ -3798,8 +4335,8 @@ var PaymanChatInner = forwardRef(function PaymanChatInner2({
3798
4335
  onAttachFileClick,
3799
4336
  editingMessageId,
3800
4337
  onClearEditing: handleClearEditing,
3801
- analysisMode,
3802
- onAnalysisModeChange: setAnalysisMode,
4338
+ analysisMode: enableDeepModeToggle ? analysisMode : void 0,
4339
+ onAnalysisModeChange: enableDeepModeToggle ? setAnalysisMode : void 0,
3803
4340
  slashCommands
3804
4341
  }
3805
4342
  )
@@ -3822,6 +4359,16 @@ var PaymanChatInner = forwardRef(function PaymanChatInner2({
3822
4359
  onClose: closeResetSessionConfirm,
3823
4360
  onConfirm: performResetSession
3824
4361
  }
4362
+ ),
4363
+ config.debug && /* @__PURE__ */ jsx(
4364
+ TraceTimelineModal,
4365
+ {
4366
+ open: debugTraceExecutionId !== null,
4367
+ onClose: () => setDebugTraceExecutionId(null),
4368
+ executionId: debugTraceExecutionId,
4369
+ apiBaseUrl: config.api.baseUrl,
4370
+ apiHeaders: config.api.headers
4371
+ }
3825
4372
  )
3826
4373
  ]
3827
4374
  }