perplexity-user-mcp 0.8.42 → 0.8.47
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 +11 -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 +37 -92
- package/dist/checks/probe.mjs +29 -0
- 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-WDIW33DA.mjs → chunk-3LUO5ATM.mjs} +1 -1
- package/dist/{chunk-HNSPNCFH.mjs → chunk-6CAXNBDD.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-RK4EBZJ3.mjs → chunk-D2ZQGKHM.mjs} +11 -8
- 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-C3HPFFTD.mjs → chunk-GBHPJ7I7.mjs} +136 -48
- package/dist/{chunk-D254EFYB.mjs → chunk-GBI2U336.mjs} +1 -1
- package/dist/chunk-GPUGKWXH.mjs +17 -0
- package/dist/chunk-KVV3JBSN.mjs +32 -0
- package/dist/{chunk-XTRJSV72.mjs → chunk-LGH5BSUY.mjs} +1 -1
- package/dist/{chunk-KJFX2ZXR.mjs → chunk-NMKNEEZB.mjs} +1 -1
- package/dist/{chunk-T6ARJK2P.mjs → chunk-P6YOLJ5T.mjs} +6 -6
- package/dist/{chunk-452DK6OS.mjs → chunk-QXYMYCHC.mjs} +2 -2
- package/dist/{chunk-Z4OLYVB2.mjs → chunk-SCZQCV7M.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-2FPGJKCA.mjs → chunk-YD25G5AD.mjs} +2 -2
- package/dist/cli.d.ts +14 -1317
- package/dist/cli.mjs +14 -21
- package/dist/client.d.ts +39 -24
- package/dist/client.mjs +9 -6
- package/dist/cloud-sync.d.ts +65 -42
- package/dist/cloud-sync.mjs +9 -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 +18 -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 +18 -17
- package/dist/daemon/index.d.ts +17 -14
- package/dist/daemon/index.mjs +19 -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 +17 -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 +12 -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 +44 -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 +23 -20
- package/dist/is-main-module.d.ts +9 -0
- package/dist/login-runner.d.ts +1 -333
- package/dist/login-runner.mjs +18 -38
- 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
package/dist/index.mjs
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
CATEGORIES,
|
|
4
4
|
formatReportMarkdown,
|
|
5
5
|
runAll
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-6CAXNBDD.mjs";
|
|
7
7
|
import {
|
|
8
8
|
buildIssueBody,
|
|
9
9
|
buildIssueUrl,
|
|
@@ -12,15 +12,15 @@ import {
|
|
|
12
12
|
} from "./chunk-DPGMKSSA.mjs";
|
|
13
13
|
import {
|
|
14
14
|
attachToDaemon
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-SCZQCV7M.mjs";
|
|
16
16
|
import {
|
|
17
17
|
ensureDaemon,
|
|
18
18
|
startDaemon
|
|
19
|
-
} from "./chunk-
|
|
20
|
-
import "./chunk-
|
|
19
|
+
} from "./chunk-D2ZQGKHM.mjs";
|
|
20
|
+
import "./chunk-LGH5BSUY.mjs";
|
|
21
21
|
import "./chunk-6YMQVLFX.mjs";
|
|
22
|
-
import "./chunk-
|
|
23
|
-
import "./chunk-
|
|
22
|
+
import "./chunk-TIWHN4IW.mjs";
|
|
23
|
+
import "./chunk-NMKNEEZB.mjs";
|
|
24
24
|
import {
|
|
25
25
|
buildAnswerPreview,
|
|
26
26
|
buildHistoryBody,
|
|
@@ -35,27 +35,31 @@ import {
|
|
|
35
35
|
registerTools,
|
|
36
36
|
saveToolConfig,
|
|
37
37
|
watchToolConfig
|
|
38
|
-
} from "./chunk-
|
|
39
|
-
import "./chunk-
|
|
40
|
-
import "./chunk-
|
|
38
|
+
} from "./chunk-P6YOLJ5T.mjs";
|
|
39
|
+
import "./chunk-TSLRTZYR.mjs";
|
|
40
|
+
import "./chunk-DKEJZ4FI.mjs";
|
|
41
41
|
import {
|
|
42
42
|
watchActiveProfile,
|
|
43
43
|
watchReinit
|
|
44
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-3LUO5ATM.mjs";
|
|
45
|
+
import {
|
|
46
|
+
isMainModule
|
|
47
|
+
} from "./chunk-GPUGKWXH.mjs";
|
|
45
48
|
import "./chunk-HMKLWVXB.mjs";
|
|
46
49
|
import {
|
|
47
50
|
hydrateCloudHistoryEntry,
|
|
48
51
|
syncCloudHistory
|
|
49
|
-
} from "./chunk-
|
|
52
|
+
} from "./chunk-YD25G5AD.mjs";
|
|
50
53
|
import {
|
|
51
54
|
PerplexityClient
|
|
52
|
-
} from "./chunk-
|
|
55
|
+
} from "./chunk-GBHPJ7I7.mjs";
|
|
56
|
+
import "./chunk-KVV3JBSN.mjs";
|
|
53
57
|
import {
|
|
54
58
|
getImpitRuntimeDir,
|
|
55
59
|
getModelsCacheInfo,
|
|
56
60
|
isImpitAvailable,
|
|
57
61
|
refreshAccountInfo
|
|
58
|
-
} from "./chunk-
|
|
62
|
+
} from "./chunk-V4LHDNWJ.mjs";
|
|
59
63
|
import {
|
|
60
64
|
append,
|
|
61
65
|
countAll,
|
|
@@ -75,24 +79,23 @@ import {
|
|
|
75
79
|
tag,
|
|
76
80
|
update,
|
|
77
81
|
upsertFromCloud
|
|
78
|
-
} from "./chunk-
|
|
82
|
+
} from "./chunk-6E6XTHTG.mjs";
|
|
79
83
|
import {
|
|
80
84
|
exportThread
|
|
81
|
-
} from "./chunk-
|
|
85
|
+
} from "./chunk-GBI2U336.mjs";
|
|
82
86
|
import {
|
|
83
87
|
findBrowser
|
|
84
|
-
} from "./chunk-
|
|
88
|
+
} from "./chunk-DXR6EEZH.mjs";
|
|
85
89
|
import {
|
|
86
90
|
getUnsealMaterial
|
|
87
|
-
} from "./chunk-
|
|
91
|
+
} from "./chunk-C5I7KXHK.mjs";
|
|
88
92
|
import "./chunk-MTDFKNXX.mjs";
|
|
89
93
|
import {
|
|
90
94
|
getActiveName
|
|
91
|
-
} from "./chunk-
|
|
95
|
+
} from "./chunk-E3GRJXXJ.mjs";
|
|
92
96
|
import "./chunk-4UEJOM6W.mjs";
|
|
93
97
|
|
|
94
98
|
// src/index.ts
|
|
95
|
-
import { pathToFileURL } from "url";
|
|
96
99
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
97
100
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
98
101
|
var client;
|
|
@@ -228,7 +231,7 @@ async function main() {
|
|
|
228
231
|
await shutdownClientWithTimeout(client);
|
|
229
232
|
}
|
|
230
233
|
}
|
|
231
|
-
if (
|
|
234
|
+
if (isMainModule(import.meta.url)) {
|
|
232
235
|
runEntrypoint().catch(async (error) => {
|
|
233
236
|
console.error("[perplexity-mcp] Fatal error:", error);
|
|
234
237
|
await shutdownClientWithTimeout(client);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns true when the importing module is the process entrypoint (i.e. was
|
|
3
|
+
* invoked as `node <script>` or via a bin symlink), false when it was imported
|
|
4
|
+
* by another module.
|
|
5
|
+
*
|
|
6
|
+
* @param {string} metaUrl - The caller's `import.meta.url`
|
|
7
|
+
* @returns {boolean}
|
|
8
|
+
*/
|
|
9
|
+
export function isMainModule(metaUrl: string): boolean;
|
package/dist/login-runner.d.ts
CHANGED
|
@@ -1,333 +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, b as buildRuntimeEndpoints, p as pageRequest } from './session-metadata-B9aV_n5g.js';
|
|
8
|
-
|
|
9
|
-
async function minimizePageWindow(page) {
|
|
10
|
-
try {
|
|
11
|
-
const context = page?.context?.();
|
|
12
|
-
if (!context || typeof context.newCDPSession !== "function") return false;
|
|
13
|
-
const session = await context.newCDPSession(page);
|
|
14
|
-
try {
|
|
15
|
-
const { windowId } = await session.send("Browser.getWindowForTarget");
|
|
16
|
-
await session.send("Browser.setWindowBounds", {
|
|
17
|
-
windowId,
|
|
18
|
-
bounds: { windowState: "minimized" },
|
|
19
|
-
});
|
|
20
|
-
return true;
|
|
21
|
-
} finally {
|
|
22
|
-
await session.detach().catch(() => {});
|
|
23
|
-
}
|
|
24
|
-
} catch {
|
|
25
|
-
return false;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// Auto-OTP login runner. Parent provides email via PERPLEXITY_EMAIL; we
|
|
30
|
-
// drive the real Perplexity email+OTP flow (NextAuth on the live site,
|
|
31
|
-
// legacy /login/* on the local mock), prompt for the six-digit code via
|
|
32
|
-
// IPC, and persist the resulting session into the profile vault.
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const ORIGIN = process.env.PERPLEXITY_ORIGIN || "https://www.perplexity.ai";
|
|
36
|
-
const LOGIN_PATH = process.env.PERPLEXITY_LOGIN_PATH || "/account";
|
|
37
|
-
const EMAIL = process.env.PERPLEXITY_EMAIL;
|
|
38
|
-
const OTP_TIMEOUT_MS = Number(process.env.PERPLEXITY_OTP_TIMEOUT_MS ?? 300_000);
|
|
39
|
-
const CF_TIMEOUT_MS = Number(process.env.PERPLEXITY_CF_TIMEOUT_MS ?? 20_000);
|
|
40
|
-
const MAX_RETRIES = 2;
|
|
41
|
-
|
|
42
|
-
function resolveProfile() {
|
|
43
|
-
return process.env.PERPLEXITY_PROFILE || getActiveName() || "default";
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function isLocalOrigin(origin) {
|
|
47
|
-
return /^https?:\/\/(127\.0\.0\.1|localhost)(:\d+)?(?:\/|$)/i.test(origin);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function ipc(msg) { if (process.send) process.send(msg); }
|
|
51
|
-
function emit(obj) { process.stdout.write(JSON.stringify(obj) + "\n"); }
|
|
52
|
-
|
|
53
|
-
async function awaitOtp() {
|
|
54
|
-
return new Promise((resolve, reject) => {
|
|
55
|
-
const timer = setTimeout(() => {
|
|
56
|
-
process.removeListener("message", handler);
|
|
57
|
-
reject(new Error("otp_timeout"));
|
|
58
|
-
}, OTP_TIMEOUT_MS);
|
|
59
|
-
const handler = (m) => {
|
|
60
|
-
if (m && typeof m.otp === "string") {
|
|
61
|
-
clearTimeout(timer);
|
|
62
|
-
process.removeListener("message", handler);
|
|
63
|
-
resolve(m.otp);
|
|
64
|
-
}
|
|
65
|
-
};
|
|
66
|
-
process.on("message", handler);
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
async function main() {
|
|
71
|
-
if (!EMAIL) {
|
|
72
|
-
emit({ ok: false, reason: "no_email" });
|
|
73
|
-
process.exit(1);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
const PROFILE = resolveProfile();
|
|
77
|
-
const localOrigin = isLocalOrigin(ORIGIN);
|
|
78
|
-
|
|
79
|
-
let executablePath;
|
|
80
|
-
let channel;
|
|
81
|
-
if (!localOrigin) {
|
|
82
|
-
try {
|
|
83
|
-
({ path: executablePath, channel } = await resolveBrowserExecutable());
|
|
84
|
-
} catch (err) {
|
|
85
|
-
emit({ ok: false, reason: "chrome_missing", error: redact(String(err?.message ?? err)) });
|
|
86
|
-
process.exit(4);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const browser = await chromium.launch({
|
|
91
|
-
headless: localOrigin,
|
|
92
|
-
...(executablePath ? { executablePath } : {}),
|
|
93
|
-
...(channel && ["chrome", "msedge", "chromium"].includes(channel) ? { channel } : {}),
|
|
94
|
-
args: localOrigin ? [] : ["--start-minimized"],
|
|
95
|
-
});
|
|
96
|
-
const ctx = await browser.newContext({ ignoreHTTPSErrors: true });
|
|
97
|
-
const page = await ctx.newPage();
|
|
98
|
-
|
|
99
|
-
try {
|
|
100
|
-
await page.goto(`${ORIGIN}${LOGIN_PATH}`, { waitUntil: "domcontentloaded", timeout: 30_000 });
|
|
101
|
-
} catch {}
|
|
102
|
-
if (!localOrigin) await minimizePageWindow(page);
|
|
103
|
-
|
|
104
|
-
const ready = await waitForLoginReady(page);
|
|
105
|
-
if (!ready) {
|
|
106
|
-
const title = await page.title().catch(() => "");
|
|
107
|
-
await browser.close().catch(() => {});
|
|
108
|
-
emit({ ok: false, reason: /just a moment/i.test(title) ? "cf_blocked" : "auto_unsupported" });
|
|
109
|
-
process.exit(/just a moment/i.test(title) ? 3 : 2);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
const liveAttempt = await startLiveEmailFlow(page);
|
|
113
|
-
let authFlow = liveAttempt;
|
|
114
|
-
if (liveAttempt.kind === "unsupported") {
|
|
115
|
-
authFlow = await startLegacyMockFlow(page);
|
|
116
|
-
}
|
|
117
|
-
if (!localOrigin) await minimizePageWindow(page);
|
|
118
|
-
|
|
119
|
-
if (authFlow.kind === "sso_required") {
|
|
120
|
-
await browser.close().catch(() => {});
|
|
121
|
-
emit({ ok: false, reason: "sso_required" });
|
|
122
|
-
process.exit(2);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
if (authFlow.kind === "unsupported") {
|
|
126
|
-
await browser.close().catch(() => {});
|
|
127
|
-
emit({ ok: false, reason: "auto_unsupported", detail: authFlow.detail });
|
|
128
|
-
process.exit(2);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
if (authFlow.kind === "email_rejected") {
|
|
132
|
-
await browser.close().catch(() => {});
|
|
133
|
-
emit({ ok: false, reason: "email_rejected", detail: authFlow.detail });
|
|
134
|
-
process.exit(2);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
138
|
-
ipc({ phase: "awaiting_otp", attempt });
|
|
139
|
-
let otp;
|
|
140
|
-
try {
|
|
141
|
-
otp = await awaitOtp();
|
|
142
|
-
} catch {
|
|
143
|
-
await browser.close().catch(() => {});
|
|
144
|
-
emit({ ok: false, reason: "otp_timeout" });
|
|
145
|
-
process.exit(2);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
const submitResp = await submitOtp(page, authFlow, otp);
|
|
149
|
-
if (submitResp.ok) {
|
|
150
|
-
const allCookies = await ctx.cookies();
|
|
151
|
-
const metadata = await collectSessionMetadata(page, ORIGIN, {
|
|
152
|
-
sessionData: submitResp.sessionData,
|
|
153
|
-
sessionTimeoutMs: 10_000,
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
const vault = new Vault();
|
|
157
|
-
await vault.set(PROFILE, "cookies", JSON.stringify(allCookies));
|
|
158
|
-
if (metadata.sessionData?.user?.email) await vault.set(PROFILE, "email", metadata.sessionData.user.email);
|
|
159
|
-
if (metadata.sessionData?.user?.id) await vault.set(PROFILE, "userId", metadata.sessionData.user.id);
|
|
160
|
-
|
|
161
|
-
const paths = getProfilePaths(PROFILE);
|
|
162
|
-
if (!existsSync(paths.dir)) mkdirSync(paths.dir, { recursive: true });
|
|
163
|
-
writeFileSync(paths.modelsCache, JSON.stringify(metadata.cache, null, 2));
|
|
164
|
-
recordLoginSuccess(PROFILE, { tier: metadata.tier, loginMode: "auto", lastLogin: new Date().toISOString() });
|
|
165
|
-
writeFileSync(paths.reinit, String(Date.now()));
|
|
166
|
-
|
|
167
|
-
await browser.close().catch(() => {});
|
|
168
|
-
emit({ ok: true, tier: metadata.tier, modelCount: Object.keys(metadata.models?.models ?? {}).length });
|
|
169
|
-
process.exit(0);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
if (authFlow.kind === "live") {
|
|
173
|
-
await page.goto(authFlow.verifyUrl, { waitUntil: "domcontentloaded", timeout: 30_000 }).catch(() => {});
|
|
174
|
-
if (!localOrigin) await minimizePageWindow(page);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
if (attempt === MAX_RETRIES) {
|
|
178
|
-
await browser.close().catch(() => {});
|
|
179
|
-
emit({ ok: false, reason: "otp_rejected" });
|
|
180
|
-
process.exit(2);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
async function waitForLoginReady(page) {
|
|
186
|
-
const started = Date.now();
|
|
187
|
-
while (Date.now() - started < CF_TIMEOUT_MS) {
|
|
188
|
-
if (await page.locator('input[type="email"]').count().catch(() => 0)) {
|
|
189
|
-
return true;
|
|
190
|
-
}
|
|
191
|
-
const title = await page.title().catch(() => "");
|
|
192
|
-
if (title && !/just a moment/i.test(title)) {
|
|
193
|
-
const body = await page.locator("body").innerText().catch(() => "");
|
|
194
|
-
if (/continue with email/i.test(body) || /single sign-on/i.test(body) || /continue/i.test(body)) {
|
|
195
|
-
return true;
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
await page.waitForTimeout(500);
|
|
199
|
-
}
|
|
200
|
-
return false;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
async function startLiveEmailFlow(page) {
|
|
204
|
-
const endpoints = buildRuntimeEndpoints(ORIGIN);
|
|
205
|
-
const csrf = await pageRequest(page, endpoints.csrf);
|
|
206
|
-
if (!(csrf.ok && csrf.contentType.includes("json") && csrf.json?.csrfToken)) {
|
|
207
|
-
return {
|
|
208
|
-
kind: "unsupported",
|
|
209
|
-
detail: { step: "csrf", status: csrf.status, contentType: csrf.contentType, error: csrf.error ?? undefined },
|
|
210
|
-
};
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
const sso = await pageRequest(page, endpoints.ssoDetails, {
|
|
214
|
-
method: "POST",
|
|
215
|
-
headers: { "content-type": "application/json" },
|
|
216
|
-
body: JSON.stringify({ email: EMAIL }),
|
|
217
|
-
});
|
|
218
|
-
if (sso.ok && sso.json?.organization) {
|
|
219
|
-
return { kind: "sso_required" };
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
const redirectUrl = `${ORIGIN}/account?login-source=settings`;
|
|
223
|
-
const signIn = await pageRequest(page, endpoints.signInEmail, {
|
|
224
|
-
method: "POST",
|
|
225
|
-
headers: { "content-type": "application/json" },
|
|
226
|
-
body: JSON.stringify({
|
|
227
|
-
email: EMAIL,
|
|
228
|
-
useNumericOtp: "true",
|
|
229
|
-
csrfToken: csrf.json.csrfToken,
|
|
230
|
-
callbackUrl: `${redirectUrl}#locale=en-US`,
|
|
231
|
-
json: "true",
|
|
232
|
-
}),
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
if (!(signIn.ok && signIn.contentType.includes("json") && signIn.json?.url)) {
|
|
236
|
-
return {
|
|
237
|
-
kind: signIn.status >= 400 && signIn.status < 500 ? "email_rejected" : "unsupported",
|
|
238
|
-
detail: { step: "signin_email", status: signIn.status, contentType: signIn.contentType, error: signIn.error ?? undefined },
|
|
239
|
-
};
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
const verifyUrl = new URL(signIn.json.url, ORIGIN);
|
|
243
|
-
verifyUrl.searchParams.set("email", EMAIL);
|
|
244
|
-
verifyUrl.searchParams.set("redirectUrl", redirectUrl);
|
|
245
|
-
await page.goto(verifyUrl.toString(), { waitUntil: "domcontentloaded", timeout: 30_000 }).catch(() => {});
|
|
246
|
-
|
|
247
|
-
return {
|
|
248
|
-
kind: "live",
|
|
249
|
-
redirectUrl,
|
|
250
|
-
verifyUrl: verifyUrl.toString(),
|
|
251
|
-
};
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
async function startLegacyMockFlow(page) {
|
|
255
|
-
const emailResp = await pageRequest(page, `${ORIGIN}/login/email`, {
|
|
256
|
-
method: "POST",
|
|
257
|
-
headers: { "content-type": "application/json" },
|
|
258
|
-
body: JSON.stringify({ email: EMAIL }),
|
|
259
|
-
});
|
|
260
|
-
|
|
261
|
-
if (emailResp.redirected && (emailResp.url || "").includes("/sso")) {
|
|
262
|
-
return { kind: "sso_required" };
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
const looksUnsupported =
|
|
266
|
-
emailResp.status === 404 ||
|
|
267
|
-
emailResp.status === 405 ||
|
|
268
|
-
emailResp.status >= 500 ||
|
|
269
|
-
!emailResp.contentType.includes("json");
|
|
270
|
-
|
|
271
|
-
if (looksUnsupported) {
|
|
272
|
-
return {
|
|
273
|
-
kind: "unsupported",
|
|
274
|
-
detail: { step: "legacy_email", status: emailResp.status, contentType: emailResp.contentType, error: emailResp.error ?? undefined },
|
|
275
|
-
};
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
if (!emailResp.ok) {
|
|
279
|
-
return { kind: "email_rejected", detail: emailResp.status };
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
return { kind: "legacy" };
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
async function submitOtp(page, flow, otp) {
|
|
286
|
-
if (flow.kind === "legacy") {
|
|
287
|
-
const submitResp = await pageRequest(page, `${ORIGIN}/login/otp`, {
|
|
288
|
-
method: "POST",
|
|
289
|
-
headers: { "content-type": "application/json" },
|
|
290
|
-
body: JSON.stringify({ email: EMAIL, otp }),
|
|
291
|
-
});
|
|
292
|
-
if (submitResp.status !== 200) {
|
|
293
|
-
return { ok: false };
|
|
294
|
-
}
|
|
295
|
-
const metadata = await collectSessionMetadata(page, ORIGIN, { sessionTimeoutMs: 2_000 });
|
|
296
|
-
return { ok: !!metadata.sessionData?.user?.id, sessionData: metadata.sessionData };
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
const endpoints = buildRuntimeEndpoints(ORIGIN);
|
|
300
|
-
const redirectResp = await pageRequest(page, endpoints.otpRedirectLink, {
|
|
301
|
-
method: "POST",
|
|
302
|
-
headers: { "content-type": "application/json" },
|
|
303
|
-
body: JSON.stringify({
|
|
304
|
-
email: EMAIL,
|
|
305
|
-
otp,
|
|
306
|
-
redirectUrl: flow.redirectUrl,
|
|
307
|
-
emailLoginMethod: "web-otp",
|
|
308
|
-
loginSource: null,
|
|
309
|
-
}),
|
|
310
|
-
});
|
|
311
|
-
|
|
312
|
-
if (!(redirectResp.ok && redirectResp.contentType.includes("json") && redirectResp.json?.redirect)) {
|
|
313
|
-
return { ok: false };
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
const callbackUrl = new URL(redirectResp.json.redirect, ORIGIN).toString();
|
|
317
|
-
await page.goto(callbackUrl, { waitUntil: "domcontentloaded", timeout: 30_000 }).catch(() => {});
|
|
318
|
-
const metadata = await collectSessionMetadata(page, ORIGIN, { sessionTimeoutMs: 5_000 });
|
|
319
|
-
return { ok: !!metadata.sessionData?.user?.id, sessionData: metadata.sessionData };
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
main().catch((err) => {
|
|
323
|
-
const msg = err?.message ?? err;
|
|
324
|
-
const stack = err?.stack;
|
|
325
|
-
emit({
|
|
326
|
-
ok: false,
|
|
327
|
-
reason: "crash",
|
|
328
|
-
error: redact(String(msg ?? "unknown error")),
|
|
329
|
-
detail: redact(String(msg ?? "unknown error")),
|
|
330
|
-
...(stack ? { stack: redact(String(stack)) } : {}),
|
|
331
|
-
});
|
|
332
|
-
process.exit(5);
|
|
333
|
-
});
|
|
1
|
+
export {};
|
package/dist/login-runner.mjs
CHANGED
|
@@ -6,47 +6,27 @@ import {
|
|
|
6
6
|
import {
|
|
7
7
|
redact
|
|
8
8
|
} from "./chunk-HMKLWVXB.mjs";
|
|
9
|
+
import {
|
|
10
|
+
loginLaunchArgs,
|
|
11
|
+
minimizePageWindow
|
|
12
|
+
} from "./chunk-KVV3JBSN.mjs";
|
|
9
13
|
import {
|
|
10
14
|
resolveBrowserExecutable
|
|
11
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-DXR6EEZH.mjs";
|
|
12
16
|
import {
|
|
13
17
|
Vault
|
|
14
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-C5I7KXHK.mjs";
|
|
15
19
|
import "./chunk-MTDFKNXX.mjs";
|
|
16
20
|
import {
|
|
17
21
|
getActiveName,
|
|
18
22
|
getProfilePaths,
|
|
19
23
|
recordLoginSuccess
|
|
20
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-E3GRJXXJ.mjs";
|
|
21
25
|
import "./chunk-4UEJOM6W.mjs";
|
|
22
26
|
|
|
23
27
|
// src/login-runner.js
|
|
24
28
|
import { writeFileSync, existsSync, mkdirSync } from "fs";
|
|
25
29
|
import { chromium } from "patchright";
|
|
26
|
-
|
|
27
|
-
// src/browser-window.js
|
|
28
|
-
async function minimizePageWindow(page) {
|
|
29
|
-
try {
|
|
30
|
-
const context = page?.context?.();
|
|
31
|
-
if (!context || typeof context.newCDPSession !== "function") return false;
|
|
32
|
-
const session = await context.newCDPSession(page);
|
|
33
|
-
try {
|
|
34
|
-
const { windowId } = await session.send("Browser.getWindowForTarget");
|
|
35
|
-
await session.send("Browser.setWindowBounds", {
|
|
36
|
-
windowId,
|
|
37
|
-
bounds: { windowState: "minimized" }
|
|
38
|
-
});
|
|
39
|
-
return true;
|
|
40
|
-
} finally {
|
|
41
|
-
await session.detach().catch(() => {
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
} catch {
|
|
45
|
-
return false;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// src/login-runner.js
|
|
50
30
|
var ORIGIN = process.env.PERPLEXITY_ORIGIN || "https://www.perplexity.ai";
|
|
51
31
|
var LOGIN_PATH = process.env.PERPLEXITY_LOGIN_PATH || "/account";
|
|
52
32
|
var EMAIL = process.env.PERPLEXITY_EMAIL;
|
|
@@ -87,6 +67,7 @@ async function main() {
|
|
|
87
67
|
process.exit(1);
|
|
88
68
|
}
|
|
89
69
|
const PROFILE = resolveProfile();
|
|
70
|
+
const paths = getProfilePaths(PROFILE);
|
|
90
71
|
const localOrigin = isLocalOrigin(ORIGIN);
|
|
91
72
|
let executablePath;
|
|
92
73
|
let channel;
|
|
@@ -98,13 +79,13 @@ async function main() {
|
|
|
98
79
|
process.exit(4);
|
|
99
80
|
}
|
|
100
81
|
}
|
|
101
|
-
const
|
|
82
|
+
const ctx = await chromium.launchPersistentContext(paths.loginBrowserData, {
|
|
102
83
|
headless: localOrigin,
|
|
84
|
+
ignoreHTTPSErrors: true,
|
|
103
85
|
...executablePath ? { executablePath } : {},
|
|
104
86
|
...channel && ["chrome", "msedge", "chromium"].includes(channel) ? { channel } : {},
|
|
105
|
-
args: localOrigin
|
|
87
|
+
args: loginLaunchArgs(localOrigin)
|
|
106
88
|
});
|
|
107
|
-
const ctx = await browser.newContext({ ignoreHTTPSErrors: true });
|
|
108
89
|
const page = await ctx.newPage();
|
|
109
90
|
try {
|
|
110
91
|
await page.goto(`${ORIGIN}${LOGIN_PATH}`, { waitUntil: "domcontentloaded", timeout: 3e4 });
|
|
@@ -114,7 +95,7 @@ async function main() {
|
|
|
114
95
|
const ready = await waitForLoginReady(page);
|
|
115
96
|
if (!ready) {
|
|
116
97
|
const title = await page.title().catch(() => "");
|
|
117
|
-
await browser
|
|
98
|
+
await ctx.browser()?.close().catch(() => {
|
|
118
99
|
});
|
|
119
100
|
emit({ ok: false, reason: /just a moment/i.test(title) ? "cf_blocked" : "auto_unsupported" });
|
|
120
101
|
process.exit(/just a moment/i.test(title) ? 3 : 2);
|
|
@@ -126,19 +107,19 @@ async function main() {
|
|
|
126
107
|
}
|
|
127
108
|
if (!localOrigin) await minimizePageWindow(page);
|
|
128
109
|
if (authFlow.kind === "sso_required") {
|
|
129
|
-
await browser
|
|
110
|
+
await ctx.browser()?.close().catch(() => {
|
|
130
111
|
});
|
|
131
112
|
emit({ ok: false, reason: "sso_required" });
|
|
132
113
|
process.exit(2);
|
|
133
114
|
}
|
|
134
115
|
if (authFlow.kind === "unsupported") {
|
|
135
|
-
await browser
|
|
116
|
+
await ctx.browser()?.close().catch(() => {
|
|
136
117
|
});
|
|
137
118
|
emit({ ok: false, reason: "auto_unsupported", detail: authFlow.detail });
|
|
138
119
|
process.exit(2);
|
|
139
120
|
}
|
|
140
121
|
if (authFlow.kind === "email_rejected") {
|
|
141
|
-
await browser
|
|
122
|
+
await ctx.browser()?.close().catch(() => {
|
|
142
123
|
});
|
|
143
124
|
emit({ ok: false, reason: "email_rejected", detail: authFlow.detail });
|
|
144
125
|
process.exit(2);
|
|
@@ -149,7 +130,7 @@ async function main() {
|
|
|
149
130
|
try {
|
|
150
131
|
otp = await awaitOtp();
|
|
151
132
|
} catch {
|
|
152
|
-
await browser
|
|
133
|
+
await ctx.browser()?.close().catch(() => {
|
|
153
134
|
});
|
|
154
135
|
emit({ ok: false, reason: "otp_timeout" });
|
|
155
136
|
process.exit(2);
|
|
@@ -165,12 +146,11 @@ async function main() {
|
|
|
165
146
|
await vault.set(PROFILE, "cookies", JSON.stringify(allCookies));
|
|
166
147
|
if (metadata.sessionData?.user?.email) await vault.set(PROFILE, "email", metadata.sessionData.user.email);
|
|
167
148
|
if (metadata.sessionData?.user?.id) await vault.set(PROFILE, "userId", metadata.sessionData.user.id);
|
|
168
|
-
const paths = getProfilePaths(PROFILE);
|
|
169
149
|
if (!existsSync(paths.dir)) mkdirSync(paths.dir, { recursive: true });
|
|
170
150
|
writeFileSync(paths.modelsCache, JSON.stringify(metadata.cache, null, 2));
|
|
171
151
|
recordLoginSuccess(PROFILE, { tier: metadata.tier, loginMode: "auto", lastLogin: (/* @__PURE__ */ new Date()).toISOString() });
|
|
172
152
|
writeFileSync(paths.reinit, String(Date.now()));
|
|
173
|
-
await browser
|
|
153
|
+
await ctx.browser()?.close().catch(() => {
|
|
174
154
|
});
|
|
175
155
|
emit({ ok: true, tier: metadata.tier, modelCount: Object.keys(metadata.models?.models ?? {}).length });
|
|
176
156
|
process.exit(0);
|
|
@@ -181,7 +161,7 @@ async function main() {
|
|
|
181
161
|
if (!localOrigin) await minimizePageWindow(page);
|
|
182
162
|
}
|
|
183
163
|
if (attempt === MAX_RETRIES) {
|
|
184
|
-
await browser
|
|
164
|
+
await ctx.browser()?.close().catch(() => {
|
|
185
165
|
});
|
|
186
166
|
emit({ ok: false, reason: "otp_rejected" });
|
|
187
167
|
process.exit(2);
|
package/dist/login.d.ts
ADDED
package/dist/logout.d.ts
CHANGED
|
@@ -1,28 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import { getActiveName, setActive, getProfilePaths, listProfiles, getProfile } from './profiles.d-DqS1oZWr.js';
|
|
4
|
-
|
|
5
|
-
async function softLogout(name) {
|
|
6
|
-
const vault = new Vault();
|
|
7
|
-
await vault.delete(name, "cookies").catch(() => {});
|
|
8
|
-
const paths = getProfilePaths(name);
|
|
9
|
-
const meta = getProfile(name);
|
|
10
|
-
if (meta) {
|
|
11
|
-
delete meta.lastLogin;
|
|
12
|
-
writeFileSync(paths.meta, JSON.stringify(meta, null, 2) + "\n");
|
|
13
|
-
}
|
|
14
|
-
if (existsSync(paths.dir)) writeFileSync(paths.reinit, String(Date.now()));
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
async function hardLogout(name) {
|
|
18
|
-
const paths = getProfilePaths(name);
|
|
19
|
-
if (existsSync(paths.dir)) rmSync(paths.dir, { recursive: true, force: true });
|
|
20
|
-
if (getActiveName() === name) {
|
|
21
|
-
const remaining = listProfiles();
|
|
22
|
-
if (remaining.length > 0) {
|
|
23
|
-
setActive(remaining[0].name);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export { hardLogout, softLogout };
|
|
1
|
+
export function softLogout(name: any): Promise<void>;
|
|
2
|
+
export function hardLogout(name: any): Promise<void>;
|
package/dist/logout.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Vault
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-C5I7KXHK.mjs";
|
|
4
4
|
import "./chunk-MTDFKNXX.mjs";
|
|
5
5
|
import {
|
|
6
6
|
createProfile,
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
getProfilePaths,
|
|
10
10
|
listProfiles,
|
|
11
11
|
setActive
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-E3GRJXXJ.mjs";
|
|
13
13
|
import "./chunk-4UEJOM6W.mjs";
|
|
14
14
|
|
|
15
15
|
// src/logout.js
|
|
@@ -24,6 +24,7 @@ async function softLogout(name) {
|
|
|
24
24
|
delete meta.lastLogin;
|
|
25
25
|
writeFileSync(paths.meta, JSON.stringify(meta, null, 2) + "\n");
|
|
26
26
|
}
|
|
27
|
+
if (existsSync(paths.loginBrowserData)) rmSync(paths.loginBrowserData, { recursive: true, force: true });
|
|
27
28
|
if (existsSync(paths.dir)) writeFileSync(paths.reinit, String(Date.now()));
|
|
28
29
|
}
|
|
29
30
|
async function hardLogout(name) {
|