Skip to content

Commit a9b327f

Browse files
feat: [feat]: add ignoreSelectors to extract()
1 parent a388afc commit a9b327f

3 files changed

Lines changed: 58 additions & 2 deletions

File tree

.stats.yml

Lines changed: 2 additions & 2 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/stagehand-dbbff1a35360850898f7d60588e257faeac145a73cfcae634cfeb1b70109b6af.yml
3-
openapi_spec_hash: 28c4b734a5309067c39bb4c4b709b9ab
2+
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase/stagehand-7182c741edd5e22cda9bd855d31ca7e60a97a409222bb887edf87b9ce15dd493.yml
3+
openapi_spec_hash: 174581867a9191c491b22855b64c4f19
44
config_hash: a962ae71493deb11a1c903256fb25386

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

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ public void FieldRoundtrip_Works()
2020
Instruction = "Extract all product names and prices from the page",
2121
Options = new()
2222
{
23+
IgnoreSelectors = ["nav", ".cookie-banner", "#sidebar-ads"],
2324
Model = new ModelConfig()
2425
{
2526
ModelName = "openai/gpt-5.4-mini",
@@ -43,6 +44,7 @@ public void FieldRoundtrip_Works()
4344
string expectedInstruction = "Extract all product names and prices from the page";
4445
SessionExtractParamsOptions expectedOptions = new()
4546
{
47+
IgnoreSelectors = ["nav", ".cookie-banner", "#sidebar-ads"],
4648
Model = new ModelConfig()
4749
{
4850
ModelName = "openai/gpt-5.4-mini",
@@ -129,6 +131,7 @@ public void OptionalNullableParamsUnsetAreNotSet_Works()
129131
Instruction = "Extract all product names and prices from the page",
130132
Options = new()
131133
{
134+
IgnoreSelectors = ["nav", ".cookie-banner", "#sidebar-ads"],
132135
Model = new ModelConfig()
133136
{
134137
ModelName = "openai/gpt-5.4-mini",
@@ -160,6 +163,7 @@ public void OptionalNullableParamsSetToNullAreSetToNull_Works()
160163
Instruction = "Extract all product names and prices from the page",
161164
Options = new()
162165
{
166+
IgnoreSelectors = ["nav", ".cookie-banner", "#sidebar-ads"],
163167
Model = new ModelConfig()
164168
{
165169
ModelName = "openai/gpt-5.4-mini",
@@ -241,6 +245,7 @@ public void CopyConstructor_Works()
241245
Instruction = "Extract all product names and prices from the page",
242246
Options = new()
243247
{
248+
IgnoreSelectors = ["nav", ".cookie-banner", "#sidebar-ads"],
244249
Model = new ModelConfig()
245250
{
246251
ModelName = "openai/gpt-5.4-mini",
@@ -272,6 +277,7 @@ public void FieldRoundtrip_Works()
272277
{
273278
var model = new SessionExtractParamsOptions
274279
{
280+
IgnoreSelectors = ["nav", ".cookie-banner", "#sidebar-ads"],
275281
Model = new ModelConfig()
276282
{
277283
ModelName = "openai/gpt-5.4-mini",
@@ -284,6 +290,7 @@ public void FieldRoundtrip_Works()
284290
Timeout = 30000,
285291
};
286292

293+
List<string> expectedIgnoreSelectors = ["nav", ".cookie-banner", "#sidebar-ads"];
287294
SessionExtractParamsOptionsModel expectedModel = new ModelConfig()
288295
{
289296
ModelName = "openai/gpt-5.4-mini",
@@ -295,6 +302,12 @@ public void FieldRoundtrip_Works()
295302
string expectedSelector = "#main-content";
296303
double expectedTimeout = 30000;
297304

305+
Assert.NotNull(model.IgnoreSelectors);
306+
Assert.Equal(expectedIgnoreSelectors.Count, model.IgnoreSelectors.Count);
307+
for (int i = 0; i < expectedIgnoreSelectors.Count; i++)
308+
{
309+
Assert.Equal(expectedIgnoreSelectors[i], model.IgnoreSelectors[i]);
310+
}
298311
Assert.Equal(expectedModel, model.Model);
299312
Assert.Equal(expectedSelector, model.Selector);
300313
Assert.Equal(expectedTimeout, model.Timeout);
@@ -305,6 +318,7 @@ public void SerializationRoundtrip_Works()
305318
{
306319
var model = new SessionExtractParamsOptions
307320
{
321+
IgnoreSelectors = ["nav", ".cookie-banner", "#sidebar-ads"],
308322
Model = new ModelConfig()
309323
{
310324
ModelName = "openai/gpt-5.4-mini",
@@ -331,6 +345,7 @@ public void FieldRoundtripThroughSerialization_Works()
331345
{
332346
var model = new SessionExtractParamsOptions
333347
{
348+
IgnoreSelectors = ["nav", ".cookie-banner", "#sidebar-ads"],
334349
Model = new ModelConfig()
335350
{
336351
ModelName = "openai/gpt-5.4-mini",
@@ -350,6 +365,7 @@ public void FieldRoundtripThroughSerialization_Works()
350365
);
351366
Assert.NotNull(deserialized);
352367

368+
List<string> expectedIgnoreSelectors = ["nav", ".cookie-banner", "#sidebar-ads"];
353369
SessionExtractParamsOptionsModel expectedModel = new ModelConfig()
354370
{
355371
ModelName = "openai/gpt-5.4-mini",
@@ -361,6 +377,12 @@ public void FieldRoundtripThroughSerialization_Works()
361377
string expectedSelector = "#main-content";
362378
double expectedTimeout = 30000;
363379

380+
Assert.NotNull(deserialized.IgnoreSelectors);
381+
Assert.Equal(expectedIgnoreSelectors.Count, deserialized.IgnoreSelectors.Count);
382+
for (int i = 0; i < expectedIgnoreSelectors.Count; i++)
383+
{
384+
Assert.Equal(expectedIgnoreSelectors[i], deserialized.IgnoreSelectors[i]);
385+
}
364386
Assert.Equal(expectedModel, deserialized.Model);
365387
Assert.Equal(expectedSelector, deserialized.Selector);
366388
Assert.Equal(expectedTimeout, deserialized.Timeout);
@@ -371,6 +393,7 @@ public void Validation_Works()
371393
{
372394
var model = new SessionExtractParamsOptions
373395
{
396+
IgnoreSelectors = ["nav", ".cookie-banner", "#sidebar-ads"],
374397
Model = new ModelConfig()
375398
{
376399
ModelName = "openai/gpt-5.4-mini",
@@ -391,6 +414,8 @@ public void OptionalNonNullablePropertiesUnsetAreNotSet_Works()
391414
{
392415
var model = new SessionExtractParamsOptions { };
393416

417+
Assert.Null(model.IgnoreSelectors);
418+
Assert.False(model.RawData.ContainsKey("ignoreSelectors"));
394419
Assert.Null(model.Model);
395420
Assert.False(model.RawData.ContainsKey("model"));
396421
Assert.Null(model.Selector);
@@ -413,11 +438,14 @@ public void OptionalNonNullablePropertiesSetToNullAreNotSet_Works()
413438
var model = new SessionExtractParamsOptions
414439
{
415440
// Null should be interpreted as omitted for these properties
441+
IgnoreSelectors = null,
416442
Model = null,
417443
Selector = null,
418444
Timeout = null,
419445
};
420446

447+
Assert.Null(model.IgnoreSelectors);
448+
Assert.False(model.RawData.ContainsKey("ignoreSelectors"));
421449
Assert.Null(model.Model);
422450
Assert.False(model.RawData.ContainsKey("model"));
423451
Assert.Null(model.Selector);
@@ -432,6 +460,7 @@ public void OptionalNonNullablePropertiesSetToNullValidation_Works()
432460
var model = new SessionExtractParamsOptions
433461
{
434462
// Null should be interpreted as omitted for these properties
463+
IgnoreSelectors = null,
435464
Model = null,
436465
Selector = null,
437466
Timeout = null,
@@ -445,6 +474,7 @@ public void CopyConstructor_Works()
445474
{
446475
var model = new SessionExtractParamsOptions
447476
{
477+
IgnoreSelectors = ["nav", ".cookie-banner", "#sidebar-ads"],
448478
Model = new ModelConfig()
449479
{
450480
ModelName = "openai/gpt-5.4-mini",

src/Stagehand/Models/Sessions/SessionExtractParams.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System.Collections.Frozen;
22
using System.Collections.Generic;
3+
using System.Collections.Immutable;
34
using System.Diagnostics.CodeAnalysis;
45
using System.Net.Http;
56
using System.Text;
@@ -255,6 +256,30 @@ public override int GetHashCode()
255256
)]
256257
public sealed record class SessionExtractParamsOptions : JsonModel
257258
{
259+
/// <summary>
260+
/// Selectors for elements and subtrees that should be excluded from extraction
261+
/// </summary>
262+
public IReadOnlyList<string>? IgnoreSelectors
263+
{
264+
get
265+
{
266+
this._rawData.Freeze();
267+
return this._rawData.GetNullableStruct<ImmutableArray<string>>("ignoreSelectors");
268+
}
269+
init
270+
{
271+
if (value == null)
272+
{
273+
return;
274+
}
275+
276+
this._rawData.Set<ImmutableArray<string>?>(
277+
"ignoreSelectors",
278+
value == null ? null : ImmutableArray.ToImmutableArray(value)
279+
);
280+
}
281+
}
282+
258283
/// <summary>
259284
/// Model configuration object or model name string (e.g., 'openai/gpt-5-nano')
260285
/// </summary>
@@ -321,6 +346,7 @@ public double? Timeout
321346
/// <inheritdoc/>
322347
public override void Validate()
323348
{
349+
_ = this.IgnoreSelectors;
324350
this.Model?.Validate();
325351
_ = this.Selector;
326352
_ = this.Timeout;

0 commit comments

Comments
 (0)