@aiqlick/inference
v0.1.0
Published
TypeScript client for the AIQLick inference API
Maintainers
Readme
@aiqlick/inference — TypeScript client
A thin wrapper over the official openai
package for the AIQLick inference API.
Deliberately thin. The whole product claim is that the API is OpenAI-compatible,
so a client that reimplemented the protocol could drift away from that claim
without anyone noticing. AIQLick extends OpenAI, so anything the official
client does — streaming, tool calling, retries, whatever it adds next — works
here unchanged.
Install
npm install @aiqlick/inference openaiopenai is a peer dependency, so you control its version and there is never a
second copy of the SDK in your tree.
Use
import { AIQLick, Models } from "@aiqlick/inference";
const client = new AIQLick({ apiKey: process.env.AIQLICK_API_KEY });
const reply = await client.chat.completions.create({
model: Models.CHAT_DEFAULT,
messages: [{ role: "user", content: "hello" }],
});
console.log(reply.choices[0]?.message?.content);Streaming works exactly as it does with the official client:
const stream = await client.chat.completions.create({
model: Models.CHAT_DEFAULT,
messages: [{ role: "user", content: "hello" }],
stream: true,
});
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}Models
Use the aliases, not provider model ids:
| Constant | Alias |
|---|---|
| Models.CHAT_PREMIUM | aiqlick/chat-premium |
| Models.CHAT_DEFAULT | aiqlick/chat-default |
| Models.CHAT_CHEAP | aiqlick/chat-cheap |
| Models.EXTRACT_DEFAULT | aiqlick/extract-default |
| Models.EXTRACT_FAST | aiqlick/extract-fast |
| Models.EMBED_DEFAULT | aiqlick/embed-default |
The mapping from an alias to a specific provider model is a platform decision that changes without callers changing — that is the entire point of the gateway. Pinning a provider id in your own code gives that up.
Your key may be scoped to a subset. client.models.list() returns only what it
can actually call.
Errors
The OpenAI SDK gives you a status and a message. asAIQLickError() promotes our
code onto a typed error, which is what lets you tell "out of credits" from
"subscription lapsed" — the same 402 with entirely different fixes.
import { asAIQLickError, ErrorCodes } from "@aiqlick/inference";
try {
await client.chat.completions.create({ /* … */ });
} catch (err) {
const specific = asAIQLickError(err);
if (specific?.code === ErrorCodes.INSUFFICIENT_CREDITS) {
// top up or upgrade the plan
}
throw specific ?? err;
}It returns undefined for anything it does not recognise rather than guessing,
so a provider error never gets mislabelled as a platform error.
| code | Meaning |
|---|---|
| INSUFFICIENT_CREDITS | Credit balance exhausted |
| SUBSCRIPTION_INACTIVE | No active subscription for the company |
| LLM_MODEL_NOT_ALLOWED | Key not permitted to use that alias |
| LLM_GATEWAY_UNAVAILABLE | Gateway unreachable — retry with backoff |
Configuration
| Variable | Default |
|---|---|
| AIQLICK_API_KEY | — |
| AIQLICK_BASE_URL | https://api.aiqlick.com/llm/v1 |
Reading the base URL from the environment means one build can be pointed at dev or a self-hosted deployment without a code change.
Not using this client
You do not have to. The API is OpenAI-compatible, so the official client works directly — this package only saves you the base URL and the constants:
import OpenAI from "openai";
const client = new OpenAI({
apiKey: "sk-…",
baseURL: "https://api.aiqlick.com/llm/v1",
});Full documentation: https://docs.aiqlick.com
