@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.
- package/dist/image-ast/index.js +39 -18
- package/dist/pdf-ast/image.js +1 -1
- package/dist/pdf-ast/index.js +1 -1
- package/dist/pdf-ast/vendor/pdfjs-fonts.mjs +9 -3
- package/dist/safe-bash/chunks/{chunk-AGHV53VF.js → chunk-M6XFU6LQ.js} +3 -1
- package/dist/safe-bash/chunks/{chunk-363QOIDR.js → chunk-T6FHWSHM.js} +3 -1
- package/dist/safe-bash/command-chunks/{chunk-ZPBL7TYJ.js → chunk-2JRHCVMQ.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-FMGNXOMV.js → chunk-2L3NMRLG.js} +7 -3
- package/dist/safe-bash/command-chunks/{chunk-DAQO64WC.js → chunk-2YKOJPIW.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-EPYJSPOY.js → chunk-3QCW4VQF.js} +12 -8
- package/dist/safe-bash/command-chunks/{chunk-YRBFNT5B.js → chunk-3YL2TMLA.js} +10 -1
- package/dist/safe-bash/command-chunks/{chunk-5H7ZHP7F.js → chunk-43NDRBKY.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-BBOYR6LV.js → chunk-46GA576V.js} +3 -3
- package/dist/safe-bash/command-chunks/{chunk-WPT2FCHH.js → chunk-4SLPM2WM.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-7ZQVMPSB.js → chunk-5CAXR62E.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-3DTHX5UU.js → chunk-66653AEZ.js} +40 -14
- package/dist/safe-bash/command-chunks/{chunk-ETFJ4L7F.js → chunk-6OLE6CLV.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-ZIDESNHW.js → chunk-7M3M6FKC.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-2KMNVJB7.js → chunk-A7PKUIJT.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-AVSINNZ6.js → chunk-DEQ47SBQ.js} +5 -5
- package/dist/safe-bash/command-chunks/{chunk-EV7A5FNN.js → chunk-FFFRLPXU.js} +2 -2
- package/dist/safe-bash/command-chunks/{chunk-4MVQE6CT.js → chunk-FYTBEGSY.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-LFTGMUAV.js → chunk-HQIZR6EU.js} +192 -489
- package/dist/safe-bash/command-chunks/chunk-HS2L7I4N.js +219 -0
- package/dist/safe-bash/command-chunks/{chunk-WKS2PAZL.js → chunk-HUGKO4ZE.js} +10 -1
- package/dist/safe-bash/command-chunks/chunk-IGXH5W5Z.js +111 -0
- package/dist/safe-bash/command-chunks/{chunk-CMJBRGU2.js → chunk-IHQZKUBS.js} +1 -1
- package/dist/safe-bash/command-chunks/chunk-JADJ4BMN.js +1519 -0
- package/dist/safe-bash/command-chunks/{chunk-5AQAWIYK.js → chunk-JEZC5V3B.js} +4 -0
- package/dist/safe-bash/command-chunks/{chunk-YB5TNDY6.js → chunk-K5VJ4NNL.js} +39 -5
- package/dist/safe-bash/command-chunks/{chunk-7RQGRFHJ.js → chunk-KHWDEAE4.js} +2 -2
- package/dist/safe-bash/command-chunks/chunk-L54KVUSY.js +604 -0
- package/dist/safe-bash/command-chunks/{chunk-3NJETNC2.js → chunk-MBXNG6C3.js} +2 -2
- package/dist/safe-bash/command-chunks/{chunk-HCPEYQKT.js → chunk-N4SH6QY5.js} +285 -302
- package/dist/safe-bash/command-chunks/{chunk-3DID6MQY.js → chunk-OWTQYLID.js} +2 -2
- package/dist/safe-bash/command-chunks/{chunk-4EA7WI3L.js → chunk-QOOQD6BD.js} +42 -33
- package/dist/safe-bash/command-chunks/{chunk-RQTFK7AV.js → chunk-QZYEI4N6.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-R3SLT3ZX.js → chunk-R6GON4H3.js} +11 -1
- package/dist/safe-bash/command-chunks/{chunk-2GILUQJY.js → chunk-R7ZGDHME.js} +3 -3
- package/dist/safe-bash/command-chunks/{chunk-HNEWGADJ.js → chunk-RUXOFW5G.js} +7 -6
- package/dist/safe-bash/command-chunks/{chunk-LKAFLJ5L.js → chunk-RWQKX44L.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-PKH57OIC.js → chunk-SG2KOOD4.js} +2 -2
- package/dist/safe-bash/command-chunks/chunk-T4TGJYFV.js +60 -0
- package/dist/safe-bash/command-chunks/chunk-TGSNVLFZ.js +105 -0
- package/dist/safe-bash/command-chunks/{chunk-NXCJNPL3.js → chunk-UCE77LYV.js} +2 -1
- package/dist/safe-bash/command-chunks/{chunk-EWECMOQ5.js → chunk-UIHPHIKI.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-XSZNL3GV.js → chunk-UJPWPRVB.js} +191 -146
- package/dist/safe-bash/command-chunks/{chunk-E5CDHXFA.js → chunk-VOR6YDZC.js} +26 -1
- package/dist/safe-bash/command-chunks/chunk-VSNVYOK2.js +30 -0
- package/dist/safe-bash/command-chunks/{chunk-4XYGJB24.js → chunk-VTH4AORO.js} +3 -3
- package/dist/safe-bash/command-chunks/{chunk-W5LH7D23.js → chunk-WKKJJBJQ.js} +8 -8
- package/dist/safe-bash/command-chunks/{chunk-OLXMWQJ5.js → chunk-WRO3PB2M.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-RUAGHZNF.js → chunk-X5ODTF3E.js} +7 -5
- package/dist/safe-bash/command-chunks/{chunk-LH4VBNF6.js → chunk-XGTSP2CP.js} +84 -16
- package/dist/safe-bash/command-chunks/{chunk-K576GZED.js → chunk-XTHKXCF2.js} +2 -2
- package/dist/safe-bash/command-chunks/{chunk-J3VS55K4.js → chunk-YHRESVJ7.js} +9 -3
- package/dist/safe-bash/command-chunks/{chunk-UWIDPTOB.js → chunk-YSCKOUQP.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-UYNJF5QN.js → chunk-ZALAWNOE.js} +76 -122
- package/dist/safe-bash/command-chunks/{chunk-OT75C5YS.js → chunk-ZYXKW2K7.js} +1 -1
- package/dist/safe-bash/command-chunks/{pdf-renderer-346WYKSZ.js → pdf-renderer-5QWOVFA4.js} +1 -1
- package/dist/safe-bash/command-chunks/{prompt-tool-debug-3POFNRYP.js → prompt-tool-debug-G7ATE7D5.js} +6 -4
- package/dist/safe-bash/commands/llm/index.browser.js +5 -1
- package/dist/safe-bash/commands/llm/index.js +1 -1
- package/dist/safe-bash/commands/python/executor.browser.js +3 -1
- package/dist/safe-bash/commands/python/executor.js +1 -1
- package/dist/safe-bash/commands/python/index.browser.js +5 -1
- package/dist/safe-bash/commands/python/index.js +1 -1
- package/dist/safe-bash/core.browser.js +2 -2
- package/dist/safe-bash/full-core.browser.js +10 -2
- package/dist/safe-bash-command-awk/awk-runtime.js +2 -2
- package/dist/safe-bash-command-awk/awk-syntax.js +1 -1
- package/dist/safe-bash-command-awk/awk.js +3 -3
- package/dist/safe-bash-command-awk/index.js +3 -3
- package/dist/safe-bash-command-gpg/index.js +11 -3
- package/dist/safe-bash-command-imagemagick/index.js +2 -2
- package/dist/safe-bash-command-llm/collections.js +6 -4
- package/dist/safe-bash-command-llm/command.js +4 -4
- package/dist/safe-bash-command-llm/import-json-document.d.ts +9 -2
- package/dist/safe-bash-command-llm/index.d.ts +2 -1
- package/dist/safe-bash-command-llm/index.js +10 -4
- package/dist/safe-bash-command-llm/loader-provider.d.ts +5 -0
- package/dist/safe-bash-command-mcp/index.js +10 -13
- package/dist/safe-bash-command-pdftoppm/index.js +2 -2
- package/dist/safe-bash-command-playwright-cli/index.js +2 -2
- package/dist/safe-bash-command-playwright-cli/playwright/ability-execution.d.ts +1 -0
- package/dist/safe-bash-command-playwright-cli/playwright/ability-execution.js +1 -1
- package/dist/safe-bash-command-playwright-cli/playwright/controller.d.ts +2 -0
- package/dist/safe-bash-command-playwright-cli/playwright/controller.js +2 -2
- package/dist/safe-bash-command-playwright-cli/playwright/index.js +2 -2
- package/dist/safe-bash-command-python/build-backend.d.ts +2 -0
- package/dist/safe-bash-command-python/cache.d.ts +1 -1
- package/dist/safe-bash-command-python/executor.d.ts +5 -2
- package/dist/safe-bash-command-python/executor.js +11 -6
- package/dist/safe-bash-command-python/host-capabilities.js +1 -1
- package/dist/safe-bash-command-python/index.js +11 -6
- package/dist/safe-bash-command-python/jspi.js +5 -3
- package/dist/safe-bash-command-python/manifest-file.d.ts +44 -0
- package/dist/safe-bash-command-python/manifest.d.ts +45 -0
- package/dist/safe-bash-command-python/provisioning.d.ts +20 -1
- package/dist/safe-bash-command-python/provisioning.js +3 -2
- package/dist/safe-bash-command-python/reply.js +7 -11
- package/dist/safe-bash-command-python/source-archive.js +2 -2
- package/dist/safe-bash-command-python/source-zip.js +2 -2
- package/dist/safe-bash-command-python/worker.js +34 -21
- package/dist/safe-bash-command-sqlite3/engine.d.ts +4 -0
- package/dist/safe-bash-command-sqlite3/index.js +174 -18
- package/dist/safe-bash-command-svgo/index.js +1 -1
- package/dist/safe-bash-command-tar/create.js +3 -3
- package/dist/safe-bash-command-tar/extract.js +3 -3
- package/dist/safe-bash-command-tar/index.js +5 -5
- package/dist/safe-bash-command-tar/modes.js +5 -5
- package/dist/safe-bash-command-tar/options.d.ts +1 -1
- package/dist/safe-bash-command-tar/options.js +1 -1
- package/dist/safe-bash-command-tar/stream.js +1 -1
- package/dist/safe-bash-command-wkhtmltopdf/index.js +1 -1
- package/dist/safe-bash-command-xan/argv.js +1 -1
- package/dist/safe-bash-command-xan/commands.js +3 -3
- package/dist/safe-bash-command-xan/index.js +3 -3
- package/dist/safe-bash-command-xan/io.js +2 -2
- package/dist/safe-bash-compression-engine/bounded-codec.js +3 -3
- package/dist/safe-bash-compression-engine/codec-loader.js +2 -2
- package/dist/safe-bash-compression-engine/files.js +6 -6
- package/dist/safe-bash-compression-engine/index.js +5 -5
- package/dist/safe-bash-compression-engine/operand.js +6 -6
- package/dist/safe-bash-compression-engine/options.js +1 -1
- package/dist/safe-bash-compression-engine/stream.js +5 -5
- package/dist/safe-bash-compression-engine/zstd-decode.js +4 -4
- package/dist/safe-bash-contracts/filesystem-descriptor.js +1 -1
- package/dist/safe-bash-contracts/filesystem-output.js +1 -1
- package/dist/safe-bash-csv-engine/index.js +6 -6
- package/dist/safe-bash-csv-engine/python-codec-aliases.js +1 -1
- package/dist/safe-bash-csv-engine/python-codepages.js +3 -3
- package/dist/safe-bash-csv-engine/python-file-codepages.js +2 -2
- package/dist/safe-bash-csv-engine/python-utf16.js +4 -4
- package/dist/safe-bash-csv-engine/text-decoder.js +6 -6
- package/dist/safe-bash-graphviz-engine/index.js +1 -1
- package/dist/safe-bash-pager-engine/index.js +2 -2
- package/dist/safe-bash-query-engine/capture.js +3 -3
- package/dist/safe-bash-query-engine/delpaths.js +3 -3
- package/dist/safe-bash-query-engine/formats.js +2 -2
- package/dist/safe-bash-query-engine/index.js +10 -10
- package/dist/safe-bash-query-engine/indices.js +3 -3
- package/dist/safe-bash-query-engine/input.d.ts +3 -3
- package/dist/safe-bash-query-engine/input.js +1 -1
- package/dist/safe-bash-query-engine/interpreter.js +9 -9
- package/dist/safe-bash-query-engine/query-core.js +10 -10
- package/dist/safe-bash-query-engine/regex.js +4 -4
- package/dist/safe-bash-query-engine/splits.js +5 -5
- package/dist/safe-bash-query-engine/values.js +2 -2
- package/package.json +2 -2
- package/dist/safe-bash/command-chunks/chunk-OOYVZAWL.js +0 -90
- package/dist/safe-bash/command-chunks/chunk-RZOHZGEZ.js +0 -772
- package/dist/safe-bash/command-chunks/chunk-WIUEM7HP.js +0 -58
- package/dist/safe-bash/command-chunks/chunk-WY6THI6J.js +0 -673
- 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-
|
|
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-
|
|
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-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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, -
|
|
124
|
-
--
|
|
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
|
|
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 === "
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
for
|
|
354
|
-
send('
|
|
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 (
|
|
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
|
-
|
|
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
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
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
|
|
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
|
-
|
|
660
|
-
|
|
661
|
-
|
|
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",
|
|
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,
|
|
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/
|
|
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
|
|
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
|
|
1264
|
-
|
|
1265
|
-
|
|
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 (
|
|
1473
|
-
|
|
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 &&
|
|
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
|
|
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
|
|
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 =
|
|
2337
|
-
await
|
|
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(
|
|
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 =
|
|
2425
|
-
await
|
|
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
|
|
2196
|
+
throw diagnose(reason instanceof PythonFailure ? reason.category : "startup", reason);
|
|
2494
2197
|
}
|
|
2495
|
-
if (!executor || typeof executor.run !== "function" || typeof executor.terminate !== "function") throw
|
|
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
|
|
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
|
|
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(
|
|
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
|
|
2252
|
+
throw diagnose(reason instanceof PythonFailure ? reason.category : ready ? "runtime" : "startup", reason);
|
|
2550
2253
|
}).then((status) => {
|
|
2551
2254
|
running = false;
|
|
2552
|
-
if (requesting) throw
|
|
2255
|
+
if (requesting) throw diagnose("transport-unavailable", void 0);
|
|
2553
2256
|
try {
|
|
2554
2257
|
return validateExitCode(status);
|
|
2555
2258
|
} catch (reason) {
|
|
2556
|
-
throw
|
|
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
|
|
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
|
|
2298
|
+
throw diagnose("transport-unavailable", reason);
|
|
2596
2299
|
}
|
|
2597
2300
|
};
|
|
2598
2301
|
try {
|
|
2599
2302
|
endpoint = options.createWorker();
|
|
2600
2303
|
} catch (reason) {
|
|
2601
|
-
throw
|
|
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(
|
|
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(
|
|
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 =
|
|
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
|
|
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:
|
|
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
|
|
2428
|
+
await writeDiagnostic(context.stderr, failure.message, context.signal);
|
|
2726
2429
|
return { exitCode: 1 };
|
|
2727
2430
|
}
|
|
2728
2431
|
return { exitCode: result };
|