teardrop-cli 0.2.0__tar.gz → 0.3.2__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.
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/PKG-INFO +47 -8
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/README.md +45 -6
- teardrop_cli-0.3.2/docs/cli-json-schema.md +130 -0
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/docs/cli-reference.md +80 -5
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/pyproject.toml +2 -2
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/src/teardrop_cli/_templates.py +1 -3
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/src/teardrop_cli/cli.py +2 -0
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/src/teardrop_cli/commands/agent_tools.py +1 -1
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/src/teardrop_cli/commands/auth.py +27 -18
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/src/teardrop_cli/commands/balance.py +2 -3
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/src/teardrop_cli/commands/chat.py +2 -4
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/src/teardrop_cli/commands/config_cmd.py +1 -3
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/src/teardrop_cli/commands/earnings.py +4 -8
- teardrop_cli-0.3.2/src/teardrop_cli/commands/event_triggers.py +457 -0
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/src/teardrop_cli/commands/llm_config.py +7 -13
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/src/teardrop_cli/commands/marketplace.py +8 -13
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/src/teardrop_cli/commands/quickstart.py +137 -29
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/src/teardrop_cli/commands/run.py +11 -9
- teardrop_cli-0.3.2/src/teardrop_cli/commands/schedules.py +386 -0
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/src/teardrop_cli/commands/tools.py +87 -49
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/src/teardrop_cli/config.py +3 -9
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/src/teardrop_cli/formatting.py +6 -3
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/src/teardrop_cli/pricing.py +2 -4
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/tests/conftest.py +111 -3
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/tests/e2e/conftest.py +1 -4
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/tests/e2e/test_auth_e2e.py +2 -8
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/tests/e2e/test_marketplace_e2e.py +3 -9
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/tests/e2e/test_signup_e2e.py +4 -11
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/tests/e2e/test_siwe_login_e2e.py +3 -9
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/tests/smoke/conftest.py +1 -0
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/tests/test_auth.py +25 -7
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/tests/test_billing.py +2 -7
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/tests/test_chat.py +6 -13
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/tests/test_credential_priority.py +10 -8
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/tests/test_earnings.py +2 -6
- teardrop_cli-0.3.2/tests/test_event_triggers.py +240 -0
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/tests/test_init_and_byok.py +31 -23
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/tests/test_llm_config.py +3 -9
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/tests/test_marketplace.py +15 -45
- teardrop_cli-0.3.2/tests/test_quickstart.py +291 -0
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/tests/test_run.py +18 -11
- teardrop_cli-0.3.2/tests/test_schedules.py +217 -0
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/tests/test_signup.py +5 -15
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/tests/test_token_expiry_fallback.py +48 -14
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/tests/test_tools.py +134 -20
- teardrop_cli-0.2.0/docs/cli-json-schema.md +0 -27
- teardrop_cli-0.2.0/src/teardrop_cli/__init__.py +0 -1
- teardrop_cli-0.2.0/tests/test_quickstart.py +0 -224
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/.github/workflows/publish.yml +0 -0
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/.github/workflows/test.yml +0 -0
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/.gitignore +0 -0
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/.vscode/settings.json +0 -0
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/LICENSE +0 -0
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/src/teardrop_cli/_fixtures.py +0 -0
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/src/teardrop_cli/_lazy.py +0 -0
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/src/teardrop_cli/commands/__init__.py +0 -0
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/src/teardrop_cli/commands/mcp.py +0 -0
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/src/teardrop_cli/commands/models.py +0 -0
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/src/teardrop_cli/commands/usage.py +0 -0
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/tests/e2e/README.md +0 -0
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/tests/e2e/__init__.py +0 -0
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/tests/e2e/test_billing_e2e.py +0 -0
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/tests/e2e/test_run_e2e.py +0 -0
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/tests/smoke/__init__.py +0 -0
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/tests/smoke/test_config_persistence.py +0 -0
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/tests/smoke/test_keyring_integration.py +0 -0
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/tests/smoke/test_perf_lazygroup.py +0 -0
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/tests/smoke/test_siwe_signing.py +0 -0
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/tests/test_config_cmd.py +0 -0
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/tests/test_mcp.py +0 -0
- {teardrop_cli-0.2.0 → teardrop_cli-0.3.2}/tests/test_models.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: teardrop-cli
|
|
3
|
-
Version: 0.2
|
|
3
|
+
Version: 0.3.2
|
|
4
4
|
Summary: Command-line interface for the Teardrop AI agent platform
|
|
5
5
|
Project-URL: Homepage, https://github.com/teardrop-ai/teardrop-cli
|
|
6
6
|
Project-URL: Repository, https://github.com/teardrop-ai/teardrop-cli
|
|
@@ -45,7 +45,7 @@ Requires-Dist: httpx>=0.27
|
|
|
45
45
|
Requires-Dist: keyring>=25.0
|
|
46
46
|
Requires-Dist: platformdirs>=4.0
|
|
47
47
|
Requires-Dist: rich>=13.0
|
|
48
|
-
Requires-Dist: teardrop-sdk>=0.
|
|
48
|
+
Requires-Dist: teardrop-sdk>=0.3.0
|
|
49
49
|
Requires-Dist: tomli-w>=1.0
|
|
50
50
|
Requires-Dist: typer>=0.12
|
|
51
51
|
Provides-Extra: dev
|
|
@@ -86,21 +86,27 @@ Requires Python ≥ 3.11.
|
|
|
86
86
|
|
|
87
87
|
## 60-Second Quickstart
|
|
88
88
|
|
|
89
|
-
The wizard walks you through sign-in, BYOK LLM setup, and your first agent run or scaffolded tool:
|
|
89
|
+
The wizard walks you through sign-in, optional BYOK LLM setup, and your first agent run or scaffolded tool:
|
|
90
90
|
|
|
91
91
|
```bash
|
|
92
92
|
teardrop quickstart
|
|
93
93
|
```
|
|
94
94
|
|
|
95
|
+
Quickstart keeps local tool scaffolding and public marketplace browsing available
|
|
96
|
+
without sign-in. A saved session is verified when you choose an agent run; if it
|
|
97
|
+
is stale, the wizard offers sign-in again before asking for a prompt or payment
|
|
98
|
+
confirmation. Environment credentials must be updated or unset when they are
|
|
99
|
+
rejected because they take precedence over interactive login.
|
|
100
|
+
|
|
95
101
|
Prefer the manual path? Pick a sign-in method:
|
|
96
102
|
|
|
97
103
|
```bash
|
|
98
|
-
# Wallet-first (no email needed) — generates a wallet on first run if you don't have one
|
|
99
|
-
teardrop auth login --siwe --generate-wallet
|
|
100
|
-
|
|
101
104
|
# Email + password
|
|
102
105
|
teardrop auth signup --email you@example.com --org-name acme
|
|
103
106
|
|
|
107
|
+
# Wallet-first (no email needed) — generates a wallet on first run if you don't have one
|
|
108
|
+
teardrop auth login --siwe --generate-wallet
|
|
109
|
+
|
|
104
110
|
# Already have an account
|
|
105
111
|
teardrop auth login --email you@example.com
|
|
106
112
|
```
|
|
@@ -143,7 +149,7 @@ Scaffold a starter spec, edit it, and publish:
|
|
|
143
149
|
```bash
|
|
144
150
|
teardrop tools init my_scraper # writes ./tool.json
|
|
145
151
|
$EDITOR tool.json # set webhook_url, schema, price
|
|
146
|
-
teardrop tools probe
|
|
152
|
+
teardrop tools probe --from-file tool.json # test webhook health before publishing
|
|
147
153
|
teardrop tools publish --from-file tool.json \
|
|
148
154
|
--settlement-wallet 0xYourChecksumAddress
|
|
149
155
|
```
|
|
@@ -156,7 +162,7 @@ teardrop tools publish
|
|
|
156
162
|
|
|
157
163
|
Tool name rules: `^[a-z][a-z0-9_]*$`, ≤ 64 chars. Prices are in atomic USDC (6 decimals): `5000` = **$0.005** per call. Settlement wallet is required once before your first payout.
|
|
158
164
|
|
|
159
|
-
Test
|
|
165
|
+
Test a local webhook before publishing with `teardrop tools probe --from-file tool.json`; the spec's method and auth settings are used by default. After publishing, use `teardrop tools probe <tool-name>`. Pass `--auth-header-name` and `--auth-header-value` to override auth settings, or use `--method` and `--payload` to customize the probe request.
|
|
160
166
|
|
|
161
167
|
Manage existing tools: `teardrop tools list | info | update | pause | delete | probe`. Full reference: [docs/cli-reference.md](docs/cli-reference.md#tool-management).
|
|
162
168
|
|
|
@@ -206,6 +212,33 @@ Streaming output renders Markdown live with inline tool calls and structured UI
|
|
|
206
212
|
|
|
207
213
|
---
|
|
208
214
|
|
|
215
|
+
## Automate Runs
|
|
216
|
+
|
|
217
|
+
Use interval schedules for recurring prompts and event triggers for inbound webhooks:
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
teardrop schedules create \
|
|
221
|
+
--name hourly-briefing \
|
|
222
|
+
--prompt "Summarize open incidents" \
|
|
223
|
+
--interval-seconds 3600
|
|
224
|
+
|
|
225
|
+
teardrop schedules list
|
|
226
|
+
teardrop schedules runs <schedule-id>
|
|
227
|
+
|
|
228
|
+
teardrop event-triggers create \
|
|
229
|
+
--name inbound-orders \
|
|
230
|
+
--prompt "Validate and process this order payload"
|
|
231
|
+
|
|
232
|
+
teardrop event-triggers runs <trigger-id>
|
|
233
|
+
teardrop event-triggers rotate-secret <trigger-id>
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
`event-triggers create` and `event-triggers rotate-secret` print the signing secret once. Store it immediately.
|
|
237
|
+
|
|
238
|
+
Full reference: [docs/cli-reference.md](docs/cli-reference.md#schedules) and [docs/cli-reference.md](docs/cli-reference.md#event-triggers).
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
209
242
|
## Chat with an Agent
|
|
210
243
|
|
|
211
244
|
A stateful chat mode that automatically continues the same thread across invocations:
|
|
@@ -268,6 +301,12 @@ teardrop llm-config set --provider google --model gemini-3-flash --routing speed
|
|
|
268
301
|
|
|
269
302
|
Pipe a key from stdin to keep it out of shell history: `--byok-key -`. See [docs/cli-reference.md](docs/cli-reference.md#llm-configuration) for advanced tuning, BYOK details, and benchmarks.
|
|
270
303
|
|
|
304
|
+
### LLM credit model
|
|
305
|
+
|
|
306
|
+
Non-BYOK organizations use Teardrop's shared provider keys. Platform credits or x402 cover the model token costs and Teardrop platform fee. BYOK organizations pay their model provider directly through their own encrypted key, but still need platform credits or x402 for the Teardrop orchestration fee. BYOK uses the configured model and does not use pooled smart routing.
|
|
307
|
+
|
|
308
|
+
New email-authenticated organizations may receive optional promotional credit after verifying their email when the program is enabled. Eligibility and availability are server-configured; SIWE users and marketplace author tools are excluded. A real top-up removes promotional restrictions.
|
|
309
|
+
|
|
271
310
|
---
|
|
272
311
|
|
|
273
312
|
## Browse the Marketplace
|
|
@@ -26,21 +26,27 @@ Requires Python ≥ 3.11.
|
|
|
26
26
|
|
|
27
27
|
## 60-Second Quickstart
|
|
28
28
|
|
|
29
|
-
The wizard walks you through sign-in, BYOK LLM setup, and your first agent run or scaffolded tool:
|
|
29
|
+
The wizard walks you through sign-in, optional BYOK LLM setup, and your first agent run or scaffolded tool:
|
|
30
30
|
|
|
31
31
|
```bash
|
|
32
32
|
teardrop quickstart
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
+
Quickstart keeps local tool scaffolding and public marketplace browsing available
|
|
36
|
+
without sign-in. A saved session is verified when you choose an agent run; if it
|
|
37
|
+
is stale, the wizard offers sign-in again before asking for a prompt or payment
|
|
38
|
+
confirmation. Environment credentials must be updated or unset when they are
|
|
39
|
+
rejected because they take precedence over interactive login.
|
|
40
|
+
|
|
35
41
|
Prefer the manual path? Pick a sign-in method:
|
|
36
42
|
|
|
37
43
|
```bash
|
|
38
|
-
# Wallet-first (no email needed) — generates a wallet on first run if you don't have one
|
|
39
|
-
teardrop auth login --siwe --generate-wallet
|
|
40
|
-
|
|
41
44
|
# Email + password
|
|
42
45
|
teardrop auth signup --email you@example.com --org-name acme
|
|
43
46
|
|
|
47
|
+
# Wallet-first (no email needed) — generates a wallet on first run if you don't have one
|
|
48
|
+
teardrop auth login --siwe --generate-wallet
|
|
49
|
+
|
|
44
50
|
# Already have an account
|
|
45
51
|
teardrop auth login --email you@example.com
|
|
46
52
|
```
|
|
@@ -83,7 +89,7 @@ Scaffold a starter spec, edit it, and publish:
|
|
|
83
89
|
```bash
|
|
84
90
|
teardrop tools init my_scraper # writes ./tool.json
|
|
85
91
|
$EDITOR tool.json # set webhook_url, schema, price
|
|
86
|
-
teardrop tools probe
|
|
92
|
+
teardrop tools probe --from-file tool.json # test webhook health before publishing
|
|
87
93
|
teardrop tools publish --from-file tool.json \
|
|
88
94
|
--settlement-wallet 0xYourChecksumAddress
|
|
89
95
|
```
|
|
@@ -96,7 +102,7 @@ teardrop tools publish
|
|
|
96
102
|
|
|
97
103
|
Tool name rules: `^[a-z][a-z0-9_]*$`, ≤ 64 chars. Prices are in atomic USDC (6 decimals): `5000` = **$0.005** per call. Settlement wallet is required once before your first payout.
|
|
98
104
|
|
|
99
|
-
Test
|
|
105
|
+
Test a local webhook before publishing with `teardrop tools probe --from-file tool.json`; the spec's method and auth settings are used by default. After publishing, use `teardrop tools probe <tool-name>`. Pass `--auth-header-name` and `--auth-header-value` to override auth settings, or use `--method` and `--payload` to customize the probe request.
|
|
100
106
|
|
|
101
107
|
Manage existing tools: `teardrop tools list | info | update | pause | delete | probe`. Full reference: [docs/cli-reference.md](docs/cli-reference.md#tool-management).
|
|
102
108
|
|
|
@@ -146,6 +152,33 @@ Streaming output renders Markdown live with inline tool calls and structured UI
|
|
|
146
152
|
|
|
147
153
|
---
|
|
148
154
|
|
|
155
|
+
## Automate Runs
|
|
156
|
+
|
|
157
|
+
Use interval schedules for recurring prompts and event triggers for inbound webhooks:
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
teardrop schedules create \
|
|
161
|
+
--name hourly-briefing \
|
|
162
|
+
--prompt "Summarize open incidents" \
|
|
163
|
+
--interval-seconds 3600
|
|
164
|
+
|
|
165
|
+
teardrop schedules list
|
|
166
|
+
teardrop schedules runs <schedule-id>
|
|
167
|
+
|
|
168
|
+
teardrop event-triggers create \
|
|
169
|
+
--name inbound-orders \
|
|
170
|
+
--prompt "Validate and process this order payload"
|
|
171
|
+
|
|
172
|
+
teardrop event-triggers runs <trigger-id>
|
|
173
|
+
teardrop event-triggers rotate-secret <trigger-id>
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
`event-triggers create` and `event-triggers rotate-secret` print the signing secret once. Store it immediately.
|
|
177
|
+
|
|
178
|
+
Full reference: [docs/cli-reference.md](docs/cli-reference.md#schedules) and [docs/cli-reference.md](docs/cli-reference.md#event-triggers).
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
149
182
|
## Chat with an Agent
|
|
150
183
|
|
|
151
184
|
A stateful chat mode that automatically continues the same thread across invocations:
|
|
@@ -208,6 +241,12 @@ teardrop llm-config set --provider google --model gemini-3-flash --routing speed
|
|
|
208
241
|
|
|
209
242
|
Pipe a key from stdin to keep it out of shell history: `--byok-key -`. See [docs/cli-reference.md](docs/cli-reference.md#llm-configuration) for advanced tuning, BYOK details, and benchmarks.
|
|
210
243
|
|
|
244
|
+
### LLM credit model
|
|
245
|
+
|
|
246
|
+
Non-BYOK organizations use Teardrop's shared provider keys. Platform credits or x402 cover the model token costs and Teardrop platform fee. BYOK organizations pay their model provider directly through their own encrypted key, but still need platform credits or x402 for the Teardrop orchestration fee. BYOK uses the configured model and does not use pooled smart routing.
|
|
247
|
+
|
|
248
|
+
New email-authenticated organizations may receive optional promotional credit after verifying their email when the program is enabled. Eligibility and availability are server-configured; SIWE users and marketplace author tools are excluded. A real top-up removes promotional restrictions.
|
|
249
|
+
|
|
211
250
|
---
|
|
212
251
|
|
|
213
252
|
## Browse the Marketplace
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# Teardrop CLI Agent Run JSON Schema
|
|
2
|
+
|
|
3
|
+
When running `teardrop run "..." --json` or `teardrop chat "..." --json`,
|
|
4
|
+
the output is a single JSON object (implies `--no-stream`).
|
|
5
|
+
|
|
6
|
+
## Schema Details
|
|
7
|
+
|
|
8
|
+
The JSON object contains the following fields:
|
|
9
|
+
|
|
10
|
+
- `text` (string): The final text response from the agent.
|
|
11
|
+
- `thread_id` (string | null): The ID of the thread used for the run. This can be used with the `--thread` flag in future runs (or `teardrop chat`) to continue the conversation.
|
|
12
|
+
|
|
13
|
+
## Example Output
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{
|
|
17
|
+
"text": "The price of ETH is currently $2,450.32.",
|
|
18
|
+
"thread_id": "thr_abc123"
|
|
19
|
+
}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
To capture specific fields, use `jq`:
|
|
24
|
+
```bash
|
|
25
|
+
teardrop run "ETH price" --json | jq -r .text
|
|
26
|
+
teardrop chat "ETH price" --json | jq -r .thread_id
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Schedules (`schedules create/get/list/update --json`)
|
|
32
|
+
|
|
33
|
+
`schedules list --json` returns a JSON array; all other commands return a single object.
|
|
34
|
+
|
|
35
|
+
| Field | Type | Description |
|
|
36
|
+
|---|---|---|
|
|
37
|
+
| `id` | string (UUID) | Schedule identifier |
|
|
38
|
+
| `org_id` | string | Owning org |
|
|
39
|
+
| `user_id` | string | Creator user |
|
|
40
|
+
| `name` | string | Display name |
|
|
41
|
+
| `prompt` | string | Agent prompt |
|
|
42
|
+
| `schedule_kind` | `"interval"` | Fixed constant |
|
|
43
|
+
| `interval_seconds` | integer | Run frequency |
|
|
44
|
+
| `enabled` | boolean | Active state |
|
|
45
|
+
| `callback_url` | string \| null | Webhook called after each run |
|
|
46
|
+
| `next_run_at` | string (ISO 8601) | Next scheduled time |
|
|
47
|
+
| `last_run_at` | string \| null (ISO 8601) | Last completed run |
|
|
48
|
+
| `consecutive_failures` | integer | Failures since last success |
|
|
49
|
+
| `created_at` | string (ISO 8601) | |
|
|
50
|
+
| `updated_at` | string (ISO 8601) | |
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
teardrop schedules create --name my-schedule --prompt "..." --interval-seconds 3600 --json | jq -r .id
|
|
54
|
+
teardrop schedules update <id> --enabled false --json | jq .enabled
|
|
55
|
+
teardrop schedules list --json | jq '.[].name'
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Event Triggers (`event-triggers create/get/list/update --json`)
|
|
61
|
+
|
|
62
|
+
`event-triggers list --json` returns a JSON array; all other commands return a single object.
|
|
63
|
+
|
|
64
|
+
| Field | Type | Description |
|
|
65
|
+
|---|---|---|
|
|
66
|
+
| `id` | string (UUID) | Trigger identifier |
|
|
67
|
+
| `org_id` | string | Owning org |
|
|
68
|
+
| `user_id` | string | Creator user |
|
|
69
|
+
| `name` | string | Display name |
|
|
70
|
+
| `prompt` | string | Prompt template (supports `{{field}}` / `{{event_json}}`) |
|
|
71
|
+
| `schedule_kind` | `"event"` | Fixed constant |
|
|
72
|
+
| `enabled` | boolean | Active state |
|
|
73
|
+
| `callback_url` | string \| null | Webhook called after each run |
|
|
74
|
+
| `trigger_token` | string | Public route discriminator |
|
|
75
|
+
| `event_path` | string | Inbound dispatch path (e.g. `/agent/events/{trigger_token}`) |
|
|
76
|
+
| `consecutive_failures` | integer | Failures since last success |
|
|
77
|
+
| `last_run_at` | string \| null (ISO 8601) | |
|
|
78
|
+
| `created_at` | string (ISO 8601) | |
|
|
79
|
+
| `updated_at` | string (ISO 8601) | |
|
|
80
|
+
|
|
81
|
+
**`event-triggers create --json` only** additionally includes:
|
|
82
|
+
|
|
83
|
+
| Field | Type | Description |
|
|
84
|
+
|---|---|---|
|
|
85
|
+
| `secret` | string | Plaintext signing secret — shown once, never retrievable again |
|
|
86
|
+
|
|
87
|
+
**`event-triggers rotate-secret --json`** returns the rotation model (not the full trigger object):
|
|
88
|
+
|
|
89
|
+
| Field | Type | Description |
|
|
90
|
+
|---|---|---|
|
|
91
|
+
| `id` | string (UUID) | Trigger identifier |
|
|
92
|
+
| `secret` | string | New plaintext signing secret — shown once |
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
# Capture id and secret on creation for use in CI
|
|
96
|
+
eval $(teardrop event-triggers create --name ci-hook --prompt "..." --json \
|
|
97
|
+
| jq -r '"TRIGGER_ID=" + .id, "TRIGGER_SECRET=" + .secret')
|
|
98
|
+
|
|
99
|
+
teardrop event-triggers list --json | jq '.[].trigger_token'
|
|
100
|
+
teardrop event-triggers rotate-secret <id> --json | jq -r .secret
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Run History (`schedules runs / event-triggers runs --json`)
|
|
106
|
+
|
|
107
|
+
Both commands return the same paginated envelope:
|
|
108
|
+
|
|
109
|
+
```json
|
|
110
|
+
{ "items": [ <ScheduledRunResult>, ... ], "next_cursor": "<cursor> | null" }
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Each `ScheduledRunResult` item:
|
|
114
|
+
|
|
115
|
+
| Field | Type | Description |
|
|
116
|
+
|---|---|---|
|
|
117
|
+
| `id` | string (UUID) | Outcome record ID |
|
|
118
|
+
| `schedule_id` | string (UUID) | Owning schedule or trigger ID |
|
|
119
|
+
| `org_id` | string | |
|
|
120
|
+
| `run_id` | string (UUID) | Core execution thread ID |
|
|
121
|
+
| `status` | `"completed" \| "failed" \| "timeout" \| "skipped"` | |
|
|
122
|
+
| `output_text` | string | Synthesized agent output |
|
|
123
|
+
| `cost_usdc` | integer | Atomic USDC charged ($1.00 = `1000000`) |
|
|
124
|
+
| `error` | string | Sanitized reason on failure; empty on success |
|
|
125
|
+
| `created_at` | string (ISO 8601) | |
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
teardrop schedules runs <id> --json | jq '.items[] | select(.status == "failed") | .error'
|
|
129
|
+
teardrop event-triggers runs <id> --limit 50 --json | jq '.next_cursor'
|
|
130
|
+
```
|
|
@@ -9,6 +9,8 @@ This document covers every flag, env var, and subcommand. For the quick path, st
|
|
|
9
9
|
- [Authentication](#authentication)
|
|
10
10
|
- [Running Agents](#running-agents)
|
|
11
11
|
- [Chat Sessions](#chat-sessions)
|
|
12
|
+
- [Schedules](#schedules)
|
|
13
|
+
- [Event Triggers](#event-triggers)
|
|
12
14
|
- [Billing & Credits](#billing--credits)
|
|
13
15
|
- [Tool Management](#tool-management)
|
|
14
16
|
- [Marketplace](#marketplace)
|
|
@@ -37,7 +39,7 @@ teardrop auth login --client-id <id> --client-secret <secret>
|
|
|
37
39
|
teardrop auth login --token <jwt>
|
|
38
40
|
|
|
39
41
|
# Sign-In With Ethereum (EIP-4361) — pick one source for the key:
|
|
40
|
-
teardrop auth login --siwe #
|
|
42
|
+
teardrop auth login --siwe # hidden prompt when no other source is supplied
|
|
41
43
|
teardrop auth login --siwe --key-file ./wallet.key # read once, never persisted
|
|
42
44
|
teardrop auth login --siwe --generate-wallet # creates a fresh wallet
|
|
43
45
|
TEARDROP_SIWE_PRIVATE_KEY=0x... teardrop auth login --siwe # CI / non-interactive
|
|
@@ -70,8 +72,9 @@ teardrop auth logout # revoke refresh token + clear stored credent
|
|
|
70
72
|
| 1 | `TEARDROP_API_KEY` env var (static JWT) |
|
|
71
73
|
| 2 | `TEARDROP_EMAIL` + `TEARDROP_SECRET` env vars |
|
|
72
74
|
| 3 | `TEARDROP_CLIENT_ID` + `TEARDROP_CLIENT_SECRET` env vars |
|
|
73
|
-
| 4 |
|
|
74
|
-
| 5 |
|
|
75
|
+
| 4 | System keyring (email + secret, or client credentials) |
|
|
76
|
+
| 5 | `access_token` in `~/.teardrop/config.toml` |
|
|
77
|
+
| 6 | Legacy `auth.token` in `~/.teardrop/config.toml` |
|
|
75
78
|
|
|
76
79
|
---
|
|
77
80
|
|
|
@@ -119,6 +122,62 @@ will start a fresh thread.
|
|
|
119
122
|
|
|
120
123
|
---
|
|
121
124
|
|
|
125
|
+
## Schedules
|
|
126
|
+
|
|
127
|
+
Recurring interval-based runs. Most commands accept `--json` to return raw structured payloads for pipeline automation:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
teardrop schedules create \
|
|
131
|
+
--name hourly-briefing \
|
|
132
|
+
--prompt "Summarize open incidents" \
|
|
133
|
+
--interval-seconds 3600 \
|
|
134
|
+
--json
|
|
135
|
+
|
|
136
|
+
teardrop schedules list --json
|
|
137
|
+
teardrop schedules get <schedule-id> --json
|
|
138
|
+
teardrop schedules update <schedule-id> --enabled false --json
|
|
139
|
+
teardrop schedules update <schedule-id> --clear-callback-url
|
|
140
|
+
teardrop schedules runs <schedule-id> --limit 50 --json
|
|
141
|
+
teardrop schedules delete <schedule-id>
|
|
142
|
+
teardrop schedules delete <schedule-id> --yes
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Non-JSON list output includes: `ID`, `Name`, `Enabled`, `Interval`, `Consecutive Failures`, `Last Run At`.
|
|
146
|
+
|
|
147
|
+
Run history output includes: `Run ID`, `Status`, `Cost (USDC)`, `Error Message`, `Executed At`.
|
|
148
|
+
|
|
149
|
+
`--clear-callback-url` sends an explicit `null` callback URL while still preserving PATCH semantics for all other omitted fields.
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Event Triggers
|
|
154
|
+
|
|
155
|
+
Reactive runs exposed as signed public webhook endpoints. Commands support a `--json` option to output formatted shapes (with creation and rotation payloads securely exposing the one-time dispatch secret):
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
teardrop event-triggers create \
|
|
159
|
+
--name inbound-orders \
|
|
160
|
+
--prompt "Validate and process this order payload" \
|
|
161
|
+
--json
|
|
162
|
+
|
|
163
|
+
teardrop event-triggers list --json
|
|
164
|
+
teardrop event-triggers get <trigger-id> --json
|
|
165
|
+
teardrop event-triggers update <trigger-id> --enabled false --json
|
|
166
|
+
teardrop event-triggers update <trigger-id> --callback-url https://example.com/hook
|
|
167
|
+
teardrop event-triggers runs <trigger-id> --limit 50 --json
|
|
168
|
+
teardrop event-triggers rotate-secret <trigger-id> --json
|
|
169
|
+
teardrop event-triggers delete <trigger-id>
|
|
170
|
+
teardrop event-triggers delete <trigger-id> --yes
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
`create` and `rotate-secret` display the signing secret once (both inside non-JSON stderr summaries and their corresponding use-once JSON attributes). Store it immediately; subsequent `list`, `get`, or `update` calls permanently exclude the plaintext secret.
|
|
174
|
+
|
|
175
|
+
Non-JSON list output includes: `ID`, `Name`, `Enabled`, `Kind`, `Consecutive Failures`, `Last Run At`.
|
|
176
|
+
|
|
177
|
+
Run history output includes: `Run ID`, `Status`, `Cost (USDC)`, `Error Message`, `Executed At`.
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
122
181
|
## Billing & Credits
|
|
123
182
|
|
|
124
183
|
```bash
|
|
@@ -137,6 +196,12 @@ The CLI does not support direct top-ups. To add credits or manage your billing m
|
|
|
137
196
|
|
|
138
197
|
If you run out of credits during an agent run, the agent will pause and provide this link.
|
|
139
198
|
|
|
199
|
+
### LLM credit model
|
|
200
|
+
|
|
201
|
+
Non-BYOK organizations use Teardrop's shared provider keys and need credits or x402 for model token costs plus the platform fee. BYOK organizations pay their provider directly through their encrypted key, but still need credits or x402 for the Teardrop orchestration fee. BYOK uses the configured model; pooled smart routing is disabled.
|
|
202
|
+
|
|
203
|
+
Optional promotional credit may be granted after successful email verification when the server-side program is enabled. It is not available to SIWE users or marketplace author tools, and a real top-up removes promotional restrictions. The CLI does not assume eligibility or a fixed promotional amount.
|
|
204
|
+
|
|
140
205
|
---
|
|
141
206
|
|
|
142
207
|
## Tool Management
|
|
@@ -208,7 +273,13 @@ teardrop tools delete get_weather --yes # skip confirmation
|
|
|
208
273
|
|
|
209
274
|
### Test webhook health
|
|
210
275
|
|
|
211
|
-
Before publishing
|
|
276
|
+
Before publishing, test a local spec without authentication or an API lookup:
|
|
277
|
+
|
|
278
|
+
```bash
|
|
279
|
+
teardrop tools probe --from-file tool.json
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
After publishing or updating a webhook URL, test the registered tool:
|
|
212
283
|
|
|
213
284
|
```bash
|
|
214
285
|
teardrop tools probe get_weather # test default POST request
|
|
@@ -231,6 +302,8 @@ teardrop tools probe get_weather --method GET
|
|
|
231
302
|
teardrop tools probe get_weather --payload '{"test": "data"}'
|
|
232
303
|
```
|
|
233
304
|
|
|
305
|
+
For `--from-file`, the spec's `webhook_method`, `auth_header_name`, and `auth_header_value` are used by default. Explicit probe flags override them.
|
|
306
|
+
|
|
234
307
|
Exit code: 0 on success (2xx–3xx), 1 on timeout/5xx/connection error. Warning (exit 0) on 4xx responses (e.g., auth failures).
|
|
235
308
|
|
|
236
309
|
---
|
|
@@ -296,7 +369,7 @@ teardrop llm-config set \
|
|
|
296
369
|
--timeout-seconds 60
|
|
297
370
|
```
|
|
298
371
|
|
|
299
|
-
**Providers:** `openrouter`, `google`, `anthropic`
|
|
372
|
+
**Providers:** `openrouter`, `google`, `anthropic`, `openai`
|
|
300
373
|
**Routing:** `default` · `cost` · `speed` · `quality`
|
|
301
374
|
**Validation:** temperature 0.0–2.0 · max tokens 1–200,000 · timeout ≥ 1 s
|
|
302
375
|
|
|
@@ -317,6 +390,8 @@ Get-Content "$key_file" | teardrop llm-config set `
|
|
|
317
390
|
teardrop llm-config set --provider anthropic --model claude-sonnet-4-6 --clear-key
|
|
318
391
|
```
|
|
319
392
|
|
|
393
|
+
BYOK keys are encrypted by the platform and used only for the configured provider/model. Teardrop still charges the orchestration fee through credits or x402; it does not charge Teardrop for the provider's model usage.
|
|
394
|
+
|
|
320
395
|
---
|
|
321
396
|
|
|
322
397
|
## MCP Servers
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "teardrop-cli"
|
|
7
|
-
version = "0.2
|
|
7
|
+
version = "0.3.2"
|
|
8
8
|
description = "Command-line interface for the Teardrop AI agent platform"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { file = "LICENSE" }
|
|
@@ -24,7 +24,7 @@ classifiers = [
|
|
|
24
24
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
25
25
|
]
|
|
26
26
|
dependencies = [
|
|
27
|
-
"teardrop-sdk>=0.
|
|
27
|
+
"teardrop-sdk>=0.3.0",
|
|
28
28
|
"typer>=0.12",
|
|
29
29
|
"rich>=13.0",
|
|
30
30
|
"platformdirs>=4.0",
|
|
@@ -47,7 +47,5 @@ def render_tool_template(name: str, *, with_marketplace: bool = False) -> dict:
|
|
|
47
47
|
data = {**_BASE_TEMPLATE, "name": name}
|
|
48
48
|
if with_marketplace:
|
|
49
49
|
data["publish_as_mcp"] = True
|
|
50
|
-
data["marketplace_description"] = (
|
|
51
|
-
"One-line marketplace pitch (max 200 characters)."
|
|
52
|
-
)
|
|
50
|
+
data["marketplace_description"] = "One-line marketplace pitch (max 200 characters)."
|
|
53
51
|
return data
|
|
@@ -23,9 +23,11 @@ from teardrop_cli._lazy import LazyGroup
|
|
|
23
23
|
"quickstart": "teardrop_cli.commands.quickstart:app",
|
|
24
24
|
"config": "teardrop_cli.commands.config_cmd:app",
|
|
25
25
|
"run": "teardrop_cli.commands.run:app",
|
|
26
|
+
"schedules": "teardrop_cli.commands.schedules:app",
|
|
26
27
|
"balance": "teardrop_cli.commands.balance:app",
|
|
27
28
|
"usage": "teardrop_cli.commands.usage:app",
|
|
28
29
|
"agent-tools": "teardrop_cli.commands.agent_tools:app",
|
|
30
|
+
"event-triggers": "teardrop_cli.commands.event_triggers:app",
|
|
29
31
|
"marketplace": "teardrop_cli.commands.marketplace:app",
|
|
30
32
|
"tools": "teardrop_cli.commands.tools:app",
|
|
31
33
|
"earnings": "teardrop_cli.commands.earnings:app",
|
|
@@ -5,6 +5,7 @@ from __future__ import annotations
|
|
|
5
5
|
import asyncio
|
|
6
6
|
import os
|
|
7
7
|
import re
|
|
8
|
+
import sys
|
|
8
9
|
from datetime import UTC, datetime
|
|
9
10
|
from pathlib import Path
|
|
10
11
|
from typing import Annotated
|
|
@@ -49,7 +50,9 @@ def signup(
|
|
|
49
50
|
str | None,
|
|
50
51
|
typer.Option("--org-name", help="Organization name (1–200 chars)."),
|
|
51
52
|
] = None,
|
|
52
|
-
as_json: Annotated[
|
|
53
|
+
as_json: Annotated[
|
|
54
|
+
bool, typer.Option("--json", help="Output the JWT response as JSON.")
|
|
55
|
+
] = False,
|
|
53
56
|
base_url: Annotated[
|
|
54
57
|
str | None, typer.Option("--base-url", help="Override the API base URL.", hidden=True)
|
|
55
58
|
] = None,
|
|
@@ -317,7 +320,11 @@ def login(
|
|
|
317
320
|
print_success(f"Logged in as [bold]{email}[/bold]{org_label}")
|
|
318
321
|
|
|
319
322
|
|
|
320
|
-
def interactive_reauthenticate(
|
|
323
|
+
def interactive_reauthenticate(
|
|
324
|
+
base_url: str | None = None,
|
|
325
|
+
*,
|
|
326
|
+
warning_message: str = "Your session expired during this command.",
|
|
327
|
+
) -> bool:
|
|
321
328
|
"""Prompt the user to sign in again after an expired session.
|
|
322
329
|
|
|
323
330
|
Returns ``True`` when authentication completed and the caller should retry,
|
|
@@ -326,7 +333,7 @@ def interactive_reauthenticate(base_url: str | None = None) -> bool:
|
|
|
326
333
|
from teardrop_cli import config
|
|
327
334
|
from teardrop_cli.formatting import console, print_warning
|
|
328
335
|
|
|
329
|
-
print_warning(
|
|
336
|
+
print_warning(warning_message)
|
|
330
337
|
console.print("\n[bold]Sign in to continue:[/bold]")
|
|
331
338
|
console.print(" [cyan]0[/cyan] Cancel")
|
|
332
339
|
console.print(" [cyan]1[/cyan] Email + password [recommended]")
|
|
@@ -373,9 +380,7 @@ def _resolve_siwe_private_key(
|
|
|
373
380
|
try:
|
|
374
381
|
from eth_account import Account
|
|
375
382
|
except ImportError:
|
|
376
|
-
print_error(
|
|
377
|
-
"eth-account is required.", hint="pip install 'teardrop-cli[siwe]'"
|
|
378
|
-
)
|
|
383
|
+
print_error("eth-account is required.", hint="pip install teardrop-cli")
|
|
379
384
|
raise typer.Exit(1) from None
|
|
380
385
|
acct = Account.create()
|
|
381
386
|
from rich.panel import Panel
|
|
@@ -406,16 +411,21 @@ def _resolve_siwe_private_key(
|
|
|
406
411
|
if env_key := os.environ.get("TEARDROP_SIWE_PRIVATE_KEY"):
|
|
407
412
|
return env_key, False
|
|
408
413
|
|
|
409
|
-
|
|
410
|
-
"
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
" • --key-file PATH\n"
|
|
415
|
-
" • --generate-wallet (creates a new wallet)"
|
|
416
|
-
),
|
|
414
|
+
hint = (
|
|
415
|
+
"Provide one via:\n"
|
|
416
|
+
" • TEARDROP_SIWE_PRIVATE_KEY env var\n"
|
|
417
|
+
" • --key-file PATH\n"
|
|
418
|
+
" • --generate-wallet (creates a new wallet)"
|
|
417
419
|
)
|
|
418
|
-
|
|
420
|
+
if not sys.stdin.isatty():
|
|
421
|
+
print_error("No Ethereum private key found.", hint=hint)
|
|
422
|
+
raise typer.Exit(1)
|
|
423
|
+
|
|
424
|
+
private_key = typer.prompt("Ethereum private key", hide_input=True).strip()
|
|
425
|
+
if not private_key:
|
|
426
|
+
print_error("No Ethereum private key provided.", hint=hint)
|
|
427
|
+
raise typer.Exit(1)
|
|
428
|
+
return private_key, False
|
|
419
429
|
|
|
420
430
|
|
|
421
431
|
async def _siwe_auth_async(
|
|
@@ -536,9 +546,7 @@ def _login_siwe(
|
|
|
536
546
|
|
|
537
547
|
try:
|
|
538
548
|
with spinner("Signing in with Ethereum…"):
|
|
539
|
-
jwt_token = asyncio.run(
|
|
540
|
-
_siwe_auth_async(url, private_key, wallet_address)
|
|
541
|
-
)
|
|
549
|
+
jwt_token = asyncio.run(_siwe_auth_async(url, private_key, wallet_address))
|
|
542
550
|
except Exception as exc:
|
|
543
551
|
_handle_auth_error(exc)
|
|
544
552
|
return
|
|
@@ -713,4 +721,5 @@ def invite(
|
|
|
713
721
|
print_success(f"Invited [bold]{email}[/bold] (role: {role})")
|
|
714
722
|
if link:
|
|
715
723
|
from teardrop_cli.formatting import console
|
|
724
|
+
|
|
716
725
|
console.print(f" Invite link: [bold]{link}[/bold]")
|
|
@@ -105,9 +105,7 @@ def show(as_json: bool, base_url: str | None) -> None:
|
|
|
105
105
|
["Daily spend", _fmt_usdc(data.get("daily_spend_usdc"))],
|
|
106
106
|
["Account status", "paused" if data.get("is_paused") else "active"],
|
|
107
107
|
]
|
|
108
|
-
print_table(
|
|
109
|
-
[("Field", {"style": "bold cyan"}), "Value"], rows, title="Account Balance"
|
|
110
|
-
)
|
|
108
|
+
print_table([("Field", {"style": "bold cyan"}), "Value"], rows, title="Account Balance")
|
|
111
109
|
|
|
112
110
|
if data.get("is_paused"):
|
|
113
111
|
console.print(
|
|
@@ -185,6 +183,7 @@ def _credit_history(limit: int, as_json: bool, base_url: str | None) -> None:
|
|
|
185
183
|
|
|
186
184
|
if not items:
|
|
187
185
|
from teardrop_cli.formatting import data_console
|
|
186
|
+
|
|
188
187
|
data_console.print("[dim]No credit history found.[/dim]")
|
|
189
188
|
return
|
|
190
189
|
|
|
@@ -136,9 +136,7 @@ def app(
|
|
|
136
136
|
if estimate_cost:
|
|
137
137
|
from teardrop_cli.commands.run import _estimate_cost
|
|
138
138
|
|
|
139
|
-
_estimate_cost(
|
|
140
|
-
message, context=context, tool_policy=tool_policy, base_url=base_url
|
|
141
|
-
)
|
|
139
|
+
_estimate_cost(message, context=context, tool_policy=tool_policy, base_url=base_url)
|
|
142
140
|
return
|
|
143
141
|
|
|
144
142
|
# --- Capture the server-returned thread id ---
|
|
@@ -174,4 +172,4 @@ def app(
|
|
|
174
172
|
|
|
175
173
|
# Always print the thread id for discoverability (to stderr)
|
|
176
174
|
if final_thread:
|
|
177
|
-
console.print(f"[dim]thread: {final_thread}[/dim]")
|
|
175
|
+
console.print(f"[dim]thread: {final_thread}[/dim]")
|