@agentuity/cli 0.1.26 → 0.1.28
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 +14 -4
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +6 -3
- package/dist/auth.js.map +1 -1
- package/dist/cmd/auth/login.d.ts.map +1 -1
- package/dist/cmd/auth/login.js +2 -1
- package/dist/cmd/auth/login.js.map +1 -1
- package/dist/cmd/build/ast.d.ts.map +1 -1
- package/dist/cmd/build/ast.js +14 -26
- 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 +7 -13
- package/dist/cmd/build/entry-generator.js.map +1 -1
- package/dist/cmd/build/vite/api-mount-path.d.ts +61 -0
- package/dist/cmd/build/vite/api-mount-path.d.ts.map +1 -0
- package/dist/cmd/build/vite/api-mount-path.js +83 -0
- package/dist/cmd/build/vite/api-mount-path.js.map +1 -0
- package/dist/cmd/cloud/deploy.d.ts.map +1 -1
- package/dist/cmd/cloud/deploy.js +4 -2
- package/dist/cmd/cloud/deploy.js.map +1 -1
- package/dist/version-check.d.ts +2 -2
- package/dist/version-check.d.ts.map +1 -1
- package/dist/version-check.js +18 -3
- package/dist/version-check.js.map +1 -1
- package/package.json +6 -6
- package/src/auth.ts +6 -3
- package/src/cmd/auth/login.ts +2 -1
- package/src/cmd/build/ast.ts +18 -27
- package/src/cmd/build/entry-generator.ts +8 -14
- package/src/cmd/build/vite/api-mount-path.ts +87 -0
- package/src/cmd/cloud/deploy.ts +4 -1
- package/src/version-check.ts +22 -2
package/src/cmd/build/ast.ts
CHANGED
|
@@ -11,6 +11,11 @@ import type { LogLevel } from '../../types';
|
|
|
11
11
|
import { existsSync, mkdirSync } from 'node:fs';
|
|
12
12
|
import JSON5 from 'json5';
|
|
13
13
|
import { formatSchemaCode } from './format-schema';
|
|
14
|
+
import {
|
|
15
|
+
computeApiMountPath,
|
|
16
|
+
joinMountAndRoute,
|
|
17
|
+
extractRelativeApiPath,
|
|
18
|
+
} from './vite/api-mount-path';
|
|
14
19
|
|
|
15
20
|
const logger = createLogger((process.env.AGENTUITY_LOG_LEVEL || 'info') as LogLevel);
|
|
16
21
|
|
|
@@ -1492,26 +1497,18 @@ export async function parseRoute(
|
|
|
1492
1497
|
|
|
1493
1498
|
const rel = relative(rootDir, filename);
|
|
1494
1499
|
|
|
1495
|
-
//
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
//
|
|
1499
|
-
//
|
|
1500
|
-
//
|
|
1501
|
-
//
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
if (apiMatch) {
|
|
1506
|
-
// File in subdirectory: src/api/auth/route.ts -> "auth"
|
|
1507
|
-
routeName = apiMatch[1];
|
|
1508
|
-
}
|
|
1509
|
-
// For files directly in src/api/ (e.g., test.ts), routeName stays empty
|
|
1510
|
-
// This prevents double /api prefix since these files often define full paths
|
|
1511
|
-
}
|
|
1500
|
+
// Compute the API mount path using the shared helper
|
|
1501
|
+
// This ensures consistency between route type generation (here) and runtime mounting (entry-generator.ts)
|
|
1502
|
+
// Examples:
|
|
1503
|
+
// src/api/index.ts -> basePath = '/api'
|
|
1504
|
+
// src/api/sessions.ts -> basePath = '/api/sessions'
|
|
1505
|
+
// src/api/auth/route.ts -> basePath = '/api/auth'
|
|
1506
|
+
// src/api/users/profile/route.ts -> basePath = '/api/users/profile'
|
|
1507
|
+
const srcDir = join(rootDir, 'src');
|
|
1508
|
+
const relativeApiPath = extractRelativeApiPath(filename, srcDir);
|
|
1509
|
+
const basePath = computeApiMountPath(relativeApiPath);
|
|
1512
1510
|
|
|
1513
1511
|
const routes: RouteDefinition = [];
|
|
1514
|
-
const routePrefix = '/api';
|
|
1515
1512
|
|
|
1516
1513
|
try {
|
|
1517
1514
|
for (const body of ast.body) {
|
|
@@ -1593,9 +1590,7 @@ export async function parseRoute(
|
|
|
1593
1590
|
|
|
1594
1591
|
// Create a route entry for each method
|
|
1595
1592
|
for (const httpMethod of methods) {
|
|
1596
|
-
const thepath =
|
|
1597
|
-
.replaceAll(/\/{2,}/g, '/')
|
|
1598
|
-
.replaceAll(/\/$/g, '');
|
|
1593
|
+
const thepath = joinMountAndRoute(basePath, pathSuffix);
|
|
1599
1594
|
const id = generateRouteId(
|
|
1600
1595
|
projectId,
|
|
1601
1596
|
deploymentId,
|
|
@@ -1692,9 +1687,7 @@ export async function parseRoute(
|
|
|
1692
1687
|
|
|
1693
1688
|
// Create a route entry for each supported method
|
|
1694
1689
|
for (const httpMethod of SUPPORTED_HTTP_METHODS) {
|
|
1695
|
-
const thepath =
|
|
1696
|
-
.replaceAll(/\/{2,}/g, '/')
|
|
1697
|
-
.replaceAll(/\/$/g, '');
|
|
1690
|
+
const thepath = joinMountAndRoute(basePath, pathSuffix);
|
|
1698
1691
|
const id = generateRouteId(
|
|
1699
1692
|
projectId,
|
|
1700
1693
|
deploymentId,
|
|
@@ -1888,9 +1881,7 @@ export async function parseRoute(
|
|
|
1888
1881
|
});
|
|
1889
1882
|
}
|
|
1890
1883
|
}
|
|
1891
|
-
const thepath =
|
|
1892
|
-
.replaceAll(/\/{2,}/g, '/')
|
|
1893
|
-
.replaceAll(/\/$/g, '');
|
|
1884
|
+
const thepath = joinMountAndRoute(basePath, suffix);
|
|
1894
1885
|
const id = generateRouteId(
|
|
1895
1886
|
projectId,
|
|
1896
1887
|
deploymentId,
|
|
@@ -7,6 +7,7 @@ import { join } from 'node:path';
|
|
|
7
7
|
import type { Logger, WorkbenchConfig, AnalyticsConfig } from '../../types';
|
|
8
8
|
import { discoverRoutes } from './vite/route-discovery';
|
|
9
9
|
import { generateWebAnalyticsFile } from './webanalytics-generator';
|
|
10
|
+
import { computeApiMountPath } from './vite/api-mount-path';
|
|
10
11
|
|
|
11
12
|
interface GenerateEntryOptions {
|
|
12
13
|
rootDir: string;
|
|
@@ -107,21 +108,14 @@ export async function generateEntryFile(options: GenerateEntryOptions): Promise<
|
|
|
107
108
|
let routeIndex = 0;
|
|
108
109
|
|
|
109
110
|
for (const routeFile of sortedRouteFiles) {
|
|
111
|
+
// Normalize path separators for cross-platform compatibility (Windows uses backslashes)
|
|
112
|
+
const normalizedRouteFile = routeFile.replace(/\\/g, '/');
|
|
110
113
|
// Convert src/api/auth/route.ts -> auth/route
|
|
111
|
-
const relativePath =
|
|
112
|
-
|
|
113
|
-
// Determine the mount path
|
|
114
|
-
//
|
|
115
|
-
|
|
116
|
-
// src/api/users/profile/route.ts -> /api/users/profile
|
|
117
|
-
let mountPath = '/api';
|
|
118
|
-
if (relativePath !== 'index') {
|
|
119
|
-
// Remove 'route' or 'index' from the end
|
|
120
|
-
const cleanPath = relativePath.replace(/\/(route|index)$/, '');
|
|
121
|
-
if (cleanPath) {
|
|
122
|
-
mountPath = `/api/${cleanPath}`;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
114
|
+
const relativePath = normalizedRouteFile.replace(/^src\/api\//, '').replace(/\.tsx?$/, '');
|
|
115
|
+
|
|
116
|
+
// Determine the mount path using the shared helper
|
|
117
|
+
// This ensures consistency with route type generation in ast.ts
|
|
118
|
+
const mountPath = computeApiMountPath(relativePath);
|
|
125
119
|
|
|
126
120
|
const importName = `router_${routeIndex++}`;
|
|
127
121
|
routeImportsAndMounts.push(
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API Mount Path Utilities
|
|
3
|
+
*
|
|
4
|
+
* Shared helpers for computing API route mount paths from file paths.
|
|
5
|
+
* Used by both entry-generator.ts (runtime mounting) and ast.ts (type generation)
|
|
6
|
+
* to ensure consistent path calculation.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Compute the API mount path from a route file's relative path.
|
|
11
|
+
* This is the path used in app.route(mountPath, router).
|
|
12
|
+
*
|
|
13
|
+
* The mount path is based on the DIRECTORY containing the file, not the filename.
|
|
14
|
+
* Files directly in src/api/ (regardless of their name) mount at /api.
|
|
15
|
+
* Files in subdirectories mount at /api/{subdirectory}.
|
|
16
|
+
*
|
|
17
|
+
* @param relativePath - Path relative to src/api/ without extension
|
|
18
|
+
* e.g., 'index', 'sessions', 'auth/route', 'users/profile/route'
|
|
19
|
+
* @returns Mount path like '/api', '/api/auth', '/api/users/profile'
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* computeApiMountPath('index') // '/api' (file in src/api/)
|
|
23
|
+
* computeApiMountPath('sessions') // '/api' (file in src/api/)
|
|
24
|
+
* computeApiMountPath('route') // '/api' (file in src/api/)
|
|
25
|
+
* computeApiMountPath('auth/route') // '/api/auth' (file in src/api/auth/)
|
|
26
|
+
* computeApiMountPath('auth/index') // '/api/auth' (file in src/api/auth/)
|
|
27
|
+
* computeApiMountPath('users/profile/route') // '/api/users/profile' (file in src/api/users/profile/)
|
|
28
|
+
*/
|
|
29
|
+
export function computeApiMountPath(relativePath: string): string {
|
|
30
|
+
// Extract the directory path (everything before the last /)
|
|
31
|
+
const lastSlashIndex = relativePath.lastIndexOf('/');
|
|
32
|
+
if (lastSlashIndex === -1) {
|
|
33
|
+
// File is directly in src/api/ (e.g., 'index', 'sessions', 'route')
|
|
34
|
+
return '/api';
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// File is in a subdirectory (e.g., 'auth/route' -> 'auth')
|
|
38
|
+
const dirPath = relativePath.substring(0, lastSlashIndex);
|
|
39
|
+
return `/api/${dirPath}`;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Join a mount base path with a route's local path.
|
|
44
|
+
* Handles normalization of slashes and empty/root paths.
|
|
45
|
+
*
|
|
46
|
+
* @param base - The mount base path (e.g., '/api/sessions')
|
|
47
|
+
* @param route - The local route path (e.g., '/', '/users', ':id')
|
|
48
|
+
* @returns The combined full path
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* joinMountAndRoute('/api/sessions', '/') // '/api/sessions'
|
|
52
|
+
* joinMountAndRoute('/api/sessions', '/users') // '/api/sessions/users'
|
|
53
|
+
* joinMountAndRoute('/api', '/health') // '/api/health'
|
|
54
|
+
* joinMountAndRoute('/api/users', ':id') // '/api/users/:id'
|
|
55
|
+
*/
|
|
56
|
+
export function joinMountAndRoute(base: string, route: string): string {
|
|
57
|
+
if (!route || route === '/') {
|
|
58
|
+
return base;
|
|
59
|
+
}
|
|
60
|
+
const normalized = route.startsWith('/') ? route : `/${route}`;
|
|
61
|
+
return `${base}${normalized}`.replace(/\/{2,}/g, '/').replace(/\/$/, '');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
import { join, relative } from 'node:path';
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Extract the relative path from a full file path to src/api/.
|
|
68
|
+
* Normalizes path separators for cross-platform compatibility.
|
|
69
|
+
*
|
|
70
|
+
* @param filename - Full path to the route file
|
|
71
|
+
* @param srcDir - Path to the src directory
|
|
72
|
+
* @returns Path relative to src/api/ without extension
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* // Given srcDir = '/project/src'
|
|
76
|
+
* extractRelativeApiPath('/project/src/api/sessions.ts', '/project/src')
|
|
77
|
+
* // Returns: 'sessions'
|
|
78
|
+
*
|
|
79
|
+
* extractRelativeApiPath('/project/src/api/auth/route.ts', '/project/src')
|
|
80
|
+
* // Returns: 'auth/route'
|
|
81
|
+
*/
|
|
82
|
+
export function extractRelativeApiPath(filename: string, srcDir: string): string {
|
|
83
|
+
const apiDir = join(srcDir, 'api');
|
|
84
|
+
return relative(apiDir, filename)
|
|
85
|
+
.replace(/\\/g, '/') // Normalize Windows paths
|
|
86
|
+
.replace(/\.tsx?$/, ''); // Remove extension
|
|
87
|
+
}
|
package/src/cmd/cloud/deploy.ts
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
getDefaultConfigDir,
|
|
14
14
|
loadProjectSDKKey,
|
|
15
15
|
updateProjectConfig,
|
|
16
|
+
getGlobalCatalystAPIClient,
|
|
16
17
|
} from '../../config';
|
|
17
18
|
import { getProjectGithubStatus } from '../git/api';
|
|
18
19
|
import { runGitLink } from '../git/link';
|
|
@@ -341,8 +342,10 @@ export const deploySubcommand = createSubcommand({
|
|
|
341
342
|
return null;
|
|
342
343
|
}
|
|
343
344
|
logger.debug('Checking %d packages for malware', packages.length);
|
|
345
|
+
// Use Catalyst client directly for malware check (security routes are on Catalyst)
|
|
346
|
+
const catalystClient = await getGlobalCatalystAPIClient(logger, auth, config?.name);
|
|
344
347
|
const result = await projectDeploymentMalwareCheck(
|
|
345
|
-
|
|
348
|
+
catalystClient,
|
|
346
349
|
deployment!.id,
|
|
347
350
|
packages
|
|
348
351
|
);
|
package/src/version-check.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Config, Logger, CommandDefinition } from './types';
|
|
1
|
+
import type { Config, Logger, CommandDefinition, SubcommandDefinition } from './types';
|
|
2
2
|
import { isRunningFromExecutable, fetchLatestVersion } from './cmd/upgrade';
|
|
3
3
|
import { getVersion, getCompareUrl, getReleaseUrl, toTag } from './version';
|
|
4
4
|
import * as tui from './tui';
|
|
@@ -7,6 +7,9 @@ import { $ } from 'bun';
|
|
|
7
7
|
|
|
8
8
|
const ONE_HOUR_MS = 60 * 60 * 1000;
|
|
9
9
|
|
|
10
|
+
// Tags that indicate a command should skip the upgrade prompt
|
|
11
|
+
const SKIP_UPGRADE_TAGS = ['read-only', 'fast'];
|
|
12
|
+
|
|
10
13
|
/**
|
|
11
14
|
* Check if we should skip the version check based on environment and config
|
|
12
15
|
*/
|
|
@@ -20,6 +23,7 @@ function shouldSkipCheck(
|
|
|
20
23
|
skipVersionCheck?: boolean;
|
|
21
24
|
},
|
|
22
25
|
commandDef: CommandDefinition | undefined,
|
|
26
|
+
subcommandDef: SubcommandDefinition | undefined,
|
|
23
27
|
args: string[]
|
|
24
28
|
): boolean {
|
|
25
29
|
// Skip if running via bun/bunx (not installed executable)
|
|
@@ -64,6 +68,21 @@ function shouldSkipCheck(
|
|
|
64
68
|
return true;
|
|
65
69
|
}
|
|
66
70
|
|
|
71
|
+
// Skip if subcommand explicitly opts out of upgrade check
|
|
72
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
73
|
+
if (subcommandDef && (subcommandDef as any).skipUpgradeCheck === true) {
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Skip if command or subcommand has tags indicating it's read-only or fast
|
|
78
|
+
// These commands shouldn't be interrupted with upgrade prompts
|
|
79
|
+
const commandTags = commandDef?.tags ?? [];
|
|
80
|
+
const subcommandTags = subcommandDef?.tags ?? [];
|
|
81
|
+
const allTags = [...commandTags, ...subcommandTags];
|
|
82
|
+
if (allTags.some((tag) => SKIP_UPGRADE_TAGS.includes(tag))) {
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
|
|
67
86
|
// Skip for help commands
|
|
68
87
|
const helpFlags = ['--help', '-h', 'help'];
|
|
69
88
|
if (args.some((arg) => helpFlags.includes(arg))) {
|
|
@@ -187,10 +206,11 @@ export async function checkForUpdates(
|
|
|
187
206
|
skipVersionCheck?: boolean;
|
|
188
207
|
},
|
|
189
208
|
commandDef: CommandDefinition | undefined,
|
|
209
|
+
subcommandDef: SubcommandDefinition | undefined,
|
|
190
210
|
args: string[]
|
|
191
211
|
): Promise<void> {
|
|
192
212
|
// Determine if we should skip the check
|
|
193
|
-
if (shouldSkipCheck(config, options, commandDef, args)) {
|
|
213
|
+
if (shouldSkipCheck(config, options, commandDef, subcommandDef, args)) {
|
|
194
214
|
logger.trace('Skipping version check (disabled or not applicable)');
|
|
195
215
|
return;
|
|
196
216
|
}
|