dooers-workers 0.2.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.
@@ -0,0 +1,228 @@
1
+ Metadata-Version: 2.4
2
+ Name: dooers-workers
3
+ Version: 0.2.0
4
+ Summary: Python SDK for dooers.ai chat protocol
5
+ Requires-Python: >=3.11
6
+ Requires-Dist: aiosqlite>=0.22.1
7
+ Requires-Dist: asyncpg>=0.31.0
8
+ Requires-Dist: httpx>=0.28.1
9
+ Requires-Dist: pydantic>=2.12.5
10
+ Requires-Dist: sqlalchemy>=2.0.46
11
+ Provides-Extra: dev
12
+ Requires-Dist: pytest-asyncio>=1.3.0; extra == 'dev'
13
+ Requires-Dist: pytest>=9.0.2; extra == 'dev'
14
+ Requires-Dist: ruff>=0.15.0; extra == 'dev'
15
+ Description-Content-Type: text/markdown
16
+
17
+ # dooers-workers
18
+
19
+ Python SDK for dooers.ai chat protocol.
20
+
21
+ ## Install
22
+
23
+ ```bash
24
+ pip install dooers-workers
25
+ ```
26
+
27
+ Or from source:
28
+
29
+ ```bash
30
+ pip install git+https://github.com/dooers/dooers-workers.git
31
+ ```
32
+
33
+ ## Usage
34
+
35
+ ```python
36
+ from fastapi import FastAPI, WebSocket
37
+ from openai import AsyncOpenAI
38
+ from dooers import WorkerServer, WorkerConfig
39
+
40
+ app = FastAPI()
41
+ openai = AsyncOpenAI()
42
+
43
+ worker_server = WorkerServer(WorkerConfig(
44
+ database_url="sqlite:///worker.db",
45
+ database_type="sqlite",
46
+ ))
47
+
48
+
49
+ async def agent_handler(request, response, memory, analytics, settings):
50
+ yield response.run_start()
51
+
52
+ # Track custom event
53
+ await analytics.track("llm.called", data={"model": "gpt-4o-mini"})
54
+
55
+ completion = await openai.chat.completions.create(
56
+ model="gpt-4o-mini",
57
+ messages=[{"role": "user", "content": request.message}],
58
+ )
59
+
60
+ yield response.text(completion.choices[0].message.content)
61
+ yield response.run_end()
62
+
63
+
64
+ @app.websocket("/ws")
65
+ async def ws(websocket: WebSocket):
66
+ await websocket.accept()
67
+ await worker_server.handle(websocket, agent_handler)
68
+ ```
69
+
70
+ ## agent_handler
71
+
72
+ ```python
73
+ async def agent_handler(request, response, memory, analytics, settings):
74
+ ...
75
+ ```
76
+
77
+ ### Request
78
+
79
+ ```python
80
+ request.message # str
81
+ request.content # list[ContentPart]
82
+ request.thread_id # str
83
+ request.event_id # str
84
+ request.user_id # str | None
85
+ ```
86
+
87
+ ### Memory
88
+
89
+ ```python
90
+ # Get formatted history (defaults to OpenAI format)
91
+ messages = await memory.get_history(limit=50)
92
+
93
+ # Specify format for different providers
94
+ messages = await memory.get_history(format="openai")
95
+ messages = await memory.get_history(format="anthropic")
96
+ messages = await memory.get_history(format="google")
97
+ messages = await memory.get_history(format="cohere")
98
+ messages = await memory.get_history(format="voyage")
99
+
100
+ # Get raw ThreadEvent objects
101
+ events = await memory.get_history_raw(limit=50)
102
+ ```
103
+
104
+ ### Response
105
+
106
+ ```python
107
+ yield response.text("Hello, I'm your assistant.")
108
+ yield response.image(url, mime_type?, alt?)
109
+ yield response.document(url, filename, mime_type)
110
+ yield response.tool_call(name, args)
111
+ yield response.tool_result(name, result)
112
+ yield response.run_start(agent_id?)
113
+ yield response.run_end(status?, error?)
114
+ ```
115
+
116
+ ### Analytics
117
+
118
+ ```python
119
+ await analytics.track("event.name", data={"key": "value"})
120
+ await analytics.like("event", target_id, reason?)
121
+ await analytics.dislike("event", target_id, reason?)
122
+ ```
123
+
124
+ ### Settings
125
+
126
+ ```python
127
+ value = await settings.get("field_id")
128
+ all_values = await settings.get_all()
129
+ await settings.set("field_id", new_value)
130
+ ```
131
+
132
+ ## worker_server
133
+
134
+ ### Persistence
135
+
136
+ Direct database access for threads, events, and settings.
137
+
138
+ ```python
139
+
140
+ persistence = worker_server.persistence
141
+
142
+ thread = await persistence.get_thread(thread_id)
143
+ await persistence.create_thread(thread)
144
+ await persistence.update_thread(thread)
145
+ threads = await persistence.list_threads(worker_id, user_id, cursor, limit)
146
+
147
+ await persistence.create_event(event)
148
+ events = await persistence.get_events(thread_id, after_event_id, limit)
149
+
150
+ settings = await persistence.get_settings(worker_id)
151
+ await persistence.update_setting(worker_id, field_id, value)
152
+ ```
153
+
154
+ ### Broadcast
155
+
156
+ Pushes events to WebSocket subscribers. `send_event` also persists the event and updates the thread timestamp.
157
+
158
+ ```python
159
+
160
+ broadcast = worker_server.broadcast
161
+
162
+ # Persist + broadcast a message (returns event, connections notified)
163
+ event, count = await broadcast.send_event(worker_id, thread_id, content, actor)
164
+
165
+ # Broadcast a thread change (no persistence, notification only)
166
+ count = await broadcast.send_thread_update(worker_id, thread)
167
+
168
+ # Create thread + broadcast (convenience)
169
+ thread, count = await broadcast.create_thread_and_broadcast(worker_id, user_id, title)
170
+ ```
171
+
172
+ ## Settings Schema
173
+
174
+ Define configurable settings for your worker:
175
+
176
+ ```python
177
+ from dooers import (
178
+ WorkerConfig,
179
+ WorkerServer,
180
+ SettingsSchema,
181
+ SettingsField,
182
+ SettingsFieldType,
183
+ SettingsSelectOption,
184
+ )
185
+
186
+ schema = SettingsSchema(
187
+ fields=[
188
+ SettingsField(
189
+ id="model",
190
+ type=SettingsFieldType.SELECT,
191
+ label="Model",
192
+ value="gpt-4o-mini",
193
+ options=[
194
+ SettingsSelectOption(value="gpt-4o-mini", label="GPT-4o Mini"),
195
+ SettingsSelectOption(value="gpt-4o", label="GPT-4o"),
196
+ ],
197
+ ),
198
+ SettingsField(
199
+ id="temperature",
200
+ type=SettingsFieldType.NUMBER,
201
+ label="Temperature",
202
+ value=0.7,
203
+ min=0,
204
+ max=2,
205
+ ),
206
+ ]
207
+ )
208
+
209
+ worker_server = WorkerServer(WorkerConfig(
210
+ database_url="sqlite:///worker.db",
211
+ database_type="sqlite",
212
+ settings_schema=schema,
213
+ ))
214
+ ```
215
+
216
+ ### Field Types
217
+
218
+ - `TEXT` - Single-line text input
219
+ - `NUMBER` - Numeric input with optional min/max
220
+ - `SELECT` - Dropdown selection
221
+ - `CHECKBOX` - Boolean toggle
222
+ - `TEXTAREA` - Multi-line text input
223
+ - `PASSWORD` - Password input (hidden)
224
+ - `EMAIL` - Email input
225
+ - `DATE` - Date picker
226
+ - `IMAGE` - Display-only image (e.g., QR codes)
227
+
228
+
@@ -0,0 +1,33 @@
1
+ dooers/__init__.py,sha256=n6Mrt6VtDrXc93vd0IdiFjZCytcIpja9MrRUuTm2Gpo,1671
2
+ dooers/broadcast.py,sha256=Lt7nJk6_0TLCoLDDLZPrRjNTkIfAkjofyuJyhG6r8xU,5407
3
+ dooers/config.py,sha256=Fzhim7QwYBX-FItNOBKBi0qlU7OJrqPSvX9KxVzW_SA,717
4
+ dooers/registry.py,sha256=5vmq8kNjqyUun0KipuWHONqOhxqNY391jvbJZl3UP8w,3346
5
+ dooers/server.py,sha256=-ct81WZ97KbuDzTGlKFXa2OE4B36SaNGkTpx46nw_EA,6499
6
+ dooers/settings.py,sha256=EAv6ZEBiw0anPfjtmwm73RmkBtWSAwjYSeE7CT6VbAk,142
7
+ dooers/features/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ dooers/features/analytics/__init__.py,sha256=Yj5F3o1NtjI2j80P1JfD9LbkiYmmXAOHA0T000ioDqQ,345
9
+ dooers/features/analytics/collector.py,sha256=1AUaoZJ70BE0DCmWCtodP15zwUGbfRQVOPabqEg91UE,7682
10
+ dooers/features/analytics/models.py,sha256=lroX6Nv2RPIu63RJ6TlFgyaYSq5_l5aM-qCUOgkqg4I,1259
11
+ dooers/features/analytics/worker_analytics.py,sha256=0Sdh5DyJ98reqMw-ekYRTro-C_nsVTaDGXHKeU8EjSA,2921
12
+ dooers/features/settings/__init__.py,sha256=0_SL46Qmvgr8hcQp5_hZb06DyTQuAx96fD5qNI8LYcA,352
13
+ dooers/features/settings/broadcaster.py,sha256=eg0jgfdU4FpvJjrt_E42Ap4mG9OXGtXRV7u6OlStdFM,3214
14
+ dooers/features/settings/models.py,sha256=Ib8mOUsAKMZfGYWzhxHnG_k8tWEJPGpiAZgeb9A4Kc4,2050
15
+ dooers/features/settings/worker_settings.py,sha256=pDGHzY_AteXm4_3EZOB8wggTzazEqqCP7HN5-M9FPls,2746
16
+ dooers/handlers/__init__.py,sha256=7pjVKZVpApq961dGJaomD8mi-JctHnbvA3u784VbHz0,516
17
+ dooers/handlers/memory.py,sha256=FHjB25cvaFfbolXsCVfFNxPK0llqucsfFu-BBQo4OrA,3491
18
+ dooers/handlers/request.py,sha256=Awyk0K67m-sFoUxqQUY1zWTeo9heZvj0ivII0f_qH9M,237
19
+ dooers/handlers/response.py,sha256=-fZLX8dZjmLMon4Z2ZCxi3xr_pXKxbFJU_mkuPUgG1E,1777
20
+ dooers/handlers/router.py,sha256=aAKPnu5e-DKtEMZ70EJxvEKmJO8YJQS_bStl1xb75Mo,35503
21
+ dooers/migrations/__init__.py,sha256=gynmHSVs_CQCuKGG0Rw4E6Eh_LCXUsZH-Zpc8tScJfM,92
22
+ dooers/migrations/schemas.py,sha256=9W37t_armHdjjzHQTnQx3OyZ0f012sQ7vAmACBHkuQk,4778
23
+ dooers/persistence/__init__.py,sha256=GnEeNPeS7ZYiEStaFDbqg9cThC5UOJZ7Wpm1aZafgxM,259
24
+ dooers/persistence/base.py,sha256=lR6yLrsuG7UPPRpr0PxuA-pbc9IsPH0-NQambQPIUFk,1545
25
+ dooers/persistence/postgres.py,sha256=GTwJzDkHiOM9OzDto418qoK-DxXZd2kpjTGNncheaFk,15806
26
+ dooers/persistence/sqlite.py,sha256=VJIKMM4cMANLke8ToZEOHPmHtCVkx8UoxZGrhYXmB78,14891
27
+ dooers/protocol/__init__.py,sha256=I9wXiA3XdqY5056vrj-RutFd6Nl3-dvBKKuWYBXDrQI,2573
28
+ dooers/protocol/frames.py,sha256=xyySImv8QZlLba_sqQ3rWEIGQPgMFZh79hAHKaJE7H0,6273
29
+ dooers/protocol/models.py,sha256=_t4zRICS8jtNxu6GLzrfbBkx8dfAn0zbsmEVEV7MvLM,1722
30
+ dooers/protocol/parser.py,sha256=t4umb5stgJt5mB7uncOGWpPzeqe4V9To2z2aDj-sQvk,452
31
+ dooers_workers-0.2.0.dist-info/METADATA,sha256=k_cw9o9zXz81Mt016EqYfGQngbZkAf1JDSwQ1MiPqKo,5539
32
+ dooers_workers-0.2.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
33
+ dooers_workers-0.2.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