@flop-labs/cli 0.0.0-stage → 0.4.0
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/CHANGELOG.md +207 -0
- package/LICENSE +238 -0
- package/README.md +499 -2
- package/dist/cli.js +12843 -0
- package/package.json +52 -3
package/README.md
CHANGED
|
@@ -1,3 +1,500 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @flop-labs/cli
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
FLOP Network CLI — interact with FLOP Network nodes from the command line.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
The full CLI (key, miner, validator and model commands) needs Node.js 22+. Run a pinned release
|
|
8
|
+
from public npm without installing it globally:
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
npx --yes --package @flop-labs/cli@0.4.0 flop --version
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Or run the promoted container image, which needs only Docker. For a reproducible digest pin,
|
|
15
|
+
use [releases.json](https://flop.network/releases.json). The image starts in `/app`, so mount
|
|
16
|
+
your working directory and pass absolute paths under it:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
docker run --rm --network host -v "$PWD:/work" \
|
|
20
|
+
ghcr.io/flop-labs/flop-core/cli:stable \
|
|
21
|
+
--version
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
`npm install --global @flop-labs/cli` also works, but it puts a second `flop` on `PATH`: the
|
|
25
|
+
public Hermes launcher's installer below refuses to install next to it, and the two commands
|
|
26
|
+
shadow each other.
|
|
27
|
+
|
|
28
|
+
For the recommended public native Hermes provider path, install the standalone launcher without repository
|
|
29
|
+
or package-registry access:
|
|
30
|
+
|
|
31
|
+
```sh
|
|
32
|
+
curl -fsSL https://flop.network/releases/cli/0.4.11/install.sh | sh -s -- --version 0.4.11
|
|
33
|
+
export PATH="$HOME/.local/bin:$PATH"
|
|
34
|
+
flop --network devnet hermes desktop --doctor
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
This release needs Node.js 22+, curl and the qualified Hermes 0.22.2 release. It contains the hosted
|
|
38
|
+
Hermes commands and the native public provider 0.1.6 and preserves an existing full CLI. See the
|
|
39
|
+
public launcher guide (`docs/integrations/hermes-public-launcher.md` in the FLOP repository) for
|
|
40
|
+
the native setup sequence, checksums, the 24-hour trial and acceptance limits.
|
|
41
|
+
The alternate hosted launcher needs explicit preparation of its generated Hermes
|
|
42
|
+
home; it is not qualified as a one-step launch on a fresh managed installation. The full CLI
|
|
43
|
+
source build remains:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
pnpm install --frozen-lockfile
|
|
47
|
+
pnpm --filter @flop-labs/gateway-core build
|
|
48
|
+
pnpm --filter @flop-labs/sdk exec tsc
|
|
49
|
+
pnpm --filter @flop-labs/sdk run build:a2a-cjs
|
|
50
|
+
pnpm --filter @flop-labs/agent-sdk exec tsc
|
|
51
|
+
pnpm --filter @flop-labs/cli build
|
|
52
|
+
node sdk/cli/dist/cli.js --version # from the repository root
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Usage
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
flop [options] [command]
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Global Options
|
|
62
|
+
|
|
63
|
+
| Option | Description | Default |
|
|
64
|
+
|--------|-------------|---------|
|
|
65
|
+
| `--network <name>` | `local`, `devnet`, `testnet`, or `mainnet` | `local` |
|
|
66
|
+
| `--rpc <url>` | Explicit RPC override | selected profile |
|
|
67
|
+
| `--signer <uri>` | Local signer URI | `//Alice` on local only |
|
|
68
|
+
| `--keystore <path>` | Encrypted Polkadot JSON keystore | — |
|
|
69
|
+
| `--password-env <name>` | Environment variable containing its password | — |
|
|
70
|
+
| `--output <mode>` | `human`, pretty `json`, or compact `agent` | `human` |
|
|
71
|
+
| `--json` | Output as JSON | false |
|
|
72
|
+
|
|
73
|
+
### Commands
|
|
74
|
+
|
|
75
|
+
#### Unified role onboarding
|
|
76
|
+
|
|
77
|
+
The role commands provide one entry point for onboarding, diagnostics, status,
|
|
78
|
+
and lifecycle operations. `init` and `doctor` are read-only. Commands such as
|
|
79
|
+
`register`, `calibrate-start`, `commission`, `unjail`, `rejoin`, and `exit`
|
|
80
|
+
are explicit chain mutations.
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
# Agents: the devnet tailnet MCP is read-only; local mode is signer-capable.
|
|
84
|
+
flop --network devnet agent init --client codex
|
|
85
|
+
flop --network devnet agent doctor
|
|
86
|
+
flop agent launch codex
|
|
87
|
+
flop agent proxy
|
|
88
|
+
flop agent hermes desktop
|
|
89
|
+
flop keys generate --out agent-key.json --password-env FLOP_KEY_PASSWORD
|
|
90
|
+
flop agent wallet create <agent-address>
|
|
91
|
+
flop agent session create --delegate <address>
|
|
92
|
+
|
|
93
|
+
# Miners: sim first, measured TDX for verified production, cloud is non-attested.
|
|
94
|
+
flop miner init --mode sim
|
|
95
|
+
flop miner doctor --mode sim
|
|
96
|
+
flop miner status [address]
|
|
97
|
+
flop --signer <MINER-URI> miner register --commission 10
|
|
98
|
+
flop --signer <MINER-URI> miner calibrate-start
|
|
99
|
+
|
|
100
|
+
# Validators: live stake minimum and PoUI-gated committee state are queried.
|
|
101
|
+
flop validator init --mode local
|
|
102
|
+
flop validator doctor
|
|
103
|
+
flop validator status [address]
|
|
104
|
+
flop --signer <VALIDATOR-URI> validator register
|
|
105
|
+
flop --signer <VALIDATOR-URI> validator commission 10
|
|
106
|
+
flop --signer <VALIDATOR-URI> validator unjail
|
|
107
|
+
flop --signer <VALIDATOR-URI> validator rejoin
|
|
108
|
+
flop --signer <VALIDATOR-URI> validator exit
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
All role planning and diagnostic commands support `--json` for automation.
|
|
112
|
+
Global network and custody options work at any nesting depth.
|
|
113
|
+
|
|
114
|
+
#### Networks and faucet
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
flop --network devnet network status
|
|
118
|
+
flop --network devnet faucet request <address>
|
|
119
|
+
flop --network testnet faucet request <address> --amount 25
|
|
120
|
+
flop --network mainnet network status # planned; no faucet
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Faucet requests compare the RPC and faucet `/chain` genesis hashes before
|
|
124
|
+
requesting funds. A recognized RPC conflicting with explicit `--network` is
|
|
125
|
+
rejected.
|
|
126
|
+
|
|
127
|
+
#### Agent-efficient output
|
|
128
|
+
|
|
129
|
+
Use `--output agent` for a stable, single-line JSON result with no banners,
|
|
130
|
+
emoji, indentation, or successful `doctor` checks:
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
flop --output agent miner doctor --mode tdx
|
|
134
|
+
flop --output agent validator status <address>
|
|
135
|
+
flop --output agent agent init --client codex
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Successes include `ok:true`. Failures go to stderr with a nonzero exit and a
|
|
139
|
+
compact `code`, `message`, `retryable`, and optional `next` action. `--json`
|
|
140
|
+
remains the backward-compatible pretty JSON format. Interactive processes such
|
|
141
|
+
as `launch`, `proxy`, and Hermes itself retain their application output after
|
|
142
|
+
startup; use Hermes `--dry-run` for a one-shot agent-readable launch plan.
|
|
143
|
+
|
|
144
|
+
#### Health
|
|
145
|
+
```bash
|
|
146
|
+
flop health # Human-readable
|
|
147
|
+
flop health --json # JSON output
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
#### Balance
|
|
151
|
+
```bash
|
|
152
|
+
flop balance 5Grwva8T1BQxqNJJM... # Check account balance
|
|
153
|
+
flop balance 5Grwva8... --json # JSON output
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
#### GPU Detection
|
|
157
|
+
```bash
|
|
158
|
+
flop gpu # Detect local GPUs
|
|
159
|
+
flop gpu --json # JSON output
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
#### Declared GPU inventory
|
|
163
|
+
```bash
|
|
164
|
+
nvidia-smi --query-gpu=name,memory.total --format=csv,noheader,nounits > gpus.csv
|
|
165
|
+
flop --keystore miner.json --password-env FLOP_KEY_PASSWORD miner declare-gpu --nvidia-smi gpus.csv
|
|
166
|
+
flop miner declare-gpu --detect --dry-run # on the GPU host itself; prints the remark only
|
|
167
|
+
flop --keystore miner.json --password-env FLOP_KEY_PASSWORD miner declare-gpu --retract # withdraw it
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
A registered miner publishes the GPUs it runs as a signed `flop.gpu-inventory.v1` remark (format:
|
|
171
|
+
`docs/design/gpu-inventory-remark.md` in the FLOP repository), so explorers can show its hardware. It is
|
|
172
|
+
self-reported and display-only: calibration caps, SKU ceilings and rewards never read it. The CLI
|
|
173
|
+
image cannot run the host's `nvidia-smi`, so pass its output with `--nvidia-smi` (`-` reads stdin).
|
|
174
|
+
|
|
175
|
+
#### Stake Info
|
|
176
|
+
```bash
|
|
177
|
+
flop info 5Grwva8... # Get miner stake info
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
#### Session Keys
|
|
181
|
+
```bash
|
|
182
|
+
flop session create --delegate <address> --daily-cap 50 --tx-limit 5
|
|
183
|
+
flop session list --owner <address>
|
|
184
|
+
flop --signer <DELEGATE-URI> chat --session-owner <OWNER> "hello"
|
|
185
|
+
flop --signer <DELEGATE-URI> proxy --session-owner <OWNER>
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Session inference checks activity, expiry, and per-tx/daily/lifetime budgets,
|
|
189
|
+
then submits the HTLC through `executeViaSession`. `chat` persists conversation
|
|
190
|
+
IDs and supports `--conversation`, `--history`, and `--delete`.
|
|
191
|
+
|
|
192
|
+
#### Named-miner inference
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
flop --network devnet --keystore agent.json --password-env FLOP_KEY_PASSWORD \
|
|
196
|
+
session run --miner MINER_SS58 --model qwen/qwen2.5-0.5b-instruct \
|
|
197
|
+
--endpoint MINER_HTTPS_URL --prompt 'Reply OK.' --max-flop 0.01 --max-tokens 8 --json
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
The completion limit defaults to 256 tokens. `--max-tokens` must be a positive safe
|
|
201
|
+
integer; `--max-flop` bounds escrow separately. JSON includes `finish_reason` and
|
|
202
|
+
`completion_tokens`; `length` means the response reached its token limit. The turn
|
|
203
|
+
deadline remains 60 seconds, so large token limits or slow inference can still time
|
|
204
|
+
out and follow normal channel recovery. Settlement separately waits for the miner's
|
|
205
|
+
on-chain calibrated allowance; faster inference does not bypass that limit. Legacy miners may require
|
|
206
|
+
`--auth-token-env MINER_SESSION_BEARER`.
|
|
207
|
+
|
|
208
|
+
#### Models
|
|
209
|
+
|
|
210
|
+
```bash
|
|
211
|
+
flop model list
|
|
212
|
+
flop model get <hash-or-name> --precision FP16
|
|
213
|
+
flop model fetch <hash-or-name> --output-dir ./weights
|
|
214
|
+
flop model fetch <hash> --source hf:org/repo --precision INT8
|
|
215
|
+
flop --signer <PUBLISHER> model upload --model-hash <hash> --path ./weights
|
|
216
|
+
BASE=http://miner:8000 DECODE_POLICY_HASH=0x<hash> \
|
|
217
|
+
flop --network local model onboard --source org/model --precision BF16
|
|
218
|
+
|
|
219
|
+
# Existing-commitment recovery/advanced mode:
|
|
220
|
+
flop --signer <PUBLISHER> model upload \
|
|
221
|
+
--model-hash <hash> --commitment <0x-hash> --size <bytes>
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
Fetch accepts `hf:`, `modelscope:`, HTTPS, and `da:` sources and writes only
|
|
225
|
+
after dm-verity matches the registered root. Full upload builds the canonical
|
|
226
|
+
image, runs `da-validator submit`, registers its leased blob, and binds it.
|
|
227
|
+
Onboard additionally registers the model, mirrors, per-precision measured root,
|
|
228
|
+
and decode policy, but only after the serving endpoint passes capture replay,
|
|
229
|
+
binding rejection, and output-coherence probes. Re-running it submits no writes.
|
|
230
|
+
`--hf-repo owner/model` gives a local `--source` a Hugging Face mirror, but only
|
|
231
|
+
after that repo reproduces the measured root. Re-running with it adds the mirror
|
|
232
|
+
to an already registered model.
|
|
233
|
+
|
|
234
|
+
#### Gateway configuration
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
export MINER_GATEWAY_TOKEN='from-a-secret-manager'
|
|
238
|
+
flop gateway allowlist \
|
|
239
|
+
--miner https://miner.example \
|
|
240
|
+
--network devnet \
|
|
241
|
+
--auth-token-env MINER_GATEWAY_TOKEN \
|
|
242
|
+
--attestation ./gateway-attestation.json \
|
|
243
|
+
--json
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
The command emits ready-to-use `GATEWAY_SESSION_ALLOWLIST` and
|
|
247
|
+
`GATEWAY_MODEL_CATALOG` string values. The selected network supplies the RPC
|
|
248
|
+
default. It anonymously probes `/session/info` first to require bearer auth,
|
|
249
|
+
then checks every advertised identity field against `model-registry`, including
|
|
250
|
+
the measured root and decode-policy allowlist, and checks the miner's calibration
|
|
251
|
+
against the finalized `hw-calibration` snapshot.
|
|
252
|
+
|
|
253
|
+
The attestation file uses `schema_version: "flop.gateway-attestation.v1"` and
|
|
254
|
+
contains `broker` limits, `deployment` evidence, and `catalog` evidence. The
|
|
255
|
+
catalog block is a `CanonicalModelRecord` without the generated identity fields
|
|
256
|
+
or `prices`; it carries one `price` snapshot instead. Deployment
|
|
257
|
+
`observedAt`/`expiresAt`, catalog price validity, and feature conformance are
|
|
258
|
+
used unchanged. Expired evidence is refused rather than refreshed.
|
|
259
|
+
|
|
260
|
+
```bash
|
|
261
|
+
# GATEWAY_SESSION_ALLOWLIST / GATEWAY_MODEL_CATALOG hold the gateway's own values.
|
|
262
|
+
export GPUAI_API_KEY='from-a-secret-manager'
|
|
263
|
+
export GATEWAY_RENEWER_SIGNER_URI='dedicated funded account, not the broker signer'
|
|
264
|
+
flop --network devnet gateway renew \
|
|
265
|
+
--allowlist-env GATEWAY_SESSION_ALLOWLIST \
|
|
266
|
+
--catalog-env GATEWAY_MODEL_CATALOG --catalog-pricing chain \
|
|
267
|
+
--provider-key-env GPUAI_API_KEY \
|
|
268
|
+
--probe-signer-env GATEWAY_RENEWER_SIGNER_URI --probe-escrow 1 \
|
|
269
|
+
--out /opt/flop/gateway-evidence/gateway-evidence.json
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
`gateway renew` re-makes that evidence instead of re-stamping it, and writes
|
|
273
|
+
the file the gateway hot-reloads as `GATEWAY_EVIDENCE_FILE`. A miner's
|
|
274
|
+
deployment is renewed only when GPU.ai still reports the instance named in
|
|
275
|
+
`deployment.source` (`operator-observed:gpu.ai/<instance> <region> <gpu>`,
|
|
276
|
+
optionally followed by a `(label)`) as `running` in that region on that GPU. The
|
|
277
|
+
GPU is GPU.ai's identifier (`rtx_a6000`) or its name in GPU.ai's GPU type table
|
|
278
|
+
(`RTX A6000`, with or without `NVIDIA`); any other name is not renewed. A
|
|
279
|
+
tailnet-hosted miner (`operator-observed:tailscale/<host> egress <ipv4> AS<n>`,
|
|
280
|
+
optionally followed by the network's name and a `(label)`) is renewed only while the
|
|
281
|
+
host's tailscaled (`--tailscale-socket`) sees exactly one node of that name online,
|
|
282
|
+
tagged `tag:miner`, on a direct path from that egress address; the country stamped
|
|
283
|
+
from that address therefore still holds. Its authenticated `/session/info` must also still advertise the pinned address,
|
|
284
|
+
enclave key, and identity that the
|
|
285
|
+
finalized chain still admits. A record's `tools` conformance is renewed only by
|
|
286
|
+
a real compute-channel turn, paid from the probe signer's escrow, whose signed
|
|
287
|
+
frames carry a `lookup` tool call with a JSON `query`. Each renewal keeps its
|
|
288
|
+
declared window length. Every other claimed feature has no probe yet and lapses.
|
|
289
|
+
Whatever is not renewed is left out of the file and lapses at its declared
|
|
290
|
+
expiry. The command exits 1 when anything lapses and never prints the allowlist.
|
|
291
|
+
Before each probe it requires one `--probe-escrow` free on the probe signer at the
|
|
292
|
+
finalized head. When the signer holds less, no further probe runs, and stderr says
|
|
293
|
+
`gateway renew: PROBE SIGNER UNDERFUNDED: …`.
|
|
294
|
+
The GPU.ai single-instance response shape (`status`, `region`, `gpu_type`) is
|
|
295
|
+
assumed from the pricing and create APIs, so watch the first run.
|
|
296
|
+
|
|
297
|
+
An operator can instead publish an already settled owner-requested tools qualification
|
|
298
|
+
without creating another probe or using the direct renewer's signer/provider credentials:
|
|
299
|
+
|
|
300
|
+
```bash
|
|
301
|
+
flop --network devnet gateway renew \
|
|
302
|
+
--catalog-env GATEWAY_MODEL_CATALOG --catalog-pricing chain \
|
|
303
|
+
--qualification-receipt ./settled-tools-qualification.json \
|
|
304
|
+
--qualification-receipt-sha256 "$QUALIFICATION_RECEIPT_SHA256" \
|
|
305
|
+
--out /opt/flop/gateway-evidence/gateway-evidence.json
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
The hash must identify the exact immutable receipt bytes. Receipt-only mode rejects the
|
|
309
|
+
direct-probe options. It verifies the original owner/resident/purpose envelope, signed
|
|
310
|
+
turn/prefix/ACK and canonical finalized positive settlement before appending one pass to
|
|
311
|
+
the existing evidence file. It preserves unrelated deployments and conformance entries,
|
|
312
|
+
keeps the proof-bound original probe time and existing declared window, and refuses a
|
|
313
|
+
conflicting re-publication. An identical receipt is a no-op. Concurrent `gateway renew`
|
|
314
|
+
commands using this version take an exclusive publication lock; a conflicting writer
|
|
315
|
+
fails rather than replacing its contents. Older or unrelated writers must be coordinated
|
|
316
|
+
separately. Receipt-only publication retains only this producer's latest unexpired pass
|
|
317
|
+
per exact model/feature identity, preserving its original times and all unrelated evidence.
|
|
318
|
+
A process killed while writing can leave `OUT.lock`; confirm that writer has stopped before
|
|
319
|
+
manually recovering that lock, and never remove another active writer's lock.
|
|
320
|
+
No fresh inference, escrow, signature submission or automatic publication by
|
|
321
|
+
the qualification endpoint occurs. Ordinary chat continues to require fresh tools
|
|
322
|
+
admission; a qualification request is not permission to run arbitrary stale-tools chat.
|
|
323
|
+
|
|
324
|
+
#### Keys, hardware, multisig, and air-gapped signing
|
|
325
|
+
|
|
326
|
+
```bash
|
|
327
|
+
export FLOP_KEY_PASSWORD='from-a-secret-manager'
|
|
328
|
+
flop keys generate --name treasury --out treasury.json \
|
|
329
|
+
--password-env FLOP_KEY_PASSWORD
|
|
330
|
+
export FLOP_IMPORTED_SECRET='mnemonic from a secret manager'
|
|
331
|
+
flop keys import --secret-env FLOP_IMPORTED_SECRET --out imported.json \
|
|
332
|
+
--password-env FLOP_KEY_PASSWORD
|
|
333
|
+
flop keys export treasury.json --source-password-env FLOP_KEY_PASSWORD \
|
|
334
|
+
--out treasury-backup.json --password-env FLOP_BACKUP_PASSWORD
|
|
335
|
+
flop keys inspect treasury.json
|
|
336
|
+
flop keys hardware
|
|
337
|
+
|
|
338
|
+
flop multisig address --threshold 2 --signatory <A> <B> <C>
|
|
339
|
+
flop --keystore treasury.json --password-env FLOP_KEY_PASSWORD \
|
|
340
|
+
multisig propose --threshold 2 --other <B> <C> --call <0x-call>
|
|
341
|
+
flop multisig list --account <MULTISIG>
|
|
342
|
+
|
|
343
|
+
flop tx build --address <ADDRESS> --call <0x-call> \
|
|
344
|
+
--out unsigned.json --qr
|
|
345
|
+
flop tx broadcast unsigned.json --signature <0x-multisignature>
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
`tx build` pins genesis, runtime, transaction version, and nonce. Broadcast
|
|
349
|
+
rejects drift. Terminal QR uses optional `qrencode`; the JSON envelope works
|
|
350
|
+
with Polkadot Vault, hardware wallets, HSM/MPC custody, or other detached
|
|
351
|
+
signers.
|
|
352
|
+
|
|
353
|
+
#### Wallets
|
|
354
|
+
```bash
|
|
355
|
+
flop wallet agent create <agent-address> --daily-cap 50 --tx-limit 5
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
#### Shared devnet agent credential
|
|
359
|
+
Provision one key for any supported agent client without launching Hermes:
|
|
360
|
+
```bash
|
|
361
|
+
flop --network devnet agent credential # path, live model, quota; no bearer
|
|
362
|
+
flop --network devnet agent credential --json # non-secret metadata
|
|
363
|
+
flop --network devnet agent credential --print-key # secret on stdout for local auth helpers
|
|
364
|
+
flop --network devnet agent credential --tailnet # private lane for approved Tailscale users
|
|
365
|
+
```
|
|
366
|
+
The command requires explicit `--network devnet`. By default it enrolls at the
|
|
367
|
+
public gateway `https://api.flop.network` with a wallet signature. On first use
|
|
368
|
+
it creates a local sr25519 account in `~/.flop/devnet-enroll-wallet.json`
|
|
369
|
+
(unencrypted, devnet only, mode 0600; its secret is never printed). If that
|
|
370
|
+
account holds less than 1 FLOP, it requests a grant from
|
|
371
|
+
`https://faucet.flop.network/fund` and waits for the grant to finalize on
|
|
372
|
+
`wss://rpc.devnet.flop.network` (`--rpc` overrides). It then signs the
|
|
373
|
+
gateway's single-use challenge. The key is cached in
|
|
374
|
+
`~/.flop/devnet-wallet-agent-key.json`. The operator must explicitly fund and configure the allowance; the recommended
|
|
375
|
+
casual-use grant is 20,000 devnet FLOP, scoped to the exact model returned by
|
|
376
|
+
enrollment, and expires within 24 hours. Re-enrolling
|
|
377
|
+
rotates the bearer but never renews quota or expiry.
|
|
378
|
+
|
|
379
|
+
`--tailnet` keeps the private lane for approved Tailscale users. It enrolls at
|
|
380
|
+
`http://gateway.ts.flop.network:3201/enroll` and gives a seven-day allowance,
|
|
381
|
+
cached in `~/.flop/devnet-agent-key.json` and shared with the Hermes provider.
|
|
382
|
+
Both caches are mode 0600 in a mode-0700 directory on POSIX systems. A `.lock`
|
|
383
|
+
directory per cache serializes enrollment across local clients. The
|
|
384
|
+
`--print-key` form is deliberately explicit; redirect or consume it privately
|
|
385
|
+
rather than recording terminal output. A stale `.lock` directory after a crash
|
|
386
|
+
can be removed only after confirming no enrollment is running.
|
|
387
|
+
|
|
388
|
+
`flop --network devnet agent init` and `agent doctor` use the public
|
|
389
|
+
`https://mcp.flop.network/mcp` read-only service by default; pass `--mcp-url`
|
|
390
|
+
to target another verified endpoint.
|
|
391
|
+
|
|
392
|
+
#### Hermes Desktop
|
|
393
|
+
The public native provider (`sdk/hermes_public`) is bundled with the
|
|
394
|
+
standalone launcher 0.4.5. Use `flop hermes plugin install` in an isolated
|
|
395
|
+
`HERMES_HOME` after `hermes pm repair`, then `hermes auth add flop-public`, `hermes model` and
|
|
396
|
+
`hermes desktop`. The separate private provider (`sdk/hermes_native`)
|
|
397
|
+
requires an approved Tailscale identity and FLOP repository access.
|
|
398
|
+
Follow the public native setup guide (`docs/integrations/hermes-public-launcher.md`,
|
|
399
|
+
"Native public provider") for the recommended public route. The full CLI also retains the private tailnet lane:
|
|
400
|
+
```bash
|
|
401
|
+
flop --network devnet hermes desktop --dry-run --json # inspect without provisioning
|
|
402
|
+
flop --network devnet hermes desktop --gateway http://gateway.ts.flop.network # tailnet lane
|
|
403
|
+
```
|
|
404
|
+
From a source checkout, replace `flop` with `node sdk/cli/dist/cli.js` after
|
|
405
|
+
the build above.
|
|
406
|
+
The alternate public hosted launcher requires managed-home preparation described
|
|
407
|
+
in the public guide; an immediate Desktop launch is not qualified. With the
|
|
408
|
+
tailnet `--gateway`, the devnet operator must approve your Tailscale user ID
|
|
409
|
+
first. The CLI then obtains a seven-day, 25 FLOP model-scoped allowance and
|
|
410
|
+
stores the key in `~/.flop/devnet-agent-key.json` (mode 0600). Later launches
|
|
411
|
+
and other local agent clients check and reuse the cached key.
|
|
412
|
+
If the local key is lost or rejected, enrollment rotates the bearer while preserving
|
|
413
|
+
its spent amount and expiry. Exhausted, expired, and revoked allowances require an
|
|
414
|
+
operator to renew or reapprove them. Normal CLI output does not print the key.
|
|
415
|
+
|
|
416
|
+
Without `--network devnet`, the command starts the embedded signer proxy as before:
|
|
417
|
+
```bash
|
|
418
|
+
flop hermes desktop # embedded proxy + launch Hermes
|
|
419
|
+
flop --signer //Bob hermes desktop # settle under //Bob
|
|
420
|
+
flop hermes desktop --model llama-3-8b-instruct --max-flop 10 --max-tokens 4096
|
|
421
|
+
flop hermes desktop --proxy-port 1234 # embedded proxy on a custom port
|
|
422
|
+
flop --network devnet --signer "$FLOP_SIGNER" hermes desktop --proxy # funded signer
|
|
423
|
+
flop hermes desktop --configure # also persist via `hermes config set`
|
|
424
|
+
flop hermes desktop --no-proxy \
|
|
425
|
+
--gateway http://gateway.ts.flop.network --model "$FLOP_MODEL"
|
|
426
|
+
flop hermes desktop --dry-run --json # print resolved env/launch plan, don't launch
|
|
427
|
+
```
|
|
428
|
+
It wires Hermes to the embedded proxy via the env vars Hermes reads for a custom
|
|
429
|
+
OpenAI-compatible endpoint — `OPENAI_BASE_URL` (→ proxy `/v1`), `OPENAI_API_KEY`,
|
|
430
|
+
and `HERMES_INFERENCE_MODEL` (`api_mode` auto-detects `chat_completions`) — plus
|
|
431
|
+
`FLOP_WS_URL`/`FLOP_SIGNER` for the `@flop-labs/hermes-plugin`. `--configure`
|
|
432
|
+
additionally persists the wiring through the real `hermes config set` CLI
|
|
433
|
+
(`model.provider=custom`, `model.base_url`, `model.api_mode`, `model.default`).
|
|
434
|
+
Requires the Hermes binary (`hermes-desktop` or `hermes`) on `PATH`; use
|
|
435
|
+
`--dry-run` to inspect without it. A custom hosted `--gateway` requires
|
|
436
|
+
`FLOP_API_KEY` supplied privately and an explicit `--model` from the live
|
|
437
|
+
catalog. The CLI checks gateway health, model availability, and key validity
|
|
438
|
+
before launching. The private devnet gateway is reachable only from the FLOP
|
|
439
|
+
tailnet.
|
|
440
|
+
|
|
441
|
+
#### Local OpenAI Proxy
|
|
442
|
+
Expose a local OpenAI-compatible API (like LM Studio / Ollama's local server)
|
|
443
|
+
where **every request is submitted and settled on-chain under your signer**.
|
|
444
|
+
The proxy estimates G_n, submits the PoUI task, waits for a TEE miner to settle
|
|
445
|
+
it, then returns the result — all behind the OpenAI REST schema:
|
|
446
|
+
```bash
|
|
447
|
+
flop proxy # http://127.0.0.1:3201/v1
|
|
448
|
+
flop --signer //Bob proxy --max-flop 10
|
|
449
|
+
flop proxy --port 1234 --host 0.0.0.0 # expose beyond localhost
|
|
450
|
+
```
|
|
451
|
+
| Endpoint | Purpose |
|
|
452
|
+
|----------|---------|
|
|
453
|
+
| `POST /v1/chat/completions` | Chat inference (OpenAI-compatible), `stream: true` supported |
|
|
454
|
+
| `POST /v1/completions` | Text completion, `stream: true` supported |
|
|
455
|
+
| `GET /v1/models` | List models (live from the payload gateway, falls back to defaults) |
|
|
456
|
+
| `GET /v1/models/{id}` | Retrieve a single model |
|
|
457
|
+
| `POST /v1/embeddings` | Embeddings, computed **locally** (no chain) — see below |
|
|
458
|
+
| `GET /health` | Liveness |
|
|
459
|
+
| `OPTIONS *` | CORS preflight (permissive, for browser/Electron clients) |
|
|
460
|
+
|
|
461
|
+
**Embeddings** are a cheap, high-frequency RAG primitive and don't need on-chain
|
|
462
|
+
settlement, so the proxy computes them **locally** with a small embedding model
|
|
463
|
+
(default `Xenova/all-MiniLM-L6-v2`, L2-normalized output like Ollama's
|
|
464
|
+
`/api/embed`). This needs the optional runtime dependency — install once:
|
|
465
|
+
```bash
|
|
466
|
+
pnpm add @huggingface/transformers
|
|
467
|
+
```
|
|
468
|
+
Without it, `/v1/embeddings` returns `501` with this hint (chat/completions are
|
|
469
|
+
unaffected). Override the model with `--embedding-model <hf-id>`.
|
|
470
|
+
|
|
471
|
+
**Streaming:** `stream: true` returns OpenAI SSE chunks (`data: {…}` … `data: [DONE]`),
|
|
472
|
+
incl. an optional usage chunk via `stream_options.include_usage`. FLOP settles a
|
|
473
|
+
task atomically, so this is *settle-then-stream*: the result is awaited, then
|
|
474
|
+
emitted as chunks (latency-to-first-token = settlement time), not incremental
|
|
475
|
+
miner generation.
|
|
476
|
+
|
|
477
|
+
**Models:** `/v1/models` reflects the payload gateway's registry
|
|
478
|
+
(`<payload-gateway>/v1/models`), falling back to the built-in defaults if it's
|
|
479
|
+
unreachable.
|
|
480
|
+
|
|
481
|
+
Options: `--port` (3201), `--host` (127.0.0.1), `--payload-gateway`
|
|
482
|
+
(off-chain prompt/result data plane, default `http://localhost:3200`),
|
|
483
|
+
`--model`, `--max-tokens` (default 2048), `--max-flop`. Uses global
|
|
484
|
+
`--rpc`/`--signer`. Point any OpenAI client at it via
|
|
485
|
+
`OPENAI_BASE_URL=http://127.0.0.1:3201/v1`.
|
|
486
|
+
|
|
487
|
+
## Architecture
|
|
488
|
+
|
|
489
|
+
- Built with Commander.js
|
|
490
|
+
- Uses local SDK via `"@flop-labs/sdk": "file:../typescript"`
|
|
491
|
+
- TypeScript with ES modules, compiled via `tsc`
|
|
492
|
+
- All commands use `FlopClient.create()` from the SDK with `--rpc` and `--signer` global options
|
|
493
|
+
- Role groups reuse existing launch, proxy, key, wallet, session, staking, TDX,
|
|
494
|
+
and provider workflows rather than introducing parallel implementations.
|
|
495
|
+
|
|
496
|
+
Operator images: use `ghcr.io/flop-labs/flop-core/cli:stable` (minimum 0.1.172),
|
|
497
|
+
`ghcr.io/flop-labs/flop-core/miner-worker:stable` (minimum 0.1.172), and
|
|
498
|
+
`ghcr.io/flop-labs/flop-core/miner-vllm-toploc:stable` (minimum 0.1.172).
|
|
499
|
+
For a reproducible pin, use the version and digest in [releases.json](https://flop.network/releases.json).
|
|
500
|
+
`just miner-pack /tmp/flop-miner-pack` copies that manifest and fills the worker and backend image pins.
|