vektori 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 +162 -0
- package/dist/index.d.mts +189 -0
- package/dist/index.d.ts +189 -0
- package/dist/index.js +226 -0
- package/dist/index.mjs +196 -0
- package/package.json +55 -0
package/README.md
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# Vektori TypeScript SDK
|
|
2
|
+
|
|
3
|
+
> AI Memory that Actually Works — Graph-based memory for LLM applications.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install vektori
|
|
9
|
+
# or
|
|
10
|
+
yarn add vektori
|
|
11
|
+
# or
|
|
12
|
+
pnpm add vektori
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import { Vektori } from 'vektori';
|
|
19
|
+
|
|
20
|
+
// Initialize with your API key
|
|
21
|
+
const memory = new Vektori({ apiKey: 'vk_your_key_here' });
|
|
22
|
+
|
|
23
|
+
// Store conversation messages
|
|
24
|
+
await memory.ingest({
|
|
25
|
+
userId: 'user_123',
|
|
26
|
+
messages: [
|
|
27
|
+
{ role: 'user', content: "I'm allergic to peanuts" },
|
|
28
|
+
{ role: 'assistant', content: 'I\'ll remember that!' },
|
|
29
|
+
{ role: 'user', content: 'I also love Italian food' }
|
|
30
|
+
]
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
// Retrieve relevant context
|
|
34
|
+
const result = await memory.retrieve({
|
|
35
|
+
userId: 'user_123',
|
|
36
|
+
query: 'What are this user\'s dietary restrictions?'
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
console.log(result.context);
|
|
40
|
+
// Output: "User is allergic to peanuts. User loves Italian food."
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Self-Hosted
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
const memory = new Vektori({ url: 'http://localhost:8080' });
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## API Reference
|
|
50
|
+
|
|
51
|
+
### `new Vektori(options)`
|
|
52
|
+
|
|
53
|
+
Create a new client instance.
|
|
54
|
+
|
|
55
|
+
| Option | Type | Required | Description |
|
|
56
|
+
|--------|------|----------|-------------|
|
|
57
|
+
| `apiKey` | string | * | API key for Vektori Cloud |
|
|
58
|
+
| `url` | string | * | URL for self-hosted instance |
|
|
59
|
+
| `timeout` | number | No | Request timeout in ms (default: 30000) |
|
|
60
|
+
|
|
61
|
+
\* Either `apiKey` or `url` must be provided.
|
|
62
|
+
|
|
63
|
+
### `memory.ingest(options)`
|
|
64
|
+
|
|
65
|
+
Store conversation messages.
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
const result = await memory.ingest({
|
|
69
|
+
userId: 'user_123',
|
|
70
|
+
messages: [
|
|
71
|
+
{ role: 'user', content: 'Hello!' },
|
|
72
|
+
{ role: 'assistant', content: 'Hi there!' }
|
|
73
|
+
],
|
|
74
|
+
sessionId: 'optional-session-id' // auto-generated if not provided
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
console.log(result.processed.facts); // Number of facts extracted
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### `memory.retrieve(options)`
|
|
81
|
+
|
|
82
|
+
Retrieve relevant context.
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
const result = await memory.retrieve({
|
|
86
|
+
userId: 'user_123',
|
|
87
|
+
query: 'What does the user like?',
|
|
88
|
+
topK: 10, // Max results (1-50)
|
|
89
|
+
includeRaw: false // Include raw facts/insights
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
console.log(result.context); // Synthesized context string
|
|
93
|
+
console.log(result.latencyMs); // Request latency
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### `memory.health()`
|
|
97
|
+
|
|
98
|
+
Check API health.
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
const status = await memory.health();
|
|
102
|
+
console.log(status.version); // "1.0.0"
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Error Handling
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
import { Vektori, VektoriError, AuthenticationError, ValidationError } from 'vektori';
|
|
109
|
+
|
|
110
|
+
try {
|
|
111
|
+
const result = await memory.retrieve({ userId: 'u1', query: 'test' });
|
|
112
|
+
} catch (error) {
|
|
113
|
+
if (error instanceof AuthenticationError) {
|
|
114
|
+
console.error('Invalid API key');
|
|
115
|
+
} else if (error instanceof ValidationError) {
|
|
116
|
+
console.error('Bad request:', error.details);
|
|
117
|
+
} else if (error instanceof VektoriError) {
|
|
118
|
+
console.error('API error:', error.message);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## With OpenAI
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
import { Vektori } from 'vektori';
|
|
127
|
+
import OpenAI from 'openai';
|
|
128
|
+
|
|
129
|
+
const memory = new Vektori({ apiKey: 'vk_...' });
|
|
130
|
+
const openai = new OpenAI();
|
|
131
|
+
|
|
132
|
+
async function chatWithMemory(userId: string, userMessage: string) {
|
|
133
|
+
// Get relevant context
|
|
134
|
+
const context = await memory.retrieve({ userId, query: userMessage });
|
|
135
|
+
|
|
136
|
+
// Generate response with context
|
|
137
|
+
const response = await openai.chat.completions.create({
|
|
138
|
+
model: 'gpt-4',
|
|
139
|
+
messages: [
|
|
140
|
+
{ role: 'system', content: `User context:\n${context.context}` },
|
|
141
|
+
{ role: 'user', content: userMessage }
|
|
142
|
+
]
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
const assistantMessage = response.choices[0].message.content!;
|
|
146
|
+
|
|
147
|
+
// Store for future context
|
|
148
|
+
await memory.ingest({
|
|
149
|
+
userId,
|
|
150
|
+
messages: [
|
|
151
|
+
{ role: 'user', content: userMessage },
|
|
152
|
+
{ role: 'assistant', content: assistantMessage }
|
|
153
|
+
]
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
return assistantMessage;
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## License
|
|
161
|
+
|
|
162
|
+
MIT
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vektori TypeScript SDK Types
|
|
3
|
+
*/
|
|
4
|
+
interface Message {
|
|
5
|
+
role: 'user' | 'assistant';
|
|
6
|
+
content: string;
|
|
7
|
+
timestamp?: string;
|
|
8
|
+
}
|
|
9
|
+
interface IngestOptions {
|
|
10
|
+
userId: string;
|
|
11
|
+
messages: Message[];
|
|
12
|
+
sessionId?: string;
|
|
13
|
+
}
|
|
14
|
+
interface RetrieveOptions {
|
|
15
|
+
userId: string;
|
|
16
|
+
query: string;
|
|
17
|
+
topK?: number;
|
|
18
|
+
includeRaw?: boolean;
|
|
19
|
+
}
|
|
20
|
+
interface ProcessedCounts {
|
|
21
|
+
messages: number;
|
|
22
|
+
sentences: number;
|
|
23
|
+
facts: number;
|
|
24
|
+
insights: number;
|
|
25
|
+
summary: boolean;
|
|
26
|
+
}
|
|
27
|
+
interface IngestResponse {
|
|
28
|
+
success: boolean;
|
|
29
|
+
sessionId: string;
|
|
30
|
+
processed: ProcessedCounts;
|
|
31
|
+
latencyMs: number;
|
|
32
|
+
errors?: string[];
|
|
33
|
+
}
|
|
34
|
+
interface RawItem {
|
|
35
|
+
id: string;
|
|
36
|
+
score: number;
|
|
37
|
+
text?: string;
|
|
38
|
+
}
|
|
39
|
+
interface RawResults {
|
|
40
|
+
facts: RawItem[];
|
|
41
|
+
insights: RawItem[];
|
|
42
|
+
sentences: RawItem[];
|
|
43
|
+
}
|
|
44
|
+
interface SourceMetadata {
|
|
45
|
+
sentences: number;
|
|
46
|
+
facts: number;
|
|
47
|
+
insights: number;
|
|
48
|
+
summaries: number;
|
|
49
|
+
}
|
|
50
|
+
interface RetrieveMetadata {
|
|
51
|
+
sources: SourceMetadata;
|
|
52
|
+
vectorLatencyMs?: number;
|
|
53
|
+
pprLatencyMs?: number;
|
|
54
|
+
synthesisUsed?: boolean;
|
|
55
|
+
}
|
|
56
|
+
interface RetrieveResponse {
|
|
57
|
+
context: string;
|
|
58
|
+
latencyMs: number;
|
|
59
|
+
metadata: RetrieveMetadata;
|
|
60
|
+
raw?: RawResults;
|
|
61
|
+
}
|
|
62
|
+
interface HealthResponse {
|
|
63
|
+
status: string;
|
|
64
|
+
version: string;
|
|
65
|
+
timestamp: string;
|
|
66
|
+
}
|
|
67
|
+
interface VektoriOptions {
|
|
68
|
+
apiKey?: string;
|
|
69
|
+
url?: string;
|
|
70
|
+
timeout?: number;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Vektori TypeScript SDK
|
|
75
|
+
*
|
|
76
|
+
* AI Memory that Actually Works — Graph-based memory for LLM applications.
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* ```typescript
|
|
80
|
+
* import { Vektori } from 'vektori';
|
|
81
|
+
*
|
|
82
|
+
* const memory = new Vektori({ apiKey: 'vk_...' });
|
|
83
|
+
*
|
|
84
|
+
* // Store memories
|
|
85
|
+
* await memory.ingest({
|
|
86
|
+
* userId: 'user_123',
|
|
87
|
+
* messages: [
|
|
88
|
+
* { role: 'user', content: 'I love pizza' },
|
|
89
|
+
* { role: 'assistant', content: 'Noted!' }
|
|
90
|
+
* ]
|
|
91
|
+
* });
|
|
92
|
+
*
|
|
93
|
+
* // Retrieve context
|
|
94
|
+
* const result = await memory.retrieve({
|
|
95
|
+
* userId: 'user_123',
|
|
96
|
+
* query: 'What food does this user like?'
|
|
97
|
+
* });
|
|
98
|
+
*
|
|
99
|
+
* console.log(result.context); // "User loves pizza"
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
102
|
+
|
|
103
|
+
declare class VektoriError extends Error {
|
|
104
|
+
constructor(message: string);
|
|
105
|
+
}
|
|
106
|
+
declare class AuthenticationError extends VektoriError {
|
|
107
|
+
constructor(message: string);
|
|
108
|
+
}
|
|
109
|
+
declare class ValidationError extends VektoriError {
|
|
110
|
+
details?: {
|
|
111
|
+
path: string;
|
|
112
|
+
message: string;
|
|
113
|
+
}[];
|
|
114
|
+
constructor(message: string, details?: {
|
|
115
|
+
path: string;
|
|
116
|
+
message: string;
|
|
117
|
+
}[]);
|
|
118
|
+
}
|
|
119
|
+
declare class Vektori {
|
|
120
|
+
private apiKey?;
|
|
121
|
+
private baseUrl;
|
|
122
|
+
private timeout;
|
|
123
|
+
/**
|
|
124
|
+
* Create a new Vektori client.
|
|
125
|
+
*
|
|
126
|
+
* @param options - Client configuration
|
|
127
|
+
* @param options.apiKey - API key for Vektori Cloud
|
|
128
|
+
* @param options.url - URL for self-hosted instance
|
|
129
|
+
* @param options.timeout - Request timeout in milliseconds (default: 30000)
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* // Cloud
|
|
133
|
+
* const memory = new Vektori({ apiKey: 'vk_...' });
|
|
134
|
+
*
|
|
135
|
+
* // Self-hosted
|
|
136
|
+
* const memory = new Vektori({ url: 'http://localhost:8080' });
|
|
137
|
+
*/
|
|
138
|
+
constructor(options: VektoriOptions);
|
|
139
|
+
/**
|
|
140
|
+
* Store conversation messages in memory.
|
|
141
|
+
*
|
|
142
|
+
* @param options - Ingest options
|
|
143
|
+
* @param options.userId - Unique identifier for the user
|
|
144
|
+
* @param options.messages - Array of messages to ingest
|
|
145
|
+
* @param options.sessionId - Optional session ID (auto-generated if not provided)
|
|
146
|
+
* @returns Ingest response with processing stats
|
|
147
|
+
*
|
|
148
|
+
* @example
|
|
149
|
+
* const result = await memory.ingest({
|
|
150
|
+
* userId: 'user_123',
|
|
151
|
+
* messages: [
|
|
152
|
+
* { role: 'user', content: "I'm allergic to peanuts" },
|
|
153
|
+
* { role: 'assistant', content: 'Noted!' }
|
|
154
|
+
* ]
|
|
155
|
+
* });
|
|
156
|
+
* console.log(`Extracted ${result.processed.facts} facts`);
|
|
157
|
+
*/
|
|
158
|
+
ingest(options: IngestOptions): Promise<IngestResponse>;
|
|
159
|
+
/**
|
|
160
|
+
* Retrieve relevant context from memory.
|
|
161
|
+
*
|
|
162
|
+
* @param options - Retrieve options
|
|
163
|
+
* @param options.userId - User to retrieve memories for
|
|
164
|
+
* @param options.query - Search query
|
|
165
|
+
* @param options.topK - Max results (1-50, default: 10)
|
|
166
|
+
* @param options.includeRaw - Include raw facts/insights (default: false)
|
|
167
|
+
* @returns Retrieve response with synthesized context
|
|
168
|
+
*
|
|
169
|
+
* @example
|
|
170
|
+
* const result = await memory.retrieve({
|
|
171
|
+
* userId: 'user_123',
|
|
172
|
+
* query: 'What are the user allergies?'
|
|
173
|
+
* });
|
|
174
|
+
* console.log(result.context); // "User is allergic to peanuts"
|
|
175
|
+
*/
|
|
176
|
+
retrieve(options: RetrieveOptions): Promise<RetrieveResponse>;
|
|
177
|
+
/**
|
|
178
|
+
* Check the health of the Vektori API.
|
|
179
|
+
*
|
|
180
|
+
* @returns Health status
|
|
181
|
+
*/
|
|
182
|
+
health(): Promise<HealthResponse>;
|
|
183
|
+
/**
|
|
184
|
+
* Make an HTTP request to the API.
|
|
185
|
+
*/
|
|
186
|
+
private request;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export { AuthenticationError, type HealthResponse, type IngestOptions, type IngestResponse, type Message, type ProcessedCounts, type RawItem, type RawResults, type RetrieveMetadata, type RetrieveOptions, type RetrieveResponse, type SourceMetadata, ValidationError, Vektori, VektoriError, type VektoriOptions };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vektori TypeScript SDK Types
|
|
3
|
+
*/
|
|
4
|
+
interface Message {
|
|
5
|
+
role: 'user' | 'assistant';
|
|
6
|
+
content: string;
|
|
7
|
+
timestamp?: string;
|
|
8
|
+
}
|
|
9
|
+
interface IngestOptions {
|
|
10
|
+
userId: string;
|
|
11
|
+
messages: Message[];
|
|
12
|
+
sessionId?: string;
|
|
13
|
+
}
|
|
14
|
+
interface RetrieveOptions {
|
|
15
|
+
userId: string;
|
|
16
|
+
query: string;
|
|
17
|
+
topK?: number;
|
|
18
|
+
includeRaw?: boolean;
|
|
19
|
+
}
|
|
20
|
+
interface ProcessedCounts {
|
|
21
|
+
messages: number;
|
|
22
|
+
sentences: number;
|
|
23
|
+
facts: number;
|
|
24
|
+
insights: number;
|
|
25
|
+
summary: boolean;
|
|
26
|
+
}
|
|
27
|
+
interface IngestResponse {
|
|
28
|
+
success: boolean;
|
|
29
|
+
sessionId: string;
|
|
30
|
+
processed: ProcessedCounts;
|
|
31
|
+
latencyMs: number;
|
|
32
|
+
errors?: string[];
|
|
33
|
+
}
|
|
34
|
+
interface RawItem {
|
|
35
|
+
id: string;
|
|
36
|
+
score: number;
|
|
37
|
+
text?: string;
|
|
38
|
+
}
|
|
39
|
+
interface RawResults {
|
|
40
|
+
facts: RawItem[];
|
|
41
|
+
insights: RawItem[];
|
|
42
|
+
sentences: RawItem[];
|
|
43
|
+
}
|
|
44
|
+
interface SourceMetadata {
|
|
45
|
+
sentences: number;
|
|
46
|
+
facts: number;
|
|
47
|
+
insights: number;
|
|
48
|
+
summaries: number;
|
|
49
|
+
}
|
|
50
|
+
interface RetrieveMetadata {
|
|
51
|
+
sources: SourceMetadata;
|
|
52
|
+
vectorLatencyMs?: number;
|
|
53
|
+
pprLatencyMs?: number;
|
|
54
|
+
synthesisUsed?: boolean;
|
|
55
|
+
}
|
|
56
|
+
interface RetrieveResponse {
|
|
57
|
+
context: string;
|
|
58
|
+
latencyMs: number;
|
|
59
|
+
metadata: RetrieveMetadata;
|
|
60
|
+
raw?: RawResults;
|
|
61
|
+
}
|
|
62
|
+
interface HealthResponse {
|
|
63
|
+
status: string;
|
|
64
|
+
version: string;
|
|
65
|
+
timestamp: string;
|
|
66
|
+
}
|
|
67
|
+
interface VektoriOptions {
|
|
68
|
+
apiKey?: string;
|
|
69
|
+
url?: string;
|
|
70
|
+
timeout?: number;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Vektori TypeScript SDK
|
|
75
|
+
*
|
|
76
|
+
* AI Memory that Actually Works — Graph-based memory for LLM applications.
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* ```typescript
|
|
80
|
+
* import { Vektori } from 'vektori';
|
|
81
|
+
*
|
|
82
|
+
* const memory = new Vektori({ apiKey: 'vk_...' });
|
|
83
|
+
*
|
|
84
|
+
* // Store memories
|
|
85
|
+
* await memory.ingest({
|
|
86
|
+
* userId: 'user_123',
|
|
87
|
+
* messages: [
|
|
88
|
+
* { role: 'user', content: 'I love pizza' },
|
|
89
|
+
* { role: 'assistant', content: 'Noted!' }
|
|
90
|
+
* ]
|
|
91
|
+
* });
|
|
92
|
+
*
|
|
93
|
+
* // Retrieve context
|
|
94
|
+
* const result = await memory.retrieve({
|
|
95
|
+
* userId: 'user_123',
|
|
96
|
+
* query: 'What food does this user like?'
|
|
97
|
+
* });
|
|
98
|
+
*
|
|
99
|
+
* console.log(result.context); // "User loves pizza"
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
102
|
+
|
|
103
|
+
declare class VektoriError extends Error {
|
|
104
|
+
constructor(message: string);
|
|
105
|
+
}
|
|
106
|
+
declare class AuthenticationError extends VektoriError {
|
|
107
|
+
constructor(message: string);
|
|
108
|
+
}
|
|
109
|
+
declare class ValidationError extends VektoriError {
|
|
110
|
+
details?: {
|
|
111
|
+
path: string;
|
|
112
|
+
message: string;
|
|
113
|
+
}[];
|
|
114
|
+
constructor(message: string, details?: {
|
|
115
|
+
path: string;
|
|
116
|
+
message: string;
|
|
117
|
+
}[]);
|
|
118
|
+
}
|
|
119
|
+
declare class Vektori {
|
|
120
|
+
private apiKey?;
|
|
121
|
+
private baseUrl;
|
|
122
|
+
private timeout;
|
|
123
|
+
/**
|
|
124
|
+
* Create a new Vektori client.
|
|
125
|
+
*
|
|
126
|
+
* @param options - Client configuration
|
|
127
|
+
* @param options.apiKey - API key for Vektori Cloud
|
|
128
|
+
* @param options.url - URL for self-hosted instance
|
|
129
|
+
* @param options.timeout - Request timeout in milliseconds (default: 30000)
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* // Cloud
|
|
133
|
+
* const memory = new Vektori({ apiKey: 'vk_...' });
|
|
134
|
+
*
|
|
135
|
+
* // Self-hosted
|
|
136
|
+
* const memory = new Vektori({ url: 'http://localhost:8080' });
|
|
137
|
+
*/
|
|
138
|
+
constructor(options: VektoriOptions);
|
|
139
|
+
/**
|
|
140
|
+
* Store conversation messages in memory.
|
|
141
|
+
*
|
|
142
|
+
* @param options - Ingest options
|
|
143
|
+
* @param options.userId - Unique identifier for the user
|
|
144
|
+
* @param options.messages - Array of messages to ingest
|
|
145
|
+
* @param options.sessionId - Optional session ID (auto-generated if not provided)
|
|
146
|
+
* @returns Ingest response with processing stats
|
|
147
|
+
*
|
|
148
|
+
* @example
|
|
149
|
+
* const result = await memory.ingest({
|
|
150
|
+
* userId: 'user_123',
|
|
151
|
+
* messages: [
|
|
152
|
+
* { role: 'user', content: "I'm allergic to peanuts" },
|
|
153
|
+
* { role: 'assistant', content: 'Noted!' }
|
|
154
|
+
* ]
|
|
155
|
+
* });
|
|
156
|
+
* console.log(`Extracted ${result.processed.facts} facts`);
|
|
157
|
+
*/
|
|
158
|
+
ingest(options: IngestOptions): Promise<IngestResponse>;
|
|
159
|
+
/**
|
|
160
|
+
* Retrieve relevant context from memory.
|
|
161
|
+
*
|
|
162
|
+
* @param options - Retrieve options
|
|
163
|
+
* @param options.userId - User to retrieve memories for
|
|
164
|
+
* @param options.query - Search query
|
|
165
|
+
* @param options.topK - Max results (1-50, default: 10)
|
|
166
|
+
* @param options.includeRaw - Include raw facts/insights (default: false)
|
|
167
|
+
* @returns Retrieve response with synthesized context
|
|
168
|
+
*
|
|
169
|
+
* @example
|
|
170
|
+
* const result = await memory.retrieve({
|
|
171
|
+
* userId: 'user_123',
|
|
172
|
+
* query: 'What are the user allergies?'
|
|
173
|
+
* });
|
|
174
|
+
* console.log(result.context); // "User is allergic to peanuts"
|
|
175
|
+
*/
|
|
176
|
+
retrieve(options: RetrieveOptions): Promise<RetrieveResponse>;
|
|
177
|
+
/**
|
|
178
|
+
* Check the health of the Vektori API.
|
|
179
|
+
*
|
|
180
|
+
* @returns Health status
|
|
181
|
+
*/
|
|
182
|
+
health(): Promise<HealthResponse>;
|
|
183
|
+
/**
|
|
184
|
+
* Make an HTTP request to the API.
|
|
185
|
+
*/
|
|
186
|
+
private request;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export { AuthenticationError, type HealthResponse, type IngestOptions, type IngestResponse, type Message, type ProcessedCounts, type RawItem, type RawResults, type RetrieveMetadata, type RetrieveOptions, type RetrieveResponse, type SourceMetadata, ValidationError, Vektori, VektoriError, type VektoriOptions };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
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
|
+
ValidationError: () => ValidationError,
|
|
25
|
+
Vektori: () => Vektori,
|
|
26
|
+
VektoriError: () => VektoriError
|
|
27
|
+
});
|
|
28
|
+
module.exports = __toCommonJS(index_exports);
|
|
29
|
+
|
|
30
|
+
// src/client.ts
|
|
31
|
+
var VektoriError = class extends Error {
|
|
32
|
+
constructor(message) {
|
|
33
|
+
super(message);
|
|
34
|
+
this.name = "VektoriError";
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
var AuthenticationError = class extends VektoriError {
|
|
38
|
+
constructor(message) {
|
|
39
|
+
super(message);
|
|
40
|
+
this.name = "AuthenticationError";
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
var ValidationError = class extends VektoriError {
|
|
44
|
+
constructor(message, details) {
|
|
45
|
+
super(message);
|
|
46
|
+
this.name = "ValidationError";
|
|
47
|
+
this.details = details;
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
var DEFAULT_CLOUD_URL = "https://api.vektori.cloud";
|
|
51
|
+
var DEFAULT_TIMEOUT = 3e4;
|
|
52
|
+
var Vektori = class {
|
|
53
|
+
/**
|
|
54
|
+
* Create a new Vektori client.
|
|
55
|
+
*
|
|
56
|
+
* @param options - Client configuration
|
|
57
|
+
* @param options.apiKey - API key for Vektori Cloud
|
|
58
|
+
* @param options.url - URL for self-hosted instance
|
|
59
|
+
* @param options.timeout - Request timeout in milliseconds (default: 30000)
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* // Cloud
|
|
63
|
+
* const memory = new Vektori({ apiKey: 'vk_...' });
|
|
64
|
+
*
|
|
65
|
+
* // Self-hosted
|
|
66
|
+
* const memory = new Vektori({ url: 'http://localhost:8080' });
|
|
67
|
+
*/
|
|
68
|
+
constructor(options) {
|
|
69
|
+
if (!options.apiKey && !options.url) {
|
|
70
|
+
throw new VektoriError(
|
|
71
|
+
"Must provide either 'apiKey' (for Cloud) or 'url' (for self-hosted)"
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
this.apiKey = options.apiKey;
|
|
75
|
+
this.baseUrl = (options.url || DEFAULT_CLOUD_URL).replace(/\/$/, "");
|
|
76
|
+
this.timeout = options.timeout || DEFAULT_TIMEOUT;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Store conversation messages in memory.
|
|
80
|
+
*
|
|
81
|
+
* @param options - Ingest options
|
|
82
|
+
* @param options.userId - Unique identifier for the user
|
|
83
|
+
* @param options.messages - Array of messages to ingest
|
|
84
|
+
* @param options.sessionId - Optional session ID (auto-generated if not provided)
|
|
85
|
+
* @returns Ingest response with processing stats
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* const result = await memory.ingest({
|
|
89
|
+
* userId: 'user_123',
|
|
90
|
+
* messages: [
|
|
91
|
+
* { role: 'user', content: "I'm allergic to peanuts" },
|
|
92
|
+
* { role: 'assistant', content: 'Noted!' }
|
|
93
|
+
* ]
|
|
94
|
+
* });
|
|
95
|
+
* console.log(`Extracted ${result.processed.facts} facts`);
|
|
96
|
+
*/
|
|
97
|
+
async ingest(options) {
|
|
98
|
+
const payload = {
|
|
99
|
+
user_id: options.userId,
|
|
100
|
+
messages: options.messages,
|
|
101
|
+
session_id: options.sessionId
|
|
102
|
+
};
|
|
103
|
+
const response = await this.request("POST", "/v1/ingest", payload);
|
|
104
|
+
return {
|
|
105
|
+
success: response.success,
|
|
106
|
+
sessionId: response.session_id,
|
|
107
|
+
processed: {
|
|
108
|
+
messages: response.processed.messages,
|
|
109
|
+
sentences: response.processed.sentences,
|
|
110
|
+
facts: response.processed.facts,
|
|
111
|
+
insights: response.processed.insights,
|
|
112
|
+
summary: response.processed.summary
|
|
113
|
+
},
|
|
114
|
+
latencyMs: response.latency_ms,
|
|
115
|
+
errors: response.errors
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Retrieve relevant context from memory.
|
|
120
|
+
*
|
|
121
|
+
* @param options - Retrieve options
|
|
122
|
+
* @param options.userId - User to retrieve memories for
|
|
123
|
+
* @param options.query - Search query
|
|
124
|
+
* @param options.topK - Max results (1-50, default: 10)
|
|
125
|
+
* @param options.includeRaw - Include raw facts/insights (default: false)
|
|
126
|
+
* @returns Retrieve response with synthesized context
|
|
127
|
+
*
|
|
128
|
+
* @example
|
|
129
|
+
* const result = await memory.retrieve({
|
|
130
|
+
* userId: 'user_123',
|
|
131
|
+
* query: 'What are the user allergies?'
|
|
132
|
+
* });
|
|
133
|
+
* console.log(result.context); // "User is allergic to peanuts"
|
|
134
|
+
*/
|
|
135
|
+
async retrieve(options) {
|
|
136
|
+
const payload = {
|
|
137
|
+
user_id: options.userId,
|
|
138
|
+
query: options.query,
|
|
139
|
+
top_k: options.topK ?? 10,
|
|
140
|
+
include_raw: options.includeRaw ?? false
|
|
141
|
+
};
|
|
142
|
+
const response = await this.request("POST", "/v1/retrieve", payload);
|
|
143
|
+
const result = {
|
|
144
|
+
context: response.context,
|
|
145
|
+
latencyMs: response.latency_ms,
|
|
146
|
+
metadata: {
|
|
147
|
+
sources: response.metadata.sources,
|
|
148
|
+
vectorLatencyMs: response.metadata.vector_latency_ms,
|
|
149
|
+
pprLatencyMs: response.metadata.ppr_latency_ms,
|
|
150
|
+
synthesisUsed: response.metadata.synthesis_used
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
if (response.raw) {
|
|
154
|
+
result.raw = {
|
|
155
|
+
facts: response.raw.facts || [],
|
|
156
|
+
insights: response.raw.insights || [],
|
|
157
|
+
sentences: response.raw.sentences || []
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
return result;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Check the health of the Vektori API.
|
|
164
|
+
*
|
|
165
|
+
* @returns Health status
|
|
166
|
+
*/
|
|
167
|
+
async health() {
|
|
168
|
+
return this.request("GET", "/v1/health");
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Make an HTTP request to the API.
|
|
172
|
+
*/
|
|
173
|
+
async request(method, path, body) {
|
|
174
|
+
const url = `${this.baseUrl}${path}`;
|
|
175
|
+
const headers = {
|
|
176
|
+
"Content-Type": "application/json"
|
|
177
|
+
};
|
|
178
|
+
if (this.apiKey) {
|
|
179
|
+
headers["Authorization"] = `Bearer ${this.apiKey}`;
|
|
180
|
+
}
|
|
181
|
+
const controller = new AbortController();
|
|
182
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
183
|
+
try {
|
|
184
|
+
const response = await fetch(url, {
|
|
185
|
+
method,
|
|
186
|
+
headers,
|
|
187
|
+
body: body ? JSON.stringify(body) : void 0,
|
|
188
|
+
signal: controller.signal
|
|
189
|
+
});
|
|
190
|
+
clearTimeout(timeoutId);
|
|
191
|
+
if (!response.ok) {
|
|
192
|
+
const errorBody = await response.json();
|
|
193
|
+
if (response.status === 401) {
|
|
194
|
+
throw new AuthenticationError(errorBody.error || "Invalid API key");
|
|
195
|
+
}
|
|
196
|
+
if (response.status === 400) {
|
|
197
|
+
throw new ValidationError(
|
|
198
|
+
errorBody.error || "Validation error",
|
|
199
|
+
errorBody.details
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
throw new VektoriError(errorBody.error || `HTTP ${response.status}`);
|
|
203
|
+
}
|
|
204
|
+
return response.json();
|
|
205
|
+
} catch (error) {
|
|
206
|
+
clearTimeout(timeoutId);
|
|
207
|
+
if (error instanceof VektoriError) {
|
|
208
|
+
throw error;
|
|
209
|
+
}
|
|
210
|
+
if (error instanceof Error) {
|
|
211
|
+
if (error.name === "AbortError") {
|
|
212
|
+
throw new VektoriError(`Request timeout after ${this.timeout}ms`);
|
|
213
|
+
}
|
|
214
|
+
throw new VektoriError(`Request failed: ${error.message}`);
|
|
215
|
+
}
|
|
216
|
+
throw new VektoriError("Unknown error occurred");
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
221
|
+
0 && (module.exports = {
|
|
222
|
+
AuthenticationError,
|
|
223
|
+
ValidationError,
|
|
224
|
+
Vektori,
|
|
225
|
+
VektoriError
|
|
226
|
+
});
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
// src/client.ts
|
|
2
|
+
var VektoriError = class extends Error {
|
|
3
|
+
constructor(message) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.name = "VektoriError";
|
|
6
|
+
}
|
|
7
|
+
};
|
|
8
|
+
var AuthenticationError = class extends VektoriError {
|
|
9
|
+
constructor(message) {
|
|
10
|
+
super(message);
|
|
11
|
+
this.name = "AuthenticationError";
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
var ValidationError = class extends VektoriError {
|
|
15
|
+
constructor(message, details) {
|
|
16
|
+
super(message);
|
|
17
|
+
this.name = "ValidationError";
|
|
18
|
+
this.details = details;
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
var DEFAULT_CLOUD_URL = "https://api.vektori.cloud";
|
|
22
|
+
var DEFAULT_TIMEOUT = 3e4;
|
|
23
|
+
var Vektori = class {
|
|
24
|
+
/**
|
|
25
|
+
* Create a new Vektori client.
|
|
26
|
+
*
|
|
27
|
+
* @param options - Client configuration
|
|
28
|
+
* @param options.apiKey - API key for Vektori Cloud
|
|
29
|
+
* @param options.url - URL for self-hosted instance
|
|
30
|
+
* @param options.timeout - Request timeout in milliseconds (default: 30000)
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* // Cloud
|
|
34
|
+
* const memory = new Vektori({ apiKey: 'vk_...' });
|
|
35
|
+
*
|
|
36
|
+
* // Self-hosted
|
|
37
|
+
* const memory = new Vektori({ url: 'http://localhost:8080' });
|
|
38
|
+
*/
|
|
39
|
+
constructor(options) {
|
|
40
|
+
if (!options.apiKey && !options.url) {
|
|
41
|
+
throw new VektoriError(
|
|
42
|
+
"Must provide either 'apiKey' (for Cloud) or 'url' (for self-hosted)"
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
this.apiKey = options.apiKey;
|
|
46
|
+
this.baseUrl = (options.url || DEFAULT_CLOUD_URL).replace(/\/$/, "");
|
|
47
|
+
this.timeout = options.timeout || DEFAULT_TIMEOUT;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Store conversation messages in memory.
|
|
51
|
+
*
|
|
52
|
+
* @param options - Ingest options
|
|
53
|
+
* @param options.userId - Unique identifier for the user
|
|
54
|
+
* @param options.messages - Array of messages to ingest
|
|
55
|
+
* @param options.sessionId - Optional session ID (auto-generated if not provided)
|
|
56
|
+
* @returns Ingest response with processing stats
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* const result = await memory.ingest({
|
|
60
|
+
* userId: 'user_123',
|
|
61
|
+
* messages: [
|
|
62
|
+
* { role: 'user', content: "I'm allergic to peanuts" },
|
|
63
|
+
* { role: 'assistant', content: 'Noted!' }
|
|
64
|
+
* ]
|
|
65
|
+
* });
|
|
66
|
+
* console.log(`Extracted ${result.processed.facts} facts`);
|
|
67
|
+
*/
|
|
68
|
+
async ingest(options) {
|
|
69
|
+
const payload = {
|
|
70
|
+
user_id: options.userId,
|
|
71
|
+
messages: options.messages,
|
|
72
|
+
session_id: options.sessionId
|
|
73
|
+
};
|
|
74
|
+
const response = await this.request("POST", "/v1/ingest", payload);
|
|
75
|
+
return {
|
|
76
|
+
success: response.success,
|
|
77
|
+
sessionId: response.session_id,
|
|
78
|
+
processed: {
|
|
79
|
+
messages: response.processed.messages,
|
|
80
|
+
sentences: response.processed.sentences,
|
|
81
|
+
facts: response.processed.facts,
|
|
82
|
+
insights: response.processed.insights,
|
|
83
|
+
summary: response.processed.summary
|
|
84
|
+
},
|
|
85
|
+
latencyMs: response.latency_ms,
|
|
86
|
+
errors: response.errors
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Retrieve relevant context from memory.
|
|
91
|
+
*
|
|
92
|
+
* @param options - Retrieve options
|
|
93
|
+
* @param options.userId - User to retrieve memories for
|
|
94
|
+
* @param options.query - Search query
|
|
95
|
+
* @param options.topK - Max results (1-50, default: 10)
|
|
96
|
+
* @param options.includeRaw - Include raw facts/insights (default: false)
|
|
97
|
+
* @returns Retrieve response with synthesized context
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* const result = await memory.retrieve({
|
|
101
|
+
* userId: 'user_123',
|
|
102
|
+
* query: 'What are the user allergies?'
|
|
103
|
+
* });
|
|
104
|
+
* console.log(result.context); // "User is allergic to peanuts"
|
|
105
|
+
*/
|
|
106
|
+
async retrieve(options) {
|
|
107
|
+
const payload = {
|
|
108
|
+
user_id: options.userId,
|
|
109
|
+
query: options.query,
|
|
110
|
+
top_k: options.topK ?? 10,
|
|
111
|
+
include_raw: options.includeRaw ?? false
|
|
112
|
+
};
|
|
113
|
+
const response = await this.request("POST", "/v1/retrieve", payload);
|
|
114
|
+
const result = {
|
|
115
|
+
context: response.context,
|
|
116
|
+
latencyMs: response.latency_ms,
|
|
117
|
+
metadata: {
|
|
118
|
+
sources: response.metadata.sources,
|
|
119
|
+
vectorLatencyMs: response.metadata.vector_latency_ms,
|
|
120
|
+
pprLatencyMs: response.metadata.ppr_latency_ms,
|
|
121
|
+
synthesisUsed: response.metadata.synthesis_used
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
if (response.raw) {
|
|
125
|
+
result.raw = {
|
|
126
|
+
facts: response.raw.facts || [],
|
|
127
|
+
insights: response.raw.insights || [],
|
|
128
|
+
sentences: response.raw.sentences || []
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
return result;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Check the health of the Vektori API.
|
|
135
|
+
*
|
|
136
|
+
* @returns Health status
|
|
137
|
+
*/
|
|
138
|
+
async health() {
|
|
139
|
+
return this.request("GET", "/v1/health");
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Make an HTTP request to the API.
|
|
143
|
+
*/
|
|
144
|
+
async request(method, path, body) {
|
|
145
|
+
const url = `${this.baseUrl}${path}`;
|
|
146
|
+
const headers = {
|
|
147
|
+
"Content-Type": "application/json"
|
|
148
|
+
};
|
|
149
|
+
if (this.apiKey) {
|
|
150
|
+
headers["Authorization"] = `Bearer ${this.apiKey}`;
|
|
151
|
+
}
|
|
152
|
+
const controller = new AbortController();
|
|
153
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
154
|
+
try {
|
|
155
|
+
const response = await fetch(url, {
|
|
156
|
+
method,
|
|
157
|
+
headers,
|
|
158
|
+
body: body ? JSON.stringify(body) : void 0,
|
|
159
|
+
signal: controller.signal
|
|
160
|
+
});
|
|
161
|
+
clearTimeout(timeoutId);
|
|
162
|
+
if (!response.ok) {
|
|
163
|
+
const errorBody = await response.json();
|
|
164
|
+
if (response.status === 401) {
|
|
165
|
+
throw new AuthenticationError(errorBody.error || "Invalid API key");
|
|
166
|
+
}
|
|
167
|
+
if (response.status === 400) {
|
|
168
|
+
throw new ValidationError(
|
|
169
|
+
errorBody.error || "Validation error",
|
|
170
|
+
errorBody.details
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
throw new VektoriError(errorBody.error || `HTTP ${response.status}`);
|
|
174
|
+
}
|
|
175
|
+
return response.json();
|
|
176
|
+
} catch (error) {
|
|
177
|
+
clearTimeout(timeoutId);
|
|
178
|
+
if (error instanceof VektoriError) {
|
|
179
|
+
throw error;
|
|
180
|
+
}
|
|
181
|
+
if (error instanceof Error) {
|
|
182
|
+
if (error.name === "AbortError") {
|
|
183
|
+
throw new VektoriError(`Request timeout after ${this.timeout}ms`);
|
|
184
|
+
}
|
|
185
|
+
throw new VektoriError(`Request failed: ${error.message}`);
|
|
186
|
+
}
|
|
187
|
+
throw new VektoriError("Unknown error occurred");
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
export {
|
|
192
|
+
AuthenticationError,
|
|
193
|
+
ValidationError,
|
|
194
|
+
Vektori,
|
|
195
|
+
VektoriError
|
|
196
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "vektori",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "AI Memory that Actually Works — TypeScript SDK for Vektori",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.mjs",
|
|
11
|
+
"require": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"README.md"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsup src/index.ts --format cjs,esm --dts",
|
|
21
|
+
"dev": "tsup src/index.ts --format cjs,esm --dts --watch",
|
|
22
|
+
"lint": "eslint src/",
|
|
23
|
+
"test": "vitest run",
|
|
24
|
+
"prepublishOnly": "npm run build"
|
|
25
|
+
},
|
|
26
|
+
"keywords": [
|
|
27
|
+
"ai",
|
|
28
|
+
"memory",
|
|
29
|
+
"llm",
|
|
30
|
+
"rag",
|
|
31
|
+
"vector",
|
|
32
|
+
"graph",
|
|
33
|
+
"context",
|
|
34
|
+
"personalization"
|
|
35
|
+
],
|
|
36
|
+
"author": "Vektori AI <hello@vektori.cloud>",
|
|
37
|
+
"license": "MIT",
|
|
38
|
+
"repository": {
|
|
39
|
+
"type": "git",
|
|
40
|
+
"url": "https://github.com/vektori-ai/vektori.git"
|
|
41
|
+
},
|
|
42
|
+
"homepage": "https://vektori.cloud",
|
|
43
|
+
"bugs": {
|
|
44
|
+
"url": "https://github.com/vektori-ai/vektori/issues"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@types/node": "^20.0.0",
|
|
48
|
+
"tsup": "^8.0.0",
|
|
49
|
+
"typescript": "^5.0.0",
|
|
50
|
+
"vitest": "^1.0.0"
|
|
51
|
+
},
|
|
52
|
+
"engines": {
|
|
53
|
+
"node": ">=18.0.0"
|
|
54
|
+
}
|
|
55
|
+
}
|