@robota-sdk/agent-provider-openai 3.0.0-beta.59 → 3.0.0-beta.60

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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @robota-sdk/agent-provider-openai
2
2
 
3
+ ## 3.0.0-beta.60
4
+
5
+ ### Minor Changes
6
+
7
+ - 7439391: Add provider-neutral native web search/fetch capability contracts, explicit unsupported handling for OpenAI-compatible/LM Studio profiles, and local WebFetch/WebSearch permission/documentation alignment.
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [7439391]
12
+ - @robota-sdk/agent-core@3.0.0-beta.60
13
+ - @robota-sdk/agent-provider-openai-compatible@3.0.0-beta.60
14
+
3
15
  ## 3.0.0-beta.59
4
16
 
5
17
  ### Patch Changes
package/README.md CHANGED
@@ -1,21 +1,23 @@
1
1
  # @robota-sdk/agent-provider-openai
2
2
 
3
- OpenAI Provider for Robota SDK - Complete type-safe integration with OpenAI's GPT models, featuring function calling, streaming, and advanced AI capabilities.
3
+ OpenAI Provider for Robota SDK - type-safe integration with the official OpenAI Responses API, structured outputs, streaming, and function calling.
4
4
 
5
5
  ## 🚀 Features
6
6
 
7
7
  ### Core Capabilities
8
8
 
9
9
  - **🎯 Type-Safe Integration**: Complete TypeScript support with zero `any` types
10
- - **🤖 GPT Model Support**: GPT-4, GPT-3.5 Turbo, OpenAI models, and OpenAI-compatible chat completion models
10
+ - **🤖 OpenAI Model Support**: Official OpenAI models through the Responses API by default
11
11
  - **⚡ Real-Time Streaming**: Asynchronous streaming responses with proper error handling
12
12
  - **🛠️ Function Calling**: Native OpenAI function calling with type validation
13
+ - **🧩 Structured Outputs**: JSON object and JSON Schema response formats
14
+ - **🌐 Capability Reporting**: Explicit native web search/fetch capability state without hidden local-tool fallback
13
15
  - **🔄 Provider-Agnostic Design**: Seamless integration with other Robota providers
14
16
  - **📊 Payload Logging**: Optional API request/response logging for debugging
15
17
 
16
18
  ### Architecture Highlights
17
19
 
18
- - **Generic Type Parameters**: Full `BaseAIProvider<TConfig, TMessage, TResponse>` implementation
20
+ - **Provider Base Contract**: `AbstractAIProvider` implementation for the Robota provider interface
19
21
  - **Facade Pattern**: Modular design with separated concerns
20
22
  - **Error Safety**: Comprehensive error handling without any-type compromises
21
23
  - **OpenAI SDK Compatibility**: Direct integration with official OpenAI SDK types
@@ -37,6 +39,7 @@ import { OpenAIProvider } from '@robota-sdk/agent-provider-openai';
37
39
  // Create type-safe OpenAI provider
38
40
  const provider = new OpenAIProvider({
39
41
  apiKey: process.env.OPENAI_API_KEY,
42
+ defaultModel: 'gpt-4o',
40
43
  });
41
44
 
42
45
  // Create Robota agent with OpenAI provider
@@ -45,7 +48,7 @@ const agent = new Robota({
45
48
  aiProviders: [provider],
46
49
  defaultModel: {
47
50
  provider: 'openai',
48
- model: 'gpt-4',
51
+ model: 'gpt-4o',
49
52
  temperature: 0.7,
50
53
  systemMessage: 'You are a helpful AI assistant specialized in technical topics.',
51
54
  },
@@ -61,7 +64,7 @@ await agent.destroy();
61
64
 
62
65
  ### OpenAI-Compatible Endpoints
63
66
 
64
- Use `baseURL` to point the provider at an OpenAI-compatible Chat Completions endpoint. For LM Studio, the local API typically listens on `http://localhost:1234/v1` and accepts a local placeholder API key:
67
+ The official OpenAI profile uses the Responses API by default. Set `baseURL`, or set `apiSurface: 'chat-completions'`, only when you intentionally need an OpenAI-compatible Chat Completions endpoint. For LM Studio, the local API typically listens on `http://localhost:1234/v1` and accepts a local placeholder API key:
65
68
 
66
69
  ```typescript
67
70
  import { OpenAIProvider } from '@robota-sdk/agent-provider-openai';
@@ -77,7 +80,9 @@ Gemma-family local models should use `@robota-sdk/agent-provider-gemma` instead
77
80
  OpenAI provider so Gemma chat-template channel markers are projected out of user-facing
78
81
  streamed text.
79
82
 
80
- For provider packages that share OpenAI-compatible transport code, the reusable primitives live in `@robota-sdk/agent-provider-openai-compatible`. This package owns OpenAI product semantics and generic OpenAI-compatible endpoint usage; model-family behavior such as Gemma reasoning/tool-call projection belongs in that model-family provider.
83
+ For provider packages that share OpenAI-compatible transport code, the reusable primitives live in `@robota-sdk/agent-provider-openai-compatible`. This package owns OpenAI product semantics and an explicit compatibility mode; model-family behavior such as Gemma reasoning/tool-call projection belongs in that model-family provider.
84
+
85
+ OpenAI-compatible Chat Completions profiles, including LM Studio-style `baseURL` profiles, are custom function-tool capable but are not treated as provider-native hosted web search/fetch providers. Use Robota local `WebSearch`/`WebFetch` tools for explicit local web access unless a concrete provider package documents hosted web support.
81
86
 
82
87
  ### Streaming Responses
83
88
 
@@ -97,7 +102,7 @@ for await (const chunk of stream) {
97
102
  }
98
103
  ```
99
104
 
100
- When `chat()` receives an `onTextDelta` callback, the provider uses the streaming Chat Completions path internally, forwards text deltas to the callback, assembles streamed tool-call chunks, and returns the final assistant message.
105
+ When `chat()` receives an `onTextDelta` callback, the provider uses the selected API surface's streaming path internally, forwards text deltas to the callback, assembles streamed tool-call chunks, and returns the final assistant message.
101
106
 
102
107
  ## 🛠️ Function Calling
103
108
 
@@ -179,12 +184,12 @@ const agent = new Robota({
179
184
  aiProviders: [openaiProvider, anthropicProvider, googleProvider],
180
185
  defaultModel: {
181
186
  provider: 'openai',
182
- model: 'gpt-4',
187
+ model: 'gpt-4o',
183
188
  },
184
189
  });
185
190
 
186
191
  // Dynamic provider switching
187
- const openaiResponse = await agent.run('Respond using GPT-4');
192
+ const openaiResponse = await agent.run('Respond using GPT-4o');
188
193
 
189
194
  agent.setModel({ provider: 'anthropic', model: 'claude-3-sonnet-20240229' });
190
195
  const claudeResponse = await agent.run('Respond using Claude');
@@ -194,19 +199,16 @@ const claudeResponse = await agent.run('Respond using Claude');
194
199
 
195
200
  ```typescript
196
201
  interface IOpenAIProviderOptions {
197
- // Required
198
- client: OpenAI; // OpenAI SDK client instance
199
-
200
202
  // Model Configuration
201
- model?: string; // Default: 'gpt-4'
202
- temperature?: number; // 0-1, default: 0.7
203
- maxTokens?: number; // Maximum tokens to generate
203
+ defaultModel?: string; // Used when chat options do not provide a model
204
204
 
205
205
  // API Configuration
206
206
  apiKey?: string; // API key (if not set in client)
207
+ client?: OpenAI; // OpenAI SDK client instance
207
208
  organization?: string; // OpenAI organization ID
208
209
  timeout?: number; // Request timeout (ms)
209
- baseURL?: string; // Custom API base URL
210
+ baseURL?: string; // Custom API base URL; defaults to Chat Completions compatibility
211
+ apiSurface?: 'responses' | 'chat-completions';
210
212
 
211
213
  // Response Configuration
212
214
  responseFormat?: 'text' | 'json_object' | 'json_schema';
@@ -217,6 +219,13 @@ interface IOpenAIProviderOptions {
217
219
  schema?: Record<string, string | number | boolean | object>;
218
220
  strict?: boolean;
219
221
  };
222
+ reasoning?: {
223
+ effort?: 'low' | 'medium' | 'high';
224
+ summary?: 'auto' | 'concise' | 'detailed';
225
+ };
226
+ store?: boolean;
227
+ includeEncryptedReasoning?: boolean;
228
+ strictTools?: boolean;
220
229
 
221
230
  // Debugging & Logging
222
231
  payloadLogger?: IPayloadLogger; // Environment-specific payload logger
@@ -228,31 +237,26 @@ interface IOpenAIProviderOptions {
228
237
  }
229
238
  ```
230
239
 
231
- ## 📋 Supported Models
240
+ ## 📋 Model Guidance
232
241
 
233
- | Model | Description | Use Cases |
234
- | ---------------------- | -------------------- | ------------------------------------------- |
235
- | `gpt-4` | Most capable model | Complex reasoning, analysis, creative tasks |
236
- | `gpt-4-turbo` | Faster GPT-4 variant | Balanced performance and cost |
237
- | `gpt-3.5-turbo` | Fast and efficient | Simple conversations, basic tasks |
238
- | `gpt-4-vision-preview` | Vision capabilities | Image analysis and understanding |
242
+ | Model | Description | Use Cases |
243
+ | --------- | --------------------- | ------------------------------------------- |
244
+ | `gpt-4o` | General-purpose model | Multimodal chat, tool use, balanced latency |
245
+ | `gpt-4.1` | Strong coding model | Code generation, refactoring, analysis |
246
+ | `o3` | Reasoning model | Complex reasoning and planning |
239
247
 
240
248
  ## 🔍 API Reference
241
249
 
242
250
  ### OpenAIProvider Class
243
251
 
244
252
  ```typescript
245
- class OpenAIProvider extends BaseAIProvider<
246
- IOpenAIProviderOptions,
247
- UniversalMessage,
248
- UniversalMessage
249
- > {
253
+ class OpenAIProvider extends AbstractAIProvider {
250
254
  // Core methods
251
- async chat(messages: UniversalMessage[], options?: ChatOptions): Promise<UniversalMessage>;
255
+ async chat(messages: TUniversalMessage[], options?: IChatOptions): Promise<TUniversalMessage>;
252
256
  async chatStream(
253
- messages: UniversalMessage[],
254
- options?: ChatOptions,
255
- ): AsyncIterable<UniversalMessage>;
257
+ messages: TUniversalMessage[],
258
+ options?: IChatOptions,
259
+ ): AsyncIterable<TUniversalMessage>;
256
260
 
257
261
  // Provider information
258
262
  readonly name: string = 'openai';
@@ -269,8 +273,8 @@ class OpenAIProvider extends BaseAIProvider<
269
273
 
270
274
  ```typescript
271
275
  // Chat Options
272
- interface ChatOptions {
273
- tools?: ToolSchema[];
276
+ interface IChatOptions {
277
+ tools?: IToolSchema[];
274
278
  maxTokens?: number;
275
279
  temperature?: number;
276
280
  model?: string;
@@ -286,7 +290,7 @@ interface OpenAIToolCall {
286
290
  };
287
291
  }
288
292
 
289
- interface OpenAILogData {
293
+ interface IOpenAILogData {
290
294
  model: string;
291
295
  messagesCount: number;
292
296
  hasTools: boolean;
@@ -311,7 +315,7 @@ import { FilePayloadLogger } from '@robota-sdk/agent-provider-openai/loggers/fil
311
315
 
312
316
  const provider = new OpenAIProvider({
313
317
  client: openaiClient,
314
- model: 'gpt-4',
318
+ defaultModel: 'gpt-4o',
315
319
  payloadLogger: new FilePayloadLogger({
316
320
  logDir: './logs/openai-api',
317
321
  enabled: true,
@@ -328,7 +332,7 @@ import { ConsolePayloadLogger } from '@robota-sdk/agent-provider-openai/loggers/
328
332
 
329
333
  const provider = new OpenAIProvider({
330
334
  client: openaiClient,
331
- model: 'gpt-4',
335
+ defaultModel: 'gpt-4o',
332
336
  payloadLogger: new ConsolePayloadLogger({
333
337
  enabled: true,
334
338
  includeTimestamp: true,
@@ -341,7 +345,7 @@ const provider = new OpenAIProvider({
341
345
  ```typescript
342
346
  const provider = new OpenAIProvider({
343
347
  client: openaiClient,
344
- model: 'gpt-4',
348
+ defaultModel: 'gpt-4o',
345
349
  // payloadLogger: undefined (default - no logging)
346
350
  });
347
351
  ```
@@ -351,14 +355,16 @@ const provider = new OpenAIProvider({
351
355
  You can create custom logger implementations by implementing the IPayloadLogger interface:
352
356
 
353
357
  ```typescript
354
- import type { IPayloadLogger, OpenAILogData } from '@robota-sdk/agent-provider-openai';
358
+ import type { IPayloadLogger } from '@robota-sdk/agent-provider-openai';
359
+
360
+ type OpenAILogPayload = Parameters<IPayloadLogger['logPayload']>[0];
355
361
 
356
362
  class CustomPayloadLogger implements IPayloadLogger {
357
363
  isEnabled(): boolean {
358
364
  return true;
359
365
  }
360
366
 
361
- async logPayload(payload: OpenAILogData, type: 'chat' | 'stream'): Promise<void> {
367
+ async logPayload(payload: OpenAILogPayload, type: 'chat' | 'stream'): Promise<void> {
362
368
  // Custom logging implementation
363
369
  console.log(`[Custom Logger] ${type}:`, payload);
364
370
  }
@@ -408,7 +414,10 @@ try {
408
414
  ```typescript
409
415
  const provider = new OpenAIProvider({
410
416
  client: openaiClient,
411
- model: 'gpt-4',
417
+ defaultModel: 'gpt-4o',
418
+ });
419
+
420
+ const response = await provider.chat(messages, {
412
421
  maxTokens: 1000, // Limit response length
413
422
  temperature: 0.3, // More deterministic responses
414
423
  });
@@ -416,9 +425,9 @@ const provider = new OpenAIProvider({
416
425
 
417
426
  ### Model Selection Strategy
418
427
 
419
- - Use `gpt-3.5-turbo` for simple tasks
420
- - Use `gpt-4` for complex reasoning
421
- - Use `gpt-4-turbo` for balanced performance
428
+ - Use `gpt-4o` for balanced multimodal chat and tool use
429
+ - Use `gpt-4.1` for coding-heavy workflows
430
+ - Use reasoning models such as `o3` when explicit reasoning controls are required
422
431
 
423
432
  ## 🤝 Contributing
424
433
 
@@ -1,5 +1,5 @@
1
1
  import OpenAI from 'openai';
2
- import { ILogger, IExecutor, TProviderOptionValueBase, AbstractAIProvider, TTextDeltaCallback, TUniversalMessage, IChatOptions, IProviderDefinition } from '@robota-sdk/agent-core';
2
+ import { ILogger, IExecutor, TProviderOptionValueBase, AbstractAIProvider, TTextDeltaCallback, TUniversalMessage, IChatOptions, IProviderCapabilities, IProviderDefinition } from '@robota-sdk/agent-core';
3
3
 
4
4
  /**
5
5
  * Payload logging data structure
@@ -56,10 +56,25 @@ interface IPayloadLoggerOptions {
56
56
  logger?: ILogger;
57
57
  }
58
58
 
59
+ type TOpenAIApiSurface = 'responses' | 'chat-completions';
60
+ interface IOpenAIJsonSchemaDefinition {
61
+ name: string;
62
+ description?: string;
63
+ schema?: Record<string, TOpenAIProviderOptionValue>;
64
+ strict?: boolean;
65
+ }
66
+ interface IOpenAIResponsesReasoningOptions {
67
+ effort?: 'low' | 'medium' | 'high';
68
+ summary?: 'auto' | 'concise' | 'detailed';
69
+ }
70
+ interface IOpenAINativeWebToolsOptions {
71
+ webSearch?: boolean;
72
+ webFetch?: boolean;
73
+ }
59
74
  /**
60
75
  * Valid provider option value types
61
76
  */
62
- type TOpenAIProviderOptionValue = string | number | boolean | undefined | null | OpenAI | IPayloadLogger | ILogger | IExecutor | TProviderOptionValueBase | TOpenAIProviderOptionValue[] | {
77
+ type TOpenAIProviderOptionValue = string | number | boolean | undefined | null | IOpenAIJsonSchemaDefinition | IOpenAINativeWebToolsOptions | IOpenAIResponsesReasoningOptions | OpenAI | IPayloadLogger | ILogger | IExecutor | TProviderOptionValueBase | TOpenAIProviderOptionValue[] | {
63
78
  [key: string]: TOpenAIProviderOptionValue;
64
79
  };
65
80
  /**
@@ -86,6 +101,17 @@ interface IOpenAIProviderOptions {
86
101
  * API base URL (default: 'https://api.openai.com/v1')
87
102
  */
88
103
  baseURL?: string;
104
+ /**
105
+ * Default model used when chat options do not provide a model.
106
+ */
107
+ defaultModel?: string;
108
+ /**
109
+ * API surface to use for direct OpenAI calls.
110
+ *
111
+ * Defaults to Responses for official OpenAI calls. Profiles with baseURL use
112
+ * Chat Completions by default for OpenAI-compatible endpoint compatibility.
113
+ */
114
+ apiSurface?: TOpenAIApiSurface;
89
115
  /**
90
116
  * Response format (default: 'text')
91
117
  * - 'text': Plain text response
@@ -96,12 +122,32 @@ interface IOpenAIProviderOptions {
96
122
  /**
97
123
  * JSON schema for structured outputs (required when responseFormat is 'json_schema')
98
124
  */
99
- jsonSchema?: {
100
- name: string;
101
- description?: string;
102
- schema?: Record<string, TOpenAIProviderOptionValue>;
103
- strict?: boolean;
104
- };
125
+ jsonSchema?: IOpenAIJsonSchemaDefinition;
126
+ /**
127
+ * Responses API reasoning controls. Hidden reasoning is never exposed in message
128
+ * content; only explicit summaries/encrypted items requested here are represented.
129
+ */
130
+ reasoning?: IOpenAIResponsesReasoningOptions;
131
+ /**
132
+ * Whether OpenAI should store Responses API results. Defaults to OpenAI API behavior.
133
+ */
134
+ store?: boolean;
135
+ /**
136
+ * Include encrypted reasoning items for stateless reasoning continuation.
137
+ */
138
+ includeEncryptedReasoning?: boolean;
139
+ /**
140
+ * Opt into strict custom function parameter validation where supported.
141
+ */
142
+ strictTools?: boolean;
143
+ /**
144
+ * Provider-native hosted web tool request from provider profile options.
145
+ *
146
+ * OpenAI-compatible Chat Completions endpoints do not support this Robota
147
+ * native web contract. The provider rejects unsupported configurations before
148
+ * any model request is sent.
149
+ */
150
+ nativeWebTools?: IOpenAINativeWebToolsOptions;
105
151
  /**
106
152
  * OpenAI client instance (optional: will be created from apiKey if not provided)
107
153
  */
@@ -168,7 +214,7 @@ interface IOpenAIProviderOptions {
168
214
  /**
169
215
  * OpenAI provider implementation for Robota
170
216
  *
171
- * Provides integration with OpenAI's GPT models following BaseAIProvider guidelines.
217
+ * Provides integration with OpenAI models through the Robota provider contract.
172
218
  * Uses OpenAI SDK native types internally for optimal performance and feature support.
173
219
  *
174
220
  * @public
@@ -178,6 +224,7 @@ declare class OpenAIProvider extends AbstractAIProvider {
178
224
  readonly version = "1.0.0";
179
225
  private readonly client?;
180
226
  private readonly options;
227
+ private readonly apiSurface;
181
228
  private readonly payloadLogger;
182
229
  private readonly responseParser;
183
230
  /**
@@ -189,9 +236,9 @@ declare class OpenAIProvider extends AbstractAIProvider {
189
236
  onTextDelta?: TTextDeltaCallback;
190
237
  constructor(options: IOpenAIProviderOptions);
191
238
  chat(messages: TUniversalMessage[], options?: IChatOptions): Promise<TUniversalMessage>;
192
- private chatWithStreamingAssembly;
193
239
  chatStream(messages: TUniversalMessage[], options?: IChatOptions): AsyncIterable<TUniversalMessage>;
194
240
  supportsTools(): boolean;
241
+ getCapabilities(): IProviderCapabilities;
195
242
  validateConfig(): boolean;
196
243
  dispose(): Promise<void>;
197
244
  protected validateMessages(messages: TUniversalMessage[]): void;
@@ -232,8 +279,7 @@ declare class OpenAIConversationAdapter {
232
279
  }
233
280
 
234
281
  declare const DEFAULT_OPENAI_PROVIDER_MODEL: string | undefined;
235
- declare const DEFAULT_OPENAI_COMPATIBLE_PROVIDER_API_KEY = "lm-studio";
236
- declare const DEFAULT_OPENAI_COMPATIBLE_PROVIDER_BASE_URL = "http://localhost:1234/v1";
282
+ declare const DEFAULT_OPENAI_PROVIDER_API_KEY_REFERENCE = "$ENV:OPENAI_API_KEY";
237
283
  declare function createOpenAIProviderDefinition(): IProviderDefinition;
238
284
 
239
- export { DEFAULT_OPENAI_COMPATIBLE_PROVIDER_API_KEY, DEFAULT_OPENAI_COMPATIBLE_PROVIDER_BASE_URL, DEFAULT_OPENAI_PROVIDER_MODEL, type IOpenAIProviderOptions, type IPayloadLogger, type IPayloadLoggerOptions, OpenAIConversationAdapter, OpenAIProvider, type TOpenAIProviderOptionValue, createOpenAIProviderDefinition };
285
+ export { DEFAULT_OPENAI_PROVIDER_API_KEY_REFERENCE, DEFAULT_OPENAI_PROVIDER_MODEL, type IOpenAIJsonSchemaDefinition, type IOpenAINativeWebToolsOptions, type IOpenAIProviderOptions, type IOpenAIResponsesReasoningOptions, type IPayloadLogger, type IPayloadLoggerOptions, OpenAIConversationAdapter, OpenAIProvider, type TOpenAIApiSurface, type TOpenAIProviderOptionValue, createOpenAIProviderDefinition };
@@ -1,2 +1 @@
1
- import C from'openai';import {AbstractAIProvider,SilentLogger}from'@robota-sdk/agent-core';import {assembleOpenAICompatibleStream,probeOpenAICompatibleProfile,OpenAICompatibleResponseParser,convertToOpenAICompatibleMessages,convertToOpenAICompatibleTools}from'@robota-sdk/agent-provider-openai-compatible';var p=class{parser;constructor(e){this.parser=new OpenAICompatibleResponseParser({logger:e});}parseResponse(e){try{return this.parser.parseResponse(e)}catch(t){let r=d(t instanceof Error?t.message:"OpenAI response parsing failed");throw new Error(`OpenAI response parsing failed: ${r}`)}}parseStreamingChunk(e){try{return this.parser.parseStreamingChunk(e)}catch(t){let r=d(t instanceof Error?t.message:"OpenAI chunk parsing failed");throw new Error(`OpenAI chunk parsing failed: ${r}`)}}};function d(a){return a.replace(/^OpenAI-compatible response parsing failed: /,"").replace(/^OpenAI-compatible chunk parsing failed: /,"").replace("OpenAI-compatible response","OpenAI response")}function m(a){return convertToOpenAICompatibleMessages(a)}function c(a){return convertToOpenAICompatibleTools(a)}var i=class extends AbstractAIProvider{name="openai";version="1.0.0";client;options;payloadLogger;responseParser;onTextDelta;constructor(e){if(super(e.logger||SilentLogger),this.options=e,e.executor&&(this.executor=e.executor),!this.executor)if(e.client)this.client=e.client;else if(e.apiKey)this.client=new C({apiKey:e.apiKey,...e.organization&&{organization:e.organization},...e.timeout&&{timeout:e.timeout},...e.baseURL&&{baseURL:e.baseURL}});else throw new Error("Either OpenAI client, apiKey, or executor is required");this.responseParser=new p(this.logger),this.payloadLogger=e.payloadLogger;}async chat(e,t){if(this.validateMessages(e),this.executor)try{return await this.executeViaExecutorOrDirect(e,t)}catch(r){throw this.logger.error("OpenAI Provider executor chat error:",r instanceof Error?r.message:String(r)),r}if(!this.client)throw new Error("OpenAI client not available. Either provide a client/apiKey or use an executor.");try{let r=m(e),o=t;if(!o?.model)throw new Error("Model is required in chat options. Please specify a model in defaultModel configuration.");let s={model:o.model,messages:r,...o.temperature!==void 0&&{temperature:o.temperature},...o.maxTokens&&{max_tokens:o.maxTokens},...o.tools&&{tools:c(o.tools),tool_choice:"auto"}},n=o.onTextDelta??this.onTextDelta;if(n)return await this.chatWithStreamingAssembly({...s,stream:!0},{...o,onTextDelta:n});if(this.payloadLogger?.isEnabled()){let I={model:s.model,messagesCount:r.length,hasTools:!!s.tools,temperature:s.temperature??void 0,maxTokens:s.max_tokens??void 0,timestamp:new Date().toISOString()};await this.payloadLogger.logPayload(I,"chat");}let l=await this.client.chat.completions.create(s);return this.responseParser.parseResponse(l)}catch(r){let s=r.message||"OpenAI API request failed";throw new Error(`OpenAI chat failed: ${s}`)}}async chatWithStreamingAssembly(e,t){if(!this.client)throw new Error("OpenAI client not available. Either provide a client/apiKey or use an executor.");try{if(this.payloadLogger?.isEnabled()){let o={model:e.model,messagesCount:e.messages.length,hasTools:!!e.tools,temperature:e.temperature??void 0,maxTokens:e.max_tokens??void 0,timestamp:new Date().toISOString()};await this.payloadLogger.logPayload(o,"stream");}let r=await this.client.chat.completions.create(e,t.signal?{signal:t.signal}:void 0);return assembleOpenAICompatibleStream({stream:r,onTextDelta:t.onTextDelta,signal:t.signal})}catch(r){let s=r.message||"OpenAI streaming request failed";throw new Error(`OpenAI stream failed: ${s}`)}}async*chatStream(e,t){if(this.executor)try{yield*this.executeStreamViaExecutorOrDirect(e,t);return}catch(r){throw this.logger.error("OpenAI Provider executor stream error:",r instanceof Error?r.message:String(r)),r}if(!this.client)throw new Error("OpenAI client not available. Either provide a client/apiKey or use an executor.");try{let r=m(e);if(!t?.model)throw new Error("Model is required in chat options. Please specify a model in defaultModel configuration.");let o={model:t.model,messages:r,stream:!0,...t?.temperature!==void 0&&{temperature:t.temperature},...t?.maxTokens&&{max_tokens:t.maxTokens},...t?.tools&&{tools:c(t.tools),tool_choice:"auto"}};if(this.payloadLogger?.isEnabled()){let n={model:o.model,messagesCount:r.length,hasTools:!!o.tools,temperature:o.temperature??void 0,maxTokens:o.max_tokens??void 0,timestamp:new Date().toISOString()};await this.payloadLogger.logPayload(n,"stream");}let s=await this.client.chat.completions.create(o);for await(let n of s){let l=this.responseParser.parseStreamingChunk(n);l&&(yield l);}}catch(r){let s=r.message||"OpenAI API request failed";throw new Error(`OpenAI stream failed: ${s}`)}}supportsTools(){return true}validateConfig(){return !!this.client&&!!this.options}async dispose(){}validateMessages(e){super.validateMessages(e);for(let t of e)if(t.role==="assistant"){let r=t;if(r.toolCalls&&r.toolCalls.length>0&&r.content==="")continue}}};var g=class{static filterMessagesForOpenAI(e){return e.filter(t=>t.role==="user"||t.role==="assistant"||t.role==="system"?true:t.role==="tool"?!!(t.toolCallId&&t.toolCallId.trim()!==""&&t.toolCallId!=="unknown"):false)}static toOpenAIFormat(e){return this.filterMessagesForOpenAI(e).map(r=>this.convertMessage(r))}static convertMessage(e){let t=e.role;if(t==="user")return {role:"user",content:e.content};if(t==="assistant"){let o=e;return o.toolCalls&&o.toolCalls.length>0?{role:"assistant",content:o.content===""?null:o.content||null,tool_calls:o.toolCalls.map(n=>({id:n.id,type:"function",function:{name:n.function.name,arguments:n.function.arguments}}))}:{role:"assistant",content:o.content===null||o.content===""?null:o.content||""}}if(t==="system")return {role:"system",content:e.content};if(t==="tool"){if(!e.toolCallId||e.toolCallId.trim()==="")throw new Error(`Tool message missing toolCallId: ${JSON.stringify(e)}`);return {role:"tool",content:e.content,tool_call_id:e.toolCallId}}let r=t;throw new Error(`Unsupported message role: ${r}`)}static addSystemPromptIfNeeded(e,t){return !t||e.some(o=>o.role==="system")?e:[{role:"system",content:t},...e]}};var F=void 0,h="lm-studio",f="http://localhost:1234/v1";function z(){return {type:"openai",displayName:"OpenAI Compatible",description:"OpenAI or OpenAI-compatible Chat Completions endpoint",defaults:{apiKey:h,baseURL:f},setupSteps:[{key:"baseURL",title:"OpenAI-compatible base URL",defaultValue:f},{key:"model",title:"OpenAI-compatible model",required:true},{key:"apiKey",title:"OpenAI-compatible API key",defaultValue:h,masked:true}],requiresApiKey:true,probeProfile:probeOpenAICompatibleProfile,createProvider:a=>new i({apiKey:x(a.apiKey),...a.baseURL!==void 0&&{baseURL:a.baseURL},...a.timeout!==void 0&&{timeout:a.timeout},defaultModel:a.model})}}function x(a){if(!a)throw new Error("Provider openai requires apiKey");return a}
2
- export{h as DEFAULT_OPENAI_COMPATIBLE_PROVIDER_API_KEY,f as DEFAULT_OPENAI_COMPATIBLE_PROVIDER_BASE_URL,F as DEFAULT_OPENAI_PROVIDER_MODEL,g as OpenAIConversationAdapter,i as OpenAIProvider,z as createOpenAIProviderDefinition};
1
+ import ye from'openai';import {AbstractAIProvider,SilentLogger}from'@robota-sdk/agent-core';import {probeOpenAICompatibleProfile,OpenAICompatibleResponseParser,assembleOpenAICompatibleStream,convertToOpenAICompatibleMessages,convertToOpenAICompatibleTools}from'@robota-sdk/agent-provider-openai-compatible';import {randomUUID}from'crypto';var i=class{parser;constructor(t){this.parser=new OpenAICompatibleResponseParser({logger:t});}parseResponse(t){try{return this.parser.parseResponse(t)}catch(n){let s=f(n instanceof Error?n.message:"OpenAI response parsing failed");throw new Error(`OpenAI response parsing failed: ${s}`)}}parseStreamingChunk(t){try{return this.parser.parseStreamingChunk(t)}catch(n){let s=f(n instanceof Error?n.message:"OpenAI chunk parsing failed");throw new Error(`OpenAI chunk parsing failed: ${s}`)}}};function f(e){return e.replace(/^OpenAI-compatible response parsing failed: /,"").replace(/^OpenAI-compatible chunk parsing failed: /,"").replace("OpenAI-compatible response","OpenAI response")}function O(e){if(e.responseFormat===void 0||e.responseFormat==="text")return;if(e.responseFormat==="json_object")return {type:"json_object"};let t=g(e);return {type:"json_schema",json_schema:{name:t.name,schema:t.schema,...t.description!==void 0&&{description:t.description},...t.strict!==void 0&&{strict:t.strict}}}}function h(e){if(e.responseFormat===void 0||e.responseFormat==="text")return;if(e.responseFormat==="json_object")return {format:{type:"json_object"}};let t=g(e);return {format:{type:"json_schema",name:t.name,schema:t.schema,...t.description!==void 0&&{description:t.description},...t.strict!==void 0&&{strict:t.strict}}}}function g(e){let t=e.jsonSchema;if(e.responseFormat!=="json_schema")throw new Error(`Unsupported OpenAI response format: ${e.responseFormat}`);if(!t?.schema)throw new Error("OpenAI jsonSchema.schema is required when responseFormat is json_schema");return {name:t.name,schema:t.schema,...t.description!==void 0&&{description:t.description},...t.strict!==void 0&&{strict:t.strict}}}function A(e){return convertToOpenAICompatibleMessages(e)}function T(e){return convertToOpenAICompatibleTools(e)}async function R(e){let t=b(e.client);try{let n=v(e);if(e.chatOptions?.onTextDelta??e.onTextDelta)return await G(t,e,{...n,stream:!0});await u(e,n,"chat");let o=await t.chat.completions.create(n);return e.responseParser.parseResponse(o)}catch(n){let o=n.message||"OpenAI API request failed";throw new Error(`OpenAI chat failed: ${o}`)}}async function*C(e){let t=b(e.client);try{let n={...v(e),stream:!0};await u(e,n,"stream");let s=await t.chat.completions.create(n,e.chatOptions?.signal?{signal:e.chatOptions.signal}:void 0);for await(let o of s){let r=e.responseParser.parseStreamingChunk(o);r&&(yield r);}}catch(n){let o=n.message||"OpenAI API request failed";throw new Error(`OpenAI stream failed: ${o}`)}}function v(e){let t=A(e.messages),n=e.chatOptions?.model??e.providerOptions.defaultModel;if(!n)throw new Error("Model is required in chat options. Please specify a model in defaultModel configuration.");let s=O(e.providerOptions);return {model:n,messages:t,...e.chatOptions?.temperature!==void 0&&{temperature:e.chatOptions.temperature},...e.chatOptions?.maxTokens!==void 0&&{max_tokens:e.chatOptions.maxTokens},...e.chatOptions?.tools&&{tools:T(e.chatOptions.tools),tool_choice:"auto"},...s!==void 0&&{response_format:s}}}async function G(e,t,n){try{await u(t,n,"stream");let s=await e.chat.completions.create(n,t.chatOptions?.signal?{signal:t.chatOptions.signal}:void 0);return assembleOpenAICompatibleStream({stream:s,onTextDelta:t.chatOptions?.onTextDelta??t.onTextDelta,signal:t.chatOptions?.signal})}catch(s){let r=s.message||"OpenAI streaming request failed";throw new Error(`OpenAI stream failed: ${r}`)}}async function u(e,t,n){if(!e.payloadLogger?.isEnabled())return;let s={model:t.model,messagesCount:t.messages.length,hasTools:!!t.tools,temperature:t.temperature??void 0,maxTokens:t.max_tokens??void 0,timestamp:new Date().toISOString()};await e.payloadLogger.logPayload(s,n);}function b(e){if(!e)throw new Error("OpenAI client not available. Either provide a client/apiKey or use an executor.");return e}function S(e){return e.flatMap(t=>B(t))}function x(e,t){let n=e?.map(s=>({type:"function",name:s.name,description:s.description,parameters:s.parameters,strict:t??false}))??[];return n.length>0?n:void 0}function B(e){if(e.role==="user")return [p("user",X(e.content,e.parts))];if(e.role==="system")return [p("system",e.content)];if(e.role==="tool"){if(!e.toolCallId||e.toolCallId.trim().length===0)throw new Error(`Tool message missing toolCallId: ${JSON.stringify(e)}`);return [{type:"function_call_output",call_id:e.toolCallId,output:e.content||""}]}return H(e)}function H(e){let t=[];e.content&&e.content.length>0&&t.push(p("assistant",e.content));for(let n of e.toolCalls??[])t.push({type:"function_call",call_id:n.id,name:n.function.name,arguments:n.function.arguments});return t.length===0&&t.push(p("assistant","")),t}function X(e,t){if(!t||t.length===0)return e;let n=t.map(s=>Z(s));return e.length>0&&!t.some(s=>s.type==="text")?[{type:"input_text",text:e},...n]:n}function Z(e){return e.type==="text"?{type:"input_text",text:e.text}:e.type==="image_uri"?{type:"input_image",image_url:e.uri}:{type:"input_image",image_url:`data:${e.mimeType};base64,${e.data}`}}function p(e,t){return {role:e,content:t}}async function*M(e,t){let n=e[Symbol.asyncIterator]();try{for(;!t?.aborted;){let s=await ee(n,t);if(s.done||t?.aborted)break;yield s.value;}}finally{t?.aborted&&await n.return?.();}}async function ee(e,t){if(!t)return e.next();if(t.aborted)return {done:true,value:void 0};let n,s=new Promise(o=>{n=()=>o({done:true,value:void 0}),t.addEventListener("abort",n,{once:true});});try{return await Promise.race([e.next(),s])}finally{n&&t.removeEventListener("abort",n);}}function w(e){L(e);let t=e.output??[],n=e.output_text??k(t);return m({content:n,toolCalls:E(t),response:e,reasoning:l(t)})}async function P(e){let t={textParts:[],toolCalls:[],reasoning:F()};for await(let n of M(e.stream,e.signal))ne(t,n,e.onTextDelta);return t.completedResponse!==void 0?oe(t):m({content:t.textParts.join(""),toolCalls:t.toolCalls,reasoning:t.reasoning})}function ne(e,t,n){if(t.type==="response.output_text.delta"){e.textParts.push(t.delta),n?.(t.delta);return}if(t.type==="response.completed"){e.completedResponse=t.response,d(e.reasoning,l(t.response.output??[]));return}if(t.type==="response.output_item.done"){se(e,t.item);return}if(t.type==="response.error"||t.type==="response.failed"||t.type==="response.incomplete")throw new Error(`OpenAI Responses API failed: ${ce(t)}`)}function se(e,t){if(U(t)){e.toolCalls.push(D(t));return}_(t)&&d(e.reasoning,l([t]));}function oe(e){let t=e.completedResponse;if(t===void 0)throw new Error("OpenAI Responses stream completed without response metadata");L(t);let n=t.output??[],s=E(n),o=e.textParts.length>0?e.textParts.join(""):t.output_text??k(n),r=l(n);return d(r,e.reasoning),m({content:o,toolCalls:s.length>0?s:e.toolCalls,response:t,reasoning:r})}function m(e){return {id:randomUUID(),role:"assistant",content:e.content,state:"complete",timestamp:new Date,...e.toolCalls.length>0&&{toolCalls:e.toolCalls},...e.response?.usage!==void 0&&{usage:ae(e.response.usage)},metadata:re(e.response,e.reasoning)}}function re(e,t){return {providerApiSurface:"responses",...e?.id!==void 0&&{responseId:e.id},...e?.model!==void 0&&{model:e.model},...e?.status!==void 0&&{finishReason:e.status},...t.reasoningSummaryCount>0&&{reasoningSummaryCount:t.reasoningSummaryCount,reasoningSummaries:t.reasoningSummaries},...t.hasEncryptedReasoning&&{hasEncryptedReasoning:true}}}function ae(e){return {promptTokens:e.input_tokens??0,completionTokens:e.output_tokens??0,totalTokens:e.total_tokens??0}}function E(e){return e.filter(U).map(t=>D(t))}function U(e){return e.type==="function_call"&&"call_id"in e&&"name"in e&&"arguments"in e}function D(e){return {id:e.call_id,type:"function",function:{name:e.name,arguments:e.arguments}}}function k(e){return e.filter(pe).flatMap(t=>t.content).map(ie).join("")}function ie(e){return e.type==="refusal"?e.refusal:e.text}function pe(e){return e.type==="message"&&"content"in e&&Array.isArray(e.content)}function l(e){let t=F();for(let n of e){if(!_(n))continue;let s=n.summary?.map(o=>o.text).filter(le)??[];t.reasoningSummaryCount+=s.length,t.reasoningSummaries.push(...s),t.hasEncryptedReasoning=t.hasEncryptedReasoning||!!n.encrypted_content;}return t}function _(e){return e.type==="reasoning"}function F(){return {reasoningSummaryCount:0,reasoningSummaries:[],hasEncryptedReasoning:false}}function d(e,t){e.reasoningSummaryCount+=t.reasoningSummaryCount,e.reasoningSummaries.push(...t.reasoningSummaries),e.hasEncryptedReasoning=e.hasEncryptedReasoning||t.hasEncryptedReasoning;}function le(e){return e!==void 0}function L(e){if(e.status==="failed"||e.status==="incomplete")throw new Error(`OpenAI Responses API failed: ${e.error?.message??e.status}`)}function ce(e){return e.message??e.error?.message??e.response?.error?.message??"unknown error"}async function W(e){let t=e.chatOptions?.onTextDelta??e.onTextDelta;if(t)return j({...e,chatOptions:{...e.chatOptions,onTextDelta:t}});if(!e.client)throw new Error("OpenAI Responses client not available.");try{let n=$(e),s=await e.client.responses.create(n,e.chatOptions?.signal?{signal:e.chatOptions.signal}:void 0);return w(s)}catch(n){let o=n.message||"OpenAI Responses API request failed";throw new Error(`OpenAI responses failed: ${o}`)}}async function*N(e){let t={deltas:[]},n=e.chatOptions?.onTextDelta??e.onTextDelta,s=j({...e,chatOptions:{...e.chatOptions,onTextDelta:o=>{n?.(o),fe(t,de(o));}}}).then(o=>Oe(t,o)).catch(o=>he(t,Te(o)));yield*Ie(t),await s;}async function j(e){if(!e.client)throw new Error("OpenAI Responses client not available.");try{let t=me(e),n=await e.client.responses.create(t,e.chatOptions?.signal?{signal:e.chatOptions.signal}:void 0);return P({stream:n,onTextDelta:e.chatOptions?.onTextDelta,signal:e.chatOptions?.signal})}catch(t){let s=t.message||"OpenAI Responses streaming request failed";throw new Error(`OpenAI responses stream failed: ${s}`)}}function $(e){let t=e.chatOptions?.model??e.providerOptions.defaultModel;if(!t)throw new Error("Model is required in chat options. Please specify a model in defaultModel configuration.");let n=x(e.chatOptions?.tools,e.providerOptions.strictTools),s=h(e.providerOptions);return {model:t,input:S(e.messages),...n!==void 0&&{tools:n,tool_choice:"auto"},...e.chatOptions?.temperature!==void 0&&{temperature:e.chatOptions.temperature},...e.chatOptions?.maxTokens!==void 0&&{max_output_tokens:e.chatOptions.maxTokens},...s!==void 0&&{text:s},...e.providerOptions.reasoning!==void 0&&{reasoning:e.providerOptions.reasoning},...e.providerOptions.includeEncryptedReasoning===true&&{include:["reasoning.encrypted_content"]},...e.providerOptions.store!==void 0&&{store:e.providerOptions.store}}}function me(e){return {...$(e),stream:true}}function de(e){return {id:randomUUID(),role:"assistant",content:e,state:"complete",timestamp:new Date,metadata:{providerApiSurface:"responses",isStreamChunk:true,isComplete:false}}}async function*Ie(e){for(;;){let t=e.deltas.shift();if(t!==void 0){yield t;continue}if(e.error!==void 0)throw e.error;if(e.finalMessage!==void 0){yield Ae(e.finalMessage);return}await ge(e);}}function fe(e,t){e.deltas.push(t),I(e);}function Oe(e,t){e.finalMessage=t,I(e);}function he(e,t){e.error=t,I(e);}function ge(e){return new Promise(t=>{e.wake=t;})}function I(e){e.wake?.(),e.wake=void 0;}function Ae(e){return {...e,content:"",metadata:{...e.metadata,isStreamChunk:true,isComplete:true}}}function Te(e){return e instanceof Error?e:new Error(String(e))}var a=class extends AbstractAIProvider{name="openai";version="1.0.0";client;options;apiSurface;payloadLogger;responseParser;onTextDelta;constructor(t){if(super(t.logger||SilentLogger),this.options=t,this.apiSurface=ve(t),be(this.apiSurface,t.nativeWebTools),t.executor&&(this.executor=t.executor),!this.executor)if(t.client)this.client=t.client;else if(t.apiKey)this.client=new ye({apiKey:t.apiKey,...t.organization&&{organization:t.organization},...t.timeout&&{timeout:t.timeout},...t.baseURL&&{baseURL:t.baseURL}});else throw new Error("Either OpenAI client, apiKey, or executor is required");this.responseParser=new i(this.logger),this.payloadLogger=t.payloadLogger;}async chat(t,n){if(this.validateMessages(t),this.validateNativeWebTools(n?.nativeWebTools),this.executor)try{return await this.executeViaExecutorOrDirect(t,n)}catch(s){throw this.logger.error("OpenAI Provider executor chat error:",s instanceof Error?s.message:String(s)),s}return this.apiSurface==="responses"?W({client:this.client,messages:t,chatOptions:n,providerOptions:this.options,onTextDelta:this.onTextDelta}):R({client:this.client,messages:t,chatOptions:n,providerOptions:this.options,payloadLogger:this.payloadLogger,responseParser:this.responseParser,onTextDelta:this.onTextDelta})}async*chatStream(t,n){if(this.validateNativeWebTools(n?.nativeWebTools),this.executor)try{yield*this.executeStreamViaExecutorOrDirect(t,n);return}catch(s){throw this.logger.error("OpenAI Provider executor stream error:",s instanceof Error?s.message:String(s)),s}if(this.apiSurface==="responses"){yield*N({client:this.client,messages:t,chatOptions:n,providerOptions:this.options,onTextDelta:this.onTextDelta});return}yield*C({client:this.client,messages:t,chatOptions:n,providerOptions:this.options,payloadLogger:this.payloadLogger,responseParser:this.responseParser,onTextDelta:this.onTextDelta});}supportsTools(){return true}getCapabilities(){let t=this.apiSurface==="chat-completions"?"openai-compatible-chat-completions":"openai-responses";return {functionCalling:{supported:true},nativeWebTools:{webSearch:{supported:false,enabled:false,source:t,reason:q(this.apiSurface,"search")},webFetch:{supported:false,enabled:false,source:t,reason:q(this.apiSurface,"fetch")}}}}validateConfig(){return !!this.client&&!!this.options}async dispose(){}validateMessages(t){super.validateMessages(t);for(let n of t)if(n.role==="assistant"){let s=n;if(s.toolCalls&&s.toolCalls.length>0&&s.content==="")continue}}};function ve(e){return e.apiSurface!==void 0?e.apiSurface:e.baseURL?"chat-completions":"responses"}function q(e,t){return e==="chat-completions"?`OpenAI-compatible Chat Completions endpoints support declared function tools, not provider-native web ${t}.`:`OpenAI Responses native web ${t} is not wired in this Robota provider version.`}function be(e,t){if(!(t?.webSearch!==true&&t?.webFetch!==true))throw new Error(`Provider openai native web search/fetch is not supported for apiSurface ${e} in this Robota provider version.`)}var Q=class{static filterMessagesForOpenAI(t){return t.filter(n=>n.role==="user"||n.role==="assistant"||n.role==="system"?true:n.role==="tool"?!!(n.toolCallId&&n.toolCallId.trim()!==""&&n.toolCallId!=="unknown"):false)}static toOpenAIFormat(t){return this.filterMessagesForOpenAI(t).map(s=>this.convertMessage(s))}static convertMessage(t){let n=t.role;if(n==="user")return {role:"user",content:t.content};if(n==="assistant"){let o=t;return o.toolCalls&&o.toolCalls.length>0?{role:"assistant",content:o.content===""?null:o.content||null,tool_calls:o.toolCalls.map(c=>({id:c.id,type:"function",function:{name:c.function.name,arguments:c.function.arguments}}))}:{role:"assistant",content:o.content===null||o.content===""?null:o.content||""}}if(n==="system")return {role:"system",content:t.content};if(n==="tool"){if(!t.toolCallId||t.toolCallId.trim()==="")throw new Error(`Tool message missing toolCallId: ${JSON.stringify(t)}`);return {role:"tool",content:t.content,tool_call_id:t.toolCallId}}let s=n;throw new Error(`Unsupported message role: ${s}`)}static addSystemPromptIfNeeded(t,n){return !n||t.some(o=>o.role==="system")?t:[{role:"system",content:n},...t]}};var pt=void 0,V="$ENV:OPENAI_API_KEY";function lt(){return {type:"openai",displayName:"OpenAI",description:"Official OpenAI Responses API provider",defaults:{apiKey:V},setupSteps:[{key:"model",title:"OpenAI model",required:true},{key:"apiKey",title:"OpenAI API key",defaultValue:V,masked:true}],requiresApiKey:true,probeProfile:probeOpenAICompatibleProfile,createProvider:e=>{let t=Me(e.options),n=we(e.options);return Pe(e.baseURL,t,n),new a({apiKey:xe(e.apiKey),...e.baseURL!==void 0&&{baseURL:e.baseURL},...e.timeout!==void 0&&{timeout:e.timeout},...t!==void 0&&{apiSurface:t},...n!==void 0&&{nativeWebTools:n},defaultModel:e.model})}}}function xe(e){if(!e)throw new Error("Provider openai requires apiKey");return e}function Me(e){let t=e?.apiSurface;if(t==="responses"||t==="chat-completions")return t}function we(e){let t=K(e?.nativeWebTools)??K(e?.builtInWebTools);if(t!==void 0)return t}function K(e){if(e==null||e instanceof Date||Array.isArray(e)||typeof e!="object")return;let t=e.webSearch,n=e.webFetch;return {...typeof t=="boolean"&&{webSearch:t},...typeof n=="boolean"&&{webFetch:n}}}function Pe(e,t,n){if(!(n?.webSearch!==true&&n?.webFetch!==true))throw e!==void 0||t==="chat-completions"?new Error("Provider openai profile uses an OpenAI-compatible Chat Completions endpoint; native web search/fetch is not supported for this profile. Use Robota local WebSearch/WebFetch tools or a provider with documented hosted web support."):new Error("Provider openai native web search/fetch is not wired in this Robota provider version. Use Robota local WebSearch/WebFetch tools or a provider with documented hosted web support.")}export{V as DEFAULT_OPENAI_PROVIDER_API_KEY_REFERENCE,pt as DEFAULT_OPENAI_PROVIDER_MODEL,Q as OpenAIConversationAdapter,a as OpenAIProvider,lt as createOpenAIProviderDefinition};
@@ -1,2 +1 @@
1
- 'use strict';var C=require('openai'),agentCore=require('@robota-sdk/agent-core'),agentProviderOpenaiCompatible=require('@robota-sdk/agent-provider-openai-compatible');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var C__default=/*#__PURE__*/_interopDefault(C);var p=class{parser;constructor(e){this.parser=new agentProviderOpenaiCompatible.OpenAICompatibleResponseParser({logger:e});}parseResponse(e){try{return this.parser.parseResponse(e)}catch(t){let r=d(t instanceof Error?t.message:"OpenAI response parsing failed");throw new Error(`OpenAI response parsing failed: ${r}`)}}parseStreamingChunk(e){try{return this.parser.parseStreamingChunk(e)}catch(t){let r=d(t instanceof Error?t.message:"OpenAI chunk parsing failed");throw new Error(`OpenAI chunk parsing failed: ${r}`)}}};function d(a){return a.replace(/^OpenAI-compatible response parsing failed: /,"").replace(/^OpenAI-compatible chunk parsing failed: /,"").replace("OpenAI-compatible response","OpenAI response")}function m(a){return agentProviderOpenaiCompatible.convertToOpenAICompatibleMessages(a)}function c(a){return agentProviderOpenaiCompatible.convertToOpenAICompatibleTools(a)}var i=class extends agentCore.AbstractAIProvider{name="openai";version="1.0.0";client;options;payloadLogger;responseParser;onTextDelta;constructor(e){if(super(e.logger||agentCore.SilentLogger),this.options=e,e.executor&&(this.executor=e.executor),!this.executor)if(e.client)this.client=e.client;else if(e.apiKey)this.client=new C__default.default({apiKey:e.apiKey,...e.organization&&{organization:e.organization},...e.timeout&&{timeout:e.timeout},...e.baseURL&&{baseURL:e.baseURL}});else throw new Error("Either OpenAI client, apiKey, or executor is required");this.responseParser=new p(this.logger),this.payloadLogger=e.payloadLogger;}async chat(e,t){if(this.validateMessages(e),this.executor)try{return await this.executeViaExecutorOrDirect(e,t)}catch(r){throw this.logger.error("OpenAI Provider executor chat error:",r instanceof Error?r.message:String(r)),r}if(!this.client)throw new Error("OpenAI client not available. Either provide a client/apiKey or use an executor.");try{let r=m(e),o=t;if(!o?.model)throw new Error("Model is required in chat options. Please specify a model in defaultModel configuration.");let s={model:o.model,messages:r,...o.temperature!==void 0&&{temperature:o.temperature},...o.maxTokens&&{max_tokens:o.maxTokens},...o.tools&&{tools:c(o.tools),tool_choice:"auto"}},n=o.onTextDelta??this.onTextDelta;if(n)return await this.chatWithStreamingAssembly({...s,stream:!0},{...o,onTextDelta:n});if(this.payloadLogger?.isEnabled()){let I={model:s.model,messagesCount:r.length,hasTools:!!s.tools,temperature:s.temperature??void 0,maxTokens:s.max_tokens??void 0,timestamp:new Date().toISOString()};await this.payloadLogger.logPayload(I,"chat");}let l=await this.client.chat.completions.create(s);return this.responseParser.parseResponse(l)}catch(r){let s=r.message||"OpenAI API request failed";throw new Error(`OpenAI chat failed: ${s}`)}}async chatWithStreamingAssembly(e,t){if(!this.client)throw new Error("OpenAI client not available. Either provide a client/apiKey or use an executor.");try{if(this.payloadLogger?.isEnabled()){let o={model:e.model,messagesCount:e.messages.length,hasTools:!!e.tools,temperature:e.temperature??void 0,maxTokens:e.max_tokens??void 0,timestamp:new Date().toISOString()};await this.payloadLogger.logPayload(o,"stream");}let r=await this.client.chat.completions.create(e,t.signal?{signal:t.signal}:void 0);return agentProviderOpenaiCompatible.assembleOpenAICompatibleStream({stream:r,onTextDelta:t.onTextDelta,signal:t.signal})}catch(r){let s=r.message||"OpenAI streaming request failed";throw new Error(`OpenAI stream failed: ${s}`)}}async*chatStream(e,t){if(this.executor)try{yield*this.executeStreamViaExecutorOrDirect(e,t);return}catch(r){throw this.logger.error("OpenAI Provider executor stream error:",r instanceof Error?r.message:String(r)),r}if(!this.client)throw new Error("OpenAI client not available. Either provide a client/apiKey or use an executor.");try{let r=m(e);if(!t?.model)throw new Error("Model is required in chat options. Please specify a model in defaultModel configuration.");let o={model:t.model,messages:r,stream:!0,...t?.temperature!==void 0&&{temperature:t.temperature},...t?.maxTokens&&{max_tokens:t.maxTokens},...t?.tools&&{tools:c(t.tools),tool_choice:"auto"}};if(this.payloadLogger?.isEnabled()){let n={model:o.model,messagesCount:r.length,hasTools:!!o.tools,temperature:o.temperature??void 0,maxTokens:o.max_tokens??void 0,timestamp:new Date().toISOString()};await this.payloadLogger.logPayload(n,"stream");}let s=await this.client.chat.completions.create(o);for await(let n of s){let l=this.responseParser.parseStreamingChunk(n);l&&(yield l);}}catch(r){let s=r.message||"OpenAI API request failed";throw new Error(`OpenAI stream failed: ${s}`)}}supportsTools(){return true}validateConfig(){return !!this.client&&!!this.options}async dispose(){}validateMessages(e){super.validateMessages(e);for(let t of e)if(t.role==="assistant"){let r=t;if(r.toolCalls&&r.toolCalls.length>0&&r.content==="")continue}}};var g=class{static filterMessagesForOpenAI(e){return e.filter(t=>t.role==="user"||t.role==="assistant"||t.role==="system"?true:t.role==="tool"?!!(t.toolCallId&&t.toolCallId.trim()!==""&&t.toolCallId!=="unknown"):false)}static toOpenAIFormat(e){return this.filterMessagesForOpenAI(e).map(r=>this.convertMessage(r))}static convertMessage(e){let t=e.role;if(t==="user")return {role:"user",content:e.content};if(t==="assistant"){let o=e;return o.toolCalls&&o.toolCalls.length>0?{role:"assistant",content:o.content===""?null:o.content||null,tool_calls:o.toolCalls.map(n=>({id:n.id,type:"function",function:{name:n.function.name,arguments:n.function.arguments}}))}:{role:"assistant",content:o.content===null||o.content===""?null:o.content||""}}if(t==="system")return {role:"system",content:e.content};if(t==="tool"){if(!e.toolCallId||e.toolCallId.trim()==="")throw new Error(`Tool message missing toolCallId: ${JSON.stringify(e)}`);return {role:"tool",content:e.content,tool_call_id:e.toolCallId}}let r=t;throw new Error(`Unsupported message role: ${r}`)}static addSystemPromptIfNeeded(e,t){return !t||e.some(o=>o.role==="system")?e:[{role:"system",content:t},...e]}};var F=void 0,h="lm-studio",f="http://localhost:1234/v1";function z(){return {type:"openai",displayName:"OpenAI Compatible",description:"OpenAI or OpenAI-compatible Chat Completions endpoint",defaults:{apiKey:h,baseURL:f},setupSteps:[{key:"baseURL",title:"OpenAI-compatible base URL",defaultValue:f},{key:"model",title:"OpenAI-compatible model",required:true},{key:"apiKey",title:"OpenAI-compatible API key",defaultValue:h,masked:true}],requiresApiKey:true,probeProfile:agentProviderOpenaiCompatible.probeOpenAICompatibleProfile,createProvider:a=>new i({apiKey:x(a.apiKey),...a.baseURL!==void 0&&{baseURL:a.baseURL},...a.timeout!==void 0&&{timeout:a.timeout},defaultModel:a.model})}}function x(a){if(!a)throw new Error("Provider openai requires apiKey");return a}
2
- exports.DEFAULT_OPENAI_COMPATIBLE_PROVIDER_API_KEY=h;exports.DEFAULT_OPENAI_COMPATIBLE_PROVIDER_BASE_URL=f;exports.DEFAULT_OPENAI_PROVIDER_MODEL=F;exports.OpenAIConversationAdapter=g;exports.OpenAIProvider=i;exports.createOpenAIProviderDefinition=z;
1
+ 'use strict';var ye=require('openai'),agentCore=require('@robota-sdk/agent-core'),agentProviderOpenaiCompatible=require('@robota-sdk/agent-provider-openai-compatible'),crypto=require('crypto');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var ye__default=/*#__PURE__*/_interopDefault(ye);var i=class{parser;constructor(t){this.parser=new agentProviderOpenaiCompatible.OpenAICompatibleResponseParser({logger:t});}parseResponse(t){try{return this.parser.parseResponse(t)}catch(n){let s=f(n instanceof Error?n.message:"OpenAI response parsing failed");throw new Error(`OpenAI response parsing failed: ${s}`)}}parseStreamingChunk(t){try{return this.parser.parseStreamingChunk(t)}catch(n){let s=f(n instanceof Error?n.message:"OpenAI chunk parsing failed");throw new Error(`OpenAI chunk parsing failed: ${s}`)}}};function f(e){return e.replace(/^OpenAI-compatible response parsing failed: /,"").replace(/^OpenAI-compatible chunk parsing failed: /,"").replace("OpenAI-compatible response","OpenAI response")}function O(e){if(e.responseFormat===void 0||e.responseFormat==="text")return;if(e.responseFormat==="json_object")return {type:"json_object"};let t=g(e);return {type:"json_schema",json_schema:{name:t.name,schema:t.schema,...t.description!==void 0&&{description:t.description},...t.strict!==void 0&&{strict:t.strict}}}}function h(e){if(e.responseFormat===void 0||e.responseFormat==="text")return;if(e.responseFormat==="json_object")return {format:{type:"json_object"}};let t=g(e);return {format:{type:"json_schema",name:t.name,schema:t.schema,...t.description!==void 0&&{description:t.description},...t.strict!==void 0&&{strict:t.strict}}}}function g(e){let t=e.jsonSchema;if(e.responseFormat!=="json_schema")throw new Error(`Unsupported OpenAI response format: ${e.responseFormat}`);if(!t?.schema)throw new Error("OpenAI jsonSchema.schema is required when responseFormat is json_schema");return {name:t.name,schema:t.schema,...t.description!==void 0&&{description:t.description},...t.strict!==void 0&&{strict:t.strict}}}function A(e){return agentProviderOpenaiCompatible.convertToOpenAICompatibleMessages(e)}function T(e){return agentProviderOpenaiCompatible.convertToOpenAICompatibleTools(e)}async function R(e){let t=b(e.client);try{let n=v(e);if(e.chatOptions?.onTextDelta??e.onTextDelta)return await G(t,e,{...n,stream:!0});await u(e,n,"chat");let o=await t.chat.completions.create(n);return e.responseParser.parseResponse(o)}catch(n){let o=n.message||"OpenAI API request failed";throw new Error(`OpenAI chat failed: ${o}`)}}async function*C(e){let t=b(e.client);try{let n={...v(e),stream:!0};await u(e,n,"stream");let s=await t.chat.completions.create(n,e.chatOptions?.signal?{signal:e.chatOptions.signal}:void 0);for await(let o of s){let r=e.responseParser.parseStreamingChunk(o);r&&(yield r);}}catch(n){let o=n.message||"OpenAI API request failed";throw new Error(`OpenAI stream failed: ${o}`)}}function v(e){let t=A(e.messages),n=e.chatOptions?.model??e.providerOptions.defaultModel;if(!n)throw new Error("Model is required in chat options. Please specify a model in defaultModel configuration.");let s=O(e.providerOptions);return {model:n,messages:t,...e.chatOptions?.temperature!==void 0&&{temperature:e.chatOptions.temperature},...e.chatOptions?.maxTokens!==void 0&&{max_tokens:e.chatOptions.maxTokens},...e.chatOptions?.tools&&{tools:T(e.chatOptions.tools),tool_choice:"auto"},...s!==void 0&&{response_format:s}}}async function G(e,t,n){try{await u(t,n,"stream");let s=await e.chat.completions.create(n,t.chatOptions?.signal?{signal:t.chatOptions.signal}:void 0);return agentProviderOpenaiCompatible.assembleOpenAICompatibleStream({stream:s,onTextDelta:t.chatOptions?.onTextDelta??t.onTextDelta,signal:t.chatOptions?.signal})}catch(s){let r=s.message||"OpenAI streaming request failed";throw new Error(`OpenAI stream failed: ${r}`)}}async function u(e,t,n){if(!e.payloadLogger?.isEnabled())return;let s={model:t.model,messagesCount:t.messages.length,hasTools:!!t.tools,temperature:t.temperature??void 0,maxTokens:t.max_tokens??void 0,timestamp:new Date().toISOString()};await e.payloadLogger.logPayload(s,n);}function b(e){if(!e)throw new Error("OpenAI client not available. Either provide a client/apiKey or use an executor.");return e}function S(e){return e.flatMap(t=>B(t))}function x(e,t){let n=e?.map(s=>({type:"function",name:s.name,description:s.description,parameters:s.parameters,strict:t??false}))??[];return n.length>0?n:void 0}function B(e){if(e.role==="user")return [p("user",X(e.content,e.parts))];if(e.role==="system")return [p("system",e.content)];if(e.role==="tool"){if(!e.toolCallId||e.toolCallId.trim().length===0)throw new Error(`Tool message missing toolCallId: ${JSON.stringify(e)}`);return [{type:"function_call_output",call_id:e.toolCallId,output:e.content||""}]}return H(e)}function H(e){let t=[];e.content&&e.content.length>0&&t.push(p("assistant",e.content));for(let n of e.toolCalls??[])t.push({type:"function_call",call_id:n.id,name:n.function.name,arguments:n.function.arguments});return t.length===0&&t.push(p("assistant","")),t}function X(e,t){if(!t||t.length===0)return e;let n=t.map(s=>Z(s));return e.length>0&&!t.some(s=>s.type==="text")?[{type:"input_text",text:e},...n]:n}function Z(e){return e.type==="text"?{type:"input_text",text:e.text}:e.type==="image_uri"?{type:"input_image",image_url:e.uri}:{type:"input_image",image_url:`data:${e.mimeType};base64,${e.data}`}}function p(e,t){return {role:e,content:t}}async function*M(e,t){let n=e[Symbol.asyncIterator]();try{for(;!t?.aborted;){let s=await ee(n,t);if(s.done||t?.aborted)break;yield s.value;}}finally{t?.aborted&&await n.return?.();}}async function ee(e,t){if(!t)return e.next();if(t.aborted)return {done:true,value:void 0};let n,s=new Promise(o=>{n=()=>o({done:true,value:void 0}),t.addEventListener("abort",n,{once:true});});try{return await Promise.race([e.next(),s])}finally{n&&t.removeEventListener("abort",n);}}function w(e){L(e);let t=e.output??[],n=e.output_text??k(t);return m({content:n,toolCalls:E(t),response:e,reasoning:l(t)})}async function P(e){let t={textParts:[],toolCalls:[],reasoning:F()};for await(let n of M(e.stream,e.signal))ne(t,n,e.onTextDelta);return t.completedResponse!==void 0?oe(t):m({content:t.textParts.join(""),toolCalls:t.toolCalls,reasoning:t.reasoning})}function ne(e,t,n){if(t.type==="response.output_text.delta"){e.textParts.push(t.delta),n?.(t.delta);return}if(t.type==="response.completed"){e.completedResponse=t.response,d(e.reasoning,l(t.response.output??[]));return}if(t.type==="response.output_item.done"){se(e,t.item);return}if(t.type==="response.error"||t.type==="response.failed"||t.type==="response.incomplete")throw new Error(`OpenAI Responses API failed: ${ce(t)}`)}function se(e,t){if(U(t)){e.toolCalls.push(D(t));return}_(t)&&d(e.reasoning,l([t]));}function oe(e){let t=e.completedResponse;if(t===void 0)throw new Error("OpenAI Responses stream completed without response metadata");L(t);let n=t.output??[],s=E(n),o=e.textParts.length>0?e.textParts.join(""):t.output_text??k(n),r=l(n);return d(r,e.reasoning),m({content:o,toolCalls:s.length>0?s:e.toolCalls,response:t,reasoning:r})}function m(e){return {id:crypto.randomUUID(),role:"assistant",content:e.content,state:"complete",timestamp:new Date,...e.toolCalls.length>0&&{toolCalls:e.toolCalls},...e.response?.usage!==void 0&&{usage:ae(e.response.usage)},metadata:re(e.response,e.reasoning)}}function re(e,t){return {providerApiSurface:"responses",...e?.id!==void 0&&{responseId:e.id},...e?.model!==void 0&&{model:e.model},...e?.status!==void 0&&{finishReason:e.status},...t.reasoningSummaryCount>0&&{reasoningSummaryCount:t.reasoningSummaryCount,reasoningSummaries:t.reasoningSummaries},...t.hasEncryptedReasoning&&{hasEncryptedReasoning:true}}}function ae(e){return {promptTokens:e.input_tokens??0,completionTokens:e.output_tokens??0,totalTokens:e.total_tokens??0}}function E(e){return e.filter(U).map(t=>D(t))}function U(e){return e.type==="function_call"&&"call_id"in e&&"name"in e&&"arguments"in e}function D(e){return {id:e.call_id,type:"function",function:{name:e.name,arguments:e.arguments}}}function k(e){return e.filter(pe).flatMap(t=>t.content).map(ie).join("")}function ie(e){return e.type==="refusal"?e.refusal:e.text}function pe(e){return e.type==="message"&&"content"in e&&Array.isArray(e.content)}function l(e){let t=F();for(let n of e){if(!_(n))continue;let s=n.summary?.map(o=>o.text).filter(le)??[];t.reasoningSummaryCount+=s.length,t.reasoningSummaries.push(...s),t.hasEncryptedReasoning=t.hasEncryptedReasoning||!!n.encrypted_content;}return t}function _(e){return e.type==="reasoning"}function F(){return {reasoningSummaryCount:0,reasoningSummaries:[],hasEncryptedReasoning:false}}function d(e,t){e.reasoningSummaryCount+=t.reasoningSummaryCount,e.reasoningSummaries.push(...t.reasoningSummaries),e.hasEncryptedReasoning=e.hasEncryptedReasoning||t.hasEncryptedReasoning;}function le(e){return e!==void 0}function L(e){if(e.status==="failed"||e.status==="incomplete")throw new Error(`OpenAI Responses API failed: ${e.error?.message??e.status}`)}function ce(e){return e.message??e.error?.message??e.response?.error?.message??"unknown error"}async function W(e){let t=e.chatOptions?.onTextDelta??e.onTextDelta;if(t)return j({...e,chatOptions:{...e.chatOptions,onTextDelta:t}});if(!e.client)throw new Error("OpenAI Responses client not available.");try{let n=$(e),s=await e.client.responses.create(n,e.chatOptions?.signal?{signal:e.chatOptions.signal}:void 0);return w(s)}catch(n){let o=n.message||"OpenAI Responses API request failed";throw new Error(`OpenAI responses failed: ${o}`)}}async function*N(e){let t={deltas:[]},n=e.chatOptions?.onTextDelta??e.onTextDelta,s=j({...e,chatOptions:{...e.chatOptions,onTextDelta:o=>{n?.(o),fe(t,de(o));}}}).then(o=>Oe(t,o)).catch(o=>he(t,Te(o)));yield*Ie(t),await s;}async function j(e){if(!e.client)throw new Error("OpenAI Responses client not available.");try{let t=me(e),n=await e.client.responses.create(t,e.chatOptions?.signal?{signal:e.chatOptions.signal}:void 0);return P({stream:n,onTextDelta:e.chatOptions?.onTextDelta,signal:e.chatOptions?.signal})}catch(t){let s=t.message||"OpenAI Responses streaming request failed";throw new Error(`OpenAI responses stream failed: ${s}`)}}function $(e){let t=e.chatOptions?.model??e.providerOptions.defaultModel;if(!t)throw new Error("Model is required in chat options. Please specify a model in defaultModel configuration.");let n=x(e.chatOptions?.tools,e.providerOptions.strictTools),s=h(e.providerOptions);return {model:t,input:S(e.messages),...n!==void 0&&{tools:n,tool_choice:"auto"},...e.chatOptions?.temperature!==void 0&&{temperature:e.chatOptions.temperature},...e.chatOptions?.maxTokens!==void 0&&{max_output_tokens:e.chatOptions.maxTokens},...s!==void 0&&{text:s},...e.providerOptions.reasoning!==void 0&&{reasoning:e.providerOptions.reasoning},...e.providerOptions.includeEncryptedReasoning===true&&{include:["reasoning.encrypted_content"]},...e.providerOptions.store!==void 0&&{store:e.providerOptions.store}}}function me(e){return {...$(e),stream:true}}function de(e){return {id:crypto.randomUUID(),role:"assistant",content:e,state:"complete",timestamp:new Date,metadata:{providerApiSurface:"responses",isStreamChunk:true,isComplete:false}}}async function*Ie(e){for(;;){let t=e.deltas.shift();if(t!==void 0){yield t;continue}if(e.error!==void 0)throw e.error;if(e.finalMessage!==void 0){yield Ae(e.finalMessage);return}await ge(e);}}function fe(e,t){e.deltas.push(t),I(e);}function Oe(e,t){e.finalMessage=t,I(e);}function he(e,t){e.error=t,I(e);}function ge(e){return new Promise(t=>{e.wake=t;})}function I(e){e.wake?.(),e.wake=void 0;}function Ae(e){return {...e,content:"",metadata:{...e.metadata,isStreamChunk:true,isComplete:true}}}function Te(e){return e instanceof Error?e:new Error(String(e))}var a=class extends agentCore.AbstractAIProvider{name="openai";version="1.0.0";client;options;apiSurface;payloadLogger;responseParser;onTextDelta;constructor(t){if(super(t.logger||agentCore.SilentLogger),this.options=t,this.apiSurface=ve(t),be(this.apiSurface,t.nativeWebTools),t.executor&&(this.executor=t.executor),!this.executor)if(t.client)this.client=t.client;else if(t.apiKey)this.client=new ye__default.default({apiKey:t.apiKey,...t.organization&&{organization:t.organization},...t.timeout&&{timeout:t.timeout},...t.baseURL&&{baseURL:t.baseURL}});else throw new Error("Either OpenAI client, apiKey, or executor is required");this.responseParser=new i(this.logger),this.payloadLogger=t.payloadLogger;}async chat(t,n){if(this.validateMessages(t),this.validateNativeWebTools(n?.nativeWebTools),this.executor)try{return await this.executeViaExecutorOrDirect(t,n)}catch(s){throw this.logger.error("OpenAI Provider executor chat error:",s instanceof Error?s.message:String(s)),s}return this.apiSurface==="responses"?W({client:this.client,messages:t,chatOptions:n,providerOptions:this.options,onTextDelta:this.onTextDelta}):R({client:this.client,messages:t,chatOptions:n,providerOptions:this.options,payloadLogger:this.payloadLogger,responseParser:this.responseParser,onTextDelta:this.onTextDelta})}async*chatStream(t,n){if(this.validateNativeWebTools(n?.nativeWebTools),this.executor)try{yield*this.executeStreamViaExecutorOrDirect(t,n);return}catch(s){throw this.logger.error("OpenAI Provider executor stream error:",s instanceof Error?s.message:String(s)),s}if(this.apiSurface==="responses"){yield*N({client:this.client,messages:t,chatOptions:n,providerOptions:this.options,onTextDelta:this.onTextDelta});return}yield*C({client:this.client,messages:t,chatOptions:n,providerOptions:this.options,payloadLogger:this.payloadLogger,responseParser:this.responseParser,onTextDelta:this.onTextDelta});}supportsTools(){return true}getCapabilities(){let t=this.apiSurface==="chat-completions"?"openai-compatible-chat-completions":"openai-responses";return {functionCalling:{supported:true},nativeWebTools:{webSearch:{supported:false,enabled:false,source:t,reason:q(this.apiSurface,"search")},webFetch:{supported:false,enabled:false,source:t,reason:q(this.apiSurface,"fetch")}}}}validateConfig(){return !!this.client&&!!this.options}async dispose(){}validateMessages(t){super.validateMessages(t);for(let n of t)if(n.role==="assistant"){let s=n;if(s.toolCalls&&s.toolCalls.length>0&&s.content==="")continue}}};function ve(e){return e.apiSurface!==void 0?e.apiSurface:e.baseURL?"chat-completions":"responses"}function q(e,t){return e==="chat-completions"?`OpenAI-compatible Chat Completions endpoints support declared function tools, not provider-native web ${t}.`:`OpenAI Responses native web ${t} is not wired in this Robota provider version.`}function be(e,t){if(!(t?.webSearch!==true&&t?.webFetch!==true))throw new Error(`Provider openai native web search/fetch is not supported for apiSurface ${e} in this Robota provider version.`)}var Q=class{static filterMessagesForOpenAI(t){return t.filter(n=>n.role==="user"||n.role==="assistant"||n.role==="system"?true:n.role==="tool"?!!(n.toolCallId&&n.toolCallId.trim()!==""&&n.toolCallId!=="unknown"):false)}static toOpenAIFormat(t){return this.filterMessagesForOpenAI(t).map(s=>this.convertMessage(s))}static convertMessage(t){let n=t.role;if(n==="user")return {role:"user",content:t.content};if(n==="assistant"){let o=t;return o.toolCalls&&o.toolCalls.length>0?{role:"assistant",content:o.content===""?null:o.content||null,tool_calls:o.toolCalls.map(c=>({id:c.id,type:"function",function:{name:c.function.name,arguments:c.function.arguments}}))}:{role:"assistant",content:o.content===null||o.content===""?null:o.content||""}}if(n==="system")return {role:"system",content:t.content};if(n==="tool"){if(!t.toolCallId||t.toolCallId.trim()==="")throw new Error(`Tool message missing toolCallId: ${JSON.stringify(t)}`);return {role:"tool",content:t.content,tool_call_id:t.toolCallId}}let s=n;throw new Error(`Unsupported message role: ${s}`)}static addSystemPromptIfNeeded(t,n){return !n||t.some(o=>o.role==="system")?t:[{role:"system",content:n},...t]}};var pt=void 0,V="$ENV:OPENAI_API_KEY";function lt(){return {type:"openai",displayName:"OpenAI",description:"Official OpenAI Responses API provider",defaults:{apiKey:V},setupSteps:[{key:"model",title:"OpenAI model",required:true},{key:"apiKey",title:"OpenAI API key",defaultValue:V,masked:true}],requiresApiKey:true,probeProfile:agentProviderOpenaiCompatible.probeOpenAICompatibleProfile,createProvider:e=>{let t=Me(e.options),n=we(e.options);return Pe(e.baseURL,t,n),new a({apiKey:xe(e.apiKey),...e.baseURL!==void 0&&{baseURL:e.baseURL},...e.timeout!==void 0&&{timeout:e.timeout},...t!==void 0&&{apiSurface:t},...n!==void 0&&{nativeWebTools:n},defaultModel:e.model})}}}function xe(e){if(!e)throw new Error("Provider openai requires apiKey");return e}function Me(e){let t=e?.apiSurface;if(t==="responses"||t==="chat-completions")return t}function we(e){let t=K(e?.nativeWebTools)??K(e?.builtInWebTools);if(t!==void 0)return t}function K(e){if(e==null||e instanceof Date||Array.isArray(e)||typeof e!="object")return;let t=e.webSearch,n=e.webFetch;return {...typeof t=="boolean"&&{webSearch:t},...typeof n=="boolean"&&{webFetch:n}}}function Pe(e,t,n){if(!(n?.webSearch!==true&&n?.webFetch!==true))throw e!==void 0||t==="chat-completions"?new Error("Provider openai profile uses an OpenAI-compatible Chat Completions endpoint; native web search/fetch is not supported for this profile. Use Robota local WebSearch/WebFetch tools or a provider with documented hosted web support."):new Error("Provider openai native web search/fetch is not wired in this Robota provider version. Use Robota local WebSearch/WebFetch tools or a provider with documented hosted web support.")}exports.DEFAULT_OPENAI_PROVIDER_API_KEY_REFERENCE=V;exports.DEFAULT_OPENAI_PROVIDER_MODEL=pt;exports.OpenAIConversationAdapter=Q;exports.OpenAIProvider=a;exports.createOpenAIProviderDefinition=lt;
@@ -1,5 +1,5 @@
1
1
  import OpenAI from 'openai';
2
- import { ILogger, IExecutor, TProviderOptionValueBase, AbstractAIProvider, TTextDeltaCallback, TUniversalMessage, IChatOptions, IProviderDefinition } from '@robota-sdk/agent-core';
2
+ import { ILogger, IExecutor, TProviderOptionValueBase, AbstractAIProvider, TTextDeltaCallback, TUniversalMessage, IChatOptions, IProviderCapabilities, IProviderDefinition } from '@robota-sdk/agent-core';
3
3
 
4
4
  /**
5
5
  * Payload logging data structure
@@ -56,10 +56,25 @@ interface IPayloadLoggerOptions {
56
56
  logger?: ILogger;
57
57
  }
58
58
 
59
+ type TOpenAIApiSurface = 'responses' | 'chat-completions';
60
+ interface IOpenAIJsonSchemaDefinition {
61
+ name: string;
62
+ description?: string;
63
+ schema?: Record<string, TOpenAIProviderOptionValue>;
64
+ strict?: boolean;
65
+ }
66
+ interface IOpenAIResponsesReasoningOptions {
67
+ effort?: 'low' | 'medium' | 'high';
68
+ summary?: 'auto' | 'concise' | 'detailed';
69
+ }
70
+ interface IOpenAINativeWebToolsOptions {
71
+ webSearch?: boolean;
72
+ webFetch?: boolean;
73
+ }
59
74
  /**
60
75
  * Valid provider option value types
61
76
  */
62
- type TOpenAIProviderOptionValue = string | number | boolean | undefined | null | OpenAI | IPayloadLogger | ILogger | IExecutor | TProviderOptionValueBase | TOpenAIProviderOptionValue[] | {
77
+ type TOpenAIProviderOptionValue = string | number | boolean | undefined | null | IOpenAIJsonSchemaDefinition | IOpenAINativeWebToolsOptions | IOpenAIResponsesReasoningOptions | OpenAI | IPayloadLogger | ILogger | IExecutor | TProviderOptionValueBase | TOpenAIProviderOptionValue[] | {
63
78
  [key: string]: TOpenAIProviderOptionValue;
64
79
  };
65
80
  /**
@@ -86,6 +101,17 @@ interface IOpenAIProviderOptions {
86
101
  * API base URL (default: 'https://api.openai.com/v1')
87
102
  */
88
103
  baseURL?: string;
104
+ /**
105
+ * Default model used when chat options do not provide a model.
106
+ */
107
+ defaultModel?: string;
108
+ /**
109
+ * API surface to use for direct OpenAI calls.
110
+ *
111
+ * Defaults to Responses for official OpenAI calls. Profiles with baseURL use
112
+ * Chat Completions by default for OpenAI-compatible endpoint compatibility.
113
+ */
114
+ apiSurface?: TOpenAIApiSurface;
89
115
  /**
90
116
  * Response format (default: 'text')
91
117
  * - 'text': Plain text response
@@ -96,12 +122,32 @@ interface IOpenAIProviderOptions {
96
122
  /**
97
123
  * JSON schema for structured outputs (required when responseFormat is 'json_schema')
98
124
  */
99
- jsonSchema?: {
100
- name: string;
101
- description?: string;
102
- schema?: Record<string, TOpenAIProviderOptionValue>;
103
- strict?: boolean;
104
- };
125
+ jsonSchema?: IOpenAIJsonSchemaDefinition;
126
+ /**
127
+ * Responses API reasoning controls. Hidden reasoning is never exposed in message
128
+ * content; only explicit summaries/encrypted items requested here are represented.
129
+ */
130
+ reasoning?: IOpenAIResponsesReasoningOptions;
131
+ /**
132
+ * Whether OpenAI should store Responses API results. Defaults to OpenAI API behavior.
133
+ */
134
+ store?: boolean;
135
+ /**
136
+ * Include encrypted reasoning items for stateless reasoning continuation.
137
+ */
138
+ includeEncryptedReasoning?: boolean;
139
+ /**
140
+ * Opt into strict custom function parameter validation where supported.
141
+ */
142
+ strictTools?: boolean;
143
+ /**
144
+ * Provider-native hosted web tool request from provider profile options.
145
+ *
146
+ * OpenAI-compatible Chat Completions endpoints do not support this Robota
147
+ * native web contract. The provider rejects unsupported configurations before
148
+ * any model request is sent.
149
+ */
150
+ nativeWebTools?: IOpenAINativeWebToolsOptions;
105
151
  /**
106
152
  * OpenAI client instance (optional: will be created from apiKey if not provided)
107
153
  */
@@ -168,7 +214,7 @@ interface IOpenAIProviderOptions {
168
214
  /**
169
215
  * OpenAI provider implementation for Robota
170
216
  *
171
- * Provides integration with OpenAI's GPT models following BaseAIProvider guidelines.
217
+ * Provides integration with OpenAI models through the Robota provider contract.
172
218
  * Uses OpenAI SDK native types internally for optimal performance and feature support.
173
219
  *
174
220
  * @public
@@ -178,6 +224,7 @@ declare class OpenAIProvider extends AbstractAIProvider {
178
224
  readonly version = "1.0.0";
179
225
  private readonly client?;
180
226
  private readonly options;
227
+ private readonly apiSurface;
181
228
  private readonly payloadLogger;
182
229
  private readonly responseParser;
183
230
  /**
@@ -189,9 +236,9 @@ declare class OpenAIProvider extends AbstractAIProvider {
189
236
  onTextDelta?: TTextDeltaCallback;
190
237
  constructor(options: IOpenAIProviderOptions);
191
238
  chat(messages: TUniversalMessage[], options?: IChatOptions): Promise<TUniversalMessage>;
192
- private chatWithStreamingAssembly;
193
239
  chatStream(messages: TUniversalMessage[], options?: IChatOptions): AsyncIterable<TUniversalMessage>;
194
240
  supportsTools(): boolean;
241
+ getCapabilities(): IProviderCapabilities;
195
242
  validateConfig(): boolean;
196
243
  dispose(): Promise<void>;
197
244
  protected validateMessages(messages: TUniversalMessage[]): void;
@@ -232,8 +279,7 @@ declare class OpenAIConversationAdapter {
232
279
  }
233
280
 
234
281
  declare const DEFAULT_OPENAI_PROVIDER_MODEL: string | undefined;
235
- declare const DEFAULT_OPENAI_COMPATIBLE_PROVIDER_API_KEY = "lm-studio";
236
- declare const DEFAULT_OPENAI_COMPATIBLE_PROVIDER_BASE_URL = "http://localhost:1234/v1";
282
+ declare const DEFAULT_OPENAI_PROVIDER_API_KEY_REFERENCE = "$ENV:OPENAI_API_KEY";
237
283
  declare function createOpenAIProviderDefinition(): IProviderDefinition;
238
284
 
239
- export { DEFAULT_OPENAI_COMPATIBLE_PROVIDER_API_KEY, DEFAULT_OPENAI_COMPATIBLE_PROVIDER_BASE_URL, DEFAULT_OPENAI_PROVIDER_MODEL, type IOpenAIProviderOptions, type IPayloadLogger, type IPayloadLoggerOptions, OpenAIConversationAdapter, OpenAIProvider, type TOpenAIProviderOptionValue, createOpenAIProviderDefinition };
285
+ export { DEFAULT_OPENAI_PROVIDER_API_KEY_REFERENCE, DEFAULT_OPENAI_PROVIDER_MODEL, type IOpenAIJsonSchemaDefinition, type IOpenAINativeWebToolsOptions, type IOpenAIProviderOptions, type IOpenAIResponsesReasoningOptions, type IPayloadLogger, type IPayloadLoggerOptions, OpenAIConversationAdapter, OpenAIProvider, type TOpenAIApiSurface, type TOpenAIProviderOptionValue, createOpenAIProviderDefinition };
@@ -1,5 +1,5 @@
1
1
  import OpenAI from 'openai';
2
- import { ILogger, IExecutor, TProviderOptionValueBase, AbstractAIProvider, TTextDeltaCallback, TUniversalMessage, IChatOptions, IProviderDefinition } from '@robota-sdk/agent-core';
2
+ import { ILogger, IExecutor, TProviderOptionValueBase, AbstractAIProvider, TTextDeltaCallback, TUniversalMessage, IChatOptions, IProviderCapabilities, IProviderDefinition } from '@robota-sdk/agent-core';
3
3
 
4
4
  /**
5
5
  * Payload logging data structure
@@ -56,10 +56,25 @@ interface IPayloadLoggerOptions {
56
56
  logger?: ILogger;
57
57
  }
58
58
 
59
+ type TOpenAIApiSurface = 'responses' | 'chat-completions';
60
+ interface IOpenAIJsonSchemaDefinition {
61
+ name: string;
62
+ description?: string;
63
+ schema?: Record<string, TOpenAIProviderOptionValue>;
64
+ strict?: boolean;
65
+ }
66
+ interface IOpenAIResponsesReasoningOptions {
67
+ effort?: 'low' | 'medium' | 'high';
68
+ summary?: 'auto' | 'concise' | 'detailed';
69
+ }
70
+ interface IOpenAINativeWebToolsOptions {
71
+ webSearch?: boolean;
72
+ webFetch?: boolean;
73
+ }
59
74
  /**
60
75
  * Valid provider option value types
61
76
  */
62
- type TOpenAIProviderOptionValue = string | number | boolean | undefined | null | OpenAI | IPayloadLogger | ILogger | IExecutor | TProviderOptionValueBase | TOpenAIProviderOptionValue[] | {
77
+ type TOpenAIProviderOptionValue = string | number | boolean | undefined | null | IOpenAIJsonSchemaDefinition | IOpenAINativeWebToolsOptions | IOpenAIResponsesReasoningOptions | OpenAI | IPayloadLogger | ILogger | IExecutor | TProviderOptionValueBase | TOpenAIProviderOptionValue[] | {
63
78
  [key: string]: TOpenAIProviderOptionValue;
64
79
  };
65
80
  /**
@@ -86,6 +101,17 @@ interface IOpenAIProviderOptions {
86
101
  * API base URL (default: 'https://api.openai.com/v1')
87
102
  */
88
103
  baseURL?: string;
104
+ /**
105
+ * Default model used when chat options do not provide a model.
106
+ */
107
+ defaultModel?: string;
108
+ /**
109
+ * API surface to use for direct OpenAI calls.
110
+ *
111
+ * Defaults to Responses for official OpenAI calls. Profiles with baseURL use
112
+ * Chat Completions by default for OpenAI-compatible endpoint compatibility.
113
+ */
114
+ apiSurface?: TOpenAIApiSurface;
89
115
  /**
90
116
  * Response format (default: 'text')
91
117
  * - 'text': Plain text response
@@ -96,12 +122,32 @@ interface IOpenAIProviderOptions {
96
122
  /**
97
123
  * JSON schema for structured outputs (required when responseFormat is 'json_schema')
98
124
  */
99
- jsonSchema?: {
100
- name: string;
101
- description?: string;
102
- schema?: Record<string, TOpenAIProviderOptionValue>;
103
- strict?: boolean;
104
- };
125
+ jsonSchema?: IOpenAIJsonSchemaDefinition;
126
+ /**
127
+ * Responses API reasoning controls. Hidden reasoning is never exposed in message
128
+ * content; only explicit summaries/encrypted items requested here are represented.
129
+ */
130
+ reasoning?: IOpenAIResponsesReasoningOptions;
131
+ /**
132
+ * Whether OpenAI should store Responses API results. Defaults to OpenAI API behavior.
133
+ */
134
+ store?: boolean;
135
+ /**
136
+ * Include encrypted reasoning items for stateless reasoning continuation.
137
+ */
138
+ includeEncryptedReasoning?: boolean;
139
+ /**
140
+ * Opt into strict custom function parameter validation where supported.
141
+ */
142
+ strictTools?: boolean;
143
+ /**
144
+ * Provider-native hosted web tool request from provider profile options.
145
+ *
146
+ * OpenAI-compatible Chat Completions endpoints do not support this Robota
147
+ * native web contract. The provider rejects unsupported configurations before
148
+ * any model request is sent.
149
+ */
150
+ nativeWebTools?: IOpenAINativeWebToolsOptions;
105
151
  /**
106
152
  * OpenAI client instance (optional: will be created from apiKey if not provided)
107
153
  */
@@ -168,7 +214,7 @@ interface IOpenAIProviderOptions {
168
214
  /**
169
215
  * OpenAI provider implementation for Robota
170
216
  *
171
- * Provides integration with OpenAI's GPT models following BaseAIProvider guidelines.
217
+ * Provides integration with OpenAI models through the Robota provider contract.
172
218
  * Uses OpenAI SDK native types internally for optimal performance and feature support.
173
219
  *
174
220
  * @public
@@ -178,6 +224,7 @@ declare class OpenAIProvider extends AbstractAIProvider {
178
224
  readonly version = "1.0.0";
179
225
  private readonly client?;
180
226
  private readonly options;
227
+ private readonly apiSurface;
181
228
  private readonly payloadLogger;
182
229
  private readonly responseParser;
183
230
  /**
@@ -189,9 +236,9 @@ declare class OpenAIProvider extends AbstractAIProvider {
189
236
  onTextDelta?: TTextDeltaCallback;
190
237
  constructor(options: IOpenAIProviderOptions);
191
238
  chat(messages: TUniversalMessage[], options?: IChatOptions): Promise<TUniversalMessage>;
192
- private chatWithStreamingAssembly;
193
239
  chatStream(messages: TUniversalMessage[], options?: IChatOptions): AsyncIterable<TUniversalMessage>;
194
240
  supportsTools(): boolean;
241
+ getCapabilities(): IProviderCapabilities;
195
242
  validateConfig(): boolean;
196
243
  dispose(): Promise<void>;
197
244
  protected validateMessages(messages: TUniversalMessage[]): void;
@@ -232,8 +279,7 @@ declare class OpenAIConversationAdapter {
232
279
  }
233
280
 
234
281
  declare const DEFAULT_OPENAI_PROVIDER_MODEL: string | undefined;
235
- declare const DEFAULT_OPENAI_COMPATIBLE_PROVIDER_API_KEY = "lm-studio";
236
- declare const DEFAULT_OPENAI_COMPATIBLE_PROVIDER_BASE_URL = "http://localhost:1234/v1";
282
+ declare const DEFAULT_OPENAI_PROVIDER_API_KEY_REFERENCE = "$ENV:OPENAI_API_KEY";
237
283
  declare function createOpenAIProviderDefinition(): IProviderDefinition;
238
284
 
239
- export { DEFAULT_OPENAI_COMPATIBLE_PROVIDER_API_KEY, DEFAULT_OPENAI_COMPATIBLE_PROVIDER_BASE_URL, DEFAULT_OPENAI_PROVIDER_MODEL, type IOpenAIProviderOptions, type IPayloadLogger, type IPayloadLoggerOptions, OpenAIConversationAdapter, OpenAIProvider, type TOpenAIProviderOptionValue, createOpenAIProviderDefinition };
285
+ export { DEFAULT_OPENAI_PROVIDER_API_KEY_REFERENCE, DEFAULT_OPENAI_PROVIDER_MODEL, type IOpenAIJsonSchemaDefinition, type IOpenAINativeWebToolsOptions, type IOpenAIProviderOptions, type IOpenAIResponsesReasoningOptions, type IPayloadLogger, type IPayloadLoggerOptions, OpenAIConversationAdapter, OpenAIProvider, type TOpenAIApiSurface, type TOpenAIProviderOptionValue, createOpenAIProviderDefinition };
@@ -1,2 +1 @@
1
- import C from'openai';import {AbstractAIProvider,SilentLogger}from'@robota-sdk/agent-core';import {assembleOpenAICompatibleStream,probeOpenAICompatibleProfile,OpenAICompatibleResponseParser,convertToOpenAICompatibleMessages,convertToOpenAICompatibleTools}from'@robota-sdk/agent-provider-openai-compatible';var p=class{parser;constructor(e){this.parser=new OpenAICompatibleResponseParser({logger:e});}parseResponse(e){try{return this.parser.parseResponse(e)}catch(t){let r=d(t instanceof Error?t.message:"OpenAI response parsing failed");throw new Error(`OpenAI response parsing failed: ${r}`)}}parseStreamingChunk(e){try{return this.parser.parseStreamingChunk(e)}catch(t){let r=d(t instanceof Error?t.message:"OpenAI chunk parsing failed");throw new Error(`OpenAI chunk parsing failed: ${r}`)}}};function d(a){return a.replace(/^OpenAI-compatible response parsing failed: /,"").replace(/^OpenAI-compatible chunk parsing failed: /,"").replace("OpenAI-compatible response","OpenAI response")}function m(a){return convertToOpenAICompatibleMessages(a)}function c(a){return convertToOpenAICompatibleTools(a)}var i=class extends AbstractAIProvider{name="openai";version="1.0.0";client;options;payloadLogger;responseParser;onTextDelta;constructor(e){if(super(e.logger||SilentLogger),this.options=e,e.executor&&(this.executor=e.executor),!this.executor)if(e.client)this.client=e.client;else if(e.apiKey)this.client=new C({apiKey:e.apiKey,...e.organization&&{organization:e.organization},...e.timeout&&{timeout:e.timeout},...e.baseURL&&{baseURL:e.baseURL}});else throw new Error("Either OpenAI client, apiKey, or executor is required");this.responseParser=new p(this.logger),this.payloadLogger=e.payloadLogger;}async chat(e,t){if(this.validateMessages(e),this.executor)try{return await this.executeViaExecutorOrDirect(e,t)}catch(r){throw this.logger.error("OpenAI Provider executor chat error:",r instanceof Error?r.message:String(r)),r}if(!this.client)throw new Error("OpenAI client not available. Either provide a client/apiKey or use an executor.");try{let r=m(e),o=t;if(!o?.model)throw new Error("Model is required in chat options. Please specify a model in defaultModel configuration.");let s={model:o.model,messages:r,...o.temperature!==void 0&&{temperature:o.temperature},...o.maxTokens&&{max_tokens:o.maxTokens},...o.tools&&{tools:c(o.tools),tool_choice:"auto"}},n=o.onTextDelta??this.onTextDelta;if(n)return await this.chatWithStreamingAssembly({...s,stream:!0},{...o,onTextDelta:n});if(this.payloadLogger?.isEnabled()){let I={model:s.model,messagesCount:r.length,hasTools:!!s.tools,temperature:s.temperature??void 0,maxTokens:s.max_tokens??void 0,timestamp:new Date().toISOString()};await this.payloadLogger.logPayload(I,"chat");}let l=await this.client.chat.completions.create(s);return this.responseParser.parseResponse(l)}catch(r){let s=r.message||"OpenAI API request failed";throw new Error(`OpenAI chat failed: ${s}`)}}async chatWithStreamingAssembly(e,t){if(!this.client)throw new Error("OpenAI client not available. Either provide a client/apiKey or use an executor.");try{if(this.payloadLogger?.isEnabled()){let o={model:e.model,messagesCount:e.messages.length,hasTools:!!e.tools,temperature:e.temperature??void 0,maxTokens:e.max_tokens??void 0,timestamp:new Date().toISOString()};await this.payloadLogger.logPayload(o,"stream");}let r=await this.client.chat.completions.create(e,t.signal?{signal:t.signal}:void 0);return assembleOpenAICompatibleStream({stream:r,onTextDelta:t.onTextDelta,signal:t.signal})}catch(r){let s=r.message||"OpenAI streaming request failed";throw new Error(`OpenAI stream failed: ${s}`)}}async*chatStream(e,t){if(this.executor)try{yield*this.executeStreamViaExecutorOrDirect(e,t);return}catch(r){throw this.logger.error("OpenAI Provider executor stream error:",r instanceof Error?r.message:String(r)),r}if(!this.client)throw new Error("OpenAI client not available. Either provide a client/apiKey or use an executor.");try{let r=m(e);if(!t?.model)throw new Error("Model is required in chat options. Please specify a model in defaultModel configuration.");let o={model:t.model,messages:r,stream:!0,...t?.temperature!==void 0&&{temperature:t.temperature},...t?.maxTokens&&{max_tokens:t.maxTokens},...t?.tools&&{tools:c(t.tools),tool_choice:"auto"}};if(this.payloadLogger?.isEnabled()){let n={model:o.model,messagesCount:r.length,hasTools:!!o.tools,temperature:o.temperature??void 0,maxTokens:o.max_tokens??void 0,timestamp:new Date().toISOString()};await this.payloadLogger.logPayload(n,"stream");}let s=await this.client.chat.completions.create(o);for await(let n of s){let l=this.responseParser.parseStreamingChunk(n);l&&(yield l);}}catch(r){let s=r.message||"OpenAI API request failed";throw new Error(`OpenAI stream failed: ${s}`)}}supportsTools(){return true}validateConfig(){return !!this.client&&!!this.options}async dispose(){}validateMessages(e){super.validateMessages(e);for(let t of e)if(t.role==="assistant"){let r=t;if(r.toolCalls&&r.toolCalls.length>0&&r.content==="")continue}}};var g=class{static filterMessagesForOpenAI(e){return e.filter(t=>t.role==="user"||t.role==="assistant"||t.role==="system"?true:t.role==="tool"?!!(t.toolCallId&&t.toolCallId.trim()!==""&&t.toolCallId!=="unknown"):false)}static toOpenAIFormat(e){return this.filterMessagesForOpenAI(e).map(r=>this.convertMessage(r))}static convertMessage(e){let t=e.role;if(t==="user")return {role:"user",content:e.content};if(t==="assistant"){let o=e;return o.toolCalls&&o.toolCalls.length>0?{role:"assistant",content:o.content===""?null:o.content||null,tool_calls:o.toolCalls.map(n=>({id:n.id,type:"function",function:{name:n.function.name,arguments:n.function.arguments}}))}:{role:"assistant",content:o.content===null||o.content===""?null:o.content||""}}if(t==="system")return {role:"system",content:e.content};if(t==="tool"){if(!e.toolCallId||e.toolCallId.trim()==="")throw new Error(`Tool message missing toolCallId: ${JSON.stringify(e)}`);return {role:"tool",content:e.content,tool_call_id:e.toolCallId}}let r=t;throw new Error(`Unsupported message role: ${r}`)}static addSystemPromptIfNeeded(e,t){return !t||e.some(o=>o.role==="system")?e:[{role:"system",content:t},...e]}};var F=void 0,h="lm-studio",f="http://localhost:1234/v1";function z(){return {type:"openai",displayName:"OpenAI Compatible",description:"OpenAI or OpenAI-compatible Chat Completions endpoint",defaults:{apiKey:h,baseURL:f},setupSteps:[{key:"baseURL",title:"OpenAI-compatible base URL",defaultValue:f},{key:"model",title:"OpenAI-compatible model",required:true},{key:"apiKey",title:"OpenAI-compatible API key",defaultValue:h,masked:true}],requiresApiKey:true,probeProfile:probeOpenAICompatibleProfile,createProvider:a=>new i({apiKey:x(a.apiKey),...a.baseURL!==void 0&&{baseURL:a.baseURL},...a.timeout!==void 0&&{timeout:a.timeout},defaultModel:a.model})}}function x(a){if(!a)throw new Error("Provider openai requires apiKey");return a}
2
- export{h as DEFAULT_OPENAI_COMPATIBLE_PROVIDER_API_KEY,f as DEFAULT_OPENAI_COMPATIBLE_PROVIDER_BASE_URL,F as DEFAULT_OPENAI_PROVIDER_MODEL,g as OpenAIConversationAdapter,i as OpenAIProvider,z as createOpenAIProviderDefinition};
1
+ import ye from'openai';import {AbstractAIProvider,SilentLogger}from'@robota-sdk/agent-core';import {probeOpenAICompatibleProfile,OpenAICompatibleResponseParser,assembleOpenAICompatibleStream,convertToOpenAICompatibleMessages,convertToOpenAICompatibleTools}from'@robota-sdk/agent-provider-openai-compatible';import {randomUUID}from'crypto';var i=class{parser;constructor(t){this.parser=new OpenAICompatibleResponseParser({logger:t});}parseResponse(t){try{return this.parser.parseResponse(t)}catch(n){let s=f(n instanceof Error?n.message:"OpenAI response parsing failed");throw new Error(`OpenAI response parsing failed: ${s}`)}}parseStreamingChunk(t){try{return this.parser.parseStreamingChunk(t)}catch(n){let s=f(n instanceof Error?n.message:"OpenAI chunk parsing failed");throw new Error(`OpenAI chunk parsing failed: ${s}`)}}};function f(e){return e.replace(/^OpenAI-compatible response parsing failed: /,"").replace(/^OpenAI-compatible chunk parsing failed: /,"").replace("OpenAI-compatible response","OpenAI response")}function O(e){if(e.responseFormat===void 0||e.responseFormat==="text")return;if(e.responseFormat==="json_object")return {type:"json_object"};let t=g(e);return {type:"json_schema",json_schema:{name:t.name,schema:t.schema,...t.description!==void 0&&{description:t.description},...t.strict!==void 0&&{strict:t.strict}}}}function h(e){if(e.responseFormat===void 0||e.responseFormat==="text")return;if(e.responseFormat==="json_object")return {format:{type:"json_object"}};let t=g(e);return {format:{type:"json_schema",name:t.name,schema:t.schema,...t.description!==void 0&&{description:t.description},...t.strict!==void 0&&{strict:t.strict}}}}function g(e){let t=e.jsonSchema;if(e.responseFormat!=="json_schema")throw new Error(`Unsupported OpenAI response format: ${e.responseFormat}`);if(!t?.schema)throw new Error("OpenAI jsonSchema.schema is required when responseFormat is json_schema");return {name:t.name,schema:t.schema,...t.description!==void 0&&{description:t.description},...t.strict!==void 0&&{strict:t.strict}}}function A(e){return convertToOpenAICompatibleMessages(e)}function T(e){return convertToOpenAICompatibleTools(e)}async function R(e){let t=b(e.client);try{let n=v(e);if(e.chatOptions?.onTextDelta??e.onTextDelta)return await G(t,e,{...n,stream:!0});await u(e,n,"chat");let o=await t.chat.completions.create(n);return e.responseParser.parseResponse(o)}catch(n){let o=n.message||"OpenAI API request failed";throw new Error(`OpenAI chat failed: ${o}`)}}async function*C(e){let t=b(e.client);try{let n={...v(e),stream:!0};await u(e,n,"stream");let s=await t.chat.completions.create(n,e.chatOptions?.signal?{signal:e.chatOptions.signal}:void 0);for await(let o of s){let r=e.responseParser.parseStreamingChunk(o);r&&(yield r);}}catch(n){let o=n.message||"OpenAI API request failed";throw new Error(`OpenAI stream failed: ${o}`)}}function v(e){let t=A(e.messages),n=e.chatOptions?.model??e.providerOptions.defaultModel;if(!n)throw new Error("Model is required in chat options. Please specify a model in defaultModel configuration.");let s=O(e.providerOptions);return {model:n,messages:t,...e.chatOptions?.temperature!==void 0&&{temperature:e.chatOptions.temperature},...e.chatOptions?.maxTokens!==void 0&&{max_tokens:e.chatOptions.maxTokens},...e.chatOptions?.tools&&{tools:T(e.chatOptions.tools),tool_choice:"auto"},...s!==void 0&&{response_format:s}}}async function G(e,t,n){try{await u(t,n,"stream");let s=await e.chat.completions.create(n,t.chatOptions?.signal?{signal:t.chatOptions.signal}:void 0);return assembleOpenAICompatibleStream({stream:s,onTextDelta:t.chatOptions?.onTextDelta??t.onTextDelta,signal:t.chatOptions?.signal})}catch(s){let r=s.message||"OpenAI streaming request failed";throw new Error(`OpenAI stream failed: ${r}`)}}async function u(e,t,n){if(!e.payloadLogger?.isEnabled())return;let s={model:t.model,messagesCount:t.messages.length,hasTools:!!t.tools,temperature:t.temperature??void 0,maxTokens:t.max_tokens??void 0,timestamp:new Date().toISOString()};await e.payloadLogger.logPayload(s,n);}function b(e){if(!e)throw new Error("OpenAI client not available. Either provide a client/apiKey or use an executor.");return e}function S(e){return e.flatMap(t=>B(t))}function x(e,t){let n=e?.map(s=>({type:"function",name:s.name,description:s.description,parameters:s.parameters,strict:t??false}))??[];return n.length>0?n:void 0}function B(e){if(e.role==="user")return [p("user",X(e.content,e.parts))];if(e.role==="system")return [p("system",e.content)];if(e.role==="tool"){if(!e.toolCallId||e.toolCallId.trim().length===0)throw new Error(`Tool message missing toolCallId: ${JSON.stringify(e)}`);return [{type:"function_call_output",call_id:e.toolCallId,output:e.content||""}]}return H(e)}function H(e){let t=[];e.content&&e.content.length>0&&t.push(p("assistant",e.content));for(let n of e.toolCalls??[])t.push({type:"function_call",call_id:n.id,name:n.function.name,arguments:n.function.arguments});return t.length===0&&t.push(p("assistant","")),t}function X(e,t){if(!t||t.length===0)return e;let n=t.map(s=>Z(s));return e.length>0&&!t.some(s=>s.type==="text")?[{type:"input_text",text:e},...n]:n}function Z(e){return e.type==="text"?{type:"input_text",text:e.text}:e.type==="image_uri"?{type:"input_image",image_url:e.uri}:{type:"input_image",image_url:`data:${e.mimeType};base64,${e.data}`}}function p(e,t){return {role:e,content:t}}async function*M(e,t){let n=e[Symbol.asyncIterator]();try{for(;!t?.aborted;){let s=await ee(n,t);if(s.done||t?.aborted)break;yield s.value;}}finally{t?.aborted&&await n.return?.();}}async function ee(e,t){if(!t)return e.next();if(t.aborted)return {done:true,value:void 0};let n,s=new Promise(o=>{n=()=>o({done:true,value:void 0}),t.addEventListener("abort",n,{once:true});});try{return await Promise.race([e.next(),s])}finally{n&&t.removeEventListener("abort",n);}}function w(e){L(e);let t=e.output??[],n=e.output_text??k(t);return m({content:n,toolCalls:E(t),response:e,reasoning:l(t)})}async function P(e){let t={textParts:[],toolCalls:[],reasoning:F()};for await(let n of M(e.stream,e.signal))ne(t,n,e.onTextDelta);return t.completedResponse!==void 0?oe(t):m({content:t.textParts.join(""),toolCalls:t.toolCalls,reasoning:t.reasoning})}function ne(e,t,n){if(t.type==="response.output_text.delta"){e.textParts.push(t.delta),n?.(t.delta);return}if(t.type==="response.completed"){e.completedResponse=t.response,d(e.reasoning,l(t.response.output??[]));return}if(t.type==="response.output_item.done"){se(e,t.item);return}if(t.type==="response.error"||t.type==="response.failed"||t.type==="response.incomplete")throw new Error(`OpenAI Responses API failed: ${ce(t)}`)}function se(e,t){if(U(t)){e.toolCalls.push(D(t));return}_(t)&&d(e.reasoning,l([t]));}function oe(e){let t=e.completedResponse;if(t===void 0)throw new Error("OpenAI Responses stream completed without response metadata");L(t);let n=t.output??[],s=E(n),o=e.textParts.length>0?e.textParts.join(""):t.output_text??k(n),r=l(n);return d(r,e.reasoning),m({content:o,toolCalls:s.length>0?s:e.toolCalls,response:t,reasoning:r})}function m(e){return {id:randomUUID(),role:"assistant",content:e.content,state:"complete",timestamp:new Date,...e.toolCalls.length>0&&{toolCalls:e.toolCalls},...e.response?.usage!==void 0&&{usage:ae(e.response.usage)},metadata:re(e.response,e.reasoning)}}function re(e,t){return {providerApiSurface:"responses",...e?.id!==void 0&&{responseId:e.id},...e?.model!==void 0&&{model:e.model},...e?.status!==void 0&&{finishReason:e.status},...t.reasoningSummaryCount>0&&{reasoningSummaryCount:t.reasoningSummaryCount,reasoningSummaries:t.reasoningSummaries},...t.hasEncryptedReasoning&&{hasEncryptedReasoning:true}}}function ae(e){return {promptTokens:e.input_tokens??0,completionTokens:e.output_tokens??0,totalTokens:e.total_tokens??0}}function E(e){return e.filter(U).map(t=>D(t))}function U(e){return e.type==="function_call"&&"call_id"in e&&"name"in e&&"arguments"in e}function D(e){return {id:e.call_id,type:"function",function:{name:e.name,arguments:e.arguments}}}function k(e){return e.filter(pe).flatMap(t=>t.content).map(ie).join("")}function ie(e){return e.type==="refusal"?e.refusal:e.text}function pe(e){return e.type==="message"&&"content"in e&&Array.isArray(e.content)}function l(e){let t=F();for(let n of e){if(!_(n))continue;let s=n.summary?.map(o=>o.text).filter(le)??[];t.reasoningSummaryCount+=s.length,t.reasoningSummaries.push(...s),t.hasEncryptedReasoning=t.hasEncryptedReasoning||!!n.encrypted_content;}return t}function _(e){return e.type==="reasoning"}function F(){return {reasoningSummaryCount:0,reasoningSummaries:[],hasEncryptedReasoning:false}}function d(e,t){e.reasoningSummaryCount+=t.reasoningSummaryCount,e.reasoningSummaries.push(...t.reasoningSummaries),e.hasEncryptedReasoning=e.hasEncryptedReasoning||t.hasEncryptedReasoning;}function le(e){return e!==void 0}function L(e){if(e.status==="failed"||e.status==="incomplete")throw new Error(`OpenAI Responses API failed: ${e.error?.message??e.status}`)}function ce(e){return e.message??e.error?.message??e.response?.error?.message??"unknown error"}async function W(e){let t=e.chatOptions?.onTextDelta??e.onTextDelta;if(t)return j({...e,chatOptions:{...e.chatOptions,onTextDelta:t}});if(!e.client)throw new Error("OpenAI Responses client not available.");try{let n=$(e),s=await e.client.responses.create(n,e.chatOptions?.signal?{signal:e.chatOptions.signal}:void 0);return w(s)}catch(n){let o=n.message||"OpenAI Responses API request failed";throw new Error(`OpenAI responses failed: ${o}`)}}async function*N(e){let t={deltas:[]},n=e.chatOptions?.onTextDelta??e.onTextDelta,s=j({...e,chatOptions:{...e.chatOptions,onTextDelta:o=>{n?.(o),fe(t,de(o));}}}).then(o=>Oe(t,o)).catch(o=>he(t,Te(o)));yield*Ie(t),await s;}async function j(e){if(!e.client)throw new Error("OpenAI Responses client not available.");try{let t=me(e),n=await e.client.responses.create(t,e.chatOptions?.signal?{signal:e.chatOptions.signal}:void 0);return P({stream:n,onTextDelta:e.chatOptions?.onTextDelta,signal:e.chatOptions?.signal})}catch(t){let s=t.message||"OpenAI Responses streaming request failed";throw new Error(`OpenAI responses stream failed: ${s}`)}}function $(e){let t=e.chatOptions?.model??e.providerOptions.defaultModel;if(!t)throw new Error("Model is required in chat options. Please specify a model in defaultModel configuration.");let n=x(e.chatOptions?.tools,e.providerOptions.strictTools),s=h(e.providerOptions);return {model:t,input:S(e.messages),...n!==void 0&&{tools:n,tool_choice:"auto"},...e.chatOptions?.temperature!==void 0&&{temperature:e.chatOptions.temperature},...e.chatOptions?.maxTokens!==void 0&&{max_output_tokens:e.chatOptions.maxTokens},...s!==void 0&&{text:s},...e.providerOptions.reasoning!==void 0&&{reasoning:e.providerOptions.reasoning},...e.providerOptions.includeEncryptedReasoning===true&&{include:["reasoning.encrypted_content"]},...e.providerOptions.store!==void 0&&{store:e.providerOptions.store}}}function me(e){return {...$(e),stream:true}}function de(e){return {id:randomUUID(),role:"assistant",content:e,state:"complete",timestamp:new Date,metadata:{providerApiSurface:"responses",isStreamChunk:true,isComplete:false}}}async function*Ie(e){for(;;){let t=e.deltas.shift();if(t!==void 0){yield t;continue}if(e.error!==void 0)throw e.error;if(e.finalMessage!==void 0){yield Ae(e.finalMessage);return}await ge(e);}}function fe(e,t){e.deltas.push(t),I(e);}function Oe(e,t){e.finalMessage=t,I(e);}function he(e,t){e.error=t,I(e);}function ge(e){return new Promise(t=>{e.wake=t;})}function I(e){e.wake?.(),e.wake=void 0;}function Ae(e){return {...e,content:"",metadata:{...e.metadata,isStreamChunk:true,isComplete:true}}}function Te(e){return e instanceof Error?e:new Error(String(e))}var a=class extends AbstractAIProvider{name="openai";version="1.0.0";client;options;apiSurface;payloadLogger;responseParser;onTextDelta;constructor(t){if(super(t.logger||SilentLogger),this.options=t,this.apiSurface=ve(t),be(this.apiSurface,t.nativeWebTools),t.executor&&(this.executor=t.executor),!this.executor)if(t.client)this.client=t.client;else if(t.apiKey)this.client=new ye({apiKey:t.apiKey,...t.organization&&{organization:t.organization},...t.timeout&&{timeout:t.timeout},...t.baseURL&&{baseURL:t.baseURL}});else throw new Error("Either OpenAI client, apiKey, or executor is required");this.responseParser=new i(this.logger),this.payloadLogger=t.payloadLogger;}async chat(t,n){if(this.validateMessages(t),this.validateNativeWebTools(n?.nativeWebTools),this.executor)try{return await this.executeViaExecutorOrDirect(t,n)}catch(s){throw this.logger.error("OpenAI Provider executor chat error:",s instanceof Error?s.message:String(s)),s}return this.apiSurface==="responses"?W({client:this.client,messages:t,chatOptions:n,providerOptions:this.options,onTextDelta:this.onTextDelta}):R({client:this.client,messages:t,chatOptions:n,providerOptions:this.options,payloadLogger:this.payloadLogger,responseParser:this.responseParser,onTextDelta:this.onTextDelta})}async*chatStream(t,n){if(this.validateNativeWebTools(n?.nativeWebTools),this.executor)try{yield*this.executeStreamViaExecutorOrDirect(t,n);return}catch(s){throw this.logger.error("OpenAI Provider executor stream error:",s instanceof Error?s.message:String(s)),s}if(this.apiSurface==="responses"){yield*N({client:this.client,messages:t,chatOptions:n,providerOptions:this.options,onTextDelta:this.onTextDelta});return}yield*C({client:this.client,messages:t,chatOptions:n,providerOptions:this.options,payloadLogger:this.payloadLogger,responseParser:this.responseParser,onTextDelta:this.onTextDelta});}supportsTools(){return true}getCapabilities(){let t=this.apiSurface==="chat-completions"?"openai-compatible-chat-completions":"openai-responses";return {functionCalling:{supported:true},nativeWebTools:{webSearch:{supported:false,enabled:false,source:t,reason:q(this.apiSurface,"search")},webFetch:{supported:false,enabled:false,source:t,reason:q(this.apiSurface,"fetch")}}}}validateConfig(){return !!this.client&&!!this.options}async dispose(){}validateMessages(t){super.validateMessages(t);for(let n of t)if(n.role==="assistant"){let s=n;if(s.toolCalls&&s.toolCalls.length>0&&s.content==="")continue}}};function ve(e){return e.apiSurface!==void 0?e.apiSurface:e.baseURL?"chat-completions":"responses"}function q(e,t){return e==="chat-completions"?`OpenAI-compatible Chat Completions endpoints support declared function tools, not provider-native web ${t}.`:`OpenAI Responses native web ${t} is not wired in this Robota provider version.`}function be(e,t){if(!(t?.webSearch!==true&&t?.webFetch!==true))throw new Error(`Provider openai native web search/fetch is not supported for apiSurface ${e} in this Robota provider version.`)}var Q=class{static filterMessagesForOpenAI(t){return t.filter(n=>n.role==="user"||n.role==="assistant"||n.role==="system"?true:n.role==="tool"?!!(n.toolCallId&&n.toolCallId.trim()!==""&&n.toolCallId!=="unknown"):false)}static toOpenAIFormat(t){return this.filterMessagesForOpenAI(t).map(s=>this.convertMessage(s))}static convertMessage(t){let n=t.role;if(n==="user")return {role:"user",content:t.content};if(n==="assistant"){let o=t;return o.toolCalls&&o.toolCalls.length>0?{role:"assistant",content:o.content===""?null:o.content||null,tool_calls:o.toolCalls.map(c=>({id:c.id,type:"function",function:{name:c.function.name,arguments:c.function.arguments}}))}:{role:"assistant",content:o.content===null||o.content===""?null:o.content||""}}if(n==="system")return {role:"system",content:t.content};if(n==="tool"){if(!t.toolCallId||t.toolCallId.trim()==="")throw new Error(`Tool message missing toolCallId: ${JSON.stringify(t)}`);return {role:"tool",content:t.content,tool_call_id:t.toolCallId}}let s=n;throw new Error(`Unsupported message role: ${s}`)}static addSystemPromptIfNeeded(t,n){return !n||t.some(o=>o.role==="system")?t:[{role:"system",content:n},...t]}};var pt=void 0,V="$ENV:OPENAI_API_KEY";function lt(){return {type:"openai",displayName:"OpenAI",description:"Official OpenAI Responses API provider",defaults:{apiKey:V},setupSteps:[{key:"model",title:"OpenAI model",required:true},{key:"apiKey",title:"OpenAI API key",defaultValue:V,masked:true}],requiresApiKey:true,probeProfile:probeOpenAICompatibleProfile,createProvider:e=>{let t=Me(e.options),n=we(e.options);return Pe(e.baseURL,t,n),new a({apiKey:xe(e.apiKey),...e.baseURL!==void 0&&{baseURL:e.baseURL},...e.timeout!==void 0&&{timeout:e.timeout},...t!==void 0&&{apiSurface:t},...n!==void 0&&{nativeWebTools:n},defaultModel:e.model})}}}function xe(e){if(!e)throw new Error("Provider openai requires apiKey");return e}function Me(e){let t=e?.apiSurface;if(t==="responses"||t==="chat-completions")return t}function we(e){let t=K(e?.nativeWebTools)??K(e?.builtInWebTools);if(t!==void 0)return t}function K(e){if(e==null||e instanceof Date||Array.isArray(e)||typeof e!="object")return;let t=e.webSearch,n=e.webFetch;return {...typeof t=="boolean"&&{webSearch:t},...typeof n=="boolean"&&{webFetch:n}}}function Pe(e,t,n){if(!(n?.webSearch!==true&&n?.webFetch!==true))throw e!==void 0||t==="chat-completions"?new Error("Provider openai profile uses an OpenAI-compatible Chat Completions endpoint; native web search/fetch is not supported for this profile. Use Robota local WebSearch/WebFetch tools or a provider with documented hosted web support."):new Error("Provider openai native web search/fetch is not wired in this Robota provider version. Use Robota local WebSearch/WebFetch tools or a provider with documented hosted web support.")}export{V as DEFAULT_OPENAI_PROVIDER_API_KEY_REFERENCE,pt as DEFAULT_OPENAI_PROVIDER_MODEL,Q as OpenAIConversationAdapter,a as OpenAIProvider,lt as createOpenAIProviderDefinition};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@robota-sdk/agent-provider-openai",
3
- "version": "3.0.0-beta.59",
4
- "description": "OpenAI integration for Robota SDK - GPT-4, GPT-3.5, function calling, and tool integration with OpenAI's API",
3
+ "version": "3.0.0-beta.60",
4
+ "description": "OpenAI integration for Robota SDK using the Responses API, structured outputs, streaming, and tool calling",
5
5
  "type": "module",
6
6
  "main": "dist/node/index.js",
7
7
  "module": "dist/node/index.mjs",
@@ -53,7 +53,8 @@
53
53
  "openai",
54
54
  "gpt",
55
55
  "gpt-4",
56
- "gpt-3.5",
56
+ "responses-api",
57
+ "structured-outputs",
57
58
  "chatgpt",
58
59
  "function-calling",
59
60
  "typescript",
@@ -75,10 +76,10 @@
75
76
  "license": "MIT",
76
77
  "dependencies": {
77
78
  "openai": "^4.98.0",
78
- "@robota-sdk/agent-provider-openai-compatible": "3.0.0-beta.59"
79
+ "@robota-sdk/agent-provider-openai-compatible": "3.0.0-beta.60"
79
80
  },
80
81
  "peerDependencies": {
81
- "@robota-sdk/agent-core": "3.0.0-beta.59"
82
+ "@robota-sdk/agent-core": "3.0.0-beta.60"
82
83
  },
83
84
  "devDependencies": {
84
85
  "@typescript-eslint/eslint-plugin": "^6.18.0",
@@ -88,7 +89,7 @@
88
89
  "tsup": "^8.0.1",
89
90
  "typescript": "^5.3.3",
90
91
  "vitest": "^1.1.0",
91
- "@robota-sdk/agent-core": "3.0.0-beta.59"
92
+ "@robota-sdk/agent-core": "3.0.0-beta.60"
92
93
  },
93
94
  "publishConfig": {
94
95
  "access": "public"