airbyte-agent-asana 0.19.27__py3-none-any.whl → 0.19.41__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.

Potentially problematic release.


This version of airbyte-agent-asana might be problematic. Click here for more details.

Files changed (33) hide show
  1. airbyte_agent_asana/__init__.py +6 -6
  2. airbyte_agent_asana/_vendored/connector_sdk/auth_strategies.py +2 -5
  3. airbyte_agent_asana/_vendored/connector_sdk/auth_template.py +1 -1
  4. airbyte_agent_asana/_vendored/connector_sdk/cloud_utils/client.py +26 -26
  5. airbyte_agent_asana/_vendored/connector_sdk/connector_model_loader.py +11 -4
  6. airbyte_agent_asana/_vendored/connector_sdk/constants.py +1 -1
  7. airbyte_agent_asana/_vendored/connector_sdk/executor/hosted_executor.py +10 -11
  8. airbyte_agent_asana/_vendored/connector_sdk/executor/local_executor.py +94 -25
  9. airbyte_agent_asana/_vendored/connector_sdk/extensions.py +43 -5
  10. airbyte_agent_asana/_vendored/connector_sdk/http/response.py +2 -0
  11. airbyte_agent_asana/_vendored/connector_sdk/introspection.py +262 -0
  12. airbyte_agent_asana/_vendored/connector_sdk/logging/logger.py +9 -9
  13. airbyte_agent_asana/_vendored/connector_sdk/logging/types.py +10 -10
  14. airbyte_agent_asana/_vendored/connector_sdk/observability/config.py +179 -0
  15. airbyte_agent_asana/_vendored/connector_sdk/observability/models.py +6 -6
  16. airbyte_agent_asana/_vendored/connector_sdk/observability/session.py +41 -32
  17. airbyte_agent_asana/_vendored/connector_sdk/performance/metrics.py +3 -3
  18. airbyte_agent_asana/_vendored/connector_sdk/schema/base.py +17 -17
  19. airbyte_agent_asana/_vendored/connector_sdk/schema/components.py +59 -58
  20. airbyte_agent_asana/_vendored/connector_sdk/schema/extensions.py +9 -9
  21. airbyte_agent_asana/_vendored/connector_sdk/schema/operations.py +32 -32
  22. airbyte_agent_asana/_vendored/connector_sdk/schema/security.py +44 -34
  23. airbyte_agent_asana/_vendored/connector_sdk/secrets.py +2 -2
  24. airbyte_agent_asana/_vendored/connector_sdk/telemetry/events.py +9 -8
  25. airbyte_agent_asana/_vendored/connector_sdk/telemetry/tracker.py +9 -5
  26. airbyte_agent_asana/_vendored/connector_sdk/types.py +7 -3
  27. airbyte_agent_asana/connector.py +88 -3
  28. airbyte_agent_asana/connector_model.py +6 -0
  29. airbyte_agent_asana/models.py +29 -29
  30. airbyte_agent_asana/types.py +1 -1
  31. {airbyte_agent_asana-0.19.27.dist-info → airbyte_agent_asana-0.19.41.dist-info}/METADATA +11 -11
  32. {airbyte_agent_asana-0.19.27.dist-info → airbyte_agent_asana-0.19.41.dist-info}/RECORD +33 -31
  33. {airbyte_agent_asana-0.19.27.dist-info → airbyte_agent_asana-0.19.41.dist-info}/WHEEL +0 -0
@@ -6,7 +6,7 @@ References:
6
6
  - https://spec.openapis.org/oas/v3.1.0#oauth-flows-object
7
7
  """
8
8
 
9
- from typing import Any, Dict, List, Literal, Optional
9
+ from typing import Any, Dict, List, Literal
10
10
 
11
11
  from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
12
12
 
@@ -20,9 +20,9 @@ class OAuth2Flow(BaseModel):
20
20
 
21
21
  model_config = ConfigDict(populate_by_name=True, extra="forbid")
22
22
 
23
- authorization_url: Optional[str] = Field(None, alias="authorizationUrl")
24
- token_url: Optional[str] = Field(None, alias="tokenUrl")
25
- refresh_url: Optional[str] = Field(None, alias="refreshUrl")
23
+ authorization_url: str | None = Field(None, alias="authorizationUrl")
24
+ token_url: str | None = Field(None, alias="tokenUrl")
25
+ refresh_url: str | None = Field(None, alias="refreshUrl")
26
26
  scopes: Dict[str, str] = Field(default_factory=dict)
27
27
 
28
28
 
@@ -35,10 +35,10 @@ class OAuth2Flows(BaseModel):
35
35
 
36
36
  model_config = ConfigDict(populate_by_name=True, extra="forbid")
37
37
 
38
- implicit: Optional[OAuth2Flow] = None
39
- password: Optional[OAuth2Flow] = None
40
- client_credentials: Optional[OAuth2Flow] = Field(None, alias="clientCredentials")
41
- authorization_code: Optional[OAuth2Flow] = Field(None, alias="authorizationCode")
38
+ implicit: OAuth2Flow | None = None
39
+ password: OAuth2Flow | None = None
40
+ client_credentials: OAuth2Flow | None = Field(None, alias="clientCredentials")
41
+ authorization_code: OAuth2Flow | None = Field(None, alias="authorizationCode")
42
42
 
43
43
 
44
44
  class AuthConfigFieldSpec(BaseModel):
@@ -51,12 +51,12 @@ class AuthConfigFieldSpec(BaseModel):
51
51
  model_config = ConfigDict(populate_by_name=True, extra="forbid")
52
52
 
53
53
  type: Literal["string", "integer", "boolean", "number"] = "string"
54
- title: Optional[str] = None
55
- description: Optional[str] = None
56
- format: Optional[str] = None # e.g., "email", "uri"
57
- pattern: Optional[str] = None # Regex validation
54
+ title: str | None = None
55
+ description: str | None = None
56
+ format: str | None = None # e.g., "email", "uri"
57
+ pattern: str | None = None # Regex validation
58
58
  airbyte_secret: bool = Field(False, alias="airbyte_secret")
59
- default: Optional[Any] = None
59
+ default: Any | None = None
60
60
 
61
61
 
62
62
  class AuthConfigOption(BaseModel):
@@ -68,8 +68,8 @@ class AuthConfigOption(BaseModel):
68
68
 
69
69
  model_config = ConfigDict(populate_by_name=True, extra="forbid")
70
70
 
71
- title: Optional[str] = None
72
- description: Optional[str] = None
71
+ title: str | None = None
72
+ description: str | None = None
73
73
  type: Literal["object"] = "object"
74
74
  required: List[str] = Field(default_factory=list)
75
75
  properties: Dict[str, AuthConfigFieldSpec] = Field(default_factory=dict)
@@ -77,6 +77,10 @@ class AuthConfigOption(BaseModel):
77
77
  default_factory=dict,
78
78
  description="Mapping from auth parameters (e.g., 'username', 'password', 'token') to template strings using ${field} syntax",
79
79
  )
80
+ replication_auth_key_mapping: Dict[str, str] | None = Field(
81
+ None,
82
+ description="Mapping from source config paths (e.g., 'credentials.api_key') to auth config keys for direct connectors",
83
+ )
80
84
 
81
85
 
82
86
  class AirbyteAuthConfig(BaseModel):
@@ -92,15 +96,21 @@ class AirbyteAuthConfig(BaseModel):
92
96
  model_config = ConfigDict(populate_by_name=True, extra="forbid")
93
97
 
94
98
  # Single option fields
95
- title: Optional[str] = None
96
- description: Optional[str] = None
97
- type: Optional[Literal["object"]] = None
98
- required: Optional[List[str]] = None
99
- properties: Optional[Dict[str, AuthConfigFieldSpec]] = None
100
- auth_mapping: Optional[Dict[str, str]] = None
99
+ title: str | None = None
100
+ description: str | None = None
101
+ type: Literal["object"] | None = None
102
+ required: List[str] | None = None
103
+ properties: Dict[str, AuthConfigFieldSpec] | None = None
104
+ auth_mapping: Dict[str, str] | None = None
105
+
106
+ # Replication connector auth mapping
107
+ replication_auth_key_mapping: Dict[str, str] | None = Field(
108
+ None,
109
+ description="Mapping from source config paths (e.g., 'credentials.api_key') to auth config keys for direct connectors",
110
+ )
101
111
 
102
112
  # Multiple options (oneOf)
103
- one_of: Optional[List[AuthConfigOption]] = Field(None, alias="oneOf")
113
+ one_of: List[AuthConfigOption] | None = Field(None, alias="oneOf")
104
114
 
105
115
  @model_validator(mode="after")
106
116
  def validate_config_structure(self) -> "AirbyteAuthConfig":
@@ -151,27 +161,27 @@ class SecurityScheme(BaseModel):
151
161
 
152
162
  # Standard OpenAPI fields
153
163
  type: Literal["apiKey", "http", "oauth2", "openIdConnect"]
154
- description: Optional[str] = None
164
+ description: str | None = None
155
165
 
156
166
  # apiKey specific
157
- name: Optional[str] = None
158
- in_: Optional[Literal["query", "header", "cookie"]] = Field(None, alias="in")
167
+ name: str | None = None
168
+ in_: Literal["query", "header", "cookie"] | None = Field(None, alias="in")
159
169
 
160
170
  # http specific
161
- scheme: Optional[str] = None # e.g., "basic", "bearer", "digest"
162
- bearer_format: Optional[str] = Field(None, alias="bearerFormat")
171
+ scheme: str | None = None # e.g., "basic", "bearer", "digest"
172
+ bearer_format: str | None = Field(None, alias="bearerFormat")
163
173
 
164
174
  # oauth2 specific
165
- flows: Optional[OAuth2Flows] = None
175
+ flows: OAuth2Flows | None = None
166
176
 
167
177
  # openIdConnect specific
168
- open_id_connect_url: Optional[str] = Field(None, alias="openIdConnectUrl")
178
+ open_id_connect_url: str | None = Field(None, alias="openIdConnectUrl")
169
179
 
170
180
  # Airbyte extensions
171
- x_token_path: Optional[str] = Field(None, alias="x-airbyte-token-path")
172
- x_token_refresh: Optional[Dict[str, Any]] = Field(None, alias="x-airbyte-token-refresh")
173
- x_airbyte_auth_config: Optional[AirbyteAuthConfig] = Field(None, alias="x-airbyte-auth-config")
174
- x_airbyte_token_extract: Optional[List[str]] = Field(
181
+ x_token_path: str | None = Field(None, alias="x-airbyte-token-path")
182
+ x_token_refresh: Dict[str, Any] | None = Field(None, alias="x-airbyte-token-refresh")
183
+ x_airbyte_auth_config: AirbyteAuthConfig | None = Field(None, alias="x-airbyte-auth-config")
184
+ x_airbyte_token_extract: List[str] | None = Field(
175
185
  None,
176
186
  alias="x-airbyte-token-extract",
177
187
  description="List of fields to extract from OAuth2 token responses and use as server variables",
@@ -179,7 +189,7 @@ class SecurityScheme(BaseModel):
179
189
 
180
190
  @field_validator("x_airbyte_token_extract", mode="after")
181
191
  @classmethod
182
- def validate_token_extract(cls, v: Optional[List[str]]) -> Optional[List[str]]:
192
+ def validate_token_extract(cls, v: List[str] | None) -> List[str] | None:
183
193
  """Validate x-airbyte-token-extract has no duplicates."""
184
194
  if v is not None:
185
195
  if len(v) != len(set(v)):
@@ -14,7 +14,7 @@ Example:
14
14
 
15
15
  import os
16
16
  import re
17
- from typing import Any, Dict, Optional
17
+ from typing import Any, Dict
18
18
 
19
19
  from pydantic import SecretStr
20
20
 
@@ -72,7 +72,7 @@ class SecretResolutionError(Exception):
72
72
  def resolve_env_var_references(
73
73
  secret_mappings: Dict[str, Any],
74
74
  strict: bool = True,
75
- env_vars: Optional[Dict[str, str]] = None,
75
+ env_vars: Dict[str, str] | None = None,
76
76
  ) -> Dict[str, str]:
77
77
  """Resolve environment variable references in secret values.
78
78
 
@@ -1,8 +1,8 @@
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
- from typing import Any, Dict, Optional
5
+ from typing import Any, Dict
6
6
 
7
7
 
8
8
  @dataclass
@@ -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."""
@@ -29,8 +30,8 @@ class ConnectorInitEvent(BaseEvent):
29
30
  python_version: str
30
31
  os_name: str
31
32
  os_version: str
32
- public_ip: Optional[str] = None
33
- connector_version: Optional[str] = None
33
+ public_ip: str | None = None
34
+ connector_version: str | None = None
34
35
 
35
36
 
36
37
  @dataclass
@@ -41,9 +42,9 @@ class OperationEvent(BaseEvent):
41
42
  entity: str
42
43
  action: str
43
44
  timing_ms: float
44
- public_ip: Optional[str] = None
45
- status_code: Optional[int] = None
46
- error_type: Optional[str] = None
45
+ public_ip: str | None = None
46
+ status_code: int | None = None
47
+ error_type: str | None = None
47
48
 
48
49
 
49
50
  @dataclass
@@ -55,4 +56,4 @@ class SessionEndEvent(BaseEvent):
55
56
  operation_count: int
56
57
  success_count: int
57
58
  failure_count: int
58
- public_ip: Optional[str] = None
59
+ public_ip: str | None = None
@@ -4,7 +4,6 @@ import logging
4
4
  import platform
5
5
  import sys
6
6
  from datetime import datetime
7
- from typing import Optional
8
7
 
9
8
  from ..observability import ObservabilitySession
10
9
 
@@ -20,7 +19,7 @@ class SegmentTracker:
20
19
  def __init__(
21
20
  self,
22
21
  session: ObservabilitySession,
23
- mode: Optional[TelemetryMode] = None,
22
+ mode: TelemetryMode | None = None,
24
23
  ):
25
24
  self.session = session
26
25
  self.mode = mode or TelemetryConfig.get_mode()
@@ -31,6 +30,8 @@ class SegmentTracker:
31
30
 
32
31
  if self.enabled:
33
32
  try:
33
+ # NOTE: Import here intentionally - segment is an optional dependency.
34
+ # This allows the SDK to work without telemetry if segment is not installed.
34
35
  import segment.analytics as analytics
35
36
 
36
37
  analytics.write_key = SEGMENT_WRITE_KEY
@@ -47,7 +48,7 @@ class SegmentTracker:
47
48
 
48
49
  def track_connector_init(
49
50
  self,
50
- connector_version: Optional[str] = None,
51
+ connector_version: str | None = None,
51
52
  ) -> None:
52
53
  """Track connector initialization."""
53
54
  if not self.enabled or not self._analytics:
@@ -59,6 +60,7 @@ class SegmentTracker:
59
60
  session_id=self.session.session_id,
60
61
  user_id=self.session.user_id,
61
62
  execution_context=self.session.execution_context,
63
+ is_internal_user=self.session.is_internal_user,
62
64
  public_ip=self.session.public_ip,
63
65
  connector_name=self.session.connector_name,
64
66
  connector_version=connector_version,
@@ -81,9 +83,9 @@ class SegmentTracker:
81
83
  self,
82
84
  entity: str,
83
85
  action: str,
84
- status_code: Optional[int],
86
+ status_code: int | None,
85
87
  timing_ms: float,
86
- error_type: Optional[str] = None,
88
+ error_type: str | None = None,
87
89
  ) -> None:
88
90
  """Track API operation."""
89
91
  # Always track success/failure counts (useful even when tracking is disabled)
@@ -101,6 +103,7 @@ class SegmentTracker:
101
103
  session_id=self.session.session_id,
102
104
  user_id=self.session.user_id,
103
105
  execution_context=self.session.execution_context,
106
+ is_internal_user=self.session.is_internal_user,
104
107
  public_ip=self.session.public_ip,
105
108
  connector_name=self.session.connector_name,
106
109
  entity=entity,
@@ -130,6 +133,7 @@ class SegmentTracker:
130
133
  session_id=self.session.session_id,
131
134
  user_id=self.session.user_id,
132
135
  execution_context=self.session.execution_context,
136
+ is_internal_user=self.session.is_internal_user,
133
137
  public_ip=self.session.public_ip,
134
138
  connector_name=self.session.connector_name,
135
139
  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
 
@@ -140,7 +140,7 @@ class AuthConfig(BaseModel):
140
140
  ValueError: If this is a multi-auth config or invalid
141
141
  """
142
142
  if self.is_multi_auth():
143
- raise ValueError("Cannot call get_single_option() on multi-auth config. " "Use options list instead.")
143
+ raise ValueError("Cannot call get_single_option() on multi-auth config. Use options list instead.")
144
144
 
145
145
  if self.type is None:
146
146
  raise ValueError("Invalid AuthConfig: neither single-auth nor multi-auth")
@@ -161,7 +161,7 @@ class EndpointDefinition(BaseModel):
161
161
  path: str # e.g., /v1/customers/{id} (OpenAPI path)
162
162
  path_override: PathOverrideConfig | None = Field(
163
163
  None,
164
- description=("Path override config from x-airbyte-path-override. " "When set, overrides the path for actual HTTP requests."),
164
+ description=("Path override config from x-airbyte-path-override. When set, overrides the path for actual HTTP requests."),
165
165
  )
166
166
  action: Action | None = None # Semantic action (get, list, create, update, delete)
167
167
  description: str | None = None
@@ -221,6 +221,10 @@ class EntityDefinition(BaseModel):
221
221
  model_config = {"populate_by_name": True}
222
222
 
223
223
  name: str
224
+ stream_name: str | None = Field(
225
+ default=None,
226
+ description="Airbyte stream name for cache lookup (from x-airbyte-stream-name schema extension)",
227
+ )
224
228
  actions: list[Action]
225
229
  endpoints: dict[Action, EndpointDefinition]
226
230
  entity_schema: dict[str, Any] | None = Field(default=None, alias="schema")
@@ -4,14 +4,15 @@ asana connector.
4
4
 
5
5
  from __future__ import annotations
6
6
 
7
- from typing import TYPE_CHECKING, Any, AsyncIterator, overload
7
+ import logging
8
+ from typing import TYPE_CHECKING, Any, Callable, TypeVar, AsyncIterator, overload
8
9
  try:
9
10
  from typing import Literal
10
11
  except ImportError:
11
12
  from typing_extensions import Literal
12
13
 
13
14
  from .connector_model import AsanaConnectorModel
14
-
15
+ from ._vendored.connector_sdk.introspection import describe_entities, generate_tool_description
15
16
  from .types import (
16
17
  AttachmentsDownloadParams,
17
18
  AttachmentsGetParams,
@@ -42,7 +43,6 @@ from .types import (
42
43
  WorkspacesGetParams,
43
44
  WorkspacesListParams,
44
45
  )
45
-
46
46
  if TYPE_CHECKING:
47
47
  from .models import AsanaAuthConfig
48
48
  # Import specific auth config classes for multi-auth isinstance checks
@@ -80,6 +80,9 @@ from .models import (
80
80
  TaskDependentsListResult,
81
81
  )
82
82
 
83
+ # TypeVar for decorator type preservation
84
+ _F = TypeVar("_F", bound=Callable[..., Any])
85
+
83
86
 
84
87
  class AsanaConnector:
85
88
  """
@@ -564,6 +567,88 @@ class AsanaConnector:
564
567
  # No extractors - return raw response data
565
568
  return result.data
566
569
 
570
+ # ===== INTROSPECTION METHODS =====
571
+
572
+ @classmethod
573
+ def describe(cls, func: _F) -> _F:
574
+ """
575
+ Decorator that populates a function's docstring with connector capabilities.
576
+
577
+ This class method can be used as a decorator to automatically generate
578
+ comprehensive documentation for AI tool functions.
579
+
580
+ Usage:
581
+ @mcp.tool()
582
+ @AsanaConnector.describe
583
+ async def execute(entity: str, action: str, params: dict):
584
+ '''Execute operations.'''
585
+ ...
586
+
587
+ The decorated function's __doc__ will be updated with:
588
+ - Available entities and their actions
589
+ - Parameter signatures with required (*) and optional (?) markers
590
+ - Response structure documentation
591
+ - Example questions (if available in OpenAPI spec)
592
+
593
+ Args:
594
+ func: The function to decorate
595
+
596
+ Returns:
597
+ The same function with updated __doc__
598
+ """
599
+ description = generate_tool_description(AsanaConnectorModel)
600
+
601
+ original_doc = func.__doc__ or ""
602
+ if original_doc.strip():
603
+ func.__doc__ = f"{original_doc.strip()}\n{description}"
604
+ else:
605
+ func.__doc__ = description
606
+
607
+ return func
608
+
609
+ def list_entities(self) -> list[dict[str, Any]]:
610
+ """
611
+ Get structured data about available entities, actions, and parameters.
612
+
613
+ Returns a list of entity descriptions with:
614
+ - entity_name: Name of the entity (e.g., "contacts", "deals")
615
+ - description: Entity description from the first endpoint
616
+ - available_actions: List of actions (e.g., ["list", "get", "create"])
617
+ - parameters: Dict mapping action -> list of parameter dicts
618
+
619
+ Example:
620
+ entities = connector.list_entities()
621
+ for entity in entities:
622
+ print(f"{entity['entity_name']}: {entity['available_actions']}")
623
+ """
624
+ return describe_entities(AsanaConnectorModel)
625
+
626
+ def entity_schema(self, entity: str) -> dict[str, Any] | None:
627
+ """
628
+ Get the JSON schema for an entity.
629
+
630
+ Args:
631
+ entity: Entity name (e.g., "contacts", "companies")
632
+
633
+ Returns:
634
+ JSON schema dict describing the entity structure, or None if not found.
635
+
636
+ Example:
637
+ schema = connector.entity_schema("contacts")
638
+ if schema:
639
+ print(f"Contact properties: {list(schema.get('properties', {}).keys())}")
640
+ """
641
+ entity_def = next(
642
+ (e for e in AsanaConnectorModel.entities if e.name == entity),
643
+ None
644
+ )
645
+ if entity_def is None:
646
+ logging.getLogger(__name__).warning(
647
+ f"Entity '{entity}' not found. Available entities: "
648
+ f"{[e.name for e in AsanaConnectorModel.entities]}"
649
+ )
650
+ return entity_def.entity_schema if entity_def else None
651
+
567
652
 
568
653
 
569
654
  class TasksQuery:
@@ -73,6 +73,11 @@ AsanaConnectorModel: ConnectorModel = ConnectorModel(
73
73
  'client_id': '${client_id}',
74
74
  'client_secret': '${client_secret}',
75
75
  },
76
+ replication_auth_key_mapping={
77
+ 'client_id': 'client_id',
78
+ 'client_secret': 'client_secret',
79
+ 'refresh_token': 'refresh_token',
80
+ },
76
81
  ),
77
82
  ),
78
83
  AuthOption(
@@ -91,6 +96,7 @@ AsanaConnectorModel: ConnectorModel = ConnectorModel(
91
96
  ),
92
97
  },
93
98
  auth_mapping={'token': '${token}'},
99
+ replication_auth_key_mapping={'personal_access_token': 'token'},
94
100
  ),
95
101
  ),
96
102
  ],
@@ -91,84 +91,84 @@ class ProjectCompact(BaseModel):
91
91
  resource_type: Union[str, Any] = Field(default=None)
92
92
  name: Union[str, Any] = Field(default=None)
93
93
 
94
- class ProjectCurrentStatusCreatedBy(BaseModel):
95
- """Nested schema for ProjectCurrentStatus.created_by"""
94
+ class ProjectMembersItem(BaseModel):
95
+ """Nested schema for Project.members_item"""
96
96
  model_config = ConfigDict(extra="allow", populate_by_name=True)
97
97
 
98
98
  gid: Union[str, Any] = Field(default=None)
99
99
  name: Union[str, Any] = Field(default=None)
100
100
  resource_type: Union[str, Any] = Field(default=None)
101
101
 
102
- class ProjectCurrentStatusAuthor(BaseModel):
103
- """Nested schema for ProjectCurrentStatus.author"""
102
+ class ProjectWorkspace(BaseModel):
103
+ """Nested schema for Project.workspace"""
104
104
  model_config = ConfigDict(extra="allow", populate_by_name=True)
105
105
 
106
106
  gid: Union[str, Any] = Field(default=None)
107
107
  name: Union[str, Any] = Field(default=None)
108
108
  resource_type: Union[str, Any] = Field(default=None)
109
109
 
110
- class ProjectCurrentStatus(BaseModel):
111
- """Nested schema for Project.current_status"""
110
+ class ProjectTeam(BaseModel):
111
+ """Nested schema for Project.team"""
112
112
  model_config = ConfigDict(extra="allow", populate_by_name=True)
113
113
 
114
114
  gid: Union[str, Any] = Field(default=None)
115
- author: Union[ProjectCurrentStatusAuthor, Any] = Field(default=None)
116
- color: Union[str, Any] = Field(default=None)
117
- created_at: Union[str, Any] = Field(default=None)
118
- created_by: Union[ProjectCurrentStatusCreatedBy, Any] = Field(default=None)
119
- modified_at: Union[str, Any] = Field(default=None)
115
+ name: Union[str, Any] = Field(default=None)
120
116
  resource_type: Union[str, Any] = Field(default=None)
121
- text: Union[str, Any] = Field(default=None)
122
- title: Union[str, Any] = Field(default=None)
123
117
 
124
- class ProjectMembersItem(BaseModel):
125
- """Nested schema for Project.members_item"""
118
+ class ProjectFollowersItem(BaseModel):
119
+ """Nested schema for Project.followers_item"""
126
120
  model_config = ConfigDict(extra="allow", populate_by_name=True)
127
121
 
128
122
  gid: Union[str, Any] = Field(default=None)
129
123
  name: Union[str, Any] = Field(default=None)
130
124
  resource_type: Union[str, Any] = Field(default=None)
131
125
 
132
- class ProjectWorkspace(BaseModel):
133
- """Nested schema for Project.workspace"""
126
+ class ProjectCurrentStatusCreatedBy(BaseModel):
127
+ """Nested schema for ProjectCurrentStatus.created_by"""
134
128
  model_config = ConfigDict(extra="allow", populate_by_name=True)
135
129
 
136
130
  gid: Union[str, Any] = Field(default=None)
137
131
  name: Union[str, Any] = Field(default=None)
138
132
  resource_type: Union[str, Any] = Field(default=None)
139
133
 
140
- class ProjectCurrentStatusUpdate(BaseModel):
141
- """Nested schema for Project.current_status_update"""
134
+ class ProjectCurrentStatusAuthor(BaseModel):
135
+ """Nested schema for ProjectCurrentStatus.author"""
142
136
  model_config = ConfigDict(extra="allow", populate_by_name=True)
143
137
 
144
138
  gid: Union[str, Any] = Field(default=None)
139
+ name: Union[str, Any] = Field(default=None)
145
140
  resource_type: Union[str, Any] = Field(default=None)
146
- resource_subtype: Union[str, Any] = Field(default=None)
147
- title: Union[str, Any] = Field(default=None)
148
141
 
149
- class ProjectOwner(BaseModel):
150
- """Nested schema for Project.owner"""
142
+ class ProjectCurrentStatus(BaseModel):
143
+ """Nested schema for Project.current_status"""
151
144
  model_config = ConfigDict(extra="allow", populate_by_name=True)
152
145
 
153
146
  gid: Union[str, Any] = Field(default=None)
154
- name: Union[str, Any] = Field(default=None)
147
+ author: Union[ProjectCurrentStatusAuthor, Any] = Field(default=None)
148
+ color: Union[str, Any] = Field(default=None)
149
+ created_at: Union[str, Any] = Field(default=None)
150
+ created_by: Union[ProjectCurrentStatusCreatedBy, Any] = Field(default=None)
151
+ modified_at: Union[str, Any] = Field(default=None)
155
152
  resource_type: Union[str, Any] = Field(default=None)
153
+ text: Union[str, Any] = Field(default=None)
154
+ title: Union[str, Any] = Field(default=None)
156
155
 
157
- class ProjectTeam(BaseModel):
158
- """Nested schema for Project.team"""
156
+ class ProjectOwner(BaseModel):
157
+ """Nested schema for Project.owner"""
159
158
  model_config = ConfigDict(extra="allow", populate_by_name=True)
160
159
 
161
160
  gid: Union[str, Any] = Field(default=None)
162
161
  name: Union[str, Any] = Field(default=None)
163
162
  resource_type: Union[str, Any] = Field(default=None)
164
163
 
165
- class ProjectFollowersItem(BaseModel):
166
- """Nested schema for Project.followers_item"""
164
+ class ProjectCurrentStatusUpdate(BaseModel):
165
+ """Nested schema for Project.current_status_update"""
167
166
  model_config = ConfigDict(extra="allow", populate_by_name=True)
168
167
 
169
168
  gid: Union[str, Any] = Field(default=None)
170
- name: Union[str, Any] = Field(default=None)
171
169
  resource_type: Union[str, Any] = Field(default=None)
170
+ resource_subtype: Union[str, Any] = Field(default=None)
171
+ title: Union[str, Any] = Field(default=None)
172
172
 
173
173
  class Project(BaseModel):
174
174
  """Full project object"""
@@ -3,7 +3,7 @@ Type definitions for asana 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-asana
3
- Version: 0.19.27
3
+ Version: 0.19.41
4
4
  Summary: Airbyte Asana 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
@@ -41,12 +37,14 @@ teams, and users for project tracking, workload analysis, and productivity insig
41
37
 
42
38
  ## Example questions
43
39
 
40
+ The Asana connector is optimized to handle prompts like these.
41
+
44
42
  - What tasks are assigned to me this week?
45
43
  - List all projects in my workspace
46
44
  - Summarize my team's workload and task completion rates
47
- - Show me the tasks for the {project_name} project
48
- - Who are the team members in my {team_name} team?
49
- - Find all tasks related to {client_name} across my workspaces
45
+ - Show me the tasks for the \{project_name\} project
46
+ - Who are the team members in my \{team_name\} team?
47
+ - Find all tasks related to \{client_name\} across my workspaces
50
48
  - Analyze the most active projects in my workspace last month
51
49
  - Compare task completion rates between my different teams
52
50
  - Identify overdue tasks across all my projects
@@ -54,6 +52,8 @@ teams, and users for project tracking, workload analysis, and productivity insig
54
52
 
55
53
  ## Unsupported questions
56
54
 
55
+ The Asana connector isn't currently able to handle prompts like these.
56
+
57
57
  - Create a new task for [TeamMember]
58
58
  - Update the priority of this task
59
59
  - Delete the project [ProjectName]
@@ -139,6 +139,6 @@ For the service's official API docs, see the [Asana API reference](https://devel
139
139
 
140
140
  ## Version information
141
141
 
142
- - **Package version:** 0.19.27
142
+ - **Package version:** 0.19.41
143
143
  - **Connector version:** 0.1.6
144
- - **Generated with Connector SDK commit SHA:** 0eb1b1c4afe2ae6607371288233ef427ccad1b80
144
+ - **Generated with Connector SDK commit SHA:** a23d9e7ac2d9d416258f7a9a3b9a731782cd6bd8