@percena/weft 0.4.0-next.0 → 0.4.0-next.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/dist/action-bridge.cjs +323 -0
  2. package/dist/action-bridge.d.cts +8 -0
  3. package/dist/action-bridge.d.ts +8 -0
  4. package/dist/action-bridge.js +291 -0
  5. package/dist/chat.cjs +3851 -36
  6. package/dist/chat.d.cts +1 -874
  7. package/dist/chat.d.ts +1 -874
  8. package/dist/chat.js +3870 -36
  9. package/dist/index.cjs +12085 -1488
  10. package/dist/index.d.cts +553 -240
  11. package/dist/index.d.ts +553 -240
  12. package/dist/index.js +12118 -1447
  13. package/dist/providers-flitro.cjs +50 -307
  14. package/dist/providers-flitro.d.cts +75 -52
  15. package/dist/providers-flitro.d.ts +75 -52
  16. package/dist/providers-flitro.js +45 -287
  17. package/dist/styles/fonts/KaTeX_AMS-Regular.ttf +0 -0
  18. package/dist/styles/fonts/KaTeX_AMS-Regular.woff +0 -0
  19. package/dist/styles/fonts/KaTeX_AMS-Regular.woff2 +0 -0
  20. package/dist/styles/fonts/KaTeX_Caligraphic-Bold.ttf +0 -0
  21. package/dist/styles/fonts/KaTeX_Caligraphic-Bold.woff +0 -0
  22. package/dist/styles/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
  23. package/dist/styles/fonts/KaTeX_Caligraphic-Regular.ttf +0 -0
  24. package/dist/styles/fonts/KaTeX_Caligraphic-Regular.woff +0 -0
  25. package/dist/styles/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
  26. package/dist/styles/fonts/KaTeX_Fraktur-Bold.ttf +0 -0
  27. package/dist/styles/fonts/KaTeX_Fraktur-Bold.woff +0 -0
  28. package/dist/styles/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
  29. package/dist/styles/fonts/KaTeX_Fraktur-Regular.ttf +0 -0
  30. package/dist/styles/fonts/KaTeX_Fraktur-Regular.woff +0 -0
  31. package/dist/styles/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
  32. package/dist/styles/fonts/KaTeX_Main-Bold.ttf +0 -0
  33. package/dist/styles/fonts/KaTeX_Main-Bold.woff +0 -0
  34. package/dist/styles/fonts/KaTeX_Main-Bold.woff2 +0 -0
  35. package/dist/styles/fonts/KaTeX_Main-BoldItalic.ttf +0 -0
  36. package/dist/styles/fonts/KaTeX_Main-BoldItalic.woff +0 -0
  37. package/dist/styles/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
  38. package/dist/styles/fonts/KaTeX_Main-Italic.ttf +0 -0
  39. package/dist/styles/fonts/KaTeX_Main-Italic.woff +0 -0
  40. package/dist/styles/fonts/KaTeX_Main-Italic.woff2 +0 -0
  41. package/dist/styles/fonts/KaTeX_Main-Regular.ttf +0 -0
  42. package/dist/styles/fonts/KaTeX_Main-Regular.woff +0 -0
  43. package/dist/styles/fonts/KaTeX_Main-Regular.woff2 +0 -0
  44. package/dist/styles/fonts/KaTeX_Math-BoldItalic.ttf +0 -0
  45. package/dist/styles/fonts/KaTeX_Math-BoldItalic.woff +0 -0
  46. package/dist/styles/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
  47. package/dist/styles/fonts/KaTeX_Math-Italic.ttf +0 -0
  48. package/dist/styles/fonts/KaTeX_Math-Italic.woff +0 -0
  49. package/dist/styles/fonts/KaTeX_Math-Italic.woff2 +0 -0
  50. package/dist/styles/fonts/KaTeX_SansSerif-Bold.ttf +0 -0
  51. package/dist/styles/fonts/KaTeX_SansSerif-Bold.woff +0 -0
  52. package/dist/styles/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
  53. package/dist/styles/fonts/KaTeX_SansSerif-Italic.ttf +0 -0
  54. package/dist/styles/fonts/KaTeX_SansSerif-Italic.woff +0 -0
  55. package/dist/styles/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
  56. package/dist/styles/fonts/KaTeX_SansSerif-Regular.ttf +0 -0
  57. package/dist/styles/fonts/KaTeX_SansSerif-Regular.woff +0 -0
  58. package/dist/styles/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
  59. package/dist/styles/fonts/KaTeX_Script-Regular.ttf +0 -0
  60. package/dist/styles/fonts/KaTeX_Script-Regular.woff +0 -0
  61. package/dist/styles/fonts/KaTeX_Script-Regular.woff2 +0 -0
  62. package/dist/styles/fonts/KaTeX_Size1-Regular.ttf +0 -0
  63. package/dist/styles/fonts/KaTeX_Size1-Regular.woff +0 -0
  64. package/dist/styles/fonts/KaTeX_Size1-Regular.woff2 +0 -0
  65. package/dist/styles/fonts/KaTeX_Size2-Regular.ttf +0 -0
  66. package/dist/styles/fonts/KaTeX_Size2-Regular.woff +0 -0
  67. package/dist/styles/fonts/KaTeX_Size2-Regular.woff2 +0 -0
  68. package/dist/styles/fonts/KaTeX_Size3-Regular.ttf +0 -0
  69. package/dist/styles/fonts/KaTeX_Size3-Regular.woff +0 -0
  70. package/dist/styles/fonts/KaTeX_Size3-Regular.woff2 +0 -0
  71. package/dist/styles/fonts/KaTeX_Size4-Regular.ttf +0 -0
  72. package/dist/styles/fonts/KaTeX_Size4-Regular.woff +0 -0
  73. package/dist/styles/fonts/KaTeX_Size4-Regular.woff2 +0 -0
  74. package/dist/styles/fonts/KaTeX_Typewriter-Regular.ttf +0 -0
  75. package/dist/styles/fonts/KaTeX_Typewriter-Regular.woff +0 -0
  76. package/dist/styles/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
  77. package/dist/styles/index.css +2 -212
  78. package/package.json +23 -49
  79. package/dist/auth.cjs +0 -241
  80. package/dist/auth.d.cts +0 -21
  81. package/dist/auth.d.ts +0 -21
  82. package/dist/auth.js +0 -208
  83. package/dist/automations.cjs +0 -3044
  84. package/dist/automations.d.cts +0 -4774
  85. package/dist/automations.d.ts +0 -4774
  86. package/dist/automations.js +0 -2965
  87. package/dist/factory.cjs +0 -5057
  88. package/dist/factory.d.cts +0 -7909
  89. package/dist/factory.d.ts +0 -7909
  90. package/dist/factory.js +0 -5008
  91. package/dist/local-runtime.cjs +0 -1387
  92. package/dist/local-runtime.d.cts +0 -3314
  93. package/dist/local-runtime.d.ts +0 -3314
  94. package/dist/local-runtime.js +0 -1345
  95. package/dist/providers.cjs +0 -6154
  96. package/dist/providers.d.cts +0 -6024
  97. package/dist/providers.d.ts +0 -6024
  98. package/dist/providers.js +0 -6110
  99. package/dist/server.cjs +0 -9137
  100. package/dist/server.d.cts +0 -9868
  101. package/dist/server.d.ts +0 -9868
  102. package/dist/server.js +0 -9118
  103. package/dist/skills-browser.cjs +0 -118
  104. package/dist/skills-browser.d.cts +0 -105
  105. package/dist/skills-browser.d.ts +0 -105
  106. package/dist/skills-browser.js +0 -88
  107. package/dist/skills.cjs +0 -505
  108. package/dist/skills.d.cts +0 -218
  109. package/dist/skills.d.ts +0 -218
  110. package/dist/skills.js +0 -458
  111. package/dist/sources.cjs +0 -1710
  112. package/dist/sources.d.cts +0 -3978
  113. package/dist/sources.d.ts +0 -3978
  114. package/dist/sources.js +0 -1675
package/dist/chat.js CHANGED
@@ -832,7 +832,7 @@ function TurnCardActionsMenu({
832
832
  hasEditOrWriteActivities,
833
833
  className
834
834
  }) {
835
- const { t: t2 } = useTranslation();
835
+ const { t: t22 } = useTranslation();
836
836
  const [isOpen, setIsOpen] = React2.useState(false);
837
837
  if (!onOpenDetails && !onOpenMultiFileDiff) {
838
838
  return null;
@@ -870,7 +870,7 @@ function TurnCardActionsMenu({
870
870
  {
871
871
  onClick: onOpenMultiFileDiff,
872
872
  icon: /* @__PURE__ */ jsx3(FileDiff, {}),
873
- children: t2("chat.viewFileChanges")
873
+ children: t22("chat.viewFileChanges")
874
874
  }
875
875
  ),
876
876
  onOpenDetails && /* @__PURE__ */ jsx3(
@@ -878,7 +878,7 @@ function TurnCardActionsMenu({
878
878
  {
879
879
  onClick: onOpenDetails,
880
880
  icon: /* @__PURE__ */ jsx3(ArrowUpRight, {}),
881
- children: t2("chat.viewTurnDetails")
881
+ children: t22("chat.viewTurnDetails")
882
882
  }
883
883
  )
884
884
  ]
@@ -2632,9 +2632,9 @@ function AcceptPlanDropdown({
2632
2632
  acceptOptionLabel,
2633
2633
  className
2634
2634
  }) {
2635
- const { t: t2 } = useTranslation2();
2636
- const effectiveAcceptLabel = acceptLabel ?? t2("plan.acceptPlan");
2637
- const effectiveAcceptOptionLabel = acceptOptionLabel ?? t2("plan.accept");
2635
+ const { t: t22 } = useTranslation2();
2636
+ const effectiveAcceptLabel = acceptLabel ?? t22("plan.acceptPlan");
2637
+ const effectiveAcceptOptionLabel = acceptOptionLabel ?? t22("plan.accept");
2638
2638
  const [isOpen, setIsOpen] = useState5(false);
2639
2639
  const [position, setPosition] = useState5(null);
2640
2640
  const triggerRef = useRef3(null);
@@ -2764,7 +2764,7 @@ function AcceptPlanDropdown({
2764
2764
  ),
2765
2765
  children: [
2766
2766
  /* @__PURE__ */ jsx21("span", { className: "text-[13px] font-medium", children: effectiveAcceptOptionLabel }),
2767
- /* @__PURE__ */ jsx21("span", { className: "text-xs text-muted-foreground", children: t2("plan.executeImmediately") })
2767
+ /* @__PURE__ */ jsx21("span", { className: "text-xs text-muted-foreground", children: t22("plan.executeImmediately") })
2768
2768
  ]
2769
2769
  }
2770
2770
  ),
@@ -2779,8 +2779,8 @@ function AcceptPlanDropdown({
2779
2779
  "transition-colors"
2780
2780
  ),
2781
2781
  children: [
2782
- /* @__PURE__ */ jsx21("span", { className: "text-[13px] font-medium", children: t2("plan.acceptAndCompact") }),
2783
- /* @__PURE__ */ jsx21("span", { className: "text-xs text-muted-foreground", children: t2("plan.worksForComplex") })
2782
+ /* @__PURE__ */ jsx21("span", { className: "text-[13px] font-medium", children: t22("plan.acceptAndCompact") }),
2783
+ /* @__PURE__ */ jsx21("span", { className: "text-xs text-muted-foreground", children: t22("plan.worksForComplex") })
2784
2784
  ]
2785
2785
  }
2786
2786
  )
@@ -2830,7 +2830,7 @@ function StyledDropdownMenuItem({
2830
2830
  );
2831
2831
  }
2832
2832
  function BranchDropdown({ onBranch }) {
2833
- const { t: t2 } = useTranslation3();
2833
+ const { t: t22 } = useTranslation3();
2834
2834
  const handleBranchClick = () => {
2835
2835
  onBranch({ newPanel: true });
2836
2836
  };
@@ -2839,8 +2839,8 @@ function BranchDropdown({ onBranch }) {
2839
2839
  "button",
2840
2840
  {
2841
2841
  type: "button",
2842
- "aria-label": t2("chat.branchOptions"),
2843
- title: t2("chat.branch"),
2842
+ "aria-label": t22("chat.branchOptions"),
2843
+ title: t22("chat.branch"),
2844
2844
  className: cn(
2845
2845
  "p-1 rounded-[4px] transition-colors select-none",
2846
2846
  "text-muted-foreground hover:text-foreground hover:bg-foreground/5",
@@ -2851,8 +2851,8 @@ function BranchDropdown({ onBranch }) {
2851
2851
  }
2852
2852
  ) }),
2853
2853
  /* @__PURE__ */ jsx23(StyledDropdownMenuContent, { align: "end", minWidth: "min-w-64", sideOffset: 6, children: /* @__PURE__ */ jsx23(StyledDropdownMenuItem, { onClick: handleBranchClick, className: "items-start py-2", children: /* @__PURE__ */ jsxs10("div", { className: "flex flex-col gap-0.5", children: [
2854
- /* @__PURE__ */ jsx23("span", { className: "text-[13px] leading-tight", children: t2("chat.branchFromThisMessage") }),
2855
- /* @__PURE__ */ jsx23("span", { className: "max-w-[220px] whitespace-normal text-xs leading-tight text-muted-foreground", children: t2("chat.branchFromThisMessageDescription") })
2854
+ /* @__PURE__ */ jsx23("span", { className: "text-[13px] leading-tight", children: t22("chat.branchFromThisMessage") }),
2855
+ /* @__PURE__ */ jsx23("span", { className: "max-w-[220px] whitespace-normal text-xs leading-tight text-muted-foreground", children: t22("chat.branchFromThisMessageDescription") })
2856
2856
  ] }) }) })
2857
2857
  ] });
2858
2858
  }
@@ -2900,7 +2900,7 @@ function ResponseCard({
2900
2900
  openAnnotationRequest,
2901
2901
  annotationInteractionMode = "interactive"
2902
2902
  }) {
2903
- const { t: t2 } = useTranslation3();
2903
+ const { t: t22 } = useTranslation3();
2904
2904
  const [displayedText, setDisplayedText] = useState6(text);
2905
2905
  const lastUpdateRef = useRef4(Date.now());
2906
2906
  const [copied, setCopied] = useState6(false);
@@ -3500,7 +3500,7 @@ function ResponseCard({
3500
3500
  "text-muted-foreground/50 hover:text-foreground",
3501
3501
  "focus:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:opacity-100"
3502
3502
  ),
3503
- title: t2("common.viewFullscreen"),
3503
+ title: t22("common.viewFullscreen"),
3504
3504
  children: /* @__PURE__ */ jsx23(Maximize2, { className: "w-3.5 h-3.5" })
3505
3505
  }
3506
3506
  ),
@@ -3563,10 +3563,10 @@ function ResponseCard({
3563
3563
  ),
3564
3564
  children: copied ? /* @__PURE__ */ jsxs10(Fragment8, { children: [
3565
3565
  /* @__PURE__ */ jsx23(Check, { className: SIZE_CONFIG.iconSize }),
3566
- /* @__PURE__ */ jsx23("span", { children: t2("common.copied") })
3566
+ /* @__PURE__ */ jsx23("span", { children: t22("common.copied") })
3567
3567
  ] }) : /* @__PURE__ */ jsxs10(Fragment8, { children: [
3568
3568
  /* @__PURE__ */ jsx23(Copy, { className: SIZE_CONFIG.iconSize }),
3569
- /* @__PURE__ */ jsx23("span", { children: t2("common.copy") })
3569
+ /* @__PURE__ */ jsx23("span", { children: t22("common.copy") })
3570
3570
  ] })
3571
3571
  }
3572
3572
  ),
@@ -3599,8 +3599,8 @@ function ResponseCard({
3599
3599
  {
3600
3600
  onAccept,
3601
3601
  onAcceptWithCompact,
3602
- acceptLabel: hasActiveFollowUpAnnotations ? t2("plan.acceptAndSendFollowups") : t2("plan.acceptPlan"),
3603
- acceptOptionLabel: hasActiveFollowUpAnnotations ? t2("plan.acceptAndSendFollowups") : t2("plan.accept")
3602
+ acceptLabel: hasActiveFollowUpAnnotations ? t22("plan.acceptAndSendFollowups") : t22("plan.acceptPlan"),
3603
+ acceptOptionLabel: hasActiveFollowUpAnnotations ? t22("plan.acceptAndSendFollowups") : t22("plan.accept")
3604
3604
  }
3605
3605
  )
3606
3606
  }
@@ -4146,12 +4146,12 @@ function InlineExecution({
4146
4146
  onRetry,
4147
4147
  className
4148
4148
  }) {
4149
- const { t: t2 } = useTranslation4();
4149
+ const { t: t22 } = useTranslation4();
4150
4150
  if (status === "executing") {
4151
4151
  return /* @__PURE__ */ jsxs13("div", { className: cn("space-y-3", className), children: [
4152
4152
  /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2", children: [
4153
4153
  /* @__PURE__ */ jsx26(LoadingIndicator, { animated: true, showElapsed: true }),
4154
- /* @__PURE__ */ jsx26("span", { className: cn("text-foreground/80", SIZE_CONFIG.fontSize), children: t2("common.editing") })
4154
+ /* @__PURE__ */ jsx26("span", { className: cn("text-foreground/80", SIZE_CONFIG.fontSize), children: t22("common.editing") })
4155
4155
  ] }),
4156
4156
  activities.length > 0 && /* @__PURE__ */ jsx26("div", { className: "space-y-0.5 pl-1", children: activities.slice(-3).map((activity) => /* @__PURE__ */ jsx26(InlineActivityRow, { activity }, activity.id)) }),
4157
4157
  /* @__PURE__ */ jsx26("div", { className: "flex items-center justify-start pt-1 border-t border-border/30", children: /* @__PURE__ */ jsx26(
@@ -4163,7 +4163,7 @@ function InlineExecution({
4163
4163
  "text-muted-foreground hover:text-foreground transition-colors",
4164
4164
  SIZE_CONFIG.fontSize
4165
4165
  ),
4166
- children: t2("common.cancel")
4166
+ children: t22("common.cancel")
4167
4167
  }
4168
4168
  ) })
4169
4169
  ] });
@@ -4172,7 +4172,7 @@ function InlineExecution({
4172
4172
  return /* @__PURE__ */ jsxs13("div", { className: cn("space-y-3", className), children: [
4173
4173
  /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2", children: [
4174
4174
  /* @__PURE__ */ jsx26(CheckCircle22, { className: "w-4 h-4 text-success" }),
4175
- /* @__PURE__ */ jsx26("span", { className: cn("text-foreground font-medium", SIZE_CONFIG.fontSize), children: t2("common.done") })
4175
+ /* @__PURE__ */ jsx26("span", { className: cn("text-foreground font-medium", SIZE_CONFIG.fontSize), children: t22("common.done") })
4176
4176
  ] }),
4177
4177
  result && /* @__PURE__ */ jsx26("div", { className: cn("text-muted-foreground leading-relaxed prose-compact", SIZE_CONFIG.fontSize), children: /* @__PURE__ */ jsx26(Markdown, { children: result }) }),
4178
4178
  /* @__PURE__ */ jsx26("div", { className: "flex items-center justify-end pt-1 border-t border-border/30", children: /* @__PURE__ */ jsxs13(
@@ -4186,7 +4186,7 @@ function InlineExecution({
4186
4186
  ),
4187
4187
  children: [
4188
4188
  /* @__PURE__ */ jsx26(CheckCircle22, { className: "w-3 h-3" }),
4189
- t2("common.done")
4189
+ t22("common.done")
4190
4190
  ]
4191
4191
  }
4192
4192
  ) })
@@ -4195,7 +4195,7 @@ function InlineExecution({
4195
4195
  return /* @__PURE__ */ jsxs13("div", { className: cn("space-y-3", className), children: [
4196
4196
  /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2", children: [
4197
4197
  /* @__PURE__ */ jsx26(XCircle2, { className: "w-4 h-4 text-destructive" }),
4198
- /* @__PURE__ */ jsx26("span", { className: cn("text-foreground font-medium", SIZE_CONFIG.fontSize), children: t2("common.failed") })
4198
+ /* @__PURE__ */ jsx26("span", { className: cn("text-foreground font-medium", SIZE_CONFIG.fontSize), children: t22("common.failed") })
4199
4199
  ] }),
4200
4200
  error && /* @__PURE__ */ jsx26("div", { className: cn("text-destructive/80 leading-relaxed prose-compact", SIZE_CONFIG.fontSize), children: /* @__PURE__ */ jsx26(Markdown, { children: error }) }),
4201
4201
  /* @__PURE__ */ jsxs13("div", { className: "flex items-center justify-end gap-2 pt-1 border-t border-border/30", children: [
@@ -4210,7 +4210,7 @@ function InlineExecution({
4210
4210
  ),
4211
4211
  children: [
4212
4212
  /* @__PURE__ */ jsx26(X, { className: "w-3 h-3" }),
4213
- t2("common.dismiss")
4213
+ t22("common.dismiss")
4214
4214
  ]
4215
4215
  }
4216
4216
  ),
@@ -4223,7 +4223,7 @@ function InlineExecution({
4223
4223
  "px-2 py-1 rounded-md bg-accent/10 text-accent hover:bg-accent/20 transition-colors",
4224
4224
  SIZE_CONFIG.fontSize
4225
4225
  ),
4226
- children: t2("common.retry")
4226
+ children: t22("common.retry")
4227
4227
  }
4228
4228
  )
4229
4229
  ] })
@@ -4450,14 +4450,14 @@ function CommandBadge({ badge }) {
4450
4450
  );
4451
4451
  }
4452
4452
  function ContextBadge({ badge }) {
4453
- const { t: t2 } = useTranslation5();
4453
+ const { t: t22 } = useTranslation5();
4454
4454
  const displayLabel = badge.collapsedLabel || badge.label;
4455
4455
  return /* @__PURE__ */ jsxs14(
4456
4456
  "span",
4457
4457
  {
4458
4458
  className: "inline-flex items-center gap-1 h-[22px] px-1.5 mr-1 rounded-[5px] bg-background shadow-minimal text-[12px] align-middle",
4459
4459
  style: { verticalAlign: "middle", transform: "translateY(-1px)" },
4460
- title: t2("chat.contextBadge"),
4460
+ title: t22("chat.contextBadge"),
4461
4461
  children: [
4462
4462
  /* @__PURE__ */ jsx28("span", { className: "h-[12px] w-[12px] rounded-[2px] bg-foreground/5 flex items-center justify-center text-foreground/50 shrink-0 text-[8px]", children: CONTEXT_ICON_TEXT }),
4463
4463
  /* @__PURE__ */ jsx28("span", { className: "truncate max-w-[200px] text-muted-foreground", children: displayLabel })
@@ -4621,7 +4621,7 @@ function UserMessageBubble({
4621
4621
  isQueued,
4622
4622
  compactMode
4623
4623
  }) {
4624
- const { t: t2 } = useTranslation5();
4624
+ const { t: t22 } = useTranslation5();
4625
4625
  const hasAttachments = attachments && attachments.length > 0;
4626
4626
  const [showQueued, setShowQueued] = useState8(isQueued ?? false);
4627
4627
  const queuedShownAtRef = useRef6(isQueued ? Date.now() : null);
@@ -4678,7 +4678,7 @@ function UserMessageBubble({
4678
4678
  {
4679
4679
  className: "shrink-0 cursor-pointer hover:opacity-80 transition-opacity",
4680
4680
  onClick: () => att.storedPath && onFileClick?.(att.storedPath),
4681
- title: t2("chat.clickToOpen", { name: att.name }),
4681
+ title: t22("chat.clickToOpen", { name: att.name }),
4682
4682
  children: isImage ? (
4683
4683
  /* IMAGE: Square thumbnail only */
4684
4684
  /* @__PURE__ */ jsx28("div", { className: "h-14 w-14 rounded-[8px] overflow-hidden bg-background shadow-minimal", children: hasThumbnail ? /* @__PURE__ */ jsx28(
@@ -4727,7 +4727,7 @@ function UserMessageBubble({
4727
4727
  "aria-live": "polite",
4728
4728
  children: [
4729
4729
  /* @__PURE__ */ jsx28(Clock, { className: "h-3 w-3 animate-pulse", "aria-hidden": "true" }),
4730
- /* @__PURE__ */ jsx28("span", { className: "text-[11px] italic", children: t2("chat.queuedBadge") })
4730
+ /* @__PURE__ */ jsx28("span", { className: "text-[11px] italic", children: t22("chat.queuedBadge") })
4731
4731
  ]
4732
4732
  }
4733
4733
  ),
@@ -5430,7 +5430,7 @@ function handleTextComplete(state, event) {
5430
5430
  const existingMsg = session.messages[msgIndex];
5431
5431
  const resolvedContent = event.text || streaming?.content || existingMsg?.content || "";
5432
5432
  const isCompletingAccumulatedText = Boolean(event.text) && (event.text === existingMsg.content || event.text === streaming?.content);
5433
- const completedTimestamp = isCompletingAccumulatedText ? existingMsg.timestamp : Math.max(event.timestamp ?? Date.now(), existingMsg.timestamp + 1);
5433
+ const completedTimestamp = event.isIntermediate ? existingMsg.timestamp : isCompletingAccumulatedText ? existingMsg.timestamp : Math.max(event.timestamp ?? Date.now(), existingMsg.timestamp + 1);
5434
5434
  const updatedSession = updateMessageAt(session, msgIndex, {
5435
5435
  // Replace temporary renderer-generated ID with authoritative main-process ID
5436
5436
  // so branchFromMessageId always resolves against persisted session.jsonl.
@@ -7038,7 +7038,7 @@ var InProcessEventSource = class {
7038
7038
  }
7039
7039
  };
7040
7040
 
7041
- // ../packages/local-chat/dist/index.js
7041
+ // ../packages/chat/dist/index.js
7042
7042
  import { useState as useState22 } from "react";
7043
7043
  import { useCallback as useCallback9, useEffect as useEffect9, useMemo as useMemo8, useRef as useRef8, useState as useState12 } from "react";
7044
7044
 
@@ -7060,7 +7060,7 @@ function timelineKey(item) {
7060
7060
  return `${item.epoch}:${item.seq}`;
7061
7061
  }
7062
7062
 
7063
- // ../packages/local-chat/dist/index.js
7063
+ // ../packages/chat/dist/index.js
7064
7064
  import { jsx as jsx39, jsxs as jsxs21 } from "react/jsx-runtime";
7065
7065
  import { useCallback as useCallback22, useEffect as useEffect22, useMemo as useMemo22, useRef as useRef22, useState as useState32 } from "react";
7066
7066
  import { jsx as jsx210, jsxs as jsxs22 } from "react/jsx-runtime";
@@ -7097,6 +7097,7 @@ function createAgentChatPanelModelFromTimeline(args) {
7097
7097
  };
7098
7098
  }
7099
7099
  function isChatTranscriptTimelineEnvelope(envelope) {
7100
+ if (!envelope.item) return false;
7100
7101
  switch (envelope.item.type) {
7101
7102
  case "user_message":
7102
7103
  case "assistant_message_delta":
@@ -7822,6 +7823,3838 @@ function TimelineAgentChatPanel({
7822
7823
  )
7823
7824
  ] });
7824
7825
  }
7826
+
7827
+ // ../packages/react/dist/index.js
7828
+ import * as React102 from "react";
7829
+ import { useMemo as useMemo52, useEffect as useEffect42, useRef as useRef52, useCallback as useCallback62, useState as useState72 } from "react";
7830
+ import i18n22 from "i18next";
7831
+ import { motion as motion42, AnimatePresence as AnimatePresence32 } from "motion/react";
7832
+ import { ChevronRight as ChevronRight32 } from "lucide-react";
7833
+ import { jsx as jsx40, jsxs as jsxs23 } from "react/jsx-runtime";
7834
+ import * as React22 from "react";
7835
+ import { useTranslation as useTranslation6 } from "react-i18next";
7836
+ import { MoreHorizontal as MoreHorizontal2, FileDiff as FileDiff2, ArrowUpRight as ArrowUpRight3 } from "lucide-react";
7837
+ import * as React11 from "react";
7838
+ import { jsx as jsx211, jsxs as jsxs24 } from "react/jsx-runtime";
7839
+ import { jsx as jsx310, jsxs as jsxs32 } from "react/jsx-runtime";
7840
+ import i18n3 from "i18next";
7841
+ import { useCallback as useCallback10, useState as useState33 } from "react";
7842
+ import { motion as motion5, AnimatePresence as AnimatePresence4 } from "motion/react";
7843
+ import {
7844
+ ChevronRight as ChevronRight4,
7845
+ CheckCircle2 as CheckCircle23,
7846
+ XCircle as XCircle3,
7847
+ Circle as Circle3,
7848
+ MessageCircleDashed as MessageCircleDashed2,
7849
+ ArrowUpRight as ArrowUpRight22,
7850
+ Pencil as Pencil2,
7851
+ FilePenLine as FilePenLine2
7852
+ } from "lucide-react";
7853
+ import { Fragment as Fragment10, jsx as jsx42 } from "react/jsx-runtime";
7854
+ import { Fragment as Fragment22, jsx as jsx52, jsxs as jsxs42 } from "react/jsx-runtime";
7855
+ import { useMemo as useMemo42, useEffect as useEffect32, useRef as useRef42, useCallback as useCallback52, useState as useState62 } from "react";
7856
+ import { useTranslation as useTranslation32 } from "react-i18next";
7857
+ import {
7858
+ FileText as FileText2,
7859
+ Copy as Copy2,
7860
+ Check as Check2,
7861
+ Maximize2 as Maximize22,
7862
+ ListTodo as ListTodo2,
7863
+ GitBranch as GitBranch2
7864
+ } from "lucide-react";
7865
+ import * as React62 from "react";
7866
+ import ReactMarkdown2 from "react-markdown";
7867
+ import rehypeKatex2 from "rehype-katex";
7868
+ import rehypeRaw2 from "rehype-raw";
7869
+ import remarkGfm2 from "remark-gfm";
7870
+ import remarkMath2 from "remark-math";
7871
+ import * as React32 from "react";
7872
+ import { createBundledHighlighter as createBundledHighlighter2, createSingletonShorthands as createSingletonShorthands2 } from "@shikijs/core";
7873
+ import { createJavaScriptRegexEngine as createJavaScriptRegexEngine2 } from "@shikijs/engine-javascript";
7874
+ import { createContext as createContext4, useContext as useContext4 } from "react";
7875
+ import { jsx as jsx62 } from "react/jsx-runtime";
7876
+ import { jsx as jsx72, jsxs as jsxs52 } from "react/jsx-runtime";
7877
+ import * as React42 from "react";
7878
+ import { jsx as jsx82, jsxs as jsxs62 } from "react/jsx-runtime";
7879
+ import { jsx as jsx92 } from "react/jsx-runtime";
7880
+ import { jsx as jsx102 } from "react/jsx-runtime";
7881
+ import { jsx as jsx112 } from "react/jsx-runtime";
7882
+ import { jsx as jsx122 } from "react/jsx-runtime";
7883
+ import { jsx as jsx132 } from "react/jsx-runtime";
7884
+ import { jsx as jsx142 } from "react/jsx-runtime";
7885
+ import { jsx as jsx152 } from "react/jsx-runtime";
7886
+ import { jsx as jsx162 } from "react/jsx-runtime";
7887
+ import * as React52 from "react";
7888
+ import { ChevronRight as ChevronRight22 } from "lucide-react";
7889
+ import { motion as motion22, AnimatePresence as AnimatePresence22 } from "motion/react";
7890
+ import { Fragment as Fragment32, jsx as jsx172, jsxs as jsxs72 } from "react/jsx-runtime";
7891
+ import { createContext as createContext22, useContext as useContext22 } from "react";
7892
+ import { jsx as jsx182 } from "react/jsx-runtime";
7893
+ import { Fragment as Fragment42, jsx as jsx192 } from "react/jsx-runtime";
7894
+ import * as React72 from "react";
7895
+ import { jsx as jsx202, jsxs as jsxs82 } from "react/jsx-runtime";
7896
+ import * as React82 from "react";
7897
+ import * as React92 from "react";
7898
+ import { useCallback as useCallback42, useEffect as useEffect23, useRef as useRef32, useState as useState52 } from "react";
7899
+ import { useTranslation as useTranslation22 } from "react-i18next";
7900
+ import * as ReactDOM2 from "react-dom";
7901
+ import { ChevronDown as ChevronDown2 } from "lucide-react";
7902
+ import { Fragment as Fragment62, jsx as jsx212, jsxs as jsxs92 } from "react/jsx-runtime";
7903
+ import { Fragment as Fragment72, jsx as jsx222 } from "react/jsx-runtime";
7904
+ import { Fragment as Fragment82, jsx as jsx232, jsxs as jsxs102 } from "react/jsx-runtime";
7905
+ import { motion as motion32 } from "motion/react";
7906
+ import {
7907
+ Circle as Circle22,
7908
+ CircleCheck as CircleCheck2,
7909
+ Ban as Ban2
7910
+ } from "lucide-react";
7911
+ import { jsx as jsx242, jsxs as jsxs112 } from "react/jsx-runtime";
7912
+ import { jsx as jsx252, jsxs as jsxs122 } from "react/jsx-runtime";
7913
+ import { useTranslation as useTranslation42 } from "react-i18next";
7914
+ import { CheckCircle2 as CheckCircle222, XCircle as XCircle22, X as X2 } from "lucide-react";
7915
+ import { Fragment as Fragment92, jsx as jsx262, jsxs as jsxs132 } from "react/jsx-runtime";
7916
+ import { useMemo as useMemo62, useState as useState92, useCallback as useCallback72 } from "react";
7917
+ import { useEffect as useEffect52, useRef as useRef62, useState as useState82 } from "react";
7918
+ import { Clock as Clock2 } from "lucide-react";
7919
+ import { File as File2, Image as ImageIcon2 } from "lucide-react";
7920
+ import { jsx as jsx272 } from "react/jsx-runtime";
7921
+ import { useTranslation as useTranslation52 } from "react-i18next";
7922
+ import { jsx as jsx282, jsxs as jsxs142 } from "react/jsx-runtime";
7923
+ import { jsx as jsx292 } from "react/jsx-runtime";
7924
+ import { jsx as jsx302, jsxs as jsxs152 } from "react/jsx-runtime";
7925
+ import { jsx as jsx312, jsxs as jsxs162 } from "react/jsx-runtime";
7926
+ import { useMemo as useMemo72 } from "react";
7927
+ import { createContext as createContext32, useContext as useContext32 } from "react";
7928
+ import { jsx as jsx322 } from "react/jsx-runtime";
7929
+ import { jsx as jsx332, jsxs as jsxs172 } from "react/jsx-runtime";
7930
+ import { jsx as jsx342, jsxs as jsxs182 } from "react/jsx-runtime";
7931
+ import { useState as useState102, useEffect as useEffect62 } from "react";
7932
+ import { jsx as jsx352 } from "react/jsx-runtime";
7933
+ import { jsx as jsx362, jsxs as jsxs192 } from "react/jsx-runtime";
7934
+ import { useEffect as useEffect72 } from "react";
7935
+ import { jsx as jsx372 } from "react/jsx-runtime";
7936
+ import { jsx as jsx382, jsxs as jsxs202 } from "react/jsx-runtime";
7937
+ import { useCallback as useCallback82, useRef as useRef72, useState as useState112, useEffect as useEffect82 } from "react";
7938
+ import { useState as useState222 } from "react";
7939
+ import { useCallback as useCallback92, useEffect as useEffect92, useMemo as useMemo82, useRef as useRef82, useState as useState122 } from "react";
7940
+ import { jsx as jsx392, jsxs as jsxs212 } from "react/jsx-runtime";
7941
+ import { useCallback as useCallback222, useEffect as useEffect222, useMemo as useMemo222, useRef as useRef222, useState as useState322 } from "react";
7942
+ import { jsx as jsx2102, jsxs as jsxs222 } from "react/jsx-runtime";
7943
+ import { useEffect as useEffect102, useMemo as useMemo92, useRef as useRef92 } from "react";
7944
+ var EN_FALLBACK2 = {
7945
+ // TurnCard
7946
+ "turnCard.processing": "Processing",
7947
+ "turnCard.responding": "Responding",
7948
+ "turnCard.stepsCompleted": "Steps completed",
7949
+ "turnCard.starting": "Starting",
7950
+ "turnCard.errorCount": "{{count}} errors",
7951
+ // Common
7952
+ "common.error": "Error",
7953
+ "common.viewFullscreen": "View fullscreen",
7954
+ "common.copy": "Copy",
7955
+ "common.copied": "Copied",
7956
+ "common.editing": "Editing",
7957
+ "common.cancel": "Cancel",
7958
+ "common.done": "Done",
7959
+ "common.failed": "Failed",
7960
+ "common.dismiss": "Dismiss",
7961
+ "common.retry": "Retry",
7962
+ // Chat
7963
+ "chat.branchOptions": "Branch options",
7964
+ "chat.branch": "Branch",
7965
+ "chat.branchFromThisMessage": "Branch from this message",
7966
+ "chat.branchFromThisMessageDescription": "Create a new conversation branch starting from this message",
7967
+ "chat.contextBadge": "Context",
7968
+ "chat.queuedBadge": "Queued",
7969
+ "chat.viewFileChanges": "View file changes",
7970
+ "chat.viewTurnDetails": "View turn details",
7971
+ // Plan
7972
+ "plan.acceptPlan": "Accept plan",
7973
+ "plan.accept": "Accept",
7974
+ "plan.executeImmediately": "Execute immediately",
7975
+ "plan.acceptAndCompact": "Accept & compact",
7976
+ "plan.worksForComplex": "Works well for complex multi-step plans",
7977
+ "plan.acceptAndSendFollowups": "Accept & send follow-ups"
7978
+ };
7979
+ function normalizePath2(path) {
7980
+ return path.replace(/\\/g, "/");
7981
+ }
7982
+ function pathStartsWith2(filePath, dirPath) {
7983
+ const normalizedFile = normalizePath2(filePath);
7984
+ const normalizedDir = normalizePath2(dirPath);
7985
+ return normalizedFile.startsWith(normalizedDir + "/") || normalizedFile === normalizedDir;
7986
+ }
7987
+ function stripPathPrefix2(filePath, prefix) {
7988
+ const normalizedFile = normalizePath2(filePath);
7989
+ const normalizedPrefix = normalizePath2(prefix);
7990
+ if (normalizedFile.startsWith(normalizedPrefix + "/")) {
7991
+ return normalizedFile.slice(normalizedPrefix.length + 1);
7992
+ }
7993
+ return filePath;
7994
+ }
7995
+ function deriveTurnPhase2(turn) {
7996
+ if (turn.isComplete) {
7997
+ return "complete";
7998
+ }
7999
+ if (turn.response && turn.response.isStreaming) {
8000
+ return "streaming";
8001
+ }
8002
+ const hasRunningTools = turn.activities.some((a) => a.type === "tool" && a.status === "running");
8003
+ if (hasRunningTools) {
8004
+ return "tool_active";
8005
+ }
8006
+ if (turn.activities.length > 0) {
8007
+ return "awaiting";
8008
+ }
8009
+ return "pending";
8010
+ }
8011
+ function shouldShowThinkingIndicator2(phase, isBuffering) {
8012
+ return phase === "pending" || phase === "awaiting" || phase === "streaming" && isBuffering;
8013
+ }
8014
+ function computeLastChildSet2(activities) {
8015
+ const lastByParent = /* @__PURE__ */ new Map();
8016
+ for (const activity of activities) {
8017
+ if (activity.depth && activity.depth > 0) {
8018
+ lastByParent.set(activity.parentId, activity.id);
8019
+ }
8020
+ }
8021
+ return new Set(lastByParent.values());
8022
+ }
8023
+ function formatDuration2(ms) {
8024
+ if (!Number.isFinite(ms) || ms < 0) {
8025
+ return "--";
8026
+ }
8027
+ const seconds = ms / 1e3;
8028
+ if (seconds < 60) {
8029
+ return `${seconds.toFixed(1)}s`;
8030
+ }
8031
+ const minutes = Math.floor(seconds / 60);
8032
+ const remainingSeconds = Math.round(seconds % 60);
8033
+ if (minutes >= 2) {
8034
+ return `${minutes}m+`;
8035
+ }
8036
+ return `${minutes}m ${remainingSeconds}s`;
8037
+ }
8038
+ function formatTokens2(count) {
8039
+ if (!Number.isFinite(count) || count < 0) {
8040
+ return "0";
8041
+ }
8042
+ count = Math.floor(count);
8043
+ if (count < 1e3) {
8044
+ return count.toString();
8045
+ }
8046
+ const k = count / 1e3;
8047
+ if (k < 10) {
8048
+ return `${k.toFixed(1)}k`;
8049
+ }
8050
+ return `${Math.round(k)}k`;
8051
+ }
8052
+ var PARENT_TASK_TOOL_NAMES3 = ["Task", "task"];
8053
+ function isParentTaskTool3(toolName) {
8054
+ return PARENT_TASK_TOOL_NAMES3.includes(toolName);
8055
+ }
8056
+ function isActivityGroup2(item) {
8057
+ return "type" in item && item.type === "group" && "parent" in item && "children" in item;
8058
+ }
8059
+ function extractTaskOutputData2(activity) {
8060
+ if (!activity.content) return void 0;
8061
+ try {
8062
+ const parsed = JSON.parse(activity.content);
8063
+ const data = {};
8064
+ if (typeof parsed.duration_ms === "number") {
8065
+ data.durationMs = parsed.duration_ms;
8066
+ }
8067
+ if (parsed.usage) {
8068
+ if (typeof parsed.usage.input_tokens === "number") {
8069
+ data.inputTokens = parsed.usage.input_tokens;
8070
+ }
8071
+ if (typeof parsed.usage.output_tokens === "number") {
8072
+ data.outputTokens = parsed.usage.output_tokens;
8073
+ }
8074
+ }
8075
+ if (data.durationMs !== void 0 || data.inputTokens !== void 0 || data.outputTokens !== void 0) {
8076
+ return data;
8077
+ }
8078
+ } catch {
8079
+ }
8080
+ return void 0;
8081
+ }
8082
+ function groupActivitiesByParent2(activities) {
8083
+ const taskToolUseIds = /* @__PURE__ */ new Set();
8084
+ for (const activity of activities) {
8085
+ if (isParentTaskTool3(activity.toolName ?? "") && activity.toolUseId) {
8086
+ taskToolUseIds.add(activity.toolUseId);
8087
+ }
8088
+ }
8089
+ const childrenByParent = /* @__PURE__ */ new Map();
8090
+ for (const activity of activities) {
8091
+ if (activity.parentId && taskToolUseIds.has(activity.parentId)) {
8092
+ const existing = childrenByParent.get(activity.parentId) || [];
8093
+ existing.push(activity);
8094
+ childrenByParent.set(activity.parentId, existing);
8095
+ }
8096
+ }
8097
+ const childIds = /* @__PURE__ */ new Set();
8098
+ for (const children of childrenByParent.values()) {
8099
+ for (const child of children) {
8100
+ childIds.add(child.id);
8101
+ }
8102
+ }
8103
+ const taskOutputByAgentId = /* @__PURE__ */ new Map();
8104
+ for (const activity of activities) {
8105
+ if (activity.toolName === "TaskOutput" && activity.status === "completed") {
8106
+ const taskId = activity.toolInput?.task_id;
8107
+ if (taskId) {
8108
+ const data = extractTaskOutputData2(activity);
8109
+ if (data) {
8110
+ taskOutputByAgentId.set(taskId, data);
8111
+ }
8112
+ }
8113
+ }
8114
+ }
8115
+ const taskToAgentId = /* @__PURE__ */ new Map();
8116
+ for (const activity of activities) {
8117
+ if (isParentTaskTool3(activity.toolName ?? "") && (activity.status === "completed" || activity.status === "backgrounded") && activity.content) {
8118
+ const agentIdMatch = activity.content.match(/agentId:\s*([a-zA-Z0-9_-]+)/);
8119
+ const capturedAgentId = agentIdMatch?.[1];
8120
+ if (capturedAgentId && activity.toolUseId) {
8121
+ taskToAgentId.set(activity.toolUseId, capturedAgentId);
8122
+ }
8123
+ }
8124
+ }
8125
+ const result = [];
8126
+ for (const activity of activities) {
8127
+ if (childIds.has(activity.id)) {
8128
+ continue;
8129
+ }
8130
+ if (activity.toolName === "TaskOutput") {
8131
+ continue;
8132
+ }
8133
+ if (isParentTaskTool3(activity.toolName ?? "")) {
8134
+ const children = activity.toolUseId ? childrenByParent.get(activity.toolUseId) || [] : [];
8135
+ let taskOutputData;
8136
+ if (activity.toolUseId) {
8137
+ const agentId = taskToAgentId.get(activity.toolUseId);
8138
+ if (agentId) {
8139
+ taskOutputData = taskOutputByAgentId.get(agentId);
8140
+ }
8141
+ }
8142
+ result.push({
8143
+ type: "group",
8144
+ parent: activity,
8145
+ children: children.sort((a, b) => a.timestamp - b.timestamp),
8146
+ taskOutputData
8147
+ });
8148
+ } else {
8149
+ result.push(activity);
8150
+ }
8151
+ }
8152
+ return result;
8153
+ }
8154
+ function asRecord2(value) {
8155
+ return value && typeof value === "object" && !Array.isArray(value) ? value : null;
8156
+ }
8157
+ function normalizeFollowUpText2(text) {
8158
+ return text.replace(/\s+/g, " ").trim();
8159
+ }
8160
+ function getAnnotationNoteText2(annotation) {
8161
+ const noteBody = annotation.body.find((body) => body.type === "note");
8162
+ const bodyText = noteBody?.text?.trim() ?? "";
8163
+ if (bodyText.length > 0) return bodyText;
8164
+ const followUpMeta = asRecord2(asRecord2(annotation.meta)?.followUp);
8165
+ const metaText = typeof followUpMeta?.text === "string" ? followUpMeta.text.trim() : "";
8166
+ return metaText;
8167
+ }
8168
+ function formatAnnotationFollowUpTooltipText2(annotation, maxLength = 180) {
8169
+ const note = normalizeFollowUpText2(getAnnotationNoteText2(annotation));
8170
+ if (!note) return "";
8171
+ return note.length > maxLength ? `${note.slice(0, maxLength - 1).trimEnd()}\u2026` : note;
8172
+ }
8173
+ function extractAnnotationSelectedText2(annotation, messageContent) {
8174
+ const quoteSelector = annotation.target.selectors.find(
8175
+ (selector) => selector.type === "text-quote"
8176
+ );
8177
+ const quoteText = quoteSelector?.exact?.trim() ?? "";
8178
+ if (quoteText.length > 0) return quoteText;
8179
+ const positionSelector = annotation.target.selectors.find(
8180
+ (selector) => selector.type === "text-position"
8181
+ );
8182
+ if (positionSelector) {
8183
+ const start = Math.max(0, Math.min(positionSelector.start, messageContent.length));
8184
+ const end = Math.max(start, Math.min(positionSelector.end, messageContent.length));
8185
+ const slice = messageContent.slice(start, end).trim();
8186
+ if (slice.length > 0) return slice;
8187
+ }
8188
+ return "Selected text";
8189
+ }
8190
+ function cn2(...classes) {
8191
+ return classes.filter(Boolean).join(" ");
8192
+ }
8193
+ function Spinner2({ className }) {
8194
+ return /* @__PURE__ */ jsxs23(
8195
+ "svg",
8196
+ {
8197
+ className: cn2("animate-spin h-4 w-4 text-muted-foreground", className),
8198
+ viewBox: "0 0 24 24",
8199
+ fill: "none",
8200
+ children: [
8201
+ /* @__PURE__ */ jsx40(
8202
+ "circle",
8203
+ {
8204
+ className: "opacity-25",
8205
+ cx: "12",
8206
+ cy: "12",
8207
+ r: "10",
8208
+ stroke: "currentColor",
8209
+ strokeWidth: "4"
8210
+ }
8211
+ ),
8212
+ /* @__PURE__ */ jsx40(
8213
+ "path",
8214
+ {
8215
+ className: "opacity-75",
8216
+ fill: "currentColor",
8217
+ 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"
8218
+ }
8219
+ )
8220
+ ]
8221
+ }
8222
+ );
8223
+ }
8224
+ function SimpleDropdown2({
8225
+ align = "start",
8226
+ onOpenChange,
8227
+ trigger,
8228
+ children
8229
+ }) {
8230
+ const [isOpen, setIsOpen] = React11.useState(false);
8231
+ const handleToggle = () => {
8232
+ const next = !isOpen;
8233
+ setIsOpen(next);
8234
+ onOpenChange?.(next);
8235
+ };
8236
+ const handleClose = () => {
8237
+ setIsOpen(false);
8238
+ onOpenChange?.(false);
8239
+ };
8240
+ return /* @__PURE__ */ jsxs24("div", { className: "relative inline-flex", children: [
8241
+ /* @__PURE__ */ jsx211("div", { onClick: handleToggle, children: trigger }),
8242
+ isOpen && /* @__PURE__ */ jsx211(
8243
+ "div",
8244
+ {
8245
+ className: cn2(
8246
+ "absolute z-50 min-w-[160px] p-1",
8247
+ "bg-background rounded-[8px] shadow-strong border border-border/50",
8248
+ align === "end" ? "right-0" : "left-0",
8249
+ "top-full mt-1"
8250
+ ),
8251
+ onClick: handleClose,
8252
+ children
8253
+ }
8254
+ )
8255
+ ] });
8256
+ }
8257
+ function SimpleDropdownItem2({
8258
+ onClick,
8259
+ icon,
8260
+ children,
8261
+ className
8262
+ }) {
8263
+ return /* @__PURE__ */ jsxs24(
8264
+ "button",
8265
+ {
8266
+ type: "button",
8267
+ onClick,
8268
+ className: cn2(
8269
+ "flex items-center gap-2 w-full px-2 py-1.5 text-left rounded-[6px]",
8270
+ "hover:bg-foreground/[0.05] focus:bg-foreground/[0.05]",
8271
+ "text-sm transition-colors",
8272
+ className
8273
+ ),
8274
+ children: [
8275
+ icon && /* @__PURE__ */ jsx211("span", { className: "shrink-0", children: icon }),
8276
+ /* @__PURE__ */ jsx211("span", { children })
8277
+ ]
8278
+ }
8279
+ );
8280
+ }
8281
+ function TurnCardActionsMenu2({
8282
+ onOpenDetails,
8283
+ onOpenMultiFileDiff,
8284
+ hasEditOrWriteActivities,
8285
+ className
8286
+ }) {
8287
+ const { t: t22 } = useTranslation6();
8288
+ const [isOpen, setIsOpen] = React22.useState(false);
8289
+ if (!onOpenDetails && !onOpenMultiFileDiff) {
8290
+ return null;
8291
+ }
8292
+ return /* @__PURE__ */ jsxs32(
8293
+ SimpleDropdown2,
8294
+ {
8295
+ align: "end",
8296
+ onOpenChange: setIsOpen,
8297
+ trigger: /* @__PURE__ */ jsx310(
8298
+ "div",
8299
+ {
8300
+ role: "button",
8301
+ tabIndex: 0,
8302
+ className: cn2(
8303
+ "p-1 rounded-[6px] transition-opacity shrink-0",
8304
+ "opacity-0 group-hover:opacity-100",
8305
+ "bg-background shadow-minimal",
8306
+ "text-muted-foreground/50 hover:text-foreground",
8307
+ "focus:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:opacity-100",
8308
+ isOpen && "opacity-100 text-foreground",
8309
+ className
8310
+ ),
8311
+ onKeyDown: (e) => {
8312
+ if (e.key === "Enter" || e.key === " ") {
8313
+ e.preventDefault();
8314
+ }
8315
+ },
8316
+ children: /* @__PURE__ */ jsx310(MoreHorizontal2, { className: "w-3 h-3" })
8317
+ }
8318
+ ),
8319
+ children: [
8320
+ onOpenMultiFileDiff && hasEditOrWriteActivities && /* @__PURE__ */ jsx310(
8321
+ SimpleDropdownItem2,
8322
+ {
8323
+ onClick: onOpenMultiFileDiff,
8324
+ icon: /* @__PURE__ */ jsx310(FileDiff2, {}),
8325
+ children: t22("chat.viewFileChanges")
8326
+ }
8327
+ ),
8328
+ onOpenDetails && /* @__PURE__ */ jsx310(
8329
+ SimpleDropdownItem2,
8330
+ {
8331
+ onClick: onOpenDetails,
8332
+ icon: /* @__PURE__ */ jsx310(ArrowUpRight3, {}),
8333
+ children: t22("chat.viewTurnDetails")
8334
+ }
8335
+ )
8336
+ ]
8337
+ }
8338
+ );
8339
+ }
8340
+ function splitComparableLines2(value) {
8341
+ if (!value) return [];
8342
+ const lines = value.split(/\r?\n/);
8343
+ if (lines.length > 0 && lines[lines.length - 1] === "") {
8344
+ lines.pop();
8345
+ }
8346
+ return lines;
8347
+ }
8348
+ function lcsLength2(a, b) {
8349
+ if (a.length === 0 || b.length === 0) return 0;
8350
+ const previous = new Array(b.length + 1).fill(0);
8351
+ const current = new Array(b.length + 1).fill(0);
8352
+ for (let i = 1; i <= a.length; i += 1) {
8353
+ for (let j = 1; j <= b.length; j += 1) {
8354
+ current[j] = a[i - 1] === b[j - 1] ? previous[j - 1] + 1 : Math.max(previous[j], current[j - 1]);
8355
+ }
8356
+ previous.splice(0, previous.length, ...current);
8357
+ current.fill(0);
8358
+ }
8359
+ return previous[b.length] ?? 0;
8360
+ }
8361
+ function getTextDiffStats2(oldText, newText) {
8362
+ const oldLines = splitComparableLines2(oldText);
8363
+ const newLines = splitComparableLines2(newText);
8364
+ const common = lcsLength2(oldLines, newLines);
8365
+ return {
8366
+ additions: Math.max(0, newLines.length - common),
8367
+ deletions: Math.max(0, oldLines.length - common)
8368
+ };
8369
+ }
8370
+ function getUnifiedDiffStats2(_diff, _path) {
8371
+ let additions = 0;
8372
+ let deletions = 0;
8373
+ let files = 0;
8374
+ for (const line of _diff.split(/\r?\n/)) {
8375
+ if (line.startsWith("diff --git ") || line.startsWith("+++ ")) {
8376
+ files += 1;
8377
+ continue;
8378
+ }
8379
+ if (line.startsWith("+++") || line.startsWith("---") || line.startsWith("@@")) {
8380
+ continue;
8381
+ }
8382
+ if (line.startsWith("+")) additions += 1;
8383
+ if (line.startsWith("-")) deletions += 1;
8384
+ }
8385
+ return { added: additions, removed: deletions, additions, deletions, files };
8386
+ }
8387
+ function t2(key, options) {
8388
+ const result = i18n3.t(key, options);
8389
+ if (!result || result === key) {
8390
+ const fallback = EN_FALLBACK2[key];
8391
+ if (!fallback) return key;
8392
+ if (options) {
8393
+ return fallback.replace(/\{\{(\w+)\}\}/g, (_, k) => String(options[k] ?? ""));
8394
+ }
8395
+ return fallback;
8396
+ }
8397
+ return result;
8398
+ }
8399
+ function stripMarkdown2(text) {
8400
+ return text.replace(/```(?:\w+)?\n?([\s\S]*?)```/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/^#{1,6}\s+/gm, "").replace(/\*\*([^*]+)\*\*/g, "$1").replace(/\*([^*]+)\*/g, "$1").replace(/__([^_]+)__/g, "$1").replace(/_([^_]+)_/g, "$1").replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/!\[[^\]]*\]\([^)]+\)/g, "").replace(/^>\s+/gm, "").replace(/^---+$/gm, "").replace(/\s+/g, " ").trim();
8401
+ }
8402
+ function computeEditWriteDiffStats2(toolName, toolInput) {
8403
+ if (!toolInput) return null;
8404
+ if (toolName === "Edit") {
8405
+ if (toolInput.changes && Array.isArray(toolInput.changes)) {
8406
+ let totalAdditions = 0;
8407
+ let totalDeletions = 0;
8408
+ for (const change of toolInput.changes) {
8409
+ if (change.diff) {
8410
+ const stats2 = getUnifiedDiffStats2(change.diff, change.path || "file");
8411
+ if (stats2) {
8412
+ totalAdditions += stats2.additions;
8413
+ totalDeletions += stats2.deletions;
8414
+ }
8415
+ }
8416
+ }
8417
+ if (totalAdditions === 0 && totalDeletions === 0) return null;
8418
+ return { additions: totalAdditions, deletions: totalDeletions };
8419
+ }
8420
+ const oldString = toolInput.old_string ?? "";
8421
+ const newString = toolInput.new_string ?? "";
8422
+ if (!oldString && !newString) return null;
8423
+ const stats = getTextDiffStats2(oldString, newString);
8424
+ if (stats.additions === 0 && stats.deletions === 0) return null;
8425
+ return stats;
8426
+ }
8427
+ if (toolName === "Write") {
8428
+ const content = toolInput.content ?? "";
8429
+ if (!content) return null;
8430
+ return getTextDiffStats2("", content);
8431
+ }
8432
+ return null;
8433
+ }
8434
+ var SIZE_CONFIG2 = {
8435
+ /** Base font size class for all text */
8436
+ fontSize: "text-[13px]",
8437
+ /** Icon size class (width and height) */
8438
+ iconSize: "w-3 h-3",
8439
+ /** Spinner text size class */
8440
+ spinnerSize: "text-[10px]",
8441
+ /** Small spinner for header */
8442
+ spinnerSizeSmall: "text-[8px]",
8443
+ /** Activity row height in pixels (approx for calculation) */
8444
+ activityRowHeight: 24,
8445
+ /** Max visible activities before scrolling (show ~15 items) */
8446
+ maxVisibleActivities: 15,
8447
+ /** Number of items before which we apply staggered animation */
8448
+ staggeredAnimationLimit: 10
8449
+ };
8450
+ var BUFFER_CONFIG2 = {
8451
+ MIN_WORDS_STANDARD: 1,
8452
+ // Base threshold for showing content
8453
+ MIN_WORDS_CODE: 15,
8454
+ // Code blocks show faster
8455
+ MIN_WORDS_LIST: 20,
8456
+ // Lists show faster
8457
+ MIN_WORDS_QUESTION: 8,
8458
+ // Questions from AI show faster
8459
+ MIN_WORDS_HEADER: 12,
8460
+ // Headers indicate structure
8461
+ MIN_BUFFER_MS: 0,
8462
+ // Show the first non-empty delta immediately
8463
+ MAX_BUFFER_MS: 800,
8464
+ // Keep fallback short if markdown structure is ambiguous
8465
+ TIMEOUT_MIN_WORDS: 1,
8466
+ // Show on timeout if at least this many words
8467
+ HIGH_WORD_COUNT: 60,
8468
+ // Show regardless of structure at this count
8469
+ CONTENT_THROTTLE_MS: 60
8470
+ // Light throttle while preserving live streaming feel
8471
+ };
8472
+ function countWords2(text) {
8473
+ return text.trim().split(/\s+/).filter((w) => w.length > 0).length;
8474
+ }
8475
+ function hasCodeBlock2(text) {
8476
+ return /```/.test(text);
8477
+ }
8478
+ function hasList2(text) {
8479
+ return /^\s*[-*•]\s/m.test(text) || /^\s*\d+\.\s/m.test(text);
8480
+ }
8481
+ function hasHeader2(text) {
8482
+ return /^#{1,4}\s/m.test(text);
8483
+ }
8484
+ function hasStructure2(text) {
8485
+ if (/[.!?:]\s*$/.test(text.trimEnd())) return true;
8486
+ if (/\n\s*\n/.test(text)) return true;
8487
+ if (/\n\s*#{1,4}\s/.test(text)) return true;
8488
+ if (hasCodeBlock2(text)) return true;
8489
+ return false;
8490
+ }
8491
+ function isQuestion2(text) {
8492
+ return /\?\s*$/.test(text.trim());
8493
+ }
8494
+ function shouldShowStreamingContent2(text, isStreaming, streamStartTime) {
8495
+ const wordCount = countWords2(text);
8496
+ if (!isStreaming) {
8497
+ return { shouldShow: true, reason: "complete", wordCount };
8498
+ }
8499
+ if (text.trim().length > 0) {
8500
+ return { shouldShow: true, reason: "threshold_met", wordCount };
8501
+ }
8502
+ const elapsed = streamStartTime ? Date.now() - streamStartTime : 0;
8503
+ if (elapsed < BUFFER_CONFIG2.MIN_BUFFER_MS) {
8504
+ return { shouldShow: false, reason: "min_time", wordCount };
8505
+ }
8506
+ if (elapsed > BUFFER_CONFIG2.MAX_BUFFER_MS && wordCount >= BUFFER_CONFIG2.TIMEOUT_MIN_WORDS) {
8507
+ return { shouldShow: true, reason: "timeout", wordCount };
8508
+ }
8509
+ if (hasCodeBlock2(text) && wordCount >= BUFFER_CONFIG2.MIN_WORDS_CODE) {
8510
+ return { shouldShow: true, reason: "code_block", wordCount };
8511
+ }
8512
+ if (hasHeader2(text) && wordCount >= BUFFER_CONFIG2.MIN_WORDS_HEADER) {
8513
+ return { shouldShow: true, reason: "header", wordCount };
8514
+ }
8515
+ if (hasList2(text) && wordCount >= BUFFER_CONFIG2.MIN_WORDS_LIST) {
8516
+ return { shouldShow: true, reason: "list", wordCount };
8517
+ }
8518
+ if (isQuestion2(text) && wordCount >= BUFFER_CONFIG2.MIN_WORDS_QUESTION) {
8519
+ return { shouldShow: true, reason: "question", wordCount };
8520
+ }
8521
+ if (wordCount >= BUFFER_CONFIG2.MIN_WORDS_STANDARD && hasStructure2(text)) {
8522
+ return { shouldShow: true, reason: "threshold_met", wordCount };
8523
+ }
8524
+ if (wordCount >= BUFFER_CONFIG2.HIGH_WORD_COUNT) {
8525
+ return { shouldShow: true, reason: "high_word_count", wordCount };
8526
+ }
8527
+ return { shouldShow: false, reason: "buffering", wordCount };
8528
+ }
8529
+ function isResponseBuffering2(response) {
8530
+ if (!response) return false;
8531
+ if (!response.isStreaming) return false;
8532
+ const decision = shouldShowStreamingContent2(response.text, response.isStreaming, response.streamStartTime);
8533
+ return !decision.shouldShow;
8534
+ }
8535
+ function getToolDisplayName2(name) {
8536
+ const stripped = name.replace(/^mcp__[^_]+__/, "");
8537
+ const displayNames = {
8538
+ "TodoWrite": "Todo List Updated",
8539
+ "set_session_labels": "Set Session Labels",
8540
+ "set_session_status": "Set Session Status",
8541
+ "get_session_info": "Get Session Info",
8542
+ "list_sessions": "List Sessions"
8543
+ };
8544
+ return displayNames[stripped] || stripped;
8545
+ }
8546
+ function stripSessionFolderPath2(filePath, sessionFolderPath) {
8547
+ if (!sessionFolderPath) return filePath;
8548
+ const workspacePath = normalizePath2(sessionFolderPath).replace(/\/sessions\/[^/]+$/, "");
8549
+ if (pathStartsWith2(filePath, sessionFolderPath)) {
8550
+ return stripPathPrefix2(filePath, sessionFolderPath);
8551
+ }
8552
+ if (pathStartsWith2(filePath, workspacePath)) {
8553
+ return stripPathPrefix2(filePath, workspacePath);
8554
+ }
8555
+ return filePath;
8556
+ }
8557
+ function formatToolInput2(input, toolName, sessionFolderPath) {
8558
+ if (!input || Object.keys(input).length === 0) return "";
8559
+ if (toolName === "mcp__session__call_llm") return "";
8560
+ const parts = [];
8561
+ const isEditOrWrite = toolName === "Edit" || toolName === "Write";
8562
+ if (isEditOrWrite && input.changes && Array.isArray(input.changes)) {
8563
+ const firstChange = input.changes[0];
8564
+ if (firstChange?.path) {
8565
+ const pathStr = stripSessionFolderPath2(firstChange.path, sessionFolderPath);
8566
+ parts.push(pathStr);
8567
+ }
8568
+ return parts.join(" ");
8569
+ }
8570
+ for (const [key, value] of Object.entries(input)) {
8571
+ if (key === "_intent" || key === "description" || value === void 0 || value === null) continue;
8572
+ if (isEditOrWrite && key !== "file_path") continue;
8573
+ let valStr = typeof value === "string" ? value.replace(/\s+/g, " ").trim() : JSON.stringify(value);
8574
+ if (isEditOrWrite && key === "file_path" && typeof value === "string") {
8575
+ valStr = stripSessionFolderPath2(valStr, sessionFolderPath);
8576
+ }
8577
+ parts.push(valStr);
8578
+ if (parts.length >= 2) break;
8579
+ }
8580
+ return parts.join(" ");
8581
+ }
8582
+ function extractActionFromDisplayName2(iconName, llmName) {
8583
+ if (llmName.toLowerCase().startsWith(iconName.toLowerCase() + " ")) {
8584
+ return llmName.slice(iconName.length + 1).trim();
8585
+ }
8586
+ return llmName;
8587
+ }
8588
+ function formatToolDisplay2(activity) {
8589
+ const { toolName, displayName, toolInput, toolDisplayMeta } = activity;
8590
+ if (toolDisplayMeta) {
8591
+ if (toolName?.startsWith("mcp__") && toolDisplayMeta.category === "source") {
8592
+ const parts = toolName.match(/^mcp__([^_]+)__(.+)$/);
8593
+ if (parts) {
8594
+ const toolSlug = parts[2];
8595
+ return {
8596
+ name: `${toolDisplayMeta.displayName}: ${toolSlug}`,
8597
+ icon: toolDisplayMeta.iconDataUrl,
8598
+ description: toolDisplayMeta.description
8599
+ };
8600
+ }
8601
+ }
8602
+ if (toolName === "Bash" && displayName) {
8603
+ const iconName = toolDisplayMeta.displayName;
8604
+ const action = extractActionFromDisplayName2(iconName, displayName);
8605
+ return {
8606
+ name: iconName.toLowerCase() === "terminal" ? action : `${iconName}: ${action}`,
8607
+ icon: toolDisplayMeta.iconDataUrl,
8608
+ description: toolDisplayMeta.description
8609
+ };
8610
+ }
8611
+ if (displayName && toolDisplayMeta.category === "native") {
8612
+ return {
8613
+ name: displayName,
8614
+ icon: toolDisplayMeta.iconDataUrl,
8615
+ description: toolDisplayMeta.description
8616
+ };
8617
+ }
8618
+ return {
8619
+ name: toolDisplayMeta.displayName,
8620
+ icon: toolDisplayMeta.iconDataUrl,
8621
+ description: toolDisplayMeta.description
8622
+ };
8623
+ }
8624
+ if (toolName === "Skill" && toolInput?.skill) {
8625
+ const skillId = String(toolInput.skill);
8626
+ const colonIdx = skillId.indexOf(":");
8627
+ const slug = colonIdx > 0 ? skillId.slice(colonIdx + 1) : skillId;
8628
+ return { name: slug };
8629
+ }
8630
+ const name = displayName || (toolName ? getToolDisplayName2(toolName) : t2("turnCard.processing"));
8631
+ return { name };
8632
+ }
8633
+ function getPreviewText2(activities, intent, isStreaming, hasResponse, isComplete) {
8634
+ if (intent) return intent;
8635
+ const activityWithIntent = activities.find((a) => a.intent);
8636
+ if (activityWithIntent?.intent) return activityWithIntent.intent;
8637
+ if (isStreaming && hasResponse) return t2("turnCard.responding");
8638
+ const runningTask = activities.find((a) => a.toolName === "Task" && a.status === "running");
8639
+ if (runningTask?.toolInput?.description) {
8640
+ return runningTask.toolInput.description;
8641
+ }
8642
+ if (isStreaming && !isComplete) {
8643
+ const latestIntermediate = [...activities].reverse().find((a) => a.type === "intermediate" && a.content);
8644
+ if (latestIntermediate?.content) {
8645
+ return latestIntermediate.content;
8646
+ }
8647
+ }
8648
+ const runningTools = activities.filter((a) => a.status === "running" && a.toolName);
8649
+ const errorCount = activities.filter((a) => a.status === "error").length;
8650
+ if (runningTools.length > 0) {
8651
+ const toolNames = runningTools.map((a) => getToolDisplayName2(a.toolName)).slice(0, 3);
8652
+ return `${toolNames.join(", ")}...`;
8653
+ }
8654
+ const firstTask = activities.find((a) => a.toolName === "Task");
8655
+ if (firstTask?.toolInput?.description) {
8656
+ const errorSuffix = errorCount > 0 ? t2("turnCard.errorCount", { count: errorCount }) : "";
8657
+ return `${firstTask.toolInput.description}${errorSuffix}`;
8658
+ }
8659
+ if (isComplete || !isStreaming && activities.length > 0) {
8660
+ const errorSuffix = errorCount > 0 ? t2("turnCard.errorCount", { count: errorCount }) : "";
8661
+ return `${t2("turnCard.stepsCompleted")}${errorSuffix}`;
8662
+ }
8663
+ return t2("turnCard.starting");
8664
+ }
8665
+ function Tooltip2({ children }) {
8666
+ return /* @__PURE__ */ jsx42(Fragment10, { children });
8667
+ }
8668
+ function TooltipTrigger2({
8669
+ children,
8670
+ asChild = false
8671
+ }) {
8672
+ return /* @__PURE__ */ jsx42(Fragment10, { children });
8673
+ }
8674
+ function TooltipContent2({
8675
+ children,
8676
+ side = "top",
8677
+ className
8678
+ }) {
8679
+ return /* @__PURE__ */ jsx42("div", { className: cn2(
8680
+ "px-2 py-1 text-xs rounded bg-foreground text-background",
8681
+ "max-w-xs whitespace-normal",
8682
+ className
8683
+ ), children });
8684
+ }
8685
+ function ActivityStatusIcon2({
8686
+ status,
8687
+ toolName,
8688
+ customIcon
8689
+ }) {
8690
+ const renderIcon = () => {
8691
+ if (status === "completed" && customIcon) {
8692
+ const isLikelyEmoji = customIcon.length <= 8 && !/^(https?:\/\/|data:)/.test(customIcon);
8693
+ if (isLikelyEmoji) {
8694
+ return /* @__PURE__ */ jsx52("span", { className: cn2(SIZE_CONFIG2.iconSize, "shrink-0 flex items-center justify-center text-[10px] leading-none"), children: customIcon });
8695
+ }
8696
+ return /* @__PURE__ */ jsx52(
8697
+ "img",
8698
+ {
8699
+ src: customIcon,
8700
+ alt: "",
8701
+ className: cn2(SIZE_CONFIG2.iconSize, "shrink-0 rounded-sm object-contain")
8702
+ }
8703
+ );
8704
+ }
8705
+ switch (status) {
8706
+ case "pending":
8707
+ return /* @__PURE__ */ jsx52(Circle3, { className: cn2(SIZE_CONFIG2.iconSize, "shrink-0 text-muted-foreground/50") });
8708
+ case "running":
8709
+ return /* @__PURE__ */ jsx52("div", { className: cn2(SIZE_CONFIG2.iconSize, "flex items-center justify-center shrink-0"), children: /* @__PURE__ */ jsx52(Spinner2, { className: SIZE_CONFIG2.spinnerSize }) });
8710
+ case "backgrounded":
8711
+ return /* @__PURE__ */ jsx52("div", { className: cn2(SIZE_CONFIG2.iconSize, "flex items-center justify-center shrink-0"), children: /* @__PURE__ */ jsx52(Spinner2, { className: cn2(SIZE_CONFIG2.spinnerSize, "text-accent") }) });
8712
+ case "completed":
8713
+ if (toolName === "Edit") {
8714
+ return /* @__PURE__ */ jsx52(Pencil2, { className: cn2(SIZE_CONFIG2.iconSize, "shrink-0 text-accent") });
8715
+ }
8716
+ if (toolName === "Write") {
8717
+ return /* @__PURE__ */ jsx52(FilePenLine2, { className: cn2(SIZE_CONFIG2.iconSize, "shrink-0 text-accent") });
8718
+ }
8719
+ return /* @__PURE__ */ jsx52(CheckCircle23, { className: cn2(SIZE_CONFIG2.iconSize, "shrink-0 text-success") });
8720
+ case "error":
8721
+ return /* @__PURE__ */ jsx52(XCircle3, { className: cn2(SIZE_CONFIG2.iconSize, "shrink-0 text-destructive") });
8722
+ }
8723
+ };
8724
+ return /* @__PURE__ */ jsx52(AnimatePresence4, { mode: "wait", initial: false, children: /* @__PURE__ */ jsx52(
8725
+ motion5.div,
8726
+ {
8727
+ initial: { opacity: 0, scale: 0.8 },
8728
+ animate: { opacity: 1, scale: 1 },
8729
+ exit: { opacity: 0, scale: 0.8 },
8730
+ transition: { duration: 0.2, ease: "easeOut" },
8731
+ className: "shrink-0",
8732
+ children: renderIcon()
8733
+ },
8734
+ status
8735
+ ) });
8736
+ }
8737
+ function TreeViewConnector2({ depth }) {
8738
+ if (depth === 0) return null;
8739
+ return /* @__PURE__ */ jsx52("div", { className: "flex self-stretch", children: Array.from({ length: depth }).map((_, i) => /* @__PURE__ */ jsx52("div", { className: "w-4 shrink-0" }, i)) });
8740
+ }
8741
+ function ActivityRow2({ activity, onOpenDetails, isLastChild, sessionFolderPath, displayMode = "detailed" }) {
8742
+ const depth = activity.depth || 0;
8743
+ if (activity.type === "intermediate") {
8744
+ const isThinking = activity.status === "running";
8745
+ const displayContent = isThinking ? "Thinking..." : stripMarkdown2(activity.content || "");
8746
+ const isComplete2 = activity.status === "completed";
8747
+ return /* @__PURE__ */ jsxs42("div", { className: "flex items-stretch", children: [
8748
+ /* @__PURE__ */ jsx52(TreeViewConnector2, { depth, isLastChild }),
8749
+ /* @__PURE__ */ jsxs42(
8750
+ "div",
8751
+ {
8752
+ className: cn2(
8753
+ "group/row flex items-center gap-2 py-0.5 text-foreground/75 flex-1 min-w-0",
8754
+ SIZE_CONFIG2.fontSize
8755
+ ),
8756
+ onClick: onOpenDetails && isComplete2 ? onOpenDetails : void 0,
8757
+ children: [
8758
+ isThinking ? /* @__PURE__ */ jsx52("div", { className: cn2(SIZE_CONFIG2.iconSize, "flex items-center justify-center shrink-0"), children: /* @__PURE__ */ jsx52(Spinner2, { className: SIZE_CONFIG2.spinnerSize }) }) : /* @__PURE__ */ jsx52(MessageCircleDashed2, { className: cn2(SIZE_CONFIG2.iconSize, "shrink-0") }),
8759
+ /* @__PURE__ */ jsx52("span", { className: cn2("truncate flex-1", onOpenDetails && isComplete2 && "group-hover/row:underline"), children: displayContent }),
8760
+ onOpenDetails && isComplete2 && /* @__PURE__ */ jsx52(
8761
+ "div",
8762
+ {
8763
+ role: "button",
8764
+ tabIndex: 0,
8765
+ onClick: (e) => {
8766
+ e.stopPropagation();
8767
+ onOpenDetails();
8768
+ },
8769
+ onKeyDown: (e) => {
8770
+ if (e.key === "Enter" || e.key === " ") {
8771
+ e.stopPropagation();
8772
+ onOpenDetails();
8773
+ }
8774
+ },
8775
+ className: cn2(
8776
+ "p-0.5 rounded-[3px] opacity-0 group-hover/row:opacity-100 transition-opacity shrink-0",
8777
+ "hover:bg-muted/80 focus:outline-none focus-visible:ring-1 focus-visible:ring-ring"
8778
+ ),
8779
+ children: /* @__PURE__ */ jsx52(ArrowUpRight22, { className: SIZE_CONFIG2.iconSize })
8780
+ }
8781
+ )
8782
+ ]
8783
+ }
8784
+ )
8785
+ ] });
8786
+ }
8787
+ if (activity.type === "status") {
8788
+ const isRunning = activity.status === "running";
8789
+ return /* @__PURE__ */ jsxs42("div", { className: "flex items-stretch", children: [
8790
+ /* @__PURE__ */ jsx52(TreeViewConnector2, { depth, isLastChild }),
8791
+ /* @__PURE__ */ jsxs42(
8792
+ "div",
8793
+ {
8794
+ className: cn2(
8795
+ "flex items-center gap-2 py-0.5 text-muted-foreground flex-1 min-w-0",
8796
+ SIZE_CONFIG2.fontSize
8797
+ ),
8798
+ children: [
8799
+ /* @__PURE__ */ jsx52("div", { className: cn2(SIZE_CONFIG2.iconSize, "flex items-center justify-center shrink-0"), children: isRunning ? /* @__PURE__ */ jsx52(Spinner2, { className: SIZE_CONFIG2.spinnerSizeSmall }) : /* @__PURE__ */ jsx52(CheckCircle23, { className: cn2(SIZE_CONFIG2.iconSize, "text-success") }) }),
8800
+ /* @__PURE__ */ jsx52("span", { className: "truncate", children: activity.content })
8801
+ ]
8802
+ }
8803
+ )
8804
+ ] });
8805
+ }
8806
+ const toolDisplay = formatToolDisplay2(activity);
8807
+ const fullDisplayName = toolDisplay.name || (activity.type === "thinking" ? "Thinking" : "Processing");
8808
+ const isMcpOrApiTool = activity.toolName?.startsWith("mcp__") ?? false;
8809
+ let sourceName = fullDisplayName;
8810
+ let toolSlug = void 0;
8811
+ if (isMcpOrApiTool) {
8812
+ const colonIndex = fullDisplayName.indexOf(":");
8813
+ if (colonIndex > 0) {
8814
+ sourceName = fullDisplayName.substring(0, colonIndex).trim();
8815
+ toolSlug = fullDisplayName.substring(colonIndex + 1).trim();
8816
+ }
8817
+ }
8818
+ const displayedName = isMcpOrApiTool ? sourceName : fullDisplayName;
8819
+ const intentOrDescription = activity.intent || activity.toolInput?.description;
8820
+ const inputSummary = formatToolInput2(activity.toolInput, activity.toolName, sessionFolderPath);
8821
+ const diffStats = computeEditWriteDiffStats2(activity.toolName, activity.toolInput);
8822
+ const isComplete = activity.status === "completed" || activity.status === "error";
8823
+ const isBackgrounded = activity.status === "backgrounded";
8824
+ const backgroundInfo = isBackgrounded ? activity.taskId ? `Task ID: ${activity.taskId}${activity.elapsedSeconds ? `, ${formatDuration2(activity.elapsedSeconds * 1e3)} elapsed` : ""}` : activity.shellId ? `Shell ID: ${activity.shellId}${activity.elapsedSeconds ? `, ${formatDuration2(activity.elapsedSeconds * 1e3)} elapsed` : ""}` : null : null;
8825
+ return /* @__PURE__ */ jsxs42("div", { className: "flex items-stretch", children: [
8826
+ /* @__PURE__ */ jsx52(TreeViewConnector2, { depth, isLastChild }),
8827
+ /* @__PURE__ */ jsxs42(
8828
+ "div",
8829
+ {
8830
+ className: cn2(
8831
+ "group/row flex items-center gap-2 py-0.5 text-muted-foreground flex-1 min-w-0",
8832
+ SIZE_CONFIG2.fontSize
8833
+ ),
8834
+ onClick: onOpenDetails && isComplete ? onOpenDetails : void 0,
8835
+ children: [
8836
+ /* @__PURE__ */ jsx52(ActivityStatusIcon2, { status: activity.status, toolName: activity.toolName, customIcon: toolDisplay.icon }),
8837
+ isMcpOrApiTool && !isBackgrounded && /* @__PURE__ */ jsxs42(Fragment22, { children: [
8838
+ /* @__PURE__ */ jsx52("span", { className: "shrink-0", children: sourceName }),
8839
+ activity.status === "error" && activity.error && /* @__PURE__ */ jsxs42(Tooltip2, { children: [
8840
+ /* @__PURE__ */ jsx52(TooltipTrigger2, { asChild: true, children: /* @__PURE__ */ jsx52(
8841
+ "span",
8842
+ {
8843
+ className: "px-1.5 py-0.5 bg-[color-mix(in_oklab,var(--destructive)_4%,var(--background))] shadow-tinted rounded-[4px] text-[10px] text-destructive font-medium cursor-default shrink-0",
8844
+ style: { "--shadow-color": "var(--destructive-rgb)" },
8845
+ children: t2("common.error")
8846
+ }
8847
+ ) }),
8848
+ /* @__PURE__ */ jsx52(TooltipContent2, { side: "top", className: "max-w-[400px]", children: activity.error })
8849
+ ] }),
8850
+ activity.toolName === "mcp__session__call_llm" && activity.toolInput?.model && /* @__PURE__ */ jsx52("span", { className: "px-1.5 py-0.5 bg-background shadow-minimal rounded-[4px] text-[10px] text-foreground/60 shrink-0", children: String(activity.toolInput.model) }),
8851
+ (intentOrDescription || displayMode === "detailed" && (toolSlug || inputSummary)) && /* @__PURE__ */ jsxs42("span", { className: cn2("truncate flex-1 min-w-0", onOpenDetails && isComplete && "group-hover/row:underline"), children: [
8852
+ intentOrDescription && /* @__PURE__ */ jsxs42(Fragment22, { children: [
8853
+ /* @__PURE__ */ jsx52("span", { className: "opacity-60", children: " \xB7 " }),
8854
+ /* @__PURE__ */ jsx52("span", { children: intentOrDescription })
8855
+ ] }),
8856
+ displayMode === "detailed" && toolSlug && /* @__PURE__ */ jsxs42(Fragment22, { children: [
8857
+ /* @__PURE__ */ jsx52("span", { className: "opacity-60", children: " \xB7 " }),
8858
+ /* @__PURE__ */ jsx52("span", { className: "opacity-70", children: toolSlug })
8859
+ ] }),
8860
+ displayMode === "detailed" && inputSummary && /* @__PURE__ */ jsxs42(Fragment22, { children: [
8861
+ /* @__PURE__ */ jsx52("span", { className: "opacity-60", children: " \xB7 " }),
8862
+ /* @__PURE__ */ jsx52("span", { className: "opacity-50", children: inputSummary })
8863
+ ] })
8864
+ ] })
8865
+ ] }),
8866
+ !isMcpOrApiTool && /* @__PURE__ */ jsx52("span", { className: cn2("shrink-0", onOpenDetails && isComplete && "group-hover/row:underline"), children: displayedName }),
8867
+ !isMcpOrApiTool && !isBackgrounded && diffStats && /* @__PURE__ */ jsxs42("span", { className: "flex items-center gap-1.5 text-[10px] shrink-0", children: [
8868
+ diffStats.deletions > 0 && /* @__PURE__ */ jsx52(
8869
+ "span",
8870
+ {
8871
+ className: "px-1.5 py-0.5 bg-[color-mix(in_oklab,var(--destructive)_5%,var(--background))] shadow-tinted rounded-[4px] text-destructive",
8872
+ style: { "--shadow-color": "var(--destructive-rgb)" },
8873
+ children: diffStats.deletions
8874
+ }
8875
+ ),
8876
+ diffStats.additions > 0 && /* @__PURE__ */ jsx52(
8877
+ "span",
8878
+ {
8879
+ className: "px-1.5 py-0.5 bg-[color-mix(in_oklab,var(--success)_5%,var(--background))] shadow-tinted rounded-[4px] text-success",
8880
+ style: { "--shadow-color": "var(--success-rgb)" },
8881
+ children: diffStats.additions
8882
+ }
8883
+ ),
8884
+ (() => {
8885
+ if (typeof activity.toolInput?.file_path === "string") {
8886
+ return /* @__PURE__ */ jsx52("span", { className: "px-1.5 py-0.5 bg-background shadow-minimal rounded-[4px] text-[11px] text-foreground/70", children: normalizePath2(activity.toolInput.file_path).split("/").pop() });
8887
+ }
8888
+ if (Array.isArray(activity.toolInput?.changes)) {
8889
+ const firstChange = activity.toolInput.changes[0];
8890
+ if (firstChange?.path) {
8891
+ return /* @__PURE__ */ jsx52("span", { className: "px-1.5 py-0.5 bg-background shadow-minimal rounded-[4px] text-[11px] text-foreground/70", children: normalizePath2(firstChange.path).split("/").pop() });
8892
+ }
8893
+ }
8894
+ return null;
8895
+ })()
8896
+ ] }),
8897
+ !isMcpOrApiTool && !isBackgrounded && !diffStats && activity.toolName === "Read" && typeof activity.toolInput?.file_path === "string" && /* @__PURE__ */ jsx52("span", { className: "flex items-center gap-1.5 text-[10px] shrink-0", children: /* @__PURE__ */ jsx52("span", { className: "px-1.5 py-0.5 bg-background shadow-minimal rounded-[4px] text-[11px] text-foreground/70", children: normalizePath2(activity.toolInput.file_path).split("/").pop() }) }),
8898
+ !isMcpOrApiTool && activity.status === "error" && activity.error && /* @__PURE__ */ jsxs42(Tooltip2, { children: [
8899
+ /* @__PURE__ */ jsx52(TooltipTrigger2, { asChild: true, children: /* @__PURE__ */ jsx52(
8900
+ "span",
8901
+ {
8902
+ className: "px-1.5 py-0.5 bg-[color-mix(in_oklab,var(--destructive)_4%,var(--background))] shadow-tinted rounded-[4px] text-[10px] text-destructive font-medium cursor-default shrink-0",
8903
+ style: { "--shadow-color": "var(--destructive-rgb)" },
8904
+ children: "Error"
8905
+ }
8906
+ ) }),
8907
+ /* @__PURE__ */ jsx52(TooltipContent2, { side: "top", className: "max-w-[400px]", children: activity.error })
8908
+ ] }),
8909
+ !isMcpOrApiTool && !isBackgrounded && (intentOrDescription || displayMode === "detailed" && inputSummary) && /* @__PURE__ */ jsxs42("span", { className: cn2("truncate flex-1 min-w-0", onOpenDetails && isComplete && "group-hover/row:underline"), children: [
8910
+ intentOrDescription && /* @__PURE__ */ jsxs42(Fragment22, { children: [
8911
+ /* @__PURE__ */ jsx52("span", { className: "opacity-60", children: " \xB7 " }),
8912
+ /* @__PURE__ */ jsx52("span", { children: intentOrDescription })
8913
+ ] }),
8914
+ displayMode === "detailed" && inputSummary && /* @__PURE__ */ jsxs42(Fragment22, { children: [
8915
+ /* @__PURE__ */ jsx52("span", { className: "opacity-60", children: " \xB7 " }),
8916
+ /* @__PURE__ */ jsx52("span", { className: "opacity-50", children: inputSummary })
8917
+ ] })
8918
+ ] }),
8919
+ backgroundInfo && /* @__PURE__ */ jsxs42(Fragment22, { children: [
8920
+ /* @__PURE__ */ jsx52("span", { className: "opacity-60 shrink-0", children: "\xB7" }),
8921
+ /* @__PURE__ */ jsx52("span", { className: "truncate min-w-0 max-w-[300px] text-accent", children: backgroundInfo })
8922
+ ] }),
8923
+ onOpenDetails && isComplete && /* @__PURE__ */ jsx52(
8924
+ "div",
8925
+ {
8926
+ role: "button",
8927
+ tabIndex: 0,
8928
+ onClick: (e) => {
8929
+ e.stopPropagation();
8930
+ onOpenDetails();
8931
+ },
8932
+ onKeyDown: (e) => {
8933
+ if (e.key === "Enter" || e.key === " ") {
8934
+ e.stopPropagation();
8935
+ onOpenDetails();
8936
+ }
8937
+ },
8938
+ className: cn2(
8939
+ "p-0.5 rounded-[3px] opacity-0 group-hover/row:opacity-100 transition-opacity shrink-0",
8940
+ "hover:bg-muted/80 focus:outline-none focus-visible:ring-1 focus-visible:ring-ring"
8941
+ ),
8942
+ children: /* @__PURE__ */ jsx52(ArrowUpRight22, { className: SIZE_CONFIG2.iconSize })
8943
+ }
8944
+ )
8945
+ ]
8946
+ }
8947
+ )
8948
+ ] });
8949
+ }
8950
+ function ActivityGroupRow2({ group, expandedGroups: externalExpandedGroups, onExpandedGroupsChange, onOpenActivityDetails, animationIndex = 0, sessionFolderPath, displayMode = "detailed" }) {
8951
+ const [localExpandedGroups, setLocalExpandedGroups] = useState33(/* @__PURE__ */ new Set());
8952
+ const expandedGroups = externalExpandedGroups ?? localExpandedGroups;
8953
+ const setExpandedGroups = onExpandedGroupsChange ?? setLocalExpandedGroups;
8954
+ const groupId = group.parent.id;
8955
+ const isExpanded = expandedGroups.has(groupId);
8956
+ const toggleExpanded = useCallback10(() => {
8957
+ const next = new Set(expandedGroups);
8958
+ if (next.has(groupId)) {
8959
+ next.delete(groupId);
8960
+ } else {
8961
+ next.add(groupId);
8962
+ }
8963
+ setExpandedGroups(next);
8964
+ }, [groupId, expandedGroups, setExpandedGroups]);
8965
+ const description = group.parent.toolInput?.description;
8966
+ const subagentType = group.parent.toolInput?.subagent_type;
8967
+ const isComplete = group.parent.status === "completed" || group.parent.status === "error";
8968
+ const hasError = group.parent.status === "error";
8969
+ return /* @__PURE__ */ jsxs42(
8970
+ motion5.div,
8971
+ {
8972
+ initial: { opacity: 0, x: -8 },
8973
+ animate: { opacity: 1, x: 0 },
8974
+ transition: { delay: animationIndex < SIZE_CONFIG2.staggeredAnimationLimit ? animationIndex * 0.03 : 0.3 },
8975
+ className: "space-y-0.5",
8976
+ children: [
8977
+ /* @__PURE__ */ jsxs42(
8978
+ "div",
8979
+ {
8980
+ className: cn2(
8981
+ "group/row flex items-center gap-2 py-0.5 rounded-md cursor-pointer text-muted-foreground",
8982
+ "hover:text-foreground transition-colors",
8983
+ SIZE_CONFIG2.fontSize
8984
+ ),
8985
+ onClick: toggleExpanded,
8986
+ children: [
8987
+ /* @__PURE__ */ jsx52(
8988
+ motion5.div,
8989
+ {
8990
+ initial: false,
8991
+ animate: { rotate: isExpanded ? 90 : 0 },
8992
+ transition: { duration: 0.15, ease: "easeOut" },
8993
+ className: cn2(SIZE_CONFIG2.iconSize, "flex items-center justify-center shrink-0"),
8994
+ children: /* @__PURE__ */ jsx52(ChevronRight4, { className: SIZE_CONFIG2.iconSize })
8995
+ }
8996
+ ),
8997
+ /* @__PURE__ */ jsx52(ActivityStatusIcon2, { status: group.parent.status, toolName: group.parent.toolName }),
8998
+ /* @__PURE__ */ jsx52("span", { className: "shrink-0 px-1.5 py-0.5 rounded-[4px] bg-background shadow-minimal text-[10px] font-medium", children: subagentType || "Task" }),
8999
+ /* @__PURE__ */ jsx52("span", { className: cn2(
9000
+ "truncate",
9001
+ hasError && "text-destructive"
9002
+ ), children: description || "Task" }),
9003
+ isComplete && group.taskOutputData && /* @__PURE__ */ jsxs42("span", { className: "shrink-0 text-muted-foreground/60 tabular-nums", children: [
9004
+ group.taskOutputData.durationMs !== void 0 && /* @__PURE__ */ jsx52("span", { children: formatDuration2(group.taskOutputData.durationMs) }),
9005
+ group.taskOutputData.durationMs !== void 0 && (group.taskOutputData.inputTokens !== void 0 || group.taskOutputData.outputTokens !== void 0) && /* @__PURE__ */ jsx52("span", { className: "mx-1", children: "\xB7" }),
9006
+ (group.taskOutputData.inputTokens !== void 0 || group.taskOutputData.outputTokens !== void 0) && /* @__PURE__ */ jsxs42("span", { children: [
9007
+ formatTokens2((group.taskOutputData.inputTokens || 0) + (group.taskOutputData.outputTokens || 0)),
9008
+ " tokens"
9009
+ ] })
9010
+ ] }),
9011
+ /* @__PURE__ */ jsx52("span", { className: "flex-1" }),
9012
+ onOpenActivityDetails && isComplete && /* @__PURE__ */ jsx52(
9013
+ "div",
9014
+ {
9015
+ role: "button",
9016
+ tabIndex: 0,
9017
+ onClick: (e) => {
9018
+ e.stopPropagation();
9019
+ onOpenActivityDetails(group.parent);
9020
+ },
9021
+ onKeyDown: (e) => {
9022
+ if (e.key === "Enter" || e.key === " ") {
9023
+ e.stopPropagation();
9024
+ onOpenActivityDetails(group.parent);
9025
+ }
9026
+ },
9027
+ className: cn2(
9028
+ "p-0.5 rounded-[3px] opacity-0 group-hover/row:opacity-100 transition-opacity shrink-0",
9029
+ "hover:bg-muted/80 focus:outline-none focus-visible:ring-1 focus-visible:ring-ring"
9030
+ ),
9031
+ children: /* @__PURE__ */ jsx52(ArrowUpRight22, { className: SIZE_CONFIG2.iconSize })
9032
+ }
9033
+ )
9034
+ ]
9035
+ }
9036
+ ),
9037
+ /* @__PURE__ */ jsx52(AnimatePresence4, { initial: false, children: isExpanded && group.children.length > 0 && /* @__PURE__ */ jsx52(
9038
+ motion5.div,
9039
+ {
9040
+ initial: { height: 0, opacity: 0 },
9041
+ animate: { height: "auto", opacity: 1 },
9042
+ exit: { height: 0, opacity: 0 },
9043
+ transition: {
9044
+ height: { duration: 0.2, ease: [0.4, 0, 0.2, 1] },
9045
+ opacity: { duration: 0.15 }
9046
+ },
9047
+ className: "overflow-hidden",
9048
+ children: /* @__PURE__ */ jsx52("div", { className: "pl-0 space-y-0.5 border-l-2 border-muted ml-[5px]", children: group.children.map((child, idx) => /* @__PURE__ */ jsx52(
9049
+ motion5.div,
9050
+ {
9051
+ initial: { opacity: 0, x: -4 },
9052
+ animate: { opacity: 1, x: 0 },
9053
+ transition: { delay: idx * 0.02 },
9054
+ className: "ml-[-4px]",
9055
+ children: /* @__PURE__ */ jsx52(
9056
+ ActivityRow2,
9057
+ {
9058
+ activity: child,
9059
+ onOpenDetails: onOpenActivityDetails ? () => onOpenActivityDetails(child) : void 0,
9060
+ isLastChild: idx === group.children.length - 1,
9061
+ sessionFolderPath,
9062
+ displayMode
9063
+ }
9064
+ )
9065
+ },
9066
+ child.id
9067
+ )) })
9068
+ }
9069
+ ) })
9070
+ ]
9071
+ }
9072
+ );
9073
+ }
9074
+ var ShikiThemeContext2 = createContext4(null);
9075
+ function useShikiTheme2() {
9076
+ return useContext4(ShikiThemeContext2);
9077
+ }
9078
+ var LANGUAGE_LOADERS2 = {
9079
+ bash: () => import("@shikijs/langs/bash"),
9080
+ c: () => import("@shikijs/langs/c"),
9081
+ cpp: () => import("@shikijs/langs/cpp"),
9082
+ css: () => import("@shikijs/langs/css"),
9083
+ graphql: () => import("@shikijs/langs/graphql"),
9084
+ html: () => import("@shikijs/langs/html"),
9085
+ java: () => import("@shikijs/langs/java"),
9086
+ javascript: () => import("@shikijs/langs/javascript"),
9087
+ json: () => import("@shikijs/langs/json"),
9088
+ jsx: () => import("@shikijs/langs/jsx"),
9089
+ less: () => import("@shikijs/langs/less"),
9090
+ markdown: () => import("@shikijs/langs/markdown"),
9091
+ php: () => import("@shikijs/langs/php"),
9092
+ python: () => import("@shikijs/langs/python"),
9093
+ scss: () => import("@shikijs/langs/scss"),
9094
+ shell: () => import("@shikijs/langs/shell"),
9095
+ sql: () => import("@shikijs/langs/sql"),
9096
+ svelte: () => import("@shikijs/langs/svelte"),
9097
+ tsx: () => import("@shikijs/langs/tsx"),
9098
+ typescript: () => import("@shikijs/langs/typescript"),
9099
+ vue: () => import("@shikijs/langs/vue"),
9100
+ wasm: () => import("@shikijs/langs/wasm"),
9101
+ yaml: () => import("@shikijs/langs/yaml")
9102
+ };
9103
+ var THEME_LOADERS2 = {
9104
+ "github-dark": () => import("@shikijs/themes/github-dark"),
9105
+ "github-light": () => import("@shikijs/themes/github-light")
9106
+ };
9107
+ var createHighlighter2 = createBundledHighlighter2({
9108
+ langs: LANGUAGE_LOADERS2,
9109
+ themes: THEME_LOADERS2,
9110
+ engine: () => createJavaScriptRegexEngine2()
9111
+ });
9112
+ var { codeToHtml: codeToHtml2 } = createSingletonShorthands2(createHighlighter2);
9113
+ var LANGUAGE_ALIASES2 = {
9114
+ "js": "javascript",
9115
+ "ts": "typescript",
9116
+ "py": "python",
9117
+ "sh": "bash",
9118
+ "zsh": "bash",
9119
+ "yml": "yaml",
9120
+ "gql": "graphql"
9121
+ };
9122
+ var highlightCache2 = /* @__PURE__ */ new Map();
9123
+ var CACHE_MAX_SIZE2 = 200;
9124
+ function getCacheKey2(code, lang, theme) {
9125
+ return `${theme}:${lang}:${code}`;
9126
+ }
9127
+ function isValidLanguage2(lang) {
9128
+ const normalized = LANGUAGE_ALIASES2[lang] || lang;
9129
+ return normalized in LANGUAGE_LOADERS2;
9130
+ }
9131
+ function CodeBlock2({ code, language = "text", className, mode = "full", forcedTheme }) {
9132
+ const [highlighted, setHighlighted] = React32.useState(null);
9133
+ const [isLoading, setIsLoading] = React32.useState(true);
9134
+ const [copied, setCopied] = React32.useState(false);
9135
+ const contextShikiTheme = useShikiTheme2();
9136
+ const langLower = language.toLowerCase();
9137
+ const resolvedLang = LANGUAGE_ALIASES2[langLower] || langLower;
9138
+ React32.useEffect(() => {
9139
+ let cancelled = false;
9140
+ async function highlight() {
9141
+ let theme;
9142
+ if (contextShikiTheme) {
9143
+ theme = contextShikiTheme;
9144
+ } else if (forcedTheme) {
9145
+ theme = forcedTheme === "dark" ? "github-dark" : "github-light";
9146
+ } else {
9147
+ const isDark = document.documentElement.classList.contains("dark");
9148
+ theme = isDark ? "github-dark" : "github-light";
9149
+ }
9150
+ const cacheKey = getCacheKey2(code, resolvedLang, theme);
9151
+ const cached = highlightCache2.get(cacheKey);
9152
+ if (cached) {
9153
+ if (!cancelled) {
9154
+ setHighlighted(cached);
9155
+ setIsLoading(false);
9156
+ }
9157
+ return;
9158
+ }
9159
+ try {
9160
+ const lang = isValidLanguage2(resolvedLang) ? resolvedLang : "text";
9161
+ const html = await codeToHtml2(code, {
9162
+ lang,
9163
+ theme
9164
+ });
9165
+ if (highlightCache2.size >= CACHE_MAX_SIZE2) {
9166
+ const firstKey = highlightCache2.keys().next().value;
9167
+ if (firstKey) highlightCache2.delete(firstKey);
9168
+ }
9169
+ highlightCache2.set(cacheKey, html);
9170
+ if (!cancelled) {
9171
+ setHighlighted(html);
9172
+ setIsLoading(false);
9173
+ }
9174
+ } catch (error) {
9175
+ console.warn(`Shiki highlighting failed for language "${resolvedLang}":`, error);
9176
+ if (!cancelled) {
9177
+ setHighlighted(null);
9178
+ setIsLoading(false);
9179
+ }
9180
+ }
9181
+ }
9182
+ highlight();
9183
+ return () => {
9184
+ cancelled = true;
9185
+ };
9186
+ }, [code, resolvedLang, forcedTheme, contextShikiTheme]);
9187
+ const handleCopy = React32.useCallback(async () => {
9188
+ try {
9189
+ await navigator.clipboard.writeText(code);
9190
+ setCopied(true);
9191
+ setTimeout(() => setCopied(false), 2e3);
9192
+ } catch (err) {
9193
+ console.error("Failed to copy code:", err);
9194
+ }
9195
+ }, [code]);
9196
+ if (mode === "terminal") {
9197
+ return /* @__PURE__ */ jsx72("pre", { className: cn2("font-mono text-sm whitespace-pre-wrap", className), children: /* @__PURE__ */ jsx72("code", { children: code }) });
9198
+ }
9199
+ if (mode === "minimal") {
9200
+ if (isLoading || !highlighted) {
9201
+ return /* @__PURE__ */ jsx72("pre", { className: cn2("font-mono text-sm whitespace-pre-wrap", className), children: /* @__PURE__ */ jsx72("code", { children: code }) });
9202
+ }
9203
+ return /* @__PURE__ */ jsx72(
9204
+ "div",
9205
+ {
9206
+ className: cn2("font-mono text-sm [&_pre]:!bg-transparent [&_pre]:!p-0 [&_pre]:whitespace-pre-wrap [&_pre]:break-all [&_code]:!bg-transparent", className),
9207
+ dangerouslySetInnerHTML: { __html: highlighted }
9208
+ }
9209
+ );
9210
+ }
9211
+ return /* @__PURE__ */ jsxs52("div", { className: cn2("relative group rounded-[8px] overflow-hidden border bg-muted/30", className), children: [
9212
+ /* @__PURE__ */ jsxs52("div", { className: "flex items-center justify-between px-3 py-1.5 bg-muted/50 border-b text-xs", children: [
9213
+ /* @__PURE__ */ jsx72("span", { className: "text-muted-foreground font-medium uppercase tracking-wide", children: resolvedLang !== "text" ? resolvedLang : "plain text" }),
9214
+ /* @__PURE__ */ jsx72(
9215
+ "button",
9216
+ {
9217
+ onClick: handleCopy,
9218
+ className: "opacity-0 group-hover:opacity-100 transition-opacity text-muted-foreground hover:text-foreground",
9219
+ "aria-label": "Copy code",
9220
+ children: copied ? /* @__PURE__ */ jsx72("svg", { className: "w-4 h-4 text-success", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx72("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" }) }) : /* @__PURE__ */ jsx72("svg", { className: "w-4 h-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx72("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z" }) })
9221
+ }
9222
+ )
9223
+ ] }),
9224
+ /* @__PURE__ */ jsx72("div", { className: "p-3 overflow-x-auto", children: isLoading || !highlighted ? /* @__PURE__ */ jsx72("pre", { className: "font-mono text-sm whitespace-pre-wrap break-all", children: /* @__PURE__ */ jsx72("code", { children: code }) }) : /* @__PURE__ */ jsx72(
9225
+ "div",
9226
+ {
9227
+ className: "font-mono text-sm [&_pre]:!bg-transparent [&_pre]:!m-0 [&_pre]:!p-0 [&_pre]:whitespace-pre-wrap [&_pre]:break-all [&_code]:!bg-transparent",
9228
+ dangerouslySetInnerHTML: { __html: highlighted }
9229
+ }
9230
+ ) })
9231
+ ] });
9232
+ }
9233
+ function InlineCode2({ children, className }) {
9234
+ return /* @__PURE__ */ jsx72("code", { className: cn2(
9235
+ "pl-1 pr-1 py-0 rounded bg-foreground/[0.04] font-mono text-[13px]",
9236
+ className
9237
+ ), children });
9238
+ }
9239
+ function getDiffLineKind2(line) {
9240
+ if (line.startsWith("@@")) return "hunk";
9241
+ if (line.startsWith("+++") || line.startsWith("---")) return "file";
9242
+ if (line.startsWith("+")) return "add";
9243
+ if (line.startsWith("-")) return "remove";
9244
+ return "context";
9245
+ }
9246
+ function getLineClass2(kind) {
9247
+ switch (kind) {
9248
+ case "add":
9249
+ return "bg-success/[0.08] text-success";
9250
+ case "remove":
9251
+ return "bg-destructive/[0.08] text-destructive";
9252
+ case "hunk":
9253
+ return "bg-accent/[0.08] text-accent";
9254
+ case "file":
9255
+ return "bg-muted/60 text-muted-foreground";
9256
+ default:
9257
+ return "text-foreground/80";
9258
+ }
9259
+ }
9260
+ function MarkdownDiffBlock2({ code, className }) {
9261
+ const lines = React42.useMemo(() => code.split(/\r?\n/), [code]);
9262
+ return /* @__PURE__ */ jsx82(
9263
+ "pre",
9264
+ {
9265
+ className: cn2(
9266
+ "relative rounded-[8px] overflow-x-auto border bg-muted/30 py-2 text-[13px] leading-relaxed",
9267
+ className
9268
+ ),
9269
+ style: { fontFamily: '"JetBrains Mono", monospace' },
9270
+ children: /* @__PURE__ */ jsx82("code", { children: lines.map((line, index) => {
9271
+ const kind = getDiffLineKind2(line);
9272
+ const sign = line[0] === "+" || line[0] === "-" ? line[0] : " ";
9273
+ return /* @__PURE__ */ jsxs62(
9274
+ "span",
9275
+ {
9276
+ className: cn2("block min-w-max px-3 whitespace-pre", getLineClass2(kind)),
9277
+ children: [
9278
+ /* @__PURE__ */ jsx82("span", { className: "mr-3 inline-block w-3 select-none text-center opacity-70", children: sign }),
9279
+ line || " "
9280
+ ]
9281
+ },
9282
+ `${index}:${line}`
9283
+ );
9284
+ }) })
9285
+ }
9286
+ );
9287
+ }
9288
+ function MarkdownJsonBlock2({ code, className }) {
9289
+ return /* @__PURE__ */ jsx92("pre", { className: cn2("font-mono text-sm whitespace-pre-wrap", className), children: /* @__PURE__ */ jsx92("code", { children: code }) });
9290
+ }
9291
+ function MarkdownMermaidBlock2({ code, className, showExpandButton = true }) {
9292
+ return /* @__PURE__ */ jsx102("pre", { className: cn2("font-mono text-sm whitespace-pre-wrap my-2", className), children: /* @__PURE__ */ jsx102("code", { children: code }) });
9293
+ }
9294
+ function MarkdownDatatableBlock2({ code, className }) {
9295
+ return /* @__PURE__ */ jsx112("pre", { className: cn2("font-mono text-sm whitespace-pre-wrap", className), children: /* @__PURE__ */ jsx112("code", { children: code }) });
9296
+ }
9297
+ function MarkdownSpreadsheetBlock2({ code, className }) {
9298
+ return /* @__PURE__ */ jsx122("pre", { className: cn2("font-mono text-sm whitespace-pre-wrap", className), children: /* @__PURE__ */ jsx122("code", { children: code }) });
9299
+ }
9300
+ function MarkdownHtmlBlock2({ code, className }) {
9301
+ return /* @__PURE__ */ jsx132("pre", { className: cn2("font-mono text-sm whitespace-pre-wrap", className), children: /* @__PURE__ */ jsx132("code", { children: code }) });
9302
+ }
9303
+ function MarkdownImageBlock2({ code, className }) {
9304
+ return /* @__PURE__ */ jsx142("pre", { className: cn2("font-mono text-sm whitespace-pre-wrap", className), children: /* @__PURE__ */ jsx142("code", { children: code }) });
9305
+ }
9306
+ function MarkdownLatexBlock2({ code, className }) {
9307
+ return /* @__PURE__ */ jsx152("pre", { className: cn2("font-mono text-sm whitespace-pre-wrap", className), children: /* @__PURE__ */ jsx152("code", { children: code }) });
9308
+ }
9309
+ function MarkdownPdfBlock2({ code, className }) {
9310
+ return /* @__PURE__ */ jsx162("pre", { className: cn2("font-mono text-sm whitespace-pre-wrap", className), children: /* @__PURE__ */ jsx162("code", { children: code }) });
9311
+ }
9312
+ function preprocessLinks2(content) {
9313
+ return content;
9314
+ }
9315
+ function resolveMarkdownLinkTarget2(target) {
9316
+ if (target.startsWith("/") || target.startsWith("./") || target.startsWith("../")) {
9317
+ return { kind: "file", path: target };
9318
+ }
9319
+ return { kind: "url", url: target };
9320
+ }
9321
+ var remarkCollapsibleSections2 = function() {
9322
+ return (tree) => tree;
9323
+ };
9324
+ var remarkCollapsibleSections_default2 = remarkCollapsibleSections2;
9325
+ function AnimatedCollapsibleContent2({ isOpen, children }) {
9326
+ return /* @__PURE__ */ jsx172(AnimatePresence22, { initial: false, children: isOpen && /* @__PURE__ */ jsx172(
9327
+ motion22.div,
9328
+ {
9329
+ initial: { height: 0, opacity: 0 },
9330
+ animate: { height: "auto", opacity: 1 },
9331
+ exit: { height: 0, opacity: 0 },
9332
+ transition: { duration: 0.2, ease: "easeInOut" },
9333
+ className: "overflow-hidden",
9334
+ children
9335
+ }
9336
+ ) });
9337
+ }
9338
+ function CollapsibleSection2({
9339
+ sectionId,
9340
+ headingLevel,
9341
+ isCollapsed,
9342
+ onToggle,
9343
+ children
9344
+ }) {
9345
+ const childArray = React52.Children.toArray(children);
9346
+ const heading = childArray[0];
9347
+ const content = childArray.slice(1);
9348
+ if (headingLevel > 4) {
9349
+ return /* @__PURE__ */ jsx172(Fragment32, { children });
9350
+ }
9351
+ const isExpanded = !isCollapsed;
9352
+ const hasContent = content.length > 0;
9353
+ return /* @__PURE__ */ jsxs72("div", { className: "markdown-collapsible-section", "data-section-id": sectionId, children: [
9354
+ /* @__PURE__ */ jsxs72(
9355
+ "div",
9356
+ {
9357
+ className: cn2(
9358
+ "relative group",
9359
+ hasContent && "cursor-pointer"
9360
+ ),
9361
+ onClick: () => hasContent && onToggle(sectionId),
9362
+ children: [
9363
+ /* @__PURE__ */ jsx172(
9364
+ motion22.div,
9365
+ {
9366
+ initial: false,
9367
+ animate: { rotate: isExpanded ? 90 : 0 },
9368
+ transition: { type: "spring", stiffness: 300, damping: 25 },
9369
+ className: cn2(
9370
+ "absolute -left-4 top-[5px] select-none transition-opacity",
9371
+ !hasContent && "opacity-0",
9372
+ hasContent && isCollapsed && "opacity-100",
9373
+ hasContent && isExpanded && "opacity-0 group-hover:opacity-100"
9374
+ ),
9375
+ children: /* @__PURE__ */ jsx172(ChevronRight22, { className: "h-3 w-3 text-muted-foreground" })
9376
+ }
9377
+ ),
9378
+ heading
9379
+ ]
9380
+ }
9381
+ ),
9382
+ hasContent && /* @__PURE__ */ jsx172(AnimatedCollapsibleContent2, { isOpen: isExpanded, children: /* @__PURE__ */ jsx172("div", { className: "collapsible-section-content", children: content }) })
9383
+ ] });
9384
+ }
9385
+ var CollapsibleMarkdownContext2 = createContext22(null);
9386
+ function useCollapsibleMarkdown2() {
9387
+ return useContext22(CollapsibleMarkdownContext2);
9388
+ }
9389
+ function wrapWithSafeProxy2(components) {
9390
+ return components;
9391
+ }
9392
+ var MARKDOWN_MATH_OPTIONS2 = {
9393
+ singleDollarTextMath: false
9394
+ };
9395
+ function stableHash2(input) {
9396
+ let hash = 2166136261;
9397
+ for (let i = 0; i < input.length; i += 1) {
9398
+ hash ^= input.charCodeAt(i);
9399
+ hash = Math.imul(hash, 16777619);
9400
+ }
9401
+ return (hash >>> 0).toString(36);
9402
+ }
9403
+ function createComponents2(mode, onUrlClick, onFileClick, collapsibleContext, firstMermaidCodeRef, hideFirstMermaidExpand = true) {
9404
+ let blockIndex = 0;
9405
+ const wrapBlock = (blockType, content, child, nodePosition) => {
9406
+ blockIndex += 1;
9407
+ const startLine = nodePosition?.start?.line;
9408
+ const endLine = nodePosition?.end?.line;
9409
+ const path = startLine && endLine ? `line:${startLine}-${endLine}` : `idx:${blockIndex}`;
9410
+ const blockId = `blk-${stableHash2(`${blockType}|${path}|${content.slice(0, 240)}`)}`;
9411
+ return /* @__PURE__ */ jsx192(
9412
+ "div",
9413
+ {
9414
+ "data-ca-block-type": blockType,
9415
+ "data-ca-block-path": path,
9416
+ "data-ca-block-id": blockId,
9417
+ children: child
9418
+ }
9419
+ );
9420
+ };
9421
+ const baseComponents = {
9422
+ // Section wrapper for collapsible headings
9423
+ div: ({ node, children, ...props }) => {
9424
+ const sectionId = props["data-section-id"];
9425
+ const headingLevel = props["data-heading-level"];
9426
+ if (sectionId && headingLevel && collapsibleContext) {
9427
+ return /* @__PURE__ */ jsx192(
9428
+ CollapsibleSection2,
9429
+ {
9430
+ sectionId,
9431
+ headingLevel,
9432
+ isCollapsed: collapsibleContext.collapsedSections.has(sectionId),
9433
+ onToggle: collapsibleContext.toggleSection,
9434
+ children
9435
+ }
9436
+ );
9437
+ }
9438
+ return /* @__PURE__ */ jsx192("div", { ...props, children });
9439
+ },
9440
+ // Links: Make clickable with callbacks
9441
+ a: ({ href, children }) => {
9442
+ const handleClick = (e) => {
9443
+ e.preventDefault();
9444
+ const fallbackText = React62.Children.toArray(children).map((child) => typeof child === "string" ? child : "").join("").trim();
9445
+ const target = href?.trim() || fallbackText;
9446
+ if (!target) return;
9447
+ const resolvedTarget = resolveMarkdownLinkTarget2(target);
9448
+ if (resolvedTarget.kind === "file" && onFileClick) {
9449
+ onFileClick(resolvedTarget.path);
9450
+ } else if (resolvedTarget.kind === "url" && onUrlClick) {
9451
+ onUrlClick(resolvedTarget.url);
9452
+ }
9453
+ };
9454
+ return /* @__PURE__ */ jsx192(
9455
+ "a",
9456
+ {
9457
+ href,
9458
+ onClick: handleClick,
9459
+ className: "text-accent hover:underline cursor-pointer",
9460
+ children
9461
+ }
9462
+ );
9463
+ }
9464
+ };
9465
+ if (mode === "terminal") {
9466
+ return {
9467
+ ...baseComponents,
9468
+ // No special code handling - just monospace
9469
+ code: ({ children }) => /* @__PURE__ */ jsx192("code", { className: "font-mono", children }),
9470
+ pre: ({ children }) => /* @__PURE__ */ jsx192("pre", { className: "font-mono whitespace-pre-wrap my-2", children }),
9471
+ // Minimal paragraph spacing
9472
+ p: ({ children }) => /* @__PURE__ */ jsx192("p", { className: "my-1", children }),
9473
+ // Simple lists
9474
+ ul: ({ children }) => /* @__PURE__ */ jsx192("ul", { className: "list-disc list-inside my-1", children }),
9475
+ ol: ({ children }) => /* @__PURE__ */ jsx192("ol", { className: "list-decimal list-inside my-1", children }),
9476
+ li: ({ children }) => /* @__PURE__ */ jsx192("li", { className: "my-0.5", children }),
9477
+ // Plain tables
9478
+ table: ({ children }) => /* @__PURE__ */ jsx192("table", { className: "my-2 font-mono text-sm", children }),
9479
+ th: ({ children }) => /* @__PURE__ */ jsx192("th", { className: "text-left pr-4", children }),
9480
+ td: ({ children }) => /* @__PURE__ */ jsx192("td", { className: "pr-4", children })
9481
+ };
9482
+ }
9483
+ if (mode === "minimal") {
9484
+ return {
9485
+ ...baseComponents,
9486
+ // Inline code
9487
+ code: ({ className, children, ...props }) => {
9488
+ const match = /language-([\w-]+)/.exec(className || "");
9489
+ const isBlock = "node" in props && props.node?.position?.start.line !== props.node?.position?.end.line;
9490
+ if (match || isBlock) {
9491
+ const code = String(children).replace(/\n$/, "");
9492
+ if (match?.[1] === "diff") {
9493
+ return wrapBlock("code", code, /* @__PURE__ */ jsx192(MarkdownDiffBlock2, { code, className: "my-2" }), props.node?.position);
9494
+ }
9495
+ if (match?.[1] === "json") {
9496
+ return wrapBlock("code", code, /* @__PURE__ */ jsx192(MarkdownJsonBlock2, { code, className: "my-2" }), props.node?.position);
9497
+ }
9498
+ if (match?.[1] === "datatable") {
9499
+ return wrapBlock("datatable", code, /* @__PURE__ */ jsx192(MarkdownDatatableBlock2, { code, className: "my-2" }), props.node?.position);
9500
+ }
9501
+ if (match?.[1] === "spreadsheet") {
9502
+ return wrapBlock("spreadsheet", code, /* @__PURE__ */ jsx192(MarkdownSpreadsheetBlock2, { code, className: "my-2" }), props.node?.position);
9503
+ }
9504
+ if (match?.[1] === "html-preview") {
9505
+ return wrapBlock("html-preview", code, /* @__PURE__ */ jsx192(MarkdownHtmlBlock2, { code, className: "my-2" }), props.node?.position);
9506
+ }
9507
+ if (match?.[1] === "pdf-preview") {
9508
+ return wrapBlock("pdf-preview", code, /* @__PURE__ */ jsx192(MarkdownPdfBlock2, { code, className: "my-2" }), props.node?.position);
9509
+ }
9510
+ if (match?.[1] === "image-preview") {
9511
+ return wrapBlock("image-preview", code, /* @__PURE__ */ jsx192(MarkdownImageBlock2, { code, className: "my-2" }), props.node?.position);
9512
+ }
9513
+ if (match?.[1] === "latex" || match?.[1] === "math") {
9514
+ return wrapBlock("latex", code, /* @__PURE__ */ jsx192(MarkdownLatexBlock2, { code, className: "my-2" }), props.node?.position);
9515
+ }
9516
+ if (match?.[1] === "mermaid") {
9517
+ const isFirstBlock = hideFirstMermaidExpand && firstMermaidCodeRef?.current != null && code === firstMermaidCodeRef.current;
9518
+ return wrapBlock(
9519
+ "mermaid",
9520
+ code,
9521
+ /* @__PURE__ */ jsx192(MarkdownMermaidBlock2, { code, className: "my-2", showExpandButton: !isFirstBlock }),
9522
+ props.node?.position
9523
+ );
9524
+ }
9525
+ return wrapBlock("code", code, /* @__PURE__ */ jsx192(CodeBlock2, { code, language: match?.[1], mode: "full", className: "my-2" }), props.node?.position);
9526
+ }
9527
+ return /* @__PURE__ */ jsx192(InlineCode2, { children });
9528
+ },
9529
+ pre: ({ children }) => /* @__PURE__ */ jsx192(Fragment42, { children }),
9530
+ // Comfortable paragraph spacing
9531
+ p: ({ children }) => /* @__PURE__ */ jsx192("p", { className: "my-2 leading-relaxed", children }),
9532
+ // Styled lists - ul uses tighter spacing, ol uses standard for number alignment
9533
+ ul: ({ children, className }) => /* @__PURE__ */ jsx192(
9534
+ "ul",
9535
+ {
9536
+ className: cn2(
9537
+ "my-2 space-y-1 ps-[16px] pe-2 list-disc marker:text-[var(--md-bullets)]",
9538
+ className?.includes("contains-task-list") && "list-none ps-0 marker:content-none"
9539
+ ),
9540
+ children
9541
+ }
9542
+ ),
9543
+ ol: ({ children, className }) => /* @__PURE__ */ jsx192("ol", { className: cn2("my-2 space-y-1 pl-6 list-decimal", className), children }),
9544
+ li: ({ children, className }) => /* @__PURE__ */ jsx192("li", { className: cn2(className?.includes("task-list-item") && "list-none"), children }),
9545
+ input: ({ type, checked }) => {
9546
+ if (type === "checkbox") {
9547
+ return /* @__PURE__ */ jsx192(
9548
+ "input",
9549
+ {
9550
+ type: "checkbox",
9551
+ checked,
9552
+ readOnly: true,
9553
+ className: "mr-2 rounded border-muted-foreground align-middle"
9554
+ }
9555
+ );
9556
+ }
9557
+ return /* @__PURE__ */ jsx192("input", { type });
9558
+ },
9559
+ // Clean tables
9560
+ table: ({ children }) => /* @__PURE__ */ jsx192("div", { className: "my-3 overflow-x-auto", children: /* @__PURE__ */ jsx192("table", { className: "min-w-full text-sm", children }) }),
9561
+ thead: ({ children }) => /* @__PURE__ */ jsx192("thead", { className: "border-b", children }),
9562
+ th: ({ children }) => /* @__PURE__ */ jsx192("th", { className: "text-left py-2 px-3 font-semibold text-muted-foreground", children }),
9563
+ td: ({ children }) => /* @__PURE__ */ jsx192("td", { className: "py-2 px-3 border-b border-border/50", children }),
9564
+ // Headings - H1/H2 same size, differentiated by weight
9565
+ h1: ({ children }) => /* @__PURE__ */ jsx192("h1", { className: "font-sans text-[16px] font-bold mt-5 mb-3", children }),
9566
+ h2: ({ children }) => /* @__PURE__ */ jsx192("h2", { className: "font-sans text-[16px] font-semibold mt-4 mb-3", children }),
9567
+ h3: ({ children }) => /* @__PURE__ */ jsx192("h3", { className: "font-sans text-[15px] font-semibold mt-4 mb-2", children }),
9568
+ // Blockquotes
9569
+ blockquote: ({ children }) => /* @__PURE__ */ jsx192("blockquote", { className: "border-l-2 border-muted-foreground/30 pl-3 my-2 text-muted-foreground italic", children }),
9570
+ // Horizontal rules
9571
+ hr: () => /* @__PURE__ */ jsx192("hr", { className: "my-4 border-border" }),
9572
+ // Strong/emphasis
9573
+ strong: ({ children }) => /* @__PURE__ */ jsx192("strong", { className: "font-semibold", children }),
9574
+ em: ({ children }) => /* @__PURE__ */ jsx192("em", { className: "italic", children })
9575
+ };
9576
+ }
9577
+ return {
9578
+ ...baseComponents,
9579
+ // Full code blocks with copy button
9580
+ code: ({ className, children, ...props }) => {
9581
+ const match = /language-([\w-]+)/.exec(className || "");
9582
+ const isBlock = "node" in props && props.node?.position?.start.line !== props.node?.position?.end.line;
9583
+ if (match || isBlock) {
9584
+ const code = String(children).replace(/\n$/, "");
9585
+ if (match?.[1] === "diff") {
9586
+ return wrapBlock("code", code, /* @__PURE__ */ jsx192(MarkdownDiffBlock2, { code, className: "my-2" }), props.node?.position);
9587
+ }
9588
+ if (match?.[1] === "json") {
9589
+ return wrapBlock("code", code, /* @__PURE__ */ jsx192(MarkdownJsonBlock2, { code, className: "my-2" }), props.node?.position);
9590
+ }
9591
+ if (match?.[1] === "datatable") {
9592
+ return wrapBlock("datatable", code, /* @__PURE__ */ jsx192(MarkdownDatatableBlock2, { code, className: "my-2" }), props.node?.position);
9593
+ }
9594
+ if (match?.[1] === "spreadsheet") {
9595
+ return wrapBlock("spreadsheet", code, /* @__PURE__ */ jsx192(MarkdownSpreadsheetBlock2, { code, className: "my-2" }), props.node?.position);
9596
+ }
9597
+ if (match?.[1] === "html-preview") {
9598
+ return wrapBlock("html-preview", code, /* @__PURE__ */ jsx192(MarkdownHtmlBlock2, { code, className: "my-2" }), props.node?.position);
9599
+ }
9600
+ if (match?.[1] === "pdf-preview") {
9601
+ return wrapBlock("pdf-preview", code, /* @__PURE__ */ jsx192(MarkdownPdfBlock2, { code, className: "my-2" }), props.node?.position);
9602
+ }
9603
+ if (match?.[1] === "image-preview") {
9604
+ return wrapBlock("image-preview", code, /* @__PURE__ */ jsx192(MarkdownImageBlock2, { code, className: "my-2" }), props.node?.position);
9605
+ }
9606
+ if (match?.[1] === "latex" || match?.[1] === "math") {
9607
+ return wrapBlock("latex", code, /* @__PURE__ */ jsx192(MarkdownLatexBlock2, { code, className: "my-2" }), props.node?.position);
9608
+ }
9609
+ if (match?.[1] === "mermaid") {
9610
+ const isFirstBlock = hideFirstMermaidExpand && firstMermaidCodeRef?.current != null && code === firstMermaidCodeRef.current;
9611
+ return wrapBlock(
9612
+ "mermaid",
9613
+ code,
9614
+ /* @__PURE__ */ jsx192(MarkdownMermaidBlock2, { code, className: "my-2", showExpandButton: !isFirstBlock }),
9615
+ props.node?.position
9616
+ );
9617
+ }
9618
+ return wrapBlock("code", code, /* @__PURE__ */ jsx192(CodeBlock2, { code, language: match?.[1], mode: "full", className: "my-2" }), props.node?.position);
9619
+ }
9620
+ return /* @__PURE__ */ jsx192(InlineCode2, { children });
9621
+ },
9622
+ pre: ({ children }) => /* @__PURE__ */ jsx192(Fragment42, { children }),
9623
+ // Rich paragraph spacing
9624
+ p: ({ children }) => /* @__PURE__ */ jsx192("p", { className: "my-3 leading-relaxed", children }),
9625
+ // Styled lists - ul uses tighter spacing, ol uses standard for number alignment
9626
+ ul: ({ children, className }) => /* @__PURE__ */ jsx192(
9627
+ "ul",
9628
+ {
9629
+ className: cn2(
9630
+ "my-3 space-y-1.5 ps-[16px] pe-2 list-disc marker:text-[var(--md-bullets)]",
9631
+ className?.includes("contains-task-list") && "list-none ps-0 marker:content-none"
9632
+ ),
9633
+ children
9634
+ }
9635
+ ),
9636
+ ol: ({ children, className }) => /* @__PURE__ */ jsx192("ol", { className: cn2("my-3 space-y-1.5 pl-6 list-decimal", className), children }),
9637
+ li: ({ children, className }) => /* @__PURE__ */ jsx192("li", { className: cn2("leading-relaxed", className?.includes("task-list-item") && "list-none"), children }),
9638
+ // Beautiful tables
9639
+ table: ({ children }) => /* @__PURE__ */ jsx192("div", { className: "my-4 overflow-x-auto rounded-md border", children: /* @__PURE__ */ jsx192("table", { className: "min-w-full divide-y divide-border", children }) }),
9640
+ thead: ({ children }) => /* @__PURE__ */ jsx192("thead", { className: "bg-muted/50", children }),
9641
+ tbody: ({ children }) => /* @__PURE__ */ jsx192("tbody", { className: "divide-y divide-border", children }),
9642
+ th: ({ children }) => /* @__PURE__ */ jsx192("th", { className: "text-left py-3 px-4 font-semibold text-sm", children }),
9643
+ td: ({ children }) => /* @__PURE__ */ jsx192("td", { className: "py-3 px-4 text-sm", children }),
9644
+ tr: ({ children }) => /* @__PURE__ */ jsx192("tr", { className: "hover:bg-muted/30 transition-colors", children }),
9645
+ // Rich headings - H1/H2 same size, differentiated by weight
9646
+ h1: ({ children }) => /* @__PURE__ */ jsx192("h1", { className: "font-sans text-[16px] font-bold mt-7 mb-4", children }),
9647
+ h2: ({ children }) => /* @__PURE__ */ jsx192("h2", { className: "font-sans text-[16px] font-semibold mt-6 mb-3", children }),
9648
+ h3: ({ children }) => /* @__PURE__ */ jsx192("h3", { className: "font-sans text-[15px] font-semibold mt-5 mb-3", children }),
9649
+ h4: ({ children }) => /* @__PURE__ */ jsx192("h4", { className: "text-[14px] font-semibold mt-3 mb-1", children }),
9650
+ // Styled blockquotes
9651
+ blockquote: ({ children }) => /* @__PURE__ */ jsx192("blockquote", { className: "border-l-4 border-foreground/30 bg-muted/30 pl-4 pr-3 py-2 my-3 rounded-r-md", children }),
9652
+ // Task lists (GFM)
9653
+ input: ({ type, checked }) => {
9654
+ if (type === "checkbox") {
9655
+ return /* @__PURE__ */ jsx192(
9656
+ "input",
9657
+ {
9658
+ type: "checkbox",
9659
+ checked,
9660
+ readOnly: true,
9661
+ className: "mr-2 rounded border-muted-foreground"
9662
+ }
9663
+ );
9664
+ }
9665
+ return /* @__PURE__ */ jsx192("input", { type });
9666
+ },
9667
+ // Horizontal rules
9668
+ hr: () => /* @__PURE__ */ jsx192("hr", { className: "my-6 border-border" }),
9669
+ // Strong/emphasis
9670
+ strong: ({ children }) => /* @__PURE__ */ jsx192("strong", { className: "font-semibold", children }),
9671
+ em: ({ children }) => /* @__PURE__ */ jsx192("em", { className: "italic", children }),
9672
+ del: ({ children }) => /* @__PURE__ */ jsx192("del", { className: "line-through text-muted-foreground", children }),
9673
+ // Handle unknown <markdown> tags that may come through rehype-raw
9674
+ // Type assertion needed because 'markdown' is not a standard HTML element
9675
+ markdown: ({ children }) => /* @__PURE__ */ jsx192(Fragment42, { children })
9676
+ };
9677
+ }
9678
+ function Markdown2({
9679
+ children,
9680
+ mode = "minimal",
9681
+ className,
9682
+ id,
9683
+ onUrlClick,
9684
+ onFileClick,
9685
+ collapsible = false,
9686
+ hideFirstMermaidExpand = true
9687
+ }) {
9688
+ const collapsibleContext = useCollapsibleMarkdown2();
9689
+ const firstMermaidCodeRef = React62.useRef(null);
9690
+ const trimmed = children.trimStart();
9691
+ if (trimmed.startsWith("```mermaid")) {
9692
+ const m = trimmed.match(/^```mermaid\n([\s\S]*?)```/);
9693
+ firstMermaidCodeRef.current = m?.[1] ? m[1].replace(/\n$/, "") : null;
9694
+ } else {
9695
+ firstMermaidCodeRef.current = null;
9696
+ }
9697
+ const components = React62.useMemo(
9698
+ () => wrapWithSafeProxy2(createComponents2(mode, onUrlClick, onFileClick, collapsible ? collapsibleContext : null, firstMermaidCodeRef, hideFirstMermaidExpand)),
9699
+ [mode, onUrlClick, onFileClick, collapsible, collapsibleContext, hideFirstMermaidExpand]
9700
+ );
9701
+ const processedContent = React62.useMemo(
9702
+ () => preprocessLinks2(children),
9703
+ [children]
9704
+ );
9705
+ const remarkPlugins = React62.useMemo(
9706
+ () => {
9707
+ const mathPlugin = [
9708
+ remarkMath2,
9709
+ MARKDOWN_MATH_OPTIONS2
9710
+ ];
9711
+ return collapsible ? [remarkGfm2, mathPlugin, remarkCollapsibleSections_default2] : [remarkGfm2, mathPlugin];
9712
+ },
9713
+ [collapsible]
9714
+ );
9715
+ return /* @__PURE__ */ jsx192("div", { className: cn2("markdown-content", className), children: /* @__PURE__ */ jsx192(
9716
+ ReactMarkdown2,
9717
+ {
9718
+ remarkPlugins,
9719
+ rehypePlugins: [rehypeKatex2, rehypeRaw2],
9720
+ components,
9721
+ children: processedContent
9722
+ }
9723
+ ) });
9724
+ }
9725
+ var MemoizedMarkdown2 = React62.memo(
9726
+ Markdown2,
9727
+ (prevProps, nextProps) => {
9728
+ if (prevProps.id && nextProps.id) {
9729
+ return prevProps.id === nextProps.id && prevProps.children === nextProps.children && prevProps.mode === nextProps.mode;
9730
+ }
9731
+ return prevProps.children === nextProps.children && prevProps.mode === nextProps.mode;
9732
+ }
9733
+ );
9734
+ MemoizedMarkdown2.displayName = "MemoizedMarkdown";
9735
+ function AnnotationIslandMenu2(_props) {
9736
+ return null;
9737
+ }
9738
+ function buildAnnotationChipEntryTransition2(_snapshot = null) {
9739
+ return {};
9740
+ }
9741
+ function buildSelectionEntryTransition2(_primary = null, _secondary) {
9742
+ return {};
9743
+ }
9744
+ var ANNOTATION_PREFIX_SUFFIX_WINDOW2 = 40;
9745
+ var SELECTION_POINTER_MAX_AGE_MS2 = 5e3;
9746
+ function clamp2(value, min, max) {
9747
+ return Math.max(min, Math.min(max, value));
9748
+ }
9749
+ function hasExistingTextRangeAnnotation2(annotations, start, end) {
9750
+ return annotations.some(
9751
+ (a) => a.target.selectors.some(
9752
+ (s) => s.type === "text-position" && s.start === start && s.end === end
9753
+ )
9754
+ );
9755
+ }
9756
+ function createSelectionPreviewAnnotation2(messageId, sessionIdOrSelection, startOrSessionId, end, exact) {
9757
+ if (typeof sessionIdOrSelection === "object") {
9758
+ const sel = sessionIdOrSelection;
9759
+ const sid = startOrSessionId ?? "";
9760
+ return {
9761
+ id: `preview-${Date.now()}`,
9762
+ schemaVersion: 1,
9763
+ createdAt: Date.now(),
9764
+ body: [{ type: "highlight" }],
9765
+ target: {
9766
+ source: { sessionId: sid, messageId },
9767
+ selectors: [
9768
+ { type: "text-quote", exact: sel.exact ?? "" },
9769
+ { type: "text-position", start: sel.start, end: sel.end }
9770
+ ]
9771
+ }
9772
+ };
9773
+ }
9774
+ return {
9775
+ id: `preview-${Date.now()}`,
9776
+ schemaVersion: 1,
9777
+ createdAt: Date.now(),
9778
+ body: [{ type: "highlight" }],
9779
+ target: {
9780
+ source: { sessionId: sessionIdOrSelection, messageId },
9781
+ selectors: [
9782
+ { type: "text-quote", exact: exact ?? "" },
9783
+ { type: "text-position", start: startOrSessionId, end: end ?? 0 }
9784
+ ]
9785
+ }
9786
+ };
9787
+ }
9788
+ function createTextSelectionAnnotation2(messageId, sessionId, start, end, exact, note) {
9789
+ return {
9790
+ id: `sel-${Date.now()}`,
9791
+ schemaVersion: 1,
9792
+ createdAt: Date.now(),
9793
+ body: [{ type: "note", text: note }],
9794
+ target: {
9795
+ source: { sessionId, messageId },
9796
+ selectors: [
9797
+ { type: "text-quote", exact },
9798
+ { type: "text-position", start, end }
9799
+ ]
9800
+ }
9801
+ };
9802
+ }
9803
+ function getCanonicalText2(_content) {
9804
+ if (typeof _content === "string") return _content;
9805
+ return "";
9806
+ }
9807
+ function resolveNodeOffset2(_root, _node, _offset) {
9808
+ return _offset ?? null;
9809
+ }
9810
+ function getAnnotationRectVisual2(_rect) {
9811
+ return { className: "absolute pointer-events-none", style: {} };
9812
+ }
9813
+ function getAnnotationChipVisual2(_chip) {
9814
+ return { className: "absolute pointer-events-auto", style: {} };
9815
+ }
9816
+ function clearBlockAnnotationMarkers2(_container) {
9817
+ }
9818
+ function applyBlockAnnotationMarker2(_container, _annotationOrId, _blockId) {
9819
+ }
9820
+ function canAnnotateMessage2(_opts) {
9821
+ if (typeof _opts === "string") return true;
9822
+ return _opts.hasAddAnnotationHandler && _opts.hasMessageId && !_opts.isStreaming;
9823
+ }
9824
+ function shouldRenderAnnotationIslandInPortal2(_context) {
9825
+ return true;
9826
+ }
9827
+ function clearDomSelection2() {
9828
+ if (typeof window !== "undefined" && window.getSelection) {
9829
+ const selection = window.getSelection();
9830
+ if (selection) {
9831
+ selection.removeAllRanges();
9832
+ }
9833
+ }
9834
+ }
9835
+ function getAnnotationChipInteraction2(_annotation) {
9836
+ return { clickable: true, openMode: "view" };
9837
+ }
9838
+ function shouldIgnoreSelectionMouseUpTarget2(_target) {
9839
+ return false;
9840
+ }
9841
+ function computeAnnotationOverlayGeometry2(_containerOrOpts, _annotations, _content) {
9842
+ return { rects: [], chips: [], unresolved: [] };
9843
+ }
9844
+ function AnnotationOverlayLayer2({
9845
+ rects,
9846
+ chips,
9847
+ annotations,
9848
+ getTooltipText,
9849
+ allowChipOpen = true,
9850
+ onChipOpen
9851
+ }) {
9852
+ const annotationMap = React72.useMemo(() => {
9853
+ return new Map((annotations ?? []).map((annotation) => [annotation.id, annotation]));
9854
+ }, [annotations]);
9855
+ if (rects.length === 0 && chips.length === 0) {
9856
+ return null;
9857
+ }
9858
+ return /* @__PURE__ */ jsxs82("div", { "data-ca-annotation-overlay": true, className: "pointer-events-none absolute inset-0 z-[2]", children: [
9859
+ rects.map((rect, idx) => {
9860
+ const rectVisual = getAnnotationRectVisual2(rect);
9861
+ return /* @__PURE__ */ jsx202(
9862
+ "div",
9863
+ {
9864
+ className: rectVisual.className,
9865
+ style: {
9866
+ left: rect.left - 4,
9867
+ top: rect.top - 1,
9868
+ width: rect.width + 8,
9869
+ height: rect.height + 2,
9870
+ backgroundColor: rect.color,
9871
+ borderRadius: "4px",
9872
+ ...rectVisual.style
9873
+ }
9874
+ },
9875
+ `rect-${rect.id}-${idx}`
9876
+ );
9877
+ }),
9878
+ chips.map((chip) => {
9879
+ const chipVisual = getAnnotationChipVisual2(chip);
9880
+ const chipAnnotation = annotationMap.get(chip.id) ?? null;
9881
+ const interaction = getAnnotationChipInteraction2(chipAnnotation);
9882
+ const tooltipText = chipAnnotation && getTooltipText ? getTooltipText(chipAnnotation, chip.index) : "";
9883
+ const canOpenChip = allowChipOpen && interaction.clickable;
9884
+ const chipButton = /* @__PURE__ */ jsx202(
9885
+ "button",
9886
+ {
9887
+ type: "button",
9888
+ "data-ca-annotation-id": chip.id,
9889
+ "data-ca-annotation-index": String(chip.index),
9890
+ "aria-disabled": !canOpenChip,
9891
+ onClick: canOpenChip ? (event) => {
9892
+ const rect = event.currentTarget.getBoundingClientRect();
9893
+ onChipOpen({
9894
+ annotationId: chip.id,
9895
+ index: chip.index,
9896
+ anchorX: rect.left + rect.width / 2,
9897
+ anchorY: rect.top - 8,
9898
+ mode: interaction.openMode
9899
+ });
9900
+ } : void 0,
9901
+ className: cn2(chipVisual.className, !canOpenChip && "cursor-default"),
9902
+ style: {
9903
+ left: chip.left,
9904
+ top: chip.top,
9905
+ transform: "translate(-2px, -8px)",
9906
+ minWidth: "16px",
9907
+ height: "15px",
9908
+ padding: "0 3px",
9909
+ borderRadius: "4px",
9910
+ fontSize: "10px",
9911
+ fontWeight: "600",
9912
+ lineHeight: "15px",
9913
+ textAlign: "center",
9914
+ userSelect: "none",
9915
+ position: "absolute",
9916
+ ...chipVisual.style
9917
+ },
9918
+ children: chip.sentFollowUp ? "i" : chip.index
9919
+ }
9920
+ );
9921
+ if (tooltipText) {
9922
+ return /* @__PURE__ */ jsxs82(Tooltip2, { children: [
9923
+ /* @__PURE__ */ jsx202(TooltipTrigger2, { asChild: true, children: chipButton }),
9924
+ /* @__PURE__ */ jsx202(TooltipContent2, { side: "top", className: "max-w-[280px] whitespace-pre-wrap text-xs", children: tooltipText })
9925
+ ] }, `chip-${chip.id}`);
9926
+ }
9927
+ return /* @__PURE__ */ jsx202(React72.Fragment, { children: chipButton }, `chip-${chip.id}`);
9928
+ })
9929
+ ] });
9930
+ }
9931
+ function getAnnotationInteractionAnchor2(_annotation) {
9932
+ return { x: 0, y: 0 };
9933
+ }
9934
+ function getAnnotationInteractionSourceKey2(_annotation, _scope) {
9935
+ return "";
9936
+ }
9937
+ function hasAnnotationInteraction2(_annotation) {
9938
+ return false;
9939
+ }
9940
+ var initialAnnotationInteractionState2 = {
9941
+ isOpen: false,
9942
+ mode: "view",
9943
+ activeDetail: null,
9944
+ draft: "",
9945
+ pendingSelection: null,
9946
+ selectionMenuView: null,
9947
+ followUpDraft: "",
9948
+ followUpMode: "none",
9949
+ activeAnnotationDetail: null
9950
+ };
9951
+ var annotationInteractionActions2 = {
9952
+ setDraft: (_draft) => ({ type: "setDraft", draft: _draft }),
9953
+ openFromSelection: (_selection) => ({ type: "openFromSelection", selection: _selection }),
9954
+ openFollowUpFromSelection: () => ({ type: "openFollowUpFromSelection" }),
9955
+ openFromAnnotation: (_detail, _noteText, _mode) => ({ type: "openFromAnnotation", detail: _detail, noteText: _noteText, mode: _mode }),
9956
+ requestEdit: () => ({ type: "requestEdit" }),
9957
+ cancelFollowUp: () => ({ type: "cancelFollowUp" }),
9958
+ closeAll: () => ({ type: "closeAll" }),
9959
+ submitSuccess: () => ({ type: "submitSuccess" }),
9960
+ deleteSuccess: () => ({ type: "deleteSuccess" })
9961
+ };
9962
+ function annotationInteractionReducer2(state, _action) {
9963
+ return state;
9964
+ }
9965
+ function useAnnotationInteractionController2() {
9966
+ const [state, dispatch] = React82.useReducer(annotationInteractionReducer2, initialAnnotationInteractionState2);
9967
+ const lastHandledOpenRequestNonceRef = React82.useRef(null);
9968
+ const setDraft = React82.useCallback((draft) => {
9969
+ dispatch(annotationInteractionActions2.setDraft(draft));
9970
+ }, []);
9971
+ const openFromSelection = React82.useCallback((selection) => {
9972
+ dispatch(annotationInteractionActions2.openFromSelection(selection));
9973
+ }, []);
9974
+ const openFollowUpFromSelection = React82.useCallback(() => {
9975
+ dispatch(annotationInteractionActions2.openFollowUpFromSelection());
9976
+ }, []);
9977
+ const openFromAnnotation = React82.useCallback((detail, noteText, mode) => {
9978
+ dispatch(annotationInteractionActions2.openFromAnnotation(detail, noteText, mode));
9979
+ }, []);
9980
+ const requestEdit = React82.useCallback(() => {
9981
+ dispatch(annotationInteractionActions2.requestEdit());
9982
+ }, []);
9983
+ const cancelFollowUp = React82.useCallback(() => {
9984
+ const hadPendingSelection = Boolean(state.pendingSelection);
9985
+ const pendingSelection = state.pendingSelection;
9986
+ dispatch(annotationInteractionActions2.cancelFollowUp());
9987
+ return { hadPendingSelection, pendingSelection };
9988
+ }, [state.pendingSelection]);
9989
+ const closeAll = React82.useCallback(() => {
9990
+ dispatch(annotationInteractionActions2.closeAll());
9991
+ }, []);
9992
+ const markSubmitSuccess = React82.useCallback(() => {
9993
+ dispatch(annotationInteractionActions2.submitSuccess());
9994
+ }, []);
9995
+ const markDeleteSuccess = React82.useCallback(() => {
9996
+ dispatch(annotationInteractionActions2.deleteSuccess());
9997
+ }, []);
9998
+ const consumeExternalOpenRequest = React82.useCallback((request, params) => {
9999
+ if (!request || !params.messageId || !params.annotations?.length) return false;
10000
+ if (request.messageId !== params.messageId) return false;
10001
+ if (lastHandledOpenRequestNonceRef.current === request.nonce) return false;
10002
+ const annotationIndex = params.annotations.findIndex((item) => item.id === request.annotationId);
10003
+ if (annotationIndex < 0) return false;
10004
+ lastHandledOpenRequestNonceRef.current = request.nonce;
10005
+ const annotation = params.annotations[annotationIndex];
10006
+ if (!annotation) return false;
10007
+ const noteText = params.getNoteText(annotation);
10008
+ const detail = {
10009
+ annotationId: request.annotationId,
10010
+ index: annotationIndex + 1,
10011
+ anchorX: request.anchorX ?? params.fallbackAnchor.x,
10012
+ anchorY: request.anchorY ?? params.fallbackAnchor.y
10013
+ };
10014
+ dispatch(annotationInteractionActions2.openFromAnnotation(detail, noteText, request.mode));
10015
+ return true;
10016
+ }, []);
10017
+ return {
10018
+ state,
10019
+ setDraft,
10020
+ openFromSelection,
10021
+ openFollowUpFromSelection,
10022
+ openFromAnnotation,
10023
+ requestEdit,
10024
+ cancelFollowUp,
10025
+ closeAll,
10026
+ markSubmitSuccess,
10027
+ markDeleteSuccess,
10028
+ consumeExternalOpenRequest
10029
+ };
10030
+ }
10031
+ function useAnnotationIslandPresentation2(_opts) {
10032
+ return {
10033
+ islandRef: React92.createRef(),
10034
+ islandPosition: { x: 0, y: 0 },
10035
+ islandStyle: {},
10036
+ shouldRenderInPortal: true,
10037
+ renderAnchor: null,
10038
+ renderSourceKey: "",
10039
+ isVisible: false,
10040
+ openedAtRef: React92.createRef(),
10041
+ handleExitComplete: () => {
10042
+ },
10043
+ resetPresentation: () => {
10044
+ }
10045
+ };
10046
+ }
10047
+ function useAnnotationIslandEvents2(_opts) {
10048
+ return {
10049
+ handleAnnotationSubmit: () => {
10050
+ },
10051
+ handleAnnotationDelete: () => {
10052
+ },
10053
+ handleAnnotationEdit: () => {
10054
+ },
10055
+ handleAnnotationCancel: () => {
10056
+ }
10057
+ };
10058
+ }
10059
+ function useAnnotationCancelRestore2(_opts) {
10060
+ return () => {
10061
+ };
10062
+ }
10063
+ function DocumentFormattedMarkdownOverlay2(_props) {
10064
+ return null;
10065
+ }
10066
+ function AcceptPlanDropdown2({
10067
+ onAccept,
10068
+ onAcceptWithCompact,
10069
+ acceptLabel,
10070
+ acceptOptionLabel,
10071
+ className
10072
+ }) {
10073
+ const { t: t22 } = useTranslation22();
10074
+ const effectiveAcceptLabel = acceptLabel ?? t22("plan.acceptPlan");
10075
+ const effectiveAcceptOptionLabel = acceptOptionLabel ?? t22("plan.accept");
10076
+ const [isOpen, setIsOpen] = useState52(false);
10077
+ const [position, setPosition] = useState52(null);
10078
+ const triggerRef = useRef32(null);
10079
+ const menuRef = useRef32(null);
10080
+ const updatePosition = useCallback42(() => {
10081
+ if (!triggerRef.current) return;
10082
+ const rect = triggerRef.current.getBoundingClientRect();
10083
+ const menuWidth = 280;
10084
+ const menuHeight = 120;
10085
+ const gap = 4;
10086
+ const spaceBelow = window.innerHeight - rect.bottom;
10087
+ const top = spaceBelow >= menuHeight + gap ? rect.bottom + gap : rect.top - menuHeight - gap;
10088
+ let left = rect.right - menuWidth;
10089
+ if (left < 8) left = 8;
10090
+ if (left + menuWidth > window.innerWidth - 8) {
10091
+ left = window.innerWidth - menuWidth - 8;
10092
+ }
10093
+ setPosition({ top, left });
10094
+ }, []);
10095
+ const handleToggle = useCallback42((e) => {
10096
+ e.stopPropagation();
10097
+ if (!isOpen) {
10098
+ if (triggerRef.current) {
10099
+ const rect = triggerRef.current.getBoundingClientRect();
10100
+ const menuWidth = 280;
10101
+ const menuHeight = 120;
10102
+ const gap = 4;
10103
+ const spaceBelow = window.innerHeight - rect.bottom;
10104
+ const top = spaceBelow >= menuHeight + gap ? rect.bottom + gap : rect.top - menuHeight - gap;
10105
+ let left = rect.right - menuWidth;
10106
+ if (left < 8) left = 8;
10107
+ if (left + menuWidth > window.innerWidth - 8) {
10108
+ left = window.innerWidth - menuWidth - 8;
10109
+ }
10110
+ setPosition({ top, left });
10111
+ }
10112
+ }
10113
+ setIsOpen((prev) => !prev);
10114
+ }, [isOpen]);
10115
+ const handleClose = useCallback42(() => {
10116
+ setIsOpen(false);
10117
+ }, []);
10118
+ const handleSelectAccept = useCallback42((e) => {
10119
+ e.stopPropagation();
10120
+ handleClose();
10121
+ onAccept();
10122
+ }, [handleClose, onAccept]);
10123
+ const handleSelectCompact = useCallback42((e) => {
10124
+ e.stopPropagation();
10125
+ handleClose();
10126
+ onAcceptWithCompact();
10127
+ }, [handleClose, onAcceptWithCompact]);
10128
+ useEffect23(() => {
10129
+ if (isOpen) {
10130
+ updatePosition();
10131
+ }
10132
+ }, [isOpen, updatePosition]);
10133
+ useEffect23(() => {
10134
+ if (!isOpen) return;
10135
+ const handleClickOutside = (e) => {
10136
+ if (menuRef.current && !menuRef.current.contains(e.target) && triggerRef.current && !triggerRef.current.contains(e.target)) {
10137
+ handleClose();
10138
+ }
10139
+ };
10140
+ const handleEscape = (e) => {
10141
+ if (e.key === "Escape") {
10142
+ handleClose();
10143
+ }
10144
+ };
10145
+ document.addEventListener("mousedown", handleClickOutside);
10146
+ document.addEventListener("keydown", handleEscape);
10147
+ return () => {
10148
+ document.removeEventListener("mousedown", handleClickOutside);
10149
+ document.removeEventListener("keydown", handleEscape);
10150
+ };
10151
+ }, [isOpen, handleClose]);
10152
+ return /* @__PURE__ */ jsxs92(Fragment62, { children: [
10153
+ /* @__PURE__ */ jsx212(
10154
+ "div",
10155
+ {
10156
+ ref: triggerRef,
10157
+ onClick: handleToggle,
10158
+ className: "inline-flex",
10159
+ children: /* @__PURE__ */ jsxs92(
10160
+ "button",
10161
+ {
10162
+ type: "button",
10163
+ className: cn2(
10164
+ "h-[28px] pl-2.5 pr-2 text-xs font-medium rounded-[6px] flex items-center gap-1.5 transition-all",
10165
+ "bg-success/5 text-success hover:bg-success/10 shadow-tinted",
10166
+ className
10167
+ ),
10168
+ style: { "--shadow-color": "34, 136, 82" },
10169
+ children: [
10170
+ /* @__PURE__ */ jsx212("svg", { className: "h-3.5 w-3.5", viewBox: "0 0 25 24", fill: "currentColor", children: /* @__PURE__ */ jsx212("path", { fillRule: "nonzero", d: "M13.7207031,22.6523438 C13.264974,22.6523438 12.9361979,22.4895833 12.734375,22.1640625 C12.5325521,21.8385417 12.360026,21.4316406 12.2167969,20.9433594 L10.6640625,15.7871094 C10.5729167,15.4615885 10.5403646,15.1995443 10.5664062,15.0009766 C10.5924479,14.8024089 10.6998698,14.6022135 10.8886719,14.4003906 L20.859375,3.6484375 C20.9179688,3.58984375 20.9472656,3.52473958 20.9472656,3.453125 C20.9472656,3.38151042 20.921224,3.32291667 20.8691406,3.27734375 C20.8170573,3.23177083 20.7568359,3.20735677 20.6884766,3.20410156 C20.6201172,3.20084635 20.5566406,3.22851562 20.4980469,3.28710938 L9.78515625,13.296875 C9.5703125,13.4921875 9.36197917,13.601237 9.16015625,13.6240234 C8.95833333,13.6468099 8.70117188,13.609375 8.38867188,13.5117188 L3.11523438,11.9101562 C2.64648438,11.7669271 2.25911458,11.5960286 1.953125,11.3974609 C1.64713542,11.1988932 1.49414062,10.875 1.49414062,10.4257812 C1.49414062,10.0742188 1.63411458,9.77148438 1.9140625,9.51757812 C2.19401042,9.26367188 2.5390625,9.05859375 2.94921875,8.90234375 L19.7460938,2.46679688 C19.9739583,2.38216146 20.1871745,2.31542969 20.3857422,2.26660156 C20.5843099,2.21777344 20.764974,2.19335938 20.9277344,2.19335938 C21.2467448,2.19335938 21.4973958,2.28450521 21.6796875,2.46679688 C21.8619792,2.64908854 21.953125,2.89973958 21.953125,3.21875 C21.953125,3.38802083 21.9287109,3.5703125 21.8798828,3.765625 C21.8310547,3.9609375 21.7643229,4.17252604 21.6796875,4.40039062 L15.2832031,21.109375 C15.1009115,21.578125 14.8828125,21.952474 14.6289062,22.2324219 C14.375,22.5123698 14.0722656,22.6523438 13.7207031,22.6523438 Z" }) }),
10171
+ /* @__PURE__ */ jsx212("span", { children: effectiveAcceptLabel }),
10172
+ /* @__PURE__ */ jsx212(ChevronDown2, { className: cn2(
10173
+ "h-3 w-3 transition-transform duration-150",
10174
+ isOpen && "rotate-180"
10175
+ ) })
10176
+ ]
10177
+ }
10178
+ )
10179
+ }
10180
+ ),
10181
+ isOpen && position && ReactDOM2.createPortal(
10182
+ /* @__PURE__ */ jsxs92(
10183
+ "div",
10184
+ {
10185
+ ref: menuRef,
10186
+ className: cn2(
10187
+ "fixed z-50 min-w-[280px] p-1.5",
10188
+ "bg-background rounded-[8px] shadow-strong border border-border/50",
10189
+ "animate-in fade-in-0 zoom-in-95 duration-100"
10190
+ ),
10191
+ style: { top: position.top, left: position.left },
10192
+ children: [
10193
+ /* @__PURE__ */ jsxs92(
10194
+ "button",
10195
+ {
10196
+ type: "button",
10197
+ onClick: handleSelectAccept,
10198
+ className: cn2(
10199
+ "flex flex-col w-full px-3 py-2 text-left rounded-[6px]",
10200
+ "hover:bg-foreground/[0.05] focus:bg-foreground/[0.05] focus:outline-none",
10201
+ "transition-colors"
10202
+ ),
10203
+ children: [
10204
+ /* @__PURE__ */ jsx212("span", { className: "text-[13px] font-medium", children: effectiveAcceptOptionLabel }),
10205
+ /* @__PURE__ */ jsx212("span", { className: "text-xs text-muted-foreground", children: t22("plan.executeImmediately") })
10206
+ ]
10207
+ }
10208
+ ),
10209
+ /* @__PURE__ */ jsxs92(
10210
+ "button",
10211
+ {
10212
+ type: "button",
10213
+ onClick: handleSelectCompact,
10214
+ className: cn2(
10215
+ "flex flex-col w-full px-3 py-2 text-left rounded-[6px]",
10216
+ "hover:bg-foreground/[0.05] focus:bg-foreground/[0.05] focus:outline-none",
10217
+ "transition-colors"
10218
+ ),
10219
+ children: [
10220
+ /* @__PURE__ */ jsx212("span", { className: "text-[13px] font-medium", children: t22("plan.acceptAndCompact") }),
10221
+ /* @__PURE__ */ jsx212("span", { className: "text-xs text-muted-foreground", children: t22("plan.worksForComplex") })
10222
+ ]
10223
+ }
10224
+ )
10225
+ ]
10226
+ }
10227
+ ),
10228
+ document.body
10229
+ )
10230
+ ] });
10231
+ }
10232
+ function DropdownMenu2({ children }) {
10233
+ return /* @__PURE__ */ jsx222(Fragment72, { children });
10234
+ }
10235
+ function DropdownMenuTrigger2({ children }) {
10236
+ return /* @__PURE__ */ jsx222(Fragment72, { children });
10237
+ }
10238
+ function StyledDropdownMenuContent2({
10239
+ children,
10240
+ align = "end",
10241
+ minWidth,
10242
+ sideOffset,
10243
+ className
10244
+ }) {
10245
+ return /* @__PURE__ */ jsx222("div", { className: cn2(
10246
+ "min-w-[180px] p-1 bg-background rounded-[8px] shadow-strong border border-border/50",
10247
+ align === "end" ? "ml-auto" : "",
10248
+ className
10249
+ ), children });
10250
+ }
10251
+ function StyledDropdownMenuItem2({
10252
+ onClick,
10253
+ children,
10254
+ className
10255
+ }) {
10256
+ return /* @__PURE__ */ jsx222(
10257
+ "button",
10258
+ {
10259
+ type: "button",
10260
+ onClick,
10261
+ className: cn2(
10262
+ "flex items-center gap-2 w-full px-2 py-1.5 text-left rounded-[6px]",
10263
+ "hover:bg-foreground/[0.05] text-sm",
10264
+ className
10265
+ ),
10266
+ children
10267
+ }
10268
+ );
10269
+ }
10270
+ function BranchDropdown2({ onBranch }) {
10271
+ const { t: t22 } = useTranslation32();
10272
+ const handleBranchClick = () => {
10273
+ onBranch({ newPanel: true });
10274
+ };
10275
+ return /* @__PURE__ */ jsxs102(DropdownMenu2, { children: [
10276
+ /* @__PURE__ */ jsx232(DropdownMenuTrigger2, { asChild: true, children: /* @__PURE__ */ jsx232(
10277
+ "button",
10278
+ {
10279
+ type: "button",
10280
+ "aria-label": t22("chat.branchOptions"),
10281
+ title: t22("chat.branch"),
10282
+ className: cn2(
10283
+ "p-1 rounded-[4px] transition-colors select-none",
10284
+ "text-muted-foreground hover:text-foreground hover:bg-foreground/5",
10285
+ "data-[state=open]:text-foreground data-[state=open]:bg-foreground/5",
10286
+ "focus:outline-none focus-visible:ring-1 focus-visible:ring-ring"
10287
+ ),
10288
+ children: /* @__PURE__ */ jsx232(GitBranch2, { className: SIZE_CONFIG2.iconSize })
10289
+ }
10290
+ ) }),
10291
+ /* @__PURE__ */ jsx232(StyledDropdownMenuContent2, { align: "end", minWidth: "min-w-64", sideOffset: 6, children: /* @__PURE__ */ jsx232(StyledDropdownMenuItem2, { onClick: handleBranchClick, className: "items-start py-2", children: /* @__PURE__ */ jsxs102("div", { className: "flex flex-col gap-0.5", children: [
10292
+ /* @__PURE__ */ jsx232("span", { className: "text-[13px] leading-tight", children: t22("chat.branchFromThisMessage") }),
10293
+ /* @__PURE__ */ jsx232("span", { className: "max-w-[220px] whitespace-normal text-xs leading-tight text-muted-foreground", children: t22("chat.branchFromThisMessageDescription") })
10294
+ ] }) }) })
10295
+ ] });
10296
+ }
10297
+ var MAX_HEIGHT2 = 540;
10298
+ function clearAnnotationMarks2(root) {
10299
+ const annotatedInlineCodeNodes = root.querySelectorAll('code[data-ca-annotation-inline-code="true"]');
10300
+ annotatedInlineCodeNodes.forEach((codeNode) => {
10301
+ codeNode.removeAttribute("data-ca-annotation-inline-code");
10302
+ codeNode.style.backgroundColor = "";
10303
+ codeNode.style.boxShadow = "";
10304
+ });
10305
+ const marks = root.querySelectorAll("span[data-ca-annotation-id]");
10306
+ marks.forEach((mark) => {
10307
+ const parent = mark.parentNode;
10308
+ if (!parent) return;
10309
+ const badge = mark.querySelector("[data-ca-annotation-index]");
10310
+ if (badge) badge.remove();
10311
+ parent.replaceChild(document.createTextNode(mark.textContent || ""), mark);
10312
+ parent.normalize();
10313
+ });
10314
+ }
10315
+ function ResponseCard2({
10316
+ text,
10317
+ isStreaming,
10318
+ streamStartTime,
10319
+ onOpenFile,
10320
+ onOpenUrl,
10321
+ onPopOut,
10322
+ variant = "response",
10323
+ sessionId,
10324
+ messageId,
10325
+ annotations,
10326
+ onAccept,
10327
+ onAcceptWithCompact,
10328
+ isLastResponse = true,
10329
+ showAcceptPlan = true,
10330
+ compactMode = false,
10331
+ onBranch,
10332
+ onAddAnnotation,
10333
+ onRemoveAnnotation,
10334
+ onUpdateAnnotation,
10335
+ sendMessageKey = "enter",
10336
+ onSaveAndSendFollowUp,
10337
+ hasActiveFollowUpAnnotations = false,
10338
+ openAnnotationRequest,
10339
+ annotationInteractionMode = "interactive"
10340
+ }) {
10341
+ const { t: t22 } = useTranslation32();
10342
+ const [displayedText, setDisplayedText] = useState62(text);
10343
+ const lastUpdateRef = useRef42(Date.now());
10344
+ const [copied, setCopied] = useState62(false);
10345
+ const [isFullscreen, setIsFullscreen] = useState62(false);
10346
+ const [isDarkMode, setIsDarkMode] = useState62(false);
10347
+ const interaction = useAnnotationInteractionController2();
10348
+ const {
10349
+ state: interactionState,
10350
+ setDraft: setFollowUpDraft,
10351
+ openFromSelection,
10352
+ openFollowUpFromSelection,
10353
+ openFromAnnotation,
10354
+ requestEdit,
10355
+ cancelFollowUp,
10356
+ closeAll,
10357
+ markSubmitSuccess,
10358
+ markDeleteSuccess,
10359
+ consumeExternalOpenRequest
10360
+ } = interaction;
10361
+ const pendingSelection = interactionState.pendingSelection;
10362
+ const selectionMenuView = interactionState.selectionMenuView;
10363
+ const followUpDraft = interactionState.followUpDraft;
10364
+ const followUpMode = interactionState.followUpMode;
10365
+ const activeAnnotationDetail = interactionState.activeAnnotationDetail;
10366
+ const [selectionMenuShowNonce, setSelectionMenuShowNonce] = useState62(0);
10367
+ const [selectionMenuTransitionConfig, setSelectionMenuTransitionConfig] = useState62(
10368
+ buildAnnotationChipEntryTransition2()
10369
+ );
10370
+ const [annotationOverlay, setAnnotationOverlay] = useState62({ rects: [], chips: [] });
10371
+ const contentRef = useRef42(null);
10372
+ const contentLayerRef = useRef42(null);
10373
+ const lastPointerRef = useRef42(null);
10374
+ const dragStartPointerRef = useRef42(null);
10375
+ const selectionStartedInContentRef = useRef42(false);
10376
+ const canAnnotate = canAnnotateMessage2({
10377
+ hasAddAnnotationHandler: !!onAddAnnotation,
10378
+ hasMessageId: !!messageId,
10379
+ isStreaming
10380
+ });
10381
+ const allowAnnotationIsland = annotationInteractionMode === "interactive";
10382
+ useEffect32(() => {
10383
+ const checkDarkMode = () => {
10384
+ setIsDarkMode(document.documentElement.classList.contains("dark"));
10385
+ };
10386
+ checkDarkMode();
10387
+ const observer = new MutationObserver(checkDarkMode);
10388
+ observer.observe(document.documentElement, { attributes: true, attributeFilter: ["class"] });
10389
+ return () => observer.disconnect();
10390
+ }, []);
10391
+ const closeSelectionMenu = useCallback52(() => {
10392
+ closeAll();
10393
+ }, [closeAll]);
10394
+ const isTargetInsideAnnotationIsland = useCallback52((target) => {
10395
+ if (!target) return false;
10396
+ const element = target instanceof Element ? target : target.parentElement;
10397
+ if (!element) return false;
10398
+ return !!element.closest('[data-ca-annotation-island="true"]');
10399
+ }, []);
10400
+ const triggerSelectionMenuEntryReplay = useCallback52(() => {
10401
+ setSelectionMenuShowNonce((prev) => prev + 1);
10402
+ }, []);
10403
+ const activeMenuAnchor = useMemo42(() => {
10404
+ return getAnnotationInteractionAnchor2(interactionState);
10405
+ }, [interactionState]);
10406
+ const selectionMenuSourceKey = useMemo42(() => {
10407
+ const messageScope = messageId ?? "no-message";
10408
+ return getAnnotationInteractionSourceKey2(interactionState, messageScope);
10409
+ }, [interactionState, messageId]);
10410
+ const {
10411
+ renderAnchor: selectionMenuRenderAnchor,
10412
+ renderSourceKey: selectionMenuRenderSourceKey,
10413
+ isVisible: isSelectionMenuVisible,
10414
+ openedAtRef: selectionMenuOpenedAtRef,
10415
+ handleExitComplete: handleSelectionMenuExitComplete,
10416
+ resetPresentation
10417
+ } = useAnnotationIslandPresentation2({
10418
+ anchor: activeMenuAnchor,
10419
+ sourceKey: selectionMenuSourceKey
10420
+ });
10421
+ const handleCopy = useCallback52(async () => {
10422
+ try {
10423
+ await navigator.clipboard.writeText(text);
10424
+ setCopied(true);
10425
+ setTimeout(() => setCopied(false), 2e3);
10426
+ } catch (err) {
10427
+ console.error("Failed to copy:", err);
10428
+ }
10429
+ }, [text]);
10430
+ const renderedAnnotations = useMemo42(() => {
10431
+ const persisted = annotations ?? [];
10432
+ if (!pendingSelection || !selectionMenuView || !messageId) {
10433
+ return persisted;
10434
+ }
10435
+ if (hasExistingTextRangeAnnotation2(persisted, pendingSelection.start, pendingSelection.end)) {
10436
+ return persisted;
10437
+ }
10438
+ return [
10439
+ ...persisted,
10440
+ createSelectionPreviewAnnotation2(messageId, pendingSelection, sessionId ?? "")
10441
+ ];
10442
+ }, [annotations, pendingSelection, selectionMenuView, messageId]);
10443
+ const activeAnnotation = useMemo42(() => {
10444
+ if (!activeAnnotationDetail) return null;
10445
+ return (annotations ?? []).find((annotation) => annotation.id === activeAnnotationDetail.annotationId) ?? null;
10446
+ }, [annotations, activeAnnotationDetail]);
10447
+ useEffect32(() => {
10448
+ if (!activeAnnotationDetail) return;
10449
+ if (!activeAnnotation) {
10450
+ closeSelectionMenu();
10451
+ }
10452
+ }, [activeAnnotationDetail, activeAnnotation, closeSelectionMenu]);
10453
+ useEffect32(() => {
10454
+ const root = contentLayerRef.current;
10455
+ if (!root) {
10456
+ setAnnotationOverlay({ rects: [], chips: [] });
10457
+ return;
10458
+ }
10459
+ const recomputeOverlay = () => {
10460
+ clearAnnotationMarks2(root);
10461
+ clearBlockAnnotationMarkers2(root);
10462
+ if (!renderedAnnotations.length) {
10463
+ setAnnotationOverlay({ rects: [], chips: [] });
10464
+ return;
10465
+ }
10466
+ const geometry = computeAnnotationOverlayGeometry2({
10467
+ root,
10468
+ renderedAnnotations,
10469
+ persistedAnnotations: annotations
10470
+ });
10471
+ for (const annotation of renderedAnnotations) {
10472
+ applyBlockAnnotationMarker2(root, annotation);
10473
+ }
10474
+ setAnnotationOverlay({ rects: geometry.rects, chips: geometry.chips });
10475
+ if (process.env.NODE_ENV !== "production" && geometry.unresolved.length > 0) {
10476
+ console.debug("[annotations] unresolved annotations", {
10477
+ count: geometry.unresolved.length,
10478
+ ids: geometry.unresolved.map((item) => item.annotation.id),
10479
+ reasons: geometry.unresolved.map((item) => item.reason)
10480
+ });
10481
+ }
10482
+ };
10483
+ recomputeOverlay();
10484
+ window.addEventListener("resize", recomputeOverlay);
10485
+ return () => {
10486
+ window.removeEventListener("resize", recomputeOverlay);
10487
+ };
10488
+ }, [annotations, renderedAnnotations, text, displayedText, isStreaming]);
10489
+ useEffect32(() => {
10490
+ if (!canAnnotate) {
10491
+ closeSelectionMenu();
10492
+ }
10493
+ }, [canAnnotate, closeSelectionMenu]);
10494
+ useEffect32(() => {
10495
+ closeSelectionMenu();
10496
+ resetPresentation();
10497
+ dragStartPointerRef.current = null;
10498
+ lastPointerRef.current = null;
10499
+ }, [sessionId, closeSelectionMenu, resetPresentation]);
10500
+ useEffect32(() => {
10501
+ if (!hasAnnotationInteraction2(interactionState) || !isSelectionMenuVisible) return;
10502
+ const handleSelectionChange = () => {
10503
+ if (selectionMenuOpenedAtRef.current == null || Date.now() - selectionMenuOpenedAtRef.current < 180) {
10504
+ return;
10505
+ }
10506
+ const root = contentLayerRef.current;
10507
+ if (!root) {
10508
+ closeSelectionMenu();
10509
+ return;
10510
+ }
10511
+ const selection = window.getSelection();
10512
+ if (!selection || selection.rangeCount === 0 || selection.isCollapsed) {
10513
+ return;
10514
+ }
10515
+ const range = selection.getRangeAt(0);
10516
+ const common = range.commonAncestorContainer;
10517
+ const commonElement = common.nodeType === Node.ELEMENT_NODE ? common : common.parentElement;
10518
+ if (commonElement && isTargetInsideAnnotationIsland(commonElement)) {
10519
+ return;
10520
+ }
10521
+ if (!root.contains(common)) {
10522
+ closeSelectionMenu();
10523
+ }
10524
+ };
10525
+ document.addEventListener("selectionchange", handleSelectionChange);
10526
+ return () => {
10527
+ document.removeEventListener("selectionchange", handleSelectionChange);
10528
+ };
10529
+ }, [interactionState, isSelectionMenuVisible, closeSelectionMenu, isTargetInsideAnnotationIsland, selectionMenuOpenedAtRef]);
10530
+ const handleOpenFollowUpView = useCallback52(() => {
10531
+ if (!pendingSelection) return;
10532
+ clearDomSelection2();
10533
+ openFollowUpFromSelection();
10534
+ }, [pendingSelection, openFollowUpFromSelection]);
10535
+ const handleRequestFollowUpEdit = useCallback52(() => {
10536
+ requestEdit();
10537
+ }, [requestEdit]);
10538
+ const saveFollowUp = useCallback52(async (note) => {
10539
+ const normalizedNote = note.trim();
10540
+ if (!messageId) return null;
10541
+ if (activeAnnotationDetail) {
10542
+ if (!onUpdateAnnotation || !activeAnnotation) {
10543
+ closeSelectionMenu();
10544
+ return null;
10545
+ }
10546
+ const existingOtherBodies = activeAnnotation.body.filter((body) => body.type !== "highlight" && body.type !== "note");
10547
+ const nextBody = [
10548
+ { type: "highlight" },
10549
+ ...normalizedNote.length > 0 ? [{ type: "note", text: normalizedNote, format: "plain" }] : [],
10550
+ ...existingOtherBodies
10551
+ ];
10552
+ const nextMeta = { ...activeAnnotation.meta ?? {} };
10553
+ delete nextMeta.followUp;
10554
+ try {
10555
+ await Promise.resolve(onUpdateAnnotation(messageId, activeAnnotationDetail.annotationId, {
10556
+ body: nextBody,
10557
+ intent: normalizedNote.length > 0 ? "comment" : "highlight",
10558
+ updatedAt: Date.now(),
10559
+ meta: normalizedNote.length > 0 ? {
10560
+ ...nextMeta,
10561
+ followUp: {
10562
+ text: normalizedNote,
10563
+ updatedAt: Date.now()
10564
+ }
10565
+ } : Object.keys(nextMeta).length > 0 ? nextMeta : void 0
10566
+ }));
10567
+ } catch {
10568
+ return null;
10569
+ }
10570
+ markSubmitSuccess();
10571
+ if (normalizedNote.length === 0) return null;
10572
+ return {
10573
+ messageId,
10574
+ annotationId: activeAnnotationDetail.annotationId,
10575
+ note: normalizedNote,
10576
+ selectedText: extractAnnotationSelectedText2(activeAnnotation, text)
10577
+ };
10578
+ }
10579
+ if (!onAddAnnotation || !pendingSelection) return null;
10580
+ if (hasExistingTextRangeAnnotation2(annotations ?? [], pendingSelection.start, pendingSelection.end)) {
10581
+ closeSelectionMenu();
10582
+ return null;
10583
+ }
10584
+ const annotation = createTextSelectionAnnotation2(messageId, sessionId ?? "", pendingSelection.start, pendingSelection.end, pendingSelection.exact ?? (activeAnnotation ? extractAnnotationSelectedText2(activeAnnotation, text) : ""), normalizedNote);
10585
+ try {
10586
+ await Promise.resolve(onAddAnnotation(messageId, annotation));
10587
+ } catch {
10588
+ return null;
10589
+ }
10590
+ markSubmitSuccess();
10591
+ clearDomSelection2();
10592
+ if (normalizedNote.length === 0) return null;
10593
+ return {
10594
+ messageId,
10595
+ annotationId: annotation.id,
10596
+ note: normalizedNote,
10597
+ selectedText: pendingSelection.selectedText ?? ""
10598
+ };
10599
+ }, [
10600
+ messageId,
10601
+ activeAnnotationDetail,
10602
+ activeAnnotation,
10603
+ onUpdateAnnotation,
10604
+ onAddAnnotation,
10605
+ pendingSelection,
10606
+ annotations,
10607
+ closeSelectionMenu,
10608
+ sessionId,
10609
+ markSubmitSuccess,
10610
+ text
10611
+ ]);
10612
+ const handleSubmitFollowUp = useCallback52((note) => {
10613
+ void saveFollowUp(note);
10614
+ }, [saveFollowUp]);
10615
+ const handleSubmitAndSendFollowUp = useCallback52((note) => {
10616
+ void saveFollowUp(note).then((savedFollowUp) => {
10617
+ if (!savedFollowUp) return;
10618
+ onSaveAndSendFollowUp?.(savedFollowUp);
10619
+ });
10620
+ }, [saveFollowUp, onSaveAndSendFollowUp]);
10621
+ const handleCancelFollowUp = useAnnotationCancelRestore2({
10622
+ contentRootRef: contentLayerRef,
10623
+ cancelFollowUp
10624
+ });
10625
+ const handleOpenAnnotationDetail = useCallback52((annotationId, index, anchorX, anchorY, mode = "view") => {
10626
+ if (!allowAnnotationIsland) return;
10627
+ const annotation = (annotations ?? []).find((item) => item.id === annotationId);
10628
+ const noteText = annotation ? getAnnotationNoteText2(annotation) : "";
10629
+ const transition = buildAnnotationChipEntryTransition2();
10630
+ setSelectionMenuTransitionConfig(transition);
10631
+ triggerSelectionMenuEntryReplay();
10632
+ openFromAnnotation({ annotationId, index, anchorX, anchorY }, noteText, mode);
10633
+ }, [allowAnnotationIsland, annotations, triggerSelectionMenuEntryReplay, openFromAnnotation]);
10634
+ useEffect32(() => {
10635
+ if (!allowAnnotationIsland) return;
10636
+ const contentRect = contentLayerRef.current?.getBoundingClientRect();
10637
+ const fallbackAnchor = {
10638
+ x: contentRect ? contentRect.left + contentRect.width / 2 : window.innerWidth / 2,
10639
+ y: contentRect ? contentRect.top + 20 : Math.max(24, window.innerHeight * 0.2)
10640
+ };
10641
+ const consumed = consumeExternalOpenRequest(openAnnotationRequest, {
10642
+ messageId,
10643
+ annotations,
10644
+ getNoteText: getAnnotationNoteText2,
10645
+ fallbackAnchor
10646
+ });
10647
+ if (!consumed) return;
10648
+ setSelectionMenuTransitionConfig(buildAnnotationChipEntryTransition2());
10649
+ triggerSelectionMenuEntryReplay();
10650
+ }, [
10651
+ allowAnnotationIsland,
10652
+ openAnnotationRequest,
10653
+ messageId,
10654
+ annotations,
10655
+ consumeExternalOpenRequest,
10656
+ triggerSelectionMenuEntryReplay
10657
+ ]);
10658
+ const handleDeleteActiveAnnotation = useCallback52(() => {
10659
+ if (!onRemoveAnnotation || !messageId || !activeAnnotationDetail) return;
10660
+ onRemoveAnnotation(messageId, activeAnnotationDetail.annotationId);
10661
+ markDeleteSuccess();
10662
+ }, [onRemoveAnnotation, messageId, activeAnnotationDetail, markDeleteSuccess]);
10663
+ const handleSelectionPointerDown = useCallback52((event) => {
10664
+ selectionStartedInContentRef.current = true;
10665
+ const snapshot = {
10666
+ x: event.clientX,
10667
+ y: event.clientY,
10668
+ timestamp: Date.now()
10669
+ };
10670
+ dragStartPointerRef.current = snapshot;
10671
+ lastPointerRef.current = snapshot;
10672
+ }, []);
10673
+ const showSelectionMenuFromCurrentSelection = useCallback52(() => {
10674
+ const root = contentLayerRef.current;
10675
+ if (!root) return;
10676
+ requestAnimationFrame(() => {
10677
+ const selection = window.getSelection();
10678
+ if (!selection || selection.rangeCount === 0 || selection.isCollapsed) {
10679
+ closeSelectionMenu();
10680
+ return;
10681
+ }
10682
+ const range = selection.getRangeAt(0);
10683
+ if (!root.contains(range.commonAncestorContainer)) {
10684
+ closeSelectionMenu();
10685
+ return;
10686
+ }
10687
+ const start = resolveNodeOffset2(root, range.startContainer, range.startOffset);
10688
+ const end = resolveNodeOffset2(root, range.endContainer, range.endOffset);
10689
+ if (start == null || end == null || end <= start) {
10690
+ closeSelectionMenu();
10691
+ return;
10692
+ }
10693
+ const selectedText = range.toString();
10694
+ if (!selectedText || !/\S/.test(selectedText)) {
10695
+ closeSelectionMenu();
10696
+ return;
10697
+ }
10698
+ if (hasExistingTextRangeAnnotation2(annotations ?? [], start, end)) {
10699
+ closeSelectionMenu();
10700
+ return;
10701
+ }
10702
+ const fullText = getCanonicalText2(root);
10703
+ const prefix = fullText.slice(Math.max(0, start - ANNOTATION_PREFIX_SUFFIX_WINDOW2), start);
10704
+ const suffix = fullText.slice(end, end + ANNOTATION_PREFIX_SUFFIX_WINDOW2);
10705
+ const rects = Array.from(range.getClientRects()).filter((rect) => rect.width > 0 && rect.height > 0);
10706
+ const pointer = lastPointerRef.current;
10707
+ const hasRecentPointer = Boolean(pointer && Date.now() - pointer.timestamp <= SELECTION_POINTER_MAX_AGE_MS2);
10708
+ const pointerX = hasRecentPointer && pointer ? pointer.x : null;
10709
+ const pointerY = hasRecentPointer && pointer ? pointer.y : null;
10710
+ let anchorRect;
10711
+ if (rects.length > 0) {
10712
+ if (pointerY != null) {
10713
+ const rowCandidates = rects.filter((rect) => pointerY >= rect.top && pointerY <= rect.bottom);
10714
+ if (rowCandidates.length > 0) {
10715
+ if (pointerX != null) {
10716
+ const xContaining = rowCandidates.filter((rect) => pointerX >= rect.left && pointerX <= rect.right);
10717
+ if (xContaining.length > 0) {
10718
+ anchorRect = xContaining.reduce((best, rect) => rect.width > best.width ? rect : best);
10719
+ } else {
10720
+ anchorRect = rowCandidates.reduce((best, rect) => {
10721
+ const bestDistance = Math.min(Math.abs(pointerX - best.left), Math.abs(pointerX - best.right));
10722
+ const rectDistance = Math.min(Math.abs(pointerX - rect.left), Math.abs(pointerX - rect.right));
10723
+ return rectDistance < bestDistance ? rect : best;
10724
+ });
10725
+ }
10726
+ } else {
10727
+ anchorRect = rowCandidates.reduce((best, rect) => rect.width > best.width ? rect : best);
10728
+ }
10729
+ } else {
10730
+ anchorRect = rects.reduce((best, rect) => {
10731
+ const bestDistance = Math.abs((best.top + best.bottom) / 2 - pointerY);
10732
+ const rectDistance = Math.abs((rect.top + rect.bottom) / 2 - pointerY);
10733
+ return rectDistance < bestDistance ? rect : best;
10734
+ });
10735
+ }
10736
+ } else {
10737
+ anchorRect = rects.reduce((best, rect) => rect.top < best.top ? rect : best);
10738
+ }
10739
+ } else {
10740
+ anchorRect = range.getBoundingClientRect();
10741
+ }
10742
+ const anchorRowRects = rects.length > 0 ? rects.filter((rect) => Math.abs(rect.top - anchorRect.top) <= 2) : [];
10743
+ const clampRects = anchorRowRects.length > 0 ? anchorRowRects : rects.length > 0 ? rects : [anchorRect];
10744
+ const selectionMinX = Math.min(...clampRects.map((rect) => rect.left));
10745
+ const selectionMaxX = Math.max(...clampRects.map((rect) => rect.right));
10746
+ const anchorX = pointerX != null ? clamp2(pointerX, selectionMinX, selectionMaxX) : anchorRect.left + anchorRect.width / 2;
10747
+ const anchorY = anchorRect.top - 8;
10748
+ const transition = buildSelectionEntryTransition2(dragStartPointerRef.current, pointer);
10749
+ setSelectionMenuTransitionConfig(transition);
10750
+ triggerSelectionMenuEntryReplay();
10751
+ openFromSelection({
10752
+ start,
10753
+ end,
10754
+ exact: selectedText,
10755
+ selectedText,
10756
+ prefix,
10757
+ suffix,
10758
+ anchorX,
10759
+ anchorY
10760
+ });
10761
+ dragStartPointerRef.current = null;
10762
+ });
10763
+ }, [annotations, closeSelectionMenu, triggerSelectionMenuEntryReplay, openFromSelection]);
10764
+ const handleTextSelection = useCallback52((event) => {
10765
+ if (!canAnnotate || !onAddAnnotation || !messageId) return;
10766
+ const root = contentLayerRef.current;
10767
+ if (!root) return;
10768
+ if (shouldIgnoreSelectionMouseUpTarget2(event.target)) {
10769
+ selectionStartedInContentRef.current = false;
10770
+ return;
10771
+ }
10772
+ lastPointerRef.current = {
10773
+ x: event.clientX,
10774
+ y: event.clientY,
10775
+ timestamp: Date.now()
10776
+ };
10777
+ if (event.shiftKey) {
10778
+ const targetElement = event.target instanceof Element ? event.target : null;
10779
+ const blockElement = targetElement?.closest("[data-ca-block-path]");
10780
+ if (blockElement) {
10781
+ const blockPath = blockElement.getAttribute("data-ca-block-path") || "";
10782
+ const blockType = blockElement.getAttribute("data-ca-block-type") || "paragraph";
10783
+ const blockId = blockElement.getAttribute("data-ca-block-id") || void 0;
10784
+ if (blockPath) {
10785
+ const alreadyExists = (annotations ?? []).some((annotation) => {
10786
+ const blockSelector = annotation.target.selectors.find((s) => s.type === "block");
10787
+ if (!blockSelector) return false;
10788
+ if (blockId && blockSelector.blockId) return blockSelector.blockId === blockId;
10789
+ return blockSelector.path === blockPath;
10790
+ });
10791
+ if (!alreadyExists) {
10792
+ const annotation = {
10793
+ id: `ann-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
10794
+ schemaVersion: 1,
10795
+ createdAt: Date.now(),
10796
+ intent: "highlight",
10797
+ body: [{ type: "highlight" }],
10798
+ target: {
10799
+ source: {
10800
+ sessionId: "",
10801
+ messageId
10802
+ },
10803
+ selectors: [
10804
+ {
10805
+ type: "block",
10806
+ blockType,
10807
+ path: blockPath,
10808
+ ...blockId ? { blockId } : {}
10809
+ }
10810
+ ]
10811
+ },
10812
+ style: { color: "yellow" }
10813
+ };
10814
+ onAddAnnotation(messageId, annotation);
10815
+ }
10816
+ }
10817
+ }
10818
+ selectionStartedInContentRef.current = false;
10819
+ closeSelectionMenu();
10820
+ return;
10821
+ }
10822
+ selectionStartedInContentRef.current = false;
10823
+ showSelectionMenuFromCurrentSelection();
10824
+ }, [canAnnotate, onAddAnnotation, messageId, annotations, showSelectionMenuFromCurrentSelection, closeSelectionMenu]);
10825
+ useEffect32(() => {
10826
+ if (!canAnnotate || !onAddAnnotation || !messageId) return;
10827
+ const handleDocumentMouseUp = (event) => {
10828
+ if (!selectionStartedInContentRef.current) return;
10829
+ selectionStartedInContentRef.current = false;
10830
+ lastPointerRef.current = {
10831
+ x: event.clientX,
10832
+ y: event.clientY,
10833
+ timestamp: Date.now()
10834
+ };
10835
+ const root = contentLayerRef.current;
10836
+ if (!root) return;
10837
+ const target = event.target;
10838
+ if (target && root.contains(target)) {
10839
+ return;
10840
+ }
10841
+ showSelectionMenuFromCurrentSelection();
10842
+ };
10843
+ document.addEventListener("mouseup", handleDocumentMouseUp);
10844
+ return () => {
10845
+ document.removeEventListener("mouseup", handleDocumentMouseUp);
10846
+ };
10847
+ }, [canAnnotate, onAddAnnotation, messageId, showSelectionMenuFromCurrentSelection]);
10848
+ const handleSelectionMenuRequestBack = useCallback52(() => {
10849
+ if (selectionMenuView !== "compact") {
10850
+ handleCancelFollowUp();
10851
+ return true;
10852
+ }
10853
+ return false;
10854
+ }, [selectionMenuView, handleCancelFollowUp]);
10855
+ useAnnotationIslandEvents2({
10856
+ enabled: allowAnnotationIsland && hasAnnotationInteraction2(interactionState) && isSelectionMenuVisible,
10857
+ openedAtRef: selectionMenuOpenedAtRef,
10858
+ isCompactView: selectionMenuView === "compact",
10859
+ isTargetInsideAnnotationIsland,
10860
+ onBack: handleSelectionMenuRequestBack,
10861
+ onClose: closeSelectionMenu
10862
+ });
10863
+ const selectionMenu = allowAnnotationIsland ? /* @__PURE__ */ jsx232(
10864
+ AnnotationIslandMenu2,
10865
+ {
10866
+ anchor: selectionMenuRenderAnchor,
10867
+ sourceKey: selectionMenuRenderSourceKey,
10868
+ replayNonce: selectionMenuShowNonce,
10869
+ isVisible: isSelectionMenuVisible,
10870
+ activeView: selectionMenuView,
10871
+ mode: followUpMode,
10872
+ draft: followUpDraft,
10873
+ onDraftChange: setFollowUpDraft,
10874
+ onOpenFollowUp: handleOpenFollowUpView,
10875
+ onCancel: handleCancelFollowUp,
10876
+ onRequestBack: handleSelectionMenuRequestBack,
10877
+ onRequestEdit: handleRequestFollowUpEdit,
10878
+ onSubmit: handleSubmitFollowUp,
10879
+ onSubmitAndSend: handleSubmitAndSendFollowUp,
10880
+ onDelete: activeAnnotationDetail ? handleDeleteActiveAnnotation : void 0,
10881
+ sendMessageKey,
10882
+ transitionConfig: selectionMenuTransitionConfig,
10883
+ onExitComplete: handleSelectionMenuExitComplete,
10884
+ usePortal: shouldRenderAnnotationIslandInPortal2("turncard")
10885
+ }
10886
+ ) : null;
10887
+ const annotationOverlayLayer = /* @__PURE__ */ jsx232(
10888
+ AnnotationOverlayLayer2,
10889
+ {
10890
+ rects: annotationOverlay.rects,
10891
+ chips: annotationOverlay.chips,
10892
+ annotations: renderedAnnotations,
10893
+ getTooltipText: (annotation) => formatAnnotationFollowUpTooltipText2(annotation),
10894
+ allowChipOpen: allowAnnotationIsland,
10895
+ onChipOpen: ({ annotationId, index, anchorX, anchorY, mode }) => {
10896
+ handleOpenAnnotationDetail(annotationId, index, anchorX, anchorY, mode);
10897
+ }
10898
+ }
10899
+ );
10900
+ useEffect32(() => {
10901
+ if (!isStreaming) {
10902
+ setDisplayedText(text);
10903
+ return;
10904
+ }
10905
+ const now = Date.now();
10906
+ const elapsed = now - lastUpdateRef.current;
10907
+ if (elapsed >= BUFFER_CONFIG2.CONTENT_THROTTLE_MS) {
10908
+ setDisplayedText(text);
10909
+ lastUpdateRef.current = now;
10910
+ } else {
10911
+ const timeout = setTimeout(() => {
10912
+ setDisplayedText(text);
10913
+ lastUpdateRef.current = Date.now();
10914
+ }, BUFFER_CONFIG2.CONTENT_THROTTLE_MS - elapsed);
10915
+ return () => clearTimeout(timeout);
10916
+ }
10917
+ }, [text, isStreaming]);
10918
+ const bufferDecision = useMemo42(() => {
10919
+ return shouldShowStreamingContent2(text, isStreaming, streamStartTime);
10920
+ }, [text, isStreaming, streamStartTime]);
10921
+ const isCompleted = !isStreaming;
10922
+ const isBuffering = isStreaming && !bufferDecision.shouldShow;
10923
+ if (isBuffering) {
10924
+ return null;
10925
+ }
10926
+ if (isCompleted || variant === "plan") {
10927
+ const isPlan = variant === "plan";
10928
+ return /* @__PURE__ */ jsxs102(Fragment82, { children: [
10929
+ /* @__PURE__ */ jsxs102("div", { className: "bg-background shadow-minimal rounded-[8px] overflow-hidden relative group", children: [
10930
+ !compactMode && /* @__PURE__ */ jsx232(
10931
+ "button",
10932
+ {
10933
+ onClick: () => setIsFullscreen(true),
10934
+ className: cn2(
10935
+ "absolute top-2 right-2 p-1 rounded-[6px] transition-all z-10 select-none",
10936
+ "opacity-0 group-hover:opacity-100",
10937
+ "bg-background shadow-minimal",
10938
+ "text-muted-foreground/50 hover:text-foreground",
10939
+ "focus:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:opacity-100"
10940
+ ),
10941
+ title: t22("common.viewFullscreen"),
10942
+ children: /* @__PURE__ */ jsx232(Maximize22, { className: "w-3.5 h-3.5" })
10943
+ }
10944
+ ),
10945
+ isPlan && /* @__PURE__ */ jsxs102(
10946
+ "div",
10947
+ {
10948
+ className: cn2(
10949
+ "px-4 py-2 border-b border-border/30 flex items-center gap-2 bg-success/5 select-none",
10950
+ SIZE_CONFIG2.fontSize
10951
+ ),
10952
+ children: [
10953
+ /* @__PURE__ */ jsx232(ListTodo2, { className: cn2(SIZE_CONFIG2.iconSize, "text-success") }),
10954
+ /* @__PURE__ */ jsx232("span", { className: "font-medium text-success", children: "Plan" })
10955
+ ]
10956
+ }
10957
+ ),
10958
+ /* @__PURE__ */ jsx232(
10959
+ "div",
10960
+ {
10961
+ ref: contentRef,
10962
+ "data-search-root": "response",
10963
+ onMouseDown: handleSelectionPointerDown,
10964
+ onMouseUp: handleTextSelection,
10965
+ className: "pl-[22px] pr-[16px] py-3 text-sm overflow-y-auto scrollbar-hover",
10966
+ style: {
10967
+ maxHeight: MAX_HEIGHT2,
10968
+ // Subtle fade at top and bottom edges (16px) - only in dark mode for better contrast
10969
+ ...isDarkMode && {
10970
+ maskImage: "linear-gradient(to bottom, transparent 0%, black 16px, black calc(100% - 16px), transparent 100%)",
10971
+ WebkitMaskImage: "linear-gradient(to bottom, transparent 0%, black 16px, black calc(100% - 16px), transparent 100%)"
10972
+ }
10973
+ },
10974
+ children: /* @__PURE__ */ jsxs102("div", { ref: contentLayerRef, className: "relative", children: [
10975
+ /* @__PURE__ */ jsx232(
10976
+ Markdown2,
10977
+ {
10978
+ mode: "minimal",
10979
+ onUrlClick: onOpenUrl,
10980
+ onFileClick: onOpenFile,
10981
+ children: text
10982
+ }
10983
+ ),
10984
+ annotationOverlayLayer
10985
+ ] })
10986
+ }
10987
+ ),
10988
+ !compactMode && /* @__PURE__ */ jsxs102("div", { className: cn2(
10989
+ "pl-4 pr-2.5 py-2 border-t border-border/30 flex items-center justify-between bg-muted/20",
10990
+ SIZE_CONFIG2.fontSize
10991
+ ), children: [
10992
+ /* @__PURE__ */ jsxs102("div", { className: "flex items-center gap-3", children: [
10993
+ /* @__PURE__ */ jsx232(
10994
+ "button",
10995
+ {
10996
+ onClick: handleCopy,
10997
+ className: cn2(
10998
+ "turn-action-btn flex items-center gap-1.5 transition-colors select-none",
10999
+ copied ? "text-success" : "text-muted-foreground hover:text-foreground",
11000
+ "focus:outline-none focus-visible:underline"
11001
+ ),
11002
+ children: copied ? /* @__PURE__ */ jsxs102(Fragment82, { children: [
11003
+ /* @__PURE__ */ jsx232(Check2, { className: SIZE_CONFIG2.iconSize }),
11004
+ /* @__PURE__ */ jsx232("span", { children: t22("common.copied") })
11005
+ ] }) : /* @__PURE__ */ jsxs102(Fragment82, { children: [
11006
+ /* @__PURE__ */ jsx232(Copy2, { className: SIZE_CONFIG2.iconSize }),
11007
+ /* @__PURE__ */ jsx232("span", { children: t22("common.copy") })
11008
+ ] })
11009
+ }
11010
+ ),
11011
+ onPopOut && /* @__PURE__ */ jsxs102(
11012
+ "button",
11013
+ {
11014
+ onClick: onPopOut,
11015
+ className: cn2(
11016
+ "turn-action-btn flex items-center gap-1.5 transition-colors select-none",
11017
+ "text-muted-foreground hover:text-foreground",
11018
+ "focus:outline-none focus-visible:underline"
11019
+ ),
11020
+ children: [
11021
+ /* @__PURE__ */ jsx232(FileText2, { className: SIZE_CONFIG2.iconSize }),
11022
+ /* @__PURE__ */ jsx232("span", { children: "Markdown" })
11023
+ ]
11024
+ }
11025
+ )
11026
+ ] }),
11027
+ /* @__PURE__ */ jsxs102("div", { className: "flex items-center gap-3", children: [
11028
+ isPlan && showAcceptPlan && onAccept && onAcceptWithCompact && /* @__PURE__ */ jsx232(
11029
+ "div",
11030
+ {
11031
+ className: cn2(
11032
+ "flex items-center gap-3 transition-all duration-200",
11033
+ isLastResponse ? "opacity-100 translate-x-0" : "opacity-0 translate-x-2 pointer-events-none"
11034
+ ),
11035
+ children: /* @__PURE__ */ jsx232(
11036
+ AcceptPlanDropdown2,
11037
+ {
11038
+ onAccept,
11039
+ onAcceptWithCompact,
11040
+ acceptLabel: hasActiveFollowUpAnnotations ? t22("plan.acceptAndSendFollowups") : t22("plan.acceptPlan"),
11041
+ acceptOptionLabel: hasActiveFollowUpAnnotations ? t22("plan.acceptAndSendFollowups") : t22("plan.accept")
11042
+ }
11043
+ )
11044
+ }
11045
+ ),
11046
+ onBranch && /* @__PURE__ */ jsx232(BranchDropdown2, { onBranch })
11047
+ ] })
11048
+ ] })
11049
+ ] }),
11050
+ /* @__PURE__ */ jsx232(
11051
+ DocumentFormattedMarkdownOverlay2,
11052
+ {
11053
+ content: text,
11054
+ isOpen: isFullscreen,
11055
+ onClose: () => setIsFullscreen(false),
11056
+ variant: isPlan ? "plan" : void 0,
11057
+ onOpenUrl,
11058
+ onOpenFile,
11059
+ sessionId,
11060
+ messageId,
11061
+ annotations,
11062
+ onAddAnnotation,
11063
+ onRemoveAnnotation,
11064
+ onUpdateAnnotation,
11065
+ sendMessageKey,
11066
+ openAnnotationRequest,
11067
+ isStreaming
11068
+ }
11069
+ ),
11070
+ selectionMenu
11071
+ ] });
11072
+ }
11073
+ return /* @__PURE__ */ jsxs102(Fragment82, { children: [
11074
+ /* @__PURE__ */ jsxs102("div", { className: "bg-background shadow-minimal rounded-[8px] overflow-hidden group", children: [
11075
+ /* @__PURE__ */ jsx232(
11076
+ "div",
11077
+ {
11078
+ ref: contentRef,
11079
+ "data-search-root": "response",
11080
+ onMouseDown: handleSelectionPointerDown,
11081
+ onMouseUp: handleTextSelection,
11082
+ className: "pl-[22px] pr-4 py-3 text-sm overflow-y-auto scrollbar-hover",
11083
+ style: {
11084
+ maxHeight: MAX_HEIGHT2,
11085
+ // Subtle fade at top and bottom edges (16px) - only in dark mode for better contrast
11086
+ ...isDarkMode && {
11087
+ maskImage: "linear-gradient(to bottom, transparent 0%, black 16px, black calc(100% - 16px), transparent 100%)",
11088
+ WebkitMaskImage: "linear-gradient(to bottom, transparent 0%, black 16px, black calc(100% - 16px), transparent 100%)"
11089
+ }
11090
+ },
11091
+ children: /* @__PURE__ */ jsxs102("div", { ref: contentLayerRef, className: "relative", children: [
11092
+ /* @__PURE__ */ jsx232(
11093
+ Markdown2,
11094
+ {
11095
+ mode: "minimal",
11096
+ onUrlClick: onOpenUrl,
11097
+ onFileClick: onOpenFile,
11098
+ children: displayedText
11099
+ }
11100
+ ),
11101
+ annotationOverlayLayer
11102
+ ] })
11103
+ }
11104
+ ),
11105
+ !compactMode && /* @__PURE__ */ jsx232("div", { className: cn2("px-4 py-2 border-t border-border/30 flex items-center bg-muted/20", SIZE_CONFIG2.fontSize), children: /* @__PURE__ */ jsxs102("div", { className: "flex items-center gap-2 text-muted-foreground", children: [
11106
+ /* @__PURE__ */ jsx232(Spinner2, { className: SIZE_CONFIG2.spinnerSize }),
11107
+ /* @__PURE__ */ jsx232("span", { children: "Streaming..." })
11108
+ ] }) })
11109
+ ] }),
11110
+ selectionMenu
11111
+ ] });
11112
+ }
11113
+ function TodoStatusIcon2({ status }) {
11114
+ switch (status) {
11115
+ case "pending":
11116
+ return /* @__PURE__ */ jsx242(Circle22, { className: cn2(SIZE_CONFIG2.iconSize, "shrink-0 text-muted-foreground/50") });
11117
+ case "in_progress":
11118
+ return /* @__PURE__ */ jsx242("div", { className: cn2(SIZE_CONFIG2.iconSize, "flex items-center justify-center shrink-0"), children: /* @__PURE__ */ jsx242(Spinner2, { className: SIZE_CONFIG2.spinnerSize }) });
11119
+ case "completed":
11120
+ return /* @__PURE__ */ jsx242(CircleCheck2, { className: cn2(SIZE_CONFIG2.iconSize, "shrink-0 text-accent") });
11121
+ case "interrupted":
11122
+ return /* @__PURE__ */ jsx242(Ban2, { className: cn2(SIZE_CONFIG2.iconSize, "shrink-0 text-muted-foreground/50") });
11123
+ }
11124
+ }
11125
+ function TodoRow2({ todo }) {
11126
+ const displayText = todo.status === "in_progress" && todo.activeForm ? todo.activeForm : todo.content;
11127
+ return /* @__PURE__ */ jsxs112("div", { className: cn2(
11128
+ "flex items-center gap-2 py-0.5 text-muted-foreground",
11129
+ SIZE_CONFIG2.fontSize,
11130
+ todo.status === "completed" && "opacity-50"
11131
+ ), children: [
11132
+ /* @__PURE__ */ jsx242(TodoStatusIcon2, { status: todo.status }),
11133
+ /* @__PURE__ */ jsx242("span", { className: cn2(
11134
+ "truncate flex-1",
11135
+ todo.status === "completed" && "line-through"
11136
+ ), children: displayText })
11137
+ ] });
11138
+ }
11139
+ function TodoList2({ todos }) {
11140
+ if (todos.length === 0) return null;
11141
+ return /* @__PURE__ */ jsxs112("div", { className: "pl-4 pr-2 pt-2.5 pb-1.5 space-y-0.5 border-l-2 border-muted ml-[13px]", children: [
11142
+ /* @__PURE__ */ jsx242("div", { className: cn2("text-muted-foreground pb-1", SIZE_CONFIG2.fontSize), children: "Todo List" }),
11143
+ todos.map((todo, index) => /* @__PURE__ */ jsx242(
11144
+ motion32.div,
11145
+ {
11146
+ initial: { opacity: 0, x: -8 },
11147
+ animate: { opacity: 1, x: 0 },
11148
+ transition: { delay: index * 0.03 },
11149
+ children: /* @__PURE__ */ jsx242(TodoRow2, { todo })
11150
+ },
11151
+ `${todo.content}-${index}`
11152
+ ))
11153
+ ] });
11154
+ }
11155
+ var TurnCard3 = React102.memo(function TurnCard22({
11156
+ sessionId,
11157
+ turnId,
11158
+ activities,
11159
+ response,
11160
+ intent,
11161
+ isStreaming,
11162
+ isComplete,
11163
+ defaultExpanded = false,
11164
+ isExpanded: externalIsExpanded,
11165
+ onExpandedChange,
11166
+ expandedActivityGroups: externalExpandedActivityGroups,
11167
+ onExpandedActivityGroupsChange,
11168
+ onOpenFile,
11169
+ onOpenUrl,
11170
+ onPopOut,
11171
+ onOpenDetails,
11172
+ onOpenActivityDetails,
11173
+ onOpenMultiFileDiff,
11174
+ hasEditOrWriteActivities,
11175
+ todos,
11176
+ renderActionsMenu,
11177
+ onAcceptPlan,
11178
+ onAcceptPlanWithCompact,
11179
+ isLastResponse,
11180
+ sessionFolderPath,
11181
+ displayMode = "detailed",
11182
+ animateResponse = false,
11183
+ compactMode = false,
11184
+ onBranch,
11185
+ onAddAnnotation,
11186
+ onRemoveAnnotation,
11187
+ onUpdateAnnotation,
11188
+ sendMessageKey = "enter",
11189
+ onSaveAndSendFollowUp,
11190
+ hasActiveFollowUpAnnotations = false,
11191
+ openAnnotationRequest,
11192
+ annotationInteractionMode = "interactive"
11193
+ }) {
11194
+ const turnPhase = useMemo52(() => {
11195
+ const turnData = {
11196
+ isComplete,
11197
+ response,
11198
+ activities
11199
+ };
11200
+ return deriveTurnPhase2(turnData);
11201
+ }, [isComplete, response, activities]);
11202
+ const [localExpandedTurns, setLocalExpandedTurns] = useState72(() => defaultExpanded ? /* @__PURE__ */ new Set([turnId]) : /* @__PURE__ */ new Set());
11203
+ const isExpanded = externalIsExpanded ?? localExpandedTurns.has(turnId);
11204
+ const hasUserToggled = useRef52(false);
11205
+ const activitiesContainerRef = useRef52(null);
11206
+ const hasMounted = useRef52(false);
11207
+ useEffect42(() => {
11208
+ hasMounted.current = true;
11209
+ }, []);
11210
+ const toggleExpanded = useCallback62(() => {
11211
+ hasUserToggled.current = true;
11212
+ const newExpanded = !isExpanded;
11213
+ if (onExpandedChange) {
11214
+ onExpandedChange(newExpanded);
11215
+ } else {
11216
+ setLocalExpandedTurns((prev) => {
11217
+ const next = new Set(prev);
11218
+ if (next.has(turnId)) {
11219
+ next.delete(turnId);
11220
+ } else {
11221
+ next.add(turnId);
11222
+ }
11223
+ return next;
11224
+ });
11225
+ }
11226
+ }, [turnId, isExpanded, onExpandedChange]);
11227
+ useEffect42(() => {
11228
+ if (isExpanded && hasUserToggled.current && activitiesContainerRef.current) {
11229
+ const timer = setTimeout(() => {
11230
+ activitiesContainerRef.current?.scrollTo({
11231
+ top: activitiesContainerRef.current.scrollHeight,
11232
+ behavior: "smooth"
11233
+ });
11234
+ }, 260);
11235
+ return () => clearTimeout(timer);
11236
+ }
11237
+ }, [isExpanded]);
11238
+ const [localExpandedActivityGroups, setLocalExpandedActivityGroups] = useState72(/* @__PURE__ */ new Set());
11239
+ const expandedActivityGroups = externalExpandedActivityGroups ?? localExpandedActivityGroups;
11240
+ const handleExpandedActivityGroupsChange = onExpandedActivityGroupsChange ?? setLocalExpandedActivityGroups;
11241
+ const isBuffering = useMemo52(
11242
+ () => isResponseBuffering2(response),
11243
+ [response]
11244
+ );
11245
+ const previewText = useMemo52(
11246
+ () => getPreviewText2(activities, intent, isStreaming, !!response, isComplete),
11247
+ [activities, intent, isStreaming, response, isComplete, i18n22.language]
11248
+ );
11249
+ const allSortedActivities = useMemo52(
11250
+ () => [...activities].sort((a, b) => a.timestamp - b.timestamp),
11251
+ [activities]
11252
+ );
11253
+ const planActivities = useMemo52(
11254
+ () => allSortedActivities.filter((a) => a.type === "plan"),
11255
+ [allSortedActivities]
11256
+ );
11257
+ const sortedActivities = useMemo52(
11258
+ () => allSortedActivities.filter((a) => a.type !== "plan"),
11259
+ [allSortedActivities]
11260
+ );
11261
+ const hasTaskSubagents = useMemo52(
11262
+ () => sortedActivities.some((a) => a.toolName === "Task"),
11263
+ [sortedActivities]
11264
+ );
11265
+ const groupedActivities = useMemo52(
11266
+ () => hasTaskSubagents ? groupActivitiesByParent2(sortedActivities) : null,
11267
+ [sortedActivities, hasTaskSubagents]
11268
+ );
11269
+ const lastChildSet = useMemo52(
11270
+ () => !hasTaskSubagents ? computeLastChildSet2(sortedActivities) : /* @__PURE__ */ new Set(),
11271
+ [sortedActivities, hasTaskSubagents]
11272
+ );
11273
+ if (activities.length === 0 && !response && isComplete) {
11274
+ return null;
11275
+ }
11276
+ const hasNoMeaningfulWork = activities.length > 0 && activities.every((a) => {
11277
+ if (a.type === "tool") return a.status === "error";
11278
+ if (a.type === "intermediate") return !a.content?.trim();
11279
+ if (a.type === "plan") return false;
11280
+ return true;
11281
+ }) && !response;
11282
+ if (hasNoMeaningfulWork) {
11283
+ return null;
11284
+ }
11285
+ const hasActivities = sortedActivities.length > 0;
11286
+ const isThinking = shouldShowThinkingIndicator2(turnPhase, isBuffering);
11287
+ return /* @__PURE__ */ jsxs122("div", { className: "space-y-1", children: [
11288
+ hasActivities && /* @__PURE__ */ jsxs122("div", { className: "group select-none", "data-search-exclude": "true", children: [
11289
+ /* @__PURE__ */ jsxs122(
11290
+ "button",
11291
+ {
11292
+ onClick: toggleExpanded,
11293
+ className: cn2(
11294
+ "flex items-center gap-2 w-full pl-2.5 pr-1.5 py-1.5 rounded-[8px] text-left",
11295
+ SIZE_CONFIG2.fontSize,
11296
+ "text-muted-foreground",
11297
+ "hover:bg-muted/50 transition-colors",
11298
+ "focus:outline-none focus-visible:ring-1 focus-visible:ring-ring"
11299
+ ),
11300
+ children: [
11301
+ /* @__PURE__ */ jsx252(
11302
+ motion42.div,
11303
+ {
11304
+ initial: false,
11305
+ animate: { rotate: isExpanded ? 90 : 0 },
11306
+ transition: { duration: 0.15, ease: "easeOut" },
11307
+ className: cn2(SIZE_CONFIG2.iconSize, "flex items-center justify-center shrink-0"),
11308
+ children: /* @__PURE__ */ jsx252(ChevronRight32, { className: SIZE_CONFIG2.iconSize })
11309
+ }
11310
+ ),
11311
+ /* @__PURE__ */ jsx252("span", { className: "-ml-0.5 shrink-0 px-1.5 py-0.5 rounded-[4px] bg-background shadow-minimal text-[10px] font-medium tabular-nums", children: activities.length }),
11312
+ /* @__PURE__ */ jsx252("span", { className: "relative flex-1 min-w-0 h-5 flex items-center", children: /* @__PURE__ */ jsx252(AnimatePresence32, { initial: false, children: /* @__PURE__ */ jsx252(
11313
+ motion42.span,
11314
+ {
11315
+ initial: { opacity: 0 },
11316
+ animate: { opacity: 1 },
11317
+ exit: { opacity: 0 },
11318
+ transition: { duration: 0.2 },
11319
+ className: "absolute inset-0 truncate",
11320
+ children: previewText
11321
+ },
11322
+ previewText
11323
+ ) }) }),
11324
+ renderActionsMenu ? renderActionsMenu() : /* @__PURE__ */ jsx252(
11325
+ TurnCardActionsMenu2,
11326
+ {
11327
+ onOpenDetails,
11328
+ onOpenMultiFileDiff,
11329
+ hasEditOrWriteActivities
11330
+ }
11331
+ )
11332
+ ]
11333
+ }
11334
+ ),
11335
+ /* @__PURE__ */ jsx252(AnimatePresence32, { initial: false, children: isExpanded && /* @__PURE__ */ jsxs122(
11336
+ motion42.div,
11337
+ {
11338
+ initial: { height: 0, opacity: 0 },
11339
+ animate: { height: "auto", opacity: 1 },
11340
+ exit: { height: 0, opacity: 0 },
11341
+ transition: {
11342
+ height: { duration: 0.25, ease: [0.4, 0, 0.2, 1] },
11343
+ opacity: { duration: 0.15 }
11344
+ },
11345
+ className: "overflow-hidden",
11346
+ children: [
11347
+ /* @__PURE__ */ jsx252(
11348
+ "div",
11349
+ {
11350
+ ref: activitiesContainerRef,
11351
+ className: cn2(
11352
+ "pl-4 pr-2 py-0 space-y-0.5 border-l-2 border-muted ml-[13px]",
11353
+ sortedActivities.length > SIZE_CONFIG2.maxVisibleActivities && "rounded-r-md overflow-y-auto scrollbar-hover py-1.5"
11354
+ ),
11355
+ style: {
11356
+ maxHeight: sortedActivities.length > SIZE_CONFIG2.maxVisibleActivities ? SIZE_CONFIG2.maxVisibleActivities * SIZE_CONFIG2.activityRowHeight : void 0
11357
+ },
11358
+ children: /* @__PURE__ */ jsxs122(AnimatePresence32, { mode: "sync", children: [
11359
+ groupedActivities ? groupedActivities.map((item, index) => isActivityGroup2(item) ? /* @__PURE__ */ jsx252(
11360
+ ActivityGroupRow2,
11361
+ {
11362
+ group: item,
11363
+ expandedGroups: expandedActivityGroups,
11364
+ onExpandedGroupsChange: handleExpandedActivityGroupsChange,
11365
+ onOpenActivityDetails,
11366
+ animationIndex: index,
11367
+ sessionFolderPath,
11368
+ displayMode
11369
+ },
11370
+ item.parent.id
11371
+ ) : /* @__PURE__ */ jsx252(
11372
+ motion42.div,
11373
+ {
11374
+ initial: hasUserToggled.current || hasMounted.current ? { opacity: 0, x: -8 } : false,
11375
+ animate: { opacity: 1, x: 0 },
11376
+ transition: { delay: hasUserToggled.current ? index < SIZE_CONFIG2.staggeredAnimationLimit ? index * 0.03 : SIZE_CONFIG2.staggeredAnimationLimit * 0.03 : 0 },
11377
+ children: /* @__PURE__ */ jsx252(
11378
+ ActivityRow2,
11379
+ {
11380
+ activity: item,
11381
+ onOpenDetails: onOpenActivityDetails ? () => onOpenActivityDetails(item) : void 0,
11382
+ sessionFolderPath,
11383
+ displayMode
11384
+ }
11385
+ )
11386
+ },
11387
+ item.id
11388
+ )) : (
11389
+ /* Flat view for simple tool calls */
11390
+ sortedActivities.map((activity, index) => /* @__PURE__ */ jsx252(
11391
+ motion42.div,
11392
+ {
11393
+ initial: hasUserToggled.current || hasMounted.current ? { opacity: 0, x: -8 } : false,
11394
+ animate: { opacity: 1, x: 0 },
11395
+ transition: { delay: hasUserToggled.current ? index < SIZE_CONFIG2.staggeredAnimationLimit ? index * 0.03 : SIZE_CONFIG2.staggeredAnimationLimit * 0.03 : 0 },
11396
+ children: /* @__PURE__ */ jsx252(
11397
+ ActivityRow2,
11398
+ {
11399
+ activity,
11400
+ onOpenDetails: onOpenActivityDetails ? () => onOpenActivityDetails(activity) : void 0,
11401
+ isLastChild: lastChildSet.has(activity.id),
11402
+ sessionFolderPath,
11403
+ displayMode
11404
+ }
11405
+ )
11406
+ },
11407
+ activity.id
11408
+ ))
11409
+ ),
11410
+ isThinking && /* @__PURE__ */ jsxs122(
11411
+ motion42.div,
11412
+ {
11413
+ initial: { opacity: 0, x: -8 },
11414
+ animate: { opacity: 1, x: 0 },
11415
+ transition: {
11416
+ delay: Math.min(sortedActivities.length, SIZE_CONFIG2.staggeredAnimationLimit) * 0.03,
11417
+ duration: 0.3,
11418
+ ease: "easeOut"
11419
+ },
11420
+ className: cn2("flex items-center gap-2 py-0.5 text-muted-foreground/70", SIZE_CONFIG2.fontSize),
11421
+ children: [
11422
+ /* @__PURE__ */ jsx252(Spinner2, { className: SIZE_CONFIG2.spinnerSize }),
11423
+ /* @__PURE__ */ jsx252("span", { children: isBuffering ? "Preparing response..." : "Thinking..." })
11424
+ ]
11425
+ },
11426
+ "thinking"
11427
+ )
11428
+ ] })
11429
+ }
11430
+ ),
11431
+ todos && todos.length > 0 && /* @__PURE__ */ jsx252(TodoList2, { todos })
11432
+ ]
11433
+ }
11434
+ ) })
11435
+ ] }),
11436
+ !hasActivities && isThinking && /* @__PURE__ */ jsxs122("div", { className: cn2("flex items-center gap-2 px-3 py-1.5 text-muted-foreground", SIZE_CONFIG2.fontSize), children: [
11437
+ /* @__PURE__ */ jsx252(Spinner2, { className: SIZE_CONFIG2.spinnerSize }),
11438
+ /* @__PURE__ */ jsx252("span", { children: isBuffering ? "Preparing response..." : "Thinking..." })
11439
+ ] }),
11440
+ planActivities.map((planActivity, index) => /* @__PURE__ */ jsx252("div", { className: cn2("select-text", (hasActivities || index > 0) && "mt-2"), children: /* @__PURE__ */ jsx252(
11441
+ ResponseCard2,
11442
+ {
11443
+ text: planActivity.content || "",
11444
+ isStreaming: false,
11445
+ sessionId,
11446
+ onOpenFile,
11447
+ onOpenUrl,
11448
+ onPopOut: onPopOut ? () => onPopOut(planActivity.content || "") : void 0,
11449
+ variant: "plan",
11450
+ messageId: planActivity.messageId,
11451
+ annotations: planActivity.annotations,
11452
+ onAddAnnotation,
11453
+ onRemoveAnnotation,
11454
+ onUpdateAnnotation,
11455
+ onSaveAndSendFollowUp,
11456
+ onAccept: onAcceptPlan,
11457
+ onAcceptWithCompact: onAcceptPlanWithCompact,
11458
+ isLastResponse: isLastResponse && index === planActivities.length - 1,
11459
+ compactMode,
11460
+ onBranch: onBranch ? (options) => onBranch(planActivity.messageId ?? planActivity.id, options) : void 0,
11461
+ sendMessageKey,
11462
+ hasActiveFollowUpAnnotations,
11463
+ openAnnotationRequest,
11464
+ annotationInteractionMode
11465
+ }
11466
+ ) }, planActivity.id)),
11467
+ animateResponse && /* @__PURE__ */ jsx252(AnimatePresence32, { children: response && !isBuffering && /* @__PURE__ */ jsx252(
11468
+ motion42.div,
11469
+ {
11470
+ initial: { opacity: 0, y: 8 },
11471
+ animate: { opacity: 1, y: 0 },
11472
+ transition: { duration: 0.3, ease: "easeOut" },
11473
+ className: cn2("select-text", hasActivities && "mt-2"),
11474
+ children: /* @__PURE__ */ jsx252(
11475
+ ResponseCard2,
11476
+ {
11477
+ text: response.text,
11478
+ isStreaming: response.isStreaming,
11479
+ streamStartTime: response.streamStartTime,
11480
+ sessionId,
11481
+ onOpenFile,
11482
+ onOpenUrl,
11483
+ onPopOut: onPopOut ? () => onPopOut(response.text) : void 0,
11484
+ variant: response.isPlan ? "plan" : "response",
11485
+ messageId: response.messageId,
11486
+ annotations: response.annotations,
11487
+ onAddAnnotation,
11488
+ onRemoveAnnotation,
11489
+ onUpdateAnnotation,
11490
+ onSaveAndSendFollowUp,
11491
+ onAccept: onAcceptPlan,
11492
+ onAcceptWithCompact: onAcceptPlanWithCompact,
11493
+ isLastResponse,
11494
+ compactMode,
11495
+ onBranch: onBranch && response.messageId ? (options) => onBranch(response.messageId, options) : void 0,
11496
+ sendMessageKey,
11497
+ hasActiveFollowUpAnnotations,
11498
+ openAnnotationRequest,
11499
+ annotationInteractionMode
11500
+ }
11501
+ )
11502
+ }
11503
+ ) }),
11504
+ !animateResponse && response && !isBuffering && /* @__PURE__ */ jsx252("div", { className: cn2("select-text", hasActivities && "mt-2"), children: /* @__PURE__ */ jsx252(
11505
+ ResponseCard2,
11506
+ {
11507
+ text: response.text,
11508
+ isStreaming: response.isStreaming,
11509
+ streamStartTime: response.streamStartTime,
11510
+ sessionId,
11511
+ onOpenFile,
11512
+ onOpenUrl,
11513
+ onPopOut: onPopOut ? () => onPopOut(response.text) : void 0,
11514
+ variant: response.isPlan ? "plan" : "response",
11515
+ messageId: response.messageId,
11516
+ annotations: response.annotations,
11517
+ onAddAnnotation,
11518
+ onRemoveAnnotation,
11519
+ onUpdateAnnotation,
11520
+ onSaveAndSendFollowUp,
11521
+ onAccept: onAcceptPlan,
11522
+ onAcceptWithCompact: onAcceptPlanWithCompact,
11523
+ isLastResponse,
11524
+ compactMode,
11525
+ onBranch: onBranch && response.messageId ? (options) => onBranch(response.messageId, options) : void 0,
11526
+ sendMessageKey,
11527
+ hasActiveFollowUpAnnotations,
11528
+ openAnnotationRequest,
11529
+ annotationInteractionMode
11530
+ }
11531
+ ) })
11532
+ ] });
11533
+ }, (prev, next) => {
11534
+ if (prev.isStreaming || next.isStreaming) return false;
11535
+ if (!prev.isComplete || !next.isComplete) return false;
11536
+ if (prev.isExpanded !== next.isExpanded) return false;
11537
+ if (prev.expandedActivityGroups !== next.expandedActivityGroups) return false;
11538
+ if (prev.isLastResponse !== next.isLastResponse) return false;
11539
+ if (prev.displayMode !== next.displayMode) return false;
11540
+ if (prev.annotationInteractionMode !== next.annotationInteractionMode) return false;
11541
+ if (prev.activities !== next.activities) {
11542
+ if (prev.activities.length !== next.activities.length) return false;
11543
+ for (let i = 0; i < prev.activities.length; i++) {
11544
+ const pa = prev.activities[i], na = next.activities[i];
11545
+ if (pa.id !== na.id || pa.status !== na.status || pa.content !== na.content) return false;
11546
+ }
11547
+ }
11548
+ if (prev.response !== next.response) {
11549
+ if (!prev.response !== !next.response) return false;
11550
+ if (prev.response && next.response) {
11551
+ if (prev.response.text !== next.response.text || prev.response.isStreaming !== next.response.isStreaming || prev.response.messageId !== next.response.messageId || prev.response.annotations?.length !== next.response.annotations?.length) return false;
11552
+ }
11553
+ }
11554
+ if (prev.openAnnotationRequest !== next.openAnnotationRequest) return false;
11555
+ if (prev.hasActiveFollowUpAnnotations !== next.hasActiveFollowUpAnnotations) return false;
11556
+ return prev.sessionId === next.sessionId && prev.turnId === next.turnId;
11557
+ });
11558
+ var PlatformContext2 = createContext32({});
11559
+ var initialRuntimeState = {
11560
+ status: "idle",
11561
+ acceptedMessages: [],
11562
+ queuedMessages: []
11563
+ };
11564
+ function useAgentSession(options) {
11565
+ const createRuntimeRef = useRef92(options.createRuntime);
11566
+ createRuntimeRef.current = options.createRuntime;
11567
+ const runtime = useMemo92(() => {
11568
+ return createDeferredAgentRuntime({
11569
+ provider: options.provider ?? "agent",
11570
+ runtimeKind: options.runtimeKind ?? "app-server",
11571
+ sessionId: options.sessionId,
11572
+ createRuntime: () => createRuntimeRef.current()
11573
+ });
11574
+ }, [options.sessionId]);
11575
+ useEffect102(() => {
11576
+ return () => {
11577
+ void runtime.disposeIfCreated();
11578
+ };
11579
+ }, [runtime]);
11580
+ return { runtime, sessionId: options.sessionId };
11581
+ }
11582
+ function createDeferredAgentRuntime(options) {
11583
+ let runtime = null;
11584
+ let disposed = false;
11585
+ const getRuntime = () => {
11586
+ if (disposed) {
11587
+ throw new Error("Agent runtime has been disposed");
11588
+ }
11589
+ runtime ??= options.createRuntime();
11590
+ return runtime;
11591
+ };
11592
+ return {
11593
+ get sessionId() {
11594
+ return runtime?.sessionId ?? options.sessionId;
11595
+ },
11596
+ get provider() {
11597
+ return runtime?.provider ?? options.provider;
11598
+ },
11599
+ get runtimeKind() {
11600
+ return runtime?.runtimeKind ?? options.runtimeKind;
11601
+ },
11602
+ events: {
11603
+ connect(onEvent, onError, onClose) {
11604
+ getRuntime().events.connect(onEvent, onError, onClose);
11605
+ },
11606
+ disconnect() {
11607
+ runtime?.events.disconnect();
11608
+ },
11609
+ isConnected() {
11610
+ return runtime?.events.isConnected() ?? false;
11611
+ }
11612
+ },
11613
+ commands: {
11614
+ sendMessage(message, sendOptions) {
11615
+ return getRuntime().commands.sendMessage(message, sendOptions);
11616
+ },
11617
+ abort(reason) {
11618
+ return getRuntime().commands.abort(reason);
11619
+ },
11620
+ respondToPermission(requestId, allowed, remember) {
11621
+ return getRuntime().commands.respondToPermission(requestId, allowed, remember);
11622
+ },
11623
+ async resumeTool(runId, resumeData) {
11624
+ const commands = getRuntime().commands;
11625
+ if (!commands.resumeTool) {
11626
+ throw new Error(`resumeTool is not supported by the ${options.provider} runtime`);
11627
+ }
11628
+ await commands.resumeTool(runId, resumeData);
11629
+ },
11630
+ dispose() {
11631
+ disposed = true;
11632
+ const current = runtime;
11633
+ runtime = null;
11634
+ return current?.commands.dispose() ?? Promise.resolve();
11635
+ }
11636
+ },
11637
+ preflight() {
11638
+ return getRuntime().preflight();
11639
+ },
11640
+ fetchTimeline(request) {
11641
+ return getRuntime().fetchTimeline(request);
11642
+ },
11643
+ getState() {
11644
+ return runtime?.getState() ?? {
11645
+ status: initialRuntimeState.status,
11646
+ acceptedMessages: [],
11647
+ queuedMessages: []
11648
+ };
11649
+ },
11650
+ async disposeIfCreated() {
11651
+ if (!runtime) return;
11652
+ const current = runtime;
11653
+ runtime = null;
11654
+ await current.commands.dispose();
11655
+ }
11656
+ };
11657
+ }
7825
11658
  export {
7826
11659
  ActivityDetailsPanel,
7827
11660
  ActivityInspector,
@@ -7881,6 +11714,7 @@ export {
7881
11714
  toStoredSession,
7882
11715
  updateMessageAt,
7883
11716
  useAgentChatSession,
11717
+ useAgentSession,
7884
11718
  useEventProcessor,
7885
11719
  useTimelineAgentChatSession
7886
11720
  };