@idea1/cli 1.10.4 → 1.11.0
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 +29 -6
- package/dist/commands/help.d.ts.map +1 -1
- package/dist/commands/help.js +14 -2
- 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 +2 -1
- package/dist/commands/release.d.ts.map +1 -1
- package/dist/commands/release.js +2 -1
- 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 +10 -3
- package/dist/lib/settings.d.ts.map +1 -1
- package/dist/lib/settings.js +13 -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/platform-auth.d.ts +43 -0
- package/dist/services/platform-auth.d.ts.map +1 -0
- package/dist/services/platform-auth.js +380 -0
- package/dist/services/platform-auth.js.map +1 -0
- package/dist/services/platform.d.ts +23 -16
- package/dist/services/platform.d.ts.map +1 -1
- package/dist/services/platform.js +188 -190
- 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 +16 -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/branch-setup.d.ts +1 -1
- package/dist/workflow/engine/branch-setup.js +1 -1
- package/dist/workflow/engine/release-engine.d.ts +6 -2
- package/dist/workflow/engine/release-engine.d.ts.map +1 -1
- package/dist/workflow/engine/release-engine.js +16 -5
- package/dist/workflow/engine/release-engine.js.map +1 -1
- package/package.json +2 -1
|
@@ -1,33 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
pullRequestUrl: string | null;
|
|
6
|
-
assignedToEmail: string | null;
|
|
7
|
-
}>;
|
|
8
|
-
export declare const listTeamMembersPrompt: import("../services/template-renderer.js").RenderTemplate<Record<string, never>>;
|
|
9
|
-
export declare const getProjectItemSummaryForBranchPrompt: import("../services/template-renderer.js").RenderTemplate<{
|
|
10
|
-
repositoryFullName: string;
|
|
11
|
-
branchName: string;
|
|
12
|
-
}>;
|
|
13
|
-
export declare const getProjectItemSummaryPrompt: import("../services/template-renderer.js").RenderTemplate<{
|
|
14
|
-
projectItemUrl: string;
|
|
15
|
-
}>;
|
|
16
|
-
export declare const upsertProjectItemWorkflowContextPrompt: import("../services/template-renderer.js").RenderTemplate<{
|
|
17
|
-
projectItemUrl: string;
|
|
18
|
-
repositoryFullName: string;
|
|
19
|
-
branchName: string;
|
|
20
|
-
baseBranch: string;
|
|
21
|
-
devWorkflowType: DevWorkflowType;
|
|
22
|
-
stackBranch: string | null;
|
|
23
|
-
integrationBranch: string | null;
|
|
24
|
-
}>;
|
|
1
|
+
/**
|
|
2
|
+
* The prompt the platform service runs to name a branch after a project item: a text-only task on
|
|
3
|
+
* the item's description, which the service reads from the platform and puts in the prompt.
|
|
4
|
+
*/
|
|
25
5
|
export declare const generateBranchNamePrompt: import("../services/template-renderer.js").RenderTemplate<{
|
|
26
|
-
|
|
27
|
-
}>;
|
|
28
|
-
export declare const listProjectsPrompt: import("../services/template-renderer.js").RenderTemplate<Record<string, never>>;
|
|
29
|
-
export declare const createProjectItemPrompt: import("../services/template-renderer.js").RenderTemplate<{
|
|
30
|
-
title: string;
|
|
31
|
-
projectName: string;
|
|
6
|
+
description: string;
|
|
32
7
|
}>;
|
|
33
8
|
//# sourceMappingURL=platform-prompts.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"platform-prompts.d.ts","sourceRoot":"","sources":["../../src/prompts/platform-prompts.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"platform-prompts.d.ts","sourceRoot":"","sources":["../../src/prompts/platform-prompts.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,eAAO,MAAM,wBAAwB;iBAAkC,MAAM;EAK5E,CAAC"}
|
|
@@ -1,49 +1,10 @@
|
|
|
1
1
|
import { compileTemplate } from '../services/template-renderer.js';
|
|
2
2
|
/**
|
|
3
|
-
* The
|
|
4
|
-
*
|
|
5
|
-
* with belong to the platform service; the prompts only name the tool, its parameters and where
|
|
6
|
-
* the answer goes.
|
|
3
|
+
* The prompt the platform service runs to name a branch after a project item: a text-only task on
|
|
4
|
+
* the item's description, which the service reads from the platform and puts in the prompt.
|
|
7
5
|
*/
|
|
8
|
-
|
|
9
|
-
* Where a call that returns a project item summary puts the tool's result.
|
|
10
|
-
*/
|
|
11
|
-
const PROJECT_ITEM_SUMMARY_OUTPUT_INSTRUCTIONS = 'Copy the tool\'s result into the "projectItemSummary" field exactly as returned: url, externalId, title, epicId, ' +
|
|
12
|
-
'completionDate, legacyWorkflowStatus, projectId (null when the item is out of scope), assignedToUserId (null when ' +
|
|
13
|
-
'unassigned) and "workflowContext" with its workflowStatus, codingAgentUrl, ' +
|
|
14
|
-
'pullRequestUrl, repositoryFullName, branchName, baseBranch, devWorkflowType, stackBranch, integrationBranch and ' +
|
|
15
|
-
'branchState (the number the tool returned), or null when the result\'s workflowContext is null. Put null in ' +
|
|
16
|
-
'"error". If the tool returns an error, put its message verbatim in "error" and null in "projectItemSummary".';
|
|
17
|
-
// TODO: This direct workflow-context update moves out of the update_item MCP tool into an authenticated platform
|
|
18
|
-
// API call. The CLI will authenticate a user and call the API for direct integrations like this; MCP tools will then
|
|
19
|
-
// be only operations that agents should run.
|
|
20
|
-
export const setWorkflowStatusPrompt = compileTemplate('Record the workflow status of {{projectItemUrl}} as "{{workflowStatus}}" by calling the update_item MCP tool with ' +
|
|
21
|
-
'itemReference "{{projectItemUrl}}", workflowStatus "{{workflowStatus}}"' +
|
|
22
|
-
'{{#if pullRequestUrl}}, pullRequestUrl "{{pullRequestUrl}}"{{/if}}' +
|
|
23
|
-
'{{#if assignedToEmail}}, assignedToEmail "{{assignedToEmail}}"{{/if}}' +
|
|
24
|
-
' and no other fields. ' +
|
|
25
|
-
'Put "done" in the "result" field on success, or an explanation in the "error" field on failure.');
|
|
26
|
-
export const listTeamMembersPrompt = compileTemplate('List the team\'s members using the list_team_members MCP tool. Copy the tool\'s result into the "members" field ' +
|
|
27
|
-
'exactly as returned: each member\'s userId, email, role and gitHubUsername (null when the member has no linked ' +
|
|
28
|
-
'GitHub account), in the order returned.');
|
|
29
|
-
export const getProjectItemSummaryForBranchPrompt = compileTemplate('Call the get_item_summary_for_branch MCP tool with repositoryFullName "{{repositoryFullName}}" and branchName "{{branchName}}". ' +
|
|
30
|
-
PROJECT_ITEM_SUMMARY_OUTPUT_INSTRUCTIONS);
|
|
31
|
-
export const getProjectItemSummaryPrompt = compileTemplate('Call the get_item_summary MCP tool with itemReference "{{projectItemUrl}}". ' +
|
|
32
|
-
PROJECT_ITEM_SUMMARY_OUTPUT_INSTRUCTIONS);
|
|
33
|
-
export const upsertProjectItemWorkflowContextPrompt = compileTemplate('Call the upsert_item_workflow_context MCP tool with itemReference "{{projectItemUrl}}", ' +
|
|
34
|
-
'repositoryFullName "{{repositoryFullName}}", branchName "{{branchName}}", baseBranch "{{baseBranch}}", ' +
|
|
35
|
-
'devWorkflowType "{{devWorkflowType}}"' +
|
|
36
|
-
'{{#if stackBranch}}, stackBranch "{{stackBranch}}"{{/if}}' +
|
|
37
|
-
'{{#if integrationBranch}}, integrationBranch "{{integrationBranch}}"{{/if}}. ' +
|
|
38
|
-
'Pass only these parameters. ' +
|
|
39
|
-
PROJECT_ITEM_SUMMARY_OUTPUT_INSTRUCTIONS);
|
|
40
|
-
export const generateBranchNamePrompt = compileTemplate('Get the description of {{projectItemUrl}} with the get_item_description MCP tool and generate a git branch name based on the description. ' +
|
|
6
|
+
export const generateBranchNamePrompt = compileTemplate('Generate a git branch name for the project item described below. ' +
|
|
41
7
|
'Don\'t use any branch name prefix or folder structure, just a one part branch name. Put the branch name in the "result" field. ' +
|
|
42
|
-
'If you cannot generate a branch name, put an explanation in the "error" field
|
|
43
|
-
|
|
44
|
-
'Put the names of the projects whose status is Live in the "projects" field, in the order returned.');
|
|
45
|
-
export const createProjectItemPrompt = compileTemplate('Create a new idea1 project item using the create_item MCP tool with description "# {{title}}" in the project named ' +
|
|
46
|
-
'"{{projectName}}" (pass projectName "{{projectName}}"). Put the created item\'s URL (the create_item result\'s ' +
|
|
47
|
-
'CreatedItemUrl) in the "projectItemUrl" field and null in the "error" field. If the tool returns an error, put the ' +
|
|
48
|
-
'error message in the "error" field and an empty string in the "projectItemUrl" field.');
|
|
8
|
+
'If you cannot generate a branch name, put an explanation in the "error" field.\n\n' +
|
|
9
|
+
'Project item description:\n\n{{description}}');
|
|
49
10
|
//# sourceMappingURL=platform-prompts.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"platform-prompts.js","sourceRoot":"","sources":["../../src/prompts/platform-prompts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;
|
|
1
|
+
{"version":3,"file":"platform-prompts.js","sourceRoot":"","sources":["../../src/prompts/platform-prompts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAEnE;;;GAGG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,eAAe,CACrD,mEAAmE;IACnE,iIAAiI;IACjI,oFAAoF;IACpF,8CAA8C,CAC/C,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The CLI's OAuth client of the Idea1 platform: it holds the credential every platform call is
|
|
3
|
+
* authorized with, and signs the user in and out.
|
|
4
|
+
*
|
|
5
|
+
* The CLI is a public client (no secret) that registers itself dynamically with the platform's
|
|
6
|
+
* authorization server, discovered at `{apiBase}/.well-known/oauth-authorization-server`. Signing in
|
|
7
|
+
* is the authorization code flow with PKCE: the browser opens the platform's consent page, where the
|
|
8
|
+
* user picks the team the grant is bound to, and the platform redirects back to a loopback server
|
|
9
|
+
* the CLI runs on a random port of 127.0.0.1 (the registered `http://127.0.0.1/callback` matches on
|
|
10
|
+
* any port). The resulting team-bound access token is short-lived; the refresh token renews it.
|
|
11
|
+
*
|
|
12
|
+
* The credential lives in the operating system's credential store (macOS Keychain, Windows
|
|
13
|
+
* Credential Manager, Secret Service on Linux) under the service `idea1-cli` and the API base URL as
|
|
14
|
+
* the account, as the JSON of a `StoredCredential`. Parallel CLI processes share it: the platform
|
|
15
|
+
* does not rotate refresh tokens, so concurrent refreshes all stay valid and the last write wins.
|
|
16
|
+
*
|
|
17
|
+
* `IDEA1_TOKEN`, when set, is the bearer token of every call instead (a team API client's token in
|
|
18
|
+
* CI, or a test's): nothing is read from or written to the credential store, and nothing is
|
|
19
|
+
* refreshed. `IDEA1_API_BASE_URL` points the CLI at another platform than https://api.idea1.ai.
|
|
20
|
+
*/
|
|
21
|
+
export declare const API_BASE_URL_ENV = "IDEA1_API_BASE_URL";
|
|
22
|
+
export declare const TOKEN_ENV = "IDEA1_TOKEN";
|
|
23
|
+
/**
|
|
24
|
+
* The base URL of the platform's API, without a trailing slash.
|
|
25
|
+
*/
|
|
26
|
+
export declare function apiBaseUrl(): string;
|
|
27
|
+
/**
|
|
28
|
+
* `fetch` with the platform credential as the bearer token. Signs the user in first when there is
|
|
29
|
+
* no usable credential (an unattended run fails instead, asking for `idea1 login`), renews an
|
|
30
|
+
* expired access token, and on a 401 renews it and retries the request once. With `IDEA1_TOKEN`
|
|
31
|
+
* set, that token is sent as it is and a 401 is the caller's response.
|
|
32
|
+
*/
|
|
33
|
+
export declare function authorizedFetch(url: string, init: RequestInit): Promise<Response>;
|
|
34
|
+
/**
|
|
35
|
+
* Sign in through the browser, replacing any stored credential for the platform.
|
|
36
|
+
*/
|
|
37
|
+
export declare function login(): Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* Revoke the stored credential's refresh token and remove the credential from the credential
|
|
40
|
+
* store. Returns false when there was no credential to remove.
|
|
41
|
+
*/
|
|
42
|
+
export declare function logout(): Promise<boolean>;
|
|
43
|
+
//# sourceMappingURL=platform-auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform-auth.d.ts","sourceRoot":"","sources":["../../src/services/platform-auth.ts"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,eAAO,MAAM,gBAAgB,uBAAuB,CAAC;AACrD,eAAO,MAAM,SAAS,gBAAgB,CAAC;AA0DvC;;GAEG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAGnC;AAOD;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,CAcvF;AAED;;GAEG;AACH,wBAAsB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAQ3C;AAED;;;GAGG;AACH,wBAAsB,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,CAa/C"}
|
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
import { createHash, randomBytes } from 'crypto';
|
|
2
|
+
import { createServer } from 'http';
|
|
3
|
+
import { AsyncEntry } from '@napi-rs/keyring';
|
|
4
|
+
import { logger } from '../lib/logger.js';
|
|
5
|
+
import { isUnattended } from '../lib/prompt.js';
|
|
6
|
+
import { openUrl } from './os-launcher.js';
|
|
7
|
+
/**
|
|
8
|
+
* The CLI's OAuth client of the Idea1 platform: it holds the credential every platform call is
|
|
9
|
+
* authorized with, and signs the user in and out.
|
|
10
|
+
*
|
|
11
|
+
* The CLI is a public client (no secret) that registers itself dynamically with the platform's
|
|
12
|
+
* authorization server, discovered at `{apiBase}/.well-known/oauth-authorization-server`. Signing in
|
|
13
|
+
* is the authorization code flow with PKCE: the browser opens the platform's consent page, where the
|
|
14
|
+
* user picks the team the grant is bound to, and the platform redirects back to a loopback server
|
|
15
|
+
* the CLI runs on a random port of 127.0.0.1 (the registered `http://127.0.0.1/callback` matches on
|
|
16
|
+
* any port). The resulting team-bound access token is short-lived; the refresh token renews it.
|
|
17
|
+
*
|
|
18
|
+
* The credential lives in the operating system's credential store (macOS Keychain, Windows
|
|
19
|
+
* Credential Manager, Secret Service on Linux) under the service `idea1-cli` and the API base URL as
|
|
20
|
+
* the account, as the JSON of a `StoredCredential`. Parallel CLI processes share it: the platform
|
|
21
|
+
* does not rotate refresh tokens, so concurrent refreshes all stay valid and the last write wins.
|
|
22
|
+
*
|
|
23
|
+
* `IDEA1_TOKEN`, when set, is the bearer token of every call instead (a team API client's token in
|
|
24
|
+
* CI, or a test's): nothing is read from or written to the credential store, and nothing is
|
|
25
|
+
* refreshed. `IDEA1_API_BASE_URL` points the CLI at another platform than https://api.idea1.ai.
|
|
26
|
+
*/
|
|
27
|
+
export const API_BASE_URL_ENV = 'IDEA1_API_BASE_URL';
|
|
28
|
+
export const TOKEN_ENV = 'IDEA1_TOKEN';
|
|
29
|
+
const DEFAULT_API_BASE_URL = 'https://api.idea1.ai';
|
|
30
|
+
const CREDENTIAL_STORE_SERVICE = 'idea1-cli';
|
|
31
|
+
const CLIENT_NAME = 'Idea1 CLI';
|
|
32
|
+
const CLIENT_SCOPE = 'team:read projects:read projects:write';
|
|
33
|
+
/** The redirect URI the client registers; the loopback server listens on a random port of it. */
|
|
34
|
+
const REGISTERED_REDIRECT_URI = 'http://127.0.0.1/callback';
|
|
35
|
+
const SIGN_IN_TIMEOUT_MS = 5 * 60 * 1000;
|
|
36
|
+
/** An access token this close to its expiry is renewed before it is used. */
|
|
37
|
+
const EXPIRY_MARGIN_MS = 60 * 1000;
|
|
38
|
+
/**
|
|
39
|
+
* An OAuth error response (RFC 6749 §5.2), from an endpoint or from the authorization redirect.
|
|
40
|
+
*/
|
|
41
|
+
class OAuthError extends Error {
|
|
42
|
+
code;
|
|
43
|
+
constructor(code, description) {
|
|
44
|
+
super(description === null ? `idea1.ai sign-in failed: ${code}` : `idea1.ai sign-in failed: ${code} (${description})`);
|
|
45
|
+
this.code = code;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* The base URL of the platform's API, without a trailing slash.
|
|
50
|
+
*/
|
|
51
|
+
export function apiBaseUrl() {
|
|
52
|
+
const configured = process.env[API_BASE_URL_ENV]?.trim();
|
|
53
|
+
return (configured ? configured : DEFAULT_API_BASE_URL).replace(/\/+$/, '');
|
|
54
|
+
}
|
|
55
|
+
function tokenFromEnvironment() {
|
|
56
|
+
const token = process.env[TOKEN_ENV]?.trim();
|
|
57
|
+
return token ? token : null;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* `fetch` with the platform credential as the bearer token. Signs the user in first when there is
|
|
61
|
+
* no usable credential (an unattended run fails instead, asking for `idea1 login`), renews an
|
|
62
|
+
* expired access token, and on a 401 renews it and retries the request once. With `IDEA1_TOKEN`
|
|
63
|
+
* set, that token is sent as it is and a 401 is the caller's response.
|
|
64
|
+
*/
|
|
65
|
+
export async function authorizedFetch(url, init) {
|
|
66
|
+
const environmentToken = tokenFromEnvironment();
|
|
67
|
+
if (environmentToken !== null) {
|
|
68
|
+
return fetch(url, withBearer(init, environmentToken));
|
|
69
|
+
}
|
|
70
|
+
const credential = await serialized(() => usableCredential(null));
|
|
71
|
+
const response = await fetch(url, withBearer(init, credential.accessToken));
|
|
72
|
+
if (response.status !== 401) {
|
|
73
|
+
return response;
|
|
74
|
+
}
|
|
75
|
+
const renewed = await serialized(() => usableCredential(credential.accessToken));
|
|
76
|
+
return fetch(url, withBearer(init, renewed.accessToken));
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Sign in through the browser, replacing any stored credential for the platform.
|
|
80
|
+
*/
|
|
81
|
+
export async function login() {
|
|
82
|
+
if (tokenFromEnvironment() !== null) {
|
|
83
|
+
throw new Error(`${TOKEN_ENV} is set, and every platform call uses it: unset it to sign in with \`idea1 login\`.`);
|
|
84
|
+
}
|
|
85
|
+
await serialized(async () => {
|
|
86
|
+
await signIn((await readStoredCredential())?.clientId ?? null);
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Revoke the stored credential's refresh token and remove the credential from the credential
|
|
91
|
+
* store. Returns false when there was no credential to remove.
|
|
92
|
+
*/
|
|
93
|
+
export async function logout() {
|
|
94
|
+
return serialized(async () => {
|
|
95
|
+
const stored = await readStoredCredential();
|
|
96
|
+
if (stored === null) {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
try {
|
|
100
|
+
await revoke(stored);
|
|
101
|
+
}
|
|
102
|
+
finally {
|
|
103
|
+
await credentialStoreEntry().deletePassword();
|
|
104
|
+
}
|
|
105
|
+
return true;
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Credential reads, renewals and sign-ins run one at a time in a process, so parallel platform
|
|
110
|
+
* calls renew or sign in once.
|
|
111
|
+
*/
|
|
112
|
+
let credentialQueue = Promise.resolve();
|
|
113
|
+
function serialized(work) {
|
|
114
|
+
const result = credentialQueue.then(work);
|
|
115
|
+
credentialQueue = result.catch(() => undefined);
|
|
116
|
+
return result;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* A credential whose access token is current, other than `rejectedAccessToken` (the one a 401 was
|
|
120
|
+
* answered with, unless another call or process has renewed it since). A credential the platform
|
|
121
|
+
* no longer honours is removed, and the user signs in again.
|
|
122
|
+
*/
|
|
123
|
+
async function usableCredential(rejectedAccessToken) {
|
|
124
|
+
const stored = await readStoredCredential();
|
|
125
|
+
if (stored === null) {
|
|
126
|
+
return signInWhenAttended(null);
|
|
127
|
+
}
|
|
128
|
+
const expired = Date.parse(stored.accessTokenExpiresAt) - EXPIRY_MARGIN_MS <= Date.now();
|
|
129
|
+
if (!expired && stored.accessToken !== rejectedAccessToken) {
|
|
130
|
+
return stored;
|
|
131
|
+
}
|
|
132
|
+
try {
|
|
133
|
+
return await refresh(stored);
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
if (error instanceof OAuthError && (error.code === 'invalid_grant' || error.code === 'invalid_client')) {
|
|
137
|
+
await credentialStoreEntry().deletePassword();
|
|
138
|
+
return signInWhenAttended(error.code === 'invalid_grant' ? stored.clientId : null);
|
|
139
|
+
}
|
|
140
|
+
throw error;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
async function signInWhenAttended(clientId) {
|
|
144
|
+
if (isUnattended()) {
|
|
145
|
+
throw new Error(`Not signed in to idea1.ai (${apiBaseUrl()}). Run \`idea1 login\` to sign in.`);
|
|
146
|
+
}
|
|
147
|
+
logger.step(`Signing in to idea1.ai (${apiBaseUrl()})...`);
|
|
148
|
+
return signIn(clientId);
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Sign in through the browser with the given registered client, or a newly registered one, and
|
|
152
|
+
* store the credential: the authorization code flow with PKCE (S256) and `state`, redirected to a
|
|
153
|
+
* loopback server on a random port.
|
|
154
|
+
*
|
|
155
|
+
* The platform answers an authorization request it refuses outright, such as one for a client it
|
|
156
|
+
* no longer knows, with an error page instead of a redirect to the loopback server. So before the
|
|
157
|
+
* browser opens, the request for a stored client is sent once without following its redirect: a
|
|
158
|
+
* client the platform no longer knows is registered again, and any other refusal ends the sign-in.
|
|
159
|
+
*/
|
|
160
|
+
async function signIn(storedClientId) {
|
|
161
|
+
const metadata = await discoverAuthorizationServer();
|
|
162
|
+
const codeVerifier = base64Url(randomBytes(32));
|
|
163
|
+
const codeChallenge = base64Url(createHash('sha256').update(codeVerifier).digest());
|
|
164
|
+
const state = base64Url(randomBytes(16));
|
|
165
|
+
const callback = await listenForAuthorizationCallback(state);
|
|
166
|
+
try {
|
|
167
|
+
const authorizationUrlFor = (clientId) => {
|
|
168
|
+
const url = new URL(metadata.authorization_endpoint);
|
|
169
|
+
url.search = new URLSearchParams({
|
|
170
|
+
response_type: 'code',
|
|
171
|
+
client_id: clientId,
|
|
172
|
+
redirect_uri: callback.redirectUri,
|
|
173
|
+
scope: CLIENT_SCOPE,
|
|
174
|
+
state,
|
|
175
|
+
code_challenge: codeChallenge,
|
|
176
|
+
code_challenge_method: 'S256'
|
|
177
|
+
}).toString();
|
|
178
|
+
return url.toString();
|
|
179
|
+
};
|
|
180
|
+
let clientId = storedClientId ?? await registerClient(metadata);
|
|
181
|
+
if (storedClientId !== null) {
|
|
182
|
+
const refusal = await authorizationRefusal(authorizationUrlFor(storedClientId));
|
|
183
|
+
if (refusal?.code === 'invalid_client') {
|
|
184
|
+
clientId = await registerClient(metadata);
|
|
185
|
+
}
|
|
186
|
+
else if (refusal !== null) {
|
|
187
|
+
throw refusal;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
const [code] = await Promise.all([callback.code, openInBrowser(authorizationUrlFor(clientId))]);
|
|
191
|
+
const tokens = await postTokenRequest(metadata, {
|
|
192
|
+
grant_type: 'authorization_code',
|
|
193
|
+
code,
|
|
194
|
+
redirect_uri: callback.redirectUri,
|
|
195
|
+
client_id: clientId,
|
|
196
|
+
code_verifier: codeVerifier
|
|
197
|
+
});
|
|
198
|
+
if (tokens.refresh_token === null) {
|
|
199
|
+
throw new Error('idea1.ai issued no refresh token for the sign-in.');
|
|
200
|
+
}
|
|
201
|
+
return storeTokens(clientId, tokens, tokens.refresh_token);
|
|
202
|
+
}
|
|
203
|
+
finally {
|
|
204
|
+
callback.close();
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* The OAuth error the authorize endpoint answers a request with instead of redirecting it; null
|
|
209
|
+
* when it redirects. The endpoint validates the request and redirects to the consent page with no
|
|
210
|
+
* side effect, so the request is safe to send ahead of the browser.
|
|
211
|
+
*/
|
|
212
|
+
async function authorizationRefusal(authorizationUrl) {
|
|
213
|
+
const response = await fetch(authorizationUrl, { redirect: 'manual', headers: { Accept: 'application/json' } });
|
|
214
|
+
const text = await response.text();
|
|
215
|
+
const error = response.status >= 400 && response.status < 500 ? parseOAuthError(text) : null;
|
|
216
|
+
return error === null ? null : new OAuthError(error.error, error.error_description ?? null);
|
|
217
|
+
}
|
|
218
|
+
async function openInBrowser(url) {
|
|
219
|
+
logger.dim(`Sign in to idea1.ai in your browser. If it does not open, open this URL:\n${url}`);
|
|
220
|
+
try {
|
|
221
|
+
await openUrl(url);
|
|
222
|
+
}
|
|
223
|
+
catch (error) {
|
|
224
|
+
logger.warning(`Could not open the browser: ${error.message}`);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* A loopback HTTP server on a random port of 127.0.0.1 that receives the authorization redirect:
|
|
229
|
+
* `code` settles with the authorization code, the platform's error, or a timeout.
|
|
230
|
+
*/
|
|
231
|
+
async function listenForAuthorizationCallback(state) {
|
|
232
|
+
const server = createServer();
|
|
233
|
+
let timeout;
|
|
234
|
+
const code = new Promise((resolve, reject) => {
|
|
235
|
+
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);
|
|
236
|
+
server.on('request', (request, response) => {
|
|
237
|
+
const url = new URL(request.url ?? '/', 'http://127.0.0.1');
|
|
238
|
+
// Anything other than the redirect of this sign-in (a favicon, a stale tab) is not an answer.
|
|
239
|
+
if (url.pathname !== '/callback' || url.searchParams.get('state') !== state) {
|
|
240
|
+
response.writeHead(404).end();
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
const error = url.searchParams.get('error');
|
|
244
|
+
const authorizationCode = url.searchParams.get('code');
|
|
245
|
+
if (error !== null || !authorizationCode) {
|
|
246
|
+
writeCallbackPage(response, 'Sign-in did not complete. Return to the terminal for details; you can close this tab.');
|
|
247
|
+
reject(new OAuthError(error ?? 'invalid_request', url.searchParams.get('error_description')));
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
writeCallbackPage(response, 'Signed in to idea1.ai. You can close this tab and return to the terminal.');
|
|
251
|
+
resolve(authorizationCode);
|
|
252
|
+
});
|
|
253
|
+
});
|
|
254
|
+
await new Promise((resolve, reject) => {
|
|
255
|
+
server.once('error', reject);
|
|
256
|
+
server.listen(0, '127.0.0.1', () => resolve());
|
|
257
|
+
});
|
|
258
|
+
const { port } = server.address();
|
|
259
|
+
const redirectUri = new URL(REGISTERED_REDIRECT_URI);
|
|
260
|
+
redirectUri.port = String(port);
|
|
261
|
+
return {
|
|
262
|
+
redirectUri: redirectUri.toString(),
|
|
263
|
+
code,
|
|
264
|
+
close: () => {
|
|
265
|
+
clearTimeout(timeout);
|
|
266
|
+
server.close();
|
|
267
|
+
server.closeAllConnections();
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
function writeCallbackPage(response, message) {
|
|
272
|
+
response.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8', Connection: 'close' });
|
|
273
|
+
response.end('<!doctype html><html><head><meta charset="utf-8"><title>Idea1 CLI</title></head>' +
|
|
274
|
+
`<body style="font-family: system-ui, sans-serif; margin: 4rem; text-align: center"><p>${message}</p></body></html>`);
|
|
275
|
+
}
|
|
276
|
+
let authorizationServerMetadata = null;
|
|
277
|
+
function discoverAuthorizationServer() {
|
|
278
|
+
authorizationServerMetadata ??= readJson(fetch(`${apiBaseUrl()}/.well-known/oauth-authorization-server`, { headers: { Accept: 'application/json' } })).catch(error => {
|
|
279
|
+
authorizationServerMetadata = null;
|
|
280
|
+
throw error;
|
|
281
|
+
});
|
|
282
|
+
return authorizationServerMetadata;
|
|
283
|
+
}
|
|
284
|
+
async function registerClient(metadata) {
|
|
285
|
+
const registration = await readJson(fetch(metadata.registration_endpoint, {
|
|
286
|
+
method: 'POST',
|
|
287
|
+
headers: { Accept: 'application/json', 'Content-Type': 'application/json' },
|
|
288
|
+
body: JSON.stringify({
|
|
289
|
+
client_name: CLIENT_NAME,
|
|
290
|
+
redirect_uris: [REGISTERED_REDIRECT_URI],
|
|
291
|
+
grant_types: ['authorization_code', 'refresh_token'],
|
|
292
|
+
response_types: ['code'],
|
|
293
|
+
token_endpoint_auth_method: 'none',
|
|
294
|
+
scope: CLIENT_SCOPE
|
|
295
|
+
})
|
|
296
|
+
}));
|
|
297
|
+
return registration.client_id;
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Renew the access token. The platform does not rotate refresh tokens, so the stored one is kept
|
|
301
|
+
* unless the response carries another.
|
|
302
|
+
*/
|
|
303
|
+
async function refresh(stored) {
|
|
304
|
+
const tokens = await postTokenRequest(await discoverAuthorizationServer(), {
|
|
305
|
+
grant_type: 'refresh_token',
|
|
306
|
+
refresh_token: stored.refreshToken,
|
|
307
|
+
client_id: stored.clientId
|
|
308
|
+
});
|
|
309
|
+
return storeTokens(stored.clientId, tokens, tokens.refresh_token ?? stored.refreshToken);
|
|
310
|
+
}
|
|
311
|
+
async function revoke(stored) {
|
|
312
|
+
const metadata = await discoverAuthorizationServer();
|
|
313
|
+
await readSuccessBody(fetch(metadata.revocation_endpoint, {
|
|
314
|
+
method: 'POST',
|
|
315
|
+
headers: { Accept: 'application/json', 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
316
|
+
body: new URLSearchParams({ token: stored.refreshToken, token_type_hint: 'refresh_token', client_id: stored.clientId }).toString()
|
|
317
|
+
}));
|
|
318
|
+
}
|
|
319
|
+
function postTokenRequest(metadata, parameters) {
|
|
320
|
+
return readJson(fetch(metadata.token_endpoint, {
|
|
321
|
+
method: 'POST',
|
|
322
|
+
headers: { Accept: 'application/json', 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
323
|
+
body: new URLSearchParams(parameters).toString()
|
|
324
|
+
}));
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* The JSON body of an OAuth endpoint's success response.
|
|
328
|
+
*/
|
|
329
|
+
async function readJson(pending) {
|
|
330
|
+
return JSON.parse(await readSuccessBody(pending));
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* The body of an OAuth endpoint's success response; an error response throws OAuthError with the
|
|
334
|
+
* endpoint's `error` code, or an Error naming the HTTP status when it has none.
|
|
335
|
+
*/
|
|
336
|
+
async function readSuccessBody(pending) {
|
|
337
|
+
const response = await pending;
|
|
338
|
+
const text = await response.text();
|
|
339
|
+
if (response.ok) {
|
|
340
|
+
return text;
|
|
341
|
+
}
|
|
342
|
+
const error = parseOAuthError(text);
|
|
343
|
+
if (error !== null) {
|
|
344
|
+
throw new OAuthError(error.error, error.error_description ?? null);
|
|
345
|
+
}
|
|
346
|
+
throw new Error(`idea1.ai refused ${response.url} (${response.status} ${response.statusText})${text.trim() ? `: ${text.trim().slice(0, 500)}` : ''}`);
|
|
347
|
+
}
|
|
348
|
+
function parseOAuthError(text) {
|
|
349
|
+
try {
|
|
350
|
+
const body = JSON.parse(text);
|
|
351
|
+
return typeof body.error === 'string' ? { error: body.error, error_description: body.error_description } : null;
|
|
352
|
+
}
|
|
353
|
+
catch {
|
|
354
|
+
return null;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
async function storeTokens(clientId, tokens, refreshToken) {
|
|
358
|
+
const credential = {
|
|
359
|
+
clientId,
|
|
360
|
+
refreshToken,
|
|
361
|
+
accessToken: tokens.access_token,
|
|
362
|
+
accessTokenExpiresAt: new Date(Date.now() + tokens.expires_in * 1000).toISOString()
|
|
363
|
+
};
|
|
364
|
+
await credentialStoreEntry().setPassword(JSON.stringify(credential));
|
|
365
|
+
return credential;
|
|
366
|
+
}
|
|
367
|
+
async function readStoredCredential() {
|
|
368
|
+
const value = await credentialStoreEntry().getPassword();
|
|
369
|
+
return value === null ? null : JSON.parse(value);
|
|
370
|
+
}
|
|
371
|
+
function credentialStoreEntry() {
|
|
372
|
+
return new AsyncEntry(CREDENTIAL_STORE_SERVICE, apiBaseUrl());
|
|
373
|
+
}
|
|
374
|
+
function withBearer(init, token) {
|
|
375
|
+
return { ...init, headers: { ...init.headers, Authorization: `Bearer ${token}` } };
|
|
376
|
+
}
|
|
377
|
+
function base64Url(bytes) {
|
|
378
|
+
return bytes.toString('base64url');
|
|
379
|
+
}
|
|
380
|
+
//# 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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"}
|
|
@@ -6,30 +6,33 @@ import type { ClaudeRunOptions } from './claude.js';
|
|
|
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
8
|
* status (with the teammate it is assigned to), creating items, listing the team's Projects and
|
|
9
|
-
* members, deriving a branch name from an item
|
|
10
|
-
* nothing about the transport.
|
|
9
|
+
* members, deriving a branch name from an item, and reading who is signed in. Callers use
|
|
10
|
+
* `platform.someFunction()` and know nothing about the transport.
|
|
11
11
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* `src/prompts/platform-prompts.ts`; this module owns the output schemas their answers are read with.
|
|
12
|
+
* The transport is the platform's REST API, authorized with the user's OAuth credential or
|
|
13
|
+
* `IDEA1_TOKEN` (see `platform-auth.ts`), on the team that credential is bound to. Responses are the
|
|
14
|
+
* platform's `ApiDataResponse` envelope; a refused request surfaces as an Error carrying the
|
|
15
|
+
* platform's status and message. Claude is used only to name branches, on PLATFORM_CALL_RUN_OPTIONS.
|
|
17
16
|
*/
|
|
18
17
|
/**
|
|
19
|
-
* Model and effort for
|
|
20
|
-
*
|
|
18
|
+
* Model and effort for the Claude run that names a branch: a small, fast model at medium effort is
|
|
19
|
+
* all a one-line answer from a description needs, and pinning it keeps the run consistent and cheap.
|
|
21
20
|
*/
|
|
22
21
|
export declare const PLATFORM_CALL_RUN_OPTIONS: Required<ClaudeRunOptions>;
|
|
22
|
+
/**
|
|
23
|
+
* Who the platform credential signs in as: the user's email address and the team its calls work on.
|
|
24
|
+
*/
|
|
25
|
+
export interface SignedInUser {
|
|
26
|
+
emailAddress: string;
|
|
27
|
+
teamName: string;
|
|
28
|
+
}
|
|
23
29
|
/**
|
|
24
30
|
* Record workflow context updates on an idea1.ai project item directly, with no side effects on the
|
|
25
31
|
* platform: the CLI has already run the transition's work locally. The item must be under workflow
|
|
26
32
|
* management (have a workflow context); the workflow engine is the only caller, as the persist step
|
|
27
33
|
* 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.
|
|
34
|
+
* status; null leaves the assignment as it is. Returns false, with a warning, when the platform did
|
|
35
|
+
* not record it.
|
|
33
36
|
*/
|
|
34
37
|
export declare function setWorkflowStatus(itemUrl: string, status: string, pullRequestUrl: string | null, assignedToEmail: string | null): Promise<boolean>;
|
|
35
38
|
/**
|
|
@@ -67,7 +70,7 @@ export interface UpsertProjectItemWorkflowContextInput {
|
|
|
67
70
|
*/
|
|
68
71
|
export declare function upsertProjectItemWorkflowContext(input: UpsertProjectItemWorkflowContextInput): Promise<ProjectItemSummary>;
|
|
69
72
|
/**
|
|
70
|
-
* Generate a branch name from a project item description
|
|
73
|
+
* Generate a branch name from a project item's description.
|
|
71
74
|
*/
|
|
72
75
|
export declare function generateBranchName(itemUrl: string): Promise<string>;
|
|
73
76
|
/**
|
|
@@ -86,9 +89,13 @@ export declare function listTeamMembers(): Promise<TeamMember[]>;
|
|
|
86
89
|
*/
|
|
87
90
|
export declare function resolveTeammate(identity: string): Promise<TeamMember>;
|
|
88
91
|
/**
|
|
89
|
-
* Create a new idea1 project item with the given title in the named Project.
|
|
92
|
+
* Create a new idea1 project item with the given title in the named live Project.
|
|
90
93
|
* The item is created with description `# <title>`.
|
|
91
94
|
* Returns the created item's URL.
|
|
92
95
|
*/
|
|
93
96
|
export declare function createProjectItem(title: string, projectName: string): Promise<string>;
|
|
97
|
+
/**
|
|
98
|
+
* The user the platform credential signs in as, and the team its calls work on.
|
|
99
|
+
*/
|
|
100
|
+
export declare function getSignedInUser(): Promise<SignedInUser>;
|
|
94
101
|
//# 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,
|
|
1
|
+
{"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../../src/services/platform.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAmB,MAAM,sCAAsC,CAAC;AAC7F,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AAC3E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAKlE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAGpD;;;;;;;;;;;GAWG;AAEH;;;GAGG;AACH,eAAO,MAAM,yBAAyB,EAAE,QAAQ,CAAC,gBAAgB,CAAyC,CAAC;AA4D3G;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAqID;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,IAAI,EAAE,eAAe,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAaxJ;AAED;;;GAGG;AACH,wBAAsB,8BAA8B,CAAC,KAAK,EAAE;IAAE,kBAAkB,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CASlJ;AAED;;;GAGG;AACH,wBAAsB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAIxF;AAED;;GAEG;AACH,MAAM,WAAW,qCAAqC;IACpD,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,yEAAyE;IACzE,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,eAAe,CAAC;IACjC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED;;;;;;GAMG;AACH,wBAAsB,gCAAgC,CAAC,KAAK,EAAE,qCAAqC,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAehI;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAWzE;AAUD;;GAEG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAItD;AAID;;;GAGG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CAQvD;AAcD;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAQ3E;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAY3F;AAED;;GAEG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,YAAY,CAAC,CAG7D"}
|