@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.cjs CHANGED
@@ -213,6 +213,8 @@ var UNIFIED_EVENT_TYPES = /* @__PURE__ */ new Set([
213
213
  "artifact_update",
214
214
  "artifact_complete",
215
215
  "source",
216
+ "state_snapshot",
217
+ "state_delta",
216
218
  "tool_start",
217
219
  "tool_input_delta",
218
220
  "tool_input_complete",
@@ -365,9 +367,10 @@ function createFlowEventTranslator() {
365
367
  pageOrigin: data.pageOrigin
366
368
  })
367
369
  ];
368
- // Channels/markers/tool-family/approval/skip/source/custom/ping the flow
369
- // consumer never read → no callback event. (A non-terminal `error` is only
370
- // produced on agent streams; dropping it here avoids a false flow_error.)
370
+ // Channels/markers/tool-family/approval/skip/source/state/custom/ping the
371
+ // flow consumer never read → no callback event. (A non-terminal `error` is
372
+ // only produced on agent streams; dropping it here avoids a false
373
+ // flow_error.)
371
374
  default:
372
375
  return [];
373
376
  }
@@ -487,6 +490,7 @@ function createAgentEventTranslator() {
487
490
  toolName: data.toolName,
488
491
  toolType: data.toolType,
489
492
  parameters: data.parameters,
493
+ hiddenParameterNames: data.hiddenParameterNames,
490
494
  origin: data.origin,
491
495
  pageOrigin: data.pageOrigin
492
496
  })
@@ -669,8 +673,9 @@ function createAgentEventTranslator() {
669
673
  case "ping":
670
674
  return [compact({ type: "agent_ping", executionId, seq, timestamp: data.timestamp })];
671
675
  // turn/text/reasoning open+close markers, step_*, artifact_*, source,
672
- // custom (fallback beat / routing), and the skill-fold result envelope
673
- // the SDK never consumed no callback event.
676
+ // state_snapshot/state_delta (agent-state channel with no stable SDK
677
+ // callback), custom (fallback beat / routing), and the skill-fold result
678
+ // envelope the SDK never consumed → no callback event.
674
679
  default:
675
680
  return [];
676
681
  }
@@ -1815,7 +1820,11 @@ var FlowBuilder = class {
1815
1820
  const flow = this.existingFlowId ? { id: this.existingFlowId } : { name: this.flowConfig.name, steps: this.steps };
1816
1821
  const request6 = { flow };
1817
1822
  if (this.recordConfig) {
1818
- request6.record = this.recordConfig;
1823
+ const { id, ...record } = this.recordConfig;
1824
+ request6.record = {
1825
+ ...record,
1826
+ ...id !== void 0 ? { id: String(id) } : {}
1827
+ };
1819
1828
  }
1820
1829
  if (this.messagesConfig) {
1821
1830
  request6.messages = this.messagesConfig;
@@ -1958,8 +1967,7 @@ var ClientFlowBuilder = class extends FlowBuilder {
1958
1967
  let runCallbacks;
1959
1968
  let localTools;
1960
1969
  let dispatchClient = this.boundClient;
1961
- const isLocalTools = (obj) => obj && typeof obj === "object" && !isStreamCallbacks(obj) && !("streamResponse" in obj) && // Not options
1962
- !("dispatch" in obj);
1970
+ 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");
1963
1971
  if (arg1) {
1964
1972
  if (typeof arg1 === "object" && "dispatch" in arg1) {
1965
1973
  if (arg2) {
@@ -3680,7 +3688,7 @@ var RuntypeFlowBuilder = class {
3680
3688
  if (isStreaming) {
3681
3689
  currentResponse = await client.dispatch(config);
3682
3690
  } else {
3683
- const data = await client.post("/dispatch", config);
3691
+ const data = await client.dispatchJson(config);
3684
3692
  currentResponse = new Response(JSON.stringify(data), {
3685
3693
  headers: { "content-type": "application/json" }
3686
3694
  });
@@ -3749,7 +3757,11 @@ var RuntypeFlowBuilder = class {
3749
3757
  const flow = this.existingFlowId ? { id: this.existingFlowId } : { name: this.flowConfig.name, steps: this.steps };
3750
3758
  const request6 = { flow };
3751
3759
  if (this.recordConfig) {
3752
- request6.record = this.recordConfig;
3760
+ const { id, ...record } = this.recordConfig;
3761
+ request6.record = {
3762
+ ...record,
3763
+ ...id !== void 0 ? { id: String(id) } : {}
3764
+ };
3753
3765
  }
3754
3766
  if (this.messagesConfig) {
3755
3767
  request6.messages = this.messagesConfig;
@@ -3821,6 +3833,9 @@ var RuntypeFlowBuilder = class {
3821
3833
  if (this.mode !== "upsert" || !this.steps.length) {
3822
3834
  return client.dispatch(config);
3823
3835
  }
3836
+ if (!config.flow) {
3837
+ throw new Error("Persisted flow dispatch requires a flow target");
3838
+ }
3824
3839
  const contentHash = await this.computeContentHash();
3825
3840
  const hashOnlyConfig = {
3826
3841
  ...config,
@@ -5891,6 +5906,47 @@ function transformQueryParams(params) {
5891
5906
  return result;
5892
5907
  }
5893
5908
 
5909
+ // src/dispatch-request.ts
5910
+ function normalizeDispatchMessageContent(content) {
5911
+ if (Array.isArray(content) && content.some(
5912
+ (part) => typeof part === "object" && part !== null && "type" in part && part.type === "asset_ref"
5913
+ )) {
5914
+ throw new Error(
5915
+ "Dispatch messages cannot submit persisted asset_ref content; provide the original image or file content instead"
5916
+ );
5917
+ }
5918
+ return content;
5919
+ }
5920
+ function normalizeDispatchRequest(request6) {
5921
+ if (!request6.flow && !request6.agent) {
5922
+ throw new Error("Dispatch requires either a flow or an agent target");
5923
+ }
5924
+ const record = request6.record === void 0 ? void 0 : {
5925
+ ...request6.record,
5926
+ ...request6.record.id !== void 0 ? { id: String(request6.record.id) } : {}
5927
+ };
5928
+ const messages = request6.messages?.map((message) => ({
5929
+ ...message,
5930
+ content: normalizeDispatchMessageContent(message.content)
5931
+ }));
5932
+ const clientTools = request6.clientTools?.map((tool) => {
5933
+ if (tool.parametersSchema.type !== "object") {
5934
+ throw new Error(`Client tool "${tool.name}" parametersSchema.type must be "object"`);
5935
+ }
5936
+ return {
5937
+ ...tool,
5938
+ parametersSchema: tool.parametersSchema
5939
+ };
5940
+ });
5941
+ const normalized = {
5942
+ ...request6,
5943
+ ...record !== void 0 ? { record } : {},
5944
+ ...messages !== void 0 ? { messages } : {},
5945
+ ...clientTools !== void 0 ? { clientTools } : {}
5946
+ };
5947
+ return request6.flow ? { ...normalized, flow: request6.flow } : { ...normalized, agent: request6.agent };
5948
+ }
5949
+
5894
5950
  // src/runtype.ts
5895
5951
  var globalConfig = {};
5896
5952
  var globalClient = null;
@@ -5988,12 +6044,42 @@ var RuntypeClient = class {
5988
6044
  });
5989
6045
  }
5990
6046
  /**
5991
- * Dispatch flow execution (streaming)
6047
+ * Dispatch flow execution (streaming).
6048
+ *
6049
+ * This is the sole streaming-dispatch chokepoint for the flow builders
6050
+ * (`RuntypeFlowBuilder`), so it normalizes the request to the canonical
6051
+ * `/v1/dispatch` wire contract here — every builder path inherits the same
6052
+ * normalization the `DispatchEndpoint` applies, with no per-builder call.
5992
6053
  */
5993
6054
  async dispatch(config) {
6055
+ const normalized = normalizeDispatchRequest(config);
6056
+ const request6 = transformRequest({
6057
+ ...normalized,
6058
+ options: {
6059
+ ...normalized.options,
6060
+ streamResponse: true
6061
+ }
6062
+ });
5994
6063
  return this.requestStream("/dispatch", {
5995
6064
  method: "POST",
5996
- body: JSON.stringify(transformRequest(config))
6065
+ body: JSON.stringify(request6)
6066
+ });
6067
+ }
6068
+ /**
6069
+ * Dispatch flow execution (non-streaming JSON).
6070
+ *
6071
+ * The non-streaming sibling of {@link dispatch}; it normalizes to the same
6072
+ * canonical wire contract so builders never post a raw, un-normalized body,
6073
+ * and pins `streamResponse: false` so the server returns buffered JSON.
6074
+ */
6075
+ async dispatchJson(config) {
6076
+ const normalized = normalizeDispatchRequest(config);
6077
+ return this.post("/dispatch", {
6078
+ ...normalized,
6079
+ options: {
6080
+ ...normalized.options,
6081
+ streamResponse: false
6082
+ }
5997
6083
  });
5998
6084
  }
5999
6085
  /**
@@ -6362,7 +6448,7 @@ var Runtype = class {
6362
6448
 
6363
6449
  // src/version.ts
6364
6450
  var FALLBACK_VERSION = "0.0.0";
6365
- var SDK_VERSION = "6.3.6".length > 0 ? "6.3.6" : FALLBACK_VERSION;
6451
+ var SDK_VERSION = "6.5.0".length > 0 ? "6.5.0" : FALLBACK_VERSION;
6366
6452
  var RUNTYPE_CLIENT_KIND = "sdk";
6367
6453
  var SDK_USER_AGENT = `runtype-sdk/${SDK_VERSION} (typescript)`;
6368
6454
 
@@ -6587,7 +6673,11 @@ function buildGeneratedRuntimeToolGateOutput(proposal, options = {}) {
6587
6673
  };
6588
6674
  }
6589
6675
  function attachRuntimeToolsToDispatchRequest(request6, runtimeTools, options = {}) {
6590
- const stepList = request6.flow.steps;
6676
+ const flow = request6.flow;
6677
+ if (!flow) {
6678
+ throw new Error("Cannot attach runtime tools: dispatch request must include flow.steps");
6679
+ }
6680
+ const stepList = flow.steps;
6591
6681
  if (!stepList || !Array.isArray(stepList) || stepList.length === 0) {
6592
6682
  throw new Error("Cannot attach runtime tools: dispatch request must include flow.steps");
6593
6683
  }
@@ -6632,7 +6722,7 @@ function attachRuntimeToolsToDispatchRequest(request6, runtimeTools, options = {
6632
6722
  return {
6633
6723
  ...request6,
6634
6724
  flow: {
6635
- ...request6.flow,
6725
+ ...flow,
6636
6726
  // `clonedSteps` is a structural clone of `request.flow.steps` (already
6637
6727
  // `FlowStepDefinition[]`); only the prompt step's `config.tools` was
6638
6728
  // merged, so every step's `type` discriminant is preserved. The clone is
@@ -8907,34 +8997,52 @@ var DispatchEndpoint = class {
8907
8997
  * Dispatch: create and/or execute flows on records atomically
8908
8998
  */
8909
8999
  async execute(data) {
8910
- return this.client.post("/dispatch", data);
9000
+ const normalized = normalizeDispatchRequest(data);
9001
+ return this.client.post("/dispatch", {
9002
+ ...normalized,
9003
+ options: {
9004
+ ...normalized.options,
9005
+ streamResponse: false
9006
+ }
9007
+ });
8911
9008
  }
8912
9009
  /**
8913
9010
  * Dispatch with streaming response
8914
9011
  */
8915
9012
  async executeStream(data) {
9013
+ const normalized = normalizeDispatchRequest(data);
8916
9014
  return this.client.requestStream("/dispatch", {
8917
9015
  method: "POST",
8918
- body: JSON.stringify(data)
9016
+ body: JSON.stringify({
9017
+ ...normalized,
9018
+ options: {
9019
+ ...normalized.options,
9020
+ streamResponse: true
9021
+ }
9022
+ })
8919
9023
  });
8920
9024
  }
8921
9025
  /**
8922
9026
  * Resume paused flow execution
8923
- * API expects snake_case field names
9027
+ * Uses buffered JSON when streamResponse is omitted.
8924
9028
  *
8925
- * @param data.execution_id - The execution ID to resume
8926
- * @param data.tool_outputs - Tool outputs to inject into the flow
8927
- * @param data.stream_response - Whether to stream the response
9029
+ * @param data.executionId - The execution ID to resume
9030
+ * @param data.toolOutputs - Tool outputs to inject into the flow
9031
+ * @param data.streamResponse - Whether to stream the response (defaults to false)
8928
9032
  * @param data.messages - Optional messages to override the original dispatch messages
8929
9033
  */
8930
9034
  async resume(data) {
8931
- if (data.streamResponse) {
9035
+ const request6 = {
9036
+ ...data,
9037
+ streamResponse: data.streamResponse ?? false
9038
+ };
9039
+ if (request6.streamResponse) {
8932
9040
  return this.client.requestStream("/dispatch/resume", {
8933
9041
  method: "POST",
8934
- body: JSON.stringify(data)
9042
+ body: JSON.stringify(request6)
8935
9043
  });
8936
9044
  }
8937
- return this.client.post("/dispatch/resume", data);
9045
+ return this.client.post("/dispatch/resume", request6);
8938
9046
  }
8939
9047
  /**
8940
9048
  * Evaluate a model-proposed runtime tool against a configurable allowlist policy.
@@ -9030,6 +9138,12 @@ var AnalyticsEndpoint = class {
9030
9138
  async getModelUsage(params) {
9031
9139
  return this.client.get("/model-usage", params);
9032
9140
  }
9141
+ /**
9142
+ * Get execution and platform-spend usage grouped by projected product end user.
9143
+ */
9144
+ async getEndUserUsage(params) {
9145
+ return this.client.get("/analytics/end-user-usage", params);
9146
+ }
9033
9147
  };
9034
9148
  var FlowStepsEndpoint = class {
9035
9149
  constructor(client) {
@@ -12800,6 +12914,21 @@ function hasToolEntryShape(value) {
12800
12914
  if (!isObjectRecord(value)) return false;
12801
12915
  return typeof value.execute === "function" && typeof value.description === "string" && typeof value.parametersSchema === "object" && value.parametersSchema !== null;
12802
12916
  }
12917
+ function assertTurnScopedLocalTools(localTools) {
12918
+ for (const [name, entry] of Object.entries(localTools)) {
12919
+ if (typeof entry === "function") continue;
12920
+ if (!hasToolEntryShape(entry)) {
12921
+ throw new Error(
12922
+ `Turn-scoped local tool "${name}" must be a function or an entry with description, parametersSchema, and execute`
12923
+ );
12924
+ }
12925
+ if (entry.parametersSchema.type !== "object") {
12926
+ throw new Error(
12927
+ `Turn-scoped local tool "${name}" parametersSchema.type must be "object"`
12928
+ );
12929
+ }
12930
+ }
12931
+ }
12803
12932
  function isPausedLocalActionResult(value) {
12804
12933
  return isObjectRecord(value) && value.status === "paused" && Array.isArray(value.pausedTools) && value.pausedTools.length > 0;
12805
12934
  }
@@ -12895,6 +13024,9 @@ var RuntypeClient2 = class {
12895
13024
  const options = (isOptionsObject(arg3) ? arg3 : arg4) ?? {};
12896
13025
  const scope = options.scope ?? "session";
12897
13026
  const isStreaming = !!callbacks;
13027
+ if (scope === "turn") {
13028
+ assertTurnScopedLocalTools(localTools);
13029
+ }
12898
13030
  const derivedClientTools = scope === "turn" ? Object.entries(localTools).filter((entry) => hasToolEntryShape(entry[1])).map(([name, entry]) => ({
12899
13031
  name,
12900
13032
  description: entry.description,