@vezlo/assistant-server 2.7.0 โ 2.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/src/bootstrap/initializeServices.d.ts +2 -0
- package/dist/src/bootstrap/initializeServices.d.ts.map +1 -1
- package/dist/src/bootstrap/initializeServices.js +4 -1
- package/dist/src/bootstrap/initializeServices.js.map +1 -1
- package/dist/src/controllers/ChatController.d.ts +2 -12
- package/dist/src/controllers/ChatController.d.ts.map +1 -1
- package/dist/src/controllers/ChatController.js +38 -192
- package/dist/src/controllers/ChatController.js.map +1 -1
- package/dist/src/controllers/KnowledgeController.d.ts +8 -1
- package/dist/src/controllers/KnowledgeController.d.ts.map +1 -1
- package/dist/src/controllers/KnowledgeController.js +38 -1
- package/dist/src/controllers/KnowledgeController.js.map +1 -1
- package/dist/src/server.js +44 -1
- package/dist/src/server.js.map +1 -1
- package/dist/src/services/CitationService.d.ts +14 -0
- package/dist/src/services/CitationService.d.ts.map +1 -0
- package/dist/src/services/CitationService.js +76 -0
- package/dist/src/services/CitationService.js.map +1 -0
- package/dist/src/services/ResponseGenerationService.d.ts +65 -0
- package/dist/src/services/ResponseGenerationService.d.ts.map +1 -0
- package/dist/src/services/ResponseGenerationService.js +165 -0
- package/dist/src/services/ResponseGenerationService.js.map +1 -0
- package/dist/src/services/ResponseStreamingService.d.ts +33 -0
- package/dist/src/services/ResponseStreamingService.d.ts.map +1 -0
- package/dist/src/services/ResponseStreamingService.js +114 -0
- package/dist/src/services/ResponseStreamingService.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ResponseGenerationService.d.ts","sourceRoot":"","sources":["../../../src/services/ResponseGenerationService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAC;AAC5E,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAGvC,MAAM,WAAW,qBAAqB;IACpC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,OAAO,EAAE,KAAK,CAAC;QACb,aAAa,EAAE,MAAM,CAAC;QACtB,cAAc,EAAE,MAAM,CAAC;QACvB,aAAa,EAAE,MAAM,EAAE,CAAC;KACzB,CAAC,CAAC;CACJ;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,QAAQ,GAAG,WAAW,CAAC;IAC7B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gBAAgB,CAAC,EAAE;QACjB,mBAAmB,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC;YAAC,OAAO,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QACvF,gBAAgB,CAAC,EAAE,MAAM,CAAC;KAC3B,CAAC;IACF,OAAO,CAAC,EAAE,KAAK,CAAC;QACd,aAAa,EAAE,MAAM,CAAC;QACtB,cAAc,EAAE,MAAM,CAAC;QACvB,aAAa,EAAE,MAAM,EAAE,CAAC;KACzB,CAAC,CAAC;CACJ;AAED,qBAAa,yBAAyB;IACpC,OAAO,CAAC,aAAa,CAAC,CAAgB;IACtC,OAAO,CAAC,SAAS,CAAC,CAAY;IAC9B,OAAO,CAAC,iBAAiB,CAAS;gBAGhC,aAAa,EAAE,aAAa,GAAG,SAAS,EACxC,SAAS,EAAE,SAAS,GAAG,SAAS,EAChC,iBAAiB,EAAE,MAAM;IAO3B;;OAEG;IACG,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,0BAA0B,CAAC;IAkBlG;;;OAGG;IACH,kBAAkB,CAChB,MAAM,EAAE,0BAA0B,EAClC,kBAAkB,EAAE,MAAM,GACzB,MAAM,GAAG,IAAI;IAmBhB;;OAEG;IACG,mBAAmB,CACvB,KAAK,EAAE,MAAM,EACb,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,qBAAqB,CAAC;IAsFjC;;OAEG;IACH,gBAAgB,CACd,QAAQ,EAAE,WAAW,EAAE,EACvB,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,GAC/B;QACD,mBAAmB,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC;YAAC,OAAO,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QACvF,gBAAgB,CAAC,EAAE,MAAM,CAAC;KAC3B;IAUD;;OAEG;IACH,YAAY,IAAI,SAAS,GAAG,SAAS;IAIrC;;OAEG;IACH,OAAO,CAAC,mBAAmB;CAa5B"}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ResponseGenerationService = void 0;
|
|
7
|
+
const logger_1 = __importDefault(require("../config/logger"));
|
|
8
|
+
class ResponseGenerationService {
|
|
9
|
+
constructor(intentService, aiService, chatHistoryLength) {
|
|
10
|
+
this.intentService = intentService;
|
|
11
|
+
this.aiService = aiService;
|
|
12
|
+
this.chatHistoryLength = chatHistoryLength;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Classify user intent
|
|
16
|
+
*/
|
|
17
|
+
async classifyIntent(message, history) {
|
|
18
|
+
if (!this.intentService) {
|
|
19
|
+
return {
|
|
20
|
+
intent: 'knowledge',
|
|
21
|
+
needsGuardrail: false,
|
|
22
|
+
contactEmail: null
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
const resolvedHistory = Array.isArray(history) ? history : [];
|
|
26
|
+
logger_1.default.info('๐งญ Classifying user intent...');
|
|
27
|
+
return this.intentService.classify({
|
|
28
|
+
message,
|
|
29
|
+
conversationHistory: resolvedHistory
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Handle intent classification result
|
|
34
|
+
* Returns response content if non-knowledge intent, null if knowledge intent
|
|
35
|
+
*/
|
|
36
|
+
handleIntentResult(result, userMessageContent) {
|
|
37
|
+
if (result.needsGuardrail && result.intent !== 'guardrail') {
|
|
38
|
+
logger_1.default.info('๐ก๏ธ Guardrail triggered');
|
|
39
|
+
return `I can help with documentation or implementation guidance, but I can't share credentials or confidential configuration. Please contact your system administrator or support for access.`;
|
|
40
|
+
}
|
|
41
|
+
logger_1.default.info(`๐งพ Intent result: ${result.intent}${result.needsGuardrail ? ' (guardrail triggered)' : ''}`);
|
|
42
|
+
// For non-knowledge intents, return the response content to be streamed
|
|
43
|
+
if (result.intent !== 'knowledge') {
|
|
44
|
+
const responseContent = result.response || this.getFallbackResponse(result.intent);
|
|
45
|
+
return responseContent;
|
|
46
|
+
}
|
|
47
|
+
// Knowledge intent - proceed to RAG flow (return null to indicate streaming will happen later)
|
|
48
|
+
logger_1.default.info('๐ Intent requires knowledge lookup; proceeding with RAG flow.');
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Search knowledge base and extract sources
|
|
53
|
+
*/
|
|
54
|
+
async searchKnowledgeBase(query, companyId) {
|
|
55
|
+
const sources = [];
|
|
56
|
+
let knowledgeResults = null;
|
|
57
|
+
const aiServiceAny = this.aiService;
|
|
58
|
+
if (!aiServiceAny || !aiServiceAny.knowledgeBaseService) {
|
|
59
|
+
logger_1.default.warn('โ ๏ธ AI service or knowledge base service not available');
|
|
60
|
+
return { knowledgeResults: null, sources: [] };
|
|
61
|
+
}
|
|
62
|
+
try {
|
|
63
|
+
logger_1.default.info(`๐ Searching KB: query="${query.substring(0, 50)}...", companyId=${companyId}`);
|
|
64
|
+
const searchResults = await aiServiceAny.knowledgeBaseService.search(query, {
|
|
65
|
+
limit: 5,
|
|
66
|
+
company_id: companyId
|
|
67
|
+
});
|
|
68
|
+
logger_1.default.info(`๐ Found knowledge base results: ${searchResults.length}`);
|
|
69
|
+
if (searchResults.length > 0) {
|
|
70
|
+
knowledgeResults = '\n\nRelevant information from knowledge base:\n';
|
|
71
|
+
searchResults.forEach((result) => {
|
|
72
|
+
const title = result.title || 'Untitled';
|
|
73
|
+
const content = result.content || '';
|
|
74
|
+
if (content.trim()) {
|
|
75
|
+
knowledgeResults += `- ${title}: ${content}\n`;
|
|
76
|
+
// Extract chunk indices from metadata.chunk_range (e.g., "0-2" -> [0,1,2])
|
|
77
|
+
let chunkIndices = [];
|
|
78
|
+
if (result.metadata?.chunk_range) {
|
|
79
|
+
const [start, end] = result.metadata.chunk_range.split('-').map((n) => parseInt(n, 10));
|
|
80
|
+
if (!isNaN(start) && !isNaN(end)) {
|
|
81
|
+
for (let i = start; i <= end; i++) {
|
|
82
|
+
chunkIndices.push(i);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// Add to sources array (deduplicate by document_uuid)
|
|
87
|
+
if (!sources.find(s => s.document_uuid === result.id)) {
|
|
88
|
+
sources.push({
|
|
89
|
+
document_uuid: result.id,
|
|
90
|
+
document_title: title,
|
|
91
|
+
chunk_indices: chunkIndices
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
const existing = sources.find(s => s.document_uuid === result.id);
|
|
96
|
+
if (existing) {
|
|
97
|
+
// Merge chunk indices
|
|
98
|
+
chunkIndices.forEach(idx => {
|
|
99
|
+
if (!existing.chunk_indices.includes(idx)) {
|
|
100
|
+
existing.chunk_indices.push(idx);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
// Verify we actually have meaningful content (not just the header)
|
|
108
|
+
const headerLength = '\n\nRelevant information from knowledge base:\n'.length;
|
|
109
|
+
if (knowledgeResults.length > headerLength + 10) {
|
|
110
|
+
logger_1.default.info(`โ
Knowledge context prepared (${knowledgeResults.length} chars, ${searchResults.length} results)`);
|
|
111
|
+
logger_1.default.info(`๐ Knowledge preview: ${knowledgeResults.substring(0, 200)}...`);
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
logger_1.default.warn(`โ ๏ธ Knowledge results found but content is empty or too short (${knowledgeResults.length} chars), treating as no results`);
|
|
115
|
+
knowledgeResults = '';
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
knowledgeResults = '';
|
|
120
|
+
logger_1.default.info('โ ๏ธ No knowledge base results found; will return appropriate fallback response');
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
console.error('โ Failed to search knowledge base:', error);
|
|
125
|
+
logger_1.default.error('Failed to search knowledge base:', error);
|
|
126
|
+
knowledgeResults = null;
|
|
127
|
+
}
|
|
128
|
+
return { knowledgeResults, sources };
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Build chat context for AI generation
|
|
132
|
+
*/
|
|
133
|
+
buildChatContext(messages, knowledgeResults) {
|
|
134
|
+
return {
|
|
135
|
+
conversationHistory: messages.map(msg => ({
|
|
136
|
+
role: msg.role,
|
|
137
|
+
content: msg.content
|
|
138
|
+
})),
|
|
139
|
+
knowledgeResults: knowledgeResults ?? undefined
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Get AI service for streaming
|
|
144
|
+
*/
|
|
145
|
+
getAIService() {
|
|
146
|
+
return this.aiService;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Get fallback response for intent
|
|
150
|
+
*/
|
|
151
|
+
getFallbackResponse(intent) {
|
|
152
|
+
const fallbacks = {
|
|
153
|
+
greeting: 'Hello! How can I help you today?',
|
|
154
|
+
acknowledgment: "You're welcome! Let me know if you need anything else.",
|
|
155
|
+
personality: `I'm ${process.env.ASSISTANT_NAME || 'AI Assistant'}, your AI assistant for ${process.env.ORGANIZATION_NAME || 'Your Organization'}.`,
|
|
156
|
+
clarification: "I'm not sure I understood. Could you clarify what you need help with?",
|
|
157
|
+
guardrail: "I can help with documentation or implementation guidance, but I can't share credentials or confidential configuration.",
|
|
158
|
+
human_support_request: "I'd be happy to connect you with our support team. Could you please provide your email address?",
|
|
159
|
+
human_support_email: "Thank you! Our support team will reach out to you shortly."
|
|
160
|
+
};
|
|
161
|
+
return fallbacks[intent] || "I'm here to help. What would you like to know?";
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
exports.ResponseGenerationService = ResponseGenerationService;
|
|
165
|
+
//# sourceMappingURL=ResponseGenerationService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ResponseGenerationService.js","sourceRoot":"","sources":["../../../src/services/ResponseGenerationService.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Response } from 'express';
|
|
2
|
+
export declare class ResponseStreamingService {
|
|
3
|
+
/**
|
|
4
|
+
* Stream text content word by word to simulate streaming
|
|
5
|
+
* This ensures consistent SSE format for all responses
|
|
6
|
+
*/
|
|
7
|
+
streamTextContent(content: string, res: Response): Promise<void>;
|
|
8
|
+
/**
|
|
9
|
+
* Stream AI response chunks with source handling
|
|
10
|
+
*/
|
|
11
|
+
streamAIResponse(stream: AsyncGenerator<{
|
|
12
|
+
chunk: string;
|
|
13
|
+
done: boolean;
|
|
14
|
+
fullContent?: string;
|
|
15
|
+
}, void, unknown>, res: Response, sources?: Array<{
|
|
16
|
+
document_uuid: string;
|
|
17
|
+
document_title: string;
|
|
18
|
+
chunk_indices: number[];
|
|
19
|
+
}>, knowledgeResults?: string | null): Promise<string>;
|
|
20
|
+
/**
|
|
21
|
+
* Send completion event
|
|
22
|
+
*/
|
|
23
|
+
sendCompletionEvent(res: Response, messageUuid: string, parentMessageUuid: string | undefined, createdAt: Date): void;
|
|
24
|
+
/**
|
|
25
|
+
* Send error event
|
|
26
|
+
*/
|
|
27
|
+
sendErrorEvent(res: Response, error: string, message?: string): void;
|
|
28
|
+
/**
|
|
29
|
+
* Setup SSE headers
|
|
30
|
+
*/
|
|
31
|
+
setupSSEHeaders(res: Response): void;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=ResponseStreamingService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ResponseStreamingService.d.ts","sourceRoot":"","sources":["../../../src/services/ResponseStreamingService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAGnC,qBAAa,wBAAwB;IACnC;;;OAGG;IACG,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IA4BtE;;OAEG;IACG,gBAAgB,CACpB,MAAM,EAAE,cAAc,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,IAAI,EAAE,OAAO,CAAC,EAC7F,GAAG,EAAE,QAAQ,EACb,OAAO,CAAC,EAAE,KAAK,CAAC;QACd,aAAa,EAAE,MAAM,CAAC;QACtB,cAAc,EAAE,MAAM,CAAC;QACvB,aAAa,EAAE,MAAM,EAAE,CAAC;KACzB,CAAC,EACF,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,GAC/B,OAAO,CAAC,MAAM,CAAC;IAiDlB;;OAEG;IACH,mBAAmB,CAAC,GAAG,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,GAAG,SAAS,EAAE,SAAS,EAAE,IAAI,GAAG,IAAI;IAWrH;;OAEG;IACH,cAAc,CAAC,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IASpE;;OAEG;IACH,eAAe,CAAC,GAAG,EAAE,QAAQ,GAAG,IAAI;CAMrC"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ResponseStreamingService = void 0;
|
|
7
|
+
const logger_1 = __importDefault(require("../config/logger"));
|
|
8
|
+
class ResponseStreamingService {
|
|
9
|
+
/**
|
|
10
|
+
* Stream text content word by word to simulate streaming
|
|
11
|
+
* This ensures consistent SSE format for all responses
|
|
12
|
+
*/
|
|
13
|
+
async streamTextContent(content, res) {
|
|
14
|
+
const words = content.split(' ');
|
|
15
|
+
const chunkSize = 2; // Stream 2 words at a time for smoother experience
|
|
16
|
+
const totalChunks = Math.ceil(words.length / chunkSize);
|
|
17
|
+
for (let i = 0; i < words.length; i += chunkSize) {
|
|
18
|
+
const chunk = words.slice(i, i + chunkSize).join(' ') + (i + chunkSize < words.length ? ' ' : '');
|
|
19
|
+
const chunkIndex = Math.floor(i / chunkSize) + 1;
|
|
20
|
+
const isLastChunk = chunkIndex === totalChunks;
|
|
21
|
+
const chunkData = JSON.stringify({
|
|
22
|
+
type: 'chunk',
|
|
23
|
+
content: chunk,
|
|
24
|
+
done: isLastChunk, // Mark last chunk with done: true
|
|
25
|
+
sources: undefined // Intent responses have no sources
|
|
26
|
+
});
|
|
27
|
+
res.write(`data: ${chunkData}\n\n`);
|
|
28
|
+
// Flush the response to ensure chunks are sent immediately
|
|
29
|
+
if (res.flush) {
|
|
30
|
+
res.flush();
|
|
31
|
+
}
|
|
32
|
+
// Delay for smooth streaming effect (30ms for better visibility)
|
|
33
|
+
await new Promise(resolve => setTimeout(resolve, 30));
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Stream AI response chunks with source handling
|
|
38
|
+
*/
|
|
39
|
+
async streamAIResponse(stream, res, sources, knowledgeResults) {
|
|
40
|
+
let accumulatedContent = '';
|
|
41
|
+
let chunkCount = 0;
|
|
42
|
+
logger_1.default.info('๐ Starting OpenAI stream...');
|
|
43
|
+
for await (const { chunk, done, fullContent } of stream) {
|
|
44
|
+
chunkCount++;
|
|
45
|
+
// On last chunk, include sources (only if we actually have useful knowledge results)
|
|
46
|
+
// Don't send sources if LLM couldn't answer or apologized
|
|
47
|
+
const shouldIncludeSources = done && sources && sources.length > 0 && knowledgeResults && knowledgeResults.trim().length > 0;
|
|
48
|
+
const chunkData = JSON.stringify({
|
|
49
|
+
type: 'chunk',
|
|
50
|
+
content: chunk,
|
|
51
|
+
done: done || false,
|
|
52
|
+
sources: shouldIncludeSources ? sources : undefined
|
|
53
|
+
});
|
|
54
|
+
// Log sources on last chunk for debugging
|
|
55
|
+
if (shouldIncludeSources) {
|
|
56
|
+
logger_1.default.info(`๐ Sending sources with last chunk: ${JSON.stringify(sources)}`);
|
|
57
|
+
}
|
|
58
|
+
else if (done && sources && sources.length > 0) {
|
|
59
|
+
logger_1.default.info(`โ ๏ธ Sources available but not sent (no knowledge results used)`);
|
|
60
|
+
}
|
|
61
|
+
res.write(`data: ${chunkData}\n\n`);
|
|
62
|
+
if (res.flush)
|
|
63
|
+
res.flush();
|
|
64
|
+
// Update accumulated content
|
|
65
|
+
if (chunk) {
|
|
66
|
+
accumulatedContent += chunk;
|
|
67
|
+
}
|
|
68
|
+
// Log first and last chunks
|
|
69
|
+
if (chunkCount === 1) {
|
|
70
|
+
logger_1.default.info(`๐ค First chunk sent: "${chunk.substring(0, 30)}..."`);
|
|
71
|
+
}
|
|
72
|
+
if (done && fullContent) {
|
|
73
|
+
accumulatedContent = fullContent;
|
|
74
|
+
logger_1.default.info(`๐ Stream complete: ${chunkCount} chunks sent, ${fullContent.length} total chars`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return accumulatedContent;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Send completion event
|
|
81
|
+
*/
|
|
82
|
+
sendCompletionEvent(res, messageUuid, parentMessageUuid, createdAt) {
|
|
83
|
+
const completionData = JSON.stringify({
|
|
84
|
+
type: 'completion',
|
|
85
|
+
uuid: messageUuid,
|
|
86
|
+
parent_message_uuid: parentMessageUuid || '',
|
|
87
|
+
status: 'completed',
|
|
88
|
+
created_at: createdAt.toISOString()
|
|
89
|
+
});
|
|
90
|
+
res.write(`data: ${completionData}\n\n`);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Send error event
|
|
94
|
+
*/
|
|
95
|
+
sendErrorEvent(res, error, message) {
|
|
96
|
+
const errorData = JSON.stringify({
|
|
97
|
+
type: 'error',
|
|
98
|
+
error,
|
|
99
|
+
message: message || 'Unknown error'
|
|
100
|
+
});
|
|
101
|
+
res.write(`data: ${errorData}\n\n`);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Setup SSE headers
|
|
105
|
+
*/
|
|
106
|
+
setupSSEHeaders(res) {
|
|
107
|
+
res.setHeader('Content-Type', 'text/event-stream');
|
|
108
|
+
res.setHeader('Cache-Control', 'no-cache');
|
|
109
|
+
res.setHeader('Connection', 'keep-alive');
|
|
110
|
+
res.setHeader('X-Accel-Buffering', 'no'); // Disable nginx buffering
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
exports.ResponseStreamingService = ResponseStreamingService;
|
|
114
|
+
//# sourceMappingURL=ResponseStreamingService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ResponseStreamingService.js","sourceRoot":"","sources":["../../../src/services/ResponseStreamingService.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vezlo/assistant-server",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.8.0",
|
|
4
4
|
"description": "Production-ready AI Assistant Server with advanced RAG (chunk-based semantic search + adjacent retrieval), conversation management, real-time communication, and human agent handoff",
|
|
5
5
|
"main": "dist/src/server.js",
|
|
6
6
|
"types": "dist/src/server.d.ts",
|