skedyul 1.4.4 → 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 +83 -16
- package/dist/config/app-config.d.ts +5 -0
- package/dist/config/types/app-event.d.ts +40 -0
- package/dist/config/types/index.d.ts +1 -0
- package/dist/dedicated/server.js +38 -2
- package/dist/esm/index.mjs +166 -65
- package/dist/events/types.d.ts +11 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +168 -65
- 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/schemas.d.ts +138 -0
- package/dist/server.js +38 -2
- package/dist/serverless/server.mjs +38 -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/cli/index.js
CHANGED
|
@@ -2904,6 +2904,16 @@ var AppAuthInvalidError = class extends Error {
|
|
|
2904
2904
|
}
|
|
2905
2905
|
};
|
|
2906
2906
|
|
|
2907
|
+
// src/ratelimit/errors.ts
|
|
2908
|
+
var RateLimitExceededError = class extends Error {
|
|
2909
|
+
constructor(retryAfterMs, message = "Rate limit exceeded. Please try again later.") {
|
|
2910
|
+
super(message);
|
|
2911
|
+
this.code = "RATE_LIMITED";
|
|
2912
|
+
this.name = "RateLimitExceededError";
|
|
2913
|
+
this.retryAfterMs = retryAfterMs;
|
|
2914
|
+
}
|
|
2915
|
+
};
|
|
2916
|
+
|
|
2907
2917
|
// src/server/context-logger.ts
|
|
2908
2918
|
var import_async_hooks3 = require("async_hooks");
|
|
2909
2919
|
var logContextStorage = new import_async_hooks3.AsyncLocalStorage();
|
|
@@ -2981,6 +2991,7 @@ function buildToolMetadata(registry) {
|
|
|
2981
2991
|
const rawRetries = tool.retries ?? toolConfig.retries;
|
|
2982
2992
|
const timeout = typeof rawTimeout === "number" && rawTimeout > 0 ? rawTimeout : 1e4;
|
|
2983
2993
|
const retries = typeof rawRetries === "number" && rawRetries >= 1 ? rawRetries : 1;
|
|
2994
|
+
const queueTouchPoints = tool.queueTouchPoints ?? toolConfig.queueTouchPoints;
|
|
2984
2995
|
return {
|
|
2985
2996
|
name: tool.name,
|
|
2986
2997
|
displayName: tool.label || tool.name,
|
|
@@ -2990,10 +3001,12 @@ function buildToolMetadata(registry) {
|
|
|
2990
3001
|
// Include timeout/retries at top-level for tools/list response (used by syncExecutableTools)
|
|
2991
3002
|
timeout,
|
|
2992
3003
|
retries,
|
|
3004
|
+
queueTouchPoints,
|
|
2993
3005
|
config: {
|
|
2994
3006
|
timeout,
|
|
2995
3007
|
retries,
|
|
2996
|
-
completionHints: toolConfig.completionHints
|
|
3008
|
+
completionHints: toolConfig.completionHints,
|
|
3009
|
+
queueTouchPoints
|
|
2997
3010
|
}
|
|
2998
3011
|
};
|
|
2999
3012
|
});
|
|
@@ -3136,6 +3149,27 @@ function createCallToolHandler(registry, state, onMaxRequests) {
|
|
|
3136
3149
|
cursor: functionResult.cursor
|
|
3137
3150
|
};
|
|
3138
3151
|
} catch (error) {
|
|
3152
|
+
if (error instanceof RateLimitExceededError) {
|
|
3153
|
+
return {
|
|
3154
|
+
success: false,
|
|
3155
|
+
output: null,
|
|
3156
|
+
billing: { credits: 0 },
|
|
3157
|
+
meta: {
|
|
3158
|
+
success: false,
|
|
3159
|
+
message: error.message,
|
|
3160
|
+
toolName
|
|
3161
|
+
},
|
|
3162
|
+
error: {
|
|
3163
|
+
code: "RATE_LIMITED",
|
|
3164
|
+
message: error.message,
|
|
3165
|
+
category: "external"
|
|
3166
|
+
},
|
|
3167
|
+
retry: {
|
|
3168
|
+
allowed: true,
|
|
3169
|
+
afterMs: error.retryAfterMs
|
|
3170
|
+
}
|
|
3171
|
+
};
|
|
3172
|
+
}
|
|
3139
3173
|
if (error instanceof AppAuthInvalidError) {
|
|
3140
3174
|
return {
|
|
3141
3175
|
output: null,
|
|
@@ -3499,7 +3533,8 @@ function serializeConfig(config) {
|
|
|
3499
3533
|
description: tool.description,
|
|
3500
3534
|
// Read timeout/retries from top-level first, then fallback to config
|
|
3501
3535
|
timeout: tool.timeout ?? tool.config?.timeout,
|
|
3502
|
-
retries: tool.retries ?? tool.config?.retries
|
|
3536
|
+
retries: tool.retries ?? tool.config?.retries,
|
|
3537
|
+
queueTouchPoints: tool.queueTouchPoints ?? tool.config?.queueTouchPoints
|
|
3503
3538
|
})) : [],
|
|
3504
3539
|
webhooks: webhookRegistry ? Object.values(webhookRegistry).map((w) => ({
|
|
3505
3540
|
name: w.name,
|
|
@@ -3509,6 +3544,7 @@ function serializeConfig(config) {
|
|
|
3509
3544
|
})) : [],
|
|
3510
3545
|
provision: isProvisionConfig(config.provision) ? config.provision : void 0,
|
|
3511
3546
|
agents: config.agents,
|
|
3547
|
+
events: config.events,
|
|
3512
3548
|
queues: config.queues
|
|
3513
3549
|
};
|
|
3514
3550
|
}
|
|
@@ -5823,17 +5859,37 @@ var CONFIG_FILE_NAMES = [
|
|
|
5823
5859
|
"skedyul.config.mjs",
|
|
5824
5860
|
"skedyul.config.cjs"
|
|
5825
5861
|
];
|
|
5862
|
+
function loadTypeScriptConfigModule(absolutePath) {
|
|
5863
|
+
try {
|
|
5864
|
+
require("tsx/cjs");
|
|
5865
|
+
delete require.cache[absolutePath];
|
|
5866
|
+
const module2 = require(absolutePath);
|
|
5867
|
+
return module2.default ?? module2;
|
|
5868
|
+
} catch (error) {
|
|
5869
|
+
throw new Error(
|
|
5870
|
+
`Cannot load TypeScript config: ${absolutePath}: ${error instanceof Error ? error.message : String(error)}`
|
|
5871
|
+
);
|
|
5872
|
+
}
|
|
5873
|
+
}
|
|
5826
5874
|
async function transpileTypeScript(filePath) {
|
|
5827
5875
|
const content = fs10.readFileSync(filePath, "utf-8");
|
|
5828
5876
|
const configDir = path10.dirname(path10.resolve(filePath));
|
|
5829
5877
|
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*$/, "}");
|
|
5830
5878
|
transpiled = transpiled.replace(
|
|
5831
5879
|
/import\s+(\w+)\s+from\s+['"](\.[^'"]+)['"]\s*(?:with\s*\{[^}]*\})?/g,
|
|
5832
|
-
(
|
|
5880
|
+
(_match, varName, relativePath) => {
|
|
5833
5881
|
const absolutePath = path10.resolve(configDir, relativePath);
|
|
5834
5882
|
return `const ${varName} = require('${absolutePath.replace(/\\/g, "/")}')`;
|
|
5835
5883
|
}
|
|
5836
5884
|
);
|
|
5885
|
+
transpiled = transpiled.replace(
|
|
5886
|
+
/import\s+\{\s*([^}]+)\s*\}\s+from\s+['"](\.[^'"]+)['"]\s*;?\n?/g,
|
|
5887
|
+
(_match, namedImports, relativePath) => {
|
|
5888
|
+
const absolutePath = path10.resolve(configDir, relativePath);
|
|
5889
|
+
return `const { ${namedImports.trim()} } = require('${absolutePath.replace(/\\/g, "/")}')
|
|
5890
|
+
`;
|
|
5891
|
+
}
|
|
5892
|
+
);
|
|
5837
5893
|
transpiled = transpiled.replace(/import\s*\(\s*['"][^'"]+['"]\s*\)/g, "null");
|
|
5838
5894
|
return transpiled;
|
|
5839
5895
|
}
|
|
@@ -5844,16 +5900,9 @@ async function loadConfig(configPath) {
|
|
|
5844
5900
|
}
|
|
5845
5901
|
const isTypeScript = absolutePath.endsWith(".ts");
|
|
5846
5902
|
try {
|
|
5847
|
-
let moduleToLoad = absolutePath;
|
|
5848
5903
|
if (isTypeScript) {
|
|
5849
|
-
const transpiled = await transpileTypeScript(absolutePath);
|
|
5850
|
-
const tempDir = os2.tmpdir();
|
|
5851
|
-
const tempFile = path10.join(tempDir, `skedyul-config-${Date.now()}.cjs`);
|
|
5852
|
-
fs10.writeFileSync(tempFile, transpiled);
|
|
5853
|
-
moduleToLoad = tempFile;
|
|
5854
5904
|
try {
|
|
5855
|
-
const
|
|
5856
|
-
const config2 = module3.default || module3;
|
|
5905
|
+
const config2 = loadTypeScriptConfigModule(absolutePath);
|
|
5857
5906
|
if (!config2 || typeof config2 !== "object") {
|
|
5858
5907
|
throw new Error("Config file must export a configuration object");
|
|
5859
5908
|
}
|
|
@@ -5861,16 +5910,31 @@ async function loadConfig(configPath) {
|
|
|
5861
5910
|
throw new Error('Config must have a "name" property');
|
|
5862
5911
|
}
|
|
5863
5912
|
return config2;
|
|
5864
|
-
}
|
|
5913
|
+
} catch (tsxError) {
|
|
5914
|
+
const transpiled = await transpileTypeScript(absolutePath);
|
|
5915
|
+
const tempFile = path10.join(os2.tmpdir(), `skedyul-config-${Date.now()}.cjs`);
|
|
5916
|
+
fs10.writeFileSync(tempFile, transpiled);
|
|
5865
5917
|
try {
|
|
5866
|
-
|
|
5867
|
-
|
|
5918
|
+
const module3 = require(tempFile);
|
|
5919
|
+
const config2 = module3.default || module3;
|
|
5920
|
+
if (!config2 || typeof config2 !== "object") {
|
|
5921
|
+
throw new Error("Config file must export a configuration object");
|
|
5922
|
+
}
|
|
5923
|
+
if (!config2.name || typeof config2.name !== "string") {
|
|
5924
|
+
throw new Error('Config must have a "name" property');
|
|
5925
|
+
}
|
|
5926
|
+
return config2;
|
|
5927
|
+
} finally {
|
|
5928
|
+
try {
|
|
5929
|
+
fs10.unlinkSync(tempFile);
|
|
5930
|
+
} catch {
|
|
5931
|
+
}
|
|
5868
5932
|
}
|
|
5869
5933
|
}
|
|
5870
5934
|
}
|
|
5871
5935
|
const module2 = await import(
|
|
5872
5936
|
/* webpackIgnore: true */
|
|
5873
|
-
|
|
5937
|
+
absolutePath
|
|
5874
5938
|
);
|
|
5875
5939
|
const config = module2.default || module2;
|
|
5876
5940
|
if (!config || typeof config !== "object") {
|
|
@@ -6370,6 +6434,7 @@ function serializeResolvedConfig(config) {
|
|
|
6370
6434
|
})) : [],
|
|
6371
6435
|
provision: config.provision,
|
|
6372
6436
|
agents: config.agents,
|
|
6437
|
+
events: config.events,
|
|
6373
6438
|
queues: config.queues
|
|
6374
6439
|
};
|
|
6375
6440
|
}
|
|
@@ -9622,7 +9687,9 @@ var ThreadEventTypeSchema = import_v44.z.enum([
|
|
|
9622
9687
|
"thread.workflow.completed",
|
|
9623
9688
|
// Scheduled events
|
|
9624
9689
|
"thread.follow_up.due",
|
|
9625
|
-
"thread.reminder.due"
|
|
9690
|
+
"thread.reminder.due",
|
|
9691
|
+
// Signal events
|
|
9692
|
+
"thread.signal.created"
|
|
9626
9693
|
]);
|
|
9627
9694
|
var CustomEventTypeSchema = import_v44.z.string().regex(/^custom\.[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)*$/, {
|
|
9628
9695
|
message: "Custom event type must match pattern: custom.{namespace}.{event}"
|
|
@@ -7,6 +7,7 @@ import type { ToolRegistry, WebhookRegistry, ToolMetadata, WebhookMetadata } fro
|
|
|
7
7
|
import type { ServerHooks } from '../types/handlers';
|
|
8
8
|
import type { CoreApiConfig } from '../core/types';
|
|
9
9
|
import type { EnvSchema, ComputeLayer, ModelDefinition, RelationshipDefinition, ChannelDefinition, WorkflowDefinition, PageDefinition, NavigationConfig, AgentDefinition, SignalDefinition } from './types';
|
|
10
|
+
import type { AppEventDefinition } from './types/app-event';
|
|
10
11
|
import type { QueueRegistry, SerializableQueueConfig } from './queue-config';
|
|
11
12
|
export type { QueueScope, QueueConfig, SerializableQueueConfig, QueueRegistry, } from './queue-config';
|
|
12
13
|
/**
|
|
@@ -102,6 +103,8 @@ export interface SkedyulConfig {
|
|
|
102
103
|
}>;
|
|
103
104
|
/** Agent definitions - multi-tenant agents with tool bindings */
|
|
104
105
|
agents?: AgentDefinition[];
|
|
106
|
+
/** App events emitted via event.create (catalog for UI + docs) */
|
|
107
|
+
events?: AppEventDefinition[];
|
|
105
108
|
/** Build configuration for the integration */
|
|
106
109
|
build?: BuildConfig;
|
|
107
110
|
/** Rate-limit queue definitions for queuedFetch */
|
|
@@ -124,6 +127,8 @@ export interface SerializableSkedyulConfig {
|
|
|
124
127
|
provision?: ProvisionConfig;
|
|
125
128
|
/** Agent definitions (stored as-is) */
|
|
126
129
|
agents?: AgentDefinition[];
|
|
130
|
+
/** App event catalog */
|
|
131
|
+
events?: AppEventDefinition[];
|
|
127
132
|
/** Rate-limit queue definitions */
|
|
128
133
|
queues?: Record<string, SerializableQueueConfig>;
|
|
129
134
|
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* App event definition for integration executable config.
|
|
3
|
+
*
|
|
4
|
+
* Events are emitted via event.create and subscribed to as
|
|
5
|
+
* `app.{appHandle}.{name}` (e.g. app.bft.member.updated).
|
|
6
|
+
*/
|
|
7
|
+
export interface AppEventDefinition {
|
|
8
|
+
/** Event suffix after app handle, e.g. member.created */
|
|
9
|
+
name: string;
|
|
10
|
+
/** UI display label */
|
|
11
|
+
label: string;
|
|
12
|
+
/** Optional description for pickers and docs */
|
|
13
|
+
description?: string;
|
|
14
|
+
/** Optional grouping label (Members, Bookings, etc.) */
|
|
15
|
+
group?: string;
|
|
16
|
+
/** Optional Lucide icon name for pickers */
|
|
17
|
+
icon?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Example flat domain payload for liquid context reference (e.g. glofox_id, phone, …).
|
|
20
|
+
* Not the full emit payload — studio/branch metadata is added at emit time.
|
|
21
|
+
*/
|
|
22
|
+
examplePayload?: Record<string, unknown>;
|
|
23
|
+
/**
|
|
24
|
+
* Typed context field tree for liquid input path browsing (data.* paths).
|
|
25
|
+
* When set, subscribers see explicit fields like data.phone.
|
|
26
|
+
*/
|
|
27
|
+
contextFields?: AppEventContextField[];
|
|
28
|
+
/**
|
|
29
|
+
* Workflow input type for app-event payloads, e.g. @app/bft/member/updated.
|
|
30
|
+
* Workflows declare this on inputs.data and subscribe with {{ data }}.
|
|
31
|
+
*/
|
|
32
|
+
workflowInputType?: string;
|
|
33
|
+
}
|
|
34
|
+
export interface AppEventContextField {
|
|
35
|
+
path: string;
|
|
36
|
+
label: string;
|
|
37
|
+
type?: string;
|
|
38
|
+
description?: string;
|
|
39
|
+
children?: AppEventContextField[];
|
|
40
|
+
}
|
package/dist/dedicated/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,
|
|
@@ -932,6 +967,7 @@ function serializeConfig(config) {
|
|
|
932
967
|
})) : [],
|
|
933
968
|
provision: isProvisionConfig(config.provision) ? config.provision : void 0,
|
|
934
969
|
agents: config.agents,
|
|
970
|
+
events: config.events,
|
|
935
971
|
queues: config.queues
|
|
936
972
|
};
|
|
937
973
|
}
|