binario 0.1.0 → 0.2.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 +1175 -1140
- package/dist/index.cjs +187 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +77 -1
- package/dist/index.d.ts +77 -1
- package/dist/index.js +183 -2
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +465 -0
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +201 -8
- package/dist/react.d.ts +201 -8
- package/dist/react.js +461 -2
- package/dist/react.js.map +1 -1
- package/package.json +103 -104
package/README.md
CHANGED
|
@@ -1,1140 +1,1175 @@
|
|
|
1
|
-
# Binario
|
|
2
|
-
|
|
3
|
-
> Universal AI SDK for Cloudflare Workers — Unified API, smart fallbacks, and cost optimization.
|
|
4
|
-
|
|
5
|
-
[](https://opensource.org/licenses/MIT)
|
|
6
|
-
[](https://www.typescriptlang.org/)
|
|
7
|
-
|
|
8
|
-
## ⚠️ Status: Beta
|
|
9
|
-
|
|
10
|
-
This SDK is currently in **beta**. The hosted API at binario.dev is fully functional. For npm installation, build from source.
|
|
11
|
-
|
|
12
|
-
## ✨ Features
|
|
13
|
-
|
|
14
|
-
| Feature | Status | Notes |
|
|
15
|
-
|---------|--------|-------|
|
|
16
|
-
| Chat completions | ✅ Working | Cloudflare Workers AI |
|
|
17
|
-
| Streaming (SSE) | ✅ Working | Real-time token streaming |
|
|
18
|
-
| Structured output | ✅ Working | JSON Schema validation |
|
|
19
|
-
| Embeddings | ✅ Working | `@cf/baai/bge-base-en-v1.5` |
|
|
20
|
-
| Agent framework | ✅ Working | Tool calling with iterations |
|
|
21
|
-
| React Hooks | ✅ Working | Chat, stream, agent, memory |
|
|
22
|
-
| Multi-provider | ⚠️ Config required | Needs your own API keys |
|
|
23
|
-
| Smart caching | ⚠️ Planned | KV-based LRU cache |
|
|
24
|
-
| Memory system | ⚠️ Client-side | Buffer, summary, vector |
|
|
25
|
-
|
|
26
|
-
## 📦 Installation
|
|
27
|
-
|
|
28
|
-
### Option 1: Use the hosted API (Recommended)
|
|
29
|
-
|
|
30
|
-
Sign up at [binario.dev](https://binario.dev) and get an API key.
|
|
31
|
-
|
|
32
|
-
### Option 2: Build from source
|
|
33
|
-
|
|
34
|
-
```bash
|
|
35
|
-
git clone https://github.com/your-repo/binario.git
|
|
36
|
-
cd binario/packages/binario
|
|
37
|
-
npm install && npm run build
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
## 🚀 Quick Start
|
|
41
|
-
|
|
42
|
-
### SaaS Mode (Recommended)
|
|
43
|
-
|
|
44
|
-
The easiest way to get started — use our hosted API with no setup required:
|
|
45
|
-
|
|
46
|
-
```typescript
|
|
47
|
-
import { Binario } from 'binario';
|
|
48
|
-
|
|
49
|
-
// Initialize with your API key
|
|
50
|
-
const client = new Binario('bsk_your_api_key');
|
|
51
|
-
|
|
52
|
-
// Simple chat
|
|
53
|
-
const response = await client.chat('What is the capital of France?');
|
|
54
|
-
console.log(response.content); // "The capital of France is Paris."
|
|
55
|
-
|
|
56
|
-
// With options
|
|
57
|
-
const response = await client.chat('Explain quantum computing', {
|
|
58
|
-
model: 'gpt-4',
|
|
59
|
-
temperature: 0.7,
|
|
60
|
-
maxTokens: 500,
|
|
61
|
-
});
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
### Streaming Responses
|
|
65
|
-
|
|
66
|
-
```typescript
|
|
67
|
-
// Streaming with async iterator
|
|
68
|
-
for await (const chunk of client.stream('Tell me a long story')) {
|
|
69
|
-
process.stdout.write(chunk);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// Streaming with callbacks
|
|
73
|
-
await client.stream('Tell me a story', {
|
|
74
|
-
onToken: (token) => process.stdout.write(token),
|
|
75
|
-
onComplete: (fullText) => console.log('\nDone!'),
|
|
76
|
-
onError: (error) => console.error('Error:', error),
|
|
77
|
-
});
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
### Check Usage & Limits
|
|
81
|
-
|
|
82
|
-
```typescript
|
|
83
|
-
// Get your current usage
|
|
84
|
-
const usage = await client.usage();
|
|
85
|
-
console.log(`Tokens: ${usage.tokensUsed}/${usage.tokensLimit}`);
|
|
86
|
-
console.log(`Requests: ${usage.requestsUsed}/${usage.requestsLimit}`);
|
|
87
|
-
console.log(`Plan: ${usage.plan}`);
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
## 🏠 Self-Hosted Mode
|
|
91
|
-
|
|
92
|
-
Run your own backend with Cloudflare Workers for full control:
|
|
93
|
-
|
|
94
|
-
```typescript
|
|
95
|
-
import { createBinario } from 'binario';
|
|
96
|
-
|
|
97
|
-
const ai = createBinario({
|
|
98
|
-
providers: {
|
|
99
|
-
cloudflare: {
|
|
100
|
-
binding: env.AI, // Cloudflare AI binding
|
|
101
|
-
accountId: env.CF_ACCOUNT_ID,
|
|
102
|
-
},
|
|
103
|
-
openrouter: {
|
|
104
|
-
apiKey: env.OPENROUTER_API_KEY,
|
|
105
|
-
},
|
|
106
|
-
},
|
|
107
|
-
defaultProvider: 'cloudflare',
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
// Chat with messages array
|
|
111
|
-
const response = await ai.chat([
|
|
112
|
-
{ role: 'system', content: 'You are a helpful assistant.' },
|
|
113
|
-
{ role: 'user', content: 'Hello!' }
|
|
114
|
-
]);
|
|
115
|
-
|
|
116
|
-
// Streaming
|
|
117
|
-
const stream = await ai.stream([
|
|
118
|
-
{ role: 'user', content: 'Write a poem' }
|
|
119
|
-
]);
|
|
120
|
-
|
|
121
|
-
for await (const chunk of stream) {
|
|
122
|
-
process.stdout.write(chunk);
|
|
123
|
-
}
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
## ⚛️ React Hooks
|
|
127
|
-
|
|
128
|
-
###
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
```tsx
|
|
133
|
-
import {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
{
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
{
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
import {
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
<
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
});
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
<div
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
{
|
|
587
|
-
{
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
);
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
const
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
});
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
###
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
```typescript
|
|
768
|
-
import {
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
console.log(
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
const
|
|
865
|
-
'
|
|
866
|
-
'
|
|
867
|
-
'
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
}
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
const
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
}
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
}
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
const
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
async
|
|
966
|
-
//
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
//
|
|
1025
|
-
const
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1
|
+
# Binario
|
|
2
|
+
|
|
3
|
+
> Universal AI SDK for Cloudflare Workers — Unified API, smart fallbacks, and cost optimization.
|
|
4
|
+
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
[](https://www.typescriptlang.org/)
|
|
7
|
+
|
|
8
|
+
## ⚠️ Status: Beta
|
|
9
|
+
|
|
10
|
+
This SDK is currently in **beta**. The hosted API at binario.dev is fully functional. For npm installation, build from source.
|
|
11
|
+
|
|
12
|
+
## ✨ Features
|
|
13
|
+
|
|
14
|
+
| Feature | Status | Notes |
|
|
15
|
+
|---------|--------|-------|
|
|
16
|
+
| Chat completions | ✅ Working | Cloudflare Workers AI |
|
|
17
|
+
| Streaming (SSE) | ✅ Working | Real-time token streaming |
|
|
18
|
+
| Structured output | ✅ Working | JSON Schema validation |
|
|
19
|
+
| Embeddings | ✅ Working | `@cf/baai/bge-base-en-v1.5` |
|
|
20
|
+
| Agent framework | ✅ Working | Tool calling with iterations |
|
|
21
|
+
| React Hooks | ✅ Working | Chat, stream, agent, memory |
|
|
22
|
+
| Multi-provider | ⚠️ Config required | Needs your own API keys |
|
|
23
|
+
| Smart caching | ⚠️ Planned | KV-based LRU cache |
|
|
24
|
+
| Memory system | ⚠️ Client-side | Buffer, summary, vector |
|
|
25
|
+
|
|
26
|
+
## 📦 Installation
|
|
27
|
+
|
|
28
|
+
### Option 1: Use the hosted API (Recommended)
|
|
29
|
+
|
|
30
|
+
Sign up at [binario.dev](https://binario.dev) and get an API key.
|
|
31
|
+
|
|
32
|
+
### Option 2: Build from source
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
git clone https://github.com/your-repo/binario.git
|
|
36
|
+
cd binario/packages/binario
|
|
37
|
+
npm install && npm run build
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## 🚀 Quick Start
|
|
41
|
+
|
|
42
|
+
### SaaS Mode (Recommended)
|
|
43
|
+
|
|
44
|
+
The easiest way to get started — use our hosted API with no setup required:
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
import { Binario } from 'binario';
|
|
48
|
+
|
|
49
|
+
// Initialize with your API key
|
|
50
|
+
const client = new Binario('bsk_your_api_key');
|
|
51
|
+
|
|
52
|
+
// Simple chat
|
|
53
|
+
const response = await client.chat('What is the capital of France?');
|
|
54
|
+
console.log(response.content); // "The capital of France is Paris."
|
|
55
|
+
|
|
56
|
+
// With options
|
|
57
|
+
const response = await client.chat('Explain quantum computing', {
|
|
58
|
+
model: 'gpt-4',
|
|
59
|
+
temperature: 0.7,
|
|
60
|
+
maxTokens: 500,
|
|
61
|
+
});
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Streaming Responses
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
// Streaming with async iterator
|
|
68
|
+
for await (const chunk of client.stream('Tell me a long story')) {
|
|
69
|
+
process.stdout.write(chunk);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Streaming with callbacks
|
|
73
|
+
await client.stream('Tell me a story', {
|
|
74
|
+
onToken: (token) => process.stdout.write(token),
|
|
75
|
+
onComplete: (fullText) => console.log('\nDone!'),
|
|
76
|
+
onError: (error) => console.error('Error:', error),
|
|
77
|
+
});
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Check Usage & Limits
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
// Get your current usage
|
|
84
|
+
const usage = await client.usage();
|
|
85
|
+
console.log(`Tokens: ${usage.tokensUsed}/${usage.tokensLimit}`);
|
|
86
|
+
console.log(`Requests: ${usage.requestsUsed}/${usage.requestsLimit}`);
|
|
87
|
+
console.log(`Plan: ${usage.plan}`);
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## 🏠 Self-Hosted Mode
|
|
91
|
+
|
|
92
|
+
Run your own backend with Cloudflare Workers for full control:
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
import { createBinario } from 'binario';
|
|
96
|
+
|
|
97
|
+
const ai = createBinario({
|
|
98
|
+
providers: {
|
|
99
|
+
cloudflare: {
|
|
100
|
+
binding: env.AI, // Cloudflare AI binding
|
|
101
|
+
accountId: env.CF_ACCOUNT_ID,
|
|
102
|
+
},
|
|
103
|
+
openrouter: {
|
|
104
|
+
apiKey: env.OPENROUTER_API_KEY,
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
defaultProvider: 'cloudflare',
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
// Chat with messages array
|
|
111
|
+
const response = await ai.chat([
|
|
112
|
+
{ role: 'system', content: 'You are a helpful assistant.' },
|
|
113
|
+
{ role: 'user', content: 'Hello!' }
|
|
114
|
+
]);
|
|
115
|
+
|
|
116
|
+
// Streaming
|
|
117
|
+
const stream = await ai.stream([
|
|
118
|
+
{ role: 'user', content: 'Write a poem' }
|
|
119
|
+
]);
|
|
120
|
+
|
|
121
|
+
for await (const chunk of stream) {
|
|
122
|
+
process.stdout.write(chunk);
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## ⚛️ React Hooks
|
|
127
|
+
|
|
128
|
+
### SaaS Client Hooks (NEW - Recommended)
|
|
129
|
+
|
|
130
|
+
These hooks work directly with your API key — no BinarioAI instance needed:
|
|
131
|
+
|
|
132
|
+
```tsx
|
|
133
|
+
import { Binario } from 'binario';
|
|
134
|
+
import { useChat, useStream, useAgent, useUsage } from 'binario/react';
|
|
135
|
+
|
|
136
|
+
const client = new Binario('bsk_your_api_key');
|
|
137
|
+
|
|
138
|
+
function ChatApp() {
|
|
139
|
+
const { messages, input, setInput, isLoading, send } = useChat(client, {
|
|
140
|
+
systemPrompt: 'You are a helpful assistant.',
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
return (
|
|
144
|
+
<div>
|
|
145
|
+
{messages.map((msg, i) => (
|
|
146
|
+
<div key={i} className={msg.role}>{msg.content}</div>
|
|
147
|
+
))}
|
|
148
|
+
<input value={input} onChange={e => setInput(e.target.value)} />
|
|
149
|
+
<button onClick={() => send()} disabled={isLoading}>Send</button>
|
|
150
|
+
</div>
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function StreamingApp() {
|
|
155
|
+
const { messages, streamingContent, isStreaming, send } = useStream(client);
|
|
156
|
+
|
|
157
|
+
return (
|
|
158
|
+
<div>
|
|
159
|
+
{messages.map((msg, i) => (
|
|
160
|
+
<div key={i}>{msg.content}</div>
|
|
161
|
+
))}
|
|
162
|
+
{isStreaming && <div className="streaming">{streamingContent}</div>}
|
|
163
|
+
<button onClick={() => send('Tell me a story')}>Stream</button>
|
|
164
|
+
</div>
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Self-Hosted Hooks (BinarioAI core)
|
|
170
|
+
|
|
171
|
+
For self-hosted mode using the `BinarioAI` instance:
|
|
172
|
+
|
|
173
|
+
```tsx
|
|
174
|
+
import { useBinarioChat } from 'binario/react';
|
|
175
|
+
|
|
176
|
+
function ChatComponent() {
|
|
177
|
+
const {
|
|
178
|
+
messages,
|
|
179
|
+
sendMessage,
|
|
180
|
+
isLoading,
|
|
181
|
+
error,
|
|
182
|
+
clearMessages
|
|
183
|
+
} = useBinarioChat({
|
|
184
|
+
apiKey: 'bsk_your_api_key',
|
|
185
|
+
systemPrompt: 'You are a helpful assistant.',
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
return (
|
|
189
|
+
<div>
|
|
190
|
+
<div className="messages">
|
|
191
|
+
{messages.map((msg, i) => (
|
|
192
|
+
<div key={i} className={`message ${msg.role}`}>
|
|
193
|
+
{msg.content}
|
|
194
|
+
</div>
|
|
195
|
+
))}
|
|
196
|
+
</div>
|
|
197
|
+
|
|
198
|
+
{isLoading && <div>Thinking...</div>}
|
|
199
|
+
{error && <div className="error">{error.message}</div>}
|
|
200
|
+
|
|
201
|
+
<form onSubmit={handleSubmit}>
|
|
202
|
+
<input name="message" placeholder="Type a message..." />
|
|
203
|
+
<button type="submit" disabled={isLoading}>Send</button>
|
|
204
|
+
</form>
|
|
205
|
+
</div>
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### useBinarioStream
|
|
211
|
+
|
|
212
|
+
Streaming responses with real-time updates:
|
|
213
|
+
|
|
214
|
+
```tsx
|
|
215
|
+
import { useBinarioStream } from 'binario/react';
|
|
216
|
+
|
|
217
|
+
function StreamingComponent() {
|
|
218
|
+
const {
|
|
219
|
+
content,
|
|
220
|
+
isStreaming,
|
|
221
|
+
startStream,
|
|
222
|
+
stopStream
|
|
223
|
+
} = useBinarioStream({
|
|
224
|
+
apiKey: 'bsk_your_api_key',
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
return (
|
|
228
|
+
<div>
|
|
229
|
+
<div className="output">{content}</div>
|
|
230
|
+
<button onClick={() => startStream('Tell me a story')}>
|
|
231
|
+
Start
|
|
232
|
+
</button>
|
|
233
|
+
{isStreaming && (
|
|
234
|
+
<button onClick={stopStream}>Stop</button>
|
|
235
|
+
)}
|
|
236
|
+
</div>
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### useBinarioAgent
|
|
242
|
+
|
|
243
|
+
Run AI agents with tools in React:
|
|
244
|
+
|
|
245
|
+
```tsx
|
|
246
|
+
import { useBinarioAgent } from 'binario/react';
|
|
247
|
+
import { defineTool } from 'binario';
|
|
248
|
+
import { z } from 'zod';
|
|
249
|
+
|
|
250
|
+
const weatherTool = defineTool({
|
|
251
|
+
name: 'get_weather',
|
|
252
|
+
description: 'Get weather for a location',
|
|
253
|
+
parameters: z.object({
|
|
254
|
+
location: z.string(),
|
|
255
|
+
}),
|
|
256
|
+
execute: async ({ location }) => {
|
|
257
|
+
return { temperature: 22, condition: 'sunny' };
|
|
258
|
+
},
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
function AgentComponent() {
|
|
262
|
+
const {
|
|
263
|
+
result,
|
|
264
|
+
isRunning,
|
|
265
|
+
runAgent,
|
|
266
|
+
steps
|
|
267
|
+
} = useBinarioAgent({
|
|
268
|
+
apiKey: 'bsk_your_api_key',
|
|
269
|
+
tools: [weatherTool],
|
|
270
|
+
systemPrompt: 'You help users with weather information.',
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
return (
|
|
274
|
+
<div>
|
|
275
|
+
<button onClick={() => runAgent('What\'s the weather in Paris?')}>
|
|
276
|
+
Ask Agent
|
|
277
|
+
</button>
|
|
278
|
+
|
|
279
|
+
{steps.map((step, i) => (
|
|
280
|
+
<div key={i} className="step">
|
|
281
|
+
{step.type === 'tool_call' && (
|
|
282
|
+
<span>Called: {step.toolName}</span>
|
|
283
|
+
)}
|
|
284
|
+
</div>
|
|
285
|
+
))}
|
|
286
|
+
|
|
287
|
+
{result && <div className="result">{result.output}</div>}
|
|
288
|
+
</div>
|
|
289
|
+
);
|
|
290
|
+
}
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### useBinarioCompletion
|
|
294
|
+
|
|
295
|
+
Simple completions without chat history management:
|
|
296
|
+
|
|
297
|
+
```tsx
|
|
298
|
+
import { useBinarioCompletion } from 'binario/react';
|
|
299
|
+
|
|
300
|
+
function CompletionComponent() {
|
|
301
|
+
const {
|
|
302
|
+
result,
|
|
303
|
+
isLoading,
|
|
304
|
+
error,
|
|
305
|
+
complete,
|
|
306
|
+
reset
|
|
307
|
+
} = useBinarioCompletion({
|
|
308
|
+
apiKey: 'bsk_your_api_key',
|
|
309
|
+
model: 'gpt-4',
|
|
310
|
+
temperature: 0.7,
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
return (
|
|
314
|
+
<div>
|
|
315
|
+
<button onClick={() => complete('Explain quantum computing in simple terms')}>
|
|
316
|
+
Generate
|
|
317
|
+
</button>
|
|
318
|
+
{isLoading && <div>Generating...</div>}
|
|
319
|
+
{result && <div className="result">{result.content}</div>}
|
|
320
|
+
{error && <div className="error">{error.message}</div>}
|
|
321
|
+
<button onClick={reset}>Reset</button>
|
|
322
|
+
</div>
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### useBinarioStructured
|
|
328
|
+
|
|
329
|
+
Type-safe structured outputs with Zod schemas:
|
|
330
|
+
|
|
331
|
+
```tsx
|
|
332
|
+
import { useBinarioStructured } from 'binario/react';
|
|
333
|
+
import { z } from 'zod';
|
|
334
|
+
|
|
335
|
+
const ProductSchema = z.object({
|
|
336
|
+
name: z.string(),
|
|
337
|
+
price: z.number(),
|
|
338
|
+
category: z.enum(['electronics', 'clothing', 'food']),
|
|
339
|
+
inStock: z.boolean(),
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
function StructuredComponent() {
|
|
343
|
+
const {
|
|
344
|
+
data,
|
|
345
|
+
isLoading,
|
|
346
|
+
error,
|
|
347
|
+
extract
|
|
348
|
+
} = useBinarioStructured<z.infer<typeof ProductSchema>>({
|
|
349
|
+
apiKey: 'bsk_your_api_key',
|
|
350
|
+
schema: ProductSchema,
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
return (
|
|
354
|
+
<div>
|
|
355
|
+
<button onClick={() => extract('iPhone 15 Pro, $999, electronics, in stock')}>
|
|
356
|
+
Extract Product
|
|
357
|
+
</button>
|
|
358
|
+
{data && (
|
|
359
|
+
<div>
|
|
360
|
+
<p>Name: {data.name}</p>
|
|
361
|
+
<p>Price: ${data.price}</p>
|
|
362
|
+
<p>Category: {data.category}</p>
|
|
363
|
+
<p>In Stock: {data.inStock ? 'Yes' : 'No'}</p>
|
|
364
|
+
</div>
|
|
365
|
+
)}
|
|
366
|
+
</div>
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
### useBinarioTools
|
|
372
|
+
|
|
373
|
+
Tool calling with automatic execution:
|
|
374
|
+
|
|
375
|
+
```tsx
|
|
376
|
+
import { useBinarioTools } from 'binario/react';
|
|
377
|
+
import { z } from 'zod';
|
|
378
|
+
|
|
379
|
+
function ToolsComponent() {
|
|
380
|
+
const {
|
|
381
|
+
messages,
|
|
382
|
+
toolCalls,
|
|
383
|
+
isExecuting,
|
|
384
|
+
sendMessage,
|
|
385
|
+
} = useBinarioTools({
|
|
386
|
+
apiKey: 'bsk_your_api_key',
|
|
387
|
+
tools: {
|
|
388
|
+
get_weather: {
|
|
389
|
+
description: 'Get weather for a location',
|
|
390
|
+
parameters: z.object({
|
|
391
|
+
location: z.string(),
|
|
392
|
+
}),
|
|
393
|
+
execute: async ({ location }) => {
|
|
394
|
+
return { temperature: 22, condition: 'sunny', location };
|
|
395
|
+
},
|
|
396
|
+
},
|
|
397
|
+
calculate: {
|
|
398
|
+
description: 'Perform calculations',
|
|
399
|
+
parameters: z.object({
|
|
400
|
+
expression: z.string(),
|
|
401
|
+
}),
|
|
402
|
+
execute: async ({ expression }) => {
|
|
403
|
+
return { result: eval(expression) };
|
|
404
|
+
},
|
|
405
|
+
},
|
|
406
|
+
},
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
return (
|
|
410
|
+
<div>
|
|
411
|
+
<button onClick={() => sendMessage('What is the weather in Paris?')}>
|
|
412
|
+
Ask
|
|
413
|
+
</button>
|
|
414
|
+
{toolCalls.map((call, i) => (
|
|
415
|
+
<div key={i}>Tool: {call.name} → {JSON.stringify(call.result)}</div>
|
|
416
|
+
))}
|
|
417
|
+
</div>
|
|
418
|
+
);
|
|
419
|
+
}
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
### useBinarioMemory
|
|
423
|
+
|
|
424
|
+
Memory management for persistent conversations:
|
|
425
|
+
|
|
426
|
+
```tsx
|
|
427
|
+
import { useBinarioMemory } from 'binario/react';
|
|
428
|
+
|
|
429
|
+
function MemoryComponent() {
|
|
430
|
+
const {
|
|
431
|
+
messages,
|
|
432
|
+
context,
|
|
433
|
+
addMessage,
|
|
434
|
+
getContext,
|
|
435
|
+
clear,
|
|
436
|
+
isLoading,
|
|
437
|
+
tokenCount,
|
|
438
|
+
} = useBinarioMemory({
|
|
439
|
+
type: 'buffer',
|
|
440
|
+
maxMessages: 50,
|
|
441
|
+
maxTokens: 4000,
|
|
442
|
+
});
|
|
443
|
+
|
|
444
|
+
// Add messages
|
|
445
|
+
const handleSend = async (content: string) => {
|
|
446
|
+
await addMessage({ role: 'user', content });
|
|
447
|
+
// Get AI response and add it
|
|
448
|
+
await addMessage({ role: 'assistant', content: 'Response...' });
|
|
449
|
+
};
|
|
450
|
+
|
|
451
|
+
return (
|
|
452
|
+
<div>
|
|
453
|
+
<div>Messages: {messages.length}</div>
|
|
454
|
+
<div>Tokens: {tokenCount}</div>
|
|
455
|
+
<button onClick={clear}>Clear Memory</button>
|
|
456
|
+
</div>
|
|
457
|
+
);
|
|
458
|
+
}
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
### useBinarioChatWithMemory
|
|
462
|
+
|
|
463
|
+
Chat with automatic persistent memory:
|
|
464
|
+
|
|
465
|
+
```tsx
|
|
466
|
+
import { useBinarioChatWithMemory } from 'binario/react';
|
|
467
|
+
|
|
468
|
+
function PersistentChatComponent() {
|
|
469
|
+
const {
|
|
470
|
+
messages,
|
|
471
|
+
sendMessage,
|
|
472
|
+
isLoading,
|
|
473
|
+
error,
|
|
474
|
+
summary,
|
|
475
|
+
memoryStats,
|
|
476
|
+
clearMemory,
|
|
477
|
+
} = useBinarioChatWithMemory({
|
|
478
|
+
apiKey: 'bsk_your_api_key',
|
|
479
|
+
memoryType: 'summary-buffer', // 'buffer' | 'summary' | 'summary-buffer' | 'vector'
|
|
480
|
+
memoryOptions: {
|
|
481
|
+
maxMessages: 20,
|
|
482
|
+
summarizeThreshold: 10,
|
|
483
|
+
},
|
|
484
|
+
systemPrompt: 'You are a helpful assistant with memory.',
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
return (
|
|
488
|
+
<div>
|
|
489
|
+
<div className="stats">
|
|
490
|
+
<span>Messages in memory: {memoryStats.messageCount}</span>
|
|
491
|
+
<span>Tokens used: {memoryStats.tokenCount}</span>
|
|
492
|
+
</div>
|
|
493
|
+
|
|
494
|
+
{summary && (
|
|
495
|
+
<div className="summary">
|
|
496
|
+
<strong>Conversation summary:</strong> {summary}
|
|
497
|
+
</div>
|
|
498
|
+
)}
|
|
499
|
+
|
|
500
|
+
<div className="messages">
|
|
501
|
+
{messages.map((msg, i) => (
|
|
502
|
+
<div key={i} className={msg.role}>{msg.content}</div>
|
|
503
|
+
))}
|
|
504
|
+
</div>
|
|
505
|
+
|
|
506
|
+
<input
|
|
507
|
+
onKeyDown={(e) => {
|
|
508
|
+
if (e.key === 'Enter') {
|
|
509
|
+
sendMessage(e.currentTarget.value);
|
|
510
|
+
e.currentTarget.value = '';
|
|
511
|
+
}
|
|
512
|
+
}}
|
|
513
|
+
/>
|
|
514
|
+
|
|
515
|
+
<button onClick={clearMemory}>Clear Memory</button>
|
|
516
|
+
</div>
|
|
517
|
+
);
|
|
518
|
+
}
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
### useBinarioEmbed
|
|
522
|
+
|
|
523
|
+
Generate embeddings for semantic operations:
|
|
524
|
+
|
|
525
|
+
```tsx
|
|
526
|
+
import { useBinarioEmbed } from 'binario/react';
|
|
527
|
+
|
|
528
|
+
function EmbeddingsComponent() {
|
|
529
|
+
const {
|
|
530
|
+
embed,
|
|
531
|
+
embedMany,
|
|
532
|
+
similarity,
|
|
533
|
+
findSimilar,
|
|
534
|
+
isLoading,
|
|
535
|
+
error,
|
|
536
|
+
} = useBinarioEmbed({
|
|
537
|
+
model: 'bge-base-en-v1.5',
|
|
538
|
+
cacheResults: true,
|
|
539
|
+
});
|
|
540
|
+
|
|
541
|
+
// Generate single embedding
|
|
542
|
+
const handleEmbed = async () => {
|
|
543
|
+
const result = await embed('Hello, world!');
|
|
544
|
+
console.log('Embedding dimensions:', result.embedding.length);
|
|
545
|
+
};
|
|
546
|
+
|
|
547
|
+
// Generate batch embeddings
|
|
548
|
+
const handleBatchEmbed = async () => {
|
|
549
|
+
const results = await embedMany([
|
|
550
|
+
'First text',
|
|
551
|
+
'Second text',
|
|
552
|
+
'Third text',
|
|
553
|
+
]);
|
|
554
|
+
console.log('Generated embeddings:', results.embeddings.length);
|
|
555
|
+
};
|
|
556
|
+
|
|
557
|
+
// Calculate similarity between texts
|
|
558
|
+
const handleSimilarity = async () => {
|
|
559
|
+
const score = await similarity(
|
|
560
|
+
'I love programming',
|
|
561
|
+
'Coding is my passion'
|
|
562
|
+
);
|
|
563
|
+
console.log('Similarity score:', score); // ~0.85
|
|
564
|
+
};
|
|
565
|
+
|
|
566
|
+
// Find similar texts
|
|
567
|
+
const handleFindSimilar = async () => {
|
|
568
|
+
const documents = [
|
|
569
|
+
'JavaScript is a programming language',
|
|
570
|
+
'Python is great for data science',
|
|
571
|
+
'The weather is nice today',
|
|
572
|
+
'React is a UI library',
|
|
573
|
+
];
|
|
574
|
+
|
|
575
|
+
const similar = await findSimilar('frontend development', documents, {
|
|
576
|
+
topK: 2,
|
|
577
|
+
minScore: 0.5,
|
|
578
|
+
});
|
|
579
|
+
|
|
580
|
+
console.log('Similar documents:', similar);
|
|
581
|
+
// [{ text: 'React is a UI library', score: 0.78 }, ...]
|
|
582
|
+
};
|
|
583
|
+
|
|
584
|
+
return (
|
|
585
|
+
<div>
|
|
586
|
+
<button onClick={handleEmbed}>Generate Embedding</button>
|
|
587
|
+
<button onClick={handleBatchEmbed}>Batch Embed</button>
|
|
588
|
+
<button onClick={handleSimilarity}>Check Similarity</button>
|
|
589
|
+
<button onClick={handleFindSimilar}>Find Similar</button>
|
|
590
|
+
{isLoading && <div>Processing...</div>}
|
|
591
|
+
</div>
|
|
592
|
+
);
|
|
593
|
+
}
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
### useBinarioSemanticSearch
|
|
597
|
+
|
|
598
|
+
Full semantic search solution with document management:
|
|
599
|
+
|
|
600
|
+
```tsx
|
|
601
|
+
import { useBinarioSemanticSearch } from 'binario/react';
|
|
602
|
+
|
|
603
|
+
function SemanticSearchComponent() {
|
|
604
|
+
const {
|
|
605
|
+
addDocument,
|
|
606
|
+
addDocuments,
|
|
607
|
+
search,
|
|
608
|
+
removeDocument,
|
|
609
|
+
clear,
|
|
610
|
+
documentCount,
|
|
611
|
+
isLoading,
|
|
612
|
+
} = useBinarioSemanticSearch({
|
|
613
|
+
model: 'bge-base-en-v1.5',
|
|
614
|
+
});
|
|
615
|
+
|
|
616
|
+
// Add documents to the index
|
|
617
|
+
const handleAddDocuments = async () => {
|
|
618
|
+
await addDocuments([
|
|
619
|
+
{ id: 'doc1', content: 'React is a JavaScript library for building UIs' },
|
|
620
|
+
{ id: 'doc2', content: 'Vue.js is a progressive JavaScript framework' },
|
|
621
|
+
{ id: 'doc3', content: 'Angular is a platform for building web apps' },
|
|
622
|
+
{ id: 'doc4', content: 'Python is popular for machine learning' },
|
|
623
|
+
]);
|
|
624
|
+
};
|
|
625
|
+
|
|
626
|
+
// Search for similar documents
|
|
627
|
+
const handleSearch = async () => {
|
|
628
|
+
const results = await search('frontend framework for web development', {
|
|
629
|
+
maxResults: 3,
|
|
630
|
+
minScore: 0.5,
|
|
631
|
+
});
|
|
632
|
+
|
|
633
|
+
console.log('Search results:', results);
|
|
634
|
+
// [
|
|
635
|
+
// { id: 'doc3', content: 'Angular...', score: 0.82 },
|
|
636
|
+
// { id: 'doc1', content: 'React...', score: 0.79 },
|
|
637
|
+
// { id: 'doc2', content: 'Vue.js...', score: 0.77 },
|
|
638
|
+
// ]
|
|
639
|
+
};
|
|
640
|
+
|
|
641
|
+
return (
|
|
642
|
+
<div>
|
|
643
|
+
<div>Documents indexed: {documentCount}</div>
|
|
644
|
+
<button onClick={handleAddDocuments}>Add Documents</button>
|
|
645
|
+
<button onClick={handleSearch}>Search</button>
|
|
646
|
+
<button onClick={() => removeDocument('doc1')}>Remove doc1</button>
|
|
647
|
+
<button onClick={clear}>Clear Index</button>
|
|
648
|
+
</div>
|
|
649
|
+
);
|
|
650
|
+
}
|
|
651
|
+
```
|
|
652
|
+
|
|
653
|
+
## 🧠 Memory System
|
|
654
|
+
|
|
655
|
+
The Memory System provides persistent conversation context with multiple strategies for different use cases.
|
|
656
|
+
|
|
657
|
+
### Memory Types
|
|
658
|
+
|
|
659
|
+
| Type | Description | Best For |
|
|
660
|
+
|------|-------------|----------|
|
|
661
|
+
| `buffer` | Sliding window of recent messages | Simple chatbots, short conversations |
|
|
662
|
+
| `summary` | LLM-powered summarization | Long conversations, context compression |
|
|
663
|
+
| `summary-buffer` | Hybrid (buffer + summary) | Balanced memory with both recent and historical context |
|
|
664
|
+
| `vector` | Semantic search with embeddings | RAG, document Q&A, knowledge retrieval |
|
|
665
|
+
|
|
666
|
+
### BufferMemory
|
|
667
|
+
|
|
668
|
+
Keeps a sliding window of the most recent messages:
|
|
669
|
+
|
|
670
|
+
```typescript
|
|
671
|
+
import { createMemory } from 'binario';
|
|
672
|
+
|
|
673
|
+
const memory = createMemory({
|
|
674
|
+
type: 'buffer',
|
|
675
|
+
options: {
|
|
676
|
+
maxMessages: 50, // Keep last 50 messages
|
|
677
|
+
maxTokens: 4000, // Or limit by token count
|
|
678
|
+
},
|
|
679
|
+
});
|
|
680
|
+
|
|
681
|
+
// Add messages
|
|
682
|
+
await memory.add({ role: 'user', content: 'Hello!' });
|
|
683
|
+
await memory.add({ role: 'assistant', content: 'Hi there!' });
|
|
684
|
+
|
|
685
|
+
// Get context for AI
|
|
686
|
+
const context = await memory.getContext();
|
|
687
|
+
console.log(context.messages); // Recent messages
|
|
688
|
+
console.log(context.tokenCount); // Approximate tokens
|
|
689
|
+
```
|
|
690
|
+
|
|
691
|
+
### SummaryMemory
|
|
692
|
+
|
|
693
|
+
Automatically summarizes conversations when they exceed a threshold:
|
|
694
|
+
|
|
695
|
+
```typescript
|
|
696
|
+
import { createMemory } from 'binario';
|
|
697
|
+
|
|
698
|
+
const memory = createMemory({
|
|
699
|
+
type: 'summary',
|
|
700
|
+
options: {
|
|
701
|
+
summarizeThreshold: 20, // Summarize after 20 messages
|
|
702
|
+
summaryMaxTokens: 500, // Max tokens for summary
|
|
703
|
+
},
|
|
704
|
+
});
|
|
705
|
+
|
|
706
|
+
// Add messages as usual
|
|
707
|
+
await memory.add({ role: 'user', content: 'Tell me about Paris' });
|
|
708
|
+
await memory.add({ role: 'assistant', content: 'Paris is the capital of France...' });
|
|
709
|
+
|
|
710
|
+
// Get context includes summary
|
|
711
|
+
const context = await memory.getContext();
|
|
712
|
+
console.log(context.summary); // "User asked about Paris. Assistant explained..."
|
|
713
|
+
console.log(context.messages); // Recent messages after summary
|
|
714
|
+
```
|
|
715
|
+
|
|
716
|
+
### SummaryBufferMemory
|
|
717
|
+
|
|
718
|
+
Combines buffer memory with automatic summarization:
|
|
719
|
+
|
|
720
|
+
```typescript
|
|
721
|
+
import { createMemory } from 'binario';
|
|
722
|
+
|
|
723
|
+
const memory = createMemory({
|
|
724
|
+
type: 'summary-buffer',
|
|
725
|
+
options: {
|
|
726
|
+
maxMessages: 10, // Keep 10 recent messages
|
|
727
|
+
summarizeThreshold: 20, // Summarize when total exceeds 20
|
|
728
|
+
summaryMaxTokens: 500,
|
|
729
|
+
},
|
|
730
|
+
});
|
|
731
|
+
|
|
732
|
+
// Best of both worlds
|
|
733
|
+
const context = await memory.getContext();
|
|
734
|
+
console.log(context.summary); // Summarized older context
|
|
735
|
+
console.log(context.messages); // Recent 10 messages
|
|
736
|
+
```
|
|
737
|
+
|
|
738
|
+
### VectorMemory
|
|
739
|
+
|
|
740
|
+
Semantic retrieval for relevant context:
|
|
741
|
+
|
|
742
|
+
```typescript
|
|
743
|
+
import { createMemory } from 'binario';
|
|
744
|
+
|
|
745
|
+
const memory = createMemory({
|
|
746
|
+
type: 'vector',
|
|
747
|
+
options: {
|
|
748
|
+
topK: 5, // Retrieve top 5 relevant messages
|
|
749
|
+
minScore: 0.7, // Minimum similarity threshold
|
|
750
|
+
embeddings: embeddingsProvider, // Your embeddings provider
|
|
751
|
+
},
|
|
752
|
+
});
|
|
753
|
+
|
|
754
|
+
// Add messages (embeddings generated automatically)
|
|
755
|
+
await memory.add({ role: 'user', content: 'How do I deploy to Cloudflare?' });
|
|
756
|
+
await memory.add({ role: 'assistant', content: 'Use wrangler deploy command...' });
|
|
757
|
+
|
|
758
|
+
// Search retrieves semantically relevant messages
|
|
759
|
+
const results = await memory.search('cloudflare deployment');
|
|
760
|
+
// Returns messages about deployment, even if exact words don't match
|
|
761
|
+
```
|
|
762
|
+
|
|
763
|
+
### Storage Backends
|
|
764
|
+
|
|
765
|
+
Memory supports multiple storage backends:
|
|
766
|
+
|
|
767
|
+
```typescript
|
|
768
|
+
import {
|
|
769
|
+
createMemory,
|
|
770
|
+
InMemoryStore,
|
|
771
|
+
LocalStorageStore,
|
|
772
|
+
CloudflareKVStore
|
|
773
|
+
} from 'binario';
|
|
774
|
+
|
|
775
|
+
// In-Memory (default, development)
|
|
776
|
+
const memoryDev = createMemory({
|
|
777
|
+
type: 'buffer',
|
|
778
|
+
store: new InMemoryStore(),
|
|
779
|
+
});
|
|
780
|
+
|
|
781
|
+
// LocalStorage (browser persistence)
|
|
782
|
+
const memoryBrowser = createMemory({
|
|
783
|
+
type: 'buffer',
|
|
784
|
+
store: new LocalStorageStore('my-chat-'),
|
|
785
|
+
});
|
|
786
|
+
|
|
787
|
+
// Cloudflare KV (production, distributed)
|
|
788
|
+
const memoryProd = createMemory({
|
|
789
|
+
type: 'buffer',
|
|
790
|
+
store: new CloudflareKVStore(env.CHAT_KV),
|
|
791
|
+
});
|
|
792
|
+
```
|
|
793
|
+
|
|
794
|
+
## 🔍 Embeddings API
|
|
795
|
+
|
|
796
|
+
Generate text embeddings for semantic search, similarity, and RAG applications.
|
|
797
|
+
|
|
798
|
+
### CloudflareEmbeddings
|
|
799
|
+
|
|
800
|
+
Use Cloudflare Workers AI for embeddings:
|
|
801
|
+
|
|
802
|
+
```typescript
|
|
803
|
+
import { CloudflareEmbeddings, createCloudflareEmbeddings } from 'binario';
|
|
804
|
+
|
|
805
|
+
// With Workers AI binding (recommended in Workers)
|
|
806
|
+
const embeddings = new CloudflareEmbeddings({
|
|
807
|
+
binding: env.AI,
|
|
808
|
+
model: 'bge-base-en-v1.5',
|
|
809
|
+
});
|
|
810
|
+
|
|
811
|
+
// With REST API (for external use)
|
|
812
|
+
const embeddings = createCloudflareEmbeddings({
|
|
813
|
+
accountId: process.env.CF_ACCOUNT_ID,
|
|
814
|
+
apiKey: process.env.CF_API_KEY,
|
|
815
|
+
model: 'bge-large-en-v1.5',
|
|
816
|
+
});
|
|
817
|
+
```
|
|
818
|
+
|
|
819
|
+
### Available Models
|
|
820
|
+
|
|
821
|
+
| Model | Dimensions | Use Case |
|
|
822
|
+
|-------|------------|----------|
|
|
823
|
+
| `bge-small-en-v1.5` | 384 | Fast, lightweight |
|
|
824
|
+
| `bge-base-en-v1.5` | 768 | Balanced (default) |
|
|
825
|
+
| `bge-large-en-v1.5` | 1024 | Highest quality |
|
|
826
|
+
|
|
827
|
+
### Generate Embeddings
|
|
828
|
+
|
|
829
|
+
```typescript
|
|
830
|
+
// Single embedding
|
|
831
|
+
const result = await embeddings.embed('Hello, world!');
|
|
832
|
+
console.log(result.embedding); // Float32Array(768)
|
|
833
|
+
console.log(result.model); // 'bge-base-en-v1.5'
|
|
834
|
+
|
|
835
|
+
// Batch embeddings (more efficient)
|
|
836
|
+
const batch = await embeddings.embedMany([
|
|
837
|
+
'First document',
|
|
838
|
+
'Second document',
|
|
839
|
+
'Third document',
|
|
840
|
+
]);
|
|
841
|
+
console.log(batch.embeddings.length); // 3
|
|
842
|
+
```
|
|
843
|
+
|
|
844
|
+
### Similarity Search
|
|
845
|
+
|
|
846
|
+
```typescript
|
|
847
|
+
// Calculate cosine similarity between two embeddings
|
|
848
|
+
function cosineSimilarity(a: number[], b: number[]): number {
|
|
849
|
+
let dotProduct = 0;
|
|
850
|
+
let normA = 0;
|
|
851
|
+
let normB = 0;
|
|
852
|
+
|
|
853
|
+
for (let i = 0; i < a.length; i++) {
|
|
854
|
+
dotProduct += a[i] * b[i];
|
|
855
|
+
normA += a[i] * a[i];
|
|
856
|
+
normB += b[i] * b[i];
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
return dotProduct / (Math.sqrt(normA) * Math.sqrt(normB));
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
// Find similar documents
|
|
863
|
+
const query = await embeddings.embed('machine learning');
|
|
864
|
+
const docs = await embeddings.embedMany([
|
|
865
|
+
'artificial intelligence and neural networks',
|
|
866
|
+
'cooking recipes for beginners',
|
|
867
|
+
'deep learning models',
|
|
868
|
+
]);
|
|
869
|
+
|
|
870
|
+
const similarities = docs.embeddings.map((emb, i) => ({
|
|
871
|
+
index: i,
|
|
872
|
+
score: cosineSimilarity(query.embedding, emb),
|
|
873
|
+
}));
|
|
874
|
+
|
|
875
|
+
similarities.sort((a, b) => b.score - a.score);
|
|
876
|
+
console.log(similarities);
|
|
877
|
+
// [{ index: 2, score: 0.89 }, { index: 0, score: 0.82 }, { index: 1, score: 0.12 }]
|
|
878
|
+
```
|
|
879
|
+
|
|
880
|
+
### RAG (Retrieval Augmented Generation)
|
|
881
|
+
|
|
882
|
+
```typescript
|
|
883
|
+
import { Binario, CloudflareEmbeddings, createMemory } from 'binario';
|
|
884
|
+
|
|
885
|
+
// Setup
|
|
886
|
+
const client = new Binario('bsk_your_api_key');
|
|
887
|
+
const embeddings = new CloudflareEmbeddings({ binding: env.AI });
|
|
888
|
+
|
|
889
|
+
// Create vector memory for documents
|
|
890
|
+
const memory = createMemory({
|
|
891
|
+
type: 'vector',
|
|
892
|
+
options: {
|
|
893
|
+
topK: 3,
|
|
894
|
+
embeddings,
|
|
895
|
+
},
|
|
896
|
+
});
|
|
897
|
+
|
|
898
|
+
// Index your documents
|
|
899
|
+
const documents = [
|
|
900
|
+
'Binario is an AI SDK for Cloudflare Workers',
|
|
901
|
+
'It supports multiple AI providers including OpenAI and Anthropic',
|
|
902
|
+
'The Memory System provides persistent conversation context',
|
|
903
|
+
'Embeddings can be generated using Cloudflare Workers AI',
|
|
904
|
+
];
|
|
905
|
+
|
|
906
|
+
for (const doc of documents) {
|
|
907
|
+
await memory.add({ role: 'system', content: doc });
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
// Query with RAG
|
|
911
|
+
async function queryWithRAG(question: string) {
|
|
912
|
+
// Retrieve relevant context
|
|
913
|
+
const results = await memory.search(question);
|
|
914
|
+
const context = results.map(r => r.content).join('\n');
|
|
915
|
+
|
|
916
|
+
// Generate answer with context
|
|
917
|
+
const response = await client.chat([
|
|
918
|
+
{ role: 'system', content: `Answer based on this context:\n${context}` },
|
|
919
|
+
{ role: 'user', content: question },
|
|
920
|
+
]);
|
|
921
|
+
|
|
922
|
+
return response.content;
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
const answer = await queryWithRAG('What AI providers does Binario support?');
|
|
926
|
+
// "Binario supports multiple AI providers including OpenAI and Anthropic."
|
|
927
|
+
```
|
|
928
|
+
|
|
929
|
+
## 🤖 Agent Framework
|
|
930
|
+
|
|
931
|
+
Create powerful AI agents with tool calling:
|
|
932
|
+
|
|
933
|
+
```typescript
|
|
934
|
+
import { Binario, defineTool } from 'binario';
|
|
935
|
+
import { z } from 'zod';
|
|
936
|
+
|
|
937
|
+
const client = new Binario('bsk_your_api_key');
|
|
938
|
+
|
|
939
|
+
// Define tools with Zod schemas
|
|
940
|
+
const calculatorTool = defineTool({
|
|
941
|
+
name: 'calculator',
|
|
942
|
+
description: 'Perform mathematical calculations',
|
|
943
|
+
parameters: z.object({
|
|
944
|
+
operation: z.enum(['add', 'subtract', 'multiply', 'divide']),
|
|
945
|
+
a: z.number().describe('First number'),
|
|
946
|
+
b: z.number().describe('Second number'),
|
|
947
|
+
}),
|
|
948
|
+
execute: async ({ operation, a, b }) => {
|
|
949
|
+
switch (operation) {
|
|
950
|
+
case 'add': return { result: a + b };
|
|
951
|
+
case 'subtract': return { result: a - b };
|
|
952
|
+
case 'multiply': return { result: a * b };
|
|
953
|
+
case 'divide': return { result: a / b };
|
|
954
|
+
}
|
|
955
|
+
},
|
|
956
|
+
});
|
|
957
|
+
|
|
958
|
+
const searchTool = defineTool({
|
|
959
|
+
name: 'web_search',
|
|
960
|
+
description: 'Search the web for information',
|
|
961
|
+
parameters: z.object({
|
|
962
|
+
query: z.string().describe('Search query'),
|
|
963
|
+
limit: z.number().optional().default(5),
|
|
964
|
+
}),
|
|
965
|
+
execute: async ({ query, limit }) => {
|
|
966
|
+
// Your search implementation
|
|
967
|
+
return { results: ['Result 1', 'Result 2'] };
|
|
968
|
+
},
|
|
969
|
+
});
|
|
970
|
+
|
|
971
|
+
// Create agent with tools
|
|
972
|
+
const agent = client.agent({
|
|
973
|
+
systemPrompt: 'You are a helpful assistant with access to tools.',
|
|
974
|
+
tools: [calculatorTool, searchTool],
|
|
975
|
+
maxIterations: 10,
|
|
976
|
+
});
|
|
977
|
+
|
|
978
|
+
// Run the agent
|
|
979
|
+
const result = await agent.run('What is 25 * 4, then search for that number');
|
|
980
|
+
|
|
981
|
+
console.log(result.output);
|
|
982
|
+
console.log('Steps taken:', result.steps.length);
|
|
983
|
+
console.log('Tokens used:', result.usage.totalTokens);
|
|
984
|
+
```
|
|
985
|
+
|
|
986
|
+
## ☁️ Cloudflare Workers
|
|
987
|
+
|
|
988
|
+
Utilities for building AI-powered Workers:
|
|
989
|
+
|
|
990
|
+
```typescript
|
|
991
|
+
import {
|
|
992
|
+
runWithTools,
|
|
993
|
+
tool,
|
|
994
|
+
calculateNeurons,
|
|
995
|
+
getRecommendedModel,
|
|
996
|
+
CLOUDFLARE_MODELS,
|
|
997
|
+
} from 'binario/cloudflare';
|
|
998
|
+
|
|
999
|
+
export default {
|
|
1000
|
+
async fetch(request: Request, env: Env): Promise<Response> {
|
|
1001
|
+
// Get recommended model based on task
|
|
1002
|
+
const model = getRecommendedModel('chat', true); // true = prefer free tier
|
|
1003
|
+
|
|
1004
|
+
// Define tools using the simple helper
|
|
1005
|
+
const weatherTool = tool('get_weather', 'Get weather info', {
|
|
1006
|
+
location: { type: 'string', description: 'City name' },
|
|
1007
|
+
});
|
|
1008
|
+
|
|
1009
|
+
// Run with tool support
|
|
1010
|
+
const result = await runWithTools(
|
|
1011
|
+
env.AI,
|
|
1012
|
+
model,
|
|
1013
|
+
[{ role: 'user', content: 'What is the weather in Tokyo?' }],
|
|
1014
|
+
[weatherTool],
|
|
1015
|
+
{
|
|
1016
|
+
onToolCall: async (name, args) => {
|
|
1017
|
+
if (name === 'get_weather') {
|
|
1018
|
+
return { temperature: 18, condition: 'cloudy' };
|
|
1019
|
+
}
|
|
1020
|
+
},
|
|
1021
|
+
}
|
|
1022
|
+
);
|
|
1023
|
+
|
|
1024
|
+
// Calculate neuron usage for billing
|
|
1025
|
+
const neurons = calculateNeurons(model, result.usage);
|
|
1026
|
+
|
|
1027
|
+
return Response.json({
|
|
1028
|
+
response: result.content,
|
|
1029
|
+
model,
|
|
1030
|
+
neurons,
|
|
1031
|
+
});
|
|
1032
|
+
},
|
|
1033
|
+
};
|
|
1034
|
+
```
|
|
1035
|
+
|
|
1036
|
+
### Available Cloudflare Models
|
|
1037
|
+
|
|
1038
|
+
```typescript
|
|
1039
|
+
import { CLOUDFLARE_MODELS, NEURON_COSTS } from 'binario/cloudflare';
|
|
1040
|
+
|
|
1041
|
+
// All available models
|
|
1042
|
+
console.log(CLOUDFLARE_MODELS);
|
|
1043
|
+
// ['@cf/meta/llama-3.3-70b-instruct-fp8-fast', '@cf/meta/llama-3.2-3b-instruct', ...]
|
|
1044
|
+
|
|
1045
|
+
// Check neuron costs
|
|
1046
|
+
console.log(NEURON_COSTS['@cf/meta/llama-3.3-70b-instruct-fp8-fast']);
|
|
1047
|
+
// { input: 0.0001, output: 0.0003 }
|
|
1048
|
+
```
|
|
1049
|
+
|
|
1050
|
+
## 📊 Structured Outputs
|
|
1051
|
+
|
|
1052
|
+
Get type-safe structured data from AI:
|
|
1053
|
+
|
|
1054
|
+
```typescript
|
|
1055
|
+
import { Binario, createSchema, z } from 'binario';
|
|
1056
|
+
|
|
1057
|
+
const client = new Binario('bsk_your_api_key');
|
|
1058
|
+
|
|
1059
|
+
// Define output schema
|
|
1060
|
+
const ProductSchema = createSchema('Product', z.object({
|
|
1061
|
+
name: z.string().describe('Product name'),
|
|
1062
|
+
price: z.number().describe('Price in USD'),
|
|
1063
|
+
category: z.enum(['electronics', 'clothing', 'food']),
|
|
1064
|
+
inStock: z.boolean(),
|
|
1065
|
+
}));
|
|
1066
|
+
|
|
1067
|
+
// Get structured output
|
|
1068
|
+
const product = await client.structured(
|
|
1069
|
+
'Extract product info: iPhone 15 Pro, $999, electronics, available',
|
|
1070
|
+
ProductSchema
|
|
1071
|
+
);
|
|
1072
|
+
|
|
1073
|
+
console.log(product.name); // "iPhone 15 Pro"
|
|
1074
|
+
console.log(product.price); // 999
|
|
1075
|
+
console.log(product.category); // "electronics"
|
|
1076
|
+
console.log(product.inStock); // true
|
|
1077
|
+
```
|
|
1078
|
+
|
|
1079
|
+
## 🔌 Supported Providers
|
|
1080
|
+
|
|
1081
|
+
| Provider | Status | Models | Free Tier |
|
|
1082
|
+
|----------|--------|--------|-----------|
|
|
1083
|
+
| Cloudflare Workers AI | ✅ Full | Llama 3.2/3.3, Mistral, Qwen, DeepSeek | ✅ 10K neurons/day |
|
|
1084
|
+
| OpenRouter | ✅ Full | 100+ models | ✅ Free models available |
|
|
1085
|
+
| OpenAI | ✅ Full | GPT-4, GPT-4o, GPT-3.5 | ❌ |
|
|
1086
|
+
| Anthropic | ✅ Full | Claude 3.5, Claude 3 | ❌ |
|
|
1087
|
+
| Google | ✅ Full | Gemini Pro, Gemini Flash | ✅ Free tier |
|
|
1088
|
+
| Mistral | ✅ Full | Mistral Large, Medium, Small | ❌ |
|
|
1089
|
+
|
|
1090
|
+
## 💰 Pricing
|
|
1091
|
+
|
|
1092
|
+
| Plan | Requests/Month | Tokens/Month | Price |
|
|
1093
|
+
|------|---------------|--------------|-------|
|
|
1094
|
+
| Free | 1,000 | 50,000 | $0 |
|
|
1095
|
+
| Pro | 50,000 | 500,000 | $19/mo |
|
|
1096
|
+
| Team | 200,000 | 2,000,000 | $79/mo |
|
|
1097
|
+
| Enterprise | Unlimited | Unlimited | Custom |
|
|
1098
|
+
|
|
1099
|
+
## 🔑 Getting Your API Key
|
|
1100
|
+
|
|
1101
|
+
1. Sign up at [binario.dev](https://binario.dev)
|
|
1102
|
+
2. Go to Dashboard → API Keys
|
|
1103
|
+
3. Create a new key starting with `bsk_`
|
|
1104
|
+
4. Use it in your application
|
|
1105
|
+
|
|
1106
|
+
## 🛠️ Error Handling
|
|
1107
|
+
|
|
1108
|
+
```typescript
|
|
1109
|
+
import { Binario, BinarioRateLimitError, BinarioPaymentError } from 'binario';
|
|
1110
|
+
|
|
1111
|
+
const client = new Binario('bsk_your_api_key');
|
|
1112
|
+
|
|
1113
|
+
try {
|
|
1114
|
+
const response = await client.chat('Hello');
|
|
1115
|
+
} catch (error) {
|
|
1116
|
+
if (error instanceof BinarioRateLimitError) {
|
|
1117
|
+
console.log('Rate limited. Retry after:', error.retryAfter);
|
|
1118
|
+
} else if (error instanceof BinarioPaymentError) {
|
|
1119
|
+
console.log('Upgrade required:', error.message);
|
|
1120
|
+
} else {
|
|
1121
|
+
throw error;
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1124
|
+
```
|
|
1125
|
+
|
|
1126
|
+
## 📚 API Reference
|
|
1127
|
+
|
|
1128
|
+
### Binario Class
|
|
1129
|
+
|
|
1130
|
+
```typescript
|
|
1131
|
+
new Binario(apiKey: string)
|
|
1132
|
+
new Binario(options: BinarioOptions)
|
|
1133
|
+
|
|
1134
|
+
interface BinarioOptions {
|
|
1135
|
+
apiKey: string;
|
|
1136
|
+
baseUrl?: string; // Custom API endpoint
|
|
1137
|
+
timeout?: number; // Request timeout in ms
|
|
1138
|
+
retries?: number; // Number of retries
|
|
1139
|
+
}
|
|
1140
|
+
```
|
|
1141
|
+
|
|
1142
|
+
### Methods
|
|
1143
|
+
|
|
1144
|
+
| Method | Description |
|
|
1145
|
+
|--------|-------------|
|
|
1146
|
+
| `chat(message, options?)` | Send a chat message |
|
|
1147
|
+
| `stream(message, options?)` | Stream a response |
|
|
1148
|
+
| `structured(message, schema)` | Get structured output |
|
|
1149
|
+
| `agent(config)` | Create an agent |
|
|
1150
|
+
| `usage()` | Get usage statistics |
|
|
1151
|
+
|
|
1152
|
+
## 🧪 Testing
|
|
1153
|
+
|
|
1154
|
+
```bash
|
|
1155
|
+
# Run tests
|
|
1156
|
+
npm test
|
|
1157
|
+
|
|
1158
|
+
# Run with coverage
|
|
1159
|
+
npm run test:coverage
|
|
1160
|
+
|
|
1161
|
+
# Watch mode
|
|
1162
|
+
npm run test:watch
|
|
1163
|
+
```
|
|
1164
|
+
|
|
1165
|
+
## 📄 License
|
|
1166
|
+
|
|
1167
|
+
MIT © Binario Team
|
|
1168
|
+
|
|
1169
|
+
## 🔗 Links
|
|
1170
|
+
|
|
1171
|
+
- [Documentation](https://binario.dev/docs)
|
|
1172
|
+
- [API Reference](https://binario.dev/docs/api)
|
|
1173
|
+
- [Examples](https://github.com/binario-ai/binario/tree/main/examples)
|
|
1174
|
+
- [Discord Community](https://discord.gg/binario)
|
|
1175
|
+
- [Twitter](https://twitter.com/binario_ai)
|