@agentuity/cli 0.0.109 → 0.0.111
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/dist/build-report.d.ts +201 -0
- package/dist/build-report.d.ts.map +1 -0
- package/dist/build-report.js +335 -0
- package/dist/build-report.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +19 -4
- package/dist/cli.js.map +1 -1
- package/dist/cmd/build/entry-generator.d.ts.map +1 -1
- package/dist/cmd/build/entry-generator.js +3 -1
- package/dist/cmd/build/entry-generator.js.map +1 -1
- package/dist/cmd/build/index.d.ts.map +1 -1
- package/dist/cmd/build/index.js +44 -1
- package/dist/cmd/build/index.js.map +1 -1
- package/dist/cmd/build/typecheck.d.ts +7 -1
- package/dist/cmd/build/typecheck.d.ts.map +1 -1
- package/dist/cmd/build/typecheck.js +11 -1
- package/dist/cmd/build/typecheck.js.map +1 -1
- package/dist/cmd/build/vite/agent-discovery.d.ts +1 -1
- package/dist/cmd/build/vite/agent-discovery.d.ts.map +1 -1
- package/dist/cmd/build/vite/agent-discovery.js +3 -3
- package/dist/cmd/build/vite/agent-discovery.js.map +1 -1
- package/dist/cmd/build/vite/index.d.ts +2 -1
- package/dist/cmd/build/vite/index.d.ts.map +1 -1
- package/dist/cmd/build/vite/index.js +3 -2
- package/dist/cmd/build/vite/index.js.map +1 -1
- package/dist/cmd/build/vite/metadata-generator.d.ts.map +1 -1
- package/dist/cmd/build/vite/metadata-generator.js +3 -5
- package/dist/cmd/build/vite/metadata-generator.js.map +1 -1
- package/dist/cmd/build/vite/registry-generator.d.ts +1 -1
- package/dist/cmd/build/vite/registry-generator.d.ts.map +1 -1
- package/dist/cmd/build/vite/registry-generator.js +126 -41
- package/dist/cmd/build/vite/registry-generator.js.map +1 -1
- package/dist/cmd/build/vite/route-discovery.d.ts +6 -0
- package/dist/cmd/build/vite/route-discovery.d.ts.map +1 -1
- package/dist/cmd/build/vite/route-discovery.js +19 -0
- package/dist/cmd/build/vite/route-discovery.js.map +1 -1
- package/dist/cmd/build/vite/vite-builder.d.ts +3 -0
- package/dist/cmd/build/vite/vite-builder.d.ts.map +1 -1
- package/dist/cmd/build/vite/vite-builder.js +10 -2
- package/dist/cmd/build/vite/vite-builder.js.map +1 -1
- package/dist/cmd/build/vite-bundler.d.ts +3 -0
- package/dist/cmd/build/vite-bundler.d.ts.map +1 -1
- package/dist/cmd/build/vite-bundler.js +14 -5
- package/dist/cmd/build/vite-bundler.js.map +1 -1
- package/dist/cmd/cloud/deploy.d.ts.map +1 -1
- package/dist/cmd/cloud/deploy.js +149 -10
- package/dist/cmd/cloud/deploy.js.map +1 -1
- package/dist/cmd/cloud/deployment/show.d.ts.map +1 -1
- package/dist/cmd/cloud/deployment/show.js +0 -1
- package/dist/cmd/cloud/deployment/show.js.map +1 -1
- package/dist/cmd/cloud/sandbox/create.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/create.js +18 -0
- package/dist/cmd/cloud/sandbox/create.js.map +1 -1
- package/dist/cmd/cloud/sandbox/delete.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/delete.js +2 -6
- package/dist/cmd/cloud/sandbox/delete.js.map +1 -1
- package/dist/cmd/cloud/sandbox/download.d.ts +3 -0
- package/dist/cmd/cloud/sandbox/download.d.ts.map +1 -0
- package/dist/cmd/cloud/sandbox/download.js +89 -0
- package/dist/cmd/cloud/sandbox/download.js.map +1 -0
- package/dist/cmd/cloud/sandbox/env.d.ts +3 -0
- package/dist/cmd/cloud/sandbox/env.d.ts.map +1 -0
- package/dist/cmd/cloud/sandbox/env.js +90 -0
- package/dist/cmd/cloud/sandbox/env.js.map +1 -0
- package/dist/cmd/cloud/sandbox/get.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/get.js +5 -0
- package/dist/cmd/cloud/sandbox/get.js.map +1 -1
- package/dist/cmd/cloud/sandbox/index.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/index.js +14 -0
- package/dist/cmd/cloud/sandbox/index.js.map +1 -1
- package/dist/cmd/cloud/sandbox/ls.d.ts +3 -0
- package/dist/cmd/cloud/sandbox/ls.d.ts.map +1 -0
- package/dist/cmd/cloud/sandbox/ls.js +119 -0
- package/dist/cmd/cloud/sandbox/ls.js.map +1 -0
- package/dist/cmd/cloud/sandbox/mkdir.d.ts +3 -0
- package/dist/cmd/cloud/sandbox/mkdir.d.ts.map +1 -0
- package/dist/cmd/cloud/sandbox/mkdir.js +59 -0
- package/dist/cmd/cloud/sandbox/mkdir.js.map +1 -0
- package/dist/cmd/cloud/sandbox/rm.d.ts +3 -0
- package/dist/cmd/cloud/sandbox/rm.d.ts.map +1 -0
- package/dist/cmd/cloud/sandbox/rm.js +45 -0
- package/dist/cmd/cloud/sandbox/rm.js.map +1 -0
- package/dist/cmd/cloud/sandbox/rmdir.d.ts +3 -0
- package/dist/cmd/cloud/sandbox/rmdir.d.ts.map +1 -0
- package/dist/cmd/cloud/sandbox/rmdir.js +59 -0
- package/dist/cmd/cloud/sandbox/rmdir.js.map +1 -0
- package/dist/cmd/cloud/sandbox/snapshot/create.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/snapshot/create.js +0 -2
- package/dist/cmd/cloud/sandbox/snapshot/create.js.map +1 -1
- package/dist/cmd/cloud/sandbox/snapshot/get.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/snapshot/get.js +0 -2
- package/dist/cmd/cloud/sandbox/snapshot/get.js.map +1 -1
- package/dist/cmd/cloud/sandbox/snapshot/list.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/snapshot/list.js +0 -3
- package/dist/cmd/cloud/sandbox/snapshot/list.js.map +1 -1
- package/dist/cmd/cloud/sandbox/upload.d.ts +3 -0
- package/dist/cmd/cloud/sandbox/upload.d.ts.map +1 -0
- package/dist/cmd/cloud/sandbox/upload.js +77 -0
- package/dist/cmd/cloud/sandbox/upload.js.map +1 -0
- package/dist/cmd/dev/index.d.ts.map +1 -1
- package/dist/cmd/dev/index.js +126 -23
- package/dist/cmd/dev/index.js.map +1 -1
- package/dist/cmd/dev/sync.d.ts.map +1 -1
- package/dist/cmd/dev/sync.js +8 -14
- package/dist/cmd/dev/sync.js.map +1 -1
- package/dist/cmd/git/account/add.d.ts +17 -0
- package/dist/cmd/git/account/add.d.ts.map +1 -0
- package/dist/cmd/git/account/add.js +244 -0
- package/dist/cmd/git/account/add.js.map +1 -0
- package/dist/cmd/git/account/index.d.ts +3 -0
- package/dist/cmd/git/account/index.d.ts.map +1 -0
- package/dist/cmd/git/account/index.js +11 -0
- package/dist/cmd/git/account/index.js.map +1 -0
- package/dist/cmd/git/account/list.d.ts +2 -0
- package/dist/cmd/git/account/list.d.ts.map +1 -0
- package/dist/cmd/git/account/list.js +111 -0
- package/dist/cmd/git/account/list.js.map +1 -0
- package/dist/cmd/git/account/remove.d.ts +2 -0
- package/dist/cmd/git/account/remove.d.ts.map +1 -0
- package/dist/cmd/git/account/remove.js +171 -0
- package/dist/cmd/git/account/remove.js.map +1 -0
- package/dist/cmd/git/index.d.ts +3 -0
- package/dist/cmd/git/index.d.ts.map +1 -0
- package/dist/cmd/git/index.js +19 -0
- package/dist/cmd/git/index.js.map +1 -0
- package/dist/cmd/git/link.d.ts +32 -0
- package/dist/cmd/git/link.d.ts.map +1 -0
- package/dist/cmd/git/link.js +357 -0
- package/dist/cmd/git/link.js.map +1 -0
- package/dist/cmd/git/list.d.ts +2 -0
- package/dist/cmd/git/list.d.ts.map +1 -0
- package/dist/cmd/git/list.js +137 -0
- package/dist/cmd/git/list.js.map +1 -0
- package/dist/cmd/git/status.d.ts +2 -0
- package/dist/cmd/git/status.d.ts.map +1 -0
- package/dist/cmd/git/status.js +119 -0
- package/dist/cmd/git/status.js.map +1 -0
- package/dist/cmd/git/unlink.d.ts +2 -0
- package/dist/cmd/git/unlink.d.ts.map +1 -0
- package/dist/cmd/git/unlink.js +98 -0
- package/dist/cmd/git/unlink.js.map +1 -0
- package/dist/cmd/index.d.ts.map +1 -1
- package/dist/cmd/index.js +2 -0
- package/dist/cmd/index.js.map +1 -1
- package/dist/cmd/integration/api.d.ts +61 -0
- package/dist/cmd/integration/api.d.ts.map +1 -0
- package/dist/cmd/integration/api.js +176 -0
- package/dist/cmd/integration/api.js.map +1 -0
- package/dist/cmd/integration/github/connect.d.ts +2 -0
- package/dist/cmd/integration/github/connect.d.ts.map +1 -0
- package/dist/cmd/integration/github/connect.js +197 -0
- package/dist/cmd/integration/github/connect.js.map +1 -0
- package/dist/cmd/integration/github/disconnect.d.ts +2 -0
- package/dist/cmd/integration/github/disconnect.d.ts.map +1 -0
- package/dist/cmd/integration/github/disconnect.js +121 -0
- package/dist/cmd/integration/github/disconnect.js.map +1 -0
- package/dist/cmd/integration/github/index.d.ts +2 -0
- package/dist/cmd/integration/github/index.d.ts.map +1 -0
- package/dist/cmd/integration/github/index.js +21 -0
- package/dist/cmd/integration/github/index.js.map +1 -0
- package/dist/cmd/integration/index.d.ts +2 -0
- package/dist/cmd/integration/index.d.ts.map +1 -0
- package/dist/cmd/integration/index.js +16 -0
- package/dist/cmd/integration/index.js.map +1 -0
- package/dist/cmd/project/auth/generate.d.ts +5 -0
- package/dist/cmd/project/auth/generate.d.ts.map +1 -0
- package/dist/cmd/project/auth/generate.js +102 -0
- package/dist/cmd/project/auth/generate.js.map +1 -0
- package/dist/cmd/project/auth/index.d.ts +2 -0
- package/dist/cmd/project/auth/index.d.ts.map +1 -0
- package/dist/cmd/project/auth/index.js +21 -0
- package/dist/cmd/project/auth/index.js.map +1 -0
- package/dist/cmd/project/auth/init.d.ts +2 -0
- package/dist/cmd/project/auth/init.d.ts.map +1 -0
- package/dist/cmd/project/auth/init.js +220 -0
- package/dist/cmd/project/auth/init.js.map +1 -0
- package/dist/cmd/project/auth/shared.d.ts +88 -0
- package/dist/cmd/project/auth/shared.d.ts.map +1 -0
- package/dist/cmd/project/auth/shared.js +435 -0
- package/dist/cmd/project/auth/shared.js.map +1 -0
- package/dist/cmd/project/index.d.ts.map +1 -1
- package/dist/cmd/project/index.js +9 -1
- package/dist/cmd/project/index.js.map +1 -1
- package/dist/cmd/project/template-flow.d.ts.map +1 -1
- package/dist/cmd/project/template-flow.js +106 -0
- package/dist/cmd/project/template-flow.js.map +1 -1
- package/dist/config.d.ts +2 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +24 -0
- package/dist/config.js.map +1 -1
- package/dist/errors.d.ts +2 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +5 -0
- package/dist/errors.js.map +1 -1
- package/dist/types.d.ts +3 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +5 -2
- package/dist/types.js.map +1 -1
- package/package.json +6 -5
- package/src/build-report.ts +457 -0
- package/src/cli.ts +20 -4
- package/src/cmd/build/entry-generator.ts +3 -1
- package/src/cmd/build/index.ts +51 -1
- package/src/cmd/build/typecheck.ts +19 -1
- package/src/cmd/build/vite/agent-discovery.ts +4 -4
- package/src/cmd/build/vite/index.ts +5 -2
- package/src/cmd/build/vite/metadata-generator.ts +5 -7
- package/src/cmd/build/vite/registry-generator.ts +136 -43
- package/src/cmd/build/vite/route-discovery.ts +20 -0
- package/src/cmd/build/vite/vite-builder.ts +13 -2
- package/src/cmd/build/vite-bundler.ts +17 -4
- package/src/cmd/cloud/deploy.ts +183 -12
- package/src/cmd/cloud/deployment/show.ts +0 -1
- package/src/cmd/cloud/sandbox/create.ts +22 -0
- package/src/cmd/cloud/sandbox/delete.ts +2 -6
- package/src/cmd/cloud/sandbox/download.ts +96 -0
- package/src/cmd/cloud/sandbox/env.ts +104 -0
- package/src/cmd/cloud/sandbox/get.ts +5 -0
- package/src/cmd/cloud/sandbox/index.ts +14 -0
- package/src/cmd/cloud/sandbox/ls.ts +126 -0
- package/src/cmd/cloud/sandbox/mkdir.ts +65 -0
- package/src/cmd/cloud/sandbox/rm.ts +51 -0
- package/src/cmd/cloud/sandbox/rmdir.ts +65 -0
- package/src/cmd/cloud/sandbox/snapshot/create.ts +0 -2
- package/src/cmd/cloud/sandbox/snapshot/get.ts +0 -2
- package/src/cmd/cloud/sandbox/snapshot/list.ts +0 -3
- package/src/cmd/cloud/sandbox/upload.ts +83 -0
- package/src/cmd/dev/index.ts +147 -33
- package/src/cmd/dev/sync.ts +26 -30
- package/src/cmd/git/account/add.ts +317 -0
- package/src/cmd/git/account/index.ts +12 -0
- package/src/cmd/git/account/list.ts +139 -0
- package/src/cmd/git/account/remove.ts +212 -0
- package/src/cmd/git/index.ts +20 -0
- package/src/cmd/git/link.ts +468 -0
- package/src/cmd/git/list.ts +161 -0
- package/src/cmd/git/status.ts +144 -0
- package/src/cmd/git/unlink.ts +117 -0
- package/src/cmd/index.ts +2 -0
- package/src/cmd/integration/api.ts +379 -0
- package/src/cmd/integration/github/connect.ts +242 -0
- package/src/cmd/integration/github/disconnect.ts +149 -0
- package/src/cmd/integration/github/index.ts +21 -0
- package/src/cmd/integration/index.ts +16 -0
- package/src/cmd/project/auth/generate.ts +116 -0
- package/src/cmd/project/auth/index.ts +21 -0
- package/src/cmd/project/auth/init.ts +263 -0
- package/src/cmd/project/auth/shared.ts +534 -0
- package/src/cmd/project/index.ts +9 -1
- package/src/cmd/project/template-flow.ts +125 -0
- package/src/config.ts +34 -0
- package/src/errors.ts +7 -0
- package/src/types.ts +5 -2
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
import { createSubcommand } from '../../../types';
|
|
2
|
+
import type { Config } from '../../../types';
|
|
3
|
+
import * as tui from '../../../tui';
|
|
4
|
+
import { getCommand } from '../../../command-prefix';
|
|
5
|
+
import { getAPIBaseURL } from '../../../api';
|
|
6
|
+
import type { APIClient } from '../../../api';
|
|
7
|
+
import { ErrorCode } from '../../../errors';
|
|
8
|
+
import { listOrganizations } from '@agentuity/server';
|
|
9
|
+
import enquirer from 'enquirer';
|
|
10
|
+
import type { Logger } from '@agentuity/core';
|
|
11
|
+
import { z } from 'zod';
|
|
12
|
+
import {
|
|
13
|
+
startGithubIntegration,
|
|
14
|
+
pollForGithubIntegration,
|
|
15
|
+
getGithubIntegrationStatus,
|
|
16
|
+
getExistingGithubIntegrations,
|
|
17
|
+
copyGithubIntegration,
|
|
18
|
+
} from '../../integration/api';
|
|
19
|
+
|
|
20
|
+
export interface RunGitAccountConnectOptions {
|
|
21
|
+
apiClient: APIClient;
|
|
22
|
+
orgId: string;
|
|
23
|
+
orgName?: string;
|
|
24
|
+
logger: Logger;
|
|
25
|
+
config?: Config | null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface RunGitAccountConnectResult {
|
|
29
|
+
connected: boolean;
|
|
30
|
+
cancelled?: boolean;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export async function runGitAccountConnect(
|
|
34
|
+
options: RunGitAccountConnectOptions
|
|
35
|
+
): Promise<RunGitAccountConnectResult> {
|
|
36
|
+
const { apiClient, orgId, orgName, logger, config } = options;
|
|
37
|
+
const orgDisplay = orgName ?? orgId;
|
|
38
|
+
|
|
39
|
+
try {
|
|
40
|
+
const currentStatus = await getGithubIntegrationStatus(apiClient, orgId);
|
|
41
|
+
const initialCount = currentStatus.integrations?.length ?? 0;
|
|
42
|
+
|
|
43
|
+
const existingIntegrations = await tui.spinner({
|
|
44
|
+
message: 'Checking for existing GitHub connections...',
|
|
45
|
+
clearOnSuccess: true,
|
|
46
|
+
callback: () => getExistingGithubIntegrations(apiClient, orgId),
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const alreadyConnectedNames = new Set(
|
|
50
|
+
currentStatus.integrations?.map((i) => i.githubAccountName) ?? []
|
|
51
|
+
);
|
|
52
|
+
const availableIntegrations = existingIntegrations.filter(
|
|
53
|
+
(i) => !alreadyConnectedNames.has(i.githubAccountName)
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
if (availableIntegrations.length > 0) {
|
|
57
|
+
tui.newline();
|
|
58
|
+
|
|
59
|
+
const integrationChoices = availableIntegrations.map((i) => ({
|
|
60
|
+
name: i.id,
|
|
61
|
+
message: `${i.githubAccountName} ${tui.muted(`(from ${i.orgName})`)}`,
|
|
62
|
+
}));
|
|
63
|
+
|
|
64
|
+
console.log(tui.muted('Press enter with none selected to add a new account'));
|
|
65
|
+
tui.newline();
|
|
66
|
+
|
|
67
|
+
const selectResponse = await enquirer.prompt<{ integrationIds: string[] }>({
|
|
68
|
+
type: 'multiselect',
|
|
69
|
+
name: 'integrationIds',
|
|
70
|
+
message: 'Select GitHub accounts to add',
|
|
71
|
+
choices: integrationChoices,
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
if (selectResponse.integrationIds.length > 0) {
|
|
75
|
+
const selectedIntegrations = availableIntegrations.filter((i) =>
|
|
76
|
+
selectResponse.integrationIds.includes(i.id)
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
const accountNames = selectedIntegrations.map((i) => i.githubAccountName).join(', ');
|
|
80
|
+
|
|
81
|
+
const confirmResponse = await enquirer.prompt<{ confirm: boolean }>({
|
|
82
|
+
type: 'confirm',
|
|
83
|
+
name: 'confirm',
|
|
84
|
+
message: `Add ${tui.bold(accountNames)} to ${tui.bold(orgDisplay)}?`,
|
|
85
|
+
initial: true,
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
if (confirmResponse.confirm) {
|
|
89
|
+
await tui.spinner({
|
|
90
|
+
message: `Adding ${selectedIntegrations.length} GitHub account${selectedIntegrations.length > 1 ? 's' : ''}...`,
|
|
91
|
+
clearOnSuccess: true,
|
|
92
|
+
callback: async () => {
|
|
93
|
+
for (const integration of selectedIntegrations) {
|
|
94
|
+
await copyGithubIntegration(apiClient, integration.orgId, orgId);
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
tui.newline();
|
|
100
|
+
tui.success(
|
|
101
|
+
`Added GitHub account${selectedIntegrations.length > 1 ? 's' : ''} to ${tui.bold(orgDisplay)}`
|
|
102
|
+
);
|
|
103
|
+
return { connected: true };
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const startResult = await tui.spinner({
|
|
109
|
+
message: 'Getting GitHub authorization URL...',
|
|
110
|
+
clearOnSuccess: true,
|
|
111
|
+
callback: () => startGithubIntegration(apiClient, orgId),
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
if (!startResult) {
|
|
115
|
+
tui.error('Failed to start GitHub authorization');
|
|
116
|
+
return { connected: false };
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const { shortId } = startResult;
|
|
120
|
+
const apiBaseUrl = getAPIBaseURL(config);
|
|
121
|
+
const url = `${apiBaseUrl}/github/connect/${shortId}`;
|
|
122
|
+
|
|
123
|
+
const copied = await tui.copyToClipboard(url);
|
|
124
|
+
|
|
125
|
+
tui.newline();
|
|
126
|
+
if (copied) {
|
|
127
|
+
console.log('GitHub authorization URL copied to clipboard! Open it in your browser:');
|
|
128
|
+
} else {
|
|
129
|
+
console.log('Open this URL in your browser to authorize GitHub access:');
|
|
130
|
+
}
|
|
131
|
+
tui.newline();
|
|
132
|
+
console.log(` ${tui.link(url)}`);
|
|
133
|
+
tui.newline();
|
|
134
|
+
console.log(tui.muted('Press Enter to open in your browser, or Ctrl+C to cancel'));
|
|
135
|
+
tui.newline();
|
|
136
|
+
|
|
137
|
+
const result = await tui.spinner({
|
|
138
|
+
type: 'countdown',
|
|
139
|
+
message: 'Waiting for GitHub authorization',
|
|
140
|
+
timeoutMs: 600000,
|
|
141
|
+
clearOnSuccess: true,
|
|
142
|
+
onEnterPress: () => {
|
|
143
|
+
const platform = process.platform;
|
|
144
|
+
if (platform === 'win32') {
|
|
145
|
+
Bun.spawn(['cmd', '/c', 'start', '', url], {
|
|
146
|
+
stdout: 'ignore',
|
|
147
|
+
stderr: 'ignore',
|
|
148
|
+
});
|
|
149
|
+
} else {
|
|
150
|
+
const command = platform === 'darwin' ? 'open' : 'xdg-open';
|
|
151
|
+
Bun.spawn([command, url], { stdout: 'ignore', stderr: 'ignore' });
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
callback: async () => {
|
|
155
|
+
return await pollForGithubIntegration(apiClient, orgId, initialCount);
|
|
156
|
+
},
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
tui.newline();
|
|
160
|
+
if (result.connected) {
|
|
161
|
+
tui.success(`GitHub account added to ${tui.bold(orgDisplay)}`);
|
|
162
|
+
return { connected: true };
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return { connected: false };
|
|
166
|
+
} catch (error) {
|
|
167
|
+
const isCancel =
|
|
168
|
+
error === '' ||
|
|
169
|
+
(error instanceof Error && (error.message === '' || error.message === 'User cancelled'));
|
|
170
|
+
|
|
171
|
+
if (isCancel) {
|
|
172
|
+
tui.newline();
|
|
173
|
+
tui.info('Cancelled');
|
|
174
|
+
return { connected: false, cancelled: true };
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
logger.trace(error);
|
|
178
|
+
throw error;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const AddOptionsSchema = z.object({
|
|
183
|
+
org: z.string().optional().describe('Organization ID to add the account to'),
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
const AddResponseSchema = z.object({
|
|
187
|
+
connected: z.boolean().describe('Whether the account was connected'),
|
|
188
|
+
orgId: z.string().optional().describe('Organization ID'),
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
export const addSubcommand = createSubcommand({
|
|
192
|
+
name: 'add',
|
|
193
|
+
description: 'Add a GitHub account to your organization',
|
|
194
|
+
tags: ['mutating', 'creates-resource', 'slow', 'api-intensive'],
|
|
195
|
+
idempotent: false,
|
|
196
|
+
requires: { auth: true, apiClient: true },
|
|
197
|
+
schema: {
|
|
198
|
+
options: AddOptionsSchema,
|
|
199
|
+
response: AddResponseSchema,
|
|
200
|
+
},
|
|
201
|
+
examples: [
|
|
202
|
+
{
|
|
203
|
+
command: getCommand('git account add'),
|
|
204
|
+
description: 'Add a GitHub account to your organization',
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
command: getCommand('git account add --org org_abc123'),
|
|
208
|
+
description: 'Add to a specific organization',
|
|
209
|
+
},
|
|
210
|
+
],
|
|
211
|
+
|
|
212
|
+
async handler(ctx) {
|
|
213
|
+
const { logger, apiClient, config, opts } = ctx;
|
|
214
|
+
|
|
215
|
+
try {
|
|
216
|
+
const orgs = await tui.spinner({
|
|
217
|
+
message: 'Fetching organizations...',
|
|
218
|
+
clearOnSuccess: true,
|
|
219
|
+
callback: () => listOrganizations(apiClient),
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
if (orgs.length === 0) {
|
|
223
|
+
tui.fatal('No organizations found for your account');
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
let orgId = opts.org;
|
|
227
|
+
let selectedOrg: (typeof orgs)[0] | undefined;
|
|
228
|
+
|
|
229
|
+
if (orgId) {
|
|
230
|
+
selectedOrg = orgs.find((o) => o.id === orgId);
|
|
231
|
+
if (!selectedOrg) {
|
|
232
|
+
tui.fatal(`Organization ${orgId} not found`);
|
|
233
|
+
}
|
|
234
|
+
} else {
|
|
235
|
+
const orgStatuses = await tui.spinner({
|
|
236
|
+
message: 'Checking GitHub integration status...',
|
|
237
|
+
clearOnSuccess: true,
|
|
238
|
+
callback: async () => {
|
|
239
|
+
const statuses = await Promise.all(
|
|
240
|
+
orgs.map(async (org) => {
|
|
241
|
+
const status = await getGithubIntegrationStatus(apiClient, org.id);
|
|
242
|
+
return {
|
|
243
|
+
...org,
|
|
244
|
+
connected: status.connected,
|
|
245
|
+
integrations: status.integrations,
|
|
246
|
+
};
|
|
247
|
+
})
|
|
248
|
+
);
|
|
249
|
+
return statuses;
|
|
250
|
+
},
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
const sortedOrgs = [...orgStatuses].sort((a, b) => a.name.localeCompare(b.name));
|
|
254
|
+
|
|
255
|
+
if (orgs.length === 1) {
|
|
256
|
+
orgId = orgs[0].id;
|
|
257
|
+
selectedOrg = orgs[0];
|
|
258
|
+
} else {
|
|
259
|
+
const choices = sortedOrgs.map((org) => {
|
|
260
|
+
const count = org.integrations.length;
|
|
261
|
+
const suffix =
|
|
262
|
+
count > 0
|
|
263
|
+
? tui.muted(` (${count} GitHub account${count > 1 ? 's' : ''})`)
|
|
264
|
+
: '';
|
|
265
|
+
return {
|
|
266
|
+
name: org.name,
|
|
267
|
+
message: `${org.name}${suffix}`,
|
|
268
|
+
value: org.id,
|
|
269
|
+
};
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
const response = await enquirer.prompt<{ orgName: string }>({
|
|
273
|
+
type: 'select',
|
|
274
|
+
name: 'orgName',
|
|
275
|
+
message: 'Select an organization',
|
|
276
|
+
choices,
|
|
277
|
+
result(name: string) {
|
|
278
|
+
// @ts-expect-error - this.map exists at runtime
|
|
279
|
+
return this.map(name)[name];
|
|
280
|
+
},
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
orgId = response.orgName;
|
|
284
|
+
selectedOrg = sortedOrgs.find((o) => o.id === orgId);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
const result = await runGitAccountConnect({
|
|
289
|
+
apiClient,
|
|
290
|
+
orgId: orgId!,
|
|
291
|
+
orgName: selectedOrg?.name,
|
|
292
|
+
logger,
|
|
293
|
+
config,
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
return { connected: result.connected, orgId };
|
|
297
|
+
} catch (error) {
|
|
298
|
+
const isCancel =
|
|
299
|
+
error === '' ||
|
|
300
|
+
(error instanceof Error &&
|
|
301
|
+
(error.message === '' || error.message === 'User cancelled'));
|
|
302
|
+
|
|
303
|
+
if (isCancel) {
|
|
304
|
+
tui.newline();
|
|
305
|
+
tui.info('Cancelled');
|
|
306
|
+
return { connected: false };
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
logger.trace(error);
|
|
310
|
+
return logger.fatal(
|
|
311
|
+
'Failed to add GitHub account: %s',
|
|
312
|
+
error,
|
|
313
|
+
ErrorCode.INTEGRATION_FAILED
|
|
314
|
+
);
|
|
315
|
+
}
|
|
316
|
+
},
|
|
317
|
+
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { createCommand } from '../../../types';
|
|
2
|
+
import { addSubcommand } from './add';
|
|
3
|
+
import { removeSubcommand } from './remove';
|
|
4
|
+
import { listSubcommand } from './list';
|
|
5
|
+
|
|
6
|
+
export const accountCommand = createCommand({
|
|
7
|
+
name: 'account',
|
|
8
|
+
description: 'Manage GitHub accounts connected to your organization',
|
|
9
|
+
subcommands: [addSubcommand, removeSubcommand, listSubcommand],
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
export default accountCommand;
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { createSubcommand } from '../../../types';
|
|
2
|
+
import * as tui from '../../../tui';
|
|
3
|
+
import { getCommand } from '../../../command-prefix';
|
|
4
|
+
import { ErrorCode } from '../../../errors';
|
|
5
|
+
import { listOrganizations } from '@agentuity/server';
|
|
6
|
+
import { getGithubIntegrationStatus } from '../../integration/api';
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
|
|
9
|
+
const ListResponseSchema = z.array(
|
|
10
|
+
z.object({
|
|
11
|
+
orgId: z.string().describe('Organization ID'),
|
|
12
|
+
orgName: z.string().describe('Organization name'),
|
|
13
|
+
integrations: z.array(
|
|
14
|
+
z.object({
|
|
15
|
+
id: z.string().describe('Integration ID'),
|
|
16
|
+
githubAccountName: z.string().describe('GitHub account name'),
|
|
17
|
+
githubAccountType: z.enum(['user', 'org']).describe('Account type'),
|
|
18
|
+
})
|
|
19
|
+
),
|
|
20
|
+
})
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
export const listSubcommand = createSubcommand({
|
|
24
|
+
name: 'list',
|
|
25
|
+
description: 'List GitHub accounts connected to your organizations',
|
|
26
|
+
aliases: ['ls'],
|
|
27
|
+
tags: ['read-only'],
|
|
28
|
+
idempotent: true,
|
|
29
|
+
requires: { auth: true, apiClient: true },
|
|
30
|
+
schema: {
|
|
31
|
+
response: ListResponseSchema,
|
|
32
|
+
},
|
|
33
|
+
examples: [
|
|
34
|
+
{
|
|
35
|
+
command: getCommand('git account list'),
|
|
36
|
+
description: 'List all connected GitHub accounts',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
command: getCommand('--json git account list'),
|
|
40
|
+
description: 'List accounts in JSON format',
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
|
|
44
|
+
async handler(ctx) {
|
|
45
|
+
const { logger, apiClient, options } = ctx;
|
|
46
|
+
|
|
47
|
+
try {
|
|
48
|
+
// Fetch organizations
|
|
49
|
+
const orgs = await tui.spinner({
|
|
50
|
+
message: 'Fetching organizations...',
|
|
51
|
+
clearOnSuccess: true,
|
|
52
|
+
callback: () => listOrganizations(apiClient),
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
if (orgs.length === 0) {
|
|
56
|
+
tui.fatal('No organizations found for your account');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Check GitHub status for each org
|
|
60
|
+
const orgStatuses = await tui.spinner({
|
|
61
|
+
message: 'Checking GitHub integration status...',
|
|
62
|
+
clearOnSuccess: true,
|
|
63
|
+
callback: async () => {
|
|
64
|
+
const statuses = await Promise.all(
|
|
65
|
+
orgs.map(async (org) => {
|
|
66
|
+
const status = await getGithubIntegrationStatus(apiClient, org.id);
|
|
67
|
+
return {
|
|
68
|
+
...org,
|
|
69
|
+
connected: status.connected,
|
|
70
|
+
integrations: status.integrations,
|
|
71
|
+
};
|
|
72
|
+
})
|
|
73
|
+
);
|
|
74
|
+
return statuses;
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// Sort orgs alphabetically
|
|
79
|
+
const sortedOrgs = [...orgStatuses].sort((a, b) => a.name.localeCompare(b.name));
|
|
80
|
+
|
|
81
|
+
const result = sortedOrgs.map((org) => ({
|
|
82
|
+
orgId: org.id,
|
|
83
|
+
orgName: org.name,
|
|
84
|
+
integrations: org.integrations.map((i) => ({
|
|
85
|
+
id: i.id,
|
|
86
|
+
githubAccountName: i.githubAccountName,
|
|
87
|
+
githubAccountType: i.githubAccountType,
|
|
88
|
+
})),
|
|
89
|
+
}));
|
|
90
|
+
|
|
91
|
+
if (options.json) {
|
|
92
|
+
return result;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
tui.newline();
|
|
96
|
+
console.log(tui.bold('GitHub Accounts'));
|
|
97
|
+
tui.newline();
|
|
98
|
+
|
|
99
|
+
let totalCount = 0;
|
|
100
|
+
|
|
101
|
+
for (const org of sortedOrgs) {
|
|
102
|
+
if (org.integrations.length === 0) {
|
|
103
|
+
console.log(` ${org.name} ${tui.muted('(no accounts connected)')}`);
|
|
104
|
+
} else {
|
|
105
|
+
console.log(` ${org.name}`);
|
|
106
|
+
for (const integration of org.integrations) {
|
|
107
|
+
const typeLabel = integration.githubAccountType === 'org' ? 'org' : 'user';
|
|
108
|
+
console.log(
|
|
109
|
+
` ${tui.colorSuccess('✓')} ${integration.githubAccountName} ${tui.muted(`(${typeLabel})`)}`
|
|
110
|
+
);
|
|
111
|
+
totalCount++;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
tui.newline();
|
|
117
|
+
if (totalCount === 0) {
|
|
118
|
+
console.log(
|
|
119
|
+
tui.muted(
|
|
120
|
+
`No GitHub accounts connected. Run ${tui.bold('agentuity git account add')} to add one.`
|
|
121
|
+
)
|
|
122
|
+
);
|
|
123
|
+
} else {
|
|
124
|
+
console.log(
|
|
125
|
+
tui.muted(`${totalCount} GitHub account${totalCount > 1 ? 's' : ''} connected`)
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return result;
|
|
130
|
+
} catch (error) {
|
|
131
|
+
logger.trace(error);
|
|
132
|
+
return logger.fatal(
|
|
133
|
+
'Failed to list GitHub accounts: %s',
|
|
134
|
+
error,
|
|
135
|
+
ErrorCode.INTEGRATION_FAILED
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
});
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { createSubcommand } from '../../../types';
|
|
2
|
+
import * as tui from '../../../tui';
|
|
3
|
+
import { getCommand } from '../../../command-prefix';
|
|
4
|
+
import { ErrorCode } from '../../../errors';
|
|
5
|
+
import { listOrganizations } from '@agentuity/server';
|
|
6
|
+
import enquirer from 'enquirer';
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
import {
|
|
9
|
+
getGithubIntegrationStatus,
|
|
10
|
+
disconnectGithubIntegration,
|
|
11
|
+
type GithubIntegration,
|
|
12
|
+
} from '../../integration/api';
|
|
13
|
+
|
|
14
|
+
const RemoveOptionsSchema = z.object({
|
|
15
|
+
org: z.string().optional().describe('Organization ID'),
|
|
16
|
+
account: z.string().optional().describe('GitHub integration ID to remove'),
|
|
17
|
+
confirm: z.boolean().optional().describe('Skip confirmation prompt'),
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const RemoveResponseSchema = z.object({
|
|
21
|
+
removed: z.boolean().describe('Whether the account was removed'),
|
|
22
|
+
orgId: z.string().optional().describe('Organization ID'),
|
|
23
|
+
integrationId: z.string().optional().describe('Integration ID that was removed'),
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
export const removeSubcommand = createSubcommand({
|
|
27
|
+
name: 'remove',
|
|
28
|
+
description: 'Remove a GitHub account from your organization',
|
|
29
|
+
tags: ['mutating', 'destructive', 'slow'],
|
|
30
|
+
idempotent: false,
|
|
31
|
+
requires: { auth: true, apiClient: true },
|
|
32
|
+
schema: {
|
|
33
|
+
options: RemoveOptionsSchema,
|
|
34
|
+
response: RemoveResponseSchema,
|
|
35
|
+
},
|
|
36
|
+
examples: [
|
|
37
|
+
{
|
|
38
|
+
command: getCommand('git account remove'),
|
|
39
|
+
description: 'Remove a GitHub account from your organization',
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
command: getCommand('git account remove --org org_abc --account int_xyz --confirm'),
|
|
43
|
+
description: 'Remove a specific account without prompts',
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
command: getCommand('--json git account remove --org org_abc --account int_xyz --confirm'),
|
|
47
|
+
description: 'Remove and return JSON result',
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
|
|
51
|
+
async handler(ctx) {
|
|
52
|
+
const { logger, apiClient, opts, options } = ctx;
|
|
53
|
+
|
|
54
|
+
try {
|
|
55
|
+
// If both org and account provided, skip interactive flow
|
|
56
|
+
if (opts.org && opts.account) {
|
|
57
|
+
if (!opts.confirm) {
|
|
58
|
+
const confirmed = await tui.confirm(
|
|
59
|
+
`Are you sure you want to remove this GitHub account?`
|
|
60
|
+
);
|
|
61
|
+
if (!confirmed) {
|
|
62
|
+
tui.info('Cancelled');
|
|
63
|
+
return { removed: false };
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
await tui.spinner({
|
|
68
|
+
message: 'Removing GitHub account...',
|
|
69
|
+
clearOnSuccess: true,
|
|
70
|
+
callback: () => disconnectGithubIntegration(apiClient, opts.org!, opts.account!),
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
if (!options.json) {
|
|
74
|
+
tui.newline();
|
|
75
|
+
tui.success('Removed GitHub account');
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return { removed: true, orgId: opts.org, integrationId: opts.account };
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Fetch organizations
|
|
82
|
+
const orgs = await tui.spinner({
|
|
83
|
+
message: 'Fetching organizations...',
|
|
84
|
+
clearOnSuccess: true,
|
|
85
|
+
callback: () => listOrganizations(apiClient),
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
if (orgs.length === 0) {
|
|
89
|
+
tui.fatal('No organizations found for your account');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Check GitHub status for each org
|
|
93
|
+
const orgStatuses = await tui.spinner({
|
|
94
|
+
message: 'Checking GitHub integration status...',
|
|
95
|
+
clearOnSuccess: true,
|
|
96
|
+
callback: async () => {
|
|
97
|
+
const statuses = await Promise.all(
|
|
98
|
+
orgs.map(async (org) => {
|
|
99
|
+
const status = await getGithubIntegrationStatus(apiClient, org.id);
|
|
100
|
+
return {
|
|
101
|
+
...org,
|
|
102
|
+
connected: status.connected,
|
|
103
|
+
integrations: status.integrations,
|
|
104
|
+
};
|
|
105
|
+
})
|
|
106
|
+
);
|
|
107
|
+
return statuses;
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
// Flatten all integrations across orgs
|
|
112
|
+
const allIntegrations: Array<{
|
|
113
|
+
orgId: string;
|
|
114
|
+
orgName: string;
|
|
115
|
+
integration: GithubIntegration;
|
|
116
|
+
}> = [];
|
|
117
|
+
|
|
118
|
+
for (const org of orgStatuses) {
|
|
119
|
+
for (const integration of org.integrations) {
|
|
120
|
+
allIntegrations.push({
|
|
121
|
+
orgId: org.id,
|
|
122
|
+
orgName: org.name,
|
|
123
|
+
integration,
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (allIntegrations.length === 0) {
|
|
129
|
+
if (!options.json) {
|
|
130
|
+
tui.newline();
|
|
131
|
+
tui.info('No GitHub accounts are connected.');
|
|
132
|
+
}
|
|
133
|
+
return { removed: false };
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Build choices showing GitHub account and org
|
|
137
|
+
const choices = allIntegrations.map((item) => ({
|
|
138
|
+
name: `${tui.bold(item.integration.githubAccountName)} ${tui.muted(`(${item.integration.githubAccountType})`)} → ${tui.bold(item.orgName)}`,
|
|
139
|
+
value: `${item.orgId}:${item.integration.id}`,
|
|
140
|
+
}));
|
|
141
|
+
|
|
142
|
+
// Show picker
|
|
143
|
+
const response = await enquirer.prompt<{ selection: string }>({
|
|
144
|
+
type: 'select',
|
|
145
|
+
name: 'selection',
|
|
146
|
+
message: 'Select a GitHub account to remove',
|
|
147
|
+
choices,
|
|
148
|
+
result(name: string) {
|
|
149
|
+
// Return the value (IDs) instead of the display name
|
|
150
|
+
const choice = choices.find((c) => c.name === name);
|
|
151
|
+
return choice?.value ?? name;
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
const colonIdx = response.selection.indexOf(':');
|
|
156
|
+
if (colonIdx === -1) {
|
|
157
|
+
logger.fatal('Invalid selection format');
|
|
158
|
+
}
|
|
159
|
+
const orgId = response.selection.slice(0, colonIdx);
|
|
160
|
+
const integrationId = response.selection.slice(colonIdx + 1);
|
|
161
|
+
const selected = allIntegrations.find(
|
|
162
|
+
(i) => i.orgId === orgId && i.integration.id === integrationId
|
|
163
|
+
);
|
|
164
|
+
const displayName = selected
|
|
165
|
+
? `${tui.bold(selected.integration.githubAccountName)} from ${tui.bold(selected.orgName)}`
|
|
166
|
+
: response.selection;
|
|
167
|
+
|
|
168
|
+
// Confirm
|
|
169
|
+
if (!opts.confirm) {
|
|
170
|
+
const confirmed = await tui.confirm(`Are you sure you want to remove ${displayName}?`);
|
|
171
|
+
|
|
172
|
+
if (!confirmed) {
|
|
173
|
+
tui.newline();
|
|
174
|
+
tui.info('Cancelled');
|
|
175
|
+
return { removed: false };
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
await tui.spinner({
|
|
180
|
+
message: 'Removing GitHub account...',
|
|
181
|
+
clearOnSuccess: true,
|
|
182
|
+
callback: () => disconnectGithubIntegration(apiClient, orgId, integrationId),
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
if (!options.json) {
|
|
186
|
+
tui.newline();
|
|
187
|
+
tui.success(`Removed ${displayName}`);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return { removed: true, orgId, integrationId };
|
|
191
|
+
} catch (error) {
|
|
192
|
+
// Handle user cancellation (Ctrl+C)
|
|
193
|
+
const isCancel =
|
|
194
|
+
error === '' ||
|
|
195
|
+
(error instanceof Error &&
|
|
196
|
+
(error.message === '' || error.message === 'User cancelled'));
|
|
197
|
+
|
|
198
|
+
if (isCancel) {
|
|
199
|
+
tui.newline();
|
|
200
|
+
tui.info('Cancelled');
|
|
201
|
+
return { removed: false };
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
logger.trace(error);
|
|
205
|
+
return logger.fatal(
|
|
206
|
+
'Failed to remove GitHub account: %s',
|
|
207
|
+
error,
|
|
208
|
+
ErrorCode.INTEGRATION_FAILED
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
},
|
|
212
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { createCommand } from '../../types';
|
|
2
|
+
import { accountCommand } from './account';
|
|
3
|
+
import { linkSubcommand } from './link';
|
|
4
|
+
import { listSubcommand } from './list';
|
|
5
|
+
import { unlinkSubcommand } from './unlink';
|
|
6
|
+
import { statusSubcommand } from './status';
|
|
7
|
+
|
|
8
|
+
export const gitCommand = createCommand({
|
|
9
|
+
name: 'git',
|
|
10
|
+
description: 'Manage GitHub integration and repository connections',
|
|
11
|
+
subcommands: [
|
|
12
|
+
accountCommand,
|
|
13
|
+
linkSubcommand,
|
|
14
|
+
listSubcommand,
|
|
15
|
+
unlinkSubcommand,
|
|
16
|
+
statusSubcommand,
|
|
17
|
+
],
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
export default gitCommand;
|