@agent-native/toolkit 0.5.1 → 0.7.0

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 (349) hide show
  1. package/README.md +17 -1
  2. package/dist/chat-history/ChatHistoryList.d.ts +103 -0
  3. package/dist/chat-history/ChatHistoryList.d.ts.map +1 -0
  4. package/dist/chat-history/ChatHistoryList.js +109 -0
  5. package/dist/chat-history/ChatHistoryList.js.map +1 -0
  6. package/dist/chat-history/ChatHistoryList.spec.d.ts +2 -0
  7. package/dist/chat-history/ChatHistoryList.spec.d.ts.map +1 -0
  8. package/dist/chat-history/ChatHistoryList.spec.js +283 -0
  9. package/dist/chat-history/ChatHistoryList.spec.js.map +1 -0
  10. package/dist/chat-history/index.d.ts +2 -0
  11. package/dist/chat-history/index.d.ts.map +1 -0
  12. package/dist/chat-history/index.js +2 -0
  13. package/dist/chat-history/index.js.map +1 -0
  14. package/dist/chat-history.css +314 -0
  15. package/dist/composer/AgentComposerFrame.d.ts +19 -0
  16. package/dist/composer/AgentComposerFrame.d.ts.map +1 -0
  17. package/dist/composer/AgentComposerFrame.js +14 -0
  18. package/dist/composer/AgentComposerFrame.js.map +1 -0
  19. package/dist/composer/ComposerPlusMenu.d.ts +17 -0
  20. package/dist/composer/ComposerPlusMenu.d.ts.map +1 -0
  21. package/dist/composer/ComposerPlusMenu.js +501 -0
  22. package/dist/composer/ComposerPlusMenu.js.map +1 -0
  23. package/dist/composer/MentionPopover.d.ts +29 -0
  24. package/dist/composer/MentionPopover.d.ts.map +1 -0
  25. package/dist/composer/MentionPopover.js +180 -0
  26. package/dist/composer/MentionPopover.js.map +1 -0
  27. package/dist/composer/PastedTextChip.d.ts +9 -0
  28. package/dist/composer/PastedTextChip.d.ts.map +1 -0
  29. package/dist/composer/PastedTextChip.js +47 -0
  30. package/dist/composer/PastedTextChip.js.map +1 -0
  31. package/dist/composer/PromptComposer.d.ts +114 -0
  32. package/dist/composer/PromptComposer.d.ts.map +1 -0
  33. package/dist/composer/PromptComposer.js +302 -0
  34. package/dist/composer/PromptComposer.js.map +1 -0
  35. package/dist/composer/PromptComposer.spec.d.ts +2 -0
  36. package/dist/composer/PromptComposer.spec.d.ts.map +1 -0
  37. package/dist/composer/PromptComposer.spec.js +64 -0
  38. package/dist/composer/PromptComposer.spec.js.map +1 -0
  39. package/dist/composer/RealtimeVoiceMode.d.ts +104 -0
  40. package/dist/composer/RealtimeVoiceMode.d.ts.map +1 -0
  41. package/dist/composer/RealtimeVoiceMode.js +245 -0
  42. package/dist/composer/RealtimeVoiceMode.js.map +1 -0
  43. package/dist/composer/RealtimeVoiceMode.spec.d.ts +2 -0
  44. package/dist/composer/RealtimeVoiceMode.spec.d.ts.map +1 -0
  45. package/dist/composer/RealtimeVoiceMode.spec.js +439 -0
  46. package/dist/composer/RealtimeVoiceMode.spec.js.map +1 -0
  47. package/dist/composer/TiptapComposer.d.ts +221 -0
  48. package/dist/composer/TiptapComposer.d.ts.map +1 -0
  49. package/dist/composer/TiptapComposer.js +1838 -0
  50. package/dist/composer/TiptapComposer.js.map +1 -0
  51. package/dist/composer/TiptapComposer.spec.d.ts +2 -0
  52. package/dist/composer/TiptapComposer.spec.d.ts.map +1 -0
  53. package/dist/composer/TiptapComposer.spec.js +277 -0
  54. package/dist/composer/TiptapComposer.spec.js.map +1 -0
  55. package/dist/composer/VoiceButton.d.ts +25 -0
  56. package/dist/composer/VoiceButton.d.ts.map +1 -0
  57. package/dist/composer/VoiceButton.js +100 -0
  58. package/dist/composer/VoiceButton.js.map +1 -0
  59. package/dist/composer/VoiceButton.spec.d.ts +2 -0
  60. package/dist/composer/VoiceButton.spec.d.ts.map +1 -0
  61. package/dist/composer/VoiceButton.spec.js +19 -0
  62. package/dist/composer/VoiceButton.spec.js.map +1 -0
  63. package/dist/composer/asset-picker-url.d.ts +16 -0
  64. package/dist/composer/asset-picker-url.d.ts.map +1 -0
  65. package/dist/composer/asset-picker-url.js +64 -0
  66. package/dist/composer/asset-picker-url.js.map +1 -0
  67. package/dist/composer/asset-picker-url.spec.d.ts +2 -0
  68. package/dist/composer/asset-picker-url.spec.d.ts.map +1 -0
  69. package/dist/composer/asset-picker-url.spec.js +23 -0
  70. package/dist/composer/asset-picker-url.spec.js.map +1 -0
  71. package/dist/composer/attachment-accept.d.ts +9 -0
  72. package/dist/composer/attachment-accept.d.ts.map +1 -0
  73. package/dist/composer/attachment-accept.js +65 -0
  74. package/dist/composer/attachment-accept.js.map +1 -0
  75. package/dist/composer/attachment-accept.spec.d.ts +2 -0
  76. package/dist/composer/attachment-accept.spec.d.ts.map +1 -0
  77. package/dist/composer/attachment-accept.spec.js +15 -0
  78. package/dist/composer/attachment-accept.spec.js.map +1 -0
  79. package/dist/composer/draft-key.d.ts +2 -0
  80. package/dist/composer/draft-key.d.ts.map +1 -0
  81. package/dist/composer/draft-key.js +8 -0
  82. package/dist/composer/draft-key.js.map +1 -0
  83. package/dist/composer/draft-key.spec.d.ts +2 -0
  84. package/dist/composer/draft-key.spec.d.ts.map +1 -0
  85. package/dist/composer/draft-key.spec.js +13 -0
  86. package/dist/composer/draft-key.spec.js.map +1 -0
  87. package/dist/composer/extensions/FileReference.d.ts +3 -0
  88. package/dist/composer/extensions/FileReference.d.ts.map +1 -0
  89. package/dist/composer/extensions/FileReference.js +36 -0
  90. package/dist/composer/extensions/FileReference.js.map +1 -0
  91. package/dist/composer/extensions/MentionReference.d.ts +3 -0
  92. package/dist/composer/extensions/MentionReference.d.ts.map +1 -0
  93. package/dist/composer/extensions/MentionReference.js +66 -0
  94. package/dist/composer/extensions/MentionReference.js.map +1 -0
  95. package/dist/composer/extensions/SkillReference.d.ts +3 -0
  96. package/dist/composer/extensions/SkillReference.d.ts.map +1 -0
  97. package/dist/composer/extensions/SkillReference.js +40 -0
  98. package/dist/composer/extensions/SkillReference.js.map +1 -0
  99. package/dist/composer/index.d.ts +14 -0
  100. package/dist/composer/index.d.ts.map +1 -0
  101. package/dist/composer/index.js +13 -0
  102. package/dist/composer/index.js.map +1 -0
  103. package/dist/composer/pasted-text.d.ts +31 -0
  104. package/dist/composer/pasted-text.d.ts.map +1 -0
  105. package/dist/composer/pasted-text.js +130 -0
  106. package/dist/composer/pasted-text.js.map +1 -0
  107. package/dist/composer/pasted-text.spec.d.ts +2 -0
  108. package/dist/composer/pasted-text.spec.d.ts.map +1 -0
  109. package/dist/composer/pasted-text.spec.js +107 -0
  110. package/dist/composer/pasted-text.spec.js.map +1 -0
  111. package/dist/composer/prompt-attachments.d.ts +18 -0
  112. package/dist/composer/prompt-attachments.d.ts.map +1 -0
  113. package/dist/composer/prompt-attachments.js +65 -0
  114. package/dist/composer/prompt-attachments.js.map +1 -0
  115. package/dist/composer/prompt-attachments.spec.d.ts +2 -0
  116. package/dist/composer/prompt-attachments.spec.d.ts.map +1 -0
  117. package/dist/composer/prompt-attachments.spec.js +63 -0
  118. package/dist/composer/prompt-attachments.spec.js.map +1 -0
  119. package/dist/composer/realtime-voice-audio-level.d.ts +14 -0
  120. package/dist/composer/realtime-voice-audio-level.d.ts.map +1 -0
  121. package/dist/composer/realtime-voice-audio-level.js +47 -0
  122. package/dist/composer/realtime-voice-audio-level.js.map +1 -0
  123. package/dist/composer/realtime-voice-audio-level.spec.d.ts +2 -0
  124. package/dist/composer/realtime-voice-audio-level.spec.d.ts.map +1 -0
  125. package/dist/composer/realtime-voice-audio-level.spec.js +25 -0
  126. package/dist/composer/realtime-voice-audio-level.spec.js.map +1 -0
  127. package/dist/composer/realtime-voice-transcript.d.ts +26 -0
  128. package/dist/composer/realtime-voice-transcript.d.ts.map +1 -0
  129. package/dist/composer/realtime-voice-transcript.js +103 -0
  130. package/dist/composer/realtime-voice-transcript.js.map +1 -0
  131. package/dist/composer/realtime-voice-transcript.spec.d.ts +2 -0
  132. package/dist/composer/realtime-voice-transcript.spec.d.ts.map +1 -0
  133. package/dist/composer/realtime-voice-transcript.spec.js +76 -0
  134. package/dist/composer/realtime-voice-transcript.spec.js.map +1 -0
  135. package/dist/composer/runtime-adapters.d.ts +163 -0
  136. package/dist/composer/runtime-adapters.d.ts.map +1 -0
  137. package/dist/composer/runtime-adapters.js +130 -0
  138. package/dist/composer/runtime-adapters.js.map +1 -0
  139. package/dist/composer/types.d.ts +60 -0
  140. package/dist/composer/types.d.ts.map +1 -0
  141. package/dist/composer/types.js +2 -0
  142. package/dist/composer/types.js.map +1 -0
  143. package/dist/composer/use-file-search.d.ts +6 -0
  144. package/dist/composer/use-file-search.d.ts.map +1 -0
  145. package/dist/composer/use-file-search.js +53 -0
  146. package/dist/composer/use-file-search.js.map +1 -0
  147. package/dist/composer/use-mention-search.d.ts +6 -0
  148. package/dist/composer/use-mention-search.d.ts.map +1 -0
  149. package/dist/composer/use-mention-search.js +75 -0
  150. package/dist/composer/use-mention-search.js.map +1 -0
  151. package/dist/composer/use-skills.d.ts +7 -0
  152. package/dist/composer/use-skills.d.ts.map +1 -0
  153. package/dist/composer/use-skills.js +40 -0
  154. package/dist/composer/use-skills.js.map +1 -0
  155. package/dist/composer/useRealtimeVoiceMode.d.ts +179 -0
  156. package/dist/composer/useRealtimeVoiceMode.d.ts.map +1 -0
  157. package/dist/composer/useRealtimeVoiceMode.js +1657 -0
  158. package/dist/composer/useRealtimeVoiceMode.js.map +1 -0
  159. package/dist/composer/useRealtimeVoiceMode.spec.d.ts +2 -0
  160. package/dist/composer/useRealtimeVoiceMode.spec.d.ts.map +1 -0
  161. package/dist/composer/useRealtimeVoiceMode.spec.js +618 -0
  162. package/dist/composer/useRealtimeVoiceMode.spec.js.map +1 -0
  163. package/dist/composer/useVoiceDictation.d.ts +57 -0
  164. package/dist/composer/useVoiceDictation.d.ts.map +1 -0
  165. package/dist/composer/useVoiceDictation.js +1004 -0
  166. package/dist/composer/useVoiceDictation.js.map +1 -0
  167. package/dist/composer/useVoiceDictation.spec.d.ts +2 -0
  168. package/dist/composer/useVoiceDictation.spec.d.ts.map +1 -0
  169. package/dist/composer/useVoiceDictation.spec.js +32 -0
  170. package/dist/composer/useVoiceDictation.spec.js.map +1 -0
  171. package/dist/editor/RegistryBlockContext.d.ts +68 -0
  172. package/dist/editor/RegistryBlockContext.d.ts.map +1 -0
  173. package/dist/editor/RegistryBlockContext.js +10 -0
  174. package/dist/editor/RegistryBlockContext.js.map +1 -0
  175. package/dist/editor/RegistryBlockNode.d.ts +66 -0
  176. package/dist/editor/RegistryBlockNode.d.ts.map +1 -0
  177. package/dist/editor/RegistryBlockNode.js +406 -0
  178. package/dist/editor/RegistryBlockNode.js.map +1 -0
  179. package/dist/editor/RegistryBlockNode.spec.d.ts +2 -0
  180. package/dist/editor/RegistryBlockNode.spec.d.ts.map +1 -0
  181. package/dist/editor/RegistryBlockNode.spec.js +215 -0
  182. package/dist/editor/RegistryBlockNode.spec.js.map +1 -0
  183. package/dist/editor/index.d.ts +2 -0
  184. package/dist/editor/index.d.ts.map +1 -1
  185. package/dist/editor/index.js +2 -0
  186. package/dist/editor/index.js.map +1 -1
  187. package/dist/editor/registrySlashCommands.d.ts +68 -0
  188. package/dist/editor/registrySlashCommands.d.ts.map +1 -0
  189. package/dist/editor/registrySlashCommands.js +51 -0
  190. package/dist/editor/registrySlashCommands.js.map +1 -0
  191. package/package.json +32 -1
  192. package/src/app-shell/header-actions.tsx +84 -0
  193. package/src/app-shell/index.ts +1 -0
  194. package/src/chat-history/ChatHistoryList.spec.tsx +453 -0
  195. package/src/chat-history/ChatHistoryList.tsx +469 -0
  196. package/src/chat-history/index.ts +7 -0
  197. package/src/chat-history.css +314 -0
  198. package/src/collab-ui/AgentPresenceChip.tsx +69 -0
  199. package/src/collab-ui/LiveCursorOverlay.tsx +241 -0
  200. package/src/collab-ui/PresenceBar.tsx +346 -0
  201. package/src/collab-ui/RecentEditHighlights.tsx +225 -0
  202. package/src/collab-ui/RemoteSelectionRings.tsx +227 -0
  203. package/src/collab-ui/agent-identity.ts +16 -0
  204. package/src/collab-ui/index.ts +39 -0
  205. package/src/collab-ui/lead-client.ts +32 -0
  206. package/src/collab-ui/types.spec.ts +18 -0
  207. package/src/collab-ui/types.ts +96 -0
  208. package/src/composer/AgentComposerFrame.tsx +59 -0
  209. package/src/composer/ComposerPlusMenu.tsx +983 -0
  210. package/src/composer/MentionPopover.tsx +412 -0
  211. package/src/composer/PastedTextChip.tsx +150 -0
  212. package/src/composer/PromptComposer.spec.ts +73 -0
  213. package/src/composer/PromptComposer.tsx +718 -0
  214. package/src/composer/RealtimeVoiceMode.spec.tsx +771 -0
  215. package/src/composer/RealtimeVoiceMode.tsx +856 -0
  216. package/src/composer/TiptapComposer.spec.ts +390 -0
  217. package/src/composer/TiptapComposer.tsx +2936 -0
  218. package/src/composer/VoiceButton.spec.ts +33 -0
  219. package/src/composer/VoiceButton.tsx +255 -0
  220. package/src/composer/asset-picker-url.spec.ts +56 -0
  221. package/src/composer/asset-picker-url.ts +80 -0
  222. package/src/composer/attachment-accept.spec.ts +22 -0
  223. package/src/composer/attachment-accept.ts +71 -0
  224. package/src/composer/draft-key.spec.ts +19 -0
  225. package/src/composer/draft-key.ts +7 -0
  226. package/src/composer/extensions/FileReference.tsx +55 -0
  227. package/src/composer/extensions/MentionReference.tsx +93 -0
  228. package/src/composer/extensions/SkillReference.tsx +56 -0
  229. package/src/composer/index.ts +79 -0
  230. package/src/composer/pasted-text.spec.ts +162 -0
  231. package/src/composer/pasted-text.ts +160 -0
  232. package/src/composer/prompt-attachments.spec.ts +80 -0
  233. package/src/composer/prompt-attachments.ts +93 -0
  234. package/src/composer/realtime-voice-audio-level.spec.ts +32 -0
  235. package/src/composer/realtime-voice-audio-level.ts +64 -0
  236. package/src/composer/realtime-voice-transcript.spec.ts +95 -0
  237. package/src/composer/realtime-voice-transcript.ts +134 -0
  238. package/src/composer/runtime-adapters.tsx +343 -0
  239. package/src/composer/types.ts +66 -0
  240. package/src/composer/use-file-search.ts +64 -0
  241. package/src/composer/use-mention-search.ts +90 -0
  242. package/src/composer/use-skills.ts +45 -0
  243. package/src/composer/useRealtimeVoiceMode.spec.ts +818 -0
  244. package/src/composer/useRealtimeVoiceMode.tsx +2117 -0
  245. package/src/composer/useVoiceDictation.spec.ts +45 -0
  246. package/src/composer/useVoiceDictation.ts +1191 -0
  247. package/src/context-ui/ContextMeter.tsx +101 -0
  248. package/src/context-ui/ContextSegmentRow.tsx +184 -0
  249. package/src/context-ui/ContextTreemap.tsx +125 -0
  250. package/src/context-ui/ContextXRayPanel.tsx +377 -0
  251. package/src/context-ui/format.ts +42 -0
  252. package/src/context-ui/index.ts +15 -0
  253. package/src/context-ui/types.ts +43 -0
  254. package/src/design-tweaks/index.ts +1 -0
  255. package/src/design-tweaks/visual-style-controls.tsx +1084 -0
  256. package/src/editor/BubbleToolbar.tsx +253 -0
  257. package/src/editor/CodeBlockNode.tsx +254 -0
  258. package/src/editor/DragHandle.spec.ts +588 -0
  259. package/src/editor/DragHandle.ts +1437 -0
  260. package/src/editor/ImageExtension.roundtrip.spec.ts +117 -0
  261. package/src/editor/ImageExtension.ts +306 -0
  262. package/src/editor/RegistryBlockContext.tsx +107 -0
  263. package/src/editor/RegistryBlockNode.spec.ts +279 -0
  264. package/src/editor/RegistryBlockNode.tsx +652 -0
  265. package/src/editor/RichMarkdownEditor.collab.spec.ts +79 -0
  266. package/src/editor/RichMarkdownEditor.roundtrip.spec.ts +226 -0
  267. package/src/editor/RichMarkdownEditor.tsx +81 -0
  268. package/src/editor/RunId.ts +61 -0
  269. package/src/editor/SharedRichEditor.tsx +321 -0
  270. package/src/editor/SlashCommandMenu.tsx +310 -0
  271. package/src/editor/disableHistory.spec.ts +85 -0
  272. package/src/editor/extensions.ts +402 -0
  273. package/src/editor/gfmDoc.spec.ts +230 -0
  274. package/src/editor/gfmDoc.ts +92 -0
  275. package/src/editor/index.ts +93 -0
  276. package/src/editor/registrySlashCommands.ts +131 -0
  277. package/src/editor/structuralReorderUndo.spec.ts +144 -0
  278. package/src/editor/surgical-apply.spec.ts +279 -0
  279. package/src/editor/surgical-apply.ts +192 -0
  280. package/src/editor/useCollabReconcile.concurrent.spec.ts +422 -0
  281. package/src/editor/useCollabReconcile.idempotent.spec.ts +324 -0
  282. package/src/editor/useCollabReconcile.ts +589 -0
  283. package/src/editor.css +510 -0
  284. package/src/hooks/index.ts +2 -0
  285. package/src/hooks/use-mobile.tsx +21 -0
  286. package/src/hooks/use-toast.ts +188 -0
  287. package/src/index.ts +8 -0
  288. package/src/onboarding/index.ts +1 -0
  289. package/src/provider.tsx +47 -0
  290. package/src/sharing/VisibilityBadge.spec.ts +96 -0
  291. package/src/sharing/VisibilityBadge.tsx +37 -0
  292. package/src/sharing/index.ts +4 -0
  293. package/src/styles.css +21 -0
  294. package/src/ui/accordion.tsx +56 -0
  295. package/src/ui/alert-dialog.tsx +141 -0
  296. package/src/ui/alert.tsx +59 -0
  297. package/src/ui/aspect-ratio.tsx +5 -0
  298. package/src/ui/avatar.tsx +48 -0
  299. package/src/ui/badge.tsx +37 -0
  300. package/src/ui/breadcrumb.tsx +115 -0
  301. package/src/ui/button.tsx +78 -0
  302. package/src/ui/calendar.tsx +214 -0
  303. package/src/ui/card.tsx +86 -0
  304. package/src/ui/carousel.tsx +260 -0
  305. package/src/ui/chart.tsx +375 -0
  306. package/src/ui/checkbox.tsx +28 -0
  307. package/src/ui/collapsible.tsx +9 -0
  308. package/src/ui/command.spec.tsx +51 -0
  309. package/src/ui/command.tsx +174 -0
  310. package/src/ui/context-menu.tsx +202 -0
  311. package/src/ui/date-picker.tsx +64 -0
  312. package/src/ui/dialog.spec.tsx +43 -0
  313. package/src/ui/dialog.tsx +146 -0
  314. package/src/ui/drawer.tsx +126 -0
  315. package/src/ui/dropdown-menu.tsx +218 -0
  316. package/src/ui/form.tsx +177 -0
  317. package/src/ui/hover-card.tsx +27 -0
  318. package/src/ui/index.ts +52 -0
  319. package/src/ui/input-otp.tsx +69 -0
  320. package/src/ui/input.tsx +22 -0
  321. package/src/ui/label.tsx +24 -0
  322. package/src/ui/logo.tsx +36 -0
  323. package/src/ui/menubar.tsx +235 -0
  324. package/src/ui/navigation-menu.tsx +128 -0
  325. package/src/ui/pagination.tsx +121 -0
  326. package/src/ui/popover.tsx +44 -0
  327. package/src/ui/progress.tsx +26 -0
  328. package/src/ui/radio-group.tsx +42 -0
  329. package/src/ui/resizable.tsx +43 -0
  330. package/src/ui/scroll-area.tsx +46 -0
  331. package/src/ui/select.tsx +158 -0
  332. package/src/ui/separator.tsx +29 -0
  333. package/src/ui/sheet.tsx +160 -0
  334. package/src/ui/sidebar.tsx +777 -0
  335. package/src/ui/skeleton.tsx +18 -0
  336. package/src/ui/slider.tsx +26 -0
  337. package/src/ui/sonner.tsx +58 -0
  338. package/src/ui/spinner.tsx +17 -0
  339. package/src/ui/switch.tsx +27 -0
  340. package/src/ui/table.tsx +117 -0
  341. package/src/ui/tabs.tsx +53 -0
  342. package/src/ui/textarea.tsx +23 -0
  343. package/src/ui/toast.tsx +127 -0
  344. package/src/ui/toaster.tsx +33 -0
  345. package/src/ui/toggle-group.tsx +59 -0
  346. package/src/ui/toggle.tsx +43 -0
  347. package/src/ui/tooltip.tsx +53 -0
  348. package/src/ui/use-toast.ts +3 -0
  349. package/src/utils.ts +8 -0
@@ -0,0 +1,101 @@
1
+ import type { ReactNode } from "react";
2
+
3
+ import { Popover, PopoverContent, PopoverTrigger } from "../ui/popover.js";
4
+ import {
5
+ Tooltip,
6
+ TooltipContent,
7
+ TooltipProvider,
8
+ TooltipTrigger,
9
+ } from "../ui/tooltip.js";
10
+ import { cn } from "../utils.js";
11
+ import { formatContextTokens } from "./format.js";
12
+ import type { ContextManifestViewData } from "./types.js";
13
+
14
+ function ContextDonut({ pct, advisory }: { pct: number; advisory: boolean }) {
15
+ const radius = 7.5;
16
+ const circumference = 2 * Math.PI * radius;
17
+ const displayPct = Math.max(3, Math.min(100, pct));
18
+ const dashOffset = circumference - (displayPct / 100) * circumference;
19
+ return (
20
+ <span className="relative flex size-5 items-center justify-center">
21
+ <svg aria-hidden="true" viewBox="0 0 20 20" className="-rotate-90 size-5">
22
+ <circle
23
+ cx="10"
24
+ cy="10"
25
+ r={radius}
26
+ className="stroke-muted"
27
+ fill="none"
28
+ strokeWidth="3"
29
+ />
30
+ <circle
31
+ cx="10"
32
+ cy="10"
33
+ r={radius}
34
+ className={cn(advisory ? "stroke-amber-500" : "stroke-[#00B5FF]")}
35
+ fill="none"
36
+ strokeLinecap="round"
37
+ strokeWidth="3"
38
+ strokeDasharray={circumference}
39
+ strokeDashoffset={dashOffset}
40
+ />
41
+ </svg>
42
+ <span className="absolute size-2 rounded-full bg-background" />
43
+ </span>
44
+ );
45
+ }
46
+
47
+ export function ContextMeterView({
48
+ manifest,
49
+ contextWindow,
50
+ open,
51
+ onOpenChange,
52
+ children,
53
+ }: {
54
+ manifest: ContextManifestViewData;
55
+ contextWindow: number;
56
+ open: boolean;
57
+ onOpenChange: (open: boolean) => void;
58
+ children: ReactNode;
59
+ }) {
60
+ const pct = Math.min(
61
+ 100,
62
+ Math.round((manifest.totalTokens / contextWindow) * 100),
63
+ );
64
+ const { conversationTokens, systemTokens } = manifest;
65
+ return (
66
+ <TooltipProvider delayDuration={200}>
67
+ <Popover open={open} onOpenChange={onOpenChange}>
68
+ <Tooltip>
69
+ <TooltipTrigger asChild>
70
+ <PopoverTrigger asChild>
71
+ <button
72
+ type="button"
73
+ aria-label={`Context ${pct}%, ${formatContextTokens(manifest.totalTokens)}${systemTokens > 0 ? ` total: ${formatContextTokens(systemTokens)} system + ${formatContextTokens(conversationTokens)} conversation` : ""}. Open Context X-Ray.`}
74
+ className={cn(
75
+ "flex size-7 shrink-0 cursor-pointer items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-accent/50 hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
76
+ open && "bg-accent/60 text-foreground",
77
+ )}
78
+ >
79
+ <ContextDonut pct={pct} advisory={!manifest.enforceable} />
80
+ </button>
81
+ </PopoverTrigger>
82
+ </TooltipTrigger>
83
+ <TooltipContent>
84
+ Context {pct}% · {formatContextTokens(manifest.totalTokens)}
85
+ {systemTokens > 0
86
+ ? ` (${formatContextTokens(systemTokens)} system + ${formatContextTokens(conversationTokens)} conversation)`
87
+ : ""}
88
+ </TooltipContent>
89
+ </Tooltip>
90
+ <PopoverContent
91
+ align="end"
92
+ side="top"
93
+ sideOffset={8}
94
+ className="w-[min(92vw,380px)] overflow-hidden border-border/70 p-0"
95
+ >
96
+ {children}
97
+ </PopoverContent>
98
+ </Popover>
99
+ </TooltipProvider>
100
+ );
101
+ }
@@ -0,0 +1,184 @@
1
+ import { IconLock, IconPin, IconRotate2, IconX } from "@tabler/icons-react";
2
+ import type { ReactNode } from "react";
3
+
4
+ import { Popover, PopoverContent, PopoverTrigger } from "../ui/popover.js";
5
+ import { Tooltip, TooltipContent, TooltipTrigger } from "../ui/tooltip.js";
6
+ import { cn } from "../utils.js";
7
+ import { contextStatusLabel, formatContextTokens } from "./format.js";
8
+ import type { ContextSegmentViewData } from "./types.js";
9
+
10
+ export function SegmentProvenancePopoverView({
11
+ segment,
12
+ children,
13
+ }: {
14
+ segment: ContextSegmentViewData;
15
+ children: ReactNode;
16
+ }) {
17
+ return (
18
+ <Popover>
19
+ <PopoverTrigger asChild>{children}</PopoverTrigger>
20
+ <PopoverContent align="start" className="w-80 p-3">
21
+ <div className="space-y-2">
22
+ <div>
23
+ <div className="text-[11px] font-medium uppercase text-muted-foreground">
24
+ Segment
25
+ </div>
26
+ <div className="mt-0.5 break-words text-xs text-foreground">
27
+ {segment.label}
28
+ </div>
29
+ </div>
30
+ <div className="grid grid-cols-2 gap-2 text-[11px] text-muted-foreground">
31
+ <div>
32
+ <span className="block font-medium text-foreground">
33
+ {formatContextTokens(segment.tokenCount)}
34
+ </span>
35
+ tokens{segment.tokenMethod === "estimate" ? " estimated" : ""}
36
+ </div>
37
+ <div>
38
+ <span className="block font-medium text-foreground">
39
+ {contextStatusLabel(segment)}
40
+ </span>
41
+ current status
42
+ </div>
43
+ <div>
44
+ <span className="block font-medium text-foreground">
45
+ {segment.msgIndex ?? "-"}
46
+ </span>
47
+ message index
48
+ </div>
49
+ <div>
50
+ <span className="block font-medium text-foreground">
51
+ {segment.partIndex ?? "-"}
52
+ </span>
53
+ part index
54
+ </div>
55
+ </div>
56
+ {segment.protected ? (
57
+ <div className="rounded-md border border-border bg-muted/40 px-2 py-1.5 text-[11px] text-muted-foreground">
58
+ This segment is part of the active turn and cannot be evicted yet.
59
+ </div>
60
+ ) : null}
61
+ </div>
62
+ </PopoverContent>
63
+ </Popover>
64
+ );
65
+ }
66
+
67
+ export function ContextSegmentRowView({
68
+ segment,
69
+ advisory,
70
+ onPin,
71
+ onEvict,
72
+ onRestore,
73
+ }: {
74
+ segment: ContextSegmentViewData;
75
+ advisory: boolean;
76
+ onPin: () => void;
77
+ onEvict: () => void;
78
+ onRestore: () => void;
79
+ }) {
80
+ const disabled = segment.protected || segment.status === "evicted";
81
+ return (
82
+ <div
83
+ tabIndex={0}
84
+ onKeyDown={(event) => {
85
+ if (event.key === "p") onPin();
86
+ if (event.key === "e" && !disabled) onEvict();
87
+ if (event.key === "u" && segment.status !== "active") onRestore();
88
+ }}
89
+ className={cn(
90
+ "group flex min-h-11 items-center gap-2 rounded-sm px-2 py-1.5 outline-none transition-colors hover:bg-accent/35 focus-visible:bg-accent/35 focus-visible:ring-1 focus-visible:ring-ring",
91
+ segment.status === "evicted" && "opacity-60",
92
+ )}
93
+ >
94
+ <SegmentProvenancePopoverView segment={segment}>
95
+ <button
96
+ type="button"
97
+ className="min-w-0 flex-1 text-left"
98
+ aria-label={`Inspect ${segment.label}`}
99
+ >
100
+ <div
101
+ className={cn(
102
+ "truncate text-[13px] font-medium leading-5 text-foreground",
103
+ segment.status === "evicted" && "line-through",
104
+ )}
105
+ >
106
+ {segment.label}
107
+ </div>
108
+ <div className="flex items-center gap-1.5 text-[11px] text-muted-foreground">
109
+ <span>{formatContextTokens(segment.tokenCount)}</span>
110
+ {segment.tokenMethod === "estimate" ? <span>~</span> : null}
111
+ <span>·</span>
112
+ <span>{contextStatusLabel(segment)}</span>
113
+ {advisory ? <span>· advisory</span> : null}
114
+ </div>
115
+ </button>
116
+ </SegmentProvenancePopoverView>
117
+ <div className="flex shrink-0 items-center gap-1 opacity-100 sm:opacity-0 sm:group-hover:opacity-100 sm:group-focus-within:opacity-100">
118
+ {segment.protected ? (
119
+ <Tooltip>
120
+ <TooltipTrigger asChild>
121
+ <span className="flex size-6 items-center justify-center rounded-md text-muted-foreground">
122
+ <IconLock className="h-3.5 w-3.5" />
123
+ </span>
124
+ </TooltipTrigger>
125
+ <TooltipContent>Protected during active turn</TooltipContent>
126
+ </Tooltip>
127
+ ) : segment.status === "evicted" ||
128
+ segment.status === "summarized" ||
129
+ segment.status === "pinned" ? (
130
+ <Tooltip>
131
+ <TooltipTrigger asChild>
132
+ <button
133
+ type="button"
134
+ onClick={onRestore}
135
+ className="flex size-6 items-center justify-center rounded-md text-muted-foreground hover:bg-background hover:text-foreground"
136
+ aria-label={
137
+ segment.status === "pinned"
138
+ ? "Unpin segment"
139
+ : "Restore segment"
140
+ }
141
+ >
142
+ <IconRotate2 className="h-3.5 w-3.5" />
143
+ </button>
144
+ </TooltipTrigger>
145
+ <TooltipContent>
146
+ {segment.status === "pinned" ? "Unpin" : "Restore"}
147
+ </TooltipContent>
148
+ </Tooltip>
149
+ ) : (
150
+ <>
151
+ <Tooltip>
152
+ <TooltipTrigger asChild>
153
+ <button
154
+ type="button"
155
+ onClick={onPin}
156
+ className="flex size-6 items-center justify-center rounded-md text-muted-foreground hover:bg-background hover:text-foreground"
157
+ aria-label="Pin segment"
158
+ >
159
+ <IconPin className="h-3.5 w-3.5" />
160
+ </button>
161
+ </TooltipTrigger>
162
+ <TooltipContent>Pin</TooltipContent>
163
+ </Tooltip>
164
+ <Tooltip>
165
+ <TooltipTrigger asChild>
166
+ <button
167
+ type="button"
168
+ onClick={onEvict}
169
+ className="flex size-6 items-center justify-center rounded-md text-muted-foreground hover:bg-background hover:text-destructive"
170
+ aria-label="Evict segment"
171
+ >
172
+ <IconX className="h-3.5 w-3.5" />
173
+ </button>
174
+ </TooltipTrigger>
175
+ <TooltipContent>
176
+ {advisory ? "Record eviction intent" : "Evict"}
177
+ </TooltipContent>
178
+ </Tooltip>
179
+ </>
180
+ )}
181
+ </div>
182
+ </div>
183
+ );
184
+ }
@@ -0,0 +1,125 @@
1
+ import { useEffect, useRef, useState } from "react";
2
+ import { Treemap } from "recharts";
3
+
4
+ import { contextGroupFill, formatContextTokens } from "./format.js";
5
+ import type {
6
+ ContextSegmentViewData,
7
+ ContextSystemSectionViewData,
8
+ } from "./types.js";
9
+
10
+ interface TreemapDatum {
11
+ name: string;
12
+ size: number;
13
+ group: string;
14
+ segmentId: string;
15
+ }
16
+
17
+ function TreemapContent(props: any) {
18
+ const { x, y, width, height, name, group, size } = props;
19
+ if (width < 8 || height < 8) return null;
20
+ const showLabel = width > 90 && height > 42;
21
+ return (
22
+ <g>
23
+ <rect
24
+ x={x}
25
+ y={y}
26
+ width={width}
27
+ height={height}
28
+ rx={3}
29
+ ry={3}
30
+ fill={contextGroupFill(group)}
31
+ stroke="var(--background)"
32
+ strokeWidth={2}
33
+ />
34
+ {showLabel ? (
35
+ <foreignObject
36
+ x={x + 6}
37
+ y={y + 6}
38
+ width={width - 12}
39
+ height={height - 12}
40
+ >
41
+ <div className="flex h-full flex-col justify-between overflow-hidden text-[11px] leading-tight text-white">
42
+ <div className="truncate font-medium">{name}</div>
43
+ <div className="text-white/85">{formatContextTokens(size)}</div>
44
+ </div>
45
+ </foreignObject>
46
+ ) : null}
47
+ </g>
48
+ );
49
+ }
50
+
51
+ export function ContextTreemapView({
52
+ segments,
53
+ systemSections = [],
54
+ onSelect,
55
+ }: {
56
+ segments: ContextSegmentViewData[];
57
+ systemSections?: ContextSystemSectionViewData[];
58
+ onSelect?: (segmentId: string) => void;
59
+ }) {
60
+ const containerRef = useRef<HTMLDivElement>(null);
61
+ const [chartWidth, setChartWidth] = useState(0);
62
+ const data: TreemapDatum[] = segments
63
+ .filter((segment) => segment.status !== "evicted" && segment.tokenCount > 0)
64
+ .map((segment) => ({
65
+ name: segment.label,
66
+ size: segment.tokenCount,
67
+ group: segment.group,
68
+ segmentId: segment.segmentId,
69
+ }));
70
+ data.push(
71
+ ...systemSections
72
+ .filter((section) => section.tokenCount > 0)
73
+ .map((section) => ({
74
+ name: section.label,
75
+ size: section.tokenCount,
76
+ group: `System · ${section.governance}`,
77
+ segmentId: section.segmentId,
78
+ })),
79
+ );
80
+
81
+ useEffect(() => {
82
+ const element = containerRef.current;
83
+ if (!element) return;
84
+ const updateWidth = () =>
85
+ setChartWidth(Math.max(0, Math.floor(element.clientWidth - 8)));
86
+ updateWidth();
87
+ const observer =
88
+ typeof ResizeObserver !== "undefined"
89
+ ? new ResizeObserver(updateWidth)
90
+ : null;
91
+ observer?.observe(element);
92
+ window.addEventListener("resize", updateWidth);
93
+ return () => {
94
+ observer?.disconnect();
95
+ window.removeEventListener("resize", updateWidth);
96
+ };
97
+ }, []);
98
+
99
+ if (data.length === 0) {
100
+ return (
101
+ <div className="flex h-52 items-center justify-center rounded-md bg-muted/30 text-xs text-muted-foreground">
102
+ No active segments
103
+ </div>
104
+ );
105
+ }
106
+ return (
107
+ <div ref={containerRef} className="h-56 min-w-0 rounded-md bg-muted/25 p-1">
108
+ {chartWidth > 0 ? (
109
+ <Treemap
110
+ width={chartWidth}
111
+ height={216}
112
+ data={data as any}
113
+ dataKey="size"
114
+ nameKey="name"
115
+ aspectRatio={4 / 3}
116
+ isAnimationActive={false}
117
+ content={<TreemapContent />}
118
+ onClick={(datum: any) => {
119
+ if (datum?.segmentId) onSelect?.(datum.segmentId);
120
+ }}
121
+ />
122
+ ) : null}
123
+ </div>
124
+ );
125
+ }