@wavebirdai/api 0.1.0-beta.11 → 0.1.0-beta.12
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 +1 -1
- package/dist/browser.d.ts +6 -1
- package/dist/browser.js +26 -8
- package/package.json +1 -1
- package/src/browser.d.ts +6 -1
- package/src/browser.js +26 -8
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ You need a saved Wavebird Test project and placement in Dashboard, a Server Test
|
|
|
9
9
|
1. Install the package and generate the route files for your app directory:
|
|
10
10
|
|
|
11
11
|
```sh
|
|
12
|
-
npm install @wavebirdai/api@0.1.0-beta.
|
|
12
|
+
npm install @wavebirdai/api@0.1.0-beta.12
|
|
13
13
|
./node_modules/.bin/wavebird-next init --lang ts --root . --app-dir src/app
|
|
14
14
|
```
|
|
15
15
|
|
package/dist/browser.d.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
/** Resolve after the publisher has presented the result; After timing starts then. */
|
|
2
|
-
export type GenerationConsumer<T> = (response: Response, lifecycle: {
|
|
2
|
+
export type GenerationConsumer<T> = (response: Response, lifecycle: {
|
|
3
|
+
/** Streaming output progress. For Before and During Image, call after the first result is presented. */
|
|
4
|
+
onDelta(): void;
|
|
5
|
+
/** Explicitly mark the result as presented. Idempotent and bound to this generation. */
|
|
6
|
+
onPresented(): void;
|
|
7
|
+
}) => T | Promise<T>;
|
|
3
8
|
export type PublisherAds<Bound extends boolean = boolean> = {
|
|
4
9
|
ready: Promise<void>;
|
|
5
10
|
connectGeneration<T>(options: { request: (headers: Record<string, string>) => Response | Promise<Response>; consume: GenerationConsumer<T>; signal?: AbortSignal }): Promise<T>;
|
package/dist/browser.js
CHANGED
|
@@ -75,6 +75,10 @@ export function createPublisherAds(options) {
|
|
|
75
75
|
sponsor = null; slot.hidden = true; slot.replaceChildren();
|
|
76
76
|
}
|
|
77
77
|
};
|
|
78
|
+
const notifyPresented = id => {
|
|
79
|
+
// Additive bridge: an already deployed renderer may predate this event.
|
|
80
|
+
if (typeof sponsor?.onPresented === "function") notify("onPresented", id);
|
|
81
|
+
};
|
|
78
82
|
const current = job => !disposed && !job.cancelled && job.context === context && active === job;
|
|
79
83
|
const event = (job, type) => {
|
|
80
84
|
if (!current(job)) return;
|
|
@@ -84,9 +88,15 @@ export function createPublisherAds(options) {
|
|
|
84
88
|
} else if (type === "progress") {
|
|
85
89
|
if (job.state === "started") { job.progressed = true; notify("onDelta", job.id); }
|
|
86
90
|
} else if (type === "no_result") {
|
|
87
|
-
if (job.state === "started") job.state = "no_result";
|
|
88
|
-
} else if (["done", "error", "abort"].includes(type)) {
|
|
89
91
|
if (job.state !== "started") return;
|
|
92
|
+
job.state = "no_result";
|
|
93
|
+
if (timing !== "after") notify("onError", job.id);
|
|
94
|
+
} else if (type === "presented") {
|
|
95
|
+
if (!["started", "done"].includes(job.state) || job.presented) return;
|
|
96
|
+
job.presented = true; notifyPresented(job.id);
|
|
97
|
+
} else if (["done", "error", "abort"].includes(type)) {
|
|
98
|
+
if (job.state !== "started" &&
|
|
99
|
+
!(job.state === "done" && !job.consumed && ["error", "abort"].includes(type))) return;
|
|
90
100
|
job.state = type;
|
|
91
101
|
notify(type === "done" ? "onDone" : type === "abort" ? "onAbort" : "onError", job.id);
|
|
92
102
|
}
|
|
@@ -118,7 +128,7 @@ export function createPublisherAds(options) {
|
|
|
118
128
|
const ready = loadRenderer(rendererUrl).then(() => {
|
|
119
129
|
if (disposed) return;
|
|
120
130
|
sponsor = window.wavebird.createChatSponsor({ target: slot, ...binding,
|
|
121
|
-
clientId: options.clientId, surfaceId: options.surfaceId, timing, consentMode,
|
|
131
|
+
clientId: options.clientId, surfaceId: options.surfaceId, jobType: options.jobType, timing, consentMode,
|
|
122
132
|
cleanupAfterClip: true,
|
|
123
133
|
...(turnBinding ? { turnBinding: true } : {}),
|
|
124
134
|
...(options.getFormat === undefined ? {} : { getFormat: options.getFormat }),
|
|
@@ -136,7 +146,8 @@ export function createPublisherAds(options) {
|
|
|
136
146
|
}).catch(() => {});
|
|
137
147
|
|
|
138
148
|
async function connectGeneration({ request, consume, signal }) {
|
|
139
|
-
const job = { id: crypto.randomUUID(), sessionId: binding.sessionId, context, state: "pending", cancelled: false
|
|
149
|
+
const job = { id: crypto.randomUUID(), sessionId: binding.sessionId, context, state: "pending", cancelled: false,
|
|
150
|
+
presented: false, consumed: false };
|
|
140
151
|
if (active) event(active, "abort");
|
|
141
152
|
active = job;
|
|
142
153
|
let reader = null, ended = false, buffer = "";
|
|
@@ -195,7 +206,8 @@ export function createPublisherAds(options) {
|
|
|
195
206
|
}
|
|
196
207
|
if (["done", "error", "abort"].includes(record.type)) {
|
|
197
208
|
ended = true;
|
|
198
|
-
if (record.type
|
|
209
|
+
if (record.type === "done" && [204, 205, 304].includes(metadata.status)) event(job, "no_result");
|
|
210
|
+
else if (record.type !== "done" || timing !== "after") event(job, record.type);
|
|
199
211
|
if (record.type === "done" || !metadata.status.toString().startsWith("2")) controller.close();
|
|
200
212
|
else controller.error(new Error("generation_" + record.type));
|
|
201
213
|
return;
|
|
@@ -210,14 +222,20 @@ export function createPublisherAds(options) {
|
|
|
210
222
|
const record = await nextRecord();
|
|
211
223
|
if (!["done", "error", "abort"].includes(record.type)) throw new Error("generation_transport_invalid");
|
|
212
224
|
ended = true;
|
|
213
|
-
if (record.type
|
|
225
|
+
if (record.type === "done") event(job, "no_result");
|
|
226
|
+
else event(job, record.type);
|
|
214
227
|
}
|
|
215
228
|
const noBody = [204, 205, 304].includes(metadata.status);
|
|
216
229
|
const primary = new Response(noBody ? null : output, {
|
|
217
230
|
status: metadata.status, statusText: metadata.status_text || "", headers: metadata.headers
|
|
218
231
|
});
|
|
219
|
-
const result = await consume(primary, { onDelta: () =>
|
|
220
|
-
|
|
232
|
+
const result = await consume(primary, { onDelta: () => {
|
|
233
|
+
event(job, "progress");
|
|
234
|
+
if (timing === "before" || (timing === "during" && options.jobType === "image")) event(job, "presented");
|
|
235
|
+
}, onPresented: () => event(job, "presented") });
|
|
236
|
+
job.consumed = true;
|
|
237
|
+
if (timing === "before" || (timing === "during" && options.jobType === "image")) event(job, "presented");
|
|
238
|
+
if (timing === "after" && ended && !noBody) event(job, "done");
|
|
221
239
|
return result;
|
|
222
240
|
} catch (error) {
|
|
223
241
|
event(job, signal?.aborted ? "abort" : "error");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wavebirdai/api",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.12",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Integrate Banner, Native, and Clip placements into authenticated chat apps with server-side keys, consent, and generation lifecycle handling",
|
package/src/browser.d.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
/** Resolve after the publisher has presented the result; After timing starts then. */
|
|
2
|
-
export type GenerationConsumer<T> = (response: Response, lifecycle: {
|
|
2
|
+
export type GenerationConsumer<T> = (response: Response, lifecycle: {
|
|
3
|
+
/** Streaming output progress. For Before and During Image, call after the first result is presented. */
|
|
4
|
+
onDelta(): void;
|
|
5
|
+
/** Explicitly mark the result as presented. Idempotent and bound to this generation. */
|
|
6
|
+
onPresented(): void;
|
|
7
|
+
}) => T | Promise<T>;
|
|
3
8
|
export type PublisherAds<Bound extends boolean = boolean> = {
|
|
4
9
|
ready: Promise<void>;
|
|
5
10
|
connectGeneration<T>(options: { request: (headers: Record<string, string>) => Response | Promise<Response>; consume: GenerationConsumer<T>; signal?: AbortSignal }): Promise<T>;
|
package/src/browser.js
CHANGED
|
@@ -75,6 +75,10 @@ export function createPublisherAds(options) {
|
|
|
75
75
|
sponsor = null; slot.hidden = true; slot.replaceChildren();
|
|
76
76
|
}
|
|
77
77
|
};
|
|
78
|
+
const notifyPresented = id => {
|
|
79
|
+
// Additive bridge: an already deployed renderer may predate this event.
|
|
80
|
+
if (typeof sponsor?.onPresented === "function") notify("onPresented", id);
|
|
81
|
+
};
|
|
78
82
|
const current = job => !disposed && !job.cancelled && job.context === context && active === job;
|
|
79
83
|
const event = (job, type) => {
|
|
80
84
|
if (!current(job)) return;
|
|
@@ -84,9 +88,15 @@ export function createPublisherAds(options) {
|
|
|
84
88
|
} else if (type === "progress") {
|
|
85
89
|
if (job.state === "started") { job.progressed = true; notify("onDelta", job.id); }
|
|
86
90
|
} else if (type === "no_result") {
|
|
87
|
-
if (job.state === "started") job.state = "no_result";
|
|
88
|
-
} else if (["done", "error", "abort"].includes(type)) {
|
|
89
91
|
if (job.state !== "started") return;
|
|
92
|
+
job.state = "no_result";
|
|
93
|
+
if (timing !== "after") notify("onError", job.id);
|
|
94
|
+
} else if (type === "presented") {
|
|
95
|
+
if (!["started", "done"].includes(job.state) || job.presented) return;
|
|
96
|
+
job.presented = true; notifyPresented(job.id);
|
|
97
|
+
} else if (["done", "error", "abort"].includes(type)) {
|
|
98
|
+
if (job.state !== "started" &&
|
|
99
|
+
!(job.state === "done" && !job.consumed && ["error", "abort"].includes(type))) return;
|
|
90
100
|
job.state = type;
|
|
91
101
|
notify(type === "done" ? "onDone" : type === "abort" ? "onAbort" : "onError", job.id);
|
|
92
102
|
}
|
|
@@ -118,7 +128,7 @@ export function createPublisherAds(options) {
|
|
|
118
128
|
const ready = loadRenderer(rendererUrl).then(() => {
|
|
119
129
|
if (disposed) return;
|
|
120
130
|
sponsor = window.wavebird.createChatSponsor({ target: slot, ...binding,
|
|
121
|
-
clientId: options.clientId, surfaceId: options.surfaceId, timing, consentMode,
|
|
131
|
+
clientId: options.clientId, surfaceId: options.surfaceId, jobType: options.jobType, timing, consentMode,
|
|
122
132
|
cleanupAfterClip: true,
|
|
123
133
|
...(turnBinding ? { turnBinding: true } : {}),
|
|
124
134
|
...(options.getFormat === undefined ? {} : { getFormat: options.getFormat }),
|
|
@@ -136,7 +146,8 @@ export function createPublisherAds(options) {
|
|
|
136
146
|
}).catch(() => {});
|
|
137
147
|
|
|
138
148
|
async function connectGeneration({ request, consume, signal }) {
|
|
139
|
-
const job = { id: crypto.randomUUID(), sessionId: binding.sessionId, context, state: "pending", cancelled: false
|
|
149
|
+
const job = { id: crypto.randomUUID(), sessionId: binding.sessionId, context, state: "pending", cancelled: false,
|
|
150
|
+
presented: false, consumed: false };
|
|
140
151
|
if (active) event(active, "abort");
|
|
141
152
|
active = job;
|
|
142
153
|
let reader = null, ended = false, buffer = "";
|
|
@@ -195,7 +206,8 @@ export function createPublisherAds(options) {
|
|
|
195
206
|
}
|
|
196
207
|
if (["done", "error", "abort"].includes(record.type)) {
|
|
197
208
|
ended = true;
|
|
198
|
-
if (record.type
|
|
209
|
+
if (record.type === "done" && [204, 205, 304].includes(metadata.status)) event(job, "no_result");
|
|
210
|
+
else if (record.type !== "done" || timing !== "after") event(job, record.type);
|
|
199
211
|
if (record.type === "done" || !metadata.status.toString().startsWith("2")) controller.close();
|
|
200
212
|
else controller.error(new Error("generation_" + record.type));
|
|
201
213
|
return;
|
|
@@ -210,14 +222,20 @@ export function createPublisherAds(options) {
|
|
|
210
222
|
const record = await nextRecord();
|
|
211
223
|
if (!["done", "error", "abort"].includes(record.type)) throw new Error("generation_transport_invalid");
|
|
212
224
|
ended = true;
|
|
213
|
-
if (record.type
|
|
225
|
+
if (record.type === "done") event(job, "no_result");
|
|
226
|
+
else event(job, record.type);
|
|
214
227
|
}
|
|
215
228
|
const noBody = [204, 205, 304].includes(metadata.status);
|
|
216
229
|
const primary = new Response(noBody ? null : output, {
|
|
217
230
|
status: metadata.status, statusText: metadata.status_text || "", headers: metadata.headers
|
|
218
231
|
});
|
|
219
|
-
const result = await consume(primary, { onDelta: () =>
|
|
220
|
-
|
|
232
|
+
const result = await consume(primary, { onDelta: () => {
|
|
233
|
+
event(job, "progress");
|
|
234
|
+
if (timing === "before" || (timing === "during" && options.jobType === "image")) event(job, "presented");
|
|
235
|
+
}, onPresented: () => event(job, "presented") });
|
|
236
|
+
job.consumed = true;
|
|
237
|
+
if (timing === "before" || (timing === "during" && options.jobType === "image")) event(job, "presented");
|
|
238
|
+
if (timing === "after" && ended && !noBody) event(job, "done");
|
|
221
239
|
return result;
|
|
222
240
|
} catch (error) {
|
|
223
241
|
event(job, signal?.aborted ? "abort" : "error");
|