@runtypelabs/sdk 4.1.0 → 4.2.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
@@ -1274,6 +1274,39 @@ function createExternalTool(config) {
1274
1274
  };
1275
1275
  }
1276
1276
 
1277
+ // src/local-tool-pause.ts
1278
+ var PENDING_NAMELESS_KEY = "";
1279
+ function collectLocalToolAwait(pausedTools, event) {
1280
+ if (event.type !== "flow_await" && event.type !== "step_await") return;
1281
+ const name = typeof event.toolName === "string" && event.toolName ? event.toolName : "";
1282
+ const executionId = typeof event.executionId === "string" && event.executionId ? event.executionId : void 0;
1283
+ if (name) {
1284
+ const pending = pausedTools.get(PENDING_NAMELESS_KEY);
1285
+ if (pending) pausedTools.delete(PENDING_NAMELESS_KEY);
1286
+ const prev2 = pausedTools.get(name) ?? pending;
1287
+ pausedTools.set(name, {
1288
+ toolName: name,
1289
+ executionId: executionId ?? prev2?.executionId ?? "",
1290
+ parameters: event.parameters ?? prev2?.parameters
1291
+ });
1292
+ return;
1293
+ }
1294
+ const namedKeys = [...pausedTools.keys()].filter((key) => key !== PENDING_NAMELESS_KEY);
1295
+ const targetKey = namedKeys.length > 0 ? namedKeys[namedKeys.length - 1] : PENDING_NAMELESS_KEY;
1296
+ const prev = pausedTools.get(targetKey);
1297
+ pausedTools.set(targetKey, {
1298
+ toolName: targetKey,
1299
+ executionId: executionId ?? prev?.executionId ?? "",
1300
+ parameters: event.parameters ?? prev?.parameters
1301
+ });
1302
+ }
1303
+ function resolveBatchExecutionId(pausedTools) {
1304
+ for (const tool of pausedTools) {
1305
+ if (tool.executionId) return tool.executionId;
1306
+ }
1307
+ return "";
1308
+ }
1309
+
1277
1310
  // src/flows-namespace.ts
1278
1311
  function isRecord(value) {
1279
1312
  return value !== null && typeof value === "object" && !Array.isArray(value);
@@ -1821,7 +1854,7 @@ var RuntypeFlowBuilder = class {
1821
1854
  };
1822
1855
  const processStep = async (response) => {
1823
1856
  if (isStreaming) {
1824
- let pausedState = null;
1857
+ const pausedTools = /* @__PURE__ */ new Map();
1825
1858
  const wrappedCallbacks = {
1826
1859
  ...callbacks,
1827
1860
  onFlowStart: (event) => callbacks?.onFlowStart?.(event),
@@ -1834,23 +1867,7 @@ var RuntypeFlowBuilder = class {
1834
1867
  const { streamEvents: streamEvents2, stepDeltaText: stepDeltaText2, stepDisplayName: stepDisplayName2, flowErrorMessage: flowErrorMessage2 } = await Promise.resolve().then(() => (init_stream_utils(), stream_utils_exports));
1835
1868
  try {
1836
1869
  for await (const event of streamEvents2(response)) {
1837
- const awaitEvent = event;
1838
- if (awaitEvent.type === "flow_await") {
1839
- const prev = pausedState;
1840
- pausedState = {
1841
- toolName: awaitEvent.toolName || prev?.toolName || "",
1842
- parameters: awaitEvent.parameters ?? prev?.parameters,
1843
- executionId: awaitEvent.executionId || prev?.executionId || ""
1844
- };
1845
- }
1846
- if (awaitEvent.type === "step_await") {
1847
- const prev = pausedState;
1848
- pausedState = {
1849
- toolName: awaitEvent.toolName || prev?.toolName || "",
1850
- parameters: awaitEvent.parameters ?? prev?.parameters,
1851
- executionId: awaitEvent.executionId || prev?.executionId || ""
1852
- };
1853
- }
1870
+ collectLocalToolAwait(pausedTools, event);
1854
1871
  switch (event.type) {
1855
1872
  case "flow_start":
1856
1873
  wrappedCallbacks.onFlowStart?.(event);
@@ -1878,19 +1895,34 @@ var RuntypeFlowBuilder = class {
1878
1895
  wrappedCallbacks.onError?.(e instanceof Error ? e : new Error(String(e)));
1879
1896
  throw e;
1880
1897
  }
1881
- if (pausedState) {
1898
+ if (pausedTools.size > 0) {
1882
1899
  return {
1883
1900
  done: false,
1884
- result: { status: "paused", pausedReason: { type: "local_action", ...pausedState } }
1901
+ result: { status: "paused", pausedTools: [...pausedTools.values()] }
1885
1902
  };
1886
1903
  }
1887
1904
  return { done: true, result: accumulatedSummary };
1888
1905
  } else {
1889
1906
  const data = await response.json();
1890
- return {
1891
- done: data.status !== "paused",
1892
- result: data
1893
- };
1907
+ if (data.status === "paused") {
1908
+ const pausedTools = /* @__PURE__ */ new Map();
1909
+ if (Array.isArray(data.events)) {
1910
+ for (const event of data.events) {
1911
+ collectLocalToolAwait(pausedTools, event);
1912
+ }
1913
+ }
1914
+ if (pausedTools.size === 0 && typeof data.pausedReason === "object" && data.pausedReason !== null && data.pausedReason.type === "local_action") {
1915
+ collectLocalToolAwait(pausedTools, {
1916
+ ...data.pausedReason,
1917
+ type: "flow_await"
1918
+ });
1919
+ }
1920
+ return {
1921
+ done: false,
1922
+ result: { status: "paused", pausedTools: [...pausedTools.values()] }
1923
+ };
1924
+ }
1925
+ return { done: true, result: data };
1894
1926
  }
1895
1927
  };
1896
1928
  let currentResponse;
@@ -1916,16 +1948,28 @@ var RuntypeFlowBuilder = class {
1916
1948
  );
1917
1949
  }
1918
1950
  const pausedResult = result;
1919
- if (pausedResult.status === "paused" && pausedResult.pausedReason?.type === "local_action") {
1920
- const { toolName, parameters, executionId } = pausedResult.pausedReason;
1921
- if (!localTools[toolName]) {
1922
- throw new Error(`Local tool "${toolName}" required but not provided in localTools map`);
1923
- }
1951
+ if (pausedResult.status === "paused" && pausedResult.pausedTools?.length) {
1952
+ const executionId = resolveBatchExecutionId(pausedResult.pausedTools);
1924
1953
  try {
1925
- const toolResult = await localTools[toolName](parameters);
1954
+ const outputs = await Promise.all(
1955
+ pausedResult.pausedTools.map(async ({ toolName, parameters }) => {
1956
+ if (!localTools[toolName]) {
1957
+ throw new Error(
1958
+ `Local tool "${toolName}" required but not provided in localTools map`
1959
+ );
1960
+ }
1961
+ try {
1962
+ return [toolName, await localTools[toolName](parameters)];
1963
+ } catch (error) {
1964
+ throw new Error(
1965
+ `Error executing local tool "${toolName}": ${error instanceof Error ? error.message : String(error)}`
1966
+ );
1967
+ }
1968
+ })
1969
+ );
1926
1970
  const resumeData = {
1927
1971
  executionId,
1928
- toolOutputs: { [toolName]: toolResult },
1972
+ toolOutputs: Object.fromEntries(outputs),
1929
1973
  streamResponse: isStreaming
1930
1974
  };
1931
1975
  if (isStreaming) {
@@ -1940,9 +1984,7 @@ var RuntypeFlowBuilder = class {
1940
1984
  });
1941
1985
  }
1942
1986
  } catch (error) {
1943
- throw new Error(
1944
- `Error executing local tool "${toolName}": ${error instanceof Error ? error.message : String(error)}`
1945
- );
1987
+ throw error instanceof Error ? error : new Error(String(error));
1946
1988
  }
1947
1989
  } else {
1948
1990
  break;
@@ -8515,11 +8557,7 @@ function hasToolEntryShape(value) {
8515
8557
  return typeof value.execute === "function" && typeof value.description === "string" && typeof value.parametersSchema === "object" && value.parametersSchema !== null;
8516
8558
  }
8517
8559
  function isPausedLocalActionResult(value) {
8518
- if (!isObjectRecord(value) || value.status !== "paused") {
8519
- return false;
8520
- }
8521
- const { pausedReason } = value;
8522
- return pausedReason === void 0 || isObjectRecord(pausedReason) && pausedReason.type === "local_action" && typeof pausedReason.toolName === "string" && typeof pausedReason.executionId === "string";
8560
+ return isObjectRecord(value) && value.status === "paused" && Array.isArray(value.pausedTools) && value.pausedTools.length > 0;
8523
8561
  }
8524
8562
  var RuntypeClient2 = class {
8525
8563
  constructor(config = {}) {
@@ -8621,7 +8659,7 @@ var RuntypeClient2 = class {
8621
8659
  };
8622
8660
  const processStep = async (response) => {
8623
8661
  if (isStreaming) {
8624
- let pausedState = null;
8662
+ const pausedTools = /* @__PURE__ */ new Map();
8625
8663
  const wrappedCallbacks = {
8626
8664
  ...callbacks,
8627
8665
  onFlowStart: (event) => callbacks?.onFlowStart?.(event),
@@ -8638,26 +8676,7 @@ var RuntypeClient2 = class {
8638
8676
  };
8639
8677
  try {
8640
8678
  for await (const event of streamEvents2(response)) {
8641
- if (event.type === "flow_await") {
8642
- const pausedEvent = event;
8643
- const prev = pausedState;
8644
- const next = {
8645
- toolName: pausedEvent.toolName ?? prev?.toolName ?? "",
8646
- executionId: pausedEvent.executionId ?? prev?.executionId ?? "",
8647
- parameters: prev?.parameters
8648
- };
8649
- pausedState = next;
8650
- }
8651
- if (event.type === "step_await") {
8652
- const pausedEvent = event;
8653
- const prev = pausedState;
8654
- const next = {
8655
- toolName: typeof pausedEvent.toolName === "string" ? pausedEvent.toolName : prev?.toolName ?? "",
8656
- parameters: pausedEvent.parameters,
8657
- executionId: typeof pausedEvent.executionId === "string" ? pausedEvent.executionId : prev?.executionId ?? ""
8658
- };
8659
- pausedState = next;
8660
- }
8679
+ collectLocalToolAwait(pausedTools, event);
8661
8680
  switch (event.type) {
8662
8681
  case "flow_start":
8663
8682
  wrappedCallbacks.onFlowStart?.(event);
@@ -8685,19 +8704,34 @@ var RuntypeClient2 = class {
8685
8704
  wrappedCallbacks.onError?.(e instanceof Error ? e : new Error(String(e)));
8686
8705
  throw e;
8687
8706
  }
8688
- if (pausedState) {
8707
+ if (pausedTools.size > 0) {
8689
8708
  return {
8690
8709
  done: false,
8691
- result: { status: "paused", pausedReason: { type: "local_action", ...pausedState } }
8710
+ result: { status: "paused", pausedTools: [...pausedTools.values()] }
8692
8711
  };
8693
8712
  }
8694
8713
  return { done: true, result: summary };
8695
8714
  } else {
8696
8715
  const data = await response.json();
8697
- return {
8698
- done: data.status !== "paused",
8699
- result: data
8700
- };
8716
+ if (data.status === "paused") {
8717
+ const pausedTools = /* @__PURE__ */ new Map();
8718
+ if (Array.isArray(data.events)) {
8719
+ for (const event of data.events) {
8720
+ collectLocalToolAwait(pausedTools, event);
8721
+ }
8722
+ }
8723
+ if (pausedTools.size === 0 && isObjectRecord(data.pausedReason) && data.pausedReason.type === "local_action") {
8724
+ collectLocalToolAwait(pausedTools, {
8725
+ ...data.pausedReason,
8726
+ type: "flow_await"
8727
+ });
8728
+ }
8729
+ return {
8730
+ done: false,
8731
+ result: { status: "paused", pausedTools: [...pausedTools.values()] }
8732
+ };
8733
+ }
8734
+ return { done: true, result: data };
8701
8735
  }
8702
8736
  };
8703
8737
  let currentResponse;
@@ -8717,26 +8751,38 @@ var RuntypeClient2 = class {
8717
8751
  new Response(JSON.stringify(result), { headers: { "content-type": "application/json" } })
8718
8752
  );
8719
8753
  }
8720
- if (isPausedLocalActionResult(result) && result.pausedReason?.type === "local_action") {
8721
- const { toolName, parameters, executionId } = result.pausedReason;
8722
- const BARE_NAME_NAMESPACES = ["webmcp:"];
8723
- const lookupCandidates = [toolName];
8724
- for (const ns of BARE_NAME_NAMESPACES) {
8725
- if (toolName.startsWith(ns)) {
8726
- lookupCandidates.push(toolName.slice(ns.length));
8727
- }
8728
- }
8729
- const matchedKey = lookupCandidates.find((key) => localTools[key]);
8730
- const toolEntry = matchedKey ? localTools[matchedKey] : void 0;
8731
- if (!toolEntry) {
8732
- throw new Error(`Local tool "${toolName}" required but not provided in localTools map`);
8733
- }
8734
- const handler = hasToolEntryShape(toolEntry) ? toolEntry.execute : toolEntry;
8754
+ if (isPausedLocalActionResult(result)) {
8755
+ const executionId = resolveBatchExecutionId(result.pausedTools);
8735
8756
  try {
8736
- const toolResult = await handler(parameters);
8757
+ const outputs = await Promise.all(
8758
+ result.pausedTools.map(async ({ toolName, parameters }) => {
8759
+ const BARE_NAME_NAMESPACES = ["webmcp:"];
8760
+ const lookupCandidates = [toolName];
8761
+ for (const ns of BARE_NAME_NAMESPACES) {
8762
+ if (toolName.startsWith(ns)) {
8763
+ lookupCandidates.push(toolName.slice(ns.length));
8764
+ }
8765
+ }
8766
+ const matchedKey = lookupCandidates.find((key) => localTools[key]);
8767
+ const toolEntry = matchedKey ? localTools[matchedKey] : void 0;
8768
+ if (!toolEntry) {
8769
+ throw new Error(
8770
+ `Local tool "${toolName}" required but not provided in localTools map`
8771
+ );
8772
+ }
8773
+ const handler = hasToolEntryShape(toolEntry) ? toolEntry.execute : toolEntry;
8774
+ try {
8775
+ return [toolName, await handler(parameters)];
8776
+ } catch (error) {
8777
+ throw new Error(
8778
+ `Error executing local tool "${toolName}": ${error instanceof Error ? error.message : String(error)}`
8779
+ );
8780
+ }
8781
+ })
8782
+ );
8737
8783
  const resumeData = {
8738
8784
  executionId,
8739
- toolOutputs: { [toolName]: toolResult },
8785
+ toolOutputs: Object.fromEntries(outputs),
8740
8786
  streamResponse: isStreaming
8741
8787
  };
8742
8788
  if (isStreaming) {
@@ -8748,9 +8794,7 @@ var RuntypeClient2 = class {
8748
8794
  });
8749
8795
  }
8750
8796
  } catch (error) {
8751
- throw new Error(
8752
- `Error executing local tool "${toolName}": ${error instanceof Error ? error.message : String(error)}`
8753
- );
8797
+ throw error instanceof Error ? error : new Error(String(error));
8754
8798
  }
8755
8799
  } else {
8756
8800
  break;
package/dist/index.d.cts CHANGED
@@ -34208,6 +34208,12 @@ interface DeploySandboxRequest {
34208
34208
  sandboxId?: string;
34209
34209
  startCommand?: string;
34210
34210
  files?: Record<string, string>;
34211
+ /** Custom labels applied at sandbox creation (Daytona), for provenance/cleanup. */
34212
+ labels?: Record<string, string>;
34213
+ /** Auto-stop interval in minutes (Daytona). Defaults to 120 when omitted. */
34214
+ autoStopInterval?: number;
34215
+ /** Auto-delete interval in minutes (Daytona); 0 deletes immediately on stop. Disabled when omitted. */
34216
+ autoDeleteInterval?: number;
34211
34217
  }
34212
34218
  interface DeploySandboxResponse {
34213
34219
  sandboxId: string;
package/dist/index.d.ts CHANGED
@@ -34208,6 +34208,12 @@ interface DeploySandboxRequest {
34208
34208
  sandboxId?: string;
34209
34209
  startCommand?: string;
34210
34210
  files?: Record<string, string>;
34211
+ /** Custom labels applied at sandbox creation (Daytona), for provenance/cleanup. */
34212
+ labels?: Record<string, string>;
34213
+ /** Auto-stop interval in minutes (Daytona). Defaults to 120 when omitted. */
34214
+ autoStopInterval?: number;
34215
+ /** Auto-delete interval in minutes (Daytona); 0 deletes immediately on stop. Disabled when omitted. */
34216
+ autoDeleteInterval?: number;
34211
34217
  }
34212
34218
  interface DeploySandboxResponse {
34213
34219
  sandboxId: string;
package/dist/index.mjs CHANGED
@@ -1191,6 +1191,39 @@ function createExternalTool(config) {
1191
1191
  };
1192
1192
  }
1193
1193
 
1194
+ // src/local-tool-pause.ts
1195
+ var PENDING_NAMELESS_KEY = "";
1196
+ function collectLocalToolAwait(pausedTools, event) {
1197
+ if (event.type !== "flow_await" && event.type !== "step_await") return;
1198
+ const name = typeof event.toolName === "string" && event.toolName ? event.toolName : "";
1199
+ const executionId = typeof event.executionId === "string" && event.executionId ? event.executionId : void 0;
1200
+ if (name) {
1201
+ const pending = pausedTools.get(PENDING_NAMELESS_KEY);
1202
+ if (pending) pausedTools.delete(PENDING_NAMELESS_KEY);
1203
+ const prev2 = pausedTools.get(name) ?? pending;
1204
+ pausedTools.set(name, {
1205
+ toolName: name,
1206
+ executionId: executionId ?? prev2?.executionId ?? "",
1207
+ parameters: event.parameters ?? prev2?.parameters
1208
+ });
1209
+ return;
1210
+ }
1211
+ const namedKeys = [...pausedTools.keys()].filter((key) => key !== PENDING_NAMELESS_KEY);
1212
+ const targetKey = namedKeys.length > 0 ? namedKeys[namedKeys.length - 1] : PENDING_NAMELESS_KEY;
1213
+ const prev = pausedTools.get(targetKey);
1214
+ pausedTools.set(targetKey, {
1215
+ toolName: targetKey,
1216
+ executionId: executionId ?? prev?.executionId ?? "",
1217
+ parameters: event.parameters ?? prev?.parameters
1218
+ });
1219
+ }
1220
+ function resolveBatchExecutionId(pausedTools) {
1221
+ for (const tool of pausedTools) {
1222
+ if (tool.executionId) return tool.executionId;
1223
+ }
1224
+ return "";
1225
+ }
1226
+
1194
1227
  // src/flows-namespace.ts
1195
1228
  function isRecord(value) {
1196
1229
  return value !== null && typeof value === "object" && !Array.isArray(value);
@@ -1738,7 +1771,7 @@ var RuntypeFlowBuilder = class {
1738
1771
  };
1739
1772
  const processStep = async (response) => {
1740
1773
  if (isStreaming) {
1741
- let pausedState = null;
1774
+ const pausedTools = /* @__PURE__ */ new Map();
1742
1775
  const wrappedCallbacks = {
1743
1776
  ...callbacks,
1744
1777
  onFlowStart: (event) => callbacks?.onFlowStart?.(event),
@@ -1751,23 +1784,7 @@ var RuntypeFlowBuilder = class {
1751
1784
  const { streamEvents: streamEvents2, stepDeltaText: stepDeltaText2, stepDisplayName: stepDisplayName2, flowErrorMessage: flowErrorMessage2 } = await Promise.resolve().then(() => (init_stream_utils(), stream_utils_exports));
1752
1785
  try {
1753
1786
  for await (const event of streamEvents2(response)) {
1754
- const awaitEvent = event;
1755
- if (awaitEvent.type === "flow_await") {
1756
- const prev = pausedState;
1757
- pausedState = {
1758
- toolName: awaitEvent.toolName || prev?.toolName || "",
1759
- parameters: awaitEvent.parameters ?? prev?.parameters,
1760
- executionId: awaitEvent.executionId || prev?.executionId || ""
1761
- };
1762
- }
1763
- if (awaitEvent.type === "step_await") {
1764
- const prev = pausedState;
1765
- pausedState = {
1766
- toolName: awaitEvent.toolName || prev?.toolName || "",
1767
- parameters: awaitEvent.parameters ?? prev?.parameters,
1768
- executionId: awaitEvent.executionId || prev?.executionId || ""
1769
- };
1770
- }
1787
+ collectLocalToolAwait(pausedTools, event);
1771
1788
  switch (event.type) {
1772
1789
  case "flow_start":
1773
1790
  wrappedCallbacks.onFlowStart?.(event);
@@ -1795,19 +1812,34 @@ var RuntypeFlowBuilder = class {
1795
1812
  wrappedCallbacks.onError?.(e instanceof Error ? e : new Error(String(e)));
1796
1813
  throw e;
1797
1814
  }
1798
- if (pausedState) {
1815
+ if (pausedTools.size > 0) {
1799
1816
  return {
1800
1817
  done: false,
1801
- result: { status: "paused", pausedReason: { type: "local_action", ...pausedState } }
1818
+ result: { status: "paused", pausedTools: [...pausedTools.values()] }
1802
1819
  };
1803
1820
  }
1804
1821
  return { done: true, result: accumulatedSummary };
1805
1822
  } else {
1806
1823
  const data = await response.json();
1807
- return {
1808
- done: data.status !== "paused",
1809
- result: data
1810
- };
1824
+ if (data.status === "paused") {
1825
+ const pausedTools = /* @__PURE__ */ new Map();
1826
+ if (Array.isArray(data.events)) {
1827
+ for (const event of data.events) {
1828
+ collectLocalToolAwait(pausedTools, event);
1829
+ }
1830
+ }
1831
+ if (pausedTools.size === 0 && typeof data.pausedReason === "object" && data.pausedReason !== null && data.pausedReason.type === "local_action") {
1832
+ collectLocalToolAwait(pausedTools, {
1833
+ ...data.pausedReason,
1834
+ type: "flow_await"
1835
+ });
1836
+ }
1837
+ return {
1838
+ done: false,
1839
+ result: { status: "paused", pausedTools: [...pausedTools.values()] }
1840
+ };
1841
+ }
1842
+ return { done: true, result: data };
1811
1843
  }
1812
1844
  };
1813
1845
  let currentResponse;
@@ -1833,16 +1865,28 @@ var RuntypeFlowBuilder = class {
1833
1865
  );
1834
1866
  }
1835
1867
  const pausedResult = result;
1836
- if (pausedResult.status === "paused" && pausedResult.pausedReason?.type === "local_action") {
1837
- const { toolName, parameters, executionId } = pausedResult.pausedReason;
1838
- if (!localTools[toolName]) {
1839
- throw new Error(`Local tool "${toolName}" required but not provided in localTools map`);
1840
- }
1868
+ if (pausedResult.status === "paused" && pausedResult.pausedTools?.length) {
1869
+ const executionId = resolveBatchExecutionId(pausedResult.pausedTools);
1841
1870
  try {
1842
- const toolResult = await localTools[toolName](parameters);
1871
+ const outputs = await Promise.all(
1872
+ pausedResult.pausedTools.map(async ({ toolName, parameters }) => {
1873
+ if (!localTools[toolName]) {
1874
+ throw new Error(
1875
+ `Local tool "${toolName}" required but not provided in localTools map`
1876
+ );
1877
+ }
1878
+ try {
1879
+ return [toolName, await localTools[toolName](parameters)];
1880
+ } catch (error) {
1881
+ throw new Error(
1882
+ `Error executing local tool "${toolName}": ${error instanceof Error ? error.message : String(error)}`
1883
+ );
1884
+ }
1885
+ })
1886
+ );
1843
1887
  const resumeData = {
1844
1888
  executionId,
1845
- toolOutputs: { [toolName]: toolResult },
1889
+ toolOutputs: Object.fromEntries(outputs),
1846
1890
  streamResponse: isStreaming
1847
1891
  };
1848
1892
  if (isStreaming) {
@@ -1857,9 +1901,7 @@ var RuntypeFlowBuilder = class {
1857
1901
  });
1858
1902
  }
1859
1903
  } catch (error) {
1860
- throw new Error(
1861
- `Error executing local tool "${toolName}": ${error instanceof Error ? error.message : String(error)}`
1862
- );
1904
+ throw error instanceof Error ? error : new Error(String(error));
1863
1905
  }
1864
1906
  } else {
1865
1907
  break;
@@ -8432,11 +8474,7 @@ function hasToolEntryShape(value) {
8432
8474
  return typeof value.execute === "function" && typeof value.description === "string" && typeof value.parametersSchema === "object" && value.parametersSchema !== null;
8433
8475
  }
8434
8476
  function isPausedLocalActionResult(value) {
8435
- if (!isObjectRecord(value) || value.status !== "paused") {
8436
- return false;
8437
- }
8438
- const { pausedReason } = value;
8439
- return pausedReason === void 0 || isObjectRecord(pausedReason) && pausedReason.type === "local_action" && typeof pausedReason.toolName === "string" && typeof pausedReason.executionId === "string";
8477
+ return isObjectRecord(value) && value.status === "paused" && Array.isArray(value.pausedTools) && value.pausedTools.length > 0;
8440
8478
  }
8441
8479
  var RuntypeClient2 = class {
8442
8480
  constructor(config = {}) {
@@ -8538,7 +8576,7 @@ var RuntypeClient2 = class {
8538
8576
  };
8539
8577
  const processStep = async (response) => {
8540
8578
  if (isStreaming) {
8541
- let pausedState = null;
8579
+ const pausedTools = /* @__PURE__ */ new Map();
8542
8580
  const wrappedCallbacks = {
8543
8581
  ...callbacks,
8544
8582
  onFlowStart: (event) => callbacks?.onFlowStart?.(event),
@@ -8555,26 +8593,7 @@ var RuntypeClient2 = class {
8555
8593
  };
8556
8594
  try {
8557
8595
  for await (const event of streamEvents2(response)) {
8558
- if (event.type === "flow_await") {
8559
- const pausedEvent = event;
8560
- const prev = pausedState;
8561
- const next = {
8562
- toolName: pausedEvent.toolName ?? prev?.toolName ?? "",
8563
- executionId: pausedEvent.executionId ?? prev?.executionId ?? "",
8564
- parameters: prev?.parameters
8565
- };
8566
- pausedState = next;
8567
- }
8568
- if (event.type === "step_await") {
8569
- const pausedEvent = event;
8570
- const prev = pausedState;
8571
- const next = {
8572
- toolName: typeof pausedEvent.toolName === "string" ? pausedEvent.toolName : prev?.toolName ?? "",
8573
- parameters: pausedEvent.parameters,
8574
- executionId: typeof pausedEvent.executionId === "string" ? pausedEvent.executionId : prev?.executionId ?? ""
8575
- };
8576
- pausedState = next;
8577
- }
8596
+ collectLocalToolAwait(pausedTools, event);
8578
8597
  switch (event.type) {
8579
8598
  case "flow_start":
8580
8599
  wrappedCallbacks.onFlowStart?.(event);
@@ -8602,19 +8621,34 @@ var RuntypeClient2 = class {
8602
8621
  wrappedCallbacks.onError?.(e instanceof Error ? e : new Error(String(e)));
8603
8622
  throw e;
8604
8623
  }
8605
- if (pausedState) {
8624
+ if (pausedTools.size > 0) {
8606
8625
  return {
8607
8626
  done: false,
8608
- result: { status: "paused", pausedReason: { type: "local_action", ...pausedState } }
8627
+ result: { status: "paused", pausedTools: [...pausedTools.values()] }
8609
8628
  };
8610
8629
  }
8611
8630
  return { done: true, result: summary };
8612
8631
  } else {
8613
8632
  const data = await response.json();
8614
- return {
8615
- done: data.status !== "paused",
8616
- result: data
8617
- };
8633
+ if (data.status === "paused") {
8634
+ const pausedTools = /* @__PURE__ */ new Map();
8635
+ if (Array.isArray(data.events)) {
8636
+ for (const event of data.events) {
8637
+ collectLocalToolAwait(pausedTools, event);
8638
+ }
8639
+ }
8640
+ if (pausedTools.size === 0 && isObjectRecord(data.pausedReason) && data.pausedReason.type === "local_action") {
8641
+ collectLocalToolAwait(pausedTools, {
8642
+ ...data.pausedReason,
8643
+ type: "flow_await"
8644
+ });
8645
+ }
8646
+ return {
8647
+ done: false,
8648
+ result: { status: "paused", pausedTools: [...pausedTools.values()] }
8649
+ };
8650
+ }
8651
+ return { done: true, result: data };
8618
8652
  }
8619
8653
  };
8620
8654
  let currentResponse;
@@ -8634,26 +8668,38 @@ var RuntypeClient2 = class {
8634
8668
  new Response(JSON.stringify(result), { headers: { "content-type": "application/json" } })
8635
8669
  );
8636
8670
  }
8637
- if (isPausedLocalActionResult(result) && result.pausedReason?.type === "local_action") {
8638
- const { toolName, parameters, executionId } = result.pausedReason;
8639
- const BARE_NAME_NAMESPACES = ["webmcp:"];
8640
- const lookupCandidates = [toolName];
8641
- for (const ns of BARE_NAME_NAMESPACES) {
8642
- if (toolName.startsWith(ns)) {
8643
- lookupCandidates.push(toolName.slice(ns.length));
8644
- }
8645
- }
8646
- const matchedKey = lookupCandidates.find((key) => localTools[key]);
8647
- const toolEntry = matchedKey ? localTools[matchedKey] : void 0;
8648
- if (!toolEntry) {
8649
- throw new Error(`Local tool "${toolName}" required but not provided in localTools map`);
8650
- }
8651
- const handler = hasToolEntryShape(toolEntry) ? toolEntry.execute : toolEntry;
8671
+ if (isPausedLocalActionResult(result)) {
8672
+ const executionId = resolveBatchExecutionId(result.pausedTools);
8652
8673
  try {
8653
- const toolResult = await handler(parameters);
8674
+ const outputs = await Promise.all(
8675
+ result.pausedTools.map(async ({ toolName, parameters }) => {
8676
+ const BARE_NAME_NAMESPACES = ["webmcp:"];
8677
+ const lookupCandidates = [toolName];
8678
+ for (const ns of BARE_NAME_NAMESPACES) {
8679
+ if (toolName.startsWith(ns)) {
8680
+ lookupCandidates.push(toolName.slice(ns.length));
8681
+ }
8682
+ }
8683
+ const matchedKey = lookupCandidates.find((key) => localTools[key]);
8684
+ const toolEntry = matchedKey ? localTools[matchedKey] : void 0;
8685
+ if (!toolEntry) {
8686
+ throw new Error(
8687
+ `Local tool "${toolName}" required but not provided in localTools map`
8688
+ );
8689
+ }
8690
+ const handler = hasToolEntryShape(toolEntry) ? toolEntry.execute : toolEntry;
8691
+ try {
8692
+ return [toolName, await handler(parameters)];
8693
+ } catch (error) {
8694
+ throw new Error(
8695
+ `Error executing local tool "${toolName}": ${error instanceof Error ? error.message : String(error)}`
8696
+ );
8697
+ }
8698
+ })
8699
+ );
8654
8700
  const resumeData = {
8655
8701
  executionId,
8656
- toolOutputs: { [toolName]: toolResult },
8702
+ toolOutputs: Object.fromEntries(outputs),
8657
8703
  streamResponse: isStreaming
8658
8704
  };
8659
8705
  if (isStreaming) {
@@ -8665,9 +8711,7 @@ var RuntypeClient2 = class {
8665
8711
  });
8666
8712
  }
8667
8713
  } catch (error) {
8668
- throw new Error(
8669
- `Error executing local tool "${toolName}": ${error instanceof Error ? error.message : String(error)}`
8670
- );
8714
+ throw error instanceof Error ? error : new Error(String(error));
8671
8715
  }
8672
8716
  } else {
8673
8717
  break;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@runtypelabs/sdk",
3
- "version": "4.1.0",
3
+ "version": "4.2.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",