@agentuity/cli 0.1.1 → 0.1.3

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 (43) hide show
  1. package/dist/cmd/build/ast.d.ts.map +1 -1
  2. package/dist/cmd/build/ast.js +9 -9
  3. package/dist/cmd/build/ast.js.map +1 -1
  4. package/dist/cmd/build/entry-generator.d.ts.map +1 -1
  5. package/dist/cmd/build/entry-generator.js +7 -3
  6. package/dist/cmd/build/entry-generator.js.map +1 -1
  7. package/dist/cmd/build/vite/config-loader.d.ts +3 -1
  8. package/dist/cmd/build/vite/config-loader.d.ts.map +1 -1
  9. package/dist/cmd/build/vite/config-loader.js +5 -3
  10. package/dist/cmd/build/vite/config-loader.js.map +1 -1
  11. package/dist/cmd/build/vite/index.js +1 -1
  12. package/dist/cmd/build/vite/index.js.map +1 -1
  13. package/dist/cmd/build/vite/vite-builder.js +1 -1
  14. package/dist/cmd/build/vite/vite-builder.js.map +1 -1
  15. package/dist/cmd/build/webanalytics-generator.js +3 -27
  16. package/dist/cmd/build/webanalytics-generator.js.map +1 -1
  17. package/dist/cmd/dev/index.d.ts.map +1 -1
  18. package/dist/cmd/dev/index.js +8 -0
  19. package/dist/cmd/dev/index.js.map +1 -1
  20. package/dist/cmd/project/auth/shared.d.ts +2 -1
  21. package/dist/cmd/project/auth/shared.d.ts.map +1 -1
  22. package/dist/cmd/project/auth/shared.js +2 -1
  23. package/dist/cmd/project/auth/shared.js.map +1 -1
  24. package/dist/cmd/project/template-flow.js +3 -3
  25. package/dist/cmd/project/template-flow.js.map +1 -1
  26. package/dist/types.d.ts +2 -2
  27. package/dist/utils/dependency-checker.d.ts.map +1 -1
  28. package/dist/utils/dependency-checker.js +0 -5
  29. package/dist/utils/dependency-checker.js.map +1 -1
  30. package/dist/version-check.js +2 -2
  31. package/dist/version-check.js.map +1 -1
  32. package/package.json +7 -6
  33. package/src/cmd/build/ast.ts +9 -11
  34. package/src/cmd/build/entry-generator.ts +7 -3
  35. package/src/cmd/build/vite/config-loader.ts +6 -3
  36. package/src/cmd/build/vite/index.ts +1 -1
  37. package/src/cmd/build/vite/vite-builder.ts +1 -1
  38. package/src/cmd/build/webanalytics-generator.ts +3 -27
  39. package/src/cmd/dev/index.ts +12 -0
  40. package/src/cmd/project/auth/shared.ts +2 -1
  41. package/src/cmd/project/template-flow.ts +3 -3
  42. package/src/utils/dependency-checker.ts +0 -6
  43. package/src/version-check.ts +2 -2
@@ -47,7 +47,8 @@ export async function generateEntryFile(options: GenerateEntryOptions): Promise<
47
47
  const hasWebFrontend =
48
48
  (await Bun.file(join(srcDir, 'web', 'index.html')).exists()) ||
49
49
  (await Bun.file(join(srcDir, 'web', 'frontend.tsx')).exists());
50
- const hasWorkbench = !!workbench;
50
+ // Workbench is configured at build time, but only enabled at runtime in dev mode
51
+ const hasWorkbenchConfig = !!workbench;
51
52
 
52
53
  // Get unique route files that need to be imported (relative to src/)
53
54
  const routeFiles = new Set<string>();
@@ -137,9 +138,12 @@ ${routeImportsAndMounts.join('\n')}
137
138
  `
138
139
  : '';
139
140
 
140
- // Workbench API routes mounting (if enabled)
141
+ // Workbench API routes mounting (if configured)
142
+ // hasWorkbenchConfig is build-time (from agentuity.config.ts)
143
+ // hasWorkbench combines config + runtime dev mode check
141
144
  const workbenchApiMount = `
142
- const hasWorkbench = ${hasWorkbench};
145
+ const hasWorkbenchConfig = ${hasWorkbenchConfig};
146
+ const hasWorkbench = isDevelopment() && hasWorkbenchConfig;
143
147
  if (hasWorkbench) {
144
148
  // Mount workbench API routes (/_agentuity/workbench/*)
145
149
  const workbenchRouter = createWorkbenchRouter();
@@ -40,7 +40,8 @@ export async function loadAgentuityConfig(
40
40
 
41
41
  /**
42
42
  * Get workbench configuration with defaults
43
- * NOTE: Workbench is only available in dev mode
43
+ * NOTE: Workbench is only enabled at runtime in dev mode, but we need to know
44
+ * if it's configured at build time so we can generate the correct code.
44
45
  *
45
46
  * Presence of workbench config implicitly enables it (no explicit 'enabled' flag needed)
46
47
  * Missing workbench config implicitly disables it
@@ -49,20 +50,22 @@ export function getWorkbenchConfig(
49
50
  config: AgentuityConfig | null,
50
51
  dev: boolean
51
52
  ): {
53
+ configured: boolean;
52
54
  enabled: boolean;
53
55
  route: string;
54
56
  headers: Record<string, string>;
55
57
  } {
56
- const hasWorkbenchConfig = config?.workbench !== undefined;
58
+ const configured = config?.workbench !== undefined;
57
59
 
58
60
  // Workbench is enabled if:
59
61
  // 1. In dev mode (never in production)
60
62
  // 2. Config has a workbench object (presence implies enablement)
61
- const enabled = dev && hasWorkbenchConfig;
63
+ const enabled = dev && configured;
62
64
 
63
65
  const workbench = config?.workbench || {};
64
66
 
65
67
  return {
68
+ configured,
66
69
  enabled,
67
70
  route: workbench.route ?? '/workbench',
68
71
  headers: workbench.headers ?? {},
@@ -103,7 +103,7 @@ export function agentuityPlugin(options: AgentuityPluginOptions): Plugin {
103
103
  deploymentId,
104
104
  logger,
105
105
  mode: dev ? 'dev' : 'prod',
106
- workbench: workbenchConfig.enabled ? workbenchConfig : undefined,
106
+ workbench: workbenchConfig.configured ? workbenchConfig : undefined,
107
107
  analytics: config?.analytics,
108
108
  });
109
109
 
@@ -102,7 +102,7 @@ export async function runViteBuild(options: ViteBuildOptions): Promise<void> {
102
102
  deploymentId: deploymentId || '',
103
103
  logger,
104
104
  mode: dev ? 'dev' : 'prod',
105
- workbench: workbenchConfig.enabled ? workbenchConfig : undefined,
105
+ workbench: workbenchConfig.configured ? workbenchConfig : undefined,
106
106
  analytics: config?.analytics,
107
107
  });
108
108
 
@@ -102,6 +102,7 @@ function getEnabledAnalyticsCode(): string {
102
102
 
103
103
  import type { Context } from 'hono';
104
104
  import {
105
+ BEACON_SCRIPT,
105
106
  createRouter,
106
107
  createWebSessionMiddleware,
107
108
  getOrganizationId,
@@ -131,8 +132,8 @@ export function injectAnalytics(html: string, analyticsConfig: AnalyticsConfig):
131
132
  const configScript = \`<script>window.__AGENTUITY_ANALYTICS__=\${JSON.stringify(pageConfig)};</script>\`;
132
133
  // Session script sets cookies and window.__AGENTUITY_SESSION__ (dynamic, not cached)
133
134
  const sessionScript = '<script src="/_agentuity/webanalytics/session.js" async></script>';
134
- // Beacon script reads from __AGENTUITY_SESSION__ and sends events (static, cached)
135
- const beaconScript = '<script src="/_agentuity/webanalytics/analytics.js" async></script>';
135
+ // Beacon script - must be sync (not async/defer) to patch history API before the router loads
136
+ const beaconScript = '<script src="/_agentuity/webanalytics/analytics.js"></script>';
136
137
  const injection = configScript + sessionScript + beaconScript;
137
138
 
138
139
  // Inject before </head> or at start of <body>
@@ -145,31 +146,6 @@ export function injectAnalytics(html: string, analyticsConfig: AnalyticsConfig):
145
146
  return injection + html;
146
147
  }
147
148
 
148
- // The beacon script - minified for production
149
- export const BEACON_SCRIPT = \`(function(){
150
- var w=window,d=document,c=w.__AGENTUITY_ANALYTICS__;
151
- if(!c||!c.enabled)return;
152
- var q=[],t=null,sr=false,E='/_agentuity/webanalytics/collect',geo=null;
153
- function id(){return crypto.randomUUID?crypto.randomUUID():Date.now()+'-'+Math.random().toString(36).substr(2,9)}
154
- function base(type){var e={id:id(),timestamp:Date.now(),timezone_offset:new Date().getTimezoneOffset(),event_type:type,url:location.href,path:location.pathname,referrer:d.referrer||'',title:d.title||'',screen_width:screen.width||0,screen_height:screen.height||0,viewport_width:innerWidth||0,viewport_height:innerHeight||0,device_pixel_ratio:devicePixelRatio||1,user_agent:navigator.userAgent||'',language:navigator.language||''};if(geo){e.country=geo.country||'';e.region=geo.region||'';e.city=geo.city||'';e.timezone=geo.timezone||''}return e}
155
- fetch('https://agentuity.sh/location').then(function(r){return r.json()}).then(function(g){geo=g;try{sessionStorage.setItem('agentuity_geo',JSON.stringify(g))}catch(e){}}).catch(function(){try{var cached=sessionStorage.getItem('agentuity_geo');if(cached)geo=JSON.parse(cached)}catch(e){}});try{var cached=sessionStorage.getItem('agentuity_geo');if(cached)geo=JSON.parse(cached)}catch(e){}
156
- function getSession(){return w.__AGENTUITY_SESSION__}
157
- function waitForSession(cb){var s=getSession();if(s){cb(s);return}var attempts=0,maxAttempts=50;var iv=setInterval(function(){s=getSession();if(s||++attempts>=maxAttempts){clearInterval(iv);cb(s)}},100)}
158
- function doFlush(s){if(!q.length)return;var events=q.splice(0);if(c.isDevmode){console.debug('[Agentuity Analytics]',events);return}var sid=s?s.sessionId:'',tid=s?s.threadId:'';var p={org_id:c.orgId,project_id:c.projectId,session_id:sid,thread_id:tid,visitor_id:localStorage.getItem('agentuity_vid')||'vid_'+id(),events:events};try{localStorage.setItem('agentuity_vid',p.visitor_id)}catch(e){}navigator.sendBeacon?navigator.sendBeacon(E,JSON.stringify(p)):fetch(E,{method:'POST',body:JSON.stringify(p),keepalive:true}).catch(function(){})}
159
- function flush(){if(sr){doFlush(getSession())}else{waitForSession(function(s){sr=true;doFlush(s)})}}
160
- function queue(e){if(c.sampleRate<1&&Math.random()>c.sampleRate)return;q.push(e);q.length>=10?flush():t||(t=setTimeout(function(){t=null;flush()},5000))}
161
- function pv(){var e=base('pageview');if(performance.getEntriesByType){var n=performance.getEntriesByType('navigation')[0];if(n){e.load_time=Math.round(n.loadEventEnd-n.startTime);e.dom_ready=Math.round(n.domContentLoadedEventEnd-n.startTime);e.ttfb=Math.round(n.responseStart-n.requestStart)}}queue(e)}
162
- w.addEventListener('visibilitychange',function(){d.visibilityState==='hidden'&&flush()});
163
- w.addEventListener('pagehide',flush);
164
- if(c.trackSPANavigation){var op=history.pushState,or=history.replaceState,cp=location.pathname;function ch(){var np=location.pathname;np!==cp&&(cp=np,pv())}history.pushState=function(){op.apply(this,arguments);ch()};history.replaceState=function(){or.apply(this,arguments);ch()};w.addEventListener('popstate',ch)}
165
- if(c.trackErrors){w.addEventListener('error',function(e){var ev=base('error');ev.event_name='js_error';ev.event_data=JSON.stringify({message:e.message||'Unknown',filename:e.filename||'',lineno:e.lineno||0});queue(ev)});w.addEventListener('unhandledrejection',function(e){var ev=base('error');ev.event_name='unhandled_rejection';ev.event_data=JSON.stringify({message:e.reason instanceof Error?e.reason.message:String(e.reason)});queue(ev)})}
166
- if(c.trackClicks){d.addEventListener('click',function(e){var t=e.target;if(!t)return;var a=t.closest('[data-analytics]');if(!a)return;var ev=base('click');ev.event_name=a.getAttribute('data-analytics');queue(ev)},true)}
167
- if(c.trackScroll){var ms=new Set(),mx=0;function gs(){var st=w.scrollY||d.documentElement.scrollTop,sh=d.documentElement.scrollHeight-d.documentElement.clientHeight;return sh<=0?100:Math.min(100,Math.round(st/sh*100))}w.addEventListener('scroll',function(){var dp=gs();if(dp>mx)mx=dp;[25,50,75,100].forEach(function(m){if(dp>=m&&!ms.has(m)){ms.add(m);var ev=base('scroll');ev.event_name='scroll_'+m;ev.scroll_depth=m;queue(ev)}})},{passive:true})}
168
- if(c.trackWebVitals!==false&&typeof PerformanceObserver!=='undefined'){var wvLcp=0,wvCls=0,wvInp=0,wvPath=location.pathname,wvSent={};function wvReset(){wvLcp=0;wvCls=0;wvInp=0;wvSent={}}function wvSend(){var p=wvPath;if(wvLcp>0&&!wvSent.lcp){wvSent.lcp=1;var ev=base('web_vital');ev.event_name='lcp';ev.lcp=Math.round(wvLcp);ev.path=p;queue(ev)}if(!wvSent.cls){wvSent.cls=1;var ev=base('web_vital');ev.event_name='cls';ev.cls=Math.round(wvCls*1000)/1000;ev.path=p;queue(ev)}if(wvInp>0&&!wvSent.inp){wvSent.inp=1;var ev=base('web_vital');ev.event_name='inp';ev.inp=Math.round(wvInp);ev.path=p;queue(ev)}flush()}try{var fcpObs=new PerformanceObserver(function(l){l.getEntries().forEach(function(e){if(e.name==='first-contentful-paint'){var ev=base('web_vital');ev.event_name='fcp';ev.fcp=Math.round(e.startTime);queue(ev);flush();fcpObs.disconnect()}})});fcpObs.observe({type:'paint',buffered:true})}catch(e){}try{new PerformanceObserver(function(l){var entries=l.getEntries();if(entries.length)wvLcp=entries[entries.length-1].startTime}).observe({type:'largest-contentful-paint',buffered:true})}catch(e){}try{new PerformanceObserver(function(l){l.getEntries().forEach(function(e){if(!e.hadRecentInput&&e.value)wvCls+=e.value})}).observe({type:'layout-shift',buffered:true})}catch(e){}try{new PerformanceObserver(function(l){l.getEntries().forEach(function(e){if(e.duration&&e.duration>wvInp)wvInp=e.duration})}).observe({type:'event',buffered:true})}catch(e){}d.addEventListener('visibilitychange',function(){if(d.visibilityState==='hidden')wvSend()});w.addEventListener('pagehide',wvSend);if(c.trackSPANavigation){var wvOp=history.pushState,wvOr=history.replaceState;function wvNav(){var np=location.pathname;if(np!==wvPath){wvSend();wvPath=np;wvReset()}}history.pushState=function(){wvOp.apply(this,arguments);wvNav()};history.replaceState=function(){wvOr.apply(this,arguments);wvNav()};w.addEventListener('popstate',wvNav)}}
169
- d.readyState==='complete'?pv():w.addEventListener('load',pv);
170
- w.agentuityAnalytics={track:function(n,p){var e=base('custom');e.event_name=n;if(p)e.event_data=JSON.stringify(p);queue(e)},flush:flush};
171
- })()\`;
172
-
173
149
  // Serve analytics routes
174
150
  export function registerAnalyticsRoutes(app: ReturnType<typeof createRouter>): void {
175
151
  // Dynamic thread config script - sets cookie and returns thread ID
@@ -18,6 +18,8 @@ import { typecheck } from '../build/typecheck';
18
18
  import { createFileWatcher } from './file-watcher';
19
19
  import { regenerateSkillsAsync } from './skills';
20
20
  import { prepareDevLock, releaseLockSync } from './dev-lock';
21
+ import { checkAndUpgradeDependencies } from '../../utils/dependency-checker';
22
+ import { ErrorCode } from '../../errors';
21
23
 
22
24
  const DEFAULT_PORT = 3500;
23
25
  const MIN_PORT = 1024;
@@ -214,6 +216,16 @@ export const command = createCommand({
214
216
  // This is a fallback for cases where the lockfile was corrupted
215
217
  await killLingeringGravityProcesses(logger);
216
218
 
219
+ // Check and upgrade @agentuity/* dependencies if needed
220
+ const upgradeResult = await checkAndUpgradeDependencies(rootDir, logger);
221
+ if (upgradeResult.failed.length > 0) {
222
+ devLock.release();
223
+ tui.fatal(
224
+ `Failed to upgrade dependencies: ${upgradeResult.failed.join(', ')}`,
225
+ ErrorCode.BUILD_FAILED
226
+ );
227
+ }
228
+
217
229
  try {
218
230
  // Setup devmode and gravity (if using public URL)
219
231
  const useMockService = process.env.DEVMODE_SYNC_SERVICE_MOCK === 'true';
@@ -122,7 +122,8 @@ export async function selectOrCreateDatabase(options: {
122
122
  export const AUTH_DEPENDENCIES = {
123
123
  '@agentuity/auth': 'latest',
124
124
  'better-auth': '^1.4.9',
125
- 'drizzle-orm': '^0.44.0',
125
+ 'drizzle-orm': '^0.45.0',
126
+ 'drizzle-kit': '^0.31.0',
126
127
  } as const;
127
128
 
128
129
  /**
@@ -196,7 +196,7 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<void> {
196
196
  return;
197
197
  }
198
198
  selectedTemplate = found;
199
- } else if (skipPrompts) {
199
+ } else if (skipPrompts || templates.length === 1) {
200
200
  selectedTemplate = templates[0];
201
201
  } else {
202
202
  let maxLength = 15;
@@ -246,8 +246,8 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<void> {
246
246
  logger,
247
247
  });
248
248
 
249
- // Re-display template selection after spinners clear it
250
- if (!skipPrompts) {
249
+ // Re-display template selection after spinners clear it (only if user actually selected)
250
+ if (!skipPrompts && templates.length > 1) {
251
251
  const { symbols, tuiColors } = tui;
252
252
  console.log(`${tuiColors.completed(symbols.completed)} Select a template:`);
253
253
  console.log(`${tuiColors.secondary(symbols.bar)} ${tuiColors.muted(selectedTemplate.name)}`);
@@ -57,12 +57,6 @@ export async function checkAndUpgradeDependencies(
57
57
  failed: [],
58
58
  };
59
59
 
60
- // Skip in CI/non-interactive environments
61
- if (!process.stdin.isTTY) {
62
- logger.debug('Skipping dependency check in non-interactive environment');
63
- return result;
64
- }
65
-
66
60
  const packageJsonPath = join(projectDir, 'package.json');
67
61
  const cliVersion = getVersion();
68
62
 
@@ -139,10 +139,10 @@ async function updateCheckTimestamp(config: Config | null, logger: Logger): Prom
139
139
  */
140
140
  async function performUpgrade(logger: Logger): Promise<void> {
141
141
  try {
142
- // Run upgrade command (it will validate, download, install, etc.)
142
+ // Run upgrade command with --force since user already confirmed via prompt
143
143
  // Use process.execPath to get the actual binary path (not Bun.main which is virtual)
144
144
  logger.info('Starting upgrade...');
145
- await $`${process.execPath} upgrade`.quiet();
145
+ await $`${process.execPath} upgrade --force`.quiet();
146
146
 
147
147
  // If we got here, the upgrade succeeded
148
148
  // Re-run the original command with the new binary