@providerprotocol/ai 0.0.6 → 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,61 @@
1
+ // ============================================
2
+ // Audio Configuration Types
3
+ // ============================================
4
+
5
+ /**
6
+ * Audio output configuration for Chat Completions
7
+ */
8
+ export interface OpenAIAudioConfig {
9
+ /** Audio format */
10
+ format: 'wav' | 'aac' | 'mp3' | 'flac' | 'opus' | 'pcm16';
11
+ /** Voice to use for audio generation */
12
+ voice:
13
+ | 'alloy'
14
+ | 'ash'
15
+ | 'ballad'
16
+ | 'coral'
17
+ | 'echo'
18
+ | 'sage'
19
+ | 'shimmer'
20
+ | 'verse'
21
+ | 'marin'
22
+ | 'cedar';
23
+ }
24
+
25
+ // ============================================
26
+ // Web Search Configuration Types
27
+ // ============================================
28
+
29
+ /**
30
+ * User location for web search context
31
+ * Requires type: 'approximate' with location fields at the same level
32
+ */
33
+ export interface OpenAIWebSearchUserLocation {
34
+ /** Location type - must be 'approximate' */
35
+ type: 'approximate';
36
+ /** City name */
37
+ city?: string;
38
+ /** ISO 3166-1 country code (e.g., "US") */
39
+ country?: string;
40
+ /** Region/state name */
41
+ region?: string;
42
+ /** IANA timezone (e.g., "America/New_York") */
43
+ timezone?: string;
44
+ }
45
+
46
+ /**
47
+ * Web search options for Chat Completions API
48
+ */
49
+ export interface OpenAIWebSearchOptions {
50
+ /**
51
+ * Context size for search results
52
+ * Controls how much context from web results to include
53
+ */
54
+ search_context_size?: 'low' | 'medium' | 'high';
55
+ /** User location for localizing search results */
56
+ user_location?: OpenAIWebSearchUserLocation | null;
57
+ }
58
+
1
59
  /**
2
60
  * OpenAI Chat Completions API parameters
3
61
  * These are passed through to the /v1/chat/completions endpoint
@@ -33,10 +91,10 @@ export interface OpenAICompletionsParams {
33
91
  /** Number of top logprobs to return (0-20) */
34
92
  top_logprobs?: number;
35
93
 
36
- /** Seed for deterministic sampling (beta) */
94
+ /** Seed for deterministic sampling (beta, deprecated) */
37
95
  seed?: number;
38
96
 
39
- /** User identifier for abuse detection */
97
+ /** User identifier (deprecated, use safety_identifier or prompt_cache_key) */
40
98
  user?: string;
41
99
 
42
100
  /** Logit bias map */
@@ -52,12 +110,12 @@ export interface OpenAICompletionsParams {
52
110
  reasoning_effort?: 'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh';
53
111
 
54
112
  /** Service tier */
55
- service_tier?: 'auto' | 'default' | 'flex' | 'priority';
113
+ service_tier?: 'auto' | 'default' | 'flex' | 'scale' | 'priority';
56
114
 
57
115
  /** Store completion for distillation */
58
116
  store?: boolean;
59
117
 
60
- /** Metadata key-value pairs */
118
+ /** Metadata key-value pairs (max 16, keys max 64 chars, values max 512 chars) */
61
119
  metadata?: Record<string, string>;
62
120
 
63
121
  /** Response format for structured output */
@@ -74,7 +132,7 @@ export interface OpenAICompletionsParams {
74
132
 
75
133
  /**
76
134
  * Stable identifier for caching similar requests
77
- * Used to optimize cache hit rates
135
+ * Used to optimize cache hit rates (replaces user field)
78
136
  */
79
137
  prompt_cache_key?: string;
80
138
 
@@ -82,13 +140,50 @@ export interface OpenAICompletionsParams {
82
140
  * Retention policy for prompt cache
83
141
  * Set to "24h" to enable extended prompt caching up to 24 hours
84
142
  */
85
- prompt_cache_retention?: '24h';
143
+ prompt_cache_retention?: 'in-memory' | '24h';
86
144
 
87
145
  /**
88
146
  * Stable identifier for abuse detection
89
147
  * Recommend hashing username or email address
90
148
  */
91
149
  safety_identifier?: string;
150
+
151
+ /**
152
+ * Output modalities to generate
153
+ * Default: ["text"]. Use ["text", "audio"] for audio-capable models
154
+ */
155
+ modalities?: Array<'text' | 'audio'>;
156
+
157
+ /**
158
+ * Audio output configuration
159
+ * Required when modalities includes "audio"
160
+ */
161
+ audio?: OpenAIAudioConfig | null;
162
+
163
+ /**
164
+ * Web search configuration
165
+ * Enables the model to search the web for up-to-date information
166
+ */
167
+ web_search_options?: OpenAIWebSearchOptions;
168
+ }
169
+
170
+ /**
171
+ * Prompt template reference for Responses API
172
+ */
173
+ export interface OpenAIPromptTemplate {
174
+ /** Prompt template ID */
175
+ id: string;
176
+ /** Variables to fill into the template */
177
+ variables?: Record<string, string>;
178
+ }
179
+
180
+ /**
181
+ * Conversation reference for Responses API
182
+ * Items from this conversation are prepended to input_items
183
+ */
184
+ export interface OpenAIConversation {
185
+ /** Conversation ID */
186
+ id: string;
92
187
  }
93
188
 
94
189
  /**
@@ -105,35 +200,108 @@ export interface OpenAIResponsesParams {
105
200
  /** Top-p (nucleus) sampling (0.0 - 1.0) */
106
201
  top_p?: number;
107
202
 
203
+ /** Number of top logprobs to return (0-20) */
204
+ top_logprobs?: number;
205
+
108
206
  /** Whether to enable parallel tool calls */
109
207
  parallel_tool_calls?: boolean;
110
208
 
111
- /** Reasoning configuration */
209
+ /** Reasoning configuration (for gpt-5 and o-series models) */
112
210
  reasoning?: {
113
211
  effort?: 'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh';
114
- summary?: string;
212
+ /** Include summary of reasoning */
213
+ summary?: 'auto' | 'concise' | 'detailed';
115
214
  };
116
215
 
117
216
  /** Service tier */
118
- service_tier?: 'auto' | 'default' | 'flex' | 'priority';
217
+ service_tier?: 'auto' | 'default' | 'flex' | 'scale' | 'priority';
119
218
 
120
219
  /** Truncation strategy */
121
220
  truncation?: 'auto' | 'disabled';
122
221
 
123
- /** Fields to include in output */
222
+ /**
223
+ * Fields to include in output
224
+ * Supported values:
225
+ * - 'web_search_call.action.sources': Include web search sources
226
+ * - 'code_interpreter_call.outputs': Include code execution outputs
227
+ * - 'computer_call_output.output.image_url': Include computer call images
228
+ * - 'file_search_call.results': Include file search results
229
+ * - 'message.input_image.image_url': Include input image URLs
230
+ * - 'message.output_text.logprobs': Include logprobs with messages
231
+ * - 'reasoning.encrypted_content': Include encrypted reasoning tokens
232
+ */
124
233
  include?: string[];
125
234
 
126
- /** Background processing */
235
+ /** Background processing - run response asynchronously */
127
236
  background?: boolean;
128
237
 
129
- /** Continue from a previous response */
238
+ /** Continue from a previous response (cannot use with conversation) */
130
239
  previous_response_id?: string;
131
240
 
241
+ /**
242
+ * Conversation context - items prepended to input_items
243
+ * Cannot be used with previous_response_id
244
+ */
245
+ conversation?: string | OpenAIConversation;
246
+
132
247
  /** Store response for continuation */
133
248
  store?: boolean;
134
249
 
135
- /** Metadata key-value pairs */
250
+ /** Metadata key-value pairs (max 16, keys max 64 chars, values max 512 chars) */
136
251
  metadata?: Record<string, string>;
252
+
253
+ /**
254
+ * Maximum total calls to built-in tools in a response
255
+ * Applies across all built-in tool calls, not per tool
256
+ */
257
+ max_tool_calls?: number;
258
+
259
+ /**
260
+ * Reference to a prompt template and its variables
261
+ */
262
+ prompt?: OpenAIPromptTemplate;
263
+
264
+ /**
265
+ * Stable identifier for caching similar requests
266
+ * Used to optimize cache hit rates (replaces user field)
267
+ */
268
+ prompt_cache_key?: string;
269
+
270
+ /**
271
+ * Retention policy for prompt cache
272
+ * Set to "24h" to enable extended prompt caching up to 24 hours
273
+ */
274
+ prompt_cache_retention?: 'in-memory' | '24h';
275
+
276
+ /**
277
+ * Stable identifier for abuse detection
278
+ * Recommend hashing username or email address
279
+ */
280
+ safety_identifier?: string;
281
+
282
+ /** User identifier (deprecated, use safety_identifier or prompt_cache_key) */
283
+ user?: string;
284
+
285
+ /**
286
+ * Built-in tools for the Responses API
287
+ * Use the tool helper constructors: tools.webSearch(), tools.imageGeneration(), etc.
288
+ *
289
+ * @example
290
+ * ```ts
291
+ * import { tools } from 'provider-protocol/openai';
292
+ *
293
+ * const model = llm({
294
+ * model: openai('gpt-4o'),
295
+ * params: {
296
+ * tools: [
297
+ * tools.webSearch(),
298
+ * tools.imageGeneration({ quality: 'high' }),
299
+ * ],
300
+ * },
301
+ * });
302
+ * ```
303
+ */
304
+ tools?: OpenAIBuiltInTool[];
137
305
  }
138
306
 
139
307
  /**
@@ -210,6 +378,12 @@ export interface OpenAICompletionsRequest {
210
378
  prompt_cache_retention?: string;
211
379
  /** Stable identifier for abuse detection */
212
380
  safety_identifier?: string;
381
+ /** Output modalities (text, audio) */
382
+ modalities?: Array<'text' | 'audio'>;
383
+ /** Audio output configuration */
384
+ audio?: OpenAIAudioConfig | null;
385
+ /** Web search configuration */
386
+ web_search_options?: OpenAIWebSearchOptions;
213
387
  }
214
388
 
215
389
  /**
@@ -422,8 +596,9 @@ export interface OpenAIResponsesRequest {
422
596
  max_output_tokens?: number;
423
597
  temperature?: number;
424
598
  top_p?: number;
599
+ top_logprobs?: number;
425
600
  stream?: boolean;
426
- tools?: OpenAIResponsesTool[];
601
+ tools?: OpenAIResponsesToolUnion[];
427
602
  tool_choice?: OpenAIResponsesToolChoice;
428
603
  parallel_tool_calls?: boolean;
429
604
  text?: OpenAIResponsesTextConfig;
@@ -432,12 +607,26 @@ export interface OpenAIResponsesRequest {
432
607
  metadata?: Record<string, string>;
433
608
  reasoning?: {
434
609
  effort?: 'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh';
435
- summary?: string;
610
+ summary?: 'auto' | 'concise' | 'detailed';
436
611
  };
437
612
  service_tier?: string;
438
613
  include?: string[];
439
614
  background?: boolean;
440
615
  previous_response_id?: string;
616
+ /** Conversation context (cannot use with previous_response_id) */
617
+ conversation?: string | OpenAIConversation;
618
+ /** Maximum total calls to built-in tools */
619
+ max_tool_calls?: number;
620
+ /** Prompt template reference */
621
+ prompt?: OpenAIPromptTemplate;
622
+ /** Stable identifier for caching (replaces user) */
623
+ prompt_cache_key?: string;
624
+ /** Retention policy for prompt cache */
625
+ prompt_cache_retention?: 'in-memory' | '24h';
626
+ /** Stable identifier for abuse detection */
627
+ safety_identifier?: string;
628
+ /** User identifier (deprecated) */
629
+ user?: string;
441
630
  }
442
631
 
443
632
  /**
@@ -573,7 +762,9 @@ export interface OpenAIResponsesResponse {
573
762
 
574
763
  export type OpenAIResponsesOutputItem =
575
764
  | OpenAIResponsesMessageOutput
576
- | OpenAIResponsesFunctionCallOutput;
765
+ | OpenAIResponsesFunctionCallOutput
766
+ | OpenAIResponsesImageGenerationOutput
767
+ | OpenAIResponsesWebSearchOutput;
577
768
 
578
769
  export interface OpenAIResponsesMessageOutput {
579
770
  type: 'message';
@@ -592,6 +783,19 @@ export interface OpenAIResponsesFunctionCallOutput {
592
783
  status: 'completed' | 'in_progress';
593
784
  }
594
785
 
786
+ export interface OpenAIResponsesImageGenerationOutput {
787
+ type: 'image_generation_call';
788
+ id: string;
789
+ result?: string;
790
+ status: 'completed' | 'in_progress';
791
+ }
792
+
793
+ export interface OpenAIResponsesWebSearchOutput {
794
+ type: 'web_search_call';
795
+ id: string;
796
+ status: 'completed' | 'in_progress';
797
+ }
798
+
595
799
  export type OpenAIResponsesOutputContent =
596
800
  | { type: 'output_text'; text: string; annotations?: unknown[] }
597
801
  | { type: 'refusal'; refusal: string };
@@ -732,3 +936,293 @@ export interface OpenAIResponseErrorEvent {
732
936
  message: string;
733
937
  };
734
938
  }
939
+
940
+ // ============================================
941
+ // Built-in Tools for Responses API
942
+ // ============================================
943
+
944
+ /**
945
+ * Web search tool for Responses API
946
+ * Enables the model to search the web for up-to-date information
947
+ */
948
+ export interface OpenAIWebSearchTool {
949
+ type: 'web_search';
950
+ /**
951
+ * Context size for search results
952
+ * Controls how much context from web results to include
953
+ */
954
+ search_context_size?: 'low' | 'medium' | 'high';
955
+ /** User location for localizing search results */
956
+ user_location?: OpenAIWebSearchUserLocation | null;
957
+ }
958
+
959
+ /**
960
+ * File search tool for Responses API
961
+ * Enables the model to search through uploaded files
962
+ */
963
+ export interface OpenAIFileSearchTool {
964
+ type: 'file_search';
965
+ /** File search configuration */
966
+ file_search?: {
967
+ /** Vector store IDs to search */
968
+ vector_store_ids: string[];
969
+ /** Maximum number of results to return */
970
+ max_num_results?: number;
971
+ /** Ranking options for search results */
972
+ ranking_options?: {
973
+ /** Ranker to use */
974
+ ranker?: 'auto' | 'default_2024_08_21';
975
+ /** Score threshold (0-1) */
976
+ score_threshold?: number;
977
+ };
978
+ /** Filters to apply */
979
+ filters?: Record<string, unknown>;
980
+ };
981
+ }
982
+
983
+ /**
984
+ * Code interpreter container configuration
985
+ */
986
+ export interface OpenAICodeInterpreterContainer {
987
+ /** Container type - 'auto' creates a new container */
988
+ type: 'auto';
989
+ /** Memory limit for the container (e.g., '1g', '4g') */
990
+ memory_limit?: string;
991
+ /** File IDs to make available in the container */
992
+ file_ids?: string[];
993
+ }
994
+
995
+ /**
996
+ * Code interpreter tool for Responses API
997
+ * Allows the model to write and run Python code
998
+ */
999
+ export interface OpenAICodeInterpreterTool {
1000
+ type: 'code_interpreter';
1001
+ /** Code interpreter configuration */
1002
+ code_interpreter?: {
1003
+ /** Container configuration */
1004
+ container: string | OpenAICodeInterpreterContainer;
1005
+ };
1006
+ }
1007
+
1008
+ /**
1009
+ * Computer tool environment configuration
1010
+ */
1011
+ export interface OpenAIComputerEnvironment {
1012
+ /** Environment type */
1013
+ type: 'browser' | 'mac' | 'windows' | 'linux' | 'ubuntu';
1014
+ }
1015
+
1016
+ /**
1017
+ * Computer tool for Responses API
1018
+ * Enables the model to interact with computer interfaces
1019
+ */
1020
+ export interface OpenAIComputerTool {
1021
+ type: 'computer';
1022
+ /** Computer tool configuration */
1023
+ computer?: {
1024
+ /** Display width in pixels */
1025
+ display_width: number;
1026
+ /** Display height in pixels */
1027
+ display_height: number;
1028
+ /** Environment configuration */
1029
+ environment?: OpenAIComputerEnvironment;
1030
+ };
1031
+ }
1032
+
1033
+ /**
1034
+ * Image generation tool for Responses API
1035
+ */
1036
+ export interface OpenAIImageGenerationTool {
1037
+ type: 'image_generation';
1038
+ /** Background transparency */
1039
+ background?: 'transparent' | 'opaque' | 'auto';
1040
+ /** Input image formats supported */
1041
+ input_image_mask?: boolean;
1042
+ /** Model to use for generation */
1043
+ model?: string;
1044
+ /** Moderation level */
1045
+ moderation?: 'auto' | 'low';
1046
+ /** Output compression */
1047
+ output_compression?: number;
1048
+ /** Output format */
1049
+ output_format?: 'png' | 'jpeg' | 'webp';
1050
+ /** Partial images during streaming */
1051
+ partial_images?: number;
1052
+ /** Image quality */
1053
+ quality?: 'auto' | 'high' | 'medium' | 'low';
1054
+ /** Image size */
1055
+ size?: 'auto' | '1024x1024' | '1024x1536' | '1536x1024';
1056
+ }
1057
+
1058
+ /**
1059
+ * MCP (Model Context Protocol) server configuration
1060
+ */
1061
+ export interface OpenAIMcpServerConfig {
1062
+ /** Server URL */
1063
+ url: string;
1064
+ /** Server name for identification */
1065
+ name?: string;
1066
+ /** Tool configuration for the server */
1067
+ tool_configuration?: {
1068
+ /** Allowed tools from this server */
1069
+ allowed_tools?: string[] | { type: 'all' };
1070
+ };
1071
+ /** Headers to send with requests */
1072
+ headers?: Record<string, string>;
1073
+ /** Allowed resources */
1074
+ allowed_resources?: string[];
1075
+ /** Require approval for tool calls */
1076
+ require_approval?: 'always' | 'never' | { type: 'except'; tools: string[] };
1077
+ }
1078
+
1079
+ /**
1080
+ * MCP tool for Responses API
1081
+ * Enables connections to MCP servers
1082
+ */
1083
+ export interface OpenAIMcpTool {
1084
+ type: 'mcp';
1085
+ /** MCP server configurations */
1086
+ mcp?: {
1087
+ /** Server configuration */
1088
+ server: OpenAIMcpServerConfig;
1089
+ };
1090
+ }
1091
+
1092
+ /**
1093
+ * Union type for all Responses API built-in tools
1094
+ */
1095
+ export type OpenAIBuiltInTool =
1096
+ | OpenAIWebSearchTool
1097
+ | OpenAIFileSearchTool
1098
+ | OpenAICodeInterpreterTool
1099
+ | OpenAIComputerTool
1100
+ | OpenAIImageGenerationTool
1101
+ | OpenAIMcpTool;
1102
+
1103
+ /**
1104
+ * Combined tool type for Responses API (built-in or function)
1105
+ */
1106
+ export type OpenAIResponsesToolUnion = OpenAIResponsesTool | OpenAIBuiltInTool;
1107
+
1108
+ // ============================================
1109
+ // Tool Helper Constructors
1110
+ // ============================================
1111
+
1112
+ /**
1113
+ * Helper to create a web search tool
1114
+ * Note: Configuration options are passed at the top level, not nested
1115
+ */
1116
+ export function webSearchTool(options?: {
1117
+ search_context_size?: 'low' | 'medium' | 'high';
1118
+ user_location?: OpenAIWebSearchUserLocation | null;
1119
+ }): OpenAIWebSearchTool {
1120
+ if (options) {
1121
+ return {
1122
+ type: 'web_search',
1123
+ ...options,
1124
+ } as OpenAIWebSearchTool;
1125
+ }
1126
+ return { type: 'web_search' };
1127
+ }
1128
+
1129
+ /**
1130
+ * Helper to create a file search tool
1131
+ */
1132
+ export function fileSearchTool(options: {
1133
+ vector_store_ids: string[];
1134
+ max_num_results?: number;
1135
+ ranking_options?: {
1136
+ ranker?: 'auto' | 'default_2024_08_21';
1137
+ score_threshold?: number;
1138
+ };
1139
+ filters?: Record<string, unknown>;
1140
+ }): OpenAIFileSearchTool {
1141
+ return {
1142
+ type: 'file_search',
1143
+ file_search: options,
1144
+ };
1145
+ }
1146
+
1147
+ /**
1148
+ * Helper to create a code interpreter tool
1149
+ */
1150
+ export function codeInterpreterTool(options?: {
1151
+ container?: string | OpenAICodeInterpreterContainer;
1152
+ }): OpenAICodeInterpreterTool {
1153
+ return {
1154
+ type: 'code_interpreter',
1155
+ ...(options?.container && { code_interpreter: { container: options.container } }),
1156
+ };
1157
+ }
1158
+
1159
+ /**
1160
+ * Helper to create a computer tool
1161
+ */
1162
+ export function computerTool(options: {
1163
+ display_width: number;
1164
+ display_height: number;
1165
+ environment?: OpenAIComputerEnvironment;
1166
+ }): OpenAIComputerTool {
1167
+ return {
1168
+ type: 'computer',
1169
+ computer: options,
1170
+ };
1171
+ }
1172
+
1173
+ /**
1174
+ * Helper to create an image generation tool
1175
+ * Note: Configuration options are passed at the top level, not nested
1176
+ */
1177
+ export function imageGenerationTool(options?: {
1178
+ background?: 'transparent' | 'opaque' | 'auto';
1179
+ model?: string;
1180
+ quality?: 'auto' | 'high' | 'medium' | 'low';
1181
+ size?: 'auto' | '1024x1024' | '1024x1536' | '1536x1024';
1182
+ output_format?: 'png' | 'jpeg' | 'webp';
1183
+ }): OpenAIImageGenerationTool {
1184
+ if (options) {
1185
+ return {
1186
+ type: 'image_generation',
1187
+ ...options,
1188
+ };
1189
+ }
1190
+ return { type: 'image_generation' };
1191
+ }
1192
+
1193
+ /**
1194
+ * Helper to create an MCP tool
1195
+ */
1196
+ export function mcpTool(options: {
1197
+ url: string;
1198
+ name?: string;
1199
+ allowed_tools?: string[] | { type: 'all' };
1200
+ headers?: Record<string, string>;
1201
+ require_approval?: 'always' | 'never' | { type: 'except'; tools: string[] };
1202
+ }): OpenAIMcpTool {
1203
+ const { url, name, allowed_tools, headers, require_approval } = options;
1204
+ return {
1205
+ type: 'mcp',
1206
+ mcp: {
1207
+ server: {
1208
+ url,
1209
+ name,
1210
+ ...(allowed_tools && { tool_configuration: { allowed_tools } }),
1211
+ headers,
1212
+ require_approval,
1213
+ },
1214
+ },
1215
+ };
1216
+ }
1217
+
1218
+ /**
1219
+ * Namespace for tool helper constructors
1220
+ */
1221
+ export const tools = {
1222
+ webSearch: webSearchTool,
1223
+ fileSearch: fileSearchTool,
1224
+ codeInterpreter: codeInterpreterTool,
1225
+ computer: computerTool,
1226
+ imageGeneration: imageGenerationTool,
1227
+ mcp: mcpTool,
1228
+ };
@@ -2,9 +2,11 @@ import { generateId } from '../utils/id.ts';
2
2
  import type {
3
3
  ContentBlock,
4
4
  TextBlock,
5
+ ImageBlock,
6
+ AudioBlock,
7
+ VideoBlock,
5
8
  UserContent,
6
9
  AssistantContent,
7
- isTextBlock,
8
10
  } from './content.ts';
9
11
  import type { ToolCall, ToolResult } from './tool.ts';
10
12
 
@@ -65,6 +67,27 @@ export abstract class Message {
65
67
  .map((block) => block.text)
66
68
  .join('\n\n');
67
69
  }
70
+
71
+ /**
72
+ * Convenience accessor for image content blocks
73
+ */
74
+ get images(): ImageBlock[] {
75
+ return this.getContent().filter((block): block is ImageBlock => block.type === 'image');
76
+ }
77
+
78
+ /**
79
+ * Convenience accessor for audio content blocks
80
+ */
81
+ get audio(): AudioBlock[] {
82
+ return this.getContent().filter((block): block is AudioBlock => block.type === 'audio');
83
+ }
84
+
85
+ /**
86
+ * Convenience accessor for video content blocks
87
+ */
88
+ get video(): VideoBlock[] {
89
+ return this.getContent().filter((block): block is VideoBlock => block.type === 'video');
90
+ }
68
91
  }
69
92
 
70
93
  /**
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/utils/id.ts","../src/types/messages.ts"],"sourcesContent":["/**\n * Generate a unique ID\n * Uses crypto.randomUUID if available, falls back to a simple implementation\n */\nexport function generateId(): string {\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n\n // Fallback for environments without crypto.randomUUID\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\n/**\n * Generate a short ID (for tool call IDs, etc.)\n */\nexport function generateShortId(prefix = ''): string {\n const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n let result = prefix;\n for (let i = 0; i < 12; i++) {\n result += chars.charAt(Math.floor(Math.random() * chars.length));\n }\n return result;\n}\n","import { generateId } from '../utils/id.ts';\nimport type {\n ContentBlock,\n TextBlock,\n UserContent,\n AssistantContent,\n isTextBlock,\n} from './content.ts';\nimport type { ToolCall, ToolResult } from './tool.ts';\n\n/**\n * Message type discriminator\n */\nexport type MessageType = 'user' | 'assistant' | 'tool_result';\n\n/**\n * Provider-namespaced metadata\n * Each provider uses its own namespace\n */\nexport interface MessageMetadata {\n [provider: string]: Record<string, unknown> | undefined;\n}\n\n/**\n * Options for message construction\n */\nexport interface MessageOptions {\n id?: string;\n metadata?: MessageMetadata;\n}\n\n/**\n * Base message class\n * All messages inherit from this\n */\nexport abstract class Message {\n /** Unique message identifier */\n readonly id: string;\n\n /** Timestamp */\n readonly timestamp: Date;\n\n /** Provider-specific metadata, namespaced by provider */\n readonly metadata?: MessageMetadata;\n\n /** Message type discriminator */\n abstract readonly type: MessageType;\n\n /** Raw content - implemented by subclasses */\n protected abstract getContent(): ContentBlock[];\n\n constructor(options?: MessageOptions) {\n this.id = options?.id ?? generateId();\n this.timestamp = new Date();\n this.metadata = options?.metadata;\n }\n\n /**\n * Convenience accessor for text content\n * Concatenates all text blocks with '\\n\\n'\n */\n get text(): string {\n return this.getContent()\n .filter((block): block is TextBlock => block.type === 'text')\n .map((block) => block.text)\n .join('\\n\\n');\n }\n}\n\n/**\n * User input message\n */\nexport class UserMessage extends Message {\n readonly type = 'user' as const;\n readonly content: UserContent[];\n\n /**\n * @param content - String (converted to TextBlock) or array of content blocks\n */\n constructor(content: string | UserContent[], options?: MessageOptions) {\n super(options);\n if (typeof content === 'string') {\n this.content = [{ type: 'text', text: content }];\n } else {\n this.content = content;\n }\n }\n\n protected getContent(): ContentBlock[] {\n return this.content;\n }\n}\n\n/**\n * Assistant response message\n * May contain text, media, and/or tool calls\n */\nexport class AssistantMessage extends Message {\n readonly type = 'assistant' as const;\n readonly content: AssistantContent[];\n\n /** Tool calls requested by the model (if any) */\n readonly toolCalls?: ToolCall[];\n\n /**\n * @param content - String (converted to TextBlock) or array of content blocks\n * @param toolCalls - Tool calls requested by the model\n * @param options - Message ID and metadata\n */\n constructor(\n content: string | AssistantContent[],\n toolCalls?: ToolCall[],\n options?: MessageOptions\n ) {\n super(options);\n if (typeof content === 'string') {\n this.content = [{ type: 'text', text: content }];\n } else {\n this.content = content;\n }\n this.toolCalls = toolCalls;\n }\n\n protected getContent(): ContentBlock[] {\n return this.content;\n }\n\n /** Check if this message requests tool execution */\n get hasToolCalls(): boolean {\n return this.toolCalls !== undefined && this.toolCalls.length > 0;\n }\n}\n\n/**\n * Result of tool execution (sent back to model)\n */\nexport class ToolResultMessage extends Message {\n readonly type = 'tool_result' as const;\n readonly results: ToolResult[];\n\n /**\n * @param results - Array of tool execution results\n * @param options - Message ID and metadata\n */\n constructor(results: ToolResult[], options?: MessageOptions) {\n super(options);\n this.results = results;\n }\n\n protected getContent(): ContentBlock[] {\n // Tool results don't have traditional content blocks\n // Return text representations of results\n return this.results.map((result) => ({\n type: 'text' as const,\n text:\n typeof result.result === 'string'\n ? result.result\n : JSON.stringify(result.result),\n }));\n }\n}\n\n/**\n * Type guard for UserMessage\n */\nexport function isUserMessage(msg: Message): msg is UserMessage {\n return msg.type === 'user';\n}\n\n/**\n * Type guard for AssistantMessage\n */\nexport function isAssistantMessage(msg: Message): msg is AssistantMessage {\n return msg.type === 'assistant';\n}\n\n/**\n * Type guard for ToolResultMessage\n */\nexport function isToolResultMessage(msg: Message): msg is ToolResultMessage {\n return msg.type === 'tool_result';\n}\n"],"mappings":";AAIO,SAAS,aAAqB;AACnC,MAAI,OAAO,WAAW,eAAe,OAAO,YAAY;AACtD,WAAO,OAAO,WAAW;AAAA,EAC3B;AAGA,SAAO,uCAAuC,QAAQ,SAAS,CAAC,MAAM;AACpE,UAAM,IAAK,KAAK,OAAO,IAAI,KAAM;AACjC,UAAM,IAAI,MAAM,MAAM,IAAK,IAAI,IAAO;AACtC,WAAO,EAAE,SAAS,EAAE;AAAA,EACtB,CAAC;AACH;;;ACoBO,IAAe,UAAf,MAAuB;AAAA;AAAA,EAEnB;AAAA;AAAA,EAGA;AAAA;AAAA,EAGA;AAAA,EAQT,YAAY,SAA0B;AACpC,SAAK,KAAK,SAAS,MAAM,WAAW;AACpC,SAAK,YAAY,oBAAI,KAAK;AAC1B,SAAK,WAAW,SAAS;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,OAAe;AACjB,WAAO,KAAK,WAAW,EACpB,OAAO,CAAC,UAA8B,MAAM,SAAS,MAAM,EAC3D,IAAI,CAAC,UAAU,MAAM,IAAI,EACzB,KAAK,MAAM;AAAA,EAChB;AACF;AAKO,IAAM,cAAN,cAA0B,QAAQ;AAAA,EAC9B,OAAO;AAAA,EACP;AAAA;AAAA;AAAA;AAAA,EAKT,YAAY,SAAiC,SAA0B;AACrE,UAAM,OAAO;AACb,QAAI,OAAO,YAAY,UAAU;AAC/B,WAAK,UAAU,CAAC,EAAE,MAAM,QAAQ,MAAM,QAAQ,CAAC;AAAA,IACjD,OAAO;AACL,WAAK,UAAU;AAAA,IACjB;AAAA,EACF;AAAA,EAEU,aAA6B;AACrC,WAAO,KAAK;AAAA,EACd;AACF;AAMO,IAAM,mBAAN,cAA+B,QAAQ;AAAA,EACnC,OAAO;AAAA,EACP;AAAA;AAAA,EAGA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOT,YACE,SACA,WACA,SACA;AACA,UAAM,OAAO;AACb,QAAI,OAAO,YAAY,UAAU;AAC/B,WAAK,UAAU,CAAC,EAAE,MAAM,QAAQ,MAAM,QAAQ,CAAC;AAAA,IACjD,OAAO;AACL,WAAK,UAAU;AAAA,IACjB;AACA,SAAK,YAAY;AAAA,EACnB;AAAA,EAEU,aAA6B;AACrC,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,IAAI,eAAwB;AAC1B,WAAO,KAAK,cAAc,UAAa,KAAK,UAAU,SAAS;AAAA,EACjE;AACF;AAKO,IAAM,oBAAN,cAAgC,QAAQ;AAAA,EACpC,OAAO;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA,EAMT,YAAY,SAAuB,SAA0B;AAC3D,UAAM,OAAO;AACb,SAAK,UAAU;AAAA,EACjB;AAAA,EAEU,aAA6B;AAGrC,WAAO,KAAK,QAAQ,IAAI,CAAC,YAAY;AAAA,MACnC,MAAM;AAAA,MACN,MACE,OAAO,OAAO,WAAW,WACrB,OAAO,SACP,KAAK,UAAU,OAAO,MAAM;AAAA,IACpC,EAAE;AAAA,EACJ;AACF;AAKO,SAAS,cAAc,KAAkC;AAC9D,SAAO,IAAI,SAAS;AACtB;AAKO,SAAS,mBAAmB,KAAuC;AACxE,SAAO,IAAI,SAAS;AACtB;AAKO,SAAS,oBAAoB,KAAwC;AAC1E,SAAO,IAAI,SAAS;AACtB;","names":[]}