axusage 3.0.0 → 3.2.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 (84) 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 +18 -38
  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 +12 -12
  22. package/dist/config/credential-sources.js +15 -2
  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/supported-service.d.ts +6 -2
  28. package/dist/services/supported-service.js +2 -6
  29. package/dist/types/{chatgpt.d.ts → codex.d.ts} +4 -4
  30. package/dist/types/{chatgpt.js → codex.js} +6 -6
  31. package/dist/types/copilot.d.ts +14 -0
  32. package/dist/types/copilot.js +21 -0
  33. package/dist/utils/check-cli-dependency.d.ts +2 -4
  34. package/dist/utils/check-cli-dependency.js +7 -4
  35. package/dist/utils/copilot-gh-token.d.ts +1 -0
  36. package/dist/utils/copilot-gh-token.js +38 -0
  37. package/dist/utils/validate-root-options.d.ts +0 -3
  38. package/dist/utils/validate-root-options.js +2 -6
  39. package/package.json +15 -19
  40. package/dist/adapters/github-copilot.d.ts +0 -6
  41. package/dist/adapters/github-copilot.js +0 -57
  42. package/dist/adapters/parse-github-copilot-usage.d.ts +0 -23
  43. package/dist/adapters/parse-github-copilot-usage.js +0 -78
  44. package/dist/commands/auth-clear-command.d.ts +0 -7
  45. package/dist/commands/auth-clear-command.js +0 -84
  46. package/dist/commands/fetch-service-usage-with-reauth.d.ts +0 -7
  47. package/dist/commands/fetch-service-usage-with-reauth.js +0 -45
  48. package/dist/services/app-paths.d.ts +0 -9
  49. package/dist/services/app-paths.js +0 -39
  50. package/dist/services/auth-storage-path.d.ts +0 -3
  51. package/dist/services/auth-storage-path.js +0 -7
  52. package/dist/services/auth-timeouts.d.ts +0 -4
  53. package/dist/services/auth-timeouts.js +0 -4
  54. package/dist/services/browser-auth-manager.d.ts +0 -49
  55. package/dist/services/browser-auth-manager.js +0 -113
  56. package/dist/services/create-auth-context.d.ts +0 -8
  57. package/dist/services/create-auth-context.js +0 -35
  58. package/dist/services/do-setup-auth.d.ts +0 -3
  59. package/dist/services/do-setup-auth.js +0 -19
  60. package/dist/services/fetch-json-with-context.d.ts +0 -5
  61. package/dist/services/fetch-json-with-context.js +0 -37
  62. package/dist/services/launch-chromium.d.ts +0 -6
  63. package/dist/services/launch-chromium.js +0 -20
  64. package/dist/services/persist-storage-state.d.ts +0 -6
  65. package/dist/services/persist-storage-state.js +0 -16
  66. package/dist/services/request-service.d.ts +0 -3
  67. package/dist/services/request-service.js +0 -4
  68. package/dist/services/service-auth-configs.d.ts +0 -15
  69. package/dist/services/service-auth-configs.js +0 -26
  70. package/dist/services/setup-auth-flow.d.ts +0 -3
  71. package/dist/services/setup-auth-flow.js +0 -67
  72. package/dist/services/shared-browser-auth-manager.d.ts +0 -4
  73. package/dist/services/shared-browser-auth-manager.js +0 -80
  74. package/dist/services/verify-session.d.ts +0 -2
  75. package/dist/services/verify-session.js +0 -25
  76. package/dist/services/wait-for-login.d.ts +0 -6
  77. package/dist/services/wait-for-login.js +0 -115
  78. package/dist/types/github-copilot.d.ts +0 -21
  79. package/dist/types/github-copilot.js +0 -27
  80. package/dist/utils/resolve-prompt-capability.d.ts +0 -1
  81. package/dist/utils/resolve-prompt-capability.js +0 -3
  82. package/dist/utils/write-atomic-json.d.ts +0 -1
  83. package/dist/utils/write-atomic-json.js +0 -56
  84. /package/dist/adapters/{parse-chatgpt-usage.js → parse-codex-usage.js} +0 -0
@@ -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>;
@@ -1,67 +0,0 @@
1
- import { getServiceAuthConfig } from "./service-auth-configs.js";
2
- import { waitForLogin } from "./wait-for-login.js";
3
- import { verifySessionByFetching } from "./verify-session.js";
4
- import { writeAtomicJson } from "../utils/write-atomic-json.js";
5
- function describeLoginOutcome(outcome) {
6
- switch (outcome) {
7
- case "manual": {
8
- return "after manual continuation";
9
- }
10
- case "timeout": {
11
- return "after login timeout";
12
- }
13
- case "closed": {
14
- return "after the browser window closed";
15
- }
16
- case "aborted": {
17
- return "after prompt cancellation";
18
- }
19
- case "selector": {
20
- return "after detecting a login signal";
21
- }
22
- case "skipped": {
23
- return "without waiting for a login signal";
24
- }
25
- }
26
- }
27
- export async function setupAuthInContext(service, context, storagePath) {
28
- const page = await context.newPage();
29
- try {
30
- const config = getServiceAuthConfig(service);
31
- await page.goto(config.url);
32
- const selectors = config.waitForSelectors ??
33
- (config.waitForSelector ? [config.waitForSelector] : []);
34
- const loginOutcome = await waitForLoginForService(page, selectors);
35
- const outcomeLabel = describeLoginOutcome(loginOutcome);
36
- if (loginOutcome === "aborted") {
37
- throw new Error("Authentication was canceled. Authentication was not saved.");
38
- }
39
- if (config.verifyUrl) {
40
- const ok = config.verifyFunction
41
- ? await config.verifyFunction(context, config.verifyUrl)
42
- : await verifySessionByFetching(context, config.verifyUrl);
43
- if (!ok) {
44
- throw new Error(`Unable to verify session via ${config.verifyUrl} ${outcomeLabel}. Authentication was not saved. Ensure login completed successfully and retry.`);
45
- }
46
- }
47
- else if (selectors.length > 0 && loginOutcome !== "selector") {
48
- // Without a verification URL, we only persist when a login selector confirms success.
49
- throw new Error(`Login was not confirmed ${outcomeLabel}. Authentication was not saved.`);
50
- }
51
- // Capture user agent for future headless contexts
52
- const userAgent = await page.evaluate(() => navigator.userAgent);
53
- const state = await context.storageState();
54
- await writeAtomicJson(storagePath, state, 0o600);
55
- return userAgent;
56
- }
57
- finally {
58
- await page.close();
59
- }
60
- }
61
- async function waitForLoginForService(page, selectors) {
62
- if (selectors.length > 0) {
63
- return waitForLogin(page, selectors);
64
- }
65
- // When no selectors are configured, skip waiting and rely on verification if available.
66
- return "skipped";
67
- }
@@ -1,4 +0,0 @@
1
- import { BrowserAuthManager } from "./browser-auth-manager.js";
2
- export declare function acquireAuthManager(): BrowserAuthManager;
3
- export declare function releaseAuthManager(): Promise<void>;
4
- export declare function installAuthManagerCleanup(): void;