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