diff --git a/bindings/typescript/src/generated/openai/ConnectorId.ts b/bindings/typescript/src/generated/openai/ConnectorId.ts index 039c3e76..17dd219f 100644 --- a/bindings/typescript/src/generated/openai/ConnectorId.ts +++ b/bindings/typescript/src/generated/openai/ConnectorId.ts @@ -2,8 +2,8 @@ /** * Identifier for service connectors, like those available in ChatGPT. One of - * `server_url` or `connector_id` must be provided. Learn more about service - * connectors [here](/docs/guides/tools-remote-mcp#connectors). + * `server_url`, `connector_id`, or `tunnel_id` must be provided. Learn more + * about service connectors [here](/docs/guides/tools-remote-mcp#connectors). * * Currently supported `connector_id` values are: * diff --git a/bindings/typescript/src/generated/openai/InputItemTool.ts b/bindings/typescript/src/generated/openai/InputItemTool.ts index 5f5a870a..cbda3738 100644 --- a/bindings/typescript/src/generated/openai/InputItemTool.ts +++ b/bindings/typescript/src/generated/openai/InputItemTool.ts @@ -182,8 +182,8 @@ search_context_size: WebSearchContextSize | null, user_location: ApproximateLoca authorization: string | null, /** * Identifier for service connectors, like those available in ChatGPT. One of - * `server_url` or `connector_id` must be provided. Learn more about service - * connectors [here](/docs/guides/tools-remote-mcp#connectors). + * `server_url`, `connector_id`, or `tunnel_id` must be provided. Learn more + * about service connectors [here](/docs/guides/tools-remote-mcp#connectors). * * Currently supported `connector_id` values are: * @@ -206,10 +206,15 @@ server_description: string | null, */ server_label: string | null, /** - * The URL for the MCP server. One of `server_url` or `connector_id` must be - * provided. + * The URL for the MCP server. One of `server_url`, `connector_id`, or + * `tunnel_id` must be provided. */ server_url: string | null, +/** + * The Secure MCP Tunnel ID to use instead of a direct server URL. One of + * `server_url`, `connector_id`, or `tunnel_id` must be provided. + */ +tunnel_id: string | null, /** * The code interpreter container. Can be a container ID or an object that * specifies uploaded file IDs to make available to your code, along with an diff --git a/crates/generate-types/src/main.rs b/crates/generate-types/src/main.rs index cc28089d..09ec5989 100644 --- a/crates/generate-types/src/main.rs +++ b/crates/generate-types/src/main.rs @@ -185,7 +185,7 @@ fn generate_openai_types_with_quicktype( let quicktype_output = match output { Ok(output) => { if output.status.success() { - String::from_utf8(output.stdout)? + strip_quicktype_preamble(&String::from_utf8(output.stdout)?) } else { return Err(format!( "quicktype failed: {}", @@ -481,7 +481,7 @@ fn generate_anthropic_types_with_quicktype( let quicktype_output = match output { Ok(output) => { if output.status.success() { - String::from_utf8(output.stdout)? + strip_quicktype_preamble(&String::from_utf8(output.stdout)?) } else { return Err(format!( "quicktype failed: {}", @@ -871,6 +871,23 @@ fn ensure_serde_json_imports(content: &str) -> String { new_lines.join("\n") } +fn strip_quicktype_preamble(raw_output: &str) -> String { + let lines: Vec<&str> = raw_output.lines().collect(); + let first_rust_line = lines + .iter() + .position(|line| { + let trimmed = line.trim(); + trimmed.starts_with("//") + || trimmed.starts_with("extern") + || trimmed.starts_with("use ") + || trimmed.starts_with("#[") + || trimmed.starts_with("#![") + || trimmed.starts_with("pub ") + }) + .unwrap_or(0); + lines[first_rust_line..].join("\n") +} + fn post_process_quicktype_output_for_anthropic(quicktype_output: &str) -> String { let mut processed = quicktype_output.to_string(); @@ -1360,7 +1377,9 @@ fn generate_google_types_with_quicktype(spec: &serde_json::Value) { let quicktype_output = match output { Ok(output) => { if output.status.success() { - String::from_utf8(output.stdout).expect("Invalid UTF-8 from quicktype") + strip_quicktype_preamble( + &String::from_utf8(output.stdout).expect("Invalid UTF-8 from quicktype"), + ) } else { println!( "❌ quicktype failed: {}", diff --git a/crates/lingua/src/providers/openai/generated.rs b/crates/lingua/src/providers/openai/generated.rs index 188fdd5d..8e06d395 100644 --- a/crates/lingua/src/providers/openai/generated.rs +++ b/crates/lingua/src/providers/openai/generated.rs @@ -1819,16 +1819,12 @@ pub struct CreateResponseClass { #[serde(skip_serializing_if = "Option::is_none")] pub prompt: Option, #[serde(skip_serializing_if = "Option::is_none")] - pub reasoning: Option, - #[serde(skip_serializing_if = "Option::is_none")] pub text: Option, #[serde(skip_serializing_if = "Option::is_none")] pub tool_choice: Option, #[serde(skip_serializing_if = "Option::is_none")] pub tools: Option>, #[serde(skip_serializing_if = "Option::is_none")] - pub truncation: Option, - #[serde(skip_serializing_if = "Option::is_none")] pub context_management: Option>, #[serde(skip_serializing_if = "Option::is_none")] pub conversation: Option, @@ -1845,11 +1841,15 @@ pub struct CreateResponseClass { #[serde(skip_serializing_if = "Option::is_none")] pub parallel_tool_calls: Option, #[serde(skip_serializing_if = "Option::is_none")] + pub reasoning: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub store: Option, #[serde(skip_serializing_if = "Option::is_none")] pub stream: Option, #[serde(skip_serializing_if = "Option::is_none")] pub stream_options: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub truncation: Option, } /// Context management configuration for this request. @@ -3742,8 +3742,8 @@ pub struct InputItemTool { #[serde(skip_serializing_if = "Option::is_none")] pub authorization: Option, /// Identifier for service connectors, like those available in ChatGPT. One of - /// `server_url` or `connector_id` must be provided. Learn more about service - /// connectors [here](/docs/guides/tools-remote-mcp#connectors). + /// `server_url`, `connector_id`, or `tunnel_id` must be provided. Learn more + /// about service connectors [here](/docs/guides/tools-remote-mcp#connectors). /// /// Currently supported `connector_id` values are: /// @@ -3767,10 +3767,14 @@ pub struct InputItemTool { /// A label for this MCP server, used to identify it in tool calls. #[serde(skip_serializing_if = "Option::is_none")] pub server_label: Option, - /// The URL for the MCP server. One of `server_url` or `connector_id` must be - /// provided. + /// The URL for the MCP server. One of `server_url`, `connector_id`, or + /// `tunnel_id` must be provided. #[serde(skip_serializing_if = "Option::is_none")] pub server_url: Option, + /// The Secure MCP Tunnel ID to use instead of a direct server URL. One of + /// `server_url`, `connector_id`, or `tunnel_id` must be provided. + #[serde(skip_serializing_if = "Option::is_none")] + pub tunnel_id: Option, /// The code interpreter container. Can be a container ID or an object that /// specifies uploaded file IDs to make available to your code, along with an /// optional `memory_limit` setting. @@ -3884,8 +3888,8 @@ pub enum Background { } /// Identifier for service connectors, like those available in ChatGPT. One of -/// `server_url` or `connector_id` must be provided. Learn more about service -/// connectors [here](/docs/guides/tools-remote-mcp#connectors). +/// `server_url`, `connector_id`, or `tunnel_id` must be provided. Learn more +/// about service connectors [here](/docs/guides/tools-remote-mcp#connectors). /// /// Currently supported `connector_id` values are: /// @@ -4563,6 +4567,8 @@ pub struct Input { #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, TS)] #[ts(export_to = "openai/")] pub struct Reasoning { + #[serde(skip_serializing_if = "Option::is_none")] + pub context: Option, #[serde(skip_serializing_if = "Option::is_none")] pub effort: Option, #[serde(skip_serializing_if = "Option::is_none")] @@ -4571,6 +4577,20 @@ pub struct Reasoning { pub summary: Option, } +/// Controls which reasoning items are rendered back to the model on later turns. +/// When returned on a response, this is the effective reasoning context mode +/// used for the response. +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, TS)] +#[serde(rename_all = "snake_case")] +#[ts(export_to = "openai/")] +pub enum Context { + #[serde(rename = "all_turns")] + AllTurns, + Auto, + #[serde(rename = "current_turn")] + CurrentTurn, +} + /// **Deprecated:** use `summary` instead. /// /// A summary of the reasoning performed by the model. This can be @@ -4974,8 +4994,8 @@ pub struct MCPTool { #[serde(skip_serializing_if = "Option::is_none")] pub authorization: Option, /// Identifier for service connectors, like those available in ChatGPT. One of - /// `server_url` or `connector_id` must be provided. Learn more about service - /// connectors [here](/docs/guides/tools-remote-mcp#connectors). + /// `server_url`, `connector_id`, or `tunnel_id` must be provided. Learn more + /// about service connectors [here](/docs/guides/tools-remote-mcp#connectors). /// /// Currently supported `connector_id` values are: /// @@ -5003,10 +5023,14 @@ pub struct MCPTool { pub server_description: Option, /// A label for this MCP server, used to identify it in tool calls. pub server_label: String, - /// The URL for the MCP server. One of `server_url` or `connector_id` must be - /// provided. + /// The URL for the MCP server. One of `server_url`, `connector_id`, or + /// `tunnel_id` must be provided. #[serde(skip_serializing_if = "Option::is_none")] pub server_url: Option, + /// The Secure MCP Tunnel ID to use instead of a direct server URL. One of + /// `server_url`, `connector_id`, or `tunnel_id` must be provided. + #[serde(skip_serializing_if = "Option::is_none")] + pub tunnel_id: Option, } /// A tool that runs Python code to help generate a response to a prompt. @@ -5243,14 +5267,10 @@ pub struct TheResponseObject { #[serde(skip_serializing_if = "Option::is_none")] pub prompt: Option, #[serde(skip_serializing_if = "Option::is_none")] - pub reasoning: Option, - #[serde(skip_serializing_if = "Option::is_none")] pub text: Option, pub tool_choice: TheResponseObjectToolChoiceParam, pub tools: Vec, #[serde(skip_serializing_if = "Option::is_none")] - pub truncation: Option, - #[serde(skip_serializing_if = "Option::is_none")] pub completed_at: Option, #[serde(skip_serializing_if = "Option::is_none")] pub conversation: Option, @@ -5283,11 +5303,15 @@ pub struct TheResponseObject { pub output_text: Option, /// Whether to allow the model to run tool calls in parallel. pub parallel_tool_calls: bool, + #[serde(skip_serializing_if = "Option::is_none")] + pub reasoning: Option, /// The status of the response generation. One of `completed`, `failed`, /// `in_progress`, `cancelled`, `queued`, or `incomplete`. #[serde(skip_serializing_if = "Option::is_none")] pub status: Option, #[serde(skip_serializing_if = "Option::is_none")] + pub truncation: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub usage: Option, } @@ -6515,8 +6539,8 @@ pub struct OutputItemTool { #[serde(skip_serializing_if = "Option::is_none")] pub authorization: Option, /// Identifier for service connectors, like those available in ChatGPT. One of - /// `server_url` or `connector_id` must be provided. Learn more about service - /// connectors [here](/docs/guides/tools-remote-mcp#connectors). + /// `server_url`, `connector_id`, or `tunnel_id` must be provided. Learn more + /// about service connectors [here](/docs/guides/tools-remote-mcp#connectors). /// /// Currently supported `connector_id` values are: /// @@ -6540,10 +6564,14 @@ pub struct OutputItemTool { /// A label for this MCP server, used to identify it in tool calls. #[serde(skip_serializing_if = "Option::is_none")] pub server_label: Option, - /// The URL for the MCP server. One of `server_url` or `connector_id` must be - /// provided. + /// The URL for the MCP server. One of `server_url`, `connector_id`, or + /// `tunnel_id` must be provided. #[serde(skip_serializing_if = "Option::is_none")] pub server_url: Option, + /// The Secure MCP Tunnel ID to use instead of a direct server URL. One of + /// `server_url`, `connector_id`, or `tunnel_id` must be provided. + #[serde(skip_serializing_if = "Option::is_none")] + pub tunnel_id: Option, /// The code interpreter container. Can be a container ID or an object that /// specifies uploaded file IDs to make available to your code, along with an /// optional `memory_limit` setting. diff --git a/crates/lingua/src/providers/openai/params.rs b/crates/lingua/src/providers/openai/params.rs index 2b5ea704..1896f6a3 100644 --- a/crates/lingua/src/providers/openai/params.rs +++ b/crates/lingua/src/providers/openai/params.rs @@ -5,7 +5,9 @@ These structs use `#[serde(flatten)]` to automatically capture unknown fields, eliminating the need for explicit KNOWN_KEYS arrays. */ -use crate::providers::openai::generated::{ChatCompletionRequestMessage, Instructions, Summary}; +use crate::providers::openai::generated::{ + ChatCompletionRequestMessage, Context as ReasoningContext, Instructions, Summary, +}; use crate::serde_json::Value; use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; @@ -221,8 +223,12 @@ pub enum OpenAIReasoningEffort { #[derive(Debug, Clone, Default, Serialize, Deserialize)] pub struct OpenAIReasoning { pub effort: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub summary: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub generate_summary: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub context: Option, } #[cfg(test)] diff --git a/crates/lingua/src/providers/openai/responses_adapter.rs b/crates/lingua/src/providers/openai/responses_adapter.rs index 7792ed8a..56a63e7e 100644 --- a/crates/lingua/src/providers/openai/responses_adapter.rs +++ b/crates/lingua/src/providers/openai/responses_adapter.rs @@ -416,6 +416,11 @@ impl ProviderAdapter for ResponsesAdapter { if let Some(moderation) = typed_params.moderation { extras_map.insert("moderation".into(), moderation); } + if let Some(ref reasoning) = typed_params.reasoning { + if let Ok(reasoning_value) = serde_json::to_value(reasoning) { + extras_map.insert("reasoning".into(), reasoning_value); + } + } if !extras_map.is_empty() { params.extras.insert(ProviderFormat::Responses, extras_map); @@ -2774,4 +2779,61 @@ mod tests { Some("{\"query\":\"studio lights\"}") ); } + + #[test] + fn test_responses_reasoning_context_roundtrips() { + let adapter = ResponsesAdapter; + let payload = json!({ + "model": "gpt-5-nano", + "input": [{"role": "user", "content": "Hello"}], + "reasoning": { + "effort": "high", + "summary": "auto", + "context": "all_turns" + } + }); + + let universal = adapter.request_to_universal(payload).unwrap(); + let reconstructed = adapter.request_from_universal(&universal).unwrap(); + + let reasoning = reconstructed + .get("reasoning") + .expect("reasoning should be present"); + assert_eq!( + reasoning.get("context").and_then(|c| c.as_str()), + Some("all_turns"), + "reasoning.context must roundtrip through universal" + ); + assert_eq!( + reasoning.get("effort").and_then(|e| e.as_str()), + Some("high") + ); + assert_eq!( + reasoning.get("summary").and_then(|s| s.as_str()), + Some("auto") + ); + } + + #[test] + fn test_responses_reasoning_context_absent_does_not_inject() { + let adapter = ResponsesAdapter; + let payload = json!({ + "model": "gpt-5-nano", + "input": [{"role": "user", "content": "Hello"}], + "reasoning": { + "effort": "medium" + } + }); + + let universal = adapter.request_to_universal(payload).unwrap(); + let reconstructed = adapter.request_from_universal(&universal).unwrap(); + + let reasoning = reconstructed + .get("reasoning") + .expect("reasoning should be present"); + assert!( + reasoning.get("context").is_none(), + "reasoning.context should not be injected when absent from input" + ); + } } diff --git a/crates/lingua/src/universal/reasoning.rs b/crates/lingua/src/universal/reasoning.rs index 18c6ba54..5b9be2bf 100644 --- a/crates/lingua/src/universal/reasoning.rs +++ b/crates/lingua/src/universal/reasoning.rs @@ -689,6 +689,7 @@ mod tests { effort: Some(OpenAIReasoningEffortParam::High), summary: Some(OpenAISummary::Detailed), generate_summary: None, + context: None, }; // Test fallback conversion (uses DEFAULT_MAX_TOKENS) diff --git a/provider-type-update-notes.md b/provider-type-update-notes.md new file mode 100644 index 00000000..b5c303e0 --- /dev/null +++ b/provider-type-update-notes.md @@ -0,0 +1,47 @@ +## OpenAI provider type update notes + +### New `reasoning.context` field (needs human clarification) + +The OpenAI Responses API `Reasoning` struct now includes a `context` field +(`Context` enum: `auto`, `current_turn`, `all_turns`). This controls which +reasoning items from previous turns are rendered back to the model. + +**Current status:** + +- The field is captured during deserialization via the hand-written + `OpenAIReasoning` param struct (`params.rs`). +- Same-provider roundtrip (Responses -> universal -> Responses) preserves + `context` through the extras mechanism. +- Cross-provider conversion drops `context` because `ReasoningConfig` has + no universal equivalent. No other provider supports this concept today. + +**Needs human decision:** + +Should `context` be added to `ReasoningConfig` as a universal field (like +`summary`/`SummaryMode`)? If so, cross-provider adapters would need a +policy for providers that don't support it (drop silently, or map to a +provider-specific default). + +### New `tunnel_id` field on MCP tool structs + +A `tunnel_id: Option` field was added to `InputItemTool`, `MCPTool`, +and `OutputItemTool` generated structs. This is a new option for connecting +to MCP servers via a secure tunnel instead of a direct URL. + +No adapter changes required. All hand-written code constructs these structs +via JSON deserialization, and the new field is optional with +`skip_serializing_if`. It serializes and deserializes correctly with no +code changes. + +### Field reordering in `CreateResponseClass` and `TheResponseObject` + +The `reasoning` and `truncation` fields moved positions within +`CreateResponseClass` and `TheResponseObject`. This is cosmetic only; serde +is order-independent. No adapter changes needed. + +### `truncation` deprecated in OpenAPI spec + +The OpenAPI spec marks `truncation` as `deprecated: true` on the +`ResponseProperties` schema. The generated Rust code does not carry a +`#[deprecated]` attribute, so this is a spec-only change with no build +impact. No adapter changes needed. diff --git a/specs/openai/openapi.yml b/specs/openai/openapi.yml index e83ae208..7955810f 100644 --- a/specs/openai/openapi.yml +++ b/specs/openai/openapi.yml @@ -14030,6 +14030,7 @@ paths: "name": "Main Admin Key", "redacted_value": "sk-admin...def", "created_at": 1711471533, + "expires_at": 1714063533, "last_used_at": 1711471534, "owner": { "type": "service_account", @@ -14063,6 +14064,14 @@ paths: name: type: string example: New Admin Key + expires_in_seconds: + type: integer + minimum: 1 + maximum: 31536000 + example: 2592000 + description: >- + The number of seconds until the API key expires. Omit this + field for a key that does not expire. responses: '200': description: The newly created admin API key. @@ -14081,7 +14090,8 @@ paths: -H "Authorization: Bearer $OPENAI_ADMIN_KEY" \ -H "Content-Type: application/json" \ -d '{ - "name": "New Admin Key" + "name": "New Admin Key", + "expires_in_seconds": 2592000 }' node.js: >- import OpenAI from 'openai'; @@ -14157,6 +14167,7 @@ paths: "name": "New Admin Key", "redacted_value": "sk-admin...xyz", "created_at": 1711471533, + "expires_at": 1714063533, "last_used_at": 1711471534, "owner": { "type": "user", @@ -14472,12 +14483,25 @@ paths: in: query description: >- Return only events performed on these targets. For example, a - project ID updated. + project ID updated. For ChatGPT connector role events, use the + workspace connector resource ID shown in `details.id`, such as + `__`. required: false schema: type: array items: type: string + - name: tenant_only + in: query + description: >- + Return only tenant-scoped events associated with this organization. + Required for tenant-scoped events such as `role.bound_to_resource` + and `role.unbound_from_resource`. When `true`, all supplied event + types must be tenant-scoped. + required: false + schema: + type: boolean + default: false - name: limit in: query description: > @@ -21913,6 +21937,133 @@ paths: } } /organization/projects/{project_id}/spend_alerts/{alert_id}: + get: + security: + - AdminApiKeyAuth: [] + summary: Retrieves a project spend alert. + operationId: retrieve-project-spend-alert + tags: + - Spend alerts + parameters: + - name: project_id + in: path + description: The ID of the project. + required: true + schema: + type: string + - name: alert_id + in: path + description: The ID of the spend alert to retrieve. + required: true + schema: + type: string + responses: + '200': + description: Project spend alert retrieved successfully. + content: + application/json: + schema: + $ref: '#/components/schemas/ProjectSpendAlert' + x-oaiMeta: + name: Retrieve project spend alert + group: administration + examples: + request: + curl: > + curl + https://api.openai.com/v1/organization/projects/proj_abc/spend_alerts/alert_abc123 + \ + -H "Authorization: Bearer $OPENAI_ADMIN_KEY" \ + -H "Content-Type: application/json" + node.js: >- + import OpenAI from 'openai'; + + + const client = new OpenAI({ + adminAPIKey: process.env['OPENAI_ADMIN_KEY'], // This is the default and can be omitted + }); + + + const projectSpendAlert = await + client.admin.organization.projects.spendAlerts.retrieve( + 'alert_id', + { project_id: 'project_id' }, + ); + + + console.log(projectSpendAlert.id); + python: >- + import os + + from openai import OpenAI + + + client = OpenAI( + admin_api_key=os.environ.get("OPENAI_ADMIN_KEY"), # This is the default and can be omitted + ) + + project_spend_alert = + client.admin.organization.projects.spend_alerts.retrieve( + alert_id="alert_id", + project_id="project_id", + ) + + print(project_spend_alert.id) + go: "package main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"github.com/openai/openai-go\"\n\t\"github.com/openai/openai-go/option\"\n)\n\nfunc main() {\n\tclient := openai.NewClient(\n\t\toption.WithAdminAPIKey(\"My Admin API Key\"),\n\t)\n\tprojectSpendAlert, err := client.Admin.Organization.Projects.SpendAlerts.Get(\n\t\tcontext.TODO(),\n\t\t\"project_id\",\n\t\t\"alert_id\",\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf(\"%+v\\n\", projectSpendAlert.ID)\n}\n" + java: >- + package com.openai.example; + + + import com.openai.client.OpenAIClient; + + import com.openai.client.okhttp.OpenAIOkHttpClient; + + import + com.openai.models.admin.organization.projects.spendalerts.ProjectSpendAlert; + + import + com.openai.models.admin.organization.projects.spendalerts.SpendAlertRetrieveParams; + + + public final class Main { + private Main() {} + + public static void main(String[] args) { + OpenAIClient client = OpenAIOkHttpClient.fromEnv(); + + SpendAlertRetrieveParams params = SpendAlertRetrieveParams.builder() + .projectId("project_id") + .alertId("alert_id") + .build(); + ProjectSpendAlert projectSpendAlert = client.admin().organization().projects().spendAlerts().retrieve(params); + } + } + ruby: >- + require "openai" + + + openai = OpenAI::Client.new(admin_api_key: "My Admin API Key") + + + project_spend_alert = + openai.admin.organization.projects.spend_alerts.retrieve("alert_id", + project_id: "project_id") + + + puts(project_spend_alert) + response: | + { + "id": "alert_abc123", + "object": "project.spend_alert", + "threshold_amount": 150000, + "currency": "USD", + "interval": "month", + "notification_channel": { + "type": "email", + "recipients": ["finance@example.com"], + "subject_prefix": "OpenAI spend alert" + } + } post: security: - AdminApiKeyAuth: [] @@ -23673,6 +23824,117 @@ paths: } } /organization/spend_alerts/{alert_id}: + get: + security: + - AdminApiKeyAuth: [] + summary: Retrieves an organization spend alert. + operationId: retrieve-organization-spend-alert + tags: + - Spend alerts + parameters: + - name: alert_id + in: path + description: The ID of the spend alert to retrieve. + required: true + schema: + type: string + responses: + '200': + description: Organization spend alert retrieved successfully. + content: + application/json: + schema: + $ref: '#/components/schemas/OrganizationSpendAlert' + x-oaiMeta: + name: Retrieve organization spend alert + group: administration + examples: + request: + curl: > + curl + https://api.openai.com/v1/organization/spend_alerts/alert_abc123 \ + -H "Authorization: Bearer $OPENAI_ADMIN_KEY" \ + -H "Content-Type: application/json" + node.js: >- + import OpenAI from 'openai'; + + + const client = new OpenAI({ + adminAPIKey: process.env['OPENAI_ADMIN_KEY'], // This is the default and can be omitted + }); + + + const organizationSpendAlert = await + client.admin.organization.spendAlerts.retrieve('alert_id'); + + + console.log(organizationSpendAlert.id); + python: >- + import os + + from openai import OpenAI + + + client = OpenAI( + admin_api_key=os.environ.get("OPENAI_ADMIN_KEY"), # This is the default and can be omitted + ) + + organization_spend_alert = + client.admin.organization.spend_alerts.retrieve( + "alert_id", + ) + + print(organization_spend_alert.id) + go: "package main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"github.com/openai/openai-go\"\n\t\"github.com/openai/openai-go/option\"\n)\n\nfunc main() {\n\tclient := openai.NewClient(\n\t\toption.WithAdminAPIKey(\"My Admin API Key\"),\n\t)\n\torganizationSpendAlert, err := client.Admin.Organization.SpendAlerts.Get(context.TODO(), \"alert_id\")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf(\"%+v\\n\", organizationSpendAlert.ID)\n}\n" + java: >- + package com.openai.example; + + + import com.openai.client.OpenAIClient; + + import com.openai.client.okhttp.OpenAIOkHttpClient; + + import + com.openai.models.admin.organization.spendalerts.OrganizationSpendAlert; + + import + com.openai.models.admin.organization.spendalerts.SpendAlertRetrieveParams; + + + public final class Main { + private Main() {} + + public static void main(String[] args) { + OpenAIClient client = OpenAIOkHttpClient.fromEnv(); + + OrganizationSpendAlert organizationSpendAlert = client.admin().organization().spendAlerts().retrieve("alert_id"); + } + } + ruby: >- + require "openai" + + + openai = OpenAI::Client.new(admin_api_key: "My Admin API Key") + + + organization_spend_alert = + openai.admin.organization.spend_alerts.retrieve("alert_id") + + + puts(organization_spend_alert) + response: | + { + "id": "alert_abc123", + "object": "organization.spend_alert", + "threshold_amount": 150000, + "currency": "USD", + "interval": "month", + "notification_channel": { + "type": "email", + "recipients": ["finance@example.com"], + "subject_prefix": "OpenAI spend alert" + } + } post: security: - AdminApiKeyAuth: [] @@ -39864,9 +40126,6 @@ paths: application/json: schema: $ref: '#/components/schemas/TokenCountsBody' - application/x-www-form-urlencoded: - schema: - $ref: '#/components/schemas/TokenCountsBody' responses: '200': description: Success @@ -39973,9 +40232,6 @@ paths: application/json: schema: $ref: '#/components/schemas/CompactResponseMethodPublicBody' - application/x-www-form-urlencoded: - schema: - $ref: '#/components/schemas/CompactResponseMethodPublicBody' responses: '200': description: Success @@ -40457,9 +40713,6 @@ paths: application/json: schema: $ref: '#/components/schemas/SetDefaultSkillVersionBody' - application/x-www-form-urlencoded: - schema: - $ref: '#/components/schemas/SetDefaultSkillVersionBody' responses: '200': description: Success @@ -42201,6 +42454,13 @@ components: format: unixtime example: 1711471533 description: The Unix timestamp (in seconds) of when the API key was created + expires_at: + anyOf: + - type: integer + format: unixtime + example: 1714063533 + description: The Unix timestamp (in seconds) of when the API key expires + - type: 'null' last_used_at: anyOf: - type: integer @@ -42242,6 +42502,7 @@ components: - object - redacted_value - created_at + - expires_at - id - owner x-oaiMeta: @@ -43463,6 +43724,101 @@ components: resource_type: type: string description: The type of resource the role assignment was scoped to. + role.bound_to_resource: + type: object + description: The details for events with this `type`. + properties: + id: + type: string + description: >- + The ID of the resource the role was bound to. ChatGPT workspace + connector resources use `__`. + role_id: + type: string + description: The ID of the role that was bound to the resource. + resource_id: + type: string + description: The ID of the resource the role was bound to. + resource_type: + type: string + description: The type of resource the role was bound to. + permissions: + type: array + items: + type: string + description: The permissions granted to the role for the resource. + workspace_id: + type: string + description: The workspace ID for a ChatGPT workspace connector resource. + connector_id: + type: string + description: The connector ID for a ChatGPT workspace connector resource. + connector_name: + type: string + description: >- + The connector display name for a ChatGPT workspace connector + resource, or the connector ID when the display name could not be + resolved. + enabled: + type: boolean + description: Whether the connector is enabled for the role. + source: + type: string + description: The connector role mutation path that produced the event. + enum: + - role_toggle + - role_connector_update + - role_delete + - workspace_permissions + - connector_publish + role.unbound_from_resource: + type: object + description: The details for events with this `type`. + properties: + id: + type: string + description: >- + The ID of the resource the role was unbound from. ChatGPT + workspace connector resources use + `__`. + role_id: + type: string + description: The ID of the role that was unbound from the resource. + resource_id: + type: string + description: The ID of the resource the role was unbound from. + resource_type: + type: string + description: The type of resource the role was unbound from. + permissions: + type: array + items: + type: string + description: The permissions remaining for the role after the change. + workspace_id: + type: string + description: The workspace ID for a ChatGPT workspace connector resource. + connector_id: + type: string + description: The connector ID for a ChatGPT workspace connector resource. + connector_name: + type: string + description: >- + The connector display name for a ChatGPT workspace connector + resource, or the connector ID when the display name could not be + resolved. + enabled: + type: boolean + description: Whether the connector is enabled for the role. + source: + type: string + description: The connector role mutation path that produced the event. + enum: + - role_toggle + - role_connector_update + - role_delete + - workspace_permissions + - connector_publish service_account.created: type: object description: The details for events with this `type`. @@ -43815,6 +44171,8 @@ components: - role.deleted - role.assignment.created - role.assignment.deleted + - role.bound_to_resource + - role.unbound_from_resource - scim.enabled - scim.disabled - service_account.created @@ -49824,6 +50182,28 @@ components: - $ref: '#/components/schemas/ResponseProperties' - type: object properties: + truncation: + deprecated: true + anyOf: + - type: string + description: > + The truncation strategy to use for the model response. + + - `auto`: If the input to this Response exceeds + the model's context window size, the model will truncate the + response to fit the context window by dropping items from the beginning of the conversation. + - `disabled` (default): If the input size will exceed the + context window + size for a model, the request will fail with a 400 error. + enum: + - auto + - disabled + default: disabled + - type: 'null' + reasoning: + anyOf: + - $ref: '#/components/schemas/Reasoning' + - type: 'null' input: $ref: '#/components/schemas/InputParam' include: @@ -56997,11 +57377,9 @@ components: server_url: type: string format: uri - description: > - The URL for the MCP server. One of `server_url` or `connector_id` - must be - - provided. + description: | + The URL for the MCP server. One of `server_url`, `connector_id`, or + `tunnel_id` must be provided. connector_id: type: string enum: @@ -57017,10 +57395,11 @@ components: Identifier for service connectors, like those available in ChatGPT. One of - `server_url` or `connector_id` must be provided. Learn more about - service + `server_url`, `connector_id`, or `tunnel_id` must be provided. Learn + more - connectors [here](/docs/guides/tools-remote-mcp#connectors). + about service connectors + [here](/docs/guides/tools-remote-mcp#connectors). Currently supported `connector_id` values are: @@ -57041,6 +57420,14 @@ components: - Outlook Email: `connector_outlookemail` - SharePoint: `connector_sharepoint` + tunnel_id: + type: string + pattern: ^tunnel_[a-z0-9]{32}$ + description: > + The Secure MCP Tunnel ID to use instead of a direct server URL. One + of + + `server_url`, `connector_id`, or `tunnel_id` must be provided. authorization: type: string description: > @@ -70804,6 +71191,22 @@ components: - concise - detailed - type: 'null' + context: + anyOf: + - type: string + description: > + Controls which reasoning items are rendered back to the model on + later turns. + + When returned on a response, this is the effective reasoning + context mode + + used for the response. + enum: + - auto + - current_turn + - all_turns + - type: 'null' generate_summary: anyOf: - type: string @@ -70929,6 +71332,23 @@ components: - $ref: '#/components/schemas/ResponseProperties' - type: object properties: + truncation: + anyOf: + - type: string + description: > + The truncation strategy to use for the model response. + + - `auto`: If the input to this Response exceeds + the model's context window size, the model will truncate the + response to fit the context window by dropping items from the beginning of the conversation. + - `disabled` (default): If the input size will exceed the + context window + size for a model, the request will fail with a 400 error. + enum: + - auto + - disabled + default: disabled + - type: 'null' id: type: string description: | @@ -70999,6 +71419,10 @@ components: supported in SDKs. items: $ref: '#/components/schemas/OutputItem' + reasoning: + anyOf: + - $ref: '#/components/schemas/Reasoning' + - type: 'null' instructions: anyOf: - description: > @@ -71117,6 +71541,7 @@ components: reasoning: effort: null summary: null + context: null store: true temperature: 1 text: @@ -73192,10 +73617,6 @@ components: to browse and compare available models. $ref: '#/components/schemas/ModelIdsResponses' - reasoning: - anyOf: - - $ref: '#/components/schemas/Reasoning' - - type: 'null' background: anyOf: - type: boolean @@ -73221,23 +73642,6 @@ components: $ref: '#/components/schemas/ToolChoiceParam' prompt: $ref: '#/components/schemas/Prompt' - truncation: - anyOf: - - type: string - description: > - The truncation strategy to use for the model response. - - - `auto`: If the input to this Response exceeds - the model's context window size, the model will truncate the - response to fit the context window by dropping items from the beginning of the conversation. - - `disabled` (default): If the input size will exceed the - context window - size for a model, the request will fail with a 400 error. - enum: - - auto - - disabled - default: disabled - - type: 'null' ResponseQueuedEvent: type: object title: ResponseQueuedEvent @@ -83382,6 +83786,10 @@ components: Optional reference asset upload or reference object that guides generation. - $ref: '#/components/schemas/ImageRefParam-2' + description: >- + Optional reference asset upload or reference object that guides + generation. Provide exactly one of `image_url` or `file_id` when + using an object. seconds: $ref: '#/components/schemas/VideoSeconds' description: >- @@ -83485,6 +83893,7 @@ components: format: binary description: Reference to the completed video to edit. - $ref: '#/components/schemas/VideoReferenceInputParam' + description: Reference to the completed video to edit. prompt: type: string maxLength: 32000 @@ -83517,6 +83926,7 @@ components: video: oneOf: - $ref: '#/components/schemas/VideoReferenceInputParam' + description: Reference to the completed video to extend. - type: string format: binary description: Reference to the completed video to extend. @@ -83682,6 +84092,7 @@ components: dropping items from the beginning of the conversation. - `disabled` (default): If the input size will exceed the context window size for a model, the request will fail with a 400 error. + deprecated: true instructions: anyOf: - type: string