bridgenode-cli 0.1.10__tar.gz → 0.1.12__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bridgenode-cli
3
- Version: 0.1.10
3
+ Version: 0.1.12
4
4
  Summary: Agentic AI CLI with x402 (HTTP 402) pay-per-request on Solana USDC — no API keys.
5
5
  Author-email: BridgeNode <eli.BNx@proton.me>
6
6
  License-Expression: MIT-0
@@ -60,8 +60,11 @@ pip install bridgenode
60
60
  ## Usage
61
61
 
62
62
  ```bash
63
+ # Free models need no wallet — and the first 2 calls to a PAID model are free
64
+ bridgenode chat "Hello!" --model gpt-oss-120b
65
+
63
66
  # Single chat completion (payment handshake fully automatic)
64
- bridgenode chat "Hello!" --model deepseek-v4-flash
67
+ bridgenode chat "Hello!" --model deepseek-flash
65
68
 
66
69
  # Smart routing: auto / eco / premium
67
70
  bridgenode chat "Analyze this code" --mode auto
@@ -83,7 +86,8 @@ bridgenode models
83
86
  ## Configuration (.env)
84
87
 
85
88
  ```bash
86
- # Required — your Solana wallet private key (base58)
89
+ # Optional — your Solana wallet private key (base58).
90
+ # Needed only for PAID requests: free models and the 2 free trials work without it.
87
91
  BRIDGENODE_WALLET_KEY=...
88
92
  # Optional: BRIDGENODE_BASE_URL, BRIDGENODE_MAX_PER_CALL, BRIDGENODE_DAILY_CAP
89
93
  ```
@@ -24,8 +24,11 @@ pip install bridgenode
24
24
  ## Usage
25
25
 
26
26
  ```bash
27
+ # Free models need no wallet — and the first 2 calls to a PAID model are free
28
+ bridgenode chat "Hello!" --model gpt-oss-120b
29
+
27
30
  # Single chat completion (payment handshake fully automatic)
28
- bridgenode chat "Hello!" --model deepseek-v4-flash
31
+ bridgenode chat "Hello!" --model deepseek-flash
29
32
 
30
33
  # Smart routing: auto / eco / premium
31
34
  bridgenode chat "Analyze this code" --mode auto
@@ -47,7 +50,8 @@ bridgenode models
47
50
  ## Configuration (.env)
48
51
 
49
52
  ```bash
50
- # Required — your Solana wallet private key (base58)
53
+ # Optional — your Solana wallet private key (base58).
54
+ # Needed only for PAID requests: free models and the 2 free trials work without it.
51
55
  BRIDGENODE_WALLET_KEY=...
52
56
  # Optional: BRIDGENODE_BASE_URL, BRIDGENODE_MAX_PER_CALL, BRIDGENODE_DAILY_CAP
53
57
  ```
@@ -0,0 +1,6 @@
1
+ """bridgenode_cli — BridgeNode CLI."""
2
+
3
+ from .main import main
4
+
5
+ __all__ = ["main"]
6
+ __version__ = "0.1.12"
@@ -1,4 +1,4 @@
1
- """__main__.py — `python -m bridgenode_cli` entry point (R18/Ž18)."""
1
+ """__main__.py — `python -m bridgenode_cli` entry point."""
2
2
 
3
3
  import sys
4
4
 
@@ -1,13 +1,13 @@
1
- """main.py — bridgenode CLI (§8.4, fix.md 4.4 step 1).
1
+ """main.py — bridgenode CLI.
2
2
 
3
3
  Commands:
4
4
  - `bridgenode chat "<prompt>"` — single chat completion via the x402 handshake
5
- (SDK: 402 → partial TX → PAYMENT-SIGNATURE → 200; §4.1)
6
- - `bridgenode models` — model list + prices from GET /v1/models (§5.2)
5
+ (SDK: 402 → partial TX → PAYMENT-SIGNATURE → 200)
6
+ - `bridgenode models` — model list + prices from GET /v1/models
7
7
 
8
- Options: --model (explicit, §5.1), --mode auto/eco/premium (smart routing,
9
- §5.1/§5.8), --max-tokens. All payment is hidden — uses the official
10
- LLMClient (P4). Errors → stderr + exit 1; success → stdout + exit 0.
8
+ Options: --model (explicit), --mode auto/eco/premium (smart routing),
9
+ --max-tokens. All payment is hidden — uses the official
10
+ LLMClient. Errors → stderr + exit 1; success → stdout + exit 0.
11
11
  """
12
12
 
13
13
  from __future__ import annotations
@@ -21,9 +21,9 @@ from bridgenode_llm import BridgenodeError, LLMClient
21
21
 
22
22
 
23
23
  def _client(args: argparse.Namespace) -> LLMClient:
24
- """LLMClient from CLI arguments (key ONLY from .env, §8.4)."""
25
- # None values are not passed — the SDK uses defaults (§8.5);
26
- # otherwise timeout=None would enter the flow timeout calculation (item 42)
24
+ """LLMClient from CLI arguments (key ONLY from .env)."""
25
+ # None values are not passed — the SDK uses defaults;
26
+ # otherwise timeout=None would enter the flow timeout calculation
27
27
  kwargs: dict[str, Any] = {}
28
28
  if args.base_url:
29
29
  kwargs["base_url"] = args.base_url
@@ -58,10 +58,10 @@ def cmd_chat(args: argparse.Namespace) -> int:
58
58
 
59
59
 
60
60
  def cmd_models(args: argparse.Namespace) -> int:
61
- """`bridgenode models` — model list + prices (§5.2).
61
+ """`bridgenode models` — model list + prices.
62
62
 
63
63
  Public endpoint (no payment) — direct HTTP, without the SDK (the SDK has
64
- only chat(), protocol §8.4)."""
64
+ only chat())."""
65
65
  import httpx
66
66
 
67
67
  base_url = (args.base_url or os.environ.get("BRIDGENODE_BASE_URL")
@@ -96,26 +96,26 @@ def build_parser() -> argparse.ArgumentParser:
96
96
  parser.add_argument("--base-url", default=None,
97
97
  help="Base URL (default: BRIDGENODE_BASE_URL / https://bridgenode.cc/v1)")
98
98
  parser.add_argument("--initial-timeout", type=float, default=None,
99
- help="Initial request timeout s (queue until 402, §5.7)")
99
+ help="Initial request timeout s (queue until 402)")
100
100
  parser.add_argument("--retry-timeout", type=float, default=None,
101
- help="Retry timeout s (≤115s budget, §4.3)")
101
+ help="Retry timeout s (≤115s budget)")
102
102
  parser.add_argument("--max-per-call", type=float, default=None,
103
103
  help="Spending policy: max USD per call (step 2)")
104
104
  parser.add_argument("--daily-cap", type=float, default=None,
105
105
  help="Spending policy: max USD per day (step 2)")
106
106
  sub = parser.add_subparsers(dest="command", required=True)
107
107
 
108
- p_chat = sub.add_parser("chat", help="Single chat completion via x402 (§4.1)")
108
+ p_chat = sub.add_parser("chat", help="Single chat completion via x402")
109
109
  p_chat.add_argument("prompt", help="Prompt text")
110
110
  p_chat.add_argument("--model", default=None,
111
111
  help="Explicit model id (see `bridgenode models`)")
112
112
  p_chat.add_argument("--mode", choices=["auto", "eco", "premium"], default=None,
113
- help="Smart routing profile (§5.1/§5.8)")
113
+ help="Smart routing profile")
114
114
  p_chat.add_argument("--max-tokens", type=int, default=None,
115
- help="Max output tokens (billing upfront, §4.2)")
115
+ help="Max output tokens (billing upfront)")
116
116
  p_chat.set_defaults(func=cmd_chat)
117
117
 
118
- p_models = sub.add_parser("models", help="Model list + prices (§5.2)")
118
+ p_models = sub.add_parser("models", help="Model list + prices")
119
119
  p_models.set_defaults(func=cmd_models)
120
120
 
121
121
  return parser
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bridgenode-cli
3
- Version: 0.1.10
3
+ Version: 0.1.12
4
4
  Summary: Agentic AI CLI with x402 (HTTP 402) pay-per-request on Solana USDC — no API keys.
5
5
  Author-email: BridgeNode <eli.BNx@proton.me>
6
6
  License-Expression: MIT-0
@@ -60,8 +60,11 @@ pip install bridgenode
60
60
  ## Usage
61
61
 
62
62
  ```bash
63
+ # Free models need no wallet — and the first 2 calls to a PAID model are free
64
+ bridgenode chat "Hello!" --model gpt-oss-120b
65
+
63
66
  # Single chat completion (payment handshake fully automatic)
64
- bridgenode chat "Hello!" --model deepseek-v4-flash
67
+ bridgenode chat "Hello!" --model deepseek-flash
65
68
 
66
69
  # Smart routing: auto / eco / premium
67
70
  bridgenode chat "Analyze this code" --mode auto
@@ -83,7 +86,8 @@ bridgenode models
83
86
  ## Configuration (.env)
84
87
 
85
88
  ```bash
86
- # Required — your Solana wallet private key (base58)
89
+ # Optional — your Solana wallet private key (base58).
90
+ # Needed only for PAID requests: free models and the 2 free trials work without it.
87
91
  BRIDGENODE_WALLET_KEY=...
88
92
  # Optional: BRIDGENODE_BASE_URL, BRIDGENODE_MAX_PER_CALL, BRIDGENODE_DAILY_CAP
89
93
  ```
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "bridgenode-cli"
3
- version = "0.1.10"
3
+ version = "0.1.12"
4
4
  description = "Agentic AI CLI with x402 (HTTP 402) pay-per-request on Solana USDC — no API keys."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -1,4 +1,4 @@
1
- """test_cli.py — bridgenode CLI tests (fix.md 4.4 z1).
1
+ """test_cli.py — bridgenode CLI tests.
2
2
 
3
3
  Checks command output and argument passing with a mocked LLMClient
4
4
  (no network, no payment). Full mock-402 path — 4.4 z2.
@@ -63,7 +63,7 @@ def test_chat_mode_passed(fake_client, capsys):
63
63
 
64
64
 
65
65
  def test_chat_model_and_mode(fake_client):
66
- """§5.1: both are passed through — the server resolves the conflict (model wins)."""
66
+ """Both are passed through — the server resolves the conflict (model wins)."""
67
67
  rc = cli.main(["chat", "hi", "--model", "deepseek-v4-flash",
68
68
  "--mode", "premium"])
69
69
  assert rc == 0
@@ -150,7 +150,7 @@ def test_client_kwargs_wired(monkeypatch):
150
150
  """CLI arguments → LLMClient kwargs (timeouts, spending policy).
151
151
 
152
152
  Global options (--base-url etc.) — BEFORE the subcommand (argparse).
153
- Checked via `chat` (the models command does not use the SDK — direct HTTP, §5.2).
153
+ Checked via `chat` (the models command does not use the SDK — direct HTTP).
154
154
  """
155
155
  captured: dict = {}
156
156
 
@@ -1,4 +1,4 @@
1
- """test_cli_integration.py — CLI → real SDK path with mock 402 (fix.md 4.4 z2).
1
+ """test_cli_integration.py — CLI → real SDK path with mock 402.
2
2
 
3
3
  Full x402 handshake through the real `bridgenode_llm` SDK: CLI `chat` → 402
4
4
  (PAYMENT-REQUIRED) → partial TX → PAYMENT-SIGNATURE → 200 + valid
@@ -180,12 +180,12 @@ def test_cli_chat_full_handshake(monkeypatch, _mock_http, capsys):
180
180
  assert len(seen) == 2
181
181
  assert seen[0]["has_payment"] is False
182
182
  assert seen[1]["has_payment"] is True
183
- assert seen[0]["body"] == seen[1]["body"] # price-bind (§4.1.1)
183
+ assert seen[0]["body"] == seen[1]["body"] # price-bind
184
184
  assert seen[0]["body"]["model"] == "deepseek-v4-flash"
185
185
 
186
186
 
187
187
  def test_cli_chat_mode_auto(monkeypatch, _mock_http, capsys):
188
- """CLI --mode auto → SDK mode is passed through (smart routing §5.1)."""
188
+ """CLI --mode auto → SDK mode is passed through (smart routing)."""
189
189
  fee_kp = Keypair()
190
190
  client_kp = Keypair()
191
191
  seen = _install_server(_mock_http, fee_kp, str(client_kp.pubkey()))
@@ -197,7 +197,7 @@ def test_cli_chat_mode_auto(monkeypatch, _mock_http, capsys):
197
197
  assert seen[0]["body"]["mode"] == "auto"
198
198
 
199
199
 
200
- def test_cli_chat_kvitas_verify_fail(monkeypatch, _mock_http, capsys):
200
+ def test_cli_chat_receipt_verify_fail(monkeypatch, _mock_http, capsys):
201
201
  """Forged receipt → CLI error (exit 1) — Free-Riding protection works."""
202
202
  fee_kp = Keypair()
203
203
  client_kp = Keypair()
@@ -233,7 +233,7 @@ def test_cli_chat_kvitas_verify_fail(monkeypatch, _mock_http, capsys):
233
233
  assert "does not match our TX" in capsys.readouterr().err
234
234
 
235
235
 
236
- # ── models: without payment (§5.2) ───────────────────────────────────────────────
236
+ # ── models: without payment ───────────────────────────────────────────────
237
237
 
238
238
  def test_cli_models_integration(monkeypatch, capsys):
239
239
  import httpx
@@ -249,7 +249,7 @@ def test_cli_models_integration(monkeypatch, capsys):
249
249
  "context_window": 131072, "max_output_tokens": 32768},
250
250
  ]})
251
251
 
252
- # models — direct HTTP (no SDK, §5.2 public endpoint)
252
+ # models — direct HTTP (no SDK, public endpoint)
253
253
  monkeypatch.setattr(httpx, "get", fake_get)
254
254
  rc = cli.main(["--base-url", API_BASE, "models"])
255
255
  assert rc == 0
@@ -1,6 +0,0 @@
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.10"
File without changes