@agentuity/cli 1.0.14 → 1.0.15

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 (129) hide show
  1. package/dist/agent-detection.js +2 -2
  2. package/dist/agent-detection.js.map +1 -1
  3. package/dist/banner.js +2 -2
  4. package/dist/banner.js.map +1 -1
  5. package/dist/bun-path.d.ts.map +1 -1
  6. package/dist/bun-path.js +2 -1
  7. package/dist/bun-path.js.map +1 -1
  8. package/dist/cmd/build/ast.d.ts.map +1 -1
  9. package/dist/cmd/build/ast.js +87 -14
  10. package/dist/cmd/build/ast.js.map +1 -1
  11. package/dist/cmd/build/vite/agent-discovery.d.ts.map +1 -1
  12. package/dist/cmd/build/vite/agent-discovery.js +3 -2
  13. package/dist/cmd/build/vite/agent-discovery.js.map +1 -1
  14. package/dist/cmd/build/vite/metadata-generator.d.ts.map +1 -1
  15. package/dist/cmd/build/vite/metadata-generator.js +2 -1
  16. package/dist/cmd/build/vite/metadata-generator.js.map +1 -1
  17. package/dist/cmd/build/vite/registry-generator.d.ts.map +1 -1
  18. package/dist/cmd/build/vite/registry-generator.js +9 -7
  19. package/dist/cmd/build/vite/registry-generator.js.map +1 -1
  20. package/dist/cmd/build/vite/route-discovery.d.ts.map +1 -1
  21. package/dist/cmd/build/vite/route-discovery.js +3 -2
  22. package/dist/cmd/build/vite/route-discovery.js.map +1 -1
  23. package/dist/cmd/cloud/deploy.d.ts.map +1 -1
  24. package/dist/cmd/cloud/deploy.js +19 -21
  25. package/dist/cmd/cloud/deploy.js.map +1 -1
  26. package/dist/cmd/cloud/env/delete.d.ts.map +1 -1
  27. package/dist/cmd/cloud/env/delete.js +3 -26
  28. package/dist/cmd/cloud/env/delete.js.map +1 -1
  29. package/dist/cmd/cloud/env/import.d.ts.map +1 -1
  30. package/dist/cmd/cloud/env/import.js +3 -16
  31. package/dist/cmd/cloud/env/import.js.map +1 -1
  32. package/dist/cmd/cloud/env/set.d.ts.map +1 -1
  33. package/dist/cmd/cloud/env/set.js +3 -19
  34. package/dist/cmd/cloud/env/set.js.map +1 -1
  35. package/dist/cmd/cloud/sandbox/cp.d.ts.map +1 -1
  36. package/dist/cmd/cloud/sandbox/cp.js +2 -1
  37. package/dist/cmd/cloud/sandbox/cp.js.map +1 -1
  38. package/dist/cmd/git/account/add.d.ts +6 -8
  39. package/dist/cmd/git/account/add.d.ts.map +1 -1
  40. package/dist/cmd/git/account/add.js +37 -151
  41. package/dist/cmd/git/account/add.js.map +1 -1
  42. package/dist/cmd/git/account/index.d.ts +0 -1
  43. package/dist/cmd/git/account/index.d.ts.map +1 -1
  44. package/dist/cmd/git/account/index.js +3 -4
  45. package/dist/cmd/git/account/index.js.map +1 -1
  46. package/dist/cmd/git/account/list.d.ts.map +1 -1
  47. package/dist/cmd/git/account/list.js +35 -67
  48. package/dist/cmd/git/account/list.js.map +1 -1
  49. package/dist/cmd/git/account/remove.d.ts.map +1 -1
  50. package/dist/cmd/git/account/remove.js +42 -84
  51. package/dist/cmd/git/account/remove.js.map +1 -1
  52. package/dist/cmd/git/api.d.ts +19 -23
  53. package/dist/cmd/git/api.d.ts.map +1 -1
  54. package/dist/cmd/git/api.js +38 -56
  55. package/dist/cmd/git/api.js.map +1 -1
  56. package/dist/cmd/git/identity/connect.d.ts +15 -0
  57. package/dist/cmd/git/identity/connect.d.ts.map +1 -0
  58. package/dist/cmd/git/identity/connect.js +135 -0
  59. package/dist/cmd/git/identity/connect.js.map +1 -0
  60. package/dist/cmd/git/identity/disconnect.d.ts +2 -0
  61. package/dist/cmd/git/identity/disconnect.d.ts.map +1 -0
  62. package/dist/cmd/git/identity/disconnect.js +83 -0
  63. package/dist/cmd/git/identity/disconnect.js.map +1 -0
  64. package/dist/cmd/git/identity/index.d.ts +2 -0
  65. package/dist/cmd/git/identity/index.d.ts.map +1 -0
  66. package/dist/cmd/git/identity/index.js +10 -0
  67. package/dist/cmd/git/identity/index.js.map +1 -0
  68. package/dist/cmd/git/identity/status.d.ts +2 -0
  69. package/dist/cmd/git/identity/status.d.ts.map +1 -0
  70. package/dist/cmd/git/identity/status.js +77 -0
  71. package/dist/cmd/git/identity/status.js.map +1 -0
  72. package/dist/cmd/git/index.d.ts +0 -1
  73. package/dist/cmd/git/index.d.ts.map +1 -1
  74. package/dist/cmd/git/index.js +3 -2
  75. package/dist/cmd/git/index.js.map +1 -1
  76. package/dist/cmd/git/link.d.ts +2 -3
  77. package/dist/cmd/git/link.d.ts.map +1 -1
  78. package/dist/cmd/git/link.js +22 -28
  79. package/dist/cmd/git/link.js.map +1 -1
  80. package/dist/cmd/git/list.d.ts.map +1 -1
  81. package/dist/cmd/git/list.js +42 -55
  82. package/dist/cmd/git/list.js.map +1 -1
  83. package/dist/cmd/git/status.d.ts.map +1 -1
  84. package/dist/cmd/git/status.js +51 -38
  85. package/dist/cmd/git/status.js.map +1 -1
  86. package/dist/config.d.ts.map +1 -1
  87. package/dist/config.js +14 -4
  88. package/dist/config.js.map +1 -1
  89. package/dist/utils/detectSubagent.d.ts.map +1 -1
  90. package/dist/utils/detectSubagent.js +3 -0
  91. package/dist/utils/detectSubagent.js.map +1 -1
  92. package/dist/utils/normalize-path.d.ts +11 -0
  93. package/dist/utils/normalize-path.d.ts.map +1 -0
  94. package/dist/utils/normalize-path.js +13 -0
  95. package/dist/utils/normalize-path.js.map +1 -0
  96. package/dist/utils/zip.d.ts.map +1 -1
  97. package/dist/utils/zip.js +2 -1
  98. package/dist/utils/zip.js.map +1 -1
  99. package/package.json +6 -6
  100. package/src/agent-detection.ts +2 -2
  101. package/src/banner.ts +2 -2
  102. package/src/bun-path.ts +2 -1
  103. package/src/cmd/build/ast.ts +96 -15
  104. package/src/cmd/build/vite/agent-discovery.ts +3 -2
  105. package/src/cmd/build/vite/metadata-generator.ts +2 -1
  106. package/src/cmd/build/vite/registry-generator.ts +9 -7
  107. package/src/cmd/build/vite/route-discovery.ts +3 -2
  108. package/src/cmd/cloud/deploy.ts +54 -61
  109. package/src/cmd/cloud/env/delete.ts +3 -34
  110. package/src/cmd/cloud/env/import.ts +2 -18
  111. package/src/cmd/cloud/env/set.ts +2 -21
  112. package/src/cmd/cloud/sandbox/cp.ts +2 -1
  113. package/src/cmd/git/account/add.ts +51 -190
  114. package/src/cmd/git/account/index.ts +3 -5
  115. package/src/cmd/git/account/list.ts +51 -82
  116. package/src/cmd/git/account/remove.ts +45 -95
  117. package/src/cmd/git/api.ts +49 -111
  118. package/src/cmd/git/identity/connect.ts +178 -0
  119. package/src/cmd/git/identity/disconnect.ts +103 -0
  120. package/src/cmd/git/identity/index.ts +10 -0
  121. package/src/cmd/git/identity/status.ts +96 -0
  122. package/src/cmd/git/index.ts +3 -3
  123. package/src/cmd/git/link.ts +32 -35
  124. package/src/cmd/git/list.ts +48 -59
  125. package/src/cmd/git/status.ts +55 -40
  126. package/src/config.ts +14 -5
  127. package/src/utils/detectSubagent.ts +5 -0
  128. package/src/utils/normalize-path.ts +12 -0
  129. package/src/utils/zip.ts +2 -1
@@ -0,0 +1,103 @@
1
+ import { z } from 'zod';
2
+ import { getCommand } from '../../../command-prefix';
3
+ import { ErrorCode } from '../../../errors';
4
+ import * as tui from '../../../tui';
5
+ import { createSubcommand } from '../../../types';
6
+ import { disconnectGithubIntegration, getGithubIntegrationStatus } from '../api';
7
+
8
+ const DisconnectOptionsSchema = z.object({
9
+ confirm: z.boolean().optional().describe('Skip confirmation prompt'),
10
+ });
11
+
12
+ const DisconnectResponseSchema = z.object({
13
+ disconnected: z.boolean().describe('Whether the identity was disconnected'),
14
+ });
15
+
16
+ export const disconnectSubcommand = createSubcommand({
17
+ name: 'disconnect',
18
+ description: 'Disconnect your GitHub identity and all installations',
19
+ tags: ['mutating', 'destructive', 'slow'],
20
+ idempotent: false,
21
+ requires: { auth: true, apiClient: true },
22
+ schema: {
23
+ options: DisconnectOptionsSchema,
24
+ response: DisconnectResponseSchema,
25
+ },
26
+ examples: [
27
+ {
28
+ command: getCommand('git identity disconnect'),
29
+ description: 'Disconnect your GitHub identity',
30
+ },
31
+ {
32
+ command: getCommand('git identity disconnect --confirm'),
33
+ description: 'Disconnect without confirmation prompt',
34
+ },
35
+ ],
36
+
37
+ async handler(ctx) {
38
+ const { logger, apiClient, opts, options } = ctx;
39
+
40
+ try {
41
+ const status = await tui.spinner({
42
+ message: 'Checking GitHub connection...',
43
+ clearOnSuccess: true,
44
+ callback: () => getGithubIntegrationStatus(apiClient),
45
+ });
46
+
47
+ if (!status.connected || !status.identity) {
48
+ if (!options.json) {
49
+ tui.newline();
50
+ tui.info('No GitHub identity connected.');
51
+ }
52
+ return { disconnected: false };
53
+ }
54
+
55
+ if (!opts.confirm) {
56
+ tui.newline();
57
+ tui.output(
58
+ `Connected as ${tui.bold(status.identity.githubUsername)} with ${status.installations.length} installation${status.installations.length !== 1 ? 's' : ''}.`
59
+ );
60
+ tui.newline();
61
+
62
+ const confirmed = await tui.confirm(
63
+ 'Are you sure you want to disconnect your GitHub identity?'
64
+ );
65
+ if (!confirmed) {
66
+ tui.info('Cancelled');
67
+ return { disconnected: false };
68
+ }
69
+ }
70
+
71
+ await tui.spinner({
72
+ message: 'Disconnecting GitHub identity...',
73
+ clearOnSuccess: true,
74
+ callback: () => disconnectGithubIntegration(apiClient),
75
+ });
76
+
77
+ if (!options.json) {
78
+ tui.newline();
79
+ tui.success('Disconnected GitHub identity and all installations');
80
+ }
81
+
82
+ return { disconnected: true };
83
+ } catch (error) {
84
+ const isCancel =
85
+ error === '' ||
86
+ (error instanceof Error &&
87
+ (error.message === '' || error.message === 'User cancelled'));
88
+
89
+ if (isCancel) {
90
+ tui.newline();
91
+ tui.info('Cancelled');
92
+ return { disconnected: false };
93
+ }
94
+
95
+ logger.trace(error);
96
+ return logger.fatal(
97
+ 'Failed to disconnect GitHub identity: %s',
98
+ error,
99
+ ErrorCode.INTEGRATION_FAILED
100
+ );
101
+ }
102
+ },
103
+ });
@@ -0,0 +1,10 @@
1
+ import { createCommand } from '../../../types';
2
+ import { connectSubcommand } from './connect';
3
+ import { disconnectSubcommand } from './disconnect';
4
+ import { statusSubcommand } from './status';
5
+
6
+ export const identityCommand = createCommand({
7
+ name: 'identity',
8
+ description: 'Manage your GitHub identity',
9
+ subcommands: [connectSubcommand, disconnectSubcommand, statusSubcommand],
10
+ });
@@ -0,0 +1,96 @@
1
+ import { z } from 'zod';
2
+ import { getCommand } from '../../../command-prefix';
3
+ import { ErrorCode } from '../../../errors';
4
+ import * as tui from '../../../tui';
5
+ import { createSubcommand } from '../../../types';
6
+ import { getGithubIntegrationStatus } from '../api';
7
+
8
+ const StatusResponseSchema = z.object({
9
+ connected: z.boolean().describe('Whether a GitHub identity is connected'),
10
+ identity: z
11
+ .object({
12
+ githubUsername: z.string().describe('GitHub username'),
13
+ githubEmail: z.string().optional().describe('GitHub email'),
14
+ })
15
+ .nullable()
16
+ .describe('Connected GitHub identity'),
17
+ });
18
+
19
+ export const statusSubcommand = createSubcommand({
20
+ name: 'status',
21
+ description: 'Show your connected GitHub identity',
22
+ tags: ['read-only'],
23
+ idempotent: true,
24
+ requires: { auth: true, apiClient: true },
25
+ schema: {
26
+ response: StatusResponseSchema,
27
+ },
28
+ examples: [
29
+ {
30
+ command: getCommand('git identity status'),
31
+ description: 'Show your connected GitHub identity',
32
+ },
33
+ {
34
+ command: getCommand('--json git identity status'),
35
+ description: 'Show identity in JSON format',
36
+ },
37
+ ],
38
+
39
+ async handler(ctx) {
40
+ const { logger, apiClient, options } = ctx;
41
+
42
+ try {
43
+ const status = await tui.spinner({
44
+ message: 'Checking GitHub connection...',
45
+ clearOnSuccess: true,
46
+ callback: () => getGithubIntegrationStatus(apiClient),
47
+ });
48
+
49
+ const result = {
50
+ connected: status.connected,
51
+ identity: status.identity
52
+ ? {
53
+ githubUsername: status.identity.githubUsername,
54
+ githubEmail: status.identity.githubEmail,
55
+ }
56
+ : null,
57
+ };
58
+
59
+ if (options.json) {
60
+ return result;
61
+ }
62
+
63
+ tui.newline();
64
+ tui.output(tui.bold('GitHub Identity'));
65
+ tui.newline();
66
+
67
+ if (!status.connected || !status.identity) {
68
+ tui.output(
69
+ tui.muted(
70
+ `No GitHub identity connected. Run ${tui.bold('agentuity git identity connect')} to connect one.`
71
+ )
72
+ );
73
+ tui.newline();
74
+ return result;
75
+ }
76
+
77
+ tui.output(
78
+ ` ${tui.colorSuccess('✓')} Connected as ${tui.bold(status.identity.githubUsername)}`
79
+ );
80
+ if (status.identity.githubEmail) {
81
+ tui.output(` Email: ${status.identity.githubEmail}`);
82
+ }
83
+
84
+ tui.newline();
85
+
86
+ return result;
87
+ } catch (error) {
88
+ logger.trace(error);
89
+ return logger.fatal(
90
+ 'Failed to check GitHub identity: %s',
91
+ error,
92
+ ErrorCode.INTEGRATION_FAILED
93
+ );
94
+ }
95
+ },
96
+ });
@@ -1,14 +1,16 @@
1
1
  import { createCommand } from '../../types';
2
2
  import { accountCommand } from './account';
3
+ import { identityCommand } from './identity';
3
4
  import { linkSubcommand } from './link';
4
5
  import { listSubcommand } from './list';
5
- import { unlinkSubcommand } from './unlink';
6
6
  import { statusSubcommand } from './status';
7
+ import { unlinkSubcommand } from './unlink';
7
8
 
8
9
  export const gitCommand = createCommand({
9
10
  name: 'git',
10
11
  description: 'Manage GitHub integration and repository connections',
11
12
  subcommands: [
13
+ identityCommand,
12
14
  accountCommand,
13
15
  linkSubcommand,
14
16
  listSubcommand,
@@ -16,5 +18,3 @@ export const gitCommand = createCommand({
16
18
  statusSubcommand,
17
19
  ],
18
20
  });
19
-
20
- export default gitCommand;
@@ -1,19 +1,20 @@
1
- import { createSubcommand, type Config } from '../../types';
2
- import * as tui from '../../tui';
3
- import { getCommand } from '../../command-prefix';
4
- import { ErrorCode } from '../../errors';
1
+ import type { Logger } from '@agentuity/core';
5
2
  import enquirer from 'enquirer';
6
3
  import { z } from 'zod';
4
+ import type { APIClient } from '../../api';
5
+ import { getCommand } from '../../command-prefix';
6
+ import { ErrorCode } from '../../errors';
7
+ import * as tui from '../../tui';
8
+ import { type Config, createSubcommand } from '../../types';
7
9
  import {
10
+ type GithubInstallation,
11
+ type GithubRepo,
8
12
  getGithubIntegrationStatus,
9
- listGithubRepos,
10
- linkProjectToRepo,
11
13
  getProjectGithubStatus,
12
- type GithubRepo,
14
+ linkProjectToRepo,
15
+ listGithubRepos,
13
16
  } from './api';
14
- import type { APIClient } from '../../api';
15
- import type { Logger } from '@agentuity/core';
16
- import { runGitAccountConnect } from './account/add';
17
+ import { runGitIdentityConnect } from './identity/connect';
17
18
 
18
19
  export interface DetectedGitInfo {
19
20
  repo: string | null;
@@ -60,7 +61,6 @@ export function detectGitInfo(): DetectedGitInfo {
60
61
  export interface RunGitLinkOptions {
61
62
  apiClient: APIClient;
62
63
  projectId: string;
63
- orgId: string;
64
64
  logger: Logger;
65
65
  branchOption?: string;
66
66
  rootOption?: string;
@@ -84,7 +84,6 @@ export async function runGitLink(options: RunGitLinkOptions): Promise<RunGitLink
84
84
  const {
85
85
  apiClient,
86
86
  projectId,
87
- orgId,
88
87
  logger,
89
88
  branchOption,
90
89
  rootOption,
@@ -120,12 +119,12 @@ export async function runGitLink(options: RunGitLinkOptions): Promise<RunGitLink
120
119
  let githubStatus = await tui.spinner({
121
120
  message: 'Checking GitHub connection...',
122
121
  clearOnSuccess: true,
123
- callback: () => getGithubIntegrationStatus(apiClient, orgId),
122
+ callback: () => getGithubIntegrationStatus(apiClient),
124
123
  });
125
124
 
126
- if (!githubStatus.connected || githubStatus.integrations.length === 0) {
125
+ if (!githubStatus.connected || githubStatus.installations.length === 0) {
127
126
  tui.newline();
128
- tui.warning('No GitHub accounts connected to this organization.');
127
+ tui.warning('No GitHub accounts connected.');
129
128
  tui.newline();
130
129
 
131
130
  const wantConnect = await tui.confirm('Would you like to connect a GitHub account now?');
@@ -134,9 +133,8 @@ export async function runGitLink(options: RunGitLinkOptions): Promise<RunGitLink
134
133
  return { linked: false, cancelled: true };
135
134
  }
136
135
 
137
- const connectResult = await runGitAccountConnect({
136
+ const connectResult = await runGitIdentityConnect({
138
137
  apiClient,
139
- orgId,
140
138
  logger,
141
139
  config,
142
140
  });
@@ -148,9 +146,9 @@ export async function runGitLink(options: RunGitLinkOptions): Promise<RunGitLink
148
146
  return { linked: false, noGithubConnected: true };
149
147
  }
150
148
 
151
- githubStatus = await getGithubIntegrationStatus(apiClient, orgId);
149
+ githubStatus = await getGithubIntegrationStatus(apiClient);
152
150
 
153
- if (!githubStatus.connected || githubStatus.integrations.length === 0) {
151
+ if (!githubStatus.connected || githubStatus.installations.length === 0) {
154
152
  tui.error('GitHub connection failed. Please try again.');
155
153
  return { linked: false, noGithubConnected: true };
156
154
  }
@@ -165,7 +163,7 @@ export async function runGitLink(options: RunGitLinkOptions): Promise<RunGitLink
165
163
  const allRepos = await tui.spinner({
166
164
  message: 'Fetching available repositories...',
167
165
  clearOnSuccess: true,
168
- callback: () => listGithubRepos(apiClient, orgId),
166
+ callback: () => listGithubRepos(apiClient),
169
167
  });
170
168
 
171
169
  if (allRepos.length === 0) {
@@ -198,14 +196,16 @@ export async function runGitLink(options: RunGitLinkOptions): Promise<RunGitLink
198
196
  if (!selectedRepo) {
199
197
  let repos = allRepos;
200
198
 
201
- if (githubStatus.integrations.length > 1) {
199
+ if (githubStatus.installations.length > 1) {
202
200
  tui.newline();
203
201
 
204
- const accountChoices = githubStatus.integrations.map((integration) => ({
205
- name: integration.githubAccountName,
206
- value: integration.id,
207
- message: `${integration.githubAccountName} ${tui.muted(`(${integration.githubAccountType})`)}`,
208
- }));
202
+ const accountChoices = githubStatus.installations.map(
203
+ (installation: GithubInstallation) => ({
204
+ name: installation.accountName,
205
+ value: installation.integrationId ?? installation.installationId,
206
+ message: `${installation.accountName} ${tui.muted(`(${installation.accountType})`)}`,
207
+ })
208
+ );
209
209
 
210
210
  const accountResponse = await enquirer.prompt<{ integrationId: string }>({
211
211
  type: 'select',
@@ -213,8 +213,10 @@ export async function runGitLink(options: RunGitLinkOptions): Promise<RunGitLink
213
213
  message: 'Select a GitHub account',
214
214
  choices: accountChoices,
215
215
  result(name: string) {
216
- // Return the value (id) instead of the name
217
- const choice = accountChoices.find((c) => c.name === name);
216
+ // Return the value (integrationId) instead of the name
217
+ const choice = accountChoices.find(
218
+ (c: { name: string; value: string; message: string }) => c.name === name
219
+ );
218
220
  return choice?.value ?? name;
219
221
  },
220
222
  });
@@ -222,7 +224,7 @@ export async function runGitLink(options: RunGitLinkOptions): Promise<RunGitLink
222
224
  repos = await tui.spinner({
223
225
  message: 'Fetching repositories...',
224
226
  clearOnSuccess: true,
225
- callback: () => listGithubRepos(apiClient, orgId, accountResponse.integrationId),
227
+ callback: () => listGithubRepos(apiClient, accountResponse.integrationId),
226
228
  });
227
229
 
228
230
  if (repos.length === 0) {
@@ -254,7 +256,7 @@ export async function runGitLink(options: RunGitLinkOptions): Promise<RunGitLink
254
256
  }
255
257
 
256
258
  // Prompt for settings with defaults
257
- const defaultBranch = branchOption ?? gitInfo.branch ?? selectedRepo.defaultBranch;
259
+ const defaultBranch = branchOption ?? selectedRepo.defaultBranch;
258
260
  const defaultRoot = rootOption ?? '.';
259
261
 
260
262
  tui.newline();
@@ -309,7 +311,6 @@ export async function runGitLink(options: RunGitLinkOptions): Promise<RunGitLink
309
311
  autoDeploy: finalAutoDeploy,
310
312
  previewDeploy: finalPreviewDeploy,
311
313
  directory: directory === '.' ? undefined : directory,
312
- integrationId: selectedRepo.integrationId,
313
314
  }),
314
315
  });
315
316
 
@@ -414,9 +415,6 @@ export const linkSubcommand = createSubcommand({
414
415
 
415
416
  try {
416
417
  // Non-interactive mode when repo is provided
417
- // Note: integrationId is not passed in non-interactive mode. The API will
418
- // attempt to find a matching integration based on the repo owner. This may
419
- // fail if the org has multiple GitHub integrations with access to the same repo.
420
418
  if (opts.repo && opts.confirm) {
421
419
  const branch = opts.branch ?? 'main';
422
420
  const directory = opts.root === '.' ? undefined : opts.root;
@@ -446,7 +444,6 @@ export const linkSubcommand = createSubcommand({
446
444
  const result = await runGitLink({
447
445
  apiClient,
448
446
  projectId: project.projectId,
449
- orgId: project.orgId,
450
447
  logger,
451
448
  branchOption: opts.branch,
452
449
  rootOption: opts.root,
@@ -1,20 +1,18 @@
1
- import { createSubcommand } from '../../types';
2
- import * as tui from '../../tui';
3
- import { getCommand } from '../../command-prefix';
4
1
  import enquirer from 'enquirer';
5
2
  import { z } from 'zod';
6
- import { getGithubIntegrationStatus, listGithubRepos } from './api';
3
+ import { getCommand } from '../../command-prefix';
7
4
  import { ErrorCode } from '../../errors';
8
- import { listOrganizations } from '@agentuity/server';
5
+ import * as tui from '../../tui';
6
+ import { createSubcommand } from '../../types';
7
+ import { getGithubIntegrationStatus, listGithubRepos } from './api';
9
8
 
10
9
  const ListOptionsSchema = z.object({
11
- org: z.string().optional().describe('Organization ID to list repos for'),
12
- account: z.string().optional().describe('GitHub account/integration ID to filter by'),
10
+ account: z.string().optional().describe('GitHub account name to filter by'),
13
11
  });
14
12
 
15
13
  export const listSubcommand = createSubcommand({
16
14
  name: 'list',
17
- description: 'List GitHub repositories accessible to your organization',
15
+ description: 'List GitHub repositories accessible to your account',
18
16
  aliases: ['ls'],
19
17
  tags: ['read-only'],
20
18
  idempotent: true,
@@ -28,8 +26,8 @@ export const listSubcommand = createSubcommand({
28
26
  description: 'List all accessible GitHub repositories',
29
27
  },
30
28
  {
31
- command: getCommand('git list --org org_abc123'),
32
- description: 'List repos for a specific organization',
29
+ command: getCommand('git list --account my-org'),
30
+ description: 'List repos for a specific GitHub account',
33
31
  },
34
32
  {
35
33
  command: getCommand('--json git list'),
@@ -41,78 +39,69 @@ export const listSubcommand = createSubcommand({
41
39
  const { logger, apiClient, opts, options } = ctx;
42
40
 
43
41
  try {
44
- // Get orgs
45
- const orgs = await tui.spinner({
46
- message: 'Fetching organizations...',
47
- clearOnSuccess: true,
48
- callback: () => listOrganizations(apiClient),
49
- });
50
-
51
- if (orgs.length === 0) {
52
- tui.error('No organizations found');
53
- return [];
54
- }
55
-
56
- // Select org
57
- let orgId = opts.org;
58
- if (!orgId) {
59
- const firstOrg = orgs[0];
60
- if (orgs.length === 1 && firstOrg) {
61
- orgId = firstOrg.id;
62
- } else {
63
- tui.newline();
64
- const orgChoices = orgs.map((o) => ({
65
- name: o.id,
66
- message: o.name,
67
- }));
68
-
69
- const response = await enquirer.prompt<{ orgId: string }>({
70
- type: 'select',
71
- name: 'orgId',
72
- message: 'Select an organization',
73
- choices: orgChoices,
74
- });
75
- orgId = response.orgId;
76
- }
77
- }
78
-
79
- // Check GitHub integrations
42
+ // Check GitHub connection
80
43
  const githubStatus = await tui.spinner({
81
44
  message: 'Checking GitHub connection...',
82
45
  clearOnSuccess: true,
83
- callback: () => getGithubIntegrationStatus(apiClient, orgId!),
46
+ callback: () => getGithubIntegrationStatus(apiClient),
84
47
  });
85
48
 
86
- if (!githubStatus.connected || githubStatus.integrations.length === 0) {
49
+ if (!githubStatus.connected || githubStatus.installations.length === 0) {
87
50
  tui.newline();
88
- tui.error('No GitHub accounts connected to this organization.');
51
+ tui.error('No GitHub accounts connected.');
89
52
  console.log(tui.muted(`Run ${tui.bold('agentuity git account add')} to connect one`));
90
53
  return [];
91
54
  }
92
55
 
93
- // Select account if multiple and not specified
94
- let integrationId = opts.account;
95
- if (!integrationId && githubStatus.integrations.length > 1) {
56
+ // Select installation if multiple and not specified
57
+ let integrationId: string | undefined;
58
+
59
+ if (opts.account) {
60
+ // Match by account name
61
+ const matched = githubStatus.installations.find(
62
+ (inst) => inst.accountName.toLowerCase() === opts.account!.toLowerCase()
63
+ );
64
+ if (!matched) {
65
+ tui.newline();
66
+ tui.error(`No installation found for account "${opts.account}"`);
67
+ console.log(
68
+ tui.muted(
69
+ `Available: ${githubStatus.installations.map((i) => i.accountName).join(', ')}`
70
+ )
71
+ );
72
+ return [];
73
+ }
74
+ integrationId = matched.integrationId;
75
+ } else if (githubStatus.installations.length > 1) {
96
76
  tui.newline();
97
- const accountChoices = githubStatus.integrations.map((integration) => ({
98
- name: integration.id,
99
- message: `${integration.githubAccountName} ${tui.muted(`(${integration.githubAccountType})`)}`,
77
+ const accountChoices = githubStatus.installations.map((installation) => ({
78
+ name: installation.installationId,
79
+ message: `${installation.accountName} ${tui.muted(`(${installation.accountType})`)}`,
80
+ value: installation.integrationId,
100
81
  }));
101
82
 
102
- const response = await enquirer.prompt<{ integrationId: string }>({
83
+ const response = await enquirer.prompt<{ installationId: string }>({
103
84
  type: 'select',
104
- name: 'integrationId',
85
+ name: 'installationId',
105
86
  message: 'Select a GitHub account',
106
87
  choices: accountChoices,
88
+ result(name: string) {
89
+ // Return the value (integrationId) instead of the display name
90
+ const choice = accountChoices.find((c) => c.name === name);
91
+ return choice?.value ?? name;
92
+ },
107
93
  });
108
- integrationId = response.integrationId;
94
+ integrationId = response.installationId;
95
+ } else {
96
+ // Single installation — use its integrationId
97
+ integrationId = githubStatus.installations[0]?.integrationId;
109
98
  }
110
99
 
111
100
  // Fetch repos
112
101
  const repos = await tui.spinner({
113
102
  message: 'Fetching repositories...',
114
103
  clearOnSuccess: true,
115
- callback: () => listGithubRepos(apiClient, orgId!, integrationId),
104
+ callback: () => listGithubRepos(apiClient, integrationId),
116
105
  });
117
106
 
118
107
  if (repos.length === 0) {