@iloveagents/foundry-web-ui 0.3.1 → 0.5.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 (227) hide show
  1. package/README.md +13 -4
  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 +94 -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 +105 -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 +13 -0
  51. package/dist/components/loading-indicator.js +35 -0
  52. package/dist/components/markdown-text.d.ts +13 -0
  53. package/dist/components/markdown-text.js +221 -0
  54. package/dist/components/message-error.d.ts +10 -0
  55. package/dist/components/message-error.js +10 -0
  56. package/dist/components/message-timestamp.d.ts +10 -0
  57. package/dist/components/message-timestamp.js +18 -0
  58. package/dist/components/name-dialog.d.ts +16 -0
  59. package/dist/components/name-dialog.js +23 -0
  60. package/dist/components/selection-popover.d.ts +12 -0
  61. package/dist/components/selection-popover.js +111 -0
  62. package/dist/components/show-document-tool-ui.d.ts +1 -0
  63. package/dist/components/show-document-tool-ui.js +53 -0
  64. package/dist/components/sidebar.d.ts +4 -0
  65. package/dist/components/sidebar.js +904 -0
  66. package/dist/components/surface-card.d.ts +9 -0
  67. package/dist/components/surface-card.js +33 -0
  68. package/dist/components/theme-runtime-provider.d.ts +15 -0
  69. package/dist/components/theme-runtime-provider.js +48 -0
  70. package/dist/components/theme-toggle.d.ts +2 -0
  71. package/dist/components/theme-toggle.js +19 -0
  72. package/dist/components/tool-call-card.d.ts +27 -0
  73. package/dist/components/tool-call-card.js +13 -0
  74. package/dist/components/tool-fallback.d.ts +26 -0
  75. package/dist/components/tool-fallback.js +129 -0
  76. package/dist/components/tool-panel-layout.d.ts +10 -0
  77. package/dist/components/tool-panel-layout.js +12 -0
  78. package/dist/components/tool-panel.d.ts +1 -0
  79. package/dist/components/tool-panel.js +89 -0
  80. package/dist/components/tooltip-icon-button.d.ts +7 -0
  81. package/dist/components/tooltip-icon-button.js +9 -0
  82. package/dist/components/user-menu.d.ts +2 -0
  83. package/dist/components/user-menu.js +14 -0
  84. package/dist/index.d.ts +68 -0
  85. package/dist/index.js +83 -0
  86. package/dist/lib/ag-ui-adapter.d.ts +29 -0
  87. package/dist/lib/ag-ui-adapter.js +382 -0
  88. package/dist/lib/app-store.d.ts +115 -0
  89. package/dist/lib/app-store.js +199 -0
  90. package/dist/lib/attachment-adapter.d.ts +20 -0
  91. package/dist/lib/attachment-adapter.js +99 -0
  92. package/dist/lib/auth-provider.d.ts +16 -0
  93. package/dist/lib/auth-provider.js +88 -0
  94. package/dist/lib/chat-bubble-store.d.ts +30 -0
  95. package/dist/lib/chat-bubble-store.js +23 -0
  96. package/dist/lib/chat-lifecycle-store.d.ts +10 -0
  97. package/{src/lib/chat-lifecycle-store.ts → dist/lib/chat-lifecycle-store.js} +3 -13
  98. package/dist/lib/client-tools.d.ts +11 -0
  99. package/dist/lib/client-tools.js +274 -0
  100. package/dist/lib/composer-submit-store.d.ts +12 -0
  101. package/dist/lib/composer-submit-store.js +17 -0
  102. package/dist/lib/dev-store.d.ts +38 -0
  103. package/dist/lib/dev-store.js +32 -0
  104. package/dist/lib/nav-config.d.ts +159 -0
  105. package/dist/lib/nav-config.js +162 -0
  106. package/dist/lib/nav-dnd.d.ts +8 -0
  107. package/dist/lib/nav-dnd.js +9 -0
  108. package/dist/lib/nav-store.d.ts +45 -0
  109. package/dist/lib/nav-store.js +49 -0
  110. package/dist/lib/selection-context.d.ts +21 -0
  111. package/dist/lib/selection-context.js +34 -0
  112. package/dist/lib/sidebar-store.d.ts +23 -0
  113. package/dist/lib/sidebar-store.js +98 -0
  114. package/dist/lib/theme-runtime.d.ts +130 -0
  115. package/dist/lib/theme-runtime.js +479 -0
  116. package/dist/lib/theme-store.d.ts +15 -0
  117. package/dist/lib/theme-store.js +53 -0
  118. package/dist/lib/tool-panel-store.d.ts +48 -0
  119. package/dist/lib/tool-panel-store.js +69 -0
  120. package/dist/lib/use-new-conversation.d.ts +8 -0
  121. package/dist/lib/use-new-conversation.js +62 -0
  122. package/dist/lib/use-page-tools.d.ts +27 -0
  123. package/{src/lib/use-page-tools.ts → dist/lib/use-page-tools.js} +11 -13
  124. package/dist/styles.css +142 -0
  125. package/dist/ui/collapsible.d.ts +5 -0
  126. package/{src/ui/collapsible.tsx → dist/ui/collapsible.js} +0 -2
  127. package/dist/ui/dialog.d.ts +15 -0
  128. package/dist/ui/dialog.js +25 -0
  129. package/dist/ui/dropdown-menu.d.ts +7 -0
  130. package/dist/ui/dropdown-menu.js +19 -0
  131. package/dist/ui/popover.d.ts +7 -0
  132. package/dist/ui/popover.js +10 -0
  133. package/dist/ui/select.d.ts +4 -0
  134. package/dist/ui/select.js +9 -0
  135. package/dist/ui/tooltip.d.ts +7 -0
  136. package/dist/ui/tooltip.js +10 -0
  137. package/package.json +31 -12
  138. package/AGENTS.md +0 -59
  139. package/CHANGELOG.md +0 -211
  140. package/CLAUDE.md +0 -1
  141. package/src/__tests__/no-spaces-imports.test.ts +0 -59
  142. package/src/__tests__/open-core-guards.test.ts +0 -307
  143. package/src/__tests__/theme-runtime.test.ts +0 -81
  144. package/src/__tests__/tool-fallback.test.tsx +0 -109
  145. package/src/components/__tests__/context-bar.test.ts +0 -112
  146. package/src/components/ag-ui-runtime-provider.tsx +0 -170
  147. package/src/components/app-brand.tsx +0 -38
  148. package/src/components/assistant-chat.tsx +0 -461
  149. package/src/components/chat-attachments.tsx +0 -68
  150. package/src/components/chat-bubble.tsx +0 -373
  151. package/src/components/chat-header.tsx +0 -44
  152. package/src/components/client-tool-executor.tsx +0 -230
  153. package/src/components/collection-empty-state.tsx +0 -37
  154. package/src/components/collection-filter-bar.tsx +0 -168
  155. package/src/components/collection-search-input.tsx +0 -41
  156. package/src/components/collection-skeleton.tsx +0 -55
  157. package/src/components/collection-sort-menu.tsx +0 -62
  158. package/src/components/collection-surface.tsx +0 -46
  159. package/src/components/collection-toolbar.tsx +0 -33
  160. package/src/components/collection-view-toggle.tsx +0 -61
  161. package/src/components/composer-submit-bridge.tsx +0 -19
  162. package/src/components/confirm-dialog.tsx +0 -49
  163. package/src/components/confirmation-card.tsx +0 -32
  164. package/src/components/context-badges.tsx +0 -136
  165. package/src/components/context-bar.tsx +0 -238
  166. package/src/components/form-dialog.tsx +0 -56
  167. package/src/components/global-selection-popover.tsx +0 -266
  168. package/src/components/infinite-scroll-sentinel.tsx +0 -48
  169. package/src/components/json-viewer.tsx +0 -232
  170. package/src/components/loading-indicator.tsx +0 -40
  171. package/src/components/markdown-text-citations.test.tsx +0 -108
  172. package/src/components/markdown-text.tsx +0 -508
  173. package/src/components/name-dialog.tsx +0 -87
  174. package/src/components/selection-popover.tsx +0 -156
  175. package/src/components/show-document-tool-ui.tsx +0 -90
  176. package/src/components/sidebar.test.tsx +0 -611
  177. package/src/components/sidebar.tsx +0 -1689
  178. package/src/components/surface-card.tsx +0 -45
  179. package/src/components/theme-runtime-provider.tsx +0 -93
  180. package/src/components/theme-toggle.tsx +0 -27
  181. package/src/components/tool-call-card.tsx +0 -126
  182. package/src/components/tool-fallback.tsx +0 -169
  183. package/src/components/tool-panel-layout.tsx +0 -36
  184. package/src/components/tool-panel.tsx +0 -233
  185. package/src/components/tooltip-icon-button.tsx +0 -28
  186. package/src/components/user-menu.tsx +0 -60
  187. package/src/index.ts +0 -185
  188. package/src/lib/__tests__/ag-ui-adapter.test.ts +0 -279
  189. package/src/lib/__tests__/app-store.test.ts +0 -405
  190. package/src/lib/__tests__/attachment-adapter.test.ts +0 -48
  191. package/src/lib/__tests__/chat-bubble-store.test.ts +0 -67
  192. package/src/lib/__tests__/client-tools.test.ts +0 -124
  193. package/src/lib/__tests__/dev-store.test.ts +0 -78
  194. package/src/lib/__tests__/nav-config.test.ts +0 -135
  195. package/src/lib/__tests__/nav-dnd.test.ts +0 -24
  196. package/src/lib/__tests__/nav-store.test.ts +0 -59
  197. package/src/lib/__tests__/selection-context.test.ts +0 -114
  198. package/src/lib/__tests__/sidebar-store.test.ts +0 -144
  199. package/src/lib/__tests__/theme-store.test.ts +0 -83
  200. package/src/lib/__tests__/tool-panel-store.test.ts +0 -61
  201. package/src/lib/__tests__/use-page-context.test.ts +0 -58
  202. package/src/lib/ag-ui-adapter.ts +0 -426
  203. package/src/lib/app-store.ts +0 -361
  204. package/src/lib/attachment-adapter.ts +0 -92
  205. package/src/lib/auth-provider.tsx +0 -144
  206. package/src/lib/chat-bubble-store.ts +0 -46
  207. package/src/lib/client-tools.ts +0 -293
  208. package/src/lib/composer-submit-store.ts +0 -32
  209. package/src/lib/dev-store.ts +0 -69
  210. package/src/lib/nav-config.ts +0 -329
  211. package/src/lib/nav-dnd.ts +0 -14
  212. package/src/lib/nav-store.ts +0 -89
  213. package/src/lib/selection-context.ts +0 -65
  214. package/src/lib/sidebar-store.ts +0 -113
  215. package/src/lib/theme-runtime.ts +0 -660
  216. package/src/lib/theme-store.ts +0 -67
  217. package/src/lib/tool-panel-store.ts +0 -121
  218. package/src/lib/use-new-conversation.test.tsx +0 -168
  219. package/src/lib/use-new-conversation.ts +0 -64
  220. package/src/ui/dialog.tsx +0 -109
  221. package/src/ui/dropdown-menu.tsx +0 -75
  222. package/src/ui/popover.tsx +0 -34
  223. package/src/ui/select.tsx +0 -15
  224. package/src/ui/tooltip.tsx +0 -30
  225. package/src/vite-env.d.ts +0 -1
  226. package/tsconfig.json +0 -16
  227. package/vitest.config.ts +0 -8
@@ -1,293 +0,0 @@
1
- /**
2
- * Global Client Tools — registered into the dynamic tool registry at app init.
3
- *
4
- * Naming convention:
5
- * ui_* — tools that affect the UI (navigate, theme, panel, content)
6
- *
7
- * Page-specific tools use their own prefix (e.g., page_search_documents).
8
- * The adapter reads from the registry (not this file) on every request.
9
- */
10
-
11
- import { useThemeStore, type ThemeMode } from "./theme-store.ts";
12
- import { useToolPanelStore } from "./tool-panel-store.ts";
13
- import { useAppStore } from "./app-store.ts";
14
- import { clientToolRegistry, type ClientToolEntry } from "@iloveagents/foundry-agent";
15
-
16
- // ---------------------------------------------------------------------------
17
- // Navigate function injection (needs React Router context)
18
- // ---------------------------------------------------------------------------
19
-
20
- let _navigateFn: ((path: string) => void) | null = null;
21
-
22
- export function setNavigateFunction(fn: (path: string) => void) {
23
- _navigateFn = fn;
24
- }
25
-
26
- // ---------------------------------------------------------------------------
27
- // Global tool definitions with executors
28
- // ---------------------------------------------------------------------------
29
-
30
- const GLOBAL_TOOLS: ClientToolEntry[] = [
31
- {
32
- name: "ui_navigate",
33
- description:
34
- "Navigate the user to a different page in the application. " +
35
- "Only use when the user explicitly asks to go to a page.",
36
- parameters: {
37
- type: "object",
38
- properties: {
39
- path: {
40
- type: "string",
41
- description: "The path to navigate to (e.g. '/workspace')",
42
- },
43
- },
44
- required: ["path"],
45
- },
46
- execute: async (argsJson) => {
47
- const { path } = JSON.parse(argsJson || "{}");
48
- if (_navigateFn) _navigateFn(path);
49
- return JSON.stringify({ status: "success", path });
50
- },
51
- },
52
- {
53
- name: "ui_set_theme",
54
- description: "Change the application theme. Modes: 'light', 'dark', or 'system'.",
55
- parameters: {
56
- type: "object",
57
- properties: {
58
- mode: {
59
- type: "string",
60
- enum: ["light", "dark", "system"],
61
- description: "The theme mode to apply",
62
- },
63
- },
64
- required: ["mode"],
65
- },
66
- execute: async (argsJson) => {
67
- const { mode } = JSON.parse(argsJson || "{}");
68
- useThemeStore.getState().setMode(mode as ThemeMode);
69
- return JSON.stringify({ status: "success", mode });
70
- },
71
- },
72
- {
73
- name: "ui_open_panel",
74
- description:
75
- "Show content in the side panel. Prefer this over ui_navigate to keep " +
76
- "chat visible. Use path for a page component (e.g. '/workspace'), " +
77
- "or content for generated markdown/text.",
78
- parameters: {
79
- type: "object",
80
- properties: {
81
- title: { type: "string", description: "Panel title" },
82
- path: {
83
- type: "string",
84
- description: "Page path to render in the panel (e.g. '/workspace')",
85
- },
86
- content: {
87
- type: "string",
88
- description: "Markdown or text content (used when path is not provided)",
89
- },
90
- type: {
91
- type: "string",
92
- enum: ["markdown", "text"],
93
- description: "Content format (default: markdown)",
94
- },
95
- },
96
- required: ["title"],
97
- },
98
- execute: async (argsJson) => {
99
- const args = JSON.parse(argsJson || "{}");
100
- if (args.path) {
101
- useToolPanelStore.getState().openPanel({
102
- title: args.title,
103
- content: args.path,
104
- type: "page",
105
- });
106
- } else {
107
- useToolPanelStore.getState().openPanel({
108
- title: args.title,
109
- content: args.content || "",
110
- type: args.type || "markdown",
111
- });
112
- }
113
- return JSON.stringify({
114
- status: "success",
115
- title: args.title,
116
- mode: args.path ? "page" : "content",
117
- });
118
- },
119
- },
120
- {
121
- name: "ui_select_item",
122
- description: "Select an item in the current page by its ID. Highlights it in the UI.",
123
- parameters: {
124
- type: "object",
125
- properties: {
126
- itemId: {
127
- type: "string",
128
- description: "The ID of the item to select (or null to deselect)",
129
- },
130
- },
131
- required: ["itemId"],
132
- },
133
- execute: async (argsJson) => {
134
- const { itemId } = JSON.parse(argsJson || "{}");
135
- useAppStore.getState().setSelectedItemId(itemId ?? null);
136
- return JSON.stringify({ status: "success", itemId });
137
- },
138
- },
139
- {
140
- name: "ui_update_content",
141
- description:
142
- "Update fields in the shared draft/form. Pass all fields as key-value " +
143
- "pairs in a single call. Works for one or many fields.",
144
- parameters: {
145
- type: "object",
146
- properties: {
147
- fields: {
148
- type: "object",
149
- description: "Key-value pairs of field names and their values",
150
- additionalProperties: true,
151
- },
152
- },
153
- required: ["fields"],
154
- },
155
- execute: async (argsJson) => {
156
- const { fields } = JSON.parse(argsJson || "{}");
157
- const store = useAppStore.getState();
158
- for (const [key, value] of Object.entries(fields)) {
159
- store.updateContentField(key, value);
160
- }
161
- return JSON.stringify({ status: "success", fields });
162
- },
163
- },
164
- {
165
- name: "ui_highlight",
166
- description: "Highlight an entity in the UI to draw the user's attention.",
167
- parameters: {
168
- type: "object",
169
- properties: {
170
- entityId: {
171
- type: "string",
172
- description: "The ID of the entity to highlight",
173
- },
174
- },
175
- required: ["entityId"],
176
- },
177
- execute: async (argsJson) => {
178
- const { entityId } = JSON.parse(argsJson || "{}");
179
- useAppStore.getState().addHighlight(entityId);
180
- return JSON.stringify({ status: "success", entityId });
181
- },
182
- },
183
- {
184
- name: "ui_confirm",
185
- description:
186
- "Ask the user to confirm or reject an action before proceeding. " +
187
- "Use for destructive or important actions.",
188
- parameters: {
189
- type: "object",
190
- properties: {
191
- action: {
192
- type: "string",
193
- description: "Short description of the action requiring confirmation",
194
- },
195
- details: {
196
- type: "string",
197
- description: "Optional details about what will happen",
198
- },
199
- },
200
- required: ["action"],
201
- },
202
- execute: async (argsJson) => {
203
- const { action, details } = JSON.parse(argsJson || "{}");
204
- return JSON.stringify({
205
- status: "pending",
206
- action,
207
- details: details || "",
208
- message: "Awaiting user confirmation via chat.",
209
- });
210
- },
211
- },
212
- {
213
- name: "ui_get_context",
214
- description:
215
- "Get the full application context: navigation breadcrumb from root " +
216
- "to current page (with accumulated metadata), selected items, draft " +
217
- "values, highlights, and user-pinned context items.",
218
- parameters: { type: "object", properties: {}, required: [] },
219
- execute: async () => {
220
- const state = useAppStore.getState().getAgentState();
221
- const { useNavStore } = await import("./nav-store.ts");
222
- const navConfig = useNavStore.getState().config;
223
-
224
- // Build breadcrumb: root group → parent item → current leaf
225
- const breadcrumb: Array<{
226
- level: string;
227
- label: string;
228
- description?: string;
229
- meta?: Record<string, unknown>;
230
- }> = [];
231
-
232
- for (const group of navConfig) {
233
- for (const item of group.items) {
234
- if (item.to === state.navigation.page) {
235
- breadcrumb.push({ level: "group", label: group.label, meta: group.meta });
236
- breadcrumb.push({
237
- level: "page",
238
- label: item.label,
239
- description: item.description,
240
- meta: item.meta,
241
- });
242
- break;
243
- }
244
- if (item.children) {
245
- for (const child of item.children) {
246
- if (child.to === state.navigation.page) {
247
- breadcrumb.push({ level: "group", label: group.label, meta: group.meta });
248
- breadcrumb.push({
249
- level: "parent",
250
- label: item.label,
251
- description: item.description,
252
- meta: item.meta,
253
- });
254
- breadcrumb.push({
255
- level: "page",
256
- label: child.label,
257
- description: child.description,
258
- meta: child.meta,
259
- });
260
- break;
261
- }
262
- }
263
- }
264
- }
265
- if (breadcrumb.length > 0) break;
266
- }
267
-
268
- return JSON.stringify({
269
- status: "success",
270
- breadcrumb,
271
- currentPage: state.navigation,
272
- selectedItemId: state.selectedItemId,
273
- content: state.content,
274
- highlights: state.highlights,
275
- contextItems: state.contextItems,
276
- });
277
- },
278
- },
279
- ];
280
-
281
- // ---------------------------------------------------------------------------
282
- // Registration — called once at module load
283
- // ---------------------------------------------------------------------------
284
-
285
- export function registerGlobalTools() {
286
- const registry = clientToolRegistry.getState();
287
- for (const tool of GLOBAL_TOOLS) {
288
- registry.registerGlobal(tool);
289
- }
290
- }
291
-
292
- // Auto-register on import
293
- registerGlobalTools();
@@ -1,32 +0,0 @@
1
- import { create } from "zustand";
2
-
3
- interface PendingComposerSubmit {
4
- id: number;
5
- text: string;
6
- }
7
-
8
- interface ComposerSubmitState {
9
- pending: PendingComposerSubmit | null;
10
- submit: (text: string) => void;
11
- consume: (id: number) => void;
12
- }
13
-
14
- let nextSubmitId = 1;
15
-
16
- export const useComposerSubmitStore = create<ComposerSubmitState>((set) => ({
17
- pending: null,
18
- submit: (text) => {
19
- const trimmed = text.trim();
20
- if (!trimmed) return;
21
- set({ pending: { id: nextSubmitId++, text: trimmed } });
22
- },
23
- consume: (id) =>
24
- set((state) => ({
25
- pending: state.pending?.id === id ? null : state.pending,
26
- })),
27
- }));
28
-
29
- export function submitComposerText(text: string): void {
30
- useComposerSubmitStore.getState().submit(text);
31
- }
32
-
@@ -1,69 +0,0 @@
1
- /**
2
- * Dev Store — captures debug telemetry for the Dev Panel.
3
- *
4
- * Only populated in dev mode. Stores the last AG-UI request payload
5
- * and tool call events so developers can inspect the full agent turn.
6
- */
7
-
8
- import { create } from "zustand";
9
-
10
- export interface DevToolCall {
11
- id: string;
12
- name: string;
13
- args: string;
14
- result?: unknown;
15
- isClientSide: boolean;
16
- timestamp: number;
17
- }
18
-
19
- interface DevState {
20
- /** Last AG-UI request payload (runInput) */
21
- lastRequest: Record<string, unknown> | null;
22
- /** Timestamp of last request */
23
- lastRequestAt: number | null;
24
- /** Tool calls from the current/last turn */
25
- toolCalls: DevToolCall[];
26
- /** SSE events log (last N) */
27
- events: Array<{ type: string; timestamp: number; data?: string }>;
28
-
29
- /** Capture a request payload (resets tool calls for new turn) */
30
- captureRequest: (payload: Record<string, unknown>) => void;
31
- /** Record a tool call */
32
- addToolCall: (call: DevToolCall) => void;
33
- /** Update a tool call with args and/or result */
34
- updateToolCall: (id: string, update: Partial<Pick<DevToolCall, "args" | "result">>) => void;
35
- /** Log an SSE event */
36
- logEvent: (type: string, data?: string) => void;
37
- }
38
-
39
- const MAX_EVENTS = 50;
40
-
41
- export const useDevStore = create<DevState>((set, get) => ({
42
- lastRequest: null,
43
- lastRequestAt: null,
44
- toolCalls: [],
45
- events: [],
46
-
47
- captureRequest: (payload) => {
48
- const isFollowUp = get().toolCalls.length > 0;
49
- set({
50
- lastRequest: payload,
51
- lastRequestAt: Date.now(),
52
- // Keep tool calls for follow-up requests (multi-turn), reset on fresh turn
53
- ...(isFollowUp ? {} : { toolCalls: [], events: [] }),
54
- });
55
- },
56
-
57
- addToolCall: (call) => set({ toolCalls: [...get().toolCalls, call] }),
58
-
59
- updateToolCall: (id, update) =>
60
- set({
61
- toolCalls: get().toolCalls.map((tc) => (tc.id === id ? { ...tc, ...update } : tc)),
62
- }),
63
-
64
- logEvent: (type, data) => {
65
- const events = get().events;
66
- const next = [...events, { type, timestamp: Date.now(), data }];
67
- set({ events: next.length > MAX_EVENTS ? next.slice(-MAX_EVENTS) : next });
68
- },
69
- }));