threadify-sdk 0.2.5__tar.gz → 0.2.7__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.
- {threadify_sdk-0.2.5/threadify_sdk.egg-info → threadify_sdk-0.2.7}/PKG-INFO +35 -3
- {threadify_sdk-0.2.5 → threadify_sdk-0.2.7}/README.md +33 -1
- {threadify_sdk-0.2.5 → threadify_sdk-0.2.7}/pyproject.toml +2 -2
- {threadify_sdk-0.2.5 → threadify_sdk-0.2.7}/threadify/__init__.py +2 -0
- {threadify_sdk-0.2.5 → threadify_sdk-0.2.7}/threadify/client.py +4 -0
- {threadify_sdk-0.2.5 → threadify_sdk-0.2.7}/threadify/connection.py +5 -2
- {threadify_sdk-0.2.5 → threadify_sdk-0.2.7}/threadify/models.py +6 -0
- {threadify_sdk-0.2.5 → threadify_sdk-0.2.7}/threadify/otel_exporter.py +17 -0
- {threadify_sdk-0.2.5 → threadify_sdk-0.2.7}/threadify/thread.py +5 -0
- {threadify_sdk-0.2.5 → threadify_sdk-0.2.7/threadify_sdk.egg-info}/PKG-INFO +35 -3
- {threadify_sdk-0.2.5 → threadify_sdk-0.2.7}/CHANGELOG.md +0 -0
- {threadify_sdk-0.2.5 → threadify_sdk-0.2.7}/LICENSE +0 -0
- {threadify_sdk-0.2.5 → threadify_sdk-0.2.7}/MANIFEST.in +0 -0
- {threadify_sdk-0.2.5 → threadify_sdk-0.2.7}/setup.cfg +0 -0
- {threadify_sdk-0.2.5 → threadify_sdk-0.2.7}/tests/test_client.py +0 -0
- {threadify_sdk-0.2.5 → threadify_sdk-0.2.7}/tests/test_connection.py +0 -0
- {threadify_sdk-0.2.5 → threadify_sdk-0.2.7}/tests/test_data_retriever.py +0 -0
- {threadify_sdk-0.2.5 → threadify_sdk-0.2.7}/tests/test_models.py +0 -0
- {threadify_sdk-0.2.5 → threadify_sdk-0.2.7}/tests/test_notification.py +0 -0
- {threadify_sdk-0.2.5 → threadify_sdk-0.2.7}/tests/test_step.py +0 -0
- {threadify_sdk-0.2.5 → threadify_sdk-0.2.7}/tests/test_thread.py +0 -0
- {threadify_sdk-0.2.5 → threadify_sdk-0.2.7}/threadify/data_retriever.py +0 -0
- {threadify_sdk-0.2.5 → threadify_sdk-0.2.7}/threadify/notification.py +0 -0
- {threadify_sdk-0.2.5 → threadify_sdk-0.2.7}/threadify/step.py +0 -0
- {threadify_sdk-0.2.5 → threadify_sdk-0.2.7}/threadify_sdk.egg-info/SOURCES.txt +0 -0
- {threadify_sdk-0.2.5 → threadify_sdk-0.2.7}/threadify_sdk.egg-info/dependency_links.txt +0 -0
- {threadify_sdk-0.2.5 → threadify_sdk-0.2.7}/threadify_sdk.egg-info/requires.txt +0 -0
- {threadify_sdk-0.2.5 → threadify_sdk-0.2.7}/threadify_sdk.egg-info/top_level.txt +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: threadify-sdk
|
|
3
|
-
Version: 0.2.
|
|
4
|
-
Summary: Python SDK for Threadify —
|
|
3
|
+
Version: 0.2.7
|
|
4
|
+
Summary: Python SDK for Threadify — Service-delivery intelligence. Track every customer request from start to finish across every system, team, and partner. Visit: https://threadify.dev
|
|
5
5
|
Author-email: Threadify Team <team@threadify.dev>
|
|
6
6
|
License: MIT
|
|
7
7
|
Keywords: threadify,workflow,orchestration,websocket,graphql
|
|
@@ -27,7 +27,7 @@ Dynamic: license-file
|
|
|
27
27
|
|
|
28
28
|
# Threadify Python SDK
|
|
29
29
|
|
|
30
|
-
Python SDK for [Threadify](https://threadify.dev) —
|
|
30
|
+
Python SDK for [Threadify](https://threadify.dev) — Service-delivery intelligence that tracks every customer request from start to finish across every system, team, and partner.
|
|
31
31
|
|
|
32
32
|
- **Documentation:** [https://docs.threadify.dev](https://docs.threadify.dev)
|
|
33
33
|
- **Create an account:** [https://threadify.dev](https://threadify.dev)
|
|
@@ -167,6 +167,38 @@ This SDK follows [Semantic Versioning](https://semver.org/) and [Conventional Co
|
|
|
167
167
|
- `feat: ...` -> Minor bump
|
|
168
168
|
- `feat!: ...` or `BREAKING CHANGE: ...` -> Major bump
|
|
169
169
|
|
|
170
|
+
## OpenTelemetry Integration
|
|
171
|
+
|
|
172
|
+
The Python SDK includes the OpenTelemetry SpanExporter in the core package.
|
|
173
|
+
|
|
174
|
+
```python
|
|
175
|
+
from opentelemetry import trace
|
|
176
|
+
from opentelemetry.sdk.trace import TracerProvider
|
|
177
|
+
from opentelemetry.sdk.trace.export import BatchSpanProcessor
|
|
178
|
+
from threadify import Threadify
|
|
179
|
+
|
|
180
|
+
conn = await Threadify.connect("api-key", service_name="checkout-service")
|
|
181
|
+
|
|
182
|
+
# Create exporter
|
|
183
|
+
exporter = conn.create_span_exporter(options={"refs": ["order.id", "customer.id"]})
|
|
184
|
+
|
|
185
|
+
# Filter spans by name — exact match or prefix wildcard with *
|
|
186
|
+
exporter = conn.create_span_exporter(options={
|
|
187
|
+
"refs": ["order.id", "customer.id"],
|
|
188
|
+
"filters": ["invoke_llm", "adk.before*", "llm.*"],
|
|
189
|
+
})
|
|
190
|
+
|
|
191
|
+
provider = TracerProvider()
|
|
192
|
+
provider.add_span_processor(BatchSpanProcessor(exporter))
|
|
193
|
+
trace.set_tracer_provider(provider)
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
**Filter patterns:**
|
|
197
|
+
|
|
198
|
+
- `"invoke_llm"` — exact match
|
|
199
|
+
- `"adk.before*"` — prefix wildcard, drops any span starting with `adk.before`
|
|
200
|
+
- `"llm.*"` — prefix wildcard, drops any span starting with `llm.`
|
|
201
|
+
|
|
170
202
|
## Testing
|
|
171
203
|
|
|
172
204
|
To run the SDK tests, execute:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Threadify Python SDK
|
|
2
2
|
|
|
3
|
-
Python SDK for [Threadify](https://threadify.dev) —
|
|
3
|
+
Python SDK for [Threadify](https://threadify.dev) — Service-delivery intelligence that tracks every customer request from start to finish across every system, team, and partner.
|
|
4
4
|
|
|
5
5
|
- **Documentation:** [https://docs.threadify.dev](https://docs.threadify.dev)
|
|
6
6
|
- **Create an account:** [https://threadify.dev](https://threadify.dev)
|
|
@@ -140,6 +140,38 @@ This SDK follows [Semantic Versioning](https://semver.org/) and [Conventional Co
|
|
|
140
140
|
- `feat: ...` -> Minor bump
|
|
141
141
|
- `feat!: ...` or `BREAKING CHANGE: ...` -> Major bump
|
|
142
142
|
|
|
143
|
+
## OpenTelemetry Integration
|
|
144
|
+
|
|
145
|
+
The Python SDK includes the OpenTelemetry SpanExporter in the core package.
|
|
146
|
+
|
|
147
|
+
```python
|
|
148
|
+
from opentelemetry import trace
|
|
149
|
+
from opentelemetry.sdk.trace import TracerProvider
|
|
150
|
+
from opentelemetry.sdk.trace.export import BatchSpanProcessor
|
|
151
|
+
from threadify import Threadify
|
|
152
|
+
|
|
153
|
+
conn = await Threadify.connect("api-key", service_name="checkout-service")
|
|
154
|
+
|
|
155
|
+
# Create exporter
|
|
156
|
+
exporter = conn.create_span_exporter(options={"refs": ["order.id", "customer.id"]})
|
|
157
|
+
|
|
158
|
+
# Filter spans by name — exact match or prefix wildcard with *
|
|
159
|
+
exporter = conn.create_span_exporter(options={
|
|
160
|
+
"refs": ["order.id", "customer.id"],
|
|
161
|
+
"filters": ["invoke_llm", "adk.before*", "llm.*"],
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
provider = TracerProvider()
|
|
165
|
+
provider.add_span_processor(BatchSpanProcessor(exporter))
|
|
166
|
+
trace.set_tracer_provider(provider)
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
**Filter patterns:**
|
|
170
|
+
|
|
171
|
+
- `"invoke_llm"` — exact match
|
|
172
|
+
- `"adk.before*"` — prefix wildcard, drops any span starting with `adk.before`
|
|
173
|
+
- `"llm.*"` — prefix wildcard, drops any span starting with `llm.`
|
|
174
|
+
|
|
143
175
|
## Testing
|
|
144
176
|
|
|
145
177
|
To run the SDK tests, execute:
|
|
@@ -4,8 +4,8 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "threadify-sdk"
|
|
7
|
-
version = "0.2.
|
|
8
|
-
description = "Python SDK for Threadify —
|
|
7
|
+
version = "0.2.7"
|
|
8
|
+
description = "Python SDK for Threadify — Service-delivery intelligence. Track every customer request from start to finish across every system, team, and partner. Visit: https://threadify.dev"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
11
11
|
license = {text = "MIT"}
|
|
@@ -5,6 +5,7 @@ from threadify.client import (
|
|
|
5
5
|
from threadify.connection import Connection
|
|
6
6
|
from threadify.data_retriever import ArchivedStep, ArchivedThread, DataRetriever
|
|
7
7
|
from threadify.models import (
|
|
8
|
+
AccessLevel,
|
|
8
9
|
CompleteDataOptions,
|
|
9
10
|
ConnectOptions,
|
|
10
11
|
HistoryQueryOptions,
|
|
@@ -46,6 +47,7 @@ __all__ = [
|
|
|
46
47
|
"RefQuery",
|
|
47
48
|
"CompleteDataOptions",
|
|
48
49
|
"HistoryQueryOptions",
|
|
50
|
+
"AccessLevel",
|
|
49
51
|
]
|
|
50
52
|
|
|
51
53
|
__version__ = "0.1.0"
|
|
@@ -64,6 +64,10 @@ def _build_connect_options(
|
|
|
64
64
|
class Threadify:
|
|
65
65
|
"""Factory for creating Threadify connections."""
|
|
66
66
|
|
|
67
|
+
FOR_EXTERNAL = "external"
|
|
68
|
+
FOR_OBSERVER = "observer"
|
|
69
|
+
FOR_PARTICIPANT = "participant"
|
|
70
|
+
|
|
67
71
|
@staticmethod
|
|
68
72
|
async def connect(
|
|
69
73
|
api_key: str,
|
|
@@ -182,7 +182,7 @@ class Connection:
|
|
|
182
182
|
raise RuntimeError(resp.get(FIELD_MESSAGE, "failed to start thread"))
|
|
183
183
|
|
|
184
184
|
thread_id = resp[FIELD_THREAD_ID]
|
|
185
|
-
thread = ThreadInstance(self, thread_id, contract_name, "", None)
|
|
185
|
+
thread = ThreadInstance(self, thread_id, contract_name, "", resp.get(FIELD_ACCESS_LEVEL, ""), None)
|
|
186
186
|
self._threads[thread_id] = thread
|
|
187
187
|
self._logger.debug(f"Thread started: {thread_id}")
|
|
188
188
|
return thread
|
|
@@ -231,7 +231,7 @@ class Connection:
|
|
|
231
231
|
|
|
232
232
|
thread_id = resp[FIELD_THREAD_ID]
|
|
233
233
|
thread_role = resp.get(FIELD_ROLE, "")
|
|
234
|
-
thread = ThreadInstance(self, thread_id, resp.get("contractId", ""), thread_role, None)
|
|
234
|
+
thread = ThreadInstance(self, thread_id, resp.get("contractId", ""), thread_role, resp.get(FIELD_ACCESS_LEVEL, ""), None)
|
|
235
235
|
self._threads[thread_id] = thread
|
|
236
236
|
self._logger.debug(f"Joined thread: {thread_id}, Role: {thread_role}")
|
|
237
237
|
return thread
|
|
@@ -464,6 +464,9 @@ class Connection:
|
|
|
464
464
|
Args:
|
|
465
465
|
options: Optional configuration dict. Supported keys:
|
|
466
466
|
- ``refs``: list of attribute keys to map to Threadify refs.
|
|
467
|
+
- ``filters``: list of span-name patterns to drop. A trailing ``*``
|
|
468
|
+
acts as a wildcard prefix match; otherwise an exact match is used.
|
|
469
|
+
Example: ``["invoke_llm", "adk.before*", "llm.*"]``.
|
|
467
470
|
|
|
468
471
|
Returns:
|
|
469
472
|
A :class:`~threadify.otel_exporter.ThreadifySpanExporter` instance.
|
|
@@ -109,6 +109,12 @@ class ValidationSeverity(str, Enum):
|
|
|
109
109
|
CRITICAL = "critical"
|
|
110
110
|
|
|
111
111
|
|
|
112
|
+
class AccessLevel(str, Enum):
|
|
113
|
+
EXTERNAL = "external"
|
|
114
|
+
OBSERVER = "observer"
|
|
115
|
+
PARTICIPANT = "participant"
|
|
116
|
+
|
|
117
|
+
|
|
112
118
|
@dataclass
|
|
113
119
|
class ConnectOptions:
|
|
114
120
|
"""Configuration for connecting to the Threadify Engine."""
|
|
@@ -73,6 +73,9 @@ class ThreadifySpanExporter(_SpanExporterBase):
|
|
|
73
73
|
else:
|
|
74
74
|
self._refs_map = {}
|
|
75
75
|
|
|
76
|
+
# Span-name filters; e.g. ["invoke_llm", "adk.before*", "llm.*"]
|
|
77
|
+
self._filters: list[str] = self._options.get("filters", [])
|
|
78
|
+
|
|
76
79
|
# trace_id -> asyncio.Future[ThreadInstance]
|
|
77
80
|
self._trace_threads: dict[str, asyncio.Future[Any]] = {}
|
|
78
81
|
|
|
@@ -111,6 +114,8 @@ class ThreadifySpanExporter(_SpanExporterBase):
|
|
|
111
114
|
|
|
112
115
|
async def _process_all(self, spans: list[ReadableSpan]) -> None:
|
|
113
116
|
for span in spans:
|
|
117
|
+
if self._should_drop(span.name):
|
|
118
|
+
continue
|
|
114
119
|
await self._process_span(span)
|
|
115
120
|
|
|
116
121
|
async def _process_span(self, span: ReadableSpan) -> None:
|
|
@@ -276,6 +281,18 @@ class ThreadifySpanExporter(_SpanExporterBase):
|
|
|
276
281
|
|
|
277
282
|
return await self._trace_threads[trace_id]
|
|
278
283
|
|
|
284
|
+
def _should_drop(self, name: str) -> bool:
|
|
285
|
+
for f in self._filters:
|
|
286
|
+
if not f:
|
|
287
|
+
continue
|
|
288
|
+
if f.endswith("*"):
|
|
289
|
+
if name.startswith(f[:-1]):
|
|
290
|
+
return True
|
|
291
|
+
continue
|
|
292
|
+
if name == f:
|
|
293
|
+
return True
|
|
294
|
+
return False
|
|
295
|
+
|
|
279
296
|
@staticmethod
|
|
280
297
|
def _span_attr(span: ReadableSpan, key: str) -> str | None:
|
|
281
298
|
value = span.attributes.get(key)
|
|
@@ -62,12 +62,14 @@ class ThreadInstance:
|
|
|
62
62
|
thread_id: str,
|
|
63
63
|
contract_id: str = "",
|
|
64
64
|
role: str = "",
|
|
65
|
+
access_level: str = "",
|
|
65
66
|
refs: dict[str, str] | None = None,
|
|
66
67
|
):
|
|
67
68
|
self._conn = conn
|
|
68
69
|
self.thread_id = thread_id
|
|
69
70
|
self.contract_id = contract_id
|
|
70
71
|
self.role = role
|
|
72
|
+
self.access_level = access_level
|
|
71
73
|
self.refs: dict[str, str] = refs or {}
|
|
72
74
|
|
|
73
75
|
self._steps: dict[str, Any] = {}
|
|
@@ -298,6 +300,9 @@ class ThreadInstance:
|
|
|
298
300
|
Args:
|
|
299
301
|
options: Optional configuration dict. Supported keys:
|
|
300
302
|
- ``refs``: list of attribute keys to map to Threadify refs.
|
|
303
|
+
- ``filters``: list of span-name patterns to drop. A trailing ``*``
|
|
304
|
+
acts as a wildcard prefix match; otherwise an exact match is used.
|
|
305
|
+
Example: ``["invoke_llm", "adk.before*", "llm.*"]``.
|
|
301
306
|
|
|
302
307
|
Returns:
|
|
303
308
|
A :class:`~threadify.otel_exporter.ThreadifySpanExporter` instance.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: threadify-sdk
|
|
3
|
-
Version: 0.2.
|
|
4
|
-
Summary: Python SDK for Threadify —
|
|
3
|
+
Version: 0.2.7
|
|
4
|
+
Summary: Python SDK for Threadify — Service-delivery intelligence. Track every customer request from start to finish across every system, team, and partner. Visit: https://threadify.dev
|
|
5
5
|
Author-email: Threadify Team <team@threadify.dev>
|
|
6
6
|
License: MIT
|
|
7
7
|
Keywords: threadify,workflow,orchestration,websocket,graphql
|
|
@@ -27,7 +27,7 @@ Dynamic: license-file
|
|
|
27
27
|
|
|
28
28
|
# Threadify Python SDK
|
|
29
29
|
|
|
30
|
-
Python SDK for [Threadify](https://threadify.dev) —
|
|
30
|
+
Python SDK for [Threadify](https://threadify.dev) — Service-delivery intelligence that tracks every customer request from start to finish across every system, team, and partner.
|
|
31
31
|
|
|
32
32
|
- **Documentation:** [https://docs.threadify.dev](https://docs.threadify.dev)
|
|
33
33
|
- **Create an account:** [https://threadify.dev](https://threadify.dev)
|
|
@@ -167,6 +167,38 @@ This SDK follows [Semantic Versioning](https://semver.org/) and [Conventional Co
|
|
|
167
167
|
- `feat: ...` -> Minor bump
|
|
168
168
|
- `feat!: ...` or `BREAKING CHANGE: ...` -> Major bump
|
|
169
169
|
|
|
170
|
+
## OpenTelemetry Integration
|
|
171
|
+
|
|
172
|
+
The Python SDK includes the OpenTelemetry SpanExporter in the core package.
|
|
173
|
+
|
|
174
|
+
```python
|
|
175
|
+
from opentelemetry import trace
|
|
176
|
+
from opentelemetry.sdk.trace import TracerProvider
|
|
177
|
+
from opentelemetry.sdk.trace.export import BatchSpanProcessor
|
|
178
|
+
from threadify import Threadify
|
|
179
|
+
|
|
180
|
+
conn = await Threadify.connect("api-key", service_name="checkout-service")
|
|
181
|
+
|
|
182
|
+
# Create exporter
|
|
183
|
+
exporter = conn.create_span_exporter(options={"refs": ["order.id", "customer.id"]})
|
|
184
|
+
|
|
185
|
+
# Filter spans by name — exact match or prefix wildcard with *
|
|
186
|
+
exporter = conn.create_span_exporter(options={
|
|
187
|
+
"refs": ["order.id", "customer.id"],
|
|
188
|
+
"filters": ["invoke_llm", "adk.before*", "llm.*"],
|
|
189
|
+
})
|
|
190
|
+
|
|
191
|
+
provider = TracerProvider()
|
|
192
|
+
provider.add_span_processor(BatchSpanProcessor(exporter))
|
|
193
|
+
trace.set_tracer_provider(provider)
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
**Filter patterns:**
|
|
197
|
+
|
|
198
|
+
- `"invoke_llm"` — exact match
|
|
199
|
+
- `"adk.before*"` — prefix wildcard, drops any span starting with `adk.before`
|
|
200
|
+
- `"llm.*"` — prefix wildcard, drops any span starting with `llm.`
|
|
201
|
+
|
|
170
202
|
## Testing
|
|
171
203
|
|
|
172
204
|
To run the SDK tests, execute:
|
|
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
|