@iloveagents/foundry-web-ui 0.3.0 → 0.4.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 (223) hide show
  1. package/README.md +14 -5
  2. package/dist/components/ag-ui-runtime-provider.d.ts +64 -0
  3. package/dist/components/ag-ui-runtime-provider.js +71 -0
  4. package/dist/components/app-brand.d.ts +6 -0
  5. package/dist/components/app-brand.js +13 -0
  6. package/dist/components/assistant-chat.d.ts +26 -0
  7. package/dist/components/assistant-chat.js +93 -0
  8. package/dist/components/chat-attachments.d.ts +25 -0
  9. package/dist/components/chat-attachments.js +20 -0
  10. package/dist/components/chat-bubble.d.ts +1 -0
  11. package/dist/components/chat-bubble.js +103 -0
  12. package/dist/components/chat-header.d.ts +2 -0
  13. package/dist/components/chat-header.js +16 -0
  14. package/dist/components/client-tool-executor.d.ts +12 -0
  15. package/dist/components/client-tool-executor.js +108 -0
  16. package/dist/components/collection-empty-state.d.ts +9 -0
  17. package/dist/components/collection-empty-state.js +6 -0
  18. package/dist/components/collection-filter-bar.d.ts +19 -0
  19. package/dist/components/collection-filter-bar.js +28 -0
  20. package/dist/components/collection-search-input.d.ts +6 -0
  21. package/dist/components/collection-search-input.js +8 -0
  22. package/dist/components/collection-skeleton.d.ts +6 -0
  23. package/dist/components/collection-skeleton.js +10 -0
  24. package/dist/components/collection-sort-menu.d.ts +10 -0
  25. package/dist/components/collection-sort-menu.js +9 -0
  26. package/dist/components/collection-surface.d.ts +8 -0
  27. package/dist/components/collection-surface.js +5 -0
  28. package/dist/components/collection-toolbar.d.ts +9 -0
  29. package/dist/components/collection-toolbar.js +5 -0
  30. package/dist/components/collection-view-toggle.d.ts +7 -0
  31. package/dist/components/collection-view-toggle.js +17 -0
  32. package/dist/components/composer-submit-bridge.d.ts +1 -0
  33. package/dist/components/composer-submit-bridge.js +15 -0
  34. package/dist/components/confirm-dialog.d.ts +11 -0
  35. package/dist/components/confirm-dialog.js +6 -0
  36. package/dist/components/confirmation-card.d.ts +14 -0
  37. package/dist/components/confirmation-card.js +12 -0
  38. package/dist/components/context-badges.d.ts +16 -0
  39. package/dist/components/context-badges.js +56 -0
  40. package/dist/components/context-bar.d.ts +41 -0
  41. package/dist/components/context-bar.js +123 -0
  42. package/dist/components/form-dialog.d.ts +12 -0
  43. package/dist/components/form-dialog.js +13 -0
  44. package/dist/components/global-selection-popover.d.ts +7 -0
  45. package/dist/components/global-selection-popover.js +167 -0
  46. package/dist/components/infinite-scroll-sentinel.d.ts +6 -0
  47. package/dist/components/infinite-scroll-sentinel.js +25 -0
  48. package/dist/components/json-viewer.d.ts +10 -0
  49. package/dist/components/json-viewer.js +80 -0
  50. package/dist/components/loading-indicator.d.ts +4 -0
  51. package/dist/components/loading-indicator.js +22 -0
  52. package/dist/components/markdown-text.d.ts +13 -0
  53. package/dist/components/markdown-text.js +221 -0
  54. package/dist/components/name-dialog.d.ts +16 -0
  55. package/dist/components/name-dialog.js +23 -0
  56. package/dist/components/selection-popover.d.ts +12 -0
  57. package/dist/components/selection-popover.js +111 -0
  58. package/dist/components/show-document-tool-ui.d.ts +1 -0
  59. package/dist/components/show-document-tool-ui.js +53 -0
  60. package/dist/components/sidebar.d.ts +4 -0
  61. package/dist/components/sidebar.js +904 -0
  62. package/dist/components/surface-card.d.ts +9 -0
  63. package/dist/components/surface-card.js +33 -0
  64. package/dist/components/theme-runtime-provider.d.ts +15 -0
  65. package/dist/components/theme-runtime-provider.js +48 -0
  66. package/dist/components/theme-toggle.d.ts +2 -0
  67. package/dist/components/theme-toggle.js +19 -0
  68. package/dist/components/tool-call-card.d.ts +27 -0
  69. package/dist/components/tool-call-card.js +13 -0
  70. package/dist/components/tool-fallback.d.ts +26 -0
  71. package/dist/components/tool-fallback.js +129 -0
  72. package/dist/components/tool-panel-layout.d.ts +10 -0
  73. package/dist/components/tool-panel-layout.js +12 -0
  74. package/dist/components/tool-panel.d.ts +1 -0
  75. package/dist/components/tool-panel.js +89 -0
  76. package/dist/components/tooltip-icon-button.d.ts +7 -0
  77. package/dist/components/tooltip-icon-button.js +9 -0
  78. package/dist/components/user-menu.d.ts +2 -0
  79. package/dist/components/user-menu.js +14 -0
  80. package/dist/index.d.ts +68 -0
  81. package/dist/index.js +83 -0
  82. package/dist/lib/ag-ui-adapter.d.ts +29 -0
  83. package/dist/lib/ag-ui-adapter.js +373 -0
  84. package/dist/lib/app-store.d.ts +115 -0
  85. package/dist/lib/app-store.js +199 -0
  86. package/dist/lib/attachment-adapter.d.ts +20 -0
  87. package/dist/lib/attachment-adapter.js +99 -0
  88. package/dist/lib/auth-provider.d.ts +16 -0
  89. package/dist/lib/auth-provider.js +88 -0
  90. package/dist/lib/chat-bubble-store.d.ts +30 -0
  91. package/dist/lib/chat-bubble-store.js +23 -0
  92. package/dist/lib/chat-lifecycle-store.d.ts +10 -0
  93. package/{src/lib/chat-lifecycle-store.ts → dist/lib/chat-lifecycle-store.js} +3 -13
  94. package/dist/lib/client-tools.d.ts +11 -0
  95. package/dist/lib/client-tools.js +274 -0
  96. package/dist/lib/composer-submit-store.d.ts +12 -0
  97. package/dist/lib/composer-submit-store.js +17 -0
  98. package/dist/lib/dev-store.d.ts +38 -0
  99. package/dist/lib/dev-store.js +32 -0
  100. package/dist/lib/nav-config.d.ts +159 -0
  101. package/dist/lib/nav-config.js +162 -0
  102. package/dist/lib/nav-dnd.d.ts +8 -0
  103. package/dist/lib/nav-dnd.js +9 -0
  104. package/dist/lib/nav-store.d.ts +45 -0
  105. package/dist/lib/nav-store.js +49 -0
  106. package/dist/lib/selection-context.d.ts +21 -0
  107. package/dist/lib/selection-context.js +34 -0
  108. package/dist/lib/sidebar-store.d.ts +23 -0
  109. package/dist/lib/sidebar-store.js +98 -0
  110. package/dist/lib/theme-runtime.d.ts +130 -0
  111. package/dist/lib/theme-runtime.js +479 -0
  112. package/dist/lib/theme-store.d.ts +15 -0
  113. package/dist/lib/theme-store.js +53 -0
  114. package/dist/lib/tool-panel-store.d.ts +48 -0
  115. package/dist/lib/tool-panel-store.js +69 -0
  116. package/dist/lib/use-new-conversation.d.ts +8 -0
  117. package/dist/lib/use-new-conversation.js +62 -0
  118. package/dist/lib/use-page-tools.d.ts +27 -0
  119. package/{src/lib/use-page-tools.ts → dist/lib/use-page-tools.js} +11 -13
  120. package/dist/styles.css +142 -0
  121. package/dist/ui/collapsible.d.ts +5 -0
  122. package/{src/ui/collapsible.tsx → dist/ui/collapsible.js} +0 -2
  123. package/dist/ui/dialog.d.ts +15 -0
  124. package/dist/ui/dialog.js +25 -0
  125. package/dist/ui/dropdown-menu.d.ts +7 -0
  126. package/dist/ui/dropdown-menu.js +19 -0
  127. package/dist/ui/popover.d.ts +7 -0
  128. package/dist/ui/popover.js +10 -0
  129. package/dist/ui/select.d.ts +4 -0
  130. package/dist/ui/select.js +9 -0
  131. package/dist/ui/tooltip.d.ts +7 -0
  132. package/dist/ui/tooltip.js +10 -0
  133. package/package.json +31 -12
  134. package/AGENTS.md +0 -59
  135. package/CHANGELOG.md +0 -203
  136. package/CLAUDE.md +0 -1
  137. package/src/__tests__/no-spaces-imports.test.ts +0 -59
  138. package/src/__tests__/open-core-guards.test.ts +0 -307
  139. package/src/__tests__/theme-runtime.test.ts +0 -81
  140. package/src/__tests__/tool-fallback.test.tsx +0 -109
  141. package/src/components/__tests__/context-bar.test.ts +0 -112
  142. package/src/components/ag-ui-runtime-provider.tsx +0 -170
  143. package/src/components/app-brand.tsx +0 -38
  144. package/src/components/assistant-chat.tsx +0 -461
  145. package/src/components/chat-attachments.tsx +0 -68
  146. package/src/components/chat-bubble.tsx +0 -373
  147. package/src/components/chat-header.tsx +0 -44
  148. package/src/components/client-tool-executor.tsx +0 -230
  149. package/src/components/collection-empty-state.tsx +0 -37
  150. package/src/components/collection-filter-bar.tsx +0 -168
  151. package/src/components/collection-search-input.tsx +0 -41
  152. package/src/components/collection-skeleton.tsx +0 -55
  153. package/src/components/collection-sort-menu.tsx +0 -62
  154. package/src/components/collection-surface.tsx +0 -46
  155. package/src/components/collection-toolbar.tsx +0 -33
  156. package/src/components/collection-view-toggle.tsx +0 -61
  157. package/src/components/composer-submit-bridge.tsx +0 -19
  158. package/src/components/confirm-dialog.tsx +0 -49
  159. package/src/components/confirmation-card.tsx +0 -32
  160. package/src/components/context-badges.tsx +0 -136
  161. package/src/components/context-bar.tsx +0 -238
  162. package/src/components/form-dialog.tsx +0 -56
  163. package/src/components/global-selection-popover.tsx +0 -266
  164. package/src/components/infinite-scroll-sentinel.tsx +0 -48
  165. package/src/components/json-viewer.tsx +0 -232
  166. package/src/components/loading-indicator.tsx +0 -40
  167. package/src/components/markdown-text-citations.test.tsx +0 -108
  168. package/src/components/markdown-text.tsx +0 -508
  169. package/src/components/name-dialog.tsx +0 -87
  170. package/src/components/selection-popover.tsx +0 -156
  171. package/src/components/show-document-tool-ui.tsx +0 -90
  172. package/src/components/sidebar.test.tsx +0 -611
  173. package/src/components/sidebar.tsx +0 -1689
  174. package/src/components/surface-card.tsx +0 -45
  175. package/src/components/theme-runtime-provider.tsx +0 -93
  176. package/src/components/theme-toggle.tsx +0 -27
  177. package/src/components/tool-call-card.tsx +0 -126
  178. package/src/components/tool-fallback.tsx +0 -169
  179. package/src/components/tool-panel-layout.tsx +0 -36
  180. package/src/components/tool-panel.tsx +0 -233
  181. package/src/components/tooltip-icon-button.tsx +0 -28
  182. package/src/components/user-menu.tsx +0 -60
  183. package/src/index.ts +0 -185
  184. package/src/lib/__tests__/ag-ui-adapter.test.ts +0 -273
  185. package/src/lib/__tests__/app-store.test.ts +0 -405
  186. package/src/lib/__tests__/attachment-adapter.test.ts +0 -48
  187. package/src/lib/__tests__/chat-bubble-store.test.ts +0 -67
  188. package/src/lib/__tests__/client-tools.test.ts +0 -124
  189. package/src/lib/__tests__/dev-store.test.ts +0 -78
  190. package/src/lib/__tests__/nav-config.test.ts +0 -135
  191. package/src/lib/__tests__/nav-dnd.test.ts +0 -24
  192. package/src/lib/__tests__/nav-store.test.ts +0 -59
  193. package/src/lib/__tests__/selection-context.test.ts +0 -114
  194. package/src/lib/__tests__/sidebar-store.test.ts +0 -144
  195. package/src/lib/__tests__/theme-store.test.ts +0 -83
  196. package/src/lib/__tests__/tool-panel-store.test.ts +0 -61
  197. package/src/lib/__tests__/use-page-context.test.ts +0 -58
  198. package/src/lib/ag-ui-adapter.ts +0 -412
  199. package/src/lib/app-store.ts +0 -361
  200. package/src/lib/attachment-adapter.ts +0 -92
  201. package/src/lib/auth-provider.tsx +0 -144
  202. package/src/lib/chat-bubble-store.ts +0 -46
  203. package/src/lib/client-tools.ts +0 -293
  204. package/src/lib/composer-submit-store.ts +0 -32
  205. package/src/lib/dev-store.ts +0 -69
  206. package/src/lib/nav-config.ts +0 -329
  207. package/src/lib/nav-dnd.ts +0 -14
  208. package/src/lib/nav-store.ts +0 -89
  209. package/src/lib/selection-context.ts +0 -65
  210. package/src/lib/sidebar-store.ts +0 -113
  211. package/src/lib/theme-runtime.ts +0 -660
  212. package/src/lib/theme-store.ts +0 -67
  213. package/src/lib/tool-panel-store.ts +0 -121
  214. package/src/lib/use-new-conversation.test.tsx +0 -168
  215. package/src/lib/use-new-conversation.ts +0 -64
  216. package/src/ui/dialog.tsx +0 -109
  217. package/src/ui/dropdown-menu.tsx +0 -75
  218. package/src/ui/popover.tsx +0 -34
  219. package/src/ui/select.tsx +0 -15
  220. package/src/ui/tooltip.tsx +0 -30
  221. package/src/vite-env.d.ts +0 -1
  222. package/tsconfig.json +0 -16
  223. package/vitest.config.ts +0 -8
@@ -0,0 +1,62 @@
1
+ import { useCallback } from "react";
2
+ import { useNavigate } from "react-router";
3
+ import { useAui } from "@assistant-ui/react";
4
+ import { useStore } from "zustand";
5
+ import { citationStore } from "@iloveagents/foundry-agent";
6
+ import { useAGUIAdapter } from "../components/ag-ui-runtime-provider.js";
7
+ import { useToolPanelStore } from "./tool-panel-store.js";
8
+ import { useAppStore } from "./app-store.js";
9
+ import { useSidebarStore } from "./sidebar-store.js";
10
+ import { useChatLifecycleStore } from "./chat-lifecycle-store.js";
11
+ /**
12
+ * Shared hook for starting a new conversation.
13
+ * Used by ChatHeader and Sidebar to keep behavior in sync.
14
+ */
15
+ export function useNewConversation(options) {
16
+ const aui = useAui();
17
+ const { resetThread } = useAGUIAdapter();
18
+ const navigate = useNavigate();
19
+ const closePanel = useToolPanelStore((s) => s.closePanel);
20
+ const resetApp = useAppStore((s) => s.resetAll);
21
+ const closeMobile = useSidebarStore((s) => s.closeMobile);
22
+ const clearCitations = useStore(citationStore, (s) => s.clear);
23
+ return useCallback(() => {
24
+ const preserved = options?.preserveNavigation
25
+ ? {
26
+ currentPage: useAppStore.getState().currentPage,
27
+ navContext: useAppStore.getState().navContext,
28
+ }
29
+ : null;
30
+ closePanel();
31
+ resetApp();
32
+ if (preserved) {
33
+ useAppStore.setState(preserved);
34
+ }
35
+ closeMobile();
36
+ clearCitations();
37
+ // Notify the host app that a new thread is starting. Spaces wires
38
+ // this to clear its active-chat sticky id so the AGUIRuntimeProvider's
39
+ // ``effectiveThreadId`` advances to a freshly-minted UUID instead of
40
+ // staying pinned to the previous chat. Must fire BEFORE ``resetThread``
41
+ // so the next render's history adapter binds to the new id and
42
+ // doesn't re-hydrate the prior chat's messages — the exact bug this
43
+ // wiring fixes for the popover (``navigateToChat: false``) path,
44
+ // where there is no ``/`` navigation to clear sticky for us.
45
+ useChatLifecycleStore.getState().onNewConversation?.();
46
+ resetThread();
47
+ aui.threads().switchToNewThread();
48
+ if (options?.navigateToChat ?? true) {
49
+ navigate("/");
50
+ }
51
+ }, [
52
+ closePanel,
53
+ resetApp,
54
+ options?.preserveNavigation,
55
+ closeMobile,
56
+ clearCitations,
57
+ resetThread,
58
+ aui,
59
+ options?.navigateToChat,
60
+ navigate,
61
+ ]);
62
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * usePageTools — hook for pages to register client tools with the agent.
3
+ *
4
+ * Call this in any page component to declare tools available on that page.
5
+ * Tools are registered on mount and removed on unmount, so the agent
6
+ * only sees tools relevant to the current page.
7
+ *
8
+ * @example
9
+ * ```tsx
10
+ * function WorkspacePage() {
11
+ * usePageTools([
12
+ * {
13
+ * name: "submit_draft",
14
+ * description: "Submit the current draft for review",
15
+ * parameters: { type: "object", properties: {}, required: [] },
16
+ * execute: async () => {
17
+ * // ... submit logic
18
+ * return JSON.stringify({ status: "success" });
19
+ * },
20
+ * },
21
+ * ]);
22
+ * return <div>...</div>;
23
+ * }
24
+ * ```
25
+ */
26
+ import { type ClientToolEntry } from "@iloveagents/foundry-agent";
27
+ export declare function usePageTools(tools: ClientToolEntry[]): void;
@@ -23,18 +23,16 @@
23
23
  * }
24
24
  * ```
25
25
  */
26
-
27
26
  import { useEffect } from "react";
28
- import { clientToolRegistry, type ClientToolEntry } from "@iloveagents/foundry-agent";
29
-
30
- export function usePageTools(tools: ClientToolEntry[]) {
31
- useEffect(() => {
32
- clientToolRegistry.getState().registerPageTools(tools);
33
- return () => {
34
- clientToolRegistry.getState().clearPageTools();
35
- };
36
- // Registers once on mount, clears on unmount.
37
- // Tools array should be stable (defined outside the component or memoized).
38
- // eslint-disable-next-line react-hooks/exhaustive-deps
39
- }, []);
27
+ import { clientToolRegistry } from "@iloveagents/foundry-agent";
28
+ export function usePageTools(tools) {
29
+ useEffect(() => {
30
+ clientToolRegistry.getState().registerPageTools(tools);
31
+ return () => {
32
+ clientToolRegistry.getState().clearPageTools();
33
+ };
34
+ // Registers once on mount, clears on unmount.
35
+ // Tools array should be stable (defined outside the component or memoized).
36
+ // eslint-disable-next-line react-hooks/exhaustive-deps
37
+ }, []);
40
38
  }
@@ -0,0 +1,142 @@
1
+ @theme inline {
2
+ --radius-xs: calc(var(--radius) - 6px);
3
+ --radius-sm: calc(var(--radius) - 4px);
4
+ --radius-md: calc(var(--radius) - 2px);
5
+ --radius-lg: var(--radius);
6
+ --radius-xl: calc(var(--radius) + 4px);
7
+ --radius-2xl: calc(var(--radius) + 8px);
8
+ --radius-3xl: calc(var(--radius) + 14px);
9
+ --color-background: var(--background);
10
+ --color-foreground: var(--foreground);
11
+ --color-card: var(--card);
12
+ --color-card-foreground: var(--card-foreground);
13
+ --color-popover: var(--popover);
14
+ --color-popover-foreground: var(--popover-foreground);
15
+ --color-primary: var(--primary);
16
+ --color-primary-foreground: var(--primary-foreground);
17
+ --color-secondary: var(--secondary);
18
+ --color-secondary-foreground: var(--secondary-foreground);
19
+ --color-muted: var(--muted);
20
+ --color-muted-foreground: var(--muted-foreground);
21
+ --color-accent: var(--accent);
22
+ --color-accent-foreground: var(--accent-foreground);
23
+ --color-destructive: var(--destructive);
24
+ --color-destructive-foreground: var(--destructive-foreground);
25
+ --color-border: var(--border);
26
+ --color-input: var(--input);
27
+ --color-ring: var(--ring);
28
+ --color-sidebar: var(--sidebar);
29
+ --color-sidebar-foreground: var(--sidebar-foreground);
30
+ --color-sidebar-primary: var(--sidebar-primary);
31
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
32
+ --color-sidebar-accent: var(--sidebar-accent);
33
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
34
+ --color-sidebar-selected: var(--sidebar-selected);
35
+ --color-sidebar-selected-foreground: var(--sidebar-selected-foreground);
36
+ --color-sidebar-border: var(--sidebar-border);
37
+ --color-sidebar-ring: var(--sidebar-ring);
38
+ --color-success: var(--success);
39
+ --color-success-foreground: var(--success-foreground);
40
+ --color-warning: var(--warning);
41
+ --color-warning-foreground: var(--warning-foreground);
42
+ --color-info: var(--info);
43
+ --color-info-foreground: var(--info-foreground);
44
+ --color-chart-1: var(--chart-1);
45
+ --color-chart-2: var(--chart-2);
46
+ --color-chart-3: var(--chart-3);
47
+ --color-chart-4: var(--chart-4);
48
+ --color-chart-5: var(--chart-5);
49
+ --color-code-block: var(--code-block);
50
+ --color-code-block-foreground: var(--code-block-foreground);
51
+ }
52
+
53
+ :root {
54
+ --radius: 0.5rem;
55
+ --background: oklch(1 0 0);
56
+ --foreground: oklch(0.141 0.005 285.823);
57
+ --card: oklch(1 0 0);
58
+ --card-foreground: oklch(0.141 0.005 285.823);
59
+ --popover: oklch(1 0 0);
60
+ --popover-foreground: oklch(0.141 0.005 285.823);
61
+ --primary: oklch(0.6 0.18 280);
62
+ --primary-foreground: oklch(0.985 0 0);
63
+ --secondary: oklch(0.967 0.001 286.375);
64
+ --secondary-foreground: oklch(0.21 0.006 285.885);
65
+ --muted: oklch(0.967 0.001 286.375);
66
+ --muted-foreground: oklch(0.552 0.016 285.938);
67
+ --accent: oklch(0.967 0.001 286.375);
68
+ --accent-foreground: oklch(0.21 0.006 285.885);
69
+ --destructive: oklch(0.577 0.245 27.325);
70
+ --destructive-foreground: oklch(0.985 0 0);
71
+ --border: oklch(0.92 0.004 286.32);
72
+ --input: oklch(0.92 0.004 286.32);
73
+ --ring: oklch(0.705 0.015 286.067);
74
+ --sidebar: oklch(0.985 0 0);
75
+ --sidebar-foreground: oklch(0.141 0.005 285.823);
76
+ --sidebar-primary: oklch(0.6 0.18 280);
77
+ --sidebar-primary-foreground: oklch(0.985 0 0);
78
+ --sidebar-accent: oklch(0.967 0.001 286.375);
79
+ --sidebar-accent-foreground: oklch(0.21 0.006 285.885);
80
+ --sidebar-selected: var(--muted);
81
+ --sidebar-selected-foreground: var(--foreground);
82
+ --sidebar-border: oklch(0.92 0.004 286.32);
83
+ --sidebar-ring: oklch(0.705 0.015 286.067);
84
+ --success: oklch(0.58 0.16 155);
85
+ --success-foreground: oklch(1 0 0);
86
+ --warning: oklch(0.72 0.16 84);
87
+ --warning-foreground: oklch(0.3 0.05 84);
88
+ --info: var(--primary);
89
+ --info-foreground: var(--primary-foreground);
90
+ --chart-1: oklch(0.55 0.19 286);
91
+ --chart-2: oklch(0.56 0.15 240);
92
+ --chart-3: oklch(0.58 0.13 195);
93
+ --chart-4: oklch(0.7 0.16 84);
94
+ --chart-5: oklch(0.63 0.17 20);
95
+ --code-block: oklch(20% 0 0);
96
+ --code-block-foreground: oklch(93% 0 0);
97
+ }
98
+
99
+ .dark {
100
+ --background: oklch(0.141 0.005 285.823);
101
+ --foreground: oklch(0.985 0 0);
102
+ --card: oklch(0.21 0.006 285.885);
103
+ --card-foreground: oklch(0.985 0 0);
104
+ --popover: oklch(0.21 0.006 285.885);
105
+ --popover-foreground: oklch(0.985 0 0);
106
+ --primary: oklch(0.7 0.2 280);
107
+ --primary-foreground: oklch(0.21 0.006 285.885);
108
+ --secondary: oklch(0.274 0.006 286.033);
109
+ --secondary-foreground: oklch(0.985 0 0);
110
+ --muted: oklch(0.274 0.006 286.033);
111
+ --muted-foreground: oklch(0.705 0.015 286.067);
112
+ --accent: oklch(0.274 0.006 286.033);
113
+ --accent-foreground: oklch(0.985 0 0);
114
+ --destructive: oklch(0.704 0.191 22.216);
115
+ --destructive-foreground: oklch(0.985 0 0);
116
+ --border: oklch(1 0 0 / 10%);
117
+ --input: oklch(1 0 0 / 15%);
118
+ --ring: oklch(0.552 0.016 285.938);
119
+ --sidebar: oklch(0.21 0.006 285.885);
120
+ --sidebar-foreground: oklch(0.985 0 0);
121
+ --sidebar-primary: oklch(0.7 0.2 280);
122
+ --sidebar-primary-foreground: oklch(0.985 0 0);
123
+ --sidebar-accent: oklch(0.274 0.006 286.033);
124
+ --sidebar-accent-foreground: oklch(0.985 0 0);
125
+ --sidebar-selected: color-mix(in srgb, var(--muted) 78%, var(--background) 22%);
126
+ --sidebar-selected-foreground: var(--foreground);
127
+ --sidebar-border: oklch(1 0 0 / 10%);
128
+ --sidebar-ring: oklch(0.552 0.016 285.938);
129
+ --success: oklch(0.72 0.14 155);
130
+ --success-foreground: oklch(0.16 0.01 155);
131
+ --warning: oklch(0.72 0.13 84);
132
+ --warning-foreground: oklch(0.2 0.03 84);
133
+ --info: var(--primary);
134
+ --info-foreground: var(--primary-foreground);
135
+ --chart-1: oklch(0.72 0.17 286);
136
+ --chart-2: oklch(0.74 0.13 240);
137
+ --chart-3: oklch(0.76 0.12 195);
138
+ --chart-4: oklch(0.79 0.15 84);
139
+ --chart-5: oklch(0.74 0.14 20);
140
+ --code-block: oklch(0.16 0.01 286);
141
+ --code-block-foreground: oklch(0.9 0.01 286);
142
+ }
@@ -0,0 +1,5 @@
1
+ import * as CollapsiblePrimitive from "@radix-ui/react-collapsible";
2
+ declare const Collapsible: import("react").ForwardRefExoticComponent<CollapsiblePrimitive.CollapsibleProps & import("react").RefAttributes<HTMLDivElement>>;
3
+ declare const CollapsibleTrigger: import("react").ForwardRefExoticComponent<CollapsiblePrimitive.CollapsibleTriggerProps & import("react").RefAttributes<HTMLButtonElement>>;
4
+ declare const CollapsibleContent: import("react").ForwardRefExoticComponent<CollapsiblePrimitive.CollapsibleContentProps & import("react").RefAttributes<HTMLDivElement>>;
5
+ export { Collapsible, CollapsibleTrigger, CollapsibleContent };
@@ -1,7 +1,5 @@
1
1
  import * as CollapsiblePrimitive from "@radix-ui/react-collapsible";
2
-
3
2
  const Collapsible = CollapsiblePrimitive.Root;
4
3
  const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger;
5
4
  const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent;
6
-
7
5
  export { Collapsible, CollapsibleTrigger, CollapsibleContent };
@@ -0,0 +1,15 @@
1
+ import * as React from "react";
2
+ import * as DialogPrimitive from "@radix-ui/react-dialog";
3
+ declare const Dialog: React.FC<DialogPrimitive.DialogProps>;
4
+ declare const DialogTrigger: React.ForwardRefExoticComponent<DialogPrimitive.DialogTriggerProps & React.RefAttributes<HTMLButtonElement>>;
5
+ declare const DialogPortal: React.FC<DialogPrimitive.DialogPortalProps>;
6
+ declare const DialogClose: React.ForwardRefExoticComponent<DialogPrimitive.DialogCloseProps & React.RefAttributes<HTMLButtonElement>>;
7
+ declare const DialogOverlay: React.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogOverlayProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
8
+ declare const DialogContent: React.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogContentProps & React.RefAttributes<HTMLDivElement>, "ref"> & {
9
+ showCloseButton?: boolean;
10
+ } & React.RefAttributes<HTMLDivElement>>;
11
+ declare function DialogHeader({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): import("react/jsx-runtime").JSX.Element;
12
+ declare function DialogFooter({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): import("react/jsx-runtime").JSX.Element;
13
+ declare const DialogTitle: React.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogTitleProps & React.RefAttributes<HTMLHeadingElement>, "ref"> & React.RefAttributes<HTMLHeadingElement>>;
14
+ declare const DialogDescription: React.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogDescriptionProps & React.RefAttributes<HTMLParagraphElement>, "ref"> & React.RefAttributes<HTMLParagraphElement>>;
15
+ export { Dialog, DialogPortal, DialogOverlay, DialogTrigger, DialogClose, DialogContent, DialogHeader, DialogFooter, DialogTitle, DialogDescription, };
@@ -0,0 +1,25 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import * as DialogPrimitive from "@radix-ui/react-dialog";
4
+ import { X } from "lucide-react";
5
+ import { cn } from "@iloveagents/foundry-web-primitives";
6
+ import { ThemeScope } from "../components/theme-runtime-provider.js";
7
+ const Dialog = DialogPrimitive.Root;
8
+ const DialogTrigger = DialogPrimitive.Trigger;
9
+ const DialogPortal = DialogPrimitive.Portal;
10
+ const DialogClose = DialogPrimitive.Close;
11
+ const DialogOverlay = React.forwardRef(({ className, ...props }, ref) => (_jsx(DialogPrimitive.Overlay, { ref: ref, className: cn("fixed inset-0 z-50 bg-black/55 backdrop-blur-sm", "data-[state=open]:animate-in data-[state=closed]:animate-out", "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0", className), ...props })));
12
+ DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
13
+ const DialogContent = React.forwardRef(({ className, children, showCloseButton = true, ...props }, ref) => (_jsxs(DialogPortal, { children: [_jsx(DialogOverlay, {}), _jsxs(DialogPrimitive.Content, { ref: ref, className: cn("fixed left-1/2 top-1/2 z-50 grid w-[calc(100%-2rem)] max-w-lg -translate-x-1/2 -translate-y-1/2 gap-4", "rounded-[2rem] border border-border bg-background/95 p-6 shadow-2xl duration-200", "data-[state=open]:animate-in data-[state=closed]:animate-out", "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0", "data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95", className), ...props, children: [_jsx(ThemeScope, { style: { display: "contents" }, children: children }), showCloseButton ? (_jsx(DialogPrimitive.Close, { className: cn("absolute right-5 top-5 rounded-md p-1 transition-colors hover:bg-muted", "focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"), "aria-label": "Close", children: _jsx(X, { className: "size-4 text-muted-foreground" }) })) : null] })] })));
14
+ DialogContent.displayName = DialogPrimitive.Content.displayName;
15
+ function DialogHeader({ className, ...props }) {
16
+ return _jsx("div", { className: cn("flex flex-col gap-1.5 pr-10", className), ...props });
17
+ }
18
+ function DialogFooter({ className, ...props }) {
19
+ return _jsx("div", { className: cn("flex justify-end gap-2", className), ...props });
20
+ }
21
+ const DialogTitle = React.forwardRef(({ className, ...props }, ref) => (_jsx(DialogPrimitive.Title, { ref: ref, className: cn("text-lg font-semibold", className), ...props })));
22
+ DialogTitle.displayName = DialogPrimitive.Title.displayName;
23
+ const DialogDescription = React.forwardRef(({ className, ...props }, ref) => (_jsx(DialogPrimitive.Description, { ref: ref, className: cn("text-sm text-muted-foreground", className), ...props })));
24
+ DialogDescription.displayName = DialogPrimitive.Description.displayName;
25
+ export { Dialog, DialogPortal, DialogOverlay, DialogTrigger, DialogClose, DialogContent, DialogHeader, DialogFooter, DialogTitle, DialogDescription, };
@@ -0,0 +1,7 @@
1
+ import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
2
+ export declare const DropdownMenu: import("react").FC<DropdownMenuPrimitive.DropdownMenuProps>;
3
+ export declare const DropdownMenuTrigger: import("react").ForwardRefExoticComponent<DropdownMenuPrimitive.DropdownMenuTriggerProps & import("react").RefAttributes<HTMLButtonElement>>;
4
+ export declare const DropdownMenuContent: import("react").ForwardRefExoticComponent<Omit<DropdownMenuPrimitive.DropdownMenuContentProps & import("react").RefAttributes<HTMLDivElement>, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
5
+ export declare const DropdownMenuItem: import("react").ForwardRefExoticComponent<Omit<DropdownMenuPrimitive.DropdownMenuItemProps & import("react").RefAttributes<HTMLDivElement>, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
6
+ export declare const DropdownMenuSeparator: import("react").ForwardRefExoticComponent<Omit<DropdownMenuPrimitive.DropdownMenuSeparatorProps & import("react").RefAttributes<HTMLDivElement>, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
7
+ export declare const DropdownMenuLabel: import("react").ForwardRefExoticComponent<Omit<DropdownMenuPrimitive.DropdownMenuLabelProps & import("react").RefAttributes<HTMLDivElement>, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,19 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
3
+ import { forwardRef } from "react";
4
+ import { cn } from "@iloveagents/foundry-web-primitives";
5
+ export const DropdownMenu = DropdownMenuPrimitive.Root;
6
+ export const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
7
+ export const DropdownMenuContent = forwardRef(({ className, sideOffset = 4, ...props }, ref) => (_jsx(DropdownMenuPrimitive.Portal, { children: _jsx(DropdownMenuPrimitive.Content, { ref: ref, sideOffset: sideOffset, className: cn("z-50 min-w-[8rem] overflow-hidden rounded-md border border-border", "bg-popover p-1 text-popover-foreground shadow-md", "data-[state=open]:animate-in data-[state=closed]:animate-out", "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0", "data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95", "data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2", "data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2", className), ...props }) })));
8
+ DropdownMenuContent.displayName = "DropdownMenuContent";
9
+ export const DropdownMenuItem = forwardRef(({ className, ...props }, ref) => (_jsx(DropdownMenuPrimitive.Item, { ref: ref, className: cn(
10
+ // ``gap-2`` is the same icon-to-text spacing the framework's
11
+ // Button primitive uses, so a ``<lucide-icon /> Label`` pattern
12
+ // inside any menu item renders consistently everywhere without
13
+ // the consumer needing to remember the override.
14
+ "relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none", "transition-colors focus:bg-accent focus:text-accent-foreground", "data-[disabled]:pointer-events-none data-[disabled]:opacity-50", className), ...props })));
15
+ DropdownMenuItem.displayName = "DropdownMenuItem";
16
+ export const DropdownMenuSeparator = forwardRef(({ className, ...props }, ref) => (_jsx(DropdownMenuPrimitive.Separator, { ref: ref, className: cn("-mx-1 my-1 h-px bg-border", className), ...props })));
17
+ DropdownMenuSeparator.displayName = "DropdownMenuSeparator";
18
+ export const DropdownMenuLabel = forwardRef(({ className, ...props }, ref) => (_jsx(DropdownMenuPrimitive.Label, { ref: ref, className: cn("px-2 py-1.5 text-sm font-semibold", className), ...props })));
19
+ DropdownMenuLabel.displayName = "DropdownMenuLabel";
@@ -0,0 +1,7 @@
1
+ import * as React from "react";
2
+ import * as PopoverPrimitive from "@radix-ui/react-popover";
3
+ declare const Popover: React.FC<PopoverPrimitive.PopoverProps>;
4
+ declare const PopoverTrigger: React.ForwardRefExoticComponent<PopoverPrimitive.PopoverTriggerProps & React.RefAttributes<HTMLButtonElement>>;
5
+ declare const PopoverAnchor: React.ForwardRefExoticComponent<PopoverPrimitive.PopoverAnchorProps & React.RefAttributes<HTMLDivElement>>;
6
+ declare const PopoverContent: React.ForwardRefExoticComponent<Omit<PopoverPrimitive.PopoverContentProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
7
+ export { Popover, PopoverTrigger, PopoverAnchor, PopoverContent };
@@ -0,0 +1,10 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import * as PopoverPrimitive from "@radix-ui/react-popover";
4
+ import { cn } from "@iloveagents/foundry-web-primitives";
5
+ const Popover = PopoverPrimitive.Root;
6
+ const PopoverTrigger = PopoverPrimitive.Trigger;
7
+ const PopoverAnchor = PopoverPrimitive.Anchor;
8
+ const PopoverContent = React.forwardRef(({ className, align = "center", sideOffset = 8, ...props }, ref) => (_jsx(PopoverPrimitive.Portal, { children: _jsx(PopoverPrimitive.Content, { ref: ref, align: align, sideOffset: sideOffset, className: cn("z-50 rounded-2xl border border-border bg-popover p-3 text-popover-foreground shadow-xl outline-none", "data-[state=open]:animate-in data-[state=closed]:animate-out", "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0", "data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95", "data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2", "data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2", className), ...props }) })));
9
+ PopoverContent.displayName = PopoverPrimitive.Content.displayName;
10
+ export { Popover, PopoverTrigger, PopoverAnchor, PopoverContent };
@@ -0,0 +1,4 @@
1
+ import * as React from "react";
2
+ declare const selectClassName = "flex h-10 w-full rounded-xl border border-border bg-background px-3 py-2 text-sm outline-none transition focus:border-primary focus:ring-2 focus:ring-primary/15 disabled:cursor-not-allowed disabled:opacity-50";
3
+ declare const Select: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.SelectHTMLAttributes<HTMLSelectElement>, HTMLSelectElement>, "ref"> & React.RefAttributes<HTMLSelectElement>>;
4
+ export { Select, selectClassName };
@@ -0,0 +1,9 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import { cn } from "@iloveagents/foundry-web-primitives";
4
+ const selectClassName = "flex h-10 w-full rounded-xl border border-border bg-background px-3 py-2 text-sm outline-none transition focus:border-primary focus:ring-2 focus:ring-primary/15 disabled:cursor-not-allowed disabled:opacity-50";
5
+ const Select = React.forwardRef(({ className, ...props }, ref) => {
6
+ return _jsx("select", { ref: ref, className: cn(selectClassName, className), ...props });
7
+ });
8
+ Select.displayName = "Select";
9
+ export { Select, selectClassName };
@@ -0,0 +1,7 @@
1
+ import * as React from "react";
2
+ import * as TooltipPrimitive from "@radix-ui/react-tooltip";
3
+ declare const TooltipProvider: React.FC<TooltipPrimitive.TooltipProviderProps>;
4
+ declare const Tooltip: React.FC<TooltipPrimitive.TooltipProps>;
5
+ declare const TooltipTrigger: React.ForwardRefExoticComponent<TooltipPrimitive.TooltipTriggerProps & React.RefAttributes<HTMLButtonElement>>;
6
+ declare const TooltipContent: React.ForwardRefExoticComponent<Omit<TooltipPrimitive.TooltipContentProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
7
+ export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };
@@ -0,0 +1,10 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import * as TooltipPrimitive from "@radix-ui/react-tooltip";
4
+ import { cn } from "@iloveagents/foundry-web-primitives";
5
+ const TooltipProvider = TooltipPrimitive.Provider;
6
+ const Tooltip = TooltipPrimitive.Root;
7
+ const TooltipTrigger = TooltipPrimitive.Trigger;
8
+ const TooltipContent = React.forwardRef(({ className, sideOffset = 4, ...props }, ref) => (_jsx(TooltipPrimitive.Portal, { children: _jsx(TooltipPrimitive.Content, { ref: ref, sideOffset: sideOffset, className: cn("z-50 overflow-hidden rounded-md bg-primary px-3 py-1.5 text-xs text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2", className), ...props }) })));
9
+ TooltipContent.displayName = TooltipPrimitive.Content.displayName;
10
+ export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };
package/package.json CHANGED
@@ -1,13 +1,22 @@
1
1
  {
2
2
  "name": "@iloveagents/foundry-web-ui",
3
- "version": "0.3.0",
4
- "license": "SEE LICENSE IN LICENSE",
3
+ "version": "0.4.0",
4
+ "license": "MIT",
5
5
  "type": "module",
6
- "types": "./src/index.ts",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
7
8
  "exports": {
8
- ".": "./src/index.ts",
9
- "./styles.css": "./src/styles.css"
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ },
13
+ "./styles.css": "./dist/styles.css"
10
14
  },
15
+ "files": [
16
+ "dist",
17
+ "README.md",
18
+ "LICENSE"
19
+ ],
11
20
  "publishConfig": {
12
21
  "access": "public"
13
22
  },
@@ -16,7 +25,6 @@
16
25
  "react-dom": "^19.0.0",
17
26
  "react-router": "^7.0.0",
18
27
  "@assistant-ui/react": "^0.12.25",
19
- "@assistant-ui/react-markdown": "^0.12.9",
20
28
  "@ag-ui/client": "^0.0.52",
21
29
  "@ag-ui/core": "^0.0.52",
22
30
  "zustand": "^5.0.0",
@@ -45,17 +53,28 @@
45
53
  "tailwind-merge": "^3.5.0",
46
54
  "react-markdown": "^10.0.0",
47
55
  "remark-gfm": "^4.0.0",
48
- "shiki": "^4.0.0",
49
- "@iloveagents/foundry-agent": "0.3.0",
50
- "@iloveagents/foundry-web-primitives": "0.3.0"
56
+ "@iloveagents/foundry-agent": "^0.4.0",
57
+ "@iloveagents/foundry-web-primitives": "^0.4.0"
51
58
  },
52
59
  "devDependencies": {
53
- "typescript": "~5.9.3",
60
+ "@ag-ui/client": "^0.0.52",
61
+ "@ag-ui/core": "^0.0.52",
62
+ "@assistant-ui/react": "^0.12.25",
63
+ "@azure/msal-browser": "^5.0.0",
64
+ "@azure/msal-react": "^5.0.0",
54
65
  "@types/react": "^19.2.2",
66
+ "jsdom": "^28.1.0",
67
+ "lucide-react": ">=0.400.0",
68
+ "react": "^19.0.0",
69
+ "react-dom": "^19.0.0",
70
+ "react-router": "^7.0.0",
71
+ "typescript": "~5.9.3",
55
72
  "vitest": "^4.1.4",
56
- "jsdom": "^28.1.0"
73
+ "zustand": "^5.0.0"
57
74
  },
58
75
  "scripts": {
59
- "test:unit": "vitest run"
76
+ "build": "tsc -p tsconfig.build.json && node ../../scripts/fix-dts-extensions.mjs dist && cp src/styles.css dist/styles.css",
77
+ "test:unit": "vitest run",
78
+ "typecheck": "tsc --noEmit"
60
79
  }
61
80
  }
package/AGENTS.md DELETED
@@ -1,59 +0,0 @@
1
- React UI core for the AG-UI protocol starter — hooks, stores, extension-point registries, assistant-ui adapter shim, ChatPanel, sidebar, layout components. Published as `@iloveagents/foundry-web-ui`.
2
-
3
- Depends on `@iloveagents/foundry-web-primitives` (leaf primitives) and `@iloveagents/foundry-agent` (cross-runtime agent transport: AG-UI runner, vanilla stores, MSAL subpath, service-fetch factory).
4
-
5
- # Architecture
6
-
7
- Relative imports only (no `@/` alias). Cross-package consumers use `@iloveagents/foundry-web-ui`.
8
-
9
- ```
10
- src/
11
- components/ ← UI components (sidebar, chat, tool-panel, markdown, etc.)
12
- lib/ ← React-coupled stores, the assistant-ui adapter shim,
13
- the React MSAL provider, hooks, utilities.
14
- ui/ ← shadcn/radix primitives (tooltip, collapsible, dropdown, dialog, popover, select)
15
- index.ts ← barrel export (all public API)
16
- ```
17
-
18
- # Import Boundary (enforced by guard test)
19
-
20
- - MUST NOT import from `@lastspace/spaces-web-ui`
21
- - MUST NOT use `@/` path aliases (relative imports only)
22
- - MUST NOT import from `features/` or `pages/` (those are app-level)
23
- - Cross-runtime transport (AG-UI runner, registry, vanilla stores, MSAL token store) lives in `@iloveagents/foundry-agent`. Re-exporting it from this package is forbidden by the no-shim rule (#90/#95).
24
-
25
- # Extension Points
26
-
27
- SPACES and other feature modules plug in via these registries:
28
-
29
- - **NavItem.dnd** (`nav-config.ts`): drag-and-drop behavior on sidebar items
30
- - **NavItem.dimmed / NavItem.badge** (`nav-config.ts`): visual modifiers on sidebar items
31
- - **NavGroupCreateAction** (`nav-config.ts`): "+ New" actions on nav group headers
32
- - **NavGroup.collapsedRail** (`nav-config.ts`): module-supplied renderer for the collapsed sidebar rail. Used when a group's collapsed view isn't a flat icon list — e.g. Spaces' "header link + active workspace's root".
33
- - **NavFooterAction** (`nav-store.ts`): action buttons in the sidebar footer
34
- - **Panel renderer registry** (`tool-panel-store.ts`): custom content renderers for the side panel (PDF, entity pages)
35
- - **Citation handler** (`citationStore` in `@iloveagents/foundry-agent`): handles `[n]` citation clicks in markdown
36
- - **Tool UI** (via `makeAssistantToolUI` from `@assistant-ui/react`): custom rendering for agent tools
37
-
38
- # Adding Extension Points
39
-
40
- 1. Define interface in the relevant store (e.g., `PanelRendererEntry`)
41
- 2. Add registry array + register function to the store
42
- 3. Component reads from registry and delegates rendering
43
- 4. Feature module calls `registerX()` at init time
44
-
45
- # AG-UI Adapter
46
-
47
- - This package ships an `AGUIAdapterSDK` shim (`src/lib/ag-ui-adapter.ts`) that implements assistant-ui's `ChatModelAdapter` by wrapping `AGUIRunner` from `@iloveagents/foundry-agent`. The runner does the protocol; the shim translates `RunnerEvent`s into cumulative `ChatModelRunResult` yields.
48
- - `@assistant-ui/react` must stay on **0.12.x or newer** — 0.11.x has a `_getInitializePromise` runtime regression.
49
- - Tool UIs use `makeAssistantToolUI(...)` (the v0.12 canonical pattern). The legacy `useAssistantToolUI` hook is no longer used.
50
- - Hook renames per v0.12: `useAssistantApi → useAui`, `useAssistantState → useAuiState`, `useAssistantEvent → useAuiEvent`.
51
-
52
- # Client-Side Tools
53
-
54
- Tools live in `clientToolRegistry` (vanilla zustand store in `@iloveagents/foundry-agent`). The runner sends schemas to the backend, intercepts `TOOL_CALL_END` for any client-side tool, executes it locally, and replays the assistant + tool messages on the next turn with the same `toolCallId`.
55
-
56
- - **`ui_*`** — global tools registered at app init in `lib/client-tools.ts` (`ui_navigate`, `ui_set_theme`, `ui_open_panel`, `ui_select_item`, `ui_update_content`, `ui_highlight`, `ui_get_context`, `ui_confirm`).
57
- - **`page_*`** — page-specific tools registered via `usePageTools([{ name, description, parameters, execute }])`.
58
-
59
- Custom tool UIs are top-level `makeAssistantToolUI(...)` constants rendered as children inside the `AssistantRuntimeProvider` tree (see `client-tool-executor.tsx`).