@5minds/node-red-dashboard-2-processcube-chat 0.1.1-add-functionality-94845a-me8hect9 → 0.1.1-develop-e94793-mcvyrm7g
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/nodes/ui-deepchat.html +102 -87
- package/nodes/ui-deepchat.js +126 -13
- package/package.json +1 -1
- package/resources/ui-deepchat.umd.js +61 -61
- package/resources/ui-deepchat.umd.js.map +1 -1
- package/ui/components/UIDeepChat.vue +290 -322
|
@@ -1,23 +1,30 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="
|
|
3
|
-
<deep-chat
|
|
2
|
+
<div ref="deepChatContainer" class="ui-deepchat-container" :style="containerStyle">
|
|
3
|
+
<deep-chat width="100%"
|
|
4
|
+
ref="deepChat"
|
|
4
5
|
:style="deepChatStyle"
|
|
5
|
-
:
|
|
6
|
-
:
|
|
6
|
+
:intro-message="config.introMessage"
|
|
7
|
+
:text-input="textInputConfig"
|
|
8
|
+
:speech-to-text="speechToTextConfig"
|
|
9
|
+
:camera="cameraConfig"
|
|
10
|
+
:microphone="microphoneConfig"
|
|
11
|
+
:mixed-files="attachmentsConfig"
|
|
12
|
+
:avatars="config.avatars"
|
|
13
|
+
:names="config.names"
|
|
14
|
+
:timestamps="config.timestamps"
|
|
15
|
+
:stream="config.stream"
|
|
7
16
|
:connect="connectConfig"
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
:timestamps="props.timestamps"
|
|
14
|
-
:stream="props.stream"
|
|
17
|
+
@onNewMessage="handleNewMessage"
|
|
18
|
+
@onClearMessages="handleClearMessages"
|
|
19
|
+
@onComponentRender="handleComponentRender"
|
|
20
|
+
@onResponse="handleResponse"
|
|
21
|
+
@onError="handleError"
|
|
15
22
|
></deep-chat>
|
|
16
23
|
</div>
|
|
17
24
|
</template>
|
|
18
25
|
|
|
19
26
|
<script>
|
|
20
|
-
import 'deep-chat'
|
|
27
|
+
import 'deep-chat'
|
|
21
28
|
|
|
22
29
|
export default {
|
|
23
30
|
name: 'UIDeepChat',
|
|
@@ -25,350 +32,311 @@ export default {
|
|
|
25
32
|
inject: ['$socket'],
|
|
26
33
|
data() {
|
|
27
34
|
return {
|
|
28
|
-
|
|
29
|
-
|
|
35
|
+
config: {
|
|
36
|
+
introMessage: 'Hello! How can I help you today?',
|
|
37
|
+
placeholder: 'Type a message...',
|
|
38
|
+
apiUrl: '',
|
|
39
|
+
apiKey: '',
|
|
40
|
+
model: 'gpt-3.5-turbo',
|
|
41
|
+
textInput: true,
|
|
42
|
+
speechToText: false,
|
|
43
|
+
camera: false,
|
|
44
|
+
microphone: false,
|
|
45
|
+
attachments: false,
|
|
46
|
+
avatars: true,
|
|
47
|
+
names: true,
|
|
48
|
+
timestamps: false,
|
|
49
|
+
stream: false
|
|
50
|
+
},
|
|
51
|
+
messages: []
|
|
52
|
+
}
|
|
30
53
|
},
|
|
31
|
-
|
|
54
|
+
|
|
32
55
|
computed: {
|
|
33
|
-
|
|
56
|
+
containerStyle() {
|
|
34
57
|
return {
|
|
35
58
|
width: '100%',
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
};
|
|
59
|
+
height: '100%',
|
|
60
|
+
minHeight: '400px'
|
|
61
|
+
}
|
|
40
62
|
},
|
|
41
63
|
|
|
64
|
+
deepChatStyle() {
|
|
65
|
+
return {
|
|
66
|
+
width: '300px',
|
|
67
|
+
height: '300px',
|
|
68
|
+
flex: '1',
|
|
69
|
+
border: 'none',
|
|
70
|
+
borderRadius: '8px'
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
|
|
74
|
+
speechToTextConfig() {
|
|
75
|
+
return this.config.speechToText ? {
|
|
76
|
+
button: true,
|
|
77
|
+
displayInterimResults: true
|
|
78
|
+
} : false
|
|
79
|
+
},
|
|
80
|
+
|
|
81
|
+
cameraConfig() {
|
|
82
|
+
return this.config.camera ? {
|
|
83
|
+
button: true
|
|
84
|
+
} : false
|
|
85
|
+
},
|
|
86
|
+
|
|
87
|
+
microphoneConfig() {
|
|
88
|
+
return this.config.microphone ? {
|
|
89
|
+
button: true,
|
|
90
|
+
audio: true
|
|
91
|
+
} : false
|
|
92
|
+
},
|
|
93
|
+
|
|
94
|
+
attachmentsConfig() {
|
|
95
|
+
return this.config.attachments ? {
|
|
96
|
+
button: true,
|
|
97
|
+
acceptedFormats: ".jpeg,.jpg,.png,.gif,.pdf,.txt,.doc,.docx"
|
|
98
|
+
} : false
|
|
99
|
+
},
|
|
100
|
+
|
|
42
101
|
textInputConfig() {
|
|
102
|
+
if (!this.config.textInput) return false
|
|
103
|
+
|
|
43
104
|
return {
|
|
44
105
|
placeholder: {
|
|
45
|
-
text: this.
|
|
46
|
-
}
|
|
47
|
-
}
|
|
106
|
+
text: this.config.placeholder
|
|
107
|
+
}
|
|
108
|
+
}
|
|
48
109
|
},
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
return {
|
|
52
|
-
|
|
53
|
-
|
|
110
|
+
|
|
111
|
+
speechToTextConfig() {
|
|
112
|
+
return this.config.speechToText ? {
|
|
113
|
+
button: true,
|
|
114
|
+
displayInterimResults: true
|
|
115
|
+
} : false
|
|
54
116
|
},
|
|
55
|
-
|
|
117
|
+
|
|
118
|
+
cameraConfig() {
|
|
119
|
+
return this.config.camera ? {
|
|
120
|
+
button: true
|
|
121
|
+
} : false
|
|
122
|
+
},
|
|
123
|
+
|
|
124
|
+
microphoneConfig() {
|
|
125
|
+
return this.config.microphone ? {
|
|
126
|
+
button: true,
|
|
127
|
+
audio: true
|
|
128
|
+
} : false
|
|
129
|
+
},
|
|
130
|
+
|
|
131
|
+
attachmentsConfig() {
|
|
132
|
+
return this.config.attachments ? {
|
|
133
|
+
button: true,
|
|
134
|
+
acceptedFormats: ".jpeg,.jpg,.png,.gif,.pdf,.txt,.doc,.docx"
|
|
135
|
+
} : false
|
|
136
|
+
},
|
|
137
|
+
|
|
56
138
|
connectConfig() {
|
|
139
|
+
if (this.config.apiUrl && this.config.apiKey) {
|
|
140
|
+
return {
|
|
141
|
+
url: this.config.apiUrl,
|
|
142
|
+
method: 'POST',
|
|
143
|
+
headers: {
|
|
144
|
+
'Authorization': `Bearer ${this.config.apiKey}`,
|
|
145
|
+
'Content-Type': 'application/json'
|
|
146
|
+
},
|
|
147
|
+
body: {
|
|
148
|
+
model: this.config.model,
|
|
149
|
+
max_tokens: 2000,
|
|
150
|
+
temperature: 0.7
|
|
151
|
+
},
|
|
152
|
+
stream: this.config.stream
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Custom Handler für Node-RED Integration
|
|
57
157
|
return {
|
|
58
|
-
handler: this.
|
|
59
|
-
|
|
60
|
-
|
|
158
|
+
handler: this.handleCustomConnection,
|
|
159
|
+
stream: this.config.stream
|
|
160
|
+
}
|
|
161
|
+
}
|
|
61
162
|
},
|
|
163
|
+
|
|
164
|
+
mounted() {
|
|
165
|
+
this.setupSocketListeners()
|
|
166
|
+
this.applyConfiguration()
|
|
167
|
+
},
|
|
168
|
+
|
|
62
169
|
beforeUnmount() {
|
|
63
|
-
this
|
|
170
|
+
this.removeSocketListeners()
|
|
64
171
|
},
|
|
65
|
-
|
|
172
|
+
|
|
66
173
|
methods: {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
if (files.length > 0 && newMessages.length > 0) {
|
|
89
|
-
const lastMessage = newMessages[newMessages.length - 1];
|
|
90
|
-
lastMessage.files = await this.processFiles(files);
|
|
91
|
-
}
|
|
92
|
-
} else if (body.messages) {
|
|
93
|
-
newMessages = body.messages;
|
|
174
|
+
setupSocketListeners() {
|
|
175
|
+
// Neue Nachricht von Node-RED empfangen
|
|
176
|
+
this.$socket.on('deepchat-newMessage:' + this.id, (data) => {
|
|
177
|
+
this.addMessage(data.message, data.role || 'ai', data.html, data.files)
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
// Konfiguration aktualisieren
|
|
181
|
+
this.$socket.on('deepchat-updateConfig:' + this.id, (newConfig) => {
|
|
182
|
+
this.config = { ...this.config, ...newConfig }
|
|
183
|
+
this.updateConfiguration()
|
|
184
|
+
})
|
|
185
|
+
|
|
186
|
+
// Chat löschen
|
|
187
|
+
this.$socket.on('deepchat-clearMessages:' + this.id, () => {
|
|
188
|
+
this.clearMessages()
|
|
189
|
+
})
|
|
190
|
+
|
|
191
|
+
// Standard Dashboard Message Input
|
|
192
|
+
this.$socket.on('msg-input:' + this.id, (msg) => {
|
|
193
|
+
if (msg.payload) {
|
|
194
|
+
this.addMessage(msg.payload, msg.role || 'ai', msg.html, msg.files)
|
|
94
195
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
|
|
196
|
+
if (msg.config) {
|
|
197
|
+
this.config = { ...this.config, ...msg.config }
|
|
198
|
+
this.updateConfiguration()
|
|
199
|
+
}
|
|
200
|
+
if (msg.clear) {
|
|
201
|
+
this.clearMessages()
|
|
202
|
+
}
|
|
203
|
+
})
|
|
204
|
+
},
|
|
205
|
+
|
|
206
|
+
removeSocketListeners() {
|
|
207
|
+
this.$socket.off('deepchat-newMessage:' + this.id)
|
|
208
|
+
this.$socket.off('deepchat-updateConfig:' + this.id)
|
|
209
|
+
this.$socket.off('deepchat-clearMessages:' + this.id)
|
|
210
|
+
this.$socket.off('msg-input:' + this.id)
|
|
211
|
+
},
|
|
212
|
+
|
|
213
|
+
applyConfiguration() {
|
|
214
|
+
// Konfiguration aus props übernehmen
|
|
215
|
+
if (this.props) {
|
|
216
|
+
Object.keys(this.props).forEach(key => {
|
|
217
|
+
if (this.config.hasOwnProperty(key)) {
|
|
218
|
+
this.config[key] = this.props[key]
|
|
219
|
+
}
|
|
220
|
+
})
|
|
105
221
|
}
|
|
106
222
|
},
|
|
107
|
-
|
|
108
|
-
|
|
223
|
+
|
|
224
|
+
clearMessages() {
|
|
109
225
|
try {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
if (file.type.startsWith('image/')) {
|
|
115
|
-
return await this.processImageFile(file);
|
|
116
|
-
} else if (file.type.startsWith('audio/')) {
|
|
117
|
-
return await this.processAudioFile(file);
|
|
118
|
-
} else {
|
|
119
|
-
// Handle other file types (PDFs, documents, etc.)
|
|
120
|
-
return await this.processDocumentFile(file);
|
|
121
|
-
}
|
|
122
|
-
})
|
|
123
|
-
);
|
|
226
|
+
if (this.$refs.deepChat) {
|
|
227
|
+
this.$refs.deepChat.clearMessages()
|
|
228
|
+
this.messages = []
|
|
229
|
+
}
|
|
124
230
|
} catch (error) {
|
|
125
|
-
console.error('Error
|
|
126
|
-
return [];
|
|
231
|
+
console.error('Error clearing Deep Chat messages:', error)
|
|
127
232
|
}
|
|
128
233
|
},
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
resolve({
|
|
135
|
-
name: file.name,
|
|
136
|
-
type: file.type,
|
|
137
|
-
size: file.size,
|
|
138
|
-
src: e.target.result,
|
|
139
|
-
});
|
|
140
|
-
reader.onerror = () => reject(new Error('Failed to read image'));
|
|
141
|
-
reader.readAsDataURL(file);
|
|
142
|
-
});
|
|
143
|
-
},
|
|
144
|
-
|
|
145
|
-
processAudioFile(file) {
|
|
146
|
-
return new Promise((resolve, reject) => {
|
|
147
|
-
const reader = new FileReader();
|
|
148
|
-
reader.onload = (e) => {
|
|
149
|
-
try {
|
|
150
|
-
const result = e.target.result;
|
|
151
|
-
const commaIndex = result.indexOf(',');
|
|
152
|
-
if (commaIndex === -1) {
|
|
153
|
-
throw new Error('Invalid data URL format: missing comma separator');
|
|
154
|
-
}
|
|
155
|
-
const base64Data = result.split(',')[1]; // Remove data URL prefix
|
|
156
|
-
|
|
157
|
-
resolve({
|
|
158
|
-
name: file.name,
|
|
159
|
-
type: file.type,
|
|
160
|
-
size: file.size,
|
|
161
|
-
base64Data: base64Data,
|
|
162
|
-
});
|
|
163
|
-
} catch (error) {
|
|
164
|
-
reject(error);
|
|
165
|
-
}
|
|
166
|
-
};
|
|
167
|
-
reader.onerror = () => reject(new Error('Failed to read audio'));
|
|
168
|
-
reader.readAsDataURL(file);
|
|
169
|
-
});
|
|
170
|
-
},
|
|
171
|
-
|
|
172
|
-
processDocumentFile(file) {
|
|
173
|
-
return new Promise((resolve, reject) => {
|
|
174
|
-
const reader = new FileReader();
|
|
175
|
-
reader.onload = (e) => {
|
|
176
|
-
try {
|
|
177
|
-
const base64Data = e.target.result.split(',')[1]; // Remove data URL prefix
|
|
178
|
-
|
|
179
|
-
resolve({
|
|
180
|
-
name: file.name,
|
|
181
|
-
type: file.type,
|
|
182
|
-
size: file.size,
|
|
183
|
-
fileData: base64Data, // Use fileData for documents
|
|
184
|
-
});
|
|
185
|
-
} catch (error) {
|
|
186
|
-
reject(error);
|
|
187
|
-
}
|
|
188
|
-
};
|
|
189
|
-
reader.onerror = () => reject(new Error('Failed to read document'));
|
|
190
|
-
reader.readAsDataURL(file);
|
|
191
|
-
});
|
|
192
|
-
},
|
|
193
|
-
|
|
194
|
-
formatForChatGPT(conversation, textOnly = false) {
|
|
195
|
-
const payload = {
|
|
196
|
-
messages: conversation.map((msg) => this.formatMessage(msg, textOnly)),
|
|
197
|
-
model: this.props.model,
|
|
198
|
-
};
|
|
199
|
-
|
|
200
|
-
// Add ChatGPT API extensions
|
|
201
|
-
if (this.props.tools) {
|
|
202
|
-
payload.tools = this.props.tools;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
if (this.props.tool_choice) {
|
|
206
|
-
payload.tool_choice = this.props.tool_choice;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
if (this.props.temperature !== undefined) {
|
|
210
|
-
payload.temperature = this.props.temperature;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
if (this.props.max_tokens) {
|
|
214
|
-
payload.max_tokens = this.props.max_tokens;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
if (this.props.top_p !== undefined) {
|
|
218
|
-
payload.top_p = this.props.top_p;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
if (this.props.frequency_penalty !== undefined) {
|
|
222
|
-
payload.frequency_penalty = this.props.frequency_penalty;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
if (this.props.presence_penalty !== undefined) {
|
|
226
|
-
payload.presence_penalty = this.props.presence_penalty;
|
|
234
|
+
|
|
235
|
+
updateConfiguration() {
|
|
236
|
+
if (this.deepChatInstance) {
|
|
237
|
+
// Bestehende Instanz aktualisieren
|
|
238
|
+
this.applyConfigToElement(this.deepChatInstance)
|
|
227
239
|
}
|
|
228
|
-
|
|
229
|
-
if (this.props.response_format) {
|
|
230
|
-
payload.response_format = this.props.response_format;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
return payload;
|
|
234
240
|
},
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
if (msg.role === 'tool') {
|
|
250
|
-
message.role = 'tool';
|
|
251
|
-
message.content = msg.content;
|
|
252
|
-
message.tool_call_id = msg.tool_call_id;
|
|
253
|
-
return message;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
// Handle messages with files
|
|
257
|
-
if (msg.files && msg.files.length > 0) {
|
|
258
|
-
message.content = this.buildContentArray(msg, textOnly);
|
|
259
|
-
return message;
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
// Handle text-only messages
|
|
263
|
-
message.content = msg.text || msg.content || '';
|
|
264
|
-
return message;
|
|
241
|
+
|
|
242
|
+
handleCustomConnection(body, signals) {
|
|
243
|
+
// Node-RED Integration: Nachricht an Node-RED senden
|
|
244
|
+
this.$socket.emit('chat-message', this.id, {
|
|
245
|
+
message: body.messages || body,
|
|
246
|
+
timestamp: new Date().toISOString(),
|
|
247
|
+
files: body.files || []
|
|
248
|
+
})
|
|
249
|
+
|
|
250
|
+
// Temporary loading message
|
|
251
|
+
signals.onOpen({
|
|
252
|
+
text: 'Processing...',
|
|
253
|
+
role: 'ai'
|
|
254
|
+
})
|
|
265
255
|
},
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
image_url: { url: file.src },
|
|
275
|
-
});
|
|
276
|
-
} else if (!textOnly && file.type && file.type.startsWith('audio/') && file.base64Data) {
|
|
277
|
-
const format = this.getAudioFormat(file.type);
|
|
278
|
-
content.push({
|
|
279
|
-
type: 'input_audio',
|
|
280
|
-
input_audio: {
|
|
281
|
-
data: file.base64Data,
|
|
282
|
-
format: format,
|
|
283
|
-
},
|
|
284
|
-
});
|
|
285
|
-
} else if (!textOnly && file.fileData) {
|
|
286
|
-
content.push({
|
|
287
|
-
type: 'file',
|
|
288
|
-
file: {
|
|
289
|
-
filename: file.name,
|
|
290
|
-
file_data: file.fileData,
|
|
291
|
-
},
|
|
292
|
-
});
|
|
293
|
-
}
|
|
294
|
-
});
|
|
295
|
-
|
|
296
|
-
return content;
|
|
256
|
+
|
|
257
|
+
handleNewMessage(event) {
|
|
258
|
+
// Event an Node-RED weiterleiten
|
|
259
|
+
this.$socket.emit('deepchat-onNewMessage', this.id, {
|
|
260
|
+
message: event.message,
|
|
261
|
+
role: event.role || 'user',
|
|
262
|
+
timestamp: new Date().toISOString()
|
|
263
|
+
})
|
|
297
264
|
},
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
return 'wav';
|
|
265
|
+
|
|
266
|
+
handleClearMessages() {
|
|
267
|
+
// Event an Node-RED weiterleiten
|
|
268
|
+
this.$socket.emit('deepchat-onClearMessages', this.id, {
|
|
269
|
+
timestamp: new Date().toISOString()
|
|
270
|
+
})
|
|
305
271
|
},
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
})
|
|
272
|
+
|
|
273
|
+
handleComponentRender(event) {
|
|
274
|
+
// Event an Node-RED weiterleiten
|
|
275
|
+
this.$socket.emit('deepchat-onComponentRender', this.id, {
|
|
276
|
+
event: event,
|
|
277
|
+
timestamp: new Date().toISOString()
|
|
278
|
+
})
|
|
313
279
|
},
|
|
280
|
+
|
|
281
|
+
handleResponse(event) {
|
|
282
|
+
console.log('Deep Chat Response:', event)
|
|
283
|
+
},
|
|
284
|
+
|
|
285
|
+
handleError(error) {
|
|
286
|
+
console.error('Deep Chat Error:', error)
|
|
287
|
+
|
|
288
|
+
// Fehler an Node-RED melden
|
|
289
|
+
this.$socket.emit('chat-message', this.id, {
|
|
290
|
+
error: error.message || error,
|
|
291
|
+
timestamp: new Date().toISOString()
|
|
292
|
+
})
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
</script>
|
|
314
297
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
role: 'ai',
|
|
323
|
-
content: fullResponse.message?.content || fullResponse.content,
|
|
324
|
-
text: fullResponse.message?.content || fullResponse.content,
|
|
325
|
-
fullResponse: fullResponse,
|
|
326
|
-
};
|
|
298
|
+
<style scoped>
|
|
299
|
+
.ui-deepchat-container {
|
|
300
|
+
position: relative;
|
|
301
|
+
border-radius: 8px;
|
|
302
|
+
overflow: hidden;
|
|
303
|
+
background: var(--v-theme-surface);
|
|
304
|
+
}
|
|
327
305
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
306
|
+
/* Deep Chat Styling Integration */
|
|
307
|
+
.ui-deepchat-container :deep(deep-chat) {
|
|
308
|
+
width: 100% !important;
|
|
309
|
+
height: 100% !important;
|
|
310
|
+
border: none !important;
|
|
311
|
+
border-radius: 8px;
|
|
312
|
+
font-family: var(--v-font-family) !important;
|
|
313
|
+
}
|
|
333
314
|
|
|
334
|
-
|
|
315
|
+
/* Dark theme support */
|
|
316
|
+
.ui-deepchat-container :deep(deep-chat) {
|
|
317
|
+
--chat-background-color: var(--v-theme-surface);
|
|
318
|
+
--user-message-color: var(--v-theme-primary);
|
|
319
|
+
--ai-message-color: var(--v-theme-secondary);
|
|
320
|
+
--border-color: var(--v-theme-outline);
|
|
321
|
+
--text-color: var(--v-theme-on-surface);
|
|
322
|
+
--placeholder-color: var(--v-theme-on-surface-variant);
|
|
323
|
+
}
|
|
335
324
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
role: 'ai',
|
|
342
|
-
});
|
|
343
|
-
} else if (fullResponse.message?.content || fullResponse.content) {
|
|
344
|
-
// Normal text response
|
|
345
|
-
signals.onResponse({
|
|
346
|
-
text: fullResponse.message?.content || fullResponse.content,
|
|
347
|
-
role: 'ai',
|
|
348
|
-
});
|
|
349
|
-
}
|
|
350
|
-
} catch (error) {
|
|
351
|
-
console.error('Error handling response:', error);
|
|
352
|
-
this.sendErrorResponse(signals, 'Error processing response');
|
|
353
|
-
}
|
|
354
|
-
},
|
|
325
|
+
/* Input area styling */
|
|
326
|
+
.ui-deepchat-container :deep(.text-input-container) {
|
|
327
|
+
border-top: 1px solid var(--v-theme-outline) !important;
|
|
328
|
+
background: var(--v-theme-surface) !important;
|
|
329
|
+
}
|
|
355
330
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
role: 'ai',
|
|
361
|
-
});
|
|
362
|
-
}
|
|
363
|
-
},
|
|
364
|
-
},
|
|
365
|
-
};
|
|
366
|
-
</script>
|
|
331
|
+
/* Message bubbles */
|
|
332
|
+
.ui-deepchat-container :deep(.message-bubble) {
|
|
333
|
+
border-radius: 12px !important;
|
|
334
|
+
}
|
|
367
335
|
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
336
|
+
/* Responsive design */
|
|
337
|
+
@media (max-width: 768px) {
|
|
338
|
+
.ui-deepchat-container {
|
|
339
|
+
border-radius: 0;
|
|
340
|
+
}
|
|
373
341
|
}
|
|
374
|
-
</style>
|
|
342
|
+
</style>
|