skedyul 1.7.6 → 1.7.8
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 +129 -0
- package/dist/config/app-config.d.ts +5 -1
- package/dist/config/define.d.ts +36 -0
- package/dist/config/index.d.ts +1 -1
- package/dist/config/types/batch-operation.d.ts +152 -0
- package/dist/config/types/index.d.ts +1 -0
- package/dist/dedicated/server.js +129 -0
- package/dist/esm/index.mjs +165 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +170 -1
- package/dist/schemas.d.ts +53 -0
- package/dist/server/index.d.ts +3 -2
- package/dist/server/route-handlers/handlers.d.ts +7 -0
- package/dist/server/route-handlers/index.d.ts +1 -1
- package/dist/server/route-handlers/types.d.ts +2 -1
- package/dist/server.js +129 -0
- package/dist/serverless/server.mjs +129 -0
- package/dist/types/batch-operation.d.ts +47 -0
- package/dist/types/index.d.ts +1 -0
- package/package.json +1 -1
package/dist/server.js
CHANGED
|
@@ -1988,6 +1988,128 @@ async function handleMcpBatchRoute(req, ctx) {
|
|
|
1988
1988
|
}
|
|
1989
1989
|
};
|
|
1990
1990
|
}
|
|
1991
|
+
async function handleBatchOperationRoute(req, ctx) {
|
|
1992
|
+
const bodyResult = parseJsonBody(req);
|
|
1993
|
+
if (!bodyResult.success) {
|
|
1994
|
+
return bodyResult.error;
|
|
1995
|
+
}
|
|
1996
|
+
const body = bodyResult.data;
|
|
1997
|
+
const registry = ctx.batchOperationRegistry;
|
|
1998
|
+
if (!registry) {
|
|
1999
|
+
return {
|
|
2000
|
+
status: 404,
|
|
2001
|
+
body: {
|
|
2002
|
+
success: false,
|
|
2003
|
+
error: "No batch operations registered"
|
|
2004
|
+
}
|
|
2005
|
+
};
|
|
2006
|
+
}
|
|
2007
|
+
const operation = registry[body.handle];
|
|
2008
|
+
if (!operation) {
|
|
2009
|
+
return {
|
|
2010
|
+
status: 404,
|
|
2011
|
+
body: {
|
|
2012
|
+
success: false,
|
|
2013
|
+
error: `Batch operation not found: ${body.handle}`
|
|
2014
|
+
}
|
|
2015
|
+
};
|
|
2016
|
+
}
|
|
2017
|
+
const context = body.context;
|
|
2018
|
+
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
|
+
};
|
|
2026
|
+
}
|
|
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
|
+
}
|
|
2038
|
+
};
|
|
2039
|
+
const requestConfig = {
|
|
2040
|
+
baseUrl: env.SKEDYUL_API_URL ?? process.env.SKEDYUL_API_URL ?? "",
|
|
2041
|
+
apiToken: env.SKEDYUL_API_TOKEN ?? process.env.SKEDYUL_API_TOKEN ?? ""
|
|
2042
|
+
};
|
|
2043
|
+
try {
|
|
2044
|
+
if (body.method === "setup") {
|
|
2045
|
+
if (!operation.setup) {
|
|
2046
|
+
return {
|
|
2047
|
+
status: 200,
|
|
2048
|
+
body: {
|
|
2049
|
+
success: true,
|
|
2050
|
+
result: { state: {}, total: void 0 }
|
|
2051
|
+
}
|
|
2052
|
+
};
|
|
2053
|
+
}
|
|
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
|
|
2062
|
+
});
|
|
2063
|
+
});
|
|
2064
|
+
return {
|
|
2065
|
+
status: 200,
|
|
2066
|
+
body: {
|
|
2067
|
+
success: true,
|
|
2068
|
+
result
|
|
2069
|
+
}
|
|
2070
|
+
};
|
|
2071
|
+
}
|
|
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
|
|
2085
|
+
});
|
|
2086
|
+
});
|
|
2087
|
+
return {
|
|
2088
|
+
status: 200,
|
|
2089
|
+
body: {
|
|
2090
|
+
success: true,
|
|
2091
|
+
result
|
|
2092
|
+
}
|
|
2093
|
+
};
|
|
2094
|
+
}
|
|
2095
|
+
return {
|
|
2096
|
+
status: 400,
|
|
2097
|
+
body: {
|
|
2098
|
+
success: false,
|
|
2099
|
+
error: `Unknown method: ${body.method}`
|
|
2100
|
+
}
|
|
2101
|
+
};
|
|
2102
|
+
} catch (err) {
|
|
2103
|
+
log.error("Batch operation failed", { error: err });
|
|
2104
|
+
return {
|
|
2105
|
+
status: 500,
|
|
2106
|
+
body: {
|
|
2107
|
+
success: false,
|
|
2108
|
+
error: err instanceof Error ? err.message : String(err)
|
|
2109
|
+
}
|
|
2110
|
+
};
|
|
2111
|
+
}
|
|
2112
|
+
}
|
|
1991
2113
|
function createNotFoundResponse() {
|
|
1992
2114
|
return {
|
|
1993
2115
|
status: 404,
|
|
@@ -2067,6 +2189,9 @@ async function routeRequest(req, ctx) {
|
|
|
2067
2189
|
if (req.path === "/mcp/batch" && req.method === "POST") {
|
|
2068
2190
|
return handleMcpBatchRoute(req, ctx);
|
|
2069
2191
|
}
|
|
2192
|
+
if (req.path === "/batch-operation" && req.method === "POST") {
|
|
2193
|
+
return handleBatchOperationRoute(req, ctx);
|
|
2194
|
+
}
|
|
2070
2195
|
return createNotFoundResponse();
|
|
2071
2196
|
} catch (err) {
|
|
2072
2197
|
return createErrorResponse(err);
|
|
@@ -2108,11 +2233,13 @@ function createDedicatedServerInstance(config, tools, callTool, state, mcpServer
|
|
|
2108
2233
|
const defaultHeaders = getDefaultHeaders(config.cors);
|
|
2109
2234
|
const registry = config.tools;
|
|
2110
2235
|
const webhookRegistry = config.webhooks;
|
|
2236
|
+
const batchOperationRegistry = config.batchOperations;
|
|
2111
2237
|
const ctx = {
|
|
2112
2238
|
config,
|
|
2113
2239
|
tools,
|
|
2114
2240
|
registry,
|
|
2115
2241
|
webhookRegistry,
|
|
2242
|
+
batchOperationRegistry,
|
|
2116
2243
|
callTool,
|
|
2117
2244
|
state,
|
|
2118
2245
|
mcpServer,
|
|
@@ -2227,12 +2354,14 @@ function createServerlessInstance(config, tools, callTool, state, mcpServer) {
|
|
|
2227
2354
|
const defaultHeaders = getDefaultHeaders(config.cors);
|
|
2228
2355
|
const registry = config.tools;
|
|
2229
2356
|
const webhookRegistry = config.webhooks;
|
|
2357
|
+
const batchOperationRegistry = config.batchOperations;
|
|
2230
2358
|
let hasLoggedStartup = false;
|
|
2231
2359
|
const ctx = {
|
|
2232
2360
|
config,
|
|
2233
2361
|
tools,
|
|
2234
2362
|
registry,
|
|
2235
2363
|
webhookRegistry,
|
|
2364
|
+
batchOperationRegistry,
|
|
2236
2365
|
callTool,
|
|
2237
2366
|
state,
|
|
2238
2367
|
mcpServer,
|
|
@@ -1949,6 +1949,128 @@ async function handleMcpBatchRoute(req, ctx) {
|
|
|
1949
1949
|
}
|
|
1950
1950
|
};
|
|
1951
1951
|
}
|
|
1952
|
+
async function handleBatchOperationRoute(req, ctx) {
|
|
1953
|
+
const bodyResult = parseJsonBody(req);
|
|
1954
|
+
if (!bodyResult.success) {
|
|
1955
|
+
return bodyResult.error;
|
|
1956
|
+
}
|
|
1957
|
+
const body = bodyResult.data;
|
|
1958
|
+
const registry = ctx.batchOperationRegistry;
|
|
1959
|
+
if (!registry) {
|
|
1960
|
+
return {
|
|
1961
|
+
status: 404,
|
|
1962
|
+
body: {
|
|
1963
|
+
success: false,
|
|
1964
|
+
error: "No batch operations registered"
|
|
1965
|
+
}
|
|
1966
|
+
};
|
|
1967
|
+
}
|
|
1968
|
+
const operation = registry[body.handle];
|
|
1969
|
+
if (!operation) {
|
|
1970
|
+
return {
|
|
1971
|
+
status: 404,
|
|
1972
|
+
body: {
|
|
1973
|
+
success: false,
|
|
1974
|
+
error: `Batch operation not found: ${body.handle}`
|
|
1975
|
+
}
|
|
1976
|
+
};
|
|
1977
|
+
}
|
|
1978
|
+
const context = body.context;
|
|
1979
|
+
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
|
+
};
|
|
1987
|
+
}
|
|
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
|
+
}
|
|
1999
|
+
};
|
|
2000
|
+
const requestConfig = {
|
|
2001
|
+
baseUrl: env.SKEDYUL_API_URL ?? process.env.SKEDYUL_API_URL ?? "",
|
|
2002
|
+
apiToken: env.SKEDYUL_API_TOKEN ?? process.env.SKEDYUL_API_TOKEN ?? ""
|
|
2003
|
+
};
|
|
2004
|
+
try {
|
|
2005
|
+
if (body.method === "setup") {
|
|
2006
|
+
if (!operation.setup) {
|
|
2007
|
+
return {
|
|
2008
|
+
status: 200,
|
|
2009
|
+
body: {
|
|
2010
|
+
success: true,
|
|
2011
|
+
result: { state: {}, total: void 0 }
|
|
2012
|
+
}
|
|
2013
|
+
};
|
|
2014
|
+
}
|
|
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
|
|
2023
|
+
});
|
|
2024
|
+
});
|
|
2025
|
+
return {
|
|
2026
|
+
status: 200,
|
|
2027
|
+
body: {
|
|
2028
|
+
success: true,
|
|
2029
|
+
result
|
|
2030
|
+
}
|
|
2031
|
+
};
|
|
2032
|
+
}
|
|
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
|
|
2046
|
+
});
|
|
2047
|
+
});
|
|
2048
|
+
return {
|
|
2049
|
+
status: 200,
|
|
2050
|
+
body: {
|
|
2051
|
+
success: true,
|
|
2052
|
+
result
|
|
2053
|
+
}
|
|
2054
|
+
};
|
|
2055
|
+
}
|
|
2056
|
+
return {
|
|
2057
|
+
status: 400,
|
|
2058
|
+
body: {
|
|
2059
|
+
success: false,
|
|
2060
|
+
error: `Unknown method: ${body.method}`
|
|
2061
|
+
}
|
|
2062
|
+
};
|
|
2063
|
+
} catch (err) {
|
|
2064
|
+
log.error("Batch operation failed", { error: err });
|
|
2065
|
+
return {
|
|
2066
|
+
status: 500,
|
|
2067
|
+
body: {
|
|
2068
|
+
success: false,
|
|
2069
|
+
error: err instanceof Error ? err.message : String(err)
|
|
2070
|
+
}
|
|
2071
|
+
};
|
|
2072
|
+
}
|
|
2073
|
+
}
|
|
1952
2074
|
function createNotFoundResponse() {
|
|
1953
2075
|
return {
|
|
1954
2076
|
status: 404,
|
|
@@ -2028,6 +2150,9 @@ async function routeRequest(req, ctx) {
|
|
|
2028
2150
|
if (req.path === "/mcp/batch" && req.method === "POST") {
|
|
2029
2151
|
return handleMcpBatchRoute(req, ctx);
|
|
2030
2152
|
}
|
|
2153
|
+
if (req.path === "/batch-operation" && req.method === "POST") {
|
|
2154
|
+
return handleBatchOperationRoute(req, ctx);
|
|
2155
|
+
}
|
|
2031
2156
|
return createNotFoundResponse();
|
|
2032
2157
|
} catch (err) {
|
|
2033
2158
|
return createErrorResponse(err);
|
|
@@ -2069,11 +2194,13 @@ function createDedicatedServerInstance(config, tools, callTool, state, mcpServer
|
|
|
2069
2194
|
const defaultHeaders = getDefaultHeaders(config.cors);
|
|
2070
2195
|
const registry = config.tools;
|
|
2071
2196
|
const webhookRegistry = config.webhooks;
|
|
2197
|
+
const batchOperationRegistry = config.batchOperations;
|
|
2072
2198
|
const ctx = {
|
|
2073
2199
|
config,
|
|
2074
2200
|
tools,
|
|
2075
2201
|
registry,
|
|
2076
2202
|
webhookRegistry,
|
|
2203
|
+
batchOperationRegistry,
|
|
2077
2204
|
callTool,
|
|
2078
2205
|
state,
|
|
2079
2206
|
mcpServer,
|
|
@@ -2188,12 +2315,14 @@ function createServerlessInstance(config, tools, callTool, state, mcpServer) {
|
|
|
2188
2315
|
const defaultHeaders = getDefaultHeaders(config.cors);
|
|
2189
2316
|
const registry = config.tools;
|
|
2190
2317
|
const webhookRegistry = config.webhooks;
|
|
2318
|
+
const batchOperationRegistry = config.batchOperations;
|
|
2191
2319
|
let hasLoggedStartup = false;
|
|
2192
2320
|
const ctx = {
|
|
2193
2321
|
config,
|
|
2194
2322
|
tools,
|
|
2195
2323
|
registry,
|
|
2196
2324
|
webhookRegistry,
|
|
2325
|
+
batchOperationRegistry,
|
|
2197
2326
|
callTool,
|
|
2198
2327
|
state,
|
|
2199
2328
|
mcpServer,
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Batch operation runtime types.
|
|
3
|
+
*
|
|
4
|
+
* These types define the registry and context for batch operations at runtime.
|
|
5
|
+
*/
|
|
6
|
+
import type { BatchOperationSetupFn, BatchOperationIterateFn } from '../config/types/batch-operation';
|
|
7
|
+
export type { BatchOperationContext } from '../config/types/batch-operation';
|
|
8
|
+
/**
|
|
9
|
+
* Entry in the batch operation registry.
|
|
10
|
+
* Contains both metadata and function implementations.
|
|
11
|
+
*/
|
|
12
|
+
export interface BatchOperationRegistryEntry {
|
|
13
|
+
/** Unique handle for this operation */
|
|
14
|
+
handle: string;
|
|
15
|
+
/** Human-readable label */
|
|
16
|
+
label: string;
|
|
17
|
+
/** Description of what this operation does */
|
|
18
|
+
description?: string;
|
|
19
|
+
/** Entity handle that items will be upserted to */
|
|
20
|
+
entity: string;
|
|
21
|
+
/** Setup function called once at the start */
|
|
22
|
+
setup?: BatchOperationSetupFn;
|
|
23
|
+
/** Iterate function called for each page */
|
|
24
|
+
iterate: BatchOperationIterateFn;
|
|
25
|
+
/** Maximum concurrent operations per app installation */
|
|
26
|
+
maxConcurrent?: number;
|
|
27
|
+
/** Default page size */
|
|
28
|
+
pageSize?: number;
|
|
29
|
+
/** Optional icon */
|
|
30
|
+
icon?: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Registry mapping batch operation handles to their implementations.
|
|
34
|
+
*/
|
|
35
|
+
export type BatchOperationRegistry = Record<string, BatchOperationRegistryEntry>;
|
|
36
|
+
/**
|
|
37
|
+
* Metadata for a batch operation (serializable, no functions).
|
|
38
|
+
*/
|
|
39
|
+
export interface BatchOperationMetadata {
|
|
40
|
+
handle: string;
|
|
41
|
+
label: string;
|
|
42
|
+
description?: string;
|
|
43
|
+
entity: string;
|
|
44
|
+
maxConcurrent?: number;
|
|
45
|
+
pageSize?: number;
|
|
46
|
+
icon?: string;
|
|
47
|
+
}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -22,3 +22,4 @@ export type { WebhookWireRequest, HandlerRawRequest, WebhookRequest, WebhookResp
|
|
|
22
22
|
export { isRuntimeWebhookContext } from './webhook';
|
|
23
23
|
export type { MCPError, MCPContentItem, MCPResult, MCPResponse, MCPRequest, } from './mcp-protocol';
|
|
24
24
|
export type { DataBlock, DataBlockLink, SpreadsheetBlock, SpreadsheetColumn, ProfileBlock, ProfileAvatar, ProfileField, FieldChangesBlock, FieldChangeItem, DateTimeBlock, } from './data-blocks';
|
|
25
|
+
export type { BatchOperationContext, BatchOperationRegistryEntry, BatchOperationRegistry, BatchOperationMetadata, } from './batch-operation';
|