agenticaichat 1.0.3 → 1.0.5
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 +189 -26
- package/bin/cli.js +118 -50
- package/dist/adapters/angular.d.ts +9 -0
- package/dist/adapters/angular.js +6 -0
- package/dist/adapters/react.d.ts +1 -0
- package/dist/adapters/react.js +8 -0
- package/dist/adapters/vue.d.ts +9 -0
- package/dist/adapters/vue.js +6 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +20 -1
- package/dist/web-component/AgenticAIChatbot.js +219 -0
- package/dist/web-component/index.js +2 -0
- package/package.json +9 -3
- package/src/web-component/AgenticAIChatbot.js +219 -0
- package/src/web-component/index.js +2 -0
package/README.md
CHANGED
|
@@ -6,45 +6,51 @@ AI-powered chatbot for business analytics with natural language database queries
|
|
|
6
6
|
- Five-minute setup with an interactive CLI wizard
|
|
7
7
|
- Natural language questions in English or Hindi
|
|
8
8
|
- Works with PostgreSQL, MySQL, SQLite, Turso, and MongoDB
|
|
9
|
-
-
|
|
9
|
+
- Universal Web Component for any framework (React, Angular, Vue, Next.js, HTML)
|
|
10
|
+
- Ready-to-use React/Next.js widget for advanced dashboards
|
|
10
11
|
- Configuration files generated for you (`.env.chatbot`, `chatbot-config.json`)
|
|
11
12
|
- Fully typed TypeScript package
|
|
12
13
|
|
|
13
14
|
## Requirements
|
|
14
15
|
|
|
15
16
|
- Node.js 18+ and npm 9+
|
|
16
|
-
- React 18+ and Next.js 13+ (app router recommended)
|
|
17
|
+
- React 18+ and Next.js 13+ (app router recommended) for the built-in widget
|
|
17
18
|
|
|
18
|
-
##
|
|
19
|
+
## Universal Web Component (Recommended for All Frameworks)
|
|
19
20
|
|
|
20
|
-
|
|
21
|
+
For the best compatibility across all frameworks and plain HTML, use our universal Web Component:
|
|
21
22
|
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
```html
|
|
24
|
+
<script src="https://cdn.jsdelivr.net/npm/agenticaichat/dist/web-component/index.js"></script>
|
|
25
|
+
<agentica-chatbot api="/api/chatbot/query"></agentica-chatbot>
|
|
26
|
+
```
|
|
25
27
|
|
|
26
|
-
|
|
27
|
-
yarn add agenticaichat
|
|
28
|
+
Or import in your framework:
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
|
|
30
|
+
```javascript
|
|
31
|
+
// React, Vue, Angular, etc.
|
|
32
|
+
import 'agenticaichat/web-component';
|
|
31
33
|
```
|
|
32
34
|
|
|
33
|
-
|
|
35
|
+
This works everywhere without framework-specific code.
|
|
34
36
|
|
|
35
|
-
|
|
36
|
-
- Collect your AI provider, model, and API key
|
|
37
|
-
- Generate `.env.chatbot` and `chatbot-config.json`
|
|
38
|
-
- Create starter files if they are missing (Next.js defaults):
|
|
39
|
-
- `app/api/chatbot/query/route.ts`
|
|
40
|
-
- `app/chat/page.tsx`
|
|
41
|
-
- Updates `.gitignore` to exclude generated secrets
|
|
37
|
+
## Widget vs Web Component — When to Use What?
|
|
42
38
|
|
|
43
|
-
|
|
39
|
+
AgenticAIChat offers two ways to integrate the chatbot:
|
|
44
40
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
41
|
+
1. **React/Next.js Widget (Advanced UI)**
|
|
42
|
+
- Fully designed UI with animations and chat history
|
|
43
|
+
- Best for dashboards and full-page experiences
|
|
44
|
+
- Uses React internally
|
|
45
|
+
- Ideal for Next.js apps
|
|
46
|
+
|
|
47
|
+
2. **Web Component (Universal) — Recommended**
|
|
48
|
+
- Works in React, Angular, Vue, Next.js, Svelte, plain HTML
|
|
49
|
+
- No framework dependencies
|
|
50
|
+
- Perfect for embedding on external websites
|
|
51
|
+
- Lightweight and self-contained
|
|
52
|
+
|
|
53
|
+
If unsure, use the Web Component for maximum compatibility.
|
|
48
54
|
|
|
49
55
|
## Quick Start (Next.js)
|
|
50
56
|
|
|
@@ -81,11 +87,151 @@ Start your Next.js app:
|
|
|
81
87
|
npm run dev
|
|
82
88
|
```
|
|
83
89
|
|
|
84
|
-
##
|
|
90
|
+
## Setting up the Backend API
|
|
91
|
+
|
|
92
|
+
For all frameworks, you need a backend endpoint that handles chatbot queries. The setup wizard generates configuration files, but you must implement the API route yourself unless using Next.js.
|
|
93
|
+
|
|
94
|
+
1. Run the setup wizard to generate `.env.chatbot` and `chatbot-config.json`:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
npx agenticai-setup
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
2. Create an HTTP POST endpoint at `/api/chatbot/query` (or any path you choose).
|
|
101
|
+
|
|
102
|
+
Use the template from `templates/api-route.template.ts` as a guide. Load environment variables from `.env.chatbot` and use the `ChatbotEngine` from `agenticaichat/core`.
|
|
103
|
+
|
|
104
|
+
Example (Node.js/Express):
|
|
105
|
+
|
|
106
|
+
```javascript
|
|
107
|
+
const express = require('express');
|
|
108
|
+
const { ChatbotEngine } = require('agenticaichat/core');
|
|
109
|
+
require('dotenv').config({ path: '.env.chatbot' });
|
|
110
|
+
|
|
111
|
+
const app = express();
|
|
112
|
+
app.use(express.json());
|
|
113
|
+
|
|
114
|
+
app.post('/api/chatbot/query', async (req, res) => {
|
|
115
|
+
const { query } = req.body;
|
|
116
|
+
const engine = new ChatbotEngine();
|
|
117
|
+
try {
|
|
118
|
+
const result = await engine.processQuery(query);
|
|
119
|
+
res.json(result);
|
|
120
|
+
} catch (error) {
|
|
121
|
+
res.status(500).json({ error: error.message });
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
app.listen(3000);
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
For Next.js, the wizard generates this automatically.
|
|
129
|
+
|
|
130
|
+
**Important: Enable CORS**
|
|
131
|
+
If your frontend and backend are on different domains or ports, enable CORS in your backend:
|
|
132
|
+
```
|
|
133
|
+
Access-Control-Allow-Origin: *
|
|
134
|
+
```
|
|
135
|
+
Or restrict to your specific domain for security.
|
|
136
|
+
|
|
137
|
+
## Setup for Angular
|
|
138
|
+
|
|
139
|
+
**Recommended:** Use the universal Web Component for easiest integration. See the Web Component section above.
|
|
140
|
+
|
|
141
|
+
If you prefer a custom Angular component:
|
|
142
|
+
|
|
143
|
+
1. Install the package and run setup:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
npm install agenticaichat
|
|
147
|
+
npx agenticai-setup
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
2. Set up the backend API as described above (e.g., using Express or your preferred Node.js framework).
|
|
151
|
+
|
|
152
|
+
3. In your Angular app, create a chatbot component:
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
// chatbot.component.ts
|
|
156
|
+
import { Component } from '@angular/core';
|
|
157
|
+
import { HttpClient } from '@angular/common/http';
|
|
158
|
+
import { AngularChatRequest, AngularChatResponse } from 'agenticaichat/angular';
|
|
159
|
+
|
|
160
|
+
@Component({
|
|
161
|
+
selector: 'app-chatbot',
|
|
162
|
+
template: `
|
|
163
|
+
<div>
|
|
164
|
+
<input [(ngModel)]="query" placeholder="Ask a question..." />
|
|
165
|
+
<button (click)="ask()">Ask</button>
|
|
166
|
+
<div *ngIf="response">{{ response.answer }}</div>
|
|
167
|
+
</div>
|
|
168
|
+
`
|
|
169
|
+
})
|
|
170
|
+
export class ChatbotComponent {
|
|
171
|
+
query = '';
|
|
172
|
+
response: AngularChatResponse | null = null;
|
|
173
|
+
|
|
174
|
+
constructor(private http: HttpClient) {}
|
|
175
|
+
|
|
176
|
+
ask() {
|
|
177
|
+
const request: AngularChatRequest = { query: this.query };
|
|
178
|
+
this.http.post<AngularChatResponse>('/api/chatbot/query', request)
|
|
179
|
+
.subscribe(res => this.response = res);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
4. Add the component to your app and ensure CORS is configured on your backend.
|
|
185
|
+
|
|
186
|
+
## Setup for Vue
|
|
187
|
+
|
|
188
|
+
**Recommended:** Use the universal Web Component for easiest integration. See the Web Component section above.
|
|
189
|
+
|
|
190
|
+
If you prefer a custom Vue component:
|
|
191
|
+
|
|
192
|
+
1. Install the package and run setup:
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
npm install agenticaichat
|
|
196
|
+
npx agenticai-setup
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
2. Set up the backend API as described above.
|
|
200
|
+
|
|
201
|
+
3. In your Vue app, create a chatbot component:
|
|
202
|
+
|
|
203
|
+
```vue
|
|
204
|
+
<!-- Chatbot.vue -->
|
|
205
|
+
<template>
|
|
206
|
+
<div>
|
|
207
|
+
<input v-model="query" placeholder="Ask a question..." />
|
|
208
|
+
<button @click="ask">Ask</button>
|
|
209
|
+
<div v-if="response">{{ response.answer }}</div>
|
|
210
|
+
</div>
|
|
211
|
+
</template>
|
|
212
|
+
|
|
213
|
+
<script setup lang="ts">
|
|
214
|
+
import { ref } from 'vue';
|
|
215
|
+
import { VueChatRequest, VueChatResponse } from 'agenticaichat/vue';
|
|
216
|
+
|
|
217
|
+
const query = ref('');
|
|
218
|
+
const response = ref<VueChatResponse | null>(null);
|
|
219
|
+
|
|
220
|
+
const ask = async () => {
|
|
221
|
+
const request: VueChatRequest = { query: query.value };
|
|
222
|
+
const res = await fetch('/api/chatbot/query', {
|
|
223
|
+
method: 'POST',
|
|
224
|
+
headers: { 'Content-Type': 'application/json' },
|
|
225
|
+
body: JSON.stringify(request)
|
|
226
|
+
});
|
|
227
|
+
response.value = await res.json();
|
|
228
|
+
};
|
|
229
|
+
</script>
|
|
230
|
+
```
|
|
85
231
|
|
|
86
|
-
|
|
232
|
+
4. Use the component in your app and configure CORS on your backend.
|
|
87
233
|
|
|
88
|
-
|
|
234
|
+
## Setup for Other React Frameworks
|
|
89
235
|
|
|
90
236
|
- Create an HTTP POST endpoint (e.g., `/api/chatbot/query`) that follows `templates/api-route.template.ts`.
|
|
91
237
|
- Load `.env.chatbot` on the server and wire `DATABASE_URL`, `DB_TYPE`, `LLM_PROVIDER`, `LLM_MODEL`, and `LLM_API_KEY` into the handler.
|
|
@@ -108,6 +254,23 @@ export default function Page() {
|
|
|
108
254
|
- `chatbot-config.json` stores non-secret metadata (database/LLM selection).
|
|
109
255
|
- `.gitignore` is updated automatically to keep generated secrets out of version control.
|
|
110
256
|
|
|
257
|
+
## Architecture Summary
|
|
258
|
+
|
|
259
|
+
```
|
|
260
|
+
[Browser: React/Angular/Vue/HTML/Next.js]
|
|
261
|
+
|
|
|
262
|
+
V
|
|
263
|
+
<agentica-chatbot web component>
|
|
264
|
+
|
|
|
265
|
+
V
|
|
266
|
+
Your Backend API (/api/chatbot/query)
|
|
267
|
+
|
|
|
268
|
+
V
|
|
269
|
+
ChatbotEngine → LLM / Database / Business Logic
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
The Web Component handles all frontend interactions and works universally across frameworks.
|
|
273
|
+
|
|
111
274
|
## Troubleshooting
|
|
112
275
|
|
|
113
276
|
- CI environments skip the wizard; run `npx agenticai-setup` locally after install.
|
package/bin/cli.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
1
|
+
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
const inquirer = require('inquirer')
|
|
3
|
+
const inquirer = require('inquirer');
|
|
4
4
|
const chalk = require('chalk');
|
|
5
5
|
const ora = require('ora');
|
|
6
6
|
const fs = require('fs');
|
|
@@ -298,8 +298,41 @@ async function main() {
|
|
|
298
298
|
const selectedProvider = llmProviders.find(p => p.value === llmAnswers.provider);
|
|
299
299
|
console.log(chalk.green(`\n✅ ${selectedProvider.name} configured!\n`));
|
|
300
300
|
|
|
301
|
-
// Step 3:
|
|
302
|
-
console.log(chalk.bold.blue('
|
|
301
|
+
// Step 3: Frontend Framework / Adapter
|
|
302
|
+
console.log(chalk.bold.blue('\n🧩 Step 3: Frontend Framework\n'));
|
|
303
|
+
|
|
304
|
+
const frontendAnswers = await inquirer.prompt([
|
|
305
|
+
{
|
|
306
|
+
type: 'list',
|
|
307
|
+
name: 'framework',
|
|
308
|
+
message: 'Which frontend framework will you use for the chat UI?',
|
|
309
|
+
choices: [
|
|
310
|
+
{
|
|
311
|
+
name: 'Next.js / React (recommended, uses built-in ChatbotWidget)',
|
|
312
|
+
value: 'react',
|
|
313
|
+
short: 'React'
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
name: 'Angular (use HTTP API from your Angular component)',
|
|
317
|
+
value: 'angular',
|
|
318
|
+
short: 'Angular'
|
|
319
|
+
},
|
|
320
|
+
{
|
|
321
|
+
name: 'Vue (use HTTP API from your Vue component)',
|
|
322
|
+
value: 'vue',
|
|
323
|
+
short: 'Vue'
|
|
324
|
+
},
|
|
325
|
+
{
|
|
326
|
+
name: 'Other / Backend-only (no bundled UI, HTTP API only)',
|
|
327
|
+
value: 'other',
|
|
328
|
+
short: 'Other'
|
|
329
|
+
}
|
|
330
|
+
]
|
|
331
|
+
}
|
|
332
|
+
]);
|
|
333
|
+
|
|
334
|
+
// Step 4: Generate configuration files
|
|
335
|
+
console.log(chalk.bold.blue('📝 Step 4: Generating Configuration Files\n'));
|
|
303
336
|
|
|
304
337
|
const spinner = ora('Creating files...').start();
|
|
305
338
|
|
|
@@ -317,6 +350,9 @@ LLM_PROVIDER=${llmAnswers.provider}
|
|
|
317
350
|
LLM_API_KEY=${llmAnswers.apiKey}
|
|
318
351
|
LLM_MODEL=${llmAnswers.model}
|
|
319
352
|
|
|
353
|
+
# Frontend Adapter
|
|
354
|
+
FRONTEND_FRAMEWORK=${frontendAnswers.framework}
|
|
355
|
+
|
|
320
356
|
# Other
|
|
321
357
|
SECRET_KEY=${crypto.randomBytes(32).toString('hex')}
|
|
322
358
|
CHATBOT_ENABLED=true
|
|
@@ -336,6 +372,9 @@ CHATBOT_ENABLED=true
|
|
|
336
372
|
provider: llmAnswers.provider,
|
|
337
373
|
model: llmAnswers.model
|
|
338
374
|
},
|
|
375
|
+
frontend: {
|
|
376
|
+
framework: frontendAnswers.framework
|
|
377
|
+
},
|
|
339
378
|
setupDate: new Date().toISOString(),
|
|
340
379
|
version: '2.0.0'
|
|
341
380
|
};
|
|
@@ -344,44 +383,52 @@ CHATBOT_ENABLED=true
|
|
|
344
383
|
fs.writeFileSync(configPath, JSON.stringify(configContent, null, 2));
|
|
345
384
|
spinner.text = 'Created chatbot-config.json';
|
|
346
385
|
|
|
347
|
-
// Create
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
386
|
+
// Create frontend scaffolding based on selected framework
|
|
387
|
+
if (frontendAnswers.framework === 'react') {
|
|
388
|
+
// Next.js / React: generate app router files
|
|
389
|
+
try {
|
|
390
|
+
const apiDir = path.join(process.cwd(), 'app', 'api', 'chatbot', 'query');
|
|
391
|
+
if (!fs.existsSync(apiDir)) {
|
|
392
|
+
fs.mkdirSync(apiDir, { recursive: true });
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
const apiTemplate = fs.readFileSync(
|
|
396
|
+
path.join(__dirname, '..', 'templates', 'api-route.txt'),
|
|
397
|
+
'utf8'
|
|
398
|
+
);
|
|
399
|
+
|
|
400
|
+
const apiPath = path.join(apiDir, 'route.ts');
|
|
401
|
+
fs.writeFileSync(apiPath, apiTemplate);
|
|
402
|
+
spinner.text = 'Created API route: app/api/chatbot/query/route.ts';
|
|
403
|
+
} catch (error) {
|
|
404
|
+
spinner.warn('Could not create API route automatically');
|
|
405
|
+
console.log(chalk.yellow('\nℹ️ You can manually create the API route later'));
|
|
352
406
|
}
|
|
353
407
|
|
|
354
|
-
|
|
355
|
-
path.join(
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
const apiPath = path.join(apiDir, 'route.ts');
|
|
360
|
-
fs.writeFileSync(apiPath, apiTemplate);
|
|
361
|
-
spinner.text = 'Created API route: app/api/chatbot/query/route.ts';
|
|
362
|
-
} catch (error) {
|
|
363
|
-
spinner.warn('Could not create API route automatically');
|
|
364
|
-
console.log(chalk.yellow('\nℹ️ You can manually create the API route later'));
|
|
365
|
-
}
|
|
408
|
+
try {
|
|
409
|
+
const chatDir = path.join(process.cwd(), 'app', 'chat');
|
|
410
|
+
if (!fs.existsSync(chatDir)) {
|
|
411
|
+
fs.mkdirSync(chatDir, { recursive: true });
|
|
412
|
+
}
|
|
366
413
|
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
414
|
+
const chatTemplate = fs.readFileSync(
|
|
415
|
+
path.join(__dirname, '..', 'templates', 'chat-page.txt'),
|
|
416
|
+
'utf8'
|
|
417
|
+
);
|
|
418
|
+
|
|
419
|
+
const chatPath = path.join(chatDir, 'page.tsx');
|
|
420
|
+
fs.writeFileSync(chatPath, chatTemplate);
|
|
421
|
+
spinner.text = 'Created chat page: app/chat/page.tsx';
|
|
422
|
+
} catch (error) {
|
|
423
|
+
spinner.warn('Could not create chat page automatically');
|
|
424
|
+
console.log(chalk.yellow('\nℹ️ You can manually create the chat page later'));
|
|
372
425
|
}
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
);
|
|
378
|
-
|
|
379
|
-
const chatPath = path.join(chatDir, 'page.tsx');
|
|
380
|
-
fs.writeFileSync(chatPath, chatTemplate);
|
|
381
|
-
spinner.text = 'Created chat page: app/chat/page.tsx';
|
|
382
|
-
} catch (error) {
|
|
383
|
-
spinner.warn('Could not create chat page automatically');
|
|
384
|
-
console.log(chalk.yellow('\nℹ️ You can manually create the chat page later'));
|
|
426
|
+
} else {
|
|
427
|
+
// Non-React frameworks: keep backend-only scaffolding, user builds UI
|
|
428
|
+
spinner.text = 'Backend configured (HTTP API). Frontend adapter to be implemented in your framework.';
|
|
429
|
+
console.log(chalk.yellow('\nℹ️ Frontend note:'));
|
|
430
|
+
console.log(chalk.gray(' - Use the /api/chatbot/query HTTP endpoint from your Angular/Vue/other component.'));
|
|
431
|
+
console.log(chalk.gray(' - See README for framework-specific adapter guidance.\n'));
|
|
385
432
|
}
|
|
386
433
|
|
|
387
434
|
// Update .gitignore
|
|
@@ -403,8 +450,8 @@ CHATBOT_ENABLED=true
|
|
|
403
450
|
// Success message
|
|
404
451
|
console.log(chalk.green.bold('\n✅ Setup Complete!\n'));
|
|
405
452
|
console.log(chalk.white('Files created:'));
|
|
406
|
-
console.log(chalk.gray(' • .env.chatbot (API keys
|
|
407
|
-
console.log(chalk.gray(' • chatbot-config.json (settings)'));
|
|
453
|
+
console.log(chalk.gray(' • .env.chatbot (API keys, database, LLM, frontend framework)'));
|
|
454
|
+
console.log(chalk.gray(' • chatbot-config.json (settings, including frontend framework)'));
|
|
408
455
|
console.log(chalk.gray(' • .gitignore (updated)\n'));
|
|
409
456
|
|
|
410
457
|
console.log(chalk.white('Database Configuration:'));
|
|
@@ -417,17 +464,38 @@ CHATBOT_ENABLED=true
|
|
|
417
464
|
console.log(chalk.cyan(` • Model: ${llmAnswers.model}`));
|
|
418
465
|
console.log(chalk.gray(` • API Key: ${'*'.repeat(20)}\n`));
|
|
419
466
|
|
|
420
|
-
console.log(chalk.white('
|
|
421
|
-
console.log(chalk.
|
|
422
|
-
console.log(chalk.cyan(' import { ChatbotWidget } from "agenticaichat";'));
|
|
423
|
-
console.log(chalk.cyan(' \n <ChatbotWidget />\n'));
|
|
424
|
-
|
|
425
|
-
console.log(chalk.yellow('2. Or create a full-page chat route:\n'));
|
|
426
|
-
console.log(chalk.cyan(' // app/chat/page.tsx'));
|
|
427
|
-
console.log(chalk.cyan(' <ChatbotWidget fullScreen />\n'));
|
|
467
|
+
console.log(chalk.white('Frontend Framework:'));
|
|
468
|
+
console.log(chalk.cyan(` • Framework: ${frontendAnswers.framework}\n`));
|
|
428
469
|
|
|
429
|
-
console.log(chalk.
|
|
430
|
-
|
|
470
|
+
console.log(chalk.white('Next steps:\n'));
|
|
471
|
+
if (frontendAnswers.framework === 'react') {
|
|
472
|
+
console.log(chalk.yellow('1. Add the widget to your Next.js/React app:\n'));
|
|
473
|
+
console.log(chalk.cyan(' import { ChatbotWidget } from "agenticaichat";'));
|
|
474
|
+
console.log(chalk.cyan(' \n <ChatbotWidget />\n'));
|
|
475
|
+
|
|
476
|
+
console.log(chalk.yellow('2. Or create a full-page chat route:\n'));
|
|
477
|
+
console.log(chalk.cyan(' // app/chat/page.tsx'));
|
|
478
|
+
console.log(chalk.cyan(' <ChatbotWidget fullScreen />\n'));
|
|
479
|
+
|
|
480
|
+
console.log(chalk.yellow('3. Start your development server:\n'));
|
|
481
|
+
console.log(chalk.cyan(' npm run dev\n'));
|
|
482
|
+
} else if (frontendAnswers.framework === 'angular') {
|
|
483
|
+
console.log(chalk.yellow('1. Set up a backend API endpoint (see README for details).\n'));
|
|
484
|
+
console.log(chalk.yellow('2. Use the universal Web Component:\n'));
|
|
485
|
+
console.log(chalk.cyan(' import "agenticaichat/web-component";'));
|
|
486
|
+
console.log(chalk.cyan(' <agentica-chatbot api="/api/chatbot/query"></agentica-chatbot>\n'));
|
|
487
|
+
console.log(chalk.yellow('3. Or create a custom Angular component (see README).\n'));
|
|
488
|
+
} else if (frontendAnswers.framework === 'vue') {
|
|
489
|
+
console.log(chalk.yellow('1. Set up a backend API endpoint (see README for details).\n'));
|
|
490
|
+
console.log(chalk.yellow('2. Use the universal Web Component:\n'));
|
|
491
|
+
console.log(chalk.cyan(' import "agenticaichat/web-component";'));
|
|
492
|
+
console.log(chalk.cyan(' <agentica-chatbot api="/api/chatbot/query"></agentica-chatbot>\n'));
|
|
493
|
+
console.log(chalk.yellow('3. Or create a custom Vue component (see README).\n'));
|
|
494
|
+
} else {
|
|
495
|
+
console.log(chalk.yellow('1. Implement a small adapter/component in your framework that calls:\n'));
|
|
496
|
+
console.log(chalk.cyan(' POST /api/chatbot/query { query: string }\n'));
|
|
497
|
+
console.log(chalk.yellow('2. Use the response to render messages in your UI.\n'));
|
|
498
|
+
}
|
|
431
499
|
|
|
432
500
|
console.log(chalk.white('Need help? Visit: ') + chalk.blue('https://github.com/yourusername/agenticaichat\n'));
|
|
433
501
|
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Placeholder types and helper for Angular adapters.
|
|
3
|
+
// Angular users should create their own component/service that calls the HTTP API:
|
|
4
|
+
// POST /api/chatbot/query { query: string }
|
|
5
|
+
// and handles the JSON response.
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { ChatbotWidget as ReactChatbotWidget } from '../widget';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ReactChatbotWidget = void 0;
|
|
4
|
+
// Thin alias so future adapters can share a consistent naming scheme.
|
|
5
|
+
// React users should continue to import from "agenticaichat" directly,
|
|
6
|
+
// but this adapter is exposed for symmetry with Angular/Vue.
|
|
7
|
+
var widget_1 = require("../widget");
|
|
8
|
+
Object.defineProperty(exports, "ReactChatbotWidget", { enumerable: true, get: function () { return widget_1.ChatbotWidget; } });
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Placeholder types and helper for Vue adapters.
|
|
3
|
+
// Vue users should create their own component/composable that calls the HTTP API:
|
|
4
|
+
// POST /api/chatbot/query { query: string }
|
|
5
|
+
// and handles the JSON response.
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { ChatbotWidget } from './widget';
|
|
2
|
+
export { ReactChatbotWidget } from './adapters/react';
|
|
2
3
|
export { ChatbotEngine } from './core/ChatbotEngine';
|
|
3
4
|
export { EngineFactory } from './core/EngineFactory';
|
|
4
5
|
export { DatabaseEngine } from './engines/base/DatabaseEngine';
|
|
@@ -18,3 +19,5 @@ export { TogetherAIProvider } from './llm/providers/TogetherAIProvider';
|
|
|
18
19
|
export { DeepInfraProvider } from './llm/providers/DeepInfraProvider';
|
|
19
20
|
export type { DatabaseCategory, SqlDatabaseType, NoSqlDatabaseType, SupportedDatabaseType, DatabaseConfig, DatabaseSchema, TableSchema, ColumnSchema, LLMConfig, LLMProviderType, ChatMessage, QueryRequest, QueryResponse, QueryResult, EngineStatus, ChatbotConfig } from './types';
|
|
20
21
|
export { Logger, logger } from './utils/logger';
|
|
22
|
+
export * from './adapters/angular';
|
|
23
|
+
export * from './adapters/vue';
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,27 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
2
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.logger = exports.Logger = exports.DeepInfraProvider = exports.TogetherAIProvider = exports.GrokProvider = exports.ClaudeProvider = exports.GeminiProvider = exports.OpenAIProvider = exports.LLMFactory = exports.MongoEngine = exports.SQLiteDialect = exports.MySQLDialect = exports.PostgresDialect = exports.NoSqlEngine = exports.SqlEngine = exports.DatabaseEngine = exports.EngineFactory = exports.ChatbotEngine = exports.ChatbotWidget = void 0;
|
|
17
|
+
exports.logger = exports.Logger = exports.DeepInfraProvider = exports.TogetherAIProvider = exports.GrokProvider = exports.ClaudeProvider = exports.GeminiProvider = exports.OpenAIProvider = exports.LLMFactory = exports.MongoEngine = exports.SQLiteDialect = exports.MySQLDialect = exports.PostgresDialect = exports.NoSqlEngine = exports.SqlEngine = exports.DatabaseEngine = exports.EngineFactory = exports.ChatbotEngine = exports.ReactChatbotWidget = exports.ChatbotWidget = void 0;
|
|
4
18
|
// ============================================
|
|
5
19
|
// CLIENT-SIDE EXPORTS (Safe for browser)
|
|
6
20
|
// ============================================
|
|
7
21
|
var widget_1 = require("./widget");
|
|
8
22
|
Object.defineProperty(exports, "ChatbotWidget", { enumerable: true, get: function () { return widget_1.ChatbotWidget; } });
|
|
23
|
+
var react_1 = require("./adapters/react");
|
|
24
|
+
Object.defineProperty(exports, "ReactChatbotWidget", { enumerable: true, get: function () { return react_1.ReactChatbotWidget; } });
|
|
9
25
|
// ============================================
|
|
10
26
|
// SERVER-SIDE EXPORTS (Node.js only)
|
|
11
27
|
// ============================================
|
|
@@ -52,3 +68,6 @@ Object.defineProperty(exports, "DeepInfraProvider", { enumerable: true, get: fun
|
|
|
52
68
|
var logger_1 = require("./utils/logger");
|
|
53
69
|
Object.defineProperty(exports, "Logger", { enumerable: true, get: function () { return logger_1.Logger; } });
|
|
54
70
|
Object.defineProperty(exports, "logger", { enumerable: true, get: function () { return logger_1.logger; } });
|
|
71
|
+
// Framework adapter helper types (for Angular/Vue HTTP adapters)
|
|
72
|
+
__exportStar(require("./adapters/angular"), exports);
|
|
73
|
+
__exportStar(require("./adapters/vue"), exports);
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
class AgenticAIChatbot extends HTMLElement {
|
|
2
|
+
constructor() {
|
|
3
|
+
super();
|
|
4
|
+
this.attachShadow({ mode: 'open' });
|
|
5
|
+
this.apiUrl = this.getAttribute('api') || '/api/chatbot/query';
|
|
6
|
+
this.messages = [];
|
|
7
|
+
this.isOpen = false;
|
|
8
|
+
this.isTyping = false;
|
|
9
|
+
this.render();
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
connectedCallback() {
|
|
13
|
+
this.setupEventListeners();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
render() {
|
|
17
|
+
this.shadowRoot.innerHTML = `
|
|
18
|
+
<style>
|
|
19
|
+
:host {
|
|
20
|
+
position: fixed;
|
|
21
|
+
bottom: 20px;
|
|
22
|
+
right: 20px;
|
|
23
|
+
z-index: 9999;
|
|
24
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.chat-container {
|
|
28
|
+
display: ${this.isOpen ? 'block' : 'none'};
|
|
29
|
+
width: 350px;
|
|
30
|
+
height: 500px;
|
|
31
|
+
background: white;
|
|
32
|
+
border-radius: 12px;
|
|
33
|
+
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
|
|
34
|
+
overflow: hidden;
|
|
35
|
+
position: relative;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.chat-header {
|
|
39
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
40
|
+
color: white;
|
|
41
|
+
padding: 16px;
|
|
42
|
+
font-weight: 600;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.chat-messages {
|
|
46
|
+
height: 380px;
|
|
47
|
+
overflow-y: auto;
|
|
48
|
+
padding: 16px;
|
|
49
|
+
background: #f8f9fa;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.message {
|
|
53
|
+
margin-bottom: 12px;
|
|
54
|
+
padding: 8px 12px;
|
|
55
|
+
border-radius: 8px;
|
|
56
|
+
max-width: 80%;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.message.user {
|
|
60
|
+
background: #007bff;
|
|
61
|
+
color: white;
|
|
62
|
+
margin-left: auto;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.message.bot {
|
|
66
|
+
background: white;
|
|
67
|
+
color: #333;
|
|
68
|
+
border: 1px solid #e9ecef;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.typing {
|
|
72
|
+
display: ${this.isTyping ? 'block' : 'none'};
|
|
73
|
+
font-style: italic;
|
|
74
|
+
color: #666;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.chat-input {
|
|
78
|
+
padding: 16px;
|
|
79
|
+
background: white;
|
|
80
|
+
border-top: 1px solid #e9ecef;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.input-group {
|
|
84
|
+
display: flex;
|
|
85
|
+
gap: 8px;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
input {
|
|
89
|
+
flex: 1;
|
|
90
|
+
padding: 8px 12px;
|
|
91
|
+
border: 1px solid #ddd;
|
|
92
|
+
border-radius: 6px;
|
|
93
|
+
outline: none;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
button {
|
|
97
|
+
padding: 8px 16px;
|
|
98
|
+
background: #007bff;
|
|
99
|
+
color: white;
|
|
100
|
+
border: none;
|
|
101
|
+
border-radius: 6px;
|
|
102
|
+
cursor: pointer;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
button:hover {
|
|
106
|
+
background: #0056b3;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.chat-toggle {
|
|
110
|
+
width: 60px;
|
|
111
|
+
height: 60px;
|
|
112
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
113
|
+
border-radius: 50%;
|
|
114
|
+
border: none;
|
|
115
|
+
color: white;
|
|
116
|
+
font-size: 24px;
|
|
117
|
+
cursor: pointer;
|
|
118
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
|
|
119
|
+
display: flex;
|
|
120
|
+
align-items: center;
|
|
121
|
+
justify-content: center;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.chat-toggle:hover {
|
|
125
|
+
transform: scale(1.05);
|
|
126
|
+
}
|
|
127
|
+
</style>
|
|
128
|
+
|
|
129
|
+
<div class="chat-container">
|
|
130
|
+
<div class="chat-header">
|
|
131
|
+
🤖 AgenticAI Chatbot
|
|
132
|
+
</div>
|
|
133
|
+
<div class="chat-messages" id="messages">
|
|
134
|
+
${this.messages.map(msg => `
|
|
135
|
+
<div class="message ${msg.sender}">
|
|
136
|
+
${msg.text}
|
|
137
|
+
</div>
|
|
138
|
+
`).join('')}
|
|
139
|
+
<div class="message bot typing" id="typing">Typing...</div>
|
|
140
|
+
</div>
|
|
141
|
+
<div class="chat-input">
|
|
142
|
+
<div class="input-group">
|
|
143
|
+
<input type="text" id="messageInput" placeholder="Ask me anything..." />
|
|
144
|
+
<button id="sendButton">Send</button>
|
|
145
|
+
</div>
|
|
146
|
+
</div>
|
|
147
|
+
</div>
|
|
148
|
+
|
|
149
|
+
<button class="chat-toggle" id="toggleButton">
|
|
150
|
+
${this.isOpen ? '✕' : '💬'}
|
|
151
|
+
</button>
|
|
152
|
+
`;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
setupEventListeners() {
|
|
156
|
+
const toggleButton = this.shadowRoot.getElementById('toggleButton');
|
|
157
|
+
const sendButton = this.shadowRoot.getElementById('sendButton');
|
|
158
|
+
const messageInput = this.shadowRoot.getElementById('messageInput');
|
|
159
|
+
|
|
160
|
+
toggleButton.addEventListener('click', () => {
|
|
161
|
+
this.isOpen = !this.isOpen;
|
|
162
|
+
this.render();
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
sendButton.addEventListener('click', () => this.sendMessage());
|
|
166
|
+
messageInput.addEventListener('keypress', (e) => {
|
|
167
|
+
if (e.key === 'Enter') this.sendMessage();
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
async sendMessage() {
|
|
172
|
+
const messageInput = this.shadowRoot.getElementById('messageInput');
|
|
173
|
+
const query = messageInput.value.trim();
|
|
174
|
+
if (!query) return;
|
|
175
|
+
|
|
176
|
+
// Add user message
|
|
177
|
+
this.messages.push({ sender: 'user', text: query });
|
|
178
|
+
messageInput.value = '';
|
|
179
|
+
this.render();
|
|
180
|
+
|
|
181
|
+
// Show typing
|
|
182
|
+
this.isTyping = true;
|
|
183
|
+
this.render();
|
|
184
|
+
|
|
185
|
+
try {
|
|
186
|
+
const response = await fetch(this.apiUrl, {
|
|
187
|
+
method: 'POST',
|
|
188
|
+
headers: {
|
|
189
|
+
'Content-Type': 'application/json',
|
|
190
|
+
},
|
|
191
|
+
body: JSON.stringify({ query }),
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
const data = await response.json();
|
|
195
|
+
|
|
196
|
+
// Hide typing
|
|
197
|
+
this.isTyping = false;
|
|
198
|
+
|
|
199
|
+
if (data.error) {
|
|
200
|
+
this.messages.push({ sender: 'bot', text: `Error: ${data.error}` });
|
|
201
|
+
} else {
|
|
202
|
+
this.messages.push({ sender: 'bot', text: data.answer || data.reply || 'No response' });
|
|
203
|
+
}
|
|
204
|
+
} catch (error) {
|
|
205
|
+
this.isTyping = false;
|
|
206
|
+
this.messages.push({ sender: 'bot', text: 'Sorry, I encountered an error. Please try again.' });
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
this.render();
|
|
210
|
+
this.scrollToBottom();
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
scrollToBottom() {
|
|
214
|
+
const messages = this.shadowRoot.getElementById('messages');
|
|
215
|
+
messages.scrollTop = messages.scrollHeight;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
customElements.define('agentica-chatbot', AgenticAIChatbot);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agenticaichat",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"description": "AI-powered chatbot for business analytics with natural language database queries",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -19,6 +19,10 @@
|
|
|
19
19
|
"types": "./dist/core/index.d.ts",
|
|
20
20
|
"import": "./dist/core/index.js",
|
|
21
21
|
"require": "./dist/core/index.js"
|
|
22
|
+
},
|
|
23
|
+
"./web-component": {
|
|
24
|
+
"import": "./dist/web-component/index.js",
|
|
25
|
+
"require": "./dist/web-component/index.js"
|
|
22
26
|
}
|
|
23
27
|
},
|
|
24
28
|
"bin": {
|
|
@@ -28,10 +32,12 @@
|
|
|
28
32
|
"dist",
|
|
29
33
|
"bin",
|
|
30
34
|
"templates",
|
|
31
|
-
"scripts"
|
|
35
|
+
"scripts",
|
|
36
|
+
"src/web-component"
|
|
32
37
|
],
|
|
33
38
|
"scripts": {
|
|
34
|
-
"build": "tsc",
|
|
39
|
+
"build": "tsc && npm run build:web-component",
|
|
40
|
+
"build:web-component": "if not exist dist\\web-component mkdir dist\\web-component && copy src\\web-component\\* dist\\web-component\\",
|
|
35
41
|
"dev": "tsc --watch",
|
|
36
42
|
"clean": "node -e \"require('fs').rmSync('dist', {recursive: true, force: true})\"",
|
|
37
43
|
"prebuild": "npm run clean",
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
class AgenticAIChatbot extends HTMLElement {
|
|
2
|
+
constructor() {
|
|
3
|
+
super();
|
|
4
|
+
this.attachShadow({ mode: 'open' });
|
|
5
|
+
this.apiUrl = this.getAttribute('api') || '/api/chatbot/query';
|
|
6
|
+
this.messages = [];
|
|
7
|
+
this.isOpen = false;
|
|
8
|
+
this.isTyping = false;
|
|
9
|
+
this.render();
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
connectedCallback() {
|
|
13
|
+
this.setupEventListeners();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
render() {
|
|
17
|
+
this.shadowRoot.innerHTML = `
|
|
18
|
+
<style>
|
|
19
|
+
:host {
|
|
20
|
+
position: fixed;
|
|
21
|
+
bottom: 20px;
|
|
22
|
+
right: 20px;
|
|
23
|
+
z-index: 9999;
|
|
24
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.chat-container {
|
|
28
|
+
display: ${this.isOpen ? 'block' : 'none'};
|
|
29
|
+
width: 350px;
|
|
30
|
+
height: 500px;
|
|
31
|
+
background: white;
|
|
32
|
+
border-radius: 12px;
|
|
33
|
+
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
|
|
34
|
+
overflow: hidden;
|
|
35
|
+
position: relative;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.chat-header {
|
|
39
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
40
|
+
color: white;
|
|
41
|
+
padding: 16px;
|
|
42
|
+
font-weight: 600;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.chat-messages {
|
|
46
|
+
height: 380px;
|
|
47
|
+
overflow-y: auto;
|
|
48
|
+
padding: 16px;
|
|
49
|
+
background: #f8f9fa;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.message {
|
|
53
|
+
margin-bottom: 12px;
|
|
54
|
+
padding: 8px 12px;
|
|
55
|
+
border-radius: 8px;
|
|
56
|
+
max-width: 80%;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.message.user {
|
|
60
|
+
background: #007bff;
|
|
61
|
+
color: white;
|
|
62
|
+
margin-left: auto;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.message.bot {
|
|
66
|
+
background: white;
|
|
67
|
+
color: #333;
|
|
68
|
+
border: 1px solid #e9ecef;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.typing {
|
|
72
|
+
display: ${this.isTyping ? 'block' : 'none'};
|
|
73
|
+
font-style: italic;
|
|
74
|
+
color: #666;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.chat-input {
|
|
78
|
+
padding: 16px;
|
|
79
|
+
background: white;
|
|
80
|
+
border-top: 1px solid #e9ecef;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.input-group {
|
|
84
|
+
display: flex;
|
|
85
|
+
gap: 8px;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
input {
|
|
89
|
+
flex: 1;
|
|
90
|
+
padding: 8px 12px;
|
|
91
|
+
border: 1px solid #ddd;
|
|
92
|
+
border-radius: 6px;
|
|
93
|
+
outline: none;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
button {
|
|
97
|
+
padding: 8px 16px;
|
|
98
|
+
background: #007bff;
|
|
99
|
+
color: white;
|
|
100
|
+
border: none;
|
|
101
|
+
border-radius: 6px;
|
|
102
|
+
cursor: pointer;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
button:hover {
|
|
106
|
+
background: #0056b3;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.chat-toggle {
|
|
110
|
+
width: 60px;
|
|
111
|
+
height: 60px;
|
|
112
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
113
|
+
border-radius: 50%;
|
|
114
|
+
border: none;
|
|
115
|
+
color: white;
|
|
116
|
+
font-size: 24px;
|
|
117
|
+
cursor: pointer;
|
|
118
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
|
|
119
|
+
display: flex;
|
|
120
|
+
align-items: center;
|
|
121
|
+
justify-content: center;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.chat-toggle:hover {
|
|
125
|
+
transform: scale(1.05);
|
|
126
|
+
}
|
|
127
|
+
</style>
|
|
128
|
+
|
|
129
|
+
<div class="chat-container">
|
|
130
|
+
<div class="chat-header">
|
|
131
|
+
🤖 AgenticAI Chatbot
|
|
132
|
+
</div>
|
|
133
|
+
<div class="chat-messages" id="messages">
|
|
134
|
+
${this.messages.map(msg => `
|
|
135
|
+
<div class="message ${msg.sender}">
|
|
136
|
+
${msg.text}
|
|
137
|
+
</div>
|
|
138
|
+
`).join('')}
|
|
139
|
+
<div class="message bot typing" id="typing">Typing...</div>
|
|
140
|
+
</div>
|
|
141
|
+
<div class="chat-input">
|
|
142
|
+
<div class="input-group">
|
|
143
|
+
<input type="text" id="messageInput" placeholder="Ask me anything..." />
|
|
144
|
+
<button id="sendButton">Send</button>
|
|
145
|
+
</div>
|
|
146
|
+
</div>
|
|
147
|
+
</div>
|
|
148
|
+
|
|
149
|
+
<button class="chat-toggle" id="toggleButton">
|
|
150
|
+
${this.isOpen ? '✕' : '💬'}
|
|
151
|
+
</button>
|
|
152
|
+
`;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
setupEventListeners() {
|
|
156
|
+
const toggleButton = this.shadowRoot.getElementById('toggleButton');
|
|
157
|
+
const sendButton = this.shadowRoot.getElementById('sendButton');
|
|
158
|
+
const messageInput = this.shadowRoot.getElementById('messageInput');
|
|
159
|
+
|
|
160
|
+
toggleButton.addEventListener('click', () => {
|
|
161
|
+
this.isOpen = !this.isOpen;
|
|
162
|
+
this.render();
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
sendButton.addEventListener('click', () => this.sendMessage());
|
|
166
|
+
messageInput.addEventListener('keypress', (e) => {
|
|
167
|
+
if (e.key === 'Enter') this.sendMessage();
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
async sendMessage() {
|
|
172
|
+
const messageInput = this.shadowRoot.getElementById('messageInput');
|
|
173
|
+
const query = messageInput.value.trim();
|
|
174
|
+
if (!query) return;
|
|
175
|
+
|
|
176
|
+
// Add user message
|
|
177
|
+
this.messages.push({ sender: 'user', text: query });
|
|
178
|
+
messageInput.value = '';
|
|
179
|
+
this.render();
|
|
180
|
+
|
|
181
|
+
// Show typing
|
|
182
|
+
this.isTyping = true;
|
|
183
|
+
this.render();
|
|
184
|
+
|
|
185
|
+
try {
|
|
186
|
+
const response = await fetch(this.apiUrl, {
|
|
187
|
+
method: 'POST',
|
|
188
|
+
headers: {
|
|
189
|
+
'Content-Type': 'application/json',
|
|
190
|
+
},
|
|
191
|
+
body: JSON.stringify({ query }),
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
const data = await response.json();
|
|
195
|
+
|
|
196
|
+
// Hide typing
|
|
197
|
+
this.isTyping = false;
|
|
198
|
+
|
|
199
|
+
if (data.error) {
|
|
200
|
+
this.messages.push({ sender: 'bot', text: `Error: ${data.error}` });
|
|
201
|
+
} else {
|
|
202
|
+
this.messages.push({ sender: 'bot', text: data.answer || data.reply || 'No response' });
|
|
203
|
+
}
|
|
204
|
+
} catch (error) {
|
|
205
|
+
this.isTyping = false;
|
|
206
|
+
this.messages.push({ sender: 'bot', text: 'Sorry, I encountered an error. Please try again.' });
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
this.render();
|
|
210
|
+
this.scrollToBottom();
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
scrollToBottom() {
|
|
214
|
+
const messages = this.shadowRoot.getElementById('messages');
|
|
215
|
+
messages.scrollTop = messages.scrollHeight;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
customElements.define('agentica-chatbot', AgenticAIChatbot);
|