@agentuity/cli 0.1.34 → 0.1.36
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/bin/cli.ts +110 -6
- package/dist/cmd/ai/index.d.ts.map +1 -1
- package/dist/cmd/ai/index.js +0 -6
- package/dist/cmd/ai/index.js.map +1 -1
- package/dist/cmd/ai/opencode/uninstall.js +1 -1
- package/dist/cmd/ai/opencode/uninstall.js.map +1 -1
- package/dist/cmd/build/vite/bun-dev-server.d.ts +6 -0
- package/dist/cmd/build/vite/bun-dev-server.d.ts.map +1 -1
- package/dist/cmd/build/vite/bun-dev-server.js +100 -33
- package/dist/cmd/build/vite/bun-dev-server.js.map +1 -1
- package/dist/cmd/cloud/apikey/create.d.ts.map +1 -1
- package/dist/cmd/cloud/apikey/create.js +1 -1
- package/dist/cmd/cloud/apikey/create.js.map +1 -1
- package/dist/cmd/cloud/deploy.d.ts.map +1 -1
- package/dist/cmd/cloud/deploy.js +4 -1
- package/dist/cmd/cloud/deploy.js.map +1 -1
- package/dist/cmd/cloud/env/delete.d.ts.map +1 -1
- package/dist/cmd/cloud/env/delete.js +100 -45
- package/dist/cmd/cloud/env/delete.js.map +1 -1
- package/dist/cmd/cloud/env/pull.d.ts.map +1 -1
- package/dist/cmd/cloud/env/pull.js +1 -1
- package/dist/cmd/cloud/env/pull.js.map +1 -1
- package/dist/cmd/cloud/machine/delete.js +1 -1
- package/dist/cmd/cloud/machine/delete.js.map +1 -1
- package/dist/cmd/dev/index.d.ts.map +1 -1
- package/dist/cmd/dev/index.js +58 -10
- package/dist/cmd/dev/index.js.map +1 -1
- package/dist/cmd/index.d.ts.map +1 -1
- package/dist/cmd/index.js +1 -0
- package/dist/cmd/index.js.map +1 -1
- package/dist/cmd/support/index.d.ts +2 -0
- package/dist/cmd/support/index.d.ts.map +1 -0
- package/dist/cmd/support/index.js +11 -0
- package/dist/cmd/support/index.js.map +1 -0
- package/dist/cmd/support/logs/index.d.ts +3 -0
- package/dist/cmd/support/logs/index.d.ts.map +1 -0
- package/dist/cmd/support/logs/index.js +9 -0
- package/dist/cmd/support/logs/index.js.map +1 -0
- package/dist/cmd/support/logs/path.d.ts +3 -0
- package/dist/cmd/support/logs/path.d.ts.map +1 -0
- package/dist/cmd/support/logs/path.js +52 -0
- package/dist/cmd/support/logs/path.js.map +1 -0
- package/dist/cmd/support/logs/show.d.ts +3 -0
- package/dist/cmd/support/logs/show.d.ts.map +1 -0
- package/dist/cmd/support/logs/show.js +121 -0
- package/dist/cmd/support/logs/show.js.map +1 -0
- package/dist/cmd/support/report.d.ts +3 -0
- package/dist/cmd/support/report.d.ts.map +1 -0
- package/dist/cmd/support/report.js +299 -0
- package/dist/cmd/support/report.js.map +1 -0
- package/dist/cmd/support/system.d.ts +3 -0
- package/dist/cmd/support/system.d.ts.map +1 -0
- package/dist/cmd/support/system.js +120 -0
- package/dist/cmd/support/system.js.map +1 -0
- package/dist/cmd/version/index.d.ts.map +1 -1
- package/dist/cmd/version/index.js +1 -0
- package/dist/cmd/version/index.js.map +1 -1
- package/dist/composite-logger.d.ts +35 -0
- package/dist/composite-logger.d.ts.map +1 -0
- package/dist/composite-logger.js +78 -0
- package/dist/composite-logger.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/internal-logger.d.ts +77 -0
- package/dist/internal-logger.d.ts.map +1 -0
- package/dist/internal-logger.js +363 -0
- package/dist/internal-logger.js.map +1 -0
- package/dist/types.d.ts +6 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +6 -6
- package/src/cmd/ai/index.ts +0 -6
- package/src/cmd/ai/opencode/uninstall.ts +1 -1
- package/src/cmd/build/vite/bun-dev-server.ts +113 -36
- package/src/cmd/cloud/apikey/create.ts +3 -1
- package/src/cmd/cloud/deploy.ts +4 -1
- package/src/cmd/cloud/env/delete.ts +100 -45
- package/src/cmd/cloud/env/pull.ts +1 -6
- package/src/cmd/cloud/machine/delete.ts +1 -1
- package/src/cmd/dev/index.ts +59 -11
- package/src/cmd/index.ts +1 -0
- package/src/cmd/support/index.ts +11 -0
- package/src/cmd/support/logs/index.ts +9 -0
- package/src/cmd/support/logs/path.ts +56 -0
- package/src/cmd/support/logs/show.ts +144 -0
- package/src/cmd/support/report.ts +364 -0
- package/src/cmd/support/system.ts +130 -0
- package/src/cmd/version/index.ts +1 -0
- package/src/composite-logger.ts +86 -0
- package/src/index.ts +7 -0
- package/src/internal-logger.ts +435 -0
- package/src/types.ts +6 -0
- package/dist/cmd/ai/skills/generate.d.ts +0 -3
- package/dist/cmd/ai/skills/generate.d.ts.map +0 -1
- package/dist/cmd/ai/skills/generate.js +0 -65
- package/dist/cmd/ai/skills/generate.js.map +0 -1
- package/dist/cmd/ai/skills/generator.d.ts +0 -4
- package/dist/cmd/ai/skills/generator.d.ts.map +0 -1
- package/dist/cmd/ai/skills/generator.js +0 -410
- package/dist/cmd/ai/skills/generator.js.map +0 -1
- package/dist/cmd/ai/skills/index.d.ts +0 -4
- package/dist/cmd/ai/skills/index.d.ts.map +0 -1
- package/dist/cmd/ai/skills/index.js +0 -21
- package/dist/cmd/ai/skills/index.js.map +0 -1
- package/dist/cmd/dev/skills.d.ts +0 -10
- package/dist/cmd/dev/skills.d.ts.map +0 -1
- package/dist/cmd/dev/skills.js +0 -57
- package/dist/cmd/dev/skills.js.map +0 -1
- package/src/cmd/ai/skills/generate.ts +0 -75
- package/src/cmd/ai/skills/generator.ts +0 -527
- package/src/cmd/ai/skills/index.ts +0 -23
- package/src/cmd/dev/skills.ts +0 -82
package/src/cmd/ai/index.ts
CHANGED
|
@@ -3,7 +3,6 @@ import cadenceCommand from './cadence';
|
|
|
3
3
|
import capabilitiesCommand from './capabilities';
|
|
4
4
|
import promptCommand from './prompt';
|
|
5
5
|
import schemaCommand from './schema';
|
|
6
|
-
import skillsCommand from './skills';
|
|
7
6
|
import opencodeCommand from './opencode';
|
|
8
7
|
import { getCommand } from '../../command-prefix';
|
|
9
8
|
|
|
@@ -25,10 +24,6 @@ export const command = createCommand({
|
|
|
25
24
|
command: getCommand('ai schema show'),
|
|
26
25
|
description: 'Output CLI schema for AI consumption',
|
|
27
26
|
},
|
|
28
|
-
{
|
|
29
|
-
command: getCommand('ai skills generate --output ./skills'),
|
|
30
|
-
description: 'Generate Agent Skills from CLI schema',
|
|
31
|
-
},
|
|
32
27
|
],
|
|
33
28
|
subcommands: [
|
|
34
29
|
opencodeCommand,
|
|
@@ -36,6 +31,5 @@ export const command = createCommand({
|
|
|
36
31
|
capabilitiesCommand,
|
|
37
32
|
promptCommand,
|
|
38
33
|
schemaCommand,
|
|
39
|
-
skillsCommand,
|
|
40
34
|
],
|
|
41
35
|
});
|
|
@@ -15,6 +15,9 @@ export interface BunDevServerOptions {
|
|
|
15
15
|
deploymentId?: string;
|
|
16
16
|
logger: Logger;
|
|
17
17
|
vitePort: number; // Port of already-running Vite asset server
|
|
18
|
+
inspect?: boolean; // Enable bun debugger
|
|
19
|
+
inspectWait?: boolean; // Enable bun debugger and wait for connection
|
|
20
|
+
inspectBrk?: boolean; // Enable bun debugger with breakpoint at first line
|
|
18
21
|
}
|
|
19
22
|
|
|
20
23
|
export interface BunDevServerResult {
|
|
@@ -30,17 +33,15 @@ export interface BunDevServerResult {
|
|
|
30
33
|
*
|
|
31
34
|
* The bundle is loaded here to ensure AI Gateway routing patches are active.
|
|
32
35
|
* Vite port is read from process.env.VITE_PORT at runtime.
|
|
36
|
+
*
|
|
37
|
+
* When debugger flags (inspect, inspectWait, inspectBrk) are passed, bun is spawned
|
|
38
|
+
* as a subprocess to enable passing the debugger CLI flags.
|
|
33
39
|
*/
|
|
34
40
|
export async function startBunDevServer(options: BunDevServerOptions): Promise<BunDevServerResult> {
|
|
35
|
-
const { rootDir, port = 3500, logger, vitePort } = options;
|
|
41
|
+
const { rootDir, port = 3500, logger, vitePort, inspect, inspectWait, inspectBrk } = options;
|
|
36
42
|
|
|
37
43
|
logger.debug('Starting Bun dev server (Vite already running on port %d)...', vitePort);
|
|
38
44
|
|
|
39
|
-
// Load the bundled app - this will start Bun.serve() internally
|
|
40
|
-
// IMPORTANT: We must import the bundled .agentuity/app.js (NOT src/generated/app.ts)
|
|
41
|
-
// because the bundled version has LLM provider patches applied that enable AI Gateway routing.
|
|
42
|
-
// Importing the source file directly would bypass these patches.
|
|
43
|
-
logger.debug('📦 Loading bundled app (Bun server will start)...');
|
|
44
45
|
const appPath = `${rootDir}/.agentuity/app.js`;
|
|
45
46
|
|
|
46
47
|
// Verify bundle exists before attempting to load
|
|
@@ -54,29 +55,45 @@ export async function startBunDevServer(options: BunDevServerOptions): Promise<B
|
|
|
54
55
|
// Set PORT env var so the generated app uses the correct port
|
|
55
56
|
process.env.PORT = String(port);
|
|
56
57
|
|
|
57
|
-
//
|
|
58
|
-
|
|
59
|
-
// so adding a unique timestamp forces a fresh import on each reload.
|
|
60
|
-
const cacheBuster = `?t=${Date.now()}`;
|
|
61
|
-
try {
|
|
62
|
-
await import(appPath + cacheBuster);
|
|
63
|
-
} catch (err) {
|
|
64
|
-
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
65
|
-
logger.error('Failed to import generated app from %s: %s', appPath, errorMessage);
|
|
66
|
-
throw new Error(`Failed to load generated app: ${errorMessage}`);
|
|
67
|
-
}
|
|
58
|
+
// Check if any debugger flag is enabled
|
|
59
|
+
const useDebugger = inspect || inspectWait || inspectBrk;
|
|
68
60
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
61
|
+
if (useDebugger) {
|
|
62
|
+
// Spawn bun as subprocess with debugger flag
|
|
63
|
+
logger.debug('📦 Spawning bun with debugger enabled...');
|
|
64
|
+
|
|
65
|
+
// Determine which debugger flag to use (priority: inspectBrk > inspectWait > inspect)
|
|
66
|
+
let debugFlag: string;
|
|
67
|
+
if (inspectBrk) {
|
|
68
|
+
debugFlag = '--inspect-brk';
|
|
69
|
+
} else if (inspectWait) {
|
|
70
|
+
debugFlag = '--inspect-wait';
|
|
71
|
+
} else {
|
|
72
|
+
debugFlag = '--inspect';
|
|
73
|
+
}
|
|
74
74
|
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
logger.debug('Using debugger flag: %s', debugFlag);
|
|
76
|
+
|
|
77
|
+
const bunProcess = Bun.spawn(['bun', debugFlag, 'run', appPath], {
|
|
78
|
+
cwd: rootDir,
|
|
79
|
+
stdout: 'inherit',
|
|
80
|
+
stderr: 'inherit',
|
|
81
|
+
env: {
|
|
82
|
+
...process.env,
|
|
83
|
+
PORT: String(port),
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// Store the process globally so it can be killed on shutdown
|
|
77
88
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
78
|
-
|
|
79
|
-
|
|
89
|
+
(globalThis as any).__AGENTUITY_BUN_SUBPROCESS__ = bunProcess;
|
|
90
|
+
|
|
91
|
+
// Wait for server to actually start listening
|
|
92
|
+
const maxRetries = 50;
|
|
93
|
+
const retryDelay = 100;
|
|
94
|
+
let serverReady = false;
|
|
95
|
+
|
|
96
|
+
for (let i = 0; i < maxRetries; i++) {
|
|
80
97
|
try {
|
|
81
98
|
await fetch(`http://127.0.0.1:${port}/`, {
|
|
82
99
|
method: 'HEAD',
|
|
@@ -88,19 +105,79 @@ export async function startBunDevServer(options: BunDevServerOptions): Promise<B
|
|
|
88
105
|
} catch {
|
|
89
106
|
// Connection refused or timeout - server not ready yet
|
|
90
107
|
}
|
|
108
|
+
// Wait before next check
|
|
109
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelay));
|
|
91
110
|
}
|
|
92
|
-
// Wait before next check
|
|
93
|
-
await new Promise((resolve) => setTimeout(resolve, retryDelay));
|
|
94
|
-
}
|
|
95
111
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
112
|
+
if (!serverReady) {
|
|
113
|
+
// Kill the subprocess if server didn't start
|
|
114
|
+
try {
|
|
115
|
+
bunProcess.kill();
|
|
116
|
+
} catch (err) {
|
|
117
|
+
logger.debug('Error killing subprocess during startup failure: %s', err);
|
|
118
|
+
}
|
|
119
|
+
throw new Error(
|
|
120
|
+
`Bun server failed to start on port ${port} after ${maxRetries * retryDelay}ms`
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
logger.debug(`Bun dev server started on http://127.0.0.1:${port} with debugger enabled`);
|
|
125
|
+
logger.debug(`Asset requests (/@vite/*, /src/web/*, etc.) proxied to Vite:${vitePort}`);
|
|
126
|
+
} else {
|
|
127
|
+
// Load the bundled app - this will start Bun.serve() internally
|
|
128
|
+
// IMPORTANT: We must import the bundled .agentuity/app.js (NOT src/generated/app.ts)
|
|
129
|
+
// because the bundled version has LLM provider patches applied that enable AI Gateway routing.
|
|
130
|
+
// Importing the source file directly would bypass these patches.
|
|
131
|
+
logger.debug('📦 Loading bundled app (Bun server will start)...');
|
|
132
|
+
|
|
133
|
+
// Import the generated app with cache-busting query parameter.
|
|
134
|
+
// Bun's module cache is keyed by the full specifier including query string,
|
|
135
|
+
// so adding a unique timestamp forces a fresh import on each reload.
|
|
136
|
+
const cacheBuster = `?t=${Date.now()}`;
|
|
137
|
+
try {
|
|
138
|
+
await import(appPath + cacheBuster);
|
|
139
|
+
} catch (err) {
|
|
140
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
141
|
+
logger.error('Failed to import generated app from %s: %s', appPath, errorMessage);
|
|
142
|
+
throw new Error(`Failed to load generated app: ${errorMessage}`);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Wait for server to actually start listening
|
|
146
|
+
// The generated app sets (globalThis as any).__AGENTUITY_SERVER__ when server starts
|
|
147
|
+
const maxRetries = 50; // Increased retries for slower systems
|
|
148
|
+
const retryDelay = 100; // ms
|
|
149
|
+
let serverReady = false;
|
|
101
150
|
|
|
102
|
-
|
|
103
|
-
|
|
151
|
+
for (let i = 0; i < maxRetries; i++) {
|
|
152
|
+
// Check if global server object exists
|
|
153
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
154
|
+
if ((globalThis as any).__AGENTUITY_SERVER__) {
|
|
155
|
+
// Server object exists, now verify it's actually listening by making a request
|
|
156
|
+
try {
|
|
157
|
+
await fetch(`http://127.0.0.1:${port}/`, {
|
|
158
|
+
method: 'HEAD',
|
|
159
|
+
signal: AbortSignal.timeout(1000),
|
|
160
|
+
});
|
|
161
|
+
// Any response (even 404) means server is listening
|
|
162
|
+
serverReady = true;
|
|
163
|
+
break;
|
|
164
|
+
} catch {
|
|
165
|
+
// Connection refused or timeout - server not ready yet
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
// Wait before next check
|
|
169
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelay));
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (!serverReady) {
|
|
173
|
+
throw new Error(
|
|
174
|
+
`Bun server failed to start on port ${port} after ${maxRetries * retryDelay}ms`
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
logger.debug(`Bun dev server started on http://127.0.0.1:${port}`);
|
|
179
|
+
logger.debug(`Asset requests (/@vite/*, /src/web/*, etc.) proxied to Vite:${vitePort}`);
|
|
180
|
+
}
|
|
104
181
|
|
|
105
182
|
return {
|
|
106
183
|
bunServerPort: port,
|
|
@@ -95,7 +95,9 @@ export const createSubcommand = createSubcommandHelper({
|
|
|
95
95
|
tui.newline();
|
|
96
96
|
tui.success('API key created successfully!');
|
|
97
97
|
tui.newline();
|
|
98
|
-
tui.
|
|
98
|
+
tui.warning(
|
|
99
|
+
'Make sure to copy the API key value now. You will not be able to see it again.'
|
|
100
|
+
);
|
|
99
101
|
tui.newline();
|
|
100
102
|
|
|
101
103
|
const rows = [
|
package/src/cmd/cloud/deploy.ts
CHANGED
|
@@ -168,7 +168,10 @@ export const deploySubcommand = createSubcommand({
|
|
|
168
168
|
const hasTTY = process.stdin.isTTY && process.stdout.isTTY;
|
|
169
169
|
if (project.region) {
|
|
170
170
|
try {
|
|
171
|
-
const serverProject = await projectGet(apiClient, {
|
|
171
|
+
const serverProject = await projectGet(apiClient, {
|
|
172
|
+
id: project.projectId,
|
|
173
|
+
keys: false,
|
|
174
|
+
});
|
|
172
175
|
const serverRegion = serverProject.cloudRegion;
|
|
173
176
|
|
|
174
177
|
if (serverRegion && serverRegion !== project.region) {
|
|
@@ -14,24 +14,30 @@ import { resolveOrgId, isOrgScope } from './org-util';
|
|
|
14
14
|
|
|
15
15
|
const EnvDeleteResponseSchema = z.object({
|
|
16
16
|
success: z.boolean().describe('Whether the operation succeeded'),
|
|
17
|
-
|
|
17
|
+
keys: z.array(z.string()).describe('Variable keys that were deleted'),
|
|
18
18
|
path: z
|
|
19
19
|
.string()
|
|
20
20
|
.optional()
|
|
21
|
-
.describe('Local file path where
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
.describe('Local file path where variables were removed (project scope only)'),
|
|
22
|
+
secrets: z.array(z.string()).describe('Keys that were secrets'),
|
|
23
|
+
env: z.array(z.string()).describe('Keys that were environment variables'),
|
|
24
|
+
scope: z.enum(['project', 'org']).describe('The scope from which the variables were deleted'),
|
|
25
|
+
notFound: z.array(z.string()).optional().describe('Keys that were not found'),
|
|
24
26
|
});
|
|
25
27
|
|
|
26
28
|
export const deleteSubcommand = createSubcommand({
|
|
27
29
|
name: 'delete',
|
|
28
30
|
aliases: ['del', 'remove', 'rm'],
|
|
29
|
-
description: 'Delete
|
|
31
|
+
description: 'Delete one or more environment variables or secrets',
|
|
30
32
|
tags: ['destructive', 'deletes-resource', 'slow', 'requires-auth'],
|
|
31
33
|
idempotent: true,
|
|
32
34
|
examples: [
|
|
33
|
-
{ command: getCommand('env delete OLD_FEATURE_FLAG'), description: 'Delete variable' },
|
|
35
|
+
{ command: getCommand('env delete OLD_FEATURE_FLAG'), description: 'Delete a variable' },
|
|
34
36
|
{ command: getCommand('env rm API_KEY'), description: 'Delete a secret' },
|
|
37
|
+
{
|
|
38
|
+
command: getCommand('env rm KEY1 KEY2 KEY3'),
|
|
39
|
+
description: 'Delete multiple variables at once',
|
|
40
|
+
},
|
|
35
41
|
{
|
|
36
42
|
command: getCommand('env rm OPENAI_API_KEY --org'),
|
|
37
43
|
description: 'Delete org-level secret',
|
|
@@ -41,7 +47,7 @@ export const deleteSubcommand = createSubcommand({
|
|
|
41
47
|
optional: { project: true },
|
|
42
48
|
schema: {
|
|
43
49
|
args: z.object({
|
|
44
|
-
key: z.string().describe('the variable or secret key to delete'),
|
|
50
|
+
key: z.array(z.string()).describe('the variable or secret key(s) to delete'),
|
|
45
51
|
}),
|
|
46
52
|
options: z.object({
|
|
47
53
|
org: z
|
|
@@ -57,6 +63,7 @@ export const deleteSubcommand = createSubcommand({
|
|
|
57
63
|
async handler(ctx) {
|
|
58
64
|
const { args, project, projectDir, apiClient, config, opts } = ctx;
|
|
59
65
|
const useOrgScope = isOrgScope(opts?.org);
|
|
66
|
+
const keys = args.key;
|
|
60
67
|
|
|
61
68
|
// Require project context if not using org scope
|
|
62
69
|
if (!useOrgScope && !project) {
|
|
@@ -65,10 +72,11 @@ export const deleteSubcommand = createSubcommand({
|
|
|
65
72
|
);
|
|
66
73
|
}
|
|
67
74
|
|
|
68
|
-
// Validate
|
|
69
|
-
|
|
75
|
+
// Validate no keys start with reserved AGENTUITY_ prefix (except AGENTUITY_PUBLIC_)
|
|
76
|
+
const reservedKeys = keys.filter(isReservedAgentuityKey);
|
|
77
|
+
if (reservedKeys.length > 0) {
|
|
70
78
|
tui.fatal(
|
|
71
|
-
|
|
79
|
+
`Cannot delete AGENTUITY_ prefixed variables: ${reservedKeys.join(', ')}. These are reserved for system use.`
|
|
72
80
|
);
|
|
73
81
|
}
|
|
74
82
|
|
|
@@ -76,85 +84,132 @@ export const deleteSubcommand = createSubcommand({
|
|
|
76
84
|
// Organization scope
|
|
77
85
|
const orgId = await resolveOrgId(apiClient, config, opts!.org!);
|
|
78
86
|
|
|
79
|
-
// First, determine
|
|
80
|
-
const orgData = await tui.spinner('Checking organization
|
|
87
|
+
// First, determine which keys exist in env or secrets
|
|
88
|
+
const orgData = await tui.spinner('Checking organization variables', () => {
|
|
81
89
|
return orgEnvGet(apiClient, { id: orgId, mask: true });
|
|
82
90
|
});
|
|
83
91
|
|
|
84
|
-
const
|
|
85
|
-
const
|
|
92
|
+
const secretKeys: string[] = [];
|
|
93
|
+
const envKeys: string[] = [];
|
|
94
|
+
const notFoundKeys: string[] = [];
|
|
95
|
+
|
|
96
|
+
for (const key of keys) {
|
|
97
|
+
if (orgData.secrets?.[key] !== undefined) {
|
|
98
|
+
secretKeys.push(key);
|
|
99
|
+
} else if (orgData.env?.[key] !== undefined) {
|
|
100
|
+
envKeys.push(key);
|
|
101
|
+
} else {
|
|
102
|
+
notFoundKeys.push(key);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
86
105
|
|
|
87
|
-
|
|
106
|
+
// If all keys are not found, fail
|
|
107
|
+
if (secretKeys.length === 0 && envKeys.length === 0) {
|
|
88
108
|
tui.fatal(
|
|
89
|
-
`
|
|
109
|
+
`No variables found in organization: ${keys.join(', ')}`,
|
|
90
110
|
ErrorCode.RESOURCE_NOT_FOUND
|
|
91
111
|
);
|
|
92
112
|
}
|
|
93
113
|
|
|
94
|
-
// Delete from cloud
|
|
95
|
-
const
|
|
96
|
-
|
|
114
|
+
// Delete from cloud (batch operation)
|
|
115
|
+
const totalToDelete = secretKeys.length + envKeys.length;
|
|
116
|
+
const label = totalToDelete === 1 ? 'variable' : 'variables';
|
|
117
|
+
await tui.spinner(`Deleting ${totalToDelete} organization ${label} from cloud`, () => {
|
|
97
118
|
return orgEnvDelete(apiClient, {
|
|
98
119
|
id: orgId,
|
|
99
|
-
...(
|
|
120
|
+
...(secretKeys.length > 0 ? { secrets: secretKeys } : {}),
|
|
121
|
+
...(envKeys.length > 0 ? { env: envKeys } : {}),
|
|
100
122
|
});
|
|
101
123
|
});
|
|
102
124
|
|
|
125
|
+
const deletedKeys = [...secretKeys, ...envKeys];
|
|
126
|
+
if (notFoundKeys.length > 0) {
|
|
127
|
+
tui.warning(`Variables not found (skipped): ${notFoundKeys.join(', ')}`);
|
|
128
|
+
}
|
|
103
129
|
tui.success(
|
|
104
|
-
`
|
|
130
|
+
`Deleted ${deletedKeys.length} organization variable(s): ${deletedKeys.join(', ')}`
|
|
105
131
|
);
|
|
106
132
|
|
|
107
133
|
return {
|
|
108
134
|
success: true,
|
|
109
|
-
|
|
110
|
-
|
|
135
|
+
keys: deletedKeys,
|
|
136
|
+
secrets: secretKeys,
|
|
137
|
+
env: envKeys,
|
|
111
138
|
scope: 'org' as const,
|
|
139
|
+
...(notFoundKeys.length > 0 ? { notFound: notFoundKeys } : {}),
|
|
112
140
|
};
|
|
113
141
|
} else {
|
|
114
|
-
// Project scope
|
|
115
|
-
const projectData = await tui.spinner('Checking
|
|
142
|
+
// Project scope
|
|
143
|
+
const projectData = await tui.spinner('Checking variables', () => {
|
|
116
144
|
return projectGet(apiClient, { id: project!.projectId, mask: true });
|
|
117
145
|
});
|
|
118
146
|
|
|
119
|
-
const
|
|
120
|
-
const
|
|
147
|
+
const secretKeys: string[] = [];
|
|
148
|
+
const envKeys: string[] = [];
|
|
149
|
+
const notFoundKeys: string[] = [];
|
|
150
|
+
|
|
151
|
+
for (const key of keys) {
|
|
152
|
+
if (projectData.secrets?.[key] !== undefined) {
|
|
153
|
+
secretKeys.push(key);
|
|
154
|
+
} else if (projectData.env?.[key] !== undefined) {
|
|
155
|
+
envKeys.push(key);
|
|
156
|
+
} else {
|
|
157
|
+
notFoundKeys.push(key);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
121
160
|
|
|
122
|
-
|
|
123
|
-
|
|
161
|
+
// If all keys are not found, fail
|
|
162
|
+
if (secretKeys.length === 0 && envKeys.length === 0) {
|
|
163
|
+
tui.fatal(`No variables found: ${keys.join(', ')}`, ErrorCode.RESOURCE_NOT_FOUND);
|
|
124
164
|
}
|
|
125
165
|
|
|
126
|
-
// Delete from cloud
|
|
127
|
-
const
|
|
128
|
-
|
|
166
|
+
// Delete from cloud (batch operation)
|
|
167
|
+
const totalToDelete = secretKeys.length + envKeys.length;
|
|
168
|
+
const label = totalToDelete === 1 ? 'variable' : 'variables';
|
|
169
|
+
await tui.spinner(`Deleting ${totalToDelete} ${label} from cloud`, () => {
|
|
129
170
|
return projectEnvDelete(apiClient, {
|
|
130
171
|
id: project!.projectId,
|
|
131
|
-
...(
|
|
172
|
+
...(secretKeys.length > 0 ? { secrets: secretKeys } : {}),
|
|
173
|
+
...(envKeys.length > 0 ? { env: envKeys } : {}),
|
|
132
174
|
});
|
|
133
175
|
});
|
|
134
176
|
|
|
135
|
-
// Update local .env file only if we have a project directory
|
|
136
|
-
// (not when using --project-id without being in a project folder)
|
|
177
|
+
// Update local .env file only if we have a project directory and an existing .env file
|
|
137
178
|
let envFilePath: string | undefined;
|
|
138
179
|
if (projectDir) {
|
|
139
180
|
envFilePath = await findExistingEnvFile(projectDir);
|
|
140
|
-
|
|
141
|
-
|
|
181
|
+
if (envFilePath) {
|
|
182
|
+
const currentEnv = await readEnvFile(envFilePath);
|
|
183
|
+
const originalKeyCount = Object.keys(currentEnv).length;
|
|
184
|
+
for (const key of [...secretKeys, ...envKeys]) {
|
|
185
|
+
delete currentEnv[key];
|
|
186
|
+
}
|
|
187
|
+
// Only write if we actually removed keys (avoid creating empty file)
|
|
188
|
+
const keysRemoved = originalKeyCount > Object.keys(currentEnv).length;
|
|
189
|
+
if (keysRemoved) {
|
|
190
|
+
await writeEnvFile(envFilePath, currentEnv, { preserveExisting: false });
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
142
194
|
|
|
143
|
-
|
|
144
|
-
|
|
195
|
+
const deletedKeys = [...secretKeys, ...envKeys];
|
|
196
|
+
if (notFoundKeys.length > 0) {
|
|
197
|
+
tui.warning(`Variables not found (skipped): ${notFoundKeys.join(', ')}`);
|
|
145
198
|
}
|
|
146
199
|
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
200
|
+
const locationMsg = envFilePath ? ` (cloud + ${envFilePath})` : ' (cloud only)';
|
|
201
|
+
tui.success(
|
|
202
|
+
`Deleted ${deletedKeys.length} variable(s): ${deletedKeys.join(', ')}${locationMsg}`
|
|
203
|
+
);
|
|
151
204
|
|
|
152
205
|
return {
|
|
153
206
|
success: true,
|
|
154
|
-
|
|
207
|
+
keys: deletedKeys,
|
|
155
208
|
path: envFilePath,
|
|
156
|
-
|
|
209
|
+
secrets: secretKeys,
|
|
210
|
+
env: envKeys,
|
|
157
211
|
scope: 'project' as const,
|
|
212
|
+
...(notFoundKeys.length > 0 ? { notFound: notFoundKeys } : {}),
|
|
158
213
|
};
|
|
159
214
|
}
|
|
160
215
|
},
|
|
@@ -2,12 +2,7 @@ import { z } from 'zod';
|
|
|
2
2
|
import { createSubcommand } from '../../../types';
|
|
3
3
|
import * as tui from '../../../tui';
|
|
4
4
|
import { projectGet, orgEnvGet } from '@agentuity/server';
|
|
5
|
-
import {
|
|
6
|
-
findExistingEnvFile,
|
|
7
|
-
readEnvFile,
|
|
8
|
-
writeEnvFile,
|
|
9
|
-
mergeEnvVars,
|
|
10
|
-
} from '../../../env-util';
|
|
5
|
+
import { findExistingEnvFile, readEnvFile, writeEnvFile, mergeEnvVars } from '../../../env-util';
|
|
11
6
|
import { getCommand } from '../../../command-prefix';
|
|
12
7
|
import { resolveOrgId, isOrgScope } from './org-util';
|
|
13
8
|
|
|
@@ -49,7 +49,7 @@ export const deleteSubcommand = createSubcommand({
|
|
|
49
49
|
if (!opts.confirm) {
|
|
50
50
|
if (process.stdin.isTTY) {
|
|
51
51
|
tui.newline();
|
|
52
|
-
tui.
|
|
52
|
+
tui.warning(`You are about to delete machine ${tui.bold(machine.id)}`);
|
|
53
53
|
if (machine.orgName) {
|
|
54
54
|
tui.info(`Organization: ${machine.orgName}`);
|
|
55
55
|
}
|
package/src/cmd/dev/index.ts
CHANGED
|
@@ -18,7 +18,6 @@ import { typecheck } from '../build/typecheck';
|
|
|
18
18
|
import { validateGravityRequiresUpgrade } from '../../runtime';
|
|
19
19
|
import { isTTY, hasLoggedInBefore } from '../../auth';
|
|
20
20
|
import { createFileWatcher } from './file-watcher';
|
|
21
|
-
import { regenerateSkillsAsync } from './skills';
|
|
22
21
|
import { prepareDevLock, releaseLockSync } from './dev-lock';
|
|
23
22
|
import { checkAndUpgradeDependencies } from '../../utils/dependency-checker';
|
|
24
23
|
import { ErrorCode } from '../../errors';
|
|
@@ -81,6 +80,7 @@ async function killLingeringGravityProcesses(logger: {
|
|
|
81
80
|
/**
|
|
82
81
|
* Stop the existing Bun server if one is running.
|
|
83
82
|
* Waits for the port to become available before returning (with timeout).
|
|
83
|
+
* Handles both in-process server and subprocess (when debugger is enabled).
|
|
84
84
|
*/
|
|
85
85
|
async function stopBunServer(
|
|
86
86
|
port: number,
|
|
@@ -88,6 +88,48 @@ async function stopBunServer(
|
|
|
88
88
|
): Promise<void> {
|
|
89
89
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
90
90
|
const globalAny = globalThis as any;
|
|
91
|
+
|
|
92
|
+
// Check for subprocess first (used when debugger flags are enabled)
|
|
93
|
+
const bunSubprocess = globalAny.__AGENTUITY_BUN_SUBPROCESS__ as ProcessLike | undefined;
|
|
94
|
+
if (bunSubprocess) {
|
|
95
|
+
logger.debug('Stopping Bun subprocess...');
|
|
96
|
+
try {
|
|
97
|
+
bunSubprocess.kill('SIGTERM');
|
|
98
|
+
// After SIGTERM, wait and check multiple times before giving up
|
|
99
|
+
let attempts = 0;
|
|
100
|
+
while (bunSubprocess.exitCode === null && attempts < 3) {
|
|
101
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
102
|
+
attempts++;
|
|
103
|
+
}
|
|
104
|
+
if (bunSubprocess.exitCode === null) {
|
|
105
|
+
bunSubprocess.kill('SIGKILL');
|
|
106
|
+
}
|
|
107
|
+
logger.debug('Bun subprocess killed');
|
|
108
|
+
} catch (err) {
|
|
109
|
+
logger.debug('Error killing Bun subprocess: %s', err);
|
|
110
|
+
}
|
|
111
|
+
globalAny.__AGENTUITY_BUN_SUBPROCESS__ = undefined;
|
|
112
|
+
|
|
113
|
+
// Wait for port to become available
|
|
114
|
+
const MAX_WAIT_ITERATIONS = 10;
|
|
115
|
+
for (let i = 0; i < MAX_WAIT_ITERATIONS; i++) {
|
|
116
|
+
try {
|
|
117
|
+
await fetch(`http://127.0.0.1:${port}/`, {
|
|
118
|
+
method: 'HEAD',
|
|
119
|
+
signal: AbortSignal.timeout(150),
|
|
120
|
+
});
|
|
121
|
+
// Still responding, wait a bit more
|
|
122
|
+
await new Promise((r) => setTimeout(r, 50));
|
|
123
|
+
} catch {
|
|
124
|
+
// Connection refused or timeout => server is down
|
|
125
|
+
logger.debug('Bun subprocess stopped');
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Handle in-process server
|
|
91
133
|
const server = globalAny.__AGENTUITY_SERVER__ as BunServer | undefined;
|
|
92
134
|
if (!server) {
|
|
93
135
|
logger.debug('No Bun server to stop');
|
|
@@ -171,6 +213,15 @@ export const command = createCommand({
|
|
|
171
213
|
.max(MAX_PORT)
|
|
172
214
|
.default(getDefaultPort())
|
|
173
215
|
.describe('The TCP port to start the dev server (also reads from PORT env)'),
|
|
216
|
+
inspect: z.boolean().optional().describe('Enable bun debugger on available port'),
|
|
217
|
+
inspectWait: z
|
|
218
|
+
.boolean()
|
|
219
|
+
.optional()
|
|
220
|
+
.describe('Enable bun debugger and wait for connection before executing'),
|
|
221
|
+
inspectBrk: z
|
|
222
|
+
.boolean()
|
|
223
|
+
.optional()
|
|
224
|
+
.describe('Enable bun debugger with breakpoint at first line'),
|
|
174
225
|
}),
|
|
175
226
|
},
|
|
176
227
|
optional: { project: true },
|
|
@@ -489,12 +540,6 @@ export const command = createCommand({
|
|
|
489
540
|
centerTitle: false,
|
|
490
541
|
});
|
|
491
542
|
|
|
492
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
493
|
-
const cliVersion = ((global as any).__CLI_SCHEMA__?.version as string) ?? '';
|
|
494
|
-
if (cliVersion) {
|
|
495
|
-
regenerateSkillsAsync(rootDir, cliVersion, logger).catch(() => {});
|
|
496
|
-
}
|
|
497
|
-
|
|
498
543
|
// Start Vite asset server ONCE before restart loop
|
|
499
544
|
// Vite handles frontend HMR independently and stays running across backend restarts
|
|
500
545
|
let viteServer: ServerLike | null = null;
|
|
@@ -961,7 +1006,7 @@ export const command = createCommand({
|
|
|
961
1006
|
}
|
|
962
1007
|
} catch (error) {
|
|
963
1008
|
tui.error(`Failed to build dev bundle: ${error}`);
|
|
964
|
-
tui.
|
|
1009
|
+
tui.warning('Waiting for file changes to retry...');
|
|
965
1010
|
|
|
966
1011
|
// Resume watcher to detect changes for retry
|
|
967
1012
|
fileWatcher.resume();
|
|
@@ -986,7 +1031,7 @@ export const command = createCommand({
|
|
|
986
1031
|
if (sdkKey) {
|
|
987
1032
|
process.env.AGENTUITY_SDK_KEY = sdkKey;
|
|
988
1033
|
} else if (project) {
|
|
989
|
-
tui.
|
|
1034
|
+
tui.warning(
|
|
990
1035
|
'AGENTUITY_SDK_KEY not found in .env file. Numerous features will be unavailable.'
|
|
991
1036
|
);
|
|
992
1037
|
tui.bullet(
|
|
@@ -1035,6 +1080,9 @@ export const command = createCommand({
|
|
|
1035
1080
|
deploymentId,
|
|
1036
1081
|
logger,
|
|
1037
1082
|
vitePort, // Pass port of already-running Vite server
|
|
1083
|
+
inspect: opts.inspect,
|
|
1084
|
+
inspectWait: opts.inspectWait,
|
|
1085
|
+
inspectBrk: opts.inspectBrk,
|
|
1038
1086
|
});
|
|
1039
1087
|
|
|
1040
1088
|
// Wait for app.ts to finish loading (Vite is ready but app may still be initializing)
|
|
@@ -1047,7 +1095,7 @@ export const command = createCommand({
|
|
|
1047
1095
|
}
|
|
1048
1096
|
} catch (error) {
|
|
1049
1097
|
tui.error(`Failed to start dev server: ${error}`);
|
|
1050
|
-
tui.
|
|
1098
|
+
tui.warning('Waiting for file changes to retry...');
|
|
1051
1099
|
|
|
1052
1100
|
// Wait for next restart trigger or shutdown
|
|
1053
1101
|
await new Promise<void>((resolve) => {
|
|
@@ -1274,7 +1322,7 @@ export const command = createCommand({
|
|
|
1274
1322
|
await Bun.sleep(500);
|
|
1275
1323
|
} catch (error) {
|
|
1276
1324
|
tui.error(`Error during server operation: ${error}`);
|
|
1277
|
-
tui.
|
|
1325
|
+
tui.warning('Waiting for file changes to retry...');
|
|
1278
1326
|
|
|
1279
1327
|
// Cleanup on error (Vite stays running)
|
|
1280
1328
|
await cleanupForRestart();
|
package/src/cmd/index.ts
CHANGED
|
@@ -15,6 +15,7 @@ export async function discoverCommands(): Promise<CommandDefinition[]> {
|
|
|
15
15
|
import('./project').then((m) => m.command),
|
|
16
16
|
import('./repl').then((m) => m.command),
|
|
17
17
|
import('./setup').then((m) => m.command),
|
|
18
|
+
import('./support').then((m) => m.command),
|
|
18
19
|
import('./upgrade').then((m) => m.command),
|
|
19
20
|
import('./version').then((m) => m.command),
|
|
20
21
|
]);
|