portal-aiatende-api 0.1.10 → 0.3.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 CHANGED
@@ -20,9 +20,9 @@ const portal = new PortalClient({
20
20
  const client = await portal.clients.getByKommoSubdomain('meusubdominio');
21
21
  const client2 = await portal.clients.getByWazzupChannelId('channel-id');
22
22
 
23
- const context = await portal.knowledge.getInternalContext({
24
- clientId: client!.id,
25
- userQuery: embeddingVector, // number[]
23
+ const chunks = await portal.knowledge.getInternalContext({
24
+ aiConfigId: client!.aiConfig.id,
25
+ question: 'Qual o horário de funcionamento?',
26
26
  });
27
27
  ```
28
28
 
package/dist/index.d.mts CHANGED
@@ -96,6 +96,8 @@ interface AiConfig {
96
96
  handoffAiState?: 'inactive' | 'untag';
97
97
  /** Ativa a Reflection Agent (segunda passada de revisão/auditoria da resposta) pra este cliente. Ausente/undefined = usa o fallback global (env USE_REFLECTION_AGENT) no atende360-assistant — ver Orchestrator.ts. */
98
98
  reflectionAgentEnabled?: boolean;
99
+ /** Limiar mínimo de similaridade (cosine, 0-1) pra um trecho da base de conhecimento entrar no contexto do RAG. `undefined`/`null` = o Portal usa o fallback global 0.5 até o admin calibrar via RAG eval. Aplicado internamente pelo Portal em `POST /api/knowledge/internal/context` — não precisa ser enviado pelo assistant-api. */
100
+ ragThreshold?: number | null;
99
101
  [key: string]: any;
100
102
  }
101
103
  interface AiExperimentCriteria {
@@ -286,18 +288,36 @@ declare class ClientsResource extends BaseResource {
286
288
  getByWazzupChannelId(channelId: string): Promise<Client | null>;
287
289
  }
288
290
 
291
+ /** Uma mensagem simplificada do histórico da conversa, enviada pro Portal reescrever a
292
+ * pergunta de acompanhamento como consulta autônoma antes de gerar o embedding. */
293
+ interface ConversationHistoryMessage {
294
+ role: 'user' | 'assistant' | 'system' | 'tool';
295
+ content: string;
296
+ }
289
297
  interface GetInternalContextParams {
290
- clientId: number | string;
291
- /** Embedding da mensagem do usuário (vetor numérico). */
292
- userQuery: number[];
298
+ /** Id do AiConfig do cliente — o Portal usa a `apiKey` configurada nele pra gerar o embedding da pergunta. */
299
+ aiConfigId: string;
300
+ /** Pergunta em texto puro do usuário. O embedding é gerado internamente pelo Portal (RagService.getEmbedding), não pelo chamador. */
301
+ question: string;
302
+ /** Últimas mensagens da conversa (mais antiga → mais recente), sem incluir `question`. Quando
303
+ * presente e não vazio, o Portal reescreve `question` como uma consulta autônoma (LLM rewrite)
304
+ * antes de buscar na base de conhecimento — melhora o recall em perguntas de acompanhamento
305
+ * (ex.: "e o azul?"). Omitir ou passar array vazio preserva o comportamento anterior (busca
306
+ * direto pela `question`, sem custo extra). */
307
+ conversationHistory?: ConversationHistoryMessage[];
293
308
  }
294
- interface InternalContextResult {
295
- found: boolean;
296
- contextData?: string;
309
+ interface InternalContextChunk {
310
+ chunkId?: string;
311
+ content: string;
312
+ /** Similaridade de cosseno (0-1) entre a pergunta e o trecho. */
313
+ similarity: number;
314
+ metadata?: Record<string, unknown>;
297
315
  }
316
+ /** Lista de trechos relevantes, já filtrados pelo `ragThreshold` do AiConfig — vazia quando nada supera o limiar. */
317
+ type InternalContextResult = InternalContextChunk[];
298
318
 
299
319
  declare class KnowledgeResource extends BaseResource {
300
- /** Recupera contexto da base RAG do cliente para uma query já embeddada (`POST /api/knowledge/internal/context`). */
320
+ /** Recupera trechos relevantes da base RAG do cliente pra uma pergunta em texto puro (`POST /api/knowledge/internal/context`). O Portal gera o embedding internamente usando a `apiKey` do AiConfig. */
301
321
  getInternalContext(params: GetInternalContextParams): Promise<InternalContextResult>;
302
322
  }
303
323
 
@@ -315,4 +335,4 @@ declare class PortalApiError extends Error {
315
335
  constructor(message: string, info?: Partial<PortalApiError>);
316
336
  }
317
337
 
318
- export { type AiActivationSchedule, type AiConfig, type AiExperiment, type AiExperimentConfig, type AiExperimentCriteria, type AiExperimentVariant, type AiPrompt, type BusinessHours, type CalendarConfig, type Client, type ClientsListResponse, ClientsResource, type DateException, type GetInternalContextParams, type InternalContextResult, KnowledgeResource, type KommoAccount, type KommoConfig, type LossReasonMapping, type NudgeSettings, type PipelineMapping, PortalApiError, PortalClient, type PortalClientConfig, type StageMapping, type TimeRange, type Wazzup, type WazzupChannel };
338
+ export { type AiActivationSchedule, type AiConfig, type AiExperiment, type AiExperimentConfig, type AiExperimentCriteria, type AiExperimentVariant, type AiPrompt, type BusinessHours, type CalendarConfig, type Client, type ClientsListResponse, ClientsResource, type ConversationHistoryMessage, type DateException, type GetInternalContextParams, type InternalContextChunk, type InternalContextResult, KnowledgeResource, type KommoAccount, type KommoConfig, type LossReasonMapping, type NudgeSettings, type PipelineMapping, PortalApiError, PortalClient, type PortalClientConfig, type StageMapping, type TimeRange, type Wazzup, type WazzupChannel };
package/dist/index.d.ts CHANGED
@@ -96,6 +96,8 @@ interface AiConfig {
96
96
  handoffAiState?: 'inactive' | 'untag';
97
97
  /** Ativa a Reflection Agent (segunda passada de revisão/auditoria da resposta) pra este cliente. Ausente/undefined = usa o fallback global (env USE_REFLECTION_AGENT) no atende360-assistant — ver Orchestrator.ts. */
98
98
  reflectionAgentEnabled?: boolean;
99
+ /** Limiar mínimo de similaridade (cosine, 0-1) pra um trecho da base de conhecimento entrar no contexto do RAG. `undefined`/`null` = o Portal usa o fallback global 0.5 até o admin calibrar via RAG eval. Aplicado internamente pelo Portal em `POST /api/knowledge/internal/context` — não precisa ser enviado pelo assistant-api. */
100
+ ragThreshold?: number | null;
99
101
  [key: string]: any;
100
102
  }
101
103
  interface AiExperimentCriteria {
@@ -286,18 +288,36 @@ declare class ClientsResource extends BaseResource {
286
288
  getByWazzupChannelId(channelId: string): Promise<Client | null>;
287
289
  }
288
290
 
291
+ /** Uma mensagem simplificada do histórico da conversa, enviada pro Portal reescrever a
292
+ * pergunta de acompanhamento como consulta autônoma antes de gerar o embedding. */
293
+ interface ConversationHistoryMessage {
294
+ role: 'user' | 'assistant' | 'system' | 'tool';
295
+ content: string;
296
+ }
289
297
  interface GetInternalContextParams {
290
- clientId: number | string;
291
- /** Embedding da mensagem do usuário (vetor numérico). */
292
- userQuery: number[];
298
+ /** Id do AiConfig do cliente — o Portal usa a `apiKey` configurada nele pra gerar o embedding da pergunta. */
299
+ aiConfigId: string;
300
+ /** Pergunta em texto puro do usuário. O embedding é gerado internamente pelo Portal (RagService.getEmbedding), não pelo chamador. */
301
+ question: string;
302
+ /** Últimas mensagens da conversa (mais antiga → mais recente), sem incluir `question`. Quando
303
+ * presente e não vazio, o Portal reescreve `question` como uma consulta autônoma (LLM rewrite)
304
+ * antes de buscar na base de conhecimento — melhora o recall em perguntas de acompanhamento
305
+ * (ex.: "e o azul?"). Omitir ou passar array vazio preserva o comportamento anterior (busca
306
+ * direto pela `question`, sem custo extra). */
307
+ conversationHistory?: ConversationHistoryMessage[];
293
308
  }
294
- interface InternalContextResult {
295
- found: boolean;
296
- contextData?: string;
309
+ interface InternalContextChunk {
310
+ chunkId?: string;
311
+ content: string;
312
+ /** Similaridade de cosseno (0-1) entre a pergunta e o trecho. */
313
+ similarity: number;
314
+ metadata?: Record<string, unknown>;
297
315
  }
316
+ /** Lista de trechos relevantes, já filtrados pelo `ragThreshold` do AiConfig — vazia quando nada supera o limiar. */
317
+ type InternalContextResult = InternalContextChunk[];
298
318
 
299
319
  declare class KnowledgeResource extends BaseResource {
300
- /** Recupera contexto da base RAG do cliente para uma query já embeddada (`POST /api/knowledge/internal/context`). */
320
+ /** Recupera trechos relevantes da base RAG do cliente pra uma pergunta em texto puro (`POST /api/knowledge/internal/context`). O Portal gera o embedding internamente usando a `apiKey` do AiConfig. */
301
321
  getInternalContext(params: GetInternalContextParams): Promise<InternalContextResult>;
302
322
  }
303
323
 
@@ -315,4 +335,4 @@ declare class PortalApiError extends Error {
315
335
  constructor(message: string, info?: Partial<PortalApiError>);
316
336
  }
317
337
 
318
- export { type AiActivationSchedule, type AiConfig, type AiExperiment, type AiExperimentConfig, type AiExperimentCriteria, type AiExperimentVariant, type AiPrompt, type BusinessHours, type CalendarConfig, type Client, type ClientsListResponse, ClientsResource, type DateException, type GetInternalContextParams, type InternalContextResult, KnowledgeResource, type KommoAccount, type KommoConfig, type LossReasonMapping, type NudgeSettings, type PipelineMapping, PortalApiError, PortalClient, type PortalClientConfig, type StageMapping, type TimeRange, type Wazzup, type WazzupChannel };
338
+ export { type AiActivationSchedule, type AiConfig, type AiExperiment, type AiExperimentConfig, type AiExperimentCriteria, type AiExperimentVariant, type AiPrompt, type BusinessHours, type CalendarConfig, type Client, type ClientsListResponse, ClientsResource, type ConversationHistoryMessage, type DateException, type GetInternalContextParams, type InternalContextChunk, type InternalContextResult, KnowledgeResource, type KommoAccount, type KommoConfig, type LossReasonMapping, type NudgeSettings, type PipelineMapping, PortalApiError, PortalClient, type PortalClientConfig, type StageMapping, type TimeRange, type Wazzup, type WazzupChannel };
package/dist/index.js CHANGED
@@ -67,16 +67,7 @@ var ClientsResource = class extends BaseResource {
67
67
  };
68
68
 
69
69
  // src/resources/knowledge/index.ts
70
- var KnowledgeResource = class extends BaseResource {
71
- /** Recupera contexto da base RAG do cliente para uma query já embeddada (`POST /api/knowledge/internal/context`). */
72
- async getInternalContext(params) {
73
- const response = await this.client.post("/api/knowledge/internal/context", {
74
- clientId: params.clientId,
75
- userQuery: params.userQuery
76
- });
77
- return response.data;
78
- }
79
- };
70
+ var import_zod = require("zod");
80
71
 
81
72
  // src/errors.ts
82
73
  var PortalApiError = class extends Error {
@@ -92,6 +83,32 @@ var PortalApiError = class extends Error {
92
83
  }
93
84
  };
94
85
 
86
+ // src/resources/knowledge/index.ts
87
+ var internalContextChunkSchema = import_zod.z.object({
88
+ chunkId: import_zod.z.string().optional(),
89
+ content: import_zod.z.string(),
90
+ similarity: import_zod.z.number(),
91
+ metadata: import_zod.z.record(import_zod.z.string(), import_zod.z.unknown()).optional()
92
+ });
93
+ var internalContextResultSchema = import_zod.z.array(internalContextChunkSchema);
94
+ var KnowledgeResource = class extends BaseResource {
95
+ /** Recupera trechos relevantes da base RAG do cliente pra uma pergunta em texto puro (`POST /api/knowledge/internal/context`). O Portal gera o embedding internamente usando a `apiKey` do AiConfig. */
96
+ async getInternalContext(params) {
97
+ const response = await this.client.post("/api/knowledge/internal/context", {
98
+ aiConfigId: params.aiConfigId,
99
+ question: params.question,
100
+ conversationHistory: params.conversationHistory
101
+ });
102
+ const parsed = internalContextResultSchema.safeParse(response.data);
103
+ if (!parsed.success) {
104
+ throw new PortalApiError("Resposta inv\xE1lida de /api/knowledge/internal/context", {
105
+ raw: parsed.error.flatten()
106
+ });
107
+ }
108
+ return parsed.data;
109
+ }
110
+ };
111
+
95
112
  // src/client.ts
96
113
  var DEFAULT_BASE_URL = "https://portal.aiatende.com.br";
97
114
  var PortalClient = class {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/client.ts","../src/base.ts","../src/resources/clients/index.ts","../src/resources/knowledge/index.ts","../src/errors.ts"],"sourcesContent":["export * from './client';\nexport * from './types';\nexport * from './errors';\nexport * from './resources/clients';\nexport * from './resources/clients/types';\nexport * from './resources/knowledge';\nexport * from './resources/knowledge/types';\n","import axios, { AxiosInstance } from 'axios';\nimport { PortalClientConfig } from './types';\nimport { ClientsResource } from './resources/clients';\nimport { KnowledgeResource } from './resources/knowledge';\nimport { PortalApiError } from './errors';\n\nconst DEFAULT_BASE_URL = 'https://portal.aiatende.com.br';\n\nexport class PortalClient {\n public config: PortalClientConfig;\n public httpClient: AxiosInstance;\n\n public clients: ClientsResource;\n public knowledge: KnowledgeResource;\n\n constructor(config: PortalClientConfig) {\n this.config = config;\n\n this.httpClient = axios.create({\n baseURL: config.baseUrl || DEFAULT_BASE_URL,\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': config.apiKey,\n 'x-internal-token': config.apiKey\n }\n });\n\n this.httpClient.interceptors.response.use(\n (response) => response,\n (error) => {\n if (error.response) {\n const errData = error.response.data;\n throw new PortalApiError(errData?.error || 'Portal API Error', {\n status: error.response.status,\n raw: errData\n });\n }\n throw error;\n }\n );\n\n this.clients = new ClientsResource(this.httpClient);\n this.knowledge = new KnowledgeResource(this.httpClient);\n }\n}\n","import { AxiosInstance } from 'axios';\n\nexport abstract class BaseResource {\n protected client: AxiosInstance;\n\n constructor(client: AxiosInstance) {\n this.client = client;\n }\n}\n","import { BaseResource } from '../../base';\nimport { Client, ClientsListResponse } from './types';\n\nexport class ClientsResource extends BaseResource {\n /** Busca o Client dono de um subdomínio Kommo (`GET /api/clients?kommo_subdomain=...`). */\n async getByKommoSubdomain(subdomain: string): Promise<Client | null> {\n const response = await this.client.get<ClientsListResponse>('/api/clients', {\n params: { kommo_subdomain: subdomain, includeConfigs: true }\n });\n return response.data.data[0] ?? null;\n }\n\n /** Busca o Client dono de um canal Wazzup (`GET /api/clients?channelId=...`). */\n async getByWazzupChannelId(channelId: string): Promise<Client | null> {\n const response = await this.client.get<ClientsListResponse>('/api/clients', {\n params: { channelId, includeConfigs: true }\n });\n return response.data.data[0] ?? null;\n }\n}\n","import { BaseResource } from '../../base';\nimport { GetInternalContextParams, InternalContextResult } from './types';\n\nexport class KnowledgeResource extends BaseResource {\n /** Recupera contexto da base RAG do cliente para uma query já embeddada (`POST /api/knowledge/internal/context`). */\n async getInternalContext(params: GetInternalContextParams): Promise<InternalContextResult> {\n const response = await this.client.post<InternalContextResult>('/api/knowledge/internal/context', {\n clientId: params.clientId,\n userQuery: params.userQuery\n });\n return response.data;\n }\n}\n","export class PortalApiError extends Error {\n status?: number;\n raw?: unknown;\n\n constructor(message: string, info?: Partial<PortalApiError>) {\n super(message);\n this.name = 'PortalApiError';\n\n if (info) {\n this.status = info.status;\n this.raw = info.raw;\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,mBAAqC;;;ACE9B,IAAe,eAAf,MAA4B;AAAA,EACvB;AAAA,EAEV,YAAY,QAAuB;AACjC,SAAK,SAAS;AAAA,EAChB;AACF;;;ACLO,IAAM,kBAAN,cAA8B,aAAa;AAAA;AAAA,EAEhD,MAAM,oBAAoB,WAA2C;AACnE,UAAM,WAAW,MAAM,KAAK,OAAO,IAAyB,gBAAgB;AAAA,MAC1E,QAAQ,EAAE,iBAAiB,WAAW,gBAAgB,KAAK;AAAA,IAC7D,CAAC;AACD,WAAO,SAAS,KAAK,KAAK,CAAC,KAAK;AAAA,EAClC;AAAA;AAAA,EAGA,MAAM,qBAAqB,WAA2C;AACpE,UAAM,WAAW,MAAM,KAAK,OAAO,IAAyB,gBAAgB;AAAA,MAC1E,QAAQ,EAAE,WAAW,gBAAgB,KAAK;AAAA,IAC5C,CAAC;AACD,WAAO,SAAS,KAAK,KAAK,CAAC,KAAK;AAAA,EAClC;AACF;;;AChBO,IAAM,oBAAN,cAAgC,aAAa;AAAA;AAAA,EAElD,MAAM,mBAAmB,QAAkE;AACzF,UAAM,WAAW,MAAM,KAAK,OAAO,KAA4B,mCAAmC;AAAA,MAChG,UAAU,OAAO;AAAA,MACjB,WAAW,OAAO;AAAA,IACpB,CAAC;AACD,WAAO,SAAS;AAAA,EAClB;AACF;;;ACZO,IAAM,iBAAN,cAA6B,MAAM;AAAA,EACxC;AAAA,EACA;AAAA,EAEA,YAAY,SAAiB,MAAgC;AAC3D,UAAM,OAAO;AACb,SAAK,OAAO;AAEZ,QAAI,MAAM;AACR,WAAK,SAAS,KAAK;AACnB,WAAK,MAAM,KAAK;AAAA,IAClB;AAAA,EACF;AACF;;;AJPA,IAAM,mBAAmB;AAElB,IAAM,eAAN,MAAmB;AAAA,EACjB;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,EAEP,YAAY,QAA4B;AACtC,SAAK,SAAS;AAEd,SAAK,aAAa,aAAAA,QAAM,OAAO;AAAA,MAC7B,SAAS,OAAO,WAAW;AAAA,MAC3B,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,aAAa,OAAO;AAAA,QACpB,oBAAoB,OAAO;AAAA,MAC7B;AAAA,IACF,CAAC;AAED,SAAK,WAAW,aAAa,SAAS;AAAA,MACpC,CAAC,aAAa;AAAA,MACd,CAAC,UAAU;AACT,YAAI,MAAM,UAAU;AAClB,gBAAM,UAAU,MAAM,SAAS;AAC/B,gBAAM,IAAI,eAAe,SAAS,SAAS,oBAAoB;AAAA,YAC7D,QAAQ,MAAM,SAAS;AAAA,YACvB,KAAK;AAAA,UACP,CAAC;AAAA,QACH;AACA,cAAM;AAAA,MACR;AAAA,IACF;AAEA,SAAK,UAAU,IAAI,gBAAgB,KAAK,UAAU;AAClD,SAAK,YAAY,IAAI,kBAAkB,KAAK,UAAU;AAAA,EACxD;AACF;","names":["axios"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/client.ts","../src/base.ts","../src/resources/clients/index.ts","../src/resources/knowledge/index.ts","../src/errors.ts"],"sourcesContent":["export * from './client';\nexport * from './types';\nexport * from './errors';\nexport * from './resources/clients';\nexport * from './resources/clients/types';\nexport * from './resources/knowledge';\nexport * from './resources/knowledge/types';\n","import axios, { AxiosInstance } from 'axios';\nimport { PortalClientConfig } from './types';\nimport { ClientsResource } from './resources/clients';\nimport { KnowledgeResource } from './resources/knowledge';\nimport { PortalApiError } from './errors';\n\nconst DEFAULT_BASE_URL = 'https://portal.aiatende.com.br';\n\nexport class PortalClient {\n public config: PortalClientConfig;\n public httpClient: AxiosInstance;\n\n public clients: ClientsResource;\n public knowledge: KnowledgeResource;\n\n constructor(config: PortalClientConfig) {\n this.config = config;\n\n this.httpClient = axios.create({\n baseURL: config.baseUrl || DEFAULT_BASE_URL,\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': config.apiKey,\n 'x-internal-token': config.apiKey\n }\n });\n\n this.httpClient.interceptors.response.use(\n (response) => response,\n (error) => {\n if (error.response) {\n const errData = error.response.data;\n throw new PortalApiError(errData?.error || 'Portal API Error', {\n status: error.response.status,\n raw: errData\n });\n }\n throw error;\n }\n );\n\n this.clients = new ClientsResource(this.httpClient);\n this.knowledge = new KnowledgeResource(this.httpClient);\n }\n}\n","import { AxiosInstance } from 'axios';\n\nexport abstract class BaseResource {\n protected client: AxiosInstance;\n\n constructor(client: AxiosInstance) {\n this.client = client;\n }\n}\n","import { BaseResource } from '../../base';\nimport { Client, ClientsListResponse } from './types';\n\nexport class ClientsResource extends BaseResource {\n /** Busca o Client dono de um subdomínio Kommo (`GET /api/clients?kommo_subdomain=...`). */\n async getByKommoSubdomain(subdomain: string): Promise<Client | null> {\n const response = await this.client.get<ClientsListResponse>('/api/clients', {\n params: { kommo_subdomain: subdomain, includeConfigs: true }\n });\n return response.data.data[0] ?? null;\n }\n\n /** Busca o Client dono de um canal Wazzup (`GET /api/clients?channelId=...`). */\n async getByWazzupChannelId(channelId: string): Promise<Client | null> {\n const response = await this.client.get<ClientsListResponse>('/api/clients', {\n params: { channelId, includeConfigs: true }\n });\n return response.data.data[0] ?? null;\n }\n}\n","import { z } from 'zod';\nimport { BaseResource } from '../../base';\nimport { PortalApiError } from '../../errors';\nimport { GetInternalContextParams, InternalContextResult } from './types';\n\nconst internalContextChunkSchema = z.object({\n chunkId: z.string().optional(),\n content: z.string(),\n similarity: z.number(),\n metadata: z.record(z.string(), z.unknown()).optional(),\n});\n\nconst internalContextResultSchema = z.array(internalContextChunkSchema);\n\nexport class KnowledgeResource extends BaseResource {\n /** Recupera trechos relevantes da base RAG do cliente pra uma pergunta em texto puro (`POST /api/knowledge/internal/context`). O Portal gera o embedding internamente usando a `apiKey` do AiConfig. */\n async getInternalContext(params: GetInternalContextParams): Promise<InternalContextResult> {\n const response = await this.client.post<unknown>('/api/knowledge/internal/context', {\n aiConfigId: params.aiConfigId,\n question: params.question,\n conversationHistory: params.conversationHistory\n });\n\n const parsed = internalContextResultSchema.safeParse(response.data);\n if (!parsed.success) {\n throw new PortalApiError('Resposta inválida de /api/knowledge/internal/context', {\n raw: parsed.error.flatten(),\n });\n }\n return parsed.data;\n }\n}\n","export class PortalApiError extends Error {\n status?: number;\n raw?: unknown;\n\n constructor(message: string, info?: Partial<PortalApiError>) {\n super(message);\n this.name = 'PortalApiError';\n\n if (info) {\n this.status = info.status;\n this.raw = info.raw;\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,mBAAqC;;;ACE9B,IAAe,eAAf,MAA4B;AAAA,EACvB;AAAA,EAEV,YAAY,QAAuB;AACjC,SAAK,SAAS;AAAA,EAChB;AACF;;;ACLO,IAAM,kBAAN,cAA8B,aAAa;AAAA;AAAA,EAEhD,MAAM,oBAAoB,WAA2C;AACnE,UAAM,WAAW,MAAM,KAAK,OAAO,IAAyB,gBAAgB;AAAA,MAC1E,QAAQ,EAAE,iBAAiB,WAAW,gBAAgB,KAAK;AAAA,IAC7D,CAAC;AACD,WAAO,SAAS,KAAK,KAAK,CAAC,KAAK;AAAA,EAClC;AAAA;AAAA,EAGA,MAAM,qBAAqB,WAA2C;AACpE,UAAM,WAAW,MAAM,KAAK,OAAO,IAAyB,gBAAgB;AAAA,MAC1E,QAAQ,EAAE,WAAW,gBAAgB,KAAK;AAAA,IAC5C,CAAC;AACD,WAAO,SAAS,KAAK,KAAK,CAAC,KAAK;AAAA,EAClC;AACF;;;ACnBA,iBAAkB;;;ACAX,IAAM,iBAAN,cAA6B,MAAM;AAAA,EACxC;AAAA,EACA;AAAA,EAEA,YAAY,SAAiB,MAAgC;AAC3D,UAAM,OAAO;AACb,SAAK,OAAO;AAEZ,QAAI,MAAM;AACR,WAAK,SAAS,KAAK;AACnB,WAAK,MAAM,KAAK;AAAA,IAClB;AAAA,EACF;AACF;;;ADRA,IAAM,6BAA6B,aAAE,OAAO;AAAA,EAC1C,SAAS,aAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,SAAS,aAAE,OAAO;AAAA,EAClB,YAAY,aAAE,OAAO;AAAA,EACrB,UAAU,aAAE,OAAO,aAAE,OAAO,GAAG,aAAE,QAAQ,CAAC,EAAE,SAAS;AACvD,CAAC;AAED,IAAM,8BAA8B,aAAE,MAAM,0BAA0B;AAE/D,IAAM,oBAAN,cAAgC,aAAa;AAAA;AAAA,EAElD,MAAM,mBAAmB,QAAkE;AACzF,UAAM,WAAW,MAAM,KAAK,OAAO,KAAc,mCAAmC;AAAA,MAClF,YAAY,OAAO;AAAA,MACnB,UAAU,OAAO;AAAA,MACjB,qBAAqB,OAAO;AAAA,IAC9B,CAAC;AAED,UAAM,SAAS,4BAA4B,UAAU,SAAS,IAAI;AAClE,QAAI,CAAC,OAAO,SAAS;AACnB,YAAM,IAAI,eAAe,2DAAwD;AAAA,QAC/E,KAAK,OAAO,MAAM,QAAQ;AAAA,MAC5B,CAAC;AAAA,IACH;AACA,WAAO,OAAO;AAAA,EAChB;AACF;;;AHzBA,IAAM,mBAAmB;AAElB,IAAM,eAAN,MAAmB;AAAA,EACjB;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,EAEP,YAAY,QAA4B;AACtC,SAAK,SAAS;AAEd,SAAK,aAAa,aAAAA,QAAM,OAAO;AAAA,MAC7B,SAAS,OAAO,WAAW;AAAA,MAC3B,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,aAAa,OAAO;AAAA,QACpB,oBAAoB,OAAO;AAAA,MAC7B;AAAA,IACF,CAAC;AAED,SAAK,WAAW,aAAa,SAAS;AAAA,MACpC,CAAC,aAAa;AAAA,MACd,CAAC,UAAU;AACT,YAAI,MAAM,UAAU;AAClB,gBAAM,UAAU,MAAM,SAAS;AAC/B,gBAAM,IAAI,eAAe,SAAS,SAAS,oBAAoB;AAAA,YAC7D,QAAQ,MAAM,SAAS;AAAA,YACvB,KAAK;AAAA,UACP,CAAC;AAAA,QACH;AACA,cAAM;AAAA,MACR;AAAA,IACF;AAEA,SAAK,UAAU,IAAI,gBAAgB,KAAK,UAAU;AAClD,SAAK,YAAY,IAAI,kBAAkB,KAAK,UAAU;AAAA,EACxD;AACF;","names":["axios"]}
package/dist/index.mjs CHANGED
@@ -28,16 +28,7 @@ var ClientsResource = class extends BaseResource {
28
28
  };
29
29
 
30
30
  // src/resources/knowledge/index.ts
31
- var KnowledgeResource = class extends BaseResource {
32
- /** Recupera contexto da base RAG do cliente para uma query já embeddada (`POST /api/knowledge/internal/context`). */
33
- async getInternalContext(params) {
34
- const response = await this.client.post("/api/knowledge/internal/context", {
35
- clientId: params.clientId,
36
- userQuery: params.userQuery
37
- });
38
- return response.data;
39
- }
40
- };
31
+ import { z } from "zod";
41
32
 
42
33
  // src/errors.ts
43
34
  var PortalApiError = class extends Error {
@@ -53,6 +44,32 @@ var PortalApiError = class extends Error {
53
44
  }
54
45
  };
55
46
 
47
+ // src/resources/knowledge/index.ts
48
+ var internalContextChunkSchema = z.object({
49
+ chunkId: z.string().optional(),
50
+ content: z.string(),
51
+ similarity: z.number(),
52
+ metadata: z.record(z.string(), z.unknown()).optional()
53
+ });
54
+ var internalContextResultSchema = z.array(internalContextChunkSchema);
55
+ var KnowledgeResource = class extends BaseResource {
56
+ /** Recupera trechos relevantes da base RAG do cliente pra uma pergunta em texto puro (`POST /api/knowledge/internal/context`). O Portal gera o embedding internamente usando a `apiKey` do AiConfig. */
57
+ async getInternalContext(params) {
58
+ const response = await this.client.post("/api/knowledge/internal/context", {
59
+ aiConfigId: params.aiConfigId,
60
+ question: params.question,
61
+ conversationHistory: params.conversationHistory
62
+ });
63
+ const parsed = internalContextResultSchema.safeParse(response.data);
64
+ if (!parsed.success) {
65
+ throw new PortalApiError("Resposta inv\xE1lida de /api/knowledge/internal/context", {
66
+ raw: parsed.error.flatten()
67
+ });
68
+ }
69
+ return parsed.data;
70
+ }
71
+ };
72
+
56
73
  // src/client.ts
57
74
  var DEFAULT_BASE_URL = "https://portal.aiatende.com.br";
58
75
  var PortalClient = class {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/client.ts","../src/base.ts","../src/resources/clients/index.ts","../src/resources/knowledge/index.ts","../src/errors.ts"],"sourcesContent":["import axios, { AxiosInstance } from 'axios';\nimport { PortalClientConfig } from './types';\nimport { ClientsResource } from './resources/clients';\nimport { KnowledgeResource } from './resources/knowledge';\nimport { PortalApiError } from './errors';\n\nconst DEFAULT_BASE_URL = 'https://portal.aiatende.com.br';\n\nexport class PortalClient {\n public config: PortalClientConfig;\n public httpClient: AxiosInstance;\n\n public clients: ClientsResource;\n public knowledge: KnowledgeResource;\n\n constructor(config: PortalClientConfig) {\n this.config = config;\n\n this.httpClient = axios.create({\n baseURL: config.baseUrl || DEFAULT_BASE_URL,\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': config.apiKey,\n 'x-internal-token': config.apiKey\n }\n });\n\n this.httpClient.interceptors.response.use(\n (response) => response,\n (error) => {\n if (error.response) {\n const errData = error.response.data;\n throw new PortalApiError(errData?.error || 'Portal API Error', {\n status: error.response.status,\n raw: errData\n });\n }\n throw error;\n }\n );\n\n this.clients = new ClientsResource(this.httpClient);\n this.knowledge = new KnowledgeResource(this.httpClient);\n }\n}\n","import { AxiosInstance } from 'axios';\n\nexport abstract class BaseResource {\n protected client: AxiosInstance;\n\n constructor(client: AxiosInstance) {\n this.client = client;\n }\n}\n","import { BaseResource } from '../../base';\nimport { Client, ClientsListResponse } from './types';\n\nexport class ClientsResource extends BaseResource {\n /** Busca o Client dono de um subdomínio Kommo (`GET /api/clients?kommo_subdomain=...`). */\n async getByKommoSubdomain(subdomain: string): Promise<Client | null> {\n const response = await this.client.get<ClientsListResponse>('/api/clients', {\n params: { kommo_subdomain: subdomain, includeConfigs: true }\n });\n return response.data.data[0] ?? null;\n }\n\n /** Busca o Client dono de um canal Wazzup (`GET /api/clients?channelId=...`). */\n async getByWazzupChannelId(channelId: string): Promise<Client | null> {\n const response = await this.client.get<ClientsListResponse>('/api/clients', {\n params: { channelId, includeConfigs: true }\n });\n return response.data.data[0] ?? null;\n }\n}\n","import { BaseResource } from '../../base';\nimport { GetInternalContextParams, InternalContextResult } from './types';\n\nexport class KnowledgeResource extends BaseResource {\n /** Recupera contexto da base RAG do cliente para uma query já embeddada (`POST /api/knowledge/internal/context`). */\n async getInternalContext(params: GetInternalContextParams): Promise<InternalContextResult> {\n const response = await this.client.post<InternalContextResult>('/api/knowledge/internal/context', {\n clientId: params.clientId,\n userQuery: params.userQuery\n });\n return response.data;\n }\n}\n","export class PortalApiError extends Error {\n status?: number;\n raw?: unknown;\n\n constructor(message: string, info?: Partial<PortalApiError>) {\n super(message);\n this.name = 'PortalApiError';\n\n if (info) {\n this.status = info.status;\n this.raw = info.raw;\n }\n }\n}\n"],"mappings":";AAAA,OAAO,WAA8B;;;ACE9B,IAAe,eAAf,MAA4B;AAAA,EACvB;AAAA,EAEV,YAAY,QAAuB;AACjC,SAAK,SAAS;AAAA,EAChB;AACF;;;ACLO,IAAM,kBAAN,cAA8B,aAAa;AAAA;AAAA,EAEhD,MAAM,oBAAoB,WAA2C;AACnE,UAAM,WAAW,MAAM,KAAK,OAAO,IAAyB,gBAAgB;AAAA,MAC1E,QAAQ,EAAE,iBAAiB,WAAW,gBAAgB,KAAK;AAAA,IAC7D,CAAC;AACD,WAAO,SAAS,KAAK,KAAK,CAAC,KAAK;AAAA,EAClC;AAAA;AAAA,EAGA,MAAM,qBAAqB,WAA2C;AACpE,UAAM,WAAW,MAAM,KAAK,OAAO,IAAyB,gBAAgB;AAAA,MAC1E,QAAQ,EAAE,WAAW,gBAAgB,KAAK;AAAA,IAC5C,CAAC;AACD,WAAO,SAAS,KAAK,KAAK,CAAC,KAAK;AAAA,EAClC;AACF;;;AChBO,IAAM,oBAAN,cAAgC,aAAa;AAAA;AAAA,EAElD,MAAM,mBAAmB,QAAkE;AACzF,UAAM,WAAW,MAAM,KAAK,OAAO,KAA4B,mCAAmC;AAAA,MAChG,UAAU,OAAO;AAAA,MACjB,WAAW,OAAO;AAAA,IACpB,CAAC;AACD,WAAO,SAAS;AAAA,EAClB;AACF;;;ACZO,IAAM,iBAAN,cAA6B,MAAM;AAAA,EACxC;AAAA,EACA;AAAA,EAEA,YAAY,SAAiB,MAAgC;AAC3D,UAAM,OAAO;AACb,SAAK,OAAO;AAEZ,QAAI,MAAM;AACR,WAAK,SAAS,KAAK;AACnB,WAAK,MAAM,KAAK;AAAA,IAClB;AAAA,EACF;AACF;;;AJPA,IAAM,mBAAmB;AAElB,IAAM,eAAN,MAAmB;AAAA,EACjB;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,EAEP,YAAY,QAA4B;AACtC,SAAK,SAAS;AAEd,SAAK,aAAa,MAAM,OAAO;AAAA,MAC7B,SAAS,OAAO,WAAW;AAAA,MAC3B,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,aAAa,OAAO;AAAA,QACpB,oBAAoB,OAAO;AAAA,MAC7B;AAAA,IACF,CAAC;AAED,SAAK,WAAW,aAAa,SAAS;AAAA,MACpC,CAAC,aAAa;AAAA,MACd,CAAC,UAAU;AACT,YAAI,MAAM,UAAU;AAClB,gBAAM,UAAU,MAAM,SAAS;AAC/B,gBAAM,IAAI,eAAe,SAAS,SAAS,oBAAoB;AAAA,YAC7D,QAAQ,MAAM,SAAS;AAAA,YACvB,KAAK;AAAA,UACP,CAAC;AAAA,QACH;AACA,cAAM;AAAA,MACR;AAAA,IACF;AAEA,SAAK,UAAU,IAAI,gBAAgB,KAAK,UAAU;AAClD,SAAK,YAAY,IAAI,kBAAkB,KAAK,UAAU;AAAA,EACxD;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/client.ts","../src/base.ts","../src/resources/clients/index.ts","../src/resources/knowledge/index.ts","../src/errors.ts"],"sourcesContent":["import axios, { AxiosInstance } from 'axios';\nimport { PortalClientConfig } from './types';\nimport { ClientsResource } from './resources/clients';\nimport { KnowledgeResource } from './resources/knowledge';\nimport { PortalApiError } from './errors';\n\nconst DEFAULT_BASE_URL = 'https://portal.aiatende.com.br';\n\nexport class PortalClient {\n public config: PortalClientConfig;\n public httpClient: AxiosInstance;\n\n public clients: ClientsResource;\n public knowledge: KnowledgeResource;\n\n constructor(config: PortalClientConfig) {\n this.config = config;\n\n this.httpClient = axios.create({\n baseURL: config.baseUrl || DEFAULT_BASE_URL,\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': config.apiKey,\n 'x-internal-token': config.apiKey\n }\n });\n\n this.httpClient.interceptors.response.use(\n (response) => response,\n (error) => {\n if (error.response) {\n const errData = error.response.data;\n throw new PortalApiError(errData?.error || 'Portal API Error', {\n status: error.response.status,\n raw: errData\n });\n }\n throw error;\n }\n );\n\n this.clients = new ClientsResource(this.httpClient);\n this.knowledge = new KnowledgeResource(this.httpClient);\n }\n}\n","import { AxiosInstance } from 'axios';\n\nexport abstract class BaseResource {\n protected client: AxiosInstance;\n\n constructor(client: AxiosInstance) {\n this.client = client;\n }\n}\n","import { BaseResource } from '../../base';\nimport { Client, ClientsListResponse } from './types';\n\nexport class ClientsResource extends BaseResource {\n /** Busca o Client dono de um subdomínio Kommo (`GET /api/clients?kommo_subdomain=...`). */\n async getByKommoSubdomain(subdomain: string): Promise<Client | null> {\n const response = await this.client.get<ClientsListResponse>('/api/clients', {\n params: { kommo_subdomain: subdomain, includeConfigs: true }\n });\n return response.data.data[0] ?? null;\n }\n\n /** Busca o Client dono de um canal Wazzup (`GET /api/clients?channelId=...`). */\n async getByWazzupChannelId(channelId: string): Promise<Client | null> {\n const response = await this.client.get<ClientsListResponse>('/api/clients', {\n params: { channelId, includeConfigs: true }\n });\n return response.data.data[0] ?? null;\n }\n}\n","import { z } from 'zod';\nimport { BaseResource } from '../../base';\nimport { PortalApiError } from '../../errors';\nimport { GetInternalContextParams, InternalContextResult } from './types';\n\nconst internalContextChunkSchema = z.object({\n chunkId: z.string().optional(),\n content: z.string(),\n similarity: z.number(),\n metadata: z.record(z.string(), z.unknown()).optional(),\n});\n\nconst internalContextResultSchema = z.array(internalContextChunkSchema);\n\nexport class KnowledgeResource extends BaseResource {\n /** Recupera trechos relevantes da base RAG do cliente pra uma pergunta em texto puro (`POST /api/knowledge/internal/context`). O Portal gera o embedding internamente usando a `apiKey` do AiConfig. */\n async getInternalContext(params: GetInternalContextParams): Promise<InternalContextResult> {\n const response = await this.client.post<unknown>('/api/knowledge/internal/context', {\n aiConfigId: params.aiConfigId,\n question: params.question,\n conversationHistory: params.conversationHistory\n });\n\n const parsed = internalContextResultSchema.safeParse(response.data);\n if (!parsed.success) {\n throw new PortalApiError('Resposta inválida de /api/knowledge/internal/context', {\n raw: parsed.error.flatten(),\n });\n }\n return parsed.data;\n }\n}\n","export class PortalApiError extends Error {\n status?: number;\n raw?: unknown;\n\n constructor(message: string, info?: Partial<PortalApiError>) {\n super(message);\n this.name = 'PortalApiError';\n\n if (info) {\n this.status = info.status;\n this.raw = info.raw;\n }\n }\n}\n"],"mappings":";AAAA,OAAO,WAA8B;;;ACE9B,IAAe,eAAf,MAA4B;AAAA,EACvB;AAAA,EAEV,YAAY,QAAuB;AACjC,SAAK,SAAS;AAAA,EAChB;AACF;;;ACLO,IAAM,kBAAN,cAA8B,aAAa;AAAA;AAAA,EAEhD,MAAM,oBAAoB,WAA2C;AACnE,UAAM,WAAW,MAAM,KAAK,OAAO,IAAyB,gBAAgB;AAAA,MAC1E,QAAQ,EAAE,iBAAiB,WAAW,gBAAgB,KAAK;AAAA,IAC7D,CAAC;AACD,WAAO,SAAS,KAAK,KAAK,CAAC,KAAK;AAAA,EAClC;AAAA;AAAA,EAGA,MAAM,qBAAqB,WAA2C;AACpE,UAAM,WAAW,MAAM,KAAK,OAAO,IAAyB,gBAAgB;AAAA,MAC1E,QAAQ,EAAE,WAAW,gBAAgB,KAAK;AAAA,IAC5C,CAAC;AACD,WAAO,SAAS,KAAK,KAAK,CAAC,KAAK;AAAA,EAClC;AACF;;;ACnBA,SAAS,SAAS;;;ACAX,IAAM,iBAAN,cAA6B,MAAM;AAAA,EACxC;AAAA,EACA;AAAA,EAEA,YAAY,SAAiB,MAAgC;AAC3D,UAAM,OAAO;AACb,SAAK,OAAO;AAEZ,QAAI,MAAM;AACR,WAAK,SAAS,KAAK;AACnB,WAAK,MAAM,KAAK;AAAA,IAClB;AAAA,EACF;AACF;;;ADRA,IAAM,6BAA6B,EAAE,OAAO;AAAA,EAC1C,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,SAAS,EAAE,OAAO;AAAA,EAClB,YAAY,EAAE,OAAO;AAAA,EACrB,UAAU,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,QAAQ,CAAC,EAAE,SAAS;AACvD,CAAC;AAED,IAAM,8BAA8B,EAAE,MAAM,0BAA0B;AAE/D,IAAM,oBAAN,cAAgC,aAAa;AAAA;AAAA,EAElD,MAAM,mBAAmB,QAAkE;AACzF,UAAM,WAAW,MAAM,KAAK,OAAO,KAAc,mCAAmC;AAAA,MAClF,YAAY,OAAO;AAAA,MACnB,UAAU,OAAO;AAAA,MACjB,qBAAqB,OAAO;AAAA,IAC9B,CAAC;AAED,UAAM,SAAS,4BAA4B,UAAU,SAAS,IAAI;AAClE,QAAI,CAAC,OAAO,SAAS;AACnB,YAAM,IAAI,eAAe,2DAAwD;AAAA,QAC/E,KAAK,OAAO,MAAM,QAAQ;AAAA,MAC5B,CAAC;AAAA,IACH;AACA,WAAO,OAAO;AAAA,EAChB;AACF;;;AHzBA,IAAM,mBAAmB;AAElB,IAAM,eAAN,MAAmB;AAAA,EACjB;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,EAEP,YAAY,QAA4B;AACtC,SAAK,SAAS;AAEd,SAAK,aAAa,MAAM,OAAO;AAAA,MAC7B,SAAS,OAAO,WAAW;AAAA,MAC3B,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,aAAa,OAAO;AAAA,QACpB,oBAAoB,OAAO;AAAA,MAC7B;AAAA,IACF,CAAC;AAED,SAAK,WAAW,aAAa,SAAS;AAAA,MACpC,CAAC,aAAa;AAAA,MACd,CAAC,UAAU;AACT,YAAI,MAAM,UAAU;AAClB,gBAAM,UAAU,MAAM,SAAS;AAC/B,gBAAM,IAAI,eAAe,SAAS,SAAS,oBAAoB;AAAA,YAC7D,QAAQ,MAAM,SAAS;AAAA,YACvB,KAAK;AAAA,UACP,CAAC;AAAA,QACH;AACA,cAAM;AAAA,MACR;AAAA,IACF;AAEA,SAAK,UAAU,IAAI,gBAAgB,KAAK,UAAU;AAClD,SAAK,YAAY,IAAI,kBAAkB,KAAK,UAAU;AAAA,EACxD;AACF;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "portal-aiatende-api",
3
- "version": "0.1.10",
3
+ "version": "0.3.0",
4
4
  "description": "Cliente TypeScript tipado para a API interna do Portal AI Atende.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -23,7 +23,8 @@
23
23
  "license": "ISC",
24
24
  "type": "commonjs",
25
25
  "dependencies": {
26
- "axios": "^1.15.2"
26
+ "axios": "^1.15.2",
27
+ "zod": "^4.3.6"
27
28
  },
28
29
  "devDependencies": {
29
30
  "@types/node": "^22.10.0",