@onlist/sdk 0.1.0 → 0.2.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 +64 -12
- package/dist/index.cjs +98 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +130 -8
- package/dist/index.d.ts +130 -8
- package/dist/index.js +96 -16
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -5,13 +5,13 @@ The official JavaScript/TypeScript SDK for [Onlist](https://onlist.io), the AI A
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
npm install onlist
|
|
8
|
+
npm install @onlist/sdk
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
## Quick Start
|
|
12
12
|
|
|
13
13
|
```typescript
|
|
14
|
-
import { Onlist } from "onlist";
|
|
14
|
+
import { Onlist } from "@onlist/sdk";
|
|
15
15
|
|
|
16
16
|
const client = new Onlist({ apiKey: "sk-..." });
|
|
17
17
|
|
|
@@ -35,9 +35,13 @@ The SDK looks for API keys in this order:
|
|
|
35
35
|
// Explicit key
|
|
36
36
|
const client = new Onlist({ apiKey: "sk-..." });
|
|
37
37
|
|
|
38
|
-
// From
|
|
38
|
+
// From ONLIST_API_KEY
|
|
39
39
|
// export ONLIST_API_KEY=sk-...
|
|
40
40
|
const client = new Onlist();
|
|
41
|
+
|
|
42
|
+
// Falls back to OPENAI_API_KEY if ONLIST_API_KEY is not set
|
|
43
|
+
// export OPENAI_API_KEY=sk-...
|
|
44
|
+
const client = new Onlist();
|
|
41
45
|
```
|
|
42
46
|
|
|
43
47
|
## Provider Routing
|
|
@@ -49,7 +53,6 @@ Route requests to specific providers on the Onlist marketplace:
|
|
|
49
53
|
const response = await client.chat.completions.create({
|
|
50
54
|
model: "anthropic/claude-sonnet-4",
|
|
51
55
|
messages: [{ role: "user", content: "Hello!" }],
|
|
52
|
-
// @ts-expect-error -- extra body fields
|
|
53
56
|
provider: { only: ["alice-shop"] },
|
|
54
57
|
});
|
|
55
58
|
|
|
@@ -57,7 +60,6 @@ const response = await client.chat.completions.create({
|
|
|
57
60
|
const response = await client.chat.completions.create({
|
|
58
61
|
model: "openai/gpt-4o",
|
|
59
62
|
messages: [{ role: "user", content: "Hello!" }],
|
|
60
|
-
// @ts-expect-error
|
|
61
63
|
provider: { sort: "price" },
|
|
62
64
|
});
|
|
63
65
|
|
|
@@ -65,7 +67,6 @@ const response = await client.chat.completions.create({
|
|
|
65
67
|
const response = await client.chat.completions.create({
|
|
66
68
|
model: "openai/gpt-4o",
|
|
67
69
|
messages: [{ role: "user", content: "Hello!" }],
|
|
68
|
-
// @ts-expect-error
|
|
69
70
|
provider: {
|
|
70
71
|
order: ["alice-shop", "bob-ai"],
|
|
71
72
|
allow_fallbacks: true,
|
|
@@ -119,13 +120,44 @@ for (const provider of providers.items) {
|
|
|
119
120
|
const profile = await client.marketplace.providers.get("alice-shop");
|
|
120
121
|
```
|
|
121
122
|
|
|
123
|
+
## Rankings API
|
|
124
|
+
|
|
125
|
+
Access model and app usage rankings:
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
// Model usage leaderboard
|
|
129
|
+
const rankings = await client.marketplace.rankings.models({
|
|
130
|
+
sort: "popular",
|
|
131
|
+
window: "week",
|
|
132
|
+
});
|
|
133
|
+
for (const entry of rankings.leaderboard) {
|
|
134
|
+
console.log(`#${entry.rank} ${entry.model_name} (${entry.total_requests} requests)`);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Trending models
|
|
138
|
+
const trending = await client.marketplace.rankings.models({
|
|
139
|
+
sort: "trending",
|
|
140
|
+
window: "month",
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
// App rankings
|
|
144
|
+
const apps = await client.marketplace.rankings.apps({
|
|
145
|
+
sort: "popular",
|
|
146
|
+
window: "month",
|
|
147
|
+
limit: 10,
|
|
148
|
+
});
|
|
149
|
+
for (const app of apps.apps) {
|
|
150
|
+
console.log(`#${app.rank} ${app.title} (${app.domain})`);
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
122
154
|
## Error Handling
|
|
123
155
|
|
|
124
156
|
OpenAI-compatible calls (`chat.completions`, `embeddings`, etc.) throw standard `openai` errors. Marketplace calls throw `onlist` errors:
|
|
125
157
|
|
|
126
158
|
```typescript
|
|
127
159
|
import OpenAI from "openai";
|
|
128
|
-
import { AuthenticationError } from "onlist";
|
|
160
|
+
import { AuthenticationError, NotFoundError } from "@onlist/sdk";
|
|
129
161
|
|
|
130
162
|
// OpenAI-compatible endpoints throw openai errors
|
|
131
163
|
try {
|
|
@@ -138,21 +170,35 @@ try {
|
|
|
138
170
|
|
|
139
171
|
// Marketplace endpoints throw onlist errors
|
|
140
172
|
try {
|
|
141
|
-
await client.marketplace.models.
|
|
173
|
+
await client.marketplace.models.get("nonexistent/model");
|
|
142
174
|
} catch (e) {
|
|
175
|
+
if (e instanceof NotFoundError) {
|
|
176
|
+
console.log("Model not found");
|
|
177
|
+
}
|
|
143
178
|
if (e instanceof AuthenticationError) {
|
|
144
179
|
console.log("Invalid API key for marketplace");
|
|
145
180
|
}
|
|
146
181
|
}
|
|
147
182
|
```
|
|
148
183
|
|
|
184
|
+
## Retry Configuration
|
|
185
|
+
|
|
186
|
+
Marketplace API calls automatically retry on transient failures (408, 429, 5xx) with exponential backoff:
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
const client = new Onlist({
|
|
190
|
+
apiKey: "sk-...",
|
|
191
|
+
maxRetries: 3, // default: 2
|
|
192
|
+
});
|
|
193
|
+
```
|
|
194
|
+
|
|
149
195
|
## Migration from OpenAI
|
|
150
196
|
|
|
151
197
|
Replace the `openai` import with `onlist`:
|
|
152
198
|
|
|
153
199
|
```diff
|
|
154
200
|
- import OpenAI from "openai";
|
|
155
|
-
+ import { Onlist } from "onlist";
|
|
201
|
+
+ import { Onlist } from "@onlist/sdk";
|
|
156
202
|
|
|
157
203
|
- const client = new OpenAI({ apiKey: "sk-..." });
|
|
158
204
|
+ const client = new Onlist({ apiKey: "sk-..." });
|
|
@@ -168,7 +214,7 @@ const response = await client.chat.completions.create({
|
|
|
168
214
|
|
|
169
215
|
```diff
|
|
170
216
|
- import OpenAI from "openai";
|
|
171
|
-
+ import { Onlist } from "onlist";
|
|
217
|
+
+ import { Onlist } from "@onlist/sdk";
|
|
172
218
|
|
|
173
219
|
- const client = new OpenAI({
|
|
174
220
|
- baseURL: "https://openrouter.ai/api/v1",
|
|
@@ -188,7 +234,13 @@ const response = await client.chat.completions.create({
|
|
|
188
234
|
The SDK is written in TypeScript and ships with full type definitions. All marketplace response types are exported:
|
|
189
235
|
|
|
190
236
|
```typescript
|
|
191
|
-
import type {
|
|
237
|
+
import type {
|
|
238
|
+
Model,
|
|
239
|
+
Provider,
|
|
240
|
+
ProviderRouting,
|
|
241
|
+
ModelRankingsResponse,
|
|
242
|
+
AppRankingsResponse,
|
|
243
|
+
} from "@onlist/sdk";
|
|
192
244
|
```
|
|
193
245
|
|
|
194
246
|
## Links
|
|
@@ -198,7 +250,7 @@ import type { Model, Provider, ProviderRouting } from "onlist";
|
|
|
198
250
|
- [Model Catalog](https://onlist.io/models)
|
|
199
251
|
- [Provider Directory](https://onlist.io/providers)
|
|
200
252
|
- [API Reference](https://onlist.io/docs/api)
|
|
201
|
-
- [GitHub](https://github.com/OnlistTeam/
|
|
253
|
+
- [GitHub](https://github.com/OnlistTeam/typescript-sdk)
|
|
202
254
|
- [Python SDK](https://pypi.org/project/onlist/)
|
|
203
255
|
|
|
204
256
|
## License
|
package/dist/index.cjs
CHANGED
|
@@ -36,6 +36,8 @@ __export(index_exports, {
|
|
|
36
36
|
Marketplace: () => Marketplace,
|
|
37
37
|
MarketplaceModels: () => MarketplaceModels,
|
|
38
38
|
MarketplaceProviders: () => MarketplaceProviders,
|
|
39
|
+
MarketplaceRankings: () => MarketplaceRankings,
|
|
40
|
+
NotFoundError: () => NotFoundError,
|
|
39
41
|
Onlist: () => Onlist,
|
|
40
42
|
OnlistError: () => OnlistError,
|
|
41
43
|
ProviderError: () => ProviderError,
|
|
@@ -94,6 +96,12 @@ var ProviderError = class extends APIError {
|
|
|
94
96
|
this.name = "ProviderError";
|
|
95
97
|
}
|
|
96
98
|
};
|
|
99
|
+
var NotFoundError = class extends APIError {
|
|
100
|
+
constructor(message = "Not found", opts) {
|
|
101
|
+
super(message, { status: 404, ...opts });
|
|
102
|
+
this.name = "NotFoundError";
|
|
103
|
+
}
|
|
104
|
+
};
|
|
97
105
|
function raiseForStatus(status, body) {
|
|
98
106
|
let error = {};
|
|
99
107
|
if (body && typeof body === "object" && "error" in body) {
|
|
@@ -109,16 +117,22 @@ function raiseForStatus(status, body) {
|
|
|
109
117
|
const opts = { status, type, code, param, body };
|
|
110
118
|
if (status === 401) throw new AuthenticationError(message, opts);
|
|
111
119
|
if (status === 402) throw new InsufficientBalanceError(message, opts);
|
|
120
|
+
if (status === 404) throw new NotFoundError(message, opts);
|
|
112
121
|
if (status === 429) throw new RateLimitError(message, opts);
|
|
113
122
|
if (code && code.startsWith("no_provider")) throw new ProviderError(message, opts);
|
|
114
123
|
throw new APIError(message, opts);
|
|
115
124
|
}
|
|
116
125
|
|
|
117
126
|
// src/version.ts
|
|
118
|
-
var VERSION = "0.
|
|
127
|
+
var VERSION = "0.2.0";
|
|
119
128
|
|
|
120
129
|
// src/marketplace.ts
|
|
121
130
|
var DEFAULT_TIMEOUT = 3e4;
|
|
131
|
+
var DEFAULT_MAX_RETRIES = 2;
|
|
132
|
+
var INITIAL_RETRY_DELAY = 500;
|
|
133
|
+
var MAX_RETRY_DELAY = 8e3;
|
|
134
|
+
var JITTER_FACTOR = 0.25;
|
|
135
|
+
var RETRYABLE_STATUSES = /* @__PURE__ */ new Set([408, 429, 500, 502, 503, 504]);
|
|
122
136
|
function encodePath(segment) {
|
|
123
137
|
return segment.split("/").map((s) => encodeURIComponent(s)).join("/");
|
|
124
138
|
}
|
|
@@ -137,66 +151,109 @@ async function parseResponse(response) {
|
|
|
137
151
|
}
|
|
138
152
|
return body;
|
|
139
153
|
}
|
|
154
|
+
function retryDelay(attempt, retryAfterHeader) {
|
|
155
|
+
if (retryAfterHeader) {
|
|
156
|
+
const seconds = Number(retryAfterHeader);
|
|
157
|
+
if (!isNaN(seconds) && seconds > 0) {
|
|
158
|
+
return Math.min(seconds * 1e3, MAX_RETRY_DELAY);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
const base = Math.min(INITIAL_RETRY_DELAY * 2 ** attempt, MAX_RETRY_DELAY);
|
|
162
|
+
const jitter = base * JITTER_FACTOR * (2 * Math.random() - 1);
|
|
163
|
+
return Math.max(0, base + jitter);
|
|
164
|
+
}
|
|
140
165
|
var MarketplaceModels = class {
|
|
141
166
|
constructor(_opts) {
|
|
142
167
|
this._opts = _opts;
|
|
143
168
|
}
|
|
144
169
|
_opts;
|
|
170
|
+
/** List models in the marketplace catalog. */
|
|
145
171
|
async list(params) {
|
|
146
172
|
const search = new URLSearchParams();
|
|
147
173
|
search.set("limit", String(params?.limit ?? 20));
|
|
148
174
|
search.set("offset", String(params?.offset ?? 0));
|
|
149
175
|
if (params?.q) search.set("q", params.q);
|
|
150
|
-
const resp = await this.
|
|
176
|
+
const resp = await fetchWithRetry(this._opts, `/api/mkt/models?${search}`);
|
|
151
177
|
return await parseResponse(resp);
|
|
152
178
|
}
|
|
179
|
+
/** Get detailed info for a specific model, including provider offers. */
|
|
153
180
|
async get(modelId) {
|
|
154
|
-
const resp = await this.
|
|
181
|
+
const resp = await fetchWithRetry(this._opts, `/api/mkt/models/${encodePath(modelId)}`);
|
|
155
182
|
let data = await parseResponse(resp);
|
|
156
183
|
if (data && typeof data === "object" && "data" in data) {
|
|
157
184
|
data = data.data;
|
|
158
185
|
}
|
|
159
186
|
return data;
|
|
160
187
|
}
|
|
161
|
-
_fetch(path, init) {
|
|
162
|
-
return fetchWithOpts(this._opts, path, init);
|
|
163
|
-
}
|
|
164
188
|
};
|
|
165
189
|
var MarketplaceProviders = class {
|
|
166
190
|
constructor(_opts) {
|
|
167
191
|
this._opts = _opts;
|
|
168
192
|
}
|
|
169
193
|
_opts;
|
|
194
|
+
/** List providers on the marketplace. */
|
|
170
195
|
async list(params) {
|
|
171
196
|
const search = new URLSearchParams();
|
|
172
197
|
if (params?.sort) search.set("sort", params.sort);
|
|
173
198
|
if (params?.q) search.set("q", params.q);
|
|
174
199
|
const qs = search.toString();
|
|
175
|
-
const resp = await this.
|
|
200
|
+
const resp = await fetchWithRetry(this._opts, `/api/mkt/providers${qs ? `?${qs}` : ""}`);
|
|
176
201
|
return await parseResponse(resp);
|
|
177
202
|
}
|
|
203
|
+
/** Get detailed info for a specific provider. */
|
|
178
204
|
async get(slug) {
|
|
179
|
-
const resp = await this.
|
|
205
|
+
const resp = await fetchWithRetry(this._opts, `/api/mkt/provider/${encodePath(slug)}`);
|
|
180
206
|
let data = await parseResponse(resp);
|
|
181
207
|
if (data && typeof data === "object" && "data" in data) {
|
|
182
208
|
data = data.data;
|
|
183
209
|
}
|
|
184
210
|
return data;
|
|
185
211
|
}
|
|
186
|
-
|
|
187
|
-
|
|
212
|
+
};
|
|
213
|
+
var MarketplaceRankings = class {
|
|
214
|
+
constructor(_opts) {
|
|
215
|
+
this._opts = _opts;
|
|
216
|
+
}
|
|
217
|
+
_opts;
|
|
218
|
+
/** Get the model usage leaderboard and chart series. */
|
|
219
|
+
async models(params) {
|
|
220
|
+
const search = new URLSearchParams();
|
|
221
|
+
if (params?.sort) search.set("sort", params.sort);
|
|
222
|
+
if (params?.window) search.set("window", params.window);
|
|
223
|
+
if (params?.limit != null) search.set("limit", String(params.limit));
|
|
224
|
+
if (params?.offset != null) search.set("offset", String(params.offset));
|
|
225
|
+
const qs = search.toString();
|
|
226
|
+
const resp = await fetchWithRetry(this._opts, `/api/mkt/rankings/models${qs ? `?${qs}` : ""}`);
|
|
227
|
+
return await parseResponse(resp);
|
|
228
|
+
}
|
|
229
|
+
/** Get the app rankings list. */
|
|
230
|
+
async apps(params) {
|
|
231
|
+
const search = new URLSearchParams();
|
|
232
|
+
if (params?.sort) search.set("sort", params.sort);
|
|
233
|
+
if (params?.window) search.set("window", params.window);
|
|
234
|
+
if (params?.category) search.set("category", params.category);
|
|
235
|
+
if (params?.subcategory) search.set("subcategory", params.subcategory);
|
|
236
|
+
if (params?.page != null) search.set("page", String(params.page));
|
|
237
|
+
if (params?.limit != null) search.set("limit", String(params.limit));
|
|
238
|
+
const qs = search.toString();
|
|
239
|
+
const resp = await fetchWithRetry(this._opts, `/api/mkt/apps${qs ? `?${qs}` : ""}`);
|
|
240
|
+
return await parseResponse(resp);
|
|
188
241
|
}
|
|
189
242
|
};
|
|
190
243
|
var Marketplace = class {
|
|
244
|
+
/** Browse and search models. */
|
|
191
245
|
models;
|
|
246
|
+
/** Browse and search providers. */
|
|
192
247
|
providers;
|
|
248
|
+
/** Model and app usage rankings. */
|
|
249
|
+
rankings;
|
|
193
250
|
constructor(opts) {
|
|
194
251
|
this.models = new MarketplaceModels(opts);
|
|
195
252
|
this.providers = new MarketplaceProviders(opts);
|
|
253
|
+
this.rankings = new MarketplaceRankings(opts);
|
|
196
254
|
}
|
|
197
255
|
};
|
|
198
|
-
function
|
|
199
|
-
const url = `${opts.baseURL.replace(/\/$/, "")}${path}`;
|
|
256
|
+
function buildFetchInit(opts, init) {
|
|
200
257
|
const headers = {
|
|
201
258
|
"User-Agent": `onlist-js/${VERSION}`,
|
|
202
259
|
Accept: "application/json",
|
|
@@ -206,17 +263,39 @@ function fetchWithOpts(opts, path, init) {
|
|
|
206
263
|
headers["Authorization"] = `Bearer ${opts.apiKey}`;
|
|
207
264
|
}
|
|
208
265
|
const signal = AbortSignal.timeout(opts.timeout ?? DEFAULT_TIMEOUT);
|
|
209
|
-
return
|
|
266
|
+
return { ...init, headers, signal };
|
|
267
|
+
}
|
|
268
|
+
async function fetchWithRetry(opts, path, init) {
|
|
269
|
+
const url = `${opts.baseURL.replace(/\/$/, "")}${path}`;
|
|
270
|
+
const fetchInit = buildFetchInit(opts, init);
|
|
271
|
+
const maxRetries = opts.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
272
|
+
let lastError;
|
|
273
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
274
|
+
try {
|
|
275
|
+
const response = await fetch(url, fetchInit);
|
|
276
|
+
if (response.ok || !RETRYABLE_STATUSES.has(response.status) || attempt === maxRetries) {
|
|
277
|
+
return response;
|
|
278
|
+
}
|
|
279
|
+
const delay = retryDelay(attempt, response.headers.get("Retry-After"));
|
|
280
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
281
|
+
} catch (err) {
|
|
282
|
+
lastError = err;
|
|
283
|
+
if (attempt === maxRetries) break;
|
|
284
|
+
const delay = retryDelay(attempt, null);
|
|
285
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
throw lastError;
|
|
210
289
|
}
|
|
211
290
|
|
|
212
291
|
// src/client.ts
|
|
213
292
|
var BASE_URL = "https://onlist.io/v1";
|
|
214
293
|
var MARKETPLACE_BASE_URL = "https://onlist.io";
|
|
215
|
-
var ENV_API_KEY = "ONLIST_API_KEY";
|
|
216
294
|
var Onlist = class extends import_openai.default {
|
|
295
|
+
/** Access to marketplace data: models, providers, and rankings. */
|
|
217
296
|
marketplace;
|
|
218
297
|
constructor(opts) {
|
|
219
|
-
const apiKey = opts?.apiKey ?? (typeof process !== "undefined" ? process.env?.
|
|
298
|
+
const apiKey = opts?.apiKey ?? (typeof process !== "undefined" ? process.env?.ONLIST_API_KEY ?? process.env?.OPENAI_API_KEY : void 0) ?? void 0;
|
|
220
299
|
const baseURL = opts?.baseURL ?? BASE_URL;
|
|
221
300
|
super({
|
|
222
301
|
...opts,
|
|
@@ -231,7 +310,8 @@ var Onlist = class extends import_openai.default {
|
|
|
231
310
|
const marketplaceBase = String(baseURL).split("/v1")[0] || MARKETPLACE_BASE_URL;
|
|
232
311
|
this.marketplace = new Marketplace({
|
|
233
312
|
apiKey: this.apiKey,
|
|
234
|
-
baseURL: marketplaceBase
|
|
313
|
+
baseURL: marketplaceBase,
|
|
314
|
+
maxRetries: opts?.maxRetries
|
|
235
315
|
});
|
|
236
316
|
}
|
|
237
317
|
};
|
|
@@ -243,6 +323,8 @@ var Onlist = class extends import_openai.default {
|
|
|
243
323
|
Marketplace,
|
|
244
324
|
MarketplaceModels,
|
|
245
325
|
MarketplaceProviders,
|
|
326
|
+
MarketplaceRankings,
|
|
327
|
+
NotFoundError,
|
|
246
328
|
Onlist,
|
|
247
329
|
OnlistError,
|
|
248
330
|
ProviderError,
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/client.ts","../src/errors.ts","../src/version.ts","../src/marketplace.ts"],"sourcesContent":["export { Onlist } from \"./client.js\";\nexport type { OnlistOptions } from \"./client.js\";\n\nexport { Marketplace, MarketplaceModels, MarketplaceProviders } from \"./marketplace.js\";\nexport type { MarketplaceOptions } from \"./marketplace.js\";\n\nexport {\n OnlistError,\n APIError,\n AuthenticationError,\n InsufficientBalanceError,\n RateLimitError,\n ProviderError,\n} from \"./errors.js\";\n\nexport type {\n Pricing,\n Architecture,\n TopProvider,\n Model,\n ProviderOffer,\n ModelDetail,\n ModelListResponse,\n Provider,\n ProviderDetail,\n ProviderListResponse,\n MaxPrice,\n ProviderRouting,\n} from \"./types/index.js\";\n\nexport { VERSION } from \"./version.js\";\n","import OpenAI from \"openai\";\nimport type { ClientOptions } from \"openai\";\nimport { Marketplace } from \"./marketplace.js\";\nimport { VERSION } from \"./version.js\";\n\nconst BASE_URL = \"https://onlist.io/v1\";\nconst MARKETPLACE_BASE_URL = \"https://onlist.io\";\nconst ENV_API_KEY = \"ONLIST_API_KEY\";\n\nexport interface OnlistOptions extends Omit<ClientOptions, \"apiKey\" | \"baseURL\"> {\n apiKey?: string | null;\n baseURL?: string | null;\n}\n\nexport class Onlist extends OpenAI {\n readonly marketplace: Marketplace;\n\n constructor(opts?: OnlistOptions) {\n const apiKey =\n opts?.apiKey ??\n (typeof process !== \"undefined\" ? process.env?.[ENV_API_KEY] : undefined) ??\n undefined;\n\n const baseURL = opts?.baseURL ?? BASE_URL;\n\n super({\n ...opts,\n apiKey: apiKey ?? undefined,\n baseURL,\n defaultHeaders: {\n \"User-Agent\": `onlist-js/${VERSION}`,\n \"HTTP-Referer\": \"https://onlist.io\",\n ...opts?.defaultHeaders,\n },\n });\n\n const marketplaceBase = String(baseURL).split(\"/v1\")[0] || MARKETPLACE_BASE_URL;\n\n this.marketplace = new Marketplace({\n apiKey: this.apiKey,\n baseURL: marketplaceBase,\n });\n }\n}\n","export class OnlistError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"OnlistError\";\n }\n}\n\nexport class APIError extends OnlistError {\n readonly status: number;\n readonly type: string | null;\n readonly code: string | null;\n readonly param: string | null;\n readonly body: unknown;\n\n constructor(\n message: string,\n opts: {\n status: number;\n type?: string | null;\n code?: string | null;\n param?: string | null;\n body?: unknown;\n },\n ) {\n super(message);\n this.name = \"APIError\";\n this.status = opts.status;\n this.type = opts.type ?? null;\n this.code = opts.code ?? null;\n this.param = opts.param ?? null;\n this.body = opts.body ?? null;\n }\n}\n\nexport class AuthenticationError extends APIError {\n constructor(message = \"Invalid API key\", opts?: Partial<ConstructorParameters<typeof APIError>[1]>) {\n super(message, { status: 401, ...opts });\n this.name = \"AuthenticationError\";\n }\n}\n\nexport class InsufficientBalanceError extends APIError {\n constructor(message = \"Insufficient balance\", opts?: Partial<ConstructorParameters<typeof APIError>[1]>) {\n super(message, { status: 402, ...opts });\n this.name = \"InsufficientBalanceError\";\n }\n}\n\nexport class RateLimitError extends APIError {\n constructor(message = \"Rate limited\", opts?: Partial<ConstructorParameters<typeof APIError>[1]>) {\n super(message, { status: 429, ...opts });\n this.name = \"RateLimitError\";\n }\n}\n\nexport class ProviderError extends APIError {\n constructor(message: string, opts: ConstructorParameters<typeof APIError>[1]) {\n super(message, opts);\n this.name = \"ProviderError\";\n }\n}\n\nexport function raiseForStatus(status: number, body: unknown): never {\n let error: Record<string, unknown> = {};\n if (body && typeof body === \"object\" && \"error\" in body) {\n const e = (body as Record<string, unknown>).error;\n error = typeof e === \"object\" && e !== null ? (e as Record<string, unknown>) : {};\n } else if (body && typeof body === \"object\") {\n error = body as Record<string, unknown>;\n }\n\n const message = (typeof error.message === \"string\" ? error.message : String(body)) || \"Unknown error\";\n const type = typeof error.type === \"string\" ? error.type : null;\n const code = typeof error.code === \"string\" ? error.code : null;\n const param = typeof error.param === \"string\" ? error.param : null;\n const opts = { status, type, code, param, body };\n\n if (status === 401) throw new AuthenticationError(message, opts);\n if (status === 402) throw new InsufficientBalanceError(message, opts);\n if (status === 429) throw new RateLimitError(message, opts);\n if (code && code.startsWith(\"no_provider\")) throw new ProviderError(message, opts);\n\n throw new APIError(message, opts);\n}\n","export const VERSION = \"0.1.0\";\n","import { raiseForStatus } from \"./errors.js\";\nimport { VERSION } from \"./version.js\";\nimport type { ModelDetail, ModelListResponse } from \"./types/model.js\";\nimport type { ProviderDetail, ProviderListResponse } from \"./types/provider.js\";\n\nconst DEFAULT_TIMEOUT = 30_000;\n\nfunction encodePath(segment: string): string {\n return segment\n .split(\"/\")\n .map((s) => encodeURIComponent(s))\n .join(\"/\");\n}\n\nasync function parseResponse(response: Response): Promise<unknown> {\n let body: unknown;\n try {\n body = await response.json();\n } catch {\n body = await response.text().catch(() => \"\");\n }\n\n if (!response.ok) {\n raiseForStatus(response.status, body);\n }\n\n if (body && typeof body === \"object\" && \"data\" in body && \"success\" in body) {\n return (body as Record<string, unknown>).data;\n }\n return body;\n}\n\nexport interface MarketplaceOptions {\n apiKey?: string | null;\n baseURL: string;\n timeout?: number;\n}\n\nexport class MarketplaceModels {\n constructor(private readonly _opts: MarketplaceOptions) {}\n\n async list(params?: { limit?: number; offset?: number; q?: string }): Promise<ModelListResponse> {\n const search = new URLSearchParams();\n search.set(\"limit\", String(params?.limit ?? 20));\n search.set(\"offset\", String(params?.offset ?? 0));\n if (params?.q) search.set(\"q\", params.q);\n\n const resp = await this._fetch(`/api/mkt/models?${search}`);\n return (await parseResponse(resp)) as ModelListResponse;\n }\n\n async get(modelId: string): Promise<ModelDetail> {\n const resp = await this._fetch(`/api/mkt/models/${encodePath(modelId)}`);\n let data = (await parseResponse(resp)) as Record<string, unknown>;\n if (data && typeof data === \"object\" && \"data\" in data) {\n data = data.data as Record<string, unknown>;\n }\n return data as unknown as ModelDetail;\n }\n\n private _fetch(path: string, init?: RequestInit): Promise<Response> {\n return fetchWithOpts(this._opts, path, init);\n }\n}\n\nexport class MarketplaceProviders {\n constructor(private readonly _opts: MarketplaceOptions) {}\n\n async list(params?: { sort?: string; q?: string }): Promise<ProviderListResponse> {\n const search = new URLSearchParams();\n if (params?.sort) search.set(\"sort\", params.sort);\n if (params?.q) search.set(\"q\", params.q);\n\n const qs = search.toString();\n const resp = await this._fetch(`/api/mkt/providers${qs ? `?${qs}` : \"\"}`);\n return (await parseResponse(resp)) as ProviderListResponse;\n }\n\n async get(slug: string): Promise<ProviderDetail> {\n const resp = await this._fetch(`/api/mkt/provider/${encodePath(slug)}`);\n let data = (await parseResponse(resp)) as Record<string, unknown>;\n if (data && typeof data === \"object\" && \"data\" in data) {\n data = data.data as Record<string, unknown>;\n }\n return data as unknown as ProviderDetail;\n }\n\n private _fetch(path: string, init?: RequestInit): Promise<Response> {\n return fetchWithOpts(this._opts, path, init);\n }\n}\n\nexport class Marketplace {\n readonly models: MarketplaceModels;\n readonly providers: MarketplaceProviders;\n\n constructor(opts: MarketplaceOptions) {\n this.models = new MarketplaceModels(opts);\n this.providers = new MarketplaceProviders(opts);\n }\n}\n\nfunction fetchWithOpts(opts: MarketplaceOptions, path: string, init?: RequestInit): Promise<Response> {\n const url = `${opts.baseURL.replace(/\\/$/, \"\")}${path}`;\n const headers: Record<string, string> = {\n \"User-Agent\": `onlist-js/${VERSION}`,\n Accept: \"application/json\",\n ...(init?.headers as Record<string, string>),\n };\n if (opts.apiKey) {\n headers[\"Authorization\"] = `Bearer ${opts.apiKey}`;\n }\n const signal = AbortSignal.timeout(opts.timeout ?? DEFAULT_TIMEOUT);\n return fetch(url, { ...init, headers, signal });\n}\n"],"mappings":"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","names":["OpenAI"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/client.ts","../src/errors.ts","../src/version.ts","../src/marketplace.ts"],"sourcesContent":["export { Onlist } from \"./client.js\";\nexport type { OnlistOptions } from \"./client.js\";\n\nexport { Marketplace, MarketplaceModels, MarketplaceProviders, MarketplaceRankings } from \"./marketplace.js\";\nexport type { MarketplaceOptions } from \"./marketplace.js\";\n\nexport {\n OnlistError,\n APIError,\n AuthenticationError,\n InsufficientBalanceError,\n NotFoundError,\n RateLimitError,\n ProviderError,\n} from \"./errors.js\";\n\nexport type {\n Pricing,\n Architecture,\n TopProvider,\n Model,\n ProviderOffer,\n ModelDetail,\n ModelListResponse,\n Provider,\n ProviderDetail,\n ProviderListResponse,\n MaxPrice,\n ProviderRouting,\n ModelRanking,\n ModelSeriesPoint,\n ModelRankingsResponse,\n ModelRankingsParams,\n AppRanking,\n AppRankingsResponse,\n AppRankingsParams,\n} from \"./types/index.js\";\n\nexport { VERSION } from \"./version.js\";\n","import OpenAI from \"openai\";\nimport type { ClientOptions } from \"openai\";\nimport { Marketplace } from \"./marketplace.js\";\nimport { VERSION } from \"./version.js\";\n\nconst BASE_URL = \"https://onlist.io/v1\";\nconst MARKETPLACE_BASE_URL = \"https://onlist.io\";\n\n/** Options for creating an Onlist client. */\nexport interface OnlistOptions extends Omit<ClientOptions, \"apiKey\" | \"baseURL\"> {\n /** API key. Falls back to ONLIST_API_KEY then OPENAI_API_KEY env vars. */\n apiKey?: string | null;\n /** Base URL for the API. Defaults to https://onlist.io/v1. */\n baseURL?: string | null;\n /** Maximum retry attempts for marketplace API calls. Defaults to 2. */\n maxRetries?: number;\n}\n\n/** Onlist API client, extending the OpenAI SDK with marketplace features. */\nexport class Onlist extends OpenAI {\n /** Access to marketplace data: models, providers, and rankings. */\n readonly marketplace: Marketplace;\n\n constructor(opts?: OnlistOptions) {\n const apiKey =\n opts?.apiKey ??\n (typeof process !== \"undefined\"\n ? process.env?.ONLIST_API_KEY ?? process.env?.OPENAI_API_KEY\n : undefined) ??\n undefined;\n\n const baseURL = opts?.baseURL ?? BASE_URL;\n\n super({\n ...opts,\n apiKey: apiKey ?? undefined,\n baseURL,\n defaultHeaders: {\n \"User-Agent\": `onlist-js/${VERSION}`,\n \"HTTP-Referer\": \"https://onlist.io\",\n ...opts?.defaultHeaders,\n },\n });\n\n const marketplaceBase = String(baseURL).split(\"/v1\")[0] || MARKETPLACE_BASE_URL;\n\n this.marketplace = new Marketplace({\n apiKey: this.apiKey,\n baseURL: marketplaceBase,\n maxRetries: opts?.maxRetries,\n });\n }\n}\n","/** Base error class for all Onlist SDK errors. */\nexport class OnlistError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"OnlistError\";\n }\n}\n\n/** Error thrown when an API request fails. */\nexport class APIError extends OnlistError {\n readonly status: number;\n readonly type: string | null;\n readonly code: string | null;\n readonly param: string | null;\n readonly body: unknown;\n\n constructor(\n message: string,\n opts: {\n status: number;\n type?: string | null;\n code?: string | null;\n param?: string | null;\n body?: unknown;\n },\n ) {\n super(message);\n this.name = \"APIError\";\n this.status = opts.status;\n this.type = opts.type ?? null;\n this.code = opts.code ?? null;\n this.param = opts.param ?? null;\n this.body = opts.body ?? null;\n }\n}\n\n/** Error thrown when the API key is invalid or missing. */\nexport class AuthenticationError extends APIError {\n constructor(message = \"Invalid API key\", opts?: Partial<ConstructorParameters<typeof APIError>[1]>) {\n super(message, { status: 401, ...opts });\n this.name = \"AuthenticationError\";\n }\n}\n\n/** Error thrown when the account balance is insufficient. */\nexport class InsufficientBalanceError extends APIError {\n constructor(message = \"Insufficient balance\", opts?: Partial<ConstructorParameters<typeof APIError>[1]>) {\n super(message, { status: 402, ...opts });\n this.name = \"InsufficientBalanceError\";\n }\n}\n\n/** Error thrown when the request is rate-limited. */\nexport class RateLimitError extends APIError {\n constructor(message = \"Rate limited\", opts?: Partial<ConstructorParameters<typeof APIError>[1]>) {\n super(message, { status: 429, ...opts });\n this.name = \"RateLimitError\";\n }\n}\n\n/** Error thrown when no matching provider is available. */\nexport class ProviderError extends APIError {\n constructor(message: string, opts: ConstructorParameters<typeof APIError>[1]) {\n super(message, opts);\n this.name = \"ProviderError\";\n }\n}\n\n/** Error thrown when a requested resource is not found. */\nexport class NotFoundError extends APIError {\n constructor(message = \"Not found\", opts?: Partial<ConstructorParameters<typeof APIError>[1]>) {\n super(message, { status: 404, ...opts });\n this.name = \"NotFoundError\";\n }\n}\n\nexport function raiseForStatus(status: number, body: unknown): never {\n let error: Record<string, unknown> = {};\n if (body && typeof body === \"object\" && \"error\" in body) {\n const e = (body as Record<string, unknown>).error;\n error = typeof e === \"object\" && e !== null ? (e as Record<string, unknown>) : {};\n } else if (body && typeof body === \"object\") {\n error = body as Record<string, unknown>;\n }\n\n const message = (typeof error.message === \"string\" ? error.message : String(body)) || \"Unknown error\";\n const type = typeof error.type === \"string\" ? error.type : null;\n const code = typeof error.code === \"string\" ? error.code : null;\n const param = typeof error.param === \"string\" ? error.param : null;\n const opts = { status, type, code, param, body };\n\n if (status === 401) throw new AuthenticationError(message, opts);\n if (status === 402) throw new InsufficientBalanceError(message, opts);\n if (status === 404) throw new NotFoundError(message, opts);\n if (status === 429) throw new RateLimitError(message, opts);\n if (code && code.startsWith(\"no_provider\")) throw new ProviderError(message, opts);\n\n throw new APIError(message, opts);\n}\n","export const VERSION = \"0.2.0\";\n","import { raiseForStatus } from \"./errors.js\";\nimport { VERSION } from \"./version.js\";\nimport type { ModelDetail, ModelListResponse } from \"./types/model.js\";\nimport type { ProviderDetail, ProviderListResponse } from \"./types/provider.js\";\nimport type {\n ModelRankingsResponse,\n ModelRankingsParams,\n AppRankingsResponse,\n AppRankingsParams,\n} from \"./types/rankings.js\";\n\nconst DEFAULT_TIMEOUT = 30_000;\nconst DEFAULT_MAX_RETRIES = 2;\nconst INITIAL_RETRY_DELAY = 500;\nconst MAX_RETRY_DELAY = 8_000;\nconst JITTER_FACTOR = 0.25;\n\n/** Retryable status codes: timeouts, rate limits, and server errors. */\nconst RETRYABLE_STATUSES = new Set([408, 429, 500, 502, 503, 504]);\n\nfunction encodePath(segment: string): string {\n return segment\n .split(\"/\")\n .map((s) => encodeURIComponent(s))\n .join(\"/\");\n}\n\nasync function parseResponse(response: Response): Promise<unknown> {\n let body: unknown;\n try {\n body = await response.json();\n } catch {\n body = await response.text().catch(() => \"\");\n }\n\n if (!response.ok) {\n raiseForStatus(response.status, body);\n }\n\n if (body && typeof body === \"object\" && \"data\" in body && \"success\" in body) {\n return (body as Record<string, unknown>).data;\n }\n return body;\n}\n\n/** Calculates the retry delay with exponential backoff and jitter. */\nfunction retryDelay(attempt: number, retryAfterHeader: string | null): number {\n if (retryAfterHeader) {\n const seconds = Number(retryAfterHeader);\n if (!isNaN(seconds) && seconds > 0) {\n return Math.min(seconds * 1000, MAX_RETRY_DELAY);\n }\n }\n const base = Math.min(INITIAL_RETRY_DELAY * 2 ** attempt, MAX_RETRY_DELAY);\n const jitter = base * JITTER_FACTOR * (2 * Math.random() - 1);\n return Math.max(0, base + jitter);\n}\n\n/** Options for creating a Marketplace client. */\nexport interface MarketplaceOptions {\n apiKey?: string | null;\n baseURL: string;\n timeout?: number;\n /** Maximum retry attempts for failed requests. Defaults to 2. */\n maxRetries?: number;\n}\n\n/** Access to marketplace model data. */\nexport class MarketplaceModels {\n constructor(private readonly _opts: MarketplaceOptions) {}\n\n /** List models in the marketplace catalog. */\n async list(params?: { limit?: number; offset?: number; q?: string }): Promise<ModelListResponse> {\n const search = new URLSearchParams();\n search.set(\"limit\", String(params?.limit ?? 20));\n search.set(\"offset\", String(params?.offset ?? 0));\n if (params?.q) search.set(\"q\", params.q);\n\n const resp = await fetchWithRetry(this._opts, `/api/mkt/models?${search}`);\n return (await parseResponse(resp)) as ModelListResponse;\n }\n\n /** Get detailed info for a specific model, including provider offers. */\n async get(modelId: string): Promise<ModelDetail> {\n const resp = await fetchWithRetry(this._opts, `/api/mkt/models/${encodePath(modelId)}`);\n let data = (await parseResponse(resp)) as Record<string, unknown>;\n if (data && typeof data === \"object\" && \"data\" in data) {\n data = data.data as Record<string, unknown>;\n }\n return data as unknown as ModelDetail;\n }\n}\n\n/** Access to marketplace provider data. */\nexport class MarketplaceProviders {\n constructor(private readonly _opts: MarketplaceOptions) {}\n\n /** List providers on the marketplace. */\n async list(params?: { sort?: string; q?: string }): Promise<ProviderListResponse> {\n const search = new URLSearchParams();\n if (params?.sort) search.set(\"sort\", params.sort);\n if (params?.q) search.set(\"q\", params.q);\n\n const qs = search.toString();\n const resp = await fetchWithRetry(this._opts, `/api/mkt/providers${qs ? `?${qs}` : \"\"}`);\n return (await parseResponse(resp)) as ProviderListResponse;\n }\n\n /** Get detailed info for a specific provider. */\n async get(slug: string): Promise<ProviderDetail> {\n const resp = await fetchWithRetry(this._opts, `/api/mkt/provider/${encodePath(slug)}`);\n let data = (await parseResponse(resp)) as Record<string, unknown>;\n if (data && typeof data === \"object\" && \"data\" in data) {\n data = data.data as Record<string, unknown>;\n }\n return data as unknown as ProviderDetail;\n }\n}\n\n/** Access to marketplace rankings (models and apps). */\nexport class MarketplaceRankings {\n constructor(private readonly _opts: MarketplaceOptions) {}\n\n /** Get the model usage leaderboard and chart series. */\n async models(params?: ModelRankingsParams): Promise<ModelRankingsResponse> {\n const search = new URLSearchParams();\n if (params?.sort) search.set(\"sort\", params.sort);\n if (params?.window) search.set(\"window\", params.window);\n if (params?.limit != null) search.set(\"limit\", String(params.limit));\n if (params?.offset != null) search.set(\"offset\", String(params.offset));\n\n const qs = search.toString();\n const resp = await fetchWithRetry(this._opts, `/api/mkt/rankings/models${qs ? `?${qs}` : \"\"}`);\n return (await parseResponse(resp)) as ModelRankingsResponse;\n }\n\n /** Get the app rankings list. */\n async apps(params?: AppRankingsParams): Promise<AppRankingsResponse> {\n const search = new URLSearchParams();\n if (params?.sort) search.set(\"sort\", params.sort);\n if (params?.window) search.set(\"window\", params.window);\n if (params?.category) search.set(\"category\", params.category);\n if (params?.subcategory) search.set(\"subcategory\", params.subcategory);\n if (params?.page != null) search.set(\"page\", String(params.page));\n if (params?.limit != null) search.set(\"limit\", String(params.limit));\n\n const qs = search.toString();\n const resp = await fetchWithRetry(this._opts, `/api/mkt/apps${qs ? `?${qs}` : \"\"}`);\n return (await parseResponse(resp)) as AppRankingsResponse;\n }\n}\n\n/** Client for the Onlist marketplace public API. */\nexport class Marketplace {\n /** Browse and search models. */\n readonly models: MarketplaceModels;\n /** Browse and search providers. */\n readonly providers: MarketplaceProviders;\n /** Model and app usage rankings. */\n readonly rankings: MarketplaceRankings;\n\n constructor(opts: MarketplaceOptions) {\n this.models = new MarketplaceModels(opts);\n this.providers = new MarketplaceProviders(opts);\n this.rankings = new MarketplaceRankings(opts);\n }\n}\n\nfunction buildFetchInit(opts: MarketplaceOptions, init?: RequestInit): RequestInit {\n const headers: Record<string, string> = {\n \"User-Agent\": `onlist-js/${VERSION}`,\n Accept: \"application/json\",\n ...(init?.headers as Record<string, string>),\n };\n if (opts.apiKey) {\n headers[\"Authorization\"] = `Bearer ${opts.apiKey}`;\n }\n const signal = AbortSignal.timeout(opts.timeout ?? DEFAULT_TIMEOUT);\n return { ...init, headers, signal };\n}\n\nasync function fetchWithRetry(\n opts: MarketplaceOptions,\n path: string,\n init?: RequestInit,\n): Promise<Response> {\n const url = `${opts.baseURL.replace(/\\/$/, \"\")}${path}`;\n const fetchInit = buildFetchInit(opts, init);\n const maxRetries = opts.maxRetries ?? DEFAULT_MAX_RETRIES;\n\n let lastError: unknown;\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n const response = await fetch(url, fetchInit);\n if (response.ok || !RETRYABLE_STATUSES.has(response.status) || attempt === maxRetries) {\n return response;\n }\n const delay = retryDelay(attempt, response.headers.get(\"Retry-After\"));\n await new Promise((resolve) => setTimeout(resolve, delay));\n } catch (err) {\n lastError = err;\n if (attempt === maxRetries) break;\n const delay = retryDelay(attempt, null);\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n }\n throw lastError;\n}\n"],"mappings":"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","names":["OpenAI"]}
|