@foisit/vue-wrapper 2.0.0 → 2.4.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.md CHANGED
@@ -1,35 +1,77 @@
1
1
  # @foisit/vue-wrapper
2
2
 
3
- Power your Vue apps with an AI-driven text assistant.
3
+ [![npm version](https://img.shields.io/npm/v/@foisit/vue-wrapper.svg)](https://www.npmjs.com/package/@foisit/vue-wrapper)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4
5
 
5
- > [!NOTE]
6
- > 🎙️ **Coming Soon**: Voice recognition and responses are planned for a future release. Current support is focused on text-based interactions and AI intent matching.
6
+ > **The AI-Powered Conversational Assistant for Vue Applications**
7
+
8
+ Transform your Vue app into an intelligent, voice-ready platform. Foisit provides a drop-in AI layer that understands natural language, manages multi-step workflows, and executes actions—all with zero backend required.
9
+
10
+ > [!NOTE] > **Voice Support Status**: Voice recognition and responses are currently in development and will be released in a future update. The current version focuses on high-performance text-based interactions and AI intent matching.
7
11
 
8
12
  ---
9
13
 
10
- ## 🚀 Installation
14
+ ## Table of Contents
15
+
16
+ - [Features](#features)
17
+ - [Installation](#installation)
18
+ - [Quick Start](#quick-start)
19
+ - [Core Concepts](#core-concepts)
20
+ - [API Reference](#api-reference)
21
+ - [Advanced Usage](#advanced-usage)
22
+ - [Examples](#examples)
23
+ - [TypeScript Support](#typescript-support)
24
+ - [Best Practices](#best-practices)
25
+
26
+ ---
27
+
28
+ ## Features
29
+
30
+ - **Natural Language Understanding** - AI-powered intent matching using GPT-4o mini (proxied securely)
31
+ - **Smart Slot Filling** - Auto-generates forms for missing parameters
32
+ - **Critical Action Protection** - Built-in confirmation dialogs for dangerous operations
33
+ - **Premium UI** - Glassmorphic overlay with dark/light mode support
34
+ - **Zero Backend Required** - Secure proxy architecture keeps API keys server-side
35
+ - **Vue Native** - Uses Composition API, `provide/inject`, and Vue 3 patterns
36
+ - **Type-Safe** - Full TypeScript support with comprehensive types
37
+ - **Responsive** - Works flawlessly on desktop and mobile
38
+
39
+ ---
40
+
41
+ ## Installation
11
42
 
12
43
  ```bash
13
44
  npm install @foisit/vue-wrapper
14
45
  ```
15
46
 
47
+ ### Peer Dependencies
48
+
49
+ ```json
50
+ {
51
+ "vue": "^3.3.0"
52
+ }
53
+ ```
54
+
16
55
  ---
17
56
 
18
- ## 🔧 Basic Setup
57
+ ## Quick Start
19
58
 
20
- Wrap your application (or a specific layout) in the `AssistantProvider` to enable the assistant.
59
+ ### Step 1: Wrap Your App
21
60
 
22
61
  ```vue
23
62
  <script setup lang="ts">
24
63
  import { AssistantProvider } from '@foisit/vue-wrapper';
25
64
 
26
65
  const config = {
27
- introMessage: 'Hi! How can I help?',
66
+ introMessage: 'Welcome! How can I assist you today?',
28
67
  enableSmartIntent: true,
29
68
  commands: [
30
69
  {
31
- command: 'home',
32
- action: () => router.push('/'),
70
+ command: 'navigate to profile',
71
+ action: () => {
72
+ window.location.href = '/profile';
73
+ return 'Navigating to profile...';
74
+ },
33
75
  },
34
76
  ],
35
77
  };
@@ -37,63 +79,619 @@ const config = {
37
79
 
38
80
  <template>
39
81
  <AssistantProvider :config="config">
40
- <RouterView />
82
+ <YourApp />
41
83
  </AssistantProvider>
42
84
  </template>
43
85
  ```
44
86
 
87
+ ### Step 2: Use the Service
88
+
89
+ ```vue
90
+ <script setup lang="ts">
91
+ import { inject } from 'vue';
92
+ import type { AssistantService } from '@foisit/vue-wrapper';
93
+
94
+ const assistant = inject<AssistantService>('assistantService');
95
+
96
+ const openAssistant = () => {
97
+ assistant?.toggle();
98
+ };
99
+ </script>
100
+
101
+ <template>
102
+ <button @click="openAssistant">Open Assistant</button>
103
+ </template>
104
+ ```
105
+
45
106
  ---
46
107
 
47
- ## 🛡️ Critical Actions
108
+ ## Core Concepts
48
109
 
49
- Commands marked as `critical` will automatically trigger a confirmation flow in the UI.
110
+ ### 1. Commands
50
111
 
51
- ```typescript
52
- const config = {
53
- commands: [
112
+ Commands are the building blocks of your assistant. Each command represents an action users can trigger through natural language.
113
+
114
+ ```javascript
115
+ {
116
+ command: 'delete account',
117
+ description: 'Permanently delete user account',
118
+ action: () => accountService.delete()
119
+ }
120
+ ```
121
+
122
+ ### 2. Parameters (Slot Filling)
123
+
124
+ Define parameters and Foisit will automatically generate forms to collect them:
125
+
126
+ ```javascript
127
+ {
128
+ command: 'create user',
129
+ description: 'Create a new user account',
130
+ parameters: [
131
+ { name: 'username', type: 'string', required: true },
132
+ { name: 'email', type: 'string', required: true },
133
+ { name: 'age', type: 'number', required: false }
134
+ ],
135
+ action: (params) => userService.create(params)
136
+ }
137
+ ```
138
+
139
+ **Supported Parameter Types:**
140
+
141
+ - `string` - Text input
142
+ - `number` - Numeric input
143
+ - `date` - Date picker
144
+ - `select` - Dropdown (static or async options)
145
+ - `file` - File upload input
146
+
147
+ ### 3. File Parameters
148
+
149
+ Collect files via the built-in form UI and receive them in your command `action`.
150
+
151
+ ```javascript
152
+ {
153
+ command: 'upload file',
154
+ description: 'Pick a file and return it to the action',
155
+ parameters: [
54
156
  {
55
- command: 'delete post',
56
- critical: true,
57
- description: 'permanently delete this post',
58
- action: () => api.deletePost(),
157
+ name: 'attachment',
158
+ type: 'file',
159
+ required: true,
160
+ accept: ['image/*', 'audio/*', 'video/*'],
161
+ multiple: false,
162
+ // delivery: 'file' | 'base64' (default: 'file')
163
+ delivery: 'file',
59
164
  },
60
165
  ],
166
+ action: async (params) => {
167
+ const file = params?.attachment;
168
+ if (!file) return { type: 'error', message: 'No file provided.' };
169
+ return {
170
+ type: 'success',
171
+ message: `File received. Name: ${file.name}, Type: ${file.type || 'unknown'}, Size: ${file.size} bytes`,
172
+ };
173
+ },
174
+ }
175
+ ```
176
+
177
+ `FileParameter` supports validations like `maxFiles`, `maxSizeBytes`, `maxTotalBytes`, and media/image constraints like `maxDurationSec`, `maxWidth`, and `maxHeight`.
178
+
179
+ ### 4. Critical Actions
180
+
181
+ Protect dangerous operations with automatic confirmation dialogs:
182
+
183
+ ```javascript
184
+ {
185
+ command: 'delete all data',
186
+ critical: true, // Requires confirmation
187
+ description: 'Permanently delete all application data',
188
+ action: async () => {
189
+ await dataService.deleteAll();
190
+ return 'All data deleted successfully.';
191
+ }
192
+ }
193
+ ```
194
+
195
+ ### 5. Select Parameters (Static)
196
+
197
+ Provide predefined options:
198
+
199
+ ```javascript
200
+ {
201
+ command: 'set theme',
202
+ parameters: [{
203
+ name: 'theme',
204
+ type: 'select',
205
+ options: [
206
+ { label: 'Light Mode', value: 'light' },
207
+ { label: 'Dark Mode', value: 'dark' },
208
+ { label: 'Auto', value: 'auto' }
209
+ ]
210
+ }],
211
+ action: (params) => setTheme(params.theme)
212
+ }
213
+ ```
214
+
215
+ ### 6. Dynamic Select Parameters
216
+
217
+ Load options from APIs:
218
+
219
+ ```javascript
220
+ {
221
+ command: 'assign to user',
222
+ parameters: [{
223
+ name: 'userId',
224
+ type: 'select',
225
+ getOptions: async () => {
226
+ const users = await userService.getAll();
227
+ return users.map(u => ({
228
+ label: `${u.name} (${u.email})`,
229
+ value: u.id
230
+ }));
231
+ }
232
+ }],
233
+ action: (params) => taskService.assign(params.userId)
234
+ }
235
+ ```
236
+
237
+ ---
238
+
239
+ ## API Reference
240
+
241
+ ### `AssistantService` (via `inject`)
242
+
243
+ Injectable service for programmatic control:
244
+
245
+ #### Methods
246
+
247
+ ##### `toggle(onSubmit?, onClose?)`
248
+
249
+ Opens or closes the assistant overlay.
250
+
251
+ ```vue
252
+ <script setup>
253
+ import { inject } from 'vue';
254
+
255
+ const assistant = inject('assistantService');
256
+
257
+ // Basic usage
258
+ const open = () => assistant.toggle();
259
+
260
+ // With callbacks
261
+ const openWithCallbacks = () => {
262
+ assistant.toggle(
263
+ (userInput) => console.log('User said:', userInput),
264
+ () => console.log('Assistant closed')
265
+ );
61
266
  };
267
+ </script>
268
+ ```
269
+
270
+ ##### `addCommand(command, action?)`
271
+
272
+ Dynamically add or update a command at runtime. Commands registered with `addCommand` apply immediately for the running session; they are stored in memory and are not automatically persisted across page reloads.
273
+
274
+ ```vue
275
+ <script setup>
276
+ import { inject, onMounted } from 'vue';
277
+
278
+ const assistant = inject('assistantService');
279
+
280
+ onMounted(() => {
281
+ // Add a simple command
282
+ assistant.addCommand('refresh data', async () => {
283
+ await dataService.refresh();
284
+ return 'Data refreshed!';
285
+ });
286
+
287
+ // Add a command with full config
288
+ assistant.addCommand({
289
+ command: 'export report',
290
+ description: 'Export data as PDF',
291
+ parameters: [
292
+ {
293
+ name: 'format',
294
+ type: 'select',
295
+ options: [
296
+ { label: 'PDF', value: 'pdf' },
297
+ { label: 'Excel', value: 'xlsx' },
298
+ ],
299
+ },
300
+ ],
301
+ action: async (params) => {
302
+ await reportService.export(params.format);
303
+ return `Report exported as ${params.format}`;
304
+ },
305
+ });
306
+ });
307
+ </script>
308
+ ```
309
+
310
+ ### Dynamic Updates (Add / Remove / Update commands at runtime) ✅
311
+
312
+ - Use `addCommand` to add or replace a command for the current runtime.
313
+ - Use `removeCommand(commandPhrase)` to unregister a command immediately.
314
+ - When adding temporary commands inside components, remove them in `onUnmounted` (or equivalent) to avoid leaving stale commands behind.
315
+
316
+ Example — register and remove a temporary command:
317
+
318
+ ```vue
319
+ import { onMounted, onUnmounted, inject } from 'vue'; const assistant = inject('assistantService'); onMounted(() => { assistant?.addCommand('temp action', () => 'Temporary action'); }); onUnmounted(() => { assistant?.removeCommand('temp action'); });
320
+ ```
321
+
322
+ Notes:
323
+
324
+ - Commands with optional parameters can return a `form` InteractiveResponse to prompt the user when no params are provided.
325
+ - Commands are not persisted by default; to persist them, re-register at app startup.
326
+
327
+ ##### `removeCommand(commandPhrase)`
328
+
329
+ Remove a registered command.
330
+
331
+ ```javascript
332
+ assistant.removeCommand('delete account');
333
+ ```
334
+
335
+ ##### `getCommands()`
336
+
337
+ Get list of all registered command names.
338
+
339
+ ```javascript
340
+ const commands = assistant.getCommands();
341
+ console.log('Available commands:', commands);
62
342
  ```
63
343
 
64
344
  ---
65
345
 
66
- ## 🧠 AI Intent Matching
346
+ ## Configuration Options
347
+
348
+ ### `AssistantConfig`
349
+
350
+ ```typescript
351
+ interface AssistantConfig {
352
+ // Activation keyword (optional)
353
+ activationCommand?: string;
354
+
355
+ // Welcome message shown when assistant opens
356
+ introMessage?: string;
357
+
358
+ // Response for unrecognized inputs
359
+ fallbackResponse?: string;
360
+
361
+ // Enable AI-powered natural language understanding
362
+ enableSmartIntent?: boolean;
363
+
364
+ // Input field placeholder text
365
+ inputPlaceholder?: string;
67
366
 
68
- Enable `enableSmartIntent: true` to allow the assistant to understand natural language.
367
+ // List of commands
368
+ commands: AssistantCommand[];
69
369
 
70
- **User says:** _"Go to my profile"_
71
- **Matched Command:** `{ command: 'profile', keywords: ['account', 'user settings'], ... }`
370
+ // Floating button configuration
371
+ floatingButton?: {
372
+ visible?: boolean;
373
+ tooltip?: string;
374
+ customHtml?: string;
375
+ position?: { bottom: string; right: string };
376
+ };
377
+ }
378
+ ```
72
379
 
73
380
  ---
74
381
 
75
- ## 🛠️ Composable Usage: `useAssistant`
382
+ ## Advanced Usage
76
383
 
77
- Interact with the assistant instance from any component within the provider.
384
+ ### Example 1: Multi-Step Booking System with Reactive State
78
385
 
79
386
  ```vue
80
387
  <script setup lang="ts">
81
- import { useAssistant } from '@foisit/vue-wrapper';
388
+ import { ref, inject, onMounted } from 'vue';
389
+ import type { AssistantService } from '@foisit/vue-wrapper';
82
390
 
83
- const assistant = useAssistant();
391
+ const bookings = ref([]);
392
+ const assistant = inject<AssistantService>('assistantService');
84
393
 
85
- const addTempCommand = () => {
86
- assistant.addCommand('clear', () => clearAll());
87
- };
394
+ onMounted(() => {
395
+ assistant?.addCommand({
396
+ command: 'book appointment',
397
+ description: 'Schedule a new appointment',
398
+ parameters: [
399
+ {
400
+ name: 'service',
401
+ type: 'select',
402
+ required: true,
403
+ getOptions: async () => {
404
+ const services = await fetch('/api/services').then((r) => r.json());
405
+ return services.map((s) => ({
406
+ label: s.name,
407
+ value: s.id,
408
+ }));
409
+ },
410
+ },
411
+ { name: 'date', type: 'date', required: true },
412
+ { name: 'notes', type: 'string', required: false },
413
+ ],
414
+ action: async (params) => {
415
+ const booking = await fetch('/api/bookings', {
416
+ method: 'POST',
417
+ body: JSON.stringify(params),
418
+ }).then((r) => r.json());
419
+
420
+ bookings.value.push(booking);
421
+ return {
422
+ type: 'success',
423
+ message: `Appointment booked for ${params.date}!`,
424
+ };
425
+ },
426
+ });
427
+ });
88
428
  </script>
89
429
 
90
430
  <template>
91
- <button @click="addTempCommand">Add Command</button>
431
+ <div>
432
+ <h1>My Bookings: {{ bookings.length }}</h1>
433
+ <button @click="assistant?.toggle()">Book New Appointment</button>
434
+ </div>
92
435
  </template>
93
436
  ```
94
437
 
438
+ ### Example 2: E-Commerce with Vue Router
439
+
440
+ ```vue
441
+ <script setup lang="ts">
442
+ import { inject, onMounted } from 'vue';
443
+ import { useRouter } from 'vue-router';
444
+ import type { AssistantService } from '@foisit/vue-wrapper';
445
+
446
+ const router = useRouter();
447
+ const assistant = inject<AssistantService>('assistantService');
448
+
449
+ onMounted(() => {
450
+ assistant?.addCommand({
451
+ command: 'search products',
452
+ parameters: [
453
+ { name: 'query', type: 'string', required: true },
454
+ {
455
+ name: 'category',
456
+ type: 'select',
457
+ required: false,
458
+ options: [
459
+ { label: 'Electronics', value: 'electronics' },
460
+ { label: 'Clothing', value: 'clothing' },
461
+ { label: 'Books', value: 'books' },
462
+ ],
463
+ },
464
+ { name: 'minPrice', type: 'number', required: false },
465
+ ],
466
+ action: async (params) => {
467
+ const results = await searchProducts(params);
468
+ router.push(`/products?q=${params.query}`);
469
+ return `Found ${results.length} products matching "${params.query}"`;
470
+ },
471
+ });
472
+ });
473
+ </script>
474
+ ```
475
+
476
+ ### Example 3: Form Validation with Composables
477
+
478
+ ```vue
479
+ <script setup lang="ts">
480
+ import { ref, inject, onMounted } from 'vue';
481
+ import { useAuth } from '@/composables/useAuth';
482
+ import type { AssistantService } from '@foisit/vue-wrapper';
483
+
484
+ const { register } = useAuth();
485
+ const user = ref(null);
486
+ const assistant = inject<AssistantService>('assistantService');
487
+
488
+ onMounted(() => {
489
+ assistant?.addCommand({
490
+ command: 'create account',
491
+ parameters: [
492
+ { name: 'email', type: 'string', required: true },
493
+ { name: 'password', type: 'string', required: true },
494
+ { name: 'age', type: 'number', required: true },
495
+ ],
496
+ action: async (params) => {
497
+ // Validation
498
+ if (params.age < 18) {
499
+ return {
500
+ type: 'error',
501
+ message: '❌ You must be 18 or older to create an account.',
502
+ };
503
+ }
504
+
505
+ if (!params.email.includes('@')) {
506
+ return {
507
+ type: 'error',
508
+ message: '❌ Please provide a valid email address.',
509
+ };
510
+ }
511
+
512
+ // Create account
513
+ try {
514
+ const newUser = await register(params);
515
+ user.value = newUser;
516
+ return {
517
+ type: 'success',
518
+ message: '✅ Account created successfully!',
519
+ };
520
+ } catch (error) {
521
+ return {
522
+ type: 'error',
523
+ message: `❌ Registration failed: ${error.message}`,
524
+ };
525
+ }
526
+ },
527
+ });
528
+ });
529
+ </script>
530
+
531
+ <template>
532
+ <div>{{ user ? `Welcome ${user.email}` : 'No user' }}</div>
533
+ </template>
534
+ ```
535
+
536
+ ---
537
+
538
+ ## TypeScript Support
539
+
540
+ ### Full Type Definitions
541
+
542
+ ```typescript
543
+ import type { AssistantCommand, InteractiveResponse } from '@foisit/core';
544
+
545
+ // Type-safe command definition
546
+ const myCommand: AssistantCommand = {
547
+ command: 'update settings',
548
+ description: 'Update user preferences',
549
+ parameters: [
550
+ {
551
+ name: 'theme',
552
+ type: 'select',
553
+ required: true,
554
+ options: [
555
+ { label: 'Light', value: 'light' },
556
+ { label: 'Dark', value: 'dark' },
557
+ ],
558
+ },
559
+ ],
560
+ action: async (params: { theme: string }): Promise<InteractiveResponse> => {
561
+ await settingsService.update(params.theme);
562
+ return {
563
+ type: 'success',
564
+ message: `Theme updated to ${params.theme}`,
565
+ };
566
+ },
567
+ };
568
+ ```
569
+
95
570
  ---
96
571
 
97
- ## 👋 Gesture Activation
572
+ ## Best Practices
573
+
574
+ ### 1. Use `onMounted` for Commands
575
+
576
+ Register commands in `onMounted` to ensure the assistant is ready:
577
+
578
+ ```vue
579
+ <script setup>
580
+ import { inject, onMounted } from 'vue';
581
+
582
+ const assistant = inject('assistantService');
583
+
584
+ onMounted(() => {
585
+ assistant?.addCommand('my command', () => 'Done');
586
+ });
587
+ </script>
588
+ ```
589
+
590
+ ### 2. Type Safety with TypeScript
591
+
592
+ Use proper type imports for better IDE support:
593
+
594
+ ```typescript
595
+ import type { AssistantService } from '@foisit/vue-wrapper';
596
+
597
+ const assistant = inject<AssistantService>('assistantService');
598
+ ```
599
+
600
+ ### 3. Reactive State Updates
601
+
602
+ Use Vue's reactivity for state changes:
603
+
604
+ ```javascript
605
+ action: async () => {
606
+ items.value.push(newItem); // ✅ Reactive update
607
+ return 'Item added';
608
+ };
609
+ ```
610
+
611
+ ### 4. Error Handling
612
+
613
+ Always handle errors gracefully:
614
+
615
+ ```javascript
616
+ action: async (params) => {
617
+ try {
618
+ await apiCall(params);
619
+ return { type: 'success', message: '✅ Success!' };
620
+ } catch (error) {
621
+ return { type: 'error', message: `❌ ${error.message}` };
622
+ }
623
+ };
624
+ ```
625
+
626
+ ---
627
+
628
+ ## Testing
629
+
630
+ ### Unit Testing with Vitest
631
+
632
+ ```typescript
633
+ import { mount } from '@vue/test-utils';
634
+ import { AssistantProvider } from '@foisit/vue-wrapper';
635
+ import App from './App.vue';
636
+
637
+ test('renders assistant', () => {
638
+ const wrapper = mount(App, {
639
+ global: {
640
+ components: { AssistantProvider },
641
+ provide: {
642
+ assistantConfig: { commands: [] },
643
+ },
644
+ },
645
+ });
646
+
647
+ // Test your app with assistant
648
+ });
649
+ ```
650
+
651
+ ---
652
+
653
+ ## Related Packages
654
+
655
+ - **[@foisit/core](../core)** - Core engine (auto-installed)
656
+ - **[@foisit/angular-wrapper](../angular-wrapper)** - Angular integration
657
+ - **[@foisit/react-wrapper](../react-wrapper)** - React integration
658
+
659
+ ---
660
+
661
+ ## Troubleshooting
662
+
663
+ ### Assistant service is undefined
664
+
665
+ Make sure you're using `inject` after the component is mounted and within the `AssistantProvider`.
666
+
667
+ ### Commands not executing
668
+
669
+ Check browser console for errors. Ensure `action` functions are returning values or promises.
670
+
671
+ ### TypeScript errors
672
+
673
+ Make sure you're using Vue 3.3+ and have proper type definitions.
674
+
675
+ ---
676
+
677
+ ## License
678
+
679
+ MIT © [Foisit](https://github.com/boluwatifee4/foisit)
680
+
681
+ ---
682
+
683
+ ## Contributing
684
+
685
+ Contributions are welcome! Please read our [Contributing Guide](../../CONTRIBUTING.md) first.
686
+
687
+ ---
688
+
689
+ ## Support
690
+
691
+ - Email: support@foisit.com
692
+ - Discord: [Join our community](https://discord.gg/foisit)
693
+ - Issues: [GitHub Issues](https://github.com/boluwatifee4/foisit/issues)
694
+
695
+ ---
98
696
 
99
- Once integrated, a subtle **"Powered by Foisit"** watermark appears. **Double-click** it to open the chat overlay.
697
+ **Made with ❤️ by the Foisit Team**