shadok-ai 0.17.2 → 0.17.3

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.
@@ -4,53 +4,64 @@
4
4
  * its privilege-dropped group agents (they have no keychain). This module drives
5
5
  * `claude setup-token` and hands the minted token to a server-supplied store.
6
6
  *
7
- * Twin of `src/claude-auth.ts` (the sign-in flow) with ONE measured difference,
8
- * and it is load-bearing: `claude setup-token` is `isatty`-gated. Run with plain
9
- * pipes it prints NOTHING (verified 2026-11-03, v2.1.317) — so, unlike
10
- * `auth login`, it must be driven on a PTY. On a PTY it renders a small TUI: a
11
- * banner, "Browser didn't open? Use the url below…", the URL inside an OSC-8
12
- * hyperlink (`ESC ] 8 ; id=… ; <url> ST`), a "Paste code here if prompted >"
13
- * prompt, and — after a valid code — the token (`sk-ant-oat01-…`).
7
+ * Driven inside a detached **tmux** session — the same engine as every agent
8
+ * (`src/tmux.ts`, `TmuxPilot`). tmux owns a real terminal, so the `isatty` gate
9
+ * `setup-token` enforces is satisfied, AND we read the terminal **already
10
+ * rendered** (`capture-pane -p`) instead of reverse-engineering a raw
11
+ * OSC-8/CSI escape stream. That removed an entire class of parsing fragility —
12
+ * the exact class that made the first (node-pty) implementation silently miss
13
+ * the minted token at the success screen.
14
14
  *
15
- * The parsers below are pure and fed the accumulated PTY stream (CSI cursor
16
- * positioning + OSC-8 links). The token value must never be logged or returned;
17
- * the flow (added alongside) stores it server-side and reports only ok/err.
15
+ * Behaviours measured live against the real CLI (v2.1.317, 2026-11-03), driving
16
+ * it through tmux exactly as this module does:
17
+ * - The URL prints as plain text on its own line (pane set wide so it never
18
+ * wraps): "Browser didn't open? Use the url below…", then the authorize URL.
19
+ * - The code box is a MASKED field ("Paste code here if prompted > *****"), so
20
+ * we wait for the typed code to land before pressing Enter.
21
+ * - A bad code renders "OAuth error: Invalid code. Please make sure the full
22
+ * code was copied" followed by "Press Enter to retry" — the retry needs an
23
+ * explicit Enter to return to the paste prompt (it does not re-prompt alone).
24
+ *
25
+ * The token value must never be logged, returned, or surfaced in an error: the
26
+ * flow stores it server-side and reports only ok/err.
18
27
  *
19
28
  * See docs/superpowers/specs/2026-11-03-mt-token-provisioning-design.md.
20
29
  */
21
30
  /**
22
- * Strip terminal escapes from a PTY chunk: OSC-8 hyperlinks (ST- or
23
- * BEL-terminated), other OSC sequences, CSI sequences (including the private
24
- * `?`/`<`/`>`/`=` parameter bytes this TUI uses), and the two-char escapes.
25
- * What remains is the visible text — which is what the parsers match on.
31
+ * Strip terminal escapes. `capture-pane -p` is already rendered plain text, so
32
+ * this is a defensive no-op there — but it also lets the parsers accept a raw
33
+ * stream (OSC-8 links, CSI cursor moves, two-char escapes) in tests and if a
34
+ * caller ever feeds one.
26
35
  */
27
36
  export declare function stripTokenEscapes(s: string): string;
28
37
  /**
29
- * Pure: the OAuth URL, pulled from the OSC-8 hyperlink TARGET (the URL is the
30
- * link target, not "visit:" prose as in `auth login`). Falls back to a bare
31
- * `https://` in the stripped visible text if no OSC-8 is present. Null until the
32
- * link has been printed.
38
+ * Pure: the OAuth URL. From the rendered pane it is a bare `https://` on its own
39
+ * line; the OSC-8 target form is still accepted (a raw stream, or a future CLI
40
+ * that emits a hyperlink). Null until the link has been printed.
33
41
  */
34
42
  export declare function parseSetupTokenUrl(chunk: string): string | null;
35
43
  /**
36
- * Pure: the refusal the CLI printed for a submitted code, if any. Like
37
- * `claude-auth.ts`, there is deliberately NO guessed success string — success is
38
- * the token appearing plus the child settling (see the flow).
44
+ * Pure: the refusal the CLI printed for a submitted code, if any. There is
45
+ * deliberately NO guessed success string — success is the token appearing (see
46
+ * the flow). The real wording is "OAuth error: Invalid code. …"; matching the
47
+ * "Invalid code" substring is enough and robust to the surrounding text.
39
48
  */
40
49
  export declare function parseSetupTokenOutcome(chunk: string): "invalid-code" | null;
41
50
  /**
42
- * Pure: the minted token (`sk-ant-oat01-…`) from the stripped stream, or null.
43
- * Stripping first rejoins a token that the terminal split with cursor-move
44
- * escapes. The flow MUST spawn the PTY wide enough that the token never
45
- * line-wraps (a hard wrap inserts a real newline no strip can undo).
51
+ * Pure: the minted token (`sk-ant-oat01-…`) from the rendered text, or null.
52
+ * Stripping first rejoins a token a raw stream split with cursor escapes; from a
53
+ * `capture-pane` the text is already clean. The flow renders the pane wide
54
+ * enough that the ~108-char token never line-wraps (a hard wrap inserts a real
55
+ * newline no strip can undo).
46
56
  */
47
57
  export declare function parseSetupToken(chunk: string): string | null;
48
58
  export declare function setupTokenPending(): boolean;
49
59
  export declare function cancelSetupToken(): void;
50
60
  /**
51
- * Start `claude setup-token` on a PTY and resolve its OAuth URL. Reuses a live
52
- * flow that already printed a URL (a reload or a second door must not kill the
53
- * link the operator is looking at — each flow carries its own PKCE challenge).
61
+ * Start `claude setup-token` in a detached tmux session and resolve its OAuth
62
+ * URL. Reuses a live flow that already printed a URL (a reload or a second door
63
+ * must not kill the link the operator is looking at — each flow carries its own
64
+ * PKCE challenge).
54
65
  */
55
66
  export declare function startSetupToken(): Promise<{
56
67
  url: string;
@@ -58,10 +69,11 @@ export declare function startSetupToken(): Promise<{
58
69
  error: string;
59
70
  }>;
60
71
  /**
61
- * Submit the pasted code. Success = the token appears AND the child settles —
62
- * never a guessed success string (the invalid-code wording is the only one the
63
- * CLI gives us). On success the token is handed to `store` and the flow is torn
64
- * down; the token is NEVER returned, logged, or surfaced in an error.
72
+ * Submit the pasted code. Types it into the masked box, waits for it to land,
73
+ * presses Enter, then watches the rendered pane for the token or the
74
+ * invalid-code refusal. Success = the token appears; it is handed to `store`
75
+ * and the flow is torn down. The token is NEVER returned, logged, or surfaced
76
+ * in an error.
65
77
  */
66
78
  export declare function submitSetupTokenCode(code: string, store: (token: string) => void): Promise<{
67
79
  ok: true;
@@ -1,47 +1,53 @@
1
- import pty from "node-pty";
1
+ import { execFileSync } from "node:child_process";
2
2
  import { claudeCommand } from "./claude-bin.js";
3
+ import { tmuxAvailable, tmuxHasSession, tmuxKillSession } from "./tmux.js";
3
4
  /**
4
5
  * In-cockpit provisioning of the long-lived subscription token
5
6
  * (`MT_CLAUDE_OAUTH_TOKEN`), the credential a multi-tenant instance injects into
6
7
  * its privilege-dropped group agents (they have no keychain). This module drives
7
8
  * `claude setup-token` and hands the minted token to a server-supplied store.
8
9
  *
9
- * Twin of `src/claude-auth.ts` (the sign-in flow) with ONE measured difference,
10
- * and it is load-bearing: `claude setup-token` is `isatty`-gated. Run with plain
11
- * pipes it prints NOTHING (verified 2026-11-03, v2.1.317) — so, unlike
12
- * `auth login`, it must be driven on a PTY. On a PTY it renders a small TUI: a
13
- * banner, "Browser didn't open? Use the url below…", the URL inside an OSC-8
14
- * hyperlink (`ESC ] 8 ; id=… ; <url> ST`), a "Paste code here if prompted >"
15
- * prompt, and — after a valid code — the token (`sk-ant-oat01-…`).
10
+ * Driven inside a detached **tmux** session — the same engine as every agent
11
+ * (`src/tmux.ts`, `TmuxPilot`). tmux owns a real terminal, so the `isatty` gate
12
+ * `setup-token` enforces is satisfied, AND we read the terminal **already
13
+ * rendered** (`capture-pane -p`) instead of reverse-engineering a raw
14
+ * OSC-8/CSI escape stream. That removed an entire class of parsing fragility —
15
+ * the exact class that made the first (node-pty) implementation silently miss
16
+ * the minted token at the success screen.
16
17
  *
17
- * The parsers below are pure and fed the accumulated PTY stream (CSI cursor
18
- * positioning + OSC-8 links). The token value must never be logged or returned;
19
- * the flow (added alongside) stores it server-side and reports only ok/err.
18
+ * Behaviours measured live against the real CLI (v2.1.317, 2026-11-03), driving
19
+ * it through tmux exactly as this module does:
20
+ * - The URL prints as plain text on its own line (pane set wide so it never
21
+ * wraps): "Browser didn't open? Use the url below…", then the authorize URL.
22
+ * - The code box is a MASKED field ("Paste code here if prompted > *****"), so
23
+ * we wait for the typed code to land before pressing Enter.
24
+ * - A bad code renders "OAuth error: Invalid code. Please make sure the full
25
+ * code was copied" followed by "Press Enter to retry" — the retry needs an
26
+ * explicit Enter to return to the paste prompt (it does not re-prompt alone).
27
+ *
28
+ * The token value must never be logged, returned, or surfaced in an error: the
29
+ * flow stores it server-side and reports only ok/err.
20
30
  *
21
31
  * See docs/superpowers/specs/2026-11-03-mt-token-provisioning-design.md.
22
32
  */
33
+ // ─── Pure parsers (fed the rendered pane text) ───────────────────────────────
23
34
  /**
24
- * Strip terminal escapes from a PTY chunk: OSC-8 hyperlinks (ST- or
25
- * BEL-terminated), other OSC sequences, CSI sequences (including the private
26
- * `?`/`<`/`>`/`=` parameter bytes this TUI uses), and the two-char escapes.
27
- * What remains is the visible text — which is what the parsers match on.
35
+ * Strip terminal escapes. `capture-pane -p` is already rendered plain text, so
36
+ * this is a defensive no-op there — but it also lets the parsers accept a raw
37
+ * stream (OSC-8 links, CSI cursor moves, two-char escapes) in tests and if a
38
+ * caller ever feeds one.
28
39
  */
29
40
  export function stripTokenEscapes(s) {
30
41
  return s
31
- // OSC-8 open (params ; url) and close (;;), ST or BEL terminated.
32
42
  .replace(/\x1b\]8;[^;]*;[^\x07\x1b]*(?:\x07|\x1b\\)/g, "")
33
- // Any other OSC (window title, etc.), ST or BEL terminated.
34
43
  .replace(/\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)/g, "")
35
- // CSI: ESC [ <params 0x30-3f> <intermediates 0x20-2f> <final 0x40-7e>.
36
44
  .replace(/\x1b\[[\x30-\x3f]*[\x20-\x2f]*[\x40-\x7e]/g, "")
37
- // Two-char escapes (ESC 7/8 save/restore, ESC =/> keypad, etc.).
38
45
  .replace(/\x1b[=>78MD]/g, "");
39
46
  }
40
47
  /**
41
- * Pure: the OAuth URL, pulled from the OSC-8 hyperlink TARGET (the URL is the
42
- * link target, not "visit:" prose as in `auth login`). Falls back to a bare
43
- * `https://` in the stripped visible text if no OSC-8 is present. Null until the
44
- * link has been printed.
48
+ * Pure: the OAuth URL. From the rendered pane it is a bare `https://` on its own
49
+ * line; the OSC-8 target form is still accepted (a raw stream, or a future CLI
50
+ * that emits a hyperlink). Null until the link has been printed.
45
51
  */
46
52
  export function parseSetupTokenUrl(chunk) {
47
53
  const osc = chunk.match(/\x1b\]8;[^;]*;(https:\/\/[^\x07\x1b]+?)(?:\x07|\x1b\\)/);
@@ -51,189 +57,196 @@ export function parseSetupTokenUrl(chunk) {
51
57
  return bare ? bare[0] : null;
52
58
  }
53
59
  /**
54
- * Pure: the refusal the CLI printed for a submitted code, if any. Like
55
- * `claude-auth.ts`, there is deliberately NO guessed success string — success is
56
- * the token appearing plus the child settling (see the flow).
60
+ * Pure: the refusal the CLI printed for a submitted code, if any. There is
61
+ * deliberately NO guessed success string — success is the token appearing (see
62
+ * the flow). The real wording is "OAuth error: Invalid code. …"; matching the
63
+ * "Invalid code" substring is enough and robust to the surrounding text.
57
64
  */
58
65
  export function parseSetupTokenOutcome(chunk) {
59
66
  return /Invalid code/i.test(stripTokenEscapes(chunk)) ? "invalid-code" : null;
60
67
  }
61
68
  /**
62
- * Pure: the minted token (`sk-ant-oat01-…`) from the stripped stream, or null.
63
- * Stripping first rejoins a token that the terminal split with cursor-move
64
- * escapes. The flow MUST spawn the PTY wide enough that the token never
65
- * line-wraps (a hard wrap inserts a real newline no strip can undo).
69
+ * Pure: the minted token (`sk-ant-oat01-…`) from the rendered text, or null.
70
+ * Stripping first rejoins a token a raw stream split with cursor escapes; from a
71
+ * `capture-pane` the text is already clean. The flow renders the pane wide
72
+ * enough that the ~108-char token never line-wraps (a hard wrap inserts a real
73
+ * newline no strip can undo).
66
74
  */
67
75
  export function parseSetupToken(chunk) {
68
76
  const m = stripTokenEscapes(chunk).match(/sk-ant-oat01-[A-Za-z0-9_-]+/);
69
77
  return m ? m[0] : null;
70
78
  }
71
- /** The OAuth URL expires anyway; a child holding the PTY forever is worse. */
79
+ // ─── The flow (impure, tmux-driven) ──────────────────────────────────────────
80
+ /** The OAuth URL expires anyway; a child holding the session forever is worse. */
72
81
  const FLOW_IDLE_MS = 10 * 60_000;
73
- /** Wide enough that the ~100-char token never line-wraps (a hard wrap inserts a
74
- * real newline no escape-strip can undo). */
75
- const PTY_COLS = 400;
76
- /**
77
- * ONE flow at a time for the whole instance (the credential is machine-global),
78
- * shared by the web card and Telegram exactly like the sign-in flow — a code
79
- * pasted from either finishes the other's.
80
- */
82
+ /** Wide enough that neither the ~346-char URL nor the ~108-char token wraps (a
83
+ * hard wrap inserts a real newline no escape-strip can undo). */
84
+ const PANE_COLS = 400;
85
+ const PANE_ROWS = 50;
86
+ /** One flow at a time for the whole instance — the tmux session name is fixed. */
87
+ const SESSION = "sk-mttoken";
81
88
  let flow = null;
82
- export function setupTokenPending() {
83
- return flow !== null && !flow.ended;
89
+ function tmux(args, input) {
90
+ return execFileSync("tmux", args, {
91
+ encoding: "utf8",
92
+ input,
93
+ timeout: 10_000,
94
+ maxBuffer: 8 * 1024 * 1024,
95
+ stdio: ["pipe", "pipe", "ignore"],
96
+ });
84
97
  }
85
- export function cancelSetupToken() {
86
- if (!flow)
87
- return;
88
- clearTimeout(flow.timer);
98
+ /** The rendered pane. `scrollback` also pulls history, so a line that scrolled
99
+ * off the visible screen (e.g. the token above a trailing prompt) is caught. */
100
+ function capture(scrollback = false) {
89
101
  try {
90
- flow.proc.kill();
102
+ const args = ["capture-pane", "-t", SESSION, "-p"];
103
+ if (scrollback)
104
+ args.push("-S", "-");
105
+ return tmux(args);
91
106
  }
92
107
  catch {
93
- /* already gone */
108
+ return "";
94
109
  }
110
+ }
111
+ function sleep(ms) {
112
+ return new Promise((r) => setTimeout(r, ms));
113
+ }
114
+ export function setupTokenPending() {
115
+ return flow !== null && !flow.ended && tmuxHasSession(SESSION);
116
+ }
117
+ export function cancelSetupToken() {
118
+ if (flow)
119
+ clearTimeout(flow.timer);
120
+ tmuxKillSession(SESSION);
95
121
  flow = null;
96
122
  }
97
123
  /**
98
- * Start `claude setup-token` on a PTY and resolve its OAuth URL. Reuses a live
99
- * flow that already printed a URL (a reload or a second door must not kill the
100
- * link the operator is looking at — each flow carries its own PKCE challenge).
124
+ * Start `claude setup-token` in a detached tmux session and resolve its OAuth
125
+ * URL. Reuses a live flow that already printed a URL (a reload or a second door
126
+ * must not kill the link the operator is looking at — each flow carries its own
127
+ * PKCE challenge).
101
128
  */
102
129
  export async function startSetupToken() {
103
- if (flow && !flow.ended && flow.url)
130
+ if (flow && !flow.ended && flow.url && tmuxHasSession(SESSION))
104
131
  return { url: flow.url };
105
132
  cancelSetupToken();
106
- let proc;
133
+ if (!tmuxAvailable())
134
+ return { error: "tmux is not available on this host — it is required to provision the token" };
135
+ // Build the command the way TmuxPilot does: `env` — unsetting any inherited
136
+ // CLAUDE*/CLAUDECODE/AI_AGENT vars (a parent session's token or child-session
137
+ // marker must not reach this nested claude) — then the assignments and the
138
+ // binary, each token single-quoted so values with specials are safe. BROWSER
139
+ // is neutralised so the CLI never tries to open a tab on the SERVER's machine.
140
+ const bin = claudeCommand();
141
+ const unset = Object.keys(process.env)
142
+ .filter((k) => /^(CLAUDE|CLAUDECODE|AI_AGENT)/.test(k))
143
+ .flatMap((k) => ["-u", k]);
144
+ const cmd = ["env", ...unset, "TERM=xterm-256color", "BROWSER=/usr/bin/true", bin, "setup-token"]
145
+ .map((a) => `'${String(a).replace(/'/g, "'\\''")}'`)
146
+ .join(" ");
107
147
  try {
108
- proc = pty.spawn(claudeCommand(), ["setup-token"], {
109
- name: "xterm-256color",
110
- cols: PTY_COLS,
111
- rows: 40,
112
- cwd: process.cwd(),
113
- // Neutralise BROWSER so the CLI never opens a tab on the SERVER's machine.
114
- env: { ...process.env, BROWSER: "/usr/bin/true" },
115
- });
148
+ tmuxKillSession(SESSION); // clear any stale session of the same name
149
+ tmux(["new-session", "-d", "-s", SESSION, "-x", String(PANE_COLS), "-y", String(PANE_ROWS), "-c", process.cwd(), cmd]);
116
150
  }
117
151
  catch (e) {
118
152
  return { error: "could not start claude setup-token: " + (e instanceof Error ? e.message : String(e)) };
119
153
  }
120
- const f = {
121
- proc,
122
- url: null,
123
- out: "",
124
- pending: null,
125
- ended: false,
126
- timer: setTimeout(() => cancelSetupToken(), FLOW_IDLE_MS),
127
- };
154
+ const f = { url: null, ended: false, timer: setTimeout(() => cancelSetupToken(), FLOW_IDLE_MS) };
128
155
  flow = f;
129
- const settle = (v) => {
130
- const done = f.pending;
131
- f.pending = null;
132
- done?.(v);
133
- };
134
- // `all` accumulates ONLY until the URL is found (the URL can span PTY chunks),
135
- // then is dropped — so the later token never lands in a buffer we do not
136
- // scrub. The token flows solely into `f.out` (scrubbed on settle), and only
137
- // while `f.pending` is set, i.e. strictly after the URL and the code.
138
- let all = "";
139
- proc.onData((d) => {
140
- if (!f.url) {
141
- all += d;
142
- const u = parseSetupTokenUrl(all);
143
- if (u) {
144
- f.url = u;
145
- all = ""; // done with it — never hold the minted token here
146
- }
147
- }
148
- if (f.pending) {
149
- f.out += d;
150
- const tok = parseSetupToken(f.out);
151
- if (tok) {
152
- settle({ kind: "success", token: tok });
153
- }
154
- else if (parseSetupTokenOutcome(f.out) === "invalid-code") {
155
- settle({ kind: "invalid-code" });
156
- }
156
+ const deadline = Date.now() + 30_000;
157
+ while (Date.now() < deadline) {
158
+ if (flow !== f || f.ended)
159
+ return { error: "the setup-token process ended before printing a URL" };
160
+ if (!tmuxHasSession(SESSION)) {
161
+ cancelSetupToken();
162
+ return { error: "the setup-token process ended before printing a URL" };
157
163
  }
158
- });
159
- proc.onExit(() => {
160
- f.ended = true;
161
- if (f.pending) {
162
- const tok = parseSetupToken(f.out);
163
- settle(tok ? { kind: "success", token: tok } : { kind: "ended" });
164
+ const url = parseSetupTokenUrl(capture());
165
+ if (url) {
166
+ f.url = url;
167
+ return { url };
164
168
  }
165
- });
166
- return new Promise((resolve) => {
167
- const deadline = setTimeout(() => {
168
- cancelSetupToken();
169
- resolve({ error: "claude setup-token printed no URL within 30s" });
170
- }, 30_000);
171
- const poll = setInterval(() => {
172
- if (f.url) {
173
- clearInterval(poll);
174
- clearTimeout(deadline);
175
- resolve({ url: f.url });
176
- }
177
- else if (flow !== f || f.ended) {
178
- clearInterval(poll);
179
- clearTimeout(deadline);
180
- resolve({ error: "the setup-token process ended before printing a URL" });
181
- }
182
- }, 100);
183
- });
169
+ await sleep(300);
170
+ }
171
+ cancelSetupToken();
172
+ return { error: "claude setup-token printed no URL within 30s" };
184
173
  }
185
174
  /**
186
- * Submit the pasted code. Success = the token appears AND the child settles —
187
- * never a guessed success string (the invalid-code wording is the only one the
188
- * CLI gives us). On success the token is handed to `store` and the flow is torn
189
- * down; the token is NEVER returned, logged, or surfaced in an error.
175
+ * Submit the pasted code. Types it into the masked box, waits for it to land,
176
+ * presses Enter, then watches the rendered pane for the token or the
177
+ * invalid-code refusal. Success = the token appears; it is handed to `store`
178
+ * and the flow is torn down. The token is NEVER returned, logged, or surfaced
179
+ * in an error.
190
180
  */
191
181
  export async function submitSetupTokenCode(code, store) {
192
182
  const f = flow;
193
- if (!f || f.ended)
183
+ if (!f || f.ended || !tmuxHasSession(SESSION))
194
184
  return { ok: false, error: "no setup-token flow is in progress — start one first" };
195
185
  const trimmed = code.trim();
196
186
  if (!trimmed)
197
187
  return { ok: false, error: "empty code" };
198
188
  clearTimeout(f.timer);
199
189
  f.timer = setTimeout(() => cancelSetupToken(), FLOW_IDLE_MS);
200
- // Forget prior output so a stale "Invalid code" is not read as THIS verdict.
201
- f.out = "";
202
- const verdict = await new Promise((resolve) => {
203
- const t = setTimeout(() => {
204
- f.pending = null;
205
- resolve({ kind: "timeout" });
206
- }, 30_000);
207
- f.pending = (v) => {
208
- clearTimeout(t);
209
- resolve(v);
210
- };
211
- // The "Paste code here >" prompt reads a line; a PTY submits on CR.
212
- f.proc.write(trimmed + "\r");
213
- });
214
- if (verdict.kind === "success") {
215
- try {
216
- store(verdict.token);
190
+ // Type the code (literal — the code may contain '#', '-', etc.), then WAIT for
191
+ // it to appear in the masked box before Enter: a no-delay Enter submits an
192
+ // empty field and nothing happens (measured).
193
+ try {
194
+ tmux(["send-keys", "-t", SESSION, "-l", "--", trimmed]);
195
+ }
196
+ catch {
197
+ return { ok: false, error: "the setup-token flow ended — start a new one and try again" };
198
+ }
199
+ const entered = Date.now() + 4_000;
200
+ while (Date.now() < entered) {
201
+ // The prompt line gains masked chars (or the code) after the ">".
202
+ const line = capture().split("\n").find((l) => /Paste code here/i.test(l)) ?? "";
203
+ if (/Paste code here[^>]*>\s*\S/i.test(line))
204
+ break;
205
+ await sleep(200);
206
+ }
207
+ try {
208
+ tmux(["send-keys", "-t", SESSION, "Enter"]);
209
+ }
210
+ catch {
211
+ return { ok: false, error: "the setup-token flow ended — start a new one and try again" };
212
+ }
213
+ const deadline = Date.now() + 30_000;
214
+ while (Date.now() < deadline) {
215
+ // Scrollback included: on success the token may sit above a trailing line.
216
+ // NB: this buffer can contain the token — it must never be logged.
217
+ const screen = capture(true);
218
+ const tok = parseSetupToken(screen);
219
+ if (tok) {
220
+ try {
221
+ store(tok);
222
+ }
223
+ catch (e) {
224
+ // Never leak the token in the error. Tear down (the token was already
225
+ // printed; there is no live prompt to retry) and ask for a fresh flow.
226
+ cancelSetupToken();
227
+ return { ok: false, error: "storing the token failed — start a new one: " + (e instanceof Error ? e.message : "unknown") };
228
+ }
229
+ cancelSetupToken();
230
+ return { ok: true };
217
231
  }
218
- catch (e) {
219
- // Never leak the token in the error. The CLI prints the token then exits,
220
- // so there is no live flow to retry here — tear it down and scrub, and
221
- // tell the caller to start a fresh one.
222
- f.out = "";
232
+ if (parseSetupTokenOutcome(screen) === "invalid-code") {
233
+ // The CLI shows "Press Enter to retry" → press Enter to return to the
234
+ // paste prompt, keeping the flow (and its PKCE URL) alive for a retry.
235
+ try {
236
+ tmux(["send-keys", "-t", SESSION, "Enter"]);
237
+ }
238
+ catch {
239
+ /* session gone — the next submit will report it */
240
+ }
241
+ return { ok: false, error: "Invalid code. Please make sure the full code was copied." };
242
+ }
243
+ if (!tmuxHasSession(SESSION)) {
244
+ f.ended = true;
223
245
  cancelSetupToken();
224
- return {
225
- ok: false,
226
- error: "storing the token failed — start a new one: " + (e instanceof Error ? e.message : "unknown"),
227
- };
246
+ return { ok: false, error: "the setup-token flow ended — start a new one and try again" };
228
247
  }
229
- f.out = ""; // scrub the buffer that held the token
230
- cancelSetupToken();
231
- return { ok: true };
248
+ await sleep(300);
232
249
  }
233
- if (verdict.kind === "invalid-code")
234
- return { ok: false, error: "Invalid code. Please make sure the full code was copied." };
235
- if (verdict.kind === "ended")
236
- return { ok: false, error: "the setup-token flow ended — start a new one and try again" };
237
250
  return { ok: false, error: "the CLI did not answer within 30s" };
238
251
  }
239
252
  //# sourceMappingURL=setup-token.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"setup-token.js","sourceRoot":"","sources":["../src/setup-token.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"setup-token.js","sourceRoot":"","sources":["../src/setup-token.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shadok-ai",
3
- "version": "0.17.2",
3
+ "version": "0.17.3",
4
4
  "main": "dist/session.js",
5
5
  "scripts": {
6
6
  "test": "node --import tsx --test --test-timeout=120000 test/*.ts context/*/test/*.test.mjs",