@workglow/tasks 0.2.2 → 0.2.4

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/browser.js CHANGED
@@ -6,17 +6,69 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
6
6
  throw Error('Dynamic require of "' + x + '" is not supported');
7
7
  });
8
8
 
9
- // src/task/image/imageRasterCodecBrowser.ts
10
- function normalizeMimeType(mimeType) {
11
- const m = mimeType.toLowerCase();
12
- if (m.includes("jpeg") || m.includes("jpg")) {
9
+ // src/task/image/imageCodecLimits.ts
10
+ var MAX_DECODED_PIXELS = 1e8;
11
+ var MAX_INPUT_BYTES_NODE = 64 * 1024 * 1024;
12
+ var MAX_INPUT_BYTES_BROWSER = 8 * 1024 * 1024;
13
+ var REJECTED_DECODE_MIME_TYPES = new Set([
14
+ "image/svg+xml",
15
+ "image/svg",
16
+ "image/gif",
17
+ "image/apng"
18
+ ]);
19
+ var SUPPORTED_OUTPUT_MIME_TYPES = ["image/jpeg", "image/png", "image/webp"];
20
+ function assertWithinPixelBudget(width, height) {
21
+ if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) {
22
+ throw new Error(`Image raster codec: invalid dimensions ${width}x${height}`);
23
+ }
24
+ const pixels = width * height;
25
+ if (pixels > MAX_DECODED_PIXELS) {
26
+ throw new Error(`Image raster codec: decoded image exceeds pixel budget ` + `(${width}x${height} = ${pixels} > ${MAX_DECODED_PIXELS})`);
27
+ }
28
+ }
29
+ function assertWithinByteBudget(byteLength, limit) {
30
+ if (byteLength > limit) {
31
+ throw new Error(`Image raster codec: input exceeds byte budget (${byteLength} > ${limit})`);
32
+ }
33
+ }
34
+ function formatDataUriErrorPreview(value) {
35
+ if (typeof value !== "string") {
36
+ return String(value);
37
+ }
38
+ if (value.startsWith("data:")) {
39
+ const commaIndex = value.indexOf(",");
40
+ if (commaIndex >= 0) {
41
+ return `${value.slice(0, commaIndex)},[REDACTED]`;
42
+ }
43
+ return `${value.slice(0, 80)}${value.length > 80 ? "…" : ""}`;
44
+ }
45
+ return `${value.slice(0, 80)}${value.length > 80 ? "…" : ""}`;
46
+ }
47
+ function assertIsDataUri(value) {
48
+ if (typeof value !== "string" || !value.startsWith("data:")) {
49
+ const preview = formatDataUriErrorPreview(value);
50
+ throw new Error(`Image raster codec: expected a data: URI but received "${preview}"`);
51
+ }
52
+ }
53
+ function extractDataUriMimeType(dataUri) {
54
+ const match = dataUri.match(/^data:([^;,]+)/);
55
+ return match?.[1]?.trim().toLowerCase();
56
+ }
57
+ function normalizeOutputMimeType(mimeType) {
58
+ const m = mimeType.toLowerCase().trim();
59
+ if (m === "image/jpeg" || m === "image/jpg") {
13
60
  return "image/jpeg";
14
61
  }
15
- if (m.includes("webp")) {
62
+ if (m === "image/png") {
63
+ return "image/png";
64
+ }
65
+ if (m === "image/webp") {
16
66
  return "image/webp";
17
67
  }
18
- return "image/png";
68
+ throw new Error(`Image raster codec: unsupported output mime type "${mimeType}". ` + `Supported: ${SUPPORTED_OUTPUT_MIME_TYPES.join(", ")}.`);
19
69
  }
70
+
71
+ // src/task/image/imageRasterCodecBrowser.ts
20
72
  function arrayBufferToBase64(buffer) {
21
73
  const bytes = new Uint8Array(buffer);
22
74
  const CHUNK = 8192;
@@ -76,22 +128,32 @@ function get2dContext(width, height) {
76
128
  throw new Error("No Canvas implementation available in this environment");
77
129
  }
78
130
  async function decodeDataUri(dataUri) {
131
+ assertIsDataUri(dataUri);
132
+ const declaredMime = extractDataUriMimeType(dataUri);
133
+ if (declaredMime && REJECTED_DECODE_MIME_TYPES.has(declaredMime)) {
134
+ throw new Error(`Image raster codec: refusing to rasterize "${declaredMime}". ` + `Vector and animated formats lose information when converted to pixels. ` + `Convert to PNG, JPEG, or WebP before passing to the codec.`);
135
+ }
79
136
  const response = await fetch(dataUri);
80
137
  const blob = await response.blob();
138
+ assertWithinByteBudget(blob.size, MAX_INPUT_BYTES_BROWSER);
81
139
  const bmp = await createImageBitmap(blob);
82
- const { ctx } = get2dContext(bmp.width, bmp.height);
83
- ctx.drawImage(bmp, 0, 0);
84
- const id = ctx.getImageData(0, 0, bmp.width, bmp.height);
85
- bmp.close();
86
- return {
87
- data: new Uint8ClampedArray(id.data),
88
- width: id.width,
89
- height: id.height,
90
- channels: 4
91
- };
140
+ try {
141
+ assertWithinPixelBudget(bmp.width, bmp.height);
142
+ const { ctx } = get2dContext(bmp.width, bmp.height);
143
+ ctx.drawImage(bmp, 0, 0);
144
+ const id = ctx.getImageData(0, 0, bmp.width, bmp.height);
145
+ return {
146
+ data: new Uint8ClampedArray(id.data),
147
+ width: id.width,
148
+ height: id.height,
149
+ channels: 4
150
+ };
151
+ } finally {
152
+ bmp.close();
153
+ }
92
154
  }
93
155
  async function encodeDataUri(image, mimeType) {
94
- const fmt = normalizeMimeType(mimeType);
156
+ const fmt = normalizeOutputMimeType(mimeType);
95
157
  const { canvas, ctx } = get2dContext(image.width, image.height);
96
158
  ctx.putImageData(rasterToImageData(image), 0, 0);
97
159
  if (canvas instanceof OffscreenCanvas) {
@@ -659,6 +721,280 @@ Workflow10.prototype.multiply = CreateAdaptiveWorkflow(ScalarMultiplyTask, Vecto
659
721
  Workflow10.prototype.divide = CreateAdaptiveWorkflow(ScalarDivideTask, VectorDivideTask);
660
722
  Workflow10.prototype.sum = CreateAdaptiveWorkflow(ScalarSumTask, VectorSumTask);
661
723
 
724
+ // src/util/SafeFetch.ts
725
+ import { PermanentJobError } from "@workglow/job-queue";
726
+
727
+ // src/util/UrlClassifier.ts
728
+ import ipaddr from "ipaddr.js";
729
+ var PRIVATE_EXACT_HOSTS = new Set([
730
+ "localhost",
731
+ "localhost.localdomain",
732
+ "ip6-localhost",
733
+ "ip6-loopback",
734
+ "metadata.google.internal",
735
+ "metadata.internal",
736
+ "metadata.azure.com",
737
+ "instance-data"
738
+ ]);
739
+ var PRIVATE_DOMAIN_SUFFIXES = [
740
+ "local",
741
+ "localhost",
742
+ "internal",
743
+ "lan",
744
+ "home.arpa",
745
+ "corp",
746
+ "intranet",
747
+ "private",
748
+ "localdomain"
749
+ ];
750
+ var PRIVATE_IPV4_RANGES = new Set([
751
+ "unspecified",
752
+ "broadcast",
753
+ "multicast",
754
+ "linkLocal",
755
+ "loopback",
756
+ "carrierGradeNat",
757
+ "private",
758
+ "reserved",
759
+ "benchmarking"
760
+ ]);
761
+ var PRIVATE_IPV6_RANGES = new Set([
762
+ "unspecified",
763
+ "linkLocal",
764
+ "multicast",
765
+ "loopback",
766
+ "uniqueLocal",
767
+ "ipv4Mapped",
768
+ "ipv4Compat",
769
+ "rfc6145",
770
+ "rfc6052",
771
+ "6to4",
772
+ "teredo",
773
+ "reserved",
774
+ "benchmarking",
775
+ "amt",
776
+ "as112v6",
777
+ "deprecated",
778
+ "orchid2",
779
+ "droneRemoteIdProtocolEntityTags"
780
+ ]);
781
+ function tryNormalizeIPv4(host) {
782
+ if (host.length === 0)
783
+ return;
784
+ if (/^\d{1,3}(\.\d{1,3}){3}$/.test(host)) {
785
+ const octets = host.split(".").map((s) => parseInt(s, 10));
786
+ if (octets.every((n) => n >= 0 && n <= 255)) {
787
+ return octets.join(".");
788
+ }
789
+ return;
790
+ }
791
+ const parts = host.split(".");
792
+ if (parts.length < 1 || parts.length > 4)
793
+ return;
794
+ const nums = [];
795
+ for (const p of parts) {
796
+ if (p.length === 0)
797
+ return;
798
+ let n;
799
+ if (/^0[xX][0-9a-fA-F]+$/.test(p)) {
800
+ n = parseInt(p.slice(2), 16);
801
+ } else if (/^0[0-7]+$/.test(p)) {
802
+ n = parseInt(p, 8);
803
+ } else if (/^\d+$/.test(p)) {
804
+ n = parseInt(p, 10);
805
+ } else {
806
+ return;
807
+ }
808
+ if (!Number.isFinite(n) || n < 0)
809
+ return;
810
+ nums.push(n);
811
+ }
812
+ let addr;
813
+ if (nums.length === 1) {
814
+ if (nums[0] > 4294967295)
815
+ return;
816
+ addr = nums[0];
817
+ } else if (nums.length === 2) {
818
+ if (nums[0] > 255 || nums[1] > 16777215)
819
+ return;
820
+ addr = nums[0] * 16777216 + nums[1];
821
+ } else if (nums.length === 3) {
822
+ if (nums[0] > 255 || nums[1] > 255 || nums[2] > 65535)
823
+ return;
824
+ addr = nums[0] * 16777216 + nums[1] * 65536 + nums[2];
825
+ } else {
826
+ if (nums.some((n) => n > 255))
827
+ return;
828
+ addr = nums[0] * 16777216 + nums[1] * 65536 + nums[2] * 256 + nums[3];
829
+ }
830
+ const o1 = Math.floor(addr / 16777216) & 255;
831
+ const o2 = Math.floor(addr / 65536) & 255;
832
+ const o3 = Math.floor(addr / 256) & 255;
833
+ const o4 = addr & 255;
834
+ return `${o1}.${o2}.${o3}.${o4}`;
835
+ }
836
+ function classifyIpLiteral(host) {
837
+ if (host.includes(":")) {
838
+ let ipv6;
839
+ try {
840
+ ipv6 = ipaddr.IPv6.parse(host);
841
+ } catch {
842
+ return;
843
+ }
844
+ if (ipv6.isIPv4MappedAddress()) {
845
+ const v4 = ipv6.toIPv4Address();
846
+ const range3 = v4.range();
847
+ const canonical3 = v4.toNormalizedString();
848
+ if (PRIVATE_IPV4_RANGES.has(range3)) {
849
+ return { kind: "private", reason: `IPv4-mapped IPv6 in ${range3} range`, canonical: canonical3 };
850
+ }
851
+ return { kind: "public", canonical: canonical3 };
852
+ }
853
+ const range2 = ipv6.range();
854
+ const canonical2 = ipv6.toNormalizedString();
855
+ if (PRIVATE_IPV6_RANGES.has(range2)) {
856
+ return { kind: "private", reason: `IPv6 in ${range2} range`, canonical: canonical2 };
857
+ }
858
+ return { kind: "public", canonical: canonical2 };
859
+ }
860
+ const canonical = tryNormalizeIPv4(host);
861
+ if (canonical === undefined)
862
+ return;
863
+ let ipv4;
864
+ try {
865
+ ipv4 = ipaddr.IPv4.parse(canonical);
866
+ } catch {
867
+ return;
868
+ }
869
+ const range = ipv4.range();
870
+ if (PRIVATE_IPV4_RANGES.has(range)) {
871
+ return { kind: "private", reason: `IPv4 in ${range} range`, canonical };
872
+ }
873
+ return { kind: "public", canonical };
874
+ }
875
+ function normalizeHost(host) {
876
+ let h = host;
877
+ if (h.startsWith("[") && h.endsWith("]")) {
878
+ h = h.slice(1, -1);
879
+ }
880
+ while (h.endsWith(".")) {
881
+ h = h.slice(0, -1);
882
+ }
883
+ return h.toLowerCase();
884
+ }
885
+ function matchesPrivateHostnamePattern(host) {
886
+ if (PRIVATE_EXACT_HOSTS.has(host)) {
887
+ return `host '${host}' is a reserved private name`;
888
+ }
889
+ for (const suffix of PRIVATE_DOMAIN_SUFFIXES) {
890
+ if (host === suffix || host.endsWith("." + suffix)) {
891
+ return `host matches private suffix '.${suffix}'`;
892
+ }
893
+ }
894
+ return;
895
+ }
896
+ function classifyUrl(urlStr) {
897
+ if (typeof urlStr !== "string" || urlStr.length === 0) {
898
+ return { kind: "invalid", reason: "empty or non-string URL" };
899
+ }
900
+ let parsed;
901
+ try {
902
+ parsed = new URL(urlStr);
903
+ } catch {
904
+ return { kind: "invalid", reason: "malformed URL" };
905
+ }
906
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
907
+ return { kind: "invalid", reason: `unsupported protocol '${parsed.protocol}'` };
908
+ }
909
+ if (parsed.username.length > 0 || parsed.password.length > 0) {
910
+ return { kind: "invalid", reason: "URL credentials are not allowed" };
911
+ }
912
+ const host = normalizeHost(parsed.hostname);
913
+ if (host.length === 0) {
914
+ return { kind: "invalid", reason: "empty host" };
915
+ }
916
+ const ipClassification = classifyIpLiteral(host);
917
+ if (ipClassification !== undefined) {
918
+ return {
919
+ kind: ipClassification.kind,
920
+ reason: ipClassification.reason,
921
+ host,
922
+ literalIp: ipClassification.canonical
923
+ };
924
+ }
925
+ const hostnameReason = matchesPrivateHostnamePattern(host);
926
+ if (hostnameReason !== undefined) {
927
+ return { kind: "private", reason: hostnameReason, host };
928
+ }
929
+ return { kind: "public", host };
930
+ }
931
+ function urlResourcePattern(urlStr) {
932
+ let parsed;
933
+ try {
934
+ parsed = new URL(urlStr);
935
+ } catch {
936
+ return urlStr;
937
+ }
938
+ const origin = parsed.port.length > 0 ? `${parsed.protocol}//${parsed.host}` : `${parsed.protocol}//${parsed.hostname}`;
939
+ return `${origin}/*`;
940
+ }
941
+
942
+ // src/util/SafeFetch.ts
943
+ var MAX_REDIRECT_HOPS = 20;
944
+ function assertAllowedUrl(url, allowPrivate) {
945
+ const classification = classifyUrl(url);
946
+ if (classification.kind === "invalid") {
947
+ throw new PermanentJobError(`Refusing to fetch invalid URL: ${classification.reason}`);
948
+ }
949
+ if (classification.kind === "private" && !allowPrivate) {
950
+ throw new PermanentJobError(`Refusing to fetch private/internal URL ${url}: ${classification.reason}. ` + `Grant the 'network:private' entitlement to allow this request.`);
951
+ }
952
+ }
953
+ function isRedirectStatus(status) {
954
+ return status === 301 || status === 302 || status === 303 || status === 307 || status === 308;
955
+ }
956
+ async function defaultSafeFetch(url, options) {
957
+ const requestedRedirectMode = options.redirect ?? "follow";
958
+ const { allowPrivate, redirect: _redirect, ...fetchOptions } = options;
959
+ let currentUrl = url;
960
+ for (let hops = 0;hops <= MAX_REDIRECT_HOPS; hops += 1) {
961
+ assertAllowedUrl(currentUrl, allowPrivate);
962
+ const response = await globalThis.fetch(currentUrl, {
963
+ ...fetchOptions,
964
+ redirect: "manual"
965
+ });
966
+ if (!isRedirectStatus(response.status)) {
967
+ return response;
968
+ }
969
+ if (requestedRedirectMode === "manual") {
970
+ return response;
971
+ }
972
+ if (requestedRedirectMode === "error") {
973
+ throw new TypeError(`Fetch for ${currentUrl} failed because redirect mode was set to 'error'.`);
974
+ }
975
+ const location = response.headers.get("location");
976
+ if (!location) {
977
+ throw new PermanentJobError(`Refusing to follow redirect from ${currentUrl}: missing Location header.`);
978
+ }
979
+ currentUrl = new URL(location, currentUrl).toString();
980
+ }
981
+ throw new PermanentJobError(`Refusing to fetch ${url}: too many redirects.`);
982
+ }
983
+ var currentImpl = defaultSafeFetch;
984
+ function registerSafeFetch(fn) {
985
+ const previousImpl = currentImpl;
986
+ currentImpl = fn;
987
+ return previousImpl;
988
+ }
989
+ function getSafeFetchImpl() {
990
+ return currentImpl;
991
+ }
992
+ function resetSafeFetch() {
993
+ currentImpl = defaultSafeFetch;
994
+ }
995
+ function safeFetch(url, options = {}) {
996
+ return currentImpl(url, options);
997
+ }
662
998
  // src/mcp-server/getMcpServerConfig.ts
663
999
  function getMcpServerConfig(configOrInput) {
664
1000
  const server = configOrInput.server;
@@ -1846,7 +2182,7 @@ Workflow13.prototype.delay = CreateWorkflow12(DelayTask);
1846
2182
  import {
1847
2183
  AbortSignalJobError,
1848
2184
  Job,
1849
- PermanentJobError,
2185
+ PermanentJobError as PermanentJobError2,
1850
2186
  RetryableJobError
1851
2187
  } from "@workglow/job-queue";
1852
2188
  import {
@@ -1855,52 +2191,13 @@ import {
1855
2191
  getJobQueueFactory,
1856
2192
  getTaskQueueRegistry,
1857
2193
  JobTaskFailedError,
2194
+ mergeEntitlements,
1858
2195
  Task as Task13,
1859
2196
  TaskConfigSchema as TaskConfigSchema3,
1860
2197
  TaskConfigurationError,
1861
2198
  TaskInvalidInputError as TaskInvalidInputError2,
1862
2199
  Workflow as Workflow14
1863
2200
  } from "@workglow/task-graph";
1864
- var PRIVATE_IP_RANGES = [
1865
- /^127\./,
1866
- /^10\./,
1867
- /^172\.(1[6-9]|2\d|3[01])\./,
1868
- /^192\.168\./,
1869
- /^169\.254\./,
1870
- /^0\./,
1871
- /^fc00:/i,
1872
- /^fe80:/i,
1873
- /^::1$/,
1874
- /^::$/
1875
- ];
1876
- var PRIVATE_HOSTNAMES = new Set(["localhost", "metadata.google.internal", "metadata.internal"]);
1877
- function isAllowPrivateUrlsEnvSet() {
1878
- if (globalThis?.process?.env?.WORKGLOW_ALLOW_PRIVATE_URLS === "true") {
1879
- return true;
1880
- }
1881
- const viteEnv = import.meta.env;
1882
- return viteEnv?.VITE_WORKGLOW_ALLOW_PRIVATE_URLS === "true";
1883
- }
1884
- function isPrivateUrl(urlStr) {
1885
- if (isAllowPrivateUrlsEnvSet()) {
1886
- return false;
1887
- }
1888
- try {
1889
- const parsed = new URL(urlStr);
1890
- const hostname = parsed.hostname.toLowerCase().replace(/^\[|\]$/g, "");
1891
- if (PRIVATE_HOSTNAMES.has(hostname) || hostname.endsWith(".local")) {
1892
- return true;
1893
- }
1894
- for (const range of PRIVATE_IP_RANGES) {
1895
- if (range.test(hostname)) {
1896
- return true;
1897
- }
1898
- }
1899
- return false;
1900
- } catch {
1901
- return false;
1902
- }
1903
- }
1904
2201
  var inputSchema13 = {
1905
2202
  type: "object",
1906
2203
  properties: {
@@ -1988,7 +2285,7 @@ async function fetchWithProgress(url, options = {}, onProgress) {
1988
2285
  if (!options.signal) {
1989
2286
  throw new TaskConfigurationError("An AbortSignal must be provided.");
1990
2287
  }
1991
- const response = await globalThis.fetch(url, options);
2288
+ const response = await safeFetch(url, options);
1992
2289
  if (!response.body) {
1993
2290
  throw new Error("ReadableStream not supported in this environment.");
1994
2291
  }
@@ -2037,14 +2334,16 @@ async function fetchWithProgress(url, options = {}, onProgress) {
2037
2334
  class FetchUrlJob extends Job {
2038
2335
  static type = "FetchUrlJob";
2039
2336
  async execute(input, context) {
2040
- if (isPrivateUrl(input.url)) {
2041
- throw new PermanentJobError(`Requests to private/internal networks are not allowed: ${input.url}. ` + `Set WORKGLOW_ALLOW_PRIVATE_URLS=true to override.`);
2337
+ const classification = classifyUrl(input.url);
2338
+ if (classification.kind === "invalid") {
2339
+ throw new PermanentJobError2(`Refusing to fetch invalid URL ${input.url}: ${classification.reason ?? "malformed"}`);
2042
2340
  }
2043
2341
  const response = await fetchWithProgress(input.url, {
2044
2342
  method: input.method,
2045
2343
  headers: input.headers,
2046
2344
  body: input.body,
2047
- signal: context.signal
2345
+ signal: context.signal,
2346
+ allowPrivate: classification.kind === "private"
2048
2347
  }, async (progress) => await context.updateProgress(progress));
2049
2348
  if (response.ok) {
2050
2349
  const contentType = response.headers.get("content-type") ?? "";
@@ -2097,7 +2396,7 @@ class FetchUrlJob extends Job {
2097
2396
  }
2098
2397
  throw new RetryableJobError(`Failed to fetch ${input.url}: ${response.status} ${response.statusText}`, retryDate);
2099
2398
  } else {
2100
- throw new PermanentJobError(`Failed to fetch ${input.url}: ${response.status} ${response.statusText}`);
2399
+ throw new PermanentJobError2(`Failed to fetch ${input.url}: ${response.status} ${response.statusText}`);
2101
2400
  }
2102
2401
  }
2103
2402
  }
@@ -2121,6 +2420,7 @@ class FetchUrlTask extends Task13 {
2121
2420
  static title = "Fetch";
2122
2421
  static description = "Fetches data from a URL with progress tracking and automatic retry handling";
2123
2422
  static hasDynamicSchemas = true;
2423
+ static hasDynamicEntitlements = true;
2124
2424
  static entitlements() {
2125
2425
  return {
2126
2426
  entitlements: [
@@ -2133,6 +2433,33 @@ class FetchUrlTask extends Task13 {
2133
2433
  ]
2134
2434
  };
2135
2435
  }
2436
+ entitlements() {
2437
+ const base = FetchUrlTask.entitlements();
2438
+ const url = this.runInputData?.url;
2439
+ if (typeof url !== "string" || url.length === 0) {
2440
+ return mergeEntitlements(base, {
2441
+ entitlements: [
2442
+ {
2443
+ id: Entitlements.NETWORK_PRIVATE,
2444
+ reason: "Runtime URL is not yet available during entitlement evaluation; private/internal destinations must be explicitly allowed"
2445
+ }
2446
+ ]
2447
+ });
2448
+ }
2449
+ const classification = classifyUrl(url);
2450
+ if (classification.kind !== "private") {
2451
+ return base;
2452
+ }
2453
+ return mergeEntitlements(base, {
2454
+ entitlements: [
2455
+ {
2456
+ id: Entitlements.NETWORK_PRIVATE,
2457
+ reason: `URL targets private/internal host: ${classification.reason ?? classification.host ?? "unknown"}`,
2458
+ resources: [urlResourcePattern(url)]
2459
+ }
2460
+ ]
2461
+ });
2462
+ }
2136
2463
  static configSchema() {
2137
2464
  return fetchUrlTaskConfigSchema;
2138
2465
  }
@@ -8832,7 +9159,7 @@ Workflow38.prototype.lambda = CreateWorkflow37(LambdaTask);
8832
9159
  import {
8833
9160
  CreateWorkflow as CreateWorkflow38,
8834
9161
  Entitlements as Entitlements3,
8835
- mergeEntitlements,
9162
+ mergeEntitlements as mergeEntitlements2,
8836
9163
  Task as Task37,
8837
9164
  Workflow as Workflow39
8838
9165
  } from "@workglow/task-graph";
@@ -9027,13 +9354,13 @@ class McpListTask extends Task37 {
9027
9354
  const base = McpListTask.entitlements();
9028
9355
  const transport = getMcpServerTransport(this);
9029
9356
  if (transport === "stdio") {
9030
- return mergeEntitlements(base, {
9357
+ return mergeEntitlements2(base, {
9031
9358
  entitlements: [
9032
9359
  { id: Entitlements3.MCP_STDIO, reason: "Uses stdio transport to spawn local process" }
9033
9360
  ]
9034
9361
  });
9035
9362
  }
9036
- return mergeEntitlements(base, {
9363
+ return mergeEntitlements2(base, {
9037
9364
  entitlements: [{ id: Entitlements3.NETWORK_HTTP, reason: "Connects to MCP server over HTTP" }]
9038
9365
  });
9039
9366
  }
@@ -9120,7 +9447,7 @@ Workflow39.prototype.mcpList = CreateWorkflow38(McpListTask);
9120
9447
  import {
9121
9448
  CreateWorkflow as CreateWorkflow39,
9122
9449
  Entitlements as Entitlements4,
9123
- mergeEntitlements as mergeEntitlements2,
9450
+ mergeEntitlements as mergeEntitlements3,
9124
9451
  Task as Task38,
9125
9452
  TaskConfigSchema as TaskConfigSchema8,
9126
9453
  Workflow as Workflow40
@@ -9276,13 +9603,13 @@ class McpPromptGetTask extends Task38 {
9276
9603
  const base = McpPromptGetTask.entitlements();
9277
9604
  const transport = getMcpServerTransport(this);
9278
9605
  if (transport === "stdio") {
9279
- return mergeEntitlements2(base, {
9606
+ return mergeEntitlements3(base, {
9280
9607
  entitlements: [
9281
9608
  { id: Entitlements4.MCP_STDIO, reason: "Uses stdio transport to spawn local process" }
9282
9609
  ]
9283
9610
  });
9284
9611
  }
9285
- return mergeEntitlements2(base, {
9612
+ return mergeEntitlements3(base, {
9286
9613
  entitlements: [
9287
9614
  { id: Entitlements4.NETWORK_HTTP, reason: "Connects to MCP server over HTTP" },
9288
9615
  { id: Entitlements4.CREDENTIAL, reason: "May require authentication", optional: true }
@@ -9386,7 +9713,7 @@ Workflow40.prototype.mcpPromptGet = CreateWorkflow39(McpPromptGetTask);
9386
9713
  import {
9387
9714
  CreateWorkflow as CreateWorkflow40,
9388
9715
  Entitlements as Entitlements5,
9389
- mergeEntitlements as mergeEntitlements3,
9716
+ mergeEntitlements as mergeEntitlements4,
9390
9717
  Task as Task39,
9391
9718
  TaskConfigSchema as TaskConfigSchema9,
9392
9719
  Workflow as Workflow41
@@ -9455,13 +9782,13 @@ class McpResourceReadTask extends Task39 {
9455
9782
  const base = McpResourceReadTask.entitlements();
9456
9783
  const transport = getMcpServerTransport(this);
9457
9784
  if (transport === "stdio") {
9458
- return mergeEntitlements3(base, {
9785
+ return mergeEntitlements4(base, {
9459
9786
  entitlements: [
9460
9787
  { id: Entitlements5.MCP_STDIO, reason: "Uses stdio transport to spawn local process" }
9461
9788
  ]
9462
9789
  });
9463
9790
  }
9464
- return mergeEntitlements3(base, {
9791
+ return mergeEntitlements4(base, {
9465
9792
  entitlements: [
9466
9793
  { id: Entitlements5.NETWORK_HTTP, reason: "Connects to MCP server over HTTP" },
9467
9794
  { id: Entitlements5.CREDENTIAL, reason: "May require authentication", optional: true }
@@ -9687,7 +10014,7 @@ Workflow42.prototype.mcpSearch = CreateWorkflow41(McpSearchTask);
9687
10014
  import {
9688
10015
  CreateWorkflow as CreateWorkflow42,
9689
10016
  Entitlements as Entitlements7,
9690
- mergeEntitlements as mergeEntitlements4,
10017
+ mergeEntitlements as mergeEntitlements5,
9691
10018
  Task as Task41,
9692
10019
  TaskConfigSchema as TaskConfigSchema10,
9693
10020
  Workflow as Workflow43
@@ -9835,13 +10162,13 @@ class McpToolCallTask extends Task41 {
9835
10162
  const base = McpToolCallTask.entitlements();
9836
10163
  const transport = getMcpServerTransport(this);
9837
10164
  if (transport === "stdio") {
9838
- return mergeEntitlements4(base, {
10165
+ return mergeEntitlements5(base, {
9839
10166
  entitlements: [
9840
10167
  { id: Entitlements7.MCP_STDIO, reason: "Uses stdio transport to spawn local process" }
9841
10168
  ]
9842
10169
  });
9843
10170
  }
9844
- return mergeEntitlements4(base, {
10171
+ return mergeEntitlements5(base, {
9845
10172
  entitlements: [
9846
10173
  { id: Entitlements7.NETWORK_HTTP, reason: "Connects to MCP server over HTTP" },
9847
10174
  { id: Entitlements7.CREDENTIAL, reason: "May require authentication", optional: true }
@@ -11934,18 +12261,24 @@ var registerCommonTasks2 = () => {
11934
12261
  return [...tasks, FileLoaderTask];
11935
12262
  };
11936
12263
  export {
12264
+ urlResourcePattern,
12265
+ tryNormalizeIPv4,
11937
12266
  split,
11938
12267
  setGlobalMcpServerRepository,
11939
12268
  searchMcpRegistryPage,
11940
12269
  searchMcpRegistry,
12270
+ safeFetch,
11941
12271
  resolveImageInput,
11942
12272
  resolveHumanConnector,
11943
12273
  resolveAuthSecrets,
12274
+ resetSafeFetch,
12275
+ registerSafeFetch,
11944
12276
  registerMcpTaskDeps,
11945
12277
  registerMcpServer,
11946
12278
  registerImageRasterCodec,
11947
12279
  registerCommonTasks2 as registerCommonTasks,
11948
12280
  produceImageOutput,
12281
+ normalizeOutputMimeType,
11949
12282
  merge,
11950
12283
  mcpTransportTypes,
11951
12284
  mcpToolCall,
@@ -11963,6 +12296,7 @@ export {
11963
12296
  json,
11964
12297
  javaScript,
11965
12298
  isDataUriImage,
12299
+ getSafeFetchImpl,
11966
12300
  getMcpTaskDeps,
11967
12301
  getMcpServerConfig,
11968
12302
  getMcpServer,
@@ -11972,11 +12306,17 @@ export {
11972
12306
  formatImageOutput,
11973
12307
  fileLoader,
11974
12308
  fetchUrl,
12309
+ extractDataUriMimeType,
11975
12310
  delay,
11976
12311
  debugLog,
11977
12312
  createMcpClient,
11978
12313
  createAuthProvider,
12314
+ classifyUrl,
12315
+ classifyIpLiteral,
11979
12316
  buildAuthConfig,
12317
+ assertWithinPixelBudget,
12318
+ assertWithinByteBudget,
12319
+ assertIsDataUri,
11980
12320
  VectorSumTask,
11981
12321
  VectorSubtractTask,
11982
12322
  VectorScaleTask,
@@ -12011,7 +12351,9 @@ export {
12011
12351
  ScalarCeilTask,
12012
12352
  ScalarAddTask,
12013
12353
  ScalarAbsTask,
12354
+ SUPPORTED_OUTPUT_MIME_TYPES,
12014
12355
  RegexTask,
12356
+ REJECTED_DECODE_MIME_TYPES,
12015
12357
  OutputTask,
12016
12358
  MergeTask,
12017
12359
  McpToolCallTask,
@@ -12026,6 +12368,9 @@ export {
12026
12368
  MCP_TASK_DEPS,
12027
12369
  MCP_SERVER_REPOSITORY,
12028
12370
  MCP_SERVERS,
12371
+ MAX_INPUT_BYTES_NODE,
12372
+ MAX_INPUT_BYTES_BROWSER,
12373
+ MAX_DECODED_PIXELS,
12029
12374
  LambdaTask,
12030
12375
  JsonTask,
12031
12376
  JsonPathTask,
@@ -12066,4 +12411,4 @@ export {
12066
12411
  ArrayTask
12067
12412
  };
12068
12413
 
12069
- //# debugId=D5A41017EFB846FA64756E2164756E21
12414
+ //# debugId=D1A8BE957A811A1A64756E2164756E21