@agent-native/core 0.99.2 → 0.100.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 (381) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +21 -0
  3. package/corpus/core/docs/content/a2a-protocol.mdx +42 -0
  4. package/corpus/core/docs/content/agent-surfaces.mdx +43 -0
  5. package/corpus/core/docs/content/external-agents.mdx +11 -0
  6. package/corpus/core/docs/content/locales/ar-SA/a2a-protocol.mdx +42 -0
  7. package/corpus/core/docs/content/locales/ar-SA/agent-surfaces.mdx +30 -0
  8. package/corpus/core/docs/content/locales/ar-SA/external-agents.mdx +9 -0
  9. package/corpus/core/docs/content/locales/de-DE/a2a-protocol.mdx +42 -0
  10. package/corpus/core/docs/content/locales/de-DE/agent-surfaces.mdx +34 -0
  11. package/corpus/core/docs/content/locales/de-DE/external-agents.mdx +10 -0
  12. package/corpus/core/docs/content/locales/es-ES/a2a-protocol.mdx +42 -0
  13. package/corpus/core/docs/content/locales/es-ES/agent-surfaces.mdx +34 -0
  14. package/corpus/core/docs/content/locales/es-ES/external-agents.mdx +10 -0
  15. package/corpus/core/docs/content/locales/fr-FR/a2a-protocol.mdx +42 -0
  16. package/corpus/core/docs/content/locales/fr-FR/agent-surfaces.mdx +34 -0
  17. package/corpus/core/docs/content/locales/fr-FR/external-agents.mdx +11 -0
  18. package/corpus/core/docs/content/locales/hi-IN/a2a-protocol.mdx +42 -0
  19. package/corpus/core/docs/content/locales/hi-IN/agent-surfaces.mdx +31 -0
  20. package/corpus/core/docs/content/locales/hi-IN/external-agents.mdx +9 -0
  21. package/corpus/core/docs/content/locales/ja-JP/a2a-protocol.mdx +42 -0
  22. package/corpus/core/docs/content/locales/ja-JP/agent-surfaces.mdx +32 -0
  23. package/corpus/core/docs/content/locales/ja-JP/external-agents.mdx +10 -0
  24. package/corpus/core/docs/content/locales/ko-KR/a2a-protocol.mdx +42 -0
  25. package/corpus/core/docs/content/locales/ko-KR/agent-surfaces.mdx +32 -0
  26. package/corpus/core/docs/content/locales/ko-KR/external-agents.mdx +9 -0
  27. package/corpus/core/docs/content/locales/pt-BR/a2a-protocol.mdx +42 -0
  28. package/corpus/core/docs/content/locales/pt-BR/agent-surfaces.mdx +33 -0
  29. package/corpus/core/docs/content/locales/pt-BR/external-agents.mdx +10 -0
  30. package/corpus/core/docs/content/locales/zh-CN/a2a-protocol.mdx +42 -0
  31. package/corpus/core/docs/content/locales/zh-CN/agent-surfaces.mdx +29 -0
  32. package/corpus/core/docs/content/locales/zh-CN/external-agents.mdx +8 -0
  33. package/corpus/core/docs/content/locales/zh-TW/a2a-protocol.mdx +42 -0
  34. package/corpus/core/docs/content/locales/zh-TW/agent-surfaces.mdx +29 -0
  35. package/corpus/core/docs/content/locales/zh-TW/external-agents.mdx +8 -0
  36. package/corpus/core/package.json +1 -1
  37. package/corpus/core/src/agent/context-xray/actions/context-evict.ts +11 -0
  38. package/corpus/core/src/agent/context-xray/actions/context-pin.ts +11 -0
  39. package/corpus/core/src/agent/context-xray/actions/context-preview-get.ts +134 -0
  40. package/corpus/core/src/agent/context-xray/actions/context-restore.ts +11 -0
  41. package/corpus/core/src/agent/context-xray/actions/errors.ts +20 -0
  42. package/corpus/core/src/agent/context-xray/manifest.ts +106 -7
  43. package/corpus/core/src/agent/engine/context-directives-transform.ts +5 -1
  44. package/corpus/core/src/agent/production-agent.ts +100 -38
  45. package/corpus/core/src/agent/run-loop-with-resume.ts +7 -2
  46. package/corpus/core/src/client/AgentPanel.tsx +35 -8
  47. package/corpus/core/src/client/agent-page/AgentContextTab.tsx +501 -0
  48. package/corpus/core/src/client/agent-page/AgentJobsTab.tsx +370 -0
  49. package/corpus/core/src/client/agent-page/AgentTabsPage.tsx +1084 -0
  50. package/corpus/core/src/client/agent-page/types.ts +18 -0
  51. package/corpus/core/src/client/agent-page/use-jobs.ts +150 -0
  52. package/corpus/core/src/client/context-xray/ContextMeter.tsx +22 -5
  53. package/corpus/core/src/client/context-xray/ContextTreemap.tsx +16 -1
  54. package/corpus/core/src/client/context-xray/ContextXRayPanel.tsx +168 -3
  55. package/corpus/core/src/client/context-xray/format.ts +6 -0
  56. package/corpus/core/src/client/index.ts +6 -0
  57. package/corpus/core/src/client/resources/ResourcesPanel.tsx +51 -23
  58. package/corpus/core/src/client/settings/AutomationsSection.tsx +407 -387
  59. package/corpus/core/src/jobs/actions/list-recurring-jobs.ts +105 -0
  60. package/corpus/core/src/jobs/actions/manage-recurring-job.ts +85 -0
  61. package/corpus/core/src/jobs/tools.ts +1 -1
  62. package/corpus/core/src/localization/default-messages.ts +110 -0
  63. package/corpus/core/src/mcp/build-server.ts +1 -0
  64. package/corpus/core/src/mcp/connect-route.ts +62 -65
  65. package/corpus/core/src/server/action-discovery.ts +23 -0
  66. package/corpus/core/src/server/agent-chat/prompt-resources.ts +174 -2
  67. package/corpus/core/src/server/agent-chat-plugin.ts +175 -2
  68. package/corpus/core/src/server/auth.ts +1 -7
  69. package/corpus/core/src/server/google-oauth.ts +1 -7
  70. package/corpus/core/src/server/workspace-oauth.ts +31 -0
  71. package/corpus/core/src/shared/context-xray.ts +84 -1
  72. package/corpus/core/src/shared/mcp-connect-content.ts +130 -0
  73. package/corpus/core/src/templates/default/app/routes/_index.tsx +11 -0
  74. package/corpus/core/src/templates/default/app/routes/agent.tsx +33 -0
  75. package/corpus/core/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
  76. package/corpus/core/src/templates/workspace-core/.agents/skills/agent-page/SKILL.md +59 -0
  77. package/corpus/core/src/templates/workspace-core/.agents/skills/context-xray/SKILL.md +25 -0
  78. package/corpus/core/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +7 -0
  79. package/corpus/core/src/templates/workspace-core/.agents/skills/recurring-jobs/SKILL.md +9 -0
  80. package/corpus/core/src/triggers/actions/list-automations.ts +99 -0
  81. package/corpus/core/src/triggers/actions/manage-automation.ts +78 -0
  82. package/corpus/templates/analytics/actions/data-source-status.ts +33 -15
  83. package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +1 -1
  84. package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +149 -24
  85. package/corpus/templates/analytics/app/components/layout/CommandPalette.tsx +17 -0
  86. package/corpus/templates/analytics/app/components/layout/Header.tsx +1 -0
  87. package/corpus/templates/analytics/app/components/layout/Layout.tsx +1 -0
  88. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +8 -0
  89. package/corpus/templates/analytics/app/i18n/zh-TW.ts +1 -0
  90. package/corpus/templates/analytics/app/i18n-data.ts +1 -0
  91. package/corpus/templates/analytics/app/routes/agent.tsx +5 -0
  92. package/corpus/templates/analytics/changelog/2026-07-13-a-full-agent-page-now-brings-context-files-connections-jobs-.md +6 -0
  93. package/corpus/templates/analytics/changelog/2026-07-13-analytics-answers-can-use-built-in-first-party-event-data.md +6 -0
  94. package/corpus/templates/analytics/changelog/2026-07-13-chart-legends-can-filter-to-one-series-or-hide-a-series-on-h.md +6 -0
  95. package/corpus/templates/analytics/changelog/2026-07-13-gpt-5-6-luna-answers-now-recover-normally-instead-of-showing.md +6 -0
  96. package/corpus/templates/analytics/server/plugins/agent-chat.ts +11 -2
  97. package/corpus/templates/assets/app/components/layout/Header.tsx +1 -0
  98. package/corpus/templates/assets/app/components/layout/Layout.tsx +1 -0
  99. package/corpus/templates/assets/app/components/layout/Sidebar.tsx +2 -0
  100. package/corpus/templates/assets/app/routes/agent.tsx +5 -0
  101. package/corpus/templates/assets/changelog/2026-07-13-a-full-agent-page-now-brings-context-files-connections-jobs-.md +6 -0
  102. package/corpus/templates/brain/app/components/layout/Layout.tsx +1 -0
  103. package/corpus/templates/brain/app/components/layout/Sidebar.tsx +4 -1
  104. package/corpus/templates/brain/app/lib/brain.ts +11 -0
  105. package/corpus/templates/brain/app/root.tsx +15 -1
  106. package/corpus/templates/brain/app/routes/agent.tsx +11 -0
  107. package/corpus/templates/brain/changelog/2026-07-13-a-full-agent-page-now-brings-context-files-connections-jobs-.md +6 -0
  108. package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +1 -0
  109. package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +2 -0
  110. package/corpus/templates/calendar/app/root.tsx +17 -1
  111. package/corpus/templates/calendar/app/routes/_app.agent.tsx +25 -0
  112. package/corpus/templates/calendar/changelog/2026-07-13-a-full-agent-page-now-brings-context-files-connections-jobs-.md +6 -0
  113. package/corpus/templates/chat/app/components/layout/Header.tsx +1 -0
  114. package/corpus/templates/chat/app/components/layout/Layout.tsx +1 -0
  115. package/corpus/templates/chat/app/components/layout/Sidebar.tsx +7 -0
  116. package/corpus/templates/chat/app/hooks/use-navigation-state.ts +3 -0
  117. package/corpus/templates/chat/app/root.tsx +24 -2
  118. package/corpus/templates/chat/app/routes/agent.tsx +15 -0
  119. package/corpus/templates/chat/changelog/2026-07-13-a-full-agent-page-now-brings-context-files-connections-jobs-.md +6 -0
  120. package/corpus/templates/clips/app/components/library/library-layout.tsx +8 -0
  121. package/corpus/templates/clips/app/i18n/ar-SA.ts +2 -0
  122. package/corpus/templates/clips/app/i18n/de-DE.ts +2 -0
  123. package/corpus/templates/clips/app/i18n/en-US.ts +2 -0
  124. package/corpus/templates/clips/app/i18n/es-ES.ts +2 -0
  125. package/corpus/templates/clips/app/i18n/fr-FR.ts +2 -0
  126. package/corpus/templates/clips/app/i18n/hi-IN.ts +2 -0
  127. package/corpus/templates/clips/app/i18n/ja-JP.ts +2 -0
  128. package/corpus/templates/clips/app/i18n/ko-KR.ts +2 -0
  129. package/corpus/templates/clips/app/i18n/pt-BR.ts +2 -0
  130. package/corpus/templates/clips/app/i18n/zh-CN.ts +2 -0
  131. package/corpus/templates/clips/app/i18n/zh-TW.ts +2 -0
  132. package/corpus/templates/clips/app/root.tsx +7 -1
  133. package/corpus/templates/clips/app/routes/_app.agent.tsx +15 -0
  134. package/corpus/templates/clips/changelog/2026-07-13-new-agent-page-see-and-manage-your-agent-s-context-files-con.md +6 -0
  135. package/corpus/templates/content/app/components/layout/Layout.tsx +1 -0
  136. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +36 -0
  137. package/corpus/templates/content/app/i18n/zh-TW.ts +2 -0
  138. package/corpus/templates/content/app/i18n-data.ts +44 -6
  139. package/corpus/templates/content/app/root.tsx +8 -0
  140. package/corpus/templates/content/app/routes/_app.agent.tsx +15 -0
  141. package/corpus/templates/content/changelog/2026-07-13-new-agent-page-see-and-manage-your-agent-s-context-files-con.md +6 -0
  142. package/corpus/templates/design/app/components/layout/Layout.tsx +1 -0
  143. package/corpus/templates/design/app/components/layout/Sidebar.tsx +2 -0
  144. package/corpus/templates/design/app/i18n/zh-TW.ts +2 -0
  145. package/corpus/templates/design/app/i18n-data.ts +20 -0
  146. package/corpus/templates/design/app/root.tsx +7 -1
  147. package/corpus/templates/design/app/routes/agent.tsx +15 -0
  148. package/corpus/templates/design/changelog/2026-07-13-new-agent-page-see-and-manage-your-agent-s-context-files-con.md +6 -0
  149. package/corpus/templates/dispatch/app/dispatch-extensions.tsx +10 -1
  150. package/corpus/templates/dispatch/app/i18n/zh-TW.ts +2 -0
  151. package/corpus/templates/dispatch/app/i18n-data.ts +20 -0
  152. package/corpus/templates/dispatch/app/root.tsx +7 -2
  153. package/corpus/templates/dispatch/app/routes/agent.tsx +18 -0
  154. package/corpus/templates/dispatch/changelog/2026-07-13-new-agent-page-see-and-manage-your-agent-s-context-files-con.md +6 -0
  155. package/corpus/templates/forms/app/components/layout/Layout.tsx +1 -0
  156. package/corpus/templates/forms/app/components/layout/Sidebar.tsx +35 -0
  157. package/corpus/templates/forms/app/i18n/ar-SA.ts +2 -0
  158. package/corpus/templates/forms/app/i18n/de-DE.ts +2 -0
  159. package/corpus/templates/forms/app/i18n/en-US.ts +2 -0
  160. package/corpus/templates/forms/app/i18n/es-ES.ts +2 -0
  161. package/corpus/templates/forms/app/i18n/fr-FR.ts +2 -0
  162. package/corpus/templates/forms/app/i18n/hi-IN.ts +2 -0
  163. package/corpus/templates/forms/app/i18n/ja-JP.ts +2 -0
  164. package/corpus/templates/forms/app/i18n/ko-KR.ts +2 -0
  165. package/corpus/templates/forms/app/i18n/pt-BR.ts +2 -0
  166. package/corpus/templates/forms/app/i18n/zh-CN.ts +2 -0
  167. package/corpus/templates/forms/app/i18n/zh-TW.ts +2 -0
  168. package/corpus/templates/forms/app/root.tsx +6 -1
  169. package/corpus/templates/forms/app/routes/_app.agent.tsx +15 -0
  170. package/corpus/templates/forms/changelog/2026-07-13-new-agent-page-see-and-manage-your-agent-s-context-files-con.md +6 -0
  171. package/corpus/templates/macros/app/components/layout/AppLayout.tsx +14 -2
  172. package/corpus/templates/macros/app/components/layout/Header.tsx +1 -0
  173. package/corpus/templates/macros/app/root.tsx +17 -2
  174. package/corpus/templates/macros/app/routes/agent.tsx +15 -0
  175. package/corpus/templates/macros/changelog/2026-07-13-new-agent-page-see-and-manage-your-agent-s-context-files-con.md +6 -0
  176. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +42 -0
  177. package/corpus/templates/mail/app/components/layout/CommandPalette.tsx +6 -0
  178. package/corpus/templates/mail/app/routes/agent.tsx +15 -0
  179. package/corpus/templates/mail/changelog/2026-07-13-new-agent-page-see-and-manage-your-agent-s-context-files-con.md +6 -0
  180. package/corpus/templates/plan/app/components/layout/Header.tsx +1 -0
  181. package/corpus/templates/plan/app/components/layout/Layout.tsx +1 -0
  182. package/corpus/templates/plan/app/components/layout/Sidebar.tsx +2 -0
  183. package/corpus/templates/plan/app/root.tsx +8 -0
  184. package/corpus/templates/plan/app/routes/agent.tsx +15 -0
  185. package/corpus/templates/plan/changelog/2026-07-13-new-agent-page-see-and-manage-your-agent-s-context-files-con.md +6 -0
  186. package/corpus/templates/slides/app/components/layout/Header.tsx +1 -0
  187. package/corpus/templates/slides/app/components/layout/Layout.tsx +1 -0
  188. package/corpus/templates/slides/app/components/layout/Sidebar.tsx +2 -0
  189. package/corpus/templates/slides/app/root.tsx +10 -1
  190. package/corpus/templates/slides/app/routes/agent.tsx +15 -0
  191. package/corpus/templates/slides/changelog/2026-07-13-new-agent-page-see-and-manage-your-agent-s-context-files-con.md +6 -0
  192. package/dist/agent/context-xray/actions/context-evict.js +5 -2
  193. package/dist/agent/context-xray/actions/context-evict.js.map +1 -1
  194. package/dist/agent/context-xray/actions/context-pin.js +5 -2
  195. package/dist/agent/context-xray/actions/context-pin.js.map +1 -1
  196. package/dist/agent/context-xray/actions/context-preview-get.d.ts +17 -0
  197. package/dist/agent/context-xray/actions/context-preview-get.d.ts.map +1 -0
  198. package/dist/agent/context-xray/actions/context-preview-get.js +94 -0
  199. package/dist/agent/context-xray/actions/context-preview-get.js.map +1 -0
  200. package/dist/agent/context-xray/actions/context-restore.js +5 -2
  201. package/dist/agent/context-xray/actions/context-restore.js.map +1 -1
  202. package/dist/agent/context-xray/actions/errors.d.ts +3 -0
  203. package/dist/agent/context-xray/actions/errors.d.ts.map +1 -1
  204. package/dist/agent/context-xray/actions/errors.js +6 -0
  205. package/dist/agent/context-xray/actions/errors.js.map +1 -1
  206. package/dist/agent/context-xray/manifest.d.ts +18 -1
  207. package/dist/agent/context-xray/manifest.d.ts.map +1 -1
  208. package/dist/agent/context-xray/manifest.js +68 -6
  209. package/dist/agent/context-xray/manifest.js.map +1 -1
  210. package/dist/agent/engine/context-directives-transform.d.ts +2 -0
  211. package/dist/agent/engine/context-directives-transform.d.ts.map +1 -1
  212. package/dist/agent/engine/context-directives-transform.js +2 -1
  213. package/dist/agent/engine/context-directives-transform.js.map +1 -1
  214. package/dist/agent/production-agent.d.ts +15 -0
  215. package/dist/agent/production-agent.d.ts.map +1 -1
  216. package/dist/agent/production-agent.js +74 -36
  217. package/dist/agent/production-agent.js.map +1 -1
  218. package/dist/agent/run-loop-with-resume.d.ts.map +1 -1
  219. package/dist/agent/run-loop-with-resume.js +6 -3
  220. package/dist/agent/run-loop-with-resume.js.map +1 -1
  221. package/dist/client/AgentPanel.d.ts +5 -1
  222. package/dist/client/AgentPanel.d.ts.map +1 -1
  223. package/dist/client/AgentPanel.js +9 -11
  224. package/dist/client/AgentPanel.js.map +1 -1
  225. package/dist/client/agent-page/AgentContextTab.d.ts +5 -0
  226. package/dist/client/agent-page/AgentContextTab.d.ts.map +1 -0
  227. package/dist/client/agent-page/AgentContextTab.js +202 -0
  228. package/dist/client/agent-page/AgentContextTab.js.map +1 -0
  229. package/dist/client/agent-page/AgentJobsTab.d.ts +3 -0
  230. package/dist/client/agent-page/AgentJobsTab.d.ts.map +1 -0
  231. package/dist/client/agent-page/AgentJobsTab.js +98 -0
  232. package/dist/client/agent-page/AgentJobsTab.js.map +1 -0
  233. package/dist/client/agent-page/AgentTabsPage.d.ts +20 -0
  234. package/dist/client/agent-page/AgentTabsPage.d.ts.map +1 -0
  235. package/dist/client/agent-page/AgentTabsPage.js +420 -0
  236. package/dist/client/agent-page/AgentTabsPage.js.map +1 -0
  237. package/dist/client/agent-page/types.d.ts +17 -0
  238. package/dist/client/agent-page/types.d.ts.map +1 -0
  239. package/dist/client/agent-page/types.js +9 -0
  240. package/dist/client/agent-page/types.js.map +1 -0
  241. package/dist/client/agent-page/use-jobs.d.ts +61 -0
  242. package/dist/client/agent-page/use-jobs.d.ts.map +1 -0
  243. package/dist/client/agent-page/use-jobs.js +71 -0
  244. package/dist/client/agent-page/use-jobs.js.map +1 -0
  245. package/dist/client/context-xray/ContextMeter.d.ts +3 -1
  246. package/dist/client/context-xray/ContextMeter.d.ts.map +1 -1
  247. package/dist/client/context-xray/ContextMeter.js +14 -5
  248. package/dist/client/context-xray/ContextMeter.js.map +1 -1
  249. package/dist/client/context-xray/ContextTreemap.d.ts +3 -2
  250. package/dist/client/context-xray/ContextTreemap.d.ts.map +1 -1
  251. package/dist/client/context-xray/ContextTreemap.js +9 -1
  252. package/dist/client/context-xray/ContextTreemap.js.map +1 -1
  253. package/dist/client/context-xray/ContextXRayPanel.d.ts.map +1 -1
  254. package/dist/client/context-xray/ContextXRayPanel.js +95 -20
  255. package/dist/client/context-xray/ContextXRayPanel.js.map +1 -1
  256. package/dist/client/context-xray/format.d.ts.map +1 -1
  257. package/dist/client/context-xray/format.js +12 -0
  258. package/dist/client/context-xray/format.js.map +1 -1
  259. package/dist/client/index.d.ts +3 -0
  260. package/dist/client/index.d.ts.map +1 -1
  261. package/dist/client/index.js +1 -0
  262. package/dist/client/index.js.map +1 -1
  263. package/dist/client/resources/ResourcesPanel.d.ts +9 -1
  264. package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
  265. package/dist/client/resources/ResourcesPanel.js +26 -10
  266. package/dist/client/resources/ResourcesPanel.js.map +1 -1
  267. package/dist/client/settings/AutomationsSection.d.ts +9 -0
  268. package/dist/client/settings/AutomationsSection.d.ts.map +1 -1
  269. package/dist/client/settings/AutomationsSection.js +128 -147
  270. package/dist/client/settings/AutomationsSection.js.map +1 -1
  271. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  272. package/dist/jobs/actions/list-recurring-jobs.d.ts +21 -0
  273. package/dist/jobs/actions/list-recurring-jobs.d.ts.map +1 -0
  274. package/dist/jobs/actions/list-recurring-jobs.js +74 -0
  275. package/dist/jobs/actions/list-recurring-jobs.js.map +1 -0
  276. package/dist/jobs/actions/manage-recurring-job.d.ts +18 -0
  277. package/dist/jobs/actions/manage-recurring-job.d.ts.map +1 -0
  278. package/dist/jobs/actions/manage-recurring-job.js +68 -0
  279. package/dist/jobs/actions/manage-recurring-job.js.map +1 -0
  280. package/dist/jobs/tools.d.ts +13 -0
  281. package/dist/jobs/tools.d.ts.map +1 -1
  282. package/dist/jobs/tools.js +1 -1
  283. package/dist/jobs/tools.js.map +1 -1
  284. package/dist/localization/default-messages.d.ts +96 -0
  285. package/dist/localization/default-messages.d.ts.map +1 -1
  286. package/dist/localization/default-messages.js +96 -0
  287. package/dist/localization/default-messages.js.map +1 -1
  288. package/dist/mcp/build-server.d.ts.map +1 -1
  289. package/dist/mcp/build-server.js +1 -0
  290. package/dist/mcp/build-server.js.map +1 -1
  291. package/dist/mcp/connect-route.d.ts.map +1 -1
  292. package/dist/mcp/connect-route.js +44 -59
  293. package/dist/mcp/connect-route.js.map +1 -1
  294. package/dist/notifications/routes.d.ts +2 -2
  295. package/dist/resources/handlers.d.ts +1 -1
  296. package/dist/server/action-discovery.d.ts.map +1 -1
  297. package/dist/server/action-discovery.js +23 -0
  298. package/dist/server/action-discovery.js.map +1 -1
  299. package/dist/server/agent-chat/prompt-resources.d.ts +14 -0
  300. package/dist/server/agent-chat/prompt-resources.d.ts.map +1 -1
  301. package/dist/server/agent-chat/prompt-resources.js +139 -2
  302. package/dist/server/agent-chat/prompt-resources.js.map +1 -1
  303. package/dist/server/agent-chat-plugin.d.ts +1 -0
  304. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  305. package/dist/server/agent-chat-plugin.js +136 -3
  306. package/dist/server/agent-chat-plugin.js.map +1 -1
  307. package/dist/server/auth.d.ts.map +1 -1
  308. package/dist/server/auth.js +1 -4
  309. package/dist/server/auth.js.map +1 -1
  310. package/dist/server/google-oauth.d.ts.map +1 -1
  311. package/dist/server/google-oauth.js +1 -4
  312. package/dist/server/google-oauth.js.map +1 -1
  313. package/dist/server/transcribe-voice.d.ts +1 -1
  314. package/dist/server/workspace-oauth.d.ts +11 -0
  315. package/dist/server/workspace-oauth.d.ts.map +1 -0
  316. package/dist/server/workspace-oauth.js +25 -0
  317. package/dist/server/workspace-oauth.js.map +1 -0
  318. package/dist/shared/context-xray.d.ts +45 -1
  319. package/dist/shared/context-xray.d.ts.map +1 -1
  320. package/dist/shared/context-xray.js +12 -0
  321. package/dist/shared/context-xray.js.map +1 -1
  322. package/dist/shared/mcp-connect-content.d.ts +37 -0
  323. package/dist/shared/mcp-connect-content.d.ts.map +1 -0
  324. package/dist/shared/mcp-connect-content.js +92 -0
  325. package/dist/shared/mcp-connect-content.js.map +1 -0
  326. package/dist/templates/default/app/routes/_index.tsx +11 -0
  327. package/dist/templates/default/app/routes/agent.tsx +33 -0
  328. package/dist/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
  329. package/dist/templates/workspace-core/.agents/skills/agent-page/SKILL.md +59 -0
  330. package/dist/templates/workspace-core/.agents/skills/context-xray/SKILL.md +25 -0
  331. package/dist/templates/workspace-core/.agents/skills/external-agents/SKILL.md +7 -0
  332. package/dist/templates/workspace-core/.agents/skills/recurring-jobs/SKILL.md +9 -0
  333. package/dist/triggers/actions/list-automations.d.ts +24 -0
  334. package/dist/triggers/actions/list-automations.d.ts.map +1 -0
  335. package/dist/triggers/actions/list-automations.js +72 -0
  336. package/dist/triggers/actions/list-automations.js.map +1 -0
  337. package/dist/triggers/actions/manage-automation.d.ts +18 -0
  338. package/dist/triggers/actions/manage-automation.d.ts.map +1 -0
  339. package/dist/triggers/actions/manage-automation.js +60 -0
  340. package/dist/triggers/actions/manage-automation.js.map +1 -0
  341. package/docs/content/a2a-protocol.mdx +42 -0
  342. package/docs/content/agent-surfaces.mdx +43 -0
  343. package/docs/content/external-agents.mdx +11 -0
  344. package/docs/content/locales/ar-SA/a2a-protocol.mdx +42 -0
  345. package/docs/content/locales/ar-SA/agent-surfaces.mdx +30 -0
  346. package/docs/content/locales/ar-SA/external-agents.mdx +9 -0
  347. package/docs/content/locales/de-DE/a2a-protocol.mdx +42 -0
  348. package/docs/content/locales/de-DE/agent-surfaces.mdx +34 -0
  349. package/docs/content/locales/de-DE/external-agents.mdx +10 -0
  350. package/docs/content/locales/es-ES/a2a-protocol.mdx +42 -0
  351. package/docs/content/locales/es-ES/agent-surfaces.mdx +34 -0
  352. package/docs/content/locales/es-ES/external-agents.mdx +10 -0
  353. package/docs/content/locales/fr-FR/a2a-protocol.mdx +42 -0
  354. package/docs/content/locales/fr-FR/agent-surfaces.mdx +34 -0
  355. package/docs/content/locales/fr-FR/external-agents.mdx +11 -0
  356. package/docs/content/locales/hi-IN/a2a-protocol.mdx +42 -0
  357. package/docs/content/locales/hi-IN/agent-surfaces.mdx +31 -0
  358. package/docs/content/locales/hi-IN/external-agents.mdx +9 -0
  359. package/docs/content/locales/ja-JP/a2a-protocol.mdx +42 -0
  360. package/docs/content/locales/ja-JP/agent-surfaces.mdx +32 -0
  361. package/docs/content/locales/ja-JP/external-agents.mdx +10 -0
  362. package/docs/content/locales/ko-KR/a2a-protocol.mdx +42 -0
  363. package/docs/content/locales/ko-KR/agent-surfaces.mdx +32 -0
  364. package/docs/content/locales/ko-KR/external-agents.mdx +9 -0
  365. package/docs/content/locales/pt-BR/a2a-protocol.mdx +42 -0
  366. package/docs/content/locales/pt-BR/agent-surfaces.mdx +33 -0
  367. package/docs/content/locales/pt-BR/external-agents.mdx +10 -0
  368. package/docs/content/locales/zh-CN/a2a-protocol.mdx +42 -0
  369. package/docs/content/locales/zh-CN/agent-surfaces.mdx +29 -0
  370. package/docs/content/locales/zh-CN/external-agents.mdx +8 -0
  371. package/docs/content/locales/zh-TW/a2a-protocol.mdx +42 -0
  372. package/docs/content/locales/zh-TW/agent-surfaces.mdx +29 -0
  373. package/docs/content/locales/zh-TW/external-agents.mdx +8 -0
  374. package/package.json +1 -1
  375. package/src/templates/default/app/routes/_index.tsx +11 -0
  376. package/src/templates/default/app/routes/agent.tsx +33 -0
  377. package/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
  378. package/src/templates/workspace-core/.agents/skills/agent-page/SKILL.md +59 -0
  379. package/src/templates/workspace-core/.agents/skills/context-xray/SKILL.md +25 -0
  380. package/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +7 -0
  381. package/src/templates/workspace-core/.agents/skills/recurring-jobs/SKILL.md +9 -0
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Shared contracts for the full-page Agent surface (`AgentTabsPage`).
3
+ *
4
+ * Ownership note for concurrent implementation work: the page shell and the
5
+ * Files/MCP/Connect tabs may ADD exports here; the Context and Jobs tab
6
+ * implementations consume these types but must not edit this file.
7
+ */
8
+ export {};
9
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/client/agent-page/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG","sourcesContent":["/**\n * Shared contracts for the full-page Agent surface (`AgentTabsPage`).\n *\n * Ownership note for concurrent implementation work: the page shell and the\n * Files/MCP/Connect tabs may ADD exports here; the Context and Jobs tab\n * implementations consume these types but must not edit this file.\n */\n\n/** Which configuration scope the page-level toggle is showing. */\nexport type AgentPageScope = \"user\" | \"org\";\n\n/** Props every Agent page tab receives from the page shell. */\nexport interface AgentPageTabProps {\n /** Current scope selected by the page-level Personal/Organization toggle. */\n scope: AgentPageScope;\n /** Whether the current user can administer org-scoped agent config. */\n canManageOrg?: boolean;\n}\n"]}
@@ -0,0 +1,61 @@
1
+ export type JobsScope = "user" | "org";
2
+ export interface RecurringJob {
3
+ id: string;
4
+ name: string;
5
+ path: string;
6
+ scope: "personal" | "organization";
7
+ schedule: string;
8
+ scheduleDescription: string;
9
+ instructions: string;
10
+ enabled: boolean;
11
+ lastRun: string | null;
12
+ lastStatus: string | null;
13
+ lastError: string | null;
14
+ nextRun: string | null;
15
+ createdBy: string | null;
16
+ canUpdate: boolean;
17
+ }
18
+ export interface Automation {
19
+ id: string;
20
+ name: string;
21
+ path: string;
22
+ scope: "personal" | "organization";
23
+ triggerType: "event" | "schedule";
24
+ event: string | null;
25
+ schedule: string | null;
26
+ scheduleDescription: string | null;
27
+ condition: string | null;
28
+ body: string;
29
+ enabled: boolean;
30
+ lastRun: string | null;
31
+ lastStatus: string | null;
32
+ lastError: string | null;
33
+ nextRun: string | null;
34
+ createdBy: string | null;
35
+ canUpdate: boolean;
36
+ }
37
+ export type ManageJobInput = {
38
+ operation: "update" | "delete";
39
+ name: string;
40
+ scope: "personal" | "organization";
41
+ enabled?: boolean;
42
+ };
43
+ export type ManageAutomationInput = {
44
+ operation: "update" | "delete";
45
+ name: string;
46
+ scope: "personal" | "organization";
47
+ enabled?: boolean;
48
+ };
49
+ export declare function useRecurringJobs(scope: JobsScope): import("@tanstack/react-query").UseQueryResult<NoInfer<RecurringJob[]>, Error>;
50
+ export declare function useAutomations(scope: JobsScope): import("@tanstack/react-query").UseQueryResult<NoInfer<Automation[]>, Error>;
51
+ export declare function useManageRecurringJob(scope: JobsScope): import("@tanstack/react-query").UseMutationResult<{
52
+ deleted?: boolean;
53
+ name: string;
54
+ enabled?: boolean;
55
+ }, Error, ManageJobInput, unknown>;
56
+ export declare function useManageAutomation(scope: JobsScope): import("@tanstack/react-query").UseMutationResult<{
57
+ deleted?: boolean;
58
+ name: string;
59
+ enabled?: boolean;
60
+ }, Error, ManageAutomationInput, unknown>;
61
+ //# sourceMappingURL=use-jobs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-jobs.d.ts","sourceRoot":"","sources":["../../../src/client/agent-page/use-jobs.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,KAAK,CAAC;AAEvC,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,UAAU,GAAG,cAAc,CAAC;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,UAAU,GAAG,cAAc,CAAC;IACnC,WAAW,EAAE,OAAO,GAAG,UAAU,CAAC;IAClC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,SAAS,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,UAAU,GAAG,cAAc,CAAC;IACnC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,SAAS,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,UAAU,GAAG,cAAc,CAAC;IACnC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAUF,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,kFAMhD;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,gFAM9C;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,SAAS;cAMtC,OAAO;UAAQ,MAAM;cAAY,OAAO;mCA0BvD;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,SAAS;cAMpC,OAAO;UAAQ,MAAM;cAAY,OAAO;0CA4BvD"}
@@ -0,0 +1,71 @@
1
+ import { useQueryClient } from "@tanstack/react-query";
2
+ import { useActionMutation, useActionQuery } from "../use-action.js";
3
+ function recurringParams(scope) {
4
+ return { scope: scope === "org" ? "organization" : "personal" };
5
+ }
6
+ function automationParams(scope) {
7
+ return { scope: scope === "org" ? "organization" : "personal" };
8
+ }
9
+ export function useRecurringJobs(scope) {
10
+ return useActionQuery("list-recurring-jobs", recurringParams(scope), { staleTime: 5_000 });
11
+ }
12
+ export function useAutomations(scope) {
13
+ return useActionQuery("list-automations", automationParams(scope), { staleTime: 5_000 });
14
+ }
15
+ export function useManageRecurringJob(scope) {
16
+ const queryClient = useQueryClient();
17
+ const params = recurringParams(scope);
18
+ const queryKey = ["action", "list-recurring-jobs", params];
19
+ return useActionMutation("manage-recurring-job", {
20
+ onMutate: async (variables) => {
21
+ await queryClient.cancelQueries({ queryKey });
22
+ const previous = queryClient.getQueryData(queryKey);
23
+ queryClient.setQueryData(queryKey, (current) => {
24
+ if (!current)
25
+ return current;
26
+ if (variables.operation === "delete") {
27
+ return current.filter((job) => job.name !== variables.name);
28
+ }
29
+ return current.map((job) => job.name === variables.name && variables.enabled !== undefined
30
+ ? { ...job, enabled: variables.enabled }
31
+ : job);
32
+ });
33
+ return { previous };
34
+ },
35
+ onError: (_error, _variables, context) => {
36
+ const rollback = context;
37
+ if (rollback && "previous" in rollback) {
38
+ queryClient.setQueryData(queryKey, rollback.previous);
39
+ }
40
+ },
41
+ });
42
+ }
43
+ export function useManageAutomation(scope) {
44
+ const queryClient = useQueryClient();
45
+ const params = automationParams(scope);
46
+ const queryKey = ["action", "list-automations", params];
47
+ return useActionMutation("manage-automation", {
48
+ onMutate: async (variables) => {
49
+ await queryClient.cancelQueries({ queryKey });
50
+ const previous = queryClient.getQueryData(queryKey);
51
+ queryClient.setQueryData(queryKey, (current) => {
52
+ if (!current)
53
+ return current;
54
+ if (variables.operation === "delete") {
55
+ return current.filter((automation) => automation.name !== variables.name);
56
+ }
57
+ return current.map((automation) => automation.name === variables.name && variables.enabled !== undefined
58
+ ? { ...automation, enabled: variables.enabled }
59
+ : automation);
60
+ });
61
+ return { previous };
62
+ },
63
+ onError: (_error, _variables, context) => {
64
+ const rollback = context;
65
+ if (rollback && "previous" in rollback) {
66
+ queryClient.setQueryData(queryKey, rollback.previous);
67
+ }
68
+ },
69
+ });
70
+ }
71
+ //# sourceMappingURL=use-jobs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-jobs.js","sourceRoot":"","sources":["../../../src/client/agent-page/use-jobs.ts"],"names":[],"mappings":"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","sourcesContent":["import { useQueryClient } from \"@tanstack/react-query\";\n\nimport { useActionMutation, useActionQuery } from \"../use-action.js\";\n\nexport type JobsScope = \"user\" | \"org\";\n\nexport interface RecurringJob {\n id: string;\n name: string;\n path: string;\n scope: \"personal\" | \"organization\";\n schedule: string;\n scheduleDescription: string;\n instructions: string;\n enabled: boolean;\n lastRun: string | null;\n lastStatus: string | null;\n lastError: string | null;\n nextRun: string | null;\n createdBy: string | null;\n canUpdate: boolean;\n}\n\nexport interface Automation {\n id: string;\n name: string;\n path: string;\n scope: \"personal\" | \"organization\";\n triggerType: \"event\" | \"schedule\";\n event: string | null;\n schedule: string | null;\n scheduleDescription: string | null;\n condition: string | null;\n body: string;\n enabled: boolean;\n lastRun: string | null;\n lastStatus: string | null;\n lastError: string | null;\n nextRun: string | null;\n createdBy: string | null;\n canUpdate: boolean;\n}\n\nexport type ManageJobInput = {\n operation: \"update\" | \"delete\";\n name: string;\n scope: \"personal\" | \"organization\";\n enabled?: boolean;\n};\n\nexport type ManageAutomationInput = {\n operation: \"update\" | \"delete\";\n name: string;\n scope: \"personal\" | \"organization\";\n enabled?: boolean;\n};\n\nfunction recurringParams(scope: JobsScope) {\n return { scope: scope === \"org\" ? \"organization\" : \"personal\" } as const;\n}\n\nfunction automationParams(scope: JobsScope) {\n return { scope: scope === \"org\" ? \"organization\" : \"personal\" } as const;\n}\n\nexport function useRecurringJobs(scope: JobsScope) {\n return useActionQuery<RecurringJob[]>(\n \"list-recurring-jobs\",\n recurringParams(scope),\n { staleTime: 5_000 },\n );\n}\n\nexport function useAutomations(scope: JobsScope) {\n return useActionQuery<Automation[]>(\n \"list-automations\",\n automationParams(scope),\n { staleTime: 5_000 },\n );\n}\n\nexport function useManageRecurringJob(scope: JobsScope) {\n const queryClient = useQueryClient();\n const params = recurringParams(scope);\n const queryKey = [\"action\", \"list-recurring-jobs\", params] as const;\n\n return useActionMutation<\n { deleted?: boolean; name: string; enabled?: boolean },\n ManageJobInput\n >(\"manage-recurring-job\", {\n onMutate: async (variables) => {\n await queryClient.cancelQueries({ queryKey });\n const previous = queryClient.getQueryData<RecurringJob[]>(queryKey);\n queryClient.setQueryData<RecurringJob[]>(queryKey, (current) => {\n if (!current) return current;\n if (variables.operation === \"delete\") {\n return current.filter((job) => job.name !== variables.name);\n }\n return current.map((job) =>\n job.name === variables.name && variables.enabled !== undefined\n ? { ...job, enabled: variables.enabled }\n : job,\n );\n });\n return { previous };\n },\n onError: (_error, _variables, context) => {\n const rollback = context as { previous?: RecurringJob[] } | undefined;\n if (rollback && \"previous\" in rollback) {\n queryClient.setQueryData(queryKey, rollback.previous);\n }\n },\n });\n}\n\nexport function useManageAutomation(scope: JobsScope) {\n const queryClient = useQueryClient();\n const params = automationParams(scope);\n const queryKey = [\"action\", \"list-automations\", params] as const;\n\n return useActionMutation<\n { deleted?: boolean; name: string; enabled?: boolean },\n ManageAutomationInput\n >(\"manage-automation\", {\n onMutate: async (variables) => {\n await queryClient.cancelQueries({ queryKey });\n const previous = queryClient.getQueryData<Automation[]>(queryKey);\n queryClient.setQueryData<Automation[]>(queryKey, (current) => {\n if (!current) return current;\n if (variables.operation === \"delete\") {\n return current.filter(\n (automation) => automation.name !== variables.name,\n );\n }\n return current.map((automation) =>\n automation.name === variables.name && variables.enabled !== undefined\n ? { ...automation, enabled: variables.enabled }\n : automation,\n );\n });\n return { previous };\n },\n onError: (_error, _variables, context) => {\n const rollback = context as { previous?: Automation[] } | undefined;\n if (rollback && \"previous\" in rollback) {\n queryClient.setQueryData(queryKey, rollback.previous);\n }\n },\n });\n}\n"]}
@@ -1,5 +1,7 @@
1
- export declare function ContextMeter({ threadId, enabled, }: {
1
+ import type { ContextManifest } from "../../shared/context-xray.js";
2
+ export declare function ContextMeter({ threadId, manifest: providedManifest, enabled, }: {
2
3
  threadId?: string | null;
4
+ manifest?: ContextManifest | null;
3
5
  enabled?: boolean;
4
6
  }): import("react").JSX.Element | null;
5
7
  //# sourceMappingURL=ContextMeter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ContextMeter.d.ts","sourceRoot":"","sources":["../../../src/client/context-xray/ContextMeter.tsx"],"names":[],"mappings":"AA6DA,wBAAgB,YAAY,CAAC,EAC3B,QAAQ,EACR,OAAc,GACf,EAAE;IACD,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,sCAuHA"}
1
+ {"version":3,"file":"ContextMeter.d.ts","sourceRoot":"","sources":["../../../src/client/context-xray/ContextMeter.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,eAAe,EAEhB,MAAM,8BAA8B,CAAC;AA4DtC,wBAAgB,YAAY,CAAC,EAC3B,QAAQ,EACR,QAAQ,EAAE,gBAAgB,EAC1B,OAAc,GACf,EAAE;IACD,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IAClC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,sCAkIA"}
@@ -1,5 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { lazy, Suspense, useEffect, useRef, useState } from "react";
3
+ import { manifestConversationTokens, manifestSystemTokens, } from "../../shared/context-xray.js";
3
4
  import { Popover, PopoverContent, PopoverTrigger, } from "../components/ui/popover.js";
4
5
  import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "../components/ui/tooltip.js";
5
6
  import { useActionMutation, useActionQuery } from "../use-action.js";
@@ -15,11 +16,11 @@ function ContextDonut({ pct, advisory }) {
15
16
  const dashOffset = circumference - (displayPct / 100) * circumference;
16
17
  return (_jsxs("span", { className: "relative flex size-5 items-center justify-center", children: [_jsxs("svg", { "aria-hidden": "true", viewBox: "0 0 20 20", className: "-rotate-90 size-5", children: [_jsx("circle", { cx: "10", cy: "10", r: radius, className: "stroke-muted", fill: "none", strokeWidth: "3" }), _jsx("circle", { cx: "10", cy: "10", r: radius, className: cn(advisory ? "stroke-amber-500" : "stroke-[#00B5FF]"), fill: "none", strokeLinecap: "round", strokeWidth: "3", strokeDasharray: circumference, strokeDashoffset: dashOffset })] }), _jsx("span", { className: "absolute size-2 rounded-full bg-background" })] }));
17
18
  }
18
- export function ContextMeter({ threadId, enabled = true, }) {
19
+ export function ContextMeter({ threadId, manifest: providedManifest, enabled = true, }) {
19
20
  const [open, setOpen] = useState(false);
20
21
  const [optimistic, setOptimistic] = useState(new Map());
21
22
  const currentThreadId = useRef(threadId);
22
- const shouldQuery = Boolean(threadId && enabled);
23
+ const shouldQuery = Boolean(threadId && enabled && !providedManifest);
23
24
  const query = useActionQuery("context-manifest-get", shouldQuery && threadId ? { threadId } : undefined, {
24
25
  enabled: shouldQuery,
25
26
  staleTime: 1000,
@@ -41,12 +42,18 @@ export function ContextMeter({ threadId, enabled = true, }) {
41
42
  setOpen(true);
42
43
  }
43
44
  }, [enabled, threadId]);
44
- const manifest = query.data;
45
+ const manifest = providedManifest ?? query.data;
45
46
  const contextWindow = resolveContextWindow(manifest?.model);
46
47
  const pct = manifest
47
48
  ? Math.min(100, Math.round((manifest.totalTokens / contextWindow) * 100))
48
49
  : 0;
49
- if (!shouldQuery || !threadId || !manifest || manifest.rawTokens <= 0) {
50
+ const systemTokens = manifest ? manifestSystemTokens(manifest) : 0;
51
+ const conversationTokens = manifest
52
+ ? manifestConversationTokens(manifest)
53
+ : 0;
54
+ if ((!shouldQuery && !providedManifest) ||
55
+ !manifest ||
56
+ (manifest.rawTokens <= 0 && manifest.totalTokens <= 0)) {
50
57
  return null;
51
58
  }
52
59
  const mutateStatus = (segmentId, status, action) => {
@@ -67,6 +74,8 @@ export function ContextMeter({ threadId, enabled = true, }) {
67
74
  if (action === "restore")
68
75
  restore.mutate(params, options);
69
76
  };
70
- return (_jsx(TooltipProvider, { delayDuration: 200, children: _jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(PopoverTrigger, { asChild: true, children: _jsx("button", { type: "button", "aria-label": `Context ${pct}%, ${formatTokens(manifest.totalTokens)}. Open Context X-Ray.`, className: cn("flex size-7 shrink-0 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", open && "bg-accent/60 text-foreground"), children: _jsx(ContextDonut, { pct: pct, advisory: !manifest.enforceable }) }) }) }), _jsxs(TooltipContent, { children: ["Context ", pct, "% \u00B7 ", formatTokens(manifest.totalTokens)] })] }), _jsx(PopoverContent, { align: "end", side: "top", sideOffset: 8, className: "w-[min(92vw,380px)] overflow-hidden border-border/70 p-0", children: open ? (_jsx(Suspense, { fallback: _jsx("div", { className: "flex h-52 items-center justify-center text-xs text-muted-foreground", children: "Loading context view\u2026" }), children: _jsx(ContextXRayPanel, { manifest: manifest, optimistic: optimistic, onPin: (segmentId) => mutateStatus(segmentId, "pinned", "pin"), onEvict: (segmentId) => mutateStatus(segmentId, "evicted", "evict"), onRestore: (segmentId) => mutateStatus(segmentId, "active", "restore") }) })) : null })] }) }));
77
+ return (_jsx(TooltipProvider, { delayDuration: 200, children: _jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(PopoverTrigger, { asChild: true, children: _jsx("button", { type: "button", "aria-label": `Context ${pct}%, ${formatTokens(manifest.totalTokens)}${systemTokens > 0 ? ` total: ${formatTokens(systemTokens)} system + ${formatTokens(conversationTokens)} conversation` : ""}. Open Context X-Ray.`, className: cn("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", open && "bg-accent/60 text-foreground"), children: _jsx(ContextDonut, { pct: pct, advisory: !manifest.enforceable }) }) }) }), _jsxs(TooltipContent, { children: ["Context ", pct, "% \u00B7 ", formatTokens(manifest.totalTokens), systemTokens > 0
78
+ ? ` (${formatTokens(systemTokens)} system + ${formatTokens(conversationTokens)} conversation)`
79
+ : ""] })] }), _jsx(PopoverContent, { align: "end", side: "top", sideOffset: 8, className: "w-[min(92vw,380px)] overflow-hidden border-border/70 p-0", children: open ? (_jsx(Suspense, { fallback: _jsx("div", { className: "flex h-52 items-center justify-center text-xs text-muted-foreground", children: "Loading context view\u2026" }), children: _jsx(ContextXRayPanel, { manifest: manifest, optimistic: optimistic, onPin: (segmentId) => mutateStatus(segmentId, "pinned", "pin"), onEvict: (segmentId) => mutateStatus(segmentId, "evicted", "evict"), onRestore: (segmentId) => mutateStatus(segmentId, "active", "restore") }) })) : null })] }) }));
71
80
  }
72
81
  //# sourceMappingURL=ContextMeter.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ContextMeter.js","sourceRoot":"","sources":["../../../src/client/context-xray/ContextMeter.tsx"],"names":[],"mappings":"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","sourcesContent":["import { lazy, Suspense, useEffect, useRef, useState } from \"react\";\n\nimport type {\n ContextManifest,\n ContextSegmentStatus,\n} from \"../../shared/context-xray.js\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"../components/ui/popover.js\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from \"../components/ui/tooltip.js\";\nimport { useActionMutation, useActionQuery } from \"../use-action.js\";\nimport { cn } from \"../utils.js\";\nimport { formatTokens, resolveContextWindow } from \"./format.js\";\n\nconst ContextXRayPanel = lazy(() =>\n import(\"./ContextXRayPanel.js\").then((m) => ({\n default: m.ContextXRayPanel,\n })),\n);\n\nfunction ContextDonut({ pct, advisory }: { pct: number; advisory: boolean }) {\n const radius = 7.5;\n const circumference = 2 * Math.PI * radius;\n const displayPct = Math.max(3, Math.min(100, pct));\n const dashOffset = circumference - (displayPct / 100) * circumference;\n\n return (\n <span className=\"relative flex size-5 items-center justify-center\">\n <svg aria-hidden=\"true\" viewBox=\"0 0 20 20\" className=\"-rotate-90 size-5\">\n <circle\n cx=\"10\"\n cy=\"10\"\n r={radius}\n className=\"stroke-muted\"\n fill=\"none\"\n strokeWidth=\"3\"\n />\n <circle\n cx=\"10\"\n cy=\"10\"\n r={radius}\n className={cn(advisory ? \"stroke-amber-500\" : \"stroke-[#00B5FF]\")}\n fill=\"none\"\n strokeLinecap=\"round\"\n strokeWidth=\"3\"\n strokeDasharray={circumference}\n strokeDashoffset={dashOffset}\n />\n </svg>\n <span className=\"absolute size-2 rounded-full bg-background\" />\n </span>\n );\n}\n\nexport function ContextMeter({\n threadId,\n enabled = true,\n}: {\n threadId?: string | null;\n enabled?: boolean;\n}) {\n const [open, setOpen] = useState(false);\n const [optimistic, setOptimistic] = useState<\n Map<string, ContextSegmentStatus>\n >(new Map());\n const currentThreadId = useRef(threadId);\n const shouldQuery = Boolean(threadId && enabled);\n const query = useActionQuery(\n \"context-manifest-get\",\n shouldQuery && threadId ? { threadId } : undefined,\n {\n enabled: shouldQuery,\n staleTime: 1000,\n },\n ) as { data?: ContextManifest };\n const pin = useActionMutation(\"context-pin\");\n const evict = useActionMutation(\"context-evict\");\n const restore = useActionMutation(\"context-restore\");\n\n useEffect(() => {\n currentThreadId.current = threadId;\n setOptimistic(new Map());\n }, [threadId]);\n\n useEffect(() => {\n if (!threadId || !enabled || typeof window === \"undefined\") return;\n const params = new URLSearchParams(window.location.search);\n const wantsXray = params.get(\"contextXray\") === \"1\";\n const targetThread = params.get(\"threadId\");\n if (wantsXray && (!targetThread || targetThread === threadId)) {\n setOpen(true);\n }\n }, [enabled, threadId]);\n\n const manifest = query.data;\n const contextWindow = resolveContextWindow(manifest?.model);\n const pct = manifest\n ? Math.min(100, Math.round((manifest.totalTokens / contextWindow) * 100))\n : 0;\n\n if (!shouldQuery || !threadId || !manifest || manifest.rawTokens <= 0) {\n return null;\n }\n\n const mutateStatus = (\n segmentId: string,\n status: ContextSegmentStatus,\n action: \"pin\" | \"evict\" | \"restore\",\n ) => {\n const previous = new Map(optimistic);\n setOptimistic((prev) => new Map(prev).set(segmentId, status));\n const params = { threadId, segmentId };\n const options = {\n onError: () => {\n if (currentThreadId.current === threadId) {\n setOptimistic(previous);\n }\n },\n };\n if (action === \"pin\") pin.mutate(params, options);\n if (action === \"evict\") evict.mutate(params, options);\n if (action === \"restore\") restore.mutate(params, options);\n };\n\n return (\n <TooltipProvider delayDuration={200}>\n <Popover open={open} onOpenChange={setOpen}>\n <Tooltip>\n <TooltipTrigger asChild>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n aria-label={`Context ${pct}%, ${formatTokens(\n manifest.totalTokens,\n )}. Open Context X-Ray.`}\n className={cn(\n \"flex size-7 shrink-0 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\",\n open && \"bg-accent/60 text-foreground\",\n )}\n >\n <ContextDonut pct={pct} advisory={!manifest.enforceable} />\n </button>\n </PopoverTrigger>\n </TooltipTrigger>\n <TooltipContent>\n Context {pct}% · {formatTokens(manifest.totalTokens)}\n </TooltipContent>\n </Tooltip>\n <PopoverContent\n align=\"end\"\n side=\"top\"\n sideOffset={8}\n className=\"w-[min(92vw,380px)] overflow-hidden border-border/70 p-0\"\n >\n {open ? (\n <Suspense\n fallback={\n <div className=\"flex h-52 items-center justify-center text-xs text-muted-foreground\">\n Loading context view…\n </div>\n }\n >\n <ContextXRayPanel\n manifest={manifest}\n optimistic={optimistic}\n onPin={(segmentId) => mutateStatus(segmentId, \"pinned\", \"pin\")}\n onEvict={(segmentId) =>\n mutateStatus(segmentId, \"evicted\", \"evict\")\n }\n onRestore={(segmentId) =>\n mutateStatus(segmentId, \"active\", \"restore\")\n }\n />\n </Suspense>\n ) : null}\n </PopoverContent>\n </Popover>\n </TooltipProvider>\n );\n}\n"]}
1
+ {"version":3,"file":"ContextMeter.js","sourceRoot":"","sources":["../../../src/client/context-xray/ContextMeter.tsx"],"names":[],"mappings":"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","sourcesContent":["import { lazy, Suspense, useEffect, useRef, useState } from \"react\";\n\nimport type {\n ContextManifest,\n ContextSegmentStatus,\n} from \"../../shared/context-xray.js\";\nimport {\n manifestConversationTokens,\n manifestSystemTokens,\n} from \"../../shared/context-xray.js\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"../components/ui/popover.js\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from \"../components/ui/tooltip.js\";\nimport { useActionMutation, useActionQuery } from \"../use-action.js\";\nimport { cn } from \"../utils.js\";\nimport { formatTokens, resolveContextWindow } from \"./format.js\";\n\nconst ContextXRayPanel = lazy(() =>\n import(\"./ContextXRayPanel.js\").then((m) => ({\n default: m.ContextXRayPanel,\n })),\n);\n\nfunction ContextDonut({ pct, advisory }: { pct: number; advisory: boolean }) {\n const radius = 7.5;\n const circumference = 2 * Math.PI * radius;\n const displayPct = Math.max(3, Math.min(100, pct));\n const dashOffset = circumference - (displayPct / 100) * circumference;\n\n return (\n <span className=\"relative flex size-5 items-center justify-center\">\n <svg aria-hidden=\"true\" viewBox=\"0 0 20 20\" className=\"-rotate-90 size-5\">\n <circle\n cx=\"10\"\n cy=\"10\"\n r={radius}\n className=\"stroke-muted\"\n fill=\"none\"\n strokeWidth=\"3\"\n />\n <circle\n cx=\"10\"\n cy=\"10\"\n r={radius}\n className={cn(advisory ? \"stroke-amber-500\" : \"stroke-[#00B5FF]\")}\n fill=\"none\"\n strokeLinecap=\"round\"\n strokeWidth=\"3\"\n strokeDasharray={circumference}\n strokeDashoffset={dashOffset}\n />\n </svg>\n <span className=\"absolute size-2 rounded-full bg-background\" />\n </span>\n );\n}\n\nexport function ContextMeter({\n threadId,\n manifest: providedManifest,\n enabled = true,\n}: {\n threadId?: string | null;\n manifest?: ContextManifest | null;\n enabled?: boolean;\n}) {\n const [open, setOpen] = useState(false);\n const [optimistic, setOptimistic] = useState<\n Map<string, ContextSegmentStatus>\n >(new Map());\n const currentThreadId = useRef(threadId);\n const shouldQuery = Boolean(threadId && enabled && !providedManifest);\n const query = useActionQuery(\n \"context-manifest-get\",\n shouldQuery && threadId ? { threadId } : undefined,\n {\n enabled: shouldQuery,\n staleTime: 1000,\n },\n ) as { data?: ContextManifest };\n const pin = useActionMutation(\"context-pin\");\n const evict = useActionMutation(\"context-evict\");\n const restore = useActionMutation(\"context-restore\");\n\n useEffect(() => {\n currentThreadId.current = threadId;\n setOptimistic(new Map());\n }, [threadId]);\n\n useEffect(() => {\n if (!threadId || !enabled || typeof window === \"undefined\") return;\n const params = new URLSearchParams(window.location.search);\n const wantsXray = params.get(\"contextXray\") === \"1\";\n const targetThread = params.get(\"threadId\");\n if (wantsXray && (!targetThread || targetThread === threadId)) {\n setOpen(true);\n }\n }, [enabled, threadId]);\n\n const manifest = providedManifest ?? query.data;\n const contextWindow = resolveContextWindow(manifest?.model);\n const pct = manifest\n ? Math.min(100, Math.round((manifest.totalTokens / contextWindow) * 100))\n : 0;\n const systemTokens = manifest ? manifestSystemTokens(manifest) : 0;\n const conversationTokens = manifest\n ? manifestConversationTokens(manifest)\n : 0;\n\n if (\n (!shouldQuery && !providedManifest) ||\n !manifest ||\n (manifest.rawTokens <= 0 && manifest.totalTokens <= 0)\n ) {\n return null;\n }\n\n const mutateStatus = (\n segmentId: string,\n status: ContextSegmentStatus,\n action: \"pin\" | \"evict\" | \"restore\",\n ) => {\n const previous = new Map(optimistic);\n setOptimistic((prev) => new Map(prev).set(segmentId, status));\n const params = { threadId, segmentId };\n const options = {\n onError: () => {\n if (currentThreadId.current === threadId) {\n setOptimistic(previous);\n }\n },\n };\n if (action === \"pin\") pin.mutate(params, options);\n if (action === \"evict\") evict.mutate(params, options);\n if (action === \"restore\") restore.mutate(params, options);\n };\n\n return (\n <TooltipProvider delayDuration={200}>\n <Popover open={open} onOpenChange={setOpen}>\n <Tooltip>\n <TooltipTrigger asChild>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n aria-label={`Context ${pct}%, ${formatTokens(\n manifest.totalTokens,\n )}${systemTokens > 0 ? ` total: ${formatTokens(systemTokens)} system + ${formatTokens(conversationTokens)} conversation` : \"\"}. Open Context X-Ray.`}\n className={cn(\n \"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\",\n open && \"bg-accent/60 text-foreground\",\n )}\n >\n <ContextDonut pct={pct} advisory={!manifest.enforceable} />\n </button>\n </PopoverTrigger>\n </TooltipTrigger>\n <TooltipContent>\n Context {pct}% · {formatTokens(manifest.totalTokens)}\n {systemTokens > 0\n ? ` (${formatTokens(systemTokens)} system + ${formatTokens(conversationTokens)} conversation)`\n : \"\"}\n </TooltipContent>\n </Tooltip>\n <PopoverContent\n align=\"end\"\n side=\"top\"\n sideOffset={8}\n className=\"w-[min(92vw,380px)] overflow-hidden border-border/70 p-0\"\n >\n {open ? (\n <Suspense\n fallback={\n <div className=\"flex h-52 items-center justify-center text-xs text-muted-foreground\">\n Loading context view…\n </div>\n }\n >\n <ContextXRayPanel\n manifest={manifest}\n optimistic={optimistic}\n onPin={(segmentId) => mutateStatus(segmentId, \"pinned\", \"pin\")}\n onEvict={(segmentId) =>\n mutateStatus(segmentId, \"evicted\", \"evict\")\n }\n onRestore={(segmentId) =>\n mutateStatus(segmentId, \"active\", \"restore\")\n }\n />\n </Suspense>\n ) : null}\n </PopoverContent>\n </Popover>\n </TooltipProvider>\n );\n}\n"]}
@@ -1,6 +1,7 @@
1
- import type { ContextManifestSegment } from "../../shared/context-xray.js";
2
- export declare function ContextTreemap({ segments, onSelect, }: {
1
+ import type { ContextManifestSegment, ContextManifestSystemSection } from "../../shared/context-xray.js";
2
+ export declare function ContextTreemap({ segments, systemSections, onSelect, }: {
3
3
  segments: ContextManifestSegment[];
4
+ systemSections?: ContextManifestSystemSection[];
4
5
  onSelect?: (segmentId: string) => void;
5
6
  }): import("react").JSX.Element;
6
7
  //# sourceMappingURL=ContextTreemap.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ContextTreemap.d.ts","sourceRoot":"","sources":["../../../src/client/context-xray/ContextTreemap.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AA4C3E,wBAAgB,cAAc,CAAC,EAC7B,QAAQ,EACR,QAAQ,GACT,EAAE;IACD,QAAQ,EAAE,sBAAsB,EAAE,CAAC;IACnC,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC,+BA4DA"}
1
+ {"version":3,"file":"ContextTreemap.d.ts","sourceRoot":"","sources":["../../../src/client/context-xray/ContextTreemap.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,sBAAsB,EACtB,4BAA4B,EAC7B,MAAM,8BAA8B,CAAC;AA4CtC,wBAAgB,cAAc,CAAC,EAC7B,QAAQ,EACR,cAAmB,EACnB,QAAQ,GACT,EAAE;IACD,QAAQ,EAAE,sBAAsB,EAAE,CAAC;IACnC,cAAc,CAAC,EAAE,4BAA4B,EAAE,CAAC;IAChD,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC,+BAsEA"}
@@ -9,7 +9,7 @@ function TreemapContent(props) {
9
9
  const showLabel = width > 90 && height > 42;
10
10
  return (_jsxs("g", { children: [_jsx("rect", { x: x, y: y, width: width, height: height, rx: 3, ry: 3, fill: groupFill(group), stroke: "var(--background)", strokeWidth: 2 }), showLabel && (_jsx("foreignObject", { x: x + 6, y: y + 6, width: width - 12, height: height - 12, children: _jsxs("div", { className: "flex h-full flex-col justify-between overflow-hidden text-[11px] leading-tight text-white", children: [_jsx("div", { className: "truncate font-medium", children: name }), _jsx("div", { className: "text-white/85", children: formatTokens(size) })] }) }))] }));
11
11
  }
12
- export function ContextTreemap({ segments, onSelect, }) {
12
+ export function ContextTreemap({ segments, systemSections = [], onSelect, }) {
13
13
  const containerRef = useRef(null);
14
14
  const [chartWidth, setChartWidth] = useState(0);
15
15
  const data = segments
@@ -20,6 +20,14 @@ export function ContextTreemap({ segments, onSelect, }) {
20
20
  group: segment.group,
21
21
  segmentId: segment.segmentId,
22
22
  }));
23
+ data.push(...systemSections
24
+ .filter((section) => section.tokenCount > 0)
25
+ .map((section) => ({
26
+ name: section.label,
27
+ size: section.tokenCount,
28
+ group: `System · ${section.governance}`,
29
+ segmentId: section.segmentId,
30
+ })));
23
31
  useEffect(() => {
24
32
  const element = containerRef.current;
25
33
  if (!element)
@@ -1 +1 @@
1
- {"version":3,"file":"ContextTreemap.js","sourceRoot":"","sources":["../../../src/client/context-xray/ContextTreemap.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useRef, useState } from \"react\";\nimport { Treemap } from \"recharts\";\n\nimport type { ContextManifestSegment } from \"../../shared/context-xray.js\";\nimport { formatTokens, groupFill } from \"./format.js\";\n\ninterface TreemapDatum {\n name: string;\n size: number;\n group: string;\n segmentId: string;\n}\n\nfunction TreemapContent(props: any) {\n const { x, y, width, height, name, group, size } = props;\n if (width < 8 || height < 8) return null;\n const showLabel = width > 90 && height > 42;\n return (\n <g>\n <rect\n x={x}\n y={y}\n width={width}\n height={height}\n rx={3}\n ry={3}\n fill={groupFill(group)}\n stroke=\"var(--background)\"\n strokeWidth={2}\n />\n {showLabel && (\n <foreignObject\n x={x + 6}\n y={y + 6}\n width={width - 12}\n height={height - 12}\n >\n <div className=\"flex h-full flex-col justify-between overflow-hidden text-[11px] leading-tight text-white\">\n <div className=\"truncate font-medium\">{name}</div>\n <div className=\"text-white/85\">{formatTokens(size)}</div>\n </div>\n </foreignObject>\n )}\n </g>\n );\n}\n\nexport function ContextTreemap({\n segments,\n onSelect,\n}: {\n segments: ContextManifestSegment[];\n onSelect?: (segmentId: string) => void;\n}) {\n const containerRef = useRef<HTMLDivElement>(null);\n const [chartWidth, setChartWidth] = useState(0);\n const data: TreemapDatum[] = segments\n .filter((segment) => segment.status !== \"evicted\" && segment.tokenCount > 0)\n .map((segment) => ({\n name: segment.label,\n size: segment.tokenCount,\n group: segment.group,\n segmentId: segment.segmentId,\n }));\n\n useEffect(() => {\n const element = containerRef.current;\n if (!element) return;\n\n const updateWidth = () => {\n setChartWidth(Math.max(0, Math.floor(element.clientWidth - 8)));\n };\n updateWidth();\n\n const observer =\n typeof ResizeObserver !== \"undefined\"\n ? new ResizeObserver(updateWidth)\n : null;\n observer?.observe(element);\n window.addEventListener(\"resize\", updateWidth);\n return () => {\n observer?.disconnect();\n window.removeEventListener(\"resize\", updateWidth);\n };\n }, []);\n\n if (data.length === 0) {\n return (\n <div className=\"flex h-52 items-center justify-center rounded-md bg-muted/30 text-xs text-muted-foreground\">\n No active segments\n </div>\n );\n }\n\n return (\n <div ref={containerRef} className=\"h-56 min-w-0 rounded-md bg-muted/25 p-1\">\n {chartWidth > 0 && (\n <Treemap\n width={chartWidth}\n height={216}\n data={data as any}\n dataKey=\"size\"\n nameKey=\"name\"\n aspectRatio={4 / 3}\n isAnimationActive={false}\n content={<TreemapContent />}\n onClick={(datum: any) => {\n if (datum?.segmentId) onSelect?.(datum.segmentId);\n }}\n />\n )}\n </div>\n );\n}\n"]}
1
+ {"version":3,"file":"ContextTreemap.js","sourceRoot":"","sources":["../../../src/client/context-xray/ContextTreemap.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useRef, useState } from \"react\";\nimport { Treemap } from \"recharts\";\n\nimport type {\n ContextManifestSegment,\n ContextManifestSystemSection,\n} from \"../../shared/context-xray.js\";\nimport { formatTokens, groupFill } from \"./format.js\";\n\ninterface TreemapDatum {\n name: string;\n size: number;\n group: string;\n segmentId: string;\n}\n\nfunction TreemapContent(props: any) {\n const { x, y, width, height, name, group, size } = props;\n if (width < 8 || height < 8) return null;\n const showLabel = width > 90 && height > 42;\n return (\n <g>\n <rect\n x={x}\n y={y}\n width={width}\n height={height}\n rx={3}\n ry={3}\n fill={groupFill(group)}\n stroke=\"var(--background)\"\n strokeWidth={2}\n />\n {showLabel && (\n <foreignObject\n x={x + 6}\n y={y + 6}\n width={width - 12}\n height={height - 12}\n >\n <div className=\"flex h-full flex-col justify-between overflow-hidden text-[11px] leading-tight text-white\">\n <div className=\"truncate font-medium\">{name}</div>\n <div className=\"text-white/85\">{formatTokens(size)}</div>\n </div>\n </foreignObject>\n )}\n </g>\n );\n}\n\nexport function ContextTreemap({\n segments,\n systemSections = [],\n onSelect,\n}: {\n segments: ContextManifestSegment[];\n systemSections?: ContextManifestSystemSection[];\n onSelect?: (segmentId: string) => void;\n}) {\n const containerRef = useRef<HTMLDivElement>(null);\n const [chartWidth, setChartWidth] = useState(0);\n const data: TreemapDatum[] = segments\n .filter((segment) => segment.status !== \"evicted\" && segment.tokenCount > 0)\n .map((segment) => ({\n name: segment.label,\n size: segment.tokenCount,\n group: segment.group,\n segmentId: segment.segmentId,\n }));\n data.push(\n ...systemSections\n .filter((section) => section.tokenCount > 0)\n .map((section) => ({\n name: section.label,\n size: section.tokenCount,\n group: `System · ${section.governance}`,\n segmentId: section.segmentId,\n })),\n );\n\n useEffect(() => {\n const element = containerRef.current;\n if (!element) return;\n\n const updateWidth = () => {\n setChartWidth(Math.max(0, Math.floor(element.clientWidth - 8)));\n };\n updateWidth();\n\n const observer =\n typeof ResizeObserver !== \"undefined\"\n ? new ResizeObserver(updateWidth)\n : null;\n observer?.observe(element);\n window.addEventListener(\"resize\", updateWidth);\n return () => {\n observer?.disconnect();\n window.removeEventListener(\"resize\", updateWidth);\n };\n }, []);\n\n if (data.length === 0) {\n return (\n <div className=\"flex h-52 items-center justify-center rounded-md bg-muted/30 text-xs text-muted-foreground\">\n No active segments\n </div>\n );\n }\n\n return (\n <div ref={containerRef} className=\"h-56 min-w-0 rounded-md bg-muted/25 p-1\">\n {chartWidth > 0 && (\n <Treemap\n width={chartWidth}\n height={216}\n data={data as any}\n dataKey=\"size\"\n nameKey=\"name\"\n aspectRatio={4 / 3}\n isAnimationActive={false}\n content={<TreemapContent />}\n onClick={(datum: any) => {\n if (datum?.segmentId) onSelect?.(datum.segmentId);\n }}\n />\n )}\n </div>\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"ContextXRayPanel.d.ts","sourceRoot":"","sources":["../../../src/client/context-xray/ContextXRayPanel.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EACV,eAAe,EAEf,oBAAoB,EACrB,MAAM,8BAA8B,CAAC;AA8DtC,wBAAgB,gBAAgB,CAAC,EAC/B,QAAQ,EACR,UAAU,EACV,KAAK,EACL,OAAO,EACP,SAAS,GACV,EAAE;IACD,QAAQ,EAAE,eAAe,CAAC;IAC1B,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;IAC9C,KAAK,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,OAAO,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,SAAS,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC,+BAuKA"}
1
+ {"version":3,"file":"ContextXRayPanel.d.ts","sourceRoot":"","sources":["../../../src/client/context-xray/ContextXRayPanel.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EACV,eAAe,EAGf,oBAAoB,EACrB,MAAM,8BAA8B,CAAC;AAkItC,wBAAgB,gBAAgB,CAAC,EAC/B,QAAQ,EACR,UAAU,EACV,KAAK,EACL,OAAO,EACP,SAAS,GACV,EAAE;IACD,QAAQ,EAAE,eAAe,CAAC;IAC1B,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;IAC9C,KAAK,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,OAAO,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,SAAS,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC,+BAsQA"}
@@ -1,7 +1,9 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { IconChartTreemap, IconChevronDown, IconChevronRight, IconListDetails, } from "@tabler/icons-react";
2
+ import { IconChartTreemap, IconChevronDown, IconChevronRight, IconLock, IconListDetails, } from "@tabler/icons-react";
3
3
  import { useMemo, useState } from "react";
4
+ import { manifestConversationTokens, manifestSystemTokens, } from "../../shared/context-xray.js";
4
5
  import { Tooltip, TooltipContent, TooltipTrigger, } from "../components/ui/tooltip.js";
6
+ import { useT } from "../i18n.js";
5
7
  import { cn } from "../utils.js";
6
8
  import { ContextSegmentRow } from "./ContextSegmentRow.js";
7
9
  import { ContextTreemap } from "./ContextTreemap.js";
@@ -47,18 +49,71 @@ function groupedSegments(segments) {
47
49
  return b.tokens - a.tokens;
48
50
  });
49
51
  }
52
+ const GOVERNANCE_ORDER = ["required", "inherited", "user"];
53
+ function governanceLabel(governance, t) {
54
+ switch (governance) {
55
+ case "required":
56
+ return t("contextXray.governance.required", {
57
+ defaultValue: "Required",
58
+ });
59
+ case "inherited":
60
+ return t("contextXray.governance.inherited", {
61
+ defaultValue: "Inherited",
62
+ });
63
+ case "user":
64
+ return t("contextXray.governance.user", {
65
+ defaultValue: "Your context",
66
+ });
67
+ }
68
+ }
69
+ function sourceLabel(section) {
70
+ return (section.sourceRef?.path ??
71
+ section.sourceRef?.resourceId ??
72
+ section.sourceRef?.scope ??
73
+ "framework");
74
+ }
75
+ function SystemSectionRow({ section, totalTokens, }) {
76
+ const share = totalTokens > 0 ? Math.round((section.tokenCount / totalTokens) * 100) : 0;
77
+ return (_jsxs("div", { className: "flex min-h-12 items-start gap-2 rounded-sm px-2 py-1.5", children: [_jsx("span", { className: "mt-1 flex size-6 shrink-0 items-center justify-center rounded-md text-muted-foreground", children: _jsx(IconLock, { className: "h-3.5 w-3.5" }) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "truncate text-[13px] font-medium leading-5 text-foreground", children: section.label }), _jsxs("div", { className: "truncate text-[11px] text-muted-foreground", children: [sourceLabel(section), " \u00B7 ", formatTokens(section.tokenCount), " tokens \u00B7", " ", share, "%", section.tokenMethod === "estimate" ? " · estimated" : ""] }), section.preview ? (_jsx("div", { className: "mt-0.5 line-clamp-2 text-[11px] text-muted-foreground/80", children: section.preview })) : null] })] }));
78
+ }
50
79
  export function ContextXRayPanel({ manifest, optimistic, onPin, onEvict, onRestore, }) {
80
+ const t = useT();
51
81
  const [mode, setMode] = useState("list");
52
82
  const [collapsed, setCollapsed] = useState(new Set());
53
83
  const segments = useMemo(() => applyOptimisticStatus(manifest.segments, optimistic), [manifest.segments, optimistic]);
54
84
  const groups = useMemo(() => groupedSegments(segments), [segments]);
85
+ const systemSections = manifest.systemSections ?? [];
86
+ const systemGroups = useMemo(() => {
87
+ const grouped = new Map();
88
+ for (const section of systemSections) {
89
+ const list = grouped.get(section.governance) ?? [];
90
+ list.push(section);
91
+ grouped.set(section.governance, list);
92
+ }
93
+ return GOVERNANCE_ORDER.flatMap((governance) => {
94
+ const sections = grouped.get(governance);
95
+ return sections && sections.length > 0
96
+ ? [
97
+ {
98
+ governance,
99
+ sections,
100
+ tokens: sections.reduce((sum, section) => sum + section.tokenCount, 0),
101
+ },
102
+ ]
103
+ : [];
104
+ });
105
+ }, [systemSections]);
55
106
  const contextWindow = resolveContextWindow(manifest.model);
56
107
  const pct = Math.min(100, Math.round((manifest.totalTokens / contextWindow) * 100));
57
108
  const headroom = Math.max(0, contextWindow - manifest.totalTokens);
58
109
  const pinned = segments.filter((s) => s.status === "pinned").length;
59
110
  const evicted = segments.filter((s) => s.status === "evicted").length;
111
+ const systemTokens = manifestSystemTokens(manifest);
112
+ const conversationTokens = manifestConversationTokens(manifest);
60
113
  const details = [
61
114
  `${formatTokens(headroom)} free`,
115
+ systemTokens > 0 ? `${formatTokens(systemTokens)} system` : null,
116
+ `${formatTokens(conversationTokens)} conversation`,
62
117
  pinned > 0 ? `${pinned} pinned` : null,
63
118
  evicted > 0 ? `${evicted} evicted` : null,
64
119
  manifest.tokenCountMethod === "estimate" ? "estimated" : null,
@@ -67,29 +122,49 @@ export function ContextXRayPanel({ manifest, optimistic, onPin, onEvict, onResto
67
122
  return (_jsxs("div", { className: "flex max-h-[min(72vh,520px)] flex-col", children: [_jsxs("div", { className: "border-b border-border/60 px-3 py-2.5", children: [_jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsx("h2", { className: "min-w-0 truncate text-sm font-medium text-foreground", children: "Context X-Ray" }), _jsxs("div", { className: "shrink-0 text-xs tabular-nums text-muted-foreground", children: [formatTokens(manifest.totalTokens), " \u00B7 ", pct, "%"] })] }), _jsx("div", { className: "mt-2 h-1 overflow-hidden rounded-full bg-muted/70", children: _jsx("div", { className: "h-full rounded-full bg-foreground origin-left transition-transform duration-200", style: {
68
123
  transform: `scaleX(${Math.min(1, pct / 100)})`,
69
124
  width: "100%",
70
- } }) }), _jsxs("div", { className: "mt-1.5 flex flex-wrap items-center gap-x-2 gap-y-1 text-[11px] text-muted-foreground", children: [details.map((detail) => (_jsx("span", { children: detail }, detail))), manifest.reclaimedTokens > 0 && (_jsxs("span", { className: "font-medium text-emerald-600 dark:text-emerald-400", children: ["-", formatTokens(manifest.reclaimedTokens)] }))] })] }), _jsxs("div", { className: "overflow-y-auto px-2 py-2", children: [_jsx("div", { className: "mb-1 flex items-center justify-end", children: _jsxs("div", { className: "inline-flex rounded-md bg-muted/40 p-0.5", children: [_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", onClick: () => setMode("list"), "aria-label": "Show context list", className: cn("flex size-7 items-center justify-center rounded text-muted-foreground", mode === "list"
125
+ } }) }), _jsxs("div", { className: "mt-1.5 flex flex-wrap items-center gap-x-2 gap-y-1 text-[11px] text-muted-foreground", children: [details.map((detail) => (_jsx("span", { children: detail }, detail))), manifest.reclaimedTokens > 0 && (_jsxs("span", { className: "font-medium text-emerald-600 dark:text-emerald-400", children: ["-", formatTokens(manifest.reclaimedTokens)] }))] })] }), _jsxs("div", { className: "overflow-y-auto px-2 py-2", children: [_jsx("div", { className: "mb-1 flex items-center justify-end", children: _jsxs("div", { className: "inline-flex rounded-md bg-muted/40 p-0.5", children: [_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", onClick: () => setMode("list"), "aria-label": "Show context list", className: cn("flex size-7 cursor-pointer items-center justify-center rounded text-muted-foreground", mode === "list"
71
126
  ? "bg-background text-foreground shadow-sm"
72
- : "hover:text-foreground"), children: _jsx(IconListDetails, { className: "h-3.5 w-3.5" }) }) }), _jsx(TooltipContent, { children: "List" })] }), _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", onClick: () => setMode("map"), "aria-label": "Show context map", className: cn("flex size-7 items-center justify-center rounded text-muted-foreground", mode === "map"
127
+ : "hover:text-foreground"), children: _jsx(IconListDetails, { className: "h-3.5 w-3.5" }) }) }), _jsx(TooltipContent, { children: "List" })] }), _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", onClick: () => setMode("map"), "aria-label": "Show context map", className: cn("flex size-7 cursor-pointer items-center justify-center rounded text-muted-foreground", mode === "map"
73
128
  ? "bg-background text-foreground shadow-sm"
74
- : "hover:text-foreground"), children: _jsx(IconChartTreemap, { className: "h-3.5 w-3.5" }) }) }), _jsx(TooltipContent, { children: "Map" })] })] }) }), mode === "map" ? (_jsx(ContextTreemap, { segments: segments, onSelect: (segmentId) => {
129
+ : "hover:text-foreground"), children: _jsx(IconChartTreemap, { className: "h-3.5 w-3.5" }) }) }), _jsx(TooltipContent, { children: "Map" })] })] }) }), mode === "map" ? (_jsx(ContextTreemap, { segments: segments, systemSections: systemSections, onSelect: (segmentId) => {
75
130
  const segment = segments.find((s) => s.segmentId === segmentId);
76
131
  if (segment)
77
132
  setCollapsed(new Set());
78
- } })) : (_jsx("div", { className: "divide-y divide-border/60", children: groups.map((group) => {
79
- const isCollapsed = collapsed.has(group.name);
80
- return (_jsxs("div", { children: [_jsxs("button", { type: "button", onClick: () => {
81
- setCollapsed((prev) => {
82
- const next = new Set(prev);
83
- if (next.has(group.name))
84
- next.delete(group.name);
85
- else
86
- next.add(group.name);
87
- return next;
88
- });
89
- }, className: "flex w-full items-center gap-2 rounded-sm px-1.5 py-2 text-left hover:bg-accent/35", children: [isCollapsed ? (_jsx(IconChevronRight, { className: "h-3.5 w-3.5 text-muted-foreground" })) : (_jsx(IconChevronDown, { className: "h-3.5 w-3.5 text-muted-foreground" })), _jsx("span", { className: cn("h-2 w-2 rounded-full", groupColor(group.name)) }), _jsx("span", { className: "min-w-0 flex-1 truncate text-xs font-medium", children: group.name }), _jsx("span", { className: "text-[11px] text-muted-foreground", children: formatTokens(group.tokens) })] }), !isCollapsed && (_jsx("div", { className: "pb-1", children: group.segments
90
- .slice()
91
- .sort((a, b) => b.tokenCount - a.tokenCount)
92
- .map((segment) => (_jsx(ContextSegmentRow, { segment: segment, advisory: !manifest.enforceable, onPin: () => onPin(segment.segmentId), onEvict: () => onEvict(segment.segmentId), onRestore: () => onRestore(segment.segmentId) }, segment.segmentId))) }))] }, group.name));
93
- }) }))] })] }));
133
+ } })) : (_jsxs("div", { className: "divide-y divide-border/60", children: [systemGroups.length > 0 && (_jsxs("div", { children: [_jsx("div", { className: "px-1.5 pb-1 pt-2 text-[10px] font-semibold uppercase tracking-[0.12em] text-muted-foreground", children: t("contextXray.systemOrdered", {
134
+ defaultValue: "System · ordered, not evictable",
135
+ }) }), systemGroups.map((group) => {
136
+ const groupKey = `system:${group.governance}`;
137
+ const isCollapsed = collapsed.has(groupKey);
138
+ return (_jsxs("div", { children: [_jsxs("button", { type: "button", onClick: () => {
139
+ setCollapsed((prev) => {
140
+ const next = new Set(prev);
141
+ if (next.has(groupKey))
142
+ next.delete(groupKey);
143
+ else
144
+ next.add(groupKey);
145
+ return next;
146
+ });
147
+ }, className: "flex w-full cursor-pointer items-center gap-2 rounded-sm px-1.5 py-2 text-left hover:bg-accent/35", children: [isCollapsed ? (_jsx(IconChevronRight, { className: "h-3.5 w-3.5 text-muted-foreground" })) : (_jsx(IconChevronDown, { className: "h-3.5 w-3.5 text-muted-foreground" })), _jsx(IconLock, { className: "h-3 w-3 text-muted-foreground" }), _jsx("span", { className: "min-w-0 flex-1 truncate text-xs font-medium", children: governanceLabel(group.governance, t) }), _jsxs("span", { className: "text-[11px] text-muted-foreground", children: [formatTokens(group.tokens), " \u00B7", " ", manifest.totalTokens > 0
148
+ ? Math.round((group.tokens / manifest.totalTokens) * 100)
149
+ : 0, "%"] })] }), !isCollapsed && (_jsx("div", { className: "pb-1", children: group.sections
150
+ .slice()
151
+ .sort((a, b) => b.tokenCount - a.tokenCount)
152
+ .map((section) => (_jsx(SystemSectionRow, { section: section, totalTokens: manifest.totalTokens }, section.segmentId))) }))] }, groupKey));
153
+ })] })), groups.map((group) => {
154
+ const isCollapsed = collapsed.has(group.name);
155
+ return (_jsxs("div", { children: [_jsxs("button", { type: "button", onClick: () => {
156
+ setCollapsed((prev) => {
157
+ const next = new Set(prev);
158
+ if (next.has(group.name))
159
+ next.delete(group.name);
160
+ else
161
+ next.add(group.name);
162
+ return next;
163
+ });
164
+ }, className: "flex w-full cursor-pointer items-center gap-2 rounded-sm px-1.5 py-2 text-left hover:bg-accent/35", children: [isCollapsed ? (_jsx(IconChevronRight, { className: "h-3.5 w-3.5 text-muted-foreground" })) : (_jsx(IconChevronDown, { className: "h-3.5 w-3.5 text-muted-foreground" })), _jsx("span", { className: cn("h-2 w-2 rounded-full", groupColor(group.name)) }), _jsx("span", { className: "min-w-0 flex-1 truncate text-xs font-medium", children: group.name }), _jsx("span", { className: "text-[11px] text-muted-foreground", children: formatTokens(group.tokens) })] }), !isCollapsed && (_jsx("div", { className: "pb-1", children: group.segments
165
+ .slice()
166
+ .sort((a, b) => b.tokenCount - a.tokenCount)
167
+ .map((segment) => (_jsx(ContextSegmentRow, { segment: segment, advisory: !manifest.enforceable, onPin: () => onPin(segment.segmentId), onEvict: () => onEvict(segment.segmentId), onRestore: () => onRestore(segment.segmentId) }, segment.segmentId))) }))] }, group.name));
168
+ })] }))] })] }));
94
169
  }
95
170
  //# sourceMappingURL=ContextXRayPanel.js.map