@runtypelabs/sdk 5.9.0 → 6.1.3

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
@@ -27,7 +27,6 @@ __export(index_exports, {
27
27
  AgentsNamespace: () => AgentsNamespace,
28
28
  AnalyticsEndpoint: () => AnalyticsEndpoint,
29
29
  ApiKeysEndpoint: () => ApiKeysEndpoint,
30
- AppsEndpoint: () => AppsEndpoint,
31
30
  BatchBuilder: () => BatchBuilder,
32
31
  BatchesNamespace: () => BatchesNamespace,
33
32
  BillingEndpoint: () => BillingEndpoint,
@@ -36,6 +35,7 @@ __export(index_exports, {
36
35
  ClientEvalBuilder: () => ClientEvalBuilder,
37
36
  ClientFlowBuilder: () => ClientFlowBuilder,
38
37
  ClientTokensEndpoint: () => ClientTokensEndpoint,
38
+ CollectionsEndpoint: () => CollectionsEndpoint,
39
39
  ContextTemplatesEndpoint: () => ContextTemplatesEndpoint,
40
40
  ConversationsEndpoint: () => ConversationsEndpoint,
41
41
  DEFAULT_RECOVERY_AFTER_EMPTY_SESSIONS: () => DEFAULT_RECOVERY_AFTER_EMPTY_SESSIONS,
@@ -1338,6 +1338,7 @@ var FlowBuilder = class {
1338
1338
  markdownIfAvailable: config.markdownIfAvailable,
1339
1339
  fetchMethod: config.fetchMethod === "http" ? "standard" : config.fetchMethod,
1340
1340
  firecrawl: config.firecrawl,
1341
+ massive: config.massive,
1341
1342
  outputVariable: config.outputVariable,
1342
1343
  errorHandling: config.errorHandling,
1343
1344
  defaultValue: config.defaultValue,
@@ -1473,7 +1474,10 @@ var FlowBuilder = class {
1473
1474
  "send-stream",
1474
1475
  config.name,
1475
1476
  {
1476
- message: config.message
1477
+ message: config.message,
1478
+ outputVariable: config.outputVariable,
1479
+ errorHandling: config.errorHandling,
1480
+ defaultValue: config.defaultValue
1477
1481
  },
1478
1482
  config.enabled,
1479
1483
  config.when
@@ -1498,7 +1502,6 @@ var FlowBuilder = class {
1498
1502
  fieldsToExclude: config.fieldsToExclude,
1499
1503
  availableFields: config.availableFields,
1500
1504
  outputVariable: config.outputVariable,
1501
- fields: config.fields,
1502
1505
  includeMetadata: config.includeMetadata,
1503
1506
  streamOutput: config.streamOutput
1504
1507
  },
@@ -1591,7 +1594,6 @@ var FlowBuilder = class {
1591
1594
  vectorStore: config.vectorStore,
1592
1595
  weaviateConfig: config.weaviateConfig,
1593
1596
  vectorizeConfig: config.vectorizeConfig,
1594
- pineconeConfig: config.pineconeConfig,
1595
1597
  limit: config.limit,
1596
1598
  threshold: config.threshold,
1597
1599
  metadataFilters: config.metadataFilters,
@@ -1620,7 +1622,6 @@ var FlowBuilder = class {
1620
1622
  recordType: config.recordType,
1621
1623
  recordName: config.recordName,
1622
1624
  textField: config.textField,
1623
- storeInRecord: config.storeInRecord,
1624
1625
  embeddingModel: config.embeddingModel,
1625
1626
  maxLength: config.maxLength,
1626
1627
  inputMode: config.inputMode,
@@ -1628,7 +1629,6 @@ var FlowBuilder = class {
1628
1629
  itemAlias: config.itemAlias,
1629
1630
  textTemplate: config.textTemplate,
1630
1631
  batchSize: config.batchSize,
1631
- vectorStore: config.vectorStore,
1632
1632
  outputVariable: config.outputVariable,
1633
1633
  streamOutput: config.streamOutput
1634
1634
  },
@@ -1677,51 +1677,6 @@ var FlowBuilder = class {
1677
1677
  );
1678
1678
  return this;
1679
1679
  }
1680
- /**
1681
- * Add a send text step
1682
- */
1683
- sendText(config) {
1684
- this.addStep(
1685
- "send-text",
1686
- config.name,
1687
- {
1688
- to: config.to,
1689
- from: config.from,
1690
- message: config.message,
1691
- outputVariable: config.outputVariable,
1692
- errorHandling: config.errorHandling,
1693
- streamOutput: config.streamOutput
1694
- },
1695
- config.enabled,
1696
- config.when
1697
- );
1698
- return this;
1699
- }
1700
- /**
1701
- * Add a fetch GitHub step
1702
- */
1703
- fetchGitHub(config) {
1704
- this.addStep(
1705
- "fetch-github",
1706
- config.name,
1707
- {
1708
- repository: config.repository,
1709
- branch: config.branch,
1710
- path: config.path,
1711
- token: config.token,
1712
- outputVariable: config.outputVariable,
1713
- contentType: config.contentType,
1714
- includePatterns: config.includePatterns,
1715
- excludePatterns: config.excludePatterns,
1716
- compress: config.compress,
1717
- style: config.style,
1718
- streamOutput: config.streamOutput
1719
- },
1720
- config.enabled,
1721
- config.when
1722
- );
1723
- return this;
1724
- }
1725
1680
  /** Add an api-call step. */
1726
1681
  apiCall(config) {
1727
1682
  return this.addRawStep("api-call", config);
@@ -2125,6 +2080,31 @@ function resolveBatchExecutionId(pausedTools) {
2125
2080
  return "";
2126
2081
  }
2127
2082
 
2083
+ // src/content-hash.ts
2084
+ function isPlainObject(value) {
2085
+ return value !== null && typeof value === "object" && !Array.isArray(value);
2086
+ }
2087
+ function normalizeValue(value) {
2088
+ if (Array.isArray(value)) {
2089
+ return value.map((item) => normalizeValue(item));
2090
+ }
2091
+ if (isPlainObject(value)) {
2092
+ const normalized = {};
2093
+ for (const key of Object.keys(value).sort()) {
2094
+ const entry = value[key];
2095
+ if (entry === void 0 || entry === null) continue;
2096
+ normalized[key] = normalizeValue(entry);
2097
+ }
2098
+ return normalized;
2099
+ }
2100
+ return value;
2101
+ }
2102
+ async function sha256Hex(serialized) {
2103
+ const encoded = new TextEncoder().encode(serialized);
2104
+ const hashBuffer = await crypto.subtle.digest("SHA-256", encoded);
2105
+ return Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
2106
+ }
2107
+
2128
2108
  // src/evals-ensure.ts
2129
2109
  var CHECK_GRADER_KINDS = /* @__PURE__ */ new Set([
2130
2110
  "contains",
@@ -2340,12 +2320,11 @@ var DEFINE_EVAL_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set([
2340
2320
  "target",
2341
2321
  "graders",
2342
2322
  "cases",
2343
- "virtual"
2323
+ "virtual",
2324
+ "recordedToolMode",
2325
+ "recordedToolUnmatchedPolicy"
2344
2326
  ]);
2345
2327
  var DEFINE_EVAL_CASE_KEYS = /* @__PURE__ */ new Set(["name", "input", "expected", "expect"]);
2346
- function isPlainObject(value) {
2347
- return value !== null && typeof value === "object" && !Array.isArray(value);
2348
- }
2349
2328
  function normalizeTarget(target) {
2350
2329
  if (!isPlainObject(target)) {
2351
2330
  throw new Error('defineEval requires a "target" object: { flow: name } or { agent: name }');
@@ -2412,9 +2391,15 @@ function defineEval(input) {
2412
2391
  const unknownKeys = Object.keys(input).filter((k) => !DEFINE_EVAL_TOP_LEVEL_KEYS.has(k));
2413
2392
  if (unknownKeys.length > 0) {
2414
2393
  throw new Error(
2415
- `defineEval: unknown field(s): ${unknownKeys.join(", ")}. Allowed fields are target, graders, cases, virtual.`
2394
+ `defineEval: unknown field(s): ${unknownKeys.join(", ")}. Allowed fields are target, graders, cases, virtual, recordedToolMode, recordedToolUnmatchedPolicy.`
2416
2395
  );
2417
2396
  }
2397
+ if (input.recordedToolMode !== void 0 && input.recordedToolMode !== "next_step" && input.recordedToolMode !== "continue") {
2398
+ throw new Error('defineEval "recordedToolMode" must be "next_step" or "continue"');
2399
+ }
2400
+ if (input.recordedToolUnmatchedPolicy !== void 0 && input.recordedToolUnmatchedPolicy !== "fail" && input.recordedToolUnmatchedPolicy !== "stub") {
2401
+ throw new Error('defineEval "recordedToolUnmatchedPolicy" must be "fail" or "stub"');
2402
+ }
2418
2403
  const target = normalizeTarget(input.target);
2419
2404
  if (input.name !== void 0 && (typeof input.name !== "string" || input.name.length === 0)) {
2420
2405
  throw new Error('defineEval "name" must be a non-empty string when provided');
@@ -2463,7 +2448,14 @@ function defineEval(input) {
2463
2448
  expect
2464
2449
  };
2465
2450
  });
2466
- return { name, target, cases, virtual: input.virtual === true };
2451
+ return {
2452
+ name,
2453
+ target,
2454
+ cases,
2455
+ virtual: input.virtual === true,
2456
+ ...input.recordedToolMode !== void 0 ? { recordedToolMode: input.recordedToolMode } : {},
2457
+ ...input.recordedToolUnmatchedPolicy !== void 0 ? { recordedToolUnmatchedPolicy: input.recordedToolUnmatchedPolicy } : {}
2458
+ };
2467
2459
  }
2468
2460
  function normalizeForHash(value) {
2469
2461
  if (Array.isArray(value)) return value.map(normalizeForHash);
@@ -2479,9 +2471,13 @@ function normalizeForHash(value) {
2479
2471
  return value;
2480
2472
  }
2481
2473
  async function computeEvalContentHash(definition) {
2474
+ const recordedToolMode = definition.recordedToolMode ?? "next_step";
2475
+ const recordedToolUnmatchedPolicy = definition.recordedToolUnmatchedPolicy ?? "fail";
2482
2476
  const canonical = {
2483
2477
  target: normalizeForHash(definition.target),
2484
2478
  virtual: definition.virtual,
2479
+ ...recordedToolMode !== "next_step" ? { recordedToolMode } : {},
2480
+ ...recordedToolUnmatchedPolicy !== "fail" ? { recordedToolUnmatchedPolicy } : {},
2485
2481
  cases: [...definition.cases].sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0).map((c) => ({
2486
2482
  name: c.name,
2487
2483
  input: normalizeForHash(c.input),
@@ -2490,10 +2486,7 @@ async function computeEvalContentHash(definition) {
2490
2486
  expect: c.expect.map((g) => normalizeForHash(g))
2491
2487
  }))
2492
2488
  };
2493
- const serialized = JSON.stringify(canonical);
2494
- const encoded = new TextEncoder().encode(serialized);
2495
- const hashBuffer = await crypto.subtle.digest("SHA-256", encoded);
2496
- return Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
2489
+ return sha256Hex(JSON.stringify(canonical));
2497
2490
  }
2498
2491
  var serverHashMemo = /* @__PURE__ */ new WeakMap();
2499
2492
  function memoFor(client) {
@@ -2540,11 +2533,8 @@ async function runEvalSuite(client, input) {
2540
2533
  }
2541
2534
 
2542
2535
  // src/flows-ensure.ts
2543
- function isPlainObject2(value) {
2544
- return value !== null && typeof value === "object" && !Array.isArray(value);
2545
- }
2546
2536
  function normalizeConfigForHash(config) {
2547
- if (!isPlainObject2(config)) return {};
2537
+ if (!isPlainObject(config)) return {};
2548
2538
  const normalized = {};
2549
2539
  for (const key of Object.keys(config).sort()) {
2550
2540
  const value = config[key];
@@ -2565,7 +2555,7 @@ function normalizeConfigForHash(config) {
2565
2555
  return normalized;
2566
2556
  }
2567
2557
  function normalizeStepForHash(step) {
2568
- const stepObj = isPlainObject2(step) ? step : {};
2558
+ const stepObj = isPlainObject(step) ? step : {};
2569
2559
  return {
2570
2560
  type: typeof stepObj.type === "string" ? stepObj.type : "",
2571
2561
  name: typeof stepObj.name === "string" ? stepObj.name : "",
@@ -2577,14 +2567,11 @@ function normalizeStepForHash(step) {
2577
2567
  }
2578
2568
  async function computeFlowContentHash(steps) {
2579
2569
  const normalized = [...steps].sort((a, b) => {
2580
- const orderA = isPlainObject2(a) && typeof a.order === "number" ? a.order : 0;
2581
- const orderB = isPlainObject2(b) && typeof b.order === "number" ? b.order : 0;
2570
+ const orderA = isPlainObject(a) && typeof a.order === "number" ? a.order : 0;
2571
+ const orderB = isPlainObject(b) && typeof b.order === "number" ? b.order : 0;
2582
2572
  return orderA - orderB;
2583
2573
  }).map(normalizeStepForHash);
2584
- const serialized = JSON.stringify(normalized);
2585
- const encoded = new TextEncoder().encode(serialized);
2586
- const hashBuffer = await crypto.subtle.digest("SHA-256", encoded);
2587
- return Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
2574
+ return sha256Hex(JSON.stringify(normalized));
2588
2575
  }
2589
2576
  var DEFINE_FLOW_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set(["name", "steps", "evals"]);
2590
2577
  var DEFINE_FLOW_STEP_KEYS = /* @__PURE__ */ new Set([
@@ -2607,27 +2594,27 @@ function collectStepNonPortableToolRefs(config, path) {
2607
2594
  });
2608
2595
  };
2609
2596
  const scanKeys = (value, subPath) => {
2610
- if (!isPlainObject2(value)) return;
2597
+ if (!isPlainObject(value)) return;
2611
2598
  for (const key of Object.keys(value)) {
2612
2599
  if (isAccountScoped(key)) found.push(`${subPath}.${key}`);
2613
2600
  }
2614
2601
  };
2615
- if (isPlainObject2(tools)) {
2602
+ if (isPlainObject(tools)) {
2616
2603
  scanArray(tools.toolIds, `${path}.tools.toolIds`);
2617
2604
  scanKeys(tools.toolConfigs, `${path}.tools.toolConfigs`);
2618
2605
  scanKeys(tools.perToolLimits, `${path}.tools.perToolLimits`);
2619
- if (isPlainObject2(tools.approval)) {
2606
+ if (isPlainObject(tools.approval)) {
2620
2607
  scanArray(tools.approval.require, `${path}.tools.approval.require`);
2621
2608
  }
2622
- if (isPlainObject2(tools.subagentConfig)) {
2609
+ if (isPlainObject(tools.subagentConfig)) {
2623
2610
  scanArray(tools.subagentConfig.toolPool, `${path}.tools.subagentConfig.toolPool`);
2624
2611
  }
2625
- if (isPlainObject2(tools.codeModeConfig)) {
2612
+ if (isPlainObject(tools.codeModeConfig)) {
2626
2613
  scanArray(tools.codeModeConfig.toolPool, `${path}.tools.codeModeConfig.toolPool`);
2627
2614
  }
2628
2615
  if (Array.isArray(tools.runtimeTools)) {
2629
2616
  tools.runtimeTools.forEach((runtimeTool, i) => {
2630
- if (!isPlainObject2(runtimeTool) || !isPlainObject2(runtimeTool.config)) return;
2617
+ if (!isPlainObject(runtimeTool) || !isPlainObject(runtimeTool.config)) return;
2631
2618
  const base = `${path}.tools.runtimeTools[${i}].config`;
2632
2619
  const rtConfig = runtimeTool.config;
2633
2620
  if (runtimeTool.toolType === "subagent" && isRawId(rtConfig.agentId, "agent_")) {
@@ -2648,7 +2635,7 @@ function collectStepNonPortableToolRefs(config, path) {
2648
2635
  const nested = config[branch];
2649
2636
  if (!Array.isArray(nested)) continue;
2650
2637
  nested.forEach((nestedStep, i) => {
2651
- if (isPlainObject2(nestedStep) && isPlainObject2(nestedStep.config)) {
2638
+ if (isPlainObject(nestedStep) && isPlainObject(nestedStep.config)) {
2652
2639
  found.push(
2653
2640
  ...collectStepNonPortableToolRefs(nestedStep.config, `${path}.${branch}[${i}].config`)
2654
2641
  );
@@ -2674,7 +2661,7 @@ function defineFlow(input) {
2674
2661
  throw new Error('defineFlow requires a non-empty "steps" array');
2675
2662
  }
2676
2663
  const steps = input.steps.map((step, index) => {
2677
- if (!isPlainObject2(step)) {
2664
+ if (!isPlainObject(step)) {
2678
2665
  throw new Error(`defineFlow: steps[${index}] must be an object`);
2679
2666
  }
2680
2667
  if (typeof step.type !== "string" || step.type.length === 0) {
@@ -2689,7 +2676,7 @@ function defineFlow(input) {
2689
2676
  `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.)`
2690
2677
  );
2691
2678
  }
2692
- const config = isPlainObject2(step.config) ? step.config : void 0;
2679
+ const config = isPlainObject(step.config) ? step.config : void 0;
2693
2680
  if (config) {
2694
2681
  const nonPortable = collectStepNonPortableToolRefs(config, `steps[${index}].config`);
2695
2682
  if (nonPortable.length > 0) {
@@ -2716,7 +2703,7 @@ function defineFlow(input) {
2716
2703
  }
2717
2704
  const seenEvalNames = /* @__PURE__ */ new Set();
2718
2705
  evals = input.evals.map((evalInput, i) => {
2719
- if (!isPlainObject2(evalInput)) {
2706
+ if (!isPlainObject(evalInput)) {
2720
2707
  throw new Error(`defineFlow: evals[${i}] must be an object`);
2721
2708
  }
2722
2709
  if (evalInput.virtual === true) {
@@ -2780,7 +2767,7 @@ function parseRequestError(err) {
2780
2767
  }
2781
2768
  function toConflictError(err) {
2782
2769
  const { status, body } = parseRequestError(err);
2783
- if (status !== 409 || !isPlainObject2(body)) return null;
2770
+ if (status !== 409 || !isPlainObject(body)) return null;
2784
2771
  const code = body.code;
2785
2772
  if (code !== "external_modification" && code !== "remote_changed") return null;
2786
2773
  return new FlowEnsureConflictError(
@@ -3145,6 +3132,7 @@ var RuntypeFlowBuilder = class {
3145
3132
  markdownIfAvailable: config.markdownIfAvailable,
3146
3133
  fetchMethod: config.fetchMethod === "http" ? "standard" : config.fetchMethod,
3147
3134
  firecrawl: config.firecrawl,
3135
+ massive: config.massive,
3148
3136
  outputVariable: config.outputVariable,
3149
3137
  errorHandling: config.errorHandling,
3150
3138
  defaultValue: config.defaultValue,
@@ -3305,7 +3293,6 @@ var RuntypeFlowBuilder = class {
3305
3293
  fieldsToExclude: config.fieldsToExclude,
3306
3294
  availableFields: config.availableFields,
3307
3295
  outputVariable: config.outputVariable,
3308
- fields: config.fields,
3309
3296
  includeMetadata: config.includeMetadata,
3310
3297
  streamOutput: config.streamOutput
3311
3298
  },
@@ -3398,7 +3385,6 @@ var RuntypeFlowBuilder = class {
3398
3385
  vectorStore: config.vectorStore,
3399
3386
  weaviateConfig: config.weaviateConfig,
3400
3387
  vectorizeConfig: config.vectorizeConfig,
3401
- pineconeConfig: config.pineconeConfig,
3402
3388
  limit: config.limit,
3403
3389
  threshold: config.threshold,
3404
3390
  metadataFilters: config.metadataFilters,
@@ -3427,7 +3413,6 @@ var RuntypeFlowBuilder = class {
3427
3413
  recordType: config.recordType,
3428
3414
  recordName: config.recordName,
3429
3415
  textField: config.textField,
3430
- storeInRecord: config.storeInRecord,
3431
3416
  embeddingModel: config.embeddingModel,
3432
3417
  maxLength: config.maxLength,
3433
3418
  inputMode: config.inputMode,
@@ -3435,7 +3420,6 @@ var RuntypeFlowBuilder = class {
3435
3420
  itemAlias: config.itemAlias,
3436
3421
  textTemplate: config.textTemplate,
3437
3422
  batchSize: config.batchSize,
3438
- vectorStore: config.vectorStore,
3439
3423
  outputVariable: config.outputVariable,
3440
3424
  streamOutput: config.streamOutput
3441
3425
  },
@@ -3484,51 +3468,6 @@ var RuntypeFlowBuilder = class {
3484
3468
  );
3485
3469
  return this;
3486
3470
  }
3487
- /**
3488
- * Add a send text step
3489
- */
3490
- sendText(config) {
3491
- this.addStep(
3492
- "send-text",
3493
- config.name,
3494
- {
3495
- to: config.to,
3496
- from: config.from,
3497
- message: config.message,
3498
- outputVariable: config.outputVariable,
3499
- errorHandling: config.errorHandling,
3500
- streamOutput: config.streamOutput
3501
- },
3502
- config.enabled,
3503
- config.when
3504
- );
3505
- return this;
3506
- }
3507
- /**
3508
- * Add a fetch GitHub step
3509
- */
3510
- fetchGitHub(config) {
3511
- this.addStep(
3512
- "fetch-github",
3513
- config.name,
3514
- {
3515
- repository: config.repository,
3516
- branch: config.branch,
3517
- path: config.path,
3518
- token: config.token,
3519
- outputVariable: config.outputVariable,
3520
- contentType: config.contentType,
3521
- includePatterns: config.includePatterns,
3522
- excludePatterns: config.excludePatterns,
3523
- compress: config.compress,
3524
- style: config.style,
3525
- streamOutput: config.streamOutput
3526
- },
3527
- config.enabled,
3528
- config.when
3529
- );
3530
- return this;
3531
- }
3532
3471
  /** Add an api-call step. */
3533
3472
  apiCall(config) {
3534
3473
  return this.addRawStep("api-call", config);
@@ -4075,6 +4014,30 @@ var EvalSuitesNamespace = class {
4075
4014
  cases
4076
4015
  });
4077
4016
  }
4017
+ /**
4018
+ * Capture a test case from a real agent run ("fork here and test the next
4019
+ * step"): freezes the run's conversation history up to a fork point, attaches
4020
+ * every recorded tool result as an editable mock, and saves it with origin
4021
+ * `saved_from_run`. Capture only — reads the run, never re-executes it.
4022
+ */
4023
+ async addCaseFromExecution(suiteId, input) {
4024
+ return this.getClient().post(
4025
+ `/eval/suites/${suiteId}/cases/from-execution`,
4026
+ input
4027
+ );
4028
+ }
4029
+ /**
4030
+ * Dry-run of {@link addCaseFromExecution}: reconstruct an agent execution
4031
+ * exactly as capture would and return its recorded actions plus the fork
4032
+ * index each maps to (and whether the case would be fully replayable), so a
4033
+ * caller can build a fork picker without re-deriving the seed math. Reads
4034
+ * only — nothing is written.
4035
+ */
4036
+ async getCapturePreview(executionId) {
4037
+ return this.getClient().get(
4038
+ `/eval/executions/${executionId}/capture-preview`
4039
+ );
4040
+ }
4078
4041
  /** Edit, enable, or disable a test case. */
4079
4042
  async updateCase(suiteId, caseId, input) {
4080
4043
  return this.getClient().patch(
@@ -4088,6 +4051,55 @@ var EvalSuitesNamespace = class {
4088
4051
  `/eval/suites/${suiteId}/cases/${caseId}`
4089
4052
  );
4090
4053
  }
4054
+ /**
4055
+ * List a suite's machine-proposed cases (the review queue). Every
4056
+ * generation source lands here; nothing enters the suite without an accept.
4057
+ */
4058
+ async listProposals(suiteId, params) {
4059
+ return this.getClient().get(
4060
+ `/eval/suites/${suiteId}/proposals`,
4061
+ params
4062
+ );
4063
+ }
4064
+ /**
4065
+ * Accept a proposal — materializes it as an eval case and backlinks it.
4066
+ * Pass `options.case` to save an edited body instead (recorded as
4067
+ * `edited_accepted`; the machine original stays on the proposal for audit).
4068
+ */
4069
+ async acceptProposal(suiteId, proposalId, options) {
4070
+ return this.getClient().post(
4071
+ `/eval/suites/${suiteId}/proposals/${proposalId}/accept`,
4072
+ options ?? {}
4073
+ );
4074
+ }
4075
+ /** Reject a proposal. The row survives as audit. */
4076
+ async rejectProposal(suiteId, proposalId) {
4077
+ return this.getClient().post(
4078
+ `/eval/suites/${suiteId}/proposals/${proposalId}/reject`,
4079
+ {}
4080
+ );
4081
+ }
4082
+ /**
4083
+ * Generate test-case proposals from the target's definition, fanned out
4084
+ * over an explicit diversity matrix (category × persona) and filtered for
4085
+ * gradeability. Results land as PROPOSALS for review — never directly in
4086
+ * the suite. Reserves one daily-eval quota slot per call.
4087
+ */
4088
+ async generateCases(suiteId, input) {
4089
+ return this.getClient().post(
4090
+ `/eval/suites/${suiteId}/generate-cases`,
4091
+ input ?? {}
4092
+ );
4093
+ }
4094
+ /**
4095
+ * The coverage meter: which of the target's tools and instruction clauses
4096
+ * the suite's cases and graders already exercise. The instruction inventory
4097
+ * is cached server-side and refreshed when the definition changes; a cache
4098
+ * miss spends a metered model call, so this requires eval-write scope.
4099
+ */
4100
+ async getCoverage(suiteId) {
4101
+ return this.getClient().get(`/eval/suites/${suiteId}/coverage`);
4102
+ }
4091
4103
  };
4092
4104
 
4093
4105
  // src/evals-namespace.ts
@@ -4261,6 +4273,30 @@ var EvalsNamespace = class {
4261
4273
  async pull(name) {
4262
4274
  return pullEval(this.getClient(), name);
4263
4275
  }
4276
+ /**
4277
+ * Split one plain-language AI-grader criterion carrying several obligations
4278
+ * into focused, independently judgeable sub-checks. Authoring assist only:
4279
+ * nothing is persisted — review the proposal, then save each accepted
4280
+ * sub-check as its own AI grader row. A single returned sub-check means the
4281
+ * criterion is already focused.
4282
+ *
4283
+ * @example
4284
+ * ```typescript
4285
+ * const { subChecks } = await Runtype.evals.decomposeCriteria(
4286
+ * 'Confirms the order number before issuing a refund, and never promises a delivery date.'
4287
+ * )
4288
+ * // In a defineEval suite, each accepted sub-check becomes its own judge row:
4289
+ * const graders = subChecks.map((s) => judge(s.criteria))
4290
+ * ```
4291
+ */
4292
+ async decomposeCriteria(criteria) {
4293
+ if (typeof criteria !== "string" || criteria.trim().length === 0) {
4294
+ throw new Error("decomposeCriteria() requires non-empty criteria");
4295
+ }
4296
+ return this.getClient().post("/eval/graders/decompose", {
4297
+ criteria
4298
+ });
4299
+ }
4264
4300
  /**
4265
4301
  * Run an eval suite synchronously and return the suite score + per-case grader
4266
4302
  * outcomes — the executing counterpart of `ensure`, powering the `runtype
@@ -4295,6 +4331,28 @@ var EvalsNamespace = class {
4295
4331
  const client = this.getClient();
4296
4332
  return client.get(`/eval/runs/${runId}/scores`);
4297
4333
  }
4334
+ /**
4335
+ * Record a lightweight human review of one AI-grader verdict ("the grader
4336
+ * got this right / wrong"), using the `scoreId` on a persisted outcome from
4337
+ * `getRunScores`. Reviews accumulate into the suite's judge-trust display
4338
+ * ("agrees with you N of M times"). Pass `null` to clear an earlier review.
4339
+ *
4340
+ * @example
4341
+ * ```typescript
4342
+ * const scores = await Runtype.evals.getRunScores(runId)
4343
+ * const outcome = scores.cases[0]?.outcomes.find((o) => o.kind === 'ai')
4344
+ * if (outcome?.scoreId) {
4345
+ * await Runtype.evals.reviewScore(outcome.scoreId, 'disagree')
4346
+ * }
4347
+ * ```
4348
+ */
4349
+ async reviewScore(scoreId, verdict) {
4350
+ const client = this.getClient();
4351
+ return client.post(
4352
+ `/eval/scores/${scoreId}/review`,
4353
+ { verdict }
4354
+ );
4355
+ }
4298
4356
  /**
4299
4357
  * Get evaluation status by ID
4300
4358
  *
@@ -4413,42 +4471,21 @@ var PromptsNamespace = class {
4413
4471
  };
4414
4472
 
4415
4473
  // src/skills-ensure.ts
4416
- function isPlainObject3(value) {
4417
- return value !== null && typeof value === "object" && !Array.isArray(value);
4418
- }
4419
- function normalizeValue(value) {
4420
- if (Array.isArray(value)) {
4421
- return value.map((item) => normalizeValue(item));
4422
- }
4423
- if (isPlainObject3(value)) {
4424
- const normalized = {};
4425
- for (const key of Object.keys(value).sort()) {
4426
- const entry = value[key];
4427
- if (entry === void 0 || entry === null) continue;
4428
- normalized[key] = normalizeValue(entry);
4429
- }
4430
- return normalized;
4431
- }
4432
- return value;
4433
- }
4434
4474
  function normalizeSkillDefinition(definition) {
4435
- const manifest = isPlainObject3(definition.manifest) ? definition.manifest : {};
4436
- const rawFrontmatter = isPlainObject3(manifest.frontmatter) ? manifest.frontmatter : {};
4475
+ const manifest = isPlainObject(definition.manifest) ? definition.manifest : {};
4476
+ const rawFrontmatter = isPlainObject(manifest.frontmatter) ? manifest.frontmatter : {};
4437
4477
  const frontmatterWithoutName = {};
4438
4478
  for (const key of Object.keys(rawFrontmatter)) {
4439
4479
  if (key === "name") continue;
4440
4480
  frontmatterWithoutName[key] = rawFrontmatter[key];
4441
4481
  }
4442
4482
  const frontmatter = normalizeValue(frontmatterWithoutName);
4443
- const runtype = isPlainObject3(manifest.runtype) ? normalizeValue(manifest.runtype) : {};
4483
+ const runtype = isPlainObject(manifest.runtype) ? normalizeValue(manifest.runtype) : {};
4444
4484
  const body = typeof manifest.body === "string" ? manifest.body : "";
4445
4485
  return { frontmatter, runtype, body };
4446
4486
  }
4447
4487
  async function computeSkillContentHash(definition) {
4448
- const serialized = JSON.stringify(normalizeSkillDefinition(definition));
4449
- const encoded = new TextEncoder().encode(serialized);
4450
- const hashBuffer = await crypto.subtle.digest("SHA-256", encoded);
4451
- return Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
4488
+ return sha256Hex(JSON.stringify(normalizeSkillDefinition(definition)));
4452
4489
  }
4453
4490
  var DEFINE_SKILL_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set(["name", "manifest"]);
4454
4491
  function defineSkill(input) {
@@ -4458,7 +4495,7 @@ function defineSkill(input) {
4458
4495
  if (typeof input.name !== "string" || input.name.length === 0) {
4459
4496
  throw new Error('defineSkill requires a non-empty string "name"');
4460
4497
  }
4461
- if (!isPlainObject3(input.manifest)) {
4498
+ if (!isPlainObject(input.manifest)) {
4462
4499
  throw new Error('defineSkill requires a "manifest" object ({ frontmatter, runtype, body })');
4463
4500
  }
4464
4501
  const unknownKeys = Object.keys(input).filter((key) => !DEFINE_SKILL_TOP_LEVEL_KEYS.has(key));
@@ -4468,7 +4505,7 @@ function defineSkill(input) {
4468
4505
  );
4469
4506
  }
4470
4507
  const frontmatter = input.manifest.frontmatter;
4471
- if (!isPlainObject3(frontmatter) || typeof frontmatter.name !== "string") {
4508
+ if (!isPlainObject(frontmatter) || typeof frontmatter.name !== "string") {
4472
4509
  throw new Error("defineSkill: manifest.frontmatter.name is required");
4473
4510
  }
4474
4511
  if (frontmatter.name !== input.name) {
@@ -4509,7 +4546,7 @@ function parseRequestError2(err) {
4509
4546
  }
4510
4547
  function toConflictError2(err) {
4511
4548
  const { status, body } = parseRequestError2(err);
4512
- if (status !== 409 || !isPlainObject3(body)) return null;
4549
+ if (status !== 409 || !isPlainObject(body)) return null;
4513
4550
  const code = body.code;
4514
4551
  if (code !== "external_modification" && code !== "remote_changed") return null;
4515
4552
  return new SkillEnsureConflictError(
@@ -4858,14 +4895,14 @@ var AGENT_CONFIG_KEYS = [
4858
4895
  "tenancyStrategy"
4859
4896
  ];
4860
4897
  var AGENT_CONFIG_KEY_LIST = [...AGENT_CONFIG_KEYS].sort();
4861
- function isPlainObject4(value) {
4898
+ function isPlainObject2(value) {
4862
4899
  return value !== null && typeof value === "object" && !Array.isArray(value);
4863
4900
  }
4864
4901
  function normalizeValue2(value) {
4865
4902
  if (Array.isArray(value)) {
4866
4903
  return value.map((item) => normalizeValue2(item));
4867
4904
  }
4868
- if (isPlainObject4(value)) {
4905
+ if (isPlainObject2(value)) {
4869
4906
  const normalized = {};
4870
4907
  for (const key of Object.keys(value).sort()) {
4871
4908
  const entry = value[key];
@@ -4878,7 +4915,7 @@ function normalizeValue2(value) {
4878
4915
  }
4879
4916
  function normalizeAgentDefinition(definition) {
4880
4917
  const config = {};
4881
- const rawConfig = isPlainObject4(definition.config) ? definition.config : {};
4918
+ const rawConfig = isPlainObject2(definition.config) ? definition.config : {};
4882
4919
  for (const key of AGENT_CONFIG_KEY_LIST) {
4883
4920
  const value = rawConfig[key];
4884
4921
  if (value === void 0 || value === null) continue;
@@ -4900,7 +4937,7 @@ async function computeAgentContentHash(definition) {
4900
4937
  var DEFINE_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set(["name", "description", "icon", ...AGENT_CONFIG_KEYS]);
4901
4938
  function collectNonPortableToolRefs(config) {
4902
4939
  const tools = config.tools;
4903
- if (!isPlainObject4(tools)) return [];
4940
+ if (!isPlainObject2(tools)) return [];
4904
4941
  const found = [];
4905
4942
  const isAccountScoped = (ref) => typeof ref === "string" && ref.startsWith("tool_");
4906
4943
  const scanArray = (value, path) => {
@@ -4910,7 +4947,7 @@ function collectNonPortableToolRefs(config) {
4910
4947
  });
4911
4948
  };
4912
4949
  const scanKeys = (value, path) => {
4913
- if (!isPlainObject4(value)) return;
4950
+ if (!isPlainObject2(value)) return;
4914
4951
  for (const key of Object.keys(value)) {
4915
4952
  if (isAccountScoped(key)) found.push(`${path}.${key}`);
4916
4953
  }
@@ -4918,16 +4955,16 @@ function collectNonPortableToolRefs(config) {
4918
4955
  scanArray(tools.toolIds, "tools.toolIds");
4919
4956
  scanKeys(tools.toolConfigs, "tools.toolConfigs");
4920
4957
  scanKeys(tools.perToolLimits, "tools.perToolLimits");
4921
- if (isPlainObject4(tools.approval)) scanArray(tools.approval.require, "tools.approval.require");
4922
- if (isPlainObject4(tools.subagentConfig)) {
4958
+ if (isPlainObject2(tools.approval)) scanArray(tools.approval.require, "tools.approval.require");
4959
+ if (isPlainObject2(tools.subagentConfig)) {
4923
4960
  scanArray(tools.subagentConfig.toolPool, "tools.subagentConfig.toolPool");
4924
4961
  }
4925
- if (isPlainObject4(tools.codeModeConfig)) {
4962
+ if (isPlainObject2(tools.codeModeConfig)) {
4926
4963
  scanArray(tools.codeModeConfig.toolPool, "tools.codeModeConfig.toolPool");
4927
4964
  }
4928
4965
  if (Array.isArray(tools.runtimeTools)) {
4929
4966
  tools.runtimeTools.forEach((runtimeTool, i) => {
4930
- if (!isPlainObject4(runtimeTool) || !isPlainObject4(runtimeTool.config)) return;
4967
+ if (!isPlainObject2(runtimeTool) || !isPlainObject2(runtimeTool.config)) return;
4931
4968
  const base = `tools.runtimeTools[${i}].config`;
4932
4969
  const rtConfig = runtimeTool.config;
4933
4970
  if (runtimeTool.toolType === "subagent" && typeof rtConfig.agentId === "string" && rtConfig.agentId.startsWith("agent_")) {
@@ -5001,7 +5038,7 @@ function parseRequestError3(err) {
5001
5038
  }
5002
5039
  function toConflictError3(err) {
5003
5040
  const { status, body } = parseRequestError3(err);
5004
- if (status !== 409 || !isPlainObject4(body)) return null;
5041
+ if (status !== 409 || !isPlainObject2(body)) return null;
5005
5042
  const code = body.code;
5006
5043
  if (code !== "external_modification" && code !== "remote_changed") return null;
5007
5044
  return new AgentEnsureConflictError(
@@ -5103,27 +5140,9 @@ var AgentsNamespace = class {
5103
5140
  };
5104
5141
 
5105
5142
  // src/tools-ensure.ts
5106
- function isPlainObject5(value) {
5107
- return value !== null && typeof value === "object" && !Array.isArray(value);
5108
- }
5109
- function normalizeValue3(value) {
5110
- if (Array.isArray(value)) {
5111
- return value.map((item) => normalizeValue3(item));
5112
- }
5113
- if (isPlainObject5(value)) {
5114
- const normalized = {};
5115
- for (const key of Object.keys(value).sort()) {
5116
- const entry = value[key];
5117
- if (entry === void 0 || entry === null) continue;
5118
- normalized[key] = normalizeValue3(entry);
5119
- }
5120
- return normalized;
5121
- }
5122
- return value;
5123
- }
5124
5143
  function normalizeToolDefinition(definition) {
5125
- const parametersSchema = isPlainObject5(definition.parametersSchema) ? normalizeValue3(definition.parametersSchema) : {};
5126
- const config = isPlainObject5(definition.config) ? normalizeValue3(definition.config) : {};
5144
+ const parametersSchema = isPlainObject(definition.parametersSchema) ? normalizeValue(definition.parametersSchema) : {};
5145
+ const config = isPlainObject(definition.config) ? normalizeValue(definition.config) : {};
5127
5146
  return {
5128
5147
  toolType: definition.toolType,
5129
5148
  ...definition.description ? { description: definition.description } : {},
@@ -5132,10 +5151,7 @@ function normalizeToolDefinition(definition) {
5132
5151
  };
5133
5152
  }
5134
5153
  async function computeToolContentHash(definition) {
5135
- const serialized = JSON.stringify(normalizeToolDefinition(definition));
5136
- const encoded = new TextEncoder().encode(serialized);
5137
- const hashBuffer = await crypto.subtle.digest("SHA-256", encoded);
5138
- return Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
5154
+ return sha256Hex(JSON.stringify(normalizeToolDefinition(definition)));
5139
5155
  }
5140
5156
  var DEFINE_TOOL_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set([
5141
5157
  "name",
@@ -5168,10 +5184,10 @@ function defineTool(input) {
5168
5184
  `defineTool requires "toolType" to be one of: ${[...TOOL_DEFINITION_TYPES].join(", ")}`
5169
5185
  );
5170
5186
  }
5171
- if (!isPlainObject5(input.parametersSchema)) {
5187
+ if (!isPlainObject(input.parametersSchema)) {
5172
5188
  throw new Error('defineTool requires a "parametersSchema" object (a JSON Schema)');
5173
5189
  }
5174
- if (!isPlainObject5(input.config)) {
5190
+ if (!isPlainObject(input.config)) {
5175
5191
  throw new Error('defineTool requires a "config" object');
5176
5192
  }
5177
5193
  const unknownKeys = Object.keys(input).filter((key) => !DEFINE_TOOL_TOP_LEVEL_KEYS.has(key));
@@ -5219,7 +5235,7 @@ function parseRequestError4(err) {
5219
5235
  }
5220
5236
  function toConflictError4(err) {
5221
5237
  const { status, body } = parseRequestError4(err);
5222
- if (status !== 409 || !isPlainObject5(body)) return null;
5238
+ if (status !== 409 || !isPlainObject(body)) return null;
5223
5239
  const code = body.code;
5224
5240
  if (code !== "external_modification" && code !== "remote_changed") return null;
5225
5241
  return new ToolEnsureConflictError(
@@ -5339,26 +5355,8 @@ var ToolsNamespace = class {
5339
5355
  };
5340
5356
 
5341
5357
  // src/products-ensure.ts
5342
- function isPlainObject6(value) {
5343
- return value !== null && typeof value === "object" && !Array.isArray(value);
5344
- }
5345
- function normalizeValue4(value) {
5346
- if (Array.isArray(value)) {
5347
- return value.map((item) => normalizeValue4(item));
5348
- }
5349
- if (isPlainObject6(value)) {
5350
- const normalized = {};
5351
- for (const key of Object.keys(value).sort()) {
5352
- const entry = value[key];
5353
- if (entry === void 0 || entry === null) continue;
5354
- normalized[key] = normalizeValue4(entry);
5355
- }
5356
- return normalized;
5357
- }
5358
- return value;
5359
- }
5360
5358
  function normalizeProductDefinition(definition) {
5361
- const spec = isPlainObject6(definition.spec) ? normalizeValue4(definition.spec) : {};
5359
+ const spec = isPlainObject(definition.spec) ? normalizeValue(definition.spec) : {};
5362
5360
  return {
5363
5361
  ...definition.description ? { description: definition.description } : {},
5364
5362
  ...definition.icon ? { icon: definition.icon } : {},
@@ -5366,10 +5364,7 @@ function normalizeProductDefinition(definition) {
5366
5364
  };
5367
5365
  }
5368
5366
  async function computeProductContentHash(definition) {
5369
- const serialized = JSON.stringify(normalizeProductDefinition(definition));
5370
- const encoded = new TextEncoder().encode(serialized);
5371
- const hashBuffer = await crypto.subtle.digest("SHA-256", encoded);
5372
- return Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
5367
+ return sha256Hex(JSON.stringify(normalizeProductDefinition(definition)));
5373
5368
  }
5374
5369
  var DEFINE_PRODUCT_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set(["name", "description", "icon", "spec"]);
5375
5370
  function defineProduct(input) {
@@ -5385,7 +5380,7 @@ function defineProduct(input) {
5385
5380
  if (input.icon != null && typeof input.icon !== "string") {
5386
5381
  throw new Error('defineProduct "icon" must be a string when provided');
5387
5382
  }
5388
- if (input.spec != null && !isPlainObject6(input.spec)) {
5383
+ if (input.spec != null && !isPlainObject(input.spec)) {
5389
5384
  throw new Error('defineProduct "spec" must be an object when provided');
5390
5385
  }
5391
5386
  const unknownKeys = Object.keys(input).filter((key) => !DEFINE_PRODUCT_TOP_LEVEL_KEYS.has(key));
@@ -5432,7 +5427,7 @@ function parseRequestError5(err) {
5432
5427
  }
5433
5428
  function toConflictError5(err) {
5434
5429
  const { status, body } = parseRequestError5(err);
5435
- if (status !== 409 || !isPlainObject6(body)) return null;
5430
+ if (status !== 409 || !isPlainObject(body)) return null;
5436
5431
  const code = body.code;
5437
5432
  if (code !== "external_modification" && code !== "remote_changed") return null;
5438
5433
  return new ProductEnsureConflictError(
@@ -5513,50 +5508,31 @@ async function pullProduct(client, name) {
5513
5508
  }
5514
5509
 
5515
5510
  // src/products-ensure-fpo.ts
5516
- function isPlainObject7(value) {
5517
- return value !== null && typeof value === "object" && !Array.isArray(value);
5518
- }
5519
- function normalizeValue5(value) {
5520
- if (Array.isArray(value)) {
5521
- return value.map((item) => normalizeValue5(item));
5522
- }
5523
- if (isPlainObject7(value)) {
5524
- const normalized = {};
5525
- for (const key of Object.keys(value).sort()) {
5526
- const entry = value[key];
5527
- if (entry === void 0 || entry === null) continue;
5528
- normalized[key] = normalizeValue5(entry);
5529
- }
5530
- return normalized;
5531
- }
5532
- return value;
5533
- }
5534
5511
  function normalizeFpoDefinition(fpo) {
5535
- const productInput = isPlainObject7(fpo.product) ? fpo.product : {};
5512
+ const productInput = isPlainObject(fpo.product) ? fpo.product : {};
5536
5513
  const { name: _identityName, ...productRest } = productInput;
5537
- const product = normalizeValue5(productRest);
5514
+ const product = normalizeValue(productRest);
5538
5515
  return {
5539
- ...fpo.version !== void 0 && fpo.version !== null ? { version: normalizeValue5(fpo.version) } : {},
5516
+ ...fpo.version !== void 0 && fpo.version !== null ? { version: normalizeValue(fpo.version) } : {},
5540
5517
  product,
5541
- capabilities: normalizeValue5(fpo.capabilities ?? []),
5542
- tools: normalizeValue5(fpo.tools ?? []),
5543
- surfaces: normalizeValue5(fpo.surfaces ?? []),
5544
- ...fpo.records !== void 0 && fpo.records !== null ? { records: normalizeValue5(fpo.records) } : {},
5545
- ...fpo.schedules !== void 0 && fpo.schedules !== null ? { schedules: normalizeValue5(fpo.schedules) } : {},
5546
- ...fpo.secrets !== void 0 && fpo.secrets !== null ? { secrets: normalizeValue5(fpo.secrets) } : {}
5518
+ capabilities: normalizeValue(fpo.capabilities ?? []),
5519
+ tools: normalizeValue(fpo.tools ?? []),
5520
+ surfaces: normalizeValue(fpo.surfaces ?? []),
5521
+ ...fpo.records !== void 0 && fpo.records !== null ? { records: normalizeValue(fpo.records) } : {},
5522
+ ...fpo.schedules !== void 0 && fpo.schedules !== null ? { schedules: normalizeValue(fpo.schedules) } : {},
5523
+ ...fpo.secrets !== void 0 && fpo.secrets !== null ? { secrets: normalizeValue(fpo.secrets) } : {},
5524
+ ...fpo.evals !== void 0 && fpo.evals !== null ? { evals: normalizeValue(fpo.evals) } : {},
5525
+ ...fpo.skills !== void 0 && fpo.skills !== null ? { skills: normalizeValue(fpo.skills) } : {}
5547
5526
  };
5548
5527
  }
5549
5528
  async function computeFpoContentHash(fpo) {
5550
- const serialized = JSON.stringify(normalizeFpoDefinition(fpo));
5551
- const encoded = new TextEncoder().encode(serialized);
5552
- const hashBuffer = await crypto.subtle.digest("SHA-256", encoded);
5553
- return Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
5529
+ return sha256Hex(JSON.stringify(normalizeFpoDefinition(fpo)));
5554
5530
  }
5555
5531
  function defineFpo(fpo) {
5556
- if (!isPlainObject7(fpo)) {
5532
+ if (!isPlainObject(fpo)) {
5557
5533
  throw new Error("defineFpo requires an FPO object");
5558
5534
  }
5559
- const product = isPlainObject7(fpo.product) ? fpo.product : void 0;
5535
+ const product = isPlainObject(fpo.product) ? fpo.product : void 0;
5560
5536
  if (!product || typeof product.name !== "string" || product.name.length === 0) {
5561
5537
  throw new Error('defineFpo requires a non-empty "product.name" (the converge identity)');
5562
5538
  }
@@ -5652,26 +5628,8 @@ var ProductsNamespace = class {
5652
5628
  };
5653
5629
 
5654
5630
  // src/surfaces-ensure.ts
5655
- function isPlainObject8(value) {
5656
- return value !== null && typeof value === "object" && !Array.isArray(value);
5657
- }
5658
- function normalizeValue6(value) {
5659
- if (Array.isArray(value)) {
5660
- return value.map((item) => normalizeValue6(item));
5661
- }
5662
- if (isPlainObject8(value)) {
5663
- const normalized = {};
5664
- for (const key of Object.keys(value).sort()) {
5665
- const entry = value[key];
5666
- if (entry === void 0 || entry === null) continue;
5667
- normalized[key] = normalizeValue6(entry);
5668
- }
5669
- return normalized;
5670
- }
5671
- return value;
5672
- }
5673
5631
  function normalizeSurfaceDefinition(definition) {
5674
- const behavior = isPlainObject8(definition.behavior) ? normalizeValue6({ type: definition.type, ...definition.behavior }) : { type: definition.type };
5632
+ const behavior = isPlainObject(definition.behavior) ? normalizeValue({ type: definition.type, ...definition.behavior }) : { type: definition.type };
5675
5633
  return {
5676
5634
  type: definition.type,
5677
5635
  behavior,
@@ -5680,10 +5638,7 @@ function normalizeSurfaceDefinition(definition) {
5680
5638
  };
5681
5639
  }
5682
5640
  async function computeSurfaceContentHash(definition) {
5683
- const serialized = JSON.stringify(normalizeSurfaceDefinition(definition));
5684
- const encoded = new TextEncoder().encode(serialized);
5685
- const hashBuffer = await crypto.subtle.digest("SHA-256", encoded);
5686
- return Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
5641
+ return sha256Hex(JSON.stringify(normalizeSurfaceDefinition(definition)));
5687
5642
  }
5688
5643
  var DEFINE_SURFACE_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set([
5689
5644
  "name",
@@ -5724,13 +5679,13 @@ function defineSurface(input) {
5724
5679
  `defineSurface requires "type" to be one of: ${[...SURFACE_DEFINITION_TYPES].join(", ")}`
5725
5680
  );
5726
5681
  }
5727
- if (input.behavior !== void 0 && !isPlainObject8(input.behavior)) {
5682
+ if (input.behavior !== void 0 && !isPlainObject(input.behavior)) {
5728
5683
  throw new Error('defineSurface "behavior" must be an object when provided');
5729
5684
  }
5730
- if (input.inbound !== void 0 && !isPlainObject8(input.inbound)) {
5685
+ if (input.inbound !== void 0 && !isPlainObject(input.inbound)) {
5731
5686
  throw new Error('defineSurface "inbound" must be an object when provided');
5732
5687
  }
5733
- if (input.outbound !== void 0 && !isPlainObject8(input.outbound)) {
5688
+ if (input.outbound !== void 0 && !isPlainObject(input.outbound)) {
5734
5689
  throw new Error('defineSurface "outbound" must be an object when provided');
5735
5690
  }
5736
5691
  if (input.status !== void 0 && !["draft", "active", "paused"].includes(input.status)) {
@@ -5786,7 +5741,7 @@ function parseRequestError6(err) {
5786
5741
  }
5787
5742
  function toConflictError6(err) {
5788
5743
  const { status, body } = parseRequestError6(err);
5789
- if (status !== 409 || !isPlainObject8(body)) return null;
5744
+ if (status !== 409 || !isPlainObject(body)) return null;
5790
5745
  const code = body.code;
5791
5746
  if (code !== "external_modification" && code !== "remote_changed") return null;
5792
5747
  return new SurfaceEnsureConflictError(
@@ -6399,7 +6354,7 @@ var Runtype = class {
6399
6354
 
6400
6355
  // src/version.ts
6401
6356
  var FALLBACK_VERSION = "0.0.0";
6402
- var SDK_VERSION = "5.9.0".length > 0 ? "5.9.0" : FALLBACK_VERSION;
6357
+ var SDK_VERSION = "6.1.3".length > 0 ? "6.1.3" : FALLBACK_VERSION;
6403
6358
  var RUNTYPE_CLIENT_KIND = "sdk";
6404
6359
  var SDK_USER_AGENT = `runtype-sdk/${SDK_VERSION} (typescript)`;
6405
6360
 
@@ -8643,6 +8598,69 @@ var RecordsEndpoint = class {
8643
8598
  });
8644
8599
  }
8645
8600
  };
8601
+ var CollectionsEndpoint = class {
8602
+ constructor(client) {
8603
+ this.client = client;
8604
+ }
8605
+ /**
8606
+ * List collections with cursor pagination. `includeCount: true` adds
8607
+ * per-collection record counts.
8608
+ */
8609
+ async list(params) {
8610
+ return this.client.get("/collections", params);
8611
+ }
8612
+ /**
8613
+ * Get a collection by slug. `includeHistory: true` embeds the append-only
8614
+ * schema version history.
8615
+ */
8616
+ async get(slug, params) {
8617
+ return this.client.get(`/collections/${slug}`, params);
8618
+ }
8619
+ /**
8620
+ * Register a record type as a collection. `validationMode` defaults to
8621
+ * `off`, so creating a collection changes no existing behavior.
8622
+ */
8623
+ async create(data) {
8624
+ return this.client.post("/collections", data);
8625
+ }
8626
+ /**
8627
+ * Update display fields, validation mode, or the schema. Breaking schema
8628
+ * changes are rejected while the resulting mode is `enforce`; transitioning
8629
+ * to `enforce` returns an `enforceCheck` dry-run summary.
8630
+ */
8631
+ async update(slug, data) {
8632
+ return this.client.patch(`/collections/${slug}`, data);
8633
+ }
8634
+ /**
8635
+ * Delete the collection REGISTRATION only — records of the type are not
8636
+ * touched and revert to schemaless behavior.
8637
+ */
8638
+ async delete(slug) {
8639
+ return this.client.delete(`/collections/${slug}`);
8640
+ }
8641
+ /**
8642
+ * Sample the type's most recently updated records and return a PROPOSED
8643
+ * schema with per-field confidence and sample values. Saves nothing —
8644
+ * review the proposal, then `update()` the collection.
8645
+ */
8646
+ async inferSchema(slug, params) {
8647
+ return this.client.post(
8648
+ `/collections/${slug}/infer-schema`,
8649
+ params ?? {}
8650
+ );
8651
+ }
8652
+ /**
8653
+ * Dry-run existing records against a schema without writing anything — the
8654
+ * "N of M records would fail" preview before enabling `enforce`. Uses the
8655
+ * provided schema when given, otherwise the collection's saved schema.
8656
+ */
8657
+ async validateExisting(slug, data) {
8658
+ return this.client.post(
8659
+ `/collections/${slug}/validate-existing`,
8660
+ data ?? {}
8661
+ );
8662
+ }
8663
+ };
8646
8664
  var ApiKeysEndpoint = class {
8647
8665
  constructor(client) {
8648
8666
  this.client = client;
@@ -9262,13 +9280,21 @@ var ClientTokensEndpoint = class {
9262
9280
  constructor(client) {
9263
9281
  this.client = client;
9264
9282
  }
9265
- /**
9266
- * List all client tokens for the authenticated user
9267
- */
9268
- async list() {
9269
- const response = await this.client.get(
9270
- "/client-tokens"
9271
- );
9283
+ async list(params) {
9284
+ const response = await this.client.get("/client-tokens", params);
9285
+ if (params?.limit !== void 0) {
9286
+ return {
9287
+ clientTokens: response.clientTokens,
9288
+ // The API always includes pagination when limit is supplied; the
9289
+ // fallback mirrors the server's own envelope math so the paged
9290
+ // overload stays total against older API deployments.
9291
+ pagination: response.pagination ?? {
9292
+ limit: params.limit,
9293
+ offset: params.offset ?? 0,
9294
+ hasMore: response.clientTokens.length === params.limit
9295
+ }
9296
+ };
9297
+ }
9272
9298
  return response.clientTokens;
9273
9299
  }
9274
9300
  /**
@@ -12688,6 +12714,22 @@ var IntegrationsEndpoint = class {
12688
12714
  async installSlack(data) {
12689
12715
  return this.client.post("/integrations/slack/install", data);
12690
12716
  }
12717
+ /**
12718
+ * Start the Slack "Add to Slack" OAuth handshake. Returns the Slack authorize
12719
+ * URL to open in a popup; the bot token is captured server-side by the
12720
+ * callback (never returned to the browser).
12721
+ */
12722
+ async startSlackOAuth(data) {
12723
+ return this.client.post("/oauth/slack/start", data);
12724
+ }
12725
+ /**
12726
+ * Generate the Slack app manifest and one-click create-app deep link for a
12727
+ * surface. The manifest carries absolute API URLs derived server-side, so it
12728
+ * is always valid for Slack (relative proxy paths never leak in).
12729
+ */
12730
+ async generateSlackManifest(data) {
12731
+ return this.client.post("/integrations/slack/manifest", data);
12732
+ }
12691
12733
  };
12692
12734
  var BillingEndpoint = class {
12693
12735
  constructor(client) {
@@ -12706,7 +12748,15 @@ var BillingEndpoint = class {
12706
12748
  return this.client.get("/billing/credits");
12707
12749
  }
12708
12750
  /**
12709
- * Get spend analytics. The window is controlled by `days` (1–365, defaults to 30).
12751
+ * Get the caller's exact current UTC-month platform spend from the local
12752
+ * meter used for spend-cap enforcement. Returns 503 when that meter is unavailable.
12753
+ */
12754
+ async getCurrentSpend() {
12755
+ return this.client.get("/billing/current-spend");
12756
+ }
12757
+ /**
12758
+ * Get spend analytics. The window is controlled by either `period` or `days`
12759
+ * (1–365, defaults to 30).
12710
12760
  */
12711
12761
  async getSpendAnalytics(params) {
12712
12762
  return this.client.get("/billing/spend-analytics", params);
@@ -12735,52 +12785,6 @@ var ToolApprovalGrantsEndpoint = class {
12735
12785
  return this.client.delete(`/tool-approval-grants/${id}`);
12736
12786
  }
12737
12787
  };
12738
- var AppsEndpoint = class {
12739
- constructor(client) {
12740
- this.client = client;
12741
- }
12742
- /** List apps for the authenticated owner, newest first. */
12743
- async list() {
12744
- return this.client.get("/apps");
12745
- }
12746
- /** Get an app by id, including its URL and active version pointer. */
12747
- async get(id) {
12748
- return this.client.get(`/apps/${id}`);
12749
- }
12750
- /** Create an app. A client token scoped to the app origin is auto-provisioned. */
12751
- async create(data) {
12752
- return this.client.post("/apps", data);
12753
- }
12754
- /** Update name, description, visibility, or status (suspended serves 410). */
12755
- async update(id, data) {
12756
- return this.client.patch(`/apps/${id}`, data);
12757
- }
12758
- /** Delete an app, its versions, and its hosting. Irreversible. */
12759
- async delete(id) {
12760
- return this.client.delete(`/apps/${id}`);
12761
- }
12762
- /** List an app's versions, newest first. */
12763
- async listVersions(id) {
12764
- return this.client.get(`/apps/${id}/versions`);
12765
- }
12766
- /** Upload a zipped bundle (raw application/zip body) as a new version. */
12767
- async uploadVersion(id, zipBytes) {
12768
- return this.client.postBinary(`/apps/${id}/versions`, zipBytes, "application/zip");
12769
- }
12770
- /**
12771
- * Upload a bundle from in-memory file maps (the API zips server-side).
12772
- * Text files in `files`, binary files base64-encoded in `filesBase64`.
12773
- */
12774
- async uploadVersionFiles(id, data) {
12775
- return this.client.post(`/apps/${id}/versions`, data);
12776
- }
12777
- /** Activate an uploaded version (deploy or rollback). */
12778
- async activate(id, versionId) {
12779
- return this.client.post(`/apps/${id}/activate`, {
12780
- versionId
12781
- });
12782
- }
12783
- };
12784
12788
 
12785
12789
  // src/client.ts
12786
12790
  function isObjectRecord(value) {
@@ -12817,6 +12821,7 @@ var RuntypeClient2 = class {
12817
12821
  this.flows = new FlowsEndpoint(this);
12818
12822
  this.prompts = new PromptsEndpoint(this);
12819
12823
  this.records = new RecordsEndpoint(this);
12824
+ this.collections = new CollectionsEndpoint(this);
12820
12825
  this.apiKeys = new ApiKeysEndpoint(this);
12821
12826
  this.modelConfigs = new ModelConfigsEndpoint(this);
12822
12827
  this.providerKeys = new ProviderKeysEndpoint(this);
@@ -12831,7 +12836,6 @@ var RuntypeClient2 = class {
12831
12836
  this.clientTokens = new ClientTokensEndpoint(this);
12832
12837
  this.agents = new AgentsEndpoint(this);
12833
12838
  this.secrets = new SecretsEndpoint(this);
12834
- this.apps = new AppsEndpoint(this);
12835
12839
  this.schedules = new SchedulesEndpoint(this);
12836
12840
  this.surfaces = new SurfacesEndpoint(this);
12837
12841
  this.conversations = new ConversationsEndpoint(this);
@@ -13654,6 +13658,7 @@ var FETCH_URL_FIELDS = [
13654
13658
  { key: "markdownIfAvailable", format: "raw" },
13655
13659
  { key: "fetchMethod", format: "json", skipDefault: "standard" },
13656
13660
  { key: "firecrawl", format: "value" },
13661
+ { key: "massive", format: "value" },
13657
13662
  { key: "outputVariable", format: "json" },
13658
13663
  { key: "streamOutput", format: "raw" },
13659
13664
  { key: "errorHandling", format: "value", skipDefault: "fail" },
@@ -13717,7 +13722,10 @@ var SEND_EMAIL_FIELDS = [
13717
13722
  { key: "defaultValue", format: "value" }
13718
13723
  ];
13719
13724
  var SEND_STREAM_FIELDS = [
13720
- { key: "message", format: "template" }
13725
+ { key: "message", format: "template" },
13726
+ { key: "outputVariable", format: "json" },
13727
+ { key: "errorHandling", format: "value", skipDefault: "fail" },
13728
+ { key: "defaultValue", format: "value" }
13721
13729
  ];
13722
13730
  var RETRIEVE_RECORD_FIELDS = [
13723
13731
  { key: "retrievalMode", format: "json" },
@@ -13729,7 +13737,6 @@ var RETRIEVE_RECORD_FIELDS = [
13729
13737
  { key: "fieldsToExclude", format: "json" },
13730
13738
  { key: "availableFields", format: "value" },
13731
13739
  { key: "outputVariable", format: "json" },
13732
- { key: "fields", format: "value" },
13733
13740
  { key: "includeMetadata", format: "raw" },
13734
13741
  { key: "streamOutput", format: "raw" }
13735
13742
  ];
@@ -13774,7 +13781,6 @@ var VECTOR_SEARCH_FIELDS = [
13774
13781
  { key: "vectorStore", format: "json" },
13775
13782
  { key: "weaviateConfig", format: "value" },
13776
13783
  { key: "vectorizeConfig", format: "value" },
13777
- { key: "pineconeConfig", format: "value" },
13778
13784
  { key: "limit", format: "raw", skipDefault: 5 },
13779
13785
  { key: "threshold", format: "raw", skipDefault: 0.7 },
13780
13786
  { key: "metadataFilters", format: "value" },
@@ -13791,7 +13797,6 @@ var GENERATE_EMBEDDING_FIELDS = [
13791
13797
  { key: "recordType", format: "json" },
13792
13798
  { key: "recordName", format: "json" },
13793
13799
  { key: "textField", format: "json" },
13794
- { key: "storeInRecord", format: "raw" },
13795
13800
  { key: "embeddingModel", format: "json" },
13796
13801
  { key: "maxLength", format: "raw" },
13797
13802
  { key: "inputMode", format: "json" },
@@ -13799,7 +13804,6 @@ var GENERATE_EMBEDDING_FIELDS = [
13799
13804
  { key: "itemAlias", format: "json" },
13800
13805
  { key: "textTemplate", format: "template" },
13801
13806
  { key: "batchSize", format: "raw" },
13802
- { key: "vectorStore", format: "value" },
13803
13807
  { key: "outputVariable", format: "json" },
13804
13808
  { key: "streamOutput", format: "raw" }
13805
13809
  ];
@@ -13819,31 +13823,9 @@ var SEND_EVENT_FIELDS = [
13819
13823
  { key: "streamOutput", format: "raw" },
13820
13824
  { key: "errorHandling", format: "value", skipDefault: "fail" }
13821
13825
  ];
13822
- var SEND_TEXT_FIELDS = [
13823
- { key: "to", format: "json" },
13824
- { key: "from", format: "json" },
13825
- { key: "message", format: "template" },
13826
- { key: "outputVariable", format: "json" },
13827
- { key: "streamOutput", format: "raw" },
13828
- { key: "errorHandling", format: "value", skipDefault: "fail" }
13829
- ];
13830
- var FETCH_GITHUB_FIELDS = [
13831
- { key: "repository", format: "json" },
13832
- { key: "branch", format: "json" },
13833
- { key: "path", format: "json" },
13834
- { key: "token", format: "json" },
13835
- { key: "outputVariable", format: "json" },
13836
- { key: "contentType", format: "json" },
13837
- { key: "includePatterns", format: "value" },
13838
- { key: "excludePatterns", format: "value" },
13839
- { key: "compress", format: "raw" },
13840
- { key: "style", format: "json" },
13841
- { key: "streamOutput", format: "raw" }
13842
- ];
13843
13826
  var API_CALL_FIELDS = [
13844
13827
  { key: "http", format: "value" },
13845
13828
  { key: "auth", format: "value" },
13846
- { key: "requestTemplate", format: "template" },
13847
13829
  { key: "responseMapping", format: "value" },
13848
13830
  { key: "outputVariable", format: "json" },
13849
13831
  { key: "streamOutput", format: "raw" },
@@ -13854,7 +13836,6 @@ var EXECUTE_AGENT_FIELDS = [
13854
13836
  { key: "agentId", format: "json" },
13855
13837
  { key: "message", format: "template" },
13856
13838
  { key: "outputVariable", format: "json" },
13857
- { key: "variables", format: "value" },
13858
13839
  { key: "maxTurns", format: "raw" },
13859
13840
  { key: "timeout", format: "raw" },
13860
13841
  { key: "errorHandling", format: "value", skipDefault: "fail" },
@@ -13901,7 +13882,6 @@ var UPDATE_RECORD_FIELDS = [
13901
13882
  { key: "recordName", format: "json" },
13902
13883
  { key: "recordFilter", format: "value" },
13903
13884
  { key: "updates", format: "value" },
13904
- { key: "updatesTemplate", format: "template" },
13905
13885
  { key: "mergeStrategy", format: "json" },
13906
13886
  { key: "outputVariable", format: "json" },
13907
13887
  { key: "streamOutput", format: "raw" },
@@ -13938,7 +13918,6 @@ var PAGINATE_API_FIELDS = [
13938
13918
  { key: "startPage", format: "raw" },
13939
13919
  { key: "entitiesPath", format: "json" },
13940
13920
  { key: "entityPath", format: "json" },
13941
- { key: "entityIdPath", format: "json" },
13942
13921
  { key: "maxEntities", format: "raw" },
13943
13922
  { key: "requestDelayMs", format: "raw" },
13944
13923
  { key: "retryOnRateLimit", format: "raw" },
@@ -13958,13 +13937,10 @@ var STORE_VECTOR_FIELDS = [
13958
13937
  { key: "destination", format: "json" },
13959
13938
  { key: "weaviateConfig", format: "value" },
13960
13939
  { key: "vectorizeConfig", format: "value" },
13961
- { key: "pineconeConfig", format: "value" },
13962
13940
  { key: "weaviateConfigId", format: "json" },
13963
13941
  { key: "weaviateClassName", format: "json" },
13964
13942
  { key: "vectorizeConfigId", format: "json" },
13965
13943
  { key: "vectorizeNamespace", format: "json" },
13966
- { key: "pineconeConfigId", format: "json" },
13967
- { key: "pineconeNamespace", format: "json" },
13968
13944
  { key: "idTemplate", format: "template" },
13969
13945
  { key: "metadata", format: "value" },
13970
13946
  { key: "outputVariable", format: "json" },
@@ -14016,8 +13992,6 @@ var STEP_FIELD_REGISTRY = {
14016
13992
  "generate-embedding": GENERATE_EMBEDDING_FIELDS,
14017
13993
  "wait-until": WAIT_UNTIL_FIELDS,
14018
13994
  "send-event": SEND_EVENT_FIELDS,
14019
- "send-text": SEND_TEXT_FIELDS,
14020
- "fetch-github": FETCH_GITHUB_FIELDS,
14021
13995
  template: TEMPLATE_FIELDS,
14022
13996
  "store-asset": STORE_ASSET_FIELDS,
14023
13997
  "generate-pdf": GENERATE_PDF_FIELDS,
@@ -14037,7 +14011,6 @@ var STEP_TYPE_TO_METHOD = {
14037
14011
  "retrieve-record": "retrieveRecord",
14038
14012
  "get-record": "getRecord",
14039
14013
  "list-records": "listRecords",
14040
- "fetch-github": "fetchGitHub",
14041
14014
  "transform-data": "transformData",
14042
14015
  template: "template",
14043
14016
  conditional: "conditional",
@@ -14045,7 +14018,6 @@ var STEP_TYPE_TO_METHOD = {
14045
14018
  "upsert-record": "upsertRecord",
14046
14019
  "update-record": "updateRecord",
14047
14020
  "send-email": "sendEmail",
14048
- "send-text": "sendText",
14049
14021
  "send-event": "sendEvent",
14050
14022
  "send-stream": "sendStream",
14051
14023
  search: "search",
@@ -14071,7 +14043,6 @@ var STEP_TYPE_TO_METHOD = {
14071
14043
  AgentsNamespace,
14072
14044
  AnalyticsEndpoint,
14073
14045
  ApiKeysEndpoint,
14074
- AppsEndpoint,
14075
14046
  BatchBuilder,
14076
14047
  BatchesNamespace,
14077
14048
  BillingEndpoint,
@@ -14080,6 +14051,7 @@ var STEP_TYPE_TO_METHOD = {
14080
14051
  ClientEvalBuilder,
14081
14052
  ClientFlowBuilder,
14082
14053
  ClientTokensEndpoint,
14054
+ CollectionsEndpoint,
14083
14055
  ContextTemplatesEndpoint,
14084
14056
  ConversationsEndpoint,
14085
14057
  DEFAULT_RECOVERY_AFTER_EMPTY_SESSIONS,