@netbirdio/explain 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.
- package/README.md +402 -0
- package/dist/client/AIAssistantProvider.d.ts +21 -0
- package/dist/client/AIAssistantProvider.d.ts.map +1 -0
- package/dist/client/AIAssistantProvider.js +198 -0
- package/dist/client/AIAssistantProvider.js.map +1 -0
- package/dist/client/AIChatBot.d.ts +10 -0
- package/dist/client/AIChatBot.d.ts.map +1 -0
- package/dist/client/AIChatBot.js +139 -0
- package/dist/client/AIChatBot.js.map +1 -0
- package/dist/client/AIFloatingButton.d.ts +7 -0
- package/dist/client/AIFloatingButton.d.ts.map +1 -0
- package/dist/client/AIFloatingButton.js +16 -0
- package/dist/client/AIFloatingButton.js.map +1 -0
- package/dist/client/index.d.ts +5 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +4 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/styles.d.ts +51 -0
- package/dist/client/styles.d.ts.map +1 -0
- package/dist/client/styles.js +317 -0
- package/dist/client/styles.js.map +1 -0
- package/dist/server/handler.d.ts +38 -0
- package/dist/server/handler.d.ts.map +1 -0
- package/dist/server/handler.js +117 -0
- package/dist/server/handler.js.map +1 -0
- package/dist/server/index.d.ts +6 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +4 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/providers/anthropic.d.ts +9 -0
- package/dist/server/providers/anthropic.d.ts.map +1 -0
- package/dist/server/providers/anthropic.js +40 -0
- package/dist/server/providers/anthropic.js.map +1 -0
- package/dist/server/providers/openai.d.ts +9 -0
- package/dist/server/providers/openai.d.ts.map +1 -0
- package/dist/server/providers/openai.js +46 -0
- package/dist/server/providers/openai.js.map +1 -0
- package/dist/server/providers/types.d.ts +9 -0
- package/dist/server/providers/types.d.ts.map +1 -0
- package/dist/server/providers/types.js +2 -0
- package/dist/server/providers/types.js.map +1 -0
- package/dist/types.d.ts +11 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +45 -0
- package/src/client/AIAssistantProvider.tsx +288 -0
- package/src/client/AIChatBot.tsx +309 -0
- package/src/client/AIFloatingButton.tsx +34 -0
- package/src/client/index.ts +4 -0
- package/src/client/styles.ts +353 -0
- package/src/server/handler.ts +158 -0
- package/src/server/index.ts +5 -0
- package/src/server/providers/anthropic.ts +53 -0
- package/src/server/providers/openai.ts +55 -0
- package/src/server/providers/types.ts +10 -0
- package/src/types.ts +11 -0
package/README.md
ADDED
|
@@ -0,0 +1,402 @@
|
|
|
1
|
+
# netbird-explain
|
|
2
|
+
|
|
3
|
+
AI-powered "Explain" assistant for React apps. Users click on UI elements and get contextual AI explanations via a chat panel.
|
|
4
|
+
|
|
5
|
+
The package has two entry points:
|
|
6
|
+
|
|
7
|
+
- `netbird-explain/client` — React components (provider, chat panel, floating button)
|
|
8
|
+
- `netbird-explain/server` — Node.js handler that proxies requests to Anthropic or OpenAI
|
|
9
|
+
|
|
10
|
+
No CSS framework required — the package is fully self-contained with inline styles and CSS custom properties.
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install netbird-explain
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Peer dependencies: `react >=18`, `react-dom >=18`.
|
|
19
|
+
|
|
20
|
+
For local development as a workspace package, add it to your `package.json`:
|
|
21
|
+
|
|
22
|
+
```json
|
|
23
|
+
{
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"netbird-explain": "file:./packages/netbird-explain"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
If you're using Next.js, add to `next.config.js`:
|
|
31
|
+
|
|
32
|
+
```js
|
|
33
|
+
module.exports = {
|
|
34
|
+
transpilePackages: ["netbird-explain"],
|
|
35
|
+
};
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Client
|
|
41
|
+
|
|
42
|
+
### Setup
|
|
43
|
+
|
|
44
|
+
Wrap your app with `AIAssistantProvider`:
|
|
45
|
+
|
|
46
|
+
```tsx
|
|
47
|
+
import { AIAssistantProvider } from "netbird-explain/client";
|
|
48
|
+
|
|
49
|
+
export default function App({ children }) {
|
|
50
|
+
return (
|
|
51
|
+
<AIAssistantProvider
|
|
52
|
+
endpoint="http://localhost:3080/api/ai/chat"
|
|
53
|
+
apiKey="your-api-key"
|
|
54
|
+
>
|
|
55
|
+
{children}
|
|
56
|
+
</AIAssistantProvider>
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
This renders the floating action button and chat panel automatically. No CSS imports are needed — the provider injects all required styles via CSS custom properties.
|
|
62
|
+
|
|
63
|
+
### Props
|
|
64
|
+
|
|
65
|
+
| Prop | Type | Required | Description |
|
|
66
|
+
| ---------- | ----------- | -------- | ----------------------------------- |
|
|
67
|
+
| `endpoint` | `string` | Yes | URL of the AI chat API |
|
|
68
|
+
| `apiKey` | `string` | No | Bearer token sent with each request |
|
|
69
|
+
| `children` | `ReactNode` | Yes | Your application |
|
|
70
|
+
|
|
71
|
+
### Marking elements as explainable
|
|
72
|
+
|
|
73
|
+
Add the `data-nb-explain` attribute to any element you want users to be able to click on in explain mode:
|
|
74
|
+
|
|
75
|
+
```tsx
|
|
76
|
+
<div data-nb-explain>
|
|
77
|
+
<Label>Name</Label>
|
|
78
|
+
<Input value={name} onChange={setName} />
|
|
79
|
+
</div>
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
When clicked, the library extracts a label from the element (first `<label>`, heading, or text content) and sends it as the query.
|
|
83
|
+
|
|
84
|
+
You can also pass a custom label directly:
|
|
85
|
+
|
|
86
|
+
```tsx
|
|
87
|
+
<div data-nb-explain="Database connection string">...</div>
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Documentation URLs
|
|
91
|
+
|
|
92
|
+
Attach docs to an element or its parent so the AI can reference them:
|
|
93
|
+
|
|
94
|
+
```tsx
|
|
95
|
+
<div data-nb-explain-docs='["https://docs.example.com/resources"]'>
|
|
96
|
+
<div data-nb-explain>...</div>
|
|
97
|
+
</div>
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Excluding elements
|
|
101
|
+
|
|
102
|
+
Use `data-nb-explain-ignore` to prevent an element from being selectable in explain mode:
|
|
103
|
+
|
|
104
|
+
```tsx
|
|
105
|
+
<button data-nb-explain-ignore onClick={enterExplainMode}>
|
|
106
|
+
Explain
|
|
107
|
+
</button>
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Setting page/modal context
|
|
111
|
+
|
|
112
|
+
Use the `useAIAssistant` hook to provide context that gets included in every query:
|
|
113
|
+
|
|
114
|
+
```tsx
|
|
115
|
+
import { useAIAssistant } from "netbird-explain/client";
|
|
116
|
+
|
|
117
|
+
function MyModal() {
|
|
118
|
+
const { setExplainContext, clearExplainContext } = useAIAssistant();
|
|
119
|
+
|
|
120
|
+
useEffect(() => {
|
|
121
|
+
setExplainContext({
|
|
122
|
+
modalName: "Add Resource",
|
|
123
|
+
pageName: "Networks",
|
|
124
|
+
docsUrls: ["https://docs.example.com/networks"],
|
|
125
|
+
});
|
|
126
|
+
return () => clearExplainContext();
|
|
127
|
+
}, []);
|
|
128
|
+
|
|
129
|
+
return <div data-nb-explain>...</div>;
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
This produces queries like: `Explain "Name" on Add Resource modal in Networks`.
|
|
134
|
+
|
|
135
|
+
### Hook API
|
|
136
|
+
|
|
137
|
+
`useAIAssistant()` returns:
|
|
138
|
+
|
|
139
|
+
| Method / Property | Description |
|
|
140
|
+
| ------------------------ | ------------------------------------------ |
|
|
141
|
+
| `openChat(query?)` | Open the chat panel, optionally with a query |
|
|
142
|
+
| `closeChat()` | Close the chat panel |
|
|
143
|
+
| `isChatOpen` | Whether the chat panel is open |
|
|
144
|
+
| `explainMode` | Whether explain mode is active |
|
|
145
|
+
| `enterExplainMode()` | Activate explain mode (click-to-explain) |
|
|
146
|
+
| `exitExplainMode()` | Deactivate explain mode |
|
|
147
|
+
| `setExplainContext(ctx)` | Set page/modal context for queries |
|
|
148
|
+
| `clearExplainContext()` | Clear the context |
|
|
149
|
+
|
|
150
|
+
### Theming
|
|
151
|
+
|
|
152
|
+
The package ships with a dark theme out of the box. All visual properties are controlled via CSS custom properties (`--nb-explain-*`) injected into `:root` by the provider. Override any of them in your own CSS to match your app's look and feel.
|
|
153
|
+
|
|
154
|
+
#### How it works
|
|
155
|
+
|
|
156
|
+
1. `AIAssistantProvider` injects a `<style>` tag with default values for all `--nb-explain-*` variables.
|
|
157
|
+
2. Components use inline styles that reference these variables (e.g., `background: var(--nb-explain-bg)`).
|
|
158
|
+
3. Your CSS can override any variable — later declarations on `:root` or more specific selectors win.
|
|
159
|
+
|
|
160
|
+
#### Overriding in CSS
|
|
161
|
+
|
|
162
|
+
Add a stylesheet or `<style>` block **after** the provider mounts (or use higher specificity):
|
|
163
|
+
|
|
164
|
+
```css
|
|
165
|
+
:root {
|
|
166
|
+
/* Change to a light theme */
|
|
167
|
+
--nb-explain-bg: #ffffff;
|
|
168
|
+
--nb-explain-bg-subtle: rgba(0, 0, 0, 0.04);
|
|
169
|
+
--nb-explain-bg-hover: rgba(0, 0, 0, 0.06);
|
|
170
|
+
--nb-explain-border: rgba(0, 0, 0, 0.12);
|
|
171
|
+
--nb-explain-text: #1a1a1a;
|
|
172
|
+
--nb-explain-text-muted: #6b7280;
|
|
173
|
+
--nb-explain-text-dim: #9ca3af;
|
|
174
|
+
--nb-explain-accent: #2563eb;
|
|
175
|
+
--nb-explain-accent-hover: #3b82f6;
|
|
176
|
+
--nb-explain-user-bg: #2563eb;
|
|
177
|
+
--nb-explain-user-text: #ffffff;
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
#### Full variable reference
|
|
182
|
+
|
|
183
|
+
| Variable | Default | Description |
|
|
184
|
+
| --------------------- | -------------------------------- | ---------------------------------- |
|
|
185
|
+
| `--nb-explain-bg` | `#0a0a0f` | Chat panel background |
|
|
186
|
+
| `--nb-explain-bg-subtle` | `rgba(255,255,255,0.06)` | Input field & assistant message bg |
|
|
187
|
+
| `--nb-explain-bg-hover` | `rgba(255,255,255,0.08)` | Hover state background |
|
|
188
|
+
| `--nb-explain-border` | `rgba(255,255,255,0.1)` | Border color |
|
|
189
|
+
| `--nb-explain-text` | `#f0f0f5` | Primary text color |
|
|
190
|
+
| `--nb-explain-text-muted` | `#9ca3af` | Secondary text color |
|
|
191
|
+
| `--nb-explain-text-dim` | `#6b7280` | Placeholder / tertiary text |
|
|
192
|
+
| `--nb-explain-accent` | `#eab308` | Accent color (buttons, icons) |
|
|
193
|
+
| `--nb-explain-accent-hover` | `#facc15` | Accent hover state |
|
|
194
|
+
| `--nb-explain-accent-glow` | `rgba(234,179,8,0.15)` | Accent glow (avatar backgrounds) |
|
|
195
|
+
| `--nb-explain-user-bg` | `#4f46e5` | User message bubble background |
|
|
196
|
+
| `--nb-explain-user-text` | `#ffffff` | User message text color |
|
|
197
|
+
| `--nb-explain-user-glow` | `rgba(79,70,229,0.25)` | User avatar glow |
|
|
198
|
+
| `--nb-explain-radius` | `12px` | Panel border radius |
|
|
199
|
+
| `--nb-explain-radius-sm` | `8px` | Message bubble border radius |
|
|
200
|
+
| `--nb-explain-radius-xs` | `6px` | Button border radius |
|
|
201
|
+
| `--nb-explain-font` | system font stack | Font family for all components |
|
|
202
|
+
| `--nb-explain-shadow` | large drop shadow | Chat panel box shadow |
|
|
203
|
+
| `--nb-explain-banner-bg` | `rgba(234,179,8,0.92)` | Explain mode banner background |
|
|
204
|
+
| `--nb-explain-banner-text` | `#000000` | Explain mode banner text |
|
|
205
|
+
| `--nb-explain-error-text` | `#f87171` | Error message text |
|
|
206
|
+
|
|
207
|
+
### Data attributes
|
|
208
|
+
|
|
209
|
+
| Attribute | Description |
|
|
210
|
+
| -------------------- | ------------------------------------------------------------------ |
|
|
211
|
+
| `data-nb-explain` | Marks element as explainable. Value can be a custom label or boolean. |
|
|
212
|
+
| `data-nb-explain-docs` | JSON array of documentation URLs for context. |
|
|
213
|
+
| `data-nb-explain-ignore` | Element is non-interactive during explain mode. |
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## Server
|
|
218
|
+
|
|
219
|
+
The server module provides a framework-agnostic handler that proxies chat requests to Anthropic or OpenAI.
|
|
220
|
+
|
|
221
|
+
### With Express
|
|
222
|
+
|
|
223
|
+
```ts
|
|
224
|
+
import express from "express";
|
|
225
|
+
import { createAssistant } from "netbird-explain/server";
|
|
226
|
+
|
|
227
|
+
const assistant = createAssistant({
|
|
228
|
+
provider: "anthropic",
|
|
229
|
+
apiKey: process.env.ANTHROPIC_API_KEY!,
|
|
230
|
+
model: "claude-sonnet-4-20250514",
|
|
231
|
+
systemPrompt: "You are a helpful assistant for MyApp.",
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
const app = express();
|
|
235
|
+
app.use(express.json());
|
|
236
|
+
|
|
237
|
+
app.post("/api/ai/chat", assistant.handler({ apiKey: "your-api-key" }));
|
|
238
|
+
|
|
239
|
+
app.listen(3080);
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### With plain Node.js HTTP
|
|
243
|
+
|
|
244
|
+
```ts
|
|
245
|
+
import http from "http";
|
|
246
|
+
import { createAssistant } from "netbird-explain/server";
|
|
247
|
+
|
|
248
|
+
const assistant = createAssistant({
|
|
249
|
+
provider: "openai",
|
|
250
|
+
apiKey: process.env.OPENAI_API_KEY!,
|
|
251
|
+
model: "gpt-4o",
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
const handle = assistant.handler({ apiKey: "your-api-key" });
|
|
255
|
+
|
|
256
|
+
http.createServer(handle).listen(3080);
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### Programmatic usage (no HTTP)
|
|
260
|
+
|
|
261
|
+
```ts
|
|
262
|
+
const assistant = createAssistant({
|
|
263
|
+
provider: "anthropic",
|
|
264
|
+
apiKey: process.env.ANTHROPIC_API_KEY!,
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
const { reply } = await assistant.chat({
|
|
268
|
+
messages: [{ role: "user", content: "What is a network resource?" }],
|
|
269
|
+
});
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### `createAssistant(config)`
|
|
273
|
+
|
|
274
|
+
| Option | Type | Required | Default |
|
|
275
|
+
| -------------- | ----------------------------- | -------- | ------------------------ |
|
|
276
|
+
| `provider` | `"anthropic"` \| `"openai"` | Yes | — |
|
|
277
|
+
| `apiKey` | `string` | Yes | — |
|
|
278
|
+
| `model` | `string` | No | Provider default |
|
|
279
|
+
| `systemPrompt` | `string` | No | Generic assistant prompt |
|
|
280
|
+
|
|
281
|
+
### `assistant.handler(opts?)`
|
|
282
|
+
|
|
283
|
+
Returns a `(req, res) => Promise<void>` handler compatible with Express, plain `http`, and similar frameworks.
|
|
284
|
+
|
|
285
|
+
| Option | Type | Description |
|
|
286
|
+
| -------- | -------- | -------------------------------------------------------------- |
|
|
287
|
+
| `apiKey` | `string` | If set, requires `Authorization: Bearer <key>` on requests |
|
|
288
|
+
|
|
289
|
+
### API contract
|
|
290
|
+
|
|
291
|
+
**Request** `POST /api/ai/chat`
|
|
292
|
+
|
|
293
|
+
```json
|
|
294
|
+
{
|
|
295
|
+
"messages": [
|
|
296
|
+
{ "role": "context", "content": "Docs: https://..." },
|
|
297
|
+
{ "role": "user", "content": "Explain network routes" }
|
|
298
|
+
]
|
|
299
|
+
}
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
**Response**
|
|
303
|
+
|
|
304
|
+
```json
|
|
305
|
+
{
|
|
306
|
+
"reply": "Network routes allow you to..."
|
|
307
|
+
}
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
**Error codes:** `400` (bad request), `401` (unauthorized), `502` (LLM error).
|
|
311
|
+
|
|
312
|
+
---
|
|
313
|
+
|
|
314
|
+
## Standalone dev server
|
|
315
|
+
|
|
316
|
+
The `server/` directory in the dashboard repo contains a ready-to-run Express server for local development.
|
|
317
|
+
|
|
318
|
+
```bash
|
|
319
|
+
cd server
|
|
320
|
+
cp .env .env.local # edit with your LLM API key
|
|
321
|
+
npm install
|
|
322
|
+
node index.js
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
Environment variables:
|
|
326
|
+
|
|
327
|
+
| Variable | Default | Description |
|
|
328
|
+
| ------------------- | -------------------------- | ---------------------- |
|
|
329
|
+
| `PORT` | `3080` | Server port |
|
|
330
|
+
| `API_KEY` | `nb-ai-dev-key-change-me` | Bearer token for auth |
|
|
331
|
+
| `LLM_PROVIDER` | `anthropic` | `anthropic` or `openai` |
|
|
332
|
+
| `ANTHROPIC_API_KEY` | — | Anthropic API key |
|
|
333
|
+
| `ANTHROPIC_MODEL` | `claude-sonnet-4-20250514` | Model ID |
|
|
334
|
+
| `OPENAI_API_KEY` | — | OpenAI API key |
|
|
335
|
+
| `OPENAI_MODEL` | `gpt-4o` | Model ID |
|
|
336
|
+
| `SYSTEM_PROMPT` | Generic NetBird prompt | System prompt for the LLM |
|
|
337
|
+
|
|
338
|
+
---
|
|
339
|
+
|
|
340
|
+
## Full integration example
|
|
341
|
+
|
|
342
|
+
```tsx
|
|
343
|
+
// layout.tsx — wrap app with provider
|
|
344
|
+
import { AIAssistantProvider } from "netbird-explain/client";
|
|
345
|
+
|
|
346
|
+
export default function Layout({ children }) {
|
|
347
|
+
return (
|
|
348
|
+
<AIAssistantProvider
|
|
349
|
+
endpoint={process.env.NEXT_PUBLIC_AI_SERVER_URL || "http://localhost:3080/api/ai/chat"}
|
|
350
|
+
apiKey={process.env.NEXT_PUBLIC_AI_API_KEY || "nb-ai-dev-key-change-me"}
|
|
351
|
+
>
|
|
352
|
+
{children}
|
|
353
|
+
</AIAssistantProvider>
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
```tsx
|
|
359
|
+
// MyModal.tsx — add explain support to a modal
|
|
360
|
+
import { useAIAssistant } from "netbird-explain/client";
|
|
361
|
+
import { Sparkles } from "lucide-react";
|
|
362
|
+
|
|
363
|
+
function MyModal() {
|
|
364
|
+
const { setExplainContext, clearExplainContext, explainMode, enterExplainMode, exitExplainMode } =
|
|
365
|
+
useAIAssistant();
|
|
366
|
+
|
|
367
|
+
useEffect(() => {
|
|
368
|
+
setExplainContext({
|
|
369
|
+
modalName: "Add Resource",
|
|
370
|
+
pageName: "Networks",
|
|
371
|
+
docsUrls: ["https://docs.netbird.io/manage/networks"],
|
|
372
|
+
});
|
|
373
|
+
return () => clearExplainContext();
|
|
374
|
+
}, []);
|
|
375
|
+
|
|
376
|
+
return (
|
|
377
|
+
<div data-nb-explain>
|
|
378
|
+
<button
|
|
379
|
+
data-nb-explain-ignore
|
|
380
|
+
onClick={() => (explainMode ? exitExplainMode() : enterExplainMode())}
|
|
381
|
+
>
|
|
382
|
+
<Sparkles size={13} />
|
|
383
|
+
{explainMode ? "Click an element..." : "Explain"}
|
|
384
|
+
</button>
|
|
385
|
+
|
|
386
|
+
<div data-nb-explain>
|
|
387
|
+
<label>Name</label>
|
|
388
|
+
<input placeholder="e.g., Postgres Database" />
|
|
389
|
+
</div>
|
|
390
|
+
|
|
391
|
+
<div data-nb-explain>
|
|
392
|
+
<label>Address</label>
|
|
393
|
+
<input placeholder="e.g., 10.0.0.1" />
|
|
394
|
+
</div>
|
|
395
|
+
</div>
|
|
396
|
+
);
|
|
397
|
+
}
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
## License
|
|
401
|
+
|
|
402
|
+
BSD-3-Clause
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { ExplainContext } from "../types";
|
|
3
|
+
type AIAssistantContextType = {
|
|
4
|
+
openChat: (selectedText?: string) => void;
|
|
5
|
+
closeChat: () => void;
|
|
6
|
+
isChatOpen: boolean;
|
|
7
|
+
explainMode: boolean;
|
|
8
|
+
enterExplainMode: () => void;
|
|
9
|
+
exitExplainMode: () => void;
|
|
10
|
+
setExplainContext: (ctx: ExplainContext) => void;
|
|
11
|
+
clearExplainContext: () => void;
|
|
12
|
+
};
|
|
13
|
+
export declare const useAIAssistant: () => AIAssistantContextType;
|
|
14
|
+
type AIAssistantProviderProps = {
|
|
15
|
+
endpoint: string;
|
|
16
|
+
apiKey?: string;
|
|
17
|
+
children: React.ReactNode;
|
|
18
|
+
};
|
|
19
|
+
export default function AIAssistantProvider({ endpoint, apiKey, children, }: AIAssistantProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=AIAssistantProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AIAssistantProvider.d.ts","sourceRoot":"","sources":["../../src/client/AIAssistantProvider.tsx"],"names":[],"mappings":"AAEA,OAAO,KAMN,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAK/C,KAAK,sBAAsB,GAAG;IAC5B,QAAQ,EAAE,CAAC,YAAY,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,UAAU,EAAE,OAAO,CAAC;IACpB,WAAW,EAAE,OAAO,CAAC;IACrB,gBAAgB,EAAE,MAAM,IAAI,CAAC;IAC7B,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,iBAAiB,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,IAAI,CAAC;IACjD,mBAAmB,EAAE,MAAM,IAAI,CAAC;CACjC,CAAC;AAaF,eAAO,MAAM,cAAc,8BAAuC,CAAC;AAEnE,KAAK,wBAAwB,GAAG;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,CAAC;AAyEF,MAAM,CAAC,OAAO,UAAU,mBAAmB,CAAC,EAC1C,QAAQ,EACR,MAAM,EACN,QAAQ,GACT,EAAE,wBAAwB,2CAwK1B"}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { createContext, useCallback, useContext, useEffect, useState, } from "react";
|
|
4
|
+
import AIChatBot from "./AIChatBot";
|
|
5
|
+
import AIFloatingButton from "./AIFloatingButton";
|
|
6
|
+
import * as S from "./styles";
|
|
7
|
+
const AIAssistantContext = createContext({
|
|
8
|
+
openChat: () => { },
|
|
9
|
+
closeChat: () => { },
|
|
10
|
+
isChatOpen: false,
|
|
11
|
+
explainMode: false,
|
|
12
|
+
enterExplainMode: () => { },
|
|
13
|
+
exitExplainMode: () => { },
|
|
14
|
+
setExplainContext: () => { },
|
|
15
|
+
clearExplainContext: () => { },
|
|
16
|
+
});
|
|
17
|
+
export const useAIAssistant = () => useContext(AIAssistantContext);
|
|
18
|
+
/**
|
|
19
|
+
* Find the closest ancestor (or self) with a data-nb-explain attribute.
|
|
20
|
+
* Returns null if nothing is explainable.
|
|
21
|
+
*/
|
|
22
|
+
function findExplainable(el) {
|
|
23
|
+
return el.closest("[data-nb-explain]");
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Extract a short label from an explainable element by looking for
|
|
27
|
+
* a label, heading, or first bit of text content.
|
|
28
|
+
*/
|
|
29
|
+
function extractLabel(el) {
|
|
30
|
+
const label = el.querySelector("label");
|
|
31
|
+
if (label?.innerText?.trim())
|
|
32
|
+
return label.innerText.trim();
|
|
33
|
+
const heading = el.querySelector("h1, h2, h3, h4");
|
|
34
|
+
if (heading?.innerText?.trim())
|
|
35
|
+
return heading.innerText.trim();
|
|
36
|
+
const text = el.innerText?.trim();
|
|
37
|
+
if (text && text.length <= 80)
|
|
38
|
+
return text;
|
|
39
|
+
if (text)
|
|
40
|
+
return text.slice(0, 80) + "...";
|
|
41
|
+
return "this element";
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Look for data-nb-explain-docs on the element or its ancestors.
|
|
45
|
+
* Returns an array of documentation URLs, or an empty array.
|
|
46
|
+
*/
|
|
47
|
+
function findExplainDocs(el) {
|
|
48
|
+
const withDocs = el.closest("[data-nb-explain-docs]");
|
|
49
|
+
if (!withDocs)
|
|
50
|
+
return [];
|
|
51
|
+
const raw = withDocs.getAttribute("data-nb-explain-docs") || "";
|
|
52
|
+
try {
|
|
53
|
+
const parsed = JSON.parse(raw);
|
|
54
|
+
if (Array.isArray(parsed))
|
|
55
|
+
return parsed;
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
// If not valid JSON, treat as a single URL
|
|
59
|
+
if (raw.trim())
|
|
60
|
+
return [raw.trim()];
|
|
61
|
+
}
|
|
62
|
+
return [];
|
|
63
|
+
}
|
|
64
|
+
function buildQuery(label, ctx, elementDocs) {
|
|
65
|
+
let userMessage = `Explain "${label}"`;
|
|
66
|
+
if (ctx) {
|
|
67
|
+
if (ctx.modalName)
|
|
68
|
+
userMessage += ` on ${ctx.modalName} modal`;
|
|
69
|
+
if (ctx.pageName)
|
|
70
|
+
userMessage += ` in ${ctx.pageName}`;
|
|
71
|
+
}
|
|
72
|
+
// Merge docs from context and element attribute
|
|
73
|
+
const allDocs = [
|
|
74
|
+
...(ctx?.docsUrls || []),
|
|
75
|
+
...elementDocs,
|
|
76
|
+
];
|
|
77
|
+
// Deduplicate
|
|
78
|
+
const uniqueDocs = [...new Set(allDocs)];
|
|
79
|
+
const parts = [userMessage];
|
|
80
|
+
if (uniqueDocs.length > 0) {
|
|
81
|
+
parts.push(`Docs: ${uniqueDocs.join(", ")}`);
|
|
82
|
+
}
|
|
83
|
+
return parts.join("\n");
|
|
84
|
+
}
|
|
85
|
+
export default function AIAssistantProvider({ endpoint, apiKey, children, }) {
|
|
86
|
+
const [isChatOpen, setIsChatOpen] = useState(false);
|
|
87
|
+
const [initialQuery, setInitialQuery] = useState("");
|
|
88
|
+
const [explainMode, setExplainMode] = useState(false);
|
|
89
|
+
const [hoveredEl, setHoveredEl] = useState(null);
|
|
90
|
+
const [explainCtx, setExplainCtx] = useState(null);
|
|
91
|
+
const openChat = useCallback((selectedText) => {
|
|
92
|
+
setInitialQuery(selectedText || "");
|
|
93
|
+
setIsChatOpen(true);
|
|
94
|
+
setExplainMode(false);
|
|
95
|
+
setHoveredEl(null);
|
|
96
|
+
}, []);
|
|
97
|
+
const closeChat = useCallback(() => {
|
|
98
|
+
setIsChatOpen(false);
|
|
99
|
+
setInitialQuery("");
|
|
100
|
+
}, []);
|
|
101
|
+
const enterExplainMode = useCallback(() => {
|
|
102
|
+
setExplainMode(true);
|
|
103
|
+
}, []);
|
|
104
|
+
const exitExplainMode = useCallback(() => {
|
|
105
|
+
setExplainMode(false);
|
|
106
|
+
setHoveredEl(null);
|
|
107
|
+
}, []);
|
|
108
|
+
const setExplainContext = useCallback((ctx) => {
|
|
109
|
+
setExplainCtx(ctx);
|
|
110
|
+
}, []);
|
|
111
|
+
const clearExplainContext = useCallback(() => {
|
|
112
|
+
setExplainCtx(null);
|
|
113
|
+
}, []);
|
|
114
|
+
// Explain mode: highlight explainable elements on hover, open chat on click
|
|
115
|
+
useEffect(() => {
|
|
116
|
+
if (!explainMode)
|
|
117
|
+
return;
|
|
118
|
+
const handleMouseOver = (e) => {
|
|
119
|
+
const target = e.target;
|
|
120
|
+
if (target.closest("[data-nb-explain-ignore]") ||
|
|
121
|
+
target.closest("[data-nb-explain-banner]"))
|
|
122
|
+
return;
|
|
123
|
+
const explainable = findExplainable(target);
|
|
124
|
+
setHoveredEl(explainable);
|
|
125
|
+
};
|
|
126
|
+
const handleMouseOut = () => {
|
|
127
|
+
setHoveredEl(null);
|
|
128
|
+
};
|
|
129
|
+
const handleClick = (e) => {
|
|
130
|
+
const target = e.target;
|
|
131
|
+
if (target.closest("[data-nb-explain-ignore]") ||
|
|
132
|
+
target.closest("[data-nb-explain-banner]"))
|
|
133
|
+
return;
|
|
134
|
+
e.preventDefault();
|
|
135
|
+
e.stopPropagation();
|
|
136
|
+
const explainable = findExplainable(target);
|
|
137
|
+
if (!explainable)
|
|
138
|
+
return;
|
|
139
|
+
const attrValue = explainable.getAttribute("data-nb-explain") || "";
|
|
140
|
+
const label = attrValue && attrValue !== "true"
|
|
141
|
+
? attrValue
|
|
142
|
+
: extractLabel(explainable);
|
|
143
|
+
const elementDocs = findExplainDocs(explainable);
|
|
144
|
+
const query = buildQuery(label, explainCtx, elementDocs);
|
|
145
|
+
openChat(query);
|
|
146
|
+
};
|
|
147
|
+
const handleKeyDown = (e) => {
|
|
148
|
+
if (e.key === "Escape") {
|
|
149
|
+
exitExplainMode();
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
document.addEventListener("mouseover", handleMouseOver, true);
|
|
153
|
+
document.addEventListener("mouseout", handleMouseOut, true);
|
|
154
|
+
document.addEventListener("click", handleClick, true);
|
|
155
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
156
|
+
return () => {
|
|
157
|
+
document.removeEventListener("mouseover", handleMouseOver, true);
|
|
158
|
+
document.removeEventListener("mouseout", handleMouseOut, true);
|
|
159
|
+
document.removeEventListener("click", handleClick, true);
|
|
160
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
161
|
+
};
|
|
162
|
+
}, [explainMode, explainCtx, openChat, exitExplainMode]);
|
|
163
|
+
// Apply/remove highlight on hovered explainable element via CSS class
|
|
164
|
+
useEffect(() => {
|
|
165
|
+
if (!hoveredEl)
|
|
166
|
+
return;
|
|
167
|
+
hoveredEl.setAttribute("data-nb-explain-highlight", "");
|
|
168
|
+
return () => {
|
|
169
|
+
hoveredEl.removeAttribute("data-nb-explain-highlight");
|
|
170
|
+
};
|
|
171
|
+
}, [hoveredEl]);
|
|
172
|
+
// Force-remove all highlights when leaving explain mode
|
|
173
|
+
useEffect(() => {
|
|
174
|
+
if (!explainMode) {
|
|
175
|
+
document.querySelectorAll("[data-nb-explain-highlight]").forEach((el) => {
|
|
176
|
+
el.removeAttribute("data-nb-explain-highlight");
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
}, [explainMode]);
|
|
180
|
+
return (_jsxs(AIAssistantContext.Provider, { value: {
|
|
181
|
+
openChat,
|
|
182
|
+
closeChat,
|
|
183
|
+
isChatOpen,
|
|
184
|
+
explainMode,
|
|
185
|
+
enterExplainMode,
|
|
186
|
+
exitExplainMode,
|
|
187
|
+
setExplainContext,
|
|
188
|
+
clearExplainContext,
|
|
189
|
+
}, children: [_jsx("style", { children: S.CSS_VARS + S.ANIMATIONS + S.HIGHLIGHT_STYLES }), children, explainMode && (_jsxs("div", { "data-nb-explain-banner": true, style: S.banner, children: [_jsx("span", { children: "Click on a highlighted element to explain it" }), _jsx("button", { onClick: () => exitExplainMode(), style: S.bannerCancel, children: "Cancel" })] })), _jsx(AIFloatingButton, { isOpen: isChatOpen, onClick: () => {
|
|
190
|
+
if (isChatOpen) {
|
|
191
|
+
closeChat();
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
openChat();
|
|
195
|
+
}
|
|
196
|
+
} }), _jsx(AIChatBot, { open: isChatOpen, onClose: closeChat, initialQuery: initialQuery, endpoint: endpoint, apiKey: apiKey })] }));
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=AIAssistantProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AIAssistantProvider.js","sourceRoot":"","sources":["../../src/client/AIAssistantProvider.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
type Props = {
|
|
2
|
+
open: boolean;
|
|
3
|
+
onClose: () => void;
|
|
4
|
+
initialQuery: string;
|
|
5
|
+
endpoint: string;
|
|
6
|
+
apiKey?: string;
|
|
7
|
+
};
|
|
8
|
+
export default function AIChatBot({ open, onClose, initialQuery, endpoint, apiKey, }: Props): import("react/jsx-runtime").JSX.Element | null;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=AIChatBot.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AIChatBot.d.ts","sourceRoot":"","sources":["../../src/client/AIChatBot.tsx"],"names":[],"mappings":"AAcA,KAAK,KAAK,GAAG;IACX,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAkCF,MAAM,CAAC,OAAO,UAAU,SAAS,CAAC,EAChC,IAAI,EACJ,OAAO,EACP,YAAY,EACZ,QAAQ,EACR,MAAM,GACP,EAAE,KAAK,kDAwPP"}
|