@phala/cloud 0.2.0 → 0.2.1-beta.2

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.
package/dist/index.mjs CHANGED
@@ -12,8 +12,11 @@ var ApiErrorSchema = z.object({
12
12
  z.object({
13
13
  msg: z.string(),
14
14
  type: z.string().optional(),
15
- ctx: z.record(z.unknown()).optional()
16
- })
15
+ ctx: z.record(z.unknown()).optional(),
16
+ loc: z.array(z.union([z.string(), z.number()])).optional(),
17
+ input: z.unknown().optional()
18
+ }).passthrough()
19
+ // Allow additional fields
17
20
  ),
18
21
  z.record(z.unknown())
19
22
  ]).optional(),
@@ -116,6 +119,9 @@ var UnknownError = class extends PhalaCloudError {
116
119
  }
117
120
  };
118
121
  function extractFieldPath(loc) {
122
+ if (!loc || !Array.isArray(loc)) {
123
+ return "unknown";
124
+ }
119
125
  const filtered = loc.filter((part) => {
120
126
  if (typeof part === "string") {
121
127
  return !["body", "query", "path", "header"].includes(part);
@@ -131,12 +137,21 @@ function parseValidationErrors(detail) {
131
137
  message: typeof detail === "string" ? detail : "Validation error"
132
138
  };
133
139
  }
134
- const errors = detail.map((item) => ({
135
- field: extractFieldPath(item.loc),
136
- message: item.msg,
137
- type: item.type,
138
- context: item.ctx
139
- }));
140
+ const errors = detail.map(
141
+ (item, index) => {
142
+ const field = extractFieldPath(item.loc);
143
+ let displayField = field;
144
+ if (field === "unknown" && item.type) {
145
+ displayField = item.type === "missing" ? "required field" : item.type;
146
+ }
147
+ return {
148
+ field: displayField,
149
+ message: item.msg,
150
+ type: item.type,
151
+ context: item.ctx
152
+ };
153
+ }
154
+ );
140
155
  const count = errors.length;
141
156
  const message = count === 1 ? `Validation failed: ${errors[0].message}` : `Validation failed (${count} issue${count > 1 ? "s" : ""})`;
142
157
  return { errors, message };
@@ -179,13 +194,21 @@ function parseApiError(requestError) {
179
194
  const status = requestError.status ?? 0;
180
195
  const statusText = requestError.statusText ?? "Unknown Error";
181
196
  const detail = requestError.detail;
197
+ const structured = parseStructuredError(detail);
198
+ if (structured) {
199
+ return new ResourceError(structured.message, {
200
+ status,
201
+ statusText,
202
+ detail,
203
+ errorCode: structured.error_code,
204
+ structuredDetails: structured.details,
205
+ suggestions: structured.suggestions,
206
+ links: structured.links
207
+ });
208
+ }
182
209
  const errorType = categorizeErrorType(status);
183
210
  const message = extractPrimaryMessage(status, detail, requestError.message);
184
- const commonData = {
185
- status,
186
- statusText,
187
- detail
188
- };
211
+ const commonData = { status, statusText, detail };
189
212
  if (errorType === "validation" && Array.isArray(detail)) {
190
213
  const { errors } = parseValidationErrors(detail);
191
214
  return new ValidationError(message, {
@@ -247,6 +270,67 @@ function getErrorMessage(error) {
247
270
  }
248
271
  return "Unknown error occurred";
249
272
  }
273
+ var ResourceError = class extends BusinessError {
274
+ constructor(message, data) {
275
+ super(message, data);
276
+ this.isResourceError = true;
277
+ this.errorCode = data.errorCode;
278
+ this.structuredDetails = data.structuredDetails;
279
+ this.suggestions = data.suggestions;
280
+ this.links = data.links;
281
+ }
282
+ };
283
+ function parseStructuredError(detail) {
284
+ if (!detail || typeof detail !== "object") {
285
+ return null;
286
+ }
287
+ const obj = detail;
288
+ if (obj.error_code && typeof obj.error_code === "string" && obj.message && typeof obj.message === "string") {
289
+ return {
290
+ error_code: obj.error_code,
291
+ message: obj.message,
292
+ details: obj.details,
293
+ suggestions: obj.suggestions,
294
+ links: obj.links
295
+ };
296
+ }
297
+ return null;
298
+ }
299
+ function formatStructuredError(error, options) {
300
+ const { showErrorCode = true, showSuggestions = true, showLinks = true } = options ?? {};
301
+ const parts = [];
302
+ if (showErrorCode && error.errorCode) {
303
+ parts.push(`Error [${error.errorCode}]: ${error.message}`);
304
+ } else {
305
+ parts.push(error.message);
306
+ }
307
+ if (error.structuredDetails && error.structuredDetails.length > 0) {
308
+ parts.push("");
309
+ parts.push("Details:");
310
+ error.structuredDetails.forEach((d) => {
311
+ if (d.message) {
312
+ parts.push(` - ${d.message}`);
313
+ } else if (d.field && d.value !== void 0) {
314
+ parts.push(` - ${d.field}: ${d.value}`);
315
+ }
316
+ });
317
+ }
318
+ if (showSuggestions && error.suggestions && error.suggestions.length > 0) {
319
+ parts.push("");
320
+ parts.push("Suggestions:");
321
+ error.suggestions.forEach((s) => {
322
+ parts.push(` - ${s}`);
323
+ });
324
+ }
325
+ if (showLinks && error.links && error.links.length > 0) {
326
+ parts.push("");
327
+ parts.push("Learn more:");
328
+ error.links.forEach((link) => {
329
+ parts.push(` - ${link.label}: ${link.url}`);
330
+ });
331
+ }
332
+ return parts.join("\n");
333
+ }
250
334
 
251
335
  // src/client.ts
252
336
  var SUPPORTED_API_VERSIONS = ["2025-05-31", "2025-10-28"];
@@ -804,10 +888,6 @@ var { action: getAvailableNodes, safeAction: safeGetAvailableNodes } = defineSim
804
888
 
805
889
  // src/actions/list-instance-types.ts
806
890
  import { z as z5 } from "zod";
807
- var ListInstanceTypesRequestSchema = z5.object({
808
- page: z5.number().int().min(1).optional().default(1),
809
- page_size: z5.number().int().min(1).max(1e3).optional().default(100)
810
- }).strict();
811
891
  var InstanceTypeSchema = z5.object({
812
892
  id: z5.string(),
813
893
  name: z5.string(),
@@ -816,22 +896,34 @@ var InstanceTypeSchema = z5.object({
816
896
  memory_mb: z5.number(),
817
897
  hourly_rate: z5.string(),
818
898
  requires_gpu: z5.boolean(),
819
- public: z5.boolean(),
820
- enabled: z5.boolean()
899
+ default_disk_size_gb: z5.number().default(20),
900
+ family: z5.string().nullable()
821
901
  }).passthrough();
822
- var PaginatedInstanceTypesSchema = z5.object({
902
+ var FamilyGroupSchema = z5.object({
903
+ name: z5.string(),
904
+ items: z5.array(InstanceTypeSchema),
905
+ total: z5.number()
906
+ }).strict();
907
+ var AllFamiliesResponseSchema = z5.object({
908
+ result: z5.array(FamilyGroupSchema)
909
+ }).strict();
910
+ var FamilyInstanceTypesResponseSchema = z5.object({
823
911
  items: z5.array(InstanceTypeSchema),
824
912
  total: z5.number(),
825
- page: z5.number(),
826
- page_size: z5.number(),
827
- pages: z5.number()
913
+ family: z5.string()
828
914
  }).strict();
829
- var { action: listInstanceTypes, safeAction: safeListInstanceTypes } = defineAction(PaginatedInstanceTypesSchema, async (client, request) => {
830
- const validatedRequest = ListInstanceTypesRequestSchema.parse(request ?? {});
831
- const queryParams = new URLSearchParams();
832
- queryParams.append("page", validatedRequest.page.toString());
833
- queryParams.append("page_size", validatedRequest.page_size.toString());
834
- return await client.get(`/api/instance-types?${queryParams.toString()}`);
915
+ var ListFamilyInstanceTypesRequestSchema = z5.object({
916
+ family: z5.string()
917
+ }).strict();
918
+ var { action: listAllInstanceTypeFamilies, safeAction: safeListAllInstanceTypeFamilies } = defineAction(
919
+ AllFamiliesResponseSchema,
920
+ async (client) => {
921
+ return await client.get("/instance-types");
922
+ }
923
+ );
924
+ var { action: listFamilyInstanceTypes, safeAction: safeListFamilyInstanceTypes } = defineAction(FamilyInstanceTypesResponseSchema, async (client, request) => {
925
+ const validated = ListFamilyInstanceTypesRequestSchema.parse(request);
926
+ return await client.get(`/instance-types/${validated.family}`);
835
927
  });
836
928
 
837
929
  // src/actions/workspaces/list_workspaces.ts
@@ -1051,6 +1143,7 @@ var ProvisionCvmSchema = z10.object({
1051
1143
  fmspc: z10.string().nullable().optional(),
1052
1144
  device_id: z10.string().nullable().optional(),
1053
1145
  os_image_hash: z10.string().nullable().optional(),
1146
+ instance_type: z10.string().nullable().optional(),
1054
1147
  teepod_id: z10.number().nullable().optional(),
1055
1148
  // Will be transformed to node_id
1056
1149
  node_id: z10.number().nullable().optional(),
@@ -1064,19 +1157,24 @@ var ProvisionCvmSchema = z10.object({
1064
1157
  });
1065
1158
  var ProvisionCvmRequestSchema = z10.object({
1066
1159
  node_id: z10.number().optional(),
1067
- // recommended
1160
+ // recommended - optional, system auto-selects if not specified
1068
1161
  teepod_id: z10.number().optional(),
1069
1162
  // deprecated, for compatibility
1163
+ region: z10.string().optional(),
1164
+ // optional - region filter for auto-selection
1070
1165
  name: z10.string(),
1071
- image: z10.string(),
1072
- vcpu: z10.number(),
1073
- memory: z10.number(),
1074
- disk_size: z10.number(),
1166
+ instance_type: z10.string().default("tdx.small"),
1167
+ // defaults to "tdx.small"
1168
+ image: z10.string().optional(),
1169
+ vcpu: z10.number().optional(),
1170
+ memory: z10.number().optional(),
1171
+ disk_size: z10.number().optional(),
1075
1172
  compose_file: z10.object({
1076
1173
  allowed_envs: z10.array(z10.string()).optional(),
1077
1174
  pre_launch_script: z10.string().optional(),
1078
1175
  docker_compose_file: z10.string().optional(),
1079
- name: z10.string().optional(),
1176
+ name: z10.string().optional().default(""),
1177
+ // optional with default empty string
1080
1178
  kms_enabled: z10.boolean().optional(),
1081
1179
  public_logs: z10.boolean().optional(),
1082
1180
  public_sysinfo: z10.boolean().optional(),
@@ -1086,8 +1184,11 @@ var ProvisionCvmRequestSchema = z10.object({
1086
1184
  // deprecated, for compatibility
1087
1185
  }),
1088
1186
  listed: z10.boolean().optional(),
1089
- instance_type: z10.string().nullable().optional(),
1090
1187
  kms_id: z10.string().optional(),
1188
+ kms: z10.enum(["PHALA", "ETHEREUM", "BASE"]).optional(),
1189
+ // KMS type selection (defaults to PHALA)
1190
+ kms_contract: z10.string().optional(),
1191
+ // KMS contract address for on-chain KMS
1091
1192
  env_keys: z10.array(z10.string()).optional()
1092
1193
  }).passthrough();
1093
1194
  function handleGatewayCompatibility(appCompose) {
@@ -1112,7 +1213,8 @@ function handleGatewayCompatibility(appCompose) {
1112
1213
  };
1113
1214
  }
1114
1215
  var { action: provisionCvm, safeAction: safeProvisionCvm } = defineAction(ProvisionCvmSchema, async (client, appCompose) => {
1115
- const body = handleGatewayCompatibility(appCompose);
1216
+ const validated = ProvisionCvmRequestSchema.parse(appCompose);
1217
+ const body = handleGatewayCompatibility(validated);
1116
1218
  let requestBody = { ...body };
1117
1219
  if (typeof body.node_id === "number") {
1118
1220
  requestBody = { ...body, teepod_id: body.node_id };
@@ -1156,7 +1258,7 @@ var CommitCvmProvisionSchema = z11.object({
1156
1258
  var CommitCvmProvisionRequestSchema = z11.object({
1157
1259
  encrypted_env: z11.string().optional().nullable(),
1158
1260
  app_id: z11.string(),
1159
- compose_hash: z11.string().optional(),
1261
+ compose_hash: z11.string(),
1160
1262
  kms_id: z11.string().optional(),
1161
1263
  contract_address: z11.string().optional(),
1162
1264
  deployer_address: z11.string().optional(),
@@ -1678,12 +1780,15 @@ var { action: updateOsImage, safeAction: safeUpdateOsImage } = defineAction(z29.
1678
1780
  // src/actions/cvms/get_cvm_state.ts
1679
1781
  import { z as z30 } from "zod";
1680
1782
  var CvmStateSchema = z30.object({
1681
- status: z30.string(),
1682
- derived_status: z30.string().optional(),
1683
- vm_uuid: z30.string().optional(),
1783
+ id: z30.string().optional(),
1684
1784
  instance_id: z30.string().optional(),
1685
- uptime: z30.string().optional()
1686
- // Add other state fields as needed
1785
+ name: z30.string(),
1786
+ status: z30.string(),
1787
+ uptime: z30.string().optional(),
1788
+ exited_at: z30.string().optional(),
1789
+ boot_progress: z30.string().optional(),
1790
+ boot_error: z30.string().optional(),
1791
+ shutdown_progress: z30.string().optional()
1687
1792
  });
1688
1793
  var GetCvmStateRequestSchema = CvmIdSchema;
1689
1794
  var { action: getCvmState, safeAction: safeGetCvmState } = defineAction(CvmStateSchema, async (client, request) => {
@@ -1699,8 +1804,10 @@ function createClient2(config = {}) {
1699
1804
  safeGetCurrentUser,
1700
1805
  getAvailableNodes,
1701
1806
  safeGetAvailableNodes,
1702
- listInstanceTypes,
1703
- safeListInstanceTypes,
1807
+ listAllInstanceTypeFamilies,
1808
+ safeListAllInstanceTypeFamilies,
1809
+ listFamilyInstanceTypes,
1810
+ safeListFamilyInstanceTypes,
1704
1811
  listWorkspaces,
1705
1812
  safeListWorkspaces,
1706
1813
  getWorkspace,
@@ -3220,6 +3327,7 @@ import { getComposeHash as getComposeHash2 } from "@phala/dstack-sdk/get-compose
3220
3327
  import { verifyEnvEncryptPublicKey } from "@phala/dstack-sdk/verify-env-encrypt-public-key";
3221
3328
  export {
3222
3329
  AddComposeHashSchema,
3330
+ AllFamiliesResponseSchema,
3223
3331
  ApiErrorSchema,
3224
3332
  AuthError,
3225
3333
  AvailableNodesSchema,
@@ -3244,6 +3352,8 @@ export {
3244
3352
  DeleteCvmRequestSchema,
3245
3353
  DeployAppAuthRequestSchema,
3246
3354
  DeployAppAuthSchema,
3355
+ FamilyGroupSchema,
3356
+ FamilyInstanceTypesResponseSchema,
3247
3357
  GetAppEnvEncryptPubKeyRequestSchema,
3248
3358
  GetAppEnvEncryptPubKeySchema,
3249
3359
  GetAvailableOSImagesRequestSchema,
@@ -3263,7 +3373,7 @@ export {
3263
3373
  GetKmsListSchema,
3264
3374
  InstanceTypeSchema,
3265
3375
  KmsInfoSchema,
3266
- ListInstanceTypesRequestSchema,
3376
+ ListFamilyInstanceTypesRequestSchema,
3267
3377
  ListWorkspacesSchema,
3268
3378
  ManagedUserSchema,
3269
3379
  MaxRetriesExceededError,
@@ -3271,7 +3381,6 @@ export {
3271
3381
  NextAppIdsRequestSchema,
3272
3382
  NextAppIdsSchema,
3273
3383
  OSImageVariantSchema,
3274
- PaginatedInstanceTypesSchema,
3275
3384
  PaginationMetadataSchema,
3276
3385
  PhalaCloudError,
3277
3386
  ProvisionCvmComposeFileUpdateRequestSchema,
@@ -3279,6 +3388,7 @@ export {
3279
3388
  ProvisionCvmRequestSchema,
3280
3389
  ProvisionCvmSchema,
3281
3390
  RequestError,
3391
+ ResourceError,
3282
3392
  RestartCvmRequestSchema,
3283
3393
  SUPPORTED_CHAINS,
3284
3394
  ServerError,
@@ -3323,6 +3433,7 @@ export {
3323
3433
  executeTransactionWithRetry,
3324
3434
  extractNetworkClients,
3325
3435
  formatErrorMessage,
3436
+ formatStructuredError,
3326
3437
  formatValidationErrors,
3327
3438
  getAppEnvEncryptPubKey,
3328
3439
  getAvailableNodes,
@@ -3343,7 +3454,8 @@ export {
3343
3454
  getKmsList,
3344
3455
  getValidationFields,
3345
3456
  getWorkspace,
3346
- listInstanceTypes,
3457
+ listAllInstanceTypeFamilies,
3458
+ listFamilyInstanceTypes,
3347
3459
  listWorkspaces,
3348
3460
  nextAppIds,
3349
3461
  parseApiError,
@@ -3375,7 +3487,8 @@ export {
3375
3487
  safeGetKmsInfo,
3376
3488
  safeGetKmsList,
3377
3489
  safeGetWorkspace,
3378
- safeListInstanceTypes,
3490
+ safeListAllInstanceTypeFamilies,
3491
+ safeListFamilyInstanceTypes,
3379
3492
  safeListWorkspaces,
3380
3493
  safeNextAppIds,
3381
3494
  safeProvisionCvm,
@@ -8,33 +8,43 @@ export declare const ApiErrorSchema: z.ZodObject<{
8
8
  msg: z.ZodString;
9
9
  type: z.ZodOptional<z.ZodString>;
10
10
  ctx: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
11
- }, "strip", z.ZodTypeAny, {
12
- msg: string;
13
- type?: string | undefined;
14
- ctx?: Record<string, unknown> | undefined;
15
- }, {
16
- msg: string;
17
- type?: string | undefined;
18
- ctx?: Record<string, unknown> | undefined;
19
- }>, "many">, z.ZodRecord<z.ZodString, z.ZodUnknown>]>>;
11
+ loc: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodNumber]>, "many">>;
12
+ input: z.ZodOptional<z.ZodUnknown>;
13
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
14
+ msg: z.ZodString;
15
+ type: z.ZodOptional<z.ZodString>;
16
+ ctx: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
17
+ loc: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodNumber]>, "many">>;
18
+ input: z.ZodOptional<z.ZodUnknown>;
19
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
20
+ msg: z.ZodString;
21
+ type: z.ZodOptional<z.ZodString>;
22
+ ctx: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
23
+ loc: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodNumber]>, "many">>;
24
+ input: z.ZodOptional<z.ZodUnknown>;
25
+ }, z.ZodTypeAny, "passthrough">>, "many">, z.ZodRecord<z.ZodString, z.ZodUnknown>]>>;
20
26
  type: z.ZodOptional<z.ZodString>;
21
27
  code: z.ZodOptional<z.ZodString>;
22
28
  }, "strip", z.ZodTypeAny, {
23
29
  code?: string | undefined;
24
30
  type?: string | undefined;
25
- detail?: string | Record<string, unknown> | {
26
- msg: string;
27
- type?: string | undefined;
28
- ctx?: Record<string, unknown> | undefined;
29
- }[] | undefined;
31
+ detail?: string | Record<string, unknown> | z.objectOutputType<{
32
+ msg: z.ZodString;
33
+ type: z.ZodOptional<z.ZodString>;
34
+ ctx: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
35
+ loc: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodNumber]>, "many">>;
36
+ input: z.ZodOptional<z.ZodUnknown>;
37
+ }, z.ZodTypeAny, "passthrough">[] | undefined;
30
38
  }, {
31
39
  code?: string | undefined;
32
40
  type?: string | undefined;
33
- detail?: string | Record<string, unknown> | {
34
- msg: string;
35
- type?: string | undefined;
36
- ctx?: Record<string, unknown> | undefined;
37
- }[] | undefined;
41
+ detail?: string | Record<string, unknown> | z.objectInputType<{
42
+ msg: z.ZodString;
43
+ type: z.ZodOptional<z.ZodString>;
44
+ ctx: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
45
+ loc: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodNumber]>, "many">>;
46
+ input: z.ZodOptional<z.ZodUnknown>;
47
+ }, z.ZodTypeAny, "passthrough">[] | undefined;
38
48
  }>;
39
49
  export type ApiError = z.infer<typeof ApiErrorSchema>;
40
50
  /**
@@ -94,6 +104,9 @@ export declare class RequestError extends PhalaCloudError implements ApiError {
94
104
  msg: string;
95
105
  type?: string;
96
106
  ctx?: Record<string, unknown>;
107
+ loc?: (string | number)[];
108
+ input?: unknown;
109
+ [key: string]: unknown;
97
110
  }>;
98
111
  code?: string | undefined;
99
112
  type?: string | undefined;
@@ -122,6 +135,9 @@ export declare class ValidationError extends PhalaCloudError {
122
135
  msg: string;
123
136
  type?: string;
124
137
  ctx?: Record<string, unknown>;
138
+ loc?: (string | number)[];
139
+ input?: unknown;
140
+ [key: string]: unknown;
125
141
  }>;
126
142
  validationErrors: ValidationErrorItem[];
127
143
  });
@@ -162,6 +178,7 @@ export declare class UnknownError extends PhalaCloudError {
162
178
  * Parse RequestError into PhalaCloudError instance
163
179
  *
164
180
  * Returns the appropriate error subclass based on status code:
181
+ * - New structured errors (with error_code) → ResourceError
165
182
  * - 422 → ValidationError (with validationErrors array)
166
183
  * - 401, 403 → AuthError
167
184
  * - 400, 409, etc. → BusinessError
@@ -176,7 +193,13 @@ export declare class UnknownError extends PhalaCloudError {
176
193
  * try {
177
194
  * await client.post('/cvms', data);
178
195
  * } catch (error) {
179
- * if (error instanceof ValidationError) {
196
+ * if (error instanceof ResourceError) {
197
+ * // New structured error with error code
198
+ * console.error(`Error [${error.errorCode}]: ${error.message}`);
199
+ * if (error.suggestions) {
200
+ * error.suggestions.forEach(s => console.log(s));
201
+ * }
202
+ * } else if (error instanceof ValidationError) {
180
203
  * // TypeScript knows error.validationErrors exists
181
204
  * error.validationErrors.forEach(e => {
182
205
  * console.error(`${e.field}: ${e.message}`);
@@ -259,3 +282,97 @@ export declare function formatErrorMessage(error: PhalaCloudError, options?: {
259
282
  * @returns Error message string
260
283
  */
261
284
  export declare function getErrorMessage(error: ApiError): string;
285
+ /**
286
+ * Structured error detail from new error format (ERR-xxxx codes)
287
+ */
288
+ export interface StructuredErrorDetail {
289
+ field?: string;
290
+ value?: unknown;
291
+ message?: string;
292
+ }
293
+ /**
294
+ * Error link from structured error response
295
+ */
296
+ export interface ErrorLink {
297
+ url: string;
298
+ label: string;
299
+ }
300
+ /**
301
+ * New structured error response format with unique error codes
302
+ */
303
+ export interface StructuredErrorResponse {
304
+ error_code: string;
305
+ message: string;
306
+ details?: StructuredErrorDetail[];
307
+ suggestions?: string[];
308
+ links?: ErrorLink[];
309
+ }
310
+ /**
311
+ * Resource provisioning error with structured details
312
+ * Extends BusinessError to handle new error format from backend
313
+ *
314
+ * Use instanceof to check: if (error instanceof ResourceError) { ... }
315
+ * Or use property: if (error.isResourceError) { ... }
316
+ */
317
+ export declare class ResourceError extends BusinessError {
318
+ readonly isResourceError: true;
319
+ readonly errorCode?: string;
320
+ readonly structuredDetails?: StructuredErrorDetail[];
321
+ readonly suggestions?: string[];
322
+ readonly links?: ErrorLink[];
323
+ constructor(message: string, data: {
324
+ status: number;
325
+ statusText: string;
326
+ detail?: string | Record<string, unknown> | Array<{
327
+ msg: string;
328
+ type?: string;
329
+ ctx?: Record<string, unknown>;
330
+ loc?: (string | number)[];
331
+ input?: unknown;
332
+ [key: string]: unknown;
333
+ }>;
334
+ errorCode?: string;
335
+ structuredDetails?: StructuredErrorDetail[];
336
+ suggestions?: string[];
337
+ links?: ErrorLink[];
338
+ });
339
+ }
340
+ /**
341
+ * Format structured error for display
342
+ *
343
+ * @param error - Resource error with structured details
344
+ * @param options - Formatting options
345
+ * @returns Formatted error message
346
+ *
347
+ * @example
348
+ * ```typescript
349
+ * try {
350
+ * await client.provisionCvm(payload);
351
+ * } catch (error) {
352
+ * if (error instanceof ResourceError) {
353
+ * console.error(formatStructuredError(error));
354
+ * }
355
+ * }
356
+ * // Output:
357
+ * // Error [ERR-01-001]: The requested instance type does not exist
358
+ * //
359
+ * // Details:
360
+ * // - Instance type 'invalid' is not recognized
361
+ * //
362
+ * // Suggestions:
363
+ * // - Use a valid instance type: tdx.small, tdx.medium, or tdx.large
364
+ * // - Alternatively, specify CPU and memory requirements manually
365
+ * //
366
+ * // Learn more:
367
+ * // - View available instance types: https://cloud.phala.network/instances
368
+ * // - Contact support: https://cloud.phala.network/support
369
+ * ```
370
+ */
371
+ export declare function formatStructuredError(error: ResourceError, options?: {
372
+ /** Show error code in output (default: true) */
373
+ showErrorCode?: boolean;
374
+ /** Show suggestions (default: true) */
375
+ showSuggestions?: boolean;
376
+ /** Show links (default: true) */
377
+ showLinks?: boolean;
378
+ }): string;
@@ -2,7 +2,7 @@ export { encryptEnvVars } from "@phala/dstack-sdk/encrypt-env-vars";
2
2
  export { getComposeHash, dumpAppCompose, preprocessAppCompose, sortObject, withComposeMethods, type AppCompose, type AppComposeWithMethods, type SortableValue, type SortableObject, type SortableArray, } from "./get_compose_hash";
3
3
  export { asHex } from "./as-hex";
4
4
  export { validateActionParameters, safeValidateActionParameters } from "./validate-parameters";
5
- export { parseApiError, PhalaCloudError, RequestError, ValidationError, AuthError, BusinessError, ServerError, UnknownError, formatValidationErrors, formatErrorMessage, getErrorMessage, getValidationFields, type ValidationErrorItem, ApiErrorSchema, type ApiError, } from "./errors";
5
+ export { parseApiError, PhalaCloudError, RequestError, ValidationError, AuthError, BusinessError, ServerError, UnknownError, ResourceError, formatValidationErrors, formatErrorMessage, formatStructuredError, getErrorMessage, getValidationFields, type ValidationErrorItem, type StructuredErrorDetail, type ErrorLink, type StructuredErrorResponse, ApiErrorSchema, type ApiError, } from "./errors";
6
6
  export { createNetworkClients, extractNetworkClients, checkNetworkStatus, checkBalance, validateNetworkPrerequisites, waitForTransactionReceipt, executeTransaction, NetworkError, WalletError, TransactionError, type NetworkConfig, type WalletConnection, type NetworkClients, type BalanceCheckResult, type TransactionOptions, type TransactionResult, } from "./network";
7
7
  export { createTransactionTracker, executeBatchTransactions, executeTransactionWithRetry, estimateTransactionGas, type TransactionState, type TransactionStatus, type TransactionTracker, type BatchTransactionOptions, type BatchTransactionResult, type RetryOptions, type GasEstimationOptions, } from "./transaction";
8
8
  export { createClientsFromPrivateKey, createClientsFromBrowser, autoCreateClients, switchToNetwork, addNetwork, } from "./client-factories";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phala/cloud",
3
- "version": "0.2.0",
3
+ "version": "0.2.1-beta.2",
4
4
  "description": "TypeScript SDK for Phala Cloud API",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -38,7 +38,7 @@
38
38
  "author": "Leechael Yim",
39
39
  "license": "Apache-2.0",
40
40
  "dependencies": {
41
- "@phala/dstack-sdk": "0.5.4-beta.6",
41
+ "@phala/dstack-sdk": "0.5.7",
42
42
  "debug": "^4.4.1",
43
43
  "mitt": "^3.0.1",
44
44
  "ofetch": "^1.3.3",