@agentuity/cli 0.1.24 → 0.1.26

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 (64) hide show
  1. package/dist/cli.d.ts.map +1 -1
  2. package/dist/cli.js +1 -1
  3. package/dist/cli.js.map +1 -1
  4. package/dist/cmd/ai/cadence/index.d.ts.map +1 -1
  5. package/dist/cmd/ai/cadence/index.js +8 -2
  6. package/dist/cmd/ai/cadence/index.js.map +1 -1
  7. package/dist/cmd/ai/index.d.ts.map +1 -1
  8. package/dist/cmd/ai/index.js +8 -1
  9. package/dist/cmd/ai/index.js.map +1 -1
  10. package/dist/cmd/build/patch/index.d.ts.map +1 -1
  11. package/dist/cmd/build/patch/index.js +4 -0
  12. package/dist/cmd/build/patch/index.js.map +1 -1
  13. package/dist/cmd/build/patch/otel-llm.d.ts +10 -0
  14. package/dist/cmd/build/patch/otel-llm.d.ts.map +1 -0
  15. package/dist/cmd/build/patch/otel-llm.js +374 -0
  16. package/dist/cmd/build/patch/otel-llm.js.map +1 -0
  17. package/dist/cmd/cloud/db/create.js +3 -3
  18. package/dist/cmd/cloud/db/create.js.map +1 -1
  19. package/dist/cmd/cloud/deploy.d.ts.map +1 -1
  20. package/dist/cmd/cloud/deploy.js +55 -2
  21. package/dist/cmd/cloud/deploy.js.map +1 -1
  22. package/dist/cmd/cloud/env/pull.d.ts.map +1 -1
  23. package/dist/cmd/cloud/env/pull.js +26 -17
  24. package/dist/cmd/cloud/env/pull.js.map +1 -1
  25. package/dist/cmd/cloud/eval-run/list.d.ts.map +1 -1
  26. package/dist/cmd/cloud/eval-run/list.js +5 -1
  27. package/dist/cmd/cloud/eval-run/list.js.map +1 -1
  28. package/dist/cmd/cloud/queue/dlq.d.ts.map +1 -1
  29. package/dist/cmd/cloud/queue/dlq.js.map +1 -1
  30. package/dist/cmd/cloud/sandbox/download.d.ts.map +1 -1
  31. package/dist/cmd/cloud/sandbox/download.js +8 -3
  32. package/dist/cmd/cloud/sandbox/download.js.map +1 -1
  33. package/dist/cmd/cloud/sandbox/snapshot/build.d.ts.map +1 -1
  34. package/dist/cmd/cloud/sandbox/snapshot/build.js +52 -35
  35. package/dist/cmd/cloud/sandbox/snapshot/build.js.map +1 -1
  36. package/dist/cmd/cloud/sandbox/upload.d.ts.map +1 -1
  37. package/dist/cmd/cloud/sandbox/upload.js +8 -1
  38. package/dist/cmd/cloud/sandbox/upload.js.map +1 -1
  39. package/dist/cmd/profile/create.js +2 -2
  40. package/dist/cmd/profile/create.js.map +1 -1
  41. package/dist/cmd/project/create.d.ts.map +1 -1
  42. package/dist/cmd/project/create.js +6 -3
  43. package/dist/cmd/project/create.js.map +1 -1
  44. package/dist/utils/deps.d.ts +8 -0
  45. package/dist/utils/deps.d.ts.map +1 -0
  46. package/dist/utils/deps.js +36 -0
  47. package/dist/utils/deps.js.map +1 -0
  48. package/package.json +6 -6
  49. package/src/cli.ts +1 -5
  50. package/src/cmd/ai/cadence/index.ts +8 -2
  51. package/src/cmd/ai/index.ts +8 -1
  52. package/src/cmd/build/patch/index.ts +4 -0
  53. package/src/cmd/build/patch/otel-llm.ts +421 -0
  54. package/src/cmd/cloud/db/create.ts +3 -3
  55. package/src/cmd/cloud/deploy.ts +77 -1
  56. package/src/cmd/cloud/env/pull.ts +29 -19
  57. package/src/cmd/cloud/eval-run/list.ts +5 -1
  58. package/src/cmd/cloud/queue/dlq.ts +11 -10
  59. package/src/cmd/cloud/sandbox/download.ts +9 -3
  60. package/src/cmd/cloud/sandbox/snapshot/build.ts +71 -44
  61. package/src/cmd/cloud/sandbox/upload.ts +9 -1
  62. package/src/cmd/profile/create.ts +2 -2
  63. package/src/cmd/project/create.ts +6 -3
  64. package/src/utils/deps.ts +54 -0
@@ -35,9 +35,8 @@ export const downloadSubcommand = createCommand({
35
35
  path: z.string().optional().describe('Path in sandbox to download (defaults to root)'),
36
36
  format: z
37
37
  .enum(['zip', 'tar.gz'])
38
- .default('tar.gz')
39
38
  .optional()
40
- .describe('Archive format (zip or tar.gz)'),
39
+ .describe('Archive format (auto-detected from filename if not specified)'),
41
40
  }),
42
41
  response: z.object({
43
42
  success: z.boolean(),
@@ -51,7 +50,8 @@ export const downloadSubcommand = createCommand({
51
50
 
52
51
  const region = await getSandboxRegion(logger, auth, config?.name, args.sandboxId, orgId);
53
52
  const client = createSandboxClient(logger, auth, region);
54
- const format = opts.format || 'tar.gz';
53
+
54
+ const format = opts.format ?? detectFormat(args.output);
55
55
 
56
56
  const stream = await sandboxDownloadArchive(client, {
57
57
  sandboxId: args.sandboxId,
@@ -94,4 +94,10 @@ function formatSize(bytes: number): string {
94
94
  return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;
95
95
  }
96
96
 
97
+ function detectFormat(filename: string): 'zip' | 'tar.gz' {
98
+ const lower = filename.toLowerCase();
99
+ if (lower.endsWith('.zip')) return 'zip';
100
+ return 'tar.gz';
101
+ }
102
+
97
103
  export default downloadSubcommand;
@@ -138,7 +138,8 @@ function parseKeyValueArgs(args: string[] | undefined): Record<string, string> {
138
138
 
139
139
  function substituteVariables(
140
140
  values: Record<string, string>,
141
- variables: Record<string, string>
141
+ variables: Record<string, string>,
142
+ flagName: 'env' | 'metadata'
142
143
  ): Record<string, string> {
143
144
  const result: Record<string, string> = {};
144
145
  const varPattern = /\$\{([^}]+)\}/g;
@@ -152,7 +153,7 @@ function substituteVariables(
152
153
  const varName = match[1];
153
154
  if (!(varName in variables)) {
154
155
  throw new Error(
155
- `Variable "\${${varName}}" in "${key}" is not defined. Use --env ${varName}=value to provide it.`
156
+ `Variable "\${${varName}}" in "${key}" is not defined. Use --${flagName} ${varName}=value to provide it.`
156
157
  );
157
158
  }
158
159
  substituted = substituted.replace(match[0], variables[varName]);
@@ -163,12 +164,15 @@ function substituteVariables(
163
164
  return result;
164
165
  }
165
166
 
167
+ // Default patterns that are always excluded from snapshot builds
168
+ const DEFAULT_EXCLUSIONS = ['.git', '.git/**', 'node_modules/**', '.agentuity/**', '.env*'];
169
+
166
170
  async function resolveFileGlobs(
167
171
  directory: string,
168
172
  patterns: string[]
169
173
  ): Promise<Map<string, FileEntry>> {
170
174
  const files = new Map<string, FileEntry>();
171
- const exclusions: string[] = [];
175
+ const exclusions: string[] = [...DEFAULT_EXCLUSIONS];
172
176
  const inclusions: string[] = [];
173
177
 
174
178
  for (const pattern of patterns) {
@@ -199,18 +203,34 @@ async function resolveFileGlobs(
199
203
  }
200
204
  }
201
205
 
206
+ // Expand exclusion patterns to include nested variants
207
+ const expandedExclusions: string[] = [];
202
208
  for (let pattern of exclusions) {
203
- // If the pattern refers to a directory, auto-append /** to exclude all contents
204
- const patternPath = join(directory, pattern);
205
- try {
206
- const stat = statSync(patternPath);
207
- if (stat.isDirectory()) {
208
- pattern = pattern.endsWith('/') ? `${pattern}**` : `${pattern}/**`;
209
+ // If pattern already contains glob wildcards, use it as-is
210
+ // Otherwise, check if it refers to a directory and auto-append /** to exclude all contents
211
+ const hasGlobChars = /[*?[\]]/.test(pattern);
212
+ if (!hasGlobChars) {
213
+ const patternPath = join(directory, pattern);
214
+ try {
215
+ const stat = statSync(patternPath);
216
+ if (stat.isDirectory()) {
217
+ pattern = pattern.endsWith('/') ? `${pattern}**` : `${pattern}/**`;
218
+ }
219
+ } catch {
220
+ // Path doesn't exist or can't be stat'd, use pattern as-is
209
221
  }
210
- } catch {
211
- // Path doesn't exist or can't be stat'd, use pattern as-is
212
222
  }
213
223
 
224
+ expandedExclusions.push(pattern);
225
+
226
+ // Add **/ prefix variant to match nested occurrences (e.g., .agentuity/** -> **/.agentuity/**)
227
+ // Skip if pattern already starts with **/ or is just a wildcard pattern
228
+ if (!pattern.startsWith('**/')) {
229
+ expandedExclusions.push(`**/${pattern}`);
230
+ }
231
+ }
232
+
233
+ for (const pattern of expandedExclusions) {
214
234
  const glob = new Bun.Glob(pattern);
215
235
  for await (const file of glob.scan({ cwd: directory, dot: true })) {
216
236
  files.delete(file);
@@ -379,37 +399,6 @@ export const buildSubcommand = createCommand({
379
399
  const { args, opts, options, auth, region, config, logger, orgId } = ctx;
380
400
 
381
401
  const dryRun = options.dryRun === true;
382
- const isPublic = opts.public === true;
383
-
384
- if (isPublic && !dryRun) {
385
- if (!opts.confirm) {
386
- if (!tui.isTTYLike()) {
387
- logger.fatal(
388
- `Publishing a public snapshot requires confirmation.\n\n` +
389
- `Public snapshots make all environment variables and files publicly accessible.\n\n` +
390
- `To proceed, add the --confirm flag:\n` +
391
- ` ${getCommand('cloud sandbox snapshot build . --public --confirm')}\n\n` +
392
- `To preview what will be published, use --dry-run first:\n` +
393
- ` ${getCommand('cloud sandbox snapshot build . --public --dry-run')}`
394
- );
395
- }
396
-
397
- tui.warningBox(
398
- 'Public Snapshot',
399
- `You are publishing a public snapshot.\n\n` +
400
- `This will make all environment variables and\n` +
401
- `files in the snapshot publicly accessible.\n\n` +
402
- `Run with --dry-run to preview the contents.`
403
- );
404
- console.log('');
405
-
406
- const confirmed = await tui.confirm('Proceed with public snapshot?', false);
407
-
408
- if (!confirmed) {
409
- logger.fatal('Aborted');
410
- }
411
- }
412
- }
413
402
 
414
403
  const directory = resolve(args.directory);
415
404
  if (!existsSync(directory)) {
@@ -470,6 +459,40 @@ export const buildSubcommand = createCommand({
470
459
 
471
460
  const buildConfig = validationResult.data;
472
461
 
462
+ // Determine if snapshot is public: CLI flag takes precedence, otherwise use build file
463
+ const isPublic =
464
+ opts.public === true || (opts.public === undefined && buildConfig.public === true);
465
+
466
+ if (isPublic && !dryRun) {
467
+ if (!opts.confirm) {
468
+ if (!tui.isTTYLike()) {
469
+ logger.fatal(
470
+ `Publishing a public snapshot requires confirmation.\n\n` +
471
+ `Public snapshots make all environment variables and files publicly accessible.\n\n` +
472
+ `To proceed, add the --confirm flag:\n` +
473
+ ` ${getCommand('cloud sandbox snapshot build . --public --confirm')}\n\n` +
474
+ `To preview what will be published, use --dry-run first:\n` +
475
+ ` ${getCommand('cloud sandbox snapshot build . --public --dry-run')}`
476
+ );
477
+ }
478
+
479
+ tui.warningBox(
480
+ 'Public Snapshot',
481
+ `You are publishing a public snapshot.\n\n` +
482
+ `This will make all environment variables and\n` +
483
+ `files in the snapshot publicly accessible.\n\n` +
484
+ `Run with --dry-run to preview the contents.`
485
+ );
486
+ console.log('');
487
+
488
+ const confirmed = await tui.confirm('Proceed with public snapshot?', false);
489
+
490
+ if (!confirmed) {
491
+ logger.fatal('Aborted');
492
+ }
493
+ }
494
+ }
495
+
473
496
  if (opts.tag) {
474
497
  if (opts.tag.length > MAX_SNAPSHOT_TAG_LENGTH) {
475
498
  logger.fatal(
@@ -502,10 +525,14 @@ export const buildSubcommand = createCommand({
502
525
 
503
526
  try {
504
527
  if (buildConfig.env) {
505
- finalEnv = substituteVariables(buildConfig.env, envSubstitutions);
528
+ finalEnv = substituteVariables(buildConfig.env, envSubstitutions, 'env');
506
529
  }
507
530
  if (buildConfig.metadata) {
508
- finalMetadata = substituteVariables(buildConfig.metadata, metadataSubstitutions);
531
+ finalMetadata = substituteVariables(
532
+ buildConfig.metadata,
533
+ metadataSubstitutions,
534
+ 'metadata'
535
+ );
509
536
  }
510
537
  } catch (err) {
511
538
  logger.fatal(err instanceof Error ? err.message : String(err));
@@ -58,11 +58,13 @@ export const uploadSubcommand = createCommand({
58
58
  const content = readFileSync(args.archive);
59
59
  const bytes = content.length;
60
60
 
61
+ const format = opts.format ?? detectFormat(args.archive);
62
+
61
63
  await sandboxUploadArchive(client, {
62
64
  sandboxId: args.sandboxId,
63
65
  archive: content,
64
66
  path: opts.path || '.',
65
- format: opts.format || '',
67
+ format,
66
68
  orgId,
67
69
  });
68
70
 
@@ -81,4 +83,10 @@ function formatSize(bytes: number): string {
81
83
  return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;
82
84
  }
83
85
 
86
+ function detectFormat(filename: string): 'zip' | 'tar.gz' {
87
+ const lower = filename.toLowerCase();
88
+ if (lower.endsWith('.zip')) return 'zip';
89
+ return 'tar.gz';
90
+ }
91
+
84
92
  export default uploadSubcommand;
@@ -24,9 +24,9 @@ export const createCommand = createSubcommand({
24
24
  aliases: ['new'],
25
25
  idempotent: false,
26
26
  examples: [
27
- { command: getCommand('profile create production'), description: 'Create new item' },
27
+ { command: getCommand('profile create production'), description: 'Create new profile' },
28
28
  { command: getCommand('profile create staging --switch'), description: 'Use switch option' },
29
- { command: getCommand('profile create development'), description: 'Create new item' },
29
+ { command: getCommand('profile create development'), description: 'Create new profile' },
30
30
  ],
31
31
  schema: {
32
32
  args: z
@@ -27,11 +27,14 @@ export const createProjectSubcommand = createSubcommand({
27
27
  idempotent: false,
28
28
  optional: { auth: true, region: true, apiClient: true },
29
29
  examples: [
30
- { command: getCommand('project create'), description: 'Create new item' },
31
- { command: getCommand('project create --name my-ai-agent'), description: 'Create new item' },
30
+ { command: getCommand('project create'), description: 'Create new project' },
31
+ {
32
+ command: getCommand('project create --name my-ai-agent'),
33
+ description: 'Create new project',
34
+ },
32
35
  {
33
36
  command: getCommand('project create --name customer-service-bot --dir ~/projects/agent'),
34
- description: 'Create new item',
37
+ description: 'Create new project',
35
38
  },
36
39
  {
37
40
  command: getCommand('project create --template basic --no-install'),
@@ -0,0 +1,54 @@
1
+ import { $ } from 'bun';
2
+ import type { Logger } from '../types';
3
+
4
+ export interface PackageRef {
5
+ name: string;
6
+ version: string;
7
+ }
8
+
9
+ export async function extractDependencies(
10
+ projectDir: string,
11
+ logger: Logger
12
+ ): Promise<PackageRef[]> {
13
+ try {
14
+ logger.debug('Extracting dependencies using bun pm ls --all');
15
+
16
+ const result = await $`bun pm ls --all`.cwd(projectDir).quiet().nothrow();
17
+
18
+ if (result.exitCode !== 0) {
19
+ logger.warn(
20
+ 'Failed to extract dependencies: bun pm ls exited with code %d',
21
+ result.exitCode
22
+ );
23
+ return [];
24
+ }
25
+
26
+ const output = result.stdout.toString();
27
+ const packages = parseBunPmLsOutput(output);
28
+
29
+ logger.debug('Extracted %d unique packages', packages.length);
30
+ return packages;
31
+ } catch (error) {
32
+ logger.warn('Failed to extract dependencies: %s', error);
33
+ return [];
34
+ }
35
+ }
36
+
37
+ export function parseBunPmLsOutput(output: string): PackageRef[] {
38
+ const packages = new Map<string, PackageRef>();
39
+ const lines = output.split('\n');
40
+
41
+ for (const line of lines) {
42
+ const match = line.match(/([^\s]+)@(\d+\.\d+\.\d+[^\s]*)/);
43
+ if (match) {
44
+ const name = match[1];
45
+ const version = match[2];
46
+ const key = `${name}@${version}`;
47
+ if (!packages.has(key)) {
48
+ packages.set(key, { name, version });
49
+ }
50
+ }
51
+ }
52
+
53
+ return Array.from(packages.values());
54
+ }