@runtypelabs/cli 2.16.3 → 2.16.5

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.
Files changed (2) hide show
  1. package/dist/index.js +371 -129
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -15732,6 +15732,16 @@ var productConfigurationSummarySchema = external_exports.object({
15732
15732
  var ORGANIZATION_INTEGRATION_PROVIDERS = ["slack", "telegram", "discord", "linear", "github"];
15733
15733
  var integrationProviderSchema = external_exports.enum(ORGANIZATION_INTEGRATION_PROVIDERS);
15734
15734
  var integrationStatusSchema = external_exports.enum(["active", "revoked", "pending"]);
15735
+ var setVariableConfigSchema = external_exports.object({
15736
+ variableName: external_exports.string().min(1, "Variable name is required"),
15737
+ // The object branch is modeled as a record (rather than the historical
15738
+ // `z.object({})`) so the inferred union keeps its primitive members distinct:
15739
+ // a bare `{}` is a supertype of `string | number | boolean` and would absorb
15740
+ // them, degrading `value` to `{}`. A record accepts exactly the same inputs as
15741
+ // the prior `z.object({})` (any plain object, never an array or primitive).
15742
+ value: external_exports.union([external_exports.string(), external_exports.number(), external_exports.boolean(), external_exports.record(external_exports.string(), external_exports.unknown())]),
15743
+ valueTemplate: external_exports.string().optional()
15744
+ });
15735
15745
  var SERIALIZED_HELPERS_SOURCE = `
15736
15746
  // Transform helper functions (from packages/shared/src/transform-helpers.ts)
15737
15747
  const helpers = (function createHelpers() {
@@ -33716,6 +33726,156 @@ var SLACK_MANIFEST_BOT_SCOPES = [
33716
33726
  ...SLACK_REQUIRED_BOT_SCOPES,
33717
33727
  ...SLACK_OPTIONAL_BOT_SCOPES
33718
33728
  ];
33729
+ var reasoningConfigSchema = external_exports.union([
33730
+ external_exports.boolean(),
33731
+ external_exports.object({
33732
+ enabled: external_exports.boolean(),
33733
+ // OpenAI GPT-5 and o-series
33734
+ reasoningEffort: external_exports.enum(["minimal", "low", "medium", "high", "xhigh"]).optional(),
33735
+ reasoningSummary: external_exports.enum(["auto", "detailed"]).optional(),
33736
+ // Anthropic Claude
33737
+ budgetTokens: external_exports.number().int().min(1e3).max(1e5).optional(),
33738
+ // Google Gemini
33739
+ thinkingBudget: external_exports.number().int().min(1024).max(65536).optional(),
33740
+ includeThoughts: external_exports.boolean().optional()
33741
+ })
33742
+ ]);
33743
+ var samplingConfigSchema = {
33744
+ topP: external_exports.number().min(0).max(1).optional(),
33745
+ topK: external_exports.number().int().min(1).max(500).optional(),
33746
+ frequencyPenalty: external_exports.number().min(-2).max(2).optional(),
33747
+ presencePenalty: external_exports.number().min(-2).max(2).optional(),
33748
+ seed: external_exports.number().int().optional()
33749
+ };
33750
+ var errorHandlingSchema = external_exports.object({
33751
+ onError: external_exports.enum(["fail", "continue", "fallback"]),
33752
+ fallbacks: external_exports.array(
33753
+ external_exports.discriminatedUnion("type", [
33754
+ external_exports.object({
33755
+ type: external_exports.literal("retry"),
33756
+ delay: external_exports.number().int().min(0).max(6e4).optional()
33757
+ }),
33758
+ external_exports.object({
33759
+ type: external_exports.literal("model"),
33760
+ model: external_exports.string(),
33761
+ temperature: external_exports.number().min(0).max(2).optional(),
33762
+ maxTokens: external_exports.number().int().min(1).optional(),
33763
+ delay: external_exports.number().int().min(0).max(6e4).optional()
33764
+ }),
33765
+ external_exports.object({
33766
+ type: external_exports.literal("message"),
33767
+ message: external_exports.string(),
33768
+ delay: external_exports.number().int().min(0).max(6e4).optional()
33769
+ })
33770
+ ])
33771
+ ).optional(),
33772
+ // Conditions that activate the fallback chain. Mirrors PromptErrorHandling.triggers;
33773
+ // defaults to error-only when omitted.
33774
+ triggers: external_exports.array(external_exports.object({ type: external_exports.enum(["error", "empty-output"]) })).optional()
33775
+ }).optional();
33776
+ var artifactConfigSchema = external_exports.object({
33777
+ enabled: external_exports.literal(true),
33778
+ types: external_exports.array(external_exports.enum(["markdown", "component"])).min(1)
33779
+ });
33780
+ var agentRuntimeConfigSchema = external_exports.object({
33781
+ model: external_exports.string().optional(),
33782
+ systemPrompt: external_exports.string().optional(),
33783
+ temperature: external_exports.number().min(0).max(2).optional(),
33784
+ ...samplingConfigSchema,
33785
+ // Unified tools configuration (nested under 'tools')
33786
+ tools: external_exports.object({
33787
+ toolIds: external_exports.array(external_exports.string()).optional(),
33788
+ toolConfigs: external_exports.record(external_exports.string(), external_exports.record(external_exports.string(), external_exports.unknown())).optional(),
33789
+ runtimeTools: external_exports.array(
33790
+ external_exports.object({
33791
+ name: external_exports.string(),
33792
+ description: external_exports.string(),
33793
+ toolType: external_exports.enum([
33794
+ "flow",
33795
+ "custom",
33796
+ "external",
33797
+ "local",
33798
+ "advisor",
33799
+ "subagent",
33800
+ "search"
33801
+ ]),
33802
+ parametersSchema: external_exports.record(external_exports.string(), external_exports.unknown()),
33803
+ config: external_exports.record(external_exports.string(), external_exports.unknown())
33804
+ })
33805
+ ).optional(),
33806
+ mcpServers: external_exports.array(
33807
+ external_exports.object({
33808
+ id: external_exports.string(),
33809
+ name: external_exports.string().optional(),
33810
+ url: external_exports.string(),
33811
+ auth: external_exports.object({
33812
+ type: external_exports.enum(["api_key", "bearer", "basic", "custom_header", "none"]),
33813
+ headerName: external_exports.string().optional(),
33814
+ token: external_exports.string().optional(),
33815
+ username: external_exports.string().optional(),
33816
+ password: external_exports.string().optional()
33817
+ }).optional(),
33818
+ allowedTools: external_exports.array(external_exports.string()).optional(),
33819
+ timeout: external_exports.number().optional(),
33820
+ transport: external_exports.enum(["streamable_http", "rest"]).optional(),
33821
+ enabled: external_exports.boolean().optional()
33822
+ })
33823
+ ).optional(),
33824
+ maxToolCalls: external_exports.number().int().min(1).max(100).optional(),
33825
+ toolCallStrategy: external_exports.enum(["auto", "required", "none"]).optional(),
33826
+ parallelCalls: external_exports.boolean().optional(),
33827
+ approval: external_exports.object({
33828
+ require: external_exports.union([external_exports.array(external_exports.string()), external_exports.boolean()]),
33829
+ timeout: external_exports.number().optional()
33830
+ }).optional(),
33831
+ perToolLimits: external_exports.record(
33832
+ external_exports.string(),
33833
+ external_exports.object({
33834
+ maxCalls: external_exports.number().optional(),
33835
+ required: external_exports.boolean().optional()
33836
+ })
33837
+ ).optional(),
33838
+ subagentConfig: external_exports.object({
33839
+ toolPool: external_exports.array(external_exports.string()),
33840
+ defaultMaxTurns: external_exports.number().int().min(1).max(100).optional(),
33841
+ maxTurnsLimit: external_exports.number().int().min(1).max(100).optional(),
33842
+ maxSpawnsPerRun: external_exports.number().int().min(1).max(50).optional(),
33843
+ defaultModel: external_exports.string().optional(),
33844
+ allowNesting: external_exports.boolean().optional(),
33845
+ defaultTimeoutMs: external_exports.number().int().min(1e3).max(6e5).optional()
33846
+ }).optional(),
33847
+ codeModeConfig: external_exports.object({
33848
+ toolPool: external_exports.array(external_exports.string()),
33849
+ description: external_exports.string().optional(),
33850
+ timeoutMs: external_exports.number().int().min(1e3).max(6e5).optional()
33851
+ }).optional()
33852
+ }).optional(),
33853
+ artifacts: artifactConfigSchema.optional(),
33854
+ reasoning: reasoningConfigSchema.optional(),
33855
+ advisor: external_exports.object({
33856
+ model: external_exports.string(),
33857
+ systemPrompt: external_exports.string().optional()
33858
+ }).optional().nullable(),
33859
+ loopConfig: external_exports.object({
33860
+ maxTurns: external_exports.number().int().min(1).max(100).optional(),
33861
+ maxCost: external_exports.number().min(0).optional(),
33862
+ enableReflection: external_exports.boolean().optional(),
33863
+ reflectionInterval: external_exports.number().int().min(1).max(50).optional()
33864
+ }).optional(),
33865
+ voice: external_exports.object({
33866
+ enabled: external_exports.boolean().optional(),
33867
+ provider: external_exports.string().optional(),
33868
+ interruptionMode: external_exports.enum(["none", "cancel", "barge-in"]).optional(),
33869
+ elevenLabs: external_exports.object({
33870
+ voiceId: external_exports.string().optional(),
33871
+ modelId: external_exports.string().optional(),
33872
+ stability: external_exports.number().min(0).max(1).optional(),
33873
+ similarity: external_exports.number().min(0).max(1).optional()
33874
+ }).optional()
33875
+ }).optional(),
33876
+ errorHandling: errorHandlingSchema,
33877
+ loggingPolicy: external_exports.enum(["default", "on", "off"]).optional()
33878
+ });
33719
33879
  var SECRET_REF_PATTERN = /\{\{secret:([A-Z][A-Z0-9_]*[A-Z0-9])\}\}/g;
33720
33880
  function extractSecretReferences(template) {
33721
33881
  const keys = /* @__PURE__ */ new Set();
@@ -33750,6 +33910,7 @@ function extractSecretReferencesFromAnyValue(value, maxDepth = 10) {
33750
33910
  }
33751
33911
  var FULL_PRODUCT_OBJECT_VERSION_1_0 = "1.0";
33752
33912
  var FULL_PRODUCT_OBJECT_VERSION_1_1 = "1.1";
33913
+ var FULL_PRODUCT_OBJECT_VERSION_2_0 = "2.0";
33753
33914
  var createPolicySchema = external_exports.enum(["create", "skip", "manual"]).optional();
33754
33915
  var flowStepSchema = external_exports.object({
33755
33916
  type: external_exports.string().refine(
@@ -33928,6 +34089,23 @@ var agentDefinitionSchema = external_exports.object({
33928
34089
  claudeManagedConfig: agentClaudeManagedConfigSchema.optional(),
33929
34090
  createPolicy: createPolicySchema
33930
34091
  });
34092
+ var agentDefinitionSchemaV2 = external_exports.object({
34093
+ name: external_exports.string().min(1),
34094
+ description: external_exports.string().min(1),
34095
+ icon: external_exports.string().max(50).optional(),
34096
+ agentType: external_exports.enum(["runtype", "external", "claude_managed"]).optional(),
34097
+ // Canonical runtime config — identical to `createAgentSchema.config`.
34098
+ config: agentRuntimeConfigSchema.optional(),
34099
+ // FPO-specific wiring, top-level like the flat shape.
34100
+ capabilityToolRefs: external_exports.array(capabilityToolRefSchema).optional(),
34101
+ // External / managed agent configs (top-level, mirroring `createAgent`).
34102
+ externalConfig: agentExternalConfigSchema.optional(),
34103
+ claudeManagedConfig: agentClaudeManagedConfigSchema.optional(),
34104
+ createPolicy: createPolicySchema
34105
+ }).strict();
34106
+ function isNestedFpoAgent(agent) {
34107
+ return !!agent && typeof agent === "object" && "config" in agent && !("model" in agent);
34108
+ }
33931
34109
  var capabilitySchema = external_exports.object({
33932
34110
  id: external_exports.string().min(1),
33933
34111
  name: external_exports.string().min(1),
@@ -33935,7 +34113,12 @@ var capabilitySchema = external_exports.object({
33935
34113
  inputSchema: external_exports.record(external_exports.string(), external_exports.any()).optional(),
33936
34114
  outputSchema: external_exports.record(external_exports.string(), external_exports.any()).optional(),
33937
34115
  flow: flowDefinitionSchema.optional(),
33938
- agent: agentDefinitionSchema.optional(),
34116
+ // Accept BOTH inline-agent shapes. The flat ≤1.1 shape requires a top-level
34117
+ // `model`; the v2 shape is `.strict()` with no top-level `model`. These are
34118
+ // mutually exclusive, so the union routes unambiguously. Version-consistency
34119
+ // (flat ↔ ≤1.1, nested ↔ 2.0) is enforced in `fullProductObjectSchema`'s
34120
+ // superRefine, which has access to the document `version`.
34121
+ agent: external_exports.union([agentDefinitionSchema, agentDefinitionSchemaV2]).optional(),
33939
34122
  existingFlowId: external_exports.string().optional(),
33940
34123
  existingAgentId: external_exports.string().optional()
33941
34124
  }).refine(
@@ -34075,7 +34258,11 @@ var metaSchema = external_exports.object({
34075
34258
  planHash: external_exports.string().min(1)
34076
34259
  });
34077
34260
  var fullProductObjectSchema = external_exports.object({
34078
- version: external_exports.enum([FULL_PRODUCT_OBJECT_VERSION_1_0, FULL_PRODUCT_OBJECT_VERSION_1_1]),
34261
+ version: external_exports.enum([
34262
+ FULL_PRODUCT_OBJECT_VERSION_1_0,
34263
+ FULL_PRODUCT_OBJECT_VERSION_1_1,
34264
+ FULL_PRODUCT_OBJECT_VERSION_2_0
34265
+ ]),
34079
34266
  product: external_exports.object({
34080
34267
  name: external_exports.string().min(1),
34081
34268
  description: external_exports.string().min(1),
@@ -34090,78 +34277,24 @@ var fullProductObjectSchema = external_exports.object({
34090
34277
  secrets: external_exports.array(productSecretSchema).max(50).optional(),
34091
34278
  _meta: metaSchema
34092
34279
  }).superRefine((fpo, ctx) => {
34093
- const capIds = /* @__PURE__ */ new Set();
34280
+ const isV2 = fpo.version === FULL_PRODUCT_OBJECT_VERSION_2_0;
34094
34281
  for (const [i, cap] of fpo.capabilities.entries()) {
34095
- const id = cap.id;
34096
- if (capIds.has(id)) {
34282
+ const agent = cap.agent;
34283
+ if (!agent || typeof agent !== "object") continue;
34284
+ const looksNested = "config" in agent && !("model" in agent);
34285
+ if (isV2 && !looksNested) {
34097
34286
  ctx.addIssue({
34098
34287
  code: "custom",
34099
- message: `Duplicate capability id: ${id}`,
34100
- path: ["capabilities", i, "id"]
34288
+ message: "Version 2.0 requires the nested inline-agent shape: put model/systemPrompt/tools under `agent.config`.",
34289
+ path: ["capabilities", i, "agent"]
34101
34290
  });
34102
- }
34103
- capIds.add(id);
34104
- }
34105
- const toolIds = /* @__PURE__ */ new Set();
34106
- for (const [i, tool] of fpo.tools.entries()) {
34107
- if (toolIds.has(tool.id)) {
34108
- ctx.addIssue({
34109
- code: "custom",
34110
- message: `Duplicate tool id: ${tool.id}`,
34111
- path: ["tools", i, "id"]
34112
- });
34113
- }
34114
- toolIds.add(tool.id);
34115
- }
34116
- const surfaceIds = /* @__PURE__ */ new Set();
34117
- for (const [i, surface] of fpo.surfaces.entries()) {
34118
- if (surfaceIds.has(surface.id)) {
34291
+ } else if (!isV2 && looksNested) {
34119
34292
  ctx.addIssue({
34120
34293
  code: "custom",
34121
- message: `Duplicate surface id: ${surface.id}`,
34122
- path: ["surfaces", i, "id"]
34294
+ message: 'The nested `agent.config` shape requires version "2.0". Use the flat agent shape for version 1.0/1.1, or set version to "2.0".',
34295
+ path: ["capabilities", i, "agent"]
34123
34296
  });
34124
34297
  }
34125
- surfaceIds.add(surface.id);
34126
- }
34127
- if (fpo.records) {
34128
- const recordIds = /* @__PURE__ */ new Set();
34129
- for (const [i, record2] of fpo.records.entries()) {
34130
- if (recordIds.has(record2.id)) {
34131
- ctx.addIssue({
34132
- code: "custom",
34133
- message: `Duplicate record id: ${record2.id}`,
34134
- path: ["records", i, "id"]
34135
- });
34136
- }
34137
- recordIds.add(record2.id);
34138
- }
34139
- }
34140
- if (fpo.schedules) {
34141
- const scheduleIds = /* @__PURE__ */ new Set();
34142
- for (const [i, schedule] of fpo.schedules.entries()) {
34143
- if (scheduleIds.has(schedule.id)) {
34144
- ctx.addIssue({
34145
- code: "custom",
34146
- message: `Duplicate schedule id: ${schedule.id}`,
34147
- path: ["schedules", i, "id"]
34148
- });
34149
- }
34150
- scheduleIds.add(schedule.id);
34151
- }
34152
- }
34153
- if (fpo.secrets) {
34154
- const secretIds = /* @__PURE__ */ new Set();
34155
- for (const [i, secret] of fpo.secrets.entries()) {
34156
- if (secretIds.has(secret.id)) {
34157
- ctx.addIssue({
34158
- code: "custom",
34159
- message: `Duplicate secret id: ${secret.id}`,
34160
- path: ["secrets", i, "id"]
34161
- });
34162
- }
34163
- secretIds.add(secret.id);
34164
- }
34165
34298
  }
34166
34299
  });
34167
34300
  function createIssue(severity, code, message, path16, suggestedFix) {
@@ -34254,6 +34387,29 @@ function validateAgentDefinition(agent, capIndex) {
34254
34387
  createIssue("error", "AGENT_NAME_EMPTY", "Agent name is required", `${base}.name`)
34255
34388
  );
34256
34389
  }
34390
+ if (isNestedFpoAgent(agent)) {
34391
+ validateNestedAgent(agent, base, result);
34392
+ } else {
34393
+ validateFlatAgent(agent, base, result);
34394
+ }
34395
+ if (agent.capabilityToolRefs) {
34396
+ for (const [i, ref] of agent.capabilityToolRefs.entries()) {
34397
+ if (!ref.toolName || ref.toolName.trim() === "") {
34398
+ result.errors.push(
34399
+ createIssue("error", "CAPABILITY_TOOL_REF_NAME_EMPTY", "capabilityToolRefs toolName is required", `${base}.capabilityToolRefs[${i}].toolName`)
34400
+ );
34401
+ }
34402
+ if (!ref.capabilityId || ref.capabilityId.trim() === "") {
34403
+ result.errors.push(
34404
+ createIssue("error", "CAPABILITY_TOOL_REF_ID_EMPTY", "capabilityToolRefs capabilityId is required", `${base}.capabilityToolRefs[${i}].capabilityId`)
34405
+ );
34406
+ }
34407
+ }
34408
+ }
34409
+ result.valid = result.errors.length === 0;
34410
+ return result;
34411
+ }
34412
+ function validateFlatAgent(agent, base, result) {
34257
34413
  if (!agent.model || agent.model.trim() === "") {
34258
34414
  result.errors.push(
34259
34415
  createIssue("error", "AGENT_NO_MODEL", "Agent model is required", `${base}.model`)
@@ -34289,22 +34445,35 @@ function validateAgentDefinition(agent, capIndex) {
34289
34445
  }
34290
34446
  }
34291
34447
  }
34292
- if (agent.capabilityToolRefs) {
34293
- for (const [i, ref] of agent.capabilityToolRefs.entries()) {
34294
- if (!ref.toolName || ref.toolName.trim() === "") {
34448
+ }
34449
+ function validateNestedAgent(agent, base, result) {
34450
+ const config3 = agent.config;
34451
+ if (!config3?.model || config3.model.trim() === "") {
34452
+ result.errors.push(
34453
+ createIssue("error", "AGENT_NO_MODEL", "Agent model is required", `${base}.config.model`)
34454
+ );
34455
+ }
34456
+ if (config3?.advisor) {
34457
+ if (!config3.advisor.model || config3.advisor.model.trim() === "") {
34458
+ result.errors.push(
34459
+ createIssue("error", "AGENT_ADVISOR_NO_MODEL", "Advisor model is required when advisor is configured", `${base}.config.advisor.model`)
34460
+ );
34461
+ }
34462
+ }
34463
+ if (config3?.tools?.runtimeTools) {
34464
+ for (const [i, tool] of config3.tools.runtimeTools.entries()) {
34465
+ if (!tool.name || tool.name.trim() === "") {
34295
34466
  result.errors.push(
34296
- createIssue("error", "CAPABILITY_TOOL_REF_NAME_EMPTY", "capabilityToolRefs toolName is required", `${base}.capabilityToolRefs[${i}].toolName`)
34467
+ createIssue("error", "RUNTIME_TOOL_NAME_EMPTY", "Runtime tool name is required", `${base}.config.tools.runtimeTools[${i}].name`)
34297
34468
  );
34298
34469
  }
34299
- if (!ref.capabilityId || ref.capabilityId.trim() === "") {
34300
- result.errors.push(
34301
- createIssue("error", "CAPABILITY_TOOL_REF_ID_EMPTY", "capabilityToolRefs capabilityId is required", `${base}.capabilityToolRefs[${i}].capabilityId`)
34470
+ if (tool.toolType === "flow" && (!tool.config?.steps || !Array.isArray(tool.config.steps) || tool.config.steps.length === 0)) {
34471
+ result.warnings.push(
34472
+ createIssue("warning", "FLOW_RUNTIME_TOOL_NO_STEPS", "Flow runtime tool should have steps in config", `${base}.config.tools.runtimeTools[${i}].config.steps`)
34302
34473
  );
34303
34474
  }
34304
34475
  }
34305
34476
  }
34306
- result.valid = result.errors.length === 0;
34307
- return result;
34308
34477
  }
34309
34478
  var KEBAB_CASE_RE = /^[a-z0-9]+(-[a-z0-9]+)*$/;
34310
34479
  function validateCapability(cap, index, context) {
@@ -34521,7 +34690,16 @@ function validateConnectivity(fpo) {
34521
34690
  }
34522
34691
  }
34523
34692
  for (const [ci, cap] of fpo.capabilities.entries()) {
34524
- const toolIds = cap.agent?.toolsConfig?.toolIds;
34693
+ const agent = cap.agent;
34694
+ let toolIds;
34695
+ let toolIdsPath;
34696
+ if (isNestedFpoAgent(agent)) {
34697
+ toolIds = agent.config?.tools?.toolIds;
34698
+ toolIdsPath = "config.tools.toolIds";
34699
+ } else {
34700
+ toolIds = agent?.toolsConfig?.toolIds;
34701
+ toolIdsPath = "toolsConfig.toolIds";
34702
+ }
34525
34703
  if (!toolIds) continue;
34526
34704
  for (const [ti, toolId] of toolIds.entries()) {
34527
34705
  if (!toolId.startsWith("capability:")) continue;
@@ -34533,7 +34711,7 @@ function validateConnectivity(fpo) {
34533
34711
  "error",
34534
34712
  "CAPABILITY_TOOLID_REF_NOT_FOUND",
34535
34713
  `toolIds references non-existent capability "${refCapId}"`,
34536
- `capabilities[${ci}].agent.toolsConfig.toolIds[${ti}]`,
34714
+ `capabilities[${ci}].agent.${toolIdsPath}[${ti}]`,
34537
34715
  "Ensure the capability:<id> matches an existing capability"
34538
34716
  )
34539
34717
  );
@@ -34543,7 +34721,7 @@ function validateConnectivity(fpo) {
34543
34721
  "error",
34544
34722
  "CAPABILITY_TOOLID_REF_NOT_FLOW",
34545
34723
  `toolIds references capability "${refCapId}" which is not a flow capability`,
34546
- `capabilities[${ci}].agent.toolsConfig.toolIds[${ti}]`,
34724
+ `capabilities[${ci}].agent.${toolIdsPath}[${ti}]`,
34547
34725
  "capability: refs in toolIds can only reference capabilities backed by a flow"
34548
34726
  )
34549
34727
  );
@@ -34554,7 +34732,7 @@ function validateConnectivity(fpo) {
34554
34732
  "error",
34555
34733
  "CAPABILITY_TOOLID_REF_SELF",
34556
34734
  `toolIds cannot reference the capability's own id "${cap.id}"`,
34557
- `capabilities[${ci}].agent.toolsConfig.toolIds[${ti}]`
34735
+ `capabilities[${ci}].agent.${toolIdsPath}[${ti}]`
34558
34736
  )
34559
34737
  );
34560
34738
  }
@@ -34589,59 +34767,80 @@ function validateConnectivity(fpo) {
34589
34767
  result.valid = result.errors.length === 0;
34590
34768
  return result;
34591
34769
  }
34770
+ function safeValidate(fn) {
34771
+ try {
34772
+ return fn();
34773
+ } catch {
34774
+ return emptyResult();
34775
+ }
34776
+ }
34777
+ function readId(entry) {
34778
+ return entry && typeof entry === "object" ? entry.id : void 0;
34779
+ }
34592
34780
  function validateFPO(fpo) {
34593
34781
  const result = emptyResult();
34594
34782
  const capIds = /* @__PURE__ */ new Set();
34595
34783
  for (const [i, cap] of fpo.capabilities.entries()) {
34596
- if (capIds.has(cap.id)) {
34784
+ const id = readId(cap);
34785
+ if (id === void 0) continue;
34786
+ if (capIds.has(id)) {
34597
34787
  result.errors.push(
34598
- createIssue("error", "DUPLICATE_CAPABILITY_ID", `Duplicate capability id: "${cap.id}"`, `capabilities[${i}].id`)
34788
+ createIssue("error", "DUPLICATE_CAPABILITY_ID", `Duplicate capability id: "${id}"`, `capabilities[${i}].id`)
34599
34789
  );
34600
34790
  }
34601
- capIds.add(cap.id);
34791
+ capIds.add(id);
34602
34792
  }
34603
34793
  const toolIdSet = /* @__PURE__ */ new Set();
34604
34794
  for (const [i, tool] of fpo.tools.entries()) {
34605
- if (toolIdSet.has(tool.id)) {
34795
+ const id = readId(tool);
34796
+ if (id === void 0) continue;
34797
+ if (toolIdSet.has(id)) {
34606
34798
  result.errors.push(
34607
- createIssue("error", "DUPLICATE_TOOL_ID", `Duplicate tool id: "${tool.id}"`, `tools[${i}].id`)
34799
+ createIssue("error", "DUPLICATE_TOOL_ID", `Duplicate tool id: "${id}"`, `tools[${i}].id`)
34608
34800
  );
34609
34801
  }
34610
- toolIdSet.add(tool.id);
34802
+ toolIdSet.add(id);
34611
34803
  }
34612
34804
  const surfaceIds = /* @__PURE__ */ new Set();
34613
34805
  for (const [i, surface] of fpo.surfaces.entries()) {
34614
- if (surfaceIds.has(surface.id)) {
34806
+ const id = readId(surface);
34807
+ if (id === void 0) continue;
34808
+ if (surfaceIds.has(id)) {
34615
34809
  result.errors.push(
34616
- createIssue("error", "DUPLICATE_SURFACE_ID", `Duplicate surface id: "${surface.id}"`, `surfaces[${i}].id`)
34810
+ createIssue("error", "DUPLICATE_SURFACE_ID", `Duplicate surface id: "${id}"`, `surfaces[${i}].id`)
34617
34811
  );
34618
34812
  }
34619
- surfaceIds.add(surface.id);
34813
+ surfaceIds.add(id);
34620
34814
  }
34621
34815
  if (fpo.records) {
34622
34816
  const recordIds = /* @__PURE__ */ new Set();
34623
34817
  for (const [i, record2] of fpo.records.entries()) {
34624
- if (recordIds.has(record2.id)) {
34818
+ const id = readId(record2);
34819
+ if (id === void 0) continue;
34820
+ if (recordIds.has(id)) {
34625
34821
  result.errors.push(
34626
- createIssue("error", "DUPLICATE_RECORD_ID", `Duplicate record id: "${record2.id}"`, `records[${i}].id`)
34822
+ createIssue("error", "DUPLICATE_RECORD_ID", `Duplicate record id: "${id}"`, `records[${i}].id`)
34627
34823
  );
34628
34824
  }
34629
- recordIds.add(record2.id);
34825
+ recordIds.add(id);
34630
34826
  }
34631
34827
  }
34632
- const capIdSet = new Set(fpo.capabilities.map((c) => c.id));
34633
34828
  if (fpo.schedules) {
34634
34829
  const scheduleIds = /* @__PURE__ */ new Set();
34635
34830
  for (const [i, schedule] of fpo.schedules.entries()) {
34636
- if (scheduleIds.has(schedule.id)) {
34637
- result.errors.push(
34638
- createIssue("error", "DUPLICATE_SCHEDULE_ID", `Duplicate schedule id: "${schedule.id}"`, `schedules[${i}].id`)
34639
- );
34831
+ const id = readId(schedule);
34832
+ if (id !== void 0) {
34833
+ if (scheduleIds.has(id)) {
34834
+ result.errors.push(
34835
+ createIssue("error", "DUPLICATE_SCHEDULE_ID", `Duplicate schedule id: "${id}"`, `schedules[${i}].id`)
34836
+ );
34837
+ }
34838
+ scheduleIds.add(id);
34640
34839
  }
34641
- scheduleIds.add(schedule.id);
34642
- if (!capIdSet.has(schedule.capabilityId)) {
34840
+ const capabilityId = schedule && typeof schedule === "object" ? schedule.capabilityId : void 0;
34841
+ if (capabilityId !== void 0 && !capIds.has(capabilityId)) {
34643
34842
  result.errors.push(
34644
- createIssue("error", "SCHEDULE_CAPABILITY_NOT_FOUND", `Schedule "${schedule.id}" references capability "${schedule.capabilityId}" which does not exist`, `schedules[${i}].capabilityId`)
34843
+ createIssue("error", "SCHEDULE_CAPABILITY_NOT_FOUND", `Schedule "${readId(schedule) ?? ""}" references capability "${capabilityId}" which does not exist`, `schedules[${i}].capabilityId`)
34645
34844
  );
34646
34845
  }
34647
34846
  }
@@ -34649,23 +34848,81 @@ function validateFPO(fpo) {
34649
34848
  if (fpo.secrets) {
34650
34849
  const secretIds = /* @__PURE__ */ new Set();
34651
34850
  for (const [i, secret] of fpo.secrets.entries()) {
34652
- if (secretIds.has(secret.id)) {
34851
+ const id = readId(secret);
34852
+ if (id === void 0) continue;
34853
+ if (secretIds.has(id)) {
34653
34854
  result.errors.push(
34654
- createIssue("error", "DUPLICATE_SECRET_ID", `Duplicate secret id: "${secret.id}"`, `secrets[${i}].id`)
34855
+ createIssue("error", "DUPLICATE_SECRET_ID", `Duplicate secret id: "${id}"`, `secrets[${i}].id`)
34655
34856
  );
34656
34857
  }
34657
- secretIds.add(secret.id);
34858
+ secretIds.add(id);
34658
34859
  }
34659
34860
  }
34660
- const toolIds = new Set(fpo.tools.map((t) => t.id));
34861
+ const toolIds = new Set(
34862
+ [...toolIdSet].filter((id) => typeof id === "string")
34863
+ );
34661
34864
  const capResults = fpo.capabilities.map(
34662
- (cap, i) => validateCapability(cap, i, { toolIds })
34865
+ (cap, i) => safeValidate(() => validateCapability(cap, i, { toolIds }))
34866
+ );
34867
+ const toolResults = fpo.tools.map(
34868
+ (tool, i) => safeValidate(() => validateToolDefinition(tool, i))
34869
+ );
34870
+ const surfaceResults = fpo.surfaces.map(
34871
+ (surface, i) => safeValidate(() => validateSurfaceDefinition(surface, i))
34663
34872
  );
34664
- const toolResults = fpo.tools.map((tool, i) => validateToolDefinition(tool, i));
34665
- const surfaceResults = fpo.surfaces.map((surface, i) => validateSurfaceDefinition(surface, i));
34666
- const connectivityResult = validateConnectivity(fpo);
34873
+ const connectivityResult = safeValidate(() => validateConnectivity(fpo));
34667
34874
  return mergeResults(result, ...capResults, ...toolResults, ...surfaceResults, connectivityResult);
34668
34875
  }
34876
+ function zodIssueCodeToValidationCode(code) {
34877
+ return code ? `SCHEMA_${code.toUpperCase()}` : "SCHEMA_ERROR";
34878
+ }
34879
+ function zodIssuesToValidationIssues(issues) {
34880
+ return issues.map(
34881
+ (issue2) => createIssue(
34882
+ "error",
34883
+ zodIssueCodeToValidationCode(issue2.code),
34884
+ issue2.message,
34885
+ issue2.path.map(String).join(".")
34886
+ )
34887
+ );
34888
+ }
34889
+ function zodIssuesToValidationResult(issues) {
34890
+ const result = emptyResult();
34891
+ result.errors.push(...zodIssuesToValidationIssues(issues));
34892
+ result.valid = false;
34893
+ return result;
34894
+ }
34895
+ function mergeZodSchemaAndSemantic(parsed, fallbackSemanticInput, validate) {
34896
+ if (parsed.success) {
34897
+ return validate(parsed.data);
34898
+ }
34899
+ const schemaResult = zodIssuesToValidationResult(parsed.error.issues);
34900
+ if (fallbackSemanticInput === null || fallbackSemanticInput === void 0) {
34901
+ return schemaResult;
34902
+ }
34903
+ let semanticResult;
34904
+ try {
34905
+ semanticResult = validate(fallbackSemanticInput);
34906
+ } catch {
34907
+ semanticResult = emptyResult();
34908
+ }
34909
+ const merged = mergeResults(schemaResult, semanticResult);
34910
+ merged.valid = false;
34911
+ return merged;
34912
+ }
34913
+ function coerceFullProductObjectForSemanticValidation(body) {
34914
+ if (typeof body !== "object" || body === null) return null;
34915
+ const obj = body;
34916
+ return {
34917
+ ...obj,
34918
+ capabilities: Array.isArray(obj.capabilities) ? obj.capabilities : [],
34919
+ tools: Array.isArray(obj.tools) ? obj.tools : [],
34920
+ surfaces: Array.isArray(obj.surfaces) ? obj.surfaces : [],
34921
+ records: Array.isArray(obj.records) ? obj.records : void 0,
34922
+ schedules: Array.isArray(obj.schedules) ? obj.schedules : void 0,
34923
+ secrets: Array.isArray(obj.secrets) ? obj.secrets : void 0
34924
+ };
34925
+ }
34669
34926
  var FULL_PRODUCT_OBJECT_TEMPLATE_VERSION = "1.0";
34670
34927
  var FULL_PRODUCT_OBJECT_TEMPLATE_VERSION_1_1 = "1.1";
34671
34928
  var fpoTemplateVariableInputTypeSchema = external_exports.enum([
@@ -34798,9 +35055,6 @@ function getVariableReferences(template) {
34798
35055
  }
34799
35056
  return references;
34800
35057
  }
34801
- function normalizeValidationPath(path16) {
34802
- return path16.map(String).join(".");
34803
- }
34804
35058
  function coerceFPOTemplateVariableValue(variable, rawValue) {
34805
35059
  if (rawValue === void 0 || rawValue === null || rawValue === "") {
34806
35060
  return void 0;
@@ -34912,11 +35166,7 @@ function validateFPOTemplate(body, options = {}) {
34912
35166
  const parseResult = fullProductObjectTemplateSchema.safeParse(body);
34913
35167
  if (!parseResult.success) {
34914
35168
  const result2 = emptyResult();
34915
- result2.errors.push(
34916
- ...parseResult.error.issues.map(
34917
- (issue2) => createIssue("error", "SCHEMA_ERROR", issue2.message, normalizeValidationPath(issue2.path))
34918
- )
34919
- );
35169
+ result2.errors.push(...zodIssuesToValidationIssues(parseResult.error.issues));
34920
35170
  result2.valid = false;
34921
35171
  return {
34922
35172
  ...result2,
@@ -57634,20 +57884,12 @@ function runValidation(body, kind) {
57634
57884
  }
57635
57885
  const parsed = fullProductObjectSchema.safeParse(body);
57636
57886
  if (!parsed.success) {
57637
- return {
57638
- kind,
57639
- valid: false,
57640
- errors: parsed.error.issues.map(
57641
- (issue2) => ({
57642
- code: "SCHEMA_ERROR",
57643
- message: issue2.message,
57644
- path: issue2.path.map(String).join("."),
57645
- severity: "error"
57646
- })
57647
- ),
57648
- warnings: [],
57649
- recommendations: []
57650
- };
57887
+ const merged = mergeZodSchemaAndSemantic(
57888
+ parsed,
57889
+ coerceFullProductObjectForSemanticValidation(body),
57890
+ validateFPO
57891
+ );
57892
+ return { kind, ...merged };
57651
57893
  }
57652
57894
  return { kind, ...validateFPO(parsed.data) };
57653
57895
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@runtypelabs/cli",
3
- "version": "2.16.3",
3
+ "version": "2.16.5",
4
4
  "description": "Command-line interface for Runtype AI platform",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -22,7 +22,7 @@
22
22
  "rosie-skills": "0.8.1",
23
23
  "yaml": "^2.8.3",
24
24
  "@runtypelabs/ink-components": "0.3.2",
25
- "@runtypelabs/sdk": "4.0.1",
25
+ "@runtypelabs/sdk": "4.0.3",
26
26
  "@runtypelabs/terminal-animations": "0.2.1"
27
27
  },
28
28
  "devDependencies": {
@@ -36,7 +36,7 @@
36
36
  "tsx": "^4.7.1",
37
37
  "typescript": "^5.3.3",
38
38
  "vitest": "^4.1.0",
39
- "@runtypelabs/shared": "1.8.0"
39
+ "@runtypelabs/shared": "1.9.0"
40
40
  },
41
41
  "engines": {
42
42
  "node": ">=22.0.0"