airbyte-agent-stripe 0.5.32__py3-none-any.whl → 0.5.37__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.
@@ -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."""
@@ -61,7 +61,7 @@ class Operation(BaseModel):
61
61
  description=(
62
62
  "JSONPath expression to extract records from API response envelopes. "
63
63
  "When specified, executor extracts data at this path instead of returning "
64
- "full response. Returns array for list/search actions, single record for "
64
+ "full response. Returns array for list/api_search actions, single record for "
65
65
  "get/create/update/delete actions."
66
66
  ),
67
67
  )
@@ -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(),
@@ -22,7 +22,7 @@ class Action(str, Enum):
22
22
  UPDATE = "update"
23
23
  DELETE = "delete"
24
24
  LIST = "list"
25
- SEARCH = "search"
25
+ API_SEARCH = "api_search"
26
26
  DOWNLOAD = "download"
27
27
  AUTHORIZE = "authorize"
28
28