@interopio/io-assist-ng 0.1.1-beta.0 → 1.0.1
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.
- package/README.internal.md +865 -0
- package/README.md +558 -139
- package/README.user.md +159 -0
- package/dist/README.md +558 -139
- package/dist/fesm2022/interopio-io-assist-ng.mjs +4388 -1940
- package/dist/fesm2022/interopio-io-assist-ng.mjs.map +1 -1
- package/dist/index.d.ts +123 -8
- package/dist/styles.css +1 -1
- package/package.json +26 -4
package/README.md
CHANGED
|
@@ -1,6 +1,26 @@
|
|
|
1
1
|
# @interopio/io-assist-ng
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A full-featured AI assistant component for Angular applications. Drop a single `<io-assist>` tag 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
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Conversational AI chat** — Streaming responses, markdown rendering, code highlighting
|
|
10
|
+
- **Persistent conversation threads** — Thread history with resume, rename, and delete
|
|
11
|
+
- **Prompt library** — Categorized pre-written prompts with favorites (persisted via IO Preferences)
|
|
12
|
+
- **MCP tool access** — Built-in io.Intelligence MCP server, extensible with remote and third-party servers
|
|
13
|
+
- **MCP Apps** — Custom HTML applications rendered inline in chat or in io.Connect workspace windows
|
|
14
|
+
- **Sampling & elicitation** — Built-in confirmation/input UI for MCP server requests (replaceable with custom handlers)
|
|
15
|
+
- **Working context** — Live data from io.Connect contexts passed to the agent with every message
|
|
16
|
+
- **Theming** — Automatic dark/light mode sync with io.Connect
|
|
17
|
+
|
|
18
|
+
## Prerequisites
|
|
19
|
+
|
|
20
|
+
- **Angular** 20.3+
|
|
21
|
+
- **Node.js** 20.19+ (< 22)
|
|
22
|
+
- **npm** 10+
|
|
23
|
+
- An **AG-UI Protocol compatible agent server** (e.g. [Mastra](https://mastra.ai/))
|
|
4
24
|
|
|
5
25
|
## Installation
|
|
6
26
|
|
|
@@ -8,211 +28,610 @@ Angular library for integrating io.Intelligence AI assistance capabilities into
|
|
|
8
28
|
npm install @interopio/io-assist-ng
|
|
9
29
|
```
|
|
10
30
|
|
|
11
|
-
|
|
31
|
+
**Install at least one platform package** — you always need to import and pass the factory in your `connectConfig`:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
# For io.Connect Browser (most common)
|
|
35
|
+
npm install @interopio/browser
|
|
36
|
+
|
|
37
|
+
# For io.Connect Desktop
|
|
38
|
+
npm install @interopio/desktop
|
|
39
|
+
|
|
40
|
+
# For both (if your app supports both environments)
|
|
41
|
+
npm install @interopio/browser @interopio/desktop
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
The following packages are bundled as `dependencies` and are installed automatically:
|
|
45
|
+
|
|
46
|
+
> `zod`, `ngx-remark`, `remark-gfm`, `remark-parse`, `unified`, `@interopio/ai-web`, `@interopio/ng`, `@interopio/working-context`, `@ngrx/store`, `@ngrx/effects`, `@ngrx/store-devtools`, `rxjs`
|
|
47
|
+
|
|
48
|
+
The following are `peerDependencies` and must be present in your project. They are usually already installed in any Angular 20+ project:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
npm install @angular/cdk @angular/common @angular/core @angular/forms @angular/platform-browser
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Agent Server
|
|
57
|
+
|
|
58
|
+
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/).
|
|
59
|
+
|
|
60
|
+
### Quick setup with Mastra
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
npx create-mastra@latest
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
This scaffolds a fully working Mastra project. Follow the prompts, then start the server:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
npm run dev
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
By default the server runs on `http://localhost:4111` — the same URL used in the Quickstart examples below.
|
|
73
|
+
|
|
74
|
+
**Required environment variables:**
|
|
75
|
+
|
|
76
|
+
```env
|
|
77
|
+
# At least one LLM provider key
|
|
78
|
+
OPENAI_API_KEY=your-key
|
|
79
|
+
ANTHROPIC_API_KEY=your-key
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
> For full Mastra documentation — including custom agents, tools, memory, and deployment — see [mastra.ai/docs](https://mastra.ai/docs).
|
|
83
|
+
|
|
84
|
+
## Quickstart
|
|
12
85
|
|
|
13
|
-
|
|
14
|
-
- Node.js 20.19+ (< 22)
|
|
15
|
-
- npm 10.0.0 or higher
|
|
86
|
+
### New Angular project
|
|
16
87
|
|
|
17
|
-
|
|
88
|
+
If you don't have an Angular project yet, create one first:
|
|
18
89
|
|
|
19
|
-
|
|
90
|
+
```bash
|
|
91
|
+
npm install -g @angular/cli
|
|
92
|
+
ng new my-app
|
|
93
|
+
cd my-app
|
|
94
|
+
npm install @interopio/io-assist-ng @interopio/browser
|
|
95
|
+
```
|
|
20
96
|
|
|
21
|
-
|
|
97
|
+
> See the full Angular setup guide at [angular.dev/installation](https://angular.dev/installation).
|
|
98
|
+
|
|
99
|
+
### Existing Angular project
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
npm install @interopio/io-assist-ng @interopio/browser
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
### 1. Add the stylesheet
|
|
108
|
+
|
|
109
|
+
```css title="src/styles.css"
|
|
110
|
+
@import "@interopio/io-assist-ng/styles.css";
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Or in `angular.json`:
|
|
22
114
|
|
|
23
|
-
**Option A: In `angular.json`**
|
|
24
115
|
```json
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
"
|
|
28
|
-
|
|
29
|
-
"build": {
|
|
30
|
-
"options": {
|
|
31
|
-
"styles": [
|
|
32
|
-
"node_modules/@interopio/io-assist-ng/styles.css",
|
|
33
|
-
"src/styles.css"
|
|
34
|
-
]
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
}
|
|
116
|
+
"styles": [
|
|
117
|
+
"node_modules/@interopio/io-assist-ng/styles.css",
|
|
118
|
+
"src/styles.css"
|
|
119
|
+
]
|
|
41
120
|
```
|
|
42
121
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
122
|
+
### 2. Configure providers
|
|
123
|
+
|
|
124
|
+
```typescript title="src/app/app.config.ts"
|
|
125
|
+
import { ApplicationConfig } from '@angular/core';
|
|
126
|
+
import { provideIoAssist } from '@interopio/io-assist-ng';
|
|
127
|
+
import IOBrowser from '@interopio/browser';
|
|
128
|
+
|
|
129
|
+
export const appConfig: ApplicationConfig = {
|
|
130
|
+
providers: [
|
|
131
|
+
provideIoAssist({
|
|
132
|
+
connectConfig: {
|
|
133
|
+
browser: {
|
|
134
|
+
factory: IOBrowser,
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
aiWebConfig: {
|
|
138
|
+
agentServer: {
|
|
139
|
+
baseUrl: 'http://localhost:4111',
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
}),
|
|
143
|
+
],
|
|
144
|
+
};
|
|
46
145
|
```
|
|
47
146
|
|
|
48
|
-
###
|
|
147
|
+
### 3. Add the component
|
|
49
148
|
|
|
50
|
-
|
|
149
|
+
The component requires a `[config]` input with the current user's identity. Pass a signal so the assistant can react to auth state changes:
|
|
51
150
|
|
|
52
|
-
```typescript
|
|
53
|
-
import { Component } from '@angular/core';
|
|
54
|
-
import { IoAssist } from '@interopio/io-assist-ng';
|
|
151
|
+
```typescript title="src/app/app.component.ts"
|
|
152
|
+
import { Component, signal } from '@angular/core';
|
|
153
|
+
import { IoAssist, IoAssistDynamicConfig } from '@interopio/io-assist-ng';
|
|
55
154
|
|
|
56
155
|
@Component({
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
template: `
|
|
61
|
-
<io-assist [config]="assistConfig"></io-assist>
|
|
62
|
-
`
|
|
156
|
+
selector: 'app-root',
|
|
157
|
+
imports: [IoAssist],
|
|
158
|
+
template: `<io-assist [config]="dynamicConfig()" />`,
|
|
63
159
|
})
|
|
64
160
|
export class AppComponent {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
161
|
+
readonly dynamicConfig = signal<IoAssistDynamicConfig>({
|
|
162
|
+
// id: Your access/auth token of choice
|
|
163
|
+
// name: UI name tha will be displayed
|
|
164
|
+
user: { id: 'yourIdOfChoice', name: 'Jane Doe' },
|
|
165
|
+
agentServer: {
|
|
166
|
+
headers: {
|
|
167
|
+
Authorization: `Bearer ${import.meta.env.VITE_AUTH_TOKEN}`,
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
});
|
|
68
171
|
}
|
|
69
172
|
```
|
|
70
173
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
The `IoAssist` component accepts a configuration object via the `[config]` input:
|
|
74
|
-
|
|
75
|
-
```typescript
|
|
76
|
-
import { IoAssistTempConfig } from '@interopio/io-assist-ng';
|
|
174
|
+
### 4. Run
|
|
77
175
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
apiEndpoint: 'https://your-api-endpoint.com',
|
|
81
|
-
theme: 'light', // or 'dark'
|
|
82
|
-
// Add other configuration options as needed
|
|
83
|
-
};
|
|
176
|
+
```bash
|
|
177
|
+
ng serve
|
|
84
178
|
```
|
|
85
179
|
|
|
86
|
-
|
|
180
|
+
Open http://localhost:4200. **io.Assist is live.**
|
|
87
181
|
|
|
88
|
-
|
|
182
|
+
---
|
|
89
183
|
|
|
90
|
-
|
|
184
|
+
### Quickstart with Login
|
|
91
185
|
|
|
92
|
-
|
|
93
|
-
```html
|
|
94
|
-
<io-assist
|
|
95
|
-
[config]="assistConfig"
|
|
96
|
-
></io-assist>
|
|
97
|
-
```
|
|
186
|
+
This pattern shows how to pair io.Assist with a login flow — the user's identity is only passed to the assistant after authentication.
|
|
98
187
|
|
|
99
|
-
|
|
100
|
-
- `config: IoAssistTempConfig` - Configuration object for the assistant
|
|
188
|
+
Follow steps 1–2 from the basic quickstart, then:
|
|
101
189
|
|
|
102
|
-
|
|
190
|
+
**Login service**
|
|
103
191
|
|
|
104
|
-
|
|
192
|
+
```typescript title="src/app/auth/auth.service.ts"
|
|
193
|
+
import { Injectable, signal } from '@angular/core';
|
|
105
194
|
|
|
106
|
-
|
|
195
|
+
@Injectable({ providedIn: 'root' })
|
|
196
|
+
export class AuthService {
|
|
197
|
+
private readonly _userId = signal<string>('');
|
|
198
|
+
readonly userId = this._userId.asReadonly();
|
|
107
199
|
|
|
108
|
-
|
|
200
|
+
login(userId: string, password: string): boolean {
|
|
201
|
+
// Replace with your own authentication logic
|
|
202
|
+
const isValid = password === 'secret';
|
|
203
|
+
if (isValid) this._userId.set(userId);
|
|
204
|
+
return isValid;
|
|
205
|
+
}
|
|
109
206
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
--io-assist-background: #your-background;
|
|
114
|
-
/* Add other custom variables */
|
|
207
|
+
logout(): void {
|
|
208
|
+
this._userId.set('');
|
|
209
|
+
}
|
|
115
210
|
}
|
|
116
211
|
```
|
|
117
212
|
|
|
118
|
-
|
|
213
|
+
**Login component**
|
|
119
214
|
|
|
120
|
-
|
|
215
|
+
```typescript title="src/app/login/login.component.ts"
|
|
216
|
+
import { Component, inject, signal } from '@angular/core';
|
|
217
|
+
import { Router } from '@angular/router';
|
|
218
|
+
import { AuthService } from '../auth/auth.service';
|
|
121
219
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
220
|
+
@Component({
|
|
221
|
+
selector: 'app-login',
|
|
222
|
+
template: `
|
|
223
|
+
<input [value]="username()" (input)="username.set($any($event.target).value)" placeholder="Username" />
|
|
224
|
+
<input [value]="password()" (input)="password.set($any($event.target).value)" type="password" placeholder="Password" />
|
|
225
|
+
<button (click)="submit()">Sign in</button>
|
|
226
|
+
`,
|
|
227
|
+
})
|
|
228
|
+
export class LoginComponent {
|
|
229
|
+
private readonly _auth = inject(AuthService);
|
|
230
|
+
private readonly _router = inject(Router);
|
|
231
|
+
|
|
232
|
+
protected readonly username = signal('');
|
|
233
|
+
protected readonly password = signal('');
|
|
234
|
+
|
|
235
|
+
protected submit(): void {
|
|
236
|
+
const success = this._auth.login(this.username(), this.password());
|
|
237
|
+
if (success) this._router.navigate(['/assistant']);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
**Assistant component** — pass the user identity as `[config]`
|
|
243
|
+
|
|
244
|
+
```typescript title="src/app/assistant/assistant.component.ts"
|
|
245
|
+
import { Component, computed, inject } from '@angular/core';
|
|
246
|
+
import { IoAssist, IoAssistDynamicConfig } from '@interopio/io-assist-ng';
|
|
247
|
+
import { AuthService } from '../auth/auth.service';
|
|
125
248
|
|
|
126
249
|
@Component({
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
template: `
|
|
131
|
-
<div class="dashboard">
|
|
132
|
-
<h1>My Dashboard</h1>
|
|
133
|
-
<io-assist [config]="config"></io-assist>
|
|
134
|
-
</div>
|
|
135
|
-
`
|
|
250
|
+
selector: 'app-assistant',
|
|
251
|
+
imports: [IoAssist],
|
|
252
|
+
template: `<io-assist [config]="dynamicConfig()" />`,
|
|
136
253
|
})
|
|
137
|
-
export class
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
254
|
+
export class AssistantComponent {
|
|
255
|
+
private readonly _auth = inject(AuthService);
|
|
256
|
+
|
|
257
|
+
protected readonly dynamicConfig = computed<IoAssistDynamicConfig>(() => ({
|
|
258
|
+
user: { id: this._auth.userId() },
|
|
259
|
+
}));
|
|
142
260
|
}
|
|
143
261
|
```
|
|
144
262
|
|
|
145
|
-
|
|
263
|
+
Once the user logs in, `dynamicConfig` updates and io.Assist loads threads scoped to that user.
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
### What you get with the minimal config
|
|
146
268
|
|
|
147
|
-
|
|
148
|
-
- Firefox (latest 2 versions)
|
|
149
|
-
- Safari (latest 2 versions)
|
|
269
|
+
With just the three required fields (`user`, `connectConfig`, `aiWebConfig.agentServer`), io.Assist provides:
|
|
150
270
|
|
|
151
|
-
|
|
271
|
+
- Full conversational AI chat with streaming markdown responses
|
|
272
|
+
- Persistent conversation threads (scoped to `user.id`)
|
|
273
|
+
- Automatic agent selection (first available agent from your server)
|
|
274
|
+
- Built-in sampling and elicitation UI panels (confirmation dialogs when MCP servers request them)
|
|
275
|
+
- Built-in io.Intelligence MCP server connection (local mode)
|
|
276
|
+
- Dark/light theme sync with io.Connect
|
|
277
|
+
- Auto-injected fonts and syntax highlighting
|
|
152
278
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
279
|
+
No prompts, no working context, and no MCP Apps — those require additional configuration below.
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
## Configuration
|
|
157
284
|
|
|
158
|
-
|
|
285
|
+
io.Assist uses two separate configuration objects:
|
|
159
286
|
|
|
160
|
-
|
|
287
|
+
- **`IoAssistStaticConfig`** — passed to `provideIoAssist()` at application bootstrap. Contains infrastructure settings that don't change at runtime.
|
|
288
|
+
- **`IoAssistDynamicConfig`** — passed as `[config]` input to `<io-assist>` in your template. Contains the active user's identity, which may only be known after login.
|
|
161
289
|
|
|
162
|
-
|
|
290
|
+
### Static configuration (`IoAssistStaticConfig`)
|
|
291
|
+
|
|
292
|
+
Passed to `provideIoAssist()`. Validated at bootstrap with Zod — throws if invalid.
|
|
293
|
+
|
|
294
|
+
**Required fields**
|
|
295
|
+
|
|
296
|
+
| Field | Type | Description |
|
|
297
|
+
|-------|------|-------------|
|
|
298
|
+
| `connectConfig` | `IOConnectNgSettings` | io.Connect platform settings. Must include `browser` or `desktop`. |
|
|
299
|
+
| `aiWebConfig.agentServer.baseUrl` | `string` | Base URL of your AG-UI compatible agent server. |
|
|
300
|
+
|
|
301
|
+
**Optional fields**
|
|
302
|
+
|
|
303
|
+
| Field | Type | Description |
|
|
304
|
+
|-------|------|-------------|
|
|
305
|
+
| `aiWebConfig.agentServer.retries` | `number` | Number of retry attempts on failure. |
|
|
306
|
+
| `aiWebConfig.agentServer.backoffMs` | `number` | Initial backoff delay in milliseconds. |
|
|
307
|
+
| `aiWebConfig.agentServer.maxBackoffMs` | `number` | Maximum backoff delay. |
|
|
308
|
+
| `aiWebConfig.agentServer.credentials` | `'omit' \| 'same-origin' \| 'include'` | Fetch credentials mode. |
|
|
309
|
+
| `aiWebConfig.mcp` | `object` | MCP configuration — remote servers, MCP Apps, sampling/elicitation overrides. |
|
|
310
|
+
| `defaultAgentName` | `string` | Agent to select on startup. Falls back to first available if not found. |
|
|
311
|
+
| `defaultPrompts` | `IoAssistPromptCategory[]` | Categorized prompt library entries. |
|
|
312
|
+
| `workingContext` | `object` | Live context collection from io.Connect. |
|
|
313
|
+
|
|
314
|
+
### Dynamic configuration (`IoAssistDynamicConfig`)
|
|
315
|
+
|
|
316
|
+
Passed as `[config]` input to `<io-assist>` in your template. Validated in `ngOnInit` with Zod — throws `ZodError` if invalid. Typically computed from your authentication state:
|
|
163
317
|
|
|
164
318
|
```typescript
|
|
165
|
-
|
|
319
|
+
protected readonly dynamicConfig = computed<IoAssistDynamicConfig>(() => ({
|
|
320
|
+
user: { id: this._auth.userId(), name: this._auth.displayName() },
|
|
321
|
+
}));
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
```html
|
|
325
|
+
<io-assist [config]="dynamicConfig()" />
|
|
166
326
|
```
|
|
167
327
|
|
|
168
|
-
|
|
328
|
+
| Field | Type | Description |
|
|
329
|
+
|-------|------|-------------|
|
|
330
|
+
| `user.id` | `string` | **Required.** Unique user identifier. Scopes conversation threads — each user sees only their own threads. |
|
|
331
|
+
| `user.name` | `string?` | Display name shown in the chat UI and thread history. |
|
|
332
|
+
| `agentServer.headers` | `Record<string, string>?` | Request headers sent with every agent call. Use for auth tokens or per-user context. |
|
|
169
333
|
|
|
170
|
-
|
|
334
|
+
---
|
|
171
335
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
336
|
+
## Configuration Examples
|
|
337
|
+
|
|
338
|
+
### Standard — with prompts and named agent
|
|
339
|
+
|
|
340
|
+
```typescript title="app.config.ts"
|
|
341
|
+
import { ApplicationConfig } from '@angular/core';
|
|
342
|
+
import { provideIoAssist } from '@interopio/io-assist-ng';
|
|
343
|
+
import IOBrowser from '@interopio/browser';
|
|
344
|
+
|
|
345
|
+
export const appConfig: ApplicationConfig = {
|
|
346
|
+
providers: [
|
|
347
|
+
provideIoAssist({
|
|
348
|
+
connectConfig: {
|
|
349
|
+
browser: { factory: IOBrowser },
|
|
350
|
+
},
|
|
351
|
+
aiWebConfig: {
|
|
352
|
+
agentServer: {
|
|
353
|
+
baseUrl: 'http://localhost:4111',
|
|
354
|
+
},
|
|
355
|
+
},
|
|
356
|
+
defaultAgentName: 'my-agent',
|
|
357
|
+
defaultPrompts: [
|
|
358
|
+
{
|
|
359
|
+
category: 'General',
|
|
360
|
+
prompts: [
|
|
361
|
+
{ name: 'Summarize', prompt: 'Please summarize the following content:' },
|
|
362
|
+
{ name: 'Explain', prompt: 'Please explain this in simple terms:' },
|
|
363
|
+
],
|
|
364
|
+
},
|
|
365
|
+
{
|
|
366
|
+
category: 'Code',
|
|
367
|
+
prompts: [
|
|
368
|
+
{ name: 'Review Code', prompt: 'Please review this code and suggest improvements:' },
|
|
369
|
+
{
|
|
370
|
+
name: 'Add Comments',
|
|
371
|
+
prompt: 'Annotate this code with detailed comments:',
|
|
372
|
+
iconResource: {
|
|
373
|
+
type: 'svg',
|
|
374
|
+
data: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="..."/></svg>',
|
|
375
|
+
},
|
|
376
|
+
},
|
|
377
|
+
],
|
|
378
|
+
},
|
|
379
|
+
],
|
|
380
|
+
}),
|
|
381
|
+
],
|
|
382
|
+
};
|
|
177
383
|
```
|
|
178
384
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
385
|
+
**What this adds over minimal:**
|
|
386
|
+
|
|
387
|
+
- **Named agent** pre-selected at startup
|
|
388
|
+
- **Prompt library** with two categories — users can browse, search, and favorite prompts
|
|
389
|
+
|
|
390
|
+
### Advanced — custom handlers, MCP Apps, working context
|
|
391
|
+
|
|
392
|
+
```typescript title="app.config.ts"
|
|
393
|
+
import { ApplicationConfig } from '@angular/core';
|
|
394
|
+
import { provideIoAssist } from '@interopio/io-assist-ng';
|
|
395
|
+
import { IoAiWeb } from '@interopio/ai-web';
|
|
396
|
+
import IOBrowser from '@interopio/browser';
|
|
397
|
+
import { IoIntelWorkingContextFactory, IoIntelWorkingContext } from '@interopio/working-context';
|
|
398
|
+
|
|
399
|
+
export const appConfig: ApplicationConfig = {
|
|
400
|
+
providers: [
|
|
401
|
+
provideIoAssist({
|
|
402
|
+
connectConfig: {
|
|
403
|
+
browser: { factory: IOBrowser },
|
|
404
|
+
},
|
|
405
|
+
aiWebConfig: {
|
|
406
|
+
agentServer: {
|
|
407
|
+
baseUrl: 'http://localhost:4111',
|
|
408
|
+
},
|
|
409
|
+
mcp: {
|
|
410
|
+
// Custom sampling handler — replaces the built-in confirmation panel
|
|
411
|
+
clientsConfig: {
|
|
412
|
+
enforceStrictCapabilities: false,
|
|
413
|
+
capabilities: {
|
|
414
|
+
sampling: {
|
|
415
|
+
handler: async (
|
|
416
|
+
serverId: string,
|
|
417
|
+
params: IoAiWeb.SamplingRequestParams,
|
|
418
|
+
): Promise<IoAiWeb.SamplingSuccessResponse> => {
|
|
419
|
+
// Your custom logic — show your own UI, call your own APIs, etc.
|
|
420
|
+
return {
|
|
421
|
+
model: 'gpt-4',
|
|
422
|
+
role: 'assistant',
|
|
423
|
+
content: { type: 'text', text: 'Custom sampling response' },
|
|
424
|
+
stopReason: 'endTurn',
|
|
425
|
+
};
|
|
426
|
+
},
|
|
427
|
+
},
|
|
428
|
+
elicitation: {
|
|
429
|
+
handler: async (
|
|
430
|
+
serverId: string,
|
|
431
|
+
params: IoAiWeb.ElicitationRequestParams,
|
|
432
|
+
): Promise<IoAiWeb.ElicitationResponse> => {
|
|
433
|
+
// Your custom logic — build a form, collect user input, etc.
|
|
434
|
+
return { action: 'accept', content: { confirmed: true } };
|
|
435
|
+
},
|
|
436
|
+
},
|
|
437
|
+
// Required for MCP Apps
|
|
438
|
+
extensions: {
|
|
439
|
+
'io.modelcontextprotocol/ui': {
|
|
440
|
+
mimeTypes: ['text/html;profile=mcp-app'],
|
|
441
|
+
},
|
|
442
|
+
},
|
|
443
|
+
},
|
|
444
|
+
},
|
|
445
|
+
// MCP Apps — interactive UI panels in chat or workspace windows
|
|
446
|
+
mcpApps: {
|
|
447
|
+
sandboxProxyUrl: 'http://localhost:6565/index.html',
|
|
448
|
+
displayMode: 'workspace', // or 'inline'
|
|
449
|
+
},
|
|
450
|
+
// Remote MCP servers
|
|
451
|
+
ioIntel: {
|
|
452
|
+
remote: {
|
|
453
|
+
streamableHttp: {
|
|
454
|
+
url: 'http://localhost:8989/mcp',
|
|
455
|
+
name: 'remote-io-mcp-server',
|
|
456
|
+
},
|
|
457
|
+
},
|
|
458
|
+
},
|
|
459
|
+
remoteServers: [
|
|
460
|
+
{
|
|
461
|
+
streamableHttp: {
|
|
462
|
+
url: 'http://localhost:8081/mcp',
|
|
463
|
+
name: 'third-party-server',
|
|
464
|
+
},
|
|
465
|
+
},
|
|
466
|
+
],
|
|
467
|
+
},
|
|
468
|
+
},
|
|
469
|
+
defaultAgentName: 'my-agent',
|
|
470
|
+
defaultPrompts: [
|
|
471
|
+
{
|
|
472
|
+
category: 'General',
|
|
473
|
+
prompts: [
|
|
474
|
+
{ name: 'Summarize', prompt: 'Please summarize the following content:' },
|
|
475
|
+
],
|
|
476
|
+
},
|
|
477
|
+
],
|
|
478
|
+
workingContext: {
|
|
479
|
+
factory: IoIntelWorkingContextFactory,
|
|
480
|
+
config: {
|
|
481
|
+
schema: {
|
|
482
|
+
userId: {
|
|
483
|
+
type: 'string',
|
|
484
|
+
description: "Current user's identifier",
|
|
485
|
+
source: {
|
|
486
|
+
context: {
|
|
487
|
+
location: { global: { names: ['UserSession'] } },
|
|
488
|
+
path: 'user.id',
|
|
489
|
+
},
|
|
490
|
+
},
|
|
491
|
+
},
|
|
492
|
+
selectedClient: {
|
|
493
|
+
type: 'string',
|
|
494
|
+
description: 'Client currently selected in the workspace',
|
|
495
|
+
source: {
|
|
496
|
+
context: {
|
|
497
|
+
location: { workspace: {} },
|
|
498
|
+
path: 'client.name',
|
|
499
|
+
},
|
|
500
|
+
},
|
|
501
|
+
},
|
|
502
|
+
},
|
|
503
|
+
} as IoIntelWorkingContext.Config,
|
|
504
|
+
},
|
|
505
|
+
}),
|
|
506
|
+
],
|
|
507
|
+
};
|
|
184
508
|
```
|
|
185
509
|
|
|
186
|
-
|
|
510
|
+
**What this adds over standard:**
|
|
187
511
|
|
|
188
|
-
|
|
512
|
+
- **Custom sampling handler** — replaces the built-in confirmation panel. When an MCP server makes a sampling request, your handler runs instead.
|
|
513
|
+
- **Custom elicitation handler** — replaces the built-in elicitation panel. When an MCP server requests user input, your handler runs instead.
|
|
514
|
+
- **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.
|
|
515
|
+
- **Remote MCP servers** — switch io.Intelligence MCP to a remote endpoint and/or add third-party MCP servers.
|
|
516
|
+
- **Working context** — io.Assist reads live data from io.Connect contexts and passes it to the agent with every message.
|
|
189
517
|
|
|
190
|
-
|
|
518
|
+
> **Component usage:** In all examples above, pair `provideIoAssist()` with `<io-assist [config]="dynamicConfig()" />` in your template. Refer to the [Quickstart with Login](#quickstart-with-login) section for a full component example.
|
|
191
519
|
|
|
192
|
-
|
|
193
|
-
- Angular 20.3
|
|
194
|
-
- TailwindCSS 4.1
|
|
195
|
-
- TypeScript 5.x
|
|
520
|
+
---
|
|
196
521
|
|
|
197
|
-
##
|
|
522
|
+
## MCP Apps
|
|
198
523
|
|
|
199
|
-
|
|
200
|
-
- GitHub: [io.Intelligence JS Repository]
|
|
201
|
-
- Documentation: [Coming Soon]
|
|
202
|
-
- Issues: [GitHub Issues]
|
|
524
|
+
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.
|
|
203
525
|
|
|
204
|
-
|
|
526
|
+
**Requirements** — two config sections must both be present:
|
|
527
|
+
|
|
528
|
+
1. **`mcpApps`** — enables the MCP Apps runtime:
|
|
529
|
+
```typescript
|
|
530
|
+
mcpApps: {
|
|
531
|
+
sandboxProxyUrl: 'http://localhost:6565/index.html',
|
|
532
|
+
displayMode: 'workspace', // 'workspace' | 'inline' (optional, auto-detects if omitted)
|
|
533
|
+
},
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
2. **`extensions`** — tells MCP servers that this client supports UI:
|
|
537
|
+
```typescript
|
|
538
|
+
capabilities: {
|
|
539
|
+
extensions: {
|
|
540
|
+
'io.modelcontextprotocol/ui': {
|
|
541
|
+
mimeTypes: ['text/html;profile=mcp-app'],
|
|
542
|
+
},
|
|
543
|
+
},
|
|
544
|
+
},
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
Without both, MCP servers will not expose UI metadata on tool definitions and no apps will be created.
|
|
548
|
+
|
|
549
|
+
**Display modes:**
|
|
550
|
+
|
|
551
|
+
| Mode | Behavior |
|
|
552
|
+
|------|----------|
|
|
553
|
+
| `'inline'` | App renders inside the chat message flow |
|
|
554
|
+
| `'workspace'` | App opens in a separate io.Connect workspace window (falls back to inline if workspaces unavailable) |
|
|
555
|
+
|
|
556
|
+
**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.
|
|
557
|
+
|
|
558
|
+
---
|
|
559
|
+
|
|
560
|
+
## Sampling & Elicitation
|
|
561
|
+
|
|
562
|
+
When an MCP server sends a sampling or elicitation request:
|
|
563
|
+
|
|
564
|
+
| Scenario | Behavior |
|
|
565
|
+
|----------|----------|
|
|
566
|
+
| **No custom handler** | io.Assist shows a built-in confirmation panel (uses io.Connect modal if available, otherwise an overlay panel) |
|
|
567
|
+
| **Custom handler provided** | Your handler function runs instead — full control over UI and response |
|
|
568
|
+
| **Request from background thread** | Automatically rejected (user must be on the active thread) |
|
|
569
|
+
|
|
570
|
+
**Sampling** — the MCP server asks the client to generate a model response. The built-in handler shows a "Permission to proceed" dialog. On accept, it calls your agent server and returns the result.
|
|
205
571
|
|
|
206
|
-
|
|
572
|
+
**Elicitation** — the MCP server asks the client to collect user input via a form schema. The built-in handler presents accept/decline options.
|
|
207
573
|
|
|
208
|
-
|
|
574
|
+
See the advanced configuration example above for custom handler signatures.
|
|
209
575
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
576
|
+
---
|
|
577
|
+
|
|
578
|
+
## Public API
|
|
579
|
+
|
|
580
|
+
```typescript
|
|
581
|
+
import { IoAssist, provideIoAssist } from '@interopio/io-assist-ng';
|
|
582
|
+
import type {
|
|
583
|
+
IoAssistStaticConfig,
|
|
584
|
+
IoAssistDynamicConfig,
|
|
585
|
+
AIWebConfig,
|
|
586
|
+
IoAssistUserConfig,
|
|
587
|
+
IO_ASSIST_CONFIG,
|
|
588
|
+
IO_ASSIST_DYNAMIC_CONFIG,
|
|
589
|
+
IoAssistPrompt,
|
|
590
|
+
IoAssistPromptCategory,
|
|
591
|
+
IconResource,
|
|
592
|
+
IconType,
|
|
593
|
+
} from '@interopio/io-assist-ng';
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
| Export | Kind | Description |
|
|
597
|
+
|--------|------|-------------|
|
|
598
|
+
| `IoAssist` | Component | The `<io-assist>` root component. Requires `[config]` input. |
|
|
599
|
+
| `provideIoAssist(config)` | Function | Registers all providers — call once in `app.config.ts` |
|
|
600
|
+
| `IoAssistStaticConfig` | Type | Static configuration shape passed to `provideIoAssist()` |
|
|
601
|
+
| `IoAssistDynamicConfig` | Type | Runtime configuration shape passed as `[config]` to `<io-assist>` |
|
|
602
|
+
| `AIWebConfig` | Type | Agent server + MCP config shape |
|
|
603
|
+
| `IoAssistUserConfig` | Type | `{ id: string; name?: string }` |
|
|
604
|
+
| `IO_ASSIST_CONFIG` | InjectionToken | DI token for the validated static config |
|
|
605
|
+
| `IO_ASSIST_DYNAMIC_CONFIG` | InjectionToken | DI token for the `WritableSignal<IoAssistDynamicConfig>` (internal use) |
|
|
606
|
+
| `IoAssistPrompt` | Type | Single prompt definition |
|
|
607
|
+
| `IoAssistPromptCategory` | Type | Category with array of prompts |
|
|
608
|
+
| `IconResource` | Type | `{ type: IconType; data: string }` |
|
|
609
|
+
| `IconType` | Type | `'svg' \| 'url' \| 'data-url'` |
|
|
610
|
+
|
|
611
|
+
---
|
|
612
|
+
|
|
613
|
+
## Prompt Icons
|
|
614
|
+
|
|
615
|
+
Each prompt can have an optional `iconResource`. Three formats are supported:
|
|
616
|
+
|
|
617
|
+
| Type | Example | Notes |
|
|
618
|
+
|------|---------|-------|
|
|
619
|
+
| `'svg'` | `'<svg xmlns="..." viewBox="0 0 24 24">...</svg>'` | Auto-sanitized: `fill`, `width`, `height` stripped; hardcoded colors → `currentColor` |
|
|
620
|
+
| `'url'` | `'/icons/summarize.svg'` | Must be an absolute URL or absolute path from document root |
|
|
621
|
+
| `'data-url'` | `'data:image/svg+xml;base64,...'` | Base64-encoded SVG, PNG, or JPEG |
|
|
622
|
+
|
|
623
|
+
Prompts without an icon show a default icon.
|
|
215
624
|
|
|
216
625
|
---
|
|
217
626
|
|
|
218
|
-
|
|
627
|
+
## Related Packages
|
|
628
|
+
|
|
629
|
+
- [@interopio/ai-web](https://www.npmjs.com/package/@interopio/ai-web) — Core intelligence library
|
|
630
|
+
- [@interopio/ng](https://www.npmjs.com/package/@interopio/ng) — io.Connect Angular integration
|
|
631
|
+
- [@interopio/browser](https://www.npmjs.com/package/@interopio/browser) — io.Connect Browser platform
|
|
632
|
+
- [@interopio/desktop](https://www.npmjs.com/package/@interopio/desktop) — io.Connect Desktop platform
|
|
633
|
+
- [@interopio/working-context](https://www.npmjs.com/package/@interopio/working-context) — Working context collection
|
|
634
|
+
|
|
635
|
+
## License
|
|
636
|
+
|
|
637
|
+
[MIT](./LICENSE)
|