dooers-workers 0.2.0__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.
- dooers_workers-0.2.0/.github/workflows/publish.yml +49 -0
- dooers_workers-0.2.0/.gitignore +5 -0
- dooers_workers-0.2.0/PKG-INFO +228 -0
- dooers_workers-0.2.0/README.md +212 -0
- dooers_workers-0.2.0/docs/plans/2026-02-05-analytics-settings-design.md +645 -0
- dooers_workers-0.2.0/examples/fastapi_anthropic.py +105 -0
- dooers_workers-0.2.0/examples/fastapi_basic.py +28 -0
- dooers_workers-0.2.0/examples/fastapi_langchain.py +53 -0
- dooers_workers-0.2.0/examples/fastapi_langgraph.py +79 -0
- dooers_workers-0.2.0/examples/fastapi_openai.py +104 -0
- dooers_workers-0.2.0/examples/fastapi_openai_agents.py +68 -0
- dooers_workers-0.2.0/examples/fastapi_tools.py +51 -0
- dooers_workers-0.2.0/examples/fastapi_vertex.py +58 -0
- dooers_workers-0.2.0/examples/fastapi_whatsapp_webhook.py +78 -0
- dooers_workers-0.2.0/pyproject.toml +52 -0
- dooers_workers-0.2.0/requirements.txt +5 -0
- dooers_workers-0.2.0/scripts/pcu.py +377 -0
- dooers_workers-0.2.0/src/dooers/__init__.py +73 -0
- dooers_workers-0.2.0/src/dooers/broadcast.py +180 -0
- dooers_workers-0.2.0/src/dooers/config.py +22 -0
- dooers_workers-0.2.0/src/dooers/features/__init__.py +0 -0
- dooers_workers-0.2.0/src/dooers/features/analytics/__init__.py +12 -0
- dooers_workers-0.2.0/src/dooers/features/analytics/collector.py +219 -0
- dooers_workers-0.2.0/src/dooers/features/analytics/models.py +50 -0
- dooers_workers-0.2.0/src/dooers/features/analytics/worker_analytics.py +100 -0
- dooers_workers-0.2.0/src/dooers/features/settings/__init__.py +12 -0
- dooers_workers-0.2.0/src/dooers/features/settings/broadcaster.py +97 -0
- dooers_workers-0.2.0/src/dooers/features/settings/models.py +72 -0
- dooers_workers-0.2.0/src/dooers/features/settings/worker_settings.py +85 -0
- dooers_workers-0.2.0/src/dooers/handlers/__init__.py +16 -0
- dooers_workers-0.2.0/src/dooers/handlers/memory.py +105 -0
- dooers_workers-0.2.0/src/dooers/handlers/request.py +12 -0
- dooers_workers-0.2.0/src/dooers/handlers/response.py +66 -0
- dooers_workers-0.2.0/src/dooers/handlers/router.py +957 -0
- dooers_workers-0.2.0/src/dooers/migrations/__init__.py +3 -0
- dooers_workers-0.2.0/src/dooers/migrations/schemas.py +126 -0
- dooers_workers-0.2.0/src/dooers/persistence/__init__.py +9 -0
- dooers_workers-0.2.0/src/dooers/persistence/base.py +42 -0
- dooers_workers-0.2.0/src/dooers/persistence/postgres.py +459 -0
- dooers_workers-0.2.0/src/dooers/persistence/sqlite.py +433 -0
- dooers_workers-0.2.0/src/dooers/protocol/__init__.py +108 -0
- dooers_workers-0.2.0/src/dooers/protocol/frames.py +298 -0
- dooers_workers-0.2.0/src/dooers/protocol/models.py +72 -0
- dooers_workers-0.2.0/src/dooers/protocol/parser.py +19 -0
- dooers_workers-0.2.0/src/dooers/registry.py +101 -0
- dooers_workers-0.2.0/src/dooers/server.py +162 -0
- dooers_workers-0.2.0/src/dooers/settings.py +3 -0
- dooers_workers-0.2.0/uv.lock +587 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
build:
|
|
9
|
+
name: Build distribution
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
steps:
|
|
12
|
+
- uses: actions/checkout@v4
|
|
13
|
+
|
|
14
|
+
- name: Set up Python
|
|
15
|
+
uses: actions/setup-python@v5
|
|
16
|
+
with:
|
|
17
|
+
python-version: "3.11"
|
|
18
|
+
|
|
19
|
+
- name: Install build dependencies
|
|
20
|
+
run: pip install build
|
|
21
|
+
|
|
22
|
+
- name: Build package
|
|
23
|
+
run: python -m build
|
|
24
|
+
|
|
25
|
+
- name: Upload distribution artifacts
|
|
26
|
+
uses: actions/upload-artifact@v4
|
|
27
|
+
with:
|
|
28
|
+
name: python-package-distributions
|
|
29
|
+
path: dist/
|
|
30
|
+
|
|
31
|
+
publish:
|
|
32
|
+
name: Publish to PyPI
|
|
33
|
+
needs: build
|
|
34
|
+
runs-on: ubuntu-latest
|
|
35
|
+
environment:
|
|
36
|
+
name: pypi
|
|
37
|
+
url: https://pypi.org/p/dooers-workers
|
|
38
|
+
permissions:
|
|
39
|
+
id-token: write
|
|
40
|
+
|
|
41
|
+
steps:
|
|
42
|
+
- name: Download distribution artifacts
|
|
43
|
+
uses: actions/download-artifact@v4
|
|
44
|
+
with:
|
|
45
|
+
name: python-package-distributions
|
|
46
|
+
path: dist/
|
|
47
|
+
|
|
48
|
+
- name: Publish to PyPI
|
|
49
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -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,212 @@
|
|
|
1
|
+
# dooers-workers
|
|
2
|
+
|
|
3
|
+
Python SDK for dooers.ai chat protocol.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install dooers-workers
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Or from source:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pip install git+https://github.com/dooers/dooers-workers.git
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
```python
|
|
20
|
+
from fastapi import FastAPI, WebSocket
|
|
21
|
+
from openai import AsyncOpenAI
|
|
22
|
+
from dooers import WorkerServer, WorkerConfig
|
|
23
|
+
|
|
24
|
+
app = FastAPI()
|
|
25
|
+
openai = AsyncOpenAI()
|
|
26
|
+
|
|
27
|
+
worker_server = WorkerServer(WorkerConfig(
|
|
28
|
+
database_url="sqlite:///worker.db",
|
|
29
|
+
database_type="sqlite",
|
|
30
|
+
))
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
async def agent_handler(request, response, memory, analytics, settings):
|
|
34
|
+
yield response.run_start()
|
|
35
|
+
|
|
36
|
+
# Track custom event
|
|
37
|
+
await analytics.track("llm.called", data={"model": "gpt-4o-mini"})
|
|
38
|
+
|
|
39
|
+
completion = await openai.chat.completions.create(
|
|
40
|
+
model="gpt-4o-mini",
|
|
41
|
+
messages=[{"role": "user", "content": request.message}],
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
yield response.text(completion.choices[0].message.content)
|
|
45
|
+
yield response.run_end()
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@app.websocket("/ws")
|
|
49
|
+
async def ws(websocket: WebSocket):
|
|
50
|
+
await websocket.accept()
|
|
51
|
+
await worker_server.handle(websocket, agent_handler)
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## agent_handler
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
async def agent_handler(request, response, memory, analytics, settings):
|
|
58
|
+
...
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Request
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
request.message # str
|
|
65
|
+
request.content # list[ContentPart]
|
|
66
|
+
request.thread_id # str
|
|
67
|
+
request.event_id # str
|
|
68
|
+
request.user_id # str | None
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Memory
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
# Get formatted history (defaults to OpenAI format)
|
|
75
|
+
messages = await memory.get_history(limit=50)
|
|
76
|
+
|
|
77
|
+
# Specify format for different providers
|
|
78
|
+
messages = await memory.get_history(format="openai")
|
|
79
|
+
messages = await memory.get_history(format="anthropic")
|
|
80
|
+
messages = await memory.get_history(format="google")
|
|
81
|
+
messages = await memory.get_history(format="cohere")
|
|
82
|
+
messages = await memory.get_history(format="voyage")
|
|
83
|
+
|
|
84
|
+
# Get raw ThreadEvent objects
|
|
85
|
+
events = await memory.get_history_raw(limit=50)
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Response
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
yield response.text("Hello, I'm your assistant.")
|
|
92
|
+
yield response.image(url, mime_type?, alt?)
|
|
93
|
+
yield response.document(url, filename, mime_type)
|
|
94
|
+
yield response.tool_call(name, args)
|
|
95
|
+
yield response.tool_result(name, result)
|
|
96
|
+
yield response.run_start(agent_id?)
|
|
97
|
+
yield response.run_end(status?, error?)
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Analytics
|
|
101
|
+
|
|
102
|
+
```python
|
|
103
|
+
await analytics.track("event.name", data={"key": "value"})
|
|
104
|
+
await analytics.like("event", target_id, reason?)
|
|
105
|
+
await analytics.dislike("event", target_id, reason?)
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Settings
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
value = await settings.get("field_id")
|
|
112
|
+
all_values = await settings.get_all()
|
|
113
|
+
await settings.set("field_id", new_value)
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## worker_server
|
|
117
|
+
|
|
118
|
+
### Persistence
|
|
119
|
+
|
|
120
|
+
Direct database access for threads, events, and settings.
|
|
121
|
+
|
|
122
|
+
```python
|
|
123
|
+
|
|
124
|
+
persistence = worker_server.persistence
|
|
125
|
+
|
|
126
|
+
thread = await persistence.get_thread(thread_id)
|
|
127
|
+
await persistence.create_thread(thread)
|
|
128
|
+
await persistence.update_thread(thread)
|
|
129
|
+
threads = await persistence.list_threads(worker_id, user_id, cursor, limit)
|
|
130
|
+
|
|
131
|
+
await persistence.create_event(event)
|
|
132
|
+
events = await persistence.get_events(thread_id, after_event_id, limit)
|
|
133
|
+
|
|
134
|
+
settings = await persistence.get_settings(worker_id)
|
|
135
|
+
await persistence.update_setting(worker_id, field_id, value)
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Broadcast
|
|
139
|
+
|
|
140
|
+
Pushes events to WebSocket subscribers. `send_event` also persists the event and updates the thread timestamp.
|
|
141
|
+
|
|
142
|
+
```python
|
|
143
|
+
|
|
144
|
+
broadcast = worker_server.broadcast
|
|
145
|
+
|
|
146
|
+
# Persist + broadcast a message (returns event, connections notified)
|
|
147
|
+
event, count = await broadcast.send_event(worker_id, thread_id, content, actor)
|
|
148
|
+
|
|
149
|
+
# Broadcast a thread change (no persistence, notification only)
|
|
150
|
+
count = await broadcast.send_thread_update(worker_id, thread)
|
|
151
|
+
|
|
152
|
+
# Create thread + broadcast (convenience)
|
|
153
|
+
thread, count = await broadcast.create_thread_and_broadcast(worker_id, user_id, title)
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Settings Schema
|
|
157
|
+
|
|
158
|
+
Define configurable settings for your worker:
|
|
159
|
+
|
|
160
|
+
```python
|
|
161
|
+
from dooers import (
|
|
162
|
+
WorkerConfig,
|
|
163
|
+
WorkerServer,
|
|
164
|
+
SettingsSchema,
|
|
165
|
+
SettingsField,
|
|
166
|
+
SettingsFieldType,
|
|
167
|
+
SettingsSelectOption,
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
schema = SettingsSchema(
|
|
171
|
+
fields=[
|
|
172
|
+
SettingsField(
|
|
173
|
+
id="model",
|
|
174
|
+
type=SettingsFieldType.SELECT,
|
|
175
|
+
label="Model",
|
|
176
|
+
value="gpt-4o-mini",
|
|
177
|
+
options=[
|
|
178
|
+
SettingsSelectOption(value="gpt-4o-mini", label="GPT-4o Mini"),
|
|
179
|
+
SettingsSelectOption(value="gpt-4o", label="GPT-4o"),
|
|
180
|
+
],
|
|
181
|
+
),
|
|
182
|
+
SettingsField(
|
|
183
|
+
id="temperature",
|
|
184
|
+
type=SettingsFieldType.NUMBER,
|
|
185
|
+
label="Temperature",
|
|
186
|
+
value=0.7,
|
|
187
|
+
min=0,
|
|
188
|
+
max=2,
|
|
189
|
+
),
|
|
190
|
+
]
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
worker_server = WorkerServer(WorkerConfig(
|
|
194
|
+
database_url="sqlite:///worker.db",
|
|
195
|
+
database_type="sqlite",
|
|
196
|
+
settings_schema=schema,
|
|
197
|
+
))
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Field Types
|
|
201
|
+
|
|
202
|
+
- `TEXT` - Single-line text input
|
|
203
|
+
- `NUMBER` - Numeric input with optional min/max
|
|
204
|
+
- `SELECT` - Dropdown selection
|
|
205
|
+
- `CHECKBOX` - Boolean toggle
|
|
206
|
+
- `TEXTAREA` - Multi-line text input
|
|
207
|
+
- `PASSWORD` - Password input (hidden)
|
|
208
|
+
- `EMAIL` - Email input
|
|
209
|
+
- `DATE` - Date picker
|
|
210
|
+
- `IMAGE` - Display-only image (e.g., QR codes)
|
|
211
|
+
|
|
212
|
+
|