@agentteams/cli 0.1.82 → 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/README.md +4 -3
- 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/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +75 -2
- package/dist/commands/doctor.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 +18 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +114 -20
- 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/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/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 +39 -4
- package/dist/utils/authServer.d.ts.map +1 -1
- package/dist/utils/authServer.js +146 -62
- package/dist/utils/authServer.js.map +1 -1
- package/dist/utils/config.d.ts +121 -10
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js +204 -5
- 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
- package/web-compatibility.json +4 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serverSpec.js","sourceRoot":"","sources":["../../src/mcp-registration/serverSpec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,
|
|
1
|
+
{"version":3,"file":"serverSpec.js","sourceRoot":"","sources":["../../src/mcp-registration/serverSpec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGjE,mGAAmG;AACnG,MAAM,CAAC,MAAM,eAAe,GAAG,YAAY,CAAC;AAE5C,iDAAiD;AACjD,MAAM,CAAC,MAAM,mBAAmB,GAAG,iBAAiB,CAAC;AAErD,oEAAoE;AACpE,MAAM,CAAC,MAAM,qBAAqB,GAAG,YAAY,CAAC;AA2BlD,SAAS,kBAAkB;IACzB,OAAO,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AACpF,CAAC;AAED,kEAAkE;AAClE,MAAM,UAAU,mBAAmB,CACjC,OAAuB,EACvB,aAAwC,UAAU;IAElD,MAAM,QAAQ,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAE/F,KAAK,MAAM,SAAS,IAAI,QAAQ,EAAE,CAAC;QACjC,KAAK,MAAM,MAAM,IAAI,kBAAkB,EAAE,EAAE,CAAC;YAC1C,IAAI,UAAU,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,qBAAqB,GAAG,MAAM,EAAE,CAAC,CAAC;gBAAE,OAAO,IAAI,CAAC;QACpF,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,eAAe,CAAC,OAA+B;IAC7D,MAAM,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC;IAChC,MAAM,GAAG,GAA2B,EAAE,CAAC;IAEvC,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,SAAS,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QAC/E,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,SAAS,EAAE,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC;IAC5D,CAAC;IAED,IAAI,OAAO,CAAC,OAAO,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;QACjF,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,mBAAmB,EAAE,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC;IAC3E,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,qBAAqB,EAAE,IAAI,EAAE,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC;AAChE,CAAC"}
|
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
export declare const MCP_CLIENT_IDS: readonly ["claude-code", "codex", "copilot-cli", "opencode", "amp", "cursor-cli", "kimi-cli", "antigravity"];
|
|
3
3
|
export type McpClientId = (typeof MCP_CLIENT_IDS)[number];
|
|
4
4
|
export type McpScope = 'user' | 'project';
|
|
5
|
-
/** Syntax the client uses to inherit a secret from its parent process. */
|
|
6
|
-
export type McpSecretReference = 'dollarBraces' | 'opencodeEnv' | 'codexEnvVars';
|
|
7
5
|
/** How the AgentTeams entry reaches the client's configuration. */
|
|
8
6
|
export type McpInstallStrategy =
|
|
9
7
|
/** The client owns the format; we shell out to its documented non-interactive command. */
|
|
@@ -61,7 +59,6 @@ export interface McpClientDefinition {
|
|
|
61
59
|
label: string;
|
|
62
60
|
/** Executable names looked up on PATH. */
|
|
63
61
|
executables: string[];
|
|
64
|
-
secretReference: McpSecretReference;
|
|
65
62
|
/** Extra directories to probe when the client installs outside PATH (e.g. Kimi). */
|
|
66
63
|
extraBinDirs?: (context: McpPathContext) => string[];
|
|
67
64
|
/** Files/directories whose presence proves the client has been configured on this machine. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/mcp-registration/types.ts"],"names":[],"mappings":"AAAA,+HAA+H;AAC/H,eAAO,MAAM,cAAc,8GASjB,CAAC;AAEX,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1D,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAC;AAE1C,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/mcp-registration/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -6,6 +6,14 @@
|
|
|
6
6
|
* CLI Configuration stored in .agentteams/config.json
|
|
7
7
|
* Contains credentials and project context for API communication
|
|
8
8
|
*/
|
|
9
|
+
/**
|
|
10
|
+
* Which credential family this project is configured to authenticate with.
|
|
11
|
+
*
|
|
12
|
+
* `personal-token` is the default: project config stays secret-free while a
|
|
13
|
+
* rotating refresh token lives in the OS credential store. `api-key` is the
|
|
14
|
+
* explicit compatibility path for existing automation and legacy projects.
|
|
15
|
+
*/
|
|
16
|
+
export type AuthMode = 'api-key' | 'personal-token';
|
|
9
17
|
export interface Config {
|
|
10
18
|
/** Team ID from AgentTeams */
|
|
11
19
|
teamId: string;
|
|
@@ -15,6 +23,8 @@ export interface Config {
|
|
|
15
23
|
apiKey: string;
|
|
16
24
|
/** API URL (e.g., "http://localhost:3001") */
|
|
17
25
|
apiUrl: string;
|
|
26
|
+
/** Legacy migration marker; absent configs choose by whether an apiKey exists. */
|
|
27
|
+
authMode?: AuthMode;
|
|
18
28
|
}
|
|
19
29
|
/**
|
|
20
30
|
* Plan from API
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH;;;GAGG;AACH,MAAM,WAAW,MAAM;IACrB,8BAA8B;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,iCAAiC;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,mDAAmD;IACnD,MAAM,EAAE,MAAM,CAAC;IACf,8CAA8C;IAC9C,MAAM,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH;;;GAGG;AACH;;;;;;GAMG;AACH,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,gBAAgB,CAAC;AAEpD,MAAM,WAAW,MAAM;IACrB,8BAA8B;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,iCAAiC;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,mDAAmD;IACnD,MAAM,EAAE,MAAM,CAAC;IACf,8CAA8C;IAC9C,MAAM,EAAE,MAAM,CAAC;IACf,kFAAkF;IAClF,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AAMD;;;GAGG;AACH,MAAM,WAAW,IAAI;IACnB,wBAAwB;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,iBAAiB;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,2BAA2B;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,2DAA2D;IAC3D,MAAM,EAAE,MAAM,CAAC;IACf,qDAAqD;IACrD,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,qDAAqD;IACrD,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,oCAAoC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,uCAAuC;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,+CAA+C;IAC/C,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAMD;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface ApiKeyInputOptions {
|
|
2
|
+
apiKey?: string;
|
|
3
|
+
apiKeyFile?: string;
|
|
4
|
+
}
|
|
5
|
+
export interface ApiKeyInputDependencies {
|
|
6
|
+
readFile: (path: string) => string;
|
|
7
|
+
readStdin: () => string;
|
|
8
|
+
warn: (message: string) => void;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Resolve explicit credential input without ever writing the credential to
|
|
12
|
+
* output. The legacy argv path remains compatible, but every use explains the
|
|
13
|
+
* safer environment, file and stdin alternatives on stderr.
|
|
14
|
+
*/
|
|
15
|
+
export declare function resolveApiKeyInput(options: ApiKeyInputOptions, dependencies?: ApiKeyInputDependencies): string | undefined;
|
|
16
|
+
//# sourceMappingURL=apiKeyInput.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apiKeyInput.d.ts","sourceRoot":"","sources":["../../src/utils/apiKeyInput.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACnC,SAAS,EAAE,MAAM,MAAM,CAAC;IACxB,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACjC;AAmBD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,kBAAkB,EAC3B,YAAY,GAAE,uBAA6C,GAC1D,MAAM,GAAG,SAAS,CA8BpB"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
const defaultDependencies = {
|
|
3
|
+
readFile: (path) => readFileSync(path, 'utf-8'),
|
|
4
|
+
readStdin: () => readFileSync(0, 'utf-8'),
|
|
5
|
+
warn: (message) => process.stderr.write(message),
|
|
6
|
+
};
|
|
7
|
+
const normalizeApiKey = (value, source) => {
|
|
8
|
+
const normalized = value.trim();
|
|
9
|
+
if (!normalized) {
|
|
10
|
+
throw new Error(`${source} is empty.`);
|
|
11
|
+
}
|
|
12
|
+
if (/\s/.test(normalized)) {
|
|
13
|
+
throw new Error(`${source} must contain exactly one API key without whitespace.`);
|
|
14
|
+
}
|
|
15
|
+
return normalized;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Resolve explicit credential input without ever writing the credential to
|
|
19
|
+
* output. The legacy argv path remains compatible, but every use explains the
|
|
20
|
+
* safer environment, file and stdin alternatives on stderr.
|
|
21
|
+
*/
|
|
22
|
+
export function resolveApiKeyInput(options, dependencies = defaultDependencies) {
|
|
23
|
+
if (options.apiKey !== undefined && options.apiKeyFile !== undefined) {
|
|
24
|
+
throw new Error('--api-key and --api-key-file cannot be used together.');
|
|
25
|
+
}
|
|
26
|
+
if (options.apiKey !== undefined) {
|
|
27
|
+
dependencies.warn('[warn] --api-key exposes credentials in shell history and process listings. Prefer AGENTTEAMS_API_KEY, --api-key-file <path>, or --api-key-file - for stdin.\n');
|
|
28
|
+
return normalizeApiKey(options.apiKey, '--api-key');
|
|
29
|
+
}
|
|
30
|
+
if (options.apiKeyFile === undefined) {
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
const source = options.apiKeyFile === '-' ? 'stdin' : `API key file ${options.apiKeyFile}`;
|
|
34
|
+
try {
|
|
35
|
+
const value = options.apiKeyFile === '-' ? dependencies.readStdin() : dependencies.readFile(options.apiKeyFile);
|
|
36
|
+
return normalizeApiKey(value, source);
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
if (error instanceof Error &&
|
|
40
|
+
(error.message.endsWith('is empty.') || error.message.includes('exactly one API key'))) {
|
|
41
|
+
throw error;
|
|
42
|
+
}
|
|
43
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
44
|
+
throw new Error(`Could not read ${source}: ${detail}`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=apiKeyInput.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apiKeyInput.js","sourceRoot":"","sources":["../../src/utils/apiKeyInput.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAavC,MAAM,mBAAmB,GAA4B;IACnD,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC;IAC/C,SAAS,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,OAAO,CAAC;IACzC,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC;CACjD,CAAC;AAEF,MAAM,eAAe,GAAG,CAAC,KAAa,EAAE,MAAc,EAAU,EAAE;IAChE,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAChC,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CAAC,GAAG,MAAM,YAAY,CAAC,CAAC;IACzC,CAAC;IACD,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,GAAG,MAAM,uDAAuD,CAAC,CAAC;IACpF,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAChC,OAA2B,EAC3B,eAAwC,mBAAmB;IAE3D,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,IAAI,OAAO,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;QACrE,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;IAC3E,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QACjC,YAAY,CAAC,IAAI,CACf,gKAAgK,CACjK,CAAC;QACF,OAAO,eAAe,CAAC,OAAO,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACtD,CAAC;IAED,IAAI,OAAO,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;QACrC,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,MAAM,GAAG,OAAO,CAAC,UAAU,KAAK,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,gBAAgB,OAAO,CAAC,UAAU,EAAE,CAAC;IAC3F,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,OAAO,CAAC,UAAU,KAAK,GAAG,CAAC,CAAC,CAAC,YAAY,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QAChH,OAAO,eAAe,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IACxC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IACE,KAAK,YAAY,KAAK;YACtB,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAC,CAAC,EACtF,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;QACD,MAAM,MAAM,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACtE,MAAM,IAAI,KAAK,CAAC,kBAAkB,MAAM,KAAK,MAAM,EAAE,CAAC,CAAC;IACzD,CAAC;AACH,CAAC"}
|
|
@@ -4,15 +4,50 @@ export type AuthResult = {
|
|
|
4
4
|
projectId: string;
|
|
5
5
|
agentName: string;
|
|
6
6
|
apiKey: string;
|
|
7
|
-
apiUrl?: string;
|
|
8
7
|
configId: string;
|
|
9
8
|
seedPlanId?: string | null;
|
|
10
9
|
};
|
|
11
|
-
|
|
10
|
+
/**
|
|
11
|
+
* The authorization-code callback. Deliberately smaller than {@link AuthResult}:
|
|
12
|
+
* a single-use code that is worthless without the `code_verifier` this process
|
|
13
|
+
* never sent anywhere, instead of a long-lived key travelling through a browser.
|
|
14
|
+
*/
|
|
15
|
+
export type AuthorizationCodeResult = {
|
|
16
|
+
code: string;
|
|
17
|
+
state: string;
|
|
18
|
+
};
|
|
19
|
+
type AuthServerResult<T> = {
|
|
12
20
|
server: Server;
|
|
13
|
-
waitForCallback: () => Promise<
|
|
21
|
+
waitForCallback: () => Promise<T>;
|
|
14
22
|
port: number;
|
|
23
|
+
/** Echo this back through the authorize URL; the callback is rejected without it. */
|
|
24
|
+
state: string;
|
|
25
|
+
};
|
|
26
|
+
type StartLocalAuthServerOptions = {
|
|
27
|
+
state?: string;
|
|
28
|
+
};
|
|
29
|
+
/** Unguessable value that proves a callback belongs to the login this process started. */
|
|
30
|
+
export declare function createAuthState(): string;
|
|
31
|
+
export type PkcePair = {
|
|
32
|
+
/** Stays in this process. Without it a stolen code cannot be redeemed. */
|
|
33
|
+
verifier: string;
|
|
34
|
+
/** S256 hash sent through the browser. */
|
|
35
|
+
challenge: string;
|
|
15
36
|
};
|
|
16
|
-
|
|
37
|
+
/**
|
|
38
|
+
* PKCE S256 pair.
|
|
39
|
+
*
|
|
40
|
+
* 48 random bytes base64url-encode to 64 characters, inside the server's
|
|
41
|
+
* 43–128 range (`api/src/routes/desktop-auth/index.ts`).
|
|
42
|
+
*/
|
|
43
|
+
export declare function createPkcePair(): PkcePair;
|
|
44
|
+
/**
|
|
45
|
+
* Legacy login callback: the web posts the issued agent key back to this port.
|
|
46
|
+
* Kept unchanged for CLI/web combinations that predate the authorization-code
|
|
47
|
+
* path; `P3` is where it goes away.
|
|
48
|
+
*/
|
|
49
|
+
export declare function startLocalAuthServer(options?: StartLocalAuthServerOptions): Promise<AuthServerResult<AuthResult>>;
|
|
50
|
+
/** Authorization-code login callback: only `{ code, state }` crosses this boundary. */
|
|
51
|
+
export declare function startAuthorizationCodeServer(options?: StartLocalAuthServerOptions): Promise<AuthServerResult<AuthorizationCodeResult>>;
|
|
17
52
|
export {};
|
|
18
53
|
//# sourceMappingURL=authServer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authServer.d.ts","sourceRoot":"","sources":["../../src/utils/authServer.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"authServer.d.ts","sourceRoot":"","sources":["../../src/utils/authServer.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,KAAK,MAAM,EAA6C,MAAM,WAAW,CAAC;AAejG,MAAM,MAAM,UAAU,GAAG;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,uBAAuB,GAAG;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,KAAK,gBAAgB,CAAC,CAAC,IAAI;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,qFAAqF;IACrF,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,KAAK,2BAA2B,GAAG;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,0FAA0F;AAC1F,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED,MAAM,MAAM,QAAQ,GAAG;IACrB,0EAA0E;IAC1E,QAAQ,EAAE,MAAM,CAAC;IACjB,0CAA0C;IAC1C,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,cAAc,IAAI,QAAQ,CAGzC;AAkUD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,CAAC,EAAE,2BAA2B,GAAG,OAAO,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC,CAEjH;AAED,uFAAuF;AACvF,wBAAgB,4BAA4B,CAC1C,OAAO,CAAC,EAAE,2BAA2B,GACpC,OAAO,CAAC,gBAAgB,CAAC,uBAAuB,CAAC,CAAC,CAKpD"}
|
package/dist/utils/authServer.js
CHANGED
|
@@ -1,36 +1,45 @@
|
|
|
1
|
+
import { createHash, 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
|
-
|
|
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');
|
|
15
16
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
uniquePorts.add(port);
|
|
26
|
-
}
|
|
27
|
-
return Array.from(uniquePorts.values());
|
|
17
|
+
/**
|
|
18
|
+
* PKCE S256 pair.
|
|
19
|
+
*
|
|
20
|
+
* 48 random bytes base64url-encode to 64 characters, inside the server's
|
|
21
|
+
* 43–128 range (`api/src/routes/desktop-auth/index.ts`).
|
|
22
|
+
*/
|
|
23
|
+
export function createPkcePair() {
|
|
24
|
+
const verifier = randomBytes(48).toString('base64url');
|
|
25
|
+
return { verifier, challenge: createHash('sha256').update(verifier).digest('base64url') };
|
|
28
26
|
}
|
|
29
|
-
function
|
|
27
|
+
function isAuthorizationCodeResult(value) {
|
|
28
|
+
if (!value || typeof value !== 'object')
|
|
29
|
+
return false;
|
|
30
|
+
const candidate = value;
|
|
31
|
+
return typeof candidate.code === 'string' && candidate.code.length > 0;
|
|
32
|
+
}
|
|
33
|
+
function listenOnEphemeralPort(server) {
|
|
30
34
|
return new Promise((resolve, reject) => {
|
|
31
35
|
const onListening = () => {
|
|
32
36
|
server.removeListener('error', onError);
|
|
33
|
-
|
|
37
|
+
const address = server.address();
|
|
38
|
+
if (!address || typeof address === 'string') {
|
|
39
|
+
reject(new Error('The local OAuth callback server did not report a TCP port.'));
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
resolve(address.port);
|
|
34
43
|
};
|
|
35
44
|
const onError = (error) => {
|
|
36
45
|
server.removeListener('listening', onListening);
|
|
@@ -38,7 +47,9 @@ function listenOnPort(server, port) {
|
|
|
38
47
|
};
|
|
39
48
|
server.once('listening', onListening);
|
|
40
49
|
server.once('error', onError);
|
|
41
|
-
|
|
50
|
+
// Port 0 asks the OS for a free port: nothing for another local process to
|
|
51
|
+
// squat on ahead of time, and no fixed range to exhaust.
|
|
52
|
+
server.listen(0, 'localhost');
|
|
42
53
|
});
|
|
43
54
|
}
|
|
44
55
|
function isAuthResult(value) {
|
|
@@ -51,10 +62,34 @@ function isAuthResult(value) {
|
|
|
51
62
|
typeof candidate.projectId === 'string' &&
|
|
52
63
|
typeof candidate.agentName === 'string' &&
|
|
53
64
|
typeof candidate.apiKey === 'string' &&
|
|
54
|
-
(candidate.apiUrl === undefined || typeof candidate.apiUrl === 'string') &&
|
|
55
65
|
typeof candidate.configId === 'string' &&
|
|
56
66
|
seedPlanIdValid);
|
|
57
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* Copy only the fields the CLI trusts. Anything else in the payload — notably an
|
|
70
|
+
* `apiUrl` pointing every later request at an attacker's server — is dropped here.
|
|
71
|
+
*/
|
|
72
|
+
function toAuthResult(payload) {
|
|
73
|
+
const result = {
|
|
74
|
+
teamId: payload.teamId,
|
|
75
|
+
projectId: payload.projectId,
|
|
76
|
+
agentName: payload.agentName,
|
|
77
|
+
apiKey: payload.apiKey,
|
|
78
|
+
configId: payload.configId,
|
|
79
|
+
};
|
|
80
|
+
if (payload.seedPlanId !== undefined) {
|
|
81
|
+
result.seedPlanId = payload.seedPlanId;
|
|
82
|
+
}
|
|
83
|
+
return result;
|
|
84
|
+
}
|
|
85
|
+
function statesMatch(expected, received) {
|
|
86
|
+
const expectedBytes = Buffer.from(expected, 'utf-8');
|
|
87
|
+
const receivedBytes = Buffer.from(received, 'utf-8');
|
|
88
|
+
if (expectedBytes.length !== receivedBytes.length) {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
return timingSafeEqual(expectedBytes, receivedBytes);
|
|
92
|
+
}
|
|
58
93
|
function readRequestBody(request) {
|
|
59
94
|
return new Promise((resolve, reject) => {
|
|
60
95
|
const chunks = [];
|
|
@@ -63,24 +98,47 @@ function readRequestBody(request) {
|
|
|
63
98
|
request.on('error', reject);
|
|
64
99
|
});
|
|
65
100
|
}
|
|
101
|
+
function normalizeOrigin(value) {
|
|
102
|
+
try {
|
|
103
|
+
return new URL(value).origin;
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Only the configured web origin may post a callback. There is deliberately no
|
|
111
|
+
* blanket `http://localhost:*` allowance: any page served from any local port
|
|
112
|
+
* used to qualify. Local development and the dev environment opt in explicitly
|
|
113
|
+
* instead, through `AGENTTEAMS_WEB_URL` or `AGENTTEAMS_OAUTH_ALLOWED_ORIGINS`.
|
|
114
|
+
*/
|
|
66
115
|
function getAllowedOrigins() {
|
|
67
|
-
const
|
|
68
|
-
|
|
116
|
+
const origins = new Set();
|
|
117
|
+
const webOrigin = normalizeOrigin(process.env.AGENTTEAMS_WEB_URL || DEFAULT_WEB_URL);
|
|
118
|
+
if (webOrigin) {
|
|
119
|
+
origins.add(webOrigin);
|
|
120
|
+
}
|
|
121
|
+
for (const entry of (process.env.AGENTTEAMS_OAUTH_ALLOWED_ORIGINS ?? '').split(',')) {
|
|
122
|
+
const trimmed = entry.trim();
|
|
123
|
+
if (trimmed.length === 0) {
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
const origin = normalizeOrigin(trimmed);
|
|
127
|
+
if (origin) {
|
|
128
|
+
origins.add(origin);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return Array.from(origins.values());
|
|
69
132
|
}
|
|
70
133
|
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;
|
|
134
|
+
if (!origin) {
|
|
135
|
+
return false;
|
|
78
136
|
}
|
|
79
|
-
return
|
|
137
|
+
return getAllowedOrigins().includes(origin);
|
|
80
138
|
}
|
|
81
139
|
function setCorsHeaders(response, request) {
|
|
82
140
|
const origin = request?.headers.origin;
|
|
83
|
-
if (
|
|
141
|
+
if (isAllowedOrigin(origin)) {
|
|
84
142
|
response.setHeader('Access-Control-Allow-Origin', origin);
|
|
85
143
|
response.setHeader('Vary', 'Origin');
|
|
86
144
|
}
|
|
@@ -96,7 +154,16 @@ function sendJson(response, statusCode, payload, request) {
|
|
|
96
154
|
});
|
|
97
155
|
response.end(body);
|
|
98
156
|
}
|
|
99
|
-
|
|
157
|
+
/**
|
|
158
|
+
* The hardened loopback callback server, shared by both login paths.
|
|
159
|
+
*
|
|
160
|
+
* Origin allow-listing, constant-time state comparison, the ephemeral port, and
|
|
161
|
+
* the "a forged callback must not consume this login" rule all live here once:
|
|
162
|
+
* the authorization-code path must not get a second, weaker copy of them. The
|
|
163
|
+
* only difference between the two callers is which payload shape they accept.
|
|
164
|
+
*/
|
|
165
|
+
async function startCallbackServer(parsePayload, options) {
|
|
166
|
+
const expectedState = options?.state ?? createAuthState();
|
|
100
167
|
let settled = false;
|
|
101
168
|
let timeoutHandle = null;
|
|
102
169
|
let isWaiting = false;
|
|
@@ -148,17 +215,39 @@ export async function startLocalAuthServer() {
|
|
|
148
215
|
sendJson(response, 404, { message: 'Not found.' }, request);
|
|
149
216
|
return;
|
|
150
217
|
}
|
|
218
|
+
// CORS headers only tell a browser what to do with a response; the body was
|
|
219
|
+
// accepted long before that. Refuse the request itself instead.
|
|
220
|
+
if (!isAllowedOrigin(request.headers.origin)) {
|
|
221
|
+
sendJson(response, 403, { message: 'OAuth callback origin is not allowed.' }, request);
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
151
224
|
if (settled) {
|
|
152
225
|
sendJson(response, 409, { message: 'OAuth callback already processed.' }, request);
|
|
153
226
|
return;
|
|
154
227
|
}
|
|
155
228
|
try {
|
|
156
229
|
const rawBody = await readRequestBody(request);
|
|
157
|
-
const
|
|
158
|
-
|
|
230
|
+
const rawPayload = JSON.parse(rawBody);
|
|
231
|
+
const payload = parsePayload(rawPayload);
|
|
232
|
+
if (!payload) {
|
|
159
233
|
sendJson(response, 400, { message: 'Invalid OAuth callback payload.' }, request);
|
|
160
234
|
return;
|
|
161
235
|
}
|
|
236
|
+
// The state is read from the raw body, not from the parsed result: the
|
|
237
|
+
// legacy parser strips every field the CLI does not trust, `state`
|
|
238
|
+
// included, and it must still be checked before anything is accepted.
|
|
239
|
+
const receivedState = rawPayload.state;
|
|
240
|
+
if (typeof receivedState !== 'string' || receivedState.length === 0) {
|
|
241
|
+
sendJson(response, 400, { message: `Missing OAuth callback state. ${WEB_UPDATE_HINT}` }, request);
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
// A mismatch must not consume `settled`: the login this process started is
|
|
245
|
+
// still outstanding, and burning it here would hand a forged callback a
|
|
246
|
+
// trivial denial of service.
|
|
247
|
+
if (!statesMatch(expectedState, receivedState)) {
|
|
248
|
+
sendJson(response, 400, { message: 'OAuth callback state does not match this login.' }, request);
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
162
251
|
sendJson(response, 200, { success: true }, request);
|
|
163
252
|
setTimeout(() => {
|
|
164
253
|
resolveAuth(payload);
|
|
@@ -168,27 +257,9 @@ export async function startLocalAuthServer() {
|
|
|
168
257
|
sendJson(response, 400, { message: 'Invalid JSON body.' }, request);
|
|
169
258
|
}
|
|
170
259
|
});
|
|
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
|
-
}
|
|
260
|
+
const port = await listenOnEphemeralPort(server);
|
|
188
261
|
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}`));
|
|
262
|
+
rejectAuth(new Error(`OAuth callback server failed: ${error.message}`));
|
|
192
263
|
});
|
|
193
264
|
server.once('close', () => {
|
|
194
265
|
if (!settled && isWaiting) {
|
|
@@ -213,6 +284,19 @@ export async function startLocalAuthServer() {
|
|
|
213
284
|
server,
|
|
214
285
|
waitForCallback,
|
|
215
286
|
port,
|
|
287
|
+
state: expectedState,
|
|
216
288
|
};
|
|
217
289
|
}
|
|
290
|
+
/**
|
|
291
|
+
* Legacy login callback: the web posts the issued agent key back to this port.
|
|
292
|
+
* Kept unchanged for CLI/web combinations that predate the authorization-code
|
|
293
|
+
* path; `P3` is where it goes away.
|
|
294
|
+
*/
|
|
295
|
+
export function startLocalAuthServer(options) {
|
|
296
|
+
return startCallbackServer((value) => (isAuthResult(value) ? toAuthResult(value) : null), options);
|
|
297
|
+
}
|
|
298
|
+
/** Authorization-code login callback: only `{ code, state }` crosses this boundary. */
|
|
299
|
+
export function startAuthorizationCodeServer(options) {
|
|
300
|
+
return startCallbackServer((value) => (isAuthorizationCodeResult(value) ? { code: value.code, state: value.state } : null), options);
|
|
301
|
+
}
|
|
218
302
|
//# 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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"}
|