perplexity-user-mcp 0.8.36
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/README.md +192 -0
- package/dist/attachments.d.ts +20 -0
- package/dist/attachments.mjs +43 -0
- package/dist/checks/browser.d.ts +100 -0
- package/dist/checks/browser.mjs +89 -0
- package/dist/checks/config.d.ts +91 -0
- package/dist/checks/config.mjs +88 -0
- package/dist/checks/ide.d.ts +89 -0
- package/dist/checks/ide.mjs +80 -0
- package/dist/checks/mcp.d.ts +61 -0
- package/dist/checks/mcp.mjs +56 -0
- package/dist/checks/native-deps.d.ts +131 -0
- package/dist/checks/native-deps.mjs +115 -0
- package/dist/checks/network.d.ts +71 -0
- package/dist/checks/network.mjs +70 -0
- package/dist/checks/probe.d.ts +93 -0
- package/dist/checks/probe.mjs +82 -0
- package/dist/checks/profiles.d.ts +99 -0
- package/dist/checks/profiles.mjs +90 -0
- package/dist/checks/runtime.d.ts +89 -0
- package/dist/checks/runtime.mjs +90 -0
- package/dist/checks/vault.d.ts +101 -0
- package/dist/checks/vault.mjs +90 -0
- package/dist/chunk-3B276PGG.mjs +115 -0
- package/dist/chunk-4UEJOM6W.mjs +9 -0
- package/dist/chunk-6EP2BLTV.mjs +205 -0
- package/dist/chunk-6YMQVLFX.mjs +146 -0
- package/dist/chunk-7JL36EBH.mjs +118 -0
- package/dist/chunk-DPGMKSSA.mjs +57 -0
- package/dist/chunk-H4BUAPPO.mjs +1950 -0
- package/dist/chunk-HMKLWVXB.mjs +109 -0
- package/dist/chunk-HTUAQRKH.mjs +125 -0
- package/dist/chunk-HU5B4FXS.mjs +139 -0
- package/dist/chunk-KCXM2M4B.mjs +1006 -0
- package/dist/chunk-LKJMLGFP.mjs +237 -0
- package/dist/chunk-LZPLNZ5U.mjs +67 -0
- package/dist/chunk-MTDFKNXX.mjs +19 -0
- package/dist/chunk-OF4DMAPJ.mjs +511 -0
- package/dist/chunk-PE23RMXY.mjs +43 -0
- package/dist/chunk-Q2VY4R5F.mjs +175 -0
- package/dist/chunk-S5VD7WTU.mjs +2540 -0
- package/dist/chunk-SVPRB62V.mjs +106 -0
- package/dist/chunk-TQLCLE4L.mjs +345 -0
- package/dist/chunk-U3DGFLXZ.mjs +43 -0
- package/dist/chunk-X45O6YD3.mjs +688 -0
- package/dist/chunk-XKSWCEGI.mjs +168 -0
- package/dist/chunk-Z7DAACGZ.mjs +534 -0
- package/dist/chunk-ZQFUZPLO.mjs +257 -0
- package/dist/cli.d.ts +952 -0
- package/dist/cli.mjs +827 -0
- package/dist/client.d.ts +355 -0
- package/dist/client.mjs +27 -0
- package/dist/cloud-sync.d-Cqt6y18U.d.ts +42 -0
- package/dist/cloud-sync.d.ts +42 -0
- package/dist/cloud-sync.mjs +17 -0
- package/dist/config.d.ts +186 -0
- package/dist/config.mjs +54 -0
- package/dist/daemon/attach.d.ts +36 -0
- package/dist/daemon/attach.mjs +25 -0
- package/dist/daemon/audit.d.ts +23 -0
- package/dist/daemon/audit.mjs +12 -0
- package/dist/daemon/client-http.d.ts +42 -0
- package/dist/daemon/client-http.mjs +29 -0
- package/dist/daemon/index.d.ts +14 -0
- package/dist/daemon/index.mjs +110 -0
- package/dist/daemon/install-tunnel.d.ts +46 -0
- package/dist/daemon/install-tunnel.mjs +14 -0
- package/dist/daemon/launcher.d.ts +163 -0
- package/dist/daemon/launcher.mjs +50 -0
- package/dist/daemon/lockfile.d.ts +29 -0
- package/dist/daemon/lockfile.mjs +18 -0
- package/dist/daemon/server.d.ts +159 -0
- package/dist/daemon/server.mjs +20 -0
- package/dist/daemon/token.d.ts +17 -0
- package/dist/daemon/token.mjs +17 -0
- package/dist/daemon/tunnel-providers/index.d.ts +330 -0
- package/dist/daemon/tunnel-providers/index.mjs +57 -0
- package/dist/daemon/tunnel.d.ts +23 -0
- package/dist/daemon/tunnel.mjs +9 -0
- package/dist/doctor-report.d.ts +24 -0
- package/dist/doctor-report.mjs +14 -0
- package/dist/doctor.d-CXmUqOXX.d.ts +43 -0
- package/dist/doctor.d.ts +44 -0
- package/dist/doctor.mjs +16 -0
- package/dist/export.d.ts +19 -0
- package/dist/export.mjs +15 -0
- package/dist/health-check.d.ts +108 -0
- package/dist/health-check.mjs +92 -0
- package/dist/history-store.d-BzjBF2m3.d.ts +65 -0
- package/dist/history-store.d.ts +65 -0
- package/dist/history-store.mjs +48 -0
- package/dist/impit-login-runner.d.ts +469 -0
- package/dist/impit-login-runner.mjs +685 -0
- package/dist/index.d.ts +159 -0
- package/dist/index.mjs +236 -0
- package/dist/login-runner.d.ts +333 -0
- package/dist/login-runner.mjs +320 -0
- package/dist/logout.d.ts +28 -0
- package/dist/logout.mjs +45 -0
- package/dist/manual-login-runner.d.ts +150 -0
- package/dist/manual-login-runner.mjs +146 -0
- package/dist/native-deps-BNThFHxa.d.ts +175 -0
- package/dist/native-deps-YNKXITRY.mjs +139 -0
- package/dist/profiles.d-DqS1oZWr.d.ts +41 -0
- package/dist/profiles.d.ts +41 -0
- package/dist/profiles.mjs +33 -0
- package/dist/redact.d.ts +159 -0
- package/dist/redact.mjs +11 -0
- package/dist/refresh.d.ts +118 -0
- package/dist/refresh.mjs +21 -0
- package/dist/reinit-watcher.d.ts +15 -0
- package/dist/reinit-watcher.mjs +8 -0
- package/dist/session-metadata-B9aV_n5g.d.ts +148 -0
- package/dist/tty-prompt.d.ts +44 -0
- package/dist/tty-prompt.mjs +39 -0
- package/dist/vault.d-BtRSLZiM.d.ts +8 -0
- package/dist/vault.d.ts +37 -0
- package/dist/vault.mjs +21 -0
- package/dist/viewer-detect.d-HWGnyFAA.d.ts +4 -0
- package/dist/viewer-detect.d.ts +4 -0
- package/dist/viewer-detect.mjs +37 -0
- package/dist/viewers.d-BGCK6sw6.d.ts +10 -0
- package/dist/viewers.d.ts +18 -0
- package/dist/viewers.mjs +122 -0
- package/package.json +152 -0
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
import { AccountInfo, SearchResult } from './config.js';
|
|
2
|
+
import 'patchright';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Perplexity Web API client — uses Playwright persistent browser context.
|
|
6
|
+
* Login (headed) and MCP server (headless) share the same browser profile directory,
|
|
7
|
+
* so Cloudflare cf_clearance and all state persist between runs.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Read the on-disk AccountInfo cache for the active profile without
|
|
12
|
+
* touching the browser or the network. Returns null when the cache file
|
|
13
|
+
* is missing, unreadable, or doesn't parse as JSON. Used by the
|
|
14
|
+
* perplexity_models handler to skip the browser launch entirely on warm
|
|
15
|
+
* runs — the cache is written by every successful refresh tier
|
|
16
|
+
* (refresh.ts) and by login-runner.js after a fresh login.
|
|
17
|
+
*/
|
|
18
|
+
declare function readCachedAccountInfoFromDisk(): AccountInfo | null;
|
|
19
|
+
interface ListAskThreadsItem {
|
|
20
|
+
backendUuid: string;
|
|
21
|
+
contextUuid: string;
|
|
22
|
+
slug: string;
|
|
23
|
+
title: string;
|
|
24
|
+
queryStr: string;
|
|
25
|
+
answerPreview: string;
|
|
26
|
+
firstAnswer: string | null;
|
|
27
|
+
createdAt: string;
|
|
28
|
+
mode: string | null;
|
|
29
|
+
displayModel: string | null;
|
|
30
|
+
searchFocus: string | null;
|
|
31
|
+
sources: string[];
|
|
32
|
+
queryCount: number;
|
|
33
|
+
threadStatus: string;
|
|
34
|
+
readWriteToken: string | null;
|
|
35
|
+
}
|
|
36
|
+
interface ListAskThreadsResult {
|
|
37
|
+
items: ListAskThreadsItem[];
|
|
38
|
+
total: number;
|
|
39
|
+
}
|
|
40
|
+
interface ListAskThreadsOpts {
|
|
41
|
+
limit?: number;
|
|
42
|
+
offset?: number;
|
|
43
|
+
searchTerm?: string;
|
|
44
|
+
excludeAsi?: boolean;
|
|
45
|
+
ascending?: boolean;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Browser-free fetch of /rest/thread/list_ask_threads via impit. Returns null
|
|
49
|
+
* when impit isn't installed, no session cookie is on disk, or the request
|
|
50
|
+
* doesn't yield a parseable 200. Lets callers (cloud-sync, the class method)
|
|
51
|
+
* fall back to the browser path on any miss.
|
|
52
|
+
*/
|
|
53
|
+
declare function listCloudThreadsViaImpit(opts?: ListAskThreadsOpts): Promise<ListAskThreadsResult | null>;
|
|
54
|
+
interface GetCloudThreadOpts {
|
|
55
|
+
limit?: number;
|
|
56
|
+
}
|
|
57
|
+
interface CloudThreadEntry {
|
|
58
|
+
backendUuid: string;
|
|
59
|
+
queryStr: string;
|
|
60
|
+
answer: string;
|
|
61
|
+
sources: Array<{
|
|
62
|
+
n: number;
|
|
63
|
+
title: string;
|
|
64
|
+
url: string;
|
|
65
|
+
snippet?: string;
|
|
66
|
+
}>;
|
|
67
|
+
mediaItems: Array<{
|
|
68
|
+
url: string;
|
|
69
|
+
name?: string;
|
|
70
|
+
type?: string;
|
|
71
|
+
}>;
|
|
72
|
+
createdAt: string;
|
|
73
|
+
status: string;
|
|
74
|
+
}
|
|
75
|
+
interface GetCloudThreadResult {
|
|
76
|
+
entries: CloudThreadEntry[];
|
|
77
|
+
thread: {
|
|
78
|
+
slug: string;
|
|
79
|
+
title: string | null;
|
|
80
|
+
contextUuid: string | null;
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Browser-free fetch of /rest/thread/<slug> via impit. Returns null when
|
|
85
|
+
* impit isn't installed/loadable, no session cookie is on disk, the
|
|
86
|
+
* response status is non-200, or the body shape is unexpected. Callers
|
|
87
|
+
* should fall back to the browser path on null. A 404 is treated as a
|
|
88
|
+
* miss (returns null) — the caller will hit the browser path which will
|
|
89
|
+
* surface the 404 as a hard error.
|
|
90
|
+
*/
|
|
91
|
+
declare function getCloudThreadViaImpit(slug: string, opts?: GetCloudThreadOpts): Promise<GetCloudThreadResult | null>;
|
|
92
|
+
interface BuildSearchRequestOpts {
|
|
93
|
+
query: string;
|
|
94
|
+
modelPreference: string;
|
|
95
|
+
mode: string;
|
|
96
|
+
sources: string[];
|
|
97
|
+
language: string;
|
|
98
|
+
followUp?: {
|
|
99
|
+
backendUuid: string;
|
|
100
|
+
readWriteToken?: string | null;
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
declare function isExperimentalImpitSearchEnabled(): boolean;
|
|
104
|
+
/**
|
|
105
|
+
* Browser-free search via impit. Returns null on any failure (impit not
|
|
106
|
+
* installed, no session cookie, non-200, parse error) so callers can fall
|
|
107
|
+
* back to the browser path. Same SSE response format as the in-page fetch
|
|
108
|
+
* — parsed by `PerplexityClient.parseSSEText`.
|
|
109
|
+
*/
|
|
110
|
+
declare function searchPerplexityViaImpit(opts: BuildSearchRequestOpts): Promise<SearchResult | null>;
|
|
111
|
+
interface RetrieveThreadViaImpitOpts {
|
|
112
|
+
threadSlug: string;
|
|
113
|
+
backendUuid: string | null;
|
|
114
|
+
readWriteToken: string | null;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Browser-free retrieve of an ASI / research result. Tries the reconnect
|
|
118
|
+
* SSE path first (POST `/rest/sse/perplexity_ask/reconnect/<uuid>`) when a
|
|
119
|
+
* backend_uuid is available, then falls back to the GET thread JSON
|
|
120
|
+
* (`/rest/thread/<slug>`). Returns null on any failure (impit not
|
|
121
|
+
* installed, no session cookie, non-200, parse error, "still running"
|
|
122
|
+
* answer that the caller will want to surface via the browser path) so
|
|
123
|
+
* the caller can fall through to the page-context path.
|
|
124
|
+
*
|
|
125
|
+
* Files are intentionally NOT downloaded here — when the result has
|
|
126
|
+
* attached files we return null so the caller forces a browser session
|
|
127
|
+
* which can drive `downloadASIFiles` via the page's APIRequestContext.
|
|
128
|
+
*/
|
|
129
|
+
declare function retrieveThreadViaImpit(opts: RetrieveThreadViaImpitOpts): Promise<SearchResult | null>;
|
|
130
|
+
interface ExportThreadViaImpitOpts {
|
|
131
|
+
threadSlug?: string | null;
|
|
132
|
+
entryUuid?: string | null;
|
|
133
|
+
format: "pdf" | "markdown" | "docx";
|
|
134
|
+
}
|
|
135
|
+
interface ExportThreadResult {
|
|
136
|
+
buffer: Buffer;
|
|
137
|
+
filename: string;
|
|
138
|
+
contentType: string;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Browser-free PDF / DOCX export via impit. Returns null on any failure
|
|
142
|
+
* (impit not installed, no session cookie, markdown format, no entry UUID
|
|
143
|
+
* resolvable, non-200, empty body) so callers can fall back to the
|
|
144
|
+
* page-context export. Markdown export is intentionally not supported here
|
|
145
|
+
* — the caller assembles markdown locally from the saved history entry.
|
|
146
|
+
*/
|
|
147
|
+
declare function exportThreadViaImpit(opts: ExportThreadViaImpitOpts): Promise<ExportThreadResult | null>;
|
|
148
|
+
declare class PerplexityClient {
|
|
149
|
+
private browser;
|
|
150
|
+
private context;
|
|
151
|
+
private page;
|
|
152
|
+
authenticated: boolean;
|
|
153
|
+
userId: string | null;
|
|
154
|
+
accountInfo: AccountInfo;
|
|
155
|
+
/**
|
|
156
|
+
* Initialize the client. Two-phase startup:
|
|
157
|
+
*
|
|
158
|
+
* Phase 1 (headed): Cloudflare Turnstile cannot be solved by headless browsers.
|
|
159
|
+
* A brief VISIBLE browser session navigates to Perplexity, auto-solves the CF
|
|
160
|
+
* challenge, and fetches all account info endpoints (models, ASI access, etc.)
|
|
161
|
+
* while Cloudflare isn't blocking. Then closes.
|
|
162
|
+
*
|
|
163
|
+
* Phase 2 (headless): Launches headless with the same persistent profile
|
|
164
|
+
* (now carrying fresh cf_clearance) for search operations.
|
|
165
|
+
*
|
|
166
|
+
* Set env PERPLEXITY_HEADLESS_ONLY=1 to skip the headed phase (uses disk cache).
|
|
167
|
+
*/
|
|
168
|
+
init(): Promise<void>;
|
|
169
|
+
/**
|
|
170
|
+
* Brief VISIBLE browser session that:
|
|
171
|
+
* 1. Navigates to Perplexity to solve Cloudflare Turnstile (auto, no user interaction)
|
|
172
|
+
* 2. Fetches all account info endpoints while CF isn't blocking
|
|
173
|
+
* 3. Caches results to disk, then closes
|
|
174
|
+
*/
|
|
175
|
+
private headedBootstrap;
|
|
176
|
+
private checkAuth;
|
|
177
|
+
/**
|
|
178
|
+
* Load dynamic account info: models config, ASI access, rate limits, experiment flags.
|
|
179
|
+
* Falls back to disk cache if Cloudflare blocks the /rest/* endpoints.
|
|
180
|
+
*/
|
|
181
|
+
private loadAccountInfo;
|
|
182
|
+
/**
|
|
183
|
+
* Load cached account info from disk (fallback when Cloudflare blocks).
|
|
184
|
+
*/
|
|
185
|
+
private loadCachedAccountInfo;
|
|
186
|
+
/**
|
|
187
|
+
* Removed in 0.3.0. Login now runs in a separate child process (login-runner)
|
|
188
|
+
* driven by AuthManager / the CLI so the long-lived MCP server doesn't hold
|
|
189
|
+
* the browser profile lock. After a successful login, the runner writes to
|
|
190
|
+
* the vault and drops a `.reinit` sentinel which the MCP server's watcher
|
|
191
|
+
* picks up to reload cookies via `reinit()`.
|
|
192
|
+
*/
|
|
193
|
+
loginViaBrowser(_opts?: {
|
|
194
|
+
log?: (line: string) => void;
|
|
195
|
+
}): Promise<{
|
|
196
|
+
success: boolean;
|
|
197
|
+
message: string;
|
|
198
|
+
}>;
|
|
199
|
+
/**
|
|
200
|
+
* Close the current browser context and re-run init() so freshly-written
|
|
201
|
+
* vault cookies are picked up. Called by the `.reinit` sentinel watcher
|
|
202
|
+
* after a child login-runner completes.
|
|
203
|
+
*/
|
|
204
|
+
reinit(): Promise<void>;
|
|
205
|
+
search(opts: {
|
|
206
|
+
query: string;
|
|
207
|
+
modelPreference?: string;
|
|
208
|
+
mode?: string;
|
|
209
|
+
sources?: string[];
|
|
210
|
+
language?: string;
|
|
211
|
+
followUp?: {
|
|
212
|
+
backendUuid: string;
|
|
213
|
+
readWriteToken?: string | null;
|
|
214
|
+
};
|
|
215
|
+
}): Promise<SearchResult>;
|
|
216
|
+
/**
|
|
217
|
+
* Submit an ASI/Computer mode task and wait for it to complete.
|
|
218
|
+
*
|
|
219
|
+
* Flow (discovered from browser HAR capture):
|
|
220
|
+
* 1. POST /rest/sse/perplexity_ask → initial SSE with status: PENDING + backend_uuid
|
|
221
|
+
* 2. POST /rest/sse/perplexity_ask/reconnect/{backend_uuid} → SSE stream with
|
|
222
|
+
* progressive updates until status: COMPLETED + step_type: FINAL
|
|
223
|
+
* 3. Parse FINAL event blocks: workflow_block (answer text + workflow sources),
|
|
224
|
+
* web_result_block (citation sources), pending_followups_block
|
|
225
|
+
*/
|
|
226
|
+
computeASI(opts: {
|
|
227
|
+
query: string;
|
|
228
|
+
modelPreference?: string;
|
|
229
|
+
language?: string;
|
|
230
|
+
timeoutMs?: number;
|
|
231
|
+
}): Promise<SearchResult>;
|
|
232
|
+
/**
|
|
233
|
+
* Re-fetch results from a Perplexity thread that may have completed after we timed out.
|
|
234
|
+
* Tries reconnect SSE first (using backendUuid), then falls back to thread endpoint.
|
|
235
|
+
*/
|
|
236
|
+
retrieveThread(opts: {
|
|
237
|
+
threadSlug: string;
|
|
238
|
+
backendUuid?: string | null;
|
|
239
|
+
readWriteToken?: string | null;
|
|
240
|
+
}): Promise<SearchResult>;
|
|
241
|
+
/**
|
|
242
|
+
* Parse the reconnect SSE stream from an ASI task.
|
|
243
|
+
*
|
|
244
|
+
* The SSE stream contains progressive events. The FINAL event has:
|
|
245
|
+
* - status: COMPLETED, step_type: FINAL, text_completed: true
|
|
246
|
+
* - blocks[]: workflow_root (workflow_block with steps/items/text),
|
|
247
|
+
* web_results (web_result_block), pending_followups, sources_answer_mode
|
|
248
|
+
*/
|
|
249
|
+
static parseASIReconnectSSE(sseText: string, threadSlug: string, backendUuid: string, readWriteToken: string): SearchResult;
|
|
250
|
+
/**
|
|
251
|
+
* Download files generated by ASI tasks.
|
|
252
|
+
*
|
|
253
|
+
* Uses Playwright's `APIRequestContext` (`context.request.get`) instead of
|
|
254
|
+
* an in-page `fetch()`. ASI assets typically live on off-origin CDN buckets
|
|
255
|
+
* (e.g. `pplx-res.cloudinary.com`, GCS, S3); fetching them from inside the
|
|
256
|
+
* Perplexity origin would trip CORS unless the browser was launched with
|
|
257
|
+
* `--disable-web-security` — which we no longer do (see STEALTH_ARGS note).
|
|
258
|
+
*
|
|
259
|
+
* `APIRequestContext` runs outside the page context, automatically inherits
|
|
260
|
+
* cookies from the BrowserContext, and is not subject to the same-origin
|
|
261
|
+
* policy, so it works for both same-origin and off-origin asset URLs.
|
|
262
|
+
*
|
|
263
|
+
* Files are saved to ~/.perplexity-mcp/downloads/<threadSlug>/.
|
|
264
|
+
*
|
|
265
|
+
* Public contract is preserved: this still mutates each `file.localPath`
|
|
266
|
+
* in-place on success and silently skips on failure (logs to stderr).
|
|
267
|
+
*/
|
|
268
|
+
private downloadASIFiles;
|
|
269
|
+
/**
|
|
270
|
+
* Parse a completed ASI thread entry from GET /rest/thread/{slug}.
|
|
271
|
+
* Used as fallback (Phase B) when streaming reconnect doesn't complete in time.
|
|
272
|
+
*
|
|
273
|
+
* Thread entry structure:
|
|
274
|
+
* - plan.goals[].description — answer text (simple queries)
|
|
275
|
+
* - text — JSON string of steps, FINAL step may have content.answer with full text + web_results
|
|
276
|
+
* - step_type: "FINAL", status: "completed"
|
|
277
|
+
*/
|
|
278
|
+
/**
|
|
279
|
+
* Extract answer from the workflow_block in the last SSE snapshot.
|
|
280
|
+
* Used when the reconnect loop didn't catch COMPLETED live but we have
|
|
281
|
+
* a snapshot with workflow_block data (steps, items, sources).
|
|
282
|
+
*/
|
|
283
|
+
static extractFromWorkflowBlock(sseText: string, threadSlug: string, backendUuid: string, readWriteToken: string): SearchResult | null;
|
|
284
|
+
static parseASIThreadEntry(entry: any, threadSlug: string, backendUuid: string, readWriteToken: string): SearchResult;
|
|
285
|
+
static parseSSEText(text: string): SearchResult;
|
|
286
|
+
/**
|
|
287
|
+
* Execute arbitrary JS in the browser context. Used for API inspection.
|
|
288
|
+
*/
|
|
289
|
+
evaluateInBrowser<T>(fn: (...args: any[]) => Promise<T>, arg?: any): Promise<T>;
|
|
290
|
+
/**
|
|
291
|
+
* Navigate to a URL, intercept network requests for a duration, return matched ones.
|
|
292
|
+
*/
|
|
293
|
+
interceptRequests(url: string, durationMs: number, filter: (url: string) => boolean): Promise<Array<{
|
|
294
|
+
method: string;
|
|
295
|
+
url: string;
|
|
296
|
+
status: number;
|
|
297
|
+
body?: string;
|
|
298
|
+
}>>;
|
|
299
|
+
private resolveThreadEntryUuid;
|
|
300
|
+
exportThread(opts: {
|
|
301
|
+
threadSlug?: string | null;
|
|
302
|
+
entryUuid?: string | null;
|
|
303
|
+
format: "pdf" | "markdown" | "docx";
|
|
304
|
+
}): Promise<{
|
|
305
|
+
buffer: Buffer;
|
|
306
|
+
filename: string;
|
|
307
|
+
contentType: string;
|
|
308
|
+
}>;
|
|
309
|
+
/**
|
|
310
|
+
* Authenticated fetch helper — routes through the persistent page so
|
|
311
|
+
* cookies (session-token + cf_clearance) ride along. Mirrors the
|
|
312
|
+
* exportThread() pattern but returns parsed JSON.
|
|
313
|
+
*/
|
|
314
|
+
private pageFetchJson;
|
|
315
|
+
/**
|
|
316
|
+
* Fetch a page of the user's library via POST /rest/thread/list_ask_threads.
|
|
317
|
+
* Endpoint captured 2026-04-21 — body shape documented in
|
|
318
|
+
* docs/export-endpoint-capture.md (alongside export).
|
|
319
|
+
*/
|
|
320
|
+
listCloudThreads(opts?: {
|
|
321
|
+
limit?: number;
|
|
322
|
+
offset?: number;
|
|
323
|
+
searchTerm?: string;
|
|
324
|
+
excludeAsi?: boolean;
|
|
325
|
+
ascending?: boolean;
|
|
326
|
+
}): Promise<{
|
|
327
|
+
items: Array<{
|
|
328
|
+
backendUuid: string;
|
|
329
|
+
contextUuid: string;
|
|
330
|
+
slug: string;
|
|
331
|
+
title: string;
|
|
332
|
+
queryStr: string;
|
|
333
|
+
answerPreview: string;
|
|
334
|
+
firstAnswer: string | null;
|
|
335
|
+
createdAt: string;
|
|
336
|
+
mode: string | null;
|
|
337
|
+
displayModel: string | null;
|
|
338
|
+
searchFocus: string | null;
|
|
339
|
+
sources: string[];
|
|
340
|
+
queryCount: number;
|
|
341
|
+
threadStatus: string;
|
|
342
|
+
readWriteToken: string | null;
|
|
343
|
+
}>;
|
|
344
|
+
total: number;
|
|
345
|
+
}>;
|
|
346
|
+
/**
|
|
347
|
+
* Fetch full content of a single cloud thread by slug. Tries impit first,
|
|
348
|
+
* falls back to the page-context fetch. Endpoint:
|
|
349
|
+
* GET /rest/thread/<slug>?from_first=true (captured 2026-04-21).
|
|
350
|
+
*/
|
|
351
|
+
getCloudThread(slug: string, opts?: GetCloudThreadOpts): Promise<GetCloudThreadResult>;
|
|
352
|
+
shutdown(): Promise<void>;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
export { type BuildSearchRequestOpts, type CloudThreadEntry, type ExportThreadResult, type ExportThreadViaImpitOpts, type GetCloudThreadOpts, type GetCloudThreadResult, type ListAskThreadsItem, type ListAskThreadsOpts, type ListAskThreadsResult, PerplexityClient, type RetrieveThreadViaImpitOpts, exportThreadViaImpit, getCloudThreadViaImpit, isExperimentalImpitSearchEnabled, listCloudThreadsViaImpit, readCachedAccountInfoFromDisk, retrieveThreadViaImpit, searchPerplexityViaImpit };
|
package/dist/client.mjs
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import {
|
|
2
|
+
PerplexityClient,
|
|
3
|
+
exportThreadViaImpit,
|
|
4
|
+
getCloudThreadViaImpit,
|
|
5
|
+
isExperimentalImpitSearchEnabled,
|
|
6
|
+
listCloudThreadsViaImpit,
|
|
7
|
+
readCachedAccountInfoFromDisk,
|
|
8
|
+
retrieveThreadViaImpit,
|
|
9
|
+
searchPerplexityViaImpit
|
|
10
|
+
} from "./chunk-H4BUAPPO.mjs";
|
|
11
|
+
import "./chunk-Z7DAACGZ.mjs";
|
|
12
|
+
import "./chunk-LZPLNZ5U.mjs";
|
|
13
|
+
import "./chunk-LKJMLGFP.mjs";
|
|
14
|
+
import "./chunk-TQLCLE4L.mjs";
|
|
15
|
+
import "./chunk-MTDFKNXX.mjs";
|
|
16
|
+
import "./chunk-XKSWCEGI.mjs";
|
|
17
|
+
import "./chunk-4UEJOM6W.mjs";
|
|
18
|
+
export {
|
|
19
|
+
PerplexityClient,
|
|
20
|
+
exportThreadViaImpit,
|
|
21
|
+
getCloudThreadViaImpit,
|
|
22
|
+
isExperimentalImpitSearchEnabled,
|
|
23
|
+
listCloudThreadsViaImpit,
|
|
24
|
+
readCachedAccountInfoFromDisk,
|
|
25
|
+
retrieveThreadViaImpit,
|
|
26
|
+
searchPerplexityViaImpit
|
|
27
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { PerplexityClient } from './client.js';
|
|
2
|
+
import './config.js';
|
|
3
|
+
import 'patchright';
|
|
4
|
+
|
|
5
|
+
interface CloudSyncProgressEvent {
|
|
6
|
+
phase: "starting" | "syncing" | "done" | "cancelled" | "error";
|
|
7
|
+
fetched?: number;
|
|
8
|
+
total?: number;
|
|
9
|
+
inserted?: number;
|
|
10
|
+
updated?: number;
|
|
11
|
+
skipped?: number;
|
|
12
|
+
error?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface CloudSyncOptions {
|
|
16
|
+
client?: PerplexityClient;
|
|
17
|
+
getClient?: () => Promise<PerplexityClient>;
|
|
18
|
+
onProgress?: (evt: CloudSyncProgressEvent) => void;
|
|
19
|
+
pageSize?: number;
|
|
20
|
+
signal?: AbortSignal;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface CloudSyncResult {
|
|
24
|
+
fetched: number;
|
|
25
|
+
total: number;
|
|
26
|
+
inserted: number;
|
|
27
|
+
updated: number;
|
|
28
|
+
skipped: number;
|
|
29
|
+
cancelled: boolean;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
declare function syncCloudHistory(opts?: CloudSyncOptions): Promise<CloudSyncResult>;
|
|
33
|
+
|
|
34
|
+
declare function hydrateCloudHistoryEntry(
|
|
35
|
+
historyId: string,
|
|
36
|
+
opts?: {
|
|
37
|
+
client?: PerplexityClient;
|
|
38
|
+
getClient?: () => Promise<PerplexityClient>;
|
|
39
|
+
},
|
|
40
|
+
): Promise<{ action: "skipped-local" | "skipped-hydrated" | "hydrated"; id?: string }>;
|
|
41
|
+
|
|
42
|
+
export { type CloudSyncOptions, type CloudSyncProgressEvent, type CloudSyncResult, hydrateCloudHistoryEntry, syncCloudHistory };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { PerplexityClient } from './client.js';
|
|
2
|
+
import './config.js';
|
|
3
|
+
import 'patchright';
|
|
4
|
+
|
|
5
|
+
interface CloudSyncProgressEvent {
|
|
6
|
+
phase: "starting" | "syncing" | "done" | "cancelled" | "error";
|
|
7
|
+
fetched?: number;
|
|
8
|
+
total?: number;
|
|
9
|
+
inserted?: number;
|
|
10
|
+
updated?: number;
|
|
11
|
+
skipped?: number;
|
|
12
|
+
error?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface CloudSyncOptions {
|
|
16
|
+
client?: PerplexityClient;
|
|
17
|
+
getClient?: () => Promise<PerplexityClient>;
|
|
18
|
+
onProgress?: (evt: CloudSyncProgressEvent) => void;
|
|
19
|
+
pageSize?: number;
|
|
20
|
+
signal?: AbortSignal;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface CloudSyncResult {
|
|
24
|
+
fetched: number;
|
|
25
|
+
total: number;
|
|
26
|
+
inserted: number;
|
|
27
|
+
updated: number;
|
|
28
|
+
skipped: number;
|
|
29
|
+
cancelled: boolean;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
declare function syncCloudHistory(opts?: CloudSyncOptions): Promise<CloudSyncResult>;
|
|
33
|
+
|
|
34
|
+
declare function hydrateCloudHistoryEntry(
|
|
35
|
+
historyId: string,
|
|
36
|
+
opts?: {
|
|
37
|
+
client?: PerplexityClient;
|
|
38
|
+
getClient?: () => Promise<PerplexityClient>;
|
|
39
|
+
},
|
|
40
|
+
): Promise<{ action: "skipped-local" | "skipped-hydrated" | "hydrated"; id?: string }>;
|
|
41
|
+
|
|
42
|
+
export { type CloudSyncOptions, type CloudSyncProgressEvent, type CloudSyncResult, hydrateCloudHistoryEntry, syncCloudHistory };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import {
|
|
2
|
+
hydrateCloudHistoryEntry,
|
|
3
|
+
syncCloudHistory
|
|
4
|
+
} from "./chunk-Q2VY4R5F.mjs";
|
|
5
|
+
import "./chunk-H4BUAPPO.mjs";
|
|
6
|
+
import "./chunk-Z7DAACGZ.mjs";
|
|
7
|
+
import "./chunk-OF4DMAPJ.mjs";
|
|
8
|
+
import "./chunk-LZPLNZ5U.mjs";
|
|
9
|
+
import "./chunk-LKJMLGFP.mjs";
|
|
10
|
+
import "./chunk-TQLCLE4L.mjs";
|
|
11
|
+
import "./chunk-MTDFKNXX.mjs";
|
|
12
|
+
import "./chunk-XKSWCEGI.mjs";
|
|
13
|
+
import "./chunk-4UEJOM6W.mjs";
|
|
14
|
+
export {
|
|
15
|
+
hydrateCloudHistoryEntry,
|
|
16
|
+
syncCloudHistory
|
|
17
|
+
};
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import * as patchright from 'patchright';
|
|
2
|
+
|
|
3
|
+
declare const PERPLEXITY_URL = "https://www.perplexity.ai";
|
|
4
|
+
declare const AUTH_SESSION_ENDPOINT = "https://www.perplexity.ai/api/auth/session";
|
|
5
|
+
declare const QUERY_ENDPOINT = "https://www.perplexity.ai/rest/sse/perplexity_ask";
|
|
6
|
+
declare const MODELS_CONFIG_ENDPOINT = "https://www.perplexity.ai/rest/models/config?config_schema=v1&version=2.18&source=default";
|
|
7
|
+
declare const ASI_ACCESS_ENDPOINT = "https://www.perplexity.ai/rest/billing/asi-access-decision?version=2.18&source=default";
|
|
8
|
+
declare const RATE_LIMIT_ENDPOINT = "https://www.perplexity.ai/rest/rate-limit/status?version=2.18&source=default";
|
|
9
|
+
declare const EXPERIMENTS_ENDPOINT = "https://www.perplexity.ai/rest/experiments/attributes?version=2.18&source=default";
|
|
10
|
+
declare const USER_INFO_ENDPOINT = "https://www.perplexity.ai/rest/user/info?version=2.18&source=default";
|
|
11
|
+
declare const THREAD_ENDPOINT: (slug: string) => string;
|
|
12
|
+
declare const CONFIG_DIR: string;
|
|
13
|
+
/**
|
|
14
|
+
* Cookies file path for the active profile (legacy fallback only — real
|
|
15
|
+
* storage is the encrypted vault now). Profile-aware, evaluated at call time.
|
|
16
|
+
*/
|
|
17
|
+
declare function getCookiesFile(): string;
|
|
18
|
+
/**
|
|
19
|
+
* Browser persistent-context directory for the active profile.
|
|
20
|
+
* Profile-aware, evaluated at call time.
|
|
21
|
+
*/
|
|
22
|
+
declare function getBrowserDataDir(): string;
|
|
23
|
+
declare const COOKIES_FILE: string;
|
|
24
|
+
declare const STORAGE_STATE_FILE: string;
|
|
25
|
+
declare const BROWSER_DATA_DIR: string;
|
|
26
|
+
type BrowserChannel = "chrome" | "msedge" | "chromium" | "bundled";
|
|
27
|
+
interface BrowserInfo {
|
|
28
|
+
/** Absolute path to a browser executable. */
|
|
29
|
+
path: string;
|
|
30
|
+
/** Channel passed to Patchright's launch APIs. */
|
|
31
|
+
channel: BrowserChannel;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Find a suitable Chromium-based browser on the system. Searches Chrome >
|
|
35
|
+
* Edge > Chromium > Brave with platform-specific paths, covering Windows,
|
|
36
|
+
* macOS (Intel+ARM), and Linux. Returns null if nothing usable is found.
|
|
37
|
+
*
|
|
38
|
+
* Env var overrides (evaluated at call time):
|
|
39
|
+
* PERPLEXITY_BROWSER_PATH — absolute path to an executable
|
|
40
|
+
* PERPLEXITY_BROWSER_CHANNEL — chrome | msedge | chromium (defaults to "chrome")
|
|
41
|
+
* PERPLEXITY_CHROME_PATH — legacy alias for PERPLEXITY_BROWSER_PATH
|
|
42
|
+
*/
|
|
43
|
+
declare function findBrowser(): BrowserInfo | null;
|
|
44
|
+
/**
|
|
45
|
+
* Pick a usable BrowserContext from a Patchright Browser. Kept as a small
|
|
46
|
+
* helper for any future CDP-connect path (e.g. attaching to a remote Chrome
|
|
47
|
+
* via `--remote-debugging-port`). For freshly launched browsers `contexts()`
|
|
48
|
+
* is empty until we call `newContext`, which then runs unchanged with the
|
|
49
|
+
* caller's options (viewport, userAgent, etc).
|
|
50
|
+
*/
|
|
51
|
+
declare function getOrCreateContext(browser: patchright.Browser, options?: Parameters<patchright.Browser["newContext"]>[0]): Promise<patchright.BrowserContext>;
|
|
52
|
+
/**
|
|
53
|
+
* Find the real Chrome executable on the system.
|
|
54
|
+
* Returns the path or null if not found.
|
|
55
|
+
*/
|
|
56
|
+
declare function findChromeExecutable(): string | null;
|
|
57
|
+
/**
|
|
58
|
+
* Resolve a browser executable the client can launch.
|
|
59
|
+
*
|
|
60
|
+
* Prefers a system browser (Chrome > Edge > Chromium > Brave) for best
|
|
61
|
+
* Cloudflare compatibility. Falls back to patchright's bundled Chromium when
|
|
62
|
+
* the user ran `npx patchright install chromium`. Throws a descriptive error
|
|
63
|
+
* when neither is available so the CLI doesn't crash with Playwright's
|
|
64
|
+
* opaque "Executable doesn't exist at ..." message.
|
|
65
|
+
*
|
|
66
|
+
* The returned `channel` field is additive and safe to ignore by legacy
|
|
67
|
+
* callers that only destructure `{ path }`.
|
|
68
|
+
*/
|
|
69
|
+
declare function resolveBrowserExecutable(): Promise<{
|
|
70
|
+
path: string;
|
|
71
|
+
channel: BrowserChannel;
|
|
72
|
+
source: "system-chrome" | "system-edge" | "system-chromium" | "system-brave" | "bundled-chromium";
|
|
73
|
+
}>;
|
|
74
|
+
declare const DEFAULT_HEADERS: Record<string, string>;
|
|
75
|
+
declare const SUPPORTED_BLOCK_USE_CASES: string[];
|
|
76
|
+
interface ModelInfo {
|
|
77
|
+
description: string;
|
|
78
|
+
mode: string;
|
|
79
|
+
provider: string | null;
|
|
80
|
+
label?: string;
|
|
81
|
+
}
|
|
82
|
+
interface ModelConfigEntry {
|
|
83
|
+
label: string;
|
|
84
|
+
description: string;
|
|
85
|
+
subheading: string | null;
|
|
86
|
+
has_new_tag: boolean;
|
|
87
|
+
subscription_tier: string;
|
|
88
|
+
non_reasoning_model: string | null;
|
|
89
|
+
reasoning_model: string | null;
|
|
90
|
+
text_only_model: boolean;
|
|
91
|
+
audience?: string | null;
|
|
92
|
+
is_default?: boolean;
|
|
93
|
+
}
|
|
94
|
+
interface ModelsConfigResponse {
|
|
95
|
+
models: Record<string, ModelInfo>;
|
|
96
|
+
config: ModelConfigEntry[];
|
|
97
|
+
default_models: Record<string, string>;
|
|
98
|
+
agentic_research_compare_models?: string[];
|
|
99
|
+
}
|
|
100
|
+
interface ASIAccessResponse {
|
|
101
|
+
can_use_computer: boolean;
|
|
102
|
+
can_access_org_credits_page: boolean;
|
|
103
|
+
can_enable_topup: boolean;
|
|
104
|
+
}
|
|
105
|
+
interface RateLimitResponse {
|
|
106
|
+
modes: Record<string, {
|
|
107
|
+
available: boolean;
|
|
108
|
+
remaining_detail: {
|
|
109
|
+
kind: string;
|
|
110
|
+
remaining?: number;
|
|
111
|
+
};
|
|
112
|
+
}>;
|
|
113
|
+
sources: Record<string, {
|
|
114
|
+
available: boolean;
|
|
115
|
+
remaining_detail: {
|
|
116
|
+
kind: string;
|
|
117
|
+
remaining?: number;
|
|
118
|
+
};
|
|
119
|
+
}>;
|
|
120
|
+
}
|
|
121
|
+
interface UserInfoResponse {
|
|
122
|
+
has_non_public_email?: boolean;
|
|
123
|
+
is_enterprise?: boolean;
|
|
124
|
+
is_gov?: boolean;
|
|
125
|
+
is_student?: boolean;
|
|
126
|
+
}
|
|
127
|
+
interface AccountInfo {
|
|
128
|
+
isPro: boolean;
|
|
129
|
+
isMax: boolean;
|
|
130
|
+
isEnterprise: boolean;
|
|
131
|
+
canUseComputer: boolean;
|
|
132
|
+
modelsConfig: ModelsConfigResponse | null;
|
|
133
|
+
rateLimits: RateLimitResponse | null;
|
|
134
|
+
}
|
|
135
|
+
interface ASIFile {
|
|
136
|
+
filename: string;
|
|
137
|
+
assetType: string;
|
|
138
|
+
url: string;
|
|
139
|
+
localPath?: string;
|
|
140
|
+
size?: number;
|
|
141
|
+
mediaType?: string;
|
|
142
|
+
}
|
|
143
|
+
interface SearchResult {
|
|
144
|
+
answer: string;
|
|
145
|
+
reasoning?: string;
|
|
146
|
+
sources: Array<{
|
|
147
|
+
title: string;
|
|
148
|
+
url: string;
|
|
149
|
+
snippet: string;
|
|
150
|
+
}>;
|
|
151
|
+
media: Array<{
|
|
152
|
+
type: string;
|
|
153
|
+
url: string;
|
|
154
|
+
name: string;
|
|
155
|
+
}>;
|
|
156
|
+
files?: ASIFile[];
|
|
157
|
+
suggestedFollowups: string[];
|
|
158
|
+
followUp?: {
|
|
159
|
+
backendUuid: string;
|
|
160
|
+
readWriteToken: string | null;
|
|
161
|
+
threadUrlSlug: string | null;
|
|
162
|
+
threadTitle: string | null;
|
|
163
|
+
};
|
|
164
|
+
threadUrl?: string;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Build cookie string from env vars or saved cookies file for Playwright context.
|
|
168
|
+
*/
|
|
169
|
+
interface PlaywrightCookie {
|
|
170
|
+
name: string;
|
|
171
|
+
value: string;
|
|
172
|
+
domain: string;
|
|
173
|
+
path: string;
|
|
174
|
+
secure?: boolean;
|
|
175
|
+
httpOnly?: boolean;
|
|
176
|
+
sameSite?: "Strict" | "Lax" | "None";
|
|
177
|
+
}
|
|
178
|
+
declare function getSavedCookies(): Promise<PlaywrightCookie[]>;
|
|
179
|
+
/**
|
|
180
|
+
* Check whether the active profile has stored login cookies in its vault.
|
|
181
|
+
* Extension has its own filesystem-based `hasStoredLogin` in session.ts that
|
|
182
|
+
* inspects COOKIES_FILE / BROWSER_DATA_DIR — this one is vault-aware.
|
|
183
|
+
*/
|
|
184
|
+
declare function hasStoredLogin(): Promise<boolean>;
|
|
185
|
+
|
|
186
|
+
export { type ASIAccessResponse, type ASIFile, ASI_ACCESS_ENDPOINT, AUTH_SESSION_ENDPOINT, type AccountInfo, BROWSER_DATA_DIR, type BrowserChannel, type BrowserInfo, CONFIG_DIR, COOKIES_FILE, DEFAULT_HEADERS, EXPERIMENTS_ENDPOINT, MODELS_CONFIG_ENDPOINT, type ModelConfigEntry, type ModelInfo, type ModelsConfigResponse, PERPLEXITY_URL, type PlaywrightCookie, QUERY_ENDPOINT, RATE_LIMIT_ENDPOINT, type RateLimitResponse, STORAGE_STATE_FILE, SUPPORTED_BLOCK_USE_CASES, type SearchResult, THREAD_ENDPOINT, USER_INFO_ENDPOINT, type UserInfoResponse, findBrowser, findChromeExecutable, getBrowserDataDir, getCookiesFile, getOrCreateContext, getSavedCookies, hasStoredLogin, resolveBrowserExecutable };
|