@agentteams/cli 0.1.83 → 0.1.84
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/.eslintcache +1 -1
- package/dist/auth/activeCredential.d.ts +22 -0
- package/dist/auth/activeCredential.d.ts.map +1 -0
- package/dist/auth/activeCredential.js +25 -0
- package/dist/auth/activeCredential.js.map +1 -0
- package/dist/auth/credentialStore.d.ts +89 -0
- package/dist/auth/credentialStore.d.ts.map +1 -0
- package/dist/auth/credentialStore.js +254 -0
- package/dist/auth/credentialStore.js.map +1 -0
- package/dist/auth/personalTokenClient.d.ts +155 -0
- package/dist/auth/personalTokenClient.d.ts.map +1 -0
- package/dist/auth/personalTokenClient.js +312 -0
- package/dist/auth/personalTokenClient.js.map +1 -0
- package/dist/auth/personalTokenStore.d.ts +16 -0
- package/dist/auth/personalTokenStore.d.ts.map +1 -0
- package/dist/auth/personalTokenStore.js +27 -0
- package/dist/auth/personalTokenStore.js.map +1 -0
- package/dist/commands/agentConfig.d.ts.map +1 -1
- package/dist/commands/agentConfig.js +8 -6
- package/dist/commands/agentConfig.js.map +1 -1
- package/dist/commands/auth.d.ts +97 -0
- package/dist/commands/auth.d.ts.map +1 -0
- package/dist/commands/auth.js +245 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +16 -2
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/convention.d.ts +11 -0
- package/dist/commands/convention.d.ts.map +1 -1
- package/dist/commands/convention.js +35 -11
- package/dist/commands/convention.js.map +1 -1
- package/dist/commands/dependency.d.ts.map +1 -1
- package/dist/commands/dependency.js +8 -6
- package/dist/commands/dependency.js.map +1 -1
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +19 -14
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/init.d.ts +17 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +90 -9
- package/dist/commands/init.js.map +1 -1
- package/dist/index.js +101 -15
- package/dist/index.js.map +1 -1
- package/dist/mcp/context.d.ts +15 -1
- package/dist/mcp/context.d.ts.map +1 -1
- package/dist/mcp/context.js +24 -5
- package/dist/mcp/context.js.map +1 -1
- package/dist/mcp/server.d.ts +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +5 -2
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.js +25 -22
- package/dist/mcp/tools.js.map +1 -1
- package/dist/mcp-registration/clients.d.ts.map +1 -1
- package/dist/mcp-registration/clients.js +1 -9
- package/dist/mcp-registration/clients.js.map +1 -1
- package/dist/mcp-registration/doctor.d.ts +38 -0
- package/dist/mcp-registration/doctor.d.ts.map +1 -0
- package/dist/mcp-registration/doctor.js +379 -0
- package/dist/mcp-registration/doctor.js.map +1 -0
- package/dist/mcp-registration/index.d.ts +7 -5
- package/dist/mcp-registration/index.d.ts.map +1 -1
- package/dist/mcp-registration/index.js +46 -21
- package/dist/mcp-registration/index.js.map +1 -1
- package/dist/mcp-registration/install.d.ts.map +1 -1
- package/dist/mcp-registration/install.js +12 -15
- package/dist/mcp-registration/install.js.map +1 -1
- package/dist/mcp-registration/render.d.ts +8 -6
- package/dist/mcp-registration/render.d.ts.map +1 -1
- package/dist/mcp-registration/render.js +15 -36
- package/dist/mcp-registration/render.js.map +1 -1
- package/dist/mcp-registration/serverSpec.d.ts +31 -18
- package/dist/mcp-registration/serverSpec.d.ts.map +1 -1
- package/dist/mcp-registration/serverSpec.js +36 -20
- package/dist/mcp-registration/serverSpec.js.map +1 -1
- package/dist/mcp-registration/types.d.ts +0 -3
- package/dist/mcp-registration/types.d.ts.map +1 -1
- package/dist/types/index.d.ts +10 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/apiKeyInput.d.ts +16 -0
- package/dist/utils/apiKeyInput.d.ts.map +1 -0
- package/dist/utils/apiKeyInput.js +47 -0
- package/dist/utils/apiKeyInput.js.map +1 -0
- package/dist/utils/authServer.d.ts +32 -3
- package/dist/utils/authServer.d.ts.map +1 -1
- package/dist/utils/authServer.js +46 -6
- package/dist/utils/authServer.js.map +1 -1
- package/dist/utils/config.d.ts +118 -15
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js +182 -8
- package/dist/utils/config.js.map +1 -1
- package/dist/utils/errors.d.ts.map +1 -1
- package/dist/utils/errors.js +16 -0
- package/dist/utils/errors.js.map +1 -1
- package/dist/utils/httpClient.d.ts.map +1 -1
- package/dist/utils/httpClient.js +25 -0
- package/dist/utils/httpClient.js.map +1 -1
- package/dist/utils/initOutput.d.ts.map +1 -1
- package/dist/utils/initOutput.js +30 -0
- package/dist/utils/initOutput.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Personal opaque-token client for the CLI.
|
|
3
|
+
*
|
|
4
|
+
* Ported from `desktop/src/main/localAgent/personalTokenClient.ts`, which drives
|
|
5
|
+
* the same server endpoints (`/api/auth/desktop/{authorize,token,revoke}`). The
|
|
6
|
+
* two clients must keep the same three guarantees, because each one exists to
|
|
7
|
+
* stop a specific failure that has bitten this flow before:
|
|
8
|
+
*
|
|
9
|
+
* 1. Refresh ahead of expiry (60s skew) so a request never races the clock.
|
|
10
|
+
* 2. Collapse concurrent refreshes into one in-flight promise, so five
|
|
11
|
+
* parallel calls rotate the refresh token once rather than five times.
|
|
12
|
+
* 3. Delete the stored refresh token **only** on an explicit `invalid_grant`.
|
|
13
|
+
* A flaky network must not log the user out — otherwise one offline moment
|
|
14
|
+
* costs a full re-login even after connectivity returns.
|
|
15
|
+
*/
|
|
16
|
+
import { createPersonalTokenStore } from './personalTokenStore.js';
|
|
17
|
+
/** Registered in `api/src/services/personalTokenClients.ts`; the server rejects anything else. */
|
|
18
|
+
export const CLI_OAUTH_CLIENT_ID = 'agentteams-cli';
|
|
19
|
+
/** Refresh this far before the server-declared expiry rather than at it. */
|
|
20
|
+
export const ACCESS_REFRESH_SKEW_MS = 60_000;
|
|
21
|
+
export class PersonalTokenError extends Error {
|
|
22
|
+
code;
|
|
23
|
+
constructor(code, message) {
|
|
24
|
+
super(message);
|
|
25
|
+
this.code = code;
|
|
26
|
+
this.name = 'PersonalTokenError';
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Classify a token-endpoint response.
|
|
31
|
+
*
|
|
32
|
+
* The split that matters is `invalid_grant` (the server has definitively
|
|
33
|
+
* refused this refresh token) versus everything else (5xx, a proxy error page,
|
|
34
|
+
* a truncated body). Only the first justifies destroying local credentials.
|
|
35
|
+
*/
|
|
36
|
+
export async function parseTokenResponse(response) {
|
|
37
|
+
let body;
|
|
38
|
+
try {
|
|
39
|
+
body = await response.json();
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return { kind: 'transient', detail: `HTTP ${response.status} with an unreadable body` };
|
|
43
|
+
}
|
|
44
|
+
const error = body && typeof body === 'object' && 'error' in body ? body.error : undefined;
|
|
45
|
+
if (!response.ok) {
|
|
46
|
+
if ((response.status === 400 || response.status === 401) && error === 'invalid_grant') {
|
|
47
|
+
return { kind: 'invalidGrant' };
|
|
48
|
+
}
|
|
49
|
+
return { kind: 'transient', detail: `HTTP ${response.status}` };
|
|
50
|
+
}
|
|
51
|
+
const data = body && typeof body === 'object' && 'data' in body ? body.data : undefined;
|
|
52
|
+
const identity = data?.identity && typeof data.identity === 'object' ? data.identity : undefined;
|
|
53
|
+
if (typeof data?.accessToken !== 'string' ||
|
|
54
|
+
typeof data.refreshToken !== 'string' ||
|
|
55
|
+
typeof data.expiresIn !== 'number' ||
|
|
56
|
+
!identity ||
|
|
57
|
+
typeof identity.memberId !== 'string' ||
|
|
58
|
+
typeof identity.email !== 'string' ||
|
|
59
|
+
typeof identity.nickname !== 'string') {
|
|
60
|
+
return { kind: 'transient', detail: 'the server returned an unexpected token payload' };
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
kind: 'success',
|
|
64
|
+
tokens: {
|
|
65
|
+
accessToken: data.accessToken,
|
|
66
|
+
refreshToken: data.refreshToken,
|
|
67
|
+
expiresIn: data.expiresIn,
|
|
68
|
+
identity: {
|
|
69
|
+
memberId: identity.memberId,
|
|
70
|
+
email: identity.email,
|
|
71
|
+
nickname: identity.nickname,
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
export class PersonalTokenClient {
|
|
77
|
+
deps;
|
|
78
|
+
accessToken = null;
|
|
79
|
+
accessExpiresAt = 0;
|
|
80
|
+
identity = null;
|
|
81
|
+
reconnectRequired = false;
|
|
82
|
+
refreshInFlight = null;
|
|
83
|
+
constructor(deps) {
|
|
84
|
+
this.deps = deps;
|
|
85
|
+
}
|
|
86
|
+
state() {
|
|
87
|
+
const storeStatus = this.deps.store.status();
|
|
88
|
+
return {
|
|
89
|
+
connected: this.deps.store.read() !== null,
|
|
90
|
+
persisted: storeStatus.persisted,
|
|
91
|
+
storeBackend: storeStatus.backend,
|
|
92
|
+
storeReason: storeStatus.reason,
|
|
93
|
+
identity: this.identity,
|
|
94
|
+
expiresAt: this.accessToken ? this.accessExpiresAt : null,
|
|
95
|
+
reconnectRequired: this.reconnectRequired,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
hasCredential() {
|
|
99
|
+
return this.deps.store.read() !== null;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Trade a PKCE authorization code for the first token pair.
|
|
103
|
+
*
|
|
104
|
+
* A failure here leaves nothing behind: there is no prior credential to
|
|
105
|
+
* protect, and a half-finished login must not look like a connected one.
|
|
106
|
+
* That includes the case where the store refuses to keep the credential — a
|
|
107
|
+
* fresh login the next command cannot see is not a login, and the refresh
|
|
108
|
+
* token the server just minted would outlive this process with nobody able to
|
|
109
|
+
* use or cancel it. It is revoked rather than left orphaned.
|
|
110
|
+
*/
|
|
111
|
+
async exchangeAuthorizationCode(grant) {
|
|
112
|
+
let parsed;
|
|
113
|
+
try {
|
|
114
|
+
parsed = await this.postToken({
|
|
115
|
+
grantType: 'authorization_code',
|
|
116
|
+
clientId: CLI_OAUTH_CLIENT_ID,
|
|
117
|
+
code: grant.code,
|
|
118
|
+
codeVerifier: grant.codeVerifier,
|
|
119
|
+
redirectUri: grant.redirectUri,
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
throw new PersonalTokenError('TRANSIENT', `Could not reach the server to exchange the authorization code: ${error instanceof Error ? error.message : String(error)}.`);
|
|
124
|
+
}
|
|
125
|
+
if (parsed.kind === 'invalidGrant') {
|
|
126
|
+
throw new PersonalTokenError('INVALID_GRANT', 'The authorization code was rejected. It may have expired or already been used — run `agentteams auth login` again.');
|
|
127
|
+
}
|
|
128
|
+
if (parsed.kind !== 'success') {
|
|
129
|
+
throw new PersonalTokenError('TRANSIENT', `Token exchange failed: ${parsed.detail}.`);
|
|
130
|
+
}
|
|
131
|
+
const stored = this.acceptTokens(parsed.tokens);
|
|
132
|
+
this.reconnectRequired = false;
|
|
133
|
+
if (!stored.persisted) {
|
|
134
|
+
await this.discardUnstorableTokens(stored);
|
|
135
|
+
}
|
|
136
|
+
return {
|
|
137
|
+
accessToken: parsed.tokens.accessToken,
|
|
138
|
+
expiresAt: this.accessExpiresAt,
|
|
139
|
+
identity: parsed.tokens.identity,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Undo a login whose credential could not be stored.
|
|
144
|
+
*
|
|
145
|
+
* Revoking is best-effort — an unreachable server is not a reason to keep a
|
|
146
|
+
* dangling local state — but the local copy always goes, so `hasCredential()`
|
|
147
|
+
* never reports a login the next process will not find.
|
|
148
|
+
*/
|
|
149
|
+
async discardUnstorableTokens(outcome) {
|
|
150
|
+
let serverRevoked = true;
|
|
151
|
+
try {
|
|
152
|
+
await this.revoke();
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
serverRevoked = false;
|
|
156
|
+
this.clear();
|
|
157
|
+
}
|
|
158
|
+
const cause = outcome.reason === 'WRITE_FAILED'
|
|
159
|
+
? `the OS credential store rejected the write${outcome.detail ? ` (${outcome.detail})` : ''}`
|
|
160
|
+
: 'this machine has no usable OS credential store';
|
|
161
|
+
throw new PersonalTokenError('STORE_UNAVAILABLE', `Signed in, but the login could not be saved: ${cause}. ` +
|
|
162
|
+
(serverRevoked
|
|
163
|
+
? 'The issued token was revoked so nothing is left behind. '
|
|
164
|
+
: 'The token could not be revoked either — cancel it from the AgentTeams web app. ') +
|
|
165
|
+
'On CI, containers and headless machines use an API key (AGENTTEAMS_API_KEY) instead.');
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Current access token, refreshing pre-emptively when it is close to expiry.
|
|
169
|
+
* Returns null when there is nothing usable — the caller decides whether that
|
|
170
|
+
* is a hard failure or a reason to fall back to another credential.
|
|
171
|
+
*/
|
|
172
|
+
async getAccessToken() {
|
|
173
|
+
const now = this.now();
|
|
174
|
+
if (this.accessToken && this.accessExpiresAt - ACCESS_REFRESH_SKEW_MS > now) {
|
|
175
|
+
return this.accessToken;
|
|
176
|
+
}
|
|
177
|
+
if (!this.refreshInFlight) {
|
|
178
|
+
this.refreshInFlight = this.refresh().finally(() => {
|
|
179
|
+
this.refreshInFlight = null;
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
return this.refreshInFlight;
|
|
183
|
+
}
|
|
184
|
+
/** Force the next {@link getAccessToken} to refresh even if the cached token looks fresh. */
|
|
185
|
+
invalidateAccessToken() {
|
|
186
|
+
this.accessToken = null;
|
|
187
|
+
this.accessExpiresAt = 0;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Revoke the token family server-side, then drop the local copy.
|
|
191
|
+
*
|
|
192
|
+
* The order is not negotiable: clearing first and failing the revoke would
|
|
193
|
+
* leave a live refresh token on the server that the user can no longer see or
|
|
194
|
+
* cancel.
|
|
195
|
+
*/
|
|
196
|
+
async revoke() {
|
|
197
|
+
const refreshToken = this.deps.store.read();
|
|
198
|
+
if (!refreshToken) {
|
|
199
|
+
throw new PersonalTokenError('NOT_LOGGED_IN', 'No personal token is stored for this server.');
|
|
200
|
+
}
|
|
201
|
+
const doFetch = this.deps.fetch ?? globalThis.fetch;
|
|
202
|
+
let response;
|
|
203
|
+
try {
|
|
204
|
+
response = await doFetch(`${this.baseUrl()}/api/auth/desktop/revoke`, {
|
|
205
|
+
method: 'POST',
|
|
206
|
+
headers: { 'Content-Type': 'application/json' },
|
|
207
|
+
body: JSON.stringify({ clientId: CLI_OAUTH_CLIENT_ID, token: refreshToken }),
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
catch (error) {
|
|
211
|
+
throw new PersonalTokenError('REVOKE_FAILED', `Could not reach the server to revoke the token: ${error instanceof Error ? error.message : String(error)}. The local credential was kept.`);
|
|
212
|
+
}
|
|
213
|
+
if (!response.ok) {
|
|
214
|
+
throw new PersonalTokenError('REVOKE_FAILED', `The server refused to revoke the token (HTTP ${response.status}). The local credential was kept.`);
|
|
215
|
+
}
|
|
216
|
+
this.clear();
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Drop the local credential without asking the server.
|
|
220
|
+
*
|
|
221
|
+
* The offline escape hatch behind `auth logout --local`: the token stays valid
|
|
222
|
+
* server-side, so the caller owes the user a "revoke it in the web app" note.
|
|
223
|
+
*/
|
|
224
|
+
forgetLocalCredential() {
|
|
225
|
+
this.clear();
|
|
226
|
+
}
|
|
227
|
+
async refresh() {
|
|
228
|
+
const refreshToken = this.deps.store.read();
|
|
229
|
+
if (!refreshToken)
|
|
230
|
+
return null;
|
|
231
|
+
let parsed;
|
|
232
|
+
try {
|
|
233
|
+
parsed = await this.postToken({
|
|
234
|
+
grantType: 'refresh_token',
|
|
235
|
+
clientId: CLI_OAUTH_CLIENT_ID,
|
|
236
|
+
refreshToken,
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
catch {
|
|
240
|
+
// Network-level failure. The refresh token is still presumed valid, so it
|
|
241
|
+
// stays exactly where it is; the next command can try again.
|
|
242
|
+
return null;
|
|
243
|
+
}
|
|
244
|
+
if (parsed.kind === 'invalidGrant') {
|
|
245
|
+
this.clear();
|
|
246
|
+
this.reconnectRequired = true;
|
|
247
|
+
return null;
|
|
248
|
+
}
|
|
249
|
+
if (parsed.kind !== 'success')
|
|
250
|
+
return null;
|
|
251
|
+
this.acceptTokens(parsed.tokens);
|
|
252
|
+
this.reconnectRequired = false;
|
|
253
|
+
return this.accessToken;
|
|
254
|
+
}
|
|
255
|
+
async postToken(body) {
|
|
256
|
+
const doFetch = this.deps.fetch ?? globalThis.fetch;
|
|
257
|
+
const response = await doFetch(`${this.baseUrl()}/api/auth/desktop/token`, {
|
|
258
|
+
method: 'POST',
|
|
259
|
+
headers: { 'Content-Type': 'application/json' },
|
|
260
|
+
body: JSON.stringify(body),
|
|
261
|
+
});
|
|
262
|
+
return parseTokenResponse(response);
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* A failed save is reported, never thrown: a long-running `agentteams mcp`
|
|
266
|
+
* that rotates its refresh token must keep running on the in-memory copy
|
|
267
|
+
* rather than die at the rotation.
|
|
268
|
+
*/
|
|
269
|
+
acceptTokens(tokens) {
|
|
270
|
+
this.accessToken = tokens.accessToken;
|
|
271
|
+
// TTL is the server's call (`ACCESS_TOKEN_TTL_MS` in api/src/services/personalToken.ts);
|
|
272
|
+
// the client never assumes a duration of its own.
|
|
273
|
+
this.accessExpiresAt = this.now() + tokens.expiresIn * 1000;
|
|
274
|
+
this.identity = tokens.identity;
|
|
275
|
+
return this.deps.store.save(tokens.refreshToken);
|
|
276
|
+
}
|
|
277
|
+
clear() {
|
|
278
|
+
this.accessToken = null;
|
|
279
|
+
this.accessExpiresAt = 0;
|
|
280
|
+
this.identity = null;
|
|
281
|
+
this.reconnectRequired = false;
|
|
282
|
+
this.deps.store.remove();
|
|
283
|
+
}
|
|
284
|
+
now() {
|
|
285
|
+
return (this.deps.now ?? Date.now)();
|
|
286
|
+
}
|
|
287
|
+
baseUrl() {
|
|
288
|
+
return this.deps.apiUrl.replace(/\/+$/, '');
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* One client per API server for the lifetime of the process.
|
|
293
|
+
*
|
|
294
|
+
* The in-flight refresh suppression and the cached access token only work if
|
|
295
|
+
* every caller shares the same instance — a per-call client would rotate the
|
|
296
|
+
* refresh token once per command, and `agentteams mcp` would do it per tool call.
|
|
297
|
+
*/
|
|
298
|
+
const clients = new Map();
|
|
299
|
+
export function getPersonalTokenClient(apiUrl) {
|
|
300
|
+
const key = apiUrl.replace(/\/+$/, '');
|
|
301
|
+
let client = clients.get(key);
|
|
302
|
+
if (!client) {
|
|
303
|
+
client = new PersonalTokenClient({ apiUrl: key, store: createPersonalTokenStore(key) });
|
|
304
|
+
clients.set(key, client);
|
|
305
|
+
}
|
|
306
|
+
return client;
|
|
307
|
+
}
|
|
308
|
+
/** Test-only: drop every cached client so a test can inject its own deps. */
|
|
309
|
+
export function resetPersonalTokenClientsForTests() {
|
|
310
|
+
clients.clear();
|
|
311
|
+
}
|
|
312
|
+
//# sourceMappingURL=personalTokenClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"personalTokenClient.js","sourceRoot":"","sources":["../../src/auth/personalTokenClient.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type CredentialSaveOutcome, type CredentialStore, type CredentialStoreStatus } from './credentialStore.js';
|
|
2
|
+
export interface PersonalTokenStore {
|
|
3
|
+
status(): CredentialStoreStatus;
|
|
4
|
+
read(): string | null;
|
|
5
|
+
save(refreshToken: string): CredentialSaveOutcome;
|
|
6
|
+
remove(): void;
|
|
7
|
+
}
|
|
8
|
+
export declare function personalTokenSlot(apiUrl: string): string;
|
|
9
|
+
/**
|
|
10
|
+
* Wrap the OS credential store in a single-slot view.
|
|
11
|
+
*
|
|
12
|
+
* Access tokens deliberately have no way in here — they live for 15 minutes and
|
|
13
|
+
* stay in process memory, so there is nothing to revoke if a disk is imaged.
|
|
14
|
+
*/
|
|
15
|
+
export declare function createPersonalTokenStore(apiUrl: string, store?: CredentialStore): PersonalTokenStore;
|
|
16
|
+
//# sourceMappingURL=personalTokenStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"personalTokenStore.d.ts","sourceRoot":"","sources":["../../src/auth/personalTokenStore.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,qBAAqB,EAC1B,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC3B,MAAM,sBAAsB,CAAC;AAU9B,MAAM,WAAW,kBAAkB;IACjC,MAAM,IAAI,qBAAqB,CAAC;IAChC,IAAI,IAAI,MAAM,GAAG,IAAI,CAAC;IACtB,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,qBAAqB,CAAC;IAClD,MAAM,IAAI,IAAI,CAAC;CAChB;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAExD;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,MAAM,EACd,KAAK,GAAE,eAAsC,GAC5C,kBAAkB,CASpB"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { getCredentialStore, } from './credentialStore.js';
|
|
2
|
+
/**
|
|
3
|
+
* The refresh token is the only long-lived secret the new auth path keeps, and
|
|
4
|
+
* it is bound to the server that issued it: a token from the dev API must never
|
|
5
|
+
* be replayed against production. The API URL is therefore part of the account
|
|
6
|
+
* name rather than shared across every server.
|
|
7
|
+
*/
|
|
8
|
+
const SLOT_PREFIX = 'personal-refresh';
|
|
9
|
+
export function personalTokenSlot(apiUrl) {
|
|
10
|
+
return `${SLOT_PREFIX}:${apiUrl.replace(/\/+$/, '')}`;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Wrap the OS credential store in a single-slot view.
|
|
14
|
+
*
|
|
15
|
+
* Access tokens deliberately have no way in here — they live for 15 minutes and
|
|
16
|
+
* stay in process memory, so there is nothing to revoke if a disk is imaged.
|
|
17
|
+
*/
|
|
18
|
+
export function createPersonalTokenStore(apiUrl, store = getCredentialStore()) {
|
|
19
|
+
const slot = personalTokenSlot(apiUrl);
|
|
20
|
+
return {
|
|
21
|
+
status: () => store.status(),
|
|
22
|
+
read: () => store.read(slot),
|
|
23
|
+
save: (refreshToken) => store.save(slot, refreshToken),
|
|
24
|
+
remove: () => store.remove(slot),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=personalTokenStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"personalTokenStore.js","sourceRoot":"","sources":["../../src/auth/personalTokenStore.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,GAInB,MAAM,sBAAsB,CAAC;AAE9B;;;;;GAKG;AACH,MAAM,WAAW,GAAG,kBAAkB,CAAC;AASvC,MAAM,UAAU,iBAAiB,CAAC,MAAc;IAC9C,OAAO,GAAG,WAAW,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC;AACxD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,wBAAwB,CACtC,MAAc,EACd,QAAyB,kBAAkB,EAAE;IAE7C,MAAM,IAAI,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAEvC,OAAO;QACL,MAAM,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE;QAC5B,IAAI,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;QAC5B,IAAI,EAAE,CAAC,YAAY,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC;QACtD,MAAM,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC;KACjC,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agentConfig.d.ts","sourceRoot":"","sources":["../../src/commands/agentConfig.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"agentConfig.d.ts","sourceRoot":"","sources":["../../src/commands/agentConfig.ts"],"names":[],"mappings":"AA0BA,wBAAsB,eAAe,IAAI,OAAO,CAAC,GAAG,CAAC,CAOpD;AAED,wBAAsB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAO7D;AAED,wBAAsB,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAUhE"}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import httpClient from '../utils/httpClient.js';
|
|
2
|
-
import { getConfigurationNotFoundMessage,
|
|
2
|
+
import { getConfigurationNotFoundMessage, loadConfigWithCredential } from '../utils/config.js';
|
|
3
3
|
import { withoutJsonContentType } from '../utils/httpHeaders.js';
|
|
4
4
|
import { buildAuthHeaders } from '../utils/apiContext.js';
|
|
5
|
-
function getConfigOrThrow() {
|
|
6
|
-
|
|
5
|
+
async function getConfigOrThrow() {
|
|
6
|
+
// Credential-aware: a personal-token project has no `apiKey` on disk, so the
|
|
7
|
+
// plain config loader would report it as "not initialized".
|
|
8
|
+
const config = await loadConfigWithCredential();
|
|
7
9
|
if (!config) {
|
|
8
10
|
throw new Error(getConfigurationNotFoundMessage());
|
|
9
11
|
}
|
|
@@ -19,7 +21,7 @@ function getApiBaseUrl(apiUrl) {
|
|
|
19
21
|
return apiUrl.endsWith('/') ? apiUrl.slice(0, -1) : apiUrl;
|
|
20
22
|
}
|
|
21
23
|
export async function agentConfigList() {
|
|
22
|
-
const config = getConfigOrThrow();
|
|
24
|
+
const config = await getConfigOrThrow();
|
|
23
25
|
const apiBaseUrl = getApiBaseUrl(config.apiUrl);
|
|
24
26
|
const response = await httpClient.get(`${apiBaseUrl}/api/projects/${config.projectId}/agent-configs`, {
|
|
25
27
|
headers: getHeaders(config.apiKey),
|
|
@@ -27,7 +29,7 @@ export async function agentConfigList() {
|
|
|
27
29
|
return response.data;
|
|
28
30
|
}
|
|
29
31
|
export async function agentConfigGet(id) {
|
|
30
|
-
const config = getConfigOrThrow();
|
|
32
|
+
const config = await getConfigOrThrow();
|
|
31
33
|
const apiBaseUrl = getApiBaseUrl(config.apiUrl);
|
|
32
34
|
const response = await httpClient.get(`${apiBaseUrl}/api/projects/${config.projectId}/agent-configs/${id}`, {
|
|
33
35
|
headers: getHeaders(config.apiKey),
|
|
@@ -35,7 +37,7 @@ export async function agentConfigGet(id) {
|
|
|
35
37
|
return response.data;
|
|
36
38
|
}
|
|
37
39
|
export async function agentConfigDelete(id) {
|
|
38
|
-
const config = getConfigOrThrow();
|
|
40
|
+
const config = await getConfigOrThrow();
|
|
39
41
|
const apiBaseUrl = getApiBaseUrl(config.apiUrl);
|
|
40
42
|
const response = await httpClient.delete(`${apiBaseUrl}/api/projects/${config.projectId}/agent-configs/${id}`, {
|
|
41
43
|
headers: withoutJsonContentType(getHeaders(config.apiKey)),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agentConfig.js","sourceRoot":"","sources":["../../src/commands/agentConfig.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,+BAA+B,EAAE,
|
|
1
|
+
{"version":3,"file":"agentConfig.js","sourceRoot":"","sources":["../../src/commands/agentConfig.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,+BAA+B,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAC/F,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE1D,KAAK,UAAU,gBAAgB;IAC7B,6EAA6E;IAC7E,4DAA4D;IAC5D,MAAM,MAAM,GAAG,MAAM,wBAAwB,EAAE,CAAC;IAChD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,+BAA+B,EAAE,CAAC,CAAC;IACrD,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,UAAU,CAAC,MAAc;IAChC,OAAO;QACL,GAAG,gBAAgB,CAAC,MAAM,CAAC;QAC3B,cAAc,EAAE,kBAAkB;KACnC,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,MAAc;IACnC,OAAO,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;AAC7D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,MAAM,MAAM,GAAG,MAAM,gBAAgB,EAAE,CAAC;IACxC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAChD,MAAM,QAAQ,GAAG,MAAM,UAAU,CAAC,GAAG,CAAC,GAAG,UAAU,iBAAiB,MAAM,CAAC,SAAS,gBAAgB,EAAE;QACpG,OAAO,EAAE,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC;KACnC,CAAC,CAAC;IACH,OAAO,QAAQ,CAAC,IAAI,CAAC;AACvB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,EAAU;IAC7C,MAAM,MAAM,GAAG,MAAM,gBAAgB,EAAE,CAAC;IACxC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAChD,MAAM,QAAQ,GAAG,MAAM,UAAU,CAAC,GAAG,CAAC,GAAG,UAAU,iBAAiB,MAAM,CAAC,SAAS,kBAAkB,EAAE,EAAE,EAAE;QAC1G,OAAO,EAAE,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC;KACnC,CAAC,CAAC;IACH,OAAO,QAAQ,CAAC,IAAI,CAAC;AACvB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,EAAU;IAChD,MAAM,MAAM,GAAG,MAAM,gBAAgB,EAAE,CAAC;IACxC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAChD,MAAM,QAAQ,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,GAAG,UAAU,iBAAiB,MAAM,CAAC,SAAS,kBAAkB,EAAE,EAAE,EAAE;QAC7G,OAAO,EAAE,sBAAsB,CAAC,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;KAC3D,CAAC,CAAC;IACH,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QAC5B,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,CAAC;IACjE,CAAC;IACD,OAAO,QAAQ,CAAC,IAAI,CAAC;AACvB,CAAC"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `agentteams auth login | status | logout`.
|
|
3
|
+
*
|
|
4
|
+
* The default authentication path for new projects and the migration path for
|
|
5
|
+
* legacy configs. The stored credential is picked up by `resolveCredential()`
|
|
6
|
+
* when the config has no `key_`, or when a migrated legacy project carries
|
|
7
|
+
* `authMode: 'personal-token'`.
|
|
8
|
+
*/
|
|
9
|
+
import type { CredentialBackendId, CredentialStoreReason } from '../auth/credentialStore.js';
|
|
10
|
+
import type { Config } from '../types/index.js';
|
|
11
|
+
import { type CredentialSource } from '../utils/config.js';
|
|
12
|
+
export type AuthLoginResult = {
|
|
13
|
+
success: true;
|
|
14
|
+
authUrl: string;
|
|
15
|
+
apiUrl: string;
|
|
16
|
+
identity: {
|
|
17
|
+
memberId: string;
|
|
18
|
+
email: string;
|
|
19
|
+
nickname: string;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Always true on success: a login that could not be persisted is rejected and
|
|
23
|
+
* revoked inside `exchangeAuthorizationCode` rather than reported as a
|
|
24
|
+
* half-login. The field stays in the payload because scripts read it.
|
|
25
|
+
*/
|
|
26
|
+
persisted: boolean;
|
|
27
|
+
/** Which OS store holds the credential — the same vocabulary as `auth status`. */
|
|
28
|
+
storeBackend: CredentialBackendId;
|
|
29
|
+
storeReason: CredentialStoreReason;
|
|
30
|
+
configPath: string | null;
|
|
31
|
+
authMode: 'personal-token';
|
|
32
|
+
warning?: string;
|
|
33
|
+
};
|
|
34
|
+
export type AuthStatusResult = {
|
|
35
|
+
apiUrl: string;
|
|
36
|
+
configPath: string | null;
|
|
37
|
+
/** Which credential the next command would authenticate with. */
|
|
38
|
+
credentialSource: CredentialSource | null;
|
|
39
|
+
authMode: Config['authMode'] | null;
|
|
40
|
+
hasProjectApiKey: boolean;
|
|
41
|
+
personalToken: {
|
|
42
|
+
connected: boolean;
|
|
43
|
+
persisted: boolean;
|
|
44
|
+
storeBackend: CredentialBackendId;
|
|
45
|
+
storeReason: CredentialStoreReason;
|
|
46
|
+
reconnectRequired: boolean;
|
|
47
|
+
identity: {
|
|
48
|
+
memberId: string;
|
|
49
|
+
email: string;
|
|
50
|
+
nickname: string;
|
|
51
|
+
} | null;
|
|
52
|
+
expiresAt: string | null;
|
|
53
|
+
};
|
|
54
|
+
problem?: string;
|
|
55
|
+
};
|
|
56
|
+
export type AuthLogoutResult = {
|
|
57
|
+
success: true;
|
|
58
|
+
apiUrl: string;
|
|
59
|
+
configPath: string | null;
|
|
60
|
+
/** false → the token is still live server-side (`--local`, or nothing was stored). */
|
|
61
|
+
revokedOnServer: boolean;
|
|
62
|
+
/** true when the project reverted to an `agentteams init` API key that is still on disk. */
|
|
63
|
+
fellBackToApiKey: boolean;
|
|
64
|
+
warning?: string;
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Where to log in. Unlike the legacy `init` path this honours the project's own
|
|
68
|
+
* `apiUrl`, because a refresh token issued by the dev API is worthless against
|
|
69
|
+
* production and storing it under the wrong server would silently fail later.
|
|
70
|
+
*/
|
|
71
|
+
export declare function resolveAuthApiUrl(options?: {
|
|
72
|
+
apiUrl?: string;
|
|
73
|
+
}): string;
|
|
74
|
+
export declare function buildPersonalTokenAuthorizeUrl(input: {
|
|
75
|
+
port: number;
|
|
76
|
+
state: string;
|
|
77
|
+
codeChallenge: string;
|
|
78
|
+
projectName?: string;
|
|
79
|
+
}): string;
|
|
80
|
+
/**
|
|
81
|
+
* Run the browser round trip and exchange the resulting code for tokens.
|
|
82
|
+
*
|
|
83
|
+
* Exported so `init --auth personal-token` reuses the identical flow rather than
|
|
84
|
+
* growing a second copy of the PKCE handshake.
|
|
85
|
+
*/
|
|
86
|
+
export declare function performPersonalTokenLogin(input: {
|
|
87
|
+
apiUrl: string;
|
|
88
|
+
projectName?: string;
|
|
89
|
+
}): Promise<{
|
|
90
|
+
authUrl: string;
|
|
91
|
+
identity: AuthLoginResult['identity'];
|
|
92
|
+
persisted: boolean;
|
|
93
|
+
storeBackend: CredentialBackendId;
|
|
94
|
+
storeReason: CredentialStoreReason;
|
|
95
|
+
}>;
|
|
96
|
+
export declare function executeAuthCommand(action: string, options?: Record<string, unknown>): Promise<unknown>;
|
|
97
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAE7F,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAEhD,OAAO,EAML,KAAK,gBAAgB,EACtB,MAAM,oBAAoB,CAAC;AAM5B,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,IAAI,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAChE;;;;OAIG;IACH,SAAS,EAAE,OAAO,CAAC;IACnB,kFAAkF;IAClF,YAAY,EAAE,mBAAmB,CAAC;IAClC,WAAW,EAAE,qBAAqB,CAAC;IACnC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,iEAAiE;IACjE,gBAAgB,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC1C,QAAQ,EAAE,MAAM,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC;IACpC,gBAAgB,EAAE,OAAO,CAAC;IAC1B,aAAa,EAAE;QACb,SAAS,EAAE,OAAO,CAAC;QACnB,SAAS,EAAE,OAAO,CAAC;QACnB,YAAY,EAAE,mBAAmB,CAAC;QAClC,WAAW,EAAE,qBAAqB,CAAC;QACnC,iBAAiB,EAAE,OAAO,CAAC;QAC3B,QAAQ,EAAE;YAAE,QAAQ,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,MAAM,CAAA;SAAE,GAAG,IAAI,CAAC;QACvE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;KAC1B,CAAC;IACF,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,IAAI,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,sFAAsF;IACtF,eAAe,EAAE,OAAO,CAAC;IACzB,4FAA4F;IAC5F,gBAAgB,EAAE,OAAO,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAOvE;AAED,wBAAgB,8BAA8B,CAAC,KAAK,EAAE;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GAAG,MAAM,CAUT;AAuBD;;;;;GAKG;AACH,wBAAsB,yBAAyB,CAAC,KAAK,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC;IACxG,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,eAAe,CAAC,UAAU,CAAC,CAAC;IACtC,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,mBAAmB,CAAC;IAClC,WAAW,EAAE,qBAAqB,CAAC;CACpC,CAAC,CA0CD;AAmJD,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAahH"}
|