@brotu/ai 0.3.0 → 0.5.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 CHANGED
@@ -1,20 +1,20 @@
1
1
  <p align="center">
2
2
  <picture>
3
- <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/Zorbi-Tech/brotu-sdk/main/docs/assets/logo.svg">
4
- <img src="https://raw.githubusercontent.com/Zorbi-Tech/brotu-sdk/main/docs/assets/logo-black.svg" alt="Brotu" width="280">
3
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/Zorbi-Tech/brotu/main/docs/assets/logo.svg">
4
+ <img src="https://raw.githubusercontent.com/Zorbi-Tech/brotu/main/docs/assets/logo-black.svg" alt="Brotu" width="280">
5
5
  </picture>
6
6
  </p>
7
7
 
8
8
  <p align="center">
9
9
  <strong>One TypeScript client for video, image, speech, text and vendor extras.</strong><br>
10
- You bring the keys. Each call hits the vendor's own API.
10
+ Your Brotu key. Vendor keys generate on the vendor.
11
11
  </p>
12
12
 
13
13
  <p align="center">
14
14
  <a href="https://www.npmjs.com/package/@brotu/ai"><img alt="npm version" src="https://img.shields.io/npm/v/@brotu/ai?color=ef5e28"></a>
15
15
  <a href="https://www.npmjs.com/package/@brotu/ai"><img alt="npm downloads" src="https://img.shields.io/npm/dm/@brotu/ai?color=ef5e28&label=downloads"></a>
16
16
  <a href="https://www.npmjs.com/package/@brotu/ai"><img alt="npm totals" src="https://img.shields.io/npm/dt/@brotu/ai?color=111&label=total"></a>
17
- <a href="https://github.com/Zorbi-Tech/brotu-sdk/blob/main/LICENSE"><img alt="MIT" src="https://img.shields.io/npm/l/@brotu/ai?color=111"></a>
17
+ <a href="https://github.com/Zorbi-Tech/brotu/blob/main/LICENSE"><img alt="MIT" src="https://img.shields.io/npm/l/@brotu/ai?color=111"></a>
18
18
  </p>
19
19
 
20
20
  <p align="center">
@@ -23,7 +23,9 @@
23
23
  <a href="https://x.com/brotuApp">@brotuApp</a>
24
24
  </p>
25
25
 
26
- Kling, Seedance, Wan, Veo, Gemini, gpt-image and ElevenLabs all speak different HTTP. This package is one `brotuClient` in front of them. No proxy.
26
+ Kling, Seedance, Wan, Veo, Gemini, gpt-image and ElevenLabs all speak different HTTP. This package is one `brotu` in front of them.
27
+
28
+ Get your key (`brotu_sk_…`) at [brotu.app](https://brotu.app). Pass a vendor key you already have and that model hits the vendor. Everything else generates on Brotu.
27
29
 
28
30
  97 models: 37 video, 29 image, 12 speech, 19 text. Full table in [CATALOG.md](./CATALOG.md). That file is generated from the catalog, so it cannot drift from what the code supports.
29
31
 
@@ -44,9 +46,10 @@ pnpm add @brotu/ai
44
46
  ## Client
45
47
 
46
48
  ```ts
47
- import { brotuClient } from "@brotu/ai";
49
+ import { brotu } from "@brotu/ai";
48
50
 
49
- const ai = brotuClient({
51
+ const ai = brotu({
52
+ apiKey: process.env.BROTU_API_KEY!, // brotu_sk_… from https://brotu.app
50
53
  providers: {
51
54
  kling: { apiKey: process.env.KLING_API_KEY! },
52
55
  byteplus: { apiKey: process.env.ARK_API_KEY! },
@@ -62,24 +65,42 @@ const ai = brotuClient({
62
65
  });
63
66
  ```
64
67
 
65
- Only configured providers appear in `ai.models()`.
68
+ Your Brotu key opens the catalog. A vendor key, when you have one, generates on that vendor.
66
69
 
67
70
  Every public call returns `{ data, error }`. `data` is unusable until you narrow on `error`.
68
71
 
69
72
  | Surface | Methods |
70
73
  |---|---|
71
- | `ai.video` | `submit` / `generate` |
72
- | `ai.image` | `submit` / `generate` |
73
- | `ai.text` | `submit` / `generate` |
74
- | `ai.audio` | `submit` / `generate` |
74
+ | `ai.video` | `submit` / `generate` / `list` |
75
+ | `ai.image` | `submit` / `generate` / `list` |
76
+ | `ai.text` | `submit` / `generate` / `list` |
77
+ | `ai.audio` | `submit` / `generate` / `list` |
75
78
  | `ai.jobs` | `poll` / `wait` |
76
79
  | `ai.webhook` | `set` / `clear` / `get` |
80
+ | `hooks` | constructor option: your own code on start, success and failure |
77
81
  | `ai.estimateCost` | units, and USD when verified |
78
82
  | `ai.kling` | `motionControl`, `omniVideo`, `avatar`, `outpainting`, `imageOmni` |
79
83
  | `ai.google` | `omniVideo` (conversational refine) |
80
84
 
81
85
  `ai.kling` and `ai.google` exist only when that key is set.
82
86
 
87
+ ## What your keys reach
88
+
89
+ The platform generates image and video. Speech and text are the vendor's work, so those need that vendor's key. `list` says which is which, per model:
90
+
91
+ ```ts
92
+ const ai = brotu({ apiKey: process.env.BROTU_API_KEY! });
93
+
94
+ ai.image.list();
95
+ // [{ model: { id: "gpt-image-2", … }, runsOn: "brotu", runnable: true }, …]
96
+
97
+ ai.audio.list();
98
+ // [{ model: { id: "kling/tts", … }, runsOn: "kling", runnable: false,
99
+ // reason: "Brotu generates image and video only. Pass providers.kling to run this one." }, …]
100
+ ```
101
+
102
+ With a Brotu key alone that is 29 image and 37 video models, and the 31 speech and text models listed with the key they are waiting on. Models you cannot reach stay in the list on purpose: hiding them would hide the gap. `ai.models()` is the filtered view, only what runs.
103
+
83
104
  ## Video
84
105
 
85
106
  `submit` returns a job handle. `generate` waits. Video takes minutes, so do not `generate` inside a request handler.
@@ -150,6 +171,10 @@ ElevenLabs: you must pass `voice`. There is no default.
150
171
 
151
172
  Realtime / Live WebSocket models are not on this surface.
152
173
 
174
+ ## CLI
175
+
176
+ The terminal lives in [`../../cli`](../../cli) (`@brotu/cli`). This package is the library only.
177
+
153
178
  ## Jobs
154
179
 
155
180
  ```ts
@@ -198,6 +223,26 @@ The POST is JSON. Check `x-brotu-event` and, if you set a secret, `x-brotu-webho
198
223
 
199
224
  Error codes: `unknown_model`, `missing_key`, `unsupported_provider`, `invalid_request`, `provider_error`, `timeout`.
200
225
 
226
+ ## Hooks
227
+
228
+ Same moments as the webhook, but a function instead of an endpoint — so it runs in your process, with your imports.
229
+
230
+ ```ts
231
+ const ai = brotu({
232
+ apiKey: process.env.BROTU_API_KEY!,
233
+ providers: { kling: { apiKey: process.env.KLING_API_KEY! } },
234
+ hooks: {
235
+ onVideoLoading: (e) => console.log("generating", e.model),
236
+ onVideoSuccess: (e) => sendEmail("your video is ready", e.outputs?.[0]?.url),
237
+ onVideoError: (e) => sendEmail("your video failed", e.error?.message),
238
+ },
239
+ });
240
+ ```
241
+
242
+ One optional callback per kind and stage — `on{Image,Video,Audio,Text}{Loading,Success,Error}`, twelve typed names. `Loading` fires once the model is routed, before the provider is called; `Success` and `Error` fire wherever the webhook fires, deduped by job id. A hook that throws never fails the generation.
243
+
244
+ The event is `HookEvent`: `kind`, `stage`, `provider`, `model`, `jobId`, `outputs`, `error`, `metadata`, `processingTimeMs`, `at`.
245
+
201
246
  ## Motion control, avatars, omni
202
247
 
203
248
  Not on `ai.video`. A shared signature would be a lie.
@@ -0,0 +1,46 @@
1
+ import { type Job, type JobSnapshot } from "../lib/jobs";
2
+ import { type AudioGenerationParams, type ContentGeneratorPort, type CostEstimate, type GenerationParams, type GenerationResult, type GenerationType, type ImageGenerationParams, type TextGenerationParams, type VideoGenerationParams } from "../ports/content-generator.port";
3
+ export interface BrotuAdapterOptions {
4
+ apiKey: string;
5
+ /** Origin only, no trailing slash. Defaults to https://api.brotu.app */
6
+ apiUrl?: string;
7
+ workspaceId?: string;
8
+ maxPollAttempts?: number;
9
+ }
10
+ /**
11
+ * SDK catalog ids that do not match the platform catalog. Unlisted ids are
12
+ * sent as-is — gpt-image-2 and bytedance/seedance-2-5 already agree.
13
+ */
14
+ declare const PLATFORM_MODEL_IDS: Record<string, string>;
15
+ export declare class BrotuAdapter implements ContentGeneratorPort {
16
+ private readonly opts;
17
+ readonly providerName = "brotu";
18
+ readonly supportedTypes: GenerationType[];
19
+ private workspaceIdCache?;
20
+ constructor(opts: BrotuAdapterOptions);
21
+ private get origin();
22
+ private headers;
23
+ private workspaceId;
24
+ private studioPath;
25
+ private request;
26
+ private platformModel;
27
+ private startGeneration;
28
+ private imageBody;
29
+ private videoBody;
30
+ private run;
31
+ completeJob(job: Job): Promise<JobSnapshot>;
32
+ private workspaceFromPoll;
33
+ generateImage(params: ImageGenerationParams): Promise<GenerationResult>;
34
+ generateVideo(params: VideoGenerationParams): Promise<GenerationResult>;
35
+ generateText(params: TextGenerationParams): Promise<GenerationResult>;
36
+ generateAudio(params: AudioGenerationParams): Promise<GenerationResult>;
37
+ estimateCost(type: GenerationType, params: GenerationParams): Promise<CostEstimate>;
38
+ supportsModel(): boolean;
39
+ getAvailableModels(): {
40
+ id: string;
41
+ name: string;
42
+ type: GenerationType;
43
+ }[];
44
+ }
45
+ export { PLATFORM_MODEL_IDS };
46
+ //# sourceMappingURL=brotu.adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"brotu.adapter.d.ts","sourceRoot":"","sources":["../../src/adapters/brotu.adapter.ts"],"names":[],"mappings":"AACA,OAAO,EAEN,KAAK,GAAG,EACR,KAAK,WAAW,EAEhB,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EACzB,KAAK,YAAY,EAEjB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,EAC1B,MAAM,iCAAiC,CAAC;AAGzC,MAAM,WAAW,mBAAmB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,wEAAwE;IACxE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;CACzB;AAMD;;;GAGG;AACH,QAAA,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAO9C,CAAC;AAuBF,qBAAa,YAAa,YAAW,oBAAoB;IAM5C,OAAO,CAAC,QAAQ,CAAC,IAAI;IALjC,QAAQ,CAAC,YAAY,WAAW;IAChC,QAAQ,CAAC,cAAc,EAAE,cAAc,EAAE,CAA8B;IAEvE,OAAO,CAAC,gBAAgB,CAAC,CAAS;IAElC,YAA6B,IAAI,EAAE,mBAAmB,EAAI;IAE1D,OAAO,KAAK,MAAM,GAEjB;IAED,OAAO,CAAC,OAAO;YAOD,WAAW;IAiBzB,OAAO,CAAC,UAAU;YAKJ,OAAO;IAyBrB,OAAO,CAAC,aAAa;YAIP,eAAe;IAwB7B,OAAO,CAAC,SAAS;IAgBjB,OAAO,CAAC,SAAS;YAqBH,GAAG;IA4DX,WAAW,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,WAAW,CAAC,CAgChD;IAED,OAAO,CAAC,iBAAiB;IAUzB,aAAa,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAEtE;IAED,aAAa,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAEtE;IAEK,YAAY,CAAC,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAU1E;IAEK,aAAa,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAU5E;IAEK,YAAY,CACjB,IAAI,EAAE,cAAc,EACpB,MAAM,EAAE,gBAAgB,GACtB,OAAO,CAAC,YAAY,CAAC,CAuDvB;IAED,aAAa,IAAI,OAAO,CAEvB;IAED,kBAAkB,IAAI;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,cAAc,CAAA;KAAE,EAAE,CAEzE;CACD;AA2BD,OAAO,EAAE,kBAAkB,EAAE,CAAC"}
package/dist/catalog.cjs CHANGED
@@ -20,6 +20,9 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/catalog.ts
21
21
  var catalog_exports = {};
22
22
  __export(catalog_exports, {
23
+ BROTU_SUPPORTED_CATEGORIES: () => BROTU_SUPPORTED_CATEGORIES,
24
+ DEFAULT_BROTU_API_URL: () => DEFAULT_BROTU_API_URL,
25
+ describeModels: () => describeModels,
23
26
  getAvailableModels: () => getAvailableModels,
24
27
  getModel: () => getModel,
25
28
  getModels: () => getModels,
@@ -995,8 +998,16 @@ var PROVIDER_BASE_URLS = {
995
998
  elevenlabs: "https://api.elevenlabs.io",
996
999
  google: "https://generativelanguage.googleapis.com",
997
1000
  openai: "https://api.openai.com",
998
- qwen: "https://dashscope-intl.aliyuncs.com"
1001
+ qwen: "https://dashscope-intl.aliyuncs.com",
1002
+ brotu: "https://api.brotu.app"
999
1003
  };
1004
+ var DEFAULT_BROTU_API_URL = PROVIDER_BASE_URLS.brotu;
1005
+ function vendorProviders(options) {
1006
+ return options.providers ?? {};
1007
+ }
1008
+ function brotuApiKey(options) {
1009
+ return options.apiKey?.trim() || void 0;
1010
+ }
1000
1011
  var BUILT_IN = [
1001
1012
  ...KLING_CATALOG,
1002
1013
  ...KLING_AUDIO_CATALOG,
@@ -1052,28 +1063,73 @@ function resolveProvider(modelId, options) {
1052
1063
  `Model "${modelId}" declares no provider, so nothing knows how to run it.`
1053
1064
  );
1054
1065
  }
1055
- const configured = options.providers[id];
1056
- if (!configured) {
1057
- const owned = Object.keys(options.providers).join(", ") || "none";
1058
- throw new Error(
1059
- `Model "${modelId}" runs on "${id}", but no API key was given for it (configured: ${owned}).`
1060
- );
1066
+ const configured = vendorProviders(options)[id];
1067
+ if (configured) {
1068
+ const baseUrl = configured.baseUrl ?? PROVIDER_BASE_URLS[id];
1069
+ if (!baseUrl) {
1070
+ throw new Error(
1071
+ `Provider "${id}" has no known base URL \u2014 pass providers.${id}.baseUrl.`
1072
+ );
1073
+ }
1074
+ return { id, apiKey: configured.apiKey, baseUrl: baseUrl.replace(/\/$/, "") };
1061
1075
  }
1062
- const baseUrl = configured.baseUrl ?? PROVIDER_BASE_URLS[id];
1063
- if (!baseUrl) {
1064
- throw new Error(
1065
- `Provider "${id}" has no known base URL \u2014 pass providers.${id}.baseUrl.`
1066
- );
1076
+ const platformKey = brotuApiKey(options);
1077
+ if (platformKey) {
1078
+ return {
1079
+ id: "brotu",
1080
+ apiKey: platformKey,
1081
+ baseUrl: (options.apiUrl ?? DEFAULT_BROTU_API_URL).replace(/\/$/, "")
1082
+ };
1067
1083
  }
1068
- return { id, apiKey: configured.apiKey, baseUrl: baseUrl.replace(/\/$/, "") };
1084
+ const owned = Object.keys(vendorProviders(options)).join(", ") || "none";
1085
+ throw new Error(
1086
+ `Model "${modelId}" runs on "${id}", but no API key was given for it (configured: ${owned}). Pass a Brotu key to generate on the platform.`
1087
+ );
1088
+ }
1089
+ var BROTU_SUPPORTED_CATEGORIES = ["image", "video"];
1090
+ function describeModels(options) {
1091
+ const vendors = vendorProviders(options);
1092
+ const platformKey = brotuApiKey(options);
1093
+ return catalog.map((model) => {
1094
+ const provider = model.provider;
1095
+ if (!provider) {
1096
+ return {
1097
+ model,
1098
+ runsOn: "(none)",
1099
+ runnable: false,
1100
+ reason: "The model declares no provider."
1101
+ };
1102
+ }
1103
+ if (provider in vendors) {
1104
+ return { model, runsOn: provider, runnable: true };
1105
+ }
1106
+ if (platformKey) {
1107
+ if (BROTU_SUPPORTED_CATEGORIES.includes(model.category)) {
1108
+ return { model, runsOn: "brotu", runnable: true };
1109
+ }
1110
+ return {
1111
+ model,
1112
+ runsOn: provider,
1113
+ runnable: false,
1114
+ reason: `Brotu generates ${BROTU_SUPPORTED_CATEGORIES.join(" and ")} only. Pass providers.${provider} to run this one.`
1115
+ };
1116
+ }
1117
+ return {
1118
+ model,
1119
+ runsOn: provider,
1120
+ runnable: false,
1121
+ reason: `No key for "${provider}". Pass a Brotu key or providers.${provider}.`
1122
+ };
1123
+ });
1069
1124
  }
1070
1125
  function getAvailableModels(options) {
1071
- return catalog.filter(
1072
- (model) => model.provider && model.provider in options.providers
1073
- );
1126
+ return describeModels(options).filter((entry) => entry.runnable).map((entry) => entry.model);
1074
1127
  }
1075
1128
  // Annotate the CommonJS export names for ESM import in node:
1076
1129
  0 && (module.exports = {
1130
+ BROTU_SUPPORTED_CATEGORIES,
1131
+ DEFAULT_BROTU_API_URL,
1132
+ describeModels,
1077
1133
  getAvailableModels,
1078
1134
  getModel,
1079
1135
  getModels,
package/dist/catalog.d.ts CHANGED
@@ -1,5 +1,6 @@
1
- import type { AIModelConfig } from "./constants/model.types";
1
+ import type { AIModelCategory, AIModelConfig } from "./constants/model.types";
2
2
  import type { BrotuAIOptions, ResolvedProvider } from "./types";
3
+ export declare const DEFAULT_BROTU_API_URL: string;
3
4
  /**
4
5
  * Add models, or patch built-in ones, matching on id.
5
6
  *
@@ -22,6 +23,27 @@ export declare function getProviders(): string[];
22
23
  * aggregator, so there is no wallet to guess between.
23
24
  */
24
25
  export declare function resolveProvider(modelId: string, options: BrotuAIOptions): ResolvedProvider;
26
+ /**
27
+ * What the platform generates on credits. Speech and text are the vendor's
28
+ * work, so a Brotu key alone does not reach them. The Brotu adapter reads this
29
+ * too, so the catalog and the adapter cannot drift apart.
30
+ */
31
+ export declare const BROTU_SUPPORTED_CATEGORIES: AIModelCategory[];
32
+ /** A model plus where it would actually run with the keys at hand. */
33
+ export interface ModelAvailability {
34
+ model: AIModelConfig;
35
+ /** Provider that serves it: a vendor id, or "brotu" for the platform. */
36
+ runsOn: string;
37
+ /** False when nothing configured can run it. `reason` says why. */
38
+ runnable: boolean;
39
+ reason?: string;
40
+ }
41
+ /**
42
+ * Every catalog model, each labelled with the host that would serve it. This is
43
+ * the honest view: `runnable: false` entries are the ones a key is missing for,
44
+ * and they stay in the list precisely so the caller can see what is missing.
45
+ */
46
+ export declare function describeModels(options: BrotuAIOptions): ModelAvailability[];
25
47
  /** Models the caller can actually run, given the keys they supplied. */
26
48
  export declare function getAvailableModels(options: BrotuAIOptions): AIModelConfig[];
27
49
  //# sourceMappingURL=catalog.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAU7D,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAkChE;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,MAAM,GAAE,aAAa,EAAO,GAAG,IAAI,CAUjE;AAED,0EAA0E;AAC1E,wBAAgB,YAAY,IAAI,IAAI,CAGnC;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAEnE;AAED,wBAAgB,SAAS,IAAI,aAAa,EAAE,CAE3C;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEjD;AAED,wDAAwD;AACxD,wBAAgB,YAAY,IAAI,MAAM,EAAE,CAQvC;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC9B,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,cAAc,GACrB,gBAAgB,CA6BlB;AAED,wEAAwE;AACxE,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,cAAc,GAAG,aAAa,EAAE,CAI3E"}
1
+ {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAU9E,OAAO,KAAK,EAAE,cAAc,EAAkB,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAgBhF,eAAO,MAAM,qBAAqB,QAA2B,CAAC;AA+B9D;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,MAAM,GAAE,aAAa,EAAO,GAAG,IAAI,CAUjE;AAED,0EAA0E;AAC1E,wBAAgB,YAAY,IAAI,IAAI,CAGnC;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAEnE;AAED,wBAAgB,SAAS,IAAI,aAAa,EAAE,CAE3C;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEjD;AAED,wDAAwD;AACxD,wBAAgB,YAAY,IAAI,MAAM,EAAE,CAQvC;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC9B,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,cAAc,GACrB,gBAAgB,CAqClB;AAED;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,EAAE,eAAe,EAAuB,CAAC;AAEhF,sEAAsE;AACtE,MAAM,WAAW,iBAAiB;IACjC,KAAK,EAAE,aAAa,CAAC;IACrB,yEAAyE;IACzE,MAAM,EAAE,MAAM,CAAC;IACf,mEAAmE;IACnE,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,cAAc,GAAG,iBAAiB,EAAE,CAmC3E;AAED,wEAAwE;AACxE,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,cAAc,GAAG,aAAa,EAAE,CAI3E"}
package/dist/catalog.js CHANGED
@@ -1,4 +1,7 @@
1
1
  import {
2
+ BROTU_SUPPORTED_CATEGORIES,
3
+ DEFAULT_BROTU_API_URL,
4
+ describeModels,
2
5
  getAvailableModels,
3
6
  getModel,
4
7
  getModels,
@@ -7,8 +10,11 @@ import {
7
10
  registerModels,
8
11
  resetCatalog,
9
12
  resolveProvider
10
- } from "./chunk-PL534BFN.js";
13
+ } from "./chunk-3MC3RDAJ.js";
11
14
  export {
15
+ BROTU_SUPPORTED_CATEGORIES,
16
+ DEFAULT_BROTU_API_URL,
17
+ describeModels,
12
18
  getAvailableModels,
13
19
  getModel,
14
20
  getModels,
@@ -1159,8 +1159,16 @@ var PROVIDER_BASE_URLS = {
1159
1159
  elevenlabs: "https://api.elevenlabs.io",
1160
1160
  google: "https://generativelanguage.googleapis.com",
1161
1161
  openai: "https://api.openai.com",
1162
- qwen: "https://dashscope-intl.aliyuncs.com"
1162
+ qwen: "https://dashscope-intl.aliyuncs.com",
1163
+ brotu: "https://api.brotu.app"
1163
1164
  };
1165
+ var DEFAULT_BROTU_API_URL = PROVIDER_BASE_URLS.brotu;
1166
+ function vendorProviders(options) {
1167
+ return options.providers ?? {};
1168
+ }
1169
+ function brotuApiKey(options) {
1170
+ return options.apiKey?.trim() || void 0;
1171
+ }
1164
1172
  var BUILT_IN = [
1165
1173
  ...KLING_CATALOG,
1166
1174
  ...KLING_AUDIO_CATALOG,
@@ -1216,25 +1224,67 @@ function resolveProvider(modelId, options) {
1216
1224
  `Model "${modelId}" declares no provider, so nothing knows how to run it.`
1217
1225
  );
1218
1226
  }
1219
- const configured = options.providers[id];
1220
- if (!configured) {
1221
- const owned = Object.keys(options.providers).join(", ") || "none";
1222
- throw new Error(
1223
- `Model "${modelId}" runs on "${id}", but no API key was given for it (configured: ${owned}).`
1224
- );
1227
+ const configured = vendorProviders(options)[id];
1228
+ if (configured) {
1229
+ const baseUrl = configured.baseUrl ?? PROVIDER_BASE_URLS[id];
1230
+ if (!baseUrl) {
1231
+ throw new Error(
1232
+ `Provider "${id}" has no known base URL \u2014 pass providers.${id}.baseUrl.`
1233
+ );
1234
+ }
1235
+ return { id, apiKey: configured.apiKey, baseUrl: baseUrl.replace(/\/$/, "") };
1225
1236
  }
1226
- const baseUrl = configured.baseUrl ?? PROVIDER_BASE_URLS[id];
1227
- if (!baseUrl) {
1228
- throw new Error(
1229
- `Provider "${id}" has no known base URL \u2014 pass providers.${id}.baseUrl.`
1230
- );
1237
+ const platformKey = brotuApiKey(options);
1238
+ if (platformKey) {
1239
+ return {
1240
+ id: "brotu",
1241
+ apiKey: platformKey,
1242
+ baseUrl: (options.apiUrl ?? DEFAULT_BROTU_API_URL).replace(/\/$/, "")
1243
+ };
1231
1244
  }
1232
- return { id, apiKey: configured.apiKey, baseUrl: baseUrl.replace(/\/$/, "") };
1245
+ const owned = Object.keys(vendorProviders(options)).join(", ") || "none";
1246
+ throw new Error(
1247
+ `Model "${modelId}" runs on "${id}", but no API key was given for it (configured: ${owned}). Pass a Brotu key to generate on the platform.`
1248
+ );
1249
+ }
1250
+ var BROTU_SUPPORTED_CATEGORIES = ["image", "video"];
1251
+ function describeModels(options) {
1252
+ const vendors = vendorProviders(options);
1253
+ const platformKey = brotuApiKey(options);
1254
+ return catalog.map((model) => {
1255
+ const provider = model.provider;
1256
+ if (!provider) {
1257
+ return {
1258
+ model,
1259
+ runsOn: "(none)",
1260
+ runnable: false,
1261
+ reason: "The model declares no provider."
1262
+ };
1263
+ }
1264
+ if (provider in vendors) {
1265
+ return { model, runsOn: provider, runnable: true };
1266
+ }
1267
+ if (platformKey) {
1268
+ if (BROTU_SUPPORTED_CATEGORIES.includes(model.category)) {
1269
+ return { model, runsOn: "brotu", runnable: true };
1270
+ }
1271
+ return {
1272
+ model,
1273
+ runsOn: provider,
1274
+ runnable: false,
1275
+ reason: `Brotu generates ${BROTU_SUPPORTED_CATEGORIES.join(" and ")} only. Pass providers.${provider} to run this one.`
1276
+ };
1277
+ }
1278
+ return {
1279
+ model,
1280
+ runsOn: provider,
1281
+ runnable: false,
1282
+ reason: `No key for "${provider}". Pass a Brotu key or providers.${provider}.`
1283
+ };
1284
+ });
1233
1285
  }
1234
1286
  function getAvailableModels(options) {
1235
- return catalog.filter(
1236
- (model) => model.provider && model.provider in options.providers
1237
- );
1287
+ return describeModels(options).filter((entry) => entry.runnable).map((entry) => entry.model);
1238
1288
  }
1239
1289
 
1240
1290
  export {
@@ -1266,6 +1316,7 @@ export {
1266
1316
  QWEN_AUDIO_MODELS,
1267
1317
  QWEN_TEXT_MODELS,
1268
1318
  QWEN_CATALOG,
1319
+ DEFAULT_BROTU_API_URL,
1269
1320
  registerModels,
1270
1321
  resetCatalog,
1271
1322
  getModel,
@@ -1273,5 +1324,7 @@ export {
1273
1324
  hasModel,
1274
1325
  getProviders,
1275
1326
  resolveProvider,
1327
+ BROTU_SUPPORTED_CATEGORIES,
1328
+ describeModels,
1276
1329
  getAvailableModels
1277
1330
  };
package/dist/client.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { getModel } from "./catalog";
1
+ import { getModel, type ModelAvailability } from "./catalog";
2
2
  import type { AIModelConfig } from "./constants/model.types";
3
3
  import { type AIError, type Generation, type Result } from "./helpers/result";
4
4
  import { type Job, type JobSnapshot } from "./lib/jobs";
@@ -14,19 +14,30 @@ export interface BrotuAI {
14
14
  submit(params: ImageGenerationParams): Promise<Result<Job>>;
15
15
  /** submit + wait. Convenient, but holds the call open for the whole run. */
16
16
  generate(params: ImageGenerationParams): Promise<Result<Generation>>;
17
+ /**
18
+ * Every image model, each labelled with the host that would serve it
19
+ * (`runsOn`) and whether your keys reach it (`runnable`). Unreachable
20
+ * models stay in the list, with `reason`, so the gap is visible.
21
+ */
22
+ list(): ModelAvailability[];
17
23
  };
18
24
  video: {
19
25
  submit(params: VideoGenerationParams): Promise<Result<Job>>;
20
26
  generate(params: VideoGenerationParams): Promise<Result<Generation>>;
27
+ list(): ModelAvailability[];
21
28
  };
22
29
  text: {
23
30
  submit(params: TextGenerationParams): Promise<Result<Job>>;
24
31
  generate(params: TextGenerationParams): Promise<Result<Generation>>;
32
+ /** Text runs on the vendor, so these need `providers`, not a Brotu key. */
33
+ list(): ModelAvailability[];
25
34
  };
26
35
  /** Speech synthesis. `prompt` is the text to speak. */
27
36
  audio: {
28
37
  submit(params: AudioGenerationParams): Promise<Result<Job>>;
29
38
  generate(params: AudioGenerationParams): Promise<Result<Generation>>;
39
+ /** Speech runs on the vendor, so these need `providers`, not a Brotu key. */
40
+ list(): ModelAvailability[];
30
41
  };
31
42
  jobs: {
32
43
  /** Ask once. Returns straight away, settled or not. */
@@ -81,7 +92,7 @@ export interface BrotuAI {
81
92
  /** Compose or edit across up to ten references. */
82
93
  imageOmni(input: ImageOmniInput): Promise<Result<Job>>;
83
94
  };
84
- /** Models runnable with the keys given to this client. */
95
+ /** Models this client can run. */
85
96
  models(): AIModelConfig[];
86
97
  /**
87
98
  * What this generation will be billed for, before running it. Always reports
@@ -90,7 +101,7 @@ export interface BrotuAI {
90
101
  */
91
102
  estimateCost(type: GenerationType, params: GenerationParams): Promise<Result<CostEstimate>>;
92
103
  }
93
- export declare function brotuClient(options: BrotuAIOptions): BrotuAI;
104
+ export declare function brotu(options: BrotuAIOptions): BrotuAI;
94
105
  export type { AIError, Generation, Result };
95
106
  export { getModel };
96
107
  //# sourceMappingURL=client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAOA,OAAO,EAGN,QAAQ,EACR,KAAK,iBAAiB,EAGtB,MAAM,WAAW,CAAC;AACnB,OAAO,KAAK,EAAmB,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC9E,OAAO,EACN,KAAK,OAAO,EAGZ,KAAK,UAAU,EAEf,KAAK,MAAM,EACX,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAEN,KAAK,GAAG,EACR,KAAK,WAAW,EAEhB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAGN,KAAK,aAAa,EAGlB,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EACX,qBAAqB,EAErB,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAEhB,cAAc,EACd,qBAAqB,EACrB,oBAAoB,EACpB,qBAAqB,EACrB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EACN,KAAK,WAAW,EAChB,KAAK,cAAc,EAEnB,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9C,mDAAmD;AACnD,eAAO,MAAM,gBAAgB,YAC5B,UAAU,EACV,YAAY,EACZ,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,MAAM,CACG,CAAC;AAOX,MAAM,WAAW,OAAO;IACvB,KAAK,EAAE;QACN,sEAAsE;QACtE,MAAM,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAC5D,4EAA4E;QAC5E,QAAQ,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;QACrE;;;;WAIG;QACH,IAAI,IAAI,iBAAiB,EAAE,CAAC;KAC5B,CAAC;IACF,KAAK,EAAE;QACN,MAAM,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAC5D,QAAQ,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;QACrE,IAAI,IAAI,iBAAiB,EAAE,CAAC;KAC5B,CAAC;IACF,IAAI,EAAE;QACL,MAAM,CAAC,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAC3D,QAAQ,CAAC,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;QACpE,2EAA2E;QAC3E,IAAI,IAAI,iBAAiB,EAAE,CAAC;KAC5B,CAAC;IACF,uDAAuD;IACvD,KAAK,EAAE;QACN,MAAM,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAC5D,QAAQ,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;QACrE,6EAA6E;QAC7E,IAAI,IAAI,iBAAiB,EAAE,CAAC;KAC5B,CAAC;IACF,IAAI,EAAE;QACL,uDAAuD;QACvD,IAAI,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC;QAC7C,wDAAwD;QACxD,IAAI,CACH,GAAG,EAAE,GAAG,EACR,OAAO,CAAC,EAAE;YAAE,SAAS,CAAC,EAAE,MAAM,CAAA;SAAE,GAC9B,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;KAC/B,CAAC;IACF;;;OAGG;IACH,OAAO,EAAE;QACR,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAAC;QACzC,KAAK,IAAI,IAAI,CAAC;QACd,GAAG,IAAI,aAAa,GAAG,SAAS,CAAC;KACjC,CAAC;IACF;;;OAGG;IACH,MAAM,CAAC,EAAE;QACR;;;;;WAKG;QACH,SAAS,CACR,KAAK,EAAE,qBAAqB,GAAG;YAAE,qBAAqB,CAAC,EAAE,MAAM,CAAA;SAAE,GAC/D,OAAO,CAAC,MAAM,CAAC;YAAE,aAAa,CAAC,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,gBAAgB,EAAE,CAAA;SAAE,CAAC,CAAC,CAAC;KAC5E,CAAC;IACF;;;;;OAKG;IACH,KAAK,CAAC,EAAE;QACP,wDAAwD;QACxD,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAC/D,8EAA8E;QAC9E,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QACvD,6DAA6D;QAC7D,MAAM,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QACjD,iDAAiD;QACjD,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAC3D,mDAAmD;QACnD,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;KACvD,CAAC;IACF,kCAAkC;IAClC,MAAM,IAAI,aAAa,EAAE,CAAC;IAC1B;;;;OAIG;IACH,YAAY,CACX,IAAI,EAAE,cAAc,EACpB,MAAM,EAAE,gBAAgB,GACtB,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;CACjC;AAED,wBAAgB,KAAK,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CA6lBtD;AAED,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,CAAC"}
@@ -2,7 +2,7 @@ import type { GenerationOutput } from "../ports/content-generator.port";
2
2
  export type AIErrorCode =
3
3
  /** The model id is not in the catalog. */
4
4
  "unknown_model"
5
- /** The model's provider has no API key configured on this client. */
5
+ /** The model's provider has no vendor key and no Brotu key. */
6
6
  | "missing_key"
7
7
  /** No adapter ships for that provider. */
8
8
  | "unsupported_provider"
@@ -1 +1 @@
1
- {"version":3,"file":"result.d.ts","sourceRoot":"","sources":["../../src/helpers/result.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAExE,MAAM,MAAM,WAAW;AACtB,0CAA0C;AACxC,eAAe;AACjB,qEAAqE;GACnE,aAAa;AACf,0CAA0C;GACxC,sBAAsB;AACxB,kEAAkE;GAChE,iBAAiB;AACnB,yEAAyE;GACvE,gBAAgB;AAClB,2EAA2E;GACzE,SAAS,CAAC;AAEb,MAAM,WAAW,OAAO;IACvB,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wDAAwD;IACxD,KAAK,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,MAAM,CAAC,CAAC,IACjB;IAAE,IAAI,EAAE,CAAC,CAAC;IAAC,KAAK,EAAE,IAAI,CAAA;CAAE,GACxB;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC;AAElC,wBAAgB,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAExC;AAED,wBAAgB,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,CAEjD;AAED,gFAAgF;AAChF,wBAAgB,QAAQ,CAAC,CAAC,EACzB,IAAI,EAAE,WAAW,EACjB,KAAK,EAAE,OAAO,EACd,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7C,MAAM,CAAC,CAAC,CAAC,CAOX;AAED,iFAAiF;AACjF,MAAM,WAAW,UAAU;IAC1B,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,MAAM,CAAC;IACzB,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC"}
1
+ {"version":3,"file":"result.d.ts","sourceRoot":"","sources":["../../src/helpers/result.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAExE,MAAM,MAAM,WAAW;AACtB,0CAA0C;AACxC,eAAe;AACjB,+DAA+D;GAC7D,aAAa;AACf,0CAA0C;GACxC,sBAAsB;AACxB,kEAAkE;GAChE,iBAAiB;AACnB,yEAAyE;GACvE,gBAAgB;AAClB,2EAA2E;GACzE,SAAS,CAAC;AAEb,MAAM,WAAW,OAAO;IACvB,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wDAAwD;IACxD,KAAK,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,MAAM,CAAC,CAAC,IACjB;IAAE,IAAI,EAAE,CAAC,CAAC;IAAC,KAAK,EAAE,IAAI,CAAA;CAAE,GACxB;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC;AAElC,wBAAgB,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAExC;AAED,wBAAgB,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,CAEjD;AAED,gFAAgF;AAChF,wBAAgB,QAAQ,CAAC,CAAC,EACzB,IAAI,EAAE,WAAW,EACjB,KAAK,EAAE,OAAO,EACd,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7C,MAAM,CAAC,CAAC,CAAC,CAOX;AAED,iFAAiF;AACjF,MAAM,WAAW,UAAU;IAC1B,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,MAAM,CAAC;IACzB,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC"}