bridgenode-cli 0.1.0__py3-none-any.whl
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.
- bridgenode_cli/__init__.py +6 -0
- bridgenode_cli/main.py +131 -0
- bridgenode_cli-0.1.0.dist-info/METADATA +65 -0
- bridgenode_cli-0.1.0.dist-info/RECORD +7 -0
- bridgenode_cli-0.1.0.dist-info/WHEEL +5 -0
- bridgenode_cli-0.1.0.dist-info/entry_points.txt +2 -0
- bridgenode_cli-0.1.0.dist-info/top_level.txt +1 -0
bridgenode_cli/main.py
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"""main.py — bridgenode CLI (§8.4, fix.md 4.4 ž1).
|
|
2
|
+
|
|
3
|
+
Komandos:
|
|
4
|
+
- `bridgenode chat "<prompt>"` — vienas chat completion per x402 handshake
|
|
5
|
+
(SDK: 402 → dalinis TX → PAYMENT-SIGNATURE → 200; §4.1)
|
|
6
|
+
- `bridgenode models` — modelių sąrašas + kainos iš GET /v1/models (§5.2)
|
|
7
|
+
|
|
8
|
+
Parinktys: --model (explicit, §5.1), --mode auto/eco/premium (smart routing,
|
|
9
|
+
§5.1/§5.8), --max-tokens. Visas mokėjimas paslėptas — naudojamas oficialus
|
|
10
|
+
LLMClient (P4). Klaidos → stderr + exit 1; sėkmė → stdout + exit 0.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import argparse
|
|
16
|
+
import os
|
|
17
|
+
import sys
|
|
18
|
+
from typing import Any
|
|
19
|
+
|
|
20
|
+
from bridgenode_llm import BridgenodeError, LLMClient
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _client(args: argparse.Namespace) -> LLMClient:
|
|
24
|
+
"""LLMClient iš CLI argumentų (raktas TIK iš .env, §8.4)."""
|
|
25
|
+
# None reikšmės neperduodamos — SDK naudoja default'us (§8.5);
|
|
26
|
+
# kitaip timeout=None patektų į flow timeout skaičiavimą (Ž42)
|
|
27
|
+
kwargs: dict[str, Any] = {}
|
|
28
|
+
if args.base_url:
|
|
29
|
+
kwargs["base_url"] = args.base_url
|
|
30
|
+
if args.initial_timeout is not None:
|
|
31
|
+
kwargs["initial_timeout"] = args.initial_timeout
|
|
32
|
+
if args.retry_timeout is not None:
|
|
33
|
+
kwargs["retry_timeout"] = args.retry_timeout
|
|
34
|
+
if args.max_per_call is not None:
|
|
35
|
+
kwargs["max_per_call_usd"] = args.max_per_call
|
|
36
|
+
if args.daily_cap is not None:
|
|
37
|
+
kwargs["daily_cap_usd"] = args.daily_cap
|
|
38
|
+
return LLMClient(**kwargs)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def cmd_chat(args: argparse.Namespace) -> int:
|
|
42
|
+
"""`bridgenode chat "<prompt>" [--model M | --mode auto|eco|premium]`."""
|
|
43
|
+
if args.model is None and args.mode is None:
|
|
44
|
+
print("Error: --model or --mode required", file=sys.stderr)
|
|
45
|
+
return 2
|
|
46
|
+
try:
|
|
47
|
+
client = _client(args)
|
|
48
|
+
messages = [{"role": "user", "content": args.prompt}]
|
|
49
|
+
resp: dict[str, Any] = client.chat(
|
|
50
|
+
args.model, messages,
|
|
51
|
+
max_tokens=args.max_tokens, mode=args.mode)
|
|
52
|
+
except BridgenodeError as exc:
|
|
53
|
+
print(f"Error: {exc}", file=sys.stderr)
|
|
54
|
+
return 1
|
|
55
|
+
content = resp["choices"][0]["message"]["content"]
|
|
56
|
+
print(content)
|
|
57
|
+
return 0
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def cmd_models(args: argparse.Namespace) -> int:
|
|
61
|
+
"""`bridgenode models` — modelių sąrašas + kainos (§5.2).
|
|
62
|
+
|
|
63
|
+
Viešas endpointas (be mokėjimo) — tiesioginis HTTP, be SDK (SDK turi
|
|
64
|
+
tik chat(), protokolas §8.4)."""
|
|
65
|
+
import httpx
|
|
66
|
+
|
|
67
|
+
base_url = (args.base_url or os.environ.get("BRIDGENODE_BASE_URL")
|
|
68
|
+
or "https://bridgenode.cc/v1").rstrip("/")
|
|
69
|
+
try:
|
|
70
|
+
resp = httpx.get(f"{base_url}/models", timeout=30.0)
|
|
71
|
+
if resp.status_code != 200:
|
|
72
|
+
raise RuntimeError(f"HTTP {resp.status_code}")
|
|
73
|
+
data = resp.json()
|
|
74
|
+
except Exception as exc:
|
|
75
|
+
print(f"Error: {exc}", file=sys.stderr)
|
|
76
|
+
return 1
|
|
77
|
+
models = data.get("data", [])
|
|
78
|
+
for m in models:
|
|
79
|
+
pricing = m.get("pricing", {})
|
|
80
|
+
print(
|
|
81
|
+
f"{m.get('id', '?'):24} "
|
|
82
|
+
f"prompt=${pricing.get('prompt', 0):.8f} "
|
|
83
|
+
f"completion=${pricing.get('completion', 0):.8f} "
|
|
84
|
+
f"context={m.get('context_window', '?')}")
|
|
85
|
+
return 0
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def build_parser() -> argparse.ArgumentParser:
|
|
89
|
+
parser = argparse.ArgumentParser(
|
|
90
|
+
prog="bridgenode",
|
|
91
|
+
description=(
|
|
92
|
+
"BridgeNode CLI — AI inference, mokėjimas Solana USDC per x402. "
|
|
93
|
+
"Jokių API key."
|
|
94
|
+
),
|
|
95
|
+
)
|
|
96
|
+
parser.add_argument("--base-url", default=None,
|
|
97
|
+
help="Base URL (default: BRIDGENODE_BASE_URL / https://bridgenode.cc/v1)")
|
|
98
|
+
parser.add_argument("--initial-timeout", type=float, default=None,
|
|
99
|
+
help="Pradinio request'o timeout s (eilė iki 402, §5.7)")
|
|
100
|
+
parser.add_argument("--retry-timeout", type=float, default=None,
|
|
101
|
+
help="Retry timeout s (≤115s biudžetas, §4.3)")
|
|
102
|
+
parser.add_argument("--max-per-call", type=float, default=None,
|
|
103
|
+
help="Spending policy: max USD per call (ž2)")
|
|
104
|
+
parser.add_argument("--daily-cap", type=float, default=None,
|
|
105
|
+
help="Spending policy: max USD per day (ž2)")
|
|
106
|
+
sub = parser.add_subparsers(dest="command", required=True)
|
|
107
|
+
|
|
108
|
+
p_chat = sub.add_parser("chat", help="Vienas chat completion per x402 (§4.1)")
|
|
109
|
+
p_chat.add_argument("prompt", help="Prompt tekstas")
|
|
110
|
+
p_chat.add_argument("--model", default=None,
|
|
111
|
+
help="Explicit model id (žr. `bridgenode models`)")
|
|
112
|
+
p_chat.add_argument("--mode", choices=["auto", "eco", "premium"], default=None,
|
|
113
|
+
help="Smart routing profilis (§5.1/§5.8)")
|
|
114
|
+
p_chat.add_argument("--max-tokens", type=int, default=None,
|
|
115
|
+
help="Max output tokenų (billing upfront, §4.2)")
|
|
116
|
+
p_chat.set_defaults(func=cmd_chat)
|
|
117
|
+
|
|
118
|
+
p_models = sub.add_parser("models", help="Modelių sąrašas + kainos (§5.2)")
|
|
119
|
+
p_models.set_defaults(func=cmd_models)
|
|
120
|
+
|
|
121
|
+
return parser
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def main(argv: list[str] | None = None) -> int:
|
|
125
|
+
parser = build_parser()
|
|
126
|
+
args = parser.parse_args(argv)
|
|
127
|
+
return args.func(args)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
if __name__ == "__main__":
|
|
131
|
+
sys.exit(main())
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: bridgenode-cli
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: BridgeNode CLI — AI inference su x402 mokėjimu (Solana USDC). Jokių API key.
|
|
5
|
+
Requires-Python: >=3.11
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
Requires-Dist: bridgenode-llm>=0.1.0
|
|
8
|
+
Provides-Extra: dev
|
|
9
|
+
Requires-Dist: pytest>=9.1.1; extra == "dev"
|
|
10
|
+
|
|
11
|
+
# bridgenode-cli
|
|
12
|
+
|
|
13
|
+
BridgeNode CLI — AI inference be API key. Mokėjimas: **Solana USDC per x402** (automatinis handshake, fee sponsorship — SOL nereikia).
|
|
14
|
+
|
|
15
|
+
## Diegimas
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pip install bridgenode-cli
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Naudojimas
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# Vienas chat completion (x402 handshake paslėptas, §4.1)
|
|
25
|
+
bridgenode chat "Labas!" --model deepseek-v4-flash
|
|
26
|
+
|
|
27
|
+
# Smart routing (§5.1/§5.8): auto / eco / premium
|
|
28
|
+
bridgenode chat "Išanalizuok šį kodą" --mode auto
|
|
29
|
+
|
|
30
|
+
# Modelių sąrašas + kainos (§5.2) — be mokėjimo
|
|
31
|
+
bridgenode models
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Parinktys
|
|
35
|
+
|
|
36
|
+
| Parinktis | Aprašas |
|
|
37
|
+
|---|---|
|
|
38
|
+
| `--model` | Explicit model id (žr. `bridgenode models`) |
|
|
39
|
+
| `--mode` | `auto` / `eco` / `premium` (smart routing) |
|
|
40
|
+
| `--max-tokens` | Max output tokenų (billing upfront, §4.2) |
|
|
41
|
+
| `--base-url` | Base URL (default: `BRIDGENODE_BASE_URL` / https://bridgenode.cc/v1) |
|
|
42
|
+
| `--max-per-call` / `--daily-cap` | Spending policy (fail-closed) |
|
|
43
|
+
|
|
44
|
+
## .env
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
# Privalomas — jūsų Solana wallet private key (base58)
|
|
48
|
+
BRIDGENODE_WALLET_KEY=...
|
|
49
|
+
# Neprivalomi: BRIDGENODE_BASE_URL, BRIDGENODE_MAX_PER_CALL, BRIDGENODE_DAILY_CAP
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Apsaugos
|
|
53
|
+
|
|
54
|
+
- **Kvito verifikacija (Free-Riding apsauga):** po 200 tikrinamas `PAYMENT-RESPONSE` — netikras kvitas → klaida.
|
|
55
|
+
- **Spending policy (fail-closed):** max USD per call / per day — tikrinama PRIEŠ pasirašant.
|
|
56
|
+
|
|
57
|
+
## Reikalavimai
|
|
58
|
+
|
|
59
|
+
- Python ≥ 3.11
|
|
60
|
+
- Solana wallet su USDC ATA (rent — agento atsakomybė, §3.3)
|
|
61
|
+
|
|
62
|
+
## Nuorodos
|
|
63
|
+
|
|
64
|
+
- Tinklalapis: https://bridgenode.cc
|
|
65
|
+
- Protokolas: x402 V2 (docs.x402.org)
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
bridgenode_cli/__init__.py,sha256=S8t6su2k7Wua02nktosiQSyed43tUcYDfKFAYZ0VeCk,127
|
|
2
|
+
bridgenode_cli/main.py,sha256=DmcE9RSHQ03Fx50L1VZQiboRIqyIgeRzBwZJ_HqylgM,5120
|
|
3
|
+
bridgenode_cli-0.1.0.dist-info/METADATA,sha256=01f58Jph414wzVdoski46hB4NHS-uI4N9P0CcoUeIUg,1845
|
|
4
|
+
bridgenode_cli-0.1.0.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
|
|
5
|
+
bridgenode_cli-0.1.0.dist-info/entry_points.txt,sha256=HZLl-3_tNozfLwEbkdrjx8QTAWNX0pp8gw29JHAmAy4,56
|
|
6
|
+
bridgenode_cli-0.1.0.dist-info/top_level.txt,sha256=ichCqXfIaZP_x4SwZ-h3aTfVqrV7haqz5jOm0ICIKPI,15
|
|
7
|
+
bridgenode_cli-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
bridgenode_cli
|