@agentuity/cli 0.0.99 → 0.0.101
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/AGENTS.md +1 -1
- package/dist/api.d.ts +1 -0
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +1 -1
- package/dist/api.js.map +1 -1
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +5 -0
- package/dist/auth.js.map +1 -1
- package/dist/cmd/build/ast.d.ts +2 -1
- package/dist/cmd/build/ast.d.ts.map +1 -1
- package/dist/cmd/build/ast.js +135 -47
- 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 +220 -188
- package/dist/cmd/build/entry-generator.js.map +1 -1
- package/dist/cmd/build/vite/agent-discovery.d.ts.map +1 -1
- package/dist/cmd/build/vite/agent-discovery.js +103 -45
- package/dist/cmd/build/vite/agent-discovery.js.map +1 -1
- package/dist/cmd/build/vite/bun-dev-server.js +1 -1
- package/dist/cmd/build/vite/bun-dev-server.js.map +1 -1
- package/dist/cmd/build/vite/docs-generator.d.ts +13 -0
- package/dist/cmd/build/vite/docs-generator.d.ts.map +1 -0
- package/dist/cmd/build/vite/docs-generator.js +81 -0
- package/dist/cmd/build/vite/docs-generator.js.map +1 -0
- package/dist/cmd/build/vite/index.d.ts +3 -4
- package/dist/cmd/build/vite/index.d.ts.map +1 -1
- package/dist/cmd/build/vite/index.js +9 -8
- package/dist/cmd/build/vite/index.js.map +1 -1
- package/dist/cmd/build/vite/lifecycle-generator.d.ts +1 -1
- package/dist/cmd/build/vite/lifecycle-generator.d.ts.map +1 -1
- package/dist/cmd/build/vite/lifecycle-generator.js +19 -5
- package/dist/cmd/build/vite/lifecycle-generator.js.map +1 -1
- package/dist/cmd/build/vite/metadata-generator.d.ts.map +1 -1
- package/dist/cmd/build/vite/metadata-generator.js +145 -0
- package/dist/cmd/build/vite/metadata-generator.js.map +1 -1
- package/dist/cmd/build/vite/registry-generator.d.ts +3 -3
- package/dist/cmd/build/vite/registry-generator.d.ts.map +1 -1
- package/dist/cmd/build/vite/registry-generator.js +627 -103
- package/dist/cmd/build/vite/registry-generator.js.map +1 -1
- package/dist/cmd/build/vite/route-discovery.d.ts +4 -0
- package/dist/cmd/build/vite/route-discovery.d.ts.map +1 -1
- package/dist/cmd/build/vite/route-discovery.js.map +1 -1
- package/dist/cmd/build/vite/server-bundler.d.ts.map +1 -1
- package/dist/cmd/build/vite/server-bundler.js +48 -1
- package/dist/cmd/build/vite/server-bundler.js.map +1 -1
- package/dist/cmd/build/vite/vite-builder.d.ts +1 -1
- package/dist/cmd/build/vite/vite-builder.d.ts.map +1 -1
- package/dist/cmd/build/vite/vite-builder.js +30 -21
- package/dist/cmd/build/vite/vite-builder.js.map +1 -1
- package/dist/cmd/build/vite-bundler.js +6 -6
- package/dist/cmd/build/vite-bundler.js.map +1 -1
- package/dist/cmd/cloud/deploy.d.ts.map +1 -1
- package/dist/cmd/cloud/deploy.js +11 -5
- package/dist/cmd/cloud/deploy.js.map +1 -1
- package/dist/cmd/dev/file-watcher.d.ts.map +1 -1
- package/dist/cmd/dev/file-watcher.js +33 -1
- package/dist/cmd/dev/file-watcher.js.map +1 -1
- package/dist/cmd/dev/index.d.ts.map +1 -1
- package/dist/cmd/dev/index.js +102 -21
- package/dist/cmd/dev/index.js.map +1 -1
- package/dist/cmd/dev/sync.d.ts.map +1 -1
- package/dist/cmd/dev/sync.js +19 -3
- package/dist/cmd/dev/sync.js.map +1 -1
- package/dist/cmd/project/create.d.ts.map +1 -1
- package/dist/cmd/project/create.js +8 -2
- package/dist/cmd/project/create.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +8 -0
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/package.json +5 -8
- package/src/api.ts +1 -1
- package/src/auth.ts +6 -0
- package/src/cmd/build/ast.ts +161 -48
- package/src/cmd/build/entry-generator.ts +225 -190
- package/src/cmd/build/vite/agent-discovery.ts +151 -58
- package/src/cmd/build/vite/bun-dev-server.ts +1 -1
- package/src/cmd/build/vite/docs-generator.ts +87 -0
- package/src/cmd/build/vite/index.ts +9 -8
- package/src/cmd/build/vite/lifecycle-generator.ts +19 -5
- package/src/cmd/build/vite/metadata-generator.ts +178 -0
- package/src/cmd/build/vite/registry-generator.ts +727 -108
- package/src/cmd/build/vite/route-discovery.ts +4 -0
- package/src/cmd/build/vite/server-bundler.ts +56 -1
- package/src/cmd/build/vite/vite-builder.ts +46 -33
- package/src/cmd/build/vite-bundler.ts +6 -6
- package/src/cmd/cloud/deploy.ts +15 -5
- package/src/cmd/dev/file-watcher.ts +37 -1
- package/src/cmd/dev/index.ts +141 -30
- package/src/cmd/dev/sync.ts +41 -6
- package/src/cmd/project/create.ts +13 -3
- package/src/config.ts +9 -0
- package/src/index.ts +0 -5
- package/src/runtime-bootstrap.md +1 -1
- package/dist/cmd/build/vite/patch-plugin.d.ts +0 -21
- package/dist/cmd/build/vite/patch-plugin.d.ts.map +0 -1
- package/dist/cmd/build/vite/patch-plugin.js +0 -70
- package/dist/cmd/build/vite/patch-plugin.js.map +0 -1
- package/dist/runtime-bootstrap.d.ts +0 -56
- package/dist/runtime-bootstrap.d.ts.map +0 -1
- package/dist/runtime-bootstrap.js +0 -95
- package/dist/runtime-bootstrap.js.map +0 -1
- package/src/cmd/build/vite/patch-plugin.ts +0 -88
- package/src/runtime-bootstrap.ts +0 -131
|
@@ -33,8 +33,12 @@ export interface RouteInfo {
|
|
|
33
33
|
routeType: 'api' | 'sms' | 'email' | 'cron' | 'websocket' | 'sse' | 'stream';
|
|
34
34
|
agentVariable?: string;
|
|
35
35
|
agentImportPath?: string;
|
|
36
|
+
agentName?: string;
|
|
37
|
+
agentDescription?: string;
|
|
36
38
|
inputSchemaVariable?: string;
|
|
37
39
|
outputSchemaVariable?: string;
|
|
40
|
+
inputSchemaCode?: string;
|
|
41
|
+
outputSchemaCode?: string;
|
|
38
42
|
stream?: boolean;
|
|
39
43
|
}
|
|
40
44
|
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
import { join } from 'node:path';
|
|
7
7
|
import { readdir, stat } from 'node:fs/promises';
|
|
8
8
|
import type { Logger } from '../../../types';
|
|
9
|
+
import type { BunPlugin } from 'bun';
|
|
10
|
+
import { generatePatches, applyPatch } from '../patch';
|
|
9
11
|
|
|
10
12
|
export interface ServerBundleOptions {
|
|
11
13
|
rootDir: string;
|
|
@@ -22,7 +24,7 @@ export async function installExternalsAndBuild(options: ServerBundleOptions): Pr
|
|
|
22
24
|
|
|
23
25
|
logger.debug('[server-bundler] Starting server bundle process');
|
|
24
26
|
|
|
25
|
-
const entryPath = join(rootDir, '
|
|
27
|
+
const entryPath = join(rootDir, 'src/generated/app.ts');
|
|
26
28
|
const outDir = join(rootDir, '.agentuity');
|
|
27
29
|
|
|
28
30
|
logger.debug(`[server-bundler] Entry: ${entryPath}, OutDir: ${outDir}`);
|
|
@@ -202,6 +204,39 @@ export async function installExternalsAndBuild(options: ServerBundleOptions): Pr
|
|
|
202
204
|
logger.debug('Building server with Bun.build...');
|
|
203
205
|
logger.debug(`External packages (${external.length}): ${external.join(', ')}`);
|
|
204
206
|
|
|
207
|
+
// Create Bun plugin to apply LLM patches during bundling
|
|
208
|
+
const patches = generatePatches();
|
|
209
|
+
logger.debug(`Loaded ${patches.size} patch(es) for LLM providers`);
|
|
210
|
+
|
|
211
|
+
const patchPlugin: BunPlugin = {
|
|
212
|
+
name: 'agentuity:patch',
|
|
213
|
+
setup(build) {
|
|
214
|
+
for (const [, patch] of patches) {
|
|
215
|
+
let modulePath = join('node_modules', patch.module, '.*');
|
|
216
|
+
if (patch.filename) {
|
|
217
|
+
modulePath = join('node_modules', patch.module, patch.filename + '.*');
|
|
218
|
+
}
|
|
219
|
+
build.onLoad(
|
|
220
|
+
{
|
|
221
|
+
filter: new RegExp(modulePath),
|
|
222
|
+
namespace: 'file',
|
|
223
|
+
},
|
|
224
|
+
async (args) => {
|
|
225
|
+
if (build.config.target !== 'bun') {
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
logger.trace(`Applying patch to: ${args.path}`);
|
|
229
|
+
const [contents, loader] = await applyPatch(args.path, patch);
|
|
230
|
+
return {
|
|
231
|
+
contents,
|
|
232
|
+
loader,
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
);
|
|
236
|
+
}
|
|
237
|
+
},
|
|
238
|
+
};
|
|
239
|
+
|
|
205
240
|
const buildConfig = {
|
|
206
241
|
entrypoints: [entryPath],
|
|
207
242
|
outdir: outDir, // Output to .agentuity/ directly (not .agentuity/server/)
|
|
@@ -211,7 +246,12 @@ export async function installExternalsAndBuild(options: ServerBundleOptions): Pr
|
|
|
211
246
|
minify: !dev,
|
|
212
247
|
sourcemap: (dev ? 'inline' : 'external') as 'inline' | 'external',
|
|
213
248
|
external,
|
|
249
|
+
// CRITICAL: Disable environment variable inlining for server builds
|
|
250
|
+
// Server code must read process.env at RUNTIME, not have values baked in at build time
|
|
251
|
+
// Without this, NODE_ENV and other env vars get inlined as string literals
|
|
252
|
+
env: 'disable' as const,
|
|
214
253
|
define: userDefine, // Include custom define values from agentuity.config.ts
|
|
254
|
+
plugins: [patchPlugin],
|
|
215
255
|
naming: {
|
|
216
256
|
entry: 'app.js', // Output as app.js (not app.generated.js)
|
|
217
257
|
},
|
|
@@ -221,6 +261,12 @@ export async function installExternalsAndBuild(options: ServerBundleOptions): Pr
|
|
|
221
261
|
`Bun.build config: ${JSON.stringify({ ...buildConfig, external: `[${external.length} packages]` }, null, 2)}`
|
|
222
262
|
);
|
|
223
263
|
|
|
264
|
+
// WORKAROUND: Temporarily delete NODE_ENV to prevent Bun.build from inlining it
|
|
265
|
+
// See: https://github.com/oven-sh/bun/issues/20183
|
|
266
|
+
// Even with env: 'disable', Bun.build still inlines NODE_ENV at build time
|
|
267
|
+
const originalNodeEnv = process.env.NODE_ENV;
|
|
268
|
+
delete process.env.NODE_ENV;
|
|
269
|
+
|
|
224
270
|
// Verify entry point exists before building
|
|
225
271
|
if (!(await Bun.file(entryPath).exists())) {
|
|
226
272
|
throw new Error(`Entry point not found: ${entryPath}`);
|
|
@@ -232,6 +278,10 @@ export async function installExternalsAndBuild(options: ServerBundleOptions): Pr
|
|
|
232
278
|
try {
|
|
233
279
|
result = await Bun.build(buildConfig);
|
|
234
280
|
} catch (error: unknown) {
|
|
281
|
+
// Restore NODE_ENV after build attempt
|
|
282
|
+
if (originalNodeEnv !== undefined) {
|
|
283
|
+
process.env.NODE_ENV = originalNodeEnv;
|
|
284
|
+
}
|
|
235
285
|
logger.error('Bun.build threw an exception');
|
|
236
286
|
|
|
237
287
|
// Handle AggregateError with build/resolve messages
|
|
@@ -250,6 +300,11 @@ export async function installExternalsAndBuild(options: ServerBundleOptions): Pr
|
|
|
250
300
|
throw error;
|
|
251
301
|
}
|
|
252
302
|
|
|
303
|
+
// Restore NODE_ENV after successful build
|
|
304
|
+
if (originalNodeEnv !== undefined) {
|
|
305
|
+
process.env.NODE_ENV = originalNodeEnv;
|
|
306
|
+
}
|
|
307
|
+
|
|
253
308
|
if (!result.success) {
|
|
254
309
|
logger.error('Bun.build failed for server');
|
|
255
310
|
logger.error(
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
import { join } from 'node:path';
|
|
8
8
|
import type { InlineConfig } from 'vite';
|
|
9
9
|
import type { Logger } from '../../../types';
|
|
10
|
-
import { patchPlugin } from './patch-plugin';
|
|
11
10
|
import { browserEnvPlugin } from './browser-env-plugin';
|
|
12
11
|
|
|
13
12
|
export interface ViteBuildOptions {
|
|
@@ -26,7 +25,7 @@ export interface ViteBuildOptions {
|
|
|
26
25
|
|
|
27
26
|
/**
|
|
28
27
|
* Run a Vite build for the specified mode
|
|
29
|
-
*
|
|
28
|
+
* Uses inline Vite config (customizable via agentuity.config.ts)
|
|
30
29
|
*/
|
|
31
30
|
export async function runViteBuild(options: ViteBuildOptions): Promise<void> {
|
|
32
31
|
const { rootDir, mode, dev = false, projectId = '', deploymentId = '', logger } = options;
|
|
@@ -36,7 +35,17 @@ export async function runViteBuild(options: ViteBuildOptions): Promise<void> {
|
|
|
36
35
|
// For server mode, use Bun.build (preserves process.env at runtime)
|
|
37
36
|
if (mode === 'server') {
|
|
38
37
|
try {
|
|
39
|
-
|
|
38
|
+
const srcDir = join(rootDir, 'src');
|
|
39
|
+
|
|
40
|
+
// Generate documentation files (if they don't exist)
|
|
41
|
+
const { generateDocumentation } = await import('./docs-generator');
|
|
42
|
+
await generateDocumentation(srcDir, logger);
|
|
43
|
+
|
|
44
|
+
// Generate lifecycle types (if setup() exists)
|
|
45
|
+
const { generateLifecycleTypes } = await import('./lifecycle-generator');
|
|
46
|
+
await generateLifecycleTypes(rootDir, srcDir, logger);
|
|
47
|
+
|
|
48
|
+
// Then, generate the entry file
|
|
40
49
|
const { generateEntryFile } = await import('../entry-generator');
|
|
41
50
|
await generateEntryFile({
|
|
42
51
|
rootDir,
|
|
@@ -46,7 +55,7 @@ export async function runViteBuild(options: ViteBuildOptions): Promise<void> {
|
|
|
46
55
|
mode: dev ? 'dev' : 'prod',
|
|
47
56
|
});
|
|
48
57
|
|
|
49
|
-
//
|
|
58
|
+
// Finally, build with Bun.build
|
|
50
59
|
const { installExternalsAndBuild } = await import('./server-bundler');
|
|
51
60
|
await installExternalsAndBuild({
|
|
52
61
|
rootDir,
|
|
@@ -76,7 +85,7 @@ export async function runViteBuild(options: ViteBuildOptions): Promise<void> {
|
|
|
76
85
|
const { workbenchEnabled = false, workbenchRoute = '/workbench' } = options;
|
|
77
86
|
|
|
78
87
|
// Load custom user plugins from agentuity.config.ts if it exists
|
|
79
|
-
const plugins = [react(), browserEnvPlugin()
|
|
88
|
+
const plugins = [react(), browserEnvPlugin()];
|
|
80
89
|
const { loadAgentuityConfig } = await import('./config-loader');
|
|
81
90
|
const userConfig = await loadAgentuityConfig(rootDir, logger);
|
|
82
91
|
const userPlugins = userConfig?.plugins || [];
|
|
@@ -147,7 +156,7 @@ export async function runViteBuild(options: ViteBuildOptions): Promise<void> {
|
|
|
147
156
|
viteConfig = {
|
|
148
157
|
root: join(rootDir, '.agentuity/workbench-src'), // Use generated workbench source
|
|
149
158
|
base, // All workbench assets are under the configured route
|
|
150
|
-
plugins: [react()
|
|
159
|
+
plugins: [react()],
|
|
151
160
|
envPrefix: ['VITE_', 'AGENTUITY_PUBLIC_', 'PUBLIC_'],
|
|
152
161
|
define: {
|
|
153
162
|
// Merge user-defined constants
|
|
@@ -214,10 +223,36 @@ export async function runAllBuilds(options: Omit<ViteBuildOptions, 'mode'>): Pro
|
|
|
214
223
|
await generateWorkbenchFiles(rootDir, projectId, workbenchConfig, logger);
|
|
215
224
|
}
|
|
216
225
|
|
|
226
|
+
// 1. Discover agents and routes BEFORE builds
|
|
227
|
+
logger.debug('Discovering agents and routes...');
|
|
228
|
+
const { generateAgentRegistry, generateRouteRegistry } = await import('./registry-generator');
|
|
229
|
+
const { discoverAgents } = await import('./agent-discovery');
|
|
230
|
+
const { discoverRoutes } = await import('./route-discovery');
|
|
231
|
+
|
|
232
|
+
const srcDir = join(rootDir, 'src');
|
|
233
|
+
const agentMetadata = await discoverAgents(
|
|
234
|
+
srcDir,
|
|
235
|
+
projectId,
|
|
236
|
+
options.deploymentId || '',
|
|
237
|
+
logger
|
|
238
|
+
);
|
|
239
|
+
const { routes, routeInfoList } = await discoverRoutes(
|
|
240
|
+
srcDir,
|
|
241
|
+
projectId,
|
|
242
|
+
options.deploymentId || '',
|
|
243
|
+
logger
|
|
244
|
+
);
|
|
245
|
+
|
|
246
|
+
// Generate agent and route registries for type augmentation BEFORE builds
|
|
247
|
+
// (TypeScript needs these files to exist during type checking)
|
|
248
|
+
generateAgentRegistry(srcDir, agentMetadata);
|
|
249
|
+
generateRouteRegistry(srcDir, routeInfoList);
|
|
250
|
+
logger.debug('Agent and route registries generated');
|
|
251
|
+
|
|
217
252
|
// Check if web frontend exists
|
|
218
253
|
const hasWebFrontend = await Bun.file(join(rootDir, 'src', 'web', 'index.html')).exists();
|
|
219
254
|
|
|
220
|
-
//
|
|
255
|
+
// 2. Build client (only if web frontend exists)
|
|
221
256
|
if (hasWebFrontend) {
|
|
222
257
|
logger.debug('Building client assets...');
|
|
223
258
|
try {
|
|
@@ -238,7 +273,7 @@ export async function runAllBuilds(options: Omit<ViteBuildOptions, 'mode'>): Pro
|
|
|
238
273
|
logger.debug('Skipping client build - no src/web/index.html found');
|
|
239
274
|
}
|
|
240
275
|
|
|
241
|
-
//
|
|
276
|
+
// 3. Build workbench (if enabled in config)
|
|
242
277
|
if (workbenchConfig.enabled) {
|
|
243
278
|
logger.debug('Building workbench assets...');
|
|
244
279
|
try {
|
|
@@ -257,7 +292,7 @@ export async function runAllBuilds(options: Omit<ViteBuildOptions, 'mode'>): Pro
|
|
|
257
292
|
}
|
|
258
293
|
}
|
|
259
294
|
|
|
260
|
-
//
|
|
295
|
+
// 4. Build server
|
|
261
296
|
logger.debug('Building server...');
|
|
262
297
|
try {
|
|
263
298
|
const started = Date.now();
|
|
@@ -269,31 +304,9 @@ export async function runAllBuilds(options: Omit<ViteBuildOptions, 'mode'>): Pro
|
|
|
269
304
|
throw error;
|
|
270
305
|
}
|
|
271
306
|
|
|
272
|
-
//
|
|
273
|
-
logger.debug('Generating
|
|
307
|
+
// 5. Generate metadata (after all builds complete)
|
|
308
|
+
logger.debug('Generating metadata...');
|
|
274
309
|
const { generateMetadata, writeMetadataFile } = await import('./metadata-generator');
|
|
275
|
-
const { generateAgentRegistry, generateRouteRegistry } = await import('./registry-generator');
|
|
276
|
-
const { discoverAgents } = await import('./agent-discovery');
|
|
277
|
-
const { discoverRoutes } = await import('./route-discovery');
|
|
278
|
-
|
|
279
|
-
const srcDir = join(rootDir, 'src');
|
|
280
|
-
const agentMetadata = await discoverAgents(
|
|
281
|
-
srcDir,
|
|
282
|
-
projectId,
|
|
283
|
-
options.deploymentId || '',
|
|
284
|
-
logger
|
|
285
|
-
);
|
|
286
|
-
const { routes, routeInfoList } = await discoverRoutes(
|
|
287
|
-
srcDir,
|
|
288
|
-
projectId,
|
|
289
|
-
options.deploymentId || '',
|
|
290
|
-
logger
|
|
291
|
-
);
|
|
292
|
-
|
|
293
|
-
// Generate agent and route registries for type augmentation
|
|
294
|
-
generateAgentRegistry(srcDir, agentMetadata);
|
|
295
|
-
generateRouteRegistry(srcDir, routeInfoList);
|
|
296
|
-
logger.debug('Agent and route registries generated');
|
|
297
310
|
|
|
298
311
|
// Generate metadata
|
|
299
312
|
const metadata = await generateMetadata({
|
|
@@ -75,8 +75,8 @@ export async function viteBundle(options: ViteBundleOptions): Promise<{ output:
|
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
try {
|
|
78
|
-
// Run all
|
|
79
|
-
logger.debug('Starting
|
|
78
|
+
// Run all builds (client -> workbench -> server)
|
|
79
|
+
logger.debug('Starting builds...');
|
|
80
80
|
|
|
81
81
|
const result = await runAllBuilds({
|
|
82
82
|
rootDir,
|
|
@@ -90,16 +90,16 @@ export async function viteBundle(options: ViteBundleOptions): Promise<{ output:
|
|
|
90
90
|
});
|
|
91
91
|
|
|
92
92
|
if (result.client.included) {
|
|
93
|
-
output.push(tui.muted(`✓ Client
|
|
93
|
+
output.push(tui.muted(`✓ Client built in ${result.client.duration}ms`));
|
|
94
94
|
}
|
|
95
95
|
if (result.workbench.included) {
|
|
96
|
-
output.push(tui.muted(`✓ Workbench
|
|
96
|
+
output.push(tui.muted(`✓ Workbench built in ${result.workbench.duration}ms`));
|
|
97
97
|
}
|
|
98
98
|
if (result.server.included) {
|
|
99
|
-
output.push(tui.muted(`✓ Server
|
|
99
|
+
output.push(tui.muted(`✓ Server built in ${result.server.duration}ms`));
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
logger.debug('
|
|
102
|
+
logger.debug('All builds complete');
|
|
103
103
|
|
|
104
104
|
return { output };
|
|
105
105
|
} catch (error) {
|
package/src/cmd/cloud/deploy.ts
CHANGED
|
@@ -6,8 +6,9 @@ import { tmpdir } from 'node:os';
|
|
|
6
6
|
import { StructuredError } from '@agentuity/core';
|
|
7
7
|
import { isRunningFromExecutable } from '../upgrade';
|
|
8
8
|
import { createSubcommand } from '../../types';
|
|
9
|
+
import { getUserAgent } from '../../api';
|
|
9
10
|
import * as tui from '../../tui';
|
|
10
|
-
import { saveProjectDir, getDefaultConfigDir } from '../../config';
|
|
11
|
+
import { saveProjectDir, getDefaultConfigDir, loadProjectSDKKey } from '../../config';
|
|
11
12
|
import {
|
|
12
13
|
runSteps,
|
|
13
14
|
stepSuccess,
|
|
@@ -106,6 +107,15 @@ export const deploySubcommand = createSubcommand({
|
|
|
106
107
|
let statusResult: DeploymentStatusResult | undefined;
|
|
107
108
|
const logs: string[] = [];
|
|
108
109
|
|
|
110
|
+
const sdkKey = await loadProjectSDKKey(ctx.logger, ctx.projectDir);
|
|
111
|
+
|
|
112
|
+
// Ensure SDK key is present before proceeding
|
|
113
|
+
if (!sdkKey) {
|
|
114
|
+
ctx.logger.fatal(
|
|
115
|
+
'SDK key not found. Run "agentuity auth login" to authenticate or set AGENTUITY_SDK_KEY environment variable.'
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
|
|
109
119
|
try {
|
|
110
120
|
await saveProjectDir(projectDir);
|
|
111
121
|
|
|
@@ -241,10 +251,6 @@ export const deploySubcommand = createSubcommand({
|
|
|
241
251
|
const deploymentZip = join(tmpdir(), `${deployment.id}.zip`);
|
|
242
252
|
await zipDir(join(projectDir, '.agentuity'), deploymentZip, {
|
|
243
253
|
filter: (_filename: string, relative: string) => {
|
|
244
|
-
// Exclude Vite-specific build artifacts
|
|
245
|
-
if (relative.endsWith('.generated.ts')) {
|
|
246
|
-
return false;
|
|
247
|
-
}
|
|
248
254
|
if (relative.startsWith('.vite/')) {
|
|
249
255
|
return false;
|
|
250
256
|
}
|
|
@@ -444,6 +450,10 @@ export const deploySubcommand = createSubcommand({
|
|
|
444
450
|
logger.debug('fetching stream: %s/%s', streamsUrl, streamId);
|
|
445
451
|
const resp = await fetch(`${streamsUrl}/${streamId}`, {
|
|
446
452
|
signal: logStreamController.signal,
|
|
453
|
+
headers: {
|
|
454
|
+
Authorization: `Bearer ${sdkKey}`,
|
|
455
|
+
'User-Agent': getUserAgent(),
|
|
456
|
+
},
|
|
447
457
|
});
|
|
448
458
|
if (!resp.ok || !resp.body) {
|
|
449
459
|
ctx.logger.trace(
|
|
@@ -5,9 +5,10 @@
|
|
|
5
5
|
* Handles both backend (API, agents, lib) and generates restart signals.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { watch, type FSWatcher } from 'node:fs';
|
|
8
|
+
import { watch, type FSWatcher, statSync, readdirSync } from 'node:fs';
|
|
9
9
|
import { resolve } from 'node:path';
|
|
10
10
|
import type { Logger } from '../../types';
|
|
11
|
+
import { createAgentTemplates, createAPITemplates } from './templates';
|
|
11
12
|
|
|
12
13
|
export interface FileWatcherOptions {
|
|
13
14
|
rootDir: string;
|
|
@@ -127,6 +128,41 @@ export function createFileWatcher(options: FileWatcherOptions): FileWatcherManag
|
|
|
127
128
|
return;
|
|
128
129
|
}
|
|
129
130
|
|
|
131
|
+
// Check if an empty directory was created in src/agent/ or src/api/
|
|
132
|
+
// This helps with developer experience by auto-scaffolding template files
|
|
133
|
+
if (changedFile && eventType === 'rename') {
|
|
134
|
+
try {
|
|
135
|
+
const absPath = resolve(watchDir, changedFile);
|
|
136
|
+
// Normalize the path for comparison (use forward slashes)
|
|
137
|
+
const normalizedPath = changedFile.replace(/\\/g, '/');
|
|
138
|
+
|
|
139
|
+
// Check if it's a directory and empty
|
|
140
|
+
const stats = statSync(absPath);
|
|
141
|
+
if (stats.isDirectory()) {
|
|
142
|
+
const contents = readdirSync(absPath);
|
|
143
|
+
if (contents.length === 0) {
|
|
144
|
+
// Check if this is an agent or API directory
|
|
145
|
+
if (
|
|
146
|
+
normalizedPath.startsWith('src/agent/') ||
|
|
147
|
+
normalizedPath.includes('/src/agent/')
|
|
148
|
+
) {
|
|
149
|
+
logger.debug('Agent directory created: %s', changedFile);
|
|
150
|
+
createAgentTemplates(absPath);
|
|
151
|
+
} else if (
|
|
152
|
+
normalizedPath.startsWith('src/api/') ||
|
|
153
|
+
normalizedPath.includes('/src/api/')
|
|
154
|
+
) {
|
|
155
|
+
logger.debug('API directory created: %s', changedFile);
|
|
156
|
+
createAPITemplates(absPath);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
} catch (error) {
|
|
161
|
+
// File might have been deleted or doesn't exist yet - this is normal
|
|
162
|
+
logger.trace('Unable to check directory for template creation: %s', error);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
130
166
|
logger.debug('File changed (%s): %s', eventType, changedFile || watchDir);
|
|
131
167
|
onRestart();
|
|
132
168
|
}
|
package/src/cmd/dev/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { resolve, join } from 'node:path';
|
|
3
3
|
import { existsSync } from 'node:fs';
|
|
4
|
-
import {
|
|
4
|
+
import { getServiceUrls } from '@agentuity/server';
|
|
5
5
|
import { createCommand } from '../../types';
|
|
6
6
|
import { startBunDevServer } from '../build/vite/bun-dev-server';
|
|
7
7
|
import { startViteAssetServer } from '../build/vite/vite-asset-server';
|
|
@@ -99,6 +99,13 @@ export const command = createCommand({
|
|
|
99
99
|
|
|
100
100
|
const interactive = !shouldDisableInteractive(opts.interactive);
|
|
101
101
|
|
|
102
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
103
|
+
let originalExit = (globalThis as any).AGENTUITY_PROCESS_EXIT;
|
|
104
|
+
|
|
105
|
+
if (!originalExit) {
|
|
106
|
+
originalExit = process.exit.bind(process);
|
|
107
|
+
}
|
|
108
|
+
|
|
102
109
|
for (const filename of mustHaves) {
|
|
103
110
|
if (!existsSync(filename)) {
|
|
104
111
|
missing.push(filename);
|
|
@@ -110,17 +117,22 @@ export const command = createCommand({
|
|
|
110
117
|
for (const filename of missing) {
|
|
111
118
|
tui.bullet(`Missing ${filename}`);
|
|
112
119
|
}
|
|
113
|
-
|
|
120
|
+
originalExit(1);
|
|
114
121
|
}
|
|
115
122
|
|
|
116
123
|
// Setup devmode and gravity (if using public URL)
|
|
117
124
|
const useMockService = process.env.DEVMODE_SYNC_SERVICE_MOCK === 'true';
|
|
118
125
|
const apiClient = auth ? new APIClient(getAPIBaseURL(config), logger, config) : null;
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
126
|
+
const syncService = apiClient
|
|
127
|
+
? createDevmodeSyncService({
|
|
128
|
+
logger,
|
|
129
|
+
apiClient,
|
|
130
|
+
mock: useMockService,
|
|
131
|
+
})
|
|
132
|
+
: null;
|
|
133
|
+
|
|
134
|
+
// Track previous metadata for sync diffing
|
|
135
|
+
let previousMetadata: Awaited<ReturnType<typeof import('../build/vite/metadata-generator').generateMetadata>> | undefined;
|
|
124
136
|
|
|
125
137
|
let devmode: DevmodeResponse | undefined;
|
|
126
138
|
let gravityBin: string | undefined;
|
|
@@ -224,8 +236,8 @@ export const command = createCommand({
|
|
|
224
236
|
|
|
225
237
|
// Start Vite asset server ONCE before restart loop
|
|
226
238
|
// Vite handles frontend HMR independently and stays running across backend restarts
|
|
227
|
-
let vitePort: number;
|
|
228
239
|
let viteServer: ServerLike | null = null;
|
|
240
|
+
let vitePort: number;
|
|
229
241
|
|
|
230
242
|
try {
|
|
231
243
|
logger.debug('Starting Vite asset server...');
|
|
@@ -241,13 +253,15 @@ export const command = createCommand({
|
|
|
241
253
|
);
|
|
242
254
|
} catch (error) {
|
|
243
255
|
tui.error(`Failed to start Vite asset server: ${error}`);
|
|
244
|
-
|
|
256
|
+
originalExit(1);
|
|
257
|
+
return;
|
|
245
258
|
}
|
|
246
259
|
|
|
247
260
|
// Restart loop - allows BACKEND server to restart on file changes
|
|
248
261
|
// Vite stays running and handles frontend changes via HMR
|
|
249
262
|
let shouldRestart = false;
|
|
250
263
|
let gravityProcess: ProcessLike | null = null;
|
|
264
|
+
let stdinListenerRegistered = false; // Track if stdin listener is already registered
|
|
251
265
|
|
|
252
266
|
const restartServer = () => {
|
|
253
267
|
shouldRestart = true;
|
|
@@ -293,11 +307,22 @@ export const command = createCommand({
|
|
|
293
307
|
}
|
|
294
308
|
}
|
|
295
309
|
|
|
296
|
-
|
|
310
|
+
originalExit(0);
|
|
297
311
|
};
|
|
298
312
|
|
|
299
|
-
|
|
300
|
-
|
|
313
|
+
// SIGINT/SIGTERM: coordinate shutdown between bundle and dev resources
|
|
314
|
+
let devShutdownHandled = false;
|
|
315
|
+
process.on('SIGINT', async () => {
|
|
316
|
+
if (devShutdownHandled) return;
|
|
317
|
+
devShutdownHandled = true;
|
|
318
|
+
// The bundle handles its own shutdown, we clean up dev resources
|
|
319
|
+
await cleanup();
|
|
320
|
+
});
|
|
321
|
+
process.on('SIGTERM', async () => {
|
|
322
|
+
if (devShutdownHandled) return;
|
|
323
|
+
devShutdownHandled = true;
|
|
324
|
+
await cleanup();
|
|
325
|
+
});
|
|
301
326
|
|
|
302
327
|
// Ensure Vite and gravity are always killed on exit (even if cleanup is bypassed)
|
|
303
328
|
process.on('exit', () => {
|
|
@@ -329,23 +354,76 @@ export const command = createCommand({
|
|
|
329
354
|
fileWatcher.pause();
|
|
330
355
|
|
|
331
356
|
try {
|
|
332
|
-
// Generate entry file for
|
|
357
|
+
// Generate entry file and bundle for dev server (with LLM patches)
|
|
333
358
|
await tui.spinner({
|
|
334
|
-
message: '
|
|
359
|
+
message: 'Building dev bundle',
|
|
335
360
|
callback: async () => {
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
361
|
+
const { generateEntryFile } = await import('../build/entry-generator');
|
|
362
|
+
await generateEntryFile({
|
|
363
|
+
rootDir,
|
|
364
|
+
projectId: project?.projectId ?? '',
|
|
365
|
+
deploymentId,
|
|
366
|
+
logger,
|
|
367
|
+
mode: 'dev',
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
// Bundle the app with LLM patches (dev mode = no minification)
|
|
371
|
+
const { installExternalsAndBuild } = await import('../build/vite/server-bundler');
|
|
372
|
+
await installExternalsAndBuild({
|
|
373
|
+
rootDir,
|
|
374
|
+
dev: true, // DevMode: no minification, inline sourcemaps
|
|
375
|
+
logger,
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
// Generate metadata file (needed for eval ID lookup at runtime)
|
|
379
|
+
const { discoverAgents } = await import('../build/vite/agent-discovery');
|
|
380
|
+
const { discoverRoutes } = await import('../build/vite/route-discovery');
|
|
381
|
+
const { generateMetadata, writeMetadataFile } = await import(
|
|
382
|
+
'../build/vite/metadata-generator'
|
|
383
|
+
);
|
|
384
|
+
|
|
385
|
+
const srcDir = join(rootDir, 'src');
|
|
386
|
+
const agents = await discoverAgents(
|
|
387
|
+
srcDir,
|
|
388
|
+
project?.projectId ?? '',
|
|
389
|
+
deploymentId,
|
|
390
|
+
logger
|
|
391
|
+
);
|
|
392
|
+
const { routes } = await discoverRoutes(
|
|
393
|
+
srcDir,
|
|
394
|
+
project?.projectId ?? '',
|
|
395
|
+
deploymentId,
|
|
396
|
+
logger
|
|
397
|
+
);
|
|
398
|
+
|
|
399
|
+
const metadata = await generateMetadata({
|
|
400
|
+
rootDir,
|
|
401
|
+
projectId: project?.projectId ?? '',
|
|
402
|
+
orgId: project?.orgId ?? '',
|
|
403
|
+
deploymentId,
|
|
404
|
+
agents,
|
|
405
|
+
routes,
|
|
406
|
+
dev: true,
|
|
407
|
+
logger,
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
writeMetadataFile(rootDir, metadata, true, logger);
|
|
411
|
+
|
|
412
|
+
// Sync metadata with backend (creates agents and evals in the database)
|
|
413
|
+
if (syncService && project?.projectId) {
|
|
414
|
+
await syncService.sync(
|
|
415
|
+
metadata,
|
|
416
|
+
previousMetadata,
|
|
417
|
+
project.projectId,
|
|
418
|
+
deploymentId
|
|
419
|
+
);
|
|
420
|
+
previousMetadata = metadata;
|
|
421
|
+
}
|
|
344
422
|
},
|
|
345
423
|
clearOnSuccess: true,
|
|
346
424
|
});
|
|
347
425
|
} catch (error) {
|
|
348
|
-
tui.error(`Failed to
|
|
426
|
+
tui.error(`Failed to build dev bundle: ${error}`);
|
|
349
427
|
tui.warn('Waiting for file changes to retry...');
|
|
350
428
|
|
|
351
429
|
// Resume watcher to detect changes for retry
|
|
@@ -364,6 +442,34 @@ export const command = createCommand({
|
|
|
364
442
|
}
|
|
365
443
|
|
|
366
444
|
try {
|
|
445
|
+
// Set environment variables for LLM provider patches BEFORE starting server
|
|
446
|
+
// These must be set so the bundled patches can route LLM calls through AI Gateway
|
|
447
|
+
const serviceUrls = getServiceUrls(project?.region);
|
|
448
|
+
|
|
449
|
+
process.env.AGENTUITY_SDK_DEV_MODE = 'true';
|
|
450
|
+
process.env.AGENTUITY_ENV = 'development';
|
|
451
|
+
process.env.NODE_ENV = 'development';
|
|
452
|
+
if (project?.region) {
|
|
453
|
+
process.env.AGENTUITY_REGION = project.region;
|
|
454
|
+
}
|
|
455
|
+
process.env.PORT = String(opts.port);
|
|
456
|
+
process.env.AGENTUITY_PORT = process.env.PORT;
|
|
457
|
+
|
|
458
|
+
if (project) {
|
|
459
|
+
process.env.AGENTUITY_TRANSPORT_URL = serviceUrls.catalyst;
|
|
460
|
+
process.env.AGENTUITY_CATALYST_URL = serviceUrls.catalyst;
|
|
461
|
+
process.env.AGENTUITY_VECTOR_URL = serviceUrls.vector;
|
|
462
|
+
process.env.AGENTUITY_KEYVALUE_URL = serviceUrls.keyvalue;
|
|
463
|
+
process.env.AGENTUITY_STREAM_URL = serviceUrls.stream;
|
|
464
|
+
process.env.AGENTUITY_CLOUD_ORG_ID = project.orgId;
|
|
465
|
+
process.env.AGENTUITY_CLOUD_PROJECT_ID = project.projectId;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
// Set Vite port for asset proxying in bundled app
|
|
469
|
+
process.env.VITE_PORT = String(vitePort);
|
|
470
|
+
|
|
471
|
+
logger.debug('Set VITE_PORT=%s for asset proxying', process.env.VITE_PORT);
|
|
472
|
+
|
|
367
473
|
// Start Bun dev server (Vite already running, just start backend)
|
|
368
474
|
await startBunDevServer({
|
|
369
475
|
rootDir,
|
|
@@ -375,8 +481,6 @@ export const command = createCommand({
|
|
|
375
481
|
vitePort, // Pass port of already-running Vite server
|
|
376
482
|
});
|
|
377
483
|
|
|
378
|
-
// Note: Bun server runs in-process, no separate app process needed
|
|
379
|
-
|
|
380
484
|
// Wait for app.ts to finish loading (Vite is ready but app may still be initializing)
|
|
381
485
|
// Give it 2 seconds to ensure app initialization completes
|
|
382
486
|
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
@@ -454,8 +558,14 @@ export const command = createCommand({
|
|
|
454
558
|
// TODO: Integrate sync service with Vite's buildStart/buildEnd hooks
|
|
455
559
|
// The sync service will be called when metadata changes are detected
|
|
456
560
|
|
|
457
|
-
// Handle keyboard shortcuts
|
|
458
|
-
if (
|
|
561
|
+
// Handle keyboard shortcuts - only register listener once
|
|
562
|
+
if (
|
|
563
|
+
interactive &&
|
|
564
|
+
process.stdin.isTTY &&
|
|
565
|
+
process.stdout.isTTY &&
|
|
566
|
+
!stdinListenerRegistered
|
|
567
|
+
) {
|
|
568
|
+
stdinListenerRegistered = true;
|
|
459
569
|
process.stdin.setRawMode(true);
|
|
460
570
|
process.stdin.resume();
|
|
461
571
|
process.stdin.setEncoding('utf8');
|
|
@@ -470,9 +580,10 @@ export const command = createCommand({
|
|
|
470
580
|
process.stdin.on('data', (data) => {
|
|
471
581
|
const key = data.toString();
|
|
472
582
|
|
|
473
|
-
// Handle Ctrl+C
|
|
583
|
+
// Handle Ctrl+C - send SIGINT to trigger graceful shutdown
|
|
474
584
|
if (key === '\u0003') {
|
|
475
|
-
|
|
585
|
+
process.kill(process.pid, 'SIGINT');
|
|
586
|
+
return;
|
|
476
587
|
}
|
|
477
588
|
|
|
478
589
|
switch (key) {
|
|
@@ -489,7 +600,7 @@ export const command = createCommand({
|
|
|
489
600
|
});
|
|
490
601
|
break;
|
|
491
602
|
case 'q':
|
|
492
|
-
|
|
603
|
+
originalExit(0);
|
|
493
604
|
break;
|
|
494
605
|
default:
|
|
495
606
|
process.stdout.write(data);
|