@allanfsouza/aether-sdk 2.4.9 → 2.4.11
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/dist/ai.d.ts +300 -0
- package/dist/ai.js +370 -0
- package/dist/database.js +16 -6
- package/dist/http-client.js +5 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.js +2 -0
- package/package.json +1 -1
- package/src/ai.ts +580 -0
- package/src/database.ts +21 -7
- package/src/http-client.ts +6 -1
- package/src/index.ts +8 -0
package/dist/ai.d.ts
ADDED
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
import type { AxiosInstance } from "axios";
|
|
2
|
+
import type { PlataformaClient } from "./index.js";
|
|
3
|
+
/**
|
|
4
|
+
* Opções para o método chat()
|
|
5
|
+
*/
|
|
6
|
+
export interface ChatOptions {
|
|
7
|
+
/** ID da conversa para manter contexto entre mensagens */
|
|
8
|
+
conversationId?: string;
|
|
9
|
+
/** Contexto adicional (ex: "vendas", "suporte", "produtos") */
|
|
10
|
+
context?: string;
|
|
11
|
+
/** Callback chamado a cada chunk de texto recebido (streaming) */
|
|
12
|
+
onChunk?: (chunk: string) => void;
|
|
13
|
+
/** Callback chamado quando a resposta completa é recebida */
|
|
14
|
+
onComplete?: (fullResponse: string, metadata: ChatMetadata) => void;
|
|
15
|
+
/** Callback chamado em caso de erro */
|
|
16
|
+
onError?: (error: Error) => void;
|
|
17
|
+
/** Timeout em ms (padrão: 30000) */
|
|
18
|
+
timeout?: number;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Metadados retornados após uma resposta completa
|
|
22
|
+
*/
|
|
23
|
+
export interface ChatMetadata {
|
|
24
|
+
conversationId: string;
|
|
25
|
+
messageId?: string;
|
|
26
|
+
tokensUsed?: number;
|
|
27
|
+
sources?: RetrievedSource[];
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Fonte de dados usada pelo RAG
|
|
31
|
+
*/
|
|
32
|
+
export interface RetrievedSource {
|
|
33
|
+
type: string;
|
|
34
|
+
content: string;
|
|
35
|
+
similarity: number;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Resposta do método ask()
|
|
39
|
+
*/
|
|
40
|
+
export interface AskResponse {
|
|
41
|
+
text: string;
|
|
42
|
+
conversationId: string;
|
|
43
|
+
sources?: RetrievedSource[];
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Conversa persistida
|
|
47
|
+
*/
|
|
48
|
+
export interface Conversation {
|
|
49
|
+
id: string;
|
|
50
|
+
title: string;
|
|
51
|
+
context: string;
|
|
52
|
+
createdAt: string;
|
|
53
|
+
updatedAt: string;
|
|
54
|
+
messageCount?: number;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Mensagem de uma conversa
|
|
58
|
+
*/
|
|
59
|
+
export interface Message {
|
|
60
|
+
id: string;
|
|
61
|
+
conversationId: string;
|
|
62
|
+
role: 'user' | 'assistant';
|
|
63
|
+
content: string;
|
|
64
|
+
metadata?: Record<string, any>;
|
|
65
|
+
createdAt: string;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Tipo de feedback
|
|
69
|
+
*/
|
|
70
|
+
export type FeedbackType = 'thumbs_up' | 'thumbs_down';
|
|
71
|
+
/**
|
|
72
|
+
* Opções para busca semântica
|
|
73
|
+
*/
|
|
74
|
+
export interface SemanticSearchOptions {
|
|
75
|
+
/** Número máximo de resultados (padrão: 10) */
|
|
76
|
+
limit?: number;
|
|
77
|
+
/** Score mínimo de similaridade 0-1 (padrão: 0.5) */
|
|
78
|
+
minScore?: number;
|
|
79
|
+
/** Filtrar por collection específica */
|
|
80
|
+
collection?: string;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Resultado de busca semântica
|
|
84
|
+
*/
|
|
85
|
+
export interface SemanticSearchResult {
|
|
86
|
+
id: string;
|
|
87
|
+
content: string;
|
|
88
|
+
collection: string;
|
|
89
|
+
similarity: number;
|
|
90
|
+
metadata?: Record<string, any>;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Opções para geração de conteúdo
|
|
94
|
+
*/
|
|
95
|
+
export interface GenerateOptions {
|
|
96
|
+
/** Tom do texto (formal, casual, técnico, etc) */
|
|
97
|
+
tone?: 'formal' | 'casual' | 'technical' | 'friendly';
|
|
98
|
+
/** Tamanho aproximado (short, medium, long) */
|
|
99
|
+
length?: 'short' | 'medium' | 'long';
|
|
100
|
+
/** Idioma (padrão: pt-BR) */
|
|
101
|
+
language?: string;
|
|
102
|
+
/** Contexto adicional para a geração */
|
|
103
|
+
context?: string;
|
|
104
|
+
}
|
|
105
|
+
export declare class AIModule {
|
|
106
|
+
private client;
|
|
107
|
+
private http;
|
|
108
|
+
/** Sub-módulo para gerenciar conversas */
|
|
109
|
+
conversations: ConversationsAPI;
|
|
110
|
+
/** Sub-módulo para funções administrativas */
|
|
111
|
+
admin: AIAdminAPI;
|
|
112
|
+
constructor(client: PlataformaClient, http: AxiosInstance);
|
|
113
|
+
/**
|
|
114
|
+
* Faz uma pergunta simples e aguarda a resposta completa.
|
|
115
|
+
* Ideal para quando não precisa de streaming.
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* const { text } = await aether.ai.ask("Quais produtos estão em promoção?");
|
|
119
|
+
* console.log(text);
|
|
120
|
+
*/
|
|
121
|
+
ask(message: string, conversationId?: string): Promise<AskResponse>;
|
|
122
|
+
/**
|
|
123
|
+
* Inicia um chat com streaming de resposta.
|
|
124
|
+
* A resposta chega em chunks conforme a IA gera.
|
|
125
|
+
*
|
|
126
|
+
* @example
|
|
127
|
+
* await aether.ai.chat("Explique como funciona o sistema de pagamentos", {
|
|
128
|
+
* onChunk: (chunk) => {
|
|
129
|
+
* // Atualiza UI em tempo real
|
|
130
|
+
* setResponse(prev => prev + chunk);
|
|
131
|
+
* },
|
|
132
|
+
* onComplete: (full, meta) => {
|
|
133
|
+
* console.log("Conversa ID:", meta.conversationId);
|
|
134
|
+
* }
|
|
135
|
+
* });
|
|
136
|
+
*/
|
|
137
|
+
chat(message: string, options?: ChatOptions): Promise<void>;
|
|
138
|
+
/**
|
|
139
|
+
* Envia feedback sobre uma resposta da IA.
|
|
140
|
+
* Ajuda a melhorar as respostas futuras.
|
|
141
|
+
*
|
|
142
|
+
* @example
|
|
143
|
+
* await aether.ai.feedback(messageId, 'thumbs_up');
|
|
144
|
+
* await aether.ai.feedback(messageId, 'thumbs_down', 'Resposta incorreta');
|
|
145
|
+
*/
|
|
146
|
+
feedback(messageId: string, type: FeedbackType, comment?: string): Promise<{
|
|
147
|
+
success: boolean;
|
|
148
|
+
}>;
|
|
149
|
+
/**
|
|
150
|
+
* Busca semântica nos dados do projeto.
|
|
151
|
+
* Encontra documentos similares usando embeddings.
|
|
152
|
+
*
|
|
153
|
+
* @example
|
|
154
|
+
* // Busca produtos similares a uma descrição
|
|
155
|
+
* const results = await aether.ai.search("tênis confortável para corrida");
|
|
156
|
+
*
|
|
157
|
+
* // Com filtros
|
|
158
|
+
* const results = await aether.ai.search("problema no login", {
|
|
159
|
+
* collection: "support_tickets",
|
|
160
|
+
* limit: 5,
|
|
161
|
+
* minScore: 0.7
|
|
162
|
+
* });
|
|
163
|
+
*/
|
|
164
|
+
search(query: string, options?: SemanticSearchOptions): Promise<SemanticSearchResult[]>;
|
|
165
|
+
/**
|
|
166
|
+
* Gera texto baseado em um prompt e contexto.
|
|
167
|
+
* Útil para descrições de produtos, resumos, etc.
|
|
168
|
+
*
|
|
169
|
+
* @example
|
|
170
|
+
* // Gerar descrição de produto
|
|
171
|
+
* const descricao = await aether.ai.generate(
|
|
172
|
+
* "Escreva uma descrição para o produto",
|
|
173
|
+
* { productName: "iPhone 15", price: 5999, features: ["5G", "48MP"] },
|
|
174
|
+
* { tone: 'friendly', length: 'medium' }
|
|
175
|
+
* );
|
|
176
|
+
*/
|
|
177
|
+
generate(prompt: string, data: Record<string, any>, options?: GenerateOptions): Promise<string>;
|
|
178
|
+
/**
|
|
179
|
+
* Analisa dados e retorna insights em linguagem natural.
|
|
180
|
+
*
|
|
181
|
+
* @example
|
|
182
|
+
* const insights = await aether.ai.analyze("orders", {
|
|
183
|
+
* question: "Como foram as vendas essa semana?",
|
|
184
|
+
* period: "7d"
|
|
185
|
+
* });
|
|
186
|
+
*/
|
|
187
|
+
analyze(collection: string, options: {
|
|
188
|
+
question: string;
|
|
189
|
+
period?: string;
|
|
190
|
+
}): Promise<{
|
|
191
|
+
insights: string;
|
|
192
|
+
data?: any;
|
|
193
|
+
}>;
|
|
194
|
+
/**
|
|
195
|
+
* Processa linguagem natural e converte em query estruturada.
|
|
196
|
+
* Útil para criar filtros de busca baseados em texto do usuário.
|
|
197
|
+
*
|
|
198
|
+
* @example
|
|
199
|
+
* const query = await aether.ai.parseQuery(
|
|
200
|
+
* "produtos vermelhos acima de 100 reais ordenados por preço"
|
|
201
|
+
* );
|
|
202
|
+
* // Retorna: { filter: { color: 'vermelho', price: { $gt: 100 } }, sort: { price: 'ASC' } }
|
|
203
|
+
*/
|
|
204
|
+
parseQuery(naturalLanguage: string, collection?: string): Promise<{
|
|
205
|
+
filter?: Record<string, any>;
|
|
206
|
+
sort?: Record<string, any>;
|
|
207
|
+
}>;
|
|
208
|
+
}
|
|
209
|
+
declare class ConversationsAPI {
|
|
210
|
+
private client;
|
|
211
|
+
private http;
|
|
212
|
+
constructor(client: PlataformaClient, http: AxiosInstance);
|
|
213
|
+
/**
|
|
214
|
+
* Lista todas as conversas do usuário no projeto.
|
|
215
|
+
*
|
|
216
|
+
* @example
|
|
217
|
+
* const conversas = await aether.ai.conversations.list();
|
|
218
|
+
*/
|
|
219
|
+
list(): Promise<Conversation[]>;
|
|
220
|
+
/**
|
|
221
|
+
* Busca o histórico de mensagens de uma conversa.
|
|
222
|
+
*
|
|
223
|
+
* @example
|
|
224
|
+
* const mensagens = await aether.ai.conversations.getMessages(conversationId);
|
|
225
|
+
*/
|
|
226
|
+
getMessages(conversationId: string): Promise<Message[]>;
|
|
227
|
+
/**
|
|
228
|
+
* Deleta uma conversa e todo seu histórico.
|
|
229
|
+
*
|
|
230
|
+
* @example
|
|
231
|
+
* await aether.ai.conversations.delete(conversationId);
|
|
232
|
+
*/
|
|
233
|
+
delete(conversationId: string): Promise<{
|
|
234
|
+
success: boolean;
|
|
235
|
+
}>;
|
|
236
|
+
/**
|
|
237
|
+
* Renomeia uma conversa.
|
|
238
|
+
*
|
|
239
|
+
* @example
|
|
240
|
+
* await aether.ai.conversations.rename(conversationId, "Suporte Técnico");
|
|
241
|
+
*/
|
|
242
|
+
rename(conversationId: string, title: string): Promise<Conversation>;
|
|
243
|
+
}
|
|
244
|
+
declare class AIAdminAPI {
|
|
245
|
+
private client;
|
|
246
|
+
private http;
|
|
247
|
+
constructor(client: PlataformaClient, http: AxiosInstance);
|
|
248
|
+
/**
|
|
249
|
+
* Reindexa todos os dados do projeto para RAG.
|
|
250
|
+
* Use após adicionar/modificar grandes volumes de dados.
|
|
251
|
+
* Executa em background.
|
|
252
|
+
*
|
|
253
|
+
* @example
|
|
254
|
+
* await aether.ai.admin.reindex();
|
|
255
|
+
*/
|
|
256
|
+
reindex(): Promise<{
|
|
257
|
+
message: string;
|
|
258
|
+
}>;
|
|
259
|
+
/**
|
|
260
|
+
* Limpa todos os embeddings do projeto.
|
|
261
|
+
* CUIDADO: A IA "esquece" todo o contexto aprendido.
|
|
262
|
+
*
|
|
263
|
+
* @example
|
|
264
|
+
* const { deletedCount } = await aether.ai.admin.clear();
|
|
265
|
+
*/
|
|
266
|
+
clear(): Promise<{
|
|
267
|
+
deletedCount: number;
|
|
268
|
+
}>;
|
|
269
|
+
/**
|
|
270
|
+
* Retorna estatísticas de uso da IA.
|
|
271
|
+
*
|
|
272
|
+
* @example
|
|
273
|
+
* const stats = await aether.ai.admin.stats();
|
|
274
|
+
* console.log(stats.totalConversations, stats.totalMessages);
|
|
275
|
+
*/
|
|
276
|
+
stats(): Promise<{
|
|
277
|
+
totalConversations: number;
|
|
278
|
+
totalMessages: number;
|
|
279
|
+
totalEmbeddings: number;
|
|
280
|
+
storageUsedMB: number;
|
|
281
|
+
}>;
|
|
282
|
+
/**
|
|
283
|
+
* Configura quais collections são indexadas automaticamente.
|
|
284
|
+
*
|
|
285
|
+
* @example
|
|
286
|
+
* await aether.ai.admin.setIndexedCollections(['products', 'articles', 'faq']);
|
|
287
|
+
*/
|
|
288
|
+
setIndexedCollections(collections: string[]): Promise<{
|
|
289
|
+
success: boolean;
|
|
290
|
+
}>;
|
|
291
|
+
/**
|
|
292
|
+
* Busca configurações atuais de IA do projeto.
|
|
293
|
+
*/
|
|
294
|
+
getConfig(): Promise<{
|
|
295
|
+
indexedCollections: string[];
|
|
296
|
+
autoIndex: boolean;
|
|
297
|
+
embeddingModel: string;
|
|
298
|
+
}>;
|
|
299
|
+
}
|
|
300
|
+
export {};
|
package/dist/ai.js
ADDED
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
// src/ai.ts
|
|
2
|
+
// [NOVO] Módulo de IA do Aether SDK
|
|
3
|
+
// Permite que clientes adicionem IA aos seus apps com poucas linhas de código
|
|
4
|
+
// Data: Dezembro 2025
|
|
5
|
+
// =============================================================================
|
|
6
|
+
// MÓDULO PRINCIPAL
|
|
7
|
+
// =============================================================================
|
|
8
|
+
export class AIModule {
|
|
9
|
+
constructor(client, http) {
|
|
10
|
+
this.client = client;
|
|
11
|
+
this.http = http;
|
|
12
|
+
this.conversations = new ConversationsAPI(client, http);
|
|
13
|
+
this.admin = new AIAdminAPI(client, http);
|
|
14
|
+
}
|
|
15
|
+
// ===========================================================================
|
|
16
|
+
// MÉTODOS PRINCIPAIS
|
|
17
|
+
// ===========================================================================
|
|
18
|
+
/**
|
|
19
|
+
* Faz uma pergunta simples e aguarda a resposta completa.
|
|
20
|
+
* Ideal para quando não precisa de streaming.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* const { text } = await aether.ai.ask("Quais produtos estão em promoção?");
|
|
24
|
+
* console.log(text);
|
|
25
|
+
*/
|
|
26
|
+
async ask(message, conversationId) {
|
|
27
|
+
return new Promise((resolve, reject) => {
|
|
28
|
+
let fullText = '';
|
|
29
|
+
let metadata = { conversationId: conversationId || '' };
|
|
30
|
+
this.chat(message, {
|
|
31
|
+
conversationId,
|
|
32
|
+
onChunk: (chunk) => {
|
|
33
|
+
fullText += chunk;
|
|
34
|
+
},
|
|
35
|
+
onComplete: (response, meta) => {
|
|
36
|
+
metadata = meta;
|
|
37
|
+
resolve({
|
|
38
|
+
text: fullText,
|
|
39
|
+
conversationId: meta.conversationId,
|
|
40
|
+
sources: meta.sources
|
|
41
|
+
});
|
|
42
|
+
},
|
|
43
|
+
onError: reject
|
|
44
|
+
}).catch(reject);
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Inicia um chat com streaming de resposta.
|
|
49
|
+
* A resposta chega em chunks conforme a IA gera.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* await aether.ai.chat("Explique como funciona o sistema de pagamentos", {
|
|
53
|
+
* onChunk: (chunk) => {
|
|
54
|
+
* // Atualiza UI em tempo real
|
|
55
|
+
* setResponse(prev => prev + chunk);
|
|
56
|
+
* },
|
|
57
|
+
* onComplete: (full, meta) => {
|
|
58
|
+
* console.log("Conversa ID:", meta.conversationId);
|
|
59
|
+
* }
|
|
60
|
+
* });
|
|
61
|
+
*/
|
|
62
|
+
async chat(message, options = {}) {
|
|
63
|
+
const projectId = this.client.projectId;
|
|
64
|
+
const token = this.client.getToken();
|
|
65
|
+
if (!token) {
|
|
66
|
+
const error = new Error('Usuário não autenticado. Faça login primeiro.');
|
|
67
|
+
if (options.onError) {
|
|
68
|
+
options.onError(error);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
throw error;
|
|
72
|
+
}
|
|
73
|
+
const timeout = options.timeout || 30000;
|
|
74
|
+
const controller = new AbortController();
|
|
75
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
76
|
+
try {
|
|
77
|
+
const response = await fetch(`${this.client.apiUrl}/v1/ai/chat`, {
|
|
78
|
+
method: 'POST',
|
|
79
|
+
headers: {
|
|
80
|
+
'Content-Type': 'application/json',
|
|
81
|
+
'Authorization': `Bearer ${token}`,
|
|
82
|
+
'X-Project-ID': projectId
|
|
83
|
+
},
|
|
84
|
+
body: JSON.stringify({
|
|
85
|
+
message,
|
|
86
|
+
projectId,
|
|
87
|
+
conversationId: options.conversationId,
|
|
88
|
+
context: options.context || 'general'
|
|
89
|
+
}),
|
|
90
|
+
signal: controller.signal
|
|
91
|
+
});
|
|
92
|
+
clearTimeout(timeoutId);
|
|
93
|
+
if (!response.ok) {
|
|
94
|
+
const errorText = await response.text();
|
|
95
|
+
throw new Error(`Erro na API: ${response.status} - ${errorText}`);
|
|
96
|
+
}
|
|
97
|
+
// Captura conversation ID do header (se disponível)
|
|
98
|
+
const convIdFromHeader = response.headers.get('X-Conversation-ID');
|
|
99
|
+
// Processa o stream
|
|
100
|
+
const reader = response.body?.getReader();
|
|
101
|
+
const decoder = new TextDecoder();
|
|
102
|
+
let fullResponse = '';
|
|
103
|
+
if (!reader) {
|
|
104
|
+
throw new Error('Stream não disponível');
|
|
105
|
+
}
|
|
106
|
+
while (true) {
|
|
107
|
+
const { done, value } = await reader.read();
|
|
108
|
+
if (done)
|
|
109
|
+
break;
|
|
110
|
+
const chunk = decoder.decode(value, { stream: true });
|
|
111
|
+
fullResponse += chunk;
|
|
112
|
+
if (options.onChunk) {
|
|
113
|
+
options.onChunk(chunk);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// Callback de conclusão
|
|
117
|
+
if (options.onComplete) {
|
|
118
|
+
options.onComplete(fullResponse, {
|
|
119
|
+
conversationId: convIdFromHeader || options.conversationId || '',
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
clearTimeout(timeoutId);
|
|
125
|
+
if (error.name === 'AbortError') {
|
|
126
|
+
error = new Error(`Timeout: A requisição excedeu ${timeout}ms`);
|
|
127
|
+
}
|
|
128
|
+
if (options.onError) {
|
|
129
|
+
options.onError(error);
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
throw error;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Envia feedback sobre uma resposta da IA.
|
|
138
|
+
* Ajuda a melhorar as respostas futuras.
|
|
139
|
+
*
|
|
140
|
+
* @example
|
|
141
|
+
* await aether.ai.feedback(messageId, 'thumbs_up');
|
|
142
|
+
* await aether.ai.feedback(messageId, 'thumbs_down', 'Resposta incorreta');
|
|
143
|
+
*/
|
|
144
|
+
async feedback(messageId, type, comment) {
|
|
145
|
+
const { data } = await this.http.post('/ai/feedback', {
|
|
146
|
+
messageId,
|
|
147
|
+
feedbackType: type,
|
|
148
|
+
comment
|
|
149
|
+
});
|
|
150
|
+
return data;
|
|
151
|
+
}
|
|
152
|
+
// ===========================================================================
|
|
153
|
+
// BUSCA SEMÂNTICA
|
|
154
|
+
// ===========================================================================
|
|
155
|
+
/**
|
|
156
|
+
* Busca semântica nos dados do projeto.
|
|
157
|
+
* Encontra documentos similares usando embeddings.
|
|
158
|
+
*
|
|
159
|
+
* @example
|
|
160
|
+
* // Busca produtos similares a uma descrição
|
|
161
|
+
* const results = await aether.ai.search("tênis confortável para corrida");
|
|
162
|
+
*
|
|
163
|
+
* // Com filtros
|
|
164
|
+
* const results = await aether.ai.search("problema no login", {
|
|
165
|
+
* collection: "support_tickets",
|
|
166
|
+
* limit: 5,
|
|
167
|
+
* minScore: 0.7
|
|
168
|
+
* });
|
|
169
|
+
*/
|
|
170
|
+
async search(query, options = {}) {
|
|
171
|
+
const { data } = await this.http.post('/ai/search', {
|
|
172
|
+
query,
|
|
173
|
+
projectId: this.client.projectId,
|
|
174
|
+
limit: options.limit || 10,
|
|
175
|
+
minScore: options.minScore || 0.5,
|
|
176
|
+
collection: options.collection
|
|
177
|
+
});
|
|
178
|
+
return data.results;
|
|
179
|
+
}
|
|
180
|
+
// ===========================================================================
|
|
181
|
+
// GERAÇÃO DE CONTEÚDO
|
|
182
|
+
// ===========================================================================
|
|
183
|
+
/**
|
|
184
|
+
* Gera texto baseado em um prompt e contexto.
|
|
185
|
+
* Útil para descrições de produtos, resumos, etc.
|
|
186
|
+
*
|
|
187
|
+
* @example
|
|
188
|
+
* // Gerar descrição de produto
|
|
189
|
+
* const descricao = await aether.ai.generate(
|
|
190
|
+
* "Escreva uma descrição para o produto",
|
|
191
|
+
* { productName: "iPhone 15", price: 5999, features: ["5G", "48MP"] },
|
|
192
|
+
* { tone: 'friendly', length: 'medium' }
|
|
193
|
+
* );
|
|
194
|
+
*/
|
|
195
|
+
async generate(prompt, data, options = {}) {
|
|
196
|
+
const { data: response } = await this.http.post('/ai/generate', {
|
|
197
|
+
prompt,
|
|
198
|
+
data,
|
|
199
|
+
projectId: this.client.projectId,
|
|
200
|
+
tone: options.tone || 'friendly',
|
|
201
|
+
length: options.length || 'medium',
|
|
202
|
+
language: options.language || 'pt-BR',
|
|
203
|
+
context: options.context
|
|
204
|
+
});
|
|
205
|
+
return response.text;
|
|
206
|
+
}
|
|
207
|
+
// ===========================================================================
|
|
208
|
+
// ANÁLISE DE DADOS
|
|
209
|
+
// ===========================================================================
|
|
210
|
+
/**
|
|
211
|
+
* Analisa dados e retorna insights em linguagem natural.
|
|
212
|
+
*
|
|
213
|
+
* @example
|
|
214
|
+
* const insights = await aether.ai.analyze("orders", {
|
|
215
|
+
* question: "Como foram as vendas essa semana?",
|
|
216
|
+
* period: "7d"
|
|
217
|
+
* });
|
|
218
|
+
*/
|
|
219
|
+
async analyze(collection, options) {
|
|
220
|
+
const { data } = await this.http.post('/ai/analyze', {
|
|
221
|
+
collection,
|
|
222
|
+
projectId: this.client.projectId,
|
|
223
|
+
question: options.question,
|
|
224
|
+
period: options.period || '7d'
|
|
225
|
+
});
|
|
226
|
+
return data;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Processa linguagem natural e converte em query estruturada.
|
|
230
|
+
* Útil para criar filtros de busca baseados em texto do usuário.
|
|
231
|
+
*
|
|
232
|
+
* @example
|
|
233
|
+
* const query = await aether.ai.parseQuery(
|
|
234
|
+
* "produtos vermelhos acima de 100 reais ordenados por preço"
|
|
235
|
+
* );
|
|
236
|
+
* // Retorna: { filter: { color: 'vermelho', price: { $gt: 100 } }, sort: { price: 'ASC' } }
|
|
237
|
+
*/
|
|
238
|
+
async parseQuery(naturalLanguage, collection) {
|
|
239
|
+
const { data } = await this.http.post('/ai/parse-query', {
|
|
240
|
+
query: naturalLanguage,
|
|
241
|
+
collection,
|
|
242
|
+
projectId: this.client.projectId
|
|
243
|
+
});
|
|
244
|
+
return data;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
// =============================================================================
|
|
248
|
+
// SUB-MÓDULO: CONVERSAS
|
|
249
|
+
// =============================================================================
|
|
250
|
+
class ConversationsAPI {
|
|
251
|
+
constructor(client, http) {
|
|
252
|
+
this.client = client;
|
|
253
|
+
this.http = http;
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Lista todas as conversas do usuário no projeto.
|
|
257
|
+
*
|
|
258
|
+
* @example
|
|
259
|
+
* const conversas = await aether.ai.conversations.list();
|
|
260
|
+
*/
|
|
261
|
+
async list() {
|
|
262
|
+
const { data } = await this.http.get('/ai/conversations', {
|
|
263
|
+
params: { projectId: this.client.projectId }
|
|
264
|
+
});
|
|
265
|
+
return data;
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Busca o histórico de mensagens de uma conversa.
|
|
269
|
+
*
|
|
270
|
+
* @example
|
|
271
|
+
* const mensagens = await aether.ai.conversations.getMessages(conversationId);
|
|
272
|
+
*/
|
|
273
|
+
async getMessages(conversationId) {
|
|
274
|
+
const { data } = await this.http.get(`/ai/messages/${conversationId}`);
|
|
275
|
+
return data;
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Deleta uma conversa e todo seu histórico.
|
|
279
|
+
*
|
|
280
|
+
* @example
|
|
281
|
+
* await aether.ai.conversations.delete(conversationId);
|
|
282
|
+
*/
|
|
283
|
+
async delete(conversationId) {
|
|
284
|
+
const { data } = await this.http.delete(`/ai/conversations/${conversationId}`);
|
|
285
|
+
return data;
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Renomeia uma conversa.
|
|
289
|
+
*
|
|
290
|
+
* @example
|
|
291
|
+
* await aether.ai.conversations.rename(conversationId, "Suporte Técnico");
|
|
292
|
+
*/
|
|
293
|
+
async rename(conversationId, title) {
|
|
294
|
+
const { data } = await this.http.patch(`/ai/conversations/${conversationId}`, {
|
|
295
|
+
title
|
|
296
|
+
});
|
|
297
|
+
return data;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
// =============================================================================
|
|
301
|
+
// SUB-MÓDULO: ADMIN
|
|
302
|
+
// =============================================================================
|
|
303
|
+
class AIAdminAPI {
|
|
304
|
+
constructor(client, http) {
|
|
305
|
+
this.client = client;
|
|
306
|
+
this.http = http;
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Reindexa todos os dados do projeto para RAG.
|
|
310
|
+
* Use após adicionar/modificar grandes volumes de dados.
|
|
311
|
+
* Executa em background.
|
|
312
|
+
*
|
|
313
|
+
* @example
|
|
314
|
+
* await aether.ai.admin.reindex();
|
|
315
|
+
*/
|
|
316
|
+
async reindex() {
|
|
317
|
+
const { data } = await this.http.post('/ai/reindex', {
|
|
318
|
+
projectId: this.client.projectId
|
|
319
|
+
});
|
|
320
|
+
return data;
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Limpa todos os embeddings do projeto.
|
|
324
|
+
* CUIDADO: A IA "esquece" todo o contexto aprendido.
|
|
325
|
+
*
|
|
326
|
+
* @example
|
|
327
|
+
* const { deletedCount } = await aether.ai.admin.clear();
|
|
328
|
+
*/
|
|
329
|
+
async clear() {
|
|
330
|
+
const { data } = await this.http.post('/ai/clear', {
|
|
331
|
+
projectId: this.client.projectId
|
|
332
|
+
});
|
|
333
|
+
return data;
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Retorna estatísticas de uso da IA.
|
|
337
|
+
*
|
|
338
|
+
* @example
|
|
339
|
+
* const stats = await aether.ai.admin.stats();
|
|
340
|
+
* console.log(stats.totalConversations, stats.totalMessages);
|
|
341
|
+
*/
|
|
342
|
+
async stats() {
|
|
343
|
+
const { data } = await this.http.get('/ai/stats', {
|
|
344
|
+
params: { projectId: this.client.projectId }
|
|
345
|
+
});
|
|
346
|
+
return data;
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Configura quais collections são indexadas automaticamente.
|
|
350
|
+
*
|
|
351
|
+
* @example
|
|
352
|
+
* await aether.ai.admin.setIndexedCollections(['products', 'articles', 'faq']);
|
|
353
|
+
*/
|
|
354
|
+
async setIndexedCollections(collections) {
|
|
355
|
+
const { data } = await this.http.post('/ai/config/collections', {
|
|
356
|
+
projectId: this.client.projectId,
|
|
357
|
+
collections
|
|
358
|
+
});
|
|
359
|
+
return data;
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Busca configurações atuais de IA do projeto.
|
|
363
|
+
*/
|
|
364
|
+
async getConfig() {
|
|
365
|
+
const { data } = await this.http.get('/ai/config', {
|
|
366
|
+
params: { projectId: this.client.projectId }
|
|
367
|
+
});
|
|
368
|
+
return data;
|
|
369
|
+
}
|
|
370
|
+
}
|