diff --git a/.github/agents/coordinator.agent.md b/.github/agents/coordinator.agent.md
new file mode 100644
index 000000000..830b131f2
--- /dev/null
+++ b/.github/agents/coordinator.agent.md
@@ -0,0 +1,126 @@
+# Coordinator Agent
+
+## Role
+
+You are the **Coordinator** — the orchestrator of a swarm of specialized sub-agents that
+evaluate and refactor OpenAI TypeSpec specifications for optimal .NET SDK code generation.
+
+## Key Principle: Three-Tier Fix Strategy
+
+All changes follow the escalation path defined in `copilot-instructions.md`:
+
+1. **Tier 1:** Use the exact base TypeSpec from `https://github.com/microsoft/openai-openapi-pr/tree/main/packages/openai-typespec/src` unchanged.
+2. **Tier 2:** Fix issues via client overlays (`specification/client/.client.tsp`)
+ or model overlays (`specification/client/models/.models.tsp`).
+3. **Tier 3:** If overlays cannot fix it, open an upstream issue in https://github.com/microsoft/openai-openapi-pr with full details.
+
+**NEVER modify base spec files.** They are synced from upstream.
+
+## Responsibilities
+
+1. **Receive** a set of TypeSpec (`.tsp`) files or an API area name as input.
+2. **Ensure** the base spec (`base/typespec//`) is an exact copy of the latest
+ upstream from `https://github.com/microsoft/openai-openapi-pr/tree/main/packages/openai-typespec/src//`.
+3. **Dispatch** the Spec Analyzer agent to scan every base spec file and produce a
+ categorized inventory of all union usages.
+4. **Route** each identified union to the appropriate specialist agent based on its category:
+ - **Category 1** (discriminated unions) → Discriminated Union Refactorer
+ - **Category 2** (non-discriminated unions) → Non-Discriminated Union Designer
+ - **Category 3** (shorthand notation unions) → Shorthand Union Handler
+5. **Collect** the proposed changes from each specialist agent.
+6. **Classify each change by tier:**
+ - Can it be done via overlay? → Produce the overlay file changes (Tier 2)
+ - Requires base spec changes? → Produce an upstream issue (Tier 3)
+7. **Validate** that proposed overlay changes are consistent (no conflicting augments).
+8. **Produce** a unified changeset organized by tier.
+
+## Workflow
+
+```
+Input: API area (e.g., "realtime")
+ │
+ ▼
+┌────────────────────────────-─┐
+│ Sync base spec from upstream │ (Tier 1: exact copy)
+└─────────────────────────────-┘
+ │
+ ▼
+┌─────────-────────────┐
+│ Spec Analyzer │ ──▶ Union Inventory (categorized list)
+└──────────-───────────┘
+ │
+ ┌────┼─────────────────────┐
+ ▼ ▼ ▼
+┌────────┐ ┌──────────────┐ ┌───────────────┐
+│ Disc. │ │ Non-Disc. │ │ Shorthand │
+│ Union │ │ Union │ │ Union │
+│ Refact.│ │ Designer │ │ Handler │
+└────────┘ └──────────────┘ └───────────────┘
+ │ │ │
+ └────────────┼────────────────────┘
+ ▼
+┌─────────────────────────────┐
+│ Tier Classification │
+│ ┌────────┐ ┌────────────┐ │
+│ │ Tier 2 │ │ Tier 3 │ │
+│ │Overlays│ │ Upstream │ │
+│ │ │ │ Issues │ │
+│ └────────┘ └────────────┘ │
+└─────────────────────────────┘
+ ▼
+ Unified Changeset
+```
+
+## Dispatching Rules
+
+- All Category 1 unions may be dispatched to the Discriminated Union Refactorer **in parallel**.
+- All Category 2 unions may be dispatched to the Non-Discriminated Union Designer **in parallel**.
+- All Category 3 unions may be dispatched to the Shorthand Union Handler **in parallel**.
+- If two unions touch the same model definition, they must be handled **sequentially** to
+ avoid conflicts. The Coordinator is responsible for detecting these overlaps.
+
+## Conflict Resolution
+
+If a specialist agent proposes a change that conflicts with another:
+1. Prefer the change that yields stronger type safety.
+2. If type safety is equivalent, prefer the simpler change.
+3. If still ambiguous, flag for human review.
+
+## Output Format
+
+The final unified changeset must include:
+
+```
+## Summary
+- Total unions analyzed: N
+- Category 1 (discriminated): N₁
+- Category 2 (non-discriminated): N₂
+- Category 3 (shorthand): N₃
+- Skipped (already correct): N₄
+
+## Tier 2: Overlay Changes
+### Client Overlay: specification/client/.client.tsp
+-
+
+### Model Overlay: specification/client/models/.models.tsp
+-
+
+## Tier 3: Upstream Issues Required
+### Issue 1:
+- Repo: microsoft/openai-openapi-pr
+- File: packages/openai-typespec/src//.tsp
+- Category: 1 | 2 | 3
+- Current: ``
+- Proposed: ``
+- Impact:
+
+## SDK Customization Notes
+-
+```
+
+## References
+
+- Read `.github/copilot-instructions.md` before every run for the latest shared rules.
+- Each specialist agent has its own detailed instructions; do not duplicate their logic.
+- Base spec repo: `microsoft/openai-openapi-pr` (packages/openai-typespec/src/)
+- SDK overlay repo: `christothes/openai-dotnet` (specification/client/)
diff --git a/.github/agents/discriminated-union-refactorer.agent.md b/.github/agents/discriminated-union-refactorer.agent.md
new file mode 100644
index 000000000..b4d43005a
--- /dev/null
+++ b/.github/agents/discriminated-union-refactorer.agent.md
@@ -0,0 +1,175 @@
+# Discriminated Union Refactorer Agent
+
+## Role
+
+You are the **Discriminated Union Refactorer** — responsible for handling TypeSpec unions of
+model types that should be proper `@discriminator`-based model hierarchies so that the C#
+code generator produces strongly-typed inheritance rather than `BinaryData`.
+
+## Critical: Three-Tier Fix Strategy
+
+Category 1 unions almost always require **Tier 3 (upstream issue)** because adding
+`@discriminator` and `extends` relationships requires structural changes to the base spec
+that CANNOT be done via overlays.
+
+**Your primary output for most Category 1 unions is an upstream issue specification,
+not a local file change.**
+
+However, in some cases a **Tier 2 overlay** may partially help:
+- `@@alternateType` can swap a union property to a custom SDK-only discriminated type
+ defined in a model overlay — but this only works if you can define the full hierarchy
+ in the overlay without modifying the base.
+- New SDK-only wrapper models in `specification/client/models/.models.tsp` can
+ approximate the desired hierarchy.
+
+Always prefer Tier 2 if feasible. Only escalate to Tier 3 when overlays truly cannot help.
+
+## Input
+
+A union inventory entry with `"category": 1` from the Spec Analyzer, containing:
+- File path, line number, property name, parent model
+- The raw union expression and its model components
+- The candidate discriminator field and per-component literal values
+
+## Process
+
+For each Category 1 union:
+
+### Step 1: Define or Identify the Base Model
+
+If a suitable base model already exists, use it. Otherwise, create one:
+
+```typespec
+@discriminator("type")
+@doc("Base type for .")
+model {
+ type: string;
+ // Include any properties shared across ALL components
+}
+```
+
+**Naming convention:** The base model name should describe the family (e.g., `RealtimeSession`,
+`RealtimeTool`, `RealtimeToolChoice`).
+
+### Step 2: Convert Components to Derived Models
+
+Each union component becomes a model that extends the base:
+
+```typespec
+model extends {
+ type: "";
+ // Component-specific properties
+}
+```
+
+If the component model already exists, add `extends ` and ensure the `type` property
+has a string-literal type matching its discriminator value.
+
+### Step 3: Replace the Union with the Base Type
+
+Replace the union expression in the property with the base model name:
+
+**Before:**
+```typespec
+session: RealtimeSessionCreateRequestGA | RealtimeTranscriptionSessionCreateRequestGA;
+```
+
+**After:**
+```typespec
+session: RealtimeSession;
+```
+
+### Step 4: Verify Consistency
+
+- Ensure the discriminator field name is consistent across all derived models.
+- Ensure no two derived models share the same discriminator value.
+- Ensure `@discriminator` is on the base model, not on derived models.
+- Ensure derived models do not redefine properties already on the base (unless overriding
+ the `type` literal).
+
+## Problem Areas (from Gist 1 — Realtime API)
+
+These are known union patterns that should be converted:
+
+| Union | Candidate Base | Discriminator | Values |
+|-------|---------------|---------------|--------|
+| `RealtimeSessionCreateRequestGA \| RealtimeTranscriptionSessionCreateRequestGA` | `RealtimeSessionCreateRequest` | `type` | `"realtime"`, `"transcription"` |
+| `(RealtimeFunctionTool \| MCPTool)[]` | `RealtimeTool` | `type` | `"function"`, `"mcp"` |
+| `ToolChoiceOptions \| ToolChoiceFunction \| ToolChoiceMCP` | `RealtimeToolChoice` | `type` | varies |
+| `TranscriptTextUsageTokens \| TranscriptTextUsageDuration` | `TranscriptTextUsage` | `type` | `"tokens"`, `"duration"` |
+| Content part types with `type?: "text" \| "audio"` | `RealtimeContentPart` | `type` | `"text"`, `"audio"` |
+| Message content types with `type?: "input_text" \| "input_audio" \| "input_image"` | `RealtimeMessageContent` | `type` | `"input_text"`, `"input_audio"`, `"input_image"` |
+| Turn detection with `server_vad` / `semantic_vad` subtypes | `RealtimeTurnDetection` | `type` | `"server_vad"`, `"semantic_vad"` |
+
+## Output Format
+
+For each union, produce ONE of the following based on the fix tier:
+
+### Tier 2 Output (Overlay Fix)
+
+```
+###
+- File (base spec):
+- Category: 1
+- Fix Tier: 2
+- Original: ``
+
+#### Client overlay change (specification/client/.client.tsp):
+```typespec
+@@alternateType(., );
+```
+
+#### Model overlay change (specification/client/models/.models.tsp):
+```typespec
+@discriminator("type")
+model { ... }
+model extends { ... }
+model extends { ... }
+```
+```
+
+### Tier 3 Output (Upstream Issue)
+
+```
+###
+- File (base spec):
+- Category: 1
+- Fix Tier: 3
+- Original: ``
+- Why overlay can't fix:
+
+#### Proposed upstream issue:
+**Title:** [TypeSpec] : Convert to @discriminator hierarchy
+**Repo:** microsoft/openai-openapi-pr
+**Body:**
+The union `` in `:` should use a `@discriminator`-based
+model hierarchy. Currently, the C# code generator produces `BinaryData` for this
+property because the union lacks structural discrimination.
+
+**Current TypeSpec:**
+```typespec
+
+```
+
+**Proposed TypeSpec:**
+```typespec
+@discriminator("type")
+model { ... }
+model extends { ... }
+```
+
+**Impact:**
+```
+
+## Rules
+
+1. **NEVER modify base spec files** — they are synced from upstream.
+2. Never remove a model — only add `extends` and restructure (in upstream proposals).
+3. Preserve all existing properties on component models.
+4. The base model should contain only shared properties + the discriminator.
+5. If a component model is used elsewhere as a standalone type, ensure the refactoring
+ doesn't break those references.
+6. Add `@doc` to new base models (in upstream proposals).
+7. When proposing Tier 2 overlays, use existing augment decorator patterns from
+ `specification/client/.client.tsp` as a style guide.
+8. When proposing Tier 3 issues, provide a complete proposed diff for the upstream repo.
diff --git a/.github/agents/non-discriminated-union-designer.agent.md b/.github/agents/non-discriminated-union-designer.agent.md
new file mode 100644
index 000000000..acdaf0a0f
--- /dev/null
+++ b/.github/agents/non-discriminated-union-designer.agent.md
@@ -0,0 +1,216 @@
+# Non-Discriminated Union Designer Agent
+
+## Role
+
+You are the **Non-Discriminated Union Designer** — responsible for designing composition-based
+wrapper types in the .NET SDK for TypeSpec unions that cannot use a `@discriminator` because
+their components are heterogeneous (e.g., a model + an enum).
+
+## Critical: Three-Tier Fix Strategy
+
+Category 2 unions are typically handled at **Tier 2 (overlays)** because the fix lives
+entirely in the SDK layer — the base TypeSpec union is left as-is, and the SDK provides
+a composition wrapper class.
+
+**Your primary output is overlay file changes:**
+- **Model overlay** (`specification/client/models/.models.tsp`): Define new SDK-only
+ types (composition wrapper models, extensible enums).
+- **Client overlay** (`specification/client/.client.tsp`): Use `@@alternateType` to
+ swap the base union property to the new SDK wrapper type. Use `@@dynamicModel` to enable
+ JsonPatch support on new types.
+
+**NEVER modify the base spec files.** The union stays as-is in the base TypeSpec.
+
+## Input
+
+A union inventory entry with `"category": 2` from the Spec Analyzer, containing:
+- File path, line number, property name, parent model
+- The raw union expression and its components (with kinds: model, string-literal, enum, etc.)
+- Whether `null` is a component (→ nullable property)
+- Whether the property is input-only, output-only, or both
+
+## Background: The Composition Pattern
+
+When a union mixes a model type with an enum (or other incompatible types), we cannot use
+`@discriminator` in TypeSpec. Instead, the TypeSpec union is LEFT AS-IS and the SDK layer
+provides a **composition wrapper class**. This design (from the .NET SDK guidelines) ensures
+the property works as both input and output.
+
+### Pattern Structure
+
+Given a union like `ModelType | "value1" | "value2" | null`:
+
+1. **Identify components:**
+ - `ModelType` → an object component (the "custom" variant)
+ - `"value1" | "value2"` → string literals → an enum component (the "global" variant)
+ - `null` → the property is nullable (not a union member)
+
+2. **Design the enum:**
+
+```csharp
+public readonly partial struct : IEquatable<> {
+ public (string value);
+
+ public static Value1 { get; }
+ public static Value2 { get; }
+
+ public readonly bool Equals( other);
+ public static bool operator ==( left, right);
+ public static implicit operator (string value);
+ public static implicit operator ?(string value);
+ public static bool operator !=( left, right);
+ public override readonly string ToString();
+}
+```
+
+3. **Design the wrapper class:**
+
+```csharp
+public class : IJsonModel<>, IPersistableModel<> {
+ // One constructor per component
+ public ( customValue);
+ public ( enumValue);
+
+ // One nullable property per component
+ public CustomValue { get; }
+ public ? EnumValue { get; }
+
+ // Implicit conversions
+ public static implicit operator ( customValue);
+ public static implicit operator ( enumValue);
+}
+```
+
+## Key Design Rules (from Gist 2)
+
+1. **One nullable property per component.** Only the property matching the active variant
+ is non-null. Consumers check for `null` to discover the type.
+
+2. **One constructor per component.** Each constructor takes exactly its component as a
+ parameter and asserts non-null.
+
+3. **No setters on component properties.** An instance cannot be mutated to a different
+ variant after construction.
+
+4. **Implicit conversion operators.** From each component type to the wrapper, enabling:
+ ```csharp
+ McpToolCallApprovalPolicy policy = GlobalMcpToolCallApprovalPolicy.AlwaysRequireApproval;
+ ```
+
+5. **Collections in wrappers are nullable.** Unlike normal SDK convention where collections
+ are never null, collection properties inside a union wrapper MUST be nullable.
+
+6. **Null component = nullable property, not a variant.** If the union includes `null`,
+ the parent property is nullable. Do not create a "null variant".
+
+7. **String-literal groups = extensible enum.** Multiple string literals in a union form a
+ single `readonly partial struct` enum, not individual variants.
+
+## Naming Conventions
+
+| Concept | Pattern | Example |
+|---------|---------|---------|
+| Wrapper class | `` | `McpToolCallApprovalPolicy` |
+| Model component property | `Custom` or descriptive name | `CustomPolicy` |
+| Enum component property | `Global` or descriptive name | `GlobalPolicy` |
+| Enum struct | `` | `GlobalMcpToolCallApprovalPolicy` |
+
+Choose names that clearly communicate when to use each variant.
+
+## Process
+
+For each Category 2 union:
+
+### Step 1: Identify Components
+
+- Separate model types, string-literal enums, and null.
+- Group string literals into a single enum.
+
+### Step 2: Design the Enum (if applicable)
+
+Produce the `readonly partial struct` with appropriate members.
+
+### Step 3: Design the Wrapper Class
+
+Produce the class following the pattern above.
+
+### Step 4: Note the TypeSpec Relationship
+
+The base `.tsp` file is NOT changed for Category 2 unions. Instead, produce overlay changes:
+
+**Client overlay** (`specification/client/.client.tsp`):
+```typespec
+@@alternateType(., );
+@@dynamicModel();
+@@dynamicModel();
+@@dynamicModel();
+```
+
+**Model overlay** (`specification/client/models/.models.tsp`):
+```typespec
+// Define the wrapper and enum types as SDK-only models
+model { ... }
+union { string, ... }
+```
+
+### Step 5: Document Serialization Behavior
+
+Describe how the wrapper serializes/deserializes:
+- On serialization: write the active component's value directly.
+- On deserialization: inspect the JSON token type to determine which component to populate.
+
+## Output Format
+
+```
+###
+- File (base spec):
+- Category: 2
+- Fix Tier: 2
+- Original: ``
+
+#### Client overlay (specification/client/.client.tsp):
+```typespec
+@@alternateType(., );
+@@dynamicModel();
+```
+
+#### Model overlay (specification/client/models/.models.tsp):
+```typespec
+
+```
+
+#### C# design (for SDK implementation reference):
+
+Enum design:
+```csharp
+public readonly partial struct : IEquatable<> { ... }
+```
+
+Wrapper class design:
+```csharp
+public class : IJsonModel<>, IPersistableModel<> { ... }
+```
+
+Usage examples:
+```csharp
+// Setting via enum
+property.ApprovalPolicy = GlobalMcpToolCallApprovalPolicy.AlwaysRequireApproval;
+
+// Setting via model
+property.ApprovalPolicy = new CustomMcpToolCallApprovalPolicy { ... };
+
+// Reading
+if (response.ApprovalPolicy.CustomPolicy is not null) { ... }
+else if (response.ApprovalPolicy.GlobalPolicy.HasValue) { ... }
+```
+```
+
+## Rules
+
+1. **NEVER modify base `.tsp` files** — they are synced from upstream.
+2. All type changes go in overlay files following existing patterns.
+3. Always design for input + output compatibility.
+4. Every constructor must null-check its argument.
+5. The wrapper must implement `IJsonModel` and `IPersistableModel`.
+6. Use `@@alternateType` in the client overlay to swap the base union to the wrapper.
+7. Use `@@dynamicModel` on all new types to enable JsonPatch support.
diff --git a/.github/agents/shorthand-union-handler.agent.md b/.github/agents/shorthand-union-handler.agent.md
new file mode 100644
index 000000000..65071f221
--- /dev/null
+++ b/.github/agents/shorthand-union-handler.agent.md
@@ -0,0 +1,177 @@
+# Shorthand Union Handler Agent
+
+## Role
+
+You are the **Shorthand Union Handler** — responsible for handling TypeSpec unions where one
+component is a convenience shorthand for another (e.g., `string[]` is shorthand for a model's
+`tool_names` property).
+
+## Critical: Three-Tier Fix Strategy
+
+Category 3 unions are handled at **Tier 2 (overlays)** because the fix lives entirely in
+the SDK layer — the base TypeSpec union is left as-is, and the SDK surfaces only the
+longhand type with custom deserialization to tolerate shorthand input.
+
+**Your primary output is overlay file changes:**
+- **Client overlay** (`specification/client/.client.tsp`): Use `@@alternateType` to
+ swap the base union property to the longhand type only.
+- **Model overlay** (`specification/client/models/.models.tsp`): Define any
+ SDK-only types if needed for the longhand representation.
+
+**NEVER modify the base spec files.** The union stays as-is in the base TypeSpec.
+
+## Input
+
+A union inventory entry with `"category": 3` from the Spec Analyzer, containing:
+- File path, line number, property name, parent model
+- The raw union expression
+- Which component is the shorthand and which is the longhand
+- Which property of the longhand model the shorthand maps to
+- Whether the property is input-only, output-only, or both
+
+## Background: The Shorthand Problem (from Gist 3)
+
+Some OpenAI REST API properties accept both a full model and a scalar/array shorthand:
+
+```typespec
+allowed_tools?: string[] | MCPToolFilter | null;
+```
+
+Here, `string[]` is shorthand for `MCPToolFilter.tool_names`. This exists for convenience
+in input, but the server may echo it back in shorthand form.
+
+### Why Not Use the Standard Composition Pattern?
+
+Applying the non-discriminated union composition wrapper here would be counterproductive:
+- It adds complexity to what was designed as a convenience.
+- Two properties (`AllowedToolNames` vs `AllowedTools`) represent the same concept, causing confusion.
+- No functional benefit over just using the longhand type.
+
+### The Solution: Longhand-Only with Tolerant Deserialization
+
+1. **Surface only the longhand type** in the SDK property.
+2. **Customize deserialization** to accept both shorthand and longhand JSON.
+3. When shorthand is received, **normalize to longhand** during deserialization.
+
+## Process
+
+For each Category 3 union:
+
+### Step 1: Confirm Shorthand Relationship
+
+Verify that the shorthand component maps cleanly to a single property of the longhand model:
+
+- `string[]` → `MCPToolFilter.tool_names` ✓
+- `string` → `SomeModel.name` ✓
+- `int[]` → `SomeModel.ids` ✓
+
+If the mapping is ambiguous or involves multiple properties, reclassify as Category 2.
+
+### Step 2: Define the SDK Property
+
+The SDK property uses ONLY the longhand type:
+
+```csharp
+public class McpTool {
+ public McpToolFilter AllowedTools { get; set; }
+}
+```
+
+The `string[] | null` shorthand and null components are handled as:
+- `null` → the property is nullable
+- `string[]` → handled via custom deserialization
+
+### Step 3: Design Custom Deserialization
+
+Produce deserialization logic that handles both forms:
+
+```csharp
+// Pseudocode for deserialization of "allowed_tools"
+if (jsonElement.ValueKind == JsonValueKind.Array
+ && jsonElement.EnumerateArray().All(e => e.ValueKind == JsonValueKind.String))
+{
+ // Shorthand: string[] → normalize to MCPToolFilter
+ var toolNames = jsonElement.EnumerateArray()
+ .Select(e => e.GetString())
+ .ToList();
+ result.AllowedTools = new McpToolFilter { ToolNames = toolNames };
+}
+else if (jsonElement.ValueKind == JsonValueKind.Object)
+{
+ // Longhand: deserialize normally
+ result.AllowedTools = McpToolFilter.DeserializeMcpToolFilter(jsonElement);
+}
+```
+
+### Step 4: Document Known Limitations
+
+For every shorthand union handled, document these known limitations:
+
+1. **Round-trip normalization:** If the server sends shorthand and the client round-trips it,
+ the client will send longhand. The server must accept longhand for this to work.
+2. **Explicit shorthand sending:** If a user needs to send shorthand specifically, they must
+ use `JsonPatch` or raw `BinaryData` — the typed SDK does not expose it.
+
+### Step 5: Produce Overlay Changes
+
+The base `.tsp` file is NOT changed for Category 3 unions. Instead, produce overlay changes:
+
+**Client overlay** (`specification/client/.client.tsp`):
+```typespec
+@@alternateType(., );
+```
+
+This tells the code generator to use only the longhand type for this property.
+Custom deserialization logic is then added in the SDK C# code to handle shorthand JSON.
+
+## Shorthand Detection Heuristics
+
+When the Spec Analyzer flags a potential Category 3, validate using these heuristics:
+
+| Shorthand | Longhand Model | Mapped Property | Confidence |
+|-----------|---------------|-----------------|------------|
+| `string[]` | Model with `string[]` property | High match if only one `string[]` property | High |
+| `string` | Model with `string` property + other props | Check if shorthand is the "primary" field | Medium |
+| `int` / `float` | Model with numeric property | Rare; verify intent | Low |
+
+If confidence is Low, flag for human review rather than auto-handling.
+
+## Output Format
+
+```
+###
+- File (base spec):
+- Category: 3
+- Fix Tier: 2
+- Original: ``
+- Shorthand: `` → maps to `.`
+
+#### Client overlay (specification/client/.client.tsp):
+```typespec
+@@alternateType(., );
+```
+
+#### SDK property design:
+```csharp
+public ? { get; set; }
+```
+
+#### Custom deserialization:
+```csharp
+// Handle shorthand: → normalize to
+
+```
+
+#### Known limitations:
+1. Round-trip: shorthand → longhand normalization
+2. Explicit shorthand requires JsonPatch
+```
+
+## Rules
+
+1. **NEVER modify base `.tsp` files** — they are synced from upstream.
+2. All type swaps go in overlay files using `@@alternateType`.
+3. Always normalize shorthand → longhand; never the reverse.
+4. If the shorthand→longhand mapping is ambiguous, escalate to human review.
+5. Custom deserialization must handle `null` gracefully (nullable property).
+6. Document all limitations explicitly — no silent behavior changes.
diff --git a/.github/agents/spec-analyzer.agent.md b/.github/agents/spec-analyzer.agent.md
new file mode 100644
index 000000000..e30cff581
--- /dev/null
+++ b/.github/agents/spec-analyzer.agent.md
@@ -0,0 +1,146 @@
+# Spec Analyzer Agent
+
+## Role
+
+You are the **Spec Analyzer** — responsible for scanning TypeSpec (`.tsp`) files and producing
+a categorized inventory of every union usage that needs attention.
+
+## Important: Base Spec Only
+
+You analyze ONLY the **base TypeSpec files** from the upstream repo
+(`microsoft/openai-openapi-pr/packages/openai-typespec/src//`), which are synced
+locally to `base/typespec//`. Do NOT analyze overlay files — those are fixes, not
+the source of truth for union discovery.
+
+Also scan existing overlays (`specification/client/.client.tsp` and
+`specification/client/models/.models.tsp`) to note which unions are **already addressed**
+by existing overlays so the specialist agents don't duplicate work.
+
+## Input
+
+A list of `.tsp` file paths or a directory containing `.tsp` files.
+
+## Process
+
+For each `.tsp` file:
+
+1. **Parse** all union expressions. A union is any occurrence of `A | B` in a property type,
+ parameter type, or named `union` declaration.
+
+2. **Classify** each union into one of three categories (see `guidelines.md`):
+
+ - **Category 1: Discriminated Union** — All components are models that share (or should
+ share) a discriminator field.
+ - **Category 2: Non-Discriminated Union** — Heterogeneous components (model + enum, model +
+ scalar) with no feasible discriminator.
+ - **Category 3: Shorthand Notation Union** — One component is a scalar/array shorthand for
+ a property of the other model component.
+ - **Already Correct** — The union already uses `@discriminator` properly, or is a simple
+ string-literal enum that needs no refactoring.
+
+3. **Extract** metadata for each union:
+ - File path and line number (in the base spec)
+ - The property or declaration name
+ - The raw union expression
+ - Each component type and whether it is a model, enum, scalar, or array
+ - Whether the property is input-only, output-only, or both
+ - Whether `null` is a component (→ nullable property, not a union member)
+ - If Category 1: the candidate discriminator field name and its literal values per component
+ - If Category 3: which component is shorthand and which property it maps to
+ - **Whether an existing overlay already addresses this union** (check client/model overlays)
+ - **Fixability assessment**: Can this be fixed via overlay (Tier 2) or does it require
+ an upstream change (Tier 3)?
+
+## Output Format
+
+Produce a JSON inventory:
+
+```json
+{
+ "files_scanned": 12,
+ "unions_found": 23,
+ "inventory": [
+ {
+ "id": "realtime-session-config",
+ "file": "realtime.tsp",
+ "line": 42,
+ "property": "session",
+ "parent_model": "RealtimeSessionCreatedEvent",
+ "raw_union": "RealtimeSessionCreateRequestGA | RealtimeTranscriptionSessionCreateRequestGA",
+ "components": [
+ { "type": "RealtimeSessionCreateRequestGA", "kind": "model" },
+ { "type": "RealtimeTranscriptionSessionCreateRequestGA", "kind": "model" }
+ ],
+ "nullable": false,
+ "input_output": "both",
+ "category": 1,
+ "discriminator_field": "type",
+ "discriminator_values": {
+ "RealtimeSessionCreateRequestGA": "realtime",
+ "RealtimeTranscriptionSessionCreateRequestGA": "transcription"
+ },
+ "existing_overlay": null,
+ "fix_tier": 3,
+ "fix_tier_reason": "Requires @discriminator on base model — cannot be done via overlay"
+ },
+ {
+ "id": "mcp-require-approval",
+ "file": "responses.tsp",
+ "line": 78,
+ "property": "require_approval",
+ "parent_model": "MCPTool",
+ "raw_union": "MCPToolRequireApproval | \"always\" | \"never\" | null",
+ "components": [
+ { "type": "MCPToolRequireApproval", "kind": "model" },
+ { "type": "\"always\"", "kind": "string-literal" },
+ { "type": "\"never\"", "kind": "string-literal" },
+ { "type": "null", "kind": "null" }
+ ],
+ "nullable": true,
+ "input_output": "both",
+ "category": 2,
+ "notes": "String literals form an enum; model + enum = non-discriminated union",
+ "existing_overlay": null,
+ "fix_tier": 2,
+ "fix_tier_reason": "Can define composition wrapper in model overlay + @@alternateType in client overlay"
+ },
+ {
+ "id": "mcp-allowed-tools",
+ "file": "responses.tsp",
+ "line": 85,
+ "property": "allowed_tools",
+ "parent_model": "MCPTool",
+ "raw_union": "string[] | MCPToolFilter | null",
+ "components": [
+ { "type": "string[]", "kind": "array" },
+ { "type": "MCPToolFilter", "kind": "model" },
+ { "type": "null", "kind": "null" }
+ ],
+ "nullable": true,
+ "input_output": "both",
+ "category": 3,
+ "shorthand_component": "string[]",
+ "longhand_component": "MCPToolFilter",
+ "mapped_property": "tool_names",
+ "existing_overlay": null,
+ "fix_tier": 2,
+ "fix_tier_reason": "Can use @@alternateType to longhand type + custom deserialization in SDK"
+ }
+ ]
+}
+```
+
+## Edge Cases
+
+- **Union of a single model + null**: Not a union — just a nullable property. Skip.
+- **Named `union` declarations**: Analyze the same way; note the union name.
+- **Nested unions**: Flatten and classify the outermost union expression.
+- **Unions already decorated with `@discriminator`**: Mark as "Already Correct".
+- **Union of only string literals**: This is an enum, not a union. Mark as "Already Correct".
+
+## Important
+
+- Do NOT propose changes. Your job is analysis only.
+- Be exhaustive — missing a union means it will ship as `BinaryData` in the SDK.
+- Include enough context (parent model, property name, line number) for the specialist agents
+ to make targeted changes without re-scanning.
diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
index 7de6c7ea2..694edc35c 100644
--- a/.github/copilot-instructions.md
+++ b/.github/copilot-instructions.md
@@ -10,5 +10,185 @@ When making changes to TypeSpec files (`.tsp` files), you must regenerate the co
This ensures that any modifications to the TypeSpec definitions are properly reflected in the generated code.
+When making changes to TypeSpec files (`.tsp` files), do not use type unions and instead use discriminators to ensure that we don't use binary data types when the generation occurs.
-When making Changes to TypeSpec files (`.tsp` files), Do not use type unions and instead use discriminators to ensure that we don't use binary data types when the generation occurs.
+# Shared Guidelines for TypeSpec Union Refactoring Agents
+
+## Objective
+
+These guidelines govern all sub-agents that evaluate and refactor OpenAI TypeSpec specifications
+to ensure the generated .NET SDK provides strongly-typed, idiomatic C# models rather than
+loosely-typed `BinaryData` properties.
+
+## Union Classification
+
+Every union encountered in a TypeSpec file MUST be classified into exactly one of three categories:
+
+### Category 1: Discriminated Union (should use `@discriminator`)
+
+A union where all components are **model types** that share (or should share) a common string
+property whose value uniquely identifies the variant.
+
+**Indicators:**
+- All components are `model` types (not scalars, not enums).
+- A `type` (or similar) property exists on each component with distinct literal values.
+- The union represents mutually-exclusive, structurally-distinct alternatives.
+
+**Action:** Convert to a `@discriminator`-based model hierarchy.
+
+### Category 2: Non-Discriminated Union (composition wrapper)
+
+A union where components are **heterogeneous** — typically mixing a model with an enum,
+or mixing structurally-incompatible models where no shared discriminator field exists.
+
+**Indicators:**
+- Components include a mix of model types and string-literal enums.
+- No common discriminator field is feasible.
+- The property is used as both input AND output (echoed back by the server).
+
+**Action:** Create a composition wrapper class with:
+- One nullable property per component.
+- One constructor per component (assert non-null).
+- Implicit conversion operators from each component to the wrapper.
+- Only one property is non-null at a time; consumers check for `null` to discover the active type.
+
+### Category 3: Shorthand Notation Union (normalize to longhand)
+
+A union where one component is a **convenience shorthand** for another
+(e.g., `string[]` is shorthand for a model's `tool_names` property).
+
+**Indicators:**
+- One component is a scalar or scalar-array that maps directly to a single property of
+ the other component.
+- The shorthand exists purely for input convenience.
+- The longhand component is a strict superset of the shorthand.
+
+**Action:**
+- Surface only the longhand type in the SDK.
+- Customize deserialization to accept shorthand and normalize it to longhand.
+- Accept the minor limitations: round-tripping may convert shorthand→longhand, and
+ sending shorthand explicitly requires `JsonPatch`.
+
+## General Rules
+
+1. **Preserve existing discriminators.** If a type already uses `@discriminator`, do not change it.
+2. **Prefer compile-time safety over runtime flexibility.** Strongly-typed hierarchies are always
+ preferable to `BinaryData` or `object`.
+3. **Nullable semantics.** When a union includes `null`, treat it as the *property* being nullable,
+ not as a union component.
+4. **String-literal sets are enums.** A union of string literals (e.g., `"always" | "never"`)
+ should be represented as an extensible enum (`readonly partial struct` in C#).
+5. **Collection properties in union wrappers must be nullable** — unlike normal collection
+ properties which are never null in the library.
+6. **Implicit conversions.** Union wrapper classes MUST have implicit conversion operators to
+ reduce ceremony for callers.
+7. **Immutability of variant.** Once a union wrapper is constructed with a given component,
+ it cannot be mutated to a different component (no setters on component properties).
+8. **Output model compatibility.** All designs must work for properties that are both input
+ and output (echoed back by the server).
+
+## Three-Tier Fix Strategy (CRITICAL)
+
+All agents MUST follow this escalation path when addressing union issues. The base TypeSpec
+spec is treated as an **immutable upstream dependency** — never modify it directly.
+
+### Tier 1: Use the Exact Base TypeSpec (No Changes)
+
+The base TypeSpec lives in the upstream repo (`microsoft/openai-openapi-pr`) under
+`packages/openai-typespec/src//`. This is imported into the SDK repo at
+`base/typespec//main.tsp`.
+
+**Rule:** Always start with an exact, unmodified copy of the latest base TypeSpec.
+Do NOT fork, patch, or hand-edit these files. They are synced from upstream.
+
+### Tier 2: Fix via Client/Model Overlays
+
+If the base spec produces incorrect or suboptimal codegen, fix it using the SDK's overlay
+files. These use TypeSpec augment decorators (`@@`) to reshape the generated output
+without touching the base spec.
+
+**Overlay locations (in the `openai-dotnet` SDK repo):**
+
+| Overlay Type | Path | Purpose |
+|---|---|---|
+| **Client overlay** | `specification/client/.client.tsp` | Operation-level customizations: rename methods (`@@clientName`), move operations (`@@clientLocation`), control access (`@@access`, `@@usage`), suppress convenience methods (`@@convenientAPI`), swap types (`@@alternateType`), enable JsonPatch (`@@dynamicModel`) |
+| **Model overlay** | `specification/client/models/.models.tsp` | Model-level customizations: define new SDK-only types, add collection options, define extensible enums (`union { string, ... }`), create alias types for query parameters |
+
+**What overlays CAN do:**
+- Change generated names, access levels, and visibility
+- Substitute alternate types for properties (`@@alternateType`)
+- Mark models as dynamic for JsonPatch support (`@@dynamicModel`)
+- Add new SDK-only models/enums/aliases that don't exist in the base spec
+- Define collection options and query parameter shapes
+
+**What overlays CANNOT do:**
+- Add `@discriminator` to an existing base model (requires base spec change)
+- Change the structural hierarchy (add `extends` relationships) of base models
+- Remove or rename properties defined in the base spec
+- Change a union to a non-union in the base spec
+
+### Tier 3: Open an Upstream Issue
+
+If the problem **cannot** be fixed through overlays (e.g., a union needs to become a
+`@discriminator` hierarchy, which requires structural changes to the base models), then:
+
+1. **Do NOT modify the base spec locally.**
+2. **Open an issue** on the upstream repo (`microsoft/openai-openapi-pr`) with:
+ - Title: `[TypeSpec] : `
+ - Body containing:
+ - The file path and line number in the base spec
+ - The current union expression
+ - The expected pattern (e.g., `@discriminator` hierarchy)
+ - Which union category (1, 2, or 3) this falls under
+ - The impact on SDK codegen (e.g., "produces `BinaryData` instead of typed model")
+ - A proposed TypeSpec diff showing the desired base spec change
+3. **Document the issue** in the changeset output so it can be tracked.
+
+### Decision Flowchart
+
+```
+Found a problematic union
+ │
+ ▼
+Can it be fixed with @@alternateType,
+@@clientName, new SDK-only models, or
+custom deserialization in overlays?
+ │
+ ┌────┴────┐
+ Yes No
+ │ │
+ ▼ ▼
+ Tier 2: Does it require structural
+ Write changes to base models?
+ overlay (e.g., @discriminator, extends)
+ files │
+ ┌────┴────┐
+ Yes No → re-evaluate
+ │
+ ▼
+ Tier 3:
+ Open upstream
+ issue
+```
+
+## TypeSpec Refactoring Conventions
+
+- Use `@discriminator("type")` (or the appropriate field name) on base models — but only
+ when proposing upstream changes (Tier 3). Never add this to the local base copy.
+- Child models should use `extends` to derive from the base — upstream only.
+- In overlays, use `@@alternateType` to swap a union property to a custom SDK type.
+- Keep union syntax in the base when the union is genuinely non-discriminated and will be
+ handled by a composition wrapper in the SDK (Tier 2 model overlay).
+- Add `@doc` annotations to new base models when proposing upstream changes.
+
+## File Organization
+
+- **Base spec files** (`base/typespec//`): NEVER modify. Synced from upstream.
+- **Client overlays** (`specification/client/.client.tsp`): Operation customizations.
+- **Model overlays** (`specification/client/models/.models.tsp`): Type customizations.
+- Each agent outputs its findings and proposed changes in a structured format.
+- Changes must be minimal and surgical.
+- Every proposed change must reference:
+ - Which category (1, 2, or 3) it falls under
+ - Which tier (1, 2, or 3) the fix uses
+ - If Tier 3: the upstream issue details
diff --git a/api/OpenAI.net10.0.cs b/api/OpenAI.net10.0.cs
index 277be3bf4..363e14ca4 100644
--- a/api/OpenAI.net10.0.cs
+++ b/api/OpenAI.net10.0.cs
@@ -5125,6 +5125,14 @@ public class TurnDetectionOptions : IJsonModel, IPersistab
}
}
namespace OpenAI.Responses {
+ [Experimental("OPENAI001")]
+ public class ApplyPatchTool : ResponseTool, IJsonModel, IPersistableModel {
+ public ApplyPatchTool();
+ protected override ResponseTool JsonModelCreateCore(ref Utf8JsonReader reader, ModelReaderWriterOptions options);
+ protected override void JsonModelWriteCore(Utf8JsonWriter writer, ModelReaderWriterOptions options);
+ protected override ResponseTool PersistableModelCreateCore(BinaryData data, ModelReaderWriterOptions options);
+ protected override BinaryData PersistableModelWriteCore(ModelReaderWriterOptions options);
+ }
[Experimental("OPENAI001")]
public class AutomaticCodeInterpreterToolContainerConfiguration : CodeInterpreterToolContainerConfiguration, IJsonModel, IPersistableModel {
public AutomaticCodeInterpreterToolContainerConfiguration();
@@ -5430,6 +5438,46 @@ public class CustomMcpToolCallApprovalPolicy : IJsonModel, IPersistableModel {
+ public CustomTool(string name);
+ public string Description { get; set; }
+ public CustomToolFormat Format { get; set; }
+ public string Name { get; set; }
+ protected override ResponseTool JsonModelCreateCore(ref Utf8JsonReader reader, ModelReaderWriterOptions options);
+ protected override void JsonModelWriteCore(Utf8JsonWriter writer, ModelReaderWriterOptions options);
+ protected override ResponseTool PersistableModelCreateCore(BinaryData data, ModelReaderWriterOptions options);
+ protected override BinaryData PersistableModelWriteCore(ModelReaderWriterOptions options);
+ }
+ [Experimental("OPENAI001")]
+ public abstract class CustomToolFormat : IJsonModel, IPersistableModel {
+ [Serialization.JsonIgnore]
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ [Experimental("SCME0001")]
+ public ref JsonPatch Patch { get; }
+ protected virtual CustomToolFormat JsonModelCreateCore(ref Utf8JsonReader reader, ModelReaderWriterOptions options);
+ protected virtual void JsonModelWriteCore(Utf8JsonWriter writer, ModelReaderWriterOptions options);
+ protected virtual CustomToolFormat PersistableModelCreateCore(BinaryData data, ModelReaderWriterOptions options);
+ protected virtual BinaryData PersistableModelWriteCore(ModelReaderWriterOptions options);
+ }
+ [Experimental("OPENAI001")]
+ public class CustomToolGrammarFormat : CustomToolFormat, IJsonModel, IPersistableModel {
+ public CustomToolGrammarFormat(GrammarSyntax syntax, string definition);
+ public string Definition { get; set; }
+ public GrammarSyntax Syntax { get; set; }
+ protected override CustomToolFormat JsonModelCreateCore(ref Utf8JsonReader reader, ModelReaderWriterOptions options);
+ protected override void JsonModelWriteCore(Utf8JsonWriter writer, ModelReaderWriterOptions options);
+ protected override CustomToolFormat PersistableModelCreateCore(BinaryData data, ModelReaderWriterOptions options);
+ protected override BinaryData PersistableModelWriteCore(ModelReaderWriterOptions options);
+ }
+ [Experimental("OPENAI001")]
+ public class CustomToolTextFormat : CustomToolFormat, IJsonModel, IPersistableModel {
+ public CustomToolTextFormat();
+ protected override CustomToolFormat JsonModelCreateCore(ref Utf8JsonReader reader, ModelReaderWriterOptions options);
+ protected override void JsonModelWriteCore(Utf8JsonWriter writer, ModelReaderWriterOptions options);
+ protected override CustomToolFormat PersistableModelCreateCore(BinaryData data, ModelReaderWriterOptions options);
+ protected override BinaryData PersistableModelWriteCore(ModelReaderWriterOptions options);
+ }
+ [Experimental("OPENAI001")]
public class FileCitationMessageAnnotation : ResponseMessageAnnotation, IJsonModel, IPersistableModel {
public FileCitationMessageAnnotation(string fileId, int index, string filename);
public string FileId { get; set; }
@@ -5607,6 +5655,22 @@ public class GetResponseOptions : IJsonModel, IPersistableMo
public override readonly string ToString();
}
[Experimental("OPENAI001")]
+ public readonly partial struct GrammarSyntax : IEquatable {
+ public GrammarSyntax(string value);
+ public static GrammarSyntax Lark { get; }
+ public static GrammarSyntax Regex { get; }
+ public readonly bool Equals(GrammarSyntax other);
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public override readonly bool Equals(object obj);
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public override readonly int GetHashCode();
+ public static bool operator ==(GrammarSyntax left, GrammarSyntax right);
+ public static implicit operator GrammarSyntax(string value);
+ public static implicit operator GrammarSyntax?(string value);
+ public static bool operator !=(GrammarSyntax left, GrammarSyntax right);
+ public override readonly string ToString();
+ }
+ [Experimental("OPENAI001")]
public class ImageGenerationCallResponseItem : ResponseItem, IJsonModel, IPersistableModel {
public ImageGenerationCallResponseItem(BinaryData imageResultBytes);
public BinaryData ImageResultBytes { get; set; }
@@ -6494,14 +6558,17 @@ public class ResponseTool : IJsonModel, IPersistableModel vectorStoreIds, int? maxResultCount = null, FileSearchToolRankingOptions rankingOptions = null, BinaryData filters = null);
public static FunctionTool CreateFunctionTool(string functionName, BinaryData functionParameters, bool? strictModeEnabled, string functionDescription = null);
public static ImageGenerationTool CreateImageGenerationTool(string model, ImageGenerationToolQuality? quality = null, ImageGenerationToolSize? size = null, ImageGenerationToolOutputFileFormat? outputFileFormat = null, int? outputCompressionFactor = null, ImageGenerationToolModerationLevel? moderationLevel = null, ImageGenerationToolBackground? background = null, ImageGenerationToolInputFidelity? inputFidelity = null, ImageGenerationToolInputImageMask inputImageMask = null, int? partialImageCount = null);
public static McpTool CreateMcpTool(string serverLabel, McpToolConnectorId connectorId, string authorizationToken = null, string serverDescription = null, IDictionary headers = null, McpToolFilter allowedTools = null, McpToolCallApprovalPolicy toolCallApprovalPolicy = null);
public static McpTool CreateMcpTool(string serverLabel, Uri serverUri, string authorizationToken = null, string serverDescription = null, IDictionary headers = null, McpToolFilter allowedTools = null, McpToolCallApprovalPolicy toolCallApprovalPolicy = null);
+ public static ShellTool CreateShellTool();
public static WebSearchPreviewTool CreateWebSearchPreviewTool(WebSearchToolLocation userLocation = null, WebSearchToolContextSize? searchContextSize = null);
public static WebSearchTool CreateWebSearchTool(WebSearchToolLocation userLocation = null, WebSearchToolContextSize? searchContextSize = null, WebSearchToolFilters filters = null);
protected virtual ResponseTool JsonModelCreateCore(ref Utf8JsonReader reader, ModelReaderWriterOptions options);
@@ -6550,6 +6617,14 @@ public enum ResponseToolChoiceKind {
public override readonly string ToString();
}
[Experimental("OPENAI001")]
+ public class ShellTool : ResponseTool, IJsonModel, IPersistableModel {
+ public ShellTool();
+ protected override ResponseTool JsonModelCreateCore(ref Utf8JsonReader reader, ModelReaderWriterOptions options);
+ protected override void JsonModelWriteCore(Utf8JsonWriter writer, ModelReaderWriterOptions options);
+ protected override ResponseTool PersistableModelCreateCore(BinaryData data, ModelReaderWriterOptions options);
+ protected override BinaryData PersistableModelWriteCore(ModelReaderWriterOptions options);
+ }
+ [Experimental("OPENAI001")]
public class StreamingResponseCodeInterpreterCallCodeDeltaUpdate : StreamingResponseUpdate, IJsonModel, IPersistableModel {
public StreamingResponseCodeInterpreterCallCodeDeltaUpdate();
public string Delta { get; set; }
diff --git a/api/OpenAI.net8.0.cs b/api/OpenAI.net8.0.cs
index 277be3bf4..363e14ca4 100644
--- a/api/OpenAI.net8.0.cs
+++ b/api/OpenAI.net8.0.cs
@@ -5125,6 +5125,14 @@ public class TurnDetectionOptions : IJsonModel, IPersistab
}
}
namespace OpenAI.Responses {
+ [Experimental("OPENAI001")]
+ public class ApplyPatchTool : ResponseTool, IJsonModel, IPersistableModel {
+ public ApplyPatchTool();
+ protected override ResponseTool JsonModelCreateCore(ref Utf8JsonReader reader, ModelReaderWriterOptions options);
+ protected override void JsonModelWriteCore(Utf8JsonWriter writer, ModelReaderWriterOptions options);
+ protected override ResponseTool PersistableModelCreateCore(BinaryData data, ModelReaderWriterOptions options);
+ protected override BinaryData PersistableModelWriteCore(ModelReaderWriterOptions options);
+ }
[Experimental("OPENAI001")]
public class AutomaticCodeInterpreterToolContainerConfiguration : CodeInterpreterToolContainerConfiguration, IJsonModel, IPersistableModel {
public AutomaticCodeInterpreterToolContainerConfiguration();
@@ -5430,6 +5438,46 @@ public class CustomMcpToolCallApprovalPolicy : IJsonModel, IPersistableModel {
+ public CustomTool(string name);
+ public string Description { get; set; }
+ public CustomToolFormat Format { get; set; }
+ public string Name { get; set; }
+ protected override ResponseTool JsonModelCreateCore(ref Utf8JsonReader reader, ModelReaderWriterOptions options);
+ protected override void JsonModelWriteCore(Utf8JsonWriter writer, ModelReaderWriterOptions options);
+ protected override ResponseTool PersistableModelCreateCore(BinaryData data, ModelReaderWriterOptions options);
+ protected override BinaryData PersistableModelWriteCore(ModelReaderWriterOptions options);
+ }
+ [Experimental("OPENAI001")]
+ public abstract class CustomToolFormat : IJsonModel, IPersistableModel {
+ [Serialization.JsonIgnore]
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ [Experimental("SCME0001")]
+ public ref JsonPatch Patch { get; }
+ protected virtual CustomToolFormat JsonModelCreateCore(ref Utf8JsonReader reader, ModelReaderWriterOptions options);
+ protected virtual void JsonModelWriteCore(Utf8JsonWriter writer, ModelReaderWriterOptions options);
+ protected virtual CustomToolFormat PersistableModelCreateCore(BinaryData data, ModelReaderWriterOptions options);
+ protected virtual BinaryData PersistableModelWriteCore(ModelReaderWriterOptions options);
+ }
+ [Experimental("OPENAI001")]
+ public class CustomToolGrammarFormat : CustomToolFormat, IJsonModel, IPersistableModel {
+ public CustomToolGrammarFormat(GrammarSyntax syntax, string definition);
+ public string Definition { get; set; }
+ public GrammarSyntax Syntax { get; set; }
+ protected override CustomToolFormat JsonModelCreateCore(ref Utf8JsonReader reader, ModelReaderWriterOptions options);
+ protected override void JsonModelWriteCore(Utf8JsonWriter writer, ModelReaderWriterOptions options);
+ protected override CustomToolFormat PersistableModelCreateCore(BinaryData data, ModelReaderWriterOptions options);
+ protected override BinaryData PersistableModelWriteCore(ModelReaderWriterOptions options);
+ }
+ [Experimental("OPENAI001")]
+ public class CustomToolTextFormat : CustomToolFormat, IJsonModel, IPersistableModel {
+ public CustomToolTextFormat();
+ protected override CustomToolFormat JsonModelCreateCore(ref Utf8JsonReader reader, ModelReaderWriterOptions options);
+ protected override void JsonModelWriteCore(Utf8JsonWriter writer, ModelReaderWriterOptions options);
+ protected override CustomToolFormat PersistableModelCreateCore(BinaryData data, ModelReaderWriterOptions options);
+ protected override BinaryData PersistableModelWriteCore(ModelReaderWriterOptions options);
+ }
+ [Experimental("OPENAI001")]
public class FileCitationMessageAnnotation : ResponseMessageAnnotation, IJsonModel, IPersistableModel {
public FileCitationMessageAnnotation(string fileId, int index, string filename);
public string FileId { get; set; }
@@ -5607,6 +5655,22 @@ public class GetResponseOptions : IJsonModel, IPersistableMo
public override readonly string ToString();
}
[Experimental("OPENAI001")]
+ public readonly partial struct GrammarSyntax : IEquatable {
+ public GrammarSyntax(string value);
+ public static GrammarSyntax Lark { get; }
+ public static GrammarSyntax Regex { get; }
+ public readonly bool Equals(GrammarSyntax other);
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public override readonly bool Equals(object obj);
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public override readonly int GetHashCode();
+ public static bool operator ==(GrammarSyntax left, GrammarSyntax right);
+ public static implicit operator GrammarSyntax(string value);
+ public static implicit operator GrammarSyntax?(string value);
+ public static bool operator !=(GrammarSyntax left, GrammarSyntax right);
+ public override readonly string ToString();
+ }
+ [Experimental("OPENAI001")]
public class ImageGenerationCallResponseItem : ResponseItem, IJsonModel, IPersistableModel {
public ImageGenerationCallResponseItem(BinaryData imageResultBytes);
public BinaryData ImageResultBytes { get; set; }
@@ -6494,14 +6558,17 @@ public class ResponseTool : IJsonModel, IPersistableModel vectorStoreIds, int? maxResultCount = null, FileSearchToolRankingOptions rankingOptions = null, BinaryData filters = null);
public static FunctionTool CreateFunctionTool(string functionName, BinaryData functionParameters, bool? strictModeEnabled, string functionDescription = null);
public static ImageGenerationTool CreateImageGenerationTool(string model, ImageGenerationToolQuality? quality = null, ImageGenerationToolSize? size = null, ImageGenerationToolOutputFileFormat? outputFileFormat = null, int? outputCompressionFactor = null, ImageGenerationToolModerationLevel? moderationLevel = null, ImageGenerationToolBackground? background = null, ImageGenerationToolInputFidelity? inputFidelity = null, ImageGenerationToolInputImageMask inputImageMask = null, int? partialImageCount = null);
public static McpTool CreateMcpTool(string serverLabel, McpToolConnectorId connectorId, string authorizationToken = null, string serverDescription = null, IDictionary headers = null, McpToolFilter allowedTools = null, McpToolCallApprovalPolicy toolCallApprovalPolicy = null);
public static McpTool CreateMcpTool(string serverLabel, Uri serverUri, string authorizationToken = null, string serverDescription = null, IDictionary headers = null, McpToolFilter allowedTools = null, McpToolCallApprovalPolicy toolCallApprovalPolicy = null);
+ public static ShellTool CreateShellTool();
public static WebSearchPreviewTool CreateWebSearchPreviewTool(WebSearchToolLocation userLocation = null, WebSearchToolContextSize? searchContextSize = null);
public static WebSearchTool CreateWebSearchTool(WebSearchToolLocation userLocation = null, WebSearchToolContextSize? searchContextSize = null, WebSearchToolFilters filters = null);
protected virtual ResponseTool JsonModelCreateCore(ref Utf8JsonReader reader, ModelReaderWriterOptions options);
@@ -6550,6 +6617,14 @@ public enum ResponseToolChoiceKind {
public override readonly string ToString();
}
[Experimental("OPENAI001")]
+ public class ShellTool : ResponseTool, IJsonModel, IPersistableModel {
+ public ShellTool();
+ protected override ResponseTool JsonModelCreateCore(ref Utf8JsonReader reader, ModelReaderWriterOptions options);
+ protected override void JsonModelWriteCore(Utf8JsonWriter writer, ModelReaderWriterOptions options);
+ protected override ResponseTool PersistableModelCreateCore(BinaryData data, ModelReaderWriterOptions options);
+ protected override BinaryData PersistableModelWriteCore(ModelReaderWriterOptions options);
+ }
+ [Experimental("OPENAI001")]
public class StreamingResponseCodeInterpreterCallCodeDeltaUpdate : StreamingResponseUpdate, IJsonModel, IPersistableModel {
public StreamingResponseCodeInterpreterCallCodeDeltaUpdate();
public string Delta { get; set; }
diff --git a/api/OpenAI.netstandard2.0.cs b/api/OpenAI.netstandard2.0.cs
index 8ae6b73a8..eb854eb8a 100644
--- a/api/OpenAI.netstandard2.0.cs
+++ b/api/OpenAI.netstandard2.0.cs
@@ -4477,6 +4477,13 @@ public class TurnDetectionOptions : IJsonModel, IPersistab
}
}
namespace OpenAI.Responses {
+ public class ApplyPatchTool : ResponseTool, IJsonModel, IPersistableModel {
+ public ApplyPatchTool();
+ protected override ResponseTool JsonModelCreateCore(ref Utf8JsonReader reader, ModelReaderWriterOptions options);
+ protected override void JsonModelWriteCore(Utf8JsonWriter writer, ModelReaderWriterOptions options);
+ protected override ResponseTool PersistableModelCreateCore(BinaryData data, ModelReaderWriterOptions options);
+ protected override BinaryData PersistableModelWriteCore(ModelReaderWriterOptions options);
+ }
public class AutomaticCodeInterpreterToolContainerConfiguration : CodeInterpreterToolContainerConfiguration, IJsonModel, IPersistableModel {
public AutomaticCodeInterpreterToolContainerConfiguration();
public IList FileIds { get; }
@@ -4750,6 +4757,41 @@ public class CustomMcpToolCallApprovalPolicy : IJsonModel, IPersistableModel {
+ public CustomTool(string name);
+ public string Description { get; set; }
+ public CustomToolFormat Format { get; set; }
+ public string Name { get; set; }
+ protected override ResponseTool JsonModelCreateCore(ref Utf8JsonReader reader, ModelReaderWriterOptions options);
+ protected override void JsonModelWriteCore(Utf8JsonWriter writer, ModelReaderWriterOptions options);
+ protected override ResponseTool PersistableModelCreateCore(BinaryData data, ModelReaderWriterOptions options);
+ protected override BinaryData PersistableModelWriteCore(ModelReaderWriterOptions options);
+ }
+ public abstract class CustomToolFormat : IJsonModel, IPersistableModel {
+ [Serialization.JsonIgnore]
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public ref JsonPatch Patch { get; }
+ protected virtual CustomToolFormat JsonModelCreateCore(ref Utf8JsonReader reader, ModelReaderWriterOptions options);
+ protected virtual void JsonModelWriteCore(Utf8JsonWriter writer, ModelReaderWriterOptions options);
+ protected virtual CustomToolFormat PersistableModelCreateCore(BinaryData data, ModelReaderWriterOptions options);
+ protected virtual BinaryData PersistableModelWriteCore(ModelReaderWriterOptions options);
+ }
+ public class CustomToolGrammarFormat : CustomToolFormat, IJsonModel, IPersistableModel {
+ public CustomToolGrammarFormat(GrammarSyntax syntax, string definition);
+ public string Definition { get; set; }
+ public GrammarSyntax Syntax { get; set; }
+ protected override CustomToolFormat JsonModelCreateCore(ref Utf8JsonReader reader, ModelReaderWriterOptions options);
+ protected override void JsonModelWriteCore(Utf8JsonWriter writer, ModelReaderWriterOptions options);
+ protected override CustomToolFormat PersistableModelCreateCore(BinaryData data, ModelReaderWriterOptions options);
+ protected override BinaryData PersistableModelWriteCore(ModelReaderWriterOptions options);
+ }
+ public class CustomToolTextFormat : CustomToolFormat, IJsonModel, IPersistableModel {
+ public CustomToolTextFormat();
+ protected override CustomToolFormat JsonModelCreateCore(ref Utf8JsonReader reader, ModelReaderWriterOptions options);
+ protected override void JsonModelWriteCore(Utf8JsonWriter writer, ModelReaderWriterOptions options);
+ protected override CustomToolFormat PersistableModelCreateCore(BinaryData data, ModelReaderWriterOptions options);
+ protected override BinaryData PersistableModelWriteCore(ModelReaderWriterOptions options);
+ }
public class FileCitationMessageAnnotation : ResponseMessageAnnotation, IJsonModel, IPersistableModel {
public FileCitationMessageAnnotation(string fileId, int index, string filename);
public string FileId { get; set; }
@@ -4909,6 +4951,21 @@ public class GetResponseOptions : IJsonModel, IPersistableMo
public static bool operator !=(GlobalMcpToolCallApprovalPolicy left, GlobalMcpToolCallApprovalPolicy right);
public override readonly string ToString();
}
+ public readonly partial struct GrammarSyntax : IEquatable {
+ public GrammarSyntax(string value);
+ public static GrammarSyntax Lark { get; }
+ public static GrammarSyntax Regex { get; }
+ public readonly bool Equals(GrammarSyntax other);
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public override readonly bool Equals(object obj);
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public override readonly int GetHashCode();
+ public static bool operator ==(GrammarSyntax left, GrammarSyntax right);
+ public static implicit operator GrammarSyntax(string value);
+ public static implicit operator GrammarSyntax?(string value);
+ public static bool operator !=(GrammarSyntax left, GrammarSyntax right);
+ public override readonly string ToString();
+ }
public class ImageGenerationCallResponseItem : ResponseItem, IJsonModel, IPersistableModel {
public ImageGenerationCallResponseItem(BinaryData imageResultBytes);
public BinaryData ImageResultBytes { get; set; }
@@ -5715,13 +5772,16 @@ public class ResponseTool : IJsonModel, IPersistableModel vectorStoreIds, int? maxResultCount = null, FileSearchToolRankingOptions rankingOptions = null, BinaryData filters = null);
public static FunctionTool CreateFunctionTool(string functionName, BinaryData functionParameters, bool? strictModeEnabled, string functionDescription = null);
public static ImageGenerationTool CreateImageGenerationTool(string model, ImageGenerationToolQuality? quality = null, ImageGenerationToolSize? size = null, ImageGenerationToolOutputFileFormat? outputFileFormat = null, int? outputCompressionFactor = null, ImageGenerationToolModerationLevel? moderationLevel = null, ImageGenerationToolBackground? background = null, ImageGenerationToolInputFidelity? inputFidelity = null, ImageGenerationToolInputImageMask inputImageMask = null, int? partialImageCount = null);
public static McpTool CreateMcpTool(string serverLabel, McpToolConnectorId connectorId, string authorizationToken = null, string serverDescription = null, IDictionary headers = null, McpToolFilter allowedTools = null, McpToolCallApprovalPolicy toolCallApprovalPolicy = null);
public static McpTool CreateMcpTool(string serverLabel, Uri serverUri, string authorizationToken = null, string serverDescription = null, IDictionary headers = null, McpToolFilter allowedTools = null, McpToolCallApprovalPolicy toolCallApprovalPolicy = null);
+ public static ShellTool CreateShellTool();
public static WebSearchPreviewTool CreateWebSearchPreviewTool(WebSearchToolLocation userLocation = null, WebSearchToolContextSize? searchContextSize = null);
public static WebSearchTool CreateWebSearchTool(WebSearchToolLocation userLocation = null, WebSearchToolContextSize? searchContextSize = null, WebSearchToolFilters filters = null);
protected virtual ResponseTool JsonModelCreateCore(ref Utf8JsonReader reader, ModelReaderWriterOptions options);
@@ -5765,6 +5825,13 @@ public enum ResponseToolChoiceKind {
public static bool operator !=(ResponseTruncationMode left, ResponseTruncationMode right);
public override readonly string ToString();
}
+ public class ShellTool : ResponseTool, IJsonModel, IPersistableModel {
+ public ShellTool();
+ protected override ResponseTool JsonModelCreateCore(ref Utf8JsonReader reader, ModelReaderWriterOptions options);
+ protected override void JsonModelWriteCore(Utf8JsonWriter writer, ModelReaderWriterOptions options);
+ protected override ResponseTool PersistableModelCreateCore(BinaryData data, ModelReaderWriterOptions options);
+ protected override BinaryData PersistableModelWriteCore(ModelReaderWriterOptions options);
+ }
public class StreamingResponseCodeInterpreterCallCodeDeltaUpdate : StreamingResponseUpdate, IJsonModel, IPersistableModel {
public StreamingResponseCodeInterpreterCallCodeDeltaUpdate();
public string Delta { get; set; }
diff --git a/specification/base/typespec/responses/custom/items.tsp b/specification/base/typespec/responses/custom/items.tsp
index ae8862ea0..32b2a10e9 100644
--- a/specification/base/typespec/responses/custom/items.tsp
+++ b/specification/base/typespec/responses/custom/items.tsp
@@ -25,6 +25,12 @@ union ItemType {
mcp_approval_request: "mcp_approval_request",
mcp_approval_response: "mcp_approval_response",
mcp_call: "mcp_call",
+ shell_call: "shell_call",
+ shell_call_output: "shell_call_output",
+ apply_patch_call: "apply_patch_call",
+ apply_patch_call_output: "apply_patch_call_output",
+ custom_tool_call: "custom_tool_call",
+ custom_tool_call_output: "custom_tool_call_output",
}
model FileSearchToolCallItemParam extends ItemParam {
@@ -237,3 +243,69 @@ model MCPCallItemResource extends ItemResource {
type: ItemType.mcp_call;
...MCPCallItemBase;
}
+
+model FunctionShellCallItemParam extends ItemParam {
+ type: ItemType.shell_call;
+ ...FunctionShellCallItemBase;
+}
+
+model FunctionShellCallItemResource extends ItemResource {
+ type: ItemType.shell_call;
+ status: FunctionShellCallItemStatus;
+ ...FunctionShellCallItemBase;
+}
+
+model FunctionShellCallOutputItemParam extends ItemParam {
+ type: ItemType.shell_call_output;
+ ...FunctionShellCallOutputItemBase;
+}
+
+model FunctionShellCallOutputItemResource extends ItemResource {
+ type: ItemType.shell_call_output;
+ status: "in_progress" | "completed" | "incomplete";
+ ...FunctionShellCallOutputItemBase;
+}
+
+model ApplyPatchToolCallItemParam extends ItemParam {
+ type: ItemType.apply_patch_call;
+ ...ApplyPatchToolCallItemBase;
+}
+
+model ApplyPatchToolCallItemResource extends ItemResource {
+ type: ItemType.apply_patch_call;
+ status: ApplyPatchCallStatusParam;
+ ...ApplyPatchToolCallItemBase;
+}
+
+model ApplyPatchToolCallOutputItemParam extends ItemParam {
+ type: ItemType.apply_patch_call_output;
+ ...ApplyPatchToolCallOutputItemBase;
+}
+
+model ApplyPatchToolCallOutputItemResource extends ItemResource {
+ type: ItemType.apply_patch_call_output;
+ status: ApplyPatchCallOutputStatusParam;
+ ...ApplyPatchToolCallOutputItemBase;
+}
+
+model CustomToolCallItemParam extends ItemParam {
+ type: ItemType.custom_tool_call;
+ ...CustomToolCallItemBase;
+}
+
+model CustomToolCallItemResource extends ItemResource {
+ type: ItemType.custom_tool_call;
+ status: "in_progress" | "completed" | "incomplete";
+ ...CustomToolCallItemBase;
+}
+
+model CustomToolCallOutputItemParam extends ItemParam {
+ type: ItemType.custom_tool_call_output;
+ ...CustomToolCallOutputItemBase;
+}
+
+model CustomToolCallOutputItemResource extends ItemResource {
+ type: ItemType.custom_tool_call_output;
+ status: "in_progress" | "completed" | "incomplete";
+ ...CustomToolCallOutputItemBase;
+}
diff --git a/specification/base/typespec/responses/models.tsp b/specification/base/typespec/responses/models.tsp
index 85a165c59..2cb268b6d 100644
--- a/specification/base/typespec/responses/models.tsp
+++ b/specification/base/typespec/responses/models.tsp
@@ -247,6 +247,12 @@ model ResponseProperties {
""")
tool_choice?: ToolChoiceOptions | ToolChoiceObject;
+ /**
+ * Reference to a prompt template and its variables.
+ * [Learn more](https://platform.openai.com/docs/guides/text?api-mode=responses#reusable-prompts).
+ */
+ prompt?: Prompt;
+
@doc("""
The truncation strategy to use for the model response.
- `auto`: If the context of this response and previous ones exceeds
@@ -498,6 +504,9 @@ union ToolType {
code_interpreter: "code_interpreter",
image_generation: "image_generation",
local_shell: "local_shell",
+ shell: "shell",
+ apply_patch: "apply_patch",
+ custom: "custom",
}
@discriminator("type")
model Tool {
@@ -534,6 +543,10 @@ union ToolChoiceObjectType {
image_generation: "image_generation",
code_interpreter: "code_interpreter",
mcp: "mcp",
+ shell: "shell",
+ apply_patch: "apply_patch",
+ custom: "custom",
+ allowed_tools: "allowed_tools",
}
@discriminator("type")
model ToolChoiceObject {
@@ -556,6 +569,58 @@ model ToolChoiceObjectCodeInterpreter extends ToolChoiceObject {
}
model ToolChoiceObjectMCP extends ToolChoiceObject {
type: ToolChoiceObjectType.mcp;
+
+ /** The label of the MCP server to use. */
+ server_label: string;
+
+ /** Optional name of a specific MCP tool to use. */
+ name?: string | null;
+}
+
+/** Use this option to force the model to call the shell tool. */
+model ToolChoiceObjectShell extends ToolChoiceObject {
+ @doc("""
+ For shell tool calling, the type is always `shell`.
+ """)
+ type: ToolChoiceObjectType.shell;
+}
+
+/** Use this option to force the model to call the apply_patch tool. */
+model ToolChoiceObjectApplyPatch extends ToolChoiceObject {
+ @doc("""
+ For apply_patch tool calling, the type is always `apply_patch`.
+ """)
+ type: ToolChoiceObjectType.apply_patch;
+}
+
+/** Use this option to force the model to call a specific custom tool. */
+@summary("Custom tool")
+model ToolChoiceObjectCustom extends ToolChoiceObject {
+ @doc("""
+ For custom tool calling, the type is always `custom`.
+ """)
+ type: ToolChoiceObjectType.custom;
+
+ /** The name of the custom tool to call. */
+ name: string;
+}
+
+/** Constrains the tools available to the model to a pre-defined set. */
+@summary("Allowed tools")
+model ToolChoiceObjectAllowed extends ToolChoiceObject {
+ @doc("""
+ Allowed tool configuration type. Always `allowed_tools`.
+ """)
+ type: ToolChoiceObjectType.allowed_tools;
+
+ /**Constrains the tools available to the model to a pre-defined set.
+ `auto` allows the model to pick from among the allowed tools and generate a
+ message.
+ `required` requires the model to call one or more of the allowed tools.*/
+ mode: "auto" | "required";
+
+ /** A list of tool definitions that the model should be allowed to call. */
+ tools: Record[];
}
// Tool customization (apply_discriminator): Apply discriminated type base
@@ -956,6 +1021,8 @@ union ResponseTextFormatConfigurationType {
text: "text",
json_schema: "json_schema",
json_object: "json_object",
+ grammar: "grammar",
+ python: "python",
}
@discriminator("type")
model ResponseTextFormatConfiguration {
@@ -970,6 +1037,27 @@ model ResponseTextFormatConfigurationJsonObject
type: ResponseTextFormatConfigurationType.json_object;
}
+/** Grammar response format. Uses a grammar definition to constrain the model output. */
+model ResponseTextFormatConfigurationGrammar
+ extends ResponseTextFormatConfiguration {
+ @doc("""
+ The type of response format being defined. Always `grammar`.
+ """)
+ type: ResponseTextFormatConfigurationType.grammar;
+
+ /** The grammar definition string. */
+ grammar: string;
+}
+
+/** Python response format. Constrains the model output to valid Python code. */
+model ResponseTextFormatConfigurationPython
+ extends ResponseTextFormatConfiguration {
+ @doc("""
+ The type of response format being defined. Always `python`.
+ """)
+ type: ResponseTextFormatConfigurationType.python;
+}
+
// Tool customization (apply_discriminator): Apply base type
/**
* JSON Schema response format. Used to generate structured JSON responses.
@@ -1406,6 +1494,8 @@ union ResponseStreamEventType {
response_reasoning_summary_done: "response.reasoning_summary.done",
response_reasoning_text_delta: "response.reasoning_text.delta",
response_reasoning_text_done: "response.reasoning_text.done",
+ response_custom_tool_call_input_delta: "response.custom_tool_call_input.delta",
+ response_custom_tool_call_input_done: "response.custom_tool_call_input.done",
}
@discriminator("type")
model ResponseStreamEvent {
@@ -2096,6 +2186,89 @@ model LocalShellTool extends Tool {
type: ToolType.local_shell;
}
+// Tool customization (apply_discriminator): Apply discriminated type base for tools
+/** A tool that allows the model to execute shell commands in a sandboxed environment. */
+@summary("Shell tool")
+model FunctionShellToolParam extends Tool {
+ @doc("""
+ The type of the shell tool. Always `shell`.
+ """)
+ type: ToolType.shell;
+}
+
+// Tool customization (apply_discriminator): Apply discriminated type base for tools
+/** A tool that allows the model to apply patches to files. */
+@summary("Apply patch tool")
+model ApplyPatchToolParam extends Tool {
+ @doc("""
+ The type of the apply patch tool. Always `apply_patch`.
+ """)
+ type: ToolType.apply_patch;
+}
+
+// Tool customization (apply_discriminator): Apply discriminated type base for tools
+/** A custom tool that the model can call. */
+@summary("Custom tool")
+model CustomToolParam extends Tool {
+ @doc("""
+ The type of the custom tool. Always `custom`.
+ """)
+ type: ToolType.custom;
+
+ /** The name of the custom tool. */
+ name: string;
+
+ /** A description of the custom tool. */
+ description?: string | null;
+
+ /** The format of the custom tool's input schema. */
+ format?: CustomToolParamFormat;
+}
+
+/** The type of the custom tool parameter format. */
+union CustomToolParamFormatType {
+ string,
+ text: "text",
+ grammar: "grammar",
+}
+
+/** The format of a custom tool parameter. */
+@discriminator("type")
+model CustomToolParamFormat {
+ type: CustomToolParamFormatType;
+}
+
+/** A text format for a custom tool parameter. */
+model CustomTextFormatParam extends CustomToolParamFormat {
+ @doc("""
+ The type of the format. Always `text`.
+ """)
+ type: CustomToolParamFormatType.text;
+}
+
+/** A grammar format for a custom tool parameter. */
+model CustomGrammarFormatParam extends CustomToolParamFormat {
+ @doc("""
+ The type of the format. Always `grammar`.
+ """)
+ type: CustomToolParamFormatType.grammar;
+
+ /** The syntax of the grammar. */
+ syntax: GrammarSyntax;
+
+ /** The grammar definition string. */
+ definition: string;
+}
+
+/** The syntax type used by a grammar definition. */
+#suppress "@azure-tools/typespec-azure-core/no-enum" "Auto-suppressed warnings non-applicable rules during import."
+enum GrammarSyntax {
+ /** Lark grammar syntax. */
+ lark,
+ /** Regex grammar syntax. */
+ regex,
+}
+
// Tool customization: Rename to supply base for split input/output models
/** A tool call to run a command on the local shell. */
alias LocalShellToolCallItemBase = {
@@ -2342,6 +2515,273 @@ alias MCPCallItemBase = {
"""
);
+
+// Tool customization: Rename to supply base for split input/output models
+/** A shell tool call initiated by the model. */
+alias FunctionShellCallItemBase = {
+ /** The unique ID of the shell tool call. */
+ call_id: string;
+
+ /** The action performed by the shell tool. */
+ action: FunctionShellActionParam;
+};
+
+@@doc(FunctionShellCallItemResource,
+ """
+ A shell tool call initiated by the model.
+
+ """
+);
+@@doc(FunctionShellCallItemParam,
+ """
+ A shell tool call initiated by the model.
+
+ """
+);
+
+/** The action to perform with the shell tool. */
+model FunctionShellActionParam {
+ /** The shell commands to execute. */
+ commands: string[];
+
+ /** Optional timeout in milliseconds for the command. */
+ timeout_ms?: int32 | null;
+
+ /** Optional working directory to run the command in. */
+ working_directory?: string | null;
+}
+
+/** The status of a shell tool call item. */
+#suppress "@azure-tools/typespec-azure-core/no-enum" "Auto-suppressed warnings non-applicable rules during import."
+enum FunctionShellCallItemStatus {
+ #suppress "@azure-tools/typespec-azure-core/documentation-required" "Auto-suppressed warnings non-applicable rules during import."
+ in_progress,
+ #suppress "@azure-tools/typespec-azure-core/documentation-required" "Auto-suppressed warnings non-applicable rules during import."
+ completed,
+ #suppress "@azure-tools/typespec-azure-core/documentation-required" "Auto-suppressed warnings non-applicable rules during import."
+ incomplete,
+}
+
+// Tool customization: Rename to supply base for split input/output models
+/** The output of a shell tool call. */
+alias FunctionShellCallOutputItemBase = {
+ /** The unique ID of the shell tool call this output is for. */
+ call_id: string;
+
+ /** The output content from the shell command. */
+ output: FunctionShellCallOutputContentParam;
+
+ /** Maximum output length requested. */
+ max_output_length?: int32 | null;
+};
+
+@@doc(FunctionShellCallOutputItemResource,
+ """
+ The output of a shell tool call.
+
+ """
+);
+@@doc(FunctionShellCallOutputItemParam,
+ """
+ The output of a shell tool call.
+
+ """
+);
+
+/** The content from a shell tool call output. */
+model FunctionShellCallOutputContentParam {
+ /** Standard output from the shell command. */
+ stdout?: string | null;
+
+ /** Standard error from the shell command. */
+ stderr?: string | null;
+
+ /** The outcome of the shell command execution. */
+ outcome?: FunctionShellCallOutputOutcomeParam;
+}
+
+/** The outcome of a shell tool call. */
+@discriminator("type")
+model FunctionShellCallOutputOutcomeParam {
+ type: string;
+}
+
+/** A timeout outcome for a shell tool call. */
+model FunctionShellCallOutputOutcomeTimeout extends FunctionShellCallOutputOutcomeParam {
+ /** The type of the outcome. Always `timeout`. */
+ type: "timeout";
+}
+
+/** An exit outcome for a shell tool call. */
+model FunctionShellCallOutputOutcomeExit extends FunctionShellCallOutputOutcomeParam {
+ /** The type of the outcome. Always `exit`. */
+ type: "exit";
+
+ /** The exit code of the shell command. */
+ exit_code: int32;
+}
+
+// Tool customization: Rename to supply base for split input/output models
+/** An apply_patch tool call initiated by the model. */
+alias ApplyPatchToolCallItemBase = {
+ /** The unique ID of the apply_patch tool call. */
+ call_id: string;
+
+ /** The patch operation to apply. */
+ operation: ApplyPatchOperationParam;
+};
+
+@@doc(ApplyPatchToolCallItemResource,
+ """
+ An apply_patch tool call initiated by the model.
+
+ """
+);
+@@doc(ApplyPatchToolCallItemParam,
+ """
+ An apply_patch tool call initiated by the model.
+
+ """
+);
+
+/** The status of an apply_patch tool call. */
+#suppress "@azure-tools/typespec-azure-core/no-enum" "Auto-suppressed warnings non-applicable rules during import."
+enum ApplyPatchCallStatusParam {
+ #suppress "@azure-tools/typespec-azure-core/documentation-required" "Auto-suppressed warnings non-applicable rules during import."
+ in_progress,
+ #suppress "@azure-tools/typespec-azure-core/documentation-required" "Auto-suppressed warnings non-applicable rules during import."
+ completed,
+ #suppress "@azure-tools/typespec-azure-core/documentation-required" "Auto-suppressed warnings non-applicable rules during import."
+ incomplete,
+}
+
+/** The type of an apply_patch file operation. */
+union ApplyPatchOperationType {
+ string,
+ create_file: "create_file",
+ delete_file: "delete_file",
+ update_file: "update_file",
+}
+
+/** A file operation for the apply_patch tool. */
+@discriminator("type")
+model ApplyPatchOperationParam {
+ type: ApplyPatchOperationType;
+}
+
+/** Create a new file with the apply_patch tool. */
+model ApplyPatchCreateFileOperation extends ApplyPatchOperationParam {
+ /** The type. Always `create_file`. */
+ type: ApplyPatchOperationType.create_file;
+
+ /** The path of the file to create. */
+ path: string;
+}
+
+/** Delete a file with the apply_patch tool. */
+model ApplyPatchDeleteFileOperation extends ApplyPatchOperationParam {
+ /** The type. Always `delete_file`. */
+ type: ApplyPatchOperationType.delete_file;
+
+ /** The path of the file to delete. */
+ path: string;
+}
+
+/** Update an existing file with the apply_patch tool. */
+model ApplyPatchUpdateFileOperation extends ApplyPatchOperationParam {
+ /** The type. Always `update_file`. */
+ type: ApplyPatchOperationType.update_file;
+
+ /** The path of the file to update. */
+ path: string;
+
+ /** The unified diff to apply to the file. */
+ diff: string;
+}
+
+// Tool customization: Rename to supply base for split input/output models
+/** The output of an apply_patch tool call. */
+alias ApplyPatchToolCallOutputItemBase = {
+ /** The unique ID of the apply_patch tool call this output is for. */
+ call_id: string;
+
+ /** A JSON string of the output of the apply_patch tool call. */
+ output?: string | null;
+};
+
+@@doc(ApplyPatchToolCallOutputItemResource,
+ """
+ The output of an apply_patch tool call.
+
+ """
+);
+@@doc(ApplyPatchToolCallOutputItemParam,
+ """
+ The output of an apply_patch tool call.
+
+ """
+);
+
+/** The status of an apply_patch tool call output. */
+#suppress "@azure-tools/typespec-azure-core/no-enum" "Auto-suppressed warnings non-applicable rules during import."
+enum ApplyPatchCallOutputStatusParam {
+ #suppress "@azure-tools/typespec-azure-core/documentation-required" "Auto-suppressed warnings non-applicable rules during import."
+ in_progress,
+ #suppress "@azure-tools/typespec-azure-core/documentation-required" "Auto-suppressed warnings non-applicable rules during import."
+ completed,
+ #suppress "@azure-tools/typespec-azure-core/documentation-required" "Auto-suppressed warnings non-applicable rules during import."
+ incomplete,
+}
+
+// Tool customization: Rename to supply base for split input/output models
+/** A custom tool call initiated by the model. */
+alias CustomToolCallItemBase = {
+ /** The unique ID of the custom tool call. */
+ call_id: string;
+
+ /** The name of the custom tool that was called. */
+ name: string;
+
+ /** The input provided by the model for the custom tool call. */
+ input: string;
+};
+
+@@doc(CustomToolCallItemResource,
+ """
+ A custom tool call initiated by the model.
+
+ """
+);
+@@doc(CustomToolCallItemParam,
+ """
+ A custom tool call initiated by the model.
+
+ """
+);
+
+// Tool customization: Rename to supply base for split input/output models
+/** The output of a custom tool call. */
+alias CustomToolCallOutputItemBase = {
+ /** The unique ID of the custom tool call this output is for. */
+ call_id: string;
+
+ /** The output from the custom tool call. */
+ output?: string | null;
+};
+
+@@doc(CustomToolCallOutputItemResource,
+ """
+ The output of a custom tool call.
+
+ """
+);
+@@doc(CustomToolCallOutputItemParam,
+ """
+ The output of a custom tool call.
+
+ """
+);
+
// Tool customization: Remove shared sequence_number property that was moved to the common parent
/** Emitted when an image generation tool call has completed and the final image is available. */
model ResponseImageGenCallCompletedEvent extends ResponseStreamEvent {
@@ -2511,6 +2951,38 @@ model ResponseMCPListToolsInProgressEvent extends ResponseStreamEvent {
output_index: int32;
}
+// Tool customization: Remove shared sequence_number property that was moved to the common parent
+/** Emitted when there is a delta (partial update) to the input of a custom tool call. */
+model ResponseCustomToolCallInputDeltaEvent extends ResponseStreamEvent {
+ /** The type of the event. Always 'response.custom_tool_call_input.delta'. */
+ type: ResponseStreamEventType.response_custom_tool_call_input_delta;
+
+ /** The index of the output item in the response's output array. */
+ output_index: int32;
+
+ /** The unique identifier of the custom tool call item being processed. */
+ item_id: string;
+
+ /** The partial update to the input for the custom tool call. */
+ delta: string;
+}
+
+// Tool customization: Remove shared sequence_number property that was moved to the common parent
+/** Emitted when the input for a custom tool call is finalized. */
+model ResponseCustomToolCallInputDoneEvent extends ResponseStreamEvent {
+ /** The type of the event. Always 'response.custom_tool_call_input.done'. */
+ type: ResponseStreamEventType.response_custom_tool_call_input_done;
+
+ /** The index of the output item in the response's output array. */
+ output_index: int32;
+
+ /** The unique identifier of the custom tool call item being processed. */
+ item_id: string;
+
+ /** The finalized input for the custom tool call. */
+ input: string;
+}
+
// Tool customization: Remove shared sequence_number property that was moved to the common parent
/** Emitted when an annotation is added to output text content. */
model ResponseOutputTextAnnotationAddedEvent extends ResponseStreamEvent {
@@ -2879,6 +3351,30 @@ enum TruncationEnum {
disabled,
}
+/**
+ * Reference to a prompt template and its variables.
+ * [Learn more](https://platform.openai.com/docs/guides/text?api-mode=responses#reusable-prompts).
+ */
+model Prompt {
+ /** The unique identifier of the prompt template to use. */
+ id: string;
+
+ /** The version of the prompt template to use. */
+ version?: string | null;
+
+ /** The variables to substitute into the prompt template. */
+ variables?: ResponsePromptVariables;
+}
+
+/** Variables to substitute into a prompt template. */
+#suppress "@azure-tools/typespec-azure-core/no-openapi" "Auto-suppressed warnings non-applicable rules during import."
+@extension("x-oaiExpandable", true)
+model ResponsePromptVariables {
+ #suppress "@azure-tools/typespec-azure-core/no-unnamed-union" "Auto-suppressed warnings non-applicable rules during import."
+ #suppress "@azure-tools/typespec-autorest/union-unsupported" "Auto-suppressed warnings non-applicable rules during import."
+ ...Record;
+}
+
#suppress "@azure-tools/typespec-azure-core/documentation-required" "Auto-suppressed warnings non-applicable rules during import."
@summary("Token counts")
model TokenCountsResource {
diff --git a/specification/client/responses.client.tsp b/specification/client/responses.client.tsp
index dabc4e4e5..e60088870 100644
--- a/specification/client/responses.client.tsp
+++ b/specification/client/responses.client.tsp
@@ -65,6 +65,18 @@ using TypeSpec.HttpClient.CSharp;
@@visibility(ImageGenToolCallItemResource.status, Lifecycle.Read);
@@clientName(ImageGenToolCallItemResource.result, "ImageResultBytes");
+@@visibility(FunctionShellCallItemResource.status, Lifecycle.Read);
+
+@@visibility(FunctionShellCallOutputItemResource.status, Lifecycle.Read);
+
+@@visibility(ApplyPatchToolCallItemResource.status, Lifecycle.Read);
+
+@@visibility(ApplyPatchToolCallOutputItemResource.status, Lifecycle.Read);
+
+@@visibility(CustomToolCallItemResource.status, Lifecycle.Read);
+
+@@visibility(CustomToolCallOutputItemResource.status, Lifecycle.Read);
+
// ------------ Tools ------------
@@clientName(FileSearchTool.max_num_results, "MaxResultCount");
@@ -114,6 +126,10 @@ using TypeSpec.HttpClient.CSharp;
@@dynamicModel(ToolChoiceObjectImageGen);
@@dynamicModel(ToolChoiceObjectCodeInterpreter);
@@dynamicModel(ToolChoiceObjectMCP);
+@@dynamicModel(ToolChoiceObjectShell);
+@@dynamicModel(ToolChoiceObjectApplyPatch);
+@@dynamicModel(ToolChoiceObjectCustom);
+@@dynamicModel(ToolChoiceObjectAllowed);
@@dynamicModel(ToolChoiceObjectFunction);
@@dynamicModel(FunctionTool);
@@dynamicModel(FileSearchTool);
@@ -141,6 +157,8 @@ using TypeSpec.HttpClient.CSharp;
@@dynamicModel(ResponseTextFormatConfigurationText);
@@dynamicModel(ResponseTextFormatConfigurationJsonObject);
@@dynamicModel(ResponseTextFormatConfigurationJsonSchema);
+@@dynamicModel(ResponseTextFormatConfigurationGrammar);
+@@dynamicModel(ResponseTextFormatConfigurationPython);
@@dynamicModel(ItemContent);
@@dynamicModel(ItemContentInputAudio);
@@dynamicModel(InputMessageContentList);
@@ -192,6 +210,21 @@ using TypeSpec.HttpClient.CSharp;
@@dynamicModel(ImageGenTool);
@@dynamicModel(LocalShellExecAction);
@@dynamicModel(LocalShellTool);
+@@dynamicModel(FunctionShellToolParam);
+@@dynamicModel(ApplyPatchToolParam);
+@@dynamicModel(CustomToolParam);
+@@dynamicModel(CustomToolParamFormat);
+@@dynamicModel(CustomTextFormatParam);
+@@dynamicModel(CustomGrammarFormatParam);
+@@dynamicModel(FunctionShellActionParam);
+@@dynamicModel(FunctionShellCallOutputContentParam);
+@@dynamicModel(FunctionShellCallOutputOutcomeParam);
+@@dynamicModel(FunctionShellCallOutputOutcomeTimeout);
+@@dynamicModel(FunctionShellCallOutputOutcomeExit);
+@@dynamicModel(ApplyPatchOperationParam);
+@@dynamicModel(ApplyPatchCreateFileOperation);
+@@dynamicModel(ApplyPatchDeleteFileOperation);
+@@dynamicModel(ApplyPatchUpdateFileOperation);
@@dynamicModel(MCPListToolsTool);
@@dynamicModel(MCPTool);
@@dynamicModel(MCPToolFilter);
@@ -207,6 +240,8 @@ using TypeSpec.HttpClient.CSharp;
@@dynamicModel(ResponseMCPListToolsCompletedEvent);
@@dynamicModel(ResponseMCPListToolsFailedEvent);
@@dynamicModel(ResponseMCPListToolsInProgressEvent);
+@@dynamicModel(ResponseCustomToolCallInputDeltaEvent);
+@@dynamicModel(ResponseCustomToolCallInputDoneEvent);
@@dynamicModel(ResponseOutputTextAnnotationAddedEvent);
@@dynamicModel(ResponseQueuedEvent);
@@dynamicModel(ResponseReasoningDeltaEvent);
@@ -227,6 +262,8 @@ using TypeSpec.HttpClient.CSharp;
@@dynamicModel(TopLogProb);
@@dynamicModel(LogProb);
@@dynamicModel(WebSearchToolFilters);
+@@dynamicModel(Prompt);
+@@dynamicModel(ResponsePromptVariables);
// custom.tsp models
@@dynamicModel(ResponseErrorResponse);
@@dynamicModel(DeleteResponseResponse);
@@ -269,6 +306,18 @@ using TypeSpec.HttpClient.CSharp;
@@dynamicModel(MCPApprovalResponseItemResource);
@@dynamicModel(MCPCallItemParam);
@@dynamicModel(MCPCallItemResource);
+@@dynamicModel(FunctionShellCallItemParam);
+@@dynamicModel(FunctionShellCallItemResource);
+@@dynamicModel(FunctionShellCallOutputItemParam);
+@@dynamicModel(FunctionShellCallOutputItemResource);
+@@dynamicModel(ApplyPatchToolCallItemParam);
+@@dynamicModel(ApplyPatchToolCallItemResource);
+@@dynamicModel(ApplyPatchToolCallOutputItemParam);
+@@dynamicModel(ApplyPatchToolCallOutputItemResource);
+@@dynamicModel(CustomToolCallItemParam);
+@@dynamicModel(CustomToolCallItemResource);
+@@dynamicModel(CustomToolCallOutputItemParam);
+@@dynamicModel(CustomToolCallOutputItemResource);
// custom/items.messages.tsp models
@@dynamicModel(ResponsesMessageItemParam);
@@dynamicModel(ResponsesUserMessageItemParam);
diff --git a/src/Custom/Responses/CreateResponseOptions.cs b/src/Custom/Responses/CreateResponseOptions.cs
index a81bc9be4..3fb9db938 100644
--- a/src/Custom/Responses/CreateResponseOptions.cs
+++ b/src/Custom/Responses/CreateResponseOptions.cs
@@ -161,6 +161,7 @@ internal CreateResponseOptions Clone()
clone.StoredOutputEnabled = StoredOutputEnabled;
clone.StreamingEnabled = StreamingEnabled;
clone.ConversationOptions = ConversationOptions;
+ clone.Prompt = Prompt;
return clone;
}
diff --git a/src/Custom/Responses/Internal/GeneratorStubs.cs b/src/Custom/Responses/Internal/GeneratorStubs.cs
index 213ddb670..cc0505918 100644
--- a/src/Custom/Responses/Internal/GeneratorStubs.cs
+++ b/src/Custom/Responses/Internal/GeneratorStubs.cs
@@ -123,4 +123,48 @@ namespace OpenAI.Responses;
[CodeGenType("UnknownCodeInterpreterToolOutput")] internal partial class InternalUnknownCodeInterpreterToolOutput {}
[CodeGenType("UnknownCodeInterpreterContainerConfiguration")] internal partial class InternalUnknownCodeInterpreterContainerConfiguration {}
[CodeGenType("GetInputTokenCountsRequestContentType")] internal readonly partial struct InternalGetInputTokenCountsRequestContentType {}
-[CodeGenType("CompactConversationRequestContentType")] internal readonly partial struct InternalCompactConversationRequestContentType {}
\ No newline at end of file
+[CodeGenType("CompactConversationRequestContentType")] internal readonly partial struct InternalCompactConversationRequestContentType {}
+[CodeGenType("ApplyPatchCallOutputStatusParam")] internal readonly partial struct InternalApplyPatchCallOutputStatusParam {}
+[CodeGenType("ApplyPatchCallStatusParam")] internal readonly partial struct InternalApplyPatchCallStatusParam {}
+[CodeGenType("ApplyPatchCreateFileOperation")] internal partial class InternalApplyPatchCreateFileOperation {}
+[CodeGenType("ApplyPatchDeleteFileOperation")] internal partial class InternalApplyPatchDeleteFileOperation {}
+[CodeGenType("ApplyPatchOperationParam")] internal partial class InternalApplyPatchOperationParam {}
+[CodeGenType("ApplyPatchOperationType")] internal readonly partial struct InternalApplyPatchOperationType {}
+[CodeGenType("ApplyPatchToolCallItemParam")] internal partial class InternalApplyPatchToolCallItemParam {}
+[CodeGenType("ApplyPatchToolCallItemResource")] internal partial class InternalApplyPatchToolCallItemResource {}
+[CodeGenType("ApplyPatchToolCallOutputItemParam")] internal partial class InternalApplyPatchToolCallOutputItemParam {}
+[CodeGenType("ApplyPatchToolCallOutputItemResource")] internal partial class InternalApplyPatchToolCallOutputItemResource {}
+[CodeGenType("ApplyPatchUpdateFileOperation")] internal partial class InternalApplyPatchUpdateFileOperation {}
+
+[CodeGenType("CustomToolCallItemParam")] internal partial class InternalCustomToolCallItemParam {}
+[CodeGenType("CustomToolCallItemResource")] internal partial class InternalCustomToolCallItemResource {}
+[CodeGenType("CustomToolCallItemResourceStatus")] internal readonly partial struct InternalCustomToolCallItemResourceStatus {}
+[CodeGenType("CustomToolCallOutputItemParam")] internal partial class InternalCustomToolCallOutputItemParam {}
+[CodeGenType("CustomToolCallOutputItemResource")] internal partial class InternalCustomToolCallOutputItemResource {}
+[CodeGenType("CustomToolCallOutputItemResourceStatus")] internal readonly partial struct InternalCustomToolCallOutputItemResourceStatus {}
+[CodeGenType("CustomToolParamFormatType")] internal readonly partial struct InternalCustomToolParamFormatType {}
+[CodeGenType("FunctionShellActionParam")] internal partial class InternalFunctionShellActionParam {}
+[CodeGenType("FunctionShellCallItemParam")] internal partial class InternalFunctionShellCallItemParam {}
+[CodeGenType("FunctionShellCallItemResource")] internal partial class InternalFunctionShellCallItemResource {}
+[CodeGenType("FunctionShellCallItemStatus")] internal readonly partial struct InternalFunctionShellCallItemStatus {}
+[CodeGenType("FunctionShellCallOutputContentParam")] internal partial class InternalFunctionShellCallOutputContentParam {}
+[CodeGenType("FunctionShellCallOutputItemParam")] internal partial class InternalFunctionShellCallOutputItemParam {}
+[CodeGenType("FunctionShellCallOutputItemResource")] internal partial class InternalFunctionShellCallOutputItemResource {}
+[CodeGenType("FunctionShellCallOutputItemResourceStatus")] internal readonly partial struct InternalFunctionShellCallOutputItemResourceStatus {}
+[CodeGenType("FunctionShellCallOutputOutcomeExit")] internal partial class InternalFunctionShellCallOutputOutcomeExit {}
+[CodeGenType("FunctionShellCallOutputOutcomeParam")] internal partial class InternalFunctionShellCallOutputOutcomeParam {}
+[CodeGenType("FunctionShellCallOutputOutcomeTimeout")] internal partial class InternalFunctionShellCallOutputOutcomeTimeout {}
+[CodeGenType("Prompt")] internal partial class InternalPrompt {}
+[CodeGenType("ResponseCustomToolCallInputDeltaEvent")] internal partial class InternalResponseCustomToolCallInputDeltaEvent {}
+[CodeGenType("ResponseCustomToolCallInputDoneEvent")] internal partial class InternalResponseCustomToolCallInputDoneEvent {}
+[CodeGenType("ResponsePromptVariables")] internal partial class InternalResponsePromptVariables {}
+[CodeGenType("ResponseTextFormatConfigurationGrammar")] internal partial class InternalResponseTextFormatConfigurationGrammar {}
+[CodeGenType("ResponseTextFormatConfigurationPython")] internal partial class InternalResponseTextFormatConfigurationPython {}
+[CodeGenType("ToolChoiceObjectAllowed")] internal partial class InternalToolChoiceObjectAllowed {}
+[CodeGenType("ToolChoiceObjectAllowedMode")] internal readonly partial struct InternalToolChoiceObjectAllowedMode {}
+[CodeGenType("ToolChoiceObjectApplyPatch")] internal partial class InternalToolChoiceObjectApplyPatch {}
+[CodeGenType("ToolChoiceObjectCustom")] internal partial class InternalToolChoiceObjectCustom {}
+[CodeGenType("ToolChoiceObjectShell")] internal partial class InternalToolChoiceObjectShell {}
+[CodeGenType("UnknownApplyPatchOperationParam")] internal partial class InternalUnknownApplyPatchOperationParam {}
+[CodeGenType("UnknownCustomToolParamFormat")] internal partial class InternalUnknownCustomToolParamFormat {}
+[CodeGenType("UnknownFunctionShellCallOutputOutcomeParam")] internal partial class InternalUnknownFunctionShellCallOutputOutcomeParam {}
\ No newline at end of file
diff --git a/src/Custom/Responses/Tools/ApplyPatchTool.cs b/src/Custom/Responses/Tools/ApplyPatchTool.cs
new file mode 100644
index 000000000..d8cee73a2
--- /dev/null
+++ b/src/Custom/Responses/Tools/ApplyPatchTool.cs
@@ -0,0 +1,9 @@
+using Microsoft.TypeSpec.Generator.Customizations;
+
+namespace OpenAI.Responses;
+
+// CUSTOM: Renamed.
+[CodeGenType("ApplyPatchToolParam")]
+public partial class ApplyPatchTool
+{
+}
diff --git a/src/Custom/Responses/Tools/CustomTool.cs b/src/Custom/Responses/Tools/CustomTool.cs
new file mode 100644
index 000000000..69ccd4152
--- /dev/null
+++ b/src/Custom/Responses/Tools/CustomTool.cs
@@ -0,0 +1,9 @@
+using Microsoft.TypeSpec.Generator.Customizations;
+
+namespace OpenAI.Responses;
+
+// CUSTOM: Renamed.
+[CodeGenType("CustomToolParam")]
+public partial class CustomTool
+{
+}
diff --git a/src/Custom/Responses/Tools/CustomToolFormat.cs b/src/Custom/Responses/Tools/CustomToolFormat.cs
new file mode 100644
index 000000000..ca31cd0eb
--- /dev/null
+++ b/src/Custom/Responses/Tools/CustomToolFormat.cs
@@ -0,0 +1,9 @@
+using Microsoft.TypeSpec.Generator.Customizations;
+
+namespace OpenAI.Responses;
+
+// CUSTOM: Renamed.
+[CodeGenType("CustomToolParamFormat")]
+public abstract partial class CustomToolFormat
+{
+}
diff --git a/src/Custom/Responses/Tools/CustomToolGrammarFormat.cs b/src/Custom/Responses/Tools/CustomToolGrammarFormat.cs
new file mode 100644
index 000000000..35efea865
--- /dev/null
+++ b/src/Custom/Responses/Tools/CustomToolGrammarFormat.cs
@@ -0,0 +1,9 @@
+using Microsoft.TypeSpec.Generator.Customizations;
+
+namespace OpenAI.Responses;
+
+// CUSTOM: Renamed.
+[CodeGenType("CustomGrammarFormatParam")]
+public partial class CustomToolGrammarFormat
+{
+}
diff --git a/src/Custom/Responses/Tools/CustomToolTextFormat.cs b/src/Custom/Responses/Tools/CustomToolTextFormat.cs
new file mode 100644
index 000000000..982a7358b
--- /dev/null
+++ b/src/Custom/Responses/Tools/CustomToolTextFormat.cs
@@ -0,0 +1,9 @@
+using Microsoft.TypeSpec.Generator.Customizations;
+
+namespace OpenAI.Responses;
+
+// CUSTOM: Renamed.
+[CodeGenType("CustomTextFormatParam")]
+public partial class CustomToolTextFormat
+{
+}
diff --git a/src/Custom/Responses/Tools/GrammarSyntax.cs b/src/Custom/Responses/Tools/GrammarSyntax.cs
new file mode 100644
index 000000000..c2bbc8fd9
--- /dev/null
+++ b/src/Custom/Responses/Tools/GrammarSyntax.cs
@@ -0,0 +1,9 @@
+using Microsoft.TypeSpec.Generator.Customizations;
+
+namespace OpenAI.Responses;
+
+// CUSTOM: Renamed.
+[CodeGenType("GrammarSyntax")]
+public readonly partial struct GrammarSyntax
+{
+}
diff --git a/src/Custom/Responses/Tools/ResponseTool.cs b/src/Custom/Responses/Tools/ResponseTool.cs
index 4c1ad299c..5cc22b174 100644
--- a/src/Custom/Responses/Tools/ResponseTool.cs
+++ b/src/Custom/Responses/Tools/ResponseTool.cs
@@ -123,6 +123,50 @@ public static CodeInterpreterTool CreateCodeInterpreterTool(CodeInterpreterToolC
container: container);
}
+ // CUSTOM: Added factory method as a convenience.
+ ///
+ /// Creates a new instance of the class.
+ ///
+ /// A new instance of the class.
+ public static ShellTool CreateShellTool()
+ {
+ return new ShellTool(
+ kind: InternalToolType.Shell,
+ patch: default);
+ }
+
+ // CUSTOM: Added factory method as a convenience.
+ ///
+ /// Creates a new instance of the class.
+ ///
+ /// A new instance of the class.
+ public static ApplyPatchTool CreateApplyPatchTool()
+ {
+ return new ApplyPatchTool(
+ kind: InternalToolType.ApplyPatch,
+ patch: default);
+ }
+
+ // CUSTOM: Added factory method as a convenience.
+ ///
+ /// Creates a new instance of the class.
+ ///
+ /// The name of the custom tool.
+ /// An optional description of the custom tool.
+ /// An optional format for the custom tool output.
+ /// A new instance of the class.
+ public static CustomTool CreateCustomTool(string name, string description = null, CustomToolFormat format = null)
+ {
+ Argument.AssertNotNull(name, nameof(name));
+
+ return new CustomTool(
+ kind: InternalToolType.Custom,
+ patch: default,
+ name: name,
+ description: description,
+ format: format);
+ }
+
// CUSTOM: Added factory method for a convenience.
///
/// Creates a new instance of the class.
diff --git a/src/Custom/Responses/Tools/ShellTool.cs b/src/Custom/Responses/Tools/ShellTool.cs
new file mode 100644
index 000000000..5aac8bcf4
--- /dev/null
+++ b/src/Custom/Responses/Tools/ShellTool.cs
@@ -0,0 +1,9 @@
+using Microsoft.TypeSpec.Generator.Customizations;
+
+namespace OpenAI.Responses;
+
+// CUSTOM: Renamed.
+[CodeGenType("FunctionShellToolParam")]
+public partial class ShellTool
+{
+}
diff --git a/src/Generated/Models/OpenAIContext.cs b/src/Generated/Models/OpenAIContext.cs
index e4c0012f7..b86ea3877 100644
--- a/src/Generated/Models/OpenAIContext.cs
+++ b/src/Generated/Models/OpenAIContext.cs
@@ -26,6 +26,7 @@
namespace OpenAI
{
+ [ModelReaderWriterBuildable(typeof(ApplyPatchTool))]
[ModelReaderWriterBuildable(typeof(Assistant))]
[ModelReaderWriterBuildable(typeof(AssistantChatMessage))]
[ModelReaderWriterBuildable(typeof(AssistantCollectionOptions))]
@@ -106,6 +107,10 @@ namespace OpenAI
[ModelReaderWriterBuildable(typeof(CreateContainerFileBody))]
[ModelReaderWriterBuildable(typeof(CreateResponseOptions))]
[ModelReaderWriterBuildable(typeof(CustomMcpToolCallApprovalPolicy))]
+ [ModelReaderWriterBuildable(typeof(CustomTool))]
+ [ModelReaderWriterBuildable(typeof(CustomToolFormat))]
+ [ModelReaderWriterBuildable(typeof(CustomToolGrammarFormat))]
+ [ModelReaderWriterBuildable(typeof(CustomToolTextFormat))]
[ModelReaderWriterBuildable(typeof(DeleteContainerFileResponse))]
[ModelReaderWriterBuildable(typeof(DeleteContainerResponse))]
[ModelReaderWriterBuildable(typeof(DeveloperChatMessage))]
@@ -170,6 +175,14 @@ namespace OpenAI
[ModelReaderWriterBuildable(typeof(InputNoiseReductionOptions))]
[ModelReaderWriterBuildable(typeof(InputTranscriptionOptions))]
[ModelReaderWriterBuildable(typeof(InternalAddUploadPartRequest))]
+ [ModelReaderWriterBuildable(typeof(InternalApplyPatchCreateFileOperation))]
+ [ModelReaderWriterBuildable(typeof(InternalApplyPatchDeleteFileOperation))]
+ [ModelReaderWriterBuildable(typeof(InternalApplyPatchOperationParam))]
+ [ModelReaderWriterBuildable(typeof(InternalApplyPatchToolCallItemParam))]
+ [ModelReaderWriterBuildable(typeof(InternalApplyPatchToolCallItemResource))]
+ [ModelReaderWriterBuildable(typeof(InternalApplyPatchToolCallOutputItemParam))]
+ [ModelReaderWriterBuildable(typeof(InternalApplyPatchToolCallOutputItemResource))]
+ [ModelReaderWriterBuildable(typeof(InternalApplyPatchUpdateFileOperation))]
[ModelReaderWriterBuildable(typeof(InternalAssistantsNamedToolChoiceFunction))]
[ModelReaderWriterBuildable(typeof(InternalAssistantToolsFileSearchFileSearch))]
[ModelReaderWriterBuildable(typeof(InternalAssistantToolsFileSearchTypeOnly))]
@@ -264,6 +277,10 @@ namespace OpenAI
[ModelReaderWriterBuildable(typeof(InternalCreateUploadRequest))]
[ModelReaderWriterBuildable(typeof(InternalCreateVectorStoreFileBatchRequest))]
[ModelReaderWriterBuildable(typeof(InternalCreateVectorStoreFileRequest))]
+ [ModelReaderWriterBuildable(typeof(InternalCustomToolCallItemParam))]
+ [ModelReaderWriterBuildable(typeof(InternalCustomToolCallItemResource))]
+ [ModelReaderWriterBuildable(typeof(InternalCustomToolCallOutputItemParam))]
+ [ModelReaderWriterBuildable(typeof(InternalCustomToolCallOutputItemResource))]
[ModelReaderWriterBuildable(typeof(InternalDeleteEvalResponse))]
[ModelReaderWriterBuildable(typeof(InternalDeleteEvalRunResponse))]
[ModelReaderWriterBuildable(typeof(InternalDeleteFineTuningCheckpointPermissionResponse))]
@@ -350,6 +367,15 @@ namespace OpenAI
[ModelReaderWriterBuildable(typeof(InternalFineTuningJobRequestMethodSupervised))]
[ModelReaderWriterBuildable(typeof(InternalFineTuningJobsPageToken))]
[ModelReaderWriterBuildable(typeof(InternalFunctionDefinition))]
+ [ModelReaderWriterBuildable(typeof(InternalFunctionShellActionParam))]
+ [ModelReaderWriterBuildable(typeof(InternalFunctionShellCallItemParam))]
+ [ModelReaderWriterBuildable(typeof(InternalFunctionShellCallItemResource))]
+ [ModelReaderWriterBuildable(typeof(InternalFunctionShellCallOutputContentParam))]
+ [ModelReaderWriterBuildable(typeof(InternalFunctionShellCallOutputItemParam))]
+ [ModelReaderWriterBuildable(typeof(InternalFunctionShellCallOutputItemResource))]
+ [ModelReaderWriterBuildable(typeof(InternalFunctionShellCallOutputOutcomeExit))]
+ [ModelReaderWriterBuildable(typeof(InternalFunctionShellCallOutputOutcomeParam))]
+ [ModelReaderWriterBuildable(typeof(InternalFunctionShellCallOutputOutcomeTimeout))]
[ModelReaderWriterBuildable(typeof(InternalFunctionToolCallItemParam))]
[ModelReaderWriterBuildable(typeof(InternalFunctionToolCallOutputItemParam))]
[ModelReaderWriterBuildable(typeof(InternalImageEditCompletedEvent))]
@@ -432,6 +458,7 @@ namespace OpenAI
[ModelReaderWriterBuildable(typeof(InternalModifyThreadRequestToolResources))]
[ModelReaderWriterBuildable(typeof(InternalModifyThreadRequestToolResourcesCodeInterpreter))]
[ModelReaderWriterBuildable(typeof(InternalOtherChunkingStrategyResponseParam))]
+ [ModelReaderWriterBuildable(typeof(InternalPrompt))]
[ModelReaderWriterBuildable(typeof(InternalRealtimeAudioFarFieldNoiseReduction))]
[ModelReaderWriterBuildable(typeof(InternalRealtimeAudioFormats))]
[ModelReaderWriterBuildable(typeof(InternalRealtimeAudioFormatsPcm))]
@@ -535,6 +562,8 @@ namespace OpenAI
[ModelReaderWriterBuildable(typeof(InternalRealtimeTranscriptionSessionGA))]
[ModelReaderWriterBuildable(typeof(InternalReasoningItemParam))]
[ModelReaderWriterBuildable(typeof(InternalRequiredFunctionToolCall))]
+ [ModelReaderWriterBuildable(typeof(InternalResponseCustomToolCallInputDeltaEvent))]
+ [ModelReaderWriterBuildable(typeof(InternalResponseCustomToolCallInputDoneEvent))]
[ModelReaderWriterBuildable(typeof(InternalResponseErrorResponse))]
[ModelReaderWriterBuildable(typeof(InternalResponseFormat))]
[ModelReaderWriterBuildable(typeof(InternalResponseFormatJsonObject))]
@@ -542,6 +571,7 @@ namespace OpenAI
[ModelReaderWriterBuildable(typeof(InternalResponseFormatJsonSchemaJsonSchema))]
[ModelReaderWriterBuildable(typeof(InternalResponseFormatJsonSchemaSchema))]
[ModelReaderWriterBuildable(typeof(InternalResponseFormatText))]
+ [ModelReaderWriterBuildable(typeof(InternalResponsePromptVariables))]
[ModelReaderWriterBuildable(typeof(InternalResponseReasoningDeltaEvent))]
[ModelReaderWriterBuildable(typeof(InternalResponseReasoningDoneEvent))]
[ModelReaderWriterBuildable(typeof(InternalResponseReasoningSummaryDeltaEvent))]
@@ -558,6 +588,8 @@ namespace OpenAI
[ModelReaderWriterBuildable(typeof(InternalResponsesTextFormatText))]
[ModelReaderWriterBuildable(typeof(InternalResponsesUserMessage))]
[ModelReaderWriterBuildable(typeof(InternalResponsesUserMessageItemParam))]
+ [ModelReaderWriterBuildable(typeof(InternalResponseTextFormatConfigurationGrammar))]
+ [ModelReaderWriterBuildable(typeof(InternalResponseTextFormatConfigurationPython))]
[ModelReaderWriterBuildable(typeof(InternalRunObjectRequiredActionSubmitToolOutputs))]
[ModelReaderWriterBuildable(typeof(InternalRunRequiredAction))]
[ModelReaderWriterBuildable(typeof(InternalRunStepCodeInterpreterLogOutput))]
@@ -600,12 +632,16 @@ namespace OpenAI
[ModelReaderWriterBuildable(typeof(InternalThreadObjectToolResourcesFileSearch))]
[ModelReaderWriterBuildable(typeof(InternalTodoFineTuneChatRequestInput))]
[ModelReaderWriterBuildable(typeof(InternalToolChoiceObject))]
+ [ModelReaderWriterBuildable(typeof(InternalToolChoiceObjectAllowed))]
+ [ModelReaderWriterBuildable(typeof(InternalToolChoiceObjectApplyPatch))]
[ModelReaderWriterBuildable(typeof(InternalToolChoiceObjectCodeInterpreter))]
[ModelReaderWriterBuildable(typeof(InternalToolChoiceObjectComputer))]
+ [ModelReaderWriterBuildable(typeof(InternalToolChoiceObjectCustom))]
[ModelReaderWriterBuildable(typeof(InternalToolChoiceObjectFileSearch))]
[ModelReaderWriterBuildable(typeof(InternalToolChoiceObjectFunction))]
[ModelReaderWriterBuildable(typeof(InternalToolChoiceObjectImageGen))]
[ModelReaderWriterBuildable(typeof(InternalToolChoiceObjectMCP))]
+ [ModelReaderWriterBuildable(typeof(InternalToolChoiceObjectShell))]
[ModelReaderWriterBuildable(typeof(InternalToolChoiceObjectWebSearch))]
[ModelReaderWriterBuildable(typeof(InternalToolResourcesFileSearchIdsOnly))]
[ModelReaderWriterBuildable(typeof(InternalTopLogProb))]
@@ -616,6 +652,7 @@ namespace OpenAI
[ModelReaderWriterBuildable(typeof(InternalTranscriptTextUsageTokens))]
[ModelReaderWriterBuildable(typeof(InternalTranscriptTextUsageTokensInputTokenDetails))]
[ModelReaderWriterBuildable(typeof(InternalUnknownAnnotation))]
+ [ModelReaderWriterBuildable(typeof(InternalUnknownApplyPatchOperationParam))]
[ModelReaderWriterBuildable(typeof(InternalUnknownChatCompletionRequestMessageContentPart))]
[ModelReaderWriterBuildable(typeof(InternalUnknownChatMessage))]
[ModelReaderWriterBuildable(typeof(InternalUnknownChatOutputPrediction))]
@@ -630,6 +667,7 @@ namespace OpenAI
[ModelReaderWriterBuildable(typeof(InternalUnknownComputerToolCallOutputItemOutput))]
[ModelReaderWriterBuildable(typeof(InternalUnknownCreateTranscriptionResponseJsonUsage))]
[ModelReaderWriterBuildable(typeof(InternalUnknownCreateTranscriptionResponseStreamEvent))]
+ [ModelReaderWriterBuildable(typeof(InternalUnknownCustomToolParamFormat))]
[ModelReaderWriterBuildable(typeof(InternalUnknownDotNetAssistantResponseFormat))]
[ModelReaderWriterBuildable(typeof(InternalUnknownDotNetCombinedChunkingStrategyParam))]
[ModelReaderWriterBuildable(typeof(InternalUnknownDotNetCreateSpeechStreamingResponse))]
@@ -640,6 +678,7 @@ namespace OpenAI
[ModelReaderWriterBuildable(typeof(InternalUnknownEvalItemContent))]
[ModelReaderWriterBuildable(typeof(InternalUnknownEvalRunDataContentSource))]
[ModelReaderWriterBuildable(typeof(InternalUnknownEvalRunDataSourceParams))]
+ [ModelReaderWriterBuildable(typeof(InternalUnknownFunctionShellCallOutputOutcomeParam))]
[ModelReaderWriterBuildable(typeof(InternalUnknownItemContent))]
[ModelReaderWriterBuildable(typeof(InternalUnknownItemParam))]
[ModelReaderWriterBuildable(typeof(InternalUnknownItemResource))]
@@ -770,6 +809,7 @@ namespace OpenAI
[ModelReaderWriterBuildable(typeof(RunStepUpdateCodeInterpreterOutput))]
[ModelReaderWriterBuildable(typeof(RunTokenUsage))]
[ModelReaderWriterBuildable(typeof(RunTruncationStrategy))]
+ [ModelReaderWriterBuildable(typeof(ShellTool))]
[ModelReaderWriterBuildable(typeof(SpeechGenerationOptions))]
[ModelReaderWriterBuildable(typeof(StaticFileChunkingStrategy))]
[ModelReaderWriterBuildable(typeof(StreamingAudioTranscriptionTextDeltaUpdate))]
diff --git a/src/Generated/Models/Responses/ApplyPatchTool.Serialization.cs b/src/Generated/Models/Responses/ApplyPatchTool.Serialization.cs
new file mode 100644
index 000000000..d05f05785
--- /dev/null
+++ b/src/Generated/Models/Responses/ApplyPatchTool.Serialization.cs
@@ -0,0 +1,112 @@
+//
+
+#nullable disable
+
+using System;
+using System.ClientModel.Primitives;
+using System.Text;
+using System.Text.Json;
+using OpenAI;
+
+namespace OpenAI.Responses
+{
+ public partial class ApplyPatchTool : ResponseTool, IJsonModel
+ {
+ void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options)
+ {
+#pragma warning disable SCME0001 // Type is for evaluation purposes only and is subject to change or removal in future updates.
+ if (Patch.Contains("$"u8))
+ {
+ writer.WriteRawValue(Patch.GetJson("$"u8));
+ return;
+ }
+#pragma warning restore SCME0001 // Type is for evaluation purposes only and is subject to change or removal in future updates.
+
+ writer.WriteStartObject();
+ JsonModelWriteCore(writer, options);
+ writer.WriteEndObject();
+ }
+
+ protected override void JsonModelWriteCore(Utf8JsonWriter writer, ModelReaderWriterOptions options)
+ {
+ string format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format;
+ if (format != "J")
+ {
+ throw new FormatException($"The model {nameof(ApplyPatchTool)} does not support writing '{format}' format.");
+ }
+ base.JsonModelWriteCore(writer, options);
+#pragma warning disable SCME0001 // Type is for evaluation purposes only and is subject to change or removal in future updates.
+
+ Patch.WriteTo(writer);
+#pragma warning restore SCME0001 // Type is for evaluation purposes only and is subject to change or removal in future updates.
+ }
+
+ ApplyPatchTool IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) => (ApplyPatchTool)JsonModelCreateCore(ref reader, options);
+
+ protected override ResponseTool JsonModelCreateCore(ref Utf8JsonReader reader, ModelReaderWriterOptions options)
+ {
+ string format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format;
+ if (format != "J")
+ {
+ throw new FormatException($"The model {nameof(ApplyPatchTool)} does not support reading '{format}' format.");
+ }
+ using JsonDocument document = JsonDocument.ParseValue(ref reader);
+ return DeserializeApplyPatchTool(document.RootElement, null, options);
+ }
+
+ internal static ApplyPatchTool DeserializeApplyPatchTool(JsonElement element, BinaryData data, ModelReaderWriterOptions options)
+ {
+ if (element.ValueKind == JsonValueKind.Null)
+ {
+ return null;
+ }
+ InternalToolType kind = default;
+#pragma warning disable SCME0001 // Type is for evaluation purposes only and is subject to change or removal in future updates.
+ JsonPatch patch = new JsonPatch(data is null ? ReadOnlyMemory.Empty : data.ToMemory());
+#pragma warning restore SCME0001 // Type is for evaluation purposes only and is subject to change or removal in future updates.
+ foreach (var prop in element.EnumerateObject())
+ {
+ if (prop.NameEquals("type"u8))
+ {
+ kind = new InternalToolType(prop.Value.GetString());
+ continue;
+ }
+ patch.Set([.. "$."u8, .. Encoding.UTF8.GetBytes(prop.Name)], prop.Value.GetUtf8Bytes());
+ }
+ return new ApplyPatchTool(kind, patch);
+ }
+
+ BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) => PersistableModelWriteCore(options);
+
+ protected override BinaryData PersistableModelWriteCore(ModelReaderWriterOptions options)
+ {
+ string format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format;
+ switch (format)
+ {
+ case "J":
+ return ModelReaderWriter.Write(this, options, OpenAIContext.Default);
+ default:
+ throw new FormatException($"The model {nameof(ApplyPatchTool)} does not support writing '{options.Format}' format.");
+ }
+ }
+
+ ApplyPatchTool IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) => (ApplyPatchTool)PersistableModelCreateCore(data, options);
+
+ protected override ResponseTool PersistableModelCreateCore(BinaryData data, ModelReaderWriterOptions options)
+ {
+ string format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format;
+ switch (format)
+ {
+ case "J":
+ using (JsonDocument document = JsonDocument.Parse(data, ModelSerializationExtensions.JsonDocumentOptions))
+ {
+ return DeserializeApplyPatchTool(document.RootElement, data, options);
+ }
+ default:
+ throw new FormatException($"The model {nameof(ApplyPatchTool)} does not support reading '{options.Format}' format.");
+ }
+ }
+
+ string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J";
+ }
+}
diff --git a/src/Generated/Models/Responses/ApplyPatchTool.cs b/src/Generated/Models/Responses/ApplyPatchTool.cs
new file mode 100644
index 000000000..18cd98fc9
--- /dev/null
+++ b/src/Generated/Models/Responses/ApplyPatchTool.cs
@@ -0,0 +1,23 @@
+//
+
+#nullable disable
+
+using System.ClientModel.Primitives;
+using System.Diagnostics.CodeAnalysis;
+
+namespace OpenAI.Responses
+{
+ [Experimental("OPENAI001")]
+ public partial class ApplyPatchTool : ResponseTool
+ {
+ public ApplyPatchTool() : this(InternalToolType.ApplyPatch, default)
+ {
+ }
+
+#pragma warning disable SCME0001 // Type is for evaluation purposes only and is subject to change or removal in future updates.
+ internal ApplyPatchTool(InternalToolType kind, in JsonPatch patch) : base(kind, patch)
+ {
+ }
+#pragma warning restore SCME0001 // Type is for evaluation purposes only and is subject to change or removal in future updates.
+ }
+}
diff --git a/src/Generated/Models/Responses/CreateResponseOptions.Serialization.cs b/src/Generated/Models/Responses/CreateResponseOptions.Serialization.cs
index 57b0dabf4..f9e0ac014 100644
--- a/src/Generated/Models/Responses/CreateResponseOptions.Serialization.cs
+++ b/src/Generated/Models/Responses/CreateResponseOptions.Serialization.cs
@@ -165,6 +165,11 @@ protected virtual void JsonModelWriteCore(Utf8JsonWriter writer, ModelReaderWrit
writer.WritePropertyName("tool_choice"u8);
writer.WriteObjectValue(ToolChoice, options);
}
+ if (Optional.IsDefined(Prompt) && !Patch.Contains("$.prompt"u8))
+ {
+ writer.WritePropertyName("prompt"u8);
+ writer.WriteObjectValue(Prompt, options);
+ }
if (Optional.IsDefined(TruncationMode) && !Patch.Contains("$.truncation"u8))
{
writer.WritePropertyName("truncation"u8);
@@ -277,6 +282,7 @@ internal static CreateResponseOptions DeserializeCreateResponseOptions(JsonEleme
ResponseTextOptions textOptions = default;
IList tools = default;
ResponseToolChoice toolChoice = default;
+ InternalPrompt prompt = default;
ResponseTruncationMode? truncationMode = default;
IList inputItems = default;
IList includedProperties = default;
@@ -456,6 +462,15 @@ internal static CreateResponseOptions DeserializeCreateResponseOptions(JsonEleme
toolChoice = ResponseToolChoice.DeserializeResponseToolChoice(prop.Value, options);
continue;
}
+ if (prop.NameEquals("prompt"u8))
+ {
+ if (prop.Value.ValueKind == JsonValueKind.Null)
+ {
+ continue;
+ }
+ prompt = InternalPrompt.DeserializeInternalPrompt(prop.Value, prop.Value.GetUtf8Bytes(), options);
+ continue;
+ }
if (prop.NameEquals("truncation"u8))
{
if (prop.Value.ValueKind == JsonValueKind.Null)
@@ -553,6 +568,7 @@ internal static CreateResponseOptions DeserializeCreateResponseOptions(JsonEleme
textOptions,
tools ?? new ChangeTrackingList(),
toolChoice,
+ prompt,
truncationMode,
inputItems ?? new ChangeTrackingList(),
includedProperties ?? new ChangeTrackingList(),
@@ -619,6 +635,10 @@ private bool PropagateGet(ReadOnlySpan jsonPath, out JsonPatch.EncodedValu
{
return TextOptions.Patch.TryGetEncodedValue([.. "$"u8, .. local.Slice("text"u8.Length)], out value);
}
+ if (local.StartsWith("prompt"u8))
+ {
+ return Prompt.Patch.TryGetEncodedValue([.. "$"u8, .. local.Slice("prompt"u8.Length)], out value);
+ }
if (local.StartsWith("conversation"u8))
{
return ConversationOptions.Patch.TryGetEncodedValue([.. "$"u8, .. local.Slice("conversation"u8.Length)], out value);
@@ -662,6 +682,11 @@ private bool PropagateSet(ReadOnlySpan jsonPath, JsonPatch.EncodedValue va
TextOptions.Patch.Set([.. "$"u8, .. local.Slice("text"u8.Length)], value);
return true;
}
+ if (local.StartsWith("prompt"u8))
+ {
+ Prompt.Patch.Set([.. "$"u8, .. local.Slice("prompt"u8.Length)], value);
+ return true;
+ }
if (local.StartsWith("conversation"u8))
{
ConversationOptions.Patch.Set([.. "$"u8, .. local.Slice("conversation"u8.Length)], value);
diff --git a/src/Generated/Models/Responses/CreateResponseOptions.cs b/src/Generated/Models/Responses/CreateResponseOptions.cs
index 285bb972e..f125d706b 100644
--- a/src/Generated/Models/Responses/CreateResponseOptions.cs
+++ b/src/Generated/Models/Responses/CreateResponseOptions.cs
@@ -17,12 +17,12 @@ public partial class CreateResponseOptions
[Experimental("SCME0001")]
private JsonPatch _patch;
- public CreateResponseOptions() : this(null, default, default, default, null, null, default, null, null, null, default, default, default, null, null, null, null, default, null, null, default, default, default, null, default)
+ public CreateResponseOptions() : this(null, default, default, default, null, null, default, null, null, null, default, default, default, null, null, null, null, null, default, null, null, default, default, default, null, default)
{
}
#pragma warning disable SCME0001 // Type is for evaluation purposes only and is subject to change or removal in future updates.
- internal CreateResponseOptions(IDictionary metadata, float? temperature, int? topLogProbabilityCount, float? topP, string endUserId, string safetyIdentifier, ResponseServiceTier? serviceTier, string previousResponseId, string model, ResponseReasoningOptions reasoningOptions, bool? backgroundModeEnabled, int? maxOutputTokenCount, int? maxToolCallCount, string instructions, ResponseTextOptions textOptions, IList tools, ResponseToolChoice toolChoice, ResponseTruncationMode? truncationMode, IList inputItems, IList includedProperties, bool? parallelToolCallsEnabled, bool? storedOutputEnabled, bool? streamingEnabled, ResponseConversationOptions conversationOptions, in JsonPatch patch)
+ internal CreateResponseOptions(IDictionary metadata, float? temperature, int? topLogProbabilityCount, float? topP, string endUserId, string safetyIdentifier, ResponseServiceTier? serviceTier, string previousResponseId, string model, ResponseReasoningOptions reasoningOptions, bool? backgroundModeEnabled, int? maxOutputTokenCount, int? maxToolCallCount, string instructions, ResponseTextOptions textOptions, IList tools, ResponseToolChoice toolChoice, InternalPrompt prompt, ResponseTruncationMode? truncationMode, IList inputItems, IList includedProperties, bool? parallelToolCallsEnabled, bool? storedOutputEnabled, bool? streamingEnabled, ResponseConversationOptions conversationOptions, in JsonPatch patch)
{
// Plugin customization: ensure initialization of collections
Metadata = metadata ?? new ChangeTrackingDictionary();
@@ -42,6 +42,7 @@ internal CreateResponseOptions(IDictionary metadata, float? temp
TextOptions = textOptions;
Tools = tools ?? new ChangeTrackingList();
ToolChoice = toolChoice;
+ Prompt = prompt;
TruncationMode = truncationMode;
InputItems = inputItems ?? new ChangeTrackingList();
IncludedProperties = includedProperties ?? new ChangeTrackingList();
@@ -76,5 +77,7 @@ internal CreateResponseOptions(IDictionary metadata, float? temp
public string Instructions { get; set; }
public IList Tools { get; }
+
+ internal InternalPrompt Prompt { get; set; }
}
}
diff --git a/src/Generated/Models/Responses/CustomTool.Serialization.cs b/src/Generated/Models/Responses/CustomTool.Serialization.cs
new file mode 100644
index 000000000..f677eeb7e
--- /dev/null
+++ b/src/Generated/Models/Responses/CustomTool.Serialization.cs
@@ -0,0 +1,186 @@
+//
+
+#nullable disable
+
+using System;
+using System.ClientModel.Primitives;
+using System.Text;
+using System.Text.Json;
+using OpenAI;
+
+namespace OpenAI.Responses
+{
+ public partial class CustomTool : ResponseTool, IJsonModel
+ {
+ internal CustomTool() : this(InternalToolType.Custom, default, null, null, null)
+ {
+ }
+
+ void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options)
+ {
+#pragma warning disable SCME0001 // Type is for evaluation purposes only and is subject to change or removal in future updates.
+ if (Patch.Contains("$"u8))
+ {
+ writer.WriteRawValue(Patch.GetJson("$"u8));
+ return;
+ }
+#pragma warning restore SCME0001 // Type is for evaluation purposes only and is subject to change or removal in future updates.
+
+ writer.WriteStartObject();
+ JsonModelWriteCore(writer, options);
+ writer.WriteEndObject();
+ }
+
+ protected override void JsonModelWriteCore(Utf8JsonWriter writer, ModelReaderWriterOptions options)
+ {
+ string format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format;
+ if (format != "J")
+ {
+ throw new FormatException($"The model {nameof(CustomTool)} does not support writing '{format}' format.");
+ }
+ base.JsonModelWriteCore(writer, options);
+#pragma warning disable SCME0001 // Type is for evaluation purposes only and is subject to change or removal in future updates.
+ if (!Patch.Contains("$.name"u8))
+ {
+ writer.WritePropertyName("name"u8);
+ writer.WriteStringValue(Name);
+ }
+ if (Optional.IsDefined(Description) && !Patch.Contains("$.description"u8))
+ {
+ writer.WritePropertyName("description"u8);
+ writer.WriteStringValue(Description);
+ }
+ if (Optional.IsDefined(Format) && !Patch.Contains("$.format"u8))
+ {
+ writer.WritePropertyName("format"u8);
+ writer.WriteObjectValue(Format, options);
+ }
+
+ Patch.WriteTo(writer);
+#pragma warning restore SCME0001 // Type is for evaluation purposes only and is subject to change or removal in future updates.
+ }
+
+ CustomTool IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) => (CustomTool)JsonModelCreateCore(ref reader, options);
+
+ protected override ResponseTool JsonModelCreateCore(ref Utf8JsonReader reader, ModelReaderWriterOptions options)
+ {
+ string format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format;
+ if (format != "J")
+ {
+ throw new FormatException($"The model {nameof(CustomTool)} does not support reading '{format}' format.");
+ }
+ using JsonDocument document = JsonDocument.ParseValue(ref reader);
+ return DeserializeCustomTool(document.RootElement, null, options);
+ }
+
+ internal static CustomTool DeserializeCustomTool(JsonElement element, BinaryData data, ModelReaderWriterOptions options)
+ {
+ if (element.ValueKind == JsonValueKind.Null)
+ {
+ return null;
+ }
+ InternalToolType kind = default;
+#pragma warning disable SCME0001 // Type is for evaluation purposes only and is subject to change or removal in future updates.
+ JsonPatch patch = new JsonPatch(data is null ? ReadOnlyMemory.Empty : data.ToMemory());
+#pragma warning restore SCME0001 // Type is for evaluation purposes only and is subject to change or removal in future updates.
+ string name = default;
+ string description = default;
+ CustomToolFormat format = default;
+ foreach (var prop in element.EnumerateObject())
+ {
+ if (prop.NameEquals("type"u8))
+ {
+ kind = new InternalToolType(prop.Value.GetString());
+ continue;
+ }
+ if (prop.NameEquals("name"u8))
+ {
+ name = prop.Value.GetString();
+ continue;
+ }
+ if (prop.NameEquals("description"u8))
+ {
+ if (prop.Value.ValueKind == JsonValueKind.Null)
+ {
+ description = null;
+ continue;
+ }
+ description = prop.Value.GetString();
+ continue;
+ }
+ if (prop.NameEquals("format"u8))
+ {
+ if (prop.Value.ValueKind == JsonValueKind.Null)
+ {
+ continue;
+ }
+ format = CustomToolFormat.DeserializeCustomToolFormat(prop.Value, prop.Value.GetUtf8Bytes(), options);
+ continue;
+ }
+ patch.Set([.. "$."u8, .. Encoding.UTF8.GetBytes(prop.Name)], prop.Value.GetUtf8Bytes());
+ }
+ return new CustomTool(kind, patch, name, description, format);
+ }
+
+ BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) => PersistableModelWriteCore(options);
+
+ protected override BinaryData PersistableModelWriteCore(ModelReaderWriterOptions options)
+ {
+ string format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format;
+ switch (format)
+ {
+ case "J":
+ return ModelReaderWriter.Write(this, options, OpenAIContext.Default);
+ default:
+ throw new FormatException($"The model {nameof(CustomTool)} does not support writing '{options.Format}' format.");
+ }
+ }
+
+ CustomTool IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) => (CustomTool)PersistableModelCreateCore(data, options);
+
+ protected override ResponseTool PersistableModelCreateCore(BinaryData data, ModelReaderWriterOptions options)
+ {
+ string format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format;
+ switch (format)
+ {
+ case "J":
+ using (JsonDocument document = JsonDocument.Parse(data, ModelSerializationExtensions.JsonDocumentOptions))
+ {
+ return DeserializeCustomTool(document.RootElement, data, options);
+ }
+ default:
+ throw new FormatException($"The model {nameof(CustomTool)} does not support reading '{options.Format}' format.");
+ }
+ }
+
+ string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J";
+
+#pragma warning disable SCME0001 // Type is for evaluation purposes only and is subject to change or removal in future updates.
+ private bool PropagateGet(ReadOnlySpan jsonPath, out JsonPatch.EncodedValue value)
+ {
+ ReadOnlySpan local = jsonPath.SliceToStartOfPropertyName();
+ value = default;
+
+ if (local.StartsWith("format"u8))
+ {
+ return Format.Patch.TryGetEncodedValue([.. "$"u8, .. local.Slice("format"u8.Length)], out value);
+ }
+ return false;
+ }
+#pragma warning restore SCME0001 // Type is for evaluation purposes only and is subject to change or removal in future updates.
+
+#pragma warning disable SCME0001 // Type is for evaluation purposes only and is subject to change or removal in future updates.
+ private bool PropagateSet(ReadOnlySpan jsonPath, JsonPatch.EncodedValue value)
+ {
+ ReadOnlySpan local = jsonPath.SliceToStartOfPropertyName();
+
+ if (local.StartsWith("format"u8))
+ {
+ Format.Patch.Set([.. "$"u8, .. local.Slice("format"u8.Length)], value);
+ return true;
+ }
+ return false;
+ }
+#pragma warning restore SCME0001 // Type is for evaluation purposes only and is subject to change or removal in future updates.
+ }
+}
diff --git a/src/Generated/Models/Responses/CustomTool.cs b/src/Generated/Models/Responses/CustomTool.cs
new file mode 100644
index 000000000..e5d5ad38c
--- /dev/null
+++ b/src/Generated/Models/Responses/CustomTool.cs
@@ -0,0 +1,37 @@
+//
+
+#nullable disable
+
+using System.ClientModel.Primitives;
+using System.Diagnostics.CodeAnalysis;
+using OpenAI;
+
+namespace OpenAI.Responses
+{
+ [Experimental("OPENAI001")]
+ public partial class CustomTool : ResponseTool
+ {
+ public CustomTool(string name) : base(InternalToolType.Custom)
+ {
+ Argument.AssertNotNull(name, nameof(name));
+
+ Name = name;
+ }
+
+#pragma warning disable SCME0001 // Type is for evaluation purposes only and is subject to change or removal in future updates.
+ internal CustomTool(InternalToolType kind, in JsonPatch patch, string name, string description, CustomToolFormat format) : base(kind, patch)
+ {
+ Name = name;
+ Description = description;
+ Format = format;
+ Patch.SetPropagators(PropagateSet, PropagateGet);
+ }
+#pragma warning restore SCME0001 // Type is for evaluation purposes only and is subject to change or removal in future updates.
+
+ public string Name { get; set; }
+
+ public string Description { get; set; }
+
+ public CustomToolFormat Format { get; set; }
+ }
+}
diff --git a/src/Generated/Models/Responses/CustomToolFormat.Serialization.cs b/src/Generated/Models/Responses/CustomToolFormat.Serialization.cs
new file mode 100644
index 000000000..93b0e2a6e
--- /dev/null
+++ b/src/Generated/Models/Responses/CustomToolFormat.Serialization.cs
@@ -0,0 +1,115 @@
+//
+
+#nullable disable
+
+using System;
+using System.ClientModel.Primitives;
+using System.Text.Json;
+using OpenAI;
+
+namespace OpenAI.Responses
+{
+ [PersistableModelProxy(typeof(InternalUnknownCustomToolParamFormat))]
+ public abstract partial class CustomToolFormat : IJsonModel
+ {
+ internal CustomToolFormat()
+ {
+ }
+
+ void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options)
+ {
+#pragma warning disable SCME0001 // Type is for evaluation purposes only and is subject to change or removal in future updates.
+ if (Patch.Contains("$"u8))
+ {
+ writer.WriteRawValue(Patch.GetJson("$"u8));
+ return;
+ }
+#pragma warning restore SCME0001 // Type is for evaluation purposes only and is subject to change or removal in future updates.
+
+ writer.WriteStartObject();
+ JsonModelWriteCore(writer, options);
+ writer.WriteEndObject();
+ }
+
+ protected virtual void JsonModelWriteCore(Utf8JsonWriter writer, ModelReaderWriterOptions options)
+ {
+ string format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format;
+ if (format != "J")
+ {
+ throw new FormatException($"The model {nameof(CustomToolFormat)} does not support writing '{format}' format.");
+ }
+#pragma warning disable SCME0001 // Type is for evaluation purposes only and is subject to change or removal in future updates.
+ if (!Patch.Contains("$.type"u8))
+ {
+ writer.WritePropertyName("type"u8);
+ writer.WriteStringValue(Kind.ToString());
+ }
+#pragma warning restore SCME0001 // Type is for evaluation purposes only and is subject to change or removal in future updates.
+ }
+
+ CustomToolFormat IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) => JsonModelCreateCore(ref reader, options);
+
+ protected virtual CustomToolFormat JsonModelCreateCore(ref Utf8JsonReader reader, ModelReaderWriterOptions options)
+ {
+ string format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format;
+ if (format != "J")
+ {
+ throw new FormatException($"The model {nameof(CustomToolFormat)} does not support reading '{format}' format.");
+ }
+ using JsonDocument document = JsonDocument.ParseValue(ref reader);
+ return DeserializeCustomToolFormat(document.RootElement, null, options);
+ }
+
+ internal static CustomToolFormat DeserializeCustomToolFormat(JsonElement element, BinaryData data, ModelReaderWriterOptions options)
+ {
+ if (element.ValueKind == JsonValueKind.Null)
+ {
+ return null;
+ }
+ if (element.TryGetProperty("type"u8, out JsonElement discriminator))
+ {
+ switch (discriminator.GetString())
+ {
+ case "text":
+ return CustomToolTextFormat.DeserializeCustomToolTextFormat(element, data, options);
+ case "grammar":
+ return CustomToolGrammarFormat.DeserializeCustomToolGrammarFormat(element, data, options);
+ }
+ }
+ return InternalUnknownCustomToolParamFormat.DeserializeInternalUnknownCustomToolParamFormat(element, data, options);
+ }
+
+ BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) => PersistableModelWriteCore(options);
+
+ protected virtual BinaryData PersistableModelWriteCore(ModelReaderWriterOptions options)
+ {
+ string format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format;
+ switch (format)
+ {
+ case "J":
+ return ModelReaderWriter.Write(this, options, OpenAIContext.Default);
+ default:
+ throw new FormatException($"The model {nameof(CustomToolFormat)} does not support writing '{options.Format}' format.");
+ }
+ }
+
+ CustomToolFormat IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) => PersistableModelCreateCore(data, options);
+
+ protected virtual CustomToolFormat PersistableModelCreateCore(BinaryData data, ModelReaderWriterOptions options)
+ {
+ string format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format;
+ switch (format)
+ {
+ case "J":
+ using (JsonDocument document = JsonDocument.Parse(data, ModelSerializationExtensions.JsonDocumentOptions))
+ {
+ return DeserializeCustomToolFormat(document.RootElement, data, options);
+ }
+ default:
+ throw new FormatException($"The model {nameof(CustomToolFormat)} does not support reading '{options.Format}' format.");
+ }
+ }
+
+ string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J";
+ }
+}
diff --git a/src/Generated/Models/Responses/CustomToolFormat.cs b/src/Generated/Models/Responses/CustomToolFormat.cs
new file mode 100644
index 000000000..9c7d63970
--- /dev/null
+++ b/src/Generated/Models/Responses/CustomToolFormat.cs
@@ -0,0 +1,38 @@
+//