@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.mjs CHANGED
@@ -1938,6 +1938,31 @@ function resolveBatchExecutionId(pausedTools) {
1938
1938
  return "";
1939
1939
  }
1940
1940
 
1941
+ // src/content-hash.ts
1942
+ function isPlainObject(value) {
1943
+ return value !== null && typeof value === "object" && !Array.isArray(value);
1944
+ }
1945
+ function normalizeValue(value) {
1946
+ if (Array.isArray(value)) {
1947
+ return value.map((item) => normalizeValue(item));
1948
+ }
1949
+ if (isPlainObject(value)) {
1950
+ const normalized = {};
1951
+ for (const key of Object.keys(value).sort()) {
1952
+ const entry = value[key];
1953
+ if (entry === void 0 || entry === null) continue;
1954
+ normalized[key] = normalizeValue(entry);
1955
+ }
1956
+ return normalized;
1957
+ }
1958
+ return value;
1959
+ }
1960
+ async function sha256Hex(serialized) {
1961
+ const encoded = new TextEncoder().encode(serialized);
1962
+ const hashBuffer = await crypto.subtle.digest("SHA-256", encoded);
1963
+ return Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
1964
+ }
1965
+
1941
1966
  // src/evals-ensure.ts
1942
1967
  var CHECK_GRADER_KINDS = /* @__PURE__ */ new Set([
1943
1968
  "contains",
@@ -2096,12 +2121,16 @@ function judge(criteria, opts) {
2096
2121
  if (typeof criteria !== "string" || criteria.trim().length === 0) {
2097
2122
  throw new Error("judge() requires non-empty criteria");
2098
2123
  }
2124
+ if (opts?.judgeFlowId !== void 0 && opts.judgeFlowId.trim().length === 0) {
2125
+ throw new Error("judge() requires a non-empty judgeFlowId when one is provided");
2126
+ }
2099
2127
  return gradeable({
2100
2128
  kind: "ai",
2101
2129
  criteria,
2102
2130
  ...opts?.preset ? { preset: opts.preset } : {},
2103
2131
  ...opts?.useExpected ? { useExpected: true } : {},
2104
2132
  ...opts?.model ? { model: opts.model } : {},
2133
+ ...opts?.judgeFlowId ? { judgeFlowId: opts.judgeFlowId } : {},
2105
2134
  ...opts?.threshold !== void 0 ? { threshold: opts.threshold } : {}
2106
2135
  });
2107
2136
  }
@@ -2152,9 +2181,6 @@ var DEFINE_EVAL_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set([
2152
2181
  "virtual"
2153
2182
  ]);
2154
2183
  var DEFINE_EVAL_CASE_KEYS = /* @__PURE__ */ new Set(["name", "input", "expected", "expect"]);
2155
- function isPlainObject(value) {
2156
- return value !== null && typeof value === "object" && !Array.isArray(value);
2157
- }
2158
2184
  function normalizeTarget(target) {
2159
2185
  if (!isPlainObject(target)) {
2160
2186
  throw new Error('defineEval requires a "target" object: { flow: name } or { agent: name }');
@@ -2299,10 +2325,7 @@ async function computeEvalContentHash(definition) {
2299
2325
  expect: c.expect.map((g) => normalizeForHash(g))
2300
2326
  }))
2301
2327
  };
2302
- const serialized = JSON.stringify(canonical);
2303
- const encoded = new TextEncoder().encode(serialized);
2304
- const hashBuffer = await crypto.subtle.digest("SHA-256", encoded);
2305
- return Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
2328
+ return sha256Hex(JSON.stringify(canonical));
2306
2329
  }
2307
2330
  var serverHashMemo = /* @__PURE__ */ new WeakMap();
2308
2331
  function memoFor(client) {
@@ -2349,11 +2372,8 @@ async function runEvalSuite(client, input) {
2349
2372
  }
2350
2373
 
2351
2374
  // src/flows-ensure.ts
2352
- function isPlainObject2(value) {
2353
- return value !== null && typeof value === "object" && !Array.isArray(value);
2354
- }
2355
2375
  function normalizeConfigForHash(config) {
2356
- if (!isPlainObject2(config)) return {};
2376
+ if (!isPlainObject(config)) return {};
2357
2377
  const normalized = {};
2358
2378
  for (const key of Object.keys(config).sort()) {
2359
2379
  const value = config[key];
@@ -2374,7 +2394,7 @@ function normalizeConfigForHash(config) {
2374
2394
  return normalized;
2375
2395
  }
2376
2396
  function normalizeStepForHash(step) {
2377
- const stepObj = isPlainObject2(step) ? step : {};
2397
+ const stepObj = isPlainObject(step) ? step : {};
2378
2398
  return {
2379
2399
  type: typeof stepObj.type === "string" ? stepObj.type : "",
2380
2400
  name: typeof stepObj.name === "string" ? stepObj.name : "",
@@ -2386,14 +2406,11 @@ function normalizeStepForHash(step) {
2386
2406
  }
2387
2407
  async function computeFlowContentHash(steps) {
2388
2408
  const normalized = [...steps].sort((a, b) => {
2389
- const orderA = isPlainObject2(a) && typeof a.order === "number" ? a.order : 0;
2390
- const orderB = isPlainObject2(b) && typeof b.order === "number" ? b.order : 0;
2409
+ const orderA = isPlainObject(a) && typeof a.order === "number" ? a.order : 0;
2410
+ const orderB = isPlainObject(b) && typeof b.order === "number" ? b.order : 0;
2391
2411
  return orderA - orderB;
2392
2412
  }).map(normalizeStepForHash);
2393
- const serialized = JSON.stringify(normalized);
2394
- const encoded = new TextEncoder().encode(serialized);
2395
- const hashBuffer = await crypto.subtle.digest("SHA-256", encoded);
2396
- return Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
2413
+ return sha256Hex(JSON.stringify(normalized));
2397
2414
  }
2398
2415
  var DEFINE_FLOW_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set(["name", "steps", "evals"]);
2399
2416
  var DEFINE_FLOW_STEP_KEYS = /* @__PURE__ */ new Set([
@@ -2416,27 +2433,27 @@ function collectStepNonPortableToolRefs(config, path) {
2416
2433
  });
2417
2434
  };
2418
2435
  const scanKeys = (value, subPath) => {
2419
- if (!isPlainObject2(value)) return;
2436
+ if (!isPlainObject(value)) return;
2420
2437
  for (const key of Object.keys(value)) {
2421
2438
  if (isAccountScoped(key)) found.push(`${subPath}.${key}`);
2422
2439
  }
2423
2440
  };
2424
- if (isPlainObject2(tools)) {
2441
+ if (isPlainObject(tools)) {
2425
2442
  scanArray(tools.toolIds, `${path}.tools.toolIds`);
2426
2443
  scanKeys(tools.toolConfigs, `${path}.tools.toolConfigs`);
2427
2444
  scanKeys(tools.perToolLimits, `${path}.tools.perToolLimits`);
2428
- if (isPlainObject2(tools.approval)) {
2445
+ if (isPlainObject(tools.approval)) {
2429
2446
  scanArray(tools.approval.require, `${path}.tools.approval.require`);
2430
2447
  }
2431
- if (isPlainObject2(tools.subagentConfig)) {
2448
+ if (isPlainObject(tools.subagentConfig)) {
2432
2449
  scanArray(tools.subagentConfig.toolPool, `${path}.tools.subagentConfig.toolPool`);
2433
2450
  }
2434
- if (isPlainObject2(tools.codeModeConfig)) {
2451
+ if (isPlainObject(tools.codeModeConfig)) {
2435
2452
  scanArray(tools.codeModeConfig.toolPool, `${path}.tools.codeModeConfig.toolPool`);
2436
2453
  }
2437
2454
  if (Array.isArray(tools.runtimeTools)) {
2438
2455
  tools.runtimeTools.forEach((runtimeTool, i) => {
2439
- if (!isPlainObject2(runtimeTool) || !isPlainObject2(runtimeTool.config)) return;
2456
+ if (!isPlainObject(runtimeTool) || !isPlainObject(runtimeTool.config)) return;
2440
2457
  const base = `${path}.tools.runtimeTools[${i}].config`;
2441
2458
  const rtConfig = runtimeTool.config;
2442
2459
  if (runtimeTool.toolType === "subagent" && isRawId(rtConfig.agentId, "agent_")) {
@@ -2457,7 +2474,7 @@ function collectStepNonPortableToolRefs(config, path) {
2457
2474
  const nested = config[branch];
2458
2475
  if (!Array.isArray(nested)) continue;
2459
2476
  nested.forEach((nestedStep, i) => {
2460
- if (isPlainObject2(nestedStep) && isPlainObject2(nestedStep.config)) {
2477
+ if (isPlainObject(nestedStep) && isPlainObject(nestedStep.config)) {
2461
2478
  found.push(
2462
2479
  ...collectStepNonPortableToolRefs(nestedStep.config, `${path}.${branch}[${i}].config`)
2463
2480
  );
@@ -2483,7 +2500,7 @@ function defineFlow(input) {
2483
2500
  throw new Error('defineFlow requires a non-empty "steps" array');
2484
2501
  }
2485
2502
  const steps = input.steps.map((step, index) => {
2486
- if (!isPlainObject2(step)) {
2503
+ if (!isPlainObject(step)) {
2487
2504
  throw new Error(`defineFlow: steps[${index}] must be an object`);
2488
2505
  }
2489
2506
  if (typeof step.type !== "string" || step.type.length === 0) {
@@ -2498,7 +2515,7 @@ function defineFlow(input) {
2498
2515
  `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.)`
2499
2516
  );
2500
2517
  }
2501
- const config = isPlainObject2(step.config) ? step.config : void 0;
2518
+ const config = isPlainObject(step.config) ? step.config : void 0;
2502
2519
  if (config) {
2503
2520
  const nonPortable = collectStepNonPortableToolRefs(config, `steps[${index}].config`);
2504
2521
  if (nonPortable.length > 0) {
@@ -2525,7 +2542,7 @@ function defineFlow(input) {
2525
2542
  }
2526
2543
  const seenEvalNames = /* @__PURE__ */ new Set();
2527
2544
  evals = input.evals.map((evalInput, i) => {
2528
- if (!isPlainObject2(evalInput)) {
2545
+ if (!isPlainObject(evalInput)) {
2529
2546
  throw new Error(`defineFlow: evals[${i}] must be an object`);
2530
2547
  }
2531
2548
  if (evalInput.virtual === true) {
@@ -2589,7 +2606,7 @@ function parseRequestError(err) {
2589
2606
  }
2590
2607
  function toConflictError(err) {
2591
2608
  const { status, body } = parseRequestError(err);
2592
- if (status !== 409 || !isPlainObject2(body)) return null;
2609
+ if (status !== 409 || !isPlainObject(body)) return null;
2593
2610
  const code = body.code;
2594
2611
  if (code !== "external_modification" && code !== "remote_changed") return null;
2595
2612
  return new FlowEnsureConflictError(
@@ -3884,6 +3901,18 @@ var EvalSuitesNamespace = class {
3884
3901
  cases
3885
3902
  });
3886
3903
  }
3904
+ /**
3905
+ * Capture a test case from a real agent run ("fork here and test the next
3906
+ * step"): freezes the run's conversation history up to a fork point, attaches
3907
+ * every recorded tool result as an editable mock, and saves it with origin
3908
+ * `saved_from_run`. Capture only — reads the run, never re-executes it.
3909
+ */
3910
+ async addCaseFromExecution(suiteId, input) {
3911
+ return this.getClient().post(
3912
+ `/eval/suites/${suiteId}/cases/from-execution`,
3913
+ input
3914
+ );
3915
+ }
3887
3916
  /** Edit, enable, or disable a test case. */
3888
3917
  async updateCase(suiteId, caseId, input) {
3889
3918
  return this.getClient().patch(
@@ -4070,6 +4099,30 @@ var EvalsNamespace = class {
4070
4099
  async pull(name) {
4071
4100
  return pullEval(this.getClient(), name);
4072
4101
  }
4102
+ /**
4103
+ * Split one plain-language AI-grader criterion carrying several obligations
4104
+ * into focused, independently judgeable sub-checks. Authoring assist only:
4105
+ * nothing is persisted — review the proposal, then save each accepted
4106
+ * sub-check as its own AI grader row. A single returned sub-check means the
4107
+ * criterion is already focused.
4108
+ *
4109
+ * @example
4110
+ * ```typescript
4111
+ * const { subChecks } = await Runtype.evals.decomposeCriteria(
4112
+ * 'Confirms the order number before issuing a refund, and never promises a delivery date.'
4113
+ * )
4114
+ * // In a defineEval suite, each accepted sub-check becomes its own judge row:
4115
+ * const graders = subChecks.map((s) => judge(s.criteria))
4116
+ * ```
4117
+ */
4118
+ async decomposeCriteria(criteria) {
4119
+ if (typeof criteria !== "string" || criteria.trim().length === 0) {
4120
+ throw new Error("decomposeCriteria() requires non-empty criteria");
4121
+ }
4122
+ return this.getClient().post("/eval/graders/decompose", {
4123
+ criteria
4124
+ });
4125
+ }
4073
4126
  /**
4074
4127
  * Run an eval suite synchronously and return the suite score + per-case grader
4075
4128
  * outcomes — the executing counterpart of `ensure`, powering the `runtype
@@ -4222,42 +4275,21 @@ var PromptsNamespace = class {
4222
4275
  };
4223
4276
 
4224
4277
  // src/skills-ensure.ts
4225
- function isPlainObject3(value) {
4226
- return value !== null && typeof value === "object" && !Array.isArray(value);
4227
- }
4228
- function normalizeValue(value) {
4229
- if (Array.isArray(value)) {
4230
- return value.map((item) => normalizeValue(item));
4231
- }
4232
- if (isPlainObject3(value)) {
4233
- const normalized = {};
4234
- for (const key of Object.keys(value).sort()) {
4235
- const entry = value[key];
4236
- if (entry === void 0 || entry === null) continue;
4237
- normalized[key] = normalizeValue(entry);
4238
- }
4239
- return normalized;
4240
- }
4241
- return value;
4242
- }
4243
4278
  function normalizeSkillDefinition(definition) {
4244
- const manifest = isPlainObject3(definition.manifest) ? definition.manifest : {};
4245
- const rawFrontmatter = isPlainObject3(manifest.frontmatter) ? manifest.frontmatter : {};
4279
+ const manifest = isPlainObject(definition.manifest) ? definition.manifest : {};
4280
+ const rawFrontmatter = isPlainObject(manifest.frontmatter) ? manifest.frontmatter : {};
4246
4281
  const frontmatterWithoutName = {};
4247
4282
  for (const key of Object.keys(rawFrontmatter)) {
4248
4283
  if (key === "name") continue;
4249
4284
  frontmatterWithoutName[key] = rawFrontmatter[key];
4250
4285
  }
4251
4286
  const frontmatter = normalizeValue(frontmatterWithoutName);
4252
- const runtype = isPlainObject3(manifest.runtype) ? normalizeValue(manifest.runtype) : {};
4287
+ const runtype = isPlainObject(manifest.runtype) ? normalizeValue(manifest.runtype) : {};
4253
4288
  const body = typeof manifest.body === "string" ? manifest.body : "";
4254
4289
  return { frontmatter, runtype, body };
4255
4290
  }
4256
4291
  async function computeSkillContentHash(definition) {
4257
- const serialized = JSON.stringify(normalizeSkillDefinition(definition));
4258
- const encoded = new TextEncoder().encode(serialized);
4259
- const hashBuffer = await crypto.subtle.digest("SHA-256", encoded);
4260
- return Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
4292
+ return sha256Hex(JSON.stringify(normalizeSkillDefinition(definition)));
4261
4293
  }
4262
4294
  var DEFINE_SKILL_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set(["name", "manifest"]);
4263
4295
  function defineSkill(input) {
@@ -4267,7 +4299,7 @@ function defineSkill(input) {
4267
4299
  if (typeof input.name !== "string" || input.name.length === 0) {
4268
4300
  throw new Error('defineSkill requires a non-empty string "name"');
4269
4301
  }
4270
- if (!isPlainObject3(input.manifest)) {
4302
+ if (!isPlainObject(input.manifest)) {
4271
4303
  throw new Error('defineSkill requires a "manifest" object ({ frontmatter, runtype, body })');
4272
4304
  }
4273
4305
  const unknownKeys = Object.keys(input).filter((key) => !DEFINE_SKILL_TOP_LEVEL_KEYS.has(key));
@@ -4277,7 +4309,7 @@ function defineSkill(input) {
4277
4309
  );
4278
4310
  }
4279
4311
  const frontmatter = input.manifest.frontmatter;
4280
- if (!isPlainObject3(frontmatter) || typeof frontmatter.name !== "string") {
4312
+ if (!isPlainObject(frontmatter) || typeof frontmatter.name !== "string") {
4281
4313
  throw new Error("defineSkill: manifest.frontmatter.name is required");
4282
4314
  }
4283
4315
  if (frontmatter.name !== input.name) {
@@ -4318,7 +4350,7 @@ function parseRequestError2(err) {
4318
4350
  }
4319
4351
  function toConflictError2(err) {
4320
4352
  const { status, body } = parseRequestError2(err);
4321
- if (status !== 409 || !isPlainObject3(body)) return null;
4353
+ if (status !== 409 || !isPlainObject(body)) return null;
4322
4354
  const code = body.code;
4323
4355
  if (code !== "external_modification" && code !== "remote_changed") return null;
4324
4356
  return new SkillEnsureConflictError(
@@ -4667,14 +4699,14 @@ var AGENT_CONFIG_KEYS = [
4667
4699
  "tenancyStrategy"
4668
4700
  ];
4669
4701
  var AGENT_CONFIG_KEY_LIST = [...AGENT_CONFIG_KEYS].sort();
4670
- function isPlainObject4(value) {
4702
+ function isPlainObject2(value) {
4671
4703
  return value !== null && typeof value === "object" && !Array.isArray(value);
4672
4704
  }
4673
4705
  function normalizeValue2(value) {
4674
4706
  if (Array.isArray(value)) {
4675
4707
  return value.map((item) => normalizeValue2(item));
4676
4708
  }
4677
- if (isPlainObject4(value)) {
4709
+ if (isPlainObject2(value)) {
4678
4710
  const normalized = {};
4679
4711
  for (const key of Object.keys(value).sort()) {
4680
4712
  const entry = value[key];
@@ -4687,7 +4719,7 @@ function normalizeValue2(value) {
4687
4719
  }
4688
4720
  function normalizeAgentDefinition(definition) {
4689
4721
  const config = {};
4690
- const rawConfig = isPlainObject4(definition.config) ? definition.config : {};
4722
+ const rawConfig = isPlainObject2(definition.config) ? definition.config : {};
4691
4723
  for (const key of AGENT_CONFIG_KEY_LIST) {
4692
4724
  const value = rawConfig[key];
4693
4725
  if (value === void 0 || value === null) continue;
@@ -4709,7 +4741,7 @@ async function computeAgentContentHash(definition) {
4709
4741
  var DEFINE_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set(["name", "description", "icon", ...AGENT_CONFIG_KEYS]);
4710
4742
  function collectNonPortableToolRefs(config) {
4711
4743
  const tools = config.tools;
4712
- if (!isPlainObject4(tools)) return [];
4744
+ if (!isPlainObject2(tools)) return [];
4713
4745
  const found = [];
4714
4746
  const isAccountScoped = (ref) => typeof ref === "string" && ref.startsWith("tool_");
4715
4747
  const scanArray = (value, path) => {
@@ -4719,7 +4751,7 @@ function collectNonPortableToolRefs(config) {
4719
4751
  });
4720
4752
  };
4721
4753
  const scanKeys = (value, path) => {
4722
- if (!isPlainObject4(value)) return;
4754
+ if (!isPlainObject2(value)) return;
4723
4755
  for (const key of Object.keys(value)) {
4724
4756
  if (isAccountScoped(key)) found.push(`${path}.${key}`);
4725
4757
  }
@@ -4727,16 +4759,16 @@ function collectNonPortableToolRefs(config) {
4727
4759
  scanArray(tools.toolIds, "tools.toolIds");
4728
4760
  scanKeys(tools.toolConfigs, "tools.toolConfigs");
4729
4761
  scanKeys(tools.perToolLimits, "tools.perToolLimits");
4730
- if (isPlainObject4(tools.approval)) scanArray(tools.approval.require, "tools.approval.require");
4731
- if (isPlainObject4(tools.subagentConfig)) {
4762
+ if (isPlainObject2(tools.approval)) scanArray(tools.approval.require, "tools.approval.require");
4763
+ if (isPlainObject2(tools.subagentConfig)) {
4732
4764
  scanArray(tools.subagentConfig.toolPool, "tools.subagentConfig.toolPool");
4733
4765
  }
4734
- if (isPlainObject4(tools.codeModeConfig)) {
4766
+ if (isPlainObject2(tools.codeModeConfig)) {
4735
4767
  scanArray(tools.codeModeConfig.toolPool, "tools.codeModeConfig.toolPool");
4736
4768
  }
4737
4769
  if (Array.isArray(tools.runtimeTools)) {
4738
4770
  tools.runtimeTools.forEach((runtimeTool, i) => {
4739
- if (!isPlainObject4(runtimeTool) || !isPlainObject4(runtimeTool.config)) return;
4771
+ if (!isPlainObject2(runtimeTool) || !isPlainObject2(runtimeTool.config)) return;
4740
4772
  const base = `tools.runtimeTools[${i}].config`;
4741
4773
  const rtConfig = runtimeTool.config;
4742
4774
  if (runtimeTool.toolType === "subagent" && typeof rtConfig.agentId === "string" && rtConfig.agentId.startsWith("agent_")) {
@@ -4810,7 +4842,7 @@ function parseRequestError3(err) {
4810
4842
  }
4811
4843
  function toConflictError3(err) {
4812
4844
  const { status, body } = parseRequestError3(err);
4813
- if (status !== 409 || !isPlainObject4(body)) return null;
4845
+ if (status !== 409 || !isPlainObject2(body)) return null;
4814
4846
  const code = body.code;
4815
4847
  if (code !== "external_modification" && code !== "remote_changed") return null;
4816
4848
  return new AgentEnsureConflictError(
@@ -4912,27 +4944,9 @@ var AgentsNamespace = class {
4912
4944
  };
4913
4945
 
4914
4946
  // src/tools-ensure.ts
4915
- function isPlainObject5(value) {
4916
- return value !== null && typeof value === "object" && !Array.isArray(value);
4917
- }
4918
- function normalizeValue3(value) {
4919
- if (Array.isArray(value)) {
4920
- return value.map((item) => normalizeValue3(item));
4921
- }
4922
- if (isPlainObject5(value)) {
4923
- const normalized = {};
4924
- for (const key of Object.keys(value).sort()) {
4925
- const entry = value[key];
4926
- if (entry === void 0 || entry === null) continue;
4927
- normalized[key] = normalizeValue3(entry);
4928
- }
4929
- return normalized;
4930
- }
4931
- return value;
4932
- }
4933
4947
  function normalizeToolDefinition(definition) {
4934
- const parametersSchema = isPlainObject5(definition.parametersSchema) ? normalizeValue3(definition.parametersSchema) : {};
4935
- const config = isPlainObject5(definition.config) ? normalizeValue3(definition.config) : {};
4948
+ const parametersSchema = isPlainObject(definition.parametersSchema) ? normalizeValue(definition.parametersSchema) : {};
4949
+ const config = isPlainObject(definition.config) ? normalizeValue(definition.config) : {};
4936
4950
  return {
4937
4951
  toolType: definition.toolType,
4938
4952
  ...definition.description ? { description: definition.description } : {},
@@ -4941,10 +4955,7 @@ function normalizeToolDefinition(definition) {
4941
4955
  };
4942
4956
  }
4943
4957
  async function computeToolContentHash(definition) {
4944
- const serialized = JSON.stringify(normalizeToolDefinition(definition));
4945
- const encoded = new TextEncoder().encode(serialized);
4946
- const hashBuffer = await crypto.subtle.digest("SHA-256", encoded);
4947
- return Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
4958
+ return sha256Hex(JSON.stringify(normalizeToolDefinition(definition)));
4948
4959
  }
4949
4960
  var DEFINE_TOOL_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set([
4950
4961
  "name",
@@ -4977,10 +4988,10 @@ function defineTool(input) {
4977
4988
  `defineTool requires "toolType" to be one of: ${[...TOOL_DEFINITION_TYPES].join(", ")}`
4978
4989
  );
4979
4990
  }
4980
- if (!isPlainObject5(input.parametersSchema)) {
4991
+ if (!isPlainObject(input.parametersSchema)) {
4981
4992
  throw new Error('defineTool requires a "parametersSchema" object (a JSON Schema)');
4982
4993
  }
4983
- if (!isPlainObject5(input.config)) {
4994
+ if (!isPlainObject(input.config)) {
4984
4995
  throw new Error('defineTool requires a "config" object');
4985
4996
  }
4986
4997
  const unknownKeys = Object.keys(input).filter((key) => !DEFINE_TOOL_TOP_LEVEL_KEYS.has(key));
@@ -5028,7 +5039,7 @@ function parseRequestError4(err) {
5028
5039
  }
5029
5040
  function toConflictError4(err) {
5030
5041
  const { status, body } = parseRequestError4(err);
5031
- if (status !== 409 || !isPlainObject5(body)) return null;
5042
+ if (status !== 409 || !isPlainObject(body)) return null;
5032
5043
  const code = body.code;
5033
5044
  if (code !== "external_modification" && code !== "remote_changed") return null;
5034
5045
  return new ToolEnsureConflictError(
@@ -5148,26 +5159,8 @@ var ToolsNamespace = class {
5148
5159
  };
5149
5160
 
5150
5161
  // src/products-ensure.ts
5151
- function isPlainObject6(value) {
5152
- return value !== null && typeof value === "object" && !Array.isArray(value);
5153
- }
5154
- function normalizeValue4(value) {
5155
- if (Array.isArray(value)) {
5156
- return value.map((item) => normalizeValue4(item));
5157
- }
5158
- if (isPlainObject6(value)) {
5159
- const normalized = {};
5160
- for (const key of Object.keys(value).sort()) {
5161
- const entry = value[key];
5162
- if (entry === void 0 || entry === null) continue;
5163
- normalized[key] = normalizeValue4(entry);
5164
- }
5165
- return normalized;
5166
- }
5167
- return value;
5168
- }
5169
5162
  function normalizeProductDefinition(definition) {
5170
- const spec = isPlainObject6(definition.spec) ? normalizeValue4(definition.spec) : {};
5163
+ const spec = isPlainObject(definition.spec) ? normalizeValue(definition.spec) : {};
5171
5164
  return {
5172
5165
  ...definition.description ? { description: definition.description } : {},
5173
5166
  ...definition.icon ? { icon: definition.icon } : {},
@@ -5175,10 +5168,7 @@ function normalizeProductDefinition(definition) {
5175
5168
  };
5176
5169
  }
5177
5170
  async function computeProductContentHash(definition) {
5178
- const serialized = JSON.stringify(normalizeProductDefinition(definition));
5179
- const encoded = new TextEncoder().encode(serialized);
5180
- const hashBuffer = await crypto.subtle.digest("SHA-256", encoded);
5181
- return Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
5171
+ return sha256Hex(JSON.stringify(normalizeProductDefinition(definition)));
5182
5172
  }
5183
5173
  var DEFINE_PRODUCT_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set(["name", "description", "icon", "spec"]);
5184
5174
  function defineProduct(input) {
@@ -5194,7 +5184,7 @@ function defineProduct(input) {
5194
5184
  if (input.icon != null && typeof input.icon !== "string") {
5195
5185
  throw new Error('defineProduct "icon" must be a string when provided');
5196
5186
  }
5197
- if (input.spec != null && !isPlainObject6(input.spec)) {
5187
+ if (input.spec != null && !isPlainObject(input.spec)) {
5198
5188
  throw new Error('defineProduct "spec" must be an object when provided');
5199
5189
  }
5200
5190
  const unknownKeys = Object.keys(input).filter((key) => !DEFINE_PRODUCT_TOP_LEVEL_KEYS.has(key));
@@ -5241,7 +5231,7 @@ function parseRequestError5(err) {
5241
5231
  }
5242
5232
  function toConflictError5(err) {
5243
5233
  const { status, body } = parseRequestError5(err);
5244
- if (status !== 409 || !isPlainObject6(body)) return null;
5234
+ if (status !== 409 || !isPlainObject(body)) return null;
5245
5235
  const code = body.code;
5246
5236
  if (code !== "external_modification" && code !== "remote_changed") return null;
5247
5237
  return new ProductEnsureConflictError(
@@ -5322,50 +5312,29 @@ async function pullProduct(client, name) {
5322
5312
  }
5323
5313
 
5324
5314
  // src/products-ensure-fpo.ts
5325
- function isPlainObject7(value) {
5326
- return value !== null && typeof value === "object" && !Array.isArray(value);
5327
- }
5328
- function normalizeValue5(value) {
5329
- if (Array.isArray(value)) {
5330
- return value.map((item) => normalizeValue5(item));
5331
- }
5332
- if (isPlainObject7(value)) {
5333
- const normalized = {};
5334
- for (const key of Object.keys(value).sort()) {
5335
- const entry = value[key];
5336
- if (entry === void 0 || entry === null) continue;
5337
- normalized[key] = normalizeValue5(entry);
5338
- }
5339
- return normalized;
5340
- }
5341
- return value;
5342
- }
5343
5315
  function normalizeFpoDefinition(fpo) {
5344
- const productInput = isPlainObject7(fpo.product) ? fpo.product : {};
5316
+ const productInput = isPlainObject(fpo.product) ? fpo.product : {};
5345
5317
  const { name: _identityName, ...productRest } = productInput;
5346
- const product = normalizeValue5(productRest);
5318
+ const product = normalizeValue(productRest);
5347
5319
  return {
5348
- ...fpo.version !== void 0 && fpo.version !== null ? { version: normalizeValue5(fpo.version) } : {},
5320
+ ...fpo.version !== void 0 && fpo.version !== null ? { version: normalizeValue(fpo.version) } : {},
5349
5321
  product,
5350
- capabilities: normalizeValue5(fpo.capabilities ?? []),
5351
- tools: normalizeValue5(fpo.tools ?? []),
5352
- surfaces: normalizeValue5(fpo.surfaces ?? []),
5353
- ...fpo.records !== void 0 && fpo.records !== null ? { records: normalizeValue5(fpo.records) } : {},
5354
- ...fpo.schedules !== void 0 && fpo.schedules !== null ? { schedules: normalizeValue5(fpo.schedules) } : {},
5355
- ...fpo.secrets !== void 0 && fpo.secrets !== null ? { secrets: normalizeValue5(fpo.secrets) } : {}
5322
+ capabilities: normalizeValue(fpo.capabilities ?? []),
5323
+ tools: normalizeValue(fpo.tools ?? []),
5324
+ surfaces: normalizeValue(fpo.surfaces ?? []),
5325
+ ...fpo.records !== void 0 && fpo.records !== null ? { records: normalizeValue(fpo.records) } : {},
5326
+ ...fpo.schedules !== void 0 && fpo.schedules !== null ? { schedules: normalizeValue(fpo.schedules) } : {},
5327
+ ...fpo.secrets !== void 0 && fpo.secrets !== null ? { secrets: normalizeValue(fpo.secrets) } : {}
5356
5328
  };
5357
5329
  }
5358
5330
  async function computeFpoContentHash(fpo) {
5359
- const serialized = JSON.stringify(normalizeFpoDefinition(fpo));
5360
- const encoded = new TextEncoder().encode(serialized);
5361
- const hashBuffer = await crypto.subtle.digest("SHA-256", encoded);
5362
- return Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
5331
+ return sha256Hex(JSON.stringify(normalizeFpoDefinition(fpo)));
5363
5332
  }
5364
5333
  function defineFpo(fpo) {
5365
- if (!isPlainObject7(fpo)) {
5334
+ if (!isPlainObject(fpo)) {
5366
5335
  throw new Error("defineFpo requires an FPO object");
5367
5336
  }
5368
- const product = isPlainObject7(fpo.product) ? fpo.product : void 0;
5337
+ const product = isPlainObject(fpo.product) ? fpo.product : void 0;
5369
5338
  if (!product || typeof product.name !== "string" || product.name.length === 0) {
5370
5339
  throw new Error('defineFpo requires a non-empty "product.name" (the converge identity)');
5371
5340
  }
@@ -5461,26 +5430,8 @@ var ProductsNamespace = class {
5461
5430
  };
5462
5431
 
5463
5432
  // src/surfaces-ensure.ts
5464
- function isPlainObject8(value) {
5465
- return value !== null && typeof value === "object" && !Array.isArray(value);
5466
- }
5467
- function normalizeValue6(value) {
5468
- if (Array.isArray(value)) {
5469
- return value.map((item) => normalizeValue6(item));
5470
- }
5471
- if (isPlainObject8(value)) {
5472
- const normalized = {};
5473
- for (const key of Object.keys(value).sort()) {
5474
- const entry = value[key];
5475
- if (entry === void 0 || entry === null) continue;
5476
- normalized[key] = normalizeValue6(entry);
5477
- }
5478
- return normalized;
5479
- }
5480
- return value;
5481
- }
5482
5433
  function normalizeSurfaceDefinition(definition) {
5483
- const behavior = isPlainObject8(definition.behavior) ? normalizeValue6({ type: definition.type, ...definition.behavior }) : { type: definition.type };
5434
+ const behavior = isPlainObject(definition.behavior) ? normalizeValue({ type: definition.type, ...definition.behavior }) : { type: definition.type };
5484
5435
  return {
5485
5436
  type: definition.type,
5486
5437
  behavior,
@@ -5489,10 +5440,7 @@ function normalizeSurfaceDefinition(definition) {
5489
5440
  };
5490
5441
  }
5491
5442
  async function computeSurfaceContentHash(definition) {
5492
- const serialized = JSON.stringify(normalizeSurfaceDefinition(definition));
5493
- const encoded = new TextEncoder().encode(serialized);
5494
- const hashBuffer = await crypto.subtle.digest("SHA-256", encoded);
5495
- return Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
5443
+ return sha256Hex(JSON.stringify(normalizeSurfaceDefinition(definition)));
5496
5444
  }
5497
5445
  var DEFINE_SURFACE_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set([
5498
5446
  "name",
@@ -5533,13 +5481,13 @@ function defineSurface(input) {
5533
5481
  `defineSurface requires "type" to be one of: ${[...SURFACE_DEFINITION_TYPES].join(", ")}`
5534
5482
  );
5535
5483
  }
5536
- if (input.behavior !== void 0 && !isPlainObject8(input.behavior)) {
5484
+ if (input.behavior !== void 0 && !isPlainObject(input.behavior)) {
5537
5485
  throw new Error('defineSurface "behavior" must be an object when provided');
5538
5486
  }
5539
- if (input.inbound !== void 0 && !isPlainObject8(input.inbound)) {
5487
+ if (input.inbound !== void 0 && !isPlainObject(input.inbound)) {
5540
5488
  throw new Error('defineSurface "inbound" must be an object when provided');
5541
5489
  }
5542
- if (input.outbound !== void 0 && !isPlainObject8(input.outbound)) {
5490
+ if (input.outbound !== void 0 && !isPlainObject(input.outbound)) {
5543
5491
  throw new Error('defineSurface "outbound" must be an object when provided');
5544
5492
  }
5545
5493
  if (input.status !== void 0 && !["draft", "active", "paused"].includes(input.status)) {
@@ -5595,7 +5543,7 @@ function parseRequestError6(err) {
5595
5543
  }
5596
5544
  function toConflictError6(err) {
5597
5545
  const { status, body } = parseRequestError6(err);
5598
- if (status !== 409 || !isPlainObject8(body)) return null;
5546
+ if (status !== 409 || !isPlainObject(body)) return null;
5599
5547
  const code = body.code;
5600
5548
  if (code !== "external_modification" && code !== "remote_changed") return null;
5601
5549
  return new SurfaceEnsureConflictError(
@@ -6208,7 +6156,7 @@ var Runtype = class {
6208
6156
 
6209
6157
  // src/version.ts
6210
6158
  var FALLBACK_VERSION = "0.0.0";
6211
- var SDK_VERSION = "5.8.1".length > 0 ? "5.8.1" : FALLBACK_VERSION;
6159
+ var SDK_VERSION = "5.10.0".length > 0 ? "5.10.0" : FALLBACK_VERSION;
6212
6160
  var RUNTYPE_CLIENT_KIND = "sdk";
6213
6161
  var SDK_USER_AGENT = `runtype-sdk/${SDK_VERSION} (typescript)`;
6214
6162
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@runtypelabs/sdk",
3
- "version": "5.8.1",
3
+ "version": "5.10.0",
4
4
  "type": "module",
5
5
  "description": "TypeScript SDK for the Runtype API with fluent methods. Use it to quickly realize AI products, agents, and workflows.",
6
6
  "main": "dist/index.cjs",