@haven_ai/cli 0.0.0-dev.202610051332.f032d0a → 0.0.0-dev.202610061536.ad3de49

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/dist/cli.cjs CHANGED
@@ -5,6 +5,7 @@ var promises = require('fs/promises');
5
5
  var os = require('os');
6
6
  var path = require('path');
7
7
  var child_process = require('child_process');
8
+ var crypto = require('crypto');
8
9
  var readline = require('readline');
9
10
 
10
11
  // src/args.ts
@@ -149,6 +150,12 @@ function helpText() {
149
150
  " catalog list List payable services",
150
151
  " contacts list List your address book",
151
152
  "",
153
+ "Feedback:",
154
+ ' feedback submit "<text>" Send feedback or a bug report. Needs',
155
+ " `haven login`. It refuses to send text that",
156
+ " looks like a credential, but cannot catch",
157
+ " every secret shape \u2014 never include one.",
158
+ "",
152
159
  "Manage (backend-only \u2014 no on-chain signing):",
153
160
  " agents pause <id> Stop the agent spending; keeps its budget",
154
161
  " agents resume <id> Let it spend again",
@@ -369,11 +376,20 @@ var UsageError = class extends Error {
369
376
  var HavenCliError = class extends Error {
370
377
  exit;
371
378
  hint;
372
- constructor(message, exit, hint) {
379
+ /**
380
+ * #3597: additional typed fields merged into the `--json` error object
381
+ * (`error.layer`, `error.reason`, …) — for a refusal where the FREE-TEXT
382
+ * hint is not enough to branch on. `feedback submit`'s secret check is the
383
+ * first caller: an agent needs `error.layer` (which of the four checks
384
+ * refused) as a number, not a string it has to parse out of a sentence.
385
+ */
386
+ extra;
387
+ constructor(message, exit, hint, extra) {
373
388
  super(message);
374
389
  this.name = "HavenCliError";
375
390
  this.exit = exit;
376
391
  this.hint = hint;
392
+ this.extra = extra;
377
393
  }
378
394
  };
379
395
  function toFailure(err) {
@@ -382,7 +398,7 @@ function toFailure(err) {
382
398
  }
383
399
  if (err instanceof HavenCliError) {
384
400
  const code = err.exit === EXIT.notAuthenticated ? "not_authenticated" : err.exit === EXIT.refused ? "refused" : err.exit === EXIT.network ? "network" : "failed";
385
- return { code, exit: err.exit, message: err.message, hint: err.hint };
401
+ return { code, exit: err.exit, message: err.message, hint: err.hint, extra: err.extra };
386
402
  }
387
403
  if (err instanceof CliApiError) {
388
404
  if (err.status === 0) {
@@ -432,6 +448,11 @@ function createOutput(json, out, err) {
432
448
  const body = {
433
449
  ok: false,
434
450
  error: {
451
+ // `extra` spreads FIRST (#3597 round 2, N-a): it is per-command
452
+ // (e.g. the secret check's `layer`/`reason`), so it must never be
453
+ // able to clobber the contract fields every command shares —
454
+ // `code`, `message`, `hint` are spread AFTER and always win.
455
+ ...failure.extra ?? {},
435
456
  code: failure.code,
436
457
  message: failure.message,
437
458
  ...failure.hint ? { hint: failure.hint } : {}
@@ -445,7 +466,7 @@ ${failure.hint}` : failure.message);
445
466
  }
446
467
 
447
468
  // src/agent-guidance-text.ts
448
- var HAVEN_AGENT_RUNBOOK_MD = "# Haven for agents \u2014 set your user up to let you pay\n\nYou are an AI agent whose user has no Haven account yet, or has one but has not connected you.\n\n> Links below are paths on this same host: resolve them against the URL you fetched this file from.\n\n## What Haven is, in three sentences\n\nYour user gives you a **budget on their own account** \u2014 not their wallet, and not a key to their funds. The budget is a delegation they sign, enforced on-chain: a payment over it, to the wrong recipient, or past its expiry is refused at execution time, not by a dashboard promise. Haven constructs and relays the payments; you get an agent credential and a signing key made on your machine, and your user can revoke the budget without you and without Haven.\n\n## The sequence\n\nFour of the six steps are your user's \u2014 each needs a human signature or a human decision. The rest is yours. If they already have a funded account, start at step 3.\n\n1. **HUMAN \u2014 create the account.** Name, email, password, then a passkey (Face ID / Touch ID) or a wallet. Never offer to enter any of it: you must not have their password, and the passkey is bound to their device. With a terminal, `<packages.cli.one_liner> login --api <api-url>` afterwards gets you a scoped session for steps 3-4 (that flag or `HAVEN_API_URL`, on the first command \u2014 the session then remembers the backend; **the CLI's built-in default is Haven's hosted production backend**, so on any other deployment an omitted flag connects you somewhere real and wrong rather than failing) \u2014 they approve a code in the browser, you never hold their password. That command is the manifest's `packages.cli.one_liner` (`/.well-known/haven.json`) \u2014 run it as given: `packages.cli.channel` serves the full spec. Do not hold the process open while you wait: under `--json`, pass `--no-wait` to get the link object back at once, then poll it with `haven login --poll <device_code>` \u2014 one round per invocation, exit 3 while it is still pending, 0 once approved. It can set up agents and read the account; it cannot sign, approve a budget, move funds, or rotate any agent's keys.\n2. **HUMAN \u2014 fund it.** USDC only, no ETH: Haven sponsors the gas. `/.well-known/haven.json` names `chains.default` as the deployment's expected chain, but after login `haven wallets funding` prints the address, the amount and which chain in one place; confirm that chain before you message your user. Without a CLI session, the dashboard's funding card shows the address and amount and its Receive-funds screen names the chain; never assume one: a testnet deployment and production both call themselves Haven. Before you write that message, read the manifest: `environment` says whether this deployment is `production`, and each `chains.supported` entry says whether that chain is a `testnet`. Real money is at stake only on a non-testnet chain of a `production` deployment \u2014 tell your user which case theirs is.\n3. **HUMAN \u2014 create the agent, set its budget**, and paste you the **setup prompt** it hands back. With a CLI session (step 1) you can do this step yourself: `haven agents connect --name <n> --budget <amount> --token USDC --period <minutes>` prints the same connector command and approval link; add `--run` to do step 4 too.\n4. **YOU \u2014 run the connector command** in that prompt (see What you run). It makes your signing key locally, registering only the public address.\n5. **HUMAN \u2014 approve the budget** with their passkey, in the Haven tab they created the agent in: it advances to the approval step by itself once your run registers.\n6. **YOU \u2014 verify, then pay.**\n\n## Budget changes later (second token, raise, revoke)\n\nThe first budget rides the setup in The sequence. After the agent exists, a CLI session can construct the LATER changes \u2014 a second token, a bigger amount, a recipient pin, a stop \u2014 and hand your user a link; the human still signs, every time:\n\n```\nhaven budget grant <agentId> --amount <n> --token USDC --period <minutes> [--recipient <address>] [--wait]\nhaven budget revoke <agentId> <delegationHash> [--wait]\n```\n\nThe CLI never signs: it prints a dashboard link, your user opens it and signs with their passkey or wallet. `--wait` polls until the human's signature lands. The hash for `revoke` is in `haven agents show <agentId>`.\n\n## Hand-off scripts\n\nSend these as your own message, `<host>` replaced by the host you fetched this file from. Say what you cannot do, not only what they must.\n\n**Before signup** (step 1):\n\n> I can do everything except the parts that need your signature. Please open `<host>/signup?next=/agents&via=agent` \u2014 name, email, password, then a passkey (Face ID / Touch ID) or a wallet. That is your account's key: I should not have it, and I will never ask for your password. Already have one? `<host>/login?next=/agents`.\n\n**At the passkey step:**\n\n> The passkey must be made on your own device \u2014 it is what keeps the account yours, so nobody, Haven included, can move your funds without you. If this browser cannot, open `<host>/onboarding?next=/agents` on your phone and finish there.\n\n**At funding** (step 2):\n\n> Your Haven account needs USDC before I can pay for anything \u2014 USDC only, no ETH: Haven sponsors the gas. Before you send anything, let me get you the exact address **and network** \u2014 `haven wallets funding` prints both, and the funding card on `<host>/dashboard` shows the same. Please do not send to an address or a chain I have not confirmed with you; a small amount first is fine.\n\n**At the budget** (step 3):\n\n> On `<host>/agents`, create an agent for me and set a budget \u2014 say 25 USDC per day. That is the limit I cannot exceed. It hands back a setup prompt: paste it to me and I run it here.\n\n**At budget approval** (step 5) \u2014 the moment your run reports that approval is required, before anything else. Send the first if your run carried `approval.url`, the second if it did not.\n\n> Setup is done on my side. Approve the budget here: <approval.url>. Approve it with your passkey; nothing can be spent until you do.\n\n> Setup is done on my side. Go back to the Haven tab where you created the agent \u2014 it should now be asking you to approve the budget. Approve it with your passkey; nothing can be spent until you do.\n\n## What you run\n\nThe setup prompt carries a **connector command** shaped like this:\n\n```\nnpx -y @haven_ai/connect@<channel> --setup EXAMPLE-SETUP-TOKEN-NOT-REAL --api <api-url> --ack-local-tools\n```\n\nRun the prompt's version, not this one: the token is one-time, the API URL is the backend's own, and `<channel>` is the npm tag your prompt names \u2014 never a tag you pick. The rules below come from that prompt, so \"me\" in them is your user, not Haven.\n\n- If you are an AI agent running this command yourself rather than a human pasting it, you should append --json: the connector then emits one machine-readable, secret-free result object on stdout with progress on stderr, and returns promptly instead of blocking while it waits for the budget approval.\n- When a --json outcome reports approval.required: true, your first action must be to relay the approval instruction to me in your own reply \u2014 if the outcome carries approval.url, give me that link; otherwise tell me to return to Haven and approve this agent's budget \u2014 before verifying the connection, restarting anything, or any other step. Never build that link yourself: relay the one the outcome gave you or none at all. Any restart the outcome asks for is a separate instruction to give me afterwards, once the approval is done.\n- If you ran the command without --json, the connector waits for the approval itself and prints its next steps when it finishes: relay the budget-approval instruction to me \u2014 the approval link if those steps printed one, otherwise that you need to return to Haven and approve this agent's budget \u2014 only if those printed next steps still ask for it. If they report the budget as already approved, there is nothing for me to approve.\n- Only two changes to the command above are permitted, and no others: appending --json, and \u2014 only if the connector refuses because it could not determine the agent runtime \u2014 re-running it once with --runtime <name> added, naming the harness you are running in, using one of the values that refusal lists. Never invent a runtime name and never change anything else.\n- Do not print private keys, API keys, credential file contents, or config secrets in chat or logs.\n\nIf the approval wait times out, nothing is lost \u2014 your agent is registered and the budget is still waiting to be approved. Send your user the `approval.url` your run reported, or, if it carried none, ask them to finish it in that same Haven tab. The outcome carries no setup id, so never assemble an approval link out of parts \u2014 relay the whole one it gave you or none at all.\n\n## How to verify\n\nCall `haven_get_agent`, one of the Haven MCP tools the connector wires into your runtime in step 4. It returns identity plus `spend_authority_readiness`:\n\n- `ready` \u2014 a budget is live; you can pay.\n- `needs_approval` \u2014 the connector finished, nobody approved yet. Ask your user again, in their Haven tab; there is no queue to wait in.\n- `revoked` \u2014 the credential is not active; ask your user to create a new agent.\n\n`ready` covers hosted identity and the budget only, not your local signer. Check that with `npx -y @haven_ai/connect@<channel> --doctor`, the same tag your prompt named \u2014 a separate command, so the two-changes rule does not bind it.\n\n## If you cannot open a browser\n\nNothing here needs you to. Steps 1-3 \u2014 account, funding, budget \u2014 are links: hand your user the full `<host>/\u2026` URL and ask them to say when it is done. Step 5 is a link only when your run reported one in `approval.url` \u2014 otherwise it is the tab they already have open. Then poll `haven_get_agent` until it reads `ready`. Do not route around the sign-in wall \u2014 it makes the account theirs, not yours.\n\n## If something breaks\n\nIf a Haven result carries `client_update`, that client is out of date: run its `upgrade_command` as given, then any repair line it prints, then retry. `required: true` means payments are refused until you do. What changed: [/releases](/releases).\n\n## Vocabulary\n\n| Term | What it is |\n|---|---|\n| **setup prompt** | The text the dashboard hands your user to paste to you. Carries the command and its rules. |\n| **connector command** | The `npx -y @haven_ai/connect@\u2026` line you run. One-time token, one use. |\n| **agent credential** | Your API key (`sk_agent_\u2026`), written to `~/.haven`. It identifies you; alone it cannot move money. |\n| **delegate key** | Your signing key, made on this machine and never sent anywhere. |\n| **budget** | The on-chain delegation your user signed. It authorises the payment; Haven constructs and relays it. |\n\nNext: [your agent hit a 402](/402.md) \xB7 [everything agent-readable](/llms.txt)\n";
469
+ var HAVEN_AGENT_RUNBOOK_MD = "# Haven for agents \u2014 set your user up to let you pay\n\nYou are an AI agent whose user has no Haven account yet, or has one but has not connected you.\n\n> Links below are paths on this same host: resolve them against the URL you fetched this file from.\n\n## What Haven is, in three sentences\n\nYour user gives you a **budget on their own account** \u2014 not their wallet, and not a key to their funds. The budget is a delegation they sign, enforced on-chain: a payment over it, to the wrong recipient, or past its expiry is refused at execution time, not by a dashboard promise. Haven constructs and relays the payments; you get an agent credential and a signing key made on your machine, and your user can revoke the budget without you and without Haven.\n\n## The sequence\n\nFour of the six steps are your user's \u2014 each needs a human signature or a human decision. The rest is yours. If they already have a funded account, start at step 3.\n\n1. **HUMAN \u2014 create the account.** Name, email, password, then a passkey (Face ID / Touch ID) or a wallet. Never offer to enter any of it: you must not have their password, and the passkey is bound to their device. With a terminal, `<packages.cli.one_liner> login --api <api-url>` afterwards gets you a scoped session for steps 3-4 (that flag or `HAVEN_API_URL`, on the first command \u2014 the session then remembers the backend; **the CLI's built-in default is Haven's hosted production backend**, so on any other deployment an omitted flag connects you somewhere real and wrong rather than failing) \u2014 they approve a code in the browser, you never hold their password. That command is the manifest's `packages.cli.one_liner` (`/.well-known/haven.json`) \u2014 run it as given: `packages.cli.channel` serves the full spec. Do not hold the process open while you wait: under `--json`, pass `--no-wait` to get the link object back at once, then poll it with `haven login --poll <device_code>` \u2014 one round per invocation, exit 3 while it is still pending, 0 once approved. It can set up agents and read the account; it cannot sign, approve a budget, move funds, or rotate any agent's keys.\n2. **HUMAN \u2014 fund it.** USDC only, no ETH: Haven sponsors the gas. `/.well-known/haven.json` names `chains.default` as the deployment's expected chain, but after login `haven wallets funding` prints the address, the amount and which chain in one place; confirm that chain before you message your user. Without a CLI session, the dashboard's funding card shows the address and amount and its Receive-funds screen names the chain; never assume one: a testnet deployment and production both call themselves Haven. Before you write that message, read the manifest: `environment` says whether this deployment is `production`, and each `chains.supported` entry says whether that chain is a `testnet`. Real money is at stake only on a non-testnet chain of a `production` deployment \u2014 tell your user which case theirs is.\n3. **HUMAN \u2014 create the agent, set its budget**, and paste you the **setup prompt** it hands back. With a CLI session (step 1) you can do this step yourself: `haven agents connect --name <n> --budget <amount> --token USDC --period <minutes>` prints the same connector command and approval link; add `--run` to do step 4 too.\n4. **YOU \u2014 run the connector command** in that prompt (see What you run). It makes your signing key locally, registering only the public address.\n5. **HUMAN \u2014 approve the budget** with their passkey, in the Haven tab they created the agent in: it advances to the approval step by itself once your run registers.\n6. **YOU \u2014 verify, then pay.**\n\n## Budget changes later (second token, raise, revoke)\n\nThe first budget rides the setup in The sequence. After the agent exists, a CLI session can construct the LATER changes \u2014 a second token, a bigger amount, a recipient pin, a stop \u2014 and hand your user a link; the human still signs, every time:\n\n```\nhaven budget grant <agentId> --amount <n> --token USDC --period <minutes> [--recipient <address>] [--wait]\nhaven budget revoke <agentId> <delegationHash> [--wait]\n```\n\nThe CLI never signs: it prints a dashboard link, your user opens it and signs with their passkey or wallet. `--wait` polls until the human's signature lands. The hash for `revoke` is in `haven agents show <agentId>`.\n\n## Hand-off scripts\n\nSend these as your own message, `<host>` replaced by the host you fetched this file from. Say what you cannot do, not only what they must.\n\n**Before signup** (step 1):\n\n> I can do everything except the parts that need your signature. Please open `<host>/signup?next=/agents&via=agent` \u2014 name, email, password, then a passkey (Face ID / Touch ID) or a wallet. That is your account's key: I should not have it, and I will never ask for your password. Already have one? `<host>/login?next=/agents`.\n\n**At the passkey step:**\n\n> The passkey must be made on your own device \u2014 it is what keeps the account yours, so nobody, Haven included, can move your funds without you. If this browser cannot, open `<host>/onboarding?next=/agents` on your phone and finish there.\n\n**At funding** (step 2):\n\n> Your Haven account needs USDC before I can pay for anything \u2014 USDC only, no ETH: Haven sponsors the gas. Before you send anything, let me get you the exact address **and network** \u2014 `haven wallets funding` prints both, and the funding card on `<host>/dashboard` shows the same. Please do not send to an address or a chain I have not confirmed with you; a small amount first is fine.\n\n**At the budget** (step 3):\n\n> On `<host>/agents`, create an agent for me and set a budget \u2014 say 25 USDC per day. That is the limit I cannot exceed. It hands back a setup prompt: paste it to me and I run it here.\n\n**At budget approval** (step 5) \u2014 the moment your run reports that approval is required, before anything else. Send the first if your run carried `approval.url`, the second if it did not.\n\n> Setup is done on my side. Approve the budget here: <approval.url>. Approve it with your passkey; nothing can be spent until you do.\n\n> Setup is done on my side. Go back to the Haven tab where you created the agent \u2014 it should now be asking you to approve the budget. Approve it with your passkey; nothing can be spent until you do.\n\n## What you run\n\nThe setup prompt carries a **connector command** shaped like this:\n\n```\nnpx -y @haven_ai/connect@<channel> --setup EXAMPLE-SETUP-TOKEN-NOT-REAL --api <api-url> --ack-local-tools\n```\n\nRun the prompt's version, not this one: the token is one-time, the API URL is the backend's own, and `<channel>` is the npm tag your prompt names \u2014 never a tag you pick. The rules below come from that prompt, so \"me\" in them is your user, not Haven.\n\n- If you are an AI agent running this command yourself rather than a human pasting it, you should append --json: the connector then emits one machine-readable, secret-free result object on stdout with progress on stderr, and returns promptly instead of blocking while it waits for the budget approval.\n- When a --json outcome reports approval.required: true, your first action must be to relay the approval instruction to me in your own reply \u2014 if the outcome carries approval.url, give me that link; otherwise tell me to return to Haven and approve this agent's budget \u2014 before verifying the connection, restarting anything, or any other step. Never build that link yourself: relay the one the outcome gave you or none at all. Any restart the outcome asks for is a separate instruction to give me afterwards, once the approval is done.\n- If you ran the command without --json, the connector waits for the approval itself and prints its next steps when it finishes: relay the budget-approval instruction to me \u2014 the approval link if those steps printed one, otherwise that you need to return to Haven and approve this agent's budget \u2014 only if those printed next steps still ask for it. If they report the budget as already approved, there is nothing for me to approve.\n- Only three changes to the command above are permitted, and no others: appending --json; re-running it once with --runtime <name> added, only if the connector refuses because it could not determine the agent runtime, naming the harness you are running in and using one of the values that refusal lists; and re-running it once with the one flag I chose added, only after I have answered a wiring_collision relay \u2014 --name <the suggested_name or a name I gave> to add alongside, or --replace to replace \u2014 keeping any change already made. If that re-run is refused too, relay the refusal to me and stop. Never invent a runtime name and never change anything else.\n- Do not print private keys, API keys, credential file contents, or config secrets in chat or logs.\n\nIf the approval wait times out, nothing is lost \u2014 your agent is registered and the budget is still waiting to be approved. Send your user the `approval.url` your run reported, or, if it carried none, ask them to finish it in that same Haven tab. The outcome carries no setup id, so never assemble an approval link out of parts \u2014 relay the whole one it gave you or none at all.\n\n## How to verify\n\nCall `haven_get_agent`, one of the Haven MCP tools the connector wires into your runtime in step 4. It returns identity plus `spend_authority_readiness`:\n\n- `ready` \u2014 a budget is live; you can pay.\n- `needs_approval` \u2014 the connector finished, nobody approved yet. Ask your user again, in their Haven tab; there is no queue to wait in.\n- `revoked` \u2014 the credential is not active; ask your user to create a new agent.\n\n`ready` covers hosted identity and the budget only, not your local signer. Check that with `npx -y @haven_ai/connect@<channel> --doctor`, the same tag your prompt named \u2014 a separate command, so the command-modification rule does not bind it.\n\n## If you cannot open a browser\n\nNothing here needs you to. Steps 1-3 \u2014 account, funding, budget \u2014 are links: hand your user the full `<host>/\u2026` URL and ask them to say when it is done. Step 5 is a link only when your run reported one in `approval.url` \u2014 otherwise it is the tab they already have open. Then poll `haven_get_agent` until it reads `ready`. Do not route around the sign-in wall \u2014 it makes the account theirs, not yours.\n\n## If something breaks\n\nIf a Haven result carries `client_update`, that client is out of date: run its `upgrade_command` as given, then any repair line it prints, then retry. `required: true` means payments are refused until you do. What changed: [/releases](/releases).\n\nSomething else wrong? `haven feedback submit \"<text>\"` sends it to Haven \u2014 it needs `haven login` first. Never put a credential in that text: no API key, no delegate key, no session token, no recovery phrase.\n\n## Vocabulary\n\n| Term | What it is |\n|---|---|\n| **setup prompt** | The text the dashboard hands your user to paste to you. Carries the command and its rules. |\n| **connector command** | The `npx -y @haven_ai/connect@\u2026` line you run. One-time token, one use. |\n| **agent credential** | Your API key (`sk_agent_\u2026`), written to `~/.haven`. It identifies you; alone it cannot move money. |\n| **delegate key** | Your signing key, made on this machine and never sent anywhere. |\n| **budget** | The on-chain delegation your user signed. It authorises the payment; Haven constructs and relays it. |\n\nNext: [your agent hit a 402](/402.md) \xB7 [everything agent-readable](/llms.txt)\n";
449
470
 
450
471
  // src/token.ts
451
472
  function sessionExpiry(token) {
@@ -618,9 +639,2515 @@ async function runConnector(connectorCommand, spawner, onStderr) {
618
639
  return { outcome, exitCode, stderr, stdoutNoise: noise };
619
640
  }
620
641
 
642
+ // ../../node_modules/@noble/hashes/esm/_u64.js
643
+ var U32_MASK64 = /* @__PURE__ */ BigInt(2 ** 32 - 1);
644
+ var _32n = /* @__PURE__ */ BigInt(32);
645
+ function fromBig(n, le = false) {
646
+ if (le)
647
+ return { h: Number(n & U32_MASK64), l: Number(n >> _32n & U32_MASK64) };
648
+ return { h: Number(n >> _32n & U32_MASK64) | 0, l: Number(n & U32_MASK64) | 0 };
649
+ }
650
+ function split(lst, le = false) {
651
+ const len = lst.length;
652
+ let Ah = new Uint32Array(len);
653
+ let Al = new Uint32Array(len);
654
+ for (let i = 0; i < len; i++) {
655
+ const { h, l } = fromBig(lst[i], le);
656
+ [Ah[i], Al[i]] = [h, l];
657
+ }
658
+ return [Ah, Al];
659
+ }
660
+ var rotlSH = (h, l, s) => h << s | l >>> 32 - s;
661
+ var rotlSL = (h, l, s) => l << s | h >>> 32 - s;
662
+ var rotlBH = (h, l, s) => l << s - 32 | h >>> 64 - s;
663
+ var rotlBL = (h, l, s) => h << s - 32 | l >>> 64 - s;
664
+
665
+ // ../../node_modules/@noble/hashes/esm/utils.js
666
+ function isBytes(a) {
667
+ return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array";
668
+ }
669
+ function anumber(n) {
670
+ if (!Number.isSafeInteger(n) || n < 0)
671
+ throw new Error("positive integer expected, got " + n);
672
+ }
673
+ function abytes(b, ...lengths) {
674
+ if (!isBytes(b))
675
+ throw new Error("Uint8Array expected");
676
+ if (lengths.length > 0 && !lengths.includes(b.length))
677
+ throw new Error("Uint8Array expected of length " + lengths + ", got length=" + b.length);
678
+ }
679
+ function aexists(instance, checkFinished = true) {
680
+ if (instance.destroyed)
681
+ throw new Error("Hash instance has been destroyed");
682
+ if (checkFinished && instance.finished)
683
+ throw new Error("Hash#digest() has already been called");
684
+ }
685
+ function aoutput(out, instance) {
686
+ abytes(out);
687
+ const min = instance.outputLen;
688
+ if (out.length < min) {
689
+ throw new Error("digestInto() expects output buffer of length at least " + min);
690
+ }
691
+ }
692
+ function u32(arr) {
693
+ return new Uint32Array(arr.buffer, arr.byteOffset, Math.floor(arr.byteLength / 4));
694
+ }
695
+ function clean(...arrays) {
696
+ for (let i = 0; i < arrays.length; i++) {
697
+ arrays[i].fill(0);
698
+ }
699
+ }
700
+ var isLE = /* @__PURE__ */ (() => new Uint8Array(new Uint32Array([287454020]).buffer)[0] === 68)();
701
+ function byteSwap(word) {
702
+ return word << 24 & 4278190080 | word << 8 & 16711680 | word >>> 8 & 65280 | word >>> 24 & 255;
703
+ }
704
+ function byteSwap32(arr) {
705
+ for (let i = 0; i < arr.length; i++) {
706
+ arr[i] = byteSwap(arr[i]);
707
+ }
708
+ return arr;
709
+ }
710
+ var swap32IfBE = isLE ? (u) => u : byteSwap32;
711
+ function utf8ToBytes(str) {
712
+ if (typeof str !== "string")
713
+ throw new Error("string expected");
714
+ return new Uint8Array(new TextEncoder().encode(str));
715
+ }
716
+ function toBytes(data) {
717
+ if (typeof data === "string")
718
+ data = utf8ToBytes(data);
719
+ abytes(data);
720
+ return data;
721
+ }
722
+ var Hash = class {
723
+ };
724
+ function createHasher(hashCons) {
725
+ const hashC = (msg) => hashCons().update(toBytes(msg)).digest();
726
+ const tmp = hashCons();
727
+ hashC.outputLen = tmp.outputLen;
728
+ hashC.blockLen = tmp.blockLen;
729
+ hashC.create = () => hashCons();
730
+ return hashC;
731
+ }
732
+
733
+ // ../../node_modules/@noble/hashes/esm/sha3.js
734
+ var _0n = BigInt(0);
735
+ var _1n = BigInt(1);
736
+ var _2n = BigInt(2);
737
+ var _7n = BigInt(7);
738
+ var _256n = BigInt(256);
739
+ var _0x71n = BigInt(113);
740
+ var SHA3_PI = [];
741
+ var SHA3_ROTL = [];
742
+ var _SHA3_IOTA = [];
743
+ for (let round = 0, R = _1n, x = 1, y = 0; round < 24; round++) {
744
+ [x, y] = [y, (2 * x + 3 * y) % 5];
745
+ SHA3_PI.push(2 * (5 * y + x));
746
+ SHA3_ROTL.push((round + 1) * (round + 2) / 2 % 64);
747
+ let t = _0n;
748
+ for (let j = 0; j < 7; j++) {
749
+ R = (R << _1n ^ (R >> _7n) * _0x71n) % _256n;
750
+ if (R & _2n)
751
+ t ^= _1n << (_1n << /* @__PURE__ */ BigInt(j)) - _1n;
752
+ }
753
+ _SHA3_IOTA.push(t);
754
+ }
755
+ var IOTAS = split(_SHA3_IOTA, true);
756
+ var SHA3_IOTA_H = IOTAS[0];
757
+ var SHA3_IOTA_L = IOTAS[1];
758
+ var rotlH = (h, l, s) => s > 32 ? rotlBH(h, l, s) : rotlSH(h, l, s);
759
+ var rotlL = (h, l, s) => s > 32 ? rotlBL(h, l, s) : rotlSL(h, l, s);
760
+ function keccakP(s, rounds = 24) {
761
+ const B = new Uint32Array(5 * 2);
762
+ for (let round = 24 - rounds; round < 24; round++) {
763
+ for (let x = 0; x < 10; x++)
764
+ B[x] = s[x] ^ s[x + 10] ^ s[x + 20] ^ s[x + 30] ^ s[x + 40];
765
+ for (let x = 0; x < 10; x += 2) {
766
+ const idx1 = (x + 8) % 10;
767
+ const idx0 = (x + 2) % 10;
768
+ const B0 = B[idx0];
769
+ const B1 = B[idx0 + 1];
770
+ const Th = rotlH(B0, B1, 1) ^ B[idx1];
771
+ const Tl = rotlL(B0, B1, 1) ^ B[idx1 + 1];
772
+ for (let y = 0; y < 50; y += 10) {
773
+ s[x + y] ^= Th;
774
+ s[x + y + 1] ^= Tl;
775
+ }
776
+ }
777
+ let curH = s[2];
778
+ let curL = s[3];
779
+ for (let t = 0; t < 24; t++) {
780
+ const shift = SHA3_ROTL[t];
781
+ const Th = rotlH(curH, curL, shift);
782
+ const Tl = rotlL(curH, curL, shift);
783
+ const PI = SHA3_PI[t];
784
+ curH = s[PI];
785
+ curL = s[PI + 1];
786
+ s[PI] = Th;
787
+ s[PI + 1] = Tl;
788
+ }
789
+ for (let y = 0; y < 50; y += 10) {
790
+ for (let x = 0; x < 10; x++)
791
+ B[x] = s[y + x];
792
+ for (let x = 0; x < 10; x++)
793
+ s[y + x] ^= ~B[(x + 2) % 10] & B[(x + 4) % 10];
794
+ }
795
+ s[0] ^= SHA3_IOTA_H[round];
796
+ s[1] ^= SHA3_IOTA_L[round];
797
+ }
798
+ clean(B);
799
+ }
800
+ var Keccak = class _Keccak extends Hash {
801
+ // NOTE: we accept arguments in bytes instead of bits here.
802
+ constructor(blockLen, suffix, outputLen, enableXOF = false, rounds = 24) {
803
+ super();
804
+ this.pos = 0;
805
+ this.posOut = 0;
806
+ this.finished = false;
807
+ this.destroyed = false;
808
+ this.enableXOF = false;
809
+ this.blockLen = blockLen;
810
+ this.suffix = suffix;
811
+ this.outputLen = outputLen;
812
+ this.enableXOF = enableXOF;
813
+ this.rounds = rounds;
814
+ anumber(outputLen);
815
+ if (!(0 < blockLen && blockLen < 200))
816
+ throw new Error("only keccak-f1600 function is supported");
817
+ this.state = new Uint8Array(200);
818
+ this.state32 = u32(this.state);
819
+ }
820
+ clone() {
821
+ return this._cloneInto();
822
+ }
823
+ keccak() {
824
+ swap32IfBE(this.state32);
825
+ keccakP(this.state32, this.rounds);
826
+ swap32IfBE(this.state32);
827
+ this.posOut = 0;
828
+ this.pos = 0;
829
+ }
830
+ update(data) {
831
+ aexists(this);
832
+ data = toBytes(data);
833
+ abytes(data);
834
+ const { blockLen, state } = this;
835
+ const len = data.length;
836
+ for (let pos = 0; pos < len; ) {
837
+ const take = Math.min(blockLen - this.pos, len - pos);
838
+ for (let i = 0; i < take; i++)
839
+ state[this.pos++] ^= data[pos++];
840
+ if (this.pos === blockLen)
841
+ this.keccak();
842
+ }
843
+ return this;
844
+ }
845
+ finish() {
846
+ if (this.finished)
847
+ return;
848
+ this.finished = true;
849
+ const { state, suffix, pos, blockLen } = this;
850
+ state[pos] ^= suffix;
851
+ if ((suffix & 128) !== 0 && pos === blockLen - 1)
852
+ this.keccak();
853
+ state[blockLen - 1] ^= 128;
854
+ this.keccak();
855
+ }
856
+ writeInto(out) {
857
+ aexists(this, false);
858
+ abytes(out);
859
+ this.finish();
860
+ const bufferOut = this.state;
861
+ const { blockLen } = this;
862
+ for (let pos = 0, len = out.length; pos < len; ) {
863
+ if (this.posOut >= blockLen)
864
+ this.keccak();
865
+ const take = Math.min(blockLen - this.posOut, len - pos);
866
+ out.set(bufferOut.subarray(this.posOut, this.posOut + take), pos);
867
+ this.posOut += take;
868
+ pos += take;
869
+ }
870
+ return out;
871
+ }
872
+ xofInto(out) {
873
+ if (!this.enableXOF)
874
+ throw new Error("XOF is not possible for this instance");
875
+ return this.writeInto(out);
876
+ }
877
+ xof(bytes) {
878
+ anumber(bytes);
879
+ return this.xofInto(new Uint8Array(bytes));
880
+ }
881
+ digestInto(out) {
882
+ aoutput(out, this);
883
+ if (this.finished)
884
+ throw new Error("digest() was already called");
885
+ this.writeInto(out);
886
+ this.destroy();
887
+ return out;
888
+ }
889
+ digest() {
890
+ return this.digestInto(new Uint8Array(this.outputLen));
891
+ }
892
+ destroy() {
893
+ this.destroyed = true;
894
+ clean(this.state);
895
+ }
896
+ _cloneInto(to) {
897
+ const { blockLen, suffix, outputLen, rounds, enableXOF } = this;
898
+ to || (to = new _Keccak(blockLen, suffix, outputLen, enableXOF, rounds));
899
+ to.state32.set(this.state32);
900
+ to.pos = this.pos;
901
+ to.posOut = this.posOut;
902
+ to.finished = this.finished;
903
+ to.rounds = rounds;
904
+ to.suffix = suffix;
905
+ to.outputLen = outputLen;
906
+ to.enableXOF = enableXOF;
907
+ to.destroyed = this.destroyed;
908
+ return to;
909
+ }
910
+ };
911
+ var gen = (suffix, blockLen, outputLen) => createHasher(() => new Keccak(blockLen, suffix, outputLen));
912
+ var keccak_256 = /* @__PURE__ */ (() => gen(1, 136, 256 / 8))();
913
+
914
+ // ../../node_modules/@scure/bip39/esm/wordlists/english.js
915
+ var wordlist = `abandon
916
+ ability
917
+ able
918
+ about
919
+ above
920
+ absent
921
+ absorb
922
+ abstract
923
+ absurd
924
+ abuse
925
+ access
926
+ accident
927
+ account
928
+ accuse
929
+ achieve
930
+ acid
931
+ acoustic
932
+ acquire
933
+ across
934
+ act
935
+ action
936
+ actor
937
+ actress
938
+ actual
939
+ adapt
940
+ add
941
+ addict
942
+ address
943
+ adjust
944
+ admit
945
+ adult
946
+ advance
947
+ advice
948
+ aerobic
949
+ affair
950
+ afford
951
+ afraid
952
+ again
953
+ age
954
+ agent
955
+ agree
956
+ ahead
957
+ aim
958
+ air
959
+ airport
960
+ aisle
961
+ alarm
962
+ album
963
+ alcohol
964
+ alert
965
+ alien
966
+ all
967
+ alley
968
+ allow
969
+ almost
970
+ alone
971
+ alpha
972
+ already
973
+ also
974
+ alter
975
+ always
976
+ amateur
977
+ amazing
978
+ among
979
+ amount
980
+ amused
981
+ analyst
982
+ anchor
983
+ ancient
984
+ anger
985
+ angle
986
+ angry
987
+ animal
988
+ ankle
989
+ announce
990
+ annual
991
+ another
992
+ answer
993
+ antenna
994
+ antique
995
+ anxiety
996
+ any
997
+ apart
998
+ apology
999
+ appear
1000
+ apple
1001
+ approve
1002
+ april
1003
+ arch
1004
+ arctic
1005
+ area
1006
+ arena
1007
+ argue
1008
+ arm
1009
+ armed
1010
+ armor
1011
+ army
1012
+ around
1013
+ arrange
1014
+ arrest
1015
+ arrive
1016
+ arrow
1017
+ art
1018
+ artefact
1019
+ artist
1020
+ artwork
1021
+ ask
1022
+ aspect
1023
+ assault
1024
+ asset
1025
+ assist
1026
+ assume
1027
+ asthma
1028
+ athlete
1029
+ atom
1030
+ attack
1031
+ attend
1032
+ attitude
1033
+ attract
1034
+ auction
1035
+ audit
1036
+ august
1037
+ aunt
1038
+ author
1039
+ auto
1040
+ autumn
1041
+ average
1042
+ avocado
1043
+ avoid
1044
+ awake
1045
+ aware
1046
+ away
1047
+ awesome
1048
+ awful
1049
+ awkward
1050
+ axis
1051
+ baby
1052
+ bachelor
1053
+ bacon
1054
+ badge
1055
+ bag
1056
+ balance
1057
+ balcony
1058
+ ball
1059
+ bamboo
1060
+ banana
1061
+ banner
1062
+ bar
1063
+ barely
1064
+ bargain
1065
+ barrel
1066
+ base
1067
+ basic
1068
+ basket
1069
+ battle
1070
+ beach
1071
+ bean
1072
+ beauty
1073
+ because
1074
+ become
1075
+ beef
1076
+ before
1077
+ begin
1078
+ behave
1079
+ behind
1080
+ believe
1081
+ below
1082
+ belt
1083
+ bench
1084
+ benefit
1085
+ best
1086
+ betray
1087
+ better
1088
+ between
1089
+ beyond
1090
+ bicycle
1091
+ bid
1092
+ bike
1093
+ bind
1094
+ biology
1095
+ bird
1096
+ birth
1097
+ bitter
1098
+ black
1099
+ blade
1100
+ blame
1101
+ blanket
1102
+ blast
1103
+ bleak
1104
+ bless
1105
+ blind
1106
+ blood
1107
+ blossom
1108
+ blouse
1109
+ blue
1110
+ blur
1111
+ blush
1112
+ board
1113
+ boat
1114
+ body
1115
+ boil
1116
+ bomb
1117
+ bone
1118
+ bonus
1119
+ book
1120
+ boost
1121
+ border
1122
+ boring
1123
+ borrow
1124
+ boss
1125
+ bottom
1126
+ bounce
1127
+ box
1128
+ boy
1129
+ bracket
1130
+ brain
1131
+ brand
1132
+ brass
1133
+ brave
1134
+ bread
1135
+ breeze
1136
+ brick
1137
+ bridge
1138
+ brief
1139
+ bright
1140
+ bring
1141
+ brisk
1142
+ broccoli
1143
+ broken
1144
+ bronze
1145
+ broom
1146
+ brother
1147
+ brown
1148
+ brush
1149
+ bubble
1150
+ buddy
1151
+ budget
1152
+ buffalo
1153
+ build
1154
+ bulb
1155
+ bulk
1156
+ bullet
1157
+ bundle
1158
+ bunker
1159
+ burden
1160
+ burger
1161
+ burst
1162
+ bus
1163
+ business
1164
+ busy
1165
+ butter
1166
+ buyer
1167
+ buzz
1168
+ cabbage
1169
+ cabin
1170
+ cable
1171
+ cactus
1172
+ cage
1173
+ cake
1174
+ call
1175
+ calm
1176
+ camera
1177
+ camp
1178
+ can
1179
+ canal
1180
+ cancel
1181
+ candy
1182
+ cannon
1183
+ canoe
1184
+ canvas
1185
+ canyon
1186
+ capable
1187
+ capital
1188
+ captain
1189
+ car
1190
+ carbon
1191
+ card
1192
+ cargo
1193
+ carpet
1194
+ carry
1195
+ cart
1196
+ case
1197
+ cash
1198
+ casino
1199
+ castle
1200
+ casual
1201
+ cat
1202
+ catalog
1203
+ catch
1204
+ category
1205
+ cattle
1206
+ caught
1207
+ cause
1208
+ caution
1209
+ cave
1210
+ ceiling
1211
+ celery
1212
+ cement
1213
+ census
1214
+ century
1215
+ cereal
1216
+ certain
1217
+ chair
1218
+ chalk
1219
+ champion
1220
+ change
1221
+ chaos
1222
+ chapter
1223
+ charge
1224
+ chase
1225
+ chat
1226
+ cheap
1227
+ check
1228
+ cheese
1229
+ chef
1230
+ cherry
1231
+ chest
1232
+ chicken
1233
+ chief
1234
+ child
1235
+ chimney
1236
+ choice
1237
+ choose
1238
+ chronic
1239
+ chuckle
1240
+ chunk
1241
+ churn
1242
+ cigar
1243
+ cinnamon
1244
+ circle
1245
+ citizen
1246
+ city
1247
+ civil
1248
+ claim
1249
+ clap
1250
+ clarify
1251
+ claw
1252
+ clay
1253
+ clean
1254
+ clerk
1255
+ clever
1256
+ click
1257
+ client
1258
+ cliff
1259
+ climb
1260
+ clinic
1261
+ clip
1262
+ clock
1263
+ clog
1264
+ close
1265
+ cloth
1266
+ cloud
1267
+ clown
1268
+ club
1269
+ clump
1270
+ cluster
1271
+ clutch
1272
+ coach
1273
+ coast
1274
+ coconut
1275
+ code
1276
+ coffee
1277
+ coil
1278
+ coin
1279
+ collect
1280
+ color
1281
+ column
1282
+ combine
1283
+ come
1284
+ comfort
1285
+ comic
1286
+ common
1287
+ company
1288
+ concert
1289
+ conduct
1290
+ confirm
1291
+ congress
1292
+ connect
1293
+ consider
1294
+ control
1295
+ convince
1296
+ cook
1297
+ cool
1298
+ copper
1299
+ copy
1300
+ coral
1301
+ core
1302
+ corn
1303
+ correct
1304
+ cost
1305
+ cotton
1306
+ couch
1307
+ country
1308
+ couple
1309
+ course
1310
+ cousin
1311
+ cover
1312
+ coyote
1313
+ crack
1314
+ cradle
1315
+ craft
1316
+ cram
1317
+ crane
1318
+ crash
1319
+ crater
1320
+ crawl
1321
+ crazy
1322
+ cream
1323
+ credit
1324
+ creek
1325
+ crew
1326
+ cricket
1327
+ crime
1328
+ crisp
1329
+ critic
1330
+ crop
1331
+ cross
1332
+ crouch
1333
+ crowd
1334
+ crucial
1335
+ cruel
1336
+ cruise
1337
+ crumble
1338
+ crunch
1339
+ crush
1340
+ cry
1341
+ crystal
1342
+ cube
1343
+ culture
1344
+ cup
1345
+ cupboard
1346
+ curious
1347
+ current
1348
+ curtain
1349
+ curve
1350
+ cushion
1351
+ custom
1352
+ cute
1353
+ cycle
1354
+ dad
1355
+ damage
1356
+ damp
1357
+ dance
1358
+ danger
1359
+ daring
1360
+ dash
1361
+ daughter
1362
+ dawn
1363
+ day
1364
+ deal
1365
+ debate
1366
+ debris
1367
+ decade
1368
+ december
1369
+ decide
1370
+ decline
1371
+ decorate
1372
+ decrease
1373
+ deer
1374
+ defense
1375
+ define
1376
+ defy
1377
+ degree
1378
+ delay
1379
+ deliver
1380
+ demand
1381
+ demise
1382
+ denial
1383
+ dentist
1384
+ deny
1385
+ depart
1386
+ depend
1387
+ deposit
1388
+ depth
1389
+ deputy
1390
+ derive
1391
+ describe
1392
+ desert
1393
+ design
1394
+ desk
1395
+ despair
1396
+ destroy
1397
+ detail
1398
+ detect
1399
+ develop
1400
+ device
1401
+ devote
1402
+ diagram
1403
+ dial
1404
+ diamond
1405
+ diary
1406
+ dice
1407
+ diesel
1408
+ diet
1409
+ differ
1410
+ digital
1411
+ dignity
1412
+ dilemma
1413
+ dinner
1414
+ dinosaur
1415
+ direct
1416
+ dirt
1417
+ disagree
1418
+ discover
1419
+ disease
1420
+ dish
1421
+ dismiss
1422
+ disorder
1423
+ display
1424
+ distance
1425
+ divert
1426
+ divide
1427
+ divorce
1428
+ dizzy
1429
+ doctor
1430
+ document
1431
+ dog
1432
+ doll
1433
+ dolphin
1434
+ domain
1435
+ donate
1436
+ donkey
1437
+ donor
1438
+ door
1439
+ dose
1440
+ double
1441
+ dove
1442
+ draft
1443
+ dragon
1444
+ drama
1445
+ drastic
1446
+ draw
1447
+ dream
1448
+ dress
1449
+ drift
1450
+ drill
1451
+ drink
1452
+ drip
1453
+ drive
1454
+ drop
1455
+ drum
1456
+ dry
1457
+ duck
1458
+ dumb
1459
+ dune
1460
+ during
1461
+ dust
1462
+ dutch
1463
+ duty
1464
+ dwarf
1465
+ dynamic
1466
+ eager
1467
+ eagle
1468
+ early
1469
+ earn
1470
+ earth
1471
+ easily
1472
+ east
1473
+ easy
1474
+ echo
1475
+ ecology
1476
+ economy
1477
+ edge
1478
+ edit
1479
+ educate
1480
+ effort
1481
+ egg
1482
+ eight
1483
+ either
1484
+ elbow
1485
+ elder
1486
+ electric
1487
+ elegant
1488
+ element
1489
+ elephant
1490
+ elevator
1491
+ elite
1492
+ else
1493
+ embark
1494
+ embody
1495
+ embrace
1496
+ emerge
1497
+ emotion
1498
+ employ
1499
+ empower
1500
+ empty
1501
+ enable
1502
+ enact
1503
+ end
1504
+ endless
1505
+ endorse
1506
+ enemy
1507
+ energy
1508
+ enforce
1509
+ engage
1510
+ engine
1511
+ enhance
1512
+ enjoy
1513
+ enlist
1514
+ enough
1515
+ enrich
1516
+ enroll
1517
+ ensure
1518
+ enter
1519
+ entire
1520
+ entry
1521
+ envelope
1522
+ episode
1523
+ equal
1524
+ equip
1525
+ era
1526
+ erase
1527
+ erode
1528
+ erosion
1529
+ error
1530
+ erupt
1531
+ escape
1532
+ essay
1533
+ essence
1534
+ estate
1535
+ eternal
1536
+ ethics
1537
+ evidence
1538
+ evil
1539
+ evoke
1540
+ evolve
1541
+ exact
1542
+ example
1543
+ excess
1544
+ exchange
1545
+ excite
1546
+ exclude
1547
+ excuse
1548
+ execute
1549
+ exercise
1550
+ exhaust
1551
+ exhibit
1552
+ exile
1553
+ exist
1554
+ exit
1555
+ exotic
1556
+ expand
1557
+ expect
1558
+ expire
1559
+ explain
1560
+ expose
1561
+ express
1562
+ extend
1563
+ extra
1564
+ eye
1565
+ eyebrow
1566
+ fabric
1567
+ face
1568
+ faculty
1569
+ fade
1570
+ faint
1571
+ faith
1572
+ fall
1573
+ false
1574
+ fame
1575
+ family
1576
+ famous
1577
+ fan
1578
+ fancy
1579
+ fantasy
1580
+ farm
1581
+ fashion
1582
+ fat
1583
+ fatal
1584
+ father
1585
+ fatigue
1586
+ fault
1587
+ favorite
1588
+ feature
1589
+ february
1590
+ federal
1591
+ fee
1592
+ feed
1593
+ feel
1594
+ female
1595
+ fence
1596
+ festival
1597
+ fetch
1598
+ fever
1599
+ few
1600
+ fiber
1601
+ fiction
1602
+ field
1603
+ figure
1604
+ file
1605
+ film
1606
+ filter
1607
+ final
1608
+ find
1609
+ fine
1610
+ finger
1611
+ finish
1612
+ fire
1613
+ firm
1614
+ first
1615
+ fiscal
1616
+ fish
1617
+ fit
1618
+ fitness
1619
+ fix
1620
+ flag
1621
+ flame
1622
+ flash
1623
+ flat
1624
+ flavor
1625
+ flee
1626
+ flight
1627
+ flip
1628
+ float
1629
+ flock
1630
+ floor
1631
+ flower
1632
+ fluid
1633
+ flush
1634
+ fly
1635
+ foam
1636
+ focus
1637
+ fog
1638
+ foil
1639
+ fold
1640
+ follow
1641
+ food
1642
+ foot
1643
+ force
1644
+ forest
1645
+ forget
1646
+ fork
1647
+ fortune
1648
+ forum
1649
+ forward
1650
+ fossil
1651
+ foster
1652
+ found
1653
+ fox
1654
+ fragile
1655
+ frame
1656
+ frequent
1657
+ fresh
1658
+ friend
1659
+ fringe
1660
+ frog
1661
+ front
1662
+ frost
1663
+ frown
1664
+ frozen
1665
+ fruit
1666
+ fuel
1667
+ fun
1668
+ funny
1669
+ furnace
1670
+ fury
1671
+ future
1672
+ gadget
1673
+ gain
1674
+ galaxy
1675
+ gallery
1676
+ game
1677
+ gap
1678
+ garage
1679
+ garbage
1680
+ garden
1681
+ garlic
1682
+ garment
1683
+ gas
1684
+ gasp
1685
+ gate
1686
+ gather
1687
+ gauge
1688
+ gaze
1689
+ general
1690
+ genius
1691
+ genre
1692
+ gentle
1693
+ genuine
1694
+ gesture
1695
+ ghost
1696
+ giant
1697
+ gift
1698
+ giggle
1699
+ ginger
1700
+ giraffe
1701
+ girl
1702
+ give
1703
+ glad
1704
+ glance
1705
+ glare
1706
+ glass
1707
+ glide
1708
+ glimpse
1709
+ globe
1710
+ gloom
1711
+ glory
1712
+ glove
1713
+ glow
1714
+ glue
1715
+ goat
1716
+ goddess
1717
+ gold
1718
+ good
1719
+ goose
1720
+ gorilla
1721
+ gospel
1722
+ gossip
1723
+ govern
1724
+ gown
1725
+ grab
1726
+ grace
1727
+ grain
1728
+ grant
1729
+ grape
1730
+ grass
1731
+ gravity
1732
+ great
1733
+ green
1734
+ grid
1735
+ grief
1736
+ grit
1737
+ grocery
1738
+ group
1739
+ grow
1740
+ grunt
1741
+ guard
1742
+ guess
1743
+ guide
1744
+ guilt
1745
+ guitar
1746
+ gun
1747
+ gym
1748
+ habit
1749
+ hair
1750
+ half
1751
+ hammer
1752
+ hamster
1753
+ hand
1754
+ happy
1755
+ harbor
1756
+ hard
1757
+ harsh
1758
+ harvest
1759
+ hat
1760
+ have
1761
+ hawk
1762
+ hazard
1763
+ head
1764
+ health
1765
+ heart
1766
+ heavy
1767
+ hedgehog
1768
+ height
1769
+ hello
1770
+ helmet
1771
+ help
1772
+ hen
1773
+ hero
1774
+ hidden
1775
+ high
1776
+ hill
1777
+ hint
1778
+ hip
1779
+ hire
1780
+ history
1781
+ hobby
1782
+ hockey
1783
+ hold
1784
+ hole
1785
+ holiday
1786
+ hollow
1787
+ home
1788
+ honey
1789
+ hood
1790
+ hope
1791
+ horn
1792
+ horror
1793
+ horse
1794
+ hospital
1795
+ host
1796
+ hotel
1797
+ hour
1798
+ hover
1799
+ hub
1800
+ huge
1801
+ human
1802
+ humble
1803
+ humor
1804
+ hundred
1805
+ hungry
1806
+ hunt
1807
+ hurdle
1808
+ hurry
1809
+ hurt
1810
+ husband
1811
+ hybrid
1812
+ ice
1813
+ icon
1814
+ idea
1815
+ identify
1816
+ idle
1817
+ ignore
1818
+ ill
1819
+ illegal
1820
+ illness
1821
+ image
1822
+ imitate
1823
+ immense
1824
+ immune
1825
+ impact
1826
+ impose
1827
+ improve
1828
+ impulse
1829
+ inch
1830
+ include
1831
+ income
1832
+ increase
1833
+ index
1834
+ indicate
1835
+ indoor
1836
+ industry
1837
+ infant
1838
+ inflict
1839
+ inform
1840
+ inhale
1841
+ inherit
1842
+ initial
1843
+ inject
1844
+ injury
1845
+ inmate
1846
+ inner
1847
+ innocent
1848
+ input
1849
+ inquiry
1850
+ insane
1851
+ insect
1852
+ inside
1853
+ inspire
1854
+ install
1855
+ intact
1856
+ interest
1857
+ into
1858
+ invest
1859
+ invite
1860
+ involve
1861
+ iron
1862
+ island
1863
+ isolate
1864
+ issue
1865
+ item
1866
+ ivory
1867
+ jacket
1868
+ jaguar
1869
+ jar
1870
+ jazz
1871
+ jealous
1872
+ jeans
1873
+ jelly
1874
+ jewel
1875
+ job
1876
+ join
1877
+ joke
1878
+ journey
1879
+ joy
1880
+ judge
1881
+ juice
1882
+ jump
1883
+ jungle
1884
+ junior
1885
+ junk
1886
+ just
1887
+ kangaroo
1888
+ keen
1889
+ keep
1890
+ ketchup
1891
+ key
1892
+ kick
1893
+ kid
1894
+ kidney
1895
+ kind
1896
+ kingdom
1897
+ kiss
1898
+ kit
1899
+ kitchen
1900
+ kite
1901
+ kitten
1902
+ kiwi
1903
+ knee
1904
+ knife
1905
+ knock
1906
+ know
1907
+ lab
1908
+ label
1909
+ labor
1910
+ ladder
1911
+ lady
1912
+ lake
1913
+ lamp
1914
+ language
1915
+ laptop
1916
+ large
1917
+ later
1918
+ latin
1919
+ laugh
1920
+ laundry
1921
+ lava
1922
+ law
1923
+ lawn
1924
+ lawsuit
1925
+ layer
1926
+ lazy
1927
+ leader
1928
+ leaf
1929
+ learn
1930
+ leave
1931
+ lecture
1932
+ left
1933
+ leg
1934
+ legal
1935
+ legend
1936
+ leisure
1937
+ lemon
1938
+ lend
1939
+ length
1940
+ lens
1941
+ leopard
1942
+ lesson
1943
+ letter
1944
+ level
1945
+ liar
1946
+ liberty
1947
+ library
1948
+ license
1949
+ life
1950
+ lift
1951
+ light
1952
+ like
1953
+ limb
1954
+ limit
1955
+ link
1956
+ lion
1957
+ liquid
1958
+ list
1959
+ little
1960
+ live
1961
+ lizard
1962
+ load
1963
+ loan
1964
+ lobster
1965
+ local
1966
+ lock
1967
+ logic
1968
+ lonely
1969
+ long
1970
+ loop
1971
+ lottery
1972
+ loud
1973
+ lounge
1974
+ love
1975
+ loyal
1976
+ lucky
1977
+ luggage
1978
+ lumber
1979
+ lunar
1980
+ lunch
1981
+ luxury
1982
+ lyrics
1983
+ machine
1984
+ mad
1985
+ magic
1986
+ magnet
1987
+ maid
1988
+ mail
1989
+ main
1990
+ major
1991
+ make
1992
+ mammal
1993
+ man
1994
+ manage
1995
+ mandate
1996
+ mango
1997
+ mansion
1998
+ manual
1999
+ maple
2000
+ marble
2001
+ march
2002
+ margin
2003
+ marine
2004
+ market
2005
+ marriage
2006
+ mask
2007
+ mass
2008
+ master
2009
+ match
2010
+ material
2011
+ math
2012
+ matrix
2013
+ matter
2014
+ maximum
2015
+ maze
2016
+ meadow
2017
+ mean
2018
+ measure
2019
+ meat
2020
+ mechanic
2021
+ medal
2022
+ media
2023
+ melody
2024
+ melt
2025
+ member
2026
+ memory
2027
+ mention
2028
+ menu
2029
+ mercy
2030
+ merge
2031
+ merit
2032
+ merry
2033
+ mesh
2034
+ message
2035
+ metal
2036
+ method
2037
+ middle
2038
+ midnight
2039
+ milk
2040
+ million
2041
+ mimic
2042
+ mind
2043
+ minimum
2044
+ minor
2045
+ minute
2046
+ miracle
2047
+ mirror
2048
+ misery
2049
+ miss
2050
+ mistake
2051
+ mix
2052
+ mixed
2053
+ mixture
2054
+ mobile
2055
+ model
2056
+ modify
2057
+ mom
2058
+ moment
2059
+ monitor
2060
+ monkey
2061
+ monster
2062
+ month
2063
+ moon
2064
+ moral
2065
+ more
2066
+ morning
2067
+ mosquito
2068
+ mother
2069
+ motion
2070
+ motor
2071
+ mountain
2072
+ mouse
2073
+ move
2074
+ movie
2075
+ much
2076
+ muffin
2077
+ mule
2078
+ multiply
2079
+ muscle
2080
+ museum
2081
+ mushroom
2082
+ music
2083
+ must
2084
+ mutual
2085
+ myself
2086
+ mystery
2087
+ myth
2088
+ naive
2089
+ name
2090
+ napkin
2091
+ narrow
2092
+ nasty
2093
+ nation
2094
+ nature
2095
+ near
2096
+ neck
2097
+ need
2098
+ negative
2099
+ neglect
2100
+ neither
2101
+ nephew
2102
+ nerve
2103
+ nest
2104
+ net
2105
+ network
2106
+ neutral
2107
+ never
2108
+ news
2109
+ next
2110
+ nice
2111
+ night
2112
+ noble
2113
+ noise
2114
+ nominee
2115
+ noodle
2116
+ normal
2117
+ north
2118
+ nose
2119
+ notable
2120
+ note
2121
+ nothing
2122
+ notice
2123
+ novel
2124
+ now
2125
+ nuclear
2126
+ number
2127
+ nurse
2128
+ nut
2129
+ oak
2130
+ obey
2131
+ object
2132
+ oblige
2133
+ obscure
2134
+ observe
2135
+ obtain
2136
+ obvious
2137
+ occur
2138
+ ocean
2139
+ october
2140
+ odor
2141
+ off
2142
+ offer
2143
+ office
2144
+ often
2145
+ oil
2146
+ okay
2147
+ old
2148
+ olive
2149
+ olympic
2150
+ omit
2151
+ once
2152
+ one
2153
+ onion
2154
+ online
2155
+ only
2156
+ open
2157
+ opera
2158
+ opinion
2159
+ oppose
2160
+ option
2161
+ orange
2162
+ orbit
2163
+ orchard
2164
+ order
2165
+ ordinary
2166
+ organ
2167
+ orient
2168
+ original
2169
+ orphan
2170
+ ostrich
2171
+ other
2172
+ outdoor
2173
+ outer
2174
+ output
2175
+ outside
2176
+ oval
2177
+ oven
2178
+ over
2179
+ own
2180
+ owner
2181
+ oxygen
2182
+ oyster
2183
+ ozone
2184
+ pact
2185
+ paddle
2186
+ page
2187
+ pair
2188
+ palace
2189
+ palm
2190
+ panda
2191
+ panel
2192
+ panic
2193
+ panther
2194
+ paper
2195
+ parade
2196
+ parent
2197
+ park
2198
+ parrot
2199
+ party
2200
+ pass
2201
+ patch
2202
+ path
2203
+ patient
2204
+ patrol
2205
+ pattern
2206
+ pause
2207
+ pave
2208
+ payment
2209
+ peace
2210
+ peanut
2211
+ pear
2212
+ peasant
2213
+ pelican
2214
+ pen
2215
+ penalty
2216
+ pencil
2217
+ people
2218
+ pepper
2219
+ perfect
2220
+ permit
2221
+ person
2222
+ pet
2223
+ phone
2224
+ photo
2225
+ phrase
2226
+ physical
2227
+ piano
2228
+ picnic
2229
+ picture
2230
+ piece
2231
+ pig
2232
+ pigeon
2233
+ pill
2234
+ pilot
2235
+ pink
2236
+ pioneer
2237
+ pipe
2238
+ pistol
2239
+ pitch
2240
+ pizza
2241
+ place
2242
+ planet
2243
+ plastic
2244
+ plate
2245
+ play
2246
+ please
2247
+ pledge
2248
+ pluck
2249
+ plug
2250
+ plunge
2251
+ poem
2252
+ poet
2253
+ point
2254
+ polar
2255
+ pole
2256
+ police
2257
+ pond
2258
+ pony
2259
+ pool
2260
+ popular
2261
+ portion
2262
+ position
2263
+ possible
2264
+ post
2265
+ potato
2266
+ pottery
2267
+ poverty
2268
+ powder
2269
+ power
2270
+ practice
2271
+ praise
2272
+ predict
2273
+ prefer
2274
+ prepare
2275
+ present
2276
+ pretty
2277
+ prevent
2278
+ price
2279
+ pride
2280
+ primary
2281
+ print
2282
+ priority
2283
+ prison
2284
+ private
2285
+ prize
2286
+ problem
2287
+ process
2288
+ produce
2289
+ profit
2290
+ program
2291
+ project
2292
+ promote
2293
+ proof
2294
+ property
2295
+ prosper
2296
+ protect
2297
+ proud
2298
+ provide
2299
+ public
2300
+ pudding
2301
+ pull
2302
+ pulp
2303
+ pulse
2304
+ pumpkin
2305
+ punch
2306
+ pupil
2307
+ puppy
2308
+ purchase
2309
+ purity
2310
+ purpose
2311
+ purse
2312
+ push
2313
+ put
2314
+ puzzle
2315
+ pyramid
2316
+ quality
2317
+ quantum
2318
+ quarter
2319
+ question
2320
+ quick
2321
+ quit
2322
+ quiz
2323
+ quote
2324
+ rabbit
2325
+ raccoon
2326
+ race
2327
+ rack
2328
+ radar
2329
+ radio
2330
+ rail
2331
+ rain
2332
+ raise
2333
+ rally
2334
+ ramp
2335
+ ranch
2336
+ random
2337
+ range
2338
+ rapid
2339
+ rare
2340
+ rate
2341
+ rather
2342
+ raven
2343
+ raw
2344
+ razor
2345
+ ready
2346
+ real
2347
+ reason
2348
+ rebel
2349
+ rebuild
2350
+ recall
2351
+ receive
2352
+ recipe
2353
+ record
2354
+ recycle
2355
+ reduce
2356
+ reflect
2357
+ reform
2358
+ refuse
2359
+ region
2360
+ regret
2361
+ regular
2362
+ reject
2363
+ relax
2364
+ release
2365
+ relief
2366
+ rely
2367
+ remain
2368
+ remember
2369
+ remind
2370
+ remove
2371
+ render
2372
+ renew
2373
+ rent
2374
+ reopen
2375
+ repair
2376
+ repeat
2377
+ replace
2378
+ report
2379
+ require
2380
+ rescue
2381
+ resemble
2382
+ resist
2383
+ resource
2384
+ response
2385
+ result
2386
+ retire
2387
+ retreat
2388
+ return
2389
+ reunion
2390
+ reveal
2391
+ review
2392
+ reward
2393
+ rhythm
2394
+ rib
2395
+ ribbon
2396
+ rice
2397
+ rich
2398
+ ride
2399
+ ridge
2400
+ rifle
2401
+ right
2402
+ rigid
2403
+ ring
2404
+ riot
2405
+ ripple
2406
+ risk
2407
+ ritual
2408
+ rival
2409
+ river
2410
+ road
2411
+ roast
2412
+ robot
2413
+ robust
2414
+ rocket
2415
+ romance
2416
+ roof
2417
+ rookie
2418
+ room
2419
+ rose
2420
+ rotate
2421
+ rough
2422
+ round
2423
+ route
2424
+ royal
2425
+ rubber
2426
+ rude
2427
+ rug
2428
+ rule
2429
+ run
2430
+ runway
2431
+ rural
2432
+ sad
2433
+ saddle
2434
+ sadness
2435
+ safe
2436
+ sail
2437
+ salad
2438
+ salmon
2439
+ salon
2440
+ salt
2441
+ salute
2442
+ same
2443
+ sample
2444
+ sand
2445
+ satisfy
2446
+ satoshi
2447
+ sauce
2448
+ sausage
2449
+ save
2450
+ say
2451
+ scale
2452
+ scan
2453
+ scare
2454
+ scatter
2455
+ scene
2456
+ scheme
2457
+ school
2458
+ science
2459
+ scissors
2460
+ scorpion
2461
+ scout
2462
+ scrap
2463
+ screen
2464
+ script
2465
+ scrub
2466
+ sea
2467
+ search
2468
+ season
2469
+ seat
2470
+ second
2471
+ secret
2472
+ section
2473
+ security
2474
+ seed
2475
+ seek
2476
+ segment
2477
+ select
2478
+ sell
2479
+ seminar
2480
+ senior
2481
+ sense
2482
+ sentence
2483
+ series
2484
+ service
2485
+ session
2486
+ settle
2487
+ setup
2488
+ seven
2489
+ shadow
2490
+ shaft
2491
+ shallow
2492
+ share
2493
+ shed
2494
+ shell
2495
+ sheriff
2496
+ shield
2497
+ shift
2498
+ shine
2499
+ ship
2500
+ shiver
2501
+ shock
2502
+ shoe
2503
+ shoot
2504
+ shop
2505
+ short
2506
+ shoulder
2507
+ shove
2508
+ shrimp
2509
+ shrug
2510
+ shuffle
2511
+ shy
2512
+ sibling
2513
+ sick
2514
+ side
2515
+ siege
2516
+ sight
2517
+ sign
2518
+ silent
2519
+ silk
2520
+ silly
2521
+ silver
2522
+ similar
2523
+ simple
2524
+ since
2525
+ sing
2526
+ siren
2527
+ sister
2528
+ situate
2529
+ six
2530
+ size
2531
+ skate
2532
+ sketch
2533
+ ski
2534
+ skill
2535
+ skin
2536
+ skirt
2537
+ skull
2538
+ slab
2539
+ slam
2540
+ sleep
2541
+ slender
2542
+ slice
2543
+ slide
2544
+ slight
2545
+ slim
2546
+ slogan
2547
+ slot
2548
+ slow
2549
+ slush
2550
+ small
2551
+ smart
2552
+ smile
2553
+ smoke
2554
+ smooth
2555
+ snack
2556
+ snake
2557
+ snap
2558
+ sniff
2559
+ snow
2560
+ soap
2561
+ soccer
2562
+ social
2563
+ sock
2564
+ soda
2565
+ soft
2566
+ solar
2567
+ soldier
2568
+ solid
2569
+ solution
2570
+ solve
2571
+ someone
2572
+ song
2573
+ soon
2574
+ sorry
2575
+ sort
2576
+ soul
2577
+ sound
2578
+ soup
2579
+ source
2580
+ south
2581
+ space
2582
+ spare
2583
+ spatial
2584
+ spawn
2585
+ speak
2586
+ special
2587
+ speed
2588
+ spell
2589
+ spend
2590
+ sphere
2591
+ spice
2592
+ spider
2593
+ spike
2594
+ spin
2595
+ spirit
2596
+ split
2597
+ spoil
2598
+ sponsor
2599
+ spoon
2600
+ sport
2601
+ spot
2602
+ spray
2603
+ spread
2604
+ spring
2605
+ spy
2606
+ square
2607
+ squeeze
2608
+ squirrel
2609
+ stable
2610
+ stadium
2611
+ staff
2612
+ stage
2613
+ stairs
2614
+ stamp
2615
+ stand
2616
+ start
2617
+ state
2618
+ stay
2619
+ steak
2620
+ steel
2621
+ stem
2622
+ step
2623
+ stereo
2624
+ stick
2625
+ still
2626
+ sting
2627
+ stock
2628
+ stomach
2629
+ stone
2630
+ stool
2631
+ story
2632
+ stove
2633
+ strategy
2634
+ street
2635
+ strike
2636
+ strong
2637
+ struggle
2638
+ student
2639
+ stuff
2640
+ stumble
2641
+ style
2642
+ subject
2643
+ submit
2644
+ subway
2645
+ success
2646
+ such
2647
+ sudden
2648
+ suffer
2649
+ sugar
2650
+ suggest
2651
+ suit
2652
+ summer
2653
+ sun
2654
+ sunny
2655
+ sunset
2656
+ super
2657
+ supply
2658
+ supreme
2659
+ sure
2660
+ surface
2661
+ surge
2662
+ surprise
2663
+ surround
2664
+ survey
2665
+ suspect
2666
+ sustain
2667
+ swallow
2668
+ swamp
2669
+ swap
2670
+ swarm
2671
+ swear
2672
+ sweet
2673
+ swift
2674
+ swim
2675
+ swing
2676
+ switch
2677
+ sword
2678
+ symbol
2679
+ symptom
2680
+ syrup
2681
+ system
2682
+ table
2683
+ tackle
2684
+ tag
2685
+ tail
2686
+ talent
2687
+ talk
2688
+ tank
2689
+ tape
2690
+ target
2691
+ task
2692
+ taste
2693
+ tattoo
2694
+ taxi
2695
+ teach
2696
+ team
2697
+ tell
2698
+ ten
2699
+ tenant
2700
+ tennis
2701
+ tent
2702
+ term
2703
+ test
2704
+ text
2705
+ thank
2706
+ that
2707
+ theme
2708
+ then
2709
+ theory
2710
+ there
2711
+ they
2712
+ thing
2713
+ this
2714
+ thought
2715
+ three
2716
+ thrive
2717
+ throw
2718
+ thumb
2719
+ thunder
2720
+ ticket
2721
+ tide
2722
+ tiger
2723
+ tilt
2724
+ timber
2725
+ time
2726
+ tiny
2727
+ tip
2728
+ tired
2729
+ tissue
2730
+ title
2731
+ toast
2732
+ tobacco
2733
+ today
2734
+ toddler
2735
+ toe
2736
+ together
2737
+ toilet
2738
+ token
2739
+ tomato
2740
+ tomorrow
2741
+ tone
2742
+ tongue
2743
+ tonight
2744
+ tool
2745
+ tooth
2746
+ top
2747
+ topic
2748
+ topple
2749
+ torch
2750
+ tornado
2751
+ tortoise
2752
+ toss
2753
+ total
2754
+ tourist
2755
+ toward
2756
+ tower
2757
+ town
2758
+ toy
2759
+ track
2760
+ trade
2761
+ traffic
2762
+ tragic
2763
+ train
2764
+ transfer
2765
+ trap
2766
+ trash
2767
+ travel
2768
+ tray
2769
+ treat
2770
+ tree
2771
+ trend
2772
+ trial
2773
+ tribe
2774
+ trick
2775
+ trigger
2776
+ trim
2777
+ trip
2778
+ trophy
2779
+ trouble
2780
+ truck
2781
+ true
2782
+ truly
2783
+ trumpet
2784
+ trust
2785
+ truth
2786
+ try
2787
+ tube
2788
+ tuition
2789
+ tumble
2790
+ tuna
2791
+ tunnel
2792
+ turkey
2793
+ turn
2794
+ turtle
2795
+ twelve
2796
+ twenty
2797
+ twice
2798
+ twin
2799
+ twist
2800
+ two
2801
+ type
2802
+ typical
2803
+ ugly
2804
+ umbrella
2805
+ unable
2806
+ unaware
2807
+ uncle
2808
+ uncover
2809
+ under
2810
+ undo
2811
+ unfair
2812
+ unfold
2813
+ unhappy
2814
+ uniform
2815
+ unique
2816
+ unit
2817
+ universe
2818
+ unknown
2819
+ unlock
2820
+ until
2821
+ unusual
2822
+ unveil
2823
+ update
2824
+ upgrade
2825
+ uphold
2826
+ upon
2827
+ upper
2828
+ upset
2829
+ urban
2830
+ urge
2831
+ usage
2832
+ use
2833
+ used
2834
+ useful
2835
+ useless
2836
+ usual
2837
+ utility
2838
+ vacant
2839
+ vacuum
2840
+ vague
2841
+ valid
2842
+ valley
2843
+ valve
2844
+ van
2845
+ vanish
2846
+ vapor
2847
+ various
2848
+ vast
2849
+ vault
2850
+ vehicle
2851
+ velvet
2852
+ vendor
2853
+ venture
2854
+ venue
2855
+ verb
2856
+ verify
2857
+ version
2858
+ very
2859
+ vessel
2860
+ veteran
2861
+ viable
2862
+ vibrant
2863
+ vicious
2864
+ victory
2865
+ video
2866
+ view
2867
+ village
2868
+ vintage
2869
+ violin
2870
+ virtual
2871
+ virus
2872
+ visa
2873
+ visit
2874
+ visual
2875
+ vital
2876
+ vivid
2877
+ vocal
2878
+ voice
2879
+ void
2880
+ volcano
2881
+ volume
2882
+ vote
2883
+ voyage
2884
+ wage
2885
+ wagon
2886
+ wait
2887
+ walk
2888
+ wall
2889
+ walnut
2890
+ want
2891
+ warfare
2892
+ warm
2893
+ warrior
2894
+ wash
2895
+ wasp
2896
+ waste
2897
+ water
2898
+ wave
2899
+ way
2900
+ wealth
2901
+ weapon
2902
+ wear
2903
+ weasel
2904
+ weather
2905
+ web
2906
+ wedding
2907
+ weekend
2908
+ weird
2909
+ welcome
2910
+ west
2911
+ wet
2912
+ whale
2913
+ what
2914
+ wheat
2915
+ wheel
2916
+ when
2917
+ where
2918
+ whip
2919
+ whisper
2920
+ wide
2921
+ width
2922
+ wife
2923
+ wild
2924
+ will
2925
+ win
2926
+ window
2927
+ wine
2928
+ wing
2929
+ wink
2930
+ winner
2931
+ winter
2932
+ wire
2933
+ wisdom
2934
+ wise
2935
+ wish
2936
+ witness
2937
+ wolf
2938
+ woman
2939
+ wonder
2940
+ wood
2941
+ wool
2942
+ word
2943
+ work
2944
+ world
2945
+ worry
2946
+ worth
2947
+ wrap
2948
+ wreck
2949
+ wrestle
2950
+ wrist
2951
+ write
2952
+ wrong
2953
+ yard
2954
+ year
2955
+ yellow
2956
+ you
2957
+ young
2958
+ youth
2959
+ zebra
2960
+ zero
2961
+ zone
2962
+ zoo`.split("\n");
2963
+
2964
+ // src/secret-check.ts
2965
+ var MAX_FEEDBACK_TEXT_LENGTH = 4e3;
2966
+ function refusal(layer, reason, message) {
2967
+ return { layer, reason, message };
2968
+ }
2969
+ var LABELLED_PATTERNS = [
2970
+ { reason: "agent_api_key", re: /sk_agent_[A-Za-z0-9]/ },
2971
+ { reason: "setup_token", re: /hv_setup_[A-Za-z0-9]/ },
2972
+ // A session JWT: three dot-separated base64url parts, each non-empty.
2973
+ // `\beyJ` (not the looser `\bey`), which is the base64url encoding of `{"`
2974
+ // — every real JWT header starts there, and the tighter anchor stops
2975
+ // ordinary words like "eyebrow" or "eyelet" from matching their own tail.
2976
+ { reason: "session_jwt", re: /\beyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\b/ },
2977
+ // key= / api_key= / api-key= / apikey= / token= / secret=, `\b`-bounded —
2978
+ // the same boundary `redact-vendor-secrets.ts:19` uses.
2979
+ { reason: "labelled_parameter", re: /\b(api[_-]?key|key|token|secret)=[^&\s"'\\)]+/i },
2980
+ { reason: "url_credentials", re: /https?:\/\/[^\s/@]+:[^\s@]+@/i },
2981
+ { reason: "rpc_path_key", re: /\/(?:rpc|v2)\/[A-Za-z0-9_-]{16,}/ }
2982
+ ];
2983
+ function checkLabelledSecrets(text) {
2984
+ for (const { reason, re } of LABELLED_PATTERNS) {
2985
+ if (re.test(text)) {
2986
+ return refusal(
2987
+ 1,
2988
+ reason,
2989
+ "Refusing to send: the text looks like it contains a secret (a credential label or prefix matched). Remove it and try again."
2990
+ );
2991
+ }
2992
+ }
2993
+ return null;
2994
+ }
2995
+ function normalize(value) {
2996
+ return value.trim().toLowerCase().replace(/^0x/, "");
2997
+ }
2998
+ async function readJsonStringField(path, field) {
2999
+ try {
3000
+ const raw = await promises.readFile(path, "utf8");
3001
+ const parsed = JSON.parse(raw);
3002
+ const value = parsed[field];
3003
+ return typeof value === "string" && value.length > 0 ? value : null;
3004
+ } catch {
3005
+ return null;
3006
+ }
3007
+ }
3008
+ async function readLocalSecrets(sources = {}) {
3009
+ const secrets = /* @__PURE__ */ new Set();
3010
+ const env = sources.env ?? process.env;
3011
+ const envKey = env.HAVEN_DELEGATE_KEY;
3012
+ if (envKey) secrets.add(normalize(envKey));
3013
+ if (sources.sessionToken) secrets.add(normalize(sources.sessionToken));
3014
+ const root = sources.baseDir ?? path.join(os.homedir(), ".haven", "agents");
3015
+ let entries = [];
3016
+ try {
3017
+ entries = await promises.readdir(root);
3018
+ } catch {
3019
+ return secrets;
3020
+ }
3021
+ for (const entry of entries) {
3022
+ const dir = path.join(root, entry);
3023
+ const delegateKey = await readJsonStringField(path.join(dir, "signer.json"), "delegate_key");
3024
+ if (delegateKey) secrets.add(normalize(delegateKey));
3025
+ const apiKey = await readJsonStringField(path.join(dir, "identity.json"), "api_key");
3026
+ if (apiKey) secrets.add(normalize(apiKey));
3027
+ const pendingKey = await readJsonStringField(path.join(dir, "rekey-pending.json"), "new_delegate_key");
3028
+ if (pendingKey) secrets.add(normalize(pendingKey));
3029
+ }
3030
+ return secrets;
3031
+ }
3032
+ function checkExactSecretMatch(text, secrets) {
3033
+ if (secrets.size === 0) return null;
3034
+ const haystack = text.toLowerCase();
3035
+ for (const secret of secrets) {
3036
+ if (secret.length >= 8 && haystack.includes(secret)) {
3037
+ return refusal(
3038
+ 2,
3039
+ "local_credential",
3040
+ "Refusing to send: the text contains a credential this machine holds (an agent delegate key, an agent API key, a pending re-key, or your own session token). Remove it and try again."
3041
+ );
3042
+ }
3043
+ }
3044
+ return null;
3045
+ }
3046
+ function findHexTokenCandidates(text) {
3047
+ const matches = text.matchAll(/(?<![0-9a-fA-F])(0x)?([0-9a-fA-F]{64})(?![0-9a-fA-F])/g);
3048
+ return [...matches].map((m) => m[2]);
3049
+ }
3050
+ function deriveAddressFromHexToken(token) {
3051
+ try {
3052
+ const ecdh = crypto.createECDH("secp256k1");
3053
+ ecdh.setPrivateKey(Buffer.from(token, "hex"));
3054
+ const uncompressed = ecdh.getPublicKey();
3055
+ const hash = keccak_256(uncompressed.subarray(1));
3056
+ return `0x${Buffer.from(hash.subarray(12)).toString("hex")}`;
3057
+ } catch {
3058
+ return null;
3059
+ }
3060
+ }
3061
+ async function collectKeyBackedAddresses(api) {
3062
+ const addresses = /* @__PURE__ */ new Set();
3063
+ const { agents } = await api.get("/agents");
3064
+ for (const agent of agents) {
3065
+ if (agent.delegate_address) addresses.add(agent.delegate_address.toLowerCase());
3066
+ }
3067
+ const { accounts } = await api.get("/user/accounts");
3068
+ for (const account of accounts) {
3069
+ if (!account.account_address) continue;
3070
+ const signers = await api.get(
3071
+ `/accounts/hybrid/${account.account_address}/signers?chain_id=${account.chain_id}`
3072
+ );
3073
+ if (signers.owner_address) addresses.add(signers.owner_address.toLowerCase());
3074
+ }
3075
+ return addresses;
3076
+ }
3077
+ async function checkKeyBackedAddresses(text, api) {
3078
+ const candidates = findHexTokenCandidates(text);
3079
+ if (candidates.length === 0) return null;
3080
+ let keyBacked;
3081
+ try {
3082
+ keyBacked = await collectKeyBackedAddresses(api);
3083
+ } catch (err) {
3084
+ if (err instanceof CliApiError && (err.status === 401 || err.status === 403)) {
3085
+ return refusal(
3086
+ 3,
3087
+ "address_check_unavailable",
3088
+ "Refusing to send: could not verify whether the text contains a private key \u2014 your session cannot read the data this check needs. Run `haven login` again; retrying this submission will not help."
3089
+ );
3090
+ }
3091
+ if (err instanceof CliApiError && err.status === 409) {
3092
+ return refusal(
3093
+ 3,
3094
+ "address_check_unavailable",
3095
+ "Refusing to send: could not verify whether the text contains a private key \u2014 one of your accounts' signer configuration is unknown, so there is nothing to compare against. Retrying this submission will not help; contact support."
3096
+ );
3097
+ }
3098
+ return refusal(
3099
+ 3,
3100
+ "address_check_unavailable",
3101
+ "Refusing to send: could not verify whether the text contains a private key (the address check failed). Retry once Haven is reachable."
3102
+ );
3103
+ }
3104
+ for (const token of candidates) {
3105
+ const address = deriveAddressFromHexToken(token);
3106
+ if (address && keyBacked.has(address.toLowerCase())) {
3107
+ return refusal(
3108
+ 3,
3109
+ "private_key",
3110
+ "Refusing to send: the text contains what looks like the private key for one of your agents or accounts. Remove it and try again."
3111
+ );
3112
+ }
3113
+ }
3114
+ return null;
3115
+ }
3116
+ var BIP39_WORDS = new Set(wordlist.map((word) => word.toLowerCase()));
3117
+ var MIN_RECOVERY_PHRASE_WORDS = 12;
3118
+ function checkRecoveryPhrase(text) {
3119
+ const tokens = text.split(/\s+/).map((t) => t.replace(/^[^A-Za-z]+|[^A-Za-z]+$/g, "").toLowerCase());
3120
+ let run2 = 0;
3121
+ for (const token of tokens) {
3122
+ if (token && BIP39_WORDS.has(token)) {
3123
+ run2 += 1;
3124
+ if (run2 >= MIN_RECOVERY_PHRASE_WORDS) {
3125
+ return refusal(
3126
+ 4,
3127
+ "recovery_phrase",
3128
+ "Refusing to send: the text looks like it contains a recovery phrase (12 or more consecutive seed words). Remove it and try again."
3129
+ );
3130
+ }
3131
+ } else {
3132
+ run2 = 0;
3133
+ }
3134
+ }
3135
+ return null;
3136
+ }
3137
+ async function checkTextForSecrets(text, deps) {
3138
+ const layer1 = checkLabelledSecrets(text);
3139
+ if (layer1) return layer1;
3140
+ const localSecrets = await readLocalSecrets(deps.localSecrets);
3141
+ const layer2 = checkExactSecretMatch(text, localSecrets);
3142
+ if (layer2) return layer2;
3143
+ const layer3 = await checkKeyBackedAddresses(text, deps.api);
3144
+ if (layer3) return layer3;
3145
+ return checkRecoveryPhrase(text);
3146
+ }
3147
+
621
3148
  // src/commands.ts
622
3149
  var DEFAULT_API = "https://havenbackend-production-8a00.up.railway.app";
623
- var CLI_VERSION = "0.0.0-dev.202610051332.f032d0a";
3150
+ var CLI_VERSION = "0.0.0-dev.202610061536.ad3de49";
624
3151
  var CLI_CLIENT_IDENTITY = `@haven_ai/cli/${CLI_VERSION}`;
625
3152
  function accountAddressOf(s) {
626
3153
  return s.account_address ?? "";
@@ -641,6 +3168,7 @@ async function run(argv, deps = {}) {
641
3168
  out,
642
3169
  err,
643
3170
  env: deps.env ?? process.env,
3171
+ credentialsBaseDir: deps.credentialsBaseDir,
644
3172
  o
645
3173
  };
646
3174
  let args;
@@ -721,6 +3249,8 @@ async function dispatch(args, d) {
721
3249
  return cmdContactsAdd(args, d);
722
3250
  case "contacts remove":
723
3251
  return cmdContactsRemove(args, d);
3252
+ case "feedback submit":
3253
+ return cmdFeedbackSubmit(args, d);
724
3254
  default:
725
3255
  throw new UsageError(`Unknown command: ${key}.`, "Run `haven --help` for the command list.");
726
3256
  }
@@ -1537,6 +4067,30 @@ async function cmdContactsRemove(args, d) {
1537
4067
  emit(d, args.flags.json, { ok: true, contact_id: id, removed: true }, () => `Contact ${id} removed.`);
1538
4068
  return EXIT.ok;
1539
4069
  }
4070
+ async function cmdFeedbackSubmit(args, d) {
4071
+ const text = args.positionals.join(" ").trim();
4072
+ if (!text) throw new UsageError('Usage: haven feedback submit "<text>"');
4073
+ if ([...text].length > MAX_FEEDBACK_TEXT_LENGTH) {
4074
+ throw new UsageError(`Feedback text must be ${MAX_FEEDBACK_TEXT_LENGTH} characters (code points) or fewer.`);
4075
+ }
4076
+ const { session, api } = await authed(args, d);
4077
+ const refusal2 = await checkTextForSecrets(text, {
4078
+ api,
4079
+ localSecrets: { sessionToken: session.token, env: d.env, baseDir: d.credentialsBaseDir }
4080
+ });
4081
+ if (refusal2) {
4082
+ throw new HavenCliError(refusal2.message, EXIT.refused, `layer ${refusal2.layer}: ${refusal2.reason}`, {
4083
+ layer: refusal2.layer,
4084
+ reason: refusal2.reason
4085
+ });
4086
+ }
4087
+ d.o.note(
4088
+ "Reminder: never include a password or any other credential in feedback text \u2014 this check cannot recognise one by shape."
4089
+ );
4090
+ const result = await api.post("/feedback", { text });
4091
+ emit(d, args.flags.json, { ok: true, ...result }, () => `Feedback submitted (id ${result.id}).`);
4092
+ return EXIT.ok;
4093
+ }
1540
4094
  function promptPasswordWith(streams) {
1541
4095
  return new Promise((resolve2, reject) => {
1542
4096
  const { stdin, stderr } = streams;
@@ -1592,5 +4146,10 @@ run(process.argv.slice(2), { promptPassword }).then((code) => process.exit(code)
1592
4146
  }
1593
4147
  process.exit(1);
1594
4148
  });
4149
+ /*! Bundled license information:
4150
+
4151
+ @noble/hashes/esm/utils.js:
4152
+ (*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) *)
4153
+ */
1595
4154
  //# sourceMappingURL=cli.cjs.map
1596
4155
  //# sourceMappingURL=cli.cjs.map