airbyte-agent-zendesk-support 0.18.32__py3-none-any.whl → 0.18.35__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.
@@ -74,5 +74,5 @@ except PackageNotFoundError:
74
74
  SDK_VERSION = "0.0.0-dev"
75
75
  """Current version of the Airbyte SDK."""
76
76
 
77
- MINIMUM_PYTHON_VERSION = "3.9"
77
+ MINIMUM_PYTHON_VERSION = "3.13"
78
78
  """Minimum Python version required to run the SDK."""
@@ -0,0 +1,179 @@
1
+ """Unified configuration for connector-sdk."""
2
+
3
+ import logging
4
+ import os
5
+ import tempfile
6
+ import uuid
7
+ from dataclasses import dataclass, field
8
+ from pathlib import Path
9
+ from typing import Any, Optional
10
+
11
+ import yaml
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+ # New config location
16
+ CONFIG_DIR = Path.home() / ".airbyte" / "connector-sdk"
17
+ CONFIG_PATH = CONFIG_DIR / "config.yaml"
18
+
19
+ # Legacy file locations (for migration)
20
+ LEGACY_USER_ID_PATH = Path.home() / ".airbyte" / "ai_sdk_user_id"
21
+ LEGACY_INTERNAL_MARKER_PATH = Path.home() / ".airbyte" / "internal_user"
22
+
23
+
24
+ @dataclass
25
+ class SDKConfig:
26
+ """Connector SDK configuration."""
27
+
28
+ user_id: str = field(default_factory=lambda: str(uuid.uuid4()))
29
+ is_internal_user: bool = False
30
+
31
+ def to_dict(self) -> dict[str, Any]:
32
+ """Convert to dictionary for YAML serialization."""
33
+ return {
34
+ "user_id": self.user_id,
35
+ "is_internal_user": self.is_internal_user,
36
+ }
37
+
38
+
39
+ def _delete_legacy_files() -> None:
40
+ """
41
+ Delete legacy config files after successful migration.
42
+
43
+ Removes:
44
+ - ~/.airbyte/ai_sdk_user_id
45
+ - ~/.airbyte/internal_user
46
+ """
47
+ for legacy_path in [LEGACY_USER_ID_PATH, LEGACY_INTERNAL_MARKER_PATH]:
48
+ try:
49
+ if legacy_path.exists():
50
+ legacy_path.unlink()
51
+ logger.debug(f"Deleted legacy config file: {legacy_path}")
52
+ except Exception as e:
53
+ logger.debug(f"Could not delete legacy file {legacy_path}: {e}")
54
+
55
+
56
+ def _migrate_legacy_config() -> Optional[SDKConfig]:
57
+ """
58
+ Migrate from legacy file-based config to new YAML format.
59
+
60
+ Reads from:
61
+ - ~/.airbyte/ai_sdk_user_id (user_id)
62
+ - ~/.airbyte/internal_user (is_internal_user marker)
63
+
64
+ Returns SDKConfig if migration was successful, None otherwise.
65
+ """
66
+ user_id = None
67
+ is_internal = False
68
+
69
+ # Try to read legacy user_id
70
+ try:
71
+ if LEGACY_USER_ID_PATH.exists():
72
+ user_id = LEGACY_USER_ID_PATH.read_text().strip()
73
+ if not user_id:
74
+ user_id = None
75
+ except Exception:
76
+ pass
77
+
78
+ # Check legacy internal_user marker
79
+ try:
80
+ is_internal = LEGACY_INTERNAL_MARKER_PATH.exists()
81
+ except Exception:
82
+ pass
83
+
84
+ if user_id or is_internal:
85
+ return SDKConfig(
86
+ user_id=user_id or str(uuid.uuid4()),
87
+ is_internal_user=is_internal,
88
+ )
89
+
90
+ return None
91
+
92
+
93
+ def load_config() -> SDKConfig:
94
+ """
95
+ Load SDK configuration from config file.
96
+
97
+ Checks (in order):
98
+ 1. New config file at ~/.airbyte/connector-sdk/config.yaml
99
+ 2. Legacy files at ~/.airbyte/ai_sdk_user_id and ~/.airbyte/internal_user
100
+ 3. Creates new config with generated user_id if nothing exists
101
+
102
+ Environment variable AIRBYTE_INTERNAL_USER can override is_internal_user.
103
+
104
+ Returns:
105
+ SDKConfig with user_id and is_internal_user
106
+ """
107
+ config = None
108
+
109
+ # Try to load from new config file
110
+ try:
111
+ if CONFIG_PATH.exists():
112
+ content = CONFIG_PATH.read_text()
113
+ data = yaml.safe_load(content) or {}
114
+ config = SDKConfig(
115
+ user_id=data.get("user_id", str(uuid.uuid4())),
116
+ is_internal_user=data.get("is_internal_user", False),
117
+ )
118
+ # Always clean up legacy files if they exist (even if new config exists)
119
+ _delete_legacy_files()
120
+ except Exception as e:
121
+ logger.debug(f"Could not load config from {CONFIG_PATH}: {e}")
122
+
123
+ # Try to migrate from legacy files if new config doesn't exist
124
+ if config is None:
125
+ config = _migrate_legacy_config()
126
+ if config:
127
+ # Save migrated config to new location
128
+ try:
129
+ save_config(config)
130
+ logger.debug("Migrated legacy config to new location")
131
+ # Delete legacy files after successful migration
132
+ _delete_legacy_files()
133
+ except Exception as e:
134
+ logger.debug(f"Could not save migrated config: {e}")
135
+
136
+ # Create new config if nothing exists
137
+ if config is None:
138
+ config = SDKConfig()
139
+ try:
140
+ save_config(config)
141
+ except Exception as e:
142
+ logger.debug(f"Could not save new config: {e}")
143
+
144
+ # Environment variable override for is_internal_user
145
+ env_value = os.getenv("AIRBYTE_INTERNAL_USER", "").lower()
146
+ if env_value in ("true", "1", "yes"):
147
+ config.is_internal_user = True
148
+ elif env_value:
149
+ # Any other non-empty value (including "false", "0", "no") defaults to False
150
+ config.is_internal_user = False
151
+
152
+ return config
153
+
154
+
155
+ def save_config(config: SDKConfig) -> None:
156
+ """
157
+ Save SDK configuration to config file.
158
+
159
+ Creates the config directory if it doesn't exist.
160
+ Uses atomic writes to prevent corruption from concurrent access.
161
+
162
+ Args:
163
+ config: SDKConfig to save
164
+ """
165
+ CONFIG_DIR.mkdir(parents=True, exist_ok=True)
166
+
167
+ # Use atomic write: write to temp file then rename (atomic on POSIX)
168
+ fd, temp_path = tempfile.mkstemp(dir=CONFIG_DIR, suffix=".tmp")
169
+ try:
170
+ with os.fdopen(fd, "w") as f:
171
+ yaml.dump(config.to_dict(), f, default_flow_style=False)
172
+ os.rename(temp_path, CONFIG_PATH)
173
+ except Exception:
174
+ # Clean up temp file on failure
175
+ try:
176
+ os.unlink(temp_path)
177
+ except OSError:
178
+ pass
179
+ raise
@@ -3,46 +3,40 @@
3
3
  import logging
4
4
  import uuid
5
5
  from datetime import UTC, datetime
6
- from pathlib import Path
7
6
  from typing import Any, Dict, Optional
8
7
 
8
+ from .config import SDKConfig, load_config
9
+
9
10
  logger = logging.getLogger(__name__)
10
11
 
12
+ # Cache the config at module level to avoid repeated reads
13
+ _cached_config: Optional[SDKConfig] = None
14
+
15
+
16
+ def _get_config() -> SDKConfig:
17
+ """Get cached SDK config or load from file."""
18
+ global _cached_config
19
+ if _cached_config is None:
20
+ _cached_config = load_config()
21
+ return _cached_config
22
+
23
+
24
+ def _clear_config_cache() -> None:
25
+ """Clear the cached config. Used for testing."""
26
+ global _cached_config
27
+ _cached_config = None
28
+
11
29
 
12
30
  def get_persistent_user_id() -> str:
13
31
  """
14
- Get or create an anonymous user ID stored in the home directory.
32
+ Get the persistent anonymous user ID.
15
33
 
16
- The ID is stored in ~/.airbyte/ai_sdk_user_id and persists across all sessions.
17
- If the file doesn't exist, a new UUID is generated and saved.
34
+ Now reads from ~/.airbyte/connector-sdk/config.yaml
18
35
 
19
36
  Returns:
20
37
  An anonymous UUID string that uniquely identifies this user across sessions.
21
38
  """
22
- try:
23
- # Create .airbyte directory in home folder if it doesn't exist
24
- airbyte_dir = Path.home() / ".airbyte"
25
- airbyte_dir.mkdir(exist_ok=True)
26
-
27
- # Path to user ID file
28
- user_id_file = airbyte_dir / "ai_sdk_user_id"
29
-
30
- # Try to read existing user ID
31
- if user_id_file.exists():
32
- user_id = user_id_file.read_text().strip()
33
- if user_id: # Validate it's not empty
34
- return user_id
35
-
36
- # Generate new user ID if file doesn't exist or is empty
37
- user_id = str(uuid.uuid4())
38
- user_id_file.write_text(user_id)
39
- logger.debug(f"Generated new anonymous user ID: {user_id}")
40
-
41
- return user_id
42
- except Exception as e:
43
- # If we can't read/write the file, generate a session-only ID
44
- logger.debug(f"Could not access anonymous user ID file: {e}")
45
- return str(uuid.uuid4())
39
+ return _get_config().user_id
46
40
 
47
41
 
48
42
  def get_public_ip() -> Optional[str]:
@@ -65,6 +59,18 @@ def get_public_ip() -> Optional[str]:
65
59
  return None
66
60
 
67
61
 
62
+ def get_is_internal_user() -> bool:
63
+ """
64
+ Check if the current user is an internal Airbyte user.
65
+
66
+ Now reads from ~/.airbyte/connector-sdk/config.yaml
67
+ Environment variable AIRBYTE_INTERNAL_USER can override.
68
+
69
+ Returns False if not set or on any error.
70
+ """
71
+ return _get_config().is_internal_user
72
+
73
+
68
74
  class ObservabilitySession:
69
75
  """Shared session context for both logging and telemetry."""
70
76
 
@@ -84,6 +90,7 @@ class ObservabilitySession:
84
90
  self.operation_count = 0
85
91
  self.metadata: Dict[str, Any] = {}
86
92
  self.public_ip = get_public_ip()
93
+ self.is_internal_user = get_is_internal_user()
87
94
 
88
95
  def increment_operations(self):
89
96
  """Increment the operation counter."""
@@ -1,6 +1,6 @@
1
1
  """Telemetry event models."""
2
2
 
3
- from dataclasses import asdict, dataclass
3
+ from dataclasses import asdict, dataclass, field
4
4
  from datetime import datetime
5
5
  from typing import Any, Dict, Optional
6
6
 
@@ -13,6 +13,7 @@ class BaseEvent:
13
13
  session_id: str
14
14
  user_id: str
15
15
  execution_context: str
16
+ is_internal_user: bool = field(default=False, kw_only=True)
16
17
 
17
18
  def to_dict(self) -> Dict[str, Any]:
18
19
  """Convert event to dictionary with ISO formatted timestamp."""
@@ -59,6 +59,7 @@ class SegmentTracker:
59
59
  session_id=self.session.session_id,
60
60
  user_id=self.session.user_id,
61
61
  execution_context=self.session.execution_context,
62
+ is_internal_user=self.session.is_internal_user,
62
63
  public_ip=self.session.public_ip,
63
64
  connector_name=self.session.connector_name,
64
65
  connector_version=connector_version,
@@ -101,6 +102,7 @@ class SegmentTracker:
101
102
  session_id=self.session.session_id,
102
103
  user_id=self.session.user_id,
103
104
  execution_context=self.session.execution_context,
105
+ is_internal_user=self.session.is_internal_user,
104
106
  public_ip=self.session.public_ip,
105
107
  connector_name=self.session.connector_name,
106
108
  entity=entity,
@@ -130,6 +132,7 @@ class SegmentTracker:
130
132
  session_id=self.session.session_id,
131
133
  user_id=self.session.user_id,
132
134
  execution_context=self.session.execution_context,
135
+ is_internal_user=self.session.is_internal_user,
133
136
  public_ip=self.session.public_ip,
134
137
  connector_name=self.session.connector_name,
135
138
  duration_seconds=self.session.duration_seconds(),
@@ -3,7 +3,7 @@ Type definitions for zendesk-support connector.
3
3
  """
4
4
  from __future__ import annotations
5
5
 
6
- # Use typing_extensions.TypedDict for Pydantic compatibility on Python < 3.12
6
+ # Use typing_extensions.TypedDict for Pydantic compatibility
7
7
  try:
8
8
  from typing_extensions import TypedDict, NotRequired
9
9
  except ImportError:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: airbyte-agent-zendesk-support
3
- Version: 0.18.32
3
+ Version: 0.18.35
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
@@ -13,13 +13,9 @@ Classifier: Development Status :: 3 - Alpha
13
13
  Classifier: Intended Audience :: Developers
14
14
  Classifier: License :: Other/Proprietary License
15
15
  Classifier: Programming Language :: Python :: 3
16
- Classifier: Programming Language :: Python :: 3.9
17
- Classifier: Programming Language :: Python :: 3.10
18
- Classifier: Programming Language :: Python :: 3.11
19
- Classifier: Programming Language :: Python :: 3.12
20
16
  Classifier: Programming Language :: Python :: 3.13
21
17
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
- Requires-Python: >=3.9
18
+ Requires-Python: >=3.13
23
19
  Requires-Dist: httpx>=0.24.0
24
20
  Requires-Dist: jinja2>=3.0.0
25
21
  Requires-Dist: jsonpath-ng>=1.6.1
@@ -141,6 +137,6 @@ For the service's official API docs, see the [Zendesk-Support API reference](htt
141
137
 
142
138
  ## Version information
143
139
 
144
- - **Package version:** 0.18.32
140
+ - **Package version:** 0.18.35
145
141
  - **Connector version:** 0.1.4
146
- - **Generated with Connector SDK commit SHA:** 3c7bfdfd1100dd20420a61cec56549b65820ea0f
142
+ - **Generated with Connector SDK commit SHA:** e80a226ece656f93854a8fd7a75aff502dadd2ae
@@ -2,13 +2,13 @@ airbyte_agent_zendesk_support/__init__.py,sha256=MPz4HU055DRA3-1qgbGXh2E0YHmhcex
2
2
  airbyte_agent_zendesk_support/connector.py,sha256=VYOTY7bEtXsvjyZSggoeS4lbSbGUsnVmtq3B2awkW5o,67058
3
3
  airbyte_agent_zendesk_support/connector_model.py,sha256=SAEWsLhW517Gc5eajkkYV1fQEGpsLlMALs2pTJ9BcPk,241131
4
4
  airbyte_agent_zendesk_support/models.py,sha256=31bsOmf4nBdf8EXN3JpYzXW8mx6gv1xaZjeuEBgSzws,36399
5
- airbyte_agent_zendesk_support/types.py,sha256=3CxJ8HosRMyzNEbVmRbybNCTVj9Ycxr7io25TP3YcCQ,6337
5
+ airbyte_agent_zendesk_support/types.py,sha256=vaWdcxDIJ8_nH7sv9PBsdWOKuTPVkskLur7fQF5Ln94,6320
6
6
  airbyte_agent_zendesk_support/_vendored/__init__.py,sha256=ILl7AHXMui__swyrjxrh9yRa4dLiwBvV6axPWFWty80,38
7
7
  airbyte_agent_zendesk_support/_vendored/connector_sdk/__init__.py,sha256=T5o7roU6NSpH-lCAGZ338sE5dlh4ZU6i6IkeG1zpems,1949
8
8
  airbyte_agent_zendesk_support/_vendored/connector_sdk/auth_strategies.py,sha256=0BfIISVzuvZTAYZjQFOOhKTpw0QuKDlLQBQ1PQo-V2M,39967
9
9
  airbyte_agent_zendesk_support/_vendored/connector_sdk/auth_template.py,sha256=vKnyA21Jp33EuDjkIUAf1PGicwk4t9kZAPJuAgAZKzU,4458
10
10
  airbyte_agent_zendesk_support/_vendored/connector_sdk/connector_model_loader.py,sha256=nKrXfe-FAyvNMkW7AqGzxrp5wXdaHiqC0yIFJoIVwlY,34890
11
- airbyte_agent_zendesk_support/_vendored/connector_sdk/constants.py,sha256=uH4rjBX6WsBP8M0jt7AUJI9w5Adn4wvJwib7Gdfkr1M,2736
11
+ airbyte_agent_zendesk_support/_vendored/connector_sdk/constants.py,sha256=AtzOvhDMWbRJgpsQNWl5tkogHD6mWgEY668PgRmgtOY,2737
12
12
  airbyte_agent_zendesk_support/_vendored/connector_sdk/exceptions.py,sha256=ss5MGv9eVPmsbLcLWetuu3sDmvturwfo6Pw3M37Oq5k,481
13
13
  airbyte_agent_zendesk_support/_vendored/connector_sdk/extensions.py,sha256=fWy9uwGUCjPO1KDYuGZo9nkrNU35P-dLcqi4K6UF4uA,21371
14
14
  airbyte_agent_zendesk_support/_vendored/connector_sdk/http_client.py,sha256=NdccrrBHI5rW56XnXcP54arCwywIVKnMeSQPas6KlOM,27466
@@ -34,9 +34,10 @@ airbyte_agent_zendesk_support/_vendored/connector_sdk/logging/__init__.py,sha256
34
34
  airbyte_agent_zendesk_support/_vendored/connector_sdk/logging/logger.py,sha256=Nh0h3C0aO-rAqZhDIyeEXG6Jd7yj1Gk32ECMPth0wl8,8118
35
35
  airbyte_agent_zendesk_support/_vendored/connector_sdk/logging/types.py,sha256=iI-xLoOg33OUGQOp3CeaxKtHh73WXE-oul6ZCNf3Nzc,3209
36
36
  airbyte_agent_zendesk_support/_vendored/connector_sdk/observability/__init__.py,sha256=ojx1n9vaWCXFFvb3-90Pwtg845trFdV2v6wcCoO75Ko,269
37
+ airbyte_agent_zendesk_support/_vendored/connector_sdk/observability/config.py,sha256=GJLzILUc7X6hqwL_Ger6sLAhlrecwV3GcjBJzvmXnqg,5385
37
38
  airbyte_agent_zendesk_support/_vendored/connector_sdk/observability/models.py,sha256=rF6-SoAAywqL8bhEv7yCbmr_W_w0vmApO-MCxcHq9RI,473
38
39
  airbyte_agent_zendesk_support/_vendored/connector_sdk/observability/redactor.py,sha256=HRbSwGxsfQYbYlG4QBVvv8Qnw0d4SMowMv0dTFHsHqQ,2361
39
- airbyte_agent_zendesk_support/_vendored/connector_sdk/observability/session.py,sha256=fLBgb9olATdoC0IMtd8MKe581t1HuK73MiGbghPzUHQ,3083
40
+ airbyte_agent_zendesk_support/_vendored/connector_sdk/observability/session.py,sha256=Q1U6qaH_Uj_eZ9sT6_Wrl27YWd95cxjA7S0GYWUrXkU,2941
40
41
  airbyte_agent_zendesk_support/_vendored/connector_sdk/performance/__init__.py,sha256=Sp5fSd1LvtIQkv-fnrKqPsM7-6IWp0sSZSK0mhzal_A,200
41
42
  airbyte_agent_zendesk_support/_vendored/connector_sdk/performance/instrumentation.py,sha256=_dXvNiqdndIBwDjeDKNViWzn_M5FkSUsMmJtFldrmsM,1504
42
43
  airbyte_agent_zendesk_support/_vendored/connector_sdk/performance/metrics.py,sha256=3-wPwlJyfVLUIG3y7ESxk0avhkILk3z8K7zSrnlZf5U,2833
@@ -49,8 +50,8 @@ airbyte_agent_zendesk_support/_vendored/connector_sdk/schema/operations.py,sha25
49
50
  airbyte_agent_zendesk_support/_vendored/connector_sdk/schema/security.py,sha256=Xo6Z0-NCryMY4EDZgvg8ABSPglskpXANvm_iI34meV8,8588
50
51
  airbyte_agent_zendesk_support/_vendored/connector_sdk/telemetry/__init__.py,sha256=RaLgkBU4dfxn1LC5Y0Q9rr2PJbrwjxvPgBLmq8_WafE,211
51
52
  airbyte_agent_zendesk_support/_vendored/connector_sdk/telemetry/config.py,sha256=tLmQwAFD0kP1WyBGWBS3ysaudN9H3e-3EopKZi6cGKg,885
52
- airbyte_agent_zendesk_support/_vendored/connector_sdk/telemetry/events.py,sha256=NvqjlUbkm6cbGh4ffKxYxtjdwwgzfPF4MKJ2GfgWeFg,1285
53
- airbyte_agent_zendesk_support/_vendored/connector_sdk/telemetry/tracker.py,sha256=KacNdbHatvPPhnNrycp5YUuD5xpkp56AFcHd-zguBgk,5247
54
- airbyte_agent_zendesk_support-0.18.32.dist-info/METADATA,sha256=cfq9fi6SsUk98-QqBlnLPfX6Bvtw9wcRpG5AteNq2Nw,6267
55
- airbyte_agent_zendesk_support-0.18.32.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
56
- airbyte_agent_zendesk_support-0.18.32.dist-info/RECORD,,
53
+ airbyte_agent_zendesk_support/_vendored/connector_sdk/telemetry/events.py,sha256=xUiasLicB818vfGVB108U7noVVDxz35g5vMomRKi0eE,1356
54
+ airbyte_agent_zendesk_support/_vendored/connector_sdk/telemetry/tracker.py,sha256=lURbjZVZSWLluX3OTK_0D8xrc3HAzK9xixtMTOEWnQ4,5439
55
+ airbyte_agent_zendesk_support-0.18.35.dist-info/METADATA,sha256=90ZXVzK1KS0xb9mS_v8STWg5-9zwUQt0BCd9p0rdkrU,6065
56
+ airbyte_agent_zendesk_support-0.18.35.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
57
+ airbyte_agent_zendesk_support-0.18.35.dist-info/RECORD,,