@candledottv/cli 0.13.23 → 0.13.24
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/README.md +23 -16
- package/dist/index.js +53 -12
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @candledottv/cli
|
|
2
2
|
|
|
3
|
-
The Candle CLI (current version 0.13.
|
|
3
|
+
The Candle CLI (current version 0.13.23): authorize a device from your browser, keep your own keys
|
|
4
4
|
in an encrypted vault on this machine, hand an agent a TEE wallet it can trade, and manage API
|
|
5
5
|
keys, wallets, and setup health from the terminal. Zero runtime dependencies; the whole thing is
|
|
6
6
|
one self-contained `dist/index.js` that runs under plain Node.
|
|
@@ -109,10 +109,10 @@ chosen words from your saved copy. Clear your terminal's scrollback too: the CLI
|
|
|
109
109
|
| `candle keys limits <prefix> <asset>=<raw> [<asset>=<raw> ...]` | Sets a key's per-asset caps (`sol`, `usdc`, `cndl`, `eth`, `usdg`, in base units per transaction) with the profile's own API key. It can only tighten; raising or removing a cap is `LOOSEN_REQUIRES_SESSION`, and the owner does that in the web key manager. A device token cannot set these caps. |
|
|
110
110
|
| `candle keys update <prefix\|label> --embedded-wallet allow\|deny [--yes]`, `candle keys self embedded-wallet deny` | Allow or deny a key the account's embedded wallet, with the device token (allowing needs the prefix typed back at a terminal). `self embedded-wallet deny` lets the profile's own key give it up with no prompt; a key can never allow itself. |
|
|
111
111
|
| `candle keys signer approve <code> --key <prefix\|label> [--reject]`, `candle keys signer move <prefix\|label> [--to-key <prefix\|label>]` | Key signers for bots on a different machine from the vault. `approve` accepts (or rejects) a key's signer request with the device token, after you type the full fingerprint the trading machine printed. `move`, on the machine holding a wallet's current signer, moves every wallet on the key onto its active signer; `--to-key` moves a revoked key's wallets to a live key. |
|
|
112
|
-
| `candle keys stop <prefix>` | Pause one key using the device token. Its requests are refused with `PROFILE_PAUSED` until resumed; the key and its local credential are kept. Repeating the command succeeds. |
|
|
113
|
-
| `candle keys resume <prefix>` | Resume a stopped key using the device token. Repeating the command succeeds. An API key cannot stop or resume itself; a revoked key cannot be resumed. |
|
|
112
|
+
| `candle keys stop <prefix\|label>` | Pause one key using the device token. Its requests are refused with `PROFILE_PAUSED` until resumed; the key and its local credential are kept. Repeating the command succeeds. |
|
|
113
|
+
| `candle keys resume <prefix\|label>` | Resume a stopped key using the device token. Repeating the command succeeds. An API key cannot stop or resume itself; a revoked key cannot be resumed. |
|
|
114
114
|
| `candle keys rotate <prefix\|label> ([--grace <duration> \| --now] [--force] [--yes] [--idempotency-key <key>] \| --finish)` | Gives a key a new secret and keeps its prefix, label, access, limits, wallets and history. The old secret keeps working through `--grace` (default `1h`, at most `24h`) or stops at once with `--now`; `--finish` ends an open window early. When the key is the CLI's own, the new secret replaces it in the keychain. A copy in `CANDLE_API_KEY_FILE`, `CANDLE_API_KEY` or anywhere else must be updated by hand before the window ends; `candle doctor` warns while the old secret is in use. Each run sends an `Idempotency-Key` and retries a dropped connection once; if there is still no answer, rerun with the printed `--idempotency-key` to recover the first secret. |
|
|
115
|
-
| `candle keys revoke <prefix>` | Revokes an API key by prefix. Revoking the CLI's own stored key also clears it locally. A prefix can start with `-`; the key commands accept it as typed, and `--` (`candle keys revoke -- -QVeHyie`) ends the options on any command. |
|
|
115
|
+
| `candle keys revoke <prefix\|label>` | Revokes an API key by prefix or label. A label resolves to its prefix the way `keys access` does; two live keys with the same label refuse and list their prefixes. Revoking the CLI's own stored key also clears it locally. A prefix can start with `-`; the key commands accept it as typed, and `--` (`candle keys revoke -- -QVeHyie`) ends the options on any command. |
|
|
116
116
|
| `candle keys wallets <prefix>`, `keys wallets set <prefix> --wallets <id,id>`, `keys wallets scope <prefix> --scope all\|selected` | Each key is an agent profile with its own wallet set: list it, replace it, or limit the profile to its assigned wallets. |
|
|
117
117
|
| `candle wallets` (alias `candle wallet`) | Shows the account's embedded (launch) wallets and any linked wallets, using the API key, with a `Signer` column saying whether this machine holds each linked wallet's signing key and a `Trusted` column saying whether it is yours (linked while signed in, or marked with `trust`). It links and revokes; it never generates or prints a key, which the vault now derives. |
|
|
118
118
|
| `candle wallets import --chain solana\|evm`, `wallets revoke <wallet-id>` | Link a wallet you own (key from `--key-file` or a hidden prompt, sealed to Privy before it leaves the machine), or unlink one. |
|
|
@@ -122,7 +122,7 @@ chosen words from your saved copy. Clear your terminal's scrollback too: the CLI
|
|
|
122
122
|
| `candle wallets allow-launch\|disallow-launch <label\|address\|id\|prefix*>...` | Deprecated. Where the server has `TEE_LAUNCH_BY_SCOPE_ENABLED` on, a key's `launch:write` decides TEE launches: `allow-launch` saves the value and exits 0, and `disallow-launch` saves it, prints the server's `ALLOW_LAUNCH_NOT_ENFORCED` message and exits 1, because no launch is stopped. A server with the switch off still lets TEE wallets pay for a launch (`candle launch`) only after `allow-launch`. Owner only, over the device token; the screen shows each wallet's label, address and bound key before a typed confirm. `disallow-launch --yes` skips the confirm. |
|
|
123
123
|
| `candle wallets close-empty [--wallet embedded\|<tee address\|label>] [--keep <mint>]... [--client-trade-id <id>] [--preview] [--yes]` | Closes a wallet's empty token accounts and returns their rent to it, after a preview: the embedded wallet (`transfer:write`), or a Solana TEE wallet bound to the key (`swap:write`), whose close transactions Candle builds, this machine checks and the key signer approves. `--preview` prints what would close — the whole preview as one JSON document on stdout under `--json` — and closes, signs and prompts nothing; headless without `--yes`, the `CONFIRMATION_REQUIRED` refusal carries that same preview under `details`. |
|
|
124
124
|
| `candle vault init\|status\|list\|new-key\|rename\|phrase show\|restore\|reconcile-exposure` | The encrypted local vault, `vault.enc` (Tier 1). `init` creates it with a passphrase factor and a 24-word recovery phrase (and no key), labels its read-back derivation as verification, and leaves security-key enrollment to the separate optional `candle vault enroll security-key` command; `new-key` derives a key inside it (`--count`, `--labels-from <file>` for many under one unlock), `list [filter] [--balances]` shows one line per key, `rename` changes a label only, `phrase show` displays the phrase on a terminal (never in `--json`, a log or a pipe), and `restore --phrase` rebuilds the derived keys on another machine with a new passphrase (`--count`, `--tee-count`, `--external-count`, `--evm-count` and `--evm-tee-count` for EVM keys and Hood TEE wallets, or a Solana gap scan with `--rpc-url`); a restored vault never allocates new keys. `reconcile-exposure` re-reads the account and adds exposure records, clearing nothing. No key ever leaves the vault to reach Candle. See [CLI custody](https://docs.candle.tv/developers/cli-custody). |
|
|
125
|
-
| `candle vault factor list\|add passphrase\|add security-key\|add touch-id\|add passkey\|remove` (or `vault enroll <kind>`), `vault backup --to <path>\|icloud`, `vault verify-backup <path>` | What can open the vault, and proving a copy of it works: `backup` verifies the copy in full before reporting (a copy is sealed, keeping only the passphrase and security-key envelopes, unless it goes to a recognised local disk or removable drive, so a cloud folder and any path the CLI cannot place are both sealed unless `--accept-shared-domain` is passed), and `verify-backup` re-checks an existing one against this vault's key and address set. `add security-key` enrolls a FIDO2 security key (CTAP2 `hmac-secret`, user-verified with the key's PIN or biometric) through the bundled `candle-fido2` helper (`--install-helper` fetches and verifies this release's helper first); one key is not a recoverable factor, two keys are a pair, an enrolled key can authorize adding another, and the passphrase stays the recovery floor. `add touch-id`
|
|
125
|
+
| `candle vault factor list\|add passphrase\|add security-key\|add touch-id\|add passkey\|remove` (or `vault enroll <kind>`), `vault backup --to <path>\|icloud`, `vault verify-backup <path>` | What can open the vault, and proving a copy of it works: `backup` verifies the copy in full before reporting (a copy is sealed, keeping only the passphrase and security-key envelopes, unless it goes to a recognised local disk or removable drive, so a cloud folder and any path the CLI cannot place are both sealed unless `--accept-shared-domain` is passed), and `verify-backup` re-checks an existing one against this vault's key and address set. `add security-key` enrolls a FIDO2 security key (CTAP2 `hmac-secret`, user-verified with the key's PIN or biometric) through the bundled `candle-fido2` helper (`--install-helper` fetches and verifies this release's helper first); one key is not a recoverable factor, two keys are a pair, an enrolled key can authorize adding another, and the passphrase stays the recovery floor. `add touch-id` is available in 0.13.23 on supported Macs with the signed `candle-enclave.app`; npm ships no native helper. `add passkey` remains unavailable (`VAULT_FACTOR_UNSUPPORTED_ON_PLATFORM`): the shipped helper lacks the associated-domain entitlement. Every vault command then takes `--factor <id\|passphrase\|security-key\|touch-id>` to say which envelope opens it and `--device <id>` to name the key when several are attached. |
|
|
126
126
|
| `candle vault transfer\|promote\|promote-batch\|fund\|demote\|export-key` | Moving value and authority. `transfer` and `fund` sign locally after showing the decoded transaction (`transfer` from a vault key or a promoted TEE wallet, which warns when an agent may be trading it and reports the finalized transfer to Candle's history; `fund` reaches a TEE wallet from its pinned vault key, or an external wallet, with no `--yes`; both verify once, at the unlock, which names the send, then show the destination grouped in fours and take a typed `confirm`); `promote --from <cold label>` derives a fresh TEE wallet pinned to that key (an EVM vault key becomes a Hood TEE wallet), shows the pinned vault address and asks you to type `confirm` to promote the new wallet (promotion moves no funds), `promote --in-place <label> --sweep-to <cold label>` promotes a key at its own address after a typed warning, `promote-batch --pairs-from <file>` does many in place under one unlock, `--to-key` binds the result to another of your keys, and `demote` (disable then sweep; `--emergency` sweeps even when the stop request fails) sends it back to its pinned vault; `export-key` is the one ceremony that writes a single private key to a file you name. `demote` takes several addresses, or `--all --empty` for every Solana TEE wallet with nothing left to sweep, under one unlock and one typed `confirm` (`--yes` skips it), with a result line per wallet and one `--json` document. |
|
|
127
127
|
| `candle external new\|list\|sweep` | External wallets for outside tools: keys on the vault's third branch (`m/44'/501'/n'/2'`), never delegated to Privy and never registered with Candle. `new` allocates one (and moves the vault to format version 3; refused in a restored vault), `list` shows them, and `sweep <external> --to <vault>` sends everything back to a named vault key, signed locally, confirmed by a typed `confirm` after the vault key's address is shown. See [Bring your own services](https://docs.candle.tv/developers/cli#bring-your-own-services). |
|
|
128
128
|
| `candle sign [--file <path>] --wallet <external>... [--broadcast] [--yes]`, `candle sign message --wallet <external> [--file <path>] [--yes]` | The generic signer: a base64 transaction any tool built, legacy or v0, decoded (lookup tables resolved) and simulated over your own RPC before it is displayed and signed with an external wallet only. A vault key, a TEE wallet or an unnamed signer is refused; a failing simulation is refused with no override; `--yes` skips the confirmation prompt and nothing else. `sign message` signs the exact bytes of a file or of stdin. |
|
|
@@ -294,22 +294,28 @@ The npm package ships no native helper: there the factor is refused with `VAULT_
|
|
|
294
294
|
until a release build's `candle-fido2` is installed and `CANDLE_FIDO2_HELPER` points at it. No
|
|
295
295
|
other factor is ever substituted for one that is refused.
|
|
296
296
|
|
|
297
|
-
The Touch ID factor (`candle vault factor add touch-id
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
297
|
+
The Touch ID factor (`candle vault factor add touch-id`) is available in
|
|
298
|
+
[0.13.23](https://github.com/candledottv/cli/releases/tag/cli-v0.13.23) on Apple silicon Macs and Intel
|
|
299
|
+
Macs with a T2 chip. It needs the signed `candle-enclave.app` helper, which the darwin tarball,
|
|
300
|
+
the installer script and Homebrew place beside `candle`. The npm package ships no native helper:
|
|
301
|
+
install the matching signed bundle and set `CANDLE_ENCLAVE_HELPER`, or the command refuses with
|
|
302
|
+
`VAULT_HELPER_MISSING`. An untrusted helper is `VAULT_HELPER_UNTRUSTED`; Linux and a Mac without
|
|
303
|
+
a Secure Enclave are `VAULT_FACTOR_UNSUPPORTED_ON_PLATFORM`. The CLI verifies the
|
|
301
304
|
helper's code signature with `/usr/bin/codesign` before trusting it, and `CANDLE_ENCLAVE_HELPER`
|
|
302
305
|
points at a bundle elsewhere. The factor opens the vault on one Mac only and is never a recovery
|
|
303
306
|
factor; the passphrase remains the recovery floor.
|
|
304
307
|
|
|
305
|
-
The synced passkey factor (`candle vault factor add passkey
|
|
306
|
-
|
|
308
|
+
The synced passkey factor (`candle vault factor add passkey`) remains unavailable in 0.13.23:
|
|
309
|
+
the shipped helper deliberately omits `webcredentials:cli.candle.tv`, so it refuses with
|
|
310
|
+
`VAULT_FACTOR_UNSUPPORTED_ON_PLATFORM` and explains the missing entitlement. Passkey enrollment
|
|
311
|
+
has not yet been checked on real Macs. A future release needs macOS 15 or later and the helper's
|
|
307
312
|
associated-domains entitlement for `webcredentials:cli.candle.tv` with an embedded provisioning
|
|
308
313
|
profile, plus an `apple-app-site-association` served at
|
|
309
314
|
`https://cli.candle.tv/.well-known/apple-app-site-association` (status 200, no redirect,
|
|
310
315
|
`Content-Type: application/json`, `{"webcredentials":{"apps":["<TEAM ID>.tv.candle.cli.enclave"]}}`).
|
|
311
|
-
|
|
312
|
-
|
|
316
|
+
A missing association refuses with `VAULT_FACTOR_UNAVAILABLE` before any passkey sheet and names
|
|
317
|
+
what must be served; serving it allows real enrollment when the local requirements are met.
|
|
318
|
+
The passkey follows the Apple account, so it is a recoverable factor; two are one factor,
|
|
313
319
|
and a copy of the vault is sealed (passphrase and security-key envelopes only) by default unless it goes to a
|
|
314
320
|
recognised local disk or removable drive, so that one account never holds
|
|
315
321
|
both the blob and a factor that opens it. iCloud Drive and other cloud folders are sealed for that
|
|
@@ -434,7 +440,7 @@ the profile they were migrated into.
|
|
|
434
440
|
`CANDLE_DEVICE_TOKEN` and `CANDLE_API_KEY` together mean CI needs no storage backend at all: set
|
|
435
441
|
both and every command works without ever touching a keychain or the encrypted file.
|
|
436
442
|
|
|
437
|
-
### External key files (
|
|
443
|
+
### External key files (CLI 0.13.22 and later)
|
|
438
444
|
|
|
439
445
|
A host may supply an absolute path with both raw key variables absent:
|
|
440
446
|
|
|
@@ -469,8 +475,9 @@ The key stays in private memory; it is never inserted into environment variables
|
|
|
469
475
|
config or saved files. Ordinary browser/helper/hook/keychain children retain the nonsecret path;
|
|
470
476
|
plugins keep their environment allowlist and receive neither the path nor key. This reduces
|
|
471
477
|
environment exposure, not access by root or another process with the same UID. Extended ACLs
|
|
472
|
-
are not audited.
|
|
473
|
-
|
|
478
|
+
are not audited. This is available in `candle` and the bundled `candle mcp` from CLI 0.13.22.
|
|
479
|
+
For standalone `candle-mcp` (`@candledottv/mcp`), this remains unreleased source support:
|
|
480
|
+
version 0.10.32 does not include it and needs its own next release.
|
|
474
481
|
|
|
475
482
|
## What this CLI deliberately does not do
|
|
476
483
|
|
package/dist/index.js
CHANGED
|
@@ -225,6 +225,11 @@ function ownerConfirmChallengeOf(result) {
|
|
|
225
225
|
const verificationUriComplete = str("verificationUriComplete");
|
|
226
226
|
if (!confirmId || !userCode || !verificationUriComplete)
|
|
227
227
|
return null;
|
|
228
|
+
const accountRaw = oc.account;
|
|
229
|
+
const account = accountRaw && typeof accountRaw === "object" && !Array.isArray(accountRaw) && typeof accountRaw.wallet === "string" ? {
|
|
230
|
+
wallet: accountRaw.wallet,
|
|
231
|
+
displayName: typeof accountRaw.displayName === "string" ? accountRaw.displayName : null
|
|
232
|
+
} : undefined;
|
|
228
233
|
return {
|
|
229
234
|
confirmId,
|
|
230
235
|
userCode,
|
|
@@ -234,6 +239,7 @@ function ownerConfirmChallengeOf(result) {
|
|
|
234
239
|
interval: Math.max(1, num("interval") ?? 5),
|
|
235
240
|
step: str("step") ?? "",
|
|
236
241
|
summary: str("summary") ?? "",
|
|
242
|
+
...account ? { account } : {},
|
|
237
243
|
reason: str("reason") ?? "required"
|
|
238
244
|
};
|
|
239
245
|
}
|
|
@@ -755,7 +761,7 @@ var init_terminal_theme = __esm(() => {
|
|
|
755
761
|
});
|
|
756
762
|
|
|
757
763
|
// src/version.ts
|
|
758
|
-
var CLI_VERSION = "0.13.
|
|
764
|
+
var CLI_VERSION = "0.13.24";
|
|
759
765
|
|
|
760
766
|
// src/presentation.ts
|
|
761
767
|
function terminalStyle(deps, stream, machine = false) {
|
|
@@ -47895,17 +47901,27 @@ async function keysRevoke(args, ctx) {
|
|
|
47895
47901
|
return 2;
|
|
47896
47902
|
}
|
|
47897
47903
|
if (parsed.positionals.length !== 1) {
|
|
47898
|
-
deps.stderr.write(`Usage: candle keys revoke <prefix>
|
|
47904
|
+
deps.stderr.write(`Usage: candle keys revoke <prefix|label>
|
|
47899
47905
|
`);
|
|
47900
47906
|
return 2;
|
|
47901
47907
|
}
|
|
47902
|
-
const
|
|
47908
|
+
const target = parsed.positionals[0];
|
|
47903
47909
|
await printIdentity(ctx);
|
|
47904
47910
|
const deviceToken = await resolveDeviceToken(deps, ctx.profile);
|
|
47905
47911
|
if (!deviceToken) {
|
|
47906
47912
|
writeLocalFailure(deps, NO_DEVICE_TOKEN, json);
|
|
47907
47913
|
return 1;
|
|
47908
47914
|
}
|
|
47915
|
+
const resolved = await resolveTargetKey(ctx, deviceToken, target, {
|
|
47916
|
+
codePrefix: "KEY_REVOKE",
|
|
47917
|
+
writeListFailure: (failure3) => {
|
|
47918
|
+
writeFailure(deps, failure3, { apiUrl, authType: "device" }, json);
|
|
47919
|
+
return 1;
|
|
47920
|
+
}
|
|
47921
|
+
});
|
|
47922
|
+
if (!resolved.ok)
|
|
47923
|
+
return resolved.code;
|
|
47924
|
+
const prefix = resolved.keyPrefix;
|
|
47909
47925
|
const result2 = await apiRequest(`${KEYS_PATH3}/${encodeURIComponent(prefix)}`, {
|
|
47910
47926
|
method: "DELETE",
|
|
47911
47927
|
auth: "device",
|
|
@@ -47955,6 +47971,7 @@ var init_keys = __esm(() => {
|
|
|
47955
47971
|
init_secret_store();
|
|
47956
47972
|
init_key_output();
|
|
47957
47973
|
init_keys_embedded_wallet();
|
|
47974
|
+
init_tee_rebind();
|
|
47958
47975
|
ACCESS_LEVELS = {
|
|
47959
47976
|
read: "read",
|
|
47960
47977
|
write: "readwrite",
|
|
@@ -78928,13 +78945,16 @@ var HELP = {
|
|
|
78928
78945
|
invocation: "self embedded-wallet deny",
|
|
78929
78946
|
description: "The profile's own key gives up the embedded wallet, with no prompt. A key can never allow itself: the owner does that with keys update"
|
|
78930
78947
|
},
|
|
78931
|
-
{
|
|
78932
|
-
|
|
78948
|
+
{
|
|
78949
|
+
invocation: "stop <prefix|label>",
|
|
78950
|
+
description: "Pause one key with the device token; reversible with keys resume"
|
|
78951
|
+
},
|
|
78952
|
+
{ invocation: "resume <prefix|label>", description: "Resume a stopped key with the device token" },
|
|
78933
78953
|
{
|
|
78934
78954
|
invocation: "rotate <prefix|label> ([--grace <duration> | --now] [--force] [--yes] | --finish)",
|
|
78935
78955
|
description: "Give a key a new secret, keeping its prefix, label, access, limits, wallets and history. The old secret works through --grace (default 1h, at most 24h) or stops at once with --now; --finish ends an open window early. The profile's own key is replaced in the keychain; update CANDLE_API_KEY or CANDLE_API_KEY_FILE yourself and restart MCP. --force rotates again while a window is open"
|
|
78936
78956
|
},
|
|
78937
|
-
{ invocation: "revoke <prefix>", description: "Revoke an API key permanently" },
|
|
78957
|
+
{ invocation: "revoke <prefix|label>", description: "Revoke an API key permanently" },
|
|
78938
78958
|
{
|
|
78939
78959
|
invocation: "signer approve <code> --key <prefix|label> [--reject]",
|
|
78940
78960
|
description: "Approve (or reject) a key's signer request with the device token; type the full fingerprint the trading machine printed"
|
|
@@ -85264,6 +85284,13 @@ init_evm_lite();
|
|
|
85264
85284
|
init_client();
|
|
85265
85285
|
var EXIT_OWNER_CONFIRM_PENDING = 7;
|
|
85266
85286
|
var OWN_NO_WAIT_COMMANDS = [["tee"], ["lab"], ["wallets", "authorize"]];
|
|
85287
|
+
function shortWallet(wallet3) {
|
|
85288
|
+
return wallet3.length >= 12 ? `${wallet3.slice(0, 4)}…${wallet3.slice(-4)}` : wallet3;
|
|
85289
|
+
}
|
|
85290
|
+
function accountLabel(account) {
|
|
85291
|
+
const short = shortWallet(account.wallet);
|
|
85292
|
+
return account.displayName ? `${account.displayName} (${short})` : short;
|
|
85293
|
+
}
|
|
85267
85294
|
function ownerConfirmPendingLine(challenge) {
|
|
85268
85295
|
return JSON.stringify({
|
|
85269
85296
|
ok: false,
|
|
@@ -85274,7 +85301,8 @@ function ownerConfirmPendingLine(challenge) {
|
|
|
85274
85301
|
verificationUriComplete: challenge.verificationUriComplete,
|
|
85275
85302
|
expiresIn: challenge.expiresIn,
|
|
85276
85303
|
step: challenge.step,
|
|
85277
|
-
summary: challenge.summary
|
|
85304
|
+
summary: challenge.summary,
|
|
85305
|
+
...challenge.account ? { account: challenge.account } : {}
|
|
85278
85306
|
}
|
|
85279
85307
|
});
|
|
85280
85308
|
}
|
|
@@ -85291,10 +85319,12 @@ function cliOwnerConfirmHooks(deps, opts, state) {
|
|
|
85291
85319
|
`);
|
|
85292
85320
|
} else {
|
|
85293
85321
|
const minutes = Math.max(1, Math.round(challenge.expiresIn / 60));
|
|
85322
|
+
const as = challenge.account ? ` as ${accountLabel(challenge.account)}` : "";
|
|
85294
85323
|
deps.stderr.write([
|
|
85295
|
-
`This needs your approval in the browser: ${challenge.summary}`,
|
|
85324
|
+
`This needs your approval in the browser${as}: ${challenge.summary}`,
|
|
85296
85325
|
`Open ${challenge.verificationUriComplete}`,
|
|
85297
85326
|
`Code: ${challenge.userCode}`,
|
|
85327
|
+
...challenge.account ? [`The browser must be signed in as ${accountLabel(challenge.account)}.`] : [],
|
|
85298
85328
|
"Only approve if you just ran this command.",
|
|
85299
85329
|
opts.wait ? `Waiting for approval (expires in ${minutes} minute${minutes === 1 ? "" : "s"})...` : ""
|
|
85300
85330
|
].filter(Boolean).join(`
|
|
@@ -93591,6 +93621,7 @@ init_presentation();
|
|
|
93591
93621
|
init_profiles();
|
|
93592
93622
|
init_key_output();
|
|
93593
93623
|
init_keys();
|
|
93624
|
+
init_tee_rebind();
|
|
93594
93625
|
function keysStop(args, ctx) {
|
|
93595
93626
|
return setKeyPaused(args, ctx, true);
|
|
93596
93627
|
}
|
|
@@ -93599,14 +93630,14 @@ function keysResume(args, ctx) {
|
|
|
93599
93630
|
}
|
|
93600
93631
|
async function setKeyPaused(args, ctx, paused) {
|
|
93601
93632
|
const { deps, apiUrl, json } = ctx;
|
|
93602
|
-
const parsed = parseArgs(args, {});
|
|
93633
|
+
const parsed = parseArgs(args, { keyPrefixPositional: true });
|
|
93603
93634
|
if ("error" in parsed) {
|
|
93604
93635
|
writeScreenUsageFailure(deps, parsed.error, json);
|
|
93605
93636
|
return 2;
|
|
93606
93637
|
}
|
|
93607
|
-
const
|
|
93608
|
-
if (!
|
|
93609
|
-
writeScreenUsageFailure(deps, `Usage: candle keys ${paused ? "stop" : "resume"} <prefix>`, json);
|
|
93638
|
+
const target = parsed.positionals[0];
|
|
93639
|
+
if (!target?.trim() || parsed.positionals.length !== 1) {
|
|
93640
|
+
writeScreenUsageFailure(deps, `Usage: candle keys ${paused ? "stop" : "resume"} <prefix|label>`, json);
|
|
93610
93641
|
return 2;
|
|
93611
93642
|
}
|
|
93612
93643
|
await printIdentity(ctx);
|
|
@@ -93615,6 +93646,16 @@ async function setKeyPaused(args, ctx, paused) {
|
|
|
93615
93646
|
writeScreenLocalFailure(deps, NO_DEVICE_TOKEN, json);
|
|
93616
93647
|
return 1;
|
|
93617
93648
|
}
|
|
93649
|
+
const resolved = await resolveTargetKey(ctx, deviceToken, target, {
|
|
93650
|
+
codePrefix: paused ? "KEY_STOP" : "KEY_RESUME",
|
|
93651
|
+
writeListFailure: (failure3) => {
|
|
93652
|
+
writeScreenFailure(deps, failure3, { apiUrl, authType: "device" }, json);
|
|
93653
|
+
return 1;
|
|
93654
|
+
}
|
|
93655
|
+
});
|
|
93656
|
+
if (!resolved.ok)
|
|
93657
|
+
return resolved.code;
|
|
93658
|
+
const prefix = resolved.keyPrefix;
|
|
93618
93659
|
const result2 = await apiRequest(`/api/v1/agent/keys/${encodeURIComponent(prefix)}/stop`, {
|
|
93619
93660
|
method: "POST",
|
|
93620
93661
|
auth: "device",
|
package/package.json
CHANGED