@agentuity/cli 1.0.38 → 1.0.40
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/app-router-detector.d.ts +42 -0
- package/dist/cmd/build/app-router-detector.d.ts.map +1 -0
- package/dist/cmd/build/app-router-detector.js +253 -0
- package/dist/cmd/build/app-router-detector.js.map +1 -0
- package/dist/cmd/build/ast.d.ts +11 -1
- package/dist/cmd/build/ast.d.ts.map +1 -1
- package/dist/cmd/build/ast.js +273 -29
- 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 +23 -16
- package/dist/cmd/build/entry-generator.js.map +1 -1
- package/dist/cmd/build/vite/bundle-files.d.ts +12 -0
- package/dist/cmd/build/vite/bundle-files.d.ts.map +1 -0
- package/dist/cmd/build/vite/bundle-files.js +107 -0
- package/dist/cmd/build/vite/bundle-files.js.map +1 -0
- package/dist/cmd/build/vite/registry-generator.d.ts.map +1 -1
- package/dist/cmd/build/vite/registry-generator.js +37 -13
- package/dist/cmd/build/vite/registry-generator.js.map +1 -1
- package/dist/cmd/build/vite/route-discovery.d.ts +17 -3
- package/dist/cmd/build/vite/route-discovery.d.ts.map +1 -1
- package/dist/cmd/build/vite/route-discovery.js +91 -3
- package/dist/cmd/build/vite/route-discovery.js.map +1 -1
- package/dist/cmd/build/vite/vite-builder.d.ts.map +1 -1
- package/dist/cmd/build/vite/vite-builder.js +9 -0
- package/dist/cmd/build/vite/vite-builder.js.map +1 -1
- package/dist/cmd/build/vite-bundler.d.ts.map +1 -1
- package/dist/cmd/build/vite-bundler.js +3 -0
- package/dist/cmd/build/vite-bundler.js.map +1 -1
- package/dist/cmd/dev/index.d.ts.map +1 -1
- package/dist/cmd/dev/index.js +30 -0
- package/dist/cmd/dev/index.js.map +1 -1
- package/dist/types.d.ts +9 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/route-migration.d.ts +61 -0
- package/dist/utils/route-migration.d.ts.map +1 -0
- package/dist/utils/route-migration.js +662 -0
- package/dist/utils/route-migration.js.map +1 -0
- package/package.json +6 -6
- package/src/cmd/build/app-router-detector.ts +350 -0
- package/src/cmd/build/ast.ts +339 -36
- package/src/cmd/build/entry-generator.ts +23 -16
- package/src/cmd/build/vite/bundle-files.ts +135 -0
- package/src/cmd/build/vite/registry-generator.ts +38 -13
- package/src/cmd/build/vite/route-discovery.ts +151 -3
- package/src/cmd/build/vite/vite-builder.ts +11 -0
- package/src/cmd/build/vite-bundler.ts +4 -0
- package/src/cmd/dev/index.ts +34 -0
- package/src/types.ts +9 -0
- package/src/utils/route-migration.ts +793 -0
|
@@ -732,7 +732,8 @@ export async function generateRouteRegistry(
|
|
|
732
732
|
resolvedPath = `../api/${finalPath}`;
|
|
733
733
|
} else if (resolvedPath.startsWith('./') || resolvedPath.startsWith('../')) {
|
|
734
734
|
// Resolve relative import from route file's directory
|
|
735
|
-
|
|
735
|
+
// Use schemaSourceFile when available (sub-router routes)
|
|
736
|
+
const normalizedFilename = toForwardSlash(route.schemaSourceFile ?? route.filename);
|
|
736
737
|
const routeDir = normalizedFilename.substring(0, normalizedFilename.lastIndexOf('/'));
|
|
737
738
|
// Join and normalize the path
|
|
738
739
|
const joined = `${routeDir}/${resolvedPath}`;
|
|
@@ -793,15 +794,19 @@ export async function generateRouteRegistry(
|
|
|
793
794
|
|
|
794
795
|
if (route.inputSchemaImportPath) {
|
|
795
796
|
// Schema is imported - rebase the import path from route file to generated file
|
|
796
|
-
|
|
797
|
+
// Use schemaSourceFile if available (sub-router routes carry the original file)
|
|
798
|
+
const sourceFile = route.schemaSourceFile ?? route.filename;
|
|
799
|
+
importPath = rebaseImportPath(sourceFile, route.inputSchemaImportPath, srcDir);
|
|
797
800
|
// Use the actual exported name (handles aliased imports like `import { A as B }`)
|
|
798
801
|
schemaNameToImport =
|
|
799
802
|
route.inputSchemaImportedName === 'default'
|
|
800
803
|
? route.inputSchemaVariable
|
|
801
804
|
: (route.inputSchemaImportedName ?? route.inputSchemaVariable);
|
|
802
805
|
} else {
|
|
803
|
-
// Schema is locally defined - import from the
|
|
804
|
-
|
|
806
|
+
// Schema is locally defined - import from the file that defines/exports it
|
|
807
|
+
// When route is mounted via .route(), schemaSourceFile points to the sub-router file
|
|
808
|
+
const sourceFile = route.schemaSourceFile ?? route.filename;
|
|
809
|
+
const filename = toForwardSlash(sourceFile);
|
|
805
810
|
const withoutSrc = filename.startsWith('src/') ? filename.substring(4) : filename;
|
|
806
811
|
const withoutLeadingDot = withoutSrc.startsWith('./')
|
|
807
812
|
? withoutSrc.substring(2)
|
|
@@ -828,15 +833,17 @@ export async function generateRouteRegistry(
|
|
|
828
833
|
|
|
829
834
|
if (route.outputSchemaImportPath) {
|
|
830
835
|
// Schema is imported - rebase the import path from route file to generated file
|
|
831
|
-
|
|
836
|
+
const sourceFile = route.schemaSourceFile ?? route.filename;
|
|
837
|
+
importPath = rebaseImportPath(sourceFile, route.outputSchemaImportPath, srcDir);
|
|
832
838
|
// Use the actual exported name (handles aliased imports like `import { A as B }`)
|
|
833
839
|
schemaNameToImport =
|
|
834
840
|
route.outputSchemaImportedName === 'default'
|
|
835
841
|
? route.outputSchemaVariable
|
|
836
842
|
: (route.outputSchemaImportedName ?? route.outputSchemaVariable);
|
|
837
843
|
} else {
|
|
838
|
-
// Schema is locally defined - import from the
|
|
839
|
-
const
|
|
844
|
+
// Schema is locally defined - import from the file that defines/exports it
|
|
845
|
+
const sourceFile = route.schemaSourceFile ?? route.filename;
|
|
846
|
+
const filename = toForwardSlash(sourceFile);
|
|
840
847
|
const withoutSrc = filename.startsWith('src/') ? filename.substring(4) : filename;
|
|
841
848
|
const withoutLeadingDot = withoutSrc.startsWith('./')
|
|
842
849
|
? withoutSrc.substring(2)
|
|
@@ -858,19 +865,37 @@ export async function generateRouteRegistry(
|
|
|
858
865
|
}
|
|
859
866
|
});
|
|
860
867
|
|
|
861
|
-
// Generate schema imports
|
|
868
|
+
// Generate schema imports, only aliasing when names collide across files
|
|
862
869
|
const schemaImportAliases = new Map<string, Map<string, string>>(); // importPath -> (schemaName -> alias)
|
|
863
|
-
|
|
870
|
+
|
|
871
|
+
// First pass: count how many times each schema name appears across all import paths
|
|
872
|
+
const globalNameCount = new Map<string, number>();
|
|
873
|
+
routeFileImports.forEach((schemas) => {
|
|
874
|
+
for (const schemaName of schemas) {
|
|
875
|
+
globalNameCount.set(schemaName, (globalNameCount.get(schemaName) ?? 0) + 1);
|
|
876
|
+
}
|
|
877
|
+
});
|
|
878
|
+
|
|
879
|
+
// Track aliases assigned to duplicated names for uniqueness
|
|
880
|
+
const duplicateCounters = new Map<string, number>();
|
|
864
881
|
|
|
865
882
|
routeFileImports.forEach((schemas, importPath) => {
|
|
866
883
|
const aliases = new Map<string, string>();
|
|
867
884
|
const importParts: string[] = [];
|
|
868
885
|
|
|
869
886
|
for (const schemaName of Array.from(schemas)) {
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
887
|
+
if ((globalNameCount.get(schemaName) ?? 0) > 1) {
|
|
888
|
+
// Name appears in multiple import paths — alias to avoid collision
|
|
889
|
+
const counter = duplicateCounters.get(schemaName) ?? 0;
|
|
890
|
+
duplicateCounters.set(schemaName, counter + 1);
|
|
891
|
+
const alias = `${schemaName}_${counter}`;
|
|
892
|
+
aliases.set(schemaName, alias);
|
|
893
|
+
importParts.push(`${schemaName} as ${alias}`);
|
|
894
|
+
} else {
|
|
895
|
+
// Unique name — import directly, no alias needed
|
|
896
|
+
aliases.set(schemaName, schemaName);
|
|
897
|
+
importParts.push(schemaName);
|
|
898
|
+
}
|
|
874
899
|
}
|
|
875
900
|
|
|
876
901
|
schemaImportAliases.set(importPath, aliases);
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Route Discovery - READ-ONLY AST analysis
|
|
3
3
|
*
|
|
4
|
-
* Discovers routes by scanning src/api/**\/*.ts files
|
|
5
|
-
*
|
|
4
|
+
* Discovers routes by scanning src/api/**\/*.ts files or by following
|
|
5
|
+
* explicit router mounts from createApp({ router }).
|
|
6
|
+
* Extracts route definitions WITHOUT mutating source files.
|
|
6
7
|
*/
|
|
7
8
|
|
|
8
9
|
import { join, relative } from 'node:path';
|
|
@@ -10,6 +11,7 @@ import { existsSync } from 'node:fs';
|
|
|
10
11
|
import type { Logger } from '../../../types';
|
|
11
12
|
import { parseRoute } from '../ast';
|
|
12
13
|
import { toForwardSlash } from '../../../utils/normalize-path';
|
|
14
|
+
import { detectExplicitRouter, type AppRouterDetection } from '../app-router-detector';
|
|
13
15
|
|
|
14
16
|
export interface RouteMetadata {
|
|
15
17
|
id: string;
|
|
@@ -46,6 +48,12 @@ export interface RouteInfo {
|
|
|
46
48
|
outputSchemaCode?: string;
|
|
47
49
|
stream?: boolean;
|
|
48
50
|
pathParams?: string[];
|
|
51
|
+
/**
|
|
52
|
+
* When a route is mounted via .route(), its filename is set to the parent file
|
|
53
|
+
* (for dedup filtering). schemaSourceFile preserves the actual file where the
|
|
54
|
+
* route's schema variables are defined/exported, so registry imports resolve correctly.
|
|
55
|
+
*/
|
|
56
|
+
schemaSourceFile?: string;
|
|
49
57
|
}
|
|
50
58
|
|
|
51
59
|
/**
|
|
@@ -66,13 +74,152 @@ export function extractPathParams(path: string): string[] {
|
|
|
66
74
|
}
|
|
67
75
|
|
|
68
76
|
/**
|
|
69
|
-
* Discover all routes
|
|
77
|
+
* Discover all routes — tries explicit router detection first, falls back to file-based.
|
|
78
|
+
*
|
|
79
|
+
* When `createApp({ router })` is detected in app.ts, routes are discovered by
|
|
80
|
+
* following the router imports with code-derived mount paths. Otherwise, falls back
|
|
81
|
+
* to scanning src/api/**\/*.ts with filesystem-derived paths.
|
|
70
82
|
*/
|
|
71
83
|
export async function discoverRoutes(
|
|
72
84
|
srcDir: string,
|
|
73
85
|
projectId: string,
|
|
74
86
|
deploymentId: string,
|
|
75
87
|
logger: Logger
|
|
88
|
+
): Promise<{
|
|
89
|
+
routes: RouteMetadata[];
|
|
90
|
+
routeInfoList: RouteInfo[];
|
|
91
|
+
/** Whether explicit router was detected (vs file-based fallback) */
|
|
92
|
+
explicitRouter?: AppRouterDetection;
|
|
93
|
+
}> {
|
|
94
|
+
const rootDir = join(srcDir, '..');
|
|
95
|
+
|
|
96
|
+
// Try explicit router detection first
|
|
97
|
+
const detection = await detectExplicitRouter(rootDir, logger);
|
|
98
|
+
if (detection.detected && detection.mounts.length > 0) {
|
|
99
|
+
logger.debug(
|
|
100
|
+
'Using explicit router detection (%d mount(s) from createApp)',
|
|
101
|
+
detection.mounts.length
|
|
102
|
+
);
|
|
103
|
+
const result = await discoverExplicitRoutes(
|
|
104
|
+
rootDir,
|
|
105
|
+
srcDir,
|
|
106
|
+
projectId,
|
|
107
|
+
deploymentId,
|
|
108
|
+
detection,
|
|
109
|
+
logger
|
|
110
|
+
);
|
|
111
|
+
return { ...result, explicitRouter: detection };
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Fall back to file-based discovery
|
|
115
|
+
return discoverFileBasedRoutes(srcDir, projectId, deploymentId, logger);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Discover routes from explicit router mounts detected in app.ts.
|
|
120
|
+
* Parses each router file with its code-derived mount prefix.
|
|
121
|
+
*/
|
|
122
|
+
async function discoverExplicitRoutes(
|
|
123
|
+
rootDir: string,
|
|
124
|
+
srcDir: string,
|
|
125
|
+
projectId: string,
|
|
126
|
+
deploymentId: string,
|
|
127
|
+
detection: AppRouterDetection,
|
|
128
|
+
logger: Logger
|
|
129
|
+
): Promise<{ routes: RouteMetadata[]; routeInfoList: RouteInfo[] }> {
|
|
130
|
+
const routes: RouteMetadata[] = [];
|
|
131
|
+
const routeInfoList: RouteInfo[] = [];
|
|
132
|
+
const visited = new Set<string>();
|
|
133
|
+
const mountedSubrouters = new Set<string>();
|
|
134
|
+
|
|
135
|
+
for (const mount of detection.mounts) {
|
|
136
|
+
try {
|
|
137
|
+
const parsedRoutes = await parseRoute(rootDir, mount.routerFile, projectId, deploymentId, {
|
|
138
|
+
visitedFiles: visited,
|
|
139
|
+
mountedSubrouters,
|
|
140
|
+
mountPrefix: mount.path,
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
if (parsedRoutes.length > 0) {
|
|
144
|
+
const relFile = './' + toForwardSlash(relative(srcDir, mount.routerFile));
|
|
145
|
+
logger.trace(
|
|
146
|
+
'Discovered %d route(s) from explicit mount at %s (%s)',
|
|
147
|
+
parsedRoutes.length,
|
|
148
|
+
mount.path,
|
|
149
|
+
relFile
|
|
150
|
+
);
|
|
151
|
+
routes.push(...parsedRoutes);
|
|
152
|
+
|
|
153
|
+
for (const route of parsedRoutes) {
|
|
154
|
+
const pathParams = extractPathParams(route.path);
|
|
155
|
+
routeInfoList.push({
|
|
156
|
+
method: route.method.toUpperCase(),
|
|
157
|
+
path: route.path,
|
|
158
|
+
filename: route.filename,
|
|
159
|
+
hasValidator: route.config?.hasValidator === true,
|
|
160
|
+
routeType: route.type || 'api',
|
|
161
|
+
agentVariable: route.config?.agentVariable as string | undefined,
|
|
162
|
+
agentImportPath: route.config?.agentImportPath as string | undefined,
|
|
163
|
+
inputSchemaVariable: route.config?.inputSchemaVariable as string | undefined,
|
|
164
|
+
outputSchemaVariable: route.config?.outputSchemaVariable as string | undefined,
|
|
165
|
+
inputSchemaImportPath: route.config?.inputSchemaImportPath as string | undefined,
|
|
166
|
+
inputSchemaImportedName: route.config?.inputSchemaImportedName as
|
|
167
|
+
| string
|
|
168
|
+
| undefined,
|
|
169
|
+
outputSchemaImportPath: route.config?.outputSchemaImportPath as
|
|
170
|
+
| string
|
|
171
|
+
| undefined,
|
|
172
|
+
outputSchemaImportedName: route.config?.outputSchemaImportedName as
|
|
173
|
+
| string
|
|
174
|
+
| undefined,
|
|
175
|
+
stream:
|
|
176
|
+
route.config?.stream !== undefined && route.config.stream !== null
|
|
177
|
+
? Boolean(route.config.stream)
|
|
178
|
+
: route.type === 'stream'
|
|
179
|
+
? true
|
|
180
|
+
: undefined,
|
|
181
|
+
pathParams: pathParams.length > 0 ? pathParams : undefined,
|
|
182
|
+
schemaSourceFile: route.config?.schemaSourceFile as string | undefined,
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
} catch (error) {
|
|
187
|
+
logger.warn(
|
|
188
|
+
'Failed to parse explicit router at %s: %s',
|
|
189
|
+
mount.routerFile,
|
|
190
|
+
error instanceof Error ? error.message : String(error)
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
logger.debug('Discovered %d route(s) via explicit router detection', routes.length);
|
|
196
|
+
|
|
197
|
+
// Check for route conflicts
|
|
198
|
+
const conflicts = detectRouteConflicts(routeInfoList);
|
|
199
|
+
if (conflicts.length > 0) {
|
|
200
|
+
logger.error('Route conflicts detected:');
|
|
201
|
+
for (const conflict of conflicts) {
|
|
202
|
+
logger.error(' %s', conflict.message);
|
|
203
|
+
for (const route of conflict.routes) {
|
|
204
|
+
logger.error(' - %s %s in %s', route.method, route.path, route.filename);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
throw new Error(
|
|
208
|
+
`Found ${conflicts.length} route conflict(s). Fix the conflicts and try again.`
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
return { routes, routeInfoList };
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Discover routes by scanning src/api directory (original file-based approach).
|
|
217
|
+
*/
|
|
218
|
+
async function discoverFileBasedRoutes(
|
|
219
|
+
srcDir: string,
|
|
220
|
+
projectId: string,
|
|
221
|
+
deploymentId: string,
|
|
222
|
+
logger: Logger
|
|
76
223
|
): Promise<{ routes: RouteMetadata[]; routeInfoList: RouteInfo[] }> {
|
|
77
224
|
const apiDir = join(srcDir, 'api');
|
|
78
225
|
const routes: RouteMetadata[] = [];
|
|
@@ -154,6 +301,7 @@ export async function discoverRoutes(
|
|
|
154
301
|
? true
|
|
155
302
|
: undefined,
|
|
156
303
|
pathParams: pathParams.length > 0 ? pathParams : undefined,
|
|
304
|
+
schemaSourceFile: route.config?.schemaSourceFile as string | undefined,
|
|
157
305
|
});
|
|
158
306
|
}
|
|
159
307
|
}
|
|
@@ -325,6 +325,17 @@ export async function runAllBuilds(options: Omit<ViteBuildOptions, 'mode'>): Pro
|
|
|
325
325
|
// Load config to check if workbench is enabled (dev mode only)
|
|
326
326
|
const { loadAgentuityConfig, getWorkbenchConfig } = await import('./config-loader');
|
|
327
327
|
const config = await loadAgentuityConfig(rootDir, logger);
|
|
328
|
+
|
|
329
|
+
// Copy bundle files if configured (before build so build output takes priority)
|
|
330
|
+
if (config?.bundle?.length) {
|
|
331
|
+
const { copyBundleFiles } = await import('./bundle-files');
|
|
332
|
+
const outDir = join(rootDir, '.agentuity');
|
|
333
|
+
const count = await copyBundleFiles(rootDir, outDir, config.bundle, logger);
|
|
334
|
+
if (count > 0) {
|
|
335
|
+
logger.debug(`Copied ${count} bundle file(s) to .agentuity`);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
328
339
|
const workbenchConfig = getWorkbenchConfig(config, dev);
|
|
329
340
|
// Generate workbench files BEFORE any builds if enabled (dev mode only)
|
|
330
341
|
if (workbenchConfig.enabled) {
|
|
@@ -10,6 +10,7 @@ import { StructuredError } from '@agentuity/core';
|
|
|
10
10
|
import type { Logger, DeployOptions } from '../../types';
|
|
11
11
|
import { runAllBuilds } from './vite/vite-builder';
|
|
12
12
|
import { checkAndUpgradeDependencies } from '../../utils/dependency-checker';
|
|
13
|
+
import { promptRouteMigration } from '../../utils/route-migration';
|
|
13
14
|
import { checkBunVersion } from '../../utils/bun-version-checker';
|
|
14
15
|
import * as tui from '../../tui';
|
|
15
16
|
import type { BuildReportCollector } from '../../build-report';
|
|
@@ -89,6 +90,9 @@ export async function viteBundle(options: ViteBundleOptions): Promise<{ output:
|
|
|
89
90
|
});
|
|
90
91
|
}
|
|
91
92
|
|
|
93
|
+
// Check if project can migrate from file-based to explicit routing
|
|
94
|
+
await promptRouteMigration(rootDir, logger);
|
|
95
|
+
|
|
92
96
|
try {
|
|
93
97
|
// Run all builds (client -> workbench -> server)
|
|
94
98
|
logger.debug('Starting builds...');
|
package/src/cmd/dev/index.ts
CHANGED
|
@@ -20,6 +20,11 @@ import { isTTY, hasLoggedInBefore } from '../../auth';
|
|
|
20
20
|
import { createFileWatcher } from './file-watcher';
|
|
21
21
|
import { prepareDevLock, releaseLockSync } from './dev-lock';
|
|
22
22
|
import { checkAndUpgradeDependencies } from '../../utils/dependency-checker';
|
|
23
|
+
import {
|
|
24
|
+
promptRouteMigration,
|
|
25
|
+
performMigration,
|
|
26
|
+
checkMigrationEligibility,
|
|
27
|
+
} from '../../utils/route-migration';
|
|
23
28
|
import { ErrorCode } from '../../errors';
|
|
24
29
|
|
|
25
30
|
const DEFAULT_PORT = 3500;
|
|
@@ -232,6 +237,12 @@ export const command = createCommand({
|
|
|
232
237
|
.boolean()
|
|
233
238
|
.optional()
|
|
234
239
|
.describe('Skip TypeScript type checking on startup and restarts'),
|
|
240
|
+
migrateRoutes: z
|
|
241
|
+
.boolean()
|
|
242
|
+
.optional()
|
|
243
|
+
.describe(
|
|
244
|
+
'Migrate file-based routes to explicit routing (src/api/index.ts root router)'
|
|
245
|
+
),
|
|
235
246
|
resume: z.string().optional().describe('Resume a paused Hub session by ID'),
|
|
236
247
|
}),
|
|
237
248
|
},
|
|
@@ -414,6 +425,29 @@ export const command = createCommand({
|
|
|
414
425
|
);
|
|
415
426
|
}
|
|
416
427
|
|
|
428
|
+
// Check if project can migrate to explicit routing
|
|
429
|
+
if (opts.migrateRoutes) {
|
|
430
|
+
const eligibility = checkMigrationEligibility(rootDir);
|
|
431
|
+
if (eligibility.available) {
|
|
432
|
+
const result = performMigration(rootDir, eligibility.routeFiles);
|
|
433
|
+
if (result.success) {
|
|
434
|
+
tui.success(result.message);
|
|
435
|
+
if (result.filesCreated.length > 0) {
|
|
436
|
+
tui.info(`Created: ${result.filesCreated.map((f) => tui.muted(f)).join(', ')}`);
|
|
437
|
+
}
|
|
438
|
+
tui.newline();
|
|
439
|
+
} else {
|
|
440
|
+
tui.warning(result.message);
|
|
441
|
+
tui.newline();
|
|
442
|
+
}
|
|
443
|
+
} else {
|
|
444
|
+
tui.info('No migration needed — already using explicit routing.');
|
|
445
|
+
tui.newline();
|
|
446
|
+
}
|
|
447
|
+
} else {
|
|
448
|
+
await promptRouteMigration(rootDir, logger, { interactive });
|
|
449
|
+
}
|
|
450
|
+
|
|
417
451
|
try {
|
|
418
452
|
// Setup devmode and gravity (if using public URL)
|
|
419
453
|
const useMockService = process.env.DEVMODE_SYNC_SERVICE_MOCK === 'true';
|
package/src/types.ts
CHANGED
|
@@ -249,6 +249,15 @@ export interface AgentuityConfig {
|
|
|
249
249
|
* Note: Cannot override AGENTUITY_PUBLIC_* or process.env.NODE_ENV
|
|
250
250
|
*/
|
|
251
251
|
define?: Record<string, string>;
|
|
252
|
+
/**
|
|
253
|
+
* Glob patterns for additional files to include in the deployment bundle.
|
|
254
|
+
* Files matching these patterns will be copied into the .agentuity build
|
|
255
|
+
* output directory before the build runs, preserving their relative paths
|
|
256
|
+
* from the project root. Build output will overwrite any conflicting files.
|
|
257
|
+
*
|
|
258
|
+
* @example ['data/**', 'templates/*.json', 'models/weights.bin']
|
|
259
|
+
*/
|
|
260
|
+
bundle?: string[];
|
|
252
261
|
}
|
|
253
262
|
|
|
254
263
|
/**
|