fix(app-server): preserve dynamic tool schema diagnostics

This commit is contained in:
Alex Kotliarskyi
2026-05-21 12:08:29 -07:00
parent 8677b878cc
commit 03190e8fd3
33 changed files with 1832 additions and 62 deletions
@@ -1100,6 +1100,33 @@
],
"type": "string"
},
"DynamicToolSchemaErrorTool": {
"properties": {
"index": {
"format": "uint",
"minimum": 0.0,
"type": "integer"
},
"name": {
"type": "string"
},
"namespace": {
"type": [
"string",
"null"
]
},
"qualifiedName": {
"type": "string"
}
},
"required": [
"index",
"name",
"qualifiedName"
],
"type": "object"
},
"ErrorNotification": {
"properties": {
"error": {
@@ -4831,6 +4858,14 @@
]
},
"data": {
"anyOf": [
{
"$ref": "#/definitions/TurnErrorData"
},
{
"type": "null"
}
],
"default": null
},
"message": {
@@ -4842,6 +4877,59 @@
],
"type": "object"
},
"TurnErrorData": {
"oneOf": [
{
"properties": {
"backend": {
"type": "string"
},
"reason": {
"enum": [
"dynamicToolInputSchema"
],
"type": "string"
},
"remediation": {
"type": "string"
},
"schemaPath": {
"type": [
"string",
"null"
]
},
"tool": {
"anyOf": [
{
"$ref": "#/definitions/DynamicToolSchemaErrorTool"
},
{
"type": "null"
}
]
},
"toolCandidates": {
"items": {
"$ref": "#/definitions/DynamicToolSchemaErrorTool"
},
"type": "array"
},
"underlyingError": {
"type": "string"
}
},
"required": [
"backend",
"reason",
"remediation",
"toolCandidates",
"underlyingError"
],
"type": "object"
}
]
},
"TurnItemsView": {
"oneOf": [
{
@@ -8214,6 +8214,33 @@
],
"type": "string"
},
"DynamicToolSchemaErrorTool": {
"properties": {
"index": {
"format": "uint",
"minimum": 0.0,
"type": "integer"
},
"name": {
"type": "string"
},
"namespace": {
"type": [
"string",
"null"
]
},
"qualifiedName": {
"type": "string"
}
},
"required": [
"index",
"name",
"qualifiedName"
],
"type": "object"
},
"DynamicToolSpec": {
"properties": {
"deferLoading": {
@@ -18260,6 +18287,14 @@
]
},
"data": {
"anyOf": [
{
"$ref": "#/definitions/v2/TurnErrorData"
},
{
"type": "null"
}
],
"default": null
},
"message": {
@@ -18271,6 +18306,59 @@
],
"type": "object"
},
"TurnErrorData": {
"oneOf": [
{
"properties": {
"backend": {
"type": "string"
},
"reason": {
"enum": [
"dynamicToolInputSchema"
],
"type": "string"
},
"remediation": {
"type": "string"
},
"schemaPath": {
"type": [
"string",
"null"
]
},
"tool": {
"anyOf": [
{
"$ref": "#/definitions/v2/DynamicToolSchemaErrorTool"
},
{
"type": "null"
}
]
},
"toolCandidates": {
"items": {
"$ref": "#/definitions/v2/DynamicToolSchemaErrorTool"
},
"type": "array"
},
"underlyingError": {
"type": "string"
}
},
"required": [
"backend",
"reason",
"remediation",
"toolCandidates",
"underlyingError"
],
"type": "object"
}
]
},
"TurnInterruptParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
@@ -4583,6 +4583,33 @@
],
"type": "string"
},
"DynamicToolSchemaErrorTool": {
"properties": {
"index": {
"format": "uint",
"minimum": 0.0,
"type": "integer"
},
"name": {
"type": "string"
},
"namespace": {
"type": [
"string",
"null"
]
},
"qualifiedName": {
"type": "string"
}
},
"required": [
"index",
"name",
"qualifiedName"
],
"type": "object"
},
"DynamicToolSpec": {
"properties": {
"deferLoading": {
@@ -16084,6 +16111,14 @@
]
},
"data": {
"anyOf": [
{
"$ref": "#/definitions/TurnErrorData"
},
{
"type": "null"
}
],
"default": null
},
"message": {
@@ -16095,6 +16130,59 @@
],
"type": "object"
},
"TurnErrorData": {
"oneOf": [
{
"properties": {
"backend": {
"type": "string"
},
"reason": {
"enum": [
"dynamicToolInputSchema"
],
"type": "string"
},
"remediation": {
"type": "string"
},
"schemaPath": {
"type": [
"string",
"null"
]
},
"tool": {
"anyOf": [
{
"$ref": "#/definitions/DynamicToolSchemaErrorTool"
},
{
"type": "null"
}
]
},
"toolCandidates": {
"items": {
"$ref": "#/definitions/DynamicToolSchemaErrorTool"
},
"type": "array"
},
"underlyingError": {
"type": "string"
}
},
"required": [
"backend",
"reason",
"remediation",
"toolCandidates",
"underlyingError"
],
"type": "object"
}
]
},
"TurnInterruptParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
@@ -138,6 +138,33 @@
}
]
},
"DynamicToolSchemaErrorTool": {
"properties": {
"index": {
"format": "uint",
"minimum": 0.0,
"type": "integer"
},
"name": {
"type": "string"
},
"namespace": {
"type": [
"string",
"null"
]
},
"qualifiedName": {
"type": "string"
}
},
"required": [
"index",
"name",
"qualifiedName"
],
"type": "object"
},
"NonSteerableTurnKind": {
"enum": [
"review",
@@ -165,6 +192,14 @@
]
},
"data": {
"anyOf": [
{
"$ref": "#/definitions/TurnErrorData"
},
{
"type": "null"
}
],
"default": null
},
"message": {
@@ -175,6 +210,59 @@
"message"
],
"type": "object"
},
"TurnErrorData": {
"oneOf": [
{
"properties": {
"backend": {
"type": "string"
},
"reason": {
"enum": [
"dynamicToolInputSchema"
],
"type": "string"
},
"remediation": {
"type": "string"
},
"schemaPath": {
"type": [
"string",
"null"
]
},
"tool": {
"anyOf": [
{
"$ref": "#/definitions/DynamicToolSchemaErrorTool"
},
{
"type": "null"
}
]
},
"toolCandidates": {
"items": {
"$ref": "#/definitions/DynamicToolSchemaErrorTool"
},
"type": "array"
},
"underlyingError": {
"type": "string"
}
},
"required": [
"backend",
"reason",
"remediation",
"toolCandidates",
"underlyingError"
],
"type": "object"
}
]
}
},
"properties": {
@@ -388,6 +388,33 @@
],
"type": "string"
},
"DynamicToolSchemaErrorTool": {
"properties": {
"index": {
"format": "uint",
"minimum": 0.0,
"type": "integer"
},
"name": {
"type": "string"
},
"namespace": {
"type": [
"string",
"null"
]
},
"qualifiedName": {
"type": "string"
}
},
"required": [
"index",
"name",
"qualifiedName"
],
"type": "object"
},
"FileUpdateChange": {
"properties": {
"diff": {
@@ -1391,6 +1418,14 @@
]
},
"data": {
"anyOf": [
{
"$ref": "#/definitions/TurnErrorData"
},
{
"type": "null"
}
],
"default": null
},
"message": {
@@ -1402,6 +1437,59 @@
],
"type": "object"
},
"TurnErrorData": {
"oneOf": [
{
"properties": {
"backend": {
"type": "string"
},
"reason": {
"enum": [
"dynamicToolInputSchema"
],
"type": "string"
},
"remediation": {
"type": "string"
},
"schemaPath": {
"type": [
"string",
"null"
]
},
"tool": {
"anyOf": [
{
"$ref": "#/definitions/DynamicToolSchemaErrorTool"
},
{
"type": "null"
}
]
},
"toolCandidates": {
"items": {
"$ref": "#/definitions/DynamicToolSchemaErrorTool"
},
"type": "array"
},
"underlyingError": {
"type": "string"
}
},
"required": [
"backend",
"reason",
"remediation",
"toolCandidates",
"underlyingError"
],
"type": "object"
}
]
},
"TurnItemsView": {
"oneOf": [
{
@@ -470,6 +470,33 @@
],
"type": "string"
},
"DynamicToolSchemaErrorTool": {
"properties": {
"index": {
"format": "uint",
"minimum": 0.0,
"type": "integer"
},
"name": {
"type": "string"
},
"namespace": {
"type": [
"string",
"null"
]
},
"qualifiedName": {
"type": "string"
}
},
"required": [
"index",
"name",
"qualifiedName"
],
"type": "object"
},
"FileUpdateChange": {
"properties": {
"diff": {
@@ -1951,6 +1978,14 @@
]
},
"data": {
"anyOf": [
{
"$ref": "#/definitions/TurnErrorData"
},
{
"type": "null"
}
],
"default": null
},
"message": {
@@ -1962,6 +1997,59 @@
],
"type": "object"
},
"TurnErrorData": {
"oneOf": [
{
"properties": {
"backend": {
"type": "string"
},
"reason": {
"enum": [
"dynamicToolInputSchema"
],
"type": "string"
},
"remediation": {
"type": "string"
},
"schemaPath": {
"type": [
"string",
"null"
]
},
"tool": {
"anyOf": [
{
"$ref": "#/definitions/DynamicToolSchemaErrorTool"
},
{
"type": "null"
}
]
},
"toolCandidates": {
"items": {
"$ref": "#/definitions/DynamicToolSchemaErrorTool"
},
"type": "array"
},
"underlyingError": {
"type": "string"
}
},
"required": [
"backend",
"reason",
"remediation",
"toolCandidates",
"underlyingError"
],
"type": "object"
}
]
},
"TurnItemsView": {
"oneOf": [
{
@@ -391,6 +391,33 @@
],
"type": "string"
},
"DynamicToolSchemaErrorTool": {
"properties": {
"index": {
"format": "uint",
"minimum": 0.0,
"type": "integer"
},
"name": {
"type": "string"
},
"namespace": {
"type": [
"string",
"null"
]
},
"qualifiedName": {
"type": "string"
}
},
"required": [
"index",
"name",
"qualifiedName"
],
"type": "object"
},
"FileUpdateChange": {
"properties": {
"diff": {
@@ -1766,6 +1793,14 @@
]
},
"data": {
"anyOf": [
{
"$ref": "#/definitions/TurnErrorData"
},
{
"type": "null"
}
],
"default": null
},
"message": {
@@ -1777,6 +1812,59 @@
],
"type": "object"
},
"TurnErrorData": {
"oneOf": [
{
"properties": {
"backend": {
"type": "string"
},
"reason": {
"enum": [
"dynamicToolInputSchema"
],
"type": "string"
},
"remediation": {
"type": "string"
},
"schemaPath": {
"type": [
"string",
"null"
]
},
"tool": {
"anyOf": [
{
"$ref": "#/definitions/DynamicToolSchemaErrorTool"
},
{
"type": "null"
}
]
},
"toolCandidates": {
"items": {
"$ref": "#/definitions/DynamicToolSchemaErrorTool"
},
"type": "array"
},
"underlyingError": {
"type": "string"
}
},
"required": [
"backend",
"reason",
"remediation",
"toolCandidates",
"underlyingError"
],
"type": "object"
}
]
},
"TurnItemsView": {
"oneOf": [
{
@@ -391,6 +391,33 @@
],
"type": "string"
},
"DynamicToolSchemaErrorTool": {
"properties": {
"index": {
"format": "uint",
"minimum": 0.0,
"type": "integer"
},
"name": {
"type": "string"
},
"namespace": {
"type": [
"string",
"null"
]
},
"qualifiedName": {
"type": "string"
}
},
"required": [
"index",
"name",
"qualifiedName"
],
"type": "object"
},
"FileUpdateChange": {
"properties": {
"diff": {
@@ -1766,6 +1793,14 @@
]
},
"data": {
"anyOf": [
{
"$ref": "#/definitions/TurnErrorData"
},
{
"type": "null"
}
],
"default": null
},
"message": {
@@ -1777,6 +1812,59 @@
],
"type": "object"
},
"TurnErrorData": {
"oneOf": [
{
"properties": {
"backend": {
"type": "string"
},
"reason": {
"enum": [
"dynamicToolInputSchema"
],
"type": "string"
},
"remediation": {
"type": "string"
},
"schemaPath": {
"type": [
"string",
"null"
]
},
"tool": {
"anyOf": [
{
"$ref": "#/definitions/DynamicToolSchemaErrorTool"
},
{
"type": "null"
}
]
},
"toolCandidates": {
"items": {
"$ref": "#/definitions/DynamicToolSchemaErrorTool"
},
"type": "array"
},
"underlyingError": {
"type": "string"
}
},
"required": [
"backend",
"reason",
"remediation",
"toolCandidates",
"underlyingError"
],
"type": "object"
}
]
},
"TurnItemsView": {
"oneOf": [
{
@@ -391,6 +391,33 @@
],
"type": "string"
},
"DynamicToolSchemaErrorTool": {
"properties": {
"index": {
"format": "uint",
"minimum": 0.0,
"type": "integer"
},
"name": {
"type": "string"
},
"namespace": {
"type": [
"string",
"null"
]
},
"qualifiedName": {
"type": "string"
}
},
"required": [
"index",
"name",
"qualifiedName"
],
"type": "object"
},
"FileUpdateChange": {
"properties": {
"diff": {
@@ -1766,6 +1793,14 @@
]
},
"data": {
"anyOf": [
{
"$ref": "#/definitions/TurnErrorData"
},
{
"type": "null"
}
],
"default": null
},
"message": {
@@ -1777,6 +1812,59 @@
],
"type": "object"
},
"TurnErrorData": {
"oneOf": [
{
"properties": {
"backend": {
"type": "string"
},
"reason": {
"enum": [
"dynamicToolInputSchema"
],
"type": "string"
},
"remediation": {
"type": "string"
},
"schemaPath": {
"type": [
"string",
"null"
]
},
"tool": {
"anyOf": [
{
"$ref": "#/definitions/DynamicToolSchemaErrorTool"
},
{
"type": "null"
}
]
},
"toolCandidates": {
"items": {
"$ref": "#/definitions/DynamicToolSchemaErrorTool"
},
"type": "array"
},
"underlyingError": {
"type": "string"
}
},
"required": [
"backend",
"reason",
"remediation",
"toolCandidates",
"underlyingError"
],
"type": "object"
}
]
},
"TurnItemsView": {
"oneOf": [
{
@@ -470,6 +470,33 @@
],
"type": "string"
},
"DynamicToolSchemaErrorTool": {
"properties": {
"index": {
"format": "uint",
"minimum": 0.0,
"type": "integer"
},
"name": {
"type": "string"
},
"namespace": {
"type": [
"string",
"null"
]
},
"qualifiedName": {
"type": "string"
}
},
"required": [
"index",
"name",
"qualifiedName"
],
"type": "object"
},
"FileUpdateChange": {
"properties": {
"diff": {
@@ -1951,6 +1978,14 @@
]
},
"data": {
"anyOf": [
{
"$ref": "#/definitions/TurnErrorData"
},
{
"type": "null"
}
],
"default": null
},
"message": {
@@ -1962,6 +1997,59 @@
],
"type": "object"
},
"TurnErrorData": {
"oneOf": [
{
"properties": {
"backend": {
"type": "string"
},
"reason": {
"enum": [
"dynamicToolInputSchema"
],
"type": "string"
},
"remediation": {
"type": "string"
},
"schemaPath": {
"type": [
"string",
"null"
]
},
"tool": {
"anyOf": [
{
"$ref": "#/definitions/DynamicToolSchemaErrorTool"
},
{
"type": "null"
}
]
},
"toolCandidates": {
"items": {
"$ref": "#/definitions/DynamicToolSchemaErrorTool"
},
"type": "array"
},
"underlyingError": {
"type": "string"
}
},
"required": [
"backend",
"reason",
"remediation",
"toolCandidates",
"underlyingError"
],
"type": "object"
}
]
},
"TurnItemsView": {
"oneOf": [
{
@@ -391,6 +391,33 @@
],
"type": "string"
},
"DynamicToolSchemaErrorTool": {
"properties": {
"index": {
"format": "uint",
"minimum": 0.0,
"type": "integer"
},
"name": {
"type": "string"
},
"namespace": {
"type": [
"string",
"null"
]
},
"qualifiedName": {
"type": "string"
}
},
"required": [
"index",
"name",
"qualifiedName"
],
"type": "object"
},
"FileUpdateChange": {
"properties": {
"diff": {
@@ -1766,6 +1793,14 @@
]
},
"data": {
"anyOf": [
{
"$ref": "#/definitions/TurnErrorData"
},
{
"type": "null"
}
],
"default": null
},
"message": {
@@ -1777,6 +1812,59 @@
],
"type": "object"
},
"TurnErrorData": {
"oneOf": [
{
"properties": {
"backend": {
"type": "string"
},
"reason": {
"enum": [
"dynamicToolInputSchema"
],
"type": "string"
},
"remediation": {
"type": "string"
},
"schemaPath": {
"type": [
"string",
"null"
]
},
"tool": {
"anyOf": [
{
"$ref": "#/definitions/DynamicToolSchemaErrorTool"
},
{
"type": "null"
}
]
},
"toolCandidates": {
"items": {
"$ref": "#/definitions/DynamicToolSchemaErrorTool"
},
"type": "array"
},
"underlyingError": {
"type": "string"
}
},
"required": [
"backend",
"reason",
"remediation",
"toolCandidates",
"underlyingError"
],
"type": "object"
}
]
},
"TurnItemsView": {
"oneOf": [
{
@@ -470,6 +470,33 @@
],
"type": "string"
},
"DynamicToolSchemaErrorTool": {
"properties": {
"index": {
"format": "uint",
"minimum": 0.0,
"type": "integer"
},
"name": {
"type": "string"
},
"namespace": {
"type": [
"string",
"null"
]
},
"qualifiedName": {
"type": "string"
}
},
"required": [
"index",
"name",
"qualifiedName"
],
"type": "object"
},
"FileUpdateChange": {
"properties": {
"diff": {
@@ -1951,6 +1978,14 @@
]
},
"data": {
"anyOf": [
{
"$ref": "#/definitions/TurnErrorData"
},
{
"type": "null"
}
],
"default": null
},
"message": {
@@ -1962,6 +1997,59 @@
],
"type": "object"
},
"TurnErrorData": {
"oneOf": [
{
"properties": {
"backend": {
"type": "string"
},
"reason": {
"enum": [
"dynamicToolInputSchema"
],
"type": "string"
},
"remediation": {
"type": "string"
},
"schemaPath": {
"type": [
"string",
"null"
]
},
"tool": {
"anyOf": [
{
"$ref": "#/definitions/DynamicToolSchemaErrorTool"
},
{
"type": "null"
}
]
},
"toolCandidates": {
"items": {
"$ref": "#/definitions/DynamicToolSchemaErrorTool"
},
"type": "array"
},
"underlyingError": {
"type": "string"
}
},
"required": [
"backend",
"reason",
"remediation",
"toolCandidates",
"underlyingError"
],
"type": "object"
}
]
},
"TurnItemsView": {
"oneOf": [
{
@@ -391,6 +391,33 @@
],
"type": "string"
},
"DynamicToolSchemaErrorTool": {
"properties": {
"index": {
"format": "uint",
"minimum": 0.0,
"type": "integer"
},
"name": {
"type": "string"
},
"namespace": {
"type": [
"string",
"null"
]
},
"qualifiedName": {
"type": "string"
}
},
"required": [
"index",
"name",
"qualifiedName"
],
"type": "object"
},
"FileUpdateChange": {
"properties": {
"diff": {
@@ -1766,6 +1793,14 @@
]
},
"data": {
"anyOf": [
{
"$ref": "#/definitions/TurnErrorData"
},
{
"type": "null"
}
],
"default": null
},
"message": {
@@ -1777,6 +1812,59 @@
],
"type": "object"
},
"TurnErrorData": {
"oneOf": [
{
"properties": {
"backend": {
"type": "string"
},
"reason": {
"enum": [
"dynamicToolInputSchema"
],
"type": "string"
},
"remediation": {
"type": "string"
},
"schemaPath": {
"type": [
"string",
"null"
]
},
"tool": {
"anyOf": [
{
"$ref": "#/definitions/DynamicToolSchemaErrorTool"
},
{
"type": "null"
}
]
},
"toolCandidates": {
"items": {
"$ref": "#/definitions/DynamicToolSchemaErrorTool"
},
"type": "array"
},
"underlyingError": {
"type": "string"
}
},
"required": [
"backend",
"reason",
"remediation",
"toolCandidates",
"underlyingError"
],
"type": "object"
}
]
},
"TurnItemsView": {
"oneOf": [
{
@@ -391,6 +391,33 @@
],
"type": "string"
},
"DynamicToolSchemaErrorTool": {
"properties": {
"index": {
"format": "uint",
"minimum": 0.0,
"type": "integer"
},
"name": {
"type": "string"
},
"namespace": {
"type": [
"string",
"null"
]
},
"qualifiedName": {
"type": "string"
}
},
"required": [
"index",
"name",
"qualifiedName"
],
"type": "object"
},
"FileUpdateChange": {
"properties": {
"diff": {
@@ -1766,6 +1793,14 @@
]
},
"data": {
"anyOf": [
{
"$ref": "#/definitions/TurnErrorData"
},
{
"type": "null"
}
],
"default": null
},
"message": {
@@ -1777,6 +1812,59 @@
],
"type": "object"
},
"TurnErrorData": {
"oneOf": [
{
"properties": {
"backend": {
"type": "string"
},
"reason": {
"enum": [
"dynamicToolInputSchema"
],
"type": "string"
},
"remediation": {
"type": "string"
},
"schemaPath": {
"type": [
"string",
"null"
]
},
"tool": {
"anyOf": [
{
"$ref": "#/definitions/DynamicToolSchemaErrorTool"
},
{
"type": "null"
}
]
},
"toolCandidates": {
"items": {
"$ref": "#/definitions/DynamicToolSchemaErrorTool"
},
"type": "array"
},
"underlyingError": {
"type": "string"
}
},
"required": [
"backend",
"reason",
"remediation",
"toolCandidates",
"underlyingError"
],
"type": "object"
}
]
},
"TurnItemsView": {
"oneOf": [
{
@@ -388,6 +388,33 @@
],
"type": "string"
},
"DynamicToolSchemaErrorTool": {
"properties": {
"index": {
"format": "uint",
"minimum": 0.0,
"type": "integer"
},
"name": {
"type": "string"
},
"namespace": {
"type": [
"string",
"null"
]
},
"qualifiedName": {
"type": "string"
}
},
"required": [
"index",
"name",
"qualifiedName"
],
"type": "object"
},
"FileUpdateChange": {
"properties": {
"diff": {
@@ -1391,6 +1418,14 @@
]
},
"data": {
"anyOf": [
{
"$ref": "#/definitions/TurnErrorData"
},
{
"type": "null"
}
],
"default": null
},
"message": {
@@ -1402,6 +1437,59 @@
],
"type": "object"
},
"TurnErrorData": {
"oneOf": [
{
"properties": {
"backend": {
"type": "string"
},
"reason": {
"enum": [
"dynamicToolInputSchema"
],
"type": "string"
},
"remediation": {
"type": "string"
},
"schemaPath": {
"type": [
"string",
"null"
]
},
"tool": {
"anyOf": [
{
"$ref": "#/definitions/DynamicToolSchemaErrorTool"
},
{
"type": "null"
}
]
},
"toolCandidates": {
"items": {
"$ref": "#/definitions/DynamicToolSchemaErrorTool"
},
"type": "array"
},
"underlyingError": {
"type": "string"
}
},
"required": [
"backend",
"reason",
"remediation",
"toolCandidates",
"underlyingError"
],
"type": "object"
}
]
},
"TurnItemsView": {
"oneOf": [
{
@@ -388,6 +388,33 @@
],
"type": "string"
},
"DynamicToolSchemaErrorTool": {
"properties": {
"index": {
"format": "uint",
"minimum": 0.0,
"type": "integer"
},
"name": {
"type": "string"
},
"namespace": {
"type": [
"string",
"null"
]
},
"qualifiedName": {
"type": "string"
}
},
"required": [
"index",
"name",
"qualifiedName"
],
"type": "object"
},
"FileUpdateChange": {
"properties": {
"diff": {
@@ -1391,6 +1418,14 @@
]
},
"data": {
"anyOf": [
{
"$ref": "#/definitions/TurnErrorData"
},
{
"type": "null"
}
],
"default": null
},
"message": {
@@ -1402,6 +1437,59 @@
],
"type": "object"
},
"TurnErrorData": {
"oneOf": [
{
"properties": {
"backend": {
"type": "string"
},
"reason": {
"enum": [
"dynamicToolInputSchema"
],
"type": "string"
},
"remediation": {
"type": "string"
},
"schemaPath": {
"type": [
"string",
"null"
]
},
"tool": {
"anyOf": [
{
"$ref": "#/definitions/DynamicToolSchemaErrorTool"
},
{
"type": "null"
}
]
},
"toolCandidates": {
"items": {
"$ref": "#/definitions/DynamicToolSchemaErrorTool"
},
"type": "array"
},
"underlyingError": {
"type": "string"
}
},
"required": [
"backend",
"reason",
"remediation",
"toolCandidates",
"underlyingError"
],
"type": "object"
}
]
},
"TurnItemsView": {
"oneOf": [
{
@@ -388,6 +388,33 @@
],
"type": "string"
},
"DynamicToolSchemaErrorTool": {
"properties": {
"index": {
"format": "uint",
"minimum": 0.0,
"type": "integer"
},
"name": {
"type": "string"
},
"namespace": {
"type": [
"string",
"null"
]
},
"qualifiedName": {
"type": "string"
}
},
"required": [
"index",
"name",
"qualifiedName"
],
"type": "object"
},
"FileUpdateChange": {
"properties": {
"diff": {
@@ -1391,6 +1418,14 @@
]
},
"data": {
"anyOf": [
{
"$ref": "#/definitions/TurnErrorData"
},
{
"type": "null"
}
],
"default": null
},
"message": {
@@ -1402,6 +1437,59 @@
],
"type": "object"
},
"TurnErrorData": {
"oneOf": [
{
"properties": {
"backend": {
"type": "string"
},
"reason": {
"enum": [
"dynamicToolInputSchema"
],
"type": "string"
},
"remediation": {
"type": "string"
},
"schemaPath": {
"type": [
"string",
"null"
]
},
"tool": {
"anyOf": [
{
"$ref": "#/definitions/DynamicToolSchemaErrorTool"
},
{
"type": "null"
}
]
},
"toolCandidates": {
"items": {
"$ref": "#/definitions/DynamicToolSchemaErrorTool"
},
"type": "array"
},
"underlyingError": {
"type": "string"
}
},
"required": [
"backend",
"reason",
"remediation",
"toolCandidates",
"underlyingError"
],
"type": "object"
}
]
},
"TurnItemsView": {
"oneOf": [
{
@@ -0,0 +1,5 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type DynamicToolSchemaErrorTool = { index: number, namespace: string | null, name: string, qualifiedName: string, };
@@ -1,7 +1,7 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { JsonValue } from "../serde_json/JsonValue";
import type { CodexErrorInfo } from "./CodexErrorInfo";
import type { TurnErrorData } from "./TurnErrorData";
export type TurnError = { message: string, codexErrorInfo: CodexErrorInfo | null, additionalDetails: string | null, data: JsonValue | null, };
export type TurnError = { message: string, codexErrorInfo: CodexErrorInfo | null, additionalDetails: string | null, data: TurnErrorData | null, };
@@ -0,0 +1,6 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { DynamicToolSchemaErrorTool } from "./DynamicToolSchemaErrorTool";
export type TurnErrorData = { "reason": "dynamicToolInputSchema", backend: string, tool: DynamicToolSchemaErrorTool | null, toolCandidates: Array<DynamicToolSchemaErrorTool>, schemaPath: string | null, underlyingError: string, remediation: string, };
@@ -85,6 +85,7 @@ export type { DynamicToolCallOutputContentItem } from "./DynamicToolCallOutputCo
export type { DynamicToolCallParams } from "./DynamicToolCallParams";
export type { DynamicToolCallResponse } from "./DynamicToolCallResponse";
export type { DynamicToolCallStatus } from "./DynamicToolCallStatus";
export type { DynamicToolSchemaErrorTool } from "./DynamicToolSchemaErrorTool";
export type { DynamicToolSpec } from "./DynamicToolSpec";
export type { ErrorNotification } from "./ErrorNotification";
export type { ExecPolicyAmendment } from "./ExecPolicyAmendment";
@@ -436,6 +437,7 @@ export type { TurnCompletedNotification } from "./TurnCompletedNotification";
export type { TurnDiffUpdatedNotification } from "./TurnDiffUpdatedNotification";
export type { TurnEnvironmentParams } from "./TurnEnvironmentParams";
export type { TurnError } from "./TurnError";
export type { TurnErrorData } from "./TurnErrorData";
export type { TurnInterruptParams } from "./TurnInterruptParams";
export type { TurnInterruptResponse } from "./TurnInterruptResponse";
export type { TurnItemsView } from "./TurnItemsView";
@@ -3181,19 +3181,19 @@ mod tests {
message: error_message.to_string(),
codex_error_info: Some(crate::protocol::v2::CodexErrorInfo::BadRequest),
additional_details: None,
data: Some(serde_json::json!({
"reason": "dynamicToolInputSchema",
"backend": "Responses API",
"tool": {
"index": 0,
"namespace": "repro",
"name": "create",
"qualifiedName": "repro.create"
},
"schemaPath": "dynamicTools[0].inputSchema.anyOf",
"underlyingError": error_message,
"remediation": "Adjust the dynamic tool inputSchema to the JSON Schema subset accepted by the model backend. For discriminated unions, wrap the union in a top-level object property or flatten it into one object schema."
})),
data: Some(crate::protocol::v2::TurnErrorData::DynamicToolInputSchema {
backend: "Responses API".to_string(),
tool: Some(crate::protocol::v2::DynamicToolSchemaErrorTool {
index: 0,
namespace: Some("repro".to_string()),
name: "create".to_string(),
qualified_name: "repro.create".to_string(),
}),
tool_candidates: Vec::new(),
schema_path: Some("dynamicTools[0].inputSchema.anyOf".to_string()),
underlying_error: error_message.to_string(),
remediation: "Adjust the dynamic tool inputSchema to the JSON Schema subset accepted by the model backend. For discriminated unions, wrap the union in a top-level object property or flatten it into one object schema.".to_string(),
}),
}),
started_at: None,
completed_at: None,
@@ -12,7 +12,6 @@ use schemars::JsonSchema;
use serde::Deserialize;
use serde::Serialize;
use serde_json::Value as JsonValue;
use serde_json::json;
use std::path::PathBuf;
use thiserror::Error;
use ts_rs::TS;
@@ -198,7 +197,34 @@ pub struct TurnError {
#[serde(default)]
pub additional_details: Option<String>,
#[serde(default)]
pub data: Option<JsonValue>,
pub data: Option<TurnErrorData>,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
#[serde(tag = "reason", rename_all = "camelCase")]
#[ts(tag = "reason")]
#[ts(export_to = "v2/")]
pub enum TurnErrorData {
#[serde(rename = "dynamicToolInputSchema", rename_all = "camelCase")]
#[ts(rename = "dynamicToolInputSchema", rename_all = "camelCase")]
DynamicToolInputSchema {
backend: String,
tool: Option<DynamicToolSchemaErrorTool>,
tool_candidates: Vec<DynamicToolSchemaErrorTool>,
schema_path: Option<String>,
underlying_error: String,
remediation: String,
},
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct DynamicToolSchemaErrorTool {
pub index: usize,
pub namespace: Option<String>,
pub name: String,
pub qualified_name: String,
}
impl TurnError {
@@ -221,39 +247,46 @@ impl TurnError {
fn dynamic_tool_input_schema_error_data(
message: &str,
dynamic_tools: &[CoreDynamicToolSpec],
) -> Option<JsonValue> {
) -> Option<TurnErrorData> {
let underlying_error = underlying_backend_error_message(message);
let backend_function_name = backend_function_name_from_schema_error(&underlying_error)?;
let matching_tools = dynamic_tools
.iter()
.enumerate()
.filter(|(_, tool)| {
backend_function_name == tool.name
|| backend_function_name == qualified_dynamic_tool_name(tool)
})
.filter(|(_, tool)| dynamic_tool_matches_backend_name(tool, backend_function_name))
.collect::<Vec<_>>();
let [(index, tool)] = matching_tools.as_slice() else {
if matching_tools.is_empty() {
return None;
}
let (tool, tool_candidates, schema_path) = match matching_tools.as_slice() {
[(index, tool)] => (
Some(dynamic_tool_error_tool(*index, tool)),
Vec::new(),
Some(dynamic_tool_schema_path(*index, &tool.input_schema)),
),
_ => (
None,
matching_tools
.iter()
.map(|(index, tool)| dynamic_tool_error_tool(*index, tool))
.collect(),
None,
),
};
let qualified_name = qualified_dynamic_tool_name(tool);
let schema_path = dynamic_tool_schema_path(*index, &tool.input_schema);
Some(json!({
"reason": "dynamicToolInputSchema",
"backend": "Responses API",
"tool": {
"index": index,
"namespace": tool.namespace,
"name": tool.name,
"qualifiedName": qualified_name,
},
"schemaPath": schema_path,
"underlyingError": underlying_error,
"remediation": "Adjust the dynamic tool inputSchema to the JSON Schema subset accepted by the model backend. For discriminated unions, wrap the union in a top-level object property or flatten it into one object schema.",
}))
Some(TurnErrorData::DynamicToolInputSchema {
backend: "Responses API".to_string(),
tool,
tool_candidates,
schema_path,
underlying_error,
remediation: DYNAMIC_TOOL_INPUT_SCHEMA_REMEDIATION.to_string(),
})
}
const DYNAMIC_TOOL_INPUT_SCHEMA_REMEDIATION: &str = "Adjust the dynamic tool inputSchema to the JSON Schema subset accepted by the model backend. For discriminated unions, wrap the union in a top-level object property or flatten it into one object schema.";
fn underlying_backend_error_message(message: &str) -> String {
let Ok(value) = serde_json::from_str::<JsonValue>(message) else {
return message.to_string();
@@ -305,9 +338,170 @@ fn dynamic_tool_schema_path(index: usize, input_schema: &JsonValue) -> String {
format!("dynamicTools[{index}].inputSchema{suffix}")
}
fn dynamic_tool_matches_backend_name(
tool: &CoreDynamicToolSpec,
backend_function_name: &str,
) -> bool {
backend_function_name == tool.name || backend_function_name == qualified_dynamic_tool_name(tool)
}
fn dynamic_tool_error_tool(index: usize, tool: &CoreDynamicToolSpec) -> DynamicToolSchemaErrorTool {
DynamicToolSchemaErrorTool {
index,
namespace: tool.namespace.clone(),
name: tool.name.clone(),
qualified_name: qualified_dynamic_tool_name(tool),
}
}
fn qualified_dynamic_tool_name(tool: &CoreDynamicToolSpec) -> String {
match tool.namespace.as_deref() {
Some(namespace) if !namespace.is_empty() => format!("{namespace}.{}", tool.name),
Some(_) | None => tool.name.clone(),
}
}
#[cfg(test)]
mod tests {
use super::DynamicToolSchemaErrorTool;
use super::TurnError;
use super::TurnErrorData;
use codex_protocol::dynamic_tools::DynamicToolSpec;
use codex_protocol::protocol::CodexErrorInfo;
use codex_protocol::protocol::ErrorEvent;
use pretty_assertions::assert_eq;
use serde_json::json;
#[test]
fn dynamic_tool_schema_error_extracts_json_backend_message() {
let backend_error = "invalid_function_parameters ... Invalid schema for function 'create': schema must be a JSON Schema of 'type: \"object\"', got 'type: \"None\"";
let error = TurnError::from_core_error_event(
&ErrorEvent {
message: json!({
"error": {
"message": backend_error,
"type": "invalid_request_error",
"code": "invalid_function_parameters"
}
})
.to_string(),
codex_error_info: Some(CodexErrorInfo::BadRequest),
},
Some(&[dynamic_tool(Some("repro"), "create", json!({"anyOf": []}))]),
);
assert_eq!(
error.data,
Some(TurnErrorData::DynamicToolInputSchema {
backend: "Responses API".to_string(),
tool: Some(DynamicToolSchemaErrorTool {
index: 0,
namespace: Some("repro".to_string()),
name: "create".to_string(),
qualified_name: "repro.create".to_string(),
}),
tool_candidates: Vec::new(),
schema_path: Some("dynamicTools[0].inputSchema.anyOf".to_string()),
underlying_error: backend_error.to_string(),
remediation: super::DYNAMIC_TOOL_INPUT_SCHEMA_REMEDIATION.to_string(),
})
);
}
#[test]
fn dynamic_tool_schema_error_matches_namespaced_backend_name() {
let error = TurnError::from_core_error_event(
&ErrorEvent {
message: "Invalid schema for function 'repro.create'".to_string(),
codex_error_info: Some(CodexErrorInfo::BadRequest),
},
Some(&[
dynamic_tool(Some("other"), "create", json!({"anyOf": []})),
dynamic_tool(Some("repro"), "create", json!({"oneOf": []})),
]),
);
assert_eq!(
error.data,
Some(TurnErrorData::DynamicToolInputSchema {
backend: "Responses API".to_string(),
tool: Some(DynamicToolSchemaErrorTool {
index: 1,
namespace: Some("repro".to_string()),
name: "create".to_string(),
qualified_name: "repro.create".to_string(),
}),
tool_candidates: Vec::new(),
schema_path: Some("dynamicTools[1].inputSchema.oneOf".to_string()),
underlying_error: "Invalid schema for function 'repro.create'".to_string(),
remediation: super::DYNAMIC_TOOL_INPUT_SCHEMA_REMEDIATION.to_string(),
})
);
}
#[test]
fn dynamic_tool_schema_error_reports_ambiguous_bare_name_candidates() {
let error = TurnError::from_core_error_event(
&ErrorEvent {
message: "Invalid schema for function 'create'".to_string(),
codex_error_info: Some(CodexErrorInfo::BadRequest),
},
Some(&[
dynamic_tool(Some("alpha"), "create", json!({"anyOf": []})),
dynamic_tool(Some("beta"), "create", json!({"oneOf": []})),
]),
);
assert_eq!(
error.data,
Some(TurnErrorData::DynamicToolInputSchema {
backend: "Responses API".to_string(),
tool: None,
tool_candidates: vec![
DynamicToolSchemaErrorTool {
index: 0,
namespace: Some("alpha".to_string()),
name: "create".to_string(),
qualified_name: "alpha.create".to_string(),
},
DynamicToolSchemaErrorTool {
index: 1,
namespace: Some("beta".to_string()),
name: "create".to_string(),
qualified_name: "beta.create".to_string(),
},
],
schema_path: None,
underlying_error: "Invalid schema for function 'create'".to_string(),
remediation: super::DYNAMIC_TOOL_INPUT_SCHEMA_REMEDIATION.to_string(),
})
);
}
#[test]
fn dynamic_tool_schema_error_ignores_unknown_function_name() {
let error = TurnError::from_core_error_event(
&ErrorEvent {
message: "Invalid schema for function 'shell'".to_string(),
codex_error_info: Some(CodexErrorInfo::BadRequest),
},
Some(&[dynamic_tool(Some("repro"), "create", json!({"anyOf": []}))]),
);
assert_eq!(error.data, None);
}
fn dynamic_tool(
namespace: Option<&str>,
name: &str,
input_schema: serde_json::Value,
) -> DynamicToolSpec {
DynamicToolSpec {
namespace: namespace.map(str::to_string),
name: name.to_string(),
description: "test".to_string(),
input_schema,
defer_loading: false,
}
}
}
+1 -1
View File
@@ -1410,7 +1410,7 @@ Dynamic tool identifiers follow the same constraints as Responses function tools
Each dynamic tool may set `deferLoading`. When omitted, it defaults to `false`. Set it to `true` to keep the tool registered and callable by runtime features such as `code_mode`, while excluding it from the model-facing tool list sent on ordinary turns. When `tool_search` is available, deferred dynamic tools are searchable and can be exposed by a matching search result.
If the model backend rejects a dynamic tool schema during turn startup, app-server emits the normal `error` notification and stores the failure on the turn returned by `thread/read`. When the backend error names a dynamic tool, `TurnError.data.reason` is `dynamicToolInputSchema` and includes the tool namespace/name, `schemaPath`, backend, underlying backend message, and remediation text.
If the model backend rejects a dynamic tool schema during turn startup, app-server emits the normal `error` notification and stores the failure on the turn returned by `thread/read` and `thread/turns/list`. When the backend error names a dynamic tool, `TurnError.data.reason` is `dynamicToolInputSchema` and includes the tool namespace/name, `schemaPath`, backend, underlying backend message, and remediation text. If the backend reports an ambiguous bare function name, `tool` and `schemaPath` are `null` and `toolCandidates` lists the matching dynamic tools.
When a dynamic tool is invoked during a turn, the server sends an `item/tool/call` JSON-RPC request to the client:
@@ -2131,11 +2131,15 @@ impl ThreadRequestProcessor {
};
let active_turn = if loaded_thread.is_some() {
// Persisted history may not yet include the currently running turn. The
// app-server listener has already projected live turn events into ThreadState,
// so merge that in-memory snapshot before paginating.
// app-server listener has already projected live turn events into
// ThreadState, so merge that in-memory snapshot before paginating. A
// failed turn may also complete before its error event is persisted, so
// bridge the latest terminal failed snapshot too.
let thread_state = self.thread_state_manager.thread_state(thread_uuid).await;
let state = thread_state.lock().await;
state.active_turn_snapshot()
state
.active_turn_snapshot()
.or_else(|| state.last_terminal_turn_snapshot())
} else {
None
};
+55 -6
View File
@@ -136,7 +136,12 @@ impl ThreadState {
}
pub(crate) fn active_turn_snapshot(&self) -> Option<Turn> {
self.current_turn_history.active_turn_snapshot()
self.current_turn_history
.active_turn_snapshot()
.map(|mut turn| {
Self::overlay_last_error(&mut turn, self.turn_summary.last_error.clone());
turn
})
}
pub(crate) fn last_terminal_turn_snapshot(&self) -> Option<Turn> {
@@ -146,6 +151,7 @@ impl ThreadState {
pub(crate) fn track_current_turn_event(&mut self, event_turn_id: &str, event: &EventMsg) {
if let EventMsg::TurnStarted(payload) = event {
self.turn_summary.started_at = payload.started_at;
self.turn_summary.last_error = None;
self.last_terminal_turn_id = None;
self.last_terminal_turn = None;
}
@@ -155,11 +161,8 @@ impl ThreadState {
{
self.last_terminal_turn_id = Some(event_turn_id.to_string());
let mut terminal_turn = self.current_turn_history.active_turn_snapshot();
if let Some(turn) = terminal_turn.as_mut()
&& let Some(error) = self.turn_summary.last_error.clone()
{
turn.status = TurnStatus::Failed;
turn.error = Some(error);
if let Some(turn) = terminal_turn.as_mut() {
Self::overlay_last_error(turn, self.turn_summary.last_error.clone());
}
self.last_terminal_turn = terminal_turn
.filter(|turn| turn.error.is_some() || matches!(turn.status, TurnStatus::Failed));
@@ -167,6 +170,13 @@ impl ThreadState {
}
}
fn overlay_last_error(turn: &mut Turn, error: Option<TurnError>) {
if let Some(error) = error {
turn.status = TurnStatus::Failed;
turn.error = Some(error);
}
}
pub(crate) fn note_thread_settings(&mut self, thread_settings: ThreadSettings) -> bool {
let changed = self.last_thread_settings.as_ref() != Some(&thread_settings);
self.last_thread_settings = Some(thread_settings);
@@ -211,12 +221,51 @@ mod tests {
use super::*;
use codex_app_server_protocol::ApprovalsReviewer;
use codex_app_server_protocol::AskForApproval;
use codex_app_server_protocol::CodexErrorInfo;
use codex_app_server_protocol::SandboxPolicy;
use codex_app_server_protocol::TurnStatus;
use codex_protocol::config_types::CollaborationMode;
use codex_protocol::config_types::ModeKind;
use codex_protocol::config_types::Settings;
use codex_protocol::protocol::CodexErrorInfo as CoreCodexErrorInfo;
use codex_protocol::protocol::ErrorEvent;
use codex_protocol::protocol::TurnStartedEvent;
use pretty_assertions::assert_eq;
#[test]
fn active_turn_snapshot_overlays_enriched_last_error() {
let mut state = ThreadState::default();
state.track_current_turn_event(
"turn-1",
&EventMsg::TurnStarted(TurnStartedEvent {
turn_id: "turn-1".to_string(),
started_at: None,
model_context_window: None,
collaboration_mode_kind: Default::default(),
}),
);
state.track_current_turn_event(
"turn-1",
&EventMsg::Error(ErrorEvent {
message: "raw error".to_string(),
codex_error_info: Some(CoreCodexErrorInfo::BadRequest),
}),
);
state.turn_summary.last_error = Some(TurnError {
message: "enriched error".to_string(),
codex_error_info: Some(CodexErrorInfo::BadRequest),
additional_details: None,
data: None,
});
let turn = state
.active_turn_snapshot()
.expect("active turn snapshot should exist");
assert_eq!(turn.status, TurnStatus::Failed);
assert_eq!(turn.error, state.turn_summary.last_error);
}
#[test]
fn note_thread_settings_reports_only_effective_changes() {
let mut state = ThreadState::default();
@@ -8,6 +8,7 @@ use codex_app_server_protocol::DynamicToolCallOutputContentItem;
use codex_app_server_protocol::DynamicToolCallParams;
use codex_app_server_protocol::DynamicToolCallResponse;
use codex_app_server_protocol::DynamicToolCallStatus;
use codex_app_server_protocol::DynamicToolSchemaErrorTool;
use codex_app_server_protocol::DynamicToolSpec;
use codex_app_server_protocol::ErrorNotification;
use codex_app_server_protocol::ItemCompletedNotification;
@@ -21,6 +22,7 @@ use codex_app_server_protocol::ThreadReadParams;
use codex_app_server_protocol::ThreadReadResponse;
use codex_app_server_protocol::ThreadStartParams;
use codex_app_server_protocol::ThreadStartResponse;
use codex_app_server_protocol::TurnErrorData;
use codex_app_server_protocol::TurnStartParams;
use codex_app_server_protocol::TurnStartResponse;
use codex_app_server_protocol::TurnStatus;
@@ -418,20 +420,20 @@ async fn backend_dynamic_tool_schema_error_is_reported_to_clients() -> Result<()
Ok(())
}
fn expected_dynamic_tool_schema_error_data(underlying_error: &str) -> Value {
json!({
"reason": "dynamicToolInputSchema",
"backend": "Responses API",
"tool": {
"index": 0,
"namespace": "repro",
"name": "create",
"qualifiedName": "repro.create"
},
"schemaPath": "dynamicTools[0].inputSchema.anyOf",
"underlyingError": underlying_error,
"remediation": "Adjust the dynamic tool inputSchema to the JSON Schema subset accepted by the model backend. For discriminated unions, wrap the union in a top-level object property or flatten it into one object schema."
})
fn expected_dynamic_tool_schema_error_data(underlying_error: &str) -> TurnErrorData {
TurnErrorData::DynamicToolInputSchema {
backend: "Responses API".to_string(),
tool: Some(DynamicToolSchemaErrorTool {
index: 0,
namespace: Some("repro".to_string()),
name: "create".to_string(),
qualified_name: "repro.create".to_string(),
}),
tool_candidates: Vec::new(),
schema_path: Some("dynamicTools[0].inputSchema.anyOf".to_string()),
underlying_error: underlying_error.to_string(),
remediation: "Adjust the dynamic tool inputSchema to the JSON Schema subset accepted by the model backend. For discriminated unions, wrap the union in a top-level object property or flatten it into one object schema.".to_string(),
}
}
/// Exercises the full dynamic tool call path (server request, client response, model output).
@@ -40,6 +40,7 @@ fn failed_turn_does_not_overwrite_output_last_message_file() {
message: "turn failed".to_string(),
additional_details: None,
codex_error_info: None,
data: None,
}),
started_at: None,
completed_at: Some(0),
@@ -1530,6 +1530,7 @@ fn failed_turn_clears_stale_final_message() {
message: "turn failed".to_string(),
additional_details: None,
codex_error_info: None,
data: None,
}),
started_at: None,
completed_at: None,
@@ -1586,6 +1587,7 @@ fn turn_failure_prefers_structured_error_message() {
message: "backend failed".to_string(),
codex_error_info: None,
additional_details: Some("request id abc".to_string()),
data: None,
},
will_retry: false,
thread_id: "thread-1".to_string(),
+1
View File
@@ -4557,6 +4557,7 @@ fn active_turn_not_steerable_turn_error_extracts_structured_server_error() {
turn_kind: AppServerNonSteerableTurnKind::Review,
}),
additional_details: None,
data: None,
};
let error = TypedRequestError::Server {
method: "turn/steer".to_string(),
@@ -751,6 +751,7 @@ async fn live_app_server_failed_turn_does_not_duplicate_error_history() {
message: "permission denied".to_string(),
codex_error_info: None,
additional_details: None,
data: None,
},
will_retry: false,
thread_id: "thread-1".to_string(),
@@ -775,6 +776,7 @@ async fn live_app_server_failed_turn_does_not_duplicate_error_history() {
message: "permission denied".to_string(),
codex_error_info: None,
additional_details: None,
data: None,
}),
started_at: None,
completed_at: Some(0),
@@ -850,6 +852,7 @@ async fn live_app_server_stream_recovery_restores_previous_status_header() {
message: "Reconnecting... 1/5".to_string(),
codex_error_info: Some(CodexErrorInfo::Other),
additional_details: None,
data: None,
},
will_retry: true,
thread_id: "thread-1".to_string(),
@@ -908,6 +911,7 @@ async fn live_app_server_server_overloaded_error_renders_warning() {
message: "server overloaded".to_string(),
codex_error_info: Some(CodexErrorInfo::ServerOverloaded),
additional_details: None,
data: None,
},
will_retry: false,
thread_id: "thread-1".to_string(),
@@ -950,6 +954,7 @@ async fn live_app_server_cyber_policy_error_renders_dedicated_notice() {
message: "server fallback message".to_string(),
codex_error_info: Some(CodexErrorInfo::CyberPolicy),
additional_details: None,
data: None,
},
will_retry: false,
thread_id: "thread-1".to_string(),
@@ -413,6 +413,7 @@ pub(super) fn handle_error(
message: message.into(),
codex_error_info,
additional_details: None,
data: None,
},
will_retry: false,
thread_id: thread_id(chat),
@@ -446,6 +447,7 @@ pub(super) fn handle_stream_error_with_replay(
message: message.into(),
codex_error_info: None,
additional_details,
data: None,
},
will_retry: true,
thread_id: thread_id(chat),
@@ -719,6 +719,7 @@ async fn replayed_retryable_app_server_error_keeps_turn_running() {
message: "Reconnecting... 1/5".to_string(),
codex_error_info: None,
additional_details: Some("Idle timeout waiting for SSE".to_string()),
data: None,
},
will_retry: true,
thread_id: "thread-1".to_string(),