@agentuity/server 0.1.7 → 0.1.9

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 (45) hide show
  1. package/dist/api/sandbox/create.d.ts.map +1 -1
  2. package/dist/api/sandbox/create.js +19 -0
  3. package/dist/api/sandbox/create.js.map +1 -1
  4. package/dist/api/sandbox/execution.d.ts +1 -0
  5. package/dist/api/sandbox/execution.d.ts.map +1 -1
  6. package/dist/api/sandbox/execution.js +3 -0
  7. package/dist/api/sandbox/execution.js.map +1 -1
  8. package/dist/api/sandbox/get.d.ts +1 -0
  9. package/dist/api/sandbox/get.d.ts.map +1 -1
  10. package/dist/api/sandbox/get.js +25 -2
  11. package/dist/api/sandbox/get.js.map +1 -1
  12. package/dist/api/sandbox/index.d.ts +2 -0
  13. package/dist/api/sandbox/index.d.ts.map +1 -1
  14. package/dist/api/sandbox/index.js +1 -0
  15. package/dist/api/sandbox/index.js.map +1 -1
  16. package/dist/api/sandbox/list.d.ts +1 -0
  17. package/dist/api/sandbox/list.d.ts.map +1 -1
  18. package/dist/api/sandbox/list.js +18 -1
  19. package/dist/api/sandbox/list.js.map +1 -1
  20. package/dist/api/sandbox/runtime.d.ts +15 -0
  21. package/dist/api/sandbox/runtime.d.ts.map +1 -0
  22. package/dist/api/sandbox/runtime.js +58 -0
  23. package/dist/api/sandbox/runtime.js.map +1 -0
  24. package/dist/api/sandbox/snapshot.d.ts +6 -1
  25. package/dist/api/sandbox/snapshot.d.ts.map +1 -1
  26. package/dist/api/sandbox/snapshot.js +12 -3
  27. package/dist/api/sandbox/snapshot.js.map +1 -1
  28. package/dist/index.d.ts +1 -0
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +2 -0
  31. package/dist/index.js.map +1 -1
  32. package/dist/util/resources.d.ts +47 -0
  33. package/dist/util/resources.d.ts.map +1 -0
  34. package/dist/util/resources.js +171 -0
  35. package/dist/util/resources.js.map +1 -0
  36. package/package.json +4 -4
  37. package/src/api/sandbox/create.ts +19 -0
  38. package/src/api/sandbox/execution.ts +4 -0
  39. package/src/api/sandbox/get.ts +26 -2
  40. package/src/api/sandbox/index.ts +2 -0
  41. package/src/api/sandbox/list.ts +19 -1
  42. package/src/api/sandbox/runtime.ts +77 -0
  43. package/src/api/sandbox/snapshot.ts +18 -4
  44. package/src/index.ts +10 -0
  45. package/src/util/resources.ts +213 -0
@@ -0,0 +1,213 @@
1
+ export interface ResourceValidationSuccess {
2
+ valid: true;
3
+ value: number;
4
+ }
5
+
6
+ export interface ResourceValidationFailure {
7
+ valid: false;
8
+ error: string;
9
+ }
10
+
11
+ export type ResourceValidationResult = ResourceValidationSuccess | ResourceValidationFailure;
12
+
13
+ /**
14
+ * Validates and parses a CPU spec string.
15
+ * Valid formats:
16
+ * - "500m" (millicores)
17
+ * - "1" or "2" (cores, converted to millicores)
18
+ * - "0.5" (fractional cores, converted to millicores)
19
+ */
20
+ export function validateCPUSpec(input: string): ResourceValidationResult {
21
+ if (!input || typeof input !== 'string') {
22
+ return { valid: false, error: 'CPU value is required' };
23
+ }
24
+
25
+ const trimmed = input.trim();
26
+
27
+ // Match millicores format: "500m", "1000m"
28
+ const milliMatch = trimmed.match(/^([0-9]+)m$/);
29
+ if (milliMatch) {
30
+ const value = parseInt(milliMatch[1], 10);
31
+ if (value <= 0) {
32
+ return { valid: false, error: `Invalid CPU value "${input}": must be greater than 0` };
33
+ }
34
+ return { valid: true, value };
35
+ }
36
+
37
+ // Match cores format: "1", "2", "0.5"
38
+ const coreMatch = trimmed.match(/^([0-9]*\.?[0-9]+)$/);
39
+ if (coreMatch) {
40
+ const cores = parseFloat(coreMatch[1]);
41
+ const millicores = Math.round(cores * 1000);
42
+ if (isNaN(millicores) || millicores <= 0) {
43
+ return {
44
+ valid: false,
45
+ error: `Invalid CPU value "${input}": must be at least 1m (0.001 cores)`,
46
+ };
47
+ }
48
+ return { valid: true, value: millicores };
49
+ }
50
+
51
+ return {
52
+ valid: false,
53
+ error: `Invalid CPU format "${input}". Use millicores (e.g., "500m", "1000m") or cores (e.g., "1", "2", "0.5")`,
54
+ };
55
+ }
56
+
57
+ const memoryMultipliers: Record<string, number> = {
58
+ k: 1000,
59
+ M: 1000 ** 2,
60
+ G: 1000 ** 3,
61
+ T: 1000 ** 4,
62
+ P: 1000 ** 5,
63
+ E: 1000 ** 6,
64
+ Ki: 1024,
65
+ Mi: 1024 ** 2,
66
+ Gi: 1024 ** 3,
67
+ Ti: 1024 ** 4,
68
+ Pi: 1024 ** 5,
69
+ Ei: 1024 ** 6,
70
+ };
71
+
72
+ const validMemoryUnits = Object.keys(memoryMultipliers).join(', ');
73
+
74
+ /**
75
+ * Validates and parses a memory/disk spec string.
76
+ * Valid formats:
77
+ * - "500Mi", "1Gi", "2Ti" (binary units)
78
+ * - "500M", "1G", "2T" (decimal units)
79
+ * - "1.5Gi", "0.5G" (decimal fractions with units)
80
+ * - "1073741824" (raw bytes)
81
+ */
82
+ export function validateMemorySpec(
83
+ input: string,
84
+ fieldName: 'memory' | 'disk' = 'memory'
85
+ ): ResourceValidationResult {
86
+ if (!input || typeof input !== 'string') {
87
+ return { valid: false, error: `${fieldName} value is required` };
88
+ }
89
+
90
+ const trimmed = input.trim();
91
+
92
+ // Match unit format: "500Mi", "1Gi", "2G", "1.5Gi", "0.5G"
93
+ const unitMatch = trimmed.match(/^([0-9]*\.?[0-9]+)([A-Za-z]{1,2})$/);
94
+ if (unitMatch) {
95
+ const amount = parseFloat(unitMatch[1]);
96
+ const unit = unitMatch[2];
97
+
98
+ if (isNaN(amount) || amount <= 0) {
99
+ return {
100
+ valid: false,
101
+ error: `Invalid ${fieldName} value "${input}": must be greater than 0`,
102
+ };
103
+ }
104
+
105
+ const multiplier = memoryMultipliers[unit];
106
+ if (multiplier === undefined) {
107
+ return {
108
+ valid: false,
109
+ error: `Invalid ${fieldName} unit "${unit}" in "${input}". Valid units: ${validMemoryUnits}`,
110
+ };
111
+ }
112
+
113
+ const value = Math.round(amount * multiplier);
114
+ if (!Number.isSafeInteger(value)) {
115
+ return {
116
+ valid: false,
117
+ error: `Invalid ${fieldName} value "${input}": exceeds maximum safe integer (value too large)`,
118
+ };
119
+ }
120
+ return { valid: true, value };
121
+ }
122
+
123
+ // Match raw bytes: "1073741824"
124
+ const bytesMatch = trimmed.match(/^([0-9]+)$/);
125
+ if (bytesMatch) {
126
+ const value = parseInt(bytesMatch[1], 10);
127
+ if (value <= 0) {
128
+ return {
129
+ valid: false,
130
+ error: `Invalid ${fieldName} value "${input}": must be greater than 0`,
131
+ };
132
+ }
133
+ if (!Number.isSafeInteger(value)) {
134
+ return {
135
+ valid: false,
136
+ error: `Invalid ${fieldName} value "${input}": exceeds maximum safe integer (value too large)`,
137
+ };
138
+ }
139
+ return { valid: true, value };
140
+ }
141
+
142
+ return {
143
+ valid: false,
144
+ error: `Invalid ${fieldName} format "${input}". Use units (e.g., "500Mi", "1Gi", "1.5Gi") or bytes (e.g., "1073741824")`,
145
+ };
146
+ }
147
+
148
+ export interface ResourcesConfig {
149
+ cpu?: string;
150
+ memory?: string;
151
+ disk?: string;
152
+ }
153
+
154
+ export interface ValidatedResources {
155
+ cpuUnits?: number;
156
+ memoryUnits?: number;
157
+ diskUnits?: number;
158
+ }
159
+
160
+ /**
161
+ * Validates all resource specs and returns either validated values or an array of errors.
162
+ */
163
+ export function validateResources(
164
+ resources: ResourcesConfig
165
+ ): { valid: true; values: ValidatedResources } | { valid: false; errors: string[] } {
166
+ const errors: string[] = [];
167
+ const values: ValidatedResources = {};
168
+
169
+ if (resources.cpu !== undefined && resources.cpu !== null) {
170
+ const result = validateCPUSpec(resources.cpu);
171
+ if (result.valid) {
172
+ if (!Number.isFinite(result.value)) {
173
+ errors.push(`Invalid CPU value "${resources.cpu}": parsed to non-finite number`);
174
+ } else {
175
+ values.cpuUnits = result.value;
176
+ }
177
+ } else {
178
+ errors.push(result.error);
179
+ }
180
+ }
181
+
182
+ if (resources.memory !== undefined && resources.memory !== null) {
183
+ const result = validateMemorySpec(resources.memory, 'memory');
184
+ if (result.valid) {
185
+ if (!Number.isFinite(result.value)) {
186
+ errors.push(`Invalid memory value "${resources.memory}": parsed to non-finite number`);
187
+ } else {
188
+ values.memoryUnits = result.value;
189
+ }
190
+ } else {
191
+ errors.push(result.error);
192
+ }
193
+ }
194
+
195
+ if (resources.disk !== undefined && resources.disk !== null) {
196
+ const result = validateMemorySpec(resources.disk, 'disk');
197
+ if (result.valid) {
198
+ if (!Number.isFinite(result.value)) {
199
+ errors.push(`Invalid disk value "${resources.disk}": parsed to non-finite number`);
200
+ } else {
201
+ values.diskUnits = result.value;
202
+ }
203
+ } else {
204
+ errors.push(result.error);
205
+ }
206
+ }
207
+
208
+ if (errors.length > 0) {
209
+ return { valid: false, errors };
210
+ }
211
+
212
+ return { valid: true, values };
213
+ }