← back to George Gmail
Add agentabrams (theagentabrams@gmail.com) as 5th george account slot
23979b00576396015f9d96eaff1733cabfde3835 · 2026-05-18 14:21:06 -0700 · Steve Abrams
Files touched
Diff
commit 23979b00576396015f9d96eaff1733cabfde3835
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Mon May 18 14:21:06 2026 -0700
Add agentabrams (theagentabrams@gmail.com) as 5th george account slot
---
server.js | 148 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 147 insertions(+), 1 deletion(-)
diff --git a/server.js b/server.js
index 6dba3af..34dbf39 100644
--- a/server.js
+++ b/server.js
@@ -65,6 +65,12 @@ const STEVESCLAUDE_REDIRECT_URI = 'http://localhost:9850/oauth2callback';
const STEVESCLAUDE_REFRESH_TOKEN = creds.STEVESCLAUDE_REFRESH_TOKEN || process.env.STEVESCLAUDE_REFRESH_TOKEN;
const STEVESCLAUDE_LOGIN_HINT = creds.STEVESCLAUDE_LOGIN_HINT || process.env.STEVESCLAUDE_LOGIN_HINT || 'stevesclaude@gmail.com';
+// ─── Agent Abrams (theagentabrams@gmail.com) Credentials ───
+// Reuses GMAIL_CLIENT_ID/SECRET. Added 2026-05-18 per Steve.
+const AGENTABRAMS_REDIRECT_URI = 'http://localhost:9850/oauth2callback';
+const AGENTABRAMS_REFRESH_TOKEN = creds.AGENTABRAMS_REFRESH_TOKEN || process.env.AGENTABRAMS_REFRESH_TOKEN;
+const AGENTABRAMS_LOGIN_HINT = creds.AGENTABRAMS_LOGIN_HINT || process.env.AGENTABRAMS_LOGIN_HINT || 'theagentabrams@gmail.com';
+
// ─── OAuth2 Scopes ───
// FULL_WORKSPACE_SCOPES = unified scope list for all 3 accounts.
// Steve approved including Forms (Q3=y) so we don't have to re-OAuth later.
@@ -192,8 +198,31 @@ try {
console.error(`[${AGENT_NAME}] StevesClaude client error: ${e.message}`);
}
+// ─── Agent Abrams (theagentabrams@gmail.com) account ───
+let agentabramsOauth2Client;
+let agentabramsGmail, agentabramsTasksApi, agentabramsDrive, agentabramsDocs, agentabramsSheets, agentabramsSlides, agentabramsCalendar, agentabramsForms;
+try {
+ agentabramsOauth2Client = new google.auth.OAuth2(GMAIL_CLIENT_ID, GMAIL_CLIENT_SECRET, AGENTABRAMS_REDIRECT_URI);
+ if (AGENTABRAMS_REFRESH_TOKEN) {
+ agentabramsOauth2Client.setCredentials({ refresh_token: AGENTABRAMS_REFRESH_TOKEN });
+ agentabramsGmail = google.gmail ({ version: 'v1', auth: agentabramsOauth2Client });
+ agentabramsTasksApi = google.tasks ({ version: 'v1', auth: agentabramsOauth2Client });
+ agentabramsDrive = google.drive ({ version: 'v3', auth: agentabramsOauth2Client });
+ agentabramsDocs = google.docs ({ version: 'v1', auth: agentabramsOauth2Client });
+ agentabramsSheets = google.sheets ({ version: 'v4', auth: agentabramsOauth2Client });
+ agentabramsSlides = google.slides ({ version: 'v1', auth: agentabramsOauth2Client });
+ agentabramsCalendar = google.calendar({ version: 'v3', auth: agentabramsOauth2Client });
+ agentabramsForms = google.forms ({ version: 'v1', auth: agentabramsOauth2Client });
+ console.log(`[${AGENT_NAME}] Agent Abrams account initialized (full Workspace)`);
+ } else {
+ console.log(`[${AGENT_NAME}] Agent Abrams not configured — visit /auth/agentabrams to authorize`);
+ }
+} catch (e) {
+ console.error(`[${AGENT_NAME}] Agent Abrams client error: ${e.message}`);
+}
+
// ─── Account resolver for per-service API endpoints ───
-// account query/body param: "steve-office" (default), "info", "steve-personal", "stevesclaude"
+// account query/body param: "steve-office" (default), "info", "steve-personal", "stevesclaude", "agentabrams"
function resolveAccount(req) {
const key = (req.query.account || req.body?.account || 'steve-office').toLowerCase();
const map = {
@@ -201,6 +230,7 @@ function resolveAccount(req) {
'info': { label: 'info@designerwallcoverings.com', oauth: infoOauth2Client, gmail: infoGmail, tasks: infoTasksApi, drive: infoDrive, docs: infoDocs, sheets: infoSheets, slides: infoSlides, calendar: infoCalendar, forms: infoForms, refreshToken: INFO_REFRESH_TOKEN },
'steve-personal': { label: 'steveabramsdesigns@gmail.com', oauth: personalOauth2Client, gmail: personalGmail, tasks: personalTasksApi, drive: personalDrive, docs: personalDocs, sheets: personalSheets, slides: personalSlides, calendar: personalCalendar, forms: personalForms, refreshToken: PERSONAL_REFRESH_TOKEN },
'stevesclaude': { label: STEVESCLAUDE_LOGIN_HINT, oauth: stevesclaudeOauth2Client, gmail: stevesclaudeGmail, tasks: stevesclaudeTasksApi, drive: stevesclaudeDrive, docs: stevesclaudeDocs, sheets: stevesclaudeSheets, slides: stevesclaudeSlides, calendar: stevesclaudeCalendar, forms: stevesclaudeForms, refreshToken: STEVESCLAUDE_REFRESH_TOKEN },
+ 'agentabrams': { label: AGENTABRAMS_LOGIN_HINT, oauth: agentabramsOauth2Client, gmail: agentabramsGmail, tasks: agentabramsTasksApi, drive: agentabramsDrive, docs: agentabramsDocs, sheets: agentabramsSheets, slides: agentabramsSlides, calendar: agentabramsCalendar, forms: agentabramsForms, refreshToken: AGENTABRAMS_REFRESH_TOKEN },
};
return { key, ...(map[key] || {}) };
}
@@ -250,6 +280,7 @@ app.get('/auth', (req, res) => {
'info': '/auth/info',
'steve-personal': '/auth/steve-personal',
'stevesclaude': '/auth/stevesclaude',
+ 'agentabrams': '/auth/agentabrams',
};
if (routes[acct]) return res.redirect(routes[acct]);
// steve-office (default, or unknown account key) — full Workspace re-auth for steve@
@@ -313,6 +344,47 @@ app.get('/oauth2callback', async (req, res) => {
return res.send(msg);
}
+ // Route to agentabrams handler if state=agentabrams
+ if (state === 'agentabrams') {
+ const { tokens } = await agentabramsOauth2Client.getToken({ code, redirect_uri: AGENTABRAMS_REDIRECT_URI });
+ agentabramsOauth2Client.setCredentials(tokens);
+ agentabramsGmail = google.gmail ({ version: 'v1', auth: agentabramsOauth2Client });
+ agentabramsTasksApi = google.tasks ({ version: 'v1', auth: agentabramsOauth2Client });
+ agentabramsDrive = google.drive ({ version: 'v3', auth: agentabramsOauth2Client });
+ agentabramsDocs = google.docs ({ version: 'v1', auth: agentabramsOauth2Client });
+ agentabramsSheets = google.sheets ({ version: 'v4', auth: agentabramsOauth2Client });
+ agentabramsSlides = google.slides ({ version: 'v1', auth: agentabramsOauth2Client });
+ agentabramsCalendar = google.calendar({ version: 'v3', auth: agentabramsOauth2Client });
+ agentabramsForms = google.forms ({ version: 'v1', auth: agentabramsOauth2Client });
+
+ let msg = '<html><body style="font-family:sans-serif;background:#0f1117;color:#e4e4e7;padding:40px">';
+ msg += '<h2 style="color:#4ade80">Agent Abrams Authorized! (Full Google Workspace)</h2>';
+ if (tokens.refresh_token) {
+ msg += `<p><strong>New Agent Abrams Refresh Token:</strong></p><code style="background:#1a1d27;padding:10px;display:block;word-break:break-all;border-radius:8px">${tokens.refresh_token}</code>`;
+ console.log(`[${AGENT_NAME}] Agent Abrams refresh token obtained: ${tokens.refresh_token.substring(0, 20)}...`);
+ try {
+ let envContent = fs.readFileSync(ENV_PATH, 'utf8');
+ if (envContent.includes('AGENTABRAMS_REFRESH_TOKEN=')) {
+ envContent = envContent.replace(/AGENTABRAMS_REFRESH_TOKEN=.*/, `AGENTABRAMS_REFRESH_TOKEN=${tokens.refresh_token}`);
+ } else {
+ envContent += `\n# Agent Abrams (theagentabrams@gmail.com) OAuth Token\nAGENTABRAMS_REFRESH_TOKEN=${tokens.refresh_token}\n`;
+ }
+ fs.writeFileSync(ENV_PATH, envContent);
+ msg += '<p style="color:#4ade80">Token auto-saved to central .env!</p>';
+ audit('agentabrams', 'oauth-authorized', { scopes: FULL_WORKSPACE_SCOPES.length });
+ } catch (e) {
+ msg += `<p style="color:#f87171">Could not auto-save: ${e.message}</p>`;
+ }
+ }
+ try {
+ const profile = await agentabramsGmail.users.getProfile({ userId: 'me' });
+ msg += `<p style="color:#60a5fa">Connected as: <strong>${profile.data.emailAddress}</strong></p>`;
+ } catch {}
+ msg += '<p style="color:#a3a3a3">You can close this tab. Restart george-gmail to load the new token persistently.</p>';
+ msg += '<p><a href="/" style="color:#60a5fa">Go to Dashboard</a></p></body></html>';
+ return res.send(msg);
+ }
+
// Route to steve-personal handler if state=personal
if (state === 'personal') {
const { tokens } = await personalOauth2Client.getToken({ code, redirect_uri: PERSONAL_REDIRECT_URI });
@@ -486,6 +558,80 @@ app.get('/api/auth-url/stevesclaude', (req, res) => {
res.json({ authUrl: url, account: STEVESCLAUDE_LOGIN_HINT, scopes: FULL_WORKSPACE_SCOPES });
});
+// ─── Agent Abrams OAuth Authorization Flow ───
+app.get('/auth/agentabrams', (req, res) => {
+ if (!agentabramsOauth2Client) return res.status(500).send('Agent Abrams OAuth client not configured');
+ const url = agentabramsOauth2Client.generateAuthUrl({
+ access_type: 'offline',
+ scope: FULL_WORKSPACE_SCOPES,
+ prompt: 'consent',
+ redirect_uri: AGENTABRAMS_REDIRECT_URI,
+ login_hint: AGENTABRAMS_LOGIN_HINT,
+ state: 'agentabrams',
+ });
+ res.redirect(url);
+});
+
+app.get('/api/auth-url/agentabrams', (req, res) => {
+ if (!agentabramsOauth2Client) return res.status(500).json({ error: 'Agent Abrams OAuth client not configured' });
+ const url = agentabramsOauth2Client.generateAuthUrl({
+ access_type: 'offline',
+ scope: FULL_WORKSPACE_SCOPES,
+ prompt: 'consent',
+ redirect_uri: AGENTABRAMS_REDIRECT_URI,
+ login_hint: AGENTABRAMS_LOGIN_HINT,
+ state: 'agentabrams',
+ });
+ res.json({ authUrl: url, account: AGENTABRAMS_LOGIN_HINT, scopes: FULL_WORKSPACE_SCOPES });
+});
+
+app.get('/api/exchange-code/agentabrams', async (req, res) => {
+ try {
+ const { code } = req.query;
+ if (!code) return res.status(400).json({ error: 'code parameter required' });
+ const { tokens } = await agentabramsOauth2Client.getToken({ code, redirect_uri: AGENTABRAMS_REDIRECT_URI });
+ agentabramsOauth2Client.setCredentials(tokens);
+ agentabramsGmail = google.gmail ({ version: 'v1', auth: agentabramsOauth2Client });
+ agentabramsTasksApi = google.tasks ({ version: 'v1', auth: agentabramsOauth2Client });
+ agentabramsDrive = google.drive ({ version: 'v3', auth: agentabramsOauth2Client });
+ agentabramsDocs = google.docs ({ version: 'v1', auth: agentabramsOauth2Client });
+ agentabramsSheets = google.sheets ({ version: 'v4', auth: agentabramsOauth2Client });
+ agentabramsSlides = google.slides ({ version: 'v1', auth: agentabramsOauth2Client });
+ agentabramsCalendar = google.calendar({ version: 'v3', auth: agentabramsOauth2Client });
+ agentabramsForms = google.forms ({ version: 'v1', auth: agentabramsOauth2Client });
+
+ const result = { success: true, account: 'agentabrams', hasRefreshToken: !!tokens.refresh_token };
+ if (tokens.refresh_token) {
+ result.refreshToken = tokens.refresh_token;
+ try {
+ let envContent = fs.readFileSync(ENV_PATH, 'utf8');
+ if (envContent.includes('AGENTABRAMS_REFRESH_TOKEN=')) {
+ envContent = envContent.replace(/AGENTABRAMS_REFRESH_TOKEN=.*/, `AGENTABRAMS_REFRESH_TOKEN=${tokens.refresh_token}`);
+ } else {
+ envContent += `\n# Agent Abrams (theagentabrams@gmail.com) OAuth Token\nAGENTABRAMS_REFRESH_TOKEN=${tokens.refresh_token}\n`;
+ }
+ fs.writeFileSync(ENV_PATH, envContent);
+ result.savedToEnv = true;
+ audit('agentabrams', 'oauth-authorized', { scopes: FULL_WORKSPACE_SCOPES.length });
+ } catch (e) {
+ result.savedToEnv = false;
+ result.envError = e.message;
+ }
+ }
+ try {
+ const profile = await agentabramsGmail.users.getProfile({ userId: 'me' });
+ result.email = profile.data.emailAddress;
+ result.ready = true;
+ } catch (e) {
+ result.ready = false;
+ result.testError = e.message;
+ }
+ res.json(result);
+ } catch (e) {
+ res.status(500).json({ error: e.message });
+ }
+});
+
// ─── Steve Personal OAuth Authorization Flow ───
app.get('/auth/steve-personal', (req, res) => {
if (!personalOauth2Client) return res.status(500).send('Personal OAuth client not configured');
← ec801aa george /auth honors ?account= — dispatches to per-account re
·
back to George Gmail
·
remove bogus stevesclaude account from George — theagentabra 2cbc311 →