@ghostlytools/cli 1.3.9 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/README.md +13 -4
  2. package/SKILL.md +7 -4
  3. package/dist/assets/{api-Cp9GxjUO.js → api-BqLfti32.js} +2 -2
  4. package/dist/assets/{api-BCrwJ57L.js → api-JMkEO0RR.js} +130 -50
  5. package/dist/assets/api-JMkEO0RR.js.map +1 -0
  6. package/dist/assets/{apiKit-B4qhnLQT.js → apiKit-BpIUCwa-.js} +3 -3
  7. package/dist/assets/{apiKit-B4qhnLQT.js.map → apiKit-BpIUCwa-.js.map} +1 -1
  8. package/dist/assets/{apps-CpxENMgl.js → apps-BdfyGVZ1.js} +1 -1
  9. package/dist/assets/{apps-DOH1P_S0.js → apps-Bettj7WQ.js} +6 -6
  10. package/dist/assets/apps-Bettj7WQ.js.map +1 -0
  11. package/dist/assets/{arkade-Cyf5MGxG.js → arkade-CP4HvKaa.js} +2 -2
  12. package/dist/assets/{arkade-Cyf5MGxG.js.map → arkade-CP4HvKaa.js.map} +1 -1
  13. package/dist/assets/{backup-CqM-0-2v.js → backup-BbO2zLjx.js} +1 -1
  14. package/dist/assets/{backup-CTpFFQ-4.js → backup-BmBtta66.js} +7 -7
  15. package/dist/assets/{backup-CTpFFQ-4.js.map → backup-BmBtta66.js.map} +1 -1
  16. package/dist/assets/blobFiles-B0rNnHlO.js +35 -0
  17. package/dist/assets/blobFiles-B0rNnHlO.js.map +1 -0
  18. package/dist/assets/{buttons-BtxwyM2l.js → buttons-YgijrprJ.js} +4 -4
  19. package/dist/assets/{buttons-BtxwyM2l.js.map → buttons-YgijrprJ.js.map} +1 -1
  20. package/dist/assets/buttons-_GBlxAti.js +2 -0
  21. package/dist/assets/{endpoint-BOTFMpfS.js → endpoint-Cl3cgAYl.js} +3 -2
  22. package/dist/assets/endpoint-Cl3cgAYl.js.map +1 -0
  23. package/dist/assets/{envelope-DW8TWKPD.js → envelope-C7vnmsJN.js} +2 -2
  24. package/dist/assets/{envelope-DW8TWKPD.js.map → envelope-C7vnmsJN.js.map} +1 -1
  25. package/dist/assets/{errors-B-zMxbcd.js → errors-BLSPp0tK.js} +3 -1
  26. package/dist/assets/errors-BLSPp0tK.js.map +1 -0
  27. package/dist/assets/{fileBytes-Di7VZtmU.js → fileBytes-B-fqGdEd.js} +3 -3
  28. package/dist/assets/{fileBytes-Di7VZtmU.js.map → fileBytes-B-fqGdEd.js.map} +1 -1
  29. package/dist/assets/{fileBytes-CgbibpbV.js → fileBytes-C2jycN_7.js} +1 -1
  30. package/dist/assets/{fileBytes-CfSXjTFa.js → fileBytes-D6fqFQEX.js} +6 -3
  31. package/dist/assets/fileBytes-D6fqFQEX.js.map +1 -0
  32. package/dist/assets/fileBytesIdb-DOxm_BKt.js +2 -0
  33. package/dist/assets/{fileBytesIdb-D5u6H8X_.js → fileBytesIdb-_HnxdacI.js} +3 -3
  34. package/dist/assets/{fileBytesIdb-D5u6H8X_.js.map → fileBytesIdb-_HnxdacI.js.map} +1 -1
  35. package/dist/assets/{fileBytesOpfs-Dd1N4ERH.js → fileBytesOpfs-p_CANncD.js} +3 -3
  36. package/dist/assets/{fileBytesOpfs-Dd1N4ERH.js.map → fileBytesOpfs-p_CANncD.js.map} +1 -1
  37. package/dist/assets/{groupFiles-uxa0U9_n.js → groupFiles-sIdGq4AV.js} +5 -5
  38. package/dist/assets/groupFiles-sIdGq4AV.js.map +1 -0
  39. package/dist/assets/{host-DPy0eaH9.js → host-Drd-c4VO.js} +147 -25
  40. package/dist/assets/host-Drd-c4VO.js.map +1 -0
  41. package/dist/assets/{hyperdhtRelay-De5FT7Am.js → hyperdhtRelay-13aQ4KOf.js} +2 -2
  42. package/dist/assets/{hyperdhtRelay-De5FT7Am.js.map → hyperdhtRelay-13aQ4KOf.js.map} +1 -1
  43. package/dist/assets/{idb-B5L8wuOm.js → idb-CMVgtn2k.js} +59 -6
  44. package/dist/assets/idb-CMVgtn2k.js.map +1 -0
  45. package/dist/assets/{irohWeb-z5QDDWa-.js → irohWeb-DHCxSvHF.js} +2 -2
  46. package/dist/assets/{irohWeb-z5QDDWa-.js.map → irohWeb-DHCxSvHF.js.map} +1 -1
  47. package/dist/assets/{main-Dt7xrqtb.js → main-BWAwKY4f.js} +476 -141
  48. package/dist/assets/main-BWAwKY4f.js.map +1 -0
  49. package/dist/assets/{mainline-Cld-bKeC.js → mainline-CsG-DdJ5.js} +2 -2
  50. package/dist/assets/{mainline-Cld-bKeC.js.map → mainline-CsG-DdJ5.js.map} +1 -1
  51. package/dist/assets/{networkReason-vUHo6A_C.js → networkReason-B91upMCb.js} +3 -3
  52. package/dist/assets/{networkReason-vUHo6A_C.js.map → networkReason-B91upMCb.js.map} +1 -1
  53. package/dist/assets/{nwc-zXpmd2FN.js → nwc-BFv67iSz.js} +3 -3
  54. package/dist/assets/{nwc-zXpmd2FN.js.map → nwc-BFv67iSz.js.map} +1 -1
  55. package/dist/assets/{nwcProvider-D482SQ1a.js → nwcProvider-BKNFdH9v.js} +2 -2
  56. package/dist/assets/{nwcProvider-D482SQ1a.js.map → nwcProvider-BKNFdH9v.js.map} +1 -1
  57. package/dist/assets/{profiles-gPCjLOQq.js → profiles-DSxPYdlU.js} +13 -3
  58. package/dist/assets/profiles-DSxPYdlU.js.map +1 -0
  59. package/dist/assets/{registry-CxsDR3c6.js → registry-CHPd_hf7.js} +1 -1
  60. package/dist/assets/{registry-OVx2kY3d.js → registry-qbnWmwCE.js} +3 -3
  61. package/dist/assets/registry-qbnWmwCE.js.map +1 -0
  62. package/dist/assets/{resolve-CPTAnu-9.js → resolve-B63_uSu7.js} +2 -2
  63. package/dist/assets/{resolve-CPTAnu-9.js.map → resolve-B63_uSu7.js.map} +1 -1
  64. package/dist/assets/{restoredRows-Db3oUTko.js → restoredRows-DeBImGRd.js} +2 -2
  65. package/dist/assets/{restoredRows-Db3oUTko.js.map → restoredRows-DeBImGRd.js.map} +1 -1
  66. package/dist/assets/{server-p5DJnN7T.js → server-Cd1dLOB8.js} +1485 -240
  67. package/dist/assets/server-Cd1dLOB8.js.map +1 -0
  68. package/dist/assets/{src-Dg1bvMNv.js → src-DzXL-GYu.js} +7277 -5975
  69. package/dist/assets/src-DzXL-GYu.js.map +1 -0
  70. package/dist/assets/turnRefs-BCtM10d3.js +357 -0
  71. package/dist/assets/turnRefs-BCtM10d3.js.map +1 -0
  72. package/dist/assets/{usdt-BY5OIIvG.js → usdt-B7JWDhQV.js} +3 -3
  73. package/dist/assets/{usdt-BY5OIIvG.js.map → usdt-B7JWDhQV.js.map} +1 -1
  74. package/dist/ghostly.mjs +1 -1
  75. package/package.json +7 -6
  76. package/skills/ghostly/README.md +41 -0
  77. package/skills/ghostly/SKILL.md +79 -0
  78. package/skills/ghostly/scripts/listen +67 -0
  79. package/skills/ghostly/scripts/react +25 -0
  80. package/skills/ghostly/scripts/say +44 -0
  81. package/skills/ghostly/scripts/status +27 -0
  82. package/dist/assets/api-BCrwJ57L.js.map +0 -1
  83. package/dist/assets/apps-DOH1P_S0.js.map +0 -1
  84. package/dist/assets/buttons-CJqNkG-Q.js +0 -2
  85. package/dist/assets/endpoint-BOTFMpfS.js.map +0 -1
  86. package/dist/assets/errors-B-zMxbcd.js.map +0 -1
  87. package/dist/assets/fileBytes-CfSXjTFa.js.map +0 -1
  88. package/dist/assets/fileBytesIdb-CFP-DSkZ.js +0 -2
  89. package/dist/assets/groupFiles-uxa0U9_n.js.map +0 -1
  90. package/dist/assets/host-DPy0eaH9.js.map +0 -1
  91. package/dist/assets/idb-B5L8wuOm.js.map +0 -1
  92. package/dist/assets/main-Dt7xrqtb.js.map +0 -1
  93. package/dist/assets/profiles-gPCjLOQq.js.map +0 -1
  94. package/dist/assets/registry-OVx2kY3d.js.map +0 -1
  95. package/dist/assets/server-p5DJnN7T.js.map +0 -1
  96. package/dist/assets/src-Dg1bvMNv.js.map +0 -1
  97. package/dist/assets/turnRefs-WnggXm2T.js +0 -323
  98. package/dist/assets/turnRefs-WnggXm2T.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main-BWAwKY4f.js","names":["commands","commands","commands","commands","commands","commands","commands","commands","general","chats","groups","files","payments","identities","services","calls","apps","packageJson"],"sources":["../../package.json","../../src/args.ts","../../src/client.ts","../../src/commands/shared.ts","../../src/commands/apps.ts","../../src/commands/calls.ts","../../src/commands/chats.ts","../../src/commands/files.ts","../../src/commands/general.ts","../../src/commands/groups.ts","../../src/commands/identities.ts","../../src/commands/payments.ts","../../src/commands/services.ts","../../src/commands/index.ts","../../src/listen.ts","../../src/secretInput.ts","../../src/main.ts"],"sourcesContent":["{\n \"name\": \"@ghostlytools/cli\",\n \"version\": \"1.4.0\",\n \"type\": \"module\",\n \"description\": \"Ghostly for bots and terminals: the app's own engine, headless on Node, behind a daemon and a `ghostly` command with JSON output.\",\n \"license\": \"MIT\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/MiguelMedeiros/ghostly.git\",\n \"directory\": \"packages/cli\"\n },\n \"homepage\": \"https://ghostly.tools/cli\",\n \"bugs\": \"https://github.com/MiguelMedeiros/ghostly/issues\",\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"bin\": {\n \"ghostly\": \"./dist/ghostly.mjs\"\n },\n \"files\": [\n \"dist\",\n \"examples\",\n \"skills\",\n \"README.md\",\n \"SKILL.md\"\n ],\n \"engines\": {\n \"node\": \">=22.12\"\n },\n \"scripts\": {\n \"build\": \"vite build\",\n \"typecheck\": \"tsc --noEmit -p tsconfig.json\",\n \"test\": \"vitest run\"\n },\n \"dependencies\": {\n \"@arkade-os/sdk\": \"0.4.79\",\n \"@atproto/jwk-webcrypto\": \"^0.3.4\",\n \"@atproto/oauth-client\": \"^0.8.9\",\n \"@bitcoindevkit/bdk-wallet-web\": \"0.3.0\",\n \"@bitcoinerlab/descriptors-scure\": \"^3.2.0\",\n \"@cashu/cashu-ts\": \"^4.11.0\",\n \"@fedimint/core\": \"0.0.0-canary-eea6a3c98909fa8e736d6dadb1f1243fd3322b27\",\n \"@fedimint/fedimint-client-wasm-bundler\": \"0.0.0-canary-eea6a3c98909fa8e736d6dadb1f1243fd3322b27\",\n \"@fedimint/types\": \"0.0.0-canary-eea6a3c98909fa8e736d6dadb1f1243fd3322b27\",\n \"@hyperswarm/dht-relay\": \"0.4.3\",\n \"@noble/ciphers\": \"^2.4.0\",\n \"@noble/curves\": \"^2.4.0\",\n \"@noble/hashes\": \"2.4.0\",\n \"@scure/base\": \"2.4.0\",\n \"@scure/bip32\": \"^2.4.0\",\n \"@scure/bip39\": \"2.4.0\",\n \"@scure/btc-signer\": \"2.4.1\",\n \"@secondts/bark\": \"0.25.0\",\n \"@serenity-kit/opaque\": \"1.1.0\",\n \"@synonymdev/pubky\": \"0.16.1\",\n \"@tetherto/wdk-wallet-evm\": \"1.0.0-beta.20\",\n \"b4a\": \"1.9.0\",\n \"bittorrent-dht\": \"11.0.12\",\n \"ethers\": \"6.17.0\",\n \"eventsource\": \"^5.1.2\",\n \"fake-indexeddb\": \"6.2.5\",\n \"hyperdht\": \"6.34.1\",\n \"keet-identity-key\": \"3.2.0\",\n \"mpg123-decoder\": \"1.0.3\",\n \"node-datachannel\": \"^0.33.4\",\n \"nostr-tools\": \"2.25.2\",\n \"opus-decoder\": \"0.7.12\",\n \"opusscript\": \"0.1.1\"\n },\n \"devDependencies\": {\n \"@ghostly/browser\": \"*\",\n \"@ghostly/core\": \"*\",\n \"@ghostly/iroh-web\": \"*\",\n \"@types/node\": \"^26.6.5\",\n \"typescript\": \"^5.9.3\",\n \"vite\": \"^8.3.4\",\n \"vitest\": \"^5.0.4\"\n }\n}\n","import { CliError } from \"./errors\";\n\nexport type OptionType = \"string\" | \"number\" | \"boolean\" | \"list\";\nexport interface OptionSpec {\n type: OptionType; short?: string; description: string;\n /** A number option that may stand alone (then `true`): it takes the next word only when that is a number. */\n optionalValue?: boolean;\n /** A boolean the command takes only as `--no-<name>`: help shows it so. */\n negatedOnly?: boolean;\n}\nexport interface Parsed { positionals: string[]; options: Record<string, string | number | boolean | string[] | undefined> }\n\n/**\n * Options every command takes. They may come anywhere on the line.\n */\nexport const GLOBAL_OPTIONS: Record<string, OptionSpec> = {\n profile: { type: \"string\", short: \"p\", description: \"Profile to use (default: $GHOSTLY_PROFILE, then the current one)\" },\n home: { type: \"string\", description: \"Ghostly's folder (default: $GHOSTLY_HOME, then ~/.ghostly)\" },\n pretty: { type: \"boolean\", description: \"Indent the JSON output\" },\n help: { type: \"boolean\", short: \"h\", description: \"Show help\" },\n};\n\n/**\n * A small, strict parser: `--name value`, `--name=value`, `-x value`, boolean flags, repeatable lists, and `--`\n * before positionals that start with a dash.\n *\n * The value of an option is taken as is even when it starts with `-` (base64url keys and seeds do one time in 64:\n * the ghostly-cli lesson of #208). So is a positional that `idSlot` says takes an id, a key or a draft: there a word\n * that starts with `-`, is longer than two characters and is no option of the command is the value (`--` starts one\n * id in 4096; `-x` stays an option). Any other positional that starts with `-` is refused instead of sent: a\n * mistyped flag must not reach a contact as text. Put `--` before a message that starts with a dash.\n */\nexport function parseArgs(argv: readonly string[], spec: Record<string, OptionSpec>, idSlot: (index: number) => boolean = () => false): Parsed {\n const all = { ...GLOBAL_OPTIONS, ...spec };\n const byShort = new Map(Object.entries(all).filter(([, s]) => s.short).map(([name, s]) => [s.short!, name]));\n const isOption = (arg: string) => {\n if (!arg.startsWith(\"--\")) return arg.length === 2 && byShort.has(arg.slice(1));\n const name = arg.slice(2).split(\"=\")[0];\n return Object.hasOwn(all, name) || (name.startsWith(\"no-\") && all[name.slice(3)]?.type === \"boolean\");\n };\n const positionals: string[] = [];\n const options: Parsed[\"options\"] = {};\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i];\n if (arg === \"--\") { positionals.push(...argv.slice(i + 1)); break; }\n if (arg.startsWith(\"-\") && arg.length > 2 && idSlot(positionals.length) && !isOption(arg)) { positionals.push(arg); continue; }\n if (arg.startsWith(\"--\") || (arg.startsWith(\"-\") && arg.length === 2 && arg !== \"-\")) {\n let name: string, inline: string | undefined;\n if (arg.startsWith(\"--\")) {\n const eq = arg.indexOf(\"=\");\n name = eq === -1 ? arg.slice(2) : arg.slice(2, eq);\n inline = eq === -1 ? undefined : arg.slice(eq + 1);\n } else {\n const long = byShort.get(arg.slice(1));\n if (!long) throw new CliError(\"usage\", `Unknown option ${arg} (put -- before text that starts with a dash)`);\n name = long;\n }\n if (name.startsWith(\"no-\") && all[name.slice(3)]?.type === \"boolean\" && inline === undefined) { options[name.slice(3)] = false; continue; }\n const option = all[name];\n if (!option) throw new CliError(\"usage\", `Unknown option --${name}`);\n if (option.type === \"boolean\") {\n if (inline !== undefined && ![\"true\", \"false\"].includes(inline)) throw new CliError(\"usage\", `--${name} takes no value`);\n options[name] = inline === undefined ? true : inline === \"true\";\n continue;\n }\n let value = inline;\n if (value === undefined && option.optionalValue && !(i + 1 < argv.length && argv[i + 1] !== \"\" && Number.isFinite(Number(argv[i + 1])))) {\n options[name] = true;\n continue;\n }\n if (value === undefined) {\n if (i + 1 >= argv.length) throw new CliError(\"usage\", `--${name} needs a value`);\n value = argv[++i];\n }\n if (option.type === \"number\") {\n // Number(\"\") and Number(\" \") are 0: an unset variable must not read as 0 and be acted on.\n const number = value.trim() === \"\" ? NaN : Number(value);\n if (!Number.isFinite(number)) throw new CliError(\"usage\", `--${name} takes a number, not ${JSON.stringify(value)}`);\n options[name] = number;\n } else if (option.type === \"list\") {\n options[name] = [...((options[name] as string[] | undefined) ?? []), value];\n } else options[name] = value;\n continue;\n }\n if (arg.startsWith(\"-\") && arg !== \"-\") throw new CliError(\"usage\", `Unknown option ${arg} (put -- before text that starts with a dash)`);\n positionals.push(arg);\n }\n return { positionals, options };\n}\n\n/** The global option a word names (`--profile`, `--profile=bot`, `-p`), else undefined. */\nexport function globalOption(arg: string): OptionSpec | undefined {\n const name = globalName(arg);\n return name ? GLOBAL_OPTIONS[name] : undefined;\n}\n\n/** The name of the global option a word names (`profile` for `-p`, `pretty` for `--no-pretty`), else undefined. */\nfunction globalName(arg: string): string | undefined {\n const eq = arg.indexOf(\"=\");\n const name = arg.startsWith(\"--\") ? arg.slice(2, eq === -1 ? undefined : eq) : arg.length === 2 && arg.startsWith(\"-\") ? Object.entries(GLOBAL_OPTIONS).find(([, o]) => o.short === arg.slice(1))?.[0] : undefined;\n if (name && Object.hasOwn(GLOBAL_OPTIONS, name)) return name;\n // A boolean's `--no-` form, as the parser reads it (with no value): before, `ghostly --no-pretty status` was no command.\n const negated = name?.startsWith(\"no-\") && eq === -1 ? name.slice(3) : undefined;\n return negated && GLOBAL_OPTIONS[negated]?.type === \"boolean\" ? negated : undefined;\n}\n\n/**\n * Global options given before the command (`ghostly --profile bot send …`) move after it, where every command's\n * parser reads them. Stops at `--` and at the first word that is not a global option. They go before the first word\n * after the command's that starts with a dash (its first option, or the `--` that ends them), else at the end: never\n * between an option and its value, which may itself be `--` (`--pretty profile set --name --`). One that takes a value\n * and is the last word has none: a usage error.\n */\nexport function liftGlobals(argv: readonly string[]): string[] {\n const lifted: string[] = [];\n let i = 0;\n while (i < argv.length) {\n const arg = argv[i];\n const eq = arg.indexOf(\"=\");\n const option = globalOption(arg);\n if (!option || arg === \"--\") break;\n const takesValue = option.type !== \"boolean\" && eq === -1;\n // `ghostly -p` alone: a usage error, as `ghostly send -p` is, not the help a line of global options alone shows.\n if (takesValue && i + 1 >= argv.length) throw new CliError(\"usage\", `--${globalName(arg)} needs a value`);\n lifted.push(...argv.slice(i, i + (takesValue ? 2 : 1)));\n i += takesValue ? 2 : 1;\n }\n const rest = argv.slice(i);\n // The first word is the command, also when it is `--version` or `--help`; a `--` there ends the options at once.\n const dash = rest[0] === \"--\" ? 0 : rest.findIndex((word, i) => i > 0 && word.startsWith(\"-\"));\n return dash === -1 ? [...rest, ...lifted] : [...rest.slice(0, dash), ...lifted, ...rest.slice(dash)];\n}\n","import { connect, type Socket } from \"node:net\";\nimport { createInterface } from \"node:readline\";\nimport { CliError, type ErrorCode } from \"./errors\";\nimport type { GhostlyEvent } from \"./events\";\nimport { HELLO, newNonce, provesDaemon, readDaemonSecret } from \"./daemonProof\";\nimport { ownSocket } from \"./privateFolder\";\n\n/** The id of the hello on every connection: a string, so it is never one of the calls' numbers. */\nconst HELLO_ID = \"hello\";\n\n/** What a client needs of a profile to reach its daemon: the socket, and the folder the daemon's secret is in. */\nexport interface DaemonAddress { socket: string; dir: string }\n\n/** The refusal of a listener that did not prove it is the profile's daemon (`isNotTheDaemon` tells it apart). */\nfunction notTheDaemon(socket: string): CliError {\n return new CliError(\"refused\", `What answers on ${socket} did not prove it is this profile's daemon, so nothing was sent to it. A daemon of an older release cannot: \\`ghostly daemon restart\\` starts this one's`, { reason: \"not-the-daemon\" });\n}\n\nexport function isNotTheDaemon(error: unknown): boolean {\n return error instanceof CliError && error.code === \"refused\" && error.details?.reason === \"not-the-daemon\";\n}\n\n/**\n * A connection to a profile's daemon over its socket (WISP 1100 § Local control API). `null` from `connectDaemon`\n * means no daemon answers there: a one-shot command runs the profile itself.\n *\n * The first line on it is a `daemon.hello`, and no call is written until its answer proves the other end read the\n * profile's daemon secret (`daemonProof.ts`): until then every call waits, under its own deadline, and a listener\n * that does not prove it gets every call refused (`refused`, `isNotTheDaemon`) having read nothing but the hello.\n * Nothing it writes before that is read either.\n */\nexport class DaemonClient {\n private nextId = 1;\n private readonly pending = new Map<number, { resolve: (value: unknown) => void; reject: (error: Error) => void }>();\n private eventListener: ((event: GhostlyEvent) => void) | null = null;\n private closedListener: (() => void) | null = null;\n /** While paused: the events of the chunk already read, given to the listener on resume. */\n private held: GhostlyEvent[] | null = null;\n private verified = false;\n private refusal: CliError | null = null;\n private readonly ready: Promise<void>;\n private settle!: { resolve: () => void; reject: (error: CliError) => void };\n\n constructor(private readonly socket: Socket, private readonly address: DaemonAddress) {\n this.ready = new Promise<void>((resolve, reject) => { this.settle = { resolve, reject }; });\n this.ready.catch(() => {});\n const nonce = newNonce();\n createInterface({ input: socket, crlfDelay: Infinity }).on(\"line\", (line) => {\n let message: { id?: number | string; result?: unknown; error?: { code: ErrorCode; message: string; details?: Record<string, unknown> }; event?: GhostlyEvent };\n try { message = JSON.parse(line); } catch { return; }\n if (!this.verified) {\n if (this.refusal || message?.id !== HELLO_ID) return;\n // The secret is read once a listener answered: the daemon wrote it before it listened.\n const secret = readDaemonSecret(this.address.dir);\n if (!message.error && secret && provesDaemon(secret, nonce, message.result)) { this.verified = true; this.settle.resolve(); return; }\n this.refuse();\n return;\n }\n if (message.event) { if (this.held) this.held.push(message.event); else this.eventListener?.(message.event); return; }\n const waiting = typeof message.id === \"number\" ? this.pending.get(message.id) : undefined;\n if (!waiting) return;\n this.pending.delete(message.id as number);\n if (message.error) waiting.reject(new CliError(message.error.code, message.error.message, message.error.details));\n else waiting.resolve(message.result);\n });\n socket.on(\"close\", () => {\n const why = this.refusal ?? new CliError(\"unavailable\", \"The daemon went away\");\n if (!this.verified) this.settle.reject(why);\n for (const waiting of this.pending.values()) waiting.reject(why);\n this.pending.clear();\n this.closedListener?.();\n });\n socket.on(\"error\", () => {});\n socket.write(JSON.stringify({ id: HELLO_ID, method: HELLO, params: { nonce } }) + \"\\n\");\n }\n\n private refuse(): void {\n this.refusal = notTheDaemon(this.address.socket);\n this.settle.reject(this.refusal);\n this.socket.destroy();\n }\n\n /**\n * `timeoutMs`: give up (code `timeout`, exit 4) when the daemon has not answered by then; without it the call waits\n * for as long as the connection holds. A call that timed out closes the connection: its answer, if one ever comes,\n * is of no use, and the process leaves once nothing else keeps it (not every caller reaches `exit`).\n */\n call(method: string, params: unknown = {}, { timeoutMs }: { timeoutMs?: number } = {}): Promise<unknown> {\n if (this.socket.destroyed) return Promise.reject(this.refusal ?? new CliError(\"unavailable\", \"The daemon went away\"));\n const id = this.nextId++;\n return new Promise((resolve, reject) => {\n let timer: ReturnType<typeof setTimeout> | undefined;\n if (timeoutMs !== undefined) {\n timer = setTimeout(() => {\n if (!this.pending.delete(id)) return;\n reject(new CliError(\"timeout\", `The daemon did not answer ${method} in ${timeoutMs / 1000} s: \\`ghostly daemon restart\\` starts a fresh one`, { method }));\n this.destroy();\n }, timeoutMs);\n timer.unref?.();\n }\n const settle = {\n resolve: (value: unknown) => { if (timer) clearTimeout(timer); resolve(value); },\n reject: (error: Error) => { if (timer) clearTimeout(timer); reject(error); },\n };\n this.pending.set(id, settle);\n // Written once the daemon proved itself, in the order the calls were made; a refusal ends each instead.\n this.ready.then(\n () => { if (this.pending.has(id) && !this.socket.destroyed) this.socket.write(JSON.stringify({ id, method, params }) + \"\\n\"); },\n (error: CliError) => { if (this.pending.delete(id)) settle.reject(error); },\n );\n });\n }\n\n /** Events after `since` (replayed from the journal), then every new one, until the connection closes. */\n async subscribe(since: number | undefined, listener: (event: GhostlyEvent) => void, onClosed?: () => void): Promise<{ lastSeq: number }> {\n this.eventListener = listener;\n this.closedListener = onClosed ?? null;\n return this.call(\"events.subscribe\", since === undefined ? {} : { since }) as Promise<{ lastSeq: number }>;\n }\n\n /**\n * Stops reading: what the daemon sends waits in the connection (and past its bound the daemon ends it), and no\n * event reaches the listener until `resume`.\n */\n pause(): void {\n if (this.held) return;\n this.held = [];\n this.socket.pause();\n }\n\n /** Gives the listener the events held, then reads again; a listener that pauses again keeps the rest held. */\n resume(): void {\n const held = this.held;\n if (!held) return;\n this.held = null;\n for (let i = 0; i < held.length; i++) {\n this.eventListener?.(held[i]);\n if (this.held) { (this.held as GhostlyEvent[]).unshift(...held.slice(i + 1)); return; }\n }\n this.socket.resume();\n }\n\n close(): void {\n this.socket.end();\n }\n\n /** Closes at once: what the daemon still sends is not read. */\n destroy(): void {\n this.socket.destroy();\n }\n}\n\n/**\n * `timeoutMs` bounds the connect only. The client it gives has sent its hello; whether the listener is the daemon is\n * known at the first call (above).\n */\nexport function connectDaemon(address: DaemonAddress, timeoutMs = 2_000): Promise<DaemonClient | null> {\n const path = address.socket;\n // Someone else's socket (or a link) where the daemon's should be is no daemon of this profile's.\n if (!ownSocket(path)) return Promise.resolve(null);\n return new Promise((resolve) => {\n const socket = connect(path);\n const timer = setTimeout(() => { socket.destroy(); resolve(null); }, timeoutMs);\n socket.once(\"connect\", () => { clearTimeout(timer); resolve(new DaemonClient(socket, address)); });\n socket.once(\"error\", () => { clearTimeout(timer); resolve(null); });\n });\n}\n","import { readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\n// From its own module, not the package: the command table is read by every command, and the package is all of the\n// protocol (~100 ms to load), which a command a daemon answers never needs.\nimport { ITEM_STATES, PR_CHECKS, PR_STATES, RUN_RESULTS, STATUS_CARD_LIMITS, cardUrl } from \"@ghostly/core/statusCards\";\nimport type { OptionSpec, Parsed } from \"../args\";\nimport { CliError, localFileError } from \"../errors\";\n\n/**\n * The commands that are one API method each: how the command line becomes the method's parameters. Commands with\n * their own flow (profiles, the daemon, listen, send's stdin, the engine passthrough) live in main.ts.\n */\nexport interface Command {\n method: string;\n usage: string;\n summary: string;\n options?: Record<string, OptionSpec>;\n /** Positionals, in order; a trailing `...` one takes the rest joined by spaces. */\n args?: string[];\n params?: (parsed: Parsed, args: Record<string, string | undefined>) => Record<string, unknown>;\n /**\n * A command that runs here, on files, with no profile or daemon (the publisher tools of WISP 1200): its answer is\n * printed as a method's is, and `method` only names it.\n */\n run?: (parsed: Parsed, args: Record<string, string | undefined>) => Promise<Record<string, unknown>>;\n}\n\nexport const wait: Record<string, OptionSpec> = {\n wait: { type: \"string\", description: \"none, sent or delivered (default: none with a daemon, sent without)\" },\n timeout: { type: \"number\", description: \"Seconds to wait (default 30)\" },\n};\n/** A group has no receipts: `sent` waits until an edge took the frame (a member's, or one of my hubs'). */\nexport const groupWait: Record<string, OptionSpec> = {\n wait: { type: \"string\", description: \"none or sent: until an edge took it (default none)\" },\n timeout: { type: \"number\", description: \"Seconds to wait (default 30)\" },\n};\nexport const net: OptionSpec = { type: \"string\", description: \"mainnet or testnet (default testnet)\" };\nexport const card: OptionSpec = { type: \"string\", description: \"A Lightning card (its id; default: the network's default)\" };\nexport const memo: OptionSpec = { type: \"string\", description: \"What it is for (up to 140 characters)\" };\nexport const confirmReal: OptionSpec = { type: \"boolean\", description: \"Confirm a Mainnet (real money) spend\" };\n\n/**\n * A path as this command's working directory means it: the daemon runs elsewhere. \"\" (an unset variable in a script)\n * names no file, never the current folder.\n */\nexport function here(path: unknown): string | undefined {\n if (path === \"\") throw new CliError(\"usage\", \"A path given as \\\"\\\" names no file\");\n return typeof path === \"string\" ? resolve(path) : undefined;\n}\n\n/**\n * A list option that names chats (`--to`, `--from`): \"\" or \"group:\" alone (an unset variable in a script) names\n * nothing, and is a usage error before the profile opens; it was a prefix of every id and took the only chat or group.\n */\nexport function refs(values: unknown, flag: string, what: string): void {\n if (!Array.isArray(values)) return;\n for (const value of values) {\n if (typeof value === \"string\" && !value.replace(/^group:/, \"\").trim()) throw new CliError(\"usage\", `--${flag} ${JSON.stringify(value)} names no ${what}`);\n }\n}\n\n/** A whole number of sats from the command line. */\nexport function sats(value: string | undefined): number {\n const n = Number(value);\n if (!value || !Number.isSafeInteger(n) || n <= 0) throw new CliError(\"usage\", `Not an amount in sats: ${JSON.stringify(value)}`);\n return n;\n}\n\n/** `name=value` options as an object. */\nexport function pairs(values: unknown): Record<string, string> | undefined {\n if (!Array.isArray(values) || !values.length) return undefined;\n const out: Record<string, string> = {};\n for (const item of values as string[]) {\n const eq = item.indexOf(\"=\");\n if (eq < 1) throw new CliError(\"usage\", `--value takes name=value, not ${JSON.stringify(item)}`);\n out[item.slice(0, eq)] = item.slice(eq + 1);\n }\n return out;\n}\n\nexport const rate: OptionSpec = { type: \"number\", description: \"The audio's sample rate: 48000 (default), 24000, 16000, 12000 or 8000\" };\nexport const force: OptionSpec = { type: \"boolean\", description: \"Send even if the text looks like a seed, a key or ecash\" };\nexport const reply: OptionSpec = { type: \"string\", description: \"Reply to this message (its id, from history or an event)\" };\n/** Buttons under a message (WISP 406 · Message Buttons): the text is the question. */\nexport const buttonOptions: Record<string, OptionSpec> = {\n button: { type: \"list\", description: \"A button under the message, id:Label (again for each, 1 to 6; the label may hold colons). A press comes back as button.pressed\" },\n style: { type: \"list\", description: \"A button's look, id=primary, neutral or danger\" },\n once: { type: \"boolean\", description: \"Each person answers once: after a press their app offers the buttons no more\" },\n id: { type: \"string\", description: \"The question's id (default: made up, ask-…)\" },\n};\n/** The group's entry link lets anyone join: printed only when asked for. */\nexport const showSecret: Record<string, OptionSpec> = { \"show-secret\": { type: \"boolean\", description: \"Print the group's entry link (anyone who has it can join)\" } };\n/** A pending chat's invite code lets whoever reads it take the chat: printed only when asked for. */\nexport const showInvite: Record<string, OptionSpec> = { \"show-secret\": { type: \"boolean\", description: \"Print a pending chat's invite code (whoever has it can take the chat)\" } };\nexport const secret = (options: Parsed[\"options\"]) => (options[\"show-secret\"] === true ? { showSecret: true } : {});\n\n/**\n * `--for` of the typing commands: the seconds it is kept on, 1 to 600, and never with `--stop`. A usage error (exit 2)\n * that names the flag: before, the API's own check answered (\"for must be a number from 1 to 600\", exit 1).\n */\nexport function typingFor(options: Parsed[\"options\"]): number | undefined {\n const seconds = options.for;\n if (seconds === undefined) return undefined;\n if (typeof seconds !== \"number\" || !(seconds >= 1 && seconds <= 600)) throw new CliError(\"usage\", `--for takes a number of seconds from 1 to 600, not ${JSON.stringify(seconds)}`);\n if (options.stop === true) throw new CliError(\"usage\", \"--for keeps it on: not with --stop\");\n return seconds;\n}\n\n/**\n * A time given as digits: milliseconds. Unix seconds (from 1e9, 2001, up to 1e11, which as milliseconds would be 1970\n * to 1973) are refused with the milliseconds they mean: before, they were read as January 1970 without a word.\n */\nfunction milliseconds(text: string, flag: string): number {\n const ms = Number(text);\n if (ms >= 1e9 && ms < 1e11) throw new CliError(\"usage\", `--${flag} takes milliseconds, not seconds: ${text}000`);\n return ms;\n}\n\n/**\n * A history cursor: a time when it is all digits (`0` is from the start), else a message id. Message ids are never all\n * digits (`me_…`, `peer_…`): before, fewer than 10 digits were read as an id (\"No message 0\").\n */\nexport function cursor(value: unknown, flag: string): string | number | undefined {\n if (value === undefined) return undefined;\n const text = String(value).trim();\n return /^\\d+$/.test(text) ? milliseconds(text, flag) : text;\n}\n\n/**\n * A status card's fields given as JSON (WISP 405 · Status Cards): inline (`{...}`), `-` for stdin, or a file's path. The\n * flags given beside it win over it.\n */\nexport function cardJson(value: unknown): Record<string, unknown> {\n if (value === undefined) return {};\n const text = String(value).trim();\n // A file's path as here() reads it (\"\" names no file, not the current folder); a file not there or a folder is said\n // with its path, as `x401 credential add` says it: before, Node's text, and a folder's named no path.\n const file = text.startsWith(\"{\") || text === \"-\" ? undefined : here(text)!;\n let raw: string;\n try { raw = text.startsWith(\"{\") ? text : readFileSync(file ?? 0, \"utf8\"); }\n catch (error) { throw (file !== undefined && localFileError(error, file)) || new CliError(\"usage\", `--json takes a card as JSON, - for stdin, or a file: ${error instanceof Error ? error.message : String(error)}`); }\n let parsed: unknown;\n try { parsed = JSON.parse(raw); } catch { throw new CliError(\"usage\", \"--json is not valid JSON\"); }\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) throw new CliError(\"usage\", \"--json is a JSON object of the card's fields\");\n return parsed as Record<string, unknown>;\n}\n\n/** Options every status card command takes. */\nexport const cardOptions: Record<string, OptionSpec> = {\n json: { type: \"string\", description: \"The card's fields as JSON: inline, - for stdin, or a file (flags win over it)\" },\n link: { type: \"list\", description: \"A link on the card: https://… or label=https://… (up to 4)\" },\n text: { type: \"string\", description: \"The text older apps show instead (default: written from the card)\" },\n force: { type: \"boolean\", description: \"Send even if the card's text looks like a seed, a key or ecash\" },\n};\n\n/** `--link label=https://…` or a bare link, as a card's links. */\nexport function cardLinks(values: unknown): { url: string; label?: string }[] | undefined {\n if (!Array.isArray(values) || !values.length) return undefined;\n return (values as string[]).map((value) => {\n const eq = value.indexOf(\"=\");\n return eq > 0 && !value.slice(0, eq).includes(\":\") ? { label: value.slice(0, eq), url: value.slice(eq + 1) } : { url: value };\n });\n}\n\nconst listed = (words: readonly string[]) => `${words.slice(0, -1).join(\", \")} or ${words.at(-1)}`;\n\n/**\n * `--item state:text` as a task's item. The word before the first colon is the state when it is one lowercase word (and\n * the colon does not start `://`): one of `ITEM_STATES`, or a usage error that lists them, so `queued:Publishing` is\n * refused rather than shown as that text. Anything else (`Step 2: build`, `Note: x`, a link, no colon) is the whole\n * text, pending; `pending:fix: tests` keeps a colon after a lowercase word.\n */\nexport function itemOf(value: string): { state: string; text: string } {\n const colon = value.indexOf(\":\");\n const word = colon > 0 ? value.slice(0, colon) : \"\";\n if (!/^[a-z]+$/.test(word) || value.startsWith(\"//\", colon + 1)) return { state: \"pending\", text: value };\n if (!(ITEM_STATES as readonly string[]).includes(word))\n throw new CliError(\"usage\", `--item takes state:text, and ${JSON.stringify(word)} is not a state: use ${listed(ITEM_STATES)} (pending:<text> keeps a colon in the text), not ${JSON.stringify(value)}`);\n return { state: word, text: value.slice(colon + 1).trim() };\n}\n\n/** `--progress`, `--left`: a percent, or a usage error that names the flag. */\nfunction percent(options: Parsed[\"options\"], flag: string): void {\n const value = options[flag];\n if (value !== undefined && !(typeof value === \"number\" && value >= 0 && value <= 100)) throw new CliError(\"usage\", `--${flag} takes a percent from 0 to 100, not ${JSON.stringify(value)}`);\n}\n\n/** The flags of a task's pull request, and the field of `pr` each one gives. */\nconst PR_FLAGS = [[\"pr-url\", \"url\"], [\"pr-number\", \"number\"], [\"additions\", \"additions\"], [\"deletions\", \"deletions\"], [\"files\", \"files\"], [\"pr-state\", \"state\"], [\"pr-checks\", \"checks\"]] as const;\n\n/**\n * A task's fields from its flags; what was not given is left out, so an update changes only what it names. What a flag\n * got wrong is a usage error (exit 2) that names the flag: before, it reached the card's own check and failed as\n * `bad_request` (exit 1) in the card's words (\"Status card: done is at most total\").\n */\nexport function taskFields(options: Parsed[\"options\"]): Record<string, unknown> {\n const fields: Record<string, unknown> = { ...cardJson(options.json) };\n const set = (key: string, value: unknown) => { if (value !== undefined) fields[key] = value; };\n set(\"id\", options.id);\n set(\"title\", options.title);\n set(\"status\", options.status);\n percent(options, \"progress\");\n if (options.progress !== undefined && options.steps !== undefined) throw new CliError(\"usage\", \"--progress or --steps, not both\");\n set(\"progress\", options.progress);\n set(\"step\", options.step);\n set(\"branch\", options.branch);\n if (options.steps !== undefined) {\n const match = /^(\\d+)\\s*\\/\\s*(\\d+)$/.exec(String(options.steps));\n if (!match) throw new CliError(\"usage\", `--steps takes done/total, like 2/5, not ${JSON.stringify(options.steps)}`);\n fields.done = Number(match[1]); fields.total = Number(match[2]);\n if (Number(match[2]) < 1 || Number(match[1]) > Number(match[2])) throw new CliError(\"usage\", `--steps takes done/total with done at most total, like 2/5, not ${JSON.stringify(options.steps)}`);\n }\n if (options[\"pr-url\"] !== undefined && !cardUrl(options[\"pr-url\"])) throw new CliError(\"usage\", `--pr-url takes an https link of at most ${STATUS_CARD_LIMITS.url} characters, not ${JSON.stringify(options[\"pr-url\"])}`);\n for (const [flag, words] of [[\"pr-state\", PR_STATES], [\"pr-checks\", PR_CHECKS]] as const)\n if (options[flag] !== undefined && !(words as readonly unknown[]).includes(options[flag])) throw new CliError(\"usage\", `--${flag} takes ${listed(words)}, not ${JSON.stringify(options[flag])}`);\n const pr: Record<string, unknown> = {};\n for (const [flag, key] of PR_FLAGS) if (options[flag] !== undefined) pr[key] = options[flag];\n if (Object.keys(pr).length) fields.pr = { ...(fields.pr && typeof fields.pr === \"object\" ? fields.pr as object : {}), ...pr };\n if (Array.isArray(options.item) && options.item.length) fields.items = (options.item as string[]).map(itemOf);\n if (Array.isArray(options.tag) && options.tag.length > STATUS_CARD_LIMITS.tags) throw new CliError(\"usage\", `--tag is given at most ${STATUS_CARD_LIMITS.tags} times, not ${options.tag.length}`);\n if (Array.isArray(options.tag) && options.tag.length) fields.tags = options.tag as string[];\n set(\"parent\", options.parent);\n const links = cardLinks(options.link);\n if (links) fields.links = links;\n return fields;\n}\n\n/**\n * The fields a new card cannot go without, given as a flag or in `--json`: a usage error (exit 2) that names the\n * flags. Before, a missing `--title` reached the card's own check and failed as `bad_request` (exit 1) with\n * \"Status card: title is text\".\n */\nexport function needs(card: Record<string, unknown>, fields: readonly (readonly [key: string, flag: string])[], usage: string): Record<string, unknown> {\n const missing = fields.filter(([key]) => typeof card[key] !== \"string\" || !(card[key] as string).trim()).map(([, flag]) => `--${flag}`);\n if (missing.length) throw new CliError(\"usage\", `${missing.join(\" and \")} ${missing.length > 1 ? \"are\" : \"is\"} needed: ghostly ${usage}`);\n return card;\n}\n\n/**\n * A new task's pull request goes by its link: `--pr-state` and the like without `--pr-url` (or `pr.url` in `--json`)\n * are a usage error that names them. An update's card may have the link already, so only a send asks.\n */\nexport function prLinked(card: Record<string, unknown>, options: Parsed[\"options\"], usage: string): Record<string, unknown> {\n const given = PR_FLAGS.filter(([flag]) => options[flag] !== undefined).map(([flag]) => `--${flag}`);\n if (!given.length || (card.pr as { url?: unknown }).url !== undefined) return card;\n throw new CliError(\"usage\", `${given.join(\" and \")} ${given.length > 1 ? \"go\" : \"goes\"} with --pr-url: ghostly ${usage}`);\n}\n\n/**\n * A usage card says how much is left: `--left`, or `--used` with `--limit`, as flags or in `--json`. The one that is\n * missing is a usage error that names the flag.\n */\nexport function quota(card: Record<string, unknown>, usage: string): Record<string, unknown> {\n const used = card.used !== undefined, limit = card.limit !== undefined;\n if (used !== limit) throw new CliError(\"usage\", `--${used ? \"used\" : \"limit\"} goes with --${used ? \"limit\" : \"used\"}: ghostly ${usage}`);\n if (card.left === undefined && !used) throw new CliError(\"usage\", `--left is needed (or --used with --limit): ghostly ${usage}`);\n return card;\n}\n\n/** A time a command names: milliseconds, or a date the JavaScript Date reads (`2026-09-30T01:00:00Z`). */\nexport function cardTime(value: unknown, flag: string): number | undefined {\n if (value === undefined) return undefined;\n const text = String(value).trim();\n const ms = /^\\d+$/.test(text) ? milliseconds(text, flag) : Date.parse(text);\n if (!Number.isSafeInteger(ms) || ms <= 0) throw new CliError(\"usage\", `--${flag} takes a time in milliseconds or a date like 2026-09-30T01:00:00Z, not ${JSON.stringify(value)}`);\n return ms;\n}\n\n/** `--run ok`, `--run failed:\"CI flaked\"`: a run of a routine, recorded as its last. */\nexport function runOf(value: unknown): { result: string; summary?: string } | undefined {\n if (value === undefined) return undefined;\n const text = String(value), colon = text.indexOf(\":\");\n const result = colon === -1 ? text : text.slice(0, colon), summary = colon === -1 ? \"\" : text.slice(colon + 1).trim();\n if (!(RUN_RESULTS as readonly string[]).includes(result)) throw new CliError(\"usage\", `--run takes ok, failed or skipped, and :a summary after it if you like, not ${JSON.stringify(value)}`);\n return { result, ...(summary && { summary }) };\n}\n\n/** A routine's fields from its flags; what was not given is left out. */\nexport function routineFields(options: Parsed[\"options\"]): Record<string, unknown> {\n const fields: Record<string, unknown> = { ...cardJson(options.json) };\n for (const key of [\"id\", \"name\", \"schedule\", \"cron\", \"state\"] as const) if (options[key] !== undefined) fields[key] = options[key];\n const next = cardTime(options.next, \"next\");\n if (next !== undefined) fields.nextRunAt = next;\n const links = cardLinks(options.link);\n if (links) fields.links = links;\n return fields;\n}\n\n/** Options a routine command takes, beside `cardOptions`. */\nexport const routineOptions: Record<string, OptionSpec> = {\n name: { type: \"string\", description: \"What the routine is (120 characters)\" },\n schedule: { type: \"string\", description: \"When it runs, as people say it: \\\"every day 01:00\\\" (80 characters)\" },\n cron: { type: \"string\", description: \"Its cron line, shown beside the schedule (never run)\" },\n state: { type: \"string\", description: \"active (default on send) or paused\" },\n next: { type: \"string\", description: \"Its next run: milliseconds or a date like 2026-09-30T01:00:00Z\" },\n run: { type: \"string\", description: \"Record a run now: ok, failed or skipped, with :a summary if you like (it becomes the last run)\" },\n ...cardOptions,\n};\n\n/** Options a task command takes, beside `cardOptions`. */\nexport const taskOptions: Record<string, OptionSpec> = {\n title: { type: \"string\", description: \"What the task is (120 characters)\" },\n status: { type: \"string\", description: \"queued, running (default on send), blocked, done, failed or cancelled\" },\n progress: { type: \"number\", description: \"Percent done, 0 to 100\" },\n steps: { type: \"string\", description: \"Steps done of total, like 2/5 (progress is worked out from them)\" },\n step: { type: \"string\", description: \"What it is doing now (200 characters)\" },\n item: { type: \"list\", description: \"A step or log line, state:text with state pending, running, done, failed or skipped (text alone: pending). A lowercase word before the first colon must be one of them; pending:fix: x keeps the colon. The list replaces the card's (up to 20)\" },\n branch: { type: \"string\", description: \"The branch it works on\" },\n \"pr-url\": { type: \"string\", description: \"The pull request's https link\" },\n \"pr-number\": { type: \"number\", description: \"The pull request's number\" },\n additions: { type: \"number\", description: \"Lines the pull request adds\" },\n deletions: { type: \"number\", description: \"Lines the pull request removes\" },\n files: { type: \"number\", description: \"Files the pull request changes\" },\n \"pr-state\": { type: \"string\", description: \"Where the pull request stands: draft, open (ready for review), merged or closed\" },\n \"pr-checks\": { type: \"string\", description: \"The pull request's checks: passing, failing or pending\" },\n tag: { type: \"list\", description: \"A short label, like an area or a repository (24 characters); up to 3. An update's tags replace the card's: give all of them\" },\n parent: { type: \"string\", description: \"The id of the task of yours in this chat that this one is a part of\" },\n ...cardOptions,\n};\n\n/**\n * `--also week=80` or `--also week=80@2026-10-10T00:00:00Z`: another window of a usage card, its percent left and, after\n * `@`, when it resets.\n */\nexport function usageWindowOf(value: string): { window: string; left: number; resetsAt?: number } {\n const match = /^([^=]+)=(\\d+(?:\\.\\d+)?)(?:@(.+))?$/.exec(value.trim());\n if (!match) throw new CliError(\"usage\", `--also takes window=percent or window=percent@time, like week=80@2026-10-10T00:00:00Z, not ${JSON.stringify(value)}`);\n const resetsAt = cardTime(match[3], \"also\");\n return { window: match[1].trim(), left: Number(match[2]), ...(resetsAt !== undefined && { resetsAt }) };\n}\n\n/** A usage card's fields from its flags (WISP 405 § Usage); `--json` gives any of them, the flags win over it. */\nexport function usageFields(options: Parsed[\"options\"]): Record<string, unknown> {\n const fields: Record<string, unknown> = { ...cardJson(options.json) };\n percent(options, \"left\");\n if (options.left !== undefined && (options.used !== undefined || options.limit !== undefined)) throw new CliError(\"usage\", \"--left or --used with --limit, not both\");\n for (const key of [\"id\", \"left\", \"used\", \"limit\", \"label\", \"account\", \"window\"] as const) if (options[key] !== undefined) fields[key] = options[key];\n const resets = cardTime(options.resets, \"resets\");\n if (resets !== undefined) fields.resetsAt = resets;\n if (Array.isArray(options.also) && options.also.length) fields.windows = (options.also as string[]).map(usageWindowOf);\n return fields;\n}\n\n/** Options `usage send` takes. */\nexport const usageOptions: Record<string, OptionSpec> = {\n left: { type: \"number\", description: \"Percent of the quota left, 0 to 100\" },\n used: { type: \"number\", description: \"How much is used, with --limit (instead of --left; the percent is worked out)\" },\n limit: { type: \"number\", description: \"The quota, with --used\" },\n label: { type: \"string\", description: \"What the quota is of, like Claude (24 characters)\" },\n account: { type: \"string\", description: \"Which of your accounts it is, short (24 characters)\" },\n window: { type: \"string\", description: \"The quota's window, as people say it: \\\"5 h\\\", \\\"week\\\" (16 characters)\" },\n resets: { type: \"string\", description: \"When the window starts again: milliseconds or a date like 2026-10-07T18:00:00Z\" },\n also: { type: \"list\", description: \"Another window, window=percent[@time], like week=80@2026-10-10T00:00:00Z (up to 3; shown in the details)\" },\n id: { type: \"string\", description: \"The card's id (default usage: one card per chat)\" },\n all: { type: \"boolean\", description: \"Every 1:1 chat with a contact, instead of one chat\" },\n json: cardOptions.json,\n text: cardOptions.text,\n force: cardOptions.force,\n};\n","import { readFileSync } from \"node:fs\";\nimport { CliError } from \"../errors\";\nimport { here, type Command } from \"./shared\";\n\n/** The key file a command signs with: always named, never a default, never on the command line itself. */\nfunction keyFile(value: unknown, usage: string): string {\n if (typeof value !== \"string\" || !value) throw new CliError(\"usage\", `--key <file> is needed: ghostly ${usage}`);\n return value;\n}\n\n/** `app send`'s message: JSON on the command line, or `-` for stdin. */\nfunction appData(value: string | undefined): unknown {\n if (value === undefined) throw new CliError(\"usage\", \"The message is needed, as JSON or - for stdin: ghostly app send <chat> <ref|name> <json|->\");\n const text = value.trim() === \"-\" ? readFileSync(0, \"utf8\") : value;\n try { return JSON.parse(text) as unknown; } catch { throw new CliError(\"usage\", \"The message is not valid JSON: quote it for the shell, like '{\\\"k\\\":\\\"move\\\"}', or pass - and write it on stdin\"); }\n}\n\nconst key = { type: \"string\", description: \"The key file (made, owner-only, when it is missing)\" } as const;\n\n/**\n * The publisher tools of WISP 1200 (Apps · Publishing): they run here, on files, with no profile or daemon. And the\n * apps a profile serves as a bot (`app serve`, `app served`, `app unserve`), which are the profile's. One entry per\n * command, in alphabetical order (test/commands.test.ts checks).\n */\nexport const commands: Record<string, Command> = {\n \"app close\": {\n method: \"app.close\", usage: \"app close <chat> <ref|name>\",\n summary: \"Close a served app in a chat: the contact's app hears it ended\",\n args: [\"chat\", \"ref\"],\n params: (_, a) => ({ chat: a.chat, ref: a.ref }),\n },\n \"app init\": {\n method: \"app.init\", usage: \"app init <dir> [--name <name>] [--title <title>] [--force]\",\n summary: \"Start an app (WISP 1200): a small working one in <dir>, its ghostly-app.json, an index.html that says hello to the contact and a README, ready for app publish\",\n args: [\"dir\"],\n options: {\n name: { type: \"string\", description: \"The app's name, lowercase letters, digits and hyphens (default: the folder's)\" },\n title: { type: \"string\", description: \"The title people see, up to 40 characters (default: from the name)\" },\n force: { type: \"boolean\", description: \"Replace the three files when they are there\" },\n },\n run: async ({ options }, a) => (await import(\"../apps\")).initApp(a.dir!, { name: options.name as string | undefined, title: options.title as string | undefined, force: options.force === true }),\n },\n \"app open\": {\n method: \"app.open\", usage: \"app open <chat> <ref|name> [--no-card]\",\n summary: \"Open a served app in a chat, as a bot (needs the daemon): the contact gets the app's card, unless their app is open there already, and the two sides can talk once both opened it\",\n args: [\"chat\", \"ref\"],\n options: { \"no-card\": { type: \"boolean\", description: \"Send no app card, only say the app is open\" } },\n params: ({ options }, a) => ({ chat: a.chat, ref: a.ref, noCard: options[\"no-card\"] === true }),\n },\n \"app publish\": {\n method: \"app.publish\", usage: \"app publish <dir> --key <file> [--out <file>]\",\n summary: \"Bundle and sign an app (WISP 1200): <dir>/ghostly-app.json and every other file in <dir> become one .ghostlyapp, its sequence one more than the bundle at --out (default <dir>/app.ghostlyapp)\",\n args: [\"dir\"],\n options: {\n key: { ...key, description: \"The publisher key file (made, owner-only, on first use; back it up)\" },\n out: { type: \"string\", description: \"Where the bundle goes (default <dir>/app.ghostlyapp); the bundle there is the version this one follows\" },\n sequence: { type: \"number\", description: \"This version's sequence, higher than the bundle at --out's (default: one more than it)\" },\n },\n run: async ({ options }, a) => (await import(\"../apps\")).publishApp(a.dir!, keyFile(options.key, \"app publish <dir> --key <file> [--out <file>] [--sequence n]\"), here(options.out), options.sequence as number | undefined),\n },\n \"app revoke\": {\n method: \"app.revoke\", usage: \"app revoke <dir> --key <file> (--digest <digest>... | --up-to <sequence>) [--reason <text>] [--bundle <file>] [--force]\",\n summary: \"Revoke versions of your app (WISP 1200 · Revocation): a ghostly-revoke/1 statement signed with its publisher key, added to <dir>/ghostly-revoke.json\",\n args: [\"dir\"],\n options: {\n key: { type: \"string\", description: \"The app's publisher key file (never made here)\" },\n digest: { type: \"list\", description: \"A version's digest, base64url as app verify prints it (again for each, up to 64)\" },\n \"up-to\": { type: \"number\", description: \"Every version with this sequence or a lower one\" },\n reason: { type: \"string\", description: \"Why, one line of up to 200 characters, shown to people\" },\n bundle: { type: \"string\", description: \"The bundle naming the app (default <dir>/app.ghostlyapp)\" },\n force: { type: \"boolean\", description: \"Allow --up-to past the bundle's own sequence (versions published from elsewhere)\" },\n },\n run: async ({ options }, a) => (await import(\"../apps\")).revokeApp(a.dir!, keyFile(options.key, \"app revoke <dir> --key <file> (--digest <digest>... | --up-to <sequence>) [--reason <text>]\"), {\n digests: options.digest as string[] | undefined, upTo: options[\"up-to\"] as number | undefined,\n reason: options.reason as string | undefined, bundle: here(options.bundle), force: options.force === true,\n }),\n },\n \"app send\": {\n method: \"app.send\", usage: \"app send <chat> <ref|name> <json|->\",\n summary: \"Send one message of a served app's own protocol to the contact's app (needs the daemon, and both sides open): any JSON value up to 32 KiB, or - to read it from stdin; live only, never kept for later\",\n args: [\"chat\", \"ref\", \"data...\"],\n params: (_, a) => ({ chat: a.chat, ref: a.ref, data: appData(a.data) }),\n },\n \"app serve\": {\n method: \"app.serve\", usage: \"app serve <bundle|url> --grant chat [--grant name] [--url <url>]\",\n summary: \"Serve an app as a bot (WISP 1200): its signed .ghostlyapp is checked as a client would, and the profile speaks the app's messages in chats itself; each permission the app asks needs its --grant\",\n args: [\"bundle\"],\n options: {\n grant: { type: \"list\", description: \"A permission the app asks and you allow: chat (talk to the contact's app) or name (your name in that chat); again for each\" },\n url: { type: \"string\", description: \"Where a contact's app reads the bundle, for the card (default: the URL it was served from, else the manifest's first source)\" },\n },\n params: ({ options }, a) => ({ bundle: /^[a-z][a-z0-9+.-]*:\\/\\//i.test(a.bundle ?? \"\") ? a.bundle : here(a.bundle), grant: options.grant, url: options.url }),\n },\n \"app served\": {\n method: \"app.served\", usage: \"app served\",\n summary: \"The apps this profile serves as a bot, and whether apps/1 is offered to contacts now\",\n },\n \"app unserve\": {\n method: \"app.unserve\", usage: \"app unserve <ref|name>\",\n summary: \"Stop serving an app, by its reference or its name\",\n args: [\"ref\"],\n params: (_, a) => ({ ref: a.ref }),\n },\n \"app verify\": {\n method: \"app.verify\", usage: \"app verify <bundle|url>\",\n summary: \"Check a .ghostlyapp as a client would, from a file or an https URL: its manifest and digest, or refused (exit 1) with the reason, revoked when the ghostly-revoke.json beside it revokes this version\",\n args: [\"bundle\"],\n run: async (_, a) => (await import(\"../apps\")).verifyApp(a.bundle!),\n },\n \"store sign\": {\n method: \"store.sign\", usage: \"store sign <index> --key <file> [--out <dir>]\",\n summary: \"Sign a store index (WISP 1200 · Stores): writes ghostly-store.json, canonical, and ghostly-store.sig beside it or in --out\",\n args: [\"index\"],\n options: {\n key: { ...key, description: \"The store key file (made, owner-only, when it is missing, the index names no key and no signed index is in the output folder; keep it offline)\" },\n out: { type: \"string\", description: \"The folder to write ghostly-store.json and ghostly-store.sig in (default: the index's)\" },\n },\n run: async ({ options }, a) => (await import(\"../apps\")).signStore(a.index!, keyFile(options.key, \"store sign <index> --key <file> [--out <dir>]\"), here(options.out)),\n },\n};\n","import { CliError } from \"../errors\";\nimport { type Command, rate, refs } from \"./shared\";\n\n/** Voice calls: one entry per command, in alphabetical order (test/commands.test.ts checks). */\nexport const commands: Record<string, Command> = {\n \"call answer\": {\n method: \"call.answer\", usage: \"call answer [<chat|call>] [--rate 48000]\", summary: \"Answer a call that rings (the only one, or the one named)\",\n args: [\"call...?\"], options: { rate: rate }, params: ({ options }, a) => ({ call: a.call, rate: options.rate }),\n },\n \"call auto\": {\n method: \"call.auto\", usage: \"call auto [on|off] [--from <chat>]... [--rate 48000]\", summary: \"Answer calls by themselves: from anyone, or the chats named (kept in the profile)\",\n args: [\"mode...?\"], options: { from: { type: \"list\", description: \"Only calls from this chat (again for more)\" }, rate: rate },\n params: ({ options }, a) => {\n if (a.mode !== undefined && a.mode !== \"on\" && a.mode !== \"off\") throw new CliError(\"usage\", \"ghostly call auto [on|off] [--from <chat>]... [--rate n]\");\n // Without `on` the chats and the rate would be dropped without a word.\n if (a.mode !== \"on\" && (options.from !== undefined || options.rate !== undefined)) throw new CliError(\"usage\", \"--from and --rate go with on: ghostly call auto on --from <chat>\");\n refs(options.from, \"from\", \"chat\");\n if (a.mode === undefined) return {};\n return a.mode === \"on\" ? { on: true, from: options.from, rate: options.rate } : { on: false };\n },\n },\n \"call flush\": { method: \"call.flush\", usage: \"call flush [<chat|call>]\", summary: \"Drop the audio queued and not played yet (barge-in)\", args: [\"call...?\"], params: (_, a) => ({ call: a.call }) },\n \"call hangup\": { method: \"call.hangup\", usage: \"call hangup [<chat|call>]\", summary: \"Hang up, or decline a call that rings\", args: [\"call...?\"], params: (_, a) => ({ call: a.call }) },\n \"call list\": { method: \"call.list\", usage: \"call list\", summary: \"Calls on now, their audio sockets, and auto-answer\" },\n \"call start\": {\n method: \"call.start\", usage: \"call start <chat> [--rate 48000]\", summary: \"Call a contact (voice); the result names the call's audio socket (daemon)\",\n args: [\"chat\"], options: { rate: rate }, params: ({ options }, a) => ({ chat: a.chat, rate: options.rate }),\n },\n};\n","import { CliError } from \"../errors\";\nimport { type Command, force, groupWait, cursor, needs, prLinked, quota, refs, routineFields, routineOptions, runOf, secret, showInvite, taskFields, taskOptions, typingFor, usageFields, usageOptions, wait } from \"./shared\";\n\nconst BUTTON_UPDATE = \"button update <chat|group> <message> [--chosen <button>] [--close] [--text <text>] [--force] [--wait none|confirmed|sent] [--timeout s]\";\n\n/** Invites, chats and messages: one entry per command, in alphabetical order (test/commands.test.ts checks). */\nexport const commands: Record<string, Command> = {\n \"button press\": {\n method: \"button.press\", usage: \"button press <chat|group> <message> <button> [--wait none|sent|delivered] [--timeout s]\",\n summary: \"Press a button of someone else's message, as a tap in the app does (its id from the message's card)\",\n args: [\"chat\", \"message\", \"button\"],\n options: {\n wait: { type: \"string\", description: \"none, sent (a one-shot's default in a chat) or delivered; a group takes none or sent\" },\n timeout: groupWait.timeout,\n },\n params: ({ options }, a) => ({ chat: a.chat, message: a.message, button: a.button, wait: options.wait, timeout: options.timeout }),\n },\n \"button update\": {\n method: \"button.update\", usage: BUTTON_UPDATE,\n summary: \"Show the answer on a message's buttons (--chosen), close them, or change its text (the messageId send --button gave)\",\n args: [\"chat\", \"message\"],\n options: {\n chosen: { type: \"string\", description: \"The button to show as the answer (its id)\" },\n close: { type: \"boolean\", description: \"Close the buttons: no more presses\" },\n text: { type: \"string\", description: \"A new text for the message (default: the one it has); people see it marked edited\" },\n force,\n wait: { type: \"string\", description: \"none (default), confirmed (a chat's contact took it) or sent (a group's edge took it)\" },\n timeout: groupWait.timeout,\n },\n params: ({ options }, a) => {\n if (!options.chosen && options.close !== true && !options.text) throw new CliError(\"usage\", `Give --chosen, --close or --text: ghostly ${BUTTON_UPDATE}`);\n return { chat: a.chat, message: a.message, chosen: options.chosen, close: options.close === true, text: options.text, force: options.force === true, wait: options.wait, timeout: options.timeout };\n },\n },\n \"chat connect\": { method: \"chat.connect\", usage: \"chat connect <chat>\", summary: \"Reconnect a chat now (ends a --hold)\", args: [\"chat\"], params: (_, { chat }) => ({ chat }) },\n \"chat disconnect\": {\n method: \"chat.disconnect\", usage: \"chat disconnect <chat> [--hold <minutes>]\", summary: \"Close a chat's live session (the contact may redial; --hold keeps it on the DHT that long, 0 ends it)\", args: [\"chat\"],\n options: { hold: { type: \"number\", description: \"Stay off the direct link this many minutes (up to 10080): DHT only, taken back after\" } },\n params: ({ options }, { chat }) => ({ chat, hold: options.hold }),\n },\n \"chat history\": {\n method: \"chat.history\", usage: \"chat history <chat> [--limit n] [--before id|ms] [--after id|ms]\", summary: \"Messages, oldest first (a page)\",\n args: [\"chat\"],\n options: { limit: { type: \"number\", description: \"Messages per page (default 50)\" }, before: { type: \"string\", description: \"Only before this message id or timestamp\" }, after: { type: \"string\", description: \"Only after this message id or timestamp\" } },\n params: ({ options }, { chat }) => ({ chat, limit: options.limit, before: cursor(options.before, \"before\"), after: cursor(options.after, \"after\") }),\n },\n \"chat list\": { method: \"chat.list\", usage: \"chat list [--show-secret]\", summary: \"Chats, newest first (a pending invite code only with --show-secret)\", options: showInvite, params: ({ options }) => secret(options) },\n \"chat remove\": {\n method: \"chat.remove\", usage: \"chat remove <chat> --yes\", summary: \"Delete a chat, its keys and history on this device\", args: [\"chat\"],\n options: { yes: { type: \"boolean\", description: \"Confirm\" } }, params: ({ options }, { chat }) => ({ chat, yes: options.yes === true }),\n },\n \"chat rename\": { method: \"chat.rename\", usage: \"chat rename <chat> <name...>\", summary: \"Name a chat on this side (empty: the contact's name)\", args: [\"chat\", \"name...?\"], params: (_, { chat, name }) => ({ chat, name: name ?? \"\" }) },\n \"chat show\": { method: \"chat.get\", usage: \"chat show <chat> [--show-secret]\", summary: \"One chat and its connection (its pending invite code only with --show-secret)\", args: [\"chat\"], options: showInvite, params: ({ options }, { chat }) => ({ chat, ...secret(options) }) },\n \"chat transport\": { method: \"chat.transport\", usage: \"chat transport <chat> <auto|dht|webrtc|iroh|hyperdht>\", summary: \"Choose what carries a chat\", args: [\"chat\", \"transport\"], params: (_, a) => ({ chat: a.chat, transport: a.transport }) },\n \"chat verify\": {\n method: \"chat.verify\", usage: \"chat verify <chat> --code <code>\", summary: \"Mark a contact verified after comparing codes\", args: [\"chat\"],\n options: { code: { type: \"string\", description: \"The code the contact reads out\" } }, params: ({ options }, { chat }) => {\n if (typeof options.code !== \"string\" || !options.code.trim()) throw new CliError(\"usage\", \"--code is needed: ghostly chat verify <chat> --code <code>\");\n return { chat, code: options.code };\n },\n },\n \"chat wait\": {\n method: \"chat.wait\", usage: \"chat wait <chat> [--until live|text|paired] [--timeout s]\", summary: \"Wait for a chat to reach a state\", args: [\"chat\"],\n options: { until: { type: \"string\", description: \"live (default), text or paired\" }, timeout: { type: \"number\", description: \"Seconds (default 60)\" } },\n params: ({ options }, { chat }) => ({ chat, until: options.until, timeout: options.timeout }),\n },\n \"forward\": {\n method: \"chat.forward\", usage: \"forward <chat|group> <message>... --to <chat|group>... [--force] [--wait none|sent] [--timeout s]\",\n summary: \"Forward messages (texts, files from the bytes here) to up to 5 chats and groups, as new messages of yours\",\n args: [\"chat\", \"message...\"],\n options: {\n to: { type: \"list\", description: \"A chat or a group to forward to (id, prefix or name; group:<id> for a group; a dash-leading id as it is); up to 5\" },\n force: { type: \"boolean\", description: \"Forward even if a text looks like a seed, a key or ecash\" },\n wait: { type: \"string\", description: \"none or sent: each text on its way (in a group, taken by an edge), each file's transfer done (default none)\" },\n timeout: groupWait.timeout,\n },\n params: ({ options }, a) => {\n if (!Array.isArray(options.to) || !options.to.length) throw new CliError(\"usage\", \"Missing --to: ghostly forward <chat|group> <message>... --to <chat|group>... [--force] [--wait none|sent] [--timeout s]\");\n refs(options.to, \"to\", \"chat or group\");\n return { chat: a.chat, messages: (a.message ?? \"\").split(\" \").filter(Boolean), to: options.to, force: options.force === true, wait: options.wait, timeout: options.timeout };\n },\n },\n \"invite create\": {\n method: \"invite.create\", usage: \"invite create [--label <name>]\", summary: \"A new chat's ghostly1 invite and its link\",\n options: { label: { type: \"string\", description: \"A name for the chat on this side\" } },\n params: ({ options }) => ({ label: options.label }),\n },\n \"invite join\": {\n method: \"invite.join\", usage: \"invite join [<invite-or-link> | -] [--label <name>]\", summary: \"Join a chat from its invite; stdin keeps it out of ps (without a daemon it waits up to 60 s for the inviter)\",\n args: [\"invite?\"], options: { label: { type: \"string\", description: \"A name for the chat on this side\" } },\n params: ({ options }, { invite }) => ({ invite, label: options.label }),\n },\n \"message delete\": { method: \"chat.delete\", usage: \"message delete <chat> <message>\", summary: \"Forget a message on this device (the contact keeps theirs)\", args: [\"chat\", \"message\"], params: (_, a) => ({ chat: a.chat, message: a.message }) },\n \"message details\": { method: \"chat.details\", usage: \"message details <chat> <message>\", summary: \"How a message travelled\", args: [\"chat\", \"message\"], params: (_, a) => ({ chat: a.chat, message: a.message }) },\n \"message retry\": { method: \"chat.retry\", usage: \"message retry <chat> <message>\", summary: \"Send a failed message again\", args: [\"chat\", \"message\"], params: (_, a) => ({ chat: a.chat, message: a.message }) },\n \"pin\": {\n method: \"chat.pin\", usage: \"pin <chat|group> <message> | --remove\", summary: \"Pin a message at the top of a chat or group (one per chat: it replaces the pinned one); --remove unpins\",\n args: [\"chat\", \"message...?\"], options: { remove: { type: \"boolean\", description: \"Unpin the chat's pinned message (it names no message)\" } },\n params: ({ options }, a) => {\n // --remove names no message: the chat has one pin. One given beside it is taken as before, and not read.\n if (a.message === undefined && options.remove !== true) throw new CliError(\"usage\", \"Missing <message>: ghostly pin <chat|group> <message> | --remove\");\n if (a.message?.includes(\" \")) throw new CliError(\"usage\", \"Too many arguments: ghostly pin <chat|group> <message> | --remove\");\n return { chat: a.chat, message: a.message, remove: options.remove === true };\n },\n },\n \"react\": {\n method: \"chat.react\", usage: \"react <chat> <message> <emoji> [--remove]\", summary: \"React to a message with one emoji (it replaces yours); --remove takes yours back\",\n args: [\"chat\", \"message\", \"emoji...?\"], options: { remove: { type: \"boolean\", description: \"Take your reaction back\" } },\n params: ({ options }, a) => ({ chat: a.chat, message: a.message, emoji: a.emoji, remove: options.remove === true }),\n },\n \"routine send\": {\n method: \"routine.send\", usage: \"routine send <chat|group> --name <name> --schedule \\\"every day 01:00\\\" [--cron \\\"0 1 * * *\\\"] [--state active|paused] [--next <time>] [--run ok|failed|skipped[:summary]] [--link url]... [--id id] [--json json|-|file] [--force] [--wait none|sent|delivered] [--timeout s]\",\n summary: \"Send a routine card (something a bot runs on a schedule: its last run and the next) to a chat or group\",\n args: [\"chat\"],\n options: { id: { type: \"string\", description: \"The routine's id, kept across updates (default: made up)\" }, ...routineOptions, ...groupWait, wait: wait.wait },\n params: ({ options }, { chat }) => ({ chat, card: needs(routineFields(options), [[\"name\", \"name\"], [\"schedule\", \"schedule\"]], \"routine send <chat|group> --name <name> --schedule \\\"every day 01:00\\\"\"), run: runOf(options.run), text: options.text, force: options.force === true, wait: options.wait, timeout: options.timeout }),\n },\n \"routine update\": {\n method: \"routine.update\", usage: \"routine update <chat|group> <routine> [--run ok|failed|skipped[:summary]] [--next <time>] [--state active|paused] [--schedule ...] [--json json|-|file] [--force] [--wait none|confirmed|sent] [--timeout s]\",\n summary: \"Update a routine card you sent: record a run, the next one, a pause (at most one update per 2.5 s; sooner ones merge)\",\n args: [\"chat\", \"routine\"],\n options: { ...routineOptions, wait: { type: \"string\", description: \"none (default), confirmed (a chat's contact took it) or sent (a group's edge took it)\" }, timeout: groupWait.timeout },\n params: ({ options }, a) => ({ chat: a.chat, routine: a.routine, card: routineFields(options), run: runOf(options.run), text: options.text, force: options.force === true, wait: options.wait, timeout: options.timeout }),\n },\n \"task send\": {\n method: \"task.send\", usage: \"task send <chat|group> --title <title> [--status s] [--progress n | --steps a/b] [--step \\\"...\\\"] [--item state:text]... [--pr-url url --pr-number n --additions n --deletions n --files n --pr-state s --pr-checks c] [--branch b] [--tag label]... [--parent task] [--link url]... [--id id] [--json json|-|file] [--force] [--wait none|sent|delivered] [--timeout s]\",\n summary: \"Send a task card (a bot's work: status, progress, its PR) to a chat or group; prints its id and message\",\n args: [\"chat\"],\n options: { id: { type: \"string\", description: \"The task's id, kept across updates (default: made up)\" }, ...taskOptions, ...groupWait, wait: wait.wait },\n params: ({ options }, { chat }) => ({ chat, card: prLinked(needs(taskFields(options), [[\"title\", \"title\"]], \"task send <chat|group> --title <title>\"), options, \"task send <chat|group> --title <title> --pr-url <url>\"), text: options.text, force: options.force === true, wait: options.wait, timeout: options.timeout }),\n },\n \"task update\": {\n method: \"task.update\", usage: \"task update <chat|group> <task> [--status s] [--progress n | --steps a/b] [--step \\\"...\\\"] [--item state:text]... [--pr-url ...] [--pr-state s] [--pr-checks c] [--tag label]... [--parent task] [--json json|-|file] [--force] [--wait none|confirmed|sent] [--timeout s]\",\n summary: \"Update a task card you sent: the fields given, merged over it (at most one update per 2.5 s; sooner ones merge)\",\n args: [\"chat\", \"task\"],\n options: { ...taskOptions, wait: { type: \"string\", description: \"none (default), confirmed (a chat's contact took it) or sent (a group's edge took it)\" }, timeout: groupWait.timeout },\n params: ({ options }, a) => ({ chat: a.chat, task: a.task, card: taskFields(options), text: options.text, force: options.force === true, wait: options.wait, timeout: options.timeout }),\n },\n \"typing\": {\n method: \"chat.typing\", usage: \"typing <chat> [--kind typing|recording|thinking] [--status \\\"<text>\\\"] [--for s] [--stop]\",\n summary: \"Show the contact you are writing, recording or thinking (live chats; it fades after 6 s unless said again, or kept with --for; a send or --stop ends it)\", args: [\"chat\"],\n options: {\n stop: { type: \"boolean\", description: \"Say you stopped\" },\n kind: { type: \"string\", description: \"typing (default), recording (a voice note) or thinking\" },\n status: { type: \"string\", description: \"A short line shown instead, e.g. \\\"Transcribing your audio…\\\" (40 characters, no links)\" },\n for: { type: \"number\", description: \"Keep saying it for this many seconds (up to 600), until a send or --stop\" },\n },\n params: ({ options }, { chat }) => ({ chat, stop: options.stop === true, kind: options.kind, status: options.status, for: typingFor(options) }),\n },\n \"usage send\": {\n method: \"usage.send\", usage: \"usage send [<chat|group>] [--all] --left <percent> [--window \\\"5 h\\\"] [--resets <time>] [--label Claude] [--account <name>] [--also week=80@<time>]... [--used n --limit n] [--id id] [--json json|-|file] [--force] [--wait none|sent] [--timeout s]\",\n summary: \"Say how much of your quota is left (a bot's usage card, one per chat, updated in place); --all for every 1:1 chat\",\n args: [\"chat?\"],\n options: { ...usageOptions, ...groupWait },\n params: ({ options }, { chat }) => {\n if (!chat && options.all !== true) throw new CliError(\"usage\", \"Name a chat or group, or give --all: ghostly usage send <chat|--all> --left <percent>\");\n return { chat, all: options.all === true, card: quota(usageFields(options), \"usage send <chat|--all> --left <percent>\"), text: options.text, force: options.force === true, wait: options.wait, timeout: options.timeout };\n },\n },\n};\n","import { GROUP_FILE_LIMITS } from \"@ghostly/core/groupFiles\";\nimport { CliError } from \"../errors\";\nimport { type Command, here, reply } from \"./shared\";\n\n/** Files: one entry per command, in alphabetical order (test/commands.test.ts checks). */\nexport const commands: Record<string, Command> = {\n \"file accept\": { method: \"file.action\", usage: \"file accept [<chat>] <file>\", summary: \"Take a file the contact offers, or download a group's file that did not come by itself (<chat> may be the group)\", args: [\"chat?\", \"file\"], params: (_, a) => ({ chat: a.chat, file: a.file, action: \"accept\" }) },\n \"file cancel\": { method: \"file.action\", usage: \"file cancel [<chat>] <file>\", summary: \"Cancel a transfer\", args: [\"chat?\", \"file\"], params: (_, a) => ({ chat: a.chat, file: a.file, action: \"cancel\" }) },\n \"file decline\": { method: \"file.action\", usage: \"file decline [<chat>] <file>\", summary: \"Refuse a file the contact offers\", args: [\"chat?\", \"file\"], params: (_, a) => ({ chat: a.chat, file: a.file, action: \"decline\" }) },\n \"file list\": { method: \"file.list\", usage: \"file list <chat|group>\", summary: \"A chat's or a group's files and their transfers\", args: [\"chat\"], params: (_, { chat }) => ({ chat }) },\n \"file pause\": { method: \"file.action\", usage: \"file pause [<chat>] <file>\", summary: \"Pause a transfer\", args: [\"chat?\", \"file\"], params: (_, a) => ({ chat: a.chat, file: a.file, action: \"pause\" }) },\n \"file request\": { method: \"file.action\", usage: \"file request [<chat>] <file>\", summary: \"Ask again for a file that stopped arriving: it goes on from what is here (a group's file: asked of whoever holds it)\", args: [\"chat?\", \"file\"], params: (_, a) => ({ chat: a.chat, file: a.file, action: \"request\" }) },\n \"file resend\": { method: \"file.action\", usage: \"file resend [<chat>] <file>\", summary: \"Send again a file that stopped moving or failed: it goes on from what the contact holds\", args: [\"chat?\", \"file\"], params: (_, a) => ({ chat: a.chat, file: a.file, action: \"resend\" }) },\n \"file resume\": { method: \"file.action\", usage: \"file resume [<chat>] <file>\", summary: \"Resume a transfer\", args: [\"chat?\", \"file\"], params: (_, a) => ({ chat: a.chat, file: a.file, action: \"resume\" }) },\n \"file save\": {\n method: \"file.save\", usage: \"file save [<chat>] <file> [--dir d | --path p] [--force] [--wait [--timeout s]]\", summary: \"Write a received file to disk (never over a file without --force; --wait: once it is all here)\",\n args: [\"chat?\", \"file\"],\n options: {\n dir: { type: \"string\", description: \"Into this folder, under its own name\" }, path: { type: \"string\", description: \"To this path\" }, force: { type: \"boolean\", description: \"Replace a file there\" },\n wait: { type: \"boolean\", description: \"Wait for the transfer to finish first\" }, timeout: { type: \"number\", description: \"Seconds --wait waits (default 300)\" },\n },\n params: ({ options }, a) => {\n // Empty (an unset variable in a script), it was the current folder: --path \"\" asked to replace it.\n if (options.path === \"\") throw new CliError(\"usage\", \"--path needs a file\");\n if (options.dir === \"\") throw new CliError(\"usage\", \"--dir needs a folder\");\n if (options.dir !== undefined && options.path !== undefined) throw new CliError(\"usage\", \"--path names the file: not with --dir\");\n if (options.timeout !== undefined && options.wait !== true) throw new CliError(\"usage\", \"--timeout is how long --wait waits: not without --wait\");\n return {\n chat: a.chat, file: a.file, dir: options.path === undefined ? here(options.dir ?? \".\") : undefined, path: here(options.path), force: options.force === true,\n wait: options.wait === true ? true : undefined, timeout: options.timeout,\n };\n },\n },\n \"file send\": {\n method: \"file.send\", usage: \"file send <chat|group> <path> [--name n] [--mime t] [--voice [ms] [--peaks 0,40,…]] [--reply <message>]\", summary: `Send a file (or, with --voice, a voice note), as a reply with --reply; to a group, every member's app fetches it (up to ${GROUP_FILE_LIMITS.maxBytes / 1024 / 1024} MiB)`,\n args: [\"chat\", \"path\"], options: { name: { type: \"string\", description: \"The name the contact (or the group) sees\" }, mime: { type: \"string\", description: \"Its type (default: from the extension)\" }, voice: { type: \"number\", optionalValue: true, description: \"A voice note; its length in milliseconds (default: measured from the sound)\" }, peaks: { type: \"string\", description: \"Loudness bars 0-255, comma-separated (default: measured from the sound)\" }, reply },\n params: ({ options }, a) => ({ chat: a.chat, path: here(a.path), name: options.name, mime: options.mime, voice: options.voice, peaks: typeof options.peaks === \"string\" ? options.peaks.split(\",\") : undefined, reply: options.reply }),\n },\n \"file wait\": {\n method: \"file.wait\", usage: \"file wait [<chat>] <file> [--timeout s]\", summary: \"Wait until a transfer is done (exit 0) or failed (exit 1, with its error)\",\n args: [\"chat?\", \"file\"], options: { timeout: { type: \"number\", description: \"Seconds (default 300)\" } },\n params: ({ options }, a) => ({ chat: a.chat, file: a.file, timeout: options.timeout }),\n },\n};\n","import { CliError } from \"../errors\";\nimport { type Command, here } from \"./shared\";\n\n/** The profile's status, its picture, the event journal: one entry per command, in alphabetical order (test/commands.test.ts checks). */\nexport const commands: Record<string, Command> = {\n \"events\": {\n method: \"events.replay\", usage: \"events [--since seq]\", summary: \"Events the journal holds, without following\",\n options: { since: { type: \"number\", description: \"Only events after this seq\" } }, params: ({ options }) => ({ since: options.since ?? 0 }),\n },\n \"profile picture\": {\n method: \"profile.picture\", usage: \"profile picture <jpeg> | --clear\", summary: \"The picture contacts see (a square JPEG, 128 px is what the app sends)\", args: [\"path...?\"],\n options: { clear: { type: \"boolean\", description: \"Remove the picture\" } },\n params: ({ options }, a) => {\n if (!a.path && options.clear !== true) throw new CliError(\"usage\", \"Missing <jpeg>: ghostly profile picture <jpeg> | --clear\");\n if (a.path && options.clear === true) throw new CliError(\"usage\", \"--clear removes the picture: not with a <jpeg>\");\n return { path: here(a.path || undefined), clear: options.clear === true };\n },\n },\n \"status\": { method: \"status\", usage: \"status\", summary: \"The profile, its chats and whether a daemon runs it\" },\n};\n","import { CliError } from \"../errors\";\nimport { type Command, here, showSecret, secret, cursor, typingFor } from \"./shared\";\n\n/** Groups: one entry per command, in alphabetical order (test/commands.test.ts checks). */\nexport const commands: Record<string, Command> = {\n \"group accept\": { method: \"group.accept\", usage: \"group accept <group>\", summary: \"Accept an invitation to a group\", args: [\"group\"], params: (_, { group }) => ({ group }) },\n \"group admin\": {\n method: \"group.admin\", usage: \"group admin <group> <member> [--show-secret]\", summary: \"Make a member the admin (admin)\", args: [\"group\", \"member\"],\n options: showSecret, params: ({ options }, a) => ({ group: a.group, member: a.member, ...secret(options) }),\n },\n \"group create\": {\n method: \"group.create\", usage: \"group create <name...> [--mesh]\", summary: \"A community (a link anyone can open) or, with --mesh, a private group of up to 32\",\n args: [\"name...\"], options: { mesh: { type: \"boolean\", description: \"A private mesh of contacts instead of a community\" } },\n params: ({ options }, { name }) => ({ name, profile: options.mesh ? \"mesh\" : \"community\" }),\n },\n \"group decline\": { method: \"group.decline\", usage: \"group decline <group>\", summary: \"Decline an invitation to a group\", args: [\"group\"], params: (_, { group }) => ({ group }) },\n \"group forget\": {\n method: \"group.forget\", usage: \"group forget <group> --yes\", summary: \"Leave and delete a group's history here\", args: [\"group\"],\n options: { yes: { type: \"boolean\", description: \"Confirm\" } }, params: ({ options }, { group }) => ({ group, yes: options.yes === true }),\n },\n \"group history\": {\n method: \"group.history\", usage: \"group history <group> [--limit n] [--before id|ms] [--after id|ms]\", summary: \"A group's messages (a page)\", args: [\"group\"],\n options: { limit: { type: \"number\", description: \"Messages per page (default 50)\" }, before: { type: \"string\", description: \"Only before this message id or timestamp\" }, after: { type: \"string\", description: \"Only after this message id or timestamp\" } },\n params: ({ options }, { group }) => ({ group, limit: options.limit, before: cursor(options.before, \"before\"), after: cursor(options.after, \"after\") }),\n },\n \"group hub\": {\n method: \"group.hub\", usage: \"group hub <group> <member> [--pin | --exclude | --auto] [--show-secret]\",\n summary: \"Pin a member as a hub of a private group past 16 members, exclude one, or leave it to their app (admin)\", args: [\"group\", \"member\"],\n options: { ...showSecret, pin: { type: \"boolean\", description: \"Always a hub while online\" }, exclude: { type: \"boolean\", description: \"Never a hub\" }, auto: { type: \"boolean\", description: \"A hub if their app stays online (the default)\" } },\n params: ({ options }, a) => {\n const roles = ([\"pin\", \"exclude\", \"auto\"] as const).filter((role) => options[role] === true);\n if (roles.length > 1) throw new CliError(\"usage\", \"--pin, --exclude or --auto: one of them\");\n return { group: a.group, member: a.member, role: roles[0] ?? \"auto\", ...secret(options) };\n },\n },\n \"group invite\": {\n method: \"group.invite\", usage: \"group invite <group> <chat> [--show-secret]\", summary: \"Invite a contact into a group you administer\", args: [\"group\", \"chat\"],\n options: showSecret, params: ({ options }, a) => ({ group: a.group, chat: a.chat, ...secret(options) }),\n },\n \"group join\": { method: \"group.join\", usage: \"group join [<link> | -]\", summary: \"Join a group by its link; the link on stdin keeps it out of ps\", args: [\"link?\"], params: (_, { link }) => ({ link }) },\n \"group leave\": {\n method: \"group.leave\", usage: \"group leave <group> --yes\", summary: \"Leave a group; its history and files go from this device\", args: [\"group\"],\n options: { yes: { type: \"boolean\", description: \"Confirm\" } }, params: ({ options }, { group }) => ({ group, yes: options.yes === true }),\n },\n \"group link\": {\n method: \"group.link\", usage: \"group link <group> [--off] [--reset]\", summary: \"Turn the group's link on (--reset: a new one), or --off\", args: [\"group\"],\n options: { off: { type: \"boolean\", description: \"Turn the link off\" }, reset: { type: \"boolean\", description: \"Replace it: the old link stops working\" } },\n params: ({ options }, a) => {\n if (options.off === true && options.reset === true) throw new CliError(\"usage\", \"--off turns the link off: not with --reset\");\n return { group: a.group, on: options.off !== true, reset: options.reset === true };\n },\n },\n \"group list\": { method: \"group.list\", usage: \"group list [--show-secret]\", summary: \"Groups and invitations\", options: showSecret, params: ({ options }) => secret(options) },\n \"group picture\": {\n method: \"group.picture\", usage: \"group picture <group> <jpeg> | --clear\", summary: \"Set or clear the group's picture (admin; a square JPEG)\", args: [\"group\", \"path...?\"],\n options: { clear: { type: \"boolean\", description: \"Remove the picture\" } },\n params: ({ options }, a) => {\n if (!a.path && options.clear !== true) throw new CliError(\"usage\", \"Missing <jpeg>: ghostly group picture <group> <jpeg> | --clear\");\n if (a.path && options.clear === true) throw new CliError(\"usage\", \"--clear removes the picture: not with a <jpeg>\");\n return { group: a.group, path: here(a.path || undefined), clear: options.clear === true };\n },\n },\n \"group react\": {\n method: \"group.react\", usage: \"group react <group> <message> <emoji> [--remove]\", summary: \"React to a group's message with one emoji; --remove takes yours back\",\n args: [\"group\", \"message\", \"emoji...?\"], options: { remove: { type: \"boolean\", description: \"Take your reaction back\" } },\n params: ({ options }, a) => ({ group: a.group, message: a.message, emoji: a.emoji, remove: options.remove === true }),\n },\n \"group remove\": {\n method: \"group.remove\", usage: \"group remove <group> <member> [--show-secret]\", summary: \"Remove a member (admin)\", args: [\"group\", \"member\"],\n options: showSecret, params: ({ options }, a) => ({ group: a.group, member: a.member, ...secret(options) }),\n },\n \"group rename\": {\n method: \"group.rename\", usage: \"group rename <group> <name...> [--show-secret]\", summary: \"Rename the group (admin; the picture stays)\", args: [\"group\", \"name...\"],\n options: showSecret, params: ({ options }, a) => ({ group: a.group, name: a.name, ...secret(options) }),\n },\n \"group rotate\": {\n method: \"group.rotate\", usage: \"group rotate <group> [--show-secret]\", summary: \"A fresh group secret, members unchanged (admin)\", args: [\"group\"],\n options: showSecret, params: ({ options }, a) => ({ group: a.group, ...secret(options) }),\n },\n \"group show\": {\n method: \"group.get\", usage: \"group show <group> [--show-secret]\", summary: \"A group and its members (its entry link only with --show-secret)\", args: [\"group\"],\n options: showSecret, params: ({ options }, { group }) => ({ group, ...secret(options) }),\n },\n \"group typing\": {\n method: \"group.typing\", usage: \"group typing <group> [--kind typing|recording|thinking] [--status \\\"<text>\\\"] [--for s] [--stop]\",\n summary: \"Show the members you are writing, recording or thinking (private groups; it fades after 6 s unless said again, or kept with --for; a send or --stop ends it)\", args: [\"group\"],\n options: {\n stop: { type: \"boolean\", description: \"Say you stopped\" },\n kind: { type: \"string\", description: \"typing (default), recording (a voice note) or thinking\" },\n status: { type: \"string\", description: \"A short line shown instead, e.g. \\\"Reading the thread…\\\" (40 characters, no links)\" },\n for: { type: \"number\", description: \"Keep saying it for this many seconds (up to 600), until a send or --stop\" },\n },\n params: ({ options }, { group }) => ({ group, stop: options.stop === true, kind: options.kind, status: options.status, for: typingFor(options) }),\n },\n};\n","import { CliError } from \"../errors\";\nimport { type Command, here, secret } from \"./shared\";\n\n/** Identity proofs and x401 credentials: one entry per command, in alphabetical order (test/commands.test.ts checks). */\nexport const commands: Record<string, Command> = {\n \"identity cancel\": { method: \"identity.cancel\", usage: \"identity cancel <draft>\", summary: \"Drop a proof not finished\", args: [\"draft\"], params: (_, a) => ({ draft: a.draft }) },\n \"identity complete\": {\n method: \"identity.complete\", usage: \"identity complete <draft> [--evidence-file f | --stdin]\", summary: \"Finish a proof: what the tool printed, or nothing for a published record\",\n args: [\"draft\"], options: { \"evidence-file\": { type: \"string\", description: \"The tool's output, from this file\" }, stdin: { type: \"boolean\", description: \"The tool's output, from stdin\" } },\n params: ({ options }, a) => {\n if (options[\"evidence-file\"] !== undefined && options.stdin === true) throw new CliError(\"usage\", \"--evidence-file or --stdin, not both\");\n return { draft: a.draft, evidenceFile: here(options[\"evidence-file\"]), stdin: options.stdin === true };\n },\n },\n \"identity contact\": { method: \"identity.contact\", usage: \"identity contact <chat>\", summary: \"What a contact shared, as this device checked it\", args: [\"chat\"], params: (_, a) => ({ chat: a.chat }) },\n \"identity list\": { method: \"identity.list\", usage: \"identity list\", summary: \"This profile's identity proofs\" },\n \"identity providers\": { method: \"identity.providers\", usage: \"identity providers\", summary: \"Kinds of identity proof, and which signers work here\" },\n \"identity recheck\": { method: \"identity.recheck\", usage: \"identity recheck <chat> <id>\", summary: \"Check a contact's proof again\", args: [\"chat\", \"id\"], params: (_, a) => ({ chat: a.chat, id: a.id }) },\n \"identity remove\": { method: \"identity.remove\", usage: \"identity remove <id>\", summary: \"Remove a proof: withdrawn from every chat, revoked\", args: [\"id\"], params: (_, a) => ({ id: a.id }) },\n \"identity share\": { method: \"identity.share\", usage: \"identity share <chat> <id>\", summary: \"Show a proof to a contact\", args: [\"chat\", \"id\"], params: (_, a) => ({ chat: a.chat, id: a.id }) },\n \"identity withdraw\": { method: \"identity.withdraw\", usage: \"identity withdraw <chat> <id>\", summary: \"Withdraw a proof from a contact\", args: [\"chat\", \"id\"], params: (_, a) => ({ chat: a.chat, id: a.id }) },\n \"x401 credential add\": {\n method: \"x401.credential.add\", usage: \"x401 credential add <file|-> [--label <name>]\", summary: \"Keep an issued SD-JWT VC bound to a key from x401 key new (a file, or - for stdin)\",\n args: [\"file\"], options: { label: { type: \"string\", description: \"Your name for it, up to 80 characters on one line (default: its type)\" } },\n params: ({ options }, a) => ({ file: a.file === \"-\" ? \"-\" : here(a.file), label: options.label }),\n },\n \"x401 credential list\": {\n method: \"x401.credential.list\", usage: \"x401 credential list [--show-secret]\", summary: \"This profile's x401 credentials: issuer, type, claim paths\",\n options: { \"show-secret\": { type: \"boolean\", description: \"Print the claims' values too (a name, a document number...)\" } }, params: ({ options }) => secret(options),\n },\n \"x401 credential remove\": { method: \"x401.credential.remove\", usage: \"x401 credential remove <id>\", summary: \"Remove a credential and its holder key\", args: [\"id\"], params: (_, a) => ({ id: a.id }) },\n \"x401 key new\": { method: \"x401.key.new\", usage: \"x401 key new\", summary: \"A fresh P-256 holder key: its public JWK goes to the issuer (the 8 newest wait for a credential; past them, the oldest is dropped)\" },\n};\n","import { type Command, net, card, memo, confirmReal, force, sats, pairs } from \"./shared\";\n\n/** Wallets and payments: one entry per command, in alphabetical order (test/commands.test.ts checks). */\nexport const commands: Record<string, Command> = {\n \"chat accept\": {\n method: \"chat.accept\", usage: \"chat accept <chat> <method> [--off] [--networks mainnet,testnet]\", summary: \"Which ways of paying a chat takes\",\n args: [\"chat\", \"method\"], options: { off: { type: \"boolean\", description: \"Stop taking it\" }, networks: { type: \"string\", description: \"Comma-separated networks it is taken on\" } },\n params: ({ options }, a) => ({ chat: a.chat, method: a.method, on: options.off !== true, networks: typeof options.networks === \"string\" ? options.networks.split(\",\").map((n) => n.trim()).filter(Boolean) : undefined }),\n },\n \"chat pay\": {\n method: \"chat.pay\", usage: \"chat pay <chat> <sats> [--memo t] [--network testnet] [--confirm-real] [--force]\", summary: \"Send ecash to a contact (Mainnet needs --confirm-real)\",\n args: [\"chat\", \"amount\"], options: { memo, network: net, \"confirm-real\": confirmReal, force },\n params: ({ options }, a) => ({ chat: a.chat, amount: sats(a.amount), memo: options.memo, network: options.network, confirmReal: options[\"confirm-real\"] === true, force: options.force === true }),\n },\n \"chat pay-request\": {\n method: \"chat.payRequest\", usage: \"chat pay-request <chat> <payment> [--via lightning] [--max-fee sats] [--card <id>] [--confirm-real]\", summary: \"Pay a contact's request\",\n args: [\"chat\", \"payment\"], options: { via: { type: \"string\", description: \"lightning: pay its invoice instead of ecash\" }, \"max-fee\": { type: \"number\", description: \"Refuse a fee above this\" }, card, \"confirm-real\": confirmReal },\n params: ({ options }, a) => ({ chat: a.chat, payment: a.payment, via: options.via, maxFee: options[\"max-fee\"], card: options.card, confirmReal: options[\"confirm-real\"] === true }),\n },\n \"chat request\": {\n method: \"chat.request\", usage: \"chat request <chat> <sats> [--memo t] [--method m] [--rail cashu|lightning] [--network testnet] [--card <id>] [--force]\", summary: \"Ask a contact to pay\",\n args: [\"chat\", \"amount\"], options: { memo, method: { type: \"string\", description: \"cashu, arkade, usdt, bitcoin, spark, …\" }, rail: { type: \"string\", description: \"cashu or lightning\" }, network: net, card, force },\n params: ({ options }, a) => ({ chat: a.chat, amount: sats(a.amount), memo: options.memo, method: options.method, rail: options.rail, network: options.network, card: options.card, force: options.force === true }),\n },\n \"lightning default\": { method: \"lightning.default\", usage: \"lightning default <card> [--network testnet]\", summary: \"The Lightning card that receives by default\", args: [\"card\"], options: { network: net }, params: ({ options }, { card: c }) => ({ card: c, network: options.network }) },\n \"lightning rename\": { method: \"lightning.rename\", usage: \"lightning rename <card> <name...> [--network testnet]\", summary: \"Name a Lightning card\", args: [\"card\", \"name...\"], options: { network: net }, params: ({ options }, a) => ({ card: a.card, name: a.name, network: options.network }) },\n \"pay\": {\n method: \"pay\", usage: \"pay <invoice|lightning-address|lnurl> [--amount sats] [--network n] [--max-fee sats] [--card <id>] [--comment t] [--confirm-real]\", summary: \"Pay over Lightning from Testnet, or --network mainnet with --confirm-real\",\n args: [\"target\"], options: { amount: { type: \"number\", description: \"Sats, for an address or LNURL\" }, network: net, \"max-fee\": { type: \"number\", description: \"Refuse a fee above this\" }, card, comment: { type: \"string\", description: \"For the address's owner\" }, \"confirm-real\": confirmReal },\n params: ({ options }, { target }) => ({ target, amount: options.amount, network: options.network, maxFee: options[\"max-fee\"], card: options.card, comment: options.comment, confirmReal: options[\"confirm-real\"] === true }),\n },\n \"payment check\": { method: \"payment.check\", usage: \"payment check <chat> <payment>\", summary: \"Paid from another wallet: the contact's app looks now\", args: [\"chat\", \"payment\"], params: (_, a) => ({ chat: a.chat, payment: a.payment }) },\n \"payment list\": { method: \"payment.list\", usage: \"payment list [--chat <chat>]\", summary: \"Payments and requests, newest first\", options: { chat: { type: \"string\", description: \"Only this chat's\" } }, params: ({ options }) => ({ chat: options.chat }) },\n \"payment reclaim\": { method: \"payment.reclaim\", usage: \"payment reclaim <payment>\", summary: \"Take back ecash the contact has not taken\", args: [\"payment\"], params: (_, a) => ({ payment: a.payment }) },\n \"wallet add-mint\": {\n method: \"wallet.mint.add\", usage: \"wallet add-mint <url> [--primary]\", summary: \"Add a Cashu mint (a local or test mint is Testnet's)\",\n args: [\"url\"], options: { primary: { type: \"boolean\", description: \"Make it the one invoices are created at\" } }, params: ({ options }, { url }) => ({ url, primary: options.primary === true }),\n },\n \"wallet address\": {\n method: \"wallet.address\", usage: \"wallet address <bitcoin|arkade|spark|usdt> [--network testnet]\", summary: \"An address to be paid on\",\n args: [\"type\"], options: { network: net }, params: ({ options }, { type }) => ({ type, network: options.network }),\n },\n \"wallet create\": {\n method: \"wallet.create\", usage: \"wallet create <type> [--network testnet] [--provider <id>] [--value name=value]... [--stdin] [--invite <code>] [--api-key <key>]\", summary: \"A wallet: cashu, lightning, arkade, spark, bitcoin, fedimint, usdt (bark: app only)\",\n args: [\"type\"], options: { network: net, provider: { type: \"string\", description: \"Lightning or on-chain source (wallet list shows them)\" }, value: { type: \"list\", description: \"A field of the source's form, name=value\" }, stdin: { type: \"boolean\", description: \"Secret fields as name=value lines on stdin (api-key=… for the API key), kept out of ps\" }, invite: { type: \"string\", description: \"Fedimint: the federation's invite\" }, \"api-key\": { type: \"string\", description: \"Spark on Mainnet: your Breez API key (better on stdin: --stdin)\" } },\n params: ({ options }, { type }) => ({ type, network: options.network, provider: options.provider, invite: options.invite, apiKey: options[\"api-key\"], values: pairs(options.value), stdin: options.stdin === true ? true : undefined }),\n },\n \"wallet faucet\": {\n method: \"wallet.faucet\", usage: \"wallet faucet <type> [--card <id>]\", summary: \"Test coins from a Testnet wallet's faucet\",\n args: [\"type\"], options: { card }, params: ({ options }, { type }) => ({ type, network: \"testnet\", card: options.card }),\n },\n \"wallet history\": {\n method: \"wallet.history\", usage: \"wallet history [--network testnet] [--limit n]\", summary: \"A network's wallet history, newest first\",\n options: { network: net, limit: { type: \"number\", description: \"Entries (default 50)\" } }, params: ({ options }) => ({ network: options.network, limit: options.limit }),\n },\n \"wallet list\": {\n method: \"wallet.list\", usage: \"wallet list [--network mainnet|testnet]\", summary: \"Wallets with their balances, and what New can make\",\n options: { network: net }, params: ({ options }) => ({ network: options.network }),\n },\n \"wallet receive\": {\n method: \"wallet.receive\", usage: \"wallet receive <sats> [--network testnet] [--card <id>]\", summary: \"A Lightning invoice to be paid\",\n args: [\"amount\"], options: { network: net, card }, params: ({ options }, { amount }) => ({ amount: sats(amount), network: options.network, card: options.card }),\n },\n \"wallet redeem\": { method: \"wallet.redeem\", usage: \"wallet redeem [<cashu-token>]\", summary: \"Take the ecash of a Cashu token (its mint must be one of yours); the token on stdin keeps it out of ps\", args: [\"token?\"], params: (_, { token }) => ({ token }) },\n \"wallet remove\": {\n method: \"wallet.remove\", usage: \"wallet remove <type> [--network testnet] [--card <id>] [--accept-loss]\", summary: \"Remove a wallet; refused while it holds money or waits for some, unless --accept-loss\",\n args: [\"type\"], options: { network: net, card: card, \"accept-loss\": { type: \"boolean\", description: \"What it holds on this device is lost without its backup\" } },\n params: ({ options }, { type }) => ({ type, network: options.network, card: options.card, acceptLoss: options[\"accept-loss\"] === true }),\n },\n};\n","import { type Command } from \"./shared\";\n\n/** Shared local services: one entry per command, in alphabetical order (test/commands.test.ts checks). */\nexport const commands: Record<string, Command> = {\n \"service add\": { method: \"service.add\", usage: \"service add <name> <http://127.0.0.1:port>\", summary: \"A web app on this machine that contacts may be given\", args: [\"name\", \"target\"], params: (_, a) => ({ name: a.name, target: a.target }) },\n \"service close\": { method: \"service.close\", usage: \"service close <chat> <service>\", summary: \"Close a contact's app opened here\", args: [\"chat\", \"service\"], params: (_, a) => ({ chat: a.chat, service: a.service }) },\n \"service enable\": { method: \"service.enable\", usage: \"service enable <service> [--off]\", summary: \"Turn a shared app on or off\", args: [\"service\"], options: { off: { type: \"boolean\", description: \"Turn it off\" } }, params: ({ options }, a) => ({ service: a.service, off: options.off === true }) },\n \"service list\": { method: \"service.list\", usage: \"service list\", summary: \"Web apps this profile shares\" },\n \"service open\": { method: \"service.open\", usage: \"service open <chat> <service> [--port p]\", summary: \"A contact's app on a loopback port here (daemon)\", args: [\"chat\", \"service\"], options: { port: { type: \"number\", description: \"Local port (default: any free one)\" } }, params: ({ options }, a) => ({ chat: a.chat, service: a.service, port: options.port }) },\n \"service peer\": { method: \"service.peer\", usage: \"service peer <chat>\", summary: \"What a contact shares with you\", args: [\"chat\"], params: (_, a) => ({ chat: a.chat }) },\n \"service remove\": { method: \"service.remove\", usage: \"service remove <service>\", summary: \"Stop sharing a web app with anyone\", args: [\"service\"], params: (_, a) => ({ service: a.service }) },\n \"service share\": { method: \"service.share\", usage: \"service share <service> <chat> [--off]\", summary: \"Give (or take back) a contact access to a web app\", args: [\"service\", \"chat\"], options: { off: { type: \"boolean\", description: \"Take it back\" } }, params: ({ options }, a) => ({ service: a.service, chat: a.chat, off: options.off === true }) },\n};\n","import { CliError } from \"../errors\";\nimport { commands as apps } from \"./apps\";\nimport { commands as calls } from \"./calls\";\nimport { commands as chats } from \"./chats\";\nimport { commands as files } from \"./files\";\nimport { commands as general } from \"./general\";\nimport { commands as groups } from \"./groups\";\nimport { commands as identities } from \"./identities\";\nimport { commands as payments } from \"./payments\";\nimport { commands as services } from \"./services\";\nimport { type Command, wait, groupWait, force, reply, buttonOptions } from \"./shared\";\nimport type { OptionSpec } from \"../args\";\n\nexport type { Command };\n\n/**\n * The commands that are one API method each, one file per area of the app, each in alphabetical order. A new\n * command goes in its area's file at its place; a new area is a new file and its two lines here. The order here\n * is the order `ghostly help` lists them in.\n */\nexport const COMMANDS: Record<string, Command> = {\n ...general,\n ...chats,\n ...groups,\n ...files,\n ...payments,\n ...identities,\n ...services,\n ...calls,\n ...apps,\n};\n\n/** Commands that take text (argument or stdin), with the secret guard and delivery waits. */\nexport const TEXT_COMMANDS: Record<string, { method: string; target: \"chat\" | \"group\"; message?: true; usage: string; summary: string; args: string[]; options: Record<string, OptionSpec> }> = {\n \"send\": {\n method: \"chat.send\", target: \"chat\", args: [\"chat\", \"text...?\"], usage: \"send <chat> [text...] [--reply <message>] [--button id:Label]... [--style id=primary|neutral|danger]... [--once] [--id id] [--stdin] [--force] [--wait none|sent|delivered]\", summary: \"Send a message (text from arguments or stdin); --button puts buttons under it, each label its own (case aside)\",\n options: { stdin: { type: \"boolean\", description: \"Read the text from stdin\" }, force, reply, ...buttonOptions, ...wait },\n },\n \"edit\": {\n method: \"chat.edit\", target: \"chat\", message: true, args: [\"chat\", \"message\", \"text...?\"], usage: \"edit <chat> <message> [text... | --text <text> | --stdin] [--force] [--wait none|confirmed]\", summary: \"Replace the text of a message you sent (the id send gave; in a group, group edit)\",\n options: { stdin: { type: \"boolean\", description: \"Read the new text from stdin\" }, text: { type: \"string\", description: \"The new text, as one argument\" }, force, wait: { type: \"string\", description: \"none or confirmed (default: none with a daemon, confirmed without)\" }, timeout: wait.timeout },\n },\n \"group send\": {\n method: \"group.send\", target: \"group\", args: [\"group\", \"text...?\"], usage: \"group send <group> [text...] [--mention <member>]... [--reply <message>] [--button id:Label]... [--style id=primary|neutral|danger]... [--once] [--id id] [--stdin] [--force] [--wait none|sent] [--timeout s]\", summary: \"Send to a group; mention members written as @name in the text; --button puts buttons under it\",\n options: { stdin: { type: \"boolean\", description: \"Read the text from stdin\" }, force, reply, mention: { type: \"list\", description: \"A member (key, key prefix, name or everyone) named as @name in the text\" }, ...buttonOptions, ...groupWait },\n },\n \"group edit\": {\n method: \"group.edit\", target: \"group\", message: true, args: [\"group\", \"message\", \"text...?\"], usage: \"group edit <group> <message> [text... | --text <text> | --stdin] [--mention <member>]... [--force] [--wait none|sent] [--timeout s]\", summary: \"Replace the text of a message you sent to a group (the id group send gave)\",\n options: { stdin: { type: \"boolean\", description: \"Read the new text from stdin\" }, text: { type: \"string\", description: \"The new text, as one argument\" }, force, mention: { type: \"list\", description: \"A member newly named as @name in the text (those the message named stay)\" }, ...groupWait },\n },\n};\n\n\n/**\n * Positionals that name something by its id (a chat or a group also by a prefix or its name). The ids are the\n * engine's and the contacts', and drafts, payments and groups are base64url, which starts with `-` one time in 64:\n * in these a word that starts with a dash is the value. A mistyped flag there names nothing and fails as not found;\n * text, names and paths stay strict.\n */\nconst ID_ARGS = new Set([\"chat\", \"message\", \"group\", \"member\", \"payment\", \"file\", \"draft\", \"id\", \"card\", \"service\", \"call\"]);\n\n/** A leading positional that may be left out (`name?`); a trailing one that may (`text...?`) shifts nothing. */\nconst leadingOptional = (name: string) => name.endsWith(\"?\") && !name.endsWith(\"...?\");\n\n/**\n * Which of a command's positionals take an id, by index (a trailing `...` one covers the rest). An optional `name?`\n * shifts the others, so it counts only where it and what may come in its place are all ids.\n */\nexport function idSlot(command: { args?: string[] }): (index: number) => boolean {\n const names = (command.args ?? []).map((name) => name.replace(/\\?$/, \"\"));\n const shift = (command.args ?? []).filter(leadingOptional).length;\n const rest = names.findIndex((name) => name.endsWith(\"...\"));\n const at = (index: number) => {\n const name = rest !== -1 && index >= rest ? names[rest].slice(0, -3) : names[index];\n return name !== undefined && ID_ARGS.has(name);\n };\n return (index) => at(index) && (shift === 0 || index + shift >= names.length || at(index + shift));\n}\n\n/**\n * The placeholders a usage line shows for its positionals, in order: `chat pay <chat> <sats> [--memo t]` →\n * [\"chat\", \"sats\"]. One that is not a plain `<x>` (`[text... | --text <text>]`) is undefined; the flags end them.\n */\nfunction usageNames(usage: string): (string | undefined)[] {\n const words = usage.split(/\\s+/);\n const first = words.findIndex((word) => word.startsWith(\"<\") || word.startsWith(\"[\"));\n const out: (string | undefined)[] = [];\n for (const word of first === -1 ? [] : words.slice(first)) {\n if (/^\\[?-|^\\|/.test(word)) break;\n out.push(/^\\[?<([^>]+?)(?:\\.\\.\\.)?>(?:\\.\\.\\.)?\\]?$/.exec(word)?.[1]);\n }\n return out;\n}\n\n/**\n * The positionals of a command, by name; missing required ones are a usage error, and so are ones given as \"\" (an\n * unset variable in a script), before the profile opens. A leading `name?` is optional: it is given only when every\n * required one is there too (`file accept [<chat>] <file>`). A trailing `name...` takes the rest and needs at least\n * one word that is not \"\"; `name...?` may take none (text from stdin, `chat rename`'s name back to the contact's).\n */\nexport function positionals(command: { usage: string; args?: string[] }, values: readonly string[]): Record<string, string | undefined> {\n let names = command.args ?? [];\n const optional = names.filter(leadingOptional);\n let skip = 0;\n if (optional.length) {\n skip = Math.max(0, optional.length - Math.max(0, values.length - (names.length - optional.length)));\n names = [...optional.slice(skip).map((name) => name.slice(0, -1)), ...names.filter((name) => !leadingOptional(name))];\n }\n // Named as the usage line shows it (`<sats>`, not the parameter's `amount`).\n const shown = usageNames(command.usage);\n const missing = (i: number, name: string) => new CliError(\"usage\", `Missing <${shown[i + skip] ?? name}>: ghostly ${command.usage}`);\n const out: Record<string, string | undefined> = {};\n for (let i = 0; i < names.length; i++) {\n const name = names[i].replace(/\\?$/, \"\");\n if (name.endsWith(\"...\")) {\n const rest = values.slice(i);\n if (rest.every((word) => word === \"\") && !names[i].endsWith(\"?\")) throw missing(i, name.slice(0, -3));\n out[name.slice(0, -3)] = rest.length ? rest.join(\" \") : undefined;\n return out;\n }\n if (values[i] === undefined || values[i] === \"\") throw missing(i, name);\n out[name] = values[i];\n }\n noMoreThan(names.length, values, command.usage);\n return out;\n}\n\n/** Words past a usage's arguments are refused, never dropped: `profile use my bot` would select `my`. */\nexport function noMoreThan(count: number, values: readonly string[], usage: string): void {\n if (values.length > count) throw new CliError(\"usage\", `Too many arguments: ghostly ${usage}`);\n}\n","import { spawn } from \"node:child_process\";\nimport { accessSync, constants, existsSync, readFileSync, renameSync, rmSync, statSync, writeFileSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\nimport { CONTACT_KEY } from \"./apiKit\";\nimport { connectDaemon, type DaemonAddress, type DaemonClient } from \"./client\";\nimport { CliError, localFileError } from \"./errors\";\nimport type { GhostlyEvent } from \"./events\";\nimport { turnRef } from \"./turnRefs\";\n\n/**\n * What `ghostly listen` does with each event: print it as a JSON line, run a command with it on stdin, or POST it to\n * a local bridge. Events are handled one at a time, in order; a cursor file acknowledges each one handled, so a\n * restarted listener resumes after the last.\n */\nexport interface ListenOptions {\n types: string[];\n exec?: string;\n webhook?: string;\n cursor?: string;\n print: boolean;\n /** `false` (as `stream.write` says it): the output wants a drain, and the next event waits for `drained`. */\n write: (line: string) => unknown;\n /** Resolves once the output takes more (its 'drain'), or is gone. */\n drained?: () => Promise<void>;\n /** `--from` and `--group`: events of anyone else stop here (they stay in the chat). */\n allow?: Allowlist;\n /** `--turns`: only agent turns, as `agent.turn` events. */\n turns?: boolean;\n /** The first wait before a webhook is tried again (500 ms), doubled each time up to a minute. */\n retryMs?: number;\n}\n\n/**\n * Who `listen` passes on, checked before any hook or output: chats by id (a contact key is matched to its chat as\n * events come, so a chat made after the start counts too), groups by id. An event of a chat or group not on it is\n * dropped; one that names neither (`daemon.started`, `events.gap`, `identity.approval`) is this profile's own and\n * passes.\n */\nexport class Allowlist {\n private readonly peers = new Map<string, string>();\n\n /** `peerOf`: a chat's contact key (null when it has none yet, or the chat is gone). */\n constructor(private readonly chats: ReadonlySet<string>, private readonly keys: ReadonlySet<string>, private readonly groups: ReadonlySet<string>, private readonly peerOf: (chat: string) => Promise<string | null>) {}\n\n async allows(event: GhostlyEvent): Promise<boolean> {\n if (\"group\" in event) return typeof event.group === \"string\" && this.groups.has(event.group);\n if (!(\"chat\" in event)) return true;\n const chat = event.chat;\n if (typeof chat !== \"string\") return false;\n if (this.chats.has(chat)) return true;\n if (!this.keys.size) return false;\n // Kept once known: a chat's contact key does not change. One not paired yet is asked again next time.\n let key = this.peers.get(chat);\n if (!key) { key = (await this.peerOf(chat).catch(() => null)) || undefined; if (key) this.peers.set(chat, key); }\n return !!key && this.keys.has(key);\n }\n}\n\n/**\n * `--from` and `--group` as ids, resolved once at start: a contact key as that key (whatever any chat is named), else a\n * chat by id, prefix or name (`findChat`); a group by id, prefix or name. A name that later changes (or a contact who\n * renames themselves) moves nothing.\n */\nexport async function allowlist(from: readonly string[], groups: readonly string[], call: (method: string, params: Record<string, unknown>) => Promise<unknown>, peerOf: (chat: string) => Promise<string | null>): Promise<Allowlist> {\n const chats = new Set<string>(), keys = new Set<string>(), groupIds = new Set<string>();\n for (const ref of from) {\n if (CONTACT_KEY.test(ref)) keys.add(ref);\n else chats.add(((await call(\"chat.get\", { chat: ref })) as { id: string }).id);\n }\n for (const ref of groups) groupIds.add(((await call(\"group.get\", { group: ref })) as { id: string }).id);\n return new Allowlist(chats, keys, groupIds, peerOf);\n}\n\n/**\n * One agent turn (docs/CLI.md § Agent turns): a message a contact sent in a chat, or a group message that mentions\n * this profile. What the sender controls (the text, their name, a quoted snippet, a file's name, the id their message\n * is stored under) is under `untrusted` and nowhere else: an agent reads it as data, never as its instructions. `seq` is\n * the source event's, so `--cursor` and `--since` work as for any event; `id` is stable for the message (dedupe on it).\n */\nexport interface AgentTurn extends GhostlyEvent {\n type: \"agent.turn\";\n source: \"message.received\" | \"group.message\" | \"group.mentioned\";\n chat?: string;\n group?: string;\n /** A group's author (their key). */\n member?: string;\n /** What `send --reply` (or `group send --reply`) takes to answer it: an id made here (`turnRef`), never the sender's. */\n messageId: string;\n timestamp: number;\n /**\n * The message pressed a button of a question this profile sent (WISP 406 · Message Buttons), as this side's engine\n * matched it: the question's id, the button's id and its label, all this profile's own words.\n */\n press?: { messageId: string; button: string; label: string; inferred?: true };\n untrusted: { text: string; name: string | null; messageId: string; replyTo?: { id: string; snippet: string }; file?: { id: string; name: string; size: number; mime: string; voice: boolean } };\n}\n\ninterface TurnMessage { id: string; text: string; timestamp: number; nick: string | null; member?: string; mentioned?: boolean; replyTo?: { id: string; snippet: string }; press?: AgentTurn[\"press\"]; file?: { id: string; name: string; size: number; mime: string; voice?: unknown } }\n\n/** The turn an event starts, or null: only a contact's message, and a group message that mentions this profile. */\nexport function toTurn(event: GhostlyEvent): AgentTurn | null {\n const message = event.message as TurnMessage | undefined;\n if (!message || typeof message.text !== \"string\") return null;\n if (event.type === \"message.received\" && typeof event.chat === \"string\") return turn(event, \"message.received\", { chat: event.chat }, message);\n if (event.type === \"group.message\" && typeof event.group === \"string\" && message.mentioned) return turn(event, \"group.message\", { group: event.group, ...(message.member ? { member: message.member } : {}) }, message);\n // A mention learned after its message was reported (its `group.message` named nobody): the turn it did not start then.\n if (event.type === \"group.mentioned\" && typeof event.group === \"string\" && message.mentioned) return turn(event, \"group.mentioned\", { group: event.group, ...(message.member ? { member: message.member } : {}) }, message);\n return null;\n}\n\nfunction turn(event: GhostlyEvent, source: AgentTurn[\"source\"], where: Pick<AgentTurn, \"chat\" | \"group\" | \"member\">, message: TurnMessage): AgentTurn {\n const file = message.file;\n // The source event's id ends in the stored id, the sender's: this one is made of the same parts with the id made here.\n const place = where.chat ?? where.group ?? \"\", messageId = turnRef(place, message.id);\n return {\n seq: event.seq, id: `agent.turn:${source}:${place}:${messageId}`, type: \"agent.turn\", at: event.at, source, ...where, messageId, timestamp: message.timestamp,\n ...(message.press ? { press: message.press } : {}),\n untrusted: {\n text: message.text, name: message.nick ?? null, messageId: message.id,\n ...(message.replyTo ? { replyTo: { id: message.replyTo.id, snippet: message.replyTo.snippet } } : {}),\n ...(file ? { file: { id: file.id, name: file.name, size: file.size, mime: file.mime, voice: !!file.voice } } : {}),\n },\n };\n}\n\n/** Only loopback: events carry message text, and a webhook is a local bridge (WISP 1100 § Security). */\nexport function checkWebhook(url: string): URL {\n let parsed: URL;\n try { parsed = new URL(url); } catch { throw new CliError(\"usage\", `Not a URL: ${url}`); }\n if (![\"http:\", \"https:\"].includes(parsed.protocol)) throw new CliError(\"usage\", \"The webhook must be http:// or https://\");\n if (![\"127.0.0.1\", \"localhost\", \"[::1]\"].includes(parsed.hostname)) throw new CliError(\"usage\", \"The webhook must be on this machine (127.0.0.1, localhost or [::1])\");\n return parsed;\n}\n\nexport function readCursor(path: string | undefined): number | undefined {\n if (!path || !existsSync(path)) return undefined;\n let text: string;\n try { text = readFileSync(path, \"utf8\"); } catch (error) { throw localFileError(error, path) ?? error; }\n const value = Number(text.trim());\n return Number.isInteger(value) && value >= 0 ? value : undefined;\n}\n\n/**\n * Whether a cursor can be kept at `path`, asked before anything starts: its folder is there and takes a file. Before, a\n * folder that was not there was found at the first event: the listener ran, said \"event N failed: ENOENT\" for each one\n * and never wrote the cursor, so the next start began at the journal's end and skipped what came while it was down.\n * Throws what the file system says (`asCliError` names the path and the code: not_found, refused).\n */\nexport function checkCursor(path: string | undefined): void {\n if (!path) return;\n const folder = dirname(resolve(path));\n if (!statSync(folder).isDirectory()) throw new CliError(\"not_found\", `No such file or folder: ${folder}`);\n accessSync(folder, constants.W_OK | constants.X_OK);\n}\n\nfunction writeCursor(path: string, seq: number): void {\n // A new file each time (`wx`): a link left where the temporary file goes is removed, never written through.\n rmSync(path + \".tmp\", { force: true });\n writeFileSync(path + \".tmp\", String(seq) + \"\\n\", { mode: 0o600, flag: \"wx\" });\n renameSync(path + \".tmp\", path);\n}\n\n/**\n * `--type`: one type (`message.received`, exactly: `group.message` is not its `group.message.edited`), or a family, a\n * word with no \".\" (`message`, `chat`) or one ending in \".\" or \"*\" (`group.typing.`). Before, a family needed its \".\" and\n * `--type chat` let nothing through. A family is whole words: `message` is not `messages.x`.\n */\nexport function matches(event: GhostlyEvent, types: readonly string[]): boolean {\n if (!types.length) return true;\n return types.some((type) => {\n if (type === \"*\") return true;\n const family = /[.*]$/.test(type) ? type.replace(/\\.?\\*$/, \"\").replace(/\\.$/, \"\") : type.includes(\".\") ? null : type;\n return event.type === type || (family !== null && event.type.startsWith(family + \".\"));\n });\n}\n\n/**\n * Every event type a daemon of this version emits (events.ts, appEvents.ts, holds.ts, identities.ts, calls/manager.ts,\n * main.ts) and `--turns`' own. A test reads them back from the source: a type added there and not here fails it.\n */\nexport const EVENT_TYPES: readonly string[] = [\n \"agent.turn\",\n \"app.closed\", \"app.message\", \"app.opened\",\n \"button.pressed\",\n \"call.connected\", \"call.ended\", \"call.incoming\", \"call.outgoing\", \"call.resumed\", \"call.stalled\",\n \"chat.announced\", \"chat.connection\", \"chat.created\", \"chat.held\", \"chat.joined\", \"chat.pairing\", \"chat.pinned\", \"chat.released\", \"chat.removed\", \"chat.renamed\",\n \"daemon.started\",\n \"events.gap\",\n \"file.done\", \"file.failed\", \"file.offered\", \"file.stage\",\n \"group.created\", \"group.deleted\", \"group.event\", \"group.members\", \"group.mentioned\", \"group.message\", \"group.message.edited\", \"group.pinned\", \"group.reaction\",\n \"group.removed\", \"group.sent\", \"group.status\", \"group.typing.started\", \"group.typing.stopped\",\n \"identity.approval\", \"identity.progress\", \"identity.received\", \"identity.status\",\n \"message.deleted\", \"message.delivery\", \"message.edited\", \"message.reaction\", \"message.received\", \"message.sent\",\n \"payment.created\", \"payment.updated\",\n \"typing.started\", \"typing.stopped\",\n];\n\n/** The families, the first word of each type: what a `--type` must start with. */\nexport const EVENT_FAMILIES: readonly string[] = [...new Set(EVENT_TYPES.map((type) => type.split(\".\")[0]))];\n\n/**\n * Checks each `--type` before anything starts. Before, `--type bogus` (or a typo such as `message.recieved`) was taken\n * and the listener stayed silent for good. A first word that is no family is a usage error naming them; a type, or a\n * family below the first word, that no event has is said on stderr (`warn`) and kept: a newer daemon may emit it.\n */\nexport function checkTypes(types: readonly string[], warn: (line: string) => void): void {\n for (const type of types) {\n if (type === \"*\") continue;\n const family = type.split(/[.*]/)[0];\n if (!EVENT_FAMILIES.includes(family)) throw new CliError(\"usage\", `No event is of type ${type}: --type takes a type, or a family (${EVENT_FAMILIES.join(\", \")})`);\n if (!EVENT_TYPES.some((known) => matches({ seq: 0, id: \"\", type: known, at: 0 }, [type]))) warn(`ghostly: no event is of type ${type}; the ${family} family has ${EVENT_TYPES.filter((known) => known.startsWith(family + \".\")).join(\", \")}`);\n }\n}\n\n/** The environment a hook runs in: this one's, less the backup passphrase (a hook, and what it runs, never needs it). */\nexport function hookEnv(env: NodeJS.ProcessEnv): NodeJS.ProcessEnv {\n const rest = { ...env };\n delete rest.GHOSTLY_BACKUP_PASSPHRASE;\n return rest;\n}\n\n/** Runs `command` through the shell with the event on stdin (never in its arguments); resolves with its exit code. */\nfunction runExec(command: string, event: GhostlyEvent): Promise<number> {\n return new Promise((resolve) => {\n const child = spawn(command, {\n shell: true,\n stdio: [\"pipe\", \"inherit\", \"inherit\"],\n env: { ...hookEnv(process.env), GHOSTLY_EVENT_TYPE: event.type, GHOSTLY_EVENT_ID: event.id, GHOSTLY_EVENT_SEQ: String(event.seq) },\n });\n child.on(\"error\", () => resolve(127));\n child.on(\"close\", (code) => resolve(code ?? 1));\n child.stdin.on(\"error\", () => {});\n child.stdin.end(JSON.stringify(event) + \"\\n\");\n });\n}\n\n/** The longest wait between two tries of a webhook that is not answering. */\nconst RETRY_MAX_MS = 60_000;\n\n/**\n * Posts one event; resolves true once the bridge took it, false when it refused it (a 4xx or a redirect, three times).\n * A bridge that is not there (refused connection, timeout, 5xx, 408, 429) has not handled the event: it is tried again,\n * waiting up to a minute between tries, for as long as it takes, so the cursor never moves past it. Before, three tries\n * in 3.5 s and the cursor moved on: a bridge restarting for longer lost every event of the time it was down, for good.\n */\nasync function post(url: URL, event: GhostlyEvent, retryMs: number): Promise<boolean> {\n let wait = retryMs, holding = false;\n for (let attempt = 0; ; attempt++) {\n let down = true;\n try {\n // A redirect is not followed: it would post the event to wherever it points, off this machine too.\n const response = await fetch(url, { method: \"POST\", redirect: \"manual\", headers: { \"content-type\": \"application/json\", \"x-ghostly-event\": event.type, \"x-ghostly-seq\": String(event.seq) }, body: JSON.stringify(event), signal: AbortSignal.timeout(10_000) });\n void response.body?.cancel().catch(() => {});\n if (response.ok) {\n if (holding) process.stderr.write(`ghostly: the webhook at ${url.href} answers again: event ${event.seq} taken\\n`);\n return true;\n }\n down = response.status >= 500 || response.status === 408 || response.status === 429;\n } catch { /* not there: tried again */ }\n if (!down && attempt >= 2) return false;\n if (down && attempt >= 2 && !holding) {\n holding = true;\n process.stderr.write(`ghostly: the webhook at ${url.href} is not answering: holding event ${event.seq} (${event.type}) until it does\\n`);\n }\n await new Promise((resolve) => setTimeout(resolve, wait));\n wait = Math.min(wait * 2, RETRY_MAX_MS);\n }\n}\n\n/** Events given to a handler and not handled yet: what `listen` holds in memory. */\nexport interface EventHandler {\n (event: GhostlyEvent): void;\n /** How many events are given and not handled yet. */\n behind(): number;\n /** Resolves when every event given is handled. */\n idle(): Promise<void>;\n}\n\n/**\n * A handler that takes events in order, one at a time. A step that throws (the output closed, the allowlist's lookup,\n * the cursor's disk) is said on stderr and passed: the cursor moves on and the next event is handled.\n */\nexport function eventHandler(options: ListenOptions): EventHandler {\n const webhook = options.webhook ? checkWebhook(options.webhook) : null;\n let chain = Promise.resolve();\n let behind = 0;\n const handle = (event: GhostlyEvent) => {\n const seq = event.seq, type = event.type;\n behind++;\n chain = chain.then(async () => {\n const skip = () => { if (options.cursor) writeCursor(options.cursor, event.seq); };\n if (!matches(event, options.types)) return skip();\n if (options.allow && !(await options.allow.allows(event))) return skip();\n if (options.turns) {\n const next = toTurn(event);\n if (!next) return skip();\n event = next;\n }\n const full = options.print && options.write(JSON.stringify(event)) === false;\n if (options.exec) {\n const code = await runExec(options.exec, event);\n if (code !== 0) process.stderr.write(`ghostly: --exec exited ${code} on event ${event.seq} (${event.type})\\n`);\n }\n if (webhook && !(await post(webhook, event, options.retryMs ?? 500))) process.stderr.write(`ghostly: the webhook did not take event ${event.seq} (${event.type})\\n`);\n // An output whose reader stopped holds the next event here, not one more line in its buffer per event.\n if (full) await options.drained?.();\n // A failed hook (an --exec exiting non-zero, an event the webhook refused) still moves the cursor: one poisonous\n // event must not stop the stream. The failure is on stderr. A webhook not answering never gets here (`post`).\n if (options.cursor) writeCursor(options.cursor, event.seq);\n }).catch((error: unknown) => {\n try {\n process.stderr.write(`ghostly: event ${seq} (${type}) failed: ${error instanceof Error ? error.message : String(error)}\\n`);\n if (options.cursor) writeCursor(options.cursor, seq);\n } catch { /* the next event moves the cursor */ }\n }).finally(() => { behind--; });\n };\n return Object.assign(handle, { behind: () => behind, idle: () => chain });\n}\n\n/** Events a listener takes ahead of its output and hooks before it stops taking more (a few MB at most). */\nexport const MAX_BEHIND = 1_000;\n\n/**\n * Bounds what a listener holds when its output or hooks fall behind (a stdout reader that hung, a slow --exec): past\n * `MAX_BEHIND` events not handled it stops taking events (`pause`: the subscription stops reading) and drops what still\n * arrives; once every event taken is handled, `resume` opens it again after the last one taken. The daemon's journal\n * keeps what came meanwhile (and says `events.gap` past what it keeps), so a consumer that hangs for a day does not\n * grow the listener by the day's traffic.\n */\nexport class Feed {\n private held = false;\n\n /** `since`: the last event taken, where a new subscription starts. */\n constructor(private readonly handle: EventHandler, public since: number | undefined, private readonly pause: () => void, private readonly resume: (since: number | undefined) => void) {}\n\n get paused(): boolean { return this.held; }\n\n readonly take = (event: GhostlyEvent): void => {\n if (this.held) return;\n this.since = event.seq;\n this.handle(event);\n if (this.handle.behind() < MAX_BEHIND) return;\n this.held = true;\n this.pause();\n void this.handle.idle().then(() => { this.held = false; this.resume(this.since); });\n };\n}\n\n/** How long a feed that fell behind keeps its connection to the daemon open, unread, while its hooks take no event (`followDaemon`). */\nexport const PAUSE_HOLD_MS = 60_000;\n\n/**\n * Follows a daemon's events into `handle` until `close`; a daemon that restarts is picked up again after the last event\n * seen. A feed that falls behind stops reading the connection, not closes it: what the daemon sent meanwhile (a replay\n * written whole) is read on resume, so a catch-up reads the journal once, not once per pause. A connection the daemon\n * ended meanwhile (past what it lets a client leave unread) is opened again after the last event taken.\n * A feed whose hooks take no event for `holdMs` (`PAUSE_HOLD_MS`: a hook that hung) ends the connection, as a full one\n * does, so the daemon does not keep a replay and what came live for it while it hangs; resume opens it again after the\n * last event taken.\n * `subscribed`: the first subscription's answer (a journal that cannot be replayed rejects it).\n */\nexport function followDaemon(address: DaemonAddress, client: DaemonClient, handle: EventHandler, since: number | undefined, holdMs = PAUSE_HOLD_MS): { subscribed: Promise<unknown>; close(): void } {\n let current: DaemonClient | null = client;\n let holding: ReturnType<typeof setTimeout> | undefined;\n const reconnect = (wait: number) => void (async () => {\n while (!current && !feed.paused) {\n await new Promise((resolve) => setTimeout(resolve, wait));\n wait = 1000;\n if (current || feed.paused) return;\n const next = await connectDaemon(address, 1000);\n if (next) { current = next; await follow(next).catch(() => { if (current === next) current = null; }); }\n }\n })();\n // A hook still taking events (a slow --exec) keeps the connection; one that took none for `holdMs` lets it go.\n const hold = (behind: number) => {\n holding = setTimeout(() => {\n if (handle.behind() < behind) return hold(handle.behind());\n const c = current; current = null; c?.destroy();\n }, holdMs);\n };\n const feed = new Feed(handle, since, () => {\n current?.pause();\n hold(handle.behind());\n }, () => {\n clearTimeout(holding);\n if (current) current.resume(); else reconnect(0);\n });\n const follow = (c: DaemonClient) => c.subscribe(feed.since, feed.take, () => {\n if (current !== c) return;\n current = null;\n reconnect(1000);\n });\n return { subscribed: follow(client), close: () => { clearTimeout(holding); current?.close(); } };\n}\n","import { CliError } from \"./errors\";\n\n/**\n * Secrets a command takes (a Cashu token, an API key, a card's form) come on stdin: on the command line they show in\n * `ps` to every user of the machine while the command runs, and stay in the shell's history. Still taken there, with\n * a warning. Fills `params` in place; the warning to print on stderr, if any. `tty`: stdin is a terminal, where a\n * read would wait on the keyboard without a word.\n */\nconst JOINS: Record<string, { param: string; arg: string; command: string; what: string }> = {\n \"group.join\": { param: \"link\", arg: \"<link>\", command: \"group join\", what: \"A group's link\" },\n \"invite.join\": { param: \"invite\", arg: \"<invite-or-link>\", command: \"invite join\", what: \"An invite\" },\n};\n\n/**\n * A join given no invite reads stdin, but a pipe nobody writes or closes (what Node's exec and most harnesses give a\n * child) would hold it for ever without a word: a note once nothing has come for a while, the usage error once nothing\n * has come at all. A producer that started writing is waited for to the end; `-` asked for stdin and waits as long.\n */\nexport const STDIN_NOTE_MS = 2_000;\nexport const STDIN_GIVE_UP_MS = 60_000;\n\n/** `read`'s `onData`: called at the first chunk, once something is coming. */\nexport type StdinRead = (onData?: () => void) => Promise<string>;\n\nexport async function secretsFromStdin(method: string, params: Record<string, unknown>, read: StdinRead, tty = false, note: (text: string) => void = () => {}): Promise<string | undefined> {\n const warning = (what: string) => `${what} on the command line shows in ps and the shell's history: give it on stdin instead`;\n if (method === \"wallet.redeem\") {\n if (params.token !== undefined) return warning(\"A token\");\n const missing = () => new CliError(\"usage\", \"Missing <cashu-token>: give it as an argument or on stdin (… | ghostly wallet redeem)\");\n if (tty) throw missing();\n const token = (await read()).trim();\n if (!token) throw missing();\n params.token = token;\n return undefined;\n }\n // A group's link and a chat's invite are secrets everywhere else (hidden in `group show`, in no event): the same here.\n const join = JOINS[method];\n if (join) {\n if (params[join.param] !== undefined && params[join.param] !== \"-\") return warning(join.what);\n const missing = () => new CliError(\"usage\", `Missing ${join.arg}: give it on stdin (… | ghostly ${join.command}) or as an argument`);\n if (tty) throw missing();\n const value = (params[join.param] === \"-\" ? await read() : await readUnasked(read, note, join)).trim();\n if (!value) throw missing();\n params[join.param] = value;\n return undefined;\n }\n if (method === \"wallet.create\") {\n // A form's fields are often plain (a network, a script type): the API key here, the secret fields by\n // `secretValuesWarning` once the source's form is known.\n const onLine = params.apiKey !== undefined;\n if (params.stdin === true) {\n const values = { ...(params.values as Record<string, string> | undefined) };\n for (const line of (await read()).split(/\\r?\\n/)) {\n if (!line.trim()) continue;\n const eq = line.indexOf(\"=\");\n if (eq < 1) throw new CliError(\"usage\", \"--stdin takes name=value lines (api-key=… for the API key)\");\n const name = line.slice(0, eq).trim(), value = line.slice(eq + 1);\n if (name === \"api-key\") params.apiKey = value;\n else values[name] = value;\n }\n if (Object.keys(values).length) params.values = values;\n }\n delete params.stdin;\n return onLine ? warning(\"An API key\") : undefined;\n }\n return undefined;\n}\n\nasync function readUnasked(read: StdinRead, note: (text: string) => void, join: { arg: string; command: string; what: string }): Promise<string> {\n let noteTimer: ReturnType<typeof setTimeout> | undefined, giveUpTimer: ReturnType<typeof setTimeout> | undefined;\n const stop = () => { clearTimeout(noteTimer); clearTimeout(giveUpTimer); };\n const nothingCame = new Promise<never>((_, reject) => {\n noteTimer = setTimeout(() => note(`Waiting for ${join.what.toLowerCase()} on stdin (… | ghostly ${join.command}): give it there or as an argument`), STDIN_NOTE_MS);\n giveUpTimer = setTimeout(() => reject(new CliError(\"usage\", `Missing ${join.arg}: nothing came on stdin in ${STDIN_GIVE_UP_MS / 1000} s; give it there (… | ghostly ${join.command}) or as an argument`)), STDIN_GIVE_UP_MS);\n });\n try { return await Promise.race([read(stop), nothingCame]); }\n finally { stop(); }\n}\n\n/**\n * `wallet create --value`: the names given on the command line that the chosen source's form marks `kind: \"secret\"`\n * (an NWC URI, a macaroon, a rune, an RPC password), as a warning. `list`: a `wallet.list` answer, where the forms are.\n */\nexport function secretValuesWarning(list: unknown, type: unknown, provider: unknown, names: string[]): string | undefined {\n if (!names.length) return undefined;\n const id = provider ?? (type === \"bitcoin\" ? \"bdk\" : undefined);\n const offers = (list as { offers?: { type?: string; providers?: { id: string; fields?: { name: string; kind?: string }[] }[] }[] } | undefined)?.offers ?? [];\n const fields = offers.find((o) => o.type === type && o.providers)?.providers?.find((p) => p.id === id)?.fields ?? [];\n const secret = names.filter((name) => fields.some((f) => f.name === name && f.kind === \"secret\"));\n if (!secret.length) return undefined;\n return `${secret.map((name) => `--value ${name}`).join(\", \")} on the command line shows in ps and the shell's history: give ${secret.length > 1 ? \"them\" : \"it\"} on stdin instead (--stdin, name=value lines)`;\n}\n","import { spawn } from \"node:child_process\";\nimport { connect } from \"node:net\";\nimport { openSync, readFileSync, rmSync } from \"node:fs\";\nimport packageJson from \"../package.json\" with { type: \"json\" };\nimport { GLOBAL_OPTIONS, globalOption, liftGlobals, parseArgs, type OptionSpec, type Parsed } from \"./args\";\nimport { connectDaemon, isNotTheDaemon, type DaemonClient } from \"./client\";\nimport { COMMANDS, idSlot, noMoreThan, positionals, TEXT_COMMANDS } from \"./commands\";\nimport { here } from \"./commands/shared\";\nimport { ENGINE_METHODS, ENGINE_PARAMS, ENGINE_READS, READ_PARAMS, SECRET_RESULTS } from \"./engineMethods\";\nimport { asCliError, CliError, EXIT, localFileError } from \"./errors\";\nimport type { GhostlyEvent } from \"./events\";\nimport type { Host } from \"./host\";\nimport type { RuntimeOptions } from \"./runtime/engine\";\nimport { allowlist, checkCursor, checkTypes, checkWebhook, eventHandler, Feed, followDaemon, readCursor } from \"./listen\";\nimport { format } from \"node:util\";\nimport { secretsFromStdin, secretValuesWarning } from \"./secretInput\";\nimport {\n checkProfileName, checkShownName, createProfile, currentProfile, DEFAULT_PROFILE, ghostlyHome, listProfiles, lockOwner, profileExists, profilePaths, selectProfile,\n type ProfilePaths,\n} from \"./profiles\";\n\nconst VERSION = packageJson.version;\n\n/**\n * The engine's modules (the API, the host, the backup, the buttons) are loaded only where a command needs them here: a\n * command a running daemon answers loads none of them, and starts about as fast as Node does. Statically imported, they\n * cost every command ~100 ms before its socket was opened.\n */\nconst engineApi = () => import(\"./api\");\nconst engineHost = () => import(\"./host\");\n\ninterface Globals { home: string; profile: string; paths: ProfilePaths; pretty: boolean }\n\nlet pretty = false;\nfunction print(value: unknown): void {\n process.stdout.write(JSON.stringify(value, null, pretty ? 2 : undefined) + \"\\n\");\n}\n\n/** Done, with something to know (a voice note sent without its waveform): said on stderr, the JSON stays the answer. */\nfunction printAnswer(result: Record<string, unknown>): void {\n if (typeof result?.warning === \"string\") {\n process.stderr.write(`ghostly: ${result.warning}\\n`);\n delete result.warning;\n }\n print(result);\n}\n\nfunction globals(parsed: Parsed): Globals {\n const home = ghostlyHome(parsed.options.home as string | undefined);\n const profile = currentProfile(home, parsed.options.profile as string | undefined);\n return { home, profile, paths: profilePaths(home, profile), pretty: parsed.options.pretty === true };\n}\n\n/** The profile must exist; `default` is made on first use, any other with `profile create`. */\nfunction requireProfile(g: Globals): void {\n if (profileExists(g.home, g.profile)) return;\n if (g.profile === DEFAULT_PROFILE) { createProfile(g.home, g.profile); return; }\n throw noProfile(g);\n}\n\nfunction noProfile(g: Globals): CliError {\n return new CliError(\"not_found\", `No profile ${g.profile}: make it with \\`ghostly profile create ${g.profile}\\``);\n}\n\n/** For a command that only reads: a mistyped profile is named as one, and `default` is not made by asking about it. */\nfunction knownProfile(g: Globals): void {\n if (g.profile !== DEFAULT_PROFILE && !profileExists(g.home, g.profile)) throw noProfile(g);\n}\n\n/** A way to call the API: the daemon's socket when one runs the profile, else the profile in this process. */\ninterface Session { mode: \"daemon\" | \"one-shot\"; call(method: string, params?: unknown): Promise<unknown>; close(): Promise<void> }\n\n/** Said on stderr when the daemon runs another release than this command (it started before an upgrade). */\nexport function versionWarning(daemon: unknown, cli: string): string | null {\n if (typeof daemon !== \"string\" || daemon === cli) return null;\n return `ghostly: the daemon runs ${daemon} and this command is ${cli}: \\`ghostly daemon restart\\` runs the new code`;\n}\n\n/**\n * Never fails, and has no deadline of its own: a daemon that does not answer is the command's own call to find out,\n * at the command's deadline, which closes the connection and ends this check with it. A deadline here ended every\n * command on a wedged daemon at 15 s with `unavailable` (\"The daemon went away\"), whatever its own `--timeout` said.\n */\nasync function warnVersion(client: DaemonClient): Promise<void> {\n const status = await client.call(\"status\").catch(() => null) as { version?: unknown } | null;\n const warning = versionWarning(status?.version, VERSION);\n if (warning) process.stderr.write(warning + \"\\n\");\n}\n\n/**\n * A command about one 1:1 chat: a one-shot for it leaves the groups' sessions unstarted. A fresh process starts an edge\n * per group member, and their first polls spent the relays' 30 requests a minute in seconds: the chat's message then\n * waited for the next minute (60 s and more instead of 3 to 5).\n */\nexport function chatOnly(method: string, params: Record<string, unknown>): boolean {\n // A status card's `chat` may name a group as well (WISP 405 · Status Cards): its sessions must start.\n if (method.startsWith(\"task.\") || method.startsWith(\"routine.\") || method.startsWith(\"button.\")) return false;\n // A usage report to every 1:1 chat (`--all`) needs no group; one to a named chat may name a group.\n if (method === \"usage.send\") return params.all === true;\n return method.startsWith(\"chat.\") || (params.chat !== undefined && params.group === undefined && !method.startsWith(\"group.\"));\n}\n\n/**\n * Calls that only read what the profile stores: a one-shot for one opens it offline (`RuntimeOptions.offline`).\n * Opened online, `status` or `chat list` started every chat, put the profile's records on the relays again and waited\n * for its leave packet to be taken: 0.25 s became 3.3 s with a relay that takes 1.5 s, and 10 s with one that does not\n * answer, and each read spent ~5 relay requests per chat of the relays' per-address budget.\n */\nconst READS: ReadonlySet<string> = new Set([\n \"status\", \"profile.get\", \"settings.get\", \"events.replay\", \"chat.list\", \"chat.get\", \"chat.history\", \"chat.details\",\n \"group.list\", \"group.get\", \"group.history\", \"file.list\", \"wallet.list\", \"wallet.history\", \"payment.list\", \"identity.list\", \"identity.providers\",\n \"identity.contact\", \"service.list\", \"service.peer\", \"call.list\", \"app.served\", \"x401.credential.list\",\n]);\n\n/** Whether a one-shot for this call opens the profile offline; test/readOnlyCommands.test.ts names every table command. */\nexport function readOnly(method: string, params: Record<string, unknown>): boolean {\n if (method === \"engine.call\") return typeof params.method === \"string\" && ENGINE_READS.includes(params.method);\n // `call auto` with no on|off says what auto-answer is.\n if (method === \"call.auto\") return params.on === undefined;\n return READS.has(method);\n}\n\n/**\n * Calls whose change stays on this device: a chat's name here, a chat removed (nothing goes to the contact), auto-answer\n * (calls.json), a proof dropped, a web app added (shared with no one yet), an x401 key or credential (WISP 3xx: never\n * shared with a contact). Opened online, each put the profile's records on the relays and waited for them (6 PUT + 4\n * GET, 3.3 s with a relay that takes 1.5 s), and the contacts' apps saw this device come online. `message delete` stays\n * online: it settles a file offer already on the DHT.\n */\nconst LOCAL_WRITES: ReadonlySet<string> = new Set([\n \"chat.rename\", \"chat.remove\", \"call.auto\", \"identity.cancel\", \"service.add\", \"x401.key.new\", \"x401.credential.add\", \"x401.credential.remove\",\n]);\n\n/** Settings of this device only: no contact and no relay hears of them (nick, avatar and the relays' do). */\nexport const LOCAL_SETTINGS: ReadonlySet<string> = new Set([\"sendTyping\", \"autoDownloads\", \"serveFiles\"]);\n\n/** Whether a one-shot for this call opens the profile offline: a read, or a change that stays on this device. */\nexport function offlineCall(method: string, params: Record<string, unknown>): boolean {\n return readOnly(method, params) || LOCAL_WRITES.has(method);\n}\n\n/** How long a daemon gets to answer before a command gives up: a read is in memory (15 s); a call that waits for the\n * contact carries its own `--timeout` (or the daemon's default for it), plus a margin; anything else may take as long\n * as it takes. */\nconst ANSWER_MS = 15_000;\nexport function answerWithin(method: string, params: Record<string, unknown>): number | undefined {\n // A `--timeout` outside the daemon's range (1 to 3600 s, 86 400 for `chat wait` and `file wait`) is refused by the\n // daemon at once (bad_request); the deadline only has to be a timer Node takes (-10 s fired at once, 1e12 after 1 ms).\n const waits = typeof params.timeout === \"number\" ? Math.min(Math.max(params.timeout, 1), 86_400) : waitsFor(method, params);\n if (waits !== undefined) return (waits + 10) * 1000;\n if (readOnly(method, params)) return ANSWER_MS;\n return undefined;\n}\n\n/**\n * The seconds a call without `--timeout` waits for the contact: the daemon's defaults (`num(params, \"timeout\", …)` in\n * api.ts, files.ts, buttons.ts and statusCards.ts), so that a bot's `chat wait` or `send --wait sent` on a daemon that\n * stopped answering ends when the wait would have. A call that does not wait is none.\n */\nfunction waitsFor(method: string, params: Record<string, unknown>): number | undefined {\n if (method === \"chat.wait\") return 60;\n if (method === \"file.wait\" || (method === \"file.save\" && params.wait === true)) return 300;\n // send, edit, forward, a button, a task or routine card: `--wait sent|confirmed|delivered`, 30 s each.\n if (typeof params.wait === \"string\" && params.wait !== \"none\") return 30;\n return undefined;\n}\n\nasync function session(g: Globals, options: RuntimeOptions): Promise<Session> {\n requireProfile(g);\n const client = await connectDaemon(g.paths);\n if (client) {\n // The version check goes on the same connection as the command, ahead of it, not before it, and with no deadline\n // of its own: a daemon that does not answer costs the command its own deadline and nothing else (a read gave up\n // after 30 s, not 15; then every command gave up at the check's 15 s, whatever its own). `close` waits for the\n // check's answer: a daemon that answered the command answered the check sent before it.\n const warned = warnVersion(client);\n return { mode: \"daemon\", call: (m, p) => client.call(m, p, { timeoutMs: answerWithin(m, (p ?? {}) as Record<string, unknown>) }), close: async () => { await warned; client.close(); } };\n }\n const [{ openHost }, { callApi }] = await Promise.all([engineHost(), engineApi()]);\n const host = await openHost(g.paths, \"one-shot\", VERSION, options);\n return { mode: \"one-shot\", call: (m, p) => callApi(host.ctx, m, p ?? {}), close: () => host.close() };\n}\n\n/**\n * How a one-shot opens the profile: `deferGroups` when the command is about one 1:1 chat (`chatOnly`) and needs\n * nothing of the groups, `offline` when it only reads or changes only this device (`offlineCall`).\n */\nasync function withSession<T>(g: Globals, work: (s: Session) => Promise<T>, options: RuntimeOptions = {}): Promise<T> {\n const s = await session(g, options);\n try { return await work(s); } finally { await s.close(); }\n}\n\n/**\n * A one-shot join waits up to 60 s for the inviter. Its answer says whether the chat paired and at what stage it is; one\n * not paired yet comes with the next step, since nothing pairs once the command has left.\n */\nexport async function oneShotJoinWait(s: Pick<Session, \"call\">, result: Record<string, unknown>, label?: string): Promise<{ answer: Record<string, unknown>; note?: string }> {\n const view = await s.call(\"chat.wait\", { chat: result.chat, until: \"paired\", timeout: 60 }).then((v) => ({ paired: true, chat: v }), () => null)\n ?? await s.call(\"chat.get\", { chat: result.chat }).then((v) => ({ paired: false, chat: v }), () => ({ paired: false, chat: null }));\n const stage = (view.chat as { stage?: unknown } | null)?.stage ?? null;\n const answer = { ...result, paired: view.paired, stage };\n if (view.paired) return { answer };\n const ref = label?.trim() && !/\\s/.test(label.trim()) ? label.trim() : String(result.chat);\n return { answer, note: `Not paired yet: the inviter's app is offline. It pairs when both are online: keep this profile running (ghostly daemon --detach), then ghostly chat wait ${ref} --until paired` };\n}\n\nasync function readStdin(onData?: () => void): Promise<string> {\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) { onData?.(); chunks.push(chunk as Buffer); }\n return Buffer.concat(chunks).toString(\"utf8\");\n}\n\n// ---------- help ----------\n\nconst o = (type: OptionSpec[\"type\"], description: string): OptionSpec => ({ type, description });\n\n/** Commands with their own flow (main.ts), as help shows them. */\nconst SPECIAL: [usage: string, summary: string, options?: Record<string, OptionSpec>][] = [\n [\"profile create <name> [--use] [--name <shown name>]\", \"Make a profile (its own keys, chats and wallets)\", { use: o(\"boolean\", \"Make it the current profile\"), name: o(\"string\", \"The name contacts see\") }],\n [\"profile list\", \"Profiles, and which one is current\"],\n [\"profile use <name>\", \"Make a profile the current one\"],\n [\"profile show\", \"The name contacts see, and whether it is shared\"],\n [\"profile set [--name <name>] [--share-profile | --no-share-profile]\", \"Change the name contacts see\", { name: o(\"string\", \"The name contacts see\"), \"share-profile\": o(\"boolean\", \"Share the name and picture with contacts (--no-share-profile: do not)\") }],\n [\"profile backup --out <file> [--passphrase-file f | --no-passphrase] [--light]\", \"A backup of the profile, encrypted with a passphrase (from a file or GHOSTLY_BACKUP_PASSPHRASE); --no-passphrase makes one anyone can read\", { out: o(\"string\", \"The backup file to write\"), \"passphrase-file\": o(\"string\", \"The passphrase, from this file (else GHOSTLY_BACKUP_PASSPHRASE)\"), passphrase: { ...o(\"boolean\", \"Do not encrypt. The file then holds the profile's keys and wallet secrets in the clear\"), negatedOnly: true }, light: o(\"boolean\", \"Leave out files over 1 MB (voice messages over 4 MB); their messages stay\") }],\n [\"profile restore <file> <new profile> [--passphrase-file f] [--use]\", \"A backup into a new profile (a backup made with --no-passphrase needs none)\", { \"passphrase-file\": o(\"string\", \"The passphrase, from this file (else GHOSTLY_BACKUP_PASSPHRASE)\"), use: o(\"boolean\", \"Make it the current profile\") }],\n [\"daemon [--detach] [--timeout s]\", \"Keep the profile online (foreground; --detach runs it in the background)\", { detach: o(\"boolean\", \"Run in the background (log in the profile folder)\"), timeout: o(\"number\", \"Seconds --detach waits for it to start (default 60)\") }],\n [\"daemon status [--timeout s]\", \"Whether a daemon runs the profile, its version, and its socket (for the socket API)\", { timeout: o(\"number\", \"Seconds to wait for its answer (default 15)\") }],\n [\"daemon stop [--timeout s]\", \"Stop the profile's daemon\", { timeout: o(\"number\", \"Seconds to wait for it to stop (default 20)\") }],\n [\"daemon restart [--timeout s]\", \"Stop the profile's daemon and start it again in the background (after an upgrade: the new code)\", { timeout: o(\"number\", \"Seconds to wait for each step\") }],\n [\"listen [--since seq] [--cursor file] [--type t]... [--turns] [--from <chat|key>]... [--group <group>]... [--exec cmd] [--webhook url] [--print]\", \"Stream events as JSON lines (starts the profile here if no daemon runs it)\", {\n since: o(\"number\", \"Replay events after this seq first\"), cursor: o(\"string\", \"A file that keeps the last seq handled (read at start, written after each event)\"),\n type: o(\"list\", \"Only events of this type (message.received) or family (message, or group.typing.); repeat for more\"),\n turns: o(\"boolean\", \"Only agent turns: each message received, and each group message that mentions you, as one agent.turn event\"),\n from: o(\"list\", \"Only this chat's events (id, prefix, name or the contact's key; again for more)\"),\n group: o(\"list\", \"Only this group's events (again for more); with --from or --group, nobody else's event gets through\"),\n exec: o(\"string\", \"Run this command per event, the event as JSON on stdin\"),\n webhook: o(\"string\", \"POST each event to this URL\"), print: o(\"boolean\", \"Print events too when --exec or --webhook handles them\"),\n }],\n [\"settings get [--show-secret]\", \"The profile's settings\", { \"show-secret\": o(\"boolean\", \"Show credentials too\") }],\n [\"settings set <key> <json-value>\", \"Change one: relays, irohRelays, hyperdhtRelay, readRelays, iceServers, publicProfiles, online, shareProfile, sendTyping, autoDownloads, serveFiles, nick\"],\n [\"engine <method> [json-params | -] [--confirm-real] [--show-secret] [--yes] [--force]\", \"Any call of the app's engine, with its own parameters (engine --list --verbose names them)\", { \"confirm-real\": o(\"boolean\", \"Confirm a Mainnet (real money) spend\"), \"show-secret\": o(\"boolean\", \"Print a call's secrets\"), yes: o(\"boolean\", \"Confirm a call that deletes chats or groups\"), force: o(\"boolean\", \"Send a text that looks like a secret\") }],\n [\"engine --list [--verbose]\", \"The engine's calls\", { verbose: o(\"boolean\", \"With what each call takes: { linkId, label }, ? for an optional one\") }],\n [\"call pipe [<chat|call>]\", \"A call's audio on stdin/stdout: raw s16le mono PCM at the call's rate (e.g. with sox or ffmpeg)\"],\n [\"identity add <provider> [subject] [--signer id] [--field name=value]... [--days n]\", \"Make an identity proof (a tool's or a published one finishes with identity complete)\", {\n signer: o(\"string\", \"Which signer makes the proof (identity providers lists them)\"), field: o(\"list\", \"A field of the provider's form, name=value\"),\n days: o(\"number\", \"How long the proof holds\"), timeout: o(\"number\", \"Seconds to wait for an approval\"),\n }],\n [\"version\", \"This CLI's version (also ghostly --version)\"],\n];\n\nfunction help(): string {\n const rows: [string, string][] = [\n ...SPECIAL.slice(0, 7).map(([usage, summary]) => [usage, summary] as [string, string]),\n ...Object.values(COMMANDS).filter((c) => c.method !== \"events.replay\").map((c) => [c.usage, c.summary] as [string, string]),\n ...Object.values(TEXT_COMMANDS).map((c) => [c.usage, c.summary] as [string, string]),\n ...SPECIAL.slice(7).map(([usage, summary]) => [usage, summary] as [string, string]),\n [COMMANDS.events.usage, COMMANDS.events.summary],\n ];\n const width = 58;\n return [\n `ghostly ${VERSION}: Ghostly for bots and terminals, the app's own engine without a screen.`,\n \"\",\n \"Usage: ghostly <command> [options] (JSON on stdout; errors as {\\\"error\\\":{code,message}} with an exit code)\",\n \"\",\n ...rows.map(([usage, summary]) => ` ${usage.length > width ? usage + \"\\n \" + \" \".repeat(width) : usage.padEnd(width)} ${summary}`),\n \"\",\n \"Options for every command:\",\n ...Object.entries(GLOBAL_OPTIONS).map(([name, o]) => ` --${name}${o.short ? `, -${o.short}` : \"\"}`.padEnd(24) + o.description),\n \"\",\n \"A <chat> is its id, a unique prefix of it, or its name; a <group> the same. Exit codes: 0 done, 1 failed,\",\n \"2 usage, 3 not found, 4 timed out, 5 needs --force/--yes/--confirm-real.\",\n \"More: https://ghostly.tools/cli, or the README.md beside this CLI.\",\n ].join(\"\\n\");\n}\n\n/** What `ghostly help help` answers. */\nconst HELP_USAGE = [\n \"Usage: ghostly help [<command>...]\", \"\",\n \" Help for every command, or for one command or a group of them (also ghostly <command> --help)\", \"\",\n \"Options for every command: --profile, -p <name> --home <dir> --pretty --help, -h\",\n].join(\"\\n\");\n\n/** Every command's help row: usage, summary and, for the table and text commands, their options. */\nfunction helpRows(): { usage: string; summary: string; options?: Record<string, OptionSpec> }[] {\n return [\n ...SPECIAL.map(([usage, summary, options]) => ({ usage, summary, options })),\n ...Object.values(COMMANDS),\n ...Object.values(TEXT_COMMANDS),\n ];\n}\n\n/** The words that name a command in its usage line: up to the first argument or option. */\nfunction commandWords(usage: string): string[] {\n const words: string[] = [];\n for (const word of usage.split(\" \")) {\n if (!/^[a-z][a-z0-9-]*$/.test(word)) break;\n words.push(word);\n }\n return words;\n}\n\n/**\n * Help for one command (`ghostly help file send`, `ghostly file send --help`): its usage, what it does and its\n * options; for a group (`ghostly help file`), the group's commands.\n */\nexport function commandHelp(words: readonly string[]): string {\n // `help` is no command of the tables: its own usage, rather than \"Unknown command: help\".\n if (words[0] === \"help\") return HELP_USAGE;\n const named = (list: readonly string[]) => helpRows().filter((row) => { const own = commandWords(row.usage); return list.every((word, i) => own[i] === word); });\n // Arguments after the command's words (`ghostly send bob hi --help`) are not part of its name.\n const given = words;\n let rows = named(words);\n while (!rows.length && words.length > 1) rows = named(words = words.slice(0, -1));\n const asked = words.join(\" \");\n if (!rows.length) throw new CliError(\"usage\", `Unknown command: ${asked} (ghostly help)`);\n const exact = rows.filter((row) => commandWords(row.usage).join(\" \") === asked);\n // Words dropped down to a group, not a command (`help chat histroy`): a word the group does not take, as `chat histroy`\n // says, not the group's list with exit 0.\n if (!exact.length && words.length < given.length) throw unknownCommand(given[0], given[1], given[2]);\n const lines: string[] = [];\n // The command asked for first, also when others extend its words (`daemon`, then `daemon stop`…): before, `daemon`'s\n // own options were shown nowhere.\n for (const row of exact) {\n lines.push(`Usage: ghostly ${row.usage}`, \"\", ` ${row.summary}`);\n const options = Object.entries(row.options ?? {}).filter(([, o]) => o.description);\n if (options.length) {\n lines.push(\"\", \"Options:\");\n const labels = options.map(([name, o]) => ` --${o.negatedOnly ? \"no-\" : \"\"}${name}${o.type === \"boolean\" ? \"\" : ` <${o.type === \"number\" ? \"n\" : \"value\"}>`}`);\n // At least two spaces between an option and its text, however long the option.\n const width = Math.max(26, ...labels.map((label) => label.length + 2));\n options.forEach(([, o], i) => lines.push(labels[i].padEnd(width) + o.description));\n }\n // A text that starts with a dash goes after `--`, and so does everything else on the line.\n if (Object.values(TEXT_COMMANDS).includes(row as (typeof TEXT_COMMANDS)[string]))\n lines.push(\"\", \" -- ends the options: everything after it is the text, options included (\\\"-- -1 --wait sent\\\" sends\", \" all of it). Put options before --.\");\n lines.push(\"\");\n }\n const rest = rows.filter((row) => !exact.includes(row));\n if (rest.length) {\n const width = Math.min(58, Math.max(...rest.map((row) => row.usage.length)));\n const count = `${rest.length}${exact.length ? \" more\" : \"\"} command${rest.length === 1 ? \"\" : \"s\"}`;\n lines.push(`ghostly ${asked}: ${count} (ghostly help ${asked} <command> for one)`, \"\");\n for (const row of rest) lines.push(` ${row.usage.length > width ? row.usage + \"\\n \" + \" \".repeat(width) : row.usage.padEnd(width)} ${row.summary}`);\n lines.push(\"\");\n }\n lines.push(\"Options for every command: --profile, -p <name> --home <dir> --pretty --help, -h\");\n return lines.join(\"\\n\");\n}\n\n// ---------- commands with their own flow ----------\n\nasync function profileCommand(sub: string | undefined, argv: string[]): Promise<void> {\n const specs: Record<string, Record<string, OptionSpec>> = {\n create: { use: { type: \"boolean\", description: \"\" }, name: { type: \"string\", description: \"\" } },\n backup: { out: { type: \"string\", description: \"\" }, \"passphrase-file\": { type: \"string\", description: \"\" }, passphrase: { type: \"boolean\", description: \"\" }, light: { type: \"boolean\", description: \"\" } },\n restore: { \"passphrase-file\": { type: \"string\", description: \"\" }, use: { type: \"boolean\", description: \"\" } },\n set: { name: { type: \"string\", description: \"\" }, \"share-profile\": { type: \"boolean\", description: \"\" } },\n };\n const parsed = parseArgs(argv, specs[sub ?? \"\"] ?? {});\n const g = globals(parsed);\n pretty = g.pretty;\n switch (sub) {\n case \"create\": {\n const [name] = parsed.positionals;\n if (!name || parsed.positionals.length > 1) throw new CliError(\"usage\", \"ghostly profile create <name>\");\n // A command that fails changes nothing: the name is checked before the folder is made, and the profile is made\n // current only once it holds it. Before, the retry with a good name was refused \"Profile <name> exists\".\n const shownName = parsed.options.name === undefined ? undefined : checkShownName(parsed.options.name);\n const paths = createProfile(g.home, name);\n let shown: unknown = null;\n if (shownName !== undefined) {\n try {\n shown = await withSession({ ...g, profile: name, paths }, (s) => s.call(\"profile.set\", { name: shownName }));\n } catch (e) {\n rmSync(paths.dir, { recursive: true, force: true });\n throw e;\n }\n }\n if (parsed.options.use) selectProfile(g.home, name);\n print({ created: name, folder: paths.dir, current: currentProfile(g.home) === name, ...(shown ? { profile: shown } : {}) });\n return;\n }\n case \"list\": {\n noMoreThan(0, parsed.positionals, \"profile list\");\n const current = currentProfile(g.home);\n print({ profiles: listProfiles(g.home).map((name) => ({ name, current: name === current, running: lockOwner(profilePaths(g.home, name)) !== null })), home: g.home });\n return;\n }\n case \"use\": {\n const [name] = parsed.positionals;\n if (!name) throw new CliError(\"usage\", \"ghostly profile use <name>\");\n noMoreThan(1, parsed.positionals, \"profile use <name>\");\n selectProfile(g.home, name);\n print({ current: name });\n return;\n }\n case \"show\":\n noMoreThan(0, parsed.positionals, \"profile show\");\n print(await withSession(g, (s) => s.call(\"profile.get\"), { offline: true }));\n return;\n case \"set\": {\n noMoreThan(0, parsed.positionals, \"profile set [--name <name>] [--share-profile | --no-share-profile]\");\n const params: Record<string, unknown> = {};\n if (parsed.options.name !== undefined) params.name = parsed.options.name;\n if (parsed.options[\"share-profile\"] !== undefined) params.shareProfile = parsed.options[\"share-profile\"];\n if (!Object.keys(params).length) throw new CliError(\"usage\", \"ghostly profile set [--name <name>] [--share-profile | --no-share-profile]\");\n print(await withSession(g, (s) => s.call(\"profile.set\", params)));\n return;\n }\n case \"backup\": {\n noMoreThan(0, parsed.positionals, \"profile backup --out <file> [--passphrase-file f | --no-passphrase] [--light]\");\n const out = parsed.options.out;\n if (typeof out !== \"string\") throw new CliError(\"usage\", \"ghostly profile backup --out <file> [--passphrase-file f | --no-passphrase] [--light] (or GHOSTLY_BACKUP_PASSPHRASE)\");\n // Encrypted unless --no-passphrase says otherwise, and never a guess: a passphrase and --no-passphrase together are refused.\n const unsealed = parsed.options.passphrase === false;\n if (parsed.options.passphrase === true) throw new CliError(\"usage\", \"The passphrase comes from --passphrase-file or GHOSTLY_BACKUP_PASSPHRASE, never the command line\");\n if (unsealed && (parsed.options[\"passphrase-file\"] !== undefined || process.env.GHOSTLY_BACKUP_PASSPHRASE)) throw new CliError(\"usage\", \"A passphrase is set (--passphrase-file or GHOSTLY_BACKUP_PASSPHRASE) and --no-passphrase was given: choose one\");\n const light = parsed.options.light === true ? { light: true } : {};\n // The passphrase is read before the profile opens, and the backup only reads the store: offline.\n const path = here(out) as string;\n const params = unsealed ? { path, noPassphrase: true, ...light } : { path, passphrase: backupPassphrase(parsed.options[\"passphrase-file\"]), ...light };\n const made = await withSession(g, (s) => s.call(\"profile.backup\", params), { offline: true });\n if (unsealed) process.stderr.write(\"Not encrypted: this file holds the profile's keys, chats and wallet secrets in the clear. Anyone who gets it gets everything in it, including any money in its wallets.\\n\");\n print(made);\n return;\n }\n case \"restore\": {\n const [file, name] = parsed.positionals;\n if (!file || !name) throw new CliError(\"usage\", \"ghostly profile restore <file> <new profile> [--passphrase-file f] [--use]\");\n noMoreThan(2, parsed.positionals, \"profile restore <file> <new profile> [--passphrase-file f] [--use]\");\n // A backup made without a passphrase says so in its header: none is asked for, and the answer says it was not protected.\n const { backupFileProtection, restoreProfile } = await import(\"./backup\");\n const protection = await backupFileProtection(file);\n const paths = await restoreProfile(g.home, checkProfileName(name), file, protection === \"none\" ? undefined : backupPassphrase(parsed.options[\"passphrase-file\"], RESTORE_PASSPHRASE));\n if (parsed.options.use) selectProfile(g.home, name);\n print({ restored: name, folder: paths.dir, protection });\n return;\n }\n default:\n throw unknownCommand(\"profile\", sub);\n }\n}\n\n/**\n * A clean stop (peers told goodbye, the store folded), once; a second signal, or a stop that takes longer than\n * 20 s, leaves at once. The store's journal makes that safe.\n */\nfunction stopper(work: () => Promise<void>): () => void {\n let started = false;\n return () => {\n if (started) process.exit(1);\n started = true;\n setTimeout(() => process.exit(1), 20_000).unref();\n void work().then(() => process.exit(0), () => process.exit(1));\n };\n}\n\n/**\n * Ctrl-C, a service manager's stop, and the terminal or SSH session it ran in closing (SIGHUP, which would otherwise\n * end it on the spot): each a clean stop.\n */\nfunction onStopSignals(stop: () => void): void {\n for (const signal of [\"SIGINT\", \"SIGTERM\", \"SIGHUP\"] as const) process.on(signal, stop);\n}\n\nconst BACKUP_PASSPHRASE = \"The backup passphrase comes from --passphrase-file or GHOSTLY_BACKUP_PASSPHRASE (at least 12 characters). For a backup that is not encrypted, say so with --no-passphrase\";\n/** Restore takes no --no-passphrase: a backup made without one says so itself. */\nconst RESTORE_PASSPHRASE = \"This backup is encrypted: its passphrase comes from --passphrase-file or GHOSTLY_BACKUP_PASSPHRASE\";\n\n/**\n * The backup passphrase: from a file or the environment, never the command line (it would sit in shell history). The\n * file is said as every other file the CLI reads: \"\" names none, a folder is named, and an empty one is called that,\n * not \"comes from --passphrase-file\" to someone who gave it.\n */\nfunction backupPassphrase(file: unknown, missing = BACKUP_PASSPHRASE): string {\n if (typeof file !== \"string\") {\n const value = process.env.GHOSTLY_BACKUP_PASSPHRASE;\n if (!value) throw new CliError(\"usage\", missing);\n return value;\n }\n let value: string;\n try { value = readFileSync(here(file) as string, \"utf8\").replace(/\\r?\\n$/, \"\"); } catch (error) { throw localFileError(error, file) ?? error; }\n if (!value) throw new CliError(\"bad_request\", `${file} is empty: it holds the backup's passphrase`);\n return value;\n}\n\nasync function runDaemon(g: Globals): Promise<void> {\n requireProfile(g);\n if (await connectDaemon(g.paths)) throw new CliError(\"busy\", `A daemon already runs profile ${g.profile}`);\n const { keepServing, openHost, serve } = await engineHost();\n const host = await openHost(g.paths, \"daemon\", VERSION);\n let served: Awaited<ReturnType<typeof serve>>;\n try { served = await serve(host); } catch (error) { await host.close(); throw error; }\n keepServing();\n const stop = stopper(async () => { await served.close(); await host.close(); });\n host.ctx.stop = stop;\n onStopSignals(stop);\n host.ctx.hub.emit(\"daemon.started\", `daemon.started:${process.pid}:${Date.now()}`, { pid: process.pid, version: VERSION });\n print({ daemon: \"ready\", profile: g.profile, pid: process.pid, socket: g.paths.socket, lastSeq: host.ctx.hub.lastSeq });\n}\n\nasync function daemonCommand(argv: string[]): Promise<void> {\n const sub = argv[0] && !argv[0].startsWith(\"-\") ? argv[0] : undefined;\n const parsed = parseArgs(sub ? argv.slice(1) : argv, { detach: { type: \"boolean\", description: \"\" }, timeout: { type: \"number\", description: \"\" } });\n const g = globals(parsed);\n pretty = g.pretty;\n if (!sub || [\"status\", \"stop\", \"restart\"].includes(sub)) noMoreThan(0, parsed.positionals, sub ? `daemon ${sub} [--timeout s]` : \"daemon [--detach] [--timeout s]\");\n if (sub === \"status\") {\n knownProfile(g);\n const client = await connectDaemon(g.paths);\n // The socket, running or not: a program on the socket API (examples/*.mjs) finds it here. It is in the profile's\n // folder, or in /tmp/ghostly-<hash>/ when that path is too long for a socket, so a program cannot guess it.\n if (!client) { print({ running: false, profile: g.profile, socket: g.paths.socket }); return; }\n try { print({ running: true, ...(await client.call(\"status\", {}, { timeoutMs: seconds(parsed, 15) * 1000 }) as object), socket: g.paths.socket }); } finally { client.close(); }\n return;\n }\n if (sub === \"stop\") {\n knownProfile(g);\n const stopFor = seconds(parsed, 20);\n const client = await connectDaemon(g.paths);\n if (!client) throw new CliError(\"not_found\", `No daemon runs profile ${g.profile}`);\n print({ stopped: true, pid: await stopDaemon(g, client, stopFor) });\n return;\n }\n if (sub === \"restart\") {\n // The running one stops (if one runs), and this command's own code starts in the background.\n const stopFor = seconds(parsed, 20), startFor = seconds(parsed, 60);\n const client = await connectDaemon(g.paths);\n // The version it ran is asked ahead of the stop, on the same connection, with no deadline of its own: cosmetic,\n // and the stop's deadline ends it (a deadline here, 15 s, closed the connection under a longer stop, which then\n // failed as `unavailable` and never reached the signals).\n const probe = client ? client.call(\"status\").catch(() => null) as Promise<{ version?: string } | null> : null;\n const stopped = client ? await stopDaemon(g, client, stopFor) : null;\n const before = (await probe)?.version ?? null;\n const started = await startDetached(g, startFor);\n print({ restarted: true, stopped, before, version: VERSION, ...started });\n return;\n }\n if (sub) throw unknownCommand(\"daemon\", sub);\n const startFor = seconds(parsed, 60);\n if (!parsed.options.detach) { await runDaemon(g); return; }\n print(await startDetached(g, startFor));\n}\n\n/** `--timeout <s>`, or `fallback` without one: seconds above 0 (0 or less would not wait at all). */\nfunction seconds(parsed: Parsed, fallback: number): number {\n const value = parsed.options.timeout;\n if (value === undefined) return fallback;\n if (typeof value !== \"number\" || !(value > 0)) throw new CliError(\"usage\", \"--timeout takes a number of seconds above 0\");\n return value;\n}\n\n/**\n * Asks the daemon to stop and waits until its process is gone, not only until it let go of the profile (it releases\n * the lock a moment before it exits); its pid. One that does not answer the ask in `seconds` (its event loop wedged)\n * is sent SIGTERM, and SIGKILL when that did not end it either in as long: `daemon restart` then starts a fresh one,\n * as the timeout error promises. The pid is the profile lock's holder, which a daemon writes itself. On Windows\n * `process.kill` with either name is TerminateProcess: the first signal ends it, there is no second.\n */\nasync function stopDaemon(g: Globals, client: DaemonClient, seconds: number): Promise<number> {\n let pid: number, answered = true;\n try { ({ pid } = await client.call(\"daemon.stop\", {}, { timeoutMs: seconds * 1000 }) as { pid: number }); }\n catch (error) {\n // What answers on the socket and does not prove it is the profile's daemon is told nothing: a daemon of an older\n // release (it cannot prove it) is stopped as the process that holds the profile's lock, which only this user\n // can write. With nobody holding it, what answers is not the daemon, and the refusal stands.\n const refused = isNotTheDaemon(error);\n if (!(error instanceof CliError && error.code === \"timeout\") && !refused) throw error;\n const holder = lockOwner(g.paths);\n if (holder === null) throw error;\n process.stderr.write(refused\n ? `ghostly: what answers on the socket did not prove it is this profile's daemon (an older release's cannot): stopping the process that holds the profile (${holder}) with SIGTERM\\n`\n : `ghostly: the daemon (process ${holder}) did not answer daemon.stop in ${seconds} s: stopping it with SIGTERM\\n`);\n pid = holder;\n answered = false;\n signal(pid, \"SIGTERM\");\n }\n client.close();\n const running = () => lockOwner(g.paths) === pid || processAlive(pid);\n const gone = async () => {\n const until = Date.now() + seconds * 1000;\n while (running()) {\n const left = until - Date.now();\n if (left <= 0) break;\n await new Promise((resolve) => setTimeout(resolve, Math.min(100, left)));\n }\n return !running();\n };\n if (await gone()) return pid;\n // A wedged event loop runs no SIGTERM handler either.\n if (!answered) {\n process.stderr.write(`ghostly: the daemon (process ${pid}) did not stop on SIGTERM in ${seconds} s: killing it\\n`);\n signal(pid, \"SIGKILL\");\n if (await gone()) return pid;\n }\n throw new CliError(\"timeout\", `The daemon (process ${pid}) has not stopped yet`, { pid });\n}\n\n/** Throws busy, with its pid, when a process other than `except` holds the profile. */\nfunction heldBy(g: Globals, except?: number): void {\n const owner = lockOwner(g.paths);\n if (owner !== null && owner !== except) throw new CliError(\"busy\", `Profile ${g.profile} is in use by process ${owner}`, { pid: owner });\n}\n\n/** Gone already, or not ours to signal: the wait that follows says so. */\nfunction signal(pid: number, name: \"SIGTERM\" | \"SIGKILL\"): void {\n try { process.kill(pid, name); } catch { /* ESRCH, EPERM */ }\n}\n\nfunction processAlive(pid: number): boolean {\n try { process.kill(pid, 0); return true; } catch (error) { return (error as NodeJS.ErrnoException).code === \"EPERM\"; }\n}\n\n/** A daemon in the background, running this command's code, once its socket answers. */\nasync function startDetached(g: Globals, seconds: number) {\n requireProfile(g);\n if (await connectDaemon(g.paths)) throw new CliError(\"busy\", `A daemon already runs profile ${g.profile}`);\n // A one-shot command (or a listen) that opened the profile in process holds it: the child would only log that.\n heldBy(g);\n const log = openSync(g.paths.log, \"a\", 0o600);\n const child = spawn(process.execPath, [...process.execArgv, process.argv[1], \"daemon\", \"--home\", g.home, \"--profile\", g.profile], { detached: true, stdio: [\"ignore\", log, log] });\n child.unref();\n const spawned = { error: null as Error | null };\n // A spawn that fails outright (EAGAIN, EMFILE) sets `exitCode` to the errno before the \"error\" event, so the loop below\n // ends on its own; the listener swallows the otherwise uncaught event and keeps the cause for the message.\n child.once(\"error\", (error) => { spawned.error = error; });\n const until = Date.now() + seconds * 1000;\n let client: DaemonClient | null = null;\n // Try at once, then every 200 ms, never past `until`: a small `--timeout` gives up near-immediately instead of always\n // waiting one 200 ms poll first (the first try finds no socket yet and returns at once). A child that exited or was\n // killed (SIGABRT on a V8 out-of-memory, the OOM killer) ends the wait too, instead of polling to the deadline.\n while (child.exitCode === null && child.signalCode === null && !spawned.error) {\n const left = until - Date.now();\n if (left <= 0) break;\n client = await connectDaemon(g.paths, Math.min(500, left));\n if (client) break;\n await new Promise((resolve) => setTimeout(resolve, Math.max(0, Math.min(200, until - Date.now()))));\n }\n if (!client) {\n heldBy(g, child.pid); // another process took the profile between the check and the child's start\n // Alive still: it is starting (a large profile takes seconds), not failed, and the profile is its own now.\n if (child.exitCode === null && child.signalCode === null && child.pid !== undefined && processAlive(child.pid)) {\n throw new CliError(\"timeout\", `The daemon (process ${child.pid}) is still starting; ghostly daemon status shows when it is up`, { pid: child.pid, log: g.paths.log });\n }\n throw new CliError(\"engine\", spawned.error ? `The daemon could not be spawned: ${spawned.error.message}` : `The daemon did not start; see ${g.paths.log}`);\n }\n client.close();\n return { daemon: \"started\", profile: g.profile, pid: child.pid, socket: g.paths.socket, log: g.paths.log };\n}\n\n/**\n * Nobody reads `listen`'s output any more (`listen | head -n 1`, a `grep -m1` that found its line): it stops as on\n * SIGTERM, exit 0. Through a daemon it died on an 'error' nobody handled; on its own profile it served on with nobody\n * to tell, holding the profile until `daemon stop`. Any other failure of the output is still an error.\n */\nfunction onReaderGone(stop: () => void): void {\n let gone = false;\n process.stdout.on(\"error\", (error: NodeJS.ErrnoException) => {\n if (gone) return;\n if (error.code !== \"EPIPE\") throw error;\n gone = true;\n stop();\n });\n}\n\nasync function listenCommand(argv: string[]): Promise<void> {\n const parsed = parseArgs(argv, {\n since: { type: \"number\", description: \"\" }, cursor: { type: \"string\", description: \"\" }, type: { type: \"list\", description: \"\" },\n exec: { type: \"string\", description: \"\" }, webhook: { type: \"string\", description: \"\" }, print: { type: \"boolean\", description: \"\" },\n from: { type: \"list\", description: \"\" }, group: { type: \"list\", description: \"\" }, turns: { type: \"boolean\", description: \"\" },\n });\n // Before the profile opens: `listen bob` (meant as `--from bob`) streams nobody's events instead of everybody's.\n noMoreThan(0, parsed.positionals, SPECIAL.find(([usage]) => usage.startsWith(\"listen \"))![0]);\n // Before the profile opens: a unit file's `--webhook \"$URL\"` with URL unset ran a plain listen, no hook and no word.\n const blank = (value: unknown) => typeof value === \"string\" && value.trim() === \"\";\n if (blank(parsed.options.webhook)) throw new CliError(\"usage\", \"--webhook needs a URL\");\n if (blank(parsed.options.exec)) throw new CliError(\"usage\", \"--exec needs a command\");\n if (parsed.options.cursor === \"\") throw new CliError(\"usage\", \"--cursor needs a file\");\n if ((parsed.options.from as string[] | undefined)?.some(blank)) throw new CliError(\"usage\", \"--from needs a chat or a contact key\");\n if ((parsed.options.group as string[] | undefined)?.some(blank)) throw new CliError(\"usage\", \"--group needs a group\");\n const g = globals(parsed);\n pretty = false; // one event per line\n if (parsed.options.webhook !== undefined) checkWebhook(String(parsed.options.webhook));\n const types = (parsed.options.type as string[] | undefined) ?? [];\n const turns = parsed.options.turns === true;\n if (turns && types.length) throw new CliError(\"usage\", \"--turns takes the place of --type: a turn is a message received, or a group message that mentions you\");\n checkTypes(types, (line) => process.stderr.write(line + \"\\n\"));\n const from = (parsed.options.from as string[] | undefined) ?? [], groups = (parsed.options.group as string[] | undefined) ?? [];\n const cursor = parsed.options.cursor as string | undefined;\n // Before the profile opens: a cursor that cannot be written is no per-event warning.\n checkCursor(cursor);\n const since = (parsed.options.since as number | undefined) ?? readCursor(cursor);\n const start = async (call: (method: string, params: Record<string, unknown>) => Promise<unknown>, peerOf: (chat: string) => Promise<string | null>) => {\n return eventHandler({\n types, turns,\n exec: parsed.options.exec as string | undefined,\n webhook: parsed.options.webhook as string | undefined,\n cursor,\n // With a hook, events go to the hook; --print shows them too.\n print: parsed.options.print === true || (!parsed.options.exec && !parsed.options.webhook),\n write: (line) => process.stdout.write(line + \"\\n\"),\n drained: () => new Promise<void>((resolve) => {\n const done = () => { process.stdout.off(\"drain\", done); process.stdout.off(\"close\", done); resolve(); };\n process.stdout.on(\"drain\", done);\n process.stdout.on(\"close\", done);\n }),\n allow: from.length || groups.length ? await allowlist(from, groups, call, peerOf) : undefined,\n });\n };\n requireProfile(g);\n const client = await connectDaemon(g.paths);\n if (client) await warnVersion(client);\n if (client) {\n // The subscription takes the connection: a chat's contact key is asked on a connection of its own.\n const handle = await start((m, p) => client.call(m, p), async (chat) => {\n const c = await connectDaemon(g.paths, 1000);\n if (!c) return null;\n try { return ((await c.call(\"chat.get\", { chat }, { timeoutMs: ANSWER_MS })) as { peer?: string }).peer || null; } finally { c.close(); }\n }).catch((error) => { client.close(); throw error; });\n // Followed until stopped, past a daemon restart and past a feed that fell behind (`followDaemon`).\n const following = followDaemon(g.paths, client, handle, since);\n const stop = () => { following.close(); process.exit(0); };\n onReaderGone(stop);\n await following.subscribed;\n process.on(\"SIGINT\", stop);\n process.on(\"SIGTERM\", stop);\n return;\n }\n // No daemon: this process becomes it (the socket too, so hooks can answer with `ghostly send`).\n const [{ keepServing, openHost, serve }, { callApi }] = await Promise.all([engineHost(), engineApi()]);\n const host: Host = await openHost(g.paths, \"daemon\", VERSION);\n const call = (m: string, p: Record<string, unknown>) => callApi(host.ctx, m, p);\n const handle = await start(call, async (chat) => ((await call(\"chat.get\", { chat })) as { peer?: string }).peer || null).catch(async (error) => { await host.close(); throw error; });\n const served = await serve(host).catch(async (error) => { await host.close(); throw error; });\n keepServing();\n const stop = stopper(async () => { await served.close(); await host.close(); });\n host.ctx.stop = stop;\n onStopSignals(stop);\n onReaderGone(stop);\n // The hub's listener comes off while the feed is paused, and back after a replay from the last event taken. What a\n // replay gave and the feed did not take yet waits for the resume: one read of the journal per catch-up, not one per\n // pause; the journal is read again only for what came meanwhile.\n let off: (() => void) | null = null, left: GhostlyEvent[] = [];\n const open = (from: number | undefined) => {\n for (;;) {\n const events = left.length ? left : host.ctx.hub.replay(from ?? host.ctx.hub.lastSeq);\n left = [];\n if (!events.length) break;\n for (let i = 0; i < events.length; i++) {\n feed.take(events[i]);\n if (feed.paused) { left = events.slice(i + 1); return; }\n }\n from = feed.since;\n }\n off = host.ctx.hub.onEvent(feed.take);\n };\n const feed = new Feed(handle, since, () => { off?.(); off = null; }, open);\n open(since);\n host.ctx.hub.emit(\"daemon.started\", `daemon.started:${process.pid}:${Date.now()}`, { pid: process.pid, version: VERSION, listen: true });\n}\n\nasync function engineCommand(argv: string[]): Promise<void> {\n const parsed = parseArgs(argv, { \"confirm-real\": { type: \"boolean\", description: \"\" }, \"show-secret\": { type: \"boolean\", description: \"\" }, yes: { type: \"boolean\", description: \"\" }, force: { type: \"boolean\", description: \"\" }, list: { type: \"boolean\", description: \"\" }, verbose: { type: \"boolean\", description: \"\" } });\n const g = globals(parsed);\n pretty = g.pretty;\n if (parsed.options.list) {\n noMoreThan(0, parsed.positionals, \"engine --list [--verbose]\");\n const methods = [...ENGINE_METHODS, ...ENGINE_READS].sort();\n // `takes`: what each call takes, in ENGINE_PARAMS' words.\n print(parsed.options.verbose ? { methods, takes: Object.fromEntries(methods.map((m) => [m, ENGINE_PARAMS[m] ?? READ_PARAMS[m]])) } : { methods });\n return;\n }\n const [method, raw] = parsed.positionals;\n if (!method || parsed.positionals.length > 2) throw new CliError(\"usage\", \"ghostly engine <method> [json-params | -]\");\n if (!ENGINE_METHODS.includes(method) && !ENGINE_READS.includes(method)) throw new CliError(\"not_found\", `The engine has no call ${method} (ghostly engine --list)`);\n const showSecret = parsed.options[\"show-secret\"] === true;\n if (SECRET_RESULTS.has(method) && !showSecret) throw new CliError(\"confirm\", `${method} answers with secrets: add --show-secret to print them`);\n let params: unknown;\n const text = raw === \"-\" ? await readStdin() : raw;\n if (text !== undefined && text.trim()) {\n try { params = JSON.parse(text); } catch { throw new CliError(\"usage\", \"The parameters must be JSON (an object)\"); }\n }\n const confirmReal = parsed.options[\"confirm-real\"] === true;\n if (confirmReal && params && typeof params === \"object\") (params as Record<string, unknown>).confirmedReal = true;\n const yes = parsed.options.yes === true;\n let result = await withSession(g, (s) => s.call(\"engine.call\", { method, params, confirmReal, yes, force: parsed.options.force === true }), { offline: ENGINE_READS.includes(method) });\n if (method === \"getState\" && !showSecret && result && typeof result === \"object\") {\n const { hideStateSecrets } = await engineApi();\n result = hideStateSecrets(result as Parameters<typeof hideStateSecrets>[0]);\n }\n print(result);\n}\n\nasync function settingsCommand(sub: string | undefined, argv: string[]): Promise<void> {\n const parsed = parseArgs(argv, { \"show-secret\": { type: \"boolean\", description: \"\" } });\n const g = globals(parsed);\n pretty = g.pretty;\n if (sub === \"get\") { noMoreThan(0, parsed.positionals, \"settings get [--show-secret]\"); print(await withSession(g, (s) => s.call(\"settings.get\", { showSecret: parsed.options[\"show-secret\"] === true }), { offline: true })); return; }\n if (sub === \"set\") {\n const [key, value] = parsed.positionals;\n if (!key || value === undefined || parsed.positionals.length > 2) throw new CliError(\"usage\", \"ghostly settings set <key> <json-value>\");\n let parsedValue: unknown;\n try { parsedValue = JSON.parse(value); } catch { parsedValue = value; }\n // A text setting (nick) keeps the word as given when it reads as JSON of another kind (2024, true, null).\n if ((await engineApi()).SETTABLE[key] === \"string\" && typeof parsedValue !== \"string\") parsedValue = value;\n printAnswer(await withSession(g, (s) => s.call(\"settings.set\", { [key]: parsedValue }), { offline: LOCAL_SETTINGS.has(key) }) as Record<string, unknown>);\n return;\n }\n throw unknownCommand(\"settings\", sub);\n}\n\nasync function textCommand(name: string, argv: string[]): Promise<void> {\n const spec = TEXT_COMMANDS[name];\n const parsed = parseArgs(argv, spec.options, idSlot(spec));\n const g = globals(parsed);\n pretty = g.pretty;\n const [target, ...rest] = parsed.positionals;\n // `edit` names the message before the text.\n const [message, ...words] = spec.message ? rest : [undefined, ...rest];\n if (!target || (spec.message && !message)) throw new CliError(\"usage\", `ghostly ${spec.usage}`);\n // Stdin only when no text word was given at all: `send bob \"$line\"` with an empty line is no text, not the rest of stdin.\n let text = words.join(\" \");\n if (parsed.options.text !== undefined) {\n if (text || parsed.options.stdin) throw new CliError(\"usage\", \"Give the text once: as arguments, --text or stdin\");\n text = String(parsed.options.text);\n } else if (parsed.options.stdin || (words.length === 0 && !process.stdin.isTTY)) {\n if (text) throw new CliError(\"usage\", \"Give the text as arguments or on stdin, not both\");\n text = (await readStdin()).replace(/\\n$/, \"\");\n }\n if (!text.trim()) throw new CliError(\"usage\", `No text: ghostly ${spec.usage}`);\n const params: Record<string, unknown> = { [spec.target]: target, text, force: parsed.options.force === true, ...(message !== undefined && { message }) };\n if (spec.target === \"group\") params.mentions = parsed.options.mention ?? [];\n if (parsed.options.reply !== undefined) params.reply = parsed.options.reply;\n if (!spec.message) Object.assign(params, (await import(\"./buttons\")).buttonsOf(parsed.options));\n print(await withSession(g, (s) => {\n if (spec.target === \"chat\") {\n // A one-shot leaves once its command is done: by default it stays until the message went out.\n params.wait = parsed.options.wait ?? (s.mode === \"one-shot\" ? (spec.message ? \"confirmed\" : \"sent\") : \"none\");\n if (parsed.options.timeout !== undefined) params.timeout = parsed.options.timeout;\n } else {\n // A group has no receipts: `--wait sent` waits until an edge took it. None by default.\n if (parsed.options.wait !== undefined) params.wait = parsed.options.wait;\n if (parsed.options.timeout !== undefined) params.timeout = parsed.options.timeout;\n }\n return s.call(spec.method, params);\n }, { deferGroups: spec.target === \"chat\" }));\n}\n\n/**\n * `identity add`: a proof. An in-app signer finishes in this one command (what it waits on is printed to stderr as it\n * comes); a tool or a published record answers with the statement, and `identity complete` finishes it later, in the\n * same daemon.\n */\nasync function identityAddCommand(argv: string[]): Promise<void> {\n const parsed = parseArgs(argv, {\n signer: { type: \"string\", description: \"\" }, field: { type: \"list\", description: \"\" }, days: { type: \"number\", description: \"\" }, timeout: { type: \"number\", description: \"\" },\n });\n const g = globals(parsed);\n pretty = g.pretty;\n const [provider, ...subject] = parsed.positionals;\n if (!provider) throw new CliError(\"usage\", \"ghostly identity add <provider> [subject] [--signer id] [--field name=value]... [--days n]\");\n const fields: Record<string, string> = {};\n for (const item of (parsed.options.field as string[] | undefined) ?? []) {\n const eq = item.indexOf(\"=\");\n if (eq < 1) throw new CliError(\"usage\", `--field takes name=value, not ${JSON.stringify(item)}`);\n fields[item.slice(0, eq)] = item.slice(eq + 1);\n }\n const params = { provider, subject: subject.join(\" \") || undefined, signer: parsed.options.signer, fields, days: parsed.options.days, timeout: parsed.options.timeout };\n const tell = (event: GhostlyEvent) => {\n if (event.type === \"identity.approval\" || event.type === \"identity.progress\") process.stderr.write(JSON.stringify(event) + \"\\n\");\n };\n requireProfile(g);\n const client = await connectDaemon(g.paths);\n if (client) {\n await warnVersion(client);\n const watcher = await connectDaemon(g.paths);\n await watcher?.subscribe(undefined, tell);\n try { print(await client.call(\"identity.add\", params)); } finally { client.close(); watcher?.close(); }\n return;\n }\n const [{ openHost }, { callApi }] = await Promise.all([engineHost(), engineApi()]);\n const host = await openHost(g.paths, \"one-shot\", VERSION);\n const off = host.ctx.hub.onEvent(tell);\n try {\n const result = await callApi(host.ctx, \"identity.add\", params) as { done: boolean; draft?: string };\n if (!result.done) {\n await callApi(host.ctx, \"identity.cancel\", { draft: result.draft }).catch(() => {});\n throw new CliError(\"unavailable\", \"A proof made in two steps waits in the daemon between them: start `ghostly daemon --detach`, then run this again\");\n }\n print(result);\n } finally { off(); await host.close(); }\n}\n\nasync function tableCommand(name: string, argv: string[]): Promise<void> {\n const command = COMMANDS[name];\n const parsed = parseArgs(argv, command.options ?? {}, idSlot(command));\n const g = globals(parsed);\n pretty = g.pretty;\n const args = positionals(command, parsed.positionals);\n if (command.run) {\n printAnswer(await command.run(parsed, args));\n return;\n }\n const params = command.params?.(parsed, args) ?? {};\n for (const key of Object.keys(params)) if (params[key] === undefined) delete params[key];\n // Evidence is read here, where the file is: the daemon runs elsewhere.\n if (command.method === \"identity.complete\") {\n if (params.evidenceFile) {\n try { params.evidence = readFileSync(params.evidenceFile as string, \"utf8\"); } catch (error) { throw localFileError(error, params.evidenceFile as string) ?? error; }\n }\n else if (params.stdin) params.evidence = await readStdin();\n delete params.evidenceFile; delete params.stdin;\n }\n if (command.method === \"x401.credential.add\") {\n try { params.credential = params.file === \"-\" ? await readStdin() : readFileSync(params.file as string, \"utf8\"); }\n // A file not there, a folder, one not allowed: said as every other file the CLI reads.\n catch (error) { throw localFileError(error, params.file as string) ?? new CliError(\"usage\", `Cannot read the credential: ${error instanceof Error ? error.message : String(error)}`); }\n // Nothing read is said of the file or stdin given, not as the API's missing `credential`.\n if (!params.credential) throw new CliError(\"bad_request\", params.file === \"-\" ? \"Nothing on stdin: give the SD-JWT VC the issuer sent\" : `${params.file as string} is empty: it holds the SD-JWT VC the issuer sent`);\n delete params.file;\n }\n // Before stdin adds its own: only the --value names came on the command line.\n const lineValues = command.method === \"wallet.create\" ? Object.keys((params.values as Record<string, string> | undefined) ?? {}) : [];\n const secretWarning = await secretsFromStdin(command.method, params, readStdin, process.stdin.isTTY === true, (note) => process.stderr.write(`ghostly: ${note}\\n`));\n if (secretWarning) process.stderr.write(`ghostly: ${secretWarning}\\n`);\n const result = await withSession(g, async (s) => {\n if (lineValues.length) {\n // Which fields are secret is the source's form, in the engine.\n const list = await s.call(\"wallet.list\", { network: params.network ?? \"testnet\" }).catch(() => undefined);\n const warning = secretValuesWarning(list, params.type, params.provider, lineValues);\n if (warning) process.stderr.write(`ghostly: ${warning}\\n`);\n }\n const result = await s.call(command.method, params) as Record<string, unknown>;\n // A one-shot join leaves once the contact can be reached: its answer has to be out first.\n if (command.method === \"invite.join\" && s.mode === \"one-shot\") {\n const joined = await oneShotJoinWait(s, result, typeof params.label === \"string\" ? params.label : undefined);\n if (joined.note) process.stderr.write(`ghostly: ${joined.note}\\n`);\n return joined.answer;\n }\n return result;\n }, { deferGroups: chatOnly(command.method, params), offline: offlineCall(command.method, params) });\n printAnswer(result);\n}\n\n/**\n * `call pipe`: a call's audio socket bridged to stdin and stdout, for shell pipelines. stdout carries audio only (the\n * contact's, raw PCM); what the command says goes to stderr. It ends when the call does.\n */\nasync function callPipeCommand(argv: string[]): Promise<void> {\n const parsed = parseArgs(argv, {}, idSlot({ args: [\"call...?\"] }));\n const g = globals(parsed);\n const ref = parsed.positionals.join(\" \") || undefined;\n const client = await connectDaemon(g.paths);\n if (!client) throw new CliError(\"unavailable\", `No daemon runs profile ${g.profile}: calls need one (ghostly daemon --detach)`);\n let call: { call: string; audio: { socket: string; rate: number } | null };\n try { call = await client.call(\"call.get\", ref ? { call: ref } : {}, { timeoutMs: ANSWER_MS }) as typeof call; } finally { client.close(); }\n const audio = call.audio;\n if (!audio) throw new CliError(\"unavailable\", \"That call has no audio yet: answer it first\");\n const socket = connect(audio.socket);\n await new Promise<void>((resolve, reject) => { socket.once(\"connect\", resolve); socket.once(\"error\", reject); });\n process.stderr.write(`ghostly: call ${call.call}: s16le mono ${audio.rate} Hz on stdin/stdout\\n`);\n // A clip that ends (`ffmpeg -t 3 … | ghostly call pipe`) is queued and played, and the contact's audio goes on\n // coming: the end of stdin never closes the socket, whose daemon side would close the call's audio with it.\n process.stdin.pipe(socket, { end: false });\n socket.pipe(process.stdout);\n socket.on(\"close\", () => exit(0));\n socket.on(\"error\", () => exit(1));\n}\n\n// ---------- entry ----------\n\n/**\n * The command's words when the line asks for help (`help <words>`, or `--help`/`--help=true`/`-h` before any `--`), else\n * null. `--help=false` asks for none: the command runs.\n */\nfunction helpAsked(argv: readonly string[]): string[] | null {\n const end = argv.indexOf(\"--\");\n const head = end === -1 ? argv : argv.slice(0, end);\n const words = (list: readonly string[]) => { const out: string[] = []; for (const word of list) { if (word.startsWith(\"-\")) break; out.push(word); } return out; };\n if (head[0] === \"help\") return words(head.slice(1));\n if (head.some((word) => word === \"--help\" || word === \"--help=true\" || word === \"-h\")) return words(head);\n return null;\n}\n\nexport async function main(input: string[]): Promise<number> {\n const argv = liftGlobals(input);\n // Global options alone (`ghostly --pretty`, `ghostly -p bot`) name no command: lifted, one of them comes first.\n const helpFor = argv.length === 0 || globalOption(argv[0]) ? [] : helpAsked(argv);\n if (helpFor) { process.stdout.write((helpFor.length ? commandHelp(helpFor) : help()) + \"\\n\"); return 0; }\n if (argv[0] === \"--version\" || argv[0] === \"version\") {\n // Global options come after the command once lifted: `--pretty` indents this answer too. Anything else is refused,\n // as every command refuses it: `version --json` (a typo) answered the version.\n const parsed = parseArgs(argv.slice(1), {});\n noMoreThan(0, parsed.positionals, \"version\");\n pretty = parsed.options.pretty === true;\n print({ version: VERSION });\n return 0;\n }\n const [first, second, third] = argv;\n const two = second && !second.startsWith(\"-\") ? `${first} ${second}` : \"\";\n const three = two && third && !third.startsWith(\"-\") ? `${two} ${third}` : \"\";\n // A command is one its table lists itself: every object has `constructor` and `toString`, which are no commands.\n const text = (name: string) => Object.hasOwn(TEXT_COMMANDS, name), table = (name: string) => Object.hasOwn(COMMANDS, name);\n if (first === \"profile\" && !table(two)) { await profileCommand(second, argv.slice(2)); return 0; }\n if (first === \"daemon\") { await daemonCommand(argv.slice(1)); return -1; }\n if (first === \"listen\") { await listenCommand(argv.slice(1)); return -1; }\n if (first === \"engine\") { await engineCommand(argv.slice(1)); return 0; }\n if (first === \"settings\") { await settingsCommand(second, argv.slice(2)); return 0; }\n if (two === \"identity add\") { await identityAddCommand(argv.slice(2)); return 0; }\n if (two === \"call pipe\") { await callPipeCommand(argv.slice(2)); return -1; }\n if (three && table(three)) { await tableCommand(three, argv.slice(3)); return 0; }\n if (two && text(two)) { await textCommand(two, argv.slice(2)); return 0; }\n if (two && table(two)) { await tableCommand(two, argv.slice(2)); return 0; }\n if (text(first)) { await textCommand(first, argv.slice(1)); return 0; }\n if (table(first)) { await tableCommand(first, argv.slice(1)); return 0; }\n throw unknownCommand(first, two ? second : undefined, three ? third : undefined);\n}\n\n/**\n * A command line that names no command. The words of a group (`ghostly chat`, `ghostly wallet frob`, `ghostly x401\n * credential`) are answered with the group's commands, as `ghostly help chat` lists them; before, it was only \"Unknown\n * command: chat\". The longest group the words name answers: `x401 credential frob` lists add, list and remove.\n */\nexport function unknownCommand(first: string | undefined, second?: string, third?: string): CliError {\n const asked = [first, second, third].filter((word): word is string => !!word);\n const all = helpRows().map((row) => commandWords(row.usage));\n for (let depth = Math.min(asked.length, 2); depth >= 1; depth--) {\n const group = asked.slice(0, depth), name = group.join(\" \"), extra = asked[depth];\n const subs = [...new Set(all.filter((words) => words.length > depth && group.every((word, i) => words[i] === word)).map((words) => words[depth]))];\n if (!subs.length) continue;\n const list = `${subs.slice(0, -1).join(\", \")}${subs.length > 1 ? \" or \" : \"\"}${subs.at(-1)}`;\n return new CliError(\"usage\", extra ? `Unknown command: ${name} ${extra}: ghostly ${name} takes ${list} (ghostly help ${name})` : `ghostly ${name} takes a command: ${list} (ghostly help ${name})`);\n }\n return new CliError(\"usage\", `Unknown command: ${asked.slice(0, 2).join(\" \")} (ghostly help)`);\n}\n\n/** Leaves once what was printed reached stdout (a pipe drains asynchronously). */\nfunction exit(code: number): void {\n process.stdout.write(\"\", () => process.exit(code));\n}\n\n/**\n * Stdout is the command's answer and nothing else: one JSON object, or a stream of JSON lines. What the engine notes\n * as it works (a relay left alone for a minute, a wallet moved to its network's key) is written with `console.info`\n * and the like, which Node sends to stdout: a script reading the answer (`ghostly wallet list | jq`) then failed on a\n * line that is not JSON. Those notes go to stderr, where a daemon's log and a terminal still show them.\n */\nexport function notesToStderr(): void {\n for (const level of [\"log\", \"info\", \"debug\"] as const) console[level] = (...args: unknown[]) => { process.stderr.write(`${format(...args)}\\n`); };\n}\n\n/** Runs the command line; `-1` from `main` means the process stays (a daemon, a listener). */\nexport async function run(argv: string[]): Promise<void> {\n notesToStderr();\n try {\n const code = await main(argv);\n if (code >= 0) exit(code);\n } catch (error) {\n const failure = asCliError(error);\n print({ error: failure.toJSON() });\n exit(EXIT[failure.code]);\n }\n}\n"],"mappings":"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"}