teardrop-cli 0.3.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.3.0 → teardrop_cli-0.3.2}/PKG-INFO +20 -8
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/README.md +18 -6
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/docs/cli-reference.md +36 -17
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/pyproject.toml +2 -2
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/src/teardrop_cli/commands/auth.py +22 -12
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/src/teardrop_cli/commands/quickstart.py +136 -22
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/src/teardrop_cli/commands/run.py +10 -6
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/src/teardrop_cli/commands/tools.py +74 -20
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/src/teardrop_cli/formatting.py +3 -2
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/tests/smoke/conftest.py +1 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/tests/test_auth.py +20 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/tests/test_quickstart.py +98 -25
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/tests/test_token_expiry_fallback.py +24 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/tests/test_tools.py +128 -0
- teardrop_cli-0.3.0/src/teardrop_cli/__init__.py +0 -1
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/.github/workflows/publish.yml +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/.github/workflows/test.yml +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/.gitignore +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/.vscode/settings.json +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/LICENSE +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/docs/cli-json-schema.md +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/src/teardrop_cli/_fixtures.py +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/src/teardrop_cli/_lazy.py +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/src/teardrop_cli/_templates.py +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/src/teardrop_cli/cli.py +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/src/teardrop_cli/commands/__init__.py +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/src/teardrop_cli/commands/agent_tools.py +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/src/teardrop_cli/commands/balance.py +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/src/teardrop_cli/commands/chat.py +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/src/teardrop_cli/commands/config_cmd.py +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/src/teardrop_cli/commands/earnings.py +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/src/teardrop_cli/commands/event_triggers.py +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/src/teardrop_cli/commands/llm_config.py +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/src/teardrop_cli/commands/marketplace.py +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/src/teardrop_cli/commands/mcp.py +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/src/teardrop_cli/commands/models.py +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/src/teardrop_cli/commands/schedules.py +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/src/teardrop_cli/commands/usage.py +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/src/teardrop_cli/config.py +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/src/teardrop_cli/pricing.py +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/tests/conftest.py +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/tests/e2e/README.md +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/tests/e2e/__init__.py +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/tests/e2e/conftest.py +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/tests/e2e/test_auth_e2e.py +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/tests/e2e/test_billing_e2e.py +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/tests/e2e/test_marketplace_e2e.py +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/tests/e2e/test_run_e2e.py +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/tests/e2e/test_signup_e2e.py +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/tests/e2e/test_siwe_login_e2e.py +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/tests/smoke/__init__.py +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/tests/smoke/test_config_persistence.py +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/tests/smoke/test_keyring_integration.py +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/tests/smoke/test_perf_lazygroup.py +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/tests/smoke/test_siwe_signing.py +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/tests/test_billing.py +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/tests/test_chat.py +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/tests/test_config_cmd.py +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/tests/test_credential_priority.py +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/tests/test_earnings.py +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/tests/test_event_triggers.py +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/tests/test_init_and_byok.py +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/tests/test_llm_config.py +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/tests/test_marketplace.py +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/tests/test_mcp.py +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/tests/test_models.py +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/tests/test_run.py +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/tests/test_schedules.py +0 -0
- {teardrop_cli-0.3.0 → teardrop_cli-0.3.2}/tests/test_signup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: teardrop-cli
|
|
3
|
-
Version: 0.3.
|
|
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
|
|
|
@@ -295,6 +301,12 @@ teardrop llm-config set --provider google --model gemini-3-flash --routing speed
|
|
|
295
301
|
|
|
296
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.
|
|
297
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
|
+
|
|
298
310
|
---
|
|
299
311
|
|
|
300
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
|
|
|
@@ -235,6 +241,12 @@ teardrop llm-config set --provider google --model gemini-3-flash --routing speed
|
|
|
235
241
|
|
|
236
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.
|
|
237
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
|
+
|
|
238
250
|
---
|
|
239
251
|
|
|
240
252
|
## Browse the Marketplace
|
|
@@ -39,7 +39,7 @@ teardrop auth login --client-id <id> --client-secret <secret>
|
|
|
39
39
|
teardrop auth login --token <jwt>
|
|
40
40
|
|
|
41
41
|
# Sign-In With Ethereum (EIP-4361) — pick one source for the key:
|
|
42
|
-
teardrop auth login --siwe #
|
|
42
|
+
teardrop auth login --siwe # hidden prompt when no other source is supplied
|
|
43
43
|
teardrop auth login --siwe --key-file ./wallet.key # read once, never persisted
|
|
44
44
|
teardrop auth login --siwe --generate-wallet # creates a fresh wallet
|
|
45
45
|
TEARDROP_SIWE_PRIVATE_KEY=0x... teardrop auth login --siwe # CI / non-interactive
|
|
@@ -72,8 +72,9 @@ teardrop auth logout # revoke refresh token + clear stored credent
|
|
|
72
72
|
| 1 | `TEARDROP_API_KEY` env var (static JWT) |
|
|
73
73
|
| 2 | `TEARDROP_EMAIL` + `TEARDROP_SECRET` env vars |
|
|
74
74
|
| 3 | `TEARDROP_CLIENT_ID` + `TEARDROP_CLIENT_SECRET` env vars |
|
|
75
|
-
| 4 |
|
|
76
|
-
| 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` |
|
|
77
78
|
|
|
78
79
|
---
|
|
79
80
|
|
|
@@ -123,17 +124,18 @@ will start a fresh thread.
|
|
|
123
124
|
|
|
124
125
|
## Schedules
|
|
125
126
|
|
|
126
|
-
Recurring interval-based runs:
|
|
127
|
+
Recurring interval-based runs. Most commands accept `--json` to return raw structured payloads for pipeline automation:
|
|
127
128
|
|
|
128
129
|
```bash
|
|
129
130
|
teardrop schedules create \
|
|
130
131
|
--name hourly-briefing \
|
|
131
132
|
--prompt "Summarize open incidents" \
|
|
132
|
-
--interval-seconds 3600
|
|
133
|
+
--interval-seconds 3600 \
|
|
134
|
+
--json
|
|
133
135
|
|
|
134
|
-
teardrop schedules list
|
|
135
|
-
teardrop schedules get <schedule-id>
|
|
136
|
-
teardrop schedules update <schedule-id> --enabled false
|
|
136
|
+
teardrop schedules list --json
|
|
137
|
+
teardrop schedules get <schedule-id> --json
|
|
138
|
+
teardrop schedules update <schedule-id> --enabled false --json
|
|
137
139
|
teardrop schedules update <schedule-id> --clear-callback-url
|
|
138
140
|
teardrop schedules runs <schedule-id> --limit 50 --json
|
|
139
141
|
teardrop schedules delete <schedule-id>
|
|
@@ -150,24 +152,25 @@ Run history output includes: `Run ID`, `Status`, `Cost (USDC)`, `Error Message`,
|
|
|
150
152
|
|
|
151
153
|
## Event Triggers
|
|
152
154
|
|
|
153
|
-
Reactive runs exposed as signed public webhook endpoints:
|
|
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):
|
|
154
156
|
|
|
155
157
|
```bash
|
|
156
158
|
teardrop event-triggers create \
|
|
157
159
|
--name inbound-orders \
|
|
158
|
-
--prompt "Validate and process this order payload"
|
|
160
|
+
--prompt "Validate and process this order payload" \
|
|
161
|
+
--json
|
|
159
162
|
|
|
160
|
-
teardrop event-triggers list
|
|
161
|
-
teardrop event-triggers get <trigger-id>
|
|
162
|
-
teardrop event-triggers update <trigger-id> --enabled false
|
|
163
|
+
teardrop event-triggers list --json
|
|
164
|
+
teardrop event-triggers get <trigger-id> --json
|
|
165
|
+
teardrop event-triggers update <trigger-id> --enabled false --json
|
|
163
166
|
teardrop event-triggers update <trigger-id> --callback-url https://example.com/hook
|
|
164
167
|
teardrop event-triggers runs <trigger-id> --limit 50 --json
|
|
165
|
-
teardrop event-triggers rotate-secret <trigger-id>
|
|
168
|
+
teardrop event-triggers rotate-secret <trigger-id> --json
|
|
166
169
|
teardrop event-triggers delete <trigger-id>
|
|
167
170
|
teardrop event-triggers delete <trigger-id> --yes
|
|
168
171
|
```
|
|
169
172
|
|
|
170
|
-
`create` and `rotate-secret` display the signing secret once. Store it immediately; subsequent `list`
|
|
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.
|
|
171
174
|
|
|
172
175
|
Non-JSON list output includes: `ID`, `Name`, `Enabled`, `Kind`, `Consecutive Failures`, `Last Run At`.
|
|
173
176
|
|
|
@@ -193,6 +196,12 @@ The CLI does not support direct top-ups. To add credits or manage your billing m
|
|
|
193
196
|
|
|
194
197
|
If you run out of credits during an agent run, the agent will pause and provide this link.
|
|
195
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
|
+
|
|
196
205
|
---
|
|
197
206
|
|
|
198
207
|
## Tool Management
|
|
@@ -264,7 +273,13 @@ teardrop tools delete get_weather --yes # skip confirmation
|
|
|
264
273
|
|
|
265
274
|
### Test webhook health
|
|
266
275
|
|
|
267
|
-
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:
|
|
268
283
|
|
|
269
284
|
```bash
|
|
270
285
|
teardrop tools probe get_weather # test default POST request
|
|
@@ -287,6 +302,8 @@ teardrop tools probe get_weather --method GET
|
|
|
287
302
|
teardrop tools probe get_weather --payload '{"test": "data"}'
|
|
288
303
|
```
|
|
289
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
|
+
|
|
290
307
|
Exit code: 0 on success (2xx–3xx), 1 on timeout/5xx/connection error. Warning (exit 0) on 4xx responses (e.g., auth failures).
|
|
291
308
|
|
|
292
309
|
---
|
|
@@ -352,7 +369,7 @@ teardrop llm-config set \
|
|
|
352
369
|
--timeout-seconds 60
|
|
353
370
|
```
|
|
354
371
|
|
|
355
|
-
**Providers:** `openrouter`, `google`, `anthropic`
|
|
372
|
+
**Providers:** `openrouter`, `google`, `anthropic`, `openai`
|
|
356
373
|
**Routing:** `default` · `cost` · `speed` · `quality`
|
|
357
374
|
**Validation:** temperature 0.0–2.0 · max tokens 1–200,000 · timeout ≥ 1 s
|
|
358
375
|
|
|
@@ -373,6 +390,8 @@ Get-Content "$key_file" | teardrop llm-config set `
|
|
|
373
390
|
teardrop llm-config set --provider anthropic --model claude-sonnet-4-6 --clear-key
|
|
374
391
|
```
|
|
375
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
|
+
|
|
376
395
|
---
|
|
377
396
|
|
|
378
397
|
## MCP Servers
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "teardrop-cli"
|
|
7
|
-
version = "0.3.
|
|
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",
|
|
@@ -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
|
|
@@ -319,7 +320,11 @@ def login(
|
|
|
319
320
|
print_success(f"Logged in as [bold]{email}[/bold]{org_label}")
|
|
320
321
|
|
|
321
322
|
|
|
322
|
-
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:
|
|
323
328
|
"""Prompt the user to sign in again after an expired session.
|
|
324
329
|
|
|
325
330
|
Returns ``True`` when authentication completed and the caller should retry,
|
|
@@ -328,7 +333,7 @@ def interactive_reauthenticate(base_url: str | None = None) -> bool:
|
|
|
328
333
|
from teardrop_cli import config
|
|
329
334
|
from teardrop_cli.formatting import console, print_warning
|
|
330
335
|
|
|
331
|
-
print_warning(
|
|
336
|
+
print_warning(warning_message)
|
|
332
337
|
console.print("\n[bold]Sign in to continue:[/bold]")
|
|
333
338
|
console.print(" [cyan]0[/cyan] Cancel")
|
|
334
339
|
console.print(" [cyan]1[/cyan] Email + password [recommended]")
|
|
@@ -375,7 +380,7 @@ def _resolve_siwe_private_key(
|
|
|
375
380
|
try:
|
|
376
381
|
from eth_account import Account
|
|
377
382
|
except ImportError:
|
|
378
|
-
print_error("eth-account is required.", hint="pip install
|
|
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(
|
|
@@ -7,6 +7,8 @@ orchestration: each step delegates to an existing command implementation.
|
|
|
7
7
|
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
|
+
import asyncio
|
|
11
|
+
|
|
10
12
|
import click
|
|
11
13
|
import typer
|
|
12
14
|
|
|
@@ -20,6 +22,110 @@ def app(base_url: str | None) -> None:
|
|
|
20
22
|
_run_quickstart(base_url)
|
|
21
23
|
|
|
22
24
|
|
|
25
|
+
def _is_authentication_failure(exc: BaseException) -> bool:
|
|
26
|
+
from teardrop import AuthenticationError
|
|
27
|
+
|
|
28
|
+
return isinstance(exc, AuthenticationError) or getattr(exc, "status_code", None) == 401
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _verify_saved_session(
|
|
32
|
+
base_url: str | None,
|
|
33
|
+
source: str,
|
|
34
|
+
*,
|
|
35
|
+
allow_recovery: bool = True,
|
|
36
|
+
) -> bool:
|
|
37
|
+
from teardrop_cli import config
|
|
38
|
+
from teardrop_cli.formatting import print_error, spinner
|
|
39
|
+
|
|
40
|
+
try:
|
|
41
|
+
client = config.get_client(base_url)
|
|
42
|
+
|
|
43
|
+
async def _fetch_identity():
|
|
44
|
+
try:
|
|
45
|
+
return await client.get_me()
|
|
46
|
+
finally:
|
|
47
|
+
await client.close()
|
|
48
|
+
|
|
49
|
+
with spinner("Verifying saved credentials…"):
|
|
50
|
+
identity = asyncio.run(_fetch_identity())
|
|
51
|
+
except (click.exceptions.Exit, SystemExit):
|
|
52
|
+
return False
|
|
53
|
+
except Exception as exc: # noqa: BLE001
|
|
54
|
+
if _is_authentication_failure(exc):
|
|
55
|
+
if not allow_recovery:
|
|
56
|
+
print_error(
|
|
57
|
+
"Sign-in failed.",
|
|
58
|
+
hint="Run [bold]teardrop auth login[/bold] to try again.",
|
|
59
|
+
)
|
|
60
|
+
return False
|
|
61
|
+
if source.startswith("env:"):
|
|
62
|
+
print_error(
|
|
63
|
+
"Saved environment credentials were rejected.",
|
|
64
|
+
hint=(
|
|
65
|
+
"Update or unset TEARDROP_API_KEY, TEARDROP_EMAIL, or "
|
|
66
|
+
"TEARDROP_CLIENT_ID, then run [bold]teardrop auth login[/bold]."
|
|
67
|
+
),
|
|
68
|
+
)
|
|
69
|
+
return False
|
|
70
|
+
|
|
71
|
+
from teardrop_cli.commands.auth import interactive_reauthenticate
|
|
72
|
+
|
|
73
|
+
try:
|
|
74
|
+
if not interactive_reauthenticate(
|
|
75
|
+
base_url=base_url,
|
|
76
|
+
warning_message="Your saved session is no longer valid. Sign in again to continue.",
|
|
77
|
+
):
|
|
78
|
+
return False
|
|
79
|
+
except (click.exceptions.Exit, SystemExit):
|
|
80
|
+
return False
|
|
81
|
+
|
|
82
|
+
refreshed_source = config.detect_credential_source()
|
|
83
|
+
if refreshed_source is None:
|
|
84
|
+
print_error("Sign-in did not produce a saved session.")
|
|
85
|
+
return False
|
|
86
|
+
return _verify_saved_session(
|
|
87
|
+
base_url,
|
|
88
|
+
refreshed_source,
|
|
89
|
+
allow_recovery=False,
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
print_error(
|
|
93
|
+
"Could not verify your saved session.",
|
|
94
|
+
hint="Check your network connection and API URL, then try again.",
|
|
95
|
+
)
|
|
96
|
+
return False
|
|
97
|
+
|
|
98
|
+
label = None
|
|
99
|
+
if isinstance(identity, dict):
|
|
100
|
+
label = identity.get("email") or identity.get("sub")
|
|
101
|
+
else:
|
|
102
|
+
label = getattr(identity, "email", None) or getattr(identity, "sub", None)
|
|
103
|
+
suffix = f" for [bold]{label}[/bold]" if label else ""
|
|
104
|
+
from teardrop_cli.formatting import console
|
|
105
|
+
|
|
106
|
+
console.print(f"[bold green]✓[/bold green] Session verified{suffix}.")
|
|
107
|
+
return True
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def _ensure_authenticated(base_url: str | None) -> bool:
|
|
111
|
+
from teardrop_cli import config
|
|
112
|
+
from teardrop_cli.formatting import console, print_error
|
|
113
|
+
|
|
114
|
+
source = config.detect_credential_source()
|
|
115
|
+
if source is None:
|
|
116
|
+
console.print("\n[bold]Sign-in is required to run an agent.[/bold]")
|
|
117
|
+
try:
|
|
118
|
+
_auth_menu(base_url)
|
|
119
|
+
except (click.exceptions.Exit, SystemExit):
|
|
120
|
+
return False
|
|
121
|
+
source = config.detect_credential_source()
|
|
122
|
+
if source is None:
|
|
123
|
+
print_error("Sign-in did not produce a saved session.")
|
|
124
|
+
return False
|
|
125
|
+
|
|
126
|
+
return _verify_saved_session(base_url, source)
|
|
127
|
+
|
|
128
|
+
|
|
23
129
|
def _run_quickstart(base_url: str | None) -> None:
|
|
24
130
|
from teardrop_cli import config
|
|
25
131
|
from teardrop_cli.formatting import console
|
|
@@ -31,19 +137,15 @@ def _run_quickstart(base_url: str | None) -> None:
|
|
|
31
137
|
"\n[bold cyan]Welcome to Teardrop.[/bold cyan] "
|
|
32
138
|
"[dim]This wizard will get you running in under a minute.[/dim]\n"
|
|
33
139
|
)
|
|
34
|
-
|
|
35
|
-
# 1. Auth — use existing creds if present, otherwise guide through auth.
|
|
36
|
-
if is_repeat:
|
|
37
|
-
console.print("[dim]Existing credentials detected.[/dim]")
|
|
38
|
-
console.print(f"[dim](source: {config.detect_credential_source()})[/dim]")
|
|
39
140
|
console.print(
|
|
40
|
-
"[dim]
|
|
41
|
-
"
|
|
141
|
+
"[dim]You can explore locally now; sign-in is requested only for "
|
|
142
|
+
"account actions and agent runs.[/dim]"
|
|
42
143
|
)
|
|
43
144
|
else:
|
|
44
|
-
|
|
145
|
+
console.print("[dim]Saved session found locally.[/dim]")
|
|
146
|
+
console.print(f"[dim](source: {config.detect_credential_source()})[/dim]")
|
|
147
|
+
console.print("[dim]It will be checked when you choose an authenticated action.[/dim]")
|
|
45
148
|
|
|
46
|
-
# 2. What's next?
|
|
47
149
|
console.print()
|
|
48
150
|
console.print("[bold]What would you like to do next?[/bold]")
|
|
49
151
|
console.print(" [cyan]0[/cyan] Nothing, just exploring [dim](exit)[/dim]")
|
|
@@ -70,13 +172,11 @@ def _auth_menu(base_url: str | None) -> None:
|
|
|
70
172
|
|
|
71
173
|
if not has_account:
|
|
72
174
|
console.print("\n[bold]Create your account:[/bold]")
|
|
73
|
-
console.print(" [cyan]1[/cyan]
|
|
74
|
-
console.print(" [cyan]2[/cyan]
|
|
175
|
+
console.print(" [cyan]1[/cyan] Email + password [recommended]")
|
|
176
|
+
console.print(" [cyan]2[/cyan] Ethereum wallet — no email needed")
|
|
75
177
|
choice = typer.prompt("Choice", default="1")
|
|
76
178
|
|
|
77
179
|
if choice == "2":
|
|
78
|
-
signup(base_url=base_url)
|
|
79
|
-
else:
|
|
80
180
|
from teardrop_cli import config
|
|
81
181
|
|
|
82
182
|
url = base_url or config.get_base_url()
|
|
@@ -86,6 +186,8 @@ def _auth_menu(base_url: str | None) -> None:
|
|
|
86
186
|
default=False,
|
|
87
187
|
)
|
|
88
188
|
_login_siwe(url, generate_wallet=generate, save_key=save_key)
|
|
189
|
+
else:
|
|
190
|
+
signup(base_url=base_url)
|
|
89
191
|
else:
|
|
90
192
|
console.print("\n[bold]Sign in:[/bold]")
|
|
91
193
|
console.print(" [cyan]1[/cyan] Ethereum wallet")
|
|
@@ -121,27 +223,39 @@ def _scaffold_branch() -> None:
|
|
|
121
223
|
|
|
122
224
|
|
|
123
225
|
def _sample_run_branch(base_url: str | None) -> None:
|
|
124
|
-
import
|
|
125
|
-
|
|
126
|
-
from teardrop_cli import config
|
|
127
|
-
from teardrop_cli.commands.run import _handle_run_error, _stream
|
|
226
|
+
from teardrop_cli.commands.run import _estimate_cost, _execute_run
|
|
128
227
|
from teardrop_cli.formatting import console
|
|
129
228
|
|
|
229
|
+
if not _ensure_authenticated(base_url):
|
|
230
|
+
return
|
|
231
|
+
|
|
130
232
|
message = typer.prompt(
|
|
131
233
|
"Prompt", default="What is the current ETH gas price?", show_default=True
|
|
132
234
|
)
|
|
133
235
|
console.print()
|
|
134
|
-
|
|
236
|
+
console.print(
|
|
237
|
+
"[dim]Billing note: platform credits or x402 cover non-BYOK model usage and platform costs. "
|
|
238
|
+
"BYOK pays your provider directly but still needs Teardrop payment capacity for orchestration.[/dim]"
|
|
239
|
+
)
|
|
240
|
+
if typer.confirm("Configure a BYOK LLM key first?", default=False):
|
|
135
241
|
from teardrop_cli.commands.llm_config import _byok_interactive
|
|
136
242
|
|
|
137
243
|
_byok_interactive(base_url=base_url)
|
|
138
244
|
console.print()
|
|
139
245
|
|
|
140
|
-
|
|
246
|
+
if typer.confirm(
|
|
247
|
+
"Show an estimated cost before running?", default=True
|
|
248
|
+
) and not _estimate_cost(message, base_url=base_url):
|
|
249
|
+
console.print("\nNo run started. Resolve the issue and run quickstart again.")
|
|
250
|
+
return
|
|
251
|
+
|
|
252
|
+
if not typer.confirm("Run this prompt now? It may use credits or x402.", default=True):
|
|
253
|
+
console.print("\nRun cancelled. No agent request was sent.")
|
|
254
|
+
return
|
|
255
|
+
|
|
141
256
|
try:
|
|
142
|
-
|
|
143
|
-
except
|
|
144
|
-
_handle_run_error(exc)
|
|
257
|
+
_execute_run(message, base_url=base_url)
|
|
258
|
+
except click.exceptions.Exit:
|
|
145
259
|
return # error already printed; skip next-steps
|
|
146
260
|
|
|
147
261
|
console.print(
|
|
@@ -216,7 +216,7 @@ def _estimate_cost(
|
|
|
216
216
|
context: dict | None = None,
|
|
217
217
|
tool_policy=None,
|
|
218
218
|
base_url: str | None = None,
|
|
219
|
-
) ->
|
|
219
|
+
) -> bool:
|
|
220
220
|
"""Show an estimated cost based on current pricing and config — no inference."""
|
|
221
221
|
from teardrop_cli.formatting import console, print_table
|
|
222
222
|
from teardrop_cli.pricing import estimate_run_cost
|
|
@@ -227,7 +227,7 @@ def _estimate_cost(
|
|
|
227
227
|
)
|
|
228
228
|
except Exception as exc: # noqa: BLE001
|
|
229
229
|
_handle_run_error(exc)
|
|
230
|
-
return
|
|
230
|
+
return False
|
|
231
231
|
|
|
232
232
|
from teardrop import format_usdc
|
|
233
233
|
|
|
@@ -247,6 +247,7 @@ def _estimate_cost(
|
|
|
247
247
|
]
|
|
248
248
|
print_table([("Item", {"style": "bold cyan"}), "Value"], rows, title="Cost Estimate")
|
|
249
249
|
console.print(f"[dim]{est.disclaimer}[/dim]")
|
|
250
|
+
return True
|
|
250
251
|
|
|
251
252
|
|
|
252
253
|
async def _stream(
|
|
@@ -341,23 +342,26 @@ async def _collect(
|
|
|
341
342
|
|
|
342
343
|
|
|
343
344
|
def _handle_run_error(exc: BaseException) -> None:
|
|
345
|
+
from teardrop import AuthenticationError, PaymentRequiredError, RateLimitError
|
|
346
|
+
|
|
344
347
|
from teardrop_cli.formatting import print_error
|
|
345
348
|
|
|
346
349
|
name = type(exc).__name__
|
|
347
350
|
msg = str(exc)
|
|
351
|
+
status_code = getattr(exc, "status_code", None)
|
|
348
352
|
|
|
349
|
-
if
|
|
353
|
+
if isinstance(exc, PaymentRequiredError) or status_code == 402:
|
|
350
354
|
print_error(
|
|
351
355
|
"Insufficient credit.",
|
|
352
|
-
hint="
|
|
356
|
+
hint="Check [bold]teardrop balance[/bold]. Add funds at: https://teardrop.dev/billing",
|
|
353
357
|
)
|
|
354
358
|
return
|
|
355
|
-
if
|
|
359
|
+
if isinstance(exc, RateLimitError) or status_code == 429:
|
|
356
360
|
retry = getattr(exc, "retry_after", None)
|
|
357
361
|
suffix = f" (retry after {retry}s)" if retry else ""
|
|
358
362
|
print_error(f"Rate limit exceeded{suffix}.")
|
|
359
363
|
return
|
|
360
|
-
if
|
|
364
|
+
if isinstance(exc, AuthenticationError) or status_code == 401:
|
|
361
365
|
print_error(
|
|
362
366
|
"Not authenticated.",
|
|
363
367
|
hint="Run `teardrop auth login` to sign in.",
|