@sintaksdev/sdk 0.0.0-stage → 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 +75 -2
- package/dist/index.cjs +174 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +120 -0
- package/dist/index.d.ts +120 -0
- package/dist/index.js +146 -0
- package/dist/index.js.map +1 -0
- package/package.json +49 -4
package/README.md
CHANGED
|
@@ -1,3 +1,76 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @sintaksdev/sdk
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
TypeScript client for the [sintaks.dev](https://sintaks.dev) OpenAI-compatible AI API gateway. Top up in IDR via QRIS/iPaymu, call chat and image models, and pay per request. Zero runtime dependencies (Node >= 18, global `fetch`).
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @sintaksdev/sdk
|
|
9
|
+
# or
|
|
10
|
+
npm install @sintaksdev/sdk
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { Sintaks } from "@sintaksdev/sdk";
|
|
17
|
+
|
|
18
|
+
const client = new Sintaks({ apiKey: "sk-..." });
|
|
19
|
+
|
|
20
|
+
// Non-streaming chat
|
|
21
|
+
const resp = await client.chat.completions.create({
|
|
22
|
+
model: "claude-sonnet-5-5",
|
|
23
|
+
messages: [{ role: "user", content: "Halo!" }],
|
|
24
|
+
});
|
|
25
|
+
console.log(resp.choices[0]?.message.content);
|
|
26
|
+
|
|
27
|
+
// Streaming
|
|
28
|
+
const stream = await client.chat.completions.create({
|
|
29
|
+
model: "claude-sonnet-5-5",
|
|
30
|
+
messages: [{ role: "user", content: "Halo!" }],
|
|
31
|
+
stream: true,
|
|
32
|
+
});
|
|
33
|
+
for await (const chunk of stream) {
|
|
34
|
+
process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Image generation
|
|
38
|
+
const images = await client.images.generate({
|
|
39
|
+
model: "flux-schnell",
|
|
40
|
+
prompt: "A futuristic Jakarta skyline at dusk",
|
|
41
|
+
});
|
|
42
|
+
console.log(images.data[0]?.url);
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
`model` defaults to `claude-sonnet-5-5` when omitted. Point at another environment with `baseURL`:
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
const client = new Sintaks({ apiKey: "sk-...", baseURL: "http://localhost:8080" });
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Errors
|
|
52
|
+
|
|
53
|
+
Failures throw `SintaksError` with `status`, `type`, `code`, and `requestId` (the gateway `X-Request-ID`, useful for support).
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
try {
|
|
57
|
+
await client.chat.completions.create({ messages: [{ role: "user", content: "x" }] });
|
|
58
|
+
} catch (err) {
|
|
59
|
+
if (err instanceof SintaksError && err.status === 402) {
|
|
60
|
+
console.error("insufficient balance, top up first");
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Development & publishing
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
pnpm install
|
|
69
|
+
pnpm typecheck
|
|
70
|
+
pnpm build # tsup → dist/ (ESM + CJS + types)
|
|
71
|
+
pnpm pack # inspect the publish tarball
|
|
72
|
+
npm login # one-time auth for your npm account
|
|
73
|
+
npm publish # requires an account with access to the @sintaksdev scope
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
`prepublishOnly` runs the build automatically, so `npm publish` ships fresh `dist/`. Publish to a different registry (e.g. GitHub Packages, Verdaccio) with `npm publish --registry <url>`.
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
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
|
+
DEFAULT_BASE_URL: () => DEFAULT_BASE_URL,
|
|
24
|
+
DEFAULT_CHAT_MODEL: () => DEFAULT_CHAT_MODEL,
|
|
25
|
+
Sintaks: () => Sintaks,
|
|
26
|
+
SintaksError: () => SintaksError,
|
|
27
|
+
default: () => index_default
|
|
28
|
+
});
|
|
29
|
+
module.exports = __toCommonJS(index_exports);
|
|
30
|
+
var DEFAULT_BASE_URL = "https://api.sintaks.dev";
|
|
31
|
+
var DEFAULT_CHAT_MODEL = "claude-sonnet-5-5";
|
|
32
|
+
var SintaksError = class extends Error {
|
|
33
|
+
status;
|
|
34
|
+
type;
|
|
35
|
+
code;
|
|
36
|
+
requestId;
|
|
37
|
+
constructor(status, message, opts = {}) {
|
|
38
|
+
super(message);
|
|
39
|
+
this.name = "SintaksError";
|
|
40
|
+
this.status = status;
|
|
41
|
+
this.type = opts.type;
|
|
42
|
+
this.code = opts.code ?? null;
|
|
43
|
+
this.requestId = opts.requestId ?? null;
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
var Sintaks = class {
|
|
47
|
+
apiKey;
|
|
48
|
+
baseURL;
|
|
49
|
+
chat;
|
|
50
|
+
images;
|
|
51
|
+
/** @internal */
|
|
52
|
+
fetchFn;
|
|
53
|
+
/** @internal */
|
|
54
|
+
extraHeaders;
|
|
55
|
+
constructor(options) {
|
|
56
|
+
if (!options.apiKey) throw new Error("Sintaks: apiKey is required");
|
|
57
|
+
this.apiKey = options.apiKey;
|
|
58
|
+
this.baseURL = (options.baseURL ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
59
|
+
this.fetchFn = options.fetch ?? fetch;
|
|
60
|
+
this.extraHeaders = options.headers ?? {};
|
|
61
|
+
this.chat = new ChatResource(this);
|
|
62
|
+
this.images = new ImagesResource(this);
|
|
63
|
+
}
|
|
64
|
+
async request(method, path, body) {
|
|
65
|
+
const res = await this.fetchFn(`${this.baseURL}${path}`, {
|
|
66
|
+
method,
|
|
67
|
+
headers: {
|
|
68
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
69
|
+
"Content-Type": "application/json",
|
|
70
|
+
...this.extraHeaders
|
|
71
|
+
},
|
|
72
|
+
body: body === void 0 ? void 0 : JSON.stringify(body)
|
|
73
|
+
});
|
|
74
|
+
if (!res.ok) {
|
|
75
|
+
let envelope = {};
|
|
76
|
+
try {
|
|
77
|
+
envelope = await res.json();
|
|
78
|
+
} catch {
|
|
79
|
+
}
|
|
80
|
+
throw new SintaksError(res.status, envelope.error?.message ?? `request failed with ${res.status}`, {
|
|
81
|
+
type: envelope.error?.type,
|
|
82
|
+
code: envelope.error?.code,
|
|
83
|
+
requestId: res.headers.get("x-request-id")
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
return await res.json();
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
var ChatResource = class {
|
|
90
|
+
constructor(client) {
|
|
91
|
+
this.client = client;
|
|
92
|
+
}
|
|
93
|
+
client;
|
|
94
|
+
completions = this;
|
|
95
|
+
async create(params) {
|
|
96
|
+
if (params.stream) {
|
|
97
|
+
return this.createStream(params);
|
|
98
|
+
}
|
|
99
|
+
return this.client.request("POST", "/v1/chat/completions", {
|
|
100
|
+
...params,
|
|
101
|
+
model: params.model ?? DEFAULT_CHAT_MODEL
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
async createStream(params) {
|
|
105
|
+
const res = await this.client.fetchFn(`${this.client.baseURL}/v1/chat/completions`, {
|
|
106
|
+
method: "POST",
|
|
107
|
+
headers: {
|
|
108
|
+
Authorization: `Bearer ${this.client.apiKey}`,
|
|
109
|
+
"Content-Type": "application/json",
|
|
110
|
+
Accept: "text/event-stream",
|
|
111
|
+
...this.client.extraHeaders
|
|
112
|
+
},
|
|
113
|
+
body: JSON.stringify({ ...params, model: params.model ?? DEFAULT_CHAT_MODEL })
|
|
114
|
+
});
|
|
115
|
+
if (!res.ok || !res.body) {
|
|
116
|
+
let envelope = {};
|
|
117
|
+
try {
|
|
118
|
+
envelope = await res.json();
|
|
119
|
+
} catch {
|
|
120
|
+
}
|
|
121
|
+
throw new SintaksError(res.status, envelope.error?.message ?? `request failed with ${res.status}`, {
|
|
122
|
+
type: envelope.error?.type,
|
|
123
|
+
code: envelope.error?.code,
|
|
124
|
+
requestId: res.headers.get("x-request-id")
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
return parseSSE(res.body);
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
async function* parseSSE(body) {
|
|
131
|
+
const reader = body.getReader();
|
|
132
|
+
const decoder = new TextDecoder();
|
|
133
|
+
let buffer = "";
|
|
134
|
+
try {
|
|
135
|
+
while (true) {
|
|
136
|
+
const { done, value } = await reader.read();
|
|
137
|
+
if (done) break;
|
|
138
|
+
buffer += decoder.decode(value, { stream: true });
|
|
139
|
+
let boundary;
|
|
140
|
+
while ((boundary = buffer.indexOf("\n\n")) !== -1) {
|
|
141
|
+
const chunk = buffer.slice(0, boundary);
|
|
142
|
+
buffer = buffer.slice(boundary + 2);
|
|
143
|
+
const dataLine = chunk.split("\n").find((line) => line.startsWith("data:"));
|
|
144
|
+
if (!dataLine) continue;
|
|
145
|
+
const payload = dataLine.slice(5).trim();
|
|
146
|
+
if (payload === "[DONE]") return;
|
|
147
|
+
try {
|
|
148
|
+
yield JSON.parse(payload);
|
|
149
|
+
} catch {
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
} finally {
|
|
154
|
+
reader.releaseLock();
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
var ImagesResource = class {
|
|
158
|
+
constructor(client) {
|
|
159
|
+
this.client = client;
|
|
160
|
+
}
|
|
161
|
+
client;
|
|
162
|
+
async generate(params) {
|
|
163
|
+
return this.client.request("POST", "/v1/images/generations", params);
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
var index_default = Sintaks;
|
|
167
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
168
|
+
0 && (module.exports = {
|
|
169
|
+
DEFAULT_BASE_URL,
|
|
170
|
+
DEFAULT_CHAT_MODEL,
|
|
171
|
+
Sintaks,
|
|
172
|
+
SintaksError
|
|
173
|
+
});
|
|
174
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * @sintaksdev/sdk — TypeScript client for the sintaks.dev OpenAI-compatible\n * AI API gateway. Zero runtime dependencies; requires Node >= 18 (global fetch).\n */\n\nexport const DEFAULT_BASE_URL = \"https://api.sintaks.dev\";\nexport const DEFAULT_CHAT_MODEL = \"claude-sonnet-5-5\";\n\n/* ------------------------------------------------------------------ */\n/* Types (OpenAI-compatible shapes) */\n/* ------------------------------------------------------------------ */\n\nexport interface ChatMessage {\n role: \"system\" | \"user\" | \"assistant\" | \"tool\";\n content: string;\n name?: string;\n}\n\nexport interface ChatCompletionCreateParams {\n model?: string;\n messages: ChatMessage[];\n stream?: boolean;\n temperature?: number;\n top_p?: number;\n max_tokens?: number;\n stop?: string | string[];\n [key: string]: unknown;\n}\n\nexport interface ChatCompletion {\n id: string;\n object: \"chat.completion\";\n created: number;\n model: string;\n choices: {\n index: number;\n message: ChatMessage;\n finish_reason: string | null;\n }[];\n usage?: {\n prompt_tokens: number;\n completion_tokens: number;\n total_tokens: number;\n };\n}\n\nexport interface ChatCompletionChunk {\n id: string;\n object: \"chat.completion.chunk\";\n created: number;\n model: string;\n choices: {\n index: number;\n delta: { role?: string; content?: string | null };\n finish_reason: string | null;\n }[];\n}\n\nexport interface ImageGenerationParams {\n model?: string;\n prompt: string;\n n?: number;\n size?: string;\n [key: string]: unknown;\n}\n\nexport interface GeneratedImage {\n url?: string;\n b64_json?: string;\n}\n\nexport interface ImageGenerationResult {\n created: number;\n data: GeneratedImage[];\n}\n\nexport interface ErrorEnvelope {\n error?: {\n message?: string;\n type?: string;\n param?: string | null;\n code?: string | null;\n };\n}\n\n/* ------------------------------------------------------------------ */\n/* Error */\n/* ------------------------------------------------------------------ */\n\nexport class SintaksError extends Error {\n readonly status: number;\n readonly type: string | undefined;\n readonly code: string | null;\n readonly requestId: string | null;\n\n constructor(\n status: number,\n message: string,\n opts: { type?: string; code?: string | null; requestId?: string | null } = {},\n ) {\n super(message);\n this.name = \"SintaksError\";\n this.status = status;\n this.type = opts.type;\n this.code = opts.code ?? null;\n this.requestId = opts.requestId ?? null;\n }\n}\n\n/* ------------------------------------------------------------------ */\n/* Client */\n/* ------------------------------------------------------------------ */\n\nexport interface SintaksOptions {\n apiKey: string;\n baseURL?: string;\n fetch?: typeof fetch;\n headers?: Record<string, string>;\n}\n\nexport class Sintaks {\n readonly apiKey: string;\n readonly baseURL: string;\n readonly chat: ChatResource;\n readonly images: ImagesResource;\n\n /** @internal */\n readonly fetchFn: typeof fetch;\n /** @internal */\n readonly extraHeaders: Record<string, string>;\n\n constructor(options: SintaksOptions) {\n if (!options.apiKey) throw new Error(\"Sintaks: apiKey is required\");\n this.apiKey = options.apiKey;\n this.baseURL = (options.baseURL ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.fetchFn = options.fetch ?? fetch;\n this.extraHeaders = options.headers ?? {};\n this.chat = new ChatResource(this);\n this.images = new ImagesResource(this);\n }\n\n async request<T>(method: string, path: string, body?: unknown): Promise<T> {\n const res = await this.fetchFn(`${this.baseURL}${path}`, {\n method,\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n \"Content-Type\": \"application/json\",\n ...this.extraHeaders,\n },\n body: body === undefined ? undefined : JSON.stringify(body),\n });\n\n if (!res.ok) {\n let envelope: ErrorEnvelope = {};\n try {\n envelope = (await res.json()) as ErrorEnvelope;\n } catch {\n // non-JSON error body; fall through with defaults\n }\n throw new SintaksError(res.status, envelope.error?.message ?? `request failed with ${res.status}`, {\n type: envelope.error?.type,\n code: envelope.error?.code,\n requestId: res.headers.get(\"x-request-id\"),\n });\n }\n return (await res.json()) as T;\n }\n}\n\n/* ------------------------------------------------------------------ */\n/* Chat */\n/* ------------------------------------------------------------------ */\n\nclass ChatResource {\n readonly completions = this;\n\n constructor(private client: Sintaks) {}\n\n async create(params: ChatCompletionCreateParams): Promise<ChatCompletion>;\n async create(params: ChatCompletionCreateParams & { stream: true }): Promise<AsyncIterable<ChatCompletionChunk>>;\n async create(\n params: ChatCompletionCreateParams,\n ): Promise<ChatCompletion | AsyncIterable<ChatCompletionChunk>> {\n if (params.stream) {\n return this.createStream(params as ChatCompletionCreateParams & { stream: true });\n }\n return this.client.request<ChatCompletion>(\"POST\", \"/v1/chat/completions\", {\n ...params,\n model: params.model ?? DEFAULT_CHAT_MODEL,\n });\n }\n\n private async createStream(\n params: ChatCompletionCreateParams & { stream: true },\n ): Promise<AsyncIterable<ChatCompletionChunk>> {\n const res = await this.client.fetchFn(`${this.client.baseURL}/v1/chat/completions`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.client.apiKey}`,\n \"Content-Type\": \"application/json\",\n Accept: \"text/event-stream\",\n ...this.client.extraHeaders,\n },\n body: JSON.stringify({ ...params, model: params.model ?? DEFAULT_CHAT_MODEL }),\n });\n\n if (!res.ok || !res.body) {\n let envelope: ErrorEnvelope = {};\n try {\n envelope = (await res.json()) as ErrorEnvelope;\n } catch {\n // ignore\n }\n throw new SintaksError(res.status, envelope.error?.message ?? `request failed with ${res.status}`, {\n type: envelope.error?.type,\n code: envelope.error?.code,\n requestId: res.headers.get(\"x-request-id\"),\n });\n }\n\n return parseSSE<ChatCompletionChunk>(res.body);\n }\n}\n\n/** Minimal SSE parser for OpenAI-style `data:` events. */\nasync function* parseSSE<T>(body: ReadableStream<Uint8Array>): AsyncIterable<T> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n\n let boundary: number;\n while ((boundary = buffer.indexOf(\"\\n\\n\")) !== -1) {\n const chunk = buffer.slice(0, boundary);\n buffer = buffer.slice(boundary + 2);\n const dataLine = chunk\n .split(\"\\n\")\n .find((line) => line.startsWith(\"data:\"));\n if (!dataLine) continue;\n const payload = dataLine.slice(5).trim();\n if (payload === \"[DONE]\") return;\n try {\n yield JSON.parse(payload) as T;\n } catch {\n // skip malformed event\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n}\n\n/* ------------------------------------------------------------------ */\n/* Images */\n/* ------------------------------------------------------------------ */\n\nclass ImagesResource {\n constructor(private client: Sintaks) {}\n\n async generate(params: ImageGenerationParams): Promise<ImageGenerationResult> {\n return this.client.request<ImageGenerationResult>(\"POST\", \"/v1/images/generations\", params);\n }\n}\n\nexport default Sintaks;"],"mappings":"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","names":[]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @sintaksdev/sdk — TypeScript client for the sintaks.dev OpenAI-compatible
|
|
3
|
+
* AI API gateway. Zero runtime dependencies; requires Node >= 18 (global fetch).
|
|
4
|
+
*/
|
|
5
|
+
declare const DEFAULT_BASE_URL = "https://api.sintaks.dev";
|
|
6
|
+
declare const DEFAULT_CHAT_MODEL = "claude-sonnet-5-5";
|
|
7
|
+
interface ChatMessage {
|
|
8
|
+
role: "system" | "user" | "assistant" | "tool";
|
|
9
|
+
content: string;
|
|
10
|
+
name?: string;
|
|
11
|
+
}
|
|
12
|
+
interface ChatCompletionCreateParams {
|
|
13
|
+
model?: string;
|
|
14
|
+
messages: ChatMessage[];
|
|
15
|
+
stream?: boolean;
|
|
16
|
+
temperature?: number;
|
|
17
|
+
top_p?: number;
|
|
18
|
+
max_tokens?: number;
|
|
19
|
+
stop?: string | string[];
|
|
20
|
+
[key: string]: unknown;
|
|
21
|
+
}
|
|
22
|
+
interface ChatCompletion {
|
|
23
|
+
id: string;
|
|
24
|
+
object: "chat.completion";
|
|
25
|
+
created: number;
|
|
26
|
+
model: string;
|
|
27
|
+
choices: {
|
|
28
|
+
index: number;
|
|
29
|
+
message: ChatMessage;
|
|
30
|
+
finish_reason: string | null;
|
|
31
|
+
}[];
|
|
32
|
+
usage?: {
|
|
33
|
+
prompt_tokens: number;
|
|
34
|
+
completion_tokens: number;
|
|
35
|
+
total_tokens: number;
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
interface ChatCompletionChunk {
|
|
39
|
+
id: string;
|
|
40
|
+
object: "chat.completion.chunk";
|
|
41
|
+
created: number;
|
|
42
|
+
model: string;
|
|
43
|
+
choices: {
|
|
44
|
+
index: number;
|
|
45
|
+
delta: {
|
|
46
|
+
role?: string;
|
|
47
|
+
content?: string | null;
|
|
48
|
+
};
|
|
49
|
+
finish_reason: string | null;
|
|
50
|
+
}[];
|
|
51
|
+
}
|
|
52
|
+
interface ImageGenerationParams {
|
|
53
|
+
model?: string;
|
|
54
|
+
prompt: string;
|
|
55
|
+
n?: number;
|
|
56
|
+
size?: string;
|
|
57
|
+
[key: string]: unknown;
|
|
58
|
+
}
|
|
59
|
+
interface GeneratedImage {
|
|
60
|
+
url?: string;
|
|
61
|
+
b64_json?: string;
|
|
62
|
+
}
|
|
63
|
+
interface ImageGenerationResult {
|
|
64
|
+
created: number;
|
|
65
|
+
data: GeneratedImage[];
|
|
66
|
+
}
|
|
67
|
+
interface ErrorEnvelope {
|
|
68
|
+
error?: {
|
|
69
|
+
message?: string;
|
|
70
|
+
type?: string;
|
|
71
|
+
param?: string | null;
|
|
72
|
+
code?: string | null;
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
declare class SintaksError extends Error {
|
|
76
|
+
readonly status: number;
|
|
77
|
+
readonly type: string | undefined;
|
|
78
|
+
readonly code: string | null;
|
|
79
|
+
readonly requestId: string | null;
|
|
80
|
+
constructor(status: number, message: string, opts?: {
|
|
81
|
+
type?: string;
|
|
82
|
+
code?: string | null;
|
|
83
|
+
requestId?: string | null;
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
interface SintaksOptions {
|
|
87
|
+
apiKey: string;
|
|
88
|
+
baseURL?: string;
|
|
89
|
+
fetch?: typeof fetch;
|
|
90
|
+
headers?: Record<string, string>;
|
|
91
|
+
}
|
|
92
|
+
declare class Sintaks {
|
|
93
|
+
readonly apiKey: string;
|
|
94
|
+
readonly baseURL: string;
|
|
95
|
+
readonly chat: ChatResource;
|
|
96
|
+
readonly images: ImagesResource;
|
|
97
|
+
/** @internal */
|
|
98
|
+
readonly fetchFn: typeof fetch;
|
|
99
|
+
/** @internal */
|
|
100
|
+
readonly extraHeaders: Record<string, string>;
|
|
101
|
+
constructor(options: SintaksOptions);
|
|
102
|
+
request<T>(method: string, path: string, body?: unknown): Promise<T>;
|
|
103
|
+
}
|
|
104
|
+
declare class ChatResource {
|
|
105
|
+
private client;
|
|
106
|
+
readonly completions: this;
|
|
107
|
+
constructor(client: Sintaks);
|
|
108
|
+
create(params: ChatCompletionCreateParams): Promise<ChatCompletion>;
|
|
109
|
+
create(params: ChatCompletionCreateParams & {
|
|
110
|
+
stream: true;
|
|
111
|
+
}): Promise<AsyncIterable<ChatCompletionChunk>>;
|
|
112
|
+
private createStream;
|
|
113
|
+
}
|
|
114
|
+
declare class ImagesResource {
|
|
115
|
+
private client;
|
|
116
|
+
constructor(client: Sintaks);
|
|
117
|
+
generate(params: ImageGenerationParams): Promise<ImageGenerationResult>;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export { type ChatCompletion, type ChatCompletionChunk, type ChatCompletionCreateParams, type ChatMessage, DEFAULT_BASE_URL, DEFAULT_CHAT_MODEL, type ErrorEnvelope, type GeneratedImage, type ImageGenerationParams, type ImageGenerationResult, Sintaks, SintaksError, type SintaksOptions, Sintaks as default };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @sintaksdev/sdk — TypeScript client for the sintaks.dev OpenAI-compatible
|
|
3
|
+
* AI API gateway. Zero runtime dependencies; requires Node >= 18 (global fetch).
|
|
4
|
+
*/
|
|
5
|
+
declare const DEFAULT_BASE_URL = "https://api.sintaks.dev";
|
|
6
|
+
declare const DEFAULT_CHAT_MODEL = "claude-sonnet-5-5";
|
|
7
|
+
interface ChatMessage {
|
|
8
|
+
role: "system" | "user" | "assistant" | "tool";
|
|
9
|
+
content: string;
|
|
10
|
+
name?: string;
|
|
11
|
+
}
|
|
12
|
+
interface ChatCompletionCreateParams {
|
|
13
|
+
model?: string;
|
|
14
|
+
messages: ChatMessage[];
|
|
15
|
+
stream?: boolean;
|
|
16
|
+
temperature?: number;
|
|
17
|
+
top_p?: number;
|
|
18
|
+
max_tokens?: number;
|
|
19
|
+
stop?: string | string[];
|
|
20
|
+
[key: string]: unknown;
|
|
21
|
+
}
|
|
22
|
+
interface ChatCompletion {
|
|
23
|
+
id: string;
|
|
24
|
+
object: "chat.completion";
|
|
25
|
+
created: number;
|
|
26
|
+
model: string;
|
|
27
|
+
choices: {
|
|
28
|
+
index: number;
|
|
29
|
+
message: ChatMessage;
|
|
30
|
+
finish_reason: string | null;
|
|
31
|
+
}[];
|
|
32
|
+
usage?: {
|
|
33
|
+
prompt_tokens: number;
|
|
34
|
+
completion_tokens: number;
|
|
35
|
+
total_tokens: number;
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
interface ChatCompletionChunk {
|
|
39
|
+
id: string;
|
|
40
|
+
object: "chat.completion.chunk";
|
|
41
|
+
created: number;
|
|
42
|
+
model: string;
|
|
43
|
+
choices: {
|
|
44
|
+
index: number;
|
|
45
|
+
delta: {
|
|
46
|
+
role?: string;
|
|
47
|
+
content?: string | null;
|
|
48
|
+
};
|
|
49
|
+
finish_reason: string | null;
|
|
50
|
+
}[];
|
|
51
|
+
}
|
|
52
|
+
interface ImageGenerationParams {
|
|
53
|
+
model?: string;
|
|
54
|
+
prompt: string;
|
|
55
|
+
n?: number;
|
|
56
|
+
size?: string;
|
|
57
|
+
[key: string]: unknown;
|
|
58
|
+
}
|
|
59
|
+
interface GeneratedImage {
|
|
60
|
+
url?: string;
|
|
61
|
+
b64_json?: string;
|
|
62
|
+
}
|
|
63
|
+
interface ImageGenerationResult {
|
|
64
|
+
created: number;
|
|
65
|
+
data: GeneratedImage[];
|
|
66
|
+
}
|
|
67
|
+
interface ErrorEnvelope {
|
|
68
|
+
error?: {
|
|
69
|
+
message?: string;
|
|
70
|
+
type?: string;
|
|
71
|
+
param?: string | null;
|
|
72
|
+
code?: string | null;
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
declare class SintaksError extends Error {
|
|
76
|
+
readonly status: number;
|
|
77
|
+
readonly type: string | undefined;
|
|
78
|
+
readonly code: string | null;
|
|
79
|
+
readonly requestId: string | null;
|
|
80
|
+
constructor(status: number, message: string, opts?: {
|
|
81
|
+
type?: string;
|
|
82
|
+
code?: string | null;
|
|
83
|
+
requestId?: string | null;
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
interface SintaksOptions {
|
|
87
|
+
apiKey: string;
|
|
88
|
+
baseURL?: string;
|
|
89
|
+
fetch?: typeof fetch;
|
|
90
|
+
headers?: Record<string, string>;
|
|
91
|
+
}
|
|
92
|
+
declare class Sintaks {
|
|
93
|
+
readonly apiKey: string;
|
|
94
|
+
readonly baseURL: string;
|
|
95
|
+
readonly chat: ChatResource;
|
|
96
|
+
readonly images: ImagesResource;
|
|
97
|
+
/** @internal */
|
|
98
|
+
readonly fetchFn: typeof fetch;
|
|
99
|
+
/** @internal */
|
|
100
|
+
readonly extraHeaders: Record<string, string>;
|
|
101
|
+
constructor(options: SintaksOptions);
|
|
102
|
+
request<T>(method: string, path: string, body?: unknown): Promise<T>;
|
|
103
|
+
}
|
|
104
|
+
declare class ChatResource {
|
|
105
|
+
private client;
|
|
106
|
+
readonly completions: this;
|
|
107
|
+
constructor(client: Sintaks);
|
|
108
|
+
create(params: ChatCompletionCreateParams): Promise<ChatCompletion>;
|
|
109
|
+
create(params: ChatCompletionCreateParams & {
|
|
110
|
+
stream: true;
|
|
111
|
+
}): Promise<AsyncIterable<ChatCompletionChunk>>;
|
|
112
|
+
private createStream;
|
|
113
|
+
}
|
|
114
|
+
declare class ImagesResource {
|
|
115
|
+
private client;
|
|
116
|
+
constructor(client: Sintaks);
|
|
117
|
+
generate(params: ImageGenerationParams): Promise<ImageGenerationResult>;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export { type ChatCompletion, type ChatCompletionChunk, type ChatCompletionCreateParams, type ChatMessage, DEFAULT_BASE_URL, DEFAULT_CHAT_MODEL, type ErrorEnvelope, type GeneratedImage, type ImageGenerationParams, type ImageGenerationResult, Sintaks, SintaksError, type SintaksOptions, Sintaks as default };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
var DEFAULT_BASE_URL = "https://api.sintaks.dev";
|
|
3
|
+
var DEFAULT_CHAT_MODEL = "claude-sonnet-5-5";
|
|
4
|
+
var SintaksError = class extends Error {
|
|
5
|
+
status;
|
|
6
|
+
type;
|
|
7
|
+
code;
|
|
8
|
+
requestId;
|
|
9
|
+
constructor(status, message, opts = {}) {
|
|
10
|
+
super(message);
|
|
11
|
+
this.name = "SintaksError";
|
|
12
|
+
this.status = status;
|
|
13
|
+
this.type = opts.type;
|
|
14
|
+
this.code = opts.code ?? null;
|
|
15
|
+
this.requestId = opts.requestId ?? null;
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
var Sintaks = class {
|
|
19
|
+
apiKey;
|
|
20
|
+
baseURL;
|
|
21
|
+
chat;
|
|
22
|
+
images;
|
|
23
|
+
/** @internal */
|
|
24
|
+
fetchFn;
|
|
25
|
+
/** @internal */
|
|
26
|
+
extraHeaders;
|
|
27
|
+
constructor(options) {
|
|
28
|
+
if (!options.apiKey) throw new Error("Sintaks: apiKey is required");
|
|
29
|
+
this.apiKey = options.apiKey;
|
|
30
|
+
this.baseURL = (options.baseURL ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
31
|
+
this.fetchFn = options.fetch ?? fetch;
|
|
32
|
+
this.extraHeaders = options.headers ?? {};
|
|
33
|
+
this.chat = new ChatResource(this);
|
|
34
|
+
this.images = new ImagesResource(this);
|
|
35
|
+
}
|
|
36
|
+
async request(method, path, body) {
|
|
37
|
+
const res = await this.fetchFn(`${this.baseURL}${path}`, {
|
|
38
|
+
method,
|
|
39
|
+
headers: {
|
|
40
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
41
|
+
"Content-Type": "application/json",
|
|
42
|
+
...this.extraHeaders
|
|
43
|
+
},
|
|
44
|
+
body: body === void 0 ? void 0 : JSON.stringify(body)
|
|
45
|
+
});
|
|
46
|
+
if (!res.ok) {
|
|
47
|
+
let envelope = {};
|
|
48
|
+
try {
|
|
49
|
+
envelope = await res.json();
|
|
50
|
+
} catch {
|
|
51
|
+
}
|
|
52
|
+
throw new SintaksError(res.status, envelope.error?.message ?? `request failed with ${res.status}`, {
|
|
53
|
+
type: envelope.error?.type,
|
|
54
|
+
code: envelope.error?.code,
|
|
55
|
+
requestId: res.headers.get("x-request-id")
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
return await res.json();
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
var ChatResource = class {
|
|
62
|
+
constructor(client) {
|
|
63
|
+
this.client = client;
|
|
64
|
+
}
|
|
65
|
+
client;
|
|
66
|
+
completions = this;
|
|
67
|
+
async create(params) {
|
|
68
|
+
if (params.stream) {
|
|
69
|
+
return this.createStream(params);
|
|
70
|
+
}
|
|
71
|
+
return this.client.request("POST", "/v1/chat/completions", {
|
|
72
|
+
...params,
|
|
73
|
+
model: params.model ?? DEFAULT_CHAT_MODEL
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
async createStream(params) {
|
|
77
|
+
const res = await this.client.fetchFn(`${this.client.baseURL}/v1/chat/completions`, {
|
|
78
|
+
method: "POST",
|
|
79
|
+
headers: {
|
|
80
|
+
Authorization: `Bearer ${this.client.apiKey}`,
|
|
81
|
+
"Content-Type": "application/json",
|
|
82
|
+
Accept: "text/event-stream",
|
|
83
|
+
...this.client.extraHeaders
|
|
84
|
+
},
|
|
85
|
+
body: JSON.stringify({ ...params, model: params.model ?? DEFAULT_CHAT_MODEL })
|
|
86
|
+
});
|
|
87
|
+
if (!res.ok || !res.body) {
|
|
88
|
+
let envelope = {};
|
|
89
|
+
try {
|
|
90
|
+
envelope = await res.json();
|
|
91
|
+
} catch {
|
|
92
|
+
}
|
|
93
|
+
throw new SintaksError(res.status, envelope.error?.message ?? `request failed with ${res.status}`, {
|
|
94
|
+
type: envelope.error?.type,
|
|
95
|
+
code: envelope.error?.code,
|
|
96
|
+
requestId: res.headers.get("x-request-id")
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
return parseSSE(res.body);
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
async function* parseSSE(body) {
|
|
103
|
+
const reader = body.getReader();
|
|
104
|
+
const decoder = new TextDecoder();
|
|
105
|
+
let buffer = "";
|
|
106
|
+
try {
|
|
107
|
+
while (true) {
|
|
108
|
+
const { done, value } = await reader.read();
|
|
109
|
+
if (done) break;
|
|
110
|
+
buffer += decoder.decode(value, { stream: true });
|
|
111
|
+
let boundary;
|
|
112
|
+
while ((boundary = buffer.indexOf("\n\n")) !== -1) {
|
|
113
|
+
const chunk = buffer.slice(0, boundary);
|
|
114
|
+
buffer = buffer.slice(boundary + 2);
|
|
115
|
+
const dataLine = chunk.split("\n").find((line) => line.startsWith("data:"));
|
|
116
|
+
if (!dataLine) continue;
|
|
117
|
+
const payload = dataLine.slice(5).trim();
|
|
118
|
+
if (payload === "[DONE]") return;
|
|
119
|
+
try {
|
|
120
|
+
yield JSON.parse(payload);
|
|
121
|
+
} catch {
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
} finally {
|
|
126
|
+
reader.releaseLock();
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
var ImagesResource = class {
|
|
130
|
+
constructor(client) {
|
|
131
|
+
this.client = client;
|
|
132
|
+
}
|
|
133
|
+
client;
|
|
134
|
+
async generate(params) {
|
|
135
|
+
return this.client.request("POST", "/v1/images/generations", params);
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
var index_default = Sintaks;
|
|
139
|
+
export {
|
|
140
|
+
DEFAULT_BASE_URL,
|
|
141
|
+
DEFAULT_CHAT_MODEL,
|
|
142
|
+
Sintaks,
|
|
143
|
+
SintaksError,
|
|
144
|
+
index_default as default
|
|
145
|
+
};
|
|
146
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * @sintaksdev/sdk — TypeScript client for the sintaks.dev OpenAI-compatible\n * AI API gateway. Zero runtime dependencies; requires Node >= 18 (global fetch).\n */\n\nexport const DEFAULT_BASE_URL = \"https://api.sintaks.dev\";\nexport const DEFAULT_CHAT_MODEL = \"claude-sonnet-5-5\";\n\n/* ------------------------------------------------------------------ */\n/* Types (OpenAI-compatible shapes) */\n/* ------------------------------------------------------------------ */\n\nexport interface ChatMessage {\n role: \"system\" | \"user\" | \"assistant\" | \"tool\";\n content: string;\n name?: string;\n}\n\nexport interface ChatCompletionCreateParams {\n model?: string;\n messages: ChatMessage[];\n stream?: boolean;\n temperature?: number;\n top_p?: number;\n max_tokens?: number;\n stop?: string | string[];\n [key: string]: unknown;\n}\n\nexport interface ChatCompletion {\n id: string;\n object: \"chat.completion\";\n created: number;\n model: string;\n choices: {\n index: number;\n message: ChatMessage;\n finish_reason: string | null;\n }[];\n usage?: {\n prompt_tokens: number;\n completion_tokens: number;\n total_tokens: number;\n };\n}\n\nexport interface ChatCompletionChunk {\n id: string;\n object: \"chat.completion.chunk\";\n created: number;\n model: string;\n choices: {\n index: number;\n delta: { role?: string; content?: string | null };\n finish_reason: string | null;\n }[];\n}\n\nexport interface ImageGenerationParams {\n model?: string;\n prompt: string;\n n?: number;\n size?: string;\n [key: string]: unknown;\n}\n\nexport interface GeneratedImage {\n url?: string;\n b64_json?: string;\n}\n\nexport interface ImageGenerationResult {\n created: number;\n data: GeneratedImage[];\n}\n\nexport interface ErrorEnvelope {\n error?: {\n message?: string;\n type?: string;\n param?: string | null;\n code?: string | null;\n };\n}\n\n/* ------------------------------------------------------------------ */\n/* Error */\n/* ------------------------------------------------------------------ */\n\nexport class SintaksError extends Error {\n readonly status: number;\n readonly type: string | undefined;\n readonly code: string | null;\n readonly requestId: string | null;\n\n constructor(\n status: number,\n message: string,\n opts: { type?: string; code?: string | null; requestId?: string | null } = {},\n ) {\n super(message);\n this.name = \"SintaksError\";\n this.status = status;\n this.type = opts.type;\n this.code = opts.code ?? null;\n this.requestId = opts.requestId ?? null;\n }\n}\n\n/* ------------------------------------------------------------------ */\n/* Client */\n/* ------------------------------------------------------------------ */\n\nexport interface SintaksOptions {\n apiKey: string;\n baseURL?: string;\n fetch?: typeof fetch;\n headers?: Record<string, string>;\n}\n\nexport class Sintaks {\n readonly apiKey: string;\n readonly baseURL: string;\n readonly chat: ChatResource;\n readonly images: ImagesResource;\n\n /** @internal */\n readonly fetchFn: typeof fetch;\n /** @internal */\n readonly extraHeaders: Record<string, string>;\n\n constructor(options: SintaksOptions) {\n if (!options.apiKey) throw new Error(\"Sintaks: apiKey is required\");\n this.apiKey = options.apiKey;\n this.baseURL = (options.baseURL ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.fetchFn = options.fetch ?? fetch;\n this.extraHeaders = options.headers ?? {};\n this.chat = new ChatResource(this);\n this.images = new ImagesResource(this);\n }\n\n async request<T>(method: string, path: string, body?: unknown): Promise<T> {\n const res = await this.fetchFn(`${this.baseURL}${path}`, {\n method,\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n \"Content-Type\": \"application/json\",\n ...this.extraHeaders,\n },\n body: body === undefined ? undefined : JSON.stringify(body),\n });\n\n if (!res.ok) {\n let envelope: ErrorEnvelope = {};\n try {\n envelope = (await res.json()) as ErrorEnvelope;\n } catch {\n // non-JSON error body; fall through with defaults\n }\n throw new SintaksError(res.status, envelope.error?.message ?? `request failed with ${res.status}`, {\n type: envelope.error?.type,\n code: envelope.error?.code,\n requestId: res.headers.get(\"x-request-id\"),\n });\n }\n return (await res.json()) as T;\n }\n}\n\n/* ------------------------------------------------------------------ */\n/* Chat */\n/* ------------------------------------------------------------------ */\n\nclass ChatResource {\n readonly completions = this;\n\n constructor(private client: Sintaks) {}\n\n async create(params: ChatCompletionCreateParams): Promise<ChatCompletion>;\n async create(params: ChatCompletionCreateParams & { stream: true }): Promise<AsyncIterable<ChatCompletionChunk>>;\n async create(\n params: ChatCompletionCreateParams,\n ): Promise<ChatCompletion | AsyncIterable<ChatCompletionChunk>> {\n if (params.stream) {\n return this.createStream(params as ChatCompletionCreateParams & { stream: true });\n }\n return this.client.request<ChatCompletion>(\"POST\", \"/v1/chat/completions\", {\n ...params,\n model: params.model ?? DEFAULT_CHAT_MODEL,\n });\n }\n\n private async createStream(\n params: ChatCompletionCreateParams & { stream: true },\n ): Promise<AsyncIterable<ChatCompletionChunk>> {\n const res = await this.client.fetchFn(`${this.client.baseURL}/v1/chat/completions`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.client.apiKey}`,\n \"Content-Type\": \"application/json\",\n Accept: \"text/event-stream\",\n ...this.client.extraHeaders,\n },\n body: JSON.stringify({ ...params, model: params.model ?? DEFAULT_CHAT_MODEL }),\n });\n\n if (!res.ok || !res.body) {\n let envelope: ErrorEnvelope = {};\n try {\n envelope = (await res.json()) as ErrorEnvelope;\n } catch {\n // ignore\n }\n throw new SintaksError(res.status, envelope.error?.message ?? `request failed with ${res.status}`, {\n type: envelope.error?.type,\n code: envelope.error?.code,\n requestId: res.headers.get(\"x-request-id\"),\n });\n }\n\n return parseSSE<ChatCompletionChunk>(res.body);\n }\n}\n\n/** Minimal SSE parser for OpenAI-style `data:` events. */\nasync function* parseSSE<T>(body: ReadableStream<Uint8Array>): AsyncIterable<T> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n\n let boundary: number;\n while ((boundary = buffer.indexOf(\"\\n\\n\")) !== -1) {\n const chunk = buffer.slice(0, boundary);\n buffer = buffer.slice(boundary + 2);\n const dataLine = chunk\n .split(\"\\n\")\n .find((line) => line.startsWith(\"data:\"));\n if (!dataLine) continue;\n const payload = dataLine.slice(5).trim();\n if (payload === \"[DONE]\") return;\n try {\n yield JSON.parse(payload) as T;\n } catch {\n // skip malformed event\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n}\n\n/* ------------------------------------------------------------------ */\n/* Images */\n/* ------------------------------------------------------------------ */\n\nclass ImagesResource {\n constructor(private client: Sintaks) {}\n\n async generate(params: ImageGenerationParams): Promise<ImageGenerationResult> {\n return this.client.request<ImageGenerationResult>(\"POST\", \"/v1/images/generations\", params);\n }\n}\n\nexport default Sintaks;"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,51 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sintaksdev/sdk",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "TypeScript client for the sintaks.dev OpenAI-compatible AI API gateway. Top up in IDR, call chat and image models, pay per request.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.cjs",
|
|
8
|
+
"module": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.js",
|
|
14
|
+
"require": "./dist/index.cjs"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist"
|
|
19
|
+
],
|
|
20
|
+
"sideEffects": false,
|
|
21
|
+
"engines": {
|
|
22
|
+
"node": ">=18"
|
|
23
|
+
},
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "tsup",
|
|
26
|
+
"typecheck": "tsc --noEmit",
|
|
27
|
+
"prepublishOnly": "pnpm build"
|
|
28
|
+
},
|
|
29
|
+
"keywords": [
|
|
30
|
+
"openai",
|
|
31
|
+
"sintaks",
|
|
32
|
+
"ai",
|
|
33
|
+
"api",
|
|
34
|
+
"llm",
|
|
35
|
+
"indonesia",
|
|
36
|
+
"qris"
|
|
37
|
+
],
|
|
38
|
+
"repository": {
|
|
39
|
+
"type": "git",
|
|
40
|
+
"url": "git+https://github.com/rendies/sintaks-dev-sdk-js.git"
|
|
41
|
+
},
|
|
42
|
+
"publishConfig": {
|
|
43
|
+
"access": "public"
|
|
44
|
+
},
|
|
45
|
+
"packageManager": "pnpm@10.29.3",
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@types/node": "^26.6.5",
|
|
48
|
+
"tsup": "^8.5.1",
|
|
49
|
+
"typescript": "^5.9.3"
|
|
50
|
+
}
|
|
51
|
+
}
|