@agentuity/server 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 (92) hide show
  1. package/dist/api/org/resources.d.ts +10 -0
  2. package/dist/api/org/resources.d.ts.map +1 -1
  3. package/dist/api/org/resources.js +12 -0
  4. package/dist/api/org/resources.js.map +1 -1
  5. package/dist/api/project/deploy.d.ts +7 -3
  6. package/dist/api/project/deploy.d.ts.map +1 -1
  7. package/dist/api/project/deploy.js +20 -8
  8. package/dist/api/project/deploy.js.map +1 -1
  9. package/dist/api/project/get.d.ts +2 -0
  10. package/dist/api/project/get.d.ts.map +1 -1
  11. package/dist/api/project/get.js +1 -0
  12. package/dist/api/project/get.js.map +1 -1
  13. package/dist/api/project/hostname.d.ts +25 -0
  14. package/dist/api/project/hostname.d.ts.map +1 -0
  15. package/dist/api/project/hostname.js +37 -0
  16. package/dist/api/project/hostname.js.map +1 -0
  17. package/dist/api/project/index.d.ts +1 -0
  18. package/dist/api/project/index.d.ts.map +1 -1
  19. package/dist/api/project/index.js +1 -0
  20. package/dist/api/project/index.js.map +1 -1
  21. package/dist/api/project/malware.d.ts +1 -1
  22. package/dist/api/project/malware.d.ts.map +1 -1
  23. package/dist/api/project/malware.js +2 -2
  24. package/dist/api/project/malware.js.map +1 -1
  25. package/dist/api/queue/queues.d.ts.map +1 -1
  26. package/dist/api/queue/queues.js +6 -0
  27. package/dist/api/queue/queues.js.map +1 -1
  28. package/dist/api/queue/types.d.ts +10 -0
  29. package/dist/api/queue/types.d.ts.map +1 -1
  30. package/dist/api/queue/types.js +4 -0
  31. package/dist/api/queue/types.js.map +1 -1
  32. package/dist/api/sandbox/cli-list.d.ts +8 -0
  33. package/dist/api/sandbox/cli-list.d.ts.map +1 -1
  34. package/dist/api/sandbox/cli-list.js +5 -1
  35. package/dist/api/sandbox/cli-list.js.map +1 -1
  36. package/dist/api/sandbox/client.d.ts.map +1 -1
  37. package/dist/api/sandbox/client.js +3 -1
  38. package/dist/api/sandbox/client.js.map +1 -1
  39. package/dist/api/sandbox/execute.d.ts.map +1 -1
  40. package/dist/api/sandbox/execute.js +23 -2
  41. package/dist/api/sandbox/execute.js.map +1 -1
  42. package/dist/api/sandbox/index.d.ts +1 -1
  43. package/dist/api/sandbox/index.d.ts.map +1 -1
  44. package/dist/api/sandbox/index.js +1 -1
  45. package/dist/api/sandbox/index.js.map +1 -1
  46. package/dist/api/sandbox/list.d.ts.map +1 -1
  47. package/dist/api/sandbox/list.js +6 -0
  48. package/dist/api/sandbox/list.js.map +1 -1
  49. package/dist/api/sandbox/runtime.d.ts.map +1 -1
  50. package/dist/api/sandbox/runtime.js +6 -0
  51. package/dist/api/sandbox/runtime.js.map +1 -1
  52. package/dist/api/sandbox/snapshot.d.ts +5 -0
  53. package/dist/api/sandbox/snapshot.d.ts.map +1 -1
  54. package/dist/api/sandbox/snapshot.js +4 -2
  55. package/dist/api/sandbox/snapshot.js.map +1 -1
  56. package/dist/api/sandbox/util.d.ts +34 -1
  57. package/dist/api/sandbox/util.d.ts.map +1 -1
  58. package/dist/api/sandbox/util.js +23 -0
  59. package/dist/api/sandbox/util.js.map +1 -1
  60. package/dist/api/session/get.d.ts +8 -8
  61. package/dist/api/session/list.d.ts +19 -12
  62. package/dist/api/session/list.d.ts.map +1 -1
  63. package/dist/api/session/list.js +13 -6
  64. package/dist/api/session/list.js.map +1 -1
  65. package/dist/api/stream/list.d.ts +9 -0
  66. package/dist/api/stream/list.d.ts.map +1 -1
  67. package/dist/api/stream/list.js +4 -0
  68. package/dist/api/stream/list.js.map +1 -1
  69. package/dist/api/thread/list.d.ts +6 -0
  70. package/dist/api/thread/list.d.ts.map +1 -1
  71. package/dist/api/thread/list.js +9 -2
  72. package/dist/api/thread/list.js.map +1 -1
  73. package/package.json +4 -4
  74. package/src/api/org/resources.ts +23 -0
  75. package/src/api/project/deploy.ts +33 -11
  76. package/src/api/project/get.ts +1 -0
  77. package/src/api/project/hostname.ts +73 -0
  78. package/src/api/project/index.ts +1 -0
  79. package/src/api/project/malware.ts +5 -2
  80. package/src/api/queue/queues.ts +6 -0
  81. package/src/api/queue/types.ts +6 -0
  82. package/src/api/sandbox/cli-list.ts +11 -1
  83. package/src/api/sandbox/client.ts +3 -1
  84. package/src/api/sandbox/execute.ts +31 -8
  85. package/src/api/sandbox/index.ts +1 -0
  86. package/src/api/sandbox/list.ts +6 -0
  87. package/src/api/sandbox/runtime.ts +6 -0
  88. package/src/api/sandbox/snapshot.ts +4 -2
  89. package/src/api/sandbox/util.ts +27 -0
  90. package/src/api/session/list.ts +22 -6
  91. package/src/api/stream/list.ts +11 -0
  92. package/src/api/thread/list.ts +13 -2
@@ -0,0 +1,73 @@
1
+ import { z } from 'zod';
2
+ import { type APIClient, APIResponseSchema } from '../api';
3
+ import { ProjectResponseError } from './util';
4
+
5
+ // --- GET hostname ---
6
+
7
+ export const ProjectHostnameGetRequestSchema = z.object({
8
+ projectId: z.string().describe('the project id'),
9
+ });
10
+
11
+ const HostnameGetDataSchema = z.object({
12
+ hostname: z.string().nullable(),
13
+ url: z.string().nullable(),
14
+ });
15
+
16
+ const ProjectHostnameGetResponseSchema = APIResponseSchema(HostnameGetDataSchema);
17
+
18
+ type ProjectHostnameGetRequest = z.infer<typeof ProjectHostnameGetRequestSchema>;
19
+ type ProjectHostnameGetResponse = z.infer<typeof ProjectHostnameGetResponseSchema>;
20
+
21
+ export type ProjectHostnameGetResult = z.infer<typeof HostnameGetDataSchema>;
22
+
23
+ export async function projectHostnameGet(
24
+ client: APIClient,
25
+ request: ProjectHostnameGetRequest
26
+ ): Promise<ProjectHostnameGetResult> {
27
+ const resp = await client.get<ProjectHostnameGetResponse>(
28
+ `/cli/project/${request.projectId}/hostname`,
29
+ ProjectHostnameGetResponseSchema
30
+ );
31
+
32
+ if (resp.success) {
33
+ return resp.data;
34
+ }
35
+
36
+ throw new ProjectResponseError({ message: resp.message });
37
+ }
38
+
39
+ // --- SET hostname ---
40
+
41
+ export const ProjectHostnameSetRequestSchema = z.object({
42
+ projectId: z.string().describe('the project id'),
43
+ hostname: z.string().describe('the vanity hostname to set'),
44
+ });
45
+
46
+ const HostnameSetDataSchema = z.object({
47
+ hostname: z.string(),
48
+ url: z.string(),
49
+ });
50
+
51
+ const ProjectHostnameSetResponseSchema = APIResponseSchema(HostnameSetDataSchema);
52
+
53
+ type ProjectHostnameSetRequest = z.infer<typeof ProjectHostnameSetRequestSchema>;
54
+ type ProjectHostnameSetResponse = z.infer<typeof ProjectHostnameSetResponseSchema>;
55
+
56
+ export type ProjectHostnameSetResult = z.infer<typeof HostnameSetDataSchema>;
57
+
58
+ export async function projectHostnameSet(
59
+ client: APIClient,
60
+ request: ProjectHostnameSetRequest
61
+ ): Promise<ProjectHostnameSetResult> {
62
+ const resp = await client.put<ProjectHostnameSetResponse>(
63
+ `/cli/project/${request.projectId}/hostname`,
64
+ { hostname: request.hostname },
65
+ ProjectHostnameSetResponseSchema
66
+ );
67
+
68
+ if (resp.success) {
69
+ return resp.data;
70
+ }
71
+
72
+ throw new ProjectResponseError({ message: resp.message });
73
+ }
@@ -7,6 +7,7 @@ export * from './env-delete';
7
7
  export * from './env-update';
8
8
  export * from './exists';
9
9
  export * from './get';
10
+ export * from './hostname';
10
11
  export * from './list';
11
12
  export * from './malware';
12
13
  export * from './update-region';
@@ -41,7 +41,8 @@ export type MalwareCheckResult = z.infer<typeof MalwareCheckResultSchema>;
41
41
  export async function projectDeploymentMalwareCheck(
42
42
  client: APIClient,
43
43
  deploymentId: string,
44
- packages: PackageRef[]
44
+ packages: PackageRef[],
45
+ signal?: AbortSignal
45
46
  ): Promise<MalwareCheckResult> {
46
47
  const resp = await client.request<z.infer<typeof MalwareCheckResponseSchema>>(
47
48
  'POST',
@@ -50,7 +51,9 @@ export async function projectDeploymentMalwareCheck(
50
51
  {
51
52
  ecosystem: 'npm',
52
53
  packages,
53
- }
54
+ },
55
+ undefined,
56
+ signal
54
57
  );
55
58
 
56
59
  if (!resp.success) {
@@ -201,6 +201,12 @@ export async function listQueues(
201
201
  if (params?.offset !== undefined) {
202
202
  searchParams.set('offset', String(params.offset));
203
203
  }
204
+ if (params?.sort) {
205
+ searchParams.set('sort', params.sort);
206
+ }
207
+ if (params?.direction) {
208
+ searchParams.set('direction', params.direction);
209
+ }
204
210
 
205
211
  const queryString = searchParams.toString();
206
212
  const url = queueApiPathWithQuery('list', queryString || undefined);
@@ -18,6 +18,8 @@ export const QueueTypeSchema = z.enum(['worker', 'pubsub']);
18
18
  */
19
19
  export type QueueType = z.infer<typeof QueueTypeSchema>;
20
20
 
21
+ export type QueueSortField = 'name' | 'created' | 'updated';
22
+
21
23
  /**
22
24
  * Base queue settings schema without defaults - used for partial updates.
23
25
  *
@@ -476,6 +478,10 @@ export const ListQueuesRequestSchema = z.object({
476
478
  limit: z.number().optional(),
477
479
  /** Number of queues to skip for pagination. */
478
480
  offset: z.number().optional(),
481
+ /** Field to sort by. */
482
+ sort: z.enum(['name', 'created', 'updated']).optional(),
483
+ /** Sort direction (asc or desc). */
484
+ direction: z.enum(['asc', 'desc']).optional(),
479
485
  });
480
486
 
481
487
  /** Request type for listing queues. */
@@ -46,6 +46,14 @@ export interface CLISandboxListOptions {
46
46
  * Number of sandboxes to skip for pagination
47
47
  */
48
48
  offset?: number;
49
+ /**
50
+ * Field to sort by
51
+ */
52
+ sort?: string;
53
+ /**
54
+ * Sort direction (default: 'desc')
55
+ */
56
+ direction?: 'asc' | 'desc';
49
57
  }
50
58
 
51
59
  /**
@@ -75,7 +83,7 @@ export async function cliSandboxList(
75
83
  client: APIClient,
76
84
  options: CLISandboxListOptions = {}
77
85
  ): Promise<CLISandboxListData> {
78
- const { projectId, orgId, status, limit, offset } = options;
86
+ const { projectId, orgId, status, limit, offset, sort, direction } = options;
79
87
  const params = new URLSearchParams();
80
88
 
81
89
  if (projectId) params.set('projectId', projectId);
@@ -83,6 +91,8 @@ export async function cliSandboxList(
83
91
  if (status) params.set('status', status);
84
92
  if (limit !== undefined) params.set('limit', limit.toString());
85
93
  if (offset !== undefined) params.set('offset', offset.toString());
94
+ if (sort) params.set('sort', sort);
95
+ if (direction) params.set('direction', direction);
86
96
 
87
97
  const queryString = params.toString();
88
98
  const resp = await client.request<CLISandboxListResponse>(
@@ -244,7 +244,9 @@ export class SandboxClient {
244
244
 
245
245
  const logger = options.logger ?? new ConsoleLogger('warn');
246
246
 
247
- this.#client = new APIClient(url, logger, apiKey ?? '', {});
247
+ // Disable retries for sandbox operations - 409 Conflict means sandbox is busy,
248
+ // not a retryable rate limit. Retrying would waste ~360s (4 attempts × 90s timeout).
249
+ this.#client = new APIClient(url, logger, apiKey ?? '', { maxRetries: 0 });
248
250
  this.#orgId = options.orgId;
249
251
  this.#apiKey = apiKey;
250
252
  this.#region = region;
@@ -1,7 +1,7 @@
1
1
  import type { ExecuteOptions, Execution, ExecutionStatus } from '@agentuity/core';
2
2
  import { z } from 'zod';
3
3
  import { type APIClient, APIResponseSchema } from '../api';
4
- import { API_VERSION, throwSandboxError } from './util';
4
+ import { API_VERSION, SandboxBusyError, throwSandboxError } from './util';
5
5
 
6
6
  export const ExecuteRequestSchema = z
7
7
  .object({
@@ -86,13 +86,36 @@ export async function sandboxExecute(
86
86
  const queryString = queryParams.toString();
87
87
  const url = `/sandbox/${API_VERSION}/${sandboxId}/execute${queryString ? `?${queryString}` : ''}`;
88
88
 
89
- const resp = await client.post<z.infer<typeof ExecuteResponseSchema>>(
90
- url,
91
- body,
92
- ExecuteResponseSchema,
93
- ExecuteRequestSchema,
94
- signal ?? options.signal
95
- );
89
+ let resp: z.infer<typeof ExecuteResponseSchema>;
90
+ try {
91
+ resp = await client.post<z.infer<typeof ExecuteResponseSchema>>(
92
+ url,
93
+ body,
94
+ ExecuteResponseSchema,
95
+ ExecuteRequestSchema,
96
+ signal ?? options.signal
97
+ );
98
+ } catch (error: unknown) {
99
+ // Detect 409 Conflict (sandbox busy) and throw a specific error.
100
+ // The sandbox API client is configured with maxRetries: 0 to fail fast
101
+ // when sandbox is busy (retrying wouldn't help - sandbox is still busy).
102
+ // Convert APIErrorResponse with status 409 to SandboxBusyError for clarity.
103
+ if (
104
+ error &&
105
+ typeof error === 'object' &&
106
+ '_tag' in error &&
107
+ (error as { _tag: string })._tag === 'APIErrorResponse' &&
108
+ 'status' in error &&
109
+ (error as { status: number }).status === 409
110
+ ) {
111
+ throw new SandboxBusyError({
112
+ message:
113
+ 'Sandbox is currently busy executing another command. Please wait for the current execution to complete before submitting a new one.',
114
+ sandboxId,
115
+ });
116
+ }
117
+ throw error;
118
+ }
96
119
 
97
120
  if (resp.success) {
98
121
  return {
@@ -177,6 +177,7 @@ export {
177
177
  ExecutionCancelledError,
178
178
  ExecutionNotFoundError,
179
179
  ExecutionTimeoutError,
180
+ SandboxBusyError,
180
181
  SandboxNotFoundError,
181
182
  SandboxResponseError,
182
183
  SandboxTerminatedError,
@@ -157,6 +157,12 @@ export async function sandboxList(
157
157
  if (params?.offset !== undefined) {
158
158
  queryParams.set('offset', params.offset.toString());
159
159
  }
160
+ if (params?.sort) {
161
+ queryParams.set('sort', params.sort);
162
+ }
163
+ if (params?.direction) {
164
+ queryParams.set('direction', params.direction);
165
+ }
160
166
  if (params?.deletedOnly) {
161
167
  queryParams.set('deletedOnly', 'true');
162
168
  }
@@ -62,6 +62,12 @@ export async function runtimeList(
62
62
  if (params?.offset !== undefined) {
63
63
  queryParams.set('offset', params.offset.toString());
64
64
  }
65
+ if (params?.sort) {
66
+ queryParams.set('sort', params.sort);
67
+ }
68
+ if (params?.direction) {
69
+ queryParams.set('direction', params.direction);
70
+ }
65
71
 
66
72
  const queryString = queryParams.toString();
67
73
  const url = `/sandbox/${API_VERSION}/runtimes${queryString ? `?${queryString}` : ''}`;
@@ -162,6 +162,8 @@ const _SnapshotListParamsSchema = z
162
162
  sandboxId: z.string().optional().describe('Filter by sandbox ID'),
163
163
  limit: z.number().optional().describe('Maximum number of snapshots to return'),
164
164
  offset: z.number().optional().describe('Number of snapshots to skip'),
165
+ sort: z.string().optional().describe('Field to sort by'),
166
+ direction: z.enum(['asc', 'desc']).optional().describe('Sort direction (asc or desc)'),
165
167
  orgId: z.string().optional().describe('Organization ID'),
166
168
  })
167
169
  .describe('Parameters for listing snapshots');
@@ -303,8 +305,8 @@ export async function snapshotList(
303
305
  client: APIClient,
304
306
  params: SnapshotListParams = {}
305
307
  ): Promise<SnapshotListResponse> {
306
- const { sandboxId, limit, offset, orgId } = params;
307
- const queryString = buildQueryString({ sandboxId, limit, offset, orgId });
308
+ const { sandboxId, limit, offset, sort, direction, orgId } = params;
309
+ const queryString = buildQueryString({ sandboxId, limit, offset, sort, direction, orgId });
308
310
  const url = `/sandbox/${API_VERSION}/snapshots${queryString}`;
309
311
 
310
312
  const resp = await client.get<z.infer<typeof SnapshotListResponseSchema>>(
@@ -12,6 +12,7 @@ interface WritableWithDrain extends EventEmitter {
12
12
  export type SandboxErrorCode =
13
13
  | 'SANDBOX_NOT_FOUND'
14
14
  | 'SANDBOX_TERMINATED'
15
+ | 'SANDBOX_BUSY'
15
16
  | 'EXECUTION_NOT_FOUND'
16
17
  | 'EXECUTION_TIMEOUT'
17
18
  | 'EXECUTION_CANCELLED'
@@ -69,6 +70,29 @@ export const SandboxTerminatedError = StructuredError('SandboxTerminatedError')<
69
70
  sandboxId: string;
70
71
  }>();
71
72
 
73
+ /**
74
+ * Error thrown when a sandbox is currently busy executing another command.
75
+ *
76
+ * This typically occurs when a second execute request is sent before the
77
+ * previous execution has completed. Sandbox executions are serialized -
78
+ * wait for the current execution to complete before sending a new one.
79
+ *
80
+ * @example
81
+ * ```typescript
82
+ * try {
83
+ * await sandbox.execute({ command: ['ls'] });
84
+ * } catch (error) {
85
+ * if (error._tag === 'SandboxBusyError') {
86
+ * console.error('Sandbox is busy, waiting for current execution to finish');
87
+ * // Wait and retry, or use executionGet with long-polling to wait for completion
88
+ * }
89
+ * }
90
+ * ```
91
+ */
92
+ export const SandboxBusyError = StructuredError('SandboxBusyError')<{
93
+ sandboxId?: string;
94
+ }>();
95
+
72
96
  /**
73
97
  * Error thrown when an execution is not found.
74
98
  *
@@ -164,6 +188,7 @@ export interface SandboxErrorContext {
164
188
  * @param context - Context about the operation (sandbox ID, execution ID, etc.)
165
189
  * @throws {SandboxNotFoundError} When code is 'SANDBOX_NOT_FOUND'
166
190
  * @throws {SandboxTerminatedError} When code is 'SANDBOX_TERMINATED'
191
+ * @throws {SandboxBusyError} When code is 'SANDBOX_BUSY'
167
192
  * @throws {ExecutionNotFoundError} When code is 'EXECUTION_NOT_FOUND'
168
193
  * @throws {ExecutionTimeoutError} When code is 'EXECUTION_TIMEOUT'
169
194
  * @throws {ExecutionCancelledError} When code is 'EXECUTION_CANCELLED'
@@ -182,6 +207,8 @@ export function throwSandboxError(
182
207
  throw new SandboxNotFoundError({ message: resp.message, sandboxId: sandboxId ?? '' });
183
208
  case 'SANDBOX_TERMINATED':
184
209
  throw new SandboxTerminatedError({ message: resp.message, sandboxId: sandboxId ?? '' });
210
+ case 'SANDBOX_BUSY':
211
+ throw new SandboxBusyError({ message: resp.message, sandboxId });
185
212
  case 'EXECUTION_NOT_FOUND':
186
213
  throw new ExecutionNotFoundError({
187
214
  message: resp.message,
@@ -1,3 +1,4 @@
1
+ import type { SortDirection } from '@agentuity/core';
1
2
  import { z } from 'zod';
2
3
  import { APIClient, APIResponseSchema } from '../api';
3
4
  import { SessionResponseError } from './util';
@@ -32,10 +33,10 @@ const SessionSchema = z.object({
32
33
  llm_prompt_token_count: z.number().nullable().describe('the LLM prompt token count'),
33
34
  llm_completion_token_count: z.number().nullable().describe('the LLM completion token count'),
34
35
  total_cost: z.number().nullable().describe('the total cost'),
35
- method: z.string().describe('the HTTP method'),
36
- url: z.string().describe('the request URL'),
37
- route_id: z.string().describe('the route id'),
38
- thread_id: z.string().describe('the thread id'),
36
+ method: z.string().nullable().describe('the HTTP method'),
37
+ url: z.string().nullable().describe('the request URL'),
38
+ route_id: z.string().nullable().describe('the route id'),
39
+ thread_id: z.string().nullable().describe('the thread id'),
39
40
  timeline: z.unknown().nullable().optional().describe('the session timeline tree'),
40
41
  user_data: z.string().nullable().optional().describe('the user data as JSON'),
41
42
  });
@@ -50,8 +51,15 @@ export type SessionListResponse = z.infer<typeof SessionListResponseSchema>;
50
51
  export type SessionList = z.infer<typeof SessionListResponse>;
51
52
  export type Session = z.infer<typeof SessionSchema>;
52
53
 
54
+ export type SessionSortField = 'created' | 'updated' | 'duration' | 'startTime';
55
+
53
56
  export interface SessionListOptions {
57
+ /** @deprecated Use `limit` instead. Will be removed in a future version. */
54
58
  count?: number;
59
+ limit?: number;
60
+ offset?: number;
61
+ sort?: SessionSortField;
62
+ direction?: SortDirection;
55
63
  orgId?: string;
56
64
  projectId?: string;
57
65
  deploymentId?: string;
@@ -78,7 +86,11 @@ export async function sessionList(
78
86
  options: SessionListOptions = {}
79
87
  ): Promise<SessionList> {
80
88
  const {
81
- count = 10,
89
+ count,
90
+ limit,
91
+ offset,
92
+ sort,
93
+ direction,
82
94
  orgId,
83
95
  projectId,
84
96
  deploymentId,
@@ -92,12 +104,16 @@ export async function sessionList(
92
104
  startBefore,
93
105
  metadata,
94
106
  } = options;
95
- const params = new URLSearchParams({ count: count.toString() });
107
+ const resolvedLimit = limit ?? count ?? 10;
108
+ const params = new URLSearchParams({ limit: resolvedLimit.toString() });
96
109
  if (orgId) params.set('orgId', orgId);
97
110
  if (projectId) params.set('projectId', projectId);
98
111
  if (deploymentId) params.set('deploymentId', deploymentId);
99
112
  if (trigger) params.set('trigger', trigger);
100
113
  if (env) params.set('env', env);
114
+ if (offset !== undefined) params.set('offset', offset.toString());
115
+ if (sort) params.set('sort', sort);
116
+ if (direction) params.set('direction', direction);
101
117
  if (devmode !== undefined) params.set('devmode', devmode.toString());
102
118
  if (success !== undefined) params.set('success', success.toString());
103
119
  if (threadId) params.set('threadId', threadId);
@@ -1,3 +1,4 @@
1
+ import type { SortDirection } from '@agentuity/core';
1
2
  import { z } from 'zod';
2
3
  import { type APIClient, APIResponseSchema } from '../api';
3
4
  import { StreamResponseError } from './util';
@@ -50,6 +51,14 @@ export interface StreamListOptions {
50
51
  * Filter by metadata key-value pairs
51
52
  */
52
53
  metadata?: Record<string, string>;
54
+ /**
55
+ * Field to sort by
56
+ */
57
+ sort?: string;
58
+ /**
59
+ * Sort direction (default: 'desc')
60
+ */
61
+ direction?: SortDirection;
53
62
  }
54
63
 
55
64
  /**
@@ -95,6 +104,8 @@ export async function streamList(
95
104
  if (metadata && Object.keys(metadata).length > 0) {
96
105
  params.set('metadata', JSON.stringify(metadata));
97
106
  }
107
+ if (options.sort) params.set('sort', options.sort);
108
+ if (options.direction) params.set('direction', options.direction);
98
109
 
99
110
  const queryString = params.toString();
100
111
  const resp = await client.request<StreamListResponse>(
@@ -1,3 +1,4 @@
1
+ import type { SortDirection } from '@agentuity/core';
1
2
  import { z } from 'zod';
2
3
  import { APIClient, APIResponseSchema } from '../api';
3
4
  import { ThreadResponseError } from './util';
@@ -27,8 +28,14 @@ export type ThreadListResponse = z.infer<typeof ThreadListResponseSchema>;
27
28
  export type ThreadList = z.infer<typeof ThreadListResponseData>;
28
29
  export type Thread = z.infer<typeof ThreadSchema>;
29
30
 
31
+ export type ThreadSortField = 'created' | 'updated';
32
+
30
33
  export interface ThreadListOptions {
31
34
  count?: number;
35
+ limit?: number;
36
+ offset?: number;
37
+ sort?: ThreadSortField;
38
+ direction?: SortDirection;
32
39
  orgId?: string;
33
40
  projectId?: string;
34
41
  metadata?: Record<string, unknown>;
@@ -45,10 +52,14 @@ export async function threadList(
45
52
  client: APIClient,
46
53
  options: ThreadListOptions = {}
47
54
  ): Promise<ThreadList> {
48
- const { count = 10, orgId, projectId, metadata } = options;
49
- const params = new URLSearchParams({ count: count.toString() });
55
+ const { limit, count, offset, sort, direction, orgId, projectId, metadata } = options;
56
+ const resolvedLimit = limit ?? count ?? 10;
57
+ const params = new URLSearchParams({ limit: resolvedLimit.toString() });
50
58
  if (orgId) params.set('orgId', orgId);
51
59
  if (projectId) params.set('projectId', projectId);
60
+ if (offset !== undefined) params.set('offset', offset.toString());
61
+ if (sort) params.set('sort', sort);
62
+ if (direction) params.set('direction', direction);
52
63
  if (metadata) params.set('metadata', JSON.stringify(metadata));
53
64
 
54
65
  const resp = await client.request<ThreadListResponse>(