skedyul 1.5.13 → 1.6.0

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.
@@ -280,6 +280,11 @@ export declare const CRMPageSchemaZ: z.ZodObject<{
280
280
  icon: z.ZodOptional<z.ZodString>;
281
281
  modelHandle: z.ZodString;
282
282
  parentPath: z.ZodOptional<z.ZodString>;
283
+ isDefault: z.ZodOptional<z.ZodBoolean>;
284
+ visibility: z.ZodOptional<z.ZodEnum<{
285
+ team: "team";
286
+ private: "private";
287
+ }>>;
283
288
  baseQuery: z.ZodOptional<z.ZodUnknown>;
284
289
  blocks: z.ZodOptional<z.ZodArray<z.ZodObject<{
285
290
  type: z.ZodEnum<{
@@ -406,6 +411,11 @@ export declare const CRMSchemaZ: z.ZodObject<{
406
411
  icon: z.ZodOptional<z.ZodString>;
407
412
  modelHandle: z.ZodString;
408
413
  parentPath: z.ZodOptional<z.ZodString>;
414
+ isDefault: z.ZodOptional<z.ZodBoolean>;
415
+ visibility: z.ZodOptional<z.ZodEnum<{
416
+ team: "team";
417
+ private: "private";
418
+ }>>;
409
419
  baseQuery: z.ZodOptional<z.ZodUnknown>;
410
420
  blocks: z.ZodOptional<z.ZodArray<z.ZodObject<{
411
421
  type: z.ZodEnum<{
package/dist/schemas.d.ts CHANGED
@@ -327,6 +327,17 @@ export declare const ModelDefinitionSchema: z.ZodObject<{
327
327
  addDefaultPages: z.ZodOptional<z.ZodBoolean>;
328
328
  addNavigation: z.ZodOptional<z.ZodBoolean>;
329
329
  page: z.ZodOptional<z.ZodString>;
330
+ env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
331
+ label: z.ZodString;
332
+ required: z.ZodOptional<z.ZodBoolean>;
333
+ visibility: z.ZodOptional<z.ZodEnum<{
334
+ visible: "visible";
335
+ encrypted: "encrypted";
336
+ }>>;
337
+ default: z.ZodOptional<z.ZodString>;
338
+ description: z.ZodOptional<z.ZodString>;
339
+ placeholder: z.ZodOptional<z.ZodString>;
340
+ }, z.core.$strip>>>;
330
341
  }, z.core.$strip>;
331
342
  export declare const RelationshipCardinalitySchema: z.ZodEnum<{
332
343
  ONE_TO_ONE: "ONE_TO_ONE";
@@ -3218,6 +3229,17 @@ export declare const InstallConfigSchema: z.ZodObject<{
3218
3229
  addDefaultPages: z.ZodOptional<z.ZodBoolean>;
3219
3230
  addNavigation: z.ZodOptional<z.ZodBoolean>;
3220
3231
  page: z.ZodOptional<z.ZodString>;
3232
+ env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
3233
+ label: z.ZodString;
3234
+ required: z.ZodOptional<z.ZodBoolean>;
3235
+ visibility: z.ZodOptional<z.ZodEnum<{
3236
+ visible: "visible";
3237
+ encrypted: "encrypted";
3238
+ }>>;
3239
+ default: z.ZodOptional<z.ZodString>;
3240
+ description: z.ZodOptional<z.ZodString>;
3241
+ placeholder: z.ZodOptional<z.ZodString>;
3242
+ }, z.core.$strip>>>;
3221
3243
  }, z.core.$strip>>>;
3222
3244
  relationships: z.ZodOptional<z.ZodArray<z.ZodObject<{
3223
3245
  source: z.ZodObject<{
@@ -3341,6 +3363,17 @@ export declare const ProvisionConfigSchema: z.ZodObject<{
3341
3363
  addDefaultPages: z.ZodOptional<z.ZodBoolean>;
3342
3364
  addNavigation: z.ZodOptional<z.ZodBoolean>;
3343
3365
  page: z.ZodOptional<z.ZodString>;
3366
+ env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
3367
+ label: z.ZodString;
3368
+ required: z.ZodOptional<z.ZodBoolean>;
3369
+ visibility: z.ZodOptional<z.ZodEnum<{
3370
+ visible: "visible";
3371
+ encrypted: "encrypted";
3372
+ }>>;
3373
+ default: z.ZodOptional<z.ZodString>;
3374
+ description: z.ZodOptional<z.ZodString>;
3375
+ placeholder: z.ZodOptional<z.ZodString>;
3376
+ }, z.core.$strip>>>;
3344
3377
  }, z.core.$strip>>>;
3345
3378
  relationships: z.ZodOptional<z.ZodArray<z.ZodObject<{
3346
3379
  source: z.ZodObject<{
@@ -4076,6 +4109,17 @@ export declare const SkedyulConfigSchema: z.ZodObject<{
4076
4109
  addDefaultPages: z.ZodOptional<z.ZodBoolean>;
4077
4110
  addNavigation: z.ZodOptional<z.ZodBoolean>;
4078
4111
  page: z.ZodOptional<z.ZodString>;
4112
+ env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
4113
+ label: z.ZodString;
4114
+ required: z.ZodOptional<z.ZodBoolean>;
4115
+ visibility: z.ZodOptional<z.ZodEnum<{
4116
+ visible: "visible";
4117
+ encrypted: "encrypted";
4118
+ }>>;
4119
+ default: z.ZodOptional<z.ZodString>;
4120
+ description: z.ZodOptional<z.ZodString>;
4121
+ placeholder: z.ZodOptional<z.ZodString>;
4122
+ }, z.core.$strip>>>;
4079
4123
  }, z.core.$strip>>>;
4080
4124
  relationships: z.ZodOptional<z.ZodArray<z.ZodObject<{
4081
4125
  source: z.ZodObject<{
@@ -0,0 +1,10 @@
1
+ import { platformSequencerBackend } from './platform';
2
+ import { memorySequencerBackend, resetMemorySequencerBackendForTests } from './memory';
3
+ import type { SequencerBackend } from '../types';
4
+ /**
5
+ * Resolve the active sequencer backend.
6
+ * Uses platform proxy by default; falls back to in-memory when configured or on local errors.
7
+ */
8
+ export declare function getSequencerBackend(): SequencerBackend;
9
+ export declare function resetSequencerBackendForTests(): void;
10
+ export { platformSequencerBackend, memorySequencerBackend, resetMemorySequencerBackendForTests };
@@ -0,0 +1,26 @@
1
+ import type { SequencerBackend, SequencerAllowResult } from '../types';
2
+ /**
3
+ * In-process sequencer backend for local development and tests.
4
+ */
5
+ export declare class MemorySequencerBackend implements SequencerBackend {
6
+ private readonly state;
7
+ private getState;
8
+ allow(sequencerKey: string, input: {
9
+ timestamp: number;
10
+ leaseId?: string;
11
+ watermarkTtlMs?: number;
12
+ }): Promise<SequencerAllowResult>;
13
+ acquire(sequencerKey: string, input: {
14
+ leaseId: string;
15
+ timestamp?: number;
16
+ lockTtlMs?: number;
17
+ watermarkTtlMs?: number;
18
+ }): Promise<{
19
+ acquired: boolean;
20
+ reason: 'ok' | 'locked';
21
+ }>;
22
+ release(sequencerKey: string, leaseId: string): Promise<void>;
23
+ resetForTests(): void;
24
+ }
25
+ export declare const memorySequencerBackend: MemorySequencerBackend;
26
+ export declare function resetMemorySequencerBackendForTests(): void;
@@ -0,0 +1,22 @@
1
+ import type { SequencerBackend, SequencerAllowResult } from '../types';
2
+ /**
3
+ * HTTP backend that delegates allow/acquire/release to the Skedyul platform proxy.
4
+ */
5
+ export declare class PlatformSequencerBackend implements SequencerBackend {
6
+ allow(sequencerKey: string, input: {
7
+ timestamp: number;
8
+ leaseId?: string;
9
+ watermarkTtlMs?: number;
10
+ }): Promise<SequencerAllowResult>;
11
+ acquire(sequencerKey: string, input: {
12
+ leaseId: string;
13
+ timestamp?: number;
14
+ lockTtlMs?: number;
15
+ watermarkTtlMs?: number;
16
+ }): Promise<{
17
+ acquired: boolean;
18
+ reason: 'ok' | 'locked';
19
+ }>;
20
+ release(sequencerKey: string, leaseId: string): Promise<void>;
21
+ }
22
+ export declare const platformSequencerBackend: PlatformSequencerBackend;
@@ -0,0 +1,9 @@
1
+ import type { SkedyulConfig } from '../config/app-config';
2
+ import type { SerializableSequencerConfig } from '../config/sequencer-config';
3
+ /**
4
+ * Register in-process server config for sequencer resolution at runtime.
5
+ */
6
+ export declare function registerSequencerConfig(config: SkedyulConfig): void;
7
+ export declare function clearRegisteredSequencerConfig(): void;
8
+ export declare function getSequencerDefinitions(): Record<string, SerializableSequencerConfig>;
9
+ export declare function getSequencerConfig(sequencerName: string): SerializableSequencerConfig | undefined;
@@ -0,0 +1,17 @@
1
+ export declare class SequencerContextError extends Error {
2
+ readonly code = "SEQUENCER_CONTEXT_ERROR";
3
+ constructor(message: string);
4
+ }
5
+ export declare class SequencerNotFoundError extends Error {
6
+ readonly code = "SEQUENCER_NOT_FOUND";
7
+ constructor(name: string);
8
+ }
9
+ export declare class SequencerBackendError extends Error {
10
+ readonly code = "SEQUENCER_BACKEND_ERROR";
11
+ readonly statusCode?: number;
12
+ constructor(message: string, statusCode?: number);
13
+ }
14
+ export declare class SequencerLockError extends Error {
15
+ readonly code = "SEQUENCER_LOCK_ERROR";
16
+ constructor(message: string);
17
+ }
@@ -0,0 +1,24 @@
1
+ import type { SequencerInput, SequencerAllowInput, SequencerAcquireInput, SequencerReleaseInput, SequencerAllowResult, ResolvedSequencer } from './types';
2
+ import type { RateLimitExecutionContext } from '../ratelimit/types';
3
+ export declare function resolveSequencer(sequencerInput: SequencerInput, ctxOverride?: Partial<RateLimitExecutionContext>): ResolvedSequencer;
4
+ export declare function createSequencerHandle(sequencerInput: SequencerInput, ctxOverride?: Partial<RateLimitExecutionContext>): {
5
+ allow(input: Omit<SequencerAllowInput, "key">): Promise<SequencerAllowResult>;
6
+ acquire(input: Omit<SequencerAcquireInput, "key">): Promise<void>;
7
+ release(input: Omit<SequencerReleaseInput, "key">): Promise<void>;
8
+ };
9
+ export declare function allow(sequencerInput: SequencerInput, input: SequencerAllowInput, ctxOverride?: Partial<RateLimitExecutionContext>): Promise<SequencerAllowResult>;
10
+ export declare function acquire(sequencerInput: SequencerInput, input: SequencerAcquireInput, ctxOverride?: Partial<RateLimitExecutionContext>): Promise<void>;
11
+ export declare function release(sequencerInput: SequencerInput, input: SequencerReleaseInput, ctxOverride?: Partial<RateLimitExecutionContext>): Promise<void>;
12
+ export { registerSequencerConfig, clearRegisteredSequencerConfig, getSequencerConfig, getSequencerDefinitions, } from './config-loader';
13
+ export { resolveSequencerKey } from './resolve-sequencer-key';
14
+ export { getSequencerBackend, resetSequencerBackendForTests, memorySequencerBackend, platformSequencerBackend, resetMemorySequencerBackendForTests, } from './backends';
15
+ export { SequencerContextError, SequencerNotFoundError, SequencerBackendError, SequencerLockError, } from './errors';
16
+ export type { SequencerInput, SequencerSelector, SequencerAllowInput, SequencerAcquireInput, SequencerReleaseInput, SequencerAllowResult, ResolvedSequencer, SequencerBackend, SequencerReason, SequencerExecutionContext, } from './types';
17
+ export type { SequencerScope, SerializableSequencerConfig, SequencerRegistry, } from '../config/sequencer-config';
18
+ export declare const sequencer: {
19
+ allow: typeof allow;
20
+ acquire: typeof acquire;
21
+ release: typeof release;
22
+ resolve: typeof resolveSequencer;
23
+ createHandle: typeof createSequencerHandle;
24
+ };
@@ -0,0 +1,7 @@
1
+ import type { RateLimitExecutionContext } from '../ratelimit/types';
2
+ import type { SerializableSequencerConfig } from '../config/sequencer-config';
3
+ /**
4
+ * Build the Redis sequencer key for a named sequencer definition.
5
+ * Must stay in sync with skedyul-core sequencer validation.
6
+ */
7
+ export declare function resolveSequencerKey(sequencerName: string, config: SerializableSequencerConfig, ctx: RateLimitExecutionContext, subKey?: string): string;
@@ -0,0 +1,50 @@
1
+ import type { SerializableSequencerConfig } from '../config/sequencer-config';
2
+ export type { RateLimitExecutionContext as SequencerExecutionContext } from '../ratelimit/types';
3
+ export type SequencerReason = 'ok' | 'stale' | 'locked' | 'disabled';
4
+ export interface SequencerSelector {
5
+ sequencer: string;
6
+ key?: string;
7
+ }
8
+ export type SequencerInput = string | SequencerSelector;
9
+ export interface SequencerAllowInput {
10
+ key?: string;
11
+ timestamp: number;
12
+ leaseId?: string;
13
+ }
14
+ export interface SequencerAcquireInput {
15
+ key?: string;
16
+ leaseId: string;
17
+ timestamp?: number;
18
+ lockTtlMs?: number;
19
+ }
20
+ export interface SequencerReleaseInput {
21
+ key?: string;
22
+ leaseId: string;
23
+ }
24
+ export interface SequencerAllowResult {
25
+ allowed: boolean;
26
+ reason: SequencerReason;
27
+ watermark?: number;
28
+ }
29
+ export interface ResolvedSequencer {
30
+ name: string;
31
+ sequencerKey: string;
32
+ config: SerializableSequencerConfig;
33
+ }
34
+ export interface SequencerBackend {
35
+ allow(sequencerKey: string, input: {
36
+ timestamp: number;
37
+ leaseId?: string;
38
+ watermarkTtlMs?: number;
39
+ }): Promise<SequencerAllowResult>;
40
+ acquire(sequencerKey: string, input: {
41
+ leaseId: string;
42
+ timestamp?: number;
43
+ lockTtlMs?: number;
44
+ watermarkTtlMs?: number;
45
+ }): Promise<{
46
+ acquired: boolean;
47
+ reason: 'ok' | 'locked';
48
+ }>;
49
+ release(sequencerKey: string, leaseId: string): Promise<void>;
50
+ }
package/dist/server.js CHANGED
@@ -97,6 +97,16 @@ function registerQueueConfig(config) {
97
97
  cachedRuntimeQueues = config.queues ?? null;
98
98
  }
99
99
 
100
+ // src/sequencer/config-loader.ts
101
+ var fs2 = __toESM(require("fs"));
102
+ var path2 = __toESM(require("path"));
103
+ var cachedRuntimeSequencers = null;
104
+ var registeredServerConfig2 = null;
105
+ function registerSequencerConfig(config) {
106
+ registeredServerConfig2 = config;
107
+ cachedRuntimeSequencers = config.sequencers ?? null;
108
+ }
109
+
100
110
  // src/server/utils/schema.ts
101
111
  var z = __toESM(require("zod"));
102
112
  function normalizeBilling(billing) {
@@ -733,7 +743,7 @@ function printStartupLog(config, tools, port) {
733
743
 
734
744
  // src/server/route-handlers/adapters.ts
735
745
  function fromLambdaEvent(event) {
736
- const path3 = event.path || event.rawPath || "/";
746
+ const path4 = event.path || event.rawPath || "/";
737
747
  const method = event.httpMethod || event.requestContext?.http?.method || "POST";
738
748
  const forwardedProto = event.headers?.["x-forwarded-proto"] ?? event.headers?.["X-Forwarded-Proto"];
739
749
  const protocol = forwardedProto ?? "https";
@@ -741,9 +751,9 @@ function fromLambdaEvent(event) {
741
751
  const queryString = event.queryStringParameters ? "?" + new URLSearchParams(
742
752
  event.queryStringParameters
743
753
  ).toString() : "";
744
- const url = `${protocol}://${host}${path3}${queryString}`;
754
+ const url = `${protocol}://${host}${path4}${queryString}`;
745
755
  return {
746
- path: path3,
756
+ path: path4,
747
757
  method,
748
758
  headers: event.headers,
749
759
  query: event.queryStringParameters ?? {},
@@ -825,8 +835,8 @@ function parseBodyByContentType(req) {
825
835
  }
826
836
 
827
837
  // src/server/route-handlers/handlers.ts
828
- var fs2 = __toESM(require("fs"));
829
- var path2 = __toESM(require("path"));
838
+ var fs3 = __toESM(require("fs"));
839
+ var path3 = __toESM(require("path"));
830
840
 
831
841
  // src/server/core-api-handler.ts
832
842
  async function handleCoreMethod(method, params) {
@@ -1293,8 +1303,13 @@ async function handleOAuthCallback(parsedBody, hooks) {
1293
1303
  }
1294
1304
  }
1295
1305
 
1306
+ // src/types/webhook.ts
1307
+ function isRuntimeWebhookContext(ctx) {
1308
+ return "appInstallationId" in ctx && ctx.appInstallationId !== void 0;
1309
+ }
1310
+
1296
1311
  // src/server/handlers/webhook-handler.ts
1297
- function parseWebhookRequest(parsedBody, method, url, path3, headers, query, rawBody, appIdHeader, appVersionIdHeader) {
1312
+ function parseWebhookRequest(parsedBody, method, url, path4, headers, query, rawBody, appIdHeader, appVersionIdHeader) {
1298
1313
  const isEnvelope = typeof parsedBody === "object" && parsedBody !== null && "env" in parsedBody && "request" in parsedBody && "context" in parsedBody;
1299
1314
  if (isEnvelope) {
1300
1315
  const envelope = parsedBody;
@@ -1348,7 +1363,7 @@ function parseWebhookRequest(parsedBody, method, url, path3, headers, query, raw
1348
1363
  const webhookRequest = {
1349
1364
  method,
1350
1365
  url,
1351
- path: path3,
1366
+ path: path4,
1352
1367
  headers,
1353
1368
  query,
1354
1369
  body: parsedBody,
@@ -1377,9 +1392,17 @@ async function executeWebhookHandler(handle, webhookRegistry, data) {
1377
1392
  };
1378
1393
  let webhookResponse;
1379
1394
  try {
1395
+ const rateLimitContext = {
1396
+ app: data.webhookContext.app,
1397
+ appInstallationId: isRuntimeWebhookContext(data.webhookContext) ? data.webhookContext.appInstallationId : void 0,
1398
+ invocation: data.invocation,
1399
+ isProvisionContext: !isRuntimeWebhookContext(data.webhookContext)
1400
+ };
1380
1401
  webhookResponse = await runWithLogContext({ invocation: data.invocation }, async () => {
1381
1402
  return await runWithConfig(requestConfig, async () => {
1382
- return await webhookDef.handler(data.webhookRequest, data.webhookContext);
1403
+ return await runWithRateLimitExecutionContext(rateLimitContext, async () => {
1404
+ return await webhookDef.handler(data.webhookRequest, data.webhookContext);
1405
+ });
1383
1406
  });
1384
1407
  });
1385
1408
  } catch (err) {
@@ -1406,7 +1429,7 @@ function isMethodAllowed(webhookRegistry, handle, method) {
1406
1429
 
1407
1430
  // src/server/route-handlers/handlers.ts
1408
1431
  function getConfigFilePath() {
1409
- return process.env.LAMBDA_TASK_ROOT ? path2.join(process.env.LAMBDA_TASK_ROOT, ".skedyul", "config.json") : ".skedyul/config.json";
1432
+ return process.env.LAMBDA_TASK_ROOT ? path3.join(process.env.LAMBDA_TASK_ROOT, ".skedyul", "config.json") : ".skedyul/config.json";
1410
1433
  }
1411
1434
  function findToolInRegistry(registry, toolName) {
1412
1435
  for (const [key, t] of Object.entries(registry)) {
@@ -1445,8 +1468,8 @@ function handleHealthRoute(ctx) {
1445
1468
  function handleConfigRoute(ctx) {
1446
1469
  const configFilePath = getConfigFilePath();
1447
1470
  try {
1448
- if (fs2.existsSync(configFilePath)) {
1449
- const fileConfig = JSON.parse(fs2.readFileSync(configFilePath, "utf-8"));
1471
+ if (fs3.existsSync(configFilePath)) {
1472
+ const fileConfig = JSON.parse(fs3.readFileSync(configFilePath, "utf-8"));
1450
1473
  return { status: 200, body: fileConfig };
1451
1474
  }
1452
1475
  } catch (err) {
@@ -2134,6 +2157,7 @@ installContextLogger();
2134
2157
  function createSkedyulServer(config) {
2135
2158
  mergeRuntimeEnv();
2136
2159
  registerQueueConfig(config);
2160
+ registerSequencerConfig(config);
2137
2161
  const registry = config.tools;
2138
2162
  const webhookRegistry = config.webhooks;
2139
2163
  if (config.coreApi?.service) {
@@ -58,6 +58,16 @@ function registerQueueConfig(config) {
58
58
  cachedRuntimeQueues = config.queues ?? null;
59
59
  }
60
60
 
61
+ // src/sequencer/config-loader.ts
62
+ import * as fs2 from "fs";
63
+ import * as path2 from "path";
64
+ var cachedRuntimeSequencers = null;
65
+ var registeredServerConfig2 = null;
66
+ function registerSequencerConfig(config) {
67
+ registeredServerConfig2 = config;
68
+ cachedRuntimeSequencers = config.sequencers ?? null;
69
+ }
70
+
61
71
  // src/server/utils/schema.ts
62
72
  import * as z from "zod";
63
73
  function normalizeBilling(billing) {
@@ -694,7 +704,7 @@ function printStartupLog(config, tools, port) {
694
704
 
695
705
  // src/server/route-handlers/adapters.ts
696
706
  function fromLambdaEvent(event) {
697
- const path3 = event.path || event.rawPath || "/";
707
+ const path4 = event.path || event.rawPath || "/";
698
708
  const method = event.httpMethod || event.requestContext?.http?.method || "POST";
699
709
  const forwardedProto = event.headers?.["x-forwarded-proto"] ?? event.headers?.["X-Forwarded-Proto"];
700
710
  const protocol = forwardedProto ?? "https";
@@ -702,9 +712,9 @@ function fromLambdaEvent(event) {
702
712
  const queryString = event.queryStringParameters ? "?" + new URLSearchParams(
703
713
  event.queryStringParameters
704
714
  ).toString() : "";
705
- const url = `${protocol}://${host}${path3}${queryString}`;
715
+ const url = `${protocol}://${host}${path4}${queryString}`;
706
716
  return {
707
- path: path3,
717
+ path: path4,
708
718
  method,
709
719
  headers: event.headers,
710
720
  query: event.queryStringParameters ?? {},
@@ -786,8 +796,8 @@ function parseBodyByContentType(req) {
786
796
  }
787
797
 
788
798
  // src/server/route-handlers/handlers.ts
789
- import * as fs2 from "fs";
790
- import * as path2 from "path";
799
+ import * as fs3 from "fs";
800
+ import * as path3 from "path";
791
801
 
792
802
  // src/server/core-api-handler.ts
793
803
  async function handleCoreMethod(method, params) {
@@ -1254,8 +1264,13 @@ async function handleOAuthCallback(parsedBody, hooks) {
1254
1264
  }
1255
1265
  }
1256
1266
 
1267
+ // src/types/webhook.ts
1268
+ function isRuntimeWebhookContext(ctx) {
1269
+ return "appInstallationId" in ctx && ctx.appInstallationId !== void 0;
1270
+ }
1271
+
1257
1272
  // src/server/handlers/webhook-handler.ts
1258
- function parseWebhookRequest(parsedBody, method, url, path3, headers, query, rawBody, appIdHeader, appVersionIdHeader) {
1273
+ function parseWebhookRequest(parsedBody, method, url, path4, headers, query, rawBody, appIdHeader, appVersionIdHeader) {
1259
1274
  const isEnvelope = typeof parsedBody === "object" && parsedBody !== null && "env" in parsedBody && "request" in parsedBody && "context" in parsedBody;
1260
1275
  if (isEnvelope) {
1261
1276
  const envelope = parsedBody;
@@ -1309,7 +1324,7 @@ function parseWebhookRequest(parsedBody, method, url, path3, headers, query, raw
1309
1324
  const webhookRequest = {
1310
1325
  method,
1311
1326
  url,
1312
- path: path3,
1327
+ path: path4,
1313
1328
  headers,
1314
1329
  query,
1315
1330
  body: parsedBody,
@@ -1338,9 +1353,17 @@ async function executeWebhookHandler(handle, webhookRegistry, data) {
1338
1353
  };
1339
1354
  let webhookResponse;
1340
1355
  try {
1356
+ const rateLimitContext = {
1357
+ app: data.webhookContext.app,
1358
+ appInstallationId: isRuntimeWebhookContext(data.webhookContext) ? data.webhookContext.appInstallationId : void 0,
1359
+ invocation: data.invocation,
1360
+ isProvisionContext: !isRuntimeWebhookContext(data.webhookContext)
1361
+ };
1341
1362
  webhookResponse = await runWithLogContext({ invocation: data.invocation }, async () => {
1342
1363
  return await runWithConfig(requestConfig, async () => {
1343
- return await webhookDef.handler(data.webhookRequest, data.webhookContext);
1364
+ return await runWithRateLimitExecutionContext(rateLimitContext, async () => {
1365
+ return await webhookDef.handler(data.webhookRequest, data.webhookContext);
1366
+ });
1344
1367
  });
1345
1368
  });
1346
1369
  } catch (err) {
@@ -1367,7 +1390,7 @@ function isMethodAllowed(webhookRegistry, handle, method) {
1367
1390
 
1368
1391
  // src/server/route-handlers/handlers.ts
1369
1392
  function getConfigFilePath() {
1370
- return process.env.LAMBDA_TASK_ROOT ? path2.join(process.env.LAMBDA_TASK_ROOT, ".skedyul", "config.json") : ".skedyul/config.json";
1393
+ return process.env.LAMBDA_TASK_ROOT ? path3.join(process.env.LAMBDA_TASK_ROOT, ".skedyul", "config.json") : ".skedyul/config.json";
1371
1394
  }
1372
1395
  function findToolInRegistry(registry, toolName) {
1373
1396
  for (const [key, t] of Object.entries(registry)) {
@@ -1406,8 +1429,8 @@ function handleHealthRoute(ctx) {
1406
1429
  function handleConfigRoute(ctx) {
1407
1430
  const configFilePath = getConfigFilePath();
1408
1431
  try {
1409
- if (fs2.existsSync(configFilePath)) {
1410
- const fileConfig = JSON.parse(fs2.readFileSync(configFilePath, "utf-8"));
1432
+ if (fs3.existsSync(configFilePath)) {
1433
+ const fileConfig = JSON.parse(fs3.readFileSync(configFilePath, "utf-8"));
1411
1434
  return { status: 200, body: fileConfig };
1412
1435
  }
1413
1436
  } catch (err) {
@@ -2095,6 +2118,7 @@ installContextLogger();
2095
2118
  function createSkedyulServer(config) {
2096
2119
  mergeRuntimeEnv();
2097
2120
  registerQueueConfig(config);
2121
+ registerSequencerConfig(config);
2098
2122
  const registry = config.tools;
2099
2123
  const webhookRegistry = config.webhooks;
2100
2124
  if (config.coreApi?.service) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skedyul",
3
- "version": "1.5.13",
3
+ "version": "1.6.0",
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",
77
77
  "db:generate": "echo 'No database generation needed for this package'",
78
78
  "dev": "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/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"
80
80
  },
81
81
  "keywords": [
82
82
  "mcp",