Skip to content
Merged
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
31 changes: 31 additions & 0 deletions .changeset/simplify-format-id-schema.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
---
"adcontextprotocol": patch
---

Simplify format-id schema structure for better code generation compatibility.

**Problem**: The previous schema used a complex `oneOf`/`not`/`anyOf` pattern in `allOf` to express that width/height fields are optional but must appear together. This caused code generators to interpret the schema as two separate types (FormatId1, FormatId2) rather than a single type with optional fields, forcing union types everywhere format_id was used.

**Solution**: Replaced the complex validation pattern with a simpler approach:
- Moved width/height fields directly into the format-id schema properties
- Used JSON Schema `dependencies` keyword to enforce that width and height must appear together
- Maintained identical validation semantics while producing cleaner generated types

**Impact**:
- Code generators now produce a single FormatId type with optional width/height fields
- No breaking changes to the wire format or validation behavior
- Improved developer experience with better TypeScript/Python type hints
- Eliminates need for union types when referencing format_id

**Example generated type (TypeScript)**:
```typescript
// Before: FormatId1 | FormatId2
// After:
interface FormatId {
agent_url: string;
id: string;
width?: number; // optional, but must have height if present
height?: number; // optional, but must have width if present
duration_ms?: number;
}
```
33 changes: 14 additions & 19 deletions static/schemas/source/core/format-id.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@
"pattern": "^[a-zA-Z0-9_-]+$",
"description": "Format identifier within the agent's namespace (e.g., 'display_static', 'video_hosted', 'audio_standard'). When used alone, references a template format. When combined with dimension/duration fields, creates a parameterized format ID for a specific variant."
},
"width": {
"type": "integer",
"minimum": 1,
"description": "Width in pixels for visual formats. When specified, height must also be specified. Both fields together create a parameterized format ID for dimension-specific variants."
},
"height": {
"type": "integer",
"minimum": 1,
"description": "Height in pixels for visual formats. When specified, width must also be specified. Both fields together create a parameterized format ID for dimension-specific variants."
},
"duration_ms": {
"type": "number",
"minimum": 1,
Expand All @@ -23,23 +33,8 @@
},
"required": ["agent_url", "id"],
"additionalProperties": false,
"allOf": [
{
"oneOf": [
{
"not": {
"anyOf": [
{"required": ["width"]},
{"required": ["height"]}
]
}
},
{
"allOf": [
{"$ref": "/schemas/core/dimensions.json"}
]
}
]
}
]
"dependencies": {
"width": ["height"],
"height": ["width"]
}
}