@runtypelabs/sdk 6.3.6 → 6.4.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
@@ -487,6 +487,7 @@ function createAgentEventTranslator() {
487
487
  toolName: data.toolName,
488
488
  toolType: data.toolType,
489
489
  parameters: data.parameters,
490
+ hiddenParameterNames: data.hiddenParameterNames,
490
491
  origin: data.origin,
491
492
  pageOrigin: data.pageOrigin
492
493
  })
@@ -1815,7 +1816,11 @@ var FlowBuilder = class {
1815
1816
  const flow = this.existingFlowId ? { id: this.existingFlowId } : { name: this.flowConfig.name, steps: this.steps };
1816
1817
  const request6 = { flow };
1817
1818
  if (this.recordConfig) {
1818
- request6.record = this.recordConfig;
1819
+ const { id, ...record } = this.recordConfig;
1820
+ request6.record = {
1821
+ ...record,
1822
+ ...id !== void 0 ? { id: String(id) } : {}
1823
+ };
1819
1824
  }
1820
1825
  if (this.messagesConfig) {
1821
1826
  request6.messages = this.messagesConfig;
@@ -1958,8 +1963,7 @@ var ClientFlowBuilder = class extends FlowBuilder {
1958
1963
  let runCallbacks;
1959
1964
  let localTools;
1960
1965
  let dispatchClient = this.boundClient;
1961
- const isLocalTools = (obj) => obj && typeof obj === "object" && !isStreamCallbacks(obj) && !("streamResponse" in obj) && // Not options
1962
- !("dispatch" in obj);
1966
+ 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
1967
  if (arg1) {
1964
1968
  if (typeof arg1 === "object" && "dispatch" in arg1) {
1965
1969
  if (arg2) {
@@ -3680,7 +3684,7 @@ var RuntypeFlowBuilder = class {
3680
3684
  if (isStreaming) {
3681
3685
  currentResponse = await client.dispatch(config);
3682
3686
  } else {
3683
- const data = await client.post("/dispatch", config);
3687
+ const data = await client.dispatchJson(config);
3684
3688
  currentResponse = new Response(JSON.stringify(data), {
3685
3689
  headers: { "content-type": "application/json" }
3686
3690
  });
@@ -3749,7 +3753,11 @@ var RuntypeFlowBuilder = class {
3749
3753
  const flow = this.existingFlowId ? { id: this.existingFlowId } : { name: this.flowConfig.name, steps: this.steps };
3750
3754
  const request6 = { flow };
3751
3755
  if (this.recordConfig) {
3752
- request6.record = this.recordConfig;
3756
+ const { id, ...record } = this.recordConfig;
3757
+ request6.record = {
3758
+ ...record,
3759
+ ...id !== void 0 ? { id: String(id) } : {}
3760
+ };
3753
3761
  }
3754
3762
  if (this.messagesConfig) {
3755
3763
  request6.messages = this.messagesConfig;
@@ -3821,6 +3829,9 @@ var RuntypeFlowBuilder = class {
3821
3829
  if (this.mode !== "upsert" || !this.steps.length) {
3822
3830
  return client.dispatch(config);
3823
3831
  }
3832
+ if (!config.flow) {
3833
+ throw new Error("Persisted flow dispatch requires a flow target");
3834
+ }
3824
3835
  const contentHash = await this.computeContentHash();
3825
3836
  const hashOnlyConfig = {
3826
3837
  ...config,
@@ -5891,6 +5902,47 @@ function transformQueryParams(params) {
5891
5902
  return result;
5892
5903
  }
5893
5904
 
5905
+ // src/dispatch-request.ts
5906
+ function normalizeDispatchMessageContent(content) {
5907
+ if (Array.isArray(content) && content.some(
5908
+ (part) => typeof part === "object" && part !== null && "type" in part && part.type === "asset_ref"
5909
+ )) {
5910
+ throw new Error(
5911
+ "Dispatch messages cannot submit persisted asset_ref content; provide the original image or file content instead"
5912
+ );
5913
+ }
5914
+ return content;
5915
+ }
5916
+ function normalizeDispatchRequest(request6) {
5917
+ if (!request6.flow && !request6.agent) {
5918
+ throw new Error("Dispatch requires either a flow or an agent target");
5919
+ }
5920
+ const record = request6.record === void 0 ? void 0 : {
5921
+ ...request6.record,
5922
+ ...request6.record.id !== void 0 ? { id: String(request6.record.id) } : {}
5923
+ };
5924
+ const messages = request6.messages?.map((message) => ({
5925
+ ...message,
5926
+ content: normalizeDispatchMessageContent(message.content)
5927
+ }));
5928
+ const clientTools = request6.clientTools?.map((tool) => {
5929
+ if (tool.parametersSchema.type !== "object") {
5930
+ throw new Error(`Client tool "${tool.name}" parametersSchema.type must be "object"`);
5931
+ }
5932
+ return {
5933
+ ...tool,
5934
+ parametersSchema: tool.parametersSchema
5935
+ };
5936
+ });
5937
+ const normalized = {
5938
+ ...request6,
5939
+ ...record !== void 0 ? { record } : {},
5940
+ ...messages !== void 0 ? { messages } : {},
5941
+ ...clientTools !== void 0 ? { clientTools } : {}
5942
+ };
5943
+ return request6.flow ? { ...normalized, flow: request6.flow } : { ...normalized, agent: request6.agent };
5944
+ }
5945
+
5894
5946
  // src/runtype.ts
5895
5947
  var globalConfig = {};
5896
5948
  var globalClient = null;
@@ -5988,14 +6040,28 @@ var RuntypeClient = class {
5988
6040
  });
5989
6041
  }
5990
6042
  /**
5991
- * Dispatch flow execution (streaming)
6043
+ * Dispatch flow execution (streaming).
6044
+ *
6045
+ * This is the sole streaming-dispatch chokepoint for the flow builders
6046
+ * (`RuntypeFlowBuilder`), so it normalizes the request to the canonical
6047
+ * `/v1/dispatch` wire contract here — every builder path inherits the same
6048
+ * normalization the `DispatchEndpoint` applies, with no per-builder call.
5992
6049
  */
5993
6050
  async dispatch(config) {
5994
6051
  return this.requestStream("/dispatch", {
5995
6052
  method: "POST",
5996
- body: JSON.stringify(transformRequest(config))
6053
+ body: JSON.stringify(transformRequest(normalizeDispatchRequest(config)))
5997
6054
  });
5998
6055
  }
6056
+ /**
6057
+ * Dispatch flow execution (non-streaming JSON).
6058
+ *
6059
+ * The non-streaming sibling of {@link dispatch}; it normalizes to the same
6060
+ * canonical wire contract so builders never post a raw, un-normalized body.
6061
+ */
6062
+ async dispatchJson(config) {
6063
+ return this.post("/dispatch", normalizeDispatchRequest(config));
6064
+ }
5999
6065
  /**
6000
6066
  * Build full URL with query parameters
6001
6067
  */
@@ -6362,7 +6428,7 @@ var Runtype = class {
6362
6428
 
6363
6429
  // src/version.ts
6364
6430
  var FALLBACK_VERSION = "0.0.0";
6365
- var SDK_VERSION = "6.3.6".length > 0 ? "6.3.6" : FALLBACK_VERSION;
6431
+ var SDK_VERSION = "6.4.0".length > 0 ? "6.4.0" : FALLBACK_VERSION;
6366
6432
  var RUNTYPE_CLIENT_KIND = "sdk";
6367
6433
  var SDK_USER_AGENT = `runtype-sdk/${SDK_VERSION} (typescript)`;
6368
6434
 
@@ -6587,7 +6653,11 @@ function buildGeneratedRuntimeToolGateOutput(proposal, options = {}) {
6587
6653
  };
6588
6654
  }
6589
6655
  function attachRuntimeToolsToDispatchRequest(request6, runtimeTools, options = {}) {
6590
- const stepList = request6.flow.steps;
6656
+ const flow = request6.flow;
6657
+ if (!flow) {
6658
+ throw new Error("Cannot attach runtime tools: dispatch request must include flow.steps");
6659
+ }
6660
+ const stepList = flow.steps;
6591
6661
  if (!stepList || !Array.isArray(stepList) || stepList.length === 0) {
6592
6662
  throw new Error("Cannot attach runtime tools: dispatch request must include flow.steps");
6593
6663
  }
@@ -6632,7 +6702,7 @@ function attachRuntimeToolsToDispatchRequest(request6, runtimeTools, options = {
6632
6702
  return {
6633
6703
  ...request6,
6634
6704
  flow: {
6635
- ...request6.flow,
6705
+ ...flow,
6636
6706
  // `clonedSteps` is a structural clone of `request.flow.steps` (already
6637
6707
  // `FlowStepDefinition[]`); only the prompt step's `config.tools` was
6638
6708
  // merged, so every step's `type` discriminant is preserved. The clone is
@@ -8907,7 +8977,7 @@ var DispatchEndpoint = class {
8907
8977
  * Dispatch: create and/or execute flows on records atomically
8908
8978
  */
8909
8979
  async execute(data) {
8910
- return this.client.post("/dispatch", data);
8980
+ return this.client.post("/dispatch", normalizeDispatchRequest(data));
8911
8981
  }
8912
8982
  /**
8913
8983
  * Dispatch with streaming response
@@ -8915,7 +8985,7 @@ var DispatchEndpoint = class {
8915
8985
  async executeStream(data) {
8916
8986
  return this.client.requestStream("/dispatch", {
8917
8987
  method: "POST",
8918
- body: JSON.stringify(data)
8988
+ body: JSON.stringify(normalizeDispatchRequest(data))
8919
8989
  });
8920
8990
  }
8921
8991
  /**
@@ -12800,6 +12870,21 @@ function hasToolEntryShape(value) {
12800
12870
  if (!isObjectRecord(value)) return false;
12801
12871
  return typeof value.execute === "function" && typeof value.description === "string" && typeof value.parametersSchema === "object" && value.parametersSchema !== null;
12802
12872
  }
12873
+ function assertTurnScopedLocalTools(localTools) {
12874
+ for (const [name, entry] of Object.entries(localTools)) {
12875
+ if (typeof entry === "function") continue;
12876
+ if (!hasToolEntryShape(entry)) {
12877
+ throw new Error(
12878
+ `Turn-scoped local tool "${name}" must be a function or an entry with description, parametersSchema, and execute`
12879
+ );
12880
+ }
12881
+ if (entry.parametersSchema.type !== "object") {
12882
+ throw new Error(
12883
+ `Turn-scoped local tool "${name}" parametersSchema.type must be "object"`
12884
+ );
12885
+ }
12886
+ }
12887
+ }
12803
12888
  function isPausedLocalActionResult(value) {
12804
12889
  return isObjectRecord(value) && value.status === "paused" && Array.isArray(value.pausedTools) && value.pausedTools.length > 0;
12805
12890
  }
@@ -12895,6 +12980,9 @@ var RuntypeClient2 = class {
12895
12980
  const options = (isOptionsObject(arg3) ? arg3 : arg4) ?? {};
12896
12981
  const scope = options.scope ?? "session";
12897
12982
  const isStreaming = !!callbacks;
12983
+ if (scope === "turn") {
12984
+ assertTurnScopedLocalTools(localTools);
12985
+ }
12898
12986
  const derivedClientTools = scope === "turn" ? Object.entries(localTools).filter((entry) => hasToolEntryShape(entry[1])).map(([name, entry]) => ({
12899
12987
  name,
12900
12988
  description: entry.description,