@leemour/max-cli 0.5.0 → 0.6.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 (141) hide show
  1. package/README.md +14 -5
  2. package/dist/cache/store.d.ts.map +1 -1
  3. package/dist/cache/store.js +1 -0
  4. package/dist/cache/store.js.map +1 -1
  5. package/dist/client.d.ts +57 -3
  6. package/dist/client.d.ts.map +1 -1
  7. package/dist/client.js +229 -78
  8. package/dist/client.js.map +1 -1
  9. package/dist/commands/commands.d.ts +8 -0
  10. package/dist/commands/commands.d.ts.map +1 -0
  11. package/dist/commands/commands.js +36 -0
  12. package/dist/commands/commands.js.map +1 -0
  13. package/dist/commands/config.d.ts.map +1 -1
  14. package/dist/commands/config.js +2 -0
  15. package/dist/commands/config.js.map +1 -1
  16. package/dist/commands/context.d.ts +18 -0
  17. package/dist/commands/context.d.ts.map +1 -1
  18. package/dist/commands/context.js +21 -0
  19. package/dist/commands/context.js.map +1 -1
  20. package/dist/commands/inbox.d.ts +14 -0
  21. package/dist/commands/inbox.d.ts.map +1 -0
  22. package/dist/commands/inbox.js +90 -0
  23. package/dist/commands/inbox.js.map +1 -0
  24. package/dist/commands/messages.d.ts.map +1 -1
  25. package/dist/commands/messages.js +6 -2
  26. package/dist/commands/messages.js.map +1 -1
  27. package/dist/commands/reactions.d.ts +3 -0
  28. package/dist/commands/reactions.d.ts.map +1 -0
  29. package/dist/commands/reactions.js +26 -0
  30. package/dist/commands/reactions.js.map +1 -0
  31. package/dist/commands/recipients.d.ts +9 -0
  32. package/dist/commands/recipients.d.ts.map +1 -0
  33. package/dist/commands/recipients.js +68 -0
  34. package/dist/commands/recipients.js.map +1 -0
  35. package/dist/commands/sends.d.ts +4 -0
  36. package/dist/commands/sends.d.ts.map +1 -0
  37. package/dist/commands/sends.js +21 -0
  38. package/dist/commands/sends.js.map +1 -0
  39. package/dist/commands/session.d.ts.map +1 -1
  40. package/dist/commands/session.js +80 -15
  41. package/dist/commands/session.js.map +1 -1
  42. package/dist/commands/skill.d.ts.map +1 -1
  43. package/dist/commands/skill.js +2 -1
  44. package/dist/commands/skill.js.map +1 -1
  45. package/dist/config.d.ts +9 -1
  46. package/dist/config.d.ts.map +1 -1
  47. package/dist/config.js +16 -0
  48. package/dist/config.js.map +1 -1
  49. package/dist/domain/map.d.ts +3 -1
  50. package/dist/domain/map.d.ts.map +1 -1
  51. package/dist/domain/map.js +9 -0
  52. package/dist/domain/map.js.map +1 -1
  53. package/dist/domain/models.d.ts +33 -0
  54. package/dist/domain/models.d.ts.map +1 -1
  55. package/dist/domain/models.js.map +1 -1
  56. package/dist/generated/client.generated.d.ts +10 -0
  57. package/dist/generated/client.generated.d.ts.map +1 -1
  58. package/dist/generated/client.generated.js +10 -0
  59. package/dist/generated/client.generated.js.map +1 -1
  60. package/dist/generated/opcodes.generated.d.ts +13 -0
  61. package/dist/generated/opcodes.generated.d.ts.map +1 -1
  62. package/dist/generated/opcodes.generated.js +13 -0
  63. package/dist/generated/opcodes.generated.js.map +1 -1
  64. package/dist/generated/operations.generated.d.ts +86 -1
  65. package/dist/generated/operations.generated.d.ts.map +1 -1
  66. package/dist/generated/operations.generated.js +10 -1
  67. package/dist/generated/operations.generated.js.map +1 -1
  68. package/dist/markdown.d.ts +18 -0
  69. package/dist/markdown.d.ts.map +1 -0
  70. package/dist/markdown.js +52 -0
  71. package/dist/markdown.js.map +1 -0
  72. package/dist/program.d.ts.map +1 -1
  73. package/dist/program.js +10 -0
  74. package/dist/program.js.map +1 -1
  75. package/dist/rendering/messages.d.ts.map +1 -1
  76. package/dist/rendering/messages.js +6 -0
  77. package/dist/rendering/messages.js.map +1 -1
  78. package/dist/resolve.d.ts +15 -0
  79. package/dist/resolve.d.ts.map +1 -0
  80. package/dist/resolve.js +48 -0
  81. package/dist/resolve.js.map +1 -0
  82. package/dist/sends/guard.d.ts +26 -0
  83. package/dist/sends/guard.d.ts.map +1 -0
  84. package/dist/sends/guard.js +48 -0
  85. package/dist/sends/guard.js.map +1 -0
  86. package/dist/sends/journal.d.ts +29 -0
  87. package/dist/sends/journal.d.ts.map +1 -0
  88. package/dist/sends/journal.js +40 -0
  89. package/dist/sends/journal.js.map +1 -0
  90. package/dist/sends/recipients.d.ts +29 -0
  91. package/dist/sends/recipients.d.ts.map +1 -0
  92. package/dist/sends/recipients.js +62 -0
  93. package/dist/sends/recipients.js.map +1 -0
  94. package/dist/session/adopt.d.ts.map +1 -1
  95. package/dist/session/adopt.js +7 -6
  96. package/dist/session/adopt.js.map +1 -1
  97. package/dist/session/browser.d.ts +55 -0
  98. package/dist/session/browser.d.ts.map +1 -0
  99. package/dist/session/browser.js +292 -0
  100. package/dist/session/browser.js.map +1 -0
  101. package/dist/session/handshake.d.ts +2 -0
  102. package/dist/session/handshake.d.ts.map +1 -1
  103. package/dist/session/handshake.js +3 -1
  104. package/dist/session/handshake.js.map +1 -1
  105. package/dist/session/login.d.ts +20 -0
  106. package/dist/session/login.d.ts.map +1 -0
  107. package/dist/session/login.js +66 -0
  108. package/dist/session/login.js.map +1 -0
  109. package/dist/session/prompt.d.ts +3 -1
  110. package/dist/session/prompt.d.ts.map +1 -1
  111. package/dist/session/prompt.js +2 -2
  112. package/dist/session/prompt.js.map +1 -1
  113. package/dist/session/qr-terminal.d.ts +9 -0
  114. package/dist/session/qr-terminal.d.ts.map +1 -0
  115. package/dist/session/qr-terminal.js +34 -0
  116. package/dist/session/qr-terminal.js.map +1 -0
  117. package/dist/session/store.d.ts +2 -0
  118. package/dist/session/store.d.ts.map +1 -1
  119. package/dist/session/store.js +2 -0
  120. package/dist/session/store.js.map +1 -1
  121. package/dist/spec/index.d.ts.map +1 -1
  122. package/dist/spec/index.js +11 -1
  123. package/dist/spec/index.js.map +1 -1
  124. package/dist/spec/operations/login.d.ts +64 -0
  125. package/dist/spec/operations/login.d.ts.map +1 -0
  126. package/dist/spec/operations/login.js +99 -0
  127. package/dist/spec/operations/login.js.map +1 -0
  128. package/dist/spec/operations/messages.d.ts +27 -1
  129. package/dist/spec/operations/messages.d.ts.map +1 -1
  130. package/dist/spec/operations/messages.js +46 -2
  131. package/dist/spec/operations/messages.js.map +1 -1
  132. package/dist/testing/mock-max.d.ts +3 -2
  133. package/dist/testing/mock-max.d.ts.map +1 -1
  134. package/dist/testing/mock-max.js +1 -1
  135. package/dist/testing/mock-max.js.map +1 -1
  136. package/dist/testing/sandbox.js +1 -0
  137. package/dist/testing/sandbox.js.map +1 -1
  138. package/dist/version.d.ts +1 -1
  139. package/dist/version.js +1 -1
  140. package/package.json +7 -3
  141. package/skills/max-cli/SKILL.md +14 -3
@@ -0,0 +1,40 @@
1
+ import { appendFileSync, mkdirSync, readFileSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { resolvePaths } from "@leemour/cli-core";
4
+ /**
5
+ * `<state dir>/sends/<profile>.jsonl` — beside `runs`, never in the cache directory, so that
6
+ * `max cache clear` cannot erase what was sent in the owner's name (the reason of `NEED-51`).
7
+ */
8
+ export const sendsPathFor = (profile, env = process.env) => join(resolvePaths({ appName: "max-cli", prefix: "MAX", env }).state, "sends", `${profile}.jsonl`);
9
+ export class SendJournal {
10
+ path;
11
+ constructor(path) {
12
+ this.path = path;
13
+ }
14
+ append(entry) {
15
+ mkdirSync(dirname(this.path), { recursive: true, mode: 0o700 });
16
+ appendFileSync(this.path, `${JSON.stringify(entry)}\n`, { mode: 0o600 });
17
+ }
18
+ /** Oldest first. A line that does not parse is skipped: a torn last write must not block sending. */
19
+ entries() {
20
+ let text;
21
+ try {
22
+ text = readFileSync(this.path, "utf8");
23
+ }
24
+ catch {
25
+ return [];
26
+ }
27
+ return text
28
+ .split("\n")
29
+ .filter((line) => line.trim() !== "")
30
+ .flatMap((line) => {
31
+ try {
32
+ return [JSON.parse(line)];
33
+ }
34
+ catch {
35
+ return [];
36
+ }
37
+ });
38
+ }
39
+ }
40
+ //# sourceMappingURL=journal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"journal.js","sourceRoot":"","sources":["../../src/sends/journal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AACjE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAqBhD;;;GAGG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,OAAe,EAAE,MAAyB,OAAO,CAAC,GAAG,EAAU,EAAE,CAC5F,IAAI,CAAC,YAAY,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,OAAO,QAAQ,CAAC,CAAA;AAEnG,MAAM,OAAO,WAAW;IACD;IAArB,YAAqB,IAAY;QAAZ,SAAI,GAAJ,IAAI,CAAQ;IAAG,CAAC;IAErC,MAAM,CAAC,KAAgB;QACrB,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;QAC/D,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;IAC1E,CAAC;IAED,qGAAqG;IACrG,OAAO;QACL,IAAI,IAAY,CAAA;QAChB,IAAI,CAAC;YACH,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;QACxC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAA;QACX,CAAC;QACD,OAAO,IAAI;aACR,KAAK,CAAC,IAAI,CAAC;aACX,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC;aACpC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;YAChB,IAAI,CAAC;gBACH,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAc,CAAC,CAAA;YACxC,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,EAAE,CAAA;YACX,CAAC;QACH,CAAC,CAAC,CAAA;IACN,CAAC;CACF"}
@@ -0,0 +1,29 @@
1
+ import type { Id } from "../domain/models.js";
2
+ export interface Recipient {
3
+ id: Id;
4
+ title: string | null;
5
+ addedAt: string;
6
+ }
7
+ /**
8
+ * A state file, not a setting: the configuration schema has deliberately no place for a chat id
9
+ * (`src/config.ts`), and this list is data about a profile rather than a preference.
10
+ */
11
+ export declare const recipientsPathFor: (profile: string, env?: NodeJS.ProcessEnv) => string;
12
+ /**
13
+ * The chats a profile may send to. **No file means the check is off**; a file with no chats in it
14
+ * means nowhere. Optional by the owner's ruling (`NEED-159`).
15
+ */
16
+ export declare class RecipientList {
17
+ #private;
18
+ readonly path: string;
19
+ constructor(path: string);
20
+ /** `undefined` when the list is off. A file that cannot be read refuses rather than opening up. */
21
+ read(): Recipient[] | undefined;
22
+ /** Whether it was new. */
23
+ add(recipient: Recipient): boolean;
24
+ /** The id or the title as it was stored; `undefined` when neither matched. */
25
+ remove(reference: string): Recipient | undefined;
26
+ /** Whether there was a list to turn off. */
27
+ off(): boolean;
28
+ }
29
+ //# sourceMappingURL=recipients.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recipients.d.ts","sourceRoot":"","sources":["../../src/sends/recipients.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,qBAAqB,CAAA;AAE7C,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,EAAE,CAAA;IACN,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,OAAO,EAAE,MAAM,CAAA;CAChB;AAED;;;GAGG;AACH,eAAO,MAAM,iBAAiB,GAAI,SAAS,MAAM,EAAE,MAAK,MAAM,CAAC,UAAwB,KAAG,MACsB,CAAA;AAEhH;;;GAGG;AACH,qBAAa,aAAa;;IACZ,QAAQ,CAAC,IAAI,EAAE,MAAM;gBAAZ,IAAI,EAAE,MAAM;IAEjC,mGAAmG;IACnG,IAAI,IAAI,SAAS,EAAE,GAAG,SAAS;IAe/B,0BAA0B;IAC1B,GAAG,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO;IAOlC,8EAA8E;IAC9E,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAUhD,4CAA4C;IAC5C,GAAG,IAAI,OAAO;CASf"}
@@ -0,0 +1,62 @@
1
+ import { existsSync, readFileSync, rmSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { CliError, resolvePaths, writeSecurely } from "@leemour/cli-core";
4
+ /**
5
+ * A state file, not a setting: the configuration schema has deliberately no place for a chat id
6
+ * (`src/config.ts`), and this list is data about a profile rather than a preference.
7
+ */
8
+ export const recipientsPathFor = (profile, env = process.env) => join(resolvePaths({ appName: "max-cli", prefix: "MAX", env }).state, "profiles", `${profile}.recipients.json`);
9
+ /**
10
+ * The chats a profile may send to. **No file means the check is off**; a file with no chats in it
11
+ * means nowhere. Optional by the owner's ruling (`NEED-159`).
12
+ */
13
+ export class RecipientList {
14
+ path;
15
+ constructor(path) {
16
+ this.path = path;
17
+ }
18
+ /** `undefined` when the list is off. A file that cannot be read refuses rather than opening up. */
19
+ read() {
20
+ if (!existsSync(this.path))
21
+ return undefined;
22
+ try {
23
+ const parsed = JSON.parse(readFileSync(this.path, "utf8"));
24
+ if (!Array.isArray(parsed.chats))
25
+ throw new Error("no `chats` array");
26
+ return parsed.chats;
27
+ }
28
+ catch (error) {
29
+ throw new CliError("configuration_error", `the recipient list ${this.path} cannot be read (${error instanceof Error ? error.message : String(error)}) — ` +
30
+ "fix the file or turn the list off with `max recipients off`");
31
+ }
32
+ }
33
+ /** Whether it was new. */
34
+ add(recipient) {
35
+ const chats = this.read() ?? [];
36
+ if (chats.some((chat) => chat.id === recipient.id))
37
+ return false;
38
+ this.#write([...chats, recipient]);
39
+ return true;
40
+ }
41
+ /** The id or the title as it was stored; `undefined` when neither matched. */
42
+ remove(reference) {
43
+ const chats = this.read() ?? [];
44
+ const wanted = reference.trim();
45
+ const gone = chats.find((chat) => chat.id === wanted) ??
46
+ chats.find((chat) => chat.title?.toLocaleLowerCase() === wanted.toLocaleLowerCase());
47
+ if (gone)
48
+ this.#write(chats.filter((chat) => chat !== gone));
49
+ return gone;
50
+ }
51
+ /** Whether there was a list to turn off. */
52
+ off() {
53
+ if (!existsSync(this.path))
54
+ return false;
55
+ rmSync(this.path);
56
+ return true;
57
+ }
58
+ #write(chats) {
59
+ writeSecurely(this.path, `${JSON.stringify({ chats }, null, 2)}\n`, 0o600);
60
+ }
61
+ }
62
+ //# sourceMappingURL=recipients.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recipients.js","sourceRoot":"","sources":["../../src/sends/recipients.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"adopt.d.ts","sourceRoot":"","sources":["../../src/session/adopt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAC7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE9C;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,UAAU,GAAU,QAAQ,SAAS,EAAE,OAAO,YAAY,EAAE,OAAO,MAAM,KAAG,OAAO,CAAC,IAAI,CASpG,CAAA"}
1
+ {"version":3,"file":"adopt.d.ts","sourceRoot":"","sources":["../../src/session/adopt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAC7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE9C;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,UAAU,GAAU,QAAQ,SAAS,EAAE,OAAO,YAAY,EAAE,OAAO,MAAM,KAAG,OAAO,CAAC,IAAI,CAUpG,CAAA"}
@@ -17,13 +17,14 @@
17
17
  * cannot be driven by a test — and this ordering is too expensive to hold on trust.
18
18
  */
19
19
  export const adoptToken = async (client, store, token) => {
20
+ const before = store.readToken();
20
21
  await client.connect({ token });
21
- // ⚠ **Only if the login did not already leave a better one.** MAX answers every login with a
22
- // fresh token and `connect` now keeps it (`MAX-11`); writing the pasted one here unconditionally
23
- // would replace that with the credential the person copied out of a browser, which is the older
24
- // of the two. The check also covers the case where the keyring write failed inside `connect`:
25
- // then there is nothing stored, and what was pasted is better than nothing.
26
- if (store.readToken() === undefined)
22
+ // ⚠ **Only if the login did not already leave a better one.** MAX answers a login with a fresh
23
+ // token when the one presented has aged, and `connect` keeps it (`MAX-11`); overwriting that here
24
+ // would put back the older credential. Comparing with what was stored before, rather than asking
25
+ // whether anything is stored, is what lets a new login replace an old session at all — until
26
+ // 2026-09-24 a profile that already held a token kept it, and the command still said "stored".
27
+ if (store.readToken() === before)
27
28
  store.writeToken(token);
28
29
  };
29
30
  //# sourceMappingURL=adopt.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"adopt.js","sourceRoot":"","sources":["../../src/session/adopt.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,EAAE,MAAiB,EAAE,KAAmB,EAAE,KAAa,EAAiB,EAAE;IACvG,MAAM,MAAM,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC,CAAA;IAE/B,6FAA6F;IAC7F,iGAAiG;IACjG,gGAAgG;IAChG,8FAA8F;IAC9F,4EAA4E;IAC5E,IAAI,KAAK,CAAC,SAAS,EAAE,KAAK,SAAS;QAAE,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAA;AAC9D,CAAC,CAAA"}
1
+ {"version":3,"file":"adopt.js","sourceRoot":"","sources":["../../src/session/adopt.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,EAAE,MAAiB,EAAE,KAAmB,EAAE,KAAa,EAAiB,EAAE;IACvG,MAAM,MAAM,GAAG,KAAK,CAAC,SAAS,EAAE,CAAA;IAChC,MAAM,MAAM,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC,CAAA;IAE/B,+FAA+F;IAC/F,kGAAkG;IAClG,iGAAiG;IACjG,6FAA6F;IAC7F,+FAA+F;IAC/F,IAAI,KAAK,CAAC,SAAS,EAAE,KAAK,MAAM;QAAE,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAA;AAC3D,CAAC,CAAA"}
@@ -0,0 +1,55 @@
1
+ import { type ChildProcess } from "node:child_process";
2
+ import type { Closeable } from "../deadline.js";
3
+ /**
4
+ * What `session start` needs from a browser. Injected in tests, which must never open a window on
5
+ * the owner's desktop — the real ones refuse inside the test sandbox.
6
+ */
7
+ export interface BrowserDoors {
8
+ /** Shows a page in whatever browser the system opens links with. */
9
+ open: (url: string) => Promise<void>;
10
+ /** Opens web.max.ru in a Chromium-family browser and waits for the page to be logged in. */
11
+ chromiumToken: (options: {
12
+ track: (closeable: Closeable) => void;
13
+ waitMs: number;
14
+ }) => Promise<string>;
15
+ }
16
+ export declare const realBrowser: BrowserDoors;
17
+ /**
18
+ * The QR page, served from `127.0.0.1` rather than written to a file: a browser installed as a
19
+ * snap cannot read our temporary directory, and a file would leave the link on disk. The path is
20
+ * random, so another local user guessing the port finds nothing.
21
+ */
22
+ export declare const serveQrPage: (link: string) => Promise<{
23
+ url: string;
24
+ } & Closeable>;
25
+ export declare const openUrl: (url: string) => Promise<void>;
26
+ /**
27
+ * Chrome, Chromium, Edge or Brave — any browser that speaks the DevTools protocol. `MAX_BROWSER`
28
+ * names another. A snap build is skipped: it keeps its own `/tmp`, so the profile we hand it would
29
+ * land where we cannot delete it.
30
+ */
31
+ export declare const findChromium: () => string | undefined;
32
+ /**
33
+ * web.max.ru logs itself in — it asks MAX for the QR code, or sends the SMS — in a real browser with
34
+ * a profile of its own, and we read the token it stores once it has one. MAX sees its own web
35
+ * client do the login, not our socket.
36
+ *
37
+ * ⚠ The profile holds a live session, so it is deleted on every way out: success, a closed window,
38
+ * `--timeout`, Ctrl-C.
39
+ */
40
+ export declare const tokenFromChromium: ({ track, waitMs, }: {
41
+ track: (closeable: Closeable) => void;
42
+ waitMs: number;
43
+ }) => Promise<string>;
44
+ export declare class ChromiumSession implements Closeable {
45
+ #private;
46
+ constructor(child: ChildProcess, profile: string, port: number, graceMs?: number);
47
+ waitForToken(waitMs: number): Promise<string>;
48
+ close(): Promise<void>;
49
+ }
50
+ /**
51
+ * The stored value is JSON holding the token, or the token itself — which one is not measured yet.
52
+ * Either way nothing here prints it.
53
+ */
54
+ export declare const tokenIn: (stored: string) => string | undefined;
55
+ //# sourceMappingURL=browser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../src/session/browser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAS,MAAM,oBAAoB,CAAA;AAW7D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAE/C;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,oEAAoE;IACpE,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACpC,4FAA4F;IAC5F,aAAa,EAAE,CAAC,OAAO,EAAE;QAAE,KAAK,EAAE,CAAC,SAAS,EAAE,SAAS,KAAK,IAAI,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;CACvG;AAED,eAAO,MAAM,WAAW,EAAE,YAGzB,CAAA;AAKD;;;;GAIG;AACH,eAAO,MAAM,WAAW,GAAU,MAAM,MAAM,KAAG,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAkCnF,CAAA;AASD,eAAO,MAAM,OAAO,GAAU,KAAK,MAAM,KAAG,OAAO,CAAC,IAAI,CAmBvD,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,YAAY,QAAO,MAAM,GAAG,SA0CxC,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,GAAU,oBAGrC;IACD,KAAK,EAAE,CAAC,SAAS,EAAE,SAAS,KAAK,IAAI,CAAA;IACrC,MAAM,EAAE,MAAM,CAAA;CACf,KAAG,OAAO,CAAC,MAAM,CAiCjB,CAAA;AAED,qBAAa,eAAgB,YAAW,SAAS;;gBAQnC,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,SAAQ;IAWzE,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAgBnD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAuCvB;AAED;;;GAGG;AACH,eAAO,MAAM,OAAO,GAAI,QAAQ,MAAM,KAAG,MAAM,GAAG,SAWjD,CAAA"}
@@ -0,0 +1,292 @@
1
+ import { spawn } from "node:child_process";
2
+ import { randomBytes } from "node:crypto";
3
+ import { existsSync, mkdtempSync, realpathSync, rmSync } from "node:fs";
4
+ import { createServer } from "node:http";
5
+ import { createServer as createTcpServer } from "node:net";
6
+ import { tmpdir } from "node:os";
7
+ import { delimiter, join } from "node:path";
8
+ import { setTimeout as delay } from "node:timers/promises";
9
+ import { CliError } from "@leemour/cli-core";
10
+ import qrcode from "qrcode-generator";
11
+ import { WebSocket } from "ws";
12
+ export const realBrowser = {
13
+ open: (url) => openUrl(url),
14
+ chromiumToken: (options) => tokenFromChromium(options),
15
+ };
16
+ const WEB_MAX = "https://web.max.ru/";
17
+ const AUTH_KEY = "__oneme_auth";
18
+ /**
19
+ * The QR page, served from `127.0.0.1` rather than written to a file: a browser installed as a
20
+ * snap cannot read our temporary directory, and a file would leave the link on disk. The path is
21
+ * random, so another local user guessing the port finds nothing.
22
+ */
23
+ export const serveQrPage = async (link) => {
24
+ const path = `/${randomBytes(16).toString("hex")}`;
25
+ const code = qrcode(0, "M");
26
+ code.addData(link);
27
+ code.make();
28
+ const page = qrHtml(code.createSvgTag({ cellSize: 8, margin: 4, scalable: true }));
29
+ const server = createServer((request, response) => {
30
+ if (request.url !== path) {
31
+ response.writeHead(404).end();
32
+ return;
33
+ }
34
+ response
35
+ .writeHead(200, {
36
+ "content-type": "text/html; charset=utf-8",
37
+ "cache-control": "no-store",
38
+ "referrer-policy": "no-referrer",
39
+ })
40
+ .end(page);
41
+ });
42
+ await new Promise((resolve, reject) => {
43
+ server.once("error", reject);
44
+ server.listen(0, "127.0.0.1", resolve);
45
+ });
46
+ const { port } = server.address();
47
+ return {
48
+ url: `http://127.0.0.1:${port}${path}`,
49
+ close: () => new Promise((resolve) => {
50
+ server.closeAllConnections();
51
+ server.close(() => resolve());
52
+ }),
53
+ };
54
+ };
55
+ const qrHtml = (svg) => `<!doctype html>
56
+ <html lang="ru"><head><meta charset="utf-8"><title>MAX — вход</title>
57
+ <style>body{font-family:system-ui,sans-serif;display:grid;place-items:center;min-height:100vh;margin:0;background:#fff;color:#111}
58
+ main{text-align:center;max-width:22rem}svg{width:18rem;height:18rem}</style></head>
59
+ <body><main>${svg}<p>Отсканируйте код приложением MAX на телефоне. Код действует около двух минут.</p>
60
+ <p>После входа эту вкладку можно закрыть.</p></main></body></html>`;
61
+ export const openUrl = async (url) => {
62
+ refuseInTests();
63
+ const [command, args] = process.platform === "darwin"
64
+ ? ["open", [url]]
65
+ : process.platform === "win32"
66
+ ? ["cmd", ["/c", "start", "", url]]
67
+ : ["xdg-open", [url]];
68
+ await new Promise((resolve, reject) => {
69
+ const child = spawn(command, args, { stdio: "ignore", detached: true, windowsHide: true });
70
+ child.once("error", () => reject(new CliError("configuration_error", "no browser could be opened here — use `session start token`")));
71
+ child.once("spawn", () => {
72
+ child.unref();
73
+ resolve();
74
+ });
75
+ });
76
+ };
77
+ /**
78
+ * Chrome, Chromium, Edge or Brave — any browser that speaks the DevTools protocol. `MAX_BROWSER`
79
+ * names another. A snap build is skipped: it keeps its own `/tmp`, so the profile we hand it would
80
+ * land where we cannot delete it.
81
+ */
82
+ export const findChromium = () => {
83
+ const named = process.env.MAX_BROWSER;
84
+ if (named)
85
+ return named;
86
+ if (process.platform === "darwin") {
87
+ return [
88
+ "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
89
+ "/Applications/Chromium.app/Contents/MacOS/Chromium",
90
+ "/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge",
91
+ "/Applications/Brave Browser.app/Contents/MacOS/Brave Browser",
92
+ ].find((path) => existsSync(path));
93
+ }
94
+ if (process.platform === "win32") {
95
+ const roots = [process.env.PROGRAMFILES, process.env["PROGRAMFILES(X86)"], process.env.LOCALAPPDATA];
96
+ const apps = [
97
+ "Google\\Chrome\\Application\\chrome.exe",
98
+ "Microsoft\\Edge\\Application\\msedge.exe",
99
+ "BraveSoftware\\Brave-Browser\\Application\\brave.exe",
100
+ ];
101
+ return apps
102
+ .flatMap((app) => roots.filter((root) => root !== undefined).map((root) => join(root, app)))
103
+ .find(existsSync);
104
+ }
105
+ const names = [
106
+ "google-chrome",
107
+ "google-chrome-stable",
108
+ "chromium",
109
+ "chromium-browser",
110
+ "microsoft-edge",
111
+ "microsoft-edge-stable",
112
+ "brave-browser",
113
+ ];
114
+ const dirs = (process.env.PATH ?? "").split(delimiter).filter(Boolean);
115
+ for (const name of names) {
116
+ for (const dir of dirs) {
117
+ const path = join(dir, name);
118
+ if (existsSync(path) && !realpathSync(path).startsWith("/snap/"))
119
+ return path;
120
+ }
121
+ }
122
+ return undefined;
123
+ };
124
+ /**
125
+ * web.max.ru logs itself in — it asks MAX for the QR code, or sends the SMS — in a real browser with
126
+ * a profile of its own, and we read the token it stores once it has one. MAX sees its own web
127
+ * client do the login, not our socket.
128
+ *
129
+ * ⚠ The profile holds a live session, so it is deleted on every way out: success, a closed window,
130
+ * `--timeout`, Ctrl-C.
131
+ */
132
+ export const tokenFromChromium = async ({ track, waitMs, }) => {
133
+ refuseInTests();
134
+ const binary = findChromium();
135
+ if (!binary) {
136
+ throw new CliError("configuration_error", "no Chrome, Chromium, Edge or Brave found — set MAX_BROWSER to one, or use `session start qr`");
137
+ }
138
+ const profile = mkdtempSync(join(tmpdir(), "max-login-"));
139
+ const port = await freePort();
140
+ const child = spawn(binary, [
141
+ `--user-data-dir=${profile}`,
142
+ `--remote-debugging-port=${port}`,
143
+ "--no-first-run",
144
+ "--no-default-browser-check",
145
+ WEB_MAX,
146
+ ], { stdio: "ignore" });
147
+ const browser = new ChromiumSession(child, profile, port);
148
+ track(browser);
149
+ const stopSignals = closeOnSignal(browser);
150
+ try {
151
+ return await browser.waitForToken(waitMs);
152
+ }
153
+ finally {
154
+ stopSignals();
155
+ await browser.close();
156
+ }
157
+ };
158
+ export class ChromiumSession {
159
+ #child;
160
+ #profile;
161
+ #port;
162
+ #exited;
163
+ #graceMs;
164
+ #closing;
165
+ constructor(child, profile, port, graceMs = 5_000) {
166
+ this.#child = child;
167
+ this.#graceMs = graceMs;
168
+ this.#profile = profile;
169
+ this.#port = port;
170
+ this.#exited = new Promise((resolve) => {
171
+ child.once("exit", () => resolve());
172
+ child.once("error", () => resolve());
173
+ });
174
+ }
175
+ async waitForToken(waitMs) {
176
+ const deadline = Date.now() + waitMs;
177
+ let running = true;
178
+ void this.#exited.then(() => {
179
+ running = false;
180
+ });
181
+ while (Date.now() < deadline) {
182
+ if (!running)
183
+ throw new CliError("cancelled", "the browser was closed before the login finished");
184
+ const token = await this.#storedToken().catch(() => undefined);
185
+ if (token)
186
+ return token;
187
+ await delay(1_000);
188
+ }
189
+ throw new CliError("timeout", `nobody logged in within ${Math.round(waitMs / 60_000)} minutes`);
190
+ }
191
+ close() {
192
+ this.#closing ??= this.#shutdown();
193
+ return this.#closing;
194
+ }
195
+ async #shutdown() {
196
+ // Chrome writes to the profile while it shuts down; removing it first leaves half of it behind.
197
+ const version = await this.#json("/json/version").catch(() => undefined);
198
+ const endpoint = typeof version?.webSocketDebuggerUrl === "string" ? version.webSocketDebuggerUrl : undefined;
199
+ if (endpoint)
200
+ await evaluateOver(endpoint, "Browser.close", {}).catch(() => undefined);
201
+ const exited = await Promise.race([this.#exited.then(() => true), delay(this.#graceMs).then(() => false)]);
202
+ if (!exited && this.#child.pid !== undefined) {
203
+ this.#child.kill();
204
+ await Promise.race([this.#exited, delay(2_000)]);
205
+ }
206
+ rmSync(this.#profile, { recursive: true, force: true, maxRetries: 3 });
207
+ }
208
+ async #storedToken() {
209
+ const targets = await this.#json("/json/list");
210
+ const page = (Array.isArray(targets) ? targets : []).find((target) => target?.type === "page" && typeof target.url === "string" && target.url.startsWith(WEB_MAX));
211
+ if (typeof page?.webSocketDebuggerUrl !== "string")
212
+ return undefined;
213
+ const result = await evaluateOver(page.webSocketDebuggerUrl, "Runtime.evaluate", {
214
+ expression: `localStorage.getItem(${JSON.stringify(AUTH_KEY)})`,
215
+ returnByValue: true,
216
+ });
217
+ const stored = result?.result?.value;
218
+ return typeof stored === "string" ? tokenIn(stored) : undefined;
219
+ }
220
+ // biome-ignore lint/suspicious/noExplicitAny: the DevTools answers are read defensively, field by field.
221
+ async #json(path) {
222
+ const response = await fetch(`http://127.0.0.1:${this.#port}${path}`, { signal: AbortSignal.timeout(2_000) });
223
+ return await response.json();
224
+ }
225
+ }
226
+ /**
227
+ * The stored value is JSON holding the token, or the token itself — which one is not measured yet.
228
+ * Either way nothing here prints it.
229
+ */
230
+ export const tokenIn = (stored) => {
231
+ try {
232
+ const parsed = JSON.parse(stored);
233
+ if (typeof parsed === "object" && parsed !== null && "token" in parsed) {
234
+ const token = parsed.token;
235
+ return typeof token === "string" && token !== "" ? token : undefined;
236
+ }
237
+ return typeof parsed === "string" && parsed !== "" ? parsed : undefined;
238
+ }
239
+ catch {
240
+ return stored === "" ? undefined : stored;
241
+ }
242
+ };
243
+ // biome-ignore lint/suspicious/noExplicitAny: see #json.
244
+ const evaluateOver = (endpoint, method, params) => new Promise((resolve, reject) => {
245
+ const socket = new WebSocket(endpoint);
246
+ const timer = setTimeout(() => {
247
+ socket.terminate();
248
+ reject(new Error("the browser did not answer"));
249
+ }, 5_000);
250
+ socket.once("error", (error) => {
251
+ clearTimeout(timer);
252
+ reject(error);
253
+ });
254
+ socket.once("open", () => socket.send(JSON.stringify({ id: 1, method, params })));
255
+ socket.on("message", (data) => {
256
+ const message = JSON.parse(String(data));
257
+ if (message.id !== 1)
258
+ return;
259
+ clearTimeout(timer);
260
+ socket.close();
261
+ resolve(message.result);
262
+ });
263
+ });
264
+ /**
265
+ * Node's default Ctrl-C exits without running a `finally`, which would leave the browser open and
266
+ * its logged-in profile on disk. Returns the function that removes the handlers again.
267
+ */
268
+ const closeOnSignal = (closeable) => {
269
+ const onSignal = () => {
270
+ void closeable.close().finally(() => process.exit(130));
271
+ };
272
+ // `on`, not `once`: a second Ctrl-C during the shutdown would otherwise exit before the profile goes.
273
+ process.on("SIGINT", onSignal);
274
+ process.on("SIGTERM", onSignal);
275
+ return () => {
276
+ process.off("SIGINT", onSignal);
277
+ process.off("SIGTERM", onSignal);
278
+ };
279
+ };
280
+ const freePort = () => new Promise((resolve, reject) => {
281
+ const probe = createTcpServer();
282
+ probe.once("error", reject);
283
+ probe.listen(0, "127.0.0.1", () => {
284
+ const { port } = probe.address();
285
+ probe.close(() => resolve(port));
286
+ });
287
+ });
288
+ const refuseInTests = () => {
289
+ if (process.env.MAX_TEST_SANDBOX)
290
+ throw new Error("a test reached the real browser — inject BrowserDoors");
291
+ };
292
+ //# sourceMappingURL=browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.js","sourceRoot":"","sources":["../../src/session/browser.ts"],"names":[],"mappings":"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"}
@@ -35,5 +35,7 @@ export interface SessionOptions {
35
35
  * diagnostic hook in `MaxClient` saw nothing of the two requests every single invocation makes,
36
36
  * and `max chats list` answers from the LOGIN response without sending anything else.
37
37
  */
38
+ /** How many chats LOGIN is asked for. MAX answers the newest that many, newest first (`FIND-80`). */
39
+ export declare const LOGIN_CHATS = 40;
38
40
  export declare const startSession: (invoke: Invoke, { token, deviceId, chatsCount, sync }: SessionOptions) => Promise<Payload>;
39
41
  //# sourceMappingURL=handshake.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"handshake.d.ts","sourceRoot":"","sources":["../../src/session/handshake.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kCAAkC,CAAA;AAC9D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAA;AAInD,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,6FAA6F;IAC7F,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;;;;;;;;;OAWG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,YAAY,GACvB,QAAQ,MAAM,EACd,uCAAgD,cAAc,KAC7D,OAAO,CAAC,OAAO,CAajB,CAAA"}
1
+ {"version":3,"file":"handshake.d.ts","sourceRoot":"","sources":["../../src/session/handshake.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kCAAkC,CAAA;AAC9D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAA;AAInD,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,6FAA6F;IAC7F,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;;;;;;;;;OAWG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED;;;;;;;;;;;;;;;GAeG;AACH,qGAAqG;AACrG,eAAO,MAAM,WAAW,KAAK,CAAA;AAE7B,eAAO,MAAM,YAAY,GACvB,QAAQ,MAAM,EACd,uCAAyD,cAAc,KACtE,OAAO,CAAC,OAAO,CAajB,CAAA"}
@@ -16,7 +16,9 @@ import { sessionInit, sessionLogin } from "../spec/operations/session.js";
16
16
  * diagnostic hook in `MaxClient` saw nothing of the two requests every single invocation makes,
17
17
  * and `max chats list` answers from the LOGIN response without sending anything else.
18
18
  */
19
- export const startSession = async (invoke, { token, deviceId, chatsCount = 40, sync = 0 }) => {
19
+ /** How many chats LOGIN is asked for. MAX answers the newest that many, newest first (`FIND-80`). */
20
+ export const LOGIN_CHATS = 40;
21
+ export const startSession = async (invoke, { token, deviceId, chatsCount = LOGIN_CHATS, sync = 0 }) => {
20
22
  await invoke(sessionInit, { userAgent: WEB_USER_AGENT, deviceId });
21
23
  return await invoke(sessionLogin, {
22
24
  token,
@@ -1 +1 @@
1
- {"version":3,"file":"handshake.js","sourceRoot":"","sources":["../../src/session/handshake.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACpD,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAA;AAsBzE;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,EAC/B,MAAc,EACd,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,GAAG,EAAE,EAAE,IAAI,GAAG,CAAC,EAAkB,EAC5C,EAAE;IACpB,MAAM,MAAM,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,cAAc,EAAE,QAAQ,EAAE,CAAC,CAAA;IAElE,OAAO,MAAM,MAAM,CAAC,YAAY,EAAE;QAChC,KAAK;QACL,8FAA8F;QAC9F,WAAW,EAAE,KAAK;QAClB,UAAU;QACV,SAAS,EAAE,IAAI;QACf,YAAY,EAAE,IAAI;QAClB,YAAY,EAAE,IAAI;QAClB,UAAU,EAAE,IAAI;KACjB,CAAC,CAAA;AACJ,CAAC,CAAA"}
1
+ {"version":3,"file":"handshake.js","sourceRoot":"","sources":["../../src/session/handshake.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACpD,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAA;AAsBzE;;;;;;;;;;;;;;;GAeG;AACH,qGAAqG;AACrG,MAAM,CAAC,MAAM,WAAW,GAAG,EAAE,CAAA;AAE7B,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,EAC/B,MAAc,EACd,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,GAAG,WAAW,EAAE,IAAI,GAAG,CAAC,EAAkB,EACrD,EAAE;IACpB,MAAM,MAAM,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,cAAc,EAAE,QAAQ,EAAE,CAAC,CAAA;IAElE,OAAO,MAAM,MAAM,CAAC,YAAY,EAAE;QAChC,KAAK;QACL,8FAA8F;QAC9F,WAAW,EAAE,KAAK;QAClB,UAAU;QACV,SAAS,EAAE,IAAI;QACf,YAAY,EAAE,IAAI;QAClB,YAAY,EAAE,IAAI;QAClB,UAAU,EAAE,IAAI;KACjB,CAAC,CAAA;AACJ,CAAC,CAAA"}
@@ -0,0 +1,20 @@
1
+ import type { WireClient } from "../generated/client.generated.js";
2
+ export interface SecondFactor {
3
+ /** Asked only when the account has a cloud password; `again` after a wrong one. */
4
+ askPassword: (hint: string | undefined, again: boolean) => Promise<string>;
5
+ }
6
+ export interface QrLogin extends SecondFactor {
7
+ /** Put the code where a phone can scan it. Resolves once it is shown, not once it is scanned. */
8
+ show: (link: string) => Promise<void>;
9
+ now?: () => number;
10
+ sleep?: (ms: number) => Promise<void>;
11
+ }
12
+ /**
13
+ * The login MAX's web client does itself when it shows a QR code: ask for a code, wait until a phone
14
+ * approves it, then exchange it for a token. Shapes from PyMax 2.4.1 (`auth/qr.py`), not measured.
15
+ *
16
+ * One code per run: an expired one is an error rather than a fresh code, so a person who walked
17
+ * away does not come back to a loop that has been asking MAX for codes all along.
18
+ */
19
+ export declare const tokenByQr: (wire: WireClient, { show, askPassword, now, sleep }: QrLogin) => Promise<string>;
20
+ //# sourceMappingURL=login.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/session/login.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAA;AAGlE,MAAM,WAAW,YAAY;IAC3B,mFAAmF;IACnF,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;CAC3E;AAED,MAAM,WAAW,OAAQ,SAAQ,YAAY;IAC3C,iGAAiG;IACjG,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACrC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CACtC;AAED;;;;;;GAMG;AACH,eAAO,MAAM,SAAS,GACpB,MAAM,UAAU,EAChB,mCAAsD,OAAO,KAC5D,OAAO,CAAC,MAAM,CAiBhB,CAAA"}