Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 126 additions & 0 deletions .github/agents/coordinator.agent.md
Original file line number Diff line number Diff line change
@@ -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/<area>.client.tsp`)
or model overlays (`specification/client/models/<area>.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/<area>/`) is an exact copy of the latest
upstream from `https://github.com/microsoft/openai-openapi-pr/tree/main/packages/openai-typespec/src/<area>/`.
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/<area>.client.tsp
- <augment decorator changes>

### Model Overlay: specification/client/models/<area>.models.tsp
- <new SDK-only types, alternate types, enums>

## Tier 3: Upstream Issues Required
### Issue 1: <title>
- Repo: microsoft/openai-openapi-pr
- File: packages/openai-typespec/src/<area>/<file>.tsp
- Category: 1 | 2 | 3
- Current: `<raw union expression>`
- Proposed: `<desired TypeSpec>`
- Impact: <what breaks in SDK codegen without this fix>

## SDK Customization Notes
- <any notes for custom deserialization or composition wrappers>
```

## 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/)
175 changes: 175 additions & 0 deletions .github/agents/discriminated-union-refactorer.agent.md
Original file line number Diff line number Diff line change
@@ -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/<area>.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 <description of the polymorphic family>.")
model <BaseName> {
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 <ComponentName> extends <BaseName> {
type: "<discriminator-value>";
// Component-specific properties
}
```

If the component model already exists, add `extends <BaseName>` 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)

```
### <union-id>
- File (base spec): <path>
- Category: 1
- Fix Tier: 2
- Original: `<raw union expression>`

#### Client overlay change (specification/client/<area>.client.tsp):
```typespec
@@alternateType(<ParentModel>.<property>, <NewSDKType>);
```

#### Model overlay change (specification/client/models/<area>.models.tsp):
```typespec
@discriminator("type")
model <NewSDKType> { ... }
model <Variant1> extends <NewSDKType> { ... }
model <Variant2> extends <NewSDKType> { ... }
```
```

### Tier 3 Output (Upstream Issue)

```
### <union-id>
- File (base spec): <path in microsoft/openai-openapi-pr>
- Category: 1
- Fix Tier: 3
- Original: `<raw union expression>`
- Why overlay can't fix: <explanation>

#### Proposed upstream issue:
**Title:** [TypeSpec] <Area>: Convert <union> to @discriminator hierarchy
**Repo:** microsoft/openai-openapi-pr
**Body:**
The union `<expression>` in `<file>:<line>` 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
<current code>
```

**Proposed TypeSpec:**
```typespec
@discriminator("type")
model <BaseName> { ... }
model <Component1> extends <BaseName> { ... }
```

**Impact:** <description of codegen 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/<area>.client.tsp` as a style guide.
8. When proposing Tier 3 issues, provide a complete proposed diff for the upstream repo.
Loading