@typhons/sandbox-tools 0.5.6 → 0.5.8

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.
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import{execSync as r}from"child_process";import f from"fs";import{setTimeout as x}from"timers/promises";var u=30,g=1,b=100,w=!1,v=!1,d=process.argv.slice(2);for(let e=0;e<d.length;e++)d[e]==="--json"?w=!0:d[e]==="--threshold"?u=parseInt(d[++e],10):d[e]==="--daemon"&&(v=!0);function _(e){try{if(e==="claude")return r("pgrep -x claude 2>/dev/null | head -1",{encoding:"utf8"}).trim()||null;if(e==="codex"){let t=r("pgrep -f 'node.*codex' 2>/dev/null",{encoding:"utf8"}).trim().split(`
3
- `);for(let n of t)if(n)try{let o=f.readFileSync(`/proc/${n}/cmdline`,"utf8").replace(/\0/g," ");if(/codex\.js|codex\/bin|@openai\/codex/.test(o))return n}catch{}}}catch{}return null}function T(){try{let e=r('find /home -name "*.jsonl" -path "*/.claude/projects/*" ! -path "*/subagents/*" -printf "%T@ %p\\n" 2>/dev/null | sort -rn | head -1',{encoding:"utf8"}).trim();if(e){let t=parseInt(e.split(" ")[0],10);return Math.floor(Date.now()/1e3)-t}}catch{}return-1}function E(){let e=-1,t=["/home/*/.codex/log/codex-tui.log","/root/.codex/log/codex-tui.log"];for(let n of t)try{let o=r(`ls ${n} 2>/dev/null`,{encoding:"utf8"}).trim().split(`
4
- `);for(let c of o)if(c)try{let a=f.statSync(c),l=Math.floor(Date.now()/1e3)-Math.floor(a.mtimeMs/1e3);(e===-1||l<e)&&(e=l)}catch{}}catch{}return e}function $(e){if(!e)return 0;let t=0;try{let n=r(`pgrep -P ${e} 2>/dev/null`,{encoding:"utf8"}).trim().split(`
5
- `);for(let o of n)if(o)try{if(f.readFileSync(`/proc/${o}/cmdline`,"utf8").replace(/\0/g," ").includes("check-claude-active"))continue;t++}catch{t++}}catch{}return t}function s(e){try{let n=f.readFileSync(`/proc/${e}/io`,"utf8").match(/^rchar:\s*(\d+)/m);return n?parseInt(n[1],10):0}catch{return 0}}async function A(e){if(!e)return 0;let t=s(e);return await x(g*1e3),s(e)-t}async function I(){let e=_("claude"),t=_("codex"),n=T(),o=E(),c=n>=0&&n<u||o>=0&&o<u,a=$(e),l=$(t),y=a>0||l>0,i=0;if(e&&t){let O=s(e),S=s(t);await x(g*1e3);let N=s(e),D=s(t);i=Math.max(N-O,D-S)}else e?i=await A(e):t&&(i=await A(t));let h=i>b,p=c||y||h,m=e&&t?"both":e?"claude":t?"codex":"none";return w||v?console.log(JSON.stringify({active:p,agent:m,claude_pid:e?parseInt(e):null,codex_pid:t?parseInt(t):null,claude_jsonl_age:n,codex_log_age:o,log_active:c,children:a+l,io_delta:i,io_active:h})):!e&&!t?console.log("Agents: not running"):p?(console.log(`Agent: ACTIVE (${m})`),c&&(n>=0&&n<u&&console.log(` Claude JSONL written ${n}s ago`),o>=0&&o<u&&console.log(` Codex log written ${o}s ago`)),y&&console.log(` ${a} claude + ${l} codex child process(es)`),h&&console.log(` I/O: ${i} bytes read in ${g}s`)):(console.log(`Agent: idle (${m} running, waiting for user)`),e&&console.log(` Claude JSONL last written ${n}s ago`),t&&console.log(` Codex log last written ${o}s ago`),console.log(" No child processes"),console.log(` I/O: ${i} bytes in ${g}s`)),p}function C(){try{return f.readFileSync("/run/e2b/.DEVBOX_NAME","utf8").trim()}catch{}return""}if(v){let e=process.env.E2B_HTTP_DOMAIN||"d.typhons.dev";for(console.log(`[agent-keepalive] domain=${e} interval=30s`);;){if(await I()){let n=C();if(n){let o=`https://${n}.${e}:49999/`;try{r(`curl -sf -o /dev/null -w '%{http_code}' --max-time 5 "${o}" 2>/dev/null`,{encoding:"utf8"})}catch{}}else console.log("[agent-keepalive] no devbox name available yet, skipping ping")}await x(29e3)}}else{let e=await I();process.exit(e?0:1)}
2
+ import{execSync as g}from"child_process";import f from"fs";import{setTimeout as D}from"timers/promises";import{execSync as b}from"child_process";function m(e){let t="";try{t=b(`pgrep -x ${e} 2>/dev/null`,{encoding:"utf8"})}catch{}return t.split(`
3
+ `).map(o=>o.trim()).filter(Boolean)}var a=30,x=1,T=100,M=!1,v=!1,r=process.argv.slice(2);for(let e=0;e<r.length;e++)r[e]==="--json"?M=!0:r[e]==="--threshold"?a=parseInt(r[++e],10):r[e]==="--daemon"&&(v=!0);function E(){try{let e=g('find /home -name "*.jsonl" -path "*/.claude/projects/*" ! -path "*/subagents/*" -printf "%T@ %p\\n" 2>/dev/null | sort -rn | head -1',{encoding:"utf8"}).trim();if(e){let t=parseInt(e.split(" ")[0],10);return Math.floor(Date.now()/1e3)-t}}catch{}return-1}function B(){let e=-1,t=["/home/*/.codex/log/codex-tui.log","/root/.codex/log/codex-tui.log"];for(let o of t)try{let n=g(`ls ${o} 2>/dev/null`,{encoding:"utf8"}).trim().split(`
4
+ `);for(let l of n)if(l)try{let i=f.statSync(l),s=Math.floor(Date.now()/1e3)-Math.floor(i.mtimeMs/1e3);(e===-1||s<e)&&(e=s)}catch{}}catch{}return e}function O(e){let t=0;for(let o of e)try{let n=g(`pgrep -P ${o} 2>/dev/null`,{encoding:"utf8"}).trim().split(`
5
+ `);for(let l of n)if(l)try{if(f.readFileSync(`/proc/${l}/cmdline`,"utf8").replace(/\0/g," ").includes("check-claude-active"))continue;t++}catch{t++}}catch{}return t}function w(e){try{let o=f.readFileSync(`/proc/${e}/io`,"utf8").match(/^rchar:\s*(\d+)/m);return o?parseInt(o[1],10):0}catch{return 0}}async function N(){let e=m("claude"),t=m("codex"),o=E(),n=B(),l=o>=0&&o<a||n>=0&&n<a,i=O(e),s=O(t),$=i>0||s>0,y=[...e,...t],_=y.map(w);await D(x*1e3);let A=y.map(w),I=0,S=0;for(let c=0;c<e.length;c++)I+=Math.max(0,A[c]-_[c]);for(let c=0;c<t.length;c++)S+=Math.max(0,A[e.length+c]-_[e.length+c]);let d=Math.max(I,S),u=d>T,h=l||$||u,p=e.length&&t.length?"both":e.length?"claude":t.length?"codex":"none";return M||v?console.log(JSON.stringify({active:h,agent:p,claude_pids:e.map(c=>parseInt(c,10)),codex_pids:t.map(c=>parseInt(c,10)),claude_jsonl_age:o,codex_log_age:n,log_active:l,children:i+s,io_delta:d,io_active:u})):!e.length&&!t.length?console.log("Agents: not running"):h?(console.log(`Agent: ACTIVE (${p}; ${e.length} claude + ${t.length} codex)`),l&&(o>=0&&o<a&&console.log(` Claude JSONL written ${o}s ago`),n>=0&&n<a&&console.log(` Codex log written ${n}s ago`)),$&&console.log(` ${i} claude + ${s} codex child process(es)`),u&&console.log(` I/O: ${d} bytes read in ${x}s`)):(console.log(`Agent: idle (${p}; ${e.length} claude + ${t.length} codex running, waiting for user)`),e.length&&console.log(` Claude JSONL last written ${o}s ago`),t.length&&console.log(` Codex log last written ${n}s ago`),console.log(" No child processes"),console.log(` I/O: ${d} bytes in ${x}s`)),h}function C(){try{return f.readFileSync("/run/e2b/.DEVBOX_NAME","utf8").trim()}catch{}return""}if(v){let e=process.env.E2B_HTTP_DOMAIN||"d.typhons.dev";for(console.log(`[agent-keepalive] domain=${e} interval=30s`);;){if(await N()){let o=C();if(o){let n=`https://${o}.${e}:49999/`;try{g(`curl -sf -o /dev/null -w '%{http_code}' --max-time 5 "${n}" 2>/dev/null`,{encoding:"utf8"})}catch{}}else console.log("[agent-keepalive] no devbox name available yet, skipping ping")}await D(29e3)}}else{let e=await N();process.exit(e?0:1)}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@typhons/sandbox-tools",
3
- "version": "0.5.6",
3
+ "version": "0.5.8",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "sandbox-relay-client": "./relay-client.js",
package/stop-agents.js CHANGED
@@ -1,8 +1,9 @@
1
1
  #!/usr/bin/env node
2
- import{execSync as e}from"child_process";import l from"fs";function n(t){console.log(`[stop-agents] ${t}`)}function r(t,d){let o;try{o=e(`pgrep -f "${d}" 2>/dev/null | head -1`,{encoding:"utf8"}).trim()}catch{}if(!o){n(`No ${t} process found`);return}let c;try{c=l.readlinkSync(`/proc/${o}/fd/0`)}catch{}if(!c||!c.startsWith("/dev/pts/")){n(`${t} (pid ${o}) has no PTY (fd/0 -> ${c}), skipping`);return}n(`Injecting Escape into ${t} (pid ${o}, tty ${c})`);try{e(`sudo python3 -c "
2
+ import{execSync as s}from"child_process";import p from"fs";import{execSync as d}from"child_process";function r(n){let o="";try{o=d(`pgrep -x ${n} 2>/dev/null`,{encoding:"utf8"})}catch{}return o.split(`
3
+ `).map(t=>t.trim()).filter(Boolean)}function c(n){console.log(`[stop-agents] ${n}`)}function l(n,o){let t;try{t=p.readlinkSync(`/proc/${o}/fd/0`)}catch{}if(!t||!t.startsWith("/dev/pts/")){c(`${n} (pid ${o}) has no PTY (fd/0 -> ${t}), skipping`);return}c(`Injecting Escape into ${n} (pid ${o}, tty ${t})`);try{s(`sudo python3 -c "
3
4
  import fcntl, os, struct
4
- fd = os.open('${c}', os.O_WRONLY)
5
+ fd = os.open('${t}', os.O_WRONLY)
5
6
  fcntl.ioctl(fd, 0x5412, struct.pack('b', 0x1b))
6
7
  os.close(fd)
7
- "`,{stdio:"ignore"}),n(`Escape injected for ${t}`)}catch{n(`TIOCSTI failed for ${t}, falling back to killing children`);try{let s=e(`pgrep -P ${o} 2>/dev/null`,{encoding:"utf8"}).trim().split(`
8
- `);for(let i of s)if(i)try{process.kill(parseInt(i),"SIGINT")}catch{}}catch{}}}r("Claude Code","^claude$");r("Codex","@openai/codex");n("Done");
8
+ "`,{stdio:"ignore"}),c(`Escape injected for ${n} (pid ${o})`)}catch{c(`TIOCSTI failed for ${n} (pid ${o}), falling back to SIGINT-ing children`);try{let e=s(`pgrep -P ${o} 2>/dev/null`,{encoding:"utf8"}).trim().split(`
9
+ `);for(let i of e)if(i)try{process.kill(parseInt(i),"SIGINT")}catch{}}catch{}}}function f(n,o){let t=r(o);if(t.length===0){c(`No ${n} process found`);return}c(`Found ${t.length} ${n} instance${t.length===1?"":"s"}: ${t.join(", ")}`);for(let e of t)l(n,e)}f("Claude Code","claude");f("Codex","codex");c("Done");