@doderasoftware/restify-ai 0.1.0-beta.4 โ†’ 0.1.0-beta.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +354 -413
  2. package/package.json +21 -9
package/README.md CHANGED
@@ -1,514 +1,455 @@
1
1
  # @doderasoftware/restify-ai
2
2
 
3
- > ๐Ÿค– A fully customizable Vue 3 AI chatbot component library with Laravel Restify integration
3
+ A production-ready AI chatbot component for Vue 3 with real-time SSE streaming, file attachments, @mentions, and seamless Laravel Restify integration.
4
4
 
5
- [![npm version](https://img.shields.io/npm/v/@doderasoftware/restify-ai)](https://www.npmjs.com/package/@doderasoftware/restify-ai)
6
- [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue)](https://www.typescriptlang.org/)
7
- [![Vue 3](https://img.shields.io/badge/Vue-3.x-brightgreen)](https://vuejs.org/)
5
+ [![npm version](https://img.shields.io/npm/v/@doderasoftware/restify-ai.svg)](https://www.npmjs.com/package/@doderasoftware/restify-ai)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+ [![Vue 3](https://img.shields.io/badge/Vue-3.x-brightgreen.svg)](https://vuejs.org/)
8
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.x-blue.svg)](https://www.typescriptlang.org/)
9
+ [![TailwindCSS](https://img.shields.io/badge/TailwindCSS-3.x-38bdf8.svg)](https://tailwindcss.com/)
8
10
 
9
- ---
11
+ **๐Ÿ“– [Laravel Restify](https://laravel-restify.com) | ๐Ÿ“ฆ [npm](https://www.npmjs.com/package/@doderasoftware/restify-ai) | ๐Ÿข [BinarCode](https://binarcode.com)**
10
12
 
11
13
  ## โœจ Features
12
14
 
13
- | Feature | Description |
14
- |---------|-------------|
15
- | ๐Ÿ”Œ **Laravel Restify** | Built for seamless Laravel Restify AI endpoints |
16
- | ๐Ÿ“ก **SSE Streaming** | Real-time streaming responses with Server-Sent Events |
17
- | ๐Ÿ“Ž **File Attachments** | Built-in file upload with progress & preview |
18
- | ๐Ÿ’ฌ **@Mentions** | Pluggable mention providers (employees, projects, etc.) |
19
- | ๐Ÿ’ก **Smart Suggestions** | Route-aware suggestion system |
20
- | ๐ŸŽจ **Fully Customizable** | UI classes, texts, slots, themes |
21
- | โŒจ๏ธ **Keyboard Shortcuts** | Configurable shortcuts (e.g., \`Cmd+G\`) |
22
- | ๐Ÿ”„ **Auto Retry** | Configurable retry logic with exponential backoff |
23
- | ๐Ÿ’พ **Session Persistence** | Chat history survives page refresh |
24
- | ๐ŸŒ™ **Dark Mode** | Full dark mode support out of the box |
25
- | ๐Ÿ“ฆ **Tree-shakable** | Import only what you need |
26
- | ๐ŸŽฏ **TypeScript** | Full TypeScript support |
27
-
28
- ---
15
+ - ๐ŸŒŠ **Real-time SSE Streaming** - Smooth character-by-character response streaming
16
+ - ๐Ÿ“Ž **File Attachments** - Upload and process documents, images, and more
17
+ - ๐Ÿ‘ฅ **@Mentions System** - Reference entities from your application (users, documents, etc.)
18
+ - ๐Ÿ’ก **Context-Aware Suggestions** - Smart prompts based on current page/route
19
+ - ๐Ÿ’ฌ **Chat History** - Persistent conversation memory with configurable limits
20
+ - ๐Ÿ“ **Markdown Rendering** - Beautiful formatting with syntax highlighting
21
+ - ๐Ÿ“Š **Quota Management** - Track and display API usage limits
22
+ - ๐ŸŽจ **Fully Customizable** - Override any style with Tailwind CSS classes
23
+ - ๐ŸŒ™ **Dark Mode Support** - Automatic dark/light theme detection
24
+ - ๐Ÿ“ฑ **Responsive Design** - Works on desktop, tablet, and mobile
25
+ - โŒจ๏ธ **Keyboard Shortcuts** - Quick access with configurable shortcuts (Cmd/Ctrl+G)
26
+ - ๐Ÿ”ณ **Fullscreen Mode** - Expandable chat interface
27
+ - ๐ŸŽฏ **TypeScript First** - Full type definitions included
28
+ - ๐Ÿ—ƒ๏ธ **Pinia Integration** - State management built-in
29
+ - ๐Ÿ”ง **Slot-Based Customization** - Override any component section
30
+ - ๐ŸŒ **i18n Ready** - Full internationalization support
31
+ - ๐Ÿ†˜ **Support Mode** - Route conversations to human agents
32
+ - ๐Ÿ”„ **Retry Logic** - Automatic retry with configurable backoff
33
+ - โš ๏ธ **Error Handling** - User-friendly error messages
29
34
 
30
35
  ## ๐Ÿ“ฆ Installation
31
36
 
32
- \`\`\`bash
37
+ ```bash
33
38
  npm install @doderasoftware/restify-ai
34
- # or
35
- pnpm add @doderasoftware/restify-ai
36
- \`\`\`
39
+ ```
37
40
 
38
- **Peer Dependencies:** \`vue ^3.4\`, \`pinia ^2.1\`
41
+ ### Peer Dependencies
39
42
 
40
- ---
43
+ ```bash
44
+ npm install vue@^3.3.0 pinia@^2.1.0 tailwindcss@^3.3.0
45
+ ```
41
46
 
42
47
  ## ๐Ÿš€ Quick Start
43
48
 
44
- \`\`\`typescript
49
+ ### 1. Configure Tailwind CSS
50
+
51
+ ```javascript
52
+ // tailwind.config.js
53
+ export default {
54
+ content: [
55
+ "./src/**/*.{vue,js,ts,jsx,tsx}",
56
+ "./node_modules/@doderasoftware/restify-ai/dist/**/*.{js,vue}",
57
+ ],
58
+ presets: [
59
+ require("@doderasoftware/restify-ai/tailwind"),
60
+ ],
61
+ }
62
+ ```
63
+
64
+ ### 2. Import Styles
65
+
66
+ ```typescript
67
+ // main.ts
68
+ import "@doderasoftware/restify-ai/styles"
69
+ ```
70
+
71
+ ### 3. Register the Plugin
72
+
73
+ ```typescript
74
+ // plugins/restifyAi.ts
75
+ import { RestifyAiPlugin } from "@doderasoftware/restify-ai"
76
+ import type { App } from "vue"
77
+
78
+ export function setupRestifyAi(app: App) {
79
+ app.use(RestifyAiPlugin, {
80
+ endpoints: {
81
+ ask: "/api/ai/ask",
82
+ uploadFile: "/api/ai/upload",
83
+ quota: "/api/ai/quota",
84
+ },
85
+ getAuthToken: () => localStorage.getItem("token"),
86
+ baseUrl: import.meta.env.VITE_API_URL,
87
+ })
88
+ }
89
+ ```
90
+
91
+ ```typescript
45
92
  // main.ts
46
- import { createApp } from 'vue'
47
- import { createPinia } from 'pinia'
48
- import { RestifyAiPlugin } from '@doderasoftware/restify-ai'
49
- import '@doderasoftware/restify-ai/styles'
93
+ import { createApp } from "vue"
94
+ import { createPinia } from "pinia"
95
+ import App from "./App.vue"
96
+ import { setupRestifyAi } from "./plugins/restifyAi"
97
+ import "@doderasoftware/restify-ai/styles"
50
98
 
51
99
  const app = createApp(App)
52
100
  app.use(createPinia())
101
+ setupRestifyAi(app)
102
+ app.mount("#app")
103
+ ```
53
104
 
54
- app.use(RestifyAiPlugin, {
55
- endpoints: {
56
- ask: '/api/ai/ask', // Required - SSE streaming endpoint
57
- quota: '/api/ai/quota', // Optional - quota endpoint
58
- uploadFile: '/api/ai/upload', // Optional - file upload
59
- },
60
- getAuthToken: () => localStorage.getItem('token'),
61
- })
105
+ ### 4. Add the Component
62
106
 
63
- app.mount('#app')
64
- \`\`\`
65
-
66
- \`\`\`vue
67
- <!-- App.vue -->
107
+ ```vue
68
108
  <template>
69
- <AiChatDrawer v-model="showChat" />
70
- <button @click="showChat = true">Open AI Chat</button>
109
+ <div>
110
+ <button @click="showChat = true" class="fixed bottom-4 right-4 p-3 bg-blue-600 rounded-full">
111
+ <SparklesIcon class="w-6 h-6 text-white" />
112
+ </button>
113
+ <AiChatDrawer v-model="showChat" />
114
+ </div>
71
115
  </template>
72
116
 
73
- <script setup>
74
- import { ref } from 'vue'
75
- import { AiChatDrawer } from '@doderasoftware/restify-ai'
117
+ <script setup lang="ts">
118
+ import { ref } from "vue"
119
+ import { AiChatDrawer } from "@doderasoftware/restify-ai"
76
120
 
77
121
  const showChat = ref(false)
78
122
  </script>
79
- \`\`\`
123
+ ```
80
124
 
81
- ---
125
+ ### 5. Enable Keyboard Shortcut
82
126
 
83
- ## โš™๏ธ Plugin Configuration
127
+ ```typescript
128
+ import { useAiDrawerShortcut } from "@doderasoftware/restify-ai"
84
129
 
85
- ### Required Options
130
+ // Enable Cmd/Ctrl+G to toggle drawer
131
+ useAiDrawerShortcut()
132
+ ```
86
133
 
87
- | Option | Type | Description |
88
- |--------|------|-------------|
89
- | \`endpoints.ask\` | \`string\` | SSE streaming endpoint |
90
- | \`getAuthToken\` | \`() => string \| Promise<string>\` | Auth token getter |
134
+ ## โš™๏ธ Configuration
91
135
 
92
- ### API Configuration
136
+ ### Full Configuration Options
93
137
 
94
- \`\`\`typescript
95
- {
96
- baseUrl: 'https://api.example.com',
138
+ ```typescript
139
+ app.use(RestifyAiPlugin, {
140
+ // REQUIRED
97
141
  endpoints: {
98
- ask: '/api/ai/ask',
99
- quota: '/api/ai/quota',
100
- uploadFile: '/api/ai/upload',
142
+ ask: "/api/ai/ask",
143
+ uploadFile: "/api/ai/upload",
144
+ quota: "/api/ai/quota",
101
145
  },
102
- getAuthToken: () => authStore.token,
103
- getCustomHeaders: () => ({
104
- 'X-CSRF-TOKEN': csrfToken,
105
- 'X-App-Version': '1.0.0',
106
- }),
107
- }
108
- \`\`\`
109
-
110
- ### Request Customization
146
+ getAuthToken: () => localStorage.getItem("auth_token"),
111
147
 
112
- \`\`\`typescript
113
- {
114
- // Modify request payload before sending
115
- buildRequest: (payload) => ({
116
- ...payload,
117
- context: { page: 'dashboard' },
118
- }),
119
-
120
- // Custom stream parser (default: OpenAI format)
121
- parseStreamContent: (data) => JSON.parse(data).content,
122
-
123
- // Request/response interceptors
124
- requestInterceptor: (url, options) => options,
125
- responseInterceptor: (response) => response,
126
- }
127
- \`\`\`
148
+ // API CONFIGURATION
149
+ baseUrl: "https://api.example.com",
150
+ getCustomHeaders: () => ({ "X-Tenant-ID": getTenantId() }),
151
+ buildRequest: (payload) => ({ ...payload, custom: "value" }),
152
+ parseStreamContent: (data) => JSON.parse(data).choices?.[0]?.delta?.content,
128
153
 
129
- ### Retry Configuration
154
+ // RETRY
155
+ retry: { maxRetries: 3, retryDelay: 1000 },
130
156
 
131
- \`\`\`typescript
132
- {
133
- retry: {
134
- maxRetries: 3,
135
- retryDelay: 1000, // ms, multiplied by attempt
136
- shouldRetry: (error, attempt) => error.status >= 500,
157
+ // INTERNATIONALIZATION
158
+ translate: (key, params) => i18n.t("ai." + key, params),
159
+ labels: {
160
+ title: "AI Assistant",
161
+ placeholder: "Ask me anything...",
162
+ loadingText: "Thinking...",
137
163
  },
138
- }
139
- \`\`\`
140
-
141
- ### Providers
142
-
143
- \`\`\`typescript
144
- {
145
- // @Mention providers
146
- mentionProviders: [
147
- {
148
- type: 'employee',
149
- label: 'Employees',
150
- priority: 10,
151
- search: async (query) => api.searchEmployees(query),
152
- },
153
- ],
154
-
155
- // Route-aware suggestions
156
- suggestionProviders: [
157
- {
158
- id: 'dashboard',
159
- routes: ['/dashboard', '/analytics'],
160
- getSuggestions: (context) => [...],
161
- },
162
- ],
163
-
164
- // Default suggestions for empty state
165
- defaultSuggestions: [
166
- { id: '1', title: 'How can you help?', prompt: 'What can you do?' },
167
- ],
168
- }
169
- \`\`\`
170
164
 
171
- ### Limits & Storage
172
-
173
- \`\`\`typescript
174
- {
175
- chatHistoryLimit: 15, // Max messages
176
- maxAttachments: 5, // Max files per message
177
- maxFileSize: 10 * 1024 * 1024, // 10MB
178
- acceptedFileTypes: 'image/*,.pdf,.txt',
179
- chatHistoryKey: 'my_chat_history', // sessionStorage key
180
- drawerStateKey: 'my_drawer_state', // localStorage key
181
- }
182
- \`\`\`
183
-
184
- ### Features
185
-
186
- \`\`\`typescript
187
- {
188
- keyboardShortcut: 'cmd+g', // null to disable
189
- enableSupportMode: true, // Support request toggle
190
- }
191
- \`\`\`
192
-
193
- ### Custom Components
194
-
195
- \`\`\`typescript
196
- {
197
- assistantAvatar: MyAvatarComponent,
198
- userAvatar: UserAvatarComponent,
199
- }
200
- \`\`\`
165
+ // MENTION PROVIDERS
166
+ mentionProviders: [{
167
+ type: "user",
168
+ label: "Users",
169
+ search: async (query) => api.searchUsers(query),
170
+ }],
171
+
172
+ // SUGGESTION PROVIDERS
173
+ suggestionProviders: [{
174
+ id: "invoices",
175
+ routes: ["/invoices/*"],
176
+ getSuggestions: (ctx) => [
177
+ { id: "1", title: "Create Invoice", prompt: "Help me create an invoice" }
178
+ ],
179
+ }],
180
+
181
+ // THEMING
182
+ theme: {
183
+ primaryColor: "#3b82f6",
184
+ userBubbleColor: "#3b82f6",
185
+ drawerWidth: "500px",
186
+ },
201
187
 
202
- ### Lifecycle Callbacks
188
+ // LIMITS
189
+ chatHistoryLimit: 50,
190
+ maxAttachments: 5,
191
+ maxFileSize: 10 * 1024 * 1024,
203
192
 
204
- \`\`\`typescript
205
- {
206
- onError: (error) => console.error(error),
207
- onQuotaFetched: (quota) => console.log(quota),
208
- onMessageSent: (message) => analytics.track('message_sent'),
209
- onResponseReceived: (message) => console.log(message),
210
- onDrawerToggle: (isOpen) => console.log(isOpen),
211
- onNewChat: () => console.log('New chat started'),
212
-
213
- // Stream hooks
214
- onStreamStart: () => console.log('Streaming...'),
215
- onStreamEnd: (fullMessage) => console.log('Done'),
216
- onStreamChunk: (chunk) => console.log(chunk.content),
217
- beforeSend: (payload) => payload,
218
- afterResponse: (message) => saveToHistory(message),
219
-
220
- // File upload hooks
221
- onFileUploadStart: (file) => console.log('Uploading', file.name),
222
- onFileUploadProgress: (file, progress) => console.log(progress),
223
- onFileUploadComplete: (file) => console.log('Done'),
224
- onFileUploadError: (file, error) => console.error(error),
225
- }
226
- \`\`\`
193
+ // FEATURES
194
+ keyboardShortcut: "cmd+g",
195
+ enableSupportMode: true,
227
196
 
228
- ### Labels / i18n
197
+ // CUSTOM AVATARS
198
+ assistantAvatar: CustomAvatarComponent,
199
+ userAvatar: () => currentUser.value?.avatarUrl,
229
200
 
230
- \`\`\`typescript
231
- {
232
- labels: {
233
- aiName: 'My AI Assistant',
234
- inputPlaceholder: 'Type your message...',
235
- emptyStateTitle: 'How can I help?',
236
- // 40+ customizable labels
237
- },
238
- translate: (key, params) => i18n.t(key, params),
239
- can: (permission) => user.hasPermission(permission),
240
- }
241
- \`\`\`
242
-
243
- ---
244
-
245
- ## ๐Ÿงฉ Components
201
+ // CALLBACKS
202
+ onMessageSent: (msg) => analytics.track("ai_sent"),
203
+ onError: (err) => Sentry.captureException(err),
204
+ onStreamStart: () => console.log("Stream started"),
205
+ beforeSend: (payload) => ({ ...payload, timestamp: Date.now() }),
206
+ })
207
+ ```
246
208
 
247
- ### \`<AiChatDrawer>\`
209
+ ## ๐ŸŽจ UI Customization
248
210
 
249
- Main chat drawer component with all features.
211
+ The `:ui` prop allows complete control over every element's styling:
250
212
 
251
- #### Props
213
+ ```vue
214
+ <AiChatDrawer
215
+ v-model="isOpen"
216
+ :ui="{
217
+ backdrop: 'bg-black/50 backdrop-blur-sm',
218
+ drawer: 'shadow-2xl',
219
+ panel: 'bg-gray-50 dark:bg-gray-900',
220
+ header: 'border-b-2 border-blue-500',
221
+ newChatButton: 'bg-gradient-to-r from-blue-500 to-purple-500',
222
+ }"
223
+ />
224
+ ```
225
+
226
+ ### Available UI Keys - AiChatDrawer
227
+
228
+ | Key | Description |
229
+ |-----|-------------|
230
+ | `backdrop` | Backdrop overlay |
231
+ | `drawer` | Drawer container |
232
+ | `panel` | Inner panel |
233
+ | `header` | Header container |
234
+ | `headerTitle` | Header title text |
235
+ | `body` | Chat body area |
236
+ | `footer` | Footer container |
237
+ | `newChatButton` | New chat button |
238
+ | `errorContainer` | Error message container |
239
+ | `retryButton` | Retry button |
240
+
241
+ ### Available UI Keys - ChatInput
242
+
243
+ | Key | Description |
244
+ |-----|-------------|
245
+ | `root` | Input root container |
246
+ | `textarea` | Textarea element |
247
+ | `sendButton` | Send button |
248
+ | `attachButton` | Attachment button |
249
+ | `suggestionsDropdown` | Suggestions dropdown |
250
+
251
+ ### Available UI Keys - ChatMessage
252
+
253
+ | Key | Description |
254
+ |-----|-------------|
255
+ | `root` | Message root container |
256
+ | `userBubble` | User message bubble |
257
+ | `assistantBubble` | Assistant message bubble |
258
+ | `content` | Message content |
259
+ | `loadingDots` | Loading animation dots |
260
+
261
+ ## ๐Ÿ“‹ Props
252
262
 
253
263
  | Prop | Type | Default | Description |
254
264
  |------|------|---------|-------------|
255
- | \`v-model\` | \`boolean\` | - | Drawer visibility |
256
- | \`width\` | \`string\` | \`'600px'\` | Drawer width |
257
- | \`fullscreenWidth\` | \`string\` | \`'90vw'\` | Fullscreen width |
258
- | \`position\` | \`'left' \| 'right'\` | \`'right'\` | Drawer position |
259
- | \`showBackdrop\` | \`boolean\` | \`false\` | Show backdrop overlay |
260
- | \`closeOnBackdropClick\` | \`boolean\` | \`false\` | Close on backdrop click |
261
- | \`closeOnEscape\` | \`boolean\` | \`true\` | Close on Escape key |
262
- | \`showQuota\` | \`boolean\` | \`true\` | Show quota display |
263
- | \`showFullscreenToggle\` | \`boolean\` | \`true\` | Show fullscreen button |
264
- | \`showMinimizeButton\` | \`boolean\` | \`true\` | Show minimize button |
265
- | \`showCloseButton\` | \`boolean\` | \`true\` | Show close button |
266
- | \`showNewChatButton\` | \`boolean\` | \`true\` | Show new chat button |
267
- | \`confirmClose\` | \`boolean\` | \`true\` | Confirm before closing |
268
- | \`ui\` | \`AiChatDrawerUI\` | - | Custom CSS classes |
269
- | \`texts\` | \`AiChatDrawerTexts\` | - | Custom text labels |
270
- | \`historyLimit\` | \`HistoryLimitConfig\` | - | History limit config |
271
- | \`loadingText\` | \`LoadingTextConfig\` | - | Dynamic loading text |
272
-
273
- #### Events
265
+ | `modelValue` | `boolean` | required | Controls drawer visibility (v-model) |
266
+ | `width` | `string` | `"600px"` | Drawer width |
267
+ | `fullscreenWidth` | `string` | `"90vw"` | Width when fullscreen |
268
+ | `topOffset` | `string` | `"0"` | Top offset (for fixed headers) |
269
+ | `position` | `"left" \| "right"` | `"right"` | Drawer position |
270
+ | `showBackdrop` | `boolean` | `false` | Show backdrop overlay |
271
+ | `closeOnEscape` | `boolean` | `true` | Close on Escape key |
272
+ | `showQuota` | `boolean` | `true` | Show quota display |
273
+ | `confirmClose` | `boolean` | `true` | Confirm before clearing |
274
+ | `ui` | `AiChatDrawerUI` | `{}` | Custom CSS classes |
275
+ | `texts` | `AiChatDrawerTexts` | `{}` | Custom text labels |
276
+
277
+ ## ๐Ÿ“ก Events
274
278
 
275
279
  | Event | Payload | Description |
276
280
  |-------|---------|-------------|
277
- | \`close\` | - | Drawer closed |
278
- | \`contact-support\` | - | Support mode triggered |
279
- | \`new-chat\` | - | New chat started |
281
+ | `update:modelValue` | `boolean` | Drawer state changed |
282
+ | `close` | - | Drawer closed |
283
+ | `contact-support` | - | Support mode activated |
284
+ | `new-chat` | - | New chat started |
280
285
 
281
- #### Slots
286
+ ## ๐ŸŽฐ Slots
282
287
 
283
288
  | Slot | Props | Description |
284
289
  |------|-------|-------------|
285
- | \`header\` | \`HeaderSlotProps\` | Custom header |
286
- | \`empty-state\` | \`{ suggestions, onClick }\` | Custom empty state |
287
- | \`message\` | \`MessageSlotProps\` | Custom message rendering |
288
- | \`input\` | \`InputSlotProps\` | Custom input |
289
- | \`quota\` | \`{ quota }\` | Custom quota display |
290
- | \`setup\` | - | Custom setup guide |
291
- | \`context-link\` | - | Link above input |
292
-
293
- ### Other Components
294
-
295
- | Component | Description |
296
- |-----------|-------------|
297
- | \`<ChatInput>\` | Message input with attachments & mentions |
298
- | \`<ChatMessage>\` | Single message display |
299
- | \`<AiEmptyState>\` | Empty state with suggestions |
300
- | \`<MentionList>\` | @mention dropdown |
301
- | \`<AiAvatar>\` | AI avatar icon |
302
- | \`<UserAvatar>\` | User avatar icon |
303
- | \`<ChatMessageActions>\` | Copy/action buttons |
304
-
305
- All components accept \`:ui\` and \`:texts\` props for full customization.
290
+ | `header` | `{ quota, isFullscreen, onNewChat, onClose }` | Custom header |
291
+ | `empty-state` | `{ suggestions, onClick }` | Custom empty state |
292
+ | `message` | `{ message, isUser, isLoading }` | Custom message bubble |
293
+ | `input` | `{ modelValue, sending, onSubmit }` | Custom input area |
294
+
295
+ ```vue
296
+ <AiChatDrawer v-model="isOpen">
297
+ <template #header="{ quota, isFullscreen, onNewChat, onClose }">
298
+ <MyCustomHeader />
299
+ </template>
300
+ <template #empty-state="{ suggestions, onClick }">
301
+ <MyCustomEmptyState />
302
+ </template>
303
+ <template #message="{ message, isUser, isLoading }">
304
+ <MyCustomMessage />
305
+ </template>
306
+ <template #input="{ modelValue, sending, onSubmit }">
307
+ <MyCustomInput />
308
+ </template>
309
+ </AiChatDrawer>
310
+ ```
311
+
312
+ ## ๐Ÿช Store API
313
+
314
+ Access the Pinia store for advanced use cases:
315
+
316
+ ```typescript
317
+ import { useRestifyAiStore } from "@doderasoftware/restify-ai"
306
318
 
307
- ---
308
-
309
- ## ๐ŸŽจ UI Customization
310
-
311
- Every component accepts a \`:ui\` prop for CSS class overrides:
312
-
313
- \`\`\`vue
314
- <AiChatDrawer
315
- :ui="{
316
- drawer: 'my-drawer-class',
317
- header: 'my-header-class',
318
- body: 'my-body-class',
319
- }"
320
- :texts="{
321
- title: 'My AI',
322
- placeholder: 'Ask anything...',
323
- }"
324
- />
325
- \`\`\`
326
-
327
- ### Available UI Props
328
-
329
- - \`AiChatDrawerUI\` - backdrop, drawer, panel, header, body, etc.
330
- - \`ChatInputUI\` - root, textarea, sendButton, attachButton, etc.
331
- - \`ChatMessageUI\` - userBubble, assistantBubble, loadingDots, etc.
332
- - \`AiEmptyStateUI\` - grid, suggestionCard, title, etc.
333
- - \`MentionListUI\` - item, itemSelected, groupHeader, etc.
334
-
335
- ---
336
-
337
- ## ๐Ÿ“š Composables
338
-
339
- \`\`\`typescript
340
- import {
341
- useRestifyAiStore, // Pinia store
342
- useAiSuggestions, // Suggestions management
343
- useAiContext, // Page context
344
- usePageAiContext, // Route-based context
345
- useKeyboardShortcut, // Custom shortcuts
346
- useAiDrawerShortcut, // Drawer toggle shortcut
347
- useMentionParsing, // Parse @mentions
348
- useChatMarkdown, // Markdown rendering
349
- useChatScroll, // Auto-scroll
350
- useChatErrorHandling, // Error management
351
- useLoadingText, // Dynamic loading messages
352
- useHistoryLimit, // History limit dialogs
353
- } from '@doderasoftware/restify-ai'
354
- \`\`\`
355
-
356
- ### Store Actions
357
-
358
- \`\`\`typescript
359
319
  const store = useRestifyAiStore()
360
320
 
361
- store.askQuestion(question, attachments, mentions)
321
+ // State
322
+ store.chatHistory // ChatMessage[]
323
+ store.loading // boolean
324
+ store.sending // boolean
325
+ store.quota // { limit, used, remaining }
326
+ store.error // { message, failedQuestion, timestamp }
327
+
328
+ // Actions
329
+ store.toggleChat()
330
+ store.sendMessage(payload)
362
331
  store.cancelRequest()
363
- store.retry()
332
+ store.retryLastMessage()
364
333
  store.clearChatHistory()
365
- store.clearError()
366
334
  store.fetchQuota()
367
- store.toggleSupportMode()
368
- \`\`\`
335
+ store.uploadFile(file)
336
+ ```
369
337
 
370
- ### Store State
338
+ ## ๐Ÿช Composables
371
339
 
372
- \`\`\`typescript
373
- store.chatHistory // ChatMessage[]
374
- store.sending // boolean
375
- store.error // ChatError
376
- store.quota // ChatQuota
377
- store.showChat // boolean
378
- store.isFullscreen // boolean
379
- store.supportRequestMode // boolean
380
- \`\`\`
340
+ ### useAiDrawerShortcut
381
341
 
382
- ---
342
+ Enable keyboard shortcuts to toggle the chat drawer:
383
343
 
384
- ## ๐Ÿ”ง Advanced Features
344
+ ```typescript
345
+ import { useAiDrawerShortcut } from "@doderasoftware/restify-ai"
385
346
 
386
- ### History Limit Dialog
347
+ // Uses store directly (recommended)
348
+ useAiDrawerShortcut()
387
349
 
388
- \`\`\`vue
389
- <AiChatDrawer
390
- :history-limit="{
391
- limit: 20,
392
- showWarningAt: 3,
393
- warningMessage: 'Almost at limit!',
394
- limitMessage: 'Start a new chat to continue.',
395
- }"
396
- />
397
- \`\`\`
350
+ // Or pass a ref
351
+ const drawerRef = ref(false)
352
+ useAiDrawerShortcut(drawerRef)
353
+ ```
398
354
 
399
- ### Dynamic Loading Text
355
+ ### usePageAiContext
400
356
 
401
- \`\`\`vue
402
- <AiChatDrawer
403
- :loading-text="{
404
- messages: ['Thinking...', 'Analyzing...', 'Almost done...'],
405
- intervals: [0, 2000, 4000],
406
- }"
407
- />
408
- \`\`\`
357
+ Provide page context to the AI for smarter responses:
409
358
 
410
- ### Keyboard Shortcut
359
+ ```typescript
360
+ import { usePageAiContext } from "@doderasoftware/restify-ai"
411
361
 
412
- \`\`\`typescript
413
- // Plugin config
414
- { keyboardShortcut: 'cmd+shift+a' }
362
+ usePageAiContext({
363
+ pageType: "invoice-detail",
364
+ entityId: route.params.id,
365
+ entityType: "invoice",
366
+ metadata: { customerName: invoice.value?.customer?.name },
367
+ })
368
+ ```
415
369
 
416
- // Or use composable
417
- const { toggle } = useAiDrawerShortcut()
418
- \`\`\`
370
+ ## ๐Ÿ”Œ Backend Integration
419
371
 
420
- ---
372
+ This package is designed to work with [Laravel Restify](https://laravel-restify.com):
421
373
 
422
- ## ๐Ÿ“ก Laravel Restify Backend
374
+ ```php
375
+ // routes/api.php
376
+ Route::middleware("auth:sanctum")->group(function () {
377
+ Route::post("/ai/ask", [AiController::class, "ask"]);
378
+ Route::post("/ai/upload", [AiController::class, "upload"]);
379
+ Route::get("/ai/quota", [AiController::class, "quota"]);
380
+ });
381
+ ```
423
382
 
424
- Expected SSE endpoint format:
383
+ ### Expected Request/Response Formats
425
384
 
426
- \`\`\`php
427
- // routes/api.php
428
- Route::post('/ai/ask', [AiController::class, 'ask']);
429
- Route::get('/ai/quota', [AiController::class, 'quota']);
430
- \`\`\`
385
+ **Ask Endpoint (SSE Stream):**
431
386
 
432
- \`\`\`php
433
- // AiController.php
434
- public function ask(Request $request)
387
+ ```typescript
388
+ // Request
435
389
  {
436
- return response()->stream(function () use ($request) {
437
- // Stream OpenAI-format chunks
438
- echo "data: " . json_encode([
439
- 'choices' => [['delta' => ['content' => 'Hello']]]
440
- ]) . "\n\n";
441
- ob_flush();
442
- flush();
443
-
444
- echo "data: [DONE]\n\n";
445
- }, 200, [
446
- 'Content-Type' => 'text/event-stream',
447
- 'Cache-Control' => 'no-cache',
448
- 'X-Accel-Buffering' => 'no',
449
- ]);
390
+ question: string
391
+ history: Array<{ role: string, message: string }>
392
+ stream: true
393
+ files?: Array<{ id: string, name: string }>
394
+ mentions?: Array<{ id: string, type: string, name: string }>
450
395
  }
451
- \`\`\`
452
396
 
453
- ---
397
+ // Response: Server-Sent Events (OpenAI format)
398
+ data: {"choices":[{"delta":{"content":"Hello"}}]}
399
+ data: {"choices":[{"delta":{"content":" world"}}]}
400
+ data: [DONE]
401
+ ```
402
+
403
+ **Upload Endpoint:**
454
404
 
455
- ## ๐Ÿ“ TypeScript Types
405
+ ```typescript
406
+ // Response
407
+ { id: string, name: string, url: string, type: string, size: number }
408
+ ```
456
409
 
457
- All types are exported:
410
+ **Quota Endpoint:**
458
411
 
459
- \`\`\`typescript
412
+ ```typescript
413
+ // Response
414
+ { limit: number, used: number, remaining: number }
415
+ ```
416
+
417
+ ## ๐Ÿ“ TypeScript
418
+
419
+ Full TypeScript support with exported types:
420
+
421
+ ```typescript
460
422
  import type {
461
423
  ChatMessage,
462
424
  ChatAttachment,
463
425
  Mention,
426
+ ChatQuota,
427
+ RestifyAiConfig,
464
428
  MentionProvider,
465
429
  SuggestionProvider,
466
430
  AISuggestion,
467
- RestifyAiConfig,
468
- ChatQuota,
469
- ChatError,
470
- // UI types
471
431
  AiChatDrawerUI,
472
- ChatInputUI,
473
- ChatMessageUI,
474
- // Text types
475
432
  AiChatDrawerTexts,
476
- ChatInputTexts,
477
- // Config types
478
- HistoryLimitConfig,
479
- LoadingTextConfig,
480
- RetryConfig,
481
- // Hook types
482
- BeforeSendHook,
483
- AfterResponseHook,
484
- StreamParserFunction,
485
- } from '@doderasoftware/restify-ai'
486
- \`\`\`
433
+ } from "@doderasoftware/restify-ai"
434
+ ```
487
435
 
488
- ---
436
+ ## ๐ŸŒ Browser Support
489
437
 
490
- ## ๐Ÿ“‹ Quick Reference
491
-
492
- | Feature | Configuration |
493
- |---------|---------------|
494
- | SSE Streaming | Built-in, automatic |
495
- | Keyboard Shortcut | \`keyboardShortcut: 'cmd+g'\` |
496
- | @Mentions | \`mentionProviders: [...]\` |
497
- | Route Suggestions | \`suggestionProviders: [...]\` |
498
- | File Attachments | \`endpoints.uploadFile\` + \`maxAttachments\` |
499
- | Support Mode | \`enableSupportMode: true\` |
500
- | Custom Headers | \`getCustomHeaders: () => ({...})\` |
501
- | Auth Token | \`getAuthToken: () => token\` |
502
- | Base URL | \`baseUrl: 'https://api.example.com'\` |
503
- | Error Handling | \`onError: (err) => {...}\` |
504
- | Retry Logic | \`retry: { maxRetries: 3 }\` |
505
- | UI Customization | \`:ui\` prop on all components |
506
- | Text/i18n | \`:texts\` prop + \`labels\` config |
507
- | History Limit | \`:history-limit\` prop |
508
- | Loading Messages | \`:loading-text\` prop |
438
+ - Chrome 80+
439
+ - Firefox 75+
440
+ - Safari 13+
441
+ - Edge 80+
509
442
 
510
- ---
443
+ ## ๐Ÿ”— Links
444
+
445
+ - [๐Ÿ“– Laravel Restify Documentation](https://laravel-restify.com)
446
+ - [๐Ÿ“ฆ npm Package](https://www.npmjs.com/package/@doderasoftware/restify-ai)
447
+ - [๐Ÿข BinarCode](https://binarcode.com)
511
448
 
512
449
  ## ๐Ÿ“„ License
513
450
 
514
- MIT ยฉ [Dodera Software](https://github.com/doderasoftware)
451
+ MIT ยฉ [BinarCode](https://binarcode.com)
452
+
453
+ ---
454
+
455
+ Built with โค๏ธ by [BinarCode](https://binarcode.com) ยท Published by [Dodera Software](https://doderasoft.com)
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@doderasoftware/restify-ai",
3
- "version": "0.1.0-beta.4",
4
- "description": "Professional AI Chatbot Vue 3 component for Laravel Restify backends. Fully customizable with SSE streaming, file attachments, mentions, and context-aware suggestions.",
3
+ "version": "0.1.0-beta.6",
4
+ "description": "Professional AI Chatbot Vue 3 component for Laravel Restify backends. SSE streaming, file uploads, @mentions, context-aware suggestions, and full TypeScript support.",
5
5
  "type": "module",
6
6
  "main": "./dist/restify-ai.umd.cjs",
7
7
  "module": "./dist/restify-ai.js",
@@ -83,37 +83,49 @@
83
83
  "chatbot",
84
84
  "chat",
85
85
  "assistant",
86
+ "ai-assistant",
86
87
  "laravel",
87
88
  "restify",
88
89
  "laravel-restify",
90
+ "binarcode",
89
91
  "sse",
90
92
  "streaming",
91
93
  "component",
92
94
  "openai",
93
95
  "anthropic",
94
96
  "claude",
97
+ "gpt",
98
+ "llm",
95
99
  "tailwindcss",
96
- "typescript"
100
+ "typescript",
101
+ "pinia",
102
+ "vue-component",
103
+ "chatgpt",
104
+ "ai-chat"
97
105
  ],
98
106
  "author": {
99
- "name": "Dodera Software",
100
- "email": "contact@doderasoftware.com",
101
- "url": "https://doderasoftware.com"
107
+ "name": "BinarCode",
108
+ "email": "hello@binarcode.com",
109
+ "url": "https://binarcode.com"
102
110
  },
103
111
  "license": "MIT",
104
112
  "repository": {
105
113
  "type": "git",
106
- "url": "git+https://github.com/doderasoftware/restify-ai.git"
114
+ "url": "git+https://github.com/BinarCode/restify-ai.git"
107
115
  },
108
116
  "bugs": {
109
- "url": "https://github.com/doderasoftware/restify-ai/issues"
117
+ "url": "https://github.com/BinarCode/restify-ai/issues"
110
118
  },
111
- "homepage": "https://github.com/doderasoftware/restify-ai#readme",
119
+ "homepage": "https://laravel-restify.com",
112
120
  "publishConfig": {
113
121
  "access": "public",
114
122
  "registry": "https://registry.npmjs.org/"
115
123
  },
116
124
  "engines": {
117
125
  "node": ">=18.0.0"
126
+ },
127
+ "funding": {
128
+ "type": "github",
129
+ "url": "https://github.com/sponsors/binarcode"
118
130
  }
119
131
  }