@agentteams/cli 0.1.83 → 0.1.85
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/api/plan.d.ts +2 -0
- package/dist/api/plan.d.ts.map +1 -1
- package/dist/api/plan.js.map +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 +118 -0
- package/dist/auth/credentialStore.d.ts.map +1 -0
- package/dist/auth/credentialStore.js +340 -0
- package/dist/auth/credentialStore.js.map +1 -0
- package/dist/auth/personalTokenClient.d.ts +189 -0
- package/dist/auth/personalTokenClient.d.ts.map +1 -0
- package/dist/auth/personalTokenClient.js +379 -0
- package/dist/auth/personalTokenClient.js.map +1 -0
- package/dist/auth/personalTokenStore.d.ts +17 -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/auth/refreshLock.d.ts +74 -0
- package/dist/auth/refreshLock.d.ts.map +1 -0
- package/dist/auth/refreshLock.js +225 -0
- package/dist/auth/refreshLock.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/attachment.d.ts.map +1 -1
- package/dist/commands/attachment.js +10 -2
- package/dist/commands/attachment.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/commands/plan.d.ts +15 -0
- package/dist/commands/plan.d.ts.map +1 -1
- package/dist/commands/plan.js +28 -0
- package/dist/commands/plan.js.map +1 -1
- package/dist/index.js +106 -16
- 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/authFormat.d.ts +18 -0
- package/dist/utils/authFormat.d.ts.map +1 -0
- package/dist/utils/authFormat.js +130 -0
- package/dist/utils/authFormat.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 +127 -15
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js +201 -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,189 @@
|
|
|
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
|
+
* Guarantee 2 covers one process. Rotation also has to be serialized *across*
|
|
17
|
+
* processes, because a one-shot `agentteams` command and a long-lived
|
|
18
|
+
* `agentteams mcp` share one credential slot: see {@link RefreshLock}.
|
|
19
|
+
*/
|
|
20
|
+
import type { CredentialBackendId, CredentialStoreReason } from './credentialStore.js';
|
|
21
|
+
import { type PersonalTokenStore } from './personalTokenStore.js';
|
|
22
|
+
import { type RefreshLock } from './refreshLock.js';
|
|
23
|
+
/** Registered in `api/src/services/personalTokenClients.ts`; the server rejects anything else. */
|
|
24
|
+
export declare const CLI_OAUTH_CLIENT_ID = "agentteams-cli";
|
|
25
|
+
/** Refresh this far before the server-declared expiry rather than at it. */
|
|
26
|
+
export declare const ACCESS_REFRESH_SKEW_MS = 60000;
|
|
27
|
+
/**
|
|
28
|
+
* Cap on a token-endpoint request.
|
|
29
|
+
*
|
|
30
|
+
* Deliberately below {@link DEFAULT_STALE_AFTER_MS}: a rotation runs with the
|
|
31
|
+
* cross-process lock held, and if it could outlast the staleness window another
|
|
32
|
+
* process would judge the lock abandoned, take it, and rotate the same refresh
|
|
33
|
+
* token — the reuse that revokes the whole family. Bounding the request keeps the
|
|
34
|
+
* holder inside the window it promised.
|
|
35
|
+
*/
|
|
36
|
+
export declare const TOKEN_REQUEST_TIMEOUT_MS: number;
|
|
37
|
+
export type PersonalTokenErrorCode = 'INVALID_GRANT' | 'TRANSIENT' | 'NOT_LOGGED_IN' | 'MALFORMED_RESPONSE' | 'REVOKE_FAILED'
|
|
38
|
+
/** A fresh login succeeded but the credential could not be kept anywhere durable. */
|
|
39
|
+
| 'STORE_UNAVAILABLE';
|
|
40
|
+
export declare class PersonalTokenError extends Error {
|
|
41
|
+
readonly code: PersonalTokenErrorCode;
|
|
42
|
+
constructor(code: PersonalTokenErrorCode, message: string);
|
|
43
|
+
}
|
|
44
|
+
export interface PersonalTokenIdentity {
|
|
45
|
+
memberId: string;
|
|
46
|
+
email: string;
|
|
47
|
+
nickname: string;
|
|
48
|
+
}
|
|
49
|
+
export interface PersonalTokenSession {
|
|
50
|
+
accessToken: string;
|
|
51
|
+
/** Epoch milliseconds, derived from the server's `expiresIn`. */
|
|
52
|
+
expiresAt: number;
|
|
53
|
+
identity: PersonalTokenIdentity;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Why the last refresh attempt produced no token. `null` once one succeeds.
|
|
57
|
+
*
|
|
58
|
+
* Exists so the caller can name the actual problem: every one of these used to
|
|
59
|
+
* surface as "check your network connection", which sends the user after a
|
|
60
|
+
* network that is fine.
|
|
61
|
+
*/
|
|
62
|
+
export type PersonalTokenRefreshFailure = 'NETWORK' | 'LOCK_CONTENTION' | 'LOCK_UNAVAILABLE';
|
|
63
|
+
export interface PersonalTokenState {
|
|
64
|
+
/** A refresh token exists locally. It may still turn out to be revoked. */
|
|
65
|
+
connected: boolean;
|
|
66
|
+
/** false → the refresh token is session-memory only and disappears with this process. */
|
|
67
|
+
persisted: boolean;
|
|
68
|
+
/** Which OS store is in play, regardless of whether it currently works. */
|
|
69
|
+
storeBackend: CredentialBackendId;
|
|
70
|
+
storeReason: CredentialStoreReason;
|
|
71
|
+
identity: PersonalTokenIdentity | null;
|
|
72
|
+
expiresAt: number | null;
|
|
73
|
+
/** The server rejected the refresh token; only a fresh login recovers. */
|
|
74
|
+
reconnectRequired: boolean;
|
|
75
|
+
/** Why the last refresh produced nothing; null when it succeeded or never ran. */
|
|
76
|
+
refreshFailure: PersonalTokenRefreshFailure | null;
|
|
77
|
+
}
|
|
78
|
+
export interface AuthorizationCodeGrant {
|
|
79
|
+
code: string;
|
|
80
|
+
codeVerifier: string;
|
|
81
|
+
redirectUri: string;
|
|
82
|
+
}
|
|
83
|
+
export interface PersonalTokenClientDeps {
|
|
84
|
+
apiUrl: string;
|
|
85
|
+
store: PersonalTokenStore;
|
|
86
|
+
fetch?: typeof fetch;
|
|
87
|
+
now?: () => number;
|
|
88
|
+
/**
|
|
89
|
+
* Serializes rotation against other processes. Defaults to a pass-through so
|
|
90
|
+
* a client built in a test touches no filesystem; {@link getPersonalTokenClient}
|
|
91
|
+
* supplies the real file lock for every shipped code path.
|
|
92
|
+
*/
|
|
93
|
+
lock?: RefreshLock;
|
|
94
|
+
}
|
|
95
|
+
interface TokenResponse {
|
|
96
|
+
accessToken: string;
|
|
97
|
+
refreshToken: string;
|
|
98
|
+
expiresIn: number;
|
|
99
|
+
identity: PersonalTokenIdentity;
|
|
100
|
+
}
|
|
101
|
+
type ParsedTokenResponse = {
|
|
102
|
+
kind: 'success';
|
|
103
|
+
tokens: TokenResponse;
|
|
104
|
+
} | {
|
|
105
|
+
kind: 'invalidGrant';
|
|
106
|
+
} | {
|
|
107
|
+
kind: 'transient';
|
|
108
|
+
detail: string;
|
|
109
|
+
};
|
|
110
|
+
/**
|
|
111
|
+
* Classify a token-endpoint response.
|
|
112
|
+
*
|
|
113
|
+
* The split that matters is `invalid_grant` (the server has definitively
|
|
114
|
+
* refused this refresh token) versus everything else (5xx, a proxy error page,
|
|
115
|
+
* a truncated body). Only the first justifies destroying local credentials.
|
|
116
|
+
*/
|
|
117
|
+
export declare function parseTokenResponse(response: Response): Promise<ParsedTokenResponse>;
|
|
118
|
+
export declare class PersonalTokenClient {
|
|
119
|
+
private readonly deps;
|
|
120
|
+
private accessToken;
|
|
121
|
+
private accessExpiresAt;
|
|
122
|
+
private identity;
|
|
123
|
+
private reconnectRequired;
|
|
124
|
+
private refreshFailure;
|
|
125
|
+
private refreshInFlight;
|
|
126
|
+
constructor(deps: PersonalTokenClientDeps);
|
|
127
|
+
state(): PersonalTokenState;
|
|
128
|
+
hasCredential(): boolean;
|
|
129
|
+
/**
|
|
130
|
+
* Trade a PKCE authorization code for the first token pair.
|
|
131
|
+
*
|
|
132
|
+
* A failure here leaves nothing behind: there is no prior credential to
|
|
133
|
+
* protect, and a half-finished login must not look like a connected one.
|
|
134
|
+
* That includes the case where the store refuses to keep the credential — a
|
|
135
|
+
* fresh login the next command cannot see is not a login, and the refresh
|
|
136
|
+
* token the server just minted would outlive this process with nobody able to
|
|
137
|
+
* use or cancel it. It is revoked rather than left orphaned.
|
|
138
|
+
*/
|
|
139
|
+
exchangeAuthorizationCode(grant: AuthorizationCodeGrant): Promise<PersonalTokenSession>;
|
|
140
|
+
/**
|
|
141
|
+
* Undo a login whose credential could not be stored.
|
|
142
|
+
*
|
|
143
|
+
* Revoking is best-effort — an unreachable server is not a reason to keep a
|
|
144
|
+
* dangling local state — but the local copy always goes, so `hasCredential()`
|
|
145
|
+
* never reports a login the next process will not find.
|
|
146
|
+
*/
|
|
147
|
+
private discardUnstorableTokens;
|
|
148
|
+
/**
|
|
149
|
+
* Current access token, refreshing pre-emptively when it is close to expiry.
|
|
150
|
+
* Returns null when there is nothing usable — the caller decides whether that
|
|
151
|
+
* is a hard failure or a reason to fall back to another credential.
|
|
152
|
+
*/
|
|
153
|
+
getAccessToken(): Promise<string | null>;
|
|
154
|
+
/** Force the next {@link getAccessToken} to refresh even if the cached token looks fresh. */
|
|
155
|
+
invalidateAccessToken(): void;
|
|
156
|
+
/**
|
|
157
|
+
* Revoke the token family server-side, then drop the local copy.
|
|
158
|
+
*
|
|
159
|
+
* The order is not negotiable: clearing first and failing the revoke would
|
|
160
|
+
* leave a live refresh token on the server that the user can no longer see or
|
|
161
|
+
* cancel.
|
|
162
|
+
*/
|
|
163
|
+
revoke(): Promise<void>;
|
|
164
|
+
/**
|
|
165
|
+
* Drop the local credential without asking the server.
|
|
166
|
+
*
|
|
167
|
+
* The offline escape hatch behind `auth logout --local`: the token stays valid
|
|
168
|
+
* server-side, so the caller owes the user a "revoke it in the web app" note.
|
|
169
|
+
*/
|
|
170
|
+
forgetLocalCredential(): void;
|
|
171
|
+
private refresh;
|
|
172
|
+
/** The rotation itself. Runs with the cross-process lock held. */
|
|
173
|
+
private rotate;
|
|
174
|
+
private postToken;
|
|
175
|
+
/**
|
|
176
|
+
* A failed save is reported, never thrown: a long-running `agentteams mcp`
|
|
177
|
+
* that rotates its refresh token must keep running on the in-memory copy
|
|
178
|
+
* rather than die at the rotation.
|
|
179
|
+
*/
|
|
180
|
+
private acceptTokens;
|
|
181
|
+
private clear;
|
|
182
|
+
private now;
|
|
183
|
+
private baseUrl;
|
|
184
|
+
}
|
|
185
|
+
export declare function getPersonalTokenClient(apiUrl: string): PersonalTokenClient;
|
|
186
|
+
/** Test-only: drop every cached client so a test can inject its own deps. */
|
|
187
|
+
export declare function resetPersonalTokenClientsForTests(): void;
|
|
188
|
+
export {};
|
|
189
|
+
//# sourceMappingURL=personalTokenClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"personalTokenClient.d.ts","sourceRoot":"","sources":["../../src/auth/personalTokenClient.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,379 @@
|
|
|
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
|
+
* Guarantee 2 covers one process. Rotation also has to be serialized *across*
|
|
17
|
+
* processes, because a one-shot `agentteams` command and a long-lived
|
|
18
|
+
* `agentteams mcp` share one credential slot: see {@link RefreshLock}.
|
|
19
|
+
*/
|
|
20
|
+
import { createPersonalTokenStore, personalTokenSlot } from './personalTokenStore.js';
|
|
21
|
+
import { createFileRefreshLock, noopRefreshLock, DEFAULT_STALE_AFTER_MS, RefreshLockTimeoutError, RefreshLockUnavailableError, } from './refreshLock.js';
|
|
22
|
+
/** Registered in `api/src/services/personalTokenClients.ts`; the server rejects anything else. */
|
|
23
|
+
export const CLI_OAUTH_CLIENT_ID = 'agentteams-cli';
|
|
24
|
+
/** Refresh this far before the server-declared expiry rather than at it. */
|
|
25
|
+
export const ACCESS_REFRESH_SKEW_MS = 60_000;
|
|
26
|
+
/**
|
|
27
|
+
* Cap on a token-endpoint request.
|
|
28
|
+
*
|
|
29
|
+
* Deliberately below {@link DEFAULT_STALE_AFTER_MS}: a rotation runs with the
|
|
30
|
+
* cross-process lock held, and if it could outlast the staleness window another
|
|
31
|
+
* process would judge the lock abandoned, take it, and rotate the same refresh
|
|
32
|
+
* token — the reuse that revokes the whole family. Bounding the request keeps the
|
|
33
|
+
* holder inside the window it promised.
|
|
34
|
+
*/
|
|
35
|
+
export const TOKEN_REQUEST_TIMEOUT_MS = Math.floor(DEFAULT_STALE_AFTER_MS / 2);
|
|
36
|
+
export class PersonalTokenError extends Error {
|
|
37
|
+
code;
|
|
38
|
+
constructor(code, message) {
|
|
39
|
+
super(message);
|
|
40
|
+
this.code = code;
|
|
41
|
+
this.name = 'PersonalTokenError';
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Classify a token-endpoint response.
|
|
46
|
+
*
|
|
47
|
+
* The split that matters is `invalid_grant` (the server has definitively
|
|
48
|
+
* refused this refresh token) versus everything else (5xx, a proxy error page,
|
|
49
|
+
* a truncated body). Only the first justifies destroying local credentials.
|
|
50
|
+
*/
|
|
51
|
+
export async function parseTokenResponse(response) {
|
|
52
|
+
let body;
|
|
53
|
+
try {
|
|
54
|
+
body = await response.json();
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return { kind: 'transient', detail: `HTTP ${response.status} with an unreadable body` };
|
|
58
|
+
}
|
|
59
|
+
const error = body && typeof body === 'object' && 'error' in body ? body.error : undefined;
|
|
60
|
+
if (!response.ok) {
|
|
61
|
+
if ((response.status === 400 || response.status === 401) && error === 'invalid_grant') {
|
|
62
|
+
return { kind: 'invalidGrant' };
|
|
63
|
+
}
|
|
64
|
+
return { kind: 'transient', detail: `HTTP ${response.status}` };
|
|
65
|
+
}
|
|
66
|
+
const data = body && typeof body === 'object' && 'data' in body ? body.data : undefined;
|
|
67
|
+
const identity = data?.identity && typeof data.identity === 'object' ? data.identity : undefined;
|
|
68
|
+
if (typeof data?.accessToken !== 'string' ||
|
|
69
|
+
typeof data.refreshToken !== 'string' ||
|
|
70
|
+
typeof data.expiresIn !== 'number' ||
|
|
71
|
+
!identity ||
|
|
72
|
+
typeof identity.memberId !== 'string' ||
|
|
73
|
+
typeof identity.email !== 'string' ||
|
|
74
|
+
typeof identity.nickname !== 'string') {
|
|
75
|
+
return { kind: 'transient', detail: 'the server returned an unexpected token payload' };
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
kind: 'success',
|
|
79
|
+
tokens: {
|
|
80
|
+
accessToken: data.accessToken,
|
|
81
|
+
refreshToken: data.refreshToken,
|
|
82
|
+
expiresIn: data.expiresIn,
|
|
83
|
+
identity: {
|
|
84
|
+
memberId: identity.memberId,
|
|
85
|
+
email: identity.email,
|
|
86
|
+
nickname: identity.nickname,
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
export class PersonalTokenClient {
|
|
92
|
+
deps;
|
|
93
|
+
accessToken = null;
|
|
94
|
+
accessExpiresAt = 0;
|
|
95
|
+
identity = null;
|
|
96
|
+
reconnectRequired = false;
|
|
97
|
+
refreshFailure = null;
|
|
98
|
+
refreshInFlight = null;
|
|
99
|
+
constructor(deps) {
|
|
100
|
+
this.deps = deps;
|
|
101
|
+
}
|
|
102
|
+
state() {
|
|
103
|
+
const storeStatus = this.deps.store.status();
|
|
104
|
+
return {
|
|
105
|
+
connected: this.deps.store.read() !== null,
|
|
106
|
+
persisted: storeStatus.persisted,
|
|
107
|
+
storeBackend: storeStatus.backend,
|
|
108
|
+
storeReason: storeStatus.reason,
|
|
109
|
+
identity: this.identity,
|
|
110
|
+
expiresAt: this.accessToken ? this.accessExpiresAt : null,
|
|
111
|
+
reconnectRequired: this.reconnectRequired,
|
|
112
|
+
refreshFailure: this.refreshFailure,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
hasCredential() {
|
|
116
|
+
return this.deps.store.read() !== null;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Trade a PKCE authorization code for the first token pair.
|
|
120
|
+
*
|
|
121
|
+
* A failure here leaves nothing behind: there is no prior credential to
|
|
122
|
+
* protect, and a half-finished login must not look like a connected one.
|
|
123
|
+
* That includes the case where the store refuses to keep the credential — a
|
|
124
|
+
* fresh login the next command cannot see is not a login, and the refresh
|
|
125
|
+
* token the server just minted would outlive this process with nobody able to
|
|
126
|
+
* use or cancel it. It is revoked rather than left orphaned.
|
|
127
|
+
*/
|
|
128
|
+
async exchangeAuthorizationCode(grant) {
|
|
129
|
+
let parsed;
|
|
130
|
+
try {
|
|
131
|
+
parsed = await this.postToken({
|
|
132
|
+
grantType: 'authorization_code',
|
|
133
|
+
clientId: CLI_OAUTH_CLIENT_ID,
|
|
134
|
+
code: grant.code,
|
|
135
|
+
codeVerifier: grant.codeVerifier,
|
|
136
|
+
redirectUri: grant.redirectUri,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
throw new PersonalTokenError('TRANSIENT', `Could not reach the server to exchange the authorization code: ${error instanceof Error ? error.message : String(error)}.`);
|
|
141
|
+
}
|
|
142
|
+
if (parsed.kind === 'invalidGrant') {
|
|
143
|
+
throw new PersonalTokenError('INVALID_GRANT', 'The authorization code was rejected. It may have expired or already been used — run `agentteams auth login` again.');
|
|
144
|
+
}
|
|
145
|
+
if (parsed.kind !== 'success') {
|
|
146
|
+
throw new PersonalTokenError('TRANSIENT', `Token exchange failed: ${parsed.detail}.`);
|
|
147
|
+
}
|
|
148
|
+
const stored = this.acceptTokens(parsed.tokens);
|
|
149
|
+
this.reconnectRequired = false;
|
|
150
|
+
if (!stored.persisted) {
|
|
151
|
+
await this.discardUnstorableTokens(stored);
|
|
152
|
+
}
|
|
153
|
+
return {
|
|
154
|
+
accessToken: parsed.tokens.accessToken,
|
|
155
|
+
expiresAt: this.accessExpiresAt,
|
|
156
|
+
identity: parsed.tokens.identity,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Undo a login whose credential could not be stored.
|
|
161
|
+
*
|
|
162
|
+
* Revoking is best-effort — an unreachable server is not a reason to keep a
|
|
163
|
+
* dangling local state — but the local copy always goes, so `hasCredential()`
|
|
164
|
+
* never reports a login the next process will not find.
|
|
165
|
+
*/
|
|
166
|
+
async discardUnstorableTokens(outcome) {
|
|
167
|
+
let serverRevoked = true;
|
|
168
|
+
try {
|
|
169
|
+
await this.revoke();
|
|
170
|
+
}
|
|
171
|
+
catch {
|
|
172
|
+
serverRevoked = false;
|
|
173
|
+
this.clear();
|
|
174
|
+
}
|
|
175
|
+
const cause = outcome.reason === 'WRITE_FAILED'
|
|
176
|
+
? `the OS credential store rejected the write${outcome.detail ? ` (${outcome.detail})` : ''}`
|
|
177
|
+
: 'this machine has no usable OS credential store';
|
|
178
|
+
throw new PersonalTokenError('STORE_UNAVAILABLE', `Signed in, but the login could not be saved: ${cause}. ` +
|
|
179
|
+
(serverRevoked
|
|
180
|
+
? 'The issued token was revoked so nothing is left behind. '
|
|
181
|
+
: 'The token could not be revoked either — cancel it from the AgentTeams web app. ') +
|
|
182
|
+
'On CI, containers and headless machines use an API key (AGENTTEAMS_API_KEY) instead.');
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Current access token, refreshing pre-emptively when it is close to expiry.
|
|
186
|
+
* Returns null when there is nothing usable — the caller decides whether that
|
|
187
|
+
* is a hard failure or a reason to fall back to another credential.
|
|
188
|
+
*/
|
|
189
|
+
async getAccessToken() {
|
|
190
|
+
const now = this.now();
|
|
191
|
+
if (this.accessToken && this.accessExpiresAt - ACCESS_REFRESH_SKEW_MS > now) {
|
|
192
|
+
return this.accessToken;
|
|
193
|
+
}
|
|
194
|
+
if (!this.refreshInFlight) {
|
|
195
|
+
this.refreshInFlight = this.refresh().finally(() => {
|
|
196
|
+
this.refreshInFlight = null;
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
return this.refreshInFlight;
|
|
200
|
+
}
|
|
201
|
+
/** Force the next {@link getAccessToken} to refresh even if the cached token looks fresh. */
|
|
202
|
+
invalidateAccessToken() {
|
|
203
|
+
this.accessToken = null;
|
|
204
|
+
this.accessExpiresAt = 0;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Revoke the token family server-side, then drop the local copy.
|
|
208
|
+
*
|
|
209
|
+
* The order is not negotiable: clearing first and failing the revoke would
|
|
210
|
+
* leave a live refresh token on the server that the user can no longer see or
|
|
211
|
+
* cancel.
|
|
212
|
+
*/
|
|
213
|
+
async revoke() {
|
|
214
|
+
// Fresh: a logout has to revoke the token the family is actually on, not a
|
|
215
|
+
// copy this process cached before someone else rotated it.
|
|
216
|
+
//
|
|
217
|
+
// Falling back to the cached copy is safe and necessary here: revocation
|
|
218
|
+
// kills the whole family, so a superseded token from the same family does the
|
|
219
|
+
// same job, and a read that failed (locked keychain, denied prompt) must not
|
|
220
|
+
// make logout claim there is nothing to revoke while a live token sits in the
|
|
221
|
+
// store — that would leave it valid server-side with no way to reach it.
|
|
222
|
+
const refreshToken = this.deps.store.read({ fresh: true }) ?? this.deps.store.read();
|
|
223
|
+
if (!refreshToken) {
|
|
224
|
+
throw new PersonalTokenError('NOT_LOGGED_IN', 'No personal token is stored for this server.');
|
|
225
|
+
}
|
|
226
|
+
const doFetch = this.deps.fetch ?? globalThis.fetch;
|
|
227
|
+
let response;
|
|
228
|
+
try {
|
|
229
|
+
response = await doFetch(`${this.baseUrl()}/api/auth/desktop/revoke`, {
|
|
230
|
+
method: 'POST',
|
|
231
|
+
headers: { 'Content-Type': 'application/json' },
|
|
232
|
+
body: JSON.stringify({ clientId: CLI_OAUTH_CLIENT_ID, token: refreshToken }),
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
catch (error) {
|
|
236
|
+
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.`);
|
|
237
|
+
}
|
|
238
|
+
if (!response.ok) {
|
|
239
|
+
throw new PersonalTokenError('REVOKE_FAILED', `The server refused to revoke the token (HTTP ${response.status}). The local credential was kept.`);
|
|
240
|
+
}
|
|
241
|
+
this.clear();
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Drop the local credential without asking the server.
|
|
245
|
+
*
|
|
246
|
+
* The offline escape hatch behind `auth logout --local`: the token stays valid
|
|
247
|
+
* server-side, so the caller owes the user a "revoke it in the web app" note.
|
|
248
|
+
*/
|
|
249
|
+
forgetLocalCredential() {
|
|
250
|
+
this.clear();
|
|
251
|
+
}
|
|
252
|
+
async refresh() {
|
|
253
|
+
// Cheap pre-check off the cache: no credential means there is nothing to
|
|
254
|
+
// serialize against, so the lock is never taken for a logged-out process.
|
|
255
|
+
if (!this.deps.store.read())
|
|
256
|
+
return null;
|
|
257
|
+
try {
|
|
258
|
+
const accessToken = await (this.deps.lock ?? noopRefreshLock).withLock(() => this.rotate());
|
|
259
|
+
if (accessToken)
|
|
260
|
+
this.refreshFailure = null;
|
|
261
|
+
return accessToken;
|
|
262
|
+
}
|
|
263
|
+
catch (error) {
|
|
264
|
+
// Both lock problems leave the refresh token exactly where it is, so the
|
|
265
|
+
// next command retries. Rotating anyway would risk the server's reuse
|
|
266
|
+
// detection revoking the whole family, which costs a full re-login. They
|
|
267
|
+
// are recorded distinctly so the caller does not blame the network.
|
|
268
|
+
if (error instanceof RefreshLockTimeoutError) {
|
|
269
|
+
this.refreshFailure = 'LOCK_CONTENTION';
|
|
270
|
+
return null;
|
|
271
|
+
}
|
|
272
|
+
if (error instanceof RefreshLockUnavailableError) {
|
|
273
|
+
this.refreshFailure = 'LOCK_UNAVAILABLE';
|
|
274
|
+
return null;
|
|
275
|
+
}
|
|
276
|
+
throw error;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
/** The rotation itself. Runs with the cross-process lock held. */
|
|
280
|
+
async rotate() {
|
|
281
|
+
// Re-read past the store's process-lifetime cache. Another process may have
|
|
282
|
+
// rotated — or cleared — the family while this one waited for the lock, and
|
|
283
|
+
// presenting the superseded token is precisely what makes the server revoke
|
|
284
|
+
// every token in the family.
|
|
285
|
+
const refreshToken = this.deps.store.read({ fresh: true });
|
|
286
|
+
if (!refreshToken)
|
|
287
|
+
return null;
|
|
288
|
+
let parsed;
|
|
289
|
+
try {
|
|
290
|
+
parsed = await this.postToken({
|
|
291
|
+
grantType: 'refresh_token',
|
|
292
|
+
clientId: CLI_OAUTH_CLIENT_ID,
|
|
293
|
+
refreshToken,
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
catch {
|
|
297
|
+
// Network-level failure, which now includes the request outrunning
|
|
298
|
+
// TOKEN_REQUEST_TIMEOUT_MS. The refresh token is still presumed valid, so
|
|
299
|
+
// it stays exactly where it is; the next command can try again.
|
|
300
|
+
this.refreshFailure = 'NETWORK';
|
|
301
|
+
return null;
|
|
302
|
+
}
|
|
303
|
+
if (parsed.kind === 'invalidGrant') {
|
|
304
|
+
this.clear();
|
|
305
|
+
this.reconnectRequired = true;
|
|
306
|
+
return null;
|
|
307
|
+
}
|
|
308
|
+
if (parsed.kind !== 'success')
|
|
309
|
+
return null;
|
|
310
|
+
this.acceptTokens(parsed.tokens);
|
|
311
|
+
this.reconnectRequired = false;
|
|
312
|
+
return this.accessToken;
|
|
313
|
+
}
|
|
314
|
+
async postToken(body) {
|
|
315
|
+
const doFetch = this.deps.fetch ?? globalThis.fetch;
|
|
316
|
+
const response = await doFetch(`${this.baseUrl()}/api/auth/desktop/token`, {
|
|
317
|
+
method: 'POST',
|
|
318
|
+
headers: { 'Content-Type': 'application/json' },
|
|
319
|
+
body: JSON.stringify(body),
|
|
320
|
+
signal: AbortSignal.timeout(TOKEN_REQUEST_TIMEOUT_MS),
|
|
321
|
+
});
|
|
322
|
+
return parseTokenResponse(response);
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* A failed save is reported, never thrown: a long-running `agentteams mcp`
|
|
326
|
+
* that rotates its refresh token must keep running on the in-memory copy
|
|
327
|
+
* rather than die at the rotation.
|
|
328
|
+
*/
|
|
329
|
+
acceptTokens(tokens) {
|
|
330
|
+
this.accessToken = tokens.accessToken;
|
|
331
|
+
// TTL is the server's call (`ACCESS_TOKEN_TTL_MS` in api/src/services/personalToken.ts);
|
|
332
|
+
// the client never assumes a duration of its own.
|
|
333
|
+
this.accessExpiresAt = this.now() + tokens.expiresIn * 1000;
|
|
334
|
+
this.identity = tokens.identity;
|
|
335
|
+
return this.deps.store.save(tokens.refreshToken);
|
|
336
|
+
}
|
|
337
|
+
clear() {
|
|
338
|
+
this.accessToken = null;
|
|
339
|
+
this.accessExpiresAt = 0;
|
|
340
|
+
this.identity = null;
|
|
341
|
+
this.reconnectRequired = false;
|
|
342
|
+
this.refreshFailure = null;
|
|
343
|
+
this.deps.store.remove();
|
|
344
|
+
}
|
|
345
|
+
now() {
|
|
346
|
+
return (this.deps.now ?? Date.now)();
|
|
347
|
+
}
|
|
348
|
+
baseUrl() {
|
|
349
|
+
return this.deps.apiUrl.replace(/\/+$/, '');
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* One client per API server for the lifetime of the process.
|
|
354
|
+
*
|
|
355
|
+
* The in-flight refresh suppression and the cached access token only work if
|
|
356
|
+
* every caller shares the same instance — a per-call client would rotate the
|
|
357
|
+
* refresh token once per command, and `agentteams mcp` would do it per tool call.
|
|
358
|
+
*/
|
|
359
|
+
const clients = new Map();
|
|
360
|
+
export function getPersonalTokenClient(apiUrl) {
|
|
361
|
+
const key = apiUrl.replace(/\/+$/, '');
|
|
362
|
+
let client = clients.get(key);
|
|
363
|
+
if (!client) {
|
|
364
|
+
const slot = personalTokenSlot(key);
|
|
365
|
+
client = new PersonalTokenClient({
|
|
366
|
+
apiUrl: key,
|
|
367
|
+
store: createPersonalTokenStore(key),
|
|
368
|
+
// Per slot, so a dev-API rotation never blocks a production one.
|
|
369
|
+
lock: createFileRefreshLock(slot),
|
|
370
|
+
});
|
|
371
|
+
clients.set(key, client);
|
|
372
|
+
}
|
|
373
|
+
return client;
|
|
374
|
+
}
|
|
375
|
+
/** Test-only: drop every cached client so a test can inject its own deps. */
|
|
376
|
+
export function resetPersonalTokenClientsForTests() {
|
|
377
|
+
clients.clear();
|
|
378
|
+
}
|
|
379
|
+
//# 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,17 @@
|
|
|
1
|
+
import { type CredentialReadOptions, type CredentialSaveOutcome, type CredentialStore, type CredentialStoreStatus } from './credentialStore.js';
|
|
2
|
+
export interface PersonalTokenStore {
|
|
3
|
+
status(): CredentialStoreStatus;
|
|
4
|
+
/** Pass `{ fresh: true }` before presenting the token — see {@link CredentialReadOptions}. */
|
|
5
|
+
read(options?: CredentialReadOptions): string | null;
|
|
6
|
+
save(refreshToken: string): CredentialSaveOutcome;
|
|
7
|
+
remove(): void;
|
|
8
|
+
}
|
|
9
|
+
export declare function personalTokenSlot(apiUrl: string): string;
|
|
10
|
+
/**
|
|
11
|
+
* Wrap the OS credential store in a single-slot view.
|
|
12
|
+
*
|
|
13
|
+
* Access tokens deliberately have no way in here — they live for 15 minutes and
|
|
14
|
+
* stay in process memory, so there is nothing to revoke if a disk is imaged.
|
|
15
|
+
*/
|
|
16
|
+
export declare function createPersonalTokenStore(apiUrl: string, store?: CredentialStore): PersonalTokenStore;
|
|
17
|
+
//# 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,qBAAqB,EAC1B,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC3B,MAAM,sBAAsB,CAAC;AAU9B,MAAM,WAAW,kBAAkB;IACjC,MAAM,IAAI,qBAAqB,CAAC;IAChC,8FAA8F;IAC9F,IAAI,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,MAAM,GAAG,IAAI,CAAC;IACrD,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: (options) => store.read(slot, options),
|
|
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,GAKnB,MAAM,sBAAsB,CAAC;AAE9B;;;;;GAKG;AACH,MAAM,WAAW,GAAG,kBAAkB,CAAC;AAUvC,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,CAAC,OAAO,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC;QAC5C,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"}
|