airbyte-agent-jira 0.1.22__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.
Files changed (56) hide show
  1. airbyte_agent_jira/__init__.py +91 -0
  2. airbyte_agent_jira/_vendored/__init__.py +1 -0
  3. airbyte_agent_jira/_vendored/connector_sdk/__init__.py +82 -0
  4. airbyte_agent_jira/_vendored/connector_sdk/auth_strategies.py +1123 -0
  5. airbyte_agent_jira/_vendored/connector_sdk/auth_template.py +135 -0
  6. airbyte_agent_jira/_vendored/connector_sdk/cloud_utils/__init__.py +5 -0
  7. airbyte_agent_jira/_vendored/connector_sdk/cloud_utils/client.py +213 -0
  8. airbyte_agent_jira/_vendored/connector_sdk/connector_model_loader.py +965 -0
  9. airbyte_agent_jira/_vendored/connector_sdk/constants.py +78 -0
  10. airbyte_agent_jira/_vendored/connector_sdk/exceptions.py +23 -0
  11. airbyte_agent_jira/_vendored/connector_sdk/executor/__init__.py +31 -0
  12. airbyte_agent_jira/_vendored/connector_sdk/executor/hosted_executor.py +197 -0
  13. airbyte_agent_jira/_vendored/connector_sdk/executor/local_executor.py +1574 -0
  14. airbyte_agent_jira/_vendored/connector_sdk/executor/models.py +190 -0
  15. airbyte_agent_jira/_vendored/connector_sdk/extensions.py +694 -0
  16. airbyte_agent_jira/_vendored/connector_sdk/http/__init__.py +37 -0
  17. airbyte_agent_jira/_vendored/connector_sdk/http/adapters/__init__.py +9 -0
  18. airbyte_agent_jira/_vendored/connector_sdk/http/adapters/httpx_adapter.py +251 -0
  19. airbyte_agent_jira/_vendored/connector_sdk/http/config.py +98 -0
  20. airbyte_agent_jira/_vendored/connector_sdk/http/exceptions.py +119 -0
  21. airbyte_agent_jira/_vendored/connector_sdk/http/protocols.py +114 -0
  22. airbyte_agent_jira/_vendored/connector_sdk/http/response.py +102 -0
  23. airbyte_agent_jira/_vendored/connector_sdk/http_client.py +686 -0
  24. airbyte_agent_jira/_vendored/connector_sdk/introspection.py +262 -0
  25. airbyte_agent_jira/_vendored/connector_sdk/logging/__init__.py +11 -0
  26. airbyte_agent_jira/_vendored/connector_sdk/logging/logger.py +264 -0
  27. airbyte_agent_jira/_vendored/connector_sdk/logging/types.py +92 -0
  28. airbyte_agent_jira/_vendored/connector_sdk/observability/__init__.py +11 -0
  29. airbyte_agent_jira/_vendored/connector_sdk/observability/models.py +19 -0
  30. airbyte_agent_jira/_vendored/connector_sdk/observability/redactor.py +81 -0
  31. airbyte_agent_jira/_vendored/connector_sdk/observability/session.py +94 -0
  32. airbyte_agent_jira/_vendored/connector_sdk/performance/__init__.py +6 -0
  33. airbyte_agent_jira/_vendored/connector_sdk/performance/instrumentation.py +57 -0
  34. airbyte_agent_jira/_vendored/connector_sdk/performance/metrics.py +93 -0
  35. airbyte_agent_jira/_vendored/connector_sdk/schema/__init__.py +75 -0
  36. airbyte_agent_jira/_vendored/connector_sdk/schema/base.py +161 -0
  37. airbyte_agent_jira/_vendored/connector_sdk/schema/components.py +239 -0
  38. airbyte_agent_jira/_vendored/connector_sdk/schema/connector.py +131 -0
  39. airbyte_agent_jira/_vendored/connector_sdk/schema/extensions.py +109 -0
  40. airbyte_agent_jira/_vendored/connector_sdk/schema/operations.py +146 -0
  41. airbyte_agent_jira/_vendored/connector_sdk/schema/security.py +223 -0
  42. airbyte_agent_jira/_vendored/connector_sdk/secrets.py +182 -0
  43. airbyte_agent_jira/_vendored/connector_sdk/telemetry/__init__.py +10 -0
  44. airbyte_agent_jira/_vendored/connector_sdk/telemetry/config.py +32 -0
  45. airbyte_agent_jira/_vendored/connector_sdk/telemetry/events.py +58 -0
  46. airbyte_agent_jira/_vendored/connector_sdk/telemetry/tracker.py +151 -0
  47. airbyte_agent_jira/_vendored/connector_sdk/types.py +245 -0
  48. airbyte_agent_jira/_vendored/connector_sdk/utils.py +60 -0
  49. airbyte_agent_jira/_vendored/connector_sdk/validation.py +822 -0
  50. airbyte_agent_jira/connector.py +978 -0
  51. airbyte_agent_jira/connector_model.py +2827 -0
  52. airbyte_agent_jira/models.py +741 -0
  53. airbyte_agent_jira/types.py +117 -0
  54. airbyte_agent_jira-0.1.22.dist-info/METADATA +113 -0
  55. airbyte_agent_jira-0.1.22.dist-info/RECORD +56 -0
  56. airbyte_agent_jira-0.1.22.dist-info/WHEEL +4 -0
@@ -0,0 +1,239 @@
1
+ """
2
+ Component models for OpenAPI 3.1: Schema, Parameter, RequestBody, Response, Components.
3
+
4
+ References:
5
+ - https://spec.openapis.org/oas/v3.1.0#components-object
6
+ - https://spec.openapis.org/oas/v3.1.0#schema-object
7
+ - https://spec.openapis.org/oas/v3.1.0#parameter-object
8
+ """
9
+
10
+ from typing import Any, Dict, List, Literal, Optional, Union
11
+
12
+ from pydantic import BaseModel, ConfigDict, Field
13
+
14
+ from .security import SecurityScheme
15
+
16
+
17
+ class Schema(BaseModel):
18
+ """
19
+ JSON Schema definition for data models.
20
+
21
+ OpenAPI Reference: https://spec.openapis.org/oas/v3.1.0#schema-object
22
+
23
+ Note: Uses Dict[str, Any] for properties to support nested schemas and $ref.
24
+ Reference resolution happens at runtime in config_loader.py.
25
+
26
+ Extensions:
27
+ - x-airbyte-resource-name: Name of the resource this schema represents (Airbyte extension)
28
+ """
29
+
30
+ model_config = ConfigDict(populate_by_name=True, extra="forbid")
31
+
32
+ # Core JSON Schema fields
33
+ type: Optional[str] = None
34
+ format: Optional[str] = None
35
+ title: Optional[str] = None
36
+ description: Optional[str] = None
37
+ default: Optional[Any] = None
38
+ example: Optional[Any] = None
39
+
40
+ # Object properties
41
+ properties: Dict[str, Any] = Field(default_factory=dict) # May contain $ref
42
+ required: List[str] = Field(default_factory=list)
43
+ additional_properties: Optional[Any] = Field(None, alias="additionalProperties")
44
+
45
+ # Array properties
46
+ items: Optional[Any] = None # May be Schema or $ref
47
+
48
+ # Validation
49
+ enum: Optional[List[Any]] = None
50
+ min_length: Optional[int] = Field(None, alias="minLength")
51
+ max_length: Optional[int] = Field(None, alias="maxLength")
52
+ minimum: Optional[float] = None
53
+ maximum: Optional[float] = None
54
+ pattern: Optional[str] = None
55
+
56
+ # Composition
57
+ all_of: Optional[List[Any]] = Field(None, alias="allOf")
58
+ any_of: Optional[List[Any]] = Field(None, alias="anyOf")
59
+ one_of: Optional[List[Any]] = Field(None, alias="oneOf")
60
+ not_: Optional[Any] = Field(None, alias="not")
61
+
62
+ # Metadata
63
+ nullable: Optional[bool] = Field(None, deprecated="Use type union with null instead (OpenAPI 3.1)")
64
+ read_only: Optional[bool] = Field(None, alias="readOnly")
65
+ write_only: Optional[bool] = Field(None, alias="writeOnly")
66
+ deprecated: Optional[bool] = None
67
+
68
+ # Airbyte extensions
69
+ x_airbyte_entity_name: Optional[str] = Field(None, alias="x-airbyte-entity-name")
70
+ x_airbyte_stream_name: Optional[str] = Field(None, alias="x-airbyte-stream-name")
71
+
72
+
73
+ class Parameter(BaseModel):
74
+ """
75
+ Operation parameter definition.
76
+
77
+ OpenAPI Reference: https://spec.openapis.org/oas/v3.1.0#parameter-object
78
+ """
79
+
80
+ model_config = ConfigDict(populate_by_name=True, extra="forbid")
81
+
82
+ name: str
83
+ in_: Literal["query", "header", "path", "cookie"] = Field(alias="in")
84
+ description: Optional[str] = None
85
+ required: Optional[bool] = None
86
+ deprecated: Optional[bool] = None
87
+ allow_empty_value: Optional[bool] = Field(None, alias="allowEmptyValue")
88
+
89
+ # Schema can be inline or reference
90
+ schema_: Optional[Dict[str, Any]] = Field(None, alias="schema")
91
+
92
+ # Style and examples
93
+ style: Optional[str] = None
94
+ explode: Optional[bool] = None
95
+ example: Optional[Any] = None
96
+ examples: Optional[Dict[str, Any]] = None
97
+
98
+
99
+ class MediaType(BaseModel):
100
+ """
101
+ Media type object for request/response content.
102
+
103
+ OpenAPI Reference: https://spec.openapis.org/oas/v3.1.0#media-type-object
104
+ """
105
+
106
+ model_config = ConfigDict(populate_by_name=True, extra="forbid")
107
+
108
+ schema_: Optional[Dict[str, Any]] = Field(None, alias="schema")
109
+ example: Optional[Any] = None
110
+ examples: Optional[Dict[str, Any]] = None
111
+ encoding: Optional[Dict[str, Any]] = None
112
+
113
+
114
+ class GraphQLBodyConfig(BaseModel):
115
+ """
116
+ GraphQL body type configuration for x-airbyte-body-type extension.
117
+
118
+ Used when x-airbyte-body-type.type = "graphql"
119
+ """
120
+
121
+ model_config = ConfigDict(populate_by_name=True, extra="forbid")
122
+
123
+ type: Literal["graphql"] = Field(..., description="Body type identifier (must be 'graphql')")
124
+ query: str = Field(
125
+ ...,
126
+ description="GraphQL query or mutation string with optional template placeholders (e.g., {{ variable }})",
127
+ )
128
+ variables: Optional[Dict[str, Any]] = Field(
129
+ None,
130
+ description="Variables to substitute in the GraphQL query using template syntax (e.g., {{ param_name }})",
131
+ )
132
+ operationName: Optional[str] = Field(None, description="Operation name for queries with multiple operations")
133
+ default_fields: Optional[Union[str, List[str]]] = Field(
134
+ None,
135
+ description="Default fields to select if not provided in request parameters. Can be a string or array of field names.",
136
+ )
137
+
138
+
139
+ # Union type for all body type configs (extensible for future types like XML, SOAP, etc.)
140
+ BodyTypeConfig = Union[GraphQLBodyConfig]
141
+
142
+
143
+ class PathOverrideConfig(BaseModel):
144
+ """
145
+ Path override configuration for x-airbyte-path-override extension.
146
+
147
+ Used when the OpenAPI path differs from the actual HTTP endpoint path.
148
+ Common for GraphQL APIs where multiple resources share the same endpoint (e.g., /graphql).
149
+
150
+ Example:
151
+ OpenAPI path: /graphql:repositories (for uniqueness)
152
+ Actual HTTP path: /graphql (configured here)
153
+ """
154
+
155
+ model_config = ConfigDict(populate_by_name=True, extra="forbid")
156
+
157
+ path: str = Field(
158
+ ...,
159
+ description=("Actual HTTP path to use for requests (e.g., '/graphql'). " "Must start with '/'"),
160
+ )
161
+
162
+
163
+ class RequestBody(BaseModel):
164
+ """
165
+ Request body definition.
166
+
167
+ OpenAPI Reference: https://spec.openapis.org/oas/v3.1.0#request-body-object
168
+
169
+ Airbyte Extensions:
170
+ See connector_sdk.extensions for documentation:
171
+ - AIRBYTE_BODY_TYPE: Body type and configuration (nested structure)
172
+ """
173
+
174
+ model_config = ConfigDict(populate_by_name=True, extra="forbid")
175
+
176
+ description: Optional[str] = None
177
+ content: Dict[str, MediaType] = Field(default_factory=dict)
178
+ required: Optional[bool] = None
179
+
180
+ # Airbyte extensions for GraphQL support
181
+ # See connector_sdk.extensions for AIRBYTE_BODY_TYPE constant
182
+ x_airbyte_body_type: Optional[BodyTypeConfig] = Field(
183
+ None,
184
+ alias="x-airbyte-body-type", # AIRBYTE_BODY_TYPE
185
+ description=(
186
+ "Body type and configuration. Contains 'type' field (e.g., 'graphql') " "and type-specific configuration (query, variables, etc.)."
187
+ ),
188
+ )
189
+
190
+
191
+ class Header(BaseModel):
192
+ """
193
+ Header definition.
194
+
195
+ OpenAPI Reference: https://spec.openapis.org/oas/v3.1.0#header-object
196
+ """
197
+
198
+ model_config = ConfigDict(populate_by_name=True, extra="forbid")
199
+
200
+ description: Optional[str] = None
201
+ required: Optional[bool] = None
202
+ deprecated: Optional[bool] = None
203
+ schema_: Optional[Dict[str, Any]] = Field(None, alias="schema")
204
+ example: Optional[Any] = None
205
+
206
+
207
+ class Response(BaseModel):
208
+ """
209
+ Response definition.
210
+
211
+ OpenAPI Reference: https://spec.openapis.org/oas/v3.1.0#response-object
212
+ """
213
+
214
+ model_config = ConfigDict(populate_by_name=True, extra="forbid")
215
+
216
+ description: str
217
+ headers: Optional[Dict[str, Header]] = None
218
+ content: Optional[Dict[str, MediaType]] = None
219
+ links: Optional[Dict[str, Any]] = None
220
+
221
+
222
+ class Components(BaseModel):
223
+ """
224
+ Reusable component definitions.
225
+
226
+ OpenAPI Reference: https://spec.openapis.org/oas/v3.1.0#components-object
227
+ """
228
+
229
+ model_config = ConfigDict(populate_by_name=True, extra="forbid")
230
+
231
+ schemas: Dict[str, Schema] = Field(default_factory=dict)
232
+ responses: Dict[str, Response] = Field(default_factory=dict)
233
+ parameters: Dict[str, Parameter] = Field(default_factory=dict)
234
+ examples: Optional[Dict[str, Any]] = None
235
+ request_bodies: Dict[str, RequestBody] = Field(default_factory=dict, alias="requestBodies")
236
+ headers: Optional[Dict[str, Header]] = None
237
+ security_schemes: Dict[str, SecurityScheme] = Field(default_factory=dict, alias="securitySchemes")
238
+ links: Optional[Dict[str, Any]] = None
239
+ callbacks: Optional[Dict[str, Any]] = None
@@ -0,0 +1,131 @@
1
+ """
2
+ Root OpenAPI 3.1 connector specification model.
3
+
4
+ References:
5
+ - https://spec.openapis.org/oas/v3.1.0#openapi-object
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ from typing import Any
11
+
12
+ from pydantic import BaseModel, ConfigDict, Field, field_validator
13
+
14
+ from ..constants import OPENAPI_VERSION_PREFIX
15
+
16
+ from .base import Info, Server
17
+ from .components import Components
18
+ from .operations import PathItem
19
+ from .security import SecurityRequirement
20
+
21
+
22
+ class Tag(BaseModel):
23
+ """
24
+ Tag metadata for grouping operations.
25
+
26
+ OpenAPI Reference: https://spec.openapis.org/oas/v3.1.0#tag-object
27
+ """
28
+
29
+ model_config = ConfigDict(populate_by_name=True, extra="forbid")
30
+
31
+ name: str
32
+ description: str | None = None
33
+ external_docs: dict[str, Any] | None = Field(None, alias="externalDocs")
34
+
35
+
36
+ class ExternalDocs(BaseModel):
37
+ """
38
+ External documentation reference.
39
+
40
+ OpenAPI Reference: https://spec.openapis.org/oas/v3.1.0#external-documentation-object
41
+ """
42
+
43
+ model_config = ConfigDict(populate_by_name=True, extra="forbid")
44
+
45
+ description: str | None = None
46
+ url: str
47
+
48
+
49
+ class OpenAPIConnector(BaseModel):
50
+ """
51
+ Root OpenAPI 3.1 connector specification.
52
+
53
+ OpenAPI Reference: https://spec.openapis.org/oas/v3.1.0#openapi-object
54
+
55
+ This is the top-level model that represents a complete OpenAPI 3.1 specification
56
+ for an Airbyte connector. It enforces strict validation (extra='forbid') to catch
57
+ typos and unknown extensions.
58
+ """
59
+
60
+ model_config = ConfigDict(populate_by_name=True, extra="forbid", validate_default=True)
61
+
62
+ # Required fields
63
+ openapi: str
64
+ info: Info
65
+ paths: dict[str, PathItem] = Field(default_factory=dict)
66
+
67
+ # Optional fields
68
+ servers: list[Server] = Field(default_factory=list)
69
+ components: Components | None = None
70
+ security: list[SecurityRequirement] | None = None
71
+ tags: list[Tag] | None = None
72
+ external_docs: ExternalDocs | None = Field(None, alias="externalDocs")
73
+
74
+ @field_validator("openapi")
75
+ @classmethod
76
+ def validate_openapi_version(cls, v: str) -> str:
77
+ """Validate that OpenAPI version is 3.1.x."""
78
+ if not v.startswith(OPENAPI_VERSION_PREFIX):
79
+ raise ValueError(f"OpenAPI version must be {OPENAPI_VERSION_PREFIX}x, got: {v}")
80
+ return v
81
+
82
+ def get_entity_operations(self, entity_name: str) -> list[tuple[str, str, Any]]:
83
+ """
84
+ Get all operations for a specific entity.
85
+
86
+ Args:
87
+ entity_name: The x-airbyte-entity value to filter by
88
+
89
+ Returns:
90
+ List of tuples: (path, method, operation)
91
+ """
92
+ results = []
93
+ for path, path_item in self.paths.items():
94
+ for method in [
95
+ "get",
96
+ "post",
97
+ "put",
98
+ "patch",
99
+ "delete",
100
+ "options",
101
+ "head",
102
+ "trace",
103
+ ]:
104
+ operation = getattr(path_item, method, None)
105
+ if operation and operation.x_airbyte_entity == entity_name:
106
+ results.append((path, method, operation))
107
+ return results
108
+
109
+ def list_entities(self) -> list[str]:
110
+ """
111
+ List all unique entity names defined in x-airbyte-entity extensions.
112
+
113
+ Returns:
114
+ Sorted list of unique entity names
115
+ """
116
+ entities = set()
117
+ for path_item in self.paths.values():
118
+ for method in [
119
+ "get",
120
+ "post",
121
+ "put",
122
+ "patch",
123
+ "delete",
124
+ "options",
125
+ "head",
126
+ "trace",
127
+ ]:
128
+ operation = getattr(path_item, method, None)
129
+ if operation and operation.x_airbyte_entity:
130
+ entities.add(operation.x_airbyte_entity)
131
+ return sorted(entities)
@@ -0,0 +1,109 @@
1
+ """
2
+ Extension models for future features.
3
+
4
+ These models are defined but NOT yet added to the main schema models.
5
+ They serve as:
6
+ 1. Type hints for future use
7
+ 2. Documentation of planned extensions
8
+ 3. Ready-to-use structures when features are implemented
9
+
10
+ NOTE: These are not currently active in the schema. They will be added
11
+ to Operation, Schema, or other models when their respective features
12
+ are implemented.
13
+ """
14
+
15
+ from typing import Literal, Optional
16
+
17
+ from pydantic import BaseModel, ConfigDict
18
+
19
+
20
+ class PaginationConfig(BaseModel):
21
+ """
22
+ Configuration for pagination support.
23
+
24
+ NOT YET USED - Defined for future implementation.
25
+
26
+ When active, will be added to Operation model as:
27
+ x_pagination: Optional[PaginationConfig] = Field(None, alias="x-pagination")
28
+ """
29
+
30
+ model_config = ConfigDict(populate_by_name=True, extra="forbid")
31
+
32
+ style: Literal["cursor", "offset", "page", "link"]
33
+ limit_param: str = "limit"
34
+
35
+ # Cursor-based pagination
36
+ cursor_param: Optional[str] = None
37
+ cursor_source: Optional[Literal["body", "headers"]] = "body"
38
+ cursor_path: Optional[str] = None
39
+
40
+ # Offset-based pagination
41
+ offset_param: Optional[str] = None
42
+
43
+ # Page-based pagination
44
+ page_param: Optional[str] = None
45
+
46
+ # Response parsing
47
+ data_path: str = "data"
48
+ has_more_path: Optional[str] = None
49
+
50
+ # Limits
51
+ max_page_size: Optional[int] = None
52
+ default_page_size: int = 100
53
+
54
+
55
+ class RateLimitConfig(BaseModel):
56
+ """
57
+ Configuration for rate limiting.
58
+
59
+ NOT YET USED - Defined for future implementation.
60
+
61
+ When active, might be added to Server or root OpenAPIConnector as:
62
+ x_rate_limit: Optional[RateLimitConfig] = Field(None, alias="x-rate-limit")
63
+ """
64
+
65
+ model_config = ConfigDict(populate_by_name=True, extra="forbid")
66
+
67
+ max_requests: int
68
+ time_window_seconds: int
69
+ retry_after_header: Optional[str] = "Retry-After"
70
+ respect_retry_after: bool = True
71
+
72
+
73
+ class RetryConfig(BaseModel):
74
+ """
75
+ Configuration for retry strategy with exponential backoff.
76
+
77
+ Used to configure automatic retries for transient errors (429, 5xx, timeouts, network errors).
78
+ Can be specified at the connector level via x-airbyte-retry-config in the OpenAPI spec's info section.
79
+
80
+ By default, retries are enabled with max_attempts=3. To disable retries, set max_attempts=1
81
+ in your connector's x-airbyte-retry-config.
82
+
83
+ Example YAML usage:
84
+ info:
85
+ title: My API
86
+ x-airbyte-retry-config:
87
+ max_attempts: 5
88
+ initial_delay_seconds: 2.0
89
+ retry_after_header: "X-RateLimit-Reset"
90
+ retry_after_format: "unix_timestamp"
91
+ """
92
+
93
+ model_config = ConfigDict(populate_by_name=True, extra="forbid")
94
+
95
+ # Core retry settings (max_attempts=3 enables retries by default)
96
+ max_attempts: int = 3
97
+ initial_delay_seconds: float = 1.0
98
+ max_delay_seconds: float = 60.0
99
+ exponential_base: float = 2.0
100
+ jitter: bool = True
101
+
102
+ # Which errors to retry
103
+ retry_on_status_codes: list[int] = [429, 500, 502, 503, 504]
104
+ retry_on_timeout: bool = True
105
+ retry_on_network_error: bool = True
106
+
107
+ # Header-based delay extraction
108
+ retry_after_header: str = "Retry-After"
109
+ retry_after_format: Literal["seconds", "milliseconds", "unix_timestamp"] = "seconds"
@@ -0,0 +1,146 @@
1
+ """
2
+ Operation and PathItem models for OpenAPI 3.1.
3
+
4
+ References:
5
+ - https://spec.openapis.org/oas/v3.1.0#operation-object
6
+ - https://spec.openapis.org/oas/v3.1.0#path-item-object
7
+ """
8
+
9
+ from typing import Any, Dict, List, Optional
10
+
11
+ from pydantic import BaseModel, ConfigDict, Field, model_validator
12
+
13
+ from ..extensions import ActionTypeLiteral
14
+ from .components import Parameter, PathOverrideConfig, RequestBody, Response
15
+ from .security import SecurityRequirement
16
+
17
+
18
+ class Operation(BaseModel):
19
+ """
20
+ Single API operation (GET, POST, PUT, PATCH, DELETE, etc.).
21
+
22
+ OpenAPI Reference: https://spec.openapis.org/oas/v3.1.0#operation-object
23
+
24
+ Extensions:
25
+ - x-airbyte-entity: Entity name (Airbyte extension)
26
+ - x-airbyte-action: Semantic action (Airbyte extension)
27
+ - x-airbyte-path-override: Path override (Airbyte extension)
28
+ - x-airbyte-record-extractor: JSONPath to extract records from response (Airbyte extension)
29
+
30
+ Future extensions (not yet active):
31
+ - x-airbyte-pagination: Pagination configuration for list operations
32
+ """
33
+
34
+ model_config = ConfigDict(populate_by_name=True, extra="forbid")
35
+
36
+ # Standard OpenAPI fields
37
+ tags: Optional[List[str]] = None
38
+ summary: Optional[str] = None
39
+ description: Optional[str] = None
40
+ external_docs: Optional[Dict[str, Any]] = Field(None, alias="externalDocs")
41
+ operation_id: Optional[str] = Field(None, alias="operationId")
42
+ parameters: Optional[List[Parameter]] = None
43
+ request_body: Optional[RequestBody] = Field(None, alias="requestBody")
44
+ responses: Dict[str, Response] = Field(default_factory=dict)
45
+ callbacks: Optional[Dict[str, Any]] = None
46
+ deprecated: Optional[bool] = None
47
+ security: Optional[List[SecurityRequirement]] = None
48
+ servers: Optional[List[Any]] = None # Can override root servers
49
+
50
+ # Airbyte extensions
51
+ x_airbyte_entity: str = Field(..., alias="x-airbyte-entity")
52
+ x_airbyte_action: ActionTypeLiteral = Field(..., alias="x-airbyte-action")
53
+ x_airbyte_path_override: Optional[PathOverrideConfig] = Field(
54
+ None,
55
+ alias="x-airbyte-path-override",
56
+ description=("Override path for HTTP requests when OpenAPI path " "differs from actual endpoint"),
57
+ )
58
+ x_airbyte_record_extractor: Optional[str] = Field(
59
+ None,
60
+ alias="x-airbyte-record-extractor",
61
+ description=(
62
+ "JSONPath expression to extract records from API response envelopes. "
63
+ "When specified, executor extracts data at this path instead of returning "
64
+ "full response. Returns array for list/search actions, single record for "
65
+ "get/create/update/delete actions."
66
+ ),
67
+ )
68
+ x_airbyte_meta_extractor: Optional[Dict[str, str]] = Field(
69
+ None,
70
+ alias="x-airbyte-meta-extractor",
71
+ description=(
72
+ "Dictionary mapping field names to JSONPath expressions for extracting "
73
+ "metadata (pagination info, request IDs, etc.) from API response envelopes. "
74
+ "Each key becomes a field in ExecutionResult.meta with the value extracted "
75
+ "using the corresponding JSONPath expression. "
76
+ "Example: {'pagination': '$.pagination', 'request_id': '$.requestId'}"
77
+ ),
78
+ )
79
+ x_airbyte_file_url: Optional[str] = Field(None, alias="x-airbyte-file-url")
80
+ x_airbyte_untested: Optional[bool] = Field(
81
+ None,
82
+ alias="x-airbyte-untested",
83
+ description=(
84
+ "Mark operation as untested to skip cassette validation in readiness checks. "
85
+ "Use this for operations that cannot be recorded (e.g., webhooks, real-time streams). "
86
+ "Validation will generate a warning instead of an error when cassettes are missing."
87
+ ),
88
+ )
89
+
90
+ # Future extensions (commented out, defined for future use)
91
+ # from .extensions import PaginationConfig
92
+ # x_pagination: Optional[PaginationConfig] = Field(None, alias="x-airbyte-pagination")
93
+
94
+ @model_validator(mode="after")
95
+ def validate_download_action_requirements(self) -> "Operation":
96
+ """
97
+ Validate download operation requirements.
98
+
99
+ Rules:
100
+ - If x-airbyte-action is "download":
101
+ - x-airbyte-file-url must be non-empty if provided
102
+ - If x-airbyte-action is not "download":
103
+ - x-airbyte-file-url must not be present
104
+ """
105
+ action = self.x_airbyte_action
106
+ file_url = self.x_airbyte_file_url
107
+
108
+ if action == "download":
109
+ # If file_url is provided, it must be non-empty
110
+ if file_url is not None and not file_url.strip():
111
+ raise ValueError("x-airbyte-file-url must be non-empty when provided for download operations")
112
+ else:
113
+ # Non-download actions cannot have file_url
114
+ if file_url is not None:
115
+ raise ValueError(f"x-airbyte-file-url can only be used with x-airbyte-action: download, but action is '{action}'")
116
+
117
+ return self
118
+
119
+
120
+ class PathItem(BaseModel):
121
+ """
122
+ Path item containing operations for different HTTP methods.
123
+
124
+ OpenAPI Reference: https://spec.openapis.org/oas/v3.1.0#path-item-object
125
+ """
126
+
127
+ model_config = ConfigDict(populate_by_name=True, extra="forbid")
128
+
129
+ # Common fields for all operations
130
+ summary: Optional[str] = None
131
+ description: Optional[str] = None
132
+ servers: Optional[List[Any]] = None
133
+ parameters: Optional[List[Parameter]] = None
134
+
135
+ # HTTP methods (all optional)
136
+ get: Optional[Operation] = None
137
+ put: Optional[Operation] = None
138
+ post: Optional[Operation] = None
139
+ delete: Optional[Operation] = None
140
+ options: Optional[Operation] = None
141
+ head: Optional[Operation] = None
142
+ patch: Optional[Operation] = None
143
+ trace: Optional[Operation] = None
144
+
145
+ # Reference support
146
+ ref: Optional[str] = Field(None, alias="$ref")