@agentteams/cli 0.1.82 → 0.1.83
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/README.md +4 -3
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +75 -2
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/init.d.ts +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +25 -12
- package/dist/commands/init.js.map +1 -1
- package/dist/mcp-registration/atomicWrite.d.ts +9 -3
- package/dist/mcp-registration/atomicWrite.d.ts.map +1 -1
- package/dist/mcp-registration/atomicWrite.js +58 -15
- package/dist/mcp-registration/atomicWrite.js.map +1 -1
- package/dist/utils/authServer.d.ts +8 -2
- package/dist/utils/authServer.d.ts.map +1 -1
- package/dist/utils/authServer.js +106 -62
- package/dist/utils/authServer.js.map +1 -1
- package/dist/utils/config.d.ts +8 -0
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js +27 -2
- package/dist/utils/config.js.map +1 -1
- package/package.json +1 -1
- package/web-compatibility.json +4 -0
package/dist/utils/authServer.js
CHANGED
|
@@ -1,36 +1,29 @@
|
|
|
1
|
+
import { randomBytes, timingSafeEqual } from 'node:crypto';
|
|
1
2
|
import { createServer } from 'node:http';
|
|
2
|
-
const DEFAULT_OAUTH_PORT = 7777;
|
|
3
|
-
const OAUTH_PORT_MIN = 7777;
|
|
4
|
-
const OAUTH_PORT_MAX = 7790;
|
|
5
3
|
const CALLBACK_TIMEOUT_MS = 60_000;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
function
|
|
17
|
-
|
|
18
|
-
const rangePorts = [];
|
|
19
|
-
for (let port = OAUTH_PORT_MIN; port <= OAUTH_PORT_MAX; port += 1) {
|
|
20
|
-
rangePorts.push(port);
|
|
21
|
-
}
|
|
22
|
-
const uniquePorts = new Set();
|
|
23
|
-
uniquePorts.add(requestedPort);
|
|
24
|
-
for (const port of rangePorts) {
|
|
25
|
-
uniquePorts.add(port);
|
|
26
|
-
}
|
|
27
|
-
return Array.from(uniquePorts.values());
|
|
4
|
+
const DEFAULT_WEB_URL = 'https://agentteams.run';
|
|
5
|
+
/** 24 random bytes → 32 base64url characters, comfortably above the 16-character floor. */
|
|
6
|
+
const AUTH_STATE_BYTES = 24;
|
|
7
|
+
// Only a web build older than this CLI omits the state, so a plain "try again"
|
|
8
|
+
// would loop the user forever. Say what is actually wrong and give the two exits
|
|
9
|
+
// that work: wait for the deploy, or install a CLI that matches the live web.
|
|
10
|
+
const WEB_UPDATE_HINT = 'The AgentTeams web page did not echo the login state, so it is older than this CLI. ' +
|
|
11
|
+
'Hard-refresh /cli/authorize and retry; if it keeps failing, the web deploy has not caught up yet — ' +
|
|
12
|
+
'retry in a few minutes or install a CLI version matching the deployed web.';
|
|
13
|
+
/** Unguessable value that proves a callback belongs to the login this process started. */
|
|
14
|
+
export function createAuthState() {
|
|
15
|
+
return randomBytes(AUTH_STATE_BYTES).toString('base64url');
|
|
28
16
|
}
|
|
29
|
-
function
|
|
17
|
+
function listenOnEphemeralPort(server) {
|
|
30
18
|
return new Promise((resolve, reject) => {
|
|
31
19
|
const onListening = () => {
|
|
32
20
|
server.removeListener('error', onError);
|
|
33
|
-
|
|
21
|
+
const address = server.address();
|
|
22
|
+
if (!address || typeof address === 'string') {
|
|
23
|
+
reject(new Error('The local OAuth callback server did not report a TCP port.'));
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
resolve(address.port);
|
|
34
27
|
};
|
|
35
28
|
const onError = (error) => {
|
|
36
29
|
server.removeListener('listening', onListening);
|
|
@@ -38,7 +31,9 @@ function listenOnPort(server, port) {
|
|
|
38
31
|
};
|
|
39
32
|
server.once('listening', onListening);
|
|
40
33
|
server.once('error', onError);
|
|
41
|
-
|
|
34
|
+
// Port 0 asks the OS for a free port: nothing for another local process to
|
|
35
|
+
// squat on ahead of time, and no fixed range to exhaust.
|
|
36
|
+
server.listen(0, 'localhost');
|
|
42
37
|
});
|
|
43
38
|
}
|
|
44
39
|
function isAuthResult(value) {
|
|
@@ -51,10 +46,34 @@ function isAuthResult(value) {
|
|
|
51
46
|
typeof candidate.projectId === 'string' &&
|
|
52
47
|
typeof candidate.agentName === 'string' &&
|
|
53
48
|
typeof candidate.apiKey === 'string' &&
|
|
54
|
-
(candidate.apiUrl === undefined || typeof candidate.apiUrl === 'string') &&
|
|
55
49
|
typeof candidate.configId === 'string' &&
|
|
56
50
|
seedPlanIdValid);
|
|
57
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* Copy only the fields the CLI trusts. Anything else in the payload — notably an
|
|
54
|
+
* `apiUrl` pointing every later request at an attacker's server — is dropped here.
|
|
55
|
+
*/
|
|
56
|
+
function toAuthResult(payload) {
|
|
57
|
+
const result = {
|
|
58
|
+
teamId: payload.teamId,
|
|
59
|
+
projectId: payload.projectId,
|
|
60
|
+
agentName: payload.agentName,
|
|
61
|
+
apiKey: payload.apiKey,
|
|
62
|
+
configId: payload.configId,
|
|
63
|
+
};
|
|
64
|
+
if (payload.seedPlanId !== undefined) {
|
|
65
|
+
result.seedPlanId = payload.seedPlanId;
|
|
66
|
+
}
|
|
67
|
+
return result;
|
|
68
|
+
}
|
|
69
|
+
function statesMatch(expected, received) {
|
|
70
|
+
const expectedBytes = Buffer.from(expected, 'utf-8');
|
|
71
|
+
const receivedBytes = Buffer.from(received, 'utf-8');
|
|
72
|
+
if (expectedBytes.length !== receivedBytes.length) {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
return timingSafeEqual(expectedBytes, receivedBytes);
|
|
76
|
+
}
|
|
58
77
|
function readRequestBody(request) {
|
|
59
78
|
return new Promise((resolve, reject) => {
|
|
60
79
|
const chunks = [];
|
|
@@ -63,24 +82,47 @@ function readRequestBody(request) {
|
|
|
63
82
|
request.on('error', reject);
|
|
64
83
|
});
|
|
65
84
|
}
|
|
85
|
+
function normalizeOrigin(value) {
|
|
86
|
+
try {
|
|
87
|
+
return new URL(value).origin;
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Only the configured web origin may post a callback. There is deliberately no
|
|
95
|
+
* blanket `http://localhost:*` allowance: any page served from any local port
|
|
96
|
+
* used to qualify. Local development and the dev environment opt in explicitly
|
|
97
|
+
* instead, through `AGENTTEAMS_WEB_URL` or `AGENTTEAMS_OAUTH_ALLOWED_ORIGINS`.
|
|
98
|
+
*/
|
|
66
99
|
function getAllowedOrigins() {
|
|
67
|
-
const
|
|
68
|
-
|
|
100
|
+
const origins = new Set();
|
|
101
|
+
const webOrigin = normalizeOrigin(process.env.AGENTTEAMS_WEB_URL || DEFAULT_WEB_URL);
|
|
102
|
+
if (webOrigin) {
|
|
103
|
+
origins.add(webOrigin);
|
|
104
|
+
}
|
|
105
|
+
for (const entry of (process.env.AGENTTEAMS_OAUTH_ALLOWED_ORIGINS ?? '').split(',')) {
|
|
106
|
+
const trimmed = entry.trim();
|
|
107
|
+
if (trimmed.length === 0) {
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
const origin = normalizeOrigin(trimmed);
|
|
111
|
+
if (origin) {
|
|
112
|
+
origins.add(origin);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return Array.from(origins.values());
|
|
69
116
|
}
|
|
70
117
|
function isAllowedOrigin(origin) {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
return true;
|
|
74
|
-
}
|
|
75
|
-
// Allow localhost with any port for dev
|
|
76
|
-
if (/^http:\/\/localhost(:\d+)?$/.test(origin)) {
|
|
77
|
-
return true;
|
|
118
|
+
if (!origin) {
|
|
119
|
+
return false;
|
|
78
120
|
}
|
|
79
|
-
return
|
|
121
|
+
return getAllowedOrigins().includes(origin);
|
|
80
122
|
}
|
|
81
123
|
function setCorsHeaders(response, request) {
|
|
82
124
|
const origin = request?.headers.origin;
|
|
83
|
-
if (
|
|
125
|
+
if (isAllowedOrigin(origin)) {
|
|
84
126
|
response.setHeader('Access-Control-Allow-Origin', origin);
|
|
85
127
|
response.setHeader('Vary', 'Origin');
|
|
86
128
|
}
|
|
@@ -96,7 +138,8 @@ function sendJson(response, statusCode, payload, request) {
|
|
|
96
138
|
});
|
|
97
139
|
response.end(body);
|
|
98
140
|
}
|
|
99
|
-
export async function startLocalAuthServer() {
|
|
141
|
+
export async function startLocalAuthServer(options) {
|
|
142
|
+
const expectedState = options?.state ?? createAuthState();
|
|
100
143
|
let settled = false;
|
|
101
144
|
let timeoutHandle = null;
|
|
102
145
|
let isWaiting = false;
|
|
@@ -148,6 +191,12 @@ export async function startLocalAuthServer() {
|
|
|
148
191
|
sendJson(response, 404, { message: 'Not found.' }, request);
|
|
149
192
|
return;
|
|
150
193
|
}
|
|
194
|
+
// CORS headers only tell a browser what to do with a response; the body was
|
|
195
|
+
// accepted long before that. Refuse the request itself instead.
|
|
196
|
+
if (!isAllowedOrigin(request.headers.origin)) {
|
|
197
|
+
sendJson(response, 403, { message: 'OAuth callback origin is not allowed.' }, request);
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
151
200
|
if (settled) {
|
|
152
201
|
sendJson(response, 409, { message: 'OAuth callback already processed.' }, request);
|
|
153
202
|
return;
|
|
@@ -159,36 +208,30 @@ export async function startLocalAuthServer() {
|
|
|
159
208
|
sendJson(response, 400, { message: 'Invalid OAuth callback payload.' }, request);
|
|
160
209
|
return;
|
|
161
210
|
}
|
|
211
|
+
const receivedState = payload.state;
|
|
212
|
+
if (typeof receivedState !== 'string' || receivedState.length === 0) {
|
|
213
|
+
sendJson(response, 400, { message: `Missing OAuth callback state. ${WEB_UPDATE_HINT}` }, request);
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
// A mismatch must not consume `settled`: the login this process started is
|
|
217
|
+
// still outstanding, and burning it here would hand a forged callback a
|
|
218
|
+
// trivial denial of service.
|
|
219
|
+
if (!statesMatch(expectedState, receivedState)) {
|
|
220
|
+
sendJson(response, 400, { message: 'OAuth callback state does not match this login.' }, request);
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
162
223
|
sendJson(response, 200, { success: true }, request);
|
|
163
224
|
setTimeout(() => {
|
|
164
|
-
resolveAuth(payload);
|
|
225
|
+
resolveAuth(toAuthResult(payload));
|
|
165
226
|
}, 100);
|
|
166
227
|
}
|
|
167
228
|
catch {
|
|
168
229
|
sendJson(response, 400, { message: 'Invalid JSON body.' }, request);
|
|
169
230
|
}
|
|
170
231
|
});
|
|
171
|
-
|
|
172
|
-
for (const candidatePort of buildCandidatePorts()) {
|
|
173
|
-
try {
|
|
174
|
-
await listenOnPort(server, candidatePort);
|
|
175
|
-
port = candidatePort;
|
|
176
|
-
break;
|
|
177
|
-
}
|
|
178
|
-
catch (error) {
|
|
179
|
-
const errorCode = typeof error === 'object' && error !== null && 'code' in error ? error.code : undefined;
|
|
180
|
-
if (errorCode !== 'EADDRINUSE') {
|
|
181
|
-
throw error;
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
if (port === null) {
|
|
186
|
-
throw new Error(`No available OAuth callback port found in ${OAUTH_PORT_MIN}-${OAUTH_PORT_MAX} and requested AGENTTEAMS_OAUTH_PORT.`);
|
|
187
|
-
}
|
|
232
|
+
const port = await listenOnEphemeralPort(server);
|
|
188
233
|
server.on('error', (error) => {
|
|
189
|
-
rejectAuth(new Error(error.
|
|
190
|
-
? `OAuth callback port ${port} is already in use.`
|
|
191
|
-
: `OAuth callback server failed: ${error.message}`));
|
|
234
|
+
rejectAuth(new Error(`OAuth callback server failed: ${error.message}`));
|
|
192
235
|
});
|
|
193
236
|
server.once('close', () => {
|
|
194
237
|
if (!settled && isWaiting) {
|
|
@@ -213,6 +256,7 @@ export async function startLocalAuthServer() {
|
|
|
213
256
|
server,
|
|
214
257
|
waitForCallback,
|
|
215
258
|
port,
|
|
259
|
+
state: expectedState,
|
|
216
260
|
};
|
|
217
261
|
}
|
|
218
262
|
//# sourceMappingURL=authServer.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authServer.js","sourceRoot":"","sources":["../../src/utils/authServer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"authServer.js","sourceRoot":"","sources":["../../src/utils/authServer.ts"],"names":[],"mappings":"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"}
|
package/dist/utils/config.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { Config } from '../types/index.js';
|
|
2
2
|
export declare const DEFAULT_API_URL = "https://api.agentteams.run";
|
|
3
|
+
/** The config file holds a long-lived API key, so it must not be group- or world-readable. */
|
|
4
|
+
export declare const CONFIG_FILE_MODE = 384;
|
|
3
5
|
export type PersistedConfig = Pick<Config, 'teamId' | 'projectId' | 'apiKey'> & Partial<Pick<Config, 'apiUrl'>>;
|
|
4
6
|
/** Read only the repository/worktree config, without environment or global fallbacks. */
|
|
5
7
|
export declare function loadProjectConfig(startDir?: string): Partial<Config> | null;
|
|
@@ -28,6 +30,12 @@ export declare function loadConfig(options?: Partial<Config>): Config | null;
|
|
|
28
30
|
* Save configuration to a JSON file.
|
|
29
31
|
* Creates parent directories if they don't exist.
|
|
30
32
|
*
|
|
33
|
+
* The file carries an API key, so it is written through a temp file in the same
|
|
34
|
+
* directory and renamed into place: a crash or a full disk can never leave a
|
|
35
|
+
* truncated config behind, and the key is never briefly visible at a wider mode.
|
|
36
|
+
* The result is always {@link CONFIG_FILE_MODE}; repairing configs this function
|
|
37
|
+
* does not write is `agentteams doctor`'s job, not this one's.
|
|
38
|
+
*
|
|
31
39
|
* @param configPath - Absolute path to write the config file
|
|
32
40
|
* @param config - Configuration object to persist
|
|
33
41
|
* @throws Error if write fails
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAMhD,eAAO,MAAM,eAAe,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAMhD,eAAO,MAAM,eAAe,+BAA+B,CAAC;AAE5D,8FAA8F;AAC9F,eAAO,MAAM,gBAAgB,MAAQ,CAAC;AACtC,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,MAAM,EAAE,QAAQ,GAAG,WAAW,GAAG,QAAQ,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;AAehH,yFAAyF;AACzF,wBAAgB,iBAAiB,CAAC,QAAQ,GAAE,MAAsB,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,IAAI,CAG1F;AAuBD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA+BjE;AAED,wBAAgB,+BAA+B,CAC7C,QAAQ,GAAE,MAAsB,EAChC,WAAW,GAAE,MAAkB,GAC9B,MAAM,CAmBR;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,GAAG,IAAI,CAwBnE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAwB5E"}
|
package/dist/utils/config.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync, readFileSync,
|
|
1
|
+
import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
2
2
|
import { join, dirname, resolve } from 'node:path';
|
|
3
3
|
import { homedir } from 'node:os';
|
|
4
4
|
import { resolveGitTopLevel, resolveMainCheckoutRoot } from './git.js';
|
|
@@ -6,6 +6,8 @@ import { canonicalizePath } from './path.js';
|
|
|
6
6
|
const CONFIG_DIR = '.agentteams';
|
|
7
7
|
const CONFIG_FILE = 'config.json';
|
|
8
8
|
export const DEFAULT_API_URL = 'https://api.agentteams.run';
|
|
9
|
+
/** The config file holds a long-lived API key, so it must not be group- or world-readable. */
|
|
10
|
+
export const CONFIG_FILE_MODE = 0o600;
|
|
9
11
|
const CONFIGURATION_NOT_FOUND_MESSAGE = "Configuration not found. Run 'agentteams init' first or set AGENTTEAMS_* environment variables.";
|
|
10
12
|
function readConfigFile(filePath) {
|
|
11
13
|
try {
|
|
@@ -135,6 +137,12 @@ export function loadConfig(options) {
|
|
|
135
137
|
* Save configuration to a JSON file.
|
|
136
138
|
* Creates parent directories if they don't exist.
|
|
137
139
|
*
|
|
140
|
+
* The file carries an API key, so it is written through a temp file in the same
|
|
141
|
+
* directory and renamed into place: a crash or a full disk can never leave a
|
|
142
|
+
* truncated config behind, and the key is never briefly visible at a wider mode.
|
|
143
|
+
* The result is always {@link CONFIG_FILE_MODE}; repairing configs this function
|
|
144
|
+
* does not write is `agentteams doctor`'s job, not this one's.
|
|
145
|
+
*
|
|
138
146
|
* @param configPath - Absolute path to write the config file
|
|
139
147
|
* @param config - Configuration object to persist
|
|
140
148
|
* @throws Error if write fails
|
|
@@ -144,6 +152,23 @@ export function saveConfig(configPath, config) {
|
|
|
144
152
|
if (!existsSync(dir)) {
|
|
145
153
|
mkdirSync(dir, { recursive: true });
|
|
146
154
|
}
|
|
147
|
-
|
|
155
|
+
const body = JSON.stringify(config, null, 2) + '\n';
|
|
156
|
+
// Same directory as the target: `rename` is only atomic within a filesystem.
|
|
157
|
+
const temporaryPath = join(dir, `.${Date.now().toString(36)}-${process.pid}.agentteams-tmp`);
|
|
158
|
+
try {
|
|
159
|
+
// `mode` on open is masked by umask, so chmod restates it unconditionally.
|
|
160
|
+
writeFileSync(temporaryPath, body, { encoding: 'utf-8', mode: CONFIG_FILE_MODE });
|
|
161
|
+
chmodSync(temporaryPath, CONFIG_FILE_MODE);
|
|
162
|
+
renameSync(temporaryPath, configPath);
|
|
163
|
+
}
|
|
164
|
+
catch (error) {
|
|
165
|
+
try {
|
|
166
|
+
unlinkSync(temporaryPath);
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
// The temp file may never have been created; the original is untouched either way.
|
|
170
|
+
}
|
|
171
|
+
throw error;
|
|
172
|
+
}
|
|
148
173
|
}
|
|
149
174
|
//# sourceMappingURL=config.js.map
|
package/dist/utils/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$comment": "Web behaviour this CLI cannot log in without. The release gate in .github/workflows/sync-cli-public.yml refuses to publish the CLI until the deployed web reports every entry in its build-info.json capabilities list (published from web/scripts/write-build-info.mjs). Add an entry in the same PR that makes the CLI depend on new web behaviour.",
|
|
3
|
+
"requiredWebCapabilities": ["cli-callback-state"]
|
|
4
|
+
}
|