@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,245 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `agentteams auth login | status | logout`.
|
|
3
|
+
*
|
|
4
|
+
* The default authentication path for new projects and the migration path for
|
|
5
|
+
* legacy configs. The stored credential is picked up by `resolveCredential()`
|
|
6
|
+
* when the config has no `key_`, or when a migrated legacy project carries
|
|
7
|
+
* `authMode: 'personal-token'`.
|
|
8
|
+
*/
|
|
9
|
+
import open from 'open';
|
|
10
|
+
import { getPersonalTokenClient, PersonalTokenError } from '../auth/personalTokenClient.js';
|
|
11
|
+
import { startAuthorizationCodeServer, createAuthState, createPkcePair } from '../utils/authServer.js';
|
|
12
|
+
import { DEFAULT_API_URL, findProjectConfig, loadProjectConfig, resolveCredential, setProjectAuthMode, } from '../utils/config.js';
|
|
13
|
+
import { createSpinner } from '../utils/spinner.js';
|
|
14
|
+
import { withCommandContext } from '../utils/commandContext.js';
|
|
15
|
+
const AUTH_BASE_URL = process.env.AGENTTEAMS_WEB_URL || 'https://agentteams.run';
|
|
16
|
+
/**
|
|
17
|
+
* Where to log in. Unlike the legacy `init` path this honours the project's own
|
|
18
|
+
* `apiUrl`, because a refresh token issued by the dev API is worthless against
|
|
19
|
+
* production and storing it under the wrong server would silently fail later.
|
|
20
|
+
*/
|
|
21
|
+
export function resolveAuthApiUrl(options) {
|
|
22
|
+
const candidate = (typeof options?.apiUrl === 'string' && options.apiUrl.length > 0 ? options.apiUrl : undefined) ??
|
|
23
|
+
process.env.AGENTTEAMS_API_URL ??
|
|
24
|
+
loadProjectConfig()?.apiUrl ??
|
|
25
|
+
DEFAULT_API_URL;
|
|
26
|
+
return candidate.replace(/\/+$/, '');
|
|
27
|
+
}
|
|
28
|
+
export function buildPersonalTokenAuthorizeUrl(input) {
|
|
29
|
+
const params = new URLSearchParams({
|
|
30
|
+
port: String(input.port),
|
|
31
|
+
state: input.state,
|
|
32
|
+
code_challenge: input.codeChallenge,
|
|
33
|
+
});
|
|
34
|
+
if (input.projectName) {
|
|
35
|
+
params.set('projectName', input.projectName);
|
|
36
|
+
}
|
|
37
|
+
return `${AUTH_BASE_URL.replace(/\/+$/, '')}/cli/authorize?${params.toString()}`;
|
|
38
|
+
}
|
|
39
|
+
function isSshEnvironment() {
|
|
40
|
+
return Boolean(process.env.SSH_CONNECTION || process.env.SSH_CLIENT || process.env.SSH_TTY);
|
|
41
|
+
}
|
|
42
|
+
async function tryOpenBrowser(url) {
|
|
43
|
+
console.log('🔐 Complete the AgentTeams login in your browser:');
|
|
44
|
+
console.log(url);
|
|
45
|
+
// Headless and SSH sessions have no browser to open; the printed URL is the
|
|
46
|
+
// whole interface there, exactly as in `init`.
|
|
47
|
+
if (isSshEnvironment()) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
try {
|
|
51
|
+
await open(url);
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
// Already printed.
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Run the browser round trip and exchange the resulting code for tokens.
|
|
59
|
+
*
|
|
60
|
+
* Exported so `init --auth personal-token` reuses the identical flow rather than
|
|
61
|
+
* growing a second copy of the PKCE handshake.
|
|
62
|
+
*/
|
|
63
|
+
export async function performPersonalTokenLogin(input) {
|
|
64
|
+
const client = getPersonalTokenClient(input.apiUrl);
|
|
65
|
+
const pkce = createPkcePair();
|
|
66
|
+
const authContext = await startAuthorizationCodeServer({ state: createAuthState() });
|
|
67
|
+
const authUrl = buildPersonalTokenAuthorizeUrl({
|
|
68
|
+
port: authContext.port,
|
|
69
|
+
state: authContext.state,
|
|
70
|
+
codeChallenge: pkce.challenge,
|
|
71
|
+
...(input.projectName ? { projectName: input.projectName } : {}),
|
|
72
|
+
});
|
|
73
|
+
await tryOpenBrowser(authUrl);
|
|
74
|
+
const spinner = createSpinner('Waiting for authorization... (Ctrl+C to cancel)');
|
|
75
|
+
try {
|
|
76
|
+
const callback = await authContext.waitForCallback();
|
|
77
|
+
spinner?.succeed();
|
|
78
|
+
const session = await client.exchangeAuthorizationCode({
|
|
79
|
+
code: callback.code,
|
|
80
|
+
codeVerifier: pkce.verifier,
|
|
81
|
+
// Must match the redirect the web registered the code against.
|
|
82
|
+
redirectUri: `http://localhost:${authContext.port}/callback`,
|
|
83
|
+
});
|
|
84
|
+
const state = client.state();
|
|
85
|
+
return {
|
|
86
|
+
authUrl,
|
|
87
|
+
identity: session.identity,
|
|
88
|
+
persisted: state.persisted,
|
|
89
|
+
storeBackend: state.storeBackend,
|
|
90
|
+
storeReason: state.storeReason,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
spinner?.fail();
|
|
95
|
+
throw error;
|
|
96
|
+
}
|
|
97
|
+
finally {
|
|
98
|
+
if (authContext.server.listening) {
|
|
99
|
+
authContext.server.close();
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
async function login(options) {
|
|
104
|
+
const requestedApiUrl = typeof options.apiUrl === 'string' ? options.apiUrl : undefined;
|
|
105
|
+
const apiUrl = resolveAuthApiUrl({ apiUrl: requestedApiUrl });
|
|
106
|
+
// What every later command will resolve against. The refresh token is filed
|
|
107
|
+
// under the server that issued it, so logging in to a different one would
|
|
108
|
+
// store the credential in a slot nothing ever reads — a "success" that makes
|
|
109
|
+
// the very next command fail.
|
|
110
|
+
const projectApiUrl = resolveAuthApiUrl();
|
|
111
|
+
if (apiUrl !== projectApiUrl) {
|
|
112
|
+
throw new PersonalTokenError('TRANSIENT', `This project talks to ${projectApiUrl}, so a login to ${apiUrl} would be stored where no command looks for it. ` +
|
|
113
|
+
`Point the project at that server first (set apiUrl in .agentteams/config.json or AGENTTEAMS_API_URL), then run 'agentteams auth login' without --api-url.`);
|
|
114
|
+
}
|
|
115
|
+
const outcome = await performPersonalTokenLogin({ apiUrl });
|
|
116
|
+
const configPath = findProjectConfig(process.cwd());
|
|
117
|
+
// Opting the project in is what makes later commands prefer this credential.
|
|
118
|
+
// Only ever done for a credential that outlives this process: flipping the
|
|
119
|
+
// project over to a login the next command cannot find would lock it out
|
|
120
|
+
// entirely when there is no `key_` left to fall back to.
|
|
121
|
+
const opted = configPath && outcome.persisted ? setProjectAuthMode(configPath, 'personal-token') : false;
|
|
122
|
+
const result = {
|
|
123
|
+
success: true,
|
|
124
|
+
authUrl: outcome.authUrl,
|
|
125
|
+
apiUrl,
|
|
126
|
+
identity: outcome.identity,
|
|
127
|
+
persisted: outcome.persisted,
|
|
128
|
+
storeBackend: outcome.storeBackend,
|
|
129
|
+
storeReason: outcome.storeReason,
|
|
130
|
+
configPath: opted ? configPath : null,
|
|
131
|
+
authMode: 'personal-token',
|
|
132
|
+
};
|
|
133
|
+
if (!outcome.persisted) {
|
|
134
|
+
result.warning =
|
|
135
|
+
'The login is kept in memory for this process only, so this project was left on its existing credential. ' +
|
|
136
|
+
'For CI and headless machines, keep using an API key (AGENTTEAMS_API_KEY).';
|
|
137
|
+
}
|
|
138
|
+
else if (!opted) {
|
|
139
|
+
result.warning =
|
|
140
|
+
"No project config was found, so nothing was switched to the personal login. Run 'agentteams init' in the project first, then run this again.";
|
|
141
|
+
}
|
|
142
|
+
return result;
|
|
143
|
+
}
|
|
144
|
+
async function status(options = {}) {
|
|
145
|
+
const apiUrl = resolveAuthApiUrl({ apiUrl: typeof options.apiUrl === 'string' ? options.apiUrl : undefined });
|
|
146
|
+
const projectConfig = loadProjectConfig();
|
|
147
|
+
const client = getPersonalTokenClient(apiUrl);
|
|
148
|
+
// Reading the state must not require a working network: a token that cannot
|
|
149
|
+
// be refreshed right now is still worth reporting as present.
|
|
150
|
+
const tokenState = client.state();
|
|
151
|
+
let credentialSource = null;
|
|
152
|
+
let problem;
|
|
153
|
+
try {
|
|
154
|
+
// The same apiUrl this command reports, so `apiUrl` and `credentialSource`
|
|
155
|
+
// can never describe two different servers.
|
|
156
|
+
credentialSource = (await resolveCredential({ apiUrl }))?.source ?? null;
|
|
157
|
+
}
|
|
158
|
+
catch (error) {
|
|
159
|
+
problem = error instanceof Error ? error.message : String(error);
|
|
160
|
+
}
|
|
161
|
+
const refreshedState = client.state();
|
|
162
|
+
const result = {
|
|
163
|
+
apiUrl,
|
|
164
|
+
configPath: findProjectConfig(process.cwd()),
|
|
165
|
+
credentialSource,
|
|
166
|
+
authMode: projectConfig?.authMode ?? null,
|
|
167
|
+
hasProjectApiKey: typeof projectConfig?.apiKey === 'string' && projectConfig.apiKey.length > 0,
|
|
168
|
+
personalToken: {
|
|
169
|
+
connected: tokenState.connected,
|
|
170
|
+
persisted: tokenState.persisted,
|
|
171
|
+
storeBackend: tokenState.storeBackend,
|
|
172
|
+
storeReason: tokenState.storeReason,
|
|
173
|
+
reconnectRequired: refreshedState.reconnectRequired,
|
|
174
|
+
identity: refreshedState.identity,
|
|
175
|
+
expiresAt: refreshedState.expiresAt ? new Date(refreshedState.expiresAt).toISOString() : null,
|
|
176
|
+
},
|
|
177
|
+
};
|
|
178
|
+
if (problem)
|
|
179
|
+
result.problem = problem;
|
|
180
|
+
return result;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Leave the personal-token path.
|
|
184
|
+
*
|
|
185
|
+
* Reverting `authMode` is the part that must always be reachable: a project
|
|
186
|
+
* left on `personal-token` with no credential fails every command, so a missing
|
|
187
|
+
* keychain entry or an unreachable server cannot be allowed to trap the user in
|
|
188
|
+
* a state only a hand-edited config file gets out of.
|
|
189
|
+
*/
|
|
190
|
+
async function logout(options = {}) {
|
|
191
|
+
const apiUrl = resolveAuthApiUrl({ apiUrl: typeof options.apiUrl === 'string' ? options.apiUrl : undefined });
|
|
192
|
+
const client = getPersonalTokenClient(apiUrl);
|
|
193
|
+
const localOnly = options.local === true;
|
|
194
|
+
let revokedOnServer = false;
|
|
195
|
+
let warning;
|
|
196
|
+
if (!client.hasCredential()) {
|
|
197
|
+
warning = `No AgentTeams login was stored for ${apiUrl}; only the project setting was reverted.`;
|
|
198
|
+
}
|
|
199
|
+
else if (localOnly) {
|
|
200
|
+
client.forgetLocalCredential();
|
|
201
|
+
warning =
|
|
202
|
+
'The local credential was removed without contacting the server, so the token is still valid there. ' +
|
|
203
|
+
'Revoke it from the AgentTeams web app if you no longer want it.';
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
try {
|
|
207
|
+
// Server first: clearing locally and then failing the revoke would leave a
|
|
208
|
+
// live refresh token the owner can no longer see or cancel.
|
|
209
|
+
await client.revoke();
|
|
210
|
+
revokedOnServer = true;
|
|
211
|
+
}
|
|
212
|
+
catch (error) {
|
|
213
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
214
|
+
throw new PersonalTokenError('REVOKE_FAILED', `${detail} Run 'agentteams auth logout --local' to leave the personal login path anyway.`);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
const configPath = findProjectConfig(process.cwd());
|
|
218
|
+
const reverted = configPath ? setProjectAuthMode(configPath, null) : false;
|
|
219
|
+
const projectConfig = loadProjectConfig();
|
|
220
|
+
const result = {
|
|
221
|
+
success: true,
|
|
222
|
+
apiUrl,
|
|
223
|
+
configPath: reverted ? configPath : null,
|
|
224
|
+
revokedOnServer,
|
|
225
|
+
fellBackToApiKey: typeof projectConfig?.apiKey === 'string' && projectConfig.apiKey.length > 0,
|
|
226
|
+
};
|
|
227
|
+
if (warning)
|
|
228
|
+
result.warning = warning;
|
|
229
|
+
return result;
|
|
230
|
+
}
|
|
231
|
+
export async function executeAuthCommand(action, options = {}) {
|
|
232
|
+
return withCommandContext(`auth:${action}`, async () => {
|
|
233
|
+
switch (action) {
|
|
234
|
+
case 'login':
|
|
235
|
+
return login(options);
|
|
236
|
+
case 'status':
|
|
237
|
+
return status(options);
|
|
238
|
+
case 'logout':
|
|
239
|
+
return logout(options);
|
|
240
|
+
default:
|
|
241
|
+
throw new Error(`Unknown action: ${action}. Expected one of: login, status, logout.`);
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAE5F,OAAO,EAAE,4BAA4B,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACvG,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,GAEnB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAEhE,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,wBAAwB,CAAC;AAmDjF;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAA6B;IAC7D,MAAM,SAAS,GACb,CAAC,OAAO,OAAO,EAAE,MAAM,KAAK,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;QAC/F,OAAO,CAAC,GAAG,CAAC,kBAAkB;QAC9B,iBAAiB,EAAE,EAAE,MAAM;QAC3B,eAAe,CAAC;IAClB,OAAO,SAAS,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,8BAA8B,CAAC,KAK9C;IACC,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC;QACjC,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;QACxB,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,cAAc,EAAE,KAAK,CAAC,aAAa;KACpC,CAAC,CAAC;IACH,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;QACtB,MAAM,CAAC,GAAG,CAAC,aAAa,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;IAC/C,CAAC;IACD,OAAO,GAAG,aAAa,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,kBAAkB,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC;AACnF,CAAC;AAED,SAAS,gBAAgB;IACvB,OAAO,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AAC9F,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,GAAW;IACvC,OAAO,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAC;IACjE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAEjB,4EAA4E;IAC5E,+CAA+C;IAC/C,IAAI,gBAAgB,EAAE,EAAE,CAAC;QACvB,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QACH,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC;IAClB,CAAC;IAAC,MAAM,CAAC;QACP,mBAAmB;IACrB,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAAC,KAA+C;IAO7F,MAAM,MAAM,GAAG,sBAAsB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACpD,MAAM,IAAI,GAAG,cAAc,EAAE,CAAC;IAC9B,MAAM,WAAW,GAAG,MAAM,4BAA4B,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,EAAE,CAAC,CAAC;IAErF,MAAM,OAAO,GAAG,8BAA8B,CAAC;QAC7C,IAAI,EAAE,WAAW,CAAC,IAAI;QACtB,KAAK,EAAE,WAAW,CAAC,KAAK;QACxB,aAAa,EAAE,IAAI,CAAC,SAAS;QAC7B,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACjE,CAAC,CAAC;IAEH,MAAM,cAAc,CAAC,OAAO,CAAC,CAAC;IAC9B,MAAM,OAAO,GAAG,aAAa,CAAC,iDAAiD,CAAC,CAAC;IAEjF,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,eAAe,EAAE,CAAC;QACrD,OAAO,EAAE,OAAO,EAAE,CAAC;QAEnB,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,yBAAyB,CAAC;YACrD,IAAI,EAAE,QAAQ,CAAC,IAAI;YACnB,YAAY,EAAE,IAAI,CAAC,QAAQ;YAC3B,+DAA+D;YAC/D,WAAW,EAAE,oBAAoB,WAAW,CAAC,IAAI,WAAW;SAC7D,CAAC,CAAC;QAEH,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,EAAE,CAAC;QAC7B,OAAO;YACL,OAAO;YACP,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,YAAY,EAAE,KAAK,CAAC,YAAY;YAChC,WAAW,EAAE,KAAK,CAAC,WAAW;SAC/B,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,EAAE,IAAI,EAAE,CAAC;QAChB,MAAM,KAAK,CAAC;IACd,CAAC;YAAS,CAAC;QACT,IAAI,WAAW,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;YACjC,WAAW,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAC7B,CAAC;IACH,CAAC;AACH,CAAC;AAED,KAAK,UAAU,KAAK,CAAC,OAAgC;IACnD,MAAM,eAAe,GAAG,OAAO,OAAO,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;IACxF,MAAM,MAAM,GAAG,iBAAiB,CAAC,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC,CAAC;IAC9D,4EAA4E;IAC5E,0EAA0E;IAC1E,6EAA6E;IAC7E,8BAA8B;IAC9B,MAAM,aAAa,GAAG,iBAAiB,EAAE,CAAC;IAE1C,IAAI,MAAM,KAAK,aAAa,EAAE,CAAC;QAC7B,MAAM,IAAI,kBAAkB,CAC1B,WAAW,EACX,yBAAyB,aAAa,mBAAmB,MAAM,kDAAkD;YAC/G,2JAA2J,CAC9J,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,yBAAyB,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;IAE5D,MAAM,UAAU,GAAG,iBAAiB,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACpD,6EAA6E;IAC7E,2EAA2E;IAC3E,yEAAyE;IACzE,yDAAyD;IACzD,MAAM,KAAK,GAAG,UAAU,IAAI,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,kBAAkB,CAAC,UAAU,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IAEzG,MAAM,MAAM,GAAoB;QAC9B,OAAO,EAAE,IAAI;QACb,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,MAAM;QACN,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,YAAY,EAAE,OAAO,CAAC,YAAY;QAClC,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,UAAU,EAAE,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI;QACrC,QAAQ,EAAE,gBAAgB;KAC3B,CAAC;IAEF,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC;QACvB,MAAM,CAAC,OAAO;YACZ,0GAA0G;gBAC1G,2EAA2E,CAAC;IAChF,CAAC;SAAM,IAAI,CAAC,KAAK,EAAE,CAAC;QAClB,MAAM,CAAC,OAAO;YACZ,8IAA8I,CAAC;IACnJ,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,KAAK,UAAU,MAAM,CAAC,UAAmC,EAAE;IACzD,MAAM,MAAM,GAAG,iBAAiB,CAAC,EAAE,MAAM,EAAE,OAAO,OAAO,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC;IAC9G,MAAM,aAAa,GAAG,iBAAiB,EAAE,CAAC;IAC1C,MAAM,MAAM,GAAG,sBAAsB,CAAC,MAAM,CAAC,CAAC;IAE9C,4EAA4E;IAC5E,8DAA8D;IAC9D,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,EAAE,CAAC;IAElC,IAAI,gBAAgB,GAA4B,IAAI,CAAC;IACrD,IAAI,OAA2B,CAAC;IAChC,IAAI,CAAC;QACH,2EAA2E;QAC3E,4CAA4C;QAC5C,gBAAgB,GAAG,CAAC,MAAM,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,IAAI,IAAI,CAAC;IAC3E,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACnE,CAAC;IAED,MAAM,cAAc,GAAG,MAAM,CAAC,KAAK,EAAE,CAAC;IAEtC,MAAM,MAAM,GAAqB;QAC/B,MAAM;QACN,UAAU,EAAE,iBAAiB,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;QAC5C,gBAAgB;QAChB,QAAQ,EAAE,aAAa,EAAE,QAAQ,IAAI,IAAI;QACzC,gBAAgB,EAAE,OAAO,aAAa,EAAE,MAAM,KAAK,QAAQ,IAAI,aAAa,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC;QAC9F,aAAa,EAAE;YACb,SAAS,EAAE,UAAU,CAAC,SAAS;YAC/B,SAAS,EAAE,UAAU,CAAC,SAAS;YAC/B,YAAY,EAAE,UAAU,CAAC,YAAY;YACrC,WAAW,EAAE,UAAU,CAAC,WAAW;YACnC,iBAAiB,EAAE,cAAc,CAAC,iBAAiB;YACnD,QAAQ,EAAE,cAAc,CAAC,QAAQ;YACjC,SAAS,EAAE,cAAc,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI;SAC9F;KACF,CAAC;IAEF,IAAI,OAAO;QAAE,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC;IACtC,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;GAOG;AACH,KAAK,UAAU,MAAM,CAAC,UAAmC,EAAE;IACzD,MAAM,MAAM,GAAG,iBAAiB,CAAC,EAAE,MAAM,EAAE,OAAO,OAAO,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC;IAC9G,MAAM,MAAM,GAAG,sBAAsB,CAAC,MAAM,CAAC,CAAC;IAC9C,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,KAAK,IAAI,CAAC;IAEzC,IAAI,eAAe,GAAG,KAAK,CAAC;IAC5B,IAAI,OAA2B,CAAC;IAEhC,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,EAAE,CAAC;QAC5B,OAAO,GAAG,sCAAsC,MAAM,0CAA0C,CAAC;IACnG,CAAC;SAAM,IAAI,SAAS,EAAE,CAAC;QACrB,MAAM,CAAC,qBAAqB,EAAE,CAAC;QAC/B,OAAO;YACL,qGAAqG;gBACrG,iEAAiE,CAAC;IACtE,CAAC;SAAM,CAAC;QACN,IAAI,CAAC;YACH,2EAA2E;YAC3E,4DAA4D;YAC5D,MAAM,MAAM,CAAC,MAAM,EAAE,CAAC;YACtB,eAAe,GAAG,IAAI,CAAC;QACzB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,MAAM,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACtE,MAAM,IAAI,kBAAkB,CAC1B,eAAe,EACf,GAAG,MAAM,gFAAgF,CAC1F,CAAC;QACJ,CAAC;IACH,CAAC;IAED,MAAM,UAAU,GAAG,iBAAiB,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACpD,MAAM,QAAQ,GAAG,UAAU,CAAC,CAAC,CAAC,kBAAkB,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IAC3E,MAAM,aAAa,GAAG,iBAAiB,EAAE,CAAC;IAE1C,MAAM,MAAM,GAAqB;QAC/B,OAAO,EAAE,IAAI;QACb,MAAM;QACN,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI;QACxC,eAAe;QACf,gBAAgB,EAAE,OAAO,aAAa,EAAE,MAAM,KAAK,QAAQ,IAAI,aAAa,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC;KAC/F,CAAC;IACF,IAAI,OAAO;QAAE,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC;IACtC,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,MAAc,EAAE,UAAmC,EAAE;IAC5F,OAAO,kBAAkB,CAAC,QAAQ,MAAM,EAAE,EAAE,KAAK,IAAI,EAAE;QACrD,QAAQ,MAAM,EAAE,CAAC;YACf,KAAK,OAAO;gBACV,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC;YACxB,KAAK,QAAQ;gBACX,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC;YACzB,KAAK,QAAQ;gBACX,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC;YACzB;gBACE,MAAM,IAAI,KAAK,CAAC,mBAAmB,MAAM,2CAA2C,CAAC,CAAC;QAC1F,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAEA,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAEA,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAyCvE"}
|
package/dist/commands/config.js
CHANGED
|
@@ -1,16 +1,28 @@
|
|
|
1
|
-
import { findProjectConfig,
|
|
1
|
+
import { findProjectConfig, loadConfigWithCredential, loadProjectConfig } from '../utils/config.js';
|
|
2
2
|
export async function executeConfigCommand(action) {
|
|
3
3
|
switch (action) {
|
|
4
4
|
case 'whoami': {
|
|
5
5
|
const configPath = findProjectConfig(process.cwd());
|
|
6
|
-
const
|
|
6
|
+
const authMode = loadProjectConfig()?.authMode ?? null;
|
|
7
|
+
// `whoami` is the command people run *because* something is wrong, so a
|
|
8
|
+
// credential that cannot be resolved is reported, never thrown.
|
|
9
|
+
let config = null;
|
|
10
|
+
let problem;
|
|
11
|
+
try {
|
|
12
|
+
config = await loadConfigWithCredential();
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
problem = error instanceof Error ? error.message : String(error);
|
|
16
|
+
}
|
|
7
17
|
if (!config) {
|
|
8
18
|
return {
|
|
9
19
|
apiUrl: process.env.AGENTTEAMS_API_URL,
|
|
10
20
|
projectId: process.env.AGENTTEAMS_PROJECT_ID,
|
|
11
21
|
teamId: process.env.AGENTTEAMS_TEAM_ID,
|
|
12
22
|
hasApiKey: Boolean(process.env.AGENTTEAMS_API_KEY),
|
|
23
|
+
authMode,
|
|
13
24
|
configPath,
|
|
25
|
+
...(problem ? { problem } : {}),
|
|
14
26
|
};
|
|
15
27
|
}
|
|
16
28
|
return {
|
|
@@ -18,6 +30,8 @@ export async function executeConfigCommand(action) {
|
|
|
18
30
|
projectId: config.projectId,
|
|
19
31
|
teamId: config.teamId,
|
|
20
32
|
hasApiKey: Boolean(config.apiKey),
|
|
33
|
+
credentialSource: config.credentialSource,
|
|
34
|
+
authMode,
|
|
21
35
|
configPath,
|
|
22
36
|
};
|
|
23
37
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAEpG,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,MAAc;IACvD,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,UAAU,GAAG,iBAAiB,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;YACpD,MAAM,QAAQ,GAAG,iBAAiB,EAAE,EAAE,QAAQ,IAAI,IAAI,CAAC;YAEvD,wEAAwE;YACxE,gEAAgE;YAChE,IAAI,MAAM,GAAG,IAAI,CAAC;YAClB,IAAI,OAA2B,CAAC;YAChC,IAAI,CAAC;gBACH,MAAM,GAAG,MAAM,wBAAwB,EAAE,CAAC;YAC5C,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACnE,CAAC;YAED,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,OAAO;oBACL,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB;oBACtC,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,qBAAqB;oBAC5C,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB;oBACtC,SAAS,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;oBAClD,QAAQ;oBACR,UAAU;oBACV,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBAChC,CAAC;YACJ,CAAC;YAED,OAAO;gBACL,MAAM,EAAE,MAAM,CAAC,MAAM;gBACrB,SAAS,EAAE,MAAM,CAAC,SAAS;gBAC3B,MAAM,EAAE,MAAM,CAAC,MAAM;gBACrB,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC;gBACjC,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;gBACzC,QAAQ;gBACR,UAAU;aACX,CAAC;QACJ,CAAC;QACD;YACE,MAAM,IAAI,KAAK,CAAC,mBAAmB,MAAM,EAAE,CAAC,CAAC;IACjD,CAAC;AACH,CAAC"}
|
|
@@ -49,6 +49,12 @@ export type ConventionStatusResult = {
|
|
|
49
49
|
hints: string[];
|
|
50
50
|
/** One-line human-readable summary. */
|
|
51
51
|
summary: string;
|
|
52
|
+
/**
|
|
53
|
+
* Set when the project *is* configured but its credential could not be
|
|
54
|
+
* resolved. Distinguishes "nothing to check" from "could not check" — the
|
|
55
|
+
* latter must never read as "up to date".
|
|
56
|
+
*/
|
|
57
|
+
credentialProblem?: string;
|
|
52
58
|
};
|
|
53
59
|
export declare function buildStatusSummary(result: ConventionFreshnessResult): string;
|
|
54
60
|
/**
|
|
@@ -58,6 +64,11 @@ export declare function buildStatusSummary(result: ConventionFreshnessResult): s
|
|
|
58
64
|
* update is available — it never downloads or mutates anything. Degrades gracefully
|
|
59
65
|
* (exit 0, updateAvailable=false) when the project is not configured or has no local
|
|
60
66
|
* conventions yet, so callers can safely "check then skip when unavailable".
|
|
67
|
+
*
|
|
68
|
+
* "Not configured" and "configured but the credential failed" are reported
|
|
69
|
+
* differently on purpose. The platform convention makes this the session-start
|
|
70
|
+
* freshness gate, so a project whose login is broken must say so instead of
|
|
71
|
+
* quietly claiming its rules are current.
|
|
61
72
|
*/
|
|
62
73
|
export declare function conventionStatus(options?: ConventionCommandOptions): Promise<ConventionStatusResult>;
|
|
63
74
|
export declare function conventionList(): Promise<any>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"convention.d.ts","sourceRoot":"","sources":["../../src/commands/convention.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAWhD,KAAK,wBAAwB,GAAG;IAC9B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC,CAAC;AAqBF,KAAK,uBAAuB,GAAG,wBAAwB,GAAG;IACxD,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACxB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,KAAK,uBAAuB,GAAG,wBAAwB,GAAG;IACxD,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACxB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,KAAK,uBAAuB,GAAG,wBAAwB,GAAG;IACxD,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAkBF,MAAM,MAAM,yBAAyB,GAAG;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,KAAK,GAAG,SAAS,GAAG,SAAS,CAAC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACtC,qBAAqB,EAAE,OAAO,CAAC;IAC/B,iBAAiB,EAAE,yBAAyB,EAAE,CAAC;CAChD,CAAC;
|
|
1
|
+
{"version":3,"file":"convention.d.ts","sourceRoot":"","sources":["../../src/commands/convention.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,7 +7,7 @@ import { isAxiosError } from 'axios';
|
|
|
7
7
|
import { downloadAllConventions, listConventions } from '../api/convention.js';
|
|
8
8
|
import matter from 'gray-matter';
|
|
9
9
|
import { diffLines, createTwoFilesPatch } from 'diff';
|
|
10
|
-
import {
|
|
10
|
+
import { loadConfigWithCredential, findProjectConfig, getConfigurationNotFoundMessage } from '../utils/config.js';
|
|
11
11
|
import { withSpinner } from '../utils/spinner.js';
|
|
12
12
|
import { withoutJsonContentType } from '../utils/httpHeaders.js';
|
|
13
13
|
import { compareVersions, getLatestCliVersion } from '../utils/updateCheck.js';
|
|
@@ -28,8 +28,11 @@ function findProjectRoot(cwd) {
|
|
|
28
28
|
function getApiBaseUrl(apiUrl) {
|
|
29
29
|
return apiUrl.endsWith('/') ? apiUrl.slice(0, -1) : apiUrl;
|
|
30
30
|
}
|
|
31
|
-
function getApiConfigOrThrow(options) {
|
|
32
|
-
|
|
31
|
+
async function getApiConfigOrThrow(options) {
|
|
32
|
+
// Credential-aware: a personal-token project keeps no `apiKey` on disk, and
|
|
33
|
+
// the conventions these commands sync become always-on agent rules — reading
|
|
34
|
+
// "not initialized" there would silently freeze a project's rules.
|
|
35
|
+
const config = options?.config ?? (await loadConfigWithCredential());
|
|
33
36
|
if (!config) {
|
|
34
37
|
throw new Error(getConfigurationNotFoundMessage(options?.cwd));
|
|
35
38
|
}
|
|
@@ -216,7 +219,7 @@ function toOptionalStringOrNullIfPresent(data, key) {
|
|
|
216
219
|
return undefined;
|
|
217
220
|
}
|
|
218
221
|
export async function conventionShow() {
|
|
219
|
-
const { config, apiUrl, headers } = getApiConfigOrThrow();
|
|
222
|
+
const { config, apiUrl, headers } = await getApiConfigOrThrow();
|
|
220
223
|
const conventions = await fetchConventionsWithContent(apiUrl, config.projectId, headers);
|
|
221
224
|
if (!conventions || conventions.length === 0) {
|
|
222
225
|
throw new Error('No conventions found for this project. Create one via the web dashboard first.');
|
|
@@ -342,10 +345,14 @@ function buildStatusResult(params) {
|
|
|
342
345
|
if (conventionUpdateAvailable) {
|
|
343
346
|
hints.push(`ACTION REQUIRED: Sync conventions now: ${actions.syncConventions}. After syncing, re-read .agentteams/convention.md and any changed rule files before continuing.`);
|
|
344
347
|
}
|
|
348
|
+
else if (params.credentialProblem) {
|
|
349
|
+
hints.push(`WARNING: Convention freshness was NOT checked — ${params.credentialProblem} Conventions may be stale; fix the login, then re-run 'agentteams convention status'.`);
|
|
350
|
+
}
|
|
345
351
|
else {
|
|
346
352
|
hints.push('OK: Conventions and platform guides are up to date.');
|
|
347
353
|
}
|
|
348
354
|
return {
|
|
355
|
+
...(params.credentialProblem ? { credentialProblem: params.credentialProblem } : {}),
|
|
349
356
|
updateAvailable: conventionUpdateAvailable,
|
|
350
357
|
conventionUpdateAvailable,
|
|
351
358
|
platformGuidesChanged: params.freshness.platformGuidesChanged,
|
|
@@ -353,7 +360,7 @@ function buildStatusResult(params) {
|
|
|
353
360
|
cliUpdateAvailable: params.cliUpdateAvailable,
|
|
354
361
|
currentCliVersion: params.currentCliVersion,
|
|
355
362
|
latestCliVersion: params.latestCliVersion,
|
|
356
|
-
actionRequired: conventionUpdateAvailable || params.cliUpdateAvailable,
|
|
363
|
+
actionRequired: conventionUpdateAvailable || params.cliUpdateAvailable || Boolean(params.credentialProblem),
|
|
357
364
|
actions,
|
|
358
365
|
hints,
|
|
359
366
|
summary: buildCombinedStatusSummary({
|
|
@@ -371,16 +378,33 @@ function buildStatusResult(params) {
|
|
|
371
378
|
* update is available — it never downloads or mutates anything. Degrades gracefully
|
|
372
379
|
* (exit 0, updateAvailable=false) when the project is not configured or has no local
|
|
373
380
|
* conventions yet, so callers can safely "check then skip when unavailable".
|
|
381
|
+
*
|
|
382
|
+
* "Not configured" and "configured but the credential failed" are reported
|
|
383
|
+
* differently on purpose. The platform convention makes this the session-start
|
|
384
|
+
* freshness gate, so a project whose login is broken must say so instead of
|
|
385
|
+
* quietly claiming its rules are current.
|
|
374
386
|
*/
|
|
375
387
|
export async function conventionStatus(options) {
|
|
376
|
-
const config = options?.config ?? loadConfig();
|
|
377
388
|
const projectRoot = findProjectRoot(options?.cwd);
|
|
378
389
|
const cliStatus = await resolveCliUpdateStatus(options);
|
|
390
|
+
let config = options?.config ?? null;
|
|
391
|
+
let credentialProblem;
|
|
392
|
+
if (!config) {
|
|
393
|
+
try {
|
|
394
|
+
config = await loadConfigWithCredential();
|
|
395
|
+
}
|
|
396
|
+
catch (error) {
|
|
397
|
+
credentialProblem = error instanceof Error ? error.message : String(error);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
379
400
|
// Not configured or no local conventions → nothing to compare; treat as up to date.
|
|
380
401
|
if (!config || !projectRoot) {
|
|
381
402
|
return buildStatusResult({
|
|
382
403
|
freshness: { platformGuidesChanged: false, conventionChanges: [] },
|
|
383
404
|
...cliStatus,
|
|
405
|
+
// Only a project that exists locally can have a credential problem worth
|
|
406
|
+
// reporting; without a project root there is nothing to be stale.
|
|
407
|
+
...(credentialProblem && projectRoot ? { credentialProblem } : {}),
|
|
384
408
|
});
|
|
385
409
|
}
|
|
386
410
|
const apiUrl = getApiBaseUrl(config.apiUrl);
|
|
@@ -392,7 +416,7 @@ export async function conventionStatus(options) {
|
|
|
392
416
|
return buildStatusResult({ freshness, ...cliStatus });
|
|
393
417
|
}
|
|
394
418
|
export async function conventionList() {
|
|
395
|
-
const { config, apiUrl, headers } = getApiConfigOrThrow();
|
|
419
|
+
const { config, apiUrl, headers } = await getApiConfigOrThrow();
|
|
396
420
|
const conventions = await fetchAllConventions(apiUrl, config.projectId, headers);
|
|
397
421
|
if (!Array.isArray(conventions)) {
|
|
398
422
|
return { data: conventions };
|
|
@@ -504,7 +528,7 @@ async function downloadReportingTemplate(projectRoot, config, apiUrl, headers) {
|
|
|
504
528
|
return true;
|
|
505
529
|
}
|
|
506
530
|
export async function conventionDownload(options) {
|
|
507
|
-
const { config, apiUrl, headers } = getApiConfigOrThrow(options);
|
|
531
|
+
const { config, apiUrl, headers } = await getApiConfigOrThrow(options);
|
|
508
532
|
const projectRoot = findProjectRoot(options?.cwd);
|
|
509
533
|
if (!projectRoot) {
|
|
510
534
|
throw new Error("No .agentteams directory found. Run 'agentteams init' first.");
|
|
@@ -590,7 +614,7 @@ function parseConventionMarkdown(fileRelativePath, markdown) {
|
|
|
590
614
|
}
|
|
591
615
|
}
|
|
592
616
|
export async function conventionCreate(options) {
|
|
593
|
-
const { config, apiUrl, headers } = getApiConfigOrThrow(options);
|
|
617
|
+
const { config, apiUrl, headers } = await getApiConfigOrThrow(options);
|
|
594
618
|
const projectRoot = findProjectRoot(options?.cwd);
|
|
595
619
|
if (!projectRoot) {
|
|
596
620
|
throw new Error("No .agentteams directory found. Run 'agentteams init' first.");
|
|
@@ -670,7 +694,7 @@ export async function conventionCreate(options) {
|
|
|
670
694
|
return results.join('\n');
|
|
671
695
|
}
|
|
672
696
|
export async function conventionUpdate(options) {
|
|
673
|
-
const { config, apiUrl, headers } = getApiConfigOrThrow(options);
|
|
697
|
+
const { config, apiUrl, headers } = await getApiConfigOrThrow(options);
|
|
674
698
|
const projectRoot = findProjectRoot(options?.cwd);
|
|
675
699
|
if (!projectRoot) {
|
|
676
700
|
throw new Error("No .agentteams directory found. Run 'agentteams init' first.");
|
|
@@ -748,7 +772,7 @@ export async function conventionUpdate(options) {
|
|
|
748
772
|
return results.join('\n\n');
|
|
749
773
|
}
|
|
750
774
|
export async function conventionDelete(options) {
|
|
751
|
-
const { config, apiUrl, headers } = getApiConfigOrThrow(options);
|
|
775
|
+
const { config, apiUrl, headers } = await getApiConfigOrThrow(options);
|
|
752
776
|
const projectRoot = findProjectRoot(options?.cwd);
|
|
753
777
|
if (!projectRoot) {
|
|
754
778
|
throw new Error("No .agentteams directory found. Run 'agentteams init' first.");
|