airbyte-agent-zendesk-support 0.18.48__py3-none-any.whl → 0.18.50__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -73,8 +73,8 @@ from .models import (
73
73
  TicketFormsListResult,
74
74
  ArticlesListResult,
75
75
  ArticleAttachmentsListResult,
76
- SearchHit,
77
- SearchResult,
76
+ AirbyteSearchHit,
77
+ AirbyteSearchResult,
78
78
  BrandsSearchData,
79
79
  BrandsSearchResult,
80
80
  GroupsSearchData,
@@ -141,8 +141,8 @@ from .types import (
141
141
  ArticleAttachmentsListParams,
142
142
  ArticleAttachmentsGetParams,
143
143
  ArticleAttachmentsDownloadParams,
144
- SearchParams,
145
- SortOrder,
144
+ AirbyteSearchParams,
145
+ AirbyteSortOrder,
146
146
  BrandsSearchFilter,
147
147
  BrandsSearchQuery,
148
148
  BrandsCondition,
@@ -250,8 +250,8 @@ __all__ = [
250
250
  "TicketFormsListResult",
251
251
  "ArticlesListResult",
252
252
  "ArticleAttachmentsListResult",
253
- "SearchHit",
254
- "SearchResult",
253
+ "AirbyteSearchHit",
254
+ "AirbyteSearchResult",
255
255
  "BrandsSearchData",
256
256
  "BrandsSearchResult",
257
257
  "GroupsSearchData",
@@ -316,8 +316,8 @@ __all__ = [
316
316
  "ArticleAttachmentsListParams",
317
317
  "ArticleAttachmentsGetParams",
318
318
  "ArticleAttachmentsDownloadParams",
319
- "SearchParams",
320
- "SortOrder",
319
+ "AirbyteSearchParams",
320
+ "AirbyteSortOrder",
321
321
  "BrandsSearchFilter",
322
322
  "BrandsSearchQuery",
323
323
  "BrandsCondition",
@@ -1222,15 +1222,22 @@ class LocalExecutor:
1222
1222
  def _extract_metadata(
1223
1223
  self,
1224
1224
  response_data: dict[str, Any],
1225
+ response_headers: dict[str, str],
1225
1226
  endpoint: EndpointDefinition,
1226
1227
  ) -> dict[str, Any] | None:
1227
1228
  """Extract metadata from response using meta extractor.
1228
1229
 
1229
- Each field in meta_extractor dict is independently extracted using JSONPath.
1230
+ Each field in meta_extractor dict is independently extracted using JSONPath
1231
+ for body extraction, or special prefixes for header extraction:
1232
+ - @link.{rel}: Extract URL from RFC 5988 Link header by rel type
1233
+ - @header.{name}: Extract raw header value by header name
1234
+ - Otherwise: JSONPath expression for body extraction
1235
+
1230
1236
  Missing or invalid paths result in None for that field (no crash).
1231
1237
 
1232
1238
  Args:
1233
1239
  response_data: Full API response (before record extraction)
1240
+ response_headers: HTTP response headers
1234
1241
  endpoint: Endpoint with optional meta extractor configuration
1235
1242
 
1236
1243
  Returns:
@@ -1241,11 +1248,15 @@ class LocalExecutor:
1241
1248
  Example:
1242
1249
  meta_extractor = {
1243
1250
  "pagination": "$.records",
1244
- "request_id": "$.requestId"
1251
+ "request_id": "$.requestId",
1252
+ "next_page_url": "@link.next",
1253
+ "rate_limit": "@header.X-RateLimit-Remaining"
1245
1254
  }
1246
1255
  Returns: {
1247
1256
  "pagination": {"cursor": "abc", "total": 100},
1248
- "request_id": "xyz123"
1257
+ "request_id": "xyz123",
1258
+ "next_page_url": "https://api.example.com/data?cursor=abc",
1259
+ "rate_limit": "99"
1249
1260
  }
1250
1261
  """
1251
1262
  # Check if endpoint has meta extractor
@@ -1255,26 +1266,96 @@ class LocalExecutor:
1255
1266
  extracted_meta: dict[str, Any] = {}
1256
1267
 
1257
1268
  # Extract each field independently
1258
- for field_name, jsonpath_expr_str in endpoint.meta_extractor.items():
1269
+ for field_name, extractor_expr in endpoint.meta_extractor.items():
1259
1270
  try:
1260
- # Parse and apply JSONPath expression
1261
- jsonpath_expr = parse_jsonpath(jsonpath_expr_str)
1262
- matches = [match.value for match in jsonpath_expr.find(response_data)]
1263
-
1264
- if matches:
1265
- # Return first match (most common case)
1266
- extracted_meta[field_name] = matches[0]
1271
+ if extractor_expr.startswith("@link."):
1272
+ # RFC 5988 Link header extraction
1273
+ rel = extractor_expr[6:]
1274
+ extracted_meta[field_name] = self._extract_link_url(response_headers, rel)
1275
+ elif extractor_expr.startswith("@header."):
1276
+ # Raw header value extraction (case-insensitive lookup)
1277
+ header_name = extractor_expr[8:]
1278
+ extracted_meta[field_name] = self._get_header_value(response_headers, header_name)
1267
1279
  else:
1268
- # Path not found - set to None
1269
- extracted_meta[field_name] = None
1280
+ # JSONPath body extraction
1281
+ jsonpath_expr = parse_jsonpath(extractor_expr)
1282
+ matches = [match.value for match in jsonpath_expr.find(response_data)]
1283
+
1284
+ if matches:
1285
+ # Return first match (most common case)
1286
+ extracted_meta[field_name] = matches[0]
1287
+ else:
1288
+ # Path not found - set to None
1289
+ extracted_meta[field_name] = None
1270
1290
 
1271
1291
  except Exception as e:
1272
1292
  # Log error but continue with other fields
1273
- logging.warning(f"Failed to apply meta extractor for field '{field_name}' with path '{jsonpath_expr_str}': {e}. Setting to None.")
1293
+ logging.warning(f"Failed to apply meta extractor for field '{field_name}' with expression '{extractor_expr}': {e}. Setting to None.")
1274
1294
  extracted_meta[field_name] = None
1275
1295
 
1276
1296
  return extracted_meta
1277
1297
 
1298
+ @staticmethod
1299
+ def _extract_link_url(headers: dict[str, str], rel: str) -> str | None:
1300
+ """Extract URL from RFC 5988 Link header by rel type.
1301
+
1302
+ Parses Link header format: <url>; param1="value1"; rel="next"; param2="value2"
1303
+
1304
+ Supports:
1305
+ - Multiple parameters per link in any order
1306
+ - Both quoted and unquoted rel values
1307
+ - Multiple links separated by commas
1308
+
1309
+ Args:
1310
+ headers: Response headers dict
1311
+ rel: The rel type to extract (e.g., "next", "prev", "first", "last")
1312
+
1313
+ Returns:
1314
+ The URL for the specified rel type, or None if not found
1315
+ """
1316
+ link_header = headers.get("Link") or headers.get("link", "")
1317
+ if not link_header:
1318
+ return None
1319
+
1320
+ for link_segment in re.split(r",(?=\s*<)", link_header):
1321
+ link_segment = link_segment.strip()
1322
+
1323
+ url_match = re.match(r"<([^>]+)>", link_segment)
1324
+ if not url_match:
1325
+ continue
1326
+
1327
+ url = url_match.group(1)
1328
+ params_str = link_segment[url_match.end() :]
1329
+
1330
+ rel_match = re.search(r';\s*rel="?([^";,]+)"?', params_str, re.IGNORECASE)
1331
+ if rel_match and rel_match.group(1).strip() == rel:
1332
+ return url
1333
+
1334
+ return None
1335
+
1336
+ @staticmethod
1337
+ def _get_header_value(headers: dict[str, str], header_name: str) -> str | None:
1338
+ """Get header value with case-insensitive lookup.
1339
+
1340
+ Args:
1341
+ headers: Response headers dict
1342
+ header_name: Header name to look up
1343
+
1344
+ Returns:
1345
+ Header value or None if not found
1346
+ """
1347
+ # Try exact match first
1348
+ if header_name in headers:
1349
+ return headers[header_name]
1350
+
1351
+ # Case-insensitive lookup
1352
+ header_name_lower = header_name.lower()
1353
+ for key, value in headers.items():
1354
+ if key.lower() == header_name_lower:
1355
+ return value
1356
+
1357
+ return None
1358
+
1278
1359
  def _validate_required_body_fields(self, endpoint: Any, params: dict[str, Any], action: Action, entity: str) -> None:
1279
1360
  """Validate that required body fields are present for CREATE/UPDATE operations.
1280
1361
 
@@ -1402,7 +1483,7 @@ class _StandardOperationHandler:
1402
1483
  request_kwargs = self.ctx.determine_request_format(endpoint, body)
1403
1484
 
1404
1485
  # Execute async HTTP request
1405
- response = await self.ctx.http_client.request(
1486
+ response_data, response_headers = await self.ctx.http_client.request(
1406
1487
  method=endpoint.method,
1407
1488
  path=path,
1408
1489
  params=query_params if query_params else None,
@@ -1411,10 +1492,10 @@ class _StandardOperationHandler:
1411
1492
  )
1412
1493
 
1413
1494
  # Extract metadata from original response (before record extraction)
1414
- metadata = self.ctx.executor._extract_metadata(response, endpoint)
1495
+ metadata = self.ctx.executor._extract_metadata(response_data, response_headers, endpoint)
1415
1496
 
1416
1497
  # Extract records if extractor configured
1417
- response = self.ctx.extract_records(response, endpoint)
1498
+ response = self.ctx.extract_records(response_data, endpoint)
1418
1499
 
1419
1500
  # Assume success with 200 status code if no exception raised
1420
1501
  status_code = 200
@@ -1540,7 +1621,7 @@ class _DownloadOperationHandler:
1540
1621
  request_format = self.ctx.determine_request_format(operation, request_body)
1541
1622
  self.ctx.validate_required_body_fields(operation, params, action, entity)
1542
1623
 
1543
- metadata_response = await self.ctx.http_client.request(
1624
+ metadata_response, _ = await self.ctx.http_client.request(
1544
1625
  method=operation.method,
1545
1626
  path=path,
1546
1627
  params=query_params,
@@ -1555,7 +1636,7 @@ class _DownloadOperationHandler:
1555
1636
  )
1556
1637
 
1557
1638
  # Step 3: Stream file from extracted URL
1558
- file_response = await self.ctx.http_client.request(
1639
+ file_response, _ = await self.ctx.http_client.request(
1559
1640
  method="GET",
1560
1641
  path=file_url,
1561
1642
  headers=headers,
@@ -1563,7 +1644,7 @@ class _DownloadOperationHandler:
1563
1644
  )
1564
1645
  else:
1565
1646
  # One-step direct download: stream file directly from endpoint
1566
- file_response = await self.ctx.http_client.request(
1647
+ file_response, _ = await self.ctx.http_client.request(
1567
1648
  method=operation.method,
1568
1649
  path=path,
1569
1650
  params=query_params,
@@ -421,10 +421,14 @@ class HTTPClient:
421
421
  headers: dict[str, str] | None = None,
422
422
  *,
423
423
  stream: bool = False,
424
- ):
424
+ ) -> tuple[dict[str, Any], dict[str, str]]:
425
425
  """Execute a single HTTP request attempt (no retries).
426
426
 
427
427
  This is the core request logic, separated from retry handling.
428
+
429
+ Returns:
430
+ Tuple of (response_data, response_headers) for non-streaming requests.
431
+ For streaming requests, returns (response_object, response_headers).
428
432
  """
429
433
  # Ensure auth credentials are initialized (proactive refresh if needed)
430
434
  await self._ensure_auth_initialized()
@@ -475,7 +479,7 @@ class HTTPClient:
475
479
  status_code=status_code,
476
480
  response_body=f"<binary content, {response.headers.get('content-length', 'unknown')} bytes>",
477
481
  )
478
- return response
482
+ return response, dict(response.headers)
479
483
 
480
484
  # Parse response - handle non-JSON responses gracefully
481
485
  content_type = response.headers.get("content-type", "")
@@ -501,7 +505,7 @@ class HTTPClient:
501
505
  status_code=status_code,
502
506
  response_body=response_data,
503
507
  )
504
- return response_data
508
+ return response_data, dict(response.headers)
505
509
 
506
510
  except AuthenticationError as e:
507
511
  # Auth error (401, 403) - handle token refresh
@@ -631,7 +635,7 @@ class HTTPClient:
631
635
  *,
632
636
  stream: bool = False,
633
637
  _auth_retry_attempted: bool = False,
634
- ):
638
+ ) -> tuple[dict[str, Any], dict[str, str]]:
635
639
  """Make an async HTTP request with optional streaming and automatic retries.
636
640
 
637
641
  Args:
@@ -644,8 +648,9 @@ class HTTPClient:
644
648
  stream: If True, do not eagerly read the body (useful for downloads)
645
649
 
646
650
  Returns:
647
- - If stream=False: Parsed JSON (dict) or empty dict
648
- - If stream=True: Response object suitable for streaming
651
+ Tuple of (response_data, response_headers):
652
+ - If stream=False: (parsed JSON dict or empty dict, response headers dict)
653
+ - If stream=True: (response object suitable for streaming, response headers dict)
649
654
 
650
655
  Raises:
651
656
  HTTPStatusError: If request fails with 4xx/5xx status after all retries
@@ -53,7 +53,7 @@ from .types import (
53
53
  UsersListParams,
54
54
  ViewsGetParams,
55
55
  ViewsListParams,
56
- SearchParams,
56
+ AirbyteSearchParams,
57
57
  BrandsSearchFilter,
58
58
  BrandsSearchQuery,
59
59
  GroupsSearchFilter,
@@ -131,8 +131,8 @@ from .models import (
131
131
  Trigger,
132
132
  User,
133
133
  View,
134
- SearchHit,
135
- SearchResult,
134
+ AirbyteSearchHit,
135
+ AirbyteSearchResult,
136
136
  BrandsSearchData,
137
137
  BrandsSearchResult,
138
138
  GroupsSearchData,
@@ -990,7 +990,7 @@ class TicketsQuery:
990
990
  Example: [["id"], ["user", "name"]] returns id and user.name fields.
991
991
 
992
992
  Returns:
993
- TicketsSearchResult with hits (list of SearchHit[TicketsSearchData]) and pagination info
993
+ TicketsSearchResult with hits (list of AirbyteSearchHit[TicketsSearchData]) and pagination info
994
994
 
995
995
  Raises:
996
996
  NotImplementedError: If called in local execution mode
@@ -1008,7 +1008,7 @@ class TicketsQuery:
1008
1008
  # Parse response into typed result
1009
1009
  return TicketsSearchResult(
1010
1010
  hits=[
1011
- SearchHit[TicketsSearchData](
1011
+ AirbyteSearchHit[TicketsSearchData](
1012
1012
  id=hit.get("id"),
1013
1013
  score=hit.get("score"),
1014
1014
  data=TicketsSearchData(**hit.get("data", {}))
@@ -1151,7 +1151,7 @@ class UsersQuery:
1151
1151
  Example: [["id"], ["user", "name"]] returns id and user.name fields.
1152
1152
 
1153
1153
  Returns:
1154
- UsersSearchResult with hits (list of SearchHit[UsersSearchData]) and pagination info
1154
+ UsersSearchResult with hits (list of AirbyteSearchHit[UsersSearchData]) and pagination info
1155
1155
 
1156
1156
  Raises:
1157
1157
  NotImplementedError: If called in local execution mode
@@ -1169,7 +1169,7 @@ class UsersQuery:
1169
1169
  # Parse response into typed result
1170
1170
  return UsersSearchResult(
1171
1171
  hits=[
1172
- SearchHit[UsersSearchData](
1172
+ AirbyteSearchHit[UsersSearchData](
1173
1173
  id=hit.get("id"),
1174
1174
  score=hit.get("score"),
1175
1175
  data=UsersSearchData(**hit.get("data", {}))
@@ -1282,7 +1282,7 @@ class OrganizationsQuery:
1282
1282
  Example: [["id"], ["user", "name"]] returns id and user.name fields.
1283
1283
 
1284
1284
  Returns:
1285
- OrganizationsSearchResult with hits (list of SearchHit[OrganizationsSearchData]) and pagination info
1285
+ OrganizationsSearchResult with hits (list of AirbyteSearchHit[OrganizationsSearchData]) and pagination info
1286
1286
 
1287
1287
  Raises:
1288
1288
  NotImplementedError: If called in local execution mode
@@ -1300,7 +1300,7 @@ class OrganizationsQuery:
1300
1300
  # Parse response into typed result
1301
1301
  return OrganizationsSearchResult(
1302
1302
  hits=[
1303
- SearchHit[OrganizationsSearchData](
1303
+ AirbyteSearchHit[OrganizationsSearchData](
1304
1304
  id=hit.get("id"),
1305
1305
  score=hit.get("score"),
1306
1306
  data=OrganizationsSearchData(**hit.get("data", {}))
@@ -1410,7 +1410,7 @@ class GroupsQuery:
1410
1410
  Example: [["id"], ["user", "name"]] returns id and user.name fields.
1411
1411
 
1412
1412
  Returns:
1413
- GroupsSearchResult with hits (list of SearchHit[GroupsSearchData]) and pagination info
1413
+ GroupsSearchResult with hits (list of AirbyteSearchHit[GroupsSearchData]) and pagination info
1414
1414
 
1415
1415
  Raises:
1416
1416
  NotImplementedError: If called in local execution mode
@@ -1428,7 +1428,7 @@ class GroupsQuery:
1428
1428
  # Parse response into typed result
1429
1429
  return GroupsSearchResult(
1430
1430
  hits=[
1431
- SearchHit[GroupsSearchData](
1431
+ AirbyteSearchHit[GroupsSearchData](
1432
1432
  id=hit.get("id"),
1433
1433
  score=hit.get("score"),
1434
1434
  data=GroupsSearchData(**hit.get("data", {}))
@@ -1527,7 +1527,7 @@ class TicketCommentsQuery:
1527
1527
  Example: [["id"], ["user", "name"]] returns id and user.name fields.
1528
1528
 
1529
1529
  Returns:
1530
- TicketCommentsSearchResult with hits (list of SearchHit[TicketCommentsSearchData]) and pagination info
1530
+ TicketCommentsSearchResult with hits (list of AirbyteSearchHit[TicketCommentsSearchData]) and pagination info
1531
1531
 
1532
1532
  Raises:
1533
1533
  NotImplementedError: If called in local execution mode
@@ -1545,7 +1545,7 @@ class TicketCommentsQuery:
1545
1545
  # Parse response into typed result
1546
1546
  return TicketCommentsSearchResult(
1547
1547
  hits=[
1548
- SearchHit[TicketCommentsSearchData](
1548
+ AirbyteSearchHit[TicketCommentsSearchData](
1549
1549
  id=hit.get("id"),
1550
1550
  score=hit.get("score"),
1551
1551
  data=TicketCommentsSearchData(**hit.get("data", {}))
@@ -1750,7 +1750,7 @@ class TicketAuditsQuery:
1750
1750
  Example: [["id"], ["user", "name"]] returns id and user.name fields.
1751
1751
 
1752
1752
  Returns:
1753
- TicketAuditsSearchResult with hits (list of SearchHit[TicketAuditsSearchData]) and pagination info
1753
+ TicketAuditsSearchResult with hits (list of AirbyteSearchHit[TicketAuditsSearchData]) and pagination info
1754
1754
 
1755
1755
  Raises:
1756
1756
  NotImplementedError: If called in local execution mode
@@ -1768,7 +1768,7 @@ class TicketAuditsQuery:
1768
1768
  # Parse response into typed result
1769
1769
  return TicketAuditsSearchResult(
1770
1770
  hits=[
1771
- SearchHit[TicketAuditsSearchData](
1771
+ AirbyteSearchHit[TicketAuditsSearchData](
1772
1772
  id=hit.get("id"),
1773
1773
  score=hit.get("score"),
1774
1774
  data=TicketAuditsSearchData(**hit.get("data", {}))
@@ -1871,7 +1871,7 @@ class TicketMetricsQuery:
1871
1871
  Example: [["id"], ["user", "name"]] returns id and user.name fields.
1872
1872
 
1873
1873
  Returns:
1874
- TicketMetricsSearchResult with hits (list of SearchHit[TicketMetricsSearchData]) and pagination info
1874
+ TicketMetricsSearchResult with hits (list of AirbyteSearchHit[TicketMetricsSearchData]) and pagination info
1875
1875
 
1876
1876
  Raises:
1877
1877
  NotImplementedError: If called in local execution mode
@@ -1889,7 +1889,7 @@ class TicketMetricsQuery:
1889
1889
  # Parse response into typed result
1890
1890
  return TicketMetricsSearchResult(
1891
1891
  hits=[
1892
- SearchHit[TicketMetricsSearchData](
1892
+ AirbyteSearchHit[TicketMetricsSearchData](
1893
1893
  id=hit.get("id"),
1894
1894
  score=hit.get("score"),
1895
1895
  data=TicketMetricsSearchData(**hit.get("data", {}))
@@ -2017,7 +2017,7 @@ class TicketFieldsQuery:
2017
2017
  Example: [["id"], ["user", "name"]] returns id and user.name fields.
2018
2018
 
2019
2019
  Returns:
2020
- TicketFieldsSearchResult with hits (list of SearchHit[TicketFieldsSearchData]) and pagination info
2020
+ TicketFieldsSearchResult with hits (list of AirbyteSearchHit[TicketFieldsSearchData]) and pagination info
2021
2021
 
2022
2022
  Raises:
2023
2023
  NotImplementedError: If called in local execution mode
@@ -2035,7 +2035,7 @@ class TicketFieldsQuery:
2035
2035
  # Parse response into typed result
2036
2036
  return TicketFieldsSearchResult(
2037
2037
  hits=[
2038
- SearchHit[TicketFieldsSearchData](
2038
+ AirbyteSearchHit[TicketFieldsSearchData](
2039
2039
  id=hit.get("id"),
2040
2040
  score=hit.get("score"),
2041
2041
  data=TicketFieldsSearchData(**hit.get("data", {}))
@@ -2149,7 +2149,7 @@ class BrandsQuery:
2149
2149
  Example: [["id"], ["user", "name"]] returns id and user.name fields.
2150
2150
 
2151
2151
  Returns:
2152
- BrandsSearchResult with hits (list of SearchHit[BrandsSearchData]) and pagination info
2152
+ BrandsSearchResult with hits (list of AirbyteSearchHit[BrandsSearchData]) and pagination info
2153
2153
 
2154
2154
  Raises:
2155
2155
  NotImplementedError: If called in local execution mode
@@ -2167,7 +2167,7 @@ class BrandsQuery:
2167
2167
  # Parse response into typed result
2168
2168
  return BrandsSearchResult(
2169
2169
  hits=[
2170
- SearchHit[BrandsSearchData](
2170
+ AirbyteSearchHit[BrandsSearchData](
2171
2171
  id=hit.get("id"),
2172
2172
  score=hit.get("score"),
2173
2173
  data=BrandsSearchData(**hit.get("data", {}))
@@ -2545,7 +2545,7 @@ class TagsQuery:
2545
2545
  Example: [["id"], ["user", "name"]] returns id and user.name fields.
2546
2546
 
2547
2547
  Returns:
2548
- TagsSearchResult with hits (list of SearchHit[TagsSearchData]) and pagination info
2548
+ TagsSearchResult with hits (list of AirbyteSearchHit[TagsSearchData]) and pagination info
2549
2549
 
2550
2550
  Raises:
2551
2551
  NotImplementedError: If called in local execution mode
@@ -2563,7 +2563,7 @@ class TagsQuery:
2563
2563
  # Parse response into typed result
2564
2564
  return TagsSearchResult(
2565
2565
  hits=[
2566
- SearchHit[TagsSearchData](
2566
+ AirbyteSearchHit[TagsSearchData](
2567
2567
  id=hit.get("id"),
2568
2568
  score=hit.get("score"),
2569
2569
  data=TagsSearchData(**hit.get("data", {}))
@@ -2682,7 +2682,7 @@ class SatisfactionRatingsQuery:
2682
2682
  Example: [["id"], ["user", "name"]] returns id and user.name fields.
2683
2683
 
2684
2684
  Returns:
2685
- SatisfactionRatingsSearchResult with hits (list of SearchHit[SatisfactionRatingsSearchData]) and pagination info
2685
+ SatisfactionRatingsSearchResult with hits (list of AirbyteSearchHit[SatisfactionRatingsSearchData]) and pagination info
2686
2686
 
2687
2687
  Raises:
2688
2688
  NotImplementedError: If called in local execution mode
@@ -2700,7 +2700,7 @@ class SatisfactionRatingsQuery:
2700
2700
  # Parse response into typed result
2701
2701
  return SatisfactionRatingsSearchResult(
2702
2702
  hits=[
2703
- SearchHit[SatisfactionRatingsSearchData](
2703
+ AirbyteSearchHit[SatisfactionRatingsSearchData](
2704
2704
  id=hit.get("id"),
2705
2705
  score=hit.get("score"),
2706
2706
  data=SatisfactionRatingsSearchData(**hit.get("data", {}))
@@ -2960,7 +2960,7 @@ class TicketFormsQuery:
2960
2960
  Example: [["id"], ["user", "name"]] returns id and user.name fields.
2961
2961
 
2962
2962
  Returns:
2963
- TicketFormsSearchResult with hits (list of SearchHit[TicketFormsSearchData]) and pagination info
2963
+ TicketFormsSearchResult with hits (list of AirbyteSearchHit[TicketFormsSearchData]) and pagination info
2964
2964
 
2965
2965
  Raises:
2966
2966
  NotImplementedError: If called in local execution mode
@@ -2978,7 +2978,7 @@ class TicketFormsQuery:
2978
2978
  # Parse response into typed result
2979
2979
  return TicketFormsSearchResult(
2980
2980
  hits=[
2981
- SearchHit[TicketFormsSearchData](
2981
+ AirbyteSearchHit[TicketFormsSearchData](
2982
2982
  id=hit.get("id"),
2983
2983
  score=hit.get("score"),
2984
2984
  data=TicketFormsSearchData(**hit.get("data", {}))
@@ -1212,7 +1212,7 @@ class UsersSearchData(BaseModel):
1212
1212
 
1213
1213
  # ===== GENERIC SEARCH RESULT TYPES =====
1214
1214
 
1215
- class SearchHit(BaseModel, Generic[D]):
1215
+ class AirbyteSearchHit(BaseModel, Generic[D]):
1216
1216
  """A single search result with typed data."""
1217
1217
  model_config = ConfigDict(extra="allow")
1218
1218
 
@@ -1224,11 +1224,11 @@ class SearchHit(BaseModel, Generic[D]):
1224
1224
  """The matched record data."""
1225
1225
 
1226
1226
 
1227
- class SearchResult(BaseModel, Generic[D]):
1228
- """Result from search operations with typed hits."""
1227
+ class AirbyteSearchResult(BaseModel, Generic[D]):
1228
+ """Result from Airbyte cache search operations with typed hits."""
1229
1229
  model_config = ConfigDict(extra="allow")
1230
1230
 
1231
- hits: list[SearchHit[D]] = Field(default_factory=list)
1231
+ hits: list[AirbyteSearchHit[D]] = Field(default_factory=list)
1232
1232
  """List of matching records."""
1233
1233
  next_cursor: str | None = None
1234
1234
  """Cursor for fetching the next page of results."""
@@ -1238,40 +1238,40 @@ class SearchResult(BaseModel, Generic[D]):
1238
1238
 
1239
1239
  # ===== ENTITY-SPECIFIC SEARCH RESULT TYPE ALIASES =====
1240
1240
 
1241
- BrandsSearchResult = SearchResult[BrandsSearchData]
1241
+ BrandsSearchResult = AirbyteSearchResult[BrandsSearchData]
1242
1242
  """Search result type for brands entity."""
1243
1243
 
1244
- GroupsSearchResult = SearchResult[GroupsSearchData]
1244
+ GroupsSearchResult = AirbyteSearchResult[GroupsSearchData]
1245
1245
  """Search result type for groups entity."""
1246
1246
 
1247
- OrganizationsSearchResult = SearchResult[OrganizationsSearchData]
1247
+ OrganizationsSearchResult = AirbyteSearchResult[OrganizationsSearchData]
1248
1248
  """Search result type for organizations entity."""
1249
1249
 
1250
- SatisfactionRatingsSearchResult = SearchResult[SatisfactionRatingsSearchData]
1250
+ SatisfactionRatingsSearchResult = AirbyteSearchResult[SatisfactionRatingsSearchData]
1251
1251
  """Search result type for satisfaction_ratings entity."""
1252
1252
 
1253
- TagsSearchResult = SearchResult[TagsSearchData]
1253
+ TagsSearchResult = AirbyteSearchResult[TagsSearchData]
1254
1254
  """Search result type for tags entity."""
1255
1255
 
1256
- TicketAuditsSearchResult = SearchResult[TicketAuditsSearchData]
1256
+ TicketAuditsSearchResult = AirbyteSearchResult[TicketAuditsSearchData]
1257
1257
  """Search result type for ticket_audits entity."""
1258
1258
 
1259
- TicketCommentsSearchResult = SearchResult[TicketCommentsSearchData]
1259
+ TicketCommentsSearchResult = AirbyteSearchResult[TicketCommentsSearchData]
1260
1260
  """Search result type for ticket_comments entity."""
1261
1261
 
1262
- TicketFieldsSearchResult = SearchResult[TicketFieldsSearchData]
1262
+ TicketFieldsSearchResult = AirbyteSearchResult[TicketFieldsSearchData]
1263
1263
  """Search result type for ticket_fields entity."""
1264
1264
 
1265
- TicketFormsSearchResult = SearchResult[TicketFormsSearchData]
1265
+ TicketFormsSearchResult = AirbyteSearchResult[TicketFormsSearchData]
1266
1266
  """Search result type for ticket_forms entity."""
1267
1267
 
1268
- TicketMetricsSearchResult = SearchResult[TicketMetricsSearchData]
1268
+ TicketMetricsSearchResult = AirbyteSearchResult[TicketMetricsSearchData]
1269
1269
  """Search result type for ticket_metrics entity."""
1270
1270
 
1271
- TicketsSearchResult = SearchResult[TicketsSearchData]
1271
+ TicketsSearchResult = AirbyteSearchResult[TicketsSearchData]
1272
1272
  """Search result type for tickets entity."""
1273
1273
 
1274
- UsersSearchResult = SearchResult[UsersSearchData]
1274
+ UsersSearchResult = AirbyteSearchResult[UsersSearchData]
1275
1275
  """Search result type for users entity."""
1276
1276
 
1277
1277