@agentuity/cli 0.1.22 → 0.1.24

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 (130) hide show
  1. package/dist/cli.d.ts.map +1 -1
  2. package/dist/cli.js +36 -5
  3. package/dist/cli.js.map +1 -1
  4. package/dist/cmd/ai/cadence/index.d.ts +3 -0
  5. package/dist/cmd/ai/cadence/index.d.ts.map +1 -0
  6. package/dist/cmd/ai/cadence/index.js +29 -0
  7. package/dist/cmd/ai/cadence/index.js.map +1 -0
  8. package/dist/cmd/ai/cadence/list.d.ts +3 -0
  9. package/dist/cmd/ai/cadence/list.d.ts.map +1 -0
  10. package/dist/cmd/ai/cadence/list.js +167 -0
  11. package/dist/cmd/ai/cadence/list.js.map +1 -0
  12. package/dist/cmd/ai/cadence/pause.d.ts +3 -0
  13. package/dist/cmd/ai/cadence/pause.d.ts.map +1 -0
  14. package/dist/cmd/ai/cadence/pause.js +103 -0
  15. package/dist/cmd/ai/cadence/pause.js.map +1 -0
  16. package/dist/cmd/ai/cadence/resume.d.ts +3 -0
  17. package/dist/cmd/ai/cadence/resume.d.ts.map +1 -0
  18. package/dist/cmd/ai/cadence/resume.js +106 -0
  19. package/dist/cmd/ai/cadence/resume.js.map +1 -0
  20. package/dist/cmd/ai/cadence/status.d.ts +3 -0
  21. package/dist/cmd/ai/cadence/status.d.ts.map +1 -0
  22. package/dist/cmd/ai/cadence/status.js +129 -0
  23. package/dist/cmd/ai/cadence/status.js.map +1 -0
  24. package/dist/cmd/ai/cadence/stop.d.ts +3 -0
  25. package/dist/cmd/ai/cadence/stop.d.ts.map +1 -0
  26. package/dist/cmd/ai/cadence/stop.js +107 -0
  27. package/dist/cmd/ai/cadence/stop.js.map +1 -0
  28. package/dist/cmd/ai/cadence/util.d.ts +44 -0
  29. package/dist/cmd/ai/cadence/util.d.ts.map +1 -0
  30. package/dist/cmd/ai/cadence/util.js +52 -0
  31. package/dist/cmd/ai/cadence/util.js.map +1 -0
  32. package/dist/cmd/ai/index.d.ts.map +1 -1
  33. package/dist/cmd/ai/index.js +2 -1
  34. package/dist/cmd/ai/index.js.map +1 -1
  35. package/dist/cmd/auth/machine/setup.js +1 -1
  36. package/dist/cmd/auth/machine/setup.js.map +1 -1
  37. package/dist/cmd/auth/ssh/add.js +1 -1
  38. package/dist/cmd/auth/ssh/add.js.map +1 -1
  39. package/dist/cmd/cloud/eval/get.d.ts +2 -0
  40. package/dist/cmd/cloud/eval/get.d.ts.map +1 -0
  41. package/dist/cmd/cloud/eval/get.js +79 -0
  42. package/dist/cmd/cloud/eval/get.js.map +1 -0
  43. package/dist/cmd/cloud/eval/index.d.ts +2 -0
  44. package/dist/cmd/cloud/eval/index.d.ts.map +1 -0
  45. package/dist/cmd/cloud/eval/index.js +15 -0
  46. package/dist/cmd/cloud/eval/index.js.map +1 -0
  47. package/dist/cmd/cloud/eval/list.d.ts +2 -0
  48. package/dist/cmd/cloud/eval/list.d.ts.map +1 -0
  49. package/dist/cmd/cloud/eval/list.js +119 -0
  50. package/dist/cmd/cloud/eval/list.js.map +1 -0
  51. package/dist/cmd/cloud/eval-run/get.d.ts +2 -0
  52. package/dist/cmd/cloud/eval-run/get.d.ts.map +1 -0
  53. package/dist/cmd/cloud/eval-run/get.js +106 -0
  54. package/dist/cmd/cloud/eval-run/get.js.map +1 -0
  55. package/dist/cmd/cloud/eval-run/index.d.ts +2 -0
  56. package/dist/cmd/cloud/eval-run/index.d.ts.map +1 -0
  57. package/dist/cmd/cloud/eval-run/index.js +15 -0
  58. package/dist/cmd/cloud/eval-run/index.js.map +1 -0
  59. package/dist/cmd/cloud/eval-run/list.d.ts +2 -0
  60. package/dist/cmd/cloud/eval-run/list.d.ts.map +1 -0
  61. package/dist/cmd/cloud/eval-run/list.js +140 -0
  62. package/dist/cmd/cloud/eval-run/list.js.map +1 -0
  63. package/dist/cmd/cloud/index.d.ts.map +1 -1
  64. package/dist/cmd/cloud/index.js +4 -0
  65. package/dist/cmd/cloud/index.js.map +1 -1
  66. package/dist/cmd/cloud/machine/list.d.ts.map +1 -1
  67. package/dist/cmd/cloud/machine/list.js +16 -0
  68. package/dist/cmd/cloud/machine/list.js.map +1 -1
  69. package/dist/cmd/cloud/queue/dlq.d.ts.map +1 -1
  70. package/dist/cmd/cloud/queue/dlq.js +15 -10
  71. package/dist/cmd/cloud/queue/dlq.js.map +1 -1
  72. package/dist/cmd/cloud/sandbox/snapshot/build.d.ts.map +1 -1
  73. package/dist/cmd/cloud/sandbox/snapshot/build.js.map +1 -1
  74. package/dist/cmd/cloud/sandbox/snapshot/create.d.ts.map +1 -1
  75. package/dist/cmd/cloud/sandbox/snapshot/create.js +5 -1
  76. package/dist/cmd/cloud/sandbox/snapshot/create.js.map +1 -1
  77. package/dist/cmd/cloud/storage/upload.js +1 -1
  78. package/dist/cmd/cloud/storage/upload.js.map +1 -1
  79. package/dist/cmd/cloud/vector/stats.d.ts.map +1 -1
  80. package/dist/cmd/cloud/vector/stats.js +3 -1
  81. package/dist/cmd/cloud/vector/stats.js.map +1 -1
  82. package/dist/cmd/cloud/vector/upsert.js +1 -1
  83. package/dist/cmd/cloud/vector/upsert.js.map +1 -1
  84. package/dist/cmd/project/delete.d.ts.map +1 -1
  85. package/dist/cmd/project/delete.js +46 -10
  86. package/dist/cmd/project/delete.js.map +1 -1
  87. package/dist/cmd/setup/index.d.ts.map +1 -1
  88. package/dist/cmd/setup/index.js +4 -1
  89. package/dist/cmd/setup/index.js.map +1 -1
  90. package/dist/env-util.d.ts.map +1 -1
  91. package/dist/env-util.js +4 -1
  92. package/dist/env-util.js.map +1 -1
  93. package/dist/schema-parser.d.ts +17 -1
  94. package/dist/schema-parser.d.ts.map +1 -1
  95. package/dist/schema-parser.js +131 -2
  96. package/dist/schema-parser.js.map +1 -1
  97. package/dist/tui.d.ts.map +1 -1
  98. package/dist/tui.js +4 -0
  99. package/dist/tui.js.map +1 -1
  100. package/package.json +6 -6
  101. package/src/cli.ts +40 -5
  102. package/src/cmd/ai/cadence/index.ts +30 -0
  103. package/src/cmd/ai/cadence/list.ts +183 -0
  104. package/src/cmd/ai/cadence/pause.ts +119 -0
  105. package/src/cmd/ai/cadence/resume.ts +124 -0
  106. package/src/cmd/ai/cadence/status.ts +141 -0
  107. package/src/cmd/ai/cadence/stop.ts +124 -0
  108. package/src/cmd/ai/cadence/util.ts +86 -0
  109. package/src/cmd/ai/index.ts +2 -1
  110. package/src/cmd/auth/machine/setup.ts +1 -1
  111. package/src/cmd/auth/ssh/add.ts +1 -1
  112. package/src/cmd/cloud/eval/get.ts +85 -0
  113. package/src/cmd/cloud/eval/index.ts +15 -0
  114. package/src/cmd/cloud/eval/list.ts +129 -0
  115. package/src/cmd/cloud/eval-run/get.ts +113 -0
  116. package/src/cmd/cloud/eval-run/index.ts +15 -0
  117. package/src/cmd/cloud/eval-run/list.ts +150 -0
  118. package/src/cmd/cloud/index.ts +4 -0
  119. package/src/cmd/cloud/machine/list.ts +16 -0
  120. package/src/cmd/cloud/queue/dlq.ts +15 -10
  121. package/src/cmd/cloud/sandbox/snapshot/build.ts +5 -1
  122. package/src/cmd/cloud/sandbox/snapshot/create.ts +5 -1
  123. package/src/cmd/cloud/storage/upload.ts +1 -1
  124. package/src/cmd/cloud/vector/stats.ts +3 -1
  125. package/src/cmd/cloud/vector/upsert.ts +1 -1
  126. package/src/cmd/project/delete.ts +55 -10
  127. package/src/cmd/setup/index.ts +4 -1
  128. package/src/env-util.ts +4 -1
  129. package/src/schema-parser.ts +150 -2
  130. package/src/tui.ts +5 -0
@@ -1,10 +1,19 @@
1
1
  import { z } from 'zod';
2
2
  import { createSubcommand } from '../../types';
3
3
  import * as tui from '../../tui';
4
- import { projectDelete, projectList } from '@agentuity/server';
4
+ import { projectDelete, projectList, projectGet } from '@agentuity/server';
5
5
  import enquirer from 'enquirer';
6
6
  import { getCommand } from '../../command-prefix';
7
7
 
8
+ interface ProjectDisplayInfo {
9
+ id: string;
10
+ name: string;
11
+ }
12
+
13
+ function formatProjectDisplay(project: ProjectDisplayInfo): string {
14
+ return `${project.name} (${project.id})`;
15
+ }
16
+
8
17
  export const deleteSubcommand = createSubcommand({
9
18
  name: 'delete',
10
19
  description: 'Delete a project',
@@ -46,11 +55,37 @@ export const deleteSubcommand = createSubcommand({
46
55
  async handler(ctx) {
47
56
  const { args, opts, apiClient } = ctx;
48
57
 
49
- let projectIds: string[] = [];
58
+ let projectsToDelete: ProjectDisplayInfo[] = [];
50
59
 
51
60
  if (args.id) {
52
- // Command line argument provided
53
- projectIds = [args.id];
61
+ // Command line argument provided - validate and fetch project details
62
+ const projectInfo = await tui.spinner({
63
+ message: 'Fetching project details',
64
+ clearOnSuccess: true,
65
+ callback: async () => {
66
+ try {
67
+ const project = await projectGet(apiClient, {
68
+ id: args.id!,
69
+ mask: true,
70
+ keys: false,
71
+ });
72
+
73
+ return {
74
+ id: project.id,
75
+ name: project.name,
76
+ };
77
+ } catch {
78
+ return null;
79
+ }
80
+ },
81
+ });
82
+
83
+ if (!projectInfo) {
84
+ tui.error(`Project not found: ${args.id}`);
85
+ return { success: false, projectIds: [], count: 0 };
86
+ }
87
+
88
+ projectsToDelete = [projectInfo];
54
89
  } else {
55
90
  // Check TTY before attempting to prompt
56
91
  if (!process.stdin.isTTY) {
@@ -87,10 +122,16 @@ export const deleteSubcommand = createSubcommand({
87
122
  choices,
88
123
  });
89
124
 
90
- projectIds = response.projects;
125
+ // Map selected IDs to full project info
126
+ projectsToDelete = response.projects
127
+ .map((id) => {
128
+ const project = projects.find((p) => p.id === id);
129
+ return project ? { id: project.id, name: project.name } : null;
130
+ })
131
+ .filter((p): p is ProjectDisplayInfo => p !== null);
91
132
  }
92
133
 
93
- if (projectIds.length === 0) {
134
+ if (projectsToDelete.length === 0) {
94
135
  tui.info('No projects selected for deletion');
95
136
  return { success: false, projectIds: [], count: 0 };
96
137
  }
@@ -103,13 +144,16 @@ export const deleteSubcommand = createSubcommand({
103
144
 
104
145
  // Confirm deletion
105
146
  if (!skipConfirm) {
106
- const projectNames = projectIds.join(', ');
107
- tui.warning(`You are about to delete: ${tui.bold(projectNames)}`);
147
+ const projectDisplay =
148
+ projectsToDelete.length === 1
149
+ ? formatProjectDisplay(projectsToDelete[0])
150
+ : projectsToDelete.map((p) => `\n • ${formatProjectDisplay(p)}`).join('');
151
+ tui.warning(`You are about to delete: ${tui.bold(projectDisplay)}`);
108
152
 
109
153
  const confirm = await enquirer.prompt<{ confirm: boolean }>({
110
154
  type: 'confirm',
111
155
  name: 'confirm',
112
- message: `Are you sure you want to delete ${projectIds.length > 1 ? 'these projects' : 'this project'}?`,
156
+ message: `Are you sure you want to delete ${projectsToDelete.length > 1 ? 'these projects' : 'this project'}?`,
113
157
  initial: false,
114
158
  });
115
159
 
@@ -119,8 +163,9 @@ export const deleteSubcommand = createSubcommand({
119
163
  }
120
164
  }
121
165
 
166
+ const projectIds = projectsToDelete.map((p) => p.id);
122
167
  const deleted = await tui.spinner({
123
- message: `Deleting ${projectIds.length} project(s)`,
168
+ message: `Deleting ${projectsToDelete.length} project(s)`,
124
169
  clearOnSuccess: true,
125
170
  callback: async () => {
126
171
  return projectDelete(apiClient, ...projectIds);
@@ -41,7 +41,10 @@ export const command = createCommand({
41
41
  // Use process.execPath which has the actual binary path
42
42
  const isCompiledBinary = process.argv[1]?.startsWith('/$bunfs/');
43
43
  const cmd = isCompiledBinary
44
- ? [process.execPath, ...process.argv.slice(2).map((x) => (x === 'setup' ? 'login' : x))]
44
+ ? [
45
+ process.execPath,
46
+ ...process.argv.slice(2).map((x) => (x === 'setup' ? 'login' : x)),
47
+ ]
45
48
  : process.argv.map((x) => (x === 'setup' ? 'login' : x));
46
49
  const r = Bun.spawn({
47
50
  cmd: cmd.concat('--json'),
package/src/env-util.ts CHANGED
@@ -17,7 +17,10 @@ export const PUBLIC_VAR_PREFIXES = ['VITE_', 'AGENTUITY_PUBLIC_', 'PUBLIC_'] as
17
17
  * Specific AGENTUITY_ keys that are allowed to be set by users.
18
18
  * Note: There is also a whitelist in the API that must be kept in sync.
19
19
  */
20
- export const AGENTUITY_ALLOWED_KEYS = ['AGENTUITY_AUTH_SECRET', 'AGENTUITY_CLOUD_BASE_URL'] as const;
20
+ export const AGENTUITY_ALLOWED_KEYS = [
21
+ 'AGENTUITY_AUTH_SECRET',
22
+ 'AGENTUITY_CLOUD_BASE_URL',
23
+ ] as const;
21
24
 
22
25
  /**
23
26
  * Check if a key is a public variable (exposed to frontend)
@@ -254,10 +254,119 @@ export function parseOptionsSchema(schema: ZodType): ParsedOption[] {
254
254
  return options;
255
255
  }
256
256
 
257
+ // Cache for stdin confirmation detection
258
+ let stdinConfirmationChecked = false;
259
+ let stdinConfirmation: boolean | null = null;
260
+
261
+ /**
262
+ * Check if stdin contains a piped "yes" confirmation.
263
+ * This allows commands to be run with `echo "yes" | agentuity <command>` pattern.
264
+ * Only works when stdin is not a TTY (piped input) and command doesn't use stdin.
265
+ */
266
+ async function checkStdinConfirmation(): Promise<boolean> {
267
+ if (stdinConfirmationChecked) {
268
+ return stdinConfirmation === true;
269
+ }
270
+ stdinConfirmationChecked = true;
271
+
272
+ // Only check if stdin is not a TTY (meaning input is piped)
273
+ if (process.stdin.isTTY) {
274
+ stdinConfirmation = null;
275
+ return false;
276
+ }
277
+
278
+ try {
279
+ // Read stdin with a short timeout to avoid blocking
280
+ const reader = process.stdin;
281
+ let timeoutId: ReturnType<typeof setTimeout> | null = null;
282
+ let resolved = false;
283
+ const MAX_BYTES = 4096;
284
+
285
+ // Define handlers outside so we can remove them in all paths
286
+ let data = '';
287
+ const onData = (chunk: Buffer) => {
288
+ data += chunk.toString();
289
+ if (data.length >= MAX_BYTES) {
290
+ data = data.slice(0, MAX_BYTES);
291
+ }
292
+ };
293
+
294
+ let onEnd: (() => void) | null = null;
295
+ let onError: ((err: Error) => void) | null = null;
296
+
297
+ const cleanup = () => {
298
+ reader.removeListener('data', onData);
299
+ if (onEnd) {
300
+ reader.removeListener('end', onEnd);
301
+ }
302
+ if (onError) {
303
+ reader.removeListener('error', onError);
304
+ }
305
+ reader.pause();
306
+ };
307
+
308
+ const readPromise = new Promise<string>((resolve) => {
309
+ onEnd = () => {
310
+ if (resolved) return;
311
+ resolved = true;
312
+ if (timeoutId !== null) {
313
+ clearTimeout(timeoutId);
314
+ timeoutId = null;
315
+ }
316
+ cleanup();
317
+ resolve(data.trim().toLowerCase());
318
+ };
319
+ onError = (_err: Error) => {
320
+ if (resolved) return;
321
+ resolved = true;
322
+ stdinConfirmation = null;
323
+ if (timeoutId !== null) {
324
+ clearTimeout(timeoutId);
325
+ timeoutId = null;
326
+ }
327
+ cleanup();
328
+ resolve('');
329
+ };
330
+ reader.on('data', onData);
331
+ reader.on('end', onEnd);
332
+ reader.on('error', onError);
333
+ });
334
+
335
+ // Use a short timeout to avoid blocking
336
+ const timeoutPromise = new Promise<string>((resolve) => {
337
+ timeoutId = setTimeout(() => {
338
+ if (resolved) return;
339
+ resolved = true;
340
+ // Clean up listeners and pause stdin when timeout wins
341
+ cleanup();
342
+ resolve('');
343
+ }, 100);
344
+ });
345
+
346
+ const input = await Promise.race([readPromise, timeoutPromise]);
347
+ // Take first token/line to handle inputs like "yes\nanything"
348
+ const firstToken = input.split(/\s+/)[0] ?? '';
349
+ stdinConfirmation = firstToken === 'yes' || firstToken === 'y';
350
+ return stdinConfirmation;
351
+ } catch {
352
+ stdinConfirmation = null;
353
+ return false;
354
+ }
355
+ }
356
+
357
+ /**
358
+ * Reset stdin confirmation cache (for testing)
359
+ */
360
+ export function resetStdinConfirmationCache(): void {
361
+ stdinConfirmationChecked = false;
362
+ stdinConfirmation = null;
363
+ }
364
+
257
365
  export function buildValidationInput(
258
366
  schemas: CommandSchemas,
259
367
  rawArgs: unknown[],
260
- rawOptions: Record<string, unknown>
368
+ rawOptions: Record<string, unknown>,
369
+ _options?: { usesStdin?: boolean }
261
370
  ): { args: Record<string, unknown>; options: Record<string, unknown> } {
262
371
  const result = { args: {} as Record<string, unknown>, options: {} as Record<string, unknown> };
263
372
 
@@ -274,7 +383,13 @@ export function buildValidationInput(
274
383
  // Only include the option if it has a value - omitting undefined allows Zod to apply defaults
275
384
  // Commander.js converts kebab-case to camelCase, so we need to check both
276
385
  const camelCaseName = opt.name.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
277
- const value = rawOptions[opt.name] ?? rawOptions[camelCaseName];
386
+ let value = rawOptions[opt.name] ?? rawOptions[camelCaseName];
387
+
388
+ // Handle --yes alias for --confirm: if confirm is not set but yes is, use yes value
389
+ if (opt.name === 'confirm' && value === undefined && rawOptions.yes === true) {
390
+ value = true;
391
+ }
392
+
278
393
  if (value !== undefined) {
279
394
  result.options[opt.name] = value;
280
395
  }
@@ -283,3 +398,36 @@ export function buildValidationInput(
283
398
 
284
399
  return result;
285
400
  }
401
+
402
+ /**
403
+ * Async version of buildValidationInput that also checks stdin for "yes" confirmation.
404
+ * Use this when the command has a confirm option and doesn't use stdin for other purposes.
405
+ */
406
+ export async function buildValidationInputAsync(
407
+ schemas: CommandSchemas,
408
+ rawArgs: unknown[],
409
+ rawOptions: Record<string, unknown>,
410
+ options?: { usesStdin?: boolean }
411
+ ): Promise<{ args: Record<string, unknown>; options: Record<string, unknown> }> {
412
+ const result = buildValidationInput(schemas, rawArgs, rawOptions, options);
413
+
414
+ // Check for stdin confirmation if:
415
+ // 1. Command has a confirm option in schema
416
+ // 2. Command doesn't use stdin for other purposes
417
+ // 3. confirm is not already set via flags
418
+ if (schemas.options && !options?.usesStdin) {
419
+ // Use getShape() instead of parseOptionsSchema() to avoid re-evaluating function defaults
420
+ const shape = getShape(schemas.options);
421
+ const hasConfirmOption = Object.prototype.hasOwnProperty.call(shape, 'confirm');
422
+ const confirmValue = result.options.confirm;
423
+
424
+ if (hasConfirmOption && confirmValue === undefined) {
425
+ const stdinConfirmed = await checkStdinConfirmation();
426
+ if (stdinConfirmed) {
427
+ result.options.confirm = true;
428
+ }
429
+ }
430
+ }
431
+
432
+ return result;
433
+ }
package/src/tui.ts CHANGED
@@ -1172,6 +1172,11 @@ export async function spinner<T>(
1172
1172
  options = messageOrOptions;
1173
1173
  }
1174
1174
 
1175
+ // assume true by default
1176
+ if (options.clearOnSuccess === undefined) {
1177
+ options.clearOnSuccess = true;
1178
+ }
1179
+
1175
1180
  const message = options.message;
1176
1181
  const reset = getColor('reset');
1177
1182