cencori 0.1.2 → 0.3.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 +1 -1
- package/dist/index.d.mts +26 -8
- package/dist/index.d.ts +26 -8
- package/dist/index.js +66 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +65 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +13 -4
package/README.md
CHANGED
|
@@ -58,7 +58,7 @@ Send a chat message to the AI.
|
|
|
58
58
|
|
|
59
59
|
**Parameters:**
|
|
60
60
|
- `messages`: Array of message objects with `role` ('user' | 'assistant') and `content`
|
|
61
|
-
- `model`: Optional AI model (defaults to 'gemini-1.5-
|
|
61
|
+
- `model`: Optional AI model (defaults to 'gemini-1.5-flash')
|
|
62
62
|
- `temperature`: Optional temperature (0-1)
|
|
63
63
|
- `maxOutputTokens`: Optional max tokens for response
|
|
64
64
|
|
package/dist/index.d.mts
CHANGED
|
@@ -8,30 +8,46 @@ interface RequestOptions {
|
|
|
8
8
|
headers?: Record<string, string>;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
+
interface Message {
|
|
12
|
+
role: 'system' | 'user' | 'assistant';
|
|
13
|
+
content: string;
|
|
14
|
+
}
|
|
11
15
|
interface ChatParams {
|
|
12
16
|
messages: Message[];
|
|
13
17
|
model?: string;
|
|
14
18
|
temperature?: number;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
role: 'user' | 'assistant';
|
|
19
|
-
content: string;
|
|
19
|
+
maxTokens?: number;
|
|
20
|
+
stream?: boolean;
|
|
21
|
+
userId?: string;
|
|
20
22
|
}
|
|
21
23
|
interface ChatResponse {
|
|
22
|
-
role: string;
|
|
23
24
|
content: string;
|
|
25
|
+
model: string;
|
|
26
|
+
provider: string;
|
|
24
27
|
usage: {
|
|
25
28
|
prompt_tokens: number;
|
|
26
29
|
completion_tokens: number;
|
|
27
30
|
total_tokens: number;
|
|
28
31
|
};
|
|
32
|
+
cost_usd: number;
|
|
33
|
+
finish_reason: 'stop' | 'length' | 'content_filter' | 'error';
|
|
34
|
+
}
|
|
35
|
+
interface StreamChunk {
|
|
36
|
+
delta: string;
|
|
37
|
+
finish_reason?: 'stop' | 'length' | 'content_filter' | 'error';
|
|
29
38
|
}
|
|
30
|
-
|
|
31
39
|
declare class AIModule {
|
|
32
40
|
private client;
|
|
33
41
|
constructor(client: CencoriClient);
|
|
42
|
+
/**
|
|
43
|
+
* Send a chat completion request (non-streaming)
|
|
44
|
+
*/
|
|
34
45
|
chat(params: ChatParams): Promise<ChatResponse>;
|
|
46
|
+
/**
|
|
47
|
+
* Send a chat completion request with streaming
|
|
48
|
+
* Returns an async generator that yields chunks as they arrive
|
|
49
|
+
*/
|
|
50
|
+
chatStream(params: ChatParams): AsyncGenerator<StreamChunk, void, unknown>;
|
|
35
51
|
}
|
|
36
52
|
|
|
37
53
|
declare class CencoriClient {
|
|
@@ -39,6 +55,8 @@ declare class CencoriClient {
|
|
|
39
55
|
private baseUrl;
|
|
40
56
|
ai: AIModule;
|
|
41
57
|
constructor(config: CencoriConfig);
|
|
58
|
+
getBaseUrl(): string;
|
|
59
|
+
getApiKey(): string;
|
|
42
60
|
request<T>(endpoint: string, options: RequestOptions): Promise<T>;
|
|
43
61
|
}
|
|
44
62
|
|
|
@@ -58,4 +76,4 @@ declare class SafetyError extends CencoriError {
|
|
|
58
76
|
constructor(message?: string, reasons?: string[] | undefined);
|
|
59
77
|
}
|
|
60
78
|
|
|
61
|
-
export { AuthenticationError, CencoriClient, type CencoriConfig, CencoriError, type ChatParams, type ChatResponse, type Message, RateLimitError, type RequestOptions, SafetyError };
|
|
79
|
+
export { AIModule, AuthenticationError, CencoriClient, type CencoriConfig, CencoriError, type ChatParams, type ChatResponse, type Message, RateLimitError, type RequestOptions, SafetyError, type StreamChunk };
|
package/dist/index.d.ts
CHANGED
|
@@ -8,30 +8,46 @@ interface RequestOptions {
|
|
|
8
8
|
headers?: Record<string, string>;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
+
interface Message {
|
|
12
|
+
role: 'system' | 'user' | 'assistant';
|
|
13
|
+
content: string;
|
|
14
|
+
}
|
|
11
15
|
interface ChatParams {
|
|
12
16
|
messages: Message[];
|
|
13
17
|
model?: string;
|
|
14
18
|
temperature?: number;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
role: 'user' | 'assistant';
|
|
19
|
-
content: string;
|
|
19
|
+
maxTokens?: number;
|
|
20
|
+
stream?: boolean;
|
|
21
|
+
userId?: string;
|
|
20
22
|
}
|
|
21
23
|
interface ChatResponse {
|
|
22
|
-
role: string;
|
|
23
24
|
content: string;
|
|
25
|
+
model: string;
|
|
26
|
+
provider: string;
|
|
24
27
|
usage: {
|
|
25
28
|
prompt_tokens: number;
|
|
26
29
|
completion_tokens: number;
|
|
27
30
|
total_tokens: number;
|
|
28
31
|
};
|
|
32
|
+
cost_usd: number;
|
|
33
|
+
finish_reason: 'stop' | 'length' | 'content_filter' | 'error';
|
|
34
|
+
}
|
|
35
|
+
interface StreamChunk {
|
|
36
|
+
delta: string;
|
|
37
|
+
finish_reason?: 'stop' | 'length' | 'content_filter' | 'error';
|
|
29
38
|
}
|
|
30
|
-
|
|
31
39
|
declare class AIModule {
|
|
32
40
|
private client;
|
|
33
41
|
constructor(client: CencoriClient);
|
|
42
|
+
/**
|
|
43
|
+
* Send a chat completion request (non-streaming)
|
|
44
|
+
*/
|
|
34
45
|
chat(params: ChatParams): Promise<ChatResponse>;
|
|
46
|
+
/**
|
|
47
|
+
* Send a chat completion request with streaming
|
|
48
|
+
* Returns an async generator that yields chunks as they arrive
|
|
49
|
+
*/
|
|
50
|
+
chatStream(params: ChatParams): AsyncGenerator<StreamChunk, void, unknown>;
|
|
35
51
|
}
|
|
36
52
|
|
|
37
53
|
declare class CencoriClient {
|
|
@@ -39,6 +55,8 @@ declare class CencoriClient {
|
|
|
39
55
|
private baseUrl;
|
|
40
56
|
ai: AIModule;
|
|
41
57
|
constructor(config: CencoriConfig);
|
|
58
|
+
getBaseUrl(): string;
|
|
59
|
+
getApiKey(): string;
|
|
42
60
|
request<T>(endpoint: string, options: RequestOptions): Promise<T>;
|
|
43
61
|
}
|
|
44
62
|
|
|
@@ -58,4 +76,4 @@ declare class SafetyError extends CencoriError {
|
|
|
58
76
|
constructor(message?: string, reasons?: string[] | undefined);
|
|
59
77
|
}
|
|
60
78
|
|
|
61
|
-
export { AuthenticationError, CencoriClient, type CencoriConfig, CencoriError, type ChatParams, type ChatResponse, type Message, RateLimitError, type RequestOptions, SafetyError };
|
|
79
|
+
export { AIModule, AuthenticationError, CencoriClient, type CencoriConfig, CencoriError, type ChatParams, type ChatResponse, type Message, RateLimitError, type RequestOptions, SafetyError, type StreamChunk };
|
package/dist/index.js
CHANGED
|
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
+
AIModule: () => AIModule,
|
|
23
24
|
AuthenticationError: () => AuthenticationError,
|
|
24
25
|
CencoriClient: () => CencoriClient,
|
|
25
26
|
CencoriError: () => CencoriError,
|
|
@@ -33,11 +34,66 @@ var AIModule = class {
|
|
|
33
34
|
constructor(client) {
|
|
34
35
|
this.client = client;
|
|
35
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* Send a chat completion request (non-streaming)
|
|
39
|
+
*/
|
|
36
40
|
async chat(params) {
|
|
37
|
-
|
|
41
|
+
const response = await this.client.request("/api/ai/chat", {
|
|
38
42
|
method: "POST",
|
|
39
|
-
body: JSON.stringify(params)
|
|
43
|
+
body: JSON.stringify({ ...params, stream: false })
|
|
40
44
|
});
|
|
45
|
+
return response;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Send a chat completion request with streaming
|
|
49
|
+
* Returns an async generator that yields chunks as they arrive
|
|
50
|
+
*/
|
|
51
|
+
async *chatStream(params) {
|
|
52
|
+
const url = `${this.client.getBaseUrl()}/api/ai/chat`;
|
|
53
|
+
const headers = {
|
|
54
|
+
"Content-Type": "application/json",
|
|
55
|
+
"CENCORI_API_KEY": this.client.getApiKey()
|
|
56
|
+
};
|
|
57
|
+
const response = await fetch(url, {
|
|
58
|
+
method: "POST",
|
|
59
|
+
headers,
|
|
60
|
+
body: JSON.stringify({ ...params, stream: true })
|
|
61
|
+
});
|
|
62
|
+
if (!response.ok) {
|
|
63
|
+
const error = await response.json();
|
|
64
|
+
throw new Error(error.error || "Stream request failed");
|
|
65
|
+
}
|
|
66
|
+
if (!response.body) {
|
|
67
|
+
throw new Error("Response body is null");
|
|
68
|
+
}
|
|
69
|
+
const reader = response.body.getReader();
|
|
70
|
+
const decoder = new TextDecoder();
|
|
71
|
+
let buffer = "";
|
|
72
|
+
try {
|
|
73
|
+
while (true) {
|
|
74
|
+
const { done, value } = await reader.read();
|
|
75
|
+
if (done) break;
|
|
76
|
+
buffer += decoder.decode(value, { stream: true });
|
|
77
|
+
const lines = buffer.split("\n");
|
|
78
|
+
buffer = lines.pop() || "";
|
|
79
|
+
for (const line of lines) {
|
|
80
|
+
if (line.trim() === "") continue;
|
|
81
|
+
if (!line.startsWith("data: ")) continue;
|
|
82
|
+
const data = line.slice(6);
|
|
83
|
+
if (data === "[DONE]") {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
try {
|
|
87
|
+
const chunk = JSON.parse(data);
|
|
88
|
+
yield chunk;
|
|
89
|
+
} catch (e) {
|
|
90
|
+
console.error("Failed to parse SSE data:", e);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
} finally {
|
|
95
|
+
reader.releaseLock();
|
|
96
|
+
}
|
|
41
97
|
}
|
|
42
98
|
};
|
|
43
99
|
|
|
@@ -112,6 +168,13 @@ var CencoriClient = class {
|
|
|
112
168
|
this.baseUrl = config.baseUrl || "https://cencori.com";
|
|
113
169
|
this.ai = new AIModule(this);
|
|
114
170
|
}
|
|
171
|
+
// Public getters for internal use by modules
|
|
172
|
+
getBaseUrl() {
|
|
173
|
+
return this.baseUrl;
|
|
174
|
+
}
|
|
175
|
+
getApiKey() {
|
|
176
|
+
return this.apiKey;
|
|
177
|
+
}
|
|
115
178
|
async request(endpoint, options) {
|
|
116
179
|
const url = `${this.baseUrl}${endpoint}`;
|
|
117
180
|
const headers = {
|
|
@@ -155,6 +218,7 @@ var CencoriClient = class {
|
|
|
155
218
|
};
|
|
156
219
|
// Annotate the CommonJS export names for ESM import in node:
|
|
157
220
|
0 && (module.exports = {
|
|
221
|
+
AIModule,
|
|
158
222
|
AuthenticationError,
|
|
159
223
|
CencoriClient,
|
|
160
224
|
CencoriError,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +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":[]}
|
|
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 { CencoriClient, ErrorResponse } from '../client';\r\n\r\nexport interface Message {\r\n role: 'system' | 'user' | 'assistant';\r\n content: string;\r\n}\r\n\r\nexport interface ChatParams {\r\n messages: Message[];\r\n model?: string;\r\n temperature?: number;\r\n maxTokens?: number;\r\n stream?: boolean;\r\n userId?: string;\r\n}\r\n\r\nexport interface ChatResponse {\r\n content: string;\r\n model: string;\r\n provider: string;\r\n usage: {\r\n prompt_tokens: number;\r\n completion_tokens: number;\r\n total_tokens: number;\r\n };\r\n cost_usd: number;\r\n finish_reason: 'stop' | 'length' | 'content_filter' | 'error';\r\n}\r\n\r\nexport interface StreamChunk {\r\n delta: string;\r\n finish_reason?: 'stop' | 'length' | 'content_filter' | 'error';\r\n}\r\n\r\nexport class AIModule {\r\n constructor(private client: CencoriClient) { }\r\n\r\n /**\r\n * Send a chat completion request (non-streaming)\r\n */\r\n async chat(params: ChatParams): Promise<ChatResponse> {\r\n const response = await this.client.request<ChatResponse>('/api/ai/chat', {\r\n method: 'POST',\r\n body: JSON.stringify({ ...params, stream: false }),\r\n });\r\n\r\n return response;\r\n }\r\n\r\n /**\r\n * Send a chat completion request with streaming\r\n * Returns an async generator that yields chunks as they arrive\r\n */\r\n async *chatStream(params: ChatParams): AsyncGenerator<StreamChunk, void, unknown> {\r\n const url = `${this.client.getBaseUrl()}/api/ai/chat`;\r\n\r\n const headers: Record<string, string> = {\r\n 'Content-Type': 'application/json',\r\n 'CENCORI_API_KEY': this.client.getApiKey(),\r\n };\r\n\r\n const response = await fetch(url, {\r\n method: 'POST',\r\n headers,\r\n body: JSON.stringify({ ...params, stream: true }),\r\n });\r\n\r\n if (!response.ok) {\r\n const error = await response.json() as ErrorResponse;\r\n throw new Error(error.error || 'Stream request failed');\r\n }\r\n\r\n if (!response.body) {\r\n throw new Error('Response body is null');\r\n }\r\n\r\n const reader = response.body.getReader();\r\n const decoder = new TextDecoder();\r\n let buffer = '';\r\n\r\n try {\r\n while (true) {\r\n const { done, value } = await reader.read();\r\n\r\n if (done) break;\r\n\r\n buffer += decoder.decode(value, { stream: true });\r\n const lines = buffer.split('\\n');\r\n\r\n // Keep the last incomplete line in the buffer\r\n buffer = lines.pop() || '';\r\n\r\n for (const line of lines) {\r\n if (line.trim() === '') continue;\r\n if (!line.startsWith('data: ')) continue;\r\n\r\n const data = line.slice(6); // Remove 'data: ' prefix\r\n\r\n if (data === '[DONE]') {\r\n return;\r\n }\r\n\r\n try {\r\n const chunk = JSON.parse(data) as StreamChunk;\r\n yield chunk;\r\n } catch (e) {\r\n console.error('Failed to parse SSE data:', e);\r\n }\r\n }\r\n }\r\n } finally {\r\n reader.releaseLock();\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';\r\nimport { AIModule } from './modules/ai';\r\nimport { fetchWithRetry } from './utils';\r\nimport {\r\n CencoriError,\r\n AuthenticationError,\r\n RateLimitError,\r\n SafetyError\r\n} from './errors';\r\n\r\nexport interface ErrorResponse {\r\n error?: string;\r\n reasons?: string[];\r\n}\r\n\r\nexport class CencoriClient {\r\n private apiKey: string;\r\n private baseUrl: string;\r\n\r\n public ai: AIModule;\r\n\r\n constructor(config: CencoriConfig) {\r\n if (!config.apiKey) {\r\n throw new Error('API key is required');\r\n }\r\n\r\n this.apiKey = config.apiKey;\r\n this.baseUrl = config.baseUrl || 'https://cencori.com';\r\n\r\n this.ai = new AIModule(this);\r\n }\r\n\r\n // Public getters for internal use by modules\r\n getBaseUrl(): string {\r\n return this.baseUrl;\r\n }\r\n\r\n getApiKey(): string {\r\n return this.apiKey;\r\n }\r\n\r\n async request<T>(endpoint: string, options: RequestOptions): Promise<T> {\r\n const url = `${this.baseUrl}${endpoint}`;\r\n\r\n const headers: Record<string, string> = {\r\n 'Content-Type': 'application/json',\r\n 'CENCORI_API_KEY': this.apiKey,\r\n ...options.headers\r\n };\r\n\r\n try {\r\n const response = await fetchWithRetry(url, {\r\n method: options.method,\r\n headers,\r\n body: options.body\r\n });\r\n\r\n const data: unknown = await response.json();\r\n\r\n // Handle API errors\r\n if (!response.ok) {\r\n const errorData = data as ErrorResponse;\r\n\r\n if (response.status === 401) {\r\n throw new AuthenticationError(errorData.error || 'Invalid API key');\r\n }\r\n if (response.status === 429) {\r\n throw new RateLimitError(errorData.error || 'Rate limit exceeded');\r\n }\r\n if (response.status === 400 && errorData.reasons) {\r\n throw new SafetyError(errorData.error, errorData.reasons);\r\n }\r\n throw new CencoriError(\r\n errorData.error || 'Request failed',\r\n response.status\r\n );\r\n }\r\n\r\n return data as T;\r\n } catch (error) {\r\n // Re-throw custom errors\r\n if (error instanceof CencoriError) {\r\n throw error;\r\n }\r\n\r\n // Wrap unknown errors\r\n throw new CencoriError(\r\n error instanceof Error ? error.message : 'Unknown error occurred'\r\n );\r\n }\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
|
package/dist/index.mjs
CHANGED
|
@@ -3,11 +3,66 @@ var AIModule = class {
|
|
|
3
3
|
constructor(client) {
|
|
4
4
|
this.client = client;
|
|
5
5
|
}
|
|
6
|
+
/**
|
|
7
|
+
* Send a chat completion request (non-streaming)
|
|
8
|
+
*/
|
|
6
9
|
async chat(params) {
|
|
7
|
-
|
|
10
|
+
const response = await this.client.request("/api/ai/chat", {
|
|
8
11
|
method: "POST",
|
|
9
|
-
body: JSON.stringify(params)
|
|
12
|
+
body: JSON.stringify({ ...params, stream: false })
|
|
10
13
|
});
|
|
14
|
+
return response;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Send a chat completion request with streaming
|
|
18
|
+
* Returns an async generator that yields chunks as they arrive
|
|
19
|
+
*/
|
|
20
|
+
async *chatStream(params) {
|
|
21
|
+
const url = `${this.client.getBaseUrl()}/api/ai/chat`;
|
|
22
|
+
const headers = {
|
|
23
|
+
"Content-Type": "application/json",
|
|
24
|
+
"CENCORI_API_KEY": this.client.getApiKey()
|
|
25
|
+
};
|
|
26
|
+
const response = await fetch(url, {
|
|
27
|
+
method: "POST",
|
|
28
|
+
headers,
|
|
29
|
+
body: JSON.stringify({ ...params, stream: true })
|
|
30
|
+
});
|
|
31
|
+
if (!response.ok) {
|
|
32
|
+
const error = await response.json();
|
|
33
|
+
throw new Error(error.error || "Stream request failed");
|
|
34
|
+
}
|
|
35
|
+
if (!response.body) {
|
|
36
|
+
throw new Error("Response body is null");
|
|
37
|
+
}
|
|
38
|
+
const reader = response.body.getReader();
|
|
39
|
+
const decoder = new TextDecoder();
|
|
40
|
+
let buffer = "";
|
|
41
|
+
try {
|
|
42
|
+
while (true) {
|
|
43
|
+
const { done, value } = await reader.read();
|
|
44
|
+
if (done) break;
|
|
45
|
+
buffer += decoder.decode(value, { stream: true });
|
|
46
|
+
const lines = buffer.split("\n");
|
|
47
|
+
buffer = lines.pop() || "";
|
|
48
|
+
for (const line of lines) {
|
|
49
|
+
if (line.trim() === "") continue;
|
|
50
|
+
if (!line.startsWith("data: ")) continue;
|
|
51
|
+
const data = line.slice(6);
|
|
52
|
+
if (data === "[DONE]") {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
try {
|
|
56
|
+
const chunk = JSON.parse(data);
|
|
57
|
+
yield chunk;
|
|
58
|
+
} catch (e) {
|
|
59
|
+
console.error("Failed to parse SSE data:", e);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
} finally {
|
|
64
|
+
reader.releaseLock();
|
|
65
|
+
}
|
|
11
66
|
}
|
|
12
67
|
};
|
|
13
68
|
|
|
@@ -82,6 +137,13 @@ var CencoriClient = class {
|
|
|
82
137
|
this.baseUrl = config.baseUrl || "https://cencori.com";
|
|
83
138
|
this.ai = new AIModule(this);
|
|
84
139
|
}
|
|
140
|
+
// Public getters for internal use by modules
|
|
141
|
+
getBaseUrl() {
|
|
142
|
+
return this.baseUrl;
|
|
143
|
+
}
|
|
144
|
+
getApiKey() {
|
|
145
|
+
return this.apiKey;
|
|
146
|
+
}
|
|
85
147
|
async request(endpoint, options) {
|
|
86
148
|
const url = `${this.baseUrl}${endpoint}`;
|
|
87
149
|
const headers = {
|
|
@@ -124,6 +186,7 @@ var CencoriClient = class {
|
|
|
124
186
|
}
|
|
125
187
|
};
|
|
126
188
|
export {
|
|
189
|
+
AIModule,
|
|
127
190
|
AuthenticationError,
|
|
128
191
|
CencoriClient,
|
|
129
192
|
CencoriError,
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +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":[]}
|
|
1
|
+
{"version":3,"sources":["../src/modules/ai.ts","../src/utils.ts","../src/errors.ts","../src/client.ts"],"sourcesContent":["import type { CencoriClient, ErrorResponse } from '../client';\r\n\r\nexport interface Message {\r\n role: 'system' | 'user' | 'assistant';\r\n content: string;\r\n}\r\n\r\nexport interface ChatParams {\r\n messages: Message[];\r\n model?: string;\r\n temperature?: number;\r\n maxTokens?: number;\r\n stream?: boolean;\r\n userId?: string;\r\n}\r\n\r\nexport interface ChatResponse {\r\n content: string;\r\n model: string;\r\n provider: string;\r\n usage: {\r\n prompt_tokens: number;\r\n completion_tokens: number;\r\n total_tokens: number;\r\n };\r\n cost_usd: number;\r\n finish_reason: 'stop' | 'length' | 'content_filter' | 'error';\r\n}\r\n\r\nexport interface StreamChunk {\r\n delta: string;\r\n finish_reason?: 'stop' | 'length' | 'content_filter' | 'error';\r\n}\r\n\r\nexport class AIModule {\r\n constructor(private client: CencoriClient) { }\r\n\r\n /**\r\n * Send a chat completion request (non-streaming)\r\n */\r\n async chat(params: ChatParams): Promise<ChatResponse> {\r\n const response = await this.client.request<ChatResponse>('/api/ai/chat', {\r\n method: 'POST',\r\n body: JSON.stringify({ ...params, stream: false }),\r\n });\r\n\r\n return response;\r\n }\r\n\r\n /**\r\n * Send a chat completion request with streaming\r\n * Returns an async generator that yields chunks as they arrive\r\n */\r\n async *chatStream(params: ChatParams): AsyncGenerator<StreamChunk, void, unknown> {\r\n const url = `${this.client.getBaseUrl()}/api/ai/chat`;\r\n\r\n const headers: Record<string, string> = {\r\n 'Content-Type': 'application/json',\r\n 'CENCORI_API_KEY': this.client.getApiKey(),\r\n };\r\n\r\n const response = await fetch(url, {\r\n method: 'POST',\r\n headers,\r\n body: JSON.stringify({ ...params, stream: true }),\r\n });\r\n\r\n if (!response.ok) {\r\n const error = await response.json() as ErrorResponse;\r\n throw new Error(error.error || 'Stream request failed');\r\n }\r\n\r\n if (!response.body) {\r\n throw new Error('Response body is null');\r\n }\r\n\r\n const reader = response.body.getReader();\r\n const decoder = new TextDecoder();\r\n let buffer = '';\r\n\r\n try {\r\n while (true) {\r\n const { done, value } = await reader.read();\r\n\r\n if (done) break;\r\n\r\n buffer += decoder.decode(value, { stream: true });\r\n const lines = buffer.split('\\n');\r\n\r\n // Keep the last incomplete line in the buffer\r\n buffer = lines.pop() || '';\r\n\r\n for (const line of lines) {\r\n if (line.trim() === '') continue;\r\n if (!line.startsWith('data: ')) continue;\r\n\r\n const data = line.slice(6); // Remove 'data: ' prefix\r\n\r\n if (data === '[DONE]') {\r\n return;\r\n }\r\n\r\n try {\r\n const chunk = JSON.parse(data) as StreamChunk;\r\n yield chunk;\r\n } catch (e) {\r\n console.error('Failed to parse SSE data:', e);\r\n }\r\n }\r\n }\r\n } finally {\r\n reader.releaseLock();\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';\r\nimport { AIModule } from './modules/ai';\r\nimport { fetchWithRetry } from './utils';\r\nimport {\r\n CencoriError,\r\n AuthenticationError,\r\n RateLimitError,\r\n SafetyError\r\n} from './errors';\r\n\r\nexport interface ErrorResponse {\r\n error?: string;\r\n reasons?: string[];\r\n}\r\n\r\nexport class CencoriClient {\r\n private apiKey: string;\r\n private baseUrl: string;\r\n\r\n public ai: AIModule;\r\n\r\n constructor(config: CencoriConfig) {\r\n if (!config.apiKey) {\r\n throw new Error('API key is required');\r\n }\r\n\r\n this.apiKey = config.apiKey;\r\n this.baseUrl = config.baseUrl || 'https://cencori.com';\r\n\r\n this.ai = new AIModule(this);\r\n }\r\n\r\n // Public getters for internal use by modules\r\n getBaseUrl(): string {\r\n return this.baseUrl;\r\n }\r\n\r\n getApiKey(): string {\r\n return this.apiKey;\r\n }\r\n\r\n async request<T>(endpoint: string, options: RequestOptions): Promise<T> {\r\n const url = `${this.baseUrl}${endpoint}`;\r\n\r\n const headers: Record<string, string> = {\r\n 'Content-Type': 'application/json',\r\n 'CENCORI_API_KEY': this.apiKey,\r\n ...options.headers\r\n };\r\n\r\n try {\r\n const response = await fetchWithRetry(url, {\r\n method: options.method,\r\n headers,\r\n body: options.body\r\n });\r\n\r\n const data: unknown = await response.json();\r\n\r\n // Handle API errors\r\n if (!response.ok) {\r\n const errorData = data as ErrorResponse;\r\n\r\n if (response.status === 401) {\r\n throw new AuthenticationError(errorData.error || 'Invalid API key');\r\n }\r\n if (response.status === 429) {\r\n throw new RateLimitError(errorData.error || 'Rate limit exceeded');\r\n }\r\n if (response.status === 400 && errorData.reasons) {\r\n throw new SafetyError(errorData.error, errorData.reasons);\r\n }\r\n throw new CencoriError(\r\n errorData.error || 'Request failed',\r\n response.status\r\n );\r\n }\r\n\r\n return data as T;\r\n } catch (error) {\r\n // Re-throw custom errors\r\n if (error instanceof CencoriError) {\r\n throw error;\r\n }\r\n\r\n // Wrap unknown errors\r\n throw new CencoriError(\r\n error instanceof Error ? error.message : 'Unknown error occurred'\r\n );\r\n }\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,19 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cencori",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Official SDK for Cencori",
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Official TypeScript SDK for Cencori - The Security Layer for AI Development",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
8
|
"files": [
|
|
9
|
-
"dist"
|
|
9
|
+
"dist",
|
|
10
|
+
"README.md"
|
|
10
11
|
],
|
|
11
12
|
"keywords": [
|
|
12
13
|
"ai",
|
|
13
14
|
"gateway",
|
|
14
15
|
"cencori",
|
|
15
16
|
"sdk",
|
|
16
|
-
"typescript"
|
|
17
|
+
"typescript",
|
|
18
|
+
"openai",
|
|
19
|
+
"anthropic",
|
|
20
|
+
"streaming",
|
|
21
|
+
"security"
|
|
17
22
|
],
|
|
18
23
|
"author": "FohnAI",
|
|
19
24
|
"license": "MIT",
|
|
@@ -21,6 +26,10 @@
|
|
|
21
26
|
"type": "git",
|
|
22
27
|
"url": "https://github.com/bolaabanjo/cencori"
|
|
23
28
|
},
|
|
29
|
+
"homepage": "https://cencori.com",
|
|
30
|
+
"bugs": {
|
|
31
|
+
"url": "https://github.com/bolaabanjo/cencori/issues"
|
|
32
|
+
},
|
|
24
33
|
"scripts": {
|
|
25
34
|
"build": "tsup",
|
|
26
35
|
"dev": "tsup --watch",
|