skedyul 1.5.0 → 1.5.10

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
@@ -364,6 +364,96 @@ var init_link = __esm({
364
364
  }
365
365
  });
366
366
 
367
+ // src/config/transpileConfigMetadata.ts
368
+ var transpileConfigMetadata_exports = {};
369
+ __export(transpileConfigMetadata_exports, {
370
+ transpileConfigMetadata: () => transpileConfigMetadata
371
+ });
372
+ function prepareConfigSource(content) {
373
+ return content.replace(/import\s*\(\s*(['"])([^'"]+)\1\s*\)/g, "Promise.resolve(null)");
374
+ }
375
+ function isJsonImport(importPath) {
376
+ return importPath.endsWith(".json");
377
+ }
378
+ async function transpileConfigMetadata(configPath) {
379
+ const esbuild = await import("esbuild");
380
+ const absolutePath = path12.resolve(configPath);
381
+ const configDir = path12.dirname(absolutePath);
382
+ const configBasename = path12.basename(absolutePath);
383
+ const result = await esbuild.build({
384
+ absWorkingDir: configDir,
385
+ entryPoints: [absolutePath],
386
+ bundle: true,
387
+ format: "cjs",
388
+ platform: "node",
389
+ target: "node22",
390
+ write: false,
391
+ logLevel: "silent",
392
+ plugins: [
393
+ {
394
+ name: "prepare-config-entry",
395
+ setup(build) {
396
+ build.onLoad({ filter: new RegExp(`/${configBasename.replace(".", "\\.")}$`) }, () => ({
397
+ contents: prepareConfigSource(fs12.readFileSync(absolutePath, "utf-8")),
398
+ loader: "ts"
399
+ }));
400
+ }
401
+ },
402
+ {
403
+ name: "skedyul-shim",
404
+ setup(build) {
405
+ build.onResolve({ filter: /^skedyul$/ }, () => ({
406
+ path: "skedyul-shim",
407
+ namespace: SKEDYUL_SHIM_NAMESPACE
408
+ }));
409
+ build.onLoad({ filter: /.*/, namespace: SKEDYUL_SHIM_NAMESPACE }, () => ({
410
+ contents: [
411
+ "function defineConfig(config) { return config; }",
412
+ "module.exports = { defineConfig };"
413
+ ].join("\n"),
414
+ loader: "js"
415
+ }));
416
+ }
417
+ },
418
+ {
419
+ name: "metadata-stub-imports",
420
+ setup(build) {
421
+ build.onResolve({ filter: /^\.{1,2}\// }, (args2) => {
422
+ if (isJsonImport(args2.path)) {
423
+ return void 0;
424
+ }
425
+ return {
426
+ path: args2.path,
427
+ namespace: METADATA_STUB_NAMESPACE
428
+ };
429
+ });
430
+ build.onLoad({ filter: /.*/, namespace: METADATA_STUB_NAMESPACE }, () => ({
431
+ contents: "module.exports = {};\n",
432
+ loader: "js"
433
+ }));
434
+ }
435
+ }
436
+ ]
437
+ });
438
+ if (result.errors.length > 0) {
439
+ throw new Error(result.errors.map((error) => error.text).join("\n"));
440
+ }
441
+ if (result.outputFiles.length === 0) {
442
+ throw new Error("Config transpile produced no output");
443
+ }
444
+ return result.outputFiles[0].text;
445
+ }
446
+ var fs12, path12, SKEDYUL_SHIM_NAMESPACE, METADATA_STUB_NAMESPACE;
447
+ var init_transpileConfigMetadata = __esm({
448
+ "src/config/transpileConfigMetadata.ts"() {
449
+ "use strict";
450
+ fs12 = __toESM(require("fs"));
451
+ path12 = __toESM(require("path"));
452
+ SKEDYUL_SHIM_NAMESPACE = "skedyul-shim";
453
+ METADATA_STUB_NAMESPACE = "metadata-stub";
454
+ }
455
+ });
456
+
367
457
  // src/cli/commands/invoke.ts
368
458
  var z2 = __toESM(require("zod"));
369
459
  var fs5 = __toESM(require("fs"));
@@ -2709,9 +2799,12 @@ function registerQueueConfig(config) {
2709
2799
  // src/server/utils/schema.ts
2710
2800
  var z4 = __toESM(require("zod"));
2711
2801
  function normalizeBilling(billing) {
2712
- if (!billing || typeof billing.credits !== "number") {
2802
+ if (!billing || typeof billing !== "object") {
2713
2803
  return { credits: 0 };
2714
2804
  }
2805
+ if (typeof billing.credits !== "number") {
2806
+ return { ...billing, credits: 0 };
2807
+ }
2715
2808
  return billing;
2716
2809
  }
2717
2810
  function toJsonSchema2(schema) {
@@ -3013,6 +3106,7 @@ function buildToolMetadata(registry) {
3013
3106
  const timeout = typeof rawTimeout === "number" && rawTimeout > 0 ? rawTimeout : 1e4;
3014
3107
  const retries = typeof rawRetries === "number" && rawRetries >= 1 ? rawRetries : 1;
3015
3108
  const queueTouchPoints = tool.queueTouchPoints ?? toolConfig.queueTouchPoints;
3109
+ const rateLimitHandoff = tool.rateLimitHandoff ?? toolConfig.rateLimitHandoff;
3016
3110
  return {
3017
3111
  name: tool.name,
3018
3112
  displayName: tool.label || tool.name,
@@ -3023,11 +3117,13 @@ function buildToolMetadata(registry) {
3023
3117
  timeout,
3024
3118
  retries,
3025
3119
  queueTouchPoints,
3120
+ rateLimitHandoff,
3026
3121
  config: {
3027
3122
  timeout,
3028
3123
  retries,
3029
3124
  completionHints: toolConfig.completionHints,
3030
- queueTouchPoints
3125
+ queueTouchPoints,
3126
+ rateLimitHandoff
3031
3127
  }
3032
3128
  };
3033
3129
  });
@@ -3069,7 +3165,8 @@ function createCallToolHandler(registry, state, onMaxRequests) {
3069
3165
  }
3070
3166
  const fn = tool.handler;
3071
3167
  const args2 = toolArgsInput ?? {};
3072
- const estimateMode = args2.estimate === true;
3168
+ const rawContextForMode = args2.context ?? {};
3169
+ const estimateMode = args2.estimate === true || rawContextForMode.mode === "estimate";
3073
3170
  if (!estimateMode) {
3074
3171
  state.incrementRequestCount();
3075
3172
  if (state.shouldShutdown()) {
@@ -3556,7 +3653,8 @@ function serializeConfig(config) {
3556
3653
  // Read timeout/retries from top-level first, then fallback to config
3557
3654
  timeout: tool.timeout ?? tool.config?.timeout,
3558
3655
  retries: tool.retries ?? tool.config?.retries,
3559
- queueTouchPoints: tool.queueTouchPoints ?? tool.config?.queueTouchPoints
3656
+ queueTouchPoints: tool.queueTouchPoints ?? tool.config?.queueTouchPoints,
3657
+ rateLimitHandoff: tool.rateLimitHandoff ?? tool.config?.rateLimitHandoff
3560
3658
  })) : [],
3561
3659
  webhooks: webhookRegistry ? Object.values(webhookRegistry).map((w) => ({
3562
3660
  name: w.name,
@@ -4251,11 +4349,12 @@ async function handleMcpRoute(req, ctx) {
4251
4349
  async function handleMcpToolsCall(params, id, ctx) {
4252
4350
  const toolName = params?.name;
4253
4351
  const rawArgs = params?.arguments ?? {};
4254
- const hasSkedyulFormat = "inputs" in rawArgs || "env" in rawArgs || "context" in rawArgs || "invocation" in rawArgs;
4352
+ const hasSkedyulFormat = "inputs" in rawArgs || "env" in rawArgs || "context" in rawArgs || "invocation" in rawArgs || "estimate" in rawArgs;
4255
4353
  const toolInputs = hasSkedyulFormat ? rawArgs.inputs ?? {} : rawArgs;
4256
4354
  const toolContext = hasSkedyulFormat ? rawArgs.context : void 0;
4257
4355
  const toolEnv = hasSkedyulFormat ? rawArgs.env : void 0;
4258
4356
  const toolInvocation = hasSkedyulFormat ? rawArgs.invocation : void 0;
4357
+ const estimate = hasSkedyulFormat && rawArgs.estimate === true;
4259
4358
  const found = findToolInRegistry(ctx.registry, toolName);
4260
4359
  if (!found) {
4261
4360
  return {
@@ -4280,7 +4379,8 @@ async function handleMcpToolsCall(params, id, ctx) {
4280
4379
  inputs: validatedInputs,
4281
4380
  context: toolContext,
4282
4381
  env: toolEnv,
4283
- invocation: toolInvocation
4382
+ invocation: toolInvocation,
4383
+ estimate
4284
4384
  });
4285
4385
  let result;
4286
4386
  const isFailure = isToolCallFailure(toolResult);
@@ -5871,165 +5971,10 @@ var fs14 = __toESM(require("fs"));
5871
5971
  var path14 = __toESM(require("path"));
5872
5972
  init_utils();
5873
5973
 
5874
- // src/config/loader.ts
5875
- var fs11 = __toESM(require("fs"));
5876
- var path11 = __toESM(require("path"));
5877
- var os2 = __toESM(require("os"));
5878
-
5879
- // src/config/transpileConfigMetadata.ts
5880
- var esbuild = __toESM(require("esbuild"));
5974
+ // src/config/schema-loader.ts
5881
5975
  var fs10 = __toESM(require("fs"));
5882
5976
  var path10 = __toESM(require("path"));
5883
- var SKEDYUL_SHIM_NAMESPACE = "skedyul-shim";
5884
- var METADATA_STUB_NAMESPACE = "metadata-stub";
5885
- function prepareConfigSource(content) {
5886
- return content.replace(/import\s*\(\s*(['"])([^'"]+)\1\s*\)/g, "Promise.resolve(null)");
5887
- }
5888
- function isJsonImport(importPath) {
5889
- return importPath.endsWith(".json");
5890
- }
5891
- async function transpileConfigMetadata(configPath) {
5892
- const absolutePath = path10.resolve(configPath);
5893
- const configDir = path10.dirname(absolutePath);
5894
- const configBasename = path10.basename(absolutePath);
5895
- const result = await esbuild.build({
5896
- absWorkingDir: configDir,
5897
- entryPoints: [absolutePath],
5898
- bundle: true,
5899
- format: "cjs",
5900
- platform: "node",
5901
- target: "node22",
5902
- write: false,
5903
- logLevel: "silent",
5904
- plugins: [
5905
- {
5906
- name: "prepare-config-entry",
5907
- setup(build2) {
5908
- build2.onLoad({ filter: new RegExp(`/${configBasename.replace(".", "\\.")}$`) }, () => ({
5909
- contents: prepareConfigSource(fs10.readFileSync(absolutePath, "utf-8")),
5910
- loader: "ts"
5911
- }));
5912
- }
5913
- },
5914
- {
5915
- name: "skedyul-shim",
5916
- setup(build2) {
5917
- build2.onResolve({ filter: /^skedyul$/ }, () => ({
5918
- path: "skedyul-shim",
5919
- namespace: SKEDYUL_SHIM_NAMESPACE
5920
- }));
5921
- build2.onLoad({ filter: /.*/, namespace: SKEDYUL_SHIM_NAMESPACE }, () => ({
5922
- contents: [
5923
- "function defineConfig(config) { return config; }",
5924
- "module.exports = { defineConfig };"
5925
- ].join("\n"),
5926
- loader: "js"
5927
- }));
5928
- }
5929
- },
5930
- {
5931
- name: "metadata-stub-imports",
5932
- setup(build2) {
5933
- build2.onResolve({ filter: /^\.{1,2}\// }, (args2) => {
5934
- if (isJsonImport(args2.path)) {
5935
- return void 0;
5936
- }
5937
- return {
5938
- path: args2.path,
5939
- namespace: METADATA_STUB_NAMESPACE
5940
- };
5941
- });
5942
- build2.onLoad({ filter: /.*/, namespace: METADATA_STUB_NAMESPACE }, () => ({
5943
- contents: "module.exports = {};\n",
5944
- loader: "js"
5945
- }));
5946
- }
5947
- }
5948
- ]
5949
- });
5950
- if (result.errors.length > 0) {
5951
- throw new Error(result.errors.map((error) => error.text).join("\n"));
5952
- }
5953
- if (result.outputFiles.length === 0) {
5954
- throw new Error("Config transpile produced no output");
5955
- }
5956
- return result.outputFiles[0].text;
5957
- }
5958
-
5959
- // src/config/loader.ts
5960
- var CONFIG_FILE_NAMES = [
5961
- "skedyul.config.ts",
5962
- "skedyul.config.js",
5963
- "skedyul.config.mjs",
5964
- "skedyul.config.cjs"
5965
- ];
5966
- async function loadConfig(configPath) {
5967
- const absolutePath = path11.resolve(configPath);
5968
- if (!fs11.existsSync(absolutePath)) {
5969
- throw new Error(`Config file not found: ${absolutePath}`);
5970
- }
5971
- const isTypeScript = absolutePath.endsWith(".ts");
5972
- try {
5973
- if (isTypeScript) {
5974
- try {
5975
- const transpiled = await transpileConfigMetadata(absolutePath);
5976
- const tempFile = path11.join(os2.tmpdir(), `skedyul-config-${Date.now()}.cjs`);
5977
- fs11.writeFileSync(tempFile, transpiled);
5978
- try {
5979
- const module3 = require(tempFile);
5980
- const config2 = module3.default || module3;
5981
- if (!config2 || typeof config2 !== "object") {
5982
- throw new Error("Config file must export a configuration object");
5983
- }
5984
- if (!config2.name || typeof config2.name !== "string") {
5985
- throw new Error('Config must have a "name" property');
5986
- }
5987
- return config2;
5988
- } finally {
5989
- try {
5990
- fs11.unlinkSync(tempFile);
5991
- } catch {
5992
- }
5993
- }
5994
- } catch (transpileError) {
5995
- throw new Error(
5996
- `Cannot load TypeScript config metadata from ${absolutePath}: ${transpileError instanceof Error ? transpileError.message : String(transpileError)}`
5997
- );
5998
- }
5999
- }
6000
- const module2 = await import(
6001
- /* webpackIgnore: true */
6002
- absolutePath
6003
- );
6004
- const config = module2.default || module2;
6005
- if (!config || typeof config !== "object") {
6006
- throw new Error("Config file must export a configuration object");
6007
- }
6008
- if (!config.name || typeof config.name !== "string") {
6009
- throw new Error('Config must have a "name" property');
6010
- }
6011
- return config;
6012
- } catch (error) {
6013
- throw new Error(
6014
- `Failed to load config from ${configPath}: ${error instanceof Error ? error.message : String(error)}`
6015
- );
6016
- }
6017
- }
6018
- function validateConfig(config) {
6019
- const errors = [];
6020
- if (!config.name) {
6021
- errors.push("Missing required field: name");
6022
- }
6023
- if (config.computeLayer && !["serverless", "dedicated"].includes(config.computeLayer)) {
6024
- errors.push(`Invalid computeLayer: ${config.computeLayer}. Must be 'serverless' or 'dedicated'`);
6025
- }
6026
- return { valid: errors.length === 0, errors };
6027
- }
6028
-
6029
- // src/config/schema-loader.ts
6030
- var fs12 = __toESM(require("fs"));
6031
- var path12 = __toESM(require("path"));
6032
- var os3 = __toESM(require("os"));
5977
+ var os2 = __toESM(require("os"));
6033
5978
 
6034
5979
  // src/schemas/crm-schema.ts
6035
5980
  var import_v42 = require("zod/v4");
@@ -6181,39 +6126,39 @@ function validateCRMSchema(data) {
6181
6126
 
6182
6127
  // src/config/schema-loader.ts
6183
6128
  async function transpileSchemaTypeScript(filePath) {
6184
- const content = fs12.readFileSync(filePath, "utf-8");
6129
+ const content = fs10.readFileSync(filePath, "utf-8");
6185
6130
  let transpiled = content.replace(/import\s+type\s+\{[^}]+\}\s+from\s+['"][^'"]+['"]\s*;?\n?/g, "").replace(/import\s+\{\s*defineSchema\s*\}\s+from\s+['"]skedyul['"]\s*;?\n?/g, "").replace(/:\s*CRMSchema/g, "").replace(/export\s+default\s+/, "module.exports = ").replace(/defineSchema\s*\(\s*\{/, "{").replace(/\}\s*\)\s*;?\s*$/, "}");
6186
6131
  return transpiled;
6187
6132
  }
6188
6133
  async function loadSchema(schemaPath, options = {}) {
6189
6134
  const { validate = true } = options;
6190
- const absolutePath = path12.resolve(schemaPath);
6191
- if (!fs12.existsSync(absolutePath)) {
6135
+ const absolutePath = path10.resolve(schemaPath);
6136
+ if (!fs10.existsSync(absolutePath)) {
6192
6137
  throw new Error(`Schema file not found: ${absolutePath}`);
6193
6138
  }
6194
6139
  const isTypeScript = absolutePath.endsWith(".ts");
6195
6140
  const isJson = absolutePath.endsWith(".json");
6196
6141
  if (!isTypeScript && !isJson) {
6197
6142
  throw new Error(
6198
- `Unsupported schema file format: ${path12.extname(absolutePath)}. Use .schema.ts or .schema.json`
6143
+ `Unsupported schema file format: ${path10.extname(absolutePath)}. Use .schema.ts or .schema.json`
6199
6144
  );
6200
6145
  }
6201
6146
  let rawSchema;
6202
6147
  try {
6203
6148
  if (isJson) {
6204
- const content = fs12.readFileSync(absolutePath, "utf-8");
6149
+ const content = fs10.readFileSync(absolutePath, "utf-8");
6205
6150
  rawSchema = JSON.parse(content);
6206
6151
  } else {
6207
6152
  const transpiled = await transpileSchemaTypeScript(absolutePath);
6208
- const tempDir = os3.tmpdir();
6209
- const tempFile = path12.join(tempDir, `skedyul-schema-${Date.now()}.cjs`);
6210
- fs12.writeFileSync(tempFile, transpiled);
6153
+ const tempDir = os2.tmpdir();
6154
+ const tempFile = path10.join(tempDir, `skedyul-schema-${Date.now()}.cjs`);
6155
+ fs10.writeFileSync(tempFile, transpiled);
6211
6156
  try {
6212
6157
  const module2 = require(tempFile);
6213
6158
  rawSchema = module2.default || module2;
6214
6159
  } finally {
6215
6160
  try {
6216
- fs12.unlinkSync(tempFile);
6161
+ fs10.unlinkSync(tempFile);
6217
6162
  } catch {
6218
6163
  }
6219
6164
  }
@@ -6258,10 +6203,10 @@ export default defineSchema(${jsonContent})
6258
6203
  `;
6259
6204
  }
6260
6205
  async function saveSchema(schema, outputPath, options = {}) {
6261
- const absolutePath = path12.resolve(outputPath);
6206
+ const absolutePath = path10.resolve(outputPath);
6262
6207
  const isTypeScript = absolutePath.endsWith(".ts");
6263
6208
  const content = isTypeScript ? serializeSchemaToTypeScript(schema) : serializeSchemaToJson(schema, options);
6264
- fs12.writeFileSync(absolutePath, content, "utf-8");
6209
+ fs10.writeFileSync(absolutePath, content, "utf-8");
6265
6210
  }
6266
6211
  var FIELD_TYPE_MAP = {
6267
6212
  string: "STRING",
@@ -6408,8 +6353,8 @@ function transformToBackendSchema(schema) {
6408
6353
  }
6409
6354
 
6410
6355
  // src/config/resolver.ts
6411
- var fs13 = __toESM(require("fs"));
6412
- var path13 = __toESM(require("path"));
6356
+ var fs11 = __toESM(require("fs"));
6357
+ var path11 = __toESM(require("path"));
6413
6358
  async function loadConfigModule(absolutePath) {
6414
6359
  if (absolutePath.endsWith(".ts")) {
6415
6360
  const altPaths = [
@@ -6418,7 +6363,7 @@ async function loadConfigModule(absolutePath) {
6418
6363
  absolutePath.replace(".ts", ".js")
6419
6364
  ];
6420
6365
  for (const altPath of altPaths) {
6421
- if (fs13.existsSync(altPath)) {
6366
+ if (fs11.existsSync(altPath)) {
6422
6367
  return await import(altPath);
6423
6368
  }
6424
6369
  }
@@ -6435,7 +6380,7 @@ async function loadConfigModule(absolutePath) {
6435
6380
  return await import(absolutePath);
6436
6381
  }
6437
6382
  async function loadAndResolveConfig(configPath) {
6438
- const absolutePath = path13.resolve(configPath);
6383
+ const absolutePath = path11.resolve(configPath);
6439
6384
  const module2 = await loadConfigModule(absolutePath);
6440
6385
  const config = module2.default;
6441
6386
  if (!config || typeof config !== "object") {
@@ -6490,7 +6435,8 @@ function serializeResolvedConfig(config) {
6490
6435
  // Read timeout/retries from top-level first, then fallback to config
6491
6436
  timeout: tool.timeout ?? tool.config?.timeout,
6492
6437
  retries: tool.retries ?? tool.config?.retries,
6493
- queueTouchPoints: tool.queueTouchPoints ?? tool.config?.queueTouchPoints
6438
+ queueTouchPoints: tool.queueTouchPoints ?? tool.config?.queueTouchPoints,
6439
+ rateLimitHandoff: tool.rateLimitHandoff ?? tool.config?.rateLimitHandoff
6494
6440
  })) : [],
6495
6441
  webhooks: config.webhooks ? Object.values(config.webhooks).map((w) => ({
6496
6442
  name: w.name,
@@ -6515,6 +6461,80 @@ function getAllEnvKeys(config) {
6515
6461
  };
6516
6462
  }
6517
6463
 
6464
+ // src/config/loader.ts
6465
+ var fs13 = __toESM(require("fs"));
6466
+ var path13 = __toESM(require("path"));
6467
+ var os3 = __toESM(require("os"));
6468
+ var CONFIG_FILE_NAMES = [
6469
+ "skedyul.config.ts",
6470
+ "skedyul.config.js",
6471
+ "skedyul.config.mjs",
6472
+ "skedyul.config.cjs"
6473
+ ];
6474
+ async function loadConfig(configPath) {
6475
+ const absolutePath = path13.resolve(configPath);
6476
+ if (!fs13.existsSync(absolutePath)) {
6477
+ throw new Error(`Config file not found: ${absolutePath}`);
6478
+ }
6479
+ const isTypeScript = absolutePath.endsWith(".ts");
6480
+ try {
6481
+ if (isTypeScript) {
6482
+ try {
6483
+ const { transpileConfigMetadata: transpileConfigMetadata2 } = await Promise.resolve().then(() => (init_transpileConfigMetadata(), transpileConfigMetadata_exports));
6484
+ const transpiled = await transpileConfigMetadata2(absolutePath);
6485
+ const tempFile = path13.join(os3.tmpdir(), `skedyul-config-${Date.now()}.cjs`);
6486
+ fs13.writeFileSync(tempFile, transpiled);
6487
+ try {
6488
+ const module3 = require(tempFile);
6489
+ const config2 = module3.default || module3;
6490
+ if (!config2 || typeof config2 !== "object") {
6491
+ throw new Error("Config file must export a configuration object");
6492
+ }
6493
+ if (!config2.name || typeof config2.name !== "string") {
6494
+ throw new Error('Config must have a "name" property');
6495
+ }
6496
+ return config2;
6497
+ } finally {
6498
+ try {
6499
+ fs13.unlinkSync(tempFile);
6500
+ } catch {
6501
+ }
6502
+ }
6503
+ } catch (transpileError) {
6504
+ throw new Error(
6505
+ `Cannot load TypeScript config metadata from ${absolutePath}: ${transpileError instanceof Error ? transpileError.message : String(transpileError)}`
6506
+ );
6507
+ }
6508
+ }
6509
+ const module2 = await import(
6510
+ /* webpackIgnore: true */
6511
+ absolutePath
6512
+ );
6513
+ const config = module2.default || module2;
6514
+ if (!config || typeof config !== "object") {
6515
+ throw new Error("Config file must export a configuration object");
6516
+ }
6517
+ if (!config.name || typeof config.name !== "string") {
6518
+ throw new Error('Config must have a "name" property');
6519
+ }
6520
+ return config;
6521
+ } catch (error) {
6522
+ throw new Error(
6523
+ `Failed to load config from ${configPath}: ${error instanceof Error ? error.message : String(error)}`
6524
+ );
6525
+ }
6526
+ }
6527
+ function validateConfig(config) {
6528
+ const errors = [];
6529
+ if (!config.name) {
6530
+ errors.push("Missing required field: name");
6531
+ }
6532
+ if (config.computeLayer && !["serverless", "dedicated"].includes(config.computeLayer)) {
6533
+ errors.push(`Invalid computeLayer: ${config.computeLayer}. Must be 'serverless' or 'dedicated'`);
6534
+ }
6535
+ return { valid: errors.length === 0, errors };
6536
+ }
6537
+
6518
6538
  // src/cli/commands/validate.ts
6519
6539
  function printHelp5() {
6520
6540
  console.log(`
@@ -12,7 +12,6 @@ export * from './types';
12
12
  export type { InstallConfig, ProvisionConfig, BuildConfig, CorsOptions, SkedyulConfig, SerializableSkedyulConfig, QueueScope, QueueConfig, SerializableQueueConfig, QueueRegistry, } from './app-config';
13
13
  export { defineConfig } from './app-config';
14
14
  export { defineModel, defineChannel, definePage, defineWorkflow, defineAgent, defineEnv, defineNavigation, } from './define';
15
- export { CONFIG_FILE_NAMES, loadConfig, validateConfig } from './loader';
16
15
  export { SCHEMA_FILE_EXTENSIONS, loadSchema, saveSchema, serializeSchemaToJson, serializeSchemaToTypeScript, transformToBackendSchema, transformFromBackendSchema, type LoadSchemaOptions, type LoadSchemaResult, type SerializeSchemaOptions, type BackendModelDefinition, type BackendFieldDefinition, type BackendRelationshipDefinition, type BackendDesiredSchema, } from './schema-loader';
17
16
  export { loadAndResolveConfig, serializeResolvedConfig, type ResolvedConfig } from './resolver';
18
17
  export { getAllEnvKeys, getRequiredInstallEnvKeys } from './utils';