@heimdall-ai/heimdall 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +471 -0
  3. package/dist/config/constants.d.ts +24 -0
  4. package/dist/config/constants.d.ts.map +1 -0
  5. package/dist/config/constants.js +70 -0
  6. package/dist/config/constants.js.map +1 -0
  7. package/dist/core/bash-manager.d.ts +56 -0
  8. package/dist/core/bash-manager.d.ts.map +1 -0
  9. package/dist/core/bash-manager.js +106 -0
  10. package/dist/core/bash-manager.js.map +1 -0
  11. package/dist/core/pyodide-manager.d.ts +125 -0
  12. package/dist/core/pyodide-manager.d.ts.map +1 -0
  13. package/dist/core/pyodide-manager.js +669 -0
  14. package/dist/core/pyodide-manager.js.map +1 -0
  15. package/dist/core/pyodide-worker.d.ts +9 -0
  16. package/dist/core/pyodide-worker.d.ts.map +1 -0
  17. package/dist/core/pyodide-worker.js +295 -0
  18. package/dist/core/pyodide-worker.js.map +1 -0
  19. package/dist/core/secure-fs.d.ts +101 -0
  20. package/dist/core/secure-fs.d.ts.map +1 -0
  21. package/dist/core/secure-fs.js +279 -0
  22. package/dist/core/secure-fs.js.map +1 -0
  23. package/dist/integration.test.d.ts +10 -0
  24. package/dist/integration.test.d.ts.map +1 -0
  25. package/dist/integration.test.js +439 -0
  26. package/dist/integration.test.js.map +1 -0
  27. package/dist/resources/index.d.ts +12 -0
  28. package/dist/resources/index.d.ts.map +1 -0
  29. package/dist/resources/index.js +13 -0
  30. package/dist/resources/index.js.map +1 -0
  31. package/dist/resources/workspace.d.ts +12 -0
  32. package/dist/resources/workspace.d.ts.map +1 -0
  33. package/dist/resources/workspace.js +105 -0
  34. package/dist/resources/workspace.js.map +1 -0
  35. package/dist/server.d.ts +17 -0
  36. package/dist/server.d.ts.map +1 -0
  37. package/dist/server.js +51 -0
  38. package/dist/server.js.map +1 -0
  39. package/dist/tools/bash-execution.d.ts +13 -0
  40. package/dist/tools/bash-execution.d.ts.map +1 -0
  41. package/dist/tools/bash-execution.js +135 -0
  42. package/dist/tools/bash-execution.js.map +1 -0
  43. package/dist/tools/filesystem.d.ts +12 -0
  44. package/dist/tools/filesystem.d.ts.map +1 -0
  45. package/dist/tools/filesystem.js +104 -0
  46. package/dist/tools/filesystem.js.map +1 -0
  47. package/dist/tools/index.d.ts +13 -0
  48. package/dist/tools/index.d.ts.map +1 -0
  49. package/dist/tools/index.js +17 -0
  50. package/dist/tools/index.js.map +1 -0
  51. package/dist/tools/python-execution.d.ts +12 -0
  52. package/dist/tools/python-execution.d.ts.map +1 -0
  53. package/dist/tools/python-execution.js +77 -0
  54. package/dist/tools/python-execution.js.map +1 -0
  55. package/dist/types/index.d.ts +64 -0
  56. package/dist/types/index.d.ts.map +1 -0
  57. package/dist/types/index.js +2 -0
  58. package/dist/types/index.js.map +1 -0
  59. package/dist/utils/async-lock.d.ts +35 -0
  60. package/dist/utils/async-lock.d.ts.map +1 -0
  61. package/dist/utils/async-lock.js +57 -0
  62. package/dist/utils/async-lock.js.map +1 -0
  63. package/dist/utils/index.d.ts +5 -0
  64. package/dist/utils/index.d.ts.map +1 -0
  65. package/dist/utils/index.js +5 -0
  66. package/dist/utils/index.js.map +1 -0
  67. package/package.json +61 -0
@@ -0,0 +1,70 @@
1
+ import * as path from "path";
2
+ import { fileURLToPath } from "url";
3
+ import * as fs from "fs";
4
+ // Get directory paths
5
+ const __filename = fileURLToPath(import.meta.url);
6
+ const __dirname = path.dirname(__filename);
7
+ /**
8
+ * Host filesystem path to workspace directory
9
+ */
10
+ export const WORKSPACE_DIR = process.env.HEIMDALL_WORKSPACE || path.join(__dirname, "..", "..", "workspace");
11
+ /**
12
+ * Virtual filesystem path to workspace directory in Pyodide
13
+ */
14
+ export const VIRTUAL_WORKSPACE = "/workspace";
15
+ /**
16
+ * Parse and validate a size limit from environment variable
17
+ * @param envValue - Environment variable value
18
+ * @param defaultValue - Default value in bytes
19
+ * @param name - Name of the configuration (for error messages)
20
+ * @returns Validated size in bytes
21
+ */
22
+ function parseSizeLimit(envValue, defaultValue, name) {
23
+ if (!envValue) {
24
+ return defaultValue;
25
+ }
26
+ const parsed = parseInt(envValue, 10);
27
+ if (isNaN(parsed) || parsed <= 0) {
28
+ console.error(`[Config] Invalid ${name}: "${envValue}". Must be a positive number. Using default: ${defaultValue} bytes`);
29
+ return defaultValue;
30
+ }
31
+ return parsed;
32
+ }
33
+ /**
34
+ * Parse and validate a timeout from environment variable
35
+ * @param envValue - Environment variable value
36
+ * @param defaultValue - Default value in milliseconds
37
+ * @param name - Name of the configuration (for error messages)
38
+ * @returns Validated timeout in milliseconds
39
+ */
40
+ function parseTimeoutMs(envValue, defaultValue, name) {
41
+ if (!envValue) {
42
+ return defaultValue;
43
+ }
44
+ const parsed = parseInt(envValue, 10);
45
+ if (isNaN(parsed) || parsed <= 0) {
46
+ console.error(`[Config] Invalid ${name}: "${envValue}". Must be a positive number. Using default: ${defaultValue}ms`);
47
+ return defaultValue;
48
+ }
49
+ return parsed;
50
+ }
51
+ /**
52
+ * Maximum size for a single file (default: 10MB)
53
+ * Configure via HEIMDALL_MAX_FILE_SIZE environment variable (in bytes)
54
+ */
55
+ export const MAX_FILE_SIZE = parseSizeLimit(process.env.HEIMDALL_MAX_FILE_SIZE, 10 * 1024 * 1024, "HEIMDALL_MAX_FILE_SIZE");
56
+ /**
57
+ * Maximum total workspace size (default: 100MB)
58
+ * Configure via HEIMDALL_MAX_WORKSPACE_SIZE environment variable (in bytes)
59
+ */
60
+ export const MAX_WORKSPACE_SIZE = parseSizeLimit(process.env.HEIMDALL_MAX_WORKSPACE_SIZE, 100 * 1024 * 1024, "HEIMDALL_MAX_WORKSPACE_SIZE");
61
+ /**
62
+ * Maximum execution time for Python code (default: 5000ms)
63
+ * Configure via HEIMDALL_PYTHON_EXECUTION_TIMEOUT_MS environment variable
64
+ */
65
+ export const PYTHON_EXECUTION_TIMEOUT_MS = parseTimeoutMs(process.env.HEIMDALL_PYTHON_EXECUTION_TIMEOUT_MS, 5000, "HEIMDALL_PYTHON_EXECUTION_TIMEOUT_MS");
66
+ // Ensure workspace exists
67
+ if (!fs.existsSync(WORKSPACE_DIR)) {
68
+ fs.mkdirSync(WORKSPACE_DIR, { recursive: true });
69
+ }
70
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/config/constants.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AAEzB,sBAAsB;AACtB,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AAE3C;;GAEG;AACH,MAAM,CAAC,MAAM,aAAa,GACxB,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC;AAElF;;GAEG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,YAAY,CAAC;AAE9C;;;;;;GAMG;AACH,SAAS,cAAc,CAAC,QAA4B,EAAE,YAAoB,EAAE,IAAY;IACtF,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,MAAM,MAAM,GAAG,QAAQ,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IAEtC,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,MAAM,IAAI,CAAC,EAAE,CAAC;QACjC,OAAO,CAAC,KAAK,CACX,oBAAoB,IAAI,MAAM,QAAQ,gDAAgD,YAAY,QAAQ,CAC3G,CAAC;QACF,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;GAMG;AACH,SAAS,cAAc,CAAC,QAA4B,EAAE,YAAoB,EAAE,IAAY;IACtF,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,MAAM,MAAM,GAAG,QAAQ,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IAEtC,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,MAAM,IAAI,CAAC,EAAE,CAAC;QACjC,OAAO,CAAC,KAAK,CACX,oBAAoB,IAAI,MAAM,QAAQ,gDAAgD,YAAY,IAAI,CACvG,CAAC;QACF,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,cAAc,CACzC,OAAO,CAAC,GAAG,CAAC,sBAAsB,EAClC,EAAE,GAAG,IAAI,GAAG,IAAI,EAChB,wBAAwB,CACzB,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,cAAc,CAC9C,OAAO,CAAC,GAAG,CAAC,2BAA2B,EACvC,GAAG,GAAG,IAAI,GAAG,IAAI,EACjB,6BAA6B,CAC9B,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG,cAAc,CACvD,OAAO,CAAC,GAAG,CAAC,oCAAoC,EAChD,IAAI,EACJ,sCAAsC,CACvC,CAAC;AAEF,0BAA0B;AAC1B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;IAClC,EAAE,CAAC,SAAS,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AACnD,CAAC"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * BashManager - Manages bash command execution using just-bash
3
+ *
4
+ * Provides a sandboxed bash environment with an in-memory virtual filesystem.
5
+ * Commands are executed using just-bash, a TypeScript implementation of bash
6
+ * that doesn't spawn real processes.
7
+ *
8
+ * SECURITY: Uses SecureFs wrapper to prevent symlink-based path traversal attacks.
9
+ * All file operations validate that resolved paths stay within the workspace.
10
+ *
11
+ * @see SECURITY-REVIEW.md for security details
12
+ */
13
+ /**
14
+ * Result of a bash command execution
15
+ */
16
+ export interface BashExecutionResult {
17
+ stdout: string;
18
+ stderr: string;
19
+ exitCode: number;
20
+ }
21
+ /**
22
+ * Options for bash execution
23
+ */
24
+ export interface BashExecutionOptions {
25
+ cwd?: string;
26
+ }
27
+ /**
28
+ * BashManager provides bash command execution in a sandboxed environment
29
+ */
30
+ export declare class BashManager {
31
+ private bash;
32
+ private workspaceDir;
33
+ private initialized;
34
+ constructor(workspaceDir?: string);
35
+ /**
36
+ * Initialize the bash manager
37
+ */
38
+ initialize(): Promise<void>;
39
+ /**
40
+ * Execute a bash command
41
+ */
42
+ execute(command: string, options?: BashExecutionOptions): Promise<BashExecutionResult>;
43
+ /**
44
+ * Get the workspace directory
45
+ */
46
+ getWorkspaceDir(): string;
47
+ /**
48
+ * Check if the manager is initialized
49
+ */
50
+ isInitialized(): boolean;
51
+ /**
52
+ * Reset the bash environment (for testing)
53
+ */
54
+ reset(): Promise<void>;
55
+ }
56
+ //# sourceMappingURL=bash-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bash-manager.d.ts","sourceRoot":"","sources":["../../src/core/bash-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAOH;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,IAAI,CAAqB;IACjC,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,WAAW,CAAS;gBAEhB,YAAY,GAAE,MAAsB;IAIhD;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IA4BjC;;OAEG;IACG,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAgC5F;;OAEG;IACH,eAAe,IAAI,MAAM;IAIzB;;OAEG;IACH,aAAa,IAAI,OAAO;IAIxB;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAK7B"}
@@ -0,0 +1,106 @@
1
+ /**
2
+ * BashManager - Manages bash command execution using just-bash
3
+ *
4
+ * Provides a sandboxed bash environment with an in-memory virtual filesystem.
5
+ * Commands are executed using just-bash, a TypeScript implementation of bash
6
+ * that doesn't spawn real processes.
7
+ *
8
+ * SECURITY: Uses SecureFs wrapper to prevent symlink-based path traversal attacks.
9
+ * All file operations validate that resolved paths stay within the workspace.
10
+ *
11
+ * @see SECURITY-REVIEW.md for security details
12
+ */
13
+ import { Bash } from "just-bash";
14
+ import { SecureFs } from "./secure-fs.js";
15
+ import { WORKSPACE_DIR } from "../config/constants.js";
16
+ import path from "path";
17
+ /**
18
+ * BashManager provides bash command execution in a sandboxed environment
19
+ */
20
+ export class BashManager {
21
+ bash = null;
22
+ workspaceDir;
23
+ initialized = false;
24
+ constructor(workspaceDir = WORKSPACE_DIR) {
25
+ this.workspaceDir = path.resolve(workspaceDir);
26
+ }
27
+ /**
28
+ * Initialize the bash manager
29
+ */
30
+ async initialize() {
31
+ if (this.initialized && this.bash) {
32
+ return;
33
+ }
34
+ // SECURITY: Use SecureFs instead of ReadWriteFs to prevent symlink attacks
35
+ // SecureFs validates all file operations to ensure they don't escape
36
+ // the workspace via symlinks
37
+ const fs = new SecureFs({ root: this.workspaceDir });
38
+ // Initialize bash environment
39
+ this.bash = new Bash({
40
+ fs,
41
+ cwd: "/",
42
+ // Configure execution limits to prevent DoS attacks
43
+ executionLimits: {
44
+ maxLoopIterations: 10000,
45
+ maxCommandCount: 10000,
46
+ maxCallDepth: 100,
47
+ },
48
+ // Network disabled by default for security
49
+ // Can be enabled later if needed with allowlist
50
+ network: undefined,
51
+ });
52
+ this.initialized = true;
53
+ }
54
+ /**
55
+ * Execute a bash command
56
+ */
57
+ async execute(command, options) {
58
+ if (!this.initialized || !this.bash) {
59
+ await this.initialize();
60
+ }
61
+ if (!this.bash) {
62
+ throw new Error("Bash manager not initialized");
63
+ }
64
+ try {
65
+ // Execute the command
66
+ const result = await this.bash.exec(command, {
67
+ cwd: options?.cwd,
68
+ });
69
+ return {
70
+ stdout: result.stdout,
71
+ stderr: result.stderr,
72
+ exitCode: result.exitCode,
73
+ };
74
+ }
75
+ catch (error) {
76
+ // Handle execution errors
77
+ const errorMessage = error instanceof Error ? error.message : String(error);
78
+ return {
79
+ stdout: "",
80
+ stderr: errorMessage,
81
+ exitCode: 1,
82
+ };
83
+ }
84
+ }
85
+ /**
86
+ * Get the workspace directory
87
+ */
88
+ getWorkspaceDir() {
89
+ return this.workspaceDir;
90
+ }
91
+ /**
92
+ * Check if the manager is initialized
93
+ */
94
+ isInitialized() {
95
+ return this.initialized;
96
+ }
97
+ /**
98
+ * Reset the bash environment (for testing)
99
+ */
100
+ async reset() {
101
+ this.bash = null;
102
+ this.initialized = false;
103
+ await this.initialize();
104
+ }
105
+ }
106
+ //# sourceMappingURL=bash-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bash-manager.js","sourceRoot":"","sources":["../../src/core/bash-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,IAAI,MAAM,MAAM,CAAC;AAkBxB;;GAEG;AACH,MAAM,OAAO,WAAW;IACd,IAAI,GAAgB,IAAI,CAAC;IACzB,YAAY,CAAS;IACrB,WAAW,GAAG,KAAK,CAAC;IAE5B,YAAY,eAAuB,aAAa;QAC9C,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IACjD,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,UAAU;QACd,IAAI,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YAClC,OAAO;QACT,CAAC;QAED,2EAA2E;QAC3E,qEAAqE;QACrE,6BAA6B;QAC7B,MAAM,EAAE,GAAG,IAAI,QAAQ,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;QAErD,8BAA8B;QAC9B,IAAI,CAAC,IAAI,GAAG,IAAI,IAAI,CAAC;YACnB,EAAE;YACF,GAAG,EAAE,GAAG;YACR,oDAAoD;YACpD,eAAe,EAAE;gBACf,iBAAiB,EAAE,KAAK;gBACxB,eAAe,EAAE,KAAK;gBACtB,YAAY,EAAE,GAAG;aAClB;YACD,2CAA2C;YAC3C,gDAAgD;YAChD,OAAO,EAAE,SAAS;SACnB,CAAC,CAAC;QAEH,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;IAC1B,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAO,CAAC,OAAe,EAAE,OAA8B;QAC3D,IAAI,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACpC,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;QAC1B,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;QAClD,CAAC;QAED,IAAI,CAAC;YACH,sBAAsB;YACtB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE;gBAC3C,GAAG,EAAE,OAAO,EAAE,GAAG;aAClB,CAAC,CAAC;YAEH,OAAO;gBACL,MAAM,EAAE,MAAM,CAAC,MAAM;gBACrB,MAAM,EAAE,MAAM,CAAC,MAAM;gBACrB,QAAQ,EAAE,MAAM,CAAC,QAAQ;aAC1B,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,0BAA0B;YAC1B,MAAM,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAE5E,OAAO;gBACL,MAAM,EAAE,EAAE;gBACV,MAAM,EAAE,YAAY;gBACpB,QAAQ,EAAE,CAAC;aACZ,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;OAEG;IACH,eAAe;QACb,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;IAED;;OAEG;IACH,aAAa;QACX,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;QACzB,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;IAC1B,CAAC;CACF"}
@@ -0,0 +1,125 @@
1
+ /**
2
+ * PyodideManager - Handles Python runtime lifecycle
3
+ *
4
+ * This class manages the Pyodide WebAssembly Python runtime, including:
5
+ * - Initialization and lifecycle management
6
+ * - Virtual filesystem operations
7
+ * - Host <-> Virtual filesystem synchronization
8
+ * - Python code execution (via worker thread for timeout support)
9
+ * - Package installation
10
+ *
11
+ * Code execution runs in a separate worker thread to enable true timeout
12
+ * enforcement. If Python code blocks indefinitely (infinite loops, etc.),
13
+ * the worker can be terminated to enforce the timeout.
14
+ */
15
+ import { PyodideInterface } from "pyodide";
16
+ import type { ExecutionResult, FileReadResult, FileWriteResult, FileListResult, FileDeleteResult, PackageInstallResult } from "../types/index.js";
17
+ export declare class PyodideManager {
18
+ private pyodide;
19
+ private initialized;
20
+ private initializationPromise;
21
+ private worker;
22
+ private workerReady;
23
+ private workerInitPromise;
24
+ private writeLock;
25
+ /**
26
+ * Convert a virtual path to a host filesystem path.
27
+ */
28
+ private virtualToHostPath;
29
+ /**
30
+ * Validate and normalize a file path to prevent directory traversal attacks
31
+ * @param filePath - The file path to validate
32
+ * @returns The normalized virtual filesystem path
33
+ * @throws Error if path is invalid or attempts to escape workspace
34
+ */
35
+ private validatePath;
36
+ /**
37
+ * Resolve symlinks and validate that the real path is within the workspace.
38
+ * This prevents symlink-based path traversal attacks where an attacker creates
39
+ * a symlink inside the workspace pointing to a location outside.
40
+ *
41
+ * @param hostPath - The host filesystem path to validate
42
+ * @throws Error if the resolved path escapes the workspace
43
+ */
44
+ private validateHostPathWithSymlinkResolution;
45
+ /**
46
+ * For files that don't exist yet, validate parent directories for symlinks.
47
+ * Walks up the path until we find an existing directory, then validates it.
48
+ */
49
+ private validateParentPathForSymlinks;
50
+ /**
51
+ * Calculate total workspace size from host filesystem
52
+ * @returns Total size in bytes
53
+ */
54
+ private getWorkspaceSize;
55
+ /**
56
+ * Validate that writing a file won't exceed workspace size limit
57
+ * @param fileSize - Size of file to be written
58
+ * @throws Error if workspace size limit would be exceeded
59
+ */
60
+ private checkWorkspaceSize;
61
+ initialize(): Promise<PyodideInterface>;
62
+ private doInitialize;
63
+ /**
64
+ * Sync files from host filesystem to Pyodide virtual FS
65
+ */
66
+ syncHostToVirtual(hostPath?: string, virtualPath?: string): Promise<void>;
67
+ /**
68
+ * Sync a specific host file or directory into the virtual FS.
69
+ */
70
+ private syncHostPathToVirtual;
71
+ /**
72
+ * Sync files from Pyodide virtual FS to host filesystem
73
+ */
74
+ syncVirtualToHost(virtualPath?: string, hostPath?: string): Promise<void>;
75
+ /**
76
+ * Sync a specific virtual file or directory into the host filesystem.
77
+ * Includes symlink protection to prevent writing outside workspace.
78
+ */
79
+ private syncVirtualPathToHost;
80
+ /**
81
+ * Initialize the worker thread for code execution
82
+ */
83
+ private initializeWorker;
84
+ private doInitializeWorker;
85
+ /**
86
+ * Terminate the worker thread
87
+ */
88
+ private terminateWorker;
89
+ /**
90
+ * Execute Python code in the sandbox using a worker thread
91
+ *
92
+ * Network access is NOT available - Pyodide runs in WebAssembly which
93
+ * doesn't have network capabilities. This is by design for security.
94
+ *
95
+ * The code runs in a separate worker thread, enabling true timeout
96
+ * enforcement. If the code doesn't complete within the timeout,
97
+ * the worker is terminated.
98
+ */
99
+ executeCode(code: string, packages?: string[]): Promise<ExecutionResult>;
100
+ /**
101
+ * Install packages via micropip
102
+ */
103
+ installPackages(packages: string[]): Promise<PackageInstallResult[]>;
104
+ /**
105
+ * Read a file from the virtual filesystem
106
+ */
107
+ readFile(filePath: string): Promise<FileReadResult>;
108
+ /**
109
+ * Write a file to the virtual filesystem
110
+ *
111
+ * Uses a write lock to prevent TOCTOU race conditions where concurrent
112
+ * writes could bypass workspace size limits. The lock ensures that the
113
+ * size check and write operation are atomic.
114
+ */
115
+ writeFile(filePath: string, content: string): Promise<FileWriteResult>;
116
+ /**
117
+ * List files in a directory
118
+ */
119
+ listFiles(dirPath?: string): Promise<FileListResult>;
120
+ /**
121
+ * Delete a file or directory
122
+ */
123
+ deleteFile(filePath: string): Promise<FileDeleteResult>;
124
+ }
125
+ //# sourceMappingURL=pyodide-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pyodide-manager.d.ts","sourceRoot":"","sources":["../../src/core/pyodide-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAe,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAYxD,OAAO,KAAK,EACV,eAAe,EACf,cAAc,EACd,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,oBAAoB,EACrB,MAAM,mBAAmB,CAAC;AA0B3B,qBAAa,cAAc;IACzB,OAAO,CAAC,OAAO,CAAiC;IAChD,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,qBAAqB,CAA0C;IAGvE,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,iBAAiB,CAA8B;IAIvD,OAAO,CAAC,SAAS,CAAmB;IAEpC;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAYzB;;;;;OAKG;IACH,OAAO,CAAC,YAAY;IAuBpB;;;;;;;OAOG;YACW,qCAAqC;IAuBnD;;;OAGG;YACW,6BAA6B;IAgC3C;;;OAGG;YACW,gBAAgB;IA0B9B;;;;OAIG;YACW,kBAAkB;IAU1B,UAAU,IAAI,OAAO,CAAC,gBAAgB,CAAC;YAsB/B,YAAY;IA4C1B;;OAEG;IACG,iBAAiB,CACrB,QAAQ,SAAgB,EACxB,WAAW,SAAoB,GAC9B,OAAO,CAAC,IAAI,CAAC;IAIhB;;OAEG;YACW,qBAAqB;IAqDnC;;OAEG;IACG,iBAAiB,CACrB,WAAW,SAAoB,EAC/B,QAAQ,SAAgB,GACvB,OAAO,CAAC,IAAI,CAAC;IAIhB;;;OAGG;YACW,qBAAqB;IAqDnC;;OAEG;YACW,gBAAgB;YAmBhB,kBAAkB;IAoEhC;;OAEG;IACH,OAAO,CAAC,eAAe;IASvB;;;;;;;;;OASG;IACG,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAM,EAAO,GAAG,OAAO,CAAC,eAAe,CAAC;IAyFlF;;OAEG;IACG,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,oBAAoB,EAAE,CAAC;IAsB1E;;OAEG;IACG,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAmBzD;;;;;;OAMG;IACG,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAqC5E;;OAEG;IACG,SAAS,CAAC,OAAO,SAAK,GAAG,OAAO,CAAC,cAAc,CAAC;IA6BtD;;OAEG;IACG,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;CAsC9D"}