@runtypelabs/sdk 6.3.6 → 6.5.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
@@ -26,6 +26,8 @@ var UNIFIED_EVENT_TYPES = /* @__PURE__ */ new Set([
26
26
  "artifact_update",
27
27
  "artifact_complete",
28
28
  "source",
29
+ "state_snapshot",
30
+ "state_delta",
29
31
  "tool_start",
30
32
  "tool_input_delta",
31
33
  "tool_input_complete",
@@ -178,9 +180,10 @@ function createFlowEventTranslator() {
178
180
  pageOrigin: data.pageOrigin
179
181
  })
180
182
  ];
181
- // Channels/markers/tool-family/approval/skip/source/custom/ping the flow
182
- // consumer never read → no callback event. (A non-terminal `error` is only
183
- // produced on agent streams; dropping it here avoids a false flow_error.)
183
+ // Channels/markers/tool-family/approval/skip/source/state/custom/ping the
184
+ // flow consumer never read → no callback event. (A non-terminal `error` is
185
+ // only produced on agent streams; dropping it here avoids a false
186
+ // flow_error.)
184
187
  default:
185
188
  return [];
186
189
  }
@@ -300,6 +303,7 @@ function createAgentEventTranslator() {
300
303
  toolName: data.toolName,
301
304
  toolType: data.toolType,
302
305
  parameters: data.parameters,
306
+ hiddenParameterNames: data.hiddenParameterNames,
303
307
  origin: data.origin,
304
308
  pageOrigin: data.pageOrigin
305
309
  })
@@ -482,8 +486,9 @@ function createAgentEventTranslator() {
482
486
  case "ping":
483
487
  return [compact({ type: "agent_ping", executionId, seq, timestamp: data.timestamp })];
484
488
  // turn/text/reasoning open+close markers, step_*, artifact_*, source,
485
- // custom (fallback beat / routing), and the skill-fold result envelope
486
- // the SDK never consumed no callback event.
489
+ // state_snapshot/state_delta (agent-state channel with no stable SDK
490
+ // callback), custom (fallback beat / routing), and the skill-fold result
491
+ // envelope the SDK never consumed → no callback event.
487
492
  default:
488
493
  return [];
489
494
  }
@@ -1628,7 +1633,11 @@ var FlowBuilder = class {
1628
1633
  const flow = this.existingFlowId ? { id: this.existingFlowId } : { name: this.flowConfig.name, steps: this.steps };
1629
1634
  const request6 = { flow };
1630
1635
  if (this.recordConfig) {
1631
- request6.record = this.recordConfig;
1636
+ const { id, ...record } = this.recordConfig;
1637
+ request6.record = {
1638
+ ...record,
1639
+ ...id !== void 0 ? { id: String(id) } : {}
1640
+ };
1632
1641
  }
1633
1642
  if (this.messagesConfig) {
1634
1643
  request6.messages = this.messagesConfig;
@@ -1771,8 +1780,7 @@ var ClientFlowBuilder = class extends FlowBuilder {
1771
1780
  let runCallbacks;
1772
1781
  let localTools;
1773
1782
  let dispatchClient = this.boundClient;
1774
- const isLocalTools = (obj) => obj && typeof obj === "object" && !isStreamCallbacks(obj) && !("streamResponse" in obj) && // Not options
1775
- !("dispatch" in obj);
1783
+ const isLocalTools = (obj) => obj && typeof obj === "object" && !Array.isArray(obj) && !isStreamCallbacks(obj) && !("dispatch" in obj) && Object.keys(obj).length > 0 && Object.values(obj).every((value) => typeof value === "function");
1776
1784
  if (arg1) {
1777
1785
  if (typeof arg1 === "object" && "dispatch" in arg1) {
1778
1786
  if (arg2) {
@@ -3493,7 +3501,7 @@ var RuntypeFlowBuilder = class {
3493
3501
  if (isStreaming) {
3494
3502
  currentResponse = await client.dispatch(config);
3495
3503
  } else {
3496
- const data = await client.post("/dispatch", config);
3504
+ const data = await client.dispatchJson(config);
3497
3505
  currentResponse = new Response(JSON.stringify(data), {
3498
3506
  headers: { "content-type": "application/json" }
3499
3507
  });
@@ -3562,7 +3570,11 @@ var RuntypeFlowBuilder = class {
3562
3570
  const flow = this.existingFlowId ? { id: this.existingFlowId } : { name: this.flowConfig.name, steps: this.steps };
3563
3571
  const request6 = { flow };
3564
3572
  if (this.recordConfig) {
3565
- request6.record = this.recordConfig;
3573
+ const { id, ...record } = this.recordConfig;
3574
+ request6.record = {
3575
+ ...record,
3576
+ ...id !== void 0 ? { id: String(id) } : {}
3577
+ };
3566
3578
  }
3567
3579
  if (this.messagesConfig) {
3568
3580
  request6.messages = this.messagesConfig;
@@ -3634,6 +3646,9 @@ var RuntypeFlowBuilder = class {
3634
3646
  if (this.mode !== "upsert" || !this.steps.length) {
3635
3647
  return client.dispatch(config);
3636
3648
  }
3649
+ if (!config.flow) {
3650
+ throw new Error("Persisted flow dispatch requires a flow target");
3651
+ }
3637
3652
  const contentHash = await this.computeContentHash();
3638
3653
  const hashOnlyConfig = {
3639
3654
  ...config,
@@ -5704,6 +5719,47 @@ function transformQueryParams(params) {
5704
5719
  return result;
5705
5720
  }
5706
5721
 
5722
+ // src/dispatch-request.ts
5723
+ function normalizeDispatchMessageContent(content) {
5724
+ if (Array.isArray(content) && content.some(
5725
+ (part) => typeof part === "object" && part !== null && "type" in part && part.type === "asset_ref"
5726
+ )) {
5727
+ throw new Error(
5728
+ "Dispatch messages cannot submit persisted asset_ref content; provide the original image or file content instead"
5729
+ );
5730
+ }
5731
+ return content;
5732
+ }
5733
+ function normalizeDispatchRequest(request6) {
5734
+ if (!request6.flow && !request6.agent) {
5735
+ throw new Error("Dispatch requires either a flow or an agent target");
5736
+ }
5737
+ const record = request6.record === void 0 ? void 0 : {
5738
+ ...request6.record,
5739
+ ...request6.record.id !== void 0 ? { id: String(request6.record.id) } : {}
5740
+ };
5741
+ const messages = request6.messages?.map((message) => ({
5742
+ ...message,
5743
+ content: normalizeDispatchMessageContent(message.content)
5744
+ }));
5745
+ const clientTools = request6.clientTools?.map((tool) => {
5746
+ if (tool.parametersSchema.type !== "object") {
5747
+ throw new Error(`Client tool "${tool.name}" parametersSchema.type must be "object"`);
5748
+ }
5749
+ return {
5750
+ ...tool,
5751
+ parametersSchema: tool.parametersSchema
5752
+ };
5753
+ });
5754
+ const normalized = {
5755
+ ...request6,
5756
+ ...record !== void 0 ? { record } : {},
5757
+ ...messages !== void 0 ? { messages } : {},
5758
+ ...clientTools !== void 0 ? { clientTools } : {}
5759
+ };
5760
+ return request6.flow ? { ...normalized, flow: request6.flow } : { ...normalized, agent: request6.agent };
5761
+ }
5762
+
5707
5763
  // src/runtype.ts
5708
5764
  var globalConfig = {};
5709
5765
  var globalClient = null;
@@ -5801,12 +5857,42 @@ var RuntypeClient = class {
5801
5857
  });
5802
5858
  }
5803
5859
  /**
5804
- * Dispatch flow execution (streaming)
5860
+ * Dispatch flow execution (streaming).
5861
+ *
5862
+ * This is the sole streaming-dispatch chokepoint for the flow builders
5863
+ * (`RuntypeFlowBuilder`), so it normalizes the request to the canonical
5864
+ * `/v1/dispatch` wire contract here — every builder path inherits the same
5865
+ * normalization the `DispatchEndpoint` applies, with no per-builder call.
5805
5866
  */
5806
5867
  async dispatch(config) {
5868
+ const normalized = normalizeDispatchRequest(config);
5869
+ const request6 = transformRequest({
5870
+ ...normalized,
5871
+ options: {
5872
+ ...normalized.options,
5873
+ streamResponse: true
5874
+ }
5875
+ });
5807
5876
  return this.requestStream("/dispatch", {
5808
5877
  method: "POST",
5809
- body: JSON.stringify(transformRequest(config))
5878
+ body: JSON.stringify(request6)
5879
+ });
5880
+ }
5881
+ /**
5882
+ * Dispatch flow execution (non-streaming JSON).
5883
+ *
5884
+ * The non-streaming sibling of {@link dispatch}; it normalizes to the same
5885
+ * canonical wire contract so builders never post a raw, un-normalized body,
5886
+ * and pins `streamResponse: false` so the server returns buffered JSON.
5887
+ */
5888
+ async dispatchJson(config) {
5889
+ const normalized = normalizeDispatchRequest(config);
5890
+ return this.post("/dispatch", {
5891
+ ...normalized,
5892
+ options: {
5893
+ ...normalized.options,
5894
+ streamResponse: false
5895
+ }
5810
5896
  });
5811
5897
  }
5812
5898
  /**
@@ -6175,7 +6261,7 @@ var Runtype = class {
6175
6261
 
6176
6262
  // src/version.ts
6177
6263
  var FALLBACK_VERSION = "0.0.0";
6178
- var SDK_VERSION = "6.3.6".length > 0 ? "6.3.6" : FALLBACK_VERSION;
6264
+ var SDK_VERSION = "6.5.0".length > 0 ? "6.5.0" : FALLBACK_VERSION;
6179
6265
  var RUNTYPE_CLIENT_KIND = "sdk";
6180
6266
  var SDK_USER_AGENT = `runtype-sdk/${SDK_VERSION} (typescript)`;
6181
6267
 
@@ -6400,7 +6486,11 @@ function buildGeneratedRuntimeToolGateOutput(proposal, options = {}) {
6400
6486
  };
6401
6487
  }
6402
6488
  function attachRuntimeToolsToDispatchRequest(request6, runtimeTools, options = {}) {
6403
- const stepList = request6.flow.steps;
6489
+ const flow = request6.flow;
6490
+ if (!flow) {
6491
+ throw new Error("Cannot attach runtime tools: dispatch request must include flow.steps");
6492
+ }
6493
+ const stepList = flow.steps;
6404
6494
  if (!stepList || !Array.isArray(stepList) || stepList.length === 0) {
6405
6495
  throw new Error("Cannot attach runtime tools: dispatch request must include flow.steps");
6406
6496
  }
@@ -6445,7 +6535,7 @@ function attachRuntimeToolsToDispatchRequest(request6, runtimeTools, options = {
6445
6535
  return {
6446
6536
  ...request6,
6447
6537
  flow: {
6448
- ...request6.flow,
6538
+ ...flow,
6449
6539
  // `clonedSteps` is a structural clone of `request.flow.steps` (already
6450
6540
  // `FlowStepDefinition[]`); only the prompt step's `config.tools` was
6451
6541
  // merged, so every step's `type` discriminant is preserved. The clone is
@@ -8720,34 +8810,52 @@ var DispatchEndpoint = class {
8720
8810
  * Dispatch: create and/or execute flows on records atomically
8721
8811
  */
8722
8812
  async execute(data) {
8723
- return this.client.post("/dispatch", data);
8813
+ const normalized = normalizeDispatchRequest(data);
8814
+ return this.client.post("/dispatch", {
8815
+ ...normalized,
8816
+ options: {
8817
+ ...normalized.options,
8818
+ streamResponse: false
8819
+ }
8820
+ });
8724
8821
  }
8725
8822
  /**
8726
8823
  * Dispatch with streaming response
8727
8824
  */
8728
8825
  async executeStream(data) {
8826
+ const normalized = normalizeDispatchRequest(data);
8729
8827
  return this.client.requestStream("/dispatch", {
8730
8828
  method: "POST",
8731
- body: JSON.stringify(data)
8829
+ body: JSON.stringify({
8830
+ ...normalized,
8831
+ options: {
8832
+ ...normalized.options,
8833
+ streamResponse: true
8834
+ }
8835
+ })
8732
8836
  });
8733
8837
  }
8734
8838
  /**
8735
8839
  * Resume paused flow execution
8736
- * API expects snake_case field names
8840
+ * Uses buffered JSON when streamResponse is omitted.
8737
8841
  *
8738
- * @param data.execution_id - The execution ID to resume
8739
- * @param data.tool_outputs - Tool outputs to inject into the flow
8740
- * @param data.stream_response - Whether to stream the response
8842
+ * @param data.executionId - The execution ID to resume
8843
+ * @param data.toolOutputs - Tool outputs to inject into the flow
8844
+ * @param data.streamResponse - Whether to stream the response (defaults to false)
8741
8845
  * @param data.messages - Optional messages to override the original dispatch messages
8742
8846
  */
8743
8847
  async resume(data) {
8744
- if (data.streamResponse) {
8848
+ const request6 = {
8849
+ ...data,
8850
+ streamResponse: data.streamResponse ?? false
8851
+ };
8852
+ if (request6.streamResponse) {
8745
8853
  return this.client.requestStream("/dispatch/resume", {
8746
8854
  method: "POST",
8747
- body: JSON.stringify(data)
8855
+ body: JSON.stringify(request6)
8748
8856
  });
8749
8857
  }
8750
- return this.client.post("/dispatch/resume", data);
8858
+ return this.client.post("/dispatch/resume", request6);
8751
8859
  }
8752
8860
  /**
8753
8861
  * Evaluate a model-proposed runtime tool against a configurable allowlist policy.
@@ -8843,6 +8951,12 @@ var AnalyticsEndpoint = class {
8843
8951
  async getModelUsage(params) {
8844
8952
  return this.client.get("/model-usage", params);
8845
8953
  }
8954
+ /**
8955
+ * Get execution and platform-spend usage grouped by projected product end user.
8956
+ */
8957
+ async getEndUserUsage(params) {
8958
+ return this.client.get("/analytics/end-user-usage", params);
8959
+ }
8846
8960
  };
8847
8961
  var FlowStepsEndpoint = class {
8848
8962
  constructor(client) {
@@ -12613,6 +12727,21 @@ function hasToolEntryShape(value) {
12613
12727
  if (!isObjectRecord(value)) return false;
12614
12728
  return typeof value.execute === "function" && typeof value.description === "string" && typeof value.parametersSchema === "object" && value.parametersSchema !== null;
12615
12729
  }
12730
+ function assertTurnScopedLocalTools(localTools) {
12731
+ for (const [name, entry] of Object.entries(localTools)) {
12732
+ if (typeof entry === "function") continue;
12733
+ if (!hasToolEntryShape(entry)) {
12734
+ throw new Error(
12735
+ `Turn-scoped local tool "${name}" must be a function or an entry with description, parametersSchema, and execute`
12736
+ );
12737
+ }
12738
+ if (entry.parametersSchema.type !== "object") {
12739
+ throw new Error(
12740
+ `Turn-scoped local tool "${name}" parametersSchema.type must be "object"`
12741
+ );
12742
+ }
12743
+ }
12744
+ }
12616
12745
  function isPausedLocalActionResult(value) {
12617
12746
  return isObjectRecord(value) && value.status === "paused" && Array.isArray(value.pausedTools) && value.pausedTools.length > 0;
12618
12747
  }
@@ -12708,6 +12837,9 @@ var RuntypeClient2 = class {
12708
12837
  const options = (isOptionsObject(arg3) ? arg3 : arg4) ?? {};
12709
12838
  const scope = options.scope ?? "session";
12710
12839
  const isStreaming = !!callbacks;
12840
+ if (scope === "turn") {
12841
+ assertTurnScopedLocalTools(localTools);
12842
+ }
12711
12843
  const derivedClientTools = scope === "turn" ? Object.entries(localTools).filter((entry) => hasToolEntryShape(entry[1])).map(([name, entry]) => ({
12712
12844
  name,
12713
12845
  description: entry.description,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@runtypelabs/sdk",
3
- "version": "6.3.6",
3
+ "version": "6.5.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",