@agentuity/server 1.0.23 → 1.0.25

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.
@@ -0,0 +1,179 @@
1
+ import { z } from 'zod';
2
+ import type { z as zType } from 'zod';
3
+ import { type APIClient, APIResponseSchema, APIResponseSchemaNoData } from '../api';
4
+ import { API_VERSION, throwSandboxError } from './util';
5
+
6
+ // --- Schemas ---
7
+
8
+ export const DiskCheckpointInfoSchema = z.object({
9
+ id: z.string().describe('Globally unique checkpoint ID (ckpt_xxx)'),
10
+ name: z.string().describe('User-provided checkpoint name'),
11
+ createdAt: z.string().describe('ISO timestamp of creation'),
12
+ parent: z.string().describe('Parent checkpoint name (empty for base)'),
13
+ });
14
+
15
+ export type DiskCheckpointInfo = z.infer<typeof DiskCheckpointInfoSchema>;
16
+
17
+ const CreateDiskCheckpointDataSchema = DiskCheckpointInfoSchema;
18
+ export const CreateDiskCheckpointResponseSchema = APIResponseSchema(CreateDiskCheckpointDataSchema);
19
+
20
+ const ListDiskCheckpointsDataSchema = z.object({
21
+ checkpoints: z.array(DiskCheckpointInfoSchema),
22
+ });
23
+ export const ListDiskCheckpointsResponseSchema = APIResponseSchema(ListDiskCheckpointsDataSchema);
24
+
25
+ export const RestoreDiskCheckpointResponseSchema = APIResponseSchemaNoData();
26
+ export const DeleteDiskCheckpointResponseSchema = APIResponseSchemaNoData();
27
+
28
+ // --- Params ---
29
+
30
+ export interface DiskCheckpointCreateParams {
31
+ sandboxId: string;
32
+ name: string;
33
+ orgId?: string;
34
+ }
35
+
36
+ export interface DiskCheckpointListParams {
37
+ sandboxId: string;
38
+ orgId?: string;
39
+ }
40
+
41
+ export interface DiskCheckpointRestoreParams {
42
+ sandboxId: string;
43
+ checkpointId: string;
44
+ orgId?: string;
45
+ }
46
+
47
+ export interface DiskCheckpointDeleteParams {
48
+ sandboxId: string;
49
+ checkpointId: string;
50
+ orgId?: string;
51
+ }
52
+
53
+ // --- API Functions ---
54
+
55
+ /**
56
+ * Creates a new disk checkpoint for a sandbox.
57
+ *
58
+ * @param client - The API client to use for the request
59
+ * @param params - Parameters including the sandbox ID and checkpoint name
60
+ * @throws {SandboxResponseError} If the sandbox is not found or checkpoint creation fails
61
+ */
62
+ export async function diskCheckpointCreate(
63
+ client: APIClient,
64
+ params: DiskCheckpointCreateParams
65
+ ): Promise<DiskCheckpointInfo> {
66
+ const { sandboxId, name, orgId } = params;
67
+ const queryParams = new URLSearchParams();
68
+ if (orgId) {
69
+ queryParams.set('orgId', orgId);
70
+ }
71
+ const queryString = queryParams.toString();
72
+ const url = `/sandbox/${API_VERSION}/${encodeURIComponent(sandboxId)}/checkpoint${queryString ? `?${queryString}` : ''}`;
73
+
74
+ const resp = await client.post<zType.infer<typeof CreateDiskCheckpointResponseSchema>>(
75
+ url,
76
+ { name },
77
+ CreateDiskCheckpointResponseSchema
78
+ );
79
+
80
+ if (resp.success) {
81
+ return resp.data;
82
+ }
83
+
84
+ throwSandboxError(resp, { sandboxId });
85
+ }
86
+
87
+ /**
88
+ * Lists all disk checkpoints for a sandbox.
89
+ *
90
+ * @param client - The API client to use for the request
91
+ * @param params - Parameters including the sandbox ID
92
+ * @throws {SandboxResponseError} If the sandbox is not found or listing fails
93
+ */
94
+ export async function diskCheckpointList(
95
+ client: APIClient,
96
+ params: DiskCheckpointListParams
97
+ ): Promise<DiskCheckpointInfo[]> {
98
+ const { sandboxId, orgId } = params;
99
+ const queryParams = new URLSearchParams();
100
+ if (orgId) {
101
+ queryParams.set('orgId', orgId);
102
+ }
103
+ const queryString = queryParams.toString();
104
+ const url = `/sandbox/${API_VERSION}/checkpoints/${encodeURIComponent(sandboxId)}${queryString ? `?${queryString}` : ''}`;
105
+
106
+ const resp = await client.get<zType.infer<typeof ListDiskCheckpointsResponseSchema>>(
107
+ url,
108
+ ListDiskCheckpointsResponseSchema
109
+ );
110
+
111
+ if (resp.success) {
112
+ return resp.data.checkpoints;
113
+ }
114
+
115
+ throwSandboxError(resp, { sandboxId });
116
+ }
117
+
118
+ /**
119
+ * Restores a sandbox to a specific disk checkpoint.
120
+ *
121
+ * @param client - The API client to use for the request
122
+ * @param params - Parameters including the sandbox ID and checkpoint ID
123
+ * @throws {SandboxResponseError} If the sandbox or checkpoint is not found, or restore fails
124
+ */
125
+ export async function diskCheckpointRestore(
126
+ client: APIClient,
127
+ params: DiskCheckpointRestoreParams
128
+ ): Promise<void> {
129
+ const { sandboxId, checkpointId, orgId } = params;
130
+ const queryParams = new URLSearchParams();
131
+ if (orgId) {
132
+ queryParams.set('orgId', orgId);
133
+ }
134
+ const queryString = queryParams.toString();
135
+ const url = `/sandbox/${API_VERSION}/${encodeURIComponent(sandboxId)}/checkpoint/${encodeURIComponent(checkpointId)}/restore${queryString ? `?${queryString}` : ''}`;
136
+
137
+ const resp = await client.post<zType.infer<typeof RestoreDiskCheckpointResponseSchema>>(
138
+ url,
139
+ undefined,
140
+ RestoreDiskCheckpointResponseSchema
141
+ );
142
+
143
+ if (resp.success) {
144
+ return;
145
+ }
146
+
147
+ throwSandboxError(resp, { sandboxId });
148
+ }
149
+
150
+ /**
151
+ * Deletes a disk checkpoint from a sandbox.
152
+ *
153
+ * @param client - The API client to use for the request
154
+ * @param params - Parameters including the sandbox ID and checkpoint ID
155
+ * @throws {SandboxResponseError} If the sandbox or checkpoint is not found, or deletion fails
156
+ */
157
+ export async function diskCheckpointDelete(
158
+ client: APIClient,
159
+ params: DiskCheckpointDeleteParams
160
+ ): Promise<void> {
161
+ const { sandboxId, checkpointId, orgId } = params;
162
+ const queryParams = new URLSearchParams();
163
+ if (orgId) {
164
+ queryParams.set('orgId', orgId);
165
+ }
166
+ const queryString = queryParams.toString();
167
+ const url = `/sandbox/${API_VERSION}/${encodeURIComponent(sandboxId)}/checkpoint/${encodeURIComponent(checkpointId)}${queryString ? `?${queryString}` : ''}`;
168
+
169
+ const resp = await client.delete<zType.infer<typeof DeleteDiskCheckpointResponseSchema>>(
170
+ url,
171
+ DeleteDiskCheckpointResponseSchema
172
+ );
173
+
174
+ if (resp.success) {
175
+ return;
176
+ }
177
+
178
+ throwSandboxError(resp, { sandboxId });
179
+ }
@@ -16,6 +16,24 @@ export {
16
16
  } from './create.ts';
17
17
  export type { SandboxDestroyParams } from './destroy.ts';
18
18
  export { DestroyResponseSchema, sandboxDestroy } from './destroy.ts';
19
+ export type {
20
+ DiskCheckpointInfo,
21
+ DiskCheckpointCreateParams,
22
+ DiskCheckpointListParams,
23
+ DiskCheckpointRestoreParams,
24
+ DiskCheckpointDeleteParams,
25
+ } from './disk-checkpoint.ts';
26
+ export {
27
+ DiskCheckpointInfoSchema,
28
+ CreateDiskCheckpointResponseSchema,
29
+ ListDiskCheckpointsResponseSchema,
30
+ RestoreDiskCheckpointResponseSchema,
31
+ DeleteDiskCheckpointResponseSchema,
32
+ diskCheckpointCreate,
33
+ diskCheckpointList,
34
+ diskCheckpointRestore,
35
+ diskCheckpointDelete,
36
+ } from './disk-checkpoint.ts';
19
37
  export type { SandboxPauseParams } from './pause.ts';
20
38
  export { PauseResponseSchema, sandboxPause } from './pause.ts';
21
39
  export type { SandboxResumeParams } from './resume.ts';
@@ -0,0 +1 @@
1
+ export * from './stats.ts';
@@ -0,0 +1,213 @@
1
+ import { z } from 'zod';
2
+ import { type APIClient, APIResponseSchema } from '../api.ts';
3
+ import { StructuredError } from '@agentuity/core';
4
+
5
+ // --- Error ---
6
+
7
+ export const ServiceStatsError = StructuredError('ServiceStatsError')<{
8
+ message: string;
9
+ }>();
10
+
11
+ // --- Per-Service Stat Schemas ---
12
+
13
+ export const KeyValueStatSchema = z.object({
14
+ namespaceCount: z.number(),
15
+ keyCount: z.number(),
16
+ totalSizeBytes: z.number(),
17
+ });
18
+
19
+ export const VectorStatSchema = z.object({
20
+ namespaceCount: z.number(),
21
+ documentCount: z.number(),
22
+ totalSizeBytes: z.number(),
23
+ });
24
+
25
+ export const QueueStatSchema = z.object({
26
+ queueCount: z.number(),
27
+ totalMessages: z.number(),
28
+ totalDlq: z.number(),
29
+ });
30
+
31
+ export const StreamStatSchema = z.object({
32
+ streamCount: z.number(),
33
+ totalSizeBytes: z.number(),
34
+ });
35
+
36
+ export const SandboxStatSchema = z.object({
37
+ totalActive: z.number(),
38
+ running: z.number(),
39
+ idle: z.number(),
40
+ creating: z.number(),
41
+ totalExecutions: z.number(),
42
+ totalCpuTimeMs: z.number(),
43
+ totalMemoryByteSec: z.number(),
44
+ totalNetworkEgressBytes: z.number(),
45
+ });
46
+
47
+ export const EmailStatSchema = z.object({
48
+ addressCount: z.number(),
49
+ inboundCount: z.number(),
50
+ outboundCount: z.number(),
51
+ outboundSuccess: z.number(),
52
+ outboundFailed: z.number(),
53
+ });
54
+
55
+ export const TaskStatSchema = z.object({
56
+ total: z.number().default(0),
57
+ open: z.number().default(0),
58
+ inProgress: z.number().default(0),
59
+ done: z.number().default(0),
60
+ closed: z.number().default(0),
61
+ cancelled: z.number().default(0),
62
+ });
63
+
64
+ export const ScheduleStatSchema = z.object({
65
+ scheduleCount: z.number(),
66
+ totalDeliveries: z.number(),
67
+ successDeliveries: z.number(),
68
+ failedDeliveries: z.number(),
69
+ });
70
+
71
+ export const DatabaseStatSchema = z.object({
72
+ databaseCount: z.number(),
73
+ totalTableCount: z.number(),
74
+ totalRecordCount: z.number(),
75
+ totalSizeBytes: z.number(),
76
+ });
77
+
78
+ // --- Aggregate Schema ---
79
+
80
+ export const ServiceStatsDataSchema = z.object({
81
+ services: z.object({
82
+ database: DatabaseStatSchema.optional(),
83
+ keyvalue: KeyValueStatSchema.optional(),
84
+ vector: VectorStatSchema.optional(),
85
+ queue: QueueStatSchema.optional(),
86
+ stream: StreamStatSchema.optional(),
87
+ sandbox: SandboxStatSchema.optional(),
88
+ email: EmailStatSchema.optional(),
89
+ task: TaskStatSchema.optional(),
90
+ schedule: ScheduleStatSchema.optional(),
91
+ }),
92
+ });
93
+
94
+ export const ServiceStatsResponseSchema = APIResponseSchema(ServiceStatsDataSchema);
95
+
96
+ // --- Types ---
97
+
98
+ export type KeyValueStat = z.infer<typeof KeyValueStatSchema>;
99
+ export type VectorStat = z.infer<typeof VectorStatSchema>;
100
+ export type QueueStat = z.infer<typeof QueueStatSchema>;
101
+ export type StreamStat = z.infer<typeof StreamStatSchema>;
102
+ export type SandboxStat = z.infer<typeof SandboxStatSchema>;
103
+ export type EmailStat = z.infer<typeof EmailStatSchema>;
104
+ export type TaskStat = z.infer<typeof TaskStatSchema>;
105
+ export type ScheduleStat = z.infer<typeof ScheduleStatSchema>;
106
+ export type DatabaseStat = z.infer<typeof DatabaseStatSchema>;
107
+ export type ServiceStatsData = z.infer<typeof ServiceStatsDataSchema>;
108
+ export type ServiceStatsResponse = z.infer<typeof ServiceStatsResponseSchema>;
109
+
110
+ // --- Valid Services ---
111
+
112
+ /**
113
+ * Valid service names that can be used to filter stats.
114
+ */
115
+ export const VALID_SERVICES = [
116
+ 'database',
117
+ 'keyvalue',
118
+ 'email',
119
+ 'vector',
120
+ 'schedule',
121
+ 'task',
122
+ 'stream',
123
+ 'sandbox',
124
+ 'queue',
125
+ ] as const;
126
+
127
+ export type ServiceName = (typeof VALID_SERVICES)[number];
128
+
129
+ // --- Options ---
130
+
131
+ export interface ServiceStatsOptions {
132
+ /**
133
+ * Filter to a specific service. If omitted, returns stats for all services.
134
+ */
135
+ service?: ServiceName;
136
+ /**
137
+ * Start time filter (ISO 8601 timestamp).
138
+ */
139
+ start?: string;
140
+ /**
141
+ * End time filter (ISO 8601 timestamp).
142
+ */
143
+ end?: string;
144
+ /**
145
+ * For CLI auth: sets x-agentuity-orgid header.
146
+ * Required when using CLI token auth (bearer tokens without embedded org).
147
+ */
148
+ orgIdHeader?: string;
149
+ }
150
+
151
+ // --- API Function ---
152
+
153
+ /**
154
+ * Get aggregated stats for services used by an organization.
155
+ *
156
+ * Returns per-service stats with service-specific fields (counts, sizes, etc.).
157
+ * Services that error on the backend are omitted from the response.
158
+ * Services with no provisioned tenant DB return zero values.
159
+ *
160
+ * @param client - The API client instance
161
+ * @param orgId - The organization ID
162
+ * @param options - Optional filtering (service, time range)
163
+ * @returns Service stats data with per-service breakdown
164
+ * @throws {ServiceStatsError} If the API request fails
165
+ *
166
+ * @example
167
+ * ```typescript
168
+ * // Get stats for all services
169
+ * const stats = await getServiceStats(client, 'org_123');
170
+ * console.log(`KV keys: ${stats.services.keyvalue?.keyCount}`);
171
+ * ```
172
+ *
173
+ * @example
174
+ * ```typescript
175
+ * // Get stats for a specific service
176
+ * const stats = await getServiceStats(client, 'org_123', {
177
+ * service: 'keyvalue',
178
+ * });
179
+ * ```
180
+ */
181
+ export async function getServiceStats(
182
+ client: APIClient,
183
+ orgId: string,
184
+ options?: ServiceStatsOptions
185
+ ): Promise<ServiceStatsData> {
186
+ const params = new URLSearchParams();
187
+ if (options?.service) params.set('service', options.service);
188
+ if (options?.start) params.set('start', options.start);
189
+ if (options?.end) params.set('end', options.end);
190
+
191
+ const queryString = params.toString();
192
+ const url = `/services/stats/2026-02-26/${encodeURIComponent(orgId)}${queryString ? `?${queryString}` : ''}`;
193
+
194
+ const headers: Record<string, string> = {};
195
+ if (options?.orgIdHeader) {
196
+ headers['x-agentuity-orgid'] = options.orgIdHeader;
197
+ }
198
+
199
+ const resp = await client.get(
200
+ url,
201
+ ServiceStatsResponseSchema,
202
+ undefined,
203
+ Object.keys(headers).length > 0 ? headers : undefined
204
+ );
205
+
206
+ if (resp.success) {
207
+ return resp.data;
208
+ }
209
+
210
+ throw new ServiceStatsError({
211
+ message: resp.message || 'Failed to get service stats',
212
+ });
213
+ }
package/src/server.ts CHANGED
@@ -269,6 +269,10 @@ class ServerFetchAdapter implements FetchAdapter {
269
269
  ) {
270
270
  headers['Content-Type'] = 'application/octet-stream';
271
271
  }
272
+ // Ensure we request JSON responses for proper error handling
273
+ if (!headers['Accept'] && !headers['accept']) {
274
+ headers['Accept'] = 'application/json';
275
+ }
272
276
  const method: HttpMethod = options.method ?? 'POST';
273
277
  this.#logger.trace('sending %s to %s with headers: %s', method, url, redactHeaders(headers));
274
278
  const res = await fetch(url, {