@runtypelabs/sdk 5.8.1 → 5.10.0

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/index.cjs CHANGED
@@ -2125,6 +2125,31 @@ function resolveBatchExecutionId(pausedTools) {
2125
2125
  return "";
2126
2126
  }
2127
2127
 
2128
+ // src/content-hash.ts
2129
+ function isPlainObject(value) {
2130
+ return value !== null && typeof value === "object" && !Array.isArray(value);
2131
+ }
2132
+ function normalizeValue(value) {
2133
+ if (Array.isArray(value)) {
2134
+ return value.map((item) => normalizeValue(item));
2135
+ }
2136
+ if (isPlainObject(value)) {
2137
+ const normalized = {};
2138
+ for (const key of Object.keys(value).sort()) {
2139
+ const entry = value[key];
2140
+ if (entry === void 0 || entry === null) continue;
2141
+ normalized[key] = normalizeValue(entry);
2142
+ }
2143
+ return normalized;
2144
+ }
2145
+ return value;
2146
+ }
2147
+ async function sha256Hex(serialized) {
2148
+ const encoded = new TextEncoder().encode(serialized);
2149
+ const hashBuffer = await crypto.subtle.digest("SHA-256", encoded);
2150
+ return Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
2151
+ }
2152
+
2128
2153
  // src/evals-ensure.ts
2129
2154
  var CHECK_GRADER_KINDS = /* @__PURE__ */ new Set([
2130
2155
  "contains",
@@ -2283,12 +2308,16 @@ function judge(criteria, opts) {
2283
2308
  if (typeof criteria !== "string" || criteria.trim().length === 0) {
2284
2309
  throw new Error("judge() requires non-empty criteria");
2285
2310
  }
2311
+ if (opts?.judgeFlowId !== void 0 && opts.judgeFlowId.trim().length === 0) {
2312
+ throw new Error("judge() requires a non-empty judgeFlowId when one is provided");
2313
+ }
2286
2314
  return gradeable({
2287
2315
  kind: "ai",
2288
2316
  criteria,
2289
2317
  ...opts?.preset ? { preset: opts.preset } : {},
2290
2318
  ...opts?.useExpected ? { useExpected: true } : {},
2291
2319
  ...opts?.model ? { model: opts.model } : {},
2320
+ ...opts?.judgeFlowId ? { judgeFlowId: opts.judgeFlowId } : {},
2292
2321
  ...opts?.threshold !== void 0 ? { threshold: opts.threshold } : {}
2293
2322
  });
2294
2323
  }
@@ -2339,9 +2368,6 @@ var DEFINE_EVAL_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set([
2339
2368
  "virtual"
2340
2369
  ]);
2341
2370
  var DEFINE_EVAL_CASE_KEYS = /* @__PURE__ */ new Set(["name", "input", "expected", "expect"]);
2342
- function isPlainObject(value) {
2343
- return value !== null && typeof value === "object" && !Array.isArray(value);
2344
- }
2345
2371
  function normalizeTarget(target) {
2346
2372
  if (!isPlainObject(target)) {
2347
2373
  throw new Error('defineEval requires a "target" object: { flow: name } or { agent: name }');
@@ -2486,10 +2512,7 @@ async function computeEvalContentHash(definition) {
2486
2512
  expect: c.expect.map((g) => normalizeForHash(g))
2487
2513
  }))
2488
2514
  };
2489
- const serialized = JSON.stringify(canonical);
2490
- const encoded = new TextEncoder().encode(serialized);
2491
- const hashBuffer = await crypto.subtle.digest("SHA-256", encoded);
2492
- return Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
2515
+ return sha256Hex(JSON.stringify(canonical));
2493
2516
  }
2494
2517
  var serverHashMemo = /* @__PURE__ */ new WeakMap();
2495
2518
  function memoFor(client) {
@@ -2536,11 +2559,8 @@ async function runEvalSuite(client, input) {
2536
2559
  }
2537
2560
 
2538
2561
  // src/flows-ensure.ts
2539
- function isPlainObject2(value) {
2540
- return value !== null && typeof value === "object" && !Array.isArray(value);
2541
- }
2542
2562
  function normalizeConfigForHash(config) {
2543
- if (!isPlainObject2(config)) return {};
2563
+ if (!isPlainObject(config)) return {};
2544
2564
  const normalized = {};
2545
2565
  for (const key of Object.keys(config).sort()) {
2546
2566
  const value = config[key];
@@ -2561,7 +2581,7 @@ function normalizeConfigForHash(config) {
2561
2581
  return normalized;
2562
2582
  }
2563
2583
  function normalizeStepForHash(step) {
2564
- const stepObj = isPlainObject2(step) ? step : {};
2584
+ const stepObj = isPlainObject(step) ? step : {};
2565
2585
  return {
2566
2586
  type: typeof stepObj.type === "string" ? stepObj.type : "",
2567
2587
  name: typeof stepObj.name === "string" ? stepObj.name : "",
@@ -2573,14 +2593,11 @@ function normalizeStepForHash(step) {
2573
2593
  }
2574
2594
  async function computeFlowContentHash(steps) {
2575
2595
  const normalized = [...steps].sort((a, b) => {
2576
- const orderA = isPlainObject2(a) && typeof a.order === "number" ? a.order : 0;
2577
- const orderB = isPlainObject2(b) && typeof b.order === "number" ? b.order : 0;
2596
+ const orderA = isPlainObject(a) && typeof a.order === "number" ? a.order : 0;
2597
+ const orderB = isPlainObject(b) && typeof b.order === "number" ? b.order : 0;
2578
2598
  return orderA - orderB;
2579
2599
  }).map(normalizeStepForHash);
2580
- const serialized = JSON.stringify(normalized);
2581
- const encoded = new TextEncoder().encode(serialized);
2582
- const hashBuffer = await crypto.subtle.digest("SHA-256", encoded);
2583
- return Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
2600
+ return sha256Hex(JSON.stringify(normalized));
2584
2601
  }
2585
2602
  var DEFINE_FLOW_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set(["name", "steps", "evals"]);
2586
2603
  var DEFINE_FLOW_STEP_KEYS = /* @__PURE__ */ new Set([
@@ -2603,27 +2620,27 @@ function collectStepNonPortableToolRefs(config, path) {
2603
2620
  });
2604
2621
  };
2605
2622
  const scanKeys = (value, subPath) => {
2606
- if (!isPlainObject2(value)) return;
2623
+ if (!isPlainObject(value)) return;
2607
2624
  for (const key of Object.keys(value)) {
2608
2625
  if (isAccountScoped(key)) found.push(`${subPath}.${key}`);
2609
2626
  }
2610
2627
  };
2611
- if (isPlainObject2(tools)) {
2628
+ if (isPlainObject(tools)) {
2612
2629
  scanArray(tools.toolIds, `${path}.tools.toolIds`);
2613
2630
  scanKeys(tools.toolConfigs, `${path}.tools.toolConfigs`);
2614
2631
  scanKeys(tools.perToolLimits, `${path}.tools.perToolLimits`);
2615
- if (isPlainObject2(tools.approval)) {
2632
+ if (isPlainObject(tools.approval)) {
2616
2633
  scanArray(tools.approval.require, `${path}.tools.approval.require`);
2617
2634
  }
2618
- if (isPlainObject2(tools.subagentConfig)) {
2635
+ if (isPlainObject(tools.subagentConfig)) {
2619
2636
  scanArray(tools.subagentConfig.toolPool, `${path}.tools.subagentConfig.toolPool`);
2620
2637
  }
2621
- if (isPlainObject2(tools.codeModeConfig)) {
2638
+ if (isPlainObject(tools.codeModeConfig)) {
2622
2639
  scanArray(tools.codeModeConfig.toolPool, `${path}.tools.codeModeConfig.toolPool`);
2623
2640
  }
2624
2641
  if (Array.isArray(tools.runtimeTools)) {
2625
2642
  tools.runtimeTools.forEach((runtimeTool, i) => {
2626
- if (!isPlainObject2(runtimeTool) || !isPlainObject2(runtimeTool.config)) return;
2643
+ if (!isPlainObject(runtimeTool) || !isPlainObject(runtimeTool.config)) return;
2627
2644
  const base = `${path}.tools.runtimeTools[${i}].config`;
2628
2645
  const rtConfig = runtimeTool.config;
2629
2646
  if (runtimeTool.toolType === "subagent" && isRawId(rtConfig.agentId, "agent_")) {
@@ -2644,7 +2661,7 @@ function collectStepNonPortableToolRefs(config, path) {
2644
2661
  const nested = config[branch];
2645
2662
  if (!Array.isArray(nested)) continue;
2646
2663
  nested.forEach((nestedStep, i) => {
2647
- if (isPlainObject2(nestedStep) && isPlainObject2(nestedStep.config)) {
2664
+ if (isPlainObject(nestedStep) && isPlainObject(nestedStep.config)) {
2648
2665
  found.push(
2649
2666
  ...collectStepNonPortableToolRefs(nestedStep.config, `${path}.${branch}[${i}].config`)
2650
2667
  );
@@ -2670,7 +2687,7 @@ function defineFlow(input) {
2670
2687
  throw new Error('defineFlow requires a non-empty "steps" array');
2671
2688
  }
2672
2689
  const steps = input.steps.map((step, index) => {
2673
- if (!isPlainObject2(step)) {
2690
+ if (!isPlainObject(step)) {
2674
2691
  throw new Error(`defineFlow: steps[${index}] must be an object`);
2675
2692
  }
2676
2693
  if (typeof step.type !== "string" || step.type.length === 0) {
@@ -2685,7 +2702,7 @@ function defineFlow(input) {
2685
2702
  `defineFlow: steps[${index}] has unknown field(s): ${unknownStepKeys.join(", ")}. Allowed step fields are type, name, order, enabled, when, config. (Step ids are server artifacts and not part of a portable definition.)`
2686
2703
  );
2687
2704
  }
2688
- const config = isPlainObject2(step.config) ? step.config : void 0;
2705
+ const config = isPlainObject(step.config) ? step.config : void 0;
2689
2706
  if (config) {
2690
2707
  const nonPortable = collectStepNonPortableToolRefs(config, `steps[${index}].config`);
2691
2708
  if (nonPortable.length > 0) {
@@ -2712,7 +2729,7 @@ function defineFlow(input) {
2712
2729
  }
2713
2730
  const seenEvalNames = /* @__PURE__ */ new Set();
2714
2731
  evals = input.evals.map((evalInput, i) => {
2715
- if (!isPlainObject2(evalInput)) {
2732
+ if (!isPlainObject(evalInput)) {
2716
2733
  throw new Error(`defineFlow: evals[${i}] must be an object`);
2717
2734
  }
2718
2735
  if (evalInput.virtual === true) {
@@ -2776,7 +2793,7 @@ function parseRequestError(err) {
2776
2793
  }
2777
2794
  function toConflictError(err) {
2778
2795
  const { status, body } = parseRequestError(err);
2779
- if (status !== 409 || !isPlainObject2(body)) return null;
2796
+ if (status !== 409 || !isPlainObject(body)) return null;
2780
2797
  const code = body.code;
2781
2798
  if (code !== "external_modification" && code !== "remote_changed") return null;
2782
2799
  return new FlowEnsureConflictError(
@@ -4071,6 +4088,18 @@ var EvalSuitesNamespace = class {
4071
4088
  cases
4072
4089
  });
4073
4090
  }
4091
+ /**
4092
+ * Capture a test case from a real agent run ("fork here and test the next
4093
+ * step"): freezes the run's conversation history up to a fork point, attaches
4094
+ * every recorded tool result as an editable mock, and saves it with origin
4095
+ * `saved_from_run`. Capture only — reads the run, never re-executes it.
4096
+ */
4097
+ async addCaseFromExecution(suiteId, input) {
4098
+ return this.getClient().post(
4099
+ `/eval/suites/${suiteId}/cases/from-execution`,
4100
+ input
4101
+ );
4102
+ }
4074
4103
  /** Edit, enable, or disable a test case. */
4075
4104
  async updateCase(suiteId, caseId, input) {
4076
4105
  return this.getClient().patch(
@@ -4257,6 +4286,30 @@ var EvalsNamespace = class {
4257
4286
  async pull(name) {
4258
4287
  return pullEval(this.getClient(), name);
4259
4288
  }
4289
+ /**
4290
+ * Split one plain-language AI-grader criterion carrying several obligations
4291
+ * into focused, independently judgeable sub-checks. Authoring assist only:
4292
+ * nothing is persisted — review the proposal, then save each accepted
4293
+ * sub-check as its own AI grader row. A single returned sub-check means the
4294
+ * criterion is already focused.
4295
+ *
4296
+ * @example
4297
+ * ```typescript
4298
+ * const { subChecks } = await Runtype.evals.decomposeCriteria(
4299
+ * 'Confirms the order number before issuing a refund, and never promises a delivery date.'
4300
+ * )
4301
+ * // In a defineEval suite, each accepted sub-check becomes its own judge row:
4302
+ * const graders = subChecks.map((s) => judge(s.criteria))
4303
+ * ```
4304
+ */
4305
+ async decomposeCriteria(criteria) {
4306
+ if (typeof criteria !== "string" || criteria.trim().length === 0) {
4307
+ throw new Error("decomposeCriteria() requires non-empty criteria");
4308
+ }
4309
+ return this.getClient().post("/eval/graders/decompose", {
4310
+ criteria
4311
+ });
4312
+ }
4260
4313
  /**
4261
4314
  * Run an eval suite synchronously and return the suite score + per-case grader
4262
4315
  * outcomes — the executing counterpart of `ensure`, powering the `runtype
@@ -4409,42 +4462,21 @@ var PromptsNamespace = class {
4409
4462
  };
4410
4463
 
4411
4464
  // src/skills-ensure.ts
4412
- function isPlainObject3(value) {
4413
- return value !== null && typeof value === "object" && !Array.isArray(value);
4414
- }
4415
- function normalizeValue(value) {
4416
- if (Array.isArray(value)) {
4417
- return value.map((item) => normalizeValue(item));
4418
- }
4419
- if (isPlainObject3(value)) {
4420
- const normalized = {};
4421
- for (const key of Object.keys(value).sort()) {
4422
- const entry = value[key];
4423
- if (entry === void 0 || entry === null) continue;
4424
- normalized[key] = normalizeValue(entry);
4425
- }
4426
- return normalized;
4427
- }
4428
- return value;
4429
- }
4430
4465
  function normalizeSkillDefinition(definition) {
4431
- const manifest = isPlainObject3(definition.manifest) ? definition.manifest : {};
4432
- const rawFrontmatter = isPlainObject3(manifest.frontmatter) ? manifest.frontmatter : {};
4466
+ const manifest = isPlainObject(definition.manifest) ? definition.manifest : {};
4467
+ const rawFrontmatter = isPlainObject(manifest.frontmatter) ? manifest.frontmatter : {};
4433
4468
  const frontmatterWithoutName = {};
4434
4469
  for (const key of Object.keys(rawFrontmatter)) {
4435
4470
  if (key === "name") continue;
4436
4471
  frontmatterWithoutName[key] = rawFrontmatter[key];
4437
4472
  }
4438
4473
  const frontmatter = normalizeValue(frontmatterWithoutName);
4439
- const runtype = isPlainObject3(manifest.runtype) ? normalizeValue(manifest.runtype) : {};
4474
+ const runtype = isPlainObject(manifest.runtype) ? normalizeValue(manifest.runtype) : {};
4440
4475
  const body = typeof manifest.body === "string" ? manifest.body : "";
4441
4476
  return { frontmatter, runtype, body };
4442
4477
  }
4443
4478
  async function computeSkillContentHash(definition) {
4444
- const serialized = JSON.stringify(normalizeSkillDefinition(definition));
4445
- const encoded = new TextEncoder().encode(serialized);
4446
- const hashBuffer = await crypto.subtle.digest("SHA-256", encoded);
4447
- return Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
4479
+ return sha256Hex(JSON.stringify(normalizeSkillDefinition(definition)));
4448
4480
  }
4449
4481
  var DEFINE_SKILL_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set(["name", "manifest"]);
4450
4482
  function defineSkill(input) {
@@ -4454,7 +4486,7 @@ function defineSkill(input) {
4454
4486
  if (typeof input.name !== "string" || input.name.length === 0) {
4455
4487
  throw new Error('defineSkill requires a non-empty string "name"');
4456
4488
  }
4457
- if (!isPlainObject3(input.manifest)) {
4489
+ if (!isPlainObject(input.manifest)) {
4458
4490
  throw new Error('defineSkill requires a "manifest" object ({ frontmatter, runtype, body })');
4459
4491
  }
4460
4492
  const unknownKeys = Object.keys(input).filter((key) => !DEFINE_SKILL_TOP_LEVEL_KEYS.has(key));
@@ -4464,7 +4496,7 @@ function defineSkill(input) {
4464
4496
  );
4465
4497
  }
4466
4498
  const frontmatter = input.manifest.frontmatter;
4467
- if (!isPlainObject3(frontmatter) || typeof frontmatter.name !== "string") {
4499
+ if (!isPlainObject(frontmatter) || typeof frontmatter.name !== "string") {
4468
4500
  throw new Error("defineSkill: manifest.frontmatter.name is required");
4469
4501
  }
4470
4502
  if (frontmatter.name !== input.name) {
@@ -4505,7 +4537,7 @@ function parseRequestError2(err) {
4505
4537
  }
4506
4538
  function toConflictError2(err) {
4507
4539
  const { status, body } = parseRequestError2(err);
4508
- if (status !== 409 || !isPlainObject3(body)) return null;
4540
+ if (status !== 409 || !isPlainObject(body)) return null;
4509
4541
  const code = body.code;
4510
4542
  if (code !== "external_modification" && code !== "remote_changed") return null;
4511
4543
  return new SkillEnsureConflictError(
@@ -4854,14 +4886,14 @@ var AGENT_CONFIG_KEYS = [
4854
4886
  "tenancyStrategy"
4855
4887
  ];
4856
4888
  var AGENT_CONFIG_KEY_LIST = [...AGENT_CONFIG_KEYS].sort();
4857
- function isPlainObject4(value) {
4889
+ function isPlainObject2(value) {
4858
4890
  return value !== null && typeof value === "object" && !Array.isArray(value);
4859
4891
  }
4860
4892
  function normalizeValue2(value) {
4861
4893
  if (Array.isArray(value)) {
4862
4894
  return value.map((item) => normalizeValue2(item));
4863
4895
  }
4864
- if (isPlainObject4(value)) {
4896
+ if (isPlainObject2(value)) {
4865
4897
  const normalized = {};
4866
4898
  for (const key of Object.keys(value).sort()) {
4867
4899
  const entry = value[key];
@@ -4874,7 +4906,7 @@ function normalizeValue2(value) {
4874
4906
  }
4875
4907
  function normalizeAgentDefinition(definition) {
4876
4908
  const config = {};
4877
- const rawConfig = isPlainObject4(definition.config) ? definition.config : {};
4909
+ const rawConfig = isPlainObject2(definition.config) ? definition.config : {};
4878
4910
  for (const key of AGENT_CONFIG_KEY_LIST) {
4879
4911
  const value = rawConfig[key];
4880
4912
  if (value === void 0 || value === null) continue;
@@ -4896,7 +4928,7 @@ async function computeAgentContentHash(definition) {
4896
4928
  var DEFINE_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set(["name", "description", "icon", ...AGENT_CONFIG_KEYS]);
4897
4929
  function collectNonPortableToolRefs(config) {
4898
4930
  const tools = config.tools;
4899
- if (!isPlainObject4(tools)) return [];
4931
+ if (!isPlainObject2(tools)) return [];
4900
4932
  const found = [];
4901
4933
  const isAccountScoped = (ref) => typeof ref === "string" && ref.startsWith("tool_");
4902
4934
  const scanArray = (value, path) => {
@@ -4906,7 +4938,7 @@ function collectNonPortableToolRefs(config) {
4906
4938
  });
4907
4939
  };
4908
4940
  const scanKeys = (value, path) => {
4909
- if (!isPlainObject4(value)) return;
4941
+ if (!isPlainObject2(value)) return;
4910
4942
  for (const key of Object.keys(value)) {
4911
4943
  if (isAccountScoped(key)) found.push(`${path}.${key}`);
4912
4944
  }
@@ -4914,16 +4946,16 @@ function collectNonPortableToolRefs(config) {
4914
4946
  scanArray(tools.toolIds, "tools.toolIds");
4915
4947
  scanKeys(tools.toolConfigs, "tools.toolConfigs");
4916
4948
  scanKeys(tools.perToolLimits, "tools.perToolLimits");
4917
- if (isPlainObject4(tools.approval)) scanArray(tools.approval.require, "tools.approval.require");
4918
- if (isPlainObject4(tools.subagentConfig)) {
4949
+ if (isPlainObject2(tools.approval)) scanArray(tools.approval.require, "tools.approval.require");
4950
+ if (isPlainObject2(tools.subagentConfig)) {
4919
4951
  scanArray(tools.subagentConfig.toolPool, "tools.subagentConfig.toolPool");
4920
4952
  }
4921
- if (isPlainObject4(tools.codeModeConfig)) {
4953
+ if (isPlainObject2(tools.codeModeConfig)) {
4922
4954
  scanArray(tools.codeModeConfig.toolPool, "tools.codeModeConfig.toolPool");
4923
4955
  }
4924
4956
  if (Array.isArray(tools.runtimeTools)) {
4925
4957
  tools.runtimeTools.forEach((runtimeTool, i) => {
4926
- if (!isPlainObject4(runtimeTool) || !isPlainObject4(runtimeTool.config)) return;
4958
+ if (!isPlainObject2(runtimeTool) || !isPlainObject2(runtimeTool.config)) return;
4927
4959
  const base = `tools.runtimeTools[${i}].config`;
4928
4960
  const rtConfig = runtimeTool.config;
4929
4961
  if (runtimeTool.toolType === "subagent" && typeof rtConfig.agentId === "string" && rtConfig.agentId.startsWith("agent_")) {
@@ -4997,7 +5029,7 @@ function parseRequestError3(err) {
4997
5029
  }
4998
5030
  function toConflictError3(err) {
4999
5031
  const { status, body } = parseRequestError3(err);
5000
- if (status !== 409 || !isPlainObject4(body)) return null;
5032
+ if (status !== 409 || !isPlainObject2(body)) return null;
5001
5033
  const code = body.code;
5002
5034
  if (code !== "external_modification" && code !== "remote_changed") return null;
5003
5035
  return new AgentEnsureConflictError(
@@ -5099,27 +5131,9 @@ var AgentsNamespace = class {
5099
5131
  };
5100
5132
 
5101
5133
  // src/tools-ensure.ts
5102
- function isPlainObject5(value) {
5103
- return value !== null && typeof value === "object" && !Array.isArray(value);
5104
- }
5105
- function normalizeValue3(value) {
5106
- if (Array.isArray(value)) {
5107
- return value.map((item) => normalizeValue3(item));
5108
- }
5109
- if (isPlainObject5(value)) {
5110
- const normalized = {};
5111
- for (const key of Object.keys(value).sort()) {
5112
- const entry = value[key];
5113
- if (entry === void 0 || entry === null) continue;
5114
- normalized[key] = normalizeValue3(entry);
5115
- }
5116
- return normalized;
5117
- }
5118
- return value;
5119
- }
5120
5134
  function normalizeToolDefinition(definition) {
5121
- const parametersSchema = isPlainObject5(definition.parametersSchema) ? normalizeValue3(definition.parametersSchema) : {};
5122
- const config = isPlainObject5(definition.config) ? normalizeValue3(definition.config) : {};
5135
+ const parametersSchema = isPlainObject(definition.parametersSchema) ? normalizeValue(definition.parametersSchema) : {};
5136
+ const config = isPlainObject(definition.config) ? normalizeValue(definition.config) : {};
5123
5137
  return {
5124
5138
  toolType: definition.toolType,
5125
5139
  ...definition.description ? { description: definition.description } : {},
@@ -5128,10 +5142,7 @@ function normalizeToolDefinition(definition) {
5128
5142
  };
5129
5143
  }
5130
5144
  async function computeToolContentHash(definition) {
5131
- const serialized = JSON.stringify(normalizeToolDefinition(definition));
5132
- const encoded = new TextEncoder().encode(serialized);
5133
- const hashBuffer = await crypto.subtle.digest("SHA-256", encoded);
5134
- return Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
5145
+ return sha256Hex(JSON.stringify(normalizeToolDefinition(definition)));
5135
5146
  }
5136
5147
  var DEFINE_TOOL_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set([
5137
5148
  "name",
@@ -5164,10 +5175,10 @@ function defineTool(input) {
5164
5175
  `defineTool requires "toolType" to be one of: ${[...TOOL_DEFINITION_TYPES].join(", ")}`
5165
5176
  );
5166
5177
  }
5167
- if (!isPlainObject5(input.parametersSchema)) {
5178
+ if (!isPlainObject(input.parametersSchema)) {
5168
5179
  throw new Error('defineTool requires a "parametersSchema" object (a JSON Schema)');
5169
5180
  }
5170
- if (!isPlainObject5(input.config)) {
5181
+ if (!isPlainObject(input.config)) {
5171
5182
  throw new Error('defineTool requires a "config" object');
5172
5183
  }
5173
5184
  const unknownKeys = Object.keys(input).filter((key) => !DEFINE_TOOL_TOP_LEVEL_KEYS.has(key));
@@ -5215,7 +5226,7 @@ function parseRequestError4(err) {
5215
5226
  }
5216
5227
  function toConflictError4(err) {
5217
5228
  const { status, body } = parseRequestError4(err);
5218
- if (status !== 409 || !isPlainObject5(body)) return null;
5229
+ if (status !== 409 || !isPlainObject(body)) return null;
5219
5230
  const code = body.code;
5220
5231
  if (code !== "external_modification" && code !== "remote_changed") return null;
5221
5232
  return new ToolEnsureConflictError(
@@ -5335,26 +5346,8 @@ var ToolsNamespace = class {
5335
5346
  };
5336
5347
 
5337
5348
  // src/products-ensure.ts
5338
- function isPlainObject6(value) {
5339
- return value !== null && typeof value === "object" && !Array.isArray(value);
5340
- }
5341
- function normalizeValue4(value) {
5342
- if (Array.isArray(value)) {
5343
- return value.map((item) => normalizeValue4(item));
5344
- }
5345
- if (isPlainObject6(value)) {
5346
- const normalized = {};
5347
- for (const key of Object.keys(value).sort()) {
5348
- const entry = value[key];
5349
- if (entry === void 0 || entry === null) continue;
5350
- normalized[key] = normalizeValue4(entry);
5351
- }
5352
- return normalized;
5353
- }
5354
- return value;
5355
- }
5356
5349
  function normalizeProductDefinition(definition) {
5357
- const spec = isPlainObject6(definition.spec) ? normalizeValue4(definition.spec) : {};
5350
+ const spec = isPlainObject(definition.spec) ? normalizeValue(definition.spec) : {};
5358
5351
  return {
5359
5352
  ...definition.description ? { description: definition.description } : {},
5360
5353
  ...definition.icon ? { icon: definition.icon } : {},
@@ -5362,10 +5355,7 @@ function normalizeProductDefinition(definition) {
5362
5355
  };
5363
5356
  }
5364
5357
  async function computeProductContentHash(definition) {
5365
- const serialized = JSON.stringify(normalizeProductDefinition(definition));
5366
- const encoded = new TextEncoder().encode(serialized);
5367
- const hashBuffer = await crypto.subtle.digest("SHA-256", encoded);
5368
- return Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
5358
+ return sha256Hex(JSON.stringify(normalizeProductDefinition(definition)));
5369
5359
  }
5370
5360
  var DEFINE_PRODUCT_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set(["name", "description", "icon", "spec"]);
5371
5361
  function defineProduct(input) {
@@ -5381,7 +5371,7 @@ function defineProduct(input) {
5381
5371
  if (input.icon != null && typeof input.icon !== "string") {
5382
5372
  throw new Error('defineProduct "icon" must be a string when provided');
5383
5373
  }
5384
- if (input.spec != null && !isPlainObject6(input.spec)) {
5374
+ if (input.spec != null && !isPlainObject(input.spec)) {
5385
5375
  throw new Error('defineProduct "spec" must be an object when provided');
5386
5376
  }
5387
5377
  const unknownKeys = Object.keys(input).filter((key) => !DEFINE_PRODUCT_TOP_LEVEL_KEYS.has(key));
@@ -5428,7 +5418,7 @@ function parseRequestError5(err) {
5428
5418
  }
5429
5419
  function toConflictError5(err) {
5430
5420
  const { status, body } = parseRequestError5(err);
5431
- if (status !== 409 || !isPlainObject6(body)) return null;
5421
+ if (status !== 409 || !isPlainObject(body)) return null;
5432
5422
  const code = body.code;
5433
5423
  if (code !== "external_modification" && code !== "remote_changed") return null;
5434
5424
  return new ProductEnsureConflictError(
@@ -5509,50 +5499,29 @@ async function pullProduct(client, name) {
5509
5499
  }
5510
5500
 
5511
5501
  // src/products-ensure-fpo.ts
5512
- function isPlainObject7(value) {
5513
- return value !== null && typeof value === "object" && !Array.isArray(value);
5514
- }
5515
- function normalizeValue5(value) {
5516
- if (Array.isArray(value)) {
5517
- return value.map((item) => normalizeValue5(item));
5518
- }
5519
- if (isPlainObject7(value)) {
5520
- const normalized = {};
5521
- for (const key of Object.keys(value).sort()) {
5522
- const entry = value[key];
5523
- if (entry === void 0 || entry === null) continue;
5524
- normalized[key] = normalizeValue5(entry);
5525
- }
5526
- return normalized;
5527
- }
5528
- return value;
5529
- }
5530
5502
  function normalizeFpoDefinition(fpo) {
5531
- const productInput = isPlainObject7(fpo.product) ? fpo.product : {};
5503
+ const productInput = isPlainObject(fpo.product) ? fpo.product : {};
5532
5504
  const { name: _identityName, ...productRest } = productInput;
5533
- const product = normalizeValue5(productRest);
5505
+ const product = normalizeValue(productRest);
5534
5506
  return {
5535
- ...fpo.version !== void 0 && fpo.version !== null ? { version: normalizeValue5(fpo.version) } : {},
5507
+ ...fpo.version !== void 0 && fpo.version !== null ? { version: normalizeValue(fpo.version) } : {},
5536
5508
  product,
5537
- capabilities: normalizeValue5(fpo.capabilities ?? []),
5538
- tools: normalizeValue5(fpo.tools ?? []),
5539
- surfaces: normalizeValue5(fpo.surfaces ?? []),
5540
- ...fpo.records !== void 0 && fpo.records !== null ? { records: normalizeValue5(fpo.records) } : {},
5541
- ...fpo.schedules !== void 0 && fpo.schedules !== null ? { schedules: normalizeValue5(fpo.schedules) } : {},
5542
- ...fpo.secrets !== void 0 && fpo.secrets !== null ? { secrets: normalizeValue5(fpo.secrets) } : {}
5509
+ capabilities: normalizeValue(fpo.capabilities ?? []),
5510
+ tools: normalizeValue(fpo.tools ?? []),
5511
+ surfaces: normalizeValue(fpo.surfaces ?? []),
5512
+ ...fpo.records !== void 0 && fpo.records !== null ? { records: normalizeValue(fpo.records) } : {},
5513
+ ...fpo.schedules !== void 0 && fpo.schedules !== null ? { schedules: normalizeValue(fpo.schedules) } : {},
5514
+ ...fpo.secrets !== void 0 && fpo.secrets !== null ? { secrets: normalizeValue(fpo.secrets) } : {}
5543
5515
  };
5544
5516
  }
5545
5517
  async function computeFpoContentHash(fpo) {
5546
- const serialized = JSON.stringify(normalizeFpoDefinition(fpo));
5547
- const encoded = new TextEncoder().encode(serialized);
5548
- const hashBuffer = await crypto.subtle.digest("SHA-256", encoded);
5549
- return Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
5518
+ return sha256Hex(JSON.stringify(normalizeFpoDefinition(fpo)));
5550
5519
  }
5551
5520
  function defineFpo(fpo) {
5552
- if (!isPlainObject7(fpo)) {
5521
+ if (!isPlainObject(fpo)) {
5553
5522
  throw new Error("defineFpo requires an FPO object");
5554
5523
  }
5555
- const product = isPlainObject7(fpo.product) ? fpo.product : void 0;
5524
+ const product = isPlainObject(fpo.product) ? fpo.product : void 0;
5556
5525
  if (!product || typeof product.name !== "string" || product.name.length === 0) {
5557
5526
  throw new Error('defineFpo requires a non-empty "product.name" (the converge identity)');
5558
5527
  }
@@ -5648,26 +5617,8 @@ var ProductsNamespace = class {
5648
5617
  };
5649
5618
 
5650
5619
  // src/surfaces-ensure.ts
5651
- function isPlainObject8(value) {
5652
- return value !== null && typeof value === "object" && !Array.isArray(value);
5653
- }
5654
- function normalizeValue6(value) {
5655
- if (Array.isArray(value)) {
5656
- return value.map((item) => normalizeValue6(item));
5657
- }
5658
- if (isPlainObject8(value)) {
5659
- const normalized = {};
5660
- for (const key of Object.keys(value).sort()) {
5661
- const entry = value[key];
5662
- if (entry === void 0 || entry === null) continue;
5663
- normalized[key] = normalizeValue6(entry);
5664
- }
5665
- return normalized;
5666
- }
5667
- return value;
5668
- }
5669
5620
  function normalizeSurfaceDefinition(definition) {
5670
- const behavior = isPlainObject8(definition.behavior) ? normalizeValue6({ type: definition.type, ...definition.behavior }) : { type: definition.type };
5621
+ const behavior = isPlainObject(definition.behavior) ? normalizeValue({ type: definition.type, ...definition.behavior }) : { type: definition.type };
5671
5622
  return {
5672
5623
  type: definition.type,
5673
5624
  behavior,
@@ -5676,10 +5627,7 @@ function normalizeSurfaceDefinition(definition) {
5676
5627
  };
5677
5628
  }
5678
5629
  async function computeSurfaceContentHash(definition) {
5679
- const serialized = JSON.stringify(normalizeSurfaceDefinition(definition));
5680
- const encoded = new TextEncoder().encode(serialized);
5681
- const hashBuffer = await crypto.subtle.digest("SHA-256", encoded);
5682
- return Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
5630
+ return sha256Hex(JSON.stringify(normalizeSurfaceDefinition(definition)));
5683
5631
  }
5684
5632
  var DEFINE_SURFACE_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set([
5685
5633
  "name",
@@ -5720,13 +5668,13 @@ function defineSurface(input) {
5720
5668
  `defineSurface requires "type" to be one of: ${[...SURFACE_DEFINITION_TYPES].join(", ")}`
5721
5669
  );
5722
5670
  }
5723
- if (input.behavior !== void 0 && !isPlainObject8(input.behavior)) {
5671
+ if (input.behavior !== void 0 && !isPlainObject(input.behavior)) {
5724
5672
  throw new Error('defineSurface "behavior" must be an object when provided');
5725
5673
  }
5726
- if (input.inbound !== void 0 && !isPlainObject8(input.inbound)) {
5674
+ if (input.inbound !== void 0 && !isPlainObject(input.inbound)) {
5727
5675
  throw new Error('defineSurface "inbound" must be an object when provided');
5728
5676
  }
5729
- if (input.outbound !== void 0 && !isPlainObject8(input.outbound)) {
5677
+ if (input.outbound !== void 0 && !isPlainObject(input.outbound)) {
5730
5678
  throw new Error('defineSurface "outbound" must be an object when provided');
5731
5679
  }
5732
5680
  if (input.status !== void 0 && !["draft", "active", "paused"].includes(input.status)) {
@@ -5782,7 +5730,7 @@ function parseRequestError6(err) {
5782
5730
  }
5783
5731
  function toConflictError6(err) {
5784
5732
  const { status, body } = parseRequestError6(err);
5785
- if (status !== 409 || !isPlainObject8(body)) return null;
5733
+ if (status !== 409 || !isPlainObject(body)) return null;
5786
5734
  const code = body.code;
5787
5735
  if (code !== "external_modification" && code !== "remote_changed") return null;
5788
5736
  return new SurfaceEnsureConflictError(
@@ -6395,7 +6343,7 @@ var Runtype = class {
6395
6343
 
6396
6344
  // src/version.ts
6397
6345
  var FALLBACK_VERSION = "0.0.0";
6398
- var SDK_VERSION = "5.8.1".length > 0 ? "5.8.1" : FALLBACK_VERSION;
6346
+ var SDK_VERSION = "5.10.0".length > 0 ? "5.10.0" : FALLBACK_VERSION;
6399
6347
  var RUNTYPE_CLIENT_KIND = "sdk";
6400
6348
  var SDK_USER_AGENT = `runtype-sdk/${SDK_VERSION} (typescript)`;
6401
6349