skedyul 1.4.5 → 1.4.7
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/cli/index.js +81 -16
- package/dist/config/types/app-event.d.ts +24 -0
- package/dist/dedicated/server.js +37 -2
- package/dist/esm/index.mjs +147 -64
- package/dist/events/types.d.ts +11 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +148 -64
- package/dist/ratelimit/errors.d.ts +6 -0
- package/dist/ratelimit/index.d.ts +1 -1
- package/dist/schemas/agent-schema-v3.d.ts +4 -0
- package/dist/schemas/agent-schema-v3.js +3 -1
- package/dist/schemas/agent-schema-v3.mjs +3 -1
- package/dist/server.js +37 -2
- package/dist/serverless/server.mjs +37 -2
- package/dist/triggers/types.d.ts +3 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/tool.d.ts +21 -2
- package/dist/workflows/types.d.ts +8 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ declare const _default: {
|
|
|
15
15
|
};
|
|
16
16
|
export default _default;
|
|
17
17
|
export { defineConfig, defineModel, defineChannel, definePage, defineWorkflow, defineAgent, defineEnv, defineNavigation, loadConfig, validateConfig, CONFIG_FILE_NAMES, getAllEnvKeys, getRequiredInstallEnvKeys, } from './config';
|
|
18
|
-
export { queuedFetch, requeue, resolveQueue, createQueueHandle, queuedFetchResponse, registerQueueConfig, runWithRateLimitExecutionContext, getRateLimitExecutionContext, defaultShouldRetry, QueueContextError, QueueNotFoundError, QueuedFetchExhaustedError, RequeueOutsideContextError, RateLimitBackendError, } from './ratelimit';
|
|
18
|
+
export { queuedFetch, requeue, resolveQueue, createQueueHandle, queuedFetchResponse, registerQueueConfig, runWithRateLimitExecutionContext, getRateLimitExecutionContext, defaultShouldRetry, QueueContextError, QueueNotFoundError, QueuedFetchExhaustedError, RequeueOutsideContextError, RateLimitBackendError, RateLimitExceededError, } from './ratelimit';
|
|
19
19
|
export type { QueueInput, QueueSelector, Lease, QueueLimits, ResolvedQueue, RateLimitExecutionContext, RateLimitBackend, QueueScope, QueueConfig, SerializableQueueConfig, QueueRegistry, } from './ratelimit';
|
|
20
20
|
export { defineSchema, validateCRMSchema, parseCRMSchema, safeParseCRMSchema, } from './schemas';
|
|
21
21
|
export { ThreadEventTypeSchema, CustomEventTypeSchema, EventTypeSchema, ParticipantKindSchema, BaseEventPayloadSchema, MessageEventPayloadSchema, ParticipantEventPayloadSchema, ContextChangedPayloadSchema, StatusChangedPayloadSchema, ScheduledEventPayloadSchema, AgentWorkflowEventPayloadSchema, CustomEventPayloadSchema, ThreadEventPayloadSchema, ThreadEventSchema, CreateThreadEventInputSchema, EventSubscriptionSchema, EventWaitSchema, EventsConfigSchema, } from './events';
|
package/dist/index.js
CHANGED
|
@@ -174,6 +174,7 @@ __export(index_exports, {
|
|
|
174
174
|
QueueNotFoundError: () => QueueNotFoundError,
|
|
175
175
|
QueuedFetchExhaustedError: () => QueuedFetchExhaustedError,
|
|
176
176
|
RateLimitBackendError: () => RateLimitBackendError,
|
|
177
|
+
RateLimitExceededError: () => RateLimitExceededError,
|
|
177
178
|
RelationshipCardinalitySchema: () => RelationshipCardinalitySchema,
|
|
178
179
|
RelationshipDefinitionSchema: () => RelationshipDefinitionSchema,
|
|
179
180
|
RelationshipExtensionSchema: () => RelationshipExtensionSchema,
|
|
@@ -718,7 +719,9 @@ var ThreadEventTypeSchema = import_v43.z.enum([
|
|
|
718
719
|
"thread.workflow.completed",
|
|
719
720
|
// Scheduled events
|
|
720
721
|
"thread.follow_up.due",
|
|
721
|
-
"thread.reminder.due"
|
|
722
|
+
"thread.reminder.due",
|
|
723
|
+
// Signal events
|
|
724
|
+
"thread.signal.created"
|
|
722
725
|
]);
|
|
723
726
|
var CustomEventTypeSchema = import_v43.z.string().regex(/^custom\.[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)*$/, {
|
|
724
727
|
message: "Custom event type must match pattern: custom.{namespace}.{event}"
|
|
@@ -3696,6 +3699,57 @@ var AppAuthInvalidError = class extends Error {
|
|
|
3696
3699
|
}
|
|
3697
3700
|
};
|
|
3698
3701
|
|
|
3702
|
+
// src/ratelimit/errors.ts
|
|
3703
|
+
var QueueContextError = class extends Error {
|
|
3704
|
+
constructor(message) {
|
|
3705
|
+
super(message);
|
|
3706
|
+
this.code = "QUEUE_CONTEXT_ERROR";
|
|
3707
|
+
this.name = "QueueContextError";
|
|
3708
|
+
}
|
|
3709
|
+
};
|
|
3710
|
+
var QueueNotFoundError = class extends Error {
|
|
3711
|
+
constructor(queueName) {
|
|
3712
|
+
super(`Queue "${queueName}" is not defined in skedyul.config queues`);
|
|
3713
|
+
this.code = "QUEUE_NOT_FOUND";
|
|
3714
|
+
this.name = "QueueNotFoundError";
|
|
3715
|
+
}
|
|
3716
|
+
};
|
|
3717
|
+
var QueuedFetchExhaustedError = class extends Error {
|
|
3718
|
+
constructor(attempts, maxRetries, causeError) {
|
|
3719
|
+
super(
|
|
3720
|
+
`queuedFetch exhausted retries after ${attempts} attempts (maxRetries=${maxRetries})`
|
|
3721
|
+
);
|
|
3722
|
+
this.code = "QUEUED_FETCH_EXHAUSTED";
|
|
3723
|
+
this.name = "QueuedFetchExhaustedError";
|
|
3724
|
+
this.attempts = attempts;
|
|
3725
|
+
this.maxRetries = maxRetries;
|
|
3726
|
+
this.causeError = causeError;
|
|
3727
|
+
}
|
|
3728
|
+
};
|
|
3729
|
+
var RequeueOutsideContextError = class extends Error {
|
|
3730
|
+
constructor() {
|
|
3731
|
+
super("requeue() can only be called inside an active queuedFetch operation");
|
|
3732
|
+
this.code = "REQUEUE_OUTSIDE_CONTEXT";
|
|
3733
|
+
this.name = "RequeueOutsideContextError";
|
|
3734
|
+
}
|
|
3735
|
+
};
|
|
3736
|
+
var RateLimitBackendError = class extends Error {
|
|
3737
|
+
constructor(message, statusCode) {
|
|
3738
|
+
super(message);
|
|
3739
|
+
this.code = "RATE_LIMIT_BACKEND_ERROR";
|
|
3740
|
+
this.name = "RateLimitBackendError";
|
|
3741
|
+
this.statusCode = statusCode;
|
|
3742
|
+
}
|
|
3743
|
+
};
|
|
3744
|
+
var RateLimitExceededError = class extends Error {
|
|
3745
|
+
constructor(retryAfterMs, message = "Rate limit exceeded. Please try again later.") {
|
|
3746
|
+
super(message);
|
|
3747
|
+
this.code = "RATE_LIMITED";
|
|
3748
|
+
this.name = "RateLimitExceededError";
|
|
3749
|
+
this.retryAfterMs = retryAfterMs;
|
|
3750
|
+
}
|
|
3751
|
+
};
|
|
3752
|
+
|
|
3699
3753
|
// src/server/context-logger.ts
|
|
3700
3754
|
var import_async_hooks3 = require("async_hooks");
|
|
3701
3755
|
var logContextStorage = new import_async_hooks3.AsyncLocalStorage();
|
|
@@ -3793,6 +3847,7 @@ function buildToolMetadata(registry) {
|
|
|
3793
3847
|
const rawRetries = tool.retries ?? toolConfig.retries;
|
|
3794
3848
|
const timeout = typeof rawTimeout === "number" && rawTimeout > 0 ? rawTimeout : 1e4;
|
|
3795
3849
|
const retries = typeof rawRetries === "number" && rawRetries >= 1 ? rawRetries : 1;
|
|
3850
|
+
const queueTouchPoints = tool.queueTouchPoints ?? toolConfig.queueTouchPoints;
|
|
3796
3851
|
return {
|
|
3797
3852
|
name: tool.name,
|
|
3798
3853
|
displayName: tool.label || tool.name,
|
|
@@ -3802,10 +3857,12 @@ function buildToolMetadata(registry) {
|
|
|
3802
3857
|
// Include timeout/retries at top-level for tools/list response (used by syncExecutableTools)
|
|
3803
3858
|
timeout,
|
|
3804
3859
|
retries,
|
|
3860
|
+
queueTouchPoints,
|
|
3805
3861
|
config: {
|
|
3806
3862
|
timeout,
|
|
3807
3863
|
retries,
|
|
3808
|
-
completionHints: toolConfig.completionHints
|
|
3864
|
+
completionHints: toolConfig.completionHints,
|
|
3865
|
+
queueTouchPoints
|
|
3809
3866
|
}
|
|
3810
3867
|
};
|
|
3811
3868
|
});
|
|
@@ -3948,6 +4005,27 @@ function createCallToolHandler(registry, state, onMaxRequests) {
|
|
|
3948
4005
|
cursor: functionResult.cursor
|
|
3949
4006
|
};
|
|
3950
4007
|
} catch (error) {
|
|
4008
|
+
if (error instanceof RateLimitExceededError) {
|
|
4009
|
+
return {
|
|
4010
|
+
success: false,
|
|
4011
|
+
output: null,
|
|
4012
|
+
billing: { credits: 0 },
|
|
4013
|
+
meta: {
|
|
4014
|
+
success: false,
|
|
4015
|
+
message: error.message,
|
|
4016
|
+
toolName
|
|
4017
|
+
},
|
|
4018
|
+
error: {
|
|
4019
|
+
code: "RATE_LIMITED",
|
|
4020
|
+
message: error.message,
|
|
4021
|
+
category: "external"
|
|
4022
|
+
},
|
|
4023
|
+
retry: {
|
|
4024
|
+
allowed: true,
|
|
4025
|
+
afterMs: error.retryAfterMs
|
|
4026
|
+
}
|
|
4027
|
+
};
|
|
4028
|
+
}
|
|
3951
4029
|
if (error instanceof AppAuthInvalidError) {
|
|
3952
4030
|
return {
|
|
3953
4031
|
output: null,
|
|
@@ -4311,7 +4389,8 @@ function serializeConfig(config) {
|
|
|
4311
4389
|
description: tool.description,
|
|
4312
4390
|
// Read timeout/retries from top-level first, then fallback to config
|
|
4313
4391
|
timeout: tool.timeout ?? tool.config?.timeout,
|
|
4314
|
-
retries: tool.retries ?? tool.config?.retries
|
|
4392
|
+
retries: tool.retries ?? tool.config?.retries,
|
|
4393
|
+
queueTouchPoints: tool.queueTouchPoints ?? tool.config?.queueTouchPoints
|
|
4315
4394
|
})) : [],
|
|
4316
4395
|
webhooks: webhookRegistry ? Object.values(webhookRegistry).map((w) => ({
|
|
4317
4396
|
name: w.name,
|
|
@@ -5733,17 +5812,37 @@ var CONFIG_FILE_NAMES = [
|
|
|
5733
5812
|
"skedyul.config.mjs",
|
|
5734
5813
|
"skedyul.config.cjs"
|
|
5735
5814
|
];
|
|
5815
|
+
function loadTypeScriptConfigModule(absolutePath) {
|
|
5816
|
+
try {
|
|
5817
|
+
require("tsx/cjs");
|
|
5818
|
+
delete require.cache[absolutePath];
|
|
5819
|
+
const module2 = require(absolutePath);
|
|
5820
|
+
return module2.default ?? module2;
|
|
5821
|
+
} catch (error) {
|
|
5822
|
+
throw new Error(
|
|
5823
|
+
`Cannot load TypeScript config: ${absolutePath}: ${error instanceof Error ? error.message : String(error)}`
|
|
5824
|
+
);
|
|
5825
|
+
}
|
|
5826
|
+
}
|
|
5736
5827
|
async function transpileTypeScript(filePath) {
|
|
5737
5828
|
const content = fs3.readFileSync(filePath, "utf-8");
|
|
5738
5829
|
const configDir = path3.dirname(path3.resolve(filePath));
|
|
5739
5830
|
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*$/, "}");
|
|
5740
5831
|
transpiled = transpiled.replace(
|
|
5741
5832
|
/import\s+(\w+)\s+from\s+['"](\.[^'"]+)['"]\s*(?:with\s*\{[^}]*\})?/g,
|
|
5742
|
-
(
|
|
5833
|
+
(_match, varName, relativePath) => {
|
|
5743
5834
|
const absolutePath = path3.resolve(configDir, relativePath);
|
|
5744
5835
|
return `const ${varName} = require('${absolutePath.replace(/\\/g, "/")}')`;
|
|
5745
5836
|
}
|
|
5746
5837
|
);
|
|
5838
|
+
transpiled = transpiled.replace(
|
|
5839
|
+
/import\s+\{\s*([^}]+)\s*\}\s+from\s+['"](\.[^'"]+)['"]\s*;?\n?/g,
|
|
5840
|
+
(_match, namedImports, relativePath) => {
|
|
5841
|
+
const absolutePath = path3.resolve(configDir, relativePath);
|
|
5842
|
+
return `const { ${namedImports.trim()} } = require('${absolutePath.replace(/\\/g, "/")}')
|
|
5843
|
+
`;
|
|
5844
|
+
}
|
|
5845
|
+
);
|
|
5747
5846
|
transpiled = transpiled.replace(/import\s*\(\s*['"][^'"]+['"]\s*\)/g, "null");
|
|
5748
5847
|
return transpiled;
|
|
5749
5848
|
}
|
|
@@ -5754,16 +5853,9 @@ async function loadConfig(configPath) {
|
|
|
5754
5853
|
}
|
|
5755
5854
|
const isTypeScript = absolutePath.endsWith(".ts");
|
|
5756
5855
|
try {
|
|
5757
|
-
let moduleToLoad = absolutePath;
|
|
5758
5856
|
if (isTypeScript) {
|
|
5759
|
-
const transpiled = await transpileTypeScript(absolutePath);
|
|
5760
|
-
const tempDir = os.tmpdir();
|
|
5761
|
-
const tempFile = path3.join(tempDir, `skedyul-config-${Date.now()}.cjs`);
|
|
5762
|
-
fs3.writeFileSync(tempFile, transpiled);
|
|
5763
|
-
moduleToLoad = tempFile;
|
|
5764
5857
|
try {
|
|
5765
|
-
const
|
|
5766
|
-
const config2 = module3.default || module3;
|
|
5858
|
+
const config2 = loadTypeScriptConfigModule(absolutePath);
|
|
5767
5859
|
if (!config2 || typeof config2 !== "object") {
|
|
5768
5860
|
throw new Error("Config file must export a configuration object");
|
|
5769
5861
|
}
|
|
@@ -5771,16 +5863,31 @@ async function loadConfig(configPath) {
|
|
|
5771
5863
|
throw new Error('Config must have a "name" property');
|
|
5772
5864
|
}
|
|
5773
5865
|
return config2;
|
|
5774
|
-
}
|
|
5866
|
+
} catch (tsxError) {
|
|
5867
|
+
const transpiled = await transpileTypeScript(absolutePath);
|
|
5868
|
+
const tempFile = path3.join(os.tmpdir(), `skedyul-config-${Date.now()}.cjs`);
|
|
5869
|
+
fs3.writeFileSync(tempFile, transpiled);
|
|
5775
5870
|
try {
|
|
5776
|
-
|
|
5777
|
-
|
|
5871
|
+
const module3 = require(tempFile);
|
|
5872
|
+
const config2 = module3.default || module3;
|
|
5873
|
+
if (!config2 || typeof config2 !== "object") {
|
|
5874
|
+
throw new Error("Config file must export a configuration object");
|
|
5875
|
+
}
|
|
5876
|
+
if (!config2.name || typeof config2.name !== "string") {
|
|
5877
|
+
throw new Error('Config must have a "name" property');
|
|
5878
|
+
}
|
|
5879
|
+
return config2;
|
|
5880
|
+
} finally {
|
|
5881
|
+
try {
|
|
5882
|
+
fs3.unlinkSync(tempFile);
|
|
5883
|
+
} catch {
|
|
5884
|
+
}
|
|
5778
5885
|
}
|
|
5779
5886
|
}
|
|
5780
5887
|
}
|
|
5781
5888
|
const module2 = await import(
|
|
5782
5889
|
/* webpackIgnore: true */
|
|
5783
|
-
|
|
5890
|
+
absolutePath
|
|
5784
5891
|
);
|
|
5785
5892
|
const config = module2.default || module2;
|
|
5786
5893
|
if (!config || typeof config !== "object") {
|
|
@@ -5831,49 +5938,6 @@ function getRequiredInstallEnvKeys(config) {
|
|
|
5831
5938
|
return Object.entries(provision.env).filter(([, def]) => def.required).map(([key]) => key);
|
|
5832
5939
|
}
|
|
5833
5940
|
|
|
5834
|
-
// src/ratelimit/errors.ts
|
|
5835
|
-
var QueueContextError = class extends Error {
|
|
5836
|
-
constructor(message) {
|
|
5837
|
-
super(message);
|
|
5838
|
-
this.code = "QUEUE_CONTEXT_ERROR";
|
|
5839
|
-
this.name = "QueueContextError";
|
|
5840
|
-
}
|
|
5841
|
-
};
|
|
5842
|
-
var QueueNotFoundError = class extends Error {
|
|
5843
|
-
constructor(queueName) {
|
|
5844
|
-
super(`Queue "${queueName}" is not defined in skedyul.config queues`);
|
|
5845
|
-
this.code = "QUEUE_NOT_FOUND";
|
|
5846
|
-
this.name = "QueueNotFoundError";
|
|
5847
|
-
}
|
|
5848
|
-
};
|
|
5849
|
-
var QueuedFetchExhaustedError = class extends Error {
|
|
5850
|
-
constructor(attempts, maxRetries, causeError) {
|
|
5851
|
-
super(
|
|
5852
|
-
`queuedFetch exhausted retries after ${attempts} attempts (maxRetries=${maxRetries})`
|
|
5853
|
-
);
|
|
5854
|
-
this.code = "QUEUED_FETCH_EXHAUSTED";
|
|
5855
|
-
this.name = "QueuedFetchExhaustedError";
|
|
5856
|
-
this.attempts = attempts;
|
|
5857
|
-
this.maxRetries = maxRetries;
|
|
5858
|
-
this.causeError = causeError;
|
|
5859
|
-
}
|
|
5860
|
-
};
|
|
5861
|
-
var RequeueOutsideContextError = class extends Error {
|
|
5862
|
-
constructor() {
|
|
5863
|
-
super("requeue() can only be called inside an active queuedFetch operation");
|
|
5864
|
-
this.code = "REQUEUE_OUTSIDE_CONTEXT";
|
|
5865
|
-
this.name = "RequeueOutsideContextError";
|
|
5866
|
-
}
|
|
5867
|
-
};
|
|
5868
|
-
var RateLimitBackendError = class extends Error {
|
|
5869
|
-
constructor(message, statusCode) {
|
|
5870
|
-
super(message);
|
|
5871
|
-
this.code = "RATE_LIMIT_BACKEND_ERROR";
|
|
5872
|
-
this.name = "RateLimitBackendError";
|
|
5873
|
-
this.statusCode = statusCode;
|
|
5874
|
-
}
|
|
5875
|
-
};
|
|
5876
|
-
|
|
5877
5941
|
// src/ratelimit/resolve-queue-key.ts
|
|
5878
5942
|
function resolveEndpointHandle(config, invocation) {
|
|
5879
5943
|
if (config.endpoint) {
|
|
@@ -6317,11 +6381,30 @@ async function executeWithRetries(operation, maxRetries) {
|
|
|
6317
6381
|
const timeoutMs = operation.resolved.config.timeout ?? 12e4;
|
|
6318
6382
|
const retryDelayMs = operation.resolved.config.retryDelayMs ?? 1e3;
|
|
6319
6383
|
const shouldRetryFn = getQueueConfigWithRetry(operation.resolved.name)?.shouldRetry ?? defaultShouldRetry;
|
|
6320
|
-
|
|
6321
|
-
|
|
6322
|
-
|
|
6323
|
-
|
|
6324
|
-
|
|
6384
|
+
let lease;
|
|
6385
|
+
try {
|
|
6386
|
+
lease = await backend.acquire(
|
|
6387
|
+
operation.resolved.queueKey,
|
|
6388
|
+
operation.resolved.limits,
|
|
6389
|
+
timeoutMs
|
|
6390
|
+
);
|
|
6391
|
+
} catch (acquireError) {
|
|
6392
|
+
if (acquireError instanceof RateLimitBackendError && acquireError.statusCode === 408) {
|
|
6393
|
+
const retryAfterMs = Math.max(
|
|
6394
|
+
operation.resolved.limits.minTime ?? 1e3,
|
|
6395
|
+
operation.resolved.config.retryDelayMs ?? 1e3
|
|
6396
|
+
);
|
|
6397
|
+
throw new RateLimitExceededError(retryAfterMs);
|
|
6398
|
+
}
|
|
6399
|
+
if (acquireError instanceof Error && acquireError.message.includes("timed out")) {
|
|
6400
|
+
const retryAfterMs = Math.max(
|
|
6401
|
+
operation.resolved.limits.minTime ?? 1e3,
|
|
6402
|
+
operation.resolved.config.retryDelayMs ?? 1e3
|
|
6403
|
+
);
|
|
6404
|
+
throw new RateLimitExceededError(retryAfterMs);
|
|
6405
|
+
}
|
|
6406
|
+
throw acquireError;
|
|
6407
|
+
}
|
|
6325
6408
|
operation.lease = lease;
|
|
6326
6409
|
setActiveQueuedOperationLease(lease);
|
|
6327
6410
|
try {
|
|
@@ -7893,6 +7976,7 @@ var index_default = { z: import_v413.z };
|
|
|
7893
7976
|
QueueNotFoundError,
|
|
7894
7977
|
QueuedFetchExhaustedError,
|
|
7895
7978
|
RateLimitBackendError,
|
|
7979
|
+
RateLimitExceededError,
|
|
7896
7980
|
RelationshipCardinalitySchema,
|
|
7897
7981
|
RelationshipDefinitionSchema,
|
|
7898
7982
|
RelationshipExtensionSchema,
|
|
@@ -25,3 +25,9 @@ export declare class RateLimitBackendError extends Error {
|
|
|
25
25
|
readonly statusCode?: number;
|
|
26
26
|
constructor(message: string, statusCode?: number);
|
|
27
27
|
}
|
|
28
|
+
/** Thrown when queuedFetch cannot acquire a rate-limit slot within the queue timeout. */
|
|
29
|
+
export declare class RateLimitExceededError extends Error {
|
|
30
|
+
readonly code = "RATE_LIMITED";
|
|
31
|
+
readonly retryAfterMs: number;
|
|
32
|
+
constructor(retryAfterMs: number, message?: string);
|
|
33
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { queuedFetch, requeue, resolveQueue, createQueueHandle, queuedFetchResponse, } from './queued-fetch';
|
|
2
2
|
export type { QueueInput, QueueSelector, Lease, QueueLimits, ResolvedQueue, RateLimitExecutionContext, RateLimitBackend, } from './types';
|
|
3
|
-
export { QueueContextError, QueueNotFoundError, QueuedFetchExhaustedError, RequeueOutsideContextError, RateLimitBackendError, } from './errors';
|
|
3
|
+
export { QueueContextError, QueueNotFoundError, QueuedFetchExhaustedError, RequeueOutsideContextError, RateLimitBackendError, RateLimitExceededError, } from './errors';
|
|
4
4
|
export { registerQueueConfig, clearRegisteredQueueConfig, getQueueDefinitions, getQueueConfig, } from './config-loader';
|
|
5
5
|
export { runWithRateLimitExecutionContext, getRateLimitExecutionContext, } from './context';
|
|
6
6
|
export { resolveQueueKey, toQueueLimits } from './resolve-queue-key';
|
|
@@ -539,6 +539,7 @@ export declare const AgentYAMLV3Schema: z.ZodObject<{
|
|
|
539
539
|
"thread.workflow.completed": "thread.workflow.completed";
|
|
540
540
|
"thread.follow_up.due": "thread.follow_up.due";
|
|
541
541
|
"thread.reminder.due": "thread.reminder.due";
|
|
542
|
+
"thread.signal.created": "thread.signal.created";
|
|
542
543
|
}>, z.ZodString]>>>;
|
|
543
544
|
condition: z.ZodOptional<z.ZodString>;
|
|
544
545
|
emits: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodEnum<{
|
|
@@ -555,6 +556,7 @@ export declare const AgentYAMLV3Schema: z.ZodObject<{
|
|
|
555
556
|
"thread.workflow.completed": "thread.workflow.completed";
|
|
556
557
|
"thread.follow_up.due": "thread.follow_up.due";
|
|
557
558
|
"thread.reminder.due": "thread.reminder.due";
|
|
559
|
+
"thread.signal.created": "thread.signal.created";
|
|
558
560
|
}>, z.ZodString]>>>;
|
|
559
561
|
waits: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
560
562
|
event: z.ZodUnion<readonly [z.ZodEnum<{
|
|
@@ -571,6 +573,7 @@ export declare const AgentYAMLV3Schema: z.ZodObject<{
|
|
|
571
573
|
"thread.workflow.completed": "thread.workflow.completed";
|
|
572
574
|
"thread.follow_up.due": "thread.follow_up.due";
|
|
573
575
|
"thread.reminder.due": "thread.reminder.due";
|
|
576
|
+
"thread.signal.created": "thread.signal.created";
|
|
574
577
|
}>, z.ZodString]>;
|
|
575
578
|
timeout: z.ZodOptional<z.ZodString>;
|
|
576
579
|
onTimeout: z.ZodOptional<z.ZodString>;
|
|
@@ -589,6 +592,7 @@ export declare const AgentYAMLV3Schema: z.ZodObject<{
|
|
|
589
592
|
"thread.workflow.completed": "thread.workflow.completed";
|
|
590
593
|
"thread.follow_up.due": "thread.follow_up.due";
|
|
591
594
|
"thread.reminder.due": "thread.reminder.due";
|
|
595
|
+
"thread.signal.created": "thread.signal.created";
|
|
592
596
|
}>, z.ZodString]>>>;
|
|
593
597
|
cancelCondition: z.ZodOptional<z.ZodString>;
|
|
594
598
|
}, z.core.$strip>>;
|
|
@@ -76,7 +76,9 @@ var ThreadEventTypeSchema = import_v4.z.enum([
|
|
|
76
76
|
"thread.workflow.completed",
|
|
77
77
|
// Scheduled events
|
|
78
78
|
"thread.follow_up.due",
|
|
79
|
-
"thread.reminder.due"
|
|
79
|
+
"thread.reminder.due",
|
|
80
|
+
// Signal events
|
|
81
|
+
"thread.signal.created"
|
|
80
82
|
]);
|
|
81
83
|
var CustomEventTypeSchema = import_v4.z.string().regex(/^custom\.[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)*$/, {
|
|
82
84
|
message: "Custom event type must match pattern: custom.{namespace}.{event}"
|
|
@@ -23,7 +23,9 @@ var ThreadEventTypeSchema = z.enum([
|
|
|
23
23
|
"thread.workflow.completed",
|
|
24
24
|
// Scheduled events
|
|
25
25
|
"thread.follow_up.due",
|
|
26
|
-
"thread.reminder.due"
|
|
26
|
+
"thread.reminder.due",
|
|
27
|
+
// Signal events
|
|
28
|
+
"thread.signal.created"
|
|
27
29
|
]);
|
|
28
30
|
var CustomEventTypeSchema = z.string().regex(/^custom\.[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)*$/, {
|
|
29
31
|
message: "Custom event type must match pattern: custom.{namespace}.{event}"
|
package/dist/server.js
CHANGED
|
@@ -307,6 +307,16 @@ var AppAuthInvalidError = class extends Error {
|
|
|
307
307
|
}
|
|
308
308
|
};
|
|
309
309
|
|
|
310
|
+
// src/ratelimit/errors.ts
|
|
311
|
+
var RateLimitExceededError = class extends Error {
|
|
312
|
+
constructor(retryAfterMs, message = "Rate limit exceeded. Please try again later.") {
|
|
313
|
+
super(message);
|
|
314
|
+
this.code = "RATE_LIMITED";
|
|
315
|
+
this.name = "RateLimitExceededError";
|
|
316
|
+
this.retryAfterMs = retryAfterMs;
|
|
317
|
+
}
|
|
318
|
+
};
|
|
319
|
+
|
|
310
320
|
// src/server/context-logger.ts
|
|
311
321
|
var import_async_hooks3 = require("async_hooks");
|
|
312
322
|
var logContextStorage = new import_async_hooks3.AsyncLocalStorage();
|
|
@@ -404,6 +414,7 @@ function buildToolMetadata(registry) {
|
|
|
404
414
|
const rawRetries = tool.retries ?? toolConfig.retries;
|
|
405
415
|
const timeout = typeof rawTimeout === "number" && rawTimeout > 0 ? rawTimeout : 1e4;
|
|
406
416
|
const retries = typeof rawRetries === "number" && rawRetries >= 1 ? rawRetries : 1;
|
|
417
|
+
const queueTouchPoints = tool.queueTouchPoints ?? toolConfig.queueTouchPoints;
|
|
407
418
|
return {
|
|
408
419
|
name: tool.name,
|
|
409
420
|
displayName: tool.label || tool.name,
|
|
@@ -413,10 +424,12 @@ function buildToolMetadata(registry) {
|
|
|
413
424
|
// Include timeout/retries at top-level for tools/list response (used by syncExecutableTools)
|
|
414
425
|
timeout,
|
|
415
426
|
retries,
|
|
427
|
+
queueTouchPoints,
|
|
416
428
|
config: {
|
|
417
429
|
timeout,
|
|
418
430
|
retries,
|
|
419
|
-
completionHints: toolConfig.completionHints
|
|
431
|
+
completionHints: toolConfig.completionHints,
|
|
432
|
+
queueTouchPoints
|
|
420
433
|
}
|
|
421
434
|
};
|
|
422
435
|
});
|
|
@@ -559,6 +572,27 @@ function createCallToolHandler(registry, state, onMaxRequests) {
|
|
|
559
572
|
cursor: functionResult.cursor
|
|
560
573
|
};
|
|
561
574
|
} catch (error) {
|
|
575
|
+
if (error instanceof RateLimitExceededError) {
|
|
576
|
+
return {
|
|
577
|
+
success: false,
|
|
578
|
+
output: null,
|
|
579
|
+
billing: { credits: 0 },
|
|
580
|
+
meta: {
|
|
581
|
+
success: false,
|
|
582
|
+
message: error.message,
|
|
583
|
+
toolName
|
|
584
|
+
},
|
|
585
|
+
error: {
|
|
586
|
+
code: "RATE_LIMITED",
|
|
587
|
+
message: error.message,
|
|
588
|
+
category: "external"
|
|
589
|
+
},
|
|
590
|
+
retry: {
|
|
591
|
+
allowed: true,
|
|
592
|
+
afterMs: error.retryAfterMs
|
|
593
|
+
}
|
|
594
|
+
};
|
|
595
|
+
}
|
|
562
596
|
if (error instanceof AppAuthInvalidError) {
|
|
563
597
|
return {
|
|
564
598
|
output: null,
|
|
@@ -922,7 +956,8 @@ function serializeConfig(config) {
|
|
|
922
956
|
description: tool.description,
|
|
923
957
|
// Read timeout/retries from top-level first, then fallback to config
|
|
924
958
|
timeout: tool.timeout ?? tool.config?.timeout,
|
|
925
|
-
retries: tool.retries ?? tool.config?.retries
|
|
959
|
+
retries: tool.retries ?? tool.config?.retries,
|
|
960
|
+
queueTouchPoints: tool.queueTouchPoints ?? tool.config?.queueTouchPoints
|
|
926
961
|
})) : [],
|
|
927
962
|
webhooks: webhookRegistry ? Object.values(webhookRegistry).map((w) => ({
|
|
928
963
|
name: w.name,
|
|
@@ -268,6 +268,16 @@ var AppAuthInvalidError = class extends Error {
|
|
|
268
268
|
}
|
|
269
269
|
};
|
|
270
270
|
|
|
271
|
+
// src/ratelimit/errors.ts
|
|
272
|
+
var RateLimitExceededError = class extends Error {
|
|
273
|
+
constructor(retryAfterMs, message = "Rate limit exceeded. Please try again later.") {
|
|
274
|
+
super(message);
|
|
275
|
+
this.code = "RATE_LIMITED";
|
|
276
|
+
this.name = "RateLimitExceededError";
|
|
277
|
+
this.retryAfterMs = retryAfterMs;
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
|
|
271
281
|
// src/server/context-logger.ts
|
|
272
282
|
import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
|
|
273
283
|
var logContextStorage = new AsyncLocalStorage3();
|
|
@@ -365,6 +375,7 @@ function buildToolMetadata(registry) {
|
|
|
365
375
|
const rawRetries = tool.retries ?? toolConfig.retries;
|
|
366
376
|
const timeout = typeof rawTimeout === "number" && rawTimeout > 0 ? rawTimeout : 1e4;
|
|
367
377
|
const retries = typeof rawRetries === "number" && rawRetries >= 1 ? rawRetries : 1;
|
|
378
|
+
const queueTouchPoints = tool.queueTouchPoints ?? toolConfig.queueTouchPoints;
|
|
368
379
|
return {
|
|
369
380
|
name: tool.name,
|
|
370
381
|
displayName: tool.label || tool.name,
|
|
@@ -374,10 +385,12 @@ function buildToolMetadata(registry) {
|
|
|
374
385
|
// Include timeout/retries at top-level for tools/list response (used by syncExecutableTools)
|
|
375
386
|
timeout,
|
|
376
387
|
retries,
|
|
388
|
+
queueTouchPoints,
|
|
377
389
|
config: {
|
|
378
390
|
timeout,
|
|
379
391
|
retries,
|
|
380
|
-
completionHints: toolConfig.completionHints
|
|
392
|
+
completionHints: toolConfig.completionHints,
|
|
393
|
+
queueTouchPoints
|
|
381
394
|
}
|
|
382
395
|
};
|
|
383
396
|
});
|
|
@@ -520,6 +533,27 @@ function createCallToolHandler(registry, state, onMaxRequests) {
|
|
|
520
533
|
cursor: functionResult.cursor
|
|
521
534
|
};
|
|
522
535
|
} catch (error) {
|
|
536
|
+
if (error instanceof RateLimitExceededError) {
|
|
537
|
+
return {
|
|
538
|
+
success: false,
|
|
539
|
+
output: null,
|
|
540
|
+
billing: { credits: 0 },
|
|
541
|
+
meta: {
|
|
542
|
+
success: false,
|
|
543
|
+
message: error.message,
|
|
544
|
+
toolName
|
|
545
|
+
},
|
|
546
|
+
error: {
|
|
547
|
+
code: "RATE_LIMITED",
|
|
548
|
+
message: error.message,
|
|
549
|
+
category: "external"
|
|
550
|
+
},
|
|
551
|
+
retry: {
|
|
552
|
+
allowed: true,
|
|
553
|
+
afterMs: error.retryAfterMs
|
|
554
|
+
}
|
|
555
|
+
};
|
|
556
|
+
}
|
|
523
557
|
if (error instanceof AppAuthInvalidError) {
|
|
524
558
|
return {
|
|
525
559
|
output: null,
|
|
@@ -883,7 +917,8 @@ function serializeConfig(config) {
|
|
|
883
917
|
description: tool.description,
|
|
884
918
|
// Read timeout/retries from top-level first, then fallback to config
|
|
885
919
|
timeout: tool.timeout ?? tool.config?.timeout,
|
|
886
|
-
retries: tool.retries ?? tool.config?.retries
|
|
920
|
+
retries: tool.retries ?? tool.config?.retries,
|
|
921
|
+
queueTouchPoints: tool.queueTouchPoints ?? tool.config?.queueTouchPoints
|
|
887
922
|
})) : [],
|
|
888
923
|
webhooks: webhookRegistry ? Object.values(webhookRegistry).map((w) => ({
|
|
889
924
|
name: w.name,
|
package/dist/triggers/types.d.ts
CHANGED
|
@@ -73,6 +73,7 @@ export declare const TriggerContextSchema: z.ZodObject<{
|
|
|
73
73
|
"thread.workflow.completed": "thread.workflow.completed";
|
|
74
74
|
"thread.follow_up.due": "thread.follow_up.due";
|
|
75
75
|
"thread.reminder.due": "thread.reminder.due";
|
|
76
|
+
"thread.signal.created": "thread.signal.created";
|
|
76
77
|
}>, z.ZodString]>;
|
|
77
78
|
payload: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
78
79
|
participant: z.ZodOptional<z.ZodObject<{
|
|
@@ -199,6 +200,7 @@ export declare const ResolvedTriggerSchema: z.ZodObject<{
|
|
|
199
200
|
"thread.workflow.completed": "thread.workflow.completed";
|
|
200
201
|
"thread.follow_up.due": "thread.follow_up.due";
|
|
201
202
|
"thread.reminder.due": "thread.reminder.due";
|
|
203
|
+
"thread.signal.created": "thread.signal.created";
|
|
202
204
|
}>, z.ZodString]>>>;
|
|
203
205
|
condition: z.ZodOptional<z.ZodString>;
|
|
204
206
|
}, z.core.$strip>>;
|
|
@@ -220,6 +222,7 @@ export declare const ResolvedTriggerSchema: z.ZodObject<{
|
|
|
220
222
|
"thread.workflow.completed": "thread.workflow.completed";
|
|
221
223
|
"thread.follow_up.due": "thread.follow_up.due";
|
|
222
224
|
"thread.reminder.due": "thread.reminder.due";
|
|
225
|
+
"thread.signal.created": "thread.signal.created";
|
|
223
226
|
}>, z.ZodString]>;
|
|
224
227
|
payload: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
225
228
|
participant: z.ZodOptional<z.ZodObject<{
|
package/dist/types/index.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export type { InvocationType, ServerHookHandle, InvocationContext, } from './inv
|
|
|
9
9
|
export { createToolCallContext, createServerHookContext, createWebhookContext, createWorkflowStepContext, } 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
|
-
export type { ToolResult, ToolSuccess, ToolFailure, ErrorCode, ErrorCategory, ToolWarning, ToolPagination, ToolBilling, ToolRetry, ToolTiming, ToolCompletionHints, ToolConfig, BillingInfo, ToolResponseMeta, ToolEffect, ToolError, ToolExecutionResult, ToolSchemaWithJson, ToolSchema, ToolHandler, ToolDefinition, ToolRegistryEntry, ToolRegistry, ToolName, ToolMetadata, ToolCallResponse, ExecutionScope, } from './tool';
|
|
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';
|
|
13
13
|
export { ToolResponseMetaSchema } from './tool';
|
|
14
14
|
export { createSuccessResponse, createListResponse, createErrorResponse, createValidationError, createNotFoundError, createAuthError, createRateLimitError, createExternalError, createTimeoutError, createPermissionError, createConflictError, isSuccess, isFailure, isRetryable, getRetryDelay, } from './tool-response';
|
|
15
15
|
export type { HealthStatus, ComputeLayer, DedicatedServerInstance, ServerlessServerInstance, SkedyulServerInstance, } from './server';
|
package/dist/types/tool.d.ts
CHANGED
|
@@ -92,9 +92,18 @@ export interface ToolCompletionHints {
|
|
|
92
92
|
idempotent?: boolean;
|
|
93
93
|
}
|
|
94
94
|
/**
|
|
95
|
-
*
|
|
96
|
-
* Groups timeout, retry, and completion hint settings.
|
|
95
|
+
* Declares which rate-limit queues a tool may touch (for orchestration probes).
|
|
97
96
|
*/
|
|
97
|
+
export interface QueueTouchPoint {
|
|
98
|
+
/** Queue name from skedyul.config queues (e.g. petbooqz_api) */
|
|
99
|
+
queue: string;
|
|
100
|
+
/** Conservative max upstream HTTP calls this handler may make */
|
|
101
|
+
estimatedCalls: number;
|
|
102
|
+
/** Arg field used as sub-key for per-resource mutex queues */
|
|
103
|
+
subKeyFromArg?: string;
|
|
104
|
+
/** True for correctness mutexes — excluded from rate-limit probe admission */
|
|
105
|
+
mutexOnly?: boolean;
|
|
106
|
+
}
|
|
98
107
|
export interface ToolConfig {
|
|
99
108
|
/** Timeout in milliseconds. Defaults to 10000 (10 seconds) if not specified. */
|
|
100
109
|
timeout?: number;
|
|
@@ -102,6 +111,8 @@ export interface ToolConfig {
|
|
|
102
111
|
retries?: number;
|
|
103
112
|
/** Hints for controlling tool completion behavior in agent loops */
|
|
104
113
|
completionHints?: ToolCompletionHints;
|
|
114
|
+
/** Rate-limit queue touch points for orchestration admission probes */
|
|
115
|
+
queueTouchPoints?: QueueTouchPoint[];
|
|
105
116
|
}
|
|
106
117
|
/**
|
|
107
118
|
* Successful tool execution result.
|
|
@@ -179,6 +190,8 @@ export interface ToolExecutionResult<Output = unknown> {
|
|
|
179
190
|
meta?: ToolResponseMeta;
|
|
180
191
|
effect?: ToolEffect;
|
|
181
192
|
error?: ToolError | null;
|
|
193
|
+
/** Retry guidance for transient failures (e.g. rate limiting) */
|
|
194
|
+
retry?: ToolRetry;
|
|
182
195
|
/** Rich data blocks for UI rendering (profiles, spreadsheets, datetime cards) */
|
|
183
196
|
dataBlocks?: import('./data-blocks').DataBlock[];
|
|
184
197
|
/** Cursor state for cron subscriptions - saved and passed to the next run */
|
|
@@ -215,6 +228,8 @@ export interface ToolDefinition<Input = unknown, Output = unknown, InputSchema e
|
|
|
215
228
|
outputSchema?: ToolSchema<OutputSchema>;
|
|
216
229
|
/** Tool execution configuration (timeout, retries, completion hints) */
|
|
217
230
|
config?: ToolConfig;
|
|
231
|
+
/** Rate-limit queue touch points (also accepted at top level for ergonomics) */
|
|
232
|
+
queueTouchPoints?: QueueTouchPoint[];
|
|
218
233
|
/**
|
|
219
234
|
* Execution scope for this tool.
|
|
220
235
|
* - `installation` (default): Requires appInstallationId, receives sk_wkp_ token.
|
|
@@ -233,6 +248,8 @@ export interface ToolRegistryEntry {
|
|
|
233
248
|
outputSchema?: ToolSchema;
|
|
234
249
|
/** Tool execution configuration (timeout, retries, completion hints) */
|
|
235
250
|
config?: ToolConfig;
|
|
251
|
+
/** Rate-limit queue touch points */
|
|
252
|
+
queueTouchPoints?: QueueTouchPoint[];
|
|
236
253
|
/** Execution scope for this tool */
|
|
237
254
|
executionScope?: ExecutionScope;
|
|
238
255
|
[key: string]: unknown;
|
|
@@ -251,6 +268,8 @@ export interface ToolMetadata {
|
|
|
251
268
|
retries?: number;
|
|
252
269
|
/** Tool execution configuration (timeout, retries, completion hints) */
|
|
253
270
|
config?: ToolConfig;
|
|
271
|
+
/** Rate-limit queue touch points for orchestration admission probes */
|
|
272
|
+
queueTouchPoints?: QueueTouchPoint[];
|
|
254
273
|
/** Execution scope for this tool */
|
|
255
274
|
executionScope?: ExecutionScope;
|
|
256
275
|
}
|