skedyul 1.7.7 → 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/.build-stamp +1 -1
- package/dist/cli/index.js +161 -55
- package/dist/config/define.d.ts +2 -0
- package/dist/config/types/batch-operation.d.ts +38 -2
- package/dist/dedicated/server.js +161 -55
- package/dist/esm/index.mjs +173 -55
- package/dist/index.js +174 -55
- package/dist/server/route-handlers/handlers.d.ts +3 -0
- package/dist/server.js +161 -55
- package/dist/serverless/server.mjs +161 -55
- package/dist/types/index.d.ts +1 -1
- package/dist/types/invocation.d.ts +16 -1
- package/package.json +2 -2
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,34 +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
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
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
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
}
|
|
2015
|
-
};
|
|
2040
|
+
return softFailureResponse({
|
|
2041
|
+
code: "NOT_FOUND",
|
|
2042
|
+
message: `Batch operation not found: ${body.handle}`,
|
|
2043
|
+
category: "validation"
|
|
2044
|
+
});
|
|
2016
2045
|
}
|
|
2017
|
-
const
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
}
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2046
|
+
const context = body.context;
|
|
2047
|
+
if (!context?.workplaceId || !context?.appInstallationId || !context?.appId) {
|
|
2048
|
+
return softFailureResponse({
|
|
2049
|
+
code: "VALIDATION_ERROR",
|
|
2050
|
+
message: "Missing context (workplaceId, appInstallationId, and appId required)",
|
|
2051
|
+
category: "validation"
|
|
2052
|
+
});
|
|
2053
|
+
}
|
|
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
|
|
2080
|
+
};
|
|
2081
|
+
const requestConfig = {
|
|
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
|
|
2027
2106
|
};
|
|
2028
2107
|
try {
|
|
2029
2108
|
if (body.method === "setup") {
|
|
@@ -2032,61 +2111,88 @@ async function handleBatchOperationRoute(req, ctx) {
|
|
|
2032
2111
|
status: 200,
|
|
2033
2112
|
body: {
|
|
2034
2113
|
success: true,
|
|
2035
|
-
result: { state: {}, total: void 0 }
|
|
2114
|
+
result: { state: {}, total: void 0 },
|
|
2115
|
+
billing: normalizeBilling(void 0)
|
|
2036
2116
|
}
|
|
2037
2117
|
};
|
|
2038
2118
|
}
|
|
2039
|
-
const
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2119
|
+
const raw2 = await runWithConfig(requestConfig, async () => {
|
|
2120
|
+
return runWithRateLimitExecutionContext(rateLimitContext, async () => {
|
|
2121
|
+
return runWithLogContext({ invocation }, async () => {
|
|
2122
|
+
return operation.setup(opContextBase);
|
|
2123
|
+
});
|
|
2124
|
+
});
|
|
2045
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
|
+
);
|
|
2046
2133
|
return {
|
|
2047
2134
|
status: 200,
|
|
2048
2135
|
body: {
|
|
2049
2136
|
success: true,
|
|
2050
|
-
result
|
|
2137
|
+
result: domain2,
|
|
2138
|
+
billing: normalizeBilling(setupResult.billing)
|
|
2051
2139
|
}
|
|
2052
2140
|
};
|
|
2053
2141
|
}
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
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
|
+
});
|
|
2152
|
+
});
|
|
2065
2153
|
});
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
success: true,
|
|
2070
|
-
result
|
|
2071
|
-
}
|
|
2072
|
-
};
|
|
2154
|
+
});
|
|
2155
|
+
if (isBatchOperationFailure(raw)) {
|
|
2156
|
+
return softFailureResponse(raw.error, raw.retry, raw.billing);
|
|
2073
2157
|
}
|
|
2158
|
+
const iterateResult = raw;
|
|
2159
|
+
const domain = stripBillingFields(
|
|
2160
|
+
iterateResult
|
|
2161
|
+
);
|
|
2074
2162
|
return {
|
|
2075
|
-
status:
|
|
2163
|
+
status: 200,
|
|
2076
2164
|
body: {
|
|
2077
|
-
success:
|
|
2078
|
-
|
|
2165
|
+
success: true,
|
|
2166
|
+
result: domain,
|
|
2167
|
+
billing: normalizeBilling(iterateResult.billing)
|
|
2079
2168
|
}
|
|
2080
2169
|
};
|
|
2081
2170
|
} catch (err) {
|
|
2082
|
-
|
|
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);
|
|
2083
2182
|
return {
|
|
2084
2183
|
status: 500,
|
|
2085
2184
|
body: {
|
|
2086
2185
|
success: false,
|
|
2087
|
-
error:
|
|
2186
|
+
error: {
|
|
2187
|
+
code: "INTERNAL_ERROR",
|
|
2188
|
+
message: err instanceof Error ? err.message : String(err),
|
|
2189
|
+
category: "internal"
|
|
2190
|
+
},
|
|
2191
|
+
billing: normalizeBilling(void 0)
|
|
2088
2192
|
}
|
|
2089
2193
|
};
|
|
2194
|
+
} finally {
|
|
2195
|
+
process.env = originalEnv;
|
|
2090
2196
|
}
|
|
2091
2197
|
}
|
|
2092
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,34 +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
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
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
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
}
|
|
1976
|
-
};
|
|
2001
|
+
return softFailureResponse({
|
|
2002
|
+
code: "NOT_FOUND",
|
|
2003
|
+
message: `Batch operation not found: ${body.handle}`,
|
|
2004
|
+
category: "validation"
|
|
2005
|
+
});
|
|
1977
2006
|
}
|
|
1978
|
-
const
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
}
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
2007
|
+
const context = body.context;
|
|
2008
|
+
if (!context?.workplaceId || !context?.appInstallationId || !context?.appId) {
|
|
2009
|
+
return softFailureResponse({
|
|
2010
|
+
code: "VALIDATION_ERROR",
|
|
2011
|
+
message: "Missing context (workplaceId, appInstallationId, and appId required)",
|
|
2012
|
+
category: "validation"
|
|
2013
|
+
});
|
|
2014
|
+
}
|
|
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
|
|
2041
|
+
};
|
|
2042
|
+
const requestConfig = {
|
|
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
|
|
1988
2067
|
};
|
|
1989
2068
|
try {
|
|
1990
2069
|
if (body.method === "setup") {
|
|
@@ -1993,61 +2072,88 @@ async function handleBatchOperationRoute(req, ctx) {
|
|
|
1993
2072
|
status: 200,
|
|
1994
2073
|
body: {
|
|
1995
2074
|
success: true,
|
|
1996
|
-
result: { state: {}, total: void 0 }
|
|
2075
|
+
result: { state: {}, total: void 0 },
|
|
2076
|
+
billing: normalizeBilling(void 0)
|
|
1997
2077
|
}
|
|
1998
2078
|
};
|
|
1999
2079
|
}
|
|
2000
|
-
const
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2080
|
+
const raw2 = await runWithConfig(requestConfig, async () => {
|
|
2081
|
+
return runWithRateLimitExecutionContext(rateLimitContext, async () => {
|
|
2082
|
+
return runWithLogContext({ invocation }, async () => {
|
|
2083
|
+
return operation.setup(opContextBase);
|
|
2084
|
+
});
|
|
2085
|
+
});
|
|
2006
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
|
+
);
|
|
2007
2094
|
return {
|
|
2008
2095
|
status: 200,
|
|
2009
2096
|
body: {
|
|
2010
2097
|
success: true,
|
|
2011
|
-
result
|
|
2098
|
+
result: domain2,
|
|
2099
|
+
billing: normalizeBilling(setupResult.billing)
|
|
2012
2100
|
}
|
|
2013
2101
|
};
|
|
2014
2102
|
}
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
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
|
+
});
|
|
2113
|
+
});
|
|
2026
2114
|
});
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
success: true,
|
|
2031
|
-
result
|
|
2032
|
-
}
|
|
2033
|
-
};
|
|
2115
|
+
});
|
|
2116
|
+
if (isBatchOperationFailure(raw)) {
|
|
2117
|
+
return softFailureResponse(raw.error, raw.retry, raw.billing);
|
|
2034
2118
|
}
|
|
2119
|
+
const iterateResult = raw;
|
|
2120
|
+
const domain = stripBillingFields(
|
|
2121
|
+
iterateResult
|
|
2122
|
+
);
|
|
2035
2123
|
return {
|
|
2036
|
-
status:
|
|
2124
|
+
status: 200,
|
|
2037
2125
|
body: {
|
|
2038
|
-
success:
|
|
2039
|
-
|
|
2126
|
+
success: true,
|
|
2127
|
+
result: domain,
|
|
2128
|
+
billing: normalizeBilling(iterateResult.billing)
|
|
2040
2129
|
}
|
|
2041
2130
|
};
|
|
2042
2131
|
} catch (err) {
|
|
2043
|
-
|
|
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);
|
|
2044
2143
|
return {
|
|
2045
2144
|
status: 500,
|
|
2046
2145
|
body: {
|
|
2047
2146
|
success: false,
|
|
2048
|
-
error:
|
|
2147
|
+
error: {
|
|
2148
|
+
code: "INTERNAL_ERROR",
|
|
2149
|
+
message: err instanceof Error ? err.message : String(err),
|
|
2150
|
+
category: "internal"
|
|
2151
|
+
},
|
|
2152
|
+
billing: normalizeBilling(void 0)
|
|
2049
2153
|
}
|
|
2050
2154
|
};
|
|
2155
|
+
} finally {
|
|
2156
|
+
process.env = originalEnv;
|
|
2051
2157
|
}
|
|
2052
2158
|
}
|
|
2053
2159
|
function createNotFoundResponse() {
|
package/dist/types/index.d.ts
CHANGED
|
@@ -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.
|
|
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",
|