@wayai/cli 0.2.46 → 0.2.47
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/commands/login.d.ts +4 -1
- package/dist/commands/login.js +27 -19
- package/dist/commands/login.js.map +1 -1
- package/dist/lib/auth.d.ts +34 -23
- package/dist/lib/auth.js +127 -48
- package/dist/lib/auth.js.map +1 -1
- package/dist/lib/config.d.ts +13 -2
- package/dist/lib/config.js +4 -7
- package/dist/lib/config.js.map +1 -1
- package/package.json +1 -1
package/dist/commands/login.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* wayai login —
|
|
2
|
+
* wayai login — OAuth 2.1 + PKCE browser flow (default) or --token fallback
|
|
3
|
+
*
|
|
4
|
+
* Browser login: Opens AuthKit authorize → PKCE flow → JWT + refresh token
|
|
5
|
+
* Token login: User pastes a way_ scoped token directly
|
|
3
6
|
*/
|
|
4
7
|
export declare function parseApiUrl(args: string[]): string;
|
|
5
8
|
export declare function loginCommand(args: string[]): Promise<void>;
|
package/dist/commands/login.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* wayai login —
|
|
2
|
+
* wayai login — OAuth 2.1 + PKCE browser flow (default) or --token fallback
|
|
3
|
+
*
|
|
4
|
+
* Browser login: Opens AuthKit authorize → PKCE flow → JWT + refresh token
|
|
5
|
+
* Token login: User pastes a way_ scoped token directly
|
|
3
6
|
*/
|
|
4
7
|
import * as readline from 'node:readline';
|
|
5
|
-
import { generateState, findAvailablePort, startCallbackServer,
|
|
8
|
+
import { generateState, generateCodeVerifier, generateCodeChallenge, findAvailablePort, startCallbackServer, exchangeCodeForTokens, validateToken, getAuthKitDomain, getAuthKitClientId, } from '../lib/auth.js';
|
|
6
9
|
import { writeConfig } from '../lib/config.js';
|
|
7
10
|
function prompt(question, defaultValue) {
|
|
8
11
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
@@ -34,25 +37,29 @@ export async function loginCommand(args) {
|
|
|
34
37
|
}
|
|
35
38
|
async function loginWithBrowser(apiUrl) {
|
|
36
39
|
console.log('\nConnecting to WayAI...');
|
|
40
|
+
const authkitDomain = getAuthKitDomain();
|
|
41
|
+
const clientId = getAuthKitClientId();
|
|
42
|
+
// Generate PKCE parameters
|
|
43
|
+
const codeVerifier = generateCodeVerifier();
|
|
44
|
+
const codeChallenge = await generateCodeChallenge(codeVerifier);
|
|
45
|
+
const state = generateState();
|
|
37
46
|
// Find an available port for the callback server
|
|
38
47
|
const port = await findAvailablePort();
|
|
39
48
|
const redirectUri = `http://127.0.0.1:${port}/callback`;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
process.exit(1);
|
|
49
|
-
}
|
|
49
|
+
// Build AuthKit authorization URL with PKCE
|
|
50
|
+
const authorizeUrl = new URL(`${authkitDomain}/oauth2/authorize`);
|
|
51
|
+
authorizeUrl.searchParams.set('client_id', clientId);
|
|
52
|
+
authorizeUrl.searchParams.set('redirect_uri', redirectUri);
|
|
53
|
+
authorizeUrl.searchParams.set('response_type', 'code');
|
|
54
|
+
authorizeUrl.searchParams.set('code_challenge', codeChallenge);
|
|
55
|
+
authorizeUrl.searchParams.set('code_challenge_method', 'S256');
|
|
56
|
+
authorizeUrl.searchParams.set('state', state);
|
|
50
57
|
// Start callback server before opening browser
|
|
51
58
|
const callbackPromise = startCallbackServer(port, state);
|
|
52
59
|
// Try to open browser
|
|
53
|
-
const openedBrowser = await tryOpenBrowser(
|
|
60
|
+
const openedBrowser = await tryOpenBrowser(authorizeUrl.toString());
|
|
54
61
|
if (!openedBrowser) {
|
|
55
|
-
console.log(`\nOpen this URL in your browser to log in:\n\n ${
|
|
62
|
+
console.log(`\nOpen this URL in your browser to log in:\n\n ${authorizeUrl.toString()}\n`);
|
|
56
63
|
}
|
|
57
64
|
else {
|
|
58
65
|
console.log('Opening browser for login...');
|
|
@@ -60,12 +67,14 @@ async function loginWithBrowser(apiUrl) {
|
|
|
60
67
|
try {
|
|
61
68
|
const { code } = await callbackPromise;
|
|
62
69
|
console.log('Exchanging authorization code...');
|
|
63
|
-
const
|
|
70
|
+
const tokens = await exchangeCodeForTokens(authkitDomain, clientId, code, codeVerifier, redirectUri);
|
|
64
71
|
writeConfig({
|
|
65
72
|
api_url: apiUrl,
|
|
66
|
-
|
|
73
|
+
access_token: tokens.access_token,
|
|
74
|
+
refresh_token: tokens.refresh_token,
|
|
75
|
+
token_expires_at: new Date(Date.now() + tokens.expires_in * 1000).toISOString(),
|
|
67
76
|
});
|
|
68
|
-
console.log(
|
|
77
|
+
console.log('\nLogin successful!');
|
|
69
78
|
console.log('Configuration saved to ~/.wayai/config.json');
|
|
70
79
|
}
|
|
71
80
|
catch (err) {
|
|
@@ -74,7 +83,7 @@ async function loginWithBrowser(apiUrl) {
|
|
|
74
83
|
}
|
|
75
84
|
}
|
|
76
85
|
async function loginWithToken(apiUrl) {
|
|
77
|
-
const token = await prompt('
|
|
86
|
+
const token = await prompt('API Token (way_...)');
|
|
78
87
|
if (!token) {
|
|
79
88
|
console.error('Token is required.');
|
|
80
89
|
process.exit(1);
|
|
@@ -98,7 +107,6 @@ async function loginWithToken(apiUrl) {
|
|
|
98
107
|
console.log('\nLogin successful! Configuration saved to ~/.wayai/config.json');
|
|
99
108
|
}
|
|
100
109
|
async function tryOpenBrowser(url) {
|
|
101
|
-
// Skip in headless environments
|
|
102
110
|
if (process.env.SSH_CONNECTION || process.env.SSH_TTY) {
|
|
103
111
|
return false;
|
|
104
112
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/auth.d.ts
CHANGED
|
@@ -1,51 +1,62 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Authentication —
|
|
2
|
+
* Authentication — OAuth 2.1 + PKCE browser login + way_ token fallback
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* 1. Browser login (default):
|
|
6
|
-
* 2. Token login (--token): User pastes a way_ token directly
|
|
4
|
+
* Two login paths:
|
|
5
|
+
* 1. Browser login (default): OAuth 2.1 with PKCE → JWT + refresh token
|
|
6
|
+
* 2. Token login (--token): User pastes a way_ scoped token directly
|
|
7
|
+
*
|
|
8
|
+
* The CLI exchanges codes directly with AuthKit's token endpoint.
|
|
9
|
+
* No backend involvement in the auth flow (unlike the old /auth/cli/* endpoints).
|
|
7
10
|
*/
|
|
8
11
|
import type { CliConfig } from './config.js';
|
|
9
12
|
/**
|
|
10
|
-
* Generate a random
|
|
13
|
+
* Generate a cryptographically random PKCE code verifier (43-128 chars, base64url).
|
|
14
|
+
*/
|
|
15
|
+
export declare function generateCodeVerifier(): string;
|
|
16
|
+
/**
|
|
17
|
+
* Generate the S256 code challenge from a code verifier.
|
|
18
|
+
*/
|
|
19
|
+
export declare function generateCodeChallenge(verifier: string): Promise<string>;
|
|
20
|
+
/**
|
|
21
|
+
* Generate a random state parameter for CSRF protection.
|
|
11
22
|
*/
|
|
12
23
|
export declare function generateState(): string;
|
|
13
24
|
/**
|
|
14
|
-
*
|
|
25
|
+
* Exchange an authorization code for JWT + refresh token at AuthKit's token endpoint.
|
|
15
26
|
*/
|
|
16
|
-
export declare function
|
|
27
|
+
export declare function exchangeCodeForTokens(authkitDomain: string, clientId: string, code: string, codeVerifier: string, redirectUri: string): Promise<{
|
|
28
|
+
access_token: string;
|
|
29
|
+
refresh_token: string;
|
|
30
|
+
expires_in: number;
|
|
31
|
+
}>;
|
|
17
32
|
/**
|
|
18
|
-
*
|
|
33
|
+
* Refresh an expired access token using the refresh token.
|
|
34
|
+
* Returns new tokens. If the server rotates refresh tokens,
|
|
35
|
+
* the new refresh_token is included in the response.
|
|
19
36
|
*/
|
|
20
|
-
export declare function
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
email: string;
|
|
37
|
+
export declare function refreshAccessToken(authkitDomain: string, clientId: string, refreshToken: string): Promise<{
|
|
38
|
+
access_token: string;
|
|
39
|
+
refresh_token?: string;
|
|
40
|
+
expires_in: number;
|
|
25
41
|
}>;
|
|
26
42
|
/**
|
|
27
|
-
* Validate a way_ token by making a lightweight API call
|
|
43
|
+
* Validate a way_ token by making a lightweight API call.
|
|
28
44
|
*/
|
|
29
45
|
export declare function validateToken(apiUrl: string, token: string): Promise<void>;
|
|
30
46
|
/**
|
|
31
47
|
* Start a local HTTP server that waits for the OAuth callback.
|
|
32
|
-
* Returns the authorization code and state received.
|
|
33
48
|
*/
|
|
34
49
|
export declare function startCallbackServer(port: number, expectedState: string, timeoutMs?: number): Promise<{
|
|
35
50
|
code: string;
|
|
36
51
|
port: number;
|
|
37
52
|
}>;
|
|
38
|
-
/**
|
|
39
|
-
* Check if a specific port is available by trying to bind then immediately closing.
|
|
40
|
-
*/
|
|
41
|
-
export declare function isPortAvailable(port: number): Promise<boolean>;
|
|
42
|
-
/**
|
|
43
|
-
* Find an available port by trying to listen on port 0
|
|
44
|
-
*/
|
|
45
53
|
export declare function findAvailablePort(): Promise<number>;
|
|
54
|
+
export declare function getAuthKitDomain(): string;
|
|
55
|
+
export declare function getAuthKitClientId(): string;
|
|
46
56
|
/**
|
|
47
57
|
* Get a valid access token from the current config.
|
|
48
|
-
*
|
|
58
|
+
* - For way_ tokens: returns directly (no refresh needed)
|
|
59
|
+
* - For OAuth JWT: checks expiry, refreshes if needed, updates config
|
|
49
60
|
*/
|
|
50
61
|
export declare function getAccessToken(config: CliConfig): Promise<string>;
|
|
51
62
|
/**
|
package/dist/lib/auth.js
CHANGED
|
@@ -1,68 +1,113 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Authentication —
|
|
2
|
+
* Authentication — OAuth 2.1 + PKCE browser login + way_ token fallback
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* 1. Browser login (default):
|
|
6
|
-
* 2. Token login (--token): User pastes a way_ token directly
|
|
4
|
+
* Two login paths:
|
|
5
|
+
* 1. Browser login (default): OAuth 2.1 with PKCE → JWT + refresh token
|
|
6
|
+
* 2. Token login (--token): User pastes a way_ scoped token directly
|
|
7
|
+
*
|
|
8
|
+
* The CLI exchanges codes directly with AuthKit's token endpoint.
|
|
9
|
+
* No backend involvement in the auth flow (unlike the old /auth/cli/* endpoints).
|
|
7
10
|
*/
|
|
8
11
|
import * as crypto from 'node:crypto';
|
|
9
12
|
import * as http from 'node:http';
|
|
10
|
-
import { readConfig } from './config.js';
|
|
13
|
+
import { readConfig, writeConfig } from './config.js';
|
|
11
14
|
import { setSentryUser } from './sentry.js';
|
|
15
|
+
// =============================================================================
|
|
16
|
+
// PKCE Utilities
|
|
17
|
+
// =============================================================================
|
|
18
|
+
/**
|
|
19
|
+
* Generate a cryptographically random PKCE code verifier (43-128 chars, base64url).
|
|
20
|
+
*/
|
|
21
|
+
export function generateCodeVerifier() {
|
|
22
|
+
return crypto.randomBytes(32).toString('base64url');
|
|
23
|
+
}
|
|
12
24
|
/**
|
|
13
|
-
* Generate
|
|
25
|
+
* Generate the S256 code challenge from a code verifier.
|
|
26
|
+
*/
|
|
27
|
+
export async function generateCodeChallenge(verifier) {
|
|
28
|
+
const hash = crypto.createHash('sha256').update(verifier).digest();
|
|
29
|
+
return hash.toString('base64url');
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Generate a random state parameter for CSRF protection.
|
|
14
33
|
*/
|
|
15
34
|
export function generateState() {
|
|
16
35
|
return crypto.randomBytes(16).toString('base64url');
|
|
17
36
|
}
|
|
37
|
+
// =============================================================================
|
|
38
|
+
// AuthKit Token Exchange
|
|
39
|
+
// =============================================================================
|
|
18
40
|
/**
|
|
19
|
-
*
|
|
41
|
+
* Exchange an authorization code for JWT + refresh token at AuthKit's token endpoint.
|
|
20
42
|
*/
|
|
21
|
-
export async function
|
|
22
|
-
const
|
|
23
|
-
|
|
43
|
+
export async function exchangeCodeForTokens(authkitDomain, clientId, code, codeVerifier, redirectUri) {
|
|
44
|
+
const response = await fetch(`${authkitDomain}/oauth2/token`, {
|
|
45
|
+
method: 'POST',
|
|
46
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
47
|
+
body: new URLSearchParams({
|
|
48
|
+
grant_type: 'authorization_code',
|
|
49
|
+
code,
|
|
50
|
+
code_verifier: codeVerifier,
|
|
51
|
+
redirect_uri: redirectUri,
|
|
52
|
+
client_id: clientId,
|
|
53
|
+
}).toString(),
|
|
54
|
+
});
|
|
24
55
|
if (!response.ok) {
|
|
25
56
|
const body = await response.text();
|
|
26
|
-
throw new Error(`
|
|
57
|
+
throw new Error(`Token exchange failed (${response.status}): ${body}`);
|
|
27
58
|
}
|
|
28
|
-
|
|
29
|
-
return data.url;
|
|
59
|
+
return response.json();
|
|
30
60
|
}
|
|
31
61
|
/**
|
|
32
|
-
*
|
|
62
|
+
* Refresh an expired access token using the refresh token.
|
|
63
|
+
* Returns new tokens. If the server rotates refresh tokens,
|
|
64
|
+
* the new refresh_token is included in the response.
|
|
33
65
|
*/
|
|
34
|
-
export async function
|
|
35
|
-
const response = await fetch(`${
|
|
66
|
+
export async function refreshAccessToken(authkitDomain, clientId, refreshToken) {
|
|
67
|
+
const response = await fetch(`${authkitDomain}/oauth2/token`, {
|
|
36
68
|
method: 'POST',
|
|
37
|
-
headers: { 'Content-Type': 'application/
|
|
38
|
-
body:
|
|
69
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
70
|
+
body: new URLSearchParams({
|
|
71
|
+
grant_type: 'refresh_token',
|
|
72
|
+
refresh_token: refreshToken,
|
|
73
|
+
client_id: clientId,
|
|
74
|
+
}).toString(),
|
|
39
75
|
});
|
|
40
76
|
if (!response.ok) {
|
|
77
|
+
const status = response.status;
|
|
41
78
|
const body = await response.text();
|
|
42
|
-
|
|
79
|
+
// Only clear tokens on invalid_grant (expired/revoked refresh token)
|
|
80
|
+
if (status === 400 || status === 401) {
|
|
81
|
+
let isInvalidGrant = false;
|
|
82
|
+
try {
|
|
83
|
+
const parsed = JSON.parse(body);
|
|
84
|
+
if (parsed.error === 'invalid_grant')
|
|
85
|
+
isInvalidGrant = true;
|
|
86
|
+
}
|
|
87
|
+
catch { /* non-JSON body */ }
|
|
88
|
+
if (isInvalidGrant)
|
|
89
|
+
throw new Error('SESSION_EXPIRED');
|
|
90
|
+
}
|
|
91
|
+
throw new Error(`Token refresh failed (${status}): ${body}`);
|
|
43
92
|
}
|
|
44
|
-
|
|
45
|
-
return {
|
|
46
|
-
token: data.data.token,
|
|
47
|
-
orgId: data.data.org_id,
|
|
48
|
-
userId: data.data.user_id,
|
|
49
|
-
email: data.data.email,
|
|
50
|
-
};
|
|
93
|
+
return response.json();
|
|
51
94
|
}
|
|
52
95
|
/**
|
|
53
|
-
* Validate a way_ token by making a lightweight API call
|
|
96
|
+
* Validate a way_ token by making a lightweight API call.
|
|
54
97
|
*/
|
|
55
98
|
export async function validateToken(apiUrl, token) {
|
|
56
|
-
const response = await fetch(`${apiUrl}/api/
|
|
99
|
+
const response = await fetch(`${apiUrl}/api/auth/me`, {
|
|
57
100
|
headers: { Authorization: `Bearer ${token}` },
|
|
58
101
|
});
|
|
59
102
|
if (!response.ok) {
|
|
60
103
|
throw new Error(`Token validation failed (${response.status})`);
|
|
61
104
|
}
|
|
62
105
|
}
|
|
106
|
+
// =============================================================================
|
|
107
|
+
// Callback Server
|
|
108
|
+
// =============================================================================
|
|
63
109
|
/**
|
|
64
110
|
* Start a local HTTP server that waits for the OAuth callback.
|
|
65
|
-
* Returns the authorization code and state received.
|
|
66
111
|
*/
|
|
67
112
|
export function startCallbackServer(port, expectedState, timeoutMs = 120_000) {
|
|
68
113
|
return new Promise((resolve, reject) => {
|
|
@@ -80,7 +125,6 @@ export function startCallbackServer(port, expectedState, timeoutMs = 120_000) {
|
|
|
80
125
|
reject(new Error(`OAuth callback error: ${errorDescription || error}`));
|
|
81
126
|
return;
|
|
82
127
|
}
|
|
83
|
-
// Validate state to prevent CSRF
|
|
84
128
|
if (state !== expectedState) {
|
|
85
129
|
res.writeHead(400, { 'Content-Type': 'text/html' });
|
|
86
130
|
res.end('<html><body><h2>Login failed</h2><p>Invalid state parameter</p></body></html>');
|
|
@@ -122,21 +166,6 @@ export function startCallbackServer(port, expectedState, timeoutMs = 120_000) {
|
|
|
122
166
|
});
|
|
123
167
|
});
|
|
124
168
|
}
|
|
125
|
-
/**
|
|
126
|
-
* Check if a specific port is available by trying to bind then immediately closing.
|
|
127
|
-
*/
|
|
128
|
-
export async function isPortAvailable(port) {
|
|
129
|
-
return new Promise((resolve) => {
|
|
130
|
-
const server = http.createServer();
|
|
131
|
-
server.listen(port, '127.0.0.1', () => {
|
|
132
|
-
server.close(() => resolve(true));
|
|
133
|
-
});
|
|
134
|
-
server.on('error', () => resolve(false));
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
/**
|
|
138
|
-
* Find an available port by trying to listen on port 0
|
|
139
|
-
*/
|
|
140
169
|
export async function findAvailablePort() {
|
|
141
170
|
return new Promise((resolve, reject) => {
|
|
142
171
|
const server = http.createServer();
|
|
@@ -153,15 +182,65 @@ export async function findAvailablePort() {
|
|
|
153
182
|
server.on('error', reject);
|
|
154
183
|
});
|
|
155
184
|
}
|
|
185
|
+
// =============================================================================
|
|
186
|
+
// Token Resolution (for API calls)
|
|
187
|
+
// =============================================================================
|
|
188
|
+
/** Default AuthKit configuration for WayAI */
|
|
189
|
+
const AUTHKIT_DOMAIN = 'https://sprightly-comic-51.authkit.app';
|
|
190
|
+
const AUTHKIT_CLIENT_ID = 'client_01KMZHB50KENM5SV90ZA80VXK4'; // WayAI CLI (public client, PKCE)
|
|
191
|
+
export function getAuthKitDomain() {
|
|
192
|
+
return process.env.WAYAI_AUTHKIT_DOMAIN || AUTHKIT_DOMAIN;
|
|
193
|
+
}
|
|
194
|
+
export function getAuthKitClientId() {
|
|
195
|
+
return process.env.WAYAI_AUTHKIT_CLIENT_ID || AUTHKIT_CLIENT_ID;
|
|
196
|
+
}
|
|
156
197
|
/**
|
|
157
198
|
* Get a valid access token from the current config.
|
|
158
|
-
*
|
|
199
|
+
* - For way_ tokens: returns directly (no refresh needed)
|
|
200
|
+
* - For OAuth JWT: checks expiry, refreshes if needed, updates config
|
|
159
201
|
*/
|
|
160
202
|
export async function getAccessToken(config) {
|
|
161
|
-
|
|
203
|
+
// way_ token path — no refresh needed
|
|
204
|
+
if (config.token) {
|
|
205
|
+
return config.token;
|
|
206
|
+
}
|
|
207
|
+
// OAuth JWT path — check expiry and refresh if needed
|
|
208
|
+
if (!config.access_token || !config.refresh_token) {
|
|
162
209
|
throw new Error('No token found. Run `wayai login` to authenticate.');
|
|
163
210
|
}
|
|
164
|
-
|
|
211
|
+
// Check if JWT is still valid (with 60s buffer)
|
|
212
|
+
if (!config.token_expires_at) {
|
|
213
|
+
// No expiry recorded — use the token as-is (don't unnecessarily refresh)
|
|
214
|
+
return config.access_token;
|
|
215
|
+
}
|
|
216
|
+
const expiresAt = new Date(config.token_expires_at).getTime();
|
|
217
|
+
if (expiresAt > Date.now() + 60_000) {
|
|
218
|
+
return config.access_token;
|
|
219
|
+
}
|
|
220
|
+
// Token expired — refresh
|
|
221
|
+
try {
|
|
222
|
+
const result = await refreshAccessToken(getAuthKitDomain(), getAuthKitClientId(), config.refresh_token);
|
|
223
|
+
// Atomically update config with new tokens
|
|
224
|
+
const updatedConfig = {
|
|
225
|
+
...config,
|
|
226
|
+
access_token: result.access_token,
|
|
227
|
+
token_expires_at: new Date(Date.now() + result.expires_in * 1000).toISOString(),
|
|
228
|
+
};
|
|
229
|
+
// Handle refresh token rotation
|
|
230
|
+
if (result.refresh_token) {
|
|
231
|
+
updatedConfig.refresh_token = result.refresh_token;
|
|
232
|
+
}
|
|
233
|
+
writeConfig(updatedConfig);
|
|
234
|
+
return result.access_token;
|
|
235
|
+
}
|
|
236
|
+
catch (err) {
|
|
237
|
+
if (err instanceof Error && err.message === 'SESSION_EXPIRED') {
|
|
238
|
+
// Clear stored tokens — user must re-login
|
|
239
|
+
writeConfig({ api_url: config.api_url });
|
|
240
|
+
throw new Error('Session expired. Please run `wayai login` again.');
|
|
241
|
+
}
|
|
242
|
+
throw err;
|
|
243
|
+
}
|
|
165
244
|
}
|
|
166
245
|
/**
|
|
167
246
|
* Read config and get access token, or exit with error.
|
package/dist/lib/auth.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/lib/auth.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/lib/auth.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/config.d.ts
CHANGED
|
@@ -1,10 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* CLI configuration management — reads/writes ~/.wayai/config.json
|
|
3
3
|
*/
|
|
4
|
+
/**
|
|
5
|
+
* CLI config supports two auth modes:
|
|
6
|
+
* - OAuth (browser login): access_token (JWT) + refresh_token + token_expires_at
|
|
7
|
+
* - Token (--token flag): token (way_ scoped token)
|
|
8
|
+
*/
|
|
4
9
|
export interface CliConfig {
|
|
5
10
|
api_url: string;
|
|
6
|
-
/**
|
|
7
|
-
token
|
|
11
|
+
/** way_ scoped token (from --token login) */
|
|
12
|
+
token?: string;
|
|
13
|
+
/** JWT access token (from OAuth browser login) */
|
|
14
|
+
access_token?: string;
|
|
15
|
+
/** OAuth refresh token */
|
|
16
|
+
refresh_token?: string;
|
|
17
|
+
/** ISO 8601 expiry of the access token */
|
|
18
|
+
token_expires_at?: string;
|
|
8
19
|
}
|
|
9
20
|
export declare function getConfigPath(): string;
|
|
10
21
|
export declare function readConfig(): CliConfig | null;
|
package/dist/lib/config.js
CHANGED
|
@@ -16,14 +16,11 @@ export function readConfig() {
|
|
|
16
16
|
try {
|
|
17
17
|
const content = fs.readFileSync(CONFIG_PATH, 'utf-8');
|
|
18
18
|
const parsed = JSON.parse(content);
|
|
19
|
-
//
|
|
20
|
-
if (
|
|
21
|
-
return
|
|
22
|
-
|
|
23
|
-
if (parsed.auth_method === 'oauth' && !parsed.token) {
|
|
24
|
-
// Legacy OAuth config — user needs to re-login
|
|
19
|
+
// Greenfield: reject old config formats — user must re-login
|
|
20
|
+
if (!parsed.api_url)
|
|
21
|
+
return null;
|
|
22
|
+
if (!parsed.token && !parsed.access_token)
|
|
25
23
|
return null;
|
|
26
|
-
}
|
|
27
24
|
return parsed;
|
|
28
25
|
}
|
|
29
26
|
catch {
|
package/dist/lib/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAmB9B,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,CAAC;AACrD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;AAEzD,MAAM,UAAU,aAAa;IAC3B,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAChC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QACtD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAEnC,6DAA6D;QAC7D,IAAI,CAAC,MAAM,CAAC,OAAO;YAAE,OAAO,IAAI,CAAC;QACjC,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,YAAY;YAAE,OAAO,IAAI,CAAC;QAEvD,OAAO,MAAmB,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAiB;IAC3C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,CAAC;IAED,EAAE,CAAC,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE;QACpE,IAAI,EAAE,KAAK,EAAE,wBAAwB;KACtC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,IAAI,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC/B,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;IAC7B,CAAC;AACH,CAAC"}
|