@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
package/dist/utils/config.d.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import type { Config } from '../types/index.js';
|
|
2
|
+
import { type PersonalTokenClient } from '../auth/personalTokenClient.js';
|
|
2
3
|
export declare const DEFAULT_API_URL = "https://api.agentteams.run";
|
|
3
|
-
|
|
4
|
+
/** Local config may contain a legacy API key, so it must not be group- or world-readable. */
|
|
5
|
+
export declare const CONFIG_FILE_MODE = 384;
|
|
6
|
+
export type PersistedConfig = Pick<Config, 'teamId' | 'projectId'> & Partial<Pick<Config, 'apiUrl' | 'authMode'>>;
|
|
7
|
+
export type LegacyApiKeyPersistedConfig = PersistedConfig & Pick<Config, 'apiKey'>;
|
|
4
8
|
/** Read only the repository/worktree config, without environment or global fallbacks. */
|
|
5
9
|
export declare function loadProjectConfig(startDir?: string): Partial<Config> | null;
|
|
6
10
|
/**
|
|
@@ -12,25 +16,132 @@ export declare function loadProjectConfig(startDir?: string): Partial<Config> |
|
|
|
12
16
|
export declare function findProjectConfig(startDir: string): string | null;
|
|
13
17
|
export declare function getConfigurationNotFoundMessage(startDir?: string, userHomeDir?: string): string;
|
|
14
18
|
/**
|
|
15
|
-
*
|
|
19
|
+
* The merge above, gated on a `key_` being present.
|
|
16
20
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* 4. Global config (~/.agentteams/config.json)
|
|
22
|
-
*
|
|
23
|
-
* @param options - CLI argument overrides (highest priority)
|
|
24
|
-
* @returns Merged Config if all required fields are present, otherwise null
|
|
21
|
+
* ⚠️ Not for command paths. A personal-login project writes no `apiKey`, so this
|
|
22
|
+
* returns null there and the caller reports a configured project as "run
|
|
23
|
+
* `agentteams init` first". Use {@link loadConfigWithCredential} to run a
|
|
24
|
+
* command, or {@link loadConfigIdentity} when only the project binding matters.
|
|
25
25
|
*/
|
|
26
26
|
export declare function loadConfig(options?: Partial<Config>): Config | null;
|
|
27
|
+
/**
|
|
28
|
+
* The project binding on its own — no credential required.
|
|
29
|
+
*
|
|
30
|
+
* A personal-token project keeps no `apiKey` on disk, so `loadConfig()` reports
|
|
31
|
+
* it as uninitialized. Callers that only need to know *which* project this is
|
|
32
|
+
* (MCP registration renders the binding into a client config) ask for this
|
|
33
|
+
* instead of forcing a keychain round trip they have no use for.
|
|
34
|
+
*/
|
|
35
|
+
export interface ConfigIdentity {
|
|
36
|
+
teamId: string;
|
|
37
|
+
projectId: string;
|
|
38
|
+
apiUrl: string;
|
|
39
|
+
authMode?: Config['authMode'];
|
|
40
|
+
}
|
|
41
|
+
export declare function loadConfigIdentity(options?: Partial<Config>): ConfigIdentity | null;
|
|
42
|
+
/**
|
|
43
|
+
* Which credential the CLI is about to authenticate with.
|
|
44
|
+
*
|
|
45
|
+
* `auth status` reports this verbatim, so the choice must never be implicit —
|
|
46
|
+
* "why is my key not being used" is unanswerable otherwise.
|
|
47
|
+
*/
|
|
48
|
+
export type CredentialSource = 'explicit-api-key' | 'personal-token' | 'config-api-key';
|
|
49
|
+
export interface ResolvedCredential {
|
|
50
|
+
source: CredentialSource;
|
|
51
|
+
/**
|
|
52
|
+
* The value that goes on the wire. `apiContext.buildAuthHeaders()` picks the
|
|
53
|
+
* header from the prefix (`key_` → `X-API-Key`, otherwise `Bearer`), which is
|
|
54
|
+
* exactly why a personal access token can be handed over in the same slot and
|
|
55
|
+
* the HTTP layer needs no change at all.
|
|
56
|
+
*/
|
|
57
|
+
apiKey: string;
|
|
58
|
+
expiresAt?: number;
|
|
59
|
+
}
|
|
60
|
+
export declare class CredentialResolutionError extends Error {
|
|
61
|
+
constructor(message: string);
|
|
62
|
+
}
|
|
63
|
+
export type ResolvedConfig = Config & {
|
|
64
|
+
credentialSource: CredentialSource;
|
|
65
|
+
};
|
|
66
|
+
export interface ResolveCredentialDeps {
|
|
67
|
+
/** Injection point for tests; production always uses the per-server singleton. */
|
|
68
|
+
getClient?: (apiUrl: string) => PersonalTokenClient;
|
|
69
|
+
}
|
|
70
|
+
/** Reset only the process-level warning latch used by isolated tests. */
|
|
71
|
+
export declare function resetLegacyApiKeyWarningForTest(): void;
|
|
72
|
+
/**
|
|
73
|
+
* Which credential *would* be used, decided from config files alone.
|
|
74
|
+
*
|
|
75
|
+
* Split out of {@link resolveCredential} so callers that only need the choice —
|
|
76
|
+
* MCP registration deciding whether to write an API key into a client config —
|
|
77
|
+
* get the answer without a keychain lookup or a token refresh, and without a
|
|
78
|
+
* second copy of the priority rule going stale.
|
|
79
|
+
*/
|
|
80
|
+
export type CredentialPlan = {
|
|
81
|
+
source: 'explicit-api-key';
|
|
82
|
+
apiKey: string;
|
|
83
|
+
apiUrl: string;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* `optedIn` separates "the project chose this path" from "there is no `key_`
|
|
87
|
+
* left, so try it". Only the first makes a missing credential fatal.
|
|
88
|
+
*/
|
|
89
|
+
| {
|
|
90
|
+
source: 'personal-token';
|
|
91
|
+
apiUrl: string;
|
|
92
|
+
optedIn: boolean;
|
|
93
|
+
fallbackApiKey?: string;
|
|
94
|
+
} | {
|
|
95
|
+
source: 'config-api-key';
|
|
96
|
+
apiKey: string;
|
|
97
|
+
apiUrl: string;
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* Priority, highest first:
|
|
101
|
+
* 1. `--api-key` / `AGENTTEAMS_API_KEY` — the CI path, and an explicit
|
|
102
|
+
* override always beats stored state.
|
|
103
|
+
* 2. A personal token from the OS credential store — but **only** when the
|
|
104
|
+
* project opted in (`authMode: 'personal-token'`) or there is no `key_` to
|
|
105
|
+
* fall back to. A project that still carries an agent key must never pay
|
|
106
|
+
* for a keychain lookup, let alone be blocked by one that fails.
|
|
107
|
+
* 3. The `key_` in `.agentteams/config.json` — the original path, unchanged.
|
|
108
|
+
*/
|
|
109
|
+
export declare function planCredential(options?: Partial<Config>): CredentialPlan;
|
|
110
|
+
/** Decide which credential to authenticate with, and produce the value to send. */
|
|
111
|
+
export declare function resolveCredential(options?: Partial<Config>, deps?: ResolveCredentialDeps): Promise<ResolvedCredential | null>;
|
|
112
|
+
/**
|
|
113
|
+
* `loadConfig()` plus credential resolution.
|
|
114
|
+
*
|
|
115
|
+
* The credential is substituted into `apiKey` at load time on purpose: `Config.apiKey`
|
|
116
|
+
* stays a required `string`, so every command and every `resolveApiContext()` call
|
|
117
|
+
* downstream is untouched by the new auth path.
|
|
118
|
+
*/
|
|
119
|
+
export declare function loadConfigWithCredential(options?: Partial<Config>, deps?: ResolveCredentialDeps): Promise<ResolvedConfig | null>;
|
|
120
|
+
/**
|
|
121
|
+
* Flip a project between the two auth paths without disturbing anything else in
|
|
122
|
+
* its config file.
|
|
123
|
+
*
|
|
124
|
+
* `saveConfig` rewrites the whole document from a typed shape, which would drop
|
|
125
|
+
* any field this CLI version does not know about — including one a newer CLI
|
|
126
|
+
* wrote. Removing `authMode` (on logout) is what lets a project fall back to the
|
|
127
|
+
* `key_` it may still have.
|
|
128
|
+
*/
|
|
129
|
+
export declare function setProjectAuthMode(configPath: string, authMode: Config['authMode'] | null): boolean;
|
|
27
130
|
/**
|
|
28
131
|
* Save configuration to a JSON file.
|
|
29
132
|
* Creates parent directories if they don't exist.
|
|
30
133
|
*
|
|
134
|
+
* The document is written through a temp file in the same directory and renamed
|
|
135
|
+
* into place: a crash or a full disk can never leave a truncated config behind.
|
|
136
|
+
* The result is always {@link CONFIG_FILE_MODE}; repairing configs this function
|
|
137
|
+
* does not write is `agentteams doctor`'s job, not this one's. This normal path
|
|
138
|
+
* deliberately cannot persist `apiKey`; only the explicit legacy helper can.
|
|
139
|
+
*
|
|
31
140
|
* @param configPath - Absolute path to write the config file
|
|
32
141
|
* @param config - Configuration object to persist
|
|
33
142
|
* @throws Error if write fails
|
|
34
143
|
*/
|
|
35
144
|
export declare function saveConfig(configPath: string, config: PersistedConfig): void;
|
|
145
|
+
/** Compatibility-only persistence for an explicit `agentteams init --auth api-key`. */
|
|
146
|
+
export declare function saveLegacyApiKeyConfig(configPath: string, config: LegacyApiKeyPersistedConfig): void;
|
|
36
147
|
//# sourceMappingURL=config.d.ts.map
|
|
@@ -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;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"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"}
|
package/dist/utils/config.js
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
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
|
+
import { setActiveCredential } from '../auth/activeCredential.js';
|
|
5
|
+
import { getPersonalTokenClient } from '../auth/personalTokenClient.js';
|
|
4
6
|
import { resolveGitTopLevel, resolveMainCheckoutRoot } from './git.js';
|
|
5
7
|
import { canonicalizePath } from './path.js';
|
|
6
8
|
const CONFIG_DIR = '.agentteams';
|
|
7
9
|
const CONFIG_FILE = 'config.json';
|
|
8
10
|
export const DEFAULT_API_URL = 'https://api.agentteams.run';
|
|
11
|
+
/** Local config may contain a legacy API key, so it must not be group- or world-readable. */
|
|
12
|
+
export const CONFIG_FILE_MODE = 0o600;
|
|
9
13
|
const CONFIGURATION_NOT_FOUND_MESSAGE = "Configuration not found. Run 'agentteams init' first or set AGENTTEAMS_* environment variables.";
|
|
10
14
|
function readConfigFile(filePath) {
|
|
11
15
|
try {
|
|
@@ -112,38 +116,233 @@ export function getConfigurationNotFoundMessage(startDir = process.cwd(), userHo
|
|
|
112
116
|
* @param options - CLI argument overrides (highest priority)
|
|
113
117
|
* @returns Merged Config if all required fields are present, otherwise null
|
|
114
118
|
*/
|
|
115
|
-
|
|
119
|
+
function mergeConfigSources(options) {
|
|
116
120
|
const globalPath = join(homedir(), CONFIG_DIR, CONFIG_FILE);
|
|
117
121
|
const globalConfig = readConfigFile(globalPath) ?? {};
|
|
118
122
|
const projectConfig = loadProjectConfig() ?? {};
|
|
119
123
|
const envConfig = loadEnvConfig();
|
|
120
124
|
const cliOptions = options ?? {};
|
|
121
|
-
|
|
125
|
+
return {
|
|
122
126
|
apiUrl: DEFAULT_API_URL,
|
|
123
127
|
...globalConfig,
|
|
124
128
|
...projectConfig,
|
|
125
129
|
...envConfig,
|
|
126
130
|
...cliOptions,
|
|
127
131
|
};
|
|
132
|
+
}
|
|
133
|
+
function isNonEmptyString(value) {
|
|
134
|
+
return typeof value === 'string' && value.length > 0;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* The merge above, gated on a `key_` being present.
|
|
138
|
+
*
|
|
139
|
+
* ⚠️ Not for command paths. A personal-login project writes no `apiKey`, so this
|
|
140
|
+
* returns null there and the caller reports a configured project as "run
|
|
141
|
+
* `agentteams init` first". Use {@link loadConfigWithCredential} to run a
|
|
142
|
+
* command, or {@link loadConfigIdentity} when only the project binding matters.
|
|
143
|
+
*/
|
|
144
|
+
export function loadConfig(options) {
|
|
145
|
+
const merged = mergeConfigSources(options);
|
|
128
146
|
const requiredFields = ['teamId', 'projectId', 'apiKey'];
|
|
129
|
-
const hasAllFields = requiredFields.every((field) =>
|
|
147
|
+
const hasAllFields = requiredFields.every((field) => isNonEmptyString(merged[field]));
|
|
130
148
|
if (!hasAllFields)
|
|
131
149
|
return null;
|
|
132
150
|
return merged;
|
|
133
151
|
}
|
|
152
|
+
export function loadConfigIdentity(options) {
|
|
153
|
+
const merged = mergeConfigSources(options);
|
|
154
|
+
if (!isNonEmptyString(merged.teamId) || !isNonEmptyString(merged.projectId))
|
|
155
|
+
return null;
|
|
156
|
+
return {
|
|
157
|
+
teamId: merged.teamId,
|
|
158
|
+
projectId: merged.projectId,
|
|
159
|
+
apiUrl: merged.apiUrl,
|
|
160
|
+
...(merged.authMode ? { authMode: merged.authMode } : {}),
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
export class CredentialResolutionError extends Error {
|
|
164
|
+
constructor(message) {
|
|
165
|
+
super(message);
|
|
166
|
+
this.name = 'CredentialResolutionError';
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
let legacyApiKeyWarningPrinted = false;
|
|
170
|
+
function warnAboutLegacyApiKey() {
|
|
171
|
+
if (legacyApiKeyWarningPrinted)
|
|
172
|
+
return;
|
|
173
|
+
legacyApiKeyWarningPrinted = true;
|
|
174
|
+
process.stderr.write("[warn] This project still stores a legacy key_ credential in .agentteams/config.json. Run 'agentteams auth login', verify it with 'agentteams auth status', then remove apiKey from the project config.\n");
|
|
175
|
+
}
|
|
176
|
+
/** Reset only the process-level warning latch used by isolated tests. */
|
|
177
|
+
export function resetLegacyApiKeyWarningForTest() {
|
|
178
|
+
legacyApiKeyWarningPrinted = false;
|
|
179
|
+
}
|
|
180
|
+
/** An explicit flag or environment variable wins over anything stored on disk or in a keychain. */
|
|
181
|
+
function explicitApiKey(options) {
|
|
182
|
+
if (isNonEmptyString(options?.apiKey))
|
|
183
|
+
return options.apiKey;
|
|
184
|
+
if (isNonEmptyString(process.env.AGENTTEAMS_API_KEY))
|
|
185
|
+
return process.env.AGENTTEAMS_API_KEY;
|
|
186
|
+
return undefined;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Priority, highest first:
|
|
190
|
+
* 1. `--api-key` / `AGENTTEAMS_API_KEY` — the CI path, and an explicit
|
|
191
|
+
* override always beats stored state.
|
|
192
|
+
* 2. A personal token from the OS credential store — but **only** when the
|
|
193
|
+
* project opted in (`authMode: 'personal-token'`) or there is no `key_` to
|
|
194
|
+
* fall back to. A project that still carries an agent key must never pay
|
|
195
|
+
* for a keychain lookup, let alone be blocked by one that fails.
|
|
196
|
+
* 3. The `key_` in `.agentteams/config.json` — the original path, unchanged.
|
|
197
|
+
*/
|
|
198
|
+
export function planCredential(options) {
|
|
199
|
+
const merged = mergeConfigSources(options);
|
|
200
|
+
const explicit = explicitApiKey(options);
|
|
201
|
+
if (explicit)
|
|
202
|
+
return { source: 'explicit-api-key', apiKey: explicit, apiUrl: merged.apiUrl };
|
|
203
|
+
const configApiKey = isNonEmptyString(merged.apiKey) ? merged.apiKey : undefined;
|
|
204
|
+
const optedIn = merged.authMode === 'personal-token';
|
|
205
|
+
if (optedIn || !configApiKey) {
|
|
206
|
+
return {
|
|
207
|
+
source: 'personal-token',
|
|
208
|
+
apiUrl: merged.apiUrl,
|
|
209
|
+
optedIn,
|
|
210
|
+
...(configApiKey ? { fallbackApiKey: configApiKey } : {}),
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
return { source: 'config-api-key', apiKey: configApiKey, apiUrl: merged.apiUrl };
|
|
214
|
+
}
|
|
215
|
+
/** Decide which credential to authenticate with, and produce the value to send. */
|
|
216
|
+
export async function resolveCredential(options, deps = {}) {
|
|
217
|
+
const plan = planCredential(options);
|
|
218
|
+
if (plan.source === 'explicit-api-key') {
|
|
219
|
+
setActiveCredential(null);
|
|
220
|
+
return { source: 'explicit-api-key', apiKey: plan.apiKey };
|
|
221
|
+
}
|
|
222
|
+
const configApiKey = plan.source === 'personal-token' ? plan.fallbackApiKey : plan.apiKey;
|
|
223
|
+
// The warning belongs here, not in `planCredential`. Planning is a pure decision that
|
|
224
|
+
// callers make without authenticating — `mcp config` renders a snippet and touches no
|
|
225
|
+
// file — and attaching stderr output to it made those commands nag about a key they
|
|
226
|
+
// never read.
|
|
227
|
+
if (configApiKey) {
|
|
228
|
+
warnAboutLegacyApiKey();
|
|
229
|
+
}
|
|
230
|
+
if (plan.source === 'personal-token') {
|
|
231
|
+
const optedIn = plan.optedIn;
|
|
232
|
+
const client = (deps.getClient ?? getPersonalTokenClient)(plan.apiUrl);
|
|
233
|
+
if (client.hasCredential()) {
|
|
234
|
+
const accessToken = await client.getAccessToken();
|
|
235
|
+
if (accessToken) {
|
|
236
|
+
// Only this branch arms the HTTP layer's 401 retry. A `key_` has nothing
|
|
237
|
+
// to refresh, so leaving the slot empty is the guard.
|
|
238
|
+
setActiveCredential({
|
|
239
|
+
refresh: async () => {
|
|
240
|
+
client.invalidateAccessToken();
|
|
241
|
+
return client.getAccessToken();
|
|
242
|
+
},
|
|
243
|
+
});
|
|
244
|
+
const expiresAt = client.state().expiresAt;
|
|
245
|
+
return expiresAt === null
|
|
246
|
+
? { source: 'personal-token', apiKey: accessToken }
|
|
247
|
+
: { source: 'personal-token', apiKey: accessToken, expiresAt };
|
|
248
|
+
}
|
|
249
|
+
// A stored-but-unusable token is only fatal when there is nothing else to
|
|
250
|
+
// try; otherwise the `key_` below still works and the user sees nothing.
|
|
251
|
+
if (!configApiKey) {
|
|
252
|
+
throw new CredentialResolutionError(client.state().reconnectRequired
|
|
253
|
+
? "Your AgentTeams login was revoked or expired. Run 'agentteams auth login' to sign in again."
|
|
254
|
+
: "Could not refresh your AgentTeams login. Check your network connection, then retry or run 'agentteams auth login'.");
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
else if (optedIn && !configApiKey) {
|
|
258
|
+
throw new CredentialResolutionError("This project is configured to use a personal login, but no credential is stored. Run 'agentteams auth login'.");
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
setActiveCredential(null);
|
|
262
|
+
return configApiKey ? { source: 'config-api-key', apiKey: configApiKey } : null;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* `loadConfig()` plus credential resolution.
|
|
266
|
+
*
|
|
267
|
+
* The credential is substituted into `apiKey` at load time on purpose: `Config.apiKey`
|
|
268
|
+
* stays a required `string`, so every command and every `resolveApiContext()` call
|
|
269
|
+
* downstream is untouched by the new auth path.
|
|
270
|
+
*/
|
|
271
|
+
export async function loadConfigWithCredential(options, deps = {}) {
|
|
272
|
+
const merged = mergeConfigSources(options);
|
|
273
|
+
if (!isNonEmptyString(merged.teamId) || !isNonEmptyString(merged.projectId))
|
|
274
|
+
return null;
|
|
275
|
+
const credential = await resolveCredential(options, deps);
|
|
276
|
+
if (!credential)
|
|
277
|
+
return null;
|
|
278
|
+
return { ...merged, apiKey: credential.apiKey, credentialSource: credential.source };
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Flip a project between the two auth paths without disturbing anything else in
|
|
282
|
+
* its config file.
|
|
283
|
+
*
|
|
284
|
+
* `saveConfig` rewrites the whole document from a typed shape, which would drop
|
|
285
|
+
* any field this CLI version does not know about — including one a newer CLI
|
|
286
|
+
* wrote. Removing `authMode` (on logout) is what lets a project fall back to the
|
|
287
|
+
* `key_` it may still have.
|
|
288
|
+
*/
|
|
289
|
+
export function setProjectAuthMode(configPath, authMode) {
|
|
290
|
+
const existing = readConfigFile(configPath);
|
|
291
|
+
if (!existing)
|
|
292
|
+
return false;
|
|
293
|
+
const next = { ...existing };
|
|
294
|
+
if (authMode) {
|
|
295
|
+
next.authMode = authMode;
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
delete next.authMode;
|
|
299
|
+
}
|
|
300
|
+
writeConfigDocument(configPath, next);
|
|
301
|
+
return true;
|
|
302
|
+
}
|
|
134
303
|
/**
|
|
135
304
|
* Save configuration to a JSON file.
|
|
136
305
|
* Creates parent directories if they don't exist.
|
|
137
306
|
*
|
|
307
|
+
* The document is written through a temp file in the same directory and renamed
|
|
308
|
+
* into place: a crash or a full disk can never leave a truncated config behind.
|
|
309
|
+
* The result is always {@link CONFIG_FILE_MODE}; repairing configs this function
|
|
310
|
+
* does not write is `agentteams doctor`'s job, not this one's. This normal path
|
|
311
|
+
* deliberately cannot persist `apiKey`; only the explicit legacy helper can.
|
|
312
|
+
*
|
|
138
313
|
* @param configPath - Absolute path to write the config file
|
|
139
314
|
* @param config - Configuration object to persist
|
|
140
315
|
* @throws Error if write fails
|
|
141
316
|
*/
|
|
142
317
|
export function saveConfig(configPath, config) {
|
|
318
|
+
writeConfigDocument(configPath, config);
|
|
319
|
+
}
|
|
320
|
+
/** Compatibility-only persistence for an explicit `agentteams init --auth api-key`. */
|
|
321
|
+
export function saveLegacyApiKeyConfig(configPath, config) {
|
|
322
|
+
writeConfigDocument(configPath, config);
|
|
323
|
+
}
|
|
324
|
+
function writeConfigDocument(configPath, config) {
|
|
143
325
|
const dir = dirname(configPath);
|
|
144
326
|
if (!existsSync(dir)) {
|
|
145
327
|
mkdirSync(dir, { recursive: true });
|
|
146
328
|
}
|
|
147
|
-
|
|
329
|
+
const body = JSON.stringify(config, null, 2) + '\n';
|
|
330
|
+
// Same directory as the target: `rename` is only atomic within a filesystem.
|
|
331
|
+
const temporaryPath = join(dir, `.${Date.now().toString(36)}-${process.pid}.agentteams-tmp`);
|
|
332
|
+
try {
|
|
333
|
+
// `mode` on open is masked by umask, so chmod restates it unconditionally.
|
|
334
|
+
writeFileSync(temporaryPath, body, { encoding: 'utf-8', mode: CONFIG_FILE_MODE });
|
|
335
|
+
chmodSync(temporaryPath, CONFIG_FILE_MODE);
|
|
336
|
+
renameSync(temporaryPath, configPath);
|
|
337
|
+
}
|
|
338
|
+
catch (error) {
|
|
339
|
+
try {
|
|
340
|
+
unlinkSync(temporaryPath);
|
|
341
|
+
}
|
|
342
|
+
catch {
|
|
343
|
+
// The temp file may never have been created; the original is untouched either way.
|
|
344
|
+
}
|
|
345
|
+
throw error;
|
|
346
|
+
}
|
|
148
347
|
}
|
|
149
348
|
//# 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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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAUA,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAsCF,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAYjF;AA4BD,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,MAAM,CAkG1E"}
|
package/dist/utils/errors.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { isAxiosError } from 'axios';
|
|
2
|
+
import { getActiveCredential } from '../auth/activeCredential.js';
|
|
2
3
|
function translateServerMessage(message) {
|
|
3
4
|
const mapping = [
|
|
4
5
|
{ match: '컨벤션 수정 권한이 없습니다', translated: "You don't have permission to modify conventions." },
|
|
@@ -61,6 +62,7 @@ export function handleError(error, context) {
|
|
|
61
62
|
const rawMessage = typeof data?.message === 'string' ? data.message : error.message;
|
|
62
63
|
const message = typeof rawMessage === 'string' ? translateServerMessage(rawMessage) : String(rawMessage);
|
|
63
64
|
const errorCode = typeof data?.errorCode === 'string' ? data.errorCode : undefined;
|
|
65
|
+
const errorDetailCode = typeof data?.errorDetailCode === 'string' ? data.errorDetailCode : undefined;
|
|
64
66
|
const minimumVersion = typeof data?.minimumVersion === 'string' ? data.minimumVersion : undefined;
|
|
65
67
|
if (status === 426 || errorCode === 'CLI_UPGRADE_REQUIRED') {
|
|
66
68
|
return formatUpgradeRequiredMessage({ message, minimumVersion });
|
|
@@ -74,6 +76,20 @@ Details: ${message}`;
|
|
|
74
76
|
}
|
|
75
77
|
return `Bad request. Check your flags and payload.\nNext: Verify required options (e.g., --id/--plan-id) and try again.\nDetails: ${message}`;
|
|
76
78
|
case 401:
|
|
79
|
+
// An agent key that ran out its 30-day TTL is not a wrong key, and telling
|
|
80
|
+
// someone to check AGENTTEAMS_API_KEY sends them looking at a value that is
|
|
81
|
+
// exactly right. This is the only signal a runner gets, so it has to name
|
|
82
|
+
// the cause and the fix.
|
|
83
|
+
if (errorDetailCode === 'AGENT_API_KEY_EXPIRED') {
|
|
84
|
+
return `This agent API key is no longer valid: it expired or was revoked.
|
|
85
|
+
Next: Reissue it in the AgentTeams web app (project settings → agents) and update .agentteams/config.json, or re-run 'agentteams init' to switch this project to a personal login that refreshes itself.
|
|
86
|
+
Details: ${message}`;
|
|
87
|
+
}
|
|
88
|
+
// A personal login that still fails after the automatic refresh is a
|
|
89
|
+
// different problem from a wrong API key, and needs a different fix.
|
|
90
|
+
if (getActiveCredential()) {
|
|
91
|
+
return `Your AgentTeams login is no longer valid.\nNext: Run 'agentteams auth login' to sign in again.\nDetails: ${message}`;
|
|
92
|
+
}
|
|
77
93
|
if (errorCode === 'AUTH_REQUIRED') {
|
|
78
94
|
return `Authentication required.
|
|
79
95
|
Next: Verify your AGENTTEAMS_API_KEY and ensure credentials are configured.
|
package/dist/utils/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,YAAY,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"httpClient.d.ts","sourceRoot":"","sources":["../../src/utils/httpClient.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"httpClient.d.ts","sourceRoot":"","sources":["../../src/utils/httpClient.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAsH1B,eAAe,KAAK,CAAC"}
|
package/dist/utils/httpClient.js
CHANGED
|
@@ -1,11 +1,22 @@
|
|
|
1
1
|
import { createRequire } from 'node:module';
|
|
2
2
|
import axios from 'axios';
|
|
3
|
+
import { getActiveCredential } from '../auth/activeCredential.js';
|
|
3
4
|
import { getCommandContext } from './commandContext.js';
|
|
4
5
|
import { writeCache } from './updateCheck.js';
|
|
5
6
|
const require = createRequire(import.meta.url);
|
|
6
7
|
const pkg = require('../../package.json');
|
|
7
8
|
const MAX_RETRIES = 3;
|
|
8
9
|
const BASE_DELAY_MS = 1_000;
|
|
10
|
+
/**
|
|
11
|
+
* Only a request that authenticated with a bearer token can be fixed by a
|
|
12
|
+
* refresh. An `X-API-Key` request carries a long-lived agent key with nothing
|
|
13
|
+
* behind it, so a 401 there means the key itself is wrong.
|
|
14
|
+
*/
|
|
15
|
+
function usedBearerCredential(config) {
|
|
16
|
+
const headers = config.headers;
|
|
17
|
+
const read = (name) => typeof headers?.get === 'function' ? headers.get(name) : headers?.[name];
|
|
18
|
+
return typeof read('Authorization') === 'string' && read('X-API-Key') === undefined;
|
|
19
|
+
}
|
|
9
20
|
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
10
21
|
const getRetryDelay = (error, attempt) => {
|
|
11
22
|
const retryAfterHeader = error.response?.headers?.['retry-after'];
|
|
@@ -44,6 +55,20 @@ axios.interceptors.response.use((response) => {
|
|
|
44
55
|
return response;
|
|
45
56
|
}, async (error) => {
|
|
46
57
|
const config = error.config;
|
|
58
|
+
// A personal access token lives 15 minutes, so a long command can outlive
|
|
59
|
+
// the one it started with. Refresh once and replay; anything beyond that is
|
|
60
|
+
// a genuine authentication failure and must reach the user.
|
|
61
|
+
if (config && error.response?.status === 401 && !config._authRefreshAttempted && usedBearerCredential(config)) {
|
|
62
|
+
const credential = getActiveCredential();
|
|
63
|
+
if (credential) {
|
|
64
|
+
config._authRefreshAttempted = true;
|
|
65
|
+
const accessToken = await credential.refresh();
|
|
66
|
+
if (accessToken) {
|
|
67
|
+
setRequestHeader(config, 'Authorization', `Bearer ${accessToken}`);
|
|
68
|
+
return axios.request(config);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
47
72
|
if (!config || error.response?.status !== 429) {
|
|
48
73
|
throw error;
|
|
49
74
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"httpClient.js","sourceRoot":"","sources":["../../src/utils/httpClient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,GAAG,GAAG,OAAO,CAAC,oBAAoB,CAAwB,CAAC;AAEjE,MAAM,WAAW,GAAG,CAAC,CAAC;AACtB,MAAM,aAAa,GAAG,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"httpClient.js","sourceRoot":"","sources":["../../src/utils/httpClient.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"initOutput.d.ts","sourceRoot":"","sources":["../../src/utils/initOutput.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"initOutput.d.ts","sourceRoot":"","sources":["../../src/utils/initOutput.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,MAAM,CAAC;AAqDhD,wBAAgB,eAAe,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,gBAAgB,GAAG,IAAI,CAqI/E"}
|
package/dist/utils/initOutput.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import { formatOutput } from './formatter.js';
|
|
3
|
+
/** Mirrors AGENT_API_KEY_TTL_MS in api/src/services/agentApiKey.ts. */
|
|
4
|
+
const AGENT_API_KEY_TTL_DAYS = 30;
|
|
5
|
+
function agentApiKeyExpiryLabel() {
|
|
6
|
+
const expiresAt = new Date(Date.now() + AGENT_API_KEY_TTL_DAYS * 24 * 60 * 60 * 1000);
|
|
7
|
+
return expiresAt.toISOString().slice(0, 10);
|
|
8
|
+
}
|
|
3
9
|
function isInitResult(result) {
|
|
4
10
|
if (!result || typeof result !== 'object')
|
|
5
11
|
return false;
|
|
@@ -79,6 +85,30 @@ export function printInitResult(result, format) {
|
|
|
79
85
|
return;
|
|
80
86
|
}
|
|
81
87
|
console.log(`✓ Authenticated as ${result.agentName}`);
|
|
88
|
+
// The human view is the default, so anything the personal-token path decided
|
|
89
|
+
// has to show up here — a warning only `--format json` reveals is a warning
|
|
90
|
+
// nobody reads.
|
|
91
|
+
if (result.authMode === 'personal-token') {
|
|
92
|
+
if (result.personalLogin) {
|
|
93
|
+
console.log(`✓ Signed in as ${result.personalLogin.email} (${result.personalLogin.nickname})`);
|
|
94
|
+
console.log(result.personalLogin.persisted
|
|
95
|
+
? '✓ Login stored in the OS credential store; no long-lived key was written to this repository.'
|
|
96
|
+
: '⚠ Login kept in memory for this process only.');
|
|
97
|
+
}
|
|
98
|
+
if (result.agentKeyRevoked === true) {
|
|
99
|
+
console.log('✓ The setup agent key was revoked; nothing long-lived is left on the server.');
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
// The compatibility path has a hard 30-day server-side TTL and no renewal of its own.
|
|
103
|
+
// Saying so here is the difference between a planned reissue and a runner that starts
|
|
104
|
+
// failing with a bare 401 exactly one month from today.
|
|
105
|
+
if (result.authMode === 'api-key') {
|
|
106
|
+
console.log(`⚠ This agent API key expires in 30 days (${agentApiKeyExpiryLabel()}) and does not renew itself.`);
|
|
107
|
+
console.log(" Reissue it in the web app (project settings → agents) before then, or run 'agentteams init' to switch to a personal login that refreshes automatically.");
|
|
108
|
+
}
|
|
109
|
+
if (result.warning) {
|
|
110
|
+
console.warn(`⚠ ${result.warning}`);
|
|
111
|
+
}
|
|
82
112
|
console.log(`✓ Config saved: ${result.configPath}`);
|
|
83
113
|
console.log(`✓ Convention saved: ${result.conventionPath}`);
|
|
84
114
|
console.log(`✓ Conventions synced to .agentteams/`);
|