@clawpump/claw-agent 0.1.3 → 0.1.5
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.
- package/agent/cli.py +135 -2
- package/agent/hermes_cli/clawpump_cli.py +3 -3
- package/agent/hermes_cli/commands.py +2 -1
- package/agent/hermes_cli/distribution.py +227 -0
- package/agent/optional-mcps/clawpump/manifest.yaml +13 -5
- package/agent/optional-mcps/clawpump-stdio/manifest.yaml +12 -4
- package/agent/skills/clawpump/SKILL.md +53 -4
- package/agent/uv.lock +8 -12
- package/package.json +1 -1
package/agent/cli.py
CHANGED
|
@@ -3347,6 +3347,9 @@ class HermesCLI:
|
|
|
3347
3347
|
# _handle_update_command() so the relaunch happens on the main thread,
|
|
3348
3348
|
# not the background process_loop thread.
|
|
3349
3349
|
self._pending_relaunch: list[str] | None = None
|
|
3350
|
+
# ClawPump: queued UsePod ("Pod") provider switch, applied post-turn by
|
|
3351
|
+
# _activate_pending_pod() after usepod_provision auto-applies its token.
|
|
3352
|
+
self._pending_pod_activation: dict | None = None
|
|
3350
3353
|
self._last_ctrl_c_time = 0
|
|
3351
3354
|
self._clarify_state = None
|
|
3352
3355
|
self._clarify_freetext = False
|
|
@@ -5141,7 +5144,10 @@ class HermesCLI:
|
|
|
5141
5144
|
skip_memory=self.ignore_rules,
|
|
5142
5145
|
tool_progress_callback=self._on_tool_progress,
|
|
5143
5146
|
tool_start_callback=self._on_tool_start if self._inline_diffs_enabled else None,
|
|
5144
|
-
|
|
5147
|
+
# Always wired: _on_tool_complete also drives ClawPump's UsePod
|
|
5148
|
+
# ("Pod") auto-apply, which must not depend on the inline-diffs
|
|
5149
|
+
# display toggle. Diff rendering inside it is still gated on it.
|
|
5150
|
+
tool_complete_callback=self._on_tool_complete,
|
|
5145
5151
|
stream_delta_callback=self._stream_delta if self.streaming_enabled else None,
|
|
5146
5152
|
tool_gen_callback=self._on_tool_gen_start if self.streaming_enabled else None,
|
|
5147
5153
|
)
|
|
@@ -7819,6 +7825,23 @@ class HermesCLI:
|
|
|
7819
7825
|
self._close_model_picker()
|
|
7820
7826
|
return
|
|
7821
7827
|
provider_data = providers[selected]
|
|
7828
|
+
# Distribution overlay (e.g. ClawPump): promoted providers that need
|
|
7829
|
+
# a guided setup (UsePod "Pod" — a plugin api-key provider that can't
|
|
7830
|
+
# be quick-switched) route to a step-by-step setup flow instead of a
|
|
7831
|
+
# failing switch. Hand the agent the configure instruction.
|
|
7832
|
+
if provider_data.get("clawpump_setup"):
|
|
7833
|
+
self._close_model_picker()
|
|
7834
|
+
try:
|
|
7835
|
+
from hermes_cli.distribution import usepod_setup_request_message
|
|
7836
|
+
_msg = usepod_setup_request_message()
|
|
7837
|
+
except Exception:
|
|
7838
|
+
_msg = (
|
|
7839
|
+
"Help me set up the Pod (UsePod) provider step by step and "
|
|
7840
|
+
"fund it from my ClawPump wallet."
|
|
7841
|
+
)
|
|
7842
|
+
if hasattr(self, "_pending_input"):
|
|
7843
|
+
self._pending_input.put(_msg)
|
|
7844
|
+
return
|
|
7822
7845
|
# Use the curated model list from list_authenticated_providers()
|
|
7823
7846
|
# (same lists as `hermes model` and gateway pickers).
|
|
7824
7847
|
# Only fall back to the live provider catalog when the curated
|
|
@@ -7933,6 +7956,15 @@ class HermesCLI:
|
|
|
7933
7956
|
except Exception:
|
|
7934
7957
|
providers = []
|
|
7935
7958
|
|
|
7959
|
+
# Distribution overlay (e.g. ClawPump): pin promoted providers
|
|
7960
|
+
# (UsePod "Pod") so they're discoverable. Selecting one routes to a
|
|
7961
|
+
# guided setup (see _handle_model_picker_selection). No-op on vanilla.
|
|
7962
|
+
try:
|
|
7963
|
+
from hermes_cli.distribution import promote_picker_providers
|
|
7964
|
+
providers = promote_picker_providers(ctx, providers)
|
|
7965
|
+
except Exception:
|
|
7966
|
+
pass
|
|
7967
|
+
|
|
7936
7968
|
if not providers:
|
|
7937
7969
|
_cprint(" No authenticated providers found.")
|
|
7938
7970
|
_cprint("")
|
|
@@ -11076,7 +11108,41 @@ class HermesCLI:
|
|
|
11076
11108
|
logger.debug("Edit snapshot capture failed for %s", function_name, exc_info=True)
|
|
11077
11109
|
|
|
11078
11110
|
def _on_tool_complete(self, tool_call_id: str, function_name: str, function_args: dict, function_result: str):
|
|
11079
|
-
"""Render file edits with inline diff after write-capable tools complete.
|
|
11111
|
+
"""Render file edits with inline diff after write-capable tools complete.
|
|
11112
|
+
|
|
11113
|
+
Also intercepts the ClawPump ``usepod_provision`` MCP tool to auto-apply
|
|
11114
|
+
the returned Pod token (downstream overlay; no-op on vanilla Hermes).
|
|
11115
|
+
Runs mid-turn in the agent thread, so it only persists credentials/config
|
|
11116
|
+
and queues the live provider switch — the switch itself happens at the
|
|
11117
|
+
post-turn boundary (``_activate_pending_pod``) to avoid mutating the
|
|
11118
|
+
agent while it is still executing tools.
|
|
11119
|
+
"""
|
|
11120
|
+
# ClawPump: auto-apply a freshly provisioned UsePod ("Pod") token.
|
|
11121
|
+
try:
|
|
11122
|
+
from hermes_cli import distribution as _dist
|
|
11123
|
+
|
|
11124
|
+
_tok = _dist.usepod_provision_token(function_name, function_result)
|
|
11125
|
+
if _tok:
|
|
11126
|
+
api_token, deposit_code = _tok
|
|
11127
|
+
if _dist.persist_usepod_credentials(api_token, deposit_code):
|
|
11128
|
+
model, provider, base_url = _dist.usepod_pod_switch_target(
|
|
11129
|
+
api_token, current_model=getattr(self, "model", "") or ""
|
|
11130
|
+
)
|
|
11131
|
+
# Queue the switch; config.yaml is persisted in
|
|
11132
|
+
# _activate_pending_pod once we're on the main thread (so a
|
|
11133
|
+
# failed/invalid token never strands config on Pod).
|
|
11134
|
+
self._pending_pod_activation = {
|
|
11135
|
+
"model": model,
|
|
11136
|
+
"provider": provider,
|
|
11137
|
+
"base_url": base_url,
|
|
11138
|
+
"api_key": api_token,
|
|
11139
|
+
}
|
|
11140
|
+
_cprint(f" ✓ Pod token applied — switching to Pod ({model}) after this turn.")
|
|
11141
|
+
except Exception:
|
|
11142
|
+
logger.debug("UsePod auto-apply failed", exc_info=True)
|
|
11143
|
+
|
|
11144
|
+
if not getattr(self, "_inline_diffs_enabled", True):
|
|
11145
|
+
return
|
|
11080
11146
|
snapshot = self._pending_edit_snapshots.pop(tool_call_id, None)
|
|
11081
11147
|
try:
|
|
11082
11148
|
from agent.display import render_edit_diff_with_delta
|
|
@@ -11091,6 +11157,68 @@ class HermesCLI:
|
|
|
11091
11157
|
except Exception:
|
|
11092
11158
|
logger.debug("Edit diff preview failed for %s", function_name, exc_info=True)
|
|
11093
11159
|
|
|
11160
|
+
def _activate_pending_pod(self) -> None:
|
|
11161
|
+
"""Apply a queued UsePod ("Pod") provider switch at a post-turn boundary.
|
|
11162
|
+
|
|
11163
|
+
Mirrors ``_apply_model_switch_result``: updates the live agent + CLI
|
|
11164
|
+
provider state so the next turn runs on Pod, with no relaunch and no
|
|
11165
|
+
manual ``claw model`` paste. Set by ``_on_tool_complete`` when
|
|
11166
|
+
``usepod_provision`` returns a token. No-op when nothing is queued.
|
|
11167
|
+
"""
|
|
11168
|
+
pending = getattr(self, "_pending_pod_activation", None)
|
|
11169
|
+
if not pending:
|
|
11170
|
+
return
|
|
11171
|
+
self._pending_pod_activation = None
|
|
11172
|
+
try:
|
|
11173
|
+
old_model = self.model
|
|
11174
|
+
model = pending["model"]
|
|
11175
|
+
provider = pending["provider"]
|
|
11176
|
+
base_url = pending.get("base_url") or ""
|
|
11177
|
+
api_key = pending.get("api_key") or ""
|
|
11178
|
+
|
|
11179
|
+
self.model = model
|
|
11180
|
+
self.provider = provider
|
|
11181
|
+
self.requested_provider = provider
|
|
11182
|
+
self._explicit_api_key = api_key
|
|
11183
|
+
self._explicit_base_url = base_url
|
|
11184
|
+
if api_key:
|
|
11185
|
+
self.api_key = api_key
|
|
11186
|
+
if base_url:
|
|
11187
|
+
self.base_url = base_url
|
|
11188
|
+
|
|
11189
|
+
if self.agent is not None:
|
|
11190
|
+
try:
|
|
11191
|
+
self.agent.switch_model(
|
|
11192
|
+
new_model=model,
|
|
11193
|
+
new_provider=provider,
|
|
11194
|
+
api_key=api_key,
|
|
11195
|
+
base_url=base_url,
|
|
11196
|
+
)
|
|
11197
|
+
# switch_model derives api_mode from provider+base_url when
|
|
11198
|
+
# not passed; sync the CLI's copy so a later re-resolution
|
|
11199
|
+
# (or relaunch) doesn't carry the old provider's wire mode.
|
|
11200
|
+
self.api_mode = getattr(self.agent, "api_mode", self.api_mode)
|
|
11201
|
+
except Exception as exc:
|
|
11202
|
+
_cprint(f" ⚠ Pod switch applied to next session ({exc}).")
|
|
11203
|
+
|
|
11204
|
+
# Persist the provider switch (model.default + model.provider) so a
|
|
11205
|
+
# later relaunch boots onto Pod. base_url is intentionally NOT
|
|
11206
|
+
# persisted — it's re-derived from USEPOD_API_KEY at startup.
|
|
11207
|
+
try:
|
|
11208
|
+
save_config_value("model.default", model)
|
|
11209
|
+
save_config_value("model.provider", provider)
|
|
11210
|
+
except Exception:
|
|
11211
|
+
logger.debug("Pod config persist failed", exc_info=True)
|
|
11212
|
+
|
|
11213
|
+
self._pending_model_switch_note = (
|
|
11214
|
+
f"[Note: the session was just switched from {old_model} to {model} "
|
|
11215
|
+
f"running on your UsePod Pod (paid in USDC from your ClawPump "
|
|
11216
|
+
f"wallet). Adjust your self-identification accordingly.]"
|
|
11217
|
+
)
|
|
11218
|
+
_cprint(f" ✓ Now running on Pod: {model}")
|
|
11219
|
+
except Exception:
|
|
11220
|
+
logger.debug("Pod activation failed", exc_info=True)
|
|
11221
|
+
|
|
11094
11222
|
# ====================================================================
|
|
11095
11223
|
# Voice mode methods
|
|
11096
11224
|
# ====================================================================
|
|
@@ -12403,6 +12531,11 @@ class HermesCLI:
|
|
|
12403
12531
|
# Update history with full conversation
|
|
12404
12532
|
self.conversation_history = result.get("messages", self.conversation_history) if result else self.conversation_history
|
|
12405
12533
|
|
|
12534
|
+
# ClawPump: apply a queued UsePod ("Pod") provider switch now that
|
|
12535
|
+
# the agent thread has joined (safe post-turn boundary). No-op unless
|
|
12536
|
+
# usepod_provision auto-applied a token during this turn.
|
|
12537
|
+
self._activate_pending_pod()
|
|
12538
|
+
|
|
12406
12539
|
# If auto-compression fired mid-turn, the agent created a new
|
|
12407
12540
|
# continuation session and mutated self.agent.session_id. Sync
|
|
12408
12541
|
# the CLI's session_id so /status, /resume, title generation,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""``hermes clawpump`` — one-command install/auth for the ClawPump MCP.
|
|
2
2
|
|
|
3
|
-
ClawPump ships its full feature set (
|
|
3
|
+
ClawPump ships its full feature set (133 tools) as an MCP server, bundled in
|
|
4
4
|
the Hermes catalog as two entries:
|
|
5
5
|
|
|
6
6
|
- ``clawpump`` remote OAuth over Streamable HTTP (browser, paste cpk_*)
|
|
@@ -59,7 +59,7 @@ def _cmd_setup(args) -> int:
|
|
|
59
59
|
print()
|
|
60
60
|
print(color(" ClawPump setup", Colors.GREEN + Colors.BOLD))
|
|
61
61
|
print(color(" ──────────────", Colors.GREEN))
|
|
62
|
-
print(" ClawPump's
|
|
62
|
+
print(" ClawPump's 133 tools (agents, trading, perps, DCA, lending,")
|
|
63
63
|
print(" token launch, marketplace, predictions, gift cards, agent")
|
|
64
64
|
print(" mail, intelligence) come in through an MCP server. Two ways")
|
|
65
65
|
print(" to connect:")
|
|
@@ -221,7 +221,7 @@ def add_parser(subparsers) -> None:
|
|
|
221
221
|
help="ClawPump (Solana token launch, trading, perps, DeFi) via MCP",
|
|
222
222
|
description=(
|
|
223
223
|
"Install and authenticate the ClawPump MCP server, then manage which "
|
|
224
|
-
"of its
|
|
224
|
+
"of its 133 tools are enabled. Subcommands: setup (default: status), "
|
|
225
225
|
"login, status, tools."
|
|
226
226
|
),
|
|
227
227
|
)
|
|
@@ -123,7 +123,8 @@ COMMAND_REGISTRY: list[CommandDef] = [
|
|
|
123
123
|
# Configuration
|
|
124
124
|
CommandDef("config", "Show current configuration", "Configuration",
|
|
125
125
|
cli_only=True),
|
|
126
|
-
CommandDef("model", "Switch model for this session", "Configuration",
|
|
126
|
+
CommandDef("model", "Switch model or provider for this session", "Configuration",
|
|
127
|
+
aliases=("provider",),
|
|
127
128
|
args_hint="[model] [--provider name] [--global] [--refresh]"),
|
|
128
129
|
CommandDef("codex-runtime", "Toggle codex app-server runtime for OpenAI/Codex models",
|
|
129
130
|
"Configuration", aliases=("codex_runtime",),
|
|
@@ -228,3 +228,230 @@ def try_self_update(project_root: Any) -> bool:
|
|
|
228
228
|
sys.exit(1)
|
|
229
229
|
print("✓ ClawPump agent updated. Restart your session with `claw`.")
|
|
230
230
|
return True
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
# ── Model picker: promoted providers ──────────────────────────────────────
|
|
234
|
+
# ClawPump pins UsePod ("Pod") to the top of the /model + /provider picker so
|
|
235
|
+
# users can discover it. UsePod is a plugin api-key provider, so it can't be
|
|
236
|
+
# quick-switched like a configured provider — selecting it instead triggers a
|
|
237
|
+
# guided setup (the picker handler keys off the ``clawpump_setup`` flag and
|
|
238
|
+
# hands the agent a "configure Pod" instruction). No-op on vanilla Hermes.
|
|
239
|
+
PICKER_PROMOTED_PROVIDER = "usepod"
|
|
240
|
+
# Honest, defensible value-prop (no fabricated savings %). Swap in a real,
|
|
241
|
+
# backed figure here if/when there is one.
|
|
242
|
+
PICKER_PROMOTED_TAGLINE = "pay-per-use USDC from your ClawPump wallet"
|
|
243
|
+
PICKER_PROMOTED_DISPLAY = "Pod"
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
def promote_picker_providers(ctx: Any, providers: Any) -> Any:
|
|
247
|
+
"""Pin the promoted provider (UsePod) to the top of the model picker.
|
|
248
|
+
|
|
249
|
+
Adds a Pod row (seeded with the provider's fallback models) tagged with
|
|
250
|
+
``clawpump_setup`` so the picker routes its selection to the guided setup
|
|
251
|
+
flow rather than a (failing) quick-switch. Idempotent; returns the list
|
|
252
|
+
unchanged on any error so the picker never breaks.
|
|
253
|
+
"""
|
|
254
|
+
try:
|
|
255
|
+
rows = list(providers or [])
|
|
256
|
+
except Exception:
|
|
257
|
+
return providers
|
|
258
|
+
|
|
259
|
+
slug = PICKER_PROMOTED_PROVIDER
|
|
260
|
+
existing = next(
|
|
261
|
+
(r for r in rows if isinstance(r, dict) and r.get("slug") == slug), None
|
|
262
|
+
)
|
|
263
|
+
others = [
|
|
264
|
+
r for r in rows if not (isinstance(r, dict) and r.get("slug") == slug)
|
|
265
|
+
]
|
|
266
|
+
|
|
267
|
+
if existing is None:
|
|
268
|
+
models = []
|
|
269
|
+
try:
|
|
270
|
+
from providers import get_provider_profile
|
|
271
|
+
|
|
272
|
+
pp = get_provider_profile(slug)
|
|
273
|
+
models = list(getattr(pp, "fallback_models", ()) or [])
|
|
274
|
+
except Exception:
|
|
275
|
+
models = []
|
|
276
|
+
existing = {
|
|
277
|
+
"slug": slug,
|
|
278
|
+
"name": PICKER_PROMOTED_DISPLAY,
|
|
279
|
+
"models": models,
|
|
280
|
+
"total_models": len(models),
|
|
281
|
+
"is_current": False,
|
|
282
|
+
"authenticated": False,
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
# Selecting Pod always routes to setup (it can't be quick-switched).
|
|
286
|
+
existing["clawpump_setup"] = True
|
|
287
|
+
name = str(existing.get("name") or PICKER_PROMOTED_DISPLAY)
|
|
288
|
+
if PICKER_PROMOTED_TAGLINE not in name:
|
|
289
|
+
existing["name"] = f"{name} · {PICKER_PROMOTED_TAGLINE}"
|
|
290
|
+
|
|
291
|
+
return [existing] + others
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
def usepod_setup_request_message() -> str:
|
|
295
|
+
"""The instruction enqueued to the agent when a user picks Pod in the
|
|
296
|
+
picker but it isn't configured — drives the step-by-step setup + funding."""
|
|
297
|
+
return (
|
|
298
|
+
"I picked Pod (UsePod) in the model picker but it isn't set up yet. "
|
|
299
|
+
"Walk me through configuring it: (1) ask how much USDC to put on the pod "
|
|
300
|
+
"(e.g. 5) — optionally check get_balance first; (2) ask which ClawPump "
|
|
301
|
+
"agent wallet should fund it — call list_agents and let me pick one by "
|
|
302
|
+
"agent_id; (3) once I approve the amount, call usepod_provision with that "
|
|
303
|
+
"amount, the chosen agent_id, and confirm_deposit: true. It registers a "
|
|
304
|
+
"fresh pod and funds it in one call. I do NOT need to paste anything: the "
|
|
305
|
+
"moment usepod_provision returns the api_token, Hermes auto-applies it "
|
|
306
|
+
"(writes USEPOD_API_KEY) and switches this session onto Pod automatically. "
|
|
307
|
+
"Just confirm the amount before the on-chain spend and report the funding "
|
|
308
|
+
"signature."
|
|
309
|
+
)
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
# ── UsePod "Pod" auto-apply (downstream) ──────────────────────────────────
|
|
313
|
+
# When the agent calls the ClawPump MCP tool ``usepod_provision`` it gets back
|
|
314
|
+
# ``{api_token, deposit_code, amount, signature, funding_error}``. Instead of
|
|
315
|
+
# telling the user to paste the api_token via ``claw model``, the CLI intercepts
|
|
316
|
+
# that result (cli.py ``_on_tool_complete``), persists the token, and switches
|
|
317
|
+
# the live session onto Pod. These helpers hold the downstream-owned logic so
|
|
318
|
+
# the cli.py touch points stay tiny and no-op on vanilla Hermes.
|
|
319
|
+
USEPOD_PROVISION_TOOL_SUFFIX = "usepod_provision"
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
def _is_clawpump_provision_tool(name: str) -> bool:
|
|
323
|
+
"""True only for the ClawPump MCP's usepod_provision tool.
|
|
324
|
+
|
|
325
|
+
The runtime names MCP tools ``mcp_<server>_<tool>`` — the remote entry is
|
|
326
|
+
``mcp_clawpump_usepod_provision`` and the stdio entry
|
|
327
|
+
``mcp_clawpump_stdio_usepod_provision``; both start with ``mcp_clawpump``.
|
|
328
|
+
Binding to that namespace (rather than a bare ``endswith``) keeps a
|
|
329
|
+
differently-named MCP server from minting a result that auto-rewrites the
|
|
330
|
+
user's inference credential.
|
|
331
|
+
"""
|
|
332
|
+
n = str(name or "")
|
|
333
|
+
if n == USEPOD_PROVISION_TOOL_SUFFIX:
|
|
334
|
+
return True
|
|
335
|
+
return n.startswith("mcp_clawpump") and n.endswith(USEPOD_PROVISION_TOOL_SUFFIX)
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
def _unwrap_provision_payload(value: Any, _depth: int = 0):
|
|
339
|
+
"""Return the innermost dict carrying ``api_token``, unwrapping envelopes.
|
|
340
|
+
|
|
341
|
+
Hermes' MCP client wraps a tool's text result as ``{"result": "<json>"}``
|
|
342
|
+
(and ``{"result": ..., "structuredContent": {...}}`` when the server sends
|
|
343
|
+
structured output) — see ``tools/mcp_tool.py``. The provision JSON therefore
|
|
344
|
+
arrives nested and string-escaped, so we re-parse ``result`` /
|
|
345
|
+
``structuredContent`` until we find the object with the token.
|
|
346
|
+
"""
|
|
347
|
+
if _depth > 4:
|
|
348
|
+
return None
|
|
349
|
+
if isinstance(value, str):
|
|
350
|
+
import json
|
|
351
|
+
|
|
352
|
+
try:
|
|
353
|
+
value = json.loads(value)
|
|
354
|
+
except Exception:
|
|
355
|
+
return None
|
|
356
|
+
if not isinstance(value, dict):
|
|
357
|
+
return None
|
|
358
|
+
if value.get("api_token"):
|
|
359
|
+
return value
|
|
360
|
+
for key in ("structuredContent", "result", "data"):
|
|
361
|
+
if key in value:
|
|
362
|
+
inner = _unwrap_provision_payload(value[key], _depth + 1)
|
|
363
|
+
if inner is not None:
|
|
364
|
+
return inner
|
|
365
|
+
return None
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
def usepod_provision_token(function_name: str, function_result: Any):
|
|
369
|
+
"""Extract ``(api_token, deposit_code)`` from a ``usepod_provision`` result.
|
|
370
|
+
|
|
371
|
+
Returns ``None`` unless *function_name* is the ClawPump MCP's
|
|
372
|
+
usepod_provision tool AND the result carries a usable ``api_token``.
|
|
373
|
+
Tolerant of the result arriving as a dict, a JSON string, or the
|
|
374
|
+
``{"result": "<escaped json>"}`` envelope Hermes' MCP client emits.
|
|
375
|
+
"""
|
|
376
|
+
if not _is_clawpump_provision_tool(function_name):
|
|
377
|
+
return None
|
|
378
|
+
|
|
379
|
+
api_token = ""
|
|
380
|
+
deposit_code = ""
|
|
381
|
+
payload = _unwrap_provision_payload(function_result)
|
|
382
|
+
if isinstance(payload, dict):
|
|
383
|
+
api_token = str(payload.get("api_token") or "").strip()
|
|
384
|
+
deposit_code = str(payload.get("deposit_code") or "").strip()
|
|
385
|
+
|
|
386
|
+
# Last-resort fallback: dig the fields straight out of the raw text. The
|
|
387
|
+
# quotes may be backslash-escaped (the JSON is a string value inside the
|
|
388
|
+
# ``{"result": "..."}`` envelope), so tolerate leading backslashes.
|
|
389
|
+
if not api_token and isinstance(function_result, str):
|
|
390
|
+
import re
|
|
391
|
+
|
|
392
|
+
m = re.search(r'\\*"api_token\\*"\s*:\s*\\*"([^"\\]+)', function_result)
|
|
393
|
+
if m:
|
|
394
|
+
api_token = m.group(1).strip()
|
|
395
|
+
m = re.search(r'\\*"deposit_code\\*"\s*:\s*\\*"([0-9a-fA-F]{16})', function_result)
|
|
396
|
+
if m:
|
|
397
|
+
deposit_code = m.group(1).strip()
|
|
398
|
+
|
|
399
|
+
if not api_token:
|
|
400
|
+
return None
|
|
401
|
+
# A funding_error means the deposit failed but the pod/token are still
|
|
402
|
+
# valid — applying the token is exactly right (the user funds later).
|
|
403
|
+
return (api_token, deposit_code)
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
def usepod_pod_switch_target(api_token: str, current_model: str = ""):
|
|
407
|
+
"""Return ``(model, provider, base_url)`` to switch onto for a Pod token.
|
|
408
|
+
|
|
409
|
+
Keeps the user's current model when UsePod's offline catalog lists it,
|
|
410
|
+
otherwise falls back to the provider's first advertised Pod model. The
|
|
411
|
+
secret-bearing base_url is derived from the token (never persisted to
|
|
412
|
+
config.yaml).
|
|
413
|
+
"""
|
|
414
|
+
provider = "usepod"
|
|
415
|
+
models = []
|
|
416
|
+
try:
|
|
417
|
+
from providers import get_provider_profile
|
|
418
|
+
|
|
419
|
+
pp = get_provider_profile(provider)
|
|
420
|
+
models = list(getattr(pp, "fallback_models", ()) or [])
|
|
421
|
+
except Exception:
|
|
422
|
+
models = []
|
|
423
|
+
|
|
424
|
+
model = ""
|
|
425
|
+
cur = (current_model or "").strip()
|
|
426
|
+
if cur and cur in models:
|
|
427
|
+
model = cur
|
|
428
|
+
elif models:
|
|
429
|
+
model = models[0]
|
|
430
|
+
else:
|
|
431
|
+
model = cur or "claude-opus-4-8"
|
|
432
|
+
|
|
433
|
+
base_url = ""
|
|
434
|
+
try:
|
|
435
|
+
from hermes_cli.auth import _resolve_usepod_base_url
|
|
436
|
+
|
|
437
|
+
base_url = _resolve_usepod_base_url(api_token)
|
|
438
|
+
except Exception:
|
|
439
|
+
base_url = ""
|
|
440
|
+
|
|
441
|
+
return (model, provider, base_url)
|
|
442
|
+
|
|
443
|
+
|
|
444
|
+
def persist_usepod_credentials(api_token: str, deposit_code: str = "") -> bool:
|
|
445
|
+
"""Write USEPOD_API_KEY (+ deposit_code) to ~/.hermes/.env. Returns success."""
|
|
446
|
+
try:
|
|
447
|
+
from hermes_cli.config import save_env_value
|
|
448
|
+
|
|
449
|
+
save_env_value("USEPOD_API_KEY", api_token)
|
|
450
|
+
if deposit_code:
|
|
451
|
+
try:
|
|
452
|
+
save_env_value("USEPOD_DEPOSIT_CODE", deposit_code)
|
|
453
|
+
except Exception:
|
|
454
|
+
pass # deposit_code is a convenience; the token is what matters
|
|
455
|
+
return True
|
|
456
|
+
except Exception:
|
|
457
|
+
return False
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
manifest_version: 1
|
|
4
4
|
|
|
5
5
|
name: clawpump
|
|
6
|
-
description: ClawPump — Solana AI agents, trading, perps, DCA, token launch, marketplace, lending, predictions, gift cards, agent mail, x402 paid APIs, market intelligence (
|
|
6
|
+
description: ClawPump — Solana AI agents, trading, perps, DCA, token launch, marketplace, lending, predictions, gift cards, agent mail, x402 paid APIs, UsePod pods, market intelligence (134 tools).
|
|
7
7
|
source: https://mcp.clawpump.tech
|
|
8
8
|
|
|
9
9
|
# ClawPump ships a remote MCP server: Streamable HTTP + native OAuth 2.1 +
|
|
@@ -29,13 +29,13 @@ auth:
|
|
|
29
29
|
# first probe / first connect.
|
|
30
30
|
|
|
31
31
|
# Tool selection at install time.
|
|
32
|
-
# ClawPump exposes
|
|
32
|
+
# ClawPump exposes 134 tools; 38 of them move real funds or are irreversible
|
|
33
33
|
# (perps orders, swaps, DCA/limit orders, lending deposit/withdraw, prediction
|
|
34
34
|
# positions, marketplace bids, external-wallet changes, wallet transfers,
|
|
35
35
|
# token launches, gift-card purchases/withdrawals, agent-mail
|
|
36
36
|
# provisioning/sending, x402 paid-API execution).
|
|
37
37
|
# Hermes does NOT auto-gate MCP tools by their destructiveHint, so we ship a
|
|
38
|
-
# read-mostly default: the
|
|
38
|
+
# read-mostly default: the 96 safe tools below are pre-checked in the install
|
|
39
39
|
# checklist (and applied directly if the server can't be probed before auth).
|
|
40
40
|
# Users opt into the financial tools per their threat model in the checklist,
|
|
41
41
|
# or later with `hermes mcp configure clawpump`.
|
|
@@ -118,6 +118,8 @@ tools:
|
|
|
118
118
|
- pay_sh_search
|
|
119
119
|
- pay_sh_provider_details
|
|
120
120
|
- pay_sh_prepare_call
|
|
121
|
+
# dexter x402 marketplace discovery (free search; paid with the agent wallet)
|
|
122
|
+
- dexter_search
|
|
121
123
|
# perps (read / preview only)
|
|
122
124
|
- perps_markets
|
|
123
125
|
- perps_market_data
|
|
@@ -155,6 +157,12 @@ tools:
|
|
|
155
157
|
# whitelist
|
|
156
158
|
- get_whitelist
|
|
157
159
|
- add_to_whitelist
|
|
160
|
+
# usepod / Pod (set up + fund the user's own inference pod from the wallet)
|
|
161
|
+
# provision is the Pod-setup entry point. Its only fund-moving path (passing
|
|
162
|
+
# an `amount`) is double-gated by `confirm_deposit: true`, so it's safe to
|
|
163
|
+
# ship enabled. The standalone top-up tool `usepod_deposit` is a pure
|
|
164
|
+
# fund-mover and stays opt-in with the other financial tools below.
|
|
165
|
+
- usepod_provision
|
|
158
166
|
|
|
159
167
|
post_install: |
|
|
160
168
|
On first connection Hermes opens a browser to ClawPump — log in and it
|
|
@@ -168,8 +176,8 @@ post_install: |
|
|
|
168
176
|
dca_create, limit_order_create, jup_lend_deposit/withdraw, predictions_open/
|
|
169
177
|
close, place_bid / accept_marketplace_bid, set_external_wallet,
|
|
170
178
|
wallet_transfer, agent_card_create/cancel/reveal/withdraw,
|
|
171
|
-
agent_mail_create/send, pay_sh_execute_approved, and the
|
|
172
|
-
tools). Several require explicit confirm flags (confirmRisk,
|
|
179
|
+
agent_mail_create/send, pay_sh_execute_approved, usepod_deposit, and the
|
|
180
|
+
token-launch tools). Several require explicit confirm flags (confirmRisk,
|
|
173
181
|
confirm_launch, confirm_spend, confirm_send, confirm_transfer,
|
|
174
182
|
confirm_payment, …).
|
|
175
183
|
Enable the ones you want and review every call:
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
manifest_version: 1
|
|
4
4
|
|
|
5
5
|
name: clawpump-stdio
|
|
6
|
-
description: ClawPump (stdio) — the same
|
|
6
|
+
description: ClawPump (stdio) — the same 134 tools via the npm package, authed with a cpk_* API key (no browser).
|
|
7
7
|
source: https://www.npmjs.com/package/@clawpump/agents
|
|
8
8
|
|
|
9
9
|
# Same tool surface as the `clawpump` remote entry, but run locally over stdio
|
|
@@ -31,8 +31,8 @@ auth:
|
|
|
31
31
|
secret: false
|
|
32
32
|
default: ""
|
|
33
33
|
|
|
34
|
-
# Same read-mostly default as the remote `clawpump` entry:
|
|
35
|
-
# pre-checked; the
|
|
34
|
+
# Same read-mostly default as the remote `clawpump` entry: 96 safe tools
|
|
35
|
+
# pre-checked; the 38 financial/irreversible tools are opt-in. See the
|
|
36
36
|
# `clawpump` manifest for the rationale (Hermes does not auto-gate MCP tools
|
|
37
37
|
# by destructiveHint).
|
|
38
38
|
tools:
|
|
@@ -114,6 +114,8 @@ tools:
|
|
|
114
114
|
- pay_sh_search
|
|
115
115
|
- pay_sh_provider_details
|
|
116
116
|
- pay_sh_prepare_call
|
|
117
|
+
# dexter x402 marketplace discovery (free search; paid with the agent wallet)
|
|
118
|
+
- dexter_search
|
|
117
119
|
# perps (read / preview only)
|
|
118
120
|
- perps_markets
|
|
119
121
|
- perps_market_data
|
|
@@ -151,12 +153,18 @@ tools:
|
|
|
151
153
|
# whitelist
|
|
152
154
|
- get_whitelist
|
|
153
155
|
- add_to_whitelist
|
|
156
|
+
# usepod / Pod (set up + fund the user's own inference pod from the wallet).
|
|
157
|
+
# provision is the Pod-setup entry point; its fund-moving path (an `amount`)
|
|
158
|
+
# is double-gated by `confirm_deposit: true`. The standalone top-up tool
|
|
159
|
+
# `usepod_deposit` is a pure fund-mover and stays opt-in (financial) below.
|
|
160
|
+
- usepod_provision
|
|
154
161
|
|
|
155
162
|
post_install: |
|
|
156
163
|
Requires Node.js / npx on PATH. Your cpk_* key is stored in ~/.hermes/.env
|
|
157
164
|
and sent directly as a Bearer token to the ClawPump backend — no browser.
|
|
158
165
|
|
|
159
|
-
Financial / irreversible tools are OFF by default.
|
|
166
|
+
Financial / irreversible tools (incl. usepod_deposit) are OFF by default.
|
|
167
|
+
Enable the ones you want:
|
|
160
168
|
hermes mcp configure clawpump-stdio
|
|
161
169
|
|
|
162
170
|
Start a new Hermes session to load the ClawPump tools.
|
|
@@ -14,7 +14,7 @@ metadata:
|
|
|
14
14
|
ClawPump is a Solana platform for AI agents: each agent has a wallet and can
|
|
15
15
|
trade, run perps, DCA, lend, launch tokens, buy gift cards, send email from
|
|
16
16
|
its own inbox, and be bought/sold on a marketplace. Its full feature set
|
|
17
|
-
reaches Hermes through the **ClawPump MCP server** (
|
|
17
|
+
reaches Hermes through the **ClawPump MCP server** (134 tools, 10 resources,
|
|
18
18
|
10 prompts).
|
|
19
19
|
|
|
20
20
|
## Enabling ClawPump
|
|
@@ -44,7 +44,7 @@ Most tools act on a specific agent. Resolve it once with `list_agents`, then
|
|
|
44
44
|
pass `agent_id`. If the user set `CLAWPUMP_DEFAULT_AGENT` (or has exactly one
|
|
45
45
|
agent), `agent_id` can usually be omitted. When unsure which agent, ask.
|
|
46
46
|
|
|
47
|
-
## What's available (
|
|
47
|
+
## What's available (134 tools, 21 groups)
|
|
48
48
|
|
|
49
49
|
| Group | Representative tools |
|
|
50
50
|
|-------|----------------------|
|
|
@@ -62,6 +62,8 @@ agent), `agent_id` can usually be omitted. When unsure which agent, ask.
|
|
|
62
62
|
| Agent cards (Laso) | `agent_card_search_merchants`, `agent_card_search_gift_cards`, `agent_card_quote`, `agent_card_create`, `agent_card_list`, `agent_card_get`, `agent_card_status`, `agent_card_data`, `agent_card_balance`, `agent_card_reveal`, `agent_card_cancel`, `agent_card_refresh`, `agent_card_withdraw`, `agent_card_withdrawals`, `agent_card_connect`, `agent_card_connect_link` |
|
|
63
63
|
| Agent mail | `agent_mail_create`, `agent_mail_get_address`, `agent_mail_send`, `agent_mail_list`, `agent_mail_read` |
|
|
64
64
|
| Pay.sh x402 (agent-wallet paid APIs) | `pay_sh_search`, `pay_sh_provider_details`, `pay_sh_prepare_call`, `pay_sh_execute_approved` |
|
|
65
|
+
| Dexter x402 marketplace (discovery) | `dexter_search` |
|
|
66
|
+
| UsePod (run + fund your own inference pod) | `usepod_provision`, `usepod_deposit` |
|
|
65
67
|
| Wallet & billing | `get_balance`, `get_budget`, `get_usage`, `get_transactions`, `get_wallet_summaries`, `get_wallet_history`, `get_private_wallet_balance`, `get_balance_history`, `sync_billing`, `wallet_transfer` |
|
|
66
68
|
| Market intelligence | `intelligence_capabilities`, `intelligence_market`, `intelligence_signals`, `intelligence_macro`, `intelligence_perps` |
|
|
67
69
|
| Integrations | `list_integrations`, `save_integration`, `remove_integration`, `get_linked_accounts` |
|
|
@@ -69,8 +71,10 @@ agent), `agent_id` can usually be omitted. When unsure which agent, ask.
|
|
|
69
71
|
| Whitelist | `get_whitelist`, `add_to_whitelist`, `remove_from_whitelist` |
|
|
70
72
|
| Utility | `get_model_catalog`, `get_news_feed` |
|
|
71
73
|
|
|
72
|
-
By default only the **
|
|
73
|
-
|
|
74
|
+
By default only the **95 read-mostly** tools are enabled (including
|
|
75
|
+
`usepod_provision`, whose only fund-moving path is double-gated by
|
|
76
|
+
`confirm_deposit`). The financial ones below are opt-in via
|
|
77
|
+
`hermes mcp configure clawpump`.
|
|
74
78
|
|
|
75
79
|
## ⚠️ FINANCIAL & IRREVERSIBLE TOOLS — confirmation is mandatory
|
|
76
80
|
|
|
@@ -92,6 +96,7 @@ explicit confirm flag (e.g. `confirmRisk: true`, `confirm_launch: true`,
|
|
|
92
96
|
- Agent mail: `agent_mail_create` (one-time ~$2 USDC from the agent wallet), `agent_mail_send` (outward-facing email; paid per send via x402 from the agent wallet)
|
|
93
97
|
- Wallet: `wallet_transfer` (irreversible on-chain send; destination must be on the agent's whitelist via `add_to_whitelist`; quote the exact amount, token, and address, then `confirm_transfer: true`)
|
|
94
98
|
- Pay.sh x402: `pay_sh_execute_approved` (pays USDC from the agent wallet via x402 — always `pay_sh_prepare_call` first; quote the exact endpoint + price; approval codes expire in 10 minutes; requires the `x402` skill on the agent)
|
|
99
|
+
- UsePod: `usepod_deposit` (top up the user's own UsePod pod from the agent's ClawPump wallet, to pay for Hermes/agent inference usage — irreversible on-chain USDC deposit of the **full** amount, no fee; the user supplies their 16-hex `deposit_code` from UsePod `/v1/register`; double-check the code and amount, then `confirm_deposit: true`)
|
|
95
100
|
|
|
96
101
|
**Always get a quote/preview first** (`swap_quote` before `swap_execute`,
|
|
97
102
|
`perps_order_preview` before `perps_order_execute`, `agent_card_quote` before
|
|
@@ -136,3 +141,47 @@ Common patterns:
|
|
|
136
141
|
- **Deliverability (avoid spam):** write genuine, complete messages — a specific subject, a greeting, 2–4 sentences of real purpose, and a sign-off. Never send one-word/empty bodies or test-like "hello": low-content mail from a fresh sender domain is the #1 spam trigger. Do **not** use fake-urgent or deceptive subjects ("IMPORTANT!!", "URGENT") to game filters — that backfires and is deceptive. Tell first-time recipients to mark "Not spam" + add the address to contacts; that trains their inbox fastest.
|
|
137
142
|
- **Fund an external wallet (e.g. a pay.sh allowance):** `get_balance` → `add_to_whitelist` (user-approved address) → (confirm) `wallet_transfer`. See the `pay-sh` skill.
|
|
138
143
|
- **Paid x402 API call (agent wallet pays):** `pay_sh_search` → `pay_sh_provider_details` (price) → `pay_sh_prepare_call` → (confirm price with user) → `pay_sh_execute_approved`. The agent needs the `x402` skill (`update_agent` with `enabled_skills`).
|
|
144
|
+
- **Discover x402 APIs on Dexter:** `dexter_search` (free, by capability — e.g. "ETH price", "image generation") returns matching resources with their payable `resourceUrl`, HTTP method, per-call USDC price, and input schema. To use one, call its `resourceUrl` with the agent's x402 rail (same custodial wallet, capped per call) — quote the price and confirm with the user first. No separate Dexter wallet.
|
|
145
|
+
- **Pay your Hermes inference from the ClawPump wallet (UsePod):** if the user runs Hermes on their own UsePod pod (`USEPOD_API_KEY` in `~/.hermes/.env`), they can top that pod up straight from their ClawPump wallet instead of funding it manually at usepod.ai. Flow: `get_balance` (confirm the agent wallet holds enough USDC) → ask for the amount + their 16-hex `deposit_code` (from UsePod `/v1/register`) → quote both back → (confirm) `usepod_deposit` with `confirm_deposit: true`. The full amount goes on-chain into that pod (no fee); UsePod then draws inference cost from it. This is **separate** from ClawPump's own hosted chat/credits — it just pays the user's own pod from their wallet.
|
|
146
|
+
|
|
147
|
+
## Setting up Pod (UsePod) — auto flow
|
|
148
|
+
|
|
149
|
+
When a user picks **Pod** in the `/provider` (or `/model`) picker and it isn't
|
|
150
|
+
configured, the picker hands you a request to set it up. Pod is a drop-in
|
|
151
|
+
inference provider whose usage is paid in USDC from the user's ClawPump wallet.
|
|
152
|
+
**Make this as automatic as possible — there is nothing to paste and nothing to
|
|
153
|
+
restart: the CLI auto-applies the token and switches the session onto Pod the
|
|
154
|
+
moment `usepod_provision` returns.**
|
|
155
|
+
|
|
156
|
+
1. **Ask the amount + which agent wallet.** "How much USDC do you want to put on
|
|
157
|
+
your Pod? (e.g. 5)" — optionally check `get_balance` first so you know it can
|
|
158
|
+
cover it. Then "Which ClawPump agent wallet should fund it?" — call
|
|
159
|
+
`list_agents` and let the user pick one; use its `agent_id`. (If there is only
|
|
160
|
+
one agent you may skip the question and omit `agent_id`.)
|
|
161
|
+
2. **Create + fund in one call** — `usepod_provision` registers a brand-new pod
|
|
162
|
+
(no signup, no human step) and funds it from the chosen agent wallet. After
|
|
163
|
+
the user approves the amount, call `usepod_provision` with that `amount`, the
|
|
164
|
+
selected `agent_id`, and `confirm_deposit: true`. It returns `api_token` (the
|
|
165
|
+
pod credential) + `deposit_code` and the funding `signature`.
|
|
166
|
+
3. **It's applied automatically** — in the interactive Hermes CLI, the instant
|
|
167
|
+
`usepod_provision` returns, Hermes writes `USEPOD_API_KEY` (+
|
|
168
|
+
`USEPOD_DEPOSIT_CODE`) to `~/.hermes/.env` and switches this session onto
|
|
169
|
+
Pod. No `claw model`, no paste, no restart. Watch for Hermes' own
|
|
170
|
+
confirmation line (`✓ Now running on Pod: …`) and then tell the user "Your
|
|
171
|
+
pod is funded and this session is now running on Pod — the next message bills
|
|
172
|
+
from your pod." Report the funding `signature`. Do **not** print the
|
|
173
|
+
`api_token` (it's a secret and is already applied). (On non-interactive
|
|
174
|
+
runtimes — bots/API — the credential is saved but the live switch happens on
|
|
175
|
+
the next start; say "restart to run on Pod" instead of claiming it switched.)
|
|
176
|
+
|
|
177
|
+
Notes:
|
|
178
|
+
- **Top up an existing pod** (user already set Pod up before): skip provisioning
|
|
179
|
+
— ask for the amount + their 16-hex `deposit_code`, then `usepod_deposit` with
|
|
180
|
+
`confirm_deposit: true`. (`usepod_deposit` is a fund-mover and is opt-in: if
|
|
181
|
+
it isn't available, the user enables it via `hermes mcp configure clawpump`.)
|
|
182
|
+
- `usepod_provision` registers the pod first and funds best-effort, so if funding
|
|
183
|
+
fails the user still gets a valid `api_token` (look for `funding_error`) — the
|
|
184
|
+
token is still auto-applied; fund it afterward with `usepod_deposit`.
|
|
185
|
+
- This is **separate** from ClawPump's hosted chat/credits — it pays the user's
|
|
186
|
+
own pod from their wallet. Always confirm the amount before the on-chain spend
|
|
187
|
+
and report the tx signature.
|
package/agent/uv.lock
CHANGED
|
@@ -1602,21 +1602,25 @@ version = "0.15.1"
|
|
|
1602
1602
|
source = { editable = "." }
|
|
1603
1603
|
dependencies = [
|
|
1604
1604
|
{ name = "croniter" },
|
|
1605
|
+
{ name = "fastapi" },
|
|
1605
1606
|
{ name = "fire" },
|
|
1606
1607
|
{ name = "httpx", extra = ["socks"] },
|
|
1607
1608
|
{ name = "jinja2" },
|
|
1608
1609
|
{ name = "openai" },
|
|
1609
1610
|
{ name = "prompt-toolkit" },
|
|
1610
1611
|
{ name = "psutil" },
|
|
1612
|
+
{ name = "ptyprocess", marker = "sys_platform != 'win32'" },
|
|
1611
1613
|
{ name = "pydantic" },
|
|
1612
1614
|
{ name = "pyjwt", extra = ["crypto"] },
|
|
1613
1615
|
{ name = "python-dotenv" },
|
|
1616
|
+
{ name = "pywinpty", marker = "sys_platform == 'win32'" },
|
|
1614
1617
|
{ name = "pyyaml" },
|
|
1615
1618
|
{ name = "requests" },
|
|
1616
1619
|
{ name = "rich" },
|
|
1617
1620
|
{ name = "ruamel-yaml" },
|
|
1618
1621
|
{ name = "tenacity" },
|
|
1619
1622
|
{ name = "tzdata", marker = "sys_platform == 'win32'" },
|
|
1623
|
+
{ name = "uvicorn", extra = ["standard"] },
|
|
1620
1624
|
]
|
|
1621
1625
|
|
|
1622
1626
|
[package.optional-dependencies]
|
|
@@ -1632,11 +1636,9 @@ all = [
|
|
|
1632
1636
|
{ name = "google-auth-httplib2" },
|
|
1633
1637
|
{ name = "google-auth-oauthlib" },
|
|
1634
1638
|
{ name = "mcp" },
|
|
1635
|
-
{ name = "ptyprocess", marker = "sys_platform != 'win32'" },
|
|
1636
1639
|
{ name = "pytest" },
|
|
1637
1640
|
{ name = "pytest-asyncio" },
|
|
1638
1641
|
{ name = "pytest-timeout" },
|
|
1639
|
-
{ name = "pywinpty", marker = "sys_platform == 'win32'" },
|
|
1640
1642
|
{ name = "ruff" },
|
|
1641
1643
|
{ name = "setuptools" },
|
|
1642
1644
|
{ name = "simple-term-menu" },
|
|
@@ -1739,10 +1741,6 @@ modal = [
|
|
|
1739
1741
|
parallel-web = [
|
|
1740
1742
|
{ name = "parallel-web" },
|
|
1741
1743
|
]
|
|
1742
|
-
pty = [
|
|
1743
|
-
{ name = "ptyprocess", marker = "sys_platform != 'win32'" },
|
|
1744
|
-
{ name = "pywinpty", marker = "sys_platform == 'win32'" },
|
|
1745
|
-
]
|
|
1746
1744
|
slack = [
|
|
1747
1745
|
{ name = "aiohttp" },
|
|
1748
1746
|
{ name = "slack-bolt" },
|
|
@@ -1755,9 +1753,7 @@ termux = [
|
|
|
1755
1753
|
{ name = "agent-client-protocol" },
|
|
1756
1754
|
{ name = "honcho-ai" },
|
|
1757
1755
|
{ name = "mcp" },
|
|
1758
|
-
{ name = "ptyprocess", marker = "sys_platform != 'win32'" },
|
|
1759
1756
|
{ name = "python-telegram-bot", extra = ["webhooks"] },
|
|
1760
|
-
{ name = "pywinpty", marker = "sys_platform == 'win32'" },
|
|
1761
1757
|
{ name = "simple-term-menu" },
|
|
1762
1758
|
{ name = "starlette" },
|
|
1763
1759
|
]
|
|
@@ -1770,9 +1766,7 @@ termux-all = [
|
|
|
1770
1766
|
{ name = "google-auth-oauthlib" },
|
|
1771
1767
|
{ name = "honcho-ai" },
|
|
1772
1768
|
{ name = "mcp" },
|
|
1773
|
-
{ name = "ptyprocess", marker = "sys_platform != 'win32'" },
|
|
1774
1769
|
{ name = "python-telegram-bot", extra = ["webhooks"] },
|
|
1775
|
-
{ name = "pywinpty", marker = "sys_platform == 'win32'" },
|
|
1776
1770
|
{ name = "simple-term-menu" },
|
|
1777
1771
|
{ name = "starlette" },
|
|
1778
1772
|
{ name = "uvicorn", extra = ["standard"] },
|
|
@@ -1822,6 +1816,7 @@ requires-dist = [
|
|
|
1822
1816
|
{ name = "elevenlabs", marker = "extra == 'tts-premium'", specifier = "==1.59.0" },
|
|
1823
1817
|
{ name = "exa-py", marker = "extra == 'exa'", specifier = "==2.10.2" },
|
|
1824
1818
|
{ name = "fal-client", marker = "extra == 'fal'", specifier = "==0.13.1" },
|
|
1819
|
+
{ name = "fastapi", specifier = ">=0.104.0,<1" },
|
|
1825
1820
|
{ name = "fastapi", marker = "extra == 'web'", specifier = "==0.133.1" },
|
|
1826
1821
|
{ name = "faster-whisper", marker = "extra == 'voice'", specifier = "==1.2.1" },
|
|
1827
1822
|
{ name = "fire", specifier = "==0.7.1" },
|
|
@@ -1868,7 +1863,7 @@ requires-dist = [
|
|
|
1868
1863
|
{ name = "parallel-web", marker = "extra == 'parallel-web'", specifier = "==0.4.2" },
|
|
1869
1864
|
{ name = "prompt-toolkit", specifier = "==3.0.52" },
|
|
1870
1865
|
{ name = "psutil", specifier = "==7.2.2" },
|
|
1871
|
-
{ name = "ptyprocess", marker = "sys_platform != 'win32'
|
|
1866
|
+
{ name = "ptyprocess", marker = "sys_platform != 'win32'", specifier = ">=0.7.0,<1" },
|
|
1872
1867
|
{ name = "pydantic", specifier = "==2.13.4" },
|
|
1873
1868
|
{ name = "pyjwt", extras = ["crypto"], specifier = "==2.12.1" },
|
|
1874
1869
|
{ name = "pytest", marker = "extra == 'dev'", specifier = "==9.0.2" },
|
|
@@ -1877,7 +1872,7 @@ requires-dist = [
|
|
|
1877
1872
|
{ name = "python-dotenv", specifier = "==1.2.2" },
|
|
1878
1873
|
{ name = "python-telegram-bot", extras = ["webhooks"], marker = "extra == 'messaging'", specifier = "==22.6" },
|
|
1879
1874
|
{ name = "python-telegram-bot", extras = ["webhooks"], marker = "extra == 'termux'", specifier = "==22.6" },
|
|
1880
|
-
{ name = "pywinpty", marker = "sys_platform == 'win32'
|
|
1875
|
+
{ name = "pywinpty", marker = "sys_platform == 'win32'", specifier = ">=2.0.0,<3" },
|
|
1881
1876
|
{ name = "pyyaml", specifier = "==6.0.3" },
|
|
1882
1877
|
{ name = "qrcode", marker = "extra == 'dingtalk'", specifier = "==7.4.2" },
|
|
1883
1878
|
{ name = "qrcode", marker = "extra == 'feishu'", specifier = "==7.4.2" },
|
|
@@ -1900,6 +1895,7 @@ requires-dist = [
|
|
|
1900
1895
|
{ name = "tenacity", specifier = "==9.1.4" },
|
|
1901
1896
|
{ name = "ty", marker = "extra == 'dev'", specifier = "==0.0.21" },
|
|
1902
1897
|
{ name = "tzdata", marker = "sys_platform == 'win32'", specifier = "==2025.3" },
|
|
1898
|
+
{ name = "uvicorn", extras = ["standard"], specifier = ">=0.24.0,<1" },
|
|
1903
1899
|
{ name = "uvicorn", extras = ["standard"], marker = "extra == 'web'", specifier = "==0.41.0" },
|
|
1904
1900
|
{ name = "youtube-transcript-api", marker = "extra == 'youtube'", specifier = "==1.2.4" },
|
|
1905
1901
|
]
|