udi-yac 0.1.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 (102) hide show
  1. package/README.md +373 -0
  2. package/dist/app/ErrorBoundary.d.ts +18 -0
  3. package/dist/app/UDIChat.d.ts +3 -0
  4. package/dist/app/UDIChatConfig.d.ts +23 -0
  5. package/dist/app/UDIChatContext.d.ts +26 -0
  6. package/dist/app/validateConfig.d.ts +14 -0
  7. package/dist/app/validateConfig.test.d.ts +1 -0
  8. package/dist/assets/domainWorker-Cd9KoNXV.js +16 -0
  9. package/dist/ce-entry-C4ngOj0B.js +42577 -0
  10. package/dist/components/ui/badge.d.ts +7 -0
  11. package/dist/components/ui/button.d.ts +8 -0
  12. package/dist/components/ui/card.d.ts +11 -0
  13. package/dist/components/ui/checkbox.d.ts +3 -0
  14. package/dist/components/ui/dialog.d.ts +17 -0
  15. package/dist/components/ui/dropdown-menu.d.ts +29 -0
  16. package/dist/components/ui/input.d.ts +3 -0
  17. package/dist/components/ui/label.d.ts +3 -0
  18. package/dist/components/ui/scroll-area.d.ts +4 -0
  19. package/dist/components/ui/select.d.ts +15 -0
  20. package/dist/components/ui/separator.d.ts +3 -0
  21. package/dist/components/ui/slider.d.ts +3 -0
  22. package/dist/components/ui/switch.d.ts +5 -0
  23. package/dist/components/ui/tabs.d.ts +10 -0
  24. package/dist/components/ui/textarea.d.ts +3 -0
  25. package/dist/components/ui/tooltip.d.ts +6 -0
  26. package/dist/data/hubmap_2025-05-05/datapackage_udi.json +19606 -0
  27. package/dist/data/hubmap_2025-05-05/datasets.csv +6324 -0
  28. package/dist/data/hubmap_2025-05-05/datasets.tsv +6324 -0
  29. package/dist/data/hubmap_2025-05-05/donors.csv +433 -0
  30. package/dist/data/hubmap_2025-05-05/donors.tsv +433 -0
  31. package/dist/data/hubmap_2025-05-05/samples.csv +4490 -0
  32. package/dist/data/hubmap_2025-05-05/samples.tsv +4490 -0
  33. package/dist/data/hubmap_api/datapackage.json +14110 -0
  34. package/dist/data/readme.md +41 -0
  35. package/dist/favicon.svg +1 -0
  36. package/dist/features/chat/api/completions.d.ts +12 -0
  37. package/dist/features/chat/components/ApiKeyInput.d.ts +5 -0
  38. package/dist/features/chat/components/ChatHeaderBar.d.ts +19 -0
  39. package/dist/features/chat/components/ChatInput.d.ts +7 -0
  40. package/dist/features/chat/components/ChatPanel.d.ts +13 -0
  41. package/dist/features/chat/components/ClosedVisualizationsPanel.d.ts +6 -0
  42. package/dist/features/chat/components/ConversationList.d.ts +1 -0
  43. package/dist/features/chat/components/DebugToggleSection.d.ts +13 -0
  44. package/dist/features/chat/components/MessageBubble.d.ts +8 -0
  45. package/dist/features/chat/components/MessageList.d.ts +7 -0
  46. package/dist/features/chat/hooks/useChatApi.d.ts +6 -0
  47. package/dist/features/chat/hooks/useDebugExports.d.ts +11 -0
  48. package/dist/features/chat/hooks/useExamplePrompts.d.ts +7 -0
  49. package/dist/features/chat/hooks/useResetHandlers.d.ts +8 -0
  50. package/dist/features/chat/index.d.ts +9 -0
  51. package/dist/features/chat/stores/conversationStore.d.ts +10 -0
  52. package/dist/features/chat/stores/conversationStore.test.d.ts +1 -0
  53. package/dist/features/dashboard/components/DashboardCard.d.ts +9 -0
  54. package/dist/features/dashboard/components/DashboardPanel.d.ts +1 -0
  55. package/dist/features/dashboard/components/DataCounts.d.ts +1 -0
  56. package/dist/features/dashboard/components/DownloadButton.d.ts +1 -0
  57. package/dist/features/dashboard/components/FilterToolbar.d.ts +1 -0
  58. package/dist/features/dashboard/components/VizTweakComponent.d.ts +8 -0
  59. package/dist/features/dashboard/components/VizTweakComponent.types.d.ts +20 -0
  60. package/dist/features/dashboard/components/WelcomeSplash.d.ts +1 -0
  61. package/dist/features/dashboard/index.d.ts +10 -0
  62. package/dist/features/dashboard/stores/dashboardStore.d.ts +70 -0
  63. package/dist/features/dashboard/stores/dashboardStore.test.d.ts +1 -0
  64. package/dist/features/dashboard/stores/dataFiltersStore.d.ts +34 -0
  65. package/dist/features/dashboard/stores/dataFiltersStore.test.d.ts +1 -0
  66. package/dist/features/dashboard/stores/memoryBankStore.d.ts +8 -0
  67. package/dist/features/dashboard/stores/memoryBankStore.test.d.ts +1 -0
  68. package/dist/features/dashboard/stores/selectionsStore.d.ts +7 -0
  69. package/dist/features/dashboard/stores/selectionsStore.test.d.ts +1 -0
  70. package/dist/features/data-package/index.d.ts +7 -0
  71. package/dist/features/data-package/stores/dataPackageStore.d.ts +25 -0
  72. package/dist/features/data-package/stores/dataPackageStore.test.d.ts +1 -0
  73. package/dist/features/data-package/types.d.ts +27 -0
  74. package/dist/features/data-package/utils/joinDataPath.d.ts +7 -0
  75. package/dist/features/data-package/utils/joinDataPath.test.d.ts +1 -0
  76. package/dist/features/data-package/utils/structuredTextParser.d.ts +7 -0
  77. package/dist/features/data-package/utils/structuredTextParser.test.d.ts +1 -0
  78. package/dist/features/data-package/workers/domainWorker.d.ts +13 -0
  79. package/dist/features/tool-calls/components/ClarifyVariable.d.ts +6 -0
  80. package/dist/features/tool-calls/components/FilterComponent.d.ts +9 -0
  81. package/dist/features/tool-calls/components/FreeTextExplain.d.ts +2 -0
  82. package/dist/features/tool-calls/components/IntervalFilterComponent.d.ts +9 -0
  83. package/dist/features/tool-calls/components/PointFilterComponent.d.ts +8 -0
  84. package/dist/features/tool-calls/components/RebuffNotice.d.ts +7 -0
  85. package/dist/features/tool-calls/components/ToolCallRenderer.d.ts +11 -0
  86. package/dist/features/tool-calls/components/VisualizationCard.d.ts +10 -0
  87. package/dist/features/tool-calls/index.d.ts +6 -0
  88. package/dist/features/tool-calls/types.d.ts +52 -0
  89. package/dist/icons.svg +24 -0
  90. package/dist/images/yac-mascot.svg +22 -0
  91. package/dist/index.d.ts +5 -0
  92. package/dist/lib/utils.d.ts +2 -0
  93. package/dist/stores/globalStore.d.ts +6 -0
  94. package/dist/stores/globalStore.test.d.ts +1 -0
  95. package/dist/test/setup.d.ts +0 -0
  96. package/dist/types/dataPackage.d.ts +64 -0
  97. package/dist/types/messages.d.ts +24 -0
  98. package/dist/udi-yac.css +3 -0
  99. package/dist/udi-yac.js +25877 -0
  100. package/dist/utils/specMutations.d.ts +45 -0
  101. package/dist/utils/specMutations.test.d.ts +1 -0
  102. package/package.json +110 -0
package/README.md ADDED
@@ -0,0 +1,373 @@
1
+ # udi-yac
2
+
3
+ React implementation of the UDI Chat interface — an AI-powered system for querying and visualizing biomedical datasets via natural language. This is a React port of the original Vue 3/Quasar `udi-chat` app. Published on npm as [`udi-yac`](https://www.npmjs.com/package/udi-yac); the repository directory remains `udi-chat-react`.
4
+
5
+ ## Quick Start
6
+
7
+ ```bash
8
+ pnpm install
9
+ pnpm dev # dev server
10
+ pnpm build # standalone app build (dist/)
11
+ pnpm build:lib # library build (dist/, consumes entry from src/index.ts)
12
+ pnpm lint # eslint
13
+ pnpm format # prettier
14
+ pnpm typecheck # tsc --noEmit
15
+ pnpm test # vitest (one-shot)
16
+ pnpm test:watch # vitest in watch mode
17
+ ```
18
+
19
+ ### Standalone app config (env vars)
20
+
21
+ The standalone `App.tsx` reads these Vite env vars (see `.env.example`). Copy `.env.example` to `.env.local` to override locally:
22
+
23
+ | Var | Default | Purpose |
24
+ | -------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------------------------- |
25
+ | `VITE_UDI_API_BASE_URL` | `http://localhost:8007` | UDIAgent FastAPI server URL |
26
+ | `VITE_UDI_DATA_PACKAGE` | (unset → inline HuBMAP API package from `src/data/hubmapRemote.ts`) | Optional path/URL to a `datapackage_udi.json`. Overrides the inline default when set. |
27
+ | `VITE_UDI_REQUIRE_API_KEY` | `true` | Set to `false` to skip the in-app OpenAI key prompt |
28
+ | `VITE_UDI_MODEL` | (unset) | Optional LLM model override |
29
+
30
+ By default the standalone app talks to the live HuBMAP Portal metadata API. To use the locally bundled snapshot instead, set:
31
+
32
+ ```
33
+ VITE_UDI_DATA_PACKAGE=/data/hubmap_2025-05-05/datapackage_udi.json
34
+ ```
35
+
36
+ > **Note on `build` vs `build:lib`**: `pnpm build` produces a deployable standalone SPA — this is the default so CI/deploy pipelines behave as expected. To build the publishable library bundle (the `UDIChat` React component), use `pnpm build:lib`, which invokes `vite build --mode lib` and emits both JS and `.d.ts` files under `dist/`.
37
+
38
+ ## Stack
39
+
40
+ - **React 19** with TypeScript
41
+ - **Tailwind 4** + **shadcn/ui** (Base UI primitives)
42
+ - **Zustand** for state management (vanilla stores via React Context)
43
+ - **UDI Toolkit** (Vue Custom Elements) for grammar-based visualization rendering
44
+ - **Arquero** for client-side data loading and domain computation
45
+ - **Vite** for dev server and library builds
46
+
47
+ ## Architecture
48
+
49
+ ### Dual Build Modes
50
+
51
+ The project builds as both a **library** and a **standalone app**:
52
+
53
+ - **Library** (`pnpm build`): Exports the `UDIChat` component and `UDIChatConfig` type. Consumers provide React and render `<UDIChat>` with configuration props.
54
+ - **Standalone** (`pnpm build:app`): Builds `App.tsx` as a full SPA with dev defaults.
55
+
56
+ ### Library Usage
57
+
58
+ ```tsx
59
+ import { UDIChat } from 'udi-yac';
60
+ import 'udi-yac/style.css';
61
+
62
+ <UDIChat
63
+ apiBaseUrl="http://localhost:8007"
64
+ dataPackagePath="./data/hubmap_2025-05-05/datapackage_udi.json"
65
+ authToken="your-jwt-token" // optional
66
+ requireApiKey // optional — prompts for OpenAI key
67
+ model="agenticx/UDI-VIS-Beta-v2" // optional
68
+ />;
69
+ ```
70
+
71
+ ### Config Props
72
+
73
+ | Prop | Type | Description |
74
+ | ------------------ | -------------------- | --------------------------------------------------------------------------------------------------------------- |
75
+ | `apiBaseUrl` | `string` | Base URL for the UDIAgent API |
76
+ | `dataPackagePath` | `string?` | URL/path to `datapackage_udi.json`. Ignored when `dataPackage` is provided. |
77
+ | `dataPackage` | `DataPackage?` | Provide a data package object directly instead of fetching from a URL. Takes precedence over `dataPackagePath`. |
78
+ | `dataFieldDomains` | `DataFieldDomain[]?` | Pre-computed field domains. Skips CSV loading for domain computation when provided with `dataPackage`. |
79
+ | `fetchOptions` | `RequestInit?` | Custom fetch options (headers, credentials, etc.) forwarded to all data-loading fetch calls. |
80
+ | `authToken` | `string?` | JWT bearer token for API auth |
81
+ | `requireApiKey` | `boolean?` | Show API key input before chatting |
82
+ | `model` | `string?` | LLM model name override |
83
+ | `className` | `string?` | CSS class for the root element |
84
+ | `style` | `CSSProperties?` | Inline styles for the root element |
85
+
86
+ ### Data Source Configuration
87
+
88
+ There are three ways to provide data to `UDIChat`, from simplest to most flexible:
89
+
90
+ #### 1. Local data package file (default)
91
+
92
+ Point `dataPackagePath` to a `datapackage_udi.json` file. The JSON must contain a `udi:path` base path and `resources` with relative file paths. CSVs are loaded client-side via Arquero.
93
+
94
+ ```tsx
95
+ <UDIChat
96
+ apiBaseUrl="http://localhost:8007"
97
+ dataPackagePath="./data/hubmap_2025-05-05/datapackage_udi.json"
98
+ />
99
+ ```
100
+
101
+ #### 2. Remote data sources
102
+
103
+ Data packages can reference remote URLs. Set `udi:path` to a remote base URL and keep resource `path` values as relative filenames. Arquero's `loadCSV` uses `fetch()` internally, so remote URLs work out of the box.
104
+
105
+ If the remote server requires authentication, pass `fetchOptions` with the necessary headers. These are forwarded to all `fetch()` calls — both the data package JSON fetch and CSV loading:
106
+
107
+ ```tsx
108
+ <UDIChat
109
+ apiBaseUrl="http://localhost:8007"
110
+ dataPackagePath="https://portal.example.com/metadata/datapackage_udi.json"
111
+ fetchOptions={{
112
+ headers: { Authorization: 'Bearer <token>' },
113
+ credentials: 'include',
114
+ }}
115
+ />
116
+ ```
117
+
118
+ > **Note:** The remote server must send appropriate CORS headers (`Access-Control-Allow-Origin`) for browser-based fetching to work.
119
+
120
+ #### 3. Inline data package (no fetch)
121
+
122
+ Pass a `DataPackage` object directly via the `dataPackage` prop. This is useful when you build the schema programmatically or receive it from an API. CSVs are still loaded from the URLs in `udi:path` + `resource.path` for domain computation, unless you also provide `dataFieldDomains` to skip that step entirely.
123
+
124
+ ```tsx
125
+ import type { DataPackage } from 'udi-yac';
126
+
127
+ const myDataPackage: DataPackage = {
128
+ 'udi:path': 'https://portal.hubmapconsortium.org/metadata/v0/',
129
+ resources: [
130
+ {
131
+ name: 'donors',
132
+ path: 'donors.tsv',
133
+ 'udi:row_count': 281,
134
+ schema: {
135
+ fields: [
136
+ {
137
+ name: 'age_value',
138
+ description: 'The time elapsed since birth.',
139
+ 'udi:data_type': 'quantitative',
140
+ },
141
+ { name: 'sex', description: 'Biological sex of the donor.', 'udi:data_type': 'nominal' },
142
+ // ... more fields
143
+ ],
144
+ },
145
+ },
146
+ // ... more resources
147
+ ],
148
+ };
149
+
150
+ <UDIChat apiBaseUrl="http://localhost:8007" dataPackage={myDataPackage} />;
151
+ ```
152
+
153
+ To skip CSV loading entirely (e.g. when you already have domain metadata), pass pre-computed domains:
154
+
155
+ ```tsx
156
+ import type { DataFieldDomain } from 'udi-yac';
157
+
158
+ const myDomains: DataFieldDomain[] = [
159
+ {
160
+ entity: 'donors',
161
+ field: 'age_value',
162
+ type: 'interval',
163
+ fieldDescription: 'The time elapsed since birth.',
164
+ domain: { min: 1, max: 87 },
165
+ },
166
+ {
167
+ entity: 'donors',
168
+ field: 'sex',
169
+ type: 'point',
170
+ fieldDescription: 'Biological sex of the donor.',
171
+ domain: { values: ['Male', 'Female'] },
172
+ },
173
+ // ...
174
+ ];
175
+
176
+ <UDIChat
177
+ apiBaseUrl="http://localhost:8007"
178
+ dataPackage={myDataPackage}
179
+ dataFieldDomains={myDomains}
180
+ />;
181
+ ```
182
+
183
+ See [`src/data/hubmapRemote.ts`](src/data/hubmapRemote.ts) for the canonical inline DataPackage example targeting the live HuBMAP Portal — this is also the default the standalone `App.tsx` uses.
184
+
185
+ ## Features
186
+
187
+ ### Chat Interface
188
+
189
+ - Natural language input with LLM-powered responses
190
+ - Tool call rendering: visualizations, filters, explanations, clarifications, rebuffs
191
+ - Example prompts dialog (fetched from backend `/v1/yac/examples`)
192
+ - Conversation reset, save/export as JSON
193
+ - API key input with localStorage persistence
194
+
195
+ ### Visualization Dashboard
196
+
197
+ - Auto-pinned visualizations from assistant responses
198
+ - Interactive Vega-Lite charts via UDI Grammar spec → UDIVis (Vue CE)
199
+ - **Cross-chart filtering**: brush selections on one chart filter all others
200
+ - **Expand/collapse** visualizations to full width
201
+ - **Table view toggle**: switch between chart and raw data table
202
+ - **Field tweaking**: swap x/y/color encodings via dropdowns
203
+ - **Spec inspector**: view/copy JSON spec, open in UDI Grammar Editor (lz-string compressed URL)
204
+ - **Hover highlighting** across chat messages and dashboard cards
205
+ - **Memory bank**: restore recently closed visualizations
206
+
207
+ ### Data Filtering
208
+
209
+ - **Interval filters**: range sliders for numeric fields
210
+ - **Point filters**: checkbox selection for categorical fields
211
+ - **Filter toolbar**: active filter chips with clear buttons
212
+ - **Cross-entity filtering**: filters propagate across related entities via foreign keys
213
+ - **Null value filtering** toggle
214
+
215
+ ### Data Management
216
+
217
+ - **Entity counts**: per-entity row counts with dynamic filtered counts
218
+ - **Download**: filtered data as ZIP of CSVs, or manifest (hubmap_id extraction)
219
+ - Data package loading with domain computation (Arquero)
220
+
221
+ ### Debug Mode (type `!/admin` in chat)
222
+
223
+ - System prompts toggle (show/hide system messages)
224
+ - Conversation sidebar drawer (load saved session JSON files)
225
+ - Export test case for benchmarking
226
+ - Download data domains / data schema as JSON
227
+ - Save conversation export
228
+
229
+ ## Project Structure
230
+
231
+ The codebase follows a [bulletproof-react](https://github.com/alan2207/bulletproof-react)-style layout. Module boundaries are enforced by [`eslint-plugin-project-structure`](https://www.npmjs.com/package/eslint-plugin-project-structure) (see [eslint.config.js](eslint.config.js)). For the reasoning behind the layout and a guide to working within it, see [CONTRIBUTING.md](CONTRIBUTING.md).
232
+
233
+ ```
234
+ src/
235
+ index.ts # Library entry: exports UDIChat + UDIChatConfig
236
+ index.css # Global Tailwind base + custom CSS
237
+ env.d.ts # Vite client types
238
+
239
+ app/ # Composition root (allowed to reach into any feature)
240
+ main.tsx # Vite app bootstrap
241
+ App.tsx # Standalone app entry (inline HuBMAP package)
242
+ UDIChat.tsx # Root component (provider + layout)
243
+ UDIChatConfig.ts # UDIChatConfig type (extracted to break circular)
244
+ UDIChatContext.tsx # Provider + hooks wiring all Zustand stores
245
+ ErrorBoundary.tsx # React error boundary
246
+ validateConfig.ts (+ .test.ts) # Runtime validation for UDIChatConfig
247
+
248
+ features/
249
+ chat/
250
+ index.ts # Public barrel — cross-feature consumers import only from here
251
+ api/
252
+ completions.ts # POST /v1/yac/completions client + QueryConfig type
253
+ components/
254
+ ChatPanel.tsx # Slim orchestrator (~85 lines)
255
+ ChatHeaderBar.tsx # Toolbar — owns debugMode subscription
256
+ DebugToggleSection.tsx # System-prompt toggle — owns debugMode + messages
257
+ ClosedVisualizationsPanel.tsx # Recently-closed viz strip — owns memoryBank
258
+ ChatInput.tsx # Message input
259
+ MessageList.tsx # Message history with auto-scroll
260
+ MessageBubble.tsx # Single message + tool call tabs
261
+ ConversationList.tsx # Sidebar with saved session files
262
+ ApiKeyInput.tsx # OpenAI API key input
263
+ hooks/
264
+ useChatApi.ts # LLM API integration hook
265
+ useExamplePrompts.ts # /v1/yac/examples fetch
266
+ useResetHandlers.ts # Bundled "reset everything" action
267
+ useDebugExports.ts # Debug-mode export buttons (save / test case / data)
268
+ stores/
269
+ conversationStore.ts # Chat messages, save/load/export
270
+
271
+ dashboard/
272
+ index.ts # Public barrel
273
+ components/
274
+ DashboardPanel.tsx # Dashboard layout (counts, filters, viz grid)
275
+ DashboardCard.tsx # Single pinned viz (chart, toolbar, tweak, spec)
276
+ DataCounts.tsx # Per-entity row counts (total + filtered)
277
+ FilterToolbar.tsx # Active filter chips
278
+ DownloadButton.tsx # CSV/manifest download dropdown
279
+ VizTweakComponent.tsx # Field encoding swap dropdowns
280
+ VizTweakComponent.types.ts # TweakableParam, LayerLike, MappingLike
281
+ WelcomeSplash.tsx # Empty dashboard placeholder
282
+ stores/
283
+ dashboardStore.ts # Pinned vizzes, interactivity, expand/table/hover
284
+ dataFiltersStore.ts # Interval/point filter state, message sync
285
+ selectionsStore.ts # Cross-viz brush selection coordination
286
+ memoryBankStore.ts # Closed visualization restoration
287
+
288
+ data-package/
289
+ index.ts # Public barrel
290
+ types.ts # Web Worker protocol types
291
+ stores/
292
+ dataPackageStore.ts # Data schema, field domains, entity relationships
293
+ utils/
294
+ joinDataPath.ts # Path joining for local + remote data URLs
295
+ structuredTextParser.ts # Template function evaluation for explanations
296
+ workers/
297
+ domainWorker.ts # Off-main-thread domain computation
298
+
299
+ tool-calls/
300
+ index.ts # Public barrel
301
+ types.ts # Args for each tool call type
302
+ components/
303
+ ToolCallRenderer.tsx # Dispatches tool calls to renderers
304
+ VisualizationCard.tsx # UDIVis preview (chat) / pinned badge
305
+ FilterComponent.tsx # Filter dispatcher (interval/point)
306
+ IntervalFilterComponent.tsx
307
+ PointFilterComponent.tsx
308
+ FreeTextExplain.tsx # Markdown explanation with structured text
309
+ RebuffNotice.tsx # Rejection with suggestion buttons
310
+ ClarifyVariable.tsx # Field disambiguation UI
311
+
312
+ components/
313
+ ui/ # shadcn/ui primitives (badge, button, dialog, …)
314
+
315
+ stores/
316
+ globalStore.ts # Truly cross-feature state (debug mode)
317
+
318
+ types/
319
+ messages.ts # Message, ToolCall, FlatToolCall (cross-feature)
320
+ dataPackage.ts # DataPackage, DataFieldDomain, etc. (cross-feature)
321
+
322
+ lib/
323
+ utils.ts # cn() helper (clsx + tailwind-merge)
324
+
325
+ utils/
326
+ specMutations.ts # Pure UDI grammar helpers
327
+
328
+ data/
329
+ hubmapRemote.ts # Inline DataPackage targeting the live HuBMAP Portal API
330
+ ```
331
+
332
+ ### Module boundaries
333
+
334
+ The `project-structure/independent-modules` rule enforces these import boundaries:
335
+
336
+ | From | Can import |
337
+ | -------------------- | ------------------------------------------------------------------------------------------------ |
338
+ | `src/features/X/**` | own family, **other features' `index.ts` only**, `src/{utils,types,lib,stores,components/ui}/**` |
339
+ | `src/app/**` | any feature internal, all shared layers |
340
+ | `src/components/ui/` | sibling UI, `src/lib/` |
341
+ | `src/utils/` | `src/{utils,types,lib,stores}/`, feature barrels |
342
+ | `src/{types,lib}/` | shared layers only |
343
+ | `src/stores/` | `src/{stores,types,lib}/` |
344
+
345
+ Cross-feature imports must go through the feature's `index.ts` barrel — direct paths like `@/features/dashboard/stores/dataFiltersStore` from another feature will fail lint.
346
+
347
+ ## API Integration
348
+
349
+ The app communicates with a UDIAgent backend:
350
+
351
+ | Endpoint | Method | Purpose |
352
+ | ---------------------- | ------ | --------------------------------- |
353
+ | `/v1/yac/completions` | POST | Send messages, receive tool calls |
354
+ | `/v1/yac/examples` | GET | Fetch example prompts |
355
+ | `/sessions/{filename}` | GET | Load saved conversation files |
356
+
357
+ Request body for completions:
358
+
359
+ ```json
360
+ {
361
+ "model": "...",
362
+ "messages": [...],
363
+ "dataSchema": "...",
364
+ "dataDomains": "..."
365
+ }
366
+ ```
367
+
368
+ ## Relationship to udi-grammar
369
+
370
+ Visualizations are rendered by the `UDIVis` Vue Custom Element from the `udi-grammar` package, consumed via the published [`udi-toolkit`](https://www.npmjs.com/package/udi-toolkit) npm package. The React wrapper (`udi-toolkit/react`) bridges Vue CE props and events:
371
+
372
+ - **Props** (`spec`, `selections`): set via `useLayoutEffect` on the DOM element
373
+ - **Events** (`selection-change`, `data-ready`): listened via `addEventListener`, with Vue CE array-wrapping unwrapped
@@ -0,0 +1,18 @@
1
+ import { Component, ErrorInfo, ReactNode } from 'react';
2
+ interface Props {
3
+ children: ReactNode;
4
+ }
5
+ interface State {
6
+ error: Error | null;
7
+ errorInfo: ErrorInfo | null;
8
+ }
9
+ export declare class ErrorBoundary extends Component<Props, State> {
10
+ state: State;
11
+ static getDerivedStateFromError(error: Error): Partial<State>;
12
+ componentDidCatch(error: Error, errorInfo: ErrorInfo): void;
13
+ private getErrorText;
14
+ private handleCopy;
15
+ private handleReset;
16
+ render(): string | number | bigint | boolean | import("react/jsx-runtime").JSX.Element | Iterable<ReactNode> | Promise<string | number | bigint | boolean | import('react').ReactPortal | import('react').ReactElement<unknown, string | import('react').JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | null | undefined;
17
+ }
18
+ export {};
@@ -0,0 +1,3 @@
1
+ import { UDIChatConfig } from './UDIChatConfig';
2
+ export type { UDIChatConfig };
3
+ export declare function UDIChat(props: UDIChatConfig): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,23 @@
1
+ import { DataPackage, DataFieldDomain } from '../types/dataPackage';
2
+ /**
3
+ * Public configuration surface for the `UDIChat` root component. Extracted
4
+ * from UDIChat.tsx so that `validateConfig` and other app-layer utilities
5
+ * can import the type without reaching into the component module.
6
+ */
7
+ export interface UDIChatConfig {
8
+ apiBaseUrl: string;
9
+ /** URL to fetch a datapackage_udi.json from. Ignored when `dataPackage` is provided. */
10
+ dataPackagePath?: string;
11
+ /** Provide a DataPackage object directly instead of fetching from a URL. Takes precedence over `dataPackagePath`. */
12
+ dataPackage?: DataPackage;
13
+ /** Pre-computed field domains. When provided with `dataPackage`, skips CSV loading for domain computation. */
14
+ dataFieldDomains?: DataFieldDomain[];
15
+ /** Custom fetch options (e.g. headers, credentials) forwarded to all data-loading fetch calls. */
16
+ fetchOptions?: RequestInit;
17
+ authToken?: string;
18
+ /** If true, prompt the user to enter an OpenAI API key before chatting. */
19
+ requireApiKey?: boolean;
20
+ model?: string;
21
+ className?: string;
22
+ style?: React.CSSProperties;
23
+ }
@@ -0,0 +1,26 @@
1
+ import { ReactNode } from 'react';
2
+ import { StoreApi } from 'zustand';
3
+ import { ConversationState } from '../features/chat/stores/conversationStore';
4
+ import { DashboardState } from '../features/dashboard/stores/dashboardStore';
5
+ import { DataPackageState } from '../features/data-package/stores/dataPackageStore';
6
+ import { SelectionsState } from '../features/dashboard/stores/selectionsStore';
7
+ import { DataFiltersState } from '../features/dashboard/stores/dataFiltersStore';
8
+ import { MemoryBankState } from '../features/dashboard/stores/memoryBankStore';
9
+ import { GlobalState } from '../stores/globalStore';
10
+ export declare function UDIChatProvider({ children }: {
11
+ children: ReactNode;
12
+ }): import("react/jsx-runtime").JSX.Element;
13
+ export declare function useConversation<T>(selector: (state: ConversationState) => T): T;
14
+ export declare function useConversationStore(): StoreApi<ConversationState>;
15
+ export declare function useDashboard<T>(selector: (state: DashboardState) => T): T;
16
+ export declare function useDashboardStore(): StoreApi<DashboardState>;
17
+ export declare function useDataPackage<T>(selector: (state: DataPackageState) => T): T;
18
+ export declare function useDataPackageStore(): StoreApi<DataPackageState>;
19
+ export declare function useSelections<T>(selector: (state: SelectionsState) => T): T;
20
+ export declare function useSelectionsStore(): StoreApi<SelectionsState>;
21
+ export declare function useDataFilters<T>(selector: (state: DataFiltersState) => T): T;
22
+ export declare function useDataFiltersStore(): StoreApi<DataFiltersState>;
23
+ export declare function useMemoryBank<T>(selector: (state: MemoryBankState) => T): T;
24
+ export declare function useMemoryBankStore(): StoreApi<MemoryBankState>;
25
+ export declare function useGlobal<T>(selector: (state: GlobalState) => T): T;
26
+ export declare function useGlobalStore(): StoreApi<GlobalState>;
@@ -0,0 +1,14 @@
1
+ import { UDIChatConfig } from './UDIChatConfig';
2
+ /**
3
+ * Lightweight runtime validation for the UDIChatConfig shape.
4
+ *
5
+ * Catches the most common consumer mistakes (missing apiBaseUrl, malformed
6
+ * URL, no data source provided, malformed DataPackage) before they fail deep
7
+ * inside Arquero or fetch with opaque stack traces. Errors are thrown so the
8
+ * surrounding ErrorBoundary renders a useful message.
9
+ *
10
+ * This is intentionally NOT a full schema validator — it covers the failure
11
+ * modes we've actually seen in practice. If a field has a bad type that React
12
+ * itself will surface clearly, we don't duplicate that check here.
13
+ */
14
+ export declare function validateConfig(config: UDIChatConfig): void;
@@ -0,0 +1 @@
1
+ export {};