atris 2.2.2 → 2.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/utils/auth.js CHANGED
@@ -109,15 +109,74 @@ function shouldRefreshToken(token, bufferSeconds = TOKEN_REFRESH_BUFFER_SECONDS)
109
109
  }
110
110
 
111
111
  // Credentials management
112
- function getCredentialsPath() {
112
+ function getAtrisDir() {
113
113
  const homeDir = os.homedir();
114
114
  const atrisDir = path.join(homeDir, '.atris');
115
-
116
115
  if (!fs.existsSync(atrisDir)) {
117
116
  fs.mkdirSync(atrisDir, { recursive: true });
118
117
  }
118
+ return atrisDir;
119
+ }
120
+
121
+ function getCredentialsPath() {
122
+ return path.join(getAtrisDir(), 'credentials.json');
123
+ }
119
124
 
120
- return path.join(atrisDir, 'credentials.json');
125
+ function getProfilesDir() {
126
+ const dir = path.join(getAtrisDir(), 'profiles');
127
+ if (!fs.existsSync(dir)) {
128
+ fs.mkdirSync(dir, { recursive: true });
129
+ }
130
+ return dir;
131
+ }
132
+
133
+ function profileNameFromEmail(email) {
134
+ if (!email) return null;
135
+ // "keshav@atrislabs.com" → "keshav"
136
+ return email.split('@')[0].toLowerCase().replace(/[^a-z0-9_-]/g, '-');
137
+ }
138
+
139
+ function saveProfile(name, credentials) {
140
+ const profilePath = path.join(getProfilesDir(), `${name}.json`);
141
+ fs.writeFileSync(profilePath, JSON.stringify(credentials, null, 2));
142
+ try { fs.chmodSync(profilePath, 0o600); } catch {}
143
+ }
144
+
145
+ function loadProfile(name) {
146
+ const profilePath = path.join(getProfilesDir(), `${name}.json`);
147
+ if (!fs.existsSync(profilePath)) return null;
148
+ try {
149
+ return JSON.parse(fs.readFileSync(profilePath, 'utf8'));
150
+ } catch {
151
+ return null;
152
+ }
153
+ }
154
+
155
+ function listProfiles() {
156
+ const dir = getProfilesDir();
157
+ try {
158
+ return fs.readdirSync(dir)
159
+ .filter(f => f.endsWith('.json'))
160
+ .map(f => f.replace('.json', ''));
161
+ } catch {
162
+ return [];
163
+ }
164
+ }
165
+
166
+ function deleteProfile(name) {
167
+ const profilePath = path.join(getProfilesDir(), `${name}.json`);
168
+ if (fs.existsSync(profilePath)) {
169
+ fs.unlinkSync(profilePath);
170
+ return true;
171
+ }
172
+ return false;
173
+ }
174
+
175
+ function autoSaveProfile(credentials) {
176
+ const name = profileNameFromEmail(credentials?.email);
177
+ if (name) {
178
+ saveProfile(name, credentials);
179
+ }
121
180
  }
122
181
 
123
182
  function saveCredentials(token, refreshToken, email, userId, provider) {
@@ -137,6 +196,9 @@ function saveCredentials(token, refreshToken, email, userId, provider) {
137
196
  } catch {
138
197
  // Best effort: permissions may be unsupported on this platform.
139
198
  }
199
+
200
+ // Auto-save as named profile
201
+ autoSaveProfile(credentials);
140
202
  }
141
203
 
142
204
  function loadCredentials() {
@@ -384,4 +446,11 @@ module.exports = {
384
446
  ensureValidCredentials,
385
447
  fetchMyAgents,
386
448
  displayAccountSummary,
449
+ // Profile switching
450
+ saveProfile,
451
+ loadProfile,
452
+ listProfiles,
453
+ deleteProfile,
454
+ profileNameFromEmail,
455
+ autoSaveProfile,
387
456
  };
@@ -175,8 +175,41 @@ function showUpdateNotification(updateInfo) {
175
175
  console.log('');
176
176
  }
177
177
 
178
+ function autoUpdate(updateInfo) {
179
+ if (!updateInfo || !updateInfo.needsUpdate) return false;
180
+
181
+ const { execSync } = require('child_process');
182
+
183
+ console.log('');
184
+ console.log(`⬆️ Updating atris ${updateInfo.installed} → ${updateInfo.latest}...`);
185
+
186
+ try {
187
+ execSync('npm update -g atris', { stdio: 'pipe', timeout: 30000 });
188
+ console.log(`✅ Updated to ${updateInfo.latest}`);
189
+
190
+ // Auto-sync skills into current project if atris/skills/ exists
191
+ try {
192
+ if (fs.existsSync(path.join(process.cwd(), 'atris', 'skills'))) {
193
+ execSync('atris sync', { stdio: 'pipe', timeout: 10000 });
194
+ console.log(`✅ Skills synced`);
195
+ }
196
+ } catch (e) {
197
+ // Sync failed — not critical
198
+ }
199
+
200
+ console.log('');
201
+ return true;
202
+ } catch (error) {
203
+ // npm update failed (permissions, network, etc) — fall back to notification
204
+ console.log(`⚠️ Auto-update failed. Run manually: npm update -g atris`);
205
+ console.log('');
206
+ return false;
207
+ }
208
+ }
209
+
178
210
  module.exports = {
179
211
  checkForUpdates,
180
212
  showUpdateNotification,
213
+ autoUpdate,
181
214
  };
182
215