skedyul 1.2.15 → 1.2.18

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 CHANGED
@@ -2951,8 +2951,66 @@ function printStartupLog(config, tools, webhookRegistry, port) {
2951
2951
  console.log("");
2952
2952
  }
2953
2953
 
2954
+ // src/config/resolve.ts
2955
+ async function resolveDynamicImport(value) {
2956
+ if (value === void 0 || value === null) {
2957
+ return void 0;
2958
+ }
2959
+ if (value instanceof Promise) {
2960
+ const resolved = await value;
2961
+ if (resolved && typeof resolved === "object" && "default" in resolved) {
2962
+ return resolved.default;
2963
+ }
2964
+ return resolved;
2965
+ }
2966
+ return value;
2967
+ }
2968
+ function serializeTools(registry) {
2969
+ return Object.entries(registry).map(([key, tool]) => ({
2970
+ name: tool.name || key,
2971
+ displayName: tool.label,
2972
+ description: tool.description,
2973
+ timeout: tool.timeout,
2974
+ retries: tool.retries
2975
+ }));
2976
+ }
2977
+ function serializeWebhooks(registry) {
2978
+ return Object.values(registry).map((webhook) => ({
2979
+ name: webhook.name,
2980
+ description: webhook.description,
2981
+ methods: webhook.methods ?? ["POST"],
2982
+ type: webhook.type ?? "WEBHOOK"
2983
+ }));
2984
+ }
2985
+ async function resolveConfig(config, registry, webhookRegistry) {
2986
+ const provision = await resolveDynamicImport(
2987
+ config.provision
2988
+ );
2989
+ const install = await resolveDynamicImport(
2990
+ config.install
2991
+ );
2992
+ const tools = serializeTools(registry);
2993
+ const webhooks = webhookRegistry ? serializeWebhooks(webhookRegistry) : [];
2994
+ return {
2995
+ name: config.name,
2996
+ version: config.version,
2997
+ description: config.description,
2998
+ computeLayer: config.computeLayer,
2999
+ tools,
3000
+ webhooks,
3001
+ provision,
3002
+ agents: config.agents
3003
+ };
3004
+ }
3005
+ function createMinimalConfig(name, version) {
3006
+ return {
3007
+ name,
3008
+ version
3009
+ };
3010
+ }
3011
+
2954
3012
  // src/server/dedicated.ts
2955
- function createDedicatedServerInstance(config, tools, callTool, state, mcpServer, webhookRegistry) {
3013
+ function createDedicatedServerInstance(config, tools, callTool, state, mcpServer, registry, webhookRegistry) {
2956
3014
  const port = getListeningPort(config);
2957
3015
  const httpServer = import_http2.default.createServer(
2958
3016
  async (req, res) => {
@@ -2969,6 +3027,15 @@ function createDedicatedServerInstance(config, tools, callTool, state, mcpServer
2969
3027
  sendJSON(res, 200, state.getHealthStatus());
2970
3028
  return;
2971
3029
  }
3030
+ if (pathname === "/config" && req.method === "GET") {
3031
+ const appConfig = config.appConfig ?? createMinimalConfig(
3032
+ config.metadata.name,
3033
+ config.metadata.version
3034
+ );
3035
+ const serializedConfig = await resolveConfig(appConfig, registry, webhookRegistry);
3036
+ sendJSON(res, 200, serializedConfig);
3037
+ return;
3038
+ }
2972
3039
  if (pathname.startsWith("/webhooks/") && webhookRegistry) {
2973
3040
  const handle = pathname.slice("/webhooks/".length);
2974
3041
  const webhookDef = webhookRegistry[handle];
@@ -4056,6 +4123,14 @@ function createServerlessInstance(config, tools, callTool, state, mcpServer, reg
4056
4123
  if (path14 === "/health" && method === "GET") {
4057
4124
  return createResponse(200, state.getHealthStatus(), headers);
4058
4125
  }
4126
+ if (path14 === "/config" && method === "GET") {
4127
+ const appConfig = config.appConfig ?? createMinimalConfig(
4128
+ config.metadata.name,
4129
+ config.metadata.version
4130
+ );
4131
+ const serializedConfig = await resolveConfig(appConfig, registry, webhookRegistry);
4132
+ return createResponse(200, serializedConfig, headers);
4133
+ }
4059
4134
  if (path14 === "/mcp" && method === "POST") {
4060
4135
  let body;
4061
4136
  try {
@@ -4429,6 +4504,7 @@ function createSkedyulServer(config, registry, webhookRegistry) {
4429
4504
  callTool,
4430
4505
  state,
4431
4506
  mcpServer,
4507
+ registry,
4432
4508
  webhookRegistry
4433
4509
  );
4434
4510
  }
@@ -13,4 +13,5 @@ export type { InstallConfig, ProvisionConfig, BuildConfig, SkedyulConfig, Serial
13
13
  export { defineConfig } from './app-config';
14
14
  export { defineModel, defineChannel, definePage, defineWorkflow, defineAgent, defineEnv, defineNavigation, } from './define';
15
15
  export { CONFIG_FILE_NAMES, loadConfig, validateConfig } from './loader';
16
+ export { resolveConfig, createMinimalConfig } from './resolve';
16
17
  export { getAllEnvKeys, getRequiredInstallEnvKeys } from './utils';
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Config resolution utilities.
3
+ *
4
+ * This module provides functions to resolve dynamic imports in SkedyulConfig
5
+ * and convert it to a serializable format for the /config endpoint.
6
+ */
7
+ import type { SkedyulConfig, SerializableSkedyulConfig } from './app-config';
8
+ import type { ToolRegistry, WebhookRegistry } from '../types';
9
+ /**
10
+ * Resolves all dynamic imports in a SkedyulConfig and returns a serializable version.
11
+ *
12
+ * This function:
13
+ * 1. Resolves dynamic imports for tools, webhooks, provision, and install
14
+ * 2. Serializes tool and webhook registries to metadata arrays
15
+ * 3. Returns a plain object suitable for JSON serialization
16
+ *
17
+ * @param config - The original SkedyulConfig (may contain dynamic imports)
18
+ * @param registry - The resolved tool registry (already loaded by mcp_server.ts)
19
+ * @param webhookRegistry - The resolved webhook registry (if any)
20
+ * @returns A fully resolved and serializable config
21
+ */
22
+ export declare function resolveConfig(config: SkedyulConfig, registry: ToolRegistry, webhookRegistry?: WebhookRegistry): Promise<SerializableSkedyulConfig>;
23
+ /**
24
+ * Creates a minimal SkedyulConfig from server metadata.
25
+ * Used as a fallback when appConfig is not provided.
26
+ */
27
+ export declare function createMinimalConfig(name: string, version?: string): SkedyulConfig;
@@ -30,6 +30,13 @@ export type FieldType = 'string' | 'long_string' | 'text' | 'number' | 'boolean'
30
30
  * - 'restrict': Prevent deletion if references exist
31
31
  */
32
32
  export type OnDelete = 'none' | 'cascade' | 'restrict';
33
+ /**
34
+ * Field requirement types.
35
+ * - 'optional': Field is never required
36
+ * - 'on_create': Field is required only when creating new records
37
+ * - 'required': Field is always required (create and update)
38
+ */
39
+ export type FieldRequirementType = 'optional' | 'on_create' | 'required';
33
40
  /**
34
41
  * Inline field definition for options and validation constraints.
35
42
  */
@@ -79,7 +86,17 @@ export interface FieldDefinition {
79
86
  * - Omitted: Auto-creates workplace definition as <subdomain>/<model>/<field>
80
87
  */
81
88
  definition?: InlineFieldDefinition | string;
82
- /** Whether this field is required */
89
+ /**
90
+ * Field requirement type.
91
+ * - 'optional': Field is never required (default)
92
+ * - 'on_create': Field is required only when creating new records
93
+ * - 'required': Field is always required (create and update)
94
+ */
95
+ requirement?: FieldRequirementType;
96
+ /**
97
+ * Whether this field is required.
98
+ * @deprecated Use `requirement` instead. Maps to 'required' if true, 'optional' if false.
99
+ */
83
100
  required?: boolean;
84
101
  /** Whether this field must be unique across all records */
85
102
  unique?: boolean;
@@ -769,8 +769,66 @@ function printStartupLog(config, tools, webhookRegistry, port) {
769
769
  console.log("");
770
770
  }
771
771
 
772
+ // src/config/resolve.ts
773
+ async function resolveDynamicImport(value) {
774
+ if (value === void 0 || value === null) {
775
+ return void 0;
776
+ }
777
+ if (value instanceof Promise) {
778
+ const resolved = await value;
779
+ if (resolved && typeof resolved === "object" && "default" in resolved) {
780
+ return resolved.default;
781
+ }
782
+ return resolved;
783
+ }
784
+ return value;
785
+ }
786
+ function serializeTools(registry) {
787
+ return Object.entries(registry).map(([key, tool]) => ({
788
+ name: tool.name || key,
789
+ displayName: tool.label,
790
+ description: tool.description,
791
+ timeout: tool.timeout,
792
+ retries: tool.retries
793
+ }));
794
+ }
795
+ function serializeWebhooks(registry) {
796
+ return Object.values(registry).map((webhook) => ({
797
+ name: webhook.name,
798
+ description: webhook.description,
799
+ methods: webhook.methods ?? ["POST"],
800
+ type: webhook.type ?? "WEBHOOK"
801
+ }));
802
+ }
803
+ async function resolveConfig(config, registry, webhookRegistry) {
804
+ const provision = await resolveDynamicImport(
805
+ config.provision
806
+ );
807
+ const install = await resolveDynamicImport(
808
+ config.install
809
+ );
810
+ const tools = serializeTools(registry);
811
+ const webhooks = webhookRegistry ? serializeWebhooks(webhookRegistry) : [];
812
+ return {
813
+ name: config.name,
814
+ version: config.version,
815
+ description: config.description,
816
+ computeLayer: config.computeLayer,
817
+ tools,
818
+ webhooks,
819
+ provision,
820
+ agents: config.agents
821
+ };
822
+ }
823
+ function createMinimalConfig(name, version) {
824
+ return {
825
+ name,
826
+ version
827
+ };
828
+ }
829
+
772
830
  // src/server/dedicated.ts
773
- function createDedicatedServerInstance(config, tools, callTool, state, mcpServer, webhookRegistry) {
831
+ function createDedicatedServerInstance(config, tools, callTool, state, mcpServer, registry, webhookRegistry) {
774
832
  const port = getListeningPort(config);
775
833
  const httpServer = import_http2.default.createServer(
776
834
  async (req, res) => {
@@ -787,6 +845,15 @@ function createDedicatedServerInstance(config, tools, callTool, state, mcpServer
787
845
  sendJSON(res, 200, state.getHealthStatus());
788
846
  return;
789
847
  }
848
+ if (pathname === "/config" && req.method === "GET") {
849
+ const appConfig = config.appConfig ?? createMinimalConfig(
850
+ config.metadata.name,
851
+ config.metadata.version
852
+ );
853
+ const serializedConfig = await resolveConfig(appConfig, registry, webhookRegistry);
854
+ sendJSON(res, 200, serializedConfig);
855
+ return;
856
+ }
790
857
  if (pathname.startsWith("/webhooks/") && webhookRegistry) {
791
858
  const handle = pathname.slice("/webhooks/".length);
792
859
  const webhookDef = webhookRegistry[handle];
@@ -1874,6 +1941,14 @@ function createServerlessInstance(config, tools, callTool, state, mcpServer, reg
1874
1941
  if (path === "/health" && method === "GET") {
1875
1942
  return createResponse(200, state.getHealthStatus(), headers);
1876
1943
  }
1944
+ if (path === "/config" && method === "GET") {
1945
+ const appConfig = config.appConfig ?? createMinimalConfig(
1946
+ config.metadata.name,
1947
+ config.metadata.version
1948
+ );
1949
+ const serializedConfig = await resolveConfig(appConfig, registry, webhookRegistry);
1950
+ return createResponse(200, serializedConfig, headers);
1951
+ }
1877
1952
  if (path === "/mcp" && method === "POST") {
1878
1953
  let body;
1879
1954
  try {
@@ -2247,6 +2322,7 @@ function createSkedyulServer(config, registry, webhookRegistry) {
2247
2322
  callTool,
2248
2323
  state,
2249
2324
  mcpServer,
2325
+ registry,
2250
2326
  webhookRegistry
2251
2327
  );
2252
2328
  }
@@ -163,11 +163,15 @@ var AppFieldVisibilitySchema = z2.object({
163
163
  list: z2.boolean().optional(),
164
164
  filters: z2.boolean().optional()
165
165
  });
166
+ var FieldRequirementTypeSchema = z2.enum(["optional", "on_create", "required"]);
166
167
  var ModelFieldDefinitionSchema = z2.object({
167
168
  handle: z2.string(),
168
169
  label: z2.string(),
169
170
  type: FieldDataTypeSchema.optional(),
170
171
  definition: z2.union([InlineFieldDefinitionSchema, z2.string()]).optional(),
172
+ /** Field requirement type: 'optional', 'on_create', or 'required' */
173
+ requirement: FieldRequirementTypeSchema.optional(),
174
+ /** @deprecated Use `requirement` instead */
171
175
  required: z2.boolean().optional(),
172
176
  unique: z2.boolean().optional(),
173
177
  system: z2.boolean().optional(),
@@ -2451,8 +2455,66 @@ function printStartupLog(config, tools, webhookRegistry, port) {
2451
2455
  console.log("");
2452
2456
  }
2453
2457
 
2458
+ // src/config/resolve.ts
2459
+ async function resolveDynamicImport(value) {
2460
+ if (value === void 0 || value === null) {
2461
+ return void 0;
2462
+ }
2463
+ if (value instanceof Promise) {
2464
+ const resolved = await value;
2465
+ if (resolved && typeof resolved === "object" && "default" in resolved) {
2466
+ return resolved.default;
2467
+ }
2468
+ return resolved;
2469
+ }
2470
+ return value;
2471
+ }
2472
+ function serializeTools(registry) {
2473
+ return Object.entries(registry).map(([key, tool]) => ({
2474
+ name: tool.name || key,
2475
+ displayName: tool.label,
2476
+ description: tool.description,
2477
+ timeout: tool.timeout,
2478
+ retries: tool.retries
2479
+ }));
2480
+ }
2481
+ function serializeWebhooks(registry) {
2482
+ return Object.values(registry).map((webhook2) => ({
2483
+ name: webhook2.name,
2484
+ description: webhook2.description,
2485
+ methods: webhook2.methods ?? ["POST"],
2486
+ type: webhook2.type ?? "WEBHOOK"
2487
+ }));
2488
+ }
2489
+ async function resolveConfig(config, registry, webhookRegistry) {
2490
+ const provision = await resolveDynamicImport(
2491
+ config.provision
2492
+ );
2493
+ const install = await resolveDynamicImport(
2494
+ config.install
2495
+ );
2496
+ const tools = serializeTools(registry);
2497
+ const webhooks = webhookRegistry ? serializeWebhooks(webhookRegistry) : [];
2498
+ return {
2499
+ name: config.name,
2500
+ version: config.version,
2501
+ description: config.description,
2502
+ computeLayer: config.computeLayer,
2503
+ tools,
2504
+ webhooks,
2505
+ provision,
2506
+ agents: config.agents
2507
+ };
2508
+ }
2509
+ function createMinimalConfig(name, version) {
2510
+ return {
2511
+ name,
2512
+ version
2513
+ };
2514
+ }
2515
+
2454
2516
  // src/server/dedicated.ts
2455
- function createDedicatedServerInstance(config, tools, callTool, state, mcpServer, webhookRegistry) {
2517
+ function createDedicatedServerInstance(config, tools, callTool, state, mcpServer, registry, webhookRegistry) {
2456
2518
  const port = getListeningPort(config);
2457
2519
  const httpServer = http.createServer(
2458
2520
  async (req, res) => {
@@ -2469,6 +2531,15 @@ function createDedicatedServerInstance(config, tools, callTool, state, mcpServer
2469
2531
  sendJSON(res, 200, state.getHealthStatus());
2470
2532
  return;
2471
2533
  }
2534
+ if (pathname === "/config" && req.method === "GET") {
2535
+ const appConfig = config.appConfig ?? createMinimalConfig(
2536
+ config.metadata.name,
2537
+ config.metadata.version
2538
+ );
2539
+ const serializedConfig = await resolveConfig(appConfig, registry, webhookRegistry);
2540
+ sendJSON(res, 200, serializedConfig);
2541
+ return;
2542
+ }
2472
2543
  if (pathname.startsWith("/webhooks/") && webhookRegistry) {
2473
2544
  const handle = pathname.slice("/webhooks/".length);
2474
2545
  const webhookDef = webhookRegistry[handle];
@@ -3556,6 +3627,14 @@ function createServerlessInstance(config, tools, callTool, state, mcpServer, reg
3556
3627
  if (path2 === "/health" && method === "GET") {
3557
3628
  return createResponse(200, state.getHealthStatus(), headers);
3558
3629
  }
3630
+ if (path2 === "/config" && method === "GET") {
3631
+ const appConfig = config.appConfig ?? createMinimalConfig(
3632
+ config.metadata.name,
3633
+ config.metadata.version
3634
+ );
3635
+ const serializedConfig = await resolveConfig(appConfig, registry, webhookRegistry);
3636
+ return createResponse(200, serializedConfig, headers);
3637
+ }
3559
3638
  if (path2 === "/mcp" && method === "POST") {
3560
3639
  let body;
3561
3640
  try {
@@ -3929,6 +4008,7 @@ function createSkedyulServer(config, registry, webhookRegistry) {
3929
4008
  callTool,
3930
4009
  state,
3931
4010
  mcpServer,
4011
+ registry,
3932
4012
  webhookRegistry
3933
4013
  );
3934
4014
  }
@@ -4175,6 +4255,7 @@ export {
4175
4255
  FieldDataTypeSchema,
4176
4256
  FieldOptionSchema,
4177
4257
  FieldOwnerSchema,
4258
+ FieldRequirementTypeSchema,
4178
4259
  FieldSettingButtonPropsSchema,
4179
4260
  FieldSettingComponentDefinitionSchema,
4180
4261
  FileSettingComponentDefinitionSchema,
@@ -4253,6 +4334,7 @@ export {
4253
4334
  communicationChannel,
4254
4335
  configure,
4255
4336
  createContextLogger,
4337
+ createMinimalConfig,
4256
4338
  createServerHookContext,
4257
4339
  createToolCallContext,
4258
4340
  createWebhookContext,
@@ -4279,6 +4361,7 @@ export {
4279
4361
  isWorkflowDependency,
4280
4362
  loadConfig,
4281
4363
  report,
4364
+ resolveConfig,
4282
4365
  resource,
4283
4366
  runWithConfig,
4284
4367
  safeParseConfig,
package/dist/index.d.ts CHANGED
@@ -15,5 +15,5 @@ declare const _default: {
15
15
  z: typeof z;
16
16
  };
17
17
  export default _default;
18
- export { defineConfig, defineModel, defineChannel, definePage, defineWorkflow, defineAgent, defineEnv, defineNavigation, loadConfig, validateConfig, CONFIG_FILE_NAMES, getAllEnvKeys, getRequiredInstallEnvKeys, } from './config';
18
+ export { defineConfig, defineModel, defineChannel, definePage, defineWorkflow, defineAgent, defineEnv, defineNavigation, loadConfig, validateConfig, resolveConfig, createMinimalConfig, CONFIG_FILE_NAMES, getAllEnvKeys, getRequiredInstallEnvKeys, } from './config';
19
19
  export type { SkedyulConfig, SerializableSkedyulConfig, InstallConfig, ProvisionConfig, BaseDefinition, Scope, FieldOwner, Visibility, ComputeLayer, StructuredFilter, FilterOperator, FilterCondition, FieldOption, EnvVariable, EnvSchema, FieldType, Cardinality, OnDelete, InlineFieldDefinition, FieldVisibility, FieldDefinition, ModelDefinition, RelationshipLink, RelationshipDefinition, CapabilityType, ChannelCapability, ChannelFieldPermissions, ChannelField, ChannelDefinition, WorkflowActionInput, WorkflowAction, WorkflowDefinition, AgentDefinition, NavigationItem, NavigationSection, NavigationSidebar, BreadcrumbItem, NavigationBreadcrumb, NavigationConfig, ContextMode, ContextItemModel, ContextItemTool, ContextItem, ContextDefinition, FormStyleProps, ButtonVariant, ButtonSize, ButtonProps, RelationshipExtension, FormHeader, ActionDefinition, ModalFormDefinition, InputComponent, TextareaComponent, SelectComponent, ComboboxComponent, CheckboxComponent, DatePickerComponent, TimePickerComponent, StatusIndicator, FieldSettingComponent, ImageSettingComponent, FileSettingComponent, ListItemTemplate, ListComponent, EmptyFormComponent, AlertComponent, FormComponent, FormLayoutColumn, FormLayoutRow, FormLayoutConfig, FormProps, CardHeader, CardBlock, ListBlock, ModelMapperBlock, BlockDefinition, PageType, PageDefinition, HttpMethod, WebhookRequest, WebhookHandlerContext, WebhookHandlerResponse, WebhookHandlerFn, WebhookHandlerDefinition, Webhooks, WebhookHandlerMetadata, ModelDependency, ChannelDependency, WorkflowDependency, ResourceDependency, } from './config';
package/dist/index.js CHANGED
@@ -57,6 +57,7 @@ __export(index_exports, {
57
57
  FieldDataTypeSchema: () => FieldDataTypeSchema,
58
58
  FieldOptionSchema: () => FieldOptionSchema,
59
59
  FieldOwnerSchema: () => FieldOwnerSchema,
60
+ FieldRequirementTypeSchema: () => FieldRequirementTypeSchema,
60
61
  FieldSettingButtonPropsSchema: () => FieldSettingButtonPropsSchema,
61
62
  FieldSettingComponentDefinitionSchema: () => FieldSettingComponentDefinitionSchema,
62
63
  FileSettingComponentDefinitionSchema: () => FileSettingComponentDefinitionSchema,
@@ -135,6 +136,7 @@ __export(index_exports, {
135
136
  communicationChannel: () => communicationChannel,
136
137
  configure: () => configure,
137
138
  createContextLogger: () => createContextLogger,
139
+ createMinimalConfig: () => createMinimalConfig,
138
140
  createServerHookContext: () => createServerHookContext,
139
141
  createToolCallContext: () => createToolCallContext,
140
142
  createWebhookContext: () => createWebhookContext,
@@ -161,6 +163,7 @@ __export(index_exports, {
161
163
  isWorkflowDependency: () => isWorkflowDependency,
162
164
  loadConfig: () => loadConfig,
163
165
  report: () => report,
166
+ resolveConfig: () => resolveConfig,
164
167
  resource: () => resource,
165
168
  runWithConfig: () => runWithConfig,
166
169
  safeParseConfig: () => safeParseConfig,
@@ -328,11 +331,15 @@ var AppFieldVisibilitySchema = import_v42.z.object({
328
331
  list: import_v42.z.boolean().optional(),
329
332
  filters: import_v42.z.boolean().optional()
330
333
  });
334
+ var FieldRequirementTypeSchema = import_v42.z.enum(["optional", "on_create", "required"]);
331
335
  var ModelFieldDefinitionSchema = import_v42.z.object({
332
336
  handle: import_v42.z.string(),
333
337
  label: import_v42.z.string(),
334
338
  type: FieldDataTypeSchema.optional(),
335
339
  definition: import_v42.z.union([InlineFieldDefinitionSchema, import_v42.z.string()]).optional(),
340
+ /** Field requirement type: 'optional', 'on_create', or 'required' */
341
+ requirement: FieldRequirementTypeSchema.optional(),
342
+ /** @deprecated Use `requirement` instead */
336
343
  required: import_v42.z.boolean().optional(),
337
344
  unique: import_v42.z.boolean().optional(),
338
345
  system: import_v42.z.boolean().optional(),
@@ -2616,8 +2623,66 @@ function printStartupLog(config, tools, webhookRegistry, port) {
2616
2623
  console.log("");
2617
2624
  }
2618
2625
 
2626
+ // src/config/resolve.ts
2627
+ async function resolveDynamicImport(value) {
2628
+ if (value === void 0 || value === null) {
2629
+ return void 0;
2630
+ }
2631
+ if (value instanceof Promise) {
2632
+ const resolved = await value;
2633
+ if (resolved && typeof resolved === "object" && "default" in resolved) {
2634
+ return resolved.default;
2635
+ }
2636
+ return resolved;
2637
+ }
2638
+ return value;
2639
+ }
2640
+ function serializeTools(registry) {
2641
+ return Object.entries(registry).map(([key, tool]) => ({
2642
+ name: tool.name || key,
2643
+ displayName: tool.label,
2644
+ description: tool.description,
2645
+ timeout: tool.timeout,
2646
+ retries: tool.retries
2647
+ }));
2648
+ }
2649
+ function serializeWebhooks(registry) {
2650
+ return Object.values(registry).map((webhook2) => ({
2651
+ name: webhook2.name,
2652
+ description: webhook2.description,
2653
+ methods: webhook2.methods ?? ["POST"],
2654
+ type: webhook2.type ?? "WEBHOOK"
2655
+ }));
2656
+ }
2657
+ async function resolveConfig(config, registry, webhookRegistry) {
2658
+ const provision = await resolveDynamicImport(
2659
+ config.provision
2660
+ );
2661
+ const install = await resolveDynamicImport(
2662
+ config.install
2663
+ );
2664
+ const tools = serializeTools(registry);
2665
+ const webhooks = webhookRegistry ? serializeWebhooks(webhookRegistry) : [];
2666
+ return {
2667
+ name: config.name,
2668
+ version: config.version,
2669
+ description: config.description,
2670
+ computeLayer: config.computeLayer,
2671
+ tools,
2672
+ webhooks,
2673
+ provision,
2674
+ agents: config.agents
2675
+ };
2676
+ }
2677
+ function createMinimalConfig(name, version) {
2678
+ return {
2679
+ name,
2680
+ version
2681
+ };
2682
+ }
2683
+
2619
2684
  // src/server/dedicated.ts
2620
- function createDedicatedServerInstance(config, tools, callTool, state, mcpServer, webhookRegistry) {
2685
+ function createDedicatedServerInstance(config, tools, callTool, state, mcpServer, registry, webhookRegistry) {
2621
2686
  const port = getListeningPort(config);
2622
2687
  const httpServer = import_http2.default.createServer(
2623
2688
  async (req, res) => {
@@ -2634,6 +2699,15 @@ function createDedicatedServerInstance(config, tools, callTool, state, mcpServer
2634
2699
  sendJSON(res, 200, state.getHealthStatus());
2635
2700
  return;
2636
2701
  }
2702
+ if (pathname === "/config" && req.method === "GET") {
2703
+ const appConfig = config.appConfig ?? createMinimalConfig(
2704
+ config.metadata.name,
2705
+ config.metadata.version
2706
+ );
2707
+ const serializedConfig = await resolveConfig(appConfig, registry, webhookRegistry);
2708
+ sendJSON(res, 200, serializedConfig);
2709
+ return;
2710
+ }
2637
2711
  if (pathname.startsWith("/webhooks/") && webhookRegistry) {
2638
2712
  const handle = pathname.slice("/webhooks/".length);
2639
2713
  const webhookDef = webhookRegistry[handle];
@@ -3721,6 +3795,14 @@ function createServerlessInstance(config, tools, callTool, state, mcpServer, reg
3721
3795
  if (path2 === "/health" && method === "GET") {
3722
3796
  return createResponse(200, state.getHealthStatus(), headers);
3723
3797
  }
3798
+ if (path2 === "/config" && method === "GET") {
3799
+ const appConfig = config.appConfig ?? createMinimalConfig(
3800
+ config.metadata.name,
3801
+ config.metadata.version
3802
+ );
3803
+ const serializedConfig = await resolveConfig(appConfig, registry, webhookRegistry);
3804
+ return createResponse(200, serializedConfig, headers);
3805
+ }
3724
3806
  if (path2 === "/mcp" && method === "POST") {
3725
3807
  let body;
3726
3808
  try {
@@ -4094,6 +4176,7 @@ function createSkedyulServer(config, registry, webhookRegistry) {
4094
4176
  callTool,
4095
4177
  state,
4096
4178
  mcpServer,
4179
+ registry,
4097
4180
  webhookRegistry
4098
4181
  );
4099
4182
  }
@@ -4341,6 +4424,7 @@ var index_default = { z: import_v44.z };
4341
4424
  FieldDataTypeSchema,
4342
4425
  FieldOptionSchema,
4343
4426
  FieldOwnerSchema,
4427
+ FieldRequirementTypeSchema,
4344
4428
  FieldSettingButtonPropsSchema,
4345
4429
  FieldSettingComponentDefinitionSchema,
4346
4430
  FileSettingComponentDefinitionSchema,
@@ -4419,6 +4503,7 @@ var index_default = { z: import_v44.z };
4419
4503
  communicationChannel,
4420
4504
  configure,
4421
4505
  createContextLogger,
4506
+ createMinimalConfig,
4422
4507
  createServerHookContext,
4423
4508
  createToolCallContext,
4424
4509
  createWebhookContext,
@@ -4444,6 +4529,7 @@ var index_default = { z: import_v44.z };
4444
4529
  isWorkflowDependency,
4445
4530
  loadConfig,
4446
4531
  report,
4532
+ resolveConfig,
4447
4533
  resource,
4448
4534
  runWithConfig,
4449
4535
  safeParseConfig,
package/dist/schemas.d.ts CHANGED
@@ -181,6 +181,11 @@ export declare const AppFieldVisibilitySchema: z.ZodObject<{
181
181
  list: z.ZodOptional<z.ZodBoolean>;
182
182
  filters: z.ZodOptional<z.ZodBoolean>;
183
183
  }, z.core.$strip>;
184
+ export declare const FieldRequirementTypeSchema: z.ZodEnum<{
185
+ required: "required";
186
+ optional: "optional";
187
+ on_create: "on_create";
188
+ }>;
184
189
  export declare const ModelFieldDefinitionSchema: z.ZodObject<{
185
190
  handle: z.ZodString;
186
191
  label: z.ZodString;
@@ -211,6 +216,11 @@ export declare const ModelFieldDefinitionSchema: z.ZodObject<{
211
216
  relatedModel: z.ZodOptional<z.ZodString>;
212
217
  pattern: z.ZodOptional<z.ZodString>;
213
218
  }, z.core.$strip>, z.ZodString]>>;
219
+ requirement: z.ZodOptional<z.ZodEnum<{
220
+ required: "required";
221
+ optional: "optional";
222
+ on_create: "on_create";
223
+ }>>;
214
224
  required: z.ZodOptional<z.ZodBoolean>;
215
225
  unique: z.ZodOptional<z.ZodBoolean>;
216
226
  system: z.ZodOptional<z.ZodBoolean>;
@@ -265,6 +275,11 @@ export declare const ModelDefinitionSchema: z.ZodObject<{
265
275
  relatedModel: z.ZodOptional<z.ZodString>;
266
276
  pattern: z.ZodOptional<z.ZodString>;
267
277
  }, z.core.$strip>, z.ZodString]>>;
278
+ requirement: z.ZodOptional<z.ZodEnum<{
279
+ required: "required";
280
+ optional: "optional";
281
+ on_create: "on_create";
282
+ }>>;
268
283
  required: z.ZodOptional<z.ZodBoolean>;
269
284
  unique: z.ZodOptional<z.ZodBoolean>;
270
285
  system: z.ZodOptional<z.ZodBoolean>;
@@ -2973,6 +2988,11 @@ export declare const InstallConfigSchema: z.ZodObject<{
2973
2988
  relatedModel: z.ZodOptional<z.ZodString>;
2974
2989
  pattern: z.ZodOptional<z.ZodString>;
2975
2990
  }, z.core.$strip>, z.ZodString]>>;
2991
+ requirement: z.ZodOptional<z.ZodEnum<{
2992
+ required: "required";
2993
+ optional: "optional";
2994
+ on_create: "on_create";
2995
+ }>>;
2976
2996
  required: z.ZodOptional<z.ZodBoolean>;
2977
2997
  unique: z.ZodOptional<z.ZodBoolean>;
2978
2998
  system: z.ZodOptional<z.ZodBoolean>;
@@ -3090,6 +3110,11 @@ export declare const ProvisionConfigSchema: z.ZodObject<{
3090
3110
  relatedModel: z.ZodOptional<z.ZodString>;
3091
3111
  pattern: z.ZodOptional<z.ZodString>;
3092
3112
  }, z.core.$strip>, z.ZodString]>>;
3113
+ requirement: z.ZodOptional<z.ZodEnum<{
3114
+ required: "required";
3115
+ optional: "optional";
3116
+ on_create: "on_create";
3117
+ }>>;
3093
3118
  required: z.ZodOptional<z.ZodBoolean>;
3094
3119
  unique: z.ZodOptional<z.ZodBoolean>;
3095
3120
  system: z.ZodOptional<z.ZodBoolean>;
@@ -3770,6 +3795,11 @@ export declare const SkedyulConfigSchema: z.ZodObject<{
3770
3795
  relatedModel: z.ZodOptional<z.ZodString>;
3771
3796
  pattern: z.ZodOptional<z.ZodString>;
3772
3797
  }, z.core.$strip>, z.ZodString]>>;
3798
+ requirement: z.ZodOptional<z.ZodEnum<{
3799
+ required: "required";
3800
+ optional: "optional";
3801
+ on_create: "on_create";
3802
+ }>>;
3773
3803
  required: z.ZodOptional<z.ZodBoolean>;
3774
3804
  unique: z.ZodOptional<z.ZodBoolean>;
3775
3805
  system: z.ZodOptional<z.ZodBoolean>;
@@ -4405,6 +4435,7 @@ export declare const SkedyulConfigSchema: z.ZodObject<{
4405
4435
  export type ParsedSkedyulConfig = z.infer<typeof SkedyulConfigSchema>;
4406
4436
  export declare function safeParseConfig(data: unknown): ParsedSkedyulConfig | null;
4407
4437
  export type FieldOwner = z.infer<typeof FieldOwnerSchema>;
4438
+ export type FieldRequirementType = z.infer<typeof FieldRequirementTypeSchema>;
4408
4439
  export type FieldOption = z.infer<typeof FieldOptionSchema>;
4409
4440
  export type InlineFieldDefinition = z.infer<typeof InlineFieldDefinitionSchema>;
4410
4441
  export type RelationshipCardinality = z.infer<typeof RelationshipCardinalitySchema>;
@@ -1,7 +1,7 @@
1
1
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- import type { SkedyulServerConfig, SkedyulServerInstance, ToolCallResponse, ToolMetadata, WebhookRegistry } from '../types';
2
+ import type { SkedyulServerConfig, SkedyulServerInstance, ToolCallResponse, ToolMetadata, ToolRegistry, WebhookRegistry } from '../types';
3
3
  import type { RequestState } from './types';
4
4
  /**
5
5
  * Creates a dedicated (long-running HTTP) server instance
6
6
  */
7
- export declare function createDedicatedServerInstance(config: SkedyulServerConfig, tools: ToolMetadata[], callTool: (nameRaw: unknown, argsRaw: unknown) => Promise<ToolCallResponse>, state: RequestState, mcpServer: McpServer, webhookRegistry?: WebhookRegistry): SkedyulServerInstance;
7
+ export declare function createDedicatedServerInstance(config: SkedyulServerConfig, tools: ToolMetadata[], callTool: (nameRaw: unknown, argsRaw: unknown) => Promise<ToolCallResponse>, state: RequestState, mcpServer: McpServer, registry: ToolRegistry, webhookRegistry?: WebhookRegistry): SkedyulServerInstance;
package/dist/server.js CHANGED
@@ -769,8 +769,66 @@ function printStartupLog(config, tools, webhookRegistry, port) {
769
769
  console.log("");
770
770
  }
771
771
 
772
+ // src/config/resolve.ts
773
+ async function resolveDynamicImport(value) {
774
+ if (value === void 0 || value === null) {
775
+ return void 0;
776
+ }
777
+ if (value instanceof Promise) {
778
+ const resolved = await value;
779
+ if (resolved && typeof resolved === "object" && "default" in resolved) {
780
+ return resolved.default;
781
+ }
782
+ return resolved;
783
+ }
784
+ return value;
785
+ }
786
+ function serializeTools(registry) {
787
+ return Object.entries(registry).map(([key, tool]) => ({
788
+ name: tool.name || key,
789
+ displayName: tool.label,
790
+ description: tool.description,
791
+ timeout: tool.timeout,
792
+ retries: tool.retries
793
+ }));
794
+ }
795
+ function serializeWebhooks(registry) {
796
+ return Object.values(registry).map((webhook) => ({
797
+ name: webhook.name,
798
+ description: webhook.description,
799
+ methods: webhook.methods ?? ["POST"],
800
+ type: webhook.type ?? "WEBHOOK"
801
+ }));
802
+ }
803
+ async function resolveConfig(config, registry, webhookRegistry) {
804
+ const provision = await resolveDynamicImport(
805
+ config.provision
806
+ );
807
+ const install = await resolveDynamicImport(
808
+ config.install
809
+ );
810
+ const tools = serializeTools(registry);
811
+ const webhooks = webhookRegistry ? serializeWebhooks(webhookRegistry) : [];
812
+ return {
813
+ name: config.name,
814
+ version: config.version,
815
+ description: config.description,
816
+ computeLayer: config.computeLayer,
817
+ tools,
818
+ webhooks,
819
+ provision,
820
+ agents: config.agents
821
+ };
822
+ }
823
+ function createMinimalConfig(name, version) {
824
+ return {
825
+ name,
826
+ version
827
+ };
828
+ }
829
+
772
830
  // src/server/dedicated.ts
773
- function createDedicatedServerInstance(config, tools, callTool, state, mcpServer, webhookRegistry) {
831
+ function createDedicatedServerInstance(config, tools, callTool, state, mcpServer, registry, webhookRegistry) {
774
832
  const port = getListeningPort(config);
775
833
  const httpServer = import_http2.default.createServer(
776
834
  async (req, res) => {
@@ -787,6 +845,15 @@ function createDedicatedServerInstance(config, tools, callTool, state, mcpServer
787
845
  sendJSON(res, 200, state.getHealthStatus());
788
846
  return;
789
847
  }
848
+ if (pathname === "/config" && req.method === "GET") {
849
+ const appConfig = config.appConfig ?? createMinimalConfig(
850
+ config.metadata.name,
851
+ config.metadata.version
852
+ );
853
+ const serializedConfig = await resolveConfig(appConfig, registry, webhookRegistry);
854
+ sendJSON(res, 200, serializedConfig);
855
+ return;
856
+ }
790
857
  if (pathname.startsWith("/webhooks/") && webhookRegistry) {
791
858
  const handle = pathname.slice("/webhooks/".length);
792
859
  const webhookDef = webhookRegistry[handle];
@@ -1874,6 +1941,14 @@ function createServerlessInstance(config, tools, callTool, state, mcpServer, reg
1874
1941
  if (path === "/health" && method === "GET") {
1875
1942
  return createResponse(200, state.getHealthStatus(), headers);
1876
1943
  }
1944
+ if (path === "/config" && method === "GET") {
1945
+ const appConfig = config.appConfig ?? createMinimalConfig(
1946
+ config.metadata.name,
1947
+ config.metadata.version
1948
+ );
1949
+ const serializedConfig = await resolveConfig(appConfig, registry, webhookRegistry);
1950
+ return createResponse(200, serializedConfig, headers);
1951
+ }
1877
1952
  if (path === "/mcp" && method === "POST") {
1878
1953
  let body;
1879
1954
  try {
@@ -2247,6 +2322,7 @@ function createSkedyulServer(config, registry, webhookRegistry) {
2247
2322
  callTool,
2248
2323
  state,
2249
2324
  mcpServer,
2325
+ registry,
2250
2326
  webhookRegistry
2251
2327
  );
2252
2328
  }
@@ -708,8 +708,66 @@ function printStartupLog(config, tools, webhookRegistry, port) {
708
708
  console.log("");
709
709
  }
710
710
 
711
+ // src/config/resolve.ts
712
+ async function resolveDynamicImport(value) {
713
+ if (value === void 0 || value === null) {
714
+ return void 0;
715
+ }
716
+ if (value instanceof Promise) {
717
+ const resolved = await value;
718
+ if (resolved && typeof resolved === "object" && "default" in resolved) {
719
+ return resolved.default;
720
+ }
721
+ return resolved;
722
+ }
723
+ return value;
724
+ }
725
+ function serializeTools(registry) {
726
+ return Object.entries(registry).map(([key, tool]) => ({
727
+ name: tool.name || key,
728
+ displayName: tool.label,
729
+ description: tool.description,
730
+ timeout: tool.timeout,
731
+ retries: tool.retries
732
+ }));
733
+ }
734
+ function serializeWebhooks(registry) {
735
+ return Object.values(registry).map((webhook) => ({
736
+ name: webhook.name,
737
+ description: webhook.description,
738
+ methods: webhook.methods ?? ["POST"],
739
+ type: webhook.type ?? "WEBHOOK"
740
+ }));
741
+ }
742
+ async function resolveConfig(config, registry, webhookRegistry) {
743
+ const provision = await resolveDynamicImport(
744
+ config.provision
745
+ );
746
+ const install = await resolveDynamicImport(
747
+ config.install
748
+ );
749
+ const tools = serializeTools(registry);
750
+ const webhooks = webhookRegistry ? serializeWebhooks(webhookRegistry) : [];
751
+ return {
752
+ name: config.name,
753
+ version: config.version,
754
+ description: config.description,
755
+ computeLayer: config.computeLayer,
756
+ tools,
757
+ webhooks,
758
+ provision,
759
+ agents: config.agents
760
+ };
761
+ }
762
+ function createMinimalConfig(name, version) {
763
+ return {
764
+ name,
765
+ version
766
+ };
767
+ }
768
+
711
769
  // src/server/dedicated.ts
712
- function createDedicatedServerInstance(config, tools, callTool, state, mcpServer, webhookRegistry) {
770
+ function createDedicatedServerInstance(config, tools, callTool, state, mcpServer, registry, webhookRegistry) {
713
771
  const port = getListeningPort(config);
714
772
  const httpServer = http.createServer(
715
773
  async (req, res) => {
@@ -726,6 +784,15 @@ function createDedicatedServerInstance(config, tools, callTool, state, mcpServer
726
784
  sendJSON(res, 200, state.getHealthStatus());
727
785
  return;
728
786
  }
787
+ if (pathname === "/config" && req.method === "GET") {
788
+ const appConfig = config.appConfig ?? createMinimalConfig(
789
+ config.metadata.name,
790
+ config.metadata.version
791
+ );
792
+ const serializedConfig = await resolveConfig(appConfig, registry, webhookRegistry);
793
+ sendJSON(res, 200, serializedConfig);
794
+ return;
795
+ }
729
796
  if (pathname.startsWith("/webhooks/") && webhookRegistry) {
730
797
  const handle = pathname.slice("/webhooks/".length);
731
798
  const webhookDef = webhookRegistry[handle];
@@ -1813,6 +1880,14 @@ function createServerlessInstance(config, tools, callTool, state, mcpServer, reg
1813
1880
  if (path === "/health" && method === "GET") {
1814
1881
  return createResponse(200, state.getHealthStatus(), headers);
1815
1882
  }
1883
+ if (path === "/config" && method === "GET") {
1884
+ const appConfig = config.appConfig ?? createMinimalConfig(
1885
+ config.metadata.name,
1886
+ config.metadata.version
1887
+ );
1888
+ const serializedConfig = await resolveConfig(appConfig, registry, webhookRegistry);
1889
+ return createResponse(200, serializedConfig, headers);
1890
+ }
1816
1891
  if (path === "/mcp" && method === "POST") {
1817
1892
  let body;
1818
1893
  try {
@@ -2186,6 +2261,7 @@ function createSkedyulServer(config, registry, webhookRegistry) {
2186
2261
  callTool,
2187
2262
  state,
2188
2263
  mcpServer,
2264
+ registry,
2189
2265
  webhookRegistry
2190
2266
  );
2191
2267
  }
@@ -2,6 +2,7 @@ import type { CoreApiConfig } from '../core/types';
2
2
  import type { ServerHooks } from './handlers';
3
3
  import type { APIGatewayProxyEvent, APIGatewayProxyResult } from './aws';
4
4
  import type { ComputeLayer } from '../config/types/compute';
5
+ import type { SkedyulConfig } from '../config/app-config';
5
6
  export interface HealthStatus {
6
7
  status: 'running';
7
8
  requests: number;
@@ -32,6 +33,8 @@ export interface SkedyulServerConfig {
32
33
  coreApi?: CoreApiConfig;
33
34
  /** Lifecycle hooks for install and provision handlers */
34
35
  hooks?: ServerHooks;
36
+ /** Original app config from skedyul.config.ts for /config endpoint serialization */
37
+ appConfig?: SkedyulConfig;
35
38
  }
36
39
  export interface DedicatedServerInstance {
37
40
  listen(port?: number): Promise<void>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skedyul",
3
- "version": "1.2.15",
3
+ "version": "1.2.18",
4
4
  "description": "The Skedyul SDK for Node.js",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",