@interopio/io-assist-react 1.0.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 (99) hide show
  1. package/README.internal.md +467 -0
  2. package/README.md +503 -0
  3. package/changelog.md +2 -0
  4. package/dist/IoAssist.d.ts +12 -0
  5. package/dist/actions/abortActiveStream.d.ts +2 -0
  6. package/dist/actions/deleteThread.d.ts +2 -0
  7. package/dist/actions/elicitation.d.ts +13 -0
  8. package/dist/actions/initIoAiWeb.d.ts +3 -0
  9. package/dist/actions/initIoConnect.d.ts +9 -0
  10. package/dist/actions/mcpAppEvents.d.ts +4 -0
  11. package/dist/actions/newConversation.d.ts +2 -0
  12. package/dist/actions/processResponseStream.d.ts +3 -0
  13. package/dist/actions/renameThread.d.ts +2 -0
  14. package/dist/actions/sampling.d.ts +5 -0
  15. package/dist/actions/selectThread.d.ts +2 -0
  16. package/dist/actions/sendUserMessage.d.ts +3 -0
  17. package/dist/actions/toggleFavoritePrompt.d.ts +7 -0
  18. package/dist/actions/toggleTool.d.ts +2 -0
  19. package/dist/components/chat/ActivePanelModal.d.ts +6 -0
  20. package/dist/components/chat/AiDisclaimer.d.ts +6 -0
  21. package/dist/components/chat/Chat.d.ts +2 -0
  22. package/dist/components/chat/ConfirmModal.d.ts +8 -0
  23. package/dist/components/chat/WelcomeHeading.d.ts +6 -0
  24. package/dist/components/header/Header.d.ts +2 -0
  25. package/dist/components/input-area/InputArea.d.ts +8 -0
  26. package/dist/components/messages/AssistantMessage.d.ts +10 -0
  27. package/dist/components/messages/McpAppResource.d.ts +11 -0
  28. package/dist/components/messages/MdFormatter.d.ts +6 -0
  29. package/dist/components/messages/MessageArea.d.ts +7 -0
  30. package/dist/components/messages/ToolMessage.d.ts +9 -0
  31. package/dist/components/messages/ToolTraceMessage.d.ts +9 -0
  32. package/dist/components/messages/UserMessage.d.ts +9 -0
  33. package/dist/components/messages/mdUtils.d.ts +1 -0
  34. package/dist/components/messages/prismTwilightTheme.d.ts +2 -0
  35. package/dist/components/prompt/FavoritePromptList.d.ts +2 -0
  36. package/dist/components/prompt/PromptListItem.d.ts +8 -0
  37. package/dist/components/prompt/PromptListPanel.d.ts +6 -0
  38. package/dist/components/scroll-area/ScrollArea.d.ts +33 -0
  39. package/dist/components/shared/Icon.d.ts +8 -0
  40. package/dist/components/shared/IconButton.d.ts +11 -0
  41. package/dist/components/shared/Modal.d.ts +12 -0
  42. package/dist/components/shared/SearchInput.d.ts +8 -0
  43. package/dist/components/shared/ToggleInput.d.ts +8 -0
  44. package/dist/components/shared/Tooltip.d.ts +10 -0
  45. package/dist/components/shared/icons.d.ts +37 -0
  46. package/dist/components/threads/ThreadHistory.d.ts +6 -0
  47. package/dist/components/threads/ThreadHistoryListItem.d.ts +18 -0
  48. package/dist/components/threads/ThreadHistoryPanel.d.ts +7 -0
  49. package/dist/components/tool/ToolListItem.d.ts +8 -0
  50. package/dist/components/tool/ToolListPanel.d.ts +2 -0
  51. package/dist/components/working-context-panel/WorkingContextPanel.d.ts +2 -0
  52. package/dist/constants/modalActions.d.ts +11 -0
  53. package/dist/constants/uiStrings.d.ts +141 -0
  54. package/dist/context/IoAssistContext.d.ts +14 -0
  55. package/dist/files/inter-latin-wght-normal.woff2 +0 -0
  56. package/dist/hooks/useHoverMouseFollow.d.ts +27 -0
  57. package/dist/hooks/useIoAiWebApi.d.ts +19 -0
  58. package/dist/hooks/useIoAiWebBootstrap.d.ts +8 -0
  59. package/dist/hooks/useIoConnectApi.d.ts +12 -0
  60. package/dist/hooks/useIoConnectBootstrap.d.ts +10 -0
  61. package/dist/hooks/useIsMobileViewport.d.ts +1 -0
  62. package/dist/index.cjs +41 -0
  63. package/dist/index.cjs.map +1 -0
  64. package/dist/index.d.ts +2 -0
  65. package/dist/index.js +3624 -0
  66. package/dist/index.js.map +1 -0
  67. package/dist/stores/agent.d.ts +15 -0
  68. package/dist/stores/app-lifecycle.d.ts +21 -0
  69. package/dist/stores/confirm-modal.d.ts +29 -0
  70. package/dist/stores/index.d.ts +32 -0
  71. package/dist/stores/mcp-apps.d.ts +13 -0
  72. package/dist/stores/message.d.ts +33 -0
  73. package/dist/stores/prompt.d.ts +16 -0
  74. package/dist/stores/response-stream.d.ts +31 -0
  75. package/dist/stores/thread.d.ts +17 -0
  76. package/dist/stores/tool.d.ts +15 -0
  77. package/dist/stores/working-context.d.ts +16 -0
  78. package/dist/styles.css +1 -0
  79. package/dist/types/agent.d.ts +8 -0
  80. package/dist/types/config.d.ts +40 -0
  81. package/dist/types/icon.d.ts +5 -0
  82. package/dist/types/index.d.ts +15 -0
  83. package/dist/types/loading.d.ts +38 -0
  84. package/dist/types/message.d.ts +56 -0
  85. package/dist/types/panel.d.ts +6 -0
  86. package/dist/types/prompt.d.ts +17 -0
  87. package/dist/types/stream.d.ts +22 -0
  88. package/dist/types/thread.d.ts +15 -0
  89. package/dist/types/tool.d.ts +15 -0
  90. package/dist/utils/confirmModal.d.ts +5 -0
  91. package/dist/utils/ioModals.d.ts +21 -0
  92. package/dist/utils/logger.d.ts +34 -0
  93. package/dist/utils/mcpAppModal.d.ts +3 -0
  94. package/dist/utils/messageConverter.d.ts +3 -0
  95. package/dist/utils/messageUtils.d.ts +16 -0
  96. package/dist/utils/safeStringify.d.ts +1 -0
  97. package/dist/utils/streamUtils.d.ts +15 -0
  98. package/dist/utils/threadUtils.d.ts +16 -0
  99. package/package.json +65 -0
package/README.md ADDED
@@ -0,0 +1,503 @@
1
+ # @interopio/io-assist-react
2
+
3
+ A full-featured AI assistant component for React applications. Drop a single `<IoAssist />` component into your app and get a conversational AI chat interface backed by any [AG-UI Protocol](https://docs.ag-ui.com) compatible agent server — with streaming responses, persistent threads, a prompt library, MCP tool access, working context awareness, and built-in sampling/elicitation handling.
4
+
5
+ Built on [io.Connect](https://interop.io/) and [@interopio/ai-web](https://www.npmjs.com/package/@interopio/ai-web).
6
+
7
+
8
+ ## Features
9
+
10
+ - **Conversational AI chat** — Streaming responses, markdown rendering, code highlighting
11
+ - **Persistent conversation threads** — Thread history with resume, rename, and delete
12
+ - **Prompt library** — Categorized pre-written prompts with favorites (persisted via io.Connect preferences)
13
+ - **MCP tool access** — Built-in io.Intelligence MCP server, extensible with remote and third-party servers
14
+ - **MCP Apps** — Custom HTML applications rendered inline in chat or in io.Connect workspace windows
15
+ - **Sampling & elicitation** — Built-in confirmation/input UI for MCP server requests (replaceable with custom handlers)
16
+ - **Working context** — Live data from io.Connect contexts passed to the agent with every message
17
+ - **Theming** — Automatic dark/light mode sync with io.Connect
18
+
19
+ ## Prerequisites
20
+
21
+ - **React** 18+
22
+ - **Node.js** 20.19+ (< 22)
23
+ - **npm** 10+
24
+ - An **AG-UI Protocol compatible agent server** (e.g. [Mastra](https://mastra.ai/))
25
+
26
+ ## Installation
27
+
28
+ ```bash
29
+ npm install @interopio/io-assist-react
30
+ ```
31
+
32
+ `react` and `react-dom` are the only **peer dependencies** — your app already provides them:
33
+
34
+ ```bash
35
+ npm install react react-dom
36
+ ```
37
+
38
+ Everything else is declared as a direct dependency and installed automatically, including the io.Connect platform packages (`@interopio/browser`, `@interopio/desktop`), the core intelligence library (`@interopio/ai-web`), working context (`@interopio/working-context`), and the UI runtime (`zustand`, `react-markdown`, `remark-gfm`, `prism-react-renderer`, `@fontsource-variable/inter`). These are resolved from your `node_modules` at runtime, not inlined into the package.
39
+
40
+ You always need to **import a platform factory** and pass it in your `connectConfig` — pick the one that matches your environment:
41
+
42
+ ```tsx
43
+ // io.Connect Browser (most common)
44
+ import IOBrowser from '@interopio/browser';
45
+
46
+ // io.Connect Desktop
47
+ import IODesktop from '@interopio/desktop';
48
+ ```
49
+
50
+ ---
51
+
52
+ ## Agent Server
53
+
54
+ io.Assist requires an **AG-UI Protocol compatible agent server** to handle chat requests. The recommended way to get started is with [Mastra](https://mastra.ai/).
55
+
56
+ ### Quick setup with Mastra
57
+
58
+ ```bash
59
+ npx create-mastra@latest
60
+ ```
61
+
62
+ This scaffolds a fully working Mastra project. Follow the prompts, then start the server:
63
+
64
+ ```bash
65
+ npm run dev
66
+ ```
67
+
68
+ By default the server runs on `http://localhost:4111` — the same URL used in the Quickstart examples below.
69
+
70
+ **Required environment variables:**
71
+
72
+ ```env
73
+ # At least one LLM provider key
74
+ OPENAI_API_KEY=your-key
75
+ ANTHROPIC_API_KEY=your-key
76
+ ```
77
+
78
+ > For full Mastra documentation — including custom agents, tools, memory, and deployment — see [mastra.ai/docs](https://mastra.ai/docs).
79
+
80
+ ## Quickstart
81
+
82
+ ### 1. Add the stylesheet
83
+
84
+ ```css title="src/styles.css"
85
+ @import "@interopio/io-assist-react/styles";
86
+ ```
87
+
88
+ ### 2. Render the component
89
+
90
+ `<IoAssist />` takes two props: a `staticConfig` (infrastructure settings, known at bootstrap) and a `dynamicConfig` (the active user's identity and per-request headers, often known only after login).
91
+
92
+ ```tsx title="src/App.tsx"
93
+ import { IoAssist, IoAssistStaticConfig, IoAssistDynamicConfig } from '@interopio/io-assist-react';
94
+ import IOBrowser from '@interopio/browser';
95
+
96
+ const staticConfig: IoAssistStaticConfig = {
97
+ connectConfig: {
98
+ browser: {
99
+ factory: IOBrowser,
100
+ },
101
+ },
102
+ aiWebConfig: {
103
+ agentServer: {
104
+ baseUrl: 'http://localhost:4111',
105
+ },
106
+ },
107
+ };
108
+
109
+ const dynamicConfig: IoAssistDynamicConfig = {
110
+ // id: Your access/auth token of choice — scopes conversation threads
111
+ // name: UI name that will be displayed
112
+ user: { id: 'yourIdOfChoice', name: 'Jane Doe' },
113
+ agentServer: {
114
+ headers: {
115
+ Authorization: `Bearer ${import.meta.env.VITE_AUTH_TOKEN}`,
116
+ },
117
+ },
118
+ };
119
+
120
+ export function App() {
121
+ return <IoAssist staticConfig={staticConfig} dynamicConfig={dynamicConfig} />;
122
+ }
123
+ ```
124
+
125
+ ### 3. Run
126
+
127
+ ```bash
128
+ npm run dev
129
+ ```
130
+
131
+ **io.Assist is live.**
132
+
133
+ ---
134
+
135
+ ## Quickstart with Login
136
+
137
+ This pattern shows how to pair io.Assist with a login flow — the user's identity is only passed to the assistant after authentication. Build the `dynamicConfig` from your auth state and render `<IoAssist />` only once a user is present.
138
+
139
+ ```tsx title="src/AssistantShell.tsx"
140
+ import { useMemo } from 'react';
141
+ import { Navigate } from 'react-router-dom';
142
+ import { IoAssist, IoAssistDynamicConfig } from '@interopio/io-assist-react';
143
+ import { staticConfig } from './configs';
144
+ import { useAuth } from './auth';
145
+
146
+ export function AssistantShell() {
147
+ const { userId } = useAuth();
148
+
149
+ const dynamicConfig = useMemo<IoAssistDynamicConfig | null>(
150
+ () => (userId ? { user: { id: userId } } : null),
151
+ [userId],
152
+ );
153
+
154
+ if (!dynamicConfig) {
155
+ return <Navigate to="/login" replace />;
156
+ }
157
+
158
+ return <IoAssist staticConfig={staticConfig} dynamicConfig={dynamicConfig} />;
159
+ }
160
+ ```
161
+
162
+ Once the user logs in, `dynamicConfig` is populated and io.Assist loads threads scoped to that user.
163
+
164
+ ---
165
+
166
+ ## What you get with the minimal config
167
+
168
+ With just the required fields (`staticConfig.connectConfig`, `staticConfig.aiWebConfig.agentServer.baseUrl`, and `dynamicConfig.user`), io.Assist provides:
169
+
170
+ - Full conversational AI chat with streaming markdown responses
171
+ - Persistent conversation threads (scoped to `user.id`)
172
+ - Automatic agent selection (first available agent from your server)
173
+ - Built-in sampling and elicitation UI (confirmation dialogs when MCP servers request them)
174
+ - Built-in io.Intelligence MCP server connection
175
+ - Dark/light theme sync with io.Connect
176
+ - Auto-injected fonts and syntax highlighting
177
+
178
+ No prompts, no working context, and no MCP Apps — those require additional configuration below.
179
+
180
+ ---
181
+
182
+ ## Configuration
183
+
184
+ io.Assist uses two separate configuration objects, passed as two distinct props:
185
+
186
+ - **`IoAssistStaticConfig`** — infrastructure settings that don't change at runtime (platform factory, agent server, MCP, prompts). Pass it as the `staticConfig` prop.
187
+ - **`IoAssistDynamicConfig`** — the active user's identity and per-request headers, which may only be known after login. Pass it as the `dynamicConfig` prop.
188
+
189
+ ### Static configuration (`IoAssistStaticConfig`)
190
+
191
+ Passed as the `staticConfig` prop.
192
+
193
+ **Required fields**
194
+
195
+ | Field | Type | Description |
196
+ |-------|------|-------------|
197
+ | `connectConfig` | `{ browser?, desktop? }` | io.Connect platform settings. Must include a `browser` and/or `desktop` entry, each with a `factory` (and optional `config`). |
198
+ | `aiWebConfig.agentServer.baseUrl` | `string` | Base URL of your AG-UI compatible agent server. |
199
+
200
+ **Optional fields**
201
+
202
+ | Field | Type | Description |
203
+ |-------|------|-------------|
204
+ | `aiWebConfig.agentServer.*` | `IoAiWeb.AgentServerConfig` | Additional agent-server options (retries, backoff, credentials, etc.). |
205
+ | `aiWebConfig.mcp` | `IoAiWeb.MCPConfig` | MCP configuration — remote servers, MCP Apps, sampling/elicitation overrides. |
206
+ | `defaultAgentName` | `string` | Agent to select on startup. Falls back to the first available agent if not found. |
207
+ | `defaultPrompts` | `IoAssistPromptCategory[]` | Categorized prompt library entries. |
208
+ | `workingContext` | `IoAiWeb.WorkingContextConfig` | Live context collection from io.Connect. |
209
+
210
+ ### Dynamic configuration (`IoAssistDynamicConfig`)
211
+
212
+ Passed as the `dynamicConfig` prop. Typically derived from your authentication state.
213
+
214
+ | Field | Type | Description |
215
+ |-------|------|-------------|
216
+ | `user.id` | `string` | **Required.** Unique user identifier. Scopes conversation threads — each user sees only their own threads. |
217
+ | `user.name` | `string?` | Display name shown in the chat UI and thread history. |
218
+ | `agentServer.headers` | `Record<string, string>?` | Request headers sent with every agent call. This is the **only** source of request headers — use it for auth tokens or per-user context. |
219
+
220
+ ---
221
+
222
+ ## Configuration Examples
223
+
224
+ ### Standard — with prompts and a named agent
225
+
226
+ ```tsx title="src/configs.ts"
227
+ import { IoAssistStaticConfig } from '@interopio/io-assist-react';
228
+ import IOBrowser from '@interopio/browser';
229
+
230
+ export const staticConfig: IoAssistStaticConfig = {
231
+ connectConfig: {
232
+ browser: { factory: IOBrowser },
233
+ },
234
+ aiWebConfig: {
235
+ agentServer: {
236
+ baseUrl: 'http://localhost:4111',
237
+ },
238
+ },
239
+ defaultAgentName: 'my-agent',
240
+ defaultPrompts: [
241
+ {
242
+ category: 'General',
243
+ prompts: [
244
+ { name: 'Summarize', prompt: 'Please summarize the following content:' },
245
+ { name: 'Explain', prompt: 'Please explain this in simple terms:' },
246
+ ],
247
+ },
248
+ {
249
+ category: 'Code',
250
+ prompts: [
251
+ { name: 'Review Code', prompt: 'Please review this code and suggest improvements:' },
252
+ {
253
+ name: 'Add Comments',
254
+ prompt: 'Annotate this code with detailed comments:',
255
+ iconResource: {
256
+ type: 'svg',
257
+ data: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="..."/></svg>',
258
+ },
259
+ },
260
+ ],
261
+ },
262
+ ],
263
+ };
264
+ ```
265
+
266
+ **What this adds over minimal:**
267
+
268
+ - **Named agent** pre-selected at startup
269
+ - **Prompt library** with two categories — users can browse, search, and favorite prompts
270
+
271
+ ### Advanced — custom handlers, MCP Apps, working context
272
+
273
+ ```tsx title="src/configs.ts"
274
+ import { IoAssistStaticConfig } from '@interopio/io-assist-react';
275
+ import { IoAiWeb } from '@interopio/ai-web';
276
+ import IOBrowser from '@interopio/browser';
277
+ import { IoIntelWorkingContextFactory, IoIntelWorkingContext } from '@interopio/working-context';
278
+
279
+ export const staticConfig: IoAssistStaticConfig = {
280
+ connectConfig: {
281
+ browser: { factory: IOBrowser },
282
+ },
283
+ aiWebConfig: {
284
+ agentServer: {
285
+ baseUrl: 'http://localhost:4111',
286
+ },
287
+ mcp: {
288
+ // Custom sampling handler — replaces the built-in confirmation dialog
289
+ clientsConfig: {
290
+ enforceStrictCapabilities: false,
291
+ capabilities: {
292
+ sampling: {
293
+ handler: async (
294
+ serverId: string,
295
+ params: IoAiWeb.SamplingRequestParams,
296
+ ): Promise<IoAiWeb.SamplingSuccessResponse> => {
297
+ // Your custom logic — show your own UI, call your own APIs, etc.
298
+ return {
299
+ model: 'gpt-4',
300
+ role: 'assistant',
301
+ content: { type: 'text', text: 'Custom sampling response' },
302
+ stopReason: 'endTurn',
303
+ };
304
+ },
305
+ },
306
+ elicitation: {
307
+ handler: async (
308
+ serverId: string,
309
+ params: IoAiWeb.ElicitationRequestParams,
310
+ ): Promise<IoAiWeb.ElicitationResponse> => {
311
+ // Your custom logic — build a form, collect user input, etc.
312
+ return { action: 'accept', content: { confirmed: true } };
313
+ },
314
+ },
315
+ // Required for MCP Apps
316
+ extensions: {
317
+ 'io.modelcontextprotocol/ui': {
318
+ mimeTypes: ['text/html;profile=mcp-app'],
319
+ },
320
+ },
321
+ },
322
+ },
323
+ // MCP Apps — interactive UI panels in chat or workspace windows
324
+ mcpApps: {
325
+ sandboxProxyUrl: 'http://localhost:6565/index.html',
326
+ displayMode: 'workspace', // or 'inline'
327
+ },
328
+ // Remote MCP servers
329
+ ioIntel: {
330
+ remote: {
331
+ streamableHttp: {
332
+ url: 'http://localhost:8989/mcp',
333
+ name: 'remote-io-mcp-server',
334
+ },
335
+ },
336
+ },
337
+ remoteServers: [
338
+ {
339
+ streamableHttp: {
340
+ url: 'http://localhost:8081/mcp',
341
+ name: 'third-party-server',
342
+ },
343
+ },
344
+ ],
345
+ },
346
+ },
347
+ defaultAgentName: 'my-agent',
348
+ defaultPrompts: [
349
+ {
350
+ category: 'General',
351
+ prompts: [
352
+ { name: 'Summarize', prompt: 'Please summarize the following content:' },
353
+ ],
354
+ },
355
+ ],
356
+ workingContext: {
357
+ factory: IoIntelWorkingContextFactory,
358
+ config: {
359
+ schema: {
360
+ userId: {
361
+ type: 'string',
362
+ description: "Current user's identifier",
363
+ source: {
364
+ context: {
365
+ location: { global: { names: ['UserSession'] } },
366
+ path: 'user.id',
367
+ },
368
+ },
369
+ },
370
+ selectedClient: {
371
+ type: 'string',
372
+ description: 'Client currently selected in the workspace',
373
+ source: {
374
+ context: {
375
+ location: { workspace: {} },
376
+ path: 'client.name',
377
+ },
378
+ },
379
+ },
380
+ },
381
+ } as IoIntelWorkingContext.Config,
382
+ },
383
+ };
384
+ ```
385
+
386
+ **What this adds over standard:**
387
+
388
+ - **Custom sampling handler** — replaces the built-in confirmation dialog. When an MCP server makes a sampling request, your handler runs instead.
389
+ - **Custom elicitation handler** — replaces the built-in elicitation dialog. When an MCP server requests user input, your handler runs instead.
390
+ - **MCP Apps** — interactive HTML panels that MCP tools can render inline in chat or in io.Connect workspace windows. Requires both `mcpApps` config and the `io.modelcontextprotocol/ui` extension.
391
+ - **Remote MCP servers** — switch the io.Intelligence MCP to a remote endpoint and/or add third-party MCP servers.
392
+ - **Working context** — io.Assist reads live data from io.Connect contexts and passes it to the agent with every message.
393
+
394
+ > **Component usage:** In all examples above, pass the config object as the `staticConfig` prop and the user identity as the `dynamicConfig` prop: `<IoAssist staticConfig={staticConfig} dynamicConfig={dynamicConfig} />`. See [Quickstart with Login](#quickstart-with-login) for a full component example.
395
+
396
+ ---
397
+
398
+ ## MCP Apps
399
+
400
+ MCP Apps are fully interactive UI applications that MCP tools can display directly inside the assistant. Instead of returning only text, a tool can ship a complete HTML application that the user interacts with in context.
401
+
402
+ **Requirements** — two config sections must both be present under `aiWebConfig.mcp`:
403
+
404
+ 1. **`mcpApps`** — enables the MCP Apps runtime:
405
+ ```tsx
406
+ mcpApps: {
407
+ sandboxProxyUrl: 'http://localhost:6565/index.html',
408
+ displayMode: 'workspace', // 'workspace' | 'inline' (optional, auto-detects if omitted)
409
+ },
410
+ ```
411
+
412
+ 2. **`extensions`** — tells MCP servers that this client supports UI:
413
+ ```tsx
414
+ capabilities: {
415
+ extensions: {
416
+ 'io.modelcontextprotocol/ui': {
417
+ mimeTypes: ['text/html;profile=mcp-app'],
418
+ },
419
+ },
420
+ },
421
+ ```
422
+
423
+ Without both, MCP servers will not expose UI metadata on tool definitions and no apps will be created.
424
+
425
+ **Display modes:**
426
+
427
+ | Mode | Behavior |
428
+ |------|----------|
429
+ | `'inline'` | App renders inside the chat message flow |
430
+ | `'workspace'` | App opens in a separate io.Connect workspace window (falls back to inline if workspaces are unavailable) |
431
+
432
+ **Sandbox proxy** — MCP Apps run inside a sandboxed iframe. The `sandboxProxyUrl` points to an HTML file that bridges communication between the host and the app. This proxy page must be served alongside your application.
433
+
434
+ ---
435
+
436
+ ## Sampling & Elicitation
437
+
438
+ When an MCP server sends a sampling or elicitation request:
439
+
440
+ | Scenario | Behavior |
441
+ |----------|----------|
442
+ | **No custom handler** | io.Assist shows a built-in confirmation dialog (uses an io.Connect modal if available, otherwise an in-app overlay) |
443
+ | **Custom handler provided** | Your handler function runs instead — full control over UI and response |
444
+ | **Request from a background thread** | Automatically rejected (the user must be on the active thread the request targets) |
445
+
446
+ **Sampling** — the MCP server asks the client to generate a model response. The built-in handler shows a "Continue / Cancel" dialog. On accept, it calls the selected agent's `generate()` and returns the result as a `SamplingSuccessResponse`. On decline, it returns an error response.
447
+
448
+ **Elicitation** — the MCP server asks the client to collect user input. The built-in handler presents accept/decline/cancel options.
449
+
450
+ Custom handlers are configured under `aiWebConfig.mcp.clientsConfig.capabilities` — see the [advanced configuration example](#advanced--custom-handlers-mcp-apps-working-context) for the handler signatures.
451
+
452
+ ---
453
+
454
+ ## Prompt Icons
455
+
456
+ Each prompt can have an optional `iconResource`. Three formats are supported:
457
+
458
+ | Type | Example | Notes |
459
+ |------|---------|-------|
460
+ | `'svg'` | `'<svg xmlns="..." viewBox="0 0 24 24">...</svg>'` | Sanitized: `fill`, `width`, `height` stripped; hardcoded colors → `currentColor` |
461
+ | `'url'` | `'/icons/summarize.svg'` | Must be an absolute URL or absolute path from the document root |
462
+ | `'data-url'` | `'data:image/svg+xml;base64,...'` | Base64-encoded SVG, PNG, or JPEG |
463
+
464
+ Prompts without an icon show a default icon.
465
+
466
+ ---
467
+
468
+ ## Public API
469
+
470
+ The package exposes a deliberately small surface — one component and the two config types it consumes:
471
+
472
+ ```tsx
473
+ import { IoAssist } from '@interopio/io-assist-react';
474
+ import type { IoAssistStaticConfig, IoAssistDynamicConfig } from '@interopio/io-assist-react';
475
+ ```
476
+
477
+ | Export | Kind | Description |
478
+ |--------|------|-------------|
479
+ | `IoAssist` | Component | The root component. Takes `staticConfig` and `dynamicConfig` props. |
480
+ | `IoAssistStaticConfig` | Type | Static configuration shape for the `staticConfig` prop. |
481
+ | `IoAssistDynamicConfig` | Type | Runtime configuration shape for the `dynamicConfig` prop. |
482
+
483
+ The prompt, icon, and working-context shapes referenced in the tables above are structural — TypeScript infers them from the config-object literals you write, so you don't need to import them separately.
484
+
485
+ The stylesheet is exported from the `./styles` subpath:
486
+
487
+ ```css
488
+ @import "@interopio/io-assist-react/styles";
489
+ ```
490
+
491
+ ---
492
+
493
+ ## Related Packages
494
+
495
+ - [@interopio/ai-web](https://www.npmjs.com/package/@interopio/ai-web) — Core intelligence library
496
+ - [@interopio/io-assist-ng](https://www.npmjs.com/package/@interopio/io-assist-ng) — The Angular equivalent of this component
497
+ - [@interopio/browser](https://www.npmjs.com/package/@interopio/browser) — io.Connect Browser platform
498
+ - [@interopio/desktop](https://www.npmjs.com/package/@interopio/desktop) — io.Connect Desktop platform
499
+ - [@interopio/working-context](https://www.npmjs.com/package/@interopio/working-context) — Working context collection
500
+
501
+ ## License
502
+
503
+ MIT
package/changelog.md ADDED
@@ -0,0 +1,2 @@
1
+ 1.0.0
2
+ - feat: initial release
@@ -0,0 +1,12 @@
1
+ import { default as React } from 'react';
2
+ import { IoAssistStaticConfig, IoAssistDynamicConfig } from './types';
3
+ type Props = {
4
+ staticConfig: IoAssistStaticConfig;
5
+ dynamicConfig: IoAssistDynamicConfig;
6
+ };
7
+ /**
8
+ * Root IoAssist component.
9
+ * Wrap in your own router/auth shell and pass validated configs.
10
+ */
11
+ export declare function IoAssist({ staticConfig, dynamicConfig }: Props): React.JSX.Element;
12
+ export {};
@@ -0,0 +1,2 @@
1
+ import { IoAssistStoreInstance } from '../stores';
2
+ export declare function abortActiveStream(store: IoAssistStoreInstance): void;
@@ -0,0 +1,2 @@
1
+ import { IoAssistStoreInstance } from '../stores';
2
+ export declare function deleteThread(store: IoAssistStoreInstance, threadId: string): Promise<void>;
@@ -0,0 +1,13 @@
1
+ import { IoAiWeb } from '@interopio/ai-web';
2
+ import { ELICITATION_ACTION } from '../constants/modalActions';
3
+ type ElicitationResponse = {
4
+ action: typeof ELICITATION_ACTION.ACCEPT;
5
+ content: Record<string, unknown>;
6
+ } | {
7
+ action: typeof ELICITATION_ACTION.DECLINE;
8
+ } | {
9
+ action: typeof ELICITATION_ACTION.CANCEL;
10
+ };
11
+ export declare function selectElicitation(mcp: IoAiWeb.MCPConfig | undefined): (serverName: string, params: IoAiWeb.ElicitationRequestParams) => Promise<ElicitationResponse>;
12
+ export declare function handleElicitationRequest(serverName: string, request: IoAiWeb.ElicitationRequestParams): Promise<ElicitationResponse>;
13
+ export {};
@@ -0,0 +1,3 @@
1
+ import { IoAssistStoreInstance } from '../stores';
2
+ import { IoAssistDynamicConfig, IoAssistStaticConfig } from '../types';
3
+ export declare function initIoAiWeb(staticConfig: IoAssistStaticConfig, dynamicConfig: IoAssistDynamicConfig, store: IoAssistStoreInstance): Promise<void>;
@@ -0,0 +1,9 @@
1
+ import { IOConnectBrowser } from '@interopio/browser';
2
+ import { IoAssistStaticConfig } from '../types';
3
+ export type IoConnectStoreSetters = {
4
+ setIoConnectApi: (api: IOConnectBrowser.API) => void;
5
+ setIsIoConnectReady: (ready: boolean) => void;
6
+ setFavoritePromptNames: (names: string[]) => void;
7
+ setIsDarkMode: (dark: boolean) => void;
8
+ };
9
+ export declare function initIoConnect(config: IoAssistStaticConfig, store: IoConnectStoreSetters): Promise<void>;
@@ -0,0 +1,4 @@
1
+ import { IoAiWeb } from '@interopio/ai-web';
2
+ import { IoAssistStoreInstance } from '../stores';
3
+ import { IoAssistDynamicConfig } from '../types';
4
+ export declare function wireMcpAppEvents(ioIntelWeb: IoAiWeb.API, store: IoAssistStoreInstance, dynamicConfig: IoAssistDynamicConfig): void;
@@ -0,0 +1,2 @@
1
+ import { IoAssistStoreInstance } from '../stores';
2
+ export declare function newConversation(store: IoAssistStoreInstance): Promise<void>;
@@ -0,0 +1,3 @@
1
+ import { IoAiWeb } from '@interopio/ai-web';
2
+ import { IoAssistStoreInstance } from '../stores';
3
+ export declare function processResponseStream(runHandle: IoAiWeb.Agents.StreamResponse, threadId: string, store: IoAssistStoreInstance, isActiveThread: () => boolean): Promise<void>;
@@ -0,0 +1,2 @@
1
+ import { IoAssistStoreInstance } from '../stores';
2
+ export declare function renameThread(store: IoAssistStoreInstance, threadId: string, title: string): Promise<void>;
@@ -0,0 +1,5 @@
1
+ import { IoAiWeb } from '@interopio/ai-web';
2
+ type SamplingResponse = IoAiWeb.SamplingSuccessResponse | IoAiWeb.SamplingErrorResponse;
3
+ export declare function selectSampling(mcp: IoAiWeb.MCPConfig | undefined): (serverName: string, params: IoAiWeb.SamplingRequestParams) => Promise<SamplingResponse>;
4
+ export declare function handleSamplingRequest(serverName: string, request: IoAiWeb.SamplingRequestParams): Promise<SamplingResponse>;
5
+ export {};
@@ -0,0 +1,2 @@
1
+ import { IoAssistStoreInstance } from '../stores';
2
+ export declare function selectThread(store: IoAssistStoreInstance, threadId: string): Promise<void>;
@@ -0,0 +1,3 @@
1
+ import { IoAssistStoreInstance } from '../stores';
2
+ import { IoAssistDynamicConfig } from '../types';
3
+ export declare function sendUserMessage(store: IoAssistStoreInstance, text: string, dynamicConfig: IoAssistDynamicConfig): Promise<void>;
@@ -0,0 +1,7 @@
1
+ import { IoAssistStoreInstance } from '../stores';
2
+ /**
3
+ * Toggle a prompt's favorite status and persist the new list to
4
+ * `io.prefs`. The store mutation is optimistic; if `prefs.update` fails,
5
+ * the previous list is restored.
6
+ */
7
+ export declare function toggleFavoritePrompt(store: IoAssistStoreInstance, name: string): Promise<void>;
@@ -0,0 +1,2 @@
1
+ import { IoAssistStoreInstance } from '../stores';
2
+ export declare function toggleTool(store: IoAssistStoreInstance, name: string, enabled: boolean): Promise<void>;
@@ -0,0 +1,6 @@
1
+ import { default as React } from 'react';
2
+ /**
3
+ * Renders the currently-active panel (working-context / prompts / tools) inside
4
+ * a centered modal. Mirrors the io-assist-ng OverlayService + AppPanel pattern.
5
+ */
6
+ export declare const ActivePanelModal: React.FC;
@@ -0,0 +1,6 @@
1
+ import { default as React } from 'react';
2
+ type Props = {
3
+ showMessageArea: boolean;
4
+ };
5
+ export declare const AiDisclaimer: React.FC<Props>;
6
+ export {};
@@ -0,0 +1,2 @@
1
+ import { default as React } from 'react';
2
+ export declare const Chat: React.FC;
@@ -0,0 +1,8 @@
1
+ import { default as React } from 'react';
2
+ /**
3
+ * Async question-style dialog backed by `currentConfirmModal` store state:
4
+ * sampling consent, elicitation, mcp-replace. Renders `{heading, text, buttons}`
5
+ * config and resolves the promise returned by `showConfirmModal` with the
6
+ * clicked button id.
7
+ */
8
+ export declare const ConfirmModal: React.FC;
@@ -0,0 +1,6 @@
1
+ import { default as React } from 'react';
2
+ type Props = {
3
+ agentName: string;
4
+ };
5
+ export declare const WelcomeHeading: React.FC<Props>;
6
+ export {};
@@ -0,0 +1,2 @@
1
+ import { default as React } from 'react';
2
+ export declare const Header: React.FC;
@@ -0,0 +1,8 @@
1
+ import { default as React } from 'react';
2
+ type Props = {
3
+ onSend: (text: string) => void;
4
+ onAbort: () => void;
5
+ className?: string;
6
+ };
7
+ export declare const InputArea: React.FC<Props>;
8
+ export {};
@@ -0,0 +1,10 @@
1
+ import { default as React } from 'react';
2
+ import { UIAssistantMessage } from '../../types';
3
+ type Props = {
4
+ message: UIAssistantMessage;
5
+ isLast?: boolean;
6
+ onReload?: () => void;
7
+ isGenerating?: boolean;
8
+ };
9
+ export declare const AssistantMessage: React.FC<Props>;
10
+ export {};