@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
@@ -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
- }));