@brotu/ai 0.2.0 → 0.3.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 +40 -0
- package/dist/client.d.ts +10 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/index.cjs +198 -11
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +195 -10
- package/dist/lib/webhook.d.ts +28 -0
- package/dist/lib/webhook.d.ts.map +1 -0
- package/dist/ports/content-generator.port.d.ts +6 -0
- package/dist/ports/content-generator.port.d.ts.map +1 -1
- package/dist/types.d.ts +7 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -55,6 +55,10 @@ const ai = brotuClient({
|
|
|
55
55
|
qwen: { apiKey: process.env.QWEN_API_KEY! },
|
|
56
56
|
elevenlabs: { apiKey: process.env.ELEVENLABS_API_KEY! },
|
|
57
57
|
},
|
|
58
|
+
webhook: {
|
|
59
|
+
url: "https://my.app/hooks/brotu",
|
|
60
|
+
secret: process.env.BROTU_WEBHOOK_SECRET,
|
|
61
|
+
},
|
|
58
62
|
});
|
|
59
63
|
```
|
|
60
64
|
|
|
@@ -69,6 +73,7 @@ Every public call returns `{ data, error }`. `data` is unusable until you narrow
|
|
|
69
73
|
| `ai.text` | `submit` / `generate` |
|
|
70
74
|
| `ai.audio` | `submit` / `generate` |
|
|
71
75
|
| `ai.jobs` | `poll` / `wait` |
|
|
76
|
+
| `ai.webhook` | `set` / `clear` / `get` |
|
|
72
77
|
| `ai.estimateCost` | units, and USD when verified |
|
|
73
78
|
| `ai.kling` | `motionControl`, `omniVideo`, `avatar`, `outpainting`, `imageOmni` |
|
|
74
79
|
| `ai.google` | `omniVideo` (conversational refine) |
|
|
@@ -156,6 +161,41 @@ if (result === undefined && snapshot?.status === "pending") {
|
|
|
156
161
|
}
|
|
157
162
|
```
|
|
158
163
|
|
|
164
|
+
## Webhook
|
|
165
|
+
|
|
166
|
+
Register a URL on the client. When `generate`, `jobs.wait` or a terminal `jobs.poll` settles, the SDK POSTs the result there. A down hook never fails the generation.
|
|
167
|
+
|
|
168
|
+
```ts
|
|
169
|
+
ai.webhook.set("https://my.app/hooks/brotu");
|
|
170
|
+
ai.webhook.clear();
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Per request, if one generation should go somewhere else:
|
|
174
|
+
|
|
175
|
+
```ts
|
|
176
|
+
await ai.video.submit({
|
|
177
|
+
model: "kling/v2-6",
|
|
178
|
+
prompt: "a cat",
|
|
179
|
+
webhook: "https://my.app/hooks/this-one",
|
|
180
|
+
});
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
The POST is JSON. Check `x-brotu-event` and, if you set a secret, `x-brotu-webhook-secret`.
|
|
184
|
+
|
|
185
|
+
```json
|
|
186
|
+
{
|
|
187
|
+
"event": "generation.succeeded",
|
|
188
|
+
"jobId": "task-1",
|
|
189
|
+
"provider": "kling",
|
|
190
|
+
"model": "kling/v2-6",
|
|
191
|
+
"kind": "video",
|
|
192
|
+
"outputs": [{ "url": "https://…", "mimeType": "video/mp4" }],
|
|
193
|
+
"completedAt": "2026-08-16T12:00:00.000Z"
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
`generation.failed` carries `error: { code, message }` and no outputs. Timeouts and routing errors do not fire the hook.
|
|
198
|
+
|
|
159
199
|
Error codes: `unknown_model`, `missing_key`, `unsupported_provider`, `invalid_request`, `provider_error`, `timeout`.
|
|
160
200
|
|
|
161
201
|
## Motion control, avatars, omni
|
package/dist/client.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { getModel } 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";
|
|
5
|
+
import { type WebhookConfig } from "./lib/webhook";
|
|
5
6
|
import type { AudioGenerationParams, CostEstimate, GenerationOutput, GenerationParams, GenerationType, ImageGenerationParams, TextGenerationParams, VideoGenerationParams } from "./ports/content-generator.port";
|
|
6
7
|
import { type AvatarInput, type ImageOmniInput, type MotionControlInput, type OmniVideoInput, type OutpaintingInput } from "./providers/kling.models";
|
|
7
8
|
import type { BrotuAIOptions } from "./types";
|
|
@@ -35,6 +36,15 @@ export interface BrotuAI {
|
|
|
35
36
|
timeoutMs?: number;
|
|
36
37
|
}): Promise<Result<Generation>>;
|
|
37
38
|
};
|
|
39
|
+
/**
|
|
40
|
+
* URL the client POSTs when a generation settles. Register at construction
|
|
41
|
+
* (`webhook:`) or here later. A down hook never fails the generation.
|
|
42
|
+
*/
|
|
43
|
+
webhook: {
|
|
44
|
+
set(value: string | WebhookConfig): void;
|
|
45
|
+
clear(): void;
|
|
46
|
+
get(): WebhookConfig | undefined;
|
|
47
|
+
};
|
|
38
48
|
/**
|
|
39
49
|
* Google capabilities with no portable equivalent. Present only when a google
|
|
40
50
|
* key is configured.
|
package/dist/client.d.ts.map
CHANGED
|
@@ -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":"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"}
|
package/dist/index.cjs
CHANGED
|
@@ -61,6 +61,7 @@ __export(index_exports, {
|
|
|
61
61
|
QwenAdapter: () => QwenAdapter,
|
|
62
62
|
brotuClient: () => brotuClient,
|
|
63
63
|
createS3Storage: () => createS3Storage,
|
|
64
|
+
deliverWebhook: () => deliverWebhook,
|
|
64
65
|
fail: () => fail,
|
|
65
66
|
getAvailableModels: () => getAvailableModels,
|
|
66
67
|
getModel: () => getModel,
|
|
@@ -72,7 +73,8 @@ __export(index_exports, {
|
|
|
72
73
|
persistOutputs: () => persistOutputs,
|
|
73
74
|
registerModels: () => registerModels,
|
|
74
75
|
resetCatalog: () => resetCatalog,
|
|
75
|
-
resolveProvider: () => resolveProvider
|
|
76
|
+
resolveProvider: () => resolveProvider,
|
|
77
|
+
resolveWebhook: () => resolveWebhook
|
|
76
78
|
});
|
|
77
79
|
module.exports = __toCommonJS(index_exports);
|
|
78
80
|
|
|
@@ -3534,6 +3536,45 @@ async function persistOutputs(storage, outputs) {
|
|
|
3534
3536
|
);
|
|
3535
3537
|
}
|
|
3536
3538
|
|
|
3539
|
+
// src/lib/webhook.ts
|
|
3540
|
+
function resolveWebhook(value) {
|
|
3541
|
+
if (!value) return void 0;
|
|
3542
|
+
if (typeof value === "string") {
|
|
3543
|
+
return isHttpUrl(value) ? { url: value } : void 0;
|
|
3544
|
+
}
|
|
3545
|
+
if (!isHttpUrl(value.url)) return void 0;
|
|
3546
|
+
return {
|
|
3547
|
+
url: value.url,
|
|
3548
|
+
secret: value.secret,
|
|
3549
|
+
headers: value.headers
|
|
3550
|
+
};
|
|
3551
|
+
}
|
|
3552
|
+
function isHttpUrl(value) {
|
|
3553
|
+
try {
|
|
3554
|
+
const parsed = new URL(value);
|
|
3555
|
+
return parsed.protocol === "https:" || parsed.protocol === "http:";
|
|
3556
|
+
} catch {
|
|
3557
|
+
return false;
|
|
3558
|
+
}
|
|
3559
|
+
}
|
|
3560
|
+
async function deliverWebhook(config, payload) {
|
|
3561
|
+
try {
|
|
3562
|
+
await fetch(config.url, {
|
|
3563
|
+
method: "POST",
|
|
3564
|
+
headers: {
|
|
3565
|
+
"content-type": "application/json",
|
|
3566
|
+
"user-agent": "@brotu/ai",
|
|
3567
|
+
"x-brotu-event": payload.event,
|
|
3568
|
+
...config.secret ? { "x-brotu-webhook-secret": config.secret } : {},
|
|
3569
|
+
...config.headers
|
|
3570
|
+
},
|
|
3571
|
+
body: JSON.stringify(payload),
|
|
3572
|
+
signal: AbortSignal.timeout(1e4)
|
|
3573
|
+
});
|
|
3574
|
+
} catch {
|
|
3575
|
+
}
|
|
3576
|
+
}
|
|
3577
|
+
|
|
3537
3578
|
// src/client.ts
|
|
3538
3579
|
var NATIVE_PROVIDERS = [
|
|
3539
3580
|
"byteplus",
|
|
@@ -3548,6 +3589,8 @@ function brotuClient(options) {
|
|
|
3548
3589
|
throw new Error("brotuClient requires at least one provider API key.");
|
|
3549
3590
|
}
|
|
3550
3591
|
registerModels(options.models);
|
|
3592
|
+
let registeredWebhook = resolveWebhook(options.webhook);
|
|
3593
|
+
const notifiedJobIds = /* @__PURE__ */ new Set();
|
|
3551
3594
|
const storage = options.storage ? createS3Storage(options.storage) : void 0;
|
|
3552
3595
|
const shouldPersist = storage && options.storage?.persistOutputs !== false;
|
|
3553
3596
|
const adapters = /* @__PURE__ */ new Map();
|
|
@@ -3637,6 +3680,31 @@ function brotuClient(options) {
|
|
|
3637
3680
|
return adapter.generateAudio(params);
|
|
3638
3681
|
return adapter.generateText(params);
|
|
3639
3682
|
}
|
|
3683
|
+
function webhookFor(params) {
|
|
3684
|
+
return resolveWebhook(params?.webhook) ?? registeredWebhook;
|
|
3685
|
+
}
|
|
3686
|
+
async function notifySettled(input) {
|
|
3687
|
+
const config = webhookFor(input.params);
|
|
3688
|
+
if (!config) return;
|
|
3689
|
+
const jobId = input.job?.id;
|
|
3690
|
+
if (jobId) {
|
|
3691
|
+
if (notifiedJobIds.has(jobId)) return;
|
|
3692
|
+
notifiedJobIds.add(jobId);
|
|
3693
|
+
}
|
|
3694
|
+
const payload = {
|
|
3695
|
+
event: input.event,
|
|
3696
|
+
jobId,
|
|
3697
|
+
provider: input.provider ?? input.job?.provider,
|
|
3698
|
+
model: input.model ?? input.job?.model,
|
|
3699
|
+
kind: input.kind ?? input.job?.kind,
|
|
3700
|
+
outputs: input.outputs,
|
|
3701
|
+
error: input.error ? { code: input.error.code, message: input.error.message } : void 0,
|
|
3702
|
+
metadata: input.metadata ?? input.job?.metadata,
|
|
3703
|
+
processingTimeMs: input.processingTimeMs,
|
|
3704
|
+
completedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
3705
|
+
};
|
|
3706
|
+
await deliverWebhook(config, payload);
|
|
3707
|
+
}
|
|
3640
3708
|
async function toGeneration(raw, metadata) {
|
|
3641
3709
|
if (!raw.success) {
|
|
3642
3710
|
return fail({
|
|
@@ -3659,15 +3727,50 @@ function brotuClient(options) {
|
|
|
3659
3727
|
const routed = route(params.model);
|
|
3660
3728
|
if (routed.error) return fail(routed.error);
|
|
3661
3729
|
try {
|
|
3662
|
-
|
|
3730
|
+
const result = await toGeneration(
|
|
3663
3731
|
await generateWith(routed.data.adapter, kind, params),
|
|
3664
3732
|
params.metadata
|
|
3665
3733
|
);
|
|
3734
|
+
if (result.error) {
|
|
3735
|
+
await notifySettled({
|
|
3736
|
+
event: "generation.failed",
|
|
3737
|
+
params,
|
|
3738
|
+
kind,
|
|
3739
|
+
provider: routed.data.provider,
|
|
3740
|
+
model: routed.data.model,
|
|
3741
|
+
error: result.error,
|
|
3742
|
+
metadata: params.metadata
|
|
3743
|
+
});
|
|
3744
|
+
return result;
|
|
3745
|
+
}
|
|
3746
|
+
await notifySettled({
|
|
3747
|
+
event: "generation.succeeded",
|
|
3748
|
+
params,
|
|
3749
|
+
kind,
|
|
3750
|
+
provider: result.data.provider,
|
|
3751
|
+
model: result.data.model,
|
|
3752
|
+
outputs: result.data.outputs,
|
|
3753
|
+
metadata: result.data.metadata,
|
|
3754
|
+
processingTimeMs: result.data.processingTimeMs
|
|
3755
|
+
});
|
|
3756
|
+
return result;
|
|
3666
3757
|
} catch (error) {
|
|
3667
|
-
|
|
3758
|
+
const failed = failFrom("provider_error", error, {
|
|
3668
3759
|
provider: routed.data.provider,
|
|
3669
3760
|
model: routed.data.model
|
|
3670
3761
|
});
|
|
3762
|
+
if (failed.error) {
|
|
3763
|
+
await notifySettled({
|
|
3764
|
+
event: "generation.failed",
|
|
3765
|
+
params,
|
|
3766
|
+
kind,
|
|
3767
|
+
provider: routed.data.provider,
|
|
3768
|
+
model: routed.data.model,
|
|
3769
|
+
error: failed.error,
|
|
3770
|
+
metadata: params.metadata
|
|
3771
|
+
});
|
|
3772
|
+
}
|
|
3773
|
+
return failed;
|
|
3671
3774
|
}
|
|
3672
3775
|
}
|
|
3673
3776
|
async function submit(kind, params) {
|
|
@@ -3686,18 +3789,40 @@ function brotuClient(options) {
|
|
|
3686
3789
|
() => generateWith(routed.data.adapter, kind, params)
|
|
3687
3790
|
);
|
|
3688
3791
|
if (!raw.success) {
|
|
3689
|
-
|
|
3792
|
+
const error = {
|
|
3690
3793
|
code: "provider_error",
|
|
3691
3794
|
message: raw.error ?? "The provider rejected the request.",
|
|
3692
3795
|
provider: raw.provider,
|
|
3693
3796
|
model: raw.model
|
|
3797
|
+
};
|
|
3798
|
+
await notifySettled({
|
|
3799
|
+
event: "generation.failed",
|
|
3800
|
+
params,
|
|
3801
|
+
kind,
|
|
3802
|
+
provider: raw.provider,
|
|
3803
|
+
model: raw.model,
|
|
3804
|
+
error,
|
|
3805
|
+
metadata: params.metadata
|
|
3694
3806
|
});
|
|
3807
|
+
return fail(error);
|
|
3695
3808
|
}
|
|
3696
|
-
|
|
3809
|
+
const job = {
|
|
3697
3810
|
...base,
|
|
3698
3811
|
id: `inline-${base.model}-${base.submittedAt}`,
|
|
3699
3812
|
result: raw
|
|
3813
|
+
};
|
|
3814
|
+
await notifySettled({
|
|
3815
|
+
event: "generation.succeeded",
|
|
3816
|
+
params,
|
|
3817
|
+
job,
|
|
3818
|
+
kind,
|
|
3819
|
+
provider: raw.provider,
|
|
3820
|
+
model: raw.model,
|
|
3821
|
+
outputs: raw.outputs,
|
|
3822
|
+
metadata: params.metadata,
|
|
3823
|
+
processingTimeMs: raw.processingTimeMs
|
|
3700
3824
|
});
|
|
3825
|
+
return ok(job);
|
|
3701
3826
|
} catch (error) {
|
|
3702
3827
|
if (!isPendingJob(error)) {
|
|
3703
3828
|
return failFrom("provider_error", error, {
|
|
@@ -3712,11 +3837,54 @@ function brotuClient(options) {
|
|
|
3712
3837
|
});
|
|
3713
3838
|
}
|
|
3714
3839
|
}
|
|
3840
|
+
async function notifyFromSnapshot(job, snapshot) {
|
|
3841
|
+
if (snapshot.status === "succeeded" && snapshot.result) {
|
|
3842
|
+
await notifySettled({
|
|
3843
|
+
event: "generation.succeeded",
|
|
3844
|
+
params: job.params,
|
|
3845
|
+
job,
|
|
3846
|
+
outputs: snapshot.result.outputs,
|
|
3847
|
+
provider: snapshot.result.provider,
|
|
3848
|
+
model: snapshot.result.model,
|
|
3849
|
+
processingTimeMs: snapshot.result.processingTimeMs,
|
|
3850
|
+
metadata: job.metadata
|
|
3851
|
+
});
|
|
3852
|
+
return;
|
|
3853
|
+
}
|
|
3854
|
+
if (snapshot.status === "failed") {
|
|
3855
|
+
await notifySettled({
|
|
3856
|
+
event: "generation.failed",
|
|
3857
|
+
params: job.params,
|
|
3858
|
+
job,
|
|
3859
|
+
error: {
|
|
3860
|
+
code: "provider_error",
|
|
3861
|
+
message: snapshot.error ?? "The job failed.",
|
|
3862
|
+
provider: job.provider,
|
|
3863
|
+
model: job.model
|
|
3864
|
+
},
|
|
3865
|
+
metadata: job.metadata
|
|
3866
|
+
});
|
|
3867
|
+
}
|
|
3868
|
+
}
|
|
3869
|
+
async function finalizeSnapshot(job, snapshot) {
|
|
3870
|
+
if (snapshot.status === "succeeded" && snapshot.result) {
|
|
3871
|
+
const persisted = await toGeneration(snapshot.result, job.metadata);
|
|
3872
|
+
if (!persisted.error) {
|
|
3873
|
+
snapshot = {
|
|
3874
|
+
status: "succeeded",
|
|
3875
|
+
result: {
|
|
3876
|
+
...snapshot.result,
|
|
3877
|
+
outputs: persisted.data.outputs
|
|
3878
|
+
}
|
|
3879
|
+
};
|
|
3880
|
+
}
|
|
3881
|
+
}
|
|
3882
|
+
await notifyFromSnapshot(job, snapshot);
|
|
3883
|
+
return snapshot;
|
|
3884
|
+
}
|
|
3715
3885
|
async function pollJob(job) {
|
|
3716
3886
|
if (job.result) {
|
|
3717
|
-
return ok(
|
|
3718
|
-
job.result.success ? { status: "succeeded", result: job.result } : { status: "failed", error: job.result.error }
|
|
3719
|
-
);
|
|
3887
|
+
return ok(await finalizeSnapshot(job, job.result.success ? { status: "succeeded", result: job.result } : { status: "failed", error: job.result.error }));
|
|
3720
3888
|
}
|
|
3721
3889
|
const routed = route(job.model);
|
|
3722
3890
|
if (routed.error) return fail(routed.error);
|
|
@@ -3729,7 +3897,7 @@ function brotuClient(options) {
|
|
|
3729
3897
|
});
|
|
3730
3898
|
}
|
|
3731
3899
|
try {
|
|
3732
|
-
return ok(await adapter.completeJob(job));
|
|
3900
|
+
return ok(await finalizeSnapshot(job, await adapter.completeJob(job)));
|
|
3733
3901
|
} catch (error) {
|
|
3734
3902
|
return failFrom("provider_error", error, {
|
|
3735
3903
|
provider: job.provider,
|
|
@@ -3798,6 +3966,17 @@ function brotuClient(options) {
|
|
|
3798
3966
|
submit: (params) => submit("audio", params),
|
|
3799
3967
|
generate: (params) => generate("audio", params)
|
|
3800
3968
|
},
|
|
3969
|
+
webhook: {
|
|
3970
|
+
set(value) {
|
|
3971
|
+
registeredWebhook = resolveWebhook(value);
|
|
3972
|
+
},
|
|
3973
|
+
clear() {
|
|
3974
|
+
registeredWebhook = void 0;
|
|
3975
|
+
},
|
|
3976
|
+
get() {
|
|
3977
|
+
return registeredWebhook;
|
|
3978
|
+
}
|
|
3979
|
+
},
|
|
3801
3980
|
jobs: {
|
|
3802
3981
|
poll: pollJob,
|
|
3803
3982
|
wait: async (job, waitOptions) => {
|
|
@@ -3807,7 +3986,13 @@ function brotuClient(options) {
|
|
|
3807
3986
|
if (polled.error) return fail(polled.error);
|
|
3808
3987
|
const snapshot = polled.data;
|
|
3809
3988
|
if (snapshot.status === "succeeded" && snapshot.result) {
|
|
3810
|
-
return
|
|
3989
|
+
return ok({
|
|
3990
|
+
outputs: snapshot.result.outputs,
|
|
3991
|
+
provider: snapshot.result.provider,
|
|
3992
|
+
model: snapshot.result.model,
|
|
3993
|
+
processingTimeMs: snapshot.result.processingTimeMs,
|
|
3994
|
+
metadata: job.metadata
|
|
3995
|
+
});
|
|
3811
3996
|
}
|
|
3812
3997
|
if (snapshot.status === "failed") {
|
|
3813
3998
|
return fail({
|
|
@@ -3877,6 +4062,7 @@ function brotuClient(options) {
|
|
|
3877
4062
|
QwenAdapter,
|
|
3878
4063
|
brotuClient,
|
|
3879
4064
|
createS3Storage,
|
|
4065
|
+
deliverWebhook,
|
|
3880
4066
|
fail,
|
|
3881
4067
|
getAvailableModels,
|
|
3882
4068
|
getModel,
|
|
@@ -3888,5 +4074,6 @@ function brotuClient(options) {
|
|
|
3888
4074
|
persistOutputs,
|
|
3889
4075
|
registerModels,
|
|
3890
4076
|
resetCatalog,
|
|
3891
|
-
resolveProvider
|
|
4077
|
+
resolveProvider,
|
|
4078
|
+
resolveWebhook
|
|
3892
4079
|
});
|
package/dist/index.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ export type * from "./constants/model.types";
|
|
|
17
17
|
export { type AIError, type AIErrorCode, fail, type Generation, ok, type Result, } from "./helpers/result";
|
|
18
18
|
export { isPendingJob, type Job, type JobSnapshot, type JobStatus, PendingJob, } from "./lib/jobs";
|
|
19
19
|
export { createS3Storage, persistOutputs, type S3StorageConfig, type Storage, } from "./lib/storage";
|
|
20
|
+
export { deliverWebhook, resolveWebhook, type WebhookConfig, type WebhookEvent, type WebhookEventName, } from "./lib/webhook";
|
|
20
21
|
export type * from "./ports/content-generator.port";
|
|
21
22
|
export { BYTEPLUS_CATALOG, BYTEPLUS_MODELS, type BytePlusModelBinding, } from "./providers/byteplus.models";
|
|
22
23
|
export { ELEVENLABS_CATALOG, ELEVENLABS_MODELS, ELEVENLABS_OUTPUT_FORMATS, } from "./providers/elevenlabs.models";
|
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,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,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,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,mBAAmB,yBAAyB,CAAC;AAC7C,OAAO,EACN,KAAK,OAAO,EACZ,KAAK,WAAW,EAChB,IAAI,EACJ,KAAK,UAAU,EACf,EAAE,EACF,KAAK,MAAM,GACX,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACN,YAAY,EACZ,KAAK,GAAG,EACR,KAAK,WAAW,EAChB,KAAK,SAAS,EACd,UAAU,GACV,MAAM,YAAY,CAAC;AACpB,OAAO,EACN,eAAe,EACf,cAAc,EACd,KAAK,eAAe,EACpB,KAAK,OAAO,GACZ,MAAM,eAAe,CAAC;AACvB,mBAAmB,gCAAgC,CAAC;AACpD,OAAO,EACN,gBAAgB,EAChB,eAAe,EACf,KAAK,oBAAoB,GACzB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACN,kBAAkB,EAClB,iBAAiB,EACjB,yBAAyB,GACzB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACN,mBAAmB,EACnB,cAAc,EACd,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,GACnB,MAAM,2BAA2B,CAAC;AACnC,YAAY,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EACN,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,kBAAkB,EAClB,aAAa,EACb,YAAY,EACZ,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,gBAAgB,GACrB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACN,cAAc,EACd,mBAAmB,EACnB,kBAAkB,GAClB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACN,iBAAiB,EACjB,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,GACrB,MAAM,yBAAyB,CAAC;AACjC,YAAY,EACX,cAAc,EACd,cAAc,EACd,kBAAkB,EAClB,gBAAgB,GAChB,MAAM,SAAS,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,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,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,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,mBAAmB,yBAAyB,CAAC;AAC7C,OAAO,EACN,KAAK,OAAO,EACZ,KAAK,WAAW,EAChB,IAAI,EACJ,KAAK,UAAU,EACf,EAAE,EACF,KAAK,MAAM,GACX,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACN,YAAY,EACZ,KAAK,GAAG,EACR,KAAK,WAAW,EAChB,KAAK,SAAS,EACd,UAAU,GACV,MAAM,YAAY,CAAC;AACpB,OAAO,EACN,eAAe,EACf,cAAc,EACd,KAAK,eAAe,EACpB,KAAK,OAAO,GACZ,MAAM,eAAe,CAAC;AACvB,OAAO,EACN,cAAc,EACd,cAAc,EACd,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,gBAAgB,GACrB,MAAM,eAAe,CAAC;AACvB,mBAAmB,gCAAgC,CAAC;AACpD,OAAO,EACN,gBAAgB,EAChB,eAAe,EACf,KAAK,oBAAoB,GACzB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACN,kBAAkB,EAClB,iBAAiB,EACjB,yBAAyB,GACzB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACN,mBAAmB,EACnB,cAAc,EACd,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,GACnB,MAAM,2BAA2B,CAAC;AACnC,YAAY,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EACN,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,kBAAkB,EAClB,aAAa,EACb,YAAY,EACZ,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,gBAAgB,GACrB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACN,cAAc,EACd,mBAAmB,EACnB,kBAAkB,GAClB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACN,iBAAiB,EACjB,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,GACrB,MAAM,yBAAyB,CAAC;AACjC,YAAY,EACX,cAAc,EACd,cAAc,EACd,kBAAkB,EAClB,gBAAgB,GAChB,MAAM,SAAS,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -2256,6 +2256,45 @@ async function persistOutputs(storage, outputs) {
|
|
|
2256
2256
|
);
|
|
2257
2257
|
}
|
|
2258
2258
|
|
|
2259
|
+
// src/lib/webhook.ts
|
|
2260
|
+
function resolveWebhook(value) {
|
|
2261
|
+
if (!value) return void 0;
|
|
2262
|
+
if (typeof value === "string") {
|
|
2263
|
+
return isHttpUrl(value) ? { url: value } : void 0;
|
|
2264
|
+
}
|
|
2265
|
+
if (!isHttpUrl(value.url)) return void 0;
|
|
2266
|
+
return {
|
|
2267
|
+
url: value.url,
|
|
2268
|
+
secret: value.secret,
|
|
2269
|
+
headers: value.headers
|
|
2270
|
+
};
|
|
2271
|
+
}
|
|
2272
|
+
function isHttpUrl(value) {
|
|
2273
|
+
try {
|
|
2274
|
+
const parsed = new URL(value);
|
|
2275
|
+
return parsed.protocol === "https:" || parsed.protocol === "http:";
|
|
2276
|
+
} catch {
|
|
2277
|
+
return false;
|
|
2278
|
+
}
|
|
2279
|
+
}
|
|
2280
|
+
async function deliverWebhook(config, payload) {
|
|
2281
|
+
try {
|
|
2282
|
+
await fetch(config.url, {
|
|
2283
|
+
method: "POST",
|
|
2284
|
+
headers: {
|
|
2285
|
+
"content-type": "application/json",
|
|
2286
|
+
"user-agent": "@brotu/ai",
|
|
2287
|
+
"x-brotu-event": payload.event,
|
|
2288
|
+
...config.secret ? { "x-brotu-webhook-secret": config.secret } : {},
|
|
2289
|
+
...config.headers
|
|
2290
|
+
},
|
|
2291
|
+
body: JSON.stringify(payload),
|
|
2292
|
+
signal: AbortSignal.timeout(1e4)
|
|
2293
|
+
});
|
|
2294
|
+
} catch {
|
|
2295
|
+
}
|
|
2296
|
+
}
|
|
2297
|
+
|
|
2259
2298
|
// src/client.ts
|
|
2260
2299
|
var NATIVE_PROVIDERS = [
|
|
2261
2300
|
"byteplus",
|
|
@@ -2270,6 +2309,8 @@ function brotuClient(options) {
|
|
|
2270
2309
|
throw new Error("brotuClient requires at least one provider API key.");
|
|
2271
2310
|
}
|
|
2272
2311
|
registerModels(options.models);
|
|
2312
|
+
let registeredWebhook = resolveWebhook(options.webhook);
|
|
2313
|
+
const notifiedJobIds = /* @__PURE__ */ new Set();
|
|
2273
2314
|
const storage = options.storage ? createS3Storage(options.storage) : void 0;
|
|
2274
2315
|
const shouldPersist = storage && options.storage?.persistOutputs !== false;
|
|
2275
2316
|
const adapters = /* @__PURE__ */ new Map();
|
|
@@ -2359,6 +2400,31 @@ function brotuClient(options) {
|
|
|
2359
2400
|
return adapter.generateAudio(params);
|
|
2360
2401
|
return adapter.generateText(params);
|
|
2361
2402
|
}
|
|
2403
|
+
function webhookFor(params) {
|
|
2404
|
+
return resolveWebhook(params?.webhook) ?? registeredWebhook;
|
|
2405
|
+
}
|
|
2406
|
+
async function notifySettled(input) {
|
|
2407
|
+
const config = webhookFor(input.params);
|
|
2408
|
+
if (!config) return;
|
|
2409
|
+
const jobId = input.job?.id;
|
|
2410
|
+
if (jobId) {
|
|
2411
|
+
if (notifiedJobIds.has(jobId)) return;
|
|
2412
|
+
notifiedJobIds.add(jobId);
|
|
2413
|
+
}
|
|
2414
|
+
const payload = {
|
|
2415
|
+
event: input.event,
|
|
2416
|
+
jobId,
|
|
2417
|
+
provider: input.provider ?? input.job?.provider,
|
|
2418
|
+
model: input.model ?? input.job?.model,
|
|
2419
|
+
kind: input.kind ?? input.job?.kind,
|
|
2420
|
+
outputs: input.outputs,
|
|
2421
|
+
error: input.error ? { code: input.error.code, message: input.error.message } : void 0,
|
|
2422
|
+
metadata: input.metadata ?? input.job?.metadata,
|
|
2423
|
+
processingTimeMs: input.processingTimeMs,
|
|
2424
|
+
completedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
2425
|
+
};
|
|
2426
|
+
await deliverWebhook(config, payload);
|
|
2427
|
+
}
|
|
2362
2428
|
async function toGeneration(raw, metadata) {
|
|
2363
2429
|
if (!raw.success) {
|
|
2364
2430
|
return fail({
|
|
@@ -2381,15 +2447,50 @@ function brotuClient(options) {
|
|
|
2381
2447
|
const routed = route(params.model);
|
|
2382
2448
|
if (routed.error) return fail(routed.error);
|
|
2383
2449
|
try {
|
|
2384
|
-
|
|
2450
|
+
const result = await toGeneration(
|
|
2385
2451
|
await generateWith(routed.data.adapter, kind, params),
|
|
2386
2452
|
params.metadata
|
|
2387
2453
|
);
|
|
2454
|
+
if (result.error) {
|
|
2455
|
+
await notifySettled({
|
|
2456
|
+
event: "generation.failed",
|
|
2457
|
+
params,
|
|
2458
|
+
kind,
|
|
2459
|
+
provider: routed.data.provider,
|
|
2460
|
+
model: routed.data.model,
|
|
2461
|
+
error: result.error,
|
|
2462
|
+
metadata: params.metadata
|
|
2463
|
+
});
|
|
2464
|
+
return result;
|
|
2465
|
+
}
|
|
2466
|
+
await notifySettled({
|
|
2467
|
+
event: "generation.succeeded",
|
|
2468
|
+
params,
|
|
2469
|
+
kind,
|
|
2470
|
+
provider: result.data.provider,
|
|
2471
|
+
model: result.data.model,
|
|
2472
|
+
outputs: result.data.outputs,
|
|
2473
|
+
metadata: result.data.metadata,
|
|
2474
|
+
processingTimeMs: result.data.processingTimeMs
|
|
2475
|
+
});
|
|
2476
|
+
return result;
|
|
2388
2477
|
} catch (error) {
|
|
2389
|
-
|
|
2478
|
+
const failed = failFrom("provider_error", error, {
|
|
2390
2479
|
provider: routed.data.provider,
|
|
2391
2480
|
model: routed.data.model
|
|
2392
2481
|
});
|
|
2482
|
+
if (failed.error) {
|
|
2483
|
+
await notifySettled({
|
|
2484
|
+
event: "generation.failed",
|
|
2485
|
+
params,
|
|
2486
|
+
kind,
|
|
2487
|
+
provider: routed.data.provider,
|
|
2488
|
+
model: routed.data.model,
|
|
2489
|
+
error: failed.error,
|
|
2490
|
+
metadata: params.metadata
|
|
2491
|
+
});
|
|
2492
|
+
}
|
|
2493
|
+
return failed;
|
|
2393
2494
|
}
|
|
2394
2495
|
}
|
|
2395
2496
|
async function submit(kind, params) {
|
|
@@ -2408,18 +2509,40 @@ function brotuClient(options) {
|
|
|
2408
2509
|
() => generateWith(routed.data.adapter, kind, params)
|
|
2409
2510
|
);
|
|
2410
2511
|
if (!raw.success) {
|
|
2411
|
-
|
|
2512
|
+
const error = {
|
|
2412
2513
|
code: "provider_error",
|
|
2413
2514
|
message: raw.error ?? "The provider rejected the request.",
|
|
2414
2515
|
provider: raw.provider,
|
|
2415
2516
|
model: raw.model
|
|
2517
|
+
};
|
|
2518
|
+
await notifySettled({
|
|
2519
|
+
event: "generation.failed",
|
|
2520
|
+
params,
|
|
2521
|
+
kind,
|
|
2522
|
+
provider: raw.provider,
|
|
2523
|
+
model: raw.model,
|
|
2524
|
+
error,
|
|
2525
|
+
metadata: params.metadata
|
|
2416
2526
|
});
|
|
2527
|
+
return fail(error);
|
|
2417
2528
|
}
|
|
2418
|
-
|
|
2529
|
+
const job = {
|
|
2419
2530
|
...base,
|
|
2420
2531
|
id: `inline-${base.model}-${base.submittedAt}`,
|
|
2421
2532
|
result: raw
|
|
2533
|
+
};
|
|
2534
|
+
await notifySettled({
|
|
2535
|
+
event: "generation.succeeded",
|
|
2536
|
+
params,
|
|
2537
|
+
job,
|
|
2538
|
+
kind,
|
|
2539
|
+
provider: raw.provider,
|
|
2540
|
+
model: raw.model,
|
|
2541
|
+
outputs: raw.outputs,
|
|
2542
|
+
metadata: params.metadata,
|
|
2543
|
+
processingTimeMs: raw.processingTimeMs
|
|
2422
2544
|
});
|
|
2545
|
+
return ok(job);
|
|
2423
2546
|
} catch (error) {
|
|
2424
2547
|
if (!isPendingJob(error)) {
|
|
2425
2548
|
return failFrom("provider_error", error, {
|
|
@@ -2434,11 +2557,54 @@ function brotuClient(options) {
|
|
|
2434
2557
|
});
|
|
2435
2558
|
}
|
|
2436
2559
|
}
|
|
2560
|
+
async function notifyFromSnapshot(job, snapshot) {
|
|
2561
|
+
if (snapshot.status === "succeeded" && snapshot.result) {
|
|
2562
|
+
await notifySettled({
|
|
2563
|
+
event: "generation.succeeded",
|
|
2564
|
+
params: job.params,
|
|
2565
|
+
job,
|
|
2566
|
+
outputs: snapshot.result.outputs,
|
|
2567
|
+
provider: snapshot.result.provider,
|
|
2568
|
+
model: snapshot.result.model,
|
|
2569
|
+
processingTimeMs: snapshot.result.processingTimeMs,
|
|
2570
|
+
metadata: job.metadata
|
|
2571
|
+
});
|
|
2572
|
+
return;
|
|
2573
|
+
}
|
|
2574
|
+
if (snapshot.status === "failed") {
|
|
2575
|
+
await notifySettled({
|
|
2576
|
+
event: "generation.failed",
|
|
2577
|
+
params: job.params,
|
|
2578
|
+
job,
|
|
2579
|
+
error: {
|
|
2580
|
+
code: "provider_error",
|
|
2581
|
+
message: snapshot.error ?? "The job failed.",
|
|
2582
|
+
provider: job.provider,
|
|
2583
|
+
model: job.model
|
|
2584
|
+
},
|
|
2585
|
+
metadata: job.metadata
|
|
2586
|
+
});
|
|
2587
|
+
}
|
|
2588
|
+
}
|
|
2589
|
+
async function finalizeSnapshot(job, snapshot) {
|
|
2590
|
+
if (snapshot.status === "succeeded" && snapshot.result) {
|
|
2591
|
+
const persisted = await toGeneration(snapshot.result, job.metadata);
|
|
2592
|
+
if (!persisted.error) {
|
|
2593
|
+
snapshot = {
|
|
2594
|
+
status: "succeeded",
|
|
2595
|
+
result: {
|
|
2596
|
+
...snapshot.result,
|
|
2597
|
+
outputs: persisted.data.outputs
|
|
2598
|
+
}
|
|
2599
|
+
};
|
|
2600
|
+
}
|
|
2601
|
+
}
|
|
2602
|
+
await notifyFromSnapshot(job, snapshot);
|
|
2603
|
+
return snapshot;
|
|
2604
|
+
}
|
|
2437
2605
|
async function pollJob(job) {
|
|
2438
2606
|
if (job.result) {
|
|
2439
|
-
return ok(
|
|
2440
|
-
job.result.success ? { status: "succeeded", result: job.result } : { status: "failed", error: job.result.error }
|
|
2441
|
-
);
|
|
2607
|
+
return ok(await finalizeSnapshot(job, job.result.success ? { status: "succeeded", result: job.result } : { status: "failed", error: job.result.error }));
|
|
2442
2608
|
}
|
|
2443
2609
|
const routed = route(job.model);
|
|
2444
2610
|
if (routed.error) return fail(routed.error);
|
|
@@ -2451,7 +2617,7 @@ function brotuClient(options) {
|
|
|
2451
2617
|
});
|
|
2452
2618
|
}
|
|
2453
2619
|
try {
|
|
2454
|
-
return ok(await adapter.completeJob(job));
|
|
2620
|
+
return ok(await finalizeSnapshot(job, await adapter.completeJob(job)));
|
|
2455
2621
|
} catch (error) {
|
|
2456
2622
|
return failFrom("provider_error", error, {
|
|
2457
2623
|
provider: job.provider,
|
|
@@ -2520,6 +2686,17 @@ function brotuClient(options) {
|
|
|
2520
2686
|
submit: (params) => submit("audio", params),
|
|
2521
2687
|
generate: (params) => generate("audio", params)
|
|
2522
2688
|
},
|
|
2689
|
+
webhook: {
|
|
2690
|
+
set(value) {
|
|
2691
|
+
registeredWebhook = resolveWebhook(value);
|
|
2692
|
+
},
|
|
2693
|
+
clear() {
|
|
2694
|
+
registeredWebhook = void 0;
|
|
2695
|
+
},
|
|
2696
|
+
get() {
|
|
2697
|
+
return registeredWebhook;
|
|
2698
|
+
}
|
|
2699
|
+
},
|
|
2523
2700
|
jobs: {
|
|
2524
2701
|
poll: pollJob,
|
|
2525
2702
|
wait: async (job, waitOptions) => {
|
|
@@ -2529,7 +2706,13 @@ function brotuClient(options) {
|
|
|
2529
2706
|
if (polled.error) return fail(polled.error);
|
|
2530
2707
|
const snapshot = polled.data;
|
|
2531
2708
|
if (snapshot.status === "succeeded" && snapshot.result) {
|
|
2532
|
-
return
|
|
2709
|
+
return ok({
|
|
2710
|
+
outputs: snapshot.result.outputs,
|
|
2711
|
+
provider: snapshot.result.provider,
|
|
2712
|
+
model: snapshot.result.model,
|
|
2713
|
+
processingTimeMs: snapshot.result.processingTimeMs,
|
|
2714
|
+
metadata: job.metadata
|
|
2715
|
+
});
|
|
2533
2716
|
}
|
|
2534
2717
|
if (snapshot.status === "failed") {
|
|
2535
2718
|
return fail({
|
|
@@ -2598,6 +2781,7 @@ export {
|
|
|
2598
2781
|
QwenAdapter,
|
|
2599
2782
|
brotuClient,
|
|
2600
2783
|
createS3Storage,
|
|
2784
|
+
deliverWebhook,
|
|
2601
2785
|
fail,
|
|
2602
2786
|
getAvailableModels,
|
|
2603
2787
|
getModel,
|
|
@@ -2609,5 +2793,6 @@ export {
|
|
|
2609
2793
|
persistOutputs,
|
|
2610
2794
|
registerModels,
|
|
2611
2795
|
resetCatalog,
|
|
2612
|
-
resolveProvider
|
|
2796
|
+
resolveProvider,
|
|
2797
|
+
resolveWebhook
|
|
2613
2798
|
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { AIError } from "../helpers/result";
|
|
2
|
+
import type { GenerationOutput, GenerationType } from "../ports/content-generator.port";
|
|
3
|
+
export type WebhookEventName = "generation.succeeded" | "generation.failed";
|
|
4
|
+
export interface WebhookConfig {
|
|
5
|
+
url: string;
|
|
6
|
+
/** Sent as `x-brotu-webhook-secret` so your endpoint can reject strangers. */
|
|
7
|
+
secret?: string;
|
|
8
|
+
headers?: Record<string, string>;
|
|
9
|
+
}
|
|
10
|
+
export interface WebhookEvent {
|
|
11
|
+
event: WebhookEventName;
|
|
12
|
+
jobId?: string;
|
|
13
|
+
provider?: string;
|
|
14
|
+
model?: string;
|
|
15
|
+
kind?: GenerationType;
|
|
16
|
+
outputs?: GenerationOutput[];
|
|
17
|
+
error?: Pick<AIError, "code" | "message">;
|
|
18
|
+
metadata?: Record<string, string>;
|
|
19
|
+
processingTimeMs?: number;
|
|
20
|
+
completedAt: string;
|
|
21
|
+
}
|
|
22
|
+
export declare function resolveWebhook(value: string | WebhookConfig | undefined): WebhookConfig | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* POST the settled generation at the registered URL. Failures are swallowed:
|
|
25
|
+
* a down hook must not fail the call the user is waiting on.
|
|
26
|
+
*/
|
|
27
|
+
export declare function deliverWebhook(config: WebhookConfig, payload: WebhookEvent): Promise<void>;
|
|
28
|
+
//# sourceMappingURL=webhook.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhook.d.ts","sourceRoot":"","sources":["../../src/lib/webhook.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,KAAK,EACX,gBAAgB,EAChB,cAAc,EACd,MAAM,iCAAiC,CAAC;AAEzC,MAAM,MAAM,gBAAgB,GAAG,sBAAsB,GAAG,mBAAmB,CAAC;AAE5E,MAAM,WAAW,aAAa;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,YAAY;IAC5B,KAAK,EAAE,gBAAgB,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,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,WAAW,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,cAAc,CAC7B,KAAK,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,GACvC,aAAa,GAAG,SAAS,CAW3B;AAWD;;;GAGG;AACH,wBAAsB,cAAc,CACnC,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,YAAY,GACnB,OAAO,CAAC,IAAI,CAAC,CAmBf"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { BillingUnit } from "../constants/model.types";
|
|
2
|
+
import type { WebhookConfig } from "../lib/webhook";
|
|
2
3
|
/** Known values, kept open because providers disagree on spelling and units. */
|
|
3
4
|
export type VideoResolution = "480p" | "580p" | "720p" | "768p" | "1080p" | "4k" | "480P" | "720P" | "1080P" | (string & {});
|
|
4
5
|
export type ImageResolution = "1K" | "2K" | "4K" | (string & {});
|
|
@@ -23,6 +24,11 @@ export interface CommonGenerationParams {
|
|
|
23
24
|
* overrides what the adapter would otherwise send.
|
|
24
25
|
*/
|
|
25
26
|
providerOptions?: Record<string, Record<string, unknown>>;
|
|
27
|
+
/**
|
|
28
|
+
* Override the client-level webhook for this request. Same shape: a URL
|
|
29
|
+
* string or `{ url, secret }`. Not sent to the provider.
|
|
30
|
+
*/
|
|
31
|
+
webhook?: string | WebhookConfig;
|
|
26
32
|
}
|
|
27
33
|
/**
|
|
28
34
|
* Shared image parameters.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content-generator.port.d.ts","sourceRoot":"","sources":["../../src/ports/content-generator.port.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"content-generator.port.d.ts","sourceRoot":"","sources":["../../src/ports/content-generator.port.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { AIModelConfig } from "./constants/model.types";
|
|
2
2
|
import type { S3StorageConfig } from "./lib/storage";
|
|
3
|
+
import type { WebhookConfig } from "./lib/webhook";
|
|
3
4
|
export interface ProviderConfig {
|
|
4
5
|
apiKey: string;
|
|
5
6
|
/** Defaults to the known base URL for the provider, when there is one. */
|
|
@@ -45,6 +46,12 @@ export interface BrotuAIOptions {
|
|
|
45
46
|
elevenLabsVoiceId?: string;
|
|
46
47
|
/** Extra models, or overrides of built-in ones, merged by id. */
|
|
47
48
|
models?: AIModelConfig[];
|
|
49
|
+
/**
|
|
50
|
+
* URL (or `{ url, secret }`) the client POSTs when a generation settles.
|
|
51
|
+
* Fires from `generate`, `jobs.wait`, and a terminal `jobs.poll`. Change it
|
|
52
|
+
* later with `ai.webhook.set`. A per-request `webhook` on the params wins.
|
|
53
|
+
*/
|
|
54
|
+
webhook?: string | WebhookConfig;
|
|
48
55
|
}
|
|
49
56
|
/** Resolved per-request routing: which host and key serve this model. */
|
|
50
57
|
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;
|
|
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,gFAAgF;IAChF,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC1C,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;CACjC;AAED,yEAAyE;AACzE,MAAM,WAAW,gBAAgB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CAChB"}
|