@humanlayer/fold-xai 0.0.1-rc.1

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/ATTRIBUTION.md ADDED
@@ -0,0 +1,5 @@
1
+ # Attribution
2
+
3
+ The OAuth protocol implementation in this package is adapted from
4
+ `packages/opencode/src/plugin/xai.ts` in [opencode](https://github.com/sst/opencode),
5
+ Copyright (c) 2025 opencode, used under the MIT License. See `LICENSE-opencode`.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 HumanLayer
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,47 @@
1
+ import { Effect, FileSystem, Option, Schema } from 'effect';
2
+ /** Milliseconds before nominal expiry a token is already treated as expired (clanka parity). */
3
+ export declare const TOKEN_EXPIRY_BUFFER_MS = 30000;
4
+ /** Default location of the fold auth store. */
5
+ export declare const defaultAuthStorePath: () => string;
6
+ declare const XaiTokenData_base: Schema.Class<XaiTokenData, Schema.Struct<{
7
+ readonly type: Schema.Literal<"oauth">;
8
+ readonly access: Schema.String;
9
+ readonly refresh: Schema.String;
10
+ readonly expires: Schema.Number;
11
+ readonly accountId: Schema.optional<Schema.String>;
12
+ }>, {}>;
13
+ /** One stored Xai OAuth credential. `expires` is epoch milliseconds for the access token. */
14
+ export declare class XaiTokenData extends XaiTokenData_base {
15
+ /** True when the token is expired - or within the safety buffer of expiring - at `nowMs`. */
16
+ isExpired(nowMs: number): boolean;
17
+ }
18
+ declare const XaiAuthStoreError_base: Schema.Class<XaiAuthStoreError, Schema.TaggedStruct<"XaiAuthStoreError", {
19
+ readonly reason: Schema.Literals<readonly ["WriteFailed"]>;
20
+ readonly message: Schema.String;
21
+ readonly cause: Schema.optional<Schema.Defect>;
22
+ }>, import("effect/Cause").YieldableError>;
23
+ /** Auth store persistence failure (reads never fail - they degrade to absent credentials). */
24
+ export declare class XaiAuthStoreError extends XaiAuthStoreError_base {
25
+ }
26
+ /** The credential store one XaiAuth instance persists through. */
27
+ export type XaiAuthStore = {
28
+ /** Absolute path of the backing JSON document (used in error messages and guidance). */
29
+ readonly path: string;
30
+ readonly load: Effect.Effect<Option.Option<XaiTokenData>>;
31
+ readonly save: (token: XaiTokenData) => Effect.Effect<XaiTokenData, XaiAuthStoreError>;
32
+ readonly clear: Effect.Effect<void, XaiAuthStoreError>;
33
+ };
34
+ /** Options for {@link makeXaiAuthStore}. */
35
+ export type MakeXaiAuthStoreOptions = {
36
+ /** Path of the auth document. Defaults to `~/.fold/auth.json`. */
37
+ readonly path?: string;
38
+ /** Key of this provider's entry in the document. Defaults to `xai`. */
39
+ readonly providerId?: string;
40
+ /** FileSystem implementation override. Defaults to the Node platform filesystem. */
41
+ readonly fileSystem?: FileSystem.FileSystem;
42
+ };
43
+ /** The process-wide Node FileSystem service, built lazily once (layer construction is synchronous). */
44
+ export declare const defaultNodeFileSystem: () => FileSystem.FileSystem;
45
+ /** Build a file-backed Xai credential store. */
46
+ export declare const makeXaiAuthStore: (options?: MakeXaiAuthStoreOptions) => XaiAuthStore;
47
+ export {};
@@ -0,0 +1,45 @@
1
+ import { Effect, Schema } from 'effect';
2
+ import { HttpClient } from 'effect/unstable/http';
3
+ import { XaiTokenData } from './AuthStore';
4
+ export declare const XAI_CLIENT_ID = "b1a00492-073a-47ea-816f-4c329264a828";
5
+ export declare const XAI_ISSUER = "https://auth.x.ai";
6
+ export declare const XAI_SCOPE = "openid profile email offline_access grok-cli:access api:access";
7
+ export declare const XAI_BROWSER_PORT = 56121;
8
+ export declare const XAI_BROWSER_REDIRECT_URI = "http://127.0.0.1:56121/callback";
9
+ declare const XaiAuthError_base: Schema.Class<XaiAuthError, Schema.TaggedStruct<"XaiAuthError", {
10
+ readonly reason: Schema.Literals<readonly ["NotAuthenticated", "RefreshFailed", "TokenExchangeFailed", "DeviceFlowFailed", "BrowserFlowFailed", "StoreFailed"]>;
11
+ readonly message: Schema.String;
12
+ readonly cause: Schema.optional<Schema.Defect>;
13
+ }>, import("effect/Cause").YieldableError>;
14
+ export declare class XaiAuthError extends XaiAuthError_base {
15
+ }
16
+ /** Scope and harden an HttpClient for xAI's OAuth issuer. */
17
+ export declare const makeXaiIssuerClient: (client: HttpClient.HttpClient) => HttpClient.HttpClient;
18
+ /** Refresh a stored xAI OAuth credential, preserving rotating or omitted refresh tokens. */
19
+ export declare const refreshXaiAccessToken: (client: HttpClient.HttpClient, refresh: string) => Effect.Effect<XaiTokenData, XaiAuthError, never>;
20
+ export type XaiDevicePrompt = {
21
+ readonly verificationUri: string;
22
+ readonly userCode: string;
23
+ readonly browserUrl: string;
24
+ };
25
+ export type XaiDeviceFlowOptions = {
26
+ readonly client: HttpClient.HttpClient;
27
+ readonly onCode: (prompt: XaiDevicePrompt) => Effect.Effect<void>;
28
+ };
29
+ /** Run RFC 8628 device authorization, including pending/slow_down backoff and expiry. */
30
+ export declare const runXaiDeviceFlow: (options: XaiDeviceFlowOptions) => Effect.Effect<XaiTokenData, XaiAuthError, never>;
31
+ export type XaiPkce = {
32
+ readonly verifier: string;
33
+ readonly challenge: string;
34
+ };
35
+ export declare const generateXaiPkce: Effect.Effect<XaiPkce>;
36
+ /** Build xAI's registered Grok CLI authorization URL. */
37
+ export declare const buildXaiAuthorizeUrl: (pkce: XaiPkce, state: string, nonce: string) => string;
38
+ export type XaiBrowserFlowOptions = {
39
+ readonly client: HttpClient.HttpClient;
40
+ readonly onUrl: (url: string) => Effect.Effect<void>;
41
+ readonly timeoutMs?: number;
42
+ };
43
+ /** Run browser PKCE on xAI's fixed registered 127.0.0.1:56121 callback. */
44
+ export declare const runXaiBrowserFlow: (options: XaiBrowserFlowOptions) => Effect.Effect<XaiTokenData, XaiAuthError, never>;
45
+ export {};
@@ -0,0 +1,32 @@
1
+ /** Persistent, single-flight xAI OAuth credential service and authenticated HTTP decorator. */
2
+ import { Context, Effect } from 'effect';
3
+ import { HttpClient } from 'effect/unstable/http';
4
+ import type { XaiAuthStore } from './AuthStore';
5
+ import { XaiTokenData } from './AuthStore';
6
+ import type { XaiBrowserFlowOptions, XaiDevicePrompt } from './OAuthFlows';
7
+ import { XaiAuthError } from './OAuthFlows';
8
+ export type XaiAuthService = {
9
+ readonly get: Effect.Effect<XaiTokenData, XaiAuthError>;
10
+ readonly authenticateDevice: Effect.Effect<XaiTokenData, XaiAuthError>;
11
+ readonly authenticateBrowser: Effect.Effect<XaiTokenData, XaiAuthError>;
12
+ readonly logout: Effect.Effect<void, XaiAuthError>;
13
+ };
14
+ declare const XaiAuth_base: Context.ServiceClass<XaiAuth, "fold/XaiAuth", XaiAuthService>;
15
+ export declare class XaiAuth extends XaiAuth_base {
16
+ }
17
+ export type MakeXaiAuthOptions = {
18
+ readonly store?: XaiAuthStore;
19
+ readonly onDeviceCode?: (prompt: XaiDevicePrompt) => Effect.Effect<void>;
20
+ readonly onBrowserUrl?: (url: string) => Effect.Effect<void>;
21
+ readonly browser?: Pick<XaiBrowserFlowOptions, 'timeoutMs'>;
22
+ };
23
+ /** Construct xAI auth over the ambient HttpClient. Interactive flows are explicit methods. */
24
+ export declare const makeXaiAuth: (options?: MakeXaiAuthOptions | undefined) => Effect.Effect<{
25
+ get: Effect.Effect<XaiTokenData, XaiAuthError, never>;
26
+ authenticateDevice: Effect.Effect<XaiTokenData, XaiAuthError, never>;
27
+ authenticateBrowser: Effect.Effect<XaiTokenData, XaiAuthError, never>;
28
+ logout: Effect.Effect<void, XaiAuthError, never>;
29
+ }, never, HttpClient.HttpClient>;
30
+ /** Inject the current OAuth bearer token into every request without mutating caller headers. */
31
+ export declare const withXaiAuth: (client: HttpClient.HttpClient, auth: XaiAuthService) => HttpClient.HttpClient;
32
+ export {};
@@ -0,0 +1,18 @@
1
+ import type { FoldModel, ReasoningLevel } from '@humanlayer/fold-core';
2
+ import { Effect } from 'effect';
3
+ import type { Scope } from 'effect';
4
+ import type { LanguageModel } from 'effect/unstable/ai';
5
+ import type { XaiAuthStore } from './AuthStore';
6
+ export declare const XAI_API_URL = "https://api.x.ai/v1";
7
+ export declare const DEFAULT_XAI_MODEL_ID = "grok-4.5";
8
+ export type XaiModelOptions = {
9
+ readonly model?: string;
10
+ readonly reasoning?: ReasoningLevel;
11
+ readonly providerId?: string;
12
+ readonly apiUrl?: string;
13
+ readonly store?: XaiAuthStore;
14
+ };
15
+ /** Build xAI's stock OpenAI-compatible LanguageModel over the OAuth transport. */
16
+ export declare const makeXaiLanguageModel: (options: XaiModelOptions) => Effect.Effect<LanguageModel.Service, never, Scope.Scope>;
17
+ /** Describe an xAI OAuth-backed model compatible with Fold sessions and switching. */
18
+ export declare const xaiModel: (options?: XaiModelOptions) => FoldModel;
@@ -0,0 +1,4 @@
1
+ export * from './AuthStore';
2
+ export * from './OAuthFlows';
3
+ export * from './XaiAuth';
4
+ export * from './XaiModel';
package/dist/index.js ADDED
@@ -0,0 +1,367 @@
1
+ // packages/fold-xai/src/AuthStore.ts
2
+ import { homedir } from "node:os";
3
+ import { dirname, join } from "node:path";
4
+ import * as NodeFileSystem from "@effect/platform-node/NodeFileSystem";
5
+ import { Context, Effect, FileSystem, Layer, Option, Schema } from "effect";
6
+ var TOKEN_EXPIRY_BUFFER_MS = 30000;
7
+ var defaultAuthStorePath = () => join(homedir(), ".fold", "auth.json");
8
+
9
+ class XaiTokenData extends Schema.Class("fold/XaiTokenData")({
10
+ type: Schema.Literal("oauth"),
11
+ access: Schema.String,
12
+ refresh: Schema.String,
13
+ expires: Schema.Number,
14
+ accountId: Schema.optional(Schema.String)
15
+ }) {
16
+ isExpired(nowMs) {
17
+ return this.expires < nowMs + TOKEN_EXPIRY_BUFFER_MS;
18
+ }
19
+ }
20
+
21
+ class XaiAuthStoreError extends Schema.TaggedErrorClass()("XaiAuthStoreError", {
22
+ reason: Schema.Literals(["WriteFailed"]),
23
+ message: Schema.String,
24
+ cause: Schema.optional(Schema.Defect())
25
+ }) {
26
+ }
27
+ var nodeFileSystem = null;
28
+ var defaultNodeFileSystem = () => {
29
+ if (nodeFileSystem === null) {
30
+ nodeFileSystem = Effect.runSync(Effect.scoped(Layer.build(NodeFileSystem.layer).pipe(Effect.map((context) => Context.get(context, FileSystem.FileSystem)))));
31
+ }
32
+ return nodeFileSystem;
33
+ };
34
+ var AuthDocument = Schema.Record(Schema.String, Schema.Unknown);
35
+ var decodeDocument = Schema.decodeUnknownOption(Schema.fromJsonString(AuthDocument));
36
+ var decodeToken = Schema.decodeUnknownOption(XaiTokenData);
37
+ var encodeToken = (token) => ({
38
+ type: token.type,
39
+ access: token.access,
40
+ refresh: token.refresh,
41
+ expires: token.expires,
42
+ ...token.accountId === undefined ? {} : { accountId: token.accountId }
43
+ });
44
+ var makeXaiAuthStore = (options) => {
45
+ const fs = options?.fileSystem ?? defaultNodeFileSystem();
46
+ const path = options?.path ?? defaultAuthStorePath();
47
+ const providerId = options?.providerId ?? "xai";
48
+ const readDocument = fs.readFileString(path).pipe(Effect.flatMap((content) => {
49
+ const document = decodeDocument(content);
50
+ return Option.isSome(document) ? Effect.succeed(document.value) : Effect.logWarning(`Auth store ${path} is not a JSON object; treating it as empty`).pipe(Effect.as({}));
51
+ }), Effect.catch(() => Effect.succeed({})));
52
+ const writeDocument = (document) => Effect.gen(function* () {
53
+ yield* fs.makeDirectory(dirname(path), { recursive: true });
54
+ yield* fs.writeFileString(path, `${JSON.stringify(document, null, 2)}
55
+ `, { mode: 384 });
56
+ yield* fs.chmod(path, 384);
57
+ }).pipe(Effect.mapError((cause) => new XaiAuthStoreError({
58
+ reason: "WriteFailed",
59
+ message: `Failed to write the auth store at ${path}`,
60
+ cause
61
+ })));
62
+ const load = Effect.gen(function* () {
63
+ const document = yield* readDocument;
64
+ const entry = document[providerId];
65
+ if (entry === undefined)
66
+ return Option.none();
67
+ const token = decodeToken(entry);
68
+ if (Option.isNone(token)) {
69
+ yield* Effect.logWarning(`Ignoring invalid "${providerId}" entry in ${path}`);
70
+ }
71
+ return token;
72
+ }).pipe(Effect.withSpan("fold.xaiAuthStore.load"));
73
+ const save = (token) => Effect.gen(function* () {
74
+ const document = yield* readDocument;
75
+ yield* writeDocument({ ...document, [providerId]: encodeToken(token) });
76
+ return token;
77
+ }).pipe(Effect.withSpan("fold.xaiAuthStore.save"));
78
+ const clear = Effect.gen(function* () {
79
+ const document = yield* readDocument;
80
+ if (document[providerId] === undefined)
81
+ return;
82
+ const { [providerId]: _removed, ...rest } = document;
83
+ yield* writeDocument(rest);
84
+ }).pipe(Effect.withSpan("fold.xaiAuthStore.clear"));
85
+ return { path, load, save, clear };
86
+ };
87
+ // packages/fold-xai/src/OAuthFlows.ts
88
+ import { createServer } from "node:http";
89
+ import { Clock, Deferred, Duration, Effect as Effect2, Schedule, Schema as Schema2 } from "effect";
90
+ import { HttpClient, HttpClientRequest, HttpClientResponse } from "effect/unstable/http";
91
+ var XAI_CLIENT_ID = "b1a00492-073a-47ea-816f-4c329264a828";
92
+ var XAI_ISSUER = "https://auth.x.ai";
93
+ var XAI_SCOPE = "openid profile email offline_access grok-cli:access api:access";
94
+ var XAI_BROWSER_PORT = 56121;
95
+ var XAI_BROWSER_REDIRECT_URI = `http://127.0.0.1:${XAI_BROWSER_PORT}/callback`;
96
+ var TOKEN_PATH = "/oauth2/token";
97
+ var DEVICE_PATH = "/oauth2/device/code";
98
+ var DEVICE_GRANT = "urn:ietf:params:oauth:grant-type:device_code";
99
+ var DEFAULT_EXPIRY_SECONDS = 3600;
100
+ var DEFAULT_DEVICE_EXPIRY_SECONDS = 300;
101
+ var DEFAULT_POLL_SECONDS = 5;
102
+ var POLL_MARGIN_MS = 3000;
103
+
104
+ class XaiAuthError extends Schema2.TaggedErrorClass()("XaiAuthError", {
105
+ reason: Schema2.Literals([
106
+ "NotAuthenticated",
107
+ "RefreshFailed",
108
+ "TokenExchangeFailed",
109
+ "DeviceFlowFailed",
110
+ "BrowserFlowFailed",
111
+ "StoreFailed"
112
+ ]),
113
+ message: Schema2.String,
114
+ cause: Schema2.optional(Schema2.Defect())
115
+ }) {
116
+ }
117
+ var TokenResponse = Schema2.Struct({
118
+ access_token: Schema2.String,
119
+ refresh_token: Schema2.optional(Schema2.String),
120
+ expires_in: Schema2.optional(Schema2.Number)
121
+ });
122
+ var DeviceResponse = Schema2.Struct({
123
+ device_code: Schema2.String,
124
+ user_code: Schema2.String,
125
+ verification_uri: Schema2.String,
126
+ verification_uri_complete: Schema2.optional(Schema2.String),
127
+ expires_in: Schema2.optional(Schema2.Number),
128
+ interval: Schema2.optional(Schema2.Number)
129
+ });
130
+ var DeviceError = Schema2.Struct({
131
+ error: Schema2.optional(Schema2.String),
132
+ error_description: Schema2.optional(Schema2.String)
133
+ });
134
+ var failure = (reason, message, cause) => new XaiAuthError({ reason, message, ...cause === undefined ? {} : { cause } });
135
+ var tokenData = (payload, fallbackRefresh) => Effect2.map(Clock.currentTimeMillis, (now) => new XaiTokenData({
136
+ type: "oauth",
137
+ access: payload.access_token,
138
+ refresh: payload.refresh_token ?? fallbackRefresh ?? "",
139
+ expires: now + (payload.expires_in ?? DEFAULT_EXPIRY_SECONDS) * 1000
140
+ }));
141
+ var makeXaiIssuerClient = (client) => client.pipe(HttpClient.mapRequest(HttpClientRequest.prependUrl(XAI_ISSUER)), HttpClient.filterStatusOk, HttpClient.retryTransient({
142
+ times: 5,
143
+ schedule: Schedule.exponential(150).pipe(Schedule.either(Schedule.spaced(5000)))
144
+ }));
145
+ var decodeToken2 = (response, reason, message, fallback) => HttpClientResponse.schemaBodyJson(TokenResponse)(response).pipe(Effect2.mapError((cause) => failure(reason, message, cause)), Effect2.flatMap((payload) => tokenData(payload, fallback)));
146
+ var refreshXaiAccessToken = Effect2.fn("fold.xaiAuth.refresh")(function* (client, refresh) {
147
+ const response = yield* HttpClientRequest.post(TOKEN_PATH).pipe(HttpClientRequest.bodyUrlParams({
148
+ grant_type: "refresh_token",
149
+ refresh_token: refresh,
150
+ client_id: XAI_CLIENT_ID
151
+ }), client.execute, Effect2.mapError((cause) => failure("RefreshFailed", "Failed to refresh the xAI access token", cause)));
152
+ return yield* decodeToken2(response, "RefreshFailed", "Failed to decode the xAI refresh response", refresh);
153
+ });
154
+ var exchangeCode = Effect2.fn("fold.xaiAuth.exchange")(function* (client, code, verifier) {
155
+ const response = yield* HttpClientRequest.post(TOKEN_PATH).pipe(HttpClientRequest.bodyUrlParams({
156
+ grant_type: "authorization_code",
157
+ code,
158
+ redirect_uri: XAI_BROWSER_REDIRECT_URI,
159
+ client_id: XAI_CLIENT_ID,
160
+ code_verifier: verifier
161
+ }), client.execute, Effect2.mapError((cause) => failure("TokenExchangeFailed", "Failed to exchange the xAI authorization code", cause)));
162
+ return yield* decodeToken2(response, "TokenExchangeFailed", "Failed to decode the xAI token response");
163
+ });
164
+ var runXaiDeviceFlow = Effect2.fn("fold.xaiAuth.deviceFlow")(function* (options) {
165
+ const response = yield* HttpClientRequest.post(DEVICE_PATH).pipe(HttpClientRequest.bodyUrlParams({ client_id: XAI_CLIENT_ID, scope: XAI_SCOPE }), options.client.execute, Effect2.mapError((cause) => failure("DeviceFlowFailed", "Failed to request an xAI device code", cause)));
166
+ const device = yield* HttpClientResponse.schemaBodyJson(DeviceResponse)(response).pipe(Effect2.mapError((cause) => failure("DeviceFlowFailed", "Failed to decode the xAI device response", cause)));
167
+ yield* options.onCode({
168
+ verificationUri: device.verification_uri,
169
+ userCode: device.user_code,
170
+ browserUrl: device.verification_uri_complete ?? device.verification_uri
171
+ });
172
+ const started = yield* Clock.currentTimeMillis;
173
+ const deadline = started + (device.expires_in ?? DEFAULT_DEVICE_EXPIRY_SECONDS) * 1000;
174
+ let delayMs = Math.max(device.interval ?? DEFAULT_POLL_SECONDS, 1) * 1000;
175
+ while ((yield* Clock.currentTimeMillis) < deadline) {
176
+ const poll = HttpClientRequest.post(TOKEN_PATH).pipe(HttpClientRequest.bodyUrlParams({
177
+ grant_type: DEVICE_GRANT,
178
+ client_id: XAI_CLIENT_ID,
179
+ device_code: device.device_code
180
+ }), options.client.execute, Effect2.result);
181
+ const result = yield* poll;
182
+ if (result._tag === "Success")
183
+ return yield* decodeToken2(result.success, "DeviceFlowFailed", "Failed to decode the xAI device token");
184
+ const body = result.failure.response === undefined ? {} : yield* HttpClientResponse.schemaBodyJson(DeviceError)(result.failure.response).pipe(Effect2.orElseSucceed(() => ({})));
185
+ if (body.error === "access_denied" || body.error === "authorization_denied")
186
+ return yield* failure("DeviceFlowFailed", "xAI device authorization was denied");
187
+ if (body.error === "expired_token")
188
+ return yield* failure("DeviceFlowFailed", "xAI device code expired");
189
+ if (body.error !== "authorization_pending" && body.error !== "slow_down") {
190
+ return yield* failure("DeviceFlowFailed", body.error_description ?? body.error ?? "xAI device token exchange failed");
191
+ }
192
+ if (body.error === "slow_down")
193
+ delayMs += 5000;
194
+ yield* Effect2.sleep(Duration.millis(delayMs + POLL_MARGIN_MS));
195
+ }
196
+ return yield* failure("DeviceFlowFailed", "xAI device authorization timed out");
197
+ });
198
+ var CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~";
199
+ var random = (length) => Array.from(crypto.getRandomValues(new Uint8Array(length))).map((byte) => CHARS[byte % CHARS.length]).join("");
200
+ var base64Url = (buffer) => Buffer.from(buffer).toString("base64url");
201
+ var generateXaiPkce = Effect2.promise(async () => {
202
+ const verifier = random(64);
203
+ return { verifier, challenge: base64Url(await crypto.subtle.digest("SHA-256", new TextEncoder().encode(verifier))) };
204
+ });
205
+ var buildXaiAuthorizeUrl = (pkce, state, nonce) => {
206
+ const query = new URLSearchParams({
207
+ response_type: "code",
208
+ client_id: XAI_CLIENT_ID,
209
+ redirect_uri: XAI_BROWSER_REDIRECT_URI,
210
+ scope: XAI_SCOPE,
211
+ code_challenge: pkce.challenge,
212
+ code_challenge_method: "S256",
213
+ state,
214
+ nonce,
215
+ plan: "generic",
216
+ referrer: "fold"
217
+ });
218
+ return `${XAI_ISSUER}/oauth2/authorize?${query.toString()}`;
219
+ };
220
+ var runXaiBrowserFlow = Effect2.fn("fold.xaiAuth.browserFlow")(function* (options) {
221
+ const pkce = yield* generateXaiPkce;
222
+ const state = base64Url(crypto.getRandomValues(new Uint8Array(32)).buffer);
223
+ const nonce = base64Url(crypto.getRandomValues(new Uint8Array(32)).buffer);
224
+ const code = yield* Effect2.scoped(Effect2.gen(function* () {
225
+ const callback = yield* Deferred.make();
226
+ yield* Effect2.acquireRelease(Effect2.tryPromise({
227
+ try: () => new Promise((resolve, reject) => {
228
+ const server = createServer((request, response) => {
229
+ const url = new URL(request.url ?? "/", XAI_BROWSER_REDIRECT_URI);
230
+ const fail = (message, status = 400) => {
231
+ Effect2.runSync(Deferred.fail(callback, failure("BrowserFlowFailed", message)));
232
+ response.writeHead(status, { "Content-Type": "text/plain" });
233
+ response.end(message);
234
+ };
235
+ if (url.pathname !== "/callback")
236
+ return fail("Not found", 404);
237
+ const oauthError = url.searchParams.get("error");
238
+ if (oauthError !== null)
239
+ return fail(url.searchParams.get("error_description") ?? oauthError, 200);
240
+ if (url.searchParams.get("state") !== state)
241
+ return fail("Invalid state - potential CSRF attack");
242
+ const received = url.searchParams.get("code");
243
+ if (received === null)
244
+ return fail("Missing authorization code");
245
+ Effect2.runSync(Deferred.succeed(callback, received));
246
+ response.writeHead(200, { "Content-Type": "text/plain" });
247
+ response.end("xAI authorization successful. Return to fold.");
248
+ });
249
+ server.once("error", reject);
250
+ server.listen(XAI_BROWSER_PORT, "127.0.0.1", () => resolve(server));
251
+ }),
252
+ catch: (cause) => failure("BrowserFlowFailed", `Failed to start callback server on port ${XAI_BROWSER_PORT}`, cause)
253
+ }), (server) => Effect2.promise(() => new Promise((resolve) => server.close(() => resolve()))));
254
+ yield* options.onUrl(buildXaiAuthorizeUrl(pkce, state, nonce));
255
+ return yield* Deferred.await(callback).pipe(Effect2.timeoutOrElse({
256
+ duration: Duration.millis(options.timeoutMs ?? 300000),
257
+ orElse: () => Effect2.fail(failure("BrowserFlowFailed", "OAuth callback timed out"))
258
+ }));
259
+ }));
260
+ return yield* exchangeCode(options.client, code, pkce.verifier);
261
+ });
262
+ // packages/fold-xai/src/XaiAuth.ts
263
+ import { Clock as Clock2, Context as Context2, Effect as Effect3, Option as Option2, Semaphore } from "effect";
264
+ import { HttpClient as HttpClient2, HttpClientError, HttpClientRequest as HttpClientRequest2 } from "effect/unstable/http";
265
+ class XaiAuth extends Context2.Service()("fold/XaiAuth") {
266
+ }
267
+ var devicePrompt = (prompt) => Effect3.log(`Open ${prompt.verificationUri} and enter code: ${prompt.userCode}`);
268
+ var browserPrompt = (url) => Effect3.log(`Open this URL to authenticate xAI:
269
+ ${url}`);
270
+ var makeXaiAuth = Effect3.fnUntraced(function* (options) {
271
+ const store = options?.store ?? makeXaiAuthStore();
272
+ const client = makeXaiIssuerClient(yield* HttpClient2.HttpClient);
273
+ const semaphore = Semaphore.makeUnsafe(1);
274
+ let current = yield* store.load;
275
+ const storeError = (cause) => new XaiAuthError({
276
+ reason: "StoreFailed",
277
+ message: `Failed to persist xAI credentials to ${store.path}`,
278
+ cause
279
+ });
280
+ const save = (token) => store.save(token).pipe(Effect3.mapError(storeError), Effect3.tap(() => Effect3.sync(() => {
281
+ current = Option2.some(token);
282
+ })));
283
+ const get = Effect3.uninterruptibleMask(Effect3.fnUntraced(function* (restore) {
284
+ const now = yield* Clock2.currentTimeMillis;
285
+ if (Option2.isSome(current) && !current.value.isExpired(now))
286
+ return current.value;
287
+ if (Option2.isNone(current))
288
+ return yield* new XaiAuthError({
289
+ reason: "NotAuthenticated",
290
+ message: `No xAI OAuth credentials found in ${store.path}`
291
+ });
292
+ return yield* restore(refreshXaiAccessToken(client, current.value.refresh)).pipe(Effect3.flatMap(save));
293
+ }));
294
+ const run = (flow) => Effect3.uninterruptibleMask((restore) => restore(flow).pipe(Effect3.flatMap(save)));
295
+ return {
296
+ get: semaphore.withPermit(get).pipe(Effect3.withSpan("fold.xaiAuth.get")),
297
+ authenticateDevice: semaphore.withPermit(run(runXaiDeviceFlow({ client, onCode: options?.onDeviceCode ?? devicePrompt }))).pipe(Effect3.withSpan("fold.xaiAuth.authenticateDevice")),
298
+ authenticateBrowser: semaphore.withPermit(run(runXaiBrowserFlow({ client, onUrl: options?.onBrowserUrl ?? browserPrompt, ...options?.browser }))).pipe(Effect3.withSpan("fold.xaiAuth.authenticateBrowser")),
299
+ logout: semaphore.withPermit(store.clear.pipe(Effect3.mapError(storeError), Effect3.tap(() => Effect3.sync(() => {
300
+ current = Option2.none();
301
+ })))).pipe(Effect3.withSpan("fold.xaiAuth.logout"))
302
+ };
303
+ });
304
+ var withXaiAuth = (client, auth) => client.pipe(HttpClient2.mapRequestEffect((request) => auth.get.pipe(Effect3.map((token) => request.pipe(HttpClientRequest2.bearerToken(token.access), HttpClientRequest2.setHeader("User-Agent", "fold/xai-oauth"))), Effect3.mapError((cause) => new HttpClientError.HttpClientError({
305
+ reason: new HttpClientError.TransportError({
306
+ request,
307
+ cause,
308
+ description: `xAI authentication failed: ${cause.message}`
309
+ })
310
+ })))));
311
+ // packages/fold-xai/src/XaiModel.ts
312
+ import { OpenAiClient, OpenAiLanguageModel } from "@effect/ai-openai";
313
+ import { customModel, resolveOpenAiReasoning } from "@humanlayer/fold-core";
314
+ import { Context as Context3, Effect as Effect4, Layer as Layer2 } from "effect";
315
+ import { FetchHttpClient, HttpClient as HttpClient3 } from "effect/unstable/http";
316
+ var XAI_API_URL = "https://api.x.ai/v1";
317
+ var DEFAULT_XAI_MODEL_ID = "grok-4.5";
318
+ var makeXaiLanguageModel = (options) => Effect4.gen(function* () {
319
+ const httpContext = yield* Layer2.build(FetchHttpClient.layer);
320
+ const base = Context3.get(httpContext, HttpClient3.HttpClient);
321
+ const auth = yield* makeXaiAuth(options.store === undefined ? {} : { store: options.store }).pipe(Effect4.provideService(HttpClient3.HttpClient, base));
322
+ const clientContext = yield* Layer2.build(OpenAiClient.layer({ apiUrl: options.apiUrl ?? XAI_API_URL })).pipe(Effect4.provideService(HttpClient3.HttpClient, withXaiAuth(base, auth)));
323
+ return yield* OpenAiLanguageModel.make({ model: options.model ?? DEFAULT_XAI_MODEL_ID }).pipe(Effect4.provideService(OpenAiClient.OpenAiClient, Context3.get(clientContext, OpenAiClient.OpenAiClient)));
324
+ });
325
+ var xaiModel = (options = {}) => {
326
+ const level = options.reasoning ?? "off";
327
+ return customModel({
328
+ activeModel: {
329
+ providerId: options.providerId ?? "xai",
330
+ providerKind: "openai-compatible",
331
+ modelId: options.model ?? DEFAULT_XAI_MODEL_ID,
332
+ role: null,
333
+ requestedReasoningLevel: level,
334
+ reasoning: resolveOpenAiReasoning(level)
335
+ },
336
+ make: makeXaiLanguageModel(options)
337
+ });
338
+ };
339
+ export {
340
+ xaiModel,
341
+ withXaiAuth,
342
+ runXaiDeviceFlow,
343
+ runXaiBrowserFlow,
344
+ refreshXaiAccessToken,
345
+ makeXaiLanguageModel,
346
+ makeXaiIssuerClient,
347
+ makeXaiAuthStore,
348
+ makeXaiAuth,
349
+ generateXaiPkce,
350
+ defaultNodeFileSystem,
351
+ defaultAuthStorePath,
352
+ buildXaiAuthorizeUrl,
353
+ XaiTokenData,
354
+ XaiAuthStoreError,
355
+ XaiAuthError,
356
+ XaiAuth,
357
+ XAI_SCOPE,
358
+ XAI_ISSUER,
359
+ XAI_CLIENT_ID,
360
+ XAI_BROWSER_REDIRECT_URI,
361
+ XAI_BROWSER_PORT,
362
+ XAI_API_URL,
363
+ TOKEN_EXPIRY_BUFFER_MS,
364
+ DEFAULT_XAI_MODEL_ID
365
+ };
366
+
367
+ //# debugId=166BE3861ABF0E6164756E2164756E21
@@ -0,0 +1,13 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/AuthStore.ts", "../src/OAuthFlows.ts", "../src/XaiAuth.ts", "../src/XaiModel.ts"],
4
+ "sourcesContent": [
5
+ "/**\n * File-backed Xai credential store: one provider-keyed JSON document (default `~/.fold/auth.json`)\n * holding OAuth tokens only (D23). Field names are agentlayer-compatible (`access`/`refresh`/`expires`/\n * `accountId`), so existing entries copy across verbatim. Reads degrade to \"no credentials\" on missing\n * or malformed data - the document may hold other providers' entries, so a bad xai entry is skipped,\n * never clobbered; writes merge over the existing document and force `0600` permissions. The FileSystem\n * is a default-or-override seam like fold-agent tools: tests pass an implementation, everyone else gets\n * the Node platform filesystem.\n */\nimport { homedir } from 'node:os'\nimport { dirname, join } from 'node:path'\n\nimport * as NodeFileSystem from '@effect/platform-node/NodeFileSystem'\nimport { Context, Effect, FileSystem, Layer, Option, Schema } from 'effect'\n\n/** Milliseconds before nominal expiry a token is already treated as expired (clanka parity). */\nexport const TOKEN_EXPIRY_BUFFER_MS = 30_000\n\n/** Default location of the fold auth store. */\nexport const defaultAuthStorePath = (): string => join(homedir(), '.fold', 'auth.json')\n\n/** One stored Xai OAuth credential. `expires` is epoch milliseconds for the access token. */\nexport class XaiTokenData extends Schema.Class<XaiTokenData>('fold/XaiTokenData')({\n\ttype: Schema.Literal('oauth'),\n\taccess: Schema.String,\n\trefresh: Schema.String,\n\texpires: Schema.Number,\n\taccountId: Schema.optional(Schema.String),\n}) {\n\t/** True when the token is expired - or within the safety buffer of expiring - at `nowMs`. */\n\tisExpired(nowMs: number): boolean {\n\t\treturn this.expires < nowMs + TOKEN_EXPIRY_BUFFER_MS\n\t}\n}\n\n/** Auth store persistence failure (reads never fail - they degrade to absent credentials). */\nexport class XaiAuthStoreError extends Schema.TaggedErrorClass<XaiAuthStoreError>()('XaiAuthStoreError', {\n\treason: Schema.Literals(['WriteFailed']),\n\tmessage: Schema.String,\n\tcause: Schema.optional(Schema.Defect()),\n}) {}\n\n/** The credential store one XaiAuth instance persists through. */\nexport type XaiAuthStore = {\n\t/** Absolute path of the backing JSON document (used in error messages and guidance). */\n\treadonly path: string\n\treadonly load: Effect.Effect<Option.Option<XaiTokenData>>\n\treadonly save: (token: XaiTokenData) => Effect.Effect<XaiTokenData, XaiAuthStoreError>\n\treadonly clear: Effect.Effect<void, XaiAuthStoreError>\n}\n\n/** Options for {@link makeXaiAuthStore}. */\nexport type MakeXaiAuthStoreOptions = {\n\t/** Path of the auth document. Defaults to `~/.fold/auth.json`. */\n\treadonly path?: string\n\t/** Key of this provider's entry in the document. Defaults to `xai`. */\n\treadonly providerId?: string\n\t/** FileSystem implementation override. Defaults to the Node platform filesystem. */\n\treadonly fileSystem?: FileSystem.FileSystem\n}\n\nlet nodeFileSystem: FileSystem.FileSystem | null = null\n\n/** The process-wide Node FileSystem service, built lazily once (layer construction is synchronous). */\nexport const defaultNodeFileSystem = (): FileSystem.FileSystem => {\n\tif (nodeFileSystem === null) {\n\t\tnodeFileSystem = Effect.runSync(\n\t\t\tEffect.scoped(\n\t\t\t\tLayer.build(NodeFileSystem.layer).pipe(\n\t\t\t\t\tEffect.map((context) => Context.get(context, FileSystem.FileSystem)),\n\t\t\t\t),\n\t\t\t),\n\t\t)\n\t}\n\n\treturn nodeFileSystem\n}\n\n/** The auth document is provider-keyed; entries other than ours are opaque and preserved verbatim. */\nconst AuthDocument = Schema.Record(Schema.String, Schema.Unknown)\n\nconst decodeDocument = Schema.decodeUnknownOption(Schema.fromJsonString(AuthDocument))\n\nconst decodeToken = Schema.decodeUnknownOption(XaiTokenData)\n\nconst encodeToken = (token: XaiTokenData): Record<string, unknown> => ({\n\ttype: token.type,\n\taccess: token.access,\n\trefresh: token.refresh,\n\texpires: token.expires,\n\t...(token.accountId === undefined ? {} : { accountId: token.accountId }),\n})\n\n/** Build a file-backed Xai credential store. */\nexport const makeXaiAuthStore = (options?: MakeXaiAuthStoreOptions): XaiAuthStore => {\n\tconst fs = options?.fileSystem ?? defaultNodeFileSystem()\n\tconst path = options?.path ?? defaultAuthStorePath()\n\tconst providerId = options?.providerId ?? 'xai'\n\n\tconst readDocument: Effect.Effect<Record<string, unknown>> = fs.readFileString(path).pipe(\n\t\tEffect.flatMap((content) => {\n\t\t\tconst document = decodeDocument(content)\n\t\t\treturn Option.isSome(document)\n\t\t\t\t? Effect.succeed(document.value)\n\t\t\t\t: Effect.logWarning(`Auth store ${path} is not a JSON object; treating it as empty`).pipe(\n\t\t\t\t\t\tEffect.as<Record<string, unknown>>({}),\n\t\t\t\t\t)\n\t\t}),\n\t\t// A missing (or unreadable) document is simply \"no credentials stored yet\".\n\t\tEffect.catch(() => Effect.succeed<Record<string, unknown>>({})),\n\t)\n\n\tconst writeDocument = (document: Record<string, unknown>): Effect.Effect<void, XaiAuthStoreError> =>\n\t\tEffect.gen(function* () {\n\t\t\tyield* fs.makeDirectory(dirname(path), { recursive: true })\n\t\t\tyield* fs.writeFileString(path, `${JSON.stringify(document, null, 2)}\\n`, { mode: 0o600 })\n\t\t\t// writeFileString's mode only applies on creation; force 0600 on pre-existing documents too.\n\t\t\tyield* fs.chmod(path, 0o600)\n\t\t}).pipe(\n\t\t\tEffect.mapError(\n\t\t\t\t(cause) =>\n\t\t\t\t\tnew XaiAuthStoreError({\n\t\t\t\t\t\treason: 'WriteFailed',\n\t\t\t\t\t\tmessage: `Failed to write the auth store at ${path}`,\n\t\t\t\t\t\tcause,\n\t\t\t\t\t}),\n\t\t\t),\n\t\t)\n\n\tconst load = Effect.gen(function* () {\n\t\tconst document = yield* readDocument\n\t\tconst entry = document[providerId]\n\t\tif (entry === undefined) return Option.none<XaiTokenData>()\n\n\t\tconst token = decodeToken(entry)\n\t\tif (Option.isNone(token)) {\n\t\t\tyield* Effect.logWarning(`Ignoring invalid \"${providerId}\" entry in ${path}`)\n\t\t}\n\n\t\treturn token\n\t}).pipe(Effect.withSpan('fold.xaiAuthStore.load'))\n\n\tconst save = (token: XaiTokenData) =>\n\t\tEffect.gen(function* () {\n\t\t\tconst document = yield* readDocument\n\t\t\tyield* writeDocument({ ...document, [providerId]: encodeToken(token) })\n\t\t\treturn token\n\t\t}).pipe(Effect.withSpan('fold.xaiAuthStore.save'))\n\n\tconst clear = Effect.gen(function* () {\n\t\tconst document = yield* readDocument\n\t\tif (document[providerId] === undefined) return\n\t\tconst { [providerId]: _removed, ...rest } = document\n\t\tyield* writeDocument(rest)\n\t}).pipe(Effect.withSpan('fold.xaiAuthStore.clear'))\n\n\treturn { path, load, save, clear }\n}\n",
6
+ "/** xAI OAuth wire protocol, adapted from opencode's xAI plugin (MIT; see LICENSE-opencode). */\nimport { createServer } from 'node:http'\nimport type { Server } from 'node:http'\n\nimport { Clock, Deferred, Duration, Effect, Schedule, Schema } from 'effect'\nimport { HttpClient, HttpClientRequest, HttpClientResponse } from 'effect/unstable/http'\n\nimport { XaiTokenData } from './AuthStore'\n\nexport const XAI_CLIENT_ID = 'b1a00492-073a-47ea-816f-4c329264a828'\nexport const XAI_ISSUER = 'https://auth.x.ai'\nexport const XAI_SCOPE = 'openid profile email offline_access grok-cli:access api:access'\nexport const XAI_BROWSER_PORT = 56121\nexport const XAI_BROWSER_REDIRECT_URI = `http://127.0.0.1:${XAI_BROWSER_PORT}/callback`\n\nconst TOKEN_PATH = '/oauth2/token'\nconst DEVICE_PATH = '/oauth2/device/code'\nconst DEVICE_GRANT = 'urn:ietf:params:oauth:grant-type:device_code'\nconst DEFAULT_EXPIRY_SECONDS = 3600\nconst DEFAULT_DEVICE_EXPIRY_SECONDS = 300\nconst DEFAULT_POLL_SECONDS = 5\nconst POLL_MARGIN_MS = 3000\n\nexport class XaiAuthError extends Schema.TaggedErrorClass<XaiAuthError>()('XaiAuthError', {\n\treason: Schema.Literals([\n\t\t'NotAuthenticated',\n\t\t'RefreshFailed',\n\t\t'TokenExchangeFailed',\n\t\t'DeviceFlowFailed',\n\t\t'BrowserFlowFailed',\n\t\t'StoreFailed',\n\t]),\n\tmessage: Schema.String,\n\tcause: Schema.optional(Schema.Defect()),\n}) {}\n\nconst TokenResponse = Schema.Struct({\n\taccess_token: Schema.String,\n\trefresh_token: Schema.optional(Schema.String),\n\texpires_in: Schema.optional(Schema.Number),\n})\n\nconst DeviceResponse = Schema.Struct({\n\tdevice_code: Schema.String,\n\tuser_code: Schema.String,\n\tverification_uri: Schema.String,\n\tverification_uri_complete: Schema.optional(Schema.String),\n\texpires_in: Schema.optional(Schema.Number),\n\tinterval: Schema.optional(Schema.Number),\n})\n\nconst DeviceError = Schema.Struct({\n\terror: Schema.optional(Schema.String),\n\terror_description: Schema.optional(Schema.String),\n})\n\nconst failure = (reason: XaiAuthError['reason'], message: string, cause?: unknown) =>\n\tnew XaiAuthError({ reason, message, ...(cause === undefined ? {} : { cause }) })\n\nconst tokenData = (payload: typeof TokenResponse.Type, fallbackRefresh?: string) =>\n\tEffect.map(\n\t\tClock.currentTimeMillis,\n\t\t(now) =>\n\t\t\tnew XaiTokenData({\n\t\t\t\ttype: 'oauth',\n\t\t\t\taccess: payload.access_token,\n\t\t\t\trefresh: payload.refresh_token ?? fallbackRefresh ?? '',\n\t\t\t\texpires: now + (payload.expires_in ?? DEFAULT_EXPIRY_SECONDS) * 1000,\n\t\t\t}),\n\t)\n\n/** Scope and harden an HttpClient for xAI's OAuth issuer. */\nexport const makeXaiIssuerClient = (client: HttpClient.HttpClient): HttpClient.HttpClient =>\n\tclient.pipe(\n\t\tHttpClient.mapRequest(HttpClientRequest.prependUrl(XAI_ISSUER)),\n\t\tHttpClient.filterStatusOk,\n\t\tHttpClient.retryTransient({\n\t\t\ttimes: 5,\n\t\t\tschedule: Schedule.exponential(150).pipe(Schedule.either(Schedule.spaced(5000))),\n\t\t}),\n\t)\n\nconst decodeToken = (\n\tresponse: HttpClientResponse.HttpClientResponse,\n\treason: XaiAuthError['reason'],\n\tmessage: string,\n\tfallback?: string,\n) =>\n\tHttpClientResponse.schemaBodyJson(TokenResponse)(response).pipe(\n\t\tEffect.mapError((cause) => failure(reason, message, cause)),\n\t\tEffect.flatMap((payload) => tokenData(payload, fallback)),\n\t)\n\n/** Refresh a stored xAI OAuth credential, preserving rotating or omitted refresh tokens. */\nexport const refreshXaiAccessToken = Effect.fn('fold.xaiAuth.refresh')(function* (\n\tclient: HttpClient.HttpClient,\n\trefresh: string,\n) {\n\tconst response = yield* HttpClientRequest.post(TOKEN_PATH).pipe(\n\t\tHttpClientRequest.bodyUrlParams({\n\t\t\tgrant_type: 'refresh_token',\n\t\t\trefresh_token: refresh,\n\t\t\tclient_id: XAI_CLIENT_ID,\n\t\t}),\n\t\tclient.execute,\n\t\tEffect.mapError((cause) => failure('RefreshFailed', 'Failed to refresh the xAI access token', cause)),\n\t)\n\treturn yield* decodeToken(response, 'RefreshFailed', 'Failed to decode the xAI refresh response', refresh)\n})\n\nconst exchangeCode = Effect.fn('fold.xaiAuth.exchange')(function* (\n\tclient: HttpClient.HttpClient,\n\tcode: string,\n\tverifier: string,\n) {\n\tconst response = yield* HttpClientRequest.post(TOKEN_PATH).pipe(\n\t\tHttpClientRequest.bodyUrlParams({\n\t\t\tgrant_type: 'authorization_code',\n\t\t\tcode,\n\t\t\tredirect_uri: XAI_BROWSER_REDIRECT_URI,\n\t\t\tclient_id: XAI_CLIENT_ID,\n\t\t\tcode_verifier: verifier,\n\t\t}),\n\t\tclient.execute,\n\t\tEffect.mapError((cause) =>\n\t\t\tfailure('TokenExchangeFailed', 'Failed to exchange the xAI authorization code', cause),\n\t\t),\n\t)\n\treturn yield* decodeToken(response, 'TokenExchangeFailed', 'Failed to decode the xAI token response')\n})\n\nexport type XaiDevicePrompt = {\n\treadonly verificationUri: string\n\treadonly userCode: string\n\treadonly browserUrl: string\n}\nexport type XaiDeviceFlowOptions = {\n\treadonly client: HttpClient.HttpClient\n\treadonly onCode: (prompt: XaiDevicePrompt) => Effect.Effect<void>\n}\n\n/** Run RFC 8628 device authorization, including pending/slow_down backoff and expiry. */\nexport const runXaiDeviceFlow = Effect.fn('fold.xaiAuth.deviceFlow')(function* (options: XaiDeviceFlowOptions) {\n\tconst response = yield* HttpClientRequest.post(DEVICE_PATH).pipe(\n\t\tHttpClientRequest.bodyUrlParams({ client_id: XAI_CLIENT_ID, scope: XAI_SCOPE }),\n\t\toptions.client.execute,\n\t\tEffect.mapError((cause) => failure('DeviceFlowFailed', 'Failed to request an xAI device code', cause)),\n\t)\n\tconst device = yield* HttpClientResponse.schemaBodyJson(DeviceResponse)(response).pipe(\n\t\tEffect.mapError((cause) => failure('DeviceFlowFailed', 'Failed to decode the xAI device response', cause)),\n\t)\n\tyield* options.onCode({\n\t\tverificationUri: device.verification_uri,\n\t\tuserCode: device.user_code,\n\t\tbrowserUrl: device.verification_uri_complete ?? device.verification_uri,\n\t})\n\n\tconst started = yield* Clock.currentTimeMillis\n\tconst deadline = started + (device.expires_in ?? DEFAULT_DEVICE_EXPIRY_SECONDS) * 1000\n\tlet delayMs = Math.max(device.interval ?? DEFAULT_POLL_SECONDS, 1) * 1000\n\twhile ((yield* Clock.currentTimeMillis) < deadline) {\n\t\tconst poll = HttpClientRequest.post(TOKEN_PATH).pipe(\n\t\t\tHttpClientRequest.bodyUrlParams({\n\t\t\t\tgrant_type: DEVICE_GRANT,\n\t\t\t\tclient_id: XAI_CLIENT_ID,\n\t\t\t\tdevice_code: device.device_code,\n\t\t\t}),\n\t\t\toptions.client.execute,\n\t\t\tEffect.result,\n\t\t)\n\t\tconst result = yield* poll\n\t\tif (result._tag === 'Success')\n\t\t\treturn yield* decodeToken(result.success, 'DeviceFlowFailed', 'Failed to decode the xAI device token')\n\t\tconst body: typeof DeviceError.Type =\n\t\t\tresult.failure.response === undefined\n\t\t\t\t? {}\n\t\t\t\t: yield* HttpClientResponse.schemaBodyJson(DeviceError)(result.failure.response).pipe(\n\t\t\t\t\t\tEffect.orElseSucceed((): typeof DeviceError.Type => ({})),\n\t\t\t\t\t)\n\t\tif (body.error === 'access_denied' || body.error === 'authorization_denied')\n\t\t\treturn yield* failure('DeviceFlowFailed', 'xAI device authorization was denied')\n\t\tif (body.error === 'expired_token') return yield* failure('DeviceFlowFailed', 'xAI device code expired')\n\t\tif (body.error !== 'authorization_pending' && body.error !== 'slow_down') {\n\t\t\treturn yield* failure(\n\t\t\t\t'DeviceFlowFailed',\n\t\t\t\tbody.error_description ?? body.error ?? 'xAI device token exchange failed',\n\t\t\t)\n\t\t}\n\t\tif (body.error === 'slow_down') delayMs += 5000\n\t\tyield* Effect.sleep(Duration.millis(delayMs + POLL_MARGIN_MS))\n\t}\n\treturn yield* failure('DeviceFlowFailed', 'xAI device authorization timed out')\n})\n\nconst CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~'\nconst random = (length: number): string =>\n\tArray.from(crypto.getRandomValues(new Uint8Array(length)))\n\t\t.map((byte) => CHARS[byte % CHARS.length])\n\t\t.join('')\nconst base64Url = (buffer: ArrayBuffer): string => Buffer.from(buffer).toString('base64url')\n\nexport type XaiPkce = { readonly verifier: string; readonly challenge: string }\nexport const generateXaiPkce: Effect.Effect<XaiPkce> = Effect.promise(async () => {\n\tconst verifier = random(64)\n\treturn { verifier, challenge: base64Url(await crypto.subtle.digest('SHA-256', new TextEncoder().encode(verifier))) }\n})\n\n/** Build xAI's registered Grok CLI authorization URL. */\nexport const buildXaiAuthorizeUrl = (pkce: XaiPkce, state: string, nonce: string): string => {\n\tconst query = new URLSearchParams({\n\t\tresponse_type: 'code',\n\t\tclient_id: XAI_CLIENT_ID,\n\t\tredirect_uri: XAI_BROWSER_REDIRECT_URI,\n\t\tscope: XAI_SCOPE,\n\t\tcode_challenge: pkce.challenge,\n\t\tcode_challenge_method: 'S256',\n\t\tstate,\n\t\tnonce,\n\t\tplan: 'generic',\n\t\treferrer: 'fold',\n\t})\n\treturn `${XAI_ISSUER}/oauth2/authorize?${query.toString()}`\n}\n\nexport type XaiBrowserFlowOptions = {\n\treadonly client: HttpClient.HttpClient\n\treadonly onUrl: (url: string) => Effect.Effect<void>\n\treadonly timeoutMs?: number\n}\n\n/** Run browser PKCE on xAI's fixed registered 127.0.0.1:56121 callback. */\nexport const runXaiBrowserFlow = Effect.fn('fold.xaiAuth.browserFlow')(function* (options: XaiBrowserFlowOptions) {\n\tconst pkce = yield* generateXaiPkce\n\tconst state = base64Url(crypto.getRandomValues(new Uint8Array(32)).buffer)\n\tconst nonce = base64Url(crypto.getRandomValues(new Uint8Array(32)).buffer)\n\tconst code = yield* Effect.scoped(\n\t\tEffect.gen(function* () {\n\t\t\tconst callback = yield* Deferred.make<string, XaiAuthError>()\n\t\t\tyield* Effect.acquireRelease(\n\t\t\t\tEffect.tryPromise({\n\t\t\t\t\ttry: () =>\n\t\t\t\t\t\tnew Promise<Server>((resolve, reject) => {\n\t\t\t\t\t\t\tconst server = createServer((request, response) => {\n\t\t\t\t\t\t\t\tconst url = new URL(request.url ?? '/', XAI_BROWSER_REDIRECT_URI)\n\t\t\t\t\t\t\t\tconst fail = (message: string, status = 400) => {\n\t\t\t\t\t\t\t\t\tEffect.runSync(Deferred.fail(callback, failure('BrowserFlowFailed', message)))\n\t\t\t\t\t\t\t\t\tresponse.writeHead(status, { 'Content-Type': 'text/plain' })\n\t\t\t\t\t\t\t\t\tresponse.end(message)\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (url.pathname !== '/callback') return fail('Not found', 404)\n\t\t\t\t\t\t\t\tconst oauthError = url.searchParams.get('error')\n\t\t\t\t\t\t\t\tif (oauthError !== null)\n\t\t\t\t\t\t\t\t\treturn fail(url.searchParams.get('error_description') ?? oauthError, 200)\n\t\t\t\t\t\t\t\tif (url.searchParams.get('state') !== state)\n\t\t\t\t\t\t\t\t\treturn fail('Invalid state - potential CSRF attack')\n\t\t\t\t\t\t\t\tconst received = url.searchParams.get('code')\n\t\t\t\t\t\t\t\tif (received === null) return fail('Missing authorization code')\n\t\t\t\t\t\t\t\tEffect.runSync(Deferred.succeed(callback, received))\n\t\t\t\t\t\t\t\tresponse.writeHead(200, { 'Content-Type': 'text/plain' })\n\t\t\t\t\t\t\t\tresponse.end('xAI authorization successful. Return to fold.')\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\tserver.once('error', reject)\n\t\t\t\t\t\t\tserver.listen(XAI_BROWSER_PORT, '127.0.0.1', () => resolve(server))\n\t\t\t\t\t\t}),\n\t\t\t\t\tcatch: (cause) =>\n\t\t\t\t\t\tfailure(\n\t\t\t\t\t\t\t'BrowserFlowFailed',\n\t\t\t\t\t\t\t`Failed to start callback server on port ${XAI_BROWSER_PORT}`,\n\t\t\t\t\t\t\tcause,\n\t\t\t\t\t\t),\n\t\t\t\t}),\n\t\t\t\t(server) => Effect.promise(() => new Promise<void>((resolve) => server.close(() => resolve()))),\n\t\t\t)\n\t\t\tyield* options.onUrl(buildXaiAuthorizeUrl(pkce, state, nonce))\n\t\t\treturn yield* Deferred.await(callback).pipe(\n\t\t\t\tEffect.timeoutOrElse({\n\t\t\t\t\tduration: Duration.millis(options.timeoutMs ?? 300_000),\n\t\t\t\t\torElse: () => Effect.fail(failure('BrowserFlowFailed', 'OAuth callback timed out')),\n\t\t\t\t}),\n\t\t\t)\n\t\t}),\n\t)\n\treturn yield* exchangeCode(options.client, code, pkce.verifier)\n})\n",
7
+ "/** Persistent, single-flight xAI OAuth credential service and authenticated HTTP decorator. */\nimport { Clock, Context, Effect, Option, Semaphore } from 'effect'\nimport { HttpClient, HttpClientError, HttpClientRequest } from 'effect/unstable/http'\n\nimport type { XaiAuthStore } from './AuthStore'\nimport { makeXaiAuthStore, XaiTokenData } from './AuthStore'\nimport type { XaiBrowserFlowOptions, XaiDevicePrompt } from './OAuthFlows'\nimport {\n\tmakeXaiIssuerClient,\n\trefreshXaiAccessToken,\n\trunXaiBrowserFlow,\n\trunXaiDeviceFlow,\n\tXaiAuthError,\n} from './OAuthFlows'\n\nexport type XaiAuthService = {\n\treadonly get: Effect.Effect<XaiTokenData, XaiAuthError>\n\treadonly authenticateDevice: Effect.Effect<XaiTokenData, XaiAuthError>\n\treadonly authenticateBrowser: Effect.Effect<XaiTokenData, XaiAuthError>\n\treadonly logout: Effect.Effect<void, XaiAuthError>\n}\n\nexport class XaiAuth extends Context.Service<XaiAuth, XaiAuthService>()('fold/XaiAuth') {}\n\nexport type MakeXaiAuthOptions = {\n\treadonly store?: XaiAuthStore\n\treadonly onDeviceCode?: (prompt: XaiDevicePrompt) => Effect.Effect<void>\n\treadonly onBrowserUrl?: (url: string) => Effect.Effect<void>\n\treadonly browser?: Pick<XaiBrowserFlowOptions, 'timeoutMs'>\n}\n\nconst devicePrompt = (prompt: XaiDevicePrompt) =>\n\tEffect.log(`Open ${prompt.verificationUri} and enter code: ${prompt.userCode}`)\nconst browserPrompt = (url: string) => Effect.log(`Open this URL to authenticate xAI:\\n${url}`)\n\n/** Construct xAI auth over the ambient HttpClient. Interactive flows are explicit methods. */\nexport const makeXaiAuth = Effect.fnUntraced(function* (options?: MakeXaiAuthOptions) {\n\tconst store = options?.store ?? makeXaiAuthStore()\n\tconst client = makeXaiIssuerClient(yield* HttpClient.HttpClient)\n\tconst semaphore = Semaphore.makeUnsafe(1)\n\tlet current = yield* store.load\n\tconst storeError = (cause: unknown) =>\n\t\tnew XaiAuthError({\n\t\t\treason: 'StoreFailed',\n\t\t\tmessage: `Failed to persist xAI credentials to ${store.path}`,\n\t\t\tcause,\n\t\t})\n\tconst save = (token: XaiTokenData) =>\n\t\tstore.save(token).pipe(\n\t\t\tEffect.mapError(storeError),\n\t\t\tEffect.tap(() =>\n\t\t\t\tEffect.sync(() => {\n\t\t\t\t\tcurrent = Option.some(token)\n\t\t\t\t}),\n\t\t\t),\n\t\t)\n\tconst get = Effect.uninterruptibleMask(\n\t\tEffect.fnUntraced(function* (restore) {\n\t\t\tconst now = yield* Clock.currentTimeMillis\n\t\t\tif (Option.isSome(current) && !current.value.isExpired(now)) return current.value\n\t\t\tif (Option.isNone(current))\n\t\t\t\treturn yield* new XaiAuthError({\n\t\t\t\t\treason: 'NotAuthenticated',\n\t\t\t\t\tmessage: `No xAI OAuth credentials found in ${store.path}`,\n\t\t\t\t})\n\t\t\treturn yield* restore(refreshXaiAccessToken(client, current.value.refresh)).pipe(Effect.flatMap(save))\n\t\t}),\n\t)\n\tconst run = (flow: Effect.Effect<XaiTokenData, XaiAuthError>) =>\n\t\tEffect.uninterruptibleMask((restore) => restore(flow).pipe(Effect.flatMap(save)))\n\treturn {\n\t\tget: semaphore.withPermit(get).pipe(Effect.withSpan('fold.xaiAuth.get')),\n\t\tauthenticateDevice: semaphore\n\t\t\t.withPermit(run(runXaiDeviceFlow({ client, onCode: options?.onDeviceCode ?? devicePrompt })))\n\t\t\t.pipe(Effect.withSpan('fold.xaiAuth.authenticateDevice')),\n\t\tauthenticateBrowser: semaphore\n\t\t\t.withPermit(\n\t\t\t\trun(runXaiBrowserFlow({ client, onUrl: options?.onBrowserUrl ?? browserPrompt, ...options?.browser })),\n\t\t\t)\n\t\t\t.pipe(Effect.withSpan('fold.xaiAuth.authenticateBrowser')),\n\t\tlogout: semaphore\n\t\t\t.withPermit(\n\t\t\t\tstore.clear.pipe(\n\t\t\t\t\tEffect.mapError(storeError),\n\t\t\t\t\tEffect.tap(() =>\n\t\t\t\t\t\tEffect.sync(() => {\n\t\t\t\t\t\t\tcurrent = Option.none()\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t)\n\t\t\t.pipe(Effect.withSpan('fold.xaiAuth.logout')),\n\t} satisfies XaiAuthService\n})\n\n/** Inject the current OAuth bearer token into every request without mutating caller headers. */\nexport const withXaiAuth = (client: HttpClient.HttpClient, auth: XaiAuthService): HttpClient.HttpClient =>\n\tclient.pipe(\n\t\tHttpClient.mapRequestEffect((request) =>\n\t\t\tauth.get.pipe(\n\t\t\t\tEffect.map((token) =>\n\t\t\t\t\trequest.pipe(\n\t\t\t\t\t\tHttpClientRequest.bearerToken(token.access),\n\t\t\t\t\t\tHttpClientRequest.setHeader('User-Agent', 'fold/xai-oauth'),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t\tEffect.mapError(\n\t\t\t\t\t(cause) =>\n\t\t\t\t\t\tnew HttpClientError.HttpClientError({\n\t\t\t\t\t\t\treason: new HttpClientError.TransportError({\n\t\t\t\t\t\t\t\trequest,\n\t\t\t\t\t\t\t\tcause,\n\t\t\t\t\t\t\t\tdescription: `xAI authentication failed: ${cause.message}`,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t),\n\t\t),\n\t)\n",
8
+ "/** FoldModel factory for xAI's OpenAI-compatible inference API authenticated with OAuth. */\nimport { OpenAiClient, OpenAiLanguageModel } from '@effect/ai-openai'\nimport { customModel, resolveOpenAiReasoning } from '@humanlayer/fold-core'\nimport type { FoldModel, ReasoningLevel } from '@humanlayer/fold-core'\nimport { Context, Effect, Layer } from 'effect'\nimport type { Scope } from 'effect'\nimport type { LanguageModel } from 'effect/unstable/ai'\nimport { FetchHttpClient, HttpClient } from 'effect/unstable/http'\n\nimport type { XaiAuthStore } from './AuthStore'\nimport { makeXaiAuth, withXaiAuth } from './XaiAuth'\n\nexport const XAI_API_URL = 'https://api.x.ai/v1'\nexport const DEFAULT_XAI_MODEL_ID = 'grok-4.5'\n\nexport type XaiModelOptions = {\n\treadonly model?: string\n\treadonly reasoning?: ReasoningLevel\n\treadonly providerId?: string\n\treadonly apiUrl?: string\n\treadonly store?: XaiAuthStore\n}\n\n/** Build xAI's stock OpenAI-compatible LanguageModel over the OAuth transport. */\nexport const makeXaiLanguageModel = (\n\toptions: XaiModelOptions,\n): Effect.Effect<LanguageModel.Service, never, Scope.Scope> =>\n\tEffect.gen(function* () {\n\t\tconst httpContext = yield* Layer.build(FetchHttpClient.layer)\n\t\tconst base = Context.get(httpContext, HttpClient.HttpClient)\n\t\tconst auth = yield* makeXaiAuth(options.store === undefined ? {} : { store: options.store }).pipe(\n\t\t\tEffect.provideService(HttpClient.HttpClient, base),\n\t\t)\n\t\tconst clientContext = yield* Layer.build(OpenAiClient.layer({ apiUrl: options.apiUrl ?? XAI_API_URL })).pipe(\n\t\t\tEffect.provideService(HttpClient.HttpClient, withXaiAuth(base, auth)),\n\t\t)\n\t\treturn yield* OpenAiLanguageModel.make({ model: options.model ?? DEFAULT_XAI_MODEL_ID }).pipe(\n\t\t\tEffect.provideService(OpenAiClient.OpenAiClient, Context.get(clientContext, OpenAiClient.OpenAiClient)),\n\t\t)\n\t})\n\n/** Describe an xAI OAuth-backed model compatible with Fold sessions and switching. */\nexport const xaiModel = (options: XaiModelOptions = {}): FoldModel => {\n\tconst level = options.reasoning ?? 'off'\n\treturn customModel({\n\t\tactiveModel: {\n\t\t\tproviderId: options.providerId ?? 'xai',\n\t\t\tproviderKind: 'openai-compatible',\n\t\t\tmodelId: options.model ?? DEFAULT_XAI_MODEL_ID,\n\t\t\trole: null,\n\t\t\trequestedReasoningLevel: level,\n\t\t\treasoning: resolveOpenAiReasoning(level),\n\t\t},\n\t\tmake: makeXaiLanguageModel(options),\n\t})\n}\n"
9
+ ],
10
+ "mappings": "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",
11
+ "debugId": "166BE3861ABF0E6164756E2164756E21",
12
+ "names": []
13
+ }
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@humanlayer/fold-xai",
3
+ "version": "0.0.1-rc.1",
4
+ "private": false,
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "default": "./dist/index.js"
14
+ }
15
+ },
16
+ "scripts": {
17
+ "typecheck": "tsc --noEmit",
18
+ "test": "bun vitest run",
19
+ "test:watch": "bun vitest"
20
+ },
21
+ "dependencies": {
22
+ "@effect/ai-openai": "4.0.0-beta.93",
23
+ "@effect/platform-node": "4.0.0-beta.93",
24
+ "@humanlayer/fold-core": "0.0.1-rc.1",
25
+ "effect": "4.0.0-beta.93"
26
+ },
27
+ "publishConfig": {
28
+ "access": "public"
29
+ },
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "git+https://github.com/humanlayer/fold.git",
33
+ "directory": "packages/fold-xai"
34
+ },
35
+ "homepage": "https://github.com/humanlayer/fold#readme",
36
+ "bugs": {
37
+ "url": "https://github.com/humanlayer/fold/issues"
38
+ }
39
+ }