skedyul 1.2.40 → 1.2.41

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/cli/index.js CHANGED
@@ -3754,28 +3754,69 @@ async function handleMcpToolsCall(params, id, ctx) {
3754
3754
  invocation: toolInvocation
3755
3755
  });
3756
3756
  let result;
3757
- if (toolResult.error) {
3758
- const errorOutput = { error: toolResult.error };
3757
+ const isNewShapeFailure = "success" in toolResult && toolResult.success === false;
3758
+ const isLegacyErrorFailure = "error" in toolResult && toolResult.error != null;
3759
+ const isLegacyMetaFailure = "meta" in toolResult && toolResult.meta != null && typeof toolResult.meta === "object" && "success" in toolResult.meta && toolResult.meta.success === false;
3760
+ const isFailure = isNewShapeFailure || isLegacyErrorFailure || isLegacyMetaFailure;
3761
+ if (isFailure) {
3762
+ let errorOutput;
3763
+ if (isNewShapeFailure && "error" in toolResult) {
3764
+ errorOutput = {
3765
+ error: toolResult.error,
3766
+ retry: "retry" in toolResult ? toolResult.retry : void 0
3767
+ };
3768
+ } else if (isLegacyErrorFailure && "error" in toolResult) {
3769
+ errorOutput = { error: toolResult.error };
3770
+ } else if (isLegacyMetaFailure && "meta" in toolResult && toolResult.meta) {
3771
+ const meta = toolResult.meta;
3772
+ errorOutput = {
3773
+ error: {
3774
+ code: "TOOL_FAILED",
3775
+ message: meta.message ?? "Tool execution failed",
3776
+ category: "internal"
3777
+ }
3778
+ };
3779
+ } else {
3780
+ errorOutput = {
3781
+ error: {
3782
+ code: "TOOL_FAILED",
3783
+ message: "Tool execution failed",
3784
+ category: "internal"
3785
+ }
3786
+ };
3787
+ }
3759
3788
  result = {
3760
3789
  content: [{ type: "text", text: JSON.stringify(errorOutput) }],
3761
3790
  structuredContent: hasOutputSchema ? void 0 : errorOutput,
3762
3791
  isError: true,
3763
- billing: toolResult.billing
3792
+ billing: "billing" in toolResult ? toolResult.billing : void 0
3764
3793
  };
3765
3794
  } else {
3766
- const outputData = toolResult.output;
3795
+ const outputData = "output" in toolResult ? toolResult.output : null;
3796
+ const effect = "effect" in toolResult ? toolResult.effect : void 0;
3797
+ const warnings = "warnings" in toolResult ? toolResult.warnings : void 0;
3798
+ const pagination = "pagination" in toolResult ? toolResult.pagination : void 0;
3767
3799
  let structuredContent;
3768
3800
  if (outputData) {
3769
- structuredContent = { ...outputData, __effect: toolResult.effect };
3770
- } else if (toolResult.effect) {
3771
- structuredContent = { __effect: toolResult.effect };
3801
+ structuredContent = {
3802
+ ...outputData,
3803
+ __effect: effect,
3804
+ __warnings: warnings,
3805
+ __pagination: pagination
3806
+ };
3807
+ } else if (effect || warnings || pagination) {
3808
+ structuredContent = {
3809
+ __effect: effect,
3810
+ __warnings: warnings,
3811
+ __pagination: pagination
3812
+ };
3772
3813
  } else if (hasOutputSchema) {
3773
3814
  structuredContent = {};
3774
3815
  }
3775
3816
  result = {
3776
- content: [{ type: "text", text: JSON.stringify(toolResult.output) }],
3817
+ content: [{ type: "text", text: JSON.stringify(outputData) }],
3777
3818
  structuredContent,
3778
- billing: toolResult.billing
3819
+ billing: "billing" in toolResult ? toolResult.billing : void 0
3779
3820
  };
3780
3821
  }
3781
3822
  return {
@@ -1546,28 +1546,69 @@ async function handleMcpToolsCall(params, id, ctx) {
1546
1546
  invocation: toolInvocation
1547
1547
  });
1548
1548
  let result;
1549
- if (toolResult.error) {
1550
- const errorOutput = { error: toolResult.error };
1549
+ const isNewShapeFailure = "success" in toolResult && toolResult.success === false;
1550
+ const isLegacyErrorFailure = "error" in toolResult && toolResult.error != null;
1551
+ const isLegacyMetaFailure = "meta" in toolResult && toolResult.meta != null && typeof toolResult.meta === "object" && "success" in toolResult.meta && toolResult.meta.success === false;
1552
+ const isFailure = isNewShapeFailure || isLegacyErrorFailure || isLegacyMetaFailure;
1553
+ if (isFailure) {
1554
+ let errorOutput;
1555
+ if (isNewShapeFailure && "error" in toolResult) {
1556
+ errorOutput = {
1557
+ error: toolResult.error,
1558
+ retry: "retry" in toolResult ? toolResult.retry : void 0
1559
+ };
1560
+ } else if (isLegacyErrorFailure && "error" in toolResult) {
1561
+ errorOutput = { error: toolResult.error };
1562
+ } else if (isLegacyMetaFailure && "meta" in toolResult && toolResult.meta) {
1563
+ const meta = toolResult.meta;
1564
+ errorOutput = {
1565
+ error: {
1566
+ code: "TOOL_FAILED",
1567
+ message: meta.message ?? "Tool execution failed",
1568
+ category: "internal"
1569
+ }
1570
+ };
1571
+ } else {
1572
+ errorOutput = {
1573
+ error: {
1574
+ code: "TOOL_FAILED",
1575
+ message: "Tool execution failed",
1576
+ category: "internal"
1577
+ }
1578
+ };
1579
+ }
1551
1580
  result = {
1552
1581
  content: [{ type: "text", text: JSON.stringify(errorOutput) }],
1553
1582
  structuredContent: hasOutputSchema ? void 0 : errorOutput,
1554
1583
  isError: true,
1555
- billing: toolResult.billing
1584
+ billing: "billing" in toolResult ? toolResult.billing : void 0
1556
1585
  };
1557
1586
  } else {
1558
- const outputData = toolResult.output;
1587
+ const outputData = "output" in toolResult ? toolResult.output : null;
1588
+ const effect = "effect" in toolResult ? toolResult.effect : void 0;
1589
+ const warnings = "warnings" in toolResult ? toolResult.warnings : void 0;
1590
+ const pagination = "pagination" in toolResult ? toolResult.pagination : void 0;
1559
1591
  let structuredContent;
1560
1592
  if (outputData) {
1561
- structuredContent = { ...outputData, __effect: toolResult.effect };
1562
- } else if (toolResult.effect) {
1563
- structuredContent = { __effect: toolResult.effect };
1593
+ structuredContent = {
1594
+ ...outputData,
1595
+ __effect: effect,
1596
+ __warnings: warnings,
1597
+ __pagination: pagination
1598
+ };
1599
+ } else if (effect || warnings || pagination) {
1600
+ structuredContent = {
1601
+ __effect: effect,
1602
+ __warnings: warnings,
1603
+ __pagination: pagination
1604
+ };
1564
1605
  } else if (hasOutputSchema) {
1565
1606
  structuredContent = {};
1566
1607
  }
1567
1608
  result = {
1568
- content: [{ type: "text", text: JSON.stringify(toolResult.output) }],
1609
+ content: [{ type: "text", text: JSON.stringify(outputData) }],
1569
1610
  structuredContent,
1570
- billing: toolResult.billing
1611
+ billing: "billing" in toolResult ? toolResult.billing : void 0
1571
1612
  };
1572
1613
  }
1573
1614
  return {
@@ -59,14 +59,143 @@ function isRuntimeContext(ctx) {
59
59
  // src/types/tool.ts
60
60
  import { z } from "zod/v4";
61
61
  var ToolResponseMetaSchema = z.object({
62
- /** Whether the tool execution succeeded */
63
62
  success: z.boolean(),
64
- /** Human-readable message describing the result or error */
65
63
  message: z.string(),
66
- /** Name of the tool that was executed */
67
64
  toolName: z.string()
68
65
  });
69
66
 
67
+ // src/types/tool-response.ts
68
+ function createSuccessResponse(output, options) {
69
+ return {
70
+ success: true,
71
+ output,
72
+ ...options
73
+ };
74
+ }
75
+ function createListResponse(items, pagination, options) {
76
+ return {
77
+ success: true,
78
+ output: items,
79
+ pagination,
80
+ ...options
81
+ };
82
+ }
83
+ function inferCategory(code) {
84
+ switch (code) {
85
+ case "VALIDATION_ERROR":
86
+ case "CONFLICT":
87
+ return "validation";
88
+ case "AUTH_INVALID":
89
+ case "AUTH_EXPIRED":
90
+ case "PERMISSION_DENIED":
91
+ return "auth";
92
+ case "TIMEOUT":
93
+ return "timeout";
94
+ case "RATE_LIMITED":
95
+ case "EXTERNAL_SERVICE_ERROR":
96
+ case "NOT_FOUND":
97
+ case "QUOTA_EXCEEDED":
98
+ return "external";
99
+ default:
100
+ return "internal";
101
+ }
102
+ }
103
+ function createErrorResponse(code, message, options) {
104
+ const category = options?.category ?? inferCategory(code);
105
+ return {
106
+ success: false,
107
+ error: {
108
+ code,
109
+ message,
110
+ category,
111
+ field: options?.field,
112
+ details: options?.details
113
+ },
114
+ retry: options?.retry,
115
+ partialOutput: options?.partialOutput,
116
+ billing: options?.billing,
117
+ effect: options?.effect
118
+ };
119
+ }
120
+ function createValidationError(message, field, details) {
121
+ return createErrorResponse("VALIDATION_ERROR", message, {
122
+ category: "validation",
123
+ field,
124
+ details
125
+ });
126
+ }
127
+ function createNotFoundError(resource2, identifier) {
128
+ const message = identifier ? `${resource2} '${identifier}' not found` : `${resource2} not found`;
129
+ return createErrorResponse("NOT_FOUND", message, { category: "external" });
130
+ }
131
+ function createAuthError(message, options) {
132
+ return createErrorResponse(
133
+ options?.expired ? "AUTH_EXPIRED" : "AUTH_INVALID",
134
+ message,
135
+ { category: "auth", retry: options?.retry }
136
+ );
137
+ }
138
+ function createRateLimitError(retryAfterMs) {
139
+ return createErrorResponse(
140
+ "RATE_LIMITED",
141
+ "Rate limit exceeded. Please try again later.",
142
+ {
143
+ category: "external",
144
+ retry: {
145
+ allowed: true,
146
+ afterMs: retryAfterMs
147
+ }
148
+ }
149
+ );
150
+ }
151
+ function createExternalError(service, message, options) {
152
+ return createErrorResponse(
153
+ "EXTERNAL_SERVICE_ERROR",
154
+ `${service}: ${message}`,
155
+ {
156
+ category: "external",
157
+ retry: options?.retry ?? { allowed: true },
158
+ details: options?.details
159
+ }
160
+ );
161
+ }
162
+ function createTimeoutError(message = "Operation timed out", options) {
163
+ return createErrorResponse("TIMEOUT", message, {
164
+ category: "timeout",
165
+ retry: options?.retry ?? { allowed: true }
166
+ });
167
+ }
168
+ function createPermissionError(message = "Permission denied") {
169
+ return createErrorResponse("PERMISSION_DENIED", message, {
170
+ category: "auth"
171
+ });
172
+ }
173
+ function createConflictError(message, field) {
174
+ return createErrorResponse("CONFLICT", message, {
175
+ category: "validation",
176
+ field
177
+ });
178
+ }
179
+ function isSuccess(result) {
180
+ return result.success === true;
181
+ }
182
+ function isFailure(result) {
183
+ return result.success === false;
184
+ }
185
+ function isRetryable(result) {
186
+ if (result.retry?.allowed === false) return false;
187
+ if (result.retry?.allowed === true) return true;
188
+ const retryableCategories = [
189
+ "network",
190
+ "timeout",
191
+ "external"
192
+ ];
193
+ return result.error.category ? retryableCategories.includes(result.error.category) : false;
194
+ }
195
+ function getRetryDelay(result) {
196
+ return result.retry?.afterMs;
197
+ }
198
+
70
199
  // src/types/webhook.ts
71
200
  function isRuntimeWebhookContext(ctx) {
72
201
  return "appInstallationId" in ctx && ctx.appInstallationId !== void 0;
@@ -3272,28 +3401,69 @@ async function handleMcpToolsCall(params, id, ctx) {
3272
3401
  invocation: toolInvocation
3273
3402
  });
3274
3403
  let result;
3275
- if (toolResult.error) {
3276
- const errorOutput = { error: toolResult.error };
3404
+ const isNewShapeFailure = "success" in toolResult && toolResult.success === false;
3405
+ const isLegacyErrorFailure = "error" in toolResult && toolResult.error != null;
3406
+ const isLegacyMetaFailure = "meta" in toolResult && toolResult.meta != null && typeof toolResult.meta === "object" && "success" in toolResult.meta && toolResult.meta.success === false;
3407
+ const isFailure2 = isNewShapeFailure || isLegacyErrorFailure || isLegacyMetaFailure;
3408
+ if (isFailure2) {
3409
+ let errorOutput;
3410
+ if (isNewShapeFailure && "error" in toolResult) {
3411
+ errorOutput = {
3412
+ error: toolResult.error,
3413
+ retry: "retry" in toolResult ? toolResult.retry : void 0
3414
+ };
3415
+ } else if (isLegacyErrorFailure && "error" in toolResult) {
3416
+ errorOutput = { error: toolResult.error };
3417
+ } else if (isLegacyMetaFailure && "meta" in toolResult && toolResult.meta) {
3418
+ const meta = toolResult.meta;
3419
+ errorOutput = {
3420
+ error: {
3421
+ code: "TOOL_FAILED",
3422
+ message: meta.message ?? "Tool execution failed",
3423
+ category: "internal"
3424
+ }
3425
+ };
3426
+ } else {
3427
+ errorOutput = {
3428
+ error: {
3429
+ code: "TOOL_FAILED",
3430
+ message: "Tool execution failed",
3431
+ category: "internal"
3432
+ }
3433
+ };
3434
+ }
3277
3435
  result = {
3278
3436
  content: [{ type: "text", text: JSON.stringify(errorOutput) }],
3279
3437
  structuredContent: hasOutputSchema ? void 0 : errorOutput,
3280
3438
  isError: true,
3281
- billing: toolResult.billing
3439
+ billing: "billing" in toolResult ? toolResult.billing : void 0
3282
3440
  };
3283
3441
  } else {
3284
- const outputData = toolResult.output;
3442
+ const outputData = "output" in toolResult ? toolResult.output : null;
3443
+ const effect = "effect" in toolResult ? toolResult.effect : void 0;
3444
+ const warnings = "warnings" in toolResult ? toolResult.warnings : void 0;
3445
+ const pagination = "pagination" in toolResult ? toolResult.pagination : void 0;
3285
3446
  let structuredContent;
3286
3447
  if (outputData) {
3287
- structuredContent = { ...outputData, __effect: toolResult.effect };
3288
- } else if (toolResult.effect) {
3289
- structuredContent = { __effect: toolResult.effect };
3448
+ structuredContent = {
3449
+ ...outputData,
3450
+ __effect: effect,
3451
+ __warnings: warnings,
3452
+ __pagination: pagination
3453
+ };
3454
+ } else if (effect || warnings || pagination) {
3455
+ structuredContent = {
3456
+ __effect: effect,
3457
+ __warnings: warnings,
3458
+ __pagination: pagination
3459
+ };
3290
3460
  } else if (hasOutputSchema) {
3291
3461
  structuredContent = {};
3292
3462
  }
3293
3463
  result = {
3294
- content: [{ type: "text", text: JSON.stringify(toolResult.output) }],
3464
+ content: [{ type: "text", text: JSON.stringify(outputData) }],
3295
3465
  structuredContent,
3296
- billing: toolResult.billing
3466
+ billing: "billing" in toolResult ? toolResult.billing : void 0
3297
3467
  };
3298
3468
  }
3299
3469
  return {
@@ -3337,7 +3507,7 @@ function createOptionsResponse() {
3337
3507
  body: { message: "OK" }
3338
3508
  };
3339
3509
  }
3340
- function createErrorResponse(err) {
3510
+ function createErrorResponse2(err) {
3341
3511
  return {
3342
3512
  status: 500,
3343
3513
  body: {
@@ -3393,7 +3563,7 @@ async function routeRequest(req, ctx) {
3393
3563
  }
3394
3564
  return createNotFoundResponse();
3395
3565
  } catch (err) {
3396
- return createErrorResponse(err);
3566
+ return createErrorResponse2(err);
3397
3567
  }
3398
3568
  }
3399
3569
 
@@ -4076,9 +4246,20 @@ export {
4076
4246
  ai,
4077
4247
  communicationChannel,
4078
4248
  configure,
4249
+ createAuthError,
4250
+ createConflictError,
4079
4251
  createContextLogger,
4252
+ createErrorResponse,
4253
+ createExternalError,
4254
+ createListResponse,
4255
+ createNotFoundError,
4256
+ createPermissionError,
4257
+ createRateLimitError,
4080
4258
  createServerHookContext,
4259
+ createSuccessResponse,
4260
+ createTimeoutError,
4081
4261
  createToolCallContext,
4262
+ createValidationError,
4082
4263
  createWebhookContext,
4083
4264
  createWorkflowStepContext,
4084
4265
  src_default as default,
@@ -4094,12 +4275,16 @@ export {
4094
4275
  getAllEnvKeys,
4095
4276
  getConfig,
4096
4277
  getRequiredInstallEnvKeys,
4278
+ getRetryDelay,
4097
4279
  instance,
4098
4280
  isChannelDependency,
4281
+ isFailure,
4099
4282
  isModelDependency,
4100
4283
  isProvisionContext,
4284
+ isRetryable,
4101
4285
  isRuntimeContext,
4102
4286
  isRuntimeWebhookContext,
4287
+ isSuccess,
4103
4288
  isWorkflowDependency,
4104
4289
  loadConfig,
4105
4290
  report,
package/dist/index.js CHANGED
@@ -135,9 +135,20 @@ __export(index_exports, {
135
135
  ai: () => ai,
136
136
  communicationChannel: () => communicationChannel,
137
137
  configure: () => configure,
138
+ createAuthError: () => createAuthError,
139
+ createConflictError: () => createConflictError,
138
140
  createContextLogger: () => createContextLogger,
141
+ createErrorResponse: () => createErrorResponse,
142
+ createExternalError: () => createExternalError,
143
+ createListResponse: () => createListResponse,
144
+ createNotFoundError: () => createNotFoundError,
145
+ createPermissionError: () => createPermissionError,
146
+ createRateLimitError: () => createRateLimitError,
139
147
  createServerHookContext: () => createServerHookContext,
148
+ createSuccessResponse: () => createSuccessResponse,
149
+ createTimeoutError: () => createTimeoutError,
140
150
  createToolCallContext: () => createToolCallContext,
151
+ createValidationError: () => createValidationError,
141
152
  createWebhookContext: () => createWebhookContext,
142
153
  createWorkflowStepContext: () => createWorkflowStepContext,
143
154
  default: () => index_default,
@@ -153,12 +164,16 @@ __export(index_exports, {
153
164
  getAllEnvKeys: () => getAllEnvKeys,
154
165
  getConfig: () => getConfig,
155
166
  getRequiredInstallEnvKeys: () => getRequiredInstallEnvKeys,
167
+ getRetryDelay: () => getRetryDelay,
156
168
  instance: () => instance,
157
169
  isChannelDependency: () => isChannelDependency,
170
+ isFailure: () => isFailure,
158
171
  isModelDependency: () => isModelDependency,
159
172
  isProvisionContext: () => isProvisionContext,
173
+ isRetryable: () => isRetryable,
160
174
  isRuntimeContext: () => isRuntimeContext,
161
175
  isRuntimeWebhookContext: () => isRuntimeWebhookContext,
176
+ isSuccess: () => isSuccess,
162
177
  isWorkflowDependency: () => isWorkflowDependency,
163
178
  loadConfig: () => loadConfig,
164
179
  report: () => report,
@@ -225,14 +240,143 @@ function isRuntimeContext(ctx) {
225
240
  // src/types/tool.ts
226
241
  var import_v4 = require("zod/v4");
227
242
  var ToolResponseMetaSchema = import_v4.z.object({
228
- /** Whether the tool execution succeeded */
229
243
  success: import_v4.z.boolean(),
230
- /** Human-readable message describing the result or error */
231
244
  message: import_v4.z.string(),
232
- /** Name of the tool that was executed */
233
245
  toolName: import_v4.z.string()
234
246
  });
235
247
 
248
+ // src/types/tool-response.ts
249
+ function createSuccessResponse(output, options) {
250
+ return {
251
+ success: true,
252
+ output,
253
+ ...options
254
+ };
255
+ }
256
+ function createListResponse(items, pagination, options) {
257
+ return {
258
+ success: true,
259
+ output: items,
260
+ pagination,
261
+ ...options
262
+ };
263
+ }
264
+ function inferCategory(code) {
265
+ switch (code) {
266
+ case "VALIDATION_ERROR":
267
+ case "CONFLICT":
268
+ return "validation";
269
+ case "AUTH_INVALID":
270
+ case "AUTH_EXPIRED":
271
+ case "PERMISSION_DENIED":
272
+ return "auth";
273
+ case "TIMEOUT":
274
+ return "timeout";
275
+ case "RATE_LIMITED":
276
+ case "EXTERNAL_SERVICE_ERROR":
277
+ case "NOT_FOUND":
278
+ case "QUOTA_EXCEEDED":
279
+ return "external";
280
+ default:
281
+ return "internal";
282
+ }
283
+ }
284
+ function createErrorResponse(code, message, options) {
285
+ const category = options?.category ?? inferCategory(code);
286
+ return {
287
+ success: false,
288
+ error: {
289
+ code,
290
+ message,
291
+ category,
292
+ field: options?.field,
293
+ details: options?.details
294
+ },
295
+ retry: options?.retry,
296
+ partialOutput: options?.partialOutput,
297
+ billing: options?.billing,
298
+ effect: options?.effect
299
+ };
300
+ }
301
+ function createValidationError(message, field, details) {
302
+ return createErrorResponse("VALIDATION_ERROR", message, {
303
+ category: "validation",
304
+ field,
305
+ details
306
+ });
307
+ }
308
+ function createNotFoundError(resource2, identifier) {
309
+ const message = identifier ? `${resource2} '${identifier}' not found` : `${resource2} not found`;
310
+ return createErrorResponse("NOT_FOUND", message, { category: "external" });
311
+ }
312
+ function createAuthError(message, options) {
313
+ return createErrorResponse(
314
+ options?.expired ? "AUTH_EXPIRED" : "AUTH_INVALID",
315
+ message,
316
+ { category: "auth", retry: options?.retry }
317
+ );
318
+ }
319
+ function createRateLimitError(retryAfterMs) {
320
+ return createErrorResponse(
321
+ "RATE_LIMITED",
322
+ "Rate limit exceeded. Please try again later.",
323
+ {
324
+ category: "external",
325
+ retry: {
326
+ allowed: true,
327
+ afterMs: retryAfterMs
328
+ }
329
+ }
330
+ );
331
+ }
332
+ function createExternalError(service, message, options) {
333
+ return createErrorResponse(
334
+ "EXTERNAL_SERVICE_ERROR",
335
+ `${service}: ${message}`,
336
+ {
337
+ category: "external",
338
+ retry: options?.retry ?? { allowed: true },
339
+ details: options?.details
340
+ }
341
+ );
342
+ }
343
+ function createTimeoutError(message = "Operation timed out", options) {
344
+ return createErrorResponse("TIMEOUT", message, {
345
+ category: "timeout",
346
+ retry: options?.retry ?? { allowed: true }
347
+ });
348
+ }
349
+ function createPermissionError(message = "Permission denied") {
350
+ return createErrorResponse("PERMISSION_DENIED", message, {
351
+ category: "auth"
352
+ });
353
+ }
354
+ function createConflictError(message, field) {
355
+ return createErrorResponse("CONFLICT", message, {
356
+ category: "validation",
357
+ field
358
+ });
359
+ }
360
+ function isSuccess(result) {
361
+ return result.success === true;
362
+ }
363
+ function isFailure(result) {
364
+ return result.success === false;
365
+ }
366
+ function isRetryable(result) {
367
+ if (result.retry?.allowed === false) return false;
368
+ if (result.retry?.allowed === true) return true;
369
+ const retryableCategories = [
370
+ "network",
371
+ "timeout",
372
+ "external"
373
+ ];
374
+ return result.error.category ? retryableCategories.includes(result.error.category) : false;
375
+ }
376
+ function getRetryDelay(result) {
377
+ return result.retry?.afterMs;
378
+ }
379
+
236
380
  // src/types/webhook.ts
237
381
  function isRuntimeWebhookContext(ctx) {
238
382
  return "appInstallationId" in ctx && ctx.appInstallationId !== void 0;
@@ -3438,28 +3582,69 @@ async function handleMcpToolsCall(params, id, ctx) {
3438
3582
  invocation: toolInvocation
3439
3583
  });
3440
3584
  let result;
3441
- if (toolResult.error) {
3442
- const errorOutput = { error: toolResult.error };
3585
+ const isNewShapeFailure = "success" in toolResult && toolResult.success === false;
3586
+ const isLegacyErrorFailure = "error" in toolResult && toolResult.error != null;
3587
+ const isLegacyMetaFailure = "meta" in toolResult && toolResult.meta != null && typeof toolResult.meta === "object" && "success" in toolResult.meta && toolResult.meta.success === false;
3588
+ const isFailure2 = isNewShapeFailure || isLegacyErrorFailure || isLegacyMetaFailure;
3589
+ if (isFailure2) {
3590
+ let errorOutput;
3591
+ if (isNewShapeFailure && "error" in toolResult) {
3592
+ errorOutput = {
3593
+ error: toolResult.error,
3594
+ retry: "retry" in toolResult ? toolResult.retry : void 0
3595
+ };
3596
+ } else if (isLegacyErrorFailure && "error" in toolResult) {
3597
+ errorOutput = { error: toolResult.error };
3598
+ } else if (isLegacyMetaFailure && "meta" in toolResult && toolResult.meta) {
3599
+ const meta = toolResult.meta;
3600
+ errorOutput = {
3601
+ error: {
3602
+ code: "TOOL_FAILED",
3603
+ message: meta.message ?? "Tool execution failed",
3604
+ category: "internal"
3605
+ }
3606
+ };
3607
+ } else {
3608
+ errorOutput = {
3609
+ error: {
3610
+ code: "TOOL_FAILED",
3611
+ message: "Tool execution failed",
3612
+ category: "internal"
3613
+ }
3614
+ };
3615
+ }
3443
3616
  result = {
3444
3617
  content: [{ type: "text", text: JSON.stringify(errorOutput) }],
3445
3618
  structuredContent: hasOutputSchema ? void 0 : errorOutput,
3446
3619
  isError: true,
3447
- billing: toolResult.billing
3620
+ billing: "billing" in toolResult ? toolResult.billing : void 0
3448
3621
  };
3449
3622
  } else {
3450
- const outputData = toolResult.output;
3623
+ const outputData = "output" in toolResult ? toolResult.output : null;
3624
+ const effect = "effect" in toolResult ? toolResult.effect : void 0;
3625
+ const warnings = "warnings" in toolResult ? toolResult.warnings : void 0;
3626
+ const pagination = "pagination" in toolResult ? toolResult.pagination : void 0;
3451
3627
  let structuredContent;
3452
3628
  if (outputData) {
3453
- structuredContent = { ...outputData, __effect: toolResult.effect };
3454
- } else if (toolResult.effect) {
3455
- structuredContent = { __effect: toolResult.effect };
3629
+ structuredContent = {
3630
+ ...outputData,
3631
+ __effect: effect,
3632
+ __warnings: warnings,
3633
+ __pagination: pagination
3634
+ };
3635
+ } else if (effect || warnings || pagination) {
3636
+ structuredContent = {
3637
+ __effect: effect,
3638
+ __warnings: warnings,
3639
+ __pagination: pagination
3640
+ };
3456
3641
  } else if (hasOutputSchema) {
3457
3642
  structuredContent = {};
3458
3643
  }
3459
3644
  result = {
3460
- content: [{ type: "text", text: JSON.stringify(toolResult.output) }],
3645
+ content: [{ type: "text", text: JSON.stringify(outputData) }],
3461
3646
  structuredContent,
3462
- billing: toolResult.billing
3647
+ billing: "billing" in toolResult ? toolResult.billing : void 0
3463
3648
  };
3464
3649
  }
3465
3650
  return {
@@ -3503,7 +3688,7 @@ function createOptionsResponse() {
3503
3688
  body: { message: "OK" }
3504
3689
  };
3505
3690
  }
3506
- function createErrorResponse(err) {
3691
+ function createErrorResponse2(err) {
3507
3692
  return {
3508
3693
  status: 500,
3509
3694
  body: {
@@ -3559,7 +3744,7 @@ async function routeRequest(req, ctx) {
3559
3744
  }
3560
3745
  return createNotFoundResponse();
3561
3746
  } catch (err) {
3562
- return createErrorResponse(err);
3747
+ return createErrorResponse2(err);
3563
3748
  }
3564
3749
  }
3565
3750
 
@@ -4243,9 +4428,20 @@ var index_default = { z: import_v44.z };
4243
4428
  ai,
4244
4429
  communicationChannel,
4245
4430
  configure,
4431
+ createAuthError,
4432
+ createConflictError,
4246
4433
  createContextLogger,
4434
+ createErrorResponse,
4435
+ createExternalError,
4436
+ createListResponse,
4437
+ createNotFoundError,
4438
+ createPermissionError,
4439
+ createRateLimitError,
4247
4440
  createServerHookContext,
4441
+ createSuccessResponse,
4442
+ createTimeoutError,
4248
4443
  createToolCallContext,
4444
+ createValidationError,
4249
4445
  createWebhookContext,
4250
4446
  createWorkflowStepContext,
4251
4447
  defineAgent,
@@ -4260,12 +4456,16 @@ var index_default = { z: import_v44.z };
4260
4456
  getAllEnvKeys,
4261
4457
  getConfig,
4262
4458
  getRequiredInstallEnvKeys,
4459
+ getRetryDelay,
4263
4460
  instance,
4264
4461
  isChannelDependency,
4462
+ isFailure,
4265
4463
  isModelDependency,
4266
4464
  isProvisionContext,
4465
+ isRetryable,
4267
4466
  isRuntimeContext,
4268
4467
  isRuntimeWebhookContext,
4468
+ isSuccess,
4269
4469
  isWorkflowDependency,
4270
4470
  loadConfig,
4271
4471
  report,
package/dist/server.js CHANGED
@@ -1546,28 +1546,69 @@ async function handleMcpToolsCall(params, id, ctx) {
1546
1546
  invocation: toolInvocation
1547
1547
  });
1548
1548
  let result;
1549
- if (toolResult.error) {
1550
- const errorOutput = { error: toolResult.error };
1549
+ const isNewShapeFailure = "success" in toolResult && toolResult.success === false;
1550
+ const isLegacyErrorFailure = "error" in toolResult && toolResult.error != null;
1551
+ const isLegacyMetaFailure = "meta" in toolResult && toolResult.meta != null && typeof toolResult.meta === "object" && "success" in toolResult.meta && toolResult.meta.success === false;
1552
+ const isFailure = isNewShapeFailure || isLegacyErrorFailure || isLegacyMetaFailure;
1553
+ if (isFailure) {
1554
+ let errorOutput;
1555
+ if (isNewShapeFailure && "error" in toolResult) {
1556
+ errorOutput = {
1557
+ error: toolResult.error,
1558
+ retry: "retry" in toolResult ? toolResult.retry : void 0
1559
+ };
1560
+ } else if (isLegacyErrorFailure && "error" in toolResult) {
1561
+ errorOutput = { error: toolResult.error };
1562
+ } else if (isLegacyMetaFailure && "meta" in toolResult && toolResult.meta) {
1563
+ const meta = toolResult.meta;
1564
+ errorOutput = {
1565
+ error: {
1566
+ code: "TOOL_FAILED",
1567
+ message: meta.message ?? "Tool execution failed",
1568
+ category: "internal"
1569
+ }
1570
+ };
1571
+ } else {
1572
+ errorOutput = {
1573
+ error: {
1574
+ code: "TOOL_FAILED",
1575
+ message: "Tool execution failed",
1576
+ category: "internal"
1577
+ }
1578
+ };
1579
+ }
1551
1580
  result = {
1552
1581
  content: [{ type: "text", text: JSON.stringify(errorOutput) }],
1553
1582
  structuredContent: hasOutputSchema ? void 0 : errorOutput,
1554
1583
  isError: true,
1555
- billing: toolResult.billing
1584
+ billing: "billing" in toolResult ? toolResult.billing : void 0
1556
1585
  };
1557
1586
  } else {
1558
- const outputData = toolResult.output;
1587
+ const outputData = "output" in toolResult ? toolResult.output : null;
1588
+ const effect = "effect" in toolResult ? toolResult.effect : void 0;
1589
+ const warnings = "warnings" in toolResult ? toolResult.warnings : void 0;
1590
+ const pagination = "pagination" in toolResult ? toolResult.pagination : void 0;
1559
1591
  let structuredContent;
1560
1592
  if (outputData) {
1561
- structuredContent = { ...outputData, __effect: toolResult.effect };
1562
- } else if (toolResult.effect) {
1563
- structuredContent = { __effect: toolResult.effect };
1593
+ structuredContent = {
1594
+ ...outputData,
1595
+ __effect: effect,
1596
+ __warnings: warnings,
1597
+ __pagination: pagination
1598
+ };
1599
+ } else if (effect || warnings || pagination) {
1600
+ structuredContent = {
1601
+ __effect: effect,
1602
+ __warnings: warnings,
1603
+ __pagination: pagination
1604
+ };
1564
1605
  } else if (hasOutputSchema) {
1565
1606
  structuredContent = {};
1566
1607
  }
1567
1608
  result = {
1568
- content: [{ type: "text", text: JSON.stringify(toolResult.output) }],
1609
+ content: [{ type: "text", text: JSON.stringify(outputData) }],
1569
1610
  structuredContent,
1570
- billing: toolResult.billing
1611
+ billing: "billing" in toolResult ? toolResult.billing : void 0
1571
1612
  };
1572
1613
  }
1573
1614
  return {
@@ -1507,28 +1507,69 @@ async function handleMcpToolsCall(params, id, ctx) {
1507
1507
  invocation: toolInvocation
1508
1508
  });
1509
1509
  let result;
1510
- if (toolResult.error) {
1511
- const errorOutput = { error: toolResult.error };
1510
+ const isNewShapeFailure = "success" in toolResult && toolResult.success === false;
1511
+ const isLegacyErrorFailure = "error" in toolResult && toolResult.error != null;
1512
+ const isLegacyMetaFailure = "meta" in toolResult && toolResult.meta != null && typeof toolResult.meta === "object" && "success" in toolResult.meta && toolResult.meta.success === false;
1513
+ const isFailure = isNewShapeFailure || isLegacyErrorFailure || isLegacyMetaFailure;
1514
+ if (isFailure) {
1515
+ let errorOutput;
1516
+ if (isNewShapeFailure && "error" in toolResult) {
1517
+ errorOutput = {
1518
+ error: toolResult.error,
1519
+ retry: "retry" in toolResult ? toolResult.retry : void 0
1520
+ };
1521
+ } else if (isLegacyErrorFailure && "error" in toolResult) {
1522
+ errorOutput = { error: toolResult.error };
1523
+ } else if (isLegacyMetaFailure && "meta" in toolResult && toolResult.meta) {
1524
+ const meta = toolResult.meta;
1525
+ errorOutput = {
1526
+ error: {
1527
+ code: "TOOL_FAILED",
1528
+ message: meta.message ?? "Tool execution failed",
1529
+ category: "internal"
1530
+ }
1531
+ };
1532
+ } else {
1533
+ errorOutput = {
1534
+ error: {
1535
+ code: "TOOL_FAILED",
1536
+ message: "Tool execution failed",
1537
+ category: "internal"
1538
+ }
1539
+ };
1540
+ }
1512
1541
  result = {
1513
1542
  content: [{ type: "text", text: JSON.stringify(errorOutput) }],
1514
1543
  structuredContent: hasOutputSchema ? void 0 : errorOutput,
1515
1544
  isError: true,
1516
- billing: toolResult.billing
1545
+ billing: "billing" in toolResult ? toolResult.billing : void 0
1517
1546
  };
1518
1547
  } else {
1519
- const outputData = toolResult.output;
1548
+ const outputData = "output" in toolResult ? toolResult.output : null;
1549
+ const effect = "effect" in toolResult ? toolResult.effect : void 0;
1550
+ const warnings = "warnings" in toolResult ? toolResult.warnings : void 0;
1551
+ const pagination = "pagination" in toolResult ? toolResult.pagination : void 0;
1520
1552
  let structuredContent;
1521
1553
  if (outputData) {
1522
- structuredContent = { ...outputData, __effect: toolResult.effect };
1523
- } else if (toolResult.effect) {
1524
- structuredContent = { __effect: toolResult.effect };
1554
+ structuredContent = {
1555
+ ...outputData,
1556
+ __effect: effect,
1557
+ __warnings: warnings,
1558
+ __pagination: pagination
1559
+ };
1560
+ } else if (effect || warnings || pagination) {
1561
+ structuredContent = {
1562
+ __effect: effect,
1563
+ __warnings: warnings,
1564
+ __pagination: pagination
1565
+ };
1525
1566
  } else if (hasOutputSchema) {
1526
1567
  structuredContent = {};
1527
1568
  }
1528
1569
  result = {
1529
- content: [{ type: "text", text: JSON.stringify(toolResult.output) }],
1570
+ content: [{ type: "text", text: JSON.stringify(outputData) }],
1530
1571
  structuredContent,
1531
- billing: toolResult.billing
1572
+ billing: "billing" in toolResult ? toolResult.billing : void 0
1532
1573
  };
1533
1574
  }
1534
1575
  return {
@@ -9,8 +9,9 @@ export type { InvocationType, ServerHookHandle, InvocationContext, } from './inv
9
9
  export { createToolCallContext, createServerHookContext, createWebhookContext, createWorkflowStepContext, } from './invocation';
10
10
  export type { ToolTrigger, ProvisionToolContext, FieldChangeToolContext, PageActionToolContext, FormSubmitToolContext, AgentToolContext, WorkflowToolContext, ToolExecutionContext, } from './tool-context';
11
11
  export { isProvisionContext, isRuntimeContext } from './tool-context';
12
- export type { BillingInfo, ToolResponseMeta, ToolEffect, ToolError, ToolExecutionResult, ToolSchemaWithJson, ToolSchema, ToolHandler, ToolDefinition, ToolRegistryEntry, ToolRegistry, ToolName, ToolMetadata, ToolCallResponse, } from './tool';
12
+ export type { ToolResult, ToolSuccess, ToolFailure, ErrorCode, ErrorCategory, ToolWarning, ToolPagination, ToolBilling, ToolRetry, ToolTiming, BillingInfo, ToolResponseMeta, ToolEffect, ToolError, ToolExecutionResult, ToolSchemaWithJson, ToolSchema, ToolHandler, ToolDefinition, ToolRegistryEntry, ToolRegistry, ToolName, ToolMetadata, ToolCallResponse, } from './tool';
13
13
  export { ToolResponseMetaSchema } from './tool';
14
+ export { createSuccessResponse, createListResponse, createErrorResponse, createValidationError, createNotFoundError, createAuthError, createRateLimitError, createExternalError, createTimeoutError, createPermissionError, createConflictError, isSuccess, isFailure, isRetryable, getRetryDelay, } from './tool-response';
14
15
  export type { HealthStatus, ComputeLayer, DedicatedServerInstance, ServerlessServerInstance, SkedyulServerInstance, } from './server';
15
16
  export type { InstallHandlerContext, InstallHandlerResponseOAuth, InstallHandlerResponseStandard, HasOAuthCallback, InstallHandlerResult, InstallHandler, UninstallHandlerContext, UninstallHandlerResult, UninstallHandler, OAuthCallbackContext, OAuthCallbackResult, OAuthCallbackHandler, ProvisionHandlerContext, ProvisionHandlerResult, ProvisionHandler, ServerHooksWithOAuth, ServerHooksWithoutOAuth, ServerHooks, } from './handlers';
16
17
  export type { APIGatewayProxyEvent, APIGatewayProxyResult } from './aws';
@@ -0,0 +1,186 @@
1
+ import type { ToolSuccess, ToolFailure, ToolResult, ErrorCode, ErrorCategory, ToolWarning, ToolPagination, ToolBilling, ToolEffect, ToolRetry } from './tool';
2
+ /**
3
+ * Create a successful tool result.
4
+ *
5
+ * @example
6
+ * ```ts
7
+ * import { createSuccessResponse } from 'skedyul'
8
+ *
9
+ * return createSuccessResponse({ order: orderData })
10
+ * ```
11
+ */
12
+ export declare function createSuccessResponse<T>(output: T, options?: {
13
+ warnings?: ToolWarning[];
14
+ pagination?: ToolPagination;
15
+ billing?: ToolBilling;
16
+ effect?: ToolEffect;
17
+ }): ToolSuccess<T>;
18
+ /**
19
+ * Create a successful list response with pagination.
20
+ *
21
+ * @example
22
+ * ```ts
23
+ * import { createListResponse } from 'skedyul'
24
+ *
25
+ * return createListResponse(items, { hasMore: true, total: 100 })
26
+ * ```
27
+ */
28
+ export declare function createListResponse<T>(items: T[], pagination: ToolPagination, options?: {
29
+ warnings?: ToolWarning[];
30
+ billing?: ToolBilling;
31
+ }): ToolSuccess<T[]>;
32
+ /**
33
+ * Create a failed tool result with full control over error details.
34
+ *
35
+ * @example
36
+ * ```ts
37
+ * import { createErrorResponse } from 'skedyul'
38
+ *
39
+ * return createErrorResponse('NOT_FOUND', 'Order not found')
40
+ * ```
41
+ */
42
+ export declare function createErrorResponse(code: ErrorCode, message: string, options?: {
43
+ category?: ErrorCategory;
44
+ field?: string;
45
+ details?: Record<string, unknown>;
46
+ retry?: ToolRetry;
47
+ partialOutput?: unknown;
48
+ billing?: ToolBilling;
49
+ effect?: ToolEffect;
50
+ }): ToolFailure;
51
+ /**
52
+ * Create a validation error result.
53
+ *
54
+ * @example
55
+ * ```ts
56
+ * import { createValidationError } from 'skedyul'
57
+ *
58
+ * return createValidationError('Email is required', 'email')
59
+ * ```
60
+ */
61
+ export declare function createValidationError(message: string, field?: string, details?: Record<string, unknown>): ToolFailure;
62
+ /**
63
+ * Create a not found error result.
64
+ *
65
+ * @example
66
+ * ```ts
67
+ * import { createNotFoundError } from 'skedyul'
68
+ *
69
+ * return createNotFoundError('Order', orderId)
70
+ * // Error message: "Order 'abc123' not found"
71
+ * ```
72
+ */
73
+ export declare function createNotFoundError(resource: string, identifier?: string): ToolFailure;
74
+ /**
75
+ * Create an authentication error result.
76
+ *
77
+ * @example
78
+ * ```ts
79
+ * import { createAuthError } from 'skedyul'
80
+ *
81
+ * return createAuthError('Invalid API key')
82
+ * return createAuthError('Token expired', { expired: true })
83
+ * ```
84
+ */
85
+ export declare function createAuthError(message: string, options?: {
86
+ expired?: boolean;
87
+ retry?: ToolRetry;
88
+ }): ToolFailure;
89
+ /**
90
+ * Create a rate limit error result.
91
+ *
92
+ * @example
93
+ * ```ts
94
+ * import { createRateLimitError } from 'skedyul'
95
+ *
96
+ * return createRateLimitError(60000) // Retry after 60 seconds
97
+ * ```
98
+ */
99
+ export declare function createRateLimitError(retryAfterMs?: number): ToolFailure;
100
+ /**
101
+ * Create an external service error result.
102
+ *
103
+ * @example
104
+ * ```ts
105
+ * import { createExternalError } from 'skedyul'
106
+ *
107
+ * return createExternalError('Petbooqz API', 'Connection timeout')
108
+ * ```
109
+ */
110
+ export declare function createExternalError(service: string, message: string, options?: {
111
+ retry?: ToolRetry;
112
+ details?: Record<string, unknown>;
113
+ }): ToolFailure;
114
+ /**
115
+ * Create a timeout error result.
116
+ *
117
+ * @example
118
+ * ```ts
119
+ * import { createTimeoutError } from 'skedyul'
120
+ *
121
+ * return createTimeoutError('Request timed out after 30 seconds')
122
+ * ```
123
+ */
124
+ export declare function createTimeoutError(message?: string, options?: {
125
+ retry?: ToolRetry;
126
+ }): ToolFailure;
127
+ /**
128
+ * Create a permission denied error result.
129
+ *
130
+ * @example
131
+ * ```ts
132
+ * import { createPermissionError } from 'skedyul'
133
+ *
134
+ * return createPermissionError('You do not have access to this resource')
135
+ * ```
136
+ */
137
+ export declare function createPermissionError(message?: string): ToolFailure;
138
+ /**
139
+ * Create a conflict error result (e.g., duplicate resource).
140
+ *
141
+ * @example
142
+ * ```ts
143
+ * import { createConflictError } from 'skedyul'
144
+ *
145
+ * return createConflictError('A client with this email already exists')
146
+ * ```
147
+ */
148
+ export declare function createConflictError(message: string, field?: string): ToolFailure;
149
+ /**
150
+ * Type guard to check if a result is successful.
151
+ *
152
+ * @example
153
+ * ```ts
154
+ * if (isSuccess(result)) {
155
+ * console.log(result.output) // TypeScript knows output exists
156
+ * }
157
+ * ```
158
+ */
159
+ export declare function isSuccess<T>(result: ToolResult<T>): result is ToolSuccess<T>;
160
+ /**
161
+ * Type guard to check if a result is a failure.
162
+ *
163
+ * @example
164
+ * ```ts
165
+ * if (isFailure(result)) {
166
+ * console.log(result.error.code) // TypeScript knows error exists
167
+ * }
168
+ * ```
169
+ */
170
+ export declare function isFailure(result: ToolResult<unknown>): result is ToolFailure;
171
+ /**
172
+ * Check if an error is retryable based on its category and retry hints.
173
+ *
174
+ * @example
175
+ * ```ts
176
+ * if (isFailure(result) && isRetryable(result)) {
177
+ * // Schedule retry
178
+ * }
179
+ * ```
180
+ */
181
+ export declare function isRetryable(result: ToolFailure): boolean;
182
+ /**
183
+ * Get the suggested retry delay in milliseconds.
184
+ * Returns undefined if no retry hint is available.
185
+ */
186
+ export declare function getRetryDelay(result: ToolFailure): number | undefined;
@@ -5,45 +5,151 @@ import type { ToolExecutionContext } from './tool-context';
5
5
  * These tools receive no user input - all data comes from context.
6
6
  */
7
7
  export type ProvisionToolInput = Record<string, never>;
8
+ /**
9
+ * Standardized error codes for consistent handling across tools.
10
+ * Custom codes are allowed for tool-specific errors.
11
+ */
12
+ export type ErrorCode = 'VALIDATION_ERROR' | 'NOT_FOUND' | 'AUTH_INVALID' | 'AUTH_EXPIRED' | 'PERMISSION_DENIED' | 'RATE_LIMITED' | 'TIMEOUT' | 'EXTERNAL_SERVICE_ERROR' | 'INTERNAL_ERROR' | 'QUOTA_EXCEEDED' | 'CONFLICT' | string;
13
+ /**
14
+ * Error category for smart retry logic.
15
+ * - validation: Don't retry, fix the input
16
+ * - auth: May need user action (re-login)
17
+ * - network: Retry with backoff
18
+ * - timeout: Retry with longer timeout
19
+ * - external: Retry with backoff
20
+ * - internal: May retry, but likely a bug
21
+ */
22
+ export type ErrorCategory = 'validation' | 'auth' | 'network' | 'timeout' | 'external' | 'internal';
23
+ /**
24
+ * Structured error information with category for smart retry logic.
25
+ */
26
+ export interface ToolError {
27
+ code: ErrorCode;
28
+ message: string;
29
+ category?: ErrorCategory;
30
+ field?: string;
31
+ details?: Record<string, unknown>;
32
+ }
33
+ /**
34
+ * Retry guidance for transient failures.
35
+ */
36
+ export interface ToolRetry {
37
+ allowed: boolean;
38
+ afterMs?: number;
39
+ maxAttempts?: number;
40
+ }
41
+ /**
42
+ * Non-fatal warning that doesn't prevent success.
43
+ */
44
+ export interface ToolWarning {
45
+ code: string;
46
+ message: string;
47
+ field?: string;
48
+ }
49
+ /**
50
+ * Pagination metadata for list operations.
51
+ */
52
+ export interface ToolPagination {
53
+ hasMore: boolean;
54
+ total?: number;
55
+ nextCursor?: string;
56
+ page?: number;
57
+ limit?: number;
58
+ }
59
+ /**
60
+ * Billing/usage information.
61
+ */
62
+ export interface ToolBilling {
63
+ credits: number;
64
+ tokens?: number;
65
+ cost?: number;
66
+ }
67
+ /**
68
+ * Client-side effects to execute after tool completion.
69
+ */
70
+ export interface ToolEffect {
71
+ redirect?: string;
72
+ toast?: {
73
+ type: 'success' | 'error' | 'warning' | 'info';
74
+ message: string;
75
+ };
76
+ refresh?: string[];
77
+ }
78
+ /**
79
+ * Execution timing for observability.
80
+ */
81
+ export interface ToolTiming {
82
+ durationMs: number;
83
+ }
84
+ /**
85
+ * Successful tool execution result.
86
+ * Output is guaranteed to exist.
87
+ */
88
+ export interface ToolSuccess<T = unknown> {
89
+ success: true;
90
+ output: T;
91
+ warnings?: ToolWarning[];
92
+ pagination?: ToolPagination;
93
+ billing?: ToolBilling;
94
+ effect?: ToolEffect;
95
+ timing?: ToolTiming;
96
+ }
97
+ /**
98
+ * Failed tool execution result.
99
+ * Error is guaranteed to exist, output is not available.
100
+ */
101
+ export interface ToolFailure {
102
+ success: false;
103
+ error: ToolError;
104
+ retry?: ToolRetry;
105
+ partialOutput?: unknown;
106
+ billing?: ToolBilling;
107
+ effect?: ToolEffect;
108
+ timing?: ToolTiming;
109
+ }
110
+ /**
111
+ * Tool execution result - either success or failure.
112
+ * Use `result.success` to narrow the type.
113
+ *
114
+ * @example
115
+ * ```ts
116
+ * const result = await tool.handler(input, context)
117
+ * if (result.success) {
118
+ * console.log(result.output) // TypeScript knows output exists
119
+ * } else {
120
+ * console.log(result.error.code) // TypeScript knows error exists
121
+ * }
122
+ * ```
123
+ */
124
+ export type ToolResult<T = unknown> = ToolSuccess<T> | ToolFailure;
125
+ /**
126
+ * @deprecated Use ToolBilling instead
127
+ */
8
128
  export interface BillingInfo {
9
129
  credits: number;
10
130
  }
11
131
  /**
12
132
  * Standardized metadata for tool responses.
13
- * Provides consistent structure for AI evaluation, logging, and debugging.
133
+ * @deprecated Use ToolResult discriminated union instead
14
134
  */
15
135
  export declare const ToolResponseMetaSchema: z.ZodObject<{
16
136
  success: z.ZodBoolean;
17
137
  message: z.ZodString;
18
138
  toolName: z.ZodString;
19
139
  }, z.core.$strip>;
20
- export type ToolResponseMeta = z.infer<typeof ToolResponseMetaSchema>;
21
140
  /**
22
- * Client-side effects that the tool wants the UI to execute.
23
- * These are separate from the data output and represent navigation/UI actions.
141
+ * @deprecated Use ToolResult discriminated union instead
24
142
  */
25
- export interface ToolEffect {
26
- /** URL to navigate to after the tool completes */
27
- redirect?: string;
28
- }
143
+ export type ToolResponseMeta = z.infer<typeof ToolResponseMetaSchema>;
29
144
  /**
30
- * Structured error information for tool execution results.
31
- * Uses codes for serialization and workflow detection.
145
+ * Legacy tool execution result type.
146
+ * @deprecated Use ToolResult<T> instead. This type is kept for backward compatibility.
32
147
  */
33
- export interface ToolError {
34
- code: string;
35
- message: string;
36
- }
37
148
  export interface ToolExecutionResult<Output = unknown> {
38
- /** Tool-specific output data. Null on error. */
39
149
  output: Output | null;
40
- /** Billing information */
41
150
  billing: BillingInfo;
42
- /** Standardized response metadata for AI evaluation and debugging */
43
151
  meta: ToolResponseMeta;
44
- /** Optional client-side effects to execute */
45
152
  effect?: ToolEffect;
46
- /** Structured error information (null/undefined if no error) */
47
153
  error?: ToolError | null;
48
154
  }
49
155
  export interface ToolSchemaWithJson<Schema extends z.ZodTypeAny = z.ZodTypeAny> {
@@ -54,8 +160,9 @@ export type ToolSchema<Schema extends z.ZodTypeAny = z.ZodTypeAny> = Schema | To
54
160
  /**
55
161
  * Tool handler function signature.
56
162
  * Receives tool-specific input as first argument and standardized context as second.
163
+ * Supports both new ToolResult and legacy ToolExecutionResult return types.
57
164
  */
58
- export type ToolHandler<Input, Output> = (input: Input, context: ToolExecutionContext) => Promise<ToolExecutionResult<Output>> | ToolExecutionResult<Output>;
165
+ export type ToolHandler<Input, Output> = (input: Input, context: ToolExecutionContext) => Promise<ToolResult<Output> | ToolExecutionResult<Output>> | ToolResult<Output> | ToolExecutionResult<Output>;
59
166
  export interface ToolDefinition<Input = unknown, Output = unknown, InputSchema extends z.ZodTypeAny = z.ZodType<Input>, OutputSchema extends z.ZodTypeAny = z.ZodType<Output>> {
60
167
  name: string;
61
168
  label?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skedyul",
3
- "version": "1.2.40",
3
+ "version": "1.2.41",
4
4
  "description": "The Skedyul SDK for Node.js",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",