perplexity-user-mcp 0.8.42 → 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.
- package/dist/attachments.d.ts +10 -20
- package/dist/browser-window.d.ts +1 -0
- package/dist/cf-warmup.d.ts +32 -0
- package/dist/checks/browser.d.ts +12 -100
- package/dist/checks/config.d.ts +25 -91
- package/dist/checks/ide.d.ts +31 -89
- package/dist/checks/mcp.d.ts +12 -61
- package/dist/checks/native-deps.d.ts +46 -131
- package/dist/checks/network.d.ts +13 -71
- package/dist/checks/probe.d.ts +20 -92
- package/dist/checks/profiles.d.ts +13 -99
- package/dist/checks/profiles.mjs +35 -0
- package/dist/checks/runtime.d.ts +24 -89
- package/dist/checks/vault.d.ts +13 -142
- package/dist/checks/vault.mjs +6 -11
- package/dist/{chunk-T6ARJK2P.mjs → chunk-2B5OQUXR.mjs} +6 -6
- package/dist/{chunk-2FPGJKCA.mjs → chunk-2EE7MNP2.mjs} +2 -2
- package/dist/{chunk-Z4OLYVB2.mjs → chunk-2OVLCZHU.mjs} +1 -1
- package/dist/{chunk-WDIW33DA.mjs → chunk-3LUO5ATM.mjs} +1 -1
- package/dist/{chunk-B65IJQZJ.mjs → chunk-6E6XTHTG.mjs} +1 -1
- package/dist/{chunk-S677V2JU.mjs → chunk-C5I7KXHK.mjs} +32 -2
- package/dist/{chunk-TDXETAQT.mjs → chunk-DKEJZ4FI.mjs} +1 -1
- package/dist/{chunk-U7QPUNRH.mjs → chunk-DXR6EEZH.mjs} +26 -7
- package/dist/{chunk-HJIXH6CL.mjs → chunk-E3GRJXXJ.mjs} +2 -0
- package/dist/{chunk-RK4EBZJ3.mjs → chunk-E75J42W5.mjs} +11 -8
- package/dist/{chunk-452DK6OS.mjs → chunk-FNHYUE22.mjs} +2 -2
- package/dist/{chunk-D254EFYB.mjs → chunk-GBI2U336.mjs} +1 -1
- package/dist/chunk-GPUGKWXH.mjs +17 -0
- package/dist/{chunk-HNSPNCFH.mjs → chunk-KSNV3ZVY.mjs} +1 -1
- package/dist/{chunk-XTRJSV72.mjs → chunk-LGH5BSUY.mjs} +1 -1
- package/dist/{chunk-KJFX2ZXR.mjs → chunk-NMKNEEZB.mjs} +1 -1
- package/dist/{chunk-FKQ3HP4Q.mjs → chunk-TIWHN4IW.mjs} +1 -1
- package/dist/{chunk-V4U3JM4R.mjs → chunk-TSLRTZYR.mjs} +1 -1
- package/dist/{chunk-DQQISMYN.mjs → chunk-V4LHDNWJ.mjs} +2 -2
- package/dist/{chunk-C3HPFFTD.mjs → chunk-WHVJ724K.mjs} +84 -44
- package/dist/cli.d.ts +14 -1317
- package/dist/cli.mjs +14 -21
- package/dist/client.d.ts +27 -24
- package/dist/client.mjs +6 -6
- package/dist/cloud-sync.d.ts +65 -42
- package/dist/cloud-sync.mjs +8 -8
- package/dist/config.d.ts +35 -39
- package/dist/config.mjs +3 -3
- package/dist/cookie-jar.d.ts +77 -0
- package/dist/daemon/attach.d.ts +5 -12
- package/dist/daemon/attach.mjs +17 -17
- package/dist/daemon/audit.d.ts +5 -7
- package/dist/daemon/audit.mjs +2 -2
- package/dist/daemon/client-http.d.ts +10 -16
- package/dist/daemon/client-http.mjs +17 -17
- package/dist/daemon/index.d.ts +17 -14
- package/dist/daemon/index.mjs +18 -18
- package/dist/daemon/install-tunnel.d.ts +8 -34
- package/dist/daemon/install-tunnel.mjs +2 -2
- package/dist/daemon/launcher.d.ts +24 -29
- package/dist/daemon/launcher.mjs +16 -16
- package/dist/daemon/local-tokens.d.ts +23 -0
- package/dist/daemon/lockfile.d.ts +10 -12
- package/dist/daemon/lockfile.mjs +2 -2
- package/dist/daemon/oauth-consent-cache.d.ts +86 -0
- package/dist/daemon/oauth-provider.d.ts +132 -0
- package/dist/daemon/public-pages.d.ts +9 -0
- package/dist/daemon/security.d.ts +52 -0
- package/dist/daemon/server.d.ts +12 -83
- package/dist/daemon/server.mjs +11 -11
- package/dist/daemon/token.d.ts +7 -9
- package/dist/daemon/token.mjs +2 -2
- package/dist/daemon/tunnel-providers/cloudflared-named-setup.d.ts +140 -0
- package/dist/daemon/tunnel-providers/cloudflared-named.d.ts +45 -0
- package/dist/daemon/tunnel-providers/cloudflared-quick.d.ts +8 -0
- package/dist/daemon/tunnel-providers/index.d.ts +16 -327
- package/dist/daemon/tunnel-providers/index.mjs +3 -3
- package/dist/daemon/tunnel-providers/ngrok-config.d.ts +18 -0
- package/dist/daemon/tunnel-providers/ngrok.d.ts +68 -0
- package/dist/daemon/tunnel-providers/types.d.ts +56 -0
- package/dist/daemon/tunnel.d.ts +5 -7
- package/dist/debug-tracer.d.ts +2 -0
- package/dist/doctor-report.d.ts +17 -22
- package/dist/doctor.d.ts +12 -44
- package/dist/doctor.mjs +2 -2
- package/dist/export.d.ts +11 -18
- package/dist/export.mjs +4 -4
- package/dist/format.d.ts +52 -0
- package/dist/fs-utils.d.ts +8 -0
- package/dist/health-check.d.ts +1 -108
- package/dist/health-check.mjs +3 -3
- package/dist/history-store.d.ts +29 -65
- package/dist/history-store.mjs +2 -2
- package/dist/impit-login-runner.d.ts +1 -469
- package/dist/impit-login-runner.mjs +4 -4
- package/dist/index.d.ts +25 -149
- package/dist/index.mjs +22 -20
- package/dist/is-main-module.d.ts +9 -0
- package/dist/login-runner.d.ts +1 -333
- package/dist/login-runner.mjs +13 -13
- package/dist/login.d.ts +5 -0
- package/dist/logout.d.ts +2 -28
- package/dist/logout.mjs +3 -2
- package/dist/manual-login-runner.d.ts +1 -150
- package/dist/manual-login-runner.mjs +11 -11
- package/dist/{native-deps-IE4B55EL.mjs → native-deps-FCSYDL4W.mjs} +4 -4
- package/dist/native-deps.d.ts +36 -0
- package/dist/package-version.d.ts +1 -0
- package/dist/profiles.d.ts +41 -41
- package/dist/profiles.mjs +1 -1
- package/dist/prompts.d.ts +2 -0
- package/dist/redact.d.ts +14 -142
- package/dist/refresh.d.ts +11 -16
- package/dist/refresh.mjs +4 -4
- package/dist/reinit-watcher.d.ts +15 -24
- package/dist/reinit-watcher.mjs +2 -2
- package/dist/resources.d.ts +5 -0
- package/dist/safe-write.d.ts +16 -0
- package/dist/session-metadata.d.ts +45 -0
- package/dist/tool-config.d.ts +10 -0
- package/dist/tools.d.ts +23 -0
- package/dist/tty-prompt.d.ts +18 -34
- package/dist/vault.d.ts +114 -34
- package/dist/vault.mjs +6 -4
- package/dist/viewer-detect.d.ts +2 -4
- package/dist/viewers.d.ts +13 -18
- package/dist/viewers.mjs +1 -1
- package/package.json +2 -2
- package/dist/cloud-sync.d-Cqt6y18U.d.ts +0 -42
- package/dist/doctor.d-CXmUqOXX.d.ts +0 -43
- package/dist/history-store.d-BzjBF2m3.d.ts +0 -65
- package/dist/native-deps-BNThFHxa.d.ts +0 -175
- package/dist/profiles.d-DqS1oZWr.d.ts +0 -41
- package/dist/session-metadata-B9aV_n5g.d.ts +0 -148
- package/dist/vault.d-BSJWDLhp.d.ts +0 -37
- package/dist/viewer-detect.d-HWGnyFAA.d.ts +0 -4
- package/dist/viewers.d-BGCK6sw6.d.ts +0 -10
|
@@ -1,150 +1 @@
|
|
|
1
|
-
|
|
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-
|
|
9
|
+
} from "./chunk-DXR6EEZH.mjs";
|
|
10
10
|
import {
|
|
11
11
|
Vault
|
|
12
|
-
} from "./chunk-
|
|
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-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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-
|
|
4
|
-
import "./chunk-
|
|
5
|
-
import "./chunk-
|
|
3
|
+
} from "./chunk-V4LHDNWJ.mjs";
|
|
4
|
+
import "./chunk-DXR6EEZH.mjs";
|
|
5
|
+
import "./chunk-C5I7KXHK.mjs";
|
|
6
6
|
import "./chunk-MTDFKNXX.mjs";
|
|
7
|
-
import "./chunk-
|
|
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;
|
package/dist/profiles.d.ts
CHANGED
|
@@ -1,41 +1,41 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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
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
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
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-
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
8
|
+
} from "./chunk-V4LHDNWJ.mjs";
|
|
9
|
+
import "./chunk-DXR6EEZH.mjs";
|
|
10
|
+
import "./chunk-C5I7KXHK.mjs";
|
|
11
11
|
import "./chunk-MTDFKNXX.mjs";
|
|
12
|
-
import "./chunk-
|
|
12
|
+
import "./chunk-E3GRJXXJ.mjs";
|
|
13
13
|
import "./chunk-4UEJOM6W.mjs";
|
|
14
14
|
export {
|
|
15
15
|
getImpitRuntimeDir,
|