perplexity-user-mcp 0.8.39 → 0.8.44

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 (133) hide show
  1. package/README.md +5 -0
  2. package/dist/attachments.d.ts +10 -20
  3. package/dist/browser-window.d.ts +1 -0
  4. package/dist/cf-warmup.d.ts +32 -0
  5. package/dist/checks/browser.d.ts +12 -100
  6. package/dist/checks/config.d.ts +25 -91
  7. package/dist/checks/ide.d.ts +31 -89
  8. package/dist/checks/mcp.d.ts +12 -61
  9. package/dist/checks/native-deps.d.ts +46 -131
  10. package/dist/checks/network.d.ts +13 -71
  11. package/dist/checks/probe.d.ts +20 -92
  12. package/dist/checks/profiles.d.ts +13 -99
  13. package/dist/checks/profiles.mjs +35 -0
  14. package/dist/checks/runtime.d.ts +24 -89
  15. package/dist/checks/vault.d.ts +13 -142
  16. package/dist/checks/vault.mjs +6 -11
  17. package/dist/{chunk-T6ARJK2P.mjs → chunk-2B5OQUXR.mjs} +6 -6
  18. package/dist/{chunk-2FPGJKCA.mjs → chunk-2EE7MNP2.mjs} +2 -2
  19. package/dist/{chunk-NJX4RBO6.mjs → chunk-2OVLCZHU.mjs} +28 -3
  20. package/dist/{chunk-WDIW33DA.mjs → chunk-3LUO5ATM.mjs} +1 -1
  21. package/dist/{chunk-B65IJQZJ.mjs → chunk-6E6XTHTG.mjs} +1 -1
  22. package/dist/{chunk-S677V2JU.mjs → chunk-C5I7KXHK.mjs} +32 -2
  23. package/dist/{chunk-TDXETAQT.mjs → chunk-DKEJZ4FI.mjs} +1 -1
  24. package/dist/{chunk-U7QPUNRH.mjs → chunk-DXR6EEZH.mjs} +26 -7
  25. package/dist/{chunk-HJIXH6CL.mjs → chunk-E3GRJXXJ.mjs} +2 -0
  26. package/dist/{chunk-RK4EBZJ3.mjs → chunk-E75J42W5.mjs} +11 -8
  27. package/dist/{chunk-452DK6OS.mjs → chunk-FNHYUE22.mjs} +2 -2
  28. package/dist/{chunk-D254EFYB.mjs → chunk-GBI2U336.mjs} +1 -1
  29. package/dist/chunk-GPUGKWXH.mjs +17 -0
  30. package/dist/{chunk-HNSPNCFH.mjs → chunk-KSNV3ZVY.mjs} +1 -1
  31. package/dist/{chunk-XTRJSV72.mjs → chunk-LGH5BSUY.mjs} +1 -1
  32. package/dist/{chunk-KJFX2ZXR.mjs → chunk-NMKNEEZB.mjs} +1 -1
  33. package/dist/{chunk-FKQ3HP4Q.mjs → chunk-TIWHN4IW.mjs} +1 -1
  34. package/dist/{chunk-V4U3JM4R.mjs → chunk-TSLRTZYR.mjs} +1 -1
  35. package/dist/{chunk-DQQISMYN.mjs → chunk-V4LHDNWJ.mjs} +2 -2
  36. package/dist/{chunk-C3HPFFTD.mjs → chunk-WHVJ724K.mjs} +84 -44
  37. package/dist/cli.d.ts +14 -1298
  38. package/dist/cli.mjs +35 -27
  39. package/dist/client.d.ts +27 -24
  40. package/dist/client.mjs +6 -6
  41. package/dist/cloud-sync.d.ts +65 -42
  42. package/dist/cloud-sync.mjs +8 -8
  43. package/dist/config.d.ts +35 -39
  44. package/dist/config.mjs +3 -3
  45. package/dist/cookie-jar.d.ts +77 -0
  46. package/dist/daemon/attach.d.ts +10 -11
  47. package/dist/daemon/attach.mjs +19 -17
  48. package/dist/daemon/audit.d.ts +5 -7
  49. package/dist/daemon/audit.mjs +2 -2
  50. package/dist/daemon/client-http.d.ts +10 -16
  51. package/dist/daemon/client-http.mjs +17 -17
  52. package/dist/daemon/index.d.ts +17 -14
  53. package/dist/daemon/index.mjs +18 -18
  54. package/dist/daemon/install-tunnel.d.ts +8 -34
  55. package/dist/daemon/install-tunnel.mjs +2 -2
  56. package/dist/daemon/launcher.d.ts +24 -29
  57. package/dist/daemon/launcher.mjs +16 -16
  58. package/dist/daemon/local-tokens.d.ts +23 -0
  59. package/dist/daemon/lockfile.d.ts +10 -12
  60. package/dist/daemon/lockfile.mjs +2 -2
  61. package/dist/daemon/oauth-consent-cache.d.ts +86 -0
  62. package/dist/daemon/oauth-provider.d.ts +132 -0
  63. package/dist/daemon/public-pages.d.ts +9 -0
  64. package/dist/daemon/security.d.ts +52 -0
  65. package/dist/daemon/server.d.ts +12 -83
  66. package/dist/daemon/server.mjs +11 -11
  67. package/dist/daemon/token.d.ts +7 -9
  68. package/dist/daemon/token.mjs +2 -2
  69. package/dist/daemon/tunnel-providers/cloudflared-named-setup.d.ts +140 -0
  70. package/dist/daemon/tunnel-providers/cloudflared-named.d.ts +45 -0
  71. package/dist/daemon/tunnel-providers/cloudflared-quick.d.ts +8 -0
  72. package/dist/daemon/tunnel-providers/index.d.ts +16 -327
  73. package/dist/daemon/tunnel-providers/index.mjs +3 -3
  74. package/dist/daemon/tunnel-providers/ngrok-config.d.ts +18 -0
  75. package/dist/daemon/tunnel-providers/ngrok.d.ts +68 -0
  76. package/dist/daemon/tunnel-providers/types.d.ts +56 -0
  77. package/dist/daemon/tunnel.d.ts +5 -7
  78. package/dist/debug-tracer.d.ts +2 -0
  79. package/dist/doctor-report.d.ts +17 -22
  80. package/dist/doctor.d.ts +12 -44
  81. package/dist/doctor.mjs +2 -2
  82. package/dist/export.d.ts +11 -18
  83. package/dist/export.mjs +4 -4
  84. package/dist/format.d.ts +52 -0
  85. package/dist/fs-utils.d.ts +8 -0
  86. package/dist/health-check.d.ts +1 -108
  87. package/dist/health-check.mjs +3 -3
  88. package/dist/history-store.d.ts +29 -65
  89. package/dist/history-store.mjs +2 -2
  90. package/dist/impit-login-runner.d.ts +1 -469
  91. package/dist/impit-login-runner.mjs +4 -4
  92. package/dist/index.d.ts +25 -149
  93. package/dist/index.mjs +22 -20
  94. package/dist/is-main-module.d.ts +9 -0
  95. package/dist/login-runner.d.ts +1 -333
  96. package/dist/login-runner.mjs +13 -13
  97. package/dist/login.d.ts +5 -0
  98. package/dist/logout.d.ts +2 -28
  99. package/dist/logout.mjs +3 -2
  100. package/dist/manual-login-runner.d.ts +1 -150
  101. package/dist/manual-login-runner.mjs +11 -11
  102. package/dist/{native-deps-IE4B55EL.mjs → native-deps-FCSYDL4W.mjs} +4 -4
  103. package/dist/native-deps.d.ts +36 -0
  104. package/dist/package-version.d.ts +1 -0
  105. package/dist/profiles.d.ts +41 -41
  106. package/dist/profiles.mjs +1 -1
  107. package/dist/prompts.d.ts +2 -0
  108. package/dist/redact.d.ts +14 -142
  109. package/dist/refresh.d.ts +11 -16
  110. package/dist/refresh.mjs +4 -4
  111. package/dist/reinit-watcher.d.ts +15 -24
  112. package/dist/reinit-watcher.mjs +2 -2
  113. package/dist/resources.d.ts +5 -0
  114. package/dist/safe-write.d.ts +16 -0
  115. package/dist/session-metadata.d.ts +45 -0
  116. package/dist/tool-config.d.ts +10 -0
  117. package/dist/tools.d.ts +23 -0
  118. package/dist/tty-prompt.d.ts +18 -34
  119. package/dist/vault.d.ts +114 -34
  120. package/dist/vault.mjs +6 -4
  121. package/dist/viewer-detect.d.ts +2 -4
  122. package/dist/viewers.d.ts +13 -18
  123. package/dist/viewers.mjs +1 -1
  124. package/package.json +3 -3
  125. package/dist/cloud-sync.d-Cqt6y18U.d.ts +0 -42
  126. package/dist/doctor.d-CXmUqOXX.d.ts +0 -43
  127. package/dist/history-store.d-BzjBF2m3.d.ts +0 -65
  128. package/dist/native-deps-BNThFHxa.d.ts +0 -175
  129. package/dist/profiles.d-DqS1oZWr.d.ts +0 -41
  130. package/dist/session-metadata-B9aV_n5g.d.ts +0 -148
  131. package/dist/vault.d-BSJWDLhp.d.ts +0 -37
  132. package/dist/viewer-detect.d-HWGnyFAA.d.ts +0 -4
  133. package/dist/viewers.d-BGCK6sw6.d.ts +0 -10
@@ -1,150 +1 @@
1
- import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
2
- import { chromium } from 'patchright';
3
- import { Vault } from './vault.d-BSJWDLhp.js';
4
- import { resolveBrowserExecutable } from './config.js';
5
- import { recordLoginSuccess, getActiveName, getProfilePaths } from './profiles.d-DqS1oZWr.js';
6
- import { redact } from './redact.js';
7
- import { c as collectSessionMetadata } from './session-metadata-B9aV_n5g.js';
8
-
9
- // Headed login runner. User drives the browser; we poll cookies until the
10
- // session token appears, then write the vault + meta + models-cache +
11
- // .reinit sentinel, and exit.
12
-
13
-
14
- const ORIGIN = process.env.PERPLEXITY_ORIGIN || "https://www.perplexity.ai";
15
- // Perplexity's login flow lives at /account (the `/login` path doesn't exist
16
- // on www.perplexity.ai). Integration tests override via env var to point at
17
- // the mock server's /login route.
18
- const LOGIN_PATH = process.env.PERPLEXITY_LOGIN_PATH || "/account";
19
- const POLL_MS = Number(process.env.PERPLEXITY_POLL_MS ?? 2000);
20
- const MAX_WAIT_MS = 180_000;
21
- const CF_TIMEOUT_MS = Number(process.env.PERPLEXITY_CF_TIMEOUT_MS ?? 20_000);
22
-
23
- function resolveProfile() {
24
- return process.env.PERPLEXITY_PROFILE || getActiveName() || "default";
25
- }
26
-
27
- const isTest = !!process.env.PERPLEXITY_TEST_AUTO_LOGIN_EMAIL || !!process.env.PERPLEXITY_TEST_BROWSER_CLOSE_AFTER_MS;
28
-
29
- function ipc(msg) { if (process.send) process.send(msg); }
30
- function emit(obj) { process.stdout.write(JSON.stringify(obj) + "\n"); }
31
-
32
- async function main() {
33
- const PROFILE = resolveProfile();
34
-
35
- let executablePath;
36
- let channel;
37
- if (!isTest) {
38
- try {
39
- ({ path: executablePath, channel } = await resolveBrowserExecutable());
40
- } catch (err) {
41
- emit({ ok: false, reason: "chrome_missing", error: redact(String(err?.message ?? err)) });
42
- process.exit(4);
43
- }
44
- }
45
-
46
- const browser = await chromium.launch({
47
- headless: isTest,
48
- ...(executablePath ? { executablePath } : {}),
49
- ...(channel && ["chrome", "msedge", "chromium"].includes(channel) ? { channel } : {}),
50
- }); // isTest = headless in CI; humans see headed.
51
- const ctx = await browser.newContext({ ignoreHTTPSErrors: true });
52
- const page = await ctx.newPage();
53
-
54
- let cfClosed = false;
55
- browser.on("disconnected", () => { cfClosed = true; });
56
-
57
- // Navigate to the login page so the page has a same-origin context for
58
- // subsequent credentialed fetch() calls. Going to ORIGIN's root path can
59
- // land on a marketing page that may not set a usable document origin for
60
- // in-page fetch. Path is env-var-configurable for the mock server tests.
61
- try { await page.goto(`${ORIGIN}${LOGIN_PATH}`, { waitUntil: "domcontentloaded", timeout: 30_000 }); }
62
- catch { /* continue; next phase checks CF */ }
63
- if (!isTest) await page.bringToFront().catch(() => {});
64
-
65
- // CF resolve check
66
- const cfStart = Date.now();
67
- while (Date.now() - cfStart < CF_TIMEOUT_MS) {
68
- try {
69
- const title = await page.title();
70
- if (!/just a moment/i.test(title)) break;
71
- } catch { break; }
72
- await page.waitForTimeout(500);
73
- }
74
- if (Date.now() - cfStart >= CF_TIMEOUT_MS) {
75
- const title = await page.title().catch(() => "");
76
- if (/just a moment/i.test(title)) {
77
- await browser.close().catch(() => {});
78
- emit({ ok: false, reason: "cf_blocked" });
79
- process.exit(3);
80
- }
81
- }
82
-
83
- ipc({ phase: "awaiting_user" });
84
- if (!isTest) await page.bringToFront().catch(() => {});
85
-
86
- // Test hook: auto-drive the login so CI doesn't need a human.
87
- if (process.env.PERPLEXITY_TEST_AUTO_LOGIN_EMAIL) {
88
- const email = process.env.PERPLEXITY_TEST_AUTO_LOGIN_EMAIL;
89
- await page.evaluate(async ({ origin, email }) => {
90
- await fetch(`${origin}/login/email`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ email }) });
91
- await fetch(`${origin}/login/otp`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ email, otp: "123456" }) });
92
- }, { origin: ORIGIN, email });
93
- }
94
-
95
- // Test hook: force a browser close to exercise the cancelled path.
96
- if (process.env.PERPLEXITY_TEST_BROWSER_CLOSE_AFTER_MS) {
97
- setTimeout(() => browser.close().catch(() => {}), Number(process.env.PERPLEXITY_TEST_BROWSER_CLOSE_AFTER_MS));
98
- }
99
-
100
- const started = Date.now();
101
- let sessionCookie = null;
102
- while (Date.now() - started < MAX_WAIT_MS) {
103
- if (cfClosed) {
104
- emit({ ok: false, reason: "cancelled" });
105
- process.exit(2);
106
- }
107
- await new Promise((r) => setTimeout(r, POLL_MS));
108
- const cookies = await ctx.cookies().catch(() => []);
109
- sessionCookie = cookies.find((c) => c.name === "__Secure-next-auth.session-token");
110
- if (sessionCookie) break;
111
- }
112
- if (!sessionCookie) {
113
- await browser.close().catch(() => {});
114
- emit({ ok: false, reason: "timeout" });
115
- process.exit(2);
116
- }
117
-
118
- const allCookies = await ctx.cookies();
119
- const metadata = await collectSessionMetadata(page, ORIGIN, { sessionTimeoutMs: 10_000 });
120
-
121
- const vault = new Vault();
122
- await vault.set(PROFILE, "cookies", JSON.stringify(allCookies));
123
- if (metadata.sessionData?.user?.email) await vault.set(PROFILE, "email", metadata.sessionData.user.email);
124
- if (metadata.sessionData?.user?.id) await vault.set(PROFILE, "userId", metadata.sessionData.user.id);
125
-
126
- const paths = getProfilePaths(PROFILE);
127
- if (!existsSync(paths.dir)) mkdirSync(paths.dir, { recursive: true });
128
- writeFileSync(paths.modelsCache, JSON.stringify(metadata.cache, null, 2));
129
-
130
- recordLoginSuccess(PROFILE, { tier: metadata.tier, loginMode: "manual", lastLogin: new Date().toISOString() });
131
-
132
- writeFileSync(paths.reinit, String(Date.now()));
133
-
134
- await browser.close().catch(() => {});
135
- emit({ ok: true, tier: metadata.tier, modelCount: Object.keys(metadata.models?.models ?? {}).length });
136
- process.exit(0);
137
- }
138
-
139
- main().catch((err) => {
140
- const msg = err?.message ?? err;
141
- const stack = err?.stack;
142
- emit({
143
- ok: false,
144
- reason: "crash",
145
- error: redact(String(msg ?? "unknown error")),
146
- detail: redact(String(msg ?? "unknown error")),
147
- ...(stack ? { stack: redact(String(stack)) } : {}),
148
- });
149
- process.exit(5);
150
- });
1
+ export {};
@@ -6,16 +6,16 @@ import {
6
6
  } from "./chunk-HMKLWVXB.mjs";
7
7
  import {
8
8
  resolveBrowserExecutable
9
- } from "./chunk-U7QPUNRH.mjs";
9
+ } from "./chunk-DXR6EEZH.mjs";
10
10
  import {
11
11
  Vault
12
- } from "./chunk-S677V2JU.mjs";
12
+ } from "./chunk-C5I7KXHK.mjs";
13
13
  import "./chunk-MTDFKNXX.mjs";
14
14
  import {
15
15
  getActiveName,
16
16
  getProfilePaths,
17
17
  recordLoginSuccess
18
- } from "./chunk-HJIXH6CL.mjs";
18
+ } from "./chunk-E3GRJXXJ.mjs";
19
19
  import "./chunk-4UEJOM6W.mjs";
20
20
 
21
21
  // src/manual-login-runner.js
@@ -38,6 +38,7 @@ function emit(obj) {
38
38
  }
39
39
  async function main() {
40
40
  const PROFILE = resolveProfile();
41
+ const paths = getProfilePaths(PROFILE);
41
42
  let executablePath;
42
43
  let channel;
43
44
  if (!isTest) {
@@ -48,15 +49,15 @@ async function main() {
48
49
  process.exit(4);
49
50
  }
50
51
  }
51
- const browser = await chromium.launch({
52
+ const ctx = await chromium.launchPersistentContext(paths.loginBrowserData, {
52
53
  headless: isTest,
54
+ ignoreHTTPSErrors: true,
53
55
  ...executablePath ? { executablePath } : {},
54
56
  ...channel && ["chrome", "msedge", "chromium"].includes(channel) ? { channel } : {}
55
57
  });
56
- const ctx = await browser.newContext({ ignoreHTTPSErrors: true });
57
58
  const page = await ctx.newPage();
58
59
  let cfClosed = false;
59
- browser.on("disconnected", () => {
60
+ ctx.browser().on("disconnected", () => {
60
61
  cfClosed = true;
61
62
  });
62
63
  try {
@@ -78,7 +79,7 @@ async function main() {
78
79
  if (Date.now() - cfStart >= CF_TIMEOUT_MS) {
79
80
  const title = await page.title().catch(() => "");
80
81
  if (/just a moment/i.test(title)) {
81
- await browser.close().catch(() => {
82
+ await ctx.browser()?.close().catch(() => {
82
83
  });
83
84
  emit({ ok: false, reason: "cf_blocked" });
84
85
  process.exit(3);
@@ -95,7 +96,7 @@ async function main() {
95
96
  }, { origin: ORIGIN, email });
96
97
  }
97
98
  if (process.env.PERPLEXITY_TEST_BROWSER_CLOSE_AFTER_MS) {
98
- setTimeout(() => browser.close().catch(() => {
99
+ setTimeout(() => ctx.browser()?.close().catch(() => {
99
100
  }), Number(process.env.PERPLEXITY_TEST_BROWSER_CLOSE_AFTER_MS));
100
101
  }
101
102
  const started = Date.now();
@@ -111,7 +112,7 @@ async function main() {
111
112
  if (sessionCookie) break;
112
113
  }
113
114
  if (!sessionCookie) {
114
- await browser.close().catch(() => {
115
+ await ctx.browser()?.close().catch(() => {
115
116
  });
116
117
  emit({ ok: false, reason: "timeout" });
117
118
  process.exit(2);
@@ -122,12 +123,11 @@ async function main() {
122
123
  await vault.set(PROFILE, "cookies", JSON.stringify(allCookies));
123
124
  if (metadata.sessionData?.user?.email) await vault.set(PROFILE, "email", metadata.sessionData.user.email);
124
125
  if (metadata.sessionData?.user?.id) await vault.set(PROFILE, "userId", metadata.sessionData.user.id);
125
- const paths = getProfilePaths(PROFILE);
126
126
  if (!existsSync(paths.dir)) mkdirSync(paths.dir, { recursive: true });
127
127
  writeFileSync(paths.modelsCache, JSON.stringify(metadata.cache, null, 2));
128
128
  recordLoginSuccess(PROFILE, { tier: metadata.tier, loginMode: "manual", lastLogin: (/* @__PURE__ */ new Date()).toISOString() });
129
129
  writeFileSync(paths.reinit, String(Date.now()));
130
- await browser.close().catch(() => {
130
+ await ctx.browser()?.close().catch(() => {
131
131
  });
132
132
  emit({ ok: true, tier: metadata.tier, modelCount: Object.keys(metadata.models?.models ?? {}).length });
133
133
  process.exit(0);
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  getImpitRuntimeDir
3
- } from "./chunk-DQQISMYN.mjs";
4
- import "./chunk-U7QPUNRH.mjs";
5
- import "./chunk-S677V2JU.mjs";
3
+ } from "./chunk-V4LHDNWJ.mjs";
4
+ import "./chunk-DXR6EEZH.mjs";
5
+ import "./chunk-C5I7KXHK.mjs";
6
6
  import "./chunk-MTDFKNXX.mjs";
7
- import "./chunk-HJIXH6CL.mjs";
7
+ import "./chunk-E3GRJXXJ.mjs";
8
8
  import "./chunk-4UEJOM6W.mjs";
9
9
 
10
10
  // src/native-deps.js
@@ -0,0 +1,36 @@
1
+ /**
2
+ * @returns {{ installed: boolean; version: string | null; installedAt: string | null; runtimeDir: string }}
3
+ */
4
+ export function getImpitStatus(): {
5
+ installed: boolean;
6
+ version: string | null;
7
+ installedAt: string | null;
8
+ runtimeDir: string;
9
+ };
10
+ /**
11
+ * Install impit into ~/.perplexity-mcp/native-deps/ via `npm install`.
12
+ * Does NOT depend on the user's project — uses --prefix into our own
13
+ * runtime dir and ensures a package.json exists there.
14
+ *
15
+ * @param {{ log?: (line: string) => void }} [opts]
16
+ * @returns {Promise<{ ok: boolean; version?: string; error?: string }>}
17
+ */
18
+ export function installImpit(opts?: {
19
+ log?: (line: string) => void;
20
+ }): Promise<{
21
+ ok: boolean;
22
+ version?: string;
23
+ error?: string;
24
+ }>;
25
+ /**
26
+ * Remove the entire native-deps runtime directory.
27
+ *
28
+ * @param {{ log?: (line: string) => void }} [opts]
29
+ * @returns {{ ok: boolean; error?: string }}
30
+ */
31
+ export function uninstallImpit(opts?: {
32
+ log?: (line: string) => void;
33
+ }): {
34
+ ok: boolean;
35
+ error?: string;
36
+ };
@@ -0,0 +1 @@
1
+ export declare function getPackageVersion(): string;
@@ -1,41 +1,41 @@
1
- interface ProfileMeta {
2
- name: string;
3
- displayName: string;
4
- createdAt: string;
5
- loginMode?: string;
6
- tier?: string;
7
- lastLogin?: string;
8
- }
9
-
10
- interface ProfilePaths {
11
- dir: string;
12
- meta: string;
13
- vault: string;
14
- vaultPlain: string;
15
- browserData: string;
16
- modelsCache: string;
17
- history: string;
18
- attachments: string;
19
- researches: string;
20
- reinit: string;
21
- }
22
-
23
- declare function getConfigDir(): string;
24
- declare function getProfilesDir(): string;
25
- declare function getProfilePaths(name: string): ProfilePaths;
26
- declare function validateName(name: string): string | null;
27
- declare function createProfile(name: string, opts?: { displayName?: string; loginMode?: string }): ProfileMeta;
28
- declare function listProfiles(): ProfileMeta[];
29
- declare function getProfile(name: string): ProfileMeta | null;
30
- declare function deleteProfile(name: string): void;
31
- declare function getActiveName(): string | null;
32
- declare function getActive(): ProfileMeta | null;
33
- declare function setActive(name: string): void;
34
- declare function suggestNextDefaultName(): string;
35
- declare function renameProfile(oldName: string, newName: string): void;
36
- declare function recordLoginSuccess(
37
- name: string,
38
- opts: { tier: string; loginMode: string; lastLogin: string }
39
- ): ProfileMeta;
40
-
41
- export { type ProfileMeta, type ProfilePaths, createProfile, deleteProfile, getActive, getActiveName, getConfigDir, getProfile, getProfilePaths, getProfilesDir, listProfiles, recordLoginSuccess, renameProfile, setActive, suggestNextDefaultName, validateName };
1
+ export function getConfigDir(): string;
2
+ export function getProfilesDir(): string;
3
+ export function getProfilePaths(name: any): {
4
+ dir: string;
5
+ meta: string;
6
+ vault: string;
7
+ vaultPlain: string;
8
+ browserData: string;
9
+ loginBrowserData: string;
10
+ modelsCache: string;
11
+ daemonStatus: string;
12
+ history: string;
13
+ attachments: string;
14
+ researches: string;
15
+ reinit: string;
16
+ };
17
+ /**
18
+ * Validate a profile name. Returns null when valid, or an error string
19
+ * (suitable for throwing) when invalid. The slug format [a-z0-9_-]{1,32}
20
+ * structurally excludes @ and . so email-shaped names are impossible.
21
+ */
22
+ export function validateName(name: any): "Profile name is required." | "Profile name must be 32 characters or fewer." | "Profile name must be lowercase." | "Profile name must contain only lowercase letters, digits, hyphens, and underscores. Invalid characters detected." | null;
23
+ export function createProfile(name: any, opts?: {}): {
24
+ name: any;
25
+ displayName: any;
26
+ createdAt: string;
27
+ loginMode: any;
28
+ };
29
+ export function listProfiles(): any[];
30
+ export function getProfile(name: any): any;
31
+ export function deleteProfile(name: any): void;
32
+ export function getActiveName(): string | null;
33
+ export function getActive(): any;
34
+ export function setActive(name: any): void;
35
+ export function suggestNextDefaultName(): string;
36
+ export function renameProfile(oldName: any, newName: any): void;
37
+ export function recordLoginSuccess(name: any, { tier, loginMode, lastLogin }: {
38
+ tier: any;
39
+ loginMode: any;
40
+ lastLogin: any;
41
+ }): any;
package/dist/profiles.mjs CHANGED
@@ -13,7 +13,7 @@ import {
13
13
  setActive,
14
14
  suggestNextDefaultName,
15
15
  validateName
16
- } from "./chunk-HJIXH6CL.mjs";
16
+ } from "./chunk-E3GRJXXJ.mjs";
17
17
  import "./chunk-4UEJOM6W.mjs";
18
18
  export {
19
19
  createProfile,
@@ -0,0 +1,2 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerPrompts(server: McpServer): void;
package/dist/redact.d.ts CHANGED
@@ -1,47 +1,3 @@
1
- // Security-critical: scrubs sensitive patterns from strings before logging
2
- // or before sending to external destinations (GitHub issue reports, debug
3
- // exports). Pattern list ordered from most-specific to least-specific to
4
- // avoid accidental re-matching by a more general rule.
5
-
6
- // Scope: this module is called on OUR OWN trusted log/debug data (logger
7
- // output, doctor reports, cookies). It is NOT a user-input sanitizer.
8
- // Deliberate trade-offs in the current pattern set:
9
- // - Emails are matched post-URL-decode only (raw %40 encoded forms pass through)
10
- // - Unix home paths assume no whitespace in usernames
11
- // - Windows home paths only cover C:\Users\... (UNC paths pass through)
12
- // - Long-token redaction (≥20 base64/hex chars) may over-redact legitimate
13
- // long URLs or JSON values — accepted trade-off for safety over debuggability
14
- // If any of these assumptions changes (e.g., we start redacting user-supplied
15
- // payloads), the pattern set must be revisited.
16
-
17
- /**
18
- * Canonical secret-shape regex list. Distinct from the legacy PATTERNS array
19
- * below because every match emits a kind-tagged `<redacted:<kind>>` placeholder
20
- * so the redactor's output is unambiguous for audit / test / grep-gate
21
- * purposes. Applied BEFORE the legacy PATTERNS inside redactString so specific
22
- * shapes win over the generic long-token catchall.
23
- */
24
- const SECRET_PATTERNS = Object.freeze([
25
- // OAuth / local prefixes come FIRST so a value like `"bearer":"pplx_at_…"`
26
- // gets the specific oauth-access tag instead of the generic daemon-bearer
27
- // one from the bearer-json catchall below.
28
- { name: "oauth-access", kind: "oauth-access", re: /pplx_at_[A-Za-z0-9_\-]{10,}/g },
29
- { name: "oauth-refresh", kind: "oauth-refresh", re: /pplx_rt_[A-Za-z0-9_\-]{10,}/g },
30
- { name: "oauth-code", kind: "oauth-code", re: /pplx_ac_[A-Za-z0-9_\-]{10,}/g },
31
- { name: "local-bearer", kind: "local-bearer", re: /pplx_local_[a-z0-9-]+_[A-Za-z0-9_\-]{10,}/g },
32
- { name: "daemon-bearer-json", kind: "daemon-bearer", re: /"bearerToken"\s*:\s*"[A-Za-z0-9_\-]{30,}"/g },
33
- // Matches the `"bearer":"..."` shape used by daemon:bearer:reveal:response
34
- // so reveal-payload logs stay leak-free. Value is only required to be
35
- // 20+ safe-identifier chars — covers both raw daemon bearers and future
36
- // short-lived tokens.
37
- { name: "bearer-json", kind: "daemon-bearer", re: /"bearer"\s*:\s*"[A-Za-z0-9_\-]{20,}"/g },
38
- { name: "authorization-header", kind: "bearer-header", re: /[Aa]uthorization\s*:\s*Bearer\s+[A-Za-z0-9_\-\.]{20,}/g },
39
- { name: "ngrok-authtoken", kind: "ngrok-authtoken", re: /"authtoken"\s*:\s*"\d+[A-Za-z0-9]{20,}"/g },
40
- { name: "jwt", kind: "jwt", re: /eyJ[A-Za-z0-9_\-]+\.[A-Za-z0-9_\-]+\.[A-Za-z0-9_\-]+/g },
41
- { name: "cf-clearance", kind: "cf-clearance", re: /cf_clearance=[^;\s]+/g },
42
- { name: "perplexity-session", kind: "perplexity-session", re: /__Secure-next-auth\.session-token=[^;\s]+/g },
43
- ]);
44
-
45
1
  /**
46
2
  * String-only secret redactor. Applies SECRET_PATTERNS and returns a string
47
3
  * with kind-tagged placeholders. Does NOT apply the legacy PATTERNS
@@ -50,71 +6,7 @@ const SECRET_PATTERNS = Object.freeze([
50
6
  * @param {string} input
51
7
  * @returns {string}
52
8
  */
53
- function redactSecrets(input) {
54
- if (typeof input !== "string") return input;
55
- let out = input;
56
- for (const { re, kind } of SECRET_PATTERNS) {
57
- out = out.replace(re, (match) => {
58
- if (match.startsWith('"bearerToken"')) return `"bearerToken":"<redacted:${kind}>"`;
59
- if (match.startsWith('"bearer"')) return `"bearer":"<redacted:${kind}>"`;
60
- if (/^[Aa]uthorization\s*:/i.test(match)) return match.replace(/Bearer\s+[A-Za-z0-9_\-\.]{20,}/, `Bearer <redacted:${kind}>`);
61
- if (match.startsWith('"authtoken"')) return `"authtoken":"<redacted:${kind}>"`;
62
- if (match.startsWith("cf_clearance=")) return `cf_clearance=<redacted:${kind}>`;
63
- if (match.startsWith("__Secure-next-auth.session-token=")) return `__Secure-next-auth.session-token=<redacted:${kind}>`;
64
- return `<redacted:${kind}>`;
65
- });
66
- }
67
- return out;
68
- }
69
-
70
- const PATTERNS = [
71
- // Emails: RFC 5322 subset. Must come before generic token rules because
72
- // emails contain characters that other rules would catch.
73
- {
74
- re: /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/g,
75
- replace: "<email>",
76
- },
77
- // Perplexity user IDs: user_ followed by hex/alphanum (>=8 chars).
78
- {
79
- re: /\buser_[A-Fa-f0-9]{8,}\b/g,
80
- replace: "<userId>",
81
- },
82
- // Home directory paths. Must replace before the "long opaque token" rule
83
- // because long path segments would otherwise trip it.
84
- {
85
- re: /(\/Users\/|\/home\/)[^/\s]+/g,
86
- replace: "<home>",
87
- },
88
- {
89
- re: /([A-Z]:)\\Users\\[^\\]+/g,
90
- replace: "<home>",
91
- },
92
- // IPv4
93
- {
94
- re: /\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/g,
95
- replace: "<ip>",
96
- },
97
- // IPv6. Three alternations cover: (1) full 8-group addresses, (2) :: compressed
98
- // forms with at least one prefix group (e.g. 2001:db8::1, fe80::1), (3) leading-::
99
- // forms like ::1 and ::. A function filter then requires hex letters (a-f/A-F) OR
100
- // a double-colon so that pure-digit colon-separated strings like "23:59:59"
101
- // (HH:MM:SS wall-clock) and ISO timestamps are left untouched.
102
- {
103
- re: /\b(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}\b|\b(?:[0-9a-fA-F]{1,4}:){1,7}:(?:[0-9a-fA-F]{1,4}(?::[0-9a-fA-F]{1,4}){0,6})?\b|(?<!\w)::(?:[0-9a-fA-F]{1,4}(?::[0-9a-fA-F]{1,4}){0,6})?(?!\w)/g,
104
- replace: (match) => {
105
- const hasHex = /[a-fA-F]/.test(match);
106
- const hasDoubleColon = /::/.test(match);
107
- return (hasHex || hasDoubleColon) ? "<ip>" : match;
108
- },
109
- },
110
- // Long opaque tokens (base64 / hex, >=20 chars). Applied last so more
111
- // specific rules win first. Captures key=value and replaces only the value.
112
- {
113
- re: /=([A-Za-z0-9+/=]{20,})/g,
114
- replace: "=<redacted>",
115
- },
116
- ];
117
-
9
+ export function redactSecrets(input: string): string;
118
10
  /**
119
11
  * Redact sensitive patterns from a string or object graph.
120
12
  * For objects: every string-valued leaf is redacted recursively.
@@ -124,36 +16,16 @@ const PATTERNS = [
124
16
  * @param {WeakSet<object>} [_seen]
125
17
  * @returns {T}
126
18
  */
127
- function redact(value, _seen) {
128
- if (value == null) return value;
129
- if (typeof value === "string") return redactString(value);
130
- if (typeof value !== "object") return value;
131
-
132
- // Cycle detection for objects/arrays. We use a WeakSet threaded through the
133
- // recursion so siblings don't falsely collide with each other.
134
- const seen = _seen ?? new WeakSet();
135
- if (seen.has(value)) return "<circular>";
136
- seen.add(value);
137
-
138
- if (Array.isArray(value)) return value.map((v) => redact(v, seen));
139
-
140
- const out = {};
141
- for (const [k, v] of Object.entries(value)) out[k] = redact(v, seen);
142
- return out;
143
- }
144
-
145
- function redactString(s) {
146
- // SECRET_PATTERNS first: specific bearer / OAuth / JWT / ngrok / cookie
147
- // shapes get tagged "<redacted:<kind>>" placeholders. Then the legacy
148
- // PATTERNS handle everything else (emails / userIds / home paths / IPs /
149
- // generic long-token catchall). Running secrets first prevents the generic
150
- // `=(20+chars)` catchall from eating a bearer with a plain `<redacted>`
151
- // label when we'd rather have `<redacted:oauth-access>`.
152
- let out = redactSecrets(s);
153
- for (const { re, replace } of PATTERNS) {
154
- out = out.replace(re, replace);
155
- }
156
- return out;
157
- }
158
-
159
- export { SECRET_PATTERNS, redact, redactSecrets };
19
+ export function redact<T>(value: T, _seen?: WeakSet<object>): T;
20
+ /**
21
+ * Canonical secret-shape regex list. Distinct from the legacy PATTERNS array
22
+ * below because every match emits a kind-tagged `<redacted:<kind>>` placeholder
23
+ * so the redactor's output is unambiguous for audit / test / grep-gate
24
+ * purposes. Applied BEFORE the legacy PATTERNS inside redactString so specific
25
+ * shapes win over the generic long-token catchall.
26
+ */
27
+ export const SECRET_PATTERNS: readonly {
28
+ name: string;
29
+ kind: string;
30
+ re: RegExp;
31
+ }[];
package/dist/refresh.d.ts CHANGED
@@ -1,6 +1,3 @@
1
- import { PlaywrightCookie } from './config.js';
2
- import 'patchright';
3
-
4
1
  /**
5
2
  * Live refresh of account info (models/config, ASI access, rate limits, experiments).
6
3
  *
@@ -23,9 +20,9 @@ import 'patchright';
23
20
  * as "try the next tier". Anything else (network error, 5xx, unparseable)
24
21
  * also cascades.
25
22
  */
26
-
27
- type RefreshTier = "got-scraping" | "impit" | "browser";
28
- interface RefreshResult {
23
+ import { type PlaywrightCookie } from "./config.js";
24
+ export type RefreshTier = "got-scraping" | "impit" | "browser";
25
+ export interface RefreshResult {
29
26
  ok: boolean;
30
27
  source: "live" | "no-cookies" | "cf-challenge" | "failed";
31
28
  tier: RefreshTier | null;
@@ -41,7 +38,7 @@ interface RefreshResult {
41
38
  error?: string;
42
39
  }>;
43
40
  }
44
- interface RefreshOptions {
41
+ export interface RefreshOptions {
45
42
  log?: (line: string) => void;
46
43
  timeoutMs?: number;
47
44
  /** Force a particular tier for testing. Omit for normal cascade. */
@@ -52,7 +49,7 @@ interface RefreshOptions {
52
49
  * Full types aren't declared in our tsconfig because impit is NOT a build-time
53
50
  * dependency — it's installed at runtime by the user via "Install Speed Boost".
54
51
  */
55
- interface ImpitModule {
52
+ export interface ImpitModule {
56
53
  Impit: new (opts: {
57
54
  browser: string;
58
55
  ignoreTlsErrors?: boolean;
@@ -85,8 +82,8 @@ interface ImpitModule {
85
82
  * file path string per the docs) and resolves impit's peer native binding
86
83
  * from native-deps/node_modules correctly.
87
84
  */
88
- declare function loadImpit(): Promise<ImpitModule | null>;
89
- declare function isImpitAvailable(): boolean;
85
+ export declare function loadImpit(): Promise<ImpitModule | null>;
86
+ export declare function isImpitAvailable(): boolean;
90
87
  /**
91
88
  * Browser-free authenticated fetch via impit. Used as a fast path for REST
92
89
  * endpoints that only need cookies + a Chrome-ish TLS fingerprint
@@ -97,7 +94,7 @@ declare function isImpitAvailable(): boolean;
97
94
  * the network level. Returns `{ challenged: true }` when the response body
98
95
  * looks like a Cloudflare interstitial.
99
96
  */
100
- declare function impitFetchJson(url: string, init: {
97
+ export declare function impitFetchJson(url: string, init: {
101
98
  method?: string;
102
99
  body?: unknown;
103
100
  headers?: Record<string, string>;
@@ -106,13 +103,11 @@ declare function impitFetchJson(url: string, init: {
106
103
  data: unknown;
107
104
  challenged?: boolean;
108
105
  } | null>;
109
- declare function refreshAccountInfo(opts?: RefreshOptions): Promise<RefreshResult>;
110
- declare function getModelsCacheInfo(): {
106
+ export declare function refreshAccountInfo(opts?: RefreshOptions): Promise<RefreshResult>;
107
+ export declare function getModelsCacheInfo(): {
111
108
  path: string;
112
109
  exists: boolean;
113
110
  mtime: Date | null;
114
111
  ageHours: number | null;
115
112
  };
116
- declare function getImpitRuntimeDir(): string;
117
-
118
- export { type ImpitModule, type RefreshOptions, type RefreshResult, type RefreshTier, getImpitRuntimeDir, getModelsCacheInfo, impitFetchJson, isImpitAvailable, loadImpit, refreshAccountInfo };
113
+ export declare function getImpitRuntimeDir(): string;
package/dist/refresh.mjs CHANGED
@@ -5,11 +5,11 @@ import {
5
5
  isImpitAvailable,
6
6
  loadImpit,
7
7
  refreshAccountInfo
8
- } from "./chunk-DQQISMYN.mjs";
9
- import "./chunk-U7QPUNRH.mjs";
10
- import "./chunk-S677V2JU.mjs";
8
+ } from "./chunk-V4LHDNWJ.mjs";
9
+ import "./chunk-DXR6EEZH.mjs";
10
+ import "./chunk-C5I7KXHK.mjs";
11
11
  import "./chunk-MTDFKNXX.mjs";
12
- import "./chunk-HJIXH6CL.mjs";
12
+ import "./chunk-E3GRJXXJ.mjs";
13
13
  import "./chunk-4UEJOM6W.mjs";
14
14
  export {
15
15
  getImpitRuntimeDir,