Skip to content

Commit 96a92ea

Browse files
committed
Fix #164 preserve typed request wrappers
1 parent 87f2ed1 commit 96a92ea

File tree

2 files changed

+148
-1
lines changed

2 files changed

+148
-1
lines changed

src/libs/AutoSDK/Models/TypeData.cs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ public static string GetCSharpType(SchemaContext context)
319319
(null, "string") => "string",
320320
("object", _) => "object",
321321

322-
(null, null) when (context.IsClass && context.ClassData?.Properties.Length > 0) || context.IsEnum =>
322+
(null, null) when HasDeclaredClassProperties(context) || context.IsEnum =>
323323
$"global::{context.Settings.Namespace}.{context.Id}",
324324
// Schema with const value should be treated as string
325325
(null, null) when context.Schema.IsConst() => "string",
@@ -363,6 +363,20 @@ public static bool IsCollapsedAnyOfLike(SchemaContext context)
363363
return types.Length == 1;
364364
}
365365

366+
private static bool HasDeclaredClassProperties(SchemaContext context)
367+
{
368+
if (!context.IsClass)
369+
{
370+
return false;
371+
}
372+
373+
var propertyContexts = context.IsDerivedClass
374+
? context.DerivedClassContext.Children
375+
: context.Children;
376+
377+
return propertyContexts.Any(static x => x.IsProperty);
378+
}
379+
366380
public static bool GetCSharpNullability(
367381
SchemaContext context,
368382
SchemaContext? additionalContext = null)

src/tests/AutoSDK.UnitTests/DataTests.cs

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,8 +190,141 @@ public void DiscriminatorOnlyOneOfWrapper_DoesNotExposeHiddenDiscriminatorToConv
190190
requestModel.IsBaseClass.Should().BeTrue();
191191
requestModel.Properties.Should().BeEmpty();
192192
endPoint.Parameters.Where(x => x.Location == null).Should().BeEmpty();
193+
endPoint.RequestType.CSharpTypeWithoutNullability.Should().Be("global::G.CreateItemRequest");
193194
generatedEndPoint.Should().NotContain("Type = type");
194195
generatedEndPoint.Should().NotContain(" string type,");
196+
generatedEndPoint.Should().Contain("global::G.CreateItemRequest request");
197+
generatedEndPoint.Should().NotContain("object request");
198+
}
199+
200+
[TestMethod]
201+
public void SharedBaseDiscriminatorOneOfWrapper_PreservesNamedRequestUnion()
202+
{
203+
var settings = DefaultSettings with
204+
{
205+
GenerateMethods = true,
206+
GenerateModels = true,
207+
GenerateSdk = true,
208+
JsonSerializerType = JsonSerializerType.SystemTextJson,
209+
TargetFramework = "net8.0",
210+
};
211+
const string yaml = """
212+
openapi: 3.0.1
213+
info:
214+
title: repro
215+
version: 1.0.0
216+
paths:
217+
/agent-input:
218+
post:
219+
operationId: createAgentInput
220+
requestBody:
221+
required: true
222+
content:
223+
application/json:
224+
schema:
225+
$ref: '#/components/schemas/CreateInputRequest'
226+
responses:
227+
'200':
228+
description: ok
229+
content:
230+
application/json:
231+
schema:
232+
$ref: '#/components/schemas/AgentResponse'
233+
components:
234+
schemas:
235+
AgentResponse:
236+
type: object
237+
properties:
238+
ok:
239+
type: boolean
240+
AgentInput:
241+
type: object
242+
properties:
243+
text:
244+
type: string
245+
InputBehavior:
246+
type: string
247+
enum:
248+
- append
249+
- replace
250+
CreateInputRequestBase:
251+
type: object
252+
properties:
253+
stream_response:
254+
type: boolean
255+
default: false
256+
CreateInputMessageRequest:
257+
allOf:
258+
- $ref: '#/components/schemas/CreateInputRequestBase'
259+
- required:
260+
- messages
261+
type: object
262+
properties:
263+
type:
264+
type: string
265+
default: input_message
266+
messages:
267+
type: array
268+
items:
269+
$ref: '#/components/schemas/AgentInput'
270+
since:
271+
type: string
272+
behavior:
273+
$ref: '#/components/schemas/InputBehavior'
274+
CreateInterruptRequest:
275+
allOf:
276+
- $ref: '#/components/schemas/CreateInputRequestBase'
277+
- required:
278+
- type
279+
type: object
280+
properties:
281+
type:
282+
type: string
283+
default: interrupt
284+
CreateCompactRequest:
285+
allOf:
286+
- $ref: '#/components/schemas/CreateInputRequestBase'
287+
- required:
288+
- type
289+
type: object
290+
properties:
291+
type:
292+
type: string
293+
default: compact
294+
compact_up_to_event_id:
295+
type: string
296+
compaction_message:
297+
type: string
298+
CreateInputRequest:
299+
required:
300+
- type
301+
oneOf:
302+
- $ref: '#/components/schemas/CreateInputMessageRequest'
303+
- $ref: '#/components/schemas/CreateInterruptRequest'
304+
- $ref: '#/components/schemas/CreateCompactRequest'
305+
description: A request to create input for an agent session.
306+
discriminator:
307+
propertyName: type
308+
mapping:
309+
input_message: '#/components/schemas/CreateInputMessageRequest'
310+
interrupt: '#/components/schemas/CreateInterruptRequest'
311+
compact: '#/components/schemas/CreateCompactRequest'
312+
x-vectara-base-schema: '#/CreateInputRequestBase'
313+
""";
314+
315+
var data = Data.Prepare(((yaml, settings), GlobalSettings: settings));
316+
var anyOf = data.AnyOfs.Single(x => x.Name == "CreateInputRequest");
317+
var endPoint = data.Methods.Should().ContainSingle().Subject;
318+
var generatedAnyOf = Sources.GenerateAnyOf(anyOf);
319+
var generatedEndPoint = Sources.GenerateEndPoint(endPoint);
320+
321+
data.Classes.Should().NotContain(x => x.ClassName == "CreateInputRequest");
322+
anyOf.SubType.Should().Be("OneOf");
323+
anyOf.Properties.Select(x => x.Name).Should().Contain(["InputMessage", "Interrupt", "Compact"]);
324+
generatedAnyOf.Should().Contain("public readonly partial struct CreateInputRequest");
325+
endPoint.RequestType.CSharpTypeWithoutNullability.Should().Be("global::G.CreateInputRequest");
326+
generatedEndPoint.Should().Contain("global::G.CreateInputRequest request");
327+
generatedEndPoint.Should().NotContain("object request");
195328
}
196329

197330
[TestMethod]

0 commit comments

Comments
 (0)