cencori 1.0.4 → 1.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/dist/index.mjs CHANGED
@@ -27,7 +27,8 @@ var AINamespace = class {
27
27
  maxTokens: request.maxTokens,
28
28
  stream: false,
29
29
  tools: request.tools,
30
- toolChoice: request.toolChoice
30
+ toolChoice: request.toolChoice,
31
+ prompt: request.prompt
31
32
  })
32
33
  });
33
34
  if (!response.ok) {
@@ -36,7 +37,8 @@ var AINamespace = class {
36
37
  }
37
38
  const data = await response.json();
38
39
  const choice = data.choices?.[0];
39
- const toolCalls = choice?.message?.tool_calls?.map((tc) => ({
40
+ const rawToolCalls = data.toolCalls ?? data.tool_calls ?? choice?.message?.tool_calls;
41
+ const toolCalls = rawToolCalls?.map((tc) => ({
40
42
  id: tc.id,
41
43
  type: tc.type,
42
44
  function: {
@@ -45,11 +47,11 @@ var AINamespace = class {
45
47
  }
46
48
  }));
47
49
  return {
48
- id: data.id,
49
- model: data.model,
50
- content: choice?.message?.content ?? "",
50
+ id: data.id ?? `chatcmpl-${Date.now()}`,
51
+ model: data.model ?? request.model,
52
+ content: data.content ?? choice?.message?.content ?? "",
51
53
  toolCalls,
52
- finishReason: choice?.finish_reason,
54
+ finishReason: data.finish_reason ?? choice?.finish_reason,
53
55
  usage: {
54
56
  promptTokens: data.usage?.prompt_tokens ?? 0,
55
57
  completionTokens: data.usage?.completion_tokens ?? 0,
@@ -81,7 +83,8 @@ var AINamespace = class {
81
83
  maxTokens: request.maxTokens,
82
84
  stream: true,
83
85
  tools: request.tools,
84
- toolChoice: request.toolChoice
86
+ toolChoice: request.toolChoice,
87
+ prompt: request.prompt
85
88
  })
86
89
  });
87
90
  if (!response.ok) {
@@ -225,7 +228,7 @@ var AINamespace = class {
225
228
  throw new Error(`Cencori API error: ${errorData.error || response.statusText}`);
226
229
  }
227
230
  const data = await response.json();
228
- const toolCall = data.choices?.[0]?.message?.tool_calls?.[0];
231
+ const toolCall = data.toolCalls?.[0] ?? data.tool_calls?.[0] ?? data.choices?.[0]?.message?.tool_calls?.[0];
229
232
  if (!toolCall) {
230
233
  throw new Error("Model did not return structured output");
231
234
  }
@@ -288,6 +291,131 @@ var AINamespace = class {
288
291
  provider: data.provider
289
292
  };
290
293
  }
294
+ /**
295
+ * RAG (Retrieval-Augmented Generation) - Chat with automatic memory context
296
+ *
297
+ * Searches your memory namespace for relevant context and includes it
298
+ * in the prompt automatically. Returns the AI response along with sources.
299
+ *
300
+ * @example
301
+ * const response = await cencori.ai.rag({
302
+ * model: 'gpt-4o',
303
+ * messages: [{ role: 'user', content: 'What are our company policies?' }],
304
+ * namespace: 'company-docs',
305
+ * limit: 5, // number of memories to retrieve
306
+ * });
307
+ * console.log(response.message.content);
308
+ * console.log(response.sources); // retrieved context
309
+ */
310
+ async rag(request) {
311
+ const response = await fetch(`${this.config.baseUrl}/api/ai/rag`, {
312
+ method: "POST",
313
+ headers: {
314
+ "CENCORI_API_KEY": this.config.apiKey,
315
+ "Content-Type": "application/json",
316
+ ...this.config.headers
317
+ },
318
+ body: JSON.stringify({
319
+ model: request.model,
320
+ messages: request.messages,
321
+ namespace: request.namespace,
322
+ temperature: request.temperature,
323
+ maxTokens: request.maxTokens,
324
+ limit: request.limit ?? 5,
325
+ threshold: request.threshold ?? 0.5,
326
+ include_sources: request.includeSources ?? true,
327
+ stream: false
328
+ })
329
+ });
330
+ if (!response.ok) {
331
+ const errorData = await response.json().catch(() => ({ error: "Unknown error" }));
332
+ throw new Error(`Cencori API error: ${errorData.error || response.statusText}`);
333
+ }
334
+ const data = await response.json();
335
+ return {
336
+ message: {
337
+ role: "assistant",
338
+ content: data.message.content
339
+ },
340
+ model: data.model,
341
+ provider: data.provider,
342
+ usage: {
343
+ promptTokens: data.usage.prompt_tokens,
344
+ completionTokens: data.usage.completion_tokens,
345
+ totalTokens: data.usage.total_tokens
346
+ },
347
+ sources: data.sources?.map((s) => ({
348
+ content: s.content,
349
+ metadata: s.metadata,
350
+ similarity: s.similarity
351
+ })),
352
+ latencyMs: data.latency_ms
353
+ };
354
+ }
355
+ /**
356
+ * Stream RAG responses with automatic memory context
357
+ *
358
+ * @example
359
+ * for await (const chunk of cencori.ai.ragStream({ model: 'gpt-4o', messages, namespace: 'docs' })) {
360
+ * if (chunk.type === 'sources') console.log('Sources:', chunk.sources);
361
+ * if (chunk.type === 'content') process.stdout.write(chunk.delta);
362
+ * }
363
+ */
364
+ async *ragStream(request) {
365
+ const response = await fetch(`${this.config.baseUrl}/api/ai/rag`, {
366
+ method: "POST",
367
+ headers: {
368
+ "CENCORI_API_KEY": this.config.apiKey,
369
+ "Content-Type": "application/json",
370
+ ...this.config.headers
371
+ },
372
+ body: JSON.stringify({
373
+ model: request.model,
374
+ messages: request.messages,
375
+ namespace: request.namespace,
376
+ temperature: request.temperature,
377
+ maxTokens: request.maxTokens,
378
+ limit: request.limit ?? 5,
379
+ threshold: request.threshold ?? 0.5,
380
+ include_sources: request.includeSources ?? true,
381
+ stream: true
382
+ })
383
+ });
384
+ if (!response.ok) {
385
+ const errorData = await response.json().catch(() => ({ error: "Unknown error" }));
386
+ throw new Error(`Cencori API error: ${errorData.error || response.statusText}`);
387
+ }
388
+ if (!response.body) {
389
+ throw new Error("Response body is null");
390
+ }
391
+ const reader = response.body.getReader();
392
+ const decoder = new TextDecoder();
393
+ let buffer = "";
394
+ try {
395
+ while (true) {
396
+ const { done, value } = await reader.read();
397
+ if (done) break;
398
+ buffer += decoder.decode(value, { stream: true });
399
+ const lines = buffer.split("\n");
400
+ buffer = lines.pop() || "";
401
+ for (const line of lines) {
402
+ if (line.trim() === "") continue;
403
+ if (!line.startsWith("data: ")) continue;
404
+ const data = line.slice(6);
405
+ if (data === "[DONE]") {
406
+ return;
407
+ }
408
+ try {
409
+ const chunk = JSON.parse(data);
410
+ yield chunk;
411
+ } catch {
412
+ }
413
+ }
414
+ }
415
+ } finally {
416
+ reader.releaseLock();
417
+ }
418
+ }
291
419
  };
292
420
 
293
421
  // src/compute/index.ts
@@ -590,6 +718,46 @@ var MemoryClient = class {
590
718
  }
591
719
  };
592
720
 
721
+ // src/telemetry/index.ts
722
+ var TelemetryClient = class {
723
+ constructor(config) {
724
+ this.config = config;
725
+ }
726
+ /**
727
+ * Report a web request to the Cencori dashboard.
728
+ *
729
+ * Fire-and-forget — this method never throws and never blocks
730
+ * your application. If the request fails, the error is silently
731
+ * swallowed so it cannot disrupt your app's critical path.
732
+ *
733
+ * @param payload - Web request details to log
734
+ *
735
+ * @example
736
+ * await cencori.telemetry.reportWebRequest({
737
+ * host: req.headers.get('host') || 'unknown',
738
+ * method: req.method,
739
+ * path: new URL(req.url).pathname,
740
+ * statusCode: response.status,
741
+ * userAgent: req.headers.get('user-agent') || undefined,
742
+ * latencyMs: Date.now() - startTime,
743
+ * });
744
+ */
745
+ async reportWebRequest(payload) {
746
+ try {
747
+ const url = `${this.config.baseUrl}/api/v1/telemetry/web`;
748
+ await fetch(url, {
749
+ method: "POST",
750
+ headers: {
751
+ "Content-Type": "application/json",
752
+ "CENCORI_API_KEY": this.config.apiKey
753
+ },
754
+ body: JSON.stringify(payload)
755
+ });
756
+ } catch {
757
+ }
758
+ }
759
+ };
760
+
593
761
  // src/utils.ts
594
762
  function sleep(ms) {
595
763
  return new Promise((resolve) => setTimeout(resolve, ms));
@@ -684,6 +852,7 @@ var Cencori = class {
684
852
  this.workflow = new WorkflowNamespace();
685
853
  this.storage = new StorageNamespace();
686
854
  this.memory = new MemoryClient(this.config);
855
+ this.telemetry = new TelemetryClient(this.config);
687
856
  }
688
857
  /**
689
858
  * Get the base URL for API calls
@@ -1106,6 +1275,7 @@ export {
1106
1275
  RateLimitError,
1107
1276
  SafetyError,
1108
1277
  StorageNamespace,
1278
+ TelemetryClient,
1109
1279
  WorkflowNamespace,
1110
1280
  cencori,
1111
1281
  createCencori,