@tchavi/sdk 0.1.1
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 +247 -0
- package/dist/index.cjs +610 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +635 -0
- package/dist/index.d.ts +635 -0
- package/dist/index.js +599 -0
- package/dist/index.js.map +1 -0
- package/package.json +45 -0
package/README.md
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
# @tchavi/sdk
|
|
2
|
+
|
|
3
|
+
Official Node.js SDK for the [Tchavi](https://tchavi.io) AI API gateway — use OpenAI-compatible models with credit-based billing, without managing provider keys yourself.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@tchavi/sdk)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
|
|
8
|
+
## Requirements
|
|
9
|
+
|
|
10
|
+
- Node.js **20+** (uses native `fetch` and `ReadableStream`)
|
|
11
|
+
- TypeScript **5+** (optional but recommended)
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install @tchavi/sdk
|
|
17
|
+
# or
|
|
18
|
+
pnpm add @tchavi/sdk
|
|
19
|
+
# or
|
|
20
|
+
yarn add @tchavi/sdk
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Quick start
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
import Tchavi from '@tchavi/sdk';
|
|
27
|
+
|
|
28
|
+
const client = new Tchavi({ apiKey: 'sk-tch-...' });
|
|
29
|
+
|
|
30
|
+
const response = await client.chat.completions.create({
|
|
31
|
+
model: 'gpt-4o-mini',
|
|
32
|
+
messages: [{ role: 'user', content: 'Hello!' }],
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
console.log(response.choices[0].message.content);
|
|
36
|
+
console.log('Credits used:', response.tchavi.credits_used);
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Get your API key from the [Tchavi dashboard](https://app.tchavi.io).
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Chat completions
|
|
44
|
+
|
|
45
|
+
### Non-streaming
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
const completion = await client.chat.completions.create({
|
|
49
|
+
model: 'gpt-4o-mini',
|
|
50
|
+
messages: [
|
|
51
|
+
{ role: 'system', content: 'You are a helpful assistant.' },
|
|
52
|
+
{ role: 'user', content: 'What is the capital of France?' },
|
|
53
|
+
],
|
|
54
|
+
temperature: 0.7,
|
|
55
|
+
max_tokens: 256,
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
console.log(completion.choices[0].message.content);
|
|
59
|
+
// Credit metadata appended by Tchavi:
|
|
60
|
+
console.log(completion.tchavi.credits_used);
|
|
61
|
+
console.log(completion.tchavi.credits_remaining);
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Streaming
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
const stream = await client.chat.completions.create({
|
|
68
|
+
model: 'gpt-4o',
|
|
69
|
+
messages: [{ role: 'user', content: 'Tell me a story.' }],
|
|
70
|
+
stream: true,
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
for await (const chunk of stream) {
|
|
74
|
+
process.stdout.write(chunk.choices[0]?.delta?.content ?? '');
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Credit metadata available after iteration completes:
|
|
78
|
+
const meta = stream.finalMeta();
|
|
79
|
+
console.log('\nCredits used:', meta?.credits_used);
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## Embeddings
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
const result = await client.embeddings.create({
|
|
88
|
+
model: 'text-embedding-3-small',
|
|
89
|
+
input: 'The quick brown fox jumps over the lazy dog',
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
console.log(result.data[0].embedding); // number[]
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Image generation
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
const result = await client.images.generations.create({
|
|
101
|
+
prompt: 'A futuristic city skyline at sunset',
|
|
102
|
+
model: 'dall-e-3',
|
|
103
|
+
n: 1,
|
|
104
|
+
size: '1024x1024',
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
console.log(result.data[0].url);
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## Error handling
|
|
113
|
+
|
|
114
|
+
```ts
|
|
115
|
+
import Tchavi, {
|
|
116
|
+
TchaviAuthenticationError,
|
|
117
|
+
TchaviInsufficientCreditsError,
|
|
118
|
+
TchaviRateLimitError,
|
|
119
|
+
TchaviAPIError,
|
|
120
|
+
TchaviError,
|
|
121
|
+
} from '@tchavi/sdk';
|
|
122
|
+
|
|
123
|
+
try {
|
|
124
|
+
const response = await client.chat.completions.create({ ... });
|
|
125
|
+
} catch (err) {
|
|
126
|
+
if (err instanceof TchaviInsufficientCreditsError) {
|
|
127
|
+
// 402 — top up credits
|
|
128
|
+
console.log('Credits remaining:', err.creditsRemaining);
|
|
129
|
+
} else if (err instanceof TchaviRateLimitError) {
|
|
130
|
+
// 429 — back off and retry
|
|
131
|
+
console.log('Retry after (s):', err.retryAfter); // number | null
|
|
132
|
+
} else if (err instanceof TchaviAuthenticationError) {
|
|
133
|
+
// 401 — invalid or revoked API key
|
|
134
|
+
console.log('Check your API key');
|
|
135
|
+
} else if (err instanceof TchaviAPIError) {
|
|
136
|
+
// Other HTTP errors
|
|
137
|
+
console.log(err.statusCode, err.errorCode, err.message);
|
|
138
|
+
} else if (err instanceof TchaviError) {
|
|
139
|
+
// Network/timeout errors
|
|
140
|
+
console.log('Network error:', err.message);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
| Error class | Status | Extra fields |
|
|
146
|
+
|---|---|---|
|
|
147
|
+
| `TchaviError` | — | Base class for all SDK errors |
|
|
148
|
+
| `TchaviAPIError` | any | `statusCode`, `errorCode`, `headers` |
|
|
149
|
+
| `TchaviAuthenticationError` | 401 | — |
|
|
150
|
+
| `TchaviInsufficientCreditsError` | 402 | `creditsRemaining: number` |
|
|
151
|
+
| `TchaviRateLimitError` | 429 | `retryAfter: number \| null` |
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## Account management
|
|
156
|
+
|
|
157
|
+
These methods use **JWT auth** — pass `email` and `password` instead of `apiKey`:
|
|
158
|
+
|
|
159
|
+
```ts
|
|
160
|
+
const client = new Tchavi({
|
|
161
|
+
email: 'me@example.com',
|
|
162
|
+
password: 'my-password',
|
|
163
|
+
});
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Credits
|
|
167
|
+
|
|
168
|
+
```ts
|
|
169
|
+
const { creditsBalance } = await client.credits.getBalance();
|
|
170
|
+
const packs = await client.credits.listPacks(); // available credit packs
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### API keys
|
|
174
|
+
|
|
175
|
+
```ts
|
|
176
|
+
// List all keys
|
|
177
|
+
const keys = await client.apiKeys.list();
|
|
178
|
+
|
|
179
|
+
// Create a new key (full secret shown only once)
|
|
180
|
+
const { plaintext, ...key } = await client.apiKeys.create({ name: 'Production' });
|
|
181
|
+
console.log('Save this:', plaintext);
|
|
182
|
+
|
|
183
|
+
// Retrieve / update / delete
|
|
184
|
+
const key = await client.apiKeys.retrieve('key-id');
|
|
185
|
+
await client.apiKeys.update('key-id', { name: 'Renamed', status: 'INACTIVE' });
|
|
186
|
+
await client.apiKeys.delete('key-id');
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Usage
|
|
190
|
+
|
|
191
|
+
```ts
|
|
192
|
+
const stats = await client.usage.getStats({ period: '30d' });
|
|
193
|
+
const history = await client.usage.getHistory({ page: 1, limit: 20 });
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Payments
|
|
197
|
+
|
|
198
|
+
```ts
|
|
199
|
+
// Initiate a credit purchase
|
|
200
|
+
const payment = await client.payments.initiate({ packId: 'pack-id', phone: '+22900000000' });
|
|
201
|
+
|
|
202
|
+
// Check payment status
|
|
203
|
+
const status = await client.payments.getStatus(payment.id);
|
|
204
|
+
|
|
205
|
+
// Payment history
|
|
206
|
+
const history = await client.payments.getHistory();
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Available models
|
|
210
|
+
|
|
211
|
+
```ts
|
|
212
|
+
const models = await client.models.list();
|
|
213
|
+
// models[].id — use this as the `model` field in requests
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
## Configuration
|
|
219
|
+
|
|
220
|
+
```ts
|
|
221
|
+
const client = new Tchavi({
|
|
222
|
+
// Authentication (one of):
|
|
223
|
+
apiKey: 'sk-tch-...', // For proxy endpoints (chat, embeddings, images)
|
|
224
|
+
email: 'me@example.com', // For account management endpoints
|
|
225
|
+
password: 'my-password', // (requires email)
|
|
226
|
+
|
|
227
|
+
// Optional:
|
|
228
|
+
baseURL: 'https://tchavi.com', // Default: http://localhost:3001
|
|
229
|
+
maxRetries: 2, // Retries on 429/502/503. Default: 2
|
|
230
|
+
timeout: 60_000, // Request timeout in ms. Default: 60000
|
|
231
|
+
});
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
| Option | Type | Default | Description |
|
|
235
|
+
|---|---|---|---|
|
|
236
|
+
| `apiKey` | `string` | — | API key (`sk-tch-...`) for proxy auth |
|
|
237
|
+
| `email` | `string` | — | Email for JWT auth |
|
|
238
|
+
| `password` | `string` | — | Password for JWT auth |
|
|
239
|
+
| `baseURL` | `string` | `http://localhost:3001` | API base URL (set to your production URL in deployed apps) |
|
|
240
|
+
| `maxRetries` | `number` | `2` | Max retries on transient errors |
|
|
241
|
+
| `timeout` | `number` | `60000` | Request timeout (ms) |
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
## License
|
|
246
|
+
|
|
247
|
+
MIT
|