pi-harness-runtime 1.1.80 → 1.1.82
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/harness/browser-scrapers/base-browser-scraper.d.ts +91 -0
- package/harness/browser-scrapers/chrome-profile-manager.d.ts +80 -0
- package/harness/browser-scrapers/codex-browser-scraper.d.ts +60 -0
- package/harness/browser-scrapers/index.d.ts +29 -0
- package/harness/browser-scrapers/zai-browser-scraper.d.ts +79 -0
- package/harness/e2e/browser-scrapers/base-browser-scraper.d.ts +92 -0
- package/harness/e2e/browser-scrapers/base-browser-scraper.ts +244 -0
- package/harness/e2e/browser-scrapers/chrome-profile-manager.d.ts +81 -0
- package/harness/e2e/browser-scrapers/chrome-profile-manager.ts +297 -0
- package/harness/e2e/browser-scrapers/codex-browser-scraper.d.ts +61 -0
- package/harness/e2e/browser-scrapers/codex-browser-scraper.ts +343 -0
- package/harness/e2e/browser-scrapers/index.d.ts +30 -0
- package/harness/e2e/browser-scrapers/index.ts +48 -0
- package/harness/e2e/browser-scrapers/zai-browser-scraper.d.ts +80 -0
- package/harness/e2e/browser-scrapers/zai-browser-scraper.ts +392 -0
- package/harness/e2e/glm-quota-scraper.ts +106 -15
- package/harness/e2e/index.ts +29 -0
- package/harness/e2e/unified-quota-manager.ts +364 -0
- package/index.ts +72 -11
- package/mirror.ts +32 -28
- package/package.json +1 -1
- package/packages/a2a-adapter/package.json +1 -1
- package/packages/architecture-generator/package.json +1 -1
- package/packages/auth/package.json +1 -1
- package/packages/autonomous-refactor/package.json +1 -1
- package/packages/autonomous-runtime/package.json +1 -1
- package/packages/cache-strategy/package.json +1 -1
- package/packages/capability-registry/package.json +1 -1
- package/packages/checkpoint/package.json +1 -1
- package/packages/cli-plugin-sdk/package.json +1 -1
- package/packages/clipboard/package.json +1 -1
- package/packages/clipboard-plugin/package.json +1 -1
- package/packages/code-generation/package.json +1 -1
- package/packages/code-review/package.json +1 -1
- package/packages/codex-adapter/package.json +1 -1
- package/packages/config-capture/package.json +1 -1
- package/packages/context-compiler/package.json +1 -1
- package/packages/context-discovery/package.json +1 -1
- package/packages/context-manager/package.json +1 -1
- package/packages/cookie-sanitizer/package.json +1 -1
- package/packages/cost-optimizer/package.json +1 -1
- package/packages/dependency-analyzer/package.json +1 -1
- package/packages/django-plugin/package.json +1 -1
- package/packages/doc-generator/package.json +1 -1
- package/packages/evaluation-engine/package.json +1 -1
- package/packages/evaluation-runner/package.json +1 -1
- package/packages/event-bus/package.json +1 -1
- package/packages/event-store/package.json +1 -1
- package/packages/experience-replay/package.json +1 -1
- package/packages/feedback-collector/package.json +1 -1
- package/packages/file-copy-helper/package.json +1 -1
- package/packages/framework-detector/package.json +1 -1
- package/packages/framework-plugin-sdk/package.json +1 -1
- package/packages/frappe-plugin/package.json +1 -1
- package/packages/generic-web-plugin/package.json +1 -1
- package/packages/health-monitor/package.json +1 -1
- package/packages/intent-analyzer/package.json +1 -1
- package/packages/jev-judge/package.json +1 -1
- package/packages/knowledge-graph/package.json +1 -1
- package/packages/knowledge-retrieval/package.json +1 -1
- package/packages/laravel-plugin/package.json +1 -1
- package/packages/learning-engine/package.json +1 -1
- package/packages/mcp-adapter/package.json +1 -1
- package/packages/memory-engine/package.json +1 -1
- package/packages/milestone-manager/package.json +1 -1
- package/packages/model-registry/package.json +1 -1
- package/packages/nextjs-plugin/package.json +1 -1
- package/packages/notification/package.json +1 -1
- package/packages/observability/package.json +1 -1
- package/packages/okf-indexer/package.json +1 -1
- package/packages/performance-optimizer/package.json +1 -1
- package/packages/privilege-broker/package.json +1 -1
- package/packages/project-analyzer/package.json +1 -1
- package/packages/project-bootstrap/package.json +1 -1
- package/packages/projection-engine/package.json +1 -1
- package/packages/prompt-compiler/package.json +1 -1
- package/packages/prompt-versioning/package.json +1 -1
- package/packages/provider-adapter-sdk/package.json +1 -1
- package/packages/provider-router/package.json +1 -1
- package/packages/provider-selector/package.json +1 -1
- package/packages/providers/dist/provider-id.d.ts.map +1 -1
- package/packages/providers/dist/provider-id.js +1 -2
- package/packages/providers/dist/provider-id.js.map +1 -1
- package/packages/providers/package.json +1 -1
- package/packages/providers/src/provider-id.ts +1 -2
- package/packages/quota-manager/package.json +1 -1
- package/packages/rate-limiter/package.json +1 -1
- package/packages/react-vite-plugin/package.json +1 -1
- package/packages/release-manager/package.json +1 -1
- package/packages/requirement-compiler/package.json +1 -1
- package/packages/runtime/package.json +1 -1
- package/packages/scheduler/package.json +1 -1
- package/packages/scheduler-adapter/package.json +1 -1
- package/packages/session/package.json +1 -1
- package/packages/session-api/package.json +1 -1
- package/packages/session-export/package.json +1 -1
- package/packages/shared-context/package.json +1 -1
- package/packages/skill-mcp-client/package.json +1 -1
- package/packages/skill-registry/package.json +1 -1
- package/packages/sprint-planner/package.json +1 -1
- package/packages/subscription-engine/package.json +1 -1
- package/packages/task-compiler/package.json +1 -1
- package/packages/tencentdb-memory/package.json +1 -1
- package/packages/tencentdb-sync/package.json +1 -1
- package/packages/test-data-generator/package.json +1 -1
- package/packages/test-generator/package.json +1 -1
- package/packages/todo-bd-sync/package.json +1 -1
- package/packages/token-estimation/package.json +1 -1
- package/packages/token-optimizer/package.json +1 -1
- package/packages/trajectory/package.json +1 -1
- package/packages/tui/package.json +1 -1
- package/packages/types/package.json +1 -1
- package/packages/workflow-events/package.json +1 -1
- package/packages/workspace-scanner/package.json +1 -1
- package/packages/worktree/package.json +1 -1
- package/packages/write-review/package.json +1 -1
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chrome Profile Manager — Browser-based quota scraping via Playwright
|
|
3
|
+
*
|
|
4
|
+
* Key concepts from google-flow-mcp:
|
|
5
|
+
* - Uses Playwright to connect to existing Chrome profile with stored cookies
|
|
6
|
+
* - Maintains persistent session across runs
|
|
7
|
+
* - Bypasses anti-bot measures by launching Chrome directly
|
|
8
|
+
*
|
|
9
|
+
* This enables scraping JavaScript-rendered pages that require authentication:
|
|
10
|
+
* - chatgpt.com/codex/cloud/settings/analytics
|
|
11
|
+
* - z.ai/manage-apikey/coding-plan/personal/usage
|
|
12
|
+
* - etc.
|
|
13
|
+
*/
|
|
14
|
+
export interface ChromeProfileConfig {
|
|
15
|
+
/** Provider name (e.g., "codex", "z-ai") */
|
|
16
|
+
provider: string;
|
|
17
|
+
/** Path to Chrome user data directory (auto-detected if not provided) */
|
|
18
|
+
userDataDir?: string;
|
|
19
|
+
/** Profile directory name within userDataDir */
|
|
20
|
+
profileName?: string;
|
|
21
|
+
/** Path to browser binary (auto-detected if not provided) */
|
|
22
|
+
binaryPath?: string;
|
|
23
|
+
/** Arguments to pass to Chrome */
|
|
24
|
+
extraArgs?: string[];
|
|
25
|
+
/** Headless mode (default: true for scraping) */
|
|
26
|
+
headless?: boolean;
|
|
27
|
+
/** Launch timeout in ms */
|
|
28
|
+
launchTimeout?: number;
|
|
29
|
+
}
|
|
30
|
+
export interface BrowserProfile {
|
|
31
|
+
/** Path to the profile directory */
|
|
32
|
+
profilePath: string;
|
|
33
|
+
/** Provider name */
|
|
34
|
+
provider: string;
|
|
35
|
+
/** Whether the profile exists */
|
|
36
|
+
exists: boolean;
|
|
37
|
+
/** Last used timestamp */
|
|
38
|
+
lastUsed?: number;
|
|
39
|
+
}
|
|
40
|
+
/** Auto-detect Chrome user data directory based on OS */
|
|
41
|
+
export declare function detectChromeUserDataDir(): string | null;
|
|
42
|
+
/** Auto-detect Chrome binary path */
|
|
43
|
+
export declare function detectChromeBinary(): string | null;
|
|
44
|
+
/**
|
|
45
|
+
* Chrome Profile Manager for browser-based scraping
|
|
46
|
+
*
|
|
47
|
+
* Manages Chrome profiles for different providers to maintain
|
|
48
|
+
* authenticated sessions across scraping runs.
|
|
49
|
+
*/
|
|
50
|
+
export declare class ChromeProfileManager {
|
|
51
|
+
private profilesDir;
|
|
52
|
+
private profiles;
|
|
53
|
+
constructor(profilesDir?: string);
|
|
54
|
+
private ensureProfilesDir;
|
|
55
|
+
private getProfileMetaPath;
|
|
56
|
+
private loadProfiles;
|
|
57
|
+
/**
|
|
58
|
+
* Get profile path for a provider
|
|
59
|
+
*/
|
|
60
|
+
getProfilePath(provider: string): string;
|
|
61
|
+
/**
|
|
62
|
+
* Ensure profile directory exists
|
|
63
|
+
*/
|
|
64
|
+
ensureProfile(provider: string): BrowserProfile;
|
|
65
|
+
private saveProfileMeta;
|
|
66
|
+
/**
|
|
67
|
+
* List all managed profiles
|
|
68
|
+
*/
|
|
69
|
+
listProfiles(): BrowserProfile[];
|
|
70
|
+
/**
|
|
71
|
+
* Delete a profile
|
|
72
|
+
*/
|
|
73
|
+
deleteProfile(provider: string): Promise<void>;
|
|
74
|
+
/**
|
|
75
|
+
* Get Chrome launch arguments for anti-bot evasion
|
|
76
|
+
* Based on google-flow-mcp approach
|
|
77
|
+
*/
|
|
78
|
+
getLaunchArgs(config: ChromeProfileConfig): string[];
|
|
79
|
+
}
|
|
80
|
+
export declare function getChromeProfileManager(): ChromeProfileManager;
|
|
81
|
+
//# sourceMappingURL=chrome-profile-manager.d.ts.map
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chrome Profile Manager — Browser-based quota scraping via Playwright
|
|
3
|
+
*
|
|
4
|
+
* Key concepts from google-flow-mcp:
|
|
5
|
+
* - Uses Playwright to connect to existing Chrome profile with stored cookies
|
|
6
|
+
* - Maintains persistent session across runs
|
|
7
|
+
* - Bypasses anti-bot measures by launching Chrome directly
|
|
8
|
+
*
|
|
9
|
+
* This enables scraping JavaScript-rendered pages that require authentication:
|
|
10
|
+
* - chatgpt.com/codex/cloud/settings/analytics
|
|
11
|
+
* - z.ai/manage-apikey/coding-plan/personal/usage
|
|
12
|
+
* - etc.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
16
|
+
import { join, dirname } from "node:path";
|
|
17
|
+
import { homedir } from "node:os";
|
|
18
|
+
|
|
19
|
+
export interface ChromeProfileConfig {
|
|
20
|
+
/** Provider name (e.g., "codex", "z-ai") */
|
|
21
|
+
provider: string;
|
|
22
|
+
/** Path to Chrome user data directory (auto-detected if not provided) */
|
|
23
|
+
userDataDir?: string;
|
|
24
|
+
/** Profile directory name within userDataDir */
|
|
25
|
+
profileName?: string;
|
|
26
|
+
/** Path to browser binary (auto-detected if not provided) */
|
|
27
|
+
binaryPath?: string;
|
|
28
|
+
/** Arguments to pass to Chrome */
|
|
29
|
+
extraArgs?: string[];
|
|
30
|
+
/** Headless mode (default: true for scraping) */
|
|
31
|
+
headless?: boolean;
|
|
32
|
+
/** Launch timeout in ms */
|
|
33
|
+
launchTimeout?: number;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface BrowserProfile {
|
|
37
|
+
/** Path to the profile directory */
|
|
38
|
+
profilePath: string;
|
|
39
|
+
/** Provider name */
|
|
40
|
+
provider: string;
|
|
41
|
+
/** Whether the profile exists */
|
|
42
|
+
exists: boolean;
|
|
43
|
+
/** Last used timestamp */
|
|
44
|
+
lastUsed?: number;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Auto-detect Chrome user data directory based on OS */
|
|
48
|
+
export function detectChromeUserDataDir(): string | null {
|
|
49
|
+
const home = homedir();
|
|
50
|
+
const os = process.platform;
|
|
51
|
+
|
|
52
|
+
if (os === "linux") {
|
|
53
|
+
// Common Chrome Linux locations
|
|
54
|
+
const candidates = [
|
|
55
|
+
join(home, ".config", "google-chrome"),
|
|
56
|
+
join(home, ".config", "chromium"),
|
|
57
|
+
join(home, ".config", "google-chrome", "Default"),
|
|
58
|
+
];
|
|
59
|
+
for (const candidate of candidates) {
|
|
60
|
+
if (existsSync(candidate)) {
|
|
61
|
+
return dirname(candidate);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
// Return default without checking
|
|
65
|
+
return join(home, ".config", "google-chrome");
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (os === "darwin") {
|
|
69
|
+
return join(home, "Library", "Application Support", "Google", "Chrome");
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (os === "win32") {
|
|
73
|
+
const localAppData = process.env.LOCALAPPDATA ?? join(home, "AppData", "Local");
|
|
74
|
+
return join(localAppData, "Google", "Chrome", "User Data");
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** Auto-detect Chrome binary path */
|
|
81
|
+
export function detectChromeBinary(): string | null {
|
|
82
|
+
const os = process.platform;
|
|
83
|
+
|
|
84
|
+
if (os === "linux") {
|
|
85
|
+
const candidates = [
|
|
86
|
+
"/usr/bin/google-chrome",
|
|
87
|
+
"/usr/bin/google-chrome-stable",
|
|
88
|
+
"/usr/bin/chromium",
|
|
89
|
+
"/usr/bin/chromium-browser",
|
|
90
|
+
"/snap/bin/chromium",
|
|
91
|
+
];
|
|
92
|
+
for (const candidate of candidates) {
|
|
93
|
+
if (existsSync(candidate)) {
|
|
94
|
+
return candidate;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (os === "darwin") {
|
|
100
|
+
const candidates = [
|
|
101
|
+
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
|
|
102
|
+
"/Applications/Chromium.app/Contents/MacOS/Chromium",
|
|
103
|
+
];
|
|
104
|
+
for (const candidate of candidates) {
|
|
105
|
+
if (existsSync(candidate)) {
|
|
106
|
+
return candidate;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (os === "win32") {
|
|
112
|
+
const programFiles = process.env["ProgramFiles"] ?? "C:\\Program Files";
|
|
113
|
+
const programFilesX86 = process.env["ProgramFiles(x86)"] ?? "C:\\Program Files (x86)";
|
|
114
|
+
const candidates = [
|
|
115
|
+
join(programFiles, "Google", "Chrome", "Application", "chrome.exe"),
|
|
116
|
+
join(programFilesX86, "Google", "Chrome", "Application", "chrome.exe"),
|
|
117
|
+
join(programFiles, "Chromium", "Application", "chrome.exe"),
|
|
118
|
+
];
|
|
119
|
+
for (const candidate of candidates) {
|
|
120
|
+
if (existsSync(candidate)) {
|
|
121
|
+
return candidate;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Chrome Profile Manager for browser-based scraping
|
|
131
|
+
*
|
|
132
|
+
* Manages Chrome profiles for different providers to maintain
|
|
133
|
+
* authenticated sessions across scraping runs.
|
|
134
|
+
*/
|
|
135
|
+
export class ChromeProfileManager {
|
|
136
|
+
private profilesDir: string;
|
|
137
|
+
private profiles: Map<string, BrowserProfile> = new Map();
|
|
138
|
+
|
|
139
|
+
constructor(profilesDir?: string) {
|
|
140
|
+
this.profilesDir =
|
|
141
|
+
profilesDir ?? join(homedir(), ".pi-harness-runtime", "browser-profiles");
|
|
142
|
+
this.ensureProfilesDir();
|
|
143
|
+
this.loadProfiles();
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
private ensureProfilesDir(): void {
|
|
147
|
+
if (!existsSync(this.profilesDir)) {
|
|
148
|
+
mkdirSync(this.profilesDir, { recursive: true });
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
private getProfileMetaPath(provider: string): string {
|
|
153
|
+
return join(this.profilesDir, `${provider}.meta.json`);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
private loadProfiles(): void {
|
|
157
|
+
if (!existsSync(this.profilesDir)) return;
|
|
158
|
+
|
|
159
|
+
const { readdirSync } = require("node:fs");
|
|
160
|
+
const entries = readdirSync(this.profilesDir);
|
|
161
|
+
for (const entry of entries) {
|
|
162
|
+
if (entry.endsWith(".meta.json")) {
|
|
163
|
+
const provider = entry.replace(".meta.json", "");
|
|
164
|
+
const metaPath = this.getProfileMetaPath(provider);
|
|
165
|
+
try {
|
|
166
|
+
const meta = JSON.parse(readFileSync(metaPath, "utf-8"));
|
|
167
|
+
this.profiles.set(provider, meta);
|
|
168
|
+
} catch {
|
|
169
|
+
// Skip invalid meta files
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Get profile path for a provider
|
|
177
|
+
*/
|
|
178
|
+
getProfilePath(provider: string): string {
|
|
179
|
+
return join(this.profilesDir, provider);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Ensure profile directory exists
|
|
184
|
+
*/
|
|
185
|
+
ensureProfile(provider: string): BrowserProfile {
|
|
186
|
+
const profilePath = this.getProfilePath(provider);
|
|
187
|
+
|
|
188
|
+
if (!existsSync(profilePath)) {
|
|
189
|
+
mkdirSync(profilePath, { recursive: true });
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const profile: BrowserProfile = {
|
|
193
|
+
profilePath,
|
|
194
|
+
provider,
|
|
195
|
+
exists: true,
|
|
196
|
+
lastUsed: Date.now(),
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
this.saveProfileMeta(profile);
|
|
200
|
+
this.profiles.set(provider, profile);
|
|
201
|
+
|
|
202
|
+
return profile;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
private saveProfileMeta(profile: BrowserProfile): void {
|
|
206
|
+
const metaPath = this.getProfileMetaPath(profile.provider);
|
|
207
|
+
writeFileSync(metaPath, JSON.stringify(profile, null, 2));
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* List all managed profiles
|
|
212
|
+
*/
|
|
213
|
+
listProfiles(): BrowserProfile[] {
|
|
214
|
+
return Array.from(this.profiles.values());
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Delete a profile
|
|
219
|
+
*/
|
|
220
|
+
async deleteProfile(provider: string): Promise<void> {
|
|
221
|
+
const { rmSync } = await import("node:fs");
|
|
222
|
+
const profilePath = this.getProfilePath(provider);
|
|
223
|
+
|
|
224
|
+
if (existsSync(profilePath)) {
|
|
225
|
+
rmSync(profilePath, { recursive: true, force: true });
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const metaPath = this.getProfileMetaPath(provider);
|
|
229
|
+
if (existsSync(metaPath)) {
|
|
230
|
+
rmSync(metaPath, { force: true });
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
this.profiles.delete(provider);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Get Chrome launch arguments for anti-bot evasion
|
|
238
|
+
* Based on google-flow-mcp approach
|
|
239
|
+
*/
|
|
240
|
+
getLaunchArgs(config: ChromeProfileConfig): string[] {
|
|
241
|
+
const args = [
|
|
242
|
+
// Disable automation flags
|
|
243
|
+
"--disable-blink-features=AutomationControlled",
|
|
244
|
+
"--no-first-run",
|
|
245
|
+
"--no-default-browser-check",
|
|
246
|
+
// Disable extensions
|
|
247
|
+
"--disable-extensions",
|
|
248
|
+
// Disable background networking
|
|
249
|
+
"--disable-background-networking",
|
|
250
|
+
// Disable background threading
|
|
251
|
+
"--disable-background-timer-throttling",
|
|
252
|
+
// Disable background render
|
|
253
|
+
"--disable-renderer-backgrounding",
|
|
254
|
+
// Disable background occluded windows
|
|
255
|
+
"--disable-backgrounding-occluded-windows",
|
|
256
|
+
// Disable crash reporter
|
|
257
|
+
"--disable-crash-reporter",
|
|
258
|
+
// Disable logging
|
|
259
|
+
"--disable-logging",
|
|
260
|
+
// Disable devtools sharing
|
|
261
|
+
"--disable-dev-shm-usage",
|
|
262
|
+
// Disable Chrome sandbox (needed in some environments)
|
|
263
|
+
// "--no-sandbox", // Uncomment if running in Docker without sandbox
|
|
264
|
+
];
|
|
265
|
+
|
|
266
|
+
// Add user data dir if using managed profile
|
|
267
|
+
if (!config.userDataDir && config.profileName) {
|
|
268
|
+
// Use our managed profile directory
|
|
269
|
+
args.push(`--user-data-dir=${this.getProfilePath(config.provider)}`);
|
|
270
|
+
} else if (config.userDataDir) {
|
|
271
|
+
// Use external Chrome user data dir
|
|
272
|
+
args.push(`--user-data-dir=${config.userDataDir}`);
|
|
273
|
+
if (config.profileName) {
|
|
274
|
+
args.push(`--profile-directory=${config.profileName}`);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Add extra args
|
|
279
|
+
if (config.extraArgs) {
|
|
280
|
+
args.push(...config.extraArgs);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
return args;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Default Chrome profile manager instance
|
|
289
|
+
*/
|
|
290
|
+
let defaultManager: ChromeProfileManager | null = null;
|
|
291
|
+
|
|
292
|
+
export function getChromeProfileManager(): ChromeProfileManager {
|
|
293
|
+
if (!defaultManager) {
|
|
294
|
+
defaultManager = new ChromeProfileManager();
|
|
295
|
+
}
|
|
296
|
+
return defaultManager;
|
|
297
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Codex Browser Scraper — Scrapes chatgpt.com/codex/cloud/settings/analytics
|
|
3
|
+
*
|
|
4
|
+
* Uses Playwright with Chrome profile to access the authenticated page
|
|
5
|
+
* and extract usage/quota data.
|
|
6
|
+
*/
|
|
7
|
+
import { BaseBrowserScraper } from "./base-browser-scraper.js";
|
|
8
|
+
export interface CodexQuotaData {
|
|
9
|
+
provider: "openai-codex";
|
|
10
|
+
/** Plan type (e.g., "pro", "plus") */
|
|
11
|
+
planType?: string;
|
|
12
|
+
/** Current usage percentage (0-100) */
|
|
13
|
+
usagePercent: number;
|
|
14
|
+
/** Total quota amount */
|
|
15
|
+
totalQuota?: string;
|
|
16
|
+
/** Used quota amount */
|
|
17
|
+
usedQuota?: string;
|
|
18
|
+
/** Remaining quota */
|
|
19
|
+
remainingQuota?: string;
|
|
20
|
+
/** Reset date/time */
|
|
21
|
+
resetAt?: string;
|
|
22
|
+
/** Usage period description */
|
|
23
|
+
period?: string;
|
|
24
|
+
/** Raw data for debugging */
|
|
25
|
+
rawData?: Record<string, unknown>;
|
|
26
|
+
/** Timestamp */
|
|
27
|
+
scrapedAt: string;
|
|
28
|
+
}
|
|
29
|
+
interface CodexScraperConfig {
|
|
30
|
+
provider?: string;
|
|
31
|
+
url?: string;
|
|
32
|
+
headless?: boolean;
|
|
33
|
+
timeout?: number;
|
|
34
|
+
viewport?: {
|
|
35
|
+
width: number;
|
|
36
|
+
height: number;
|
|
37
|
+
};
|
|
38
|
+
slowMo?: number;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Codex Browser Scraper
|
|
42
|
+
*
|
|
43
|
+
* Scrapes usage data from chatgpt.com/codex/cloud/settings/analytics
|
|
44
|
+
*/
|
|
45
|
+
export declare class CodexBrowserScraper extends BaseBrowserScraper<CodexQuotaData> {
|
|
46
|
+
constructor(config?: Partial<CodexScraperConfig>);
|
|
47
|
+
protected createBrowser(): Promise<void>;
|
|
48
|
+
private getProfileDir;
|
|
49
|
+
protected isLoginPage(): Promise<boolean>;
|
|
50
|
+
protected extractData(): Promise<CodexQuotaData | null>;
|
|
51
|
+
private extractUsageData;
|
|
52
|
+
private extractAdditionalData;
|
|
53
|
+
private extractFromHeadings;
|
|
54
|
+
private extractChartData;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Quick scrape function
|
|
58
|
+
*/
|
|
59
|
+
export declare function scrapeCodexQuota(): Promise<CodexQuotaData | null>;
|
|
60
|
+
export {};
|
|
61
|
+
//# sourceMappingURL=codex-browser-scraper.d.ts.map
|