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.
Files changed (116) hide show
  1. package/harness/browser-scrapers/base-browser-scraper.d.ts +91 -0
  2. package/harness/browser-scrapers/chrome-profile-manager.d.ts +80 -0
  3. package/harness/browser-scrapers/codex-browser-scraper.d.ts +60 -0
  4. package/harness/browser-scrapers/index.d.ts +29 -0
  5. package/harness/browser-scrapers/zai-browser-scraper.d.ts +79 -0
  6. package/harness/e2e/browser-scrapers/base-browser-scraper.d.ts +92 -0
  7. package/harness/e2e/browser-scrapers/base-browser-scraper.ts +244 -0
  8. package/harness/e2e/browser-scrapers/chrome-profile-manager.d.ts +81 -0
  9. package/harness/e2e/browser-scrapers/chrome-profile-manager.ts +297 -0
  10. package/harness/e2e/browser-scrapers/codex-browser-scraper.d.ts +61 -0
  11. package/harness/e2e/browser-scrapers/codex-browser-scraper.ts +343 -0
  12. package/harness/e2e/browser-scrapers/index.d.ts +30 -0
  13. package/harness/e2e/browser-scrapers/index.ts +48 -0
  14. package/harness/e2e/browser-scrapers/zai-browser-scraper.d.ts +80 -0
  15. package/harness/e2e/browser-scrapers/zai-browser-scraper.ts +392 -0
  16. package/harness/e2e/glm-quota-scraper.ts +106 -15
  17. package/harness/e2e/index.ts +29 -0
  18. package/harness/e2e/unified-quota-manager.ts +364 -0
  19. package/index.ts +72 -11
  20. package/mirror.ts +32 -28
  21. package/package.json +1 -1
  22. package/packages/a2a-adapter/package.json +1 -1
  23. package/packages/architecture-generator/package.json +1 -1
  24. package/packages/auth/package.json +1 -1
  25. package/packages/autonomous-refactor/package.json +1 -1
  26. package/packages/autonomous-runtime/package.json +1 -1
  27. package/packages/cache-strategy/package.json +1 -1
  28. package/packages/capability-registry/package.json +1 -1
  29. package/packages/checkpoint/package.json +1 -1
  30. package/packages/cli-plugin-sdk/package.json +1 -1
  31. package/packages/clipboard/package.json +1 -1
  32. package/packages/clipboard-plugin/package.json +1 -1
  33. package/packages/code-generation/package.json +1 -1
  34. package/packages/code-review/package.json +1 -1
  35. package/packages/codex-adapter/package.json +1 -1
  36. package/packages/config-capture/package.json +1 -1
  37. package/packages/context-compiler/package.json +1 -1
  38. package/packages/context-discovery/package.json +1 -1
  39. package/packages/context-manager/package.json +1 -1
  40. package/packages/cookie-sanitizer/package.json +1 -1
  41. package/packages/cost-optimizer/package.json +1 -1
  42. package/packages/dependency-analyzer/package.json +1 -1
  43. package/packages/django-plugin/package.json +1 -1
  44. package/packages/doc-generator/package.json +1 -1
  45. package/packages/evaluation-engine/package.json +1 -1
  46. package/packages/evaluation-runner/package.json +1 -1
  47. package/packages/event-bus/package.json +1 -1
  48. package/packages/event-store/package.json +1 -1
  49. package/packages/experience-replay/package.json +1 -1
  50. package/packages/feedback-collector/package.json +1 -1
  51. package/packages/file-copy-helper/package.json +1 -1
  52. package/packages/framework-detector/package.json +1 -1
  53. package/packages/framework-plugin-sdk/package.json +1 -1
  54. package/packages/frappe-plugin/package.json +1 -1
  55. package/packages/generic-web-plugin/package.json +1 -1
  56. package/packages/health-monitor/package.json +1 -1
  57. package/packages/intent-analyzer/package.json +1 -1
  58. package/packages/jev-judge/package.json +1 -1
  59. package/packages/knowledge-graph/package.json +1 -1
  60. package/packages/knowledge-retrieval/package.json +1 -1
  61. package/packages/laravel-plugin/package.json +1 -1
  62. package/packages/learning-engine/package.json +1 -1
  63. package/packages/mcp-adapter/package.json +1 -1
  64. package/packages/memory-engine/package.json +1 -1
  65. package/packages/milestone-manager/package.json +1 -1
  66. package/packages/model-registry/package.json +1 -1
  67. package/packages/nextjs-plugin/package.json +1 -1
  68. package/packages/notification/package.json +1 -1
  69. package/packages/observability/package.json +1 -1
  70. package/packages/okf-indexer/package.json +1 -1
  71. package/packages/performance-optimizer/package.json +1 -1
  72. package/packages/privilege-broker/package.json +1 -1
  73. package/packages/project-analyzer/package.json +1 -1
  74. package/packages/project-bootstrap/package.json +1 -1
  75. package/packages/projection-engine/package.json +1 -1
  76. package/packages/prompt-compiler/package.json +1 -1
  77. package/packages/prompt-versioning/package.json +1 -1
  78. package/packages/provider-adapter-sdk/package.json +1 -1
  79. package/packages/provider-router/package.json +1 -1
  80. package/packages/provider-selector/package.json +1 -1
  81. package/packages/providers/dist/provider-id.d.ts.map +1 -1
  82. package/packages/providers/dist/provider-id.js +1 -2
  83. package/packages/providers/dist/provider-id.js.map +1 -1
  84. package/packages/providers/package.json +1 -1
  85. package/packages/providers/src/provider-id.ts +1 -2
  86. package/packages/quota-manager/package.json +1 -1
  87. package/packages/rate-limiter/package.json +1 -1
  88. package/packages/react-vite-plugin/package.json +1 -1
  89. package/packages/release-manager/package.json +1 -1
  90. package/packages/requirement-compiler/package.json +1 -1
  91. package/packages/runtime/package.json +1 -1
  92. package/packages/scheduler/package.json +1 -1
  93. package/packages/scheduler-adapter/package.json +1 -1
  94. package/packages/session/package.json +1 -1
  95. package/packages/session-api/package.json +1 -1
  96. package/packages/session-export/package.json +1 -1
  97. package/packages/shared-context/package.json +1 -1
  98. package/packages/skill-mcp-client/package.json +1 -1
  99. package/packages/skill-registry/package.json +1 -1
  100. package/packages/sprint-planner/package.json +1 -1
  101. package/packages/subscription-engine/package.json +1 -1
  102. package/packages/task-compiler/package.json +1 -1
  103. package/packages/tencentdb-memory/package.json +1 -1
  104. package/packages/tencentdb-sync/package.json +1 -1
  105. package/packages/test-data-generator/package.json +1 -1
  106. package/packages/test-generator/package.json +1 -1
  107. package/packages/todo-bd-sync/package.json +1 -1
  108. package/packages/token-estimation/package.json +1 -1
  109. package/packages/token-optimizer/package.json +1 -1
  110. package/packages/trajectory/package.json +1 -1
  111. package/packages/tui/package.json +1 -1
  112. package/packages/types/package.json +1 -1
  113. package/packages/workflow-events/package.json +1 -1
  114. package/packages/workspace-scanner/package.json +1 -1
  115. package/packages/worktree/package.json +1 -1
  116. package/packages/write-review/package.json +1 -1
@@ -0,0 +1,343 @@
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
+
8
+ import { BaseBrowserScraper } from "./base-browser-scraper.js";
9
+
10
+ export interface CodexQuotaData {
11
+ provider: "openai-codex";
12
+ /** Plan type (e.g., "pro", "plus") */
13
+ planType?: string;
14
+ /** Current usage percentage (0-100) */
15
+ usagePercent: number;
16
+ /** Total quota amount */
17
+ totalQuota?: string;
18
+ /** Used quota amount */
19
+ usedQuota?: string;
20
+ /** Remaining quota */
21
+ remainingQuota?: string;
22
+ /** Reset date/time */
23
+ resetAt?: string;
24
+ /** Usage period description */
25
+ period?: string;
26
+ /** Raw data for debugging */
27
+ rawData?: Record<string, unknown>;
28
+ /** Timestamp */
29
+ scrapedAt: string;
30
+ }
31
+
32
+ interface CodexScraperConfig {
33
+ provider?: string;
34
+ url?: string;
35
+ headless?: boolean;
36
+ timeout?: number;
37
+ viewport?: { width: number; height: number };
38
+ slowMo?: number;
39
+ }
40
+
41
+ /**
42
+ * Codex Browser Scraper
43
+ *
44
+ * Scrapes usage data from chatgpt.com/codex/cloud/settings/analytics
45
+ */
46
+ export class CodexBrowserScraper extends BaseBrowserScraper<CodexQuotaData> {
47
+ constructor(config: Partial<CodexScraperConfig> = {}) {
48
+ super({
49
+ provider: "openai-codex",
50
+ url: config.url ?? "https://chatgpt.com/codex/cloud/settings/analytics",
51
+ headless: config.headless ?? true,
52
+ timeout: config.timeout ?? 30000,
53
+ viewport: config.viewport,
54
+ slowMo: config.slowMo,
55
+ });
56
+ }
57
+
58
+ protected async createBrowser(): Promise<void> {
59
+ const { chromium } = await import("playwright");
60
+ const profileDir = this.getProfileDir();
61
+
62
+ this.browser = await chromium.launch({
63
+ headless: this.config.headless,
64
+ slowMo: this.config.slowMo,
65
+ args: [
66
+ `--user-data-dir=${profileDir}`,
67
+ "--disable-blink-features=AutomationControlled",
68
+ ],
69
+ });
70
+
71
+ this.context = await this.browser.newContext({
72
+ viewport: this.config.viewport,
73
+ });
74
+
75
+ this.page = await this.context.newPage();
76
+ }
77
+
78
+ private getProfileDir(): string {
79
+ const { join } = require("node:path");
80
+ const { homedir } = require("node:os");
81
+ return join(homedir(), ".pi-harness-runtime", "browser-profiles", "codex");
82
+ }
83
+
84
+ protected async isLoginPage(): Promise<boolean> {
85
+ if (!this.page) return false;
86
+
87
+ // Check for common login indicators
88
+ const loginSelectors = [
89
+ 'button[data-testid="sign-in"]',
90
+ 'button:has-text("Sign in")',
91
+ 'input[name="email"]',
92
+ 'input[placeholder*="email" i]',
93
+ '[data-testid="login"]',
94
+ ];
95
+
96
+ for (const selector of loginSelectors) {
97
+ try {
98
+ const element = await this.page.$(selector);
99
+ if (element != null) {
100
+ const text = await element.textContent();
101
+ if (text && /sign\s*in|log\s*in/i.test(text)) {
102
+ return true;
103
+ }
104
+ }
105
+ } catch {
106
+ // Selector might not exist, continue
107
+ }
108
+ }
109
+
110
+ // Check URL for login-related paths
111
+ const url = this.page.url();
112
+ if (/signin|login|auth/i.test(url)) {
113
+ return true;
114
+ }
115
+
116
+ return false;
117
+ }
118
+
119
+ protected async extractData(): Promise<CodexQuotaData | null> {
120
+ if (!this.page) return null;
121
+
122
+ try {
123
+ // Wait for the analytics page to load
124
+ await this.page.waitForTimeout(3000);
125
+
126
+ // Try multiple selectors for usage data
127
+ const usageData = await this.extractUsageData();
128
+ if (!usageData) {
129
+ return null;
130
+ }
131
+
132
+ return {
133
+ provider: "openai-codex",
134
+ ...usageData,
135
+ scrapedAt: new Date().toISOString(),
136
+ };
137
+ } catch (error) {
138
+ console.error(`[codex] Extraction error: ${error}`);
139
+ return null;
140
+ }
141
+ }
142
+
143
+ private async extractUsageData(): Promise<Omit<CodexQuotaData, "provider" | "scrapedAt"> | null> {
144
+ if (!this.page) return null;
145
+
146
+ // Strategy 1: Look for percentage display
147
+ const percentSelectors = [
148
+ // Common patterns for usage percentage
149
+ '[class*="usage"] [class*="percent"]',
150
+ '[data-testid*="usage"] [class*="progress"]',
151
+ '[class*="quota"] [class*="percent"]',
152
+ // Text content patterns
153
+ 'text=/\\d+%/',
154
+ // SVG progress circles
155
+ 'svg[class*="progress"]',
156
+ // Heading patterns
157
+ 'h1:has-text("Usage") + *',
158
+ 'h2:has-text("Usage") + *',
159
+ ];
160
+
161
+ for (const selector of percentSelectors) {
162
+ try {
163
+ const element = await this.page.$(selector);
164
+ if (element != null) {
165
+ const text = await element.textContent();
166
+ const percentMatch = text?.match(/(\d+(?:\.\d+)?)\s*%/);
167
+ if (percentMatch) {
168
+ const usagePercent = parseFloat(percentMatch[1]);
169
+ if (!isNaN(usagePercent)) {
170
+ // Try to get additional data
171
+ const additionalData = await this.extractAdditionalData();
172
+ return {
173
+ usagePercent,
174
+ ...additionalData,
175
+ };
176
+ }
177
+ }
178
+ }
179
+ } catch {
180
+ // Continue to next selector
181
+ }
182
+ }
183
+
184
+ // Strategy 2: Look for numbers in heading/title
185
+ const headingData = await this.extractFromHeadings();
186
+ if (headingData) {
187
+ return headingData;
188
+ }
189
+
190
+ // Strategy 3: Look for chart/graph data (often contains raw numbers)
191
+ const chartData = await this.extractChartData();
192
+ if (chartData) {
193
+ return chartData;
194
+ }
195
+
196
+ return null;
197
+ }
198
+
199
+ private async extractAdditionalData(): Promise<Partial<CodexQuotaData>> {
200
+ const result: Partial<CodexQuotaData> = {};
201
+
202
+ // Try to extract plan type
203
+ const planSelectors = [
204
+ '[class*="plan"]',
205
+ '[data-testid*="plan"]',
206
+ 'text=/Pro|Plus|Team|Enterprise/i',
207
+ ];
208
+
209
+ for (const selector of planSelectors) {
210
+ try {
211
+ if (!this.page) continue;
212
+ const text = await this.page.locator(selector).first().textContent({ timeout: 2000 }).catch(() => null);
213
+ if (text && /Pro|Plus|Team|Enterprise/i.test(text)) {
214
+ result.planType = text.trim();
215
+ break;
216
+ }
217
+ } catch {
218
+ // Continue
219
+ }
220
+ }
221
+
222
+ // Try to extract quota amounts (e.g., "1.5 GB of 5 GB used")
223
+ const quotaText = await this.extractText('text=/\\d+.*\\/(?:of\\s+)?\\d+/');
224
+ if (quotaText) {
225
+ const match = quotaText.match(/([\d,.]+)\s*(?:GB|MB|TB)?\s*(?:\/|of)\s*([\d,.]+)\s*(?:GB|MB|TB)?/i);
226
+ if (match) {
227
+ result.usedQuota = match[1];
228
+ result.totalQuota = match[2];
229
+ result.remainingQuota = String(parseFloat(match[2]) - parseFloat(match[1]));
230
+ }
231
+ }
232
+
233
+ // Try to extract reset date
234
+ const resetSelectors = [
235
+ 'text=/resets?\\s+(at|on|in)/i',
236
+ '[class*="reset"]',
237
+ '[class*="renews"]',
238
+ ];
239
+
240
+ for (const selector of resetSelectors) {
241
+ try {
242
+ if (!this.page) continue;
243
+ const text = await this.page.locator(selector).first().textContent({ timeout: 2000 }).catch(() => null);
244
+ if (text) {
245
+ result.resetAt = text.trim();
246
+ break;
247
+ }
248
+ } catch {
249
+ // Continue
250
+ }
251
+ }
252
+
253
+ return result;
254
+ }
255
+
256
+ private async extractFromHeadings(): Promise<Omit<CodexQuotaData, "provider" | "scrapedAt"> | null> {
257
+ if (!this.page) return null;
258
+
259
+ // Get all headings and look for ones containing numbers
260
+ const headings = await this.page.$$("h1, h2, h3, h4");
261
+ for (const heading of headings) {
262
+ const text = await heading.textContent();
263
+ if (text) {
264
+ const percentMatch = text.match(/(\d+(?:\.\d+)?)\s*%/);
265
+ if (percentMatch) {
266
+ return {
267
+ usagePercent: parseFloat(percentMatch[1]),
268
+ period: text.replace(percentMatch[0], "").trim() || undefined,
269
+ };
270
+ }
271
+ }
272
+ }
273
+
274
+ return null;
275
+ }
276
+
277
+ private async extractChartData(): Promise<Omit<CodexQuotaData, "provider" | "scrapedAt"> | null> {
278
+ if (!this.page) return null;
279
+
280
+ // Look for canvas or SVG charts
281
+ const charts = await this.page.$$("canvas, svg[class*='chart'], svg[class*='graph']");
282
+ if (charts.length > 0) {
283
+ // Try to get data from aria-labels or data attributes
284
+ for (const chart of charts) {
285
+ const ariaLabel = await chart.getAttribute("aria-label");
286
+ if (ariaLabel) {
287
+ const percentMatch = ariaLabel.match(/(\d+(?:\.\d+)?)\s*%/);
288
+ if (percentMatch) {
289
+ return {
290
+ usagePercent: parseFloat(percentMatch[1]),
291
+ };
292
+ }
293
+ }
294
+ }
295
+
296
+ // Try to extract from JavaScript data
297
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
298
+ const chartData = await this.page.evaluate(() => {
299
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
300
+ const win = (globalThis as any);
301
+ const doc = win.document;
302
+ if (!doc) return null;
303
+ const canvases = doc.querySelectorAll("canvas");
304
+ const foundResult: { percent: number } | null = null;
305
+ for (const canvas of canvases) {
306
+ const parent = canvas.parentElement;
307
+ if (parent) {
308
+ const attrNames: string[] = Array.from(parent.getAttributeNames());
309
+ for (const attrName of attrNames) {
310
+ if (attrName.startsWith("data-") || attrName.includes("chart")) {
311
+ const value = parent.getAttribute(attrName);
312
+ const match = value?.match(/(\d+(?:\.\d+)?)\s*%/);
313
+ if (match) {
314
+ return { percent: parseFloat(match[1]) };
315
+ }
316
+ }
317
+ }
318
+ }
319
+ }
320
+ return foundResult;
321
+ });
322
+
323
+ if (chartData?.percent) {
324
+ return { usagePercent: chartData.percent };
325
+ }
326
+ }
327
+
328
+ return null;
329
+ }
330
+ }
331
+
332
+ /**
333
+ * Quick scrape function
334
+ */
335
+ export async function scrapeCodexQuota(): Promise<CodexQuotaData | null> {
336
+ const scraper = new CodexBrowserScraper({ headless: true });
337
+ try {
338
+ const result = await scraper.scrape();
339
+ return result.data ?? null;
340
+ } finally {
341
+ await scraper.cleanup();
342
+ }
343
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Browser Scrapers — Browser-based quota scraping via Playwright
3
+ *
4
+ * Authentication strategies by provider:
5
+ *
6
+ * | Provider | Auth Method | Cookies Work? | Notes |
7
+ * |-----------|----------------------|---------------|--------------------------|
8
+ * | MiniMax | Browser cookies | Yes | Direct browser scraping |
9
+ * | ChatGPT | OAuth tokens | No | Use ~/.codex/auth.json |
10
+ * | Codex | OAuth tokens | No | Use ~/.codex/auth.json |
11
+ * | Z.ai | Browser cookies | Unknown | Try browser profile |
12
+ *
13
+ * For providers where browser cookies don't work for automation:
14
+ * - Use API tokens (OAuth, API keys)
15
+ * - Export cookies from DevTools (may not work due to HttpOnly, Secure flags)
16
+ * - Manual authentication via headful browser with user interaction
17
+ */
18
+ export { ChromeProfileManager, getChromeProfileManager, detectChromeUserDataDir, detectChromeBinary, type ChromeProfileConfig, type BrowserProfile, } from "./chrome-profile-manager.js";
19
+ export { BaseBrowserScraper, type BrowserScraperConfig, type QuotaScrapingResult, } from "./base-browser-scraper.js";
20
+ export { CodexBrowserScraper, scrapeCodexQuota, type CodexQuotaData } from "./codex-browser-scraper.js";
21
+ export { ZaiBrowserScraper, scrapeZaiQuota, checkZaiCookies, type ZaiQuotaData } from "./zai-browser-scraper.js";
22
+ /**
23
+ * All available browser scrapers
24
+ */
25
+ export declare const BROWSER_SCRAPERS: {
26
+ readonly "openai-codex": () => Promise<typeof import("./codex-browser-scraper.js").CodexBrowserScraper>;
27
+ readonly "z-ai": () => Promise<typeof import("./zai-browser-scraper.js").ZaiBrowserScraper>;
28
+ };
29
+ export type BrowserScraperProvider = keyof typeof BROWSER_SCRAPERS;
30
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Browser Scrapers — Browser-based quota scraping via Playwright
3
+ *
4
+ * Authentication strategies by provider:
5
+ *
6
+ * | Provider | Auth Method | Cookies Work? | Notes |
7
+ * |-----------|----------------------|---------------|--------------------------|
8
+ * | MiniMax | Browser cookies | Yes | Direct browser scraping |
9
+ * | ChatGPT | OAuth tokens | No | Use ~/.codex/auth.json |
10
+ * | Codex | OAuth tokens | No | Use ~/.codex/auth.json |
11
+ * | Z.ai | Browser cookies | Unknown | Try browser profile |
12
+ *
13
+ * For providers where browser cookies don't work for automation:
14
+ * - Use API tokens (OAuth, API keys)
15
+ * - Export cookies from DevTools (may not work due to HttpOnly, Secure flags)
16
+ * - Manual authentication via headful browser with user interaction
17
+ */
18
+
19
+ // Chrome profile management for persistent sessions
20
+ export {
21
+ ChromeProfileManager,
22
+ getChromeProfileManager,
23
+ detectChromeUserDataDir,
24
+ detectChromeBinary,
25
+ type ChromeProfileConfig,
26
+ type BrowserProfile,
27
+ } from "./chrome-profile-manager.js";
28
+
29
+ // Base scraper class
30
+ export {
31
+ BaseBrowserScraper,
32
+ type BrowserScraperConfig,
33
+ type QuotaScrapingResult,
34
+ } from "./base-browser-scraper.js";
35
+
36
+ // Provider-specific scrapers
37
+ export { CodexBrowserScraper, scrapeCodexQuota, type CodexQuotaData } from "./codex-browser-scraper.js";
38
+ export { ZaiBrowserScraper, scrapeZaiQuota, checkZaiCookies, type ZaiQuotaData } from "./zai-browser-scraper.js";
39
+
40
+ /**
41
+ * All available browser scrapers
42
+ */
43
+ export const BROWSER_SCRAPERS = {
44
+ "openai-codex": () => import("./codex-browser-scraper.js").then((m) => m.CodexBrowserScraper),
45
+ "z-ai": () => import("./zai-browser-scraper.js").then((m) => m.ZaiBrowserScraper),
46
+ } as const;
47
+
48
+ export type BrowserScraperProvider = keyof typeof BROWSER_SCRAPERS;
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Z.ai Browser Scraper — Scrapes z.ai usage data
3
+ *
4
+ * Authentication approach:
5
+ * - Z.ai uses cookies from browser login (different from ChatGPT)
6
+ * - Cookies from ~/.config/google-chrome or browser export need to be tested
7
+ * - Fallback: Manual cookie export from browser DevTools
8
+ *
9
+ * Note: If cookies don't work for browser automation (like Codex),
10
+ * we may need to find alternative auth methods (OAuth, API keys, etc.)
11
+ */
12
+ import { BaseBrowserScraper } from "./base-browser-scraper.js";
13
+ export interface ZaiQuotaData {
14
+ provider: "z-ai";
15
+ /** Plan type (e.g., "Pro", "Team", "Enterprise") */
16
+ planType?: string;
17
+ /** Current usage percentage (0-100) */
18
+ usagePercent: number;
19
+ /** Total quota (e.g., "5 GB") */
20
+ totalQuota?: string;
21
+ /** Used quota (e.g., "1.5 GB") */
22
+ usedQuota?: string;
23
+ /** Remaining quota */
24
+ remainingQuota?: string;
25
+ /** Reset date/time */
26
+ resetAt?: string;
27
+ /** Billing period */
28
+ period?: string;
29
+ /** Timestamp */
30
+ scrapedAt: string;
31
+ }
32
+ interface ZaiScraperConfig {
33
+ provider?: string;
34
+ url?: string;
35
+ headless?: boolean;
36
+ timeout?: number;
37
+ viewport?: {
38
+ width: number;
39
+ height: number;
40
+ };
41
+ slowMo?: number;
42
+ /** Path to cookies file (Netscape format) */
43
+ cookiesFile?: string;
44
+ }
45
+ /**
46
+ * Z.ai Browser Scraper
47
+ */
48
+ export declare class ZaiBrowserScraper extends BaseBrowserScraper<ZaiQuotaData> {
49
+ private cookiesFile?;
50
+ constructor(config?: Partial<ZaiScraperConfig>);
51
+ /**
52
+ * Find available cookies file
53
+ */
54
+ private findCookiesFile;
55
+ protected createBrowser(): Promise<void>;
56
+ /**
57
+ * Load cookies from file and convert to headers (fallback auth method)
58
+ * Note: This won't work for all sites - some require full cookie jar
59
+ */
60
+ private loadCookiesAsHeaders;
61
+ protected isLoginPage(): Promise<boolean>;
62
+ protected extractData(): Promise<ZaiQuotaData | null>;
63
+ private extractUsagePercent;
64
+ private extractPlanType;
65
+ private extractQuotaData;
66
+ private extractResetDate;
67
+ }
68
+ /**
69
+ * Quick scrape function
70
+ */
71
+ export declare function scrapeZaiQuota(cookiesFile?: string): Promise<ZaiQuotaData | null>;
72
+ /**
73
+ * Check if z.ai cookies are available
74
+ */
75
+ export declare function checkZaiCookies(): {
76
+ available: boolean;
77
+ path?: string;
78
+ };
79
+ export {};
80
+ //# sourceMappingURL=zai-browser-scraper.d.ts.map