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/atris/skills/calendar/SKILL.md +3 -3
- package/atris/skills/email-agent/SKILL.md +42 -2
- package/atris/skills/notion/SKILL.md +478 -0
- package/atris/skills/slides/SKILL.md +355 -0
- package/bin/atris.js +35 -109
- package/commands/auth.js +97 -2
- package/commands/integrations.js +26 -12
- package/commands/plugin.js +450 -0
- package/commands/sync.js +87 -1
- package/package.json +1 -1
- package/utils/auth.js +72 -3
- package/utils/update-check.js +33 -0
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
|
|
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
|
-
|
|
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
|
};
|
package/utils/update-check.js
CHANGED
|
@@ -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
|
|