airbyte-agent-zendesk-support 0.18.78__tar.gz → 0.18.80__tar.gz

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.
Files changed (62) hide show
  1. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/AUTH.md +53 -0
  2. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/CHANGELOG.md +10 -0
  3. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/PKG-INFO +3 -3
  4. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/README.md +2 -2
  5. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/connector_model_loader.py +0 -5
  6. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/executor/local_executor.py +16 -20
  7. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/schema/__init__.py +0 -2
  8. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/schema/base.py +32 -1
  9. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/schema/extensions.py +41 -3
  10. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/schema/operations.py +3 -2
  11. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/schema/security.py +33 -41
  12. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/types.py +1 -1
  13. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/validation.py +1 -1
  14. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/pyproject.toml +1 -1
  15. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/.gitignore +0 -0
  16. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/REFERENCE.md +0 -0
  17. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/__init__.py +0 -0
  18. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/__init__.py +0 -0
  19. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/__init__.py +0 -0
  20. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/auth_strategies.py +0 -0
  21. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/auth_template.py +0 -0
  22. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/cloud_utils/__init__.py +0 -0
  23. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/cloud_utils/client.py +0 -0
  24. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/constants.py +0 -0
  25. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/exceptions.py +0 -0
  26. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/executor/__init__.py +0 -0
  27. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/executor/hosted_executor.py +0 -0
  28. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/executor/models.py +0 -0
  29. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/extensions.py +0 -0
  30. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/http/__init__.py +0 -0
  31. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/http/adapters/__init__.py +0 -0
  32. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/http/adapters/httpx_adapter.py +0 -0
  33. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/http/config.py +0 -0
  34. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/http/exceptions.py +0 -0
  35. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/http/protocols.py +0 -0
  36. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/http/response.py +0 -0
  37. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/http_client.py +0 -0
  38. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/introspection.py +0 -0
  39. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/logging/__init__.py +0 -0
  40. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/logging/logger.py +0 -0
  41. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/logging/types.py +0 -0
  42. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/observability/__init__.py +0 -0
  43. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/observability/config.py +0 -0
  44. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/observability/models.py +0 -0
  45. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/observability/redactor.py +0 -0
  46. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/observability/session.py +0 -0
  47. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/performance/__init__.py +0 -0
  48. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/performance/instrumentation.py +0 -0
  49. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/performance/metrics.py +0 -0
  50. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/schema/components.py +0 -0
  51. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/schema/connector.py +0 -0
  52. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/secrets.py +0 -0
  53. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/telemetry/__init__.py +0 -0
  54. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/telemetry/config.py +0 -0
  55. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/telemetry/events.py +0 -0
  56. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/telemetry/tracker.py +0 -0
  57. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/utils.py +0 -0
  58. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/_vendored/connector_sdk/validation_replication.py +0 -0
  59. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/connector.py +0 -0
  60. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/connector_model.py +0 -0
  61. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/models.py +0 -0
  62. {airbyte_agent_zendesk_support-0.18.78 → airbyte_agent_zendesk_support-0.18.80}/airbyte_agent_zendesk_support/types.py +0 -0
@@ -87,6 +87,59 @@ curl -X POST "https://api.airbyte.ai/v1/integrations/connectors" \
87
87
  }'
88
88
  ```
89
89
 
90
+
91
+
92
+ #### Bring your own OAuth flow
93
+ To implement your own OAuth flow, use Airbyte's server-side OAuth API endpoints. For a complete guide, see [Implement your own OAuth flow](https://docs.airbyte.com/ai-agents/quickstarts/tutorial-server-side-oauth).
94
+
95
+ **Step 1: Initiate the OAuth flow**
96
+
97
+ Request a consent URL for your user.
98
+
99
+ | Field Name | Type | Required | Description |
100
+ |------------|------|----------|-------------|
101
+ | `external_user_id` | `string` | Yes | Your unique identifier for the end user |
102
+ | `connector_type` | `string` | Yes | The connector type (e.g., "Zendesk-Support") |
103
+ | `redirect_url` | `string` | Yes | URL to redirect to after OAuth authorization |
104
+
105
+ Example request:
106
+
107
+ ```bash
108
+ curl -X POST "https://api.airbyte.ai/v1/integrations/connectors/oauth/initiate" \
109
+ -H "Authorization: Bearer <BEARER_TOKEN>" \
110
+ -H "Content-Type: application/json" \
111
+ -d '{
112
+ "external_user_id": "<EXTERNAL_USER_ID>",
113
+ "connector_type": "Zendesk-Support",
114
+ "redirect_url": "https://yourapp.com/oauth/callback"
115
+ }'
116
+ ```
117
+
118
+ Redirect your user to the `consent_url` from the response. After they authorize, they'll be redirected back to your app with a `secret_id` query parameter.
119
+
120
+ **Step 2: Create a connector with the secret ID**
121
+
122
+ | Field Name | Type | Required | Description |
123
+ |------------|------|----------|-------------|
124
+ | `external_user_id` | `string` | Yes | Your unique identifier for the end user |
125
+ | `connector_type` | `string` | Yes | The connector type (e.g., "Zendesk-Support") |
126
+ | `name` | `string` | Yes | A name for this connector instance |
127
+ | `server_side_oauth_secret_id` | `string` | Yes | The secret_id from the OAuth callback |
128
+
129
+ Example request:
130
+
131
+ ```bash
132
+ curl -X POST "https://api.airbyte.ai/v1/integrations/connectors" \
133
+ -H "Authorization: Bearer <BEARER_TOKEN>" \
134
+ -H "Content-Type: application/json" \
135
+ -d '{
136
+ "external_user_id": "<EXTERNAL_USER_ID>",
137
+ "connector_type": "Zendesk-Support",
138
+ "name": "My Zendesk-Support Connector",
139
+ "server_side_oauth_secret_id": "<secret_id_from_callback>"
140
+ }'
141
+ ```
142
+
90
143
  #### Token
91
144
  Create a connector with Token credentials.
92
145
 
@@ -1,5 +1,15 @@
1
1
  # Zendesk Support changelog
2
2
 
3
+ ## [0.18.80] - 2026-02-03
4
+ - Updated connector definition (YAML version 0.1.11)
5
+ - Source commit: 5c6dbf88
6
+ - SDK version: 0.1.0
7
+
8
+ ## [0.18.79] - 2026-02-02
9
+ - Updated connector definition (YAML version 0.1.11)
10
+ - Source commit: 94024675
11
+ - SDK version: 0.1.0
12
+
3
13
  ## [0.18.78] - 2026-02-02
4
14
  - Updated connector definition (YAML version 0.1.11)
5
15
  - Source commit: 9d9866b0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: airbyte-agent-zendesk-support
3
- Version: 0.18.78
3
+ Version: 0.18.80
4
4
  Summary: Airbyte Zendesk-Support Connector for AI platforms
5
5
  Project-URL: Homepage, https://github.com/airbytehq/airbyte-agent-connectors
6
6
  Project-URL: Documentation, https://docs.airbyte.com/ai-agents/
@@ -157,7 +157,7 @@ See the official [Zendesk-Support API reference](https://developer.zendesk.com/a
157
157
 
158
158
  ## Version information
159
159
 
160
- - **Package version:** 0.18.78
160
+ - **Package version:** 0.18.80
161
161
  - **Connector version:** 0.1.11
162
- - **Generated with Connector SDK commit SHA:** 9d9866b0aae8c3494d04d34e193b9bd860bfc1c6
162
+ - **Generated with Connector SDK commit SHA:** 5c6dbf883d3b057550333775bd83a78777527017
163
163
  - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/zendesk-support/CHANGELOG.md)
@@ -124,7 +124,7 @@ See the official [Zendesk-Support API reference](https://developer.zendesk.com/a
124
124
 
125
125
  ## Version information
126
126
 
127
- - **Package version:** 0.18.78
127
+ - **Package version:** 0.18.80
128
128
  - **Connector version:** 0.1.11
129
- - **Generated with Connector SDK commit SHA:** 9d9866b0aae8c3494d04d34e193b9bd860bfc1c6
129
+ - **Generated with Connector SDK commit SHA:** 5c6dbf883d3b057550333775bd83a78777527017
130
130
  - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/zendesk-support/CHANGELOG.md)
@@ -766,7 +766,6 @@ def _generate_default_auth_config(auth_type: AuthType) -> AirbyteAuthConfig:
766
766
  )
767
767
  },
768
768
  auth_mapping={"token": "${token}"},
769
- oneOf=None,
770
769
  )
771
770
  elif auth_type == AuthType.BASIC:
772
771
  return AirbyteAuthConfig(
@@ -793,7 +792,6 @@ def _generate_default_auth_config(auth_type: AuthType) -> AirbyteAuthConfig:
793
792
  ),
794
793
  },
795
794
  auth_mapping={"username": "${username}", "password": "${password}"},
796
- oneOf=None,
797
795
  )
798
796
  elif auth_type == AuthType.API_KEY:
799
797
  return AirbyteAuthConfig(
@@ -812,7 +810,6 @@ def _generate_default_auth_config(auth_type: AuthType) -> AirbyteAuthConfig:
812
810
  )
813
811
  },
814
812
  auth_mapping={"api_key": "${api_key}"},
815
- oneOf=None,
816
813
  )
817
814
  elif auth_type == AuthType.OAUTH2:
818
815
  # OAuth2: No fields are strictly required to support both modes:
@@ -865,7 +862,6 @@ def _generate_default_auth_config(auth_type: AuthType) -> AirbyteAuthConfig:
865
862
  "client_id": "${client_id}",
866
863
  "client_secret": "${client_secret}",
867
864
  },
868
- oneOf=None,
869
865
  )
870
866
  else:
871
867
  # Unknown auth type - return minimal config
@@ -876,7 +872,6 @@ def _generate_default_auth_config(auth_type: AuthType) -> AirbyteAuthConfig:
876
872
  required=None,
877
873
  properties={},
878
874
  auth_mapping={},
879
- oneOf=None,
880
875
  )
881
876
 
882
877
 
@@ -261,19 +261,10 @@ class LocalExecutor:
261
261
  auth_mapping = None
262
262
  required_fields: list[str] | None = None
263
263
 
264
- # Check for single option (direct auth_mapping)
264
+ # Get auth_mapping from the config
265
265
  if user_config_spec.auth_mapping:
266
266
  auth_mapping = user_config_spec.auth_mapping
267
267
  required_fields = user_config_spec.required
268
- # Check for oneOf (multiple auth options)
269
- elif user_config_spec.one_of:
270
- # Find the matching option based on which required fields are present
271
- for option in user_config_spec.one_of:
272
- option_required = option.required or []
273
- if all(field in user_secrets for field in option_required):
274
- auth_mapping = option.auth_mapping
275
- required_fields = option_required
276
- break
277
268
 
278
269
  if not auth_mapping:
279
270
  # No matching auth_mapping found, use secrets as-is
@@ -546,23 +537,25 @@ class LocalExecutor:
546
537
  return ExecutionResult(success=False, data={}, error=str(e))
547
538
 
548
539
  async def check(self) -> ExecutionResult:
549
- """Perform a health check by running a lightweight list operation.
540
+ """Perform a health check by running a lightweight operation.
550
541
 
551
542
  Finds the operation marked with preferred_for_check=True, or falls back
552
- to the first list operation. Executes it with limit=1 to verify
553
- connectivity and credentials.
543
+ to the first list operation. Executes it to verify connectivity and credentials.
544
+ For list operations, uses limit=1 to minimize data transfer.
554
545
 
555
546
  Returns:
556
547
  ExecutionResult with data containing status, error, and checked operation details.
557
548
  """
558
549
  check_entity = None
559
550
  check_endpoint = None
551
+ check_action = None
560
552
 
561
- # Look for preferred check operation
553
+ # Look for preferred check operation (can be any action type)
562
554
  for (ent_name, op_action), endpoint in self._operation_index.items():
563
555
  if getattr(endpoint, "preferred_for_check", False):
564
556
  check_entity = ent_name
565
557
  check_endpoint = endpoint
558
+ check_action = op_action
566
559
  break
567
560
 
568
561
  # Fallback to first list operation
@@ -571,18 +564,19 @@ class LocalExecutor:
571
564
  if op_action == Action.LIST:
572
565
  check_entity = ent_name
573
566
  check_endpoint = endpoint
567
+ check_action = op_action
574
568
  break
575
569
 
576
- if check_endpoint is None or check_entity is None:
570
+ if check_endpoint is None or check_entity is None or check_action is None:
577
571
  return ExecutionResult(
578
572
  success=True,
579
573
  data={
580
574
  "status": "skipped",
581
- "error": "No list operation available for health check",
575
+ "error": "No operation available for health check",
582
576
  },
583
577
  )
584
578
 
585
- # Find the standard handler to execute the list operation
579
+ # Find the standard handler to execute the operation
586
580
  standard_handler = next(
587
581
  (h for h in self._operation_handlers if isinstance(h, _StandardOperationHandler)),
588
582
  None,
@@ -598,13 +592,15 @@ class LocalExecutor:
598
592
  )
599
593
 
600
594
  try:
601
- await standard_handler.execute_operation(check_entity, Action.LIST, {"limit": 1})
595
+ # Use limit=1 for list operations to minimize data transfer
596
+ params = {"limit": 1} if check_action == Action.LIST else {}
597
+ await standard_handler.execute_operation(check_entity, check_action, params)
602
598
  return ExecutionResult(
603
599
  success=True,
604
600
  data={
605
601
  "status": "healthy",
606
602
  "checked_entity": check_entity,
607
- "checked_action": "list",
603
+ "checked_action": check_action.value,
608
604
  },
609
605
  )
610
606
  except Exception as e:
@@ -614,7 +610,7 @@ class LocalExecutor:
614
610
  "status": "unhealthy",
615
611
  "error": str(e),
616
612
  "checked_entity": check_entity,
617
- "checked_action": "list",
613
+ "checked_action": check_action.value,
618
614
  },
619
615
  error=str(e),
620
616
  )
@@ -31,7 +31,6 @@ from .operations import Operation, PathItem
31
31
  from .security import (
32
32
  AirbyteAuthConfig,
33
33
  AuthConfigFieldSpec,
34
- AuthConfigOption,
35
34
  OAuth2Flow,
36
35
  OAuth2Flows,
37
36
  SecurityRequirement,
@@ -55,7 +54,6 @@ __all__ = [
55
54
  "OAuth2Flow",
56
55
  "OAuth2Flows",
57
56
  "AirbyteAuthConfig",
58
- "AuthConfigOption",
59
57
  "AuthConfigFieldSpec",
60
58
  # Component models
61
59
  "Components",
@@ -10,7 +10,7 @@ from enum import StrEnum
10
10
  from typing import Any, Dict
11
11
  from uuid import UUID
12
12
 
13
- from pydantic import BaseModel, ConfigDict, Field, field_validator
13
+ from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
14
14
  from pydantic_core import Url
15
15
 
16
16
  from .extensions import CacheConfig, ReplicationConfig, RetryConfig
@@ -210,3 +210,34 @@ class Server(BaseModel):
210
210
  raise ValueError("Server URL cannot be empty")
211
211
  # Allow both absolute URLs and relative paths
212
212
  return v
213
+
214
+ @model_validator(mode="after")
215
+ def validate_replication_environment_mapping(self) -> "Server":
216
+ """Validate that x-airbyte-replication-environment-mapping sources exist in variables.
217
+
218
+ For simple mappings like {"subdomain": "subdomain"}, the key is the source variable.
219
+ For transform mappings like {"domain": {"source": "subdomain", "format": "..."}},
220
+ the "source" field is the source variable.
221
+ """
222
+ env_mapping = self.x_airbyte_replication_environment_mapping
223
+ if not env_mapping or not self.variables:
224
+ return self
225
+
226
+ variable_names = set(self.variables.keys())
227
+
228
+ for env_key, mapping_value in env_mapping.items():
229
+ if isinstance(mapping_value, str):
230
+ source_var = env_key
231
+ elif isinstance(mapping_value, EnvironmentMappingTransform):
232
+ source_var = mapping_value.source
233
+ else:
234
+ continue
235
+
236
+ if source_var not in variable_names:
237
+ available = ", ".join(sorted(variable_names)) if variable_names else "(none)"
238
+ raise ValueError(
239
+ f"x-airbyte-replication-environment-mapping: source variable '{source_var}' "
240
+ f"not found in server variables. Available: {available}"
241
+ )
242
+
243
+ return self
@@ -14,7 +14,7 @@ are implemented.
14
14
 
15
15
  from typing import Literal
16
16
 
17
- from pydantic import BaseModel, ConfigDict, Field
17
+ from pydantic import BaseModel, ConfigDict, Field, model_validator
18
18
 
19
19
 
20
20
  class PaginationConfig(BaseModel):
@@ -182,12 +182,25 @@ class CacheEntityConfig(BaseModel):
182
182
  return self.x_airbyte_name or self.entity
183
183
 
184
184
 
185
+ class ReplicationConfigPropertyItems(BaseModel):
186
+ """
187
+ Items definition for array-type replication configuration fields.
188
+
189
+ Defines the schema for items in an array-type replication config property.
190
+ """
191
+
192
+ model_config = ConfigDict(populate_by_name=True, extra="forbid")
193
+
194
+ type: str
195
+
196
+
185
197
  class ReplicationConfigProperty(BaseModel):
186
198
  """
187
199
  Property definition for replication configuration fields.
188
200
 
189
201
  Defines a single field in the replication configuration with its type,
190
- description, and optional default value.
202
+ description, and optional default value. Supports both simple types
203
+ (string, integer, boolean) and array types.
191
204
 
192
205
  Example YAML usage:
193
206
  x-airbyte-replication-config:
@@ -197,6 +210,12 @@ class ReplicationConfigProperty(BaseModel):
197
210
  title: Start Date
198
211
  description: UTC date and time from which to replicate data
199
212
  format: date-time
213
+ account_ids:
214
+ type: array
215
+ title: Account IDs
216
+ description: List of account IDs to replicate
217
+ items:
218
+ type: string
200
219
  """
201
220
 
202
221
  model_config = ConfigDict(populate_by_name=True, extra="forbid")
@@ -205,8 +224,9 @@ class ReplicationConfigProperty(BaseModel):
205
224
  title: str | None = None
206
225
  description: str | None = None
207
226
  format: str | None = None
208
- default: str | int | float | bool | None = None
227
+ default: str | int | float | bool | list | None = None
209
228
  enum: list[str] | None = None
229
+ items: ReplicationConfigPropertyItems | None = None
210
230
 
211
231
 
212
232
  class ReplicationConfig(BaseModel):
@@ -252,6 +272,24 @@ class ReplicationConfig(BaseModel):
252
272
  description="Mapping from replication_config field names to source_config field names",
253
273
  )
254
274
 
275
+ @model_validator(mode="after")
276
+ def validate_replication_config_key_mapping(self) -> "ReplicationConfig":
277
+ """Validate that replication_config_key_mapping keys exist in properties.
278
+
279
+ The mapping is: {local_key: airbyte_path}
280
+ We validate that local_key exists in our properties.
281
+ """
282
+ if self.replication_config_key_mapping and self.properties:
283
+ property_names = set(self.properties.keys())
284
+ for local_key, airbyte_path in self.replication_config_key_mapping.items():
285
+ if local_key not in property_names:
286
+ available = ", ".join(sorted(property_names)) if property_names else "(none)"
287
+ raise ValueError(
288
+ f"replication_config_key_mapping: local key '{local_key}' "
289
+ f"(mapped to '{airbyte_path}') not found in properties. Available: {available}"
290
+ )
291
+ return self
292
+
255
293
 
256
294
  class CacheConfig(BaseModel):
257
295
  """
@@ -90,9 +90,10 @@ class Operation(BaseModel):
90
90
  None,
91
91
  alias="x-airbyte-preferred-for-check",
92
92
  description=(
93
- "Mark this list operation as the preferred operation for health checks. "
93
+ "Mark this operation as the preferred operation for health checks. "
94
94
  "When the CHECK action is executed, this operation will be used instead of "
95
- "falling back to the first available list operation. Choose a lightweight, "
95
+ "falling back to the first available list operation. The operation's actual "
96
+ "action type (get, list, etc.) will be respected. Choose a lightweight, "
96
97
  "always-available endpoint (e.g., users, accounts)."
97
98
  ),
98
99
  )
@@ -58,30 +58,6 @@ class AuthConfigFieldSpec(BaseModel):
58
58
  default: Any | None = None
59
59
 
60
60
 
61
- class AuthConfigOption(BaseModel):
62
- """
63
- A single authentication configuration option.
64
-
65
- Defines user-facing fields and how they map to auth parameters.
66
- """
67
-
68
- model_config = ConfigDict(populate_by_name=True, extra="forbid")
69
-
70
- title: str | None = None
71
- description: str | None = None
72
- type: Literal["object"] = "object"
73
- required: List[str] = Field(default_factory=list)
74
- properties: Dict[str, AuthConfigFieldSpec] = Field(default_factory=dict)
75
- auth_mapping: Dict[str, str] = Field(
76
- default_factory=dict,
77
- description="Mapping from auth parameters (e.g., 'username', 'password', 'token') to template strings using ${field} syntax",
78
- )
79
- replication_auth_key_mapping: Dict[str, str] | None = Field(
80
- None,
81
- description="Mapping from source config paths (e.g., 'credentials.api_key') to auth config keys for direct connectors",
82
- )
83
-
84
-
85
61
  class AirbyteAuthConfig(BaseModel):
86
62
  """
87
63
  Airbyte auth configuration extension (x-airbyte-auth-config).
@@ -89,12 +65,12 @@ class AirbyteAuthConfig(BaseModel):
89
65
  Defines user-facing authentication configuration and how it maps to
90
66
  the underlying OpenAPI security scheme.
91
67
 
92
- Either a single auth option or multiple options via oneOf.
68
+ For multiple authentication methods, define separate security schemes
69
+ rather than using oneOf within a single scheme.
93
70
  """
94
71
 
95
72
  model_config = ConfigDict(populate_by_name=True, extra="forbid")
96
73
 
97
- # Single option fields
98
74
  title: str | None = None
99
75
  description: str | None = None
100
76
  type: Literal["object"] | None = None
@@ -122,32 +98,48 @@ class AirbyteAuthConfig(BaseModel):
122
98
  None,
123
99
  description="Constant values to always inject at source config paths (e.g., 'credentials.auth_type': 'OAuth2.0')",
124
100
  )
125
- # Multiple options (oneOf)
126
- one_of: List[AuthConfigOption] | None = Field(None, alias="oneOf")
127
101
 
128
102
  @model_validator(mode="after")
129
103
  def validate_config_structure(self) -> "AirbyteAuthConfig":
130
- """Validate that either single option or oneOf is provided, not both."""
131
- has_single = self.type is not None or self.properties is not None or self.auth_mapping is not None
132
- has_one_of = self.one_of is not None and len(self.one_of) > 0
133
-
134
- if not has_single and not has_one_of:
135
- raise ValueError("Either single auth option (type/properties/auth_mapping) or oneOf must be provided")
104
+ """Validate that required fields are provided for auth config."""
105
+ has_config = self.type is not None or self.properties is not None or self.auth_mapping is not None
136
106
 
137
- if has_single and has_one_of:
138
- raise ValueError("Cannot have both single auth option and oneOf")
107
+ if not has_config:
108
+ raise ValueError("Auth config must have type, properties, and auth_mapping")
139
109
 
140
- if has_single:
141
- # Validate single option has required fields
110
+ if has_config:
111
+ # Validate required fields
142
112
  if self.type != "object":
143
- raise ValueError("Single auth option must have type='object'")
113
+ raise ValueError("Auth config must have type='object'")
144
114
  if not self.properties:
145
- raise ValueError("Single auth option must have properties")
115
+ raise ValueError("Auth config must have properties")
146
116
  if not self.auth_mapping:
147
- raise ValueError("Single auth option must have auth_mapping")
117
+ raise ValueError("Auth config must have auth_mapping")
118
+
119
+ # Validate replication_auth_key_mapping targets exist in properties
120
+ if self.replication_auth_key_mapping and self.properties:
121
+ self._validate_replication_auth_key_mapping(self.replication_auth_key_mapping, self.properties, context="x-airbyte-auth-config")
148
122
 
149
123
  return self
150
124
 
125
+ @staticmethod
126
+ def _validate_replication_auth_key_mapping(mapping: Dict[str, str], properties: Dict[str, AuthConfigFieldSpec], context: str) -> None:
127
+ """Validate that replication_auth_key_mapping target keys exist in properties.
128
+
129
+ Args:
130
+ mapping: The replication_auth_key_mapping dict (airbyte_path -> our_key)
131
+ properties: The properties dict from x-airbyte-auth-config
132
+ context: Context string for error messages
133
+ """
134
+ property_names = set(properties.keys())
135
+ for airbyte_path, our_key in mapping.items():
136
+ if our_key not in property_names:
137
+ available = ", ".join(sorted(property_names)) if property_names else "(none)"
138
+ raise ValueError(
139
+ f"replication_auth_key_mapping in {context}: target key '{our_key}' "
140
+ f"(mapped from '{airbyte_path}') not found in properties. Available: {available}"
141
+ )
142
+
151
143
 
152
144
  class SecurityScheme(BaseModel):
153
145
  """
@@ -239,7 +239,7 @@ class EndpointDefinition(BaseModel):
239
239
  # Health check support (Airbyte extension)
240
240
  preferred_for_check: bool = Field(
241
241
  False,
242
- description="Mark this list operation as preferred for health checks (from x-airbyte-preferred-for-check extension)",
242
+ description="Mark this operation as preferred for health checks (from x-airbyte-preferred-for-check extension)",
243
243
  )
244
244
 
245
245
 
@@ -959,7 +959,7 @@ def validate_connector_readiness(connector_dir: str | Path) -> Dict[str, Any]:
959
959
  if not has_preferred_check:
960
960
  readiness_warnings.append(
961
961
  "No operation has x-airbyte-preferred-for-check: true. "
962
- "Add this extension to a lightweight list operation (e.g., users.list) "
962
+ "Add this extension to a lightweight operation (e.g., users.list or accounts.get) "
963
963
  "to enable reliable health checks."
964
964
  )
965
965
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "airbyte-agent-zendesk-support"
3
- version = "0.18.78"
3
+ version = "0.18.80"
4
4
  description = "Airbyte Zendesk-Support Connector for AI platforms"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.13"