@humanlayer/agentlayer-provider-auth 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/auth.d.ts ADDED
@@ -0,0 +1,53 @@
1
+ export interface OAuthAuthInfo {
2
+ kind: 'oauth';
3
+ accessToken: string;
4
+ refreshToken?: string;
5
+ expiresAt?: number;
6
+ idToken?: string;
7
+ scope?: string;
8
+ tokenType?: string;
9
+ accountId?: string;
10
+ enterpriseUrl?: string;
11
+ }
12
+ export interface ApiAuthInfo {
13
+ kind: 'api';
14
+ apiKey: string;
15
+ metadata?: Record<string, string>;
16
+ }
17
+ export type AuthInfo = OAuthAuthInfo | ApiAuthInfo;
18
+ export type AuthKind = AuthInfo['kind'];
19
+ export type CanonicalAuthProviderId = 'codex' | 'copilot' | 'copilot-enterprise';
20
+ export declare const AUTH_PROVIDER_IDS: {
21
+ readonly codex: "codex";
22
+ readonly copilot: "copilot";
23
+ readonly copilotEnterprise: "copilot-enterprise";
24
+ };
25
+ export declare const AUTH_PROVIDER_ALIASES: Record<string, CanonicalAuthProviderId>;
26
+ export interface AuthStore {
27
+ get(providerId: string): Promise<AuthInfo | undefined>;
28
+ set(providerId: string, auth: AuthInfo): Promise<void>;
29
+ delete(providerId: string): Promise<void>;
30
+ getAll(): Promise<Record<string, AuthInfo>>;
31
+ }
32
+ export interface FileAuthStoreOptions {
33
+ filePath?: string;
34
+ agentSdkAuthFilePath?: string;
35
+ openCodeAuthFilePath?: string;
36
+ enableOpenCodeFallback?: boolean;
37
+ }
38
+ export declare function createMemoryAuthStore(initialAuth?: Record<string, AuthInfo>): AuthStore;
39
+ export declare function createFileAuthStore(options?: FileAuthStoreOptions): AuthStore;
40
+ export declare function ensureFileAuthStore(options?: FileAuthStoreOptions): Promise<AuthStore>;
41
+ export declare function getDefaultAgentLayerAuthPath(): string;
42
+ export declare function getDefaultAgentSdkAuthPath(): string;
43
+ export declare function getDefaultOpenCodeAuthPath(): string;
44
+ export declare function readAuth(providerId: string, options?: FileAuthStoreOptions): Promise<AuthInfo | undefined>;
45
+ export declare function writeAuth(providerId: string, auth: AuthInfo, options?: FileAuthStoreOptions): Promise<void>;
46
+ export declare function removeAuth(providerId: string, options?: FileAuthStoreOptions): Promise<void>;
47
+ export declare function readAllAuth(options?: FileAuthStoreOptions): Promise<Record<string, AuthInfo>>;
48
+ export declare function requireAuth(store: AuthStore, providerId: string): Promise<AuthInfo>;
49
+ export declare function requireAuth<TKind extends AuthKind>(store: AuthStore, providerId: string, expectedKind: TKind): Promise<Extract<AuthInfo, {
50
+ kind: TKind;
51
+ }>>;
52
+ export declare function normalizeProviderId(providerId: string): string;
53
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export * from './auth';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,287 @@
1
+ // src/auth.ts
2
+ import * as fs from "node:fs/promises";
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+ var AUTH_PROVIDER_IDS = {
6
+ codex: "codex",
7
+ copilot: "copilot",
8
+ copilotEnterprise: "copilot-enterprise"
9
+ };
10
+ var AUTH_PROVIDER_ALIASES = {
11
+ openai: AUTH_PROVIDER_IDS.codex,
12
+ "openai.codex": AUTH_PROVIDER_IDS.codex,
13
+ codex: AUTH_PROVIDER_IDS.codex,
14
+ "github-copilot": AUTH_PROVIDER_IDS.copilot,
15
+ copilot: AUTH_PROVIDER_IDS.copilot,
16
+ "github-copilot-enterprise": AUTH_PROVIDER_IDS.copilotEnterprise,
17
+ "copilot-enterprise": AUTH_PROVIDER_IDS.copilotEnterprise
18
+ };
19
+ function createMemoryAuthStore(initialAuth = {}) {
20
+ const store = new Map;
21
+ for (const [providerId, auth] of Object.entries(initialAuth)) {
22
+ store.set(normalizeProviderId(providerId), cloneAuth(auth));
23
+ }
24
+ return {
25
+ async get(providerId) {
26
+ const auth = store.get(normalizeProviderId(providerId));
27
+ return auth ? cloneAuth(auth) : undefined;
28
+ },
29
+ async set(providerId, auth) {
30
+ store.set(normalizeProviderId(providerId), cloneAuth(auth));
31
+ },
32
+ async delete(providerId) {
33
+ store.delete(normalizeProviderId(providerId));
34
+ },
35
+ async getAll() {
36
+ return cloneAuthRecord(Object.fromEntries(store.entries()));
37
+ }
38
+ };
39
+ }
40
+ function createFileAuthStore(options = {}) {
41
+ const resolved = resolveFileAuthStoreOptions(options);
42
+ return {
43
+ async get(providerId) {
44
+ const key = normalizeProviderId(providerId);
45
+ const auth = (await readAuthFile(resolved.filePath))[key];
46
+ if (auth)
47
+ return cloneAuth(auth);
48
+ if (!resolved.enableOpenCodeFallback)
49
+ return;
50
+ const fallbackAuth = (await readAuthFile(resolved.openCodeAuthFilePath))[key];
51
+ if (!fallbackAuth)
52
+ return;
53
+ const allAuth = await readAuthFile(resolved.filePath);
54
+ await writeAuthFile(resolved.filePath, { ...allAuth, [key]: fallbackAuth });
55
+ return cloneAuth(fallbackAuth);
56
+ },
57
+ async set(providerId, auth) {
58
+ const key = normalizeProviderId(providerId);
59
+ const allAuth = await readAuthFile(resolved.filePath);
60
+ await writeAuthFile(resolved.filePath, { ...allAuth, [key]: auth });
61
+ },
62
+ async delete(providerId) {
63
+ const key = normalizeProviderId(providerId);
64
+ const allAuth = await readAuthFile(resolved.filePath);
65
+ delete allAuth[key];
66
+ await writeAuthFile(resolved.filePath, allAuth);
67
+ },
68
+ async getAll() {
69
+ const allAuth = await readAuthFile(resolved.filePath);
70
+ if (!resolved.enableOpenCodeFallback)
71
+ return cloneAuthRecord(allAuth);
72
+ const fallbackAuth = await readAuthFile(resolved.openCodeAuthFilePath);
73
+ let imported = false;
74
+ const merged = { ...allAuth };
75
+ for (const [providerId, auth] of Object.entries(fallbackAuth)) {
76
+ if (merged[providerId])
77
+ continue;
78
+ merged[providerId] = auth;
79
+ imported = true;
80
+ }
81
+ if (imported) {
82
+ await writeAuthFile(resolved.filePath, merged);
83
+ }
84
+ return cloneAuthRecord(merged);
85
+ }
86
+ };
87
+ }
88
+ async function ensureFileAuthStore(options = {}) {
89
+ const resolved = resolveFileAuthStoreOptions(options);
90
+ if (!await fileExists(resolved.filePath)) {
91
+ const agentSdkAuth = await readAuthFile(resolved.agentSdkAuthFilePath);
92
+ if (Object.keys(agentSdkAuth).length > 0) {
93
+ await writeAuthFile(resolved.filePath, agentSdkAuth);
94
+ }
95
+ }
96
+ return createFileAuthStore(options);
97
+ }
98
+ function getDefaultAgentLayerAuthPath() {
99
+ if (process.env.AGENTLAYER_AUTH_PATH)
100
+ return process.env.AGENTLAYER_AUTH_PATH;
101
+ return path.join(getXdgDataHome(), "agentlayer", "auth.json");
102
+ }
103
+ function getDefaultAgentSdkAuthPath() {
104
+ if (process.env.AGENT_SDK_AUTH_PATH)
105
+ return process.env.AGENT_SDK_AUTH_PATH;
106
+ return path.join(os.homedir(), ".humanlayer", "agent-sdk", "auth.json");
107
+ }
108
+ function getDefaultOpenCodeAuthPath() {
109
+ if (process.env.OPENCODE_AUTH_PATH)
110
+ return process.env.OPENCODE_AUTH_PATH;
111
+ return path.join(getXdgDataHome(), "opencode", "auth.json");
112
+ }
113
+ async function readAuth(providerId, options) {
114
+ return createFileAuthStore(options).get(providerId);
115
+ }
116
+ async function writeAuth(providerId, auth, options) {
117
+ return createFileAuthStore(options).set(providerId, auth);
118
+ }
119
+ async function removeAuth(providerId, options) {
120
+ return createFileAuthStore(options).delete(providerId);
121
+ }
122
+ async function readAllAuth(options) {
123
+ return createFileAuthStore(options).getAll();
124
+ }
125
+ async function requireAuth(store, providerId, expectedKind) {
126
+ const auth = await store.get(providerId);
127
+ if (!auth) {
128
+ throw new Error(`Missing auth for provider: ${providerId}`);
129
+ }
130
+ if (expectedKind && auth.kind !== expectedKind) {
131
+ throw new Error(`Expected ${expectedKind} auth for provider: ${providerId}, got ${auth.kind}`);
132
+ }
133
+ return auth;
134
+ }
135
+ function normalizeProviderId(providerId) {
136
+ const normalized = providerId.trim().replace(/\/+$/, "");
137
+ return AUTH_PROVIDER_ALIASES[normalized] ?? normalized;
138
+ }
139
+ function resolveFileAuthStoreOptions(options) {
140
+ return {
141
+ filePath: options.filePath ?? getDefaultAgentLayerAuthPath(),
142
+ agentSdkAuthFilePath: options.agentSdkAuthFilePath ?? getDefaultAgentSdkAuthPath(),
143
+ openCodeAuthFilePath: options.openCodeAuthFilePath ?? getDefaultOpenCodeAuthPath(),
144
+ enableOpenCodeFallback: options.enableOpenCodeFallback ?? options.openCodeAuthFilePath != null
145
+ };
146
+ }
147
+ async function fileExists(filePath) {
148
+ try {
149
+ await fs.access(filePath);
150
+ return true;
151
+ } catch (error) {
152
+ if (isNotFoundError(error))
153
+ return false;
154
+ throw error;
155
+ }
156
+ }
157
+ function getXdgDataHome() {
158
+ return process.env.XDG_DATA_HOME ?? path.join(os.homedir(), ".local", "share");
159
+ }
160
+ async function readAuthFile(filePath) {
161
+ let text;
162
+ try {
163
+ text = await fs.readFile(filePath, "utf8");
164
+ } catch (error) {
165
+ if (isNotFoundError(error))
166
+ return {};
167
+ throw error;
168
+ }
169
+ const parsed = JSON.parse(text);
170
+ if (!isRecord(parsed))
171
+ return {};
172
+ const allAuth = {};
173
+ for (const [providerId, value] of Object.entries(parsed)) {
174
+ const auth = decodeAuthInfo(value);
175
+ if (!auth)
176
+ continue;
177
+ allAuth[normalizeProviderId(providerId)] = auth;
178
+ }
179
+ return allAuth;
180
+ }
181
+ async function writeAuthFile(filePath, auth) {
182
+ const normalizedAuth = Object.fromEntries(Object.entries(auth).map(([providerId, value]) => [normalizeProviderId(providerId), cloneAuth(value)]));
183
+ await fs.mkdir(path.dirname(filePath), { recursive: true });
184
+ await fs.writeFile(filePath, `${JSON.stringify(normalizedAuth, null, "\t")}
185
+ `, { mode: 384 });
186
+ await fs.chmod(filePath, 384);
187
+ }
188
+ function decodeAuthInfo(value) {
189
+ if (!isRecord(value))
190
+ return;
191
+ if (value.kind === "oauth")
192
+ return decodeOAuthAuthInfo(value);
193
+ if (value.kind === "api")
194
+ return decodeApiAuthInfo(value);
195
+ if (value.type === "oauth")
196
+ return decodeOpenCodeOAuthAuthInfo(value);
197
+ if (value.type === "api")
198
+ return decodeOpenCodeApiAuthInfo(value);
199
+ return;
200
+ }
201
+ function decodeOAuthAuthInfo(value) {
202
+ if (typeof value.accessToken !== "string")
203
+ return;
204
+ return {
205
+ kind: "oauth",
206
+ accessToken: value.accessToken,
207
+ ...optionalString("refreshToken", value.refreshToken),
208
+ ...optionalNumber("expiresAt", value.expiresAt),
209
+ ...optionalString("idToken", value.idToken),
210
+ ...optionalString("scope", value.scope),
211
+ ...optionalString("tokenType", value.tokenType),
212
+ ...optionalString("accountId", value.accountId),
213
+ ...optionalString("enterpriseUrl", value.enterpriseUrl)
214
+ };
215
+ }
216
+ function decodeApiAuthInfo(value) {
217
+ if (typeof value.apiKey !== "string")
218
+ return;
219
+ return {
220
+ kind: "api",
221
+ apiKey: value.apiKey,
222
+ ...optionalStringRecord("metadata", value.metadata)
223
+ };
224
+ }
225
+ function decodeOpenCodeOAuthAuthInfo(value) {
226
+ if (typeof value.access !== "string")
227
+ return;
228
+ return {
229
+ kind: "oauth",
230
+ accessToken: value.access,
231
+ ...optionalString("refreshToken", value.refresh),
232
+ ...optionalNumber("expiresAt", value.expires),
233
+ ...optionalString("accountId", value.accountId),
234
+ ...optionalString("enterpriseUrl", value.enterpriseUrl)
235
+ };
236
+ }
237
+ function decodeOpenCodeApiAuthInfo(value) {
238
+ if (typeof value.key !== "string")
239
+ return;
240
+ return {
241
+ kind: "api",
242
+ apiKey: value.key,
243
+ ...optionalStringRecord("metadata", value.metadata)
244
+ };
245
+ }
246
+ function optionalString(key, value) {
247
+ return typeof value === "string" ? { [key]: value } : {};
248
+ }
249
+ function optionalNumber(key, value) {
250
+ return typeof value === "number" ? { [key]: value } : {};
251
+ }
252
+ function optionalStringRecord(key, value) {
253
+ if (!isRecord(value))
254
+ return {};
255
+ const entries = Object.entries(value).filter((entry) => typeof entry[1] === "string");
256
+ return entries.length > 0 ? { [key]: Object.fromEntries(entries) } : {};
257
+ }
258
+ function isRecord(value) {
259
+ return typeof value === "object" && value !== null && !Array.isArray(value);
260
+ }
261
+ function isNotFoundError(error) {
262
+ return isRecord(error) && error.code === "ENOENT";
263
+ }
264
+ function cloneAuth(auth) {
265
+ return structuredClone(auth);
266
+ }
267
+ function cloneAuthRecord(auth) {
268
+ return Object.fromEntries(Object.entries(auth).map(([providerId, value]) => [providerId, cloneAuth(value)]));
269
+ }
270
+ export {
271
+ writeAuth,
272
+ requireAuth,
273
+ removeAuth,
274
+ readAuth,
275
+ readAllAuth,
276
+ normalizeProviderId,
277
+ getDefaultOpenCodeAuthPath,
278
+ getDefaultAgentSdkAuthPath,
279
+ getDefaultAgentLayerAuthPath,
280
+ ensureFileAuthStore,
281
+ createMemoryAuthStore,
282
+ createFileAuthStore,
283
+ AUTH_PROVIDER_IDS,
284
+ AUTH_PROVIDER_ALIASES
285
+ };
286
+
287
+ //# debugId=D9DD89FCBCE34B6B64756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/auth.ts"],
4
+ "sourcesContent": [
5
+ "import * as fs from 'node:fs/promises'\nimport os from 'node:os'\nimport path from 'node:path'\n\nexport interface OAuthAuthInfo {\n\tkind: 'oauth'\n\taccessToken: string\n\trefreshToken?: string\n\texpiresAt?: number\n\tidToken?: string\n\tscope?: string\n\ttokenType?: string\n\taccountId?: string\n\tenterpriseUrl?: string\n}\n\nexport interface ApiAuthInfo {\n\tkind: 'api'\n\tapiKey: string\n\tmetadata?: Record<string, string>\n}\n\nexport type AuthInfo = OAuthAuthInfo | ApiAuthInfo\nexport type AuthKind = AuthInfo['kind']\nexport type CanonicalAuthProviderId = 'codex' | 'copilot' | 'copilot-enterprise'\n\nexport const AUTH_PROVIDER_IDS = {\n\tcodex: 'codex',\n\tcopilot: 'copilot',\n\tcopilotEnterprise: 'copilot-enterprise',\n} as const satisfies Record<string, CanonicalAuthProviderId>\n\nexport const AUTH_PROVIDER_ALIASES: Record<string, CanonicalAuthProviderId> = {\n\topenai: AUTH_PROVIDER_IDS.codex,\n\t'openai.codex': AUTH_PROVIDER_IDS.codex,\n\tcodex: AUTH_PROVIDER_IDS.codex,\n\t'github-copilot': AUTH_PROVIDER_IDS.copilot,\n\tcopilot: AUTH_PROVIDER_IDS.copilot,\n\t'github-copilot-enterprise': AUTH_PROVIDER_IDS.copilotEnterprise,\n\t'copilot-enterprise': AUTH_PROVIDER_IDS.copilotEnterprise,\n}\n\nexport interface AuthStore {\n\tget(providerId: string): Promise<AuthInfo | undefined>\n\tset(providerId: string, auth: AuthInfo): Promise<void>\n\tdelete(providerId: string): Promise<void>\n\tgetAll(): Promise<Record<string, AuthInfo>>\n}\n\nexport interface FileAuthStoreOptions {\n\tfilePath?: string\n\tagentSdkAuthFilePath?: string\n\topenCodeAuthFilePath?: string\n\tenableOpenCodeFallback?: boolean\n}\n\ninterface ResolvedFileAuthStoreOptions {\n\tfilePath: string\n\tagentSdkAuthFilePath: string\n\topenCodeAuthFilePath: string\n\tenableOpenCodeFallback: boolean\n}\n\nexport function createMemoryAuthStore(initialAuth: Record<string, AuthInfo> = {}): AuthStore {\n\tconst store = new Map<string, AuthInfo>()\n\n\tfor (const [providerId, auth] of Object.entries(initialAuth)) {\n\t\tstore.set(normalizeProviderId(providerId), cloneAuth(auth))\n\t}\n\n\treturn {\n\t\tasync get(providerId) {\n\t\t\tconst auth = store.get(normalizeProviderId(providerId))\n\t\t\treturn auth ? cloneAuth(auth) : undefined\n\t\t},\n\t\tasync set(providerId, auth) {\n\t\t\tstore.set(normalizeProviderId(providerId), cloneAuth(auth))\n\t\t},\n\t\tasync delete(providerId) {\n\t\t\tstore.delete(normalizeProviderId(providerId))\n\t\t},\n\t\tasync getAll() {\n\t\t\treturn cloneAuthRecord(Object.fromEntries(store.entries()))\n\t\t},\n\t}\n}\n\nexport function createFileAuthStore(options: FileAuthStoreOptions = {}): AuthStore {\n\tconst resolved = resolveFileAuthStoreOptions(options)\n\n\treturn {\n\t\tasync get(providerId) {\n\t\t\tconst key = normalizeProviderId(providerId)\n\t\t\tconst auth = (await readAuthFile(resolved.filePath))[key]\n\t\t\tif (auth) return cloneAuth(auth)\n\n\t\t\tif (!resolved.enableOpenCodeFallback) return undefined\n\n\t\t\tconst fallbackAuth = (await readAuthFile(resolved.openCodeAuthFilePath))[key]\n\t\t\tif (!fallbackAuth) return undefined\n\n\t\t\tconst allAuth = await readAuthFile(resolved.filePath)\n\t\t\tawait writeAuthFile(resolved.filePath, { ...allAuth, [key]: fallbackAuth })\n\t\t\treturn cloneAuth(fallbackAuth)\n\t\t},\n\t\tasync set(providerId, auth) {\n\t\t\tconst key = normalizeProviderId(providerId)\n\t\t\tconst allAuth = await readAuthFile(resolved.filePath)\n\t\t\tawait writeAuthFile(resolved.filePath, { ...allAuth, [key]: auth })\n\t\t},\n\t\tasync delete(providerId) {\n\t\t\tconst key = normalizeProviderId(providerId)\n\t\t\tconst allAuth = await readAuthFile(resolved.filePath)\n\t\t\tdelete allAuth[key]\n\t\t\tawait writeAuthFile(resolved.filePath, allAuth)\n\t\t},\n\t\tasync getAll() {\n\t\t\tconst allAuth = await readAuthFile(resolved.filePath)\n\t\t\tif (!resolved.enableOpenCodeFallback) return cloneAuthRecord(allAuth)\n\n\t\t\tconst fallbackAuth = await readAuthFile(resolved.openCodeAuthFilePath)\n\t\t\tlet imported = false\n\t\t\tconst merged = { ...allAuth }\n\t\t\tfor (const [providerId, auth] of Object.entries(fallbackAuth)) {\n\t\t\t\tif (merged[providerId]) continue\n\t\t\t\tmerged[providerId] = auth\n\t\t\t\timported = true\n\t\t\t}\n\n\t\t\tif (imported) {\n\t\t\t\tawait writeAuthFile(resolved.filePath, merged)\n\t\t\t}\n\n\t\t\treturn cloneAuthRecord(merged)\n\t\t},\n\t}\n}\n\nexport async function ensureFileAuthStore(options: FileAuthStoreOptions = {}): Promise<AuthStore> {\n\tconst resolved = resolveFileAuthStoreOptions(options)\n\tif (!(await fileExists(resolved.filePath))) {\n\t\tconst agentSdkAuth = await readAuthFile(resolved.agentSdkAuthFilePath)\n\t\tif (Object.keys(agentSdkAuth).length > 0) {\n\t\t\tawait writeAuthFile(resolved.filePath, agentSdkAuth)\n\t\t}\n\t}\n\treturn createFileAuthStore(options)\n}\n\nexport function getDefaultAgentLayerAuthPath(): string {\n\tif (process.env.AGENTLAYER_AUTH_PATH) return process.env.AGENTLAYER_AUTH_PATH\n\treturn path.join(getXdgDataHome(), 'agentlayer', 'auth.json')\n}\n\nexport function getDefaultAgentSdkAuthPath(): string {\n\tif (process.env.AGENT_SDK_AUTH_PATH) return process.env.AGENT_SDK_AUTH_PATH\n\treturn path.join(os.homedir(), '.humanlayer', 'agent-sdk', 'auth.json')\n}\n\nexport function getDefaultOpenCodeAuthPath(): string {\n\tif (process.env.OPENCODE_AUTH_PATH) return process.env.OPENCODE_AUTH_PATH\n\treturn path.join(getXdgDataHome(), 'opencode', 'auth.json')\n}\n\nexport async function readAuth(providerId: string, options?: FileAuthStoreOptions): Promise<AuthInfo | undefined> {\n\treturn createFileAuthStore(options).get(providerId)\n}\n\nexport async function writeAuth(providerId: string, auth: AuthInfo, options?: FileAuthStoreOptions): Promise<void> {\n\treturn createFileAuthStore(options).set(providerId, auth)\n}\n\nexport async function removeAuth(providerId: string, options?: FileAuthStoreOptions): Promise<void> {\n\treturn createFileAuthStore(options).delete(providerId)\n}\n\nexport async function readAllAuth(options?: FileAuthStoreOptions): Promise<Record<string, AuthInfo>> {\n\treturn createFileAuthStore(options).getAll()\n}\n\nexport async function requireAuth(store: AuthStore, providerId: string): Promise<AuthInfo>\nexport async function requireAuth<TKind extends AuthKind>(\n\tstore: AuthStore,\n\tproviderId: string,\n\texpectedKind: TKind,\n): Promise<Extract<AuthInfo, { kind: TKind }>>\nexport async function requireAuth(store: AuthStore, providerId: string, expectedKind?: AuthKind): Promise<AuthInfo> {\n\tconst auth = await store.get(providerId)\n\tif (!auth) {\n\t\tthrow new Error(`Missing auth for provider: ${providerId}`)\n\t}\n\tif (expectedKind && auth.kind !== expectedKind) {\n\t\tthrow new Error(`Expected ${expectedKind} auth for provider: ${providerId}, got ${auth.kind}`)\n\t}\n\treturn auth\n}\n\nexport function normalizeProviderId(providerId: string): string {\n\tconst normalized = providerId.trim().replace(/\\/+$/, '')\n\treturn AUTH_PROVIDER_ALIASES[normalized] ?? normalized\n}\n\nfunction resolveFileAuthStoreOptions(options: FileAuthStoreOptions): ResolvedFileAuthStoreOptions {\n\treturn {\n\t\tfilePath: options.filePath ?? getDefaultAgentLayerAuthPath(),\n\t\tagentSdkAuthFilePath: options.agentSdkAuthFilePath ?? getDefaultAgentSdkAuthPath(),\n\t\topenCodeAuthFilePath: options.openCodeAuthFilePath ?? getDefaultOpenCodeAuthPath(),\n\t\tenableOpenCodeFallback: options.enableOpenCodeFallback ?? options.openCodeAuthFilePath != null,\n\t}\n}\n\nasync function fileExists(filePath: string): Promise<boolean> {\n\ttry {\n\t\tawait fs.access(filePath)\n\t\treturn true\n\t} catch (error) {\n\t\tif (isNotFoundError(error)) return false\n\t\tthrow error\n\t}\n}\n\nfunction getXdgDataHome(): string {\n\treturn process.env.XDG_DATA_HOME ?? path.join(os.homedir(), '.local', 'share')\n}\n\nasync function readAuthFile(filePath: string): Promise<Record<string, AuthInfo>> {\n\tlet text: string\n\ttry {\n\t\ttext = await fs.readFile(filePath, 'utf8')\n\t} catch (error) {\n\t\tif (isNotFoundError(error)) return {}\n\t\tthrow error\n\t}\n\n\tconst parsed = JSON.parse(text) as unknown\n\tif (!isRecord(parsed)) return {}\n\n\tconst allAuth: Record<string, AuthInfo> = {}\n\tfor (const [providerId, value] of Object.entries(parsed)) {\n\t\tconst auth = decodeAuthInfo(value)\n\t\tif (!auth) continue\n\t\tallAuth[normalizeProviderId(providerId)] = auth\n\t}\n\treturn allAuth\n}\n\nasync function writeAuthFile(filePath: string, auth: Record<string, AuthInfo>): Promise<void> {\n\tconst normalizedAuth = Object.fromEntries(\n\t\tObject.entries(auth).map(([providerId, value]) => [normalizeProviderId(providerId), cloneAuth(value)]),\n\t)\n\tawait fs.mkdir(path.dirname(filePath), { recursive: true })\n\tawait fs.writeFile(filePath, `${JSON.stringify(normalizedAuth, null, '\\t')}\\n`, { mode: 0o600 })\n\tawait fs.chmod(filePath, 0o600)\n}\n\nfunction decodeAuthInfo(value: unknown): AuthInfo | undefined {\n\tif (!isRecord(value)) return undefined\n\n\tif (value.kind === 'oauth') return decodeOAuthAuthInfo(value)\n\tif (value.kind === 'api') return decodeApiAuthInfo(value)\n\tif (value.type === 'oauth') return decodeOpenCodeOAuthAuthInfo(value)\n\tif (value.type === 'api') return decodeOpenCodeApiAuthInfo(value)\n\n\treturn undefined\n}\n\nfunction decodeOAuthAuthInfo(value: Record<string, unknown>): OAuthAuthInfo | undefined {\n\tif (typeof value.accessToken !== 'string') return undefined\n\treturn {\n\t\tkind: 'oauth',\n\t\taccessToken: value.accessToken,\n\t\t...optionalString('refreshToken', value.refreshToken),\n\t\t...optionalNumber('expiresAt', value.expiresAt),\n\t\t...optionalString('idToken', value.idToken),\n\t\t...optionalString('scope', value.scope),\n\t\t...optionalString('tokenType', value.tokenType),\n\t\t...optionalString('accountId', value.accountId),\n\t\t...optionalString('enterpriseUrl', value.enterpriseUrl),\n\t}\n}\n\nfunction decodeApiAuthInfo(value: Record<string, unknown>): ApiAuthInfo | undefined {\n\tif (typeof value.apiKey !== 'string') return undefined\n\treturn {\n\t\tkind: 'api',\n\t\tapiKey: value.apiKey,\n\t\t...optionalStringRecord('metadata', value.metadata),\n\t}\n}\n\nfunction decodeOpenCodeOAuthAuthInfo(value: Record<string, unknown>): OAuthAuthInfo | undefined {\n\tif (typeof value.access !== 'string') return undefined\n\treturn {\n\t\tkind: 'oauth',\n\t\taccessToken: value.access,\n\t\t...optionalString('refreshToken', value.refresh),\n\t\t...optionalNumber('expiresAt', value.expires),\n\t\t...optionalString('accountId', value.accountId),\n\t\t...optionalString('enterpriseUrl', value.enterpriseUrl),\n\t}\n}\n\nfunction decodeOpenCodeApiAuthInfo(value: Record<string, unknown>): ApiAuthInfo | undefined {\n\tif (typeof value.key !== 'string') return undefined\n\treturn {\n\t\tkind: 'api',\n\t\tapiKey: value.key,\n\t\t...optionalStringRecord('metadata', value.metadata),\n\t}\n}\n\nfunction optionalString(key: string, value: unknown): Record<string, string> {\n\treturn typeof value === 'string' ? { [key]: value } : {}\n}\n\nfunction optionalNumber(key: string, value: unknown): Record<string, number> {\n\treturn typeof value === 'number' ? { [key]: value } : {}\n}\n\nfunction optionalStringRecord(key: string, value: unknown): Record<string, Record<string, string>> {\n\tif (!isRecord(value)) return {}\n\tconst entries = Object.entries(value).filter((entry): entry is [string, string] => typeof entry[1] === 'string')\n\treturn entries.length > 0 ? { [key]: Object.fromEntries(entries) } : {}\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction isNotFoundError(error: unknown): boolean {\n\treturn isRecord(error) && error.code === 'ENOENT'\n}\n\nfunction cloneAuth<T extends AuthInfo>(auth: T): T {\n\treturn structuredClone(auth)\n}\n\nfunction cloneAuthRecord(auth: Record<string, AuthInfo>): Record<string, AuthInfo> {\n\treturn Object.fromEntries(Object.entries(auth).map(([providerId, value]) => [providerId, cloneAuth(value)]))\n}\n"
6
+ ],
7
+ "mappings": "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",
8
+ "debugId": "D9DD89FCBCE34B6B64756E2164756E21",
9
+ "names": []
10
+ }
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@humanlayer/agentlayer-provider-auth",
3
+ "source": "./src/index.ts",
4
+ "type": "module",
5
+ "version": "0.0.7",
6
+ "private": false,
7
+ "main": "./dist/index.js",
8
+ "module": "./dist/index.js",
9
+ "types": "./dist/index.d.ts",
10
+ "publishConfig": {
11
+ "access": "public"
12
+ },
13
+ "files": [
14
+ "src",
15
+ "dist"
16
+ ],
17
+ "scripts": {
18
+ "typecheck": "tsgo --noEmit",
19
+ "build": "bun run build:js && bunx tsc -p tsconfig.build.json",
20
+ "build:js": "bun run build.ts",
21
+ "build:types": "bunx tsc -p tsconfig.build.json"
22
+ },
23
+ "devDependencies": {
24
+ "@types/bun": "latest"
25
+ },
26
+ "peerDependencies": {
27
+ "typescript": "^5"
28
+ },
29
+ "exports": {
30
+ ".": {
31
+ "source": "./src/index.ts",
32
+ "types": "./dist/index.d.ts",
33
+ "import": "./dist/index.js",
34
+ "default": "./dist/index.js"
35
+ }
36
+ },
37
+ "dependencies": {}
38
+ }
package/src/auth.ts ADDED
@@ -0,0 +1,340 @@
1
+ import * as fs from 'node:fs/promises'
2
+ import os from 'node:os'
3
+ import path from 'node:path'
4
+
5
+ export interface OAuthAuthInfo {
6
+ kind: 'oauth'
7
+ accessToken: string
8
+ refreshToken?: string
9
+ expiresAt?: number
10
+ idToken?: string
11
+ scope?: string
12
+ tokenType?: string
13
+ accountId?: string
14
+ enterpriseUrl?: string
15
+ }
16
+
17
+ export interface ApiAuthInfo {
18
+ kind: 'api'
19
+ apiKey: string
20
+ metadata?: Record<string, string>
21
+ }
22
+
23
+ export type AuthInfo = OAuthAuthInfo | ApiAuthInfo
24
+ export type AuthKind = AuthInfo['kind']
25
+ export type CanonicalAuthProviderId = 'codex' | 'copilot' | 'copilot-enterprise'
26
+
27
+ export const AUTH_PROVIDER_IDS = {
28
+ codex: 'codex',
29
+ copilot: 'copilot',
30
+ copilotEnterprise: 'copilot-enterprise',
31
+ } as const satisfies Record<string, CanonicalAuthProviderId>
32
+
33
+ export const AUTH_PROVIDER_ALIASES: Record<string, CanonicalAuthProviderId> = {
34
+ openai: AUTH_PROVIDER_IDS.codex,
35
+ 'openai.codex': AUTH_PROVIDER_IDS.codex,
36
+ codex: AUTH_PROVIDER_IDS.codex,
37
+ 'github-copilot': AUTH_PROVIDER_IDS.copilot,
38
+ copilot: AUTH_PROVIDER_IDS.copilot,
39
+ 'github-copilot-enterprise': AUTH_PROVIDER_IDS.copilotEnterprise,
40
+ 'copilot-enterprise': AUTH_PROVIDER_IDS.copilotEnterprise,
41
+ }
42
+
43
+ export interface AuthStore {
44
+ get(providerId: string): Promise<AuthInfo | undefined>
45
+ set(providerId: string, auth: AuthInfo): Promise<void>
46
+ delete(providerId: string): Promise<void>
47
+ getAll(): Promise<Record<string, AuthInfo>>
48
+ }
49
+
50
+ export interface FileAuthStoreOptions {
51
+ filePath?: string
52
+ agentSdkAuthFilePath?: string
53
+ openCodeAuthFilePath?: string
54
+ enableOpenCodeFallback?: boolean
55
+ }
56
+
57
+ interface ResolvedFileAuthStoreOptions {
58
+ filePath: string
59
+ agentSdkAuthFilePath: string
60
+ openCodeAuthFilePath: string
61
+ enableOpenCodeFallback: boolean
62
+ }
63
+
64
+ export function createMemoryAuthStore(initialAuth: Record<string, AuthInfo> = {}): AuthStore {
65
+ const store = new Map<string, AuthInfo>()
66
+
67
+ for (const [providerId, auth] of Object.entries(initialAuth)) {
68
+ store.set(normalizeProviderId(providerId), cloneAuth(auth))
69
+ }
70
+
71
+ return {
72
+ async get(providerId) {
73
+ const auth = store.get(normalizeProviderId(providerId))
74
+ return auth ? cloneAuth(auth) : undefined
75
+ },
76
+ async set(providerId, auth) {
77
+ store.set(normalizeProviderId(providerId), cloneAuth(auth))
78
+ },
79
+ async delete(providerId) {
80
+ store.delete(normalizeProviderId(providerId))
81
+ },
82
+ async getAll() {
83
+ return cloneAuthRecord(Object.fromEntries(store.entries()))
84
+ },
85
+ }
86
+ }
87
+
88
+ export function createFileAuthStore(options: FileAuthStoreOptions = {}): AuthStore {
89
+ const resolved = resolveFileAuthStoreOptions(options)
90
+
91
+ return {
92
+ async get(providerId) {
93
+ const key = normalizeProviderId(providerId)
94
+ const auth = (await readAuthFile(resolved.filePath))[key]
95
+ if (auth) return cloneAuth(auth)
96
+
97
+ if (!resolved.enableOpenCodeFallback) return undefined
98
+
99
+ const fallbackAuth = (await readAuthFile(resolved.openCodeAuthFilePath))[key]
100
+ if (!fallbackAuth) return undefined
101
+
102
+ const allAuth = await readAuthFile(resolved.filePath)
103
+ await writeAuthFile(resolved.filePath, { ...allAuth, [key]: fallbackAuth })
104
+ return cloneAuth(fallbackAuth)
105
+ },
106
+ async set(providerId, auth) {
107
+ const key = normalizeProviderId(providerId)
108
+ const allAuth = await readAuthFile(resolved.filePath)
109
+ await writeAuthFile(resolved.filePath, { ...allAuth, [key]: auth })
110
+ },
111
+ async delete(providerId) {
112
+ const key = normalizeProviderId(providerId)
113
+ const allAuth = await readAuthFile(resolved.filePath)
114
+ delete allAuth[key]
115
+ await writeAuthFile(resolved.filePath, allAuth)
116
+ },
117
+ async getAll() {
118
+ const allAuth = await readAuthFile(resolved.filePath)
119
+ if (!resolved.enableOpenCodeFallback) return cloneAuthRecord(allAuth)
120
+
121
+ const fallbackAuth = await readAuthFile(resolved.openCodeAuthFilePath)
122
+ let imported = false
123
+ const merged = { ...allAuth }
124
+ for (const [providerId, auth] of Object.entries(fallbackAuth)) {
125
+ if (merged[providerId]) continue
126
+ merged[providerId] = auth
127
+ imported = true
128
+ }
129
+
130
+ if (imported) {
131
+ await writeAuthFile(resolved.filePath, merged)
132
+ }
133
+
134
+ return cloneAuthRecord(merged)
135
+ },
136
+ }
137
+ }
138
+
139
+ export async function ensureFileAuthStore(options: FileAuthStoreOptions = {}): Promise<AuthStore> {
140
+ const resolved = resolveFileAuthStoreOptions(options)
141
+ if (!(await fileExists(resolved.filePath))) {
142
+ const agentSdkAuth = await readAuthFile(resolved.agentSdkAuthFilePath)
143
+ if (Object.keys(agentSdkAuth).length > 0) {
144
+ await writeAuthFile(resolved.filePath, agentSdkAuth)
145
+ }
146
+ }
147
+ return createFileAuthStore(options)
148
+ }
149
+
150
+ export function getDefaultAgentLayerAuthPath(): string {
151
+ if (process.env.AGENTLAYER_AUTH_PATH) return process.env.AGENTLAYER_AUTH_PATH
152
+ return path.join(getXdgDataHome(), 'agentlayer', 'auth.json')
153
+ }
154
+
155
+ export function getDefaultAgentSdkAuthPath(): string {
156
+ if (process.env.AGENT_SDK_AUTH_PATH) return process.env.AGENT_SDK_AUTH_PATH
157
+ return path.join(os.homedir(), '.humanlayer', 'agent-sdk', 'auth.json')
158
+ }
159
+
160
+ export function getDefaultOpenCodeAuthPath(): string {
161
+ if (process.env.OPENCODE_AUTH_PATH) return process.env.OPENCODE_AUTH_PATH
162
+ return path.join(getXdgDataHome(), 'opencode', 'auth.json')
163
+ }
164
+
165
+ export async function readAuth(providerId: string, options?: FileAuthStoreOptions): Promise<AuthInfo | undefined> {
166
+ return createFileAuthStore(options).get(providerId)
167
+ }
168
+
169
+ export async function writeAuth(providerId: string, auth: AuthInfo, options?: FileAuthStoreOptions): Promise<void> {
170
+ return createFileAuthStore(options).set(providerId, auth)
171
+ }
172
+
173
+ export async function removeAuth(providerId: string, options?: FileAuthStoreOptions): Promise<void> {
174
+ return createFileAuthStore(options).delete(providerId)
175
+ }
176
+
177
+ export async function readAllAuth(options?: FileAuthStoreOptions): Promise<Record<string, AuthInfo>> {
178
+ return createFileAuthStore(options).getAll()
179
+ }
180
+
181
+ export async function requireAuth(store: AuthStore, providerId: string): Promise<AuthInfo>
182
+ export async function requireAuth<TKind extends AuthKind>(
183
+ store: AuthStore,
184
+ providerId: string,
185
+ expectedKind: TKind,
186
+ ): Promise<Extract<AuthInfo, { kind: TKind }>>
187
+ export async function requireAuth(store: AuthStore, providerId: string, expectedKind?: AuthKind): Promise<AuthInfo> {
188
+ const auth = await store.get(providerId)
189
+ if (!auth) {
190
+ throw new Error(`Missing auth for provider: ${providerId}`)
191
+ }
192
+ if (expectedKind && auth.kind !== expectedKind) {
193
+ throw new Error(`Expected ${expectedKind} auth for provider: ${providerId}, got ${auth.kind}`)
194
+ }
195
+ return auth
196
+ }
197
+
198
+ export function normalizeProviderId(providerId: string): string {
199
+ const normalized = providerId.trim().replace(/\/+$/, '')
200
+ return AUTH_PROVIDER_ALIASES[normalized] ?? normalized
201
+ }
202
+
203
+ function resolveFileAuthStoreOptions(options: FileAuthStoreOptions): ResolvedFileAuthStoreOptions {
204
+ return {
205
+ filePath: options.filePath ?? getDefaultAgentLayerAuthPath(),
206
+ agentSdkAuthFilePath: options.agentSdkAuthFilePath ?? getDefaultAgentSdkAuthPath(),
207
+ openCodeAuthFilePath: options.openCodeAuthFilePath ?? getDefaultOpenCodeAuthPath(),
208
+ enableOpenCodeFallback: options.enableOpenCodeFallback ?? options.openCodeAuthFilePath != null,
209
+ }
210
+ }
211
+
212
+ async function fileExists(filePath: string): Promise<boolean> {
213
+ try {
214
+ await fs.access(filePath)
215
+ return true
216
+ } catch (error) {
217
+ if (isNotFoundError(error)) return false
218
+ throw error
219
+ }
220
+ }
221
+
222
+ function getXdgDataHome(): string {
223
+ return process.env.XDG_DATA_HOME ?? path.join(os.homedir(), '.local', 'share')
224
+ }
225
+
226
+ async function readAuthFile(filePath: string): Promise<Record<string, AuthInfo>> {
227
+ let text: string
228
+ try {
229
+ text = await fs.readFile(filePath, 'utf8')
230
+ } catch (error) {
231
+ if (isNotFoundError(error)) return {}
232
+ throw error
233
+ }
234
+
235
+ const parsed = JSON.parse(text) as unknown
236
+ if (!isRecord(parsed)) return {}
237
+
238
+ const allAuth: Record<string, AuthInfo> = {}
239
+ for (const [providerId, value] of Object.entries(parsed)) {
240
+ const auth = decodeAuthInfo(value)
241
+ if (!auth) continue
242
+ allAuth[normalizeProviderId(providerId)] = auth
243
+ }
244
+ return allAuth
245
+ }
246
+
247
+ async function writeAuthFile(filePath: string, auth: Record<string, AuthInfo>): Promise<void> {
248
+ const normalizedAuth = Object.fromEntries(
249
+ Object.entries(auth).map(([providerId, value]) => [normalizeProviderId(providerId), cloneAuth(value)]),
250
+ )
251
+ await fs.mkdir(path.dirname(filePath), { recursive: true })
252
+ await fs.writeFile(filePath, `${JSON.stringify(normalizedAuth, null, '\t')}\n`, { mode: 0o600 })
253
+ await fs.chmod(filePath, 0o600)
254
+ }
255
+
256
+ function decodeAuthInfo(value: unknown): AuthInfo | undefined {
257
+ if (!isRecord(value)) return undefined
258
+
259
+ if (value.kind === 'oauth') return decodeOAuthAuthInfo(value)
260
+ if (value.kind === 'api') return decodeApiAuthInfo(value)
261
+ if (value.type === 'oauth') return decodeOpenCodeOAuthAuthInfo(value)
262
+ if (value.type === 'api') return decodeOpenCodeApiAuthInfo(value)
263
+
264
+ return undefined
265
+ }
266
+
267
+ function decodeOAuthAuthInfo(value: Record<string, unknown>): OAuthAuthInfo | undefined {
268
+ if (typeof value.accessToken !== 'string') return undefined
269
+ return {
270
+ kind: 'oauth',
271
+ accessToken: value.accessToken,
272
+ ...optionalString('refreshToken', value.refreshToken),
273
+ ...optionalNumber('expiresAt', value.expiresAt),
274
+ ...optionalString('idToken', value.idToken),
275
+ ...optionalString('scope', value.scope),
276
+ ...optionalString('tokenType', value.tokenType),
277
+ ...optionalString('accountId', value.accountId),
278
+ ...optionalString('enterpriseUrl', value.enterpriseUrl),
279
+ }
280
+ }
281
+
282
+ function decodeApiAuthInfo(value: Record<string, unknown>): ApiAuthInfo | undefined {
283
+ if (typeof value.apiKey !== 'string') return undefined
284
+ return {
285
+ kind: 'api',
286
+ apiKey: value.apiKey,
287
+ ...optionalStringRecord('metadata', value.metadata),
288
+ }
289
+ }
290
+
291
+ function decodeOpenCodeOAuthAuthInfo(value: Record<string, unknown>): OAuthAuthInfo | undefined {
292
+ if (typeof value.access !== 'string') return undefined
293
+ return {
294
+ kind: 'oauth',
295
+ accessToken: value.access,
296
+ ...optionalString('refreshToken', value.refresh),
297
+ ...optionalNumber('expiresAt', value.expires),
298
+ ...optionalString('accountId', value.accountId),
299
+ ...optionalString('enterpriseUrl', value.enterpriseUrl),
300
+ }
301
+ }
302
+
303
+ function decodeOpenCodeApiAuthInfo(value: Record<string, unknown>): ApiAuthInfo | undefined {
304
+ if (typeof value.key !== 'string') return undefined
305
+ return {
306
+ kind: 'api',
307
+ apiKey: value.key,
308
+ ...optionalStringRecord('metadata', value.metadata),
309
+ }
310
+ }
311
+
312
+ function optionalString(key: string, value: unknown): Record<string, string> {
313
+ return typeof value === 'string' ? { [key]: value } : {}
314
+ }
315
+
316
+ function optionalNumber(key: string, value: unknown): Record<string, number> {
317
+ return typeof value === 'number' ? { [key]: value } : {}
318
+ }
319
+
320
+ function optionalStringRecord(key: string, value: unknown): Record<string, Record<string, string>> {
321
+ if (!isRecord(value)) return {}
322
+ const entries = Object.entries(value).filter((entry): entry is [string, string] => typeof entry[1] === 'string')
323
+ return entries.length > 0 ? { [key]: Object.fromEntries(entries) } : {}
324
+ }
325
+
326
+ function isRecord(value: unknown): value is Record<string, unknown> {
327
+ return typeof value === 'object' && value !== null && !Array.isArray(value)
328
+ }
329
+
330
+ function isNotFoundError(error: unknown): boolean {
331
+ return isRecord(error) && error.code === 'ENOENT'
332
+ }
333
+
334
+ function cloneAuth<T extends AuthInfo>(auth: T): T {
335
+ return structuredClone(auth)
336
+ }
337
+
338
+ function cloneAuthRecord(auth: Record<string, AuthInfo>): Record<string, AuthInfo> {
339
+ return Object.fromEntries(Object.entries(auth).map(([providerId, value]) => [providerId, cloneAuth(value)]))
340
+ }
package/src/index.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './auth'