just-bash 2.14.0 → 2.15.0-executor.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 (36) hide show
  1. package/dist/Bash.d.ts +86 -0
  2. package/dist/bin/chunks/chunk-MNMRGJJM.js +11 -0
  3. package/dist/bin/chunks/{js-exec-BDQGEAU6.js → js-exec-6UJKEL4G.js} +9 -9
  4. package/dist/bin/chunks/js-exec-worker.js +233 -1
  5. package/dist/bin/chunks/{python3-VCIXXAXF.js → python3-QOJU2POC.js} +1 -1
  6. package/dist/bin/chunks/worker.js +15 -1
  7. package/dist/bin/just-bash.js +236 -236
  8. package/dist/bin/shell/chunks/chunk-MNMRGJJM.js +11 -0
  9. package/dist/bin/shell/chunks/{js-exec-HPXZV7UJ.js → js-exec-H26D5H6V.js} +9 -9
  10. package/dist/bin/shell/chunks/{python3-KFZH67GD.js → python3-O4VTP6TD.js} +1 -1
  11. package/dist/bin/shell/shell.js +101 -101
  12. package/dist/bundle/browser.js +6 -6
  13. package/dist/bundle/chunks/chunk-B6O2PIY4.js +10 -0
  14. package/dist/bundle/chunks/{js-exec-4CW5N6RM.js → js-exec-OOPTBRNB.js} +9 -9
  15. package/dist/bundle/chunks/js-exec-worker.js +233 -1
  16. package/dist/bundle/chunks/{python3-SG3DOKBZ.js → python3-5F2XPEW4.js} +1 -1
  17. package/dist/bundle/chunks/worker.js +15 -1
  18. package/dist/bundle/index.cjs +663 -663
  19. package/dist/bundle/index.js +7 -7
  20. package/dist/commands/js-exec/executor-adapter.d.ts +66 -0
  21. package/dist/commands/js-exec/js-exec.d.ts +19 -1
  22. package/dist/commands/js-exec/worker.d.ts +8 -0
  23. package/dist/commands/worker-bridge/bridge-handler.d.ts +3 -1
  24. package/dist/commands/worker-bridge/protocol.d.ts +1 -0
  25. package/dist/commands/worker-bridge/sync-backend.d.ts +5 -0
  26. package/dist/executor-init.d.ts +10 -0
  27. package/dist/interpreter/interpreter.d.ts +2 -0
  28. package/dist/interpreter/types.d.ts +5 -0
  29. package/dist/types.d.ts +6 -0
  30. package/package.json +37 -34
  31. package/vendor/cpython-emscripten/python.wasm +0 -0
  32. package/vendor/executor/executor-sdk-bundle.d.mts +18 -0
  33. package/vendor/executor/executor-sdk-bundle.mjs +972 -0
  34. package/dist/bin/chunks/chunk-3KAVXQP4.js +0 -11
  35. package/dist/bin/shell/chunks/chunk-3KAVXQP4.js +0 -11
  36. package/dist/bundle/chunks/chunk-S4EYC6T6.js +0 -10
package/dist/Bash.d.ts CHANGED
@@ -31,6 +31,74 @@ export interface JavaScriptConfig {
31
31
  /** Bootstrap JavaScript code to run before user scripts */
32
32
  bootstrap?: string;
33
33
  }
34
+ /** Tool definition for the executor integration */
35
+ export interface ExecutorToolDef {
36
+ description?: string;
37
+ execute: (...args: any[]) => unknown;
38
+ }
39
+ /**
40
+ * Executor SDK instance type (from @executor/sdk).
41
+ * Kept as an opaque type to avoid requiring the SDK at import time.
42
+ */
43
+ export interface ExecutorSDKHandle {
44
+ execute: (code: string) => Promise<{
45
+ result: unknown;
46
+ error?: string;
47
+ logs?: string[];
48
+ }>;
49
+ sources: {
50
+ add: (input: Record<string, unknown>, options?: Record<string, unknown>) => Promise<unknown>;
51
+ list: () => Promise<unknown[]>;
52
+ [key: string]: unknown;
53
+ };
54
+ close: () => Promise<void>;
55
+ [key: string]: unknown;
56
+ }
57
+ /** Executor configuration for js-exec tool invocation */
58
+ export interface ExecutorConfig {
59
+ /** Tool map: keys are dot-separated paths (e.g. "math.add"), values are tool definitions */
60
+ tools?: Record<string, ExecutorToolDef>;
61
+ /**
62
+ * Async setup function that receives the @executor/sdk instance.
63
+ * Use this to add OpenAPI, GraphQL, or MCP sources that auto-discover tools.
64
+ * When provided, js-exec delegates execution to the SDK pipeline
65
+ * (which handles tool approval, auth flows, and interaction loops).
66
+ *
67
+ * Requires @executor/sdk as a dependency.
68
+ *
69
+ * @example
70
+ * ```ts
71
+ * const bash = new Bash({
72
+ * executor: {
73
+ * setup: async (sdk) => {
74
+ * await sdk.sources.add({ kind: "openapi", endpoint: "https://api.example.com", specUrl: "https://api.example.com/openapi.json", name: "myapi" });
75
+ * await sdk.sources.add({ kind: "mcp", endpoint: "https://mcp.example.com/sse", name: "tools" });
76
+ * },
77
+ * },
78
+ * });
79
+ * ```
80
+ */
81
+ setup?: (sdk: ExecutorSDKHandle) => Promise<void>;
82
+ /**
83
+ * Tool approval callback for the @executor/sdk pipeline.
84
+ * Called when a tool invocation requires approval.
85
+ * Defaults to "allow-all" when not provided.
86
+ */
87
+ onToolApproval?: "allow-all" | "deny-all" | ((request: {
88
+ toolPath: string;
89
+ sourceId: string;
90
+ sourceName: string;
91
+ operationKind: "read" | "write" | "delete" | "execute" | "unknown";
92
+ args: unknown;
93
+ reason: string;
94
+ approvalLabel: string | null;
95
+ }) => Promise<{
96
+ approved: true;
97
+ } | {
98
+ approved: false;
99
+ reason?: string;
100
+ }>);
101
+ }
34
102
  export interface BashOptions {
35
103
  files?: InitialFiles;
36
104
  env?: Record<string, string>;
@@ -76,6 +144,13 @@ export interface BashOptions {
76
144
  * Disabled by default. Can be a boolean or a config object with bootstrap code.
77
145
  */
78
146
  javascript?: boolean | JavaScriptConfig;
147
+ /**
148
+ * Executor configuration for tool invocation in js-exec.
149
+ * When provided, code running in js-exec has access to a `tools` proxy
150
+ * (e.g. `tools.math.add({ a: 1, b: 2 })`).
151
+ * Implicitly enables JavaScript if not already enabled.
152
+ */
153
+ executor?: ExecutorConfig;
79
154
  /**
80
155
  * Optional list of command names to register.
81
156
  * If not provided, all built-in commands are available.
@@ -214,11 +289,22 @@ export declare class Bash {
214
289
  private defenseInDepthConfig?;
215
290
  private coverageWriter?;
216
291
  private jsBootstrapCode?;
292
+ private executorInvokeTool?;
293
+ private executorSetup?;
294
+ private executorApproval?;
295
+ private executorSDK?;
296
+ private executorInitPromise?;
217
297
  private transformPlugins;
218
298
  private state;
219
299
  constructor(options?: BashOptions);
220
300
  registerCommand(command: Command): void;
221
301
  private logResult;
302
+ /**
303
+ * Lazily initialize the @executor/sdk when setup is configured.
304
+ * Creates the SDK instance, runs the user's setup function, and wires
305
+ * the SDK's tool invocation into the executorInvokeTool callback.
306
+ */
307
+ private ensureExecutorReady;
222
308
  exec(commandLine: string, options?: ExecOptions): Promise<BashExecResult>;
223
309
  readFile(path: string): Promise<string>;
224
310
  writeFile(path: string, content: string): Promise<void>;
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ import{a as F}from"./chunk-4OALHZXB.js";import{a as w,b as h}from"./chunk-LIYVQA3X.js";import{a as T,b as g}from"./chunk-OOJCYVYF.js";import{a as m}from"./chunk-RLNOQILG.js";var n={NOOP:0,READ_FILE:1,WRITE_FILE:2,STAT:3,READDIR:4,MKDIR:5,RM:6,EXISTS:7,APPEND_FILE:8,SYMLINK:9,READLINK:10,LSTAT:11,CHMOD:12,REALPATH:13,RENAME:14,COPY_FILE:15,WRITE_STDOUT:100,WRITE_STDERR:101,EXIT:102,HTTP_REQUEST:200,EXEC_COMMAND:300,INVOKE_TOOL:400},r={PENDING:0,READY:1,SUCCESS:2,ERROR:3},l={NONE:0,NOT_FOUND:1,IS_DIRECTORY:2,NOT_DIRECTORY:3,EXISTS:4,PERMISSION_DENIED:5,INVALID_PATH:6,IO_ERROR:7,TIMEOUT:8,NETWORK_ERROR:9,NETWORK_NOT_CONFIGURED:10},o={OP_CODE:0,STATUS:4,PATH_LENGTH:8,DATA_LENGTH:12,RESULT_LENGTH:16,ERROR_CODE:20,FLAGS:24,MODE:28,PATH_BUFFER:32,DATA_BUFFER:4128},p={CONTROL_REGION:32,PATH_BUFFER:4096,DATA_BUFFER:1048576,TOTAL:1052704},S={NONE:0,RECURSIVE:1,FORCE:2,MKDIR_RECURSIVE:1},u={IS_FILE:0,IS_DIRECTORY:1,IS_SYMLINK:2,MODE:4,SIZE:8,MTIME:16,TOTAL:24};function _(){return new w(p.TOTAL)}var R=class{int32View;uint8View;dataView;constructor(t){this.int32View=new Int32Array(t),this.uint8View=new Uint8Array(t),this.dataView=new DataView(t)}getOpCode(){return h.load(this.int32View,o.OP_CODE/4)}setOpCode(t){h.store(this.int32View,o.OP_CODE/4,t)}getStatus(){return h.load(this.int32View,o.STATUS/4)}setStatus(t){h.store(this.int32View,o.STATUS/4,t)}getPathLength(){return h.load(this.int32View,o.PATH_LENGTH/4)}setPathLength(t){h.store(this.int32View,o.PATH_LENGTH/4,t)}getDataLength(){return h.load(this.int32View,o.DATA_LENGTH/4)}setDataLength(t){h.store(this.int32View,o.DATA_LENGTH/4,t)}getResultLength(){return h.load(this.int32View,o.RESULT_LENGTH/4)}setResultLength(t){h.store(this.int32View,o.RESULT_LENGTH/4,t)}getErrorCode(){return h.load(this.int32View,o.ERROR_CODE/4)}setErrorCode(t){h.store(this.int32View,o.ERROR_CODE/4,t)}getFlags(){return h.load(this.int32View,o.FLAGS/4)}setFlags(t){h.store(this.int32View,o.FLAGS/4,t)}getMode(){return h.load(this.int32View,o.MODE/4)}setMode(t){h.store(this.int32View,o.MODE/4,t)}getPath(){let t=this.getPathLength(),e=this.uint8View.slice(o.PATH_BUFFER,o.PATH_BUFFER+t);return new TextDecoder().decode(e)}setPath(t){let e=new TextEncoder().encode(t);if(e.length>p.PATH_BUFFER)throw new Error(`Path too long: ${e.length} > ${p.PATH_BUFFER}`);this.uint8View.set(e,o.PATH_BUFFER),this.setPathLength(e.length)}getData(){let t=this.getDataLength();return this.uint8View.slice(o.DATA_BUFFER,o.DATA_BUFFER+t)}setData(t){if(t.length>p.DATA_BUFFER)throw new Error(`Data too large: ${t.length} > ${p.DATA_BUFFER}`);this.uint8View.set(t,o.DATA_BUFFER),this.setDataLength(t.length)}getDataAsString(){let t=this.getData();return new TextDecoder().decode(t)}setDataFromString(t){let e=new TextEncoder().encode(t);this.setData(e)}getResult(){let t=this.getResultLength();return this.uint8View.slice(o.DATA_BUFFER,o.DATA_BUFFER+t)}setResult(t){if(t.length>p.DATA_BUFFER)throw new Error(`Result too large: ${t.length} > ${p.DATA_BUFFER}`);this.uint8View.set(t,o.DATA_BUFFER),this.setResultLength(t.length)}getResultAsString(){let t=this.getResult();return new TextDecoder().decode(t)}setResultFromString(t){let e=new TextEncoder().encode(t);this.setResult(e)}encodeStat(t){this.uint8View[o.DATA_BUFFER+u.IS_FILE]=t.isFile?1:0,this.uint8View[o.DATA_BUFFER+u.IS_DIRECTORY]=t.isDirectory?1:0,this.uint8View[o.DATA_BUFFER+u.IS_SYMLINK]=t.isSymbolicLink?1:0,this.dataView.setInt32(o.DATA_BUFFER+u.MODE,t.mode,!0);let e=Math.min(t.size,Number.MAX_SAFE_INTEGER);this.dataView.setFloat64(o.DATA_BUFFER+u.SIZE,e,!0),this.dataView.setFloat64(o.DATA_BUFFER+u.MTIME,t.mtime.getTime(),!0),this.setResultLength(u.TOTAL)}decodeStat(){return{isFile:this.uint8View[o.DATA_BUFFER+u.IS_FILE]===1,isDirectory:this.uint8View[o.DATA_BUFFER+u.IS_DIRECTORY]===1,isSymbolicLink:this.uint8View[o.DATA_BUFFER+u.IS_SYMLINK]===1,mode:this.dataView.getInt32(o.DATA_BUFFER+u.MODE,!0),size:this.dataView.getFloat64(o.DATA_BUFFER+u.SIZE,!0),mtime:new Date(this.dataView.getFloat64(o.DATA_BUFFER+u.MTIME,!0))}}waitForReady(t){return h.wait(this.int32View,o.STATUS/4,r.PENDING,t)}waitForReadyAsync(t){return h.waitAsync(this.int32View,o.STATUS/4,r.PENDING,t)}async waitUntilReady(t){let e=Date.now();for(;;){let a=this.getStatus();if(a===r.READY)return!0;let s=Date.now()-e;if(s>=t)return!1;let i=t-s,c=h.waitAsync(this.int32View,o.STATUS/4,a,i);if(c.async&&await c.value==="timed-out")return!1}}waitForResult(t){return h.wait(this.int32View,o.STATUS/4,r.READY,t)}notify(){return h.notify(this.int32View,o.STATUS/4)}reset(){this.setOpCode(n.NOOP),this.setStatus(r.PENDING),this.setPathLength(0),this.setDataLength(0),this.setResultLength(0),this.setErrorCode(l.NONE),this.setFlags(S.NONE),this.setMode(0)}};var O=class{fs;cwd;commandName;secureFetch;maxOutputSize;exec;invokeTool;protocol;running=!1;output={stdout:"",stderr:"",exitCode:0};outputLimitExceeded=!1;startTime=0;timeoutMs=0;constructor(t,e,a,s,i=void 0,c=0,d=void 0,E=void 0){this.fs=e,this.cwd=a,this.commandName=s,this.secureFetch=i,this.maxOutputSize=c,this.exec=d,this.invokeTool=E,this.protocol=new R(t)}remainingMs(){return Math.max(0,this.timeoutMs-(Date.now()-this.startTime))}raceDeadline(t){let e=this.remainingMs();if(e<=0)return this.running=!1,this.output.exitCode=124,this.output.stderr+=`
3
+ ${this.commandName}: execution timeout exceeded
4
+ `,Promise.reject(new Error("Operation timed out"));let a=t();return new Promise((s,i)=>{let c=T(()=>{this.running=!1,this.output.exitCode=124,this.output.stderr+=`
5
+ ${this.commandName}: execution timeout exceeded
6
+ `,i(new Error("Operation timed out"))},e);a.then(d=>{g(c),s(d)},d=>{g(c),i(d)})})}async run(t){for(this.running=!0,this.startTime=Date.now(),this.timeoutMs=t;this.running;){if(Date.now()-this.startTime>=t){this.output.stderr+=`
7
+ ${this.commandName}: execution timeout exceeded
8
+ `,this.output.exitCode=124;break}let a=this.remainingMs();if(!await this.protocol.waitUntilReady(a)){this.output.stderr+=`
9
+ ${this.commandName}: execution timeout exceeded
10
+ `,this.output.exitCode=124;break}let i=this.protocol.getOpCode();await this.handleOperation(i),this.protocol.notify()}return this.output}stop(){this.running=!1}async handleOperation(t){try{switch(t){case n.READ_FILE:await this.handleReadFile();break;case n.WRITE_FILE:await this.handleWriteFile();break;case n.STAT:await this.handleStat();break;case n.LSTAT:await this.handleLstat();break;case n.READDIR:await this.handleReaddir();break;case n.MKDIR:await this.handleMkdir();break;case n.RM:await this.handleRm();break;case n.EXISTS:await this.handleExists();break;case n.APPEND_FILE:await this.handleAppendFile();break;case n.SYMLINK:await this.handleSymlink();break;case n.READLINK:await this.handleReadlink();break;case n.CHMOD:await this.handleChmod();break;case n.REALPATH:await this.handleRealpath();break;case n.RENAME:await this.handleRename();break;case n.COPY_FILE:await this.handleCopyFile();break;case n.WRITE_STDOUT:this.handleWriteStdout();break;case n.WRITE_STDERR:this.handleWriteStderr();break;case n.EXIT:this.handleExit();break;case n.HTTP_REQUEST:await this.handleHttpRequest();break;case n.EXEC_COMMAND:await this.handleExecCommand();break;case n.INVOKE_TOOL:await this.handleInvokeTool();break;default:this.protocol.setErrorCode(l.IO_ERROR),this.protocol.setStatus(r.ERROR)}}catch(e){this.setErrorFromException(e)}}resolvePath(t){return this.fs.resolvePath(this.cwd,t)}async handleReadFile(){let t=this.resolvePath(this.protocol.getPath());try{let e=await this.fs.readFileBuffer(t);this.protocol.setResult(e),this.protocol.setStatus(r.SUCCESS)}catch(e){this.setErrorFromException(e)}}async handleWriteFile(){let t=this.resolvePath(this.protocol.getPath()),e=this.protocol.getData();try{await this.fs.writeFile(t,e),this.protocol.setStatus(r.SUCCESS)}catch(a){this.setErrorFromException(a)}}async handleStat(){let t=this.resolvePath(this.protocol.getPath());try{let e=await this.fs.stat(t);this.protocol.encodeStat(e),this.protocol.setStatus(r.SUCCESS)}catch(e){this.setErrorFromException(e)}}async handleLstat(){let t=this.resolvePath(this.protocol.getPath());try{let e=await this.fs.lstat(t);this.protocol.encodeStat(e),this.protocol.setStatus(r.SUCCESS)}catch(e){this.setErrorFromException(e)}}async handleReaddir(){let t=this.resolvePath(this.protocol.getPath());try{let e=await this.fs.readdir(t);this.protocol.setResultFromString(JSON.stringify(e)),this.protocol.setStatus(r.SUCCESS)}catch(e){this.setErrorFromException(e)}}async handleMkdir(){let t=this.resolvePath(this.protocol.getPath()),a=(this.protocol.getFlags()&S.MKDIR_RECURSIVE)!==0;try{await this.fs.mkdir(t,{recursive:a}),this.protocol.setStatus(r.SUCCESS)}catch(s){this.setErrorFromException(s)}}async handleRm(){let t=this.resolvePath(this.protocol.getPath()),e=this.protocol.getFlags(),a=(e&S.RECURSIVE)!==0,s=(e&S.FORCE)!==0;try{await this.fs.rm(t,{recursive:a,force:s}),this.protocol.setStatus(r.SUCCESS)}catch(i){this.setErrorFromException(i)}}async handleExists(){let t=this.resolvePath(this.protocol.getPath());try{let e=await this.fs.exists(t);this.protocol.setResult(new Uint8Array([e?1:0])),this.protocol.setStatus(r.SUCCESS)}catch(e){this.setErrorFromException(e)}}async handleAppendFile(){let t=this.resolvePath(this.protocol.getPath()),e=this.protocol.getData();try{await this.fs.appendFile(t,e),this.protocol.setStatus(r.SUCCESS)}catch(a){this.setErrorFromException(a)}}async handleSymlink(){let t=this.protocol.getPath(),e=this.protocol.getDataAsString(),a=this.resolvePath(t);try{await this.fs.symlink(e,a),this.protocol.setStatus(r.SUCCESS)}catch(s){this.setErrorFromException(s)}}async handleReadlink(){let t=this.resolvePath(this.protocol.getPath());try{let e=await this.fs.readlink(t);this.protocol.setResultFromString(e),this.protocol.setStatus(r.SUCCESS)}catch(e){this.setErrorFromException(e)}}async handleChmod(){let t=this.resolvePath(this.protocol.getPath()),e=this.protocol.getMode();try{await this.fs.chmod(t,e),this.protocol.setStatus(r.SUCCESS)}catch(a){this.setErrorFromException(a)}}async handleRealpath(){let t=this.resolvePath(this.protocol.getPath());try{let e=await this.fs.realpath(t);this.protocol.setResultFromString(e),this.protocol.setStatus(r.SUCCESS)}catch(e){this.setErrorFromException(e)}}async handleRename(){let t=this.resolvePath(this.protocol.getPath()),e=this.resolvePath(this.protocol.getDataAsString());try{await this.fs.mv(t,e),this.protocol.setStatus(r.SUCCESS)}catch(a){this.setErrorFromException(a)}}async handleCopyFile(){let t=this.resolvePath(this.protocol.getPath()),e=this.resolvePath(this.protocol.getDataAsString());try{await this.fs.cp(t,e),this.protocol.setStatus(r.SUCCESS)}catch(a){this.setErrorFromException(a)}}handleWriteStdout(){let t=this.protocol.getDataAsString();if(!this.tryAppendOutput("stdout",t)){this.outputLimitExceeded=!0,this.output.exitCode=1,this.appendOutputLimitError(),this.protocol.setErrorCode(l.IO_ERROR),this.protocol.setResultFromString("Output size limit exceeded"),this.protocol.setStatus(r.ERROR);return}this.protocol.setStatus(r.SUCCESS)}handleWriteStderr(){let t=this.protocol.getDataAsString();if(!this.tryAppendOutput("stderr",t)){this.outputLimitExceeded=!0,this.output.exitCode=1,this.appendOutputLimitError(),this.protocol.setErrorCode(l.IO_ERROR),this.protocol.setResultFromString("Output size limit exceeded"),this.protocol.setStatus(r.ERROR);return}this.protocol.setStatus(r.SUCCESS)}handleExit(){let t=this.protocol.getFlags();this.outputLimitExceeded?this.output.exitCode===0&&(this.output.exitCode=1):this.output.exitCode=t,this.protocol.setStatus(r.SUCCESS),this.running=!1}tryAppendOutput(t,e){return this.outputLimitExceeded?!1:this.maxOutputSize<=0?(t==="stdout"?this.output.stdout+=e:this.output.stderr+=e,!0):this.output.stdout.length+this.output.stderr.length+e.length>this.maxOutputSize?!1:(t==="stdout"?this.output.stdout+=e:this.output.stderr+=e,!0)}appendOutputLimitError(){if(this.maxOutputSize<=0)return;let t=`${this.commandName}: total output size exceeded (>${this.maxOutputSize} bytes), increase executionLimits.maxOutputSize
11
+ `,e=t.length>this.maxOutputSize?t.slice(0,this.maxOutputSize):t;if(this.output.stderr.includes("total output size exceeded"))return;let s=this.output.stdout.length+this.output.stderr.length+e.length-this.maxOutputSize;if(s>0)if(this.output.stdout.length>=s)this.output.stdout=this.output.stdout.slice(0,this.output.stdout.length-s);else{let i=s-this.output.stdout.length;this.output.stdout="",i>=this.output.stderr.length?this.output.stderr="":this.output.stderr=this.output.stderr.slice(0,this.output.stderr.length-i)}this.output.stderr+=e}async handleHttpRequest(){let t=this.secureFetch;if(!t){this.protocol.setErrorCode(l.NETWORK_NOT_CONFIGURED),this.protocol.setResultFromString("Network access not configured. Enable network in Bash options."),this.protocol.setStatus(r.ERROR);return}let e=this.protocol.getPath(),a=this.protocol.getDataAsString();try{let s=a?JSON.parse(a):{},i=this.remainingMs(),c=await this.raceDeadline(()=>t(e,{method:s.method,headers:s.headers,body:s.body,timeoutMs:i})),d=JSON.stringify({status:c.status,statusText:c.statusText,headers:c.headers,body:c.body,url:c.url});this.protocol.setResultFromString(d),this.protocol.setStatus(r.SUCCESS)}catch(s){let i=m(s instanceof Error?s.message:String(s));this.protocol.setErrorCode(l.NETWORK_ERROR),this.protocol.setResultFromString(i),this.protocol.setStatus(r.ERROR)}}async handleExecCommand(){let t=this.exec;if(!t){this.protocol.setErrorCode(l.IO_ERROR),this.protocol.setResultFromString("Command execution not available in this context."),this.protocol.setStatus(r.ERROR);return}let e=this.protocol.getPath(),a=this.protocol.getDataAsString(),s=new AbortController;try{let i={cwd:this.cwd,signal:s.signal};if(a){let E=JSON.parse(a);E.stdin&&(i.stdin=E.stdin),E.args&&Array.isArray(E.args)&&(i.args=E.args.map(D=>String(D)),e=F([e]))}let c=await this.raceDeadline(()=>t(e,i)),d=JSON.stringify({stdout:c.stdout,stderr:c.stderr,exitCode:c.exitCode});this.protocol.setResultFromString(d),this.protocol.setStatus(r.SUCCESS)}catch(i){s.abort();let c=i instanceof Error?i.message:String(i);this.protocol.setErrorCode(l.IO_ERROR),this.protocol.setResultFromString(c),this.protocol.setStatus(r.ERROR)}}async handleInvokeTool(){let t=this.invokeTool;if(!t){this.protocol.setErrorCode(l.IO_ERROR),this.protocol.setResultFromString("Tool invocation not available in this context."),this.protocol.setStatus(r.ERROR);return}let e=this.protocol.getPath(),a=this.protocol.getDataAsString();try{let s=await this.raceDeadline(()=>t(e,a));this.protocol.setResultFromString(s),this.protocol.setStatus(r.SUCCESS)}catch(s){let i=s instanceof Error?s.message:String(s);this.protocol.setErrorCode(l.IO_ERROR),this.protocol.setResultFromString(i),this.protocol.setStatus(r.ERROR)}}setErrorFromException(t){let e=t instanceof Error?t.message:String(t),a=m(e),s=l.IO_ERROR,i=e.toLowerCase();i.includes("no such file")||i.includes("not found")||i.includes("enoent")?s=l.NOT_FOUND:i.includes("is a directory")||i.includes("eisdir")?s=l.IS_DIRECTORY:i.includes("not a directory")||i.includes("enotdir")?s=l.NOT_DIRECTORY:i.includes("already exists")||i.includes("eexist")?s=l.EXISTS:(i.includes("permission")||i.includes("eperm")||i.includes("eacces"))&&(s=l.PERMISSION_DENIED),this.protocol.setErrorCode(s),this.protocol.setResultFromString(a),this.protocol.setStatus(r.ERROR)}};export{_ as a,O as b};
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import{a as A,b as P}from"./chunk-3KAVXQP4.js";import"./chunk-4OALHZXB.js";import"./chunk-MY5PY2PL.js";import"./chunk-LIYVQA3X.js";import{a as k,b as T}from"./chunk-OOJCYVYF.js";import{a as W}from"./chunk-4PRVMER6.js";import{b as C}from"./chunk-YU6OGPZR.js";import{a as M,b as x}from"./chunk-RLNOQILG.js";import{a as v}from"./chunk-4VDEBYW7.js";import{b as F}from"./chunk-GTNBSMZR.js";import"./chunk-KGOUQS5A.js";import{AsyncLocalStorage as U}from"node:async_hooks";import{randomBytes as I}from"node:crypto";import{fileURLToPath as J}from"node:url";import{Worker as D}from"node:worker_threads";var N=1e4,H=6e4,B=new U,_=`js-exec - Sandboxed JavaScript/TypeScript runtime with Node.js-compatible APIs
2
+ import{a as F,b as P}from"./chunk-MNMRGJJM.js";import"./chunk-4OALHZXB.js";import"./chunk-MY5PY2PL.js";import"./chunk-LIYVQA3X.js";import{a as v,b as T}from"./chunk-OOJCYVYF.js";import{a as M}from"./chunk-4PRVMER6.js";import{b as B}from"./chunk-YU6OGPZR.js";import{a as O,b as S}from"./chunk-RLNOQILG.js";import{a as E}from"./chunk-4VDEBYW7.js";import{b as L}from"./chunk-GTNBSMZR.js";import"./chunk-KGOUQS5A.js";import{AsyncLocalStorage as N}from"node:async_hooks";import{randomBytes as q}from"node:crypto";import{fileURLToPath as D}from"node:url";import{Worker as z}from"node:worker_threads";var _=1e4,I=6e4,W=new N,J=`js-exec - Sandboxed JavaScript/TypeScript runtime with Node.js-compatible APIs
3
3
 
4
4
  Usage: js-exec [OPTIONS] [-c CODE | FILE] [ARGS...]
5
5
 
@@ -84,14 +84,14 @@ Limits:
84
84
  Memory: 64 MB per execution
85
85
  Timeout: 10 s (60 s with network; configurable via maxJsTimeoutMs)
86
86
  Engine: QuickJS (compiled to WebAssembly)
87
- `;function z(t){let e={code:null,scriptFile:null,showVersion:!1,scriptArgs:[],isModule:!1,stripTypes:!1};if(t.length===0)return e;for(let r=0;r<t.length;r++){let s=t[r];if(s==="-m"||s==="--module"){e.isModule=!0;continue}if(s==="--strip-types"){e.stripTypes=!0;continue}if(s==="-c")return r+1>=t.length?{stdout:"",stderr:`js-exec: option requires an argument -- 'c'
87
+ `;function $(t){let e={code:null,scriptFile:null,showVersion:!1,scriptArgs:[],isModule:!1,stripTypes:!1};if(t.length===0)return e;for(let r=0;r<t.length;r++){let s=t[r];if(s==="-m"||s==="--module"){e.isModule=!0;continue}if(s==="--strip-types"){e.stripTypes=!0;continue}if(s==="-c")return r+1>=t.length?{stdout:"",stderr:`js-exec: option requires an argument -- 'c'
88
88
  `,exitCode:2}:(e.code=t[r+1],e.scriptArgs=t.slice(r+2),e);if(s==="--version"||s==="-V")return e.showVersion=!0,e;if(s.startsWith("-")&&s!=="-"&&s!=="--")return{stdout:"",stderr:`js-exec: unrecognized option '${s}'
89
- `,exitCode:2};if(s==="--")return r+1<t.length&&(e.scriptFile=t[r+1],e.scriptArgs=t.slice(r+2)),e;if(!s.startsWith("-"))return e.scriptFile=s,e.scriptArgs=t.slice(r+1),e}return e}var i=null,w=null,c=[],o=null,$=J(new URL("./worker.js",import.meta.url));function p(){for(;c.length>0&&c[0].canceled;)c.shift();if(o||c.length===0)return;let t=c.shift();if(!t)return;o=t,Q().postMessage(o.input)}function V(t,e){if(!t||typeof t!="object")return{success:!1,error:"Malformed worker response"};let r=t;return typeof r.protocolToken!="string"||r.protocolToken!==e?{success:!1,error:"Malformed worker response: invalid protocol token"}:typeof r.success!="boolean"?{success:!1,error:"Malformed worker response: missing success flag"}:r.success?{success:!0}:{success:!1,error:typeof r.error=="string"&&r.error.length>0?r.error:"Worker execution failed"}}function Q(){if(w&&(T(w),w=null),i)return i;let t=C.runTrusted(()=>new D($));return i=t,t.on("message",e=>{if(i===t){if(o){let r=V(e,o.input.protocolToken);o.resolve(r),o=null}c.length>0?p():G()}}),t.on("error",e=>{if(i===t){if(o){let r=x(v(e));o.resolve({success:!1,error:r}),o=null}for(let r of c)r.resolve({success:!1,error:"Worker crashed"});c.length=0,i=null}}),t.on("exit",()=>{i===t&&(i=null,o&&(o.resolve({success:!1,error:"Worker exited unexpectedly"}),o=null),c.length>0&&p())}),t}function G(){w=k(()=>{i&&!o&&c.length===0&&(i.terminate(),i=null)},5e3)}async function K(t,e,r,s=[],n,u,a){return B.getStore()?{stdout:"",stderr:`js-exec: recursive invocation is not supported
90
- `,exitCode:1}:X(t,e,r,s,n,u,a)}async function X(t,e,r,s=[],n,u,a){let m=A(),d=e.exec,g=d?(l,j)=>B.run(!0,()=>d(l,j)):void 0,q=new P(m,e.fs,e.cwd,"js-exec",e.fetch,e.limits?.maxOutputSize??0,g),E=e.limits?.maxJsTimeoutMs??N,h=e.fetch?Math.max(E,H):E,O={protocolToken:I(16).toString("hex"),sharedBuffer:m,jsCode:t,cwd:e.cwd,env:W(e.env),args:s,scriptPath:r,bootstrapCode:n,isModule:u,stripTypes:a,timeoutMs:h},b,L=new Promise(l=>{b=l}),f={input:O,resolve:()=>{}},R=k(()=>{if(o===f){let l=i;l&&(i=null,l.terminate()),o=null,p()}else f.canceled=!0,o||p();f.resolve({success:!1,error:`Execution timeout: exceeded ${h}ms limit`})},h);f.resolve=l=>{T(R),b(l)},c.push(f),p();let[y,S]=await Promise.all([q.run(h),L.catch(l=>({success:!1,error:x(v(l))}))]);return!S.success&&S.error?{stdout:y.stdout,stderr:`${y.stderr}js-exec: ${x(S.error)}
91
- `,exitCode:y.exitCode||1}:y}var de={name:"js-exec",async execute(t,e){if(F(t))return{stdout:_,stderr:"",exitCode:0};let r=z(t);if("exitCode"in r)return r;if(r.showVersion)return{stdout:`QuickJS (quickjs-emscripten)
92
- `,stderr:"",exitCode:0};let s,n;if(r.code!==null)s=r.code,n="-c";else if(r.scriptFile!==null){let d=e.fs.resolvePath(e.cwd,r.scriptFile);if(!await e.fs.exists(d))return{stdout:"",stderr:`js-exec: can't open file '${r.scriptFile}': No such file or directory
93
- `,exitCode:2};try{s=await e.fs.readFile(d),n=d}catch(g){return{stdout:"",stderr:`js-exec: can't open file '${r.scriptFile}': ${M(g.message)}
89
+ `,exitCode:2};if(s==="--")return r+1<t.length&&(e.scriptFile=t[r+1],e.scriptArgs=t.slice(r+2)),e;if(!s.startsWith("-"))return e.scriptFile=s,e.scriptArgs=t.slice(r+1),e}return e}var i=null,j=null,l=[],o=null,V=D(new URL("./worker.js",import.meta.url));function h(){for(;l.length>0&&l[0].canceled;)l.shift();if(o||l.length===0)return;let t=l.shift();if(!t)return;o=t,G().postMessage(o.input)}function Q(t,e){if(!t||typeof t!="object")return{success:!1,error:"Malformed worker response"};let r=t;return typeof r.protocolToken!="string"||r.protocolToken!==e?{success:!1,error:"Malformed worker response: invalid protocol token"}:typeof r.success!="boolean"?{success:!1,error:"Malformed worker response: missing success flag"}:r.success?{success:!0}:{success:!1,error:typeof r.error=="string"&&r.error.length>0?r.error:"Worker execution failed"}}function G(){if(j&&(T(j),j=null),i)return i;let t=B.runTrusted(()=>new z(V));return i=t,t.on("message",e=>{if(i===t){if(o){let r=Q(e,o.input.protocolToken);o.resolve(r),o=null}l.length>0?h():K()}}),t.on("error",e=>{if(i===t){if(o){let r=S(E(e));o.resolve({success:!1,error:r}),o=null}for(let r of l)r.resolve({success:!1,error:"Worker crashed"});l.length=0,i=null}}),t.on("exit",()=>{i===t&&(i=null,o&&(o.resolve({success:!1,error:"Worker exited unexpectedly"}),o=null),l.length>0&&h())}),t}function K(){j=v(()=>{i&&!o&&l.length===0&&(i.terminate(),i=null)},5e3)}async function X(t,e,r,s=[],n,u,a){return W.getStore()?{stdout:"",stderr:`js-exec: recursive invocation is not supported
90
+ `,exitCode:1}:Y(t,e,r,s,n,u,a)}async function Y(t,e,r,s=[],n,u,a){let y=F(),p=e.exec,x=p?(d,R)=>W.run(!0,()=>p(d,R)):void 0,b=new P(y,e.fs,e.cwd,"js-exec",e.fetch,e.limits?.maxOutputSize??0,x,e.executorInvokeTool),m=e.limits?.maxJsTimeoutMs??_,w=e.fetch?Math.max(m,I):m,c={protocolToken:q(16).toString("hex"),sharedBuffer:y,jsCode:t,cwd:e.cwd,env:M(e.env),args:s,scriptPath:r,bootstrapCode:n,isModule:u,stripTypes:a,timeoutMs:w,hasExecutorTools:e.executorInvokeTool!==void 0},A,U=new Promise(d=>{A=d}),g={input:c,resolve:()=>{}},H=v(()=>{if(o===g){let d=i;d&&(i=null,d.terminate()),o=null,h()}else g.canceled=!0,o||h();g.resolve({success:!1,error:`Execution timeout: exceeded ${w}ms limit`})},w);g.resolve=d=>{T(H),A(d)},l.push(g),h();let[k,C]=await Promise.all([b.run(w),U.catch(d=>({success:!1,error:S(E(d))}))]);return!C.success&&C.error?{stdout:k.stdout,stderr:`${k.stderr}js-exec: ${S(C.error)}
91
+ `,exitCode:k.exitCode||1}:k}async function de(t,e,r){if(W.getStore())return{result:null,error:"js-exec: recursive invocation is not supported"};let s=F(),n=new P(s,e.fs,e.cwd,"js-exec",e.fetch,e.limits?.maxOutputSize??0,void 0,r),u=e.limits?.maxJsTimeoutMs??_,a=e.fetch?Math.max(u,I):u,p={protocolToken:q(16).toString("hex"),sharedBuffer:s,jsCode:t,cwd:e.cwd,env:M(e.env),args:[],executorMode:!0,timeoutMs:a},x,b=new Promise(c=>{x=c}),m={input:p,resolve:()=>{}},w=v(()=>{if(o===m){let c=i;c&&(i=null,c.terminate()),o=null,h()}else m.canceled=!0,o||h();m.resolve({success:!1,error:`Execution timeout: exceeded ${a}ms limit`})},a);m.resolve=c=>{T(w),x(c)},l.push(m),h();let[,f]=await Promise.all([n.run(a),b.catch(c=>({success:!1,error:S(E(c))}))]);if("executorResult"in f&&f.executorResult!==void 0){let c;try{c=JSON.parse(f.executorResult)}catch{c=f.executorResult}return{result:c,logs:f.executorLogs}}return{result:null,error:f.error||"Unknown execution error",logs:"executorLogs"in f?f.executorLogs:void 0}}var fe={name:"js-exec",async execute(t,e){if(L(t))return{stdout:J,stderr:"",exitCode:0};let r=$(t);if("exitCode"in r)return r;if(r.showVersion)return{stdout:`QuickJS (quickjs-emscripten)
92
+ `,stderr:"",exitCode:0};let s,n;if(r.code!==null)s=r.code,n="-c";else if(r.scriptFile!==null){let p=e.fs.resolvePath(e.cwd,r.scriptFile);if(!await e.fs.exists(p))return{stdout:"",stderr:`js-exec: can't open file '${r.scriptFile}': No such file or directory
93
+ `,exitCode:2};try{s=await e.fs.readFile(p),n=p}catch(x){return{stdout:"",stderr:`js-exec: can't open file '${r.scriptFile}': ${O(x.message)}
94
94
  `,exitCode:2}}}else if(e.stdin.trim())s=e.stdin,n="<stdin>";else return{stdout:"",stderr:`js-exec: no input provided (use -c CODE or provide a script file)
95
- `,exitCode:2};let u=r.isModule,a=r.stripTypes;n&&n!=="-c"&&n!=="<stdin>"&&((n.endsWith(".mjs")||n.endsWith(".mts")||n.endsWith(".ts"))&&(u=!0),(n.endsWith(".ts")||n.endsWith(".mts"))&&(a=!0)),!u&&/\bawait\s+[\w([`]/.test(s)&&(u=!0);let m=e.jsBootstrapCode;return K(s,e,n,r.scriptArgs,m,u,a)}},fe={name:"node",async execute(){return{stdout:"",stderr:`node: this sandbox uses js-exec instead of node
95
+ `,exitCode:2};let u=r.isModule,a=r.stripTypes;n&&n!=="-c"&&n!=="<stdin>"&&((n.endsWith(".mjs")||n.endsWith(".mts")||n.endsWith(".ts"))&&(u=!0),(n.endsWith(".ts")||n.endsWith(".mts"))&&(a=!0)),!u&&/\bawait\s+[\w([`]/.test(s)&&(u=!0);let y=e.jsBootstrapCode;return X(s,e,n,r.scriptArgs,y,u,a)}},pe={name:"node",async execute(){return{stdout:"",stderr:`node: this sandbox uses js-exec instead of node
96
96
 
97
- ${_}`,exitCode:1}}};export{de as jsExecCommand,fe as nodeStubCommand};
97
+ ${J}`,exitCode:1}}};export{de as executeForExecutor,fe as jsExecCommand,pe as nodeStubCommand};
@@ -1530,7 +1530,9 @@ var OpCode = {
1530
1530
  // HTTP operations
1531
1531
  HTTP_REQUEST: 200,
1532
1532
  // Sub-shell execution
1533
- EXEC_COMMAND: 300
1533
+ EXEC_COMMAND: 300,
1534
+ // Tool invocation (executor mode)
1535
+ INVOKE_TOOL: 400
1534
1536
  };
1535
1537
  var Status = {
1536
1538
  PENDING: 0,
@@ -2003,6 +2005,18 @@ var SyncBackend = class {
2003
2005
  const responseJson = new TextDecoder().decode(result.result);
2004
2006
  return JSON.parse(responseJson);
2005
2007
  }
2008
+ /**
2009
+ * Invoke a tool through the main thread's tool invoker (executor mode).
2010
+ * Returns the JSON-serialized result.
2011
+ */
2012
+ invokeTool(path, argsJson) {
2013
+ const requestData = argsJson ? new TextEncoder().encode(argsJson) : void 0;
2014
+ const result = this.execSync(OpCode.INVOKE_TOOL, path, requestData);
2015
+ if (!result.success) {
2016
+ throw new Error(result.error || "Tool invocation failed");
2017
+ }
2018
+ return new TextDecoder().decode(result.result);
2019
+ }
2006
2020
  };
2007
2021
 
2008
2022
  // src/commands/js-exec/fetch-polyfill.ts
@@ -3813,6 +3827,26 @@ function setupContext(context, backend, input) {
3813
3827
  );
3814
3828
  context.setProp(context.global, "__execArgs", execArgsFn);
3815
3829
  execArgsFn.dispose();
3830
+ if (input.hasExecutorTools || input.executorMode) {
3831
+ const invokeToolFn = context.newFunction(
3832
+ "__invokeTool",
3833
+ (pathHandle, argsHandle) => {
3834
+ const path = context.getString(pathHandle);
3835
+ const argsJson = context.getString(argsHandle);
3836
+ try {
3837
+ const resultJson = backend.invokeTool(path, argsJson);
3838
+ return context.newString(resultJson);
3839
+ } catch (e) {
3840
+ return throwError(
3841
+ context,
3842
+ e.message || "tool invocation failed"
3843
+ );
3844
+ }
3845
+ }
3846
+ );
3847
+ context.setProp(context.global, "__invokeTool", invokeToolFn);
3848
+ invokeToolFn.dispose();
3849
+ }
3816
3850
  const envObj = jsToHandle(context, input.env);
3817
3851
  context.setProp(context.global, "env", envObj);
3818
3852
  envObj.dispose();
@@ -4070,6 +4104,78 @@ async function initializeWithDefense() {
4070
4104
  ]
4071
4105
  });
4072
4106
  }
4107
+ var TOOLS_ONLY_SETUP_SOURCE = `(function() {
4108
+ globalThis.tools = (function makeProxy(path) {
4109
+ return new Proxy(function(){}, {
4110
+ get: function(_t, prop) {
4111
+ if (prop === 'then' || typeof prop === 'symbol') return undefined;
4112
+ return makeProxy(path.concat([String(prop)]));
4113
+ },
4114
+ apply: function(_t, _this, args) {
4115
+ var toolPath = path.join('.');
4116
+ if (!toolPath) throw new Error('Tool path missing in invocation');
4117
+ var argsJson = args[0] !== undefined ? JSON.stringify(args[0]) : '{}';
4118
+ var resultJson = globalThis.__invokeTool(toolPath, argsJson);
4119
+ return resultJson !== undefined && resultJson !== '' ? JSON.parse(resultJson) : undefined;
4120
+ }
4121
+ });
4122
+ })([]);
4123
+ })();`;
4124
+ var EXECUTOR_SETUP_SOURCE = `(function() {
4125
+ var __logs = [];
4126
+ globalThis[Symbol.for('jb:executorLogs')] = __logs;
4127
+
4128
+ var _fmt = function(v) {
4129
+ if (typeof v === 'string') return v;
4130
+ try { return JSON.stringify(v); }
4131
+ catch(e) { return String(v); }
4132
+ };
4133
+
4134
+ globalThis.console = {
4135
+ log: function() { var a = []; for(var i=0;i<arguments.length;i++) a.push(_fmt(arguments[i])); __logs.push('[log] ' + a.join(' ')); },
4136
+ error: function() { var a = []; for(var i=0;i<arguments.length;i++) a.push(_fmt(arguments[i])); __logs.push('[error] ' + a.join(' ')); },
4137
+ warn: function() { var a = []; for(var i=0;i<arguments.length;i++) a.push(_fmt(arguments[i])); __logs.push('[warn] ' + a.join(' ')); },
4138
+ info: function() { var a = []; for(var i=0;i<arguments.length;i++) a.push(_fmt(arguments[i])); __logs.push('[info] ' + a.join(' ')); },
4139
+ debug: function() { var a = []; for(var i=0;i<arguments.length;i++) a.push(_fmt(arguments[i])); __logs.push('[debug] ' + a.join(' ')); },
4140
+ };
4141
+
4142
+ globalThis.tools = (function makeProxy(path) {
4143
+ return new Proxy(function(){}, {
4144
+ get: function(_t, prop) {
4145
+ if (prop === 'then' || typeof prop === 'symbol') return undefined;
4146
+ return makeProxy(path.concat([String(prop)]));
4147
+ },
4148
+ apply: function(_t, _this, args) {
4149
+ var toolPath = path.join('.');
4150
+ if (!toolPath) throw new Error('Tool path missing in invocation');
4151
+ var argsJson = args[0] !== undefined ? JSON.stringify(args[0]) : '{}';
4152
+ var resultJson = globalThis.__invokeTool(toolPath, argsJson);
4153
+ return resultJson !== undefined && resultJson !== '' ? JSON.parse(resultJson) : undefined;
4154
+ }
4155
+ });
4156
+ })([]);
4157
+ })();`;
4158
+ function readExecutorLogs(context) {
4159
+ const logsResult = context.evalCode(
4160
+ `globalThis[Symbol.for('jb:executorLogs')]`,
4161
+ "<read-logs>"
4162
+ );
4163
+ if (logsResult.error) {
4164
+ logsResult.error.dispose();
4165
+ return [];
4166
+ }
4167
+ const logs = context.dump(logsResult.value);
4168
+ logsResult.value.dispose();
4169
+ return Array.isArray(logs) ? logs : [];
4170
+ }
4171
+ function readPropDump(context, handle, key) {
4172
+ const prop = context.getProp(handle, key);
4173
+ try {
4174
+ return context.dump(prop);
4175
+ } finally {
4176
+ prop.dispose();
4177
+ }
4178
+ }
4073
4179
  async function executeCode(input) {
4074
4180
  const qjs = await getQuickJSModule();
4075
4181
  const backend = new SyncBackend(input.sharedBuffer, input.timeoutMs);
@@ -4277,6 +4383,132 @@ async function executeCode(input) {
4277
4383
  }
4278
4384
  bootstrapResult.value.dispose();
4279
4385
  }
4386
+ if (input.hasExecutorTools && !input.executorMode) {
4387
+ const toolsSetupResult = context.evalCode(
4388
+ TOOLS_ONLY_SETUP_SOURCE,
4389
+ "<tools-setup>"
4390
+ );
4391
+ if (toolsSetupResult.error) {
4392
+ toolsSetupResult.error.dispose();
4393
+ } else {
4394
+ toolsSetupResult.value.dispose();
4395
+ }
4396
+ }
4397
+ if (input.executorMode) {
4398
+ const executorSetupResult = context.evalCode(
4399
+ EXECUTOR_SETUP_SOURCE,
4400
+ "<executor-setup>"
4401
+ );
4402
+ if (executorSetupResult.error) {
4403
+ const errVal = context.dump(executorSetupResult.error);
4404
+ executorSetupResult.error.dispose();
4405
+ backend.exit(1);
4406
+ return {
4407
+ success: true,
4408
+ error: formatError(errVal),
4409
+ executorLogs: []
4410
+ };
4411
+ }
4412
+ executorSetupResult.value.dispose();
4413
+ const wrappedCode = `(async () => {
4414
+ ${input.jsCode}
4415
+ })()`;
4416
+ const evalResult = context.evalCode(wrappedCode, "<executor>");
4417
+ if (evalResult.error) {
4418
+ const errorVal = context.dump(evalResult.error);
4419
+ evalResult.error.dispose();
4420
+ const errorMsg = formatError(errorVal);
4421
+ backend.exit(1);
4422
+ return {
4423
+ success: true,
4424
+ executorLogs: readExecutorLogs(context),
4425
+ error: errorMsg
4426
+ };
4427
+ }
4428
+ context.setProp(context.global, "__executorPromise", evalResult.value);
4429
+ evalResult.value.dispose();
4430
+ const stateResult = context.evalCode(
4431
+ [
4432
+ "(function(p){",
4433
+ " var s = { v: void 0, e: void 0, settled: false };",
4434
+ " var fmtErr = function(e) {",
4435
+ " if (e && typeof e === 'object') {",
4436
+ " var m = typeof e.message === 'string' ? e.message : '';",
4437
+ " var st = typeof e.stack === 'string' ? e.stack : '';",
4438
+ " if (m && st) return st.indexOf(m) === -1 ? m + '\\n' + st : st;",
4439
+ " if (m) return m; if (st) return st;",
4440
+ " }",
4441
+ " return String(e);",
4442
+ " };",
4443
+ " p.then(",
4444
+ " function(v){ s.v = v; s.settled = true; },",
4445
+ " function(e){ s.e = fmtErr(e); s.settled = true; }",
4446
+ " );",
4447
+ " return s;",
4448
+ "})(__executorPromise)"
4449
+ ].join("\n"),
4450
+ "<state-tracker>"
4451
+ );
4452
+ if (stateResult.error) {
4453
+ const errorVal = context.dump(stateResult.error);
4454
+ stateResult.error.dispose();
4455
+ backend.exit(1);
4456
+ return {
4457
+ success: true,
4458
+ executorLogs: readExecutorLogs(context),
4459
+ error: formatError(errorVal)
4460
+ };
4461
+ }
4462
+ const stateHandle = stateResult.value;
4463
+ const pendingResult = runtime.executePendingJobs();
4464
+ if ("error" in pendingResult && pendingResult.error) {
4465
+ const errorVal = context.dump(pendingResult.error);
4466
+ pendingResult.error.dispose();
4467
+ const rawMsg = typeof errorVal === "object" && errorVal !== null && "message" in errorVal ? errorVal.message : String(errorVal);
4468
+ if (rawMsg !== "__EXIT__") {
4469
+ stateHandle.dispose();
4470
+ backend.exit(1);
4471
+ return {
4472
+ success: true,
4473
+ executorLogs: readExecutorLogs(context),
4474
+ error: formatError(errorVal)
4475
+ };
4476
+ }
4477
+ }
4478
+ const settled = readPropDump(context, stateHandle, "settled");
4479
+ const value = readPropDump(context, stateHandle, "v");
4480
+ const stateError = readPropDump(context, stateHandle, "e");
4481
+ stateHandle.dispose();
4482
+ const logs = readExecutorLogs(context);
4483
+ if (!settled) {
4484
+ backend.exit(0);
4485
+ return {
4486
+ success: true,
4487
+ executorLogs: logs,
4488
+ error: "Execution did not settle"
4489
+ };
4490
+ }
4491
+ if (typeof stateError !== "undefined") {
4492
+ backend.exit(0);
4493
+ return {
4494
+ success: true,
4495
+ executorLogs: logs,
4496
+ error: String(stateError)
4497
+ };
4498
+ }
4499
+ let resultJson;
4500
+ try {
4501
+ resultJson = value !== void 0 ? JSON.stringify(value) : void 0;
4502
+ } catch {
4503
+ resultJson = void 0;
4504
+ }
4505
+ backend.exit(0);
4506
+ return {
4507
+ success: true,
4508
+ executorResult: resultJson,
4509
+ executorLogs: logs
4510
+ };
4511
+ }
4280
4512
  const filename = input.scriptPath || "<eval>";
4281
4513
  let jsCode = input.jsCode;
4282
4514
  if (input.stripTypes) {
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import{a as _,b as O}from"./chunk-3KAVXQP4.js";import"./chunk-4OALHZXB.js";import"./chunk-MY5PY2PL.js";import"./chunk-LIYVQA3X.js";import{a as v,b as T}from"./chunk-OOJCYVYF.js";import{a as D}from"./chunk-4PRVMER6.js";import{c as y}from"./chunk-MO4RPBN2.js";import{b as C}from"./chunk-YU6OGPZR.js";import{a as M,b as c}from"./chunk-RLNOQILG.js";import{a as E}from"./chunk-4VDEBYW7.js";import{a as b,b as P}from"./chunk-GTNBSMZR.js";import"./chunk-KGOUQS5A.js";import{randomBytes as $}from"node:crypto";import{fileURLToPath as Q}from"node:url";import{Worker as R}from"node:worker_threads";var U=1e4,H=6e4,I={name:"python3",summary:"Execute Python code via CPython Emscripten",usage:"python3 [OPTIONS] [-c CODE | -m MODULE | FILE] [ARGS...]",description:["Execute Python code using CPython compiled to WebAssembly via Emscripten.","","This command runs Python in an isolated environment with access to","the virtual filesystem. Standard library modules are available."],options:["-c CODE Execute CODE as Python script","-m MODULE Run library module as a script","--version Show Python version","--help Show this help"],examples:['python3 -c "print(1 + 2)"','python3 -c "import sys; print(sys.version)"',"python3 script.py","python3 script.py arg1 arg2",`echo 'print("hello")' | python3`],notes:["CPython runs in WebAssembly, so execution may be slower than native Python.","Standard library modules are available (no pip install).","Maximum execution time is 30 seconds by default."]};function L(r){let e={code:null,module:null,scriptFile:null,showVersion:!1,scriptArgs:[]};if(r.length===0)return e;let t=r.findIndex(o=>!o.startsWith("-")||o==="-"||o==="--");for(let o=0;o<(t===-1?r.length:t);o++){let s=r[o];if(s==="-c")return o+1>=r.length?{stdout:"",stderr:`python3: option requires an argument -- 'c'
2
+ import{a as _,b as O}from"./chunk-MNMRGJJM.js";import"./chunk-4OALHZXB.js";import"./chunk-MY5PY2PL.js";import"./chunk-LIYVQA3X.js";import{a as v,b as T}from"./chunk-OOJCYVYF.js";import{a as D}from"./chunk-4PRVMER6.js";import{c as y}from"./chunk-MO4RPBN2.js";import{b as C}from"./chunk-YU6OGPZR.js";import{a as M,b as c}from"./chunk-RLNOQILG.js";import{a as E}from"./chunk-4VDEBYW7.js";import{a as b,b as P}from"./chunk-GTNBSMZR.js";import"./chunk-KGOUQS5A.js";import{randomBytes as $}from"node:crypto";import{fileURLToPath as Q}from"node:url";import{Worker as R}from"node:worker_threads";var U=1e4,H=6e4,I={name:"python3",summary:"Execute Python code via CPython Emscripten",usage:"python3 [OPTIONS] [-c CODE | -m MODULE | FILE] [ARGS...]",description:["Execute Python code using CPython compiled to WebAssembly via Emscripten.","","This command runs Python in an isolated environment with access to","the virtual filesystem. Standard library modules are available."],options:["-c CODE Execute CODE as Python script","-m MODULE Run library module as a script","--version Show Python version","--help Show this help"],examples:['python3 -c "print(1 + 2)"','python3 -c "import sys; print(sys.version)"',"python3 script.py","python3 script.py arg1 arg2",`echo 'print("hello")' | python3`],notes:["CPython runs in WebAssembly, so execution may be slower than native Python.","Standard library modules are available (no pip install).","Maximum execution time is 30 seconds by default."]};function L(r){let e={code:null,module:null,scriptFile:null,showVersion:!1,scriptArgs:[]};if(r.length===0)return e;let t=r.findIndex(o=>!o.startsWith("-")||o==="-"||o==="--");for(let o=0;o<(t===-1?r.length:t);o++){let s=r[o];if(s==="-c")return o+1>=r.length?{stdout:"",stderr:`python3: option requires an argument -- 'c'
3
3
  `,exitCode:2}:(e.code=r[o+1],e.scriptArgs=r.slice(o+2),e);if(s==="-m")return o+1>=r.length?{stdout:"",stderr:`python3: option requires an argument -- 'm'
4
4
  `,exitCode:2}:(e.module=r[o+1],e.scriptArgs=r.slice(o+2),e);if(s==="--version"||s==="-V")return e.showVersion=!0,e;if(s.startsWith("-")&&s!=="-")return{stdout:"",stderr:`python3: unrecognized option '${s}'
5
5
  `,exitCode:2}}if(t!==-1){let o=r[t];o==="--"?t+1<r.length&&(e.scriptFile=r[t+1],e.scriptArgs=r.slice(t+2)):(e.scriptFile=o,e.scriptArgs=r.slice(t+1))}return e}var k=new WeakMap;function z(r){let e=k.get(r);return e||(e={executionQueue:[],isExecuting:!1},k.set(r,e)),e}function ie(){k=new WeakMap}var N=Q(new URL("./worker.js",import.meta.url));function B(){return $(16).toString("hex")}function V(r,e){if(!r||typeof r!="object")return{success:!1,error:"Malformed worker response"};let t=r;return typeof t.protocolToken!="string"||t.protocolToken!==e?{success:!1,error:"Malformed worker response: invalid protocol token"}:t.type==="security-violation"?{success:!1,error:`Security violation: ${typeof t.violation?.type=="string"?t.violation.type:"unknown"}`}:typeof t.success!="boolean"?{success:!1,error:"Malformed worker response: missing success flag"}:t.success?{success:!0}:{success:!1,error:typeof t.error=="string"&&t.error.length>0?t.error:"Worker execution failed"}}function a(r){if(r.isExecuting||r.executionQueue.length===0)return;for(;r.executionQueue.length>0&&r.executionQueue[0].canceled;)r.executionQueue.shift();if(r.executionQueue.length===0)return;let e=r.executionQueue.shift();if(!e)return;r.isExecuting=!0;let t;try{t=C.runTrusted(()=>new R(N,{workerData:e.input}))}catch(n){let i=n instanceof Error?n.message:String(n);e.resolve({success:!1,error:c(i)}),r.isExecuting=!1,a(r);return}e.workerRef&&(e.workerRef.current=t);let o=y(e.requireDefenseContext,"python3","worker message callback",n=>{e.resolve(V(n,e.input.protocolToken)),r.isExecuting=!1,t.terminate(),a(r)}),s=y(e.requireDefenseContext,"python3","worker error callback",n=>{let i=c(E(n));e.resolve({success:!1,error:i}),r.isExecuting=!1,a(r)}),p=y(e.requireDefenseContext,"python3","worker exit callback",()=>{r.isExecuting&&(e.resolve({success:!1,error:"Worker exited unexpectedly"}),r.isExecuting=!1,a(r))}),f=n=>{try{o(n)}catch(i){let m=i instanceof Error?i.message:String(i);e.resolve({success:!1,error:c(m)}),r.isExecuting=!1,t.terminate(),a(r)}},l=n=>{try{s(n)}catch(i){let m=i instanceof Error?i.message:String(i);e.resolve({success:!1,error:c(m)}),r.isExecuting=!1,a(r)}},g=()=>{try{p()}catch(n){let i=n instanceof Error?n.message:String(n);e.resolve({success:!1,error:c(i)}),r.isExecuting=!1,a(r)}};t.on("message",f),t.on("error",l),t.on("exit",g)}async function j(r,e,t,o=[]){let s=_(),p=new O(s,e.fs,e.cwd,"python3",e.fetch,e.limits?.maxOutputSize??0),f=e.limits?.maxPythonTimeoutMs??U,l=e.fetch?Math.max(f,H):f,g=z(e.fs),n={protocolToken:B(),sharedBuffer:s,pythonCode:r,cwd:e.cwd,env:D(e.env),args:o,scriptPath:t,timeoutMs:l},i={current:null},m=new Promise(u=>{let d={input:n,resolve:()=>{},workerRef:i,requireDefenseContext:e.requireDefenseContext},A=y(e.requireDefenseContext,"python3","worker timeout callback",()=>{i.current?i.current.terminate():d.canceled=!0,u({success:!1,error:`Execution timeout: exceeded ${l}ms limit`})}),F=v(()=>{try{A()}catch(h){let W=h instanceof Error?h.message:String(h);u({success:!1,error:c(W)})}},l);d.resolve=h=>{T(F),u(h)},g.executionQueue.push(d),a(g)}),[x,w]=await Promise.all([p.run(l).catch(u=>({stdout:"",stderr:`python3: bridge error: ${c(E(u))}
@@ -1569,7 +1569,9 @@ var OpCode = {
1569
1569
  // HTTP operations
1570
1570
  HTTP_REQUEST: 200,
1571
1571
  // Sub-shell execution
1572
- EXEC_COMMAND: 300
1572
+ EXEC_COMMAND: 300,
1573
+ // Tool invocation (executor mode)
1574
+ INVOKE_TOOL: 400
1573
1575
  };
1574
1576
  var Status = {
1575
1577
  PENDING: 0,
@@ -2042,6 +2044,18 @@ var SyncBackend = class {
2042
2044
  const responseJson = new TextDecoder().decode(result.result);
2043
2045
  return JSON.parse(responseJson);
2044
2046
  }
2047
+ /**
2048
+ * Invoke a tool through the main thread's tool invoker (executor mode).
2049
+ * Returns the JSON-serialized result.
2050
+ */
2051
+ invokeTool(path, argsJson) {
2052
+ const requestData = argsJson ? new TextEncoder().encode(argsJson) : void 0;
2053
+ const result = this.execSync(OpCode.INVOKE_TOOL, path, requestData);
2054
+ if (!result.success) {
2055
+ throw new Error(result.error || "Tool invocation failed");
2056
+ }
2057
+ return new TextDecoder().decode(result.result);
2058
+ }
2045
2059
  };
2046
2060
 
2047
2061
  // src/commands/python3/worker.ts