@agentuity/cli 1.0.29 → 1.0.31

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 (61) hide show
  1. package/dist/agent-detection.d.ts.map +1 -1
  2. package/dist/agent-detection.js +23 -3
  3. package/dist/agent-detection.js.map +1 -1
  4. package/dist/cli.d.ts.map +1 -1
  5. package/dist/cli.js +2 -0
  6. package/dist/cli.js.map +1 -1
  7. package/dist/cmd/cloud/keyvalue/repl.js +1 -1
  8. package/dist/cmd/cloud/keyvalue/repl.js.map +1 -1
  9. package/dist/cmd/cloud/keyvalue/search.js +2 -2
  10. package/dist/cmd/cloud/keyvalue/search.js.map +1 -1
  11. package/dist/cmd/cloud/storage/config.d.ts +2 -0
  12. package/dist/cmd/cloud/storage/config.d.ts.map +1 -0
  13. package/dist/cmd/cloud/storage/config.js +202 -0
  14. package/dist/cmd/cloud/storage/config.js.map +1 -0
  15. package/dist/cmd/cloud/storage/index.d.ts.map +1 -1
  16. package/dist/cmd/cloud/storage/index.js +2 -0
  17. package/dist/cmd/cloud/storage/index.js.map +1 -1
  18. package/dist/cmd/cloud/storage/list.d.ts.map +1 -1
  19. package/dist/cmd/cloud/storage/list.js +19 -0
  20. package/dist/cmd/cloud/storage/list.js.map +1 -1
  21. package/dist/cmd/cloud/task/create.d.ts.map +1 -1
  22. package/dist/cmd/cloud/task/create.js +15 -6
  23. package/dist/cmd/cloud/task/create.js.map +1 -1
  24. package/dist/cmd/cloud/task/delete.d.ts +8 -0
  25. package/dist/cmd/cloud/task/delete.d.ts.map +1 -0
  26. package/dist/cmd/cloud/task/delete.js +281 -0
  27. package/dist/cmd/cloud/task/delete.js.map +1 -0
  28. package/dist/cmd/cloud/task/get.d.ts.map +1 -1
  29. package/dist/cmd/cloud/task/get.js +10 -3
  30. package/dist/cmd/cloud/task/get.js.map +1 -1
  31. package/dist/cmd/cloud/task/index.d.ts.map +1 -1
  32. package/dist/cmd/cloud/task/index.js +10 -0
  33. package/dist/cmd/cloud/task/index.js.map +1 -1
  34. package/dist/cmd/cloud/task/list.d.ts.map +1 -1
  35. package/dist/cmd/cloud/task/list.js +2 -0
  36. package/dist/cmd/cloud/task/list.js.map +1 -1
  37. package/dist/cmd/project/template-flow.d.ts.map +1 -1
  38. package/dist/cmd/project/template-flow.js +30 -2
  39. package/dist/cmd/project/template-flow.js.map +1 -1
  40. package/dist/domain.d.ts.map +1 -1
  41. package/dist/domain.js +48 -0
  42. package/dist/domain.js.map +1 -1
  43. package/dist/tui.d.ts.map +1 -1
  44. package/dist/tui.js +3 -1
  45. package/dist/tui.js.map +1 -1
  46. package/package.json +6 -6
  47. package/src/agent-detection.ts +23 -3
  48. package/src/cli.ts +1 -0
  49. package/src/cmd/cloud/keyvalue/repl.ts +1 -1
  50. package/src/cmd/cloud/keyvalue/search.ts +2 -2
  51. package/src/cmd/cloud/storage/config.ts +238 -0
  52. package/src/cmd/cloud/storage/index.ts +2 -0
  53. package/src/cmd/cloud/storage/list.ts +18 -0
  54. package/src/cmd/cloud/task/create.ts +17 -8
  55. package/src/cmd/cloud/task/delete.ts +331 -0
  56. package/src/cmd/cloud/task/get.ts +11 -3
  57. package/src/cmd/cloud/task/index.ts +10 -0
  58. package/src/cmd/cloud/task/list.ts +2 -0
  59. package/src/cmd/project/template-flow.ts +31 -1
  60. package/src/domain.ts +52 -4
  61. package/src/tui.ts +2 -1
@@ -11,6 +11,14 @@ const EntityRefSchema = z
11
11
  })
12
12
  .optional();
13
13
 
14
+ const UserEntityRefSchema = z
15
+ .object({
16
+ id: z.string(),
17
+ name: z.string(),
18
+ type: z.enum(['human', 'agent']).optional(),
19
+ })
20
+ .optional();
21
+
14
22
  const TaskGetResponseSchema = z.object({
15
23
  success: z.boolean().describe('Whether the operation succeeded'),
16
24
  task: z.object({
@@ -21,9 +29,9 @@ const TaskGetResponseSchema = z.object({
21
29
  status: z.string().describe('Task status'),
22
30
  priority: z.string().describe('Task priority'),
23
31
  parent_id: z.string().optional().describe('Parent task ID'),
24
- creator: EntityRefSchema.describe('Creator'),
25
- assignee: EntityRefSchema.describe('Assignee'),
26
- closer: EntityRefSchema.describe('Closer'),
32
+ creator: UserEntityRefSchema.describe('Creator'),
33
+ assignee: UserEntityRefSchema.describe('Assignee'),
34
+ closer: UserEntityRefSchema.describe('Closer'),
27
35
  project: EntityRefSchema.describe('Project'),
28
36
  metadata: z.record(z.string(), z.unknown()).optional().describe('Task metadata'),
29
37
  created_at: z.string().describe('Creation timestamp'),
@@ -3,6 +3,7 @@ import { getSubcommand } from './get';
3
3
  import { createSubcommand } from './create';
4
4
  import { updateSubcommand } from './update';
5
5
  import { listSubcommand } from './list';
6
+ import { deleteSubcommand } from './delete';
6
7
  import { statsSubcommand } from './stats';
7
8
  import { attachmentSubcommand } from './attachment';
8
9
  import { getCommand } from '../../../command-prefix';
@@ -28,6 +29,14 @@ export const taskCommand = createCommand({
28
29
  command: getCommand('cloud task update task_abc123 --status in_progress'),
29
30
  description: 'Update task status',
30
31
  },
32
+ {
33
+ command: getCommand('cloud task delete task_abc123'),
34
+ description: 'Delete a task by ID',
35
+ },
36
+ {
37
+ command: getCommand('cloud task delete --status closed --older-than 7d'),
38
+ description: 'Batch delete closed tasks older than 7 days',
39
+ },
31
40
  {
32
41
  command: getCommand('cloud task attachment upload task_abc123 ./report.pdf'),
33
42
  description: 'Upload a file attachment to a task',
@@ -38,6 +47,7 @@ export const taskCommand = createCommand({
38
47
  createSubcommand,
39
48
  updateSubcommand,
40
49
  listSubcommand,
50
+ deleteSubcommand,
41
51
  statsSubcommand,
42
52
  attachmentSubcommand,
43
53
  ],
@@ -18,12 +18,14 @@ const TaskListResponseSchema = z.object({
18
18
  .object({
19
19
  id: z.string(),
20
20
  name: z.string(),
21
+ type: z.enum(['human', 'agent']).optional(),
21
22
  })
22
23
  .optional(),
23
24
  assignee: z
24
25
  .object({
25
26
  id: z.string(),
26
27
  name: z.string(),
28
+ type: z.enum(['human', 'agent']).optional(),
27
29
  })
28
30
  .optional(),
29
31
  project: z
@@ -11,6 +11,7 @@ import {
11
11
  APIClient as ServerAPIClient,
12
12
  createResources,
13
13
  validateDatabaseName,
14
+ validateBucketName,
14
15
  } from '@agentuity/server';
15
16
  import type { Logger } from '@agentuity/core';
16
17
  import * as tui from '../../tui';
@@ -440,11 +441,40 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<CreateF
440
441
  // Process storage action
441
442
  switch (s3_action) {
442
443
  case 'Create New': {
444
+ let bucketName: string | undefined;
445
+ let bucketDescription: string | undefined;
446
+
447
+ // Only prompt for name/description in interactive mode
448
+ if (isInteractive) {
449
+ const bucketNameInput = await prompt.text({
450
+ message: 'Bucket name',
451
+ hint: 'Optional - lowercase letters, digits, hyphens only',
452
+ validate: (value: string) => {
453
+ const trimmed = value.trim();
454
+ if (trimmed === '') return true;
455
+ const result = validateBucketName(trimmed);
456
+ return result.valid ? true : result.error!;
457
+ },
458
+ });
459
+ bucketName = bucketNameInput.trim() || undefined;
460
+ bucketDescription =
461
+ (await prompt.text({
462
+ message: 'Bucket description',
463
+ hint: 'Optional - press Enter to skip',
464
+ })) || undefined;
465
+ }
466
+
443
467
  const created = await tui.spinner({
444
468
  message: 'Provisioning New Bucket',
445
469
  clearOnSuccess: true,
446
470
  callback: async () => {
447
- return createResources(catalystClient!, orgId!, region!, [{ type: 's3' }]);
471
+ return createResources(catalystClient!, orgId!, region!, [
472
+ {
473
+ type: 's3',
474
+ name: bucketName,
475
+ description: bucketDescription,
476
+ },
477
+ ]);
448
478
  },
449
479
  });
450
480
  // Collect env vars from newly created resource
package/src/domain.ts CHANGED
@@ -95,6 +95,30 @@ async function fetchDNSRecord(name: string, type: string): Promise<string | null
95
95
  return records[0] ?? null;
96
96
  }
97
97
 
98
+ /**
99
+ * Check if a domain has a valid TLS certificate by making a HEAD request.
100
+ * This also triggers Let's Encrypt certificate provisioning on first access.
101
+ * Returns true if the TLS certificate is valid (any HTTP status code received).
102
+ * Returns false if the certificate is not yet provisioned (timeout or TLS error).
103
+ */
104
+ async function checkTLSCertificate(domain: string): Promise<boolean> {
105
+ try {
106
+ await fetch(`https://${domain}`, {
107
+ method: 'HEAD',
108
+ signal: AbortSignal.timeout(timeoutMs),
109
+ redirect: 'manual',
110
+ // @ts-expect-error - cache is supported by Bun's fetch at runtime but missing from type definitions
111
+ cache: 'no-store',
112
+ });
113
+ // Any HTTP response means TLS handshake succeeded and certificate is valid
114
+ return true;
115
+ } catch {
116
+ // Timeout, TLS certificate error, connection refused, etc.
117
+ // All indicate the certificate is not yet provisioned
118
+ return false;
119
+ }
120
+ }
121
+
98
122
  const LOCAL_DNS = 'agentuity.io';
99
123
  const PRODUCTION_DNS = 'agentuity.run';
100
124
 
@@ -171,15 +195,27 @@ export async function checkCustomDomainForDNS(
171
195
  if (timeoutId) clearTimeout(timeoutId);
172
196
  });
173
197
 
174
- if (result) {
175
- if (result === proxy) {
198
+ if (result) {
199
+ if (result === proxy) {
200
+ // DNS is correct — verify TLS certificate (also triggers Let's Encrypt provisioning)
201
+ const tlsValid = await checkTLSCertificate(domain);
202
+ if (tlsValid) {
203
+ return {
204
+ domain,
205
+ target: proxy,
206
+ aRecordTarget,
207
+ recordType: 'CNAME',
208
+ success: true,
209
+ } as DNSSuccess;
210
+ }
176
211
  return {
177
212
  domain,
178
213
  target: proxy,
179
214
  aRecordTarget,
180
215
  recordType: 'CNAME',
181
216
  success: true,
182
- } as DNSSuccess;
217
+ pending: true,
218
+ } as DNSPending;
183
219
  }
184
220
  return {
185
221
  domain,
@@ -242,13 +278,25 @@ export async function checkCustomDomainForDNS(
242
278
  if (domainARecords.length > 0) {
243
279
  const matching = domainARecords.some((a) => ionIPs.includes(a));
244
280
  if (matching) {
281
+ // DNS is correct — verify TLS certificate (also triggers Let's Encrypt provisioning)
282
+ const tlsValid = await checkTLSCertificate(domain);
283
+ if (tlsValid) {
284
+ return {
285
+ domain,
286
+ target: proxy,
287
+ aRecordTarget,
288
+ recordType: 'A',
289
+ success: true,
290
+ } as DNSSuccess;
291
+ }
245
292
  return {
246
293
  domain,
247
294
  target: proxy,
248
295
  aRecordTarget,
249
296
  recordType: 'A',
250
297
  success: true,
251
- } as DNSSuccess;
298
+ pending: true,
299
+ } as DNSPending;
252
300
  }
253
301
  return {
254
302
  domain,
package/src/tui.ts CHANGED
@@ -2235,7 +2235,8 @@ export function formatBytes(bytes: number): string {
2235
2235
  if (bytes < 1024) return `${bytes} B`;
2236
2236
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(2)} KB`;
2237
2237
  if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
2238
- return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)} GB`;
2238
+ if (bytes < 1024 * 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)} GB`;
2239
+ return `${(bytes / (1024 * 1024 * 1024 * 1024)).toFixed(2)} TB`;
2239
2240
  }
2240
2241
 
2241
2242
  export function clearLastLines(n: number, s?: (v: string) => void) {