@agentuity/cli 0.1.33 → 0.1.35
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 +107 -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/cloud/sandbox/exec.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/exec.js +10 -35
- package/dist/cmd/cloud/sandbox/exec.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 +340 -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/dist/utils/installation-type.d.ts.map +1 -1
- package/dist/utils/installation-type.js +54 -16
- package/dist/utils/installation-type.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/cloud/sandbox/exec.ts +10 -41
- 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 +411 -0
- package/src/types.ts +6 -0
- package/src/utils/installation-type.ts +55 -16
- 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
|
@@ -1,7 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Detects how the CLI was installed and is being run
|
|
3
3
|
*/
|
|
4
|
+
import fs from 'node:fs';
|
|
4
5
|
import os from 'node:os';
|
|
6
|
+
/**
|
|
7
|
+
* Resolve a path to its real path (following symlinks) and normalize to POSIX separators.
|
|
8
|
+
* Returns the original path if resolution fails.
|
|
9
|
+
*/
|
|
10
|
+
function resolveRealPath(path) {
|
|
11
|
+
if (!path)
|
|
12
|
+
return '';
|
|
13
|
+
try {
|
|
14
|
+
// fs.realpathSync resolves symlinks (e.g., /tmp -> /private/tmp on macOS)
|
|
15
|
+
return fs.realpathSync(path).replace(/\\/g, '/');
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
// If the path doesn't exist or can't be resolved, return normalized original
|
|
19
|
+
return path.replace(/\\/g, '/');
|
|
20
|
+
}
|
|
21
|
+
}
|
|
5
22
|
/**
|
|
6
23
|
* Determines the installation type based on how the CLI is being executed
|
|
7
24
|
*
|
|
@@ -10,29 +27,50 @@ import os from 'node:os';
|
|
|
10
27
|
* @returns 'source' - Running from source code (development)
|
|
11
28
|
*/
|
|
12
29
|
export function getInstallationType() {
|
|
13
|
-
//
|
|
30
|
+
// Bun.main already returns the resolved real path, just normalize separators
|
|
14
31
|
const mainPath = Bun.main.replace(/\\/g, '/');
|
|
15
|
-
//
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
//
|
|
19
|
-
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
//
|
|
23
|
-
//
|
|
24
|
-
|
|
25
|
-
|
|
32
|
+
// Get home directory reliably and resolve symlinks
|
|
33
|
+
// On macOS, os.homedir() returns /Users/xxx which is already real
|
|
34
|
+
const home = resolveRealPath(os.homedir() ?? process.env.HOME ?? process.env.USERPROFILE ?? '');
|
|
35
|
+
// Get bun install directory from BUN_INSTALL or default to ~/.bun
|
|
36
|
+
// Resolve symlinks to handle cases like BUN_INSTALL=/tmp/... on macOS where /tmp -> /private/tmp
|
|
37
|
+
const bunInstallRaw = process.env.BUN_INSTALL ?? (home ? `${home}/.bun` : '');
|
|
38
|
+
const bunInstall = resolveRealPath(bunInstallRaw);
|
|
39
|
+
// GLOBAL DETECTION: Check if running from bun's global install location
|
|
40
|
+
// When installed via `bun add -g`, the CLI lives at ~/.bun/node_modules/@agentuity/cli/
|
|
41
|
+
// or ~/.bun/install/global/node_modules/@agentuity/cli/
|
|
42
|
+
if (bunInstall) {
|
|
43
|
+
// Check for ~/.bun/node_modules/@agentuity/cli/ (common bun global layout)
|
|
44
|
+
if (mainPath.startsWith(`${bunInstall}/node_modules/@agentuity/cli/`)) {
|
|
45
|
+
return 'global';
|
|
46
|
+
}
|
|
47
|
+
// Check for ~/.bun/install/global/node_modules/@agentuity/cli/ (alternative layout)
|
|
48
|
+
if (mainPath.startsWith(`${bunInstall}/install/global/`)) {
|
|
49
|
+
return 'global';
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// GLOBAL DETECTION: Check for legacy ~/.agentuity/ installation
|
|
53
|
+
// The install.sh script may install to ~/.agentuity/node_modules/@agentuity/cli/
|
|
54
|
+
// or create a shim at ~/.agentuity/bin/agentuity
|
|
55
|
+
if (home) {
|
|
56
|
+
const agentuityDir = resolveRealPath(`${home}/.agentuity`);
|
|
57
|
+
if (mainPath.startsWith(`${agentuityDir}/`)) {
|
|
58
|
+
return 'global';
|
|
59
|
+
}
|
|
26
60
|
}
|
|
27
|
-
//
|
|
28
|
-
|
|
61
|
+
// GLOBAL DETECTION: Fallback check for any path containing /.bun/ before node_modules
|
|
62
|
+
// This catches edge cases where BUN_INSTALL might not match the actual path
|
|
63
|
+
if (mainPath.includes('/.bun/') && mainPath.includes('/node_modules/@agentuity/cli/')) {
|
|
29
64
|
return 'global';
|
|
30
65
|
}
|
|
31
|
-
//
|
|
66
|
+
// LOCAL DETECTION: Running from a project's node_modules
|
|
67
|
+
// This is when someone runs `bunx agentuity` or has it as a project dependency
|
|
68
|
+
// At this point, we've ruled out global installs, so any node_modules path is local
|
|
32
69
|
if (mainPath.includes('/node_modules/@agentuity/cli/')) {
|
|
33
70
|
return 'local';
|
|
34
71
|
}
|
|
35
|
-
//
|
|
72
|
+
// SOURCE DETECTION: Running from source code (development)
|
|
73
|
+
// This is when running directly from the monorepo: packages/cli/bin/cli.ts
|
|
36
74
|
return 'source';
|
|
37
75
|
}
|
|
38
76
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"installation-type.js","sourceRoot":"","sources":["../../src/utils/installation-type.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AAIzB
|
|
1
|
+
{"version":3,"file":"installation-type.js","sourceRoot":"","sources":["../../src/utils/installation-type.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,MAAM,SAAS,CAAC;AAIzB;;;GAGG;AACH,SAAS,eAAe,CAAC,IAAY;IACpC,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,CAAC;IACrB,IAAI,CAAC;QACJ,0EAA0E;QAC1E,OAAO,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAClD,CAAC;IAAC,MAAM,CAAC;QACR,6EAA6E;QAC7E,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACjC,CAAC;AACF,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB;IAClC,6EAA6E;IAC7E,MAAM,QAAQ,GAAG,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAE9C,mDAAmD;IACnD,kEAAkE;IAClE,MAAM,IAAI,GAAG,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;IAEhG,kEAAkE;IAClE,iGAAiG;IACjG,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAC9E,MAAM,UAAU,GAAG,eAAe,CAAC,aAAa,CAAC,CAAC;IAElD,wEAAwE;IACxE,wFAAwF;IACxF,wDAAwD;IACxD,IAAI,UAAU,EAAE,CAAC;QAChB,2EAA2E;QAC3E,IAAI,QAAQ,CAAC,UAAU,CAAC,GAAG,UAAU,+BAA+B,CAAC,EAAE,CAAC;YACvE,OAAO,QAAQ,CAAC;QACjB,CAAC;QACD,oFAAoF;QACpF,IAAI,QAAQ,CAAC,UAAU,CAAC,GAAG,UAAU,kBAAkB,CAAC,EAAE,CAAC;YAC1D,OAAO,QAAQ,CAAC;QACjB,CAAC;IACF,CAAC;IAED,gEAAgE;IAChE,iFAAiF;IACjF,iDAAiD;IACjD,IAAI,IAAI,EAAE,CAAC;QACV,MAAM,YAAY,GAAG,eAAe,CAAC,GAAG,IAAI,aAAa,CAAC,CAAC;QAC3D,IAAI,QAAQ,CAAC,UAAU,CAAC,GAAG,YAAY,GAAG,CAAC,EAAE,CAAC;YAC7C,OAAO,QAAQ,CAAC;QACjB,CAAC;IACF,CAAC;IAED,sFAAsF;IACtF,4EAA4E;IAC5E,IAAI,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,+BAA+B,CAAC,EAAE,CAAC;QACvF,OAAO,QAAQ,CAAC;IACjB,CAAC;IAED,yDAAyD;IACzD,+EAA+E;IAC/E,oFAAoF;IACpF,IAAI,QAAQ,CAAC,QAAQ,CAAC,+BAA+B,CAAC,EAAE,CAAC;QACxD,OAAO,OAAO,CAAC;IAChB,CAAC;IAED,2DAA2D;IAC3D,2EAA2E;IAC3E,OAAO,QAAQ,CAAC;AACjB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe;IAC9B,OAAO,mBAAmB,EAAE,KAAK,QAAQ,CAAC;AAC3C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc;IAC7B,OAAO,mBAAmB,EAAE,KAAK,OAAO,CAAC;AAC1C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe;IAC9B,OAAO,mBAAmB,EAAE,KAAK,QAAQ,CAAC;AAC3C,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentuity/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.35",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"author": "Agentuity employees and contributors",
|
|
6
6
|
"type": "module",
|
|
@@ -40,9 +40,9 @@
|
|
|
40
40
|
"prepublishOnly": "bun run clean && bun run build"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@agentuity/auth": "0.1.
|
|
44
|
-
"@agentuity/core": "0.1.
|
|
45
|
-
"@agentuity/server": "0.1.
|
|
43
|
+
"@agentuity/auth": "0.1.35",
|
|
44
|
+
"@agentuity/core": "0.1.35",
|
|
45
|
+
"@agentuity/server": "0.1.35",
|
|
46
46
|
"@datasert/cronjs-parser": "^1.4.0",
|
|
47
47
|
"@terascope/fetch-github-release": "^2.2.1",
|
|
48
48
|
"@vitejs/plugin-react": "^5.1.2",
|
|
@@ -60,10 +60,10 @@
|
|
|
60
60
|
"typescript": "^5.9.0",
|
|
61
61
|
"vite": "^7.2.7",
|
|
62
62
|
"zod": "^4.3.5",
|
|
63
|
-
"@agentuity/frontend": "0.1.
|
|
63
|
+
"@agentuity/frontend": "0.1.35"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
|
-
"@agentuity/test-utils": "0.1.
|
|
66
|
+
"@agentuity/test-utils": "0.1.35",
|
|
67
67
|
"@types/adm-zip": "^0.5.7",
|
|
68
68
|
"@types/bun": "latest",
|
|
69
69
|
"@types/tar-fs": "^2.0.4",
|
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
|
}
|