@xsai/stream-object 0.1.0-beta.7 → 0.1.0-beta.8

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/dist/index.d.ts CHANGED
@@ -2,15 +2,36 @@ import { StreamTextOptions, StreamTextResult } from '@xsai/stream-text';
2
2
  import { PartialDeep } from 'type-fest';
3
3
  import { Schema, Infer } from 'xsschema';
4
4
 
5
+ interface StreamObjectOnFinishResult<T extends Schema> {
6
+ object?: Infer<T>;
7
+ }
5
8
  interface StreamObjectOptions<T extends Schema> extends StreamTextOptions {
6
9
  schema: T;
7
10
  schemaDescription?: string;
8
11
  schemaName?: string;
9
12
  }
10
13
  interface StreamObjectResult<T extends Schema> extends StreamTextResult {
11
- partialObjectStream: ReadableStream<PartialDeep<Infer<T>>>;
14
+ elementStream?: ReadableStream<Infer<T>>;
15
+ partialObjectStream?: ReadableStream<PartialDeep<Infer<T>>>;
16
+ }
17
+ interface StreamObjectExtraOptions<T extends Schema> {
18
+ onFinish?: (result: StreamObjectOnFinishResult<T>) => unknown;
12
19
  }
13
- /** @experimental WIP */
14
- declare const streamObject: <T extends Schema>(options: StreamObjectOptions<T>) => Promise<StreamObjectResult<T>>;
20
+ declare function streamObject<T extends Schema>(options: StreamObjectExtraOptions<T> & StreamObjectOptions<T> & {
21
+ output: 'array';
22
+ }): Promise<StreamObjectResult<T> & {
23
+ elementStream: ReadableStream<Infer<T>>;
24
+ partialObjectStream: undefined;
25
+ }>;
26
+ declare function streamObject<T extends Schema>(options: StreamObjectExtraOptions<T> & StreamObjectOptions<T> & {
27
+ output: 'object';
28
+ }): Promise<StreamObjectResult<T> & {
29
+ elementStream: undefined;
30
+ partialObjectStream: ReadableStream<PartialDeep<Infer<T>>>;
31
+ }>;
32
+ declare function streamObject<T extends Schema>(options: StreamObjectExtraOptions<T> & StreamObjectOptions<T>): Promise<StreamObjectResult<T> & {
33
+ elementStream: undefined;
34
+ partialObjectStream: ReadableStream<PartialDeep<Infer<T>>>;
35
+ }>;
15
36
 
16
- export { type StreamObjectOptions, type StreamObjectResult, streamObject };
37
+ export { type StreamObjectOnFinishResult, type StreamObjectOptions, type StreamObjectResult, streamObject };
package/dist/index.js CHANGED
@@ -251,44 +251,90 @@ var require_parse = __commonJS({
251
251
  var import_best_effort_json_parser = __toESM(require_parse(), 1);
252
252
  import { streamText } from "@xsai/stream-text";
253
253
  import { toJSONSchema } from "xsschema";
254
- var streamObject = async (options) => streamText({
255
- ...options,
256
- response_format: {
257
- json_schema: {
258
- description: options.schemaDescription,
259
- name: options.schemaName ?? "json_schema",
260
- schema: await toJSONSchema(options.schema),
261
- strict: true
254
+ var wrap = (schema) => {
255
+ return {
256
+ properties: {
257
+ elements: {
258
+ items: schema,
259
+ type: "array"
260
+ }
262
261
  },
263
- type: "json_schema"
264
- },
265
- schema: void 0,
266
- schemaDescription: void 0,
267
- schemaName: void 0
268
- }).then(({ chunkStream, stepStream, textStream: rawTextStream }) => {
269
- const [textStream, rawPartialObjectStream] = rawTextStream.tee();
270
- let partialObjectData = "";
271
- let partialObjectSnapshot = {};
272
- const partialObjectStream = rawPartialObjectStream.pipeThrough(new TransformStream({
273
- transform: (chunk, controller) => {
274
- partialObjectData += chunk;
275
- try {
276
- const data = (0, import_best_effort_json_parser.parse)(partialObjectData);
277
- if (JSON.stringify(partialObjectSnapshot) !== JSON.stringify(data)) {
278
- partialObjectSnapshot = data;
279
- controller.enqueue(data);
262
+ required: ["elements"],
263
+ type: "object"
264
+ };
265
+ };
266
+ async function streamObject(options) {
267
+ const { schema: schemaValidator } = options;
268
+ let schema = await toJSONSchema(schemaValidator);
269
+ if (options.output === "array")
270
+ schema = wrap(schema);
271
+ return streamText({
272
+ ...options,
273
+ response_format: {
274
+ json_schema: {
275
+ description: options.schemaDescription,
276
+ name: options.schemaName ?? "json_schema",
277
+ schema,
278
+ strict: true
279
+ },
280
+ type: "json_schema"
281
+ },
282
+ schema: void 0,
283
+ schemaDescription: void 0,
284
+ schemaName: void 0
285
+ }).then(({ chunkStream, stepStream, textStream }) => {
286
+ let elementStream;
287
+ let partialObjectStream;
288
+ let index = 0;
289
+ if (options.output === "array") {
290
+ let rawElementStream;
291
+ [rawElementStream, textStream] = textStream.tee();
292
+ let partialData = "";
293
+ elementStream = rawElementStream.pipeThrough(new TransformStream({
294
+ flush: (controller) => {
295
+ const data = (0, import_best_effort_json_parser.parse)(partialData);
296
+ controller.enqueue(data.elements.at(-1));
297
+ options.onFinish?.({ object: data.elements });
298
+ },
299
+ transform: (chunk, controller) => {
300
+ partialData += chunk;
301
+ try {
302
+ const data = (0, import_best_effort_json_parser.parse)(partialData);
303
+ if (Array.isArray(Object.getOwnPropertyDescriptor(data, "elements")?.value) && data.elements.length > index + 1) {
304
+ controller.enqueue(data.elements[index++]);
305
+ }
306
+ } catch {
307
+ }
280
308
  }
281
- } catch {
282
- }
309
+ }));
310
+ } else {
311
+ let rawPartialObjectStream;
312
+ [textStream, rawPartialObjectStream] = textStream.tee();
313
+ let partialObjectData = "";
314
+ let partialObjectSnapshot = {};
315
+ partialObjectStream = rawPartialObjectStream.pipeThrough(new TransformStream({
316
+ transform: (chunk, controller) => {
317
+ partialObjectData += chunk;
318
+ try {
319
+ const data = (0, import_best_effort_json_parser.parse)(partialObjectData);
320
+ if (JSON.stringify(partialObjectSnapshot) !== JSON.stringify(data)) {
321
+ partialObjectSnapshot = data;
322
+ controller.enqueue(data);
323
+ }
324
+ } catch {
325
+ }
326
+ }
327
+ }));
283
328
  }
284
- }));
285
- return {
286
- chunkStream,
287
- partialObjectStream,
288
- stepStream,
289
- textStream
290
- };
291
- });
329
+ return {
330
+ chunkStream,
331
+ elementStream,
332
+ partialObjectStream,
333
+ stepStream,
334
+ textStream
335
+ };
336
+ });
337
+ }
292
338
  export {
293
339
  streamObject
294
340
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@xsai/stream-object",
3
3
  "type": "module",
4
- "version": "0.1.0-beta.7",
4
+ "version": "0.1.0-beta.8",
5
5
  "description": "extra-small AI SDK for Browser, Node.js, Deno, Bun or Edge Runtime.",
6
6
  "author": "Moeru AI",
7
7
  "license": "MIT",