@runtypelabs/sdk 1.22.0 → 1.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -469,6 +469,53 @@ var FlowResult = class {
469
469
  };
470
470
 
471
471
  // src/flows-namespace.ts
472
+ function isRecord(value) {
473
+ return value !== null && typeof value === "object" && !Array.isArray(value);
474
+ }
475
+ function normalizeConfig(config) {
476
+ if (!isRecord(config)) return {};
477
+ const normalized = {};
478
+ for (const key of Object.keys(config).sort()) {
479
+ const value = config[key];
480
+ if (value === void 0) continue;
481
+ if (value !== null && typeof value === "object" && !Array.isArray(value)) {
482
+ normalized[key] = normalizeConfig(value);
483
+ } else if (Array.isArray(value)) {
484
+ normalized[key] = value.map((item) => {
485
+ if (item !== null && typeof item === "object" && !Array.isArray(item)) {
486
+ return normalizeConfig(item);
487
+ }
488
+ return item;
489
+ });
490
+ } else {
491
+ normalized[key] = value;
492
+ }
493
+ }
494
+ return normalized;
495
+ }
496
+ function normalizeStepForHash(step) {
497
+ const stepObj = isRecord(step) ? step : {};
498
+ return {
499
+ type: typeof stepObj.type === "string" ? stepObj.type : "",
500
+ name: typeof stepObj.name === "string" ? stepObj.name : "",
501
+ enabled: stepObj.enabled !== false,
502
+ ...typeof stepObj.when === "string" ? { when: stepObj.when } : {},
503
+ config: normalizeConfig(stepObj.config),
504
+ order: typeof stepObj.order === "number" ? stepObj.order : 0
505
+ };
506
+ }
507
+ async function computeFlowContentHash(steps) {
508
+ const normalized = [...steps].sort((a, b) => {
509
+ const orderA = isRecord(a) && typeof a.order === "number" ? a.order : 0;
510
+ const orderB = isRecord(b) && typeof b.order === "number" ? b.order : 0;
511
+ return orderA - orderB;
512
+ }).map(normalizeStepForHash);
513
+ const serialized = JSON.stringify(normalized);
514
+ const encoded = new TextEncoder().encode(serialized);
515
+ const hashBuffer = await crypto.subtle.digest("SHA-256", encoded);
516
+ const hashArray = new Uint8Array(hashBuffer);
517
+ return Array.from(hashArray).map((b) => b.toString(16).padStart(2, "0")).join("");
518
+ }
472
519
  var FlowsNamespace = class {
473
520
  constructor(getClient) {
474
521
  this.getClient = getClient;
@@ -914,7 +961,7 @@ var RuntypeFlowBuilder = class {
914
961
  }
915
962
  config.options = { ...config.options, streamResponse: true };
916
963
  const client = this.getClient();
917
- const response = await client.dispatch(config);
964
+ const response = await this.dispatchWithPersistedFlow(client, config);
918
965
  const result = new FlowResult(response);
919
966
  if (callbacks) {
920
967
  await result.stream(callbacks);
@@ -943,7 +990,7 @@ var RuntypeFlowBuilder = class {
943
990
  }
944
991
  config.options = { ...config.options, streamResponse: true };
945
992
  const client = this.getClient();
946
- const response = await client.dispatch(config);
993
+ const response = await this.dispatchWithPersistedFlow(client, config);
947
994
  const result = new FlowResult(response);
948
995
  await result.getSummary();
949
996
  return result;
@@ -1127,6 +1174,37 @@ var RuntypeFlowBuilder = class {
1127
1174
  // ============================================================================
1128
1175
  // Private Helpers
1129
1176
  // ============================================================================
1177
+ /**
1178
+ * Persisted flow protocol (APQ-style): send hash-only first, retry with
1179
+ * full definition on FLOW_DEFINITION_REQUIRED. For non-upsert modes,
1180
+ * dispatches directly.
1181
+ */
1182
+ async dispatchWithPersistedFlow(client, config) {
1183
+ if (this.mode !== "upsert" || !this.steps.length) {
1184
+ return client.dispatch(config);
1185
+ }
1186
+ const contentHash = await this.computeContentHash();
1187
+ const hashOnlyConfig = {
1188
+ ...config,
1189
+ flow: { name: config.flow.name, contentHash }
1190
+ };
1191
+ try {
1192
+ return await client.dispatch(hashOnlyConfig);
1193
+ } catch (err) {
1194
+ const message = err instanceof Error ? err.message : "";
1195
+ if (!message.includes("422")) {
1196
+ throw err;
1197
+ }
1198
+ }
1199
+ const fullConfig = {
1200
+ ...config,
1201
+ flow: { ...config.flow, contentHash }
1202
+ };
1203
+ return client.dispatch(fullConfig);
1204
+ }
1205
+ async computeContentHash() {
1206
+ return computeFlowContentHash(this.steps);
1207
+ }
1130
1208
  addStep(type, name, config, enabled = true) {
1131
1209
  this.stepCounter++;
1132
1210
  const cleanConfig = {};
@@ -3526,6 +3604,12 @@ var FlowsEndpoint = class {
3526
3604
  async delete(id) {
3527
3605
  return this.client.delete(`/flows/${id}`);
3528
3606
  }
3607
+ /**
3608
+ * Export a flow as a self-contained runtime definition for @runtypelabs/runtime
3609
+ */
3610
+ async exportRuntime(id) {
3611
+ return this.client.get(`/flows/${id}/export-runtime`);
3612
+ }
3529
3613
  /**
3530
3614
  * Run a flow on all records of a specific type
3531
3615
  */
@@ -4507,6 +4591,12 @@ var _AgentsEndpoint = class _AgentsEndpoint {
4507
4591
  async delete(id) {
4508
4592
  return this.client.delete(`/agents/${id}`);
4509
4593
  }
4594
+ /**
4595
+ * Export an agent as a self-contained runtime definition for @runtypelabs/runtime
4596
+ */
4597
+ async exportRuntime(id) {
4598
+ return this.client.get(`/agents/${id}/export-runtime`);
4599
+ }
4510
4600
  /**
4511
4601
  * Evaluate a model-proposed runtime tool against a configurable allowlist policy.
4512
4602
  * Useful for local `propose_runtime_tool` handlers before follow-up execution.