stemtrace 0.1.0__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.
Files changed (72) hide show
  1. stemtrace/__init__.py +173 -0
  2. stemtrace/core/__init__.py +15 -0
  3. stemtrace/core/events.py +67 -0
  4. stemtrace/core/exceptions.py +25 -0
  5. stemtrace/core/graph.py +348 -0
  6. stemtrace/core/ports.py +42 -0
  7. stemtrace/library/__init__.py +1 -0
  8. stemtrace/library/bootsteps.py +169 -0
  9. stemtrace/library/config.py +55 -0
  10. stemtrace/library/scrubbing.py +195 -0
  11. stemtrace/library/signals.py +434 -0
  12. stemtrace/library/transports/__init__.py +36 -0
  13. stemtrace/library/transports/memory.py +33 -0
  14. stemtrace/library/transports/redis.py +92 -0
  15. stemtrace/py.typed +0 -0
  16. stemtrace/server/__init__.py +24 -0
  17. stemtrace/server/__main__.py +136 -0
  18. stemtrace/server/api/__init__.py +29 -0
  19. stemtrace/server/api/routes.py +270 -0
  20. stemtrace/server/api/schemas.py +136 -0
  21. stemtrace/server/api/websocket.py +28 -0
  22. stemtrace/server/consumer.py +133 -0
  23. stemtrace/server/fastapi/__init__.py +13 -0
  24. stemtrace/server/fastapi/auth.py +77 -0
  25. stemtrace/server/fastapi/extension.py +121 -0
  26. stemtrace/server/fastapi/router.py +42 -0
  27. stemtrace/server/store.py +260 -0
  28. stemtrace/server/ui/__init__.py +5 -0
  29. stemtrace/server/ui/frontend/biome.json +58 -0
  30. stemtrace/server/ui/frontend/dist/assets/index-CCs7iO1n.css +1 -0
  31. stemtrace/server/ui/frontend/dist/assets/index-Dao0_Q6x.js +14 -0
  32. stemtrace/server/ui/frontend/dist/index.html +17 -0
  33. stemtrace/server/ui/frontend/index.html +16 -0
  34. stemtrace/server/ui/frontend/package-lock.json +4049 -0
  35. stemtrace/server/ui/frontend/package.json +46 -0
  36. stemtrace/server/ui/frontend/playwright.config.ts +40 -0
  37. stemtrace/server/ui/frontend/postcss.config.js +5 -0
  38. stemtrace/server/ui/frontend/src/api/client.ts +173 -0
  39. stemtrace/server/ui/frontend/src/api/queries.ts +151 -0
  40. stemtrace/server/ui/frontend/src/components/DateRangePicker.tsx +244 -0
  41. stemtrace/server/ui/frontend/src/components/Filters.tsx +116 -0
  42. stemtrace/server/ui/frontend/src/components/TaskGraph.tsx +453 -0
  43. stemtrace/server/ui/frontend/src/components/TaskList.tsx +172 -0
  44. stemtrace/server/ui/frontend/src/components/TaskStateBadge.tsx +27 -0
  45. stemtrace/server/ui/frontend/src/components/TaskTimeline.tsx +144 -0
  46. stemtrace/server/ui/frontend/src/components/TimelineBar.tsx +224 -0
  47. stemtrace/server/ui/frontend/src/components/Tooltip.tsx +54 -0
  48. stemtrace/server/ui/frontend/src/hooks/WebSocketContext.tsx +143 -0
  49. stemtrace/server/ui/frontend/src/hooks/useInfiniteScroll.ts +56 -0
  50. stemtrace/server/ui/frontend/src/index.css +104 -0
  51. stemtrace/server/ui/frontend/src/main.tsx +44 -0
  52. stemtrace/server/ui/frontend/src/routes/__root.tsx +103 -0
  53. stemtrace/server/ui/frontend/src/routes/graph.$rootId.tsx +51 -0
  54. stemtrace/server/ui/frontend/src/routes/graphs.tsx +186 -0
  55. stemtrace/server/ui/frontend/src/routes/index.tsx +119 -0
  56. stemtrace/server/ui/frontend/src/routes/registry.tsx +211 -0
  57. stemtrace/server/ui/frontend/src/routes/tasks.$taskId.tsx +313 -0
  58. stemtrace/server/ui/frontend/src/utils/format.ts +38 -0
  59. stemtrace/server/ui/frontend/tests/graphs.spec.ts +485 -0
  60. stemtrace/server/ui/frontend/tests/registry.spec.ts +117 -0
  61. stemtrace/server/ui/frontend/tests/task-detail.spec.ts +147 -0
  62. stemtrace/server/ui/frontend/tests/tasks.spec.ts +92 -0
  63. stemtrace/server/ui/frontend/tsconfig.json +32 -0
  64. stemtrace/server/ui/frontend/tsconfig.tsbuildinfo +1 -0
  65. stemtrace/server/ui/frontend/vite.config.ts +30 -0
  66. stemtrace/server/ui/static.py +56 -0
  67. stemtrace/server/websocket.py +99 -0
  68. stemtrace-0.1.0.dist-info/METADATA +428 -0
  69. stemtrace-0.1.0.dist-info/RECORD +72 -0
  70. stemtrace-0.1.0.dist-info/WHEEL +4 -0
  71. stemtrace-0.1.0.dist-info/entry_points.txt +2 -0
  72. stemtrace-0.1.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,428 @@
1
+ Metadata-Version: 2.4
2
+ Name: stemtrace
3
+ Version: 0.1.0
4
+ Summary: A lightweight Celery task flow visualizer
5
+ Project-URL: Homepage, https://github.com/iansokolskyi/stemtrace
6
+ Project-URL: Documentation, https://github.com/iansokolskyi/stemtrace#readme
7
+ Project-URL: Repository, https://github.com/iansokolskyi/stemtrace
8
+ Project-URL: Issues, https://github.com/iansokolskyi/stemtrace/issues
9
+ Project-URL: Changelog, https://github.com/iansokolskyi/stemtrace/blob/main/CHANGELOG.md
10
+ Author-email: Ian Sokolskyi <iansokolskyi@gmail.com>
11
+ License: MIT
12
+ License-File: LICENSE
13
+ Keywords: celery,monitoring,queue,task,visualization,workflow
14
+ Classifier: Development Status :: 3 - Alpha
15
+ Classifier: Environment :: Console
16
+ Classifier: Environment :: Web Environment
17
+ Classifier: Framework :: Celery
18
+ Classifier: Intended Audience :: Developers
19
+ Classifier: License :: OSI Approved :: MIT License
20
+ Classifier: Operating System :: OS Independent
21
+ Classifier: Programming Language :: Python :: 3
22
+ Classifier: Programming Language :: Python :: 3.10
23
+ Classifier: Programming Language :: Python :: 3.11
24
+ Classifier: Programming Language :: Python :: 3.12
25
+ Classifier: Programming Language :: Python :: 3.13
26
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
27
+ Classifier: Topic :: System :: Monitoring
28
+ Classifier: Typing :: Typed
29
+ Requires-Python: >=3.10
30
+ Requires-Dist: celery>=5.0.0
31
+ Requires-Dist: fastapi>=0.100.0
32
+ Requires-Dist: httpx>=0.24.0
33
+ Requires-Dist: pydantic>=2.0.0
34
+ Requires-Dist: redis>=4.0.0
35
+ Requires-Dist: typer>=0.9.0
36
+ Requires-Dist: typing-extensions>=4.0.0
37
+ Requires-Dist: uvicorn[standard]>=0.20.0
38
+ Provides-Extra: dev
39
+ Requires-Dist: build>=1.0.0; extra == 'dev'
40
+ Requires-Dist: bump-my-version>=0.28.0; extra == 'dev'
41
+ Requires-Dist: hatchling>=1.20.0; extra == 'dev'
42
+ Requires-Dist: mypy>=1.0.0; extra == 'dev'
43
+ Requires-Dist: pika>=1.3.0; extra == 'dev'
44
+ Requires-Dist: pre-commit>=3.0.0; extra == 'dev'
45
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
46
+ Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
47
+ Requires-Dist: pytest>=7.0.0; extra == 'dev'
48
+ Requires-Dist: ruff>=0.1.0; extra == 'dev'
49
+ Requires-Dist: twine>=5.0.0; extra == 'dev'
50
+ Requires-Dist: types-redis>=4.0.0; extra == 'dev'
51
+ Requires-Dist: websockets>=12.0; extra == 'dev'
52
+ Provides-Extra: rabbitmq
53
+ Requires-Dist: pika>=1.3.0; extra == 'rabbitmq'
54
+ Description-Content-Type: text/markdown
55
+
56
+ # stemtrace 🌿
57
+
58
+ **Zero-infrastructure Celery task flow visualizer**
59
+
60
+ [![PyPI version](https://badge.fury.io/py/stemtrace.svg)](https://badge.fury.io/py/stemtrace)
61
+ [![Python](https://img.shields.io/pypi/pyversions/stemtrace.svg)](https://pypi.org/project/stemtrace/)
62
+ [![CI](https://github.com/iansokolskyi/stemtrace/actions/workflows/ci.yml/badge.svg)](https://github.com/iansokolskyi/stemtrace/actions/workflows/ci.yml)
63
+ [![codecov](https://codecov.io/gh/iansokolskyi/stemtrace/graph/badge.svg)](https://codecov.io/gh/iansokolskyi/stemtrace)
64
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
65
+ [![Code style: ruff](https://img.shields.io/badge/code%20style-ruff-000000.svg)](https://github.com/astral-sh/ruff)
66
+ [![Type checked: mypy](https://img.shields.io/badge/type%20checked-mypy-blue.svg)](https://mypy-lang.org/)
67
+
68
+ ---
69
+
70
+ > **Flower answers "what exists". stemtrace answers "what happened".**
71
+
72
+ `stemtrace` models Celery as a graph of executions derived from events. Visualize task flows, timelines, retries, and parent-child relationships — using your existing broker with zero new infrastructure.
73
+
74
+ ## ✨ Features
75
+
76
+ - **Task Flow Graphs** — Visualize parent → child chains, groups, and chords as DAGs
77
+ - **Canvas Awareness** — Synthetic GROUP nodes for `group()` and `chord()` visualization
78
+ - **Execution Timeline** — See queued → received → started → retried → finished states
79
+ - **Full Lifecycle Capture** — PENDING, RECEIVED, STARTED, RETRY, SUCCESS, FAILURE states
80
+ - **Arguments & Results** — View task inputs and outputs with sensitive data scrubbing
81
+ - **Exception Capture** — Full traceback visibility on retries and failures
82
+ - **Task Registry** — Browse all discovered task definitions
83
+ - **Timing Visibility** — Start time and duration shown directly in graph nodes
84
+ - **Correlation Tracking** — Trace requests across multiple tasks via `trace_id`
85
+ - **Retry Visibility** — Know exactly which retries happened and why
86
+ - **Zero Infrastructure** — Uses your existing broker; no database required
87
+ - **Broker-Agnostic** — Works with Redis, RabbitMQ, and other Celery brokers
88
+ - **FastAPI Pluggable** — Mount directly into your existing FastAPI app
89
+ - **Zero Config** — Auto-detects your Celery broker configuration
90
+ - **Read-Only** — Safe for production; never modifies your task queue
91
+
92
+ ## 🚀 Quick Start
93
+
94
+ ### 1. Install
95
+
96
+ ```bash
97
+ pip install stemtrace
98
+ ```
99
+
100
+ ### 2. Instrument your Celery app
101
+
102
+ ```python
103
+ from celery import Celery
104
+ import stemtrace
105
+
106
+ app = Celery("myapp", broker="redis://localhost:6379/0")
107
+
108
+ # One line to enable flow tracking
109
+ stemtrace.init(app)
110
+ ```
111
+
112
+ ### 3. Run the visualizer
113
+
114
+ ```bash
115
+ stemtrace server
116
+ ```
117
+
118
+ Open [http://localhost:8000](http://localhost:8000) and watch your task flows come alive.
119
+
120
+ > By default, connects to `redis://localhost:6379/0`. Override with `--broker-url` or `STEMTRACE_BROKER_URL` env var.
121
+
122
+ See [Deployment Options](#️-deployment-options) for FastAPI integration and production setups.
123
+
124
+ ## 📦 Architecture
125
+
126
+ stemtrace is designed as two decoupled components:
127
+
128
+ ```text
129
+ ┌──────────────────────────────────────────────────────────────────┐
130
+ │ Your Application │
131
+ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
132
+ │ │ Celery Worker│ │ Celery Worker│ │ Celery Worker│ │
133
+ │ │ + stemtrace │ │ + stemtrace │ │ + stemtrace │ │
134
+ │ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │
135
+ │ │ │ │ │
136
+ │ └───────────────────┼───────────────────┘ │
137
+ │ │ events │
138
+ │ ▼ │
139
+ │ ┌───────────────┐ │
140
+ │ │ Broker │ │
141
+ │ └───────┬───────┘ │
142
+ │ │ │
143
+ └─────────────────────────────┼────────────────────────────────────┘
144
+ │
145
+ ▼
146
+ ┌───────────────────┐
147
+ │ stemtrace │
148
+ │ server (viewer) │
149
+ │ ┌─────────────┐ │
150
+ │ │ Web UI │ │
151
+ │ └─────────────┘ │
152
+ └───────────────────┘
153
+ ```
154
+
155
+ ### Library (`stemtrace`)
156
+ - Hooks into Celery signals
157
+ - Captures task lifecycle events
158
+ - Sends normalized events to the broker
159
+ - **Zero overhead in critical path** — fire-and-forget writes
160
+
161
+ ### Server (`stemtrace server`)
162
+ - Reads events from the broker
163
+ - Builds task graphs
164
+ - Serves the web UI
165
+ - **Completely read-only** — safe for production
166
+
167
+ ## 🔧 Configuration
168
+
169
+ ### Library Options
170
+
171
+ ```python
172
+ import stemtrace
173
+
174
+ stemtrace.init(
175
+ app,
176
+ # Optional: override broker URL (defaults to Celery's broker_url)
177
+ transport_url="redis://localhost:6379/0",
178
+ prefix="stemtrace", # Key/queue prefix
179
+ ttl=86400, # Event TTL in seconds (default: 24h)
180
+
181
+ # Data capture (all enabled by default)
182
+ capture_args=True, # Capture task args/kwargs
183
+ capture_result=True, # Capture return values
184
+
185
+ # Sensitive data scrubbing (Sentry-style)
186
+ scrub_sensitive_data=True, # Scrub passwords, API keys, etc.
187
+ additional_sensitive_keys=frozenset({"my_secret"}), # Add custom keys
188
+ safe_keys=frozenset({"public_key"}), # Never scrub these keys
189
+ )
190
+
191
+ # Introspection (after init)
192
+ stemtrace.is_initialized() # -> True
193
+ stemtrace.get_config() # -> StemtraceConfig
194
+ stemtrace.get_transport() # -> EventTransport (for testing)
195
+ ```
196
+
197
+ #### Sensitive Data Scrubbing
198
+
199
+ By default, stemtrace scrubs common sensitive keys from task arguments:
200
+ - Passwords: `password`, `passwd`, `pwd`, `secret`
201
+ - API keys: `api_key`, `apikey`, `token`, `bearer`, `authorization`
202
+ - Financial: `credit_card`, `cvv`, `ssn`
203
+ - Session: `cookie`, `session`, `csrf`
204
+
205
+ Scrubbed values appear as `[Filtered]` in the UI.
206
+
207
+ ### Canvas Graph Visualization
208
+
209
+ stemtrace automatically detects and visualizes Celery canvas constructs:
210
+
211
+ ```text
212
+ # Parent-spawned group: GROUP is child of parent
213
+ batch_processor
214
+ └── ┌─ GROUP ──────────┐
215
+ │ ├── add(1, 2) │
216
+ │ ├── add(3, 4) │
217
+ │ └── add(5, 6) │
218
+ └──────────────────┘
219
+
220
+ # Standalone group: GROUP is a root node
221
+ ┌─ GROUP ──────────┐
222
+ │ ├── add(1, 1) │
223
+ │ ├── add(2, 2) │
224
+ │ └── add(3, 3) │
225
+ └──────────────────┘
226
+
227
+ # Chord: header tasks inside, callback outside with edges
228
+ ┌─ CHORD ──────────┐
229
+ │ ├── add(10, 10) │──┐
230
+ │ ├── add(20, 20) │──┼──► aggregate_results
231
+ │ └── add(30, 30) │──┘
232
+ └──────────────────┘
233
+ ```
234
+
235
+ - **Synthetic containers** — GROUP/CHORD nodes are always created when 2+ tasks share a `group_id`
236
+ - **Parent linking** — When spawned from a parent task, the container becomes a child of that parent
237
+ - **Chord callbacks** — Rendered outside the container with edges from each header task
238
+ - **Timing** — Each node displays start time and duration directly in the graph
239
+ - **Aggregate state** — Container shows running/success/failure based on member states
240
+
241
+ ### Environment Variables
242
+
243
+ | Variable | Description | Default |
244
+ |----------|-------------|---------|
245
+ | `STEMTRACE_BROKER_URL` | Broker connection URL | Auto-detect from Celery |
246
+ | `STEMTRACE_TTL` | Event TTL in seconds | `86400` |
247
+ | `STEMTRACE_PREFIX` | Key/queue prefix | `stemtrace` |
248
+
249
+ ### Supported Brokers
250
+
251
+ | Broker | URL Scheme | Status |
252
+ |--------|------------|--------|
253
+ | Redis | `redis://`, `rediss://` | ✅ Supported |
254
+ | RabbitMQ | `amqp://`, `amqps://` | 🚧 Planned |
255
+ | Amazon SQS | `sqs://` | 🚧 Planned |
256
+
257
+ ## 🐳 Docker
258
+
259
+ ```bash
260
+ # With Redis
261
+ docker run -p 8000:8000 \
262
+ -e STEMTRACE_BROKER_URL=redis://host.docker.internal:6379/0 \
263
+ ghcr.io/stemtrace/server
264
+
265
+ # With RabbitMQ
266
+ docker run -p 8000:8000 \
267
+ -e STEMTRACE_BROKER_URL=amqp://guest:guest@host.docker.internal:5672/ \
268
+ ghcr.io/stemtrace/server
269
+ ```
270
+
271
+ Or with Docker Compose:
272
+
273
+ ```yaml
274
+ services:
275
+ stemtrace:
276
+ image: ghcr.io/stemtrace/server
277
+ ports:
278
+ - "8000:8000"
279
+ environment:
280
+ - STEMTRACE_BROKER_URL=redis://redis:6379/0
281
+ ```
282
+
283
+ ## 🖥️ Deployment Options
284
+
285
+ stemtrace offers two deployment modes depending on your needs:
286
+
287
+ | Mode | Best For | Command |
288
+ |------|----------|---------|
289
+ | **Standalone Server** | Dedicated monitoring, simple setup | `stemtrace server` |
290
+ | **FastAPI Embedded** | Single-app deployment, existing FastAPI apps | `StemtraceExtension` |
291
+
292
+ ### Option 1: Standalone Server (Recommended)
293
+
294
+ The simplest way to run stemtrace — a dedicated monitoring service:
295
+
296
+ ```bash
297
+ pip install stemtrace
298
+
299
+ stemtrace server
300
+ ```
301
+
302
+ Open [http://localhost:8000](http://localhost:8000) to view the dashboard.
303
+
304
+ #### Server Options
305
+
306
+ ```bash
307
+ stemtrace server \
308
+ --broker-url redis://myredis:6379/0 \
309
+ --host 0.0.0.0 \
310
+ --port 8000 \
311
+ --reload # For development
312
+ ```
313
+
314
+ #### High-Scale Production Setup
315
+
316
+ For high-throughput environments, run the consumer separately from the web server:
317
+
318
+ ```bash
319
+ # Terminal 1: Run consumer (processes events)
320
+ stemtrace consume
321
+
322
+ # Terminal 2: Run API server (separate process, shares state via broker)
323
+ stemtrace server
324
+ ```
325
+ ### Option 2: FastAPI Embedded
326
+
327
+ Mount stemtrace directly into your existing FastAPI application:
328
+
329
+ ```python
330
+ from fastapi import FastAPI
331
+ from stemtrace.server import StemtraceExtension
332
+
333
+ flow = StemtraceExtension(broker_url="redis://localhost:6379/0")
334
+ app = FastAPI(lifespan=flow.lifespan)
335
+ app.include_router(flow.router, prefix="/stemtrace")
336
+ ```
337
+
338
+ Access the dashboard at `/stemtrace/` within your app.
339
+
340
+ #### With Custom Authentication
341
+
342
+ Use your existing auth middleware:
343
+
344
+ ```python
345
+ from fastapi import Depends
346
+ from stemtrace.server import StemtraceExtension
347
+ from your_app.auth import require_admin
348
+
349
+ flow = StemtraceExtension(
350
+ broker_url="redis://localhost:6379/0",
351
+ auth_dependency=Depends(require_admin),
352
+ )
353
+ app = FastAPI(lifespan=flow.lifespan)
354
+ app.include_router(flow.router, prefix="/stemtrace")
355
+ ```
356
+
357
+ Or use built-in auth helpers:
358
+
359
+ ```python
360
+ from stemtrace.server import StemtraceExtension, require_basic_auth
361
+
362
+ flow = StemtraceExtension(
363
+ broker_url="redis://localhost:6379/0",
364
+ auth_dependency=require_basic_auth("admin", "secret"),
365
+ )
366
+ app = FastAPI(lifespan=flow.lifespan)
367
+ app.include_router(flow.router, prefix="/stemtrace")
368
+ ```
369
+
370
+ #### Embedded Consumer Modes
371
+
372
+ | Mode | Use Case | Setup |
373
+ |------|----------|-------|
374
+ | Embedded | Development, simple apps | Default — consumer runs in FastAPI process |
375
+ | External | Production, high scale | Run `stemtrace consume` separately |
376
+
377
+ ## 🗺️ Roadmap
378
+
379
+ ### Completed
380
+
381
+ - [x] Task lifecycle tracking via signals
382
+ - [x] Broker-agnostic event transport (Redis Streams)
383
+ - [x] FastAPI pluggable integration
384
+ - [x] React SPA dashboard with real-time WebSocket updates
385
+ - [x] Task flow graph visualization
386
+ - [x] Execution timeline view
387
+ - [x] Task args/kwargs capture with sensitive data scrubbing
388
+ - [x] Exception and traceback capture
389
+ - [x] Task registry (browse all discovered tasks)
390
+ - [x] PENDING/RECEIVED state capture
391
+ - [x] E2E test suite (Docker API tests + Playwright browser tests)
392
+ - [x] Canvas graph reconstruction (`group_id` capture, synthetic GROUP/CHORD nodes)
393
+ - [x] Chord callback linking (CHORD node → callback edge)
394
+ - [x] Timing display in graph nodes (start time, duration)
395
+
396
+ ### Planned
397
+
398
+ - [ ] Worker/queue tracking in events
399
+ - [ ] Monitoring APIs (workers, stats, orphan detection)
400
+ - [ ] UI reorganization (Dashboard, unified Executions, enhanced Registry)
401
+ - [ ] RabbitMQ transport
402
+ - [ ] OpenTelemetry export
403
+ - [ ] Webhook event export
404
+ - [ ] JSON export API
405
+
406
+ ## 🤝 Contributing
407
+
408
+ Contributions are welcome! Please read our [Contributing Guide](CONTRIBUTING.md) first.
409
+
410
+ ```bash
411
+ # Clone the repo
412
+ git clone https://github.com/iansokolskyi/stemtrace.git
413
+ cd stemtrace
414
+
415
+ # Install dependencies (requires uv)
416
+ uv sync --all-extras
417
+
418
+ # Run checks
419
+ make check
420
+ ```
421
+
422
+ ## 📄 License
423
+
424
+ MIT License — see [LICENSE](LICENSE) for details.
425
+
426
+ ---
427
+
428
+ **stemtrace** is not affiliated with the Celery project. Celery is a trademark of Ask Solem.
@@ -0,0 +1,72 @@
1
+ stemtrace/__init__.py,sha256=VCi7FsIzWLrjuc1U1Fck4lo9LHGzsoo8yNSvi4OzjAE,4981
2
+ stemtrace/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ stemtrace/core/__init__.py,sha256=0xTAr5JzuVnkrEL5kNMMEn6gco_ua7bqpks03eOlzrU,403
4
+ stemtrace/core/events.py,sha256=biwfWmKvUpuGIJxIsTiAfQG6XmCG9Q1CrgTDJbdtMzQ,2195
5
+ stemtrace/core/exceptions.py,sha256=NB5pixKgogcqtZAiwZSQNK5WtPkwiA-mjy2zFV49sHY,686
6
+ stemtrace/core/graph.py,sha256=UiNREghBjwahid65jr3rVIIiLPTmHeFI74qmpjYL0nA,14360
7
+ stemtrace/core/ports.py,sha256=eG3hBs0eeT54eASJwSQLUtfOlaJugw9Wft-mV7zqwzE,1256
8
+ stemtrace/library/__init__.py,sha256=ALeKSzpGbdXRHJmeCY5PmOW3yqr8KaJtZA0uY8Uaf58,46
9
+ stemtrace/library/bootsteps.py,sha256=kbbHWjgf-BNfi4_tuZ6DlkJyO6AhWwIvK3wE6PvGLh4,5951
10
+ stemtrace/library/config.py,sha256=Eg2r9k2IkPcbafYGz5ObQzx6v441bYRuIT9koUjGd20,1685
11
+ stemtrace/library/scrubbing.py,sha256=jasysLmHj3QrFyxLo5oCwcuEN0x-8_fffTM8HUnGVDU,5806
12
+ stemtrace/library/signals.py,sha256=N6nBwj9lFqXw1Wz05i3UOtaEHaO_MzvHUuc9-4v-p40,13259
13
+ stemtrace/library/transports/__init__.py,sha256=6T4g0PbwmPDPOfpqsyIFdCHlNmIMqHtLezS0Ui-5mBA,952
14
+ stemtrace/library/transports/memory.py,sha256=SgcmKQrhMKx-jy52CrRQokFlY2cby6krkWl5y8Fmtro,861
15
+ stemtrace/library/transports/redis.py,sha256=UN_-r42eBtnIvDq_fm7v2w3106UxZRcrtTuY-GRyxVQ,2823
16
+ stemtrace/server/__init__.py,sha256=LKUW0aSjqdmM1ClwCnsaSBS0PUO_YyHkxpHtSoI4TaA,587
17
+ stemtrace/server/__main__.py,sha256=wTEPquBo78VYXHMpFbRO5fyUGYQ97iwPsst_2ngp9yk,3581
18
+ stemtrace/server/consumer.py,sha256=vg3jyXaqtSRUb1Qg2juxwoWMBCZfsUxGnCkdG_Lfu8A,3994
19
+ stemtrace/server/store.py,sha256=uRwxW1WdyKGlFFv-YO2lw84m1rZdvuRol3005cXa20M,9162
20
+ stemtrace/server/websocket.py,sha256=pwFPsv8o9px432FpzJadAY_U1k4jYjL83dvFaKv-JKA,3520
21
+ stemtrace/server/api/__init__.py,sha256=tZBo4R6F59KC9eUYwJxTNm-4O4b4iywUWJZb1wau-E0,699
22
+ stemtrace/server/api/routes.py,sha256=vKhImnvzvoVxv-ZJlcsVWHyrp1Qv9VAH1VSlaNkOw8o,9358
23
+ stemtrace/server/api/schemas.py,sha256=lRKzQif67VFDJjHf1PLCf4OZPbqnnbbbYzYLc-O8HVA,3117
24
+ stemtrace/server/api/websocket.py,sha256=OpZBvCK7JY1yPqARDBakuyUqZ3rm-RuR1yYJHufye5o,857
25
+ stemtrace/server/fastapi/__init__.py,sha256=uK1rAAGvhTokZ05c3l3pEVLFJYzL0hPgDAxWG2pEEdU,372
26
+ stemtrace/server/fastapi/auth.py,sha256=TXOtDXRJuJfzSRJDab6rGef6ANP_pZbnWcg6J94WrYI,2303
27
+ stemtrace/server/fastapi/extension.py,sha256=vc8HosBCUhZHR-SqGYMHBRvn80OHoJpQ_yZIVAHBjYk,3835
28
+ stemtrace/server/fastapi/router.py,sha256=ttQ4pH6_cvHB9DD5d801oliciJNPT1bFQ3KPQKZTw60,1241
29
+ stemtrace/server/ui/__init__.py,sha256=5SJ0J1k0AcUQhDsvIRM4Fssh2U2gtlMOBFEqPB4SfqA,179
30
+ stemtrace/server/ui/static.py,sha256=FcYS-_FgW1uzASFrnRqpYguFUB5gl7iTBz28m9DnVw4,1835
31
+ stemtrace/server/ui/frontend/biome.json,sha256=kX0OM-agwyiGsjevcL09JfjzZAcSyCMAAqsVr4LegUA,1185
32
+ stemtrace/server/ui/frontend/index.html,sha256=yxl3UpLiqoKS1SQJ7v9uGGrvQyULWvG7RZDqaDuReiI,656
33
+ stemtrace/server/ui/frontend/package-lock.json,sha256=iXT5FT2_JrzP2ZdEuHDbbRKYn3F8CUkomwbSiUFl2IY,136799
34
+ stemtrace/server/ui/frontend/package.json,sha256=CkKoky9EIb_Bu9AZ-uTy-aGst6qH7eqxiP5fXfbMdN4,1281
35
+ stemtrace/server/ui/frontend/playwright.config.ts,sha256=amsln86idhc-UMPyeAjEVaTkAxL68fHG7UTkraAF7AQ,1032
36
+ stemtrace/server/ui/frontend/postcss.config.js,sha256=P8jRwTrZY7v32gTVkCTTjMKtFFY7Nq_XG8i0PHFI3SU,69
37
+ stemtrace/server/ui/frontend/tsconfig.json,sha256=V0r2aFumnBIEdaU3-RHKlvKZxATrn4mt-bnp9UuwWo8,713
38
+ stemtrace/server/ui/frontend/tsconfig.tsbuildinfo,sha256=IWAH8V54aeckBxPJdIJ3HyAW90vPSwKqz8DTUhQV7Ic,449
39
+ stemtrace/server/ui/frontend/vite.config.ts,sha256=HytXV_BlGUCgHnLKLYWxZueZEu0zJh-U2Dv3Fki3W3I,644
40
+ stemtrace/server/ui/frontend/dist/index.html,sha256=MoSLb1oQqZxPYUDUye-cspCt9lZ-2R0FO-KWgykio58,754
41
+ stemtrace/server/ui/frontend/dist/assets/index-CCs7iO1n.css,sha256=2-1pM0g4_5PBEDbyT6kcuovUwmA1KfeLLtzEx7-kcUg,55961
42
+ stemtrace/server/ui/frontend/dist/assets/index-Dao0_Q6x.js,sha256=HNXt8CWq6SaKYhTd3aukmWDOC93W8wi_abm1l1TKzsc,545168
43
+ stemtrace/server/ui/frontend/src/index.css,sha256=X_-gO_nIhdb8kYS4DXlGvi9GJV5RbHTsxrZmjafdZgA,2231
44
+ stemtrace/server/ui/frontend/src/main.tsx,sha256=A9JRlExwral6oVS2hI6k84OcU6QugDtN3Te86kdj7QY,1048
45
+ stemtrace/server/ui/frontend/src/api/client.ts,sha256=k_BS8dUPdij3w30kaMI7XpSElMNVVvMo4UYcoHiuaI8,4687
46
+ stemtrace/server/ui/frontend/src/api/queries.ts,sha256=dm1_-wBPm4Z0WCvZQOYxJcRvZYCPAJ-dXBxSfANrDDU,4307
47
+ stemtrace/server/ui/frontend/src/components/DateRangePicker.tsx,sha256=-CA6A0lDpPYVAwBedd-NL6NjmneuD7b2SchXOYUzg5I,6831
48
+ stemtrace/server/ui/frontend/src/components/Filters.tsx,sha256=s9qbzHL70gS-3WTTOx7lONcaQE-K2CzKIzHGRBOM1QU,3591
49
+ stemtrace/server/ui/frontend/src/components/TaskGraph.tsx,sha256=Cfr52R2lyYhkRQ2-dUEmpnfPwrnOYWd7Cci3gL394vU,15510
50
+ stemtrace/server/ui/frontend/src/components/TaskList.tsx,sha256=kiLHn8o2KjqzqO95W8OnPY5SWLUq_r_AzGUG5N4rP5c,5151
51
+ stemtrace/server/ui/frontend/src/components/TaskStateBadge.tsx,sha256=Ur-f1yNlFRpr-iH3pr4ZgUluxS7ut4eME_ho6BAp-As,704
52
+ stemtrace/server/ui/frontend/src/components/TaskTimeline.tsx,sha256=SL2cdG24UoerbTGautFBLkltxDPfifz2Xy6Guqi1VY0,4581
53
+ stemtrace/server/ui/frontend/src/components/TimelineBar.tsx,sha256=ezT3z3ZjoA_c3fYcxe6MAHaRWZThegHVleISBYpGOuI,7158
54
+ stemtrace/server/ui/frontend/src/components/Tooltip.tsx,sha256=daoBzyjYc_V6dfLvN-iUS8BAFJzEQpx6D4kwwYpDjJk,1789
55
+ stemtrace/server/ui/frontend/src/hooks/WebSocketContext.tsx,sha256=9HZyORmTTjMt77-FrPV1_E8rCgrW8E9KDad7joKQLMk,4066
56
+ stemtrace/server/ui/frontend/src/hooks/useInfiniteScroll.ts,sha256=Fi0Lz7n2c4pP9dg-6XvNanhTypd3d9YqqLMHnJjqaL8,1246
57
+ stemtrace/server/ui/frontend/src/routes/__root.tsx,sha256=f96fRT7Ab0AJ8PRvMJjl57yr8klpFhz4C8mkvF-uBdY,3751
58
+ stemtrace/server/ui/frontend/src/routes/graph.$rootId.tsx,sha256=hYDb9FOaIn14VZUq_sSixOzSD5JYO9ZPYnrnBbMnAAg,1532
59
+ stemtrace/server/ui/frontend/src/routes/graphs.tsx,sha256=SWOMIkT3Bxk-3ZM9QYmp4ioDe2ABM5aj0nHespMzPEY,6016
60
+ stemtrace/server/ui/frontend/src/routes/index.tsx,sha256=nQ_vRZZHU3pc5wWgUFbS2AdRQsrBNW10W_Ml5mNNrLQ,3398
61
+ stemtrace/server/ui/frontend/src/routes/registry.tsx,sha256=r4vcnSgvogXwjVXlo9sTjVk5QnGF2vlDJOvr3uV6Y1I,6881
62
+ stemtrace/server/ui/frontend/src/routes/tasks.$taskId.tsx,sha256=-zo6Bd_7405wIi5EZ-sn7Yb5sJFw0mXlDuYfUYuHfWI,11400
63
+ stemtrace/server/ui/frontend/src/utils/format.ts,sha256=_8WyC7qebk1QkZS8EOaWy5ZO5-NaSrqeD_WbL6C3DoM,1146
64
+ stemtrace/server/ui/frontend/tests/graphs.spec.ts,sha256=MEhcH8-5pxdIeuRCmMMDs1oKMrlcCCaNApjW-O74LIM,15382
65
+ stemtrace/server/ui/frontend/tests/registry.spec.ts,sha256=SuxsUSq-JzLyJ0IONESlvUbdYUH78IeS6iU_Nro0IgI,3626
66
+ stemtrace/server/ui/frontend/tests/task-detail.spec.ts,sha256=NbjSG6ilmIDU2VpptNI7o2r_UICmDrcY8lV0vJS3gZ8,4540
67
+ stemtrace/server/ui/frontend/tests/tasks.spec.ts,sha256=w9juNZ6hQZZSmlMAx4HbtW7yKa5yQtkB4GZln1c39o4,2823
68
+ stemtrace-0.1.0.dist-info/METADATA,sha256=00Knm6jKBq_kIDA1PbTqxu-Wm8vIljiVwA1nNfTmFnw,15838
69
+ stemtrace-0.1.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
70
+ stemtrace-0.1.0.dist-info/entry_points.txt,sha256=eXdGn8NKvgXel-4_nCMG_E6vCp2Ri6SGlgQPbvJ5MXQ,61
71
+ stemtrace-0.1.0.dist-info/licenses/LICENSE,sha256=JcXwyyW0EPCs0zFfx5gI2bpaJ6WX9Wz74tAwEOOLNN0,1070
72
+ stemtrace-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.28.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ stemtrace = stemtrace.server.__main__:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Ian Sokolskyi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.