@agentuity/cli 0.0.78 → 0.0.80

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 (42) hide show
  1. package/dist/cmd/build/ast.d.ts +2 -2
  2. package/dist/cmd/build/ast.d.ts.map +1 -1
  3. package/dist/cmd/build/ast.js +229 -24
  4. package/dist/cmd/build/ast.js.map +1 -1
  5. package/dist/cmd/build/bundler.d.ts +3 -1
  6. package/dist/cmd/build/bundler.d.ts.map +1 -1
  7. package/dist/cmd/build/bundler.js +18 -17
  8. package/dist/cmd/build/bundler.js.map +1 -1
  9. package/dist/cmd/build/index.d.ts.map +1 -1
  10. package/dist/cmd/build/index.js +5 -2
  11. package/dist/cmd/build/index.js.map +1 -1
  12. package/dist/cmd/build/plugin.d.ts.map +1 -1
  13. package/dist/cmd/build/plugin.js +29 -31
  14. package/dist/cmd/build/plugin.js.map +1 -1
  15. package/dist/cmd/build/{workbench-templates.d.ts → workbench.d.ts} +3 -1
  16. package/dist/cmd/build/workbench.d.ts.map +1 -0
  17. package/dist/cmd/build/{workbench-templates.js → workbench.js} +13 -1
  18. package/dist/cmd/build/workbench.js.map +1 -0
  19. package/dist/cmd/cloud/deploy.d.ts.map +1 -1
  20. package/dist/cmd/cloud/deploy.js +0 -1
  21. package/dist/cmd/cloud/deploy.js.map +1 -1
  22. package/dist/cmd/dev/index.d.ts.map +1 -1
  23. package/dist/cmd/dev/index.js +11 -2
  24. package/dist/cmd/dev/index.js.map +1 -1
  25. package/dist/cmd/project/template-flow.d.ts.map +1 -1
  26. package/dist/cmd/project/template-flow.js +13 -2
  27. package/dist/cmd/project/template-flow.js.map +1 -1
  28. package/dist/sound.d.ts.map +1 -1
  29. package/dist/sound.js +1 -16
  30. package/dist/sound.js.map +1 -1
  31. package/package.json +5 -4
  32. package/src/cmd/build/ast.ts +322 -38
  33. package/src/cmd/build/bundler.ts +20 -17
  34. package/src/cmd/build/index.ts +5 -2
  35. package/src/cmd/build/plugin.ts +45 -41
  36. package/src/cmd/build/{workbench-templates.ts → workbench.ts} +13 -0
  37. package/src/cmd/cloud/deploy.ts +0 -1
  38. package/src/cmd/dev/index.ts +13 -2
  39. package/src/cmd/project/template-flow.ts +14 -2
  40. package/src/sound.ts +1 -17
  41. package/dist/cmd/build/workbench-templates.d.ts.map +0 -1
  42. package/dist/cmd/build/workbench-templates.js.map +0 -1
@@ -1,5 +1,5 @@
1
1
  import * as acornLoose from 'acorn-loose';
2
- import { dirname, relative } from 'node:path';
2
+ import { dirname, relative, join, basename } from 'node:path';
3
3
  import { parse as parseCronExpression } from '@datasert/cronjs-parser';
4
4
  import { generate } from 'astring';
5
5
  import type { BuildMetadata } from '../../types';
@@ -7,7 +7,7 @@ import { createLogger } from '@agentuity/server';
7
7
  import * as ts from 'typescript';
8
8
  import { StructuredError, type WorkbenchConfig } from '@agentuity/core';
9
9
  import type { LogLevel } from '../../types';
10
- import { join } from 'node:path';
10
+
11
11
  import { existsSync, mkdirSync } from 'node:fs';
12
12
  import JSON5 from 'json5';
13
13
  import { formatSchemaCode } from './format-schema';
@@ -152,7 +152,7 @@ function getEvalId(
152
152
  name: string,
153
153
  version: string
154
154
  ): string {
155
- return `eval_${hashSHA1(projectId, deploymentId, filename, name, version)}`;
155
+ return `evalid_${hashSHA1(projectId, deploymentId, filename, name, version)}`;
156
156
  }
157
157
 
158
158
  function generateRouteId(
@@ -172,7 +172,7 @@ function generateStableAgentId(projectId: string, name: string): string {
172
172
  }
173
173
 
174
174
  function generateStableEvalId(projectId: string, agentId: string, name: string): string {
175
- return `evalid_${hashSHA1(projectId, agentId, name)}`.substring(0, 64);
175
+ return `eval_${hashSHA1(projectId, agentId, name)}`.substring(0, 64);
176
176
  }
177
177
 
178
178
  /**
@@ -328,24 +328,135 @@ function createAgentMetadataNode(
328
328
 
329
329
  const DuplicateNameError = StructuredError('DuplicateNameError')<{ filename: string }>();
330
330
 
331
- export function parseEvalMetadata(
331
+ function injectEvalMetadata(
332
+ configObj: ASTObjectExpression,
333
+ evalId: string,
334
+ stableEvalId: string,
335
+ version: string,
336
+ filename: string,
337
+ agentId?: string
338
+ ): void {
339
+ // Create metadata object with eval IDs and version
340
+ const properties = [
341
+ createObjectPropertyNode('id', evalId),
342
+ createObjectPropertyNode('evalId', stableEvalId),
343
+ createObjectPropertyNode('version', version),
344
+ createObjectPropertyNode('filename', filename),
345
+ ];
346
+
347
+ // Add agentId if available
348
+ if (agentId) {
349
+ properties.push(createObjectPropertyNode('agentId', agentId));
350
+ }
351
+
352
+ const metadataObj: ASTPropertyNode = {
353
+ type: 'Property',
354
+ kind: 'init',
355
+ key: {
356
+ type: 'Identifier',
357
+ name: 'metadata',
358
+ },
359
+ value: {
360
+ type: 'ObjectExpression',
361
+ properties,
362
+ } as ASTObjectExpression,
363
+ };
364
+
365
+ // Add metadata to the config object
366
+ configObj.properties.push(metadataObj);
367
+ }
368
+
369
+ function findAgentVariableAndImport(
370
+ ast: ASTProgram
371
+ ): { varName: string; importPath: string } | undefined {
372
+ // First, find what variable is being used in agent.createEval() calls
373
+ let agentVarName: string | undefined;
374
+
375
+ for (const node of ast.body) {
376
+ if (node.type === 'ExportNamedDeclaration') {
377
+ const exportDecl = node as {
378
+ declaration?: { type: string; declarations?: Array<ASTVariableDeclarator> };
379
+ };
380
+ if (exportDecl.declaration?.type === 'VariableDeclaration') {
381
+ const variableDeclaration = exportDecl.declaration as {
382
+ declarations: Array<ASTVariableDeclarator>;
383
+ };
384
+
385
+ for (const vardecl of variableDeclaration.declarations) {
386
+ if (
387
+ vardecl.type === 'VariableDeclarator' &&
388
+ vardecl.init?.type === 'CallExpression'
389
+ ) {
390
+ const call = vardecl.init as ASTCallExpression;
391
+ if (call.callee.type === 'MemberExpression') {
392
+ const memberExpr = call.callee as ASTMemberExpression;
393
+ const object = memberExpr.object as ASTNodeIdentifier;
394
+ const property = memberExpr.property as ASTNodeIdentifier;
395
+ if (
396
+ object.type === 'Identifier' &&
397
+ property.type === 'Identifier' &&
398
+ property.name === 'createEval'
399
+ ) {
400
+ agentVarName = object.name;
401
+ break;
402
+ }
403
+ }
404
+ }
405
+ }
406
+ if (agentVarName) break;
407
+ }
408
+ }
409
+ }
410
+
411
+ if (!agentVarName) return undefined;
412
+
413
+ // Now find the import for this variable
414
+ for (const node of ast.body) {
415
+ if (node.type === 'ImportDeclaration') {
416
+ const importDecl = node as unknown as {
417
+ source: ASTLiteral;
418
+ specifiers: Array<{
419
+ type: string;
420
+ local: ASTNodeIdentifier;
421
+ }>;
422
+ };
423
+
424
+ // Find default import specifier that matches our variable
425
+ for (const spec of importDecl.specifiers) {
426
+ if (spec.type === 'ImportDefaultSpecifier' && spec.local.name === agentVarName) {
427
+ const importPath = importDecl.source.value;
428
+ if (typeof importPath === 'string') {
429
+ return { varName: agentVarName, importPath };
430
+ }
431
+ }
432
+ }
433
+ }
434
+ }
435
+
436
+ return undefined;
437
+ }
438
+
439
+ export async function parseEvalMetadata(
332
440
  rootDir: string,
333
441
  filename: string,
334
442
  contents: string,
335
443
  projectId: string,
336
444
  deploymentId: string,
337
- agentId?: string
338
- ): [
339
- string,
340
- Array<{
341
- filename: string;
342
- id: string;
343
- version: string;
344
- name: string;
345
- evalId: string;
346
- description?: string;
347
- }>,
348
- ] {
445
+ agentId?: string,
446
+ agentMetadata?: Map<string, Map<string, string>>
447
+ ): Promise<
448
+ [
449
+ string,
450
+ Array<{
451
+ filename: string;
452
+ id: string;
453
+ version: string;
454
+ name: string;
455
+ evalId: string;
456
+ description?: string;
457
+ }>,
458
+ ]
459
+ > {
349
460
  const logLevel = (process.env.AGENTUITY_LOG_LEVEL || 'info') as
350
461
  | 'trace'
351
462
  | 'debug'
@@ -370,6 +481,47 @@ export function parseEvalMetadata(
370
481
  description?: string;
371
482
  }> = [];
372
483
 
484
+ // Try to find the corresponding agent to get the agentId
485
+ let resolvedAgentId = agentId;
486
+ if (!resolvedAgentId && agentMetadata) {
487
+ const agentInfo = findAgentVariableAndImport(ast);
488
+ if (agentInfo) {
489
+ logger.trace(
490
+ `[EVAL METADATA] Found agent variable '${agentInfo.varName}' imported from '${agentInfo.importPath}'`
491
+ );
492
+
493
+ // Resolve the import path to actual file path
494
+ let resolvedPath = agentInfo.importPath;
495
+ if (resolvedPath.startsWith('./') || resolvedPath.startsWith('../')) {
496
+ // Convert relative path to match the format in agentMetadata
497
+ const baseDir = dirname(filename);
498
+ resolvedPath = join(baseDir, resolvedPath);
499
+ // Normalize and ensure .ts extension
500
+ if (!resolvedPath.endsWith('.ts')) {
501
+ resolvedPath += '.ts';
502
+ }
503
+ }
504
+
505
+ // Find the agent metadata from the passed agentMetadata map
506
+ for (const [agentFile, metadata] of agentMetadata) {
507
+ // Check if this agent file matches the resolved import path
508
+ if (agentFile.includes(basename(resolvedPath)) && metadata.has('agentId')) {
509
+ resolvedAgentId = metadata.get('agentId');
510
+ logger.trace(
511
+ `[EVAL METADATA] Resolved agentId from agent metadata: ${resolvedAgentId} (file: ${agentFile})`
512
+ );
513
+ break;
514
+ }
515
+ }
516
+
517
+ if (!resolvedAgentId) {
518
+ logger.warn(
519
+ `[EVAL METADATA] Could not find agent metadata for import path: ${resolvedPath}`
520
+ );
521
+ }
522
+ }
523
+ }
524
+
373
525
  // Find all exported agent.createEval() calls
374
526
  for (const body of ast.body) {
375
527
  let variableDeclaration: { declarations: Array<ASTVariableDeclarator> } | undefined;
@@ -451,16 +603,25 @@ export function parseEvalMetadata(
451
603
  );
452
604
  const evalId = getEvalId(projectId, deploymentId, rel, finalName, version);
453
605
 
454
- // Generate stable evalId
455
- const effectiveAgentId = agentId || '';
606
+ // Generate stable evalId using resolved agentId
607
+ const effectiveAgentId = resolvedAgentId || '';
456
608
  const stableEvalId = generateStableEvalId(
457
609
  projectId,
458
610
  effectiveAgentId,
459
611
  finalName
460
612
  );
461
613
 
462
- // Note: We no longer inject metadata into the AST since there's no metadata object
463
- // The runtime will generate IDs from the name parameter
614
+ // Inject eval metadata into the AST (same pattern as agents)
615
+ if (configObj) {
616
+ injectEvalMetadata(
617
+ configObj,
618
+ evalId,
619
+ stableEvalId,
620
+ version,
621
+ rel,
622
+ resolvedAgentId
623
+ );
624
+ }
464
625
 
465
626
  evals.push({
466
627
  filename: rel,
@@ -740,13 +901,14 @@ export async function parseAgentMetadata(
740
901
  const transpiler = new Bun.Transpiler({ loader: 'ts', target: 'bun' });
741
902
  const evalsContents = transpiler.transformSync(evalsSource);
742
903
  const agentId = result[1].get('agentId') || '';
743
- const [, evals] = parseEvalMetadata(
904
+ const [, evals] = await parseEvalMetadata(
744
905
  rootDir,
745
906
  evalsPath,
746
907
  evalsContents,
747
908
  projectId,
748
909
  deploymentId,
749
- agentId
910
+ agentId,
911
+ new Map() // Empty map since we already have agentId
750
912
  );
751
913
  if (evals.length > 0) {
752
914
  logger.trace(`Adding ${evals.length} eval(s) to agent metadata for ${name}`);
@@ -1777,11 +1939,17 @@ export * from '${runtimeImportPath}/src/index';
1777
1939
  */
1778
1940
  export function analyzeWorkbench(content: string): WorkbenchAnalysis {
1779
1941
  try {
1942
+ if (!content.includes('@agentuity/workbench')) {
1943
+ return {
1944
+ hasWorkbench: false,
1945
+ config: null,
1946
+ };
1947
+ }
1780
1948
  const sourceFile = ts.createSourceFile('app.ts', content, ts.ScriptTarget.Latest, true);
1781
1949
 
1782
1950
  let hasImport = false;
1783
- let hasUsage = false;
1784
- let config: WorkbenchConfig | null = null;
1951
+ const workbenchVariables = new Map<string, WorkbenchConfig>();
1952
+ let usedInServices = false;
1785
1953
 
1786
1954
  function visitNode(node: ts.Node): void {
1787
1955
  // Check for import declarations with createWorkbench
@@ -1795,18 +1963,55 @@ export function analyzeWorkbench(content: string): WorkbenchAnalysis {
1795
1963
  }
1796
1964
  }
1797
1965
 
1798
- // Check for createWorkbench function calls and extract config
1799
- if (ts.isCallExpression(node) && ts.isIdentifier(node.expression)) {
1800
- if (node.expression.text === 'createWorkbench') {
1801
- hasUsage = true;
1802
-
1966
+ // Track variables assigned from createWorkbench() calls
1967
+ if (
1968
+ ts.isVariableDeclaration(node) &&
1969
+ node.initializer &&
1970
+ ts.isCallExpression(node.initializer) &&
1971
+ ts.isIdentifier(node.initializer.expression) &&
1972
+ node.initializer.expression.text === 'createWorkbench'
1973
+ ) {
1974
+ // Extract variable name
1975
+ if (ts.isIdentifier(node.name)) {
1803
1976
  // Extract configuration from the first argument (if any)
1804
- if (node.arguments.length > 0) {
1805
- const configArg = node.arguments[0];
1806
- config = parseConfigObject(configArg);
1977
+ let varConfig: WorkbenchConfig;
1978
+ if (node.initializer.arguments.length > 0) {
1979
+ const configArg = node.initializer.arguments[0];
1980
+ varConfig = parseConfigObject(configArg) || { route: '/workbench' };
1807
1981
  } else {
1808
1982
  // Default config if no arguments provided
1809
- config = { route: '/workbench' };
1983
+ varConfig = { route: '/workbench' };
1984
+ }
1985
+ workbenchVariables.set(node.name.text, varConfig);
1986
+ }
1987
+ }
1988
+
1989
+ // Check if workbench variable is used in createApp's services config
1990
+ if (
1991
+ ts.isCallExpression(node) &&
1992
+ ts.isIdentifier(node.expression) &&
1993
+ node.expression.text === 'createApp' &&
1994
+ node.arguments.length > 0
1995
+ ) {
1996
+ const configArg = node.arguments[0];
1997
+ if (ts.isObjectLiteralExpression(configArg)) {
1998
+ // Find the services property
1999
+ for (const prop of configArg.properties) {
2000
+ if (
2001
+ ts.isPropertyAssignment(prop) &&
2002
+ ts.isIdentifier(prop.name) &&
2003
+ prop.name.text === 'services'
2004
+ ) {
2005
+ // Check if any workbench variable is referenced in services
2006
+ const foundVariableName = checkForWorkbenchUsage(
2007
+ prop.initializer,
2008
+ workbenchVariables
2009
+ );
2010
+ if (foundVariableName) {
2011
+ usedInServices = true;
2012
+ }
2013
+ break;
2014
+ }
1810
2015
  }
1811
2016
  }
1812
2017
  }
@@ -1815,15 +2020,94 @@ export function analyzeWorkbench(content: string): WorkbenchAnalysis {
1815
2020
  ts.forEachChild(node, visitNode);
1816
2021
  }
1817
2022
 
2023
+ // Helper function to check if workbench variable is used in services config
2024
+ // Returns the variable name if found, otherwise null
2025
+ function checkForWorkbenchUsage(
2026
+ node: ts.Node,
2027
+ variables: Map<string, WorkbenchConfig>
2028
+ ): string | null {
2029
+ let foundVar: string | null = null;
2030
+
2031
+ function visit(n: ts.Node): void {
2032
+ if (foundVar) return; // Already found
2033
+
2034
+ // Check for identifier references
2035
+ if (ts.isIdentifier(n) && variables.has(n.text)) {
2036
+ foundVar = n.text;
2037
+ return;
2038
+ }
2039
+
2040
+ // Check for property shorthand: { workbench } in services
2041
+ if (ts.isShorthandPropertyAssignment(n) && variables.has(n.name.text)) {
2042
+ foundVar = n.name.text;
2043
+ return;
2044
+ }
2045
+
2046
+ // Check for property value: { workbench: workbench } in services
2047
+ if (
2048
+ ts.isPropertyAssignment(n) &&
2049
+ n.initializer &&
2050
+ ts.isIdentifier(n.initializer) &&
2051
+ variables.has(n.initializer.text)
2052
+ ) {
2053
+ foundVar = n.initializer.text;
2054
+ return;
2055
+ }
2056
+
2057
+ ts.forEachChild(n, visit);
2058
+ }
2059
+
2060
+ visit(node);
2061
+ return foundVar;
2062
+ }
2063
+
1818
2064
  visitNode(sourceFile);
1819
2065
 
1820
- // Set default config if workbench is used but no config was parsed
1821
- if (hasImport && hasUsage && !config) {
1822
- config = { route: '/workbench', headers: {}, port: 3500 };
2066
+ // Get the config from the first used workbench variable
2067
+ let config: WorkbenchConfig | null = null;
2068
+ if (hasImport && usedInServices) {
2069
+ // Re-check which variable was used
2070
+ const ast = sourceFile;
2071
+ for (const [varName, varConfig] of workbenchVariables.entries()) {
2072
+ // Simple check: walk through and find if this variable is used in services
2073
+ let used = false;
2074
+ function checkUsage(node: ts.Node): void {
2075
+ if (
2076
+ ts.isCallExpression(node) &&
2077
+ ts.isIdentifier(node.expression) &&
2078
+ node.expression.text === 'createApp' &&
2079
+ node.arguments.length > 0
2080
+ ) {
2081
+ const configArg = node.arguments[0];
2082
+ if (ts.isObjectLiteralExpression(configArg)) {
2083
+ for (const prop of configArg.properties) {
2084
+ if (
2085
+ ts.isPropertyAssignment(prop) &&
2086
+ ts.isIdentifier(prop.name) &&
2087
+ prop.name.text === 'services'
2088
+ ) {
2089
+ const foundVar = checkForWorkbenchUsage(
2090
+ prop.initializer,
2091
+ workbenchVariables
2092
+ );
2093
+ if (foundVar === varName) {
2094
+ used = true;
2095
+ config = varConfig;
2096
+ }
2097
+ break;
2098
+ }
2099
+ }
2100
+ }
2101
+ }
2102
+ ts.forEachChild(node, checkUsage);
2103
+ }
2104
+ checkUsage(ast);
2105
+ if (used) break;
2106
+ }
1823
2107
  }
1824
2108
 
1825
2109
  return {
1826
- hasWorkbench: hasImport && hasUsage,
2110
+ hasWorkbench: hasImport && usedInServices,
1827
2111
  config: config,
1828
2112
  };
1829
2113
  } catch (error) {
@@ -11,8 +11,8 @@ import { getVersion } from '../../version';
11
11
  import type { Project } from '../../types';
12
12
  import { fixDuplicateExportsInDirectory } from './fix-duplicate-exports';
13
13
  import type { Logger } from '../../types';
14
- import { generateWorkbenchMainTsx, generateWorkbenchIndexHtml } from './workbench-templates';
15
- import { analyzeWorkbench } from './ast';
14
+ import { generateWorkbenchMainTsx, generateWorkbenchIndexHtml } from './workbench';
15
+ import { analyzeWorkbench, type WorkbenchAnalysis } from './ast';
16
16
  import { type DeployOptions } from '../../schemas/deploy';
17
17
 
18
18
  const minBunVersion = '>=1.3.3';
@@ -64,6 +64,7 @@ export interface BundleOptions extends DeployOptions {
64
64
  outDir?: string;
65
65
  region: string;
66
66
  logger: Logger;
67
+ workbench?: WorkbenchAnalysis;
67
68
  }
68
69
 
69
70
  type BuildResult = Awaited<ReturnType<typeof Bun.build>>;
@@ -116,6 +117,7 @@ export async function bundle({
116
117
  env,
117
118
  region,
118
119
  logger,
120
+ workbench,
119
121
  }: BundleOptions): Promise<{ output: string[] }> {
120
122
  const output: string[] = [];
121
123
 
@@ -305,10 +307,12 @@ export async function bundle({
305
307
  format: 'esm',
306
308
  banner: `// Generated file. DO NOT EDIT`,
307
309
  // Disable minify for server bundle (keep code readable for debugging)
308
- // Enable splitting to reduce bundle size by extracting common code
309
- minify: false,
310
+ minify: !dev,
310
311
  drop: isProd ? ['debugger'] : undefined,
311
- splitting: true,
312
+ // Disable splitting - causes module initialization issues with externalized packages
313
+ // The chunk helper functions (__commonJS, __esm, etc.) don't properly handle
314
+ // CommonJS packages in node_modules that require() other modules
315
+ splitting: false,
312
316
  conditions: [isProd ? 'production' : 'development', 'bun'],
313
317
  external,
314
318
  naming: {
@@ -322,9 +326,6 @@ export async function bundle({
322
326
  if (!buildResult.success) {
323
327
  handleBuildFailure(buildResult);
324
328
  }
325
- // Fix duplicate exports caused by Bun splitting bug
326
- // See: https://github.com/oven-sh/bun/issues/5344
327
- await fixDuplicateExportsInDirectory(outDir, false);
328
329
  })();
329
330
 
330
331
  const buildmetadata = getBuildMetadata();
@@ -468,13 +469,15 @@ export async function bundle({
468
469
 
469
470
  // Bundle workbench app if detected via setupWorkbench
470
471
  if (existsSync(appFile)) {
471
- const appContent = await Bun.file(appFile).text();
472
- const analysis = analyzeWorkbench(appContent);
472
+ if (!workbench) {
473
+ const appContent = await Bun.file(appFile).text();
474
+ workbench = analyzeWorkbench(appContent);
475
+ }
473
476
 
474
- if (analysis.hasWorkbench) {
477
+ if (workbench.hasWorkbench) {
475
478
  // Create workbench config with proper defaults
476
479
  const defaultConfig = { route: '/workbench', headers: {}, port: port || 3500 };
477
- const config = { ...defaultConfig, ...analysis.config };
480
+ const config = { ...defaultConfig, ...workbench.config };
478
481
  try {
479
482
  // Generate workbench files on the fly instead of using files from package
480
483
  const tempWorkbenchDir = join(outDir, 'temp-workbench');
@@ -486,19 +489,19 @@ export async function bundle({
486
489
  await Bun.write(workbenchIndexFile, generateWorkbenchIndexHtml());
487
490
 
488
491
  // Bundle workbench using generated files
489
- // NOTE: Don't set 'root' to tempWorkbenchDir because it breaks module resolution
490
- // Bun needs to resolve @agentuity/* packages from the project's node_modules
492
+ // Disable splitting to avoid CommonJS/ESM module resolution conflicts
491
493
  const workbenchBuildConfig: Bun.BuildConfig = {
492
494
  entrypoints: [workbenchIndexFile],
493
495
  outdir: join(outDir, 'workbench'),
494
496
  sourcemap: dev ? 'inline' : 'linked',
495
- plugins: [AgentuityBundler], // i dont think we need this plugin here
496
497
  target: 'browser',
497
498
  format: 'esm',
498
499
  banner: `// Generated file. DO NOT EDIT`,
499
- minify: !dev, // Disable minification in dev to avoid module resolution issues
500
- splitting: !dev, // Disable code splitting in dev to avoid relative import resolution issues
500
+ minify: !dev,
501
+ drop: isProd ? ['debugger'] : undefined,
502
+ splitting: false,
501
503
  packages: 'bundle',
504
+ conditions: ['browser', 'import', 'default'],
502
505
  naming: {
503
506
  entry: '[dir]/[name].[ext]',
504
507
  chunk: 'workbench/chunk/[name]-[hash].[ext]',
@@ -1,5 +1,5 @@
1
1
  import { z } from 'zod';
2
- import { resolve, join } from 'node:path';
2
+ import { resolve, join, relative } from 'node:path';
3
3
  import { getServiceUrls } from '@agentuity/server';
4
4
  import { createCommand } from '../../types';
5
5
  import { bundle } from './bundler';
@@ -47,7 +47,10 @@ export const command = createCommand({
47
47
  const outDir = opts.outdir ? resolve(opts.outdir) : join(absoluteProjectDir, '.agentuity');
48
48
 
49
49
  try {
50
- tui.info(`Bundling project at ${absoluteProjectDir} to ${outDir}`);
50
+ const rel = outDir.startsWith(absoluteProjectDir)
51
+ ? relative(absoluteProjectDir, outDir)
52
+ : outDir;
53
+ tui.info(`Bundling project at ${absoluteProjectDir} to ${rel}`);
51
54
 
52
55
  const env: Map<string, string> = new Map();
53
56
 
@@ -236,38 +236,55 @@ const AgentuityBundler: BunPlugin = {
236
236
  let newsource = await Bun.file(args.path).text();
237
237
  if (args.path.startsWith(srcDir)) {
238
238
  const contents = transpiler.transformSync(newsource);
239
- const result = await parseAgentMetadata(
240
- rootDir,
241
- args.path,
242
- contents,
243
- projectId,
244
- deploymentId
245
- );
246
239
 
247
- // Skip files that don't have a createAgent export
248
- if (result === undefined) {
249
- return {
250
- contents: newsource,
251
- loader: 'ts',
252
- };
253
- }
240
+ // Check if this is an eval file (eval.ts)
241
+ if (args.path.endsWith('/eval.ts')) {
242
+ // parseEvalMetadata will find the agent from the import statement
243
+ const [ns] = await parseEvalMetadata(
244
+ rootDir,
245
+ args.path,
246
+ contents,
247
+ projectId,
248
+ deploymentId,
249
+ undefined, // No agentId - will be resolved from import
250
+ agentMetadata
251
+ );
252
+ newsource = ns;
253
+ } else {
254
+ // Handle regular agent files
255
+ const result = await parseAgentMetadata(
256
+ rootDir,
257
+ args.path,
258
+ contents,
259
+ projectId,
260
+ deploymentId
261
+ );
262
+
263
+ // Skip files that don't have a createAgent export
264
+ if (result === undefined) {
265
+ return {
266
+ contents: newsource,
267
+ loader: 'ts',
268
+ };
269
+ }
254
270
 
255
- const [ns, md] = result;
256
- newsource = ns;
257
-
258
- // Only process files that actually export an agent
259
- if (md.has('name')) {
260
- const newAgentName = md.get('name');
261
- for (const [, kv] of agentMetadata) {
262
- const found = kv.get('name');
263
- if (newAgentName === found) {
264
- throw new AgentNameDuplicateError({
265
- message: `The agent in ${kv.get('filename')} and the agent in ${md.get('filename')} have the same name (${found}). Agent Names must be unique within a project.`,
266
- });
271
+ const [ns, md] = result;
272
+ newsource = ns;
273
+
274
+ // Only process files that actually export an agent
275
+ if (md.has('name')) {
276
+ const newAgentName = md.get('name');
277
+ for (const [, kv] of agentMetadata) {
278
+ const found = kv.get('name');
279
+ if (newAgentName === found) {
280
+ throw new AgentNameDuplicateError({
281
+ message: `The agent in ${kv.get('filename')} and the agent in ${md.get('filename')} have the same name (${found}). Agent Names must be unique within a project.`,
282
+ });
283
+ }
267
284
  }
268
- }
269
285
 
270
- agentMetadata.set(md.get('name')!, md);
286
+ agentMetadata.set(md.get('name')!, md);
287
+ }
271
288
  }
272
289
  }
273
290
  return {
@@ -276,19 +293,6 @@ const AgentuityBundler: BunPlugin = {
276
293
  };
277
294
  });
278
295
 
279
- build.onLoad({ filter: /\/eval\.ts$/, namespace: 'file' }, async (args) => {
280
- let newsource = await Bun.file(args.path).text();
281
- if (args.path.startsWith(srcDir)) {
282
- const contents = transpiler.transformSync(newsource);
283
- const [ns] = parseEvalMetadata(rootDir, args.path, contents, projectId, deploymentId);
284
- newsource = ns;
285
- }
286
- return {
287
- contents: newsource,
288
- loader: 'ts',
289
- };
290
- });
291
-
292
296
  const patches = generatePatches();
293
297
  for (const [, patch] of patches) {
294
298
  let modulePath = join('node_modules', patch.module, '.*');