Skip to content

Commit 6171867

Browse files
feat: Add executionModel serialization to api client
1 parent 5f7a786 commit 6171867

7 files changed

Lines changed: 459 additions & 40 deletions

File tree

.github/workflows/publish-nuget.yml

Lines changed: 0 additions & 33 deletions
This file was deleted.

.stats.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
configured_endpoints: 8
2-
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-43e6dd4ce19381de488d296e9036fea15bfea9a6f946cf8ccf4e02aecc8fb765.yml
3-
openapi_spec_hash: f736e7a8acea0d73e1031c86ea803246
4-
config_hash: b375728ccf7d33287335852f4f59c293
2+
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-8fbb3fa8f3a37c1c7408de427fe125aadec49f705e8e30d191601a9b69c4cc41.yml
3+
openapi_spec_hash: 48b4dfac35a842d7fb0d228caf87544e
4+
config_hash: 242651c4871c2869ba3c2e3d337505b9

README.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,9 @@ Most existing browser automation tools either require you to write low-level cod
6767

6868
## Installation
6969

70-
Install the package from [NuGet](https://www.nuget.org/packages/Stagehand):
71-
7270
```bash
73-
dotnet add package Stagehand
71+
git clone git@github.com:browserbase/stagehand-net.git
72+
dotnet add reference stagehand-net/src/Stagehand
7473
```
7574

7675
## Requirements

src/Stagehand.Tests/Models/Sessions/SessionExecuteParamsTest.cs

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@ public void FieldRoundtrip_Works()
1818
AgentConfig = new()
1919
{
2020
Cua = true,
21+
ExecutionModel = new ModelConfig()
22+
{
23+
ModelName = "openai/gpt-5-nano",
24+
ApiKey = "sk-some-openai-api-key",
25+
BaseUrl = "https://api.openai.com/v1",
26+
Provider = ModelConfigProvider.OpenAI,
27+
},
2128
Mode = Mode.Cua,
2229
Model = new ModelConfig()
2330
{
@@ -45,6 +52,13 @@ public void FieldRoundtrip_Works()
4552
AgentConfig expectedAgentConfig = new()
4653
{
4754
Cua = true,
55+
ExecutionModel = new ModelConfig()
56+
{
57+
ModelName = "openai/gpt-5-nano",
58+
ApiKey = "sk-some-openai-api-key",
59+
BaseUrl = "https://api.openai.com/v1",
60+
Provider = ModelConfigProvider.OpenAI,
61+
},
4862
Mode = Mode.Cua,
4963
Model = new ModelConfig()
5064
{
@@ -85,6 +99,13 @@ public void OptionalNonNullableParamsUnsetAreNotSet_Works()
8599
AgentConfig = new()
86100
{
87101
Cua = true,
102+
ExecutionModel = new ModelConfig()
103+
{
104+
ModelName = "openai/gpt-5-nano",
105+
ApiKey = "sk-some-openai-api-key",
106+
BaseUrl = "https://api.openai.com/v1",
107+
Provider = ModelConfigProvider.OpenAI,
108+
},
88109
Mode = Mode.Cua,
89110
Model = new ModelConfig()
90111
{
@@ -121,6 +142,13 @@ public void OptionalNonNullableParamsSetToNullAreNotSet_Works()
121142
AgentConfig = new()
122143
{
123144
Cua = true,
145+
ExecutionModel = new ModelConfig()
146+
{
147+
ModelName = "openai/gpt-5-nano",
148+
ApiKey = "sk-some-openai-api-key",
149+
BaseUrl = "https://api.openai.com/v1",
150+
Provider = ModelConfigProvider.OpenAI,
151+
},
124152
Mode = Mode.Cua,
125153
Model = new ModelConfig()
126154
{
@@ -161,6 +189,13 @@ public void OptionalNullableParamsUnsetAreNotSet_Works()
161189
AgentConfig = new()
162190
{
163191
Cua = true,
192+
ExecutionModel = new ModelConfig()
193+
{
194+
ModelName = "openai/gpt-5-nano",
195+
ApiKey = "sk-some-openai-api-key",
196+
BaseUrl = "https://api.openai.com/v1",
197+
Provider = ModelConfigProvider.OpenAI,
198+
},
164199
Mode = Mode.Cua,
165200
Model = new ModelConfig()
166201
{
@@ -196,6 +231,13 @@ public void OptionalNullableParamsSetToNullAreSetToNull_Works()
196231
AgentConfig = new()
197232
{
198233
Cua = true,
234+
ExecutionModel = new ModelConfig()
235+
{
236+
ModelName = "openai/gpt-5-nano",
237+
ApiKey = "sk-some-openai-api-key",
238+
BaseUrl = "https://api.openai.com/v1",
239+
Provider = ModelConfigProvider.OpenAI,
240+
},
199241
Mode = Mode.Cua,
200242
Model = new ModelConfig()
201243
{
@@ -233,6 +275,13 @@ public void Url_Works()
233275
AgentConfig = new()
234276
{
235277
Cua = true,
278+
ExecutionModel = new ModelConfig()
279+
{
280+
ModelName = "openai/gpt-5-nano",
281+
ApiKey = "sk-some-openai-api-key",
282+
BaseUrl = "https://api.openai.com/v1",
283+
Provider = ModelConfigProvider.OpenAI,
284+
},
236285
Mode = Mode.Cua,
237286
Model = new ModelConfig()
238287
{
@@ -280,6 +329,13 @@ public void AddHeadersToRequest_Works()
280329
AgentConfig = new()
281330
{
282331
Cua = true,
332+
ExecutionModel = new ModelConfig()
333+
{
334+
ModelName = "openai/gpt-5-nano",
335+
ApiKey = "sk-some-openai-api-key",
336+
BaseUrl = "https://api.openai.com/v1",
337+
Provider = ModelConfigProvider.OpenAI,
338+
},
283339
Mode = Mode.Cua,
284340
Model = new ModelConfig()
285341
{
@@ -323,6 +379,13 @@ public void CopyConstructor_Works()
323379
AgentConfig = new()
324380
{
325381
Cua = true,
382+
ExecutionModel = new ModelConfig()
383+
{
384+
ModelName = "openai/gpt-5-nano",
385+
ApiKey = "sk-some-openai-api-key",
386+
BaseUrl = "https://api.openai.com/v1",
387+
Provider = ModelConfigProvider.OpenAI,
388+
},
326389
Mode = Mode.Cua,
327390
Model = new ModelConfig()
328391
{
@@ -360,6 +423,13 @@ public void FieldRoundtrip_Works()
360423
var model = new AgentConfig
361424
{
362425
Cua = true,
426+
ExecutionModel = new ModelConfig()
427+
{
428+
ModelName = "openai/gpt-5-nano",
429+
ApiKey = "sk-some-openai-api-key",
430+
BaseUrl = "https://api.openai.com/v1",
431+
Provider = ModelConfigProvider.OpenAI,
432+
},
363433
Mode = Mode.Cua,
364434
Model = new ModelConfig()
365435
{
@@ -373,6 +443,13 @@ public void FieldRoundtrip_Works()
373443
};
374444

375445
bool expectedCua = true;
446+
ExecutionModel expectedExecutionModel = new ModelConfig()
447+
{
448+
ModelName = "openai/gpt-5-nano",
449+
ApiKey = "sk-some-openai-api-key",
450+
BaseUrl = "https://api.openai.com/v1",
451+
Provider = ModelConfigProvider.OpenAI,
452+
};
376453
ApiEnum<string, Mode> expectedMode = Mode.Cua;
377454
AgentConfigModel expectedModel = new ModelConfig()
378455
{
@@ -385,6 +462,7 @@ public void FieldRoundtrip_Works()
385462
string expectedSystemPrompt = "systemPrompt";
386463

387464
Assert.Equal(expectedCua, model.Cua);
465+
Assert.Equal(expectedExecutionModel, model.ExecutionModel);
388466
Assert.Equal(expectedMode, model.Mode);
389467
Assert.Equal(expectedModel, model.Model);
390468
Assert.Equal(expectedProvider, model.Provider);
@@ -397,6 +475,13 @@ public void SerializationRoundtrip_Works()
397475
var model = new AgentConfig
398476
{
399477
Cua = true,
478+
ExecutionModel = new ModelConfig()
479+
{
480+
ModelName = "openai/gpt-5-nano",
481+
ApiKey = "sk-some-openai-api-key",
482+
BaseUrl = "https://api.openai.com/v1",
483+
Provider = ModelConfigProvider.OpenAI,
484+
},
400485
Mode = Mode.Cua,
401486
Model = new ModelConfig()
402487
{
@@ -424,6 +509,13 @@ public void FieldRoundtripThroughSerialization_Works()
424509
var model = new AgentConfig
425510
{
426511
Cua = true,
512+
ExecutionModel = new ModelConfig()
513+
{
514+
ModelName = "openai/gpt-5-nano",
515+
ApiKey = "sk-some-openai-api-key",
516+
BaseUrl = "https://api.openai.com/v1",
517+
Provider = ModelConfigProvider.OpenAI,
518+
},
427519
Mode = Mode.Cua,
428520
Model = new ModelConfig()
429521
{
@@ -444,6 +536,13 @@ public void FieldRoundtripThroughSerialization_Works()
444536
Assert.NotNull(deserialized);
445537

446538
bool expectedCua = true;
539+
ExecutionModel expectedExecutionModel = new ModelConfig()
540+
{
541+
ModelName = "openai/gpt-5-nano",
542+
ApiKey = "sk-some-openai-api-key",
543+
BaseUrl = "https://api.openai.com/v1",
544+
Provider = ModelConfigProvider.OpenAI,
545+
};
447546
ApiEnum<string, Mode> expectedMode = Mode.Cua;
448547
AgentConfigModel expectedModel = new ModelConfig()
449548
{
@@ -456,6 +555,7 @@ public void FieldRoundtripThroughSerialization_Works()
456555
string expectedSystemPrompt = "systemPrompt";
457556

458557
Assert.Equal(expectedCua, deserialized.Cua);
558+
Assert.Equal(expectedExecutionModel, deserialized.ExecutionModel);
459559
Assert.Equal(expectedMode, deserialized.Mode);
460560
Assert.Equal(expectedModel, deserialized.Model);
461561
Assert.Equal(expectedProvider, deserialized.Provider);
@@ -468,6 +568,13 @@ public void Validation_Works()
468568
var model = new AgentConfig
469569
{
470570
Cua = true,
571+
ExecutionModel = new ModelConfig()
572+
{
573+
ModelName = "openai/gpt-5-nano",
574+
ApiKey = "sk-some-openai-api-key",
575+
BaseUrl = "https://api.openai.com/v1",
576+
Provider = ModelConfigProvider.OpenAI,
577+
},
471578
Mode = Mode.Cua,
472579
Model = new ModelConfig()
473580
{
@@ -490,6 +597,8 @@ public void OptionalNonNullablePropertiesUnsetAreNotSet_Works()
490597

491598
Assert.Null(model.Cua);
492599
Assert.False(model.RawData.ContainsKey("cua"));
600+
Assert.Null(model.ExecutionModel);
601+
Assert.False(model.RawData.ContainsKey("executionModel"));
493602
Assert.Null(model.Mode);
494603
Assert.False(model.RawData.ContainsKey("mode"));
495604
Assert.Null(model.Model);
@@ -515,6 +624,7 @@ public void OptionalNonNullablePropertiesSetToNullAreNotSet_Works()
515624
{
516625
// Null should be interpreted as omitted for these properties
517626
Cua = null,
627+
ExecutionModel = null,
518628
Mode = null,
519629
Model = null,
520630
Provider = null,
@@ -523,6 +633,8 @@ public void OptionalNonNullablePropertiesSetToNullAreNotSet_Works()
523633

524634
Assert.Null(model.Cua);
525635
Assert.False(model.RawData.ContainsKey("cua"));
636+
Assert.Null(model.ExecutionModel);
637+
Assert.False(model.RawData.ContainsKey("executionModel"));
526638
Assert.Null(model.Mode);
527639
Assert.False(model.RawData.ContainsKey("mode"));
528640
Assert.Null(model.Model);
@@ -540,6 +652,7 @@ public void OptionalNonNullablePropertiesSetToNullValidation_Works()
540652
{
541653
// Null should be interpreted as omitted for these properties
542654
Cua = null,
655+
ExecutionModel = null,
543656
Mode = null,
544657
Model = null,
545658
Provider = null,
@@ -555,6 +668,13 @@ public void CopyConstructor_Works()
555668
var model = new AgentConfig
556669
{
557670
Cua = true,
671+
ExecutionModel = new ModelConfig()
672+
{
673+
ModelName = "openai/gpt-5-nano",
674+
ApiKey = "sk-some-openai-api-key",
675+
BaseUrl = "https://api.openai.com/v1",
676+
Provider = ModelConfigProvider.OpenAI,
677+
},
558678
Mode = Mode.Cua,
559679
Model = new ModelConfig()
560680
{
@@ -573,6 +693,61 @@ public void CopyConstructor_Works()
573693
}
574694
}
575695

696+
public class ExecutionModelTest : TestBase
697+
{
698+
[Fact]
699+
public void ModelConfigValidationWorks()
700+
{
701+
ExecutionModel value = new ModelConfig()
702+
{
703+
ModelName = "openai/gpt-5-nano",
704+
ApiKey = "sk-some-openai-api-key",
705+
BaseUrl = "https://api.openai.com/v1",
706+
Provider = ModelConfigProvider.OpenAI,
707+
};
708+
value.Validate();
709+
}
710+
711+
[Fact]
712+
public void StringValidationWorks()
713+
{
714+
ExecutionModel value = "string";
715+
value.Validate();
716+
}
717+
718+
[Fact]
719+
public void ModelConfigSerializationRoundtripWorks()
720+
{
721+
ExecutionModel value = new ModelConfig()
722+
{
723+
ModelName = "openai/gpt-5-nano",
724+
ApiKey = "sk-some-openai-api-key",
725+
BaseUrl = "https://api.openai.com/v1",
726+
Provider = ModelConfigProvider.OpenAI,
727+
};
728+
string element = JsonSerializer.Serialize(value, ModelBase.SerializerOptions);
729+
var deserialized = JsonSerializer.Deserialize<ExecutionModel>(
730+
element,
731+
ModelBase.SerializerOptions
732+
);
733+
734+
Assert.Equal(value, deserialized);
735+
}
736+
737+
[Fact]
738+
public void StringSerializationRoundtripWorks()
739+
{
740+
ExecutionModel value = "string";
741+
string element = JsonSerializer.Serialize(value, ModelBase.SerializerOptions);
742+
var deserialized = JsonSerializer.Deserialize<ExecutionModel>(
743+
element,
744+
ModelBase.SerializerOptions
745+
);
746+
747+
Assert.Equal(value, deserialized);
748+
}
749+
}
750+
576751
public class ModeTest : TestBase
577752
{
578753
[Theory]

0 commit comments

Comments
 (0)