airbyte-agent-zendesk-support 0.18.27__tar.gz → 0.18.29__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.
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/CHANGELOG.md +10 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/PKG-INFO +8 -8
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/README.md +7 -7
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/connector_sdk/__init__.py +3 -0
- airbyte_agent_zendesk_support-0.18.29/airbyte_agent_zendesk_support/_vendored/connector_sdk/decorators.py +128 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/connector_sdk/executor/local_executor.py +12 -21
- airbyte_agent_zendesk_support-0.18.29/airbyte_agent_zendesk_support/_vendored/connector_sdk/introspection.py +262 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/connector.py +47 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/pyproject.toml +1 -1
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/.gitignore +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/REFERENCE.md +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/__init__.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/__init__.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/connector_sdk/auth_strategies.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/connector_sdk/auth_template.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/connector_sdk/cloud_utils/__init__.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/connector_sdk/cloud_utils/client.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/connector_sdk/connector_model_loader.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/connector_sdk/constants.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/connector_sdk/exceptions.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/connector_sdk/executor/__init__.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/connector_sdk/executor/hosted_executor.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/connector_sdk/executor/models.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/connector_sdk/extensions.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/connector_sdk/http/__init__.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/connector_sdk/http/adapters/__init__.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/connector_sdk/http/adapters/httpx_adapter.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/connector_sdk/http/config.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/connector_sdk/http/exceptions.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/connector_sdk/http/protocols.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/connector_sdk/http/response.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/connector_sdk/http_client.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/connector_sdk/logging/__init__.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/connector_sdk/logging/logger.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/connector_sdk/logging/types.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/connector_sdk/observability/__init__.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/connector_sdk/observability/models.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/connector_sdk/observability/redactor.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/connector_sdk/observability/session.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/connector_sdk/performance/__init__.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/connector_sdk/performance/instrumentation.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/connector_sdk/performance/metrics.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/connector_sdk/schema/__init__.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/connector_sdk/schema/base.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/connector_sdk/schema/components.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/connector_sdk/schema/connector.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/connector_sdk/schema/extensions.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/connector_sdk/schema/operations.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/connector_sdk/schema/security.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/connector_sdk/secrets.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/connector_sdk/telemetry/__init__.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/connector_sdk/telemetry/config.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/connector_sdk/telemetry/events.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/connector_sdk/telemetry/tracker.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/connector_sdk/types.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/connector_sdk/utils.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/_vendored/connector_sdk/validation.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/connector_model.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/models.py +0 -0
- {airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/airbyte_agent_zendesk_support/types.py +0 -0
{airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/CHANGELOG.md
RENAMED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Zendesk Support changelog
|
|
2
2
|
|
|
3
|
+
## [0.18.29] - 2026-01-07
|
|
4
|
+
- Updated connector definition (YAML version 0.1.4)
|
|
5
|
+
- Source commit: d023e05f
|
|
6
|
+
- SDK version: 0.1.0
|
|
7
|
+
|
|
8
|
+
## [0.18.28] - 2026-01-06
|
|
9
|
+
- Updated connector definition (YAML version 0.1.4)
|
|
10
|
+
- Source commit: 0580c727
|
|
11
|
+
- SDK version: 0.1.0
|
|
12
|
+
|
|
3
13
|
## [0.18.27] - 2026-01-06
|
|
4
14
|
- Updated connector definition (YAML version 0.1.4)
|
|
5
15
|
- Source commit: e0e2f989
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: airbyte-agent-zendesk-support
|
|
3
|
-
Version: 0.18.
|
|
3
|
+
Version: 0.18.29
|
|
4
4
|
Summary: Airbyte Zendesk-Support Connector for AI platforms
|
|
5
5
|
Project-URL: Homepage, https://github.com/airbytehq/airbyte-embedded
|
|
6
6
|
Project-URL: Documentation, https://github.com/airbytehq/airbyte-embedded/tree/main/integrations
|
|
@@ -47,10 +47,10 @@ The Zendesk-Support connector is optimized to handle prompts like these.
|
|
|
47
47
|
|
|
48
48
|
- Show me the tickets assigned to me last week
|
|
49
49
|
- What are the top 5 support issues our organization has faced this month?
|
|
50
|
-
- List all unresolved tickets for {customer}
|
|
50
|
+
- List all unresolved tickets for \{customer\}
|
|
51
51
|
- Analyze the satisfaction ratings for our support team in the last 30 days
|
|
52
52
|
- Compare ticket resolution times across different support groups
|
|
53
|
-
- Show me the details of recent tickets tagged with {tag}
|
|
53
|
+
- Show me the details of recent tickets tagged with \{tag\}
|
|
54
54
|
- Identify the most common ticket fields used in our support workflow
|
|
55
55
|
- Summarize the performance of our SLA policies this quarter
|
|
56
56
|
|
|
@@ -58,11 +58,11 @@ The Zendesk-Support connector is optimized to handle prompts like these.
|
|
|
58
58
|
|
|
59
59
|
The Zendesk-Support connector isn't currently able to handle prompts like these.
|
|
60
60
|
|
|
61
|
-
- Create a new support ticket for {customer}
|
|
61
|
+
- Create a new support ticket for \{customer\}
|
|
62
62
|
- Update the priority of this ticket
|
|
63
|
-
- Assign this ticket to {team_member}
|
|
63
|
+
- Assign this ticket to \{team_member\}
|
|
64
64
|
- Delete these old support tickets
|
|
65
|
-
- Send an automatic response to {customer}
|
|
65
|
+
- Send an automatic response to \{customer\}
|
|
66
66
|
|
|
67
67
|
## Installation
|
|
68
68
|
|
|
@@ -141,6 +141,6 @@ For the service's official API docs, see the [Zendesk-Support API reference](htt
|
|
|
141
141
|
|
|
142
142
|
## Version information
|
|
143
143
|
|
|
144
|
-
- **Package version:** 0.18.
|
|
144
|
+
- **Package version:** 0.18.29
|
|
145
145
|
- **Connector version:** 0.1.4
|
|
146
|
-
- **Generated with Connector SDK commit SHA:**
|
|
146
|
+
- **Generated with Connector SDK commit SHA:** d023e05f2b7a1ddabf81fab7640c64de1e0aa6a1
|
|
@@ -13,10 +13,10 @@ The Zendesk-Support connector is optimized to handle prompts like these.
|
|
|
13
13
|
|
|
14
14
|
- Show me the tickets assigned to me last week
|
|
15
15
|
- What are the top 5 support issues our organization has faced this month?
|
|
16
|
-
- List all unresolved tickets for {customer}
|
|
16
|
+
- List all unresolved tickets for \{customer\}
|
|
17
17
|
- Analyze the satisfaction ratings for our support team in the last 30 days
|
|
18
18
|
- Compare ticket resolution times across different support groups
|
|
19
|
-
- Show me the details of recent tickets tagged with {tag}
|
|
19
|
+
- Show me the details of recent tickets tagged with \{tag\}
|
|
20
20
|
- Identify the most common ticket fields used in our support workflow
|
|
21
21
|
- Summarize the performance of our SLA policies this quarter
|
|
22
22
|
|
|
@@ -24,11 +24,11 @@ The Zendesk-Support connector is optimized to handle prompts like these.
|
|
|
24
24
|
|
|
25
25
|
The Zendesk-Support connector isn't currently able to handle prompts like these.
|
|
26
26
|
|
|
27
|
-
- Create a new support ticket for {customer}
|
|
27
|
+
- Create a new support ticket for \{customer\}
|
|
28
28
|
- Update the priority of this ticket
|
|
29
|
-
- Assign this ticket to {team_member}
|
|
29
|
+
- Assign this ticket to \{team_member\}
|
|
30
30
|
- Delete these old support tickets
|
|
31
|
-
- Send an automatic response to {customer}
|
|
31
|
+
- Send an automatic response to \{customer\}
|
|
32
32
|
|
|
33
33
|
## Installation
|
|
34
34
|
|
|
@@ -107,6 +107,6 @@ For the service's official API docs, see the [Zendesk-Support API reference](htt
|
|
|
107
107
|
|
|
108
108
|
## Version information
|
|
109
109
|
|
|
110
|
-
- **Package version:** 0.18.
|
|
110
|
+
- **Package version:** 0.18.29
|
|
111
111
|
- **Connector version:** 0.1.4
|
|
112
|
-
- **Generated with Connector SDK commit SHA:**
|
|
112
|
+
- **Generated with Connector SDK commit SHA:** d023e05f2b7a1ddabf81fab7640c64de1e0aa6a1
|
|
@@ -13,6 +13,7 @@ from __future__ import annotations
|
|
|
13
13
|
from .auth_strategies import AuthStrategy
|
|
14
14
|
from .connector_model_loader import load_connector_model
|
|
15
15
|
from .constants import SDK_VERSION
|
|
16
|
+
from .decorators import airbyte_description
|
|
16
17
|
from .exceptions import (
|
|
17
18
|
AuthenticationError,
|
|
18
19
|
HTTPClientError,
|
|
@@ -79,4 +80,6 @@ __all__ = [
|
|
|
79
80
|
"instrument",
|
|
80
81
|
# Utilities
|
|
81
82
|
"save_download",
|
|
83
|
+
# Decorators for AI integration
|
|
84
|
+
"airbyte_description",
|
|
82
85
|
]
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Decorators for AI agent tool integration.
|
|
3
|
+
|
|
4
|
+
Provides utilities to auto-generate comprehensive tool descriptions
|
|
5
|
+
from connector metadata, enabling easy integration with AI frameworks.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import importlib
|
|
11
|
+
from typing import Any, Callable, TypeVar
|
|
12
|
+
|
|
13
|
+
from .introspection import (
|
|
14
|
+
MAX_EXAMPLE_QUESTIONS,
|
|
15
|
+
ConnectorModelProtocol,
|
|
16
|
+
EndpointProtocol,
|
|
17
|
+
generate_tool_description,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
F = TypeVar("F", bound=Callable[..., Any])
|
|
21
|
+
|
|
22
|
+
__all__ = [
|
|
23
|
+
"airbyte_description",
|
|
24
|
+
"EndpointProtocol",
|
|
25
|
+
"ConnectorModelProtocol",
|
|
26
|
+
"MAX_EXAMPLE_QUESTIONS",
|
|
27
|
+
# Private function exposed for testing
|
|
28
|
+
"_load_connector_model",
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def airbyte_description(connector_name: str) -> Callable[[F], F]:
|
|
33
|
+
"""
|
|
34
|
+
Decorator that generates comprehensive tool descriptions from connector metadata.
|
|
35
|
+
|
|
36
|
+
Automatically populates the function's docstring with:
|
|
37
|
+
- Connector description
|
|
38
|
+
- Available entities and their actions
|
|
39
|
+
- Example questions the connector can answer
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
connector_name: Name of the connector (e.g., "hubspot", "stripe")
|
|
43
|
+
Must match the generated package name pattern:
|
|
44
|
+
airbyte_agent_{connector_name}
|
|
45
|
+
|
|
46
|
+
Returns:
|
|
47
|
+
Decorator that updates the function's __doc__ attribute
|
|
48
|
+
|
|
49
|
+
Example:
|
|
50
|
+
from airbyte_agent_hubspot import HubspotConnector
|
|
51
|
+
|
|
52
|
+
connector = HubspotConnector(
|
|
53
|
+
external_user_id=external_user_id,
|
|
54
|
+
airbyte_client_id=airbyte_client_id,
|
|
55
|
+
airbyte_client_secret=airbyte_client_secret
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
# IMPORTANT: @airbyte_description must be the INNER decorator (closest to function)
|
|
59
|
+
# This ensures __doc__ is expanded BEFORE frameworks like FastMCP capture it
|
|
60
|
+
@agent.tool_plain # or @mcp.tool() for FastMCP
|
|
61
|
+
@airbyte_description("hubspot")
|
|
62
|
+
async def hubspot_exec(entity: str, action: str, params: dict | None = None):
|
|
63
|
+
'''Execute HubSpot operations.'''
|
|
64
|
+
return await connector.execute(entity, action, params or {})
|
|
65
|
+
|
|
66
|
+
The decorator will update hubspot_exec.__doc__ with a comprehensive
|
|
67
|
+
description including all available entities, actions, and example questions.
|
|
68
|
+
"""
|
|
69
|
+
|
|
70
|
+
def decorator(func: F) -> F:
|
|
71
|
+
# Load connector model from generated package
|
|
72
|
+
model = _load_connector_model(connector_name)
|
|
73
|
+
|
|
74
|
+
# Generate description using shared introspection module
|
|
75
|
+
description = generate_tool_description(model)
|
|
76
|
+
|
|
77
|
+
# Preserve original docstring if present, append to it
|
|
78
|
+
original_doc = func.__doc__ or ""
|
|
79
|
+
if original_doc.strip():
|
|
80
|
+
func.__doc__ = f"{original_doc.strip()}\n\n{description}"
|
|
81
|
+
else:
|
|
82
|
+
func.__doc__ = description
|
|
83
|
+
|
|
84
|
+
return func
|
|
85
|
+
|
|
86
|
+
return decorator
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def _load_connector_model(connector_name: str) -> Any:
|
|
90
|
+
"""
|
|
91
|
+
Load connector model from generated package.
|
|
92
|
+
|
|
93
|
+
Args:
|
|
94
|
+
connector_name: Connector name (e.g., "hubspot")
|
|
95
|
+
|
|
96
|
+
Returns:
|
|
97
|
+
ConnectorModel instance from the generated package
|
|
98
|
+
|
|
99
|
+
Raises:
|
|
100
|
+
ImportError: If connector package is not installed
|
|
101
|
+
AttributeError: If connector model constant not found
|
|
102
|
+
"""
|
|
103
|
+
# Normalize connector name to package name
|
|
104
|
+
package_name = f"airbyte_agent_{connector_name.replace('-', '_')}"
|
|
105
|
+
|
|
106
|
+
try:
|
|
107
|
+
# Import the connector_model module from the generated package
|
|
108
|
+
module = importlib.import_module(f"{package_name}.connector_model")
|
|
109
|
+
except ImportError as e:
|
|
110
|
+
raise ImportError(f"Could not import connector package '{package_name}'. " f"Ensure the package is installed. Error: {e}") from e
|
|
111
|
+
|
|
112
|
+
# Find the ConnectorModel constant (named like HubspotConnectorModel)
|
|
113
|
+
# Convention: {PascalCase connector name}ConnectorModel
|
|
114
|
+
pascal_name = "".join(word.capitalize() for word in connector_name.replace("-", "_").split("_"))
|
|
115
|
+
model_name = f"{pascal_name}ConnectorModel"
|
|
116
|
+
|
|
117
|
+
model = getattr(module, model_name, None)
|
|
118
|
+
if model is None:
|
|
119
|
+
# Fallback: look for any ConnectorModel attribute
|
|
120
|
+
for attr_name in dir(module):
|
|
121
|
+
if attr_name.endswith("ConnectorModel"):
|
|
122
|
+
model = getattr(module, attr_name)
|
|
123
|
+
break
|
|
124
|
+
|
|
125
|
+
if model is None:
|
|
126
|
+
raise AttributeError(f"Could not find ConnectorModel in {package_name}.connector_model. " f"Expected constant named '{model_name}'")
|
|
127
|
+
|
|
128
|
+
return model
|
|
@@ -674,16 +674,16 @@ class LocalExecutor:
|
|
|
674
674
|
return {key: value for key, value in params.items() if key in allowed_params}
|
|
675
675
|
|
|
676
676
|
def _extract_body(self, allowed_fields: list[str], params: dict[str, Any]) -> dict[str, Any]:
|
|
677
|
-
"""Extract body fields from params.
|
|
677
|
+
"""Extract body fields from params, filtering out None values.
|
|
678
678
|
|
|
679
679
|
Args:
|
|
680
680
|
allowed_fields: List of allowed body field names
|
|
681
681
|
params: All parameters
|
|
682
682
|
|
|
683
683
|
Returns:
|
|
684
|
-
Dictionary of body fields
|
|
684
|
+
Dictionary of body fields with None values filtered out
|
|
685
685
|
"""
|
|
686
|
-
return {key: value for key, value in params.items() if key in allowed_fields}
|
|
686
|
+
return {key: value for key, value in params.items() if key in allowed_fields and value is not None}
|
|
687
687
|
|
|
688
688
|
def _serialize_deep_object_params(self, params: dict[str, Any], deep_object_param_names: list[str]) -> dict[str, Any]:
|
|
689
689
|
"""Serialize deepObject parameters to bracket notation format.
|
|
@@ -838,11 +838,7 @@ class LocalExecutor:
|
|
|
838
838
|
"""
|
|
839
839
|
if endpoint.graphql_body:
|
|
840
840
|
# Extract defaults from query_params_schema for GraphQL variable interpolation
|
|
841
|
-
param_defaults = {
|
|
842
|
-
name: schema.get("default")
|
|
843
|
-
for name, schema in endpoint.query_params_schema.items()
|
|
844
|
-
if "default" in schema
|
|
845
|
-
}
|
|
841
|
+
param_defaults = {name: schema.get("default") for name, schema in endpoint.query_params_schema.items() if "default" in schema}
|
|
846
842
|
return self._build_graphql_body(endpoint.graphql_body, params, param_defaults)
|
|
847
843
|
elif endpoint.body_fields:
|
|
848
844
|
return self._extract_body(endpoint.body_fields, params)
|
|
@@ -934,9 +930,7 @@ class LocalExecutor:
|
|
|
934
930
|
|
|
935
931
|
# Substitute variables from params
|
|
936
932
|
if "variables" in graphql_config and graphql_config["variables"]:
|
|
937
|
-
body["variables"] = self._interpolate_variables(
|
|
938
|
-
graphql_config["variables"], params, param_defaults
|
|
939
|
-
)
|
|
933
|
+
body["variables"] = self._interpolate_variables(graphql_config["variables"], params, param_defaults)
|
|
940
934
|
|
|
941
935
|
# Add operation name if specified
|
|
942
936
|
if "operationName" in graphql_config:
|
|
@@ -1180,21 +1174,18 @@ class LocalExecutor:
|
|
|
1180
1174
|
if action not in (Action.CREATE, Action.UPDATE):
|
|
1181
1175
|
return
|
|
1182
1176
|
|
|
1183
|
-
#
|
|
1184
|
-
|
|
1177
|
+
# Get the request schema to find truly required fields
|
|
1178
|
+
request_schema = endpoint.request_schema
|
|
1179
|
+
if not request_schema:
|
|
1185
1180
|
return
|
|
1186
1181
|
|
|
1187
|
-
#
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
missing_fields = []
|
|
1191
|
-
for field in endpoint.body_fields:
|
|
1192
|
-
if field not in params:
|
|
1193
|
-
missing_fields.append(field)
|
|
1182
|
+
# Only validate fields explicitly marked as required in the schema
|
|
1183
|
+
required_fields = request_schema.get("required", [])
|
|
1184
|
+
missing_fields = [field for field in required_fields if field not in params]
|
|
1194
1185
|
|
|
1195
1186
|
if missing_fields:
|
|
1196
1187
|
raise MissingParameterError(
|
|
1197
|
-
f"Missing required body fields for {entity}.{action.value}: {missing_fields}. Provided parameters: {list(params.keys())}"
|
|
1188
|
+
f"Missing required body fields for {entity}.{action.value}: {missing_fields}. " f"Provided parameters: {list(params.keys())}"
|
|
1198
1189
|
)
|
|
1199
1190
|
|
|
1200
1191
|
async def close(self):
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Shared introspection utilities for connector metadata.
|
|
3
|
+
|
|
4
|
+
This module provides utilities for introspecting connector metadata,
|
|
5
|
+
generating descriptions, and formatting parameter signatures. These
|
|
6
|
+
functions are used by both the runtime decorators and the generated
|
|
7
|
+
connector code.
|
|
8
|
+
|
|
9
|
+
The module is designed to work with any object conforming to the
|
|
10
|
+
ConnectorModel and EndpointDefinition interfaces from connector_sdk.types.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
from typing import Any, Protocol
|
|
16
|
+
|
|
17
|
+
# Constants
|
|
18
|
+
MAX_EXAMPLE_QUESTIONS = 5 # Maximum number of example questions to include in description
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class EndpointProtocol(Protocol):
|
|
22
|
+
"""Protocol defining the expected interface for endpoint parameters.
|
|
23
|
+
|
|
24
|
+
This allows functions to work with any endpoint-like object
|
|
25
|
+
that has these attributes, including EndpointDefinition and mock objects.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
path_params: list[str]
|
|
29
|
+
path_params_schema: dict[str, dict[str, Any]]
|
|
30
|
+
query_params: list[str]
|
|
31
|
+
query_params_schema: dict[str, dict[str, Any]]
|
|
32
|
+
body_fields: list[str]
|
|
33
|
+
request_schema: dict[str, Any] | None
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class EntityProtocol(Protocol):
|
|
37
|
+
"""Protocol defining the expected interface for entity definitions."""
|
|
38
|
+
|
|
39
|
+
name: str
|
|
40
|
+
actions: list[Any]
|
|
41
|
+
endpoints: dict[Any, EndpointProtocol]
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class ConnectorModelProtocol(Protocol):
|
|
45
|
+
"""Protocol defining the expected interface for connector model parameters.
|
|
46
|
+
|
|
47
|
+
This allows functions to work with any connector-like object
|
|
48
|
+
that has these attributes, including ConnectorModel and mock objects.
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
@property
|
|
52
|
+
def entities(self) -> list[EntityProtocol]: ...
|
|
53
|
+
|
|
54
|
+
@property
|
|
55
|
+
def openapi_spec(self) -> Any: ...
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def format_param_signature(endpoint: EndpointProtocol) -> str:
|
|
59
|
+
"""Format parameter signature for an endpoint action.
|
|
60
|
+
|
|
61
|
+
Returns a string like: (id*) or (limit?, starting_after?, email?)
|
|
62
|
+
where * = required, ? = optional
|
|
63
|
+
|
|
64
|
+
Args:
|
|
65
|
+
endpoint: Object conforming to EndpointProtocol (e.g., EndpointDefinition)
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
Formatted parameter signature string
|
|
69
|
+
"""
|
|
70
|
+
params = []
|
|
71
|
+
|
|
72
|
+
# Defensive: safely access attributes with defaults for malformed endpoints
|
|
73
|
+
path_params = getattr(endpoint, "path_params", []) or []
|
|
74
|
+
query_params = getattr(endpoint, "query_params", []) or []
|
|
75
|
+
query_params_schema = getattr(endpoint, "query_params_schema", {}) or {}
|
|
76
|
+
body_fields = getattr(endpoint, "body_fields", []) or []
|
|
77
|
+
request_schema = getattr(endpoint, "request_schema", None)
|
|
78
|
+
|
|
79
|
+
# Path params (always required)
|
|
80
|
+
for name in path_params:
|
|
81
|
+
params.append(f"{name}*")
|
|
82
|
+
|
|
83
|
+
# Query params
|
|
84
|
+
for name in query_params:
|
|
85
|
+
schema = query_params_schema.get(name, {})
|
|
86
|
+
required = schema.get("required", False)
|
|
87
|
+
params.append(f"{name}{'*' if required else '?'}")
|
|
88
|
+
|
|
89
|
+
# Body fields
|
|
90
|
+
if request_schema:
|
|
91
|
+
required_fields = set(request_schema.get("required", []))
|
|
92
|
+
for name in body_fields:
|
|
93
|
+
params.append(f"{name}{'*' if name in required_fields else '?'}")
|
|
94
|
+
|
|
95
|
+
return f"({', '.join(params)})" if params else "()"
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def describe_entities(model: ConnectorModelProtocol) -> list[dict[str, Any]]:
|
|
99
|
+
"""Generate entity descriptions from ConnectorModel.
|
|
100
|
+
|
|
101
|
+
Returns a list of entity descriptions with detailed parameter information
|
|
102
|
+
for each action. This is used by generated connectors' describe() method.
|
|
103
|
+
|
|
104
|
+
Args:
|
|
105
|
+
model: Object conforming to ConnectorModelProtocol (e.g., ConnectorModel)
|
|
106
|
+
|
|
107
|
+
Returns:
|
|
108
|
+
List of entity description dicts with keys:
|
|
109
|
+
- entity_name: Name of the entity (e.g., "contacts", "deals")
|
|
110
|
+
- description: Entity description from the first endpoint
|
|
111
|
+
- available_actions: List of actions (e.g., ["list", "get", "create"])
|
|
112
|
+
- parameters: Dict mapping action -> list of parameter dicts
|
|
113
|
+
"""
|
|
114
|
+
entities = []
|
|
115
|
+
for entity_def in model.entities:
|
|
116
|
+
description = ""
|
|
117
|
+
parameters: dict[str, list[dict[str, Any]]] = {}
|
|
118
|
+
|
|
119
|
+
endpoints = getattr(entity_def, "endpoints", {}) or {}
|
|
120
|
+
if endpoints:
|
|
121
|
+
for action, endpoint in endpoints.items():
|
|
122
|
+
# Get description from first endpoint that has one
|
|
123
|
+
if not description:
|
|
124
|
+
endpoint_desc = getattr(endpoint, "description", None)
|
|
125
|
+
if endpoint_desc:
|
|
126
|
+
description = endpoint_desc
|
|
127
|
+
|
|
128
|
+
action_params: list[dict[str, Any]] = []
|
|
129
|
+
|
|
130
|
+
# Defensive: safely access endpoint attributes
|
|
131
|
+
path_params = getattr(endpoint, "path_params", []) or []
|
|
132
|
+
path_params_schema = getattr(endpoint, "path_params_schema", {}) or {}
|
|
133
|
+
query_params = getattr(endpoint, "query_params", []) or []
|
|
134
|
+
query_params_schema = getattr(endpoint, "query_params_schema", {}) or {}
|
|
135
|
+
body_fields = getattr(endpoint, "body_fields", []) or []
|
|
136
|
+
request_schema = getattr(endpoint, "request_schema", None)
|
|
137
|
+
|
|
138
|
+
# Path params (always required)
|
|
139
|
+
for param_name in path_params:
|
|
140
|
+
schema = path_params_schema.get(param_name, {})
|
|
141
|
+
action_params.append(
|
|
142
|
+
{
|
|
143
|
+
"name": param_name,
|
|
144
|
+
"in": "path",
|
|
145
|
+
"required": True,
|
|
146
|
+
"type": schema.get("type", "string"),
|
|
147
|
+
"description": schema.get("description", ""),
|
|
148
|
+
}
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
# Query params
|
|
152
|
+
for param_name in query_params:
|
|
153
|
+
schema = query_params_schema.get(param_name, {})
|
|
154
|
+
action_params.append(
|
|
155
|
+
{
|
|
156
|
+
"name": param_name,
|
|
157
|
+
"in": "query",
|
|
158
|
+
"required": schema.get("required", False),
|
|
159
|
+
"type": schema.get("type", "string"),
|
|
160
|
+
"description": schema.get("description", ""),
|
|
161
|
+
}
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
# Body fields
|
|
165
|
+
if request_schema:
|
|
166
|
+
required_fields = request_schema.get("required", [])
|
|
167
|
+
properties = request_schema.get("properties", {})
|
|
168
|
+
for param_name in body_fields:
|
|
169
|
+
prop = properties.get(param_name, {})
|
|
170
|
+
action_params.append(
|
|
171
|
+
{
|
|
172
|
+
"name": param_name,
|
|
173
|
+
"in": "body",
|
|
174
|
+
"required": param_name in required_fields,
|
|
175
|
+
"type": prop.get("type", "string"),
|
|
176
|
+
"description": prop.get("description", ""),
|
|
177
|
+
}
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
if action_params:
|
|
181
|
+
# Action is an enum, use .value to get string
|
|
182
|
+
action_key = action.value if hasattr(action, "value") else str(action)
|
|
183
|
+
parameters[action_key] = action_params
|
|
184
|
+
|
|
185
|
+
actions = getattr(entity_def, "actions", []) or []
|
|
186
|
+
entities.append(
|
|
187
|
+
{
|
|
188
|
+
"entity_name": entity_def.name,
|
|
189
|
+
"description": description,
|
|
190
|
+
"available_actions": [a.value if hasattr(a, "value") else str(a) for a in actions],
|
|
191
|
+
"parameters": parameters,
|
|
192
|
+
}
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
return entities
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def generate_tool_description(model: ConnectorModelProtocol) -> str:
|
|
199
|
+
"""Generate AI tool description from connector metadata.
|
|
200
|
+
|
|
201
|
+
Produces a detailed description that includes:
|
|
202
|
+
- Per-entity/action parameter signatures with required (*) and optional (?) markers
|
|
203
|
+
- Response structure documentation with pagination hints
|
|
204
|
+
- Example questions if available in the OpenAPI spec
|
|
205
|
+
|
|
206
|
+
This is used by the @airbyte_description decorator to populate
|
|
207
|
+
function docstrings for AI framework integration.
|
|
208
|
+
|
|
209
|
+
Args:
|
|
210
|
+
model: Object conforming to ConnectorModelProtocol (e.g., ConnectorModel)
|
|
211
|
+
|
|
212
|
+
Returns:
|
|
213
|
+
Formatted description string suitable for AI tool documentation
|
|
214
|
+
"""
|
|
215
|
+
lines = []
|
|
216
|
+
|
|
217
|
+
# Entity/action parameter details (including pagination params like limit, starting_after)
|
|
218
|
+
lines.append("ENTITIES AND PARAMETERS:")
|
|
219
|
+
for entity in model.entities:
|
|
220
|
+
lines.append(f" {entity.name}:")
|
|
221
|
+
actions = getattr(entity, "actions", []) or []
|
|
222
|
+
endpoints = getattr(entity, "endpoints", {}) or {}
|
|
223
|
+
for action in actions:
|
|
224
|
+
action_str = action.value if hasattr(action, "value") else str(action)
|
|
225
|
+
endpoint = endpoints.get(action)
|
|
226
|
+
if endpoint:
|
|
227
|
+
param_sig = format_param_signature(endpoint)
|
|
228
|
+
lines.append(f" - {action_str}{param_sig}")
|
|
229
|
+
else:
|
|
230
|
+
lines.append(f" - {action_str}()")
|
|
231
|
+
|
|
232
|
+
# Response structure (brief, includes pagination hint)
|
|
233
|
+
lines.append("")
|
|
234
|
+
lines.append("RESPONSE STRUCTURE:")
|
|
235
|
+
lines.append(" - list/search: {data: [...], meta: {has_more: bool}}")
|
|
236
|
+
lines.append(" - get: Returns entity directly (no envelope)")
|
|
237
|
+
lines.append(" To paginate: pass starting_after=<last_id> while has_more is true")
|
|
238
|
+
|
|
239
|
+
# Add example questions if available in openapi_spec
|
|
240
|
+
openapi_spec = getattr(model, "openapi_spec", None)
|
|
241
|
+
if openapi_spec:
|
|
242
|
+
info = getattr(openapi_spec, "info", None)
|
|
243
|
+
if info:
|
|
244
|
+
example_questions = getattr(info, "x_airbyte_example_questions", None)
|
|
245
|
+
if example_questions:
|
|
246
|
+
supported = getattr(example_questions, "supported", None)
|
|
247
|
+
if supported:
|
|
248
|
+
lines.append("")
|
|
249
|
+
lines.append("EXAMPLE QUESTIONS:")
|
|
250
|
+
for q in supported[:MAX_EXAMPLE_QUESTIONS]:
|
|
251
|
+
lines.append(f" - {q}")
|
|
252
|
+
|
|
253
|
+
# Generic parameter description for function signature
|
|
254
|
+
lines.append("")
|
|
255
|
+
lines.append("FUNCTION PARAMETERS:")
|
|
256
|
+
lines.append(" - entity: Entity name (string)")
|
|
257
|
+
lines.append(" - action: Operation to perform (string)")
|
|
258
|
+
lines.append(" - params: Operation parameters (dict) - see entity details above")
|
|
259
|
+
lines.append("")
|
|
260
|
+
lines.append("Parameter markers: * = required, ? = optional")
|
|
261
|
+
|
|
262
|
+
return "\n".join(lines)
|
|
@@ -4,6 +4,7 @@ zendesk-support connector.
|
|
|
4
4
|
|
|
5
5
|
from __future__ import annotations
|
|
6
6
|
|
|
7
|
+
import logging
|
|
7
8
|
from typing import TYPE_CHECKING, Any, AsyncIterator, overload
|
|
8
9
|
try:
|
|
9
10
|
from typing import Literal
|
|
@@ -11,6 +12,7 @@ except ImportError:
|
|
|
11
12
|
from typing_extensions import Literal
|
|
12
13
|
|
|
13
14
|
from .connector_model import ZendeskSupportConnectorModel
|
|
15
|
+
from ._vendored.connector_sdk.introspection import describe_entities
|
|
14
16
|
|
|
15
17
|
from .types import (
|
|
16
18
|
ArticleAttachmentsDownloadParams,
|
|
@@ -712,6 +714,51 @@ class ZendeskSupportConnector:
|
|
|
712
714
|
# No extractors - return raw response data
|
|
713
715
|
return result.data
|
|
714
716
|
|
|
717
|
+
# ===== INTROSPECTION METHODS =====
|
|
718
|
+
|
|
719
|
+
def describe(self) -> list[dict[str, Any]]:
|
|
720
|
+
"""
|
|
721
|
+
Describe available entities, actions, and parameters.
|
|
722
|
+
|
|
723
|
+
Returns a list of entity descriptions with:
|
|
724
|
+
- entity_name: Name of the entity (e.g., "contacts", "deals")
|
|
725
|
+
- description: Entity description from the first endpoint
|
|
726
|
+
- available_actions: List of actions (e.g., ["list", "get", "create"])
|
|
727
|
+
- parameters: Dict mapping action -> list of parameter dicts
|
|
728
|
+
|
|
729
|
+
Example:
|
|
730
|
+
entities = connector.describe()
|
|
731
|
+
for entity in entities:
|
|
732
|
+
print(f"{entity['entity_name']}: {entity['available_actions']}")
|
|
733
|
+
"""
|
|
734
|
+
return describe_entities(ZendeskSupportConnectorModel)
|
|
735
|
+
|
|
736
|
+
def entity_schema(self, entity: str) -> dict[str, Any] | None:
|
|
737
|
+
"""
|
|
738
|
+
Get the JSON schema for an entity.
|
|
739
|
+
|
|
740
|
+
Args:
|
|
741
|
+
entity: Entity name (e.g., "contacts", "companies")
|
|
742
|
+
|
|
743
|
+
Returns:
|
|
744
|
+
JSON schema dict describing the entity structure, or None if not found.
|
|
745
|
+
|
|
746
|
+
Example:
|
|
747
|
+
schema = connector.entity_schema("contacts")
|
|
748
|
+
if schema:
|
|
749
|
+
print(f"Contact properties: {list(schema.get('properties', {}).keys())}")
|
|
750
|
+
"""
|
|
751
|
+
entity_def = next(
|
|
752
|
+
(e for e in ZendeskSupportConnectorModel.entities if e.name == entity),
|
|
753
|
+
None
|
|
754
|
+
)
|
|
755
|
+
if entity_def is None:
|
|
756
|
+
logging.getLogger(__name__).warning(
|
|
757
|
+
f"Entity '{entity}' not found. Available entities: "
|
|
758
|
+
f"{[e.name for e in ZendeskSupportConnectorModel.entities]}"
|
|
759
|
+
)
|
|
760
|
+
return entity_def.entity_schema if entity_def else None
|
|
761
|
+
|
|
715
762
|
|
|
716
763
|
|
|
717
764
|
class TicketsQuery:
|
|
File without changes
|
{airbyte_agent_zendesk_support-0.18.27 → airbyte_agent_zendesk_support-0.18.29}/REFERENCE.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|