alchemylab 2.3.0 → 3.0.1

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.
@@ -6,82 +6,96 @@ return t[n].call(module.exports,module,module.exports,e),module.loaded=!0,module
6
6
  const t=String(e??"").trim().toLowerCase().match(/^(\d+(?:\.\d+)?)\s*([bkmg]?)b?$/)
7
7
  if(!t)return NaN
8
8
  const r={"":1,b:1,k:1024,m:1048576,g:1024**3}[t[2]]
9
- return Math.round(parseFloat(t[1])*r)}function n(e,t,r,n){return e>0&&r>0?t+r<=e?null:`Not started: this ${n} needs ${u(r)} of memory, and the boxes already running on this machine have ${u(t)} of the ${u(e)} Docker can give. Stop a box you no longer need (experiment_list shows yours) or try again when one ends.`:null}function o(e){if(!Number.isInteger(e)||e<=0)return!0
10
- try{return process.kill(e,0),!0}catch(e){return"EPERM"===e?.code}}function s(e,t,r=o){return!(!e||!d.has(t)||r(Number(e)))}async function a(){const e=await(0,l.docker)(["ps","-a","--filter","label=alchemy.project","--filter","status=running","--filter","status=created","--format",'{{.ID}}\t{{.Label "alchemy.owner"}}\t{{.Label "alchemy.sandbox"}}'],l.DOCKER_OP_TIMEOUT_MS)
9
+ return Math.round(parseFloat(t[1])*r)}function n(e,t,r,n){return e>0&&r>0?t+r<=e?null:`Not started: this ${n} needs ${p(r)} of memory, and the boxes already running on this machine have ${p(t)} of the ${p(e)} Docker can give. Stop a box you no longer need (experiment_list shows yours) or try again when one ends.`:null}async function o(){const e=r(process.env.ALCHEMY_BOX_MEMORY_BUDGET)
10
+ if(e>0)return e
11
+ const t=await(0,d.docker)(["info","--format","{{.MemTotal}}"],d.DOCKER_OP_TIMEOUT_MS)
12
+ return 0===t.exit?Number(t.stdout.trim()):NaN}function s(e){if(!Number.isInteger(e)||e<=0)return!0
13
+ try{return process.kill(e,0),!0}catch(e){return"EPERM"===e?.code}}function a(e,t,r=s){return!(!e||!f.has(t)||r(Number(e)))}async function i(){const e=await(0,d.docker)(["ps","-a","--filter","label=alchemy.project","--filter","status=running","--filter","status=created","--format",'{{.ID}}\t{{.Label "alchemy.owner"}}\t{{.Label "alchemy.sandbox"}}'],d.DOCKER_OP_TIMEOUT_MS)
11
14
  if(0!==e.exit)return 0
12
15
  const t=[]
13
16
  for(const r of e.stdout.split("\n").map(e=>e.trim()).filter(Boolean)){const[e,n="",o=""]=r.split("\t")
14
- s(n,o)?await(0,l.docker)(["rm","-f","-v",e],l.DOCKER_OP_TIMEOUT_MS):t.push(e)}if(!t.length)return 0
15
- const r=await(0,l.docker)(["inspect","--format","{{.HostConfig.Memory}}",...t],l.DOCKER_OP_TIMEOUT_MS)
16
- return 0!==r.exit?0:r.stdout.split("\n").map(e=>Number(e.trim())||0).reduce((e,t)=>e+t,0)}function i(e){const t=[]
17
+ a(n,o)?await(0,d.docker)(["rm","-f","-v",e],d.DOCKER_OP_TIMEOUT_MS):t.push(e)}if(!t.length)return 0
18
+ const r=await(0,d.docker)(["inspect","--format","{{.HostConfig.Memory}}",...t],d.DOCKER_OP_TIMEOUT_MS)
19
+ return 0!==r.exit?0:r.stdout.split("\n").map(e=>Number(e.trim())||0).reduce((e,t)=>e+t,0)}async function c(e,t,s=exports.ROOM_WAIT_MS,a=5e3,c=i,l=o){try{const o=r(e),i=await l(),u=Date.now()+s
20
+ for(function(){const e=(0,d.containerLabels)()
21
+ "check"===e["alchemy.purpose"]&&e["alchemy.request"]}();;){const e=n(i,await c(),o,t)
22
+ if(!e)return null
23
+ if(Date.now()>=u)return e
24
+ await new Promise(e=>setTimeout(e,a))}}catch{return null}}function l(e){const t=[]
17
25
  for(const r of String(e||"").split(",").map(e=>e.trim()).filter(Boolean)){const e=r.match(/^(\d+)(?:-(\d+))?$/)
18
26
  if(!e)continue
19
27
  const n=Number(e[1]),o=void 0!==e[2]?Number(e[2]):n
20
- for(let e=n;e<=o&&e-n<1024;e++)t.push(e)}return t}function c(e,t,r){const n=new Array(e).fill(0)
21
- for(const t of r)for(const r of i(t))r<e&&n[r]++
22
- return[...n.keys()].sort((e,t)=>n[e]-n[t]||e-t).slice(0,t).sort((e,t)=>e-t)}exports.TS=void 0,exports.withAdmission=function(e,t,o){const s=p.then(async()=>{const s=await async function(e,t,o=12e4,s=5e3){try{const i=r(e),c=await async function(){const e=r(process.env.ALCHEMY_BOX_MEMORY_BUDGET)
23
- if(e>0)return e
24
- const t=await(0,l.docker)(["info","--format","{{.MemTotal}}"],l.DOCKER_OP_TIMEOUT_MS)
25
- return 0===t.exit?Number(t.stdout.trim()):NaN}(),u=Date.now()+o
26
- for(;;){const e=n(c,await a(),i,t)
27
- if(!e||Date.now()>=u)return e
28
- await new Promise(e=>setTimeout(e,s))}}catch{return null}}(e,t)
29
- return s?{refused:s}:{value:await o()}})
30
- return p=s.catch(()=>{}),s},exports.pickCores=async function(e,t,r="standard"){try{const n=await(0,l.docker)(["info","--format","{{.NCPU}}"],l.DOCKER_OP_TIMEOUT_MS),o=Number(n.stdout.trim())
28
+ for(let e=n;e<=o&&e-n<1024;e++)t.push(e)}return t}function u(e,t,r){const n=new Array(e).fill(0)
29
+ for(const t of r)for(const r of l(t))r<e&&n[r]++
30
+ return[...n.keys()].sort((e,t)=>n[e]-n[t]||e-t).slice(0,t).sort((e,t)=>e-t)}exports.TS=exports.FY=exports.ROOM_WAIT_MS=exports.Lt=exports.kz=exports.IDLE_GRACE_MS=void 0,exports.waitForRoom=c,exports.withAdmission=function(e,t,r,n){h++,h>1&&n?.(`waiting behind ${h-1} other box start(s)`,(h-1)*exports.FY)
31
+ const o=m.then(async()=>{n?.("waiting for room to start its box",exports.FY)
32
+ const o=await c(e,t)
33
+ return o?{refused:o}:{value:await r()}})
34
+ return m=o.catch(()=>{}),o.catch(()=>{}).then(()=>{h--}),o},exports.pickCores=async function(e,t,r="standard"){try{const n=await(0,d.docker)(["info","--format","{{.NCPU}}"],d.DOCKER_OP_TIMEOUT_MS),o=Number(n.stdout.trim())
31
35
  if(!(o>0))return{cpus:e??t}
32
- const s=await(0,l.docker)(["ps","-a","-q","--filter","label=alchemy.project","--filter","status=running","--filter","status=created"],l.DOCKER_OP_TIMEOUT_MS),a=0===s.exit?s.stdout.split("\n").map(e=>e.trim()).filter(Boolean):[],u=a.length?(await(0,l.docker)(["inspect","--format","{{.HostConfig.CpusetCpus}}",...a],l.DOCKER_OP_TIMEOUT_MS)).stdout.split("\n").map(e=>e.trim()).filter(Boolean):[],d=new Set(u.flatMap(i).filter(e=>e<o)),p=e??function(e,t,r){return"light"===e?2:"heavy"===e?Math.max(2,Math.min(t-2,r-2)):function(e,t){const r=Math.max(2,Math.floor(e/2))
33
- return Math.min(r,Math.max(2,Math.ceil(t/2)))}(t,r)}(r,o,o-d.size),f=Math.max(1,Math.ceil(p))
34
- return f>=o?{cpus:p}:{cpus:p,cpuset:c(o,f,u).join(",")}}catch{return{cpus:e??t}}}
35
- const l=t(81618),u=e=>`${(e/1024**3).toFixed(1)} GB`,d=new Set(["experiment","rung1","deps","egress-proxy","service"])
36
- let p=Promise.resolve()
37
- exports.TS=["light","standard","heavy"]},52429(e,exports,t){exports.ContainerRunner=void 0
38
- const r=t(81618),n=t(22604),o=t(11895),s=t(26166),a=t(2566),i=t(90695),c=t(61260)
39
- exports.ContainerRunner=class{constructor(e={}){this.image=e.image??"node:20-alpine",this.stepTimeoutMs=e.stepTimeoutMs??12e4,this.network=e.network??"none",this.resources=e.resources??{}}async run(e){if(!e.worktreePath)return{steps:[],ok:!1,error:"worktreePath is required"}
40
- const t=e.image??this.image,s={}
41
- let l=Date.now()
42
- const u=e=>{const t=Date.now()
43
- s[e]=(s[e]??0)+(t-l),l=t},d=await(0,r.ensureImage)(t)
44
- if(u("image"),d)return{steps:[],ok:!1,error:d}
45
- const p=await(0,n.withAdmission)(this.resources.memory??"1g","check",async()=>{const{cpus:s,cpuset:a}=await(0,n.pickCores)(this.resources.cpus,o.DEFAULT_CPUS,this.resources.size)
46
- let c=await(0,r.docker)(this.createArgs(e,t,!0,a,s),r.DOCKER_OP_TIMEOUT_MS)
47
- if(0!==c.exit)return{error:c.spawnError??`docker create failed: ${(c.stderr||String(c.exit)).trim()}`}
48
- let l=c.stdout.trim()
49
- if(u("create"),await(0,i.claimScratch)(l,t,"1000:1000")){if(await(0,r.docker)(["rm","-f","-v",l],r.DOCKER_OP_TIMEOUT_MS),c=await(0,r.docker)(this.createArgs(e,t,!1,a,s),r.DOCKER_OP_TIMEOUT_MS),0!==c.exit)return{error:c.spawnError??`docker create failed: ${(c.stderr||String(c.exit)).trim()}`}
50
- l=c.stdout.trim()}return u("scratch"),{id:l}})
51
- if("refused"in p)return{steps:[],ok:!1,error:p.refused}
52
- if("error"in p.value)return{steps:[],ok:!1,error:p.value.error}
53
- const f=p.value.id
54
- try{const t=await(0,r.docker)(["start",f],r.DOCKER_OP_TIMEOUT_MS)
55
- if(u("start"),0!==t.exit)return{steps:[],ok:!1,error:`docker start failed: ${(t.stderr||String(t.exit)).trim()}`}
36
+ const s=await(0,d.docker)(["ps","-a","-q","--filter","label=alchemy.project","--filter","status=running","--filter","status=created"],d.DOCKER_OP_TIMEOUT_MS),a=0===s.exit?s.stdout.split("\n").map(e=>e.trim()).filter(Boolean):[],i=a.length?(await(0,d.docker)(["inspect","--format","{{.HostConfig.CpusetCpus}}",...a],d.DOCKER_OP_TIMEOUT_MS)).stdout.split("\n").map(e=>e.trim()).filter(Boolean):[],c=new Set(i.flatMap(l).filter(e=>e<o)),p=e??function(e,t,r){return"light"===e?2:"heavy"===e?Math.max(2,Math.min(t-2,r-2)):function(e,t){const r=Math.max(2,Math.floor(e/2))
37
+ return Math.min(r,Math.max(2,Math.ceil(t/2)))}(t,r)}(r,o,o-c.size),f=Math.max(1,Math.ceil(p))
38
+ return f>=o?{cpus:p}:{cpus:p,cpuset:u(o,f,i).join(",")}}catch{return{cpus:e??t}}}
39
+ const d=t(81618),p=e=>`${(e/1024**3).toFixed(1)} GB`,f=new Set(["experiment","rung1","deps","egress-proxy","service"])
40
+ exports.IDLE_GRACE_MS=3e5,exports.kz=6e4,exports.Lt=3e4,exports.ROOM_WAIT_MS=12e4
41
+ let m=Promise.resolve(),h=0
42
+ exports.FY=exports.ROOM_WAIT_MS+6*d.DOCKER_OP_TIMEOUT_MS,exports.TS=["light","standard","heavy"]},52429(e,exports,t){exports.ContainerRunner=void 0
43
+ const r=t(81618),n=t(83129),o=t(22604),s=t(11895),a=t(26166),i=t(2566),c=t(90695),l=t(61260),u=6e5
44
+ exports.ContainerRunner=class{constructor(e={}){this.image=e.image??"node:20-alpine",this.stepTimeoutMs=e.stepTimeoutMs??12e4,this.network=e.network??"none",this.resources=e.resources??{},this.memory=(0,s.memoryForBox)(this.resources.memory,this.resources.size)}async run(e){if(!e.worktreePath)return{steps:[],ok:!1,error:"worktreePath is required"}
45
+ const t=e.image??this.image,a={}
46
+ let d=Date.now()
47
+ const p=e=>{const t=Date.now()
48
+ a[e]=(a[e]??0)+(t-d),d=t},f=e.onStep??(()=>{})
49
+ f("getting its image",r.DOCKER_OP_TIMEOUT_MS+((0,n.localRecipeFor)(t)?n.BUILD_TIMEOUT_MS:r.PULL_TIMEOUT_MS))
50
+ const m=await(0,r.ensureImage)(t)
51
+ if(p("image"),m)return{steps:[],ok:!1,error:m}
52
+ if("background"===this.resources.priority){f("waiting for room to start its box",u+r.DOCKER_OP_TIMEOUT_MS)
53
+ const e=await(0,o.waitForRoom)(this.memory,"check of main",u)
54
+ if(p("room"),e)return{steps:[],ok:!1,error:e}}const h=await(0,o.withAdmission)(this.memory,"check",async()=>{const{cpus:n,cpuset:a}=await(0,o.pickCores)(this.resources.cpus,s.DEFAULT_CPUS,this.resources.size)
55
+ let i=await(0,r.docker)(this.createArgs(e,t,!0,a,n),r.DOCKER_OP_TIMEOUT_MS)
56
+ if(0!==i.exit)return{error:i.spawnError??`docker create failed: ${(i.stderr||String(i.exit)).trim()}`}
57
+ let l=i.stdout.trim()
58
+ if(p("create"),await(0,c.claimScratch)(l,t,"1000:1000")){if(await(0,r.docker)(["rm","-f","-v",l],r.DOCKER_OP_TIMEOUT_MS),i=await(0,r.docker)(this.createArgs(e,t,!1,a,n),r.DOCKER_OP_TIMEOUT_MS),0!==i.exit)return{error:i.spawnError??`docker create failed: ${(i.stderr||String(i.exit)).trim()}`}
59
+ l=i.stdout.trim()}return p("scratch"),{id:l}},f)
60
+ if("refused"in h)return{steps:[],ok:!1,error:h.refused}
61
+ if("error"in h.value)return{steps:[],ok:!1,error:h.value.error}
62
+ const w=h.value.id
63
+ try{f("starting its box",2*r.DOCKER_OP_TIMEOUT_MS)
64
+ const t=await(0,r.docker)(["start",w],r.DOCKER_OP_TIMEOUT_MS)
65
+ if(p("start"),0!==t.exit)return{steps:[],ok:!1,error:`docker start failed: ${(t.stderr||String(t.exit)).trim()}`}
56
66
  const n=[]
57
- let o=await(0,c.readOomKills)(f)??0
58
- for(const t of e.steps){const s=Date.now(),i=await(0,r.dockerKeepingEnds)(["exec","-e",`${a.RUN_ENV_VAR}=${(0,a.withShellInit)(e.shellInit,t.run)}`,f,"/bin/sh","-c",a.RUN_FROM_ENV],t.timeoutMs??this.stepTimeoutMs),l=Date.now()-s,u=await(0,c.readOomKills)(f),d=null!=u?Math.max(0,u-o):0
59
- null!=u&&(o=u)
60
- const p=d>0?`${i.stderr}${i.stderr&&!i.stderr.endsWith("\n")?"\n":""}${(0,c.oomNote)(d,this.resources.memory??"1g")}\n`:i.stderr
61
- n.push({run:t.run,exit:i.exit,stdout:i.stdout,stderr:p,ms:l,timedOut:i.timedOut})}return u("commands"),{steps:n,ok:n.every(e=>0===e.exit),phaseMs:s}}finally{const e=Date.now()
62
- await(0,r.docker)(["rm","-f","-v",f],r.DOCKER_OP_TIMEOUT_MS),s.remove=Date.now()-e}}createArgs(e,t,r,n,a){const c=Object.entries(e.env??{}).flatMap(([e,t])=>["-e",`${e}=${t}`]),l=e.depsVolume?["-v",`${e.depsVolume}:/work/node_modules`]:[],u=(e.mounts??[]).flatMap(e=>["-v",`${e.volume}:${e.target}`]),d=(e.readOnlyBinds??[]).flatMap(e=>["-v",`${e.host}:${e.target}:ro`])
63
- return["create","--label","alchemy.sandbox=rung1",...(0,s.hardenedCreateArgs)({network:this.network,user:"1000:1000",...r?{}:{extraTmpfs:[(0,i.scratchTmpfsArg)(512)]},shmSizeMb:this.resources.shmSizeMb,memory:this.resources.memory??"1g",cpus:a??this.resources.cpus??o.DEFAULT_CPUS,cpuset:n,pidsLimit:this.resources.pidsLimit??512}),...r?i.SCRATCH_VOLUME_ARGS:[],...c,"-v",`${e.worktreePath}:/work:rw`,...l,...u,...d,"-w","/work",t,"tail","-f","/dev/null"]}}},81618(e,exports,t){function r(e){if("create"!==e[0]&&"run"!==e[0])return e
67
+ let o=await(0,l.readOomKills)(w)??0
68
+ for(const t of e.steps){const s=Date.now(),a=void 0!==e.deadlineAt?e.deadlineAt-s:1/0
69
+ if(a<=0){n.push({run:t.run,exit:-1,stdout:"",stderr:"",ms:0,timedOut:!0})
70
+ continue}const c=Math.min(t.timeoutMs??this.stepTimeoutMs,a)
71
+ f(`running \`${t.run.replace(/\s+/g," ").slice(0,80)}\``,c+1e4)
72
+ const u=await(0,r.dockerKeepingEnds)(["exec","-e",`${i.RUN_ENV_VAR}=${(0,i.withShellInit)(e.shellInit,t.run)}`,w,"/bin/sh","-c",i.RUN_FROM_ENV],c),d=Date.now()-s,p=await(0,l.readOomKills)(w),m=null!=p?Math.max(0,p-o):0
73
+ null!=p&&(o=p)
74
+ const h=m>0?`${u.stderr}${u.stderr&&!u.stderr.endsWith("\n")?"\n":""}${(0,l.oomNote)(m,this.memory)}\n`:u.stderr
75
+ if(n.push({run:t.run,exit:u.exit,stdout:u.stdout,stderr:h,ms:d,timedOut:u.timedOut,...m>0?{oomKills:m}:{}}),t.stopOnFail&&0!==u.exit)break}return p("commands"),{steps:n,ok:n.every(e=>0===e.exit),phaseMs:a}}finally{const e=Date.now()
76
+ f("removing its box",r.DOCKER_OP_TIMEOUT_MS),await(0,r.docker)(["rm","-f","-v",w],r.DOCKER_OP_TIMEOUT_MS),a.remove=Date.now()-e}}createArgs(e,t,r,n,o){const i=Object.entries(e.env??{}).flatMap(([e,t])=>["-e",`${e}=${t}`]),l=e.depsVolume?["-v",`${e.depsVolume}:/work/node_modules`]:[],u=(e.mounts??[]).flatMap(e=>["-v",`${e.volume}:${e.target}`]),d=(e.readOnlyBinds??[]).flatMap(e=>["-v",`${e.host}:${e.target}:ro`])
77
+ return["create","--label","alchemy.sandbox=rung1",...(0,a.hardenedCreateArgs)({network:this.network,user:"1000:1000",...r?{}:{extraTmpfs:[(0,c.scratchTmpfsArg)(512)]},shmSizeMb:this.resources.shmSizeMb,memory:this.memory,cpus:o??this.resources.cpus??s.DEFAULT_CPUS,cpuset:n,pidsLimit:this.resources.pidsLimit??512}),..."background"===this.resources.priority?["--cpu-shares",String(128)]:[],...r?c.SCRATCH_VOLUME_ARGS:[],...i,"-v",`${e.worktreePath}:/work:rw`,...l,...u,...d,"-w","/work",t,"tail","-f","/dev/null"]}}},81618(e,exports,t){function r(){return{"alchemy.owner":String(process.pid),...u.getStore()??{}}}function n(e){if("create"!==e[0]&&"run"!==e[0])return e
64
78
  const t=new Set
65
79
  e.forEach((r,n)=>{"--label"===e[n-1]&&t.add(r.split("=")[0])})
66
- const r=Object.entries({"alchemy.owner":String(process.pid),...c.getStore()??{}}).filter(([e])=>!t.has(e)).flatMap(([e,t])=>["--label",`${e}=${t.replace(/[\r\n]/g," ").slice(0,200)}`])
67
- return r.length?[e[0],...r,...e.slice(1)]:e}function n(e,t){return new Promise(n=>{(0,o.execFile)("docker",r(e),{timeout:t,killSignal:"SIGKILL",maxBuffer:33554432,windowsHide:!0},(e,t,r)=>{if(!e)return void n({exit:0,stdout:t,stderr:r,timedOut:!1})
80
+ const n=Object.entries(r()).filter(([e])=>!t.has(e)).flatMap(([e,t])=>["--label",`${e}=${t.replace(/[\r\n]/g," ").slice(0,200)}`])
81
+ return n.length?[e[0],...n,...e.slice(1)]:e}function o(e,t){return new Promise(r=>{(0,s.execFile)("docker",n(e),{timeout:t,killSignal:"SIGKILL",maxBuffer:33554432,windowsHide:!0},(e,t,n)=>{if(!e)return void r({exit:0,stdout:t,stderr:n,timedOut:!1})
68
82
  const o=e
69
- if("ENOENT"===o.code)return void n({exit:-1,stdout:t??"",stderr:r??"",timedOut:!1,spawnError:"docker CLI not found on PATH"})
83
+ if("ENOENT"===o.code)return void r({exit:-1,stdout:t??"",stderr:n??"",timedOut:!1,spawnError:"docker CLI not found on PATH"})
70
84
  const s=!0===o.killed||"SIGKILL"===o.signal,a="number"==typeof o.code?o.code:-1
71
- n({exit:a,stdout:t??"",stderr:r??"",timedOut:s})})})}exports.P=exports.DOCKER_OP_TIMEOUT_MS=void 0,exports.dockerKeepingEnds=function(e,t,n=524288){return new Promise(s=>{const a=new i.EndsKeeper(n),c=new i.EndsKeeper(n)
72
- let l=!1,u=!1
73
- const d=(0,o.spawn)("docker",r(e),{windowsHide:!0}),p=setTimeout(()=>{l=!0,d.kill("SIGKILL")},t)
74
- d.stdout.setEncoding("utf8").on("data",e=>a.push(e)),d.stderr.setEncoding("utf8").on("data",e=>c.push(e))
75
- const f=e=>{u||(u=!0,clearTimeout(p),s(e))}
76
- d.on("error",e=>f({exit:-1,stdout:a.text(),stderr:c.text(),timedOut:!1,..."ENOENT"===e.code?{spawnError:"docker CLI not found on PATH"}:{spawnError:e.message}})),d.on("close",e=>f({exit:l?-1:e??-1,stdout:a.text(),stderr:c.text(),timedOut:l}))})},exports.docker=n,exports.ensureImage=async function(e){const t=(0,a.localRecipeFor)(e)
77
- if(t)return(0,a.ensureLocalImage)(t)
78
- const r=await n(["image","inspect",e],exports.DOCKER_OP_TIMEOUT_MS)
85
+ r({exit:a,stdout:t??"",stderr:n??"",timedOut:s})})})}exports.PULL_TIMEOUT_MS=exports.DOCKER_OP_TIMEOUT_MS=void 0,exports.containerLabels=r,exports.dockerKeepingEnds=function(e,t,r=524288){return new Promise(o=>{const a=new c.EndsKeeper(r),i=new c.EndsKeeper(r)
86
+ let u=!1,d=!1
87
+ const p=(0,s.spawn)("docker",n(e),{windowsHide:!0}),f=(0,l.awakeTimeout)(()=>{u=!0,p.kill("SIGKILL")},t)
88
+ p.stdout.setEncoding("utf8").on("data",e=>a.push(e)),p.stderr.setEncoding("utf8").on("data",e=>i.push(e))
89
+ const m=e=>{d||(d=!0,f.clear(),o(e))}
90
+ p.on("error",e=>m({exit:-1,stdout:a.text(),stderr:i.text(),timedOut:!1,..."ENOENT"===e.code?{spawnError:"docker CLI not found on PATH"}:{spawnError:e.message}})),p.on("close",e=>m({exit:u?-1:e??-1,stdout:a.text(),stderr:i.text(),timedOut:u}))})},exports.docker=o,exports.ensureImage=async function(e){const t=(0,i.localRecipeFor)(e)
91
+ if(t)return(0,i.ensureLocalImage)(t)
92
+ const r=await o(["image","inspect",e],exports.DOCKER_OP_TIMEOUT_MS)
79
93
  if(r.spawnError)return r.spawnError
80
94
  if(0===r.exit)return
81
- const o=await n(["pull",e],exports.P)
82
- return 0!==o.exit?`docker pull ${e} failed: ${(o.stderr||String(o.exit)).trim()}`:void 0}
83
- const o=t(31421),s=t(16698),a=t(83129),i=t(88196),c=new s.AsyncLocalStorage
84
- exports.DOCKER_OP_TIMEOUT_MS=6e4,exports.P=3e5},26166(e,exports){exports.hardenedCreateArgs=function(e){return["--network",e.network,"--user",e.user,"--cap-drop","ALL",...(e.capAdds??[]).flatMap(e=>["--cap-add",e]),...Object.entries(e.sysctls??{}).flatMap(([e,t])=>["--sysctl",`${e}=${t}`]),"--security-opt","no-new-privileges","--read-only","--tmpfs","/tmp:rw,nosuid,nodev,exec,size=256m",...(e.extraTmpfs??[]).flatMap(e=>["--tmpfs",e]),"--ipc","none","--tmpfs",`/dev/shm:rw,nosuid,nodev,size=${e.shmSizeMb??64}m`,"--memory",e.memory,"--memory-swap",e.memory,"--cpus",String(e.cpus),...e.cpuset?["--cpuset-cpus",e.cpuset]:[],"--pids-limit",String(e.pidsLimit),"-e","HOME=/tmp","-e","XDG_CACHE_HOME=/tmp/.cache","-e","MYPY_CACHE_DIR=/tmp/.mypy_cache","-e","RUFF_CACHE_DIR=/tmp/.ruff_cache","-e","PYTHONPYCACHEPREFIX=/tmp/.pycache","-e","npm_config_cache=/tmp/.npm",..."none"===e.network?["-e","UV_OFFLINE=1","-e","PIP_NO_INDEX=1","-e","npm_config_offline=true"]:[]]}},83129(e,exports,t){function r(e){const t=m.get(e.image)
95
+ const n=await o(["pull",e],exports.PULL_TIMEOUT_MS)
96
+ return 0!==n.exit?`docker pull ${e} failed: ${(n.stderr||String(n.exit)).trim()}`:void 0}
97
+ const s=t(31421),a=t(16698),i=t(83129),c=t(88196),l=t(4334),u=new a.AsyncLocalStorage
98
+ exports.DOCKER_OP_TIMEOUT_MS=6e4,exports.PULL_TIMEOUT_MS=3e5},26166(e,exports){exports.hardenedCreateArgs=function(e){return["--network",e.network,"--user",e.user,"--cap-drop","ALL",...(e.capAdds??[]).flatMap(e=>["--cap-add",e]),...Object.entries(e.sysctls??{}).flatMap(([e,t])=>["--sysctl",`${e}=${t}`]),"--security-opt","no-new-privileges","--read-only","--tmpfs","/tmp:rw,nosuid,nodev,exec,size=256m",...(e.extraTmpfs??[]).flatMap(e=>["--tmpfs",e]),"--ipc","none","--tmpfs",`/dev/shm:rw,nosuid,nodev,size=${e.shmSizeMb??64}m`,"--memory",e.memory,"--memory-swap",e.memory,"--cpus",String(e.cpus),...e.cpuset?["--cpuset-cpus",e.cpuset]:[],"--pids-limit",String(e.pidsLimit),"-e","HOME=/tmp","-e","XDG_CACHE_HOME=/tmp/.cache","-e","MYPY_CACHE_DIR=/tmp/.mypy_cache","-e","RUFF_CACHE_DIR=/tmp/.ruff_cache","-e","PYTHONPYCACHEPREFIX=/tmp/.pycache","-e","npm_config_cache=/tmp/.npm",..."none"===e.network?["-e","UV_OFFLINE=1","-e","PIP_NO_INDEX=1","-e","npm_config_offline=true"]:[]]}},83129(e,exports,t){function r(e){const t=m.get(e.image)
85
99
  if(t)return t.work
86
100
  const r=(async()=>{const t=await(0,u.docker)(["image","inspect","--format",`{{ index .Config.Labels "${p}" }}`,e.image],u.DOCKER_OP_TIMEOUT_MS)
87
101
  if(t.spawnError)return t.spawnError
@@ -114,9 +128,9 @@ if(0===t.exit){const e=/^oom_kill (\d+)/m.exec(t.stdout)
114
128
  if(e)return Number(e[1])}const o=await(0,r.docker)(["exec",e,"cat","/sys/fs/cgroup/memory/memory.oom_control"],n)
115
129
  if(0===o.exit){const e=/^oom_kill (\d+)/m.exec(o.stdout)
116
130
  if(e)return Number(e[1])}return null},exports.probeBox=async function(e){const t=`cat /sys/fs/cgroup/memory.events 2>/dev/null || cat /sys/fs/cgroup/memory/memory.oom_control 2>/dev/null; if [ -s ${exports.H} ]; then echo __ALCHEMY_LIVE_FRAME__; fi`,o=await(0,r.docker)(["exec",e,"/bin/sh","-c",t],n),s=/^oom_kill (\d+)/m.exec(o.stdout)
117
- return{oomKills:s?Number(s[1]):null,liveFrame:o.stdout.includes("__ALCHEMY_LIVE_FRAME__")}},exports.oomNote=function(e,t){return`[AlchemyLab] Out of memory: the kernel killed ${1===e?"a process":`${e} processes`} in this box during this command (the box's memory cap is ${t}). Exit code 137 means killed. Make the case smaller, or raise the environment's memory (resources.memory).`}
131
+ return{oomKills:s?Number(s[1]):null,liveFrame:o.stdout.includes("__ALCHEMY_LIVE_FRAME__")}},exports.oomNote=function(e,t,r=!1){return`[AlchemyLab] Out of memory: the kernel killed ${1===e?"a process":`${e} processes`} in this box during this command (the box's memory cap is ${t}). Exit code 137 means killed. `+(r?'A heavy box has 6 GB: experiment_start with size "heavy", then run in it. Or make the case smaller.':"Make the case smaller, or raise the environment's memory (resources.memory).")}
118
132
  const r=t(81618),n=5e3
119
- exports.H="/tmp/.alchemy_live.png"},11895(e,exports,t){exports.DEFAULT_CPUS=void 0,t(81618),t(22604),t(26166),t(2566),t(90695),t(61260),exports.DEFAULT_CPUS=4},90695(e,exports,t){exports.SCRATCH_VOLUME_ARGS=void 0,exports.scratchTmpfsArg=function(e){return`/scratch:rw,nosuid,nodev,exec,size=${e}m`},exports.claimScratch=async function(e,t,n){const o=await(0,r.docker)(["run","--rm","--network","none","--user","0:0","--volumes-from",e,"--entrypoint","chown",t,n,"/scratch"],r.DOCKER_OP_TIMEOUT_MS)
133
+ exports.H="/tmp/.alchemy_live.png"},11895(e,exports,t){exports.DEFAULT_CPUS=exports.HEAVY_MEMORY=void 0,exports.memoryForBox=function(e,t){return e??("heavy"===t?exports.HEAVY_MEMORY:"2g")},t(81618),t(22604),t(26166),t(2566),t(90695),t(61260),exports.HEAVY_MEMORY="6g",exports.DEFAULT_CPUS=4},90695(e,exports,t){exports.SCRATCH_VOLUME_ARGS=void 0,exports.scratchTmpfsArg=function(e){return`/scratch:rw,nosuid,nodev,exec,size=${e}m`},exports.claimScratch=async function(e,t,n){const o=await(0,r.docker)(["run","--rm","--network","none","--user","0:0","--volumes-from",e,"--entrypoint","chown",t,n,"/scratch"],r.DOCKER_OP_TIMEOUT_MS)
120
134
  return 0===o.exit?null:o.spawnError??((o.stderr||"").trim()||`chown exited ${o.exit}`)}
121
135
  const r=t(81618)
122
136
  exports.SCRATCH_VOLUME_ARGS=["--mount","type=volume,dst=/scratch"]},2566(e,exports,t){exports.RUN_ENV_VAR=exports.RUN_FROM_ENV=void 0,exports.withShellInit=function(e,t){const r=(e??"").trim()
@@ -129,41 +143,46 @@ const r=t(76982)
129
143
  exports.m4=1,exports.OFFICE_BOX_IMAGE=`alchemylab-local/office-box:v${exports.m4}`,exports.OT="/scratch/render",exports.dw="local NBH = utf8.char(0x2011)\nfunction Str(el)\n local t = el.text\n for _ = 1, 2 do t = t:gsub('(%d)%-(%d)', '%1' .. NBH .. '%2') end\n if t ~= el.text then el.text = t end\n return el\nend\n"
130
144
  const n="/usr/local/share/render-pdf/nobreak.lua",o=`#!/bin/sh\n# render-pdf FILE... : convert Word, Excel, PowerPoint, OpenDocument, Markdown or HTML to PDF.\n# Writes each PDF under \${RENDER_OUT:-${exports.OT}} and prints its path, one per line.\nset -e\nout="\${RENDER_OUT:-${exports.OT}}"\nmkdir -p "$out" /scratch/.render-work\nexport HOME="\${HOME:-/scratch}"\nif [ "$1" = "--self-test" ]; then\n cd /scratch/.render-work\n python3 -c "import docx; d = docx.Document(); d.add_heading('render-pdf self-test', 1); d.add_paragraph('ok'); d.save('self-test.docx')"\n set -- /scratch/.render-work/self-test.docx\nfi\n[ "$#" -gt 0 ] || { echo "usage: render-pdf FILE..." >&2; exit 2; }\nfor f in "$@"; do\n [ -f "$f" ] || { echo "render-pdf: no such file: $f" >&2; exit 1; }\n name=$(basename "$f"); stem="\${name%.*}"\n case "$name" in\n *.md|*.markdown) pandoc --lua-filter ${n} "$f" -o "/scratch/.render-work/$stem.docx"; src="/scratch/.render-work/$stem.docx" ;;\n *) src="$f" ;;\n esac\n soffice --headless --norestore -env:UserInstallation=file:///scratch/.render-profile --convert-to pdf --outdir "$out" "$src" >/scratch/.render-work/soffice.log 2>&1 \\\n || { echo "render-pdf: LibreOffice could not convert $f" >&2; tail -5 /scratch/.render-work/soffice.log >&2; exit 1; }\n [ -f "$out/$stem.pdf" ] || { echo "render-pdf: no PDF produced for $f" >&2; exit 1; }\n echo "$out/$stem.pdf"\ndone\n`
131
145
  exports.OFFICE_BOX_DOCKERFILE=function(){const e=Buffer.from(o).toString("base64"),t=Buffer.from(exports.dw).toString("base64")
132
- return["FROM python:3.12-slim","ENV DEBIAN_FRONTEND=noninteractive PIP_NO_CACHE_DIR=1 PYTHONDONTWRITEBYTECODE=1","RUN apt-get update \\"," && apt-get install -y --no-install-recommends \\"," libreoffice-writer-nogui libreoffice-calc-nogui libreoffice-impress-nogui \\"," pandoc fonts-liberation fonts-dejavu-core fonts-crosextra-carlito fonts-crosextra-caladea \\"," zbar-tools poppler-utils \\"," && rm -rf /var/lib/apt/lists/*","RUN pip install python-docx openpyxl python-pptx pypdf segno",`RUN echo ${e} | base64 -d > /usr/local/bin/render-pdf && chmod 755 /usr/local/bin/render-pdf`,`RUN mkdir -p ${n.replace(/\/[^/]+$/,"")} && echo ${t} | base64 -d > ${n}`,""].join("\n")}(),exports.OFFICE_BOX_RECIPE_HASH=(0,r.createHash)("sha256").update(exports.OFFICE_BOX_DOCKERFILE).digest("hex").slice(0,16),exports.VP={name:"Office",description:'Make and render office files: python-docx, openpyxl, python-pptx, pandoc and LibreOffice in a sealed box. `render-pdf FILE` writes a PDF under /scratch/render. QR codes: `segno "URL" -o qr.png --scale 10`, read back with `zbarimg`; `pdftoppm -png` turns PDF pages into images. Word styling from Markdown: `pandoc --reference-doc`. The worktree is read-only here: make files under /scratch, record them (results record, box), then view_asset({ result }) to look at a PDF and write_file({ path, fromResult }) to put a file in the repository. Scripts you write to make a file stay in /scratch: the repository gets the finished files, and a note in the source saying how it was rendered.',smoke:"render-pdf --self-test",config:{image:exports.OFFICE_BOX_IMAGE,shellInit:"export HOME=/scratch",resources:{memory:"3g",scratchMb:1024,shmMb:256}}},exports.ENVIRONMENT_PRESETS={office:exports.VP}},3517(e,exports,t){function r(e,t){const r=d.extname(e).slice(1).toLowerCase()
133
- return h[t].includes(r)}function n(e,t){const r=e=>`'${e.replace(/'/g,"'\\''")}'`,n=`/work/in/${e}`,o=e.replace(/\.[^.]+$/,"")
134
- return"pdf"===t?`RENDER_OUT=/work/out render-pdf ${r(n)}`:"docx"===t&&/\.(md|markdown|html?)$/i.test(e)?`pandoc ${r(n)} -o ${r(`/work/out/${o}.docx`)}`:`soffice --headless --norestore -env:UserInstallation=file:///scratch/.render-profile --convert-to ${t} --outdir /work/out ${r(n)} >/dev/null`}var o,s=this&&this.__createBinding||(Object.create?function(e,t,r,n){void 0===n&&(n=r)
146
+ return["FROM python:3.12-slim","ENV DEBIAN_FRONTEND=noninteractive PIP_NO_CACHE_DIR=1 PYTHONDONTWRITEBYTECODE=1","RUN apt-get update \\"," && apt-get install -y --no-install-recommends \\"," libreoffice-writer-nogui libreoffice-calc-nogui libreoffice-impress-nogui \\"," pandoc fonts-liberation fonts-dejavu-core fonts-crosextra-carlito fonts-crosextra-caladea \\"," zbar-tools poppler-utils \\"," && rm -rf /var/lib/apt/lists/*","RUN pip install python-docx openpyxl python-pptx pypdf segno",`RUN echo ${e} | base64 -d > /usr/local/bin/render-pdf && chmod 755 /usr/local/bin/render-pdf`,`RUN mkdir -p ${n.replace(/\/[^/]+$/,"")} && echo ${t} | base64 -d > ${n}`,""].join("\n")}(),exports.OFFICE_BOX_RECIPE_HASH=(0,r.createHash)("sha256").update(exports.OFFICE_BOX_DOCKERFILE).digest("hex").slice(0,16),exports.VP={name:"Office",description:'Make and render office files: python-docx, openpyxl, python-pptx, pandoc and LibreOffice in a sealed box. `render-pdf FILE` writes a PDF under /scratch/render. QR codes: `segno "URL" -o qr.png --scale 10`, read back with `zbarimg`; `pdftoppm -png` turns PDF pages into images. Word styling from Markdown: `pandoc --reference-doc`. The worktree is read-only here: make files under /scratch, record them (results record, box), then view_asset({ result }) to look at a PDF and write_file({ path, fromResult }) to put a file in the repository. Scripts you write to make a file stay in /scratch: the repository gets the finished files, and a note in the source saying how it was rendered.',smoke:"render-pdf --self-test",config:{image:exports.OFFICE_BOX_IMAGE,shellInit:"export HOME=/scratch",resources:{memory:"3g",scratchMb:1024,shmMb:256}}},exports.ENVIRONMENT_PRESETS={office:exports.VP}},3517(e,exports,t){function r(e,t){const r=p.extname(e).slice(1).toLowerCase()
147
+ return w[t].includes(r)}function n(e,t){const r=e=>`'${e.replace(/'/g,"'\\''")}'`,n=`/work/in/${e}`,o=e.replace(/\.[^.]+$/,"")
148
+ return"pdf"===t?`RENDER_OUT=/work/out render-pdf ${r(n)}`:"docx"===t&&/\.(md|markdown|html?)$/i.test(e)?`pandoc ${r(n)} -o ${r(`/work/out/${o}.docx`)}`:`soffice --headless --norestore -env:UserInstallation=file:///scratch/.render-profile --convert-to ${t} --outdir /work/out ${r(n)} >/dev/null`}async function o(e,t,r,o){const s=await u.promises.mkdtemp(p.join(d.tmpdir(),"alchemylab-render-"))
149
+ try{await u.promises.mkdir(p.join(s,"in")),await u.promises.mkdir(p.join(s,"out")),await u.promises.chmod(s,493),await u.promises.chmod(p.join(s,"in"),493),await u.promises.chmod(p.join(s,"out"),511),await u.promises.writeFile(p.join(s,"in",e),t.bytes,{mode:420})
150
+ const a=new f.ContainerRunner({image:h.OFFICE_BOX_IMAGE,stepTimeoutMs:18e4,resources:{memory:"3g",shmSizeMb:256}}),i=await a.run({worktreePath:s,image:h.OFFICE_BOX_IMAGE,env:{HOME:"/scratch"},steps:[{run:n(e,t.to)}]})
151
+ if(!i.ok){const e=i.steps[0]
152
+ return{ok:!1,error:(i.error??`${(e?.stderr||e?.stdout||"").trim().split("\n").slice(-4).join(" ")}`)||"rendering failed",unavailable:!!i.error&&/docker|daemon|not found on PATH|Cannot connect/i.test(i.error)}}const c=(await u.promises.readdir(p.join(s,"out"))).find(e=>e.toLowerCase().endsWith(`.${t.to}`))
153
+ if(!c)return{ok:!1,error:`no ${t.to.toUpperCase()} was produced`}
154
+ const l=await u.promises.readFile(p.join(s,"out",c))
155
+ return await u.promises.mkdir(o,{recursive:!0}),await u.promises.writeFile(r,l),{ok:!0,bytes:l,cached:!1}}finally{await u.promises.rm(s,{recursive:!0,force:!0})}}var s,a=this&&this.__createBinding||(Object.create?function(e,t,r,n){void 0===n&&(n=r)
135
156
  var o=Object.getOwnPropertyDescriptor(t,r)
136
- o&&!("get"in o?!t.__esModule:o.writable||o.configurable)||(o={enumerable:!0,get:function(){return t[r]}}),Object.defineProperty(e,n,o)}:function(e,t,r,n){void 0===n&&(n=r),e[n]=t[r]}),a=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),i=this&&this.__importStar||(o=function(e){return o=Object.getOwnPropertyNames||function(e){var t=[]
157
+ o&&!("get"in o?!t.__esModule:o.writable||o.configurable)||(o={enumerable:!0,get:function(){return t[r]}}),Object.defineProperty(e,n,o)}:function(e,t,r,n){void 0===n&&(n=r),e[n]=t[r]}),i=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),c=this&&this.__importStar||(s=function(e){return s=Object.getOwnPropertyNames||function(e){var t=[]
137
158
  for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[t.length]=r)
138
- return t},o(e)},function(e){if(e&&e.__esModule)return e
159
+ return t},s(e)},function(e){if(e&&e.__esModule)return e
139
160
  var t={}
140
- if(null!=e)for(var r=o(e),n=0;n<r.length;n++)"default"!==r[n]&&s(t,e,r[n])
141
- return a(t,e),t})
142
- Object.defineProperty(exports,"__esModule",{value:!0}),exports.RENDER_MIME=exports.MAX_RENDER_INPUT_BYTES=void 0,exports.canRender=r,exports.renderDocument=async function(e,t){const o=(s=e.filename,d.basename(s).replace(/[^A-Za-z0-9._-]+/g,"_").replace(/^\.+/,"")||"document")
161
+ if(null!=e)for(var r=s(e),n=0;n<r.length;n++)"default"!==r[n]&&a(t,e,r[n])
162
+ return i(t,e),t})
163
+ Object.defineProperty(exports,"__esModule",{value:!0}),exports.RENDER_MIME=exports.MAX_RENDER_INPUT_BYTES=void 0,exports.canRender=r,exports.rendersInFlight=function(){return g.size},exports.renderDocument=async function(e,t){const n=(s=e.filename,p.basename(s).replace(/[^A-Za-z0-9._-]+/g,"_").replace(/^\.+/,"")||"document")
143
164
  var s
144
- if(!r(o,e.to))return{ok:!1,error:`${d.extname(o)||"this file"} cannot be turned into ${e.to.toUpperCase()}`}
165
+ if(!r(n,e.to))return{ok:!1,error:`${p.extname(n)||"this file"} cannot be turned into ${e.to.toUpperCase()}`}
145
166
  if(e.bytes.length>exports.MAX_RENDER_INPUT_BYTES)return{ok:!1,error:`file is over ${exports.MAX_RENDER_INPUT_BYTES/1048576} MB`}
146
- const a=(0,c.createHash)("sha256").update(m.OFFICE_BOX_RECIPE_HASH).update("\0").update(e.to).update("\0").update(d.extname(o).toLowerCase()).update("\0").update(e.bytes).digest("hex"),i=d.join(t.cacheDir,`${a}.${e.to}`)
147
- try{return{ok:!0,bytes:await l.promises.readFile(i),cached:!0}}catch{}const h=t.image??"wait"
148
- if("wait"!==h){const e=(0,f.localRecipeFor)(m.OFFICE_BOX_IMAGE),t=await(0,f.localImageState)(e)
167
+ const a=(0,l.createHash)("sha256").update(h.OFFICE_BOX_RECIPE_HASH).update("\0").update(e.to).update("\0").update(p.extname(n).toLowerCase()).update("\0").update(e.bytes).digest("hex"),i=p.join(t.cacheDir,`${a}.${e.to}`)
168
+ try{return{ok:!0,bytes:await u.promises.readFile(i),cached:!0}}catch{}const c=t.image??"wait"
169
+ if("wait"!==c){const e=(0,m.localRecipeFor)(h.OFFICE_BOX_IMAGE),t=await(0,m.localImageState)(e)
149
170
  if("no-docker"===t.state)return{ok:!1,error:t.error,unavailable:!0}
150
- if("building"===t.state)return{ok:!1,error:w,preparing:!0,since:t.since}
171
+ if("building"===t.state)return{ok:!1,error:b,preparing:!0,since:t.since}
151
172
  if("failed"===t.state&&Date.now()-t.at<12e4)return{ok:!1,error:`building the office renderer failed: ${t.error.split("\n").slice(-3).join(" ")}`}
152
- if("ready"!==t.state){if("present-only"===h)return{ok:!1,error:"the office renderer is not built on this machine yet",unavailable:!0}
153
- const{since:t}=(0,f.startLocalImageBuild)(e)
154
- return{ok:!1,error:w,preparing:!0,since:t}}}const b=await l.promises.mkdtemp(d.join(u.tmpdir(),"alchemylab-render-"))
155
- try{await l.promises.mkdir(d.join(b,"in")),await l.promises.mkdir(d.join(b,"out")),await l.promises.chmod(b,493),await l.promises.chmod(d.join(b,"in"),493),await l.promises.chmod(d.join(b,"out"),511),await l.promises.writeFile(d.join(b,"in",o),e.bytes,{mode:420})
156
- const r=new p.ContainerRunner({image:m.OFFICE_BOX_IMAGE,stepTimeoutMs:18e4,resources:{memory:"3g",shmSizeMb:256}}),s=await r.run({worktreePath:b,image:m.OFFICE_BOX_IMAGE,env:{HOME:"/scratch"},steps:[{run:n(o,e.to)}]})
157
- if(!s.ok){const e=s.steps[0]
158
- return{ok:!1,error:(s.error??`${(e?.stderr||e?.stdout||"").trim().split("\n").slice(-4).join(" ")}`)||"rendering failed",unavailable:!!s.error&&/docker|daemon|not found on PATH|Cannot connect/i.test(s.error)}}const a=(await l.promises.readdir(d.join(b,"out"))).find(t=>t.toLowerCase().endsWith(`.${e.to}`))
159
- if(!a)return{ok:!1,error:`no ${e.to.toUpperCase()} was produced`}
160
- const c=await l.promises.readFile(d.join(b,"out",a))
161
- return await l.promises.mkdir(t.cacheDir,{recursive:!0}),await l.promises.writeFile(i,c),{ok:!0,bytes:c,cached:!1}}finally{await l.promises.rm(b,{recursive:!0,force:!0})}}
162
- const c=t(76982),l=t(79896),u=i(t(70857)),d=i(t(16928)),p=t(52429),f=t(83129),m=t(44853)
173
+ if("ready"!==t.state){if("present-only"===c)return{ok:!1,error:"the office renderer is not built on this machine yet",unavailable:!0}
174
+ const{since:t}=(0,m.startLocalImageBuild)(e)
175
+ return{ok:!1,error:b,preparing:!0,since:t}}}let d=g.get(a)
176
+ if(d||(d={since:Date.now(),done:(t.run??o)(n,e,i,t.cacheDir).catch(e=>({ok:!1,error:e instanceof Error?e.message:String(e)})).finally(()=>{g.delete(a)})},g.set(a,d)),!t.answerWithin||t.answerWithin<=0)return d.done
177
+ const{since:f,done:w}=d
178
+ let x
179
+ const _=new Promise(e=>{x=setTimeout(()=>e({ok:!1,rendering:!0,since:f,error:"the exact copy is still rendering"}),t.answerWithin)})
180
+ try{return await Promise.race([w,_])}finally{x&&clearTimeout(x)}}
181
+ const l=t(76982),u=t(79896),d=c(t(70857)),p=c(t(16928)),f=t(52429),m=t(83129),h=t(44853)
163
182
  exports.MAX_RENDER_INPUT_BYTES=52428800
164
- const h={pdf:["docx","doc","odt","rtf","xlsx","xlsm","xls","ods","csv","pptx","ppt","odp","md","markdown","html","htm"],docx:["md","markdown","html","htm","odt","rtf","doc"],xlsx:["xls","ods"],pptx:["ppt","odp"]}
183
+ const w={pdf:["docx","doc","odt","rtf","xlsx","xlsm","xls","ods","csv","pptx","ppt","odp","md","markdown","html","htm"],docx:["md","markdown","html","htm","odt","rtf","doc"],xlsx:["xls","ods"],pptx:["ppt","odp"]}
165
184
  exports.RENDER_MIME={pdf:"application/pdf",docx:"application/vnd.openxmlformats-officedocument.wordprocessingml.document",xlsx:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",pptx:"application/vnd.openxmlformats-officedocument.presentationml.presentation"}
166
- const w="the office renderer is being built on this machine (first use only, usually a few minutes)"},43701(e,exports){function t(e){return e<128?String.fromCharCode(e):"\u20ac\x81\u201a\u0192\u201e\u2026\u2020\u2021\u02c6\u2030\u0160\u2039\u0152\x8d\u017d\x8f\x90\u2018\u2019\u201c\u201d\u2022\u2013\u2014\u02dc\u2122\u0161\u203a\u0153\x9d\u017e\u0178\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"[e-128]??""}exports.rtfToText=function(e){const o="string"==typeof e?e:Buffer.from(e).toString("latin1")
185
+ const b="the office renderer is being built on this machine (first use only, usually a few minutes)",g=new Map},43701(e,exports){function t(e){return e<128?String.fromCharCode(e):"\u20ac\x81\u201a\u0192\u201e\u2026\u2020\u2021\u02c6\u2030\u0160\u2039\u0152\x8d\u017d\x8f\x90\u2018\u2019\u201c\u201d\u2022\u2013\u2014\u02dc\u2122\u0161\u203a\u0153\x9d\u017e\u0178\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"[e-128]??""}exports.rtfToText=function(e){const o="string"==typeof e?e:Buffer.from(e).toString("latin1")
167
186
  if(!/^\s*\{\s*\\rtf/i.test(o))throw new Error("not an RTF file (it does not start with {\\rtf)")
168
187
  const s=[],a=[{skip:!1,skipChars:0}],i=()=>a[a.length-1],c=e=>{i().skip||s.push(e)}
169
188
  for(let e=0;e<o.length;e++){const s=o[e]
@@ -303,7 +322,7 @@ const c=new Map
303
322
  for(const e of Object.keys(s.files)){const t=/^(.+)\/content\.xml$/.exec(e)?.[1]
304
323
  if(!t)continue
305
324
  const r=await n(s,e)
306
- r&&/<chart:chart\b/.test(r)&&c.set(t,$(r))}return{xml:i.split(/<office:body\b/)[1]??i,objects:c}}function v(e,t){return e.object?t.get((e.href??"").replace(/^\.\//,""))??`[embedded object: ${(e.desc||e.title||e.name||"unnamed").trim()}]`:e.image?l(e.desc||e.title,e.name):null}function $(e){const t=/chart:class="chart:(\w+)"/.exec(e)?.[1]??"chart",r=[...(/<chart:title\b[^>]*>([\s\S]*?)<\/chart:title>/.exec(e)?.[1]??"").matchAll(/<text:p\b[^>]*>([\s\S]*?)<\/text:p>/g)].map(e=>o(e[1].replace(/<[^>]+>/g,""))).join(" ").trim(),n=[],a=/<table:table\b[^>]*table:name="local-table"[^>]*>([\s\S]*?)<\/table:table>/.exec(e)?.[1]
325
+ r&&/<chart:chart\b/.test(r)&&c.set(t,O(r))}return{xml:i.split(/<office:body\b/)[1]??i,objects:c}}function y(e,t){return e.object?t.get((e.href??"").replace(/^\.\//,""))??`[embedded object: ${(e.desc||e.title||e.name||"unnamed").trim()}]`:e.image?l(e.desc||e.title,e.name):null}function O(e){const t=/chart:class="chart:(\w+)"/.exec(e)?.[1]??"chart",r=[...(/<chart:title\b[^>]*>([\s\S]*?)<\/chart:title>/.exec(e)?.[1]??"").matchAll(/<text:p\b[^>]*>([\s\S]*?)<\/text:p>/g)].map(e=>o(e[1].replace(/<[^>]+>/g,""))).join(" ").trim(),n=[],a=/<table:table\b[^>]*table:name="local-table"[^>]*>([\s\S]*?)<\/table:table>/.exec(e)?.[1]
307
326
  if(a)for(const e of a.matchAll(/<table:table-row\b[^>]*>([\s\S]*?)<\/table:table-row>/g)){const t=[]
308
327
  for(const r of e[1].matchAll(/<table:(?:table-cell|covered-table-cell)\b([^>]*?)(?:\/>|>([\s\S]*?)<\/table:(?:table-cell|covered-table-cell)>)/g)){const e=o([...(r[2]??"").matchAll(/<text:p\b[^>]*>([\s\S]*?)<\/text:p>/g)].map(e=>e[1].replace(/<[^>]+>/g,"")).join(" ")).trim()||s(r[1],"office:value")||"",n=Math.min(Math.max(1,Number(s(r[1],"table:number-columns-repeated")??1)||1),256)
309
328
  for(let r=0;r<n;r++)t.push(e)}n.push(t)}const i=e=>{const t=/^\$?([A-Z]+)\$?(\d+)$/.exec(e)
@@ -316,10 +335,10 @@ for(let t=e.row;t<=r.row;t++)for(let s=e.col;s<=r.col;s++)o.push(n[t]?.[s]??"")
316
335
  return`${o.slice(0,8).join(", ")}${o.length>8?`, ... (${o.length})`:""}`}const r=t.map(e=>e.ref.replace(/\$/g,""))
317
336
  return`${t[0].table?`${t[0].table}!`:""}${2===r.length&&r[0]===r[1]?r[0]:r.join(":")}`},l=c(/<chart:categories\b[^>]*table:cell-range-address="([^"]+)"/.exec(e)?.[1]),u=[...e.matchAll(/<chart:series\b([^>]*)>/g)].map(e=>{const t=c(s(e[1],"chart:values-cell-range-address"))
318
337
  return`${c(s(e[1],"chart:label-cell-address"))||"series"}${t?`: ${t}`:""}${l?` by ${l}`:""}`})
319
- return`[chart: ${I[t]??t}${r?` "${r}"`:""}${u.length?`; ${u.join("; ")}`:""}]`}function y(e,t,r){switch(e){case"text:tab":return r.push("\t"),!0
338
+ return`[chart: ${R[t]??t}${r?` "${r}"`:""}${u.length?`; ${u.join("; ")}`:""}]`}function E(e,t,r){switch(e){case"text:tab":return r.push("\t"),!0
320
339
  case"text:line-break":return r.push("\n"),!0
321
340
  case"text:s":return r.push(" ".repeat(Math.min(100,Number(s(t,"text:c")??1)||1))),!0
322
- default:return!1}}function E(e,t=new Map){const r=[],n=[],a=new R
341
+ default:return!1}}function v(e,t=new Map){const r=[],n=[],a=new I
323
342
  let i=0,c=0,l=null,u=null
324
343
  for(const d of e.matchAll(T)){const[,e,p,f,m,h]=d
325
344
  if(void 0!==h){if(c)continue
@@ -329,7 +348,7 @@ continue}if(c)continue
329
348
  const w=n[n.length-1]
330
349
  if(e)switch(p){case"svg:title":case"svg:desc":u=null
331
350
  break
332
- case"draw:frame":{const e=l?v(l,t):null
351
+ case"draw:frame":{const e=l?y(l,t):null
333
352
  if(l=null,!e)break
334
353
  a.current?a.pushSpaced(e):w?.cell?w.cell.push(e):r.push(e)
335
354
  break}case"text:p":case"text:h":{const e=a.close()
@@ -347,7 +366,7 @@ case"table:table":{const e=n.pop()
347
366
  if(!e)break
348
367
  const t=e.rows.map(e=>`| ${e.map(e=>e.replace(/\|/g,"\\|")).join(" | ")} |`),o=n[n.length-1]
349
368
  o?.cell?o.cell.push(t.join(" ")):r.push(...t,"")
350
- break}}else{if(y(p,f,a))continue
369
+ break}}else{if(E(p,f,a))continue
351
370
  switch(p){case"text:p":case"text:h":m?!w?.cell&&r.length&&""!==r[r.length-1]&&r.push(""):a.open("text:h"===p?Number(s(f,"text:outline-level")??1)||1:0,i>0)
352
371
  break
353
372
  case"text:list-item":m||i++
@@ -364,9 +383,9 @@ case"draw:image":l&&(l.image=!0)
364
383
  break
365
384
  case"draw:object":case"draw:object-ole":l&&(l.object=!0,l.href=s(f,"xlink:href"))
366
385
  break
367
- case"svg:title":case"svg:desc":!m&&l&&(u="svg:title"===p?"title":"desc")}}}return r.join("\n").replace(/\n{3,}/g,"\n\n").trim()}exports.bi=void 0,exports.documentKindFor=function(e){const t=(0,O.formatFor)(e)
386
+ case"svg:title":case"svg:desc":!m&&l&&(u="svg:title"===p?"title":"desc")}}}return r.join("\n").replace(/\n{3,}/g,"\n\n").trim()}exports.bi=void 0,exports.documentKindFor=function(e){const t=(0,$.formatFor)(e)
368
387
  return t?.text?t.kind:void 0},exports.extractDocumentText=async function e(i,c,l={}){if(i.byteLength>exports.bi)throw new Error(`file is ${(i.byteLength/1048576).toFixed(1)} MB; text extraction stops at ${exports.bi/1048576} MB`)
369
- const d=(0,O.formatOfKind)(c).textVia
388
+ const d=(0,$.formatOfKind)(c).textVia
370
389
  if(d){if(!l.convert)throw new Error(`.${c} files are read by converting them in the office box, which is not reachable from here`)
371
390
  const t=await e(await l.convert(i,c,d),d)
372
391
  return{...t,kind:c,note:`Converted from .${c} to .${d} in the office box first. ${t.note??""}`.trim()}}switch(c){case"pdf":return async function(e){const r=await Promise.resolve().then(()=>t.t(88891,23)),{getDocumentProxy:n,extractText:o}=r?.default??r,s=await n(new Uint8Array(e),{isEvalSupported:!1})
@@ -402,7 +421,7 @@ const f=[...p.values()].find(e=>/notesSlide\d*\.xml$/.test(e)),m=f?await n(t,f):
402
421
  let w=`## Slide ${e+1}\n${s.join("\n")||"(no text)"}`
403
422
  h.length&&(w+=`\n\nNotes:\n${h.join("\n")}`),l.push(w)}return{kind:"pptx",text:l.join("\n\n"),units:c.length,note:"Slide text and speaker notes; pictures show as [image: alt text] and charts as a one-line summary; layout is dropped. To see a slide, view_asset this path."}}(i)
404
423
  case"odt":return async function(e){const{xml:t,objects:r}=await k(e,"application/vnd.oasis.opendocument.text","text document")
405
- return{kind:"odt",text:E(t,r),note:"Text, headings, lists and tables; pictures show as [image: alt text] and charts as a one-line summary; notes, comments and formatting are dropped. To see the pages, view_asset this path."}}(i)
424
+ return{kind:"odt",text:v(t,r),note:"Text, headings, lists and tables; pictures show as [image: alt text] and charts as a one-line summary; notes, comments and formatting are dropped. To see the pages, view_asset this path."}}(i)
406
425
  case"ods":return async function(e){const{xml:t,objects:r}=await k(e,"application/vnd.oasis.opendocument.spreadsheet","spreadsheet"),{sheets:n,truncated:a}=function(e,t=new Map){const r=[]
407
426
  let n=!1,a=null,i=null,c=null,l=null,u=null,d=0,p=!1
408
427
  for(const f of e.matchAll(T)){const[,e,m,h,w,b]=f
@@ -418,7 +437,7 @@ var t
418
437
  i.col+=c.repeat,c=null}
419
438
  if(e)switch(m){case"svg:title":case"svg:desc":u=null
420
439
  break
421
- case"draw:frame":{const e=l?v(l,t):null
440
+ case"draw:frame":{const e=l?y(l,t):null
422
441
  l=null,e&&a&&a.figures.push(e)
423
442
  break}case"text:p":p=!1
424
443
  break
@@ -450,7 +469,7 @@ case"svg:title":case"svg:desc":!w&&l&&(u="svg:title"===m?"title":"desc")}}return
450
469
  return{kind:"ods",text:n.map(e=>`## Sheet: ${e.name}\n${e.text||"(empty)"}${e.figures.length?`\n\n${e.figures.join("\n")}`:""}`).join("\n\n"),units:n.length,note:"Cell values as tab-separated rows (column letters in the header); a formula shows as its value followed by (=formula). Charts and pictures are listed under their sheet."+(a?" Sheets over 5000 rows are cut off.":"")}}(i)
451
470
  case"odp":return async function(e){const{xml:t,objects:r}=await k(e,"application/vnd.oasis.opendocument.presentation","presentation"),n=function(e,t=new Map){const r=[]
452
471
  let n=null
453
- const a=new R
472
+ const a=new I
454
473
  let i=0,c=0,l=null,u=null
455
474
  for(const d of e.matchAll(T)){const[,e,p,f,m,h]=d
456
475
  if(void 0===h){if(A.has(p))m||(c+=e?-1:1)
@@ -458,14 +477,14 @@ else if(!c)if(e)switch(p){case"svg:title":case"svg:desc":u=null
458
477
  break
459
478
  case"text:p":case"text:h":{const e=a.close()
460
479
  !e?.plain||!n||i&&/^<number>$/.test(e.plain)||(i?n.notes:n.lines).push(e.plain)
461
- break}case"draw:frame":{const e=l?v(l,t):null
480
+ break}case"draw:frame":{const e=l?y(l,t):null
462
481
  l=null,e&&n&&n.lines.push(e)
463
482
  break}case"presentation:notes":i=Math.max(0,i-1)
464
483
  break
465
484
  case"draw:page":{if(!n)break
466
485
  let e=`## Slide ${r.length+1}\n${n.lines.join("\n")||"(no text)"}`
467
486
  n.notes.length&&(e+=`\n\nNotes:\n${n.notes.join("\n")}`),r.push(e),n=null
468
- break}}else{if(y(p,f,a))continue
487
+ break}}else{if(E(p,f,a))continue
469
488
  switch(p){case"draw:page":m||(n={lines:[],notes:[]})
470
489
  break
471
490
  case"presentation:notes":m||i++
@@ -483,10 +502,10 @@ u&&l?l[u]=(l[u]??"")+o(h):a.push(o(h))}}return r}(t,r)
483
502
  return{kind:"odp",text:n.join("\n\n"),units:n.length,note:"Slide text and speaker notes; pictures show as [image: alt text] and charts as a one-line summary; layout is dropped. To see a slide, view_asset this path."}}(i)
484
503
  case"rtf":return{kind:"rtf",text:(0,M.rtfToText)(i),note:"Text, paragraphs and table rows; styling, pictures and layout are dropped. To see the pages, view_asset this path."}
485
504
  default:throw new Error(`no text form for .${c}`)}}
486
- const O=t(12661),M=t(43701)
505
+ const $=t(12661),M=t(43701)
487
506
  exports.bi=52428800
488
- const S=5e3,C={barChart:"bar",bar3DChart:"bar",lineChart:"line",line3DChart:"line",pieChart:"pie",pie3DChart:"pie",ofPieChart:"pie",doughnutChart:"doughnut",areaChart:"area",area3DChart:"area",scatterChart:"scatter",radarChart:"radar",bubbleChart:"bubble",stockChart:"stock",surfaceChart:"surface",surface3DChart:"surface"},T=/<(\/?)([A-Za-z][\w.-]*:[\w.-]+)\b([^>]*?)(\/?)>|([^<]+)/g,A=new Set(["text:note","office:annotation","text:tracked-changes","office:forms","text:sequence-decls"]),I={circle:"pie",ring:"doughnut"}
489
- class R{constructor(){this.stack=[]}open(e,t){this.stack.push({parts:[],heading:e,listed:t})}get current(){return this.stack[this.stack.length-1]}push(e){this.current?.parts.push(e)}pushSpaced(e){const t=this.current?.parts
507
+ const S=5e3,C={barChart:"bar",bar3DChart:"bar",lineChart:"line",line3DChart:"line",pieChart:"pie",pie3DChart:"pie",ofPieChart:"pie",doughnutChart:"doughnut",areaChart:"area",area3DChart:"area",scatterChart:"scatter",radarChart:"radar",bubbleChart:"bubble",stockChart:"stock",surfaceChart:"surface",surface3DChart:"surface"},T=/<(\/?)([A-Za-z][\w.-]*:[\w.-]+)\b([^>]*?)(\/?)>|([^<]+)/g,A=new Set(["text:note","office:annotation","text:tracked-changes","office:forms","text:sequence-decls"]),R={circle:"pie",ring:"doughnut"}
508
+ class I{constructor(){this.stack=[]}open(e,t){this.stack.push({parts:[],heading:e,listed:t})}get current(){return this.stack[this.stack.length-1]}push(e){this.current?.parts.push(e)}pushSpaced(e){const t=this.current?.parts
490
509
  if(!t)return
491
510
  const r=t[t.length-1]??""
492
511
  t.push(`${!r||/\s$/.test(r)?"":" "}${e} `)}close(){const e=this.stack.pop()
@@ -509,22 +528,62 @@ return s(t,e),t})
509
528
  Object.defineProperty(exports,"__esModule",{value:!0}),exports.textconv=r
510
529
  const i=e(91943),c=a(e(70857)),l=a(e(16928)),u=e(36018),d=e(3517)
511
530
  if(e.c[e.s]===module){const e=process.argv[2]
512
- e||(process.stderr.write("usage: textconv <file>\n"),process.exit(2)),r(e).then(e=>process.stdout.write(e),()=>process.stdout.write("(AlchemyLab: text conversion failed)\n"))}},88196(e,exports){exports.EndsKeeper=void 0,exports.EndsKeeper=class{constructor(e){this.half=e,this.head="",this.tail="",this.cut=0}push(e){if(this.head.length<this.half){const t=this.half-this.head.length
531
+ e||(process.stderr.write("usage: textconv <file>\n"),process.exit(2)),r(e).then(e=>process.stdout.write(e),()=>process.stdout.write("(AlchemyLab: text conversion failed)\n"))}},4334(e,exports,t){function r(e=Date.now()){const t=Number(process.hrtime.bigint()/1000000n)
532
+ if(!w)return m=e,h=t,function(e){if(x)try{const t=JSON.parse(d.readFileSync(x,"utf8"))
533
+ if(!Array.isArray(t))return
534
+ for(const r of t)r&&"number"==typeof r.from&&"number"==typeof r.to&&r.to>r.from&&(r.to<e-6048e5||b.some(e=>e.from===r.from&&e.to===r.to)||b.push({from:r.from,to:r.to}))
535
+ b.sort((e,t)=>e.from-t.from)}catch{}}(e),w=setInterval(()=>r(),5e3),void w.unref?.()
536
+ if(e-m>2e4){const r={from:m,to:e}
537
+ if(!1!==g(r,t-h)){for(b.push(r);b.length&&b[0].to<e-6048e5;)b.shift()
538
+ !function(){if(x)try{d.mkdirSync(f.dirname(x),{recursive:!0})
539
+ const e=`${x}.${process.pid}.tmp`
540
+ d.writeFileSync(e,JSON.stringify(b)),d.renameSync(e,x)}catch{}}()}}e>m&&(m=e),h=t}function n(e,t=Date.now()){r()
541
+ let n=0
542
+ for(const r of b){const o=Math.max(r.from,e),s=Math.min(r.to,t)
543
+ s>o&&(n+=s-o)}return n}function o(e,t=Date.now()){return Math.max(0,t-e-n(e,t))}function s(e){const t=Math.max(1,Math.round(e/6e4))
544
+ if(t<60)return`${t} min`
545
+ const r=Math.floor(t/60),n=t%60
546
+ return n?`${r} h ${n} min`:`${r} h`}var a,i=this&&this.__createBinding||(Object.create?function(e,t,r,n){void 0===n&&(n=r)
547
+ var o=Object.getOwnPropertyDescriptor(t,r)
548
+ o&&!("get"in o?!t.__esModule:o.writable||o.configurable)||(o={enumerable:!0,get:function(){return t[r]}}),Object.defineProperty(e,n,o)}:function(e,t,r,n){void 0===n&&(n=r),e[n]=t[r]}),c=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),l=this&&this.__importStar||(a=function(e){return a=Object.getOwnPropertyNames||function(e){var t=[]
549
+ for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[t.length]=r)
550
+ return t},a(e)},function(e){if(e&&e.__esModule)return e
551
+ var t={}
552
+ if(null!=e)for(var r=a(e),n=0;n<r.length;n++)"default"!==r[n]&&i(t,e,r[n])
553
+ return c(t,e),t})
554
+ Object.defineProperty(exports,"__esModule",{value:!0}),exports.systemSleepCheck=void 0,exports.sampleAwakeClock=r,exports.sleptBetween=n,exports.awakeSince=o,exports.sleepWords=s,exports.awakeTimeout=function(e,t){const s=Date.now()
555
+ r(s)
556
+ let a=null
557
+ const i=e=>{a=setTimeout(c,Math.max(0,e))},c=()=>{a=null
558
+ const r=t-o(s)
559
+ r>0?i(r):e()}
560
+ return i(t),{clear:()=>{a&&clearTimeout(a),a=null},slept:()=>n(s)}},exports.sleptDuringRunNote=function(e){return`[AlchemyLab] The computer slept for ${s(e)} while this command ran. Nothing ran during that time (the box sleeps with the computer), and that time did not count toward the command's time limit.`},exports.sleptBetweenRunsNote=function(e){return`[AlchemyLab] The computer slept for ${s(e)} since the last command in this box ended. Nothing in the box ran during that time, background processes included; they went on when it woke.`},exports.resetAwakeClockForTests=function(e={}){w&&clearInterval(w),w=null,m=0,h=0,b.length=0,g=e.check??(()=>!0),x=e.store??null}
561
+ const u=t(35317),d=l(t(79896)),p=l(t(70857)),f=l(t(16928))
562
+ exports.systemSleepCheck=(e,t)=>{if("linux"===process.platform)return e.to-e.from-t>1e4
563
+ if("darwin"!==process.platform)return null
564
+ try{const t=(0,u.execFileSync)("sysctl",["-n","kern.waketime"],{encoding:"utf8",timeout:2e3}).match(/sec\s*=\s*(\d+)\s*,\s*usec\s*=\s*(\d+)/)
565
+ if(!t)return null
566
+ const r=1e3*Number(t[1])+Math.floor(Number(t[2])/1e3)
567
+ return r>e.from-1e3&&r<=e.to+1e3}catch{return null}}
568
+ let m=0,h=0,w=null
569
+ const b=[]
570
+ let g=exports.systemSleepCheck,x=f.join(p.homedir(),".alchemy_lab","sleep-gaps.json")
571
+ r()},88196(e,exports){exports.EndsKeeper=void 0,exports.EndsKeeper=class{constructor(e){this.half=e,this.head="",this.tail="",this.cut=0}push(e){if(this.head.length<this.half){const t=this.half-this.head.length
513
572
  if(this.head+=e.slice(0,t),!(e=e.slice(t)))return}this.tail+=e,this.tail.length>this.half&&(this.cut+=this.tail.length-this.half,this.tail=this.tail.slice(-this.half))}text(){return this.cut>0?`${this.head}\n[AlchemyLab] ${this.cut} characters of output cut here; the start and the end are kept.\n${this.tail}`:this.head+this.tail}}},44600(e,exports,t){async function r(e,r={}){const{spawn:n}=await Promise.resolve().then(()=>t.t(35317,23))
514
- return new Promise(t=>{const o="win32"===process.platform,s=o?n(e,{cwd:r.cwd??process.cwd(),env:r.env,shell:"cmd.exe",stdio:["pipe","pipe","pipe"],detached:!1}):n("/bin/sh",["-c",exports.RUN_FROM_ENV],{cwd:r.cwd??process.cwd(),env:{...r.env??process.env,[exports.RUN_ENV_VAR]:e},stdio:["pipe","pipe","pipe"],detached:!0}),a=[],i=[]
515
- let c=!1,l=!1
516
- const u=e=>{if(s.pid)try{o?s.kill(e):process.kill(-s.pid,e)}catch{}}
517
- let d,p
518
- r.onKillReady?.((e="SIGTERM")=>{u(e),"SIGKILL"!==e&&setTimeout(()=>{l||u("SIGKILL")},2e3)}),r.timeoutMs&&r.timeoutMs>0&&(p=setTimeout(()=>{c=!0,u("SIGTERM"),d=setTimeout(()=>{l||u("SIGKILL")},2e3)},r.timeoutMs)),s.stdout?.on("data",e=>{a.push(e),r.onChunk?.("stdout",e)}),s.stderr?.on("data",e=>{i.push(e),r.onChunk?.("stderr",e)})
519
- const f=e=>{l||(l=!0,p&&clearTimeout(p),d&&clearTimeout(d),t({stdout:Buffer.concat(a).toString("utf-8"),stderr:Buffer.concat(i).toString("utf-8"),exitCode:e,timedOut:c}))}
520
- s.on("close",e=>f(e??(c?124:1))),s.on("error",()=>f(1))})}Object.defineProperty(exports,"__esModule",{value:!0}),exports.RUN_ENV_VAR=exports.RUN_FROM_ENV=exports.RUN_PARSE_FAILED_EXIT=void 0,exports.exitMeansCouldNotRun=function(e){return e===exports.RUN_PARSE_FAILED_EXIT||127===e},exports.execAsync=async function(e,t={}){return new Promise((r,o)=>{const[s,...a]=e.split(" "),i=(0,n.spawn)(s,a,{cwd:t.cwd||process.cwd(),stdio:["pipe","pipe","pipe"]})
573
+ return new Promise(t=>{const s="win32"===process.platform,a=s?n(e,{cwd:r.cwd??process.cwd(),env:r.env,shell:"cmd.exe",stdio:["pipe","pipe","pipe"],detached:!1}):n("/bin/sh",["-c",exports.RUN_FROM_ENV],{cwd:r.cwd??process.cwd(),env:{...r.env??process.env,[exports.RUN_ENV_VAR]:e},stdio:["pipe","pipe","pipe"],detached:!0}),i=[],c=[]
574
+ let l=!1,u=!1
575
+ const d=e=>{if(a.pid)try{s?a.kill(e):process.kill(-a.pid,e)}catch{}}
576
+ let p,f
577
+ r.onKillReady?.((e="SIGTERM")=>{d(e),"SIGKILL"!==e&&setTimeout(()=>{u||d("SIGKILL")},2e3)}),r.timeoutMs&&r.timeoutMs>0&&(f=(0,o.awakeTimeout)(()=>{l=!0,d("SIGTERM"),p=setTimeout(()=>{u||d("SIGKILL")},2e3)},r.timeoutMs)),a.stdout?.on("data",e=>{i.push(e),r.onChunk?.("stdout",e)}),a.stderr?.on("data",e=>{c.push(e),r.onChunk?.("stderr",e)})
578
+ const m=e=>{u||(u=!0,f?.clear(),p&&clearTimeout(p),t({stdout:Buffer.concat(i).toString("utf-8"),stderr:Buffer.concat(c).toString("utf-8"),exitCode:e,timedOut:l}))}
579
+ a.on("close",e=>m(e??(l?124:1))),a.on("error",()=>m(1))})}Object.defineProperty(exports,"__esModule",{value:!0}),exports.RUN_ENV_VAR=exports.RUN_FROM_ENV=exports.RUN_PARSE_FAILED_EXIT=void 0,exports.exitMeansCouldNotRun=function(e){return e===exports.RUN_PARSE_FAILED_EXIT||127===e},exports.execAsync=async function(e,t={}){return new Promise((r,o)=>{const[s,...a]=e.split(" "),i=(0,n.spawn)(s,a,{cwd:t.cwd||process.cwd(),stdio:["pipe","pipe","pipe"]})
521
580
  let c="",l=""
522
581
  i.stdout?.on("data",e=>{c+=e.toString()}),i.stderr?.on("data",e=>{l+=e.toString()}),i.on("close",e=>{r({stdout:c,stderr:l,exitCode:e||0})}),i.on("error",t=>{o(new Error(`Command failed: ${e}\nError: ${t.message}`))}),t.timeout&&setTimeout(()=>{i.kill(),o(new Error(`Command timed out: ${e}`))},t.timeout)})},exports.runShellCommand=r,exports.runTrackedShellCommand=async function(e,n,o){const{getActionServerBaseUrl:s}=await t.e(414).then(()=>t(79414)),a=s(),i=(new Date).toISOString(),c=n.cwd??process.cwd()
523
582
  let l
524
583
  fetch(`${a}/api/commands/start`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({id:o.id,name:o.name,command:e,cwd:c,sessionId:o.sessionId,startedAt:i,logPath:o.logPath,timeoutMs:n.timeoutMs}),signal:AbortSignal.timeout(2e3)}).catch(()=>{})
525
584
  try{l=await r(e,n)}catch(e){throw fetch(`${a}/api/commands/end`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({id:o.id,exitCode:1,timedOut:!1,finishedAt:(new Date).toISOString()}),signal:AbortSignal.timeout(2e3)}).catch(()=>{}),e}return fetch(`${a}/api/commands/end`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({id:o.id,exitCode:l.exitCode,timedOut:l.timedOut,finishedAt:(new Date).toISOString()}),signal:AbortSignal.timeout(2e3)}).catch(()=>{}),l}
526
- const n=t(35317)
527
- exports.RUN_PARSE_FAILED_EXIT=125,exports.RUN_FROM_ENV=["c=$ALCHEMY_RUN_CMD; unset ALCHEMY_RUN_CMD",`if (set -o pipefail) 2>/dev/null; then set -o pipefail; sh -n -c "$c" || exit ${exports.RUN_PARSE_FAILED_EXIT}; eval "$c"`,`elif command -v bash >/dev/null 2>&1; then ALCHEMY_RUN_CMD=$c; export ALCHEMY_RUN_CMD; exec bash -o pipefail -c 'c=$ALCHEMY_RUN_CMD; unset ALCHEMY_RUN_CMD; bash -n -c "$c" || exit ${exports.RUN_PARSE_FAILED_EXIT}; eval "$c"'`,`else sh -n -c "$c" || exit ${exports.RUN_PARSE_FAILED_EXIT}; eval "$c"; fi`].join("\n"),exports.RUN_ENV_VAR="ALCHEMY_RUN_CMD"},88194(module){module.exports=require("jszip")},9956(module){module.exports=require("undici")},88891(module){module.exports=require("unpdf")},35317(module){module.exports=require("child_process")},76982(module){module.exports=require("crypto")},79896(module){module.exports=require("fs")},91943(module){module.exports=require("fs/promises")},16698(module){module.exports=require("node:async_hooks")},31421(module){module.exports=require("node:child_process")},73024(module){module.exports=require("node:fs")},48161(module){module.exports=require("node:os")},76760(module){module.exports=require("node:path")},70857(module){module.exports=require("os")},16928(module){module.exports=require("path")},2203(module){module.exports=require("stream")}}
585
+ const n=t(35317),o=t(4334)
586
+ exports.RUN_PARSE_FAILED_EXIT=125,exports.RUN_FROM_ENV=["c=$ALCHEMY_RUN_CMD; unset ALCHEMY_RUN_CMD",`case "$c" in *ALCHEMY_PROJECT_ROOT*) if [ -z "\${ALCHEMY_PROJECT_ROOT:-}" ]; then echo "Not run: ALCHEMY_PROJECT_ROOT (the project's folder) is not set here." >&2; exit ${exports.RUN_PARSE_FAILED_EXIT}; fi;; esac`,`if command -v bash >/dev/null 2>&1; then ALCHEMY_RUN_CMD=$c; export ALCHEMY_RUN_CMD; exec bash -o pipefail -c 'c=$ALCHEMY_RUN_CMD; unset ALCHEMY_RUN_CMD; bash -n -c "$c" || exit ${exports.RUN_PARSE_FAILED_EXIT}; eval "$c"'`,`elif (set -o pipefail) 2>/dev/null; then set -o pipefail; sh -n -c "$c" || exit ${exports.RUN_PARSE_FAILED_EXIT}; eval "$c"`,`else sh -n -c "$c" || exit ${exports.RUN_PARSE_FAILED_EXIT}; eval "$c"; fi`].join("\n"),exports.RUN_ENV_VAR="ALCHEMY_RUN_CMD"},88194(module){module.exports=require("jszip")},9956(module){module.exports=require("undici")},88891(module){module.exports=require("unpdf")},35317(module){module.exports=require("child_process")},76982(module){module.exports=require("crypto")},79896(module){module.exports=require("fs")},91943(module){module.exports=require("fs/promises")},16698(module){module.exports=require("node:async_hooks")},31421(module){module.exports=require("node:child_process")},73024(module){module.exports=require("node:fs")},48161(module){module.exports=require("node:os")},76760(module){module.exports=require("node:path")},70857(module){module.exports=require("os")},16928(module){module.exports=require("path")},2203(module){module.exports=require("stream")}}
528
587
  const r={}
529
588
  e.m=t,e.c=r,(()=>{const t=Object.getPrototypeOf
530
589
  let r