skedyul 1.2.51 → 1.3.1

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/index.js CHANGED
@@ -169,10 +169,15 @@ __export(index_exports, {
169
169
  ParticipantEventPayloadSchema: () => ParticipantEventPayloadSchema,
170
170
  ParticipantKindSchema: () => ParticipantKindSchema,
171
171
  ProvisionConfigSchema: () => ProvisionConfigSchema,
172
+ QueueContextError: () => QueueContextError,
173
+ QueueNotFoundError: () => QueueNotFoundError,
174
+ QueuedFetchExhaustedError: () => QueuedFetchExhaustedError,
175
+ RateLimitBackendError: () => RateLimitBackendError,
172
176
  RelationshipCardinalitySchema: () => RelationshipCardinalitySchema,
173
177
  RelationshipDefinitionSchema: () => RelationshipDefinitionSchema,
174
178
  RelationshipExtensionSchema: () => RelationshipExtensionSchema,
175
179
  RelationshipLinkSchema: () => RelationshipLinkSchema,
180
+ RequeueOutsideContextError: () => RequeueOutsideContextError,
176
181
  ResolvedSkillSchema: () => ResolvedSkillSchema,
177
182
  ResolvedTriggerSchema: () => ResolvedTriggerSchema,
178
183
  ResourceDependencySchema: () => ResourceDependencySchema,
@@ -250,6 +255,7 @@ __export(index_exports, {
250
255
  createListResponse: () => createListResponse,
251
256
  createNotFoundError: () => createNotFoundError,
252
257
  createPermissionError: () => createPermissionError,
258
+ createQueueHandle: () => createQueueHandle,
253
259
  createRateLimitError: () => createRateLimitError,
254
260
  createServerHookContext: () => createServerHookContext,
255
261
  createSuccessResponse: () => createSuccessResponse,
@@ -260,6 +266,7 @@ __export(index_exports, {
260
266
  createWorkflowStepContext: () => createWorkflowStepContext,
261
267
  cron: () => cron,
262
268
  default: () => index_default,
269
+ defaultShouldRetry: () => defaultShouldRetry,
263
270
  defineAgent: () => defineAgent,
264
271
  defineChannel: () => defineChannel,
265
272
  defineConfig: () => defineConfig,
@@ -282,6 +289,7 @@ __export(index_exports, {
282
289
  getConfig: () => getConfig,
283
290
  getContextByHandle: () => getContextByHandle,
284
291
  getContextByModel: () => getContextByModel,
292
+ getRateLimitExecutionContext: () => getRateLimitExecutionContext,
285
293
  getRequiredInstallEnvKeys: () => getRequiredInstallEnvKeys,
286
294
  getRetryDelay: () => getRetryDelay,
287
295
  instance: () => instance,
@@ -301,10 +309,16 @@ __export(index_exports, {
301
309
  loadConfig: () => loadConfig,
302
310
  matchesTrigger: () => matchesTrigger,
303
311
  parseCRMSchema: () => parseCRMSchema,
312
+ queuedFetch: () => queuedFetch,
313
+ queuedFetchResponse: () => queuedFetchResponse,
314
+ registerQueueConfig: () => registerQueueConfig,
304
315
  report: () => report,
316
+ requeue: () => requeue,
305
317
  resolveInputMappings: () => resolveInputMappings,
318
+ resolveQueue: () => resolveQueue,
306
319
  resource: () => resource,
307
320
  runWithConfig: () => runWithConfig,
321
+ runWithRateLimitExecutionContext: () => runWithRateLimitExecutionContext,
308
322
  safeParseCRMSchema: () => safeParseCRMSchema,
309
323
  safeParseConfig: () => safeParseConfig,
310
324
  server: () => server,
@@ -2163,6 +2177,68 @@ var CoreApiService = class {
2163
2177
  };
2164
2178
  var coreApiService = new CoreApiService();
2165
2179
 
2180
+ // src/ratelimit/config-loader.ts
2181
+ var fs = __toESM(require("fs"));
2182
+ var path = __toESM(require("path"));
2183
+ var cachedRuntimeQueues = null;
2184
+ function getRuntimeConfigPath() {
2185
+ if (process.env.LAMBDA_TASK_ROOT) {
2186
+ return path.join(process.env.LAMBDA_TASK_ROOT, ".skedyul", "config.json");
2187
+ }
2188
+ return path.join(process.cwd(), ".skedyul", "config.json");
2189
+ }
2190
+ function loadRuntimeConfigFile() {
2191
+ const configPath = getRuntimeConfigPath();
2192
+ if (!fs.existsSync(configPath)) {
2193
+ return null;
2194
+ }
2195
+ try {
2196
+ const raw = fs.readFileSync(configPath, "utf-8");
2197
+ return JSON.parse(raw);
2198
+ } catch {
2199
+ return null;
2200
+ }
2201
+ }
2202
+ var registeredServerConfig = null;
2203
+ function registerQueueConfig(config) {
2204
+ registeredServerConfig = config;
2205
+ cachedRuntimeQueues = config.queues ?? null;
2206
+ }
2207
+ function getQueueDefinitions() {
2208
+ if (cachedRuntimeQueues) {
2209
+ return cachedRuntimeQueues;
2210
+ }
2211
+ if (registeredServerConfig?.queues) {
2212
+ cachedRuntimeQueues = stripNonSerializableQueues(registeredServerConfig.queues);
2213
+ return cachedRuntimeQueues;
2214
+ }
2215
+ const fileConfig = loadRuntimeConfigFile();
2216
+ if (fileConfig?.queues) {
2217
+ cachedRuntimeQueues = fileConfig.queues;
2218
+ return cachedRuntimeQueues;
2219
+ }
2220
+ return {};
2221
+ }
2222
+ function stripNonSerializableQueues(queues) {
2223
+ const result = {};
2224
+ for (const [name, config] of Object.entries(queues)) {
2225
+ const { shouldRetry: _shouldRetry, ...serializable } = config;
2226
+ result[name] = serializable;
2227
+ }
2228
+ return result;
2229
+ }
2230
+ function getQueueConfig(queueName) {
2231
+ return getQueueDefinitions()[queueName];
2232
+ }
2233
+ function getQueueConfigWithRetry(queueName) {
2234
+ const fromServer = registeredServerConfig?.queues?.[queueName];
2235
+ if (fromServer) {
2236
+ return fromServer;
2237
+ }
2238
+ const serializable = getQueueConfig(queueName);
2239
+ return serializable;
2240
+ }
2241
+
2166
2242
  // src/server/utils/schema.ts
2167
2243
  var z8 = __toESM(require("zod"));
2168
2244
  function normalizeBilling(billing) {
@@ -3484,6 +3560,35 @@ var report = {
3484
3560
  }
3485
3561
  };
3486
3562
 
3563
+ // src/ratelimit/context.ts
3564
+ var import_async_hooks2 = require("async_hooks");
3565
+ var executionContextStorage = new import_async_hooks2.AsyncLocalStorage();
3566
+ var activeOperationStorage = new import_async_hooks2.AsyncLocalStorage();
3567
+ function runWithRateLimitExecutionContext(ctx, fn) {
3568
+ return executionContextStorage.run(ctx, fn);
3569
+ }
3570
+ function getRateLimitExecutionContext() {
3571
+ return executionContextStorage.getStore();
3572
+ }
3573
+ function runWithActiveQueuedOperation(operation, fn) {
3574
+ return activeOperationStorage.run(operation, fn);
3575
+ }
3576
+ function getActiveQueuedOperation() {
3577
+ return activeOperationStorage.getStore();
3578
+ }
3579
+ function setActiveQueuedOperationLease(lease) {
3580
+ const op = activeOperationStorage.getStore();
3581
+ if (op) {
3582
+ op.lease = lease;
3583
+ }
3584
+ }
3585
+ function updateActiveQueuedOperationAttempt(attempt) {
3586
+ const op = activeOperationStorage.getStore();
3587
+ if (op) {
3588
+ op.attempt = attempt;
3589
+ }
3590
+ }
3591
+
3487
3592
  // src/errors.ts
3488
3593
  var InstallError = class extends Error {
3489
3594
  // Optional: which field caused the error
@@ -3538,8 +3643,8 @@ var AppAuthInvalidError = class extends Error {
3538
3643
  };
3539
3644
 
3540
3645
  // src/server/context-logger.ts
3541
- var import_async_hooks2 = require("async_hooks");
3542
- var logContextStorage = new import_async_hooks2.AsyncLocalStorage();
3646
+ var import_async_hooks3 = require("async_hooks");
3647
+ var logContextStorage = new import_async_hooks3.AsyncLocalStorage();
3543
3648
  function runWithLogContext(context, fn) {
3544
3649
  return logContextStorage.run(context, fn);
3545
3650
  }
@@ -3752,9 +3857,17 @@ function createCallToolHandler(registry, state, onMaxRequests) {
3752
3857
  baseUrl: toolEnv.SKEDYUL_API_URL ?? "",
3753
3858
  apiToken: toolEnv.SKEDYUL_API_TOKEN ?? ""
3754
3859
  };
3860
+ const rateLimitContext = {
3861
+ app,
3862
+ appInstallationId: trigger === "provision" ? void 0 : rawContext.appInstallationId,
3863
+ invocation,
3864
+ isProvisionContext: trigger === "provision"
3865
+ };
3755
3866
  const functionResult = await runWithConfig(requestConfig, async () => {
3756
- return await runWithLogContext({ invocation }, async () => {
3757
- return await fn(inputs, executionContext);
3867
+ return await runWithRateLimitExecutionContext(rateLimitContext, async () => {
3868
+ return await runWithLogContext({ invocation }, async () => {
3869
+ return await fn(inputs, executionContext);
3870
+ });
3758
3871
  });
3759
3872
  });
3760
3873
  const billing = normalizeBilling(functionResult.billing);
@@ -3798,6 +3911,7 @@ function createCallToolHandler(registry, state, onMaxRequests) {
3798
3911
  };
3799
3912
  }
3800
3913
  const errorMessage = error instanceof Error ? error.message : String(error ?? "");
3914
+ const errorCode = error && typeof error === "object" && "code" in error && typeof error.code === "string" ? error.code : "TOOL_EXECUTION_ERROR";
3801
3915
  return {
3802
3916
  output: null,
3803
3917
  billing: { credits: 0 },
@@ -3807,7 +3921,7 @@ function createCallToolHandler(registry, state, onMaxRequests) {
3807
3921
  toolName
3808
3922
  },
3809
3923
  error: {
3810
- code: "TOOL_EXECUTION_ERROR",
3924
+ code: errorCode,
3811
3925
  message: errorMessage
3812
3926
  }
3813
3927
  };
@@ -3891,7 +4005,7 @@ function printStartupLog(config, tools, port) {
3891
4005
 
3892
4006
  // src/server/route-handlers/adapters.ts
3893
4007
  function fromLambdaEvent(event2) {
3894
- const path5 = event2.path || event2.rawPath || "/";
4008
+ const path6 = event2.path || event2.rawPath || "/";
3895
4009
  const method = event2.httpMethod || event2.requestContext?.http?.method || "POST";
3896
4010
  const forwardedProto = event2.headers?.["x-forwarded-proto"] ?? event2.headers?.["X-Forwarded-Proto"];
3897
4011
  const protocol = forwardedProto ?? "https";
@@ -3899,9 +4013,9 @@ function fromLambdaEvent(event2) {
3899
4013
  const queryString = event2.queryStringParameters ? "?" + new URLSearchParams(
3900
4014
  event2.queryStringParameters
3901
4015
  ).toString() : "";
3902
- const url = `${protocol}://${host}${path5}${queryString}`;
4016
+ const url = `${protocol}://${host}${path6}${queryString}`;
3903
4017
  return {
3904
- path: path5,
4018
+ path: path6,
3905
4019
  method,
3906
4020
  headers: event2.headers,
3907
4021
  query: event2.queryStringParameters ?? {},
@@ -3983,8 +4097,8 @@ function parseBodyByContentType(req) {
3983
4097
  }
3984
4098
 
3985
4099
  // src/server/route-handlers/handlers.ts
3986
- var fs = __toESM(require("fs"));
3987
- var path = __toESM(require("path"));
4100
+ var fs2 = __toESM(require("fs"));
4101
+ var path2 = __toESM(require("path"));
3988
4102
 
3989
4103
  // src/server/core-api-handler.ts
3990
4104
  async function handleCoreMethod(method, params) {
@@ -4152,7 +4266,8 @@ function serializeConfig(config) {
4152
4266
  type: w.type ?? "WEBHOOK"
4153
4267
  })) : [],
4154
4268
  provision: isProvisionConfig(config.provision) ? config.provision : void 0,
4155
- agents: config.agents
4269
+ agents: config.agents,
4270
+ queues: config.queues
4156
4271
  };
4157
4272
  }
4158
4273
  function isProvisionConfig(value) {
@@ -4448,7 +4563,7 @@ async function handleOAuthCallback(parsedBody, hooks) {
4448
4563
  }
4449
4564
 
4450
4565
  // src/server/handlers/webhook-handler.ts
4451
- function parseWebhookRequest(parsedBody, method, url, path5, headers, query, rawBody, appIdHeader, appVersionIdHeader) {
4566
+ function parseWebhookRequest(parsedBody, method, url, path6, headers, query, rawBody, appIdHeader, appVersionIdHeader) {
4452
4567
  const isEnvelope = typeof parsedBody === "object" && parsedBody !== null && "env" in parsedBody && "request" in parsedBody && "context" in parsedBody;
4453
4568
  if (isEnvelope) {
4454
4569
  const envelope = parsedBody;
@@ -4502,7 +4617,7 @@ function parseWebhookRequest(parsedBody, method, url, path5, headers, query, raw
4502
4617
  const webhookRequest = {
4503
4618
  method,
4504
4619
  url,
4505
- path: path5,
4620
+ path: path6,
4506
4621
  headers,
4507
4622
  query,
4508
4623
  body: parsedBody,
@@ -4560,7 +4675,7 @@ function isMethodAllowed(webhookRegistry, handle, method) {
4560
4675
 
4561
4676
  // src/server/route-handlers/handlers.ts
4562
4677
  function getConfigFilePath() {
4563
- return process.env.LAMBDA_TASK_ROOT ? path.join(process.env.LAMBDA_TASK_ROOT, ".skedyul", "config.json") : ".skedyul/config.json";
4678
+ return process.env.LAMBDA_TASK_ROOT ? path2.join(process.env.LAMBDA_TASK_ROOT, ".skedyul", "config.json") : ".skedyul/config.json";
4564
4679
  }
4565
4680
  function findToolInRegistry(registry, toolName) {
4566
4681
  for (const [key, t] of Object.entries(registry)) {
@@ -4599,8 +4714,8 @@ function handleHealthRoute(ctx) {
4599
4714
  function handleConfigRoute(ctx) {
4600
4715
  const configFilePath = getConfigFilePath();
4601
4716
  try {
4602
- if (fs.existsSync(configFilePath)) {
4603
- const fileConfig = JSON.parse(fs.readFileSync(configFilePath, "utf-8"));
4717
+ if (fs2.existsSync(configFilePath)) {
4718
+ const fileConfig = JSON.parse(fs2.readFileSync(configFilePath, "utf-8"));
4604
4719
  return { status: 200, body: fileConfig };
4605
4720
  }
4606
4721
  } catch (err) {
@@ -5285,6 +5400,7 @@ function createServerlessInstance(config, tools, callTool, state, mcpServer) {
5285
5400
  installContextLogger();
5286
5401
  function createSkedyulServer(config) {
5287
5402
  mergeRuntimeEnv();
5403
+ registerQueueConfig(config);
5288
5404
  const registry = config.tools;
5289
5405
  const webhookRegistry = config.webhooks;
5290
5406
  if (config.coreApi?.service) {
@@ -5553,8 +5669,8 @@ function defineNavigation(navigation) {
5553
5669
  }
5554
5670
 
5555
5671
  // src/config/loader.ts
5556
- var fs2 = __toESM(require("fs"));
5557
- var path2 = __toESM(require("path"));
5672
+ var fs3 = __toESM(require("fs"));
5673
+ var path3 = __toESM(require("path"));
5558
5674
  var os = __toESM(require("os"));
5559
5675
  var CONFIG_FILE_NAMES = [
5560
5676
  "skedyul.config.ts",
@@ -5563,13 +5679,13 @@ var CONFIG_FILE_NAMES = [
5563
5679
  "skedyul.config.cjs"
5564
5680
  ];
5565
5681
  async function transpileTypeScript(filePath) {
5566
- const content = fs2.readFileSync(filePath, "utf-8");
5567
- const configDir = path2.dirname(path2.resolve(filePath));
5682
+ const content = fs3.readFileSync(filePath, "utf-8");
5683
+ const configDir = path3.dirname(path3.resolve(filePath));
5568
5684
  let transpiled = content.replace(/import\s+type\s+\{[^}]+\}\s+from\s+['"][^'"]+['"]\s*;?\n?/g, "").replace(/import\s+\{\s*defineConfig\s*\}\s+from\s+['"]skedyul['"]\s*;?\n?/g, "").replace(/:\s*SkedyulConfig/g, "").replace(/export\s+default\s+/, "module.exports = ").replace(/defineConfig\s*\(\s*\{/, "{").replace(/\}\s*\)\s*;?\s*$/, "}");
5569
5685
  transpiled = transpiled.replace(
5570
5686
  /import\s+(\w+)\s+from\s+['"](\.[^'"]+)['"]\s*(?:with\s*\{[^}]*\})?/g,
5571
5687
  (match, varName, relativePath) => {
5572
- const absolutePath = path2.resolve(configDir, relativePath);
5688
+ const absolutePath = path3.resolve(configDir, relativePath);
5573
5689
  return `const ${varName} = require('${absolutePath.replace(/\\/g, "/")}')`;
5574
5690
  }
5575
5691
  );
@@ -5577,8 +5693,8 @@ async function transpileTypeScript(filePath) {
5577
5693
  return transpiled;
5578
5694
  }
5579
5695
  async function loadConfig(configPath) {
5580
- const absolutePath = path2.resolve(configPath);
5581
- if (!fs2.existsSync(absolutePath)) {
5696
+ const absolutePath = path3.resolve(configPath);
5697
+ if (!fs3.existsSync(absolutePath)) {
5582
5698
  throw new Error(`Config file not found: ${absolutePath}`);
5583
5699
  }
5584
5700
  const isTypeScript = absolutePath.endsWith(".ts");
@@ -5587,8 +5703,8 @@ async function loadConfig(configPath) {
5587
5703
  if (isTypeScript) {
5588
5704
  const transpiled = await transpileTypeScript(absolutePath);
5589
5705
  const tempDir = os.tmpdir();
5590
- const tempFile = path2.join(tempDir, `skedyul-config-${Date.now()}.cjs`);
5591
- fs2.writeFileSync(tempFile, transpiled);
5706
+ const tempFile = path3.join(tempDir, `skedyul-config-${Date.now()}.cjs`);
5707
+ fs3.writeFileSync(tempFile, transpiled);
5592
5708
  moduleToLoad = tempFile;
5593
5709
  try {
5594
5710
  const module3 = require(moduleToLoad);
@@ -5602,7 +5718,7 @@ async function loadConfig(configPath) {
5602
5718
  return config2;
5603
5719
  } finally {
5604
5720
  try {
5605
- fs2.unlinkSync(tempFile);
5721
+ fs3.unlinkSync(tempFile);
5606
5722
  } catch {
5607
5723
  }
5608
5724
  }
@@ -5637,13 +5753,13 @@ function validateConfig(config) {
5637
5753
  }
5638
5754
 
5639
5755
  // src/config/schema-loader.ts
5640
- var fs3 = __toESM(require("fs"));
5641
- var path3 = __toESM(require("path"));
5756
+ var fs4 = __toESM(require("fs"));
5757
+ var path4 = __toESM(require("path"));
5642
5758
  var os2 = __toESM(require("os"));
5643
5759
 
5644
5760
  // src/config/resolver.ts
5645
- var fs4 = __toESM(require("fs"));
5646
- var path4 = __toESM(require("path"));
5761
+ var fs5 = __toESM(require("fs"));
5762
+ var path5 = __toESM(require("path"));
5647
5763
 
5648
5764
  // src/config/utils.ts
5649
5765
  function getAllEnvKeys(config) {
@@ -5660,6 +5776,553 @@ function getRequiredInstallEnvKeys(config) {
5660
5776
  return Object.entries(provision.env).filter(([, def]) => def.required).map(([key]) => key);
5661
5777
  }
5662
5778
 
5779
+ // src/ratelimit/errors.ts
5780
+ var QueueContextError = class extends Error {
5781
+ constructor(message) {
5782
+ super(message);
5783
+ this.code = "QUEUE_CONTEXT_ERROR";
5784
+ this.name = "QueueContextError";
5785
+ }
5786
+ };
5787
+ var QueueNotFoundError = class extends Error {
5788
+ constructor(queueName) {
5789
+ super(`Queue "${queueName}" is not defined in skedyul.config queues`);
5790
+ this.code = "QUEUE_NOT_FOUND";
5791
+ this.name = "QueueNotFoundError";
5792
+ }
5793
+ };
5794
+ var QueuedFetchExhaustedError = class extends Error {
5795
+ constructor(attempts, maxRetries, causeError) {
5796
+ super(
5797
+ `queuedFetch exhausted retries after ${attempts} attempts (maxRetries=${maxRetries})`
5798
+ );
5799
+ this.code = "QUEUED_FETCH_EXHAUSTED";
5800
+ this.name = "QueuedFetchExhaustedError";
5801
+ this.attempts = attempts;
5802
+ this.maxRetries = maxRetries;
5803
+ this.causeError = causeError;
5804
+ }
5805
+ };
5806
+ var RequeueOutsideContextError = class extends Error {
5807
+ constructor() {
5808
+ super("requeue() can only be called inside an active queuedFetch operation");
5809
+ this.code = "REQUEUE_OUTSIDE_CONTEXT";
5810
+ this.name = "RequeueOutsideContextError";
5811
+ }
5812
+ };
5813
+ var RateLimitBackendError = class extends Error {
5814
+ constructor(message, statusCode) {
5815
+ super(message);
5816
+ this.code = "RATE_LIMIT_BACKEND_ERROR";
5817
+ this.name = "RateLimitBackendError";
5818
+ this.statusCode = statusCode;
5819
+ }
5820
+ };
5821
+
5822
+ // src/ratelimit/resolve-queue-key.ts
5823
+ function resolveEndpointHandle(config, invocation) {
5824
+ if (config.endpoint) {
5825
+ return config.endpoint;
5826
+ }
5827
+ if (invocation?.toolHandle) {
5828
+ return invocation.toolHandle;
5829
+ }
5830
+ if (invocation?.serverHookHandle) {
5831
+ return invocation.serverHookHandle;
5832
+ }
5833
+ throw new QueueContextError(
5834
+ `Cannot resolve endpoint handle for queue scope "${config.scope}". Set endpoint in queue config or ensure invocation.toolHandle/serverHookHandle is available.`
5835
+ );
5836
+ }
5837
+ function appendSubKey(base, subKey) {
5838
+ return subKey ? `${base}:${subKey}` : base;
5839
+ }
5840
+ function resolveQueueKey(queueName, config, ctx, subKey) {
5841
+ const { app, appInstallationId, invocation, isProvisionContext: isProvisionContext2 } = ctx;
5842
+ switch (config.scope) {
5843
+ case "provision": {
5844
+ const base = `rl:pv:${app.versionId}:${queueName}`;
5845
+ return appendSubKey(base, subKey);
5846
+ }
5847
+ case "install": {
5848
+ if (!appInstallationId) {
5849
+ throw new QueueContextError(
5850
+ `Queue "${queueName}" with scope "install" requires appInstallationId in context`
5851
+ );
5852
+ }
5853
+ const base = `rl:in:${appInstallationId}:${queueName}`;
5854
+ return appendSubKey(base, subKey);
5855
+ }
5856
+ case "provision_endpoint": {
5857
+ if (!isProvisionContext2 && appInstallationId) {
5858
+ throw new QueueContextError(
5859
+ `Queue "${queueName}" with scope "provision_endpoint" requires provision context (no install)`
5860
+ );
5861
+ }
5862
+ const endpointHandle = resolveEndpointHandle(config, invocation);
5863
+ const base = `rl:pep:${app.versionId}:${endpointHandle}:${queueName}`;
5864
+ return appendSubKey(base, subKey);
5865
+ }
5866
+ case "install_endpoint": {
5867
+ if (!appInstallationId) {
5868
+ throw new QueueContextError(
5869
+ `Queue "${queueName}" with scope "install_endpoint" requires appInstallationId in context`
5870
+ );
5871
+ }
5872
+ const endpointHandle = resolveEndpointHandle(config, invocation);
5873
+ const base = `rl:iep:${appInstallationId}:${endpointHandle}:${queueName}`;
5874
+ return appendSubKey(base, subKey);
5875
+ }
5876
+ case "global": {
5877
+ const base = `rl:gl:${app.versionId}:${queueName}`;
5878
+ return appendSubKey(base, subKey);
5879
+ }
5880
+ default: {
5881
+ const _exhaustive = config.scope;
5882
+ throw new QueueContextError(`Unknown queue scope: ${String(_exhaustive)}`);
5883
+ }
5884
+ }
5885
+ }
5886
+ function toQueueLimits(config) {
5887
+ return {
5888
+ maxConcurrent: config.maxConcurrent,
5889
+ minTime: config.minTime,
5890
+ reservoir: config.reservoir,
5891
+ reservoirRefreshAmount: config.reservoirRefreshAmount,
5892
+ reservoirRefreshInterval: config.reservoirRefreshInterval
5893
+ };
5894
+ }
5895
+
5896
+ // src/ratelimit/backends/platform.ts
5897
+ function getApiBaseUrl() {
5898
+ const config = getConfig();
5899
+ if (config.baseUrl) {
5900
+ return config.baseUrl.replace(/\/+$/, "");
5901
+ }
5902
+ return (process.env.SKEDYUL_API_URL ?? process.env.SKEDYUL_NODE_URL ?? "").replace(/\/+$/, "");
5903
+ }
5904
+ function getApiToken() {
5905
+ const config = getConfig();
5906
+ return config.apiToken || process.env.SKEDYUL_API_TOKEN || "";
5907
+ }
5908
+ async function callRateLimitApi(path6, body) {
5909
+ const baseUrl = getApiBaseUrl();
5910
+ const token2 = getApiToken();
5911
+ if (!baseUrl || !token2) {
5912
+ throw new RateLimitBackendError(
5913
+ "SKEDYUL_API_URL and SKEDYUL_API_TOKEN are required for platform queue coordination"
5914
+ );
5915
+ }
5916
+ const response = await fetch(`${baseUrl}/api/internal/ratelimit/${path6}`, {
5917
+ method: "POST",
5918
+ headers: {
5919
+ Authorization: `Bearer ${token2}`,
5920
+ "Content-Type": "application/json"
5921
+ },
5922
+ body: JSON.stringify(body)
5923
+ });
5924
+ const payload = await response.json().catch(() => null);
5925
+ if (!response.ok || payload?.success === false) {
5926
+ const message = payload?.errors?.[0]?.message ?? `Queue coordination API ${path6} failed with status ${response.status}`;
5927
+ throw new RateLimitBackendError(message, response.status);
5928
+ }
5929
+ if (!payload?.data) {
5930
+ throw new RateLimitBackendError(`Queue coordination API ${path6} returned empty data`);
5931
+ }
5932
+ return payload.data;
5933
+ }
5934
+ var PlatformRateLimitBackend = class {
5935
+ async acquire(queueKey, limits, timeoutMs) {
5936
+ const data = await callRateLimitApi("acquire", {
5937
+ queueKey,
5938
+ limits,
5939
+ timeoutMs
5940
+ });
5941
+ return {
5942
+ leaseId: data.leaseId,
5943
+ acquiredAt: data.acquiredAt,
5944
+ queueKey: data.queueKey
5945
+ };
5946
+ }
5947
+ async release(lease) {
5948
+ await callRateLimitApi("release", {
5949
+ leaseId: lease.leaseId
5950
+ });
5951
+ }
5952
+ };
5953
+ var platformRateLimitBackend = new PlatformRateLimitBackend();
5954
+
5955
+ // src/ratelimit/backends/memory.ts
5956
+ var DEFAULT_MAX_CONCURRENT = 10;
5957
+ function getMaxConcurrent(limits) {
5958
+ return limits.maxConcurrent ?? DEFAULT_MAX_CONCURRENT;
5959
+ }
5960
+ function getMinTime(limits) {
5961
+ return limits.minTime ?? 0;
5962
+ }
5963
+ function generateLeaseId() {
5964
+ return `mem_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;
5965
+ }
5966
+ function refillTokens(state, limits) {
5967
+ if (limits.reservoir === void 0) {
5968
+ return;
5969
+ }
5970
+ const capacity = limits.reservoir;
5971
+ const refreshAmount = limits.reservoirRefreshAmount ?? limits.reservoir;
5972
+ const refreshInterval = limits.reservoirRefreshInterval ?? 6e4;
5973
+ const now = Date.now();
5974
+ const elapsed = now - state.lastRefillAt;
5975
+ if (elapsed >= refreshInterval) {
5976
+ const intervals = Math.floor(elapsed / refreshInterval);
5977
+ state.tokens = Math.min(capacity, state.tokens + intervals * refreshAmount);
5978
+ state.lastRefillAt = now;
5979
+ }
5980
+ }
5981
+ function canAcquire(state, limits) {
5982
+ if (state.running >= getMaxConcurrent(limits)) {
5983
+ return false;
5984
+ }
5985
+ refillTokens(state, limits);
5986
+ if (limits.reservoir !== void 0 && state.tokens <= 0) {
5987
+ return false;
5988
+ }
5989
+ const minTime = getMinTime(limits);
5990
+ if (minTime > 0 && state.lastStartAt > 0) {
5991
+ if (Date.now() - state.lastStartAt < minTime) {
5992
+ return false;
5993
+ }
5994
+ }
5995
+ return true;
5996
+ }
5997
+ var MemoryRateLimitBackend = class {
5998
+ constructor() {
5999
+ this.queues = /* @__PURE__ */ new Map();
6000
+ this.leases = /* @__PURE__ */ new Map();
6001
+ }
6002
+ getState(queueKey) {
6003
+ let state = this.queues.get(queueKey);
6004
+ if (!state) {
6005
+ state = {
6006
+ running: 0,
6007
+ waiters: [],
6008
+ lastStartAt: 0,
6009
+ tokens: Number.POSITIVE_INFINITY,
6010
+ lastRefillAt: Date.now()
6011
+ };
6012
+ if (queueKey.includes(":")) {
6013
+ }
6014
+ this.queues.set(queueKey, state);
6015
+ }
6016
+ return state;
6017
+ }
6018
+ grant(state, queueKey, limits) {
6019
+ if (limits.reservoir !== void 0) {
6020
+ state.tokens -= 1;
6021
+ }
6022
+ state.running += 1;
6023
+ state.lastStartAt = Date.now();
6024
+ const leaseId = generateLeaseId();
6025
+ this.leases.set(leaseId, { queueKey, limits });
6026
+ return { leaseId, acquiredAt: Date.now(), queueKey };
6027
+ }
6028
+ drainWaiters(queueKey, state) {
6029
+ let progressed = true;
6030
+ while (progressed && state.waiters.length > 0) {
6031
+ progressed = false;
6032
+ for (let i = 0; i < state.waiters.length; i += 1) {
6033
+ const waiter = state.waiters[i];
6034
+ if (!waiter || !canAcquire(state, waiter.limits)) {
6035
+ continue;
6036
+ }
6037
+ state.waiters.splice(i, 1);
6038
+ if (waiter.timer) {
6039
+ clearTimeout(waiter.timer);
6040
+ }
6041
+ waiter.resolve(this.grant(state, queueKey, waiter.limits));
6042
+ progressed = true;
6043
+ break;
6044
+ }
6045
+ }
6046
+ }
6047
+ async acquire(queueKey, limits, timeoutMs = 12e4) {
6048
+ const state = this.getState(queueKey);
6049
+ if (limits.reservoir !== void 0 && state.tokens === Number.POSITIVE_INFINITY) {
6050
+ state.tokens = limits.reservoir;
6051
+ }
6052
+ if (canAcquire(state, limits)) {
6053
+ return this.grant(state, queueKey, limits);
6054
+ }
6055
+ return new Promise((resolve4, reject) => {
6056
+ const waiter = {
6057
+ resolve: resolve4,
6058
+ reject,
6059
+ timer: null,
6060
+ limits
6061
+ };
6062
+ if (timeoutMs > 0) {
6063
+ waiter.timer = setTimeout(() => {
6064
+ const idx = state.waiters.indexOf(waiter);
6065
+ if (idx >= 0) {
6066
+ state.waiters.splice(idx, 1);
6067
+ }
6068
+ reject(
6069
+ new Error(`Queue slot acquire timed out after ${timeoutMs}ms for ${queueKey}`)
6070
+ );
6071
+ }, timeoutMs);
6072
+ }
6073
+ state.waiters.push(waiter);
6074
+ const retry = () => {
6075
+ if (!state.waiters.includes(waiter)) {
6076
+ return;
6077
+ }
6078
+ if (canAcquire(state, limits)) {
6079
+ const idx = state.waiters.indexOf(waiter);
6080
+ if (idx >= 0) {
6081
+ state.waiters.splice(idx, 1);
6082
+ }
6083
+ if (waiter.timer) {
6084
+ clearTimeout(waiter.timer);
6085
+ }
6086
+ resolve4(this.grant(state, queueKey, limits));
6087
+ return;
6088
+ }
6089
+ setTimeout(retry, Math.max(getMinTime(limits), 10));
6090
+ };
6091
+ setTimeout(retry, Math.max(getMinTime(limits), 10));
6092
+ });
6093
+ }
6094
+ async release(lease) {
6095
+ const tracked = this.leases.get(lease.leaseId);
6096
+ this.leases.delete(lease.leaseId);
6097
+ const queueKey = tracked?.queueKey ?? lease.queueKey;
6098
+ const state = this.queues.get(queueKey);
6099
+ if (!state) {
6100
+ return;
6101
+ }
6102
+ state.running = Math.max(0, state.running - 1);
6103
+ this.drainWaiters(queueKey, state);
6104
+ }
6105
+ };
6106
+ var memoryRateLimitBackend = new MemoryRateLimitBackend();
6107
+
6108
+ // src/ratelimit/backends/index.ts
6109
+ var cachedBackend = null;
6110
+ function shouldForceMemoryBackend() {
6111
+ const flag = process.env.SKEDYUL_RATE_LIMIT_MEMORY;
6112
+ return flag === "1" || flag === "true";
6113
+ }
6114
+ function getRateLimitBackend() {
6115
+ if (cachedBackend) {
6116
+ return cachedBackend;
6117
+ }
6118
+ if (shouldForceMemoryBackend()) {
6119
+ cachedBackend = memoryRateLimitBackend;
6120
+ return cachedBackend;
6121
+ }
6122
+ cachedBackend = createResilientBackend();
6123
+ return cachedBackend;
6124
+ }
6125
+ function createResilientBackend() {
6126
+ return {
6127
+ async acquire(queueKey, limits, timeoutMs) {
6128
+ try {
6129
+ return await platformRateLimitBackend.acquire(queueKey, limits, timeoutMs);
6130
+ } catch (error) {
6131
+ if (shouldFallbackToMemory(error)) {
6132
+ return memoryRateLimitBackend.acquire(queueKey, limits, timeoutMs);
6133
+ }
6134
+ throw error;
6135
+ }
6136
+ },
6137
+ async release(lease) {
6138
+ if (lease.leaseId.startsWith("mem_")) {
6139
+ return memoryRateLimitBackend.release(lease);
6140
+ }
6141
+ try {
6142
+ await platformRateLimitBackend.release(lease);
6143
+ } catch (error) {
6144
+ if (shouldFallbackToMemory(error)) {
6145
+ return memoryRateLimitBackend.release(lease);
6146
+ }
6147
+ throw error;
6148
+ }
6149
+ }
6150
+ };
6151
+ }
6152
+ function shouldFallbackToMemory(error) {
6153
+ if (shouldForceMemoryBackend()) {
6154
+ return true;
6155
+ }
6156
+ if (error instanceof RateLimitBackendError) {
6157
+ if (error.statusCode === 404 || error.statusCode === 503) {
6158
+ return true;
6159
+ }
6160
+ }
6161
+ if (error instanceof TypeError) {
6162
+ return true;
6163
+ }
6164
+ const nodeEnv = process.env.NODE_ENV;
6165
+ return nodeEnv === "development" || nodeEnv === "test";
6166
+ }
6167
+
6168
+ // src/ratelimit/should-retry.ts
6169
+ var DEFAULT_RETRY_STATUS_CODES = /* @__PURE__ */ new Set([429, 502, 503, 504]);
6170
+ function getErrorStatusCode(error) {
6171
+ if (typeof error !== "object" || error === null) {
6172
+ return void 0;
6173
+ }
6174
+ const record2 = error;
6175
+ if (typeof record2.statusCode === "number") {
6176
+ return record2.statusCode;
6177
+ }
6178
+ if (typeof record2.status === "number") {
6179
+ return record2.status;
6180
+ }
6181
+ return void 0;
6182
+ }
6183
+ function getErrorCode(error) {
6184
+ if (typeof error !== "object" || error === null) {
6185
+ return void 0;
6186
+ }
6187
+ const record2 = error;
6188
+ return typeof record2.code === "string" ? record2.code : void 0;
6189
+ }
6190
+ function defaultShouldRetry(error, _attempt) {
6191
+ const code = getErrorCode(error);
6192
+ if (code === "RATE_LIMITED" || code === "RATE_LIMIT_BACKEND_ERROR") {
6193
+ return true;
6194
+ }
6195
+ const status = getErrorStatusCode(error);
6196
+ if (status !== void 0 && DEFAULT_RETRY_STATUS_CODES.has(status)) {
6197
+ return true;
6198
+ }
6199
+ const message = error instanceof Error ? error.message : typeof error === "string" ? error : "";
6200
+ const lower = message.toLowerCase();
6201
+ if (lower.includes("rate limit") || lower.includes("too many requests") || lower.includes("econnreset") || lower.includes("etimedout")) {
6202
+ return true;
6203
+ }
6204
+ return false;
6205
+ }
6206
+ function sleep(ms) {
6207
+ return new Promise((resolve4) => setTimeout(resolve4, ms));
6208
+ }
6209
+
6210
+ // src/ratelimit/queued-fetch.ts
6211
+ function normalizeQueueInput(input) {
6212
+ if (typeof input === "string") {
6213
+ return { name: input };
6214
+ }
6215
+ return { name: input.queue, subKey: input.key };
6216
+ }
6217
+ function resolveQueue(queueInput, ctxOverride) {
6218
+ const ctx = ctxOverride ?? getRateLimitExecutionContext();
6219
+ if (!ctx?.app?.versionId) {
6220
+ throw new QueueContextError(
6221
+ "Cannot resolve queue without app context. Ensure queuedFetch runs inside a tool/hook handler."
6222
+ );
6223
+ }
6224
+ const { name, subKey } = normalizeQueueInput(queueInput);
6225
+ const config = getQueueConfigWithRetry(name);
6226
+ if (!config) {
6227
+ throw new QueueNotFoundError(name);
6228
+ }
6229
+ const queueKey = resolveQueueKey(name, config, ctx, subKey);
6230
+ return {
6231
+ name,
6232
+ queueKey,
6233
+ config,
6234
+ limits: toQueueLimits(config)
6235
+ };
6236
+ }
6237
+ function createQueueHandle(queueInput) {
6238
+ return {
6239
+ run(fn) {
6240
+ return queuedFetch(queueInput, fn);
6241
+ }
6242
+ };
6243
+ }
6244
+ async function queuedFetch(queueInput, fnOrPromise) {
6245
+ const fn = typeof fnOrPromise === "function" ? fnOrPromise : () => fnOrPromise;
6246
+ const resolved = resolveQueue(queueInput);
6247
+ const maxRetries = resolved.config.maxRetries ?? 0;
6248
+ const operation = {
6249
+ queueInput,
6250
+ fn,
6251
+ attempt: 0,
6252
+ resolved,
6253
+ lease: null
6254
+ };
6255
+ return runWithActiveQueuedOperation(
6256
+ operation,
6257
+ () => executeWithRetries(operation, maxRetries)
6258
+ );
6259
+ }
6260
+ async function executeWithRetries(operation, maxRetries) {
6261
+ const backend = getRateLimitBackend();
6262
+ const timeoutMs = operation.resolved.config.timeout ?? 12e4;
6263
+ const retryDelayMs = operation.resolved.config.retryDelayMs ?? 1e3;
6264
+ const shouldRetryFn = getQueueConfigWithRetry(operation.resolved.name)?.shouldRetry ?? defaultShouldRetry;
6265
+ const lease = await backend.acquire(
6266
+ operation.resolved.queueKey,
6267
+ operation.resolved.limits,
6268
+ timeoutMs
6269
+ );
6270
+ operation.lease = lease;
6271
+ setActiveQueuedOperationLease(lease);
6272
+ try {
6273
+ return await operation.fn();
6274
+ } catch (error) {
6275
+ await backend.release(lease);
6276
+ operation.lease = null;
6277
+ setActiveQueuedOperationLease(null);
6278
+ if (shouldRetryFn(error, operation.attempt) && operation.attempt < maxRetries) {
6279
+ await sleep(retryDelayMs);
6280
+ operation.attempt += 1;
6281
+ updateActiveQueuedOperationAttempt(operation.attempt);
6282
+ return executeWithRetries(operation, maxRetries);
6283
+ }
6284
+ if (shouldRetryFn(error, operation.attempt) && operation.attempt >= maxRetries) {
6285
+ throw new QueuedFetchExhaustedError(
6286
+ operation.attempt + 1,
6287
+ maxRetries,
6288
+ error
6289
+ );
6290
+ }
6291
+ throw error;
6292
+ } finally {
6293
+ if (operation.lease) {
6294
+ await backend.release(operation.lease);
6295
+ operation.lease = null;
6296
+ setActiveQueuedOperationLease(null);
6297
+ }
6298
+ }
6299
+ }
6300
+ async function requeue() {
6301
+ const operation = getActiveQueuedOperation();
6302
+ if (!operation) {
6303
+ throw new RequeueOutsideContextError();
6304
+ }
6305
+ const maxRetries = operation.resolved.config.maxRetries ?? 0;
6306
+ const nextAttempt = operation.attempt + 1;
6307
+ if (nextAttempt > maxRetries) {
6308
+ throw new QueuedFetchExhaustedError(nextAttempt, maxRetries, void 0);
6309
+ }
6310
+ if (operation.lease) {
6311
+ const backend = getRateLimitBackend();
6312
+ await backend.release(operation.lease);
6313
+ operation.lease = null;
6314
+ setActiveQueuedOperationLease(null);
6315
+ }
6316
+ operation.attempt = nextAttempt;
6317
+ updateActiveQueuedOperationAttempt(nextAttempt);
6318
+ const retryDelayMs = operation.resolved.config.retryDelayMs ?? 1e3;
6319
+ await sleep(retryDelayMs);
6320
+ return executeWithRetries(operation, maxRetries);
6321
+ }
6322
+ async function queuedFetchResponse(queueInput, url, init) {
6323
+ return queuedFetch(queueInput, () => fetch(url, init));
6324
+ }
6325
+
5663
6326
  // src/triggers/types.ts
5664
6327
  var import_v49 = require("zod/v4");
5665
6328
  var CRMDataSchema = import_v49.z.object({
@@ -5764,16 +6427,16 @@ function evaluateTemplate(template, context) {
5764
6427
  const templateRegex = /\{\{\s*([^}]+)\s*\}\}/g;
5765
6428
  const singleMatch = template.match(/^\{\{\s*([^}]+)\s*\}\}$/);
5766
6429
  if (singleMatch) {
5767
- const path5 = singleMatch[1].trim();
5768
- return resolvePath(context, path5);
6430
+ const path6 = singleMatch[1].trim();
6431
+ return resolvePath(context, path6);
5769
6432
  }
5770
- return template.replace(templateRegex, (_, path5) => {
5771
- const value = resolvePath(context, path5.trim());
6433
+ return template.replace(templateRegex, (_, path6) => {
6434
+ const value = resolvePath(context, path6.trim());
5772
6435
  return value === void 0 || value === null ? "" : String(value);
5773
6436
  });
5774
6437
  }
5775
- function resolvePath(obj, path5) {
5776
- const parts = path5.split(".");
6438
+ function resolvePath(obj, path6) {
6439
+ const parts = path6.split(".");
5777
6440
  let current = obj;
5778
6441
  for (const part of parts) {
5779
6442
  if (current === null || current === void 0) {
@@ -5794,14 +6457,14 @@ function evaluateCondition(condition, context) {
5794
6457
  const expression = match[1].trim();
5795
6458
  const eqMatch = expression.match(/^(.+?)\s*==\s*['"](.+)['"]$/);
5796
6459
  if (eqMatch) {
5797
- const [, path5, expectedValue] = eqMatch;
5798
- const actualValue = resolvePath(context, path5.trim());
6460
+ const [, path6, expectedValue] = eqMatch;
6461
+ const actualValue = resolvePath(context, path6.trim());
5799
6462
  return actualValue === expectedValue;
5800
6463
  }
5801
6464
  const neqMatch = expression.match(/^(.+?)\s*!=\s*['"](.+)['"]$/);
5802
6465
  if (neqMatch) {
5803
- const [, path5, expectedValue] = neqMatch;
5804
- const actualValue = resolvePath(context, path5.trim());
6466
+ const [, path6, expectedValue] = neqMatch;
6467
+ const actualValue = resolvePath(context, path6.trim());
5805
6468
  return actualValue !== expectedValue;
5806
6469
  }
5807
6470
  const value = resolvePath(context, expression);
@@ -6810,6 +7473,9 @@ function isTimeInWindowSlot(date, window) {
6810
7473
  const tzInfo = getTimezoneInfo(date, tz);
6811
7474
  return allowedDays.includes(tzInfo.day) && tzInfo.totalMinutes >= windowStartMinutes && tzInfo.totalMinutes < windowEndMinutes;
6812
7475
  }
7476
+ function getLocalDateKey(date, timezone) {
7477
+ return date.toLocaleDateString("en-CA", { timeZone: timezone });
7478
+ }
6813
7479
  function calculateWaitTime(step, now) {
6814
7480
  const nowTime = now.getTime();
6815
7481
  switch (step.mode) {
@@ -6878,7 +7544,7 @@ function calculateWaitTime(step, now) {
6878
7544
  }
6879
7545
  }
6880
7546
  let earliestScheduledTime = null;
6881
- let earliestWaitTime = Infinity;
7547
+ let earliestWaitFromNow = Infinity;
6882
7548
  for (const window of step.windows) {
6883
7549
  if (!window || window.startTime === void 0 || window.endTime === void 0) {
6884
7550
  continue;
@@ -6896,12 +7562,10 @@ function calculateWaitTime(step, now) {
6896
7562
  const currentHour = targetTzInfo.hour;
6897
7563
  const currentMinute = targetTzInfo.minute;
6898
7564
  const currentTotalMinutes = targetTzInfo.totalMinutes;
6899
- let windowWaitTime;
6900
- let windowScheduledTime;
7565
+ let msUntilWindowStart;
6901
7566
  if (allowedDays.includes(currentDay) && currentTotalMinutes < windowStartMinutes) {
6902
7567
  const minutesUntilWindow = windowStartMinutes - currentTotalMinutes;
6903
- windowWaitTime = minutesUntilWindow * 60 * 1e3;
6904
- windowScheduledTime = new Date(targetDate.getTime() + windowWaitTime);
7568
+ msUntilWindowStart = minutesUntilWindow * 60 * 1e3;
6905
7569
  } else {
6906
7570
  let daysToAdd = 7;
6907
7571
  for (let i = 1; i <= 7; i++) {
@@ -6917,17 +7581,20 @@ function calculateWaitTime(step, now) {
6917
7581
  const daysMs = daysToAdd * millisecondsPerDay;
6918
7582
  const hoursAdjustment = (windowStartHour - currentHour) * millisecondsPerHour;
6919
7583
  const minutesAdjustment = (windowStartMinute - currentMinute) * millisecondsPerMinute;
6920
- windowWaitTime = daysMs + hoursAdjustment + minutesAdjustment;
6921
- windowScheduledTime = new Date(targetDate.getTime() + windowWaitTime);
7584
+ msUntilWindowStart = daysMs + hoursAdjustment + minutesAdjustment;
6922
7585
  }
6923
- if (windowWaitTime < earliestWaitTime) {
6924
- earliestWaitTime = windowWaitTime;
7586
+ const windowStartTimeMs = targetDate.getTime() + msUntilWindowStart;
7587
+ const sameLocalDayAsNow = getLocalDateKey(now, tz) === getLocalDateKey(targetDate, tz);
7588
+ const windowScheduledTime = sameLocalDayAsNow ? new Date(windowStartTimeMs + relativeDelay) : new Date(windowStartTimeMs);
7589
+ const waitFromNow = windowScheduledTime.getTime() - nowTime;
7590
+ if (waitFromNow < earliestWaitFromNow) {
7591
+ earliestWaitFromNow = waitFromNow;
6925
7592
  earliestScheduledTime = windowScheduledTime;
6926
7593
  }
6927
7594
  }
6928
7595
  if (earliestScheduledTime) {
6929
7596
  return {
6930
- waitTime: relativeDelay + earliestWaitTime,
7597
+ waitTime: Math.max(0, earliestScheduledTime.getTime() - nowTime),
6931
7598
  scheduledAt: earliestScheduledTime
6932
7599
  };
6933
7600
  }
@@ -7166,10 +7833,15 @@ var index_default = { z: import_v413.z };
7166
7833
  ParticipantEventPayloadSchema,
7167
7834
  ParticipantKindSchema,
7168
7835
  ProvisionConfigSchema,
7836
+ QueueContextError,
7837
+ QueueNotFoundError,
7838
+ QueuedFetchExhaustedError,
7839
+ RateLimitBackendError,
7169
7840
  RelationshipCardinalitySchema,
7170
7841
  RelationshipDefinitionSchema,
7171
7842
  RelationshipExtensionSchema,
7172
7843
  RelationshipLinkSchema,
7844
+ RequeueOutsideContextError,
7173
7845
  ResolvedSkillSchema,
7174
7846
  ResolvedTriggerSchema,
7175
7847
  ResourceDependencySchema,
@@ -7247,6 +7919,7 @@ var index_default = { z: import_v413.z };
7247
7919
  createListResponse,
7248
7920
  createNotFoundError,
7249
7921
  createPermissionError,
7922
+ createQueueHandle,
7250
7923
  createRateLimitError,
7251
7924
  createServerHookContext,
7252
7925
  createSuccessResponse,
@@ -7256,6 +7929,7 @@ var index_default = { z: import_v413.z };
7256
7929
  createWebhookContext,
7257
7930
  createWorkflowStepContext,
7258
7931
  cron,
7932
+ defaultShouldRetry,
7259
7933
  defineAgent,
7260
7934
  defineChannel,
7261
7935
  defineConfig,
@@ -7278,6 +7952,7 @@ var index_default = { z: import_v413.z };
7278
7952
  getConfig,
7279
7953
  getContextByHandle,
7280
7954
  getContextByModel,
7955
+ getRateLimitExecutionContext,
7281
7956
  getRequiredInstallEnvKeys,
7282
7957
  getRetryDelay,
7283
7958
  instance,
@@ -7297,10 +7972,16 @@ var index_default = { z: import_v413.z };
7297
7972
  loadConfig,
7298
7973
  matchesTrigger,
7299
7974
  parseCRMSchema,
7975
+ queuedFetch,
7976
+ queuedFetchResponse,
7977
+ registerQueueConfig,
7300
7978
  report,
7979
+ requeue,
7301
7980
  resolveInputMappings,
7981
+ resolveQueue,
7302
7982
  resource,
7303
7983
  runWithConfig,
7984
+ runWithRateLimitExecutionContext,
7304
7985
  safeParseCRMSchema,
7305
7986
  safeParseConfig,
7306
7987
  server,