vectorgov 0.1.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 ADDED
@@ -0,0 +1,222 @@
1
+ # VectorGov SDK for TypeScript/JavaScript
2
+
3
+ SDK oficial para a API VectorGov - Busca semântica em legislação brasileira.
4
+
5
+ ## Instalação
6
+
7
+ ```bash
8
+ npm install vectorgov
9
+ # ou
10
+ yarn add vectorgov
11
+ # ou
12
+ pnpm add vectorgov
13
+ ```
14
+
15
+ ## Uso Rápido
16
+
17
+ ```typescript
18
+ import { VectorGov } from 'vectorgov';
19
+
20
+ const vg = new VectorGov({ apiKey: 'vg_sua_chave' });
21
+
22
+ // Busca simples
23
+ const results = await vg.search('O que é ETP?');
24
+
25
+ for (const hit of results.hits) {
26
+ console.log(`${hit.source}: ${hit.text.slice(0, 100)}...`);
27
+ }
28
+ ```
29
+
30
+ ## Integração com LLMs
31
+
32
+ ### OpenAI
33
+
34
+ ```typescript
35
+ import { VectorGov } from 'vectorgov';
36
+ import OpenAI from 'openai';
37
+
38
+ const vg = new VectorGov({ apiKey: 'vg_sua_chave' });
39
+ const openai = new OpenAI();
40
+
41
+ // Busca contexto relevante
42
+ const results = await vg.search('Quais os critérios de julgamento?');
43
+
44
+ // Gera resposta com GPT-4
45
+ const response = await openai.chat.completions.create({
46
+ model: 'gpt-4',
47
+ messages: results.toMessages('Quais os critérios de julgamento?')
48
+ });
49
+
50
+ console.log(response.choices[0].message.content);
51
+ ```
52
+
53
+ ### Anthropic Claude
54
+
55
+ ```typescript
56
+ import { VectorGov } from 'vectorgov';
57
+ import Anthropic from '@anthropic-ai/sdk';
58
+
59
+ const vg = new VectorGov({ apiKey: 'vg_sua_chave' });
60
+ const anthropic = new Anthropic();
61
+
62
+ const results = await vg.search('Quando o ETP pode ser dispensado?');
63
+ const messages = results.toMessages('Quando o ETP pode ser dispensado?');
64
+
65
+ const response = await anthropic.messages.create({
66
+ model: 'claude-sonnet-4-20250514',
67
+ max_tokens: 1024,
68
+ system: messages[0].content,
69
+ messages: [{ role: 'user', content: messages[1].content }]
70
+ });
71
+
72
+ console.log(response.content[0].text);
73
+ ```
74
+
75
+ ### Google Gemini
76
+
77
+ ```typescript
78
+ import { VectorGov } from 'vectorgov';
79
+ import { GoogleGenerativeAI } from '@google/generative-ai';
80
+
81
+ const vg = new VectorGov({ apiKey: 'vg_sua_chave' });
82
+ const genAI = new GoogleGenerativeAI(process.env.GOOGLE_API_KEY!);
83
+
84
+ const results = await vg.search('O que é pesquisa de preços?');
85
+ const messages = results.toMessages('O que é pesquisa de preços?');
86
+
87
+ const model = genAI.getGenerativeModel({
88
+ model: 'gemini-2.0-flash',
89
+ systemInstruction: messages[0].content
90
+ });
91
+
92
+ const response = await model.generateContent(messages[1].content);
93
+ console.log(response.response.text());
94
+ ```
95
+
96
+ ## Modos de Busca
97
+
98
+ ```typescript
99
+ // Fast (~2s) - Busca direta, sem reranking
100
+ const fast = await vg.search('O que é ETP?', { mode: 'fast' });
101
+
102
+ // Balanced (~5s) - Com reranking (padrão)
103
+ const balanced = await vg.search('O que é ETP?', { mode: 'balanced' });
104
+
105
+ // Precise (~15s) - HyDE + reranking para máxima precisão
106
+ const precise = await vg.search('O que é ETP?', { mode: 'precise' });
107
+ ```
108
+
109
+ ## Filtros
110
+
111
+ ```typescript
112
+ // Filtrar por tipo de documento
113
+ const results = await vg.search('dispensa de licitação', {
114
+ tipoDocumento: 'lei',
115
+ ano: 2021
116
+ });
117
+ ```
118
+
119
+ ## Perguntas com Resposta
120
+
121
+ ```typescript
122
+ // Usa o LLM do VectorGov para gerar resposta
123
+ const response = await vg.ask('O que é ETP?');
124
+
125
+ console.log(response.answer);
126
+ console.log(`Confiança: ${(response.confidence * 100).toFixed(1)}%`);
127
+
128
+ for (const citation of response.citations) {
129
+ console.log(` - ${citation.short}`);
130
+ }
131
+ ```
132
+
133
+ ## Feedback
134
+
135
+ ```typescript
136
+ const results = await vg.search('O que é ETP?');
137
+
138
+ // Enviar feedback positivo
139
+ await vg.feedback(results.metadata.queryId, true);
140
+
141
+ // Ou negativo
142
+ await vg.feedback(results.metadata.queryId, false);
143
+ ```
144
+
145
+ ## Tratamento de Erros
146
+
147
+ ```typescript
148
+ import { VectorGov, AuthenticationError, RateLimitError, VectorGovError } from 'vectorgov';
149
+
150
+ try {
151
+ const results = await vg.search('query');
152
+ } catch (error) {
153
+ if (error instanceof AuthenticationError) {
154
+ console.error('API key inválida');
155
+ } else if (error instanceof RateLimitError) {
156
+ console.error(`Rate limit. Retry após ${error.retryAfter}s`);
157
+ } else if (error instanceof VectorGovError) {
158
+ console.error(`Erro: ${error.message} (${error.statusCode})`);
159
+ }
160
+ }
161
+ ```
162
+
163
+ ## Configuração
164
+
165
+ ```typescript
166
+ const vg = new VectorGov({
167
+ apiKey: 'vg_sua_chave',
168
+ baseUrl: 'https://vectorgov.io/api/v1', // opcional
169
+ timeout: 30000 // opcional, em ms
170
+ });
171
+ ```
172
+
173
+ ## Variáveis de Ambiente
174
+
175
+ ```bash
176
+ export VECTORGOV_API_KEY="vg_sua_chave"
177
+ ```
178
+
179
+ ```typescript
180
+ const vg = new VectorGov({
181
+ apiKey: process.env.VECTORGOV_API_KEY!
182
+ });
183
+ ```
184
+
185
+ ## API Reference
186
+
187
+ ### VectorGov
188
+
189
+ | Método | Descrição |
190
+ |--------|-----------|
191
+ | `search(query, options?)` | Busca semântica |
192
+ | `ask(query, options?)` | Pergunta com resposta IA |
193
+ | `feedback(queryId, like)` | Envia feedback |
194
+
195
+ ### SearchOptions
196
+
197
+ | Campo | Tipo | Padrão | Descrição |
198
+ |-------|------|--------|-----------|
199
+ | `topK` | number | 5 | Número de resultados |
200
+ | `mode` | 'fast' \| 'balanced' \| 'precise' | 'balanced' | Modo de busca |
201
+ | `tipoDocumento` | string | - | Filtro por tipo |
202
+ | `ano` | number | - | Filtro por ano |
203
+
204
+ ### SearchResult
205
+
206
+ | Campo | Tipo | Descrição |
207
+ |-------|------|-----------|
208
+ | `hits` | SearchHit[] | Resultados |
209
+ | `total` | number | Total encontrado |
210
+ | `metadata` | SearchMetadata | Metadados |
211
+ | `toMessages(query)` | ChatMessage[] | Formato para LLMs |
212
+ | `toContext()` | string | Contexto em texto |
213
+
214
+ ## Links
215
+
216
+ - [Documentação](https://vectorgov.io/documentacao)
217
+ - [GitHub](https://github.com/euteajudo/vectorgov-sdk-ts)
218
+ - [npm](https://www.npmjs.com/package/vectorgov)
219
+
220
+ ## Licença
221
+
222
+ MIT
@@ -0,0 +1,217 @@
1
+ /**
2
+ * VectorGov SDK Types
3
+ */
4
+ /** Modos de busca disponíveis */
5
+ type SearchMode = 'fast' | 'balanced' | 'precise';
6
+ /** Configuração do cliente VectorGov */
7
+ interface VectorGovConfig {
8
+ /** API key para autenticação */
9
+ apiKey: string;
10
+ /** URL base da API (padrão: https://vectorgov.io/api/v1) */
11
+ baseUrl?: string;
12
+ /** Timeout em milissegundos (padrão: 30000) */
13
+ timeout?: number;
14
+ }
15
+ /** Opções de busca */
16
+ interface SearchOptions {
17
+ /** Número de resultados (padrão: 5) */
18
+ topK?: number;
19
+ /** Modo de busca (padrão: 'balanced') */
20
+ mode?: SearchMode;
21
+ /** Tipo de documento para filtrar */
22
+ tipoDocumento?: string;
23
+ /** Ano do documento para filtrar */
24
+ ano?: number;
25
+ }
26
+ /** Hit individual de busca */
27
+ interface SearchHit {
28
+ /** Texto do trecho encontrado */
29
+ text: string;
30
+ /** Número do artigo */
31
+ articleNumber?: string;
32
+ /** ID do documento */
33
+ documentId?: string;
34
+ /** Tipo do documento (LEI, DECRETO, IN, etc) */
35
+ documentType?: string;
36
+ /** Número do documento */
37
+ documentNumber?: string;
38
+ /** Ano do documento */
39
+ year?: number;
40
+ /** Score de relevância */
41
+ score: number;
42
+ /** Score final após reranking */
43
+ finalScore?: number;
44
+ /** Fonte formatada */
45
+ source?: string;
46
+ }
47
+ /** Metadados da busca */
48
+ interface SearchMetadata {
49
+ /** Tempo total em milissegundos */
50
+ latencyMs: number;
51
+ /** Se a resposta veio do cache */
52
+ cached: boolean;
53
+ /** ID único da query (para feedback) */
54
+ queryId: string;
55
+ }
56
+ /** Resultado da busca */
57
+ interface SearchResult {
58
+ /** Lista de resultados */
59
+ hits: SearchHit[];
60
+ /** Total de resultados encontrados */
61
+ total: number;
62
+ /** Metadados da busca */
63
+ metadata: SearchMetadata;
64
+ /** Converte para formato de mensagens (OpenAI, Claude, etc) */
65
+ toMessages(query: string): ChatMessage[];
66
+ /** Converte para contexto de texto */
67
+ toContext(): string;
68
+ }
69
+ /** Mensagem de chat (formato OpenAI) */
70
+ interface ChatMessage {
71
+ role: 'system' | 'user' | 'assistant';
72
+ content: string;
73
+ }
74
+ /** Citação em uma resposta */
75
+ interface Citation {
76
+ /** Texto completo da citação */
77
+ text: string;
78
+ /** Versão curta (ex: "Art. 5, I") */
79
+ short: string;
80
+ /** Tipo do documento */
81
+ documentType?: string;
82
+ /** Número do documento */
83
+ documentNumber?: string;
84
+ /** Ano */
85
+ year?: number;
86
+ /** Número do artigo */
87
+ article?: string;
88
+ }
89
+ /** Metadados da resposta de pergunta */
90
+ interface AskMetadata {
91
+ /** Modelo usado */
92
+ model: string;
93
+ /** Tempo total em ms */
94
+ latencyMs: number;
95
+ /** Tempo de busca em ms */
96
+ retrievalMs?: number;
97
+ /** Tempo de geração em ms */
98
+ generationMs?: number;
99
+ /** Chunks usados */
100
+ chunksUsed: number;
101
+ /** Tokens usados */
102
+ tokens?: number;
103
+ /** Hash da query (para feedback) */
104
+ queryHash?: string;
105
+ }
106
+ /** Resposta de uma pergunta */
107
+ interface AskResponse {
108
+ /** Resposta gerada */
109
+ answer: string;
110
+ /** Citações */
111
+ citations: Citation[];
112
+ /** Confiança (0-1) */
113
+ confidence: number;
114
+ /** Metadados */
115
+ metadata: AskMetadata;
116
+ }
117
+ /** Opções para perguntar */
118
+ interface AskOptions extends SearchOptions {
119
+ /** Usar cache semântico */
120
+ useCache?: boolean;
121
+ }
122
+ /** Resposta de feedback */
123
+ interface FeedbackResponse {
124
+ success: boolean;
125
+ message: string;
126
+ newLikes?: number;
127
+ newDislikes?: number;
128
+ }
129
+ /** Erros da API */
130
+ declare class VectorGovError extends Error {
131
+ statusCode?: number | undefined;
132
+ code?: string | undefined;
133
+ constructor(message: string, statusCode?: number | undefined, code?: string | undefined);
134
+ }
135
+ declare class AuthenticationError extends VectorGovError {
136
+ constructor(message?: string);
137
+ }
138
+ declare class RateLimitError extends VectorGovError {
139
+ retryAfter?: number | undefined;
140
+ constructor(message?: string, retryAfter?: number | undefined);
141
+ }
142
+
143
+ /**
144
+ * VectorGov SDK Client
145
+ */
146
+
147
+ /**
148
+ * Cliente para a API VectorGov
149
+ *
150
+ * @example
151
+ * ```typescript
152
+ * import { VectorGov } from 'vectorgov';
153
+ *
154
+ * const vg = new VectorGov({ apiKey: 'vg_sua_chave' });
155
+ *
156
+ * // Busca
157
+ * const results = await vg.search('O que é ETP?');
158
+ *
159
+ * // Para usar com OpenAI
160
+ * const messages = results.toMessages('O que é ETP?');
161
+ * ```
162
+ */
163
+ declare class VectorGov {
164
+ private readonly apiKey;
165
+ private readonly baseUrl;
166
+ private readonly timeout;
167
+ constructor(config: VectorGovConfig);
168
+ /**
169
+ * Faz uma requisição para a API
170
+ */
171
+ private request;
172
+ /**
173
+ * Busca semântica em documentos legais
174
+ *
175
+ * @param query - Pergunta ou texto para buscar
176
+ * @param options - Opções de busca
177
+ * @returns Resultado da busca com métodos auxiliares
178
+ *
179
+ * @example
180
+ * ```typescript
181
+ * const results = await vg.search('O que é ETP?', {
182
+ * topK: 5,
183
+ * mode: 'balanced'
184
+ * });
185
+ *
186
+ * for (const hit of results.hits) {
187
+ * console.log(`${hit.source}: ${hit.text.slice(0, 100)}...`);
188
+ * }
189
+ * ```
190
+ */
191
+ search(query: string, options?: SearchOptions): Promise<SearchResult>;
192
+ /**
193
+ * Faz uma pergunta e recebe uma resposta gerada por IA
194
+ *
195
+ * @param query - Pergunta
196
+ * @param options - Opções
197
+ * @returns Resposta com citações
198
+ */
199
+ ask(query: string, options?: AskOptions): Promise<AskResponse>;
200
+ /**
201
+ * Envia feedback (like/dislike) para uma resposta
202
+ *
203
+ * @param queryId - ID da query (de SearchMetadata ou AskMetadata)
204
+ * @param like - true para like, false para dislike
205
+ */
206
+ feedback(queryId: string, like: boolean): Promise<FeedbackResponse>;
207
+ /**
208
+ * Converte hits para formato de mensagens de chat
209
+ */
210
+ private hitsToMessages;
211
+ /**
212
+ * Converte hits para texto de contexto
213
+ */
214
+ private hitsToContext;
215
+ }
216
+
217
+ export { type AskMetadata, type AskOptions, type AskResponse, AuthenticationError, type ChatMessage, type Citation, type FeedbackResponse, RateLimitError, type SearchHit, type SearchMetadata, type SearchMode, type SearchOptions, type SearchResult, VectorGov, type VectorGovConfig, VectorGovError };
@@ -0,0 +1,217 @@
1
+ /**
2
+ * VectorGov SDK Types
3
+ */
4
+ /** Modos de busca disponíveis */
5
+ type SearchMode = 'fast' | 'balanced' | 'precise';
6
+ /** Configuração do cliente VectorGov */
7
+ interface VectorGovConfig {
8
+ /** API key para autenticação */
9
+ apiKey: string;
10
+ /** URL base da API (padrão: https://vectorgov.io/api/v1) */
11
+ baseUrl?: string;
12
+ /** Timeout em milissegundos (padrão: 30000) */
13
+ timeout?: number;
14
+ }
15
+ /** Opções de busca */
16
+ interface SearchOptions {
17
+ /** Número de resultados (padrão: 5) */
18
+ topK?: number;
19
+ /** Modo de busca (padrão: 'balanced') */
20
+ mode?: SearchMode;
21
+ /** Tipo de documento para filtrar */
22
+ tipoDocumento?: string;
23
+ /** Ano do documento para filtrar */
24
+ ano?: number;
25
+ }
26
+ /** Hit individual de busca */
27
+ interface SearchHit {
28
+ /** Texto do trecho encontrado */
29
+ text: string;
30
+ /** Número do artigo */
31
+ articleNumber?: string;
32
+ /** ID do documento */
33
+ documentId?: string;
34
+ /** Tipo do documento (LEI, DECRETO, IN, etc) */
35
+ documentType?: string;
36
+ /** Número do documento */
37
+ documentNumber?: string;
38
+ /** Ano do documento */
39
+ year?: number;
40
+ /** Score de relevância */
41
+ score: number;
42
+ /** Score final após reranking */
43
+ finalScore?: number;
44
+ /** Fonte formatada */
45
+ source?: string;
46
+ }
47
+ /** Metadados da busca */
48
+ interface SearchMetadata {
49
+ /** Tempo total em milissegundos */
50
+ latencyMs: number;
51
+ /** Se a resposta veio do cache */
52
+ cached: boolean;
53
+ /** ID único da query (para feedback) */
54
+ queryId: string;
55
+ }
56
+ /** Resultado da busca */
57
+ interface SearchResult {
58
+ /** Lista de resultados */
59
+ hits: SearchHit[];
60
+ /** Total de resultados encontrados */
61
+ total: number;
62
+ /** Metadados da busca */
63
+ metadata: SearchMetadata;
64
+ /** Converte para formato de mensagens (OpenAI, Claude, etc) */
65
+ toMessages(query: string): ChatMessage[];
66
+ /** Converte para contexto de texto */
67
+ toContext(): string;
68
+ }
69
+ /** Mensagem de chat (formato OpenAI) */
70
+ interface ChatMessage {
71
+ role: 'system' | 'user' | 'assistant';
72
+ content: string;
73
+ }
74
+ /** Citação em uma resposta */
75
+ interface Citation {
76
+ /** Texto completo da citação */
77
+ text: string;
78
+ /** Versão curta (ex: "Art. 5, I") */
79
+ short: string;
80
+ /** Tipo do documento */
81
+ documentType?: string;
82
+ /** Número do documento */
83
+ documentNumber?: string;
84
+ /** Ano */
85
+ year?: number;
86
+ /** Número do artigo */
87
+ article?: string;
88
+ }
89
+ /** Metadados da resposta de pergunta */
90
+ interface AskMetadata {
91
+ /** Modelo usado */
92
+ model: string;
93
+ /** Tempo total em ms */
94
+ latencyMs: number;
95
+ /** Tempo de busca em ms */
96
+ retrievalMs?: number;
97
+ /** Tempo de geração em ms */
98
+ generationMs?: number;
99
+ /** Chunks usados */
100
+ chunksUsed: number;
101
+ /** Tokens usados */
102
+ tokens?: number;
103
+ /** Hash da query (para feedback) */
104
+ queryHash?: string;
105
+ }
106
+ /** Resposta de uma pergunta */
107
+ interface AskResponse {
108
+ /** Resposta gerada */
109
+ answer: string;
110
+ /** Citações */
111
+ citations: Citation[];
112
+ /** Confiança (0-1) */
113
+ confidence: number;
114
+ /** Metadados */
115
+ metadata: AskMetadata;
116
+ }
117
+ /** Opções para perguntar */
118
+ interface AskOptions extends SearchOptions {
119
+ /** Usar cache semântico */
120
+ useCache?: boolean;
121
+ }
122
+ /** Resposta de feedback */
123
+ interface FeedbackResponse {
124
+ success: boolean;
125
+ message: string;
126
+ newLikes?: number;
127
+ newDislikes?: number;
128
+ }
129
+ /** Erros da API */
130
+ declare class VectorGovError extends Error {
131
+ statusCode?: number | undefined;
132
+ code?: string | undefined;
133
+ constructor(message: string, statusCode?: number | undefined, code?: string | undefined);
134
+ }
135
+ declare class AuthenticationError extends VectorGovError {
136
+ constructor(message?: string);
137
+ }
138
+ declare class RateLimitError extends VectorGovError {
139
+ retryAfter?: number | undefined;
140
+ constructor(message?: string, retryAfter?: number | undefined);
141
+ }
142
+
143
+ /**
144
+ * VectorGov SDK Client
145
+ */
146
+
147
+ /**
148
+ * Cliente para a API VectorGov
149
+ *
150
+ * @example
151
+ * ```typescript
152
+ * import { VectorGov } from 'vectorgov';
153
+ *
154
+ * const vg = new VectorGov({ apiKey: 'vg_sua_chave' });
155
+ *
156
+ * // Busca
157
+ * const results = await vg.search('O que é ETP?');
158
+ *
159
+ * // Para usar com OpenAI
160
+ * const messages = results.toMessages('O que é ETP?');
161
+ * ```
162
+ */
163
+ declare class VectorGov {
164
+ private readonly apiKey;
165
+ private readonly baseUrl;
166
+ private readonly timeout;
167
+ constructor(config: VectorGovConfig);
168
+ /**
169
+ * Faz uma requisição para a API
170
+ */
171
+ private request;
172
+ /**
173
+ * Busca semântica em documentos legais
174
+ *
175
+ * @param query - Pergunta ou texto para buscar
176
+ * @param options - Opções de busca
177
+ * @returns Resultado da busca com métodos auxiliares
178
+ *
179
+ * @example
180
+ * ```typescript
181
+ * const results = await vg.search('O que é ETP?', {
182
+ * topK: 5,
183
+ * mode: 'balanced'
184
+ * });
185
+ *
186
+ * for (const hit of results.hits) {
187
+ * console.log(`${hit.source}: ${hit.text.slice(0, 100)}...`);
188
+ * }
189
+ * ```
190
+ */
191
+ search(query: string, options?: SearchOptions): Promise<SearchResult>;
192
+ /**
193
+ * Faz uma pergunta e recebe uma resposta gerada por IA
194
+ *
195
+ * @param query - Pergunta
196
+ * @param options - Opções
197
+ * @returns Resposta com citações
198
+ */
199
+ ask(query: string, options?: AskOptions): Promise<AskResponse>;
200
+ /**
201
+ * Envia feedback (like/dislike) para uma resposta
202
+ *
203
+ * @param queryId - ID da query (de SearchMetadata ou AskMetadata)
204
+ * @param like - true para like, false para dislike
205
+ */
206
+ feedback(queryId: string, like: boolean): Promise<FeedbackResponse>;
207
+ /**
208
+ * Converte hits para formato de mensagens de chat
209
+ */
210
+ private hitsToMessages;
211
+ /**
212
+ * Converte hits para texto de contexto
213
+ */
214
+ private hitsToContext;
215
+ }
216
+
217
+ export { type AskMetadata, type AskOptions, type AskResponse, AuthenticationError, type ChatMessage, type Citation, type FeedbackResponse, RateLimitError, type SearchHit, type SearchMetadata, type SearchMode, type SearchOptions, type SearchResult, VectorGov, type VectorGovConfig, VectorGovError };
package/dist/index.js ADDED
@@ -0,0 +1,286 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ AuthenticationError: () => AuthenticationError,
24
+ RateLimitError: () => RateLimitError,
25
+ VectorGov: () => VectorGov,
26
+ VectorGovError: () => VectorGovError
27
+ });
28
+ module.exports = __toCommonJS(index_exports);
29
+
30
+ // src/types.ts
31
+ var VectorGovError = class extends Error {
32
+ constructor(message, statusCode, code) {
33
+ super(message);
34
+ this.statusCode = statusCode;
35
+ this.code = code;
36
+ this.name = "VectorGovError";
37
+ }
38
+ };
39
+ var AuthenticationError = class extends VectorGovError {
40
+ constructor(message = "Invalid or missing API key") {
41
+ super(message, 401, "AUTHENTICATION_ERROR");
42
+ this.name = "AuthenticationError";
43
+ }
44
+ };
45
+ var RateLimitError = class extends VectorGovError {
46
+ constructor(message = "Rate limit exceeded", retryAfter) {
47
+ super(message, 429, "RATE_LIMIT_ERROR");
48
+ this.retryAfter = retryAfter;
49
+ this.name = "RateLimitError";
50
+ }
51
+ };
52
+
53
+ // src/client.ts
54
+ var DEFAULT_BASE_URL = "https://vectorgov.io/api/v1";
55
+ var DEFAULT_TIMEOUT = 3e4;
56
+ var SYSTEM_PROMPT = `Voc\xEA \xE9 um assistente jur\xEDdico especializado em legisla\xE7\xE3o brasileira de licita\xE7\xF5es e contratos administrativos.
57
+
58
+ Use APENAS as informa\xE7\xF5es fornecidas no contexto para responder. Se a informa\xE7\xE3o n\xE3o estiver no contexto, diga que n\xE3o encontrou.
59
+
60
+ Ao citar artigos, use o formato: [Art. X] ou [Art. X, \xA7Y] ou [Art. X, inciso Y].
61
+
62
+ Responda de forma clara, objetiva e em portugu\xEAs brasileiro.`;
63
+ var VectorGov = class {
64
+ constructor(config) {
65
+ if (!config.apiKey) {
66
+ throw new AuthenticationError("API key is required");
67
+ }
68
+ this.apiKey = config.apiKey;
69
+ this.baseUrl = config.baseUrl || DEFAULT_BASE_URL;
70
+ this.timeout = config.timeout || DEFAULT_TIMEOUT;
71
+ }
72
+ /**
73
+ * Faz uma requisição para a API
74
+ */
75
+ async request(endpoint, options = {}) {
76
+ const url = `${this.baseUrl}${endpoint}`;
77
+ const controller = new AbortController();
78
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
79
+ try {
80
+ const response = await fetch(url, {
81
+ ...options,
82
+ headers: {
83
+ "Content-Type": "application/json",
84
+ "X-API-Key": this.apiKey,
85
+ ...options.headers
86
+ },
87
+ signal: controller.signal
88
+ });
89
+ clearTimeout(timeoutId);
90
+ if (!response.ok) {
91
+ const errorData = await response.json().catch(() => ({}));
92
+ if (response.status === 401) {
93
+ throw new AuthenticationError(errorData.detail || "Invalid API key");
94
+ }
95
+ if (response.status === 429) {
96
+ const retryAfter = response.headers.get("Retry-After");
97
+ throw new RateLimitError(
98
+ errorData.detail || "Rate limit exceeded",
99
+ retryAfter ? parseInt(retryAfter, 10) : void 0
100
+ );
101
+ }
102
+ throw new VectorGovError(
103
+ errorData.detail || `Request failed with status ${response.status}`,
104
+ response.status
105
+ );
106
+ }
107
+ return response.json();
108
+ } catch (error) {
109
+ clearTimeout(timeoutId);
110
+ if (error instanceof VectorGovError) {
111
+ throw error;
112
+ }
113
+ if (error instanceof Error && error.name === "AbortError") {
114
+ throw new VectorGovError("Request timeout", 408, "TIMEOUT");
115
+ }
116
+ throw new VectorGovError(
117
+ error instanceof Error ? error.message : "Unknown error"
118
+ );
119
+ }
120
+ }
121
+ /**
122
+ * Busca semântica em documentos legais
123
+ *
124
+ * @param query - Pergunta ou texto para buscar
125
+ * @param options - Opções de busca
126
+ * @returns Resultado da busca com métodos auxiliares
127
+ *
128
+ * @example
129
+ * ```typescript
130
+ * const results = await vg.search('O que é ETP?', {
131
+ * topK: 5,
132
+ * mode: 'balanced'
133
+ * });
134
+ *
135
+ * for (const hit of results.hits) {
136
+ * console.log(`${hit.source}: ${hit.text.slice(0, 100)}...`);
137
+ * }
138
+ * ```
139
+ */
140
+ async search(query, options = {}) {
141
+ const {
142
+ topK = 5,
143
+ mode = "balanced",
144
+ tipoDocumento,
145
+ ano
146
+ } = options;
147
+ const response = await this.request("/sdk/search", {
148
+ method: "POST",
149
+ body: JSON.stringify({
150
+ query,
151
+ top_k: topK,
152
+ mode,
153
+ tipo_documento: tipoDocumento,
154
+ ano
155
+ })
156
+ });
157
+ const hits = response.hits.map((hit) => ({
158
+ text: hit.text,
159
+ articleNumber: hit.article_number,
160
+ documentId: hit.document_id,
161
+ documentType: hit.document_type,
162
+ documentNumber: hit.document_number,
163
+ year: hit.year,
164
+ score: hit.score,
165
+ finalScore: hit.final_score,
166
+ source: hit.document_type && hit.document_number && hit.year ? `${hit.document_type} ${hit.document_number}/${hit.year}, Art. ${hit.article_number || "N/A"}` : void 0
167
+ }));
168
+ const metadata = {
169
+ latencyMs: response.latency_ms,
170
+ cached: response.cached,
171
+ queryId: response.query_id
172
+ };
173
+ return {
174
+ hits,
175
+ total: response.total,
176
+ metadata,
177
+ toMessages: (q) => this.hitsToMessages(hits, q),
178
+ toContext: () => this.hitsToContext(hits)
179
+ };
180
+ }
181
+ /**
182
+ * Faz uma pergunta e recebe uma resposta gerada por IA
183
+ *
184
+ * @param query - Pergunta
185
+ * @param options - Opções
186
+ * @returns Resposta com citações
187
+ */
188
+ async ask(query, options = {}) {
189
+ const {
190
+ topK = 5,
191
+ mode = "balanced",
192
+ useCache = true,
193
+ tipoDocumento,
194
+ ano
195
+ } = options;
196
+ const response = await this.request("/sdk/ask", {
197
+ method: "POST",
198
+ body: JSON.stringify({
199
+ query,
200
+ top_k: topK,
201
+ mode,
202
+ use_cache: useCache,
203
+ tipo_documento: tipoDocumento,
204
+ ano
205
+ })
206
+ });
207
+ return {
208
+ answer: response.data.answer,
209
+ citations: response.data.citations.map((c) => ({
210
+ text: c.text,
211
+ short: c.short,
212
+ documentType: c.document_type,
213
+ documentNumber: c.document_number,
214
+ year: c.year,
215
+ article: c.article
216
+ })),
217
+ confidence: response.data.confidence,
218
+ metadata: {
219
+ model: response.metadata.model,
220
+ latencyMs: response.metadata.latency_ms,
221
+ retrievalMs: response.metadata.retrieval_ms,
222
+ generationMs: response.metadata.generation_ms,
223
+ chunksUsed: response.metadata.chunks_used,
224
+ tokens: response.metadata.tokens,
225
+ queryHash: response.metadata.query_hash
226
+ }
227
+ };
228
+ }
229
+ /**
230
+ * Envia feedback (like/dislike) para uma resposta
231
+ *
232
+ * @param queryId - ID da query (de SearchMetadata ou AskMetadata)
233
+ * @param like - true para like, false para dislike
234
+ */
235
+ async feedback(queryId, like) {
236
+ const response = await this.request("/cache/feedback", {
237
+ method: "POST",
238
+ body: JSON.stringify({
239
+ query_hash: queryId,
240
+ is_like: like
241
+ })
242
+ });
243
+ return {
244
+ success: response.success,
245
+ message: response.message,
246
+ newLikes: response.new_likes,
247
+ newDislikes: response.new_dislikes
248
+ };
249
+ }
250
+ /**
251
+ * Converte hits para formato de mensagens de chat
252
+ */
253
+ hitsToMessages(hits, query) {
254
+ const context = this.hitsToContext(hits);
255
+ return [
256
+ {
257
+ role: "system",
258
+ content: SYSTEM_PROMPT
259
+ },
260
+ {
261
+ role: "user",
262
+ content: `Contexto:
263
+ ${context}
264
+
265
+ Pergunta: ${query}`
266
+ }
267
+ ];
268
+ }
269
+ /**
270
+ * Converte hits para texto de contexto
271
+ */
272
+ hitsToContext(hits) {
273
+ return hits.map((hit, i) => {
274
+ const source = hit.source || `Resultado ${i + 1}`;
275
+ return `[${source}]
276
+ ${hit.text}`;
277
+ }).join("\n\n---\n\n");
278
+ }
279
+ };
280
+ // Annotate the CommonJS export names for ESM import in node:
281
+ 0 && (module.exports = {
282
+ AuthenticationError,
283
+ RateLimitError,
284
+ VectorGov,
285
+ VectorGovError
286
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,256 @@
1
+ // src/types.ts
2
+ var VectorGovError = class extends Error {
3
+ constructor(message, statusCode, code) {
4
+ super(message);
5
+ this.statusCode = statusCode;
6
+ this.code = code;
7
+ this.name = "VectorGovError";
8
+ }
9
+ };
10
+ var AuthenticationError = class extends VectorGovError {
11
+ constructor(message = "Invalid or missing API key") {
12
+ super(message, 401, "AUTHENTICATION_ERROR");
13
+ this.name = "AuthenticationError";
14
+ }
15
+ };
16
+ var RateLimitError = class extends VectorGovError {
17
+ constructor(message = "Rate limit exceeded", retryAfter) {
18
+ super(message, 429, "RATE_LIMIT_ERROR");
19
+ this.retryAfter = retryAfter;
20
+ this.name = "RateLimitError";
21
+ }
22
+ };
23
+
24
+ // src/client.ts
25
+ var DEFAULT_BASE_URL = "https://vectorgov.io/api/v1";
26
+ var DEFAULT_TIMEOUT = 3e4;
27
+ var SYSTEM_PROMPT = `Voc\xEA \xE9 um assistente jur\xEDdico especializado em legisla\xE7\xE3o brasileira de licita\xE7\xF5es e contratos administrativos.
28
+
29
+ Use APENAS as informa\xE7\xF5es fornecidas no contexto para responder. Se a informa\xE7\xE3o n\xE3o estiver no contexto, diga que n\xE3o encontrou.
30
+
31
+ Ao citar artigos, use o formato: [Art. X] ou [Art. X, \xA7Y] ou [Art. X, inciso Y].
32
+
33
+ Responda de forma clara, objetiva e em portugu\xEAs brasileiro.`;
34
+ var VectorGov = class {
35
+ constructor(config) {
36
+ if (!config.apiKey) {
37
+ throw new AuthenticationError("API key is required");
38
+ }
39
+ this.apiKey = config.apiKey;
40
+ this.baseUrl = config.baseUrl || DEFAULT_BASE_URL;
41
+ this.timeout = config.timeout || DEFAULT_TIMEOUT;
42
+ }
43
+ /**
44
+ * Faz uma requisição para a API
45
+ */
46
+ async request(endpoint, options = {}) {
47
+ const url = `${this.baseUrl}${endpoint}`;
48
+ const controller = new AbortController();
49
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
50
+ try {
51
+ const response = await fetch(url, {
52
+ ...options,
53
+ headers: {
54
+ "Content-Type": "application/json",
55
+ "X-API-Key": this.apiKey,
56
+ ...options.headers
57
+ },
58
+ signal: controller.signal
59
+ });
60
+ clearTimeout(timeoutId);
61
+ if (!response.ok) {
62
+ const errorData = await response.json().catch(() => ({}));
63
+ if (response.status === 401) {
64
+ throw new AuthenticationError(errorData.detail || "Invalid API key");
65
+ }
66
+ if (response.status === 429) {
67
+ const retryAfter = response.headers.get("Retry-After");
68
+ throw new RateLimitError(
69
+ errorData.detail || "Rate limit exceeded",
70
+ retryAfter ? parseInt(retryAfter, 10) : void 0
71
+ );
72
+ }
73
+ throw new VectorGovError(
74
+ errorData.detail || `Request failed with status ${response.status}`,
75
+ response.status
76
+ );
77
+ }
78
+ return response.json();
79
+ } catch (error) {
80
+ clearTimeout(timeoutId);
81
+ if (error instanceof VectorGovError) {
82
+ throw error;
83
+ }
84
+ if (error instanceof Error && error.name === "AbortError") {
85
+ throw new VectorGovError("Request timeout", 408, "TIMEOUT");
86
+ }
87
+ throw new VectorGovError(
88
+ error instanceof Error ? error.message : "Unknown error"
89
+ );
90
+ }
91
+ }
92
+ /**
93
+ * Busca semântica em documentos legais
94
+ *
95
+ * @param query - Pergunta ou texto para buscar
96
+ * @param options - Opções de busca
97
+ * @returns Resultado da busca com métodos auxiliares
98
+ *
99
+ * @example
100
+ * ```typescript
101
+ * const results = await vg.search('O que é ETP?', {
102
+ * topK: 5,
103
+ * mode: 'balanced'
104
+ * });
105
+ *
106
+ * for (const hit of results.hits) {
107
+ * console.log(`${hit.source}: ${hit.text.slice(0, 100)}...`);
108
+ * }
109
+ * ```
110
+ */
111
+ async search(query, options = {}) {
112
+ const {
113
+ topK = 5,
114
+ mode = "balanced",
115
+ tipoDocumento,
116
+ ano
117
+ } = options;
118
+ const response = await this.request("/sdk/search", {
119
+ method: "POST",
120
+ body: JSON.stringify({
121
+ query,
122
+ top_k: topK,
123
+ mode,
124
+ tipo_documento: tipoDocumento,
125
+ ano
126
+ })
127
+ });
128
+ const hits = response.hits.map((hit) => ({
129
+ text: hit.text,
130
+ articleNumber: hit.article_number,
131
+ documentId: hit.document_id,
132
+ documentType: hit.document_type,
133
+ documentNumber: hit.document_number,
134
+ year: hit.year,
135
+ score: hit.score,
136
+ finalScore: hit.final_score,
137
+ source: hit.document_type && hit.document_number && hit.year ? `${hit.document_type} ${hit.document_number}/${hit.year}, Art. ${hit.article_number || "N/A"}` : void 0
138
+ }));
139
+ const metadata = {
140
+ latencyMs: response.latency_ms,
141
+ cached: response.cached,
142
+ queryId: response.query_id
143
+ };
144
+ return {
145
+ hits,
146
+ total: response.total,
147
+ metadata,
148
+ toMessages: (q) => this.hitsToMessages(hits, q),
149
+ toContext: () => this.hitsToContext(hits)
150
+ };
151
+ }
152
+ /**
153
+ * Faz uma pergunta e recebe uma resposta gerada por IA
154
+ *
155
+ * @param query - Pergunta
156
+ * @param options - Opções
157
+ * @returns Resposta com citações
158
+ */
159
+ async ask(query, options = {}) {
160
+ const {
161
+ topK = 5,
162
+ mode = "balanced",
163
+ useCache = true,
164
+ tipoDocumento,
165
+ ano
166
+ } = options;
167
+ const response = await this.request("/sdk/ask", {
168
+ method: "POST",
169
+ body: JSON.stringify({
170
+ query,
171
+ top_k: topK,
172
+ mode,
173
+ use_cache: useCache,
174
+ tipo_documento: tipoDocumento,
175
+ ano
176
+ })
177
+ });
178
+ return {
179
+ answer: response.data.answer,
180
+ citations: response.data.citations.map((c) => ({
181
+ text: c.text,
182
+ short: c.short,
183
+ documentType: c.document_type,
184
+ documentNumber: c.document_number,
185
+ year: c.year,
186
+ article: c.article
187
+ })),
188
+ confidence: response.data.confidence,
189
+ metadata: {
190
+ model: response.metadata.model,
191
+ latencyMs: response.metadata.latency_ms,
192
+ retrievalMs: response.metadata.retrieval_ms,
193
+ generationMs: response.metadata.generation_ms,
194
+ chunksUsed: response.metadata.chunks_used,
195
+ tokens: response.metadata.tokens,
196
+ queryHash: response.metadata.query_hash
197
+ }
198
+ };
199
+ }
200
+ /**
201
+ * Envia feedback (like/dislike) para uma resposta
202
+ *
203
+ * @param queryId - ID da query (de SearchMetadata ou AskMetadata)
204
+ * @param like - true para like, false para dislike
205
+ */
206
+ async feedback(queryId, like) {
207
+ const response = await this.request("/cache/feedback", {
208
+ method: "POST",
209
+ body: JSON.stringify({
210
+ query_hash: queryId,
211
+ is_like: like
212
+ })
213
+ });
214
+ return {
215
+ success: response.success,
216
+ message: response.message,
217
+ newLikes: response.new_likes,
218
+ newDislikes: response.new_dislikes
219
+ };
220
+ }
221
+ /**
222
+ * Converte hits para formato de mensagens de chat
223
+ */
224
+ hitsToMessages(hits, query) {
225
+ const context = this.hitsToContext(hits);
226
+ return [
227
+ {
228
+ role: "system",
229
+ content: SYSTEM_PROMPT
230
+ },
231
+ {
232
+ role: "user",
233
+ content: `Contexto:
234
+ ${context}
235
+
236
+ Pergunta: ${query}`
237
+ }
238
+ ];
239
+ }
240
+ /**
241
+ * Converte hits para texto de contexto
242
+ */
243
+ hitsToContext(hits) {
244
+ return hits.map((hit, i) => {
245
+ const source = hit.source || `Resultado ${i + 1}`;
246
+ return `[${source}]
247
+ ${hit.text}`;
248
+ }).join("\n\n---\n\n");
249
+ }
250
+ };
251
+ export {
252
+ AuthenticationError,
253
+ RateLimitError,
254
+ VectorGov,
255
+ VectorGovError
256
+ };
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "vectorgov",
3
+ "version": "0.1.0",
4
+ "description": "SDK TypeScript para a API VectorGov - Busca semântica em legislação brasileira",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "scripts": {
19
+ "build": "tsup src/index.ts --format cjs,esm --dts",
20
+ "dev": "tsup src/index.ts --format cjs,esm --dts --watch",
21
+ "lint": "eslint src/",
22
+ "test": "vitest",
23
+ "prepublishOnly": "npm run build"
24
+ },
25
+ "keywords": [
26
+ "vectorgov",
27
+ "legal",
28
+ "legislation",
29
+ "semantic-search",
30
+ "rag",
31
+ "licitacao",
32
+ "brazil",
33
+ "sdk"
34
+ ],
35
+ "author": "VectorGov <contato@vectorgov.io>",
36
+ "license": "MIT",
37
+ "repository": {
38
+ "type": "git",
39
+ "url": "https://github.com/euteajudo/vectorgov-sdk-ts"
40
+ },
41
+ "bugs": {
42
+ "url": "https://github.com/euteajudo/vectorgov-sdk-ts/issues"
43
+ },
44
+ "homepage": "https://vectorgov.io",
45
+ "devDependencies": {
46
+ "@types/node": "^20.0.0",
47
+ "tsup": "^8.0.0",
48
+ "typescript": "^5.0.0",
49
+ "vitest": "^1.0.0"
50
+ },
51
+ "engines": {
52
+ "node": ">=18.0.0"
53
+ }
54
+ }