@idea1/cli 1.10.4 → 1.11.1
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/README.md +74 -32
- package/dist/commands/help.d.ts.map +1 -1
- package/dist/commands/help.js +30 -12
- package/dist/commands/help.js.map +1 -1
- package/dist/commands/index.d.ts +3 -1
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +5 -1
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/login.d.ts +3 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +15 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/logout.d.ts +3 -0
- package/dist/commands/logout.d.ts.map +1 -0
- package/dist/commands/logout.js +17 -0
- package/dist/commands/logout.js.map +1 -0
- package/dist/commands/release.d.ts +9 -4
- package/dist/commands/release.d.ts.map +1 -1
- package/dist/commands/release.js +53 -27
- package/dist/commands/release.js.map +1 -1
- package/dist/lib/project-item-url.d.ts +6 -0
- package/dist/lib/project-item-url.d.ts.map +1 -1
- package/dist/lib/project-item-url.js +11 -0
- package/dist/lib/project-item-url.js.map +1 -1
- package/dist/lib/settings.d.ts +25 -3
- package/dist/lib/settings.d.ts.map +1 -1
- package/dist/lib/settings.js +26 -1
- package/dist/lib/settings.js.map +1 -1
- package/dist/prompts/platform-prompts.d.ts +5 -30
- package/dist/prompts/platform-prompts.d.ts.map +1 -1
- package/dist/prompts/platform-prompts.js +5 -44
- package/dist/prompts/platform-prompts.js.map +1 -1
- package/dist/services/github.d.ts +21 -19
- package/dist/services/github.d.ts.map +1 -1
- package/dist/services/github.js +56 -64
- package/dist/services/github.js.map +1 -1
- package/dist/services/platform-auth.d.ts +44 -0
- package/dist/services/platform-auth.d.ts.map +1 -0
- package/dist/services/platform-auth.js +476 -0
- package/dist/services/platform-auth.js.map +1 -0
- package/dist/services/platform.d.ts +75 -18
- package/dist/services/platform.d.ts.map +1 -1
- package/dist/services/platform.js +254 -191
- package/dist/services/platform.js.map +1 -1
- package/dist/services/setup.d.ts.map +1 -1
- package/dist/services/setup.js +2 -1
- package/dist/services/setup.js.map +1 -1
- package/dist/types/index.d.ts +32 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +1 -1
- package/dist/types/index.js.map +1 -1
- package/dist/workflow/data/team-member.d.ts +9 -2
- package/dist/workflow/data/team-member.d.ts.map +1 -1
- package/dist/workflow/data/team-member.js +8 -1
- package/dist/workflow/data/team-member.js.map +1 -1
- package/dist/workflow/engine/approval-flow.d.ts +28 -11
- package/dist/workflow/engine/approval-flow.d.ts.map +1 -1
- package/dist/workflow/engine/approval-flow.js +52 -17
- package/dist/workflow/engine/approval-flow.js.map +1 -1
- package/dist/workflow/engine/branch-setup.d.ts +1 -1
- package/dist/workflow/engine/branch-setup.js +1 -1
- package/dist/workflow/engine/handlers/approve-pr.d.ts +10 -9
- package/dist/workflow/engine/handlers/approve-pr.d.ts.map +1 -1
- package/dist/workflow/engine/handlers/approve-pr.js +24 -17
- package/dist/workflow/engine/handlers/approve-pr.js.map +1 -1
- package/dist/workflow/engine/release-engine.d.ts +90 -58
- package/dist/workflow/engine/release-engine.d.ts.map +1 -1
- package/dist/workflow/engine/release-engine.js +296 -161
- package/dist/workflow/engine/release-engine.js.map +1 -1
- package/dist/workflow/engine/workflow-engine.d.ts +9 -2
- package/dist/workflow/engine/workflow-engine.d.ts.map +1 -1
- package/dist/workflow/engine/workflow-engine.js +20 -2
- package/dist/workflow/engine/workflow-engine.js.map +1 -1
- package/package.json +2 -1
|
@@ -0,0 +1,476 @@
|
|
|
1
|
+
import { createHash, randomBytes } from 'crypto';
|
|
2
|
+
import { createServer } from 'http';
|
|
3
|
+
import { setTimeout as delay } from 'timers/promises';
|
|
4
|
+
import { AsyncEntry } from '@napi-rs/keyring';
|
|
5
|
+
import { logger } from '../lib/logger.js';
|
|
6
|
+
import { isUnattended } from '../lib/prompt.js';
|
|
7
|
+
import { openUrl } from './os-launcher.js';
|
|
8
|
+
/**
|
|
9
|
+
* The CLI's OAuth client of the Idea1 platform: it holds the credential every platform call is
|
|
10
|
+
* authorized with, and signs the user in and out.
|
|
11
|
+
*
|
|
12
|
+
* The CLI is a public client (no secret) that registers itself dynamically with the platform's
|
|
13
|
+
* authorization server, discovered at `{apiBase}/.well-known/oauth-authorization-server`. Signing in
|
|
14
|
+
* is the authorization code flow with PKCE: the browser opens the platform's consent page, where the
|
|
15
|
+
* user picks the team the grant is bound to, and the platform redirects back to a loopback server
|
|
16
|
+
* the CLI runs on a random port of 127.0.0.1 (the registered `http://127.0.0.1/callback` matches on
|
|
17
|
+
* any port). The resulting team-bound access token is short-lived; the refresh token renews it.
|
|
18
|
+
*
|
|
19
|
+
* The credential lives in the operating system's credential store (macOS Keychain, Windows
|
|
20
|
+
* Credential Manager, Secret Service on Linux) under the service `idea1-cli` and the API base URL as
|
|
21
|
+
* the account, as the JSON of a `StoredCredential`; a credential longer than one entry holds
|
|
22
|
+
* continues in further entries. Parallel CLI processes share it: the platform does not rotate
|
|
23
|
+
* refresh tokens, so concurrent refreshes all stay valid and the last write wins.
|
|
24
|
+
*
|
|
25
|
+
* `IDEA1_TOKEN`, when set, is the bearer token of every call instead (a team API client's token in
|
|
26
|
+
* CI, or a test's): nothing is read from or written to the credential store, and nothing is
|
|
27
|
+
* refreshed. `IDEA1_API_BASE_URL` points the CLI at another platform than https://api.idea1.ai.
|
|
28
|
+
*/
|
|
29
|
+
export const API_BASE_URL_ENV = 'IDEA1_API_BASE_URL';
|
|
30
|
+
export const TOKEN_ENV = 'IDEA1_TOKEN';
|
|
31
|
+
const DEFAULT_API_BASE_URL = 'https://api.idea1.ai';
|
|
32
|
+
const CREDENTIAL_STORE_SERVICE = 'idea1-cli';
|
|
33
|
+
/**
|
|
34
|
+
* The most UTF-16 code units one credential store entry holds: Windows Credential Manager caps an
|
|
35
|
+
* entry at 2560 bytes. The platform's access and refresh tokens are JWTs that together exceed it,
|
|
36
|
+
* so a credential is kept as a run of entries, each a piece of its JSON behind a header of at most
|
|
37
|
+
* CREDENTIAL_PIECE_HEADER_LENGTH code units (the write's id and the run's length).
|
|
38
|
+
*/
|
|
39
|
+
const CREDENTIAL_STORE_ENTRY_LENGTH = 1280;
|
|
40
|
+
const CREDENTIAL_PIECE_HEADER_LENGTH = 12;
|
|
41
|
+
const CREDENTIAL_PIECE_TEXT_LENGTH = CREDENTIAL_STORE_ENTRY_LENGTH - CREDENTIAL_PIECE_HEADER_LENGTH;
|
|
42
|
+
const CREDENTIAL_PIECE_PATTERN = /^([0-9a-f]{8}):(\d+):(.*)$/s;
|
|
43
|
+
/** How many times, and how far apart, a run whose entries are not all of one write is read. */
|
|
44
|
+
const STORED_CREDENTIAL_READ_ATTEMPTS = 4;
|
|
45
|
+
const STORED_CREDENTIAL_READ_RETRY_MS = 100;
|
|
46
|
+
const CLIENT_NAME = 'Idea1 CLI';
|
|
47
|
+
const CLIENT_SCOPE = 'team:read projects:read projects:write';
|
|
48
|
+
/** The redirect URI the client registers; the loopback server listens on a random port of it. */
|
|
49
|
+
const REGISTERED_REDIRECT_URI = 'http://127.0.0.1/callback';
|
|
50
|
+
const SIGN_IN_TIMEOUT_MS = 5 * 60 * 1000;
|
|
51
|
+
/** An access token this close to its expiry is renewed before it is used. */
|
|
52
|
+
const EXPIRY_MARGIN_MS = 60 * 1000;
|
|
53
|
+
/**
|
|
54
|
+
* An OAuth error response (RFC 6749 §5.2), from an endpoint or from the authorization redirect.
|
|
55
|
+
*/
|
|
56
|
+
class OAuthError extends Error {
|
|
57
|
+
code;
|
|
58
|
+
constructor(code, description) {
|
|
59
|
+
super(description === null ? `idea1.ai sign-in failed: ${code}` : `idea1.ai sign-in failed: ${code} (${description})`);
|
|
60
|
+
this.code = code;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* The base URL of the platform's API, without a trailing slash.
|
|
65
|
+
*/
|
|
66
|
+
export function apiBaseUrl() {
|
|
67
|
+
const configured = process.env[API_BASE_URL_ENV]?.trim();
|
|
68
|
+
return (configured ? configured : DEFAULT_API_BASE_URL).replace(/\/+$/, '');
|
|
69
|
+
}
|
|
70
|
+
function tokenFromEnvironment() {
|
|
71
|
+
const token = process.env[TOKEN_ENV]?.trim();
|
|
72
|
+
return token ? token : null;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* `fetch` with the platform credential as the bearer token. Signs the user in first when there is
|
|
76
|
+
* no usable credential (an unattended run fails instead, asking for `idea1 login`), renews an
|
|
77
|
+
* expired access token, and on a 401 renews it and retries the request once. With `IDEA1_TOKEN`
|
|
78
|
+
* set, that token is sent as it is and a 401 is the caller's response.
|
|
79
|
+
*/
|
|
80
|
+
export async function authorizedFetch(url, init) {
|
|
81
|
+
const environmentToken = tokenFromEnvironment();
|
|
82
|
+
if (environmentToken !== null) {
|
|
83
|
+
return fetch(url, withBearer(init, environmentToken));
|
|
84
|
+
}
|
|
85
|
+
const credential = await serialized(() => usableCredential(null));
|
|
86
|
+
const response = await fetch(url, withBearer(init, credential.accessToken));
|
|
87
|
+
if (response.status !== 401) {
|
|
88
|
+
return response;
|
|
89
|
+
}
|
|
90
|
+
const renewed = await serialized(() => usableCredential(credential.accessToken));
|
|
91
|
+
return fetch(url, withBearer(init, renewed.accessToken));
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Sign in through the browser, replacing any stored credential for the platform.
|
|
95
|
+
*/
|
|
96
|
+
export async function login() {
|
|
97
|
+
if (tokenFromEnvironment() !== null) {
|
|
98
|
+
throw new Error(`${TOKEN_ENV} is set, and every platform call uses it: unset it to sign in with \`idea1 login\`.`);
|
|
99
|
+
}
|
|
100
|
+
await serialized(async () => {
|
|
101
|
+
await signIn((await readStoredCredential())?.clientId ?? null);
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Revoke the stored credential's refresh token and remove the credential from the credential
|
|
106
|
+
* store. Returns false when there was no credential to remove.
|
|
107
|
+
*/
|
|
108
|
+
export async function logout() {
|
|
109
|
+
return serialized(async () => {
|
|
110
|
+
const stored = await readStoredCredential();
|
|
111
|
+
if (stored === null) {
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
try {
|
|
115
|
+
await revoke(stored);
|
|
116
|
+
}
|
|
117
|
+
finally {
|
|
118
|
+
await deleteStoredCredential();
|
|
119
|
+
}
|
|
120
|
+
return true;
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Credential reads, renewals and sign-ins run one at a time in a process, so parallel platform
|
|
125
|
+
* calls renew or sign in once.
|
|
126
|
+
*/
|
|
127
|
+
let credentialQueue = Promise.resolve();
|
|
128
|
+
function serialized(work) {
|
|
129
|
+
const result = credentialQueue.then(work);
|
|
130
|
+
credentialQueue = result.catch(() => undefined);
|
|
131
|
+
return result;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* A credential whose access token is current, other than `rejectedAccessToken` (the one a 401 was
|
|
135
|
+
* answered with, unless another call or process has renewed it since). A credential the platform
|
|
136
|
+
* no longer honours is removed, and the user signs in again.
|
|
137
|
+
*/
|
|
138
|
+
async function usableCredential(rejectedAccessToken) {
|
|
139
|
+
const stored = await readStoredCredential();
|
|
140
|
+
if (stored === null) {
|
|
141
|
+
return signInWhenAttended(null);
|
|
142
|
+
}
|
|
143
|
+
const expired = Date.parse(stored.accessTokenExpiresAt) - EXPIRY_MARGIN_MS <= Date.now();
|
|
144
|
+
if (!expired && stored.accessToken !== rejectedAccessToken) {
|
|
145
|
+
return stored;
|
|
146
|
+
}
|
|
147
|
+
try {
|
|
148
|
+
return await refresh(stored);
|
|
149
|
+
}
|
|
150
|
+
catch (error) {
|
|
151
|
+
if (error instanceof OAuthError && (error.code === 'invalid_grant' || error.code === 'invalid_client')) {
|
|
152
|
+
await deleteStoredCredential();
|
|
153
|
+
return signInWhenAttended(error.code === 'invalid_grant' ? stored.clientId : null);
|
|
154
|
+
}
|
|
155
|
+
throw error;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
async function signInWhenAttended(clientId) {
|
|
159
|
+
if (isUnattended()) {
|
|
160
|
+
throw new Error(`Not signed in to idea1.ai (${apiBaseUrl()}). Run \`idea1 login\` to sign in.`);
|
|
161
|
+
}
|
|
162
|
+
logger.step(`Signing in to idea1.ai (${apiBaseUrl()})...`);
|
|
163
|
+
return signIn(clientId);
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Sign in through the browser with the given registered client, or a newly registered one, and
|
|
167
|
+
* store the credential: the authorization code flow with PKCE (S256) and `state`, redirected to a
|
|
168
|
+
* loopback server on a random port.
|
|
169
|
+
*
|
|
170
|
+
* The platform answers an authorization request it refuses outright, such as one for a client it
|
|
171
|
+
* no longer knows, with an error page instead of a redirect to the loopback server. So before the
|
|
172
|
+
* browser opens, the request for a stored client is sent once without following its redirect: a
|
|
173
|
+
* client the platform no longer knows is registered again, and any other refusal ends the sign-in.
|
|
174
|
+
*/
|
|
175
|
+
async function signIn(storedClientId) {
|
|
176
|
+
const metadata = await discoverAuthorizationServer();
|
|
177
|
+
const codeVerifier = base64Url(randomBytes(32));
|
|
178
|
+
const codeChallenge = base64Url(createHash('sha256').update(codeVerifier).digest());
|
|
179
|
+
const state = base64Url(randomBytes(16));
|
|
180
|
+
const callback = await listenForAuthorizationCallback(state);
|
|
181
|
+
try {
|
|
182
|
+
const authorizationUrlFor = (clientId) => {
|
|
183
|
+
const url = new URL(metadata.authorization_endpoint);
|
|
184
|
+
url.search = new URLSearchParams({
|
|
185
|
+
response_type: 'code',
|
|
186
|
+
client_id: clientId,
|
|
187
|
+
redirect_uri: callback.redirectUri,
|
|
188
|
+
scope: CLIENT_SCOPE,
|
|
189
|
+
state,
|
|
190
|
+
code_challenge: codeChallenge,
|
|
191
|
+
code_challenge_method: 'S256'
|
|
192
|
+
}).toString();
|
|
193
|
+
return url.toString();
|
|
194
|
+
};
|
|
195
|
+
let clientId = storedClientId ?? await registerClient(metadata);
|
|
196
|
+
if (storedClientId !== null) {
|
|
197
|
+
const refusal = await authorizationRefusal(authorizationUrlFor(storedClientId));
|
|
198
|
+
if (refusal?.code === 'invalid_client') {
|
|
199
|
+
clientId = await registerClient(metadata);
|
|
200
|
+
}
|
|
201
|
+
else if (refusal !== null) {
|
|
202
|
+
throw refusal;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
const [code] = await Promise.all([callback.code, openInBrowser(authorizationUrlFor(clientId))]);
|
|
206
|
+
const tokens = await postTokenRequest(metadata, {
|
|
207
|
+
grant_type: 'authorization_code',
|
|
208
|
+
code,
|
|
209
|
+
redirect_uri: callback.redirectUri,
|
|
210
|
+
client_id: clientId,
|
|
211
|
+
code_verifier: codeVerifier
|
|
212
|
+
});
|
|
213
|
+
if (tokens.refresh_token === null) {
|
|
214
|
+
throw new Error('idea1.ai issued no refresh token for the sign-in.');
|
|
215
|
+
}
|
|
216
|
+
return storeTokens(clientId, tokens, tokens.refresh_token);
|
|
217
|
+
}
|
|
218
|
+
finally {
|
|
219
|
+
callback.close();
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* The OAuth error the authorize endpoint answers a request with instead of redirecting it; null
|
|
224
|
+
* when it redirects. The endpoint validates the request and redirects to the consent page with no
|
|
225
|
+
* side effect, so the request is safe to send ahead of the browser.
|
|
226
|
+
*/
|
|
227
|
+
async function authorizationRefusal(authorizationUrl) {
|
|
228
|
+
const response = await fetch(authorizationUrl, { redirect: 'manual', headers: { Accept: 'application/json' } });
|
|
229
|
+
const text = await response.text();
|
|
230
|
+
const error = response.status >= 400 && response.status < 500 ? parseOAuthError(text) : null;
|
|
231
|
+
return error === null ? null : new OAuthError(error.error, error.error_description ?? null);
|
|
232
|
+
}
|
|
233
|
+
async function openInBrowser(url) {
|
|
234
|
+
logger.dim(`Sign in to idea1.ai in your browser. If it does not open, open this URL:\n${url}`);
|
|
235
|
+
try {
|
|
236
|
+
await openUrl(url);
|
|
237
|
+
}
|
|
238
|
+
catch (error) {
|
|
239
|
+
logger.warning(`Could not open the browser: ${error.message}`);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* A loopback HTTP server on a random port of 127.0.0.1 that receives the authorization redirect:
|
|
244
|
+
* `code` settles with the authorization code, the platform's error, or a timeout.
|
|
245
|
+
*/
|
|
246
|
+
async function listenForAuthorizationCallback(state) {
|
|
247
|
+
const server = createServer();
|
|
248
|
+
let timeout;
|
|
249
|
+
const code = new Promise((resolve, reject) => {
|
|
250
|
+
timeout = setTimeout(() => reject(new Error(`Sign-in did not finish in the browser within ${SIGN_IN_TIMEOUT_MS / 60_000} minutes.`)), SIGN_IN_TIMEOUT_MS);
|
|
251
|
+
server.on('request', (request, response) => {
|
|
252
|
+
const url = new URL(request.url ?? '/', 'http://127.0.0.1');
|
|
253
|
+
// Anything other than the redirect of this sign-in (a favicon, a stale tab) is not an answer.
|
|
254
|
+
if (url.pathname !== '/callback' || url.searchParams.get('state') !== state) {
|
|
255
|
+
response.writeHead(404).end();
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
const error = url.searchParams.get('error');
|
|
259
|
+
const authorizationCode = url.searchParams.get('code');
|
|
260
|
+
if (error !== null || !authorizationCode) {
|
|
261
|
+
writeCallbackPage(response, 'Sign-in did not complete. Return to the terminal for details; you can close this tab.');
|
|
262
|
+
reject(new OAuthError(error ?? 'invalid_request', url.searchParams.get('error_description')));
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
writeCallbackPage(response, 'Signed in to idea1.ai. You can close this tab and return to the terminal.');
|
|
266
|
+
resolve(authorizationCode);
|
|
267
|
+
});
|
|
268
|
+
});
|
|
269
|
+
await new Promise((resolve, reject) => {
|
|
270
|
+
server.once('error', reject);
|
|
271
|
+
server.listen(0, '127.0.0.1', () => resolve());
|
|
272
|
+
});
|
|
273
|
+
const { port } = server.address();
|
|
274
|
+
const redirectUri = new URL(REGISTERED_REDIRECT_URI);
|
|
275
|
+
redirectUri.port = String(port);
|
|
276
|
+
return {
|
|
277
|
+
redirectUri: redirectUri.toString(),
|
|
278
|
+
code,
|
|
279
|
+
close: () => {
|
|
280
|
+
clearTimeout(timeout);
|
|
281
|
+
server.close();
|
|
282
|
+
server.closeAllConnections();
|
|
283
|
+
}
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
function writeCallbackPage(response, message) {
|
|
287
|
+
response.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8', Connection: 'close' });
|
|
288
|
+
response.end('<!doctype html><html><head><meta charset="utf-8"><title>Idea1 CLI</title></head>' +
|
|
289
|
+
`<body style="font-family: system-ui, sans-serif; margin: 4rem; text-align: center"><p>${message}</p></body></html>`);
|
|
290
|
+
}
|
|
291
|
+
let authorizationServerMetadata = null;
|
|
292
|
+
function discoverAuthorizationServer() {
|
|
293
|
+
authorizationServerMetadata ??= readJson(fetch(`${apiBaseUrl()}/.well-known/oauth-authorization-server`, { headers: { Accept: 'application/json' } })).catch(error => {
|
|
294
|
+
authorizationServerMetadata = null;
|
|
295
|
+
throw error;
|
|
296
|
+
});
|
|
297
|
+
return authorizationServerMetadata;
|
|
298
|
+
}
|
|
299
|
+
async function registerClient(metadata) {
|
|
300
|
+
const registration = await readJson(fetch(metadata.registration_endpoint, {
|
|
301
|
+
method: 'POST',
|
|
302
|
+
headers: { Accept: 'application/json', 'Content-Type': 'application/json' },
|
|
303
|
+
body: JSON.stringify({
|
|
304
|
+
client_name: CLIENT_NAME,
|
|
305
|
+
redirect_uris: [REGISTERED_REDIRECT_URI],
|
|
306
|
+
grant_types: ['authorization_code', 'refresh_token'],
|
|
307
|
+
response_types: ['code'],
|
|
308
|
+
token_endpoint_auth_method: 'none',
|
|
309
|
+
scope: CLIENT_SCOPE
|
|
310
|
+
})
|
|
311
|
+
}));
|
|
312
|
+
return registration.client_id;
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Renew the access token. The platform does not rotate refresh tokens, so the stored one is kept
|
|
316
|
+
* unless the response carries another.
|
|
317
|
+
*/
|
|
318
|
+
async function refresh(stored) {
|
|
319
|
+
const tokens = await postTokenRequest(await discoverAuthorizationServer(), {
|
|
320
|
+
grant_type: 'refresh_token',
|
|
321
|
+
refresh_token: stored.refreshToken,
|
|
322
|
+
client_id: stored.clientId
|
|
323
|
+
});
|
|
324
|
+
return storeTokens(stored.clientId, tokens, tokens.refresh_token ?? stored.refreshToken);
|
|
325
|
+
}
|
|
326
|
+
async function revoke(stored) {
|
|
327
|
+
const metadata = await discoverAuthorizationServer();
|
|
328
|
+
await readSuccessBody(fetch(metadata.revocation_endpoint, {
|
|
329
|
+
method: 'POST',
|
|
330
|
+
headers: { Accept: 'application/json', 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
331
|
+
body: new URLSearchParams({ token: stored.refreshToken, token_type_hint: 'refresh_token', client_id: stored.clientId }).toString()
|
|
332
|
+
}));
|
|
333
|
+
}
|
|
334
|
+
function postTokenRequest(metadata, parameters) {
|
|
335
|
+
return readJson(fetch(metadata.token_endpoint, {
|
|
336
|
+
method: 'POST',
|
|
337
|
+
headers: { Accept: 'application/json', 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
338
|
+
body: new URLSearchParams(parameters).toString()
|
|
339
|
+
}));
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* The JSON body of an OAuth endpoint's success response.
|
|
343
|
+
*/
|
|
344
|
+
async function readJson(pending) {
|
|
345
|
+
return JSON.parse(await readSuccessBody(pending));
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* The body of an OAuth endpoint's success response; an error response throws OAuthError with the
|
|
349
|
+
* endpoint's `error` code, or an Error naming the HTTP status when it has none.
|
|
350
|
+
*/
|
|
351
|
+
async function readSuccessBody(pending) {
|
|
352
|
+
const response = await pending;
|
|
353
|
+
const text = await response.text();
|
|
354
|
+
if (response.ok) {
|
|
355
|
+
return text;
|
|
356
|
+
}
|
|
357
|
+
const error = parseOAuthError(text);
|
|
358
|
+
if (error !== null) {
|
|
359
|
+
throw new OAuthError(error.error, error.error_description ?? null);
|
|
360
|
+
}
|
|
361
|
+
throw new Error(`idea1.ai refused ${response.url} (${response.status} ${response.statusText})${text.trim() ? `: ${text.trim().slice(0, 500)}` : ''}`);
|
|
362
|
+
}
|
|
363
|
+
function parseOAuthError(text) {
|
|
364
|
+
try {
|
|
365
|
+
const body = JSON.parse(text);
|
|
366
|
+
return typeof body.error === 'string' ? { error: body.error, error_description: body.error_description } : null;
|
|
367
|
+
}
|
|
368
|
+
catch {
|
|
369
|
+
return null;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
async function storeTokens(clientId, tokens, refreshToken) {
|
|
373
|
+
const credential = {
|
|
374
|
+
clientId,
|
|
375
|
+
refreshToken,
|
|
376
|
+
accessToken: tokens.access_token,
|
|
377
|
+
accessTokenExpiresAt: new Date(Date.now() + tokens.expires_in * 1000).toISOString()
|
|
378
|
+
};
|
|
379
|
+
await writeStoredCredential(credential);
|
|
380
|
+
return credential;
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* The credential's run of entries: its JSON in pieces, the first under the API base URL as the
|
|
384
|
+
* account and the rest under the URL suffixed `#2`, `#3`, and so on. Entries are written one at a
|
|
385
|
+
* time, so a run read mid-write, or left by a write that was cut short, mixes entries of different
|
|
386
|
+
* writes: it is read again a few times, and if it stays mixed there is no credential and the user
|
|
387
|
+
* signs in again. An entry of plain JSON is a whole credential on its own, and a stored text that
|
|
388
|
+
* is not JSON is no credential, since its parse error would quote the store's content.
|
|
389
|
+
*/
|
|
390
|
+
async function readStoredCredential() {
|
|
391
|
+
for (let attempt = 1; attempt <= STORED_CREDENTIAL_READ_ATTEMPTS; attempt++) {
|
|
392
|
+
const first = await credentialStoreEntry(1).getPassword();
|
|
393
|
+
if (first === null) {
|
|
394
|
+
return null;
|
|
395
|
+
}
|
|
396
|
+
if (first.startsWith('{')) {
|
|
397
|
+
return parseStoredCredential(first);
|
|
398
|
+
}
|
|
399
|
+
const json = await readStoredCredentialRun(first);
|
|
400
|
+
if (json !== null) {
|
|
401
|
+
return parseStoredCredential(json);
|
|
402
|
+
}
|
|
403
|
+
await delay(STORED_CREDENTIAL_READ_RETRY_MS);
|
|
404
|
+
}
|
|
405
|
+
return null;
|
|
406
|
+
}
|
|
407
|
+
/** The JSON of the run that `first` starts, or null when its entries are not all of one write. */
|
|
408
|
+
async function readStoredCredentialRun(first) {
|
|
409
|
+
const firstPiece = parseCredentialPiece(first);
|
|
410
|
+
if (firstPiece === null) {
|
|
411
|
+
return null;
|
|
412
|
+
}
|
|
413
|
+
const texts = [firstPiece.text];
|
|
414
|
+
for (let index = 2; index <= firstPiece.count; index++) {
|
|
415
|
+
const entry = await credentialStoreEntry(index).getPassword();
|
|
416
|
+
const piece = entry === null ? null : parseCredentialPiece(entry);
|
|
417
|
+
if (piece === null || piece.writeId !== firstPiece.writeId || piece.count !== firstPiece.count) {
|
|
418
|
+
return null;
|
|
419
|
+
}
|
|
420
|
+
texts.push(piece.text);
|
|
421
|
+
}
|
|
422
|
+
return texts.join('');
|
|
423
|
+
}
|
|
424
|
+
function parseStoredCredential(json) {
|
|
425
|
+
try {
|
|
426
|
+
return JSON.parse(json);
|
|
427
|
+
}
|
|
428
|
+
catch (error) {
|
|
429
|
+
if (error instanceof SyntaxError) {
|
|
430
|
+
return null;
|
|
431
|
+
}
|
|
432
|
+
throw error;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
function parseCredentialPiece(entry) {
|
|
436
|
+
const match = CREDENTIAL_PIECE_PATTERN.exec(entry);
|
|
437
|
+
return match === null ? null : { writeId: match[1], count: Number(match[2]), text: match[3] };
|
|
438
|
+
}
|
|
439
|
+
async function writeStoredCredential(credential) {
|
|
440
|
+
const json = JSON.stringify(credential);
|
|
441
|
+
const texts = [];
|
|
442
|
+
for (let start = 0; start < json.length;) {
|
|
443
|
+
let end = Math.min(start + CREDENTIAL_PIECE_TEXT_LENGTH, json.length);
|
|
444
|
+
// A surrogate pair stays in one piece: the store cannot hold half of one.
|
|
445
|
+
if (end < json.length && json.charCodeAt(end - 1) >= 0xd800 && json.charCodeAt(end - 1) <= 0xdbff) {
|
|
446
|
+
end--;
|
|
447
|
+
}
|
|
448
|
+
texts.push(json.slice(start, end));
|
|
449
|
+
start = end;
|
|
450
|
+
}
|
|
451
|
+
const writeId = randomBytes(4).toString('hex');
|
|
452
|
+
for (const [offset, text] of texts.entries()) {
|
|
453
|
+
await credentialStoreEntry(offset + 1).setPassword(`${writeId}:${texts.length}:${text}`);
|
|
454
|
+
}
|
|
455
|
+
await deleteStoredCredentialFrom(texts.length + 1);
|
|
456
|
+
}
|
|
457
|
+
async function deleteStoredCredential() {
|
|
458
|
+
await deleteStoredCredentialFrom(1);
|
|
459
|
+
}
|
|
460
|
+
/** Removes the entries of the run from `index` on, such as those a shorter credential leaves behind. */
|
|
461
|
+
async function deleteStoredCredentialFrom(index) {
|
|
462
|
+
while (await credentialStoreEntry(index).deletePassword()) {
|
|
463
|
+
index++;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
function credentialStoreEntry(index) {
|
|
467
|
+
const account = index === 1 ? apiBaseUrl() : `${apiBaseUrl()}#${index}`;
|
|
468
|
+
return new AsyncEntry(CREDENTIAL_STORE_SERVICE, account);
|
|
469
|
+
}
|
|
470
|
+
function withBearer(init, token) {
|
|
471
|
+
return { ...init, headers: { ...init.headers, Authorization: `Bearer ${token}` } };
|
|
472
|
+
}
|
|
473
|
+
function base64Url(bytes) {
|
|
474
|
+
return bytes.toString('base64url');
|
|
475
|
+
}
|
|
476
|
+
//# sourceMappingURL=platform-auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform-auth.js","sourceRoot":"","sources":["../../src/services/platform-auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,37 +1,89 @@
|
|
|
1
|
-
import type { DevWorkflowType } from '../workflow/data/workflow-context.js';
|
|
1
|
+
import type { DevWorkflowType, WorkflowContext } from '../workflow/data/workflow-context.js';
|
|
2
2
|
import type { ProjectItemSummary } from '../workflow/data/project-item.js';
|
|
3
3
|
import type { TeamMember } from '../workflow/data/team-member.js';
|
|
4
4
|
import type { ClaudeRunOptions } from './claude.js';
|
|
5
5
|
/**
|
|
6
6
|
* The CLI's access to the Idea1 cloud platform (app.idea1.ai / api.idea1.ai): reading a project
|
|
7
7
|
* item's summary (by item or by branch), recording the item's workflow context, setting its workflow
|
|
8
|
-
* status (with the teammate it is assigned to),
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
* status (with the teammate it is assigned to), transitioning an item on the platform and approving
|
|
9
|
+
* a branch's pull request (the stage-1 merges the platform performs), approving a release and
|
|
10
|
+
* committing its version bump (the stage-2 work the platform performs), creating items, listing the team's Projects and
|
|
11
|
+
* members, deriving a branch name from an item, and reading who is signed in. Callers use
|
|
12
|
+
* `platform.someFunction()` and know nothing about the transport.
|
|
11
13
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* `src/prompts/platform-prompts.ts`; this module owns the output schemas their answers are read with.
|
|
14
|
+
* The transport is the platform's REST API, authorized with the user's OAuth credential or
|
|
15
|
+
* `IDEA1_TOKEN` (see `platform-auth.ts`), on the team that credential is bound to. Responses are the
|
|
16
|
+
* platform's `ApiDataResponse` envelope; a refused request surfaces as an Error carrying the
|
|
17
|
+
* platform's status and message. Claude is used only to name branches, on PLATFORM_CALL_RUN_OPTIONS.
|
|
17
18
|
*/
|
|
18
19
|
/**
|
|
19
|
-
* Model and effort for
|
|
20
|
-
*
|
|
20
|
+
* Model and effort for the Claude run that names a branch: a small, fast model at medium effort is
|
|
21
|
+
* all a one-line answer from a description needs, and pinning it keeps the run consistent and cheap.
|
|
21
22
|
*/
|
|
22
23
|
export declare const PLATFORM_CALL_RUN_OPTIONS: Required<ClaudeRunOptions>;
|
|
24
|
+
/**
|
|
25
|
+
* Who the platform credential signs in as: the user's email address and the team its calls work on.
|
|
26
|
+
*/
|
|
27
|
+
export interface SignedInUser {
|
|
28
|
+
emailAddress: string;
|
|
29
|
+
teamName: string;
|
|
30
|
+
}
|
|
23
31
|
/**
|
|
24
32
|
* Record workflow context updates on an idea1.ai project item directly, with no side effects on the
|
|
25
33
|
* platform: the CLI has already run the transition's work locally. The item must be under workflow
|
|
26
34
|
* management (have a workflow context); the workflow engine is the only caller, as the persist step
|
|
27
35
|
* of a transition. `assignedToEmail` names the team member the item is assigned to along with the
|
|
28
|
-
* status; null leaves the assignment as it is.
|
|
29
|
-
*
|
|
30
|
-
* TODO: Direct workflow-context updates move from the update_item MCP tool to an authenticated
|
|
31
|
-
* platform API call; the CLI will authenticate a user and call the API for direct integrations
|
|
32
|
-
* like this, and MCP tools will be only operations that agents should run.
|
|
36
|
+
* status; null leaves the assignment as it is. Returns false, with a warning, when the platform did
|
|
37
|
+
* not record it.
|
|
33
38
|
*/
|
|
34
39
|
export declare function setWorkflowStatus(itemUrl: string, status: string, pullRequestUrl: string | null, assignedToEmail: string | null): Promise<boolean>;
|
|
40
|
+
/**
|
|
41
|
+
* The platform's `WorkflowTransitionResponse`: the item's workflow context after the transition, and
|
|
42
|
+
* what was done.
|
|
43
|
+
*/
|
|
44
|
+
export interface WorkflowTransitionResult {
|
|
45
|
+
workflowContext: WorkflowContext;
|
|
46
|
+
message: string;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Move a project item into `targetStatus` on the platform, which runs the side effects of every
|
|
50
|
+
* state it enters and records each one: entering Approved and Merged merges the item's pull request
|
|
51
|
+
* as the Idea1 GitHub App, once the signed-in user's approval is recorded on it. `expectedStatus` is
|
|
52
|
+
* the status the item has as far as the CLI knows; the platform refuses the transition when the item
|
|
53
|
+
* has moved since, so it never runs twice.
|
|
54
|
+
*/
|
|
55
|
+
export declare function transitionWorkflow(itemUrl: string, expectedStatus: string, targetStatus: string): Promise<WorkflowTransitionResult>;
|
|
56
|
+
/**
|
|
57
|
+
* Approve the open pull request of a branch no project item carries: the platform records the
|
|
58
|
+
* signed-in user's approval on it and merges it as the Idea1 GitHub App. Returns what was done.
|
|
59
|
+
*/
|
|
60
|
+
export declare function approvePullRequest(repositoryFullName: string, branchName: string): Promise<string>;
|
|
61
|
+
/**
|
|
62
|
+
* Approve the open release PR from a release branch (the base, hotfix or content release branch):
|
|
63
|
+
* the platform checks the signed-in user is its assignee and holds the release role, brings its
|
|
64
|
+
* change list up to date, records the approval on it and merges it as the Idea1 GitHub App. Returns
|
|
65
|
+
* what was done.
|
|
66
|
+
*/
|
|
67
|
+
export declare function approveRelease(repositoryFullName: string, branchName: string): Promise<string>;
|
|
68
|
+
/** A version file of a version bump with its whole new content. */
|
|
69
|
+
export interface VersionFileContent {
|
|
70
|
+
path: string;
|
|
71
|
+
content: string;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* The platform's `ReleaseVersionBumpResponse`.
|
|
75
|
+
*/
|
|
76
|
+
interface ReleaseVersionBumpResponse {
|
|
77
|
+
commitSha: string;
|
|
78
|
+
subject: string;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Have the platform commit a release's version bump onto its release branch as the Idea1 GitHub
|
|
82
|
+
* App, for a releaser who cannot push to the branch: the new content of each version file, made
|
|
83
|
+
* against the branch at `expectedHeadSha`. The platform accepts only version edits of the declared
|
|
84
|
+
* packages' version files. Returns the commit.
|
|
85
|
+
*/
|
|
86
|
+
export declare function commitVersionBump(repositoryFullName: string, branchName: string, expectedHeadSha: string, files: readonly VersionFileContent[]): Promise<ReleaseVersionBumpResponse>;
|
|
35
87
|
/**
|
|
36
88
|
* The summary of the project item a branch implements: null for a branch outside workflow
|
|
37
89
|
* management. The repository is always named; nothing defaults it.
|
|
@@ -67,7 +119,7 @@ export interface UpsertProjectItemWorkflowContextInput {
|
|
|
67
119
|
*/
|
|
68
120
|
export declare function upsertProjectItemWorkflowContext(input: UpsertProjectItemWorkflowContextInput): Promise<ProjectItemSummary>;
|
|
69
121
|
/**
|
|
70
|
-
* Generate a branch name from a project item description
|
|
122
|
+
* Generate a branch name from a project item's description.
|
|
71
123
|
*/
|
|
72
124
|
export declare function generateBranchName(itemUrl: string): Promise<string>;
|
|
73
125
|
/**
|
|
@@ -86,9 +138,14 @@ export declare function listTeamMembers(): Promise<TeamMember[]>;
|
|
|
86
138
|
*/
|
|
87
139
|
export declare function resolveTeammate(identity: string): Promise<TeamMember>;
|
|
88
140
|
/**
|
|
89
|
-
* Create a new idea1 project item with the given title in the named Project.
|
|
141
|
+
* Create a new idea1 project item with the given title in the named live Project.
|
|
90
142
|
* The item is created with description `# <title>`.
|
|
91
143
|
* Returns the created item's URL.
|
|
92
144
|
*/
|
|
93
145
|
export declare function createProjectItem(title: string, projectName: string): Promise<string>;
|
|
146
|
+
/**
|
|
147
|
+
* The user the platform credential signs in as, and the team its calls work on.
|
|
148
|
+
*/
|
|
149
|
+
export declare function getSignedInUser(): Promise<SignedInUser>;
|
|
150
|
+
export {};
|
|
94
151
|
//# sourceMappingURL=platform.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../../src/services/platform.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;
|
|
1
|
+
{"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../../src/services/platform.ts"],"names":[],"mappings":"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"}
|