@inferall/sdk 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/LICENSE +21 -0
- package/README.md +134 -0
- package/dist/index.cjs +238 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +168 -0
- package/dist/index.d.ts +168 -0
- package/dist/index.js +208 -0
- package/dist/index.js.map +1 -0
- package/package.json +65 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Kindly Robotics
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# @inferall/sdk
|
|
2
|
+
|
|
3
|
+
Official TypeScript SDK for the [InferAll](https://inferall.ai) AI gateway. One
|
|
4
|
+
API, every model provider — OpenAI, Anthropic, Google Gemini, Replicate, and
|
|
5
|
+
more — behind a single bearer token.
|
|
6
|
+
|
|
7
|
+
This is the TypeScript counterpart to the [`inferall-ai`](https://pypi.org/project/inferall-ai/)
|
|
8
|
+
Python package and mirrors its surface one-to-one.
|
|
9
|
+
|
|
10
|
+
> Zero runtime dependencies. The client uses only the platform `fetch` API, so
|
|
11
|
+
> it ships cleanly into Node, edge functions, and browsers. ESM, CJS, and full
|
|
12
|
+
> type declarations are all bundled.
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install @inferall/sdk
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Requires Node 18+ (or any runtime with a global `fetch`).
|
|
21
|
+
|
|
22
|
+
## Quick start
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
import { Inferall } from "@inferall/sdk";
|
|
26
|
+
|
|
27
|
+
const ai = new Inferall(); // reads INFERALL_API_KEY from the environment
|
|
28
|
+
|
|
29
|
+
console.log(await ai.text("Summarize the theory of relativity in two sentences."));
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Explicit credentials
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
const ai = new Inferall({ apiKey: "sk-inferall-..." });
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### System prompt + custom model
|
|
39
|
+
|
|
40
|
+
```ts
|
|
41
|
+
await ai.text("Translate to French: 'Where is the library?'", {
|
|
42
|
+
system: "You are a careful translator.",
|
|
43
|
+
provider: "openai",
|
|
44
|
+
model: "gpt-4o-mini",
|
|
45
|
+
temperature: 0.2,
|
|
46
|
+
});
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Multi-turn chat
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
await ai.chat([
|
|
53
|
+
{ role: "user", content: "Hello!" },
|
|
54
|
+
{ role: "assistant", content: "Hi there — how can I help?" },
|
|
55
|
+
{ role: "user", content: "What's 2 + 2?" },
|
|
56
|
+
]);
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Vision
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
import { readFile } from "node:fs/promises";
|
|
63
|
+
|
|
64
|
+
const imageBase64 = (await readFile("receipt.jpg")).toString("base64");
|
|
65
|
+
|
|
66
|
+
await ai.vision(imageBase64, "What's the total on this receipt?");
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Raw responses
|
|
70
|
+
|
|
71
|
+
When you need access to tool calls, automatic-fallback metadata
|
|
72
|
+
(`fallback_used` / `actual_provider`), or any provider-specific field, use
|
|
73
|
+
`generate()` to get the full payload:
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
const raw = await ai.generate({
|
|
77
|
+
provider: "anthropic",
|
|
78
|
+
model: "claude-3-5-sonnet-latest",
|
|
79
|
+
operation: "chat",
|
|
80
|
+
messages: [{ role: "user", content: "..." }],
|
|
81
|
+
});
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Environment variables
|
|
85
|
+
|
|
86
|
+
| Variable | Purpose |
|
|
87
|
+
| ------------------- | ------------------------------------------------------------------- |
|
|
88
|
+
| `INFERALL_API_KEY` | Bearer token. Used when `apiKey` isn't passed to the constructor. |
|
|
89
|
+
| `INFERALL_BASE_URL` | Override the gateway URL (default `https://api.inferall.ai`). |
|
|
90
|
+
| `AI_GATEWAY_KEY` | Legacy fallback for `INFERALL_API_KEY` (recognised for back-compat).|
|
|
91
|
+
| `AI_GATEWAY_URL` | Legacy fallback for `INFERALL_BASE_URL`. |
|
|
92
|
+
|
|
93
|
+
Environment variables are only read in runtimes that expose `process.env` (Node,
|
|
94
|
+
most edge functions). In the browser, pass `apiKey` / `baseURL` explicitly.
|
|
95
|
+
|
|
96
|
+
## Errors
|
|
97
|
+
|
|
98
|
+
Gateway failures throw `InferallError`. A `status` of `0` indicates a
|
|
99
|
+
transport-level failure (network error or timeout) rather than an HTTP error
|
|
100
|
+
response.
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
import { Inferall, InferallError } from "@inferall/sdk";
|
|
104
|
+
|
|
105
|
+
const ai = new Inferall();
|
|
106
|
+
try {
|
|
107
|
+
await ai.text("...");
|
|
108
|
+
} catch (err) {
|
|
109
|
+
if (err instanceof InferallError) {
|
|
110
|
+
console.error(err.status, err.body);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Python ↔ TypeScript
|
|
116
|
+
|
|
117
|
+
| Python (`inferall-ai`) | TypeScript (`@inferall/sdk`) |
|
|
118
|
+
| ---------------------------------- | ------------------------------------------- |
|
|
119
|
+
| `from inferall import Inferall` | `import { Inferall } from "@inferall/sdk"` |
|
|
120
|
+
| `Inferall(api_key=...)` | `new Inferall({ apiKey: ... })` |
|
|
121
|
+
| `ai.text(prompt, system=...)` | `ai.text(prompt, { system: ... })` |
|
|
122
|
+
| `ai.chat(messages)` | `ai.chat(messages)` |
|
|
123
|
+
| `ai.vision(img_b64, prompt)` | `ai.vision(imgBase64, prompt)` |
|
|
124
|
+
| `ai.generate(provider=..., ...)` | `ai.generate({ provider: ..., ... })` |
|
|
125
|
+
| `InferallError` | `InferallError` |
|
|
126
|
+
|
|
127
|
+
Keyword arguments map to a trailing options object; snake_case parameters become
|
|
128
|
+
camelCase (`max_tokens` → `maxTokens`, `base_url` → `baseURL`). Behaviour
|
|
129
|
+
(defaults, env-var resolution, the `/ai/v1/generate` route, and response
|
|
130
|
+
normalization) is identical.
|
|
131
|
+
|
|
132
|
+
## License
|
|
133
|
+
|
|
134
|
+
MIT
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,238 @@
|
|
|
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_MODEL: () => DEFAULT_MODEL,
|
|
25
|
+
DEFAULT_PROVIDER: () => DEFAULT_PROVIDER,
|
|
26
|
+
Inferall: () => Inferall,
|
|
27
|
+
InferallError: () => InferallError,
|
|
28
|
+
VERSION: () => VERSION,
|
|
29
|
+
default: () => index_default
|
|
30
|
+
});
|
|
31
|
+
module.exports = __toCommonJS(index_exports);
|
|
32
|
+
var DEFAULT_BASE_URL = "https://api.inferall.ai";
|
|
33
|
+
var DEFAULT_PROVIDER = "gemini";
|
|
34
|
+
var DEFAULT_MODEL = "gemini-2.5-flash";
|
|
35
|
+
var VERSION = "0.1.0";
|
|
36
|
+
var USER_AGENT = `inferall-typescript/${VERSION}`;
|
|
37
|
+
var InferallError = class _InferallError extends Error {
|
|
38
|
+
constructor(status, body) {
|
|
39
|
+
super(`InferAll gateway returned ${status}: ${body}`);
|
|
40
|
+
this.name = "InferallError";
|
|
41
|
+
this.status = status;
|
|
42
|
+
this.body = body;
|
|
43
|
+
Object.setPrototypeOf(this, _InferallError.prototype);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
function readEnv(name) {
|
|
47
|
+
const proc = globalThis.process;
|
|
48
|
+
return proc?.env?.[name];
|
|
49
|
+
}
|
|
50
|
+
function resolveApiKey(apiKey) {
|
|
51
|
+
if (apiKey) return apiKey;
|
|
52
|
+
return readEnv("INFERALL_API_KEY") || readEnv("AI_GATEWAY_KEY") || "";
|
|
53
|
+
}
|
|
54
|
+
function resolveBaseURL(baseURL) {
|
|
55
|
+
if (baseURL) return baseURL.replace(/\/+$/, "");
|
|
56
|
+
const env = readEnv("INFERALL_BASE_URL") || readEnv("AI_GATEWAY_URL");
|
|
57
|
+
return (env || DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
58
|
+
}
|
|
59
|
+
var Inferall = class _Inferall {
|
|
60
|
+
constructor(options = {}) {
|
|
61
|
+
this.apiKey = resolveApiKey(options.apiKey);
|
|
62
|
+
this.baseURL = resolveBaseURL(options.baseURL);
|
|
63
|
+
this.defaultProvider = options.defaultProvider ?? DEFAULT_PROVIDER;
|
|
64
|
+
this.defaultModel = options.defaultModel ?? DEFAULT_MODEL;
|
|
65
|
+
this.timeout = options.timeout ?? 12e4;
|
|
66
|
+
}
|
|
67
|
+
// ---------------------------------------------------------------- public
|
|
68
|
+
/** Single-turn text completion. Prompt in, string out. */
|
|
69
|
+
async text(prompt, options = {}) {
|
|
70
|
+
const resp = await this.request({
|
|
71
|
+
provider: options.provider || this.defaultProvider,
|
|
72
|
+
model: options.model || this.defaultModel,
|
|
73
|
+
operation: "text",
|
|
74
|
+
messages: [{ role: "user", content: prompt }],
|
|
75
|
+
system: options.system,
|
|
76
|
+
temperature: options.temperature ?? 0.3,
|
|
77
|
+
maxTokens: options.maxTokens ?? 4096
|
|
78
|
+
});
|
|
79
|
+
return _Inferall.extractText(resp);
|
|
80
|
+
}
|
|
81
|
+
/** Multi-turn chat completion. Returns the assistant's response text. */
|
|
82
|
+
async chat(messages, options = {}) {
|
|
83
|
+
const resp = await this.request({
|
|
84
|
+
provider: options.provider || this.defaultProvider,
|
|
85
|
+
model: options.model || this.defaultModel,
|
|
86
|
+
operation: "chat",
|
|
87
|
+
messages,
|
|
88
|
+
system: options.system,
|
|
89
|
+
temperature: options.temperature ?? 0.3,
|
|
90
|
+
maxTokens: options.maxTokens ?? 4096
|
|
91
|
+
});
|
|
92
|
+
return _Inferall.extractText(resp);
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Analyze an image (base64-encoded) with a text prompt.
|
|
96
|
+
*
|
|
97
|
+
* Resolves `provider` and `model` from the client's defaults so that
|
|
98
|
+
* `new Inferall({ defaultProvider: "openai" }).vision(...)` actually routes
|
|
99
|
+
* to OpenAI. Falls back to gemini-2.5-flash only when no default is set.
|
|
100
|
+
*/
|
|
101
|
+
async vision(imageBase64, prompt, options = {}) {
|
|
102
|
+
const resp = await this.request({
|
|
103
|
+
provider: options.provider || this.defaultProvider || "gemini",
|
|
104
|
+
model: options.model || this.defaultModel || "gemini-2.5-flash",
|
|
105
|
+
operation: "image-analyze",
|
|
106
|
+
messages: [{ role: "user", content: prompt }],
|
|
107
|
+
images: [imageBase64],
|
|
108
|
+
temperature: 0.3,
|
|
109
|
+
maxTokens: options.maxTokens ?? 4096
|
|
110
|
+
});
|
|
111
|
+
return _Inferall.extractText(resp);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Escape hatch — return the raw, provider-shaped response payload.
|
|
115
|
+
*
|
|
116
|
+
* Use this when you need access to tool calls, fallback metadata
|
|
117
|
+
* (`fallback_used` / `actual_provider`), streaming chunks, or any
|
|
118
|
+
* provider-specific field that the convenience helpers ({@link text},
|
|
119
|
+
* {@link chat}, {@link vision}) strip out.
|
|
120
|
+
*/
|
|
121
|
+
async generate(options = {}) {
|
|
122
|
+
return this.request({
|
|
123
|
+
provider: options.provider || this.defaultProvider,
|
|
124
|
+
model: options.model || this.defaultModel,
|
|
125
|
+
operation: options.operation ?? "text",
|
|
126
|
+
messages: options.messages,
|
|
127
|
+
system: options.system,
|
|
128
|
+
images: options.images,
|
|
129
|
+
prompt: options.prompt,
|
|
130
|
+
temperature: options.temperature ?? 0.3,
|
|
131
|
+
maxTokens: options.maxTokens ?? 4096
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
// -------------------------------------------------------------- internal
|
|
135
|
+
async request(args) {
|
|
136
|
+
if (!this.apiKey) {
|
|
137
|
+
throw new Error(
|
|
138
|
+
"InferAll API key not set. Pass { apiKey } to the constructor or set the INFERALL_API_KEY environment variable (legacy AI_GATEWAY_KEY is also accepted as a fallback)."
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
const body = {
|
|
142
|
+
provider: args.provider,
|
|
143
|
+
model: args.model,
|
|
144
|
+
operation: args.operation,
|
|
145
|
+
config: { temperature: args.temperature, maxTokens: args.maxTokens }
|
|
146
|
+
};
|
|
147
|
+
if (args.messages && args.messages.length > 0) body.messages = args.messages;
|
|
148
|
+
if (args.system) body.system = args.system;
|
|
149
|
+
if (args.images && args.images.length > 0) body.images = args.images;
|
|
150
|
+
if (args.prompt) body.prompt = args.prompt;
|
|
151
|
+
const controller = new AbortController();
|
|
152
|
+
const timer = setTimeout(() => controller.abort(), this.timeout);
|
|
153
|
+
let response;
|
|
154
|
+
try {
|
|
155
|
+
response = await fetch(`${this.baseURL}/ai/v1/generate`, {
|
|
156
|
+
method: "POST",
|
|
157
|
+
headers: {
|
|
158
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
159
|
+
"Content-Type": "application/json",
|
|
160
|
+
"User-Agent": USER_AGENT
|
|
161
|
+
},
|
|
162
|
+
body: JSON.stringify(body),
|
|
163
|
+
signal: controller.signal
|
|
164
|
+
});
|
|
165
|
+
} catch (err) {
|
|
166
|
+
if (err instanceof DOMException && err.name === "AbortError") {
|
|
167
|
+
throw new InferallError(0, `Request timed out after ${this.timeout}ms`);
|
|
168
|
+
}
|
|
169
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
170
|
+
throw new InferallError(0, `Network error: ${reason}`);
|
|
171
|
+
} finally {
|
|
172
|
+
clearTimeout(timer);
|
|
173
|
+
}
|
|
174
|
+
if (!response.ok) {
|
|
175
|
+
const errorBody = await response.text().catch(() => "");
|
|
176
|
+
throw new InferallError(response.status, errorBody);
|
|
177
|
+
}
|
|
178
|
+
try {
|
|
179
|
+
return await response.json();
|
|
180
|
+
} catch (err) {
|
|
181
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
182
|
+
throw new InferallError(0, `Failed to parse gateway response: ${reason}`);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Extract text from any supported provider's response format.
|
|
187
|
+
*
|
|
188
|
+
* For providers that return multiple text segments in a single response
|
|
189
|
+
* (Gemini `parts`, Anthropic `content` blocks), all text segments are
|
|
190
|
+
* concatenated with newlines so callers see the full message rather than a
|
|
191
|
+
* silently-truncated first chunk.
|
|
192
|
+
*
|
|
193
|
+
* Throws {@link InferallError} if the response does not match any recognized
|
|
194
|
+
* shape — we never coerce arbitrary JSON into a string.
|
|
195
|
+
*/
|
|
196
|
+
static extractText(resp) {
|
|
197
|
+
const candidates = resp["candidates"];
|
|
198
|
+
if (Array.isArray(candidates) && candidates.length > 0) {
|
|
199
|
+
const parts = candidates[0]?.["content"];
|
|
200
|
+
const partList = parts?.["parts"];
|
|
201
|
+
if (Array.isArray(partList)) {
|
|
202
|
+
const texts = partList.filter((p) => isRecord(p) && typeof p["text"] === "string").map((p) => p["text"]);
|
|
203
|
+
if (texts.length > 0) return texts.join("\n");
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
const choices = resp["choices"];
|
|
207
|
+
if (Array.isArray(choices) && choices.length > 0) {
|
|
208
|
+
const message = choices[0]?.["message"];
|
|
209
|
+
const content2 = message?.["content"];
|
|
210
|
+
return typeof content2 === "string" ? content2 : "";
|
|
211
|
+
}
|
|
212
|
+
const content = resp["content"];
|
|
213
|
+
if (Array.isArray(content)) {
|
|
214
|
+
const texts = content.filter((block) => isRecord(block) && Boolean(block["text"])).map((block) => block["text"]);
|
|
215
|
+
if (texts.length > 0) return texts.join("\n");
|
|
216
|
+
}
|
|
217
|
+
const output = resp["output"];
|
|
218
|
+
if (typeof output === "string") return output;
|
|
219
|
+
if (Array.isArray(output) && output.length > 0 && typeof output[0] === "string") {
|
|
220
|
+
return output[0];
|
|
221
|
+
}
|
|
222
|
+
throw new InferallError(0, `Unrecognized response shape: keys=${JSON.stringify(Object.keys(resp))}`);
|
|
223
|
+
}
|
|
224
|
+
};
|
|
225
|
+
function isRecord(value) {
|
|
226
|
+
return typeof value === "object" && value !== null;
|
|
227
|
+
}
|
|
228
|
+
var index_default = Inferall;
|
|
229
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
230
|
+
0 && (module.exports = {
|
|
231
|
+
DEFAULT_BASE_URL,
|
|
232
|
+
DEFAULT_MODEL,
|
|
233
|
+
DEFAULT_PROVIDER,
|
|
234
|
+
Inferall,
|
|
235
|
+
InferallError,
|
|
236
|
+
VERSION
|
|
237
|
+
});
|
|
238
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * InferAll TypeScript client.\n *\n * The {@link Inferall} client speaks to the InferAll gateway over a single HTTP\n * endpoint and normalizes responses across providers (OpenAI, Anthropic, Google\n * Gemini, Replicate, and more).\n *\n * Quick start:\n *\n * ```ts\n * import { Inferall } from \"@inferall/sdk\";\n *\n * const ai = new Inferall(); // picks up INFERALL_API_KEY from the environment\n *\n * console.log(await ai.text(\"Summarize the theory of relativity in two sentences.\"));\n * ```\n *\n * This is a faithful port of the published `inferall-ai` Python package. The\n * client depends only on the platform `fetch` API so it can be dropped into\n * lambdas, edge functions, and browsers without pulling in transitive\n * dependencies.\n */\n\nexport const DEFAULT_BASE_URL = \"https://api.inferall.ai\";\nexport const DEFAULT_PROVIDER = \"gemini\";\nexport const DEFAULT_MODEL = \"gemini-2.5-flash\";\n\n/** Package version, mirrored from package.json. */\nexport const VERSION = \"0.1.0\";\n\nconst USER_AGENT = `inferall-typescript/${VERSION}`;\n\n/**\n * A single chat message. Mirrors the Python SDK's `list[dict]` message shape;\n * arbitrary provider-specific keys are allowed.\n */\nexport interface Message {\n role: string;\n content: unknown;\n [key: string]: unknown;\n}\n\n/** A provider-shaped response payload, as returned by {@link Inferall.generate}. */\nexport type GenerateResponse = Record<string, unknown>;\n\n/** Options for the {@link Inferall} constructor. */\nexport interface InferallOptions {\n /**\n * Bearer token for the gateway. If omitted, the client reads\n * `INFERALL_API_KEY` (preferred) or `AI_GATEWAY_KEY` (legacy) from the\n * environment.\n */\n apiKey?: string;\n /**\n * Override the gateway URL. Defaults to `https://api.inferall.ai`\n * (or `INFERALL_BASE_URL` / `AI_GATEWAY_URL` from the environment).\n */\n baseURL?: string;\n /** Provider used when a call site does not pass `provider`. */\n defaultProvider?: string;\n /** Model used when a call site does not pass `model`. */\n defaultModel?: string;\n /**\n * Per-request timeout, in milliseconds. Defaults to 120000ms (120s) to\n * accommodate large completions.\n */\n timeout?: number;\n}\n\n/** Options for {@link Inferall.text}. */\nexport interface TextOptions {\n system?: string;\n provider?: string;\n model?: string;\n /** @default 0.3 */\n temperature?: number;\n /** @default 4096 */\n maxTokens?: number;\n}\n\n/** Options for {@link Inferall.chat}. */\nexport interface ChatOptions {\n system?: string;\n provider?: string;\n model?: string;\n /** @default 0.3 */\n temperature?: number;\n /** @default 4096 */\n maxTokens?: number;\n}\n\n/** Options for {@link Inferall.vision}. */\nexport interface VisionOptions {\n provider?: string;\n model?: string;\n /** @default 4096 */\n maxTokens?: number;\n}\n\n/** Options for {@link Inferall.generate}. */\nexport interface GenerateOptions {\n provider?: string;\n model?: string;\n /** @default \"text\" */\n operation?: string;\n messages?: Message[];\n system?: string;\n images?: string[];\n prompt?: string;\n /** @default 0.3 */\n temperature?: number;\n /** @default 4096 */\n maxTokens?: number;\n}\n\ninterface RequestBody {\n provider: string;\n model: string;\n operation: string;\n config: { temperature: number; maxTokens: number };\n messages?: Message[];\n system?: string;\n images?: string[];\n prompt?: string;\n}\n\n/**\n * Raised when the InferAll gateway returns an error or the request fails.\n *\n * Mirrors the Python `InferallError` (a subclass of `RuntimeError`). A `status`\n * of `0` indicates a transport-level failure (network error, timeout) rather\n * than an HTTP error response.\n */\nexport class InferallError extends Error {\n readonly status: number;\n readonly body: string;\n\n constructor(status: number, body: string) {\n super(`InferAll gateway returned ${status}: ${body}`);\n this.name = \"InferallError\";\n this.status = status;\n this.body = body;\n // Restore prototype chain for instanceof across transpilation targets.\n Object.setPrototypeOf(this, InferallError.prototype);\n }\n}\n\nfunction readEnv(name: string): string | undefined {\n // Guard against non-Node runtimes (browsers, some edge functions) where\n // `process` is undefined. There the caller must pass apiKey/baseURL explicitly.\n const proc = (globalThis as { process?: { env?: Record<string, string | undefined> } }).process;\n return proc?.env?.[name];\n}\n\n/**\n * Return the API key from the explicit arg or environment.\n *\n * Honors `INFERALL_API_KEY` first, then falls back to `AI_GATEWAY_KEY` for\n * backwards compatibility with the original internal client.\n */\nfunction resolveApiKey(apiKey: string | undefined): string {\n if (apiKey) return apiKey;\n return readEnv(\"INFERALL_API_KEY\") || readEnv(\"AI_GATEWAY_KEY\") || \"\";\n}\n\nfunction resolveBaseURL(baseURL: string | undefined): string {\n if (baseURL) return baseURL.replace(/\\/+$/, \"\");\n const env = readEnv(\"INFERALL_BASE_URL\") || readEnv(\"AI_GATEWAY_URL\");\n return (env || DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n}\n\n/**\n * Client for the InferAll AI gateway.\n *\n * @example\n * ```ts\n * const ai = new Inferall(); // env-based key\n * const ai = new Inferall({ apiKey: \"sk-…\" }); // explicit key\n * ```\n */\nexport class Inferall {\n readonly apiKey: string;\n readonly baseURL: string;\n readonly defaultProvider: string;\n readonly defaultModel: string;\n readonly timeout: number;\n\n constructor(options: InferallOptions = {}) {\n this.apiKey = resolveApiKey(options.apiKey);\n this.baseURL = resolveBaseURL(options.baseURL);\n this.defaultProvider = options.defaultProvider ?? DEFAULT_PROVIDER;\n this.defaultModel = options.defaultModel ?? DEFAULT_MODEL;\n this.timeout = options.timeout ?? 120_000;\n }\n\n // ---------------------------------------------------------------- public\n\n /** Single-turn text completion. Prompt in, string out. */\n async text(prompt: string, options: TextOptions = {}): Promise<string> {\n const resp = await this.request({\n provider: options.provider || this.defaultProvider,\n model: options.model || this.defaultModel,\n operation: \"text\",\n messages: [{ role: \"user\", content: prompt }],\n system: options.system,\n temperature: options.temperature ?? 0.3,\n maxTokens: options.maxTokens ?? 4096,\n });\n return Inferall.extractText(resp);\n }\n\n /** Multi-turn chat completion. Returns the assistant's response text. */\n async chat(messages: Message[], options: ChatOptions = {}): Promise<string> {\n const resp = await this.request({\n provider: options.provider || this.defaultProvider,\n model: options.model || this.defaultModel,\n operation: \"chat\",\n messages,\n system: options.system,\n temperature: options.temperature ?? 0.3,\n maxTokens: options.maxTokens ?? 4096,\n });\n return Inferall.extractText(resp);\n }\n\n /**\n * Analyze an image (base64-encoded) with a text prompt.\n *\n * Resolves `provider` and `model` from the client's defaults so that\n * `new Inferall({ defaultProvider: \"openai\" }).vision(...)` actually routes\n * to OpenAI. Falls back to gemini-2.5-flash only when no default is set.\n */\n async vision(imageBase64: string, prompt: string, options: VisionOptions = {}): Promise<string> {\n const resp = await this.request({\n provider: options.provider || this.defaultProvider || \"gemini\",\n model: options.model || this.defaultModel || \"gemini-2.5-flash\",\n operation: \"image-analyze\",\n messages: [{ role: \"user\", content: prompt }],\n images: [imageBase64],\n temperature: 0.3,\n maxTokens: options.maxTokens ?? 4096,\n });\n return Inferall.extractText(resp);\n }\n\n /**\n * Escape hatch — return the raw, provider-shaped response payload.\n *\n * Use this when you need access to tool calls, fallback metadata\n * (`fallback_used` / `actual_provider`), streaming chunks, or any\n * provider-specific field that the convenience helpers ({@link text},\n * {@link chat}, {@link vision}) strip out.\n */\n async generate(options: GenerateOptions = {}): Promise<GenerateResponse> {\n return this.request({\n provider: options.provider || this.defaultProvider,\n model: options.model || this.defaultModel,\n operation: options.operation ?? \"text\",\n messages: options.messages,\n system: options.system,\n images: options.images,\n prompt: options.prompt,\n temperature: options.temperature ?? 0.3,\n maxTokens: options.maxTokens ?? 4096,\n });\n }\n\n // -------------------------------------------------------------- internal\n\n private async request(args: {\n provider: string;\n model: string;\n operation: string;\n messages?: Message[];\n system?: string;\n images?: string[];\n prompt?: string;\n temperature: number;\n maxTokens: number;\n }): Promise<GenerateResponse> {\n if (!this.apiKey) {\n throw new Error(\n \"InferAll API key not set. Pass { apiKey } to the constructor or set \" +\n \"the INFERALL_API_KEY environment variable \" +\n \"(legacy AI_GATEWAY_KEY is also accepted as a fallback).\"\n );\n }\n\n const body: RequestBody = {\n provider: args.provider,\n model: args.model,\n operation: args.operation,\n config: { temperature: args.temperature, maxTokens: args.maxTokens },\n };\n if (args.messages && args.messages.length > 0) body.messages = args.messages;\n if (args.system) body.system = args.system;\n if (args.images && args.images.length > 0) body.images = args.images;\n if (args.prompt) body.prompt = args.prompt;\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n let response: Response;\n try {\n response = await fetch(`${this.baseURL}/ai/v1/generate`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n \"Content-Type\": \"application/json\",\n \"User-Agent\": USER_AGENT,\n },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n } catch (err) {\n if (err instanceof DOMException && err.name === \"AbortError\") {\n throw new InferallError(0, `Request timed out after ${this.timeout}ms`);\n }\n const reason = err instanceof Error ? err.message : String(err);\n throw new InferallError(0, `Network error: ${reason}`);\n } finally {\n clearTimeout(timer);\n }\n\n if (!response.ok) {\n const errorBody = await response.text().catch(() => \"\");\n throw new InferallError(response.status, errorBody);\n }\n\n try {\n return (await response.json()) as GenerateResponse;\n } catch (err) {\n const reason = err instanceof Error ? err.message : String(err);\n throw new InferallError(0, `Failed to parse gateway response: ${reason}`);\n }\n }\n\n /**\n * Extract text from any supported provider's response format.\n *\n * For providers that return multiple text segments in a single response\n * (Gemini `parts`, Anthropic `content` blocks), all text segments are\n * concatenated with newlines so callers see the full message rather than a\n * silently-truncated first chunk.\n *\n * Throws {@link InferallError} if the response does not match any recognized\n * shape — we never coerce arbitrary JSON into a string.\n */\n static extractText(resp: GenerateResponse): string {\n // Gemini\n const candidates = resp[\"candidates\"];\n if (Array.isArray(candidates) && candidates.length > 0) {\n const parts = (candidates[0] as Record<string, unknown> | undefined)?.[\"content\"];\n const partList = (parts as Record<string, unknown> | undefined)?.[\"parts\"];\n if (Array.isArray(partList)) {\n const texts = partList\n .filter((p): p is Record<string, unknown> => isRecord(p) && typeof p[\"text\"] === \"string\")\n .map((p) => p[\"text\"] as string);\n if (texts.length > 0) return texts.join(\"\\n\");\n }\n }\n\n // OpenAI\n const choices = resp[\"choices\"];\n if (Array.isArray(choices) && choices.length > 0) {\n const message = (choices[0] as Record<string, unknown> | undefined)?.[\"message\"];\n const content = (message as Record<string, unknown> | undefined)?.[\"content\"];\n return typeof content === \"string\" ? content : \"\";\n }\n\n // Anthropic\n const content = resp[\"content\"];\n if (Array.isArray(content)) {\n const texts = content\n .filter((block): block is Record<string, unknown> => isRecord(block) && Boolean(block[\"text\"]))\n .map((block) => block[\"text\"] as string);\n if (texts.length > 0) return texts.join(\"\\n\");\n }\n\n // Replicate\n const output = resp[\"output\"];\n if (typeof output === \"string\") return output;\n if (Array.isArray(output) && output.length > 0 && typeof output[0] === \"string\") {\n return output[0];\n }\n\n throw new InferallError(0, `Unrecognized response shape: keys=${JSON.stringify(Object.keys(resp))}`);\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nexport default Inferall;\n"],"mappings":"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","names":["content"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* InferAll TypeScript client.
|
|
3
|
+
*
|
|
4
|
+
* The {@link Inferall} client speaks to the InferAll gateway over a single HTTP
|
|
5
|
+
* endpoint and normalizes responses across providers (OpenAI, Anthropic, Google
|
|
6
|
+
* Gemini, Replicate, and more).
|
|
7
|
+
*
|
|
8
|
+
* Quick start:
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* import { Inferall } from "@inferall/sdk";
|
|
12
|
+
*
|
|
13
|
+
* const ai = new Inferall(); // picks up INFERALL_API_KEY from the environment
|
|
14
|
+
*
|
|
15
|
+
* console.log(await ai.text("Summarize the theory of relativity in two sentences."));
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* This is a faithful port of the published `inferall-ai` Python package. The
|
|
19
|
+
* client depends only on the platform `fetch` API so it can be dropped into
|
|
20
|
+
* lambdas, edge functions, and browsers without pulling in transitive
|
|
21
|
+
* dependencies.
|
|
22
|
+
*/
|
|
23
|
+
declare const DEFAULT_BASE_URL = "https://api.inferall.ai";
|
|
24
|
+
declare const DEFAULT_PROVIDER = "gemini";
|
|
25
|
+
declare const DEFAULT_MODEL = "gemini-2.5-flash";
|
|
26
|
+
/** Package version, mirrored from package.json. */
|
|
27
|
+
declare const VERSION = "0.1.0";
|
|
28
|
+
/**
|
|
29
|
+
* A single chat message. Mirrors the Python SDK's `list[dict]` message shape;
|
|
30
|
+
* arbitrary provider-specific keys are allowed.
|
|
31
|
+
*/
|
|
32
|
+
interface Message {
|
|
33
|
+
role: string;
|
|
34
|
+
content: unknown;
|
|
35
|
+
[key: string]: unknown;
|
|
36
|
+
}
|
|
37
|
+
/** A provider-shaped response payload, as returned by {@link Inferall.generate}. */
|
|
38
|
+
type GenerateResponse = Record<string, unknown>;
|
|
39
|
+
/** Options for the {@link Inferall} constructor. */
|
|
40
|
+
interface InferallOptions {
|
|
41
|
+
/**
|
|
42
|
+
* Bearer token for the gateway. If omitted, the client reads
|
|
43
|
+
* `INFERALL_API_KEY` (preferred) or `AI_GATEWAY_KEY` (legacy) from the
|
|
44
|
+
* environment.
|
|
45
|
+
*/
|
|
46
|
+
apiKey?: string;
|
|
47
|
+
/**
|
|
48
|
+
* Override the gateway URL. Defaults to `https://api.inferall.ai`
|
|
49
|
+
* (or `INFERALL_BASE_URL` / `AI_GATEWAY_URL` from the environment).
|
|
50
|
+
*/
|
|
51
|
+
baseURL?: string;
|
|
52
|
+
/** Provider used when a call site does not pass `provider`. */
|
|
53
|
+
defaultProvider?: string;
|
|
54
|
+
/** Model used when a call site does not pass `model`. */
|
|
55
|
+
defaultModel?: string;
|
|
56
|
+
/**
|
|
57
|
+
* Per-request timeout, in milliseconds. Defaults to 120000ms (120s) to
|
|
58
|
+
* accommodate large completions.
|
|
59
|
+
*/
|
|
60
|
+
timeout?: number;
|
|
61
|
+
}
|
|
62
|
+
/** Options for {@link Inferall.text}. */
|
|
63
|
+
interface TextOptions {
|
|
64
|
+
system?: string;
|
|
65
|
+
provider?: string;
|
|
66
|
+
model?: string;
|
|
67
|
+
/** @default 0.3 */
|
|
68
|
+
temperature?: number;
|
|
69
|
+
/** @default 4096 */
|
|
70
|
+
maxTokens?: number;
|
|
71
|
+
}
|
|
72
|
+
/** Options for {@link Inferall.chat}. */
|
|
73
|
+
interface ChatOptions {
|
|
74
|
+
system?: string;
|
|
75
|
+
provider?: string;
|
|
76
|
+
model?: string;
|
|
77
|
+
/** @default 0.3 */
|
|
78
|
+
temperature?: number;
|
|
79
|
+
/** @default 4096 */
|
|
80
|
+
maxTokens?: number;
|
|
81
|
+
}
|
|
82
|
+
/** Options for {@link Inferall.vision}. */
|
|
83
|
+
interface VisionOptions {
|
|
84
|
+
provider?: string;
|
|
85
|
+
model?: string;
|
|
86
|
+
/** @default 4096 */
|
|
87
|
+
maxTokens?: number;
|
|
88
|
+
}
|
|
89
|
+
/** Options for {@link Inferall.generate}. */
|
|
90
|
+
interface GenerateOptions {
|
|
91
|
+
provider?: string;
|
|
92
|
+
model?: string;
|
|
93
|
+
/** @default "text" */
|
|
94
|
+
operation?: string;
|
|
95
|
+
messages?: Message[];
|
|
96
|
+
system?: string;
|
|
97
|
+
images?: string[];
|
|
98
|
+
prompt?: string;
|
|
99
|
+
/** @default 0.3 */
|
|
100
|
+
temperature?: number;
|
|
101
|
+
/** @default 4096 */
|
|
102
|
+
maxTokens?: number;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Raised when the InferAll gateway returns an error or the request fails.
|
|
106
|
+
*
|
|
107
|
+
* Mirrors the Python `InferallError` (a subclass of `RuntimeError`). A `status`
|
|
108
|
+
* of `0` indicates a transport-level failure (network error, timeout) rather
|
|
109
|
+
* than an HTTP error response.
|
|
110
|
+
*/
|
|
111
|
+
declare class InferallError extends Error {
|
|
112
|
+
readonly status: number;
|
|
113
|
+
readonly body: string;
|
|
114
|
+
constructor(status: number, body: string);
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Client for the InferAll AI gateway.
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* ```ts
|
|
121
|
+
* const ai = new Inferall(); // env-based key
|
|
122
|
+
* const ai = new Inferall({ apiKey: "sk-…" }); // explicit key
|
|
123
|
+
* ```
|
|
124
|
+
*/
|
|
125
|
+
declare class Inferall {
|
|
126
|
+
readonly apiKey: string;
|
|
127
|
+
readonly baseURL: string;
|
|
128
|
+
readonly defaultProvider: string;
|
|
129
|
+
readonly defaultModel: string;
|
|
130
|
+
readonly timeout: number;
|
|
131
|
+
constructor(options?: InferallOptions);
|
|
132
|
+
/** Single-turn text completion. Prompt in, string out. */
|
|
133
|
+
text(prompt: string, options?: TextOptions): Promise<string>;
|
|
134
|
+
/** Multi-turn chat completion. Returns the assistant's response text. */
|
|
135
|
+
chat(messages: Message[], options?: ChatOptions): Promise<string>;
|
|
136
|
+
/**
|
|
137
|
+
* Analyze an image (base64-encoded) with a text prompt.
|
|
138
|
+
*
|
|
139
|
+
* Resolves `provider` and `model` from the client's defaults so that
|
|
140
|
+
* `new Inferall({ defaultProvider: "openai" }).vision(...)` actually routes
|
|
141
|
+
* to OpenAI. Falls back to gemini-2.5-flash only when no default is set.
|
|
142
|
+
*/
|
|
143
|
+
vision(imageBase64: string, prompt: string, options?: VisionOptions): Promise<string>;
|
|
144
|
+
/**
|
|
145
|
+
* Escape hatch — return the raw, provider-shaped response payload.
|
|
146
|
+
*
|
|
147
|
+
* Use this when you need access to tool calls, fallback metadata
|
|
148
|
+
* (`fallback_used` / `actual_provider`), streaming chunks, or any
|
|
149
|
+
* provider-specific field that the convenience helpers ({@link text},
|
|
150
|
+
* {@link chat}, {@link vision}) strip out.
|
|
151
|
+
*/
|
|
152
|
+
generate(options?: GenerateOptions): Promise<GenerateResponse>;
|
|
153
|
+
private request;
|
|
154
|
+
/**
|
|
155
|
+
* Extract text from any supported provider's response format.
|
|
156
|
+
*
|
|
157
|
+
* For providers that return multiple text segments in a single response
|
|
158
|
+
* (Gemini `parts`, Anthropic `content` blocks), all text segments are
|
|
159
|
+
* concatenated with newlines so callers see the full message rather than a
|
|
160
|
+
* silently-truncated first chunk.
|
|
161
|
+
*
|
|
162
|
+
* Throws {@link InferallError} if the response does not match any recognized
|
|
163
|
+
* shape — we never coerce arbitrary JSON into a string.
|
|
164
|
+
*/
|
|
165
|
+
static extractText(resp: GenerateResponse): string;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export { type ChatOptions, DEFAULT_BASE_URL, DEFAULT_MODEL, DEFAULT_PROVIDER, type GenerateOptions, type GenerateResponse, Inferall, InferallError, type InferallOptions, type Message, type TextOptions, VERSION, type VisionOptions, Inferall as default };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* InferAll TypeScript client.
|
|
3
|
+
*
|
|
4
|
+
* The {@link Inferall} client speaks to the InferAll gateway over a single HTTP
|
|
5
|
+
* endpoint and normalizes responses across providers (OpenAI, Anthropic, Google
|
|
6
|
+
* Gemini, Replicate, and more).
|
|
7
|
+
*
|
|
8
|
+
* Quick start:
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* import { Inferall } from "@inferall/sdk";
|
|
12
|
+
*
|
|
13
|
+
* const ai = new Inferall(); // picks up INFERALL_API_KEY from the environment
|
|
14
|
+
*
|
|
15
|
+
* console.log(await ai.text("Summarize the theory of relativity in two sentences."));
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* This is a faithful port of the published `inferall-ai` Python package. The
|
|
19
|
+
* client depends only on the platform `fetch` API so it can be dropped into
|
|
20
|
+
* lambdas, edge functions, and browsers without pulling in transitive
|
|
21
|
+
* dependencies.
|
|
22
|
+
*/
|
|
23
|
+
declare const DEFAULT_BASE_URL = "https://api.inferall.ai";
|
|
24
|
+
declare const DEFAULT_PROVIDER = "gemini";
|
|
25
|
+
declare const DEFAULT_MODEL = "gemini-2.5-flash";
|
|
26
|
+
/** Package version, mirrored from package.json. */
|
|
27
|
+
declare const VERSION = "0.1.0";
|
|
28
|
+
/**
|
|
29
|
+
* A single chat message. Mirrors the Python SDK's `list[dict]` message shape;
|
|
30
|
+
* arbitrary provider-specific keys are allowed.
|
|
31
|
+
*/
|
|
32
|
+
interface Message {
|
|
33
|
+
role: string;
|
|
34
|
+
content: unknown;
|
|
35
|
+
[key: string]: unknown;
|
|
36
|
+
}
|
|
37
|
+
/** A provider-shaped response payload, as returned by {@link Inferall.generate}. */
|
|
38
|
+
type GenerateResponse = Record<string, unknown>;
|
|
39
|
+
/** Options for the {@link Inferall} constructor. */
|
|
40
|
+
interface InferallOptions {
|
|
41
|
+
/**
|
|
42
|
+
* Bearer token for the gateway. If omitted, the client reads
|
|
43
|
+
* `INFERALL_API_KEY` (preferred) or `AI_GATEWAY_KEY` (legacy) from the
|
|
44
|
+
* environment.
|
|
45
|
+
*/
|
|
46
|
+
apiKey?: string;
|
|
47
|
+
/**
|
|
48
|
+
* Override the gateway URL. Defaults to `https://api.inferall.ai`
|
|
49
|
+
* (or `INFERALL_BASE_URL` / `AI_GATEWAY_URL` from the environment).
|
|
50
|
+
*/
|
|
51
|
+
baseURL?: string;
|
|
52
|
+
/** Provider used when a call site does not pass `provider`. */
|
|
53
|
+
defaultProvider?: string;
|
|
54
|
+
/** Model used when a call site does not pass `model`. */
|
|
55
|
+
defaultModel?: string;
|
|
56
|
+
/**
|
|
57
|
+
* Per-request timeout, in milliseconds. Defaults to 120000ms (120s) to
|
|
58
|
+
* accommodate large completions.
|
|
59
|
+
*/
|
|
60
|
+
timeout?: number;
|
|
61
|
+
}
|
|
62
|
+
/** Options for {@link Inferall.text}. */
|
|
63
|
+
interface TextOptions {
|
|
64
|
+
system?: string;
|
|
65
|
+
provider?: string;
|
|
66
|
+
model?: string;
|
|
67
|
+
/** @default 0.3 */
|
|
68
|
+
temperature?: number;
|
|
69
|
+
/** @default 4096 */
|
|
70
|
+
maxTokens?: number;
|
|
71
|
+
}
|
|
72
|
+
/** Options for {@link Inferall.chat}. */
|
|
73
|
+
interface ChatOptions {
|
|
74
|
+
system?: string;
|
|
75
|
+
provider?: string;
|
|
76
|
+
model?: string;
|
|
77
|
+
/** @default 0.3 */
|
|
78
|
+
temperature?: number;
|
|
79
|
+
/** @default 4096 */
|
|
80
|
+
maxTokens?: number;
|
|
81
|
+
}
|
|
82
|
+
/** Options for {@link Inferall.vision}. */
|
|
83
|
+
interface VisionOptions {
|
|
84
|
+
provider?: string;
|
|
85
|
+
model?: string;
|
|
86
|
+
/** @default 4096 */
|
|
87
|
+
maxTokens?: number;
|
|
88
|
+
}
|
|
89
|
+
/** Options for {@link Inferall.generate}. */
|
|
90
|
+
interface GenerateOptions {
|
|
91
|
+
provider?: string;
|
|
92
|
+
model?: string;
|
|
93
|
+
/** @default "text" */
|
|
94
|
+
operation?: string;
|
|
95
|
+
messages?: Message[];
|
|
96
|
+
system?: string;
|
|
97
|
+
images?: string[];
|
|
98
|
+
prompt?: string;
|
|
99
|
+
/** @default 0.3 */
|
|
100
|
+
temperature?: number;
|
|
101
|
+
/** @default 4096 */
|
|
102
|
+
maxTokens?: number;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Raised when the InferAll gateway returns an error or the request fails.
|
|
106
|
+
*
|
|
107
|
+
* Mirrors the Python `InferallError` (a subclass of `RuntimeError`). A `status`
|
|
108
|
+
* of `0` indicates a transport-level failure (network error, timeout) rather
|
|
109
|
+
* than an HTTP error response.
|
|
110
|
+
*/
|
|
111
|
+
declare class InferallError extends Error {
|
|
112
|
+
readonly status: number;
|
|
113
|
+
readonly body: string;
|
|
114
|
+
constructor(status: number, body: string);
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Client for the InferAll AI gateway.
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* ```ts
|
|
121
|
+
* const ai = new Inferall(); // env-based key
|
|
122
|
+
* const ai = new Inferall({ apiKey: "sk-…" }); // explicit key
|
|
123
|
+
* ```
|
|
124
|
+
*/
|
|
125
|
+
declare class Inferall {
|
|
126
|
+
readonly apiKey: string;
|
|
127
|
+
readonly baseURL: string;
|
|
128
|
+
readonly defaultProvider: string;
|
|
129
|
+
readonly defaultModel: string;
|
|
130
|
+
readonly timeout: number;
|
|
131
|
+
constructor(options?: InferallOptions);
|
|
132
|
+
/** Single-turn text completion. Prompt in, string out. */
|
|
133
|
+
text(prompt: string, options?: TextOptions): Promise<string>;
|
|
134
|
+
/** Multi-turn chat completion. Returns the assistant's response text. */
|
|
135
|
+
chat(messages: Message[], options?: ChatOptions): Promise<string>;
|
|
136
|
+
/**
|
|
137
|
+
* Analyze an image (base64-encoded) with a text prompt.
|
|
138
|
+
*
|
|
139
|
+
* Resolves `provider` and `model` from the client's defaults so that
|
|
140
|
+
* `new Inferall({ defaultProvider: "openai" }).vision(...)` actually routes
|
|
141
|
+
* to OpenAI. Falls back to gemini-2.5-flash only when no default is set.
|
|
142
|
+
*/
|
|
143
|
+
vision(imageBase64: string, prompt: string, options?: VisionOptions): Promise<string>;
|
|
144
|
+
/**
|
|
145
|
+
* Escape hatch — return the raw, provider-shaped response payload.
|
|
146
|
+
*
|
|
147
|
+
* Use this when you need access to tool calls, fallback metadata
|
|
148
|
+
* (`fallback_used` / `actual_provider`), streaming chunks, or any
|
|
149
|
+
* provider-specific field that the convenience helpers ({@link text},
|
|
150
|
+
* {@link chat}, {@link vision}) strip out.
|
|
151
|
+
*/
|
|
152
|
+
generate(options?: GenerateOptions): Promise<GenerateResponse>;
|
|
153
|
+
private request;
|
|
154
|
+
/**
|
|
155
|
+
* Extract text from any supported provider's response format.
|
|
156
|
+
*
|
|
157
|
+
* For providers that return multiple text segments in a single response
|
|
158
|
+
* (Gemini `parts`, Anthropic `content` blocks), all text segments are
|
|
159
|
+
* concatenated with newlines so callers see the full message rather than a
|
|
160
|
+
* silently-truncated first chunk.
|
|
161
|
+
*
|
|
162
|
+
* Throws {@link InferallError} if the response does not match any recognized
|
|
163
|
+
* shape — we never coerce arbitrary JSON into a string.
|
|
164
|
+
*/
|
|
165
|
+
static extractText(resp: GenerateResponse): string;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export { type ChatOptions, DEFAULT_BASE_URL, DEFAULT_MODEL, DEFAULT_PROVIDER, type GenerateOptions, type GenerateResponse, Inferall, InferallError, type InferallOptions, type Message, type TextOptions, VERSION, type VisionOptions, Inferall as default };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
var DEFAULT_BASE_URL = "https://api.inferall.ai";
|
|
3
|
+
var DEFAULT_PROVIDER = "gemini";
|
|
4
|
+
var DEFAULT_MODEL = "gemini-2.5-flash";
|
|
5
|
+
var VERSION = "0.1.0";
|
|
6
|
+
var USER_AGENT = `inferall-typescript/${VERSION}`;
|
|
7
|
+
var InferallError = class _InferallError extends Error {
|
|
8
|
+
constructor(status, body) {
|
|
9
|
+
super(`InferAll gateway returned ${status}: ${body}`);
|
|
10
|
+
this.name = "InferallError";
|
|
11
|
+
this.status = status;
|
|
12
|
+
this.body = body;
|
|
13
|
+
Object.setPrototypeOf(this, _InferallError.prototype);
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
function readEnv(name) {
|
|
17
|
+
const proc = globalThis.process;
|
|
18
|
+
return proc?.env?.[name];
|
|
19
|
+
}
|
|
20
|
+
function resolveApiKey(apiKey) {
|
|
21
|
+
if (apiKey) return apiKey;
|
|
22
|
+
return readEnv("INFERALL_API_KEY") || readEnv("AI_GATEWAY_KEY") || "";
|
|
23
|
+
}
|
|
24
|
+
function resolveBaseURL(baseURL) {
|
|
25
|
+
if (baseURL) return baseURL.replace(/\/+$/, "");
|
|
26
|
+
const env = readEnv("INFERALL_BASE_URL") || readEnv("AI_GATEWAY_URL");
|
|
27
|
+
return (env || DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
28
|
+
}
|
|
29
|
+
var Inferall = class _Inferall {
|
|
30
|
+
constructor(options = {}) {
|
|
31
|
+
this.apiKey = resolveApiKey(options.apiKey);
|
|
32
|
+
this.baseURL = resolveBaseURL(options.baseURL);
|
|
33
|
+
this.defaultProvider = options.defaultProvider ?? DEFAULT_PROVIDER;
|
|
34
|
+
this.defaultModel = options.defaultModel ?? DEFAULT_MODEL;
|
|
35
|
+
this.timeout = options.timeout ?? 12e4;
|
|
36
|
+
}
|
|
37
|
+
// ---------------------------------------------------------------- public
|
|
38
|
+
/** Single-turn text completion. Prompt in, string out. */
|
|
39
|
+
async text(prompt, options = {}) {
|
|
40
|
+
const resp = await this.request({
|
|
41
|
+
provider: options.provider || this.defaultProvider,
|
|
42
|
+
model: options.model || this.defaultModel,
|
|
43
|
+
operation: "text",
|
|
44
|
+
messages: [{ role: "user", content: prompt }],
|
|
45
|
+
system: options.system,
|
|
46
|
+
temperature: options.temperature ?? 0.3,
|
|
47
|
+
maxTokens: options.maxTokens ?? 4096
|
|
48
|
+
});
|
|
49
|
+
return _Inferall.extractText(resp);
|
|
50
|
+
}
|
|
51
|
+
/** Multi-turn chat completion. Returns the assistant's response text. */
|
|
52
|
+
async chat(messages, options = {}) {
|
|
53
|
+
const resp = await this.request({
|
|
54
|
+
provider: options.provider || this.defaultProvider,
|
|
55
|
+
model: options.model || this.defaultModel,
|
|
56
|
+
operation: "chat",
|
|
57
|
+
messages,
|
|
58
|
+
system: options.system,
|
|
59
|
+
temperature: options.temperature ?? 0.3,
|
|
60
|
+
maxTokens: options.maxTokens ?? 4096
|
|
61
|
+
});
|
|
62
|
+
return _Inferall.extractText(resp);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Analyze an image (base64-encoded) with a text prompt.
|
|
66
|
+
*
|
|
67
|
+
* Resolves `provider` and `model` from the client's defaults so that
|
|
68
|
+
* `new Inferall({ defaultProvider: "openai" }).vision(...)` actually routes
|
|
69
|
+
* to OpenAI. Falls back to gemini-2.5-flash only when no default is set.
|
|
70
|
+
*/
|
|
71
|
+
async vision(imageBase64, prompt, options = {}) {
|
|
72
|
+
const resp = await this.request({
|
|
73
|
+
provider: options.provider || this.defaultProvider || "gemini",
|
|
74
|
+
model: options.model || this.defaultModel || "gemini-2.5-flash",
|
|
75
|
+
operation: "image-analyze",
|
|
76
|
+
messages: [{ role: "user", content: prompt }],
|
|
77
|
+
images: [imageBase64],
|
|
78
|
+
temperature: 0.3,
|
|
79
|
+
maxTokens: options.maxTokens ?? 4096
|
|
80
|
+
});
|
|
81
|
+
return _Inferall.extractText(resp);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Escape hatch — return the raw, provider-shaped response payload.
|
|
85
|
+
*
|
|
86
|
+
* Use this when you need access to tool calls, fallback metadata
|
|
87
|
+
* (`fallback_used` / `actual_provider`), streaming chunks, or any
|
|
88
|
+
* provider-specific field that the convenience helpers ({@link text},
|
|
89
|
+
* {@link chat}, {@link vision}) strip out.
|
|
90
|
+
*/
|
|
91
|
+
async generate(options = {}) {
|
|
92
|
+
return this.request({
|
|
93
|
+
provider: options.provider || this.defaultProvider,
|
|
94
|
+
model: options.model || this.defaultModel,
|
|
95
|
+
operation: options.operation ?? "text",
|
|
96
|
+
messages: options.messages,
|
|
97
|
+
system: options.system,
|
|
98
|
+
images: options.images,
|
|
99
|
+
prompt: options.prompt,
|
|
100
|
+
temperature: options.temperature ?? 0.3,
|
|
101
|
+
maxTokens: options.maxTokens ?? 4096
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
// -------------------------------------------------------------- internal
|
|
105
|
+
async request(args) {
|
|
106
|
+
if (!this.apiKey) {
|
|
107
|
+
throw new Error(
|
|
108
|
+
"InferAll API key not set. Pass { apiKey } to the constructor or set the INFERALL_API_KEY environment variable (legacy AI_GATEWAY_KEY is also accepted as a fallback)."
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
const body = {
|
|
112
|
+
provider: args.provider,
|
|
113
|
+
model: args.model,
|
|
114
|
+
operation: args.operation,
|
|
115
|
+
config: { temperature: args.temperature, maxTokens: args.maxTokens }
|
|
116
|
+
};
|
|
117
|
+
if (args.messages && args.messages.length > 0) body.messages = args.messages;
|
|
118
|
+
if (args.system) body.system = args.system;
|
|
119
|
+
if (args.images && args.images.length > 0) body.images = args.images;
|
|
120
|
+
if (args.prompt) body.prompt = args.prompt;
|
|
121
|
+
const controller = new AbortController();
|
|
122
|
+
const timer = setTimeout(() => controller.abort(), this.timeout);
|
|
123
|
+
let response;
|
|
124
|
+
try {
|
|
125
|
+
response = await fetch(`${this.baseURL}/ai/v1/generate`, {
|
|
126
|
+
method: "POST",
|
|
127
|
+
headers: {
|
|
128
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
129
|
+
"Content-Type": "application/json",
|
|
130
|
+
"User-Agent": USER_AGENT
|
|
131
|
+
},
|
|
132
|
+
body: JSON.stringify(body),
|
|
133
|
+
signal: controller.signal
|
|
134
|
+
});
|
|
135
|
+
} catch (err) {
|
|
136
|
+
if (err instanceof DOMException && err.name === "AbortError") {
|
|
137
|
+
throw new InferallError(0, `Request timed out after ${this.timeout}ms`);
|
|
138
|
+
}
|
|
139
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
140
|
+
throw new InferallError(0, `Network error: ${reason}`);
|
|
141
|
+
} finally {
|
|
142
|
+
clearTimeout(timer);
|
|
143
|
+
}
|
|
144
|
+
if (!response.ok) {
|
|
145
|
+
const errorBody = await response.text().catch(() => "");
|
|
146
|
+
throw new InferallError(response.status, errorBody);
|
|
147
|
+
}
|
|
148
|
+
try {
|
|
149
|
+
return await response.json();
|
|
150
|
+
} catch (err) {
|
|
151
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
152
|
+
throw new InferallError(0, `Failed to parse gateway response: ${reason}`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Extract text from any supported provider's response format.
|
|
157
|
+
*
|
|
158
|
+
* For providers that return multiple text segments in a single response
|
|
159
|
+
* (Gemini `parts`, Anthropic `content` blocks), all text segments are
|
|
160
|
+
* concatenated with newlines so callers see the full message rather than a
|
|
161
|
+
* silently-truncated first chunk.
|
|
162
|
+
*
|
|
163
|
+
* Throws {@link InferallError} if the response does not match any recognized
|
|
164
|
+
* shape — we never coerce arbitrary JSON into a string.
|
|
165
|
+
*/
|
|
166
|
+
static extractText(resp) {
|
|
167
|
+
const candidates = resp["candidates"];
|
|
168
|
+
if (Array.isArray(candidates) && candidates.length > 0) {
|
|
169
|
+
const parts = candidates[0]?.["content"];
|
|
170
|
+
const partList = parts?.["parts"];
|
|
171
|
+
if (Array.isArray(partList)) {
|
|
172
|
+
const texts = partList.filter((p) => isRecord(p) && typeof p["text"] === "string").map((p) => p["text"]);
|
|
173
|
+
if (texts.length > 0) return texts.join("\n");
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
const choices = resp["choices"];
|
|
177
|
+
if (Array.isArray(choices) && choices.length > 0) {
|
|
178
|
+
const message = choices[0]?.["message"];
|
|
179
|
+
const content2 = message?.["content"];
|
|
180
|
+
return typeof content2 === "string" ? content2 : "";
|
|
181
|
+
}
|
|
182
|
+
const content = resp["content"];
|
|
183
|
+
if (Array.isArray(content)) {
|
|
184
|
+
const texts = content.filter((block) => isRecord(block) && Boolean(block["text"])).map((block) => block["text"]);
|
|
185
|
+
if (texts.length > 0) return texts.join("\n");
|
|
186
|
+
}
|
|
187
|
+
const output = resp["output"];
|
|
188
|
+
if (typeof output === "string") return output;
|
|
189
|
+
if (Array.isArray(output) && output.length > 0 && typeof output[0] === "string") {
|
|
190
|
+
return output[0];
|
|
191
|
+
}
|
|
192
|
+
throw new InferallError(0, `Unrecognized response shape: keys=${JSON.stringify(Object.keys(resp))}`);
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
function isRecord(value) {
|
|
196
|
+
return typeof value === "object" && value !== null;
|
|
197
|
+
}
|
|
198
|
+
var index_default = Inferall;
|
|
199
|
+
export {
|
|
200
|
+
DEFAULT_BASE_URL,
|
|
201
|
+
DEFAULT_MODEL,
|
|
202
|
+
DEFAULT_PROVIDER,
|
|
203
|
+
Inferall,
|
|
204
|
+
InferallError,
|
|
205
|
+
VERSION,
|
|
206
|
+
index_default as default
|
|
207
|
+
};
|
|
208
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * InferAll TypeScript client.\n *\n * The {@link Inferall} client speaks to the InferAll gateway over a single HTTP\n * endpoint and normalizes responses across providers (OpenAI, Anthropic, Google\n * Gemini, Replicate, and more).\n *\n * Quick start:\n *\n * ```ts\n * import { Inferall } from \"@inferall/sdk\";\n *\n * const ai = new Inferall(); // picks up INFERALL_API_KEY from the environment\n *\n * console.log(await ai.text(\"Summarize the theory of relativity in two sentences.\"));\n * ```\n *\n * This is a faithful port of the published `inferall-ai` Python package. The\n * client depends only on the platform `fetch` API so it can be dropped into\n * lambdas, edge functions, and browsers without pulling in transitive\n * dependencies.\n */\n\nexport const DEFAULT_BASE_URL = \"https://api.inferall.ai\";\nexport const DEFAULT_PROVIDER = \"gemini\";\nexport const DEFAULT_MODEL = \"gemini-2.5-flash\";\n\n/** Package version, mirrored from package.json. */\nexport const VERSION = \"0.1.0\";\n\nconst USER_AGENT = `inferall-typescript/${VERSION}`;\n\n/**\n * A single chat message. Mirrors the Python SDK's `list[dict]` message shape;\n * arbitrary provider-specific keys are allowed.\n */\nexport interface Message {\n role: string;\n content: unknown;\n [key: string]: unknown;\n}\n\n/** A provider-shaped response payload, as returned by {@link Inferall.generate}. */\nexport type GenerateResponse = Record<string, unknown>;\n\n/** Options for the {@link Inferall} constructor. */\nexport interface InferallOptions {\n /**\n * Bearer token for the gateway. If omitted, the client reads\n * `INFERALL_API_KEY` (preferred) or `AI_GATEWAY_KEY` (legacy) from the\n * environment.\n */\n apiKey?: string;\n /**\n * Override the gateway URL. Defaults to `https://api.inferall.ai`\n * (or `INFERALL_BASE_URL` / `AI_GATEWAY_URL` from the environment).\n */\n baseURL?: string;\n /** Provider used when a call site does not pass `provider`. */\n defaultProvider?: string;\n /** Model used when a call site does not pass `model`. */\n defaultModel?: string;\n /**\n * Per-request timeout, in milliseconds. Defaults to 120000ms (120s) to\n * accommodate large completions.\n */\n timeout?: number;\n}\n\n/** Options for {@link Inferall.text}. */\nexport interface TextOptions {\n system?: string;\n provider?: string;\n model?: string;\n /** @default 0.3 */\n temperature?: number;\n /** @default 4096 */\n maxTokens?: number;\n}\n\n/** Options for {@link Inferall.chat}. */\nexport interface ChatOptions {\n system?: string;\n provider?: string;\n model?: string;\n /** @default 0.3 */\n temperature?: number;\n /** @default 4096 */\n maxTokens?: number;\n}\n\n/** Options for {@link Inferall.vision}. */\nexport interface VisionOptions {\n provider?: string;\n model?: string;\n /** @default 4096 */\n maxTokens?: number;\n}\n\n/** Options for {@link Inferall.generate}. */\nexport interface GenerateOptions {\n provider?: string;\n model?: string;\n /** @default \"text\" */\n operation?: string;\n messages?: Message[];\n system?: string;\n images?: string[];\n prompt?: string;\n /** @default 0.3 */\n temperature?: number;\n /** @default 4096 */\n maxTokens?: number;\n}\n\ninterface RequestBody {\n provider: string;\n model: string;\n operation: string;\n config: { temperature: number; maxTokens: number };\n messages?: Message[];\n system?: string;\n images?: string[];\n prompt?: string;\n}\n\n/**\n * Raised when the InferAll gateway returns an error or the request fails.\n *\n * Mirrors the Python `InferallError` (a subclass of `RuntimeError`). A `status`\n * of `0` indicates a transport-level failure (network error, timeout) rather\n * than an HTTP error response.\n */\nexport class InferallError extends Error {\n readonly status: number;\n readonly body: string;\n\n constructor(status: number, body: string) {\n super(`InferAll gateway returned ${status}: ${body}`);\n this.name = \"InferallError\";\n this.status = status;\n this.body = body;\n // Restore prototype chain for instanceof across transpilation targets.\n Object.setPrototypeOf(this, InferallError.prototype);\n }\n}\n\nfunction readEnv(name: string): string | undefined {\n // Guard against non-Node runtimes (browsers, some edge functions) where\n // `process` is undefined. There the caller must pass apiKey/baseURL explicitly.\n const proc = (globalThis as { process?: { env?: Record<string, string | undefined> } }).process;\n return proc?.env?.[name];\n}\n\n/**\n * Return the API key from the explicit arg or environment.\n *\n * Honors `INFERALL_API_KEY` first, then falls back to `AI_GATEWAY_KEY` for\n * backwards compatibility with the original internal client.\n */\nfunction resolveApiKey(apiKey: string | undefined): string {\n if (apiKey) return apiKey;\n return readEnv(\"INFERALL_API_KEY\") || readEnv(\"AI_GATEWAY_KEY\") || \"\";\n}\n\nfunction resolveBaseURL(baseURL: string | undefined): string {\n if (baseURL) return baseURL.replace(/\\/+$/, \"\");\n const env = readEnv(\"INFERALL_BASE_URL\") || readEnv(\"AI_GATEWAY_URL\");\n return (env || DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n}\n\n/**\n * Client for the InferAll AI gateway.\n *\n * @example\n * ```ts\n * const ai = new Inferall(); // env-based key\n * const ai = new Inferall({ apiKey: \"sk-…\" }); // explicit key\n * ```\n */\nexport class Inferall {\n readonly apiKey: string;\n readonly baseURL: string;\n readonly defaultProvider: string;\n readonly defaultModel: string;\n readonly timeout: number;\n\n constructor(options: InferallOptions = {}) {\n this.apiKey = resolveApiKey(options.apiKey);\n this.baseURL = resolveBaseURL(options.baseURL);\n this.defaultProvider = options.defaultProvider ?? DEFAULT_PROVIDER;\n this.defaultModel = options.defaultModel ?? DEFAULT_MODEL;\n this.timeout = options.timeout ?? 120_000;\n }\n\n // ---------------------------------------------------------------- public\n\n /** Single-turn text completion. Prompt in, string out. */\n async text(prompt: string, options: TextOptions = {}): Promise<string> {\n const resp = await this.request({\n provider: options.provider || this.defaultProvider,\n model: options.model || this.defaultModel,\n operation: \"text\",\n messages: [{ role: \"user\", content: prompt }],\n system: options.system,\n temperature: options.temperature ?? 0.3,\n maxTokens: options.maxTokens ?? 4096,\n });\n return Inferall.extractText(resp);\n }\n\n /** Multi-turn chat completion. Returns the assistant's response text. */\n async chat(messages: Message[], options: ChatOptions = {}): Promise<string> {\n const resp = await this.request({\n provider: options.provider || this.defaultProvider,\n model: options.model || this.defaultModel,\n operation: \"chat\",\n messages,\n system: options.system,\n temperature: options.temperature ?? 0.3,\n maxTokens: options.maxTokens ?? 4096,\n });\n return Inferall.extractText(resp);\n }\n\n /**\n * Analyze an image (base64-encoded) with a text prompt.\n *\n * Resolves `provider` and `model` from the client's defaults so that\n * `new Inferall({ defaultProvider: \"openai\" }).vision(...)` actually routes\n * to OpenAI. Falls back to gemini-2.5-flash only when no default is set.\n */\n async vision(imageBase64: string, prompt: string, options: VisionOptions = {}): Promise<string> {\n const resp = await this.request({\n provider: options.provider || this.defaultProvider || \"gemini\",\n model: options.model || this.defaultModel || \"gemini-2.5-flash\",\n operation: \"image-analyze\",\n messages: [{ role: \"user\", content: prompt }],\n images: [imageBase64],\n temperature: 0.3,\n maxTokens: options.maxTokens ?? 4096,\n });\n return Inferall.extractText(resp);\n }\n\n /**\n * Escape hatch — return the raw, provider-shaped response payload.\n *\n * Use this when you need access to tool calls, fallback metadata\n * (`fallback_used` / `actual_provider`), streaming chunks, or any\n * provider-specific field that the convenience helpers ({@link text},\n * {@link chat}, {@link vision}) strip out.\n */\n async generate(options: GenerateOptions = {}): Promise<GenerateResponse> {\n return this.request({\n provider: options.provider || this.defaultProvider,\n model: options.model || this.defaultModel,\n operation: options.operation ?? \"text\",\n messages: options.messages,\n system: options.system,\n images: options.images,\n prompt: options.prompt,\n temperature: options.temperature ?? 0.3,\n maxTokens: options.maxTokens ?? 4096,\n });\n }\n\n // -------------------------------------------------------------- internal\n\n private async request(args: {\n provider: string;\n model: string;\n operation: string;\n messages?: Message[];\n system?: string;\n images?: string[];\n prompt?: string;\n temperature: number;\n maxTokens: number;\n }): Promise<GenerateResponse> {\n if (!this.apiKey) {\n throw new Error(\n \"InferAll API key not set. Pass { apiKey } to the constructor or set \" +\n \"the INFERALL_API_KEY environment variable \" +\n \"(legacy AI_GATEWAY_KEY is also accepted as a fallback).\"\n );\n }\n\n const body: RequestBody = {\n provider: args.provider,\n model: args.model,\n operation: args.operation,\n config: { temperature: args.temperature, maxTokens: args.maxTokens },\n };\n if (args.messages && args.messages.length > 0) body.messages = args.messages;\n if (args.system) body.system = args.system;\n if (args.images && args.images.length > 0) body.images = args.images;\n if (args.prompt) body.prompt = args.prompt;\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n let response: Response;\n try {\n response = await fetch(`${this.baseURL}/ai/v1/generate`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n \"Content-Type\": \"application/json\",\n \"User-Agent\": USER_AGENT,\n },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n } catch (err) {\n if (err instanceof DOMException && err.name === \"AbortError\") {\n throw new InferallError(0, `Request timed out after ${this.timeout}ms`);\n }\n const reason = err instanceof Error ? err.message : String(err);\n throw new InferallError(0, `Network error: ${reason}`);\n } finally {\n clearTimeout(timer);\n }\n\n if (!response.ok) {\n const errorBody = await response.text().catch(() => \"\");\n throw new InferallError(response.status, errorBody);\n }\n\n try {\n return (await response.json()) as GenerateResponse;\n } catch (err) {\n const reason = err instanceof Error ? err.message : String(err);\n throw new InferallError(0, `Failed to parse gateway response: ${reason}`);\n }\n }\n\n /**\n * Extract text from any supported provider's response format.\n *\n * For providers that return multiple text segments in a single response\n * (Gemini `parts`, Anthropic `content` blocks), all text segments are\n * concatenated with newlines so callers see the full message rather than a\n * silently-truncated first chunk.\n *\n * Throws {@link InferallError} if the response does not match any recognized\n * shape — we never coerce arbitrary JSON into a string.\n */\n static extractText(resp: GenerateResponse): string {\n // Gemini\n const candidates = resp[\"candidates\"];\n if (Array.isArray(candidates) && candidates.length > 0) {\n const parts = (candidates[0] as Record<string, unknown> | undefined)?.[\"content\"];\n const partList = (parts as Record<string, unknown> | undefined)?.[\"parts\"];\n if (Array.isArray(partList)) {\n const texts = partList\n .filter((p): p is Record<string, unknown> => isRecord(p) && typeof p[\"text\"] === \"string\")\n .map((p) => p[\"text\"] as string);\n if (texts.length > 0) return texts.join(\"\\n\");\n }\n }\n\n // OpenAI\n const choices = resp[\"choices\"];\n if (Array.isArray(choices) && choices.length > 0) {\n const message = (choices[0] as Record<string, unknown> | undefined)?.[\"message\"];\n const content = (message as Record<string, unknown> | undefined)?.[\"content\"];\n return typeof content === \"string\" ? content : \"\";\n }\n\n // Anthropic\n const content = resp[\"content\"];\n if (Array.isArray(content)) {\n const texts = content\n .filter((block): block is Record<string, unknown> => isRecord(block) && Boolean(block[\"text\"]))\n .map((block) => block[\"text\"] as string);\n if (texts.length > 0) return texts.join(\"\\n\");\n }\n\n // Replicate\n const output = resp[\"output\"];\n if (typeof output === \"string\") return output;\n if (Array.isArray(output) && output.length > 0 && typeof output[0] === \"string\") {\n return output[0];\n }\n\n throw new InferallError(0, `Unrecognized response shape: keys=${JSON.stringify(Object.keys(resp))}`);\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nexport default Inferall;\n"],"mappings":"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","names":["content"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@inferall/sdk",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Official TypeScript SDK for the InferAll AI gateway — one API for every model provider.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.cjs",
|
|
7
|
+
"module": "dist/index.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"default": "./dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"require": {
|
|
16
|
+
"types": "./dist/index.d.cts",
|
|
17
|
+
"default": "./dist/index.cjs"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist",
|
|
23
|
+
"README.md",
|
|
24
|
+
"LICENSE"
|
|
25
|
+
],
|
|
26
|
+
"sideEffects": false,
|
|
27
|
+
"engines": {
|
|
28
|
+
"node": ">=18"
|
|
29
|
+
},
|
|
30
|
+
"scripts": {
|
|
31
|
+
"build": "tsup",
|
|
32
|
+
"typecheck": "tsc --noEmit",
|
|
33
|
+
"test": "vitest run",
|
|
34
|
+
"test:watch": "vitest",
|
|
35
|
+
"prepublishOnly": "npm run build"
|
|
36
|
+
},
|
|
37
|
+
"keywords": [
|
|
38
|
+
"ai",
|
|
39
|
+
"inference",
|
|
40
|
+
"gateway",
|
|
41
|
+
"llm",
|
|
42
|
+
"openai",
|
|
43
|
+
"anthropic",
|
|
44
|
+
"gemini",
|
|
45
|
+
"replicate",
|
|
46
|
+
"inferall"
|
|
47
|
+
],
|
|
48
|
+
"author": "Kindly Robotics <hello@inferall.ai>",
|
|
49
|
+
"license": "MIT",
|
|
50
|
+
"homepage": "https://inferall.ai",
|
|
51
|
+
"repository": {
|
|
52
|
+
"type": "git",
|
|
53
|
+
"url": "https://github.com/kindlyrobotics/infra.git",
|
|
54
|
+
"directory": "packages/inferall-ts"
|
|
55
|
+
},
|
|
56
|
+
"bugs": {
|
|
57
|
+
"url": "https://github.com/kindlyrobotics/infra/issues"
|
|
58
|
+
},
|
|
59
|
+
"devDependencies": {
|
|
60
|
+
"@types/node": "^20.19.41",
|
|
61
|
+
"tsup": "^8.0.0",
|
|
62
|
+
"typescript": "^5.7.0",
|
|
63
|
+
"vitest": "^2.1.0"
|
|
64
|
+
}
|
|
65
|
+
}
|