alchemylab 3.0.4 → 3.0.5
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.
- package/dist/293.js +41 -40
- package/dist/cli.js +191 -168
- package/dist/http-server.js +98 -70
- package/dist/index.js +98 -70
- package/dist/mcp-direct.js +275 -247
- package/package.json +2 -2
package/dist/293.js
CHANGED
|
@@ -1,58 +1,59 @@
|
|
|
1
1
|
"use strict"
|
|
2
|
-
exports.ids=[293],exports.modules={79293(e,exports,t){function
|
|
3
|
-
if(!
|
|
2
|
+
exports.ids=[293],exports.modules={79293(e,exports,t){function n(e){const t=e.lastIndexOf("@"),n=t>0?e.slice(t+1):""
|
|
3
|
+
if(!n||!/^\d/.test(n))throw new Error(`"${e}" has no pinned version. A boxed connection installs once and reuses that build, so it needs an exact version, for example ${function(e){const t=String(e??"").lastIndexOf("@")
|
|
4
4
|
return t>0?e.slice(0,t):String(e??"")}(e)}@1.2.3.`)
|
|
5
|
-
return
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
if(
|
|
9
|
-
|
|
5
|
+
return n}function r(e,t){return(0,s.addressedName)("alchemy-mcp-box",e,t)}async function o(e,t,n){const o=r(e.projectId,e.name),c=(p=e.projectId,g=e.name,(0,s.addressedName)("alchemy-mcp-state",p,g)),d=e.image??l,m=await(0,i.docker)(["inspect","-f",'{{.State.Running}} {{index .Config.Labels "alchemy.image"}} {{index .Config.Labels "alchemy.box"}}',o],i.DOCKER_OP_TIMEOUT_MS)
|
|
6
|
+
var p,g
|
|
7
|
+
if(0===m.exit){const[e,t,r]=m.stdout.trim().split(/\s+/,3)
|
|
8
|
+
if("true"===e&&(t??"")===d&&"2"===(r??""))return{ok:!0,box:o}
|
|
9
|
+
"true"===e&&n.info("MCP connection box holds another image, replacing it",{box:o,was:t,now:d}),await(0,i.docker)(["rm","-f",o],i.DOCKER_OP_TIMEOUT_MS)}const f=null===t?void 0:await(0,i.ensureImage)(d)
|
|
10
|
+
if(f)return{ok:!1,error:f}
|
|
11
|
+
const k=await(0,i.docker)(["run","--rm","-u","0","-v",`${c}:/state`,"alpine:3.20","sh","-c","touch /state/.owner && chown -R 1000:1000 /state"],i.DOCKER_OP_TIMEOUT_MS)
|
|
12
|
+
if(0!==k.exit)return{ok:!1,error:`could not prepare the state volume: ${(k.stderr||"").trim()}`}
|
|
13
|
+
const h=Object.entries(e.environment??{}).flatMap(([e,t])=>["-e",`${e}=${t}`]),w=await(0,i.docker)(["create","--name",o,"--label",u,"--label",`alchemy.project=${e.projectId}`,"--label",`alchemy.image=${d}`,"--label","alchemy.box=2","--label",`alchemy.connection=${e.name}`,...(0,a.hardenedCreateArgs)({network:(x=e.egress,"open"===x?"bridge":"none"),user:"1000:1000",memory:"1g",cpus:1,pidsLimit:256,...null===t?{extraTmpfs:["/scratch:rw,nosuid,nodev,size=1g"]}:{}}),...h,...null===t?[]:["-v",`${t}:/pkg:ro`],...null===t?["--entrypoint","tail"]:[],"-v",`${c}:/state`,...e.worktreePath?["-v",`${e.worktreePath}:/work:ro`]:[],...null===t?[]:["-w",e.worktreePath?"/work":"/state"],d,...null===t?["-f","/dev/null"]:["tail","-f","/dev/null"]],i.DOCKER_OP_TIMEOUT_MS)
|
|
14
|
+
var x
|
|
15
|
+
if(0!==w.exit)return{ok:!1,error:`could not create the box: ${(w.stderr||"").trim()}`}
|
|
16
|
+
const $=await(0,i.docker)(["start",o],i.DOCKER_OP_TIMEOUT_MS)
|
|
17
|
+
return 0!==$.exit?(await(0,i.docker)(["rm","-f",o],i.DOCKER_OP_TIMEOUT_MS),{ok:!1,error:`could not start the box: ${($.stderr||"").trim()}`}):(n.info("MCP connection box up",{box:o,image:d,package:e.packageSpec??null,egress:e.egress??"none"}),{ok:!0,box:o})}exports.K4=void 0,exports.prepareConnectionArtifact=async function(e,t){const r=String(e.packageSpec??"")
|
|
18
|
+
n(r)
|
|
19
|
+
const o=function(e){return n(e),(0,s.addressedName)("alchemy-mcp-pkg",e)}(r)
|
|
20
|
+
if(await async function(e){return!!await(0,i.volumeExists)(e)&&0===(await(0,i.docker)(["run","--rm","-v",`${e}:/pkg:ro`,"alpine:3.20","test","-f",`/pkg/${d}`],i.DOCKER_OP_TIMEOUT_MS)).exit}(o))return t.info("MCP artifact already installed, reusing",{volume:o,package:r}),{ok:!0,volume:o}
|
|
21
|
+
const a=e.image??l,m=await(0,i.ensureImage)(a)
|
|
10
22
|
if(m)return{ok:!1,error:m}
|
|
11
|
-
const p=await(0,
|
|
23
|
+
const p=await(0,i.docker)(["run","--rm","-u","0","-v",`${o}:/pkg`,"alpine:3.20","sh","-c","touch /pkg/.owner && chown -R 1000:1000 /pkg"],i.DOCKER_OP_TIMEOUT_MS)
|
|
12
24
|
if(0!==p.exit)return{ok:!1,error:`could not prepare the artifact volume: ${(p.stderr||"").trim()}`}
|
|
13
|
-
const g=new
|
|
25
|
+
const g=new c.EgressProxy(`mcp-pkg-${Date.now()}-${process.pid}`,exports.K4,!1)
|
|
14
26
|
let f=[],k=[]
|
|
15
27
|
const h=await g.start().catch(e=>({ok:!1,error:String(e)}))
|
|
16
28
|
if(!h.ok||!h.network)return await g.stop().catch(()=>{}),{ok:!1,error:`could not start the registry proxy, refusing to install with open egress: ${h.error??"unknown"}`}
|
|
17
|
-
f=["--network",h.network],k=Object.entries(h.proxyEnv||{}).flatMap(([e,t])=>["-e",`${e}=${t}`]),t.info("Installing MCP connection artifact",{package:
|
|
18
|
-
const w=await(0,
|
|
19
|
-
return await g.stop().catch(()=>{}),0!==w.exit?{ok:!1,error:`install failed: ${(w.stderr||w.stdout||`exit ${w.exit}`).trim().slice(0,400)}`}:(t.info("MCP connection artifact installed",{package:
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
if(
|
|
23
|
-
|
|
24
|
-
if(g)return{ok:!1,error:g}
|
|
25
|
-
const f=await(0,n.docker)(["run","--rm","-u","0","-v",`${l}:/state`,"alpine:3.20","sh","-c","touch /state/.owner && chown -R 1000:1000 /state"],n.DOCKER_OP_TIMEOUT_MS)
|
|
26
|
-
if(0!==f.exit)return{ok:!1,error:`could not prepare the state volume: ${(f.stderr||"").trim()}`}
|
|
27
|
-
const k=Object.entries(e.environment??{}).flatMap(([e,t])=>["-e",`${e}=${t}`]),h=await(0,n.docker)(["create","--name",i,"--label",s,"--label",`alchemy.project=${e.projectId}`,"--label",`alchemy.image=${u}`,"--label",`alchemy.connection=${e.name}`,...(0,o.hardenedCreateArgs)({network:(w=e.egress,"open"===w?"bridge":"none"),user:"1000:1000",memory:"1g",cpus:1,pidsLimit:256,...null===t?{extraTmpfs:["/scratch:rw,nosuid,nodev,size=1g"]}:{}}),...k,...null===t?[]:["-v",`${t}:/pkg:ro`],...null===t?["--entrypoint","tail"]:[],"-v",`${l}:/state`,...e.worktreePath?["-v",`${e.worktreePath}:/work:ro`,"-w","/work"]:["-w","/state"],u,...null===t?["-f","/dev/null"]:["tail","-f","/dev/null"]],n.DOCKER_OP_TIMEOUT_MS)
|
|
28
|
-
var w
|
|
29
|
-
if(0!==h.exit)return{ok:!1,error:`could not create the box: ${(h.stderr||"").trim()}`}
|
|
30
|
-
const x=await(0,n.docker)(["start",i],n.DOCKER_OP_TIMEOUT_MS)
|
|
31
|
-
return 0!==x.exit?(await(0,n.docker)(["rm","-f",i],n.DOCKER_OP_TIMEOUT_MS),{ok:!1,error:`could not start the box: ${(x.stderr||"").trim()}`}):(r.info("MCP connection box up",{box:i,image:u,package:e.packageSpec??null,egress:e.egress??"none"}),{ok:!0,box:i})},exports.boxedCommand=function(e,t){return["docker","exec","-i",e,"node",`/pkg/node_modules/.bin/${t}`]},exports.prepareRepoImage=async function(e,t){const r=(i=e.projectId,c=e.name,s=e.dockerfile,l=e.treeHash,`${(0,a.addressedName)("alchemy-mcp-repo",i,c,s,l)}:latest`),o=await(0,n.docker)(["image","inspect",r],n.DOCKER_OP_TIMEOUT_MS)
|
|
32
|
-
var i,c,s,l
|
|
33
|
-
if(o.spawnError)return{ok:!1,error:o.spawnError}
|
|
34
|
-
if(0===o.exit)return{ok:!0,image:r}
|
|
29
|
+
f=["--network",h.network],k=Object.entries(h.proxyEnv||{}).flatMap(([e,t])=>["-e",`${e}=${t}`]),t.info("Installing MCP connection artifact",{package:r,volume:o})
|
|
30
|
+
const w=await(0,i.docker)(["run","--rm","--label",u,"--user","1000:1000","--cap-drop","ALL","--security-opt","no-new-privileges","--read-only","--tmpfs","/tmp:rw,nosuid,nodev,exec,size=512m","--ipc","none","--memory","2g","--memory-swap","2g","--cpus","2","--pids-limit","512","-e","HOME=/tmp","-e","npm_config_cache=/tmp/.npm",...f,...k,"-v",`${o}:/pkg`,"-w","/pkg",a,"sh","-c",`npm install --no-audit --no-fund --no-package-lock ${r} && touch /pkg/${d}`],3e5)
|
|
31
|
+
return await g.stop().catch(()=>{}),0!==w.exit?{ok:!1,error:`install failed: ${(w.stderr||w.stdout||`exit ${w.exit}`).trim().slice(0,400)}`}:(t.info("MCP connection artifact installed",{package:r,volume:o}),{ok:!0,volume:o})},exports.ensureConnectionBox=async function(e,t,n){const i=r(e.projectId,e.name),a=(m.get(i)??Promise.resolve()).then(()=>o(e,t,n),()=>o(e,t,n)),c=a.then(()=>{},()=>{})
|
|
32
|
+
return m.set(i,c),c.then(()=>{m.get(i)===c&&m.delete(i)}),a},exports.boxedCommand=function(e,t){return["docker","exec","-i",e,"node",`/pkg/node_modules/.bin/${t}`]},exports.prepareRepoImage=async function(e,t){const n=(o=e.projectId,a=e.name,c=e.dockerfile,l=e.treeHash,`${(0,s.addressedName)("alchemy-mcp-repo",o,a,c,l)}:latest`),r=await(0,i.docker)(["image","inspect",n],i.DOCKER_OP_TIMEOUT_MS)
|
|
33
|
+
var o,a,c,l
|
|
34
|
+
if(r.spawnError)return{ok:!1,error:r.spawnError}
|
|
35
|
+
if(0===r.exit)return{ok:!0,image:n}
|
|
35
36
|
const u=e.context?.trim()||"."
|
|
36
|
-
t.info("Building MCP connection image from the repository",{name:e.name,dockerfile:e.dockerfile,context:u,tree:e.treeHash.slice(0,12),image:
|
|
37
|
-
const d=await(0,
|
|
37
|
+
t.info("Building MCP connection image from the repository",{name:e.name,dockerfile:e.dockerfile,context:u,tree:e.treeHash.slice(0,12),image:n})
|
|
38
|
+
const d=await(0,i.docker)(["build","-f",`${e.projectPath}/${e.dockerfile}`,"-t",n,`${e.projectPath}/${u}`],12e5)
|
|
38
39
|
if(0!==d.exit){const t=(d.stderr||d.stdout||`exit ${d.exit}`).trim().split("\n").slice(-6).join("\n")
|
|
39
|
-
return{ok:!1,error:`docker build of ${e.dockerfile} failed: ${t.slice(0,600)}`}}return t.info("MCP connection image built",{name:e.name,image:
|
|
40
|
-
if(0!==
|
|
41
|
-
const[o
|
|
42
|
-
return Array.isArray(t)?t:null}catch{return null}},c=function(e,t,
|
|
43
|
-
return c.length<=4?{ok:!1,error:"the image has no ENTRYPOINT or CMD, so there is nothing to run; give the Dockerfile one that starts the MCP server on stdio"}:{ok:!0,command:c}},exports.explainDerivedCommand=async function(e,
|
|
40
|
+
return{ok:!1,error:`docker build of ${e.dockerfile} failed: ${t.slice(0,600)}`}}return t.info("MCP connection image built",{name:e.name,image:n}),{ok:!0,image:n}},exports.repoCommand=async function(e,t){const n=await(0,i.docker)(["image","inspect","-f","{{json .Config.Entrypoint}}\n{{json .Config.Cmd}}",t],i.DOCKER_OP_TIMEOUT_MS)
|
|
41
|
+
if(0!==n.exit)return{ok:!1,error:`could not read the image's entrypoint: ${(n.stderr||"").trim()}`}
|
|
42
|
+
const[r,o]=n.stdout.trim().split("\n"),a=e=>{try{const t=JSON.parse(e??"null")
|
|
43
|
+
return Array.isArray(t)?t:null}catch{return null}},c=function(e,t,n){return["docker","exec","-i",e,...t??[],...n??[]]}(e,a(r),a(o))
|
|
44
|
+
return c.length<=4?{ok:!1,error:"the image has no ENTRYPOINT or CMD, so there is nothing to run; give the Dockerfile one that starts the MCP server on stdio"}:{ok:!0,command:c}},exports.explainDerivedCommand=async function(e,n=8e3){const{spawn:r}=await Promise.resolve().then(()=>t.t(35317,23))
|
|
44
45
|
return await new Promise(t=>{let o="",i=!1
|
|
45
46
|
const a=e=>{i||(i=!0,t(e))}
|
|
46
|
-
try{const t=
|
|
47
|
+
try{const t=r(e[0],e.slice(1),{stdio:["ignore","pipe","pipe"]}),i=e=>{o=(o+e.toString("utf8")).slice(-2e3)}
|
|
47
48
|
t.stdout?.on("data",i),t.stderr?.on("data",i)
|
|
48
|
-
const c=setTimeout(()=>{try{t.kill("SIGKILL")}catch{}a("")},
|
|
49
|
+
const c=setTimeout(()=>{try{t.kill("SIGKILL")}catch{}a("")},n)
|
|
49
50
|
t.on("error",e=>{clearTimeout(c),a(String(e.message??e))}),t.on("close",e=>{clearTimeout(c)
|
|
50
51
|
const t=o.trim().split("\n").filter(Boolean).slice(-4).join("\n")
|
|
51
52
|
a(t?`exit ${e}: ${t}`:0===e?"":`exit ${e} with no output`)})}catch(e){a(String(e?.message??e))}})}
|
|
52
|
-
const
|
|
53
|
+
const i=t(81618),a=t(26166),c=t(99559),s=t(56149),l="node:20-alpine",u="alchemy.mcp=connection"
|
|
53
54
|
exports.K4=["registry.npmjs.org","npmjs.org","npmjs.com"]
|
|
54
|
-
const
|
|
55
|
-
for(const
|
|
55
|
+
const d=".alchemy-install-complete",m=new Map},56149(e,exports,t){exports.Jj=void 0,exports.addressedName=function(e,...t){return`${e}-${function(e,t=exports.Jj){return e.slice(0,t)}(function(...e){const t=(0,n.createHash)("sha256")
|
|
56
|
+
for(const n of e){const e=n??""
|
|
56
57
|
t.update(String(e.length)).update(":").update(e).update("\0")}return t.digest("hex")}(...t))}`}
|
|
57
|
-
const
|
|
58
|
+
const n=t(76982)
|
|
58
59
|
exports.Jj=12}}
|