axusage 3.1.0 → 3.3.0

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 (88) hide show
  1. package/README.md +78 -194
  2. package/dist/adapters/claude.js +9 -8
  3. package/dist/adapters/coalesce-claude-usage-response.js +5 -7
  4. package/dist/adapters/{chatgpt.d.ts → codex.d.ts} +1 -1
  5. package/dist/adapters/{chatgpt.js → codex.js} +5 -5
  6. package/dist/adapters/copilot.d.ts +7 -0
  7. package/dist/adapters/copilot.js +58 -0
  8. package/dist/adapters/{parse-chatgpt-usage.d.ts → parse-codex-usage.d.ts} +3 -3
  9. package/dist/adapters/parse-copilot-usage.d.ts +15 -0
  10. package/dist/adapters/parse-copilot-usage.js +61 -0
  11. package/dist/cli.js +4 -21
  12. package/dist/commands/auth-setup-command.d.ts +1 -2
  13. package/dist/commands/auth-setup-command.js +44 -67
  14. package/dist/commands/auth-status-command.js +9 -40
  15. package/dist/commands/fetch-service-usage.d.ts +0 -1
  16. package/dist/commands/fetch-service-usage.js +1 -2
  17. package/dist/commands/run-auth-setup.d.ts +0 -10
  18. package/dist/commands/run-auth-setup.js +3 -80
  19. package/dist/commands/usage-command.d.ts +2 -7
  20. package/dist/commands/usage-command.js +7 -39
  21. package/dist/config/credential-sources.d.ts +3 -11
  22. package/dist/config/credential-sources.js +1 -1
  23. package/dist/services/get-service-access-token.d.ts +3 -3
  24. package/dist/services/get-service-access-token.js +11 -11
  25. package/dist/services/service-adapter-registry.d.ts +2 -2
  26. package/dist/services/service-adapter-registry.js +4 -4
  27. package/dist/services/service-diagnostics.d.ts +11 -0
  28. package/dist/services/service-diagnostics.js +29 -0
  29. package/dist/services/supported-service.d.ts +6 -2
  30. package/dist/services/supported-service.js +2 -6
  31. package/dist/types/{chatgpt.d.ts → codex.d.ts} +4 -4
  32. package/dist/types/{chatgpt.js → codex.js} +6 -6
  33. package/dist/types/copilot.d.ts +14 -0
  34. package/dist/types/copilot.js +21 -0
  35. package/dist/utils/check-cli-dependency.d.ts +2 -4
  36. package/dist/utils/check-cli-dependency.js +7 -4
  37. package/dist/utils/copilot-gh-token.d.ts +1 -0
  38. package/dist/utils/copilot-gh-token.js +38 -0
  39. package/dist/utils/format-requires-help-text.d.ts +17 -0
  40. package/dist/utils/format-requires-help-text.js +62 -0
  41. package/dist/utils/validate-root-options.d.ts +0 -3
  42. package/dist/utils/validate-root-options.js +2 -6
  43. package/package.json +15 -19
  44. package/dist/adapters/github-copilot.d.ts +0 -6
  45. package/dist/adapters/github-copilot.js +0 -57
  46. package/dist/adapters/parse-github-copilot-usage.d.ts +0 -23
  47. package/dist/adapters/parse-github-copilot-usage.js +0 -78
  48. package/dist/commands/auth-clear-command.d.ts +0 -7
  49. package/dist/commands/auth-clear-command.js +0 -84
  50. package/dist/commands/fetch-service-usage-with-reauth.d.ts +0 -7
  51. package/dist/commands/fetch-service-usage-with-reauth.js +0 -45
  52. package/dist/services/app-paths.d.ts +0 -9
  53. package/dist/services/app-paths.js +0 -39
  54. package/dist/services/auth-storage-path.d.ts +0 -3
  55. package/dist/services/auth-storage-path.js +0 -7
  56. package/dist/services/auth-timeouts.d.ts +0 -4
  57. package/dist/services/auth-timeouts.js +0 -4
  58. package/dist/services/browser-auth-manager.d.ts +0 -49
  59. package/dist/services/browser-auth-manager.js +0 -113
  60. package/dist/services/create-auth-context.d.ts +0 -8
  61. package/dist/services/create-auth-context.js +0 -35
  62. package/dist/services/do-setup-auth.d.ts +0 -3
  63. package/dist/services/do-setup-auth.js +0 -19
  64. package/dist/services/fetch-json-with-context.d.ts +0 -5
  65. package/dist/services/fetch-json-with-context.js +0 -37
  66. package/dist/services/launch-chromium.d.ts +0 -6
  67. package/dist/services/launch-chromium.js +0 -20
  68. package/dist/services/persist-storage-state.d.ts +0 -6
  69. package/dist/services/persist-storage-state.js +0 -16
  70. package/dist/services/request-service.d.ts +0 -3
  71. package/dist/services/request-service.js +0 -4
  72. package/dist/services/service-auth-configs.d.ts +0 -15
  73. package/dist/services/service-auth-configs.js +0 -26
  74. package/dist/services/setup-auth-flow.d.ts +0 -3
  75. package/dist/services/setup-auth-flow.js +0 -67
  76. package/dist/services/shared-browser-auth-manager.d.ts +0 -4
  77. package/dist/services/shared-browser-auth-manager.js +0 -87
  78. package/dist/services/verify-session.d.ts +0 -2
  79. package/dist/services/verify-session.js +0 -27
  80. package/dist/services/wait-for-login.d.ts +0 -6
  81. package/dist/services/wait-for-login.js +0 -115
  82. package/dist/types/github-copilot.d.ts +0 -21
  83. package/dist/types/github-copilot.js +0 -27
  84. package/dist/utils/resolve-prompt-capability.d.ts +0 -1
  85. package/dist/utils/resolve-prompt-capability.js +0 -3
  86. package/dist/utils/write-atomic-json.d.ts +0 -1
  87. package/dist/utils/write-atomic-json.js +0 -56
  88. /package/dist/adapters/{parse-chatgpt-usage.js → parse-codex-usage.js} +0 -0
@@ -1,84 +0,0 @@
1
- import { confirm } from "@inquirer/prompts";
2
- import { existsSync, readdirSync } from "node:fs";
3
- import path from "node:path";
4
- import trash from "trash";
5
- import { validateService } from "../services/supported-service.js";
6
- import { getAuthMetaPathFor, getStorageStatePathFor, } from "../services/auth-storage-path.js";
7
- import { getBrowserContextsDirectory } from "../services/app-paths.js";
8
- import { chalk } from "../utils/color.js";
9
- import { resolvePromptCapability } from "../utils/resolve-prompt-capability.js";
10
- function isPromptCancellation(error) {
11
- return (error instanceof Error &&
12
- (error.name === "AbortPromptError" ||
13
- error.name === "CancelPromptError" ||
14
- error.name === "ExitPromptError"));
15
- }
16
- function collectRelatedArtifacts(filePath) {
17
- const directory = path.dirname(filePath);
18
- const baseName = path.basename(filePath);
19
- try {
20
- return readdirSync(directory)
21
- .filter((entry) => entry.startsWith(`${baseName}.`) &&
22
- (entry.endsWith(".bak") || entry.endsWith(".tmp")))
23
- .map((entry) => path.join(directory, entry));
24
- }
25
- catch {
26
- return [];
27
- }
28
- }
29
- export async function authClearCommand(options) {
30
- const service = validateService(options.service);
31
- const dataDirectory = getBrowserContextsDirectory();
32
- const storage = getStorageStatePathFor(dataDirectory, service);
33
- const meta = getAuthMetaPathFor(dataDirectory, service);
34
- try {
35
- const artifactTargets = [storage, meta].filter((p) => existsSync(p));
36
- const backupTargets = [storage, meta].flatMap((filePath) => collectRelatedArtifacts(filePath));
37
- const targets = [...new Set([...artifactTargets, ...backupTargets])];
38
- if (targets.length === 0) {
39
- console.error(chalk.gray(`\nNo saved authentication found for ${service}.`));
40
- return;
41
- }
42
- if (!options.force) {
43
- if (!options.interactive) {
44
- console.error(chalk.red("Error: Clearing saved authentication requires confirmation."));
45
- console.error(chalk.gray("Re-run with --interactive to confirm, or use --force to skip confirmation."));
46
- console.error(chalk.gray("Try 'axusage --help' for details."));
47
- process.exitCode = 1;
48
- return;
49
- }
50
- if (!resolvePromptCapability()) {
51
- console.error(chalk.red("Error: --interactive requires a TTY-enabled terminal."));
52
- console.error(chalk.gray("Re-run in a terminal or pass --force instead."));
53
- console.error(chalk.gray("Try 'axusage --help' for details."));
54
- process.exitCode = 1;
55
- return;
56
- }
57
- let confirmed = false;
58
- try {
59
- confirmed = await confirm({
60
- message: `Remove saved authentication for ${service}?`,
61
- default: false,
62
- });
63
- }
64
- catch (error) {
65
- if (isPromptCancellation(error)) {
66
- console.error(chalk.gray("Aborted."));
67
- process.exitCode = 1;
68
- return;
69
- }
70
- throw error;
71
- }
72
- if (!confirmed) {
73
- console.error(chalk.gray("Aborted."));
74
- return;
75
- }
76
- }
77
- await trash(targets, { glob: false });
78
- console.error(chalk.green(`\n✓ Cleared authentication for ${service}`));
79
- }
80
- catch (error) {
81
- console.error(chalk.red(`\n✗ Failed to clear authentication for ${service}: ${error instanceof Error ? error.message : String(error)}`));
82
- process.exitCode = 1;
83
- }
84
- }
@@ -1,7 +0,0 @@
1
- import type { ServiceResult } from "../types/domain.js";
2
- /**
3
- * Fetch usage for a service, with automatic re-authentication on auth errors.
4
- * Prompts the user to re-authenticate if the initial fetch fails with an auth error,
5
- * then retries the fetch. Returns the original result if re-authentication fails.
6
- */
7
- export declare function fetchServiceUsageWithAutoReauth(serviceName: string, interactive: boolean): Promise<ServiceResult>;
@@ -1,45 +0,0 @@
1
- import { fetchServiceUsage } from "./fetch-service-usage.js";
2
- import { isAuthFailure, runAuthSetup } from "./run-auth-setup.js";
3
- import { validateService } from "../services/supported-service.js";
4
- import { chalk } from "../utils/color.js";
5
- /**
6
- * Fetch usage for a service, with automatic re-authentication on auth errors.
7
- * Prompts the user to re-authenticate if the initial fetch fails with an auth error,
8
- * then retries the fetch. Returns the original result if re-authentication fails.
9
- */
10
- export async function fetchServiceUsageWithAutoReauth(serviceName, interactive) {
11
- const result = await fetchServiceUsage(serviceName);
12
- if (!interactive) {
13
- return { service: serviceName, result };
14
- }
15
- // If auth error, try to re-authenticate and retry
16
- if (isAuthFailure(result)) {
17
- console.error(chalk.yellow(`⚠ Authentication failed for ${serviceName}. Attempting to re-authenticate...`));
18
- try {
19
- const service = validateService(serviceName);
20
- const authSuccess = await runAuthSetup(service);
21
- if (authSuccess) {
22
- if (process.stderr.isTTY) {
23
- console.error(chalk.blue(`Retrying ${serviceName} usage fetch...\n`));
24
- }
25
- const retryResult = await fetchServiceUsage(serviceName);
26
- return { service: serviceName, result: retryResult };
27
- }
28
- else {
29
- console.error(chalk.red(`Re-authentication failed for ${serviceName}.`));
30
- }
31
- }
32
- catch (error) {
33
- const errorMessage = error instanceof Error ? error.message : String(error);
34
- // Distinguish validation errors from auth setup errors
35
- const isValidationError = errorMessage.includes("Unsupported service") ||
36
- errorMessage.includes("Service is required");
37
- const prefix = isValidationError
38
- ? "Invalid service"
39
- : "Failed to re-authenticate";
40
- console.error(chalk.red(`${prefix}: ${errorMessage}`));
41
- }
42
- }
43
- // Return original result if re-authentication failed or was not attempted
44
- return { service: serviceName, result };
45
- }
@@ -1,9 +0,0 @@
1
- /**
2
- * Directory for storing browser authentication contexts
3
- */
4
- export declare function getBrowserContextsDirectory(): string;
5
- /**
6
- * Ensure a directory exists with restricted permissions (owner-only access).
7
- * Creates the directory recursively if needed and sets mode 0o700.
8
- */
9
- export declare function ensureSecureDirectory(directoryPath: string): Promise<void>;
@@ -1,39 +0,0 @@
1
- import envPaths from "env-paths";
2
- import path from "node:path";
3
- import { mkdir, chmod } from "node:fs/promises";
4
- /**
5
- * env-paths resolves directories during module initialization, so changes to
6
- * environment variables (like XDG_DATA_HOME) after the first import will not
7
- * be picked up without restarting the process.
8
- */
9
- const paths = envPaths("axusage", { suffix: "" });
10
- /**
11
- * Directory for storing browser authentication contexts
12
- */
13
- export function getBrowserContextsDirectory() {
14
- return path.join(paths.data, "browser-contexts");
15
- }
16
- /**
17
- * Ensure a directory exists with restricted permissions (owner-only access).
18
- * Creates the directory recursively if needed and sets mode 0o700.
19
- */
20
- export async function ensureSecureDirectory(directoryPath) {
21
- try {
22
- await mkdir(directoryPath, { recursive: true, mode: 0o700 });
23
- }
24
- catch (error) {
25
- // Only ignore EEXIST; re-throw everything else
26
- // mkdir may ignore mode due to umask; we'll enforce via chmod below
27
- const isEexist = error instanceof Error && "code" in error && error.code === "EEXIST";
28
- if (!isEexist) {
29
- throw error;
30
- }
31
- }
32
- try {
33
- await chmod(directoryPath, 0o700);
34
- }
35
- catch {
36
- // Best effort: some filesystems (network mounts, containers) may not
37
- // support chmod or have different permission models
38
- }
39
- }
@@ -1,3 +0,0 @@
1
- import type { SupportedService } from "./supported-service.js";
2
- export declare function getStorageStatePathFor(dataDirectory: string, service: SupportedService): string;
3
- export declare function getAuthMetaPathFor(dataDirectory: string, service: SupportedService): string;
@@ -1,7 +0,0 @@
1
- import path from "node:path";
2
- export function getStorageStatePathFor(dataDirectory, service) {
3
- return path.join(dataDirectory, `${service}-auth.json`);
4
- }
5
- export function getAuthMetaPathFor(dataDirectory, service) {
6
- return path.join(dataDirectory, `${service}-auth.meta.json`);
7
- }
@@ -1,4 +0,0 @@
1
- /**
2
- * Shared authentication-related timeouts.
3
- */
4
- export declare const LOGIN_TIMEOUT_MS = 300000;
@@ -1,4 +0,0 @@
1
- /**
2
- * Shared authentication-related timeouts.
3
- */
4
- export const LOGIN_TIMEOUT_MS = 300_000; // 5 minutes
@@ -1,49 +0,0 @@
1
- import type { BrowserContext } from "playwright";
2
- import type { SupportedService } from "./supported-service.js";
3
- /**
4
- * Configuration for browser authentication manager
5
- */
6
- type BrowserAuthConfig = {
7
- readonly dataDir?: string;
8
- readonly headless?: boolean;
9
- };
10
- /**
11
- * Manages browser contexts for persistent authentication across services
12
- */
13
- export declare class BrowserAuthManager {
14
- private readonly dataDir;
15
- private readonly headless;
16
- private browser;
17
- private browserPromise;
18
- constructor(config?: BrowserAuthConfig);
19
- /**
20
- * Get the storage state file path for a service
21
- */
22
- private getStorageStatePath;
23
- /**
24
- * Check if a service has saved authentication
25
- */
26
- hasAuth(service: SupportedService): boolean;
27
- /**
28
- * Ensure a Chromium browser instance is available
29
- */
30
- private ensureBrowser;
31
- private launchAndStoreBrowser;
32
- /**
33
- * Set up authentication for a service by launching a browser for the user to log in
34
- */
35
- setupAuth(service: SupportedService): Promise<void>;
36
- /**
37
- * Get a browser context with saved authentication for a service
38
- */
39
- getAuthContext(service: SupportedService): Promise<BrowserContext>;
40
- /**
41
- * Make an authenticated request to a URL using the browser context
42
- */
43
- makeAuthenticatedRequest(service: SupportedService, url: string): Promise<string>;
44
- /**
45
- * Close the browser and clean up resources
46
- */
47
- close(): Promise<void>;
48
- }
49
- export {};
@@ -1,113 +0,0 @@
1
- import { existsSync } from "node:fs";
2
- import { getServiceAuthConfig } from "./service-auth-configs.js";
3
- import { launchChromium } from "./launch-chromium.js";
4
- import { requestService } from "./request-service.js";
5
- import { doSetupAuth } from "./do-setup-auth.js";
6
- import { getStorageStatePathFor } from "./auth-storage-path.js";
7
- import { createAuthContext, loadStoredUserAgent, } from "./create-auth-context.js";
8
- import { getBrowserContextsDirectory, ensureSecureDirectory, } from "./app-paths.js";
9
- import { persistStorageState } from "./persist-storage-state.js";
10
- /**
11
- * Manages browser contexts for persistent authentication across services
12
- */
13
- export class BrowserAuthManager {
14
- dataDir;
15
- headless;
16
- browser = undefined;
17
- browserPromise = undefined;
18
- constructor(config = {}) {
19
- this.dataDir = config.dataDir || getBrowserContextsDirectory();
20
- // Default to headless for non-interactive usage flows; auth setup passes headless: false
21
- this.headless = config.headless ?? true;
22
- }
23
- /**
24
- * Get the storage state file path for a service
25
- */
26
- getStorageStatePath(service) {
27
- return getStorageStatePathFor(this.dataDir, service);
28
- }
29
- /**
30
- * Check if a service has saved authentication
31
- */
32
- hasAuth(service) {
33
- return existsSync(this.getStorageStatePath(service));
34
- }
35
- /**
36
- * Ensure a Chromium browser instance is available
37
- */
38
- async ensureBrowser() {
39
- if (!this.browserPromise) {
40
- this.browserPromise = this.launchAndStoreBrowser();
41
- }
42
- return this.browserPromise;
43
- }
44
- async launchAndStoreBrowser() {
45
- try {
46
- const browser = await launchChromium(this.headless);
47
- this.browser = browser;
48
- return browser;
49
- }
50
- catch (error) {
51
- // Allow retries on subsequent calls if the launch fails
52
- this.browserPromise = undefined;
53
- throw error;
54
- }
55
- }
56
- /**
57
- * Set up authentication for a service by launching a browser for the user to log in
58
- */
59
- async setupAuth(service) {
60
- const config = getServiceAuthConfig(service);
61
- await ensureSecureDirectory(this.dataDir);
62
- const browser = await this.ensureBrowser();
63
- const storagePath = this.getStorageStatePath(service);
64
- // Load existing storage state if available - this gives the browser a chance
65
- // to refresh expired cookies/tokens during the login flow
66
- const storageState = existsSync(storagePath) ? storagePath : undefined;
67
- const userAgent = await loadStoredUserAgent(this.dataDir, service);
68
- let context;
69
- try {
70
- context = await browser.newContext({ storageState, userAgent });
71
- }
72
- catch {
73
- // Corrupted storage state - fall back to fresh context
74
- context = await browser.newContext({ userAgent });
75
- }
76
- try {
77
- await doSetupAuth(service, context, this.getStorageStatePath(service), config.instructions);
78
- }
79
- finally {
80
- await context.close();
81
- }
82
- }
83
- /**
84
- * Get a browser context with saved authentication for a service
85
- */
86
- async getAuthContext(service) {
87
- const browser = await this.ensureBrowser();
88
- return createAuthContext(browser, this.dataDir, service);
89
- }
90
- /**
91
- * Make an authenticated request to a URL using the browser context
92
- */
93
- async makeAuthenticatedRequest(service, url) {
94
- const context = await this.getAuthContext(service);
95
- try {
96
- return await requestService(service, url, () => Promise.resolve(context));
97
- }
98
- finally {
99
- await persistStorageState(context, this.getStorageStatePath(service));
100
- await context.close();
101
- }
102
- }
103
- /**
104
- * Close the browser and clean up resources
105
- */
106
- async close() {
107
- if (this.browser) {
108
- await this.browser.close();
109
- this.browser = undefined;
110
- this.browserPromise = undefined;
111
- }
112
- }
113
- }
@@ -1,8 +0,0 @@
1
- import type { Browser, BrowserContext } from "playwright";
2
- import type { SupportedService } from "./supported-service.js";
3
- /**
4
- * Load the stored userAgent from the auth meta file for a service.
5
- * Returns undefined if meta file doesn't exist or is invalid.
6
- */
7
- export declare function loadStoredUserAgent(dataDirectory: string, service: SupportedService): Promise<string | undefined>;
8
- export declare function createAuthContext(browser: Browser, dataDirectory: string, service: SupportedService): Promise<BrowserContext>;
@@ -1,35 +0,0 @@
1
- import { existsSync } from "node:fs";
2
- import { readFile } from "node:fs/promises";
3
- import { getAuthMetaPathFor, getStorageStatePathFor, } from "./auth-storage-path.js";
4
- /**
5
- * Load the stored userAgent from the auth meta file for a service.
6
- * Returns undefined if meta file doesn't exist or is invalid.
7
- */
8
- export async function loadStoredUserAgent(dataDirectory, service) {
9
- try {
10
- const metaPath = getAuthMetaPathFor(dataDirectory, service);
11
- const metaRaw = await readFile(metaPath, "utf8");
12
- const meta = JSON.parse(metaRaw);
13
- // Validate the parsed structure at runtime
14
- if (meta &&
15
- typeof meta === "object" &&
16
- "userAgent" in meta &&
17
- typeof meta.userAgent === "string") {
18
- return meta.userAgent;
19
- }
20
- return undefined;
21
- }
22
- catch {
23
- // Meta file missing, unreadable, or contains invalid JSON
24
- return undefined;
25
- }
26
- }
27
- export async function createAuthContext(browser, dataDirectory, service) {
28
- const storageStatePath = getStorageStatePathFor(dataDirectory, service);
29
- if (!existsSync(storageStatePath)) {
30
- throw new Error(`No saved authentication for ${service}. ` +
31
- `Run 'axusage --auth-setup ${service} --interactive' first.`);
32
- }
33
- const userAgent = await loadStoredUserAgent(dataDirectory, service);
34
- return browser.newContext({ storageState: storageStatePath, userAgent });
35
- }
@@ -1,3 +0,0 @@
1
- import type { BrowserContext } from "playwright";
2
- import type { SupportedService } from "./supported-service.js";
3
- export declare function doSetupAuth(service: SupportedService, context: BrowserContext, storagePath: string, instructions: string): Promise<void>;
@@ -1,19 +0,0 @@
1
- import { setupAuthInContext } from "./setup-auth-flow.js";
2
- import path from "node:path";
3
- import { getAuthMetaPathFor } from "./auth-storage-path.js";
4
- import { writeAtomicJson } from "../utils/write-atomic-json.js";
5
- export async function doSetupAuth(service, context, storagePath, instructions) {
6
- console.error(`\n${instructions}`);
7
- console.error("Waiting for login to complete (or press Enter to continue)\n");
8
- const userAgent = await setupAuthInContext(service, context, storagePath);
9
- try {
10
- if (userAgent) {
11
- const metaPath = getAuthMetaPathFor(path.dirname(storagePath), service);
12
- await writeAtomicJson(metaPath, { userAgent }, 0o600);
13
- }
14
- }
15
- catch {
16
- // ignore errors when writing meta; not critical
17
- }
18
- console.error(`\n✓ Authentication saved for ${service}. You can now close the browser.`);
19
- }
@@ -1,5 +0,0 @@
1
- import type { BrowserContext } from "playwright";
2
- /**
3
- * Fetch JSON using the page's fetch API so cookies/session are included without navigation.
4
- */
5
- export declare function fetchJsonWithContext(context: BrowserContext, url: string): Promise<string>;
@@ -1,37 +0,0 @@
1
- /**
2
- * Fetch JSON using the page's fetch API so cookies/session are included without navigation.
3
- */
4
- export async function fetchJsonWithContext(context, url) {
5
- const page = await context.newPage();
6
- try {
7
- const origin = new URL(url).origin;
8
- await page.goto(origin + "/", { waitUntil: "domcontentloaded" });
9
- const result = await page.evaluate(async (targetUrl) => {
10
- const response = await fetch(targetUrl, {
11
- credentials: "include",
12
- headers: {
13
- Accept: "application/json, text/plain, */*",
14
- "X-Requested-With": "XMLHttpRequest",
15
- },
16
- });
17
- const text = await response.text();
18
- return {
19
- ok: response.ok,
20
- status: response.status,
21
- statusText: response.statusText,
22
- contentType: response.headers.get("content-type") || "",
23
- text,
24
- };
25
- }, url);
26
- if (!result.ok) {
27
- throw new Error(`Request failed: ${String(result.status)} ${result.statusText}`);
28
- }
29
- if (!result.contentType.toLowerCase().startsWith("application/json")) {
30
- throw new Error(`Expected JSON response, got ${result.contentType}`);
31
- }
32
- return result.text;
33
- }
34
- finally {
35
- await page.close();
36
- }
37
- }
@@ -1,6 +0,0 @@
1
- import type { Browser } from "playwright";
2
- /**
3
- * Launch Chromium with automation indicators disabled to reduce Cloudflare bot detection
4
- * during the authentication flow.
5
- */
6
- export declare function launchChromium(headless: boolean): Promise<Browser>;
@@ -1,20 +0,0 @@
1
- import { chromium } from "playwright";
2
- /**
3
- * Launch Chromium with automation indicators disabled to reduce Cloudflare bot detection
4
- * during the authentication flow.
5
- */
6
- export async function launchChromium(headless) {
7
- try {
8
- return await chromium.launch({
9
- headless,
10
- args: ["--disable-blink-features=AutomationControlled"],
11
- });
12
- }
13
- catch (error) {
14
- const message = error instanceof Error ? error.message : String(error);
15
- if (/Executable doesn't exist|playwright\s+install/iu.test(message)) {
16
- throw new Error("Playwright browsers are not installed. This is usually handled automatically by the postinstall script in package.json. Please try reinstalling the package or check if the postinstall script ran successfully. If the problem persists, you can manually run `pnpm exec playwright install chromium` or `npx playwright install chromium`, then retry.");
17
- }
18
- throw error;
19
- }
20
- }
@@ -1,6 +0,0 @@
1
- import type { BrowserContext } from "playwright";
2
- /**
3
- * Persist context storage state to disk with secure permissions (0o600).
4
- * Errors are logged as warnings to avoid blocking the main operation.
5
- */
6
- export declare function persistStorageState(context: BrowserContext, storagePath: string): Promise<void>;
@@ -1,16 +0,0 @@
1
- import { writeAtomicJson } from "../utils/write-atomic-json.js";
2
- import { chalk } from "../utils/color.js";
3
- /**
4
- * Persist context storage state to disk with secure permissions (0o600).
5
- * Errors are logged as warnings to avoid blocking the main operation.
6
- */
7
- export async function persistStorageState(context, storagePath) {
8
- try {
9
- const state = await context.storageState();
10
- await writeAtomicJson(storagePath, state, 0o600);
11
- }
12
- catch (error) {
13
- const details = error instanceof Error ? error.message : String(error);
14
- console.error(chalk.yellow(`Warning: Failed to persist auth state to ${storagePath} (${details}).`));
15
- }
16
- }
@@ -1,3 +0,0 @@
1
- import type { BrowserContext } from "playwright";
2
- import type { SupportedService } from "./supported-service.js";
3
- export declare function requestService(service: SupportedService, url: string, getContext: () => Promise<BrowserContext>): Promise<string>;
@@ -1,4 +0,0 @@
1
- import { fetchJsonWithContext } from "./fetch-json-with-context.js";
2
- export async function requestService(service, url, getContext) {
3
- return await fetchJsonWithContext(await getContext(), url);
4
- }
@@ -1,15 +0,0 @@
1
- import type { SupportedService } from "./supported-service.js";
2
- import type { BrowserContext } from "playwright";
3
- /**
4
- * Service-specific configuration for authentication
5
- */
6
- type ServiceAuthConfig = {
7
- readonly url: string;
8
- readonly waitForSelector?: string;
9
- readonly waitForSelectors?: readonly string[];
10
- readonly verifyUrl?: string;
11
- readonly verifyFunction?: (context: BrowserContext, url: string) => Promise<boolean>;
12
- readonly instructions: string;
13
- };
14
- export declare function getServiceAuthConfig(service: SupportedService): ServiceAuthConfig;
15
- export {};
@@ -1,26 +0,0 @@
1
- const SERVICE_AUTH_CONFIGS = {
2
- // Claude uses CLI-based auth via Claude Code credentials
3
- claude: {
4
- url: "",
5
- instructions: "Claude uses Claude Code authentication. Run 'claude' in your terminal to authenticate.",
6
- },
7
- // ChatGPT uses CLI-based auth via Codex credentials
8
- chatgpt: {
9
- url: "",
10
- instructions: "ChatGPT uses Codex CLI authentication. Run 'codex' in your terminal to authenticate.",
11
- },
12
- "github-copilot": {
13
- url: "https://github.com/login",
14
- waitForSelector: 'img[alt*="@"]',
15
- verifyUrl: "https://github.com/github-copilot/chat/entitlement",
16
- instructions: "Please log in to your GitHub account in the browser window.",
17
- },
18
- // Gemini uses CLI-based auth, not browser auth. This entry exists only to satisfy the Record type.
19
- gemini: {
20
- url: "",
21
- instructions: "Gemini uses CLI-based authentication. Run 'gemini' in your terminal.",
22
- },
23
- };
24
- export function getServiceAuthConfig(service) {
25
- return SERVICE_AUTH_CONFIGS[service];
26
- }
@@ -1,3 +0,0 @@
1
- import type { BrowserContext } from "playwright";
2
- import type { SupportedService } from "./supported-service.js";
3
- export declare function setupAuthInContext(service: SupportedService, context: BrowserContext, storagePath: string): Promise<string | undefined>;