@bagelink/sdk 1.8.39 → 1.8.43

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.cjs CHANGED
@@ -1162,10 +1162,8 @@ function generateTypes(schemas) {
1162
1162
  class StreamController {
1163
1163
  constructor(cleanup) {
1164
1164
  this.cleanup = cleanup;
1165
- this.controller = new AbortController();
1166
1165
  }
1167
1166
  handlers = /* @__PURE__ */ new Map();
1168
- controller;
1169
1167
  _closed = false;
1170
1168
  /**
1171
1169
  * Register an event handler (fully typed!)
@@ -1180,40 +1178,6 @@ class StreamController {
1180
1178
  this.handlers.get(event).add(handler);
1181
1179
  return this;
1182
1180
  }
1183
- /**
1184
- * Register a one-time event handler (fully typed!)
1185
- * @param event - Event type to listen for
1186
- * @param handler - Handler function (called once then removed)
1187
- * @returns this (for chaining)
1188
- */
1189
- once(event, handler) {
1190
- const wrappedHandler = (data) => {
1191
- handler(data);
1192
- this.off(event, wrappedHandler);
1193
- };
1194
- return this.on(event, wrappedHandler);
1195
- }
1196
- /**
1197
- * Remove an event handler (fully typed!)
1198
- * @param event - Event type
1199
- * @param handler - Handler to remove
1200
- * @returns this (for chaining)
1201
- */
1202
- off(event, handler) {
1203
- this.handlers.get(event)?.delete(handler);
1204
- return this;
1205
- }
1206
- /**
1207
- * Remove all handlers for an event (or all events if no event specified)
1208
- */
1209
- removeAllListeners(event) {
1210
- if (event === void 0) {
1211
- this.handlers.clear();
1212
- } else {
1213
- this.handlers.delete(event);
1214
- }
1215
- return this;
1216
- }
1217
1181
  /**
1218
1182
  * Emit an event to all registered handlers
1219
1183
  * @internal
@@ -1235,17 +1199,10 @@ class StreamController {
1235
1199
  */
1236
1200
  close() {
1237
1201
  if (!this._closed) {
1238
- this.controller.abort();
1239
1202
  this.cleanup();
1240
1203
  this._closed = true;
1241
1204
  }
1242
1205
  }
1243
- /**
1244
- * Check if stream is closed
1245
- */
1246
- get closed() {
1247
- return this._closed;
1248
- }
1249
1206
  }
1250
1207
 
1251
1208
  function createSSEStream(url, options = {}) {
@@ -1257,11 +1214,14 @@ function createSSEStream(url, options = {}) {
1257
1214
  fetch(url, {
1258
1215
  method: "GET",
1259
1216
  headers: {
1260
- Accept: "text/event-stream",
1217
+ "Accept": "text/event-stream",
1218
+ "Cache-Control": "no-cache",
1261
1219
  ...headers
1262
1220
  },
1263
1221
  credentials: withCredentials ? "include" : "same-origin",
1264
- signal: controller.signal
1222
+ signal: controller.signal,
1223
+ // Disable keepalive for streaming
1224
+ keepalive: false
1265
1225
  }).then(async (response) => {
1266
1226
  if (!response.ok) {
1267
1227
  throw new Error(`HTTP ${response.status}: ${response.statusText}`);
@@ -1276,35 +1236,47 @@ function createSSEStream(url, options = {}) {
1276
1236
  while (true) {
1277
1237
  const { done, value } = await reader.read();
1278
1238
  if (done) {
1239
+ stream.emit("done", {});
1279
1240
  stream.emit("complete", {});
1280
1241
  break;
1281
1242
  }
1282
1243
  buffer += decoder.decode(value, { stream: true });
1283
1244
  const lines = buffer.split("\n");
1284
1245
  buffer = lines.pop() || "";
1285
- let eventData = "";
1246
+ let currentEvent = "message";
1247
+ let currentData = "";
1286
1248
  for (const line of lines) {
1287
- if (line.startsWith("data:")) {
1288
- eventData = line.slice(5).trim();
1289
- } else if (line === "" && eventData) {
1249
+ if (line.startsWith("event:")) {
1250
+ currentEvent = line.slice(6).trim();
1251
+ } else if (line.startsWith("data:")) {
1252
+ currentData = line.slice(5).trim();
1253
+ } else if (line === "" && currentData) {
1290
1254
  try {
1291
- const data = JSON.parse(eventData);
1292
- stream.emit(data.type || "message", data);
1293
- } catch (error) {
1294
- console.error("Failed to parse SSE event:", error);
1255
+ const parsed = JSON.parse(currentData);
1256
+ stream.emit(currentEvent, parsed);
1257
+ } catch {
1258
+ stream.emit(currentEvent, currentData);
1295
1259
  }
1296
- eventData = "";
1260
+ currentEvent = "message";
1261
+ currentData = "";
1297
1262
  }
1298
1263
  }
1299
1264
  }
1300
1265
  } catch (error) {
1301
- if (error instanceof Error && error.name !== "AbortError") {
1302
- stream.emit("error", error);
1266
+ if (error?.name !== "AbortError") {
1267
+ const errorMessage = error?.message || "Stream connection error";
1268
+ stream.emit("error", new Error(errorMessage));
1269
+ }
1270
+ } finally {
1271
+ try {
1272
+ reader.releaseLock();
1273
+ } catch {
1303
1274
  }
1304
1275
  }
1305
1276
  }).catch((error) => {
1306
- if (error.name !== "AbortError") {
1307
- stream.emit("error", error);
1277
+ if (error?.name !== "AbortError") {
1278
+ const errorMessage = error?.message || "Failed to establish stream connection";
1279
+ stream.emit("error", new Error(errorMessage));
1308
1280
  }
1309
1281
  });
1310
1282
  return stream;
@@ -1320,11 +1292,14 @@ function createSSEStreamPost(url, body, options = {}) {
1320
1292
  headers: {
1321
1293
  "Accept": "text/event-stream",
1322
1294
  "Content-Type": "application/json",
1295
+ "Cache-Control": "no-cache",
1323
1296
  ...headers
1324
1297
  },
1325
1298
  credentials: withCredentials ? "include" : "same-origin",
1326
1299
  body: JSON.stringify(body),
1327
- signal: controller.signal
1300
+ signal: controller.signal,
1301
+ // Disable keepalive for streaming
1302
+ keepalive: false
1328
1303
  }).then(async (response) => {
1329
1304
  if (!response.ok) {
1330
1305
  throw new Error(`HTTP ${response.status}: ${response.statusText}`);
@@ -1339,35 +1314,47 @@ function createSSEStreamPost(url, body, options = {}) {
1339
1314
  while (true) {
1340
1315
  const { done, value } = await reader.read();
1341
1316
  if (done) {
1317
+ stream.emit("done", {});
1342
1318
  stream.emit("complete", {});
1343
1319
  break;
1344
1320
  }
1345
1321
  buffer += decoder.decode(value, { stream: true });
1346
1322
  const lines = buffer.split("\n");
1347
1323
  buffer = lines.pop() || "";
1348
- let eventData = "";
1324
+ let currentEvent = "message";
1325
+ let currentData = "";
1349
1326
  for (const line of lines) {
1350
- if (line.startsWith("data:")) {
1351
- eventData = line.slice(5).trim();
1352
- } else if (line === "" && eventData) {
1327
+ if (line.startsWith("event:")) {
1328
+ currentEvent = line.slice(6).trim();
1329
+ } else if (line.startsWith("data:")) {
1330
+ currentData = line.slice(5).trim();
1331
+ } else if (line === "" && currentData) {
1353
1332
  try {
1354
- const data = JSON.parse(eventData);
1355
- stream.emit(data.type || "message", data);
1356
- } catch (error) {
1357
- console.error("Failed to parse SSE event:", error);
1333
+ const parsed = JSON.parse(currentData);
1334
+ stream.emit(currentEvent, parsed);
1335
+ } catch {
1336
+ stream.emit(currentEvent, currentData);
1358
1337
  }
1359
- eventData = "";
1338
+ currentEvent = "message";
1339
+ currentData = "";
1360
1340
  }
1361
1341
  }
1362
1342
  }
1363
1343
  } catch (error) {
1364
- if (error instanceof Error && error.name !== "AbortError") {
1365
- stream.emit("error", error);
1344
+ if (error?.name !== "AbortError") {
1345
+ const errorMessage = error?.message || "Stream connection error";
1346
+ stream.emit("error", new Error(errorMessage));
1347
+ }
1348
+ } finally {
1349
+ try {
1350
+ reader.releaseLock();
1351
+ } catch {
1366
1352
  }
1367
1353
  }
1368
1354
  }).catch((error) => {
1369
- if (error.name !== "AbortError") {
1370
- stream.emit("error", error);
1355
+ if (error?.name !== "AbortError") {
1356
+ const errorMessage = error?.message || "Failed to establish stream connection";
1357
+ stream.emit("error", new Error(errorMessage));
1371
1358
  }
1372
1359
  });
1373
1360
  return stream;
package/dist/index.d.cts CHANGED
@@ -5,14 +5,6 @@ import { Ref } from 'vue';
5
5
  * StreamController - Simple, reliable SSE stream management
6
6
  * Provides a type-safe API for consuming Server-Sent Events
7
7
  */
8
- interface SSEEvent<T = any> {
9
- /** Event type (e.g., "token", "tool_call", "done") */
10
- type: string;
11
- /** Event data payload */
12
- data: T;
13
- /** Raw event string */
14
- raw?: string;
15
- }
16
8
  type EventHandler<T = any> = (data: T) => void;
17
9
  /**
18
10
  * Type-safe event map for stream events
@@ -33,7 +25,6 @@ type StreamEventMap = Record<string, any>;
33
25
  declare class StreamController<TEventMap extends StreamEventMap = StreamEventMap> {
34
26
  private cleanup;
35
27
  private handlers;
36
- private controller;
37
28
  private _closed;
38
29
  constructor(cleanup: () => void);
39
30
  /**
@@ -42,25 +33,7 @@ declare class StreamController<TEventMap extends StreamEventMap = StreamEventMap
42
33
  * @param handler - Handler function (data type inferred from event)
43
34
  * @returns this (for chaining)
44
35
  */
45
- on<K extends keyof TEventMap | 'error' | 'complete'>(event: K, handler: K extends 'error' ? (error: Error) => void : K extends 'complete' ? () => void : K extends keyof TEventMap ? (data: TEventMap[K]) => void : EventHandler): this;
46
- /**
47
- * Register a one-time event handler (fully typed!)
48
- * @param event - Event type to listen for
49
- * @param handler - Handler function (called once then removed)
50
- * @returns this (for chaining)
51
- */
52
- once<K extends keyof TEventMap | 'error' | 'complete'>(event: K, handler: K extends 'error' ? (error: Error) => void : K extends 'complete' ? () => void : K extends keyof TEventMap ? (data: TEventMap[K]) => void : EventHandler): this;
53
- /**
54
- * Remove an event handler (fully typed!)
55
- * @param event - Event type
56
- * @param handler - Handler to remove
57
- * @returns this (for chaining)
58
- */
59
- off<K extends keyof TEventMap | 'error' | 'complete'>(event: K, handler: K extends 'error' ? (error: Error) => void : K extends 'complete' ? () => void : K extends keyof TEventMap ? (data: TEventMap[K]) => void : EventHandler): this;
60
- /**
61
- * Remove all handlers for an event (or all events if no event specified)
62
- */
63
- removeAllListeners(event?: keyof TEventMap | 'error' | 'complete'): this;
36
+ on<K extends keyof TEventMap | 'error' | 'complete' | 'done'>(event: K, handler: K extends 'error' ? (error: Error) => void : K extends 'complete' | 'done' ? (data?: any) => void : K extends keyof TEventMap ? (data: TEventMap[K]) => void : EventHandler): this;
64
37
  /**
65
38
  * Emit an event to all registered handlers
66
39
  * @internal
@@ -70,10 +43,6 @@ declare class StreamController<TEventMap extends StreamEventMap = StreamEventMap
70
43
  * Close the stream
71
44
  */
72
45
  close(): void;
73
- /**
74
- * Check if stream is closed
75
- */
76
- get closed(): boolean;
77
46
  }
78
47
 
79
48
  /**
@@ -799,4 +768,4 @@ declare class Bagel {
799
768
  }
800
769
 
801
770
  export { ApiResponse, Bagel, StreamController, createSSEStream, createSSEStreamPost, dereference, extractSSEEventInfo, extractSSEEventTypes, formatAPIErrorMessage, formatFieldErrors, getPath, isReferenceObject, isSSEStream, isSchemaObject, _default as openAPI, parseApiError, unwrap, useApiRequest, useCancellableRequest, wrapApiForDirectReturn };
802
- export type { ApiConfig, ApiRequestState, BaseParameterObject, CallbackObject, CallbacksObject, ComponentsObject, ContactObject, ContentObject, DiscriminatorObject, EncodingObject, EncodingPropertyObject, ExampleObject, ExamplesObject, ExternalDocumentationObject, FastAPIErrorResponse, FastAPIValidationError, HeaderObject, HeadersObject, InfoObject, LicenseObject, LinkObject, LinkParametersObject, LinksObject, MediaTypeObject, OAuthFlowObject, OAuthFlowsObject, OpenAPIObject, OperationObject, ParameterLocation, ParameterObject, ParameterStyle, ParsedError, PathItemObject, PathsObject, ReferenceObject, RequestBodyObject, RequestInterceptor, ResponseInterceptor, ResponseMetadata, ResponseObject, ResponsesObject, SSEEvent, SSEEventTypeInfo, SSEStreamOptions, SchemaObject, SchemaObjectType, SchemasObject, ScopesObject, SecurityRequirementObject, SecuritySchemeObject, SecuritySchemeType, ServerObject, ServerVariableObject, StreamEventMap, TableToTypeMapping, Tables, TagObject, TypeFormatT, Unwrap, Unwrapped, UploadOptions, User, XmlObject };
771
+ export type { ApiConfig, ApiRequestState, BaseParameterObject, CallbackObject, CallbacksObject, ComponentsObject, ContactObject, ContentObject, DiscriminatorObject, EncodingObject, EncodingPropertyObject, ExampleObject, ExamplesObject, ExternalDocumentationObject, FastAPIErrorResponse, FastAPIValidationError, HeaderObject, HeadersObject, InfoObject, LicenseObject, LinkObject, LinkParametersObject, LinksObject, MediaTypeObject, OAuthFlowObject, OAuthFlowsObject, OpenAPIObject, OperationObject, ParameterLocation, ParameterObject, ParameterStyle, ParsedError, PathItemObject, PathsObject, ReferenceObject, RequestBodyObject, RequestInterceptor, ResponseInterceptor, ResponseMetadata, ResponseObject, ResponsesObject, SSEEventTypeInfo, SSEStreamOptions, SchemaObject, SchemaObjectType, SchemasObject, ScopesObject, SecurityRequirementObject, SecuritySchemeObject, SecuritySchemeType, ServerObject, ServerVariableObject, StreamEventMap, TableToTypeMapping, Tables, TagObject, TypeFormatT, Unwrap, Unwrapped, UploadOptions, User, XmlObject };
package/dist/index.d.mts CHANGED
@@ -5,14 +5,6 @@ import { Ref } from 'vue';
5
5
  * StreamController - Simple, reliable SSE stream management
6
6
  * Provides a type-safe API for consuming Server-Sent Events
7
7
  */
8
- interface SSEEvent<T = any> {
9
- /** Event type (e.g., "token", "tool_call", "done") */
10
- type: string;
11
- /** Event data payload */
12
- data: T;
13
- /** Raw event string */
14
- raw?: string;
15
- }
16
8
  type EventHandler<T = any> = (data: T) => void;
17
9
  /**
18
10
  * Type-safe event map for stream events
@@ -33,7 +25,6 @@ type StreamEventMap = Record<string, any>;
33
25
  declare class StreamController<TEventMap extends StreamEventMap = StreamEventMap> {
34
26
  private cleanup;
35
27
  private handlers;
36
- private controller;
37
28
  private _closed;
38
29
  constructor(cleanup: () => void);
39
30
  /**
@@ -42,25 +33,7 @@ declare class StreamController<TEventMap extends StreamEventMap = StreamEventMap
42
33
  * @param handler - Handler function (data type inferred from event)
43
34
  * @returns this (for chaining)
44
35
  */
45
- on<K extends keyof TEventMap | 'error' | 'complete'>(event: K, handler: K extends 'error' ? (error: Error) => void : K extends 'complete' ? () => void : K extends keyof TEventMap ? (data: TEventMap[K]) => void : EventHandler): this;
46
- /**
47
- * Register a one-time event handler (fully typed!)
48
- * @param event - Event type to listen for
49
- * @param handler - Handler function (called once then removed)
50
- * @returns this (for chaining)
51
- */
52
- once<K extends keyof TEventMap | 'error' | 'complete'>(event: K, handler: K extends 'error' ? (error: Error) => void : K extends 'complete' ? () => void : K extends keyof TEventMap ? (data: TEventMap[K]) => void : EventHandler): this;
53
- /**
54
- * Remove an event handler (fully typed!)
55
- * @param event - Event type
56
- * @param handler - Handler to remove
57
- * @returns this (for chaining)
58
- */
59
- off<K extends keyof TEventMap | 'error' | 'complete'>(event: K, handler: K extends 'error' ? (error: Error) => void : K extends 'complete' ? () => void : K extends keyof TEventMap ? (data: TEventMap[K]) => void : EventHandler): this;
60
- /**
61
- * Remove all handlers for an event (or all events if no event specified)
62
- */
63
- removeAllListeners(event?: keyof TEventMap | 'error' | 'complete'): this;
36
+ on<K extends keyof TEventMap | 'error' | 'complete' | 'done'>(event: K, handler: K extends 'error' ? (error: Error) => void : K extends 'complete' | 'done' ? (data?: any) => void : K extends keyof TEventMap ? (data: TEventMap[K]) => void : EventHandler): this;
64
37
  /**
65
38
  * Emit an event to all registered handlers
66
39
  * @internal
@@ -70,10 +43,6 @@ declare class StreamController<TEventMap extends StreamEventMap = StreamEventMap
70
43
  * Close the stream
71
44
  */
72
45
  close(): void;
73
- /**
74
- * Check if stream is closed
75
- */
76
- get closed(): boolean;
77
46
  }
78
47
 
79
48
  /**
@@ -799,4 +768,4 @@ declare class Bagel {
799
768
  }
800
769
 
801
770
  export { ApiResponse, Bagel, StreamController, createSSEStream, createSSEStreamPost, dereference, extractSSEEventInfo, extractSSEEventTypes, formatAPIErrorMessage, formatFieldErrors, getPath, isReferenceObject, isSSEStream, isSchemaObject, _default as openAPI, parseApiError, unwrap, useApiRequest, useCancellableRequest, wrapApiForDirectReturn };
802
- export type { ApiConfig, ApiRequestState, BaseParameterObject, CallbackObject, CallbacksObject, ComponentsObject, ContactObject, ContentObject, DiscriminatorObject, EncodingObject, EncodingPropertyObject, ExampleObject, ExamplesObject, ExternalDocumentationObject, FastAPIErrorResponse, FastAPIValidationError, HeaderObject, HeadersObject, InfoObject, LicenseObject, LinkObject, LinkParametersObject, LinksObject, MediaTypeObject, OAuthFlowObject, OAuthFlowsObject, OpenAPIObject, OperationObject, ParameterLocation, ParameterObject, ParameterStyle, ParsedError, PathItemObject, PathsObject, ReferenceObject, RequestBodyObject, RequestInterceptor, ResponseInterceptor, ResponseMetadata, ResponseObject, ResponsesObject, SSEEvent, SSEEventTypeInfo, SSEStreamOptions, SchemaObject, SchemaObjectType, SchemasObject, ScopesObject, SecurityRequirementObject, SecuritySchemeObject, SecuritySchemeType, ServerObject, ServerVariableObject, StreamEventMap, TableToTypeMapping, Tables, TagObject, TypeFormatT, Unwrap, Unwrapped, UploadOptions, User, XmlObject };
771
+ export type { ApiConfig, ApiRequestState, BaseParameterObject, CallbackObject, CallbacksObject, ComponentsObject, ContactObject, ContentObject, DiscriminatorObject, EncodingObject, EncodingPropertyObject, ExampleObject, ExamplesObject, ExternalDocumentationObject, FastAPIErrorResponse, FastAPIValidationError, HeaderObject, HeadersObject, InfoObject, LicenseObject, LinkObject, LinkParametersObject, LinksObject, MediaTypeObject, OAuthFlowObject, OAuthFlowsObject, OpenAPIObject, OperationObject, ParameterLocation, ParameterObject, ParameterStyle, ParsedError, PathItemObject, PathsObject, ReferenceObject, RequestBodyObject, RequestInterceptor, ResponseInterceptor, ResponseMetadata, ResponseObject, ResponsesObject, SSEEventTypeInfo, SSEStreamOptions, SchemaObject, SchemaObjectType, SchemasObject, ScopesObject, SecurityRequirementObject, SecuritySchemeObject, SecuritySchemeType, ServerObject, ServerVariableObject, StreamEventMap, TableToTypeMapping, Tables, TagObject, TypeFormatT, Unwrap, Unwrapped, UploadOptions, User, XmlObject };
package/dist/index.d.ts CHANGED
@@ -5,14 +5,6 @@ import { Ref } from 'vue';
5
5
  * StreamController - Simple, reliable SSE stream management
6
6
  * Provides a type-safe API for consuming Server-Sent Events
7
7
  */
8
- interface SSEEvent<T = any> {
9
- /** Event type (e.g., "token", "tool_call", "done") */
10
- type: string;
11
- /** Event data payload */
12
- data: T;
13
- /** Raw event string */
14
- raw?: string;
15
- }
16
8
  type EventHandler<T = any> = (data: T) => void;
17
9
  /**
18
10
  * Type-safe event map for stream events
@@ -33,7 +25,6 @@ type StreamEventMap = Record<string, any>;
33
25
  declare class StreamController<TEventMap extends StreamEventMap = StreamEventMap> {
34
26
  private cleanup;
35
27
  private handlers;
36
- private controller;
37
28
  private _closed;
38
29
  constructor(cleanup: () => void);
39
30
  /**
@@ -42,25 +33,7 @@ declare class StreamController<TEventMap extends StreamEventMap = StreamEventMap
42
33
  * @param handler - Handler function (data type inferred from event)
43
34
  * @returns this (for chaining)
44
35
  */
45
- on<K extends keyof TEventMap | 'error' | 'complete'>(event: K, handler: K extends 'error' ? (error: Error) => void : K extends 'complete' ? () => void : K extends keyof TEventMap ? (data: TEventMap[K]) => void : EventHandler): this;
46
- /**
47
- * Register a one-time event handler (fully typed!)
48
- * @param event - Event type to listen for
49
- * @param handler - Handler function (called once then removed)
50
- * @returns this (for chaining)
51
- */
52
- once<K extends keyof TEventMap | 'error' | 'complete'>(event: K, handler: K extends 'error' ? (error: Error) => void : K extends 'complete' ? () => void : K extends keyof TEventMap ? (data: TEventMap[K]) => void : EventHandler): this;
53
- /**
54
- * Remove an event handler (fully typed!)
55
- * @param event - Event type
56
- * @param handler - Handler to remove
57
- * @returns this (for chaining)
58
- */
59
- off<K extends keyof TEventMap | 'error' | 'complete'>(event: K, handler: K extends 'error' ? (error: Error) => void : K extends 'complete' ? () => void : K extends keyof TEventMap ? (data: TEventMap[K]) => void : EventHandler): this;
60
- /**
61
- * Remove all handlers for an event (or all events if no event specified)
62
- */
63
- removeAllListeners(event?: keyof TEventMap | 'error' | 'complete'): this;
36
+ on<K extends keyof TEventMap | 'error' | 'complete' | 'done'>(event: K, handler: K extends 'error' ? (error: Error) => void : K extends 'complete' | 'done' ? (data?: any) => void : K extends keyof TEventMap ? (data: TEventMap[K]) => void : EventHandler): this;
64
37
  /**
65
38
  * Emit an event to all registered handlers
66
39
  * @internal
@@ -70,10 +43,6 @@ declare class StreamController<TEventMap extends StreamEventMap = StreamEventMap
70
43
  * Close the stream
71
44
  */
72
45
  close(): void;
73
- /**
74
- * Check if stream is closed
75
- */
76
- get closed(): boolean;
77
46
  }
78
47
 
79
48
  /**
@@ -799,4 +768,4 @@ declare class Bagel {
799
768
  }
800
769
 
801
770
  export { ApiResponse, Bagel, StreamController, createSSEStream, createSSEStreamPost, dereference, extractSSEEventInfo, extractSSEEventTypes, formatAPIErrorMessage, formatFieldErrors, getPath, isReferenceObject, isSSEStream, isSchemaObject, _default as openAPI, parseApiError, unwrap, useApiRequest, useCancellableRequest, wrapApiForDirectReturn };
802
- export type { ApiConfig, ApiRequestState, BaseParameterObject, CallbackObject, CallbacksObject, ComponentsObject, ContactObject, ContentObject, DiscriminatorObject, EncodingObject, EncodingPropertyObject, ExampleObject, ExamplesObject, ExternalDocumentationObject, FastAPIErrorResponse, FastAPIValidationError, HeaderObject, HeadersObject, InfoObject, LicenseObject, LinkObject, LinkParametersObject, LinksObject, MediaTypeObject, OAuthFlowObject, OAuthFlowsObject, OpenAPIObject, OperationObject, ParameterLocation, ParameterObject, ParameterStyle, ParsedError, PathItemObject, PathsObject, ReferenceObject, RequestBodyObject, RequestInterceptor, ResponseInterceptor, ResponseMetadata, ResponseObject, ResponsesObject, SSEEvent, SSEEventTypeInfo, SSEStreamOptions, SchemaObject, SchemaObjectType, SchemasObject, ScopesObject, SecurityRequirementObject, SecuritySchemeObject, SecuritySchemeType, ServerObject, ServerVariableObject, StreamEventMap, TableToTypeMapping, Tables, TagObject, TypeFormatT, Unwrap, Unwrapped, UploadOptions, User, XmlObject };
771
+ export type { ApiConfig, ApiRequestState, BaseParameterObject, CallbackObject, CallbacksObject, ComponentsObject, ContactObject, ContentObject, DiscriminatorObject, EncodingObject, EncodingPropertyObject, ExampleObject, ExamplesObject, ExternalDocumentationObject, FastAPIErrorResponse, FastAPIValidationError, HeaderObject, HeadersObject, InfoObject, LicenseObject, LinkObject, LinkParametersObject, LinksObject, MediaTypeObject, OAuthFlowObject, OAuthFlowsObject, OpenAPIObject, OperationObject, ParameterLocation, ParameterObject, ParameterStyle, ParsedError, PathItemObject, PathsObject, ReferenceObject, RequestBodyObject, RequestInterceptor, ResponseInterceptor, ResponseMetadata, ResponseObject, ResponsesObject, SSEEventTypeInfo, SSEStreamOptions, SchemaObject, SchemaObjectType, SchemasObject, ScopesObject, SecurityRequirementObject, SecuritySchemeObject, SecuritySchemeType, ServerObject, ServerVariableObject, StreamEventMap, TableToTypeMapping, Tables, TagObject, TypeFormatT, Unwrap, Unwrapped, UploadOptions, User, XmlObject };
package/dist/index.mjs CHANGED
@@ -1156,10 +1156,8 @@ function generateTypes(schemas) {
1156
1156
  class StreamController {
1157
1157
  constructor(cleanup) {
1158
1158
  this.cleanup = cleanup;
1159
- this.controller = new AbortController();
1160
1159
  }
1161
1160
  handlers = /* @__PURE__ */ new Map();
1162
- controller;
1163
1161
  _closed = false;
1164
1162
  /**
1165
1163
  * Register an event handler (fully typed!)
@@ -1174,40 +1172,6 @@ class StreamController {
1174
1172
  this.handlers.get(event).add(handler);
1175
1173
  return this;
1176
1174
  }
1177
- /**
1178
- * Register a one-time event handler (fully typed!)
1179
- * @param event - Event type to listen for
1180
- * @param handler - Handler function (called once then removed)
1181
- * @returns this (for chaining)
1182
- */
1183
- once(event, handler) {
1184
- const wrappedHandler = (data) => {
1185
- handler(data);
1186
- this.off(event, wrappedHandler);
1187
- };
1188
- return this.on(event, wrappedHandler);
1189
- }
1190
- /**
1191
- * Remove an event handler (fully typed!)
1192
- * @param event - Event type
1193
- * @param handler - Handler to remove
1194
- * @returns this (for chaining)
1195
- */
1196
- off(event, handler) {
1197
- this.handlers.get(event)?.delete(handler);
1198
- return this;
1199
- }
1200
- /**
1201
- * Remove all handlers for an event (or all events if no event specified)
1202
- */
1203
- removeAllListeners(event) {
1204
- if (event === void 0) {
1205
- this.handlers.clear();
1206
- } else {
1207
- this.handlers.delete(event);
1208
- }
1209
- return this;
1210
- }
1211
1175
  /**
1212
1176
  * Emit an event to all registered handlers
1213
1177
  * @internal
@@ -1229,17 +1193,10 @@ class StreamController {
1229
1193
  */
1230
1194
  close() {
1231
1195
  if (!this._closed) {
1232
- this.controller.abort();
1233
1196
  this.cleanup();
1234
1197
  this._closed = true;
1235
1198
  }
1236
1199
  }
1237
- /**
1238
- * Check if stream is closed
1239
- */
1240
- get closed() {
1241
- return this._closed;
1242
- }
1243
1200
  }
1244
1201
 
1245
1202
  function createSSEStream(url, options = {}) {
@@ -1251,11 +1208,14 @@ function createSSEStream(url, options = {}) {
1251
1208
  fetch(url, {
1252
1209
  method: "GET",
1253
1210
  headers: {
1254
- Accept: "text/event-stream",
1211
+ "Accept": "text/event-stream",
1212
+ "Cache-Control": "no-cache",
1255
1213
  ...headers
1256
1214
  },
1257
1215
  credentials: withCredentials ? "include" : "same-origin",
1258
- signal: controller.signal
1216
+ signal: controller.signal,
1217
+ // Disable keepalive for streaming
1218
+ keepalive: false
1259
1219
  }).then(async (response) => {
1260
1220
  if (!response.ok) {
1261
1221
  throw new Error(`HTTP ${response.status}: ${response.statusText}`);
@@ -1270,35 +1230,47 @@ function createSSEStream(url, options = {}) {
1270
1230
  while (true) {
1271
1231
  const { done, value } = await reader.read();
1272
1232
  if (done) {
1233
+ stream.emit("done", {});
1273
1234
  stream.emit("complete", {});
1274
1235
  break;
1275
1236
  }
1276
1237
  buffer += decoder.decode(value, { stream: true });
1277
1238
  const lines = buffer.split("\n");
1278
1239
  buffer = lines.pop() || "";
1279
- let eventData = "";
1240
+ let currentEvent = "message";
1241
+ let currentData = "";
1280
1242
  for (const line of lines) {
1281
- if (line.startsWith("data:")) {
1282
- eventData = line.slice(5).trim();
1283
- } else if (line === "" && eventData) {
1243
+ if (line.startsWith("event:")) {
1244
+ currentEvent = line.slice(6).trim();
1245
+ } else if (line.startsWith("data:")) {
1246
+ currentData = line.slice(5).trim();
1247
+ } else if (line === "" && currentData) {
1284
1248
  try {
1285
- const data = JSON.parse(eventData);
1286
- stream.emit(data.type || "message", data);
1287
- } catch (error) {
1288
- console.error("Failed to parse SSE event:", error);
1249
+ const parsed = JSON.parse(currentData);
1250
+ stream.emit(currentEvent, parsed);
1251
+ } catch {
1252
+ stream.emit(currentEvent, currentData);
1289
1253
  }
1290
- eventData = "";
1254
+ currentEvent = "message";
1255
+ currentData = "";
1291
1256
  }
1292
1257
  }
1293
1258
  }
1294
1259
  } catch (error) {
1295
- if (error instanceof Error && error.name !== "AbortError") {
1296
- stream.emit("error", error);
1260
+ if (error?.name !== "AbortError") {
1261
+ const errorMessage = error?.message || "Stream connection error";
1262
+ stream.emit("error", new Error(errorMessage));
1263
+ }
1264
+ } finally {
1265
+ try {
1266
+ reader.releaseLock();
1267
+ } catch {
1297
1268
  }
1298
1269
  }
1299
1270
  }).catch((error) => {
1300
- if (error.name !== "AbortError") {
1301
- stream.emit("error", error);
1271
+ if (error?.name !== "AbortError") {
1272
+ const errorMessage = error?.message || "Failed to establish stream connection";
1273
+ stream.emit("error", new Error(errorMessage));
1302
1274
  }
1303
1275
  });
1304
1276
  return stream;
@@ -1314,11 +1286,14 @@ function createSSEStreamPost(url, body, options = {}) {
1314
1286
  headers: {
1315
1287
  "Accept": "text/event-stream",
1316
1288
  "Content-Type": "application/json",
1289
+ "Cache-Control": "no-cache",
1317
1290
  ...headers
1318
1291
  },
1319
1292
  credentials: withCredentials ? "include" : "same-origin",
1320
1293
  body: JSON.stringify(body),
1321
- signal: controller.signal
1294
+ signal: controller.signal,
1295
+ // Disable keepalive for streaming
1296
+ keepalive: false
1322
1297
  }).then(async (response) => {
1323
1298
  if (!response.ok) {
1324
1299
  throw new Error(`HTTP ${response.status}: ${response.statusText}`);
@@ -1333,35 +1308,47 @@ function createSSEStreamPost(url, body, options = {}) {
1333
1308
  while (true) {
1334
1309
  const { done, value } = await reader.read();
1335
1310
  if (done) {
1311
+ stream.emit("done", {});
1336
1312
  stream.emit("complete", {});
1337
1313
  break;
1338
1314
  }
1339
1315
  buffer += decoder.decode(value, { stream: true });
1340
1316
  const lines = buffer.split("\n");
1341
1317
  buffer = lines.pop() || "";
1342
- let eventData = "";
1318
+ let currentEvent = "message";
1319
+ let currentData = "";
1343
1320
  for (const line of lines) {
1344
- if (line.startsWith("data:")) {
1345
- eventData = line.slice(5).trim();
1346
- } else if (line === "" && eventData) {
1321
+ if (line.startsWith("event:")) {
1322
+ currentEvent = line.slice(6).trim();
1323
+ } else if (line.startsWith("data:")) {
1324
+ currentData = line.slice(5).trim();
1325
+ } else if (line === "" && currentData) {
1347
1326
  try {
1348
- const data = JSON.parse(eventData);
1349
- stream.emit(data.type || "message", data);
1350
- } catch (error) {
1351
- console.error("Failed to parse SSE event:", error);
1327
+ const parsed = JSON.parse(currentData);
1328
+ stream.emit(currentEvent, parsed);
1329
+ } catch {
1330
+ stream.emit(currentEvent, currentData);
1352
1331
  }
1353
- eventData = "";
1332
+ currentEvent = "message";
1333
+ currentData = "";
1354
1334
  }
1355
1335
  }
1356
1336
  }
1357
1337
  } catch (error) {
1358
- if (error instanceof Error && error.name !== "AbortError") {
1359
- stream.emit("error", error);
1338
+ if (error?.name !== "AbortError") {
1339
+ const errorMessage = error?.message || "Stream connection error";
1340
+ stream.emit("error", new Error(errorMessage));
1341
+ }
1342
+ } finally {
1343
+ try {
1344
+ reader.releaseLock();
1345
+ } catch {
1360
1346
  }
1361
1347
  }
1362
1348
  }).catch((error) => {
1363
- if (error.name !== "AbortError") {
1364
- stream.emit("error", error);
1349
+ if (error?.name !== "AbortError") {
1350
+ const errorMessage = error?.message || "Failed to establish stream connection";
1351
+ stream.emit("error", new Error(errorMessage));
1365
1352
  }
1366
1353
  });
1367
1354
  return stream;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bagelink/sdk",
3
3
  "type": "module",
4
- "version": "1.8.39",
4
+ "version": "1.8.43",
5
5
  "description": "Bagel core sdk packages",
6
6
  "author": {
7
7
  "name": "Bagel Studio",
package/src/index.ts CHANGED
@@ -8,7 +8,6 @@ export { default as openAPI } from './openAPITools'
8
8
  export {
9
9
  createSSEStream,
10
10
  createSSEStreamPost,
11
- type SSEEvent,
12
11
  type SSEStreamOptions,
13
12
  StreamController,
14
13
  type StreamEventMap
@@ -4,15 +4,6 @@
4
4
  * Provides a type-safe API for consuming Server-Sent Events
5
5
  */
6
6
 
7
- export interface SSEEvent<T = any> {
8
- /** Event type (e.g., "token", "tool_call", "done") */
9
- type: string
10
- /** Event data payload */
11
- data: T
12
- /** Raw event string */
13
- raw?: string
14
- }
15
-
16
7
  type EventHandler<T = any> = (data: T) => void
17
8
 
18
9
  /**
@@ -34,12 +25,9 @@ export type StreamEventMap = Record<string, any>
34
25
  */
35
26
  export class StreamController<TEventMap extends StreamEventMap = StreamEventMap> {
36
27
  private handlers = new Map<string, Set<EventHandler>>()
37
- private controller: AbortController
38
28
  private _closed = false
39
29
 
40
- constructor(private cleanup: () => void) {
41
- this.controller = new AbortController()
42
- }
30
+ constructor(private cleanup: () => void) {}
43
31
 
44
32
  /**
45
33
  * Register an event handler (fully typed!)
@@ -47,12 +35,12 @@ export class StreamController<TEventMap extends StreamEventMap = StreamEventMap>
47
35
  * @param handler - Handler function (data type inferred from event)
48
36
  * @returns this (for chaining)
49
37
  */
50
- on<K extends keyof TEventMap | 'error' | 'complete'>(
38
+ on<K extends keyof TEventMap | 'error' | 'complete' | 'done'>(
51
39
  event: K,
52
40
  handler: K extends 'error'
53
41
  ? (error: Error) => void
54
- : K extends 'complete'
55
- ? () => void
42
+ : K extends 'complete' | 'done'
43
+ ? (data?: any) => void
56
44
  : K extends keyof TEventMap
57
45
  ? (data: TEventMap[K]) => void
58
46
  : EventHandler
@@ -64,61 +52,6 @@ export class StreamController<TEventMap extends StreamEventMap = StreamEventMap>
64
52
  return this
65
53
  }
66
54
 
67
- /**
68
- * Register a one-time event handler (fully typed!)
69
- * @param event - Event type to listen for
70
- * @param handler - Handler function (called once then removed)
71
- * @returns this (for chaining)
72
- */
73
- once<K extends keyof TEventMap | 'error' | 'complete'>(
74
- event: K,
75
- handler: K extends 'error'
76
- ? (error: Error) => void
77
- : K extends 'complete'
78
- ? () => void
79
- : K extends keyof TEventMap
80
- ? (data: TEventMap[K]) => void
81
- : EventHandler
82
- ): this {
83
- const wrappedHandler = (data: any) => {
84
- (handler as any)(data)
85
- this.off(event, wrappedHandler as any)
86
- }
87
- return this.on(event, wrappedHandler as any)
88
- }
89
-
90
- /**
91
- * Remove an event handler (fully typed!)
92
- * @param event - Event type
93
- * @param handler - Handler to remove
94
- * @returns this (for chaining)
95
- */
96
- off<K extends keyof TEventMap | 'error' | 'complete'>(
97
- event: K,
98
- handler: K extends 'error'
99
- ? (error: Error) => void
100
- : K extends 'complete'
101
- ? () => void
102
- : K extends keyof TEventMap
103
- ? (data: TEventMap[K]) => void
104
- : EventHandler
105
- ): this {
106
- this.handlers.get(event as string)?.delete(handler as EventHandler)
107
- return this
108
- }
109
-
110
- /**
111
- * Remove all handlers for an event (or all events if no event specified)
112
- */
113
- removeAllListeners(event?: keyof TEventMap | 'error' | 'complete'): this {
114
- if (event === undefined) {
115
- this.handlers.clear()
116
- } else {
117
- this.handlers.delete(event as string)
118
- }
119
- return this
120
- }
121
-
122
55
  /**
123
56
  * Emit an event to all registered handlers
124
57
  * @internal
@@ -141,16 +74,8 @@ export class StreamController<TEventMap extends StreamEventMap = StreamEventMap>
141
74
  */
142
75
  close(): void {
143
76
  if (!this._closed) {
144
- this.controller.abort()
145
77
  this.cleanup()
146
78
  this._closed = true
147
79
  }
148
80
  }
149
-
150
- /**
151
- * Check if stream is closed
152
- */
153
- get closed(): boolean {
154
- return this._closed
155
- }
156
81
  }
@@ -10,7 +10,7 @@
10
10
  import type { StreamEventMap } from './StreamController'
11
11
  import { StreamController } from './StreamController'
12
12
 
13
- export { type SSEEvent, StreamController, type StreamEventMap } from './StreamController'
13
+ export { StreamController, type StreamEventMap } from './StreamController'
14
14
 
15
15
  export interface SSEStreamOptions {
16
16
  /** Additional headers to send with the request */
@@ -49,11 +49,14 @@ export function createSSEStream<TEventMap extends StreamEventMap = StreamEventMa
49
49
  fetch(url, {
50
50
  method: 'GET',
51
51
  headers: {
52
- Accept: 'text/event-stream',
52
+ 'Accept': 'text/event-stream',
53
+ 'Cache-Control': 'no-cache',
53
54
  ...headers,
54
55
  },
55
56
  credentials: withCredentials ? 'include' : 'same-origin',
56
57
  signal: controller.signal,
58
+ // Disable keepalive for streaming
59
+ keepalive: false,
57
60
  })
58
61
  .then(async (response) => {
59
62
  if (!response.ok) {
@@ -73,6 +76,7 @@ export function createSSEStream<TEventMap extends StreamEventMap = StreamEventMa
73
76
  const { done, value } = await reader.read()
74
77
 
75
78
  if (done) {
79
+ stream.emit('done', {})
76
80
  stream.emit('complete', {})
77
81
  break
78
82
  }
@@ -84,33 +88,48 @@ export function createSSEStream<TEventMap extends StreamEventMap = StreamEventMa
84
88
  const lines = buffer.split('\n')
85
89
  buffer = lines.pop() || '' // Keep incomplete line in buffer
86
90
 
87
- let eventData = ''
91
+ let currentEvent = 'message'
92
+ let currentData = ''
88
93
 
89
94
  for (const line of lines) {
90
- if (line.startsWith('data:')) {
91
- eventData = line.slice(5).trim()
92
- } else if (line === '' && eventData) {
95
+ if (line.startsWith('event:')) {
96
+ currentEvent = line.slice(6).trim()
97
+ } else if (line.startsWith('data:')) {
98
+ currentData = line.slice(5).trim()
99
+ } else if (line === '' && currentData) {
93
100
  // Empty line indicates end of event - emit immediately
94
101
  try {
95
- const data = JSON.parse(eventData)
96
- // Emit using data.type for the event name
97
- stream.emit(data.type || 'message', data)
98
- } catch (error) {
99
- console.error('Failed to parse SSE event:', error)
102
+ const parsed = JSON.parse(currentData)
103
+ stream.emit(currentEvent, parsed)
104
+ } catch {
105
+ // If not valid JSON, emit as string
106
+ stream.emit(currentEvent, currentData)
100
107
  }
101
- eventData = ''
108
+ // Reset for next event
109
+ currentEvent = 'message'
110
+ currentData = ''
102
111
  }
103
112
  }
104
113
  }
105
- } catch (error) {
106
- if (error instanceof Error && error.name !== 'AbortError') {
107
- stream.emit('error', error)
114
+ } catch (error: any) {
115
+ // Handle all stream errors (network errors, protocol errors, etc.)
116
+ if (error?.name !== 'AbortError') {
117
+ const errorMessage = error?.message || 'Stream connection error'
118
+ stream.emit('error', new Error(errorMessage))
119
+ }
120
+ } finally {
121
+ // Clean up reader
122
+ try {
123
+ reader.releaseLock()
124
+ } catch {
125
+ // Ignore cleanup errors
108
126
  }
109
127
  }
110
128
  })
111
- .catch((error) => {
112
- if (error.name !== 'AbortError') {
113
- stream.emit('error', error)
129
+ .catch((error: any) => {
130
+ if (error?.name !== 'AbortError') {
131
+ const errorMessage = error?.message || 'Failed to establish stream connection'
132
+ stream.emit('error', new Error(errorMessage))
114
133
  }
115
134
  })
116
135
 
@@ -148,11 +167,14 @@ export function createSSEStreamPost<TEventMap extends StreamEventMap = StreamEve
148
167
  headers: {
149
168
  'Accept': 'text/event-stream',
150
169
  'Content-Type': 'application/json',
170
+ 'Cache-Control': 'no-cache',
151
171
  ...headers,
152
172
  },
153
173
  credentials: withCredentials ? 'include' : 'same-origin',
154
174
  body: JSON.stringify(body),
155
175
  signal: controller.signal,
176
+ // Disable keepalive for streaming
177
+ keepalive: false,
156
178
  })
157
179
  .then(async (response) => {
158
180
  if (!response.ok) {
@@ -172,6 +194,7 @@ export function createSSEStreamPost<TEventMap extends StreamEventMap = StreamEve
172
194
  const { done, value } = await reader.read()
173
195
 
174
196
  if (done) {
197
+ stream.emit('done', {})
175
198
  stream.emit('complete', {})
176
199
  break
177
200
  }
@@ -183,33 +206,48 @@ export function createSSEStreamPost<TEventMap extends StreamEventMap = StreamEve
183
206
  const lines = buffer.split('\n')
184
207
  buffer = lines.pop() || '' // Keep incomplete line in buffer
185
208
 
186
- let eventData = ''
209
+ let currentEvent = 'message'
210
+ let currentData = ''
187
211
 
188
212
  for (const line of lines) {
189
- if (line.startsWith('data:')) {
190
- eventData = line.slice(5).trim()
191
- } else if (line === '' && eventData) {
213
+ if (line.startsWith('event:')) {
214
+ currentEvent = line.slice(6).trim()
215
+ } else if (line.startsWith('data:')) {
216
+ currentData = line.slice(5).trim()
217
+ } else if (line === '' && currentData) {
192
218
  // Empty line indicates end of event - emit immediately
193
219
  try {
194
- const data = JSON.parse(eventData)
195
- // Emit using data.type for the event name
196
- stream.emit(data.type || 'message', data)
197
- } catch (error) {
198
- console.error('Failed to parse SSE event:', error)
220
+ const parsed = JSON.parse(currentData)
221
+ stream.emit(currentEvent, parsed)
222
+ } catch {
223
+ // If not valid JSON, emit as string
224
+ stream.emit(currentEvent, currentData)
199
225
  }
200
- eventData = ''
226
+ // Reset for next event
227
+ currentEvent = 'message'
228
+ currentData = ''
201
229
  }
202
230
  }
203
231
  }
204
- } catch (error) {
205
- if (error instanceof Error && error.name !== 'AbortError') {
206
- stream.emit('error', error)
232
+ } catch (error: any) {
233
+ // Handle all stream errors (network errors, protocol errors, etc.)
234
+ if (error?.name !== 'AbortError') {
235
+ const errorMessage = error?.message || 'Stream connection error'
236
+ stream.emit('error', new Error(errorMessage))
237
+ }
238
+ } finally {
239
+ // Clean up reader
240
+ try {
241
+ reader.releaseLock()
242
+ } catch {
243
+ // Ignore cleanup errors
207
244
  }
208
245
  }
209
246
  })
210
- .catch((error) => {
211
- if (error.name !== 'AbortError') {
212
- stream.emit('error', error)
247
+ .catch((error: any) => {
248
+ if (error?.name !== 'AbortError') {
249
+ const errorMessage = error?.message || 'Failed to establish stream connection'
250
+ stream.emit('error', new Error(errorMessage))
213
251
  }
214
252
  })
215
253