grok-it-mcp 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.md +106 -0
  2. package/dist/auth/credentials.d.ts +28 -0
  3. package/dist/auth/credentials.js +67 -0
  4. package/dist/auth/credentials.js.map +1 -0
  5. package/dist/auth/oauth.d.ts +101 -0
  6. package/dist/auth/oauth.js +284 -0
  7. package/dist/auth/oauth.js.map +1 -0
  8. package/dist/cache/artifacts.d.ts +16 -0
  9. package/dist/cache/artifacts.js +62 -0
  10. package/dist/cache/artifacts.js.map +1 -0
  11. package/dist/cli.d.ts +19 -0
  12. package/dist/cli.js +278 -0
  13. package/dist/cli.js.map +1 -0
  14. package/dist/config/constants.d.ts +18 -0
  15. package/dist/config/constants.js +19 -0
  16. package/dist/config/constants.js.map +1 -0
  17. package/dist/config/env.d.ts +11 -0
  18. package/dist/config/env.js +17 -0
  19. package/dist/config/env.js.map +1 -0
  20. package/dist/index.d.ts +2 -0
  21. package/dist/index.js +15 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/mcp/server.d.ts +2 -0
  24. package/dist/mcp/server.js +67 -0
  25. package/dist/mcp/server.js.map +1 -0
  26. package/dist/tools/image-generate.d.ts +41 -0
  27. package/dist/tools/image-generate.js +45 -0
  28. package/dist/tools/image-generate.js.map +1 -0
  29. package/dist/tools/video-generate.d.ts +66 -0
  30. package/dist/tools/video-generate.js +89 -0
  31. package/dist/tools/video-generate.js.map +1 -0
  32. package/dist/tools/x-search.d.ts +27 -0
  33. package/dist/tools/x-search.js +48 -0
  34. package/dist/tools/x-search.js.map +1 -0
  35. package/dist/xai/client.d.ts +25 -0
  36. package/dist/xai/client.js +77 -0
  37. package/dist/xai/client.js.map +1 -0
  38. package/package.json +36 -0
  39. package/plugins/grok-it/.claude-plugin/plugin.json +12 -0
  40. package/plugins/grok-it/.codex-plugin/plugin.json +37 -0
  41. package/plugins/grok-it/.mcp.json +15 -0
  42. package/plugins/grok-it/skills/grok-tools/SKILL.md +16 -0
  43. package/plugins/grok-it/skills/grok-tools/agents/openai.yaml +13 -0
package/README.md ADDED
@@ -0,0 +1,106 @@
1
+ # grok-it MCP Plugin
2
+
3
+ Local TypeScript stdio MCP server published as an npm CLI package, plus shared Claude Code + Codex plugin wrappers for Grok/xAI.
4
+
5
+ - `grok_x_search` — xAI Responses API with built-in `x_search`.
6
+ - `grok_image_generate` — `/images/generations`, cached locally by default.
7
+ - `grok_video_generate` — `/videos/generations`, polling; returns remote URL by default, optional local cache.
8
+ - `grok_auth_status` / `grok_login` — Grok OAuth PKCE status/login with `XAI_API_KEY` fallback.
9
+
10
+ ## npm CLI
11
+
12
+ Install the server directly:
13
+
14
+ ```bash
15
+ npm install -g grok-it-mcp
16
+ ```
17
+
18
+ Or run it ad hoc:
19
+
20
+ ```bash
21
+ npx -y grok-it-mcp@0.1.0
22
+ ```
23
+
24
+ The default CLI starts the stdio MCP server defined in `src/index.ts`. It also exposes auth helpers for terminal use:
25
+
26
+ ```bash
27
+ grok-it-mcp status
28
+ grok-it-mcp login --open
29
+ grok-it-mcp search "xAI news"
30
+ grok-it-mcp x-search "grok updates" --include-handles xai --max-results 5 --json
31
+ ```
32
+
33
+ For manual OAuth completion without a loopback browser flow:
34
+
35
+ ```bash
36
+ grok-it-mcp login
37
+ grok-it-mcp login --callback '<callback-url-or-code>' --verifier '<verifier>' --state '<state>' --redirect-uri 'http://127.0.0.1:8765/callback'
38
+ ```
39
+
40
+
41
+ ### OAuth note
42
+
43
+ The current default browser-login flow uses xAI's public Grok OAuth client id and the `grok-cli:access api:access` scopes. If xAI changes those values again, override them with `GROK_IT_OAUTH_CLIENT_ID` or fall back to `XAI_API_KEY`.
44
+
45
+ ### Search connectivity test
46
+
47
+ Use `search` or its alias `x-search` to run the existing `grok_x_search` flow from a terminal. This is useful for end-to-end connectivity checks because it exercises credential resolution, xAI `/responses`, and the built-in `x_search` tool:
48
+
49
+ ```bash
50
+ grok-it-mcp search "xAI news"
51
+ grok-it-mcp x-search --query "grok updates" --include-handles xai,elonmusk --max-results 10 --json
52
+ ```
53
+
54
+ Supported search flags: `--model`, `--from-date`, `--to-date`, `--include-handles`, `--exclude-handles`, `--include-images`, `--include-videos`, `--max-results`, and `--json`.
55
+ ## Cross-platform plugin root
56
+
57
+ `plugins/grok-it/` is the canonical plugin root for both Claude Code and Codex:
58
+
59
+ ```text
60
+ plugins/grok-it/
61
+ .claude-plugin/plugin.json # Claude Code manifest
62
+ .codex-plugin/plugin.json # Codex manifest
63
+ .mcp.json # shared MCP server config
64
+ skills/grok-tools/SKILL.md # shared skill instructions
65
+ skills/grok-tools/agents/openai.yaml
66
+ ```
67
+
68
+ Both manifests reference the same `./skills/` and `./.mcp.json`. The shared MCP config launches `npx -y grok-it-mcp@0.1.0`, so the plugin no longer bundles `dist/index.js`.
69
+
70
+ ## Install/build
71
+
72
+ ```bash
73
+ npm install
74
+ npm run build
75
+ ```
76
+
77
+ `npm run build` typechecks and emits the CLI entrypoint.
78
+
79
+ ## Authentication
80
+
81
+ Preferred: call MCP tool `grok_login`. It performs OAuth PKCE and stores tokens at `~/.grok-it/auth.json` (override with `GROK_IT_TOKEN_STORE`). The tool never returns token material.
82
+
83
+ Fallback: set `XAI_API_KEY`. OAuth credentials take precedence over API keys. OAuth bearer requests are pinned to `https://*.x.ai` so `XAI_BASE_URL` cannot leak OAuth tokens to another origin.
84
+
85
+ ## Codex
86
+
87
+ Install/use `plugins/grok-it/` as the Codex plugin root. The Codex manifest is at `plugins/grok-it/.codex-plugin/plugin.json`.
88
+
89
+ ## Claude Code
90
+
91
+ Install/use the same `plugins/grok-it/` folder as the Claude Code plugin root. The Claude manifest is at `plugins/grok-it/.claude-plugin/plugin.json`.
92
+
93
+ ## Validation
94
+
95
+ ```bash
96
+ npm run typecheck
97
+ npm test
98
+ npm run build
99
+ npm run validate:plugin
100
+ npm run validate:codex-plugin
101
+ ```
102
+
103
+ - `validate:plugin` checks the shared Claude/Codex plugin root and shared MCP config.
104
+ - `validate:codex-plugin` runs the official plugin-creator validator against `plugins/grok-it/` and checks shared skill metadata.
105
+
106
+ Tests mock network behavior; they must not call real xAI APIs or open browsers.
@@ -0,0 +1,28 @@
1
+ export type CredentialSource = 'xai-oauth' | 'xai';
2
+ export type ResolvedCredentials = {
3
+ provider: CredentialSource;
4
+ credentialSource: CredentialSource;
5
+ authorization: string;
6
+ baseUrl: string;
7
+ expiresAt?: number;
8
+ tokenStorePath?: string;
9
+ };
10
+ export declare class AuthRequiredError extends Error {
11
+ constructor(message?: string);
12
+ }
13
+ export declare function resolveCredentials(options?: {
14
+ forceRefresh?: boolean;
15
+ fetchImpl?: typeof fetch;
16
+ env?: NodeJS.ProcessEnv;
17
+ }): Promise<ResolvedCredentials>;
18
+ export declare function isOAuthCredential(creds: ResolvedCredentials): boolean;
19
+ export declare function redactSecret(input: string): string;
20
+ export declare function authStatus(env?: NodeJS.ProcessEnv): Promise<{
21
+ logged_in: boolean;
22
+ provider: string | null;
23
+ base_url: string | null;
24
+ oauth_expires_at: string | null;
25
+ token_store: string;
26
+ cache_dir: string;
27
+ api_key_present: boolean;
28
+ }>;
@@ -0,0 +1,67 @@
1
+ import { DEFAULT_XAI_BASE_URL } from '../config/constants.js';
2
+ import { getConfig } from '../config/env.js';
3
+ import { OAuthError, readOAuthState, refreshOAuthState, validateInferenceBaseUrl } from './oauth.js';
4
+ export class AuthRequiredError extends Error {
5
+ constructor(message = 'No Grok OAuth token or XAI_API_KEY is configured') {
6
+ super(message);
7
+ this.name = 'AuthRequiredError';
8
+ }
9
+ }
10
+ export async function resolveCredentials(options = {}) {
11
+ const config = getConfig(options.env);
12
+ const oauth = await readOAuthState(config.tokenStorePath);
13
+ if (oauth) {
14
+ try {
15
+ const fresh = await refreshOAuthState(oauth, { force: options.forceRefresh, fetchImpl: options.fetchImpl, tokenStorePath: config.tokenStorePath });
16
+ return {
17
+ provider: 'xai-oauth',
18
+ credentialSource: 'xai-oauth',
19
+ authorization: `Bearer ${fresh.tokens.access_token}`,
20
+ baseUrl: validateInferenceBaseUrl(fresh.base_url || DEFAULT_XAI_BASE_URL),
21
+ expiresAt: fresh.tokens.expires_at,
22
+ tokenStorePath: config.tokenStorePath,
23
+ };
24
+ }
25
+ catch (error) {
26
+ if (error instanceof OAuthError && (error.code === 'invalid_grant' || error.code === 'oauth_entitlement_required')) {
27
+ if (config.apiKey)
28
+ return apiKeyCredentials(config);
29
+ }
30
+ throw error;
31
+ }
32
+ }
33
+ if (config.apiKey)
34
+ return apiKeyCredentials(config);
35
+ throw new AuthRequiredError();
36
+ }
37
+ function apiKeyCredentials(config) {
38
+ return {
39
+ provider: 'xai',
40
+ credentialSource: 'xai',
41
+ authorization: `Bearer ${config.apiKey}`,
42
+ baseUrl: config.baseUrl.replace(/\/$/, ''),
43
+ tokenStorePath: config.tokenStorePath,
44
+ };
45
+ }
46
+ export function isOAuthCredential(creds) {
47
+ return creds.provider === 'xai-oauth';
48
+ }
49
+ export function redactSecret(input) {
50
+ return input
51
+ .replace(/Bearer\s+[A-Za-z0-9._~+/-]+/g, 'Bearer [REDACTED]')
52
+ .replace(/(access_token|refresh_token|id_token|code|code_verifier)=([^&\s]+)/gi, '$1=[REDACTED]');
53
+ }
54
+ export async function authStatus(env = process.env) {
55
+ const config = getConfig(env);
56
+ const oauth = await readOAuthState(config.tokenStorePath);
57
+ return {
58
+ logged_in: Boolean(oauth?.tokens?.access_token || config.apiKey),
59
+ provider: oauth?.tokens?.access_token ? 'xai-oauth' : config.apiKey ? 'xai' : null,
60
+ base_url: oauth?.tokens?.access_token ? oauth.base_url : config.apiKey ? config.baseUrl : null,
61
+ oauth_expires_at: oauth?.tokens?.expires_at ? new Date(oauth.tokens.expires_at).toISOString() : null,
62
+ token_store: config.tokenStorePath,
63
+ cache_dir: config.cacheDir,
64
+ api_key_present: Boolean(config.apiKey),
65
+ };
66
+ }
67
+ //# sourceMappingURL=credentials.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credentials.js","sourceRoot":"","sources":["../../src/auth/credentials.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,101 @@
1
+ export type OAuthDiscovery = {
2
+ issuer?: string;
3
+ authorization_endpoint: string;
4
+ token_endpoint: string;
5
+ };
6
+ export type StoredOAuthTokens = {
7
+ access_token: string;
8
+ refresh_token?: string;
9
+ id_token?: string;
10
+ expires_at?: number;
11
+ token_type?: string;
12
+ scope?: string;
13
+ };
14
+ export type StoredOAuthState = {
15
+ provider: 'xai-oauth';
16
+ auth_mode: 'oauth_pkce';
17
+ tokens: StoredOAuthTokens;
18
+ discovery: OAuthDiscovery;
19
+ redirect_uri: string;
20
+ base_url: string;
21
+ last_refresh: string;
22
+ invalid?: boolean;
23
+ last_auth_error?: string;
24
+ };
25
+ export type AuthStore = {
26
+ providers?: {
27
+ 'xai-oauth'?: StoredOAuthState;
28
+ };
29
+ };
30
+ export type LoginSession = {
31
+ verifier: string;
32
+ challenge: string;
33
+ state: string;
34
+ nonce: string;
35
+ redirectUri: string;
36
+ authorizeUrl: string;
37
+ discovery: OAuthDiscovery;
38
+ };
39
+ export declare class OAuthError extends Error {
40
+ code: string;
41
+ status?: number | undefined;
42
+ constructor(code: string, message: string, status?: number | undefined);
43
+ }
44
+ export declare function base64Url(input: Buffer): string;
45
+ export declare function generatePkce(): {
46
+ verifier: string;
47
+ challenge: string;
48
+ };
49
+ export declare function randomState(): string;
50
+ export declare function isXaiOrigin(value: string): boolean;
51
+ export declare function validateXaiHttpsUrl(value: string, label?: string): string;
52
+ export declare function validateInferenceBaseUrl(value: string): string;
53
+ export declare function readAuthStore(tokenStorePath?: string): Promise<AuthStore>;
54
+ export declare function writeAuthStore(store: AuthStore, tokenStorePath?: string): Promise<void>;
55
+ export declare function readOAuthState(tokenStorePath?: string): Promise<StoredOAuthState | undefined>;
56
+ export declare function saveOAuthState(state: StoredOAuthState, tokenStorePath?: string): Promise<void>;
57
+ export declare function markOAuthInvalid(reason: string, tokenStorePath?: string): Promise<void>;
58
+ export declare function clearOAuthState(tokenStorePath?: string): Promise<void>;
59
+ export declare function tokenExpiresAt(tokenResponse: Record<string, unknown>, now?: number): number | undefined;
60
+ export declare function isTokenExpiring(tokens: StoredOAuthTokens, now?: number): boolean;
61
+ export declare function discoverOAuth(fetchImpl?: typeof fetch): Promise<OAuthDiscovery>;
62
+ export declare function buildAuthorizeUrl(params: {
63
+ discovery: OAuthDiscovery;
64
+ clientId?: string;
65
+ redirectUri: string;
66
+ scope?: string;
67
+ challenge: string;
68
+ state: string;
69
+ nonce: string;
70
+ }): string;
71
+ export declare function createLoginSession(options?: {
72
+ redirectUri?: string;
73
+ port?: number;
74
+ fetchImpl?: typeof fetch;
75
+ }): Promise<LoginSession>;
76
+ export declare function parseCallback(input: string, expectedState?: string): {
77
+ code: string;
78
+ state?: string;
79
+ };
80
+ export declare function exchangeCodeForTokens(params: {
81
+ code: string;
82
+ verifier: string;
83
+ challenge?: string;
84
+ redirectUri: string;
85
+ discovery: OAuthDiscovery;
86
+ clientId?: string;
87
+ fetchImpl?: typeof fetch;
88
+ }): Promise<StoredOAuthTokens>;
89
+ export declare function persistTokenResponse(params: {
90
+ tokens: StoredOAuthTokens;
91
+ discovery: OAuthDiscovery;
92
+ redirectUri: string;
93
+ baseUrl?: string;
94
+ tokenStorePath?: string;
95
+ }): Promise<StoredOAuthState>;
96
+ export declare function refreshOAuthState(state: StoredOAuthState, options?: {
97
+ force?: boolean;
98
+ fetchImpl?: typeof fetch;
99
+ tokenStorePath?: string;
100
+ }): Promise<StoredOAuthState>;
101
+ export declare function waitForLoopbackCode(session: LoginSession, timeoutMs: number): Promise<string>;
@@ -0,0 +1,284 @@
1
+ import crypto from 'node:crypto';
2
+ import http from 'node:http';
3
+ import { URL, URLSearchParams } from 'node:url';
4
+ import { mkdir, readFile, rename, rm, writeFile } from 'node:fs/promises';
5
+ import path from 'node:path';
6
+ import { DEFAULT_REDIRECT_HOST, DEFAULT_REDIRECT_PATH, DEFAULT_REDIRECT_PORT, DEFAULT_XAI_DISCOVERY_URL, DEFAULT_XAI_OAUTH_CLIENT_ID, DEFAULT_XAI_OAUTH_SCOPE, OAUTH_REFRESH_SKEW_MS, PACKAGE_NAME, PACKAGE_VERSION, } from '../config/constants.js';
7
+ import { getConfig } from '../config/env.js';
8
+ export class OAuthError extends Error {
9
+ code;
10
+ status;
11
+ constructor(code, message, status) {
12
+ super(message);
13
+ this.code = code;
14
+ this.status = status;
15
+ this.name = 'OAuthError';
16
+ }
17
+ }
18
+ export function base64Url(input) {
19
+ return input.toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/g, '');
20
+ }
21
+ export function generatePkce() {
22
+ const verifier = base64Url(crypto.randomBytes(32));
23
+ const challenge = base64Url(crypto.createHash('sha256').update(verifier).digest());
24
+ return { verifier, challenge };
25
+ }
26
+ export function randomState() {
27
+ return base64Url(crypto.randomBytes(24));
28
+ }
29
+ export function isXaiOrigin(value) {
30
+ try {
31
+ const url = new URL(value);
32
+ return url.protocol === 'https:' && (url.hostname === 'x.ai' || url.hostname.endsWith('.x.ai'));
33
+ }
34
+ catch {
35
+ return false;
36
+ }
37
+ }
38
+ export function validateXaiHttpsUrl(value, label = 'xAI URL') {
39
+ if (!isXaiOrigin(value)) {
40
+ throw new OAuthError('xai_origin_required', `${label} must be an https://*.x.ai URL`);
41
+ }
42
+ return value;
43
+ }
44
+ export function validateInferenceBaseUrl(value) {
45
+ const url = new URL(validateXaiHttpsUrl(value, 'OAuth inference base URL'));
46
+ url.pathname = url.pathname.replace(/\/$/, '');
47
+ return url.toString().replace(/\/$/, '');
48
+ }
49
+ export async function readAuthStore(tokenStorePath = getConfig().tokenStorePath) {
50
+ try {
51
+ return JSON.parse(await readFile(tokenStorePath, 'utf8'));
52
+ }
53
+ catch (error) {
54
+ if (error.code === 'ENOENT')
55
+ return {};
56
+ throw error;
57
+ }
58
+ }
59
+ export async function writeAuthStore(store, tokenStorePath = getConfig().tokenStorePath) {
60
+ await mkdir(path.dirname(tokenStorePath), { recursive: true, mode: 0o700 });
61
+ const tmp = `${tokenStorePath}.${process.pid}.tmp`;
62
+ await writeFile(tmp, `${JSON.stringify(store, null, 2)}\n`, { mode: 0o600 });
63
+ await rename(tmp, tokenStorePath);
64
+ }
65
+ export async function readOAuthState(tokenStorePath = getConfig().tokenStorePath) {
66
+ const state = (await readAuthStore(tokenStorePath)).providers?.['xai-oauth'];
67
+ if (!state || state.invalid || !state.tokens?.access_token)
68
+ return undefined;
69
+ return state;
70
+ }
71
+ export async function saveOAuthState(state, tokenStorePath = getConfig().tokenStorePath) {
72
+ const store = await readAuthStore(tokenStorePath);
73
+ store.providers ||= {};
74
+ store.providers['xai-oauth'] = state;
75
+ await writeAuthStore(store, tokenStorePath);
76
+ }
77
+ export async function markOAuthInvalid(reason, tokenStorePath = getConfig().tokenStorePath) {
78
+ const store = await readAuthStore(tokenStorePath);
79
+ if (store.providers?.['xai-oauth']) {
80
+ store.providers['xai-oauth'].invalid = true;
81
+ store.providers['xai-oauth'].last_auth_error = reason;
82
+ await writeAuthStore(store, tokenStorePath);
83
+ }
84
+ }
85
+ export async function clearOAuthState(tokenStorePath = getConfig().tokenStorePath) {
86
+ const store = await readAuthStore(tokenStorePath);
87
+ if (store.providers?.['xai-oauth']) {
88
+ delete store.providers['xai-oauth'];
89
+ await writeAuthStore(store, tokenStorePath);
90
+ }
91
+ else {
92
+ await rm(tokenStorePath, { force: true });
93
+ }
94
+ }
95
+ export function tokenExpiresAt(tokenResponse, now = Date.now()) {
96
+ if (typeof tokenResponse.expires_at === 'number')
97
+ return tokenResponse.expires_at;
98
+ if (typeof tokenResponse.expires_in === 'number')
99
+ return now + tokenResponse.expires_in * 1000;
100
+ return undefined;
101
+ }
102
+ export function isTokenExpiring(tokens, now = Date.now()) {
103
+ return typeof tokens.expires_at === 'number' && tokens.expires_at - now <= OAUTH_REFRESH_SKEW_MS;
104
+ }
105
+ export async function discoverOAuth(fetchImpl = fetch) {
106
+ const response = await fetchImpl(DEFAULT_XAI_DISCOVERY_URL, { headers: { accept: 'application/json', 'user-agent': `${PACKAGE_NAME}/${PACKAGE_VERSION}` } });
107
+ if (!response.ok)
108
+ throw new OAuthError('discovery_failed', `OIDC discovery failed with HTTP ${response.status}`, response.status);
109
+ const discovery = (await response.json());
110
+ validateXaiHttpsUrl(discovery.authorization_endpoint, 'authorization_endpoint');
111
+ validateXaiHttpsUrl(discovery.token_endpoint, 'token_endpoint');
112
+ return discovery;
113
+ }
114
+ export function buildAuthorizeUrl(params) {
115
+ const url = new URL(params.discovery.authorization_endpoint);
116
+ url.search = new URLSearchParams({
117
+ response_type: 'code',
118
+ client_id: params.clientId || DEFAULT_XAI_OAUTH_CLIENT_ID,
119
+ redirect_uri: params.redirectUri,
120
+ scope: params.scope || DEFAULT_XAI_OAUTH_SCOPE,
121
+ code_challenge: params.challenge,
122
+ code_challenge_method: 'S256',
123
+ state: params.state,
124
+ nonce: params.nonce,
125
+ plan: 'generic',
126
+ referrer: PACKAGE_NAME,
127
+ }).toString();
128
+ return url.toString();
129
+ }
130
+ export async function createLoginSession(options = {}) {
131
+ const config = getConfig();
132
+ const discovery = await discoverOAuth(options.fetchImpl || fetch);
133
+ const { verifier, challenge } = generatePkce();
134
+ const state = randomState();
135
+ const nonce = randomState();
136
+ const redirectUri = options.redirectUri || `http://${DEFAULT_REDIRECT_HOST}:${options.port || DEFAULT_REDIRECT_PORT}${DEFAULT_REDIRECT_PATH}`;
137
+ return {
138
+ verifier,
139
+ challenge,
140
+ state,
141
+ nonce,
142
+ redirectUri,
143
+ discovery,
144
+ authorizeUrl: buildAuthorizeUrl({ discovery, clientId: config.oauthClientId, redirectUri, challenge, state, nonce }),
145
+ };
146
+ }
147
+ export function parseCallback(input, expectedState) {
148
+ let code = null;
149
+ let state = null;
150
+ let callbackUrl = false;
151
+ if (/^https?:\/\//.test(input)) {
152
+ callbackUrl = true;
153
+ const url = new URL(input);
154
+ const error = url.searchParams.get('error');
155
+ if (error)
156
+ throw new OAuthError(error, url.searchParams.get('error_description') || error);
157
+ code = url.searchParams.get('code');
158
+ state = url.searchParams.get('state');
159
+ }
160
+ else {
161
+ code = input.trim();
162
+ }
163
+ if (!code)
164
+ throw new OAuthError('missing_code', 'OAuth callback did not contain an authorization code');
165
+ if (expectedState && callbackUrl && !state)
166
+ throw new OAuthError('missing_state', 'OAuth callback URL did not contain state');
167
+ if (expectedState && state !== null && state !== expectedState)
168
+ throw new OAuthError('state_mismatch', 'OAuth callback state did not match login session');
169
+ return { code, state: state || undefined };
170
+ }
171
+ export async function exchangeCodeForTokens(params) {
172
+ const body = new URLSearchParams({
173
+ grant_type: 'authorization_code',
174
+ code: params.code,
175
+ redirect_uri: params.redirectUri,
176
+ client_id: params.clientId || DEFAULT_XAI_OAUTH_CLIENT_ID,
177
+ code_verifier: params.verifier,
178
+ });
179
+ if (params.challenge) {
180
+ body.set('code_challenge', params.challenge);
181
+ body.set('code_challenge_method', 'S256');
182
+ }
183
+ const response = await (params.fetchImpl || fetch)(validateXaiHttpsUrl(params.discovery.token_endpoint, 'token_endpoint'), {
184
+ method: 'POST',
185
+ headers: { accept: 'application/json', 'content-type': 'application/x-www-form-urlencoded', 'user-agent': `${PACKAGE_NAME}/${PACKAGE_VERSION}` },
186
+ body,
187
+ });
188
+ const payload = (await response.json().catch(() => ({})));
189
+ if (!response.ok) {
190
+ const message = typeof payload.error_description === 'string' ? payload.error_description : `Token exchange failed with HTTP ${response.status}`;
191
+ throw new OAuthError(response.status === 403 ? 'oauth_entitlement_required' : 'token_exchange_failed', message, response.status);
192
+ }
193
+ if (typeof payload.access_token !== 'string')
194
+ throw new OAuthError('missing_access_token', 'Token exchange response did not contain access_token');
195
+ return {
196
+ access_token: payload.access_token,
197
+ refresh_token: typeof payload.refresh_token === 'string' ? payload.refresh_token : undefined,
198
+ id_token: typeof payload.id_token === 'string' ? payload.id_token : undefined,
199
+ expires_at: tokenExpiresAt(payload),
200
+ token_type: typeof payload.token_type === 'string' ? payload.token_type : 'Bearer',
201
+ scope: typeof payload.scope === 'string' ? payload.scope : undefined,
202
+ };
203
+ }
204
+ export async function persistTokenResponse(params) {
205
+ const state = {
206
+ provider: 'xai-oauth',
207
+ auth_mode: 'oauth_pkce',
208
+ tokens: params.tokens,
209
+ discovery: params.discovery,
210
+ redirect_uri: params.redirectUri,
211
+ base_url: validateInferenceBaseUrl(params.baseUrl || getConfig().oauthBaseUrl),
212
+ last_refresh: new Date().toISOString(),
213
+ };
214
+ await saveOAuthState(state, params.tokenStorePath);
215
+ return state;
216
+ }
217
+ export async function refreshOAuthState(state, options = {}) {
218
+ if (!options.force && !isTokenExpiring(state.tokens))
219
+ return state;
220
+ if (!state.tokens.refresh_token)
221
+ throw new OAuthError('missing_refresh_token', 'OAuth token has no refresh_token; run grok_login again');
222
+ const body = new URLSearchParams({
223
+ grant_type: 'refresh_token',
224
+ client_id: getConfig().oauthClientId || DEFAULT_XAI_OAUTH_CLIENT_ID,
225
+ refresh_token: state.tokens.refresh_token,
226
+ });
227
+ const response = await (options.fetchImpl || fetch)(validateXaiHttpsUrl(state.discovery.token_endpoint, 'token_endpoint'), {
228
+ method: 'POST',
229
+ headers: { accept: 'application/json', 'content-type': 'application/x-www-form-urlencoded', 'user-agent': `${PACKAGE_NAME}/${PACKAGE_VERSION}` },
230
+ body,
231
+ });
232
+ const payload = (await response.json().catch(() => ({})));
233
+ if (!response.ok) {
234
+ const code = response.status === 403 ? 'oauth_entitlement_required' : response.status === 400 || response.status === 401 ? 'invalid_grant' : 'refresh_failed';
235
+ if (code === 'invalid_grant' || code === 'oauth_entitlement_required')
236
+ await markOAuthInvalid(code, options.tokenStorePath);
237
+ throw new OAuthError(code, typeof payload.error_description === 'string' ? payload.error_description : `OAuth refresh failed with HTTP ${response.status}`, response.status);
238
+ }
239
+ if (typeof payload.access_token !== 'string')
240
+ throw new OAuthError('missing_access_token', 'OAuth refresh response did not contain access_token');
241
+ const next = {
242
+ ...state,
243
+ invalid: false,
244
+ last_auth_error: undefined,
245
+ last_refresh: new Date().toISOString(),
246
+ tokens: {
247
+ access_token: payload.access_token,
248
+ refresh_token: typeof payload.refresh_token === 'string' ? payload.refresh_token : state.tokens.refresh_token,
249
+ id_token: typeof payload.id_token === 'string' ? payload.id_token : state.tokens.id_token,
250
+ expires_at: tokenExpiresAt(payload),
251
+ token_type: typeof payload.token_type === 'string' ? payload.token_type : 'Bearer',
252
+ scope: typeof payload.scope === 'string' ? payload.scope : state.tokens.scope,
253
+ },
254
+ };
255
+ await saveOAuthState(next, options.tokenStorePath);
256
+ return next;
257
+ }
258
+ export async function waitForLoopbackCode(session, timeoutMs) {
259
+ const redirect = new URL(session.redirectUri);
260
+ return new Promise((resolve, reject) => {
261
+ const timer = setTimeout(() => {
262
+ server.close();
263
+ reject(new OAuthError('callback_timeout', 'Timed out waiting for OAuth loopback callback'));
264
+ }, timeoutMs);
265
+ const server = http.createServer((req, res) => {
266
+ try {
267
+ const parsed = new URL(req.url || '/', session.redirectUri);
268
+ const { code } = parseCallback(parsed.toString(), session.state);
269
+ res.writeHead(200, { 'content-type': 'text/plain' });
270
+ res.end('Grok login complete. You can close this tab.');
271
+ clearTimeout(timer);
272
+ server.close();
273
+ resolve(code);
274
+ }
275
+ catch (error) {
276
+ res.writeHead(400, { 'content-type': 'text/plain' });
277
+ res.end(error.message);
278
+ }
279
+ });
280
+ server.listen(Number(redirect.port), redirect.hostname, () => undefined);
281
+ server.on('error', reject);
282
+ });
283
+ }
284
+ //# sourceMappingURL=oauth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth.js","sourceRoot":"","sources":["../../src/auth/oauth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ export type CacheResult = {
2
+ path: string;
3
+ bytes: number;
4
+ contentType?: string;
5
+ };
6
+ export declare function cacheBase64Artifact(data: string, options?: {
7
+ mediaType: 'image' | 'video';
8
+ contentType?: string;
9
+ cacheDir?: string;
10
+ }): Promise<CacheResult>;
11
+ export declare function cacheUrlArtifact(url: string, options?: {
12
+ mediaType: 'image' | 'video';
13
+ cacheDir?: string;
14
+ maxBytes?: number;
15
+ fetchImpl?: typeof fetch;
16
+ }): Promise<CacheResult>;