@agentuity/cli 0.0.98 → 0.0.100

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.
Files changed (71) hide show
  1. package/dist/auth.d.ts.map +1 -1
  2. package/dist/auth.js +5 -0
  3. package/dist/auth.js.map +1 -1
  4. package/dist/banner.d.ts.map +1 -1
  5. package/dist/banner.js +22 -6
  6. package/dist/banner.js.map +1 -1
  7. package/dist/cmd/build/entry-generator.d.ts.map +1 -1
  8. package/dist/cmd/build/entry-generator.js +84 -61
  9. package/dist/cmd/build/entry-generator.js.map +1 -1
  10. package/dist/cmd/build/vite/bun-dev-server.d.ts +3 -7
  11. package/dist/cmd/build/vite/bun-dev-server.d.ts.map +1 -1
  12. package/dist/cmd/build/vite/bun-dev-server.js +5 -14
  13. package/dist/cmd/build/vite/bun-dev-server.js.map +1 -1
  14. package/dist/cmd/build/vite/index.d.ts +0 -1
  15. package/dist/cmd/build/vite/index.d.ts.map +1 -1
  16. package/dist/cmd/build/vite/index.js +0 -1
  17. package/dist/cmd/build/vite/index.js.map +1 -1
  18. package/dist/cmd/build/vite/server-bundler.d.ts.map +1 -1
  19. package/dist/cmd/build/vite/server-bundler.js +41 -1
  20. package/dist/cmd/build/vite/server-bundler.js.map +1 -1
  21. package/dist/cmd/build/vite/vite-asset-server-config.d.ts.map +1 -1
  22. package/dist/cmd/build/vite/vite-asset-server-config.js +17 -1
  23. package/dist/cmd/build/vite/vite-asset-server-config.js.map +1 -1
  24. package/dist/cmd/build/vite/vite-asset-server.js +1 -1
  25. package/dist/cmd/build/vite/vite-asset-server.js.map +1 -1
  26. package/dist/cmd/build/vite/vite-builder.d.ts.map +1 -1
  27. package/dist/cmd/build/vite/vite-builder.js +22 -4
  28. package/dist/cmd/build/vite/vite-builder.js.map +1 -1
  29. package/dist/cmd/cloud/deploy.d.ts.map +1 -1
  30. package/dist/cmd/cloud/deploy.js +32 -21
  31. package/dist/cmd/cloud/deploy.js.map +1 -1
  32. package/dist/cmd/dev/file-watcher.d.ts +24 -0
  33. package/dist/cmd/dev/file-watcher.d.ts.map +1 -0
  34. package/dist/cmd/dev/file-watcher.js +213 -0
  35. package/dist/cmd/dev/file-watcher.js.map +1 -0
  36. package/dist/cmd/dev/index.d.ts.map +1 -1
  37. package/dist/cmd/dev/index.js +61 -23
  38. package/dist/cmd/dev/index.js.map +1 -1
  39. package/dist/cmd/project/create.d.ts.map +1 -1
  40. package/dist/cmd/project/create.js +8 -2
  41. package/dist/cmd/project/create.js.map +1 -1
  42. package/dist/cmd/setup/index.d.ts.map +1 -1
  43. package/dist/cmd/setup/index.js +3 -3
  44. package/dist/cmd/setup/index.js.map +1 -1
  45. package/dist/repl.js +2 -2
  46. package/dist/repl.js.map +1 -1
  47. package/dist/types.d.ts +6 -0
  48. package/dist/types.d.ts.map +1 -1
  49. package/dist/types.js.map +1 -1
  50. package/package.json +8 -4
  51. package/src/auth.ts +6 -0
  52. package/src/banner.ts +25 -6
  53. package/src/cmd/build/entry-generator.ts +84 -62
  54. package/src/cmd/build/vite/bun-dev-server.ts +8 -18
  55. package/src/cmd/build/vite/index.ts +0 -1
  56. package/src/cmd/build/vite/server-bundler.ts +52 -1
  57. package/src/cmd/build/vite/vite-asset-server-config.ts +22 -1
  58. package/src/cmd/build/vite/vite-asset-server.ts +1 -1
  59. package/src/cmd/build/vite/vite-builder.ts +30 -4
  60. package/src/cmd/cloud/deploy.ts +41 -24
  61. package/src/cmd/dev/file-watcher.ts +264 -0
  62. package/src/cmd/dev/index.ts +69 -24
  63. package/src/cmd/project/create.ts +13 -3
  64. package/src/cmd/setup/index.ts +7 -3
  65. package/src/repl.ts +2 -2
  66. package/src/types.ts +6 -0
  67. package/dist/cmd/build/vite/patch-plugin.d.ts +0 -21
  68. package/dist/cmd/build/vite/patch-plugin.d.ts.map +0 -1
  69. package/dist/cmd/build/vite/patch-plugin.js +0 -70
  70. package/dist/cmd/build/vite/patch-plugin.js.map +0 -1
  71. package/src/cmd/build/vite/patch-plugin.ts +0 -88
@@ -0,0 +1,264 @@
1
+ /**
2
+ * File Watcher for Dev Server Hot Reload
3
+ *
4
+ * Watches source files and triggers server restart on changes.
5
+ * Handles both backend (API, agents, lib) and generates restart signals.
6
+ */
7
+
8
+ import { watch, type FSWatcher, statSync, readdirSync } from 'node:fs';
9
+ import { resolve } from 'node:path';
10
+ import type { Logger } from '../../types';
11
+ import { createAgentTemplates, createAPITemplates } from './templates';
12
+
13
+ export interface FileWatcherOptions {
14
+ rootDir: string;
15
+ logger: Logger;
16
+ onRestart: () => void;
17
+ additionalPaths?: string[];
18
+ }
19
+
20
+ export interface FileWatcherManager {
21
+ start: () => void;
22
+ stop: () => void;
23
+ pause: () => void;
24
+ resume: () => void;
25
+ }
26
+
27
+ /**
28
+ * Create a file watcher manager for hot reload
29
+ */
30
+ export function createFileWatcher(options: FileWatcherOptions): FileWatcherManager {
31
+ const { rootDir, logger, onRestart, additionalPaths = [] } = options;
32
+
33
+ const watchers: FSWatcher[] = [];
34
+ let paused = false;
35
+ let buildCooldownTimer: NodeJS.Timeout | null = null;
36
+
37
+ // Watch the entire root directory recursively
38
+ // This is simpler and more reliable than watching individual paths
39
+ const watchDirs = [rootDir];
40
+
41
+ // Directories to ignore
42
+ const ignorePaths = [
43
+ '.agentuity',
44
+ 'node_modules',
45
+ '.git',
46
+ 'dist',
47
+ 'build',
48
+ '.next',
49
+ '.turbo',
50
+ 'src/web', // Vite handles frontend with HMR - no backend restart needed
51
+ ];
52
+
53
+ /**
54
+ * Check if a path should be ignored
55
+ */
56
+ function shouldIgnorePath(changedFile: string | null, watchDir: string): boolean {
57
+ if (!changedFile) return false;
58
+
59
+ const absPath = resolve(watchDir, changedFile);
60
+
61
+ // Check against ignore list - match both relative path and absolute path
62
+ for (const ignorePath of ignorePaths) {
63
+ // Check relative path from watchDir
64
+ if (
65
+ changedFile === ignorePath ||
66
+ changedFile.startsWith(`${ignorePath}/`) ||
67
+ changedFile.startsWith(`${ignorePath}\\`)
68
+ ) {
69
+ logger.trace('File change ignored (%s): %s', ignorePath, changedFile);
70
+ return true;
71
+ }
72
+
73
+ // Check if absolute path contains the ignore pattern
74
+ const ignoreAbsPath = resolve(rootDir, ignorePath);
75
+ if (
76
+ absPath === ignoreAbsPath ||
77
+ absPath.startsWith(`${ignoreAbsPath}/`) ||
78
+ absPath.startsWith(`${ignoreAbsPath}\\`)
79
+ ) {
80
+ logger.trace('File change ignored (%s): %s', ignorePath, changedFile);
81
+ return true;
82
+ }
83
+
84
+ // Also check if changedFile path includes the ignore pattern anywhere
85
+ // This handles cases like "some/path/.agentuity/file.js"
86
+ const normalizedChanged = changedFile.replace(/\\/g, '/');
87
+ const normalizedIgnore = ignorePath.replace(/\\/g, '/');
88
+ if (
89
+ normalizedChanged.includes(`/${normalizedIgnore}/`) ||
90
+ normalizedChanged.includes(`/${normalizedIgnore}`)
91
+ ) {
92
+ logger.trace('File change ignored (%s in path): %s', ignorePath, changedFile);
93
+ return true;
94
+ }
95
+ }
96
+
97
+ // Ignore temp files from editors
98
+ if (changedFile.match(/\.(tmp|swp|swo|swx)$|~$/)) {
99
+ logger.trace('File change ignored (temp file): %s', changedFile);
100
+ return true;
101
+ }
102
+
103
+ // Ignore hidden files (except .env)
104
+ if (changedFile.startsWith('.') && !changedFile.startsWith('.env')) {
105
+ logger.trace('File change ignored (hidden file): %s', changedFile);
106
+ return true;
107
+ }
108
+
109
+ return false;
110
+ }
111
+
112
+ /**
113
+ * Handle file change event
114
+ */
115
+ function handleFileChange(eventType: string, changedFile: string | null, watchDir: string) {
116
+ if (paused) {
117
+ logger.trace('File change ignored (watcher paused): %s', changedFile);
118
+ return;
119
+ }
120
+
121
+ if (shouldIgnorePath(changedFile, watchDir)) {
122
+ return;
123
+ }
124
+
125
+ // During build cooldown, ignore changes (they're likely build outputs)
126
+ if (buildCooldownTimer) {
127
+ logger.trace('File change ignored (build cooldown): %s', changedFile);
128
+ return;
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 (normalizedPath.startsWith('src/agent/') || normalizedPath.includes('/src/agent/')) {
146
+ logger.debug('Agent directory created: %s', changedFile);
147
+ createAgentTemplates(absPath);
148
+ } else if (normalizedPath.startsWith('src/api/') || normalizedPath.includes('/src/api/')) {
149
+ logger.debug('API directory created: %s', changedFile);
150
+ createAPITemplates(absPath);
151
+ }
152
+ }
153
+ }
154
+ } catch (error) {
155
+ // File might have been deleted or doesn't exist yet - this is normal
156
+ logger.trace('Unable to check directory for template creation: %s', error);
157
+ }
158
+ }
159
+
160
+ logger.debug('File changed (%s): %s', eventType, changedFile || watchDir);
161
+ onRestart();
162
+ }
163
+
164
+ /**
165
+ * Start watching files
166
+ */
167
+ function start() {
168
+ logger.debug('Starting file watchers for hot reload...');
169
+
170
+ // Watch root directory (already absolute path)
171
+ for (const watchPath of watchDirs) {
172
+ try {
173
+ logger.trace('Setting up watcher for: %s', watchPath);
174
+
175
+ const watcher = watch(watchPath, { recursive: true }, (eventType, changedFile) => {
176
+ handleFileChange(eventType, changedFile, watchPath);
177
+ });
178
+
179
+ watchers.push(watcher);
180
+ logger.trace('Watcher started for: %s', watchPath);
181
+ } catch (error) {
182
+ logger.warn('Failed to start watcher for %s: %s', watchPath, error);
183
+ }
184
+ }
185
+
186
+ // Watch additional paths if provided
187
+ if (additionalPaths && additionalPaths.length > 0) {
188
+ for (const additionalPath of additionalPaths) {
189
+ const fullPath = resolve(rootDir, additionalPath);
190
+ try {
191
+ logger.trace('Setting up watcher for additional path: %s', fullPath);
192
+
193
+ const watcher = watch(fullPath, { recursive: true }, (eventType, changedFile) => {
194
+ handleFileChange(eventType, changedFile, fullPath);
195
+ });
196
+
197
+ watchers.push(watcher);
198
+ logger.trace('Watcher started for additional path: %s', fullPath);
199
+ } catch (error) {
200
+ logger.warn('Failed to start watcher for %s: %s', fullPath, error);
201
+ }
202
+ }
203
+ }
204
+
205
+ logger.debug('File watchers started (%d paths)', watchers.length);
206
+ }
207
+
208
+ /**
209
+ * Stop all watchers
210
+ */
211
+ function stop() {
212
+ logger.debug('Stopping file watchers...');
213
+
214
+ for (const watcher of watchers) {
215
+ try {
216
+ watcher.close();
217
+ } catch (error) {
218
+ logger.trace('Error closing watcher: %s', error);
219
+ }
220
+ }
221
+
222
+ watchers.length = 0;
223
+
224
+ if (buildCooldownTimer) {
225
+ clearTimeout(buildCooldownTimer);
226
+ buildCooldownTimer = null;
227
+ }
228
+
229
+ logger.debug('File watchers stopped');
230
+ }
231
+
232
+ /**
233
+ * Temporarily pause watching (e.g., during build)
234
+ */
235
+ function pause() {
236
+ paused = true;
237
+ logger.trace('File watchers paused');
238
+
239
+ // Set cooldown timer to ignore changes for a bit after build
240
+ if (buildCooldownTimer) {
241
+ clearTimeout(buildCooldownTimer);
242
+ }
243
+
244
+ buildCooldownTimer = setTimeout(() => {
245
+ buildCooldownTimer = null;
246
+ logger.trace('Build cooldown expired');
247
+ }, 500); // 500ms cooldown
248
+ }
249
+
250
+ /**
251
+ * Resume watching
252
+ */
253
+ function resume() {
254
+ paused = false;
255
+ logger.trace('File watchers resumed');
256
+ }
257
+
258
+ return {
259
+ start,
260
+ stop,
261
+ pause,
262
+ resume,
263
+ };
264
+ }
@@ -4,6 +4,7 @@ import { existsSync } from 'node:fs';
4
4
  import { internalExit } from '@agentuity/runtime';
5
5
  import { createCommand } from '../../types';
6
6
  import { startBunDevServer } from '../build/vite/bun-dev-server';
7
+ import { startViteAssetServer } from '../build/vite/vite-asset-server';
7
8
  import * as tui from '../../tui';
8
9
  import { getCommand } from '../../command-prefix';
9
10
  import { generateEndpoint, type DevmodeResponse } from './api';
@@ -13,6 +14,7 @@ import { createDevmodeSyncService } from './sync';
13
14
  import { getDevmodeDeploymentId } from '../build/ast';
14
15
  import { getDefaultConfigDir, saveConfig } from '../../config';
15
16
  import type { Config } from '../../types';
17
+ import { createFileWatcher } from './file-watcher';
16
18
 
17
19
  const DEFAULT_PORT = 3500;
18
20
  const MIN_PORT = 1024;
@@ -220,9 +222,31 @@ export const command = createCommand({
220
222
  centerTitle: false,
221
223
  });
222
224
 
223
- // Restart loop - allows server to restart on file changes
224
- let shouldRestart = false;
225
+ // Start Vite asset server ONCE before restart loop
226
+ // Vite handles frontend HMR independently and stays running across backend restarts
227
+ let vitePort: number;
225
228
  let viteServer: ServerLike | null = null;
229
+
230
+ try {
231
+ logger.debug('Starting Vite asset server...');
232
+ const viteResult = await startViteAssetServer({
233
+ rootDir,
234
+ logger,
235
+ workbenchPath: workbench.config?.route,
236
+ });
237
+ viteServer = viteResult.server;
238
+ vitePort = viteResult.port;
239
+ logger.debug(
240
+ `Vite asset server running on port ${vitePort} (stays running across backend restarts)`
241
+ );
242
+ } catch (error) {
243
+ tui.error(`Failed to start Vite asset server: ${error}`);
244
+ internalExit(1);
245
+ }
246
+
247
+ // Restart loop - allows BACKEND server to restart on file changes
248
+ // Vite stays running and handles frontend changes via HMR
249
+ let shouldRestart = false;
226
250
  let gravityProcess: ProcessLike | null = null;
227
251
 
228
252
  const restartServer = () => {
@@ -233,13 +257,23 @@ export const command = createCommand({
233
257
  logger.info('DevMode ready 🚀');
234
258
  };
235
259
 
236
- // Make restart function available globally for HMR plugin
237
- (globalThis as Record<string, unknown>).__AGENTUITY_RESTART__ = restartServer;
260
+ // Create file watcher for backend hot reload
261
+ const fileWatcher = createFileWatcher({
262
+ rootDir,
263
+ logger,
264
+ onRestart: restartServer,
265
+ });
266
+
267
+ // Start file watcher (will be paused during builds)
268
+ fileWatcher.start();
238
269
 
239
270
  // Setup signal handlers once before the loop
240
271
  const cleanup = async () => {
241
272
  tui.info('Shutting down...');
242
273
 
274
+ // Stop file watcher
275
+ fileWatcher.stop();
276
+
243
277
  // Close Vite asset server first
244
278
  if (viteServer) {
245
279
  await viteServer.close();
@@ -265,13 +299,24 @@ export const command = createCommand({
265
299
  process.on('SIGINT', cleanup);
266
300
  process.on('SIGTERM', cleanup);
267
301
 
268
- // Ensure gravity client is always killed on exit (even if cleanup is bypassed)
269
- // Use SIGKILL for immediate termination since the process is already exiting
302
+ // Ensure Vite and gravity are always killed on exit (even if cleanup is bypassed)
270
303
  process.on('exit', () => {
304
+ // Close Vite server synchronously if possible
305
+ // Note: Vite's close() is async, but we can't await in 'exit' handler
306
+ // Most Vite implementations handle sync close gracefully
307
+ if (viteServer) {
308
+ try {
309
+ viteServer.close();
310
+ } catch {
311
+ // Ignore errors during exit cleanup
312
+ }
313
+ }
314
+
315
+ // Kill gravity client with SIGKILL for immediate termination
271
316
  if (gravityProcess && gravityProcess.exitCode === null) {
272
317
  try {
273
318
  gravityProcess.kill('SIGKILL');
274
- } catch (_err) {
319
+ } catch {
275
320
  // Ignore errors during exit cleanup
276
321
  }
277
322
  }
@@ -280,6 +325,9 @@ export const command = createCommand({
280
325
  while (true) {
281
326
  shouldRestart = false;
282
327
 
328
+ // Pause file watcher during build to avoid loops
329
+ fileWatcher.pause();
330
+
283
331
  try {
284
332
  // Generate entry file for Vite before starting dev server
285
333
  await tui.spinner({
@@ -300,6 +348,9 @@ export const command = createCommand({
300
348
  tui.error(`Failed to generate entry file: ${error}`);
301
349
  tui.warn('Waiting for file changes to retry...');
302
350
 
351
+ // Resume watcher to detect changes for retry
352
+ fileWatcher.resume();
353
+
303
354
  // Wait for next restart trigger
304
355
  await new Promise<void>((resolve) => {
305
356
  const checkRestart = setInterval(() => {
@@ -313,17 +364,17 @@ export const command = createCommand({
313
364
  }
314
365
 
315
366
  try {
316
- // Start Bun dev server (with Vite asset server for HMR)
317
- const result = await startBunDevServer({
367
+ // Start Bun dev server (Vite already running, just start backend)
368
+ await startBunDevServer({
318
369
  rootDir,
319
370
  port: opts.port,
320
371
  projectId: project?.projectId,
321
372
  orgId: project?.orgId,
322
373
  deploymentId,
323
374
  logger,
375
+ vitePort, // Pass port of already-running Vite server
324
376
  });
325
377
 
326
- viteServer = result.viteAssetServer.server;
327
378
  // Note: Bun server runs in-process, no separate app process needed
328
379
 
329
380
  // Wait for app.ts to finish loading (Vite is ready but app may still be initializing)
@@ -441,7 +492,7 @@ export const command = createCommand({
441
492
  internalExit(0);
442
493
  break;
443
494
  default:
444
- console.log(data);
495
+ process.stdout.write(data);
445
496
  break;
446
497
  }
447
498
  });
@@ -449,6 +500,9 @@ export const command = createCommand({
449
500
 
450
501
  showWelcome();
451
502
 
503
+ // Start/resume file watcher now that server is ready
504
+ fileWatcher.resume();
505
+
452
506
  // Wait for restart signal
453
507
  await new Promise<void>((resolve) => {
454
508
  const checkRestart = setInterval(() => {
@@ -459,14 +513,10 @@ export const command = createCommand({
459
513
  }, 100);
460
514
  });
461
515
 
462
- // Restart triggered - cleanup and loop
463
- tui.info('Restarting server...');
464
-
465
- // Close Vite asset server
466
- if (viteServer) {
467
- await viteServer.close();
468
- }
516
+ // Restart triggered - cleanup and loop (Vite stays running)
517
+ logger.debug('Restarting backend server...');
469
518
 
519
+ // Kill gravity client (if running)
470
520
  if (gravityProcess) {
471
521
  try {
472
522
  gravityProcess.kill('SIGTERM');
@@ -485,11 +535,7 @@ export const command = createCommand({
485
535
  tui.error(`Error during server operation: ${error}`);
486
536
  tui.warn('Waiting for file changes to retry...');
487
537
 
488
- // Cleanup on error - close Vite asset server
489
- if (viteServer) {
490
- await viteServer.close();
491
- }
492
-
538
+ // Cleanup on error (Vite stays running)
493
539
  if (gravityProcess) {
494
540
  try {
495
541
  gravityProcess.kill('SIGTERM');
@@ -501,7 +547,6 @@ export const command = createCommand({
501
547
  logger.debug('Error killing gravity process on error: %s', err);
502
548
  }
503
549
  }
504
- if (viteServer) await viteServer.close();
505
550
 
506
551
  // Wait for next restart trigger
507
552
  await new Promise<void>((resolve) => {
@@ -1,7 +1,8 @@
1
- import { createSubcommand } from '../../types';
1
+ import { createSubcommand, type CommandContext, type AuthData } from '../../types';
2
2
  import { z } from 'zod';
3
3
  import { runCreateFlow } from './template-flow';
4
4
  import { getCommand } from '../../command-prefix';
5
+ import type { APIClient as APIClientType } from '../../api';
5
6
 
6
7
  const ProjectCreateResponseSchema = z.object({
7
8
  success: z.boolean().describe('Whether the operation succeeded'),
@@ -21,7 +22,7 @@ export const createProjectSubcommand = createSubcommand({
21
22
  banner: true,
22
23
  toplevel: true,
23
24
  idempotent: false,
24
- optional: { auth: true, org: true, region: true, apiClient: true },
25
+ optional: { auth: true, region: true, apiClient: true },
25
26
  examples: [
26
27
  { command: getCommand('project create'), description: 'Create new item' },
27
28
  { command: getCommand('project create --name my-ai-agent'), description: 'Create new item' },
@@ -69,7 +70,16 @@ export const createProjectSubcommand = createSubcommand({
69
70
  },
70
71
 
71
72
  async handler(ctx) {
72
- const { logger, opts, auth, config, apiClient, orgId, region } = ctx;
73
+ const { logger, opts, auth, config, apiClient, region } = ctx;
74
+
75
+ // Only get org if registering
76
+ let orgId: string | undefined;
77
+ if (opts.register === true && auth && apiClient) {
78
+ const { optionalOrg } = await import('../../auth');
79
+ orgId = await optionalOrg(
80
+ ctx as CommandContext & { apiClient?: APIClientType; auth?: AuthData }
81
+ );
82
+ }
73
83
 
74
84
  await runCreateFlow({
75
85
  projectName: opts.name,
@@ -29,10 +29,14 @@ export const command = createCommand({
29
29
  tui.output(`${tui.muted('To get started, run:')}`);
30
30
  tui.newline();
31
31
  tui.output(
32
- `${getCommand('login')} ${tui.muted('Login to an existing account (or signup)')}`
32
+ `${tui.colorPrimary(getCommand('login'))} ${tui.muted('Login to an existing account (or signup)')}`
33
+ );
34
+ tui.output(
35
+ `${tui.colorPrimary(getCommand('create'))} ${tui.muted('Create a project')}`
36
+ );
37
+ tui.output(
38
+ `${tui.colorPrimary(getCommand('help'))} ${tui.muted('List commands and options')}`
33
39
  );
34
- tui.output(`${getCommand('create')} ${tui.muted('Create a project')}`);
35
- tui.output(`${getCommand('help')} ${tui.muted('List commands and options')}`);
36
40
  } else {
37
41
  tui.success('Welcome back! 🙌');
38
42
  }
package/src/repl.ts CHANGED
@@ -236,7 +236,7 @@ async function loadHistory(name: string): Promise<string[]> {
236
236
 
237
237
  const content = await Bun.file(historyFile).text();
238
238
  return content.split('\n').filter((line) => line.trim());
239
- } catch (_err) {
239
+ } catch {
240
240
  return [];
241
241
  }
242
242
  }
@@ -253,7 +253,7 @@ async function saveHistory(name: string, history: string[]): Promise<void> {
253
253
 
254
254
  const historyFile = join(historyDir, `${name}.txt`);
255
255
  await Bun.write(historyFile, history.join('\n'));
256
- } catch (_err) {
256
+ } catch {
257
257
  // Silently fail - history is not critical
258
258
  }
259
259
  }
package/src/types.ts CHANGED
@@ -137,6 +137,12 @@ export interface AgentuityConfig {
137
137
  * These are added AFTER Agentuity's built-in plugins
138
138
  */
139
139
  plugins?: Array<import('vite').Plugin>;
140
+ /**
141
+ * Additional define constants for code replacement in Vite builds
142
+ * These are merged with Agentuity's default defines
143
+ * Note: Cannot override AGENTUITY_PUBLIC_* or process.env.NODE_ENV
144
+ */
145
+ define?: Record<string, string>;
140
146
  }
141
147
 
142
148
  /**
@@ -1,21 +0,0 @@
1
- /**
2
- * Vite Plugin for Runtime Patching
3
- *
4
- * Applies runtime patches to AI SDK packages to inject:
5
- * - Agentuity AI Gateway routing
6
- * - Telemetry enablement
7
- * - Environment variable guards
8
- *
9
- * This plugin uses Vite's transform hook to modify module code during bundling.
10
- */
11
- import type { Plugin } from 'vite';
12
- import type { Logger } from '../../../types';
13
- export interface PatchPluginOptions {
14
- logger: Logger;
15
- dev?: boolean;
16
- }
17
- /**
18
- * Create Vite plugin that patches AI SDK modules at build time
19
- */
20
- export declare function patchPlugin(options: PatchPluginOptions): Plugin;
21
- //# sourceMappingURL=patch-plugin.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"patch-plugin.d.ts","sourceRoot":"","sources":["../../../../src/cmd/build/vite/patch-plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AACnC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAG7C,MAAM,WAAW,kBAAkB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,OAAO,CAAC;CACd;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,MAAM,CAgE/D"}
@@ -1,70 +0,0 @@
1
- /**
2
- * Vite Plugin for Runtime Patching
3
- *
4
- * Applies runtime patches to AI SDK packages to inject:
5
- * - Agentuity AI Gateway routing
6
- * - Telemetry enablement
7
- * - Environment variable guards
8
- *
9
- * This plugin uses Vite's transform hook to modify module code during bundling.
10
- */
11
- import { generatePatches, applyPatch } from '../patch';
12
- /**
13
- * Create Vite plugin that patches AI SDK modules at build time
14
- */
15
- export function patchPlugin(options) {
16
- const { logger } = options;
17
- const patches = generatePatches();
18
- // Log registered patches
19
- logger.trace('Patch plugin initialized with %d patch(es)', patches.size);
20
- for (const [moduleName] of patches) {
21
- logger.trace(' - %s', moduleName);
22
- }
23
- return {
24
- name: 'agentuity:patch',
25
- enforce: 'post', // Run after other transforms
26
- /**
27
- * Transform hook - patches modules during bundling
28
- */
29
- async transform(code, id) {
30
- // Check if this module needs patching
31
- for (const [moduleName, patch] of patches) {
32
- // Match module by package name
33
- const normalizedId = id.replace(/\\/g, '/');
34
- // Check if this file matches the patch module
35
- // Example: node_modules/@ai-sdk/openai/dist/index.js
36
- if (!normalizedId.includes(`node_modules/${moduleName}/`)) {
37
- continue;
38
- }
39
- // If patch specifies a filename, ensure it matches
40
- if (patch.filename) {
41
- const expectedPath = `${moduleName}/${patch.filename}`;
42
- if (!normalizedId.includes(expectedPath) &&
43
- !normalizedId.includes(`${expectedPath}.js`) &&
44
- !normalizedId.includes(`${expectedPath}.mjs`) &&
45
- !normalizedId.includes(`${expectedPath}.ts`)) {
46
- continue;
47
- }
48
- }
49
- // Apply the patch
50
- logger.debug('Applying patch to %s', moduleName);
51
- try {
52
- const [patchedCode] = await applyPatch(id, patch);
53
- // Return transformed code with source map
54
- return {
55
- code: patchedCode,
56
- map: null, // Could add source map generation here
57
- };
58
- }
59
- catch (error) {
60
- logger.warn('Failed to apply patch to %s: %s', moduleName, error);
61
- // Continue without patching on error
62
- return null;
63
- }
64
- }
65
- // No patch needed
66
- return null;
67
- },
68
- };
69
- }
70
- //# sourceMappingURL=patch-plugin.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"patch-plugin.js","sourceRoot":"","sources":["../../../../src/cmd/build/vite/patch-plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAOvD;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,OAA2B;IACtD,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAC3B,MAAM,OAAO,GAAG,eAAe,EAAE,CAAC;IAElC,yBAAyB;IACzB,MAAM,CAAC,KAAK,CAAC,4CAA4C,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IACzE,KAAK,MAAM,CAAC,UAAU,CAAC,IAAI,OAAO,EAAE,CAAC;QACpC,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IACpC,CAAC;IAED,OAAO;QACN,IAAI,EAAE,iBAAiB;QACvB,OAAO,EAAE,MAAM,EAAE,6BAA6B;QAE9C;;WAEG;QACH,KAAK,CAAC,SAAS,CAAC,IAAY,EAAE,EAAU;YACvC,sCAAsC;YACtC,KAAK,MAAM,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,OAAO,EAAE,CAAC;gBAC3C,+BAA+B;gBAC/B,MAAM,YAAY,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;gBAE5C,8CAA8C;gBAC9C,qDAAqD;gBACrD,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,gBAAgB,UAAU,GAAG,CAAC,EAAE,CAAC;oBAC3D,SAAS;gBACV,CAAC;gBAED,mDAAmD;gBACnD,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;oBACpB,MAAM,YAAY,GAAG,GAAG,UAAU,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;oBACvD,IACC,CAAC,YAAY,CAAC,QAAQ,CAAC,YAAY,CAAC;wBACpC,CAAC,YAAY,CAAC,QAAQ,CAAC,GAAG,YAAY,KAAK,CAAC;wBAC5C,CAAC,YAAY,CAAC,QAAQ,CAAC,GAAG,YAAY,MAAM,CAAC;wBAC7C,CAAC,YAAY,CAAC,QAAQ,CAAC,GAAG,YAAY,KAAK,CAAC,EAC3C,CAAC;wBACF,SAAS;oBACV,CAAC;gBACF,CAAC;gBAED,kBAAkB;gBAClB,MAAM,CAAC,KAAK,CAAC,sBAAsB,EAAE,UAAU,CAAC,CAAC;gBAEjD,IAAI,CAAC;oBACJ,MAAM,CAAC,WAAW,CAAC,GAAG,MAAM,UAAU,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;oBAElD,0CAA0C;oBAC1C,OAAO;wBACN,IAAI,EAAE,WAAW;wBACjB,GAAG,EAAE,IAAI,EAAE,uCAAuC;qBAClD,CAAC;gBACH,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBAChB,MAAM,CAAC,IAAI,CAAC,iCAAiC,EAAE,UAAU,EAAE,KAAK,CAAC,CAAC;oBAClE,qCAAqC;oBACrC,OAAO,IAAI,CAAC;gBACb,CAAC;YACF,CAAC;YAED,kBAAkB;YAClB,OAAO,IAAI,CAAC;QACb,CAAC;KACD,CAAC;AACH,CAAC"}