@agentuity/cli 1.0.10 → 1.0.11

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 (121) hide show
  1. package/dist/cmd/build/ast.d.ts +1 -1
  2. package/dist/cmd/build/ast.d.ts.map +1 -1
  3. package/dist/cmd/build/ast.js +103 -5
  4. package/dist/cmd/build/ast.js.map +1 -1
  5. package/dist/cmd/build/vite/config-loader.d.ts.map +1 -1
  6. package/dist/cmd/build/vite/config-loader.js +1 -1
  7. package/dist/cmd/build/vite/config-loader.js.map +1 -1
  8. package/dist/cmd/build/vite/index.d.ts +2 -0
  9. package/dist/cmd/build/vite/index.d.ts.map +1 -1
  10. package/dist/cmd/build/vite/index.js +2 -1
  11. package/dist/cmd/build/vite/index.js.map +1 -1
  12. package/dist/cmd/build/vite/metadata-generator.d.ts +4 -1
  13. package/dist/cmd/build/vite/metadata-generator.d.ts.map +1 -1
  14. package/dist/cmd/build/vite/metadata-generator.js +1 -0
  15. package/dist/cmd/build/vite/metadata-generator.js.map +1 -1
  16. package/dist/cmd/build/vite/route-discovery.d.ts.map +1 -1
  17. package/dist/cmd/build/vite/route-discovery.js +23 -1
  18. package/dist/cmd/build/vite/route-discovery.js.map +1 -1
  19. package/dist/cmd/build/vite/vite-builder.d.ts +2 -0
  20. package/dist/cmd/build/vite/vite-builder.d.ts.map +1 -1
  21. package/dist/cmd/build/vite/vite-builder.js +1 -0
  22. package/dist/cmd/build/vite/vite-builder.js.map +1 -1
  23. package/dist/cmd/build/vite-bundler.d.ts +2 -0
  24. package/dist/cmd/build/vite-bundler.d.ts.map +1 -1
  25. package/dist/cmd/build/vite-bundler.js +2 -1
  26. package/dist/cmd/build/vite-bundler.js.map +1 -1
  27. package/dist/cmd/cloud/db/list.d.ts.map +1 -1
  28. package/dist/cmd/cloud/db/list.js +14 -1
  29. package/dist/cmd/cloud/db/list.js.map +1 -1
  30. package/dist/cmd/cloud/deploy.d.ts.map +1 -1
  31. package/dist/cmd/cloud/deploy.js +36 -22
  32. package/dist/cmd/cloud/deploy.js.map +1 -1
  33. package/dist/cmd/cloud/queue/list.d.ts.map +1 -1
  34. package/dist/cmd/cloud/queue/list.js +10 -0
  35. package/dist/cmd/cloud/queue/list.js.map +1 -1
  36. package/dist/cmd/cloud/sandbox/list.d.ts.map +1 -1
  37. package/dist/cmd/cloud/sandbox/list.js +10 -0
  38. package/dist/cmd/cloud/sandbox/list.js.map +1 -1
  39. package/dist/cmd/cloud/sandbox/runtime/list.d.ts.map +1 -1
  40. package/dist/cmd/cloud/sandbox/runtime/list.js +10 -0
  41. package/dist/cmd/cloud/sandbox/runtime/list.js.map +1 -1
  42. package/dist/cmd/cloud/sandbox/snapshot/list.d.ts.map +1 -1
  43. package/dist/cmd/cloud/sandbox/snapshot/list.js +10 -0
  44. package/dist/cmd/cloud/sandbox/snapshot/list.js.map +1 -1
  45. package/dist/cmd/cloud/session/get.js +12 -12
  46. package/dist/cmd/cloud/session/get.js.map +1 -1
  47. package/dist/cmd/cloud/session/list.d.ts.map +1 -1
  48. package/dist/cmd/cloud/session/list.js +14 -4
  49. package/dist/cmd/cloud/session/list.js.map +1 -1
  50. package/dist/cmd/cloud/storage/list.d.ts.map +1 -1
  51. package/dist/cmd/cloud/storage/list.js +14 -1
  52. package/dist/cmd/cloud/storage/list.js.map +1 -1
  53. package/dist/cmd/cloud/stream/list.d.ts.map +1 -1
  54. package/dist/cmd/cloud/stream/list.js +10 -0
  55. package/dist/cmd/cloud/stream/list.js.map +1 -1
  56. package/dist/cmd/cloud/thread/list.d.ts.map +1 -1
  57. package/dist/cmd/cloud/thread/list.js +10 -0
  58. package/dist/cmd/cloud/thread/list.js.map +1 -1
  59. package/dist/cmd/project/domain/check.d.ts +2 -0
  60. package/dist/cmd/project/domain/check.d.ts.map +1 -0
  61. package/dist/cmd/project/domain/check.js +131 -0
  62. package/dist/cmd/project/domain/check.js.map +1 -0
  63. package/dist/cmd/project/domain/index.d.ts +2 -0
  64. package/dist/cmd/project/domain/index.d.ts.map +1 -0
  65. package/dist/cmd/project/domain/index.js +20 -0
  66. package/dist/cmd/project/domain/index.js.map +1 -0
  67. package/dist/cmd/project/hostname/get.d.ts +2 -0
  68. package/dist/cmd/project/hostname/get.d.ts.map +1 -0
  69. package/dist/cmd/project/hostname/get.js +50 -0
  70. package/dist/cmd/project/hostname/get.js.map +1 -0
  71. package/dist/cmd/project/hostname/index.d.ts +2 -0
  72. package/dist/cmd/project/hostname/index.d.ts.map +1 -0
  73. package/dist/cmd/project/hostname/index.js +18 -0
  74. package/dist/cmd/project/hostname/index.js.map +1 -0
  75. package/dist/cmd/project/hostname/set.d.ts +2 -0
  76. package/dist/cmd/project/hostname/set.d.ts.map +1 -0
  77. package/dist/cmd/project/hostname/set.js +100 -0
  78. package/dist/cmd/project/hostname/set.js.map +1 -0
  79. package/dist/cmd/project/index.d.ts.map +1 -1
  80. package/dist/cmd/project/index.js +12 -0
  81. package/dist/cmd/project/index.js.map +1 -1
  82. package/dist/index.d.ts +1 -1
  83. package/dist/index.d.ts.map +1 -1
  84. package/dist/index.js +1 -1
  85. package/dist/index.js.map +1 -1
  86. package/dist/steps.d.ts +9 -0
  87. package/dist/steps.d.ts.map +1 -1
  88. package/dist/steps.js +131 -71
  89. package/dist/steps.js.map +1 -1
  90. package/dist/tui.d.ts +2 -2
  91. package/dist/tui.d.ts.map +1 -1
  92. package/dist/tui.js +6 -4
  93. package/dist/tui.js.map +1 -1
  94. package/package.json +6 -6
  95. package/src/cmd/build/ast.ts +141 -5
  96. package/src/cmd/build/vite/config-loader.ts +1 -3
  97. package/src/cmd/build/vite/index.ts +4 -0
  98. package/src/cmd/build/vite/metadata-generator.ts +5 -1
  99. package/src/cmd/build/vite/route-discovery.ts +34 -1
  100. package/src/cmd/build/vite/vite-builder.ts +3 -0
  101. package/src/cmd/build/vite-bundler.ts +4 -0
  102. package/src/cmd/cloud/db/list.ts +14 -1
  103. package/src/cmd/cloud/deploy.ts +46 -21
  104. package/src/cmd/cloud/queue/list.ts +10 -0
  105. package/src/cmd/cloud/sandbox/list.ts +10 -0
  106. package/src/cmd/cloud/sandbox/runtime/list.ts +10 -0
  107. package/src/cmd/cloud/sandbox/snapshot/list.ts +10 -0
  108. package/src/cmd/cloud/session/get.ts +12 -12
  109. package/src/cmd/cloud/session/list.ts +28 -18
  110. package/src/cmd/cloud/storage/list.ts +14 -1
  111. package/src/cmd/cloud/stream/list.ts +18 -8
  112. package/src/cmd/cloud/thread/list.ts +15 -5
  113. package/src/cmd/project/domain/check.ts +146 -0
  114. package/src/cmd/project/domain/index.ts +20 -0
  115. package/src/cmd/project/hostname/get.ts +54 -0
  116. package/src/cmd/project/hostname/index.ts +18 -0
  117. package/src/cmd/project/hostname/set.ts +123 -0
  118. package/src/cmd/project/index.ts +12 -0
  119. package/src/index.ts +1 -1
  120. package/src/steps.ts +139 -74
  121. package/src/tui.ts +6 -4
@@ -46,6 +46,14 @@ export const listSubcommand = createSubcommand({
46
46
  'Show credentials in plain text (default: masked in terminal, unmasked in JSON)'
47
47
  ),
48
48
  nameOnly: z.boolean().optional().describe('Print the name only'),
49
+ sort: z
50
+ .enum(['name', 'created'])
51
+ .optional()
52
+ .describe('field to sort by (default: created)'),
53
+ direction: z
54
+ .enum(['asc', 'desc'])
55
+ .optional()
56
+ .describe('sort direction (default: desc)'),
49
57
  }),
50
58
  response: DBListResponseSchema,
51
59
  },
@@ -60,7 +68,12 @@ export const listSubcommand = createSubcommand({
60
68
  message: 'Fetching databases',
61
69
  clearOnSuccess: true,
62
70
  callback: async () => {
63
- return listOrgResources(catalystClient, { type: 'db', orgId: opts?.orgId });
71
+ return listOrgResources(catalystClient, {
72
+ type: 'db',
73
+ orgId: opts?.orgId,
74
+ sort: opts?.sort,
75
+ direction: opts?.direction,
76
+ });
64
77
  },
65
78
  });
66
79
 
@@ -22,6 +22,7 @@ import {
22
22
  stepSkipped,
23
23
  stepError,
24
24
  pauseStepUI,
25
+ StepInterruptError,
25
26
  type Step,
26
27
  type StepContext,
27
28
  } from '../../steps';
@@ -428,6 +429,13 @@ export const deploySubcommand = createSubcommand({
428
429
  }
429
430
  }
430
431
 
432
+ // Create a unified abort controller for the entire deploy flow
433
+ const deployAbortController = new AbortController();
434
+ const deployAbortHandler = () => {
435
+ deployAbortController.abort();
436
+ };
437
+ process.on('SIGINT', deployAbortHandler);
438
+
431
439
  // Start malware check async (runs in parallel with build)
432
440
  if (deployment) {
433
441
  malwareCheckPromise = (async () => {
@@ -444,7 +452,8 @@ export const deploySubcommand = createSubcommand({
444
452
  const result = await projectDeploymentMalwareCheck(
445
453
  catalystClient,
446
454
  deployment!.id,
447
- packages
455
+ packages,
456
+ deployAbortController.signal
448
457
  );
449
458
  logger.debug(
450
459
  'Malware check complete: action=%s, flagged=%d',
@@ -599,7 +608,7 @@ export const deploySubcommand = createSubcommand({
599
608
 
600
609
  {
601
610
  label: 'Build, Verify and Package',
602
- run: async () => {
611
+ run: async (stepCtx: StepContext) => {
603
612
  if (!deployment) {
604
613
  return stepError('deployment was null');
605
614
  }
@@ -636,6 +645,7 @@ export const deploySubcommand = createSubcommand({
636
645
  region: project.region,
637
646
  logger: ctx.logger,
638
647
  deploymentOptions: opts,
648
+ deploymentConfig: project.deployment,
639
649
  collector,
640
650
  });
641
651
  capturedOutput = [...capturedOutput, ...bundleResult.output];
@@ -643,7 +653,8 @@ export const deploySubcommand = createSubcommand({
643
653
  instructions = await projectDeploymentUpdate(
644
654
  apiClient,
645
655
  deployment.id,
646
- build
656
+ build,
657
+ stepCtx.signal
647
658
  );
648
659
  return stepSuccess(capturedOutput.length > 0 ? capturedOutput : undefined);
649
660
  } catch (ex) {
@@ -789,6 +800,7 @@ export const deploySubcommand = createSubcommand({
789
800
  'Content-Type': 'application/zip',
790
801
  },
791
802
  body: zipfile,
803
+ signal: stepCtx.signal,
792
804
  });
793
805
  ctx.logger.trace(`Upload response: ${resp.status}`);
794
806
  if (!resp.ok) {
@@ -876,6 +888,7 @@ export const deploySubcommand = createSubcommand({
876
888
  duplex: 'half',
877
889
  headers,
878
890
  body,
891
+ signal: stepCtx.signal,
879
892
  })
880
893
  );
881
894
  }
@@ -910,11 +923,15 @@ export const deploySubcommand = createSubcommand({
910
923
  },
911
924
  {
912
925
  label: 'Provision Deployment',
913
- run: async () => {
926
+ run: async (stepCtx: StepContext) => {
914
927
  if (!deployment) {
915
928
  return stepError('deployment was null');
916
929
  }
917
- complete = await projectDeploymentComplete(apiClient, deployment.id);
930
+ complete = await projectDeploymentComplete(
931
+ apiClient,
932
+ deployment.id,
933
+ stepCtx.signal
934
+ );
918
935
  return stepSuccess();
919
936
  },
920
937
  },
@@ -945,12 +962,7 @@ export const deploySubcommand = createSubcommand({
945
962
  const maxAttempts = 600;
946
963
  let attempts = 0;
947
964
 
948
- // Create abort controller to allow Ctrl+C to interrupt polling
949
- const pollAbortController = new AbortController();
950
- const sigintHandler = () => {
951
- pollAbortController.abort();
952
- };
953
- process.on('SIGINT', sigintHandler);
965
+ // Reuse the deploy abort controller for polling (already aborted on Ctrl+C)
954
966
 
955
967
  try {
956
968
  if (streamId) {
@@ -1014,7 +1026,7 @@ export const deploySubcommand = createSubcommand({
1014
1026
  // Poll for deployment status
1015
1027
  while (attempts < maxAttempts) {
1016
1028
  // Check if user pressed Ctrl+C
1017
- if (pollAbortController.signal.aborted) {
1029
+ if (deployAbortController.signal.aborted) {
1018
1030
  logStreamController.abort();
1019
1031
  throw new DeploymentCancelledError();
1020
1032
  }
@@ -1023,7 +1035,8 @@ export const deploySubcommand = createSubcommand({
1023
1035
  try {
1024
1036
  statusResult = await projectDeploymentStatus(
1025
1037
  apiClient,
1026
- deployment?.id ?? ''
1038
+ deployment?.id ?? '',
1039
+ deployAbortController.signal
1027
1040
  );
1028
1041
 
1029
1042
  logger.trace('status result: %s', statusResult);
@@ -1115,14 +1128,15 @@ export const deploySubcommand = createSubcommand({
1115
1128
  callback: async () => {
1116
1129
  while (attempts < maxAttempts) {
1117
1130
  // Check if user pressed Ctrl+C
1118
- if (pollAbortController.signal.aborted) {
1131
+ if (deployAbortController.signal.aborted) {
1119
1132
  throw new DeploymentCancelledError();
1120
1133
  }
1121
1134
 
1122
1135
  attempts++;
1123
1136
  statusResult = await projectDeploymentStatus(
1124
1137
  apiClient,
1125
- deployment?.id ?? ''
1138
+ deployment?.id ?? '',
1139
+ deployAbortController.signal
1126
1140
  );
1127
1141
 
1128
1142
  if (statusResult.state === 'completed') {
@@ -1172,7 +1186,7 @@ export const deploySubcommand = createSubcommand({
1172
1186
  tui.fatal('Deployment failed', ErrorCode.BUILD_FAILED);
1173
1187
  } finally {
1174
1188
  // Clean up signal handler
1175
- process.off('SIGINT', sigintHandler);
1189
+ process.off('SIGINT', deployAbortHandler);
1176
1190
  }
1177
1191
 
1178
1192
  // Show deployment URLs
@@ -1185,15 +1199,18 @@ export const deploySubcommand = createSubcommand({
1185
1199
  );
1186
1200
  }
1187
1201
  } else {
1202
+ // Prefer vanity URLs, fall back to hash-based
1203
+ const deploymentUrl =
1204
+ complete.publicUrls.vanityDeployment ?? complete.publicUrls.deployment;
1205
+ const latestUrl = complete.publicUrls.vanityProject ?? complete.publicUrls.latest;
1188
1206
  lines.push(
1189
1207
  `${tui.ICONS.arrow} ${
1190
- tui.bold(tui.padRight('Deployment:', 12)) +
1191
- tui.link(complete.publicUrls.deployment)
1208
+ tui.bold(tui.padRight('Deployment:', 12)) + tui.link(deploymentUrl)
1192
1209
  }`
1193
1210
  );
1194
1211
  lines.push(
1195
1212
  `${tui.ICONS.arrow} ${
1196
- tui.bold(tui.padRight('Project:', 12)) + tui.link(complete.publicUrls.latest)
1213
+ tui.bold(tui.padRight('Project:', 12)) + tui.link(latestUrl)
1197
1214
  }`
1198
1215
  );
1199
1216
  }
@@ -1222,20 +1239,28 @@ export const deploySubcommand = createSubcommand({
1222
1239
  logs,
1223
1240
  urls: complete?.publicUrls
1224
1241
  ? {
1225
- deployment: complete.publicUrls.deployment,
1226
- latest: complete.publicUrls.latest,
1242
+ deployment:
1243
+ complete.publicUrls.vanityDeployment ?? complete.publicUrls.deployment,
1244
+ latest: complete.publicUrls.vanityProject ?? complete.publicUrls.latest,
1227
1245
  custom: complete.publicUrls.custom,
1228
1246
  dashboard,
1229
1247
  }
1230
1248
  : undefined,
1231
1249
  };
1232
1250
  } catch (ex) {
1251
+ // Handle step interruption (Ctrl+C during build steps)
1252
+ if (ex instanceof StepInterruptError) {
1253
+ tui.warning('Deployment cancelled');
1254
+ process.exit(ex.exitCode);
1255
+ }
1233
1256
  collector.addGeneralError('deploy', String(ex), 'DEPLOY004');
1234
1257
  if (opts.reportFile) {
1235
1258
  await collector.forceWrite();
1236
1259
  }
1237
1260
  clearGlobalCollector();
1238
1261
  tui.fatal(`unexpected error trying to deploy project. ${ex}`);
1262
+ } finally {
1263
+ process.off('SIGINT', deployAbortHandler);
1239
1264
  }
1240
1265
  },
1241
1266
  });
@@ -34,6 +34,14 @@ export const listSubcommand = createCommand({
34
34
  orgId: z.string().optional().describe('filter by organization id'),
35
35
  limit: z.coerce.number().optional().describe('Maximum number of queues to return'),
36
36
  offset: z.coerce.number().optional().describe('Offset for pagination'),
37
+ sort: z
38
+ .enum(['name', 'created', 'updated'])
39
+ .optional()
40
+ .describe('field to sort by (default: created)'),
41
+ direction: z
42
+ .enum(['asc', 'desc'])
43
+ .optional()
44
+ .describe('sort direction (default: desc)'),
37
45
  }),
38
46
  response: QueueListResponseSchema,
39
47
  },
@@ -48,6 +56,8 @@ export const listSubcommand = createCommand({
48
56
  {
49
57
  limit: opts.limit,
50
58
  offset: opts.offset,
59
+ sort: opts.sort,
60
+ direction: opts.direction,
51
61
  },
52
62
  queueOptions
53
63
  );
@@ -75,6 +75,14 @@ export const listSubcommand = createCommand({
75
75
  all: z.boolean().optional().describe('List all sandboxes regardless of project context'),
76
76
  limit: z.number().optional().describe('Maximum number of results (default: 50, max: 100)'),
77
77
  offset: z.number().optional().describe('Pagination offset'),
78
+ sort: z
79
+ .enum(['name', 'created', 'updated', 'status'])
80
+ .optional()
81
+ .describe('field to sort by (default: created)'),
82
+ direction: z
83
+ .enum(['asc', 'desc'])
84
+ .optional()
85
+ .describe('sort direction (default: desc)'),
78
86
  }),
79
87
  response: SandboxListResponseSchema,
80
88
  },
@@ -94,6 +102,8 @@ export const listSubcommand = createCommand({
94
102
  status: opts.status,
95
103
  limit: opts.limit,
96
104
  offset: opts.offset,
105
+ sort: opts.sort,
106
+ direction: opts.direction,
97
107
  });
98
108
 
99
109
  // Check if results span multiple orgs
@@ -34,6 +34,14 @@ export const listSubcommand = createCommand({
34
34
  limit: z.number().optional().describe('Maximum number of results'),
35
35
  offset: z.number().optional().describe('Offset for pagination'),
36
36
  orgId: z.string().optional().describe('filter by organization id'),
37
+ sort: z
38
+ .enum(['name', 'created'])
39
+ .optional()
40
+ .describe('field to sort by (default: created)'),
41
+ direction: z
42
+ .enum(['asc', 'desc'])
43
+ .optional()
44
+ .describe('sort direction (default: desc)'),
37
45
  }),
38
46
  response: RuntimeListResponseSchema,
39
47
  },
@@ -47,6 +55,8 @@ export const listSubcommand = createCommand({
47
55
  orgId: effectiveOrgId,
48
56
  limit: opts.limit,
49
57
  offset: opts.offset,
58
+ sort: opts.sort,
59
+ direction: opts.direction,
50
60
  });
51
61
 
52
62
  if (!options.json) {
@@ -47,6 +47,14 @@ export const listSubcommand = createCommand({
47
47
  limit: z.number().optional().describe('Maximum number of results'),
48
48
  offset: z.number().optional().describe('Offset for pagination'),
49
49
  orgId: z.string().optional().describe('filter by organization id'),
50
+ sort: z
51
+ .enum(['name', 'created', 'size'])
52
+ .optional()
53
+ .describe('field to sort by (default: created)'),
54
+ direction: z
55
+ .enum(['asc', 'desc'])
56
+ .optional()
57
+ .describe('sort direction (default: desc)'),
50
58
  }),
51
59
  response: SnapshotListResponseSchema,
52
60
  },
@@ -61,6 +69,8 @@ export const listSubcommand = createCommand({
61
69
  limit: opts.limit,
62
70
  offset: opts.offset,
63
71
  orgId: effectiveOrgId,
72
+ sort: opts.sort,
73
+ direction: opts.direction,
64
74
  });
65
75
 
66
76
  if (!options.json) {
@@ -46,10 +46,10 @@ const SessionGetResponseSchema = z.object({
46
46
  pending: z.boolean().describe('Pending'),
47
47
  success: z.boolean().describe('Success'),
48
48
  error: z.string().nullable().describe('Error message'),
49
- method: z.string().describe('HTTP method'),
50
- url: z.string().describe('Request URL'),
51
- route_id: z.string().describe('Route ID'),
52
- thread_id: z.string().describe('Thread ID'),
49
+ method: z.string().nullable().describe('HTTP method'),
50
+ url: z.string().nullable().describe('Request URL'),
51
+ route_id: z.string().nullable().describe('Route ID'),
52
+ thread_id: z.string().nullable().describe('Thread ID'),
53
53
  agents: z
54
54
  .array(
55
55
  z.object({
@@ -148,10 +148,10 @@ export const getSubcommand = createSubcommand({
148
148
  pending: session.pending,
149
149
  success: session.success,
150
150
  error: session.error,
151
- method: session.method,
152
- url: session.url,
153
- route_id: session.route_id,
154
- thread_id: session.thread_id,
151
+ method: session.method ?? null,
152
+ url: session.url ?? null,
153
+ route_id: session.route_id ?? null,
154
+ thread_id: session.thread_id ?? null,
155
155
  agents: enriched.agents,
156
156
  eval_runs: enriched.evalRuns.map((run: EvalRun) => ({
157
157
  id: run.id,
@@ -183,8 +183,8 @@ export const getSubcommand = createSubcommand({
183
183
  if (session.duration != null && session.end_time != null) {
184
184
  tableData['Duration'] = `${(session.duration / 1_000_000).toFixed(0)}ms`;
185
185
  }
186
- tableData['Method'] = session.method;
187
- tableData['URL'] = tui.link(session.url, session.url);
186
+ tableData['Method'] = session.method ?? '-';
187
+ tableData['URL'] = session.url ? tui.link(session.url, session.url) : '-';
188
188
  tableData['Trigger'] = session.trigger;
189
189
  if (session.env !== 'production') {
190
190
  tableData['Environment'] = session.env;
@@ -204,9 +204,9 @@ export const getSubcommand = createSubcommand({
204
204
  tableData['Route'] =
205
205
  `${enriched.route.method.toUpperCase()} ${enriched.route.path} ${tui.muted(`(${enriched.route.id})`)}`;
206
206
  } else {
207
- tableData['Route ID'] = session.route_id;
207
+ tableData['Route ID'] = session.route_id ?? '-';
208
208
  }
209
- tableData['Thread ID'] = session.thread_id;
209
+ tableData['Thread ID'] = session.thread_id ?? '-';
210
210
 
211
211
  tui.table([tableData], Object.keys(tableData), { layout: 'vertical', padStart: ' ' });
212
212
 
@@ -12,8 +12,8 @@ const SessionListResponseSchema = z.array(
12
12
  created_at: z.string().describe('Creation timestamp'),
13
13
  success: z.boolean().describe('Whether the session succeeded'),
14
14
  duration: z.number().nullable().describe('Duration in nanoseconds'),
15
- method: z.string().describe('HTTP method'),
16
- url: z.string().describe('Request URL'),
15
+ method: z.string().nullable().describe('HTTP method'),
16
+ url: z.string().nullable().describe('Request URL'),
17
17
  trigger: z.string().describe('Trigger type'),
18
18
  env: z.string().describe('Environment'),
19
19
  })
@@ -91,6 +91,14 @@ export const listSubcommand = createSubcommand({
91
91
  success: z.coerce.boolean().optional().describe('Filter by success status (true/false)'),
92
92
  startAfter: z.string().optional().describe('Filter by start time after (ISO 8601)'),
93
93
  startBefore: z.string().optional().describe('Filter by start time before (ISO 8601)'),
94
+ sort: z
95
+ .enum(['created', 'updated', 'duration', 'startTime'])
96
+ .optional()
97
+ .describe('field to sort by (default: created)'),
98
+ direction: z
99
+ .enum(['asc', 'desc'])
100
+ .optional()
101
+ .describe('sort direction (default: desc)'),
94
102
  }),
95
103
  response: SessionListResponseSchema,
96
104
  },
@@ -109,20 +117,22 @@ export const listSubcommand = createSubcommand({
109
117
  const projectId = opts.all || opts.orgId ? undefined : opts.projectId || project?.projectId;
110
118
 
111
119
  try {
112
- const sessions = await sessionList(catalystClient, {
113
- count: opts.count,
114
- orgId: opts?.orgId,
115
- projectId,
116
- deploymentId: opts.deploymentId,
117
- trigger: opts.trigger,
118
- env: opts.env,
119
- devmode: opts.devmode,
120
- success: opts.success,
121
- threadId: opts.threadId,
122
- agentIdentifier: opts.agentIdentifier,
123
- startAfter: opts.startAfter,
124
- startBefore: opts.startBefore,
125
- });
120
+ const sessions = await sessionList(catalystClient, {
121
+ count: opts.count,
122
+ orgId: opts?.orgId,
123
+ projectId,
124
+ deploymentId: opts.deploymentId,
125
+ trigger: opts.trigger,
126
+ env: opts.env,
127
+ devmode: opts.devmode,
128
+ success: opts.success,
129
+ threadId: opts.threadId,
130
+ agentIdentifier: opts.agentIdentifier,
131
+ startAfter: opts.startAfter,
132
+ startBefore: opts.startBefore,
133
+ sort: opts.sort,
134
+ direction: opts.direction,
135
+ });
126
136
 
127
137
  const result = sessions.map((s) => ({
128
138
  id: s.id,
@@ -146,13 +156,13 @@ export const listSubcommand = createSubcommand({
146
156
  }
147
157
 
148
158
  const tableData = sessions.map((s) => {
149
- const urlPath = new URL(s.url).pathname;
159
+ const urlPath = s.url ? new URL(s.url).pathname : '-';
150
160
  return {
151
161
  ID: s.id,
152
162
  Created: new Date(s.created_at).toLocaleString(),
153
163
  Success: s.success ? '✓' : '✗',
154
164
  Duration: s.duration ? `${(s.duration / 1_000_000).toFixed(0)}ms` : '-',
155
- Method: s.method,
165
+ Method: s.method ?? '-',
156
166
  Path: urlPath.length > 50 ? urlPath.substring(0, 47) + '...' : urlPath,
157
167
  Trigger: s.trigger,
158
168
  Env: s.env,
@@ -77,6 +77,14 @@ export const listSubcommand = createSubcommand({
77
77
  'Show credentials in plain text (default: masked in terminal, unmasked in JSON)'
78
78
  ),
79
79
  nameOnly: z.boolean().optional().describe('Print the name only'),
80
+ sort: z
81
+ .enum(['name', 'created'])
82
+ .optional()
83
+ .describe('field to sort by (default: created)'),
84
+ direction: z
85
+ .enum(['asc', 'desc'])
86
+ .optional()
87
+ .describe('sort direction (default: desc)'),
80
88
  }),
81
89
  response: StorageListResponseSchema,
82
90
  },
@@ -95,7 +103,12 @@ export const listSubcommand = createSubcommand({
95
103
  message: 'Fetching storage',
96
104
  clearOnSuccess: true,
97
105
  callback: async () => {
98
- return listOrgResources(catalystClient, { type: 's3', orgId: opts?.orgId });
106
+ return listOrgResources(catalystClient, {
107
+ type: 's3',
108
+ orgId: opts?.orgId,
109
+ sort: opts?.sort,
110
+ direction: opts?.direction,
111
+ });
99
112
  },
100
113
  });
101
114
 
@@ -67,6 +67,14 @@ export const listSubcommand = createCommand({
67
67
  .describe('filter by metadata (format: key=value or key1=value1,key2=value2)'),
68
68
  projectId: z.string().optional().describe('filter by project ID'),
69
69
  orgId: z.string().optional().describe('filter by organization ID'),
70
+ sort: z
71
+ .enum(['name', 'created', 'updated', 'size'])
72
+ .optional()
73
+ .describe('field to sort by (default: created)'),
74
+ direction: z
75
+ .enum(['asc', 'desc'])
76
+ .optional()
77
+ .describe('sort direction (default: desc)'),
70
78
  }),
71
79
  response: ListStreamsResponseSchema,
72
80
  },
@@ -120,14 +128,16 @@ export const listSubcommand = createCommand({
120
128
  }
121
129
 
122
130
  try {
123
- const result = await streamList(apiClient, {
124
- limit: opts.size,
125
- offset: opts.offset,
126
- namespace: opts.namespace,
127
- metadata: metadataFilter,
128
- projectId,
129
- orgId: opts.orgId,
130
- });
131
+ const result = await streamList(apiClient, {
132
+ limit: opts.size,
133
+ offset: opts.offset,
134
+ namespace: opts.namespace,
135
+ metadata: metadataFilter,
136
+ projectId,
137
+ orgId: opts.orgId,
138
+ sort: opts.sort,
139
+ direction: opts.direction,
140
+ });
131
141
 
132
142
  if (options.json) {
133
143
  console.log(JSON.stringify(result, null, 2));
@@ -63,6 +63,14 @@ export const listSubcommand = createSubcommand({
63
63
  orgId: z.string().optional().describe('Filter by organization ID'),
64
64
  projectId: z.string().optional().describe('Filter by project ID'),
65
65
  all: z.boolean().optional().describe('List all threads regardless of project context'),
66
+ sort: z
67
+ .enum(['created', 'updated'])
68
+ .optional()
69
+ .describe('field to sort by (default: created)'),
70
+ direction: z
71
+ .enum(['asc', 'desc'])
72
+ .optional()
73
+ .describe('sort direction (default: desc)'),
66
74
  }),
67
75
  response: ThreadListResponseSchema,
68
76
  },
@@ -78,11 +86,13 @@ export const listSubcommand = createSubcommand({
78
86
  const orgId = opts.orgId;
79
87
 
80
88
  try {
81
- const threads = await threadList(catalystClient, {
82
- count: opts.count,
83
- orgId,
84
- projectId,
85
- });
89
+ const threads = await threadList(catalystClient, {
90
+ count: opts.count,
91
+ orgId,
92
+ projectId,
93
+ sort: opts.sort,
94
+ direction: opts.direction,
95
+ });
86
96
 
87
97
  const result = threads.map((t: Thread) => ({
88
98
  id: t.id,