atris 3.67.0 → 3.68.0
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/commands/signup.js +45 -2
- package/package.json +1 -1
package/commands/signup.js
CHANGED
|
@@ -11,8 +11,10 @@
|
|
|
11
11
|
// Backend: backend/routers/agent_auth_router.py (POST /auth/agent/signup).
|
|
12
12
|
|
|
13
13
|
const crypto = require('crypto');
|
|
14
|
+
const fs = require('fs');
|
|
14
15
|
const { apiRequestJson, getApiBaseUrl } = require('../utils/api');
|
|
15
|
-
const { saveCredentials } = require('../utils/auth');
|
|
16
|
+
const { saveCredentials, saveProfile, saveAgentClientCredentials, getCredentialsPath } = require('../utils/auth');
|
|
17
|
+
const agentClient = require('../utils/agent-client');
|
|
16
18
|
const { argsWantHelp, isHelpToken } = require('../lib/noninteractive');
|
|
17
19
|
|
|
18
20
|
// Mirror the server rule exactly (^[a-z0-9]{3,30}$) so we fail fast and friendly
|
|
@@ -45,6 +47,36 @@ function parseHandle(args = []) {
|
|
|
45
47
|
return (positional || '').trim().toLowerCase();
|
|
46
48
|
}
|
|
47
49
|
|
|
50
|
+
// Newer servers also hand back an agent client (id + secret) so the agent can
|
|
51
|
+
// renew its own login forever. Store it the way `atris login` does with the
|
|
52
|
+
// secret in ATRIS_CLIENT_SECRET: a private 0600 copy under
|
|
53
|
+
// ~/.atris/agent-clients/, then make the client the active login. The 30-day
|
|
54
|
+
// token just saved stays reachable as a profile named after the handle.
|
|
55
|
+
// Returns { ok: true } or { ok: false, secretFile, clientId }. Never throws,
|
|
56
|
+
// never prints the secret or a token.
|
|
57
|
+
async function adoptSignupClient(client, handle, deps = {}) {
|
|
58
|
+
const clientId = client && typeof client.client_id === 'string' ? client.client_id.trim() : '';
|
|
59
|
+
const secret = client && typeof client.client_secret === 'string' ? client.client_secret.trim() : '';
|
|
60
|
+
if (!clientId.startsWith(agentClient.CLIENT_ID_PREFIX) || !secret) return { ok: false };
|
|
61
|
+
|
|
62
|
+
let secretFile = null;
|
|
63
|
+
try {
|
|
64
|
+
const target = agentClient.managedSecretPath(clientId);
|
|
65
|
+
agentClient.writeFileAtomic(target, `${secret}\n`);
|
|
66
|
+
secretFile = target;
|
|
67
|
+
const entry = await agentClient.requestClientToken({ clientId, secret, scope: null }, deps);
|
|
68
|
+
|
|
69
|
+
// Keep the 30-day login as a profile named after the handle, then switch.
|
|
70
|
+
const fallback = JSON.parse(fs.readFileSync(getCredentialsPath(), 'utf8'));
|
|
71
|
+
saveProfile(handle, fallback);
|
|
72
|
+
saveAgentClientCredentials({ client_id: clientId, client_secret_file: secretFile, scope: null });
|
|
73
|
+
agentClient.writeTokenCache(clientId, entry);
|
|
74
|
+
return { ok: true, clientId };
|
|
75
|
+
} catch (error) {
|
|
76
|
+
return { ok: false, clientId, secretFile, reason: agentClient.scrub(error && error.message, [secret]) };
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
48
80
|
function printSignupUsage() {
|
|
49
81
|
console.error('Usage: atris signup <handle>');
|
|
50
82
|
console.error(' handle: 3–30 characters, lowercase letters and digits only.');
|
|
@@ -79,9 +111,20 @@ async function signupCommand(args = []) {
|
|
|
79
111
|
const { token, email, user_id: userId } = res.data;
|
|
80
112
|
const identity = email || `${handle}@atrismail.com`;
|
|
81
113
|
saveCredentials(token, null, identity, userId || null, 'atrisos');
|
|
114
|
+
const hasClient = Boolean(res.data.client);
|
|
115
|
+
const adopted = hasClient ? await adoptSignupClient(res.data.client, handle) : { ok: false };
|
|
82
116
|
console.log(`\n✓ You're in: ${identity}`);
|
|
117
|
+
if (adopted.ok) console.log('This agent renews its own login; no human needed.');
|
|
83
118
|
console.log(' Inert starter account (0 credits): identity is free, capability is earned.');
|
|
84
119
|
console.log(' Saved to your active profile.');
|
|
120
|
+
if (adopted.ok) {
|
|
121
|
+
console.log(` The 30-day login is kept as a backup. switch to it: atris switch ${handle} --global`);
|
|
122
|
+
} else if (hasClient && adopted.secretFile) {
|
|
123
|
+
console.log(` Could not sign in with the agent client yet${adopted.reason ? ` (${adopted.reason})` : ''}. Using the 30-day login for now.`);
|
|
124
|
+
console.log(` Try again: atris login --client-id ${adopted.clientId} --client-secret-file ${adopted.secretFile}`);
|
|
125
|
+
} else if (hasClient || typeof res.data.client_error === 'string') {
|
|
126
|
+
console.log(' This login lasts 30 days; after that, renewing it will need a fresh signup login.');
|
|
127
|
+
}
|
|
85
128
|
console.log('\nNext:');
|
|
86
129
|
console.log(' atris play # claim a starter mission and earn your first proof-backed rep');
|
|
87
130
|
console.log(' atris xp # see where you stand on the board');
|
|
@@ -107,4 +150,4 @@ async function signupCommand(args = []) {
|
|
|
107
150
|
return 1;
|
|
108
151
|
}
|
|
109
152
|
|
|
110
|
-
module.exports = { signupCommand, parseHandle, HANDLE_RE };
|
|
153
|
+
module.exports = { signupCommand, parseHandle, HANDLE_RE, adoptSignupClient };
|