cencori 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,140 @@
1
+ # Cencori SDK
2
+
3
+ Official TypeScript SDK for the Cencori AI Gateway and Infrastructure Platform.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install cencori
9
+ # or
10
+ yarn add cencori
11
+ ```
12
+
13
+ ## Quick Start
14
+
15
+ ```typescript
16
+ import { CencoriClient } from 'cencori';
17
+
18
+ const cencori = new CencoriClient({
19
+ apiKey: process.env.CENCORI_API_KEY!
20
+ });
21
+
22
+ const response = await cencori.ai.chat({
23
+ messages: [
24
+ { role: 'user', content: 'Hello, AI!' }
25
+ ]
26
+ });
27
+
28
+ console.log(response.content);
29
+ ```
30
+
31
+ ## Authentication
32
+
33
+ Get your API key from the [Cencori Dashboard](https://cencori.com/dashboard):
34
+
35
+ 1. Create a project
36
+ 2. Navigate to API Keys
37
+ 3. Generate a new key
38
+ 4. Copy and store it securely
39
+
40
+ ## API Reference
41
+
42
+ ### CencoriClient
43
+
44
+ Initialize the SDK client.
45
+
46
+ ```typescript
47
+ const cencori = new CencoriClient({
48
+ apiKey: 'your_api_key_here',
49
+ baseUrl: 'https://cencori.com' // Optional, defaults to production
50
+ });
51
+ ```
52
+
53
+ ### AI Module
54
+
55
+ #### `ai.chat(params)`
56
+
57
+ Send a chat message to the AI.
58
+
59
+ **Parameters:**
60
+ - `messages`: Array of message objects with `role` ('user' | 'assistant') and `content`
61
+ - `model`: Optional AI model (defaults to 'gemini-1.5-pro')
62
+ - `temperature`: Optional temperature (0-1)
63
+ - `maxOutputTokens`: Optional max tokens for response
64
+
65
+ **Example:**
66
+
67
+ ```typescript
68
+ const response = await cencori.ai.chat({
69
+ messages: [
70
+ { role: 'user', content: 'Explain quantum computing' }
71
+ ],
72
+ temperature: 0.7
73
+ });
74
+
75
+ console.log(response.content);
76
+ console.log(response.usage); // Token usage stats
77
+ ```
78
+
79
+ ## Error Handling
80
+
81
+ The SDK includes custom error classes for common scenarios:
82
+
83
+ ```typescript
84
+ import {
85
+ CencoriClient,
86
+ AuthenticationError,
87
+ RateLimitError,
88
+ SafetyError
89
+ } from 'cencori';
90
+
91
+ try {
92
+ const response = await cencori.ai.chat({ messages: [...] });
93
+ } catch (error) {
94
+ if (error instanceof AuthenticationError) {
95
+ console.error('Invalid API key');
96
+ } else if (error instanceof RateLimitError) {
97
+ console.error('Too many requests, please slow down');
98
+ } else if (error instanceof SafetyError) {
99
+ console.error('Content blocked:', error.reasons);
100
+ }
101
+ }
102
+ ```
103
+
104
+ ## TypeScript Support
105
+
106
+ The SDK is written in TypeScript and includes full type definitions.
107
+
108
+ ```typescript
109
+ import type { ChatParams, ChatResponse, Message } from 'cencori';
110
+ ```
111
+
112
+ ## Features
113
+
114
+ - ✨ Full TypeScript support with type definitions
115
+ - 🔒 Built-in authentication
116
+ - 🔄 Automatic retry logic with exponential backoff
117
+ - 🚨 Custom error classes
118
+ - 🛡️ Content safety filtering
119
+ - ⚡ Rate limiting protection
120
+
121
+ ## Local Development
122
+
123
+ For local development or testing:
124
+
125
+ ```typescript
126
+ const cencori = new CencoriClient({
127
+ apiKey: 'cen_test_...',
128
+ baseUrl: 'http://localhost:3000'
129
+ });
130
+ ```
131
+
132
+ ## Support
133
+
134
+ - **Documentation**: [docs.cencori.com](https://docs.cencori.com)
135
+ - **Dashboard**: [cencori.com/dashboard](https://cencori.com/dashboard)
136
+ - **GitHub**: [github.com/bolaabanjo/cencori](https://github.com/bolaabanjo/cencori)
137
+
138
+ ## License
139
+
140
+ MIT © FohnAI
@@ -0,0 +1,61 @@
1
+ interface CencoriConfig {
2
+ apiKey: string;
3
+ baseUrl?: string;
4
+ }
5
+ interface RequestOptions {
6
+ method: 'GET' | 'POST' | 'PUT' | 'DELETE';
7
+ body?: string;
8
+ headers?: Record<string, string>;
9
+ }
10
+
11
+ interface ChatParams {
12
+ messages: Message[];
13
+ model?: string;
14
+ temperature?: number;
15
+ maxOutputTokens?: number;
16
+ }
17
+ interface Message {
18
+ role: 'user' | 'assistant';
19
+ content: string;
20
+ }
21
+ interface ChatResponse {
22
+ role: string;
23
+ content: string;
24
+ usage: {
25
+ prompt_tokens: number;
26
+ completion_tokens: number;
27
+ total_tokens: number;
28
+ };
29
+ }
30
+
31
+ declare class AIModule {
32
+ private client;
33
+ constructor(client: CencoriClient);
34
+ chat(params: ChatParams): Promise<ChatResponse>;
35
+ }
36
+
37
+ declare class CencoriClient {
38
+ private apiKey;
39
+ private baseUrl;
40
+ ai: AIModule;
41
+ constructor(config: CencoriConfig);
42
+ request<T>(endpoint: string, options: RequestOptions): Promise<T>;
43
+ }
44
+
45
+ declare class CencoriError extends Error {
46
+ statusCode?: number | undefined;
47
+ code?: string | undefined;
48
+ constructor(message: string, statusCode?: number | undefined, code?: string | undefined);
49
+ }
50
+ declare class AuthenticationError extends CencoriError {
51
+ constructor(message?: string);
52
+ }
53
+ declare class RateLimitError extends CencoriError {
54
+ constructor(message?: string);
55
+ }
56
+ declare class SafetyError extends CencoriError {
57
+ reasons?: string[] | undefined;
58
+ constructor(message?: string, reasons?: string[] | undefined);
59
+ }
60
+
61
+ export { AuthenticationError, CencoriClient, type CencoriConfig, CencoriError, type ChatParams, type ChatResponse, type Message, RateLimitError, type RequestOptions, SafetyError };
@@ -0,0 +1,61 @@
1
+ interface CencoriConfig {
2
+ apiKey: string;
3
+ baseUrl?: string;
4
+ }
5
+ interface RequestOptions {
6
+ method: 'GET' | 'POST' | 'PUT' | 'DELETE';
7
+ body?: string;
8
+ headers?: Record<string, string>;
9
+ }
10
+
11
+ interface ChatParams {
12
+ messages: Message[];
13
+ model?: string;
14
+ temperature?: number;
15
+ maxOutputTokens?: number;
16
+ }
17
+ interface Message {
18
+ role: 'user' | 'assistant';
19
+ content: string;
20
+ }
21
+ interface ChatResponse {
22
+ role: string;
23
+ content: string;
24
+ usage: {
25
+ prompt_tokens: number;
26
+ completion_tokens: number;
27
+ total_tokens: number;
28
+ };
29
+ }
30
+
31
+ declare class AIModule {
32
+ private client;
33
+ constructor(client: CencoriClient);
34
+ chat(params: ChatParams): Promise<ChatResponse>;
35
+ }
36
+
37
+ declare class CencoriClient {
38
+ private apiKey;
39
+ private baseUrl;
40
+ ai: AIModule;
41
+ constructor(config: CencoriConfig);
42
+ request<T>(endpoint: string, options: RequestOptions): Promise<T>;
43
+ }
44
+
45
+ declare class CencoriError extends Error {
46
+ statusCode?: number | undefined;
47
+ code?: string | undefined;
48
+ constructor(message: string, statusCode?: number | undefined, code?: string | undefined);
49
+ }
50
+ declare class AuthenticationError extends CencoriError {
51
+ constructor(message?: string);
52
+ }
53
+ declare class RateLimitError extends CencoriError {
54
+ constructor(message?: string);
55
+ }
56
+ declare class SafetyError extends CencoriError {
57
+ reasons?: string[] | undefined;
58
+ constructor(message?: string, reasons?: string[] | undefined);
59
+ }
60
+
61
+ export { AuthenticationError, CencoriClient, type CencoriConfig, CencoriError, type ChatParams, type ChatResponse, type Message, RateLimitError, type RequestOptions, SafetyError };
package/dist/index.js ADDED
@@ -0,0 +1,164 @@
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
+ CencoriClient: () => CencoriClient,
25
+ CencoriError: () => CencoriError,
26
+ RateLimitError: () => RateLimitError,
27
+ SafetyError: () => SafetyError
28
+ });
29
+ module.exports = __toCommonJS(index_exports);
30
+
31
+ // src/modules/ai.ts
32
+ var AIModule = class {
33
+ constructor(client) {
34
+ this.client = client;
35
+ }
36
+ async chat(params) {
37
+ return this.client.request("/api/ai/chat", {
38
+ method: "POST",
39
+ body: JSON.stringify(params)
40
+ });
41
+ }
42
+ };
43
+
44
+ // src/utils.ts
45
+ function sleep(ms) {
46
+ return new Promise((resolve) => setTimeout(resolve, ms));
47
+ }
48
+ async function fetchWithRetry(url, options, maxRetries = 3) {
49
+ let lastError = null;
50
+ for (let attempt = 0; attempt < maxRetries; attempt++) {
51
+ try {
52
+ const response = await fetch(url, options);
53
+ if (response.ok || response.status >= 400 && response.status < 500) {
54
+ return response;
55
+ }
56
+ lastError = new Error(`HTTP ${response.status}: ${response.statusText}`);
57
+ if (attempt === maxRetries - 1) {
58
+ return response;
59
+ }
60
+ await sleep(Math.pow(2, attempt) * 1e3);
61
+ } catch (error) {
62
+ lastError = error instanceof Error ? error : new Error(String(error));
63
+ if (attempt === maxRetries - 1) {
64
+ throw lastError;
65
+ }
66
+ await sleep(Math.pow(2, attempt) * 1e3);
67
+ }
68
+ }
69
+ throw lastError || new Error("Max retries reached");
70
+ }
71
+
72
+ // src/errors.ts
73
+ var CencoriError = class _CencoriError extends Error {
74
+ constructor(message, statusCode, code) {
75
+ super(message);
76
+ this.statusCode = statusCode;
77
+ this.code = code;
78
+ this.name = "CencoriError";
79
+ Object.setPrototypeOf(this, _CencoriError.prototype);
80
+ }
81
+ };
82
+ var AuthenticationError = class _AuthenticationError extends CencoriError {
83
+ constructor(message = "Invalid API key") {
84
+ super(message, 401, "INVALID_API_KEY");
85
+ this.name = "AuthenticationError";
86
+ Object.setPrototypeOf(this, _AuthenticationError.prototype);
87
+ }
88
+ };
89
+ var RateLimitError = class _RateLimitError extends CencoriError {
90
+ constructor(message = "Rate limit exceeded") {
91
+ super(message, 429, "RATE_LIMIT_EXCEEDED");
92
+ this.name = "RateLimitError";
93
+ Object.setPrototypeOf(this, _RateLimitError.prototype);
94
+ }
95
+ };
96
+ var SafetyError = class _SafetyError extends CencoriError {
97
+ constructor(message = "Content safety violation", reasons) {
98
+ super(message, 400, "SAFETY_VIOLATION");
99
+ this.reasons = reasons;
100
+ this.name = "SafetyError";
101
+ Object.setPrototypeOf(this, _SafetyError.prototype);
102
+ }
103
+ };
104
+
105
+ // src/client.ts
106
+ var CencoriClient = class {
107
+ constructor(config) {
108
+ if (!config.apiKey) {
109
+ throw new Error("API key is required");
110
+ }
111
+ this.apiKey = config.apiKey;
112
+ this.baseUrl = config.baseUrl || "https://cencori.com";
113
+ this.ai = new AIModule(this);
114
+ }
115
+ async request(endpoint, options) {
116
+ const url = `${this.baseUrl}${endpoint}`;
117
+ const headers = {
118
+ "Content-Type": "application/json",
119
+ "CENCORI_API_KEY": this.apiKey,
120
+ ...options.headers
121
+ };
122
+ try {
123
+ const response = await fetchWithRetry(url, {
124
+ method: options.method,
125
+ headers,
126
+ body: options.body
127
+ });
128
+ const data = await response.json();
129
+ if (!response.ok) {
130
+ const errorData = data;
131
+ if (response.status === 401) {
132
+ throw new AuthenticationError(errorData.error || "Invalid API key");
133
+ }
134
+ if (response.status === 429) {
135
+ throw new RateLimitError(errorData.error || "Rate limit exceeded");
136
+ }
137
+ if (response.status === 400 && errorData.reasons) {
138
+ throw new SafetyError(errorData.error, errorData.reasons);
139
+ }
140
+ throw new CencoriError(
141
+ errorData.error || "Request failed",
142
+ response.status
143
+ );
144
+ }
145
+ return data;
146
+ } catch (error) {
147
+ if (error instanceof CencoriError) {
148
+ throw error;
149
+ }
150
+ throw new CencoriError(
151
+ error instanceof Error ? error.message : "Unknown error occurred"
152
+ );
153
+ }
154
+ }
155
+ };
156
+ // Annotate the CommonJS export names for ESM import in node:
157
+ 0 && (module.exports = {
158
+ AuthenticationError,
159
+ CencoriClient,
160
+ CencoriError,
161
+ RateLimitError,
162
+ SafetyError
163
+ });
164
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/modules/ai.ts","../src/utils.ts","../src/errors.ts","../src/client.ts"],"sourcesContent":["export { CencoriClient } from './client';\r\nexport * from './types';\r\nexport * from './errors';\r\n","import type { ChatParams, ChatResponse } from '../types/ai';\r\nimport type { CencoriClient } from '../client';\r\n\r\nexport class AIModule {\r\n constructor(private client: CencoriClient) { }\r\n\r\n async chat(params: ChatParams): Promise<ChatResponse> {\r\n return this.client.request<ChatResponse>('/api/ai/chat', {\r\n method: 'POST',\r\n body: JSON.stringify(params)\r\n });\r\n }\r\n}\r\n","function sleep(ms: number): Promise<void> {\r\n return new Promise(resolve => setTimeout(resolve, ms));\r\n}\r\n\r\nexport async function fetchWithRetry(\r\n url: string,\r\n options: RequestInit,\r\n maxRetries = 3\r\n): Promise<Response> {\r\n let lastError: Error | null = null;\r\n\r\n for (let attempt = 0; attempt < maxRetries; attempt++) {\r\n try {\r\n const response = await fetch(url, options);\r\n\r\n // Return immediately if request succeeded or if it's a client error (4xx)\r\n if (response.ok || (response.status >= 400 && response.status < 500)) {\r\n return response;\r\n }\r\n\r\n // Retry on 5xx errors\r\n lastError = new Error(`HTTP ${response.status}: ${response.statusText}`);\r\n\r\n // Don't retry on last attempt\r\n if (attempt === maxRetries - 1) {\r\n return response;\r\n }\r\n\r\n // Exponential backoff: 1s, 2s, 4s\r\n await sleep(Math.pow(2, attempt) * 1000);\r\n } catch (error) {\r\n lastError = error instanceof Error ? error : new Error(String(error));\r\n\r\n // Don't retry on last attempt\r\n if (attempt === maxRetries - 1) {\r\n throw lastError;\r\n }\r\n\r\n // Exponential backoff\r\n await sleep(Math.pow(2, attempt) * 1000);\r\n }\r\n }\r\n\r\n throw lastError || new Error('Max retries reached');\r\n}\r\n","export class CencoriError extends Error {\r\n constructor(\r\n message: string,\r\n public statusCode?: number,\r\n public code?: string\r\n ) {\r\n super(message);\r\n this.name = 'CencoriError';\r\n Object.setPrototypeOf(this, CencoriError.prototype);\r\n }\r\n}\r\n\r\nexport class AuthenticationError extends CencoriError {\r\n constructor(message = 'Invalid API key') {\r\n super(message, 401, 'INVALID_API_KEY');\r\n this.name = 'AuthenticationError';\r\n Object.setPrototypeOf(this, AuthenticationError.prototype);\r\n }\r\n}\r\n\r\nexport class RateLimitError extends CencoriError {\r\n constructor(message = 'Rate limit exceeded') {\r\n super(message, 429, 'RATE_LIMIT_EXCEEDED');\r\n this.name = 'RateLimitError';\r\n Object.setPrototypeOf(this, RateLimitError.prototype);\r\n }\r\n}\r\n\r\nexport class SafetyError extends CencoriError {\r\n constructor(message = 'Content safety violation', public reasons?: string[]) {\r\n super(message, 400, 'SAFETY_VIOLATION');\r\n this.name = 'SafetyError';\r\n Object.setPrototypeOf(this, SafetyError.prototype);\r\n }\r\n}\r\n","import type { CencoriConfig, RequestOptions } from './types/common';\nimport { AIModule } from './modules/ai';\nimport { fetchWithRetry } from './utils';\nimport {\n CencoriError,\n AuthenticationError,\n RateLimitError,\n SafetyError\n} from './errors';\n\ninterface ErrorResponse {\n error?: string;\n reasons?: string[];\n}\n\nexport class CencoriClient {\n private apiKey: string;\n private baseUrl: string;\n\n public ai: AIModule;\n\n constructor(config: CencoriConfig) {\n if (!config.apiKey) {\n throw new Error('API key is required');\n }\n\n this.apiKey = config.apiKey;\n this.baseUrl = config.baseUrl || 'https://cencori.com';\n\n this.ai = new AIModule(this);\n }\n\n async request<T>(endpoint: string, options: RequestOptions): Promise<T> {\n const url = `${this.baseUrl}${endpoint}`;\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'CENCORI_API_KEY': this.apiKey,\n ...options.headers\n };\n\n try {\n const response = await fetchWithRetry(url, {\n method: options.method,\n headers,\n body: options.body\n });\n\n const data: unknown = await response.json();\n\n // Handle API errors\n if (!response.ok) {\n const errorData = data as ErrorResponse;\n \n if (response.status === 401) {\n throw new AuthenticationError(errorData.error || 'Invalid API key');\n }\n if (response.status === 429) {\n throw new RateLimitError(errorData.error || 'Rate limit exceeded');\n }\n if (response.status === 400 && errorData.reasons) {\n throw new SafetyError(errorData.error, errorData.reasons);\n }\n throw new CencoriError(\n errorData.error || 'Request failed',\n response.status\n );\n }\n\n return data as T;\n } catch (error) {\n // Re-throw custom errors\n if (error instanceof CencoriError) {\n throw error;\n }\n\n // Wrap unknown errors\n throw new CencoriError(\n error instanceof Error ? error.message : 'Unknown error occurred'\n );\n }\n }\n}\n"],"mappings":"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","names":[]}
package/dist/index.mjs ADDED
@@ -0,0 +1,133 @@
1
+ // src/modules/ai.ts
2
+ var AIModule = class {
3
+ constructor(client) {
4
+ this.client = client;
5
+ }
6
+ async chat(params) {
7
+ return this.client.request("/api/ai/chat", {
8
+ method: "POST",
9
+ body: JSON.stringify(params)
10
+ });
11
+ }
12
+ };
13
+
14
+ // src/utils.ts
15
+ function sleep(ms) {
16
+ return new Promise((resolve) => setTimeout(resolve, ms));
17
+ }
18
+ async function fetchWithRetry(url, options, maxRetries = 3) {
19
+ let lastError = null;
20
+ for (let attempt = 0; attempt < maxRetries; attempt++) {
21
+ try {
22
+ const response = await fetch(url, options);
23
+ if (response.ok || response.status >= 400 && response.status < 500) {
24
+ return response;
25
+ }
26
+ lastError = new Error(`HTTP ${response.status}: ${response.statusText}`);
27
+ if (attempt === maxRetries - 1) {
28
+ return response;
29
+ }
30
+ await sleep(Math.pow(2, attempt) * 1e3);
31
+ } catch (error) {
32
+ lastError = error instanceof Error ? error : new Error(String(error));
33
+ if (attempt === maxRetries - 1) {
34
+ throw lastError;
35
+ }
36
+ await sleep(Math.pow(2, attempt) * 1e3);
37
+ }
38
+ }
39
+ throw lastError || new Error("Max retries reached");
40
+ }
41
+
42
+ // src/errors.ts
43
+ var CencoriError = class _CencoriError extends Error {
44
+ constructor(message, statusCode, code) {
45
+ super(message);
46
+ this.statusCode = statusCode;
47
+ this.code = code;
48
+ this.name = "CencoriError";
49
+ Object.setPrototypeOf(this, _CencoriError.prototype);
50
+ }
51
+ };
52
+ var AuthenticationError = class _AuthenticationError extends CencoriError {
53
+ constructor(message = "Invalid API key") {
54
+ super(message, 401, "INVALID_API_KEY");
55
+ this.name = "AuthenticationError";
56
+ Object.setPrototypeOf(this, _AuthenticationError.prototype);
57
+ }
58
+ };
59
+ var RateLimitError = class _RateLimitError extends CencoriError {
60
+ constructor(message = "Rate limit exceeded") {
61
+ super(message, 429, "RATE_LIMIT_EXCEEDED");
62
+ this.name = "RateLimitError";
63
+ Object.setPrototypeOf(this, _RateLimitError.prototype);
64
+ }
65
+ };
66
+ var SafetyError = class _SafetyError extends CencoriError {
67
+ constructor(message = "Content safety violation", reasons) {
68
+ super(message, 400, "SAFETY_VIOLATION");
69
+ this.reasons = reasons;
70
+ this.name = "SafetyError";
71
+ Object.setPrototypeOf(this, _SafetyError.prototype);
72
+ }
73
+ };
74
+
75
+ // src/client.ts
76
+ var CencoriClient = class {
77
+ constructor(config) {
78
+ if (!config.apiKey) {
79
+ throw new Error("API key is required");
80
+ }
81
+ this.apiKey = config.apiKey;
82
+ this.baseUrl = config.baseUrl || "https://cencori.com";
83
+ this.ai = new AIModule(this);
84
+ }
85
+ async request(endpoint, options) {
86
+ const url = `${this.baseUrl}${endpoint}`;
87
+ const headers = {
88
+ "Content-Type": "application/json",
89
+ "CENCORI_API_KEY": this.apiKey,
90
+ ...options.headers
91
+ };
92
+ try {
93
+ const response = await fetchWithRetry(url, {
94
+ method: options.method,
95
+ headers,
96
+ body: options.body
97
+ });
98
+ const data = await response.json();
99
+ if (!response.ok) {
100
+ const errorData = data;
101
+ if (response.status === 401) {
102
+ throw new AuthenticationError(errorData.error || "Invalid API key");
103
+ }
104
+ if (response.status === 429) {
105
+ throw new RateLimitError(errorData.error || "Rate limit exceeded");
106
+ }
107
+ if (response.status === 400 && errorData.reasons) {
108
+ throw new SafetyError(errorData.error, errorData.reasons);
109
+ }
110
+ throw new CencoriError(
111
+ errorData.error || "Request failed",
112
+ response.status
113
+ );
114
+ }
115
+ return data;
116
+ } catch (error) {
117
+ if (error instanceof CencoriError) {
118
+ throw error;
119
+ }
120
+ throw new CencoriError(
121
+ error instanceof Error ? error.message : "Unknown error occurred"
122
+ );
123
+ }
124
+ }
125
+ };
126
+ export {
127
+ AuthenticationError,
128
+ CencoriClient,
129
+ CencoriError,
130
+ RateLimitError,
131
+ SafetyError
132
+ };
133
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/modules/ai.ts","../src/utils.ts","../src/errors.ts","../src/client.ts"],"sourcesContent":["import type { ChatParams, ChatResponse } from '../types/ai';\r\nimport type { CencoriClient } from '../client';\r\n\r\nexport class AIModule {\r\n constructor(private client: CencoriClient) { }\r\n\r\n async chat(params: ChatParams): Promise<ChatResponse> {\r\n return this.client.request<ChatResponse>('/api/ai/chat', {\r\n method: 'POST',\r\n body: JSON.stringify(params)\r\n });\r\n }\r\n}\r\n","function sleep(ms: number): Promise<void> {\r\n return new Promise(resolve => setTimeout(resolve, ms));\r\n}\r\n\r\nexport async function fetchWithRetry(\r\n url: string,\r\n options: RequestInit,\r\n maxRetries = 3\r\n): Promise<Response> {\r\n let lastError: Error | null = null;\r\n\r\n for (let attempt = 0; attempt < maxRetries; attempt++) {\r\n try {\r\n const response = await fetch(url, options);\r\n\r\n // Return immediately if request succeeded or if it's a client error (4xx)\r\n if (response.ok || (response.status >= 400 && response.status < 500)) {\r\n return response;\r\n }\r\n\r\n // Retry on 5xx errors\r\n lastError = new Error(`HTTP ${response.status}: ${response.statusText}`);\r\n\r\n // Don't retry on last attempt\r\n if (attempt === maxRetries - 1) {\r\n return response;\r\n }\r\n\r\n // Exponential backoff: 1s, 2s, 4s\r\n await sleep(Math.pow(2, attempt) * 1000);\r\n } catch (error) {\r\n lastError = error instanceof Error ? error : new Error(String(error));\r\n\r\n // Don't retry on last attempt\r\n if (attempt === maxRetries - 1) {\r\n throw lastError;\r\n }\r\n\r\n // Exponential backoff\r\n await sleep(Math.pow(2, attempt) * 1000);\r\n }\r\n }\r\n\r\n throw lastError || new Error('Max retries reached');\r\n}\r\n","export class CencoriError extends Error {\r\n constructor(\r\n message: string,\r\n public statusCode?: number,\r\n public code?: string\r\n ) {\r\n super(message);\r\n this.name = 'CencoriError';\r\n Object.setPrototypeOf(this, CencoriError.prototype);\r\n }\r\n}\r\n\r\nexport class AuthenticationError extends CencoriError {\r\n constructor(message = 'Invalid API key') {\r\n super(message, 401, 'INVALID_API_KEY');\r\n this.name = 'AuthenticationError';\r\n Object.setPrototypeOf(this, AuthenticationError.prototype);\r\n }\r\n}\r\n\r\nexport class RateLimitError extends CencoriError {\r\n constructor(message = 'Rate limit exceeded') {\r\n super(message, 429, 'RATE_LIMIT_EXCEEDED');\r\n this.name = 'RateLimitError';\r\n Object.setPrototypeOf(this, RateLimitError.prototype);\r\n }\r\n}\r\n\r\nexport class SafetyError extends CencoriError {\r\n constructor(message = 'Content safety violation', public reasons?: string[]) {\r\n super(message, 400, 'SAFETY_VIOLATION');\r\n this.name = 'SafetyError';\r\n Object.setPrototypeOf(this, SafetyError.prototype);\r\n }\r\n}\r\n","import type { CencoriConfig, RequestOptions } from './types/common';\nimport { AIModule } from './modules/ai';\nimport { fetchWithRetry } from './utils';\nimport {\n CencoriError,\n AuthenticationError,\n RateLimitError,\n SafetyError\n} from './errors';\n\ninterface ErrorResponse {\n error?: string;\n reasons?: string[];\n}\n\nexport class CencoriClient {\n private apiKey: string;\n private baseUrl: string;\n\n public ai: AIModule;\n\n constructor(config: CencoriConfig) {\n if (!config.apiKey) {\n throw new Error('API key is required');\n }\n\n this.apiKey = config.apiKey;\n this.baseUrl = config.baseUrl || 'https://cencori.com';\n\n this.ai = new AIModule(this);\n }\n\n async request<T>(endpoint: string, options: RequestOptions): Promise<T> {\n const url = `${this.baseUrl}${endpoint}`;\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'CENCORI_API_KEY': this.apiKey,\n ...options.headers\n };\n\n try {\n const response = await fetchWithRetry(url, {\n method: options.method,\n headers,\n body: options.body\n });\n\n const data: unknown = await response.json();\n\n // Handle API errors\n if (!response.ok) {\n const errorData = data as ErrorResponse;\n \n if (response.status === 401) {\n throw new AuthenticationError(errorData.error || 'Invalid API key');\n }\n if (response.status === 429) {\n throw new RateLimitError(errorData.error || 'Rate limit exceeded');\n }\n if (response.status === 400 && errorData.reasons) {\n throw new SafetyError(errorData.error, errorData.reasons);\n }\n throw new CencoriError(\n errorData.error || 'Request failed',\n response.status\n );\n }\n\n return data as T;\n } catch (error) {\n // Re-throw custom errors\n if (error instanceof CencoriError) {\n throw error;\n }\n\n // Wrap unknown errors\n throw new CencoriError(\n error instanceof Error ? error.message : 'Unknown error occurred'\n );\n }\n }\n}\n"],"mappings":"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","names":[]}
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "cencori",
3
+ "version": "0.1.0",
4
+ "description": "Official TypeScript SDK for Cencori AI Gateway and Infrastructure Platform",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.ts",
8
+ "files": [
9
+ "dist"
10
+ ],
11
+ "keywords": [
12
+ "ai",
13
+ "gateway",
14
+ "cencori",
15
+ "sdk",
16
+ "typescript"
17
+ ],
18
+ "author": "FohnAI",
19
+ "license": "MIT",
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "https://github.com/bolaabanjo/cencori"
23
+ },
24
+ "scripts": {
25
+ "build": "tsup",
26
+ "dev": "tsup --watch",
27
+ "prepublishOnly": "npm run build"
28
+ },
29
+ "devDependencies": {
30
+ "tsup": "^8.0.0",
31
+ "typescript": "^5.3.0"
32
+ }
33
+ }