Unverified Commit 4950fede authored by Timothy Jaeryang Baek's avatar Timothy Jaeryang Baek Committed by GitHub
Browse files

Merge pull request #2325 from open-webui/pyscript

feat: python code execution
parents 7db4baef 18a7634f
...@@ -117,6 +117,18 @@ app.state.config.WEBHOOK_URL = WEBHOOK_URL ...@@ -117,6 +117,18 @@ app.state.config.WEBHOOK_URL = WEBHOOK_URL
origins = ["*"] origins = ["*"]
# Custom middleware to add security headers
class SecurityHeadersMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request: Request, call_next):
response: Response = await call_next(request)
response.headers["Cross-Origin-Opener-Policy"] = "same-origin"
response.headers["Cross-Origin-Embedder-Policy"] = "require-corp"
return response
app.add_middleware(SecurityHeadersMiddleware)
class RAGMiddleware(BaseHTTPMiddleware): class RAGMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request: Request, call_next): async def dispatch(self, request: Request, call_next):
return_citations = False return_citations = False
......
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
"name": "open-webui", "name": "open-webui",
"version": "0.1.124", "version": "0.1.124",
"dependencies": { "dependencies": {
"@micropython/micropython-webassembly-pyscript": "^1.22.0-369",
"@pyscript/core": "^0.4.32",
"@sveltejs/adapter-node": "^1.3.1", "@sveltejs/adapter-node": "^1.3.1",
"async": "^3.2.5", "async": "^3.2.5",
"bits-ui": "^0.19.7", "bits-ui": "^0.19.7",
...@@ -22,6 +24,7 @@ ...@@ -22,6 +24,7 @@
"js-sha256": "^0.10.1", "js-sha256": "^0.10.1",
"katex": "^0.16.9", "katex": "^0.16.9",
"marked": "^9.1.0", "marked": "^9.1.0",
"pyodide": "^0.25.1",
"svelte-sonner": "^0.3.19", "svelte-sonner": "^0.3.19",
"tippy.js": "^6.3.7", "tippy.js": "^6.3.7",
"uuid": "^9.0.1" "uuid": "^9.0.1"
...@@ -831,6 +834,11 @@ ...@@ -831,6 +834,11 @@
"svelte": ">=3 <5" "svelte": ">=3 <5"
} }
}, },
"node_modules/@micropython/micropython-webassembly-pyscript": {
"version": "1.22.0-369",
"resolved": "https://registry.npmjs.org/@micropython/micropython-webassembly-pyscript/-/micropython-webassembly-pyscript-1.22.0-369.tgz",
"integrity": "sha512-+wqB6Va0rJtWXUmkthPVIEh1+Xh9Q+eJlBKWgYjjSe/FaRYo9z9U7CbvLaJNOJrb5R9dCTI6P9Ij4BrBxnwyVQ=="
},
"node_modules/@nodelib/fs.scandir": { "node_modules/@nodelib/fs.scandir": {
"version": "2.1.5", "version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
...@@ -890,6 +898,19 @@ ...@@ -890,6 +898,19 @@
"url": "https://opencollective.com/popperjs" "url": "https://opencollective.com/popperjs"
} }
}, },
"node_modules/@pyscript/core": {
"version": "0.4.32",
"resolved": "https://registry.npmjs.org/@pyscript/core/-/core-0.4.32.tgz",
"integrity": "sha512-WQATzPp1ggf871+PukCmTypzScXkEB1EWD/vg5GNxpM96N6rDPqQ13msuA5XvwU01ZVhL8HHSFDLk4IfaXNGWg==",
"dependencies": {
"@ungap/with-resolvers": "^0.1.0",
"basic-devtools": "^0.1.6",
"polyscript": "^0.12.8",
"sticky-module": "^0.1.1",
"to-json-callback": "^0.1.1",
"type-checked-collections": "^0.1.7"
}
},
"node_modules/@rollup/plugin-commonjs": { "node_modules/@rollup/plugin-commonjs": {
"version": "25.0.7", "version": "25.0.7",
"resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-25.0.7.tgz", "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-25.0.7.tgz",
...@@ -1605,8 +1626,12 @@ ...@@ -1605,8 +1626,12 @@
"node_modules/@ungap/structured-clone": { "node_modules/@ungap/structured-clone": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
"integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ=="
"dev": true },
"node_modules/@ungap/with-resolvers": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/@ungap/with-resolvers/-/with-resolvers-0.1.0.tgz",
"integrity": "sha512-g7f0IkJdPW2xhY7H4iE72DAsIyfuwEFc6JWc2tYFwKDMWWAF699vGjrM348cwQuOXgHpe1gWFe+Eiyjx/ewvvw=="
}, },
"node_modules/@vitest/expect": { "node_modules/@vitest/expect": {
"version": "1.6.0", "version": "1.6.0",
...@@ -1713,6 +1738,11 @@ ...@@ -1713,6 +1738,11 @@
"@types/estree": "^1.0.0" "@types/estree": "^1.0.0"
} }
}, },
"node_modules/@webreflection/fetch": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/@webreflection/fetch/-/fetch-0.1.5.tgz",
"integrity": "sha512-zCcqCJoNLvdeF41asAK71XPlwSPieeRDsE09albBunJEksuYPYNillKNQjf8p5BqSoTKTuKrW3lUm3MNodUC4g=="
},
"node_modules/acorn": { "node_modules/acorn": {
"version": "8.11.3", "version": "8.11.3",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
...@@ -2027,6 +2057,11 @@ ...@@ -2027,6 +2057,11 @@
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"node_modules/base-64": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/base-64/-/base-64-1.0.0.tgz",
"integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg=="
},
"node_modules/base64-js": { "node_modules/base64-js": {
"version": "1.5.1", "version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
...@@ -2047,6 +2082,11 @@ ...@@ -2047,6 +2082,11 @@
} }
] ]
}, },
"node_modules/basic-devtools": {
"version": "0.1.6",
"resolved": "https://registry.npmjs.org/basic-devtools/-/basic-devtools-0.1.6.tgz",
"integrity": "sha512-g9zJ63GmdUesS3/Fwv0B5SYX6nR56TQXmGr+wE5PRTNCnGQMYWhUx/nZB/mMWnQJVLPPAp89oxDNlasdtNkW5Q=="
},
"node_modules/bcrypt-pbkdf": { "node_modules/bcrypt-pbkdf": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
...@@ -2661,6 +2701,28 @@ ...@@ -2661,6 +2701,28 @@
"@types/estree": "^1.0.0" "@types/estree": "^1.0.0"
} }
}, },
"node_modules/codedent": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/codedent/-/codedent-0.1.2.tgz",
"integrity": "sha512-qEqzcy5viM3UoCN0jYHZeXZoyd4NZQzYFg0kOBj8O1CgoGG9WYYTF+VeQRsN0OSKFjF3G1u4WDUOtOsWEx6N2w==",
"dependencies": {
"plain-tag": "^0.1.3"
}
},
"node_modules/coincident": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/coincident/-/coincident-1.2.3.tgz",
"integrity": "sha512-Uxz3BMTWIslzeWjuQnizGWVg0j6khbvHUQ8+5BdM7WuJEm4ALXwq3wluYoB+uF68uPBz/oUOeJnYURKyfjexlA==",
"dependencies": {
"@ungap/structured-clone": "^1.2.0",
"@ungap/with-resolvers": "^0.1.0",
"gc-hook": "^0.3.1",
"proxy-target": "^3.0.2"
},
"optionalDependencies": {
"ws": "^8.16.0"
}
},
"node_modules/color-convert": { "node_modules/color-convert": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
...@@ -4001,6 +4063,11 @@ ...@@ -4001,6 +4063,11 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/gc-hook": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/gc-hook/-/gc-hook-0.3.1.tgz",
"integrity": "sha512-E5M+O/h2o7eZzGhzRZGex6hbB3k4NWqO0eA+OzLRLXxhdbYPajZnynPwAtphnh+cRHPwsj5Z80dqZlfI4eK55A=="
},
"node_modules/get-func-name": { "node_modules/get-func-name": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz",
...@@ -4328,6 +4395,11 @@ ...@@ -4328,6 +4395,11 @@
"node": ">=12.0.0" "node": ">=12.0.0"
} }
}, },
"node_modules/html-escaper": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-3.0.3.tgz",
"integrity": "sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ=="
},
"node_modules/htmlparser2": { "node_modules/htmlparser2": {
"version": "8.0.2", "version": "8.0.2",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz",
...@@ -5838,6 +5910,29 @@ ...@@ -5838,6 +5910,29 @@
"pathe": "^1.1.2" "pathe": "^1.1.2"
} }
}, },
"node_modules/plain-tag": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/plain-tag/-/plain-tag-0.1.3.tgz",
"integrity": "sha512-yyVAOFKTAElc7KdLt2+UKGExNYwYb/Y/WE9i+1ezCQsJE8gbKSjewfpRqK2nQgZ4d4hhAAGgDCOcIZVilqE5UA=="
},
"node_modules/polyscript": {
"version": "0.12.8",
"resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.12.8.tgz",
"integrity": "sha512-kcG3W9jU/s1sYjWOTAa2jAh5D2jm3zJRi+glSTsC+lA3D1b/Sd67pEIGpyL9bWNKYSimqAx4se6jAhQjJZ7+jQ==",
"dependencies": {
"@ungap/structured-clone": "^1.2.0",
"@ungap/with-resolvers": "^0.1.0",
"@webreflection/fetch": "^0.1.5",
"basic-devtools": "^0.1.6",
"codedent": "^0.1.2",
"coincident": "^1.2.3",
"gc-hook": "^0.3.1",
"html-escaper": "^3.0.3",
"proxy-target": "^3.0.2",
"sticky-module": "^0.1.1",
"to-json-callback": "^0.1.1"
}
},
"node_modules/postcss": { "node_modules/postcss": {
"version": "8.4.38", "version": "8.4.38",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz",
...@@ -6151,6 +6246,11 @@ ...@@ -6151,6 +6246,11 @@
"integrity": "sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A==", "integrity": "sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A==",
"dev": true "dev": true
}, },
"node_modules/proxy-target": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/proxy-target/-/proxy-target-3.0.2.tgz",
"integrity": "sha512-FFE1XNwXX/FNC3/P8HiKaJSy/Qk68RitG/QEcLy/bVnTAPlgTAWPZKh0pARLAnpfXQPKyalBhk009NRTgsk8vQ=="
},
"node_modules/psl": { "node_modules/psl": {
"version": "1.9.0", "version": "1.9.0",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
...@@ -6176,6 +6276,15 @@ ...@@ -6176,6 +6276,15 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/pyodide": {
"version": "0.25.1",
"resolved": "https://registry.npmjs.org/pyodide/-/pyodide-0.25.1.tgz",
"integrity": "sha512-y0nJ/fLA3bxD2iZRzvVTbP2O+wp4Ewm2wThfV4HF0BytQ6hsoqTJFLNY4usLOcCVBrK8TTWqFqrmsVPzHe4rsw==",
"dependencies": {
"base-64": "^1.0.0",
"ws": "^8.5.0"
}
},
"node_modules/qs": { "node_modules/qs": {
"version": "6.10.4", "version": "6.10.4",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.10.4.tgz", "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.4.tgz",
...@@ -6858,6 +6967,11 @@ ...@@ -6858,6 +6967,11 @@
"integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==", "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==",
"dev": true "dev": true
}, },
"node_modules/sticky-module": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/sticky-module/-/sticky-module-0.1.1.tgz",
"integrity": "sha512-IuYgnyIMUx/m6rtu14l/LR2MaqOLtpXcWkxPmtPsiScRHEo+S4Tojk+DWFHOncSdFX/OsoLOM4+T92yOmI1AMw=="
},
"node_modules/stream-composer": { "node_modules/stream-composer": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/stream-composer/-/stream-composer-1.0.2.tgz", "resolved": "https://registry.npmjs.org/stream-composer/-/stream-composer-1.0.2.tgz",
...@@ -7520,6 +7634,11 @@ ...@@ -7520,6 +7634,11 @@
"node": ">=14.14" "node": ">=14.14"
} }
}, },
"node_modules/to-json-callback": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/to-json-callback/-/to-json-callback-0.1.1.tgz",
"integrity": "sha512-BzOeinTT3NjE+FJ2iCvWB8HvyuyBzoH3WlSnJ+AYVC4tlePyZWSYdkQIFOARWiq0t35/XhmI0uQsFiUsRksRqg=="
},
"node_modules/to-regex-range": { "node_modules/to-regex-range": {
"version": "5.0.1", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
...@@ -7629,6 +7748,11 @@ ...@@ -7629,6 +7748,11 @@
"node": ">= 0.8.0" "node": ">= 0.8.0"
} }
}, },
"node_modules/type-checked-collections": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/type-checked-collections/-/type-checked-collections-0.1.7.tgz",
"integrity": "sha512-fLIydlJy7IG9XL4wjRwEcKhxx/ekLXiWiMvcGo01cOMF+TN+5ZqajM1mRNRz2bNNi1bzou2yofhjZEQi7kgl9A=="
},
"node_modules/type-detect": { "node_modules/type-detect": {
"version": "4.0.8", "version": "4.0.8",
"resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
...@@ -8883,6 +9007,26 @@ ...@@ -8883,6 +9007,26 @@
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
}, },
"node_modules/ws": {
"version": "8.17.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.17.0.tgz",
"integrity": "sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==",
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": ">=5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
}
},
"node_modules/xtend": { "node_modules/xtend": {
"version": "4.0.2", "version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
......
...@@ -47,6 +47,8 @@ ...@@ -47,6 +47,8 @@
}, },
"type": "module", "type": "module",
"dependencies": { "dependencies": {
"@micropython/micropython-webassembly-pyscript": "^1.22.0-369",
"@pyscript/core": "^0.4.32",
"@sveltejs/adapter-node": "^1.3.1", "@sveltejs/adapter-node": "^1.3.1",
"async": "^3.2.5", "async": "^3.2.5",
"bits-ui": "^0.19.7", "bits-ui": "^0.19.7",
...@@ -61,6 +63,7 @@ ...@@ -61,6 +63,7 @@
"js-sha256": "^0.10.1", "js-sha256": "^0.10.1",
"katex": "^0.16.9", "katex": "^0.16.9",
"marked": "^9.1.0", "marked": "^9.1.0",
"pyodide": "^0.25.1",
"svelte-sonner": "^0.3.19", "svelte-sonner": "^0.3.19",
"tippy.js": "^6.3.7", "tippy.js": "^6.3.7",
"uuid": "^9.0.1" "uuid": "^9.0.1"
......
cp -R ./node_modules/@pyscript/core/dist ./static/pyscript
# mkdir -p ./static/micropython
# cp -R ./node_modules/@micropython/micropython-webassembly-pyscript/micropython.* ./static/micropython
mkdir -p ./static/pyodide
cp ./node_modules/pyodide/pyodide* ./static/pyodide/
cp ./node_modules/pyodide/python_stdlib.zip ./static/pyodide/
\ No newline at end of file
function execute(id, text) {
// pyscript
let div = document.createElement('div');
let html = `
<py-script type="mpy">
${text}
</py-script>
`;
div.innerHTML = html;
const pyScript = div.firstElementChild;
try {
document.body.appendChild(pyScript);
setTimeout(() => {
document.body.removeChild(pyScript);
}, 0);
} catch (error) {
console.error('Python error:');
console.error(error);
}
}
...@@ -12,6 +12,10 @@ ...@@ -12,6 +12,10 @@
title="Open WebUI" title="Open WebUI"
href="/opensearch.xml" href="/opensearch.xml"
/> />
<script type="module" src="/pyscript/core.js"></script>
<link rel="stylesheet" href="/pyscript/core.css" />
<script> <script>
// On page load or when changing themes, best to add inline in `head` to avoid FOUC // On page load or when changing themes, best to add inline in `head` to avoid FOUC
(() => { (() => {
...@@ -54,6 +58,11 @@ ...@@ -54,6 +58,11 @@
%sveltekit.head% %sveltekit.head%
</head> </head>
<body data-sveltekit-preload-data="hover"> <body data-sveltekit-preload-data="hover">
<py-config> interpreter = "/pyodide/pyodide.mjs" </py-config>
<script type="py">
print('pyscript:loaded')
</script>
<div style="display: contents">%sveltekit.body%</div> <div style="display: contents">%sveltekit.body%</div>
<div <div
......
...@@ -506,6 +506,7 @@ ...@@ -506,6 +506,7 @@
> >
<div class="flex items-center gap-2 text-sm dark:text-gray-500"> <div class="flex items-center gap-2 text-sm dark:text-gray-500">
<img <img
crossorigin="anonymous"
alt="model profile" alt="model profile"
class="size-5 max-w-[28px] object-cover rounded-full" class="size-5 max-w-[28px] object-cover rounded-full"
src={$modelfiles.find((modelfile) => modelfile.tagName === selectedModel.id) src={$modelfiles.find((modelfile) => modelfile.tagName === selectedModel.id)
......
...@@ -2,10 +2,14 @@ ...@@ -2,10 +2,14 @@
import { copyToClipboard } from '$lib/utils'; import { copyToClipboard } from '$lib/utils';
import hljs from 'highlight.js'; import hljs from 'highlight.js';
import 'highlight.js/styles/github-dark.min.css'; import 'highlight.js/styles/github-dark.min.css';
import { tick } from 'svelte';
export let id = '';
export let lang = ''; export let lang = '';
export let code = ''; export let code = '';
let executed = false;
let copied = false; let copied = false;
const copyCode = async () => { const copyCode = async () => {
...@@ -17,6 +21,184 @@ ...@@ -17,6 +21,184 @@
}, 1000); }, 1000);
}; };
const checkPythonCode = (str) => {
// Check if the string contains typical Python keywords, syntax, or functions
const pythonKeywords = [
'def',
'class',
'import',
'from',
'if',
'else',
'elif',
'for',
'while',
'try',
'except',
'finally',
'return',
'yield',
'lambda',
'assert',
'pass',
'break',
'continue',
'global',
'nonlocal',
'del',
'True',
'False',
'None',
'and',
'or',
'not',
'in',
'is',
'as',
'with'
];
for (let keyword of pythonKeywords) {
if (str.includes(keyword)) {
return true;
}
}
// Check if the string contains typical Python syntax characters
const pythonSyntax = [
'def ',
'class ',
'import ',
'from ',
'if ',
'else:',
'elif ',
'for ',
'while ',
'try:',
'except:',
'finally:',
'return ',
'yield ',
'lambda ',
'assert ',
'pass',
'break',
'continue',
'global ',
'nonlocal ',
'del ',
'True',
'False',
'None',
' and ',
' or ',
' not ',
' in ',
' is ',
' as ',
' with ',
':',
'=',
'==',
'!=',
'>',
'<',
'>=',
'<=',
'+',
'-',
'*',
'/',
'%',
'**',
'//',
'(',
')',
'[',
']',
'{',
'}'
];
for (let syntax of pythonSyntax) {
if (str.includes(syntax)) {
return true;
}
}
// If none of the above conditions met, it's probably not Python code
return false;
};
const executePython = async (text) => {
executed = true;
await tick();
const outputDiv = document.getElementById(`code-output-${id}`);
if (outputDiv) {
outputDiv.innerText = 'Running...';
}
text = text
.split('\n')
.map((line, index) => (index === 0 ? line : ' ' + line))
.join('\n');
// pyscript
let div = document.createElement('div');
let html = `
<py-script type="py" worker>
import js
import sys
import io
# Create a StringIO object to capture the output
output_capture = io.StringIO()
# Save the current standard output
original_stdout = sys.stdout
# Replace the standard output with the StringIO object
sys.stdout = output_capture
try:
${text}
except Exception as e:
# Capture any errors and write them to the output capture
print(f"Error: {e}", file=output_capture)
# Restore the original standard output
sys.stdout = original_stdout
# Retrieve the captured output
captured_output = "[NO OUTPUT]"
captured_output = output_capture.getvalue()
# Print the captured output
print(captured_output)
def display_message():
output_div = js.document.getElementById("code-output-${id}")
output_div.innerText = captured_output
display_message()
</py-script>`;
div.innerHTML = html;
const pyScript = div.firstElementChild;
try {
document.body.appendChild(pyScript);
setTimeout(() => {
document.body.removeChild(pyScript);
}, 0);
} catch (error) {
console.error('Python error:');
console.error(error);
}
};
$: highlightedCode = code ? hljs.highlightAuto(code, hljs.getLanguage(lang)?.aliases).value : ''; $: highlightedCode = code ? hljs.highlightAuto(code, hljs.getLanguage(lang)?.aliases).value : '';
</script> </script>
...@@ -26,15 +208,34 @@ ...@@ -26,15 +208,34 @@
class="flex justify-between bg-[#202123] text-white text-xs px-4 pt-1 pb-0.5 rounded-t-lg overflow-x-auto" class="flex justify-between bg-[#202123] text-white text-xs px-4 pt-1 pb-0.5 rounded-t-lg overflow-x-auto"
> >
<div class="p-1">{@html lang}</div> <div class="p-1">{@html lang}</div>
<button class="copy-code-button bg-none border-none p-1" on:click={copyCode}
>{copied ? 'Copied' : 'Copy Code'}</button <div class="flex items-center">
> {#if lang === 'python' || checkPythonCode(code)}
<button
class="copy-code-button bg-none border-none p-1"
on:click={() => {
executePython(code);
}}>Run</button
>
{/if}
<button class="copy-code-button bg-none border-none p-1" on:click={copyCode}
>{copied ? 'Copied' : 'Copy Code'}</button
>
</div>
</div> </div>
<pre <pre
class=" hljs p-4 px-5 overflow-x-auto" class=" hljs p-4 px-5 overflow-x-auto"
style="border-top-left-radius: 0px; border-top-right-radius: 0px;"><code style="border-top-left-radius: 0px; border-top-right-radius: 0px; {executed &&
'border-bottom-left-radius: 0px; border-bottom-right-radius: 0px;'}"><code
class="language-{lang} rounded-t-none whitespace-pre">{@html highlightedCode || code}</code class="language-{lang} rounded-t-none whitespace-pre">{@html highlightedCode || code}</code
></pre> ></pre>
{#if executed}
<div class="bg-[#202123] text-white px-4 py-4 rounded-b-lg">
<div class=" text-gray-500 text-xs mb-1">STDOUT/STDERR</div>
<div id="code-output-{id}" class="text-sm" />
</div>
{/if}
</div> </div>
{/if} {/if}
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
> >
{#if model in modelfiles} {#if model in modelfiles}
<img <img
crossorigin="anonymous"
src={modelfiles[model]?.imageUrl ?? `${WEBUI_BASE_URL}/static/favicon.png`} src={modelfiles[model]?.imageUrl ?? `${WEBUI_BASE_URL}/static/favicon.png`}
alt="modelfile" alt="modelfile"
class=" size-[2.7rem] rounded-full border-[1px] border-gray-200 dark:border-none" class=" size-[2.7rem] rounded-full border-[1px] border-gray-200 dark:border-none"
...@@ -50,6 +51,7 @@ ...@@ -50,6 +51,7 @@
/> />
{:else} {:else}
<img <img
crossorigin="anonymous"
src={$i18n.language === 'dg-DG' src={$i18n.language === 'dg-DG'
? `/doge.png` ? `/doge.png`
: `${WEBUI_BASE_URL}/static/favicon.png`} : `${WEBUI_BASE_URL}/static/favicon.png`}
......
...@@ -3,5 +3,11 @@ ...@@ -3,5 +3,11 @@
</script> </script>
<div class=" mr-3"> <div class=" mr-3">
<img {src} class=" w-8 object-cover rounded-full" alt="profile" draggable="false" /> <img
crossorigin="anonymous"
{src}
class=" w-8 object-cover rounded-full"
alt="profile"
draggable="false"
/>
</div> </div>
...@@ -437,6 +437,7 @@ ...@@ -437,6 +437,7 @@
{#each tokens as token} {#each tokens as token}
{#if token.type === 'code'} {#if token.type === 'code'}
<CodeBlock <CodeBlock
id={message.id}
lang={token.lang} lang={token.lang}
code={revertSanitizedResponseContent(token.text)} code={revertSanitizedResponseContent(token.text)}
/> />
......
...@@ -248,6 +248,7 @@ ...@@ -248,6 +248,7 @@
> >
<div class="self-center mx-1.5"> <div class="self-center mx-1.5">
<img <img
crossorigin="anonymous"
src="{WEBUI_BASE_URL}/static/favicon.png" src="{WEBUI_BASE_URL}/static/favicon.png"
class=" size-6 -translate-x-1.5 rounded-full" class=" size-6 -translate-x-1.5 rounded-full"
alt="logo" alt="logo"
......
...@@ -89,7 +89,7 @@ ...@@ -89,7 +89,7 @@
<svelte:head> <svelte:head>
<title>{$WEBUI_NAME}</title> <title>{$WEBUI_NAME}</title>
<link rel="icon" href="{WEBUI_BASE_URL}/static/favicon.png" /> <link crossorigin="anonymous" rel="icon" href="{WEBUI_BASE_URL}/static/favicon.png" />
<!-- rosepine themes have been disabled as it's not up to date with our latest version. --> <!-- rosepine themes have been disabled as it's not up to date with our latest version. -->
<!-- feel free to make a PR to fix if anyone wants to see it return --> <!-- feel free to make a PR to fix if anyone wants to see it return -->
......
...@@ -76,7 +76,12 @@ ...@@ -76,7 +76,12 @@
<div class="fixed m-10 z-50"> <div class="fixed m-10 z-50">
<div class="flex space-x-2"> <div class="flex space-x-2">
<div class=" self-center"> <div class=" self-center">
<img src="{WEBUI_BASE_URL}/static/favicon.png" class=" w-8 rounded-full" alt="logo" /> <img
crossorigin="anonymous"
src="{WEBUI_BASE_URL}/static/favicon.png"
class=" w-8 rounded-full"
alt="logo"
/>
</div> </div>
</div> </div>
</div> </div>
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
"use strict";var loadPyodide=(()=>{var ce=Object.create;var _=Object.defineProperty;var le=Object.getOwnPropertyDescriptor;var de=Object.getOwnPropertyNames;var fe=Object.getPrototypeOf,ue=Object.prototype.hasOwnProperty;var f=(t,e)=>_(t,"name",{value:e,configurable:!0}),g=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(e,c)=>(typeof require<"u"?require:e)[c]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw new Error('Dynamic require of "'+t+'" is not supported')});var $=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports),pe=(t,e)=>{for(var c in e)_(t,c,{get:e[c],enumerable:!0})},M=(t,e,c,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let a of de(e))!ue.call(t,a)&&a!==c&&_(t,a,{get:()=>e[a],enumerable:!(o=le(e,a))||o.enumerable});return t};var h=(t,e,c)=>(c=t!=null?ce(fe(t)):{},M(e||!t||!t.__esModule?_(c,"default",{value:t,enumerable:!0}):c,t)),me=t=>M(_({},"__esModule",{value:!0}),t);var j=$((P,C)=>{(function(t,e){"use strict";typeof define=="function"&&define.amd?define("stackframe",[],e):typeof P=="object"?C.exports=e():t.StackFrame=e()})(P,function(){"use strict";function t(d){return!isNaN(parseFloat(d))&&isFinite(d)}f(t,"_isNumber");function e(d){return d.charAt(0).toUpperCase()+d.substring(1)}f(e,"_capitalize");function c(d){return function(){return this[d]}}f(c,"_getter");var o=["isConstructor","isEval","isNative","isToplevel"],a=["columnNumber","lineNumber"],r=["fileName","functionName","source"],n=["args"],u=["evalOrigin"],i=o.concat(a,r,n,u);function s(d){if(d)for(var y=0;y<i.length;y++)d[i[y]]!==void 0&&this["set"+e(i[y])](d[i[y]])}f(s,"StackFrame"),s.prototype={getArgs:function(){return this.args},setArgs:function(d){if(Object.prototype.toString.call(d)!=="[object Array]")throw new TypeError("Args must be an Array");this.args=d},getEvalOrigin:function(){return this.evalOrigin},setEvalOrigin:function(d){if(d instanceof s)this.evalOrigin=d;else if(d instanceof Object)this.evalOrigin=new s(d);else throw new TypeError("Eval Origin must be an Object or StackFrame")},toString:function(){var d=this.getFileName()||"",y=this.getLineNumber()||"",w=this.getColumnNumber()||"",E=this.getFunctionName()||"";return this.getIsEval()?d?"[eval] ("+d+":"+y+":"+w+")":"[eval]:"+y+":"+w:E?E+" ("+d+":"+y+":"+w+")":d+":"+y+":"+w}},s.fromString=f(function(y){var w=y.indexOf("("),E=y.lastIndexOf(")"),ne=y.substring(0,w),ie=y.substring(w+1,E).split(","),U=y.substring(E+1);if(U.indexOf("@")===0)var R=/@(.+?)(?::(\d+))?(?::(\d+))?$/.exec(U,""),oe=R[1],ae=R[2],se=R[3];return new s({functionName:ne,args:ie||void 0,fileName:oe,lineNumber:ae||void 0,columnNumber:se||void 0})},"StackFrame$$fromString");for(var l=0;l<o.length;l++)s.prototype["get"+e(o[l])]=c(o[l]),s.prototype["set"+e(o[l])]=function(d){return function(y){this[d]=!!y}}(o[l]);for(var m=0;m<a.length;m++)s.prototype["get"+e(a[m])]=c(a[m]),s.prototype["set"+e(a[m])]=function(d){return function(y){if(!t(y))throw new TypeError(d+" must be a Number");this[d]=Number(y)}}(a[m]);for(var p=0;p<r.length;p++)s.prototype["get"+e(r[p])]=c(r[p]),s.prototype["set"+e(r[p])]=function(d){return function(y){this[d]=String(y)}}(r[p]);return s})});var W=$((x,B)=>{(function(t,e){"use strict";typeof define=="function"&&define.amd?define("error-stack-parser",["stackframe"],e):typeof x=="object"?B.exports=e(j()):t.ErrorStackParser=e(t.StackFrame)})(x,f(function(e){"use strict";var c=/(^|@)\S+:\d+/,o=/^\s*at .*(\S+:\d+|\(native\))/m,a=/^(eval@)?(\[native code])?$/;return{parse:f(function(n){if(typeof n.stacktrace<"u"||typeof n["opera#sourceloc"]<"u")return this.parseOpera(n);if(n.stack&&n.stack.match(o))return this.parseV8OrIE(n);if(n.stack)return this.parseFFOrSafari(n);throw new Error("Cannot parse given Error object")},"ErrorStackParser$$parse"),extractLocation:f(function(n){if(n.indexOf(":")===-1)return[n];var u=/(.+?)(?::(\d+))?(?::(\d+))?$/,i=u.exec(n.replace(/[()]/g,""));return[i[1],i[2]||void 0,i[3]||void 0]},"ErrorStackParser$$extractLocation"),parseV8OrIE:f(function(n){var u=n.stack.split(`
`).filter(function(i){return!!i.match(o)},this);return u.map(function(i){i.indexOf("(eval ")>-1&&(i=i.replace(/eval code/g,"eval").replace(/(\(eval at [^()]*)|(,.*$)/g,""));var s=i.replace(/^\s+/,"").replace(/\(eval code/g,"(").replace(/^.*?\s+/,""),l=s.match(/ (\(.+\)$)/);s=l?s.replace(l[0],""):s;var m=this.extractLocation(l?l[1]:s),p=l&&s||void 0,d=["eval","<anonymous>"].indexOf(m[0])>-1?void 0:m[0];return new e({functionName:p,fileName:d,lineNumber:m[1],columnNumber:m[2],source:i})},this)},"ErrorStackParser$$parseV8OrIE"),parseFFOrSafari:f(function(n){var u=n.stack.split(`
`).filter(function(i){return!i.match(a)},this);return u.map(function(i){if(i.indexOf(" > eval")>-1&&(i=i.replace(/ line (\d+)(?: > eval line \d+)* > eval:\d+:\d+/g,":$1")),i.indexOf("@")===-1&&i.indexOf(":")===-1)return new e({functionName:i});var s=/((.*".+"[^@]*)?[^@]*)(?:@)/,l=i.match(s),m=l&&l[1]?l[1]:void 0,p=this.extractLocation(i.replace(s,""));return new e({functionName:m,fileName:p[0],lineNumber:p[1],columnNumber:p[2],source:i})},this)},"ErrorStackParser$$parseFFOrSafari"),parseOpera:f(function(n){return!n.stacktrace||n.message.indexOf(`
`)>-1&&n.message.split(`
`).length>n.stacktrace.split(`
`).length?this.parseOpera9(n):n.stack?this.parseOpera11(n):this.parseOpera10(n)},"ErrorStackParser$$parseOpera"),parseOpera9:f(function(n){for(var u=/Line (\d+).*script (?:in )?(\S+)/i,i=n.message.split(`
`),s=[],l=2,m=i.length;l<m;l+=2){var p=u.exec(i[l]);p&&s.push(new e({fileName:p[2],lineNumber:p[1],source:i[l]}))}return s},"ErrorStackParser$$parseOpera9"),parseOpera10:f(function(n){for(var u=/Line (\d+).*script (?:in )?(\S+)(?:: In function (\S+))?$/i,i=n.stacktrace.split(`
`),s=[],l=0,m=i.length;l<m;l+=2){var p=u.exec(i[l]);p&&s.push(new e({functionName:p[3]||void 0,fileName:p[2],lineNumber:p[1],source:i[l]}))}return s},"ErrorStackParser$$parseOpera10"),parseOpera11:f(function(n){var u=n.stack.split(`
`).filter(function(i){return!!i.match(c)&&!i.match(/^Error created at/)},this);return u.map(function(i){var s=i.split("@"),l=this.extractLocation(s.pop()),m=s.shift()||"",p=m.replace(/<anonymous function(: (\w+))?>/,"$2").replace(/\([^)]*\)/g,"")||void 0,d;m.match(/\(([^)]*)\)/)&&(d=m.replace(/^[^(]+\(([^)]*)\)$/,"$1"));var y=d===void 0||d==="[arguments not available]"?void 0:d.split(",");return new e({functionName:p,args:y,fileName:l[0],lineNumber:l[1],columnNumber:l[2],source:i})},this)},"ErrorStackParser$$parseOpera11")}},"ErrorStackParser"))});var Re={};pe(Re,{loadPyodide:()=>T,version:()=>b});var G=h(W());var v=typeof process=="object"&&typeof process.versions=="object"&&typeof process.versions.node=="string"&&typeof process.browser>"u",F=v&&typeof module<"u"&&typeof module.exports<"u"&&typeof g<"u"&&typeof __dirname<"u",H=v&&!F,ye=typeof Deno<"u",z=!v&&!ye,q=z&&typeof window<"u"&&typeof document<"u"&&typeof document.createElement<"u"&&typeof sessionStorage<"u",V=z&&typeof importScripts<"u"&&typeof self<"u";var K,k,L,X,D,ge=`"fetch" is not defined, maybe you're using node < 18? From Pyodide >= 0.25.0, node >= 18 is required. Older versions of Node.js may work, but it is not guaranteed or supported. Falling back to "node-fetch".`;async function A(){if(!v||(K=(await import(/* webpackIgnore */"url")).default,D=await import(/* webpackIgnore */"fs/promises"),globalThis.fetch?k=fetch:(console.warn(ge),k=(await import(/* webpackIgnore */"node-fetch")).default),X=(await import(/* webpackIgnore */"vm")).default,L=await import(/* webpackIgnore */"path"),I=L.sep,typeof g<"u"))return;let t=await import(/* webpackIgnore */"fs"),e=await import(/* webpackIgnore */"crypto"),c=await import(/* webpackIgnore */"ws"),o=await import(/* webpackIgnore */"child_process"),a={fs:t,crypto:e,ws:c,child_process:o};globalThis.require=function(r){return a[r]}}f(A,"initNodeModules");function he(t,e){return L.resolve(e||".",t)}f(he,"node_resolvePath");function ve(t,e){return e===void 0&&(e=location),new URL(t,e).toString()}f(ve,"browser_resolvePath");var N;v?N=he:N=ve;var I;v||(I="/");function we(t,e){return t.startsWith("file://")&&(t=t.slice(7)),t.includes("://")?{response:k(t)}:{binary:D.readFile(t).then(c=>new Uint8Array(c.buffer,c.byteOffset,c.byteLength))}}f(we,"node_getBinaryResponse");function be(t,e){let c=new URL(t,location);return{response:fetch(c,e?{integrity:e}:{})}}f(be,"browser_getBinaryResponse");var O;v?O=we:O=be;async function J(t,e){let{response:c,binary:o}=O(t,e);if(o)return o;let a=await c;if(!a.ok)throw new Error(`Failed to load '${t}': request failed.`);return new Uint8Array(await a.arrayBuffer())}f(J,"loadBinaryFile");var S;if(q)S=f(async t=>await import(/* webpackIgnore */t),"loadScript");else if(V)S=f(async t=>{try{globalThis.importScripts(t)}catch(e){if(e instanceof TypeError)await import(/* webpackIgnore */t);else throw e}},"loadScript");else if(v)S=Ee;else throw new Error("Cannot determine runtime environment");async function Ee(t){t.startsWith("file://")&&(t=t.slice(7)),t.includes("://")?X.runInThisContext(await(await k(t)).text()):await import(/* webpackIgnore */K.pathToFileURL(t).href)}f(Ee,"nodeLoadScript");async function Y(t){if(v){await A();let e=await D.readFile(t);return JSON.parse(e)}else return await(await fetch(t)).json()}f(Y,"loadLockFile");async function Q(){if(F)return __dirname;let t;try{throw new Error}catch(o){t=o}let e=G.default.parse(t)[0].fileName;if(H){let o=await import(/* webpackIgnore */"path");return(await import(/* webpackIgnore */"url")).fileURLToPath(o.dirname(e))}let c=e.lastIndexOf(I);if(c===-1)throw new Error("Could not extract indexURL path from pyodide module location");return e.slice(0,c)}f(Q,"calculateDirname");function Z(t){let e=t.FS,c=t.FS.filesystems.MEMFS,o=t.PATH,a={DIR_MODE:16895,FILE_MODE:33279,mount:function(r){if(!r.opts.fileSystemHandle)throw new Error("opts.fileSystemHandle is required");return c.mount.apply(null,arguments)},syncfs:async(r,n,u)=>{try{let i=a.getLocalSet(r),s=await a.getRemoteSet(r),l=n?s:i,m=n?i:s;await a.reconcile(r,l,m),u(null)}catch(i){u(i)}},getLocalSet:r=>{let n=Object.create(null);function u(l){return l!=="."&&l!==".."}f(u,"isRealDir");function i(l){return m=>o.join2(l,m)}f(i,"toAbsolute");let s=e.readdir(r.mountpoint).filter(u).map(i(r.mountpoint));for(;s.length;){let l=s.pop(),m=e.stat(l);e.isDir(m.mode)&&s.push.apply(s,e.readdir(l).filter(u).map(i(l))),n[l]={timestamp:m.mtime,mode:m.mode}}return{type:"local",entries:n}},getRemoteSet:async r=>{let n=Object.create(null),u=await _e(r.opts.fileSystemHandle);for(let[i,s]of u)i!=="."&&(n[o.join2(r.mountpoint,i)]={timestamp:s.kind==="file"?(await s.getFile()).lastModifiedDate:new Date,mode:s.kind==="file"?a.FILE_MODE:a.DIR_MODE});return{type:"remote",entries:n,handles:u}},loadLocalEntry:r=>{let u=e.lookupPath(r).node,i=e.stat(r);if(e.isDir(i.mode))return{timestamp:i.mtime,mode:i.mode};if(e.isFile(i.mode))return u.contents=c.getFileDataAsTypedArray(u),{timestamp:i.mtime,mode:i.mode,contents:u.contents};throw new Error("node type not supported")},storeLocalEntry:(r,n)=>{if(e.isDir(n.mode))e.mkdirTree(r,n.mode);else if(e.isFile(n.mode))e.writeFile(r,n.contents,{canOwn:!0});else throw new Error("node type not supported");e.chmod(r,n.mode),e.utime(r,n.timestamp,n.timestamp)},removeLocalEntry:r=>{var n=e.stat(r);e.isDir(n.mode)?e.rmdir(r):e.isFile(n.mode)&&e.unlink(r)},loadRemoteEntry:async r=>{if(r.kind==="file"){let n=await r.getFile();return{contents:new Uint8Array(await n.arrayBuffer()),mode:a.FILE_MODE,timestamp:n.lastModifiedDate}}else{if(r.kind==="directory")return{mode:a.DIR_MODE,timestamp:new Date};throw new Error("unknown kind: "+r.kind)}},storeRemoteEntry:async(r,n,u)=>{let i=r.get(o.dirname(n)),s=e.isFile(u.mode)?await i.getFileHandle(o.basename(n),{create:!0}):await i.getDirectoryHandle(o.basename(n),{create:!0});if(s.kind==="file"){let l=await s.createWritable();await l.write(u.contents),await l.close()}r.set(n,s)},removeRemoteEntry:async(r,n)=>{await r.get(o.dirname(n)).removeEntry(o.basename(n)),r.delete(n)},reconcile:async(r,n,u)=>{let i=0,s=[];Object.keys(n.entries).forEach(function(p){let d=n.entries[p],y=u.entries[p];(!y||e.isFile(d.mode)&&d.timestamp.getTime()>y.timestamp.getTime())&&(s.push(p),i++)}),s.sort();let l=[];if(Object.keys(u.entries).forEach(function(p){n.entries[p]||(l.push(p),i++)}),l.sort().reverse(),!i)return;let m=n.type==="remote"?n.handles:u.handles;for(let p of s){let d=o.normalize(p.replace(r.mountpoint,"/")).substring(1);if(u.type==="local"){let y=m.get(d),w=await a.loadRemoteEntry(y);a.storeLocalEntry(p,w)}else{let y=a.loadLocalEntry(p);await a.storeRemoteEntry(m,d,y)}}for(let p of l)if(u.type==="local")a.removeLocalEntry(p);else{let d=o.normalize(p.replace(r.mountpoint,"/")).substring(1);await a.removeRemoteEntry(m,d)}}};t.FS.filesystems.NATIVEFS_ASYNC=a}f(Z,"initializeNativeFS");var _e=f(async t=>{let e=[];async function c(a){for await(let r of a.values())e.push(r),r.kind==="directory"&&await c(r)}f(c,"collect"),await c(t);let o=new Map;o.set(".",t);for(let a of e){let r=(await t.resolve(a)).join("/");o.set(r,a)}return o},"getFsHandles");function ee(){let t={};return t.noImageDecoding=!0,t.noAudioDecoding=!0,t.noWasmDecoding=!1,t.preRun=[],t.quit=(e,c)=>{throw t.exited={status:e,toThrow:c},c},t}f(ee,"createModule");function Se(t,e){t.preRun.push(function(){let c="/";try{t.FS.mkdirTree(e)}catch(o){console.error(`Error occurred while making a home directory '${e}':`),console.error(o),console.error(`Using '${c}' for a home directory instead`),e=c}t.FS.chdir(e)})}f(Se,"createHomeDirectory");function Oe(t,e){t.preRun.push(function(){Object.assign(t.ENV,e)})}f(Oe,"setEnvironment");function ke(t,e){t.preRun.push(()=>{for(let c of e)t.FS.mkdirTree(c),t.FS.mount(t.FS.filesystems.NODEFS,{root:c},c)})}f(ke,"mountLocalDirectories");function Ne(t,e){let c=J(e);t.preRun.push(()=>{let o=t._py_version_major(),a=t._py_version_minor();t.FS.mkdirTree("/lib"),t.FS.mkdirTree(`/lib/python${o}.${a}/site-packages`),t.addRunDependency("install-stdlib"),c.then(r=>{t.FS.writeFile(`/lib/python${o}${a}.zip`,r)}).catch(r=>{console.error("Error occurred while installing the standard library:"),console.error(r)}).finally(()=>{t.removeRunDependency("install-stdlib")})})}f(Ne,"installStdlib");function te(t,e){let c;e.stdLibURL!=null?c=e.stdLibURL:c=e.indexURL+"python_stdlib.zip",Ne(t,c),Se(t,e.env.HOME),Oe(t,e.env),ke(t,e._node_mounts),t.preRun.push(()=>Z(t))}f(te,"initializeFileSystem");function re(t,e){let{binary:c,response:o}=O(e+"pyodide.asm.wasm");t.instantiateWasm=function(a,r){return async function(){try{let n;o?n=await WebAssembly.instantiateStreaming(o,a):n=await WebAssembly.instantiate(await c,a);let{instance:u,module:i}=n;typeof WasmOffsetConverter<"u"&&(wasmOffsetConverter=new WasmOffsetConverter(wasmBinary,i)),r(u,i)}catch(n){console.warn("wasm instantiation failed!"),console.warn(n)}}(),{}}}f(re,"preloadWasm");var b="0.25.1";async function T(t={}){await A();let e=t.indexURL||await Q();e=N(e),e.endsWith("/")||(e+="/"),t.indexURL=e;let c={fullStdLib:!1,jsglobals:globalThis,stdin:globalThis.prompt?globalThis.prompt:void 0,lockFileURL:e+"pyodide-lock.json",args:[],_node_mounts:[],env:{},packageCacheDir:e,packages:[]},o=Object.assign(c,t);o.env.HOME||(o.env.HOME="/home/pyodide");let a=ee();a.print=o.stdout,a.printErr=o.stderr,a.arguments=o.args;let r={config:o};a.API=r,r.lockFilePromise=Y(o.lockFileURL),re(a,e),te(a,o);let n=new Promise(s=>a.postRun=s);if(a.locateFile=s=>o.indexURL+s,typeof _createPyodideModule!="function"){let s=`${o.indexURL}pyodide.asm.js`;await S(s)}if(await _createPyodideModule(a),await n,a.exited)throw a.exited.toThrow;if(t.pyproxyToStringRepr&&r.setPyProxyToStringMethod(!0),r.version!==b)throw new Error(`Pyodide version does not match: '${b}' <==> '${r.version}'. If you updated the Pyodide version, make sure you also updated the 'indexURL' parameter passed to loadPyodide.`);a.locateFile=s=>{throw new Error("Didn't expect to load any more file_packager files!")};let u=r.finalizeBootstrap();if(u.version.includes("dev")||r.setCdnUrl(`https://cdn.jsdelivr.net/pyodide/v${u.version}/full/`),await r.packageIndexReady,r._pyodide._importhook.register_module_not_found_hook(r._import_name_to_package_name,r.lockfile_unvendored_stdlibs_and_test),r.lockfile_info.version!==b)throw new Error("Lock file version doesn't match Pyodide version");return r.package_loader.init_loaded_packages(),o.fullStdLib&&await u.loadPackage(r.lockfile_unvendored_stdlibs),r.initializeStreams(o.stdin,o.stdout,o.stderr),u}f(T,"loadPyodide");globalThis.loadPyodide=T;return me(Re);})();
try{Object.assign(exports,loadPyodide)}catch(_){}
globalThis.loadPyodide=loadPyodide.loadPyodide;
//# sourceMappingURL=pyodide.js.map
This diff is collapsed.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment