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.
@@ -0,0 +1,6 @@
1
+ """bridgenode_cli — BridgeNode CLI (§8.4, fix.md 4.4)."""
2
+
3
+ from .main import main
4
+
5
+ __all__ = ["main"]
6
+ __version__ = "0.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,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (83.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ bridgenode = bridgenode_cli.main:main
@@ -0,0 +1 @@
1
+ bridgenode_cli