axauth 2.0.0 → 3.0.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 (50) hide show
  1. package/README.md +10 -4
  2. package/dist/auth/adapter.d.ts +60 -20
  3. package/dist/auth/agents/claude-install.d.ts +11 -0
  4. package/dist/auth/agents/claude-install.js +80 -0
  5. package/dist/auth/agents/claude-storage.d.ts +13 -5
  6. package/dist/auth/agents/claude-storage.js +11 -16
  7. package/dist/auth/agents/claude.js +14 -89
  8. package/dist/auth/agents/codex-auth-check.d.ts +6 -5
  9. package/dist/auth/agents/codex-auth-check.js +34 -20
  10. package/dist/auth/agents/codex-install.js +1 -2
  11. package/dist/auth/agents/codex-storage.d.ts +0 -1
  12. package/dist/auth/agents/codex-storage.js +4 -5
  13. package/dist/auth/agents/codex.js +4 -4
  14. package/dist/auth/agents/copilot-install.js +2 -3
  15. package/dist/auth/agents/copilot.js +11 -6
  16. package/dist/auth/agents/gemini-install.d.ts +1 -1
  17. package/dist/auth/agents/gemini-install.js +3 -3
  18. package/dist/auth/agents/gemini.js +19 -17
  19. package/dist/auth/agents/opencode-credentials.d.ts +25 -37
  20. package/dist/auth/agents/opencode-credentials.js +48 -122
  21. package/dist/auth/agents/opencode-remove-provider.d.ts +25 -0
  22. package/dist/auth/agents/opencode-remove-provider.js +86 -0
  23. package/dist/auth/agents/opencode-storage.js +18 -22
  24. package/dist/auth/agents/opencode.d.ts +1 -1
  25. package/dist/auth/agents/opencode.js +59 -41
  26. package/dist/auth/build-refreshed-credentials.d.ts +6 -4
  27. package/dist/auth/build-refreshed-credentials.js +34 -19
  28. package/dist/auth/extract-creds-from-directory.d.ts +7 -3
  29. package/dist/auth/extract-creds-from-directory.js +4 -1
  30. package/dist/auth/is-token-expired.d.ts +52 -2
  31. package/dist/auth/is-token-expired.js +71 -5
  32. package/dist/auth/refresh-credentials.d.ts +38 -12
  33. package/dist/auth/refresh-credentials.js +49 -18
  34. package/dist/auth/registry.d.ts +18 -15
  35. package/dist/auth/registry.js +35 -18
  36. package/dist/auth/resolve-refresh-credentials.d.ts +11 -8
  37. package/dist/auth/resolve-refresh-credentials.js +12 -48
  38. package/dist/auth/types.d.ts +3 -35
  39. package/dist/auth/types.js +2 -47
  40. package/dist/auth/wait-for-refreshed-credentials.d.ts +5 -1
  41. package/dist/auth/wait-for-refreshed-credentials.js +7 -4
  42. package/dist/commands/auth-export.js +24 -46
  43. package/dist/commands/auth.js +13 -3
  44. package/dist/commands/copy-to-clipboard.d.ts +6 -0
  45. package/dist/commands/copy-to-clipboard.js +48 -0
  46. package/dist/commands/vault.js +16 -15
  47. package/dist/index.d.ts +3 -3
  48. package/dist/index.js +4 -4
  49. package/dist/vault/vault-client.js +21 -2
  50. package/package.json +11 -11
package/README.md CHANGED
@@ -38,6 +38,7 @@ axauth list --json
38
38
 
39
39
  # Get access token for an agent (outputs raw token for piping)
40
40
  axauth token --agent claude
41
+ axauth token --agent opencode --provider anthropic # OpenCode requires --provider
41
42
 
42
43
  # Export credentials to encrypted file
43
44
  axauth export --agent claude --output creds.json
@@ -87,7 +88,7 @@ import {
87
88
  checkAuth, // Check single agent auth status
88
89
  checkAllAuth, // Check all agents' auth status
89
90
  getAgentAccessToken, // Get access token for an agent
90
- extractRawCredentials, // Extract full credentials for export
91
+ findCredentials, // Find credentials from storage or environment
91
92
  installCredentials, // Install credentials to storage
92
93
  removeCredentials, // Remove credentials from storage
93
94
 
@@ -125,11 +126,16 @@ if (status.authenticated) {
125
126
  }
126
127
 
127
128
  // Get access token for API calls
128
- const token = getAgentAccessToken("claude");
129
+ const token = await getAgentAccessToken("claude");
129
130
  if (token) {
130
131
  // Use token for API calls
131
132
  }
132
133
 
134
+ // OpenCode requires explicit provider (multi-provider agent)
135
+ const openCodeToken = await getAgentAccessToken("opencode", {
136
+ provider: "anthropic",
137
+ });
138
+
133
139
  // Check adapter capabilities
134
140
  const caps = getCapabilities("gemini");
135
141
  if (!caps.keychain) {
@@ -146,9 +152,9 @@ import { getAdapter } from "axauth";
146
152
 
147
153
  const adapter = getAdapter("claude");
148
154
 
149
- // All adapters have the same interface
155
+ // All adapters have the same interface (OpenCode requires { provider } option)
150
156
  const status = adapter.checkAuth();
151
- const creds = adapter.extractRawCredentials();
157
+ const creds = adapter.findStoredCredentials(); // OpenCode: findStoredCredentials({ provider: "anthropic" })
152
158
  const token = adapter.getAccessToken(creds);
153
159
  const envVars = adapter.credentialsToEnvironment(creds);
154
160
 
@@ -13,6 +13,11 @@ interface OperationResult {
13
13
  ok: boolean;
14
14
  message: string;
15
15
  }
16
+ /** Result of finding stored credentials */
17
+ interface StoredCredentials {
18
+ credentials: Credentials;
19
+ source: "keychain" | "file";
20
+ }
16
21
  /**
17
22
  * Options for credential installation.
18
23
  *
@@ -22,7 +27,7 @@ interface OperationResult {
22
27
  * When no directories are provided, `storage` controls where credentials go:
23
28
  * - `"keychain"`: Store in macOS Keychain (if supported)
24
29
  * - `"file"`: Store in agent's default file location
25
- * - `undefined`: Use the `_source` marker in credentials, or default to file
30
+ * - `undefined`: Default to file storage
26
31
  *
27
32
  * **Agents without separation** (Claude, Codex, Gemini, Copilot):
28
33
  * - Config and data are stored in the same directory
@@ -36,7 +41,11 @@ interface OperationResult {
36
41
  * - If only `dataDir` provided, config uses default location
37
42
  */
38
43
  interface InstallOptions {
39
- /** Storage type for default location (ignored if configDir/dataDir is set) */
44
+ /**
45
+ * Storage type for default location.
46
+ * Required when re-installing refreshed credentials to preserve original location.
47
+ * Ignored if configDir/dataDir is set.
48
+ */
40
49
  storage?: StorageType;
41
50
  /** Custom config directory for settings/preferences */
42
51
  configDir?: string;
@@ -65,7 +74,21 @@ interface RemoveOptions {
65
74
  dataDir?: string;
66
75
  }
67
76
  /**
68
- * Options for extracting credentials from a custom directory.
77
+ * Options for finding stored credentials.
78
+ *
79
+ * **Multi-provider agents** (OpenCode):
80
+ * - `provider` is required to specify which provider's credentials to return
81
+ * - Throws an error if provider is not specified
82
+ *
83
+ * **Single-provider agents** (Claude, Codex, Gemini, Copilot):
84
+ * - `provider` is ignored
85
+ */
86
+ interface FindStoredCredentialsOptions {
87
+ /** Provider ID for multi-provider agents (required for OpenCode) */
88
+ provider?: string;
89
+ }
90
+ /**
91
+ * Options for loading credentials from a custom directory.
69
92
  *
70
93
  * **Agents without separation** (Claude, Codex, Gemini, Copilot):
71
94
  * - `configDir` and `dataDir` are interchangeable
@@ -73,13 +96,16 @@ interface RemoveOptions {
73
96
  *
74
97
  * **Agents with separation** (OpenCode):
75
98
  * - `dataDir` must be provided to specify where credentials are stored
76
- * - If only `configDir` is provided, returns undefined (use extractRawCredentials() for default location)
99
+ * - If only `configDir` is provided, returns undefined (use findStoredCredentials() for default location)
100
+ * - `provider` filters to a specific provider's credentials
77
101
  */
78
102
  interface ExtractOptions {
79
103
  /** Custom config directory for settings/preferences */
80
104
  configDir?: string;
81
105
  /** Custom data directory for credentials */
82
106
  dataDir?: string;
107
+ /** Provider ID for multi-provider agents (OpenCode) - filters to specific provider */
108
+ provider?: string;
83
109
  }
84
110
  /**
85
111
  * Options for token extraction.
@@ -94,6 +120,8 @@ interface TokenOptions {
94
120
  skipRefresh?: boolean;
95
121
  /** Timeout for refresh operation in ms (default: 30000) */
96
122
  refreshTimeout?: number;
123
+ /** Storage location for persisting refreshed credentials (default: "file") */
124
+ storage?: "keychain" | "file";
97
125
  }
98
126
  /** Capabilities that an adapter supports */
99
127
  interface AdapterCapabilities {
@@ -116,9 +144,9 @@ interface AdapterCapabilities {
116
144
  *
117
145
  * When resolving credentials, sources are checked in this order:
118
146
  *
119
- * 1. **Environment variables** (via `extractFromEnvironment`)
147
+ * 1. **Environment variables** (via `getEnvironmentCredentials`)
120
148
  * 2. **Vault** (external, via axvault server when configured)
121
- * 3. **Local storage** (keychain/file via `extractRawCredentials`)
149
+ * 3. **Local storage** (keychain/file via `findStoredCredentials`)
122
150
  *
123
151
  * Environment variables always take precedence to allow easy overrides
124
152
  * in CI/CD and development. Vault provides centralized credential
@@ -137,7 +165,7 @@ interface AuthAdapter {
137
165
  */
138
166
  checkAuth(): AuthStatus;
139
167
  /**
140
- * Extract credentials from environment variables only.
168
+ * Get credentials from environment variables only.
141
169
  *
142
170
  * This is called before checking vault or local storage to ensure
143
171
  * environment variables have highest priority. Returns undefined if
@@ -145,22 +173,33 @@ interface AuthAdapter {
145
173
  *
146
174
  * @example
147
175
  * // For Claude, checks CLAUDE_CODE_OAUTH_TOKEN and ANTHROPIC_API_KEY
148
- * const envCreds = adapter.extractFromEnvironment?.();
176
+ * const envCreds = adapter.getEnvironmentCredentials?.();
149
177
  * if (envCreds) return envCreds; // Env vars win over vault
150
178
  */
151
- extractFromEnvironment?(): Credentials | undefined;
179
+ getEnvironmentCredentials?(): Credentials | undefined;
152
180
  /**
153
- * Extract raw credentials for export.
181
+ * Find stored credentials and their source.
182
+ *
183
+ * Returns the full credential data from the first available storage location
184
+ * (keychain or file), along with the source it was found in. Returns undefined
185
+ * if not authenticated. Does not check environment variables.
186
+ *
187
+ * The returned `source` should be passed to `installCredentials()` when
188
+ * re-installing refreshed credentials to preserve the original storage location.
189
+ *
190
+ * **Multi-provider agents** (OpenCode):
191
+ * - `options.provider` is required - throws if not specified
192
+ * - Returns credentials for the specified provider only
154
193
  *
155
- * Returns the full credential data from the first available source,
156
- * suitable for encrypted export. Returns undefined if not authenticated.
194
+ * **Single-provider agents** (Claude, Codex, Gemini, Copilot):
195
+ * - `options` is ignored
157
196
  *
158
197
  * Note: The `data` field format is agent-specific and not standardized.
159
198
  * Use {@link getAccessToken} to extract the token in a uniform way.
160
199
  */
161
- extractRawCredentials(): Credentials | undefined;
200
+ findStoredCredentials(options?: FindStoredCredentialsOptions): StoredCredentials | undefined;
162
201
  /**
163
- * Extract raw credentials from custom directories.
202
+ * Load credentials from a custom directory.
164
203
  *
165
204
  * Used by token refresh and CI/CD to read credentials from temp directories.
166
205
  * Returns undefined if no credentials found at the specified location.
@@ -168,15 +207,16 @@ interface AuthAdapter {
168
207
  * **Agents without separation**: Look in `configDir` or `dataDir` (interchangeable)
169
208
  * **Agents with separation** (OpenCode): Look in `dataDir` for credentials
170
209
  */
171
- extractRawCredentialsFromDirectory?(options: ExtractOptions): Credentials | undefined;
210
+ loadCredentialsFromDirectory?(options: ExtractOptions): Credentials | undefined;
172
211
  /**
173
212
  * Install credentials to storage.
174
213
  *
175
- * When `options.path` is provided, credentials are written as a file to that
176
- * path. Keychain storage is not available for custom paths.
214
+ * When `options.configDir`/`options.dataDir` is provided, credentials are
215
+ * written as a file to that directory. Keychain storage is not available for
216
+ * custom paths.
177
217
  *
178
- * When `options.path` is not provided, credentials are written to the default
179
- * location. The `storage` option or `_source` marker controls keychain vs file.
218
+ * When no directories are provided, credentials are written to the default
219
+ * location. The `storage` option controls keychain vs file (defaults to file).
180
220
  */
181
221
  installCredentials(creds: Credentials, options?: InstallOptions): OperationResult;
182
222
  /**
@@ -219,4 +259,4 @@ interface AuthAdapter {
219
259
  */
220
260
  getCredentialFilePath(directory: string): string;
221
261
  }
222
- export type { AdapterCapabilities, AuthAdapter, ExtractOptions, InstallOptions, OperationResult, RemoveOptions, TokenOptions, };
262
+ export type { AdapterCapabilities, AuthAdapter, ExtractOptions, FindStoredCredentialsOptions, InstallOptions, OperationResult, RemoveOptions, StoredCredentials, TokenOptions, };
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Claude Code credential installation and removal.
3
+ */
4
+ import type { InstallOptions, OperationResult, RemoveOptions } from "../adapter.js";
5
+ import type { Credentials } from "../types.js";
6
+ declare const CREDS_FILE_NAME = ".credentials.json";
7
+ /** Install credentials to storage */
8
+ declare function installCredentials(creds: Credentials, options?: InstallOptions): OperationResult;
9
+ /** Remove credentials from storage */
10
+ declare function removeCredentials(options?: RemoveOptions): OperationResult;
11
+ export { CREDS_FILE_NAME, installCredentials, removeCredentials };
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Claude Code credential installation and removal.
3
+ */
4
+ import path from "node:path";
5
+ import { isMacOS } from "../keychain.js";
6
+ import { resolveCustomDirectory } from "../validate-directories.js";
7
+ import { AGENT_ID, deleteFileCreds, deleteKeychainCreds, getDefaultCredsFilePath, saveFileCreds, saveKeychainCreds, } from "./claude-storage.js";
8
+ const CREDS_FILE_NAME = ".credentials.json";
9
+ /** Install credentials to storage */
10
+ function installCredentials(creds, options) {
11
+ const resolved = resolveCustomDirectory(AGENT_ID, options?.configDir, options?.dataDir);
12
+ if (!resolved.ok)
13
+ return resolved.error;
14
+ if (creds.type === "api-key") {
15
+ return {
16
+ ok: false,
17
+ message: "API key credentials cannot be installed (use ANTHROPIC_API_KEY env var)",
18
+ };
19
+ }
20
+ // Custom directory forces file storage (keychain only for default location)
21
+ if (resolved.customDir) {
22
+ const targetPath = path.join(resolved.customDir, CREDS_FILE_NAME);
23
+ if (saveFileCreds(creds.data, targetPath)) {
24
+ return { ok: true, message: `Installed credentials to ${targetPath}` };
25
+ }
26
+ return {
27
+ ok: false,
28
+ message: `Failed to install credentials to ${targetPath}`,
29
+ };
30
+ }
31
+ // Default location: use storage option or default to file
32
+ const targetStorage = options?.storage ?? "file";
33
+ if (targetStorage === "keychain") {
34
+ if (!isMacOS()) {
35
+ return {
36
+ ok: false,
37
+ message: "Keychain storage is only available on macOS",
38
+ };
39
+ }
40
+ if (saveKeychainCreds(creds.data)) {
41
+ return { ok: true, message: "Installed credentials to macOS Keychain" };
42
+ }
43
+ return { ok: false, message: "Failed to save to macOS Keychain" };
44
+ }
45
+ const defaultPath = getDefaultCredsFilePath();
46
+ if (saveFileCreds(creds.data, defaultPath)) {
47
+ return { ok: true, message: `Installed credentials to ${defaultPath}` };
48
+ }
49
+ return {
50
+ ok: false,
51
+ message: `Failed to install credentials to ${defaultPath}`,
52
+ };
53
+ }
54
+ /** Remove credentials from storage */
55
+ function removeCredentials(options) {
56
+ const resolved = resolveCustomDirectory(AGENT_ID, options?.configDir, options?.dataDir);
57
+ if (!resolved.ok)
58
+ return resolved.error;
59
+ // Custom directory: only remove that specific file (no keychain)
60
+ if (resolved.customDir) {
61
+ const targetPath = path.join(resolved.customDir, CREDS_FILE_NAME);
62
+ if (deleteFileCreds(targetPath)) {
63
+ return { ok: true, message: `Removed ${targetPath}` };
64
+ }
65
+ return { ok: true, message: "No credentials file found at specified path" };
66
+ }
67
+ // Default location: remove from both keychain and default file
68
+ const removedFrom = [];
69
+ if (deleteKeychainCreds()) {
70
+ removedFrom.push("macOS Keychain");
71
+ }
72
+ if (deleteFileCreds()) {
73
+ removedFrom.push(getDefaultCredsFilePath());
74
+ }
75
+ if (removedFrom.length === 0) {
76
+ return { ok: true, message: "No credentials found" };
77
+ }
78
+ return { ok: true, message: `Removed from ${removedFrom.join(" and ")}` };
79
+ }
80
+ export { CREDS_FILE_NAME, installCredentials, removeCredentials };
@@ -19,18 +19,26 @@ declare function checkAuth(): {
19
19
  details?: Record<string, unknown>;
20
20
  };
21
21
  /**
22
- * Extract credentials from environment variables only.
22
+ * Get credentials from environment variables only.
23
23
  *
24
24
  * This is called before checking vault or local storage to ensure
25
25
  * environment variables have highest priority.
26
26
  */
27
- declare function extractFromEnvironment(): {
27
+ declare function getEnvironmentCredentials(): {
28
28
  type: "oauth-credentials" | "oauth-token" | "api-key";
29
29
  data: Record<string, unknown>;
30
30
  } | undefined;
31
- /** Extract raw credentials from available sources */
32
- declare function extractRawCredentials(): {
31
+ /**
32
+ * Find credentials from local storage only (keychain + file).
33
+ *
34
+ * This skips environment variable checks and only looks at local storage.
35
+ * Used as fallback after vault fetch fails.
36
+ *
37
+ * Returns credentials and their source for round-tripping during refresh.
38
+ */
39
+ declare function findStoredCredentials(): {
33
40
  type: "oauth-credentials" | "oauth-token" | "api-key";
41
+ source: "keychain" | "file";
34
42
  data: Record<string, unknown>;
35
43
  } | undefined;
36
- export { AGENT_ID, checkAuth, deleteFileCreds, deleteKeychainCreds, extractFromEnvironment, extractRawCredentials, getDefaultCredsFilePath, saveFileCreds, saveKeychainCreds, };
44
+ export { AGENT_ID, checkAuth, deleteFileCreds, deleteKeychainCreds, findStoredCredentials, getDefaultCredsFilePath, getEnvironmentCredentials, saveFileCreds, saveKeychainCreds, };
@@ -82,12 +82,12 @@ function checkAuth() {
82
82
  return { authenticated: false };
83
83
  }
84
84
  /**
85
- * Extract credentials from environment variables only.
85
+ * Get credentials from environment variables only.
86
86
  *
87
87
  * This is called before checking vault or local storage to ensure
88
88
  * environment variables have highest priority.
89
89
  */
90
- function extractFromEnvironment() {
90
+ function getEnvironmentCredentials() {
91
91
  if (process.env.CLAUDE_CODE_OAUTH_TOKEN) {
92
92
  return {
93
93
  type: "oauth-token",
@@ -103,35 +103,30 @@ function extractFromEnvironment() {
103
103
  return undefined;
104
104
  }
105
105
  /**
106
- * Extract credentials from local storage only (keychain + file).
106
+ * Find credentials from local storage only (keychain + file).
107
107
  *
108
108
  * This skips environment variable checks and only looks at local storage.
109
109
  * Used as fallback after vault fetch fails.
110
+ *
111
+ * Returns credentials and their source for round-tripping during refresh.
110
112
  */
111
- function extractFromLocalStorage() {
113
+ function findStoredCredentials() {
112
114
  const keychainCreds = loadKeychainCreds();
113
115
  if (keychainCreds) {
114
116
  return {
115
117
  type: "oauth-credentials",
116
- data: { ...keychainCreds, _source: "keychain" },
118
+ source: "keychain",
119
+ data: keychainCreds,
117
120
  };
118
121
  }
119
122
  const fileCreds = loadFileCreds();
120
123
  if (fileCreds) {
121
124
  return {
122
125
  type: "oauth-credentials",
123
- data: { ...fileCreds, _source: "file" },
126
+ source: "file",
127
+ data: fileCreds,
124
128
  };
125
129
  }
126
130
  return undefined;
127
131
  }
128
- /** Extract raw credentials from available sources */
129
- function extractRawCredentials() {
130
- // Check env vars first
131
- const environmentCreds = extractFromEnvironment();
132
- if (environmentCreds)
133
- return environmentCreds;
134
- // Fall back to local storage
135
- return extractFromLocalStorage();
136
- }
137
- export { AGENT_ID, checkAuth, deleteFileCreds, deleteKeychainCreds, extractFromEnvironment, extractRawCredentials, getDefaultCredsFilePath, saveFileCreds, saveKeychainCreds, };
132
+ export { AGENT_ID, checkAuth, deleteFileCreds, deleteKeychainCreds, findStoredCredentials, getDefaultCredsFilePath, getEnvironmentCredentials, saveFileCreds, saveKeychainCreds, };
@@ -5,10 +5,8 @@
5
5
  */
6
6
  import path from "node:path";
7
7
  import { extractCredsFromDirectory } from "../extract-creds-from-directory.js";
8
- import { isMacOS } from "../keychain.js";
9
- import { resolveCustomDirectory } from "../validate-directories.js";
10
- import { AGENT_ID, checkAuth, deleteFileCreds, deleteKeychainCreds, extractFromEnvironment, extractRawCredentials, getDefaultCredsFilePath, saveFileCreds, saveKeychainCreds, } from "./claude-storage.js";
11
- const CREDS_FILE_NAME = ".credentials.json";
8
+ import { CREDS_FILE_NAME, installCredentials, removeCredentials, } from "./claude-install.js";
9
+ import { AGENT_ID, checkAuth, findStoredCredentials as findStoredCredentialsInternal, getEnvironmentCredentials as getEnvironmentCredentialsInternal, } from "./claude-storage.js";
12
10
  /** Claude Code authentication adapter */
13
11
  const claudeCodeAdapter = {
14
12
  agentId: AGENT_ID,
@@ -22,19 +20,22 @@ const claudeCodeAdapter = {
22
20
  const result = checkAuth();
23
21
  return { agentId: AGENT_ID, ...result };
24
22
  },
25
- extractFromEnvironment() {
26
- const result = extractFromEnvironment();
23
+ getEnvironmentCredentials() {
24
+ const result = getEnvironmentCredentialsInternal();
27
25
  if (!result)
28
26
  return undefined;
29
- return { agent: AGENT_ID, ...result };
27
+ return { agent: AGENT_ID, type: result.type, data: result.data };
30
28
  },
31
- extractRawCredentials() {
32
- const result = extractRawCredentials();
29
+ findStoredCredentials() {
30
+ const result = findStoredCredentialsInternal();
33
31
  if (!result)
34
32
  return undefined;
35
- return { agent: AGENT_ID, ...result };
33
+ return {
34
+ credentials: { agent: AGENT_ID, type: result.type, data: result.data },
35
+ source: result.source,
36
+ };
36
37
  },
37
- extractRawCredentialsFromDirectory(options) {
38
+ loadCredentialsFromDirectory(options) {
38
39
  // Claude doesn't separate config/data - use either directory
39
40
  const directory = options.dataDir ?? options.configDir;
40
41
  if (!directory)
@@ -47,84 +48,8 @@ const claudeCodeAdapter = {
47
48
  : undefined;
48
49
  });
49
50
  },
50
- installCredentials(creds, options) {
51
- // Resolve custom directory with validation
52
- const resolved = resolveCustomDirectory(AGENT_ID, options?.configDir, options?.dataDir);
53
- if (!resolved.ok)
54
- return resolved.error;
55
- if (creds.type === "api-key") {
56
- return {
57
- ok: false,
58
- message: "API key credentials cannot be installed (use ANTHROPIC_API_KEY env var)",
59
- };
60
- }
61
- const { _source, ...oauthData } = creds.data;
62
- // Custom directory forces file storage (keychain only for default location)
63
- if (resolved.customDir) {
64
- const targetPath = path.join(resolved.customDir, CREDS_FILE_NAME);
65
- if (saveFileCreds(oauthData, targetPath)) {
66
- return {
67
- ok: true,
68
- message: `Installed credentials to ${targetPath}`,
69
- };
70
- }
71
- return {
72
- ok: false,
73
- message: `Failed to install credentials to ${targetPath}`,
74
- };
75
- }
76
- // Default location: use storage option or _source marker
77
- const targetStorage = options?.storage ?? (_source === "keychain" ? "keychain" : "file");
78
- if (targetStorage === "keychain") {
79
- if (!isMacOS()) {
80
- return {
81
- ok: false,
82
- message: "Keychain storage is only available on macOS",
83
- };
84
- }
85
- if (saveKeychainCreds(oauthData)) {
86
- return { ok: true, message: "Installed credentials to macOS Keychain" };
87
- }
88
- return { ok: false, message: "Failed to save to macOS Keychain" };
89
- }
90
- const defaultPath = getDefaultCredsFilePath();
91
- if (saveFileCreds(oauthData, defaultPath)) {
92
- return { ok: true, message: `Installed credentials to ${defaultPath}` };
93
- }
94
- return {
95
- ok: false,
96
- message: `Failed to install credentials to ${defaultPath}`,
97
- };
98
- },
99
- removeCredentials(options) {
100
- // Resolve custom directory with validation
101
- const resolved = resolveCustomDirectory(AGENT_ID, options?.configDir, options?.dataDir);
102
- if (!resolved.ok)
103
- return resolved.error;
104
- // Custom directory: only remove that specific file (no keychain)
105
- if (resolved.customDir) {
106
- const targetPath = path.join(resolved.customDir, CREDS_FILE_NAME);
107
- if (deleteFileCreds(targetPath)) {
108
- return { ok: true, message: `Removed ${targetPath}` };
109
- }
110
- return {
111
- ok: true,
112
- message: "No credentials file found at specified path",
113
- };
114
- }
115
- // Default location: remove from both keychain and default file
116
- const removedFrom = [];
117
- if (deleteKeychainCreds()) {
118
- removedFrom.push("macOS Keychain");
119
- }
120
- if (deleteFileCreds()) {
121
- removedFrom.push(getDefaultCredsFilePath());
122
- }
123
- if (removedFrom.length === 0) {
124
- return { ok: true, message: "No credentials found" };
125
- }
126
- return { ok: true, message: `Removed from ${removedFrom.join(" and ")}` };
127
- },
51
+ installCredentials,
52
+ removeCredentials,
128
53
  getAccessToken(creds) {
129
54
  const data = creds.data;
130
55
  if ((creds.type === "oauth-credentials" || creds.type === "oauth-token") &&
@@ -1,11 +1,12 @@
1
1
  /**
2
2
  * Codex auth status checking and credential extraction.
3
3
  */
4
+ import type { StoredCredentials } from "../adapter.js";
4
5
  import type { AuthStatus, Credentials } from "../types.js";
5
6
  /** Check auth status across all sources */
6
7
  declare function checkAuth(): AuthStatus;
7
- /** Extract credentials from environment */
8
- declare function extractEnvironmentCredentials(): Credentials | undefined;
9
- /** Extract raw credentials from first available source */
10
- declare function extractRawCredentials(): Credentials | undefined;
11
- export { checkAuth, extractEnvironmentCredentials, extractRawCredentials };
8
+ /** Get credentials from environment variables */
9
+ declare function getEnvironmentCredentials(): Credentials | undefined;
10
+ /** Find stored credentials from keychain or file */
11
+ declare function findStoredCredentials(): StoredCredentials | undefined;
12
+ export { checkAuth, findStoredCredentials, getEnvironmentCredentials };
@@ -46,8 +46,8 @@ function checkAuth() {
46
46
  checkKeychainAuth() ??
47
47
  checkFileAuth() ?? { agentId: AGENT_ID, authenticated: false });
48
48
  }
49
- /** Extract credentials from environment */
50
- function extractEnvironmentCredentials() {
49
+ /** Get credentials from environment variables */
50
+ function getEnvironmentCredentials() {
51
51
  const environmentKey = getEnvironmentApiKey();
52
52
  if (environmentKey) {
53
53
  return {
@@ -58,44 +58,58 @@ function extractEnvironmentCredentials() {
58
58
  }
59
59
  return undefined;
60
60
  }
61
- /** Extract credentials from keychain */
61
+ /** Extract credentials from keychain (internal, returns source) */
62
62
  function extractKeychainCredentials() {
63
63
  const keychainAuth = loadKeychainCreds();
64
64
  if (keychainAuth?.OPENAI_API_KEY) {
65
65
  return {
66
- agent: AGENT_ID,
67
- type: "api-key",
68
- data: { apiKey: keychainAuth.OPENAI_API_KEY, _source: "keychain" },
66
+ credentials: {
67
+ agent: AGENT_ID,
68
+ type: "api-key",
69
+ data: { apiKey: keychainAuth.OPENAI_API_KEY },
70
+ },
71
+ source: "keychain",
69
72
  };
70
73
  }
71
74
  if (keychainAuth?.tokens) {
72
75
  return {
73
- agent: AGENT_ID,
74
- type: "oauth-credentials",
75
- data: { ...keychainAuth, _source: "keychain" },
76
+ credentials: {
77
+ agent: AGENT_ID,
78
+ type: "oauth-credentials",
79
+ data: keychainAuth,
80
+ },
81
+ source: "keychain",
76
82
  };
77
83
  }
78
84
  return undefined;
79
85
  }
80
- /** Extract credentials from file */
86
+ /** Extract credentials from file (internal, returns source) */
81
87
  function extractFileCredentials() {
82
88
  const fileAuth = loadFileCreds();
83
89
  if (fileAuth?.OPENAI_API_KEY) {
84
90
  return {
85
- agent: AGENT_ID,
86
- type: "api-key",
87
- data: { apiKey: fileAuth.OPENAI_API_KEY },
91
+ credentials: {
92
+ agent: AGENT_ID,
93
+ type: "api-key",
94
+ data: { apiKey: fileAuth.OPENAI_API_KEY },
95
+ },
96
+ source: "file",
88
97
  };
89
98
  }
90
99
  if (fileAuth?.tokens) {
91
- return { agent: AGENT_ID, type: "oauth-credentials", data: fileAuth };
100
+ return {
101
+ credentials: {
102
+ agent: AGENT_ID,
103
+ type: "oauth-credentials",
104
+ data: fileAuth,
105
+ },
106
+ source: "file",
107
+ };
92
108
  }
93
109
  return undefined;
94
110
  }
95
- /** Extract raw credentials from first available source */
96
- function extractRawCredentials() {
97
- return (extractEnvironmentCredentials() ??
98
- extractKeychainCredentials() ??
99
- extractFileCredentials());
111
+ /** Find stored credentials from keychain or file */
112
+ function findStoredCredentials() {
113
+ return extractKeychainCredentials() ?? extractFileCredentials();
100
114
  }
101
- export { checkAuth, extractEnvironmentCredentials, extractRawCredentials };
115
+ export { checkAuth, findStoredCredentials, getEnvironmentCredentials };
@@ -65,8 +65,7 @@ function installCodexCredentials(creds, options) {
65
65
  if (resolved.customDir) {
66
66
  return installToCustomDirectory(authContent, resolved.customDir);
67
67
  }
68
- const sourceMarker = creds.data._source;
69
- const targetStorage = options?.storage ?? (sourceMarker === "keychain" ? "keychain" : "file");
68
+ const targetStorage = options?.storage ?? "file";
70
69
  return installToDefaultLocation(authContent, targetStorage);
71
70
  }
72
71
  /** Remove Codex credentials */
@@ -34,7 +34,6 @@ declare function saveFileCreds(auth: CodexAuthJson, filePath?: string): boolean;
34
34
  declare function deleteFileCreds(filePath?: string): boolean;
35
35
  interface CredentialsData {
36
36
  apiKey?: string;
37
- _source?: unknown;
38
37
  tokens?: CodexAuthJson["tokens"];
39
38
  [key: string]: unknown;
40
39
  }