teardrop-cli 0.1.1__tar.gz → 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.
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/PKG-INFO +53 -8
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/README.md +51 -6
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/docs/cli-json-schema.md +4 -2
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/docs/cli-reference.md +44 -2
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/pyproject.toml +2 -2
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/src/teardrop_cli/_fixtures.py +57 -3
- teardrop_cli-0.2.0/src/teardrop_cli/_templates.py +53 -0
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/src/teardrop_cli/cli.py +2 -0
- teardrop_cli-0.2.0/src/teardrop_cli/commands/agent_tools.py +90 -0
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/src/teardrop_cli/commands/auth.py +185 -39
- teardrop_cli-0.2.0/src/teardrop_cli/commands/balance.py +202 -0
- teardrop_cli-0.2.0/src/teardrop_cli/commands/chat.py +177 -0
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/src/teardrop_cli/commands/earnings.py +31 -13
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/src/teardrop_cli/commands/marketplace.py +50 -15
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/src/teardrop_cli/commands/models.py +4 -2
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/src/teardrop_cli/commands/quickstart.py +31 -59
- teardrop_cli-0.2.0/src/teardrop_cli/commands/run.py +373 -0
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/src/teardrop_cli/commands/tools.py +28 -0
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/src/teardrop_cli/config.py +156 -1
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/src/teardrop_cli/formatting.py +159 -35
- teardrop_cli-0.2.0/src/teardrop_cli/pricing.py +266 -0
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/tests/conftest.py +21 -1
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/tests/e2e/test_billing_e2e.py +13 -3
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/tests/test_auth.py +47 -11
- teardrop_cli-0.2.0/tests/test_billing.py +78 -0
- teardrop_cli-0.2.0/tests/test_chat.py +237 -0
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/tests/test_credential_priority.py +57 -0
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/tests/test_init_and_byok.py +65 -0
- teardrop_cli-0.2.0/tests/test_marketplace.py +159 -0
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/tests/test_models.py +4 -4
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/tests/test_quickstart.py +64 -18
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/tests/test_run.py +44 -0
- teardrop_cli-0.2.0/tests/test_token_expiry_fallback.py +123 -0
- teardrop_cli-0.1.1/src/teardrop_cli/_templates.py +0 -37
- teardrop_cli-0.1.1/src/teardrop_cli/commands/balance.py +0 -74
- teardrop_cli-0.1.1/src/teardrop_cli/commands/run.py +0 -189
- teardrop_cli-0.1.1/tests/test_billing.py +0 -39
- teardrop_cli-0.1.1/tests/test_marketplace.py +0 -80
- teardrop_cli-0.1.1/tests/test_token_expiry_fallback.py +0 -62
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/.github/workflows/publish.yml +0 -0
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/.github/workflows/test.yml +0 -0
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/.gitignore +0 -0
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/.vscode/settings.json +0 -0
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/LICENSE +0 -0
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/src/teardrop_cli/__init__.py +0 -0
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/src/teardrop_cli/_lazy.py +0 -0
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/src/teardrop_cli/commands/__init__.py +0 -0
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/src/teardrop_cli/commands/config_cmd.py +0 -0
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/src/teardrop_cli/commands/llm_config.py +0 -0
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/src/teardrop_cli/commands/mcp.py +0 -0
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/src/teardrop_cli/commands/usage.py +0 -0
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/tests/e2e/README.md +0 -0
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/tests/e2e/__init__.py +0 -0
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/tests/e2e/conftest.py +0 -0
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/tests/e2e/test_auth_e2e.py +0 -0
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/tests/e2e/test_marketplace_e2e.py +0 -0
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/tests/e2e/test_run_e2e.py +0 -0
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/tests/e2e/test_signup_e2e.py +0 -0
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/tests/e2e/test_siwe_login_e2e.py +0 -0
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/tests/smoke/__init__.py +0 -0
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/tests/smoke/conftest.py +0 -0
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/tests/smoke/test_config_persistence.py +0 -0
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/tests/smoke/test_keyring_integration.py +0 -0
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/tests/smoke/test_perf_lazygroup.py +0 -0
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/tests/smoke/test_siwe_signing.py +0 -0
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/tests/test_config_cmd.py +0 -0
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/tests/test_earnings.py +0 -0
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/tests/test_llm_config.py +0 -0
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/tests/test_mcp.py +0 -0
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/tests/test_signup.py +0 -0
- {teardrop_cli-0.1.1 → teardrop_cli-0.2.0}/tests/test_tools.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: teardrop-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
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.1.
|
|
48
|
+
Requires-Dist: teardrop-sdk>=0.1.8
|
|
49
49
|
Requires-Dist: tomli-w>=1.0
|
|
50
50
|
Requires-Dist: typer>=0.12
|
|
51
51
|
Provides-Extra: dev
|
|
@@ -118,14 +118,19 @@ teardrop run "Summarize the latest ETH gas trends"
|
|
|
118
118
|
| Goal | Command |
|
|
119
119
|
|------|---------|
|
|
120
120
|
| Create account & org | `teardrop auth signup` |
|
|
121
|
-
|
|
|
122
|
-
|
|
|
121
|
+
| Generate a new wallet & sign in | `teardrop auth login --siwe --generate-wallet [--save-key]` |
|
|
122
|
+
| Sign in with wallet (existing key) | `teardrop auth login --siwe --key-file wallet.key [--save-key]` |
|
|
123
123
|
| Email + password | `teardrop auth login --email you@example.com` |
|
|
124
124
|
| Pre-issued JWT | `teardrop auth login --token <jwt>` |
|
|
125
|
+
| Invite a team member | `teardrop auth invite colleague@example.com` |
|
|
125
126
|
| Show identity | `teardrop auth status` |
|
|
126
127
|
| Sign out | `teardrop auth logout` |
|
|
127
128
|
|
|
128
|
-
Private keys are never persisted by the CLI
|
|
129
|
+
Private keys are never persisted by the CLI unless you pass ``--save-key``.
|
|
130
|
+
When saved, the key is stored in your OS keyring (never in a config file)
|
|
131
|
+
and can be used for automatic re-authentication when the session token
|
|
132
|
+
expires. An encrypted keyring backend is required — plaintext fallbacks
|
|
133
|
+
are refused.
|
|
129
134
|
|
|
130
135
|
For machine-to-machine credentials, env-var precedence, and CI patterns, see [docs/cli-reference.md](docs/cli-reference.md#authentication).
|
|
131
136
|
|
|
@@ -181,6 +186,15 @@ teardrop run "Follow up" --thread <thread-id>
|
|
|
181
186
|
# Pass structured context
|
|
182
187
|
teardrop run "Process this order" --context '{"order_id":"ord_123"}'
|
|
183
188
|
|
|
189
|
+
# Exclude specific tools
|
|
190
|
+
teardrop run "Summarize news" --exclude platform/web_search
|
|
191
|
+
|
|
192
|
+
# Estimate cost based on current pricing & config (no run performed)
|
|
193
|
+
teardrop run "Analyze this data" --estimate-cost
|
|
194
|
+
|
|
195
|
+
# Apply a tool policy from a file
|
|
196
|
+
teardrop run "Execute workflow" --policy-file policy.json
|
|
197
|
+
|
|
184
198
|
# Machine-readable output
|
|
185
199
|
teardrop run "..." --json --no-stream
|
|
186
200
|
|
|
@@ -188,18 +202,49 @@ teardrop run "..." --json --no-stream
|
|
|
188
202
|
teardrop run "..." --json --with-ui
|
|
189
203
|
```
|
|
190
204
|
|
|
191
|
-
Streaming output renders Markdown live with inline tool calls. A token + cost summary prints at the end. By default, CLI output is optimized for scripting and automation (`emit_ui=false`); use `--with-ui` only if you need structured UI component data in the JSON output.
|
|
205
|
+
Streaming output renders Markdown live with inline tool calls and structured UI components. A token + cost summary prints at the end. By default, CLI output is optimized for scripting and automation (`emit_ui=false`); use `--with-ui` only if you need structured UI component data in the JSON output.
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## Chat with an Agent
|
|
192
210
|
|
|
193
|
-
|
|
211
|
+
A stateful chat mode that automatically continues the same thread across invocations:
|
|
194
212
|
|
|
195
213
|
```bash
|
|
196
|
-
teardrop
|
|
214
|
+
teardrop chat "What is the current ETH gas price?" # auto-creates a thread
|
|
215
|
+
teardrop chat "Follow up on that" # continues the same thread
|
|
216
|
+
teardrop chat "Start fresh" --new # starts a new conversation
|
|
217
|
+
teardrop chat "Specific thread" --thread thr_abc123 # explicit thread by id
|
|
218
|
+
teardrop chat "..." --json # machine-readable output
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
The active thread id is stored in `~/.teardrop/config.toml` and reused on your next `teardrop chat` call. The thread id is printed after every turn for copy/paste. All run flags (`--context`, `--exclude`, `--policy-file`, `--estimate-cost`, `--with-ui`, `--no-stream`) are supported.
|
|
222
|
+
|
|
223
|
+
Use `teardrop run` for one-shot, script-friendly calls — use `teardrop chat` for conversational interaction.
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
If a run fails on credit, check your balance and history:
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
teardrop balance # current credits
|
|
231
|
+
teardrop balance credit-history # past charges and top-ups
|
|
197
232
|
```
|
|
198
233
|
|
|
199
234
|
To add credits, visit [teardrop.dev](https://teardrop.dev).
|
|
200
235
|
|
|
201
236
|
---
|
|
202
237
|
|
|
238
|
+
## Agent Tools
|
|
239
|
+
|
|
240
|
+
List all tools visible to your agent (platform, marketplace subscriptions, and your own tools):
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
teardrop agent-tools list
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
203
248
|
## Configure Your LLM
|
|
204
249
|
|
|
205
250
|
One-shot bring-your-own-key wizard:
|
|
@@ -58,14 +58,19 @@ teardrop run "Summarize the latest ETH gas trends"
|
|
|
58
58
|
| Goal | Command |
|
|
59
59
|
|------|---------|
|
|
60
60
|
| Create account & org | `teardrop auth signup` |
|
|
61
|
-
|
|
|
62
|
-
|
|
|
61
|
+
| Generate a new wallet & sign in | `teardrop auth login --siwe --generate-wallet [--save-key]` |
|
|
62
|
+
| Sign in with wallet (existing key) | `teardrop auth login --siwe --key-file wallet.key [--save-key]` |
|
|
63
63
|
| Email + password | `teardrop auth login --email you@example.com` |
|
|
64
64
|
| Pre-issued JWT | `teardrop auth login --token <jwt>` |
|
|
65
|
+
| Invite a team member | `teardrop auth invite colleague@example.com` |
|
|
65
66
|
| Show identity | `teardrop auth status` |
|
|
66
67
|
| Sign out | `teardrop auth logout` |
|
|
67
68
|
|
|
68
|
-
Private keys are never persisted by the CLI
|
|
69
|
+
Private keys are never persisted by the CLI unless you pass ``--save-key``.
|
|
70
|
+
When saved, the key is stored in your OS keyring (never in a config file)
|
|
71
|
+
and can be used for automatic re-authentication when the session token
|
|
72
|
+
expires. An encrypted keyring backend is required — plaintext fallbacks
|
|
73
|
+
are refused.
|
|
69
74
|
|
|
70
75
|
For machine-to-machine credentials, env-var precedence, and CI patterns, see [docs/cli-reference.md](docs/cli-reference.md#authentication).
|
|
71
76
|
|
|
@@ -121,6 +126,15 @@ teardrop run "Follow up" --thread <thread-id>
|
|
|
121
126
|
# Pass structured context
|
|
122
127
|
teardrop run "Process this order" --context '{"order_id":"ord_123"}'
|
|
123
128
|
|
|
129
|
+
# Exclude specific tools
|
|
130
|
+
teardrop run "Summarize news" --exclude platform/web_search
|
|
131
|
+
|
|
132
|
+
# Estimate cost based on current pricing & config (no run performed)
|
|
133
|
+
teardrop run "Analyze this data" --estimate-cost
|
|
134
|
+
|
|
135
|
+
# Apply a tool policy from a file
|
|
136
|
+
teardrop run "Execute workflow" --policy-file policy.json
|
|
137
|
+
|
|
124
138
|
# Machine-readable output
|
|
125
139
|
teardrop run "..." --json --no-stream
|
|
126
140
|
|
|
@@ -128,18 +142,49 @@ teardrop run "..." --json --no-stream
|
|
|
128
142
|
teardrop run "..." --json --with-ui
|
|
129
143
|
```
|
|
130
144
|
|
|
131
|
-
Streaming output renders Markdown live with inline tool calls. A token + cost summary prints at the end. By default, CLI output is optimized for scripting and automation (`emit_ui=false`); use `--with-ui` only if you need structured UI component data in the JSON output.
|
|
145
|
+
Streaming output renders Markdown live with inline tool calls and structured UI components. A token + cost summary prints at the end. By default, CLI output is optimized for scripting and automation (`emit_ui=false`); use `--with-ui` only if you need structured UI component data in the JSON output.
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## Chat with an Agent
|
|
132
150
|
|
|
133
|
-
|
|
151
|
+
A stateful chat mode that automatically continues the same thread across invocations:
|
|
134
152
|
|
|
135
153
|
```bash
|
|
136
|
-
teardrop
|
|
154
|
+
teardrop chat "What is the current ETH gas price?" # auto-creates a thread
|
|
155
|
+
teardrop chat "Follow up on that" # continues the same thread
|
|
156
|
+
teardrop chat "Start fresh" --new # starts a new conversation
|
|
157
|
+
teardrop chat "Specific thread" --thread thr_abc123 # explicit thread by id
|
|
158
|
+
teardrop chat "..." --json # machine-readable output
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
The active thread id is stored in `~/.teardrop/config.toml` and reused on your next `teardrop chat` call. The thread id is printed after every turn for copy/paste. All run flags (`--context`, `--exclude`, `--policy-file`, `--estimate-cost`, `--with-ui`, `--no-stream`) are supported.
|
|
162
|
+
|
|
163
|
+
Use `teardrop run` for one-shot, script-friendly calls — use `teardrop chat` for conversational interaction.
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
If a run fails on credit, check your balance and history:
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
teardrop balance # current credits
|
|
171
|
+
teardrop balance credit-history # past charges and top-ups
|
|
137
172
|
```
|
|
138
173
|
|
|
139
174
|
To add credits, visit [teardrop.dev](https://teardrop.dev).
|
|
140
175
|
|
|
141
176
|
---
|
|
142
177
|
|
|
178
|
+
## Agent Tools
|
|
179
|
+
|
|
180
|
+
List all tools visible to your agent (platform, marketplace subscriptions, and your own tools):
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
teardrop agent-tools list
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
143
188
|
## Configure Your LLM
|
|
144
189
|
|
|
145
190
|
One-shot bring-your-own-key wizard:
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
# Teardrop CLI Agent Run JSON Schema
|
|
2
2
|
|
|
3
|
-
When running `teardrop run "..." --json
|
|
3
|
+
When running `teardrop run "..." --json` or `teardrop chat "..." --json`,
|
|
4
|
+
the output is a single JSON object (implies `--no-stream`).
|
|
4
5
|
|
|
5
6
|
## Schema Details
|
|
6
7
|
|
|
7
8
|
The JSON object contains the following fields:
|
|
8
9
|
|
|
9
10
|
- `text` (string): The final text response from the agent.
|
|
10
|
-
- `thread_id` (string | null): The ID of the thread used for the run. This can be used with the `--thread` flag in future runs to continue the conversation.
|
|
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.
|
|
11
12
|
|
|
12
13
|
## Example Output
|
|
13
14
|
|
|
@@ -22,4 +23,5 @@ The JSON object contains the following fields:
|
|
|
22
23
|
To capture specific fields, use `jq`:
|
|
23
24
|
```bash
|
|
24
25
|
teardrop run "ETH price" --json | jq -r .text
|
|
26
|
+
teardrop chat "ETH price" --json | jq -r .thread_id
|
|
25
27
|
```
|
|
@@ -8,6 +8,7 @@ This document covers every flag, env var, and subcommand. For the quick path, st
|
|
|
8
8
|
|
|
9
9
|
- [Authentication](#authentication)
|
|
10
10
|
- [Running Agents](#running-agents)
|
|
11
|
+
- [Chat Sessions](#chat-sessions)
|
|
11
12
|
- [Billing & Credits](#billing--credits)
|
|
12
13
|
- [Tool Management](#tool-management)
|
|
13
14
|
- [Marketplace](#marketplace)
|
|
@@ -90,6 +91,34 @@ Streaming output renders Markdown live with inline tool calls. A token + cost su
|
|
|
90
91
|
|
|
91
92
|
---
|
|
92
93
|
|
|
94
|
+
## Chat Sessions
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
teardrop chat "What is the current ETH gas price?" # auto-creates a thread
|
|
98
|
+
teardrop chat "Follow up on that" # continues the same thread
|
|
99
|
+
teardrop chat "Start fresh" --new # starts a new conversation
|
|
100
|
+
teardrop chat "Specific thread" --thread thr_abc123 # explicit thread by id
|
|
101
|
+
teardrop chat "..." --json # machine-readable output
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
The active thread id is stored in `~/.teardrop/config.toml` (`chat.active_thread_id`).
|
|
105
|
+
The file is chmod'd 600 and the thread id is printed to stderr after every turn.
|
|
106
|
+
|
|
107
|
+
**Flag precedence** (highest first):
|
|
108
|
+
1. `--new` — clears the stored thread; a fresh one is created server-side.
|
|
109
|
+
2. `--thread <id>` — overrides any stored thread.
|
|
110
|
+
3. **Stored thread** — read from config if neither `--new` nor `--thread` is given.
|
|
111
|
+
4. **Server‑minted** — if none of the above resolve to a value, the server assigns one and it is persisted automatically.
|
|
112
|
+
|
|
113
|
+
Chat supports all the same options as `run` (`--context`, `--exclude`, `--policy-file`,
|
|
114
|
+
`--estimate-cost`, `--with-ui`, `--no-stream`, `--base-url`).
|
|
115
|
+
|
|
116
|
+
**Logout clears state**: `teardrop auth logout` removes both credentials **and**
|
|
117
|
+
the active thread id from the config file. The next `teardrop chat` after logout
|
|
118
|
+
will start a fresh thread.
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
93
122
|
## Billing & Credits
|
|
94
123
|
|
|
95
124
|
```bash
|
|
@@ -134,17 +163,30 @@ Example `tool.json`:
|
|
|
134
163
|
{
|
|
135
164
|
"name": "get_weather",
|
|
136
165
|
"description": "Fetch current weather conditions for a given city.",
|
|
137
|
-
"webhook_url": "https://api.example.com/webhooks/teardrop",
|
|
138
166
|
"input_schema": {
|
|
139
167
|
"type": "object",
|
|
140
168
|
"properties": {
|
|
141
169
|
"city": { "type": "string", "description": "City name, e.g. 'London'" }
|
|
142
170
|
},
|
|
143
|
-
"required": ["city"]
|
|
171
|
+
"required": ["city"],
|
|
172
|
+
"additionalProperties": false
|
|
173
|
+
},
|
|
174
|
+
"output_schema": {
|
|
175
|
+
"type": "object",
|
|
176
|
+
"properties": {
|
|
177
|
+
"result": { "type": "string", "description": "Weather summary for the requested city." }
|
|
178
|
+
},
|
|
179
|
+
"required": ["result"],
|
|
180
|
+
"additionalProperties": true
|
|
144
181
|
},
|
|
182
|
+
"webhook_url": "https://api.example.com/webhooks/teardrop",
|
|
183
|
+
"webhook_method": "GET",
|
|
184
|
+
"auth_header_name": null,
|
|
185
|
+
"auth_header_value": null,
|
|
145
186
|
"timeout_seconds": 10,
|
|
146
187
|
"publish_as_mcp": true,
|
|
147
188
|
"marketplace_description": "Real-time weather data for any city worldwide.",
|
|
189
|
+
"category": "data",
|
|
148
190
|
"base_price_usdc": 5000
|
|
149
191
|
}
|
|
150
192
|
```
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "teardrop-cli"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.2.0"
|
|
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.1.
|
|
27
|
+
"teardrop-sdk>=0.1.8",
|
|
28
28
|
"typer>=0.12",
|
|
29
29
|
"rich>=13.0",
|
|
30
30
|
"platformdirs>=4.0",
|
|
@@ -176,9 +176,9 @@ def make_benchmarks_response(models: list[dict] | None = None) -> MagicMock:
|
|
|
176
176
|
"supports_streaming": True,
|
|
177
177
|
"quality_tier": 2,
|
|
178
178
|
"pricing": {
|
|
179
|
-
"tokens_in_cost_per_1k": 0
|
|
180
|
-
"tokens_out_cost_per_1k": 0
|
|
181
|
-
"tool_call_cost":
|
|
179
|
+
"tokens_in_cost_per_1k": 1_250.0,
|
|
180
|
+
"tokens_out_cost_per_1k": 6_250.0,
|
|
181
|
+
"tool_call_cost": 1_000.0,
|
|
182
182
|
},
|
|
183
183
|
"benchmarks": {
|
|
184
184
|
"total_runs_7d": 1250,
|
|
@@ -195,3 +195,57 @@ def make_benchmarks_response(models: list[dict] | None = None) -> MagicMock:
|
|
|
195
195
|
obj.models = models
|
|
196
196
|
obj.updated_at = data["updated_at"]
|
|
197
197
|
return obj
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def make_pricing_response(
|
|
201
|
+
base_cost_usdc: int = 500,
|
|
202
|
+
tools: list[dict] | None = None,
|
|
203
|
+
) -> MagicMock:
|
|
204
|
+
"""Return a minimal BillingPricingResponse-like mock."""
|
|
205
|
+
if tools is None:
|
|
206
|
+
tools = [
|
|
207
|
+
{
|
|
208
|
+
"tool_name": "acme/weather",
|
|
209
|
+
"price_usdc": 5000,
|
|
210
|
+
"description": "Get the weather",
|
|
211
|
+
}
|
|
212
|
+
]
|
|
213
|
+
data = {"tools": tools, "base_cost_usdc": base_cost_usdc, "updated_at": "2026-04-16T12:00:00Z"}
|
|
214
|
+
obj = MagicMock()
|
|
215
|
+
obj.model_dump = lambda: dict(data)
|
|
216
|
+
obj.tools = tools
|
|
217
|
+
obj.base_cost_usdc = base_cost_usdc
|
|
218
|
+
obj.updated_at = data["updated_at"]
|
|
219
|
+
return obj
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def make_credit_history_entries(
|
|
223
|
+
count: int = 3,
|
|
224
|
+
) -> list[MagicMock]:
|
|
225
|
+
"""Return a list of CreditHistoryEntry-like mocks.
|
|
226
|
+
|
|
227
|
+
Each mock has a ``model_dump`` method so the CLI can normalise it, matching
|
|
228
|
+
the real SDK's ``list[CreditHistoryEntry]`` return type.
|
|
229
|
+
"""
|
|
230
|
+
entries = []
|
|
231
|
+
samples = [
|
|
232
|
+
{"reason": "Subscription fee — acme/weather", "amount_usdc": 5000, "operation": "debit"},
|
|
233
|
+
{"reason": "Top-up", "amount_usdc": 50_000_000, "operation": "topup"},
|
|
234
|
+
{"reason": "Agent run — code review", "amount_usdc": 1250, "operation": "debit"},
|
|
235
|
+
]
|
|
236
|
+
for i in range(count):
|
|
237
|
+
base = samples[i % len(samples)]
|
|
238
|
+
data = {
|
|
239
|
+
"id": f"ch_{i}",
|
|
240
|
+
"amount_usdc": base["amount_usdc"],
|
|
241
|
+
"operation": base["operation"],
|
|
242
|
+
"balance_usdc_after": 100_000_000 - base["amount_usdc"] * (i + 1),
|
|
243
|
+
"reason": base["reason"],
|
|
244
|
+
"created_at": f"2026-06-{10 - i:02d}T12:00:00Z",
|
|
245
|
+
}
|
|
246
|
+
obj = MagicMock()
|
|
247
|
+
obj.model_dump = lambda d=data: dict(d)
|
|
248
|
+
for k, v in data.items():
|
|
249
|
+
setattr(obj, k, v)
|
|
250
|
+
entries.append(obj)
|
|
251
|
+
return entries
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"""In-package templates for ``teardrop tools init``."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
# Complete starter template matching CreateOrgToolRequest schema.
|
|
6
|
+
# All fields are explicit --- nullable fields use None so they appear as
|
|
7
|
+
# ``null`` in the output JSON and users discover them early.
|
|
8
|
+
_BASE_TEMPLATE = {
|
|
9
|
+
"name": "{name}",
|
|
10
|
+
"description": "Short one-line summary of what this tool does.",
|
|
11
|
+
"input_schema": {
|
|
12
|
+
"type": "object",
|
|
13
|
+
"properties": {
|
|
14
|
+
"query": {
|
|
15
|
+
"type": "string",
|
|
16
|
+
"description": "Example input field. Replace with your real schema.",
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"required": ["query"],
|
|
20
|
+
"additionalProperties": False,
|
|
21
|
+
},
|
|
22
|
+
"output_schema": {
|
|
23
|
+
"type": "object",
|
|
24
|
+
"properties": {
|
|
25
|
+
"result": {
|
|
26
|
+
"type": "string",
|
|
27
|
+
"description": "Example output field. Replace with your real schema.",
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"required": ["result"],
|
|
31
|
+
"additionalProperties": True,
|
|
32
|
+
},
|
|
33
|
+
"webhook_url": "https://example.com/your-webhook-endpoint",
|
|
34
|
+
"webhook_method": "GET",
|
|
35
|
+
"auth_header_name": None,
|
|
36
|
+
"auth_header_value": None,
|
|
37
|
+
"timeout_seconds": 10,
|
|
38
|
+
"publish_as_mcp": False,
|
|
39
|
+
"marketplace_description": None,
|
|
40
|
+
"category": "",
|
|
41
|
+
"base_price_usdc": 0,
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def render_tool_template(name: str, *, with_marketplace: bool = False) -> dict:
|
|
46
|
+
"""Return a dict suitable for ``json.dumps`` describing a starter tool."""
|
|
47
|
+
data = {**_BASE_TEMPLATE, "name": name}
|
|
48
|
+
if with_marketplace:
|
|
49
|
+
data["publish_as_mcp"] = True
|
|
50
|
+
data["marketplace_description"] = (
|
|
51
|
+
"One-line marketplace pitch (max 200 characters)."
|
|
52
|
+
)
|
|
53
|
+
return data
|
|
@@ -18,12 +18,14 @@ from teardrop_cli._lazy import LazyGroup
|
|
|
18
18
|
cls=LazyGroup,
|
|
19
19
|
lazy_subcommands={
|
|
20
20
|
"auth": "teardrop_cli.commands.auth:app",
|
|
21
|
+
"chat": "teardrop_cli.commands.chat:app",
|
|
21
22
|
"init": "teardrop_cli.commands.config_cmd:init_app",
|
|
22
23
|
"quickstart": "teardrop_cli.commands.quickstart:app",
|
|
23
24
|
"config": "teardrop_cli.commands.config_cmd:app",
|
|
24
25
|
"run": "teardrop_cli.commands.run:app",
|
|
25
26
|
"balance": "teardrop_cli.commands.balance:app",
|
|
26
27
|
"usage": "teardrop_cli.commands.usage:app",
|
|
28
|
+
"agent-tools": "teardrop_cli.commands.agent_tools:app",
|
|
27
29
|
"marketplace": "teardrop_cli.commands.marketplace:app",
|
|
28
30
|
"tools": "teardrop_cli.commands.tools:app",
|
|
29
31
|
"earnings": "teardrop_cli.commands.earnings:app",
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"""``teardrop agent-tools`` — list tools visible to the agent."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import asyncio
|
|
6
|
+
|
|
7
|
+
import click
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@click.group(name="agent-tools", help="Tools visible to your agent.")
|
|
11
|
+
def app() -> None:
|
|
12
|
+
"""Query tools available to the agent (platform + subscribed + custom)."""
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@app.command(name="list", help="List all tools visible to your agent.")
|
|
16
|
+
@click.option("--json", "as_json", is_flag=True, default=False, help="Output as JSON.")
|
|
17
|
+
@click.option("--base-url", "base_url", default=None, hidden=True)
|
|
18
|
+
def _list(as_json: bool, base_url: str | None) -> None:
|
|
19
|
+
from teardrop_cli import config
|
|
20
|
+
from teardrop_cli.formatting import (
|
|
21
|
+
data_console,
|
|
22
|
+
handle_token_expiry,
|
|
23
|
+
print_json,
|
|
24
|
+
print_table,
|
|
25
|
+
spinner,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
async def _fetch_once(client):
|
|
29
|
+
try:
|
|
30
|
+
return await client.get_agent_tools()
|
|
31
|
+
finally:
|
|
32
|
+
await client.close()
|
|
33
|
+
|
|
34
|
+
def _call_once():
|
|
35
|
+
client = config.get_client(base_url)
|
|
36
|
+
return asyncio.run(_fetch_once(client))
|
|
37
|
+
|
|
38
|
+
try:
|
|
39
|
+
with spinner("Fetching agent tools…"):
|
|
40
|
+
tools = _call_once()
|
|
41
|
+
except Exception as exc:
|
|
42
|
+
action = asyncio.run(
|
|
43
|
+
handle_token_expiry(
|
|
44
|
+
exc,
|
|
45
|
+
base_url,
|
|
46
|
+
allow_prompt_login=not as_json,
|
|
47
|
+
)
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
if action == "retry":
|
|
51
|
+
with spinner("Fetching agent tools…"):
|
|
52
|
+
tools = _call_once()
|
|
53
|
+
elif action == "prompt_login":
|
|
54
|
+
from teardrop_cli.commands.auth import interactive_reauthenticate
|
|
55
|
+
|
|
56
|
+
if not interactive_reauthenticate(base_url=base_url):
|
|
57
|
+
raise click.exceptions.Exit(1) from None
|
|
58
|
+
with spinner("Fetching agent tools…"):
|
|
59
|
+
tools = _call_once()
|
|
60
|
+
elif action == "fail":
|
|
61
|
+
raise click.exceptions.Exit(1) from None
|
|
62
|
+
else:
|
|
63
|
+
raise
|
|
64
|
+
|
|
65
|
+
items = [t.model_dump() if hasattr(t, "model_dump") else dict(t) for t in tools]
|
|
66
|
+
|
|
67
|
+
if as_json:
|
|
68
|
+
print_json(items)
|
|
69
|
+
return
|
|
70
|
+
|
|
71
|
+
if not items:
|
|
72
|
+
data_console.print("[dim]No agent tools found.[/dim]")
|
|
73
|
+
return
|
|
74
|
+
|
|
75
|
+
rows = []
|
|
76
|
+
for t in items:
|
|
77
|
+
name = t.get("name", "—")
|
|
78
|
+
source = t.get("source", "—")
|
|
79
|
+
access = t.get("access_mode", "—")
|
|
80
|
+
rows.append([name, source, access])
|
|
81
|
+
|
|
82
|
+
print_table(
|
|
83
|
+
[
|
|
84
|
+
("Name", {"style": "bold cyan"}),
|
|
85
|
+
("Source", {"style": "bold"}),
|
|
86
|
+
("Access", {"style": "bold"}),
|
|
87
|
+
],
|
|
88
|
+
rows,
|
|
89
|
+
title="Agent Tools",
|
|
90
|
+
)
|