skedyul 1.7.8 → 1.7.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/server.js CHANGED
@@ -1988,6 +1988,39 @@ async function handleMcpBatchRoute(req, ctx) {
1988
1988
  }
1989
1989
  };
1990
1990
  }
1991
+ function isBatchOperationFailure(result) {
1992
+ return result != null && typeof result === "object" && result.success === false && typeof result.error === "object" && result.error != null;
1993
+ }
1994
+ function toStringEnv(env) {
1995
+ const out = {};
1996
+ for (const [key, value] of Object.entries(env)) {
1997
+ if (value !== void 0) {
1998
+ out[key] = value;
1999
+ }
2000
+ }
2001
+ return out;
2002
+ }
2003
+ function stripBillingFields(result) {
2004
+ const {
2005
+ billing: _billing,
2006
+ success: _success,
2007
+ error: _error,
2008
+ retry: _retry,
2009
+ ...domain
2010
+ } = result;
2011
+ return domain;
2012
+ }
2013
+ function softFailureResponse(error, retry, billing) {
2014
+ return {
2015
+ status: 200,
2016
+ body: {
2017
+ success: false,
2018
+ error,
2019
+ ...retry ? { retry } : {},
2020
+ billing: normalizeBilling(billing)
2021
+ }
2022
+ };
2023
+ }
1991
2024
  async function handleBatchOperationRoute(req, ctx) {
1992
2025
  const bodyResult = parseJsonBody(req);
1993
2026
  if (!bodyResult.success) {
@@ -1996,49 +2029,80 @@ async function handleBatchOperationRoute(req, ctx) {
1996
2029
  const body = bodyResult.data;
1997
2030
  const registry = ctx.batchOperationRegistry;
1998
2031
  if (!registry) {
1999
- return {
2000
- status: 404,
2001
- body: {
2002
- success: false,
2003
- error: "No batch operations registered"
2004
- }
2005
- };
2032
+ return softFailureResponse({
2033
+ code: "NOT_FOUND",
2034
+ message: "No batch operations registered",
2035
+ category: "validation"
2036
+ });
2006
2037
  }
2007
2038
  const operation = registry[body.handle];
2008
2039
  if (!operation) {
2009
- return {
2010
- status: 404,
2011
- body: {
2012
- success: false,
2013
- error: `Batch operation not found: ${body.handle}`
2014
- }
2015
- };
2040
+ return softFailureResponse({
2041
+ code: "NOT_FOUND",
2042
+ message: `Batch operation not found: ${body.handle}`,
2043
+ category: "validation"
2044
+ });
2016
2045
  }
2017
2046
  const context = body.context;
2018
2047
  if (!context?.workplaceId || !context?.appInstallationId || !context?.appId) {
2019
- return {
2020
- status: 400,
2021
- body: {
2022
- success: false,
2023
- error: "Missing context (workplaceId, appInstallationId, and appId required)"
2024
- }
2025
- };
2048
+ return softFailureResponse({
2049
+ code: "VALIDATION_ERROR",
2050
+ message: "Missing context (workplaceId, appInstallationId, and appId required)",
2051
+ category: "validation"
2052
+ });
2026
2053
  }
2027
- const env = body.env ?? {};
2028
- const log = {
2029
- info: (message, meta) => {
2030
- console.log(`[batch:${body.handle}] ${message}`, meta ?? "");
2031
- },
2032
- warn: (message, meta) => {
2033
- console.warn(`[batch:${body.handle}] ${message}`, meta ?? "");
2034
- },
2035
- error: (message, meta) => {
2036
- console.error(`[batch:${body.handle}] ${message}`, meta ?? "");
2037
- }
2054
+ if (body.method !== "setup" && body.method !== "iterate") {
2055
+ return softFailureResponse({
2056
+ code: "VALIDATION_ERROR",
2057
+ message: `Unknown method: ${body.method}`,
2058
+ category: "validation"
2059
+ });
2060
+ }
2061
+ const requestEnv = body.env ?? {};
2062
+ const mergedEnv = toStringEnv(buildToolExecutionEnv(requestEnv));
2063
+ const originalEnv = { ...process.env };
2064
+ Object.assign(process.env, mergedEnv);
2065
+ const log = createContextLogger();
2066
+ const app = context.app ?? {
2067
+ id: context.appId,
2068
+ versionId: context.appId
2069
+ };
2070
+ const workplace = context.workplace ?? {
2071
+ id: context.workplaceId,
2072
+ subdomain: ""
2073
+ };
2074
+ const invocation = body.invocation ?? {
2075
+ invocationId: `${body.handle}-${body.method}-${Date.now()}`,
2076
+ invocationType: "batch_operation",
2077
+ batchOperationHandle: body.handle,
2078
+ batchOperationMethod: body.method,
2079
+ appInstallationId: context.appInstallationId
2038
2080
  };
2039
2081
  const requestConfig = {
2040
- baseUrl: env.SKEDYUL_API_URL ?? process.env.SKEDYUL_API_URL ?? "",
2041
- apiToken: env.SKEDYUL_API_TOKEN ?? process.env.SKEDYUL_API_TOKEN ?? ""
2082
+ baseUrl: mergedEnv.SKEDYUL_API_URL ?? process.env.SKEDYUL_API_URL ?? "",
2083
+ apiToken: mergedEnv.SKEDYUL_API_TOKEN ?? process.env.SKEDYUL_API_TOKEN ?? ""
2084
+ };
2085
+ const rateLimitContext = {
2086
+ app,
2087
+ appInstallationId: context.appInstallationId,
2088
+ invocation,
2089
+ preAcquiredLeases: parsePreAcquiredLeases(
2090
+ mergedEnv.SKEDYUL_RATE_LIMIT_LEASES
2091
+ ),
2092
+ heldMutexQueueKeys: parseHeldMutexQueueKeys(
2093
+ mergedEnv.SKEDYUL_HELD_MUTEX_QUEUE_KEYS
2094
+ )
2095
+ };
2096
+ const opContextBase = {
2097
+ workplaceId: context.workplaceId,
2098
+ appInstallationId: context.appInstallationId,
2099
+ appId: context.appId,
2100
+ app,
2101
+ workplace,
2102
+ input: body.input,
2103
+ env: mergedEnv,
2104
+ invocation,
2105
+ log
2042
2106
  };
2043
2107
  try {
2044
2108
  if (body.method === "setup") {
@@ -2047,67 +2111,98 @@ async function handleBatchOperationRoute(req, ctx) {
2047
2111
  status: 200,
2048
2112
  body: {
2049
2113
  success: true,
2050
- result: { state: {}, total: void 0 }
2114
+ result: {
2115
+ state: {},
2116
+ total: void 0,
2117
+ cascade: operation.cascade
2118
+ },
2119
+ billing: normalizeBilling(void 0)
2051
2120
  }
2052
2121
  };
2053
2122
  }
2054
- const result = await runWithConfig(requestConfig, async () => {
2055
- return operation.setup({
2056
- workplaceId: context.workplaceId,
2057
- appInstallationId: context.appInstallationId,
2058
- appId: context.appId,
2059
- input: body.input,
2060
- env,
2061
- log
2123
+ const raw2 = await runWithConfig(requestConfig, async () => {
2124
+ return runWithRateLimitExecutionContext(rateLimitContext, async () => {
2125
+ return runWithLogContext({ invocation }, async () => {
2126
+ return operation.setup(opContextBase);
2127
+ });
2062
2128
  });
2063
2129
  });
2130
+ if (isBatchOperationFailure(raw2)) {
2131
+ return softFailureResponse(raw2.error, raw2.retry, raw2.billing);
2132
+ }
2133
+ const setupResult = raw2;
2134
+ const domain2 = stripBillingFields(
2135
+ setupResult
2136
+ );
2064
2137
  return {
2065
2138
  status: 200,
2066
2139
  body: {
2067
2140
  success: true,
2068
- result
2141
+ result: {
2142
+ ...domain2,
2143
+ // Expose definition cascade to the platform workflow
2144
+ cascade: operation.cascade ?? domain2.cascade
2145
+ },
2146
+ billing: normalizeBilling(setupResult.billing)
2069
2147
  }
2070
2148
  };
2071
2149
  }
2072
- if (body.method === "iterate") {
2073
- const result = await runWithConfig(requestConfig, async () => {
2074
- return operation.iterate({
2075
- workplaceId: context.workplaceId,
2076
- appInstallationId: context.appInstallationId,
2077
- appId: context.appId,
2078
- input: body.input,
2079
- state: body.state,
2080
- page: body.page,
2081
- cursor: body.cursor,
2082
- limit: body.limit,
2083
- env,
2084
- log
2150
+ const iterateBody = body;
2151
+ const raw = await runWithConfig(requestConfig, async () => {
2152
+ return runWithRateLimitExecutionContext(rateLimitContext, async () => {
2153
+ return runWithLogContext({ invocation }, async () => {
2154
+ return operation.iterate({
2155
+ ...opContextBase,
2156
+ state: iterateBody.state,
2157
+ page: iterateBody.page,
2158
+ cursor: iterateBody.cursor,
2159
+ limit: iterateBody.limit,
2160
+ cascadeEntities: iterateBody.cascadeEntities
2161
+ });
2085
2162
  });
2086
2163
  });
2087
- return {
2088
- status: 200,
2089
- body: {
2090
- success: true,
2091
- result
2092
- }
2093
- };
2164
+ });
2165
+ if (isBatchOperationFailure(raw)) {
2166
+ return softFailureResponse(raw.error, raw.retry, raw.billing);
2094
2167
  }
2168
+ const iterateResult = raw;
2169
+ const domain = stripBillingFields(
2170
+ iterateResult
2171
+ );
2095
2172
  return {
2096
- status: 400,
2173
+ status: 200,
2097
2174
  body: {
2098
- success: false,
2099
- error: `Unknown method: ${body.method}`
2175
+ success: true,
2176
+ result: domain,
2177
+ billing: normalizeBilling(iterateResult.billing)
2100
2178
  }
2101
2179
  };
2102
2180
  } catch (err) {
2103
- log.error("Batch operation failed", { error: err });
2181
+ if (err instanceof RateLimitExceededError) {
2182
+ return softFailureResponse(
2183
+ {
2184
+ code: "RATE_LIMITED",
2185
+ message: err.message,
2186
+ category: "external"
2187
+ },
2188
+ { allowed: true, afterMs: err.retryAfterMs }
2189
+ );
2190
+ }
2191
+ log.error("Batch operation failed", err);
2104
2192
  return {
2105
2193
  status: 500,
2106
2194
  body: {
2107
2195
  success: false,
2108
- error: err instanceof Error ? err.message : String(err)
2196
+ error: {
2197
+ code: "INTERNAL_ERROR",
2198
+ message: err instanceof Error ? err.message : String(err),
2199
+ category: "internal"
2200
+ },
2201
+ billing: normalizeBilling(void 0)
2109
2202
  }
2110
2203
  };
2204
+ } finally {
2205
+ process.env = originalEnv;
2111
2206
  }
2112
2207
  }
2113
2208
  function createNotFoundResponse() {
@@ -1949,6 +1949,39 @@ async function handleMcpBatchRoute(req, ctx) {
1949
1949
  }
1950
1950
  };
1951
1951
  }
1952
+ function isBatchOperationFailure(result) {
1953
+ return result != null && typeof result === "object" && result.success === false && typeof result.error === "object" && result.error != null;
1954
+ }
1955
+ function toStringEnv(env) {
1956
+ const out = {};
1957
+ for (const [key, value] of Object.entries(env)) {
1958
+ if (value !== void 0) {
1959
+ out[key] = value;
1960
+ }
1961
+ }
1962
+ return out;
1963
+ }
1964
+ function stripBillingFields(result) {
1965
+ const {
1966
+ billing: _billing,
1967
+ success: _success,
1968
+ error: _error,
1969
+ retry: _retry,
1970
+ ...domain
1971
+ } = result;
1972
+ return domain;
1973
+ }
1974
+ function softFailureResponse(error, retry, billing) {
1975
+ return {
1976
+ status: 200,
1977
+ body: {
1978
+ success: false,
1979
+ error,
1980
+ ...retry ? { retry } : {},
1981
+ billing: normalizeBilling(billing)
1982
+ }
1983
+ };
1984
+ }
1952
1985
  async function handleBatchOperationRoute(req, ctx) {
1953
1986
  const bodyResult = parseJsonBody(req);
1954
1987
  if (!bodyResult.success) {
@@ -1957,49 +1990,80 @@ async function handleBatchOperationRoute(req, ctx) {
1957
1990
  const body = bodyResult.data;
1958
1991
  const registry = ctx.batchOperationRegistry;
1959
1992
  if (!registry) {
1960
- return {
1961
- status: 404,
1962
- body: {
1963
- success: false,
1964
- error: "No batch operations registered"
1965
- }
1966
- };
1993
+ return softFailureResponse({
1994
+ code: "NOT_FOUND",
1995
+ message: "No batch operations registered",
1996
+ category: "validation"
1997
+ });
1967
1998
  }
1968
1999
  const operation = registry[body.handle];
1969
2000
  if (!operation) {
1970
- return {
1971
- status: 404,
1972
- body: {
1973
- success: false,
1974
- error: `Batch operation not found: ${body.handle}`
1975
- }
1976
- };
2001
+ return softFailureResponse({
2002
+ code: "NOT_FOUND",
2003
+ message: `Batch operation not found: ${body.handle}`,
2004
+ category: "validation"
2005
+ });
1977
2006
  }
1978
2007
  const context = body.context;
1979
2008
  if (!context?.workplaceId || !context?.appInstallationId || !context?.appId) {
1980
- return {
1981
- status: 400,
1982
- body: {
1983
- success: false,
1984
- error: "Missing context (workplaceId, appInstallationId, and appId required)"
1985
- }
1986
- };
2009
+ return softFailureResponse({
2010
+ code: "VALIDATION_ERROR",
2011
+ message: "Missing context (workplaceId, appInstallationId, and appId required)",
2012
+ category: "validation"
2013
+ });
1987
2014
  }
1988
- const env = body.env ?? {};
1989
- const log = {
1990
- info: (message, meta) => {
1991
- console.log(`[batch:${body.handle}] ${message}`, meta ?? "");
1992
- },
1993
- warn: (message, meta) => {
1994
- console.warn(`[batch:${body.handle}] ${message}`, meta ?? "");
1995
- },
1996
- error: (message, meta) => {
1997
- console.error(`[batch:${body.handle}] ${message}`, meta ?? "");
1998
- }
2015
+ if (body.method !== "setup" && body.method !== "iterate") {
2016
+ return softFailureResponse({
2017
+ code: "VALIDATION_ERROR",
2018
+ message: `Unknown method: ${body.method}`,
2019
+ category: "validation"
2020
+ });
2021
+ }
2022
+ const requestEnv = body.env ?? {};
2023
+ const mergedEnv = toStringEnv(buildToolExecutionEnv(requestEnv));
2024
+ const originalEnv = { ...process.env };
2025
+ Object.assign(process.env, mergedEnv);
2026
+ const log = createContextLogger();
2027
+ const app = context.app ?? {
2028
+ id: context.appId,
2029
+ versionId: context.appId
2030
+ };
2031
+ const workplace = context.workplace ?? {
2032
+ id: context.workplaceId,
2033
+ subdomain: ""
2034
+ };
2035
+ const invocation = body.invocation ?? {
2036
+ invocationId: `${body.handle}-${body.method}-${Date.now()}`,
2037
+ invocationType: "batch_operation",
2038
+ batchOperationHandle: body.handle,
2039
+ batchOperationMethod: body.method,
2040
+ appInstallationId: context.appInstallationId
1999
2041
  };
2000
2042
  const requestConfig = {
2001
- baseUrl: env.SKEDYUL_API_URL ?? process.env.SKEDYUL_API_URL ?? "",
2002
- apiToken: env.SKEDYUL_API_TOKEN ?? process.env.SKEDYUL_API_TOKEN ?? ""
2043
+ baseUrl: mergedEnv.SKEDYUL_API_URL ?? process.env.SKEDYUL_API_URL ?? "",
2044
+ apiToken: mergedEnv.SKEDYUL_API_TOKEN ?? process.env.SKEDYUL_API_TOKEN ?? ""
2045
+ };
2046
+ const rateLimitContext = {
2047
+ app,
2048
+ appInstallationId: context.appInstallationId,
2049
+ invocation,
2050
+ preAcquiredLeases: parsePreAcquiredLeases(
2051
+ mergedEnv.SKEDYUL_RATE_LIMIT_LEASES
2052
+ ),
2053
+ heldMutexQueueKeys: parseHeldMutexQueueKeys(
2054
+ mergedEnv.SKEDYUL_HELD_MUTEX_QUEUE_KEYS
2055
+ )
2056
+ };
2057
+ const opContextBase = {
2058
+ workplaceId: context.workplaceId,
2059
+ appInstallationId: context.appInstallationId,
2060
+ appId: context.appId,
2061
+ app,
2062
+ workplace,
2063
+ input: body.input,
2064
+ env: mergedEnv,
2065
+ invocation,
2066
+ log
2003
2067
  };
2004
2068
  try {
2005
2069
  if (body.method === "setup") {
@@ -2008,67 +2072,98 @@ async function handleBatchOperationRoute(req, ctx) {
2008
2072
  status: 200,
2009
2073
  body: {
2010
2074
  success: true,
2011
- result: { state: {}, total: void 0 }
2075
+ result: {
2076
+ state: {},
2077
+ total: void 0,
2078
+ cascade: operation.cascade
2079
+ },
2080
+ billing: normalizeBilling(void 0)
2012
2081
  }
2013
2082
  };
2014
2083
  }
2015
- const result = await runWithConfig(requestConfig, async () => {
2016
- return operation.setup({
2017
- workplaceId: context.workplaceId,
2018
- appInstallationId: context.appInstallationId,
2019
- appId: context.appId,
2020
- input: body.input,
2021
- env,
2022
- log
2084
+ const raw2 = await runWithConfig(requestConfig, async () => {
2085
+ return runWithRateLimitExecutionContext(rateLimitContext, async () => {
2086
+ return runWithLogContext({ invocation }, async () => {
2087
+ return operation.setup(opContextBase);
2088
+ });
2023
2089
  });
2024
2090
  });
2091
+ if (isBatchOperationFailure(raw2)) {
2092
+ return softFailureResponse(raw2.error, raw2.retry, raw2.billing);
2093
+ }
2094
+ const setupResult = raw2;
2095
+ const domain2 = stripBillingFields(
2096
+ setupResult
2097
+ );
2025
2098
  return {
2026
2099
  status: 200,
2027
2100
  body: {
2028
2101
  success: true,
2029
- result
2102
+ result: {
2103
+ ...domain2,
2104
+ // Expose definition cascade to the platform workflow
2105
+ cascade: operation.cascade ?? domain2.cascade
2106
+ },
2107
+ billing: normalizeBilling(setupResult.billing)
2030
2108
  }
2031
2109
  };
2032
2110
  }
2033
- if (body.method === "iterate") {
2034
- const result = await runWithConfig(requestConfig, async () => {
2035
- return operation.iterate({
2036
- workplaceId: context.workplaceId,
2037
- appInstallationId: context.appInstallationId,
2038
- appId: context.appId,
2039
- input: body.input,
2040
- state: body.state,
2041
- page: body.page,
2042
- cursor: body.cursor,
2043
- limit: body.limit,
2044
- env,
2045
- log
2111
+ const iterateBody = body;
2112
+ const raw = await runWithConfig(requestConfig, async () => {
2113
+ return runWithRateLimitExecutionContext(rateLimitContext, async () => {
2114
+ return runWithLogContext({ invocation }, async () => {
2115
+ return operation.iterate({
2116
+ ...opContextBase,
2117
+ state: iterateBody.state,
2118
+ page: iterateBody.page,
2119
+ cursor: iterateBody.cursor,
2120
+ limit: iterateBody.limit,
2121
+ cascadeEntities: iterateBody.cascadeEntities
2122
+ });
2046
2123
  });
2047
2124
  });
2048
- return {
2049
- status: 200,
2050
- body: {
2051
- success: true,
2052
- result
2053
- }
2054
- };
2125
+ });
2126
+ if (isBatchOperationFailure(raw)) {
2127
+ return softFailureResponse(raw.error, raw.retry, raw.billing);
2055
2128
  }
2129
+ const iterateResult = raw;
2130
+ const domain = stripBillingFields(
2131
+ iterateResult
2132
+ );
2056
2133
  return {
2057
- status: 400,
2134
+ status: 200,
2058
2135
  body: {
2059
- success: false,
2060
- error: `Unknown method: ${body.method}`
2136
+ success: true,
2137
+ result: domain,
2138
+ billing: normalizeBilling(iterateResult.billing)
2061
2139
  }
2062
2140
  };
2063
2141
  } catch (err) {
2064
- log.error("Batch operation failed", { error: err });
2142
+ if (err instanceof RateLimitExceededError) {
2143
+ return softFailureResponse(
2144
+ {
2145
+ code: "RATE_LIMITED",
2146
+ message: err.message,
2147
+ category: "external"
2148
+ },
2149
+ { allowed: true, afterMs: err.retryAfterMs }
2150
+ );
2151
+ }
2152
+ log.error("Batch operation failed", err);
2065
2153
  return {
2066
2154
  status: 500,
2067
2155
  body: {
2068
2156
  success: false,
2069
- error: err instanceof Error ? err.message : String(err)
2157
+ error: {
2158
+ code: "INTERNAL_ERROR",
2159
+ message: err instanceof Error ? err.message : String(err),
2160
+ category: "internal"
2161
+ },
2162
+ billing: normalizeBilling(void 0)
2070
2163
  }
2071
2164
  };
2165
+ } finally {
2166
+ process.env = originalEnv;
2072
2167
  }
2073
2168
  }
2074
2169
  function createNotFoundResponse() {
@@ -3,8 +3,8 @@
3
3
  *
4
4
  * These types define the registry and context for batch operations at runtime.
5
5
  */
6
- import type { BatchOperationSetupFn, BatchOperationIterateFn } from '../config/types/batch-operation';
7
- export type { BatchOperationContext } from '../config/types/batch-operation';
6
+ import type { BatchCascadePhase, BatchOperationSetupFn, BatchOperationIterateFn } from '../config/types/batch-operation';
7
+ export type { BatchCascadePhase, BatchOperationContext, } from '../config/types/batch-operation';
8
8
  /**
9
9
  * Entry in the batch operation registry.
10
10
  * Contains both metadata and function implementations.
@@ -16,8 +16,10 @@ export interface BatchOperationRegistryEntry {
16
16
  label: string;
17
17
  /** Description of what this operation does */
18
18
  description?: string;
19
- /** Entity handle that items will be upserted to */
19
+ /** Primary entity handle that items will be upserted to */
20
20
  entity: string;
21
+ /** Optional multi-entity cascade phases */
22
+ cascade?: BatchCascadePhase[];
21
23
  /** Setup function called once at the start */
22
24
  setup?: BatchOperationSetupFn;
23
25
  /** Iterate function called for each page */
@@ -41,6 +43,7 @@ export interface BatchOperationMetadata {
41
43
  label: string;
42
44
  description?: string;
43
45
  entity: string;
46
+ cascade?: BatchCascadePhase[];
44
47
  maxConcurrent?: number;
45
48
  pageSize?: number;
46
49
  icon?: string;
@@ -6,7 +6,7 @@
6
6
  */
7
7
  export type { AppInfo, AppInfoWithHandles, WorkplaceInfo, RequestInfo } from './shared';
8
8
  export type { InvocationType, ServerHookHandle, InvocationContext, } from './invocation';
9
- export { createToolCallContext, createServerHookContext, createWebhookContext, createWorkflowStepContext, } from './invocation';
9
+ export { createToolCallContext, createServerHookContext, createWebhookContext, createWorkflowStepContext, createBatchOperationContext, } from './invocation';
10
10
  export type { ToolTrigger, ProvisionToolContext, DeveloperPageActionToolContext, DeveloperFormSubmitToolContext, FieldChangeToolContext, PageActionToolContext, FormSubmitToolContext, AgentToolContext, WorkflowToolContext, CronToolContext, CronContext, ToolExecutionContext, } from './tool-context';
11
11
  export { isProvisionContext, isRuntimeContext, isCronContext, isDeveloperContext } from './tool-context';
12
12
  export type { ToolResult, ToolSuccess, ToolFailure, ErrorCode, ErrorCategory, ToolWarning, ToolPagination, ToolBilling, ToolRetry, ToolTiming, ToolCompletionHints, ToolConfig, QueueTouchPoint, BillingInfo, ToolResponseMeta, ToolEffect, ToolError, ToolExecutionResult, ToolSchemaWithJson, ToolSchema, ToolHandler, ToolDefinition, ToolRegistryEntry, ToolRegistry, ToolName, ToolMetadata, ToolCallResponse, ExecutionScope, } from './tool';
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Type of invocation that triggered the executable
3
3
  */
4
- export type InvocationType = 'tool_call' | 'server_hook' | 'workflow_step' | 'webhook';
4
+ export type InvocationType = 'tool_call' | 'server_hook' | 'workflow_step' | 'webhook' | 'batch_operation';
5
5
  /**
6
6
  * Server hook handles for lifecycle events
7
7
  */
@@ -19,6 +19,10 @@ export interface InvocationContext {
19
19
  toolCallId?: string;
20
20
  /** The tool's handle for searching (e.g., "get_customers") */
21
21
  toolHandle?: string;
22
+ /** Batch operation handle (for batch_operation invocations) */
23
+ batchOperationHandle?: string;
24
+ /** setup | iterate */
25
+ batchOperationMethod?: 'setup' | 'iterate';
22
26
  /** Hook type: "provision", "install", "uninstall", "oauth_callback", "setup.revalidate" */
23
27
  serverHookHandle?: ServerHookHandle;
24
28
  /** The app installation that triggered the call */
@@ -69,3 +73,14 @@ export declare function createWorkflowStepContext(params: {
69
73
  workflowRunId: string;
70
74
  workflowStepId?: string;
71
75
  }): InvocationContext;
76
+ /**
77
+ * Create an invocation context for a batch operation setup/iterate call
78
+ */
79
+ export declare function createBatchOperationContext(params: {
80
+ invocationId: string;
81
+ batchOperationHandle: string;
82
+ batchOperationMethod: 'setup' | 'iterate';
83
+ appInstallationId?: string;
84
+ workflowId?: string;
85
+ workflowRunId?: string;
86
+ }): InvocationContext;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skedyul",
3
- "version": "1.7.8",
3
+ "version": "1.7.11",
4
4
  "description": "The Skedyul SDK for Node.js",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -76,7 +76,7 @@
76
76
  "build": "rm -rf dist tsconfig.tsbuildinfo && tsc --emitDeclarationOnly && pnpm exec tsup-node && node -e \"require('fs').mkdirSync('dist',{recursive:true}); require('fs').writeFileSync('dist/.build-stamp', String(Date.now()))\"",
77
77
  "db:generate": "echo 'No database generation needed for this package'",
78
78
  "dev:watch": "npx nodemon --watch src --ext js,ts --exec \"pnpm run build\"",
79
- "test": "tsc --project tsconfig.tests.json && node --test dist-tests/tests/server.test.js dist-tests/tests/cli.test.js dist-tests/tests/agent-schema-v3.test.js dist-tests/tests/ratelimit.test.js dist-tests/tests/sequencer.test.js dist-tests/tests/config-loader.test.js dist-tests/tests/gsm7.test.js"
79
+ "test": "tsc --project tsconfig.tests.json && node --test dist-tests/tests/server.test.js dist-tests/tests/cli.test.js dist-tests/tests/agent-schema-v3.test.js dist-tests/tests/ratelimit.test.js dist-tests/tests/sequencer.test.js dist-tests/tests/config-loader.test.js dist-tests/tests/gsm7.test.js dist-tests/tests/batch-operation.test.js"
80
80
  },
81
81
  "keywords": [
82
82
  "mcp",