gemix 0.0.1 → 0.0.2

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.
@@ -1 +1 @@
1
- {"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../../src/auth/oauth.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAqBxD,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,SAAS,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAcD,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,WAAW,CAAC,CA8HnE;AA+BD,wBAAsB,aAAa,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CA2BhF"}
1
+ {"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../../src/auth/oauth.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AA0BxD,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,SAAS,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,WAAW,CAAC,CAuFnE;AAoCD,wBAAsB,aAAa,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAkChF"}
@@ -1,182 +1,144 @@
1
- import { OAuth2Client } from 'google-auth-library';
2
- import * as http from 'node:http';
3
- import * as url from 'node:url';
4
- import * as net from 'node:net';
5
1
  import * as crypto from 'node:crypto';
2
+ import * as readline from 'node:readline';
6
3
  import open from 'open';
7
- // OAuth Client ID (same as Gemini CLI - public for installed apps)
8
- const OAUTH_CLIENT_ID = '681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j.apps.googleusercontent.com';
9
- const OAUTH_CLIENT_SECRET = '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';
4
+ const OAUTH_CLIENT_ID = '1071006060591-tmhssin2h21lcre235vtolojh4g403ep.apps.googleusercontent.com';
5
+ const OAUTH_CLIENT_SECRET = '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';
10
6
  const OAUTH_SCOPE = [
11
7
  'openid',
12
8
  'https://www.googleapis.com/auth/cloud-platform',
13
9
  'https://www.googleapis.com/auth/userinfo.email',
14
10
  'https://www.googleapis.com/auth/userinfo.profile',
11
+ 'https://www.googleapis.com/auth/cclog',
12
+ 'https://www.googleapis.com/auth/experimentsandconfigs',
15
13
  ];
16
- const HTTP_REDIRECT = 301;
17
- const SIGN_IN_SUCCESS_URL = 'https://developers.google.com/gemini-code-assist/auth_success_gemini';
18
- const SIGN_IN_FAILURE_URL = 'https://developers.google.com/gemini-code-assist/auth_failure_gemini';
19
- function getAvailablePort() {
20
- return new Promise((resolve, reject) => {
21
- const server = net.createServer();
22
- server.listen(0, () => {
23
- const address = server.address();
24
- const port = address && typeof address === 'object' ? address.port : 0;
25
- server.close(() => resolve(port));
26
- });
27
- server.on('error', reject);
28
- });
14
+ const REDIRECT_URI = 'https://antigravity.google/oauth-callback';
15
+ function generateCodeVerifier() {
16
+ return crypto.randomBytes(32).toString('base64url');
17
+ }
18
+ function generateCodeChallenge(verifier) {
19
+ return crypto.createHash('sha256').update(verifier).digest('base64url');
29
20
  }
30
21
  export async function authenticateWithGoogle() {
31
- const client = new OAuth2Client({
32
- clientId: OAUTH_CLIENT_ID,
33
- clientSecret: OAUTH_CLIENT_SECRET,
34
- });
35
- const port = await getAvailablePort();
36
- const redirectUri = `http://127.0.0.1:${port}/oauth2callback`;
37
22
  const state = crypto.randomBytes(32).toString('hex');
38
- const authUrl = client.generateAuthUrl({
39
- redirect_uri: redirectUri,
23
+ const codeVerifier = generateCodeVerifier();
24
+ const codeChallenge = generateCodeChallenge(codeVerifier);
25
+ const authParams = new URLSearchParams({
26
+ client_id: OAUTH_CLIENT_ID,
27
+ response_type: 'code',
28
+ redirect_uri: REDIRECT_URI,
29
+ scope: OAUTH_SCOPE.join(' '),
40
30
  access_type: 'offline',
41
- scope: OAUTH_SCOPE,
42
31
  prompt: 'consent',
43
32
  state,
33
+ code_challenge: codeChallenge,
34
+ code_challenge_method: 'S256',
44
35
  });
45
- const loginCompletePromise = new Promise((resolve, reject) => {
46
- const server = http.createServer(async (req, res) => {
47
- try {
48
- if (!req.url || req.url.indexOf('/oauth2callback') === -1) {
49
- res.writeHead(HTTP_REDIRECT, { Location: SIGN_IN_FAILURE_URL });
50
- res.end();
51
- reject(new Error('Unexpected request: ' + req.url));
52
- return;
53
- }
54
- const qs = new url.URL(req.url, `http://127.0.0.1:${port}`).searchParams;
55
- if (qs.get('error')) {
56
- res.writeHead(HTTP_REDIRECT, { Location: SIGN_IN_FAILURE_URL });
57
- res.end();
58
- reject(new Error(`Google OAuth error: ${qs.get('error')}. ${qs.get('error_description') || ''}`));
59
- return;
60
- }
61
- if (qs.get('state') !== state) {
62
- res.writeHead(200, { 'Content-Type': 'text/html' });
63
- res.end('<h1>State mismatch. Possible CSRF attack.</h1>');
64
- reject(new Error('State mismatch. Possible CSRF attack.'));
65
- return;
66
- }
67
- if (qs.get('code')) {
68
- res.writeHead(HTTP_REDIRECT, { Location: SIGN_IN_SUCCESS_URL });
69
- res.end();
70
- resolve({ code: qs.get('code') });
71
- }
72
- else {
73
- res.writeHead(HTTP_REDIRECT, { Location: SIGN_IN_FAILURE_URL });
74
- res.end();
75
- reject(new Error('No authorization code received.'));
76
- }
77
- }
78
- catch (e) {
79
- res.writeHead(HTTP_REDIRECT, { Location: SIGN_IN_FAILURE_URL });
80
- res.end();
81
- reject(e instanceof Error ? e : new Error(String(e)));
82
- }
83
- finally {
84
- server.close();
85
- }
86
- });
87
- server.listen(port, '127.0.0.1', () => { });
88
- server.on('error', reject);
89
- });
36
+ const authUrl = `https://accounts.google.com/o/oauth2/auth?${authParams.toString()}`;
90
37
  console.log('\nOpening browser for Google authentication...\n');
38
+ console.log('After signing in, copy the authorization code from the redirect page.\n');
91
39
  console.log(`If the browser doesn't open, visit:\n${authUrl}\n`);
92
40
  const childProcess = await open(authUrl);
93
41
  childProcess.on('error', (error) => {
94
42
  console.error(`Failed to open browser: ${error.message}`);
95
43
  console.log(`Please visit:\n${authUrl}\n`);
96
44
  });
97
- const authTimeout = 5 * 60 * 1000;
98
- let timeoutId;
99
- const timeoutPromise = new Promise((_, reject) => {
100
- timeoutId = setTimeout(() => {
101
- reject(new Error('Authentication timed out after 5 minutes.'));
102
- }, authTimeout);
103
- });
104
- const cancellationPromise = new Promise((_, reject) => {
105
- process.on('SIGINT', () => {
106
- reject(new Error('Authentication cancelled by user.'));
107
- });
108
- });
109
- try {
110
- const { code } = await Promise.race([
111
- loginCompletePromise,
112
- timeoutPromise,
113
- cancellationPromise,
114
- ]);
115
- if (timeoutId)
116
- clearTimeout(timeoutId);
117
- const { tokens } = await client.getToken({
45
+ const code = await promptForAuthCode();
46
+ const startTime = Date.now();
47
+ const tokenResponse = await fetch('https://oauth2.googleapis.com/token', {
48
+ method: 'POST',
49
+ headers: {
50
+ 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
51
+ },
52
+ body: new URLSearchParams({
53
+ client_id: OAUTH_CLIENT_ID,
54
+ client_secret: OAUTH_CLIENT_SECRET,
118
55
  code,
119
- redirect_uri: redirectUri,
120
- });
121
- client.setCredentials(tokens);
122
- const userInfo = await fetchUserInfo(client);
123
- return {
124
- tokens: {
125
- access_token: tokens.access_token || '',
126
- refresh_token: tokens.refresh_token || '',
127
- id_token: tokens.id_token || '',
128
- scope: tokens.scope || OAUTH_SCOPE.join(' '),
129
- token_type: tokens.token_type || 'Bearer',
130
- expiry_date: tokens.expiry_date || Date.now(),
131
- },
132
- email: userInfo.email,
133
- name: userInfo.name,
134
- picture: userInfo.picture,
135
- };
136
- }
137
- finally {
138
- if (timeoutId)
139
- clearTimeout(timeoutId);
56
+ grant_type: 'authorization_code',
57
+ redirect_uri: REDIRECT_URI,
58
+ code_verifier: codeVerifier,
59
+ }),
60
+ });
61
+ if (!tokenResponse.ok) {
62
+ const errorText = await tokenResponse.text();
63
+ throw new Error(`Token exchange failed: ${tokenResponse.status} ${errorText}`);
140
64
  }
141
- }
142
- async function fetchUserInfo(client) {
143
- const { token } = await client.getAccessToken();
144
- if (!token)
145
- throw new Error('No access token available');
146
- const response = await fetch('https://www.googleapis.com/oauth2/v2/userinfo', {
147
- headers: { Authorization: `Bearer ${token}` },
65
+ const tokenPayload = (await tokenResponse.json());
66
+ const userInfoResponse = await fetch('https://www.googleapis.com/oauth2/v2/userinfo', {
67
+ headers: { Authorization: `Bearer ${tokenPayload.access_token}` },
148
68
  });
149
- if (!response.ok) {
150
- throw new Error(`Failed to fetch user info: ${response.status} ${response.statusText}`);
69
+ if (!userInfoResponse.ok) {
70
+ throw new Error(`Failed to fetch user info: ${userInfoResponse.status} ${userInfoResponse.statusText}`);
151
71
  }
152
- const userInfo = (await response.json());
72
+ const userInfo = (await userInfoResponse.json());
153
73
  return {
74
+ tokens: {
75
+ access_token: tokenPayload.access_token,
76
+ refresh_token: tokenPayload.refresh_token,
77
+ id_token: '',
78
+ scope: tokenPayload.scope || OAUTH_SCOPE.join(' '),
79
+ token_type: tokenPayload.token_type || 'Bearer',
80
+ expiry_date: startTime + tokenPayload.expires_in * 1000,
81
+ },
154
82
  email: userInfo.email,
155
83
  name: userInfo.name,
156
84
  picture: userInfo.picture,
157
85
  };
158
86
  }
87
+ function promptForAuthCode() {
88
+ return new Promise((resolve, reject) => {
89
+ const rl = readline.createInterface({
90
+ input: process.stdin,
91
+ output: process.stdout,
92
+ });
93
+ const authTimeout = 5 * 60 * 1000;
94
+ const timeoutId = setTimeout(() => {
95
+ rl.close();
96
+ reject(new Error('Authentication timed out after 5 minutes.'));
97
+ }, authTimeout);
98
+ const onSigint = () => {
99
+ clearTimeout(timeoutId);
100
+ rl.close();
101
+ reject(new Error('Authentication cancelled by user.'));
102
+ };
103
+ process.on('SIGINT', onSigint);
104
+ rl.question('Paste the authorization code: ', (answer) => {
105
+ clearTimeout(timeoutId);
106
+ process.removeListener('SIGINT', onSigint);
107
+ rl.close();
108
+ const code = answer.trim();
109
+ if (!code) {
110
+ reject(new Error('No authorization code provided.'));
111
+ }
112
+ else {
113
+ resolve(code);
114
+ }
115
+ });
116
+ });
117
+ }
159
118
  export async function refreshTokens(tokens) {
160
119
  try {
161
- const client = new OAuth2Client({
162
- clientId: OAUTH_CLIENT_ID,
163
- clientSecret: OAUTH_CLIENT_SECRET,
164
- });
165
- client.setCredentials({
166
- access_token: tokens.access_token,
167
- refresh_token: tokens.refresh_token,
120
+ const tokenResponse = await fetch('https://oauth2.googleapis.com/token', {
121
+ method: 'POST',
122
+ headers: {
123
+ 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
124
+ },
125
+ body: new URLSearchParams({
126
+ client_id: OAUTH_CLIENT_ID,
127
+ client_secret: OAUTH_CLIENT_SECRET,
128
+ refresh_token: tokens.refresh_token,
129
+ grant_type: 'refresh_token',
130
+ }),
168
131
  });
169
- const { token: newAccessToken } = await client.getAccessToken();
170
- if (!newAccessToken)
132
+ if (!tokenResponse.ok)
171
133
  return null;
172
- const credentials = client.credentials;
134
+ const tokenPayload = (await tokenResponse.json());
173
135
  return {
174
- access_token: newAccessToken,
175
- refresh_token: credentials.refresh_token || tokens.refresh_token,
176
- id_token: credentials.id_token || tokens.id_token || '',
136
+ access_token: tokenPayload.access_token,
137
+ refresh_token: tokens.refresh_token,
138
+ id_token: tokens.id_token || '',
177
139
  scope: tokens.scope,
178
- token_type: tokens.token_type,
179
- expiry_date: credentials.expiry_date || Date.now() + 3600 * 1000,
140
+ token_type: tokenPayload.token_type || 'Bearer',
141
+ expiry_date: Date.now() + tokenPayload.expires_in * 1000,
180
142
  };
181
143
  }
182
144
  catch {
@@ -1 +1 @@
1
- {"version":3,"file":"oauth.js","sourceRoot":"","sources":["../../src/auth/oauth.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"oauth.js","sourceRoot":"","sources":["../../src/auth/oauth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAC;AAC1C,OAAO,IAAI,MAAM,MAAM,CAAC;AAGxB,MAAM,eAAe,GACnB,2EAA2E,CAAC;AAE9E,MAAM,mBAAmB,GAAG,qCAAqC,CAAC;AAElE,MAAM,WAAW,GAAG;IAClB,QAAQ;IACR,gDAAgD;IAChD,gDAAgD;IAChD,kDAAkD;IAClD,uCAAuC;IACvC,uDAAuD;CACxD,CAAC;AAEF,MAAM,YAAY,GAAG,2CAA2C,CAAC;AAEjE,SAAS,oBAAoB;IAC3B,OAAO,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AACtD,CAAC;AAED,SAAS,qBAAqB,CAAC,QAAgB;IAC7C,OAAO,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;AAC1E,CAAC;AASD,MAAM,CAAC,KAAK,UAAU,sBAAsB;IAC1C,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACrD,MAAM,YAAY,GAAG,oBAAoB,EAAE,CAAC;IAC5C,MAAM,aAAa,GAAG,qBAAqB,CAAC,YAAY,CAAC,CAAC;IAE1D,MAAM,UAAU,GAAG,IAAI,eAAe,CAAC;QACrC,SAAS,EAAE,eAAe;QAC1B,aAAa,EAAE,MAAM;QACrB,YAAY,EAAE,YAAY;QAC1B,KAAK,EAAE,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC;QAC5B,WAAW,EAAE,SAAS;QACtB,MAAM,EAAE,SAAS;QACjB,KAAK;QACL,cAAc,EAAE,aAAa;QAC7B,qBAAqB,EAAE,MAAM;KAC9B,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,6CAA6C,UAAU,CAAC,QAAQ,EAAE,EAAE,CAAC;IAErF,OAAO,CAAC,GAAG,CAAC,kDAAkD,CAAC,CAAC;IAChE,OAAO,CAAC,GAAG,CAAC,yEAAyE,CAAC,CAAC;IACvF,OAAO,CAAC,GAAG,CAAC,wCAAwC,OAAO,IAAI,CAAC,CAAC;IAEjE,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,CAAC;IACzC,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;QACjC,OAAO,CAAC,KAAK,CAAC,2BAA2B,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QAC1D,OAAO,CAAC,GAAG,CAAC,kBAAkB,OAAO,IAAI,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,MAAM,iBAAiB,EAAE,CAAC;IAEvC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,MAAM,aAAa,GAAG,MAAM,KAAK,CAAC,qCAAqC,EAAE;QACvE,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,cAAc,EAAE,iDAAiD;SAClE;QACD,IAAI,EAAE,IAAI,eAAe,CAAC;YACxB,SAAS,EAAE,eAAe;YAC1B,aAAa,EAAE,mBAAmB;YAClC,IAAI;YACJ,UAAU,EAAE,oBAAoB;YAChC,YAAY,EAAE,YAAY;YAC1B,aAAa,EAAE,YAAY;SAC5B,CAAC;KACH,CAAC,CAAC;IAEH,IAAI,CAAC,aAAa,CAAC,EAAE,EAAE,CAAC;QACtB,MAAM,SAAS,GAAG,MAAM,aAAa,CAAC,IAAI,EAAE,CAAC;QAC7C,MAAM,IAAI,KAAK,CAAC,0BAA0B,aAAa,CAAC,MAAM,IAAI,SAAS,EAAE,CAAC,CAAC;IACjF,CAAC;IAED,MAAM,YAAY,GAAG,CAAC,MAAM,aAAa,CAAC,IAAI,EAAE,CAM/C,CAAC;IAEF,MAAM,gBAAgB,GAAG,MAAM,KAAK,CAAC,+CAA+C,EAAE;QACpF,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,YAAY,CAAC,YAAY,EAAE,EAAE;KAClE,CAAC,CAAC;IAEH,IAAI,CAAC,gBAAgB,CAAC,EAAE,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,8BAA8B,gBAAgB,CAAC,MAAM,IAAI,gBAAgB,CAAC,UAAU,EAAE,CAAC,CAAC;IAC1G,CAAC;IAED,MAAM,QAAQ,GAAG,CAAC,MAAM,gBAAgB,CAAC,IAAI,EAAE,CAI9C,CAAC;IAEF,OAAO;QACL,MAAM,EAAE;YACN,YAAY,EAAE,YAAY,CAAC,YAAY;YACvC,aAAa,EAAE,YAAY,CAAC,aAAa;YACzC,QAAQ,EAAE,EAAE;YACZ,KAAK,EAAE,YAAY,CAAC,KAAK,IAAI,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC;YAClD,UAAU,EAAE,YAAY,CAAC,UAAU,IAAI,QAAQ;YAC/C,WAAW,EAAE,SAAS,GAAG,YAAY,CAAC,UAAU,GAAG,IAAI;SACxD;QACD,KAAK,EAAE,QAAQ,CAAC,KAAK;QACrB,IAAI,EAAE,QAAQ,CAAC,IAAI;QACnB,OAAO,EAAE,QAAQ,CAAC,OAAO;KAC1B,CAAC;AACJ,CAAC;AAED,SAAS,iBAAiB;IACxB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC;YAClC,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC,CAAC;QAEH,MAAM,WAAW,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;QAClC,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE;YAChC,EAAE,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,CAAC,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC,CAAC;QACjE,CAAC,EAAE,WAAW,CAAC,CAAC;QAEhB,MAAM,QAAQ,GAAG,GAAG,EAAE;YACpB,YAAY,CAAC,SAAS,CAAC,CAAC;YACxB,EAAE,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,CAAC,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC,CAAC;QACzD,CAAC,CAAC;QACF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAE/B,EAAE,CAAC,QAAQ,CAAC,gCAAgC,EAAE,CAAC,MAAM,EAAE,EAAE;YACvD,YAAY,CAAC,SAAS,CAAC,CAAC;YACxB,OAAO,CAAC,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;YAC3C,EAAE,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;YAC3B,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,MAAM,CAAC,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC,CAAC;YACvD,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,IAAI,CAAC,CAAC;YAChB,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,MAAiB;IACnD,IAAI,CAAC;QACH,MAAM,aAAa,GAAG,MAAM,KAAK,CAAC,qCAAqC,EAAE;YACvE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,iDAAiD;aAClE;YACD,IAAI,EAAE,IAAI,eAAe,CAAC;gBACxB,SAAS,EAAE,eAAe;gBAC1B,aAAa,EAAE,mBAAmB;gBAClC,aAAa,EAAE,MAAM,CAAC,aAAa;gBACnC,UAAU,EAAE,eAAe;aAC5B,CAAC;SACH,CAAC,CAAC;QAEH,IAAI,CAAC,aAAa,CAAC,EAAE;YAAE,OAAO,IAAI,CAAC;QAEnC,MAAM,YAAY,GAAG,CAAC,MAAM,aAAa,CAAC,IAAI,EAAE,CAI/C,CAAC;QAEF,OAAO;YACL,YAAY,EAAE,YAAY,CAAC,YAAY;YACvC,aAAa,EAAE,MAAM,CAAC,aAAa;YACnC,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,EAAE;YAC/B,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,UAAU,EAAE,YAAY,CAAC,UAAU,IAAI,QAAQ;YAC/C,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,YAAY,CAAC,UAAU,GAAG,IAAI;SACzD,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -5,8 +5,8 @@ export async function currentCommand() {
5
5
  const accounts = await loadAccounts();
6
6
  if (!activeUsername || !accounts.accounts[activeUsername]) {
7
7
  console.log('No active account.');
8
- console.log('Use "gemx list" to see available accounts.');
9
- console.log('Use "gemx use <username>" to switch accounts.');
8
+ console.log('Use "gemix list" to see available accounts.');
9
+ console.log('Use "gemix use <username>" to switch accounts.');
10
10
  return;
11
11
  }
12
12
  const account = accounts.accounts[activeUsername];
@@ -1 +1 @@
1
- {"version":3,"file":"current.js","sourceRoot":"","sources":["../../src/commands/current.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,MAAM,cAAc,GAAG,MAAM,iBAAiB,EAAE,CAAC;IACjD,MAAM,QAAQ,GAAG,MAAM,YAAY,EAAE,CAAC;IAEtC,IAAI,CAAC,cAAc,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;QAC1D,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;QAClC,OAAO,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC;QAC1D,OAAO,CAAC,GAAG,CAAC,+CAA+C,CAAC,CAAC;QAC7D,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAG,QAAQ,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;IAClD,OAAO,CAAC,GAAG,CAAC,mBAAmB,cAAc,KAAK,OAAO,CAAC,KAAK,GAAG,CAAC,CAAC;IACpE,OAAO,CAAC,GAAG,CAAC,WAAW,YAAY,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AACzD,CAAC"}
1
+ {"version":3,"file":"current.js","sourceRoot":"","sources":["../../src/commands/current.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,MAAM,cAAc,GAAG,MAAM,iBAAiB,EAAE,CAAC;IACjD,MAAM,QAAQ,GAAG,MAAM,YAAY,EAAE,CAAC;IAEtC,IAAI,CAAC,cAAc,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;QAC1D,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;QAClC,OAAO,CAAC,GAAG,CAAC,6CAA6C,CAAC,CAAC;QAC3D,OAAO,CAAC,GAAG,CAAC,gDAAgD,CAAC,CAAC;QAC9D,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAG,QAAQ,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;IAClD,OAAO,CAAC,GAAG,CAAC,mBAAmB,cAAc,KAAK,OAAO,CAAC,KAAK,GAAG,CAAC,CAAC;IACpE,OAAO,CAAC,GAAG,CAAC,WAAW,YAAY,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AACzD,CAAC"}
@@ -5,7 +5,7 @@ export async function listCommand(json = false) {
5
5
  const activeUsername = accounts.active;
6
6
  if (Object.keys(accounts.accounts).length === 0) {
7
7
  console.log('No accounts registered.');
8
- console.log('Run "gemx register <username>" to add an account.');
8
+ console.log('Run "gemix register <username>" to add an account.');
9
9
  return;
10
10
  }
11
11
  if (json) {
@@ -1 +1 @@
1
- {"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAE/E,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAgB,KAAK;IACrD,MAAM,QAAQ,GAAG,MAAM,YAAY,EAAE,CAAC;IACtC,MAAM,cAAc,GAAG,QAAQ,CAAC,MAAM,CAAC;IAEvC,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChD,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;QACvC,OAAO,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAC;QACjE,OAAO;IACT,CAAC;IAED,IAAI,IAAI,EAAE,CAAC;QACT,MAAM,MAAM,GAAG,sBAAsB,CAAC,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;QACzE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC/C,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC,CAAC;IACrE,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAE/E,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAgB,KAAK;IACrD,MAAM,QAAQ,GAAG,MAAM,YAAY,EAAE,CAAC;IACtC,MAAM,cAAc,GAAG,QAAQ,CAAC,MAAM,CAAC;IAEvC,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChD,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;QACvC,OAAO,CAAC,GAAG,CAAC,oDAAoD,CAAC,CAAC;QAClE,OAAO;IACT,CAAC;IAED,IAAI,IAAI,EAAE,CAAC;QACT,MAAM,MAAM,GAAG,sBAAsB,CAAC,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;QACzE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC/C,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC,CAAC;IACrE,CAAC;AACH,CAAC"}
@@ -11,7 +11,7 @@ export async function registerCommand(username) {
11
11
  const accounts = await loadAccounts();
12
12
  if (accounts.accounts[username]) {
13
13
  console.error(`Error: Account '${username}' already exists.`);
14
- console.error(`Use 'gemx remove ${username}' to remove it first.`);
14
+ console.error(`Use 'gemix remove ${username}' to remove it first.`);
15
15
  process.exit(1);
16
16
  }
17
17
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"register.js","sourceRoot":"","sources":["../../src/commands/register.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,QAAgB;IACpD,MAAM,UAAU,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAC9C,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;QACtB,OAAO,CAAC,KAAK,CAAC,UAAU,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC;QAC5C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,YAAY,EAAE,CAAC;IACtC,IAAI,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QAChC,OAAO,CAAC,KAAK,CAAC,mBAAmB,QAAQ,mBAAmB,CAAC,CAAC;QAC9D,OAAO,CAAC,KAAK,CAAC,oBAAoB,QAAQ,uBAAuB,CAAC,CAAC;QACnE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,wBAAwB,QAAQ,MAAM,CAAC,CAAC;QACpD,MAAM,MAAM,GAAG,MAAM,sBAAsB,EAAE,CAAC;QAE9C,MAAM,UAAU,CACd,QAAQ,EACR,MAAM,CAAC,KAAK,EACZ,MAAM,CAAC,IAAI,EACX,MAAM,CAAC,OAAO,EACd,MAAM,CAAC,MAAM,CACd,CAAC;QAEF,MAAM,cAAc,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC;QAEnE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,gBAAgB,QAAQ,KAAK,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC;QAC1D,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,OAAO,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;QACrC,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,aAAa,YAAY,CAAC,EAAE,cAAc,EAAE,GAAG,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;QAEzF,IAAI,cAAc,EAAE,CAAC;YACnB,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;QACzC,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAClB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YAClE,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;QACzC,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,sBAAsB,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QACxF,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"register.js","sourceRoot":"","sources":["../../src/commands/register.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,QAAgB;IACpD,MAAM,UAAU,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAC9C,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;QACtB,OAAO,CAAC,KAAK,CAAC,UAAU,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC;QAC5C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,YAAY,EAAE,CAAC;IACtC,IAAI,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QAChC,OAAO,CAAC,KAAK,CAAC,mBAAmB,QAAQ,mBAAmB,CAAC,CAAC;QAC9D,OAAO,CAAC,KAAK,CAAC,qBAAqB,QAAQ,uBAAuB,CAAC,CAAC;QACpE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,wBAAwB,QAAQ,MAAM,CAAC,CAAC;QACpD,MAAM,MAAM,GAAG,MAAM,sBAAsB,EAAE,CAAC;QAE9C,MAAM,UAAU,CACd,QAAQ,EACR,MAAM,CAAC,KAAK,EACZ,MAAM,CAAC,IAAI,EACX,MAAM,CAAC,OAAO,EACd,MAAM,CAAC,MAAM,CACd,CAAC;QAEF,MAAM,cAAc,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC;QAEnE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,gBAAgB,QAAQ,KAAK,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC;QAC1D,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,OAAO,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;QACrC,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,aAAa,YAAY,CAAC,EAAE,cAAc,EAAE,GAAG,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;QAEzF,IAAI,cAAc,EAAE,CAAC;YACnB,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;QACzC,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAClB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YAClE,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;QACzC,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,sBAAsB,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QACxF,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
@@ -4,7 +4,7 @@ export async function removeCommand(username, yes = false) {
4
4
  const accounts = await loadAccounts();
5
5
  if (!accounts.accounts[username]) {
6
6
  console.error(`Error: Account '${username}' not found.`);
7
- console.error('Use "gemx list" to see available accounts.');
7
+ console.error('Use "gemix list" to see available accounts.');
8
8
  process.exit(1);
9
9
  }
10
10
  if (!yes) {
@@ -1 +1 @@
1
- {"version":3,"file":"remove.js","sourceRoot":"","sources":["../../src/commands/remove.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAErE,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,QAAgB,EAAE,MAAe,KAAK;IACxE,MAAM,QAAQ,GAAG,MAAM,YAAY,EAAE,CAAC;IAEtC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QACjC,OAAO,CAAC,KAAK,CAAC,mBAAmB,QAAQ,cAAc,CAAC,CAAC;QACzD,OAAO,CAAC,KAAK,CAAC,4CAA4C,CAAC,CAAC;QAC5D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC;YAClC,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,MAAM,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,EAAE;YACnD,EAAE,CAAC,QAAQ,CAAC,mBAAmB,QAAQ,WAAW,EAAE,OAAO,CAAC,CAAC;QAC/D,CAAC,CAAC,CAAC;QACH,EAAE,CAAC,KAAK,EAAE,CAAC;QAEX,IAAI,MAAM,CAAC,WAAW,EAAE,KAAK,GAAG,IAAI,MAAM,CAAC,WAAW,EAAE,KAAK,KAAK,EAAE,CAAC;YACnE,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;YAClC,OAAO;QACT,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,QAAQ,CAAC,CAAC;IAC9C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC;QAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,sBAAsB,QAAQ,GAAG,CAAC,CAAC;AACjD,CAAC"}
1
+ {"version":3,"file":"remove.js","sourceRoot":"","sources":["../../src/commands/remove.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAErE,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,QAAgB,EAAE,MAAe,KAAK;IACxE,MAAM,QAAQ,GAAG,MAAM,YAAY,EAAE,CAAC;IAEtC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QACjC,OAAO,CAAC,KAAK,CAAC,mBAAmB,QAAQ,cAAc,CAAC,CAAC;QACzD,OAAO,CAAC,KAAK,CAAC,6CAA6C,CAAC,CAAC;QAC7D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC;YAClC,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,MAAM,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,EAAE;YACnD,EAAE,CAAC,QAAQ,CAAC,mBAAmB,QAAQ,WAAW,EAAE,OAAO,CAAC,CAAC;QAC/D,CAAC,CAAC,CAAC;QACH,EAAE,CAAC,KAAK,EAAE,CAAC;QAEX,IAAI,MAAM,CAAC,WAAW,EAAE,KAAK,GAAG,IAAI,MAAM,CAAC,WAAW,EAAE,KAAK,KAAK,EAAE,CAAC;YACnE,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;YAClC,OAAO;QACT,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,QAAQ,CAAC,CAAC;IAC9C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC;QAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,sBAAsB,QAAQ,GAAG,CAAC,CAAC;AACjD,CAAC"}
@@ -3,7 +3,7 @@ export async function useCommand(username) {
3
3
  const accounts = await loadAccounts();
4
4
  if (!accounts.accounts[username]) {
5
5
  console.error(`Error: Account '${username}' not found.`);
6
- console.error('Use "gemx list" to see available accounts.');
6
+ console.error('Use "gemix list" to see available accounts.');
7
7
  process.exit(1);
8
8
  }
9
9
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"use.js","sourceRoot":"","sources":["../../src/commands/use.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAErE,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,QAAgB;IAC/C,MAAM,QAAQ,GAAG,MAAM,YAAY,EAAE,CAAC;IAEtC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QACjC,OAAO,CAAC,KAAK,CAAC,mBAAmB,QAAQ,cAAc,CAAC,CAAC;QACzD,OAAO,CAAC,KAAK,CAAC,4CAA4C,CAAC,CAAC;QAC5D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,QAAQ,CAAC,CAAC;QAC9C,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC;YAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,OAAO,GAAG,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAC5C,OAAO,CAAC,GAAG,CAAC,iBAAiB,QAAQ,KAAK,OAAO,CAAC,KAAK,GAAG,CAAC,CAAC;IAC9D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QACxE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"use.js","sourceRoot":"","sources":["../../src/commands/use.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAErE,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,QAAgB;IAC/C,MAAM,QAAQ,GAAG,MAAM,YAAY,EAAE,CAAC;IAEtC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QACjC,OAAO,CAAC,KAAK,CAAC,mBAAmB,QAAQ,cAAc,CAAC,CAAC;QACzD,OAAO,CAAC,KAAK,CAAC,6CAA6C,CAAC,CAAC;QAC7D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,QAAQ,CAAC,CAAC;QAC9C,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC;YAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,OAAO,GAAG,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAC5C,OAAO,CAAC,GAAG,CAAC,iBAAiB,QAAQ,KAAK,OAAO,CAAC,KAAK,GAAG,CAAC,CAAC;IAC9D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QACxE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
package/dist/index.js CHANGED
@@ -7,7 +7,7 @@ import { currentCommand } from './commands/current.js';
7
7
  import { removeCommand } from './commands/remove.js';
8
8
  const program = new Command();
9
9
  program
10
- .name('gemx')
10
+ .name('gemix')
11
11
  .description('Gemini multi-account CLI - manage multiple Google accounts')
12
12
  .version('1.0.0');
13
13
  program
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,MAAM,CAAC;KACZ,WAAW,CAAC,4DAA4D,CAAC;KACzE,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;KACJ,OAAO,CAAC,UAAU,CAAC;KACnB,WAAW,CAAC,+BAA+B,CAAC;KAC5C,QAAQ,CAAC,YAAY,EAAE,kCAAkC,CAAC;KAC1D,MAAM,CAAC,KAAK,EAAE,QAAgB,EAAE,EAAE;IACjC,MAAM,eAAe,CAAC,QAAQ,CAAC,CAAC;AAClC,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,KAAK,CAAC,IAAI,CAAC;KACX,WAAW,CAAC,8BAA8B,CAAC;KAC3C,MAAM,CAAC,YAAY,EAAE,uBAAuB,CAAC;KAC7C,MAAM,CAAC,KAAK,EAAE,OAA2B,EAAE,EAAE;IAC5C,MAAM,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AAClC,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,KAAK,CAAC;KACd,WAAW,CAAC,+BAA+B,CAAC;KAC5C,QAAQ,CAAC,YAAY,EAAE,sCAAsC,CAAC;KAC9D,MAAM,CAAC,KAAK,EAAE,QAAgB,EAAE,EAAE;IACjC,MAAM,UAAU,CAAC,QAAQ,CAAC,CAAC;AAC7B,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,SAAS,CAAC;KAClB,WAAW,CAAC,mCAAmC,CAAC;KAChD,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,MAAM,cAAc,EAAE,CAAC;AACzB,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,KAAK,CAAC,IAAI,CAAC;KACX,WAAW,CAAC,6BAA6B,CAAC;KAC1C,QAAQ,CAAC,YAAY,EAAE,mCAAmC,CAAC;KAC3D,MAAM,CAAC,WAAW,EAAE,mBAAmB,CAAC;KACxC,MAAM,CAAC,KAAK,EAAE,QAAgB,EAAE,OAA0B,EAAE,EAAE;IAC7D,MAAM,aAAa,CAAC,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;AAC7C,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,KAAK,EAAE,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,OAAO,CAAC;KACb,WAAW,CAAC,4DAA4D,CAAC;KACzE,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;KACJ,OAAO,CAAC,UAAU,CAAC;KACnB,WAAW,CAAC,+BAA+B,CAAC;KAC5C,QAAQ,CAAC,YAAY,EAAE,kCAAkC,CAAC;KAC1D,MAAM,CAAC,KAAK,EAAE,QAAgB,EAAE,EAAE;IACjC,MAAM,eAAe,CAAC,QAAQ,CAAC,CAAC;AAClC,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,KAAK,CAAC,IAAI,CAAC;KACX,WAAW,CAAC,8BAA8B,CAAC;KAC3C,MAAM,CAAC,YAAY,EAAE,uBAAuB,CAAC;KAC7C,MAAM,CAAC,KAAK,EAAE,OAA2B,EAAE,EAAE;IAC5C,MAAM,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AAClC,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,KAAK,CAAC;KACd,WAAW,CAAC,+BAA+B,CAAC;KAC5C,QAAQ,CAAC,YAAY,EAAE,sCAAsC,CAAC;KAC9D,MAAM,CAAC,KAAK,EAAE,QAAgB,EAAE,EAAE;IACjC,MAAM,UAAU,CAAC,QAAQ,CAAC,CAAC;AAC7B,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,SAAS,CAAC;KAClB,WAAW,CAAC,mCAAmC,CAAC;KAChD,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,MAAM,cAAc,EAAE,CAAC;AACzB,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,KAAK,CAAC,IAAI,CAAC;KACX,WAAW,CAAC,6BAA6B,CAAC;KAC1C,QAAQ,CAAC,YAAY,EAAE,mCAAmC,CAAC;KAC3D,MAAM,CAAC,WAAW,EAAE,mBAAmB,CAAC;KACxC,MAAM,CAAC,KAAK,EAAE,QAAgB,EAAE,OAA0B,EAAE,EAAE;IAC7D,MAAM,aAAa,CAAC,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;AAC7C,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -1,7 +1,7 @@
1
1
  import * as path from 'node:path';
2
2
  import * as os from 'node:os';
3
3
  import { promises as fs } from 'node:fs';
4
- const GEMX_DIR = '.gemx';
4
+ const GEMX_DIR = '.gemix';
5
5
  const GEMINI_DIR = '.gemini';
6
6
  const ACCOUNTS_FILE = 'accounts.json';
7
7
  const ACTIVE_FILE = 'active';
@@ -1 +1 @@
1
- {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/storage/paths.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AAEzC,MAAM,QAAQ,GAAG,OAAO,CAAC;AACzB,MAAM,UAAU,GAAG,SAAS,CAAC;AAC7B,MAAM,aAAa,GAAG,eAAe,CAAC;AACtC,MAAM,WAAW,GAAG,QAAQ,CAAC;AAC7B,MAAM,YAAY,GAAG,UAAU,CAAC;AAChC,MAAM,gBAAgB,GAAG,kBAAkB,CAAC;AAC5C,MAAM,oBAAoB,GAAG,sBAAsB,CAAC;AAEpD,MAAM,UAAU,UAAU;IACxB,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,mBAAmB;IACjC,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,aAAa,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,WAAW,CAAC,CAAC;AAC9C,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,YAAY,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,QAAgB;IAC5C,OAAO,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,QAAQ,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,QAAgB;IACnD,OAAO,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,EAAE,aAAa,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,UAAU,uBAAuB;IACrC,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,gBAAgB,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,2BAA2B;IACzC,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,oBAAoB,CAAC,CAAC;AACnE,CAAC;AAED,MAAM,UAAU,4BAA4B;IAC1C,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,iBAAiB,EAAE,yBAAyB,CAAC,CAAC;AAC3F,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,MAAM,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAClD,MAAM,EAAE,CAAC,KAAK,CAAC,cAAc,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AACxD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,QAAgB;IACrD,MAAM,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAC/D,CAAC"}
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/storage/paths.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AAEzC,MAAM,QAAQ,GAAG,QAAQ,CAAC;AAC1B,MAAM,UAAU,GAAG,SAAS,CAAC;AAC7B,MAAM,aAAa,GAAG,eAAe,CAAC;AACtC,MAAM,WAAW,GAAG,QAAQ,CAAC;AAC7B,MAAM,YAAY,GAAG,UAAU,CAAC;AAChC,MAAM,gBAAgB,GAAG,kBAAkB,CAAC;AAC5C,MAAM,oBAAoB,GAAG,sBAAsB,CAAC;AAEpD,MAAM,UAAU,UAAU;IACxB,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,mBAAmB;IACjC,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,aAAa,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,WAAW,CAAC,CAAC;AAC9C,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,YAAY,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,QAAgB;IAC5C,OAAO,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,QAAQ,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,QAAgB;IACnD,OAAO,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,EAAE,aAAa,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,UAAU,uBAAuB;IACrC,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,gBAAgB,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,2BAA2B;IACzC,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,oBAAoB,CAAC,CAAC;AACnE,CAAC;AAED,MAAM,UAAU,4BAA4B;IAC1C,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,iBAAiB,EAAE,yBAAyB,CAAC,CAAC;AAC3F,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,MAAM,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAClD,MAAM,EAAE,CAAC,KAAK,CAAC,cAAc,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AACxD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,QAAgB;IACrD,MAAM,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAC/D,CAAC"}
package/doc/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # gemx - Gemini Multi-Account CLI
1
+ # gemix - Gemini Multi-Account CLI
2
2
 
3
3
  Manage multiple Google accounts for Gemini API access from a single CLI tool.
4
4
 
@@ -8,7 +8,7 @@ Manage multiple Google accounts for Gemini API access from a single CLI tool.
8
8
 
9
9
  ```bash
10
10
  git clone <repo-url>
11
- cd gemx
11
+ cd gemix
12
12
  npm install
13
13
  npm run build
14
14
  npm link
@@ -23,46 +23,46 @@ npm link
23
23
 
24
24
  ```bash
25
25
  # Register your first account
26
- gemx register personal
26
+ gemix register personal
27
27
 
28
28
  # Register another account
29
- gemx register work
29
+ gemix register work
30
30
 
31
31
  # List all accounts
32
- gemx list
32
+ gemix list
33
33
 
34
34
  # Switch accounts
35
- gemx use work
35
+ gemix use work
36
36
 
37
37
  # Check active account
38
- gemx current
38
+ gemix current
39
39
 
40
40
  # Remove an account
41
- gemx remove personal
41
+ gemix remove personal
42
42
  ```
43
43
 
44
44
  ## Commands
45
45
 
46
46
  | Command | Description |
47
47
  |---------|-------------|
48
- | `gemx register <username>` | Register a new Google account via OAuth |
49
- | `gemx list` | List all registered accounts |
50
- | `gemx list --json` | Output in JSON format |
51
- | `gemx use <username>` | Switch active account |
52
- | `gemx current` | Show active account |
53
- | `gemx remove <username>` | Remove an account |
48
+ | `gemix register <username>` | Register a new Google account via OAuth |
49
+ | `gemix list` | List all registered accounts |
50
+ | `gemix list --json` | Output in JSON format |
51
+ | `gemix use <username>` | Switch active account |
52
+ | `gemix current` | Show active account |
53
+ | `gemix remove <username>` | Remove an account |
54
54
 
55
55
  ## How It Works
56
56
 
57
57
  ### Storage
58
58
 
59
- - `~/.gemx/accounts.json` - Master registry of all accounts
60
- - `~/.gemx/accounts/<username>/tokens.json` - Per-account OAuth tokens
59
+ - `~/.gemix/accounts.json` - Master registry of all accounts
60
+ - `~/.gemix/accounts/<username>/tokens.json` - Per-account OAuth tokens
61
61
  - `~/.gemini/oauth_creds.json` - Gemini CLI reads from here
62
62
 
63
63
  ### Account Switching
64
64
 
65
- When you run `gemx use <username>`, it copies that account's tokens to `~/.gemini/oauth_creds.json` where Gemini CLI expects them.
65
+ When you run `gemix use <username>`, it copies that account's tokens to `~/.gemini/oauth_creds.json` where Gemini CLI expects them.
66
66
 
67
67
  ### OAuth Flow
68
68
 
@@ -79,11 +79,11 @@ Uses the same OAuth Client ID as Gemini CLI (public for installed apps). Your cr
79
79
 
80
80
  | Issue | Solution |
81
81
  |-------|----------|
82
- | "Account already exists" | Run `gemx remove <username>` first |
83
- | "Account not found" | Run `gemx list` to see available accounts |
82
+ | "Account already exists" | Run `gemix remove <username>` first |
83
+ | "Account not found" | Run `gemix list` to see available accounts |
84
84
  | Browser doesn't open | Visit the URL shown in the terminal manually |
85
85
  | Auth timed out | Try again, complete login within 5 minutes |
86
- | "No active account" | Run `gemx register <username>` to add one |
86
+ | "No active account" | Run `gemix register <username>` to add one |
87
87
 
88
88
  ## License
89
89
 
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "gemix",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "description": "Gemini multi-account CLI - manage multiple Google accounts for Gemini API",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "bin": {
8
- "gemx": "./dist/index.js"
8
+ "gemix": "./dist/index.js"
9
9
  },
10
10
  "scripts": {
11
11
  "build": "tsc",
@@ -13,12 +13,17 @@
13
13
  "start": "node dist/index.js",
14
14
  "link": "npm run build && npm link"
15
15
  },
16
- "keywords": ["gemini", "google", "oauth", "multi-account", "cli"],
16
+ "keywords": [
17
+ "gemini",
18
+ "google",
19
+ "oauth",
20
+ "multi-account",
21
+ "cli"
22
+ ],
17
23
  "author": "",
18
24
  "license": "MIT",
19
25
  "dependencies": {
20
26
  "commander": "^12.1.0",
21
- "google-auth-library": "^9.15.1",
22
27
  "open": "^10.1.0",
23
28
  "cli-table3": "^0.6.5"
24
29
  },
package/src/auth/oauth.ts CHANGED
@@ -1,29 +1,31 @@
1
- import { OAuth2Client } from 'google-auth-library';
2
- import * as http from 'node:http';
3
- import * as url from 'node:url';
4
- import * as net from 'node:net';
5
1
  import * as crypto from 'node:crypto';
2
+ import * as readline from 'node:readline';
6
3
  import open from 'open';
7
4
  import type { TokenData } from '../storage/accounts.js';
8
5
 
9
- // OAuth Client ID (same as Gemini CLI - public for installed apps)
10
6
  const OAUTH_CLIENT_ID =
11
- '681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j.apps.googleusercontent.com';
7
+ '1071006060591-tmhssin2h21lcre235vtolojh4g403ep.apps.googleusercontent.com';
12
8
 
13
- const OAUTH_CLIENT_SECRET = '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';
9
+ const OAUTH_CLIENT_SECRET = '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';
14
10
 
15
11
  const OAUTH_SCOPE = [
16
12
  'openid',
17
13
  'https://www.googleapis.com/auth/cloud-platform',
18
14
  'https://www.googleapis.com/auth/userinfo.email',
19
15
  'https://www.googleapis.com/auth/userinfo.profile',
16
+ 'https://www.googleapis.com/auth/cclog',
17
+ 'https://www.googleapis.com/auth/experimentsandconfigs',
20
18
  ];
21
19
 
22
- const HTTP_REDIRECT = 301;
23
- const SIGN_IN_SUCCESS_URL =
24
- 'https://developers.google.com/gemini-code-assist/auth_success_gemini';
25
- const SIGN_IN_FAILURE_URL =
26
- 'https://developers.google.com/gemini-code-assist/auth_failure_gemini';
20
+ const REDIRECT_URI = 'https://antigravity.google/oauth-callback';
21
+
22
+ function generateCodeVerifier(): string {
23
+ return crypto.randomBytes(32).toString('base64url');
24
+ }
25
+
26
+ function generateCodeChallenge(verifier: string): string {
27
+ return crypto.createHash('sha256').update(verifier).digest('base64url');
28
+ }
27
29
 
28
30
  export interface OAuthResult {
29
31
  tokens: TokenData;
@@ -32,87 +34,27 @@ export interface OAuthResult {
32
34
  picture?: string;
33
35
  }
34
36
 
35
- function getAvailablePort(): Promise<number> {
36
- return new Promise((resolve, reject) => {
37
- const server = net.createServer();
38
- server.listen(0, () => {
39
- const address = server.address();
40
- const port = address && typeof address === 'object' ? address.port : 0;
41
- server.close(() => resolve(port));
42
- });
43
- server.on('error', reject);
44
- });
45
- }
46
-
47
37
  export async function authenticateWithGoogle(): Promise<OAuthResult> {
48
- const client = new OAuth2Client({
49
- clientId: OAUTH_CLIENT_ID,
50
- clientSecret: OAUTH_CLIENT_SECRET,
51
- });
52
-
53
- const port = await getAvailablePort();
54
- const redirectUri = `http://127.0.0.1:${port}/oauth2callback`;
55
38
  const state = crypto.randomBytes(32).toString('hex');
56
-
57
- const authUrl = client.generateAuthUrl({
58
- redirect_uri: redirectUri,
39
+ const codeVerifier = generateCodeVerifier();
40
+ const codeChallenge = generateCodeChallenge(codeVerifier);
41
+
42
+ const authParams = new URLSearchParams({
43
+ client_id: OAUTH_CLIENT_ID,
44
+ response_type: 'code',
45
+ redirect_uri: REDIRECT_URI,
46
+ scope: OAUTH_SCOPE.join(' '),
59
47
  access_type: 'offline',
60
- scope: OAUTH_SCOPE,
61
48
  prompt: 'consent',
62
49
  state,
50
+ code_challenge: codeChallenge,
51
+ code_challenge_method: 'S256',
63
52
  });
64
53
 
65
- const loginCompletePromise = new Promise<{
66
- code: string;
67
- }>((resolve, reject) => {
68
- const server = http.createServer(async (req, res) => {
69
- try {
70
- if (!req.url || req.url.indexOf('/oauth2callback') === -1) {
71
- res.writeHead(HTTP_REDIRECT, { Location: SIGN_IN_FAILURE_URL });
72
- res.end();
73
- reject(new Error('Unexpected request: ' + req.url));
74
- return;
75
- }
76
-
77
- const qs = new url.URL(req.url, `http://127.0.0.1:${port}`).searchParams;
78
-
79
- if (qs.get('error')) {
80
- res.writeHead(HTTP_REDIRECT, { Location: SIGN_IN_FAILURE_URL });
81
- res.end();
82
- reject(new Error(`Google OAuth error: ${qs.get('error')}. ${qs.get('error_description') || ''}`));
83
- return;
84
- }
85
-
86
- if (qs.get('state') !== state) {
87
- res.writeHead(200, { 'Content-Type': 'text/html' });
88
- res.end('<h1>State mismatch. Possible CSRF attack.</h1>');
89
- reject(new Error('State mismatch. Possible CSRF attack.'));
90
- return;
91
- }
92
-
93
- if (qs.get('code')) {
94
- res.writeHead(HTTP_REDIRECT, { Location: SIGN_IN_SUCCESS_URL });
95
- res.end();
96
- resolve({ code: qs.get('code')! });
97
- } else {
98
- res.writeHead(HTTP_REDIRECT, { Location: SIGN_IN_FAILURE_URL });
99
- res.end();
100
- reject(new Error('No authorization code received.'));
101
- }
102
- } catch (e) {
103
- res.writeHead(HTTP_REDIRECT, { Location: SIGN_IN_FAILURE_URL });
104
- res.end();
105
- reject(e instanceof Error ? e : new Error(String(e)));
106
- } finally {
107
- server.close();
108
- }
109
- });
110
-
111
- server.listen(port, '127.0.0.1', () => {});
112
- server.on('error', reject);
113
- });
54
+ const authUrl = `https://accounts.google.com/o/oauth2/auth?${authParams.toString()}`;
114
55
 
115
56
  console.log('\nOpening browser for Google authentication...\n');
57
+ console.log('After signing in, copy the authorization code from the redirect page.\n');
116
58
  console.log(`If the browser doesn't open, visit:\n${authUrl}\n`);
117
59
 
118
60
  const childProcess = await open(authUrl);
@@ -121,109 +63,130 @@ export async function authenticateWithGoogle(): Promise<OAuthResult> {
121
63
  console.log(`Please visit:\n${authUrl}\n`);
122
64
  });
123
65
 
124
- const authTimeout = 5 * 60 * 1000;
125
- let timeoutId: NodeJS.Timeout | undefined;
126
-
127
- const timeoutPromise = new Promise<never>((_, reject) => {
128
- timeoutId = setTimeout(() => {
129
- reject(new Error('Authentication timed out after 5 minutes.'));
130
- }, authTimeout);
131
- });
132
-
133
- const cancellationPromise = new Promise<never>((_, reject) => {
134
- process.on('SIGINT', () => {
135
- reject(new Error('Authentication cancelled by user.'));
136
- });
137
- });
138
-
139
- try {
140
- const { code } = await Promise.race([
141
- loginCompletePromise,
142
- timeoutPromise,
143
- cancellationPromise,
144
- ]);
145
-
146
- if (timeoutId) clearTimeout(timeoutId);
147
-
148
- const { tokens } = await client.getToken({
66
+ const code = await promptForAuthCode();
67
+
68
+ const startTime = Date.now();
69
+ const tokenResponse = await fetch('https://oauth2.googleapis.com/token', {
70
+ method: 'POST',
71
+ headers: {
72
+ 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
73
+ },
74
+ body: new URLSearchParams({
75
+ client_id: OAUTH_CLIENT_ID,
76
+ client_secret: OAUTH_CLIENT_SECRET,
149
77
  code,
150
- redirect_uri: redirectUri,
151
- });
152
-
153
- client.setCredentials(tokens);
154
-
155
- const userInfo = await fetchUserInfo(client);
78
+ grant_type: 'authorization_code',
79
+ redirect_uri: REDIRECT_URI,
80
+ code_verifier: codeVerifier,
81
+ }),
82
+ });
156
83
 
157
- return {
158
- tokens: {
159
- access_token: tokens.access_token || '',
160
- refresh_token: tokens.refresh_token || '',
161
- id_token: tokens.id_token || '',
162
- scope: tokens.scope || OAUTH_SCOPE.join(' '),
163
- token_type: tokens.token_type || 'Bearer',
164
- expiry_date: tokens.expiry_date || Date.now(),
165
- },
166
- email: userInfo.email,
167
- name: userInfo.name,
168
- picture: userInfo.picture,
169
- };
170
- } finally {
171
- if (timeoutId) clearTimeout(timeoutId);
84
+ if (!tokenResponse.ok) {
85
+ const errorText = await tokenResponse.text();
86
+ throw new Error(`Token exchange failed: ${tokenResponse.status} ${errorText}`);
172
87
  }
173
- }
174
88
 
175
- async function fetchUserInfo(client: OAuth2Client): Promise<{
176
- email: string;
177
- name: string;
178
- picture?: string;
179
- }> {
180
- const { token } = await client.getAccessToken();
181
- if (!token) throw new Error('No access token available');
89
+ const tokenPayload = (await tokenResponse.json()) as {
90
+ access_token: string;
91
+ refresh_token: string;
92
+ expires_in: number;
93
+ token_type: string;
94
+ scope: string;
95
+ };
182
96
 
183
- const response = await fetch('https://www.googleapis.com/oauth2/v2/userinfo', {
184
- headers: { Authorization: `Bearer ${token}` },
97
+ const userInfoResponse = await fetch('https://www.googleapis.com/oauth2/v2/userinfo', {
98
+ headers: { Authorization: `Bearer ${tokenPayload.access_token}` },
185
99
  });
186
100
 
187
- if (!response.ok) {
188
- throw new Error(`Failed to fetch user info: ${response.status} ${response.statusText}`);
101
+ if (!userInfoResponse.ok) {
102
+ throw new Error(`Failed to fetch user info: ${userInfoResponse.status} ${userInfoResponse.statusText}`);
189
103
  }
190
104
 
191
- const userInfo = (await response.json()) as {
105
+ const userInfo = (await userInfoResponse.json()) as {
192
106
  email: string;
193
107
  name: string;
194
108
  picture?: string;
195
109
  };
196
110
 
197
111
  return {
112
+ tokens: {
113
+ access_token: tokenPayload.access_token,
114
+ refresh_token: tokenPayload.refresh_token,
115
+ id_token: '',
116
+ scope: tokenPayload.scope || OAUTH_SCOPE.join(' '),
117
+ token_type: tokenPayload.token_type || 'Bearer',
118
+ expiry_date: startTime + tokenPayload.expires_in * 1000,
119
+ },
198
120
  email: userInfo.email,
199
121
  name: userInfo.name,
200
122
  picture: userInfo.picture,
201
123
  };
202
124
  }
203
125
 
126
+ function promptForAuthCode(): Promise<string> {
127
+ return new Promise((resolve, reject) => {
128
+ const rl = readline.createInterface({
129
+ input: process.stdin,
130
+ output: process.stdout,
131
+ });
132
+
133
+ const authTimeout = 5 * 60 * 1000;
134
+ const timeoutId = setTimeout(() => {
135
+ rl.close();
136
+ reject(new Error('Authentication timed out after 5 minutes.'));
137
+ }, authTimeout);
138
+
139
+ const onSigint = () => {
140
+ clearTimeout(timeoutId);
141
+ rl.close();
142
+ reject(new Error('Authentication cancelled by user.'));
143
+ };
144
+ process.on('SIGINT', onSigint);
145
+
146
+ rl.question('Paste the authorization code: ', (answer) => {
147
+ clearTimeout(timeoutId);
148
+ process.removeListener('SIGINT', onSigint);
149
+ rl.close();
150
+ const code = answer.trim();
151
+ if (!code) {
152
+ reject(new Error('No authorization code provided.'));
153
+ } else {
154
+ resolve(code);
155
+ }
156
+ });
157
+ });
158
+ }
159
+
204
160
  export async function refreshTokens(tokens: TokenData): Promise<TokenData | null> {
205
161
  try {
206
- const client = new OAuth2Client({
207
- clientId: OAUTH_CLIENT_ID,
208
- clientSecret: OAUTH_CLIENT_SECRET,
162
+ const tokenResponse = await fetch('https://oauth2.googleapis.com/token', {
163
+ method: 'POST',
164
+ headers: {
165
+ 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
166
+ },
167
+ body: new URLSearchParams({
168
+ client_id: OAUTH_CLIENT_ID,
169
+ client_secret: OAUTH_CLIENT_SECRET,
170
+ refresh_token: tokens.refresh_token,
171
+ grant_type: 'refresh_token',
172
+ }),
209
173
  });
210
174
 
211
- client.setCredentials({
212
- access_token: tokens.access_token,
213
- refresh_token: tokens.refresh_token,
214
- });
175
+ if (!tokenResponse.ok) return null;
215
176
 
216
- const { token: newAccessToken } = await client.getAccessToken();
217
- if (!newAccessToken) return null;
177
+ const tokenPayload = (await tokenResponse.json()) as {
178
+ access_token: string;
179
+ expires_in: number;
180
+ token_type: string;
181
+ };
218
182
 
219
- const credentials = client.credentials;
220
183
  return {
221
- access_token: newAccessToken,
222
- refresh_token: credentials.refresh_token || tokens.refresh_token,
223
- id_token: credentials.id_token || tokens.id_token || '',
184
+ access_token: tokenPayload.access_token,
185
+ refresh_token: tokens.refresh_token,
186
+ id_token: tokens.id_token || '',
224
187
  scope: tokens.scope,
225
- token_type: tokens.token_type,
226
- expiry_date: credentials.expiry_date || Date.now() + 3600 * 1000,
188
+ token_type: tokenPayload.token_type || 'Bearer',
189
+ expiry_date: Date.now() + tokenPayload.expires_in * 1000,
227
190
  };
228
191
  } catch {
229
192
  return null;
@@ -7,8 +7,8 @@ export async function currentCommand(): Promise<void> {
7
7
 
8
8
  if (!activeUsername || !accounts.accounts[activeUsername]) {
9
9
  console.log('No active account.');
10
- console.log('Use "gemx list" to see available accounts.');
11
- console.log('Use "gemx use <username>" to switch accounts.');
10
+ console.log('Use "gemix list" to see available accounts.');
11
+ console.log('Use "gemix use <username>" to switch accounts.');
12
12
  return;
13
13
  }
14
14
 
@@ -7,7 +7,7 @@ export async function listCommand(json: boolean = false): Promise<void> {
7
7
 
8
8
  if (Object.keys(accounts.accounts).length === 0) {
9
9
  console.log('No accounts registered.');
10
- console.log('Run "gemx register <username>" to add an account.');
10
+ console.log('Run "gemix register <username>" to add an account.');
11
11
  return;
12
12
  }
13
13
 
@@ -13,7 +13,7 @@ export async function registerCommand(username: string): Promise<void> {
13
13
  const accounts = await loadAccounts();
14
14
  if (accounts.accounts[username]) {
15
15
  console.error(`Error: Account '${username}' already exists.`);
16
- console.error(`Use 'gemx remove ${username}' to remove it first.`);
16
+ console.error(`Use 'gemix remove ${username}' to remove it first.`);
17
17
  process.exit(1);
18
18
  }
19
19
 
@@ -6,7 +6,7 @@ export async function removeCommand(username: string, yes: boolean = false): Pro
6
6
 
7
7
  if (!accounts.accounts[username]) {
8
8
  console.error(`Error: Account '${username}' not found.`);
9
- console.error('Use "gemx list" to see available accounts.');
9
+ console.error('Use "gemix list" to see available accounts.');
10
10
  process.exit(1);
11
11
  }
12
12
 
@@ -5,7 +5,7 @@ export async function useCommand(username: string): Promise<void> {
5
5
 
6
6
  if (!accounts.accounts[username]) {
7
7
  console.error(`Error: Account '${username}' not found.`);
8
- console.error('Use "gemx list" to see available accounts.');
8
+ console.error('Use "gemix list" to see available accounts.');
9
9
  process.exit(1);
10
10
  }
11
11
 
package/src/index.ts CHANGED
@@ -10,7 +10,7 @@ import { removeCommand } from './commands/remove.js';
10
10
  const program = new Command();
11
11
 
12
12
  program
13
- .name('gemx')
13
+ .name('gemix')
14
14
  .description('Gemini multi-account CLI - manage multiple Google accounts')
15
15
  .version('1.0.0');
16
16
 
@@ -2,7 +2,7 @@ import * as path from 'node:path';
2
2
  import * as os from 'node:os';
3
3
  import { promises as fs } from 'node:fs';
4
4
 
5
- const GEMX_DIR = '.gemx';
5
+ const GEMX_DIR = '.gemix';
6
6
  const GEMINI_DIR = '.gemini';
7
7
  const ACCOUNTS_FILE = 'accounts.json';
8
8
  const ACTIVE_FILE = 'active';