@agentuity/cli 0.0.110 → 0.0.112

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.
Files changed (258) hide show
  1. package/bin/cli.ts +4 -0
  2. package/dist/agents-docs.d.ts +5 -4
  3. package/dist/agents-docs.d.ts.map +1 -1
  4. package/dist/agents-docs.js +28 -8
  5. package/dist/agents-docs.js.map +1 -1
  6. package/dist/cli.d.ts.map +1 -1
  7. package/dist/cli.js +19 -4
  8. package/dist/cli.js.map +1 -1
  9. package/dist/cmd/auth/apikey.d.ts +2 -0
  10. package/dist/cmd/auth/apikey.d.ts.map +1 -0
  11. package/dist/cmd/auth/apikey.js +31 -0
  12. package/dist/cmd/auth/apikey.js.map +1 -0
  13. package/dist/cmd/auth/index.d.ts.map +1 -1
  14. package/dist/cmd/auth/index.js +9 -1
  15. package/dist/cmd/auth/index.js.map +1 -1
  16. package/dist/cmd/build/ast.d.ts.map +1 -1
  17. package/dist/cmd/build/ast.js +103 -2
  18. package/dist/cmd/build/ast.js.map +1 -1
  19. package/dist/cmd/build/entry-generator.d.ts +2 -1
  20. package/dist/cmd/build/entry-generator.d.ts.map +1 -1
  21. package/dist/cmd/build/entry-generator.js +152 -9
  22. package/dist/cmd/build/entry-generator.js.map +1 -1
  23. package/dist/cmd/build/vite/agent-discovery.d.ts +1 -1
  24. package/dist/cmd/build/vite/agent-discovery.d.ts.map +1 -1
  25. package/dist/cmd/build/vite/agent-discovery.js +7 -6
  26. package/dist/cmd/build/vite/agent-discovery.js.map +1 -1
  27. package/dist/cmd/build/vite/index.d.ts.map +1 -1
  28. package/dist/cmd/build/vite/index.js +3 -2
  29. package/dist/cmd/build/vite/index.js.map +1 -1
  30. package/dist/cmd/build/vite/metadata-generator.js +1 -1
  31. package/dist/cmd/build/vite/metadata-generator.js.map +1 -1
  32. package/dist/cmd/build/vite/registry-generator.d.ts +1 -1
  33. package/dist/cmd/build/vite/registry-generator.d.ts.map +1 -1
  34. package/dist/cmd/build/vite/registry-generator.js +115 -23
  35. package/dist/cmd/build/vite/registry-generator.js.map +1 -1
  36. package/dist/cmd/build/vite/route-discovery.d.ts +6 -0
  37. package/dist/cmd/build/vite/route-discovery.d.ts.map +1 -1
  38. package/dist/cmd/build/vite/route-discovery.js +19 -0
  39. package/dist/cmd/build/vite/route-discovery.js.map +1 -1
  40. package/dist/cmd/build/vite/vite-builder.d.ts.map +1 -1
  41. package/dist/cmd/build/vite/vite-builder.js +3 -2
  42. package/dist/cmd/build/vite/vite-builder.js.map +1 -1
  43. package/dist/cmd/cloud/deploy-fork.d.ts +32 -0
  44. package/dist/cmd/cloud/deploy-fork.d.ts.map +1 -0
  45. package/dist/cmd/cloud/deploy-fork.js +258 -0
  46. package/dist/cmd/cloud/deploy-fork.js.map +1 -0
  47. package/dist/cmd/cloud/deploy.d.ts.map +1 -1
  48. package/dist/cmd/cloud/deploy.js +125 -4
  49. package/dist/cmd/cloud/deploy.js.map +1 -1
  50. package/dist/cmd/cloud/sandbox/create.d.ts.map +1 -1
  51. package/dist/cmd/cloud/sandbox/create.js +18 -0
  52. package/dist/cmd/cloud/sandbox/create.js.map +1 -1
  53. package/dist/cmd/cloud/sandbox/delete.d.ts.map +1 -1
  54. package/dist/cmd/cloud/sandbox/delete.js +2 -6
  55. package/dist/cmd/cloud/sandbox/delete.js.map +1 -1
  56. package/dist/cmd/cloud/sandbox/download.d.ts +3 -0
  57. package/dist/cmd/cloud/sandbox/download.d.ts.map +1 -0
  58. package/dist/cmd/cloud/sandbox/download.js +89 -0
  59. package/dist/cmd/cloud/sandbox/download.js.map +1 -0
  60. package/dist/cmd/cloud/sandbox/env.d.ts +3 -0
  61. package/dist/cmd/cloud/sandbox/env.d.ts.map +1 -0
  62. package/dist/cmd/cloud/sandbox/env.js +90 -0
  63. package/dist/cmd/cloud/sandbox/env.js.map +1 -0
  64. package/dist/cmd/cloud/sandbox/get.d.ts.map +1 -1
  65. package/dist/cmd/cloud/sandbox/get.js +24 -0
  66. package/dist/cmd/cloud/sandbox/get.js.map +1 -1
  67. package/dist/cmd/cloud/sandbox/index.d.ts.map +1 -1
  68. package/dist/cmd/cloud/sandbox/index.js +14 -0
  69. package/dist/cmd/cloud/sandbox/index.js.map +1 -1
  70. package/dist/cmd/cloud/sandbox/ls.d.ts +3 -0
  71. package/dist/cmd/cloud/sandbox/ls.d.ts.map +1 -0
  72. package/dist/cmd/cloud/sandbox/ls.js +119 -0
  73. package/dist/cmd/cloud/sandbox/ls.js.map +1 -0
  74. package/dist/cmd/cloud/sandbox/mkdir.d.ts +3 -0
  75. package/dist/cmd/cloud/sandbox/mkdir.d.ts.map +1 -0
  76. package/dist/cmd/cloud/sandbox/mkdir.js +59 -0
  77. package/dist/cmd/cloud/sandbox/mkdir.js.map +1 -0
  78. package/dist/cmd/cloud/sandbox/rm.d.ts +3 -0
  79. package/dist/cmd/cloud/sandbox/rm.d.ts.map +1 -0
  80. package/dist/cmd/cloud/sandbox/rm.js +45 -0
  81. package/dist/cmd/cloud/sandbox/rm.js.map +1 -0
  82. package/dist/cmd/cloud/sandbox/rmdir.d.ts +3 -0
  83. package/dist/cmd/cloud/sandbox/rmdir.d.ts.map +1 -0
  84. package/dist/cmd/cloud/sandbox/rmdir.js +59 -0
  85. package/dist/cmd/cloud/sandbox/rmdir.js.map +1 -0
  86. package/dist/cmd/cloud/sandbox/snapshot/create.d.ts.map +1 -1
  87. package/dist/cmd/cloud/sandbox/snapshot/create.js +0 -2
  88. package/dist/cmd/cloud/sandbox/snapshot/create.js.map +1 -1
  89. package/dist/cmd/cloud/sandbox/snapshot/get.d.ts.map +1 -1
  90. package/dist/cmd/cloud/sandbox/snapshot/get.js +0 -2
  91. package/dist/cmd/cloud/sandbox/snapshot/get.js.map +1 -1
  92. package/dist/cmd/cloud/sandbox/snapshot/list.d.ts.map +1 -1
  93. package/dist/cmd/cloud/sandbox/snapshot/list.js +0 -3
  94. package/dist/cmd/cloud/sandbox/snapshot/list.js.map +1 -1
  95. package/dist/cmd/cloud/sandbox/upload.d.ts +3 -0
  96. package/dist/cmd/cloud/sandbox/upload.d.ts.map +1 -0
  97. package/dist/cmd/cloud/sandbox/upload.js +77 -0
  98. package/dist/cmd/cloud/sandbox/upload.js.map +1 -0
  99. package/dist/cmd/cloud/ssh.d.ts.map +1 -1
  100. package/dist/cmd/cloud/ssh.js +9 -3
  101. package/dist/cmd/cloud/ssh.js.map +1 -1
  102. package/dist/cmd/dev/index.d.ts.map +1 -1
  103. package/dist/cmd/dev/index.js +34 -19
  104. package/dist/cmd/dev/index.js.map +1 -1
  105. package/dist/cmd/dev/sync.d.ts.map +1 -1
  106. package/dist/cmd/dev/sync.js +8 -14
  107. package/dist/cmd/dev/sync.js.map +1 -1
  108. package/dist/cmd/git/account/add.d.ts +17 -0
  109. package/dist/cmd/git/account/add.d.ts.map +1 -0
  110. package/dist/cmd/git/account/add.js +244 -0
  111. package/dist/cmd/git/account/add.js.map +1 -0
  112. package/dist/cmd/git/account/index.d.ts +3 -0
  113. package/dist/cmd/git/account/index.d.ts.map +1 -0
  114. package/dist/cmd/git/account/index.js +11 -0
  115. package/dist/cmd/git/account/index.js.map +1 -0
  116. package/dist/cmd/git/account/list.d.ts +2 -0
  117. package/dist/cmd/git/account/list.d.ts.map +1 -0
  118. package/dist/cmd/git/account/list.js +111 -0
  119. package/dist/cmd/git/account/list.js.map +1 -0
  120. package/dist/cmd/git/account/remove.d.ts +2 -0
  121. package/dist/cmd/git/account/remove.d.ts.map +1 -0
  122. package/dist/cmd/git/account/remove.js +171 -0
  123. package/dist/cmd/git/account/remove.js.map +1 -0
  124. package/dist/cmd/git/index.d.ts +3 -0
  125. package/dist/cmd/git/index.d.ts.map +1 -0
  126. package/dist/cmd/git/index.js +19 -0
  127. package/dist/cmd/git/index.js.map +1 -0
  128. package/dist/cmd/git/link.d.ts +32 -0
  129. package/dist/cmd/git/link.d.ts.map +1 -0
  130. package/dist/cmd/git/link.js +357 -0
  131. package/dist/cmd/git/link.js.map +1 -0
  132. package/dist/cmd/git/list.d.ts +2 -0
  133. package/dist/cmd/git/list.d.ts.map +1 -0
  134. package/dist/cmd/git/list.js +137 -0
  135. package/dist/cmd/git/list.js.map +1 -0
  136. package/dist/cmd/git/status.d.ts +2 -0
  137. package/dist/cmd/git/status.d.ts.map +1 -0
  138. package/dist/cmd/git/status.js +119 -0
  139. package/dist/cmd/git/status.js.map +1 -0
  140. package/dist/cmd/git/unlink.d.ts +2 -0
  141. package/dist/cmd/git/unlink.d.ts.map +1 -0
  142. package/dist/cmd/git/unlink.js +98 -0
  143. package/dist/cmd/git/unlink.js.map +1 -0
  144. package/dist/cmd/index.d.ts.map +1 -1
  145. package/dist/cmd/index.js +2 -0
  146. package/dist/cmd/index.js.map +1 -1
  147. package/dist/cmd/integration/api.d.ts +61 -0
  148. package/dist/cmd/integration/api.d.ts.map +1 -0
  149. package/dist/cmd/integration/api.js +176 -0
  150. package/dist/cmd/integration/api.js.map +1 -0
  151. package/dist/cmd/integration/github/connect.d.ts +2 -0
  152. package/dist/cmd/integration/github/connect.d.ts.map +1 -0
  153. package/dist/cmd/integration/github/connect.js +197 -0
  154. package/dist/cmd/integration/github/connect.js.map +1 -0
  155. package/dist/cmd/integration/github/disconnect.d.ts +2 -0
  156. package/dist/cmd/integration/github/disconnect.d.ts.map +1 -0
  157. package/dist/cmd/integration/github/disconnect.js +121 -0
  158. package/dist/cmd/integration/github/disconnect.js.map +1 -0
  159. package/dist/cmd/integration/github/index.d.ts +2 -0
  160. package/dist/cmd/integration/github/index.d.ts.map +1 -0
  161. package/dist/cmd/integration/github/index.js +21 -0
  162. package/dist/cmd/integration/github/index.js.map +1 -0
  163. package/dist/cmd/integration/index.d.ts +2 -0
  164. package/dist/cmd/integration/index.d.ts.map +1 -0
  165. package/dist/cmd/integration/index.js +16 -0
  166. package/dist/cmd/integration/index.js.map +1 -0
  167. package/dist/config.d.ts +2 -0
  168. package/dist/config.d.ts.map +1 -1
  169. package/dist/config.js +25 -1
  170. package/dist/config.js.map +1 -1
  171. package/dist/errors.d.ts +2 -1
  172. package/dist/errors.d.ts.map +1 -1
  173. package/dist/errors.js +5 -0
  174. package/dist/errors.js.map +1 -1
  175. package/dist/log-collector.d.ts +30 -0
  176. package/dist/log-collector.d.ts.map +1 -0
  177. package/dist/log-collector.js +74 -0
  178. package/dist/log-collector.js.map +1 -0
  179. package/dist/output.d.ts.map +1 -1
  180. package/dist/output.js +2 -1
  181. package/dist/output.js.map +1 -1
  182. package/dist/steps.d.ts.map +1 -1
  183. package/dist/steps.js +48 -3
  184. package/dist/steps.js.map +1 -1
  185. package/dist/tui/box.d.ts.map +1 -1
  186. package/dist/tui/box.js +1 -6
  187. package/dist/tui/box.js.map +1 -1
  188. package/dist/tui/symbols.d.ts.map +1 -1
  189. package/dist/tui/symbols.js +4 -0
  190. package/dist/tui/symbols.js.map +1 -1
  191. package/dist/tui.d.ts +21 -12
  192. package/dist/tui.d.ts.map +1 -1
  193. package/dist/tui.js +74 -25
  194. package/dist/tui.js.map +1 -1
  195. package/dist/types.d.ts +73 -1
  196. package/dist/types.d.ts.map +1 -1
  197. package/dist/types.js +4 -0
  198. package/dist/types.js.map +1 -1
  199. package/dist/typescript-errors.d.ts.map +1 -1
  200. package/dist/typescript-errors.js +2 -2
  201. package/dist/typescript-errors.js.map +1 -1
  202. package/package.json +6 -6
  203. package/src/agents-docs.ts +42 -8
  204. package/src/cli.ts +20 -4
  205. package/src/cmd/auth/apikey.ts +36 -0
  206. package/src/cmd/auth/index.ts +9 -1
  207. package/src/cmd/build/ast.ts +120 -2
  208. package/src/cmd/build/entry-generator.ts +157 -10
  209. package/src/cmd/build/vite/agent-discovery.ts +8 -5
  210. package/src/cmd/build/vite/index.ts +3 -2
  211. package/src/cmd/build/vite/metadata-generator.ts +1 -1
  212. package/src/cmd/build/vite/registry-generator.ts +125 -24
  213. package/src/cmd/build/vite/route-discovery.ts +20 -0
  214. package/src/cmd/build/vite/vite-builder.ts +3 -2
  215. package/src/cmd/cloud/deploy-fork.ts +296 -0
  216. package/src/cmd/cloud/deploy.ts +148 -4
  217. package/src/cmd/cloud/sandbox/create.ts +22 -0
  218. package/src/cmd/cloud/sandbox/delete.ts +2 -6
  219. package/src/cmd/cloud/sandbox/download.ts +96 -0
  220. package/src/cmd/cloud/sandbox/env.ts +104 -0
  221. package/src/cmd/cloud/sandbox/get.ts +22 -0
  222. package/src/cmd/cloud/sandbox/index.ts +14 -0
  223. package/src/cmd/cloud/sandbox/ls.ts +126 -0
  224. package/src/cmd/cloud/sandbox/mkdir.ts +65 -0
  225. package/src/cmd/cloud/sandbox/rm.ts +51 -0
  226. package/src/cmd/cloud/sandbox/rmdir.ts +65 -0
  227. package/src/cmd/cloud/sandbox/snapshot/create.ts +0 -2
  228. package/src/cmd/cloud/sandbox/snapshot/get.ts +0 -2
  229. package/src/cmd/cloud/sandbox/snapshot/list.ts +0 -3
  230. package/src/cmd/cloud/sandbox/upload.ts +83 -0
  231. package/src/cmd/cloud/ssh.ts +13 -3
  232. package/src/cmd/dev/index.ts +49 -31
  233. package/src/cmd/dev/sync.ts +26 -30
  234. package/src/cmd/git/account/add.ts +317 -0
  235. package/src/cmd/git/account/index.ts +12 -0
  236. package/src/cmd/git/account/list.ts +139 -0
  237. package/src/cmd/git/account/remove.ts +212 -0
  238. package/src/cmd/git/index.ts +20 -0
  239. package/src/cmd/git/link.ts +468 -0
  240. package/src/cmd/git/list.ts +161 -0
  241. package/src/cmd/git/status.ts +144 -0
  242. package/src/cmd/git/unlink.ts +117 -0
  243. package/src/cmd/index.ts +2 -0
  244. package/src/cmd/integration/api.ts +379 -0
  245. package/src/cmd/integration/github/connect.ts +242 -0
  246. package/src/cmd/integration/github/disconnect.ts +149 -0
  247. package/src/cmd/integration/github/index.ts +21 -0
  248. package/src/cmd/integration/index.ts +16 -0
  249. package/src/config.ts +35 -1
  250. package/src/errors.ts +7 -0
  251. package/src/log-collector.ts +77 -0
  252. package/src/output.ts +2 -1
  253. package/src/steps.ts +52 -4
  254. package/src/tui/box.ts +1 -7
  255. package/src/tui/symbols.ts +5 -0
  256. package/src/tui.ts +77 -25
  257. package/src/types.ts +89 -0
  258. package/src/typescript-errors.ts +2 -1
@@ -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;