@agentuity/cli 1.0.9 → 1.0.11
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/cmd/build/ast.d.ts +1 -1
- package/dist/cmd/build/ast.d.ts.map +1 -1
- package/dist/cmd/build/ast.js +103 -5
- package/dist/cmd/build/ast.js.map +1 -1
- package/dist/cmd/build/entry-generator.d.ts.map +1 -1
- package/dist/cmd/build/entry-generator.js +1 -8
- package/dist/cmd/build/entry-generator.js.map +1 -1
- package/dist/cmd/build/vite/config-loader.d.ts +9 -0
- package/dist/cmd/build/vite/config-loader.d.ts.map +1 -1
- package/dist/cmd/build/vite/config-loader.js +30 -0
- package/dist/cmd/build/vite/config-loader.js.map +1 -1
- package/dist/cmd/build/vite/index.d.ts +2 -0
- package/dist/cmd/build/vite/index.d.ts.map +1 -1
- package/dist/cmd/build/vite/index.js +2 -1
- package/dist/cmd/build/vite/index.js.map +1 -1
- package/dist/cmd/build/vite/metadata-generator.d.ts +4 -1
- package/dist/cmd/build/vite/metadata-generator.d.ts.map +1 -1
- package/dist/cmd/build/vite/metadata-generator.js +1 -0
- package/dist/cmd/build/vite/metadata-generator.js.map +1 -1
- package/dist/cmd/build/vite/route-discovery.d.ts.map +1 -1
- package/dist/cmd/build/vite/route-discovery.js +23 -1
- package/dist/cmd/build/vite/route-discovery.js.map +1 -1
- package/dist/cmd/build/vite/vite-asset-server-config.d.ts.map +1 -1
- package/dist/cmd/build/vite/vite-asset-server-config.js +19 -14
- package/dist/cmd/build/vite/vite-asset-server-config.js.map +1 -1
- package/dist/cmd/build/vite/vite-builder.d.ts +2 -0
- package/dist/cmd/build/vite/vite-builder.d.ts.map +1 -1
- package/dist/cmd/build/vite/vite-builder.js +13 -8
- package/dist/cmd/build/vite/vite-builder.js.map +1 -1
- package/dist/cmd/build/vite-bundler.d.ts +2 -0
- package/dist/cmd/build/vite-bundler.d.ts.map +1 -1
- package/dist/cmd/build/vite-bundler.js +2 -1
- package/dist/cmd/build/vite-bundler.js.map +1 -1
- package/dist/cmd/cloud/db/list.d.ts.map +1 -1
- package/dist/cmd/cloud/db/list.js +14 -1
- package/dist/cmd/cloud/db/list.js.map +1 -1
- package/dist/cmd/cloud/deploy.d.ts.map +1 -1
- package/dist/cmd/cloud/deploy.js +36 -22
- package/dist/cmd/cloud/deploy.js.map +1 -1
- package/dist/cmd/cloud/queue/list.d.ts.map +1 -1
- package/dist/cmd/cloud/queue/list.js +10 -0
- package/dist/cmd/cloud/queue/list.js.map +1 -1
- package/dist/cmd/cloud/sandbox/list.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/list.js +10 -0
- package/dist/cmd/cloud/sandbox/list.js.map +1 -1
- package/dist/cmd/cloud/sandbox/runtime/list.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/runtime/list.js +10 -0
- package/dist/cmd/cloud/sandbox/runtime/list.js.map +1 -1
- package/dist/cmd/cloud/sandbox/snapshot/list.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/snapshot/list.js +10 -0
- package/dist/cmd/cloud/sandbox/snapshot/list.js.map +1 -1
- package/dist/cmd/cloud/session/get.js +12 -12
- package/dist/cmd/cloud/session/get.js.map +1 -1
- package/dist/cmd/cloud/session/list.d.ts.map +1 -1
- package/dist/cmd/cloud/session/list.js +14 -4
- package/dist/cmd/cloud/session/list.js.map +1 -1
- package/dist/cmd/cloud/storage/list.d.ts.map +1 -1
- package/dist/cmd/cloud/storage/list.js +14 -1
- package/dist/cmd/cloud/storage/list.js.map +1 -1
- package/dist/cmd/cloud/stream/list.d.ts.map +1 -1
- package/dist/cmd/cloud/stream/list.js +10 -0
- package/dist/cmd/cloud/stream/list.js.map +1 -1
- package/dist/cmd/cloud/thread/list.d.ts.map +1 -1
- package/dist/cmd/cloud/thread/list.js +10 -0
- package/dist/cmd/cloud/thread/list.js.map +1 -1
- package/dist/cmd/dev/download.d.ts.map +1 -1
- package/dist/cmd/dev/download.js +63 -53
- package/dist/cmd/dev/download.js.map +1 -1
- package/dist/cmd/project/domain/check.d.ts +2 -0
- package/dist/cmd/project/domain/check.d.ts.map +1 -0
- package/dist/cmd/project/domain/check.js +131 -0
- package/dist/cmd/project/domain/check.js.map +1 -0
- package/dist/cmd/project/domain/index.d.ts +2 -0
- package/dist/cmd/project/domain/index.d.ts.map +1 -0
- package/dist/cmd/project/domain/index.js +20 -0
- package/dist/cmd/project/domain/index.js.map +1 -0
- package/dist/cmd/project/hostname/get.d.ts +2 -0
- package/dist/cmd/project/hostname/get.d.ts.map +1 -0
- package/dist/cmd/project/hostname/get.js +50 -0
- package/dist/cmd/project/hostname/get.js.map +1 -0
- package/dist/cmd/project/hostname/index.d.ts +2 -0
- package/dist/cmd/project/hostname/index.d.ts.map +1 -0
- package/dist/cmd/project/hostname/index.js +18 -0
- package/dist/cmd/project/hostname/index.js.map +1 -0
- package/dist/cmd/project/hostname/set.d.ts +2 -0
- package/dist/cmd/project/hostname/set.d.ts.map +1 -0
- package/dist/cmd/project/hostname/set.js +100 -0
- package/dist/cmd/project/hostname/set.js.map +1 -0
- package/dist/cmd/project/index.d.ts.map +1 -1
- package/dist/cmd/project/index.js +12 -0
- package/dist/cmd/project/index.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/steps.d.ts +9 -0
- package/dist/steps.d.ts.map +1 -1
- package/dist/steps.js +131 -71
- package/dist/steps.js.map +1 -1
- package/dist/tui.d.ts +2 -2
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +6 -4
- package/dist/tui.js.map +1 -1
- package/dist/types.d.ts +4 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +6 -7
- package/src/cmd/build/ast.ts +141 -5
- package/src/cmd/build/entry-generator.ts +1 -8
- package/src/cmd/build/vite/config-loader.ts +35 -0
- package/src/cmd/build/vite/index.ts +4 -0
- package/src/cmd/build/vite/metadata-generator.ts +5 -1
- package/src/cmd/build/vite/route-discovery.ts +34 -1
- package/src/cmd/build/vite/vite-asset-server-config.ts +22 -13
- package/src/cmd/build/vite/vite-builder.ts +20 -8
- package/src/cmd/build/vite-bundler.ts +4 -0
- package/src/cmd/cloud/db/list.ts +14 -1
- package/src/cmd/cloud/deploy.ts +46 -21
- package/src/cmd/cloud/queue/list.ts +10 -0
- package/src/cmd/cloud/sandbox/list.ts +10 -0
- package/src/cmd/cloud/sandbox/runtime/list.ts +10 -0
- package/src/cmd/cloud/sandbox/snapshot/list.ts +10 -0
- package/src/cmd/cloud/session/get.ts +12 -12
- package/src/cmd/cloud/session/list.ts +28 -18
- package/src/cmd/cloud/storage/list.ts +14 -1
- package/src/cmd/cloud/stream/list.ts +18 -8
- package/src/cmd/cloud/thread/list.ts +15 -5
- package/src/cmd/dev/download.ts +76 -78
- package/src/cmd/project/domain/check.ts +146 -0
- package/src/cmd/project/domain/index.ts +20 -0
- package/src/cmd/project/hostname/get.ts +54 -0
- package/src/cmd/project/hostname/index.ts +18 -0
- package/src/cmd/project/hostname/set.ts +123 -0
- package/src/cmd/project/index.ts +12 -0
- package/src/index.ts +1 -1
- package/src/steps.ts +139 -74
- package/src/tui.ts +6 -4
- package/src/types.ts +4 -2
|
@@ -12,8 +12,8 @@ const SessionListResponseSchema = z.array(
|
|
|
12
12
|
created_at: z.string().describe('Creation timestamp'),
|
|
13
13
|
success: z.boolean().describe('Whether the session succeeded'),
|
|
14
14
|
duration: z.number().nullable().describe('Duration in nanoseconds'),
|
|
15
|
-
method: z.string().describe('HTTP method'),
|
|
16
|
-
url: z.string().describe('Request URL'),
|
|
15
|
+
method: z.string().nullable().describe('HTTP method'),
|
|
16
|
+
url: z.string().nullable().describe('Request URL'),
|
|
17
17
|
trigger: z.string().describe('Trigger type'),
|
|
18
18
|
env: z.string().describe('Environment'),
|
|
19
19
|
})
|
|
@@ -91,6 +91,14 @@ export const listSubcommand = createSubcommand({
|
|
|
91
91
|
success: z.coerce.boolean().optional().describe('Filter by success status (true/false)'),
|
|
92
92
|
startAfter: z.string().optional().describe('Filter by start time after (ISO 8601)'),
|
|
93
93
|
startBefore: z.string().optional().describe('Filter by start time before (ISO 8601)'),
|
|
94
|
+
sort: z
|
|
95
|
+
.enum(['created', 'updated', 'duration', 'startTime'])
|
|
96
|
+
.optional()
|
|
97
|
+
.describe('field to sort by (default: created)'),
|
|
98
|
+
direction: z
|
|
99
|
+
.enum(['asc', 'desc'])
|
|
100
|
+
.optional()
|
|
101
|
+
.describe('sort direction (default: desc)'),
|
|
94
102
|
}),
|
|
95
103
|
response: SessionListResponseSchema,
|
|
96
104
|
},
|
|
@@ -109,20 +117,22 @@ export const listSubcommand = createSubcommand({
|
|
|
109
117
|
const projectId = opts.all || opts.orgId ? undefined : opts.projectId || project?.projectId;
|
|
110
118
|
|
|
111
119
|
try {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
120
|
+
const sessions = await sessionList(catalystClient, {
|
|
121
|
+
count: opts.count,
|
|
122
|
+
orgId: opts?.orgId,
|
|
123
|
+
projectId,
|
|
124
|
+
deploymentId: opts.deploymentId,
|
|
125
|
+
trigger: opts.trigger,
|
|
126
|
+
env: opts.env,
|
|
127
|
+
devmode: opts.devmode,
|
|
128
|
+
success: opts.success,
|
|
129
|
+
threadId: opts.threadId,
|
|
130
|
+
agentIdentifier: opts.agentIdentifier,
|
|
131
|
+
startAfter: opts.startAfter,
|
|
132
|
+
startBefore: opts.startBefore,
|
|
133
|
+
sort: opts.sort,
|
|
134
|
+
direction: opts.direction,
|
|
135
|
+
});
|
|
126
136
|
|
|
127
137
|
const result = sessions.map((s) => ({
|
|
128
138
|
id: s.id,
|
|
@@ -146,13 +156,13 @@ export const listSubcommand = createSubcommand({
|
|
|
146
156
|
}
|
|
147
157
|
|
|
148
158
|
const tableData = sessions.map((s) => {
|
|
149
|
-
const urlPath = new URL(s.url).pathname;
|
|
159
|
+
const urlPath = s.url ? new URL(s.url).pathname : '-';
|
|
150
160
|
return {
|
|
151
161
|
ID: s.id,
|
|
152
162
|
Created: new Date(s.created_at).toLocaleString(),
|
|
153
163
|
Success: s.success ? '✓' : '✗',
|
|
154
164
|
Duration: s.duration ? `${(s.duration / 1_000_000).toFixed(0)}ms` : '-',
|
|
155
|
-
Method: s.method,
|
|
165
|
+
Method: s.method ?? '-',
|
|
156
166
|
Path: urlPath.length > 50 ? urlPath.substring(0, 47) + '...' : urlPath,
|
|
157
167
|
Trigger: s.trigger,
|
|
158
168
|
Env: s.env,
|
|
@@ -77,6 +77,14 @@ export const listSubcommand = createSubcommand({
|
|
|
77
77
|
'Show credentials in plain text (default: masked in terminal, unmasked in JSON)'
|
|
78
78
|
),
|
|
79
79
|
nameOnly: z.boolean().optional().describe('Print the name only'),
|
|
80
|
+
sort: z
|
|
81
|
+
.enum(['name', 'created'])
|
|
82
|
+
.optional()
|
|
83
|
+
.describe('field to sort by (default: created)'),
|
|
84
|
+
direction: z
|
|
85
|
+
.enum(['asc', 'desc'])
|
|
86
|
+
.optional()
|
|
87
|
+
.describe('sort direction (default: desc)'),
|
|
80
88
|
}),
|
|
81
89
|
response: StorageListResponseSchema,
|
|
82
90
|
},
|
|
@@ -95,7 +103,12 @@ export const listSubcommand = createSubcommand({
|
|
|
95
103
|
message: 'Fetching storage',
|
|
96
104
|
clearOnSuccess: true,
|
|
97
105
|
callback: async () => {
|
|
98
|
-
return listOrgResources(catalystClient, {
|
|
106
|
+
return listOrgResources(catalystClient, {
|
|
107
|
+
type: 's3',
|
|
108
|
+
orgId: opts?.orgId,
|
|
109
|
+
sort: opts?.sort,
|
|
110
|
+
direction: opts?.direction,
|
|
111
|
+
});
|
|
99
112
|
},
|
|
100
113
|
});
|
|
101
114
|
|
|
@@ -67,6 +67,14 @@ export const listSubcommand = createCommand({
|
|
|
67
67
|
.describe('filter by metadata (format: key=value or key1=value1,key2=value2)'),
|
|
68
68
|
projectId: z.string().optional().describe('filter by project ID'),
|
|
69
69
|
orgId: z.string().optional().describe('filter by organization ID'),
|
|
70
|
+
sort: z
|
|
71
|
+
.enum(['name', 'created', 'updated', 'size'])
|
|
72
|
+
.optional()
|
|
73
|
+
.describe('field to sort by (default: created)'),
|
|
74
|
+
direction: z
|
|
75
|
+
.enum(['asc', 'desc'])
|
|
76
|
+
.optional()
|
|
77
|
+
.describe('sort direction (default: desc)'),
|
|
70
78
|
}),
|
|
71
79
|
response: ListStreamsResponseSchema,
|
|
72
80
|
},
|
|
@@ -120,14 +128,16 @@ export const listSubcommand = createCommand({
|
|
|
120
128
|
}
|
|
121
129
|
|
|
122
130
|
try {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
+
const result = await streamList(apiClient, {
|
|
132
|
+
limit: opts.size,
|
|
133
|
+
offset: opts.offset,
|
|
134
|
+
namespace: opts.namespace,
|
|
135
|
+
metadata: metadataFilter,
|
|
136
|
+
projectId,
|
|
137
|
+
orgId: opts.orgId,
|
|
138
|
+
sort: opts.sort,
|
|
139
|
+
direction: opts.direction,
|
|
140
|
+
});
|
|
131
141
|
|
|
132
142
|
if (options.json) {
|
|
133
143
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -63,6 +63,14 @@ export const listSubcommand = createSubcommand({
|
|
|
63
63
|
orgId: z.string().optional().describe('Filter by organization ID'),
|
|
64
64
|
projectId: z.string().optional().describe('Filter by project ID'),
|
|
65
65
|
all: z.boolean().optional().describe('List all threads regardless of project context'),
|
|
66
|
+
sort: z
|
|
67
|
+
.enum(['created', 'updated'])
|
|
68
|
+
.optional()
|
|
69
|
+
.describe('field to sort by (default: created)'),
|
|
70
|
+
direction: z
|
|
71
|
+
.enum(['asc', 'desc'])
|
|
72
|
+
.optional()
|
|
73
|
+
.describe('sort direction (default: desc)'),
|
|
66
74
|
}),
|
|
67
75
|
response: ThreadListResponseSchema,
|
|
68
76
|
},
|
|
@@ -78,11 +86,13 @@ export const listSubcommand = createSubcommand({
|
|
|
78
86
|
const orgId = opts.orgId;
|
|
79
87
|
|
|
80
88
|
try {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
89
|
+
const threads = await threadList(catalystClient, {
|
|
90
|
+
count: opts.count,
|
|
91
|
+
orgId,
|
|
92
|
+
projectId,
|
|
93
|
+
sort: opts.sort,
|
|
94
|
+
direction: opts.direction,
|
|
95
|
+
});
|
|
86
96
|
|
|
87
97
|
const result = threads.map((t: Thread) => ({
|
|
88
98
|
id: t.id,
|
package/src/cmd/dev/download.ts
CHANGED
|
@@ -1,118 +1,116 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
|
-
import {
|
|
2
|
+
import { mkdirSync, rmSync, writeFileSync } from 'node:fs';
|
|
3
3
|
import { tmpdir, platform } from 'node:os';
|
|
4
4
|
import { join, dirname } from 'node:path';
|
|
5
5
|
import * as tar from 'tar';
|
|
6
|
-
import {
|
|
6
|
+
import { StructuredError } from '@agentuity/core';
|
|
7
7
|
import { spinner } from '../../tui';
|
|
8
8
|
|
|
9
|
-
const user = 'agentuity';
|
|
10
|
-
const repo = 'gravity';
|
|
11
|
-
|
|
12
|
-
function filterRelease(release: { prerelease: boolean }) {
|
|
13
|
-
// Filter out prereleases.
|
|
14
|
-
return release.prerelease === false;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function filterAsset(asset: { name: string }): boolean {
|
|
18
|
-
// Filter out the release matching our os and architecture
|
|
19
|
-
let arch: string = process.arch;
|
|
20
|
-
if (arch === 'x64') {
|
|
21
|
-
arch = 'x86_64';
|
|
22
|
-
}
|
|
23
|
-
return asset.name.includes(arch) && asset.name.includes(platform());
|
|
24
|
-
}
|
|
25
|
-
|
|
26
9
|
interface GravityClient {
|
|
27
10
|
filename: string;
|
|
28
11
|
version: string;
|
|
29
12
|
}
|
|
30
13
|
|
|
14
|
+
const GravityVersionError = StructuredError('GravityVersionError')<{
|
|
15
|
+
status: number;
|
|
16
|
+
statusText: string;
|
|
17
|
+
}>();
|
|
18
|
+
const GravityDownloadError = StructuredError('GravityDownloadError')<{
|
|
19
|
+
status: number;
|
|
20
|
+
statusText: string;
|
|
21
|
+
}>();
|
|
22
|
+
const GravityExtractionError = StructuredError('GravityExtractionError')<{
|
|
23
|
+
path: string;
|
|
24
|
+
}>();
|
|
25
|
+
|
|
26
|
+
function getBaseURL(): string {
|
|
27
|
+
return process.env.AGENTUITY_SH_URL || 'https://agentuity.sh';
|
|
28
|
+
}
|
|
29
|
+
|
|
31
30
|
/**
|
|
32
31
|
*
|
|
33
32
|
* @returns full path to the downloaded file
|
|
34
33
|
*/
|
|
35
34
|
export async function download(gravityDir: string): Promise<GravityClient> {
|
|
36
|
-
const
|
|
35
|
+
const baseURL = getBaseURL();
|
|
37
36
|
|
|
38
|
-
|
|
37
|
+
// Step 1: Get the latest version from agentuity.sh
|
|
38
|
+
const tag = (await spinner({
|
|
39
39
|
message: 'Checking Agentuity Gravity',
|
|
40
40
|
callback: async () => {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
)
|
|
41
|
+
const resp = await fetch(`${baseURL}/release/gravity/version`, {
|
|
42
|
+
signal: AbortSignal.timeout(10_000),
|
|
43
|
+
});
|
|
44
|
+
if (!resp.ok) {
|
|
45
|
+
throw new GravityVersionError({
|
|
46
|
+
status: resp.status,
|
|
47
|
+
statusText: resp.statusText,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
const text = (await resp.text()).trim();
|
|
51
|
+
return text.startsWith('v') ? text : `v${text}`;
|
|
52
52
|
},
|
|
53
53
|
clearOnSuccess: true,
|
|
54
|
-
})) as
|
|
54
|
+
})) as string;
|
|
55
55
|
|
|
56
|
-
const
|
|
57
|
-
const version = versionTok[1] ?? 'unknown';
|
|
56
|
+
const version = tag.startsWith('v') ? tag.slice(1) : tag;
|
|
58
57
|
const releaseFilename = join(gravityDir, version, 'gravity');
|
|
59
|
-
const mustDownload = !existsSync(releaseFilename);
|
|
60
58
|
|
|
61
|
-
if
|
|
59
|
+
// Step 2: Check if already downloaded
|
|
60
|
+
if (await Bun.file(releaseFilename).exists()) {
|
|
62
61
|
return { filename: releaseFilename, version };
|
|
63
62
|
}
|
|
64
63
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
outputdir,
|
|
72
|
-
filterRelease,
|
|
73
|
-
filterAsset,
|
|
74
|
-
false,
|
|
75
|
-
true,
|
|
76
|
-
false,
|
|
77
|
-
''
|
|
78
|
-
)) as string[];
|
|
79
|
-
const file = res[0];
|
|
80
|
-
if (!file) {
|
|
81
|
-
throw new Error('No file downloaded from release');
|
|
82
|
-
}
|
|
83
|
-
return file;
|
|
84
|
-
},
|
|
85
|
-
clearOnSuccess: true,
|
|
86
|
-
});
|
|
64
|
+
// Step 3: Download the binary from agentuity.sh
|
|
65
|
+
const os = platform();
|
|
66
|
+
let arch: string = process.arch;
|
|
67
|
+
if (arch === 'x64') {
|
|
68
|
+
arch = 'x86_64';
|
|
69
|
+
}
|
|
87
70
|
|
|
88
|
-
|
|
71
|
+
const tmpFile = join(tmpdir(), `${randomUUID()}.tar.gz`);
|
|
72
|
+
|
|
73
|
+
try {
|
|
89
74
|
await spinner({
|
|
90
|
-
message:
|
|
75
|
+
message: `Downloading Gravity ${version}`,
|
|
91
76
|
callback: async () => {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
const downloadDir = dirname(releaseFilename);
|
|
95
|
-
if (!existsSync(downloadDir)) {
|
|
96
|
-
mkdirSync(downloadDir, { recursive: true });
|
|
97
|
-
}
|
|
98
|
-
input.on('finish', resolve);
|
|
99
|
-
input.on('end', resolve);
|
|
100
|
-
input.on('error', reject);
|
|
101
|
-
input.pipe(tar.x({ C: downloadDir, chmod: true }));
|
|
77
|
+
const resp = await fetch(`${baseURL}/release/gravity/${tag}/${os}/${arch}`, {
|
|
78
|
+
signal: AbortSignal.timeout(60_000),
|
|
102
79
|
});
|
|
80
|
+
if (!resp.ok) {
|
|
81
|
+
throw new GravityDownloadError({
|
|
82
|
+
status: resp.status,
|
|
83
|
+
statusText: resp.statusText,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
const buffer = await resp.arrayBuffer();
|
|
87
|
+
writeFileSync(tmpFile, Buffer.from(buffer));
|
|
103
88
|
},
|
|
104
89
|
clearOnSuccess: true,
|
|
105
90
|
});
|
|
106
|
-
} else {
|
|
107
|
-
// TODO:
|
|
108
|
-
}
|
|
109
91
|
|
|
110
|
-
|
|
111
|
-
|
|
92
|
+
// Step 4: Extract the tarball
|
|
93
|
+
await spinner({
|
|
94
|
+
message: 'Extracting release',
|
|
95
|
+
callback: async () => {
|
|
96
|
+
const downloadDir = dirname(releaseFilename);
|
|
97
|
+
if (!(await Bun.file(downloadDir).exists())) {
|
|
98
|
+
mkdirSync(downloadDir, { recursive: true });
|
|
99
|
+
}
|
|
100
|
+
await tar.x({ file: tmpFile, cwd: downloadDir, chmod: true });
|
|
101
|
+
},
|
|
102
|
+
clearOnSuccess: true,
|
|
103
|
+
});
|
|
104
|
+
} finally {
|
|
105
|
+
// Clean up temp file regardless of success or failure
|
|
106
|
+
if (await Bun.file(tmpFile).exists()) {
|
|
107
|
+
rmSync(tmpFile);
|
|
108
|
+
}
|
|
112
109
|
}
|
|
113
110
|
|
|
114
|
-
|
|
115
|
-
|
|
111
|
+
// Step 5: Verify the binary was extracted
|
|
112
|
+
if (!(await Bun.file(releaseFilename).exists())) {
|
|
113
|
+
throw new GravityExtractionError({ path: releaseFilename });
|
|
116
114
|
}
|
|
117
115
|
|
|
118
116
|
return { filename: releaseFilename, version };
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { createSubcommand } from '../../../types';
|
|
3
|
+
import * as tui from '../../../tui';
|
|
4
|
+
import { getCommand } from '../../../command-prefix';
|
|
5
|
+
import { loadProjectConfig } from '../../../config';
|
|
6
|
+
import { isJSONMode } from '../../../output';
|
|
7
|
+
import {
|
|
8
|
+
checkCustomDomainForDNS,
|
|
9
|
+
isSuccess,
|
|
10
|
+
isPending,
|
|
11
|
+
isMissing,
|
|
12
|
+
isMisconfigured,
|
|
13
|
+
isError,
|
|
14
|
+
} from '../../../domain';
|
|
15
|
+
|
|
16
|
+
export const checkSubcommand = createSubcommand({
|
|
17
|
+
name: 'check',
|
|
18
|
+
description: 'Check DNS configuration for custom domains',
|
|
19
|
+
tags: ['read-only', 'slow', 'requires-auth', 'requires-project'],
|
|
20
|
+
requires: { auth: true, project: true },
|
|
21
|
+
idempotent: true,
|
|
22
|
+
examples: [
|
|
23
|
+
{
|
|
24
|
+
command: getCommand('project domain check'),
|
|
25
|
+
description: 'Check all configured domains',
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
command: getCommand('project domain check --domain example.com'),
|
|
29
|
+
description: 'Check a specific domain',
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
schema: {
|
|
33
|
+
options: z.object({
|
|
34
|
+
domain: z.string().optional().describe('Specific domain to check'),
|
|
35
|
+
}),
|
|
36
|
+
response: z.object({
|
|
37
|
+
domains: z.array(
|
|
38
|
+
z.object({
|
|
39
|
+
domain: z.string(),
|
|
40
|
+
recordType: z.string(),
|
|
41
|
+
target: z.string(),
|
|
42
|
+
status: z.string(),
|
|
43
|
+
success: z.boolean(),
|
|
44
|
+
})
|
|
45
|
+
),
|
|
46
|
+
}),
|
|
47
|
+
},
|
|
48
|
+
|
|
49
|
+
async handler(ctx) {
|
|
50
|
+
const { opts, options, projectDir, config, project } = ctx;
|
|
51
|
+
const jsonMode = isJSONMode(options);
|
|
52
|
+
|
|
53
|
+
// Determine which domains to check
|
|
54
|
+
let domainsToCheck: string[];
|
|
55
|
+
|
|
56
|
+
if (opts?.domain) {
|
|
57
|
+
domainsToCheck = [opts.domain.toLowerCase().trim()];
|
|
58
|
+
} else {
|
|
59
|
+
const projectConfig = await loadProjectConfig(projectDir, config);
|
|
60
|
+
domainsToCheck = projectConfig.deployment?.domains ?? [];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (domainsToCheck.length === 0) {
|
|
64
|
+
if (!jsonMode) {
|
|
65
|
+
tui.info('No custom domains configured for this project');
|
|
66
|
+
tui.info(`Use ${tui.bold(getCommand('project add domain <domain>'))} to add one`);
|
|
67
|
+
}
|
|
68
|
+
return { domains: [] };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const results = jsonMode
|
|
72
|
+
? await checkCustomDomainForDNS(project.projectId, domainsToCheck, config)
|
|
73
|
+
: await tui.spinner({
|
|
74
|
+
message: `Checking DNS for ${domainsToCheck.length} ${tui.plural(domainsToCheck.length, 'domain', 'domains')}`,
|
|
75
|
+
clearOnSuccess: true,
|
|
76
|
+
callback: () => checkCustomDomainForDNS(project.projectId, domainsToCheck, config),
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
const domainResults = results.map((r) => {
|
|
80
|
+
let status: string;
|
|
81
|
+
let statusRaw: string;
|
|
82
|
+
let success = false;
|
|
83
|
+
|
|
84
|
+
if (isSuccess(r)) {
|
|
85
|
+
status = tui.colorSuccess(`${tui.ICONS.success} Configured`);
|
|
86
|
+
statusRaw = 'configured';
|
|
87
|
+
success = true;
|
|
88
|
+
} else if (isPending(r)) {
|
|
89
|
+
status = tui.colorWarning('⏳ Pending');
|
|
90
|
+
statusRaw = 'pending';
|
|
91
|
+
} else if (isMisconfigured(r)) {
|
|
92
|
+
status = tui.colorWarning(`${tui.ICONS.warning} ${r.misconfigured}`);
|
|
93
|
+
statusRaw = 'misconfigured';
|
|
94
|
+
} else if (isError(r)) {
|
|
95
|
+
status = tui.colorError(`${tui.ICONS.error} ${r.error}`);
|
|
96
|
+
statusRaw = 'error';
|
|
97
|
+
} else if (isMissing(r)) {
|
|
98
|
+
status = tui.colorError(`${tui.ICONS.error} Missing`);
|
|
99
|
+
statusRaw = 'missing';
|
|
100
|
+
} else {
|
|
101
|
+
status = tui.colorError(`${tui.ICONS.error} Unknown`);
|
|
102
|
+
statusRaw = 'unknown';
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return {
|
|
106
|
+
domain: r.domain,
|
|
107
|
+
recordType: r.recordType,
|
|
108
|
+
target: r.target,
|
|
109
|
+
status,
|
|
110
|
+
statusRaw,
|
|
111
|
+
success,
|
|
112
|
+
};
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
if (!jsonMode) {
|
|
116
|
+
tui.newline();
|
|
117
|
+
for (const r of domainResults) {
|
|
118
|
+
console.log(` ${tui.colorInfo('Domain:')} ${tui.colorPrimary(r.domain)}`);
|
|
119
|
+
console.log(` ${tui.colorInfo('Type:')} ${tui.colorPrimary(r.recordType)}`);
|
|
120
|
+
console.log(` ${tui.colorInfo('Target:')} ${tui.colorPrimary(r.target)}`);
|
|
121
|
+
console.log(` ${tui.colorInfo('Status:')} ${r.status}`);
|
|
122
|
+
console.log();
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const allGood = domainResults.every((r) => r.success);
|
|
126
|
+
if (allGood) {
|
|
127
|
+
tui.success('All domains are correctly configured');
|
|
128
|
+
} else {
|
|
129
|
+
const failCount = domainResults.filter((r) => !r.success).length;
|
|
130
|
+
tui.warning(
|
|
131
|
+
`${failCount} ${tui.plural(failCount, 'domain has', 'domains have')} DNS issues — add a CNAME record pointing to the target shown above`
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return {
|
|
137
|
+
domains: domainResults.map((r) => ({
|
|
138
|
+
domain: r.domain,
|
|
139
|
+
recordType: r.recordType,
|
|
140
|
+
target: r.target,
|
|
141
|
+
status: r.statusRaw,
|
|
142
|
+
success: r.success,
|
|
143
|
+
})),
|
|
144
|
+
};
|
|
145
|
+
},
|
|
146
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { createCommand } from '../../../types';
|
|
2
|
+
import { checkSubcommand } from './check';
|
|
3
|
+
import { getCommand } from '../../../command-prefix';
|
|
4
|
+
|
|
5
|
+
export const domainCommand = createCommand({
|
|
6
|
+
name: 'domain',
|
|
7
|
+
description: 'Manage custom domains for the project',
|
|
8
|
+
tags: ['fast', 'requires-auth'],
|
|
9
|
+
examples: [
|
|
10
|
+
{
|
|
11
|
+
command: getCommand('project domain check'),
|
|
12
|
+
description: 'Check DNS for all custom domains',
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
command: getCommand('project domain check --domain example.com'),
|
|
16
|
+
description: 'Check DNS for a specific domain',
|
|
17
|
+
},
|
|
18
|
+
],
|
|
19
|
+
subcommands: [checkSubcommand],
|
|
20
|
+
});
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { createSubcommand } from '../../../types';
|
|
3
|
+
import * as tui from '../../../tui';
|
|
4
|
+
import { projectHostnameGet } from '@agentuity/server';
|
|
5
|
+
import { getCommand } from '../../../command-prefix';
|
|
6
|
+
import { isJSONMode } from '../../../output';
|
|
7
|
+
|
|
8
|
+
const HostnameGetResponseSchema = z.object({
|
|
9
|
+
hostname: z.string().nullable().describe('The vanity hostname'),
|
|
10
|
+
url: z.string().nullable().describe('The full URL'),
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
export const getSubcommand = createSubcommand({
|
|
14
|
+
name: 'get',
|
|
15
|
+
description: 'Show the current vanity hostname for the project',
|
|
16
|
+
tags: ['read-only', 'fast', 'requires-auth', 'requires-project'],
|
|
17
|
+
requires: { auth: true, apiClient: true, project: true },
|
|
18
|
+
idempotent: true,
|
|
19
|
+
examples: [
|
|
20
|
+
{
|
|
21
|
+
command: getCommand('project hostname get'),
|
|
22
|
+
description: 'Show current hostname',
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
schema: {
|
|
26
|
+
response: HostnameGetResponseSchema,
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
async handler(ctx) {
|
|
30
|
+
const { apiClient, project, options } = ctx;
|
|
31
|
+
const jsonMode = isJSONMode(options);
|
|
32
|
+
|
|
33
|
+
const result = jsonMode
|
|
34
|
+
? await projectHostnameGet(apiClient, { projectId: project.projectId })
|
|
35
|
+
: await tui.spinner('Fetching hostname', () => {
|
|
36
|
+
return projectHostnameGet(apiClient, { projectId: project.projectId });
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
if (!jsonMode) {
|
|
40
|
+
if (result.hostname) {
|
|
41
|
+
tui.success(`Hostname: ${tui.bold(result.hostname)}`);
|
|
42
|
+
tui.info(`URL: ${result.url}`);
|
|
43
|
+
} else {
|
|
44
|
+
tui.info('No vanity hostname set for this project');
|
|
45
|
+
tui.info(`Use ${tui.bold(getCommand('project hostname set <hostname>'))} to set one`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
hostname: result.hostname,
|
|
51
|
+
url: result.url,
|
|
52
|
+
};
|
|
53
|
+
},
|
|
54
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { createCommand } from '../../../types';
|
|
2
|
+
import { getSubcommand } from './get';
|
|
3
|
+
import { setSubcommand } from './set';
|
|
4
|
+
import { getCommand } from '../../../command-prefix';
|
|
5
|
+
|
|
6
|
+
export const hostnameCommand = createCommand({
|
|
7
|
+
name: 'hostname',
|
|
8
|
+
description: 'Manage the project vanity hostname on agentuity.run',
|
|
9
|
+
tags: ['fast', 'requires-auth'],
|
|
10
|
+
examples: [
|
|
11
|
+
{ command: getCommand('project hostname get'), description: 'Show current hostname' },
|
|
12
|
+
{
|
|
13
|
+
command: getCommand('project hostname set my-cool-api'),
|
|
14
|
+
description: 'Set a custom hostname',
|
|
15
|
+
},
|
|
16
|
+
],
|
|
17
|
+
subcommands: [getSubcommand, setSubcommand],
|
|
18
|
+
});
|