@brotu/ai 0.4.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 +45 -7
- package/dist/adapters/brotu.adapter.d.ts.map +1 -1
- package/dist/catalog.cjs +41 -7
- package/dist/catalog.d.ts +22 -1
- package/dist/catalog.d.ts.map +1 -1
- package/dist/catalog.js +5 -1
- package/dist/{chunk-QOWHHKSI.js → chunk-3MC3RDAJ.js} +39 -7
- package/dist/client.d.ts +13 -2
- package/dist/client.d.ts.map +1 -1
- package/dist/index.cjs +133 -45
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +69 -11
- package/dist/lib/hooks.d.ts +32 -0
- package/dist/lib/hooks.d.ts.map +1 -0
- package/dist/types.d.ts +9 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -23,7 +23,7 @@
|
|
|
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 `
|
|
26
|
+
Kling, Seedance, Wan, Veo, Gemini, gpt-image and ElevenLabs all speak different HTTP. This package is one `brotu` in front of them.
|
|
27
27
|
|
|
28
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.
|
|
29
29
|
|
|
@@ -46,9 +46,9 @@ pnpm add @brotu/ai
|
|
|
46
46
|
## Client
|
|
47
47
|
|
|
48
48
|
```ts
|
|
49
|
-
import {
|
|
49
|
+
import { brotu } from "@brotu/ai";
|
|
50
50
|
|
|
51
|
-
const ai =
|
|
51
|
+
const ai = brotu({
|
|
52
52
|
apiKey: process.env.BROTU_API_KEY!, // brotu_sk_… from https://brotu.app
|
|
53
53
|
providers: {
|
|
54
54
|
kling: { apiKey: process.env.KLING_API_KEY! },
|
|
@@ -71,18 +71,36 @@ Every public call returns `{ data, error }`. `data` is unusable until you narrow
|
|
|
71
71
|
|
|
72
72
|
| Surface | Methods |
|
|
73
73
|
|---|---|
|
|
74
|
-
| `ai.video` | `submit` / `generate` |
|
|
75
|
-
| `ai.image` | `submit` / `generate` |
|
|
76
|
-
| `ai.text` | `submit` / `generate` |
|
|
77
|
-
| `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` |
|
|
78
78
|
| `ai.jobs` | `poll` / `wait` |
|
|
79
79
|
| `ai.webhook` | `set` / `clear` / `get` |
|
|
80
|
+
| `hooks` | constructor option: your own code on start, success and failure |
|
|
80
81
|
| `ai.estimateCost` | units, and USD when verified |
|
|
81
82
|
| `ai.kling` | `motionControl`, `omniVideo`, `avatar`, `outpainting`, `imageOmni` |
|
|
82
83
|
| `ai.google` | `omniVideo` (conversational refine) |
|
|
83
84
|
|
|
84
85
|
`ai.kling` and `ai.google` exist only when that key is set.
|
|
85
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
|
+
|
|
86
104
|
## Video
|
|
87
105
|
|
|
88
106
|
`submit` returns a job handle. `generate` waits. Video takes minutes, so do not `generate` inside a request handler.
|
|
@@ -205,6 +223,26 @@ The POST is JSON. Check `x-brotu-event` and, if you set a secret, `x-brotu-webho
|
|
|
205
223
|
|
|
206
224
|
Error codes: `unknown_model`, `missing_key`, `unsupported_provider`, `invalid_request`, `provider_error`, `timeout`.
|
|
207
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
|
+
|
|
208
246
|
## Motion control, avatars, omni
|
|
209
247
|
|
|
210
248
|
Not on `ai.video`. A shared signature would be a lie.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"brotu.adapter.d.ts","sourceRoot":"","sources":["../../src/adapters/brotu.adapter.ts"],"names":[],"mappings":"
|
|
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,7 +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,
|
|
23
24
|
DEFAULT_BROTU_API_URL: () => DEFAULT_BROTU_API_URL,
|
|
25
|
+
describeModels: () => describeModels,
|
|
24
26
|
getAvailableModels: () => getAvailableModels,
|
|
25
27
|
getModel: () => getModel,
|
|
26
28
|
getModels: () => getModels,
|
|
@@ -1084,18 +1086,50 @@ function resolveProvider(modelId, options) {
|
|
|
1084
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.`
|
|
1085
1087
|
);
|
|
1086
1088
|
}
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
return catalog.filter((model) => Boolean(model.provider));
|
|
1090
|
-
}
|
|
1089
|
+
var BROTU_SUPPORTED_CATEGORIES = ["image", "video"];
|
|
1090
|
+
function describeModels(options) {
|
|
1091
1091
|
const vendors = vendorProviders(options);
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
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
|
+
});
|
|
1124
|
+
}
|
|
1125
|
+
function getAvailableModels(options) {
|
|
1126
|
+
return describeModels(options).filter((entry) => entry.runnable).map((entry) => entry.model);
|
|
1095
1127
|
}
|
|
1096
1128
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1097
1129
|
0 && (module.exports = {
|
|
1130
|
+
BROTU_SUPPORTED_CATEGORIES,
|
|
1098
1131
|
DEFAULT_BROTU_API_URL,
|
|
1132
|
+
describeModels,
|
|
1099
1133
|
getAvailableModels,
|
|
1100
1134
|
getModel,
|
|
1101
1135
|
getModels,
|
package/dist/catalog.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
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
3
|
export declare const DEFAULT_BROTU_API_URL: string;
|
|
4
4
|
/**
|
|
@@ -23,6 +23,27 @@ export declare function getProviders(): string[];
|
|
|
23
23
|
* aggregator, so there is no wallet to guess between.
|
|
24
24
|
*/
|
|
25
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[];
|
|
26
47
|
/** Models the caller can actually run, given the keys they supplied. */
|
|
27
48
|
export declare function getAvailableModels(options: BrotuAIOptions): AIModelConfig[];
|
|
28
49
|
//# sourceMappingURL=catalog.d.ts.map
|
package/dist/catalog.d.ts.map
CHANGED
|
@@ -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;
|
|
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,5 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
+
BROTU_SUPPORTED_CATEGORIES,
|
|
2
3
|
DEFAULT_BROTU_API_URL,
|
|
4
|
+
describeModels,
|
|
3
5
|
getAvailableModels,
|
|
4
6
|
getModel,
|
|
5
7
|
getModels,
|
|
@@ -8,9 +10,11 @@ import {
|
|
|
8
10
|
registerModels,
|
|
9
11
|
resetCatalog,
|
|
10
12
|
resolveProvider
|
|
11
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-3MC3RDAJ.js";
|
|
12
14
|
export {
|
|
15
|
+
BROTU_SUPPORTED_CATEGORIES,
|
|
13
16
|
DEFAULT_BROTU_API_URL,
|
|
17
|
+
describeModels,
|
|
14
18
|
getAvailableModels,
|
|
15
19
|
getModel,
|
|
16
20
|
getModels,
|
|
@@ -1247,14 +1247,44 @@ function resolveProvider(modelId, options) {
|
|
|
1247
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
1248
|
);
|
|
1249
1249
|
}
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
return catalog.filter((model) => Boolean(model.provider));
|
|
1253
|
-
}
|
|
1250
|
+
var BROTU_SUPPORTED_CATEGORIES = ["image", "video"];
|
|
1251
|
+
function describeModels(options) {
|
|
1254
1252
|
const vendors = vendorProviders(options);
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
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
|
+
});
|
|
1285
|
+
}
|
|
1286
|
+
function getAvailableModels(options) {
|
|
1287
|
+
return describeModels(options).filter((entry) => entry.runnable).map((entry) => entry.model);
|
|
1258
1288
|
}
|
|
1259
1289
|
|
|
1260
1290
|
export {
|
|
@@ -1294,5 +1324,7 @@ export {
|
|
|
1294
1324
|
hasModel,
|
|
1295
1325
|
getProviders,
|
|
1296
1326
|
resolveProvider,
|
|
1327
|
+
BROTU_SUPPORTED_CATEGORIES,
|
|
1328
|
+
describeModels,
|
|
1297
1329
|
getAvailableModels
|
|
1298
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. */
|
|
@@ -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
|
|
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
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAOA,OAAO,
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/index.cjs
CHANGED
|
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
+
BROTU_SUPPORTED_CATEGORIES: () => BROTU_SUPPORTED_CATEGORIES,
|
|
33
34
|
BYTEPLUS_CATALOG: () => BYTEPLUS_CATALOG,
|
|
34
35
|
BYTEPLUS_MODELS: () => BYTEPLUS_MODELS,
|
|
35
36
|
BrotuAdapter: () => BrotuAdapter,
|
|
@@ -61,9 +62,10 @@ __export(index_exports, {
|
|
|
61
62
|
QWEN_TEXT_MODELS: () => QWEN_TEXT_MODELS,
|
|
62
63
|
QWEN_VIDEO_MODELS: () => QWEN_VIDEO_MODELS,
|
|
63
64
|
QwenAdapter: () => QwenAdapter,
|
|
64
|
-
|
|
65
|
+
brotu: () => brotu,
|
|
65
66
|
createS3Storage: () => createS3Storage,
|
|
66
67
|
deliverWebhook: () => deliverWebhook,
|
|
68
|
+
describeModels: () => describeModels,
|
|
67
69
|
fail: () => fail,
|
|
68
70
|
getAvailableModels: () => getAvailableModels,
|
|
69
71
|
getModel: () => getModel,
|
|
@@ -80,34 +82,6 @@ __export(index_exports, {
|
|
|
80
82
|
});
|
|
81
83
|
module.exports = __toCommonJS(index_exports);
|
|
82
84
|
|
|
83
|
-
// src/lib/jobs.ts
|
|
84
|
-
var import_node_async_hooks = require("async_hooks");
|
|
85
|
-
var PendingJob = class extends Error {
|
|
86
|
-
taskId;
|
|
87
|
-
pollEndpoint;
|
|
88
|
-
constructor(taskId, pollEndpoint) {
|
|
89
|
-
super(`Job ${taskId} was submitted and is still running.`);
|
|
90
|
-
this.name = "PendingJob";
|
|
91
|
-
this.taskId = taskId;
|
|
92
|
-
this.pollEndpoint = pollEndpoint;
|
|
93
|
-
}
|
|
94
|
-
};
|
|
95
|
-
function isPendingJob(error) {
|
|
96
|
-
return error instanceof PendingJob;
|
|
97
|
-
}
|
|
98
|
-
var submitMode = new import_node_async_hooks.AsyncLocalStorage();
|
|
99
|
-
function runInSubmitMode(fn) {
|
|
100
|
-
return submitMode.run(true, fn);
|
|
101
|
-
}
|
|
102
|
-
function isSubmitMode() {
|
|
103
|
-
return submitMode.getStore() === true;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// src/ports/content-generator.port.ts
|
|
107
|
-
function expiresInHours(hours) {
|
|
108
|
-
return new Date(Date.now() + hours * 36e5).toISOString();
|
|
109
|
-
}
|
|
110
|
-
|
|
111
85
|
// src/providers/byteplus.models.ts
|
|
112
86
|
var FPS = 24;
|
|
113
87
|
var PIXELS = {
|
|
@@ -1357,14 +1331,72 @@ function resolveProvider(modelId, options) {
|
|
|
1357
1331
|
`Model "${modelId}" runs on "${id}", but no API key was given for it (configured: ${owned}). Pass a Brotu key to generate on the platform.`
|
|
1358
1332
|
);
|
|
1359
1333
|
}
|
|
1334
|
+
var BROTU_SUPPORTED_CATEGORIES = ["image", "video"];
|
|
1335
|
+
function describeModels(options) {
|
|
1336
|
+
const vendors = vendorProviders(options);
|
|
1337
|
+
const platformKey = brotuApiKey(options);
|
|
1338
|
+
return catalog.map((model) => {
|
|
1339
|
+
const provider = model.provider;
|
|
1340
|
+
if (!provider) {
|
|
1341
|
+
return {
|
|
1342
|
+
model,
|
|
1343
|
+
runsOn: "(none)",
|
|
1344
|
+
runnable: false,
|
|
1345
|
+
reason: "The model declares no provider."
|
|
1346
|
+
};
|
|
1347
|
+
}
|
|
1348
|
+
if (provider in vendors) {
|
|
1349
|
+
return { model, runsOn: provider, runnable: true };
|
|
1350
|
+
}
|
|
1351
|
+
if (platformKey) {
|
|
1352
|
+
if (BROTU_SUPPORTED_CATEGORIES.includes(model.category)) {
|
|
1353
|
+
return { model, runsOn: "brotu", runnable: true };
|
|
1354
|
+
}
|
|
1355
|
+
return {
|
|
1356
|
+
model,
|
|
1357
|
+
runsOn: provider,
|
|
1358
|
+
runnable: false,
|
|
1359
|
+
reason: `Brotu generates ${BROTU_SUPPORTED_CATEGORIES.join(" and ")} only. Pass providers.${provider} to run this one.`
|
|
1360
|
+
};
|
|
1361
|
+
}
|
|
1362
|
+
return {
|
|
1363
|
+
model,
|
|
1364
|
+
runsOn: provider,
|
|
1365
|
+
runnable: false,
|
|
1366
|
+
reason: `No key for "${provider}". Pass a Brotu key or providers.${provider}.`
|
|
1367
|
+
};
|
|
1368
|
+
});
|
|
1369
|
+
}
|
|
1360
1370
|
function getAvailableModels(options) {
|
|
1361
|
-
|
|
1362
|
-
|
|
1371
|
+
return describeModels(options).filter((entry) => entry.runnable).map((entry) => entry.model);
|
|
1372
|
+
}
|
|
1373
|
+
|
|
1374
|
+
// src/lib/jobs.ts
|
|
1375
|
+
var import_node_async_hooks = require("async_hooks");
|
|
1376
|
+
var PendingJob = class extends Error {
|
|
1377
|
+
taskId;
|
|
1378
|
+
pollEndpoint;
|
|
1379
|
+
constructor(taskId, pollEndpoint) {
|
|
1380
|
+
super(`Job ${taskId} was submitted and is still running.`);
|
|
1381
|
+
this.name = "PendingJob";
|
|
1382
|
+
this.taskId = taskId;
|
|
1383
|
+
this.pollEndpoint = pollEndpoint;
|
|
1363
1384
|
}
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1385
|
+
};
|
|
1386
|
+
function isPendingJob(error) {
|
|
1387
|
+
return error instanceof PendingJob;
|
|
1388
|
+
}
|
|
1389
|
+
var submitMode = new import_node_async_hooks.AsyncLocalStorage();
|
|
1390
|
+
function runInSubmitMode(fn) {
|
|
1391
|
+
return submitMode.run(true, fn);
|
|
1392
|
+
}
|
|
1393
|
+
function isSubmitMode() {
|
|
1394
|
+
return submitMode.getStore() === true;
|
|
1395
|
+
}
|
|
1396
|
+
|
|
1397
|
+
// src/ports/content-generator.port.ts
|
|
1398
|
+
function expiresInHours(hours) {
|
|
1399
|
+
return new Date(Date.now() + hours * 36e5).toISOString();
|
|
1368
1400
|
}
|
|
1369
1401
|
|
|
1370
1402
|
// src/adapters/estimate.ts
|
|
@@ -1412,7 +1444,7 @@ var BrotuAdapter = class {
|
|
|
1412
1444
|
}
|
|
1413
1445
|
opts;
|
|
1414
1446
|
providerName = "brotu";
|
|
1415
|
-
supportedTypes =
|
|
1447
|
+
supportedTypes = BROTU_SUPPORTED_CATEGORIES;
|
|
1416
1448
|
workspaceIdCache;
|
|
1417
1449
|
get origin() {
|
|
1418
1450
|
return (this.opts.apiUrl ?? DEFAULT_API_URL).replace(/\/$/, "");
|
|
@@ -3740,6 +3772,22 @@ function failFrom(code, cause, context) {
|
|
|
3740
3772
|
});
|
|
3741
3773
|
}
|
|
3742
3774
|
|
|
3775
|
+
// src/lib/hooks.ts
|
|
3776
|
+
function hookName(kind, stage) {
|
|
3777
|
+
return `on${kind[0].toUpperCase()}${kind.slice(1)}${stage}`;
|
|
3778
|
+
}
|
|
3779
|
+
function findHook(hooks, kind, stage) {
|
|
3780
|
+
if (!hooks || !kind) return void 0;
|
|
3781
|
+
return hooks[hookName(kind, stage)];
|
|
3782
|
+
}
|
|
3783
|
+
async function runHook(hook, event) {
|
|
3784
|
+
if (!hook) return;
|
|
3785
|
+
try {
|
|
3786
|
+
await hook(event);
|
|
3787
|
+
} catch {
|
|
3788
|
+
}
|
|
3789
|
+
}
|
|
3790
|
+
|
|
3743
3791
|
// src/lib/storage.ts
|
|
3744
3792
|
async function loadS3(config) {
|
|
3745
3793
|
let s3;
|
|
@@ -3910,7 +3958,7 @@ var NATIVE_PROVIDERS = [
|
|
|
3910
3958
|
"openai",
|
|
3911
3959
|
"qwen"
|
|
3912
3960
|
];
|
|
3913
|
-
function
|
|
3961
|
+
function brotu(options) {
|
|
3914
3962
|
const apiKey = options.apiKey?.trim();
|
|
3915
3963
|
if (!apiKey) {
|
|
3916
3964
|
throw new Error(
|
|
@@ -4023,7 +4071,10 @@ function brotuClient(options) {
|
|
|
4023
4071
|
}
|
|
4024
4072
|
async function notifySettled(input) {
|
|
4025
4073
|
const config = webhookFor(input.params);
|
|
4026
|
-
|
|
4074
|
+
const kind = input.kind ?? input.job?.kind;
|
|
4075
|
+
const stage = input.event === "generation.succeeded" ? "Success" : "Error";
|
|
4076
|
+
const hook = findHook(options.hooks, kind, stage);
|
|
4077
|
+
if (!config && !hook) return;
|
|
4027
4078
|
const jobId = input.job?.id;
|
|
4028
4079
|
if (jobId) {
|
|
4029
4080
|
if (notifiedJobIds.has(jobId)) return;
|
|
@@ -4034,14 +4085,38 @@ function brotuClient(options) {
|
|
|
4034
4085
|
jobId,
|
|
4035
4086
|
provider: input.provider ?? input.job?.provider,
|
|
4036
4087
|
model: input.model ?? input.job?.model,
|
|
4037
|
-
kind
|
|
4088
|
+
kind,
|
|
4038
4089
|
outputs: input.outputs,
|
|
4039
4090
|
error: input.error ? { code: input.error.code, message: input.error.message } : void 0,
|
|
4040
4091
|
metadata: input.metadata ?? input.job?.metadata,
|
|
4041
4092
|
processingTimeMs: input.processingTimeMs,
|
|
4042
4093
|
completedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
4043
4094
|
};
|
|
4044
|
-
|
|
4095
|
+
if (hook && kind) {
|
|
4096
|
+
await runHook(hook, {
|
|
4097
|
+
kind,
|
|
4098
|
+
stage,
|
|
4099
|
+
provider: payload.provider ?? "",
|
|
4100
|
+
model: payload.model ?? "",
|
|
4101
|
+
jobId: payload.jobId,
|
|
4102
|
+
outputs: payload.outputs,
|
|
4103
|
+
error: payload.error,
|
|
4104
|
+
metadata: payload.metadata,
|
|
4105
|
+
processingTimeMs: payload.processingTimeMs,
|
|
4106
|
+
at: payload.completedAt
|
|
4107
|
+
});
|
|
4108
|
+
}
|
|
4109
|
+
if (config) await deliverWebhook(config, payload);
|
|
4110
|
+
}
|
|
4111
|
+
function notifyLoading(kind, routed, params) {
|
|
4112
|
+
return runHook(findHook(options.hooks, kind, "Loading"), {
|
|
4113
|
+
kind,
|
|
4114
|
+
stage: "Loading",
|
|
4115
|
+
provider: routed.provider,
|
|
4116
|
+
model: routed.model,
|
|
4117
|
+
metadata: params.metadata,
|
|
4118
|
+
at: (/* @__PURE__ */ new Date()).toISOString()
|
|
4119
|
+
});
|
|
4045
4120
|
}
|
|
4046
4121
|
async function toGeneration(raw, metadata) {
|
|
4047
4122
|
if (!raw.success) {
|
|
@@ -4064,6 +4139,7 @@ function brotuClient(options) {
|
|
|
4064
4139
|
async function generate(kind, params) {
|
|
4065
4140
|
const routed = route(params.model);
|
|
4066
4141
|
if (routed.error) return fail(routed.error);
|
|
4142
|
+
await notifyLoading(kind, routed.data, params);
|
|
4067
4143
|
try {
|
|
4068
4144
|
const result = await toGeneration(
|
|
4069
4145
|
await generateWith(routed.data.adapter, kind, params),
|
|
@@ -4114,6 +4190,7 @@ function brotuClient(options) {
|
|
|
4114
4190
|
async function submit(kind, params) {
|
|
4115
4191
|
const routed = route(params.model);
|
|
4116
4192
|
if (routed.error) return fail(routed.error);
|
|
4193
|
+
await notifyLoading(kind, routed.data, params);
|
|
4117
4194
|
const base = {
|
|
4118
4195
|
provider: routed.data.provider,
|
|
4119
4196
|
model: routed.data.model,
|
|
@@ -4285,24 +4362,33 @@ function brotuClient(options) {
|
|
|
4285
4362
|
}
|
|
4286
4363
|
};
|
|
4287
4364
|
}
|
|
4365
|
+
function listFor(category) {
|
|
4366
|
+
return describeModels(optionsWithKey).filter(
|
|
4367
|
+
(entry) => entry.model.category === category
|
|
4368
|
+
);
|
|
4369
|
+
}
|
|
4288
4370
|
return {
|
|
4289
4371
|
google: googleNamespace(),
|
|
4290
4372
|
kling: klingNamespace(),
|
|
4291
4373
|
image: {
|
|
4292
4374
|
submit: (params) => submit("image", params),
|
|
4293
|
-
generate: (params) => generate("image", params)
|
|
4375
|
+
generate: (params) => generate("image", params),
|
|
4376
|
+
list: () => listFor("image")
|
|
4294
4377
|
},
|
|
4295
4378
|
video: {
|
|
4296
4379
|
submit: (params) => submit("video", params),
|
|
4297
|
-
generate: (params) => generate("video", params)
|
|
4380
|
+
generate: (params) => generate("video", params),
|
|
4381
|
+
list: () => listFor("video")
|
|
4298
4382
|
},
|
|
4299
4383
|
text: {
|
|
4300
4384
|
submit: (params) => submit("text", params),
|
|
4301
|
-
generate: (params) => generate("text", params)
|
|
4385
|
+
generate: (params) => generate("text", params),
|
|
4386
|
+
list: () => listFor("text")
|
|
4302
4387
|
},
|
|
4303
4388
|
audio: {
|
|
4304
4389
|
submit: (params) => submit("audio", params),
|
|
4305
|
-
generate: (params) => generate("audio", params)
|
|
4390
|
+
generate: (params) => generate("audio", params),
|
|
4391
|
+
list: () => listFor("audio")
|
|
4306
4392
|
},
|
|
4307
4393
|
webhook: {
|
|
4308
4394
|
set(value) {
|
|
@@ -4369,6 +4455,7 @@ function brotuClient(options) {
|
|
|
4369
4455
|
}
|
|
4370
4456
|
// Annotate the CommonJS export names for ESM import in node:
|
|
4371
4457
|
0 && (module.exports = {
|
|
4458
|
+
BROTU_SUPPORTED_CATEGORIES,
|
|
4372
4459
|
BYTEPLUS_CATALOG,
|
|
4373
4460
|
BYTEPLUS_MODELS,
|
|
4374
4461
|
BrotuAdapter,
|
|
@@ -4400,9 +4487,10 @@ function brotuClient(options) {
|
|
|
4400
4487
|
QWEN_TEXT_MODELS,
|
|
4401
4488
|
QWEN_VIDEO_MODELS,
|
|
4402
4489
|
QwenAdapter,
|
|
4403
|
-
|
|
4490
|
+
brotu,
|
|
4404
4491
|
createS3Storage,
|
|
4405
4492
|
deliverWebhook,
|
|
4493
|
+
describeModels,
|
|
4406
4494
|
fail,
|
|
4407
4495
|
getAvailableModels,
|
|
4408
4496
|
getModel,
|
package/dist/index.d.ts
CHANGED
|
@@ -12,11 +12,13 @@ export type { OpenAIAdapterOptions } from "./adapters/openai.adapter";
|
|
|
12
12
|
export { OpenAIAdapter } from "./adapters/openai.adapter";
|
|
13
13
|
export type { QwenAdapterOptions } from "./adapters/qwen.adapter";
|
|
14
14
|
export { QwenAdapter } from "./adapters/qwen.adapter";
|
|
15
|
-
export {
|
|
15
|
+
export type { ModelAvailability } from "./catalog";
|
|
16
|
+
export { BROTU_SUPPORTED_CATEGORIES, DEFAULT_BROTU_API_URL, describeModels, getAvailableModels, getModel, getModels, getProviders, hasModel, registerModels, resetCatalog, resolveProvider, } from "./catalog";
|
|
16
17
|
export type { BrotuAI } from "./client";
|
|
17
|
-
export {
|
|
18
|
+
export { brotu } from "./client";
|
|
18
19
|
export type * from "./constants/model.types";
|
|
19
20
|
export { type AIError, type AIErrorCode, fail, type Generation, ok, type Result, } from "./helpers/result";
|
|
21
|
+
export type { HookEvent, HookFn, Hooks, HookStage, } from "./lib/hooks";
|
|
20
22
|
export { isPendingJob, type Job, type JobSnapshot, type JobStatus, PendingJob, } from "./lib/jobs";
|
|
21
23
|
export { createS3Storage, persistOutputs, type S3StorageConfig, type Storage, } from "./lib/storage";
|
|
22
24
|
export { deliverWebhook, resolveWebhook, type WebhookConfig, type WebhookEvent, type WebhookEventName, } from "./lib/webhook";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,YAAY,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAC1E,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,YAAY,EACX,wBAAwB,EACxB,eAAe,GACf,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAClE,YAAY,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,YAAY,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,YAAY,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,YAAY,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EACN,qBAAqB,EACrB,kBAAkB,EAClB,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,QAAQ,EACR,cAAc,EACd,YAAY,EACZ,eAAe,GACf,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
BROTU_SUPPORTED_CATEGORIES,
|
|
2
3
|
BYTEPLUS_CATALOG,
|
|
3
4
|
BYTEPLUS_IMAGE_MODELS,
|
|
4
5
|
BYTEPLUS_MODELS,
|
|
@@ -26,6 +27,7 @@ import {
|
|
|
26
27
|
QWEN_IMAGE_PATHS,
|
|
27
28
|
QWEN_TEXT_MODELS,
|
|
28
29
|
QWEN_VIDEO_MODELS,
|
|
30
|
+
describeModels,
|
|
29
31
|
fieldsFor,
|
|
30
32
|
getAvailableModels,
|
|
31
33
|
getModel,
|
|
@@ -36,7 +38,7 @@ import {
|
|
|
36
38
|
resetCatalog,
|
|
37
39
|
resolveProvider,
|
|
38
40
|
videoPathFor
|
|
39
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-3MC3RDAJ.js";
|
|
40
42
|
|
|
41
43
|
// src/lib/jobs.ts
|
|
42
44
|
import { AsyncLocalStorage } from "async_hooks";
|
|
@@ -111,7 +113,7 @@ var BrotuAdapter = class {
|
|
|
111
113
|
}
|
|
112
114
|
opts;
|
|
113
115
|
providerName = "brotu";
|
|
114
|
-
supportedTypes =
|
|
116
|
+
supportedTypes = BROTU_SUPPORTED_CATEGORIES;
|
|
115
117
|
workspaceIdCache;
|
|
116
118
|
get origin() {
|
|
117
119
|
return (this.opts.apiUrl ?? DEFAULT_API_URL).replace(/\/$/, "");
|
|
@@ -2439,6 +2441,22 @@ function failFrom(code, cause, context) {
|
|
|
2439
2441
|
});
|
|
2440
2442
|
}
|
|
2441
2443
|
|
|
2444
|
+
// src/lib/hooks.ts
|
|
2445
|
+
function hookName(kind, stage) {
|
|
2446
|
+
return `on${kind[0].toUpperCase()}${kind.slice(1)}${stage}`;
|
|
2447
|
+
}
|
|
2448
|
+
function findHook(hooks, kind, stage) {
|
|
2449
|
+
if (!hooks || !kind) return void 0;
|
|
2450
|
+
return hooks[hookName(kind, stage)];
|
|
2451
|
+
}
|
|
2452
|
+
async function runHook(hook, event) {
|
|
2453
|
+
if (!hook) return;
|
|
2454
|
+
try {
|
|
2455
|
+
await hook(event);
|
|
2456
|
+
} catch {
|
|
2457
|
+
}
|
|
2458
|
+
}
|
|
2459
|
+
|
|
2442
2460
|
// src/lib/storage.ts
|
|
2443
2461
|
async function loadS3(config) {
|
|
2444
2462
|
let s3;
|
|
@@ -2609,7 +2627,7 @@ var NATIVE_PROVIDERS = [
|
|
|
2609
2627
|
"openai",
|
|
2610
2628
|
"qwen"
|
|
2611
2629
|
];
|
|
2612
|
-
function
|
|
2630
|
+
function brotu(options) {
|
|
2613
2631
|
const apiKey = options.apiKey?.trim();
|
|
2614
2632
|
if (!apiKey) {
|
|
2615
2633
|
throw new Error(
|
|
@@ -2722,7 +2740,10 @@ function brotuClient(options) {
|
|
|
2722
2740
|
}
|
|
2723
2741
|
async function notifySettled(input) {
|
|
2724
2742
|
const config = webhookFor(input.params);
|
|
2725
|
-
|
|
2743
|
+
const kind = input.kind ?? input.job?.kind;
|
|
2744
|
+
const stage = input.event === "generation.succeeded" ? "Success" : "Error";
|
|
2745
|
+
const hook = findHook(options.hooks, kind, stage);
|
|
2746
|
+
if (!config && !hook) return;
|
|
2726
2747
|
const jobId = input.job?.id;
|
|
2727
2748
|
if (jobId) {
|
|
2728
2749
|
if (notifiedJobIds.has(jobId)) return;
|
|
@@ -2733,14 +2754,38 @@ function brotuClient(options) {
|
|
|
2733
2754
|
jobId,
|
|
2734
2755
|
provider: input.provider ?? input.job?.provider,
|
|
2735
2756
|
model: input.model ?? input.job?.model,
|
|
2736
|
-
kind
|
|
2757
|
+
kind,
|
|
2737
2758
|
outputs: input.outputs,
|
|
2738
2759
|
error: input.error ? { code: input.error.code, message: input.error.message } : void 0,
|
|
2739
2760
|
metadata: input.metadata ?? input.job?.metadata,
|
|
2740
2761
|
processingTimeMs: input.processingTimeMs,
|
|
2741
2762
|
completedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
2742
2763
|
};
|
|
2743
|
-
|
|
2764
|
+
if (hook && kind) {
|
|
2765
|
+
await runHook(hook, {
|
|
2766
|
+
kind,
|
|
2767
|
+
stage,
|
|
2768
|
+
provider: payload.provider ?? "",
|
|
2769
|
+
model: payload.model ?? "",
|
|
2770
|
+
jobId: payload.jobId,
|
|
2771
|
+
outputs: payload.outputs,
|
|
2772
|
+
error: payload.error,
|
|
2773
|
+
metadata: payload.metadata,
|
|
2774
|
+
processingTimeMs: payload.processingTimeMs,
|
|
2775
|
+
at: payload.completedAt
|
|
2776
|
+
});
|
|
2777
|
+
}
|
|
2778
|
+
if (config) await deliverWebhook(config, payload);
|
|
2779
|
+
}
|
|
2780
|
+
function notifyLoading(kind, routed, params) {
|
|
2781
|
+
return runHook(findHook(options.hooks, kind, "Loading"), {
|
|
2782
|
+
kind,
|
|
2783
|
+
stage: "Loading",
|
|
2784
|
+
provider: routed.provider,
|
|
2785
|
+
model: routed.model,
|
|
2786
|
+
metadata: params.metadata,
|
|
2787
|
+
at: (/* @__PURE__ */ new Date()).toISOString()
|
|
2788
|
+
});
|
|
2744
2789
|
}
|
|
2745
2790
|
async function toGeneration(raw, metadata) {
|
|
2746
2791
|
if (!raw.success) {
|
|
@@ -2763,6 +2808,7 @@ function brotuClient(options) {
|
|
|
2763
2808
|
async function generate(kind, params) {
|
|
2764
2809
|
const routed = route(params.model);
|
|
2765
2810
|
if (routed.error) return fail(routed.error);
|
|
2811
|
+
await notifyLoading(kind, routed.data, params);
|
|
2766
2812
|
try {
|
|
2767
2813
|
const result = await toGeneration(
|
|
2768
2814
|
await generateWith(routed.data.adapter, kind, params),
|
|
@@ -2813,6 +2859,7 @@ function brotuClient(options) {
|
|
|
2813
2859
|
async function submit(kind, params) {
|
|
2814
2860
|
const routed = route(params.model);
|
|
2815
2861
|
if (routed.error) return fail(routed.error);
|
|
2862
|
+
await notifyLoading(kind, routed.data, params);
|
|
2816
2863
|
const base = {
|
|
2817
2864
|
provider: routed.data.provider,
|
|
2818
2865
|
model: routed.data.model,
|
|
@@ -2984,24 +3031,33 @@ function brotuClient(options) {
|
|
|
2984
3031
|
}
|
|
2985
3032
|
};
|
|
2986
3033
|
}
|
|
3034
|
+
function listFor(category) {
|
|
3035
|
+
return describeModels(optionsWithKey).filter(
|
|
3036
|
+
(entry) => entry.model.category === category
|
|
3037
|
+
);
|
|
3038
|
+
}
|
|
2987
3039
|
return {
|
|
2988
3040
|
google: googleNamespace(),
|
|
2989
3041
|
kling: klingNamespace(),
|
|
2990
3042
|
image: {
|
|
2991
3043
|
submit: (params) => submit("image", params),
|
|
2992
|
-
generate: (params) => generate("image", params)
|
|
3044
|
+
generate: (params) => generate("image", params),
|
|
3045
|
+
list: () => listFor("image")
|
|
2993
3046
|
},
|
|
2994
3047
|
video: {
|
|
2995
3048
|
submit: (params) => submit("video", params),
|
|
2996
|
-
generate: (params) => generate("video", params)
|
|
3049
|
+
generate: (params) => generate("video", params),
|
|
3050
|
+
list: () => listFor("video")
|
|
2997
3051
|
},
|
|
2998
3052
|
text: {
|
|
2999
3053
|
submit: (params) => submit("text", params),
|
|
3000
|
-
generate: (params) => generate("text", params)
|
|
3054
|
+
generate: (params) => generate("text", params),
|
|
3055
|
+
list: () => listFor("text")
|
|
3001
3056
|
},
|
|
3002
3057
|
audio: {
|
|
3003
3058
|
submit: (params) => submit("audio", params),
|
|
3004
|
-
generate: (params) => generate("audio", params)
|
|
3059
|
+
generate: (params) => generate("audio", params),
|
|
3060
|
+
list: () => listFor("audio")
|
|
3005
3061
|
},
|
|
3006
3062
|
webhook: {
|
|
3007
3063
|
set(value) {
|
|
@@ -3067,6 +3123,7 @@ function brotuClient(options) {
|
|
|
3067
3123
|
};
|
|
3068
3124
|
}
|
|
3069
3125
|
export {
|
|
3126
|
+
BROTU_SUPPORTED_CATEGORIES,
|
|
3070
3127
|
BYTEPLUS_CATALOG,
|
|
3071
3128
|
BYTEPLUS_MODELS,
|
|
3072
3129
|
BrotuAdapter,
|
|
@@ -3098,9 +3155,10 @@ export {
|
|
|
3098
3155
|
QWEN_TEXT_MODELS,
|
|
3099
3156
|
QWEN_VIDEO_MODELS,
|
|
3100
3157
|
QwenAdapter,
|
|
3101
|
-
|
|
3158
|
+
brotu,
|
|
3102
3159
|
createS3Storage,
|
|
3103
3160
|
deliverWebhook,
|
|
3161
|
+
describeModels,
|
|
3104
3162
|
fail,
|
|
3105
3163
|
getAvailableModels,
|
|
3106
3164
|
getModel,
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { AIError } from "../helpers/result";
|
|
2
|
+
import type { GenerationOutput, GenerationType } from "../ports/content-generator.port";
|
|
3
|
+
/** Where a generation is when the hook fires. */
|
|
4
|
+
export type HookStage = "Loading" | "Success" | "Error";
|
|
5
|
+
/** What every hook receives. Fields absent at that stage stay undefined. */
|
|
6
|
+
export interface HookEvent {
|
|
7
|
+
kind: GenerationType;
|
|
8
|
+
stage: HookStage;
|
|
9
|
+
provider: string;
|
|
10
|
+
model: string;
|
|
11
|
+
jobId?: string;
|
|
12
|
+
outputs?: GenerationOutput[];
|
|
13
|
+
error?: Pick<AIError, "code" | "message">;
|
|
14
|
+
metadata?: Record<string, string>;
|
|
15
|
+
processingTimeMs?: number;
|
|
16
|
+
at: string;
|
|
17
|
+
}
|
|
18
|
+
export type HookFn = (event: HookEvent) => void | Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* One optional callback per kind and stage — `onVideoLoading`,
|
|
21
|
+
* `onImageSuccess`, `onAudioError`, and so on for every combination.
|
|
22
|
+
*/
|
|
23
|
+
export type Hooks = Partial<Record<`on${Capitalize<GenerationType>}${HookStage}`, HookFn>>;
|
|
24
|
+
/** The hook registered for this kind and stage, if any. */
|
|
25
|
+
export declare function findHook(hooks: Hooks | undefined, kind: GenerationType | undefined, stage: HookStage): HookFn | undefined;
|
|
26
|
+
/**
|
|
27
|
+
* Run a hook without letting it break the caller. Same contract as the
|
|
28
|
+
* webhook: your logging or your mailer going down must not fail a generation
|
|
29
|
+
* that already succeeded.
|
|
30
|
+
*/
|
|
31
|
+
export declare function runHook(hook: HookFn | undefined, event: HookEvent): Promise<void>;
|
|
32
|
+
//# sourceMappingURL=hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/lib/hooks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,KAAK,EACX,gBAAgB,EAChB,cAAc,EACd,MAAM,iCAAiC,CAAC;AAEzC,iDAAiD;AACjD,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;AAExD,4EAA4E;AAC5E,MAAM,WAAW,SAAS;IACzB,IAAI,EAAE,cAAc,CAAC;IACrB,KAAK,EAAE,SAAS,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAC7B,KAAK,CAAC,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IAC1C,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,EAAE,EAAE,MAAM,CAAC;CACX;AAED,MAAM,MAAM,MAAM,GAAG,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAEhE;;;GAGG;AACH,MAAM,MAAM,KAAK,GAAG,OAAO,CAC1B,MAAM,CAAC,KAAK,UAAU,CAAC,cAAc,CAAC,GAAG,SAAS,EAAE,EAAE,MAAM,CAAC,CAC7D,CAAC;AAMF,2DAA2D;AAC3D,wBAAgB,QAAQ,CACvB,KAAK,EAAE,KAAK,GAAG,SAAS,EACxB,IAAI,EAAE,cAAc,GAAG,SAAS,EAChC,KAAK,EAAE,SAAS,GACd,MAAM,GAAG,SAAS,CAGpB;AAED;;;;GAIG;AACH,wBAAsB,OAAO,CAC5B,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,KAAK,EAAE,SAAS,GACd,OAAO,CAAC,IAAI,CAAC,CAOf"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AIModelConfig } from "./constants/model.types";
|
|
2
|
+
import type { Hooks } from "./lib/hooks";
|
|
2
3
|
import type { S3StorageConfig } from "./lib/storage";
|
|
3
4
|
import type { WebhookConfig } from "./lib/webhook";
|
|
4
5
|
export interface ProviderConfig {
|
|
@@ -64,6 +65,14 @@ export interface BrotuAIOptions {
|
|
|
64
65
|
* later with `ai.webhook.set`. A per-request `webhook` on the params wins.
|
|
65
66
|
*/
|
|
66
67
|
webhook?: string | WebhookConfig;
|
|
68
|
+
/**
|
|
69
|
+
* In-process callbacks, one per kind and stage: `onVideoLoading`,
|
|
70
|
+
* `onVideoSuccess`, `onVideoError`, and the same three for image, audio and
|
|
71
|
+
* text. Your logic runs inside your process, so it can send an email, write
|
|
72
|
+
* to your DB or push to a queue — no endpoint needed, unlike `webhook`.
|
|
73
|
+
* Throwing inside a hook never fails the generation.
|
|
74
|
+
*/
|
|
75
|
+
hooks?: Hooks;
|
|
67
76
|
}
|
|
68
77
|
/** Resolved per-request routing: which host and key serve this model. */
|
|
69
78
|
export interface ResolvedProvider {
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,MAAM,WAAW,cAAc;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,0EAA0E;IAC1E,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IAClC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC9B;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,6DAA6D;IAC7D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC3C,mFAAmF;IACnF,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9C;;;;OAIG;IACH,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAC1D;;;;OAIG;IACH,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B;;;OAGG;IACH,WAAW,CAAC,EAAE,CACb,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,KACZ,OAAO,CAAC,MAAM,CAAC,CAAC;IACrB;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iEAAiE;IACjE,MAAM,CAAC,EAAE,aAAa,EAAE,CAAC;IACzB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,MAAM,WAAW,cAAc;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,0EAA0E;IAC1E,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IAClC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC9B;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,6DAA6D;IAC7D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC3C,mFAAmF;IACnF,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9C;;;;OAIG;IACH,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAC1D;;;;OAIG;IACH,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B;;;OAGG;IACH,WAAW,CAAC,EAAE,CACb,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,KACZ,OAAO,CAAC,MAAM,CAAC,CAAC;IACrB;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iEAAiE;IACjE,MAAM,CAAC,EAAE,aAAa,EAAE,CAAC;IACzB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,aAAa,CAAC;IACjC;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,KAAK,CAAC;CACd;AAED,yEAAyE;AACzE,MAAM,WAAW,gBAAgB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CAChB"}
|