@chaoslabs/ai-sdk 0.0.3 → 0.0.5

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.
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,345 @@
1
+ import { describe, it, expect } from "bun:test";
2
+ import { isAgentStatusMessage, isAgentMessage, isReportMessage, isFollowUpSuggestions, isUserInputMessage, parseAgentStatus, isTerminalStatus, extractAgentMessageText, extractSuggestions, extractReportBlock, parseStreamLine, parseStreamLines, } from "../stream";
3
+ describe("isAgentStatusMessage", () => {
4
+ it("returns true for agent_status_change message", () => {
5
+ const msg = {
6
+ id: "1",
7
+ type: "agent_status_change",
8
+ timestamp: Date.now(),
9
+ content: { status: "processing" },
10
+ context: {
11
+ sessionId: "session-1",
12
+ artifactId: "artifact-1",
13
+ },
14
+ };
15
+ expect(isAgentStatusMessage(msg)).toBe(true);
16
+ });
17
+ it("returns false for other message types", () => {
18
+ const msg = {
19
+ id: "2",
20
+ type: "agent_message",
21
+ timestamp: Date.now(),
22
+ content: { messageId: "m1", data: { message: "Hello" } },
23
+ context: {
24
+ sessionId: "session-1",
25
+ artifactId: "artifact-1",
26
+ },
27
+ };
28
+ expect(isAgentStatusMessage(msg)).toBe(false);
29
+ });
30
+ });
31
+ describe("isAgentMessage", () => {
32
+ it("returns true for agent_message type", () => {
33
+ const msg = {
34
+ id: "1",
35
+ type: "agent_message",
36
+ timestamp: Date.now(),
37
+ content: { messageId: "m1", data: { message: "Hello" } },
38
+ context: { sessionId: "s1", artifactId: "a1" },
39
+ };
40
+ expect(isAgentMessage(msg)).toBe(true);
41
+ });
42
+ it("returns false for other message types", () => {
43
+ const msg = {
44
+ id: "1",
45
+ type: "report",
46
+ timestamp: Date.now(),
47
+ content: { id: "r1", type: "table", data: {} },
48
+ context: { sessionId: "s1", artifactId: "a1" },
49
+ };
50
+ expect(isAgentMessage(msg)).toBe(false);
51
+ });
52
+ });
53
+ describe("isReportMessage", () => {
54
+ it("returns true for report type", () => {
55
+ const msg = {
56
+ id: "1",
57
+ type: "report",
58
+ timestamp: Date.now(),
59
+ content: { id: "r1", type: "table", data: {} },
60
+ context: { sessionId: "s1", artifactId: "a1" },
61
+ };
62
+ expect(isReportMessage(msg)).toBe(true);
63
+ });
64
+ it("returns false for other message types", () => {
65
+ const msg = {
66
+ id: "1",
67
+ type: "agent_message",
68
+ timestamp: Date.now(),
69
+ content: { messageId: "m1", data: { message: "Hello" } },
70
+ context: { sessionId: "s1", artifactId: "a1" },
71
+ };
72
+ expect(isReportMessage(msg)).toBe(false);
73
+ });
74
+ });
75
+ describe("isFollowUpSuggestions", () => {
76
+ it("returns true for follow_up_suggestions type", () => {
77
+ const msg = {
78
+ id: "1",
79
+ type: "follow_up_suggestions",
80
+ timestamp: Date.now(),
81
+ content: { suggestions: ["Question 1?", "Question 2?"] },
82
+ context: { sessionId: "s1", artifactId: "a1" },
83
+ };
84
+ expect(isFollowUpSuggestions(msg)).toBe(true);
85
+ });
86
+ it("returns false for other message types", () => {
87
+ const msg = {
88
+ id: "1",
89
+ type: "agent_message",
90
+ timestamp: Date.now(),
91
+ content: { messageId: "m1", data: { message: "Hello" } },
92
+ context: { sessionId: "s1", artifactId: "a1" },
93
+ };
94
+ expect(isFollowUpSuggestions(msg)).toBe(false);
95
+ });
96
+ });
97
+ describe("isUserInputMessage", () => {
98
+ it("returns true for user_input type", () => {
99
+ const msg = {
100
+ id: "1",
101
+ type: "user_input",
102
+ timestamp: Date.now(),
103
+ content: { query: "What is my balance?" },
104
+ context: { sessionId: "s1", artifactId: "a1" },
105
+ };
106
+ expect(isUserInputMessage(msg)).toBe(true);
107
+ });
108
+ it("returns false for other message types", () => {
109
+ const msg = {
110
+ id: "1",
111
+ type: "agent_message",
112
+ timestamp: Date.now(),
113
+ content: { messageId: "m1", data: { message: "Hello" } },
114
+ context: { sessionId: "s1", artifactId: "a1" },
115
+ };
116
+ expect(isUserInputMessage(msg)).toBe(false);
117
+ });
118
+ });
119
+ describe("parseAgentStatus", () => {
120
+ it("extracts status from agent_status_change message", () => {
121
+ const msg = {
122
+ id: "1",
123
+ type: "agent_status_change",
124
+ timestamp: Date.now(),
125
+ content: { status: "processing" },
126
+ context: { sessionId: "s1", artifactId: "a1" },
127
+ };
128
+ expect(parseAgentStatus(msg)).toBe("processing");
129
+ });
130
+ it("extracts done status", () => {
131
+ const msg = {
132
+ id: "1",
133
+ type: "agent_status_change",
134
+ timestamp: Date.now(),
135
+ content: { status: "done" },
136
+ context: { sessionId: "s1", artifactId: "a1" },
137
+ };
138
+ expect(parseAgentStatus(msg)).toBe("done");
139
+ });
140
+ it("returns null for non-status messages", () => {
141
+ const msg = {
142
+ id: "1",
143
+ type: "agent_message",
144
+ timestamp: Date.now(),
145
+ content: { messageId: "m1", data: { message: "Hello" } },
146
+ context: { sessionId: "s1", artifactId: "a1" },
147
+ };
148
+ expect(parseAgentStatus(msg)).toBeNull();
149
+ });
150
+ it("returns null for invalid content", () => {
151
+ const msg = {
152
+ id: "1",
153
+ type: "agent_status_change",
154
+ timestamp: Date.now(),
155
+ content: { notStatus: "wrong" },
156
+ context: { sessionId: "s1", artifactId: "a1" },
157
+ };
158
+ expect(parseAgentStatus(msg)).toBeNull();
159
+ });
160
+ });
161
+ describe("isTerminalStatus", () => {
162
+ it("returns true for done status", () => {
163
+ expect(isTerminalStatus("done")).toBe(true);
164
+ });
165
+ it("returns true for error status", () => {
166
+ expect(isTerminalStatus("error")).toBe(true);
167
+ });
168
+ it("returns true for cancelled status", () => {
169
+ expect(isTerminalStatus("cancelled")).toBe(true);
170
+ });
171
+ it("returns false for processing status", () => {
172
+ expect(isTerminalStatus("processing")).toBe(false);
173
+ });
174
+ });
175
+ describe("extractAgentMessageText", () => {
176
+ it("extracts message text from agent_message", () => {
177
+ const msg = {
178
+ id: "1",
179
+ type: "agent_message",
180
+ timestamp: Date.now(),
181
+ content: { messageId: "m1", data: { message: "Hello world" } },
182
+ context: { sessionId: "s1", artifactId: "a1" },
183
+ };
184
+ expect(extractAgentMessageText(msg)).toBe("Hello world");
185
+ });
186
+ it("returns null for non-agent_message types", () => {
187
+ const msg = {
188
+ id: "1",
189
+ type: "report",
190
+ timestamp: Date.now(),
191
+ content: { id: "r1", type: "table", data: {} },
192
+ context: { sessionId: "s1", artifactId: "a1" },
193
+ };
194
+ expect(extractAgentMessageText(msg)).toBeNull();
195
+ });
196
+ it("returns null for invalid content structure", () => {
197
+ const msg = {
198
+ id: "1",
199
+ type: "agent_message",
200
+ timestamp: Date.now(),
201
+ content: { messageId: "m1" }, // missing data.message
202
+ context: { sessionId: "s1", artifactId: "a1" },
203
+ };
204
+ expect(extractAgentMessageText(msg)).toBeNull();
205
+ });
206
+ });
207
+ describe("extractSuggestions", () => {
208
+ it("extracts suggestions array from follow_up_suggestions", () => {
209
+ const msg = {
210
+ id: "1",
211
+ type: "follow_up_suggestions",
212
+ timestamp: Date.now(),
213
+ content: { suggestions: ["Question 1?", "Question 2?"] },
214
+ context: { sessionId: "s1", artifactId: "a1" },
215
+ };
216
+ expect(extractSuggestions(msg)).toEqual(["Question 1?", "Question 2?"]);
217
+ });
218
+ it("returns empty array for non-follow_up_suggestions types", () => {
219
+ const msg = {
220
+ id: "1",
221
+ type: "agent_message",
222
+ timestamp: Date.now(),
223
+ content: { messageId: "m1", data: { message: "Hello" } },
224
+ context: { sessionId: "s1", artifactId: "a1" },
225
+ };
226
+ expect(extractSuggestions(msg)).toEqual([]);
227
+ });
228
+ it("returns empty array for invalid content structure", () => {
229
+ const msg = {
230
+ id: "1",
231
+ type: "follow_up_suggestions",
232
+ timestamp: Date.now(),
233
+ content: { notSuggestions: "wrong" },
234
+ context: { sessionId: "s1", artifactId: "a1" },
235
+ };
236
+ expect(extractSuggestions(msg)).toEqual([]);
237
+ });
238
+ });
239
+ describe("extractReportBlock", () => {
240
+ it("extracts data from report message", () => {
241
+ const reportData = { columns: ["name"], rows: [["Alice"]] };
242
+ const msg = {
243
+ id: "1",
244
+ type: "report",
245
+ timestamp: Date.now(),
246
+ content: { id: "r1", type: "table", data: reportData },
247
+ context: { sessionId: "s1", artifactId: "a1" },
248
+ };
249
+ expect(extractReportBlock(msg)).toEqual(reportData);
250
+ });
251
+ it("returns null for non-report types", () => {
252
+ const msg = {
253
+ id: "1",
254
+ type: "agent_message",
255
+ timestamp: Date.now(),
256
+ content: { messageId: "m1", data: { message: "Hello" } },
257
+ context: { sessionId: "s1", artifactId: "a1" },
258
+ };
259
+ expect(extractReportBlock(msg)).toBeNull();
260
+ });
261
+ it("returns null for invalid content structure", () => {
262
+ const msg = {
263
+ id: "1",
264
+ type: "report",
265
+ timestamp: Date.now(),
266
+ content: { id: "r1", type: "table" }, // missing data
267
+ context: { sessionId: "s1", artifactId: "a1" },
268
+ };
269
+ expect(extractReportBlock(msg)).toBeNull();
270
+ });
271
+ });
272
+ describe("parseStreamLine", () => {
273
+ it("parses valid NDJSON line to StreamMessage", () => {
274
+ const msg = {
275
+ id: "1",
276
+ type: "agent_message",
277
+ timestamp: 1234567890,
278
+ content: { messageId: "m1", data: { message: "Hello" } },
279
+ context: { sessionId: "s1", artifactId: "a1" },
280
+ };
281
+ const line = JSON.stringify(msg);
282
+ const result = parseStreamLine(line);
283
+ expect(result).toEqual(msg);
284
+ });
285
+ it("returns null for empty line", () => {
286
+ expect(parseStreamLine("")).toBeNull();
287
+ });
288
+ it("returns null for whitespace-only line", () => {
289
+ expect(parseStreamLine(" ")).toBeNull();
290
+ });
291
+ it("returns null for invalid JSON", () => {
292
+ expect(parseStreamLine("{not valid json}")).toBeNull();
293
+ });
294
+ it("returns null for missing required fields", () => {
295
+ expect(parseStreamLine('{"id": "1"}')).toBeNull();
296
+ });
297
+ });
298
+ describe("parseStreamLines", () => {
299
+ it("parses multiple NDJSON lines", () => {
300
+ const msg1 = {
301
+ id: "1",
302
+ type: "agent_status_change",
303
+ timestamp: 1234567890,
304
+ content: { status: "processing" },
305
+ context: { sessionId: "s1", artifactId: "a1" },
306
+ };
307
+ const msg2 = {
308
+ id: "2",
309
+ type: "agent_message",
310
+ timestamp: 1234567891,
311
+ content: { messageId: "m1", data: { message: "Hello" } },
312
+ context: { sessionId: "s1", artifactId: "a1" },
313
+ };
314
+ const text = JSON.stringify(msg1) + "\n" + JSON.stringify(msg2);
315
+ const result = parseStreamLines(text);
316
+ expect(result).toEqual([msg1, msg2]);
317
+ });
318
+ it("returns empty array for empty string", () => {
319
+ expect(parseStreamLines("")).toEqual([]);
320
+ });
321
+ it("skips invalid lines and returns valid ones", () => {
322
+ const validMsg = {
323
+ id: "1",
324
+ type: "agent_message",
325
+ timestamp: 1234567890,
326
+ content: { messageId: "m1", data: { message: "Hello" } },
327
+ context: { sessionId: "s1", artifactId: "a1" },
328
+ };
329
+ const text = "invalid json\n" + JSON.stringify(validMsg) + "\n{broken}";
330
+ const result = parseStreamLines(text);
331
+ expect(result).toEqual([validMsg]);
332
+ });
333
+ it("handles lines with various whitespace", () => {
334
+ const msg = {
335
+ id: "1",
336
+ type: "agent_message",
337
+ timestamp: 1234567890,
338
+ content: { messageId: "m1", data: { message: "Hello" } },
339
+ context: { sessionId: "s1", artifactId: "a1" },
340
+ };
341
+ const text = "\n\n" + JSON.stringify(msg) + "\n\n";
342
+ const result = parseStreamLines(text);
343
+ expect(result).toEqual([msg]);
344
+ });
345
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,6 @@
1
+ import { describe, it, expect } from 'bun:test';
2
+ describe('test infrastructure', () => {
3
+ it('works', () => {
4
+ expect(1 + 1).toBe(2);
5
+ });
6
+ });
package/dist/client.d.ts CHANGED
@@ -1,23 +1,33 @@
1
1
  import type { ChaosConfig, CreateResponseParams, Response } from './types.js';
2
2
  import { WALLET_MODEL, ASK_MODEL } from './request.js';
3
+ import { StreamingHttpClient } from './http-streaming.js';
3
4
  export { WALLET_MODEL, ASK_MODEL };
5
+ /**
6
+ * Extended config with useNativeHttp option
7
+ */
8
+ interface ExtendedChaosConfig extends ChaosConfig {
9
+ apiKey: string;
10
+ baseUrl: string;
11
+ timeout: number;
12
+ useNativeHttp: boolean;
13
+ }
4
14
  /**
5
15
  * The v1 responses API namespace.
6
16
  */
7
17
  declare class V1Responses {
8
18
  private config;
9
19
  private sessionId;
10
- private abortController;
11
- constructor(config: Required<ChaosConfig>);
20
+ private streamingClient;
21
+ constructor(config: ExtendedChaosConfig);
12
22
  private generateId;
13
23
  /**
14
24
  * Create a response using v1 API.
15
25
  */
16
26
  create(params: CreateResponseParams): Promise<Response>;
17
27
  /**
18
- * Create a non-streaming response.
28
+ * Create a response using native HTTP streaming.
19
29
  */
20
- private createNonStreaming;
30
+ private createWithNativeHttp;
21
31
  /**
22
32
  * Cancel the current request.
23
33
  */
@@ -32,7 +42,7 @@ declare class V1Responses {
32
42
  */
33
43
  declare class V1Chat {
34
44
  readonly responses: V1Responses;
35
- constructor(config: Required<ChaosConfig>);
45
+ constructor(config: ExtendedChaosConfig);
36
46
  }
37
47
  /**
38
48
  * Chaos AI SDK Client - V1 API.
@@ -64,6 +74,8 @@ declare class V1Chat {
64
74
  export declare class Chaos {
65
75
  readonly chat: V1Chat;
66
76
  private config;
77
+ /** Whether to use native http module for streaming */
78
+ readonly useNativeHttp: boolean;
67
79
  constructor(config: ChaosConfig);
68
80
  /**
69
81
  * Get the API key.
@@ -73,5 +85,9 @@ export declare class Chaos {
73
85
  * Get the base URL.
74
86
  */
75
87
  get baseUrl(): string;
88
+ /**
89
+ * Get a StreamingHttpClient instance for direct streaming access.
90
+ */
91
+ getStreamingClient(): StreamingHttpClient;
76
92
  }
77
93
  export default Chaos;
package/dist/client.js CHANGED
@@ -3,23 +3,37 @@
3
3
  // This client talks to the new v1 API endpoint with Bearer auth.
4
4
  import { ChaosError, ChaosTimeoutError } from './types.js';
5
5
  import { toV1WalletRequest, toV1AskRequest, buildV1Headers, buildV1Endpoint, WALLET_MODEL, ASK_MODEL, } from './request.js';
6
- import { parseV1Stream, toV1Response } from './response.js';
6
+ import { toV1Response } from './response.js';
7
+ import { parseStreamLine } from './stream.js';
8
+ import { StreamingHttpClient } from './http-streaming.js';
9
+ /**
10
+ * Build final state from a list of stream events.
11
+ */
12
+ function buildFinalStateFromEvents(events) {
13
+ const blocks = [];
14
+ for (const event of events) {
15
+ if (event.type === 'report' && event.content) {
16
+ const content = event.content;
17
+ if (content.data) {
18
+ blocks.push(content.data);
19
+ }
20
+ }
21
+ }
22
+ return { blocks };
23
+ }
7
24
  // Export model constants
8
25
  export { WALLET_MODEL, ASK_MODEL };
9
26
  // ============================================================================
10
27
  // Constants
11
28
  // ============================================================================
12
29
  const DEFAULT_TIMEOUT = 120000; // 2 minutes
13
- // ============================================================================
14
- // V1 Responses Class
15
- // ============================================================================
16
30
  /**
17
31
  * The v1 responses API namespace.
18
32
  */
19
33
  class V1Responses {
20
34
  config;
21
35
  sessionId;
22
- abortController = null;
36
+ streamingClient = null;
23
37
  constructor(config) {
24
38
  this.config = config;
25
39
  this.sessionId = this.generateId();
@@ -31,48 +45,63 @@ class V1Responses {
31
45
  * Create a response using v1 API.
32
46
  */
33
47
  async create(params) {
34
- return this.createNonStreaming(params);
48
+ // Always use native HTTP for true streaming behavior
49
+ return this.createWithNativeHttp(params);
35
50
  }
36
51
  /**
37
- * Create a non-streaming response.
52
+ * Create a response using native HTTP streaming.
38
53
  */
39
- async createNonStreaming(params) {
54
+ async createWithNativeHttp(params) {
40
55
  const responseId = this.generateId();
41
56
  const sessionId = params.metadata.session_id || this.sessionId;
42
- // Create abort controller for timeout
43
- this.abortController = new AbortController();
44
- const timeoutSignal = AbortSignal.timeout(this.config.timeout);
45
- const signal = AbortSignal.any([this.abortController.signal, timeoutSignal]);
57
+ // Create streaming client
58
+ this.streamingClient = new StreamingHttpClient({
59
+ baseUrl: this.config.baseUrl,
60
+ timeout: this.config.timeout,
61
+ });
46
62
  // Build request
47
- const endpoint = buildV1Endpoint(this.config.baseUrl);
48
63
  const headers = buildV1Headers(this.config.apiKey);
49
64
  // Check if wallet or ask mode
50
65
  const isWallet = params.model === WALLET_MODEL || params.model.includes('WALLET');
51
66
  const requestBody = isWallet
52
67
  ? toV1WalletRequest(params, sessionId)
53
68
  : toV1AskRequest(params, sessionId);
69
+ // Build endpoint path
70
+ const endpoint = buildV1Endpoint(this.config.baseUrl);
71
+ const url = new URL(endpoint);
72
+ const path = url.pathname + url.search;
54
73
  try {
55
- // Make request
56
- const response = await fetch(endpoint, {
74
+ // Collect events for final response
75
+ const events = [];
76
+ // Stream lines using native http
77
+ for await (const line of this.streamingClient.streamLines(path, {
57
78
  method: 'POST',
58
79
  headers,
59
80
  body: JSON.stringify(requestBody),
60
- signal,
61
- });
62
- if (!response.ok) {
63
- throw new ChaosError(`HTTP error: ${response.status} ${response.statusText}`, response.status);
81
+ })) {
82
+ try {
83
+ const event = JSON.parse(line);
84
+ events.push(event);
85
+ // Call stream event callback if provided
86
+ if (params.onStreamEvent) {
87
+ const msg = parseStreamLine(line);
88
+ if (msg) {
89
+ params.onStreamEvent(msg);
90
+ }
91
+ }
92
+ }
93
+ catch {
94
+ // Skip invalid JSON lines
95
+ }
64
96
  }
65
- if (!response.body) {
66
- throw new ChaosError('Response body is null');
67
- }
68
- // Parse NDJSON stream
69
- const finalState = await parseV1Stream(response.body);
97
+ // Build final state from events
98
+ const finalState = buildFinalStateFromEvents(events);
70
99
  // Convert to Response
71
100
  return toV1Response(responseId, params.model, finalState);
72
101
  }
73
102
  catch (error) {
74
- if (error instanceof Error && error.name === 'TimeoutError') {
75
- throw new ChaosTimeoutError(this.config.timeout);
103
+ if (error instanceof ChaosTimeoutError) {
104
+ throw error;
76
105
  }
77
106
  if (error instanceof ChaosError) {
78
107
  throw error;
@@ -80,15 +109,17 @@ class V1Responses {
80
109
  throw new ChaosError(error instanceof Error ? error.message : String(error));
81
110
  }
82
111
  finally {
83
- this.abortController = null;
112
+ this.streamingClient = null;
84
113
  }
85
114
  }
86
115
  /**
87
116
  * Cancel the current request.
88
117
  */
89
118
  cancel() {
90
- this.abortController?.abort();
91
- this.abortController = null;
119
+ // Cancel native HTTP streaming client
120
+ if (this.streamingClient) {
121
+ this.streamingClient.abort();
122
+ }
92
123
  }
93
124
  /**
94
125
  * Reset the session for a new conversation.
@@ -143,12 +174,18 @@ class V1Chat {
143
174
  export class Chaos {
144
175
  chat;
145
176
  config;
177
+ /** Whether to use native http module for streaming */
178
+ useNativeHttp;
146
179
  constructor(config) {
180
+ // Default useNativeHttp to true for proper streaming
181
+ const useNativeHttp = config.useNativeHttp !== false;
147
182
  this.config = {
148
183
  apiKey: config.apiKey,
149
184
  baseUrl: config.baseUrl || 'https://ai-staging.chaoslabs.co',
150
185
  timeout: config.timeout || DEFAULT_TIMEOUT,
186
+ useNativeHttp,
151
187
  };
188
+ this.useNativeHttp = useNativeHttp;
152
189
  this.chat = new V1Chat(this.config);
153
190
  }
154
191
  /**
@@ -163,5 +200,14 @@ export class Chaos {
163
200
  get baseUrl() {
164
201
  return this.config.baseUrl;
165
202
  }
203
+ /**
204
+ * Get a StreamingHttpClient instance for direct streaming access.
205
+ */
206
+ getStreamingClient() {
207
+ return new StreamingHttpClient({
208
+ baseUrl: this.config.baseUrl,
209
+ timeout: this.config.timeout,
210
+ });
211
+ }
166
212
  }
167
213
  export default Chaos;
@@ -0,0 +1,55 @@
1
+ export interface HttpStreamOptions {
2
+ url: string;
3
+ method: string;
4
+ headers: Record<string, string>;
5
+ body: string;
6
+ timeout: number;
7
+ }
8
+ export interface StreamingHttpClientOptions {
9
+ baseUrl: string;
10
+ timeout: number;
11
+ }
12
+ export interface StreamRequestOptions {
13
+ method: string;
14
+ headers?: Record<string, string>;
15
+ body: string;
16
+ }
17
+ /**
18
+ * Makes an HTTP request using Node's native http/https modules and returns
19
+ * an async iterator that yields chunks as they arrive (true streaming).
20
+ *
21
+ * @param options - Request options
22
+ * @returns AsyncIterable that yields string chunks
23
+ */
24
+ export declare function httpStreamRequest(options: HttpStreamOptions): AsyncIterable<string>;
25
+ /**
26
+ * High-level HTTP streaming client that provides methods for streaming
27
+ * requests with proper chunk and line parsing.
28
+ */
29
+ export declare class StreamingHttpClient {
30
+ private baseUrl;
31
+ private timeout;
32
+ private aborted;
33
+ private currentIterator;
34
+ constructor(options: StreamingHttpClientOptions);
35
+ /**
36
+ * Stream raw chunks from a request.
37
+ *
38
+ * @param path - URL path (will be appended to baseUrl)
39
+ * @param options - Request options
40
+ * @returns AsyncIterable of raw string chunks
41
+ */
42
+ stream(path: string, options: StreamRequestOptions): AsyncIterable<string>;
43
+ /**
44
+ * Stream parsed NDJSON lines from a request.
45
+ *
46
+ * @param path - URL path (will be appended to baseUrl)
47
+ * @param options - Request options
48
+ * @returns AsyncIterable of complete JSON lines (without newline)
49
+ */
50
+ streamLines(path: string, options: StreamRequestOptions): AsyncIterable<string>;
51
+ /**
52
+ * Abort the current in-progress request.
53
+ */
54
+ abort(): void;
55
+ }