@agentuity/cli 0.0.110 → 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/cli.d.ts.map +1 -1
- package/dist/cli.js +19 -4
- package/dist/cli.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.js +1 -1
- package/dist/cmd/build/vite/index.js.map +1 -1
- package/dist/cmd/build/vite/metadata-generator.js +1 -1
- 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 +70 -23
- 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.js +1 -1
- package/dist/cmd/build/vite/vite-builder.js.map +1 -1
- package/dist/cmd/cloud/deploy.d.ts.map +1 -1
- package/dist/cmd/cloud/deploy.js +63 -1
- package/dist/cmd/cloud/deploy.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 +17 -8
- 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/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 +2 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +4 -0
- package/dist/types.js.map +1 -1
- package/package.json +6 -6
- package/src/cli.ts +20 -4
- package/src/cmd/build/vite/agent-discovery.ts +4 -4
- package/src/cmd/build/vite/index.ts +1 -1
- package/src/cmd/build/vite/metadata-generator.ts +1 -1
- package/src/cmd/build/vite/registry-generator.ts +78 -24
- package/src/cmd/build/vite/route-discovery.ts +20 -0
- package/src/cmd/build/vite/vite-builder.ts +1 -1
- package/src/cmd/cloud/deploy.ts +78 -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 +32 -19
- 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/config.ts +34 -0
- package/src/errors.ts +7 -0
- package/src/types.ts +4 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { createSubcommand } from '../../types';
|
|
2
|
+
import * as tui from '../../tui';
|
|
3
|
+
import { getCommand } from '../../command-prefix';
|
|
4
|
+
import enquirer from 'enquirer';
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import { getGithubIntegrationStatus, listGithubRepos } from '../integration/api';
|
|
7
|
+
import { ErrorCode } from '../../errors';
|
|
8
|
+
import { listOrganizations } from '@agentuity/server';
|
|
9
|
+
|
|
10
|
+
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'),
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
export const listSubcommand = createSubcommand({
|
|
16
|
+
name: 'list',
|
|
17
|
+
description: 'List GitHub repositories accessible to your organization',
|
|
18
|
+
aliases: ['ls'],
|
|
19
|
+
tags: ['read-only'],
|
|
20
|
+
idempotent: true,
|
|
21
|
+
requires: { auth: true, apiClient: true },
|
|
22
|
+
schema: {
|
|
23
|
+
options: ListOptionsSchema,
|
|
24
|
+
},
|
|
25
|
+
examples: [
|
|
26
|
+
{
|
|
27
|
+
command: getCommand('git list'),
|
|
28
|
+
description: 'List all accessible GitHub repositories',
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
command: getCommand('git list --org org_abc123'),
|
|
32
|
+
description: 'List repos for a specific organization',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
command: getCommand('--json git list'),
|
|
36
|
+
description: 'List repos in JSON format',
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
|
|
40
|
+
async handler(ctx) {
|
|
41
|
+
const { logger, apiClient, opts, options } = ctx;
|
|
42
|
+
|
|
43
|
+
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
|
+
if (orgs.length === 1) {
|
|
60
|
+
orgId = orgs[0].id;
|
|
61
|
+
} else {
|
|
62
|
+
tui.newline();
|
|
63
|
+
const orgChoices = orgs.map((o) => ({
|
|
64
|
+
name: o.id,
|
|
65
|
+
message: o.name,
|
|
66
|
+
}));
|
|
67
|
+
|
|
68
|
+
const response = await enquirer.prompt<{ orgId: string }>({
|
|
69
|
+
type: 'select',
|
|
70
|
+
name: 'orgId',
|
|
71
|
+
message: 'Select an organization',
|
|
72
|
+
choices: orgChoices,
|
|
73
|
+
});
|
|
74
|
+
orgId = response.orgId;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Check GitHub integrations
|
|
79
|
+
const githubStatus = await tui.spinner({
|
|
80
|
+
message: 'Checking GitHub connection...',
|
|
81
|
+
clearOnSuccess: true,
|
|
82
|
+
callback: () => getGithubIntegrationStatus(apiClient, orgId!),
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
if (!githubStatus.connected || githubStatus.integrations.length === 0) {
|
|
86
|
+
tui.newline();
|
|
87
|
+
tui.error('No GitHub accounts connected to this organization.');
|
|
88
|
+
console.log(tui.muted(`Run ${tui.bold('agentuity git account add')} to connect one`));
|
|
89
|
+
return [];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Select account if multiple and not specified
|
|
93
|
+
let integrationId = opts.account;
|
|
94
|
+
if (!integrationId && githubStatus.integrations.length > 1) {
|
|
95
|
+
tui.newline();
|
|
96
|
+
const accountChoices = githubStatus.integrations.map((integration) => ({
|
|
97
|
+
name: integration.id,
|
|
98
|
+
message: `${integration.githubAccountName} ${tui.muted(`(${integration.githubAccountType})`)}`,
|
|
99
|
+
}));
|
|
100
|
+
|
|
101
|
+
const response = await enquirer.prompt<{ integrationId: string }>({
|
|
102
|
+
type: 'select',
|
|
103
|
+
name: 'integrationId',
|
|
104
|
+
message: 'Select a GitHub account',
|
|
105
|
+
choices: accountChoices,
|
|
106
|
+
});
|
|
107
|
+
integrationId = response.integrationId;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Fetch repos
|
|
111
|
+
const repos = await tui.spinner({
|
|
112
|
+
message: 'Fetching repositories...',
|
|
113
|
+
clearOnSuccess: true,
|
|
114
|
+
callback: () => listGithubRepos(apiClient, orgId!, integrationId),
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
if (repos.length === 0) {
|
|
118
|
+
tui.newline();
|
|
119
|
+
tui.info('No repositories found.');
|
|
120
|
+
console.log(
|
|
121
|
+
tui.muted('Make sure your GitHub App has access to the repositories you want.')
|
|
122
|
+
);
|
|
123
|
+
return [];
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (!options.json) {
|
|
127
|
+
tui.newline();
|
|
128
|
+
console.log(tui.bold(`${repos.length} repositories`));
|
|
129
|
+
tui.newline();
|
|
130
|
+
|
|
131
|
+
for (const repo of repos) {
|
|
132
|
+
const visibility = repo.private ? tui.muted('private') : 'public';
|
|
133
|
+
console.log(
|
|
134
|
+
` ${repo.fullName} ${tui.muted(`[${repo.defaultBranch}]`)} ${visibility}`
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
tui.newline();
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return repos;
|
|
141
|
+
} catch (error) {
|
|
142
|
+
const isCancel =
|
|
143
|
+
error === '' ||
|
|
144
|
+
(error instanceof Error &&
|
|
145
|
+
(error.message === '' || error.message === 'User cancelled'));
|
|
146
|
+
|
|
147
|
+
if (isCancel) {
|
|
148
|
+
tui.newline();
|
|
149
|
+
tui.info('Cancelled');
|
|
150
|
+
return [];
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
logger.trace(error);
|
|
154
|
+
return logger.fatal(
|
|
155
|
+
'Failed to list repositories: %s',
|
|
156
|
+
error,
|
|
157
|
+
ErrorCode.INTEGRATION_FAILED
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
});
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { createSubcommand } from '../../types';
|
|
2
|
+
import * as tui from '../../tui';
|
|
3
|
+
import { getCommand } from '../../command-prefix';
|
|
4
|
+
import { ErrorCode } from '../../errors';
|
|
5
|
+
import { getProjectGithubStatus, getGithubIntegrationStatus } from '../integration/api';
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
|
|
8
|
+
const StatusResponseSchema = z.object({
|
|
9
|
+
orgId: z.string().describe('Organization ID'),
|
|
10
|
+
connected: z.boolean().describe('Whether GitHub is connected to the org'),
|
|
11
|
+
integrations: z
|
|
12
|
+
.array(
|
|
13
|
+
z.object({
|
|
14
|
+
id: z.string(),
|
|
15
|
+
githubAccountName: z.string(),
|
|
16
|
+
githubAccountType: z.enum(['user', 'org']),
|
|
17
|
+
})
|
|
18
|
+
)
|
|
19
|
+
.describe('Connected GitHub accounts'),
|
|
20
|
+
projectId: z.string().describe('Project ID'),
|
|
21
|
+
linked: z.boolean().describe('Whether the project is linked to a repo'),
|
|
22
|
+
repoFullName: z.string().optional().describe('Full repository name'),
|
|
23
|
+
branch: z.string().optional().describe('Branch'),
|
|
24
|
+
directory: z.string().optional().describe('Directory'),
|
|
25
|
+
autoDeploy: z.boolean().optional().describe('Auto-deploy enabled'),
|
|
26
|
+
previewDeploy: z.boolean().optional().describe('Preview deploys enabled'),
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
export const statusSubcommand = createSubcommand({
|
|
30
|
+
name: 'status',
|
|
31
|
+
description: 'Show GitHub connection status for current project',
|
|
32
|
+
tags: ['read-only'],
|
|
33
|
+
idempotent: true,
|
|
34
|
+
requires: { auth: true, apiClient: true, project: true },
|
|
35
|
+
schema: {
|
|
36
|
+
response: StatusResponseSchema,
|
|
37
|
+
},
|
|
38
|
+
examples: [
|
|
39
|
+
{
|
|
40
|
+
command: getCommand('git status'),
|
|
41
|
+
description: 'Show GitHub status for current project',
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
command: getCommand('--json git status'),
|
|
45
|
+
description: 'Get status in JSON format',
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
|
|
49
|
+
async handler(ctx) {
|
|
50
|
+
const { logger, apiClient, project, options } = ctx;
|
|
51
|
+
|
|
52
|
+
try {
|
|
53
|
+
// Get org-level GitHub status
|
|
54
|
+
const orgStatus = await tui.spinner({
|
|
55
|
+
message: 'Checking GitHub connection...',
|
|
56
|
+
clearOnSuccess: true,
|
|
57
|
+
callback: () => getGithubIntegrationStatus(apiClient, project.orgId),
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// Get project-level link status
|
|
61
|
+
const projectStatus = await tui.spinner({
|
|
62
|
+
message: 'Checking project status...',
|
|
63
|
+
clearOnSuccess: true,
|
|
64
|
+
callback: () => getProjectGithubStatus(apiClient, project.projectId),
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
const result = {
|
|
68
|
+
orgId: project.orgId,
|
|
69
|
+
connected: orgStatus.connected,
|
|
70
|
+
integrations: orgStatus.integrations.map((i) => ({
|
|
71
|
+
id: i.id,
|
|
72
|
+
githubAccountName: i.githubAccountName,
|
|
73
|
+
githubAccountType: i.githubAccountType,
|
|
74
|
+
})),
|
|
75
|
+
projectId: project.projectId,
|
|
76
|
+
linked: projectStatus.linked,
|
|
77
|
+
repoFullName: projectStatus.repoFullName,
|
|
78
|
+
branch: projectStatus.branch,
|
|
79
|
+
directory: projectStatus.directory,
|
|
80
|
+
autoDeploy: projectStatus.autoDeploy,
|
|
81
|
+
previewDeploy: projectStatus.previewDeploy,
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
if (options.json) {
|
|
85
|
+
return result;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
tui.newline();
|
|
89
|
+
console.log(tui.bold('GitHub Status'));
|
|
90
|
+
tui.newline();
|
|
91
|
+
|
|
92
|
+
// Organization status
|
|
93
|
+
console.log(`${tui.bold('Organization:')} ${project.orgId}`);
|
|
94
|
+
if (orgStatus.connected && orgStatus.integrations.length > 0) {
|
|
95
|
+
console.log(
|
|
96
|
+
` ${tui.colorSuccess('✓')} ${orgStatus.integrations.length} GitHub account${orgStatus.integrations.length > 1 ? 's' : ''} connected`
|
|
97
|
+
);
|
|
98
|
+
for (const integration of orgStatus.integrations) {
|
|
99
|
+
const typeLabel = integration.githubAccountType === 'org' ? 'org' : 'user';
|
|
100
|
+
console.log(` - ${integration.githubAccountName} ${tui.muted(`(${typeLabel})`)}`);
|
|
101
|
+
}
|
|
102
|
+
} else {
|
|
103
|
+
console.log(` ${tui.colorError('✗')} No GitHub accounts connected`);
|
|
104
|
+
console.log(
|
|
105
|
+
tui.muted(` Run ${tui.bold('agentuity git account add')} to connect one`)
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
tui.newline();
|
|
110
|
+
|
|
111
|
+
// Project status
|
|
112
|
+
console.log(`${tui.bold('Project:')} ${project.projectId}`);
|
|
113
|
+
if (projectStatus.linked) {
|
|
114
|
+
console.log(
|
|
115
|
+
` ${tui.colorSuccess('✓')} Linked to ${tui.bold(projectStatus.repoFullName ?? '<unknown repository>')}`
|
|
116
|
+
);
|
|
117
|
+
console.log(` Branch: ${projectStatus.branch}`);
|
|
118
|
+
if (projectStatus.directory) {
|
|
119
|
+
console.log(` Directory: ${projectStatus.directory}`);
|
|
120
|
+
}
|
|
121
|
+
console.log(
|
|
122
|
+
` Auto-deploy: ${projectStatus.autoDeploy ? tui.colorSuccess('enabled') : tui.muted('disabled')}`
|
|
123
|
+
);
|
|
124
|
+
console.log(
|
|
125
|
+
` Preview deploys: ${projectStatus.previewDeploy ? tui.colorSuccess('enabled') : tui.muted('disabled')}`
|
|
126
|
+
);
|
|
127
|
+
} else {
|
|
128
|
+
console.log(` ${tui.muted('○')} Not linked to a repository`);
|
|
129
|
+
console.log(tui.muted(` Run ${tui.bold('agentuity git link')} to link one`));
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
tui.newline();
|
|
133
|
+
|
|
134
|
+
return result;
|
|
135
|
+
} catch (error) {
|
|
136
|
+
logger.trace(error);
|
|
137
|
+
return logger.fatal(
|
|
138
|
+
'Failed to get GitHub status: %s',
|
|
139
|
+
error,
|
|
140
|
+
ErrorCode.INTEGRATION_FAILED
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
});
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { createSubcommand } from '../../types';
|
|
2
|
+
import * as tui from '../../tui';
|
|
3
|
+
import { getCommand } from '../../command-prefix';
|
|
4
|
+
import { ErrorCode } from '../../errors';
|
|
5
|
+
import { getProjectGithubStatus, unlinkProjectFromRepo } from '../integration/api';
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
|
|
8
|
+
const UnlinkOptionsSchema = z.object({
|
|
9
|
+
confirm: z.boolean().optional().describe('Skip confirmation prompt'),
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
const UnlinkResponseSchema = z.object({
|
|
13
|
+
unlinked: z.boolean().describe('Whether the project was unlinked'),
|
|
14
|
+
repoFullName: z.string().optional().describe('Repository that was unlinked'),
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
export const unlinkSubcommand = createSubcommand({
|
|
18
|
+
name: 'unlink',
|
|
19
|
+
description: 'Unlink a project from its GitHub repository',
|
|
20
|
+
tags: ['mutating', 'destructive'],
|
|
21
|
+
idempotent: false,
|
|
22
|
+
requires: { auth: true, apiClient: true, project: true },
|
|
23
|
+
schema: {
|
|
24
|
+
options: UnlinkOptionsSchema,
|
|
25
|
+
response: UnlinkResponseSchema,
|
|
26
|
+
},
|
|
27
|
+
examples: [
|
|
28
|
+
{
|
|
29
|
+
command: getCommand('git unlink'),
|
|
30
|
+
description: 'Unlink current project from GitHub',
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
command: getCommand('git unlink --confirm'),
|
|
34
|
+
description: 'Unlink without confirmation prompt',
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
command: getCommand('--json git unlink --confirm'),
|
|
38
|
+
description: 'Unlink and return JSON result',
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
|
|
42
|
+
async handler(ctx) {
|
|
43
|
+
const { logger, apiClient, project, opts, options } = ctx;
|
|
44
|
+
|
|
45
|
+
try {
|
|
46
|
+
// Check current status
|
|
47
|
+
const status = await tui.spinner({
|
|
48
|
+
message: 'Checking current status...',
|
|
49
|
+
clearOnSuccess: true,
|
|
50
|
+
callback: () => getProjectGithubStatus(apiClient, project.projectId),
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
if (!status.linked) {
|
|
54
|
+
if (!options.json) {
|
|
55
|
+
tui.newline();
|
|
56
|
+
tui.info('This project is not linked to a GitHub repository.');
|
|
57
|
+
}
|
|
58
|
+
return { unlinked: false };
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (!opts.confirm) {
|
|
62
|
+
tui.newline();
|
|
63
|
+
console.log(`Currently linked to: ${tui.bold(status.repoFullName ?? 'Unknown')}`);
|
|
64
|
+
console.log(` Branch: ${status.branch ?? 'default'}`);
|
|
65
|
+
if (status.directory) {
|
|
66
|
+
console.log(` Directory: ${status.directory}`);
|
|
67
|
+
}
|
|
68
|
+
console.log(` Auto-deploy: ${status.autoDeploy ? 'enabled' : 'disabled'}`);
|
|
69
|
+
console.log(` Preview deploys: ${status.previewDeploy ? 'enabled' : 'disabled'}`);
|
|
70
|
+
tui.newline();
|
|
71
|
+
|
|
72
|
+
const confirmed = await tui.confirm(
|
|
73
|
+
`Are you sure you want to unlink from ${tui.bold(status.repoFullName ?? 'this repository')}?`
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
if (!confirmed) {
|
|
77
|
+
tui.info('Cancelled');
|
|
78
|
+
return { unlinked: false };
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
await tui.spinner({
|
|
83
|
+
message: 'Unlinking repository...',
|
|
84
|
+
clearOnSuccess: true,
|
|
85
|
+
callback: () => unlinkProjectFromRepo(apiClient, project.projectId),
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
if (!options.json) {
|
|
89
|
+
tui.newline();
|
|
90
|
+
tui.success(`Unlinked from ${tui.bold(status.repoFullName ?? 'repository')}`);
|
|
91
|
+
tui.newline();
|
|
92
|
+
console.log('Automatic deployments have been disabled for this project.');
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return { unlinked: true, repoFullName: status.repoFullName };
|
|
96
|
+
} catch (error) {
|
|
97
|
+
// Handle user cancellation
|
|
98
|
+
const isCancel =
|
|
99
|
+
error === '' ||
|
|
100
|
+
(error instanceof Error &&
|
|
101
|
+
(error.message === '' || error.message === 'User cancelled'));
|
|
102
|
+
|
|
103
|
+
if (isCancel) {
|
|
104
|
+
tui.newline();
|
|
105
|
+
tui.info('Cancelled');
|
|
106
|
+
return { unlinked: false };
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
logger.trace(error);
|
|
110
|
+
return logger.fatal(
|
|
111
|
+
'Failed to unlink repository: %s',
|
|
112
|
+
error,
|
|
113
|
+
ErrorCode.INTEGRATION_FAILED
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
});
|
package/src/cmd/index.ts
CHANGED
|
@@ -9,7 +9,9 @@ export async function discoverCommands(): Promise<CommandDefinition[]> {
|
|
|
9
9
|
import('./build').then((m) => m.command),
|
|
10
10
|
import('./cloud').then((m) => m.command),
|
|
11
11
|
import('./dev').then((m) => m.command),
|
|
12
|
+
import('./git').then((m) => m.gitCommand),
|
|
12
13
|
import('./help').then((m) => m.command),
|
|
14
|
+
import('./integration').then((m) => m.command),
|
|
13
15
|
import('./profile').then((m) => m.command),
|
|
14
16
|
import('./project').then((m) => m.command),
|
|
15
17
|
import('./repl').then((m) => m.command),
|