@poe-platform/safe-bash 0.1.825 → 0.1.827

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.
Files changed (155) hide show
  1. package/dist/image-ast/index.js +39 -18
  2. package/dist/pdf-ast/image.js +1 -1
  3. package/dist/pdf-ast/index.js +1 -1
  4. package/dist/pdf-ast/vendor/pdfjs-fonts.mjs +9 -3
  5. package/dist/safe-bash/chunks/{chunk-AGHV53VF.js → chunk-M6XFU6LQ.js} +3 -1
  6. package/dist/safe-bash/chunks/{chunk-363QOIDR.js → chunk-T6FHWSHM.js} +3 -1
  7. package/dist/safe-bash/command-chunks/{chunk-ZPBL7TYJ.js → chunk-2JRHCVMQ.js} +1 -1
  8. package/dist/safe-bash/command-chunks/{chunk-FMGNXOMV.js → chunk-2L3NMRLG.js} +7 -3
  9. package/dist/safe-bash/command-chunks/{chunk-DAQO64WC.js → chunk-2YKOJPIW.js} +1 -1
  10. package/dist/safe-bash/command-chunks/{chunk-EPYJSPOY.js → chunk-3QCW4VQF.js} +12 -8
  11. package/dist/safe-bash/command-chunks/{chunk-YRBFNT5B.js → chunk-3YL2TMLA.js} +10 -1
  12. package/dist/safe-bash/command-chunks/{chunk-5H7ZHP7F.js → chunk-43NDRBKY.js} +1 -1
  13. package/dist/safe-bash/command-chunks/{chunk-BBOYR6LV.js → chunk-46GA576V.js} +3 -3
  14. package/dist/safe-bash/command-chunks/{chunk-WPT2FCHH.js → chunk-4SLPM2WM.js} +1 -1
  15. package/dist/safe-bash/command-chunks/{chunk-7ZQVMPSB.js → chunk-5CAXR62E.js} +1 -1
  16. package/dist/safe-bash/command-chunks/{chunk-3DTHX5UU.js → chunk-66653AEZ.js} +40 -14
  17. package/dist/safe-bash/command-chunks/{chunk-ETFJ4L7F.js → chunk-6OLE6CLV.js} +1 -1
  18. package/dist/safe-bash/command-chunks/{chunk-ZIDESNHW.js → chunk-7M3M6FKC.js} +1 -1
  19. package/dist/safe-bash/command-chunks/{chunk-2KMNVJB7.js → chunk-A7PKUIJT.js} +1 -1
  20. package/dist/safe-bash/command-chunks/{chunk-AVSINNZ6.js → chunk-DEQ47SBQ.js} +5 -5
  21. package/dist/safe-bash/command-chunks/{chunk-EV7A5FNN.js → chunk-FFFRLPXU.js} +2 -2
  22. package/dist/safe-bash/command-chunks/{chunk-4MVQE6CT.js → chunk-FYTBEGSY.js} +1 -1
  23. package/dist/safe-bash/command-chunks/{chunk-LFTGMUAV.js → chunk-HQIZR6EU.js} +192 -489
  24. package/dist/safe-bash/command-chunks/chunk-HS2L7I4N.js +219 -0
  25. package/dist/safe-bash/command-chunks/{chunk-WKS2PAZL.js → chunk-HUGKO4ZE.js} +10 -1
  26. package/dist/safe-bash/command-chunks/chunk-IGXH5W5Z.js +111 -0
  27. package/dist/safe-bash/command-chunks/{chunk-CMJBRGU2.js → chunk-IHQZKUBS.js} +1 -1
  28. package/dist/safe-bash/command-chunks/chunk-JADJ4BMN.js +1519 -0
  29. package/dist/safe-bash/command-chunks/{chunk-5AQAWIYK.js → chunk-JEZC5V3B.js} +4 -0
  30. package/dist/safe-bash/command-chunks/{chunk-YB5TNDY6.js → chunk-K5VJ4NNL.js} +39 -5
  31. package/dist/safe-bash/command-chunks/{chunk-7RQGRFHJ.js → chunk-KHWDEAE4.js} +2 -2
  32. package/dist/safe-bash/command-chunks/chunk-L54KVUSY.js +604 -0
  33. package/dist/safe-bash/command-chunks/{chunk-3NJETNC2.js → chunk-MBXNG6C3.js} +2 -2
  34. package/dist/safe-bash/command-chunks/{chunk-HCPEYQKT.js → chunk-N4SH6QY5.js} +285 -302
  35. package/dist/safe-bash/command-chunks/{chunk-3DID6MQY.js → chunk-OWTQYLID.js} +2 -2
  36. package/dist/safe-bash/command-chunks/{chunk-4EA7WI3L.js → chunk-QOOQD6BD.js} +42 -33
  37. package/dist/safe-bash/command-chunks/{chunk-RQTFK7AV.js → chunk-QZYEI4N6.js} +1 -1
  38. package/dist/safe-bash/command-chunks/{chunk-R3SLT3ZX.js → chunk-R6GON4H3.js} +11 -1
  39. package/dist/safe-bash/command-chunks/{chunk-2GILUQJY.js → chunk-R7ZGDHME.js} +3 -3
  40. package/dist/safe-bash/command-chunks/{chunk-HNEWGADJ.js → chunk-RUXOFW5G.js} +7 -6
  41. package/dist/safe-bash/command-chunks/{chunk-LKAFLJ5L.js → chunk-RWQKX44L.js} +1 -1
  42. package/dist/safe-bash/command-chunks/{chunk-PKH57OIC.js → chunk-SG2KOOD4.js} +2 -2
  43. package/dist/safe-bash/command-chunks/chunk-T4TGJYFV.js +60 -0
  44. package/dist/safe-bash/command-chunks/chunk-TGSNVLFZ.js +105 -0
  45. package/dist/safe-bash/command-chunks/{chunk-NXCJNPL3.js → chunk-UCE77LYV.js} +2 -1
  46. package/dist/safe-bash/command-chunks/{chunk-EWECMOQ5.js → chunk-UIHPHIKI.js} +1 -1
  47. package/dist/safe-bash/command-chunks/{chunk-XSZNL3GV.js → chunk-UJPWPRVB.js} +191 -146
  48. package/dist/safe-bash/command-chunks/{chunk-E5CDHXFA.js → chunk-VOR6YDZC.js} +26 -1
  49. package/dist/safe-bash/command-chunks/chunk-VSNVYOK2.js +30 -0
  50. package/dist/safe-bash/command-chunks/{chunk-4XYGJB24.js → chunk-VTH4AORO.js} +3 -3
  51. package/dist/safe-bash/command-chunks/{chunk-W5LH7D23.js → chunk-WKKJJBJQ.js} +8 -8
  52. package/dist/safe-bash/command-chunks/{chunk-OLXMWQJ5.js → chunk-WRO3PB2M.js} +1 -1
  53. package/dist/safe-bash/command-chunks/{chunk-RUAGHZNF.js → chunk-X5ODTF3E.js} +7 -5
  54. package/dist/safe-bash/command-chunks/{chunk-LH4VBNF6.js → chunk-XGTSP2CP.js} +84 -16
  55. package/dist/safe-bash/command-chunks/{chunk-K576GZED.js → chunk-XTHKXCF2.js} +2 -2
  56. package/dist/safe-bash/command-chunks/{chunk-J3VS55K4.js → chunk-YHRESVJ7.js} +9 -3
  57. package/dist/safe-bash/command-chunks/{chunk-UWIDPTOB.js → chunk-YSCKOUQP.js} +1 -1
  58. package/dist/safe-bash/command-chunks/{chunk-UYNJF5QN.js → chunk-ZALAWNOE.js} +76 -122
  59. package/dist/safe-bash/command-chunks/{chunk-OT75C5YS.js → chunk-ZYXKW2K7.js} +1 -1
  60. package/dist/safe-bash/command-chunks/{pdf-renderer-346WYKSZ.js → pdf-renderer-5QWOVFA4.js} +1 -1
  61. package/dist/safe-bash/command-chunks/{prompt-tool-debug-3POFNRYP.js → prompt-tool-debug-G7ATE7D5.js} +6 -4
  62. package/dist/safe-bash/commands/llm/index.browser.js +5 -1
  63. package/dist/safe-bash/commands/llm/index.js +1 -1
  64. package/dist/safe-bash/commands/python/executor.browser.js +3 -1
  65. package/dist/safe-bash/commands/python/executor.js +1 -1
  66. package/dist/safe-bash/commands/python/index.browser.js +5 -1
  67. package/dist/safe-bash/commands/python/index.js +1 -1
  68. package/dist/safe-bash/core.browser.js +2 -2
  69. package/dist/safe-bash/full-core.browser.js +10 -2
  70. package/dist/safe-bash-command-awk/awk-runtime.js +2 -2
  71. package/dist/safe-bash-command-awk/awk-syntax.js +1 -1
  72. package/dist/safe-bash-command-awk/awk.js +3 -3
  73. package/dist/safe-bash-command-awk/index.js +3 -3
  74. package/dist/safe-bash-command-gpg/index.js +11 -3
  75. package/dist/safe-bash-command-imagemagick/index.js +2 -2
  76. package/dist/safe-bash-command-llm/collections.js +6 -4
  77. package/dist/safe-bash-command-llm/command.js +4 -4
  78. package/dist/safe-bash-command-llm/import-json-document.d.ts +9 -2
  79. package/dist/safe-bash-command-llm/index.d.ts +2 -1
  80. package/dist/safe-bash-command-llm/index.js +10 -4
  81. package/dist/safe-bash-command-llm/loader-provider.d.ts +5 -0
  82. package/dist/safe-bash-command-mcp/index.js +10 -13
  83. package/dist/safe-bash-command-pdftoppm/index.js +2 -2
  84. package/dist/safe-bash-command-playwright-cli/index.js +2 -2
  85. package/dist/safe-bash-command-playwright-cli/playwright/ability-execution.d.ts +1 -0
  86. package/dist/safe-bash-command-playwright-cli/playwright/ability-execution.js +1 -1
  87. package/dist/safe-bash-command-playwright-cli/playwright/controller.d.ts +2 -0
  88. package/dist/safe-bash-command-playwright-cli/playwright/controller.js +2 -2
  89. package/dist/safe-bash-command-playwright-cli/playwright/index.js +2 -2
  90. package/dist/safe-bash-command-python/build-backend.d.ts +2 -0
  91. package/dist/safe-bash-command-python/cache.d.ts +1 -1
  92. package/dist/safe-bash-command-python/executor.d.ts +5 -2
  93. package/dist/safe-bash-command-python/executor.js +11 -6
  94. package/dist/safe-bash-command-python/host-capabilities.js +1 -1
  95. package/dist/safe-bash-command-python/index.js +11 -6
  96. package/dist/safe-bash-command-python/jspi.js +5 -3
  97. package/dist/safe-bash-command-python/manifest-file.d.ts +44 -0
  98. package/dist/safe-bash-command-python/manifest.d.ts +45 -0
  99. package/dist/safe-bash-command-python/provisioning.d.ts +20 -1
  100. package/dist/safe-bash-command-python/provisioning.js +3 -2
  101. package/dist/safe-bash-command-python/reply.js +7 -11
  102. package/dist/safe-bash-command-python/source-archive.js +2 -2
  103. package/dist/safe-bash-command-python/source-zip.js +2 -2
  104. package/dist/safe-bash-command-python/worker.js +34 -21
  105. package/dist/safe-bash-command-sqlite3/engine.d.ts +4 -0
  106. package/dist/safe-bash-command-sqlite3/index.js +174 -18
  107. package/dist/safe-bash-command-svgo/index.js +1 -1
  108. package/dist/safe-bash-command-tar/create.js +3 -3
  109. package/dist/safe-bash-command-tar/extract.js +3 -3
  110. package/dist/safe-bash-command-tar/index.js +5 -5
  111. package/dist/safe-bash-command-tar/modes.js +5 -5
  112. package/dist/safe-bash-command-tar/options.d.ts +1 -1
  113. package/dist/safe-bash-command-tar/options.js +1 -1
  114. package/dist/safe-bash-command-tar/stream.js +1 -1
  115. package/dist/safe-bash-command-wkhtmltopdf/index.js +1 -1
  116. package/dist/safe-bash-command-xan/argv.js +1 -1
  117. package/dist/safe-bash-command-xan/commands.js +3 -3
  118. package/dist/safe-bash-command-xan/index.js +3 -3
  119. package/dist/safe-bash-command-xan/io.js +2 -2
  120. package/dist/safe-bash-compression-engine/bounded-codec.js +3 -3
  121. package/dist/safe-bash-compression-engine/codec-loader.js +2 -2
  122. package/dist/safe-bash-compression-engine/files.js +6 -6
  123. package/dist/safe-bash-compression-engine/index.js +5 -5
  124. package/dist/safe-bash-compression-engine/operand.js +6 -6
  125. package/dist/safe-bash-compression-engine/options.js +1 -1
  126. package/dist/safe-bash-compression-engine/stream.js +5 -5
  127. package/dist/safe-bash-compression-engine/zstd-decode.js +4 -4
  128. package/dist/safe-bash-contracts/filesystem-descriptor.js +1 -1
  129. package/dist/safe-bash-contracts/filesystem-output.js +1 -1
  130. package/dist/safe-bash-csv-engine/index.js +6 -6
  131. package/dist/safe-bash-csv-engine/python-codec-aliases.js +1 -1
  132. package/dist/safe-bash-csv-engine/python-codepages.js +3 -3
  133. package/dist/safe-bash-csv-engine/python-file-codepages.js +2 -2
  134. package/dist/safe-bash-csv-engine/python-utf16.js +4 -4
  135. package/dist/safe-bash-csv-engine/text-decoder.js +6 -6
  136. package/dist/safe-bash-graphviz-engine/index.js +1 -1
  137. package/dist/safe-bash-pager-engine/index.js +2 -2
  138. package/dist/safe-bash-query-engine/capture.js +3 -3
  139. package/dist/safe-bash-query-engine/delpaths.js +3 -3
  140. package/dist/safe-bash-query-engine/formats.js +2 -2
  141. package/dist/safe-bash-query-engine/index.js +10 -10
  142. package/dist/safe-bash-query-engine/indices.js +3 -3
  143. package/dist/safe-bash-query-engine/input.d.ts +3 -3
  144. package/dist/safe-bash-query-engine/input.js +1 -1
  145. package/dist/safe-bash-query-engine/interpreter.js +9 -9
  146. package/dist/safe-bash-query-engine/query-core.js +10 -10
  147. package/dist/safe-bash-query-engine/regex.js +4 -4
  148. package/dist/safe-bash-query-engine/splits.js +5 -5
  149. package/dist/safe-bash-query-engine/values.js +2 -2
  150. package/package.json +2 -2
  151. package/dist/safe-bash/command-chunks/chunk-OOYVZAWL.js +0 -90
  152. package/dist/safe-bash/command-chunks/chunk-RZOHZGEZ.js +0 -772
  153. package/dist/safe-bash/command-chunks/chunk-WIUEM7HP.js +0 -58
  154. package/dist/safe-bash/command-chunks/chunk-WY6THI6J.js +0 -673
  155. package/dist/safe-bash/command-chunks/chunk-ZERCTWUI.js +0 -467
@@ -3,18 +3,18 @@ import {
3
3
  createPythonPackageManifestStore,
4
4
  publishPythonBuildWheel,
5
5
  pythonDocumentPackages
6
- } from "./chunk-RZOHZGEZ.js";
6
+ } from "./chunk-JADJ4BMN.js";
7
7
  import {
8
8
  pythonShellDispatchActive
9
9
  } from "./chunk-NHAG4DWL.js";
10
- import {
11
- openPythonPackageFile
12
- } from "./chunk-NXCJNPL3.js";
13
10
  import {
14
11
  PythonInvocationError,
15
12
  parsePythonInvocation,
16
13
  pythonPackageUrlHash
17
- } from "./chunk-WY6THI6J.js";
14
+ } from "./chunk-L54KVUSY.js";
15
+ import {
16
+ openPythonPackageFile
17
+ } from "./chunk-UCE77LYV.js";
18
18
  import {
19
19
  pythonLlmProvider
20
20
  } from "./chunk-YYRVGXJH.js";
@@ -28,7 +28,7 @@ import {
28
28
  } from "./chunk-TO6UNFEF.js";
29
29
  import {
30
30
  createPythonHostBridge
31
- } from "./chunk-EPYJSPOY.js";
31
+ } from "./chunk-3QCW4VQF.js";
32
32
 
33
33
  // packages/safe-bash-command-python/src/executor.ts
34
34
  import { PythonFileSystem, PythonStatTranslator } from "@poe-platform/safe-fs/core";
@@ -40,12 +40,15 @@ import { FsError } from "../../safe-bash-contracts/errors.js";
40
40
  function encodePythonReply(value, maxBytes) {
41
41
  let used = 0;
42
42
  const ancestors = /* @__PURE__ */ new Set();
43
+ const checkSize = (bytes, remaining = maxBytes - used) => {
44
+ if (bytes > remaining) throw new FsError("EFBIG", { syscall: "python reply" });
45
+ };
43
46
  const reserve = (bytes) => {
47
+ checkSize(bytes);
44
48
  used += bytes;
45
- if (used > maxBytes) throw new FsError("EFBIG", { syscall: "python reply" });
46
49
  };
47
50
  const string = (text) => {
48
- if (text.length + 2 > maxBytes - used) throw new FsError("EFBIG", { syscall: "python reply" });
51
+ checkSize(text.length + 2);
49
52
  reserve(2);
50
53
  for (let index = 0; index < text.length; index++) {
51
54
  const code = text.charCodeAt(index);
@@ -61,7 +64,7 @@ function encodePythonReply(value, maxBytes) {
61
64
  return text;
62
65
  };
63
66
  const own = (input, depth) => {
64
- if (depth > 64) throw new FsError("EFBIG", { syscall: "python reply" });
67
+ checkSize(depth, 64);
65
68
  if (input === null || input === void 0) {
66
69
  reserve(4);
67
70
  return null;
@@ -80,7 +83,7 @@ function encodePythonReply(value, maxBytes) {
80
83
  ancestors.add(input);
81
84
  try {
82
85
  if (input instanceof Uint8Array || Array.isArray(input)) {
83
- if (input.length > maxBytes - used) throw new FsError("EFBIG", { syscall: "python reply" });
86
+ checkSize(input.length);
84
87
  reserve(2);
85
88
  const output2 = [];
86
89
  for (let index = 0; index < input.length; index++) {
@@ -97,7 +100,7 @@ function encodePythonReply(value, maxBytes) {
97
100
  let visited = 0;
98
101
  for (const key in input) {
99
102
  if (!Object.hasOwn(input, key)) continue;
100
- if (++visited > maxBytes) throw new FsError("EFBIG", { syscall: "python reply" });
103
+ checkSize(++visited, maxBytes);
101
104
  const descriptor = Object.getOwnPropertyDescriptor(input, key);
102
105
  if (!("value" in descriptor)) throw new TypeError("Accessor Python reply");
103
106
  if (descriptor.value === void 0 || typeof descriptor.value === "function") continue;
@@ -120,8 +123,10 @@ var PythonInstallationError = class extends Error {
120
123
  };
121
124
  var pythonInstallationHelp = `Usage: python -m pip install [OPTIONS] PACKAGE ...
122
125
  python -m pip uninstall [-y/--yes] PACKAGE ...
123
- Install: -r/--requirement FILE, -e/--editable PATH, --pre, -U/--upgrade,
124
- --force-reinstall, --no-cache-dir
126
+ Install: -r/--requirement FILE, -c/--constraint FILE, -e/--editable PATH,
127
+ --pre, --no-deps/--no-dependencies, -U/--upgrade,
128
+ --force-reinstall, --no-cache-dir, --no-index
129
+ -i/--index-url URL, --extra-index-url URL
125
130
  Both accept -h/--help and --.
126
131
  `;
127
132
  function parsePythonInstallation(pipArgs) {
@@ -143,7 +148,7 @@ function parsePythonInstallation(pipArgs) {
143
148
  packages.push(option);
144
149
  continue;
145
150
  }
146
- const flag = { "--pre": "pre", "--no-cache-dir": "noCache", "-U": "upgrade", "--upgrade": "upgrade", "--force-reinstall": "forceReinstall" }[option];
151
+ const flag = { "--no-index": "noIndex", "--no-deps": "noDeps", "--no-dependencies": "noDeps", "--pre": "pre", "--no-cache-dir": "noCache", "-U": "upgrade", "--upgrade": "upgrade", "--force-reinstall": "forceReinstall" }[option];
147
152
  if (!uninstall && flag) {
148
153
  controls[flag] = true;
149
154
  continue;
@@ -161,12 +166,22 @@ function parsePythonInstallation(pipArgs) {
161
166
  continue;
162
167
  }
163
168
  if (!uninstall) {
164
- const kind = ["requirement", "editable"].find((name) => option.startsWith("-" + name[0]) || option.split("=", 1)[0] === "--" + name);
169
+ const indexOption = option.split("=", 1)[0];
170
+ if (option.startsWith("-i") || indexOption === "--index-url" || indexOption === "--extra-index-url") {
171
+ const value = option.startsWith("-i") && option.length > 2 ? option.slice(2) : option.includes("=") ? option.slice(option.indexOf("=") + 1) : pipArgs[++index];
172
+ if (!value || value.startsWith("-")) throw new PythonInvocationError(option + " requires a URL");
173
+ if (indexOption === "--extra-index-url") controls.extraIndexUrls = [...controls.extraIndexUrls ?? [], value];
174
+ else controls.indexUrl = value;
175
+ continue;
176
+ }
177
+ const kind = ["requirement", "editable", "constraint"].find((name) => option.startsWith("-" + name[0]) || option.split("=", 1)[0] === "--" + name);
165
178
  if (kind) {
166
179
  const prefix = "--" + kind;
167
180
  const path = option.startsWith(prefix + "=") ? option.slice(prefix.length + 1) : option === prefix || option.length === 2 ? pipArgs[++index] : option.slice(2);
168
181
  if (!path || path.startsWith("-")) throw new PythonInvocationError(option + " requires a path");
169
- (kind === "editable" ? controls.editable ??= [] : requirements).push(path);
182
+ if (kind === "constraint") controls.constraintFiles = [...controls.constraintFiles ?? [], path];
183
+ else if (kind === "editable") controls.editable = [...controls.editable ?? [], path];
184
+ else requirements.push(path);
170
185
  continue;
171
186
  }
172
187
  }
@@ -221,7 +236,7 @@ function createPythonLlmPackageManager(options) {
221
236
  return installer.execute({ ...isolated, command: "python", args: ["-m", "pip", ...planned] });
222
237
  };
223
238
  }
224
- var pythonLlmPackageProgram = String.raw`
239
+ var pythonLlmPackageProgram = `
225
240
  import sys
226
241
  import safe_host
227
242
  import llm.cli
@@ -235,6 +250,27 @@ llm.cli.run_module = _safe_package_request
235
250
  llm.cli.cli.main(args=sys.argv[1:], prog_name='llm')
236
251
  `;
237
252
 
253
+ // packages/safe-bash-command-python/src/llm-exit-handlers.ts
254
+ var pythonLlmExitHandlers = /* @__PURE__ */ (() => String.raw`
255
+ except (KeyboardInterrupt, EOFError, Abort) as error:
256
+ echo(("" if isinstance(error, Abort) else "\n") + "Aborted!", err=True)
257
+ send("exit")
258
+ raise SystemExit(1)
259
+ except SystemExit:
260
+ send("exit")
261
+ raise
262
+ `)();
263
+ var pythonLlmLookupErrors = /* @__PURE__ */ (() => String.raw`
264
+ except (EOFError, Abort):
265
+ raise
266
+ except ClickException as error:
267
+ error.show()
268
+ raise SystemExit(error.exit_code)
269
+ except Exception as error:
270
+ send('lookup', message=str(error))
271
+ return
272
+ `)();
273
+
238
274
  // packages/safe-bash-command-python/src/llm-plugin-setup.ts
239
275
  var pythonLlmPluginSetup = /* @__PURE__ */ (() => String.raw`
240
276
  def load_plugins(request):
@@ -252,7 +288,7 @@ def load_plugins(request):
252
288
  `)();
253
289
 
254
290
  // packages/safe-bash-command-python/src/llm-json-loader.ts
255
- import { LlmLoaderLookupError } from "../../safe-bash-command-llm/index.js";
291
+ import { LlmLoaderLookupError, LlmPluginExit } from "../../safe-bash-command-llm/index.js";
256
292
  import { toByteSource as toByteSource2 } from "../../safe-bash-contracts/index.js";
257
293
  function createPythonLlmJsonLoader(options, capabilityName, program, label) {
258
294
  if (!options.createExecutor) throw new TypeError(`Python ${label} loading requires an asynchronous executor`);
@@ -270,7 +306,7 @@ function createPythonLlmJsonLoader(options, capabilityName, program, label) {
270
306
  const { maxBytes, signal } = context;
271
307
  if (maxBytes !== Infinity && (!Number.isSafeInteger(maxBytes) || maxBytes < 0)) throw new RangeError(`Invalid Python ${label} byte limit`);
272
308
  signal.throwIfAborted();
273
- let size = 0, done = false, failure;
309
+ let size = 0, done = false, exited = false, failure;
274
310
  const chunks = [];
275
311
  const invocation = { ...context, command: "python", args: ["-c", program], signal, env: context.env ?? {}, stdin: toByteSource2(""), stdout: context.stdout ?? { async write() {
276
312
  } }, stderr: context.stderr ?? { async write() {
@@ -286,6 +322,11 @@ function createPythonLlmJsonLoader(options, capabilityName, program, label) {
286
322
  done = true;
287
323
  return null;
288
324
  }
325
+ if (message.op === "exit") {
326
+ done = true;
327
+ exited = true;
328
+ return null;
329
+ }
289
330
  if (message.op === "done") {
290
331
  done = true;
291
332
  return null;
@@ -307,6 +348,7 @@ function createPythonLlmJsonLoader(options, capabilityName, program, label) {
307
348
  const result = await command.execute(invocation);
308
349
  signal.throwIfAborted();
309
350
  if (failure) throw failure;
351
+ if (exited) throw new LlmPluginExit(result.exitCode);
310
352
  if (result.exitCode) throw new Error(`Python ${label} interpreter exited with status ${result.exitCode}`);
311
353
  if (!done) throw new Error(`Python ${label} interpreter returned no result`);
312
354
  return JSON.parse(chunks.join(""));
@@ -329,6 +371,7 @@ function createPythonLlmTemplateLoader(options, prefix) {
329
371
  };
330
372
  }
331
373
  var pythonLlmTemplateProgram = /* @__PURE__ */ (() => String.raw`
374
+ from click import Abort, ClickException, echo
332
375
  import json, llm, safe_host
333
376
 
334
377
  ${pythonLlmPluginSetup}
@@ -341,25 +384,27 @@ def main():
341
384
  try:
342
385
  load_plugins(request)
343
386
  loaders = llm.get_template_loaders()
344
- except Exception as error:
345
- send('lookup', message=str(error))
346
- return
387
+ ${pythonLlmLookupErrors}
347
388
  if request['prefix'] not in loaders:
348
389
  send('missing', message='Unknown template prefix: ' + request['prefix'])
349
390
  return
350
- template = loaders[request['prefix']](request['value'])
351
- encoder = json.JSONEncoder(ensure_ascii=False, separators=(',', ':'))
352
- for part in encoder.iterencode(template.model_dump(exclude_none=True)):
353
- for offset in range(0, len(part), 4096): send('text', text=part[offset:offset + 4096])
354
- send('done')
391
+ try:
392
+ template = loaders[request['prefix']](request['value'])
393
+ encoder = json.JSONEncoder(ensure_ascii=False, separators=(',', ':'))
394
+ for part in encoder.iterencode(template.model_dump(exclude_none=True)):
395
+ for offset in range(0, len(part), 4096): send('text', text=part[offset:offset + 4096])
396
+ send('done')
397
+ except Exception as error:
398
+ send('error', message=str(error))
355
399
  try:
356
400
  main()
401
+ ${pythonLlmExitHandlers}
357
402
  except Exception as error:
358
403
  send('error', message=str(error))
359
404
  `)();
360
405
 
361
406
  // packages/safe-bash-command-python/src/llm-fragment-loader.ts
362
- import { createLlmSpool, createLlmUrlSource, LlmLoaderLookupError as LlmLoaderLookupError2 } from "../../safe-bash-command-llm/index.js";
407
+ import { createLlmSpool, createLlmUrlSource, LlmLoaderLookupError as LlmLoaderLookupError2, LlmPluginExit as LlmPluginExit2 } from "../../safe-bash-command-llm/index.js";
363
408
  import { toByteSource as toByteSource3 } from "../../safe-bash-contracts/index.js";
364
409
  function deferred() {
365
410
  let resolve, reject;
@@ -390,7 +435,7 @@ function createPythonLlmFragmentLoader(options, prefix) {
390
435
  const controller = new AbortController(), signal = AbortSignal.any([context.signal, controller.signal]);
391
436
  signal.throwIfAborted();
392
437
  let ready = deferred(), resume;
393
- let current, spool, closed = false, bytes = 0;
438
+ let current, spool, closed = false, exited = false, bytes = 0;
394
439
  const sources = /* @__PURE__ */ new Set();
395
440
  const admit = (size) => {
396
441
  if (size > maxBytes - bytes) throw new RangeError("Python fragment byte limit exceeded");
@@ -418,6 +463,10 @@ function createPythonLlmFragmentLoader(options, prefix) {
418
463
  if (!input || typeof input !== "object" || Array.isArray(input)) throw new TypeError("Invalid Python fragment message");
419
464
  const message = input;
420
465
  if (message.op === "request") return { prefix, value, plugins };
466
+ if (message.op === "exit") {
467
+ exited = true;
468
+ return null;
469
+ }
421
470
  if (message.op === "missing" || message.op === "lookup") throw new LlmLoaderLookupError2(String(message.message));
422
471
  if (message.op === "error") throw new Error(String(message.message));
423
472
  if (message.op === "begin") {
@@ -475,7 +524,8 @@ function createPythonLlmFragmentLoader(options, prefix) {
475
524
  } });
476
525
  const running = Promise.resolve().then(() => command.execute(invocation)).then((result) => {
477
526
  if (closed) return;
478
- if (result.exitCode) fail(new Error(`Python fragment interpreter exited with status ${result.exitCode}`));
527
+ if (exited) fail(new LlmPluginExit2(result.exitCode));
528
+ else if (result.exitCode) fail(new Error(`Python fragment interpreter exited with status ${result.exitCode}`));
479
529
  else ready.resolve(void 0);
480
530
  }, (error) => {
481
531
  if (!closed) fail(error);
@@ -515,6 +565,7 @@ function createPythonLlmFragmentLoader(options, prefix) {
515
565
  };
516
566
  }
517
567
  var pythonLlmFragmentProgram = /* @__PURE__ */ (() => String.raw`
568
+ from click import Abort, ClickException, echo
518
569
  import hashlib, llm, safe_host
519
570
  from llm_safe_host import _attachment_type
520
571
 
@@ -546,23 +597,25 @@ def main():
546
597
  try:
547
598
  load_plugins(request)
548
599
  loaders = llm.get_fragment_loaders()
549
- except Exception as error:
550
- send('lookup', message=str(error))
551
- return
600
+ ${pythonLlmLookupErrors}
552
601
  if request['prefix'] not in loaders:
553
602
  send('missing', message='Unknown fragment prefix: ' + request['prefix'])
554
603
  return
555
- result = loaders[request['prefix']](request['value'])
556
- if not isinstance(result, list): result = [result]
557
- for value in result:
558
- if isinstance(value, llm.Attachment): emit_attachment(value)
559
- elif isinstance(value, str):
560
- send('begin', type='text')
561
- for offset in range(0, len(value), 4096): send('text', text=value[offset:offset + 4096])
562
- else: raise TypeError('Fragment loader must return text or attachments')
563
- if not send('end'): return
604
+ try:
605
+ result = loaders[request['prefix']](request['value'])
606
+ if not isinstance(result, list): result = [result]
607
+ for value in result:
608
+ if isinstance(value, llm.Attachment): emit_attachment(value)
609
+ elif isinstance(value, str):
610
+ send('begin', type='text')
611
+ for offset in range(0, len(value), 4096): send('text', text=value[offset:offset + 4096])
612
+ else: raise TypeError('Fragment loader must return text or attachments')
613
+ if not send('end'): return
614
+ except Exception as error:
615
+ send('error', message=str(error))
564
616
  try:
565
617
  main()
618
+ ${pythonLlmExitHandlers}
566
619
  except Exception as error:
567
620
  send('error', message=str(error))
568
621
  `)();
@@ -595,6 +648,7 @@ function createPythonLlmLoaderDiscovery(options) {
595
648
  };
596
649
  }
597
650
  var pythonLlmLoaderDiscoveryProgram = /* @__PURE__ */ (() => String.raw`
651
+ from click import Abort, ClickException, echo
598
652
  import json, llm, safe_host
599
653
 
600
654
  ${pythonLlmPluginSetup}
@@ -614,199 +668,27 @@ def main():
614
668
  send('done')
615
669
  try:
616
670
  main()
671
+ ${pythonLlmExitHandlers}
672
+ except ClickException as error:
673
+ error.show()
674
+ send('exit')
675
+ raise SystemExit(error.exit_code)
617
676
  except Exception as error:
618
677
  send('error', message=str(error))
619
678
  `)();
620
679
 
621
680
  // packages/safe-bash-command-python/src/llm-functions-loader.ts
622
- import { createLlmSpool as createLlmSpool2, createLlmToolRegistry } from "../../safe-bash-command-llm/index.js";
681
+ import { LlmPluginExit as LlmPluginExit3, createLlmSpool as createLlmSpool2, createLlmToolRegistry } from "../../safe-bash-command-llm/index.js";
623
682
  import { toByteSource as toByteSource4 } from "../../safe-bash-contracts/index.js";
624
683
 
625
- // packages/safe-bash-command-python/src/llm-functions-program.ts
626
- var pythonLlmFunctionsProgram = /* @__PURE__ */ (() => String.raw`
627
- import asyncio, codecs, inspect, json
628
- import safe_host
629
- from _poe_llm_capability import bridge
630
- from llm.cli import _tools_from_code, _gather_tools
631
- from llm import ToolOutput, Tool, Toolbox, get_tools, get_plugins
632
- from llm.models import _wrap_tools, _get_instance
633
- from llm_safe_host import _attachment_type
634
-
635
-
636
- def send(op, **fields):
637
- return safe_host.call("llm_tools", dict(op=op, **fields))
638
-
639
-
640
- def load_definition(definition):
641
- if "\n" in definition or not definition.endswith(".py"):
642
- send("admit", size=len(definition.encode("utf-8")))
643
- return definition
644
- decoder = codecs.getincrementaldecoder("utf-8")()
645
- chunks = []
646
- try:
647
- with open(definition, "rb") as source:
648
- for chunk in iter(lambda: source.read(4096), b""):
649
- send("admit", size=len(chunk))
650
- chunks.append(decoder.decode(chunk))
651
- chunks.append(decoder.decode(b"", final=True))
652
- except FileNotFoundError:
653
- from click import ClickException
654
- raise ClickException("File not found: " + definition)
655
- code = "".join(chunks).replace("\r\n", "\n").replace("\r", "\n")
656
- return code + "\n" if "\n" not in code and code.endswith(".py") else code
657
-
684
+ // packages/safe-bash-command-python/src/llm-functions-program.generated.ts
685
+ var pythonLlmFunctionsProgramGzip = "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";
658
686
 
659
- def write_text(identifier, value):
660
- for offset in range(0, len(value), 4096):
661
- send("text", id=identifier, text=value[offset:offset + 4096])
662
-
663
-
664
- def write_attachment(identifier, attachment):
665
- mime = _attachment_type(attachment)
666
- if attachment.content:
667
- descriptor = dict(mimeType=mime, id=attachment.id())
668
- handle = send("attachment", id=identifier, descriptor=descriptor)
669
- content = memoryview(attachment.content)
670
- for offset in range(0, len(content), 4096):
671
- send("bytes", id=identifier, attachment=handle, bytes=list(content[offset:offset + 4096]))
672
- elif attachment.path:
673
- handle = send("attachment", id=identifier, descriptor=dict(mimeType=mime, id=attachment.id()))
674
- with open(attachment.path, "rb") as source:
675
- for chunk in iter(lambda: source.read(4096), b""):
676
- send("bytes", id=identifier, attachment=handle, bytes=list(chunk))
677
- elif attachment.url:
678
- send("attachment", id=identifier, descriptor=dict(mimeType=mime, id=attachment.id(), url=attachment.url))
679
- else:
680
- send("attachment", id=identifier, descriptor=dict(mimeType=mime, id=attachment.id()))
681
-
682
-
683
- async def main():
684
- definitions = send("definitions")
685
- selection = send("selection")
686
- names = selection.get("names", [])
687
- discovery = selection.get("discovery", False)
688
- tools = []
689
- try:
690
- requested_plugins = selection.get("plugins", [])
691
- if requested_plugins:
692
- import llm.plugins as plugin_manager
693
- plugin_manager.load_plugins()
694
- original = (plugin_manager.DEFAULT_PLUGINS, plugin_manager.LLM_LOAD_PLUGINS, plugin_manager._loaded)
695
- try:
696
- # Reuse native explicit-distribution loading. The host's tooling
697
- # registration guard and ambient-entrypoint prohibition stay active.
698
- plugin_manager.DEFAULT_PLUGINS = ()
699
- plugin_manager.LLM_LOAD_PLUGINS = ",".join(requested_plugins)
700
- plugin_manager._loaded = False
701
- plugin_manager.load_plugins()
702
- finally:
703
- plugin_manager.DEFAULT_PLUGINS, plugin_manager.LLM_LOAD_PLUGINS, plugin_manager._loaded = original
704
- plugin_query = selection.get("pluginQuery")
705
- if plugin_query is not None:
706
- plugins = get_plugins(plugin_query["all"])
707
- hooks = set(plugin_query["hooks"])
708
- if hooks:
709
- plugins = [plugin for plugin in plugins if hooks.intersection(plugin["hooks"])]
710
- send("plugins", plugins=plugins)
711
- registered = get_tools() if discovery and not names else {}
712
- functions = []
713
- for definition in definitions:
714
- functions.extend(_tools_from_code(load_definition(definition)))
715
- if discovery:
716
- if names:
717
- registered = {tool.name: tool for tool in functions + _gather_tools(names, [])}
718
- else:
719
- for tool in functions:
720
- registered[tool.name] = tool
721
- entries = [(key, tool, None) for key, tool in registered.items()]
722
- else:
723
- entries = [(tool.name, tool, None) for tool in functions]
724
- for selection_index, selected in enumerate(_gather_tools(names, [])):
725
- entries.extend((tool.name, tool, selection_index) for tool in _wrap_tools([selected]))
726
- for key, tool, selection_index in entries:
727
- if not isinstance(tool, Tool):
728
- methods = []
729
- for method in tool.method_tools():
730
- methods.append(dict(name=method.name, description=method.description,
731
- inputSchema=method.input_schema,
732
- signature=str(inspect.signature(method.implementation)).replace("(self, ", "(").replace("(self)", "()")))
733
- send("toolbox", name=key, tools=methods)
734
- continue
735
- index = len(tools)
736
- tools.append(tool)
737
- send("register", index=index, name=tool.name, registryKey=key, description=tool.description,
738
- plugin=tool.plugin, selectionIndex=selection_index, inputSchema=tool.input_schema,
739
- signature=str(inspect.signature(tool.implementation)),
740
- asynchronous=inspect.iscoroutinefunction(tool.implementation))
741
- except Exception as error:
742
- send("failed", message=getattr(error, "message", str(error)))
743
- return
744
- send("ready", prepare=any(isinstance(_get_instance(tool.implementation), Toolbox) for tool in tools))
745
- pending = set()
746
- cancelled = False
747
-
748
- async def execute(command):
749
- identifier = command["id"]
750
- try:
751
- if command.get("prepare"):
752
- asynchronous = command.get("asynchronous", False)
753
- flag = "_async_prepared" if asynchronous else "_prepared"
754
- instances = []
755
- for tool in {tool.name: tool for tool in tools}.values():
756
- instance = _get_instance(tool.implementation)
757
- if isinstance(instance, Toolbox) and not getattr(instance, flag, False):
758
- instances.append(instance)
759
- for instance in instances:
760
- if asynchronous:
761
- await instance.prepare_async()
762
- else:
763
- instance.prepare()
764
- setattr(instance, flag, True)
765
- send("done", id=identifier)
766
- return
767
- output = tools[command["tool"]].implementation(**command["arguments"])
768
- if inspect.isawaitable(output):
769
- output = await output
770
- attachments = []
771
- if isinstance(output, ToolOutput):
772
- attachments, output = output.attachments, output.output
773
- if not isinstance(output, str):
774
- output = json.dumps(output, default=repr)
775
- write_text(identifier, output)
776
- for attachment in attachments:
777
- write_attachment(identifier, attachment)
778
- send("done", id=identifier)
779
- except Exception as error:
780
- send("error", id=identifier, message=str(error))
781
-
782
- def completed(task):
783
- pending.discard(task)
784
- # Host transport failures already reject all outstanding calls. Retrieve
785
- # the exception so a completed task cannot leak an unobserved failure.
786
- if not task.cancelled():
787
- task.exception()
788
-
789
- try:
790
- while True:
791
- command = await bridge.wait("begin", capability="llm_tools", value=dict(op="next"))
792
- if command is None:
793
- break
794
- if command.get("cancel"):
795
- cancelled = True
796
- break
797
- task = asyncio.create_task(execute(command))
798
- pending.add(task)
799
- task.add_done_callback(completed)
800
- if pending and not cancelled:
801
- await asyncio.gather(*pending)
802
- finally:
803
- for task in pending:
804
- task.cancel()
805
- if pending:
806
- await asyncio.gather(*pending, return_exceptions=True)
807
-
808
- asyncio.run(main())
809
- `)();
687
+ // packages/safe-bash-command-python/src/llm-functions-program.ts
688
+ var decoded;
689
+ function loadPythonLlmFunctionsProgram() {
690
+ return decoded ??= new Response(new Blob([Uint8Array.from(atob(pythonLlmFunctionsProgramGzip), (character) => character.charCodeAt(0))]).stream().pipeThrough(new DecompressionStream("gzip"))).text();
691
+ }
810
692
 
811
693
  // packages/safe-bash-command-python/src/llm-functions-loader.ts
812
694
  function deferred2() {
@@ -839,6 +721,8 @@ function createPythonLlmToolLoader(options) {
839
721
  if (pluginQuery && (typeof pluginQuery.all !== "boolean" || !Array.isArray(pluginQuery.hooks) || pluginQuery.hooks.some((value) => typeof value !== "string"))) throw new TypeError("Invalid Python plugin query");
840
722
  for (const limit of [maxInputBytes, maxOutputBytes]) if (limit !== Infinity && (!Number.isSafeInteger(limit) || limit < 0)) throw new RangeError("Invalid Python tool byte limit");
841
723
  context.signal.throwIfAborted();
724
+ const program = await loadPythonLlmFunctionsProgram();
725
+ context.signal.throwIfAborted();
842
726
  const controller = new AbortController();
843
727
  const runtimeController = new AbortController();
844
728
  const signal = AbortSignal.any([context.signal, controller.signal]);
@@ -850,7 +734,7 @@ function createPythonLlmToolLoader(options) {
850
734
  const jobs = /* @__PURE__ */ new Map();
851
735
  const queue = [];
852
736
  let waiter;
853
- let serial3 = 0, controls = 0, loaded = false, initializationFailed = false, closed = false, closing;
737
+ let serial3 = 0, controls = 0, loaded = false, exited = false, initializationFailed = false, closed = false, closing;
854
738
  const encoder2 = new TextEncoder();
855
739
  const fail = (error) => {
856
740
  ready.reject(error);
@@ -930,6 +814,11 @@ function createPythonLlmToolLoader(options) {
930
814
  }
931
815
  return null;
932
816
  }
817
+ if (message.op === "exit") {
818
+ exited = true;
819
+ waiter?.resolve(null);
820
+ return null;
821
+ }
933
822
  if (message.op === "failed") {
934
823
  initializationFailed = true;
935
824
  fail(new Error(String(message.message)));
@@ -1059,11 +948,11 @@ function createPythonLlmToolLoader(options) {
1059
948
  }
1060
949
  } };
1061
950
  const { registerCleanup: ignoredParentCleanup, ...isolatedContext } = context;
1062
- const invocation = { ...isolatedContext, signal: runtimeController.signal, command: "python", args: ["-c", pythonLlmFunctionsProgram], stdin: toByteSource4("") };
951
+ const invocation = { ...isolatedContext, signal: runtimeController.signal, command: "python", args: ["-c", program], stdin: toByteSource4("") };
1063
952
  capabilitiesByArguments.set(invocation.args, capability);
1064
953
  const running = Promise.resolve().then(() => command.execute(invocation)).then(
1065
954
  (result) => {
1066
- if (!closed) fail(new Error(`Python tool interpreter exited with status ${result.exitCode}`));
955
+ if (!closed) fail(exited ? new LlmPluginExit3(result.exitCode) : new Error(`Python tool interpreter exited with status ${result.exitCode}`));
1067
956
  },
1068
957
  (error) => {
1069
958
  if (!closed) fail(error);
@@ -1103,13 +992,19 @@ function createPythonLlmToolLoader(options) {
1103
992
  function createPythonBuildEnvironment(options = {}) {
1104
993
  const manifestStore = createPythonPackageManifestStore({ maxEntries: 1, ...options.maxManifestBytes === void 0 ? {} : { maxBytes: options.maxManifestBytes } });
1105
994
  const isolated = { ...options, manifestStore, scope: "build" };
995
+ delete isolated.noDeps;
996
+ delete isolated.constraints;
997
+ delete isolated.constraintFiles;
1106
998
  delete isolated.editable;
1107
999
  delete isolated.requirements;
1108
1000
  delete isolated.requirementFiles;
1109
1001
  delete isolated.profile;
1110
1002
  const environment = createPythonPackageEnvironment(isolated);
1111
1003
  let disposing;
1112
- return { ...environment, dispose() {
1004
+ return { ...environment, prepare(context) {
1005
+ const { noDeps: ignoredNoDeps, constraints: ignoredConstraints, constraintFiles: ignoredFiles, ...input } = context;
1006
+ return environment.prepare(input);
1007
+ }, dispose() {
1113
1008
  return disposing ??= environment.dispose().finally(() => manifestStore.dispose());
1114
1009
  } };
1115
1010
  }
@@ -1117,49 +1012,8 @@ function createPythonBuildEnvironment(options = {}) {
1117
1012
  // packages/safe-bash-command-python/src/build-dependencies.ts
1118
1013
  import { toByteSource as toByteSource6 } from "../../safe-bash-contracts/index.js";
1119
1014
 
1120
- // packages/safe-bash-command-python/src/source-origin-program.generated.ts
1121
- var pythonSourceOriginProgram = "def read_source_origin(request):\n import re, json\n from urllib.parse import urlsplit, urlunsplit\n source = request['source']\n if source.startswith('/'):\n from pathlib import Path\n source = Path(source).as_uri()\n url = urlsplit(source)\n netloc = url.netloc\n if '@' in netloc:\n credentials, host = netloc.split('@', 1)\n if not re.match(r'^\\$\\{[A-Za-z0-9-_]+\\}(:\\$\\{[A-Za-z0-9-_]+\\})?$', credentials): netloc = host\n result = {'url': urlunsplit((url.scheme, netloc, url.path, url.query, ''))}\n subdirectory = re.search(r'[#&]subdirectory=([^&]*)', source)\n if subdirectory: result['subdirectory'] = subdirectory.group(1)\n info = {}\n if not request['directory']:\n hashed = re.search(r'(sha1|sha224|sha384|sha256|sha512|md5)=([a-f0-9]+)', source)\n if hashed: info['hash'] = hashed.group(1) + '=' + hashed.group(2)\n result['dir_info' if request['directory'] else 'archive_info'] = info\n return json.dumps(result, sort_keys=True)\n";
1122
-
1123
- // packages/safe-bash-command-python/src/source-filename-program.ts
1124
- var pythonDownloadFilenameProgram = /* @__PURE__ */ (() => String.raw`
1125
- MIME_PREFERENCES = {"application/andrew-inset":".ez","application/applixware":".aw","application/atom+xml":".atom","application/atomcat+xml":".atomcat","application/atomsvc+xml":".atomsvc","application/ccxml+xml":".ccxml","application/cdmi-capability":".cdmia","application/cdmi-container":".cdmic","application/cdmi-domain":".cdmid","application/cdmi-object":".cdmio","application/cdmi-queue":".cdmiq","application/cu-seeme":".cu","application/davmount+xml":".davmount","application/docbook+xml":".dbk","application/dssc+der":".dssc","application/dssc+xml":".xdssc","application/ecmascript":".ecma","application/emma+xml":".emma","application/epub+zip":".epub","application/exi":".exi","application/font-tdpfr":".pfr","application/gml+xml":".gml","application/gpx+xml":".gpx","application/gxf":".gxf","application/hyperstudio":".stk","application/inkml+xml":".ink","application/ipfix":".ipfix","application/java-archive":".jar","application/java-serialized-object":".ser","application/java-vm":".class","application/json":".json","application/jsonml+json":".jsonml","application/lost+xml":".lostxml","application/mac-binhex40":".hqx","application/mac-compactpro":".cpt","application/mads+xml":".mads","application/manifest+json":".webmanifest","application/marc":".mrc","application/marcxml+xml":".mrcx","application/mathematica":".ma","application/mathml+xml":".mathml","application/mbox":".mbox","application/mediaservercontrol+xml":".mscml","application/metalink+xml":".metalink","application/metalink4+xml":".meta4","application/mets+xml":".mets","application/mods+xml":".mods","application/mp21":".m21","application/mp4":".mp4s","application/msword":".doc","application/mxf":".mxf","application/octet-stream":".bin","application/oda":".oda","application/oebps-package+xml":".opf","application/ogg":".ogx","application/omdoc+xml":".omdoc","application/onenote":".onetoc","application/oxps":".oxps","application/patch-ops-error+xml":".xer","application/pdf":".pdf","application/pgp-encrypted":".pgp","application/pgp-signature":".asc","application/pics-rules":".prf","application/pkcs10":".p10","application/pkcs7-mime":".p7c","application/pkcs7-signature":".p7s","application/pkcs8":".p8","application/pkix-attr-cert":".ac","application/pkix-cert":".cer","application/pkix-crl":".crl","application/pkix-pkipath":".pkipath","application/pkixcmp":".pki","application/pls+xml":".pls","application/postscript":".ps","application/prs.cww":".cww","application/pskc+xml":".pskcxml","application/rdf+xml":".rdf","application/reginfo+xml":".rif","application/relax-ng-compact-syntax":".rnc","application/resource-lists+xml":".rl","application/resource-lists-diff+xml":".rld","application/rls-services+xml":".rs","application/rpki-ghostbusters":".gbr","application/rpki-manifest":".mft","application/rpki-roa":".roa","application/rsd+xml":".rsd","application/rss+xml":".rss","application/rtf":".rtf","application/sbml+xml":".sbml","application/scvp-cv-request":".scq","application/scvp-cv-response":".scs","application/scvp-vp-request":".spq","application/scvp-vp-response":".spp","application/sdp":".sdp","application/set-payment-initiation":".setpay","application/set-registration-initiation":".setreg","application/shf+xml":".shf","application/smil+xml":".smi","application/sparql-query":".rq","application/sparql-results+xml":".srx","application/srgs":".gram","application/srgs+xml":".grxml","application/sru+xml":".sru","application/ssdl+xml":".ssdl","application/ssml+xml":".ssml","application/tei+xml":".tei","application/thraud+xml":".tfi","application/timestamped-data":".tsd","application/vnd.3gpp.pic-bw-large":".plb","application/vnd.3gpp.pic-bw-small":".psb","application/vnd.3gpp.pic-bw-var":".pvb","application/vnd.3gpp2.tcap":".tcap","application/vnd.3m.post-it-notes":".pwn","application/vnd.accpac.simply.aso":".aso","application/vnd.accpac.simply.imp":".imp","application/vnd.acucobol":".acu","application/vnd.acucorp":".atc","application/vnd.adobe.air-application-installer-package+zip":".air","application/vnd.adobe.formscentral.fcdt":".fcdt","application/vnd.adobe.fxp":".fxp","application/vnd.adobe.xdp+xml":".xdp","application/vnd.adobe.xfdf":".xfdf","application/vnd.ahead.space":".ahead","application/vnd.airzip.filesecure.azf":".azf","application/vnd.airzip.filesecure.azs":".azs","application/vnd.amazon.ebook":".azw","application/vnd.americandynamics.acc":".acc","application/vnd.amiga.ami":".ami","application/vnd.android.package-archive":".apk","application/vnd.anser-web-certificate-issue-initiation":".cii","application/vnd.anser-web-funds-transfer-initiation":".fti","application/vnd.antix.game-component":".atx","application/vnd.apple.installer+xml":".mpkg","application/vnd.aristanetworks.swi":".swi","application/vnd.astraea-software.iota":".iota","application/vnd.audiograph":".aep","application/vnd.blueice.multipass":".mpm","application/vnd.bmi":".bmi","application/vnd.businessobjects":".rep","application/vnd.chemdraw+xml":".cdxml","application/vnd.chipnuts.karaoke-mmd":".mmd","application/vnd.cinderella":".cdy","application/vnd.claymore":".cla","application/vnd.cloanto.rp9":".rp9","application/vnd.clonk.c4group":".c4g","application/vnd.cluetrust.cartomobile-config":".c11amc","application/vnd.cluetrust.cartomobile-config-pkg":".c11amz","application/vnd.commonspace":".csp","application/vnd.contact.cmsg":".cdbcmsg","application/vnd.cosmocaller":".cmc","application/vnd.crick.clicker":".clkx","application/vnd.crick.clicker.keyboard":".clkk","application/vnd.crick.clicker.palette":".clkp","application/vnd.crick.clicker.template":".clkt","application/vnd.crick.clicker.wordbank":".clkw","application/vnd.criticaltools.wbs+xml":".wbs","application/vnd.ctc-posml":".pml","application/vnd.cups-ppd":".ppd","application/vnd.curl.car":".car","application/vnd.curl.pcurl":".pcurl","application/vnd.dart":".dart","application/vnd.data-vision.rdz":".rdz","application/vnd.dece.data":".uvf","application/vnd.dece.ttml+xml":".uvt","application/vnd.dece.unspecified":".uvx","application/vnd.dece.zip":".uvz","application/vnd.denovo.fcselayout-link":".fe_launch","application/vnd.dna":".dna","application/vnd.dolby.mlp":".mlp","application/vnd.dpgraph":".dpg","application/vnd.dreamfactory":".dfac","application/vnd.ds-keypoint":".kpxx","application/vnd.dvb.ait":".ait","application/vnd.dvb.service":".svc","application/vnd.dynageo":".geo","application/vnd.ecowin.chart":".mag","application/vnd.enliven":".nml","application/vnd.epson.esf":".esf","application/vnd.epson.msf":".msf","application/vnd.epson.quickanime":".qam","application/vnd.epson.salt":".slt","application/vnd.epson.ssf":".ssf","application/vnd.eszigno3+xml":".es3","application/vnd.ezpix-album":".ez2","application/vnd.ezpix-package":".ez3","application/vnd.fdf":".fdf","application/vnd.fdsn.mseed":".mseed","application/vnd.fdsn.seed":".seed","application/vnd.flographit":".gph","application/vnd.fluxtime.clip":".ftc","application/vnd.framemaker":".fm","application/vnd.frogans.fnc":".fnc","application/vnd.frogans.ltf":".ltf","application/vnd.fsc.weblaunch":".fsc","application/vnd.fujitsu.oasys":".oas","application/vnd.fujitsu.oasys2":".oa2","application/vnd.fujitsu.oasys3":".oa3","application/vnd.fujitsu.oasysgp":".fg5","application/vnd.fujitsu.oasysprs":".bh2","application/vnd.fujixerox.ddd":".ddd","application/vnd.fujixerox.docuworks":".xdw","application/vnd.fujixerox.docuworks.binder":".xbd","application/vnd.fuzzysheet":".fzs","application/vnd.genomatix.tuxedo":".txd","application/vnd.geogebra.file":".ggb","application/vnd.geogebra.slides":".ggs","application/vnd.geogebra.tool":".ggt","application/vnd.geometry-explorer":".gex","application/vnd.geonext":".gxt","application/vnd.geoplan":".g2w","application/vnd.geospace":".g3w","application/vnd.gmx":".gmx","application/vnd.google-earth.kml+xml":".kml","application/vnd.google-earth.kmz":".kmz","application/vnd.grafeq":".gqf","application/vnd.groove-account":".gac","application/vnd.groove-help":".ghf","application/vnd.groove-identity-message":".gim","application/vnd.groove-injector":".grv","application/vnd.groove-tool-message":".gtm","application/vnd.groove-tool-template":".tpl","application/vnd.groove-vcard":".vcg","application/vnd.hal+xml":".hal","application/vnd.handheld-entertainment+xml":".zmm","application/vnd.hbci":".hbci","application/vnd.hhe.lesson-player":".les","application/vnd.hp-hpgl":".hpgl","application/vnd.hp-hpid":".hpid","application/vnd.hp-hps":".hps","application/vnd.hp-jlyt":".jlt","application/vnd.hp-pcl":".pcl","application/vnd.hp-pclxl":".pclxl","application/vnd.hydrostatix.sof-data":".sfd-hdstx","application/vnd.ibm.minipay":".mpy","application/vnd.ibm.modcap":".afp","application/vnd.ibm.rights-management":".irm","application/vnd.ibm.secure-container":".sc","application/vnd.iccprofile":".icc","application/vnd.igloader":".igl","application/vnd.immervision-ivp":".ivp","application/vnd.immervision-ivu":".ivu","application/vnd.insors.igm":".igm","application/vnd.intercon.formnet":".xpw","application/vnd.intergeo":".i2g","application/vnd.intu.qbo":".qbo","application/vnd.intu.qfx":".qfx","application/vnd.ipunplugged.rcprofile":".rcprofile","application/vnd.irepository.package+xml":".irp","application/vnd.is-xpr":".xpr","application/vnd.isac.fcs":".fcs","application/vnd.jam":".jam","application/vnd.jcp.javame.midlet-rms":".rms","application/vnd.jisp":".jisp","application/vnd.joost.joda-archive":".joda","application/vnd.kahootz":".ktz","application/vnd.kde.karbon":".karbon","application/vnd.kde.kchart":".chrt","application/vnd.kde.kformula":".kfo","application/vnd.kde.kivio":".flw","application/vnd.kde.kontour":".kon","application/vnd.kde.kpresenter":".kpr","application/vnd.kde.kspread":".ksp","application/vnd.kde.kword":".kwd","application/vnd.kenameaapp":".htke","application/vnd.kidspiration":".kia","application/vnd.kinar":".kne","application/vnd.koan":".skp","application/vnd.kodak-descriptor":".sse","application/vnd.las.las+xml":".lasxml","application/vnd.llamagraphics.life-balance.desktop":".lbd","application/vnd.llamagraphics.life-balance.exchange+xml":".lbe","application/vnd.lotus-1-2-3":".123","application/vnd.lotus-approach":".apr","application/vnd.lotus-freelance":".pre","application/vnd.lotus-notes":".nsf","application/vnd.lotus-organizer":".org","application/vnd.lotus-screencam":".scm","application/vnd.lotus-wordpro":".lwp","application/vnd.macports.portpkg":".portpkg","application/vnd.mcd":".mcd","application/vnd.medcalcdata":".mc1","application/vnd.mediastation.cdkey":".cdkey","application/vnd.mfer":".mwf","application/vnd.mfmp":".mfm","application/vnd.micrografx.flo":".flo","application/vnd.micrografx.igx":".igx","application/vnd.mif":".mif","application/vnd.mobius.daf":".daf","application/vnd.mobius.dis":".dis","application/vnd.mobius.mbk":".mbk","application/vnd.mobius.mqy":".mqy","application/vnd.mobius.msl":".msl","application/vnd.mobius.plc":".plc","application/vnd.mobius.txf":".txf","application/vnd.mophun.application":".mpn","application/vnd.mophun.certificate":".mpc","application/vnd.mozilla.xul+xml":".xul","application/vnd.ms-artgalry":".cil","application/vnd.ms-cab-compressed":".cab","application/vnd.ms-excel":".xls","application/vnd.ms-excel.addin.macroenabled.12":".xlam","application/vnd.ms-excel.sheet.binary.macroenabled.12":".xlsb","application/vnd.ms-excel.sheet.macroenabled.12":".xlsm","application/vnd.ms-excel.template.macroenabled.12":".xltm","application/vnd.ms-fontobject":".eot","application/vnd.ms-htmlhelp":".chm","application/vnd.ms-ims":".ims","application/vnd.ms-lrm":".lrm","application/vnd.ms-officetheme":".thmx","application/vnd.ms-pki.seccat":".cat","application/vnd.ms-pki.stl":".stl","application/vnd.ms-powerpoint":".ppt","application/vnd.ms-powerpoint.addin.macroenabled.12":".ppam","application/vnd.ms-powerpoint.presentation.macroenabled.12":".pptm","application/vnd.ms-powerpoint.slide.macroenabled.12":".sldm","application/vnd.ms-powerpoint.slideshow.macroenabled.12":".ppsm","application/vnd.ms-powerpoint.template.macroenabled.12":".potm","application/vnd.ms-project":".mpp","application/vnd.ms-word.document.macroenabled.12":".docm","application/vnd.ms-word.template.macroenabled.12":".dotm","application/vnd.ms-works":".wps","application/vnd.ms-wpl":".wpl","application/vnd.ms-xpsdocument":".xps","application/vnd.mseq":".mseq","application/vnd.musician":".mus","application/vnd.muvee.style":".msty","application/vnd.mynfc":".taglet","application/vnd.neurolanguage.nlu":".nlu","application/vnd.nitf":".ntf","application/vnd.noblenet-directory":".nnd","application/vnd.noblenet-sealer":".nns","application/vnd.noblenet-web":".nnw","application/vnd.nokia.n-gage.data":".ngdat","application/vnd.nokia.n-gage.symbian.install":".n-gage","application/vnd.nokia.radio-preset":".rpst","application/vnd.nokia.radio-presets":".rpss","application/vnd.novadigm.edm":".edm","application/vnd.novadigm.edx":".edx","application/vnd.novadigm.ext":".ext","application/vnd.oasis.opendocument.chart":".odc","application/vnd.oasis.opendocument.chart-template":".otc","application/vnd.oasis.opendocument.database":".odb","application/vnd.oasis.opendocument.formula":".odf","application/vnd.oasis.opendocument.formula-template":".odft","application/vnd.oasis.opendocument.graphics":".odg","application/vnd.oasis.opendocument.graphics-template":".otg","application/vnd.oasis.opendocument.image":".odi","application/vnd.oasis.opendocument.image-template":".oti","application/vnd.oasis.opendocument.presentation":".odp","application/vnd.oasis.opendocument.presentation-template":".otp","application/vnd.oasis.opendocument.spreadsheet":".ods","application/vnd.oasis.opendocument.spreadsheet-template":".ots","application/vnd.oasis.opendocument.text":".odt","application/vnd.oasis.opendocument.text-master":".odm","application/vnd.oasis.opendocument.text-template":".ott","application/vnd.oasis.opendocument.text-web":".oth","application/vnd.olpc-sugar":".xo","application/vnd.oma.dd2+xml":".dd2","application/vnd.openofficeorg.extension":".oxt","application/vnd.openxmlformats-officedocument.presentationml.presentation":".pptx","application/vnd.openxmlformats-officedocument.presentationml.slide":".sldx","application/vnd.openxmlformats-officedocument.presentationml.slideshow":".ppsx","application/vnd.openxmlformats-officedocument.presentationml.template":".potx","application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":".xlsx","application/vnd.openxmlformats-officedocument.spreadsheetml.template":".xltx","application/vnd.openxmlformats-officedocument.wordprocessingml.document":".docx","application/vnd.openxmlformats-officedocument.wordprocessingml.template":".dotx","application/vnd.osgeo.mapguide.package":".mgp","application/vnd.osgi.dp":".dp","application/vnd.osgi.subsystem":".esa","application/vnd.palm":".pdb","application/vnd.pawaafile":".paw","application/vnd.pg.format":".str","application/vnd.pg.osasli":".ei6","application/vnd.picsel":".efif","application/vnd.pmi.widget":".wg","application/vnd.pocketlearn":".plf","application/vnd.powerbuilder6":".pbd","application/vnd.previewsystems.box":".box","application/vnd.proteus.magazine":".mgz","application/vnd.publishare-delta-tree":".qps","application/vnd.pvi.ptid1":".ptid","application/vnd.quark.quarkxpress":".qxd","application/vnd.realvnc.bed":".bed","application/vnd.recordare.musicxml":".mxl","application/vnd.recordare.musicxml+xml":".musicxml","application/vnd.rig.cryptonote":".cryptonote","application/vnd.rim.cod":".cod","application/vnd.rn-realmedia":".rm","application/vnd.rn-realmedia-vbr":".rmvb","application/vnd.route66.link66+xml":".link66","application/vnd.sailingtracker.track":".st","application/vnd.seemail":".see","application/vnd.sema":".sema","application/vnd.semd":".semd","application/vnd.semf":".semf","application/vnd.shana.informed.formdata":".ifm","application/vnd.shana.informed.formtemplate":".itp","application/vnd.shana.informed.interchange":".iif","application/vnd.shana.informed.package":".ipk","application/vnd.simtech-mindmapper":".twd","application/vnd.smaf":".mmf","application/vnd.smart.teacher":".teacher","application/vnd.solent.sdkm+xml":".sdkm","application/vnd.spotfire.dxp":".dxp","application/vnd.spotfire.sfs":".sfs","application/vnd.stardivision.calc":".sdc","application/vnd.stardivision.draw":".sda","application/vnd.stardivision.impress":".sdd","application/vnd.stardivision.math":".smf","application/vnd.stardivision.writer":".sdw","application/vnd.stardivision.writer-global":".sgl","application/vnd.stepmania.package":".smzip","application/vnd.stepmania.stepchart":".sm","application/vnd.sun.xml.calc":".sxc","application/vnd.sun.xml.calc.template":".stc","application/vnd.sun.xml.draw":".sxd","application/vnd.sun.xml.draw.template":".std","application/vnd.sun.xml.impress":".sxi","application/vnd.sun.xml.impress.template":".sti","application/vnd.sun.xml.math":".sxm","application/vnd.sun.xml.writer":".sxw","application/vnd.sun.xml.writer.global":".sxg","application/vnd.sun.xml.writer.template":".stw","application/vnd.sus-calendar":".sus","application/vnd.svd":".svd","application/vnd.symbian.install":".sis","application/vnd.syncml+xml":".xsm","application/vnd.syncml.dm+wbxml":".bdm","application/vnd.syncml.dm+xml":".xdm","application/vnd.tao.intent-module-archive":".tao","application/vnd.tcpdump.pcap":".pcap","application/vnd.tmobile-livetv":".tmo","application/vnd.trid.tpt":".tpt","application/vnd.triscape.mxs":".mxs","application/vnd.trueapp":".tra","application/vnd.ufdl":".ufd","application/vnd.uiq.theme":".utz","application/vnd.umajin":".umj","application/vnd.unity":".unityweb","application/vnd.uoml+xml":".uoml","application/vnd.vcx":".vcx","application/vnd.visio":".vsd","application/vnd.visionary":".vis","application/vnd.vsf":".vsf","application/vnd.wap.wbxml":".wbxml","application/vnd.wap.wmlc":".wmlc","application/vnd.wap.wmlscriptc":".wmlsc","application/vnd.webturbo":".wtb","application/vnd.wolfram.player":".nbp","application/vnd.wordperfect":".wpd","application/vnd.wqd":".wqd","application/vnd.wt.stf":".stf","application/vnd.xara":".xar","application/vnd.xfdl":".xfdl","application/vnd.yamaha.hv-dic":".hvd","application/vnd.yamaha.hv-script":".hvs","application/vnd.yamaha.hv-voice":".hvp","application/vnd.yamaha.openscoreformat":".osf","application/vnd.yamaha.openscoreformat.osfpvg+xml":".osfpvg","application/vnd.yamaha.smaf-audio":".saf","application/vnd.yamaha.smaf-phrase":".spf","application/vnd.yellowriver-custom-menu":".cmp","application/vnd.zul":".zir","application/vnd.zzazz.deck+xml":".zaz","application/voicexml+xml":".vxml","application/wasm":".wasm","application/widget":".wgt","application/winhlp":".hlp","application/wsdl+xml":".wsdl","application/wspolicy+xml":".wspolicy","application/x-7z-compressed":".7z","application/x-abiword":".abw","application/x-ace-compressed":".ace","application/x-apple-diskimage":".dmg","application/x-authorware-bin":".aab","application/x-authorware-map":".aam","application/x-authorware-seg":".aas","application/x-bcpio":".bcpio","application/x-bittorrent":".torrent","application/x-blorb":".blb","application/x-bzip":".bz","application/x-bzip2":".bz2","application/x-cbr":".cbr","application/x-cdlink":".vcd","application/x-cfs-compressed":".cfs","application/x-chat":".chat","application/x-chess-pgn":".pgn","application/x-conference":".nsc","application/x-cpio":".cpio","application/x-csh":".csh","application/x-debian-package":".deb","application/x-dgc-compressed":".dgc","application/x-director":".dir","application/x-doom":".wad","application/x-dtbncx+xml":".ncx","application/x-dtbook+xml":".dtb","application/x-dtbresource+xml":".res","application/x-dvi":".dvi","application/x-envoy":".evy","application/x-eva":".eva","application/x-font-bdf":".bdf","application/x-font-ghostscript":".gsf","application/x-font-linux-psf":".psf","application/x-font-pcf":".pcf","application/x-font-snf":".snf","application/x-font-type1":".pfa","application/x-freearc":".arc","application/x-futuresplash":".spl","application/x-gca-compressed":".gca","application/x-glulx":".ulx","application/x-gnumeric":".gnumeric","application/x-gramps-xml":".gramps","application/x-gtar":".gtar","application/x-hdf":".hdf","application/x-install-instructions":".install","application/x-iso9660-image":".iso","application/x-java-jnlp-file":".jnlp","application/x-latex":".latex","application/x-lzh-compressed":".lzh","application/x-mie":".mie","application/x-mobipocket-ebook":".prc","application/x-mpegurl":".m3u8","application/x-ms-application":".application","application/x-ms-shortcut":".lnk","application/x-ms-wmd":".wmd","application/x-ms-xbap":".xbap","application/x-msaccess":".mdb","application/x-msbinder":".obd","application/x-mscardfile":".crd","application/x-msclip":".clp","application/x-msdownload":".exe","application/x-msmediaview":".mvb","application/x-msmetafile":".wmf","application/x-msmoney":".mny","application/x-mspublisher":".pub","application/x-msschedule":".scd","application/x-msterminal":".trm","application/x-mswrite":".wri","application/x-netcdf":".cdf","application/x-nzb":".nzb","application/x-pkcs12":".p12","application/x-pkcs7-certificates":".p7b","application/x-pkcs7-certreqresp":".p7r","application/x-python-code":".pyc","application/x-rar-compressed":".rar","application/x-research-info-systems":".ris","application/x-sh":".sh","application/x-shar":".shar","application/x-shockwave-flash":".swf","application/x-silverlight-app":".xap","application/x-sql":".sql","application/x-stuffit":".sit","application/x-stuffitx":".sitx","application/x-subrip":".srt","application/x-sv4cpio":".sv4cpio","application/x-sv4crc":".sv4crc","application/x-t3vm-image":".t3","application/x-tads":".gam","application/x-tar":".tar","application/x-tcl":".tcl","application/x-tex":".tex","application/x-tex-tfm":".tfm","application/x-texinfo":".texi","application/x-tgif":".obj","application/x-ustar":".ustar","application/x-wais-source":".src","application/x-x509-ca-cert":".der","application/x-xfig":".fig","application/x-xliff+xml":".xlf","application/x-xpinstall":".xpi","application/x-xz":".xz","application/x-zmachine":".z1","application/xaml+xml":".xaml","application/xcap-diff+xml":".xdf","application/xenc+xml":".xenc","application/xhtml+xml":".xhtml","application/xml":".xsl","application/xml-dtd":".dtd","application/xop+xml":".xop","application/xproc+xml":".xpl","application/xslt+xml":".xslt","application/xspf+xml":".xspf","application/xv+xml":".mxml","application/yang":".yang","application/yin+xml":".yin","application/zip":".zip","audio/adpcm":".adp","audio/basic":".au","audio/midi":".mid","audio/mp4":".m4a","audio/mp4a-latm":".m4a","audio/mpeg":".mp3","audio/ogg":".oga","audio/s3m":".s3m","audio/silk":".sil","audio/vnd.dece.audio":".uva","audio/vnd.digital-winds":".eol","audio/vnd.dra":".dra","audio/vnd.dts":".dts","audio/vnd.dts.hd":".dtshd","audio/vnd.lucent.voice":".lvp","audio/vnd.ms-playready.media.pya":".pya","audio/vnd.nuera.ecelp4800":".ecelp4800","audio/vnd.nuera.ecelp7470":".ecelp7470","audio/vnd.nuera.ecelp9600":".ecelp9600","audio/vnd.rip":".rip","audio/webm":".weba","audio/x-aac":".aac","audio/x-aiff":".aif","audio/x-caf":".caf","audio/x-flac":".flac","audio/x-matroska":".mka","audio/x-mpegurl":".m3u","audio/x-ms-wax":".wax","audio/x-ms-wma":".wma","audio/x-pn-realaudio":".ra","audio/x-pn-realaudio-plugin":".rmp","audio/x-wav":".wav","audio/xm":".xm","chemical/x-cdx":".cdx","chemical/x-cif":".cif","chemical/x-cmdf":".cmdf","chemical/x-cml":".cml","chemical/x-csml":".csml","chemical/x-xyz":".xyz","font/collection":".ttc","font/otf":".otf","font/ttf":".ttf","font/woff":".woff","font/woff2":".woff2","image/avif":".avif","image/bmp":".bmp","image/cgm":".cgm","image/g3fax":".g3","image/gif":".gif","image/ief":".ief","image/jp2":".jp2","image/jpeg":".jpg","image/jxl":".jxl","image/ktx":".ktx","image/pict":".pict","image/png":".png","image/prs.btif":".btif","image/sgi":".sgi","image/svg+xml":".svg","image/tiff":".tiff","image/vnd.adobe.photoshop":".psd","image/vnd.dece.graphic":".uvi","image/vnd.djvu":".djvu","image/vnd.dwg":".dwg","image/vnd.dxf":".dxf","image/vnd.fastbidsheet":".fbs","image/vnd.fpx":".fpx","image/vnd.fst":".fst","image/vnd.fujixerox.edmics-mmr":".mmr","image/vnd.fujixerox.edmics-rlc":".rlc","image/vnd.ms-modi":".mdi","image/vnd.ms-photo":".wdp","image/vnd.net-fpx":".npx","image/vnd.wap.wbmp":".wbmp","image/vnd.xiff":".xif","image/webp":".webp","image/x-3ds":".3ds","image/x-cmu-raster":".ras","image/x-cmx":".cmx","image/x-freehand":".fh","image/x-icon":".ico","image/x-macpaint":".pntg","image/x-mrsid-image":".sid","image/x-pcx":".pcx","image/x-pict":".pic","image/x-portable-anymap":".pnm","image/x-portable-bitmap":".pbm","image/x-portable-graymap":".pgm","image/x-portable-pixmap":".ppm","image/x-quicktime":".qtif","image/x-rgb":".rgb","image/x-tga":".tga","image/x-xbitmap":".xbm","image/x-xpixmap":".xpm","image/x-xwindowdump":".xwd","message/rfc822":".eml","model/iges":".igs","model/mesh":".msh","model/vnd.collada+xml":".dae","model/vnd.dwf":".dwf","model/vnd.gdl":".gdl","model/vnd.gtw":".gtw","model/vnd.vtu":".vtu","model/vrml":".wrl","model/x3d+binary":".x3db","model/x3d+vrml":".x3dv","model/x3d+xml":".x3d","text/cache-manifest":".manifest","text/calendar":".ics","text/css":".css","text/csv":".csv","text/html":".html","text/javascript":".js","text/n3":".n3","text/plain":".txt","text/prs.lines.tag":".dsc","text/richtext":".rtx","text/sgml":".sgml","text/tab-separated-values":".tsv","text/troff":".t","text/turtle":".ttl","text/uri-list":".uri","text/vcard":".vcard","text/vnd.curl":".curl","text/vnd.curl.dcurl":".dcurl","text/vnd.curl.mcurl":".mcurl","text/vnd.curl.scurl":".scurl","text/vnd.dvb.subtitle":".sub","text/vnd.fly":".fly","text/vnd.fmi.flexstor":".flx","text/vnd.graphviz":".gv","text/vnd.in3d.3dml":".3dml","text/vnd.in3d.spot":".spot","text/vnd.sun.j2me.app-descriptor":".jad","text/vnd.wap.wml":".wml","text/vnd.wap.wmlscript":".wmls","text/x-asm":".s","text/x-c":".c","text/x-fortran":".f","text/x-java-source":".java","text/x-nfo":".nfo","text/x-opml":".opml","text/x-pascal":".p","text/x-python":".py","text/x-setext":".etx","text/x-sfv":".sfv","text/x-uuencode":".uu","text/x-vcalendar":".vcs","text/x-vcard":".vcf","video/3gpp":".3gp","video/3gpp2":".3g2","video/h261":".h261","video/h263":".h263","video/h264":".h264","video/jpeg":".jpgv","video/jpm":".jpm","video/mj2":".mj2","video/mp2t":".ts","video/mp4":".mp4","video/mpeg":".mpeg","video/ogg":".ogv","video/quicktime":".mov","video/vnd.dece.hd":".uvh","video/vnd.dece.mobile":".uvm","video/vnd.dece.pd":".uvp","video/vnd.dece.sd":".uvs","video/vnd.dece.video":".uvv","video/vnd.dvb.file":".dvb","video/vnd.fvt":".fvt","video/vnd.mpegurl":".mxu","video/vnd.ms-playready.media.pyv":".pyv","video/vnd.uvvu.mp4":".uvu","video/vnd.vivo":".viv","video/webm":".webm","video/x-dv":".dv","video/x-f4v":".f4v","video/x-fli":".fli","video/x-flv":".flv","video/x-m4v":".m4v","video/x-matroska":".mkv","video/x-mng":".mng","video/x-ms-asf":".asf","video/x-ms-vob":".vob","video/x-ms-wm":".wm","video/x-ms-wmv":".wmv","video/x-ms-wmx":".wmx","video/x-ms-wvx":".wvx","video/x-msvideo":".avi","video/x-sgi-movie":".movie","video/x-smv":".smv","x-conference/x-cooltalk":".ice"}
1126
-
1127
- def read_download_filename(request):
1128
- from urllib.parse import urlsplit, unquote
1129
- import posixpath
1130
- url = urlsplit(request['source'])
1131
- filename = unquote(posixpath.basename(url.path.rstrip('/'))) or url.netloc.rsplit('@', 1)[-1]
1132
- headers = {key.lower(): value for key, value in request['headers']}
1133
- # CPython 3.9 cgi.parse_header rules, including last duplicate wins.
1134
- remaining = ';' + headers.get('content-disposition', '')
1135
- parameters = []
1136
- while remaining[:1] == ';':
1137
- remaining = remaining[1:]
1138
- end = remaining.find(';')
1139
- while end > 0 and (remaining.count('"', 0, end) - remaining.count('\\"', 0, end)) % 2:
1140
- end = remaining.find(';', end + 1)
1141
- if end < 0: end = len(remaining)
1142
- parameters.append(remaining[:end].strip())
1143
- remaining = remaining[end:]
1144
- selected = None
1145
- for parameter in parameters[1:]:
1146
- if '=' not in parameter: continue
1147
- key, value = parameter.split('=', 1)
1148
- if key.strip().lower() != 'filename': continue
1149
- value = value.strip()
1150
- if len(value) >= 2 and value[0] == value[-1] == '"':
1151
- value = value[1:-1].replace('\\\\', '\\').replace('\\"', '"')
1152
- selected = posixpath.basename(value) if value else ''
1153
- filename = selected or filename
1154
- ext = posixpath.splitext(filename)[1]
1155
- if not ext:
1156
- ext = MIME_PREFERENCES.get(headers.get('content-type', '').lower())
1157
- if ext: filename += ext
1158
- if not ext and request['source'] != request['responseUrl']:
1159
- ext = posixpath.splitext(request['responseUrl'])[1]
1160
- if ext: filename += ext
1161
- return filename
1162
- `)();
1015
+ // packages/safe-bash-command-python/src/build-backend.generated.ts
1016
+ var pythonBuildBackendProgramGzip = "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";
1163
1017
 
1164
1018
  // packages/safe-bash-command-python/src/build-backend.ts
1165
1019
  import { toByteSource as toByteSource5 } from "../../safe-bash-contracts/index.js";
@@ -1200,7 +1054,9 @@ function createPythonBuildBackend(options) {
1200
1054
  const request = structuredClone(input.hook === "read_build_system" ? { ...input, maxBytes: maxBytes === Infinity ? null : maxBytes } : input);
1201
1055
  let done = false, size = 0, failure;
1202
1056
  const chunks = [];
1203
- const invocation = { ...context, command: "python", args: ["-c", pythonBuildBackendProgram], stdin: toByteSource5("") };
1057
+ const program = await loadPythonBuildBackendProgram();
1058
+ context.signal.throwIfAborted();
1059
+ const invocation = { ...context, command: "python", args: ["-c", program], stdin: toByteSource5("") };
1204
1060
  if (request.hook === "build_legacy_wheel" || request.hook === "get_requires_for_legacy_wheel") legacy.add(invocation.args);
1205
1061
  capabilities.set(invocation.args, { async call(value) {
1206
1062
  try {
@@ -1260,191 +1116,10 @@ function createPythonBuildBackend(options) {
1260
1116
  }
1261
1117
  };
1262
1118
  }
1263
- var pythonBuildBackendProgram = /* @__PURE__ */ (() => String.raw`
1264
- import importlib, json, os, sys, safe_host
1265
- ${pythonDownloadFilenameProgram}
1266
-
1267
- def send(op, **fields):
1268
- return safe_host.call('python_build', dict(op=op, **fields))
1269
-
1270
-
1271
- ${pythonSourceOriginProgram}
1272
-
1273
- def parse_build_requirement(value):
1274
- from urllib.parse import urlparse, urlunparse
1275
- from micropip._vendored.packaging.src.packaging.requirements import Requirement, InvalidRequirement
1276
- requirement = Requirement(value)
1277
- if requirement.url:
1278
- url = urlparse(requirement.url)
1279
- if (url.scheme == 'file' and urlunparse(url) != requirement.url) or (url.scheme != 'file' and not (url.scheme and url.netloc)): raise InvalidRequirement(value)
1280
- return requirement
1281
-
1282
- def check_build_requirements(request):
1283
- from importlib.metadata import distribution, PackageNotFoundError
1284
- from micropip._vendored.packaging.src.packaging.utils import canonicalize_name
1285
- from micropip._vendored.packaging.src.packaging.version import Version
1286
- installed = {canonicalize_name(name) for name in request['installed']}
1287
- conflicting, missing = set(), set()
1288
- for value in request['requirements']:
1289
- requirement = parse_build_requirement(value)
1290
- if canonicalize_name(requirement.name) not in installed:
1291
- missing.add(value)
1292
- continue
1293
- try: version = Version(distribution(requirement.name).version)
1294
- except PackageNotFoundError:
1295
- missing.add(value)
1296
- continue
1297
- if version not in requirement.specifier: conflicting.add((requirement.name + '==' + str(version), value))
1298
- return dict(conflicting=sorted(conflicting), missing=sorted(missing))
1299
-
1300
- def read_build_system(request):
1301
- import tomllib
1302
- from micropip._vendored.packaging.src.packaging.requirements import InvalidRequirement
1303
- class InstallationError(Exception): pass
1304
- source = request['source']
1305
- filename = os.path.join(source, 'pyproject.toml')
1306
- has_project, has_setup = os.path.isfile(filename), os.path.isfile(os.path.join(source, 'setup.py'))
1307
- if request.get('installation') == 'directory' and not has_project and not has_setup:
1308
- raise InstallationError("Directory {!r} is not installable. Neither 'setup.py' nor 'pyproject.toml' found.".format(request.get('name', source)))
1309
- system = None
1310
- if has_project:
1311
- limit = request['maxBytes']
1312
- with open(filename, 'rb') as stream: raw = stream.read() if limit is None else stream.read(limit + 1)
1313
- if limit is not None and len(raw) > limit: raise ValueError('Python build configuration limit exceeded')
1314
- system = tomllib.loads(raw.decode('utf-8')).get('build-system')
1315
- selected = request.get('usePep517')
1316
- if has_project and not has_setup:
1317
- if selected is False: raise InstallationError('Disabling PEP 517 processing is invalid: project does not have a setup.py')
1318
- selected = True
1319
- elif system and 'build-backend' in system:
1320
- if selected is False: raise InstallationError('Disabling PEP 517 processing is invalid: project specifies a build backend of {} in pyproject.toml'.format(system['build-backend']))
1321
- selected = True
1322
- elif selected is None: selected = has_project
1323
- if not selected:
1324
- if request.get('installation') and not os.path.exists(os.path.join(source, 'setup.py')):
1325
- raise InstallationError('File "setup.py" not found for legacy project {}.'.format(request.get('name', source)))
1326
- return None
1327
- defaults = ['setuptools>=40.8.0', 'wheel']
1328
- if system is None: system = {'requires': defaults, 'build-backend': 'setuptools.build_meta:__legacy__'}
1329
- def invalid(reason):
1330
- raise InstallationError('{} has a pyproject.toml file that does not comply with PEP 518: {}'.format(request.get('name', source), reason))
1331
- if 'requires' not in system: invalid("it has a 'build-system' table but not 'build-system.requires' which is mandatory in the table")
1332
- requirements = system['requires']
1333
- if not isinstance(requirements, list) or not all(isinstance(value, str) for value in requirements): invalid("'build-system.requires' is not a list of strings.")
1334
- for value in requirements:
1335
- try:
1336
- parse_build_requirement(value)
1337
- except InvalidRequirement: invalid("'build-system.requires' contains an invalid requirement: {!r}".format(value))
1338
- backend = system.get('build-backend')
1339
- return dict(requires=requirements, backend=backend if backend is not None else 'setuptools.build_meta:__legacy__', check=defaults if backend is None else [], backendPath=system.get('backend-path', []))
1340
-
1341
- def build_legacy_wheel(request):
1342
- source = os.path.realpath(request['source'])
1343
- directory = os.path.abspath(request['wheelDirectory'])
1344
- filename = os.path.join(source, 'setup.py')
1345
- os.chdir(source)
1346
- sys.path.insert(0, '')
1347
- sys.argv = [filename, 'bdist_wheel', '-d', directory]
1348
- namespace = dict(__name__='__main__', __file__=filename)
1349
- try:
1350
- exec("import io, os, sys, setuptools, tokenize\nsys.argv[0] = __file__\nf = getattr(tokenize, 'open', open)(__file__) if os.path.exists(__file__) else io.StringIO('from setuptools import setup; setup()')\ncode = f.read().replace('\\r\\n', '\\n')\nf.close()\nexec(compile(code, __file__, 'exec'))", namespace)
1351
- except SystemExit as error:
1352
- if error.code not in (None, 0): raise
1353
- first = None
1354
- with os.scandir(directory) as entries:
1355
- for entry in entries:
1356
- if first is None or entry.name < first: first = entry.name
1357
- if first is None: raise RuntimeError('Legacy wheel build created no files')
1358
- return first
1359
-
1360
- def read_source_requirement(request):
1361
- from micropip._vendored.packaging.src.packaging.requirements import InvalidRequirement
1362
- try: requirement = parse_build_requirement(request['source'])
1363
- except InvalidRequirement: return None
1364
- if not requirement.url: return None
1365
- marker = requirement.marker
1366
- return dict(name=requirement.name, extras=sorted({'_'.join(part for part in extra.lower().split('_') if part) for extra in requirement.extras}), url=requirement.url, marker=str(marker) if marker else None, active=not marker or marker.evaluate({'extra': ''}))
1367
-
1368
- def read_editable_requirement(request):
1369
- from pathlib import Path
1370
- from micropip._vendored.packaging.src.packaging.requirements import Requirement
1371
- class InstallationError(Exception): pass
1372
- source, extras = request['source'], None
1373
- if request.get('requirementLine'):
1374
- import shlex, optparse
1375
- class OptionParsingError(Exception): pass
1376
- class Parser(optparse.OptionParser):
1377
- def exit(self, status=0, message=None): raise OptionParsingError(message)
1378
- parser = Parser(add_help_option=False)
1379
- parser.add_option('-e', '--editable', action='append', dest='editables')
1380
- options, _ = parser.parse_args(shlex.split(source))
1381
- if not options.editables: raise InstallationError('Editable requirement line requires -e')
1382
- source = options.editables[0]
1383
- start = source.rfind('[')
1384
- if start > 0 and source.endswith(']') and start < len(source) - 2 and ']' not in source[start + 1:-1]:
1385
- source, extras = source[:start], source[start:]
1386
- if os.path.isdir(source):
1387
- if not any(os.path.exists(os.path.join(source, name)) for name in ('setup.py', 'setup.cfg')):
1388
- message = 'File "setup.py" or "setup.cfg" not found. Directory cannot be installed in editable mode: {}'.format(os.path.abspath(source))
1389
- if os.path.isfile(os.path.join(source, 'pyproject.toml')): message += '\n(A "pyproject.toml" file was found, but editable mode currently requires a setuptools-based build.)'
1390
- raise InstallationError(message)
1391
- source = Path(os.path.abspath(source)).as_uri()
1392
- if not source.lower().startswith('file:'): raise InstallationError('Editable source requires a local directory')
1393
- name = ''
1394
- for index, character in enumerate(source):
1395
- if character in '#&' and source.startswith('egg=', index + 1):
1396
- name = source[index + 5:].split('&', 1)[0]
1397
- break
1398
- return dict(name=name, url=source, extras=sorted(Requirement('placeholder' + extras.lower()).extras) if extras else [], marker=None, active=True)
1399
-
1400
- def main():
1401
- request = send('request')
1402
- if request['hook'] == 'get_requires_for_legacy_wheel': request.update(hook='get_requires_for_build_wheel', backend='setuptools.build_meta:__legacy__')
1403
- if request['hook'] == 'read_source_origin': return read_source_origin(request)
1404
- if request['hook'] == 'read_download_filename': return read_download_filename(request)
1405
- if request['hook'] == 'read_source_requirement': return read_source_requirement(request)
1406
- if request['hook'] == 'read_editable_requirement': return read_editable_requirement(request)
1407
- if request['hook'] == 'build_legacy_wheel':
1408
- if not request.get('editable'): return build_legacy_wheel(request)
1409
- request.update(hook='build_wheel', backend='setuptools.build_meta:__legacy__')
1410
- if request['hook'] == 'read_build_system': return read_build_system(request)
1411
- if request['hook'] == 'check_build_requirements': return check_build_requirements(request)
1412
- source = os.path.realpath(request['source'])
1413
- wheel_directory = os.path.abspath(request['wheelDirectory']) if request['hook'] == 'build_wheel' else None
1414
- metadata_directory = os.path.abspath(request['metadataDirectory']) if request.get('metadataDirectory') is not None else None
1415
- os.chdir(source)
1416
- paths = []
1417
- for entry in request.get('backendPath', []):
1418
- if os.path.isabs(entry): raise ValueError('paths must be relative')
1419
- path = os.path.realpath(os.path.join(source, entry))
1420
- if os.path.commonpath([source, path]) != source: raise ValueError('paths must be inside source tree')
1421
- paths.append(path)
1422
- sys.path[:0] = paths
1423
- module, _, attributes = request['backend'].partition(':')
1424
- backend = importlib.import_module(module)
1425
- if paths and not any(os.path.commonpath([os.path.realpath(backend.__file__), path]) == path for path in paths):
1426
- raise ValueError('Backend was not loaded from backend-path')
1427
- if attributes:
1428
- for name in attributes.split('.'): backend = getattr(backend, name)
1429
- settings = request.get('configSettings')
1430
- if request['hook'] == 'get_requires_for_build_wheel':
1431
- try: hook = backend.get_requires_for_build_wheel
1432
- except AttributeError: result = []
1433
- else: result = hook(settings)
1434
- else:
1435
- if request.get('editable'): result = backend.build_editable(wheel_directory, {'editable_mode': 'compat'}, metadata_directory)
1436
- else: result = backend.build_wheel(wheel_directory, settings, metadata_directory)
1437
- return result
1438
-
1439
- try:
1440
- result = main()
1441
- encoder = json.JSONEncoder(ensure_ascii=False, separators=(',', ':'))
1442
- for part in encoder.iterencode(result):
1443
- for offset in range(0, len(part), 4096): send('text', text=part[offset:offset + 4096])
1444
- send('done')
1445
- except Exception as error:
1446
- send('error', type=type(error).__name__, message=str(error))
1447
- `)();
1119
+ var decodedBuildProgram;
1120
+ function loadPythonBuildBackendProgram() {
1121
+ return decodedBuildProgram ??= new Response(new Blob([Uint8Array.from(atob(pythonBuildBackendProgramGzip), (character) => character.charCodeAt(0))]).stream().pipeThrough(new DecompressionStream("gzip"))).text();
1122
+ }
1448
1123
 
1449
1124
  // packages/safe-bash-command-python/src/build-dependencies.ts
1450
1125
  function createPythonBuildDependencies(options) {
@@ -1466,11 +1141,32 @@ function createPythonBuildDependencies(options) {
1466
1141
  };
1467
1142
  const check = async (requirements2, against) => {
1468
1143
  if (!requirements2.length) return [];
1469
- const receipt = await isolated.environment.prepare(context);
1144
+ const receipt = await isolated.environment.prepare({ ...context, recordTransport: "host" });
1470
1145
  let installed;
1471
1146
  try {
1472
- if (!receipt.records && receipt.restore?.length) throw new Error("Python build dependency checks require an installed metadata manifest");
1473
- installed = receipt.records?.map((record2) => record2[0]) ?? [];
1147
+ if (receipt.recordCount === void 0) {
1148
+ if (!receipt.records && receipt.restore?.length) throw new Error("Python build dependency checks require an installed metadata manifest");
1149
+ installed = receipt.records?.map((record2) => record2[0]) ?? [];
1150
+ } else {
1151
+ if (receipt.recordCount < 0 && receipt.restore?.length) throw new Error("Python build dependency checks require an installed metadata manifest");
1152
+ const names = [];
1153
+ let bytes = 0;
1154
+ for (let ordinal = 0; ordinal < receipt.recordCount; ordinal++) {
1155
+ let text = "";
1156
+ for (; ; ) {
1157
+ const chunk = await isolated.environment.dispatch("package-record-read", [receipt.session, ordinal, text.length, 0], context);
1158
+ if (typeof chunk !== "string") throw new Error("Python build dependency name transport is unavailable");
1159
+ bytes += new TextEncoder().encode(chunk).length;
1160
+ if (bytes > context.maxBytes) throw new RangeError("Python build dependency names exceed maxBytes");
1161
+ text += chunk;
1162
+ if (chunk.length < 8192) break;
1163
+ }
1164
+ const name = JSON.parse(text);
1165
+ if (typeof name !== "string") throw new TypeError("Invalid Python build dependency name");
1166
+ names.push(name);
1167
+ }
1168
+ installed = names;
1169
+ }
1474
1170
  } finally {
1475
1171
  await isolated.environment.finish(receipt);
1476
1172
  }
@@ -2002,6 +1698,7 @@ import { FsError as FsError4, toByteSource as toByteSource7 } from "../../safe-b
2002
1698
  import { resolvePath as resolvePath4 } from "../../safe-bash-contracts/path.js";
2003
1699
 
2004
1700
  // packages/safe-bash-command-python/src/source-download.ts
1701
+ import { bytesToHex } from "../../safe-bash-io-engine/byte-encoding.js";
2005
1702
  import { dirname as dirname2, resolvePath as resolvePath3 } from "../../safe-bash-contracts/path.js";
2006
1703
  import { sha224, sha256, sha384, sha512 } from "@noble/hashes/sha2.js";
2007
1704
  import { sha1, md5 } from "@noble/hashes/legacy.js";
@@ -2021,7 +1718,7 @@ async function* verifiedBytes(source, expected, maxBytes, signal) {
2021
1718
  yield chunk;
2022
1719
  }
2023
1720
  }
2024
- if (checksum && Array.from(checksum.digest(), (byte) => byte.toString(16).padStart(2, "0")).join("") !== expected[1]) throw new Error("Python source archive integrity mismatch: " + expected[0]);
1721
+ if (checksum && bytesToHex(checksum.digest()) !== expected[1]) throw new Error("Python source archive integrity mismatch: " + expected[0]);
2025
1722
  } finally {
2026
1723
  checksum?.destroy();
2027
1724
  }
@@ -2296,9 +1993,13 @@ function createPythonSourcePackageEnvironment(options, build) {
2296
1993
  var encoder = new TextEncoder();
2297
1994
  var PythonInputChunkError = class extends RangeError {
2298
1995
  };
1996
+ function writeDiagnostic(output, message, signal) {
1997
+ return writeBytes(output, encoder.encode("python: " + message + "\n"), signal);
1998
+ }
2299
1999
  function createPythonExecutorCommands(options) {
2300
2000
  if (!options || typeof options.createWorker === "function" === (typeof options.createExecutor === "function") || options.createWorker !== void 0 && typeof options.createWorker !== "function" || options.createExecutor !== void 0 && typeof options.createExecutor !== "function") throw new PythonFailure("executor-unavailable");
2301
2001
  if (options.createCapabilities && !options.createExecutor) throw new TypeError("Python host capabilities require an asynchronous executor");
2002
+ if (options.packageRecordTransport !== void 0 && !["host", "inline"].includes(options.packageRecordTransport)) throw new TypeError("Invalid Python package record transport");
2302
2003
  if (options.onDiagnostic !== void 0 && typeof options.onDiagnostic !== "function") throw new TypeError("Python onDiagnostic must be a function");
2303
2004
  if (options.environment && options.provisioning) throw new TypeError("A borrowed Python environment cannot be combined with provisioning options");
2304
2005
  const maxTransferBytes = options.maxTransferBytes ?? Infinity;
@@ -2313,9 +2014,10 @@ function createPythonExecutorCommands(options) {
2313
2014
  const runtimeMount = options.runtimeMount ?? "/.pyodide-runtime";
2314
2015
  if (!runtimeMount.startsWith("/") || runtimeMount === "/" || runtimeMount.slice(1).includes("/") || runtimeMount.includes("\0") || runtimeMount.split("/").some((part) => part === ".." || part === ".")) throw new TypeError("Python runtime mount must be an absolute top-level canonical path");
2315
2016
  const environment = options.environment ?? createPythonPackageEnvironment(options.provisioning);
2017
+ const diagnose = (category, reason) => reportPythonFailure(category, reason, options.onDiagnostic);
2316
2018
  const execute = async (context) => {
2317
2019
  if (pythonShellDispatchActive(context.executionScope)) {
2318
- await writeBytes(context.stderr, encoder.encode("python: nested Python execution is unavailable while the parent interpreter is suspended\n"), context.signal);
2020
+ await writeDiagnostic(context.stderr, "nested Python execution is unavailable while the parent interpreter is suspended", context.signal);
2319
2021
  return { exitCode: 1 };
2320
2022
  }
2321
2023
  let installation;
@@ -2324,7 +2026,7 @@ function createPythonExecutorCommands(options) {
2324
2026
  installation = invocation.module?.name === "pip" ? parsePythonInstallation(invocation.module.args) : void 0;
2325
2027
  } catch (error) {
2326
2028
  if (!(error instanceof PythonInvocationError)) throw error;
2327
- await writeBytes(context.stderr, encoder.encode("python: " + error.message + "\n"), context.signal);
2029
+ await writeDiagnostic(context.stderr, error.message, context.signal);
2328
2030
  return { exitCode: 2 };
2329
2031
  }
2330
2032
  if (installation?.help) {
@@ -2333,8 +2035,8 @@ function createPythonExecutorCommands(options) {
2333
2035
  }
2334
2036
  context.signal.throwIfAborted();
2335
2037
  if (activeWorkers >= maxConcurrentWorkers) {
2336
- const failure = reportPythonFailure("capacity", void 0, options.onDiagnostic);
2337
- await writeBytes(context.stderr, encoder.encode("python: " + failure.message + "\n"), context.signal);
2038
+ const failure = diagnose("capacity", void 0);
2039
+ await writeDiagnostic(context.stderr, failure.message, context.signal);
2338
2040
  return { exitCode: 1 };
2339
2041
  }
2340
2042
  const controller = new AbortController();
@@ -2397,7 +2099,7 @@ function createPythonExecutorCommands(options) {
2397
2099
  }
2398
2100
  finish();
2399
2101
  }, (reason) => {
2400
- fail(reportPythonFailure("cleanup", reason, options.onDiagnostic));
2102
+ fail(diagnose("cleanup", reason));
2401
2103
  });
2402
2104
  return closing;
2403
2105
  };
@@ -2418,11 +2120,11 @@ function createPythonExecutorCommands(options) {
2418
2120
  stderrOperation = createOutputOperation(outputContext, context.stderr);
2419
2121
  const diagnoseFilesystemFailure = async (operation, error) => {
2420
2122
  if (typeof error !== "object" || error === null || !("code" in error) || error.code !== "ENOTSUP") return;
2421
- const category = operation === "open" ? "filesystem-open" : operation === "read" ? "filesystem-read" : operation === "write" || operation === "ftruncate" ? "filesystem-write" : operation === "readdir" ? "filesystem-directory" : "filesystem-operation";
2123
+ const category = operation === "open" ? "filesystem-open" : operation === "read" ? "filesystem-read" : operation === "write" || operation === "ftruncate" ? "filesystem-write" : operation === "readdir" || operation.startsWith("directory") ? "filesystem-directory" : "filesystem-operation";
2422
2124
  if (!filesystemDiagnostics.has(category)) {
2423
2125
  filesystemDiagnostics.add(category);
2424
- const failure = reportPythonFailure(category, error, options.onDiagnostic);
2425
- await writeBytes(stderrOperation.output, encoder.encode("python: " + failure.message + "\n"), signal);
2126
+ const failure = diagnose(category, error);
2127
+ await writeDiagnostic(stderrOperation.output, failure.message, signal);
2426
2128
  }
2427
2129
  };
2428
2130
  const dispatch = async (request) => {
@@ -2472,6 +2174,7 @@ function createPythonExecutorCommands(options) {
2472
2174
  const preparation = environment.prepare({
2473
2175
  ...context,
2474
2176
  signal,
2177
+ recordTransport: options.packageRecordTransport ?? "host",
2475
2178
  ...installation?.controls,
2476
2179
  ...installation?.uninstall ? { uninstall: { packages: installation.packages, yes: !!installation.yes } } : {},
2477
2180
  requirements: [...options.packages ?? [], ...options.packageProfile ? pythonDocumentPackages : [], ...installation?.uninstall ? [] : installation?.packages ?? []],
@@ -2490,9 +2193,9 @@ function createPythonExecutorCommands(options) {
2490
2193
  try {
2491
2194
  executor = options.createExecutor();
2492
2195
  } catch (reason) {
2493
- throw reportPythonFailure(reason instanceof PythonFailure ? reason.category : "startup", reason, options.onDiagnostic);
2196
+ throw diagnose(reason instanceof PythonFailure ? reason.category : "startup", reason);
2494
2197
  }
2495
- if (!executor || typeof executor.run !== "function" || typeof executor.terminate !== "function") throw reportPythonFailure("executor-unavailable", void 0, options.onDiagnostic);
2198
+ if (!executor || typeof executor.run !== "function" || typeof executor.terminate !== "function") throw diagnose("executor-unavailable", void 0);
2496
2199
  let requesting = false;
2497
2200
  let running = true;
2498
2201
  const start = {
@@ -2515,16 +2218,16 @@ function createPythonExecutorCommands(options) {
2515
2218
  }
2516
2219
  },
2517
2220
  async dispatch(request) {
2518
- if (!request || typeof request.op !== "string" || !Array.isArray(request.args)) throw reportPythonFailure("transport-unavailable", void 0, options.onDiagnostic);
2221
+ if (!request || typeof request.op !== "string" || !Array.isArray(request.args)) throw diagnose("transport-unavailable", void 0);
2519
2222
  const releasing = request.op === "close";
2520
2223
  if (!releasing) signal.throwIfAborted();
2521
- if (closed && !releasing || !running || requesting) throw reportPythonFailure("transport-unavailable", void 0, options.onDiagnostic);
2224
+ if (closed && !releasing || !running || requesting) throw diagnose("transport-unavailable", void 0);
2522
2225
  requesting = true;
2523
2226
  const operation = Promise.resolve().then(() => dispatch(request)).catch(async (error) => {
2524
2227
  if (releasing) throw error;
2525
2228
  signal.throwIfAborted();
2526
2229
  if (error instanceof PythonInputChunkError) rejectRun?.(error);
2527
- if (request.op.startsWith("package-")) throw Object.assign(reportPythonFailure("runtime-assets", error, options.onDiagnostic), { code: "EPACKAGE" });
2230
+ if (request.op.startsWith("package-")) throw Object.assign(diagnose("runtime-assets", error), { code: "EPACKAGE" });
2528
2231
  await diagnoseFilesystemFailure(request.op, error);
2529
2232
  throw error;
2530
2233
  });
@@ -2546,14 +2249,14 @@ function createPythonExecutorCommands(options) {
2546
2249
  }).catch((reason) => {
2547
2250
  running = false;
2548
2251
  if (signal.aborted) throw signal.reason;
2549
- throw reportPythonFailure(reason instanceof PythonFailure ? reason.category : ready ? "runtime" : "startup", reason, options.onDiagnostic);
2252
+ throw diagnose(reason instanceof PythonFailure ? reason.category : ready ? "runtime" : "startup", reason);
2550
2253
  }).then((status) => {
2551
2254
  running = false;
2552
- if (requesting) throw reportPythonFailure("transport-unavailable", void 0, options.onDiagnostic);
2255
+ if (requesting) throw diagnose("transport-unavailable", void 0);
2553
2256
  try {
2554
2257
  return validateExitCode(status);
2555
2258
  } catch (reason) {
2556
- throw reportPythonFailure("transport-unavailable", reason, options.onDiagnostic);
2259
+ throw diagnose("transport-unavailable", reason);
2557
2260
  }
2558
2261
  });
2559
2262
  const tracked = execution.then(() => {
@@ -2572,7 +2275,7 @@ function createPythonExecutorCommands(options) {
2572
2275
  try {
2573
2276
  shared = new SharedArrayBuffer(8 + transferChunkBytes * 6 + 65536);
2574
2277
  } catch (reason) {
2575
- throw reportPythonFailure("transport-unavailable", reason, options.onDiagnostic);
2278
+ throw diagnose("transport-unavailable", reason);
2576
2279
  }
2577
2280
  const control = new Int32Array(shared, 0, 2);
2578
2281
  const payload = new Uint8Array(shared, 8);
@@ -2592,13 +2295,13 @@ function createPythonExecutorCommands(options) {
2592
2295
  Atomics.store(control, 0, status);
2593
2296
  Atomics.notify(control, 0);
2594
2297
  } catch (reason) {
2595
- throw reportPythonFailure("transport-unavailable", reason, options.onDiagnostic);
2298
+ throw diagnose("transport-unavailable", reason);
2596
2299
  }
2597
2300
  };
2598
2301
  try {
2599
2302
  endpoint = options.createWorker();
2600
2303
  } catch (reason) {
2601
- throw reportPythonFailure(reason instanceof PythonFailure ? reason.category : "startup", reason, options.onDiagnostic);
2304
+ throw diagnose(reason instanceof PythonFailure ? reason.category : "startup", reason);
2602
2305
  }
2603
2306
  signal.throwIfAborted();
2604
2307
  result = await new Promise((resolve, reject) => {
@@ -2610,7 +2313,7 @@ function createPythonExecutorCommands(options) {
2610
2313
  rejectRun = fail;
2611
2314
  signal.addEventListener("abort", aborted, { once: true });
2612
2315
  const transportFailure = (reason) => {
2613
- fail(reportPythonFailure("transport-unavailable", reason, options.onDiagnostic));
2316
+ fail(diagnose("transport-unavailable", reason));
2614
2317
  };
2615
2318
  try {
2616
2319
  unsubscribe = endpoint.subscribe((value) => {
@@ -2644,7 +2347,7 @@ function createPythonExecutorCommands(options) {
2644
2347
  return;
2645
2348
  }
2646
2349
  if (message.type === "error") {
2647
- fail(reportPythonFailure(isPythonFailureCategory(message.category) ? message.category : ready ? "runtime" : "startup", message.message, options.onDiagnostic));
2350
+ fail(diagnose(isPythonFailureCategory(message.category) ? message.category : ready ? "runtime" : "startup", message.message));
2648
2351
  return;
2649
2352
  }
2650
2353
  if (typeof message.op !== "string" || !Array.isArray(message.args) || pending.size) {
@@ -2663,7 +2366,7 @@ function createPythonExecutorCommands(options) {
2663
2366
  return;
2664
2367
  }
2665
2368
  if (typeof message.op === "string" && message.op.startsWith("package-")) {
2666
- const failure = reportPythonFailure("runtime-assets", error, options.onDiagnostic);
2369
+ const failure = diagnose("runtime-assets", error);
2667
2370
  pending.delete(work);
2668
2371
  reply({ code: "EPACKAGE", message: failure.message }, 2);
2669
2372
  return;
@@ -2700,12 +2403,12 @@ function createPythonExecutorCommands(options) {
2700
2403
  } catch (reason) {
2701
2404
  if (!signal.aborted && (reason instanceof PythonInputChunkError || reason instanceof PythonInstallationError)) {
2702
2405
  try {
2703
- await writeBytes(stderrOperation.output, encoder.encode("python: " + reason.message + "\n"), signal);
2406
+ await writeDiagnostic(stderrOperation.output, reason.message, signal);
2704
2407
  } catch (error) {
2705
2408
  primary = { reason: error };
2706
2409
  }
2707
2410
  } else if (!signal.aborted && typeof reason === "object" && reason !== null && "code" in reason && reason.code === "EPACKAGE") {
2708
- primary = { reason: reportPythonFailure("runtime-assets", reason, options.onDiagnostic) };
2411
+ primary = { reason: diagnose("runtime-assets", reason) };
2709
2412
  } else primary = { reason };
2710
2413
  }
2711
2414
  try {
@@ -2722,7 +2425,7 @@ function createPythonExecutorCommands(options) {
2722
2425
  if (primary) {
2723
2426
  if (!(primary.reason instanceof PythonFailure)) throw primary.reason;
2724
2427
  const failure = primary.reason;
2725
- await writeBytes(context.stderr, encoder.encode("python: " + failure.message + "\n"), context.signal);
2428
+ await writeDiagnostic(context.stderr, failure.message, context.signal);
2726
2429
  return { exitCode: 1 };
2727
2430
  }
2728
2431
  return { exitCode: result };