ai.matey.types 0.2.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.
Files changed (69) hide show
  1. package/LICENSE +21 -0
  2. package/dist/cjs/adapters.js +16 -0
  3. package/dist/cjs/adapters.js.map +1 -0
  4. package/dist/cjs/bridge.js +32 -0
  5. package/dist/cjs/bridge.js.map +1 -0
  6. package/dist/cjs/errors.js +121 -0
  7. package/dist/cjs/errors.js.map +1 -0
  8. package/dist/cjs/index.js +44 -0
  9. package/dist/cjs/index.js.map +1 -0
  10. package/dist/cjs/ir.js +17 -0
  11. package/dist/cjs/ir.js.map +1 -0
  12. package/dist/cjs/middleware.js +11 -0
  13. package/dist/cjs/middleware.js.map +1 -0
  14. package/dist/cjs/model-runner.js +11 -0
  15. package/dist/cjs/model-runner.js.map +1 -0
  16. package/dist/cjs/model-translation.js +10 -0
  17. package/dist/cjs/model-translation.js.map +1 -0
  18. package/dist/cjs/models.js +11 -0
  19. package/dist/cjs/models.js.map +1 -0
  20. package/dist/cjs/router.js +93 -0
  21. package/dist/cjs/router.js.map +1 -0
  22. package/dist/cjs/streaming.js +28 -0
  23. package/dist/cjs/streaming.js.map +1 -0
  24. package/dist/esm/adapters.js +15 -0
  25. package/dist/esm/adapters.js.map +1 -0
  26. package/dist/esm/bridge.js +29 -0
  27. package/dist/esm/bridge.js.map +1 -0
  28. package/dist/esm/errors.js +118 -0
  29. package/dist/esm/errors.js.map +1 -0
  30. package/dist/esm/index.js +28 -0
  31. package/dist/esm/index.js.map +1 -0
  32. package/dist/esm/ir.js +16 -0
  33. package/dist/esm/ir.js.map +1 -0
  34. package/dist/esm/middleware.js +10 -0
  35. package/dist/esm/middleware.js.map +1 -0
  36. package/dist/esm/model-runner.js +10 -0
  37. package/dist/esm/model-runner.js.map +1 -0
  38. package/dist/esm/model-translation.js +9 -0
  39. package/dist/esm/model-translation.js.map +1 -0
  40. package/dist/esm/models.js +10 -0
  41. package/dist/esm/models.js.map +1 -0
  42. package/dist/esm/router.js +90 -0
  43. package/dist/esm/router.js.map +1 -0
  44. package/dist/esm/streaming.js +25 -0
  45. package/dist/esm/streaming.js.map +1 -0
  46. package/dist/types/adapters.d.ts +377 -0
  47. package/dist/types/adapters.d.ts.map +1 -0
  48. package/dist/types/bridge.d.ts +290 -0
  49. package/dist/types/bridge.d.ts.map +1 -0
  50. package/dist/types/errors.d.ts +380 -0
  51. package/dist/types/errors.d.ts.map +1 -0
  52. package/dist/types/index.d.ts +18 -0
  53. package/dist/types/index.d.ts.map +1 -0
  54. package/dist/types/ir.d.ts +820 -0
  55. package/dist/types/ir.d.ts.map +1 -0
  56. package/dist/types/middleware.d.ts +256 -0
  57. package/dist/types/middleware.d.ts.map +1 -0
  58. package/dist/types/model-runner.d.ts +344 -0
  59. package/dist/types/model-runner.d.ts.map +1 -0
  60. package/dist/types/model-translation.d.ts +76 -0
  61. package/dist/types/model-translation.d.ts.map +1 -0
  62. package/dist/types/models.d.ts +160 -0
  63. package/dist/types/models.d.ts.map +1 -0
  64. package/dist/types/router.d.ts +526 -0
  65. package/dist/types/router.d.ts.map +1 -0
  66. package/dist/types/streaming.d.ts +96 -0
  67. package/dist/types/streaming.d.ts.map +1 -0
  68. package/package.json +64 -0
  69. package/readme.md +84 -0
@@ -0,0 +1,820 @@
1
+ /**
2
+ * Intermediate Representation (IR) Types
3
+ *
4
+ * The IR is the universal format that sits between frontend and backend adapters.
5
+ * It represents chat requests, responses, and streams in a normalized, provider-agnostic way.
6
+ *
7
+ * Design principles:
8
+ * - Provider-agnostic: No provider-specific fields in core types
9
+ * - Extensible: Support for metadata and custom fields
10
+ * - Type-safe: Use discriminated unions for runtime type checking
11
+ * - Stream-friendly: First-class support for streaming responses
12
+ *
13
+ * @module
14
+ */
15
+ import type { StreamMode } from './streaming.js';
16
+ /**
17
+ * Message role in a conversation.
18
+ *
19
+ * Maps to roles across all major providers:
20
+ * - system: Initial instructions/context (some providers use special parameter)
21
+ * - user: Messages from the user
22
+ * - assistant: Messages from the AI
23
+ * - tool: Results from tool/function calls
24
+ */
25
+ export type MessageRole = 'system' | 'user' | 'assistant' | 'tool';
26
+ /**
27
+ * Text content block.
28
+ */
29
+ export interface TextContent {
30
+ readonly type: 'text';
31
+ readonly text: string;
32
+ }
33
+ /**
34
+ * Image content block.
35
+ *
36
+ * Supports both URLs and base64-encoded images.
37
+ *
38
+ * @example
39
+ * ```typescript
40
+ * // Image from URL
41
+ * const imageUrl: ImageContent = {
42
+ * type: 'image',
43
+ * source: {
44
+ * type: 'url',
45
+ * url: 'https://example.com/image.jpg'
46
+ * }
47
+ * };
48
+ *
49
+ * // Base64 image
50
+ * const imageBase64: ImageContent = {
51
+ * type: 'image',
52
+ * source: {
53
+ * type: 'base64',
54
+ * mediaType: 'image/jpeg',
55
+ * data: 'iVBORw0KGgo...'
56
+ * }
57
+ * };
58
+ * ```
59
+ */
60
+ export interface ImageContent {
61
+ readonly type: 'image';
62
+ readonly source: {
63
+ readonly type: 'url';
64
+ readonly url: string;
65
+ } | {
66
+ readonly type: 'base64';
67
+ readonly mediaType: string;
68
+ readonly data: string;
69
+ };
70
+ }
71
+ /**
72
+ * Tool use request (AI wants to call a tool).
73
+ */
74
+ export interface ToolUseContent {
75
+ readonly type: 'tool_use';
76
+ readonly id: string;
77
+ readonly name: string;
78
+ readonly input: Record<string, unknown>;
79
+ }
80
+ /**
81
+ * Tool result (response from tool execution).
82
+ */
83
+ export interface ToolResultContent {
84
+ readonly type: 'tool_result';
85
+ readonly toolUseId: string;
86
+ readonly content: string | TextContent[];
87
+ readonly isError?: boolean;
88
+ }
89
+ /**
90
+ * Union of all content types.
91
+ *
92
+ * Uses discriminated union pattern for type-safe content handling.
93
+ */
94
+ export type MessageContent = TextContent | ImageContent | ToolUseContent | ToolResultContent;
95
+ /**
96
+ * A message in the conversation.
97
+ *
98
+ * Messages can have either simple string content or structured content blocks.
99
+ * The IR normalizes both formats into a consistent representation.
100
+ *
101
+ * @example
102
+ * ```typescript
103
+ * // Simple text message
104
+ * const textMessage: IRMessage = {
105
+ * role: 'user',
106
+ * content: 'Hello, AI!'
107
+ * };
108
+ *
109
+ * // Multi-modal message with image
110
+ * const multiModalMessage: IRMessage = {
111
+ * role: 'user',
112
+ * content: [
113
+ * { type: 'text', text: 'What is in this image?' },
114
+ * {
115
+ * type: 'image',
116
+ * source: {
117
+ * type: 'url',
118
+ * url: 'https://example.com/photo.jpg'
119
+ * }
120
+ * }
121
+ * ]
122
+ * };
123
+ *
124
+ * // System message
125
+ * const systemMessage: IRMessage = {
126
+ * role: 'system',
127
+ * content: 'You are a helpful assistant.'
128
+ * };
129
+ * ```
130
+ */
131
+ export interface IRMessage {
132
+ /**
133
+ * Message role (system, user, assistant, tool).
134
+ */
135
+ readonly role: MessageRole;
136
+ /**
137
+ * Message content.
138
+ * Can be a simple string or array of content blocks.
139
+ */
140
+ readonly content: string | readonly MessageContent[];
141
+ /**
142
+ * Optional message name/identifier.
143
+ * Used for tool messages or multi-user scenarios.
144
+ */
145
+ readonly name?: string;
146
+ /**
147
+ * Provider-specific metadata.
148
+ * Stored but not processed by IR.
149
+ */
150
+ readonly metadata?: Record<string, unknown>;
151
+ }
152
+ /**
153
+ * JSON Schema type definitions.
154
+ */
155
+ export type JSONSchemaType = 'string' | 'number' | 'integer' | 'boolean' | 'object' | 'array' | 'null';
156
+ /**
157
+ * JSON Schema for tool parameters.
158
+ *
159
+ * Simplified schema supporting common validation patterns.
160
+ */
161
+ export interface JSONSchema {
162
+ readonly type?: JSONSchemaType | readonly JSONSchemaType[];
163
+ readonly description?: string;
164
+ readonly enum?: readonly unknown[];
165
+ readonly const?: unknown;
166
+ readonly properties?: Record<string, JSONSchema>;
167
+ readonly required?: readonly string[];
168
+ readonly items?: JSONSchema;
169
+ readonly additionalProperties?: boolean | JSONSchema;
170
+ readonly minimum?: number;
171
+ readonly maximum?: number;
172
+ readonly minLength?: number;
173
+ readonly maxLength?: number;
174
+ readonly pattern?: string;
175
+ readonly format?: string;
176
+ readonly default?: unknown;
177
+ readonly examples?: readonly unknown[];
178
+ }
179
+ /**
180
+ * Tool/function definition.
181
+ *
182
+ * Describes a tool that the AI can call.
183
+ *
184
+ * @example
185
+ * ```typescript
186
+ * const weatherTool: IRTool = {
187
+ * name: 'get_weather',
188
+ * description: 'Get current weather for a location',
189
+ * parameters: {
190
+ * type: 'object',
191
+ * properties: {
192
+ * location: {
193
+ * type: 'string',
194
+ * description: 'City name or coordinates'
195
+ * },
196
+ * units: {
197
+ * type: 'string',
198
+ * enum: ['celsius', 'fahrenheit'],
199
+ * default: 'celsius'
200
+ * }
201
+ * },
202
+ * required: ['location']
203
+ * }
204
+ * };
205
+ * ```
206
+ */
207
+ export interface IRTool {
208
+ /**
209
+ * Tool name (must be valid identifier).
210
+ */
211
+ readonly name: string;
212
+ /**
213
+ * Human-readable description of what the tool does.
214
+ */
215
+ readonly description: string;
216
+ /**
217
+ * JSON Schema for tool parameters.
218
+ */
219
+ readonly parameters: JSONSchema;
220
+ /**
221
+ * Provider-specific tool configuration.
222
+ */
223
+ readonly metadata?: Record<string, unknown>;
224
+ }
225
+ /**
226
+ * Normalized request parameters.
227
+ *
228
+ * Common parameters across all providers, normalized to consistent ranges.
229
+ * Provider-specific parameters can be added to `custom` field.
230
+ *
231
+ * @example
232
+ * ```typescript
233
+ * const params: IRParameters = {
234
+ * model: 'gpt-4',
235
+ * temperature: 0.7,
236
+ * maxTokens: 1000,
237
+ * topP: 0.9,
238
+ * frequencyPenalty: 0.0,
239
+ * presencePenalty: 0.0,
240
+ * stopSequences: ['\n\n', 'END']
241
+ * };
242
+ * ```
243
+ */
244
+ export interface IRParameters {
245
+ /**
246
+ * Model identifier.
247
+ * Provider-specific model name.
248
+ */
249
+ readonly model?: string;
250
+ /**
251
+ * Sampling temperature (0.0 to 2.0).
252
+ * Higher values make output more random.
253
+ * @default 0.7
254
+ */
255
+ readonly temperature?: number;
256
+ /**
257
+ * Maximum tokens to generate.
258
+ * Actual limit depends on model and provider.
259
+ */
260
+ readonly maxTokens?: number;
261
+ /**
262
+ * Nucleus sampling threshold (0.0 to 1.0).
263
+ * Alternative to temperature.
264
+ */
265
+ readonly topP?: number;
266
+ /**
267
+ * Top-K sampling limit.
268
+ * Only consider top K tokens.
269
+ */
270
+ readonly topK?: number;
271
+ /**
272
+ * Frequency penalty (-2.0 to 2.0).
273
+ * Penalize tokens based on frequency in text so far.
274
+ */
275
+ readonly frequencyPenalty?: number;
276
+ /**
277
+ * Presence penalty (-2.0 to 2.0).
278
+ * Penalize tokens based on whether they appear in text so far.
279
+ */
280
+ readonly presencePenalty?: number;
281
+ /**
282
+ * Stop sequences.
283
+ * Generation stops when any sequence is encountered.
284
+ */
285
+ readonly stopSequences?: readonly string[];
286
+ /**
287
+ * Random seed for deterministic generation.
288
+ */
289
+ readonly seed?: number;
290
+ /**
291
+ * User identifier for abuse monitoring.
292
+ */
293
+ readonly user?: string;
294
+ /**
295
+ * Provider-specific parameters.
296
+ * Passed through to backend without modification.
297
+ */
298
+ readonly custom?: Record<string, unknown>;
299
+ }
300
+ /**
301
+ * System message handling strategy.
302
+ */
303
+ export type SystemMessageStrategy = 'separate-parameter' | 'in-messages' | 'prepend-user' | 'not-supported';
304
+ /**
305
+ * Adapter capabilities metadata.
306
+ *
307
+ * Describes what an adapter supports for routing and validation.
308
+ *
309
+ * @example
310
+ * ```typescript
311
+ * const openaiCapabilities: IRCapabilities = {
312
+ * streaming: true,
313
+ * multiModal: true,
314
+ * tools: true,
315
+ * maxContextTokens: 128000,
316
+ * supportedModels: ['gpt-4', 'gpt-4-turbo', 'gpt-3.5-turbo'],
317
+ * systemMessageStrategy: 'in-messages',
318
+ * supportsMultipleSystemMessages: true,
319
+ * supportsTemperature: true,
320
+ * supportsTopP: true,
321
+ * supportsTopK: false,
322
+ * supportsSeed: true
323
+ * };
324
+ * ```
325
+ */
326
+ export interface IRCapabilities {
327
+ /**
328
+ * Supports streaming responses.
329
+ */
330
+ readonly streaming: boolean;
331
+ /**
332
+ * Supports multi-modal content (images, etc.).
333
+ */
334
+ readonly multiModal: boolean;
335
+ /**
336
+ * Supports tool/function calling.
337
+ */
338
+ readonly tools?: boolean;
339
+ /**
340
+ * Maximum context window size (tokens).
341
+ */
342
+ readonly maxContextTokens?: number;
343
+ /**
344
+ * List of supported model identifiers.
345
+ */
346
+ readonly supportedModels?: readonly string[];
347
+ /**
348
+ * How system messages are handled.
349
+ */
350
+ readonly systemMessageStrategy: SystemMessageStrategy;
351
+ /**
352
+ * Supports multiple system messages.
353
+ */
354
+ readonly supportsMultipleSystemMessages: boolean;
355
+ /**
356
+ * Supports temperature parameter.
357
+ */
358
+ readonly supportsTemperature?: boolean;
359
+ /**
360
+ * Supports topP parameter.
361
+ */
362
+ readonly supportsTopP?: boolean;
363
+ /**
364
+ * Supports topK parameter.
365
+ */
366
+ readonly supportsTopK?: boolean;
367
+ /**
368
+ * Supports seed parameter.
369
+ */
370
+ readonly supportsSeed?: boolean;
371
+ /**
372
+ * Supports frequency penalty.
373
+ */
374
+ readonly supportsFrequencyPenalty?: boolean;
375
+ /**
376
+ * Supports presence penalty.
377
+ */
378
+ readonly supportsPresencePenalty?: boolean;
379
+ /**
380
+ * Maximum number of stop sequences.
381
+ */
382
+ readonly maxStopSequences?: number;
383
+ }
384
+ /**
385
+ * Warning severity levels.
386
+ */
387
+ export type WarningSeverity = 'info' | 'warning' | 'error';
388
+ /**
389
+ * Warning categories for semantic drift and compatibility issues.
390
+ */
391
+ export type WarningCategory = 'parameter-normalized' | 'parameter-clamped' | 'parameter-unsupported' | 'capability-unsupported' | 'token-limit-exceeded' | 'stop-sequences-truncated' | 'system-message-transformed' | 'content-type-unsupported' | 'tool-unsupported' | 'model-substituted';
392
+ /**
393
+ * Semantic drift warning.
394
+ *
395
+ * Documents transformations and compatibility issues that occur
396
+ * when converting between provider formats.
397
+ *
398
+ * @example
399
+ * ```typescript
400
+ * const warning: IRWarning = {
401
+ * category: 'parameter-normalized',
402
+ * severity: 'info',
403
+ * message: 'Temperature normalized from 0-2 range to 0-1 range',
404
+ * field: 'temperature',
405
+ * originalValue: 1.5,
406
+ * transformedValue: 0.75,
407
+ * source: 'openai-backend'
408
+ * };
409
+ * ```
410
+ */
411
+ export interface IRWarning {
412
+ /**
413
+ * Warning category.
414
+ */
415
+ readonly category: WarningCategory;
416
+ /**
417
+ * Severity level.
418
+ */
419
+ readonly severity: WarningSeverity;
420
+ /**
421
+ * Human-readable warning message.
422
+ */
423
+ readonly message: string;
424
+ /**
425
+ * Field or parameter that caused the warning.
426
+ */
427
+ readonly field?: string;
428
+ /**
429
+ * Original value before transformation.
430
+ */
431
+ readonly originalValue?: unknown;
432
+ /**
433
+ * Transformed value after normalization.
434
+ */
435
+ readonly transformedValue?: unknown;
436
+ /**
437
+ * Source adapter that generated the warning.
438
+ */
439
+ readonly source?: string;
440
+ /**
441
+ * Additional context or details.
442
+ */
443
+ readonly details?: Record<string, unknown>;
444
+ }
445
+ /**
446
+ * Provenance tracking for request/response chain.
447
+ */
448
+ export interface IRProvenance {
449
+ /**
450
+ * Frontend adapter name.
451
+ */
452
+ readonly frontend?: string;
453
+ /**
454
+ * Backend adapter name.
455
+ */
456
+ readonly backend?: string;
457
+ /**
458
+ * Middleware chain (in order of execution).
459
+ */
460
+ readonly middleware?: readonly string[];
461
+ /**
462
+ * Router name (if applicable).
463
+ */
464
+ readonly router?: string;
465
+ }
466
+ /**
467
+ * Request/response metadata.
468
+ *
469
+ * Tracks provenance, timing, warnings, and custom metadata throughout the adapter chain.
470
+ *
471
+ * @example
472
+ * ```typescript
473
+ * const metadata: IRMetadata = {
474
+ * requestId: 'req_abc123',
475
+ * timestamp: Date.now(),
476
+ * provenance: {
477
+ * frontend: 'anthropic',
478
+ * backend: 'openai',
479
+ * middleware: ['logging', 'caching']
480
+ * },
481
+ * warnings: [
482
+ * {
483
+ * category: 'parameter-normalized',
484
+ * severity: 'info',
485
+ * message: 'Temperature scaled from 0-2 to 0-1 range',
486
+ * field: 'temperature'
487
+ * }
488
+ * ],
489
+ * custom: {
490
+ * userId: 'user_123',
491
+ * sessionId: 'session_456'
492
+ * }
493
+ * };
494
+ * ```
495
+ */
496
+ export interface IRMetadata {
497
+ /**
498
+ * Unique request identifier.
499
+ * Generated by the client (frontend adapter or Bridge).
500
+ * Stable across retries and fallbacks for correlation.
501
+ */
502
+ readonly requestId: string;
503
+ /**
504
+ * Provider's response identifier.
505
+ * Set by backend adapter from the provider's actual response ID.
506
+ * Examples: OpenAI's "chatcmpl-xxx", Anthropic's "msg_xxx".
507
+ * Useful for correlating with provider logs and billing.
508
+ */
509
+ readonly providerResponseId?: string;
510
+ /**
511
+ * Request timestamp (milliseconds since epoch).
512
+ */
513
+ readonly timestamp: number;
514
+ /**
515
+ * Adapter chain provenance.
516
+ */
517
+ readonly provenance?: IRProvenance;
518
+ /**
519
+ * Semantic drift warnings collected during processing.
520
+ * Documents any transformations or compatibility issues.
521
+ */
522
+ readonly warnings?: readonly IRWarning[];
523
+ /**
524
+ * Custom metadata fields.
525
+ * Can be used by middleware or application code.
526
+ */
527
+ readonly custom?: Record<string, unknown>;
528
+ }
529
+ /**
530
+ * Universal chat completion request.
531
+ *
532
+ * This is the normalized format that all frontend adapters convert to
533
+ * and all backend adapters consume.
534
+ *
535
+ * @example
536
+ * ```typescript
537
+ * const request: IRChatRequest = {
538
+ * messages: [
539
+ * { role: 'system', content: 'You are helpful.' },
540
+ * { role: 'user', content: 'Hello!' }
541
+ * ],
542
+ * parameters: {
543
+ * model: 'gpt-4',
544
+ * temperature: 0.7,
545
+ * maxTokens: 1000
546
+ * },
547
+ * metadata: {
548
+ * requestId: 'req_abc123',
549
+ * timestamp: Date.now(),
550
+ * provenance: {
551
+ * frontend: 'openai'
552
+ * }
553
+ * },
554
+ * stream: false
555
+ * };
556
+ * ```
557
+ */
558
+ export interface IRChatRequest {
559
+ /**
560
+ * Conversation messages.
561
+ * Must contain at least one message.
562
+ */
563
+ readonly messages: readonly IRMessage[];
564
+ /**
565
+ * Tool/function definitions.
566
+ * Optional, for function calling.
567
+ */
568
+ readonly tools?: readonly IRTool[];
569
+ /**
570
+ * Tool choice strategy.
571
+ * - 'auto': Model decides whether to call tools
572
+ * - 'required': Model must call a tool
573
+ * - 'none': Model cannot call tools
574
+ * - { name: string }: Force specific tool
575
+ */
576
+ readonly toolChoice?: 'auto' | 'required' | 'none' | {
577
+ readonly name: string;
578
+ };
579
+ /**
580
+ * Request parameters.
581
+ */
582
+ readonly parameters?: IRParameters;
583
+ /**
584
+ * Request metadata.
585
+ */
586
+ readonly metadata: IRMetadata;
587
+ /**
588
+ * Whether to stream the response.
589
+ * @default false
590
+ */
591
+ readonly stream?: boolean;
592
+ /**
593
+ * Preferred streaming mode (hint to backend).
594
+ *
595
+ * - `delta`: Request incremental chunks only (most efficient)
596
+ * - `accumulated`: Request full accumulated text in each chunk
597
+ *
598
+ * This is a preference hint - backends may choose to:
599
+ * - Provide only delta (always safe, universal)
600
+ * - Provide both delta and accumulated (maximum flexibility)
601
+ * - Provide only accumulated (if that's native format)
602
+ *
603
+ * Frontends and wrappers can convert between modes as needed.
604
+ *
605
+ * @default 'delta'
606
+ */
607
+ readonly streamMode?: StreamMode;
608
+ }
609
+ /**
610
+ * Finish reason for generation.
611
+ */
612
+ export type FinishReason = 'stop' | 'length' | 'tool_calls' | 'content_filter' | 'error' | 'cancelled';
613
+ /**
614
+ * Token usage statistics.
615
+ */
616
+ export interface IRUsage {
617
+ /**
618
+ * Tokens in the prompt.
619
+ */
620
+ readonly promptTokens: number;
621
+ /**
622
+ * Tokens in the completion.
623
+ */
624
+ readonly completionTokens: number;
625
+ /**
626
+ * Total tokens (prompt + completion).
627
+ */
628
+ readonly totalTokens: number;
629
+ /**
630
+ * Provider-specific usage details.
631
+ */
632
+ readonly details?: Record<string, unknown>;
633
+ }
634
+ /**
635
+ * Universal chat completion response.
636
+ *
637
+ * Normalized format that all backend adapters convert to
638
+ * and all frontend adapters consume.
639
+ *
640
+ * @example
641
+ * ```typescript
642
+ * const response: IRChatResponse = {
643
+ * message: {
644
+ * role: 'assistant',
645
+ * content: 'Hello! How can I help you today?'
646
+ * },
647
+ * finishReason: 'stop',
648
+ * usage: {
649
+ * promptTokens: 15,
650
+ * completionTokens: 10,
651
+ * totalTokens: 25
652
+ * },
653
+ * metadata: {
654
+ * requestId: 'req_abc123',
655
+ * timestamp: Date.now(),
656
+ * provenance: {
657
+ * frontend: 'openai',
658
+ * backend: 'openai'
659
+ * }
660
+ * }
661
+ * };
662
+ * ```
663
+ */
664
+ export interface IRChatResponse {
665
+ /**
666
+ * Generated message from the assistant.
667
+ */
668
+ readonly message: IRMessage;
669
+ /**
670
+ * Why generation finished.
671
+ */
672
+ readonly finishReason: FinishReason;
673
+ /**
674
+ * Token usage statistics.
675
+ */
676
+ readonly usage?: IRUsage;
677
+ /**
678
+ * Response metadata.
679
+ * Includes original request metadata plus backend provenance.
680
+ */
681
+ readonly metadata: IRMetadata;
682
+ /**
683
+ * Provider-specific response data.
684
+ */
685
+ readonly raw?: Record<string, unknown>;
686
+ }
687
+ /**
688
+ * Stream chunk types.
689
+ */
690
+ export type StreamChunkType = 'start' | 'content' | 'tool_use' | 'metadata' | 'done' | 'error';
691
+ /**
692
+ * Base stream chunk interface.
693
+ */
694
+ export interface BaseStreamChunk {
695
+ readonly type: StreamChunkType;
696
+ readonly sequence: number;
697
+ }
698
+ /**
699
+ * Start of stream chunk.
700
+ */
701
+ export interface StreamStartChunk extends BaseStreamChunk {
702
+ readonly type: 'start';
703
+ readonly metadata: IRMetadata;
704
+ }
705
+ /**
706
+ * Content chunk with flexible streaming support.
707
+ *
708
+ * Supports both delta (incremental) and accumulated (full text) streaming modes:
709
+ *
710
+ * **Delta Mode (default):**
711
+ * - `delta` contains only the new text generated in this chunk
712
+ * - Consumers must accumulate deltas to get full text
713
+ * - Most efficient for network and memory
714
+ *
715
+ * **Accumulated Mode (optional):**
716
+ * - `accumulated` contains all text generated so far
717
+ * - Each chunk has the complete text up to that point
718
+ * - Useful for UIs that want to replace text (Chrome AI style)
719
+ *
720
+ * **Backward Compatibility:**
721
+ * - `delta` is ALWAYS present (universal standard)
722
+ * - `accumulated` is optional (provided when backend configured for it)
723
+ *
724
+ * @example
725
+ * ```typescript
726
+ * // Delta-only chunk (standard)
727
+ * { type: 'content', delta: ' world', sequence: 2 }
728
+ *
729
+ * // With both formats (configured backend)
730
+ * { type: 'content', delta: ' world', accumulated: 'Hello world', sequence: 2 }
731
+ * ```
732
+ */
733
+ export interface StreamContentChunk extends BaseStreamChunk {
734
+ readonly type: 'content';
735
+ /**
736
+ * Incremental text delta (new content only).
737
+ * ALWAYS present for maximum compatibility.
738
+ * Contains only the text generated in this chunk.
739
+ */
740
+ readonly delta: string;
741
+ /**
742
+ * Accumulated text (full content so far).
743
+ * Optional - provided when backend is configured for accumulated mode.
744
+ * Contains all text generated from the start up to and including this chunk.
745
+ */
746
+ readonly accumulated?: string;
747
+ readonly role?: 'assistant';
748
+ }
749
+ /**
750
+ * Tool use chunk.
751
+ */
752
+ export interface StreamToolUseChunk extends BaseStreamChunk {
753
+ readonly type: 'tool_use';
754
+ readonly id: string;
755
+ readonly name: string;
756
+ readonly inputDelta?: string;
757
+ }
758
+ /**
759
+ * Metadata chunk (usage, etc.).
760
+ */
761
+ export interface StreamMetadataChunk extends BaseStreamChunk {
762
+ readonly type: 'metadata';
763
+ readonly usage?: Partial<IRUsage>;
764
+ readonly metadata?: Partial<IRMetadata>;
765
+ }
766
+ /**
767
+ * Done chunk (end of stream).
768
+ */
769
+ export interface StreamDoneChunk extends BaseStreamChunk {
770
+ readonly type: 'done';
771
+ readonly finishReason: FinishReason;
772
+ readonly usage?: IRUsage;
773
+ readonly message?: IRMessage;
774
+ }
775
+ /**
776
+ * Error chunk.
777
+ */
778
+ export interface StreamErrorChunk extends BaseStreamChunk {
779
+ readonly type: 'error';
780
+ readonly error: {
781
+ readonly code: string;
782
+ readonly message: string;
783
+ readonly details?: Record<string, unknown>;
784
+ };
785
+ }
786
+ /**
787
+ * Union of all stream chunk types.
788
+ *
789
+ * Uses discriminated union for type-safe chunk handling.
790
+ */
791
+ export type IRStreamChunk = StreamStartChunk | StreamContentChunk | StreamToolUseChunk | StreamMetadataChunk | StreamDoneChunk | StreamErrorChunk;
792
+ /**
793
+ * Async generator for streaming responses.
794
+ *
795
+ * Yields IR stream chunks as they arrive from the backend.
796
+ *
797
+ * @example
798
+ * ```typescript
799
+ * async function processStream(stream: IRChatStream) {
800
+ * for await (const chunk of stream) {
801
+ * switch (chunk.type) {
802
+ * case 'start':
803
+ * console.log('Stream started:', chunk.metadata.requestId);
804
+ * break;
805
+ * case 'content':
806
+ * process.stdout.write(chunk.delta);
807
+ * break;
808
+ * case 'done':
809
+ * console.log('\nStream finished:', chunk.finishReason);
810
+ * break;
811
+ * case 'error':
812
+ * console.error('Stream error:', chunk.error.message);
813
+ * break;
814
+ * }
815
+ * }
816
+ * }
817
+ * ```
818
+ */
819
+ export type IRChatStream = AsyncGenerator<IRStreamChunk, void, undefined>;
820
+ //# sourceMappingURL=ir.d.ts.map