skedyul 1.7.8 → 1.7.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,88 @@ async function handleBatchOperationRoute(req, ctx) {
2047
2111
  status: 200,
2048
2112
  body: {
2049
2113
  success: true,
2050
- result: { state: {}, total: void 0 }
2114
+ result: { state: {}, total: void 0 },
2115
+ billing: normalizeBilling(void 0)
2051
2116
  }
2052
2117
  };
2053
2118
  }
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
2119
+ const raw2 = await runWithConfig(requestConfig, async () => {
2120
+ return runWithRateLimitExecutionContext(rateLimitContext, async () => {
2121
+ return runWithLogContext({ invocation }, async () => {
2122
+ return operation.setup(opContextBase);
2123
+ });
2062
2124
  });
2063
2125
  });
2126
+ if (isBatchOperationFailure(raw2)) {
2127
+ return softFailureResponse(raw2.error, raw2.retry, raw2.billing);
2128
+ }
2129
+ const setupResult = raw2;
2130
+ const domain2 = stripBillingFields(
2131
+ setupResult
2132
+ );
2064
2133
  return {
2065
2134
  status: 200,
2066
2135
  body: {
2067
2136
  success: true,
2068
- result
2137
+ result: domain2,
2138
+ billing: normalizeBilling(setupResult.billing)
2069
2139
  }
2070
2140
  };
2071
2141
  }
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
2142
+ const raw = await runWithConfig(requestConfig, async () => {
2143
+ return runWithRateLimitExecutionContext(rateLimitContext, async () => {
2144
+ return runWithLogContext({ invocation }, async () => {
2145
+ return operation.iterate({
2146
+ ...opContextBase,
2147
+ state: body.state,
2148
+ page: body.page,
2149
+ cursor: body.cursor,
2150
+ limit: body.limit
2151
+ });
2085
2152
  });
2086
2153
  });
2087
- return {
2088
- status: 200,
2089
- body: {
2090
- success: true,
2091
- result
2092
- }
2093
- };
2154
+ });
2155
+ if (isBatchOperationFailure(raw)) {
2156
+ return softFailureResponse(raw.error, raw.retry, raw.billing);
2094
2157
  }
2158
+ const iterateResult = raw;
2159
+ const domain = stripBillingFields(
2160
+ iterateResult
2161
+ );
2095
2162
  return {
2096
- status: 400,
2163
+ status: 200,
2097
2164
  body: {
2098
- success: false,
2099
- error: `Unknown method: ${body.method}`
2165
+ success: true,
2166
+ result: domain,
2167
+ billing: normalizeBilling(iterateResult.billing)
2100
2168
  }
2101
2169
  };
2102
2170
  } catch (err) {
2103
- log.error("Batch operation failed", { error: err });
2171
+ if (err instanceof RateLimitExceededError) {
2172
+ return softFailureResponse(
2173
+ {
2174
+ code: "RATE_LIMITED",
2175
+ message: err.message,
2176
+ category: "external"
2177
+ },
2178
+ { allowed: true, afterMs: err.retryAfterMs }
2179
+ );
2180
+ }
2181
+ log.error("Batch operation failed", err);
2104
2182
  return {
2105
2183
  status: 500,
2106
2184
  body: {
2107
2185
  success: false,
2108
- error: err instanceof Error ? err.message : String(err)
2186
+ error: {
2187
+ code: "INTERNAL_ERROR",
2188
+ message: err instanceof Error ? err.message : String(err),
2189
+ category: "internal"
2190
+ },
2191
+ billing: normalizeBilling(void 0)
2109
2192
  }
2110
2193
  };
2194
+ } finally {
2195
+ process.env = originalEnv;
2111
2196
  }
2112
2197
  }
2113
2198
  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,88 @@ async function handleBatchOperationRoute(req, ctx) {
2008
2072
  status: 200,
2009
2073
  body: {
2010
2074
  success: true,
2011
- result: { state: {}, total: void 0 }
2075
+ result: { state: {}, total: void 0 },
2076
+ billing: normalizeBilling(void 0)
2012
2077
  }
2013
2078
  };
2014
2079
  }
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
2080
+ const raw2 = await runWithConfig(requestConfig, async () => {
2081
+ return runWithRateLimitExecutionContext(rateLimitContext, async () => {
2082
+ return runWithLogContext({ invocation }, async () => {
2083
+ return operation.setup(opContextBase);
2084
+ });
2023
2085
  });
2024
2086
  });
2087
+ if (isBatchOperationFailure(raw2)) {
2088
+ return softFailureResponse(raw2.error, raw2.retry, raw2.billing);
2089
+ }
2090
+ const setupResult = raw2;
2091
+ const domain2 = stripBillingFields(
2092
+ setupResult
2093
+ );
2025
2094
  return {
2026
2095
  status: 200,
2027
2096
  body: {
2028
2097
  success: true,
2029
- result
2098
+ result: domain2,
2099
+ billing: normalizeBilling(setupResult.billing)
2030
2100
  }
2031
2101
  };
2032
2102
  }
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
2103
+ const raw = await runWithConfig(requestConfig, async () => {
2104
+ return runWithRateLimitExecutionContext(rateLimitContext, async () => {
2105
+ return runWithLogContext({ invocation }, async () => {
2106
+ return operation.iterate({
2107
+ ...opContextBase,
2108
+ state: body.state,
2109
+ page: body.page,
2110
+ cursor: body.cursor,
2111
+ limit: body.limit
2112
+ });
2046
2113
  });
2047
2114
  });
2048
- return {
2049
- status: 200,
2050
- body: {
2051
- success: true,
2052
- result
2053
- }
2054
- };
2115
+ });
2116
+ if (isBatchOperationFailure(raw)) {
2117
+ return softFailureResponse(raw.error, raw.retry, raw.billing);
2055
2118
  }
2119
+ const iterateResult = raw;
2120
+ const domain = stripBillingFields(
2121
+ iterateResult
2122
+ );
2056
2123
  return {
2057
- status: 400,
2124
+ status: 200,
2058
2125
  body: {
2059
- success: false,
2060
- error: `Unknown method: ${body.method}`
2126
+ success: true,
2127
+ result: domain,
2128
+ billing: normalizeBilling(iterateResult.billing)
2061
2129
  }
2062
2130
  };
2063
2131
  } catch (err) {
2064
- log.error("Batch operation failed", { error: err });
2132
+ if (err instanceof RateLimitExceededError) {
2133
+ return softFailureResponse(
2134
+ {
2135
+ code: "RATE_LIMITED",
2136
+ message: err.message,
2137
+ category: "external"
2138
+ },
2139
+ { allowed: true, afterMs: err.retryAfterMs }
2140
+ );
2141
+ }
2142
+ log.error("Batch operation failed", err);
2065
2143
  return {
2066
2144
  status: 500,
2067
2145
  body: {
2068
2146
  success: false,
2069
- error: err instanceof Error ? err.message : String(err)
2147
+ error: {
2148
+ code: "INTERNAL_ERROR",
2149
+ message: err instanceof Error ? err.message : String(err),
2150
+ category: "internal"
2151
+ },
2152
+ billing: normalizeBilling(void 0)
2070
2153
  }
2071
2154
  };
2155
+ } finally {
2156
+ process.env = originalEnv;
2072
2157
  }
2073
2158
  }
2074
2159
  function createNotFoundResponse() {
@@ -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.9",
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",