alchemylab 1.4.14 → 2.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.
- package/README.md +39 -0
- package/dist/129.js +25 -0
- package/dist/19.js +260 -0
- package/dist/{800.js → 237.js} +5 -5
- package/dist/301.js +138 -0
- package/dist/380.js +17 -0
- package/dist/403.js +4 -0
- package/dist/491.js +31 -0
- package/dist/540.js +56 -0
- package/dist/554.js +26 -0
- package/dist/{60.js → 565.js} +8 -8
- package/dist/636.js +11 -0
- package/dist/674.js +15 -0
- package/dist/729.js +89 -0
- package/dist/796.js +47 -0
- package/dist/cli.js +6571 -1623
- package/dist/document-textconv.js +484 -0
- package/dist/http-server.js +7243 -5436
- package/dist/index.js +7254 -5457
- package/dist/mcp-direct.js +7147 -5301
- package/dist/plugins/hooks/plugin.js +1 -157
- package/dist/plugins/inject-session.js +1 -66
- package/dist/plugins/system-logger.js +1 -93
- package/package.json +26 -15
- package/dist/414.js +0 -9
- package/dist/478.js +0 -109
- package/dist/939.js +0 -17
- package/dist/994.js +0 -126
- package/dist/mcp-cli-bridge.js +0 -96
- package/dist/plugins/hooks/lib/condition-evaluator.js +0 -114
- package/dist/plugins/hooks/lib/dedup-utils.js +0 -94
- package/dist/plugins/hooks/lib/hook-utils.js +0 -90
package/dist/540.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict"
|
|
2
|
+
exports.id=540,exports.ids=[540],exports.modules={76390:(e,exports,t)=>{function r(...e){const t=(0,o.createHash)("sha256")
|
|
3
|
+
for(const r of e){const e=r??""
|
|
4
|
+
t.update(String(e.length)).update(":").update(e).update("\0")}return t.digest("hex")}function n(e,t=exports.SHORT_ADDRESS_LENGTH){return e.slice(0,t)}Object.defineProperty(exports,"__esModule",{value:!0}),exports.SHORT_ADDRESS_LENGTH=void 0,exports.contentAddress=r,exports.shortAddress=n,exports.addressedName=function(e,...t){return`${e}-${n(r(...t))}`}
|
|
5
|
+
const o=t(76982)
|
|
6
|
+
exports.SHORT_ADDRESS_LENGTH=12},78540:(e,exports,t)=>{function r(e){const t=String(e??"").lastIndexOf("@")
|
|
7
|
+
return t>0?e.slice(0,t):String(e??"")}function n(e){const t=e.lastIndexOf("@"),n=t>0?e.slice(t+1):""
|
|
8
|
+
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 ${r(e)}@1.2.3.`)
|
|
9
|
+
return n}function o(e){return n(e),(0,m.addressedName)("alchemy-mcp-pkg",e)}function i(e,t){return(0,m.addressedName)("alchemy-mcp-state",e,t)}function a(e,t){return(0,m.addressedName)("alchemy-mcp-box",e,t)}function c(e,t,r,n){return`${(0,m.addressedName)("alchemy-mcp-repo",e,t,r,n)}:latest`}function s(e,t,r){return["docker","exec","-i",e,...t??[],...r??[]]}Object.defineProperty(exports,"__esModule",{value:!0}),exports.REGISTRY_ALLOWLIST=void 0,exports.packageNameOf=r,exports.assertPinned=n,exports.artifactVolumeFor=o,exports.stateVolumeFor=i,exports.boxNameFor=a,exports.prepareConnectionArtifact=async function(e,t){const r=String(e.packageSpec??"")
|
|
10
|
+
n(r)
|
|
11
|
+
const i=o(r)
|
|
12
|
+
if(await async function(e){return!!await(0,l.volumeExists)(e)&&0===(await(0,l.docker)(["run","--rm","-v",`${e}:/pkg:ro`,"alpine:3.20","test","-f",`/pkg/${k}`],l.DOCKER_OP_TIMEOUT_MS)).exit}(i))return t.info("MCP artifact already installed, reusing",{volume:i,package:r}),{ok:!0,volume:i}
|
|
13
|
+
const a=e.image??f,c=await(0,l.ensureImage)(a)
|
|
14
|
+
if(c)return{ok:!1,error:c}
|
|
15
|
+
const s=await(0,l.docker)(["run","--rm","-u","0","-v",`${i}:/pkg`,"alpine:3.20","sh","-c","touch /pkg/.owner && chown -R 1000:1000 /pkg"],l.DOCKER_OP_TIMEOUT_MS)
|
|
16
|
+
if(0!==s.exit)return{ok:!1,error:`could not prepare the artifact volume: ${(s.stderr||"").trim()}`}
|
|
17
|
+
const u=new d.EgressProxy(`mcp-pkg-${Date.now()}-${process.pid}`,exports.REGISTRY_ALLOWLIST,!1)
|
|
18
|
+
let m=[],h=[]
|
|
19
|
+
const w=await u.start().catch((e=>({ok:!1,error:String(e)})))
|
|
20
|
+
if(!w.ok||!w.network)return await u.stop().catch((()=>{})),{ok:!1,error:`could not start the registry proxy, refusing to install with open egress: ${w.error??"unknown"}`}
|
|
21
|
+
m=["--network",w.network],h=Object.entries(w.proxyEnv||{}).flatMap((([e,t])=>["-e",`${e}=${t}`])),t.info("Installing MCP connection artifact",{package:r,volume:i})
|
|
22
|
+
const x=await(0,l.docker)(["run","--rm","--label",g,"--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",...m,...h,"-v",`${i}:/pkg`,"-w","/pkg",a,"sh","-c",`npm install --no-audit --no-fund --no-package-lock ${r} && touch /pkg/${k}`],p)
|
|
23
|
+
return await u.stop().catch((()=>{})),0!==x.exit?{ok:!1,error:`install failed: ${(x.stderr||x.stdout||`exit ${x.exit}`).trim().slice(0,400)}`}:(t.info("MCP connection artifact installed",{package:r,volume:i}),{ok:!0,volume:i})},exports.ensureConnectionBox=async function(e,t,r){const n=a(e.projectId,e.name),o=i(e.projectId,e.name),c=e.image??f,s=await(0,l.docker)(["inspect","-f",'{{.State.Running}} {{index .Config.Labels "alchemy.image"}}',n],l.DOCKER_OP_TIMEOUT_MS)
|
|
24
|
+
if(0===s.exit){const[e,t]=s.stdout.trim().split(/\s+/,2)
|
|
25
|
+
if("true"===e&&(t??"")===c)return{ok:!0,box:n}
|
|
26
|
+
"true"===e&&r.info("MCP connection box holds another image, replacing it",{box:n,was:t,now:c}),await(0,l.docker)(["rm","-f",n],l.DOCKER_OP_TIMEOUT_MS)}const d=null===t?void 0:await(0,l.ensureImage)(c)
|
|
27
|
+
if(d)return{ok:!1,error:d}
|
|
28
|
+
const m=await(0,l.docker)(["run","--rm","-u","0","-v",`${o}:/state`,"alpine:3.20","sh","-c","touch /state/.owner && chown -R 1000:1000 /state"],l.DOCKER_OP_TIMEOUT_MS)
|
|
29
|
+
if(0!==m.exit)return{ok:!1,error:`could not prepare the state volume: ${(m.stderr||"").trim()}`}
|
|
30
|
+
const p=Object.entries(e.environment??{}).flatMap((([e,t])=>["-e",`${e}=${t}`])),k=await(0,l.docker)(["create","--name",n,"--label",g,"--label",`alchemy.project=${e.projectId}`,"--label",`alchemy.image=${c}`,"--label",`alchemy.connection=${e.name}`,...(0,u.hardenedCreateArgs)({network:(h=e.egress,"open"===h?"bridge":"none"),user:"1000:1000",memory:"1g",cpus:1,pidsLimit:256,...null===t?{extraTmpfs:["/scratch:rw,nosuid,nodev,size=1g"]}:{}}),...p,...null===t?[]:["-v",`${t}:/pkg:ro`],...null===t?["--entrypoint","tail"]:[],"-v",`${o}:/state`,...e.worktreePath?["-v",`${e.worktreePath}:/work:ro`,"-w","/work"]:["-w","/state"],c,...null===t?["-f","/dev/null"]:["tail","-f","/dev/null"]],l.DOCKER_OP_TIMEOUT_MS)
|
|
31
|
+
var h
|
|
32
|
+
if(0!==k.exit)return{ok:!1,error:`could not create the box: ${(k.stderr||"").trim()}`}
|
|
33
|
+
const w=await(0,l.docker)(["start",n],l.DOCKER_OP_TIMEOUT_MS)
|
|
34
|
+
return 0!==w.exit?(await(0,l.docker)(["rm","-f",n],l.DOCKER_OP_TIMEOUT_MS),{ok:!1,error:`could not start the box: ${(w.stderr||"").trim()}`}):(r.info("MCP connection box up",{box:n,image:c,package:e.packageSpec??null,egress:e.egress??"none"}),{ok:!0,box:n})},exports.boxedCommand=function(e,t){return["docker","exec","-i",e,"node",`/pkg/node_modules/.bin/${t}`]},exports.repoImageTagFor=c,exports.prepareRepoImage=async function(e,t){const r=c(e.projectId,e.name,e.dockerfile,e.treeHash),n=await(0,l.docker)(["image","inspect",r],l.DOCKER_OP_TIMEOUT_MS)
|
|
35
|
+
if(n.spawnError)return{ok:!1,error:n.spawnError}
|
|
36
|
+
if(0===n.exit)return{ok:!0,image:r}
|
|
37
|
+
const o=e.context?.trim()||"."
|
|
38
|
+
t.info("Building MCP connection image from the repository",{name:e.name,dockerfile:e.dockerfile,context:o,tree:e.treeHash.slice(0,12),image:r})
|
|
39
|
+
const i=await(0,l.docker)(["build","-f",`${e.projectPath}/${e.dockerfile}`,"-t",r,`${e.projectPath}/${o}`],h)
|
|
40
|
+
if(0!==i.exit){const t=(i.stderr||i.stdout||`exit ${i.exit}`).trim().split("\n").slice(-6).join("\n")
|
|
41
|
+
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:r}),{ok:!0,image:r}},exports.execCommandFromImageConfig=s,exports.repoCommand=async function(e,t){const r=await(0,l.docker)(["image","inspect","-f","{{json .Config.Entrypoint}}\n{{json .Config.Cmd}}",t],l.DOCKER_OP_TIMEOUT_MS)
|
|
42
|
+
if(0!==r.exit)return{ok:!1,error:`could not read the image's entrypoint: ${(r.stderr||"").trim()}`}
|
|
43
|
+
const[n,o]=r.stdout.trim().split("\n"),i=e=>{try{const t=JSON.parse(e??"null")
|
|
44
|
+
return Array.isArray(t)?t:null}catch{return null}},a=s(e,i(n),i(o))
|
|
45
|
+
return a.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:a}},exports.removeConnectionBox=async function(e,t){await(0,l.docker)(["rm","-f",a(e,t)],l.DOCKER_OP_TIMEOUT_MS).catch((()=>{}))},exports.explainDerivedCommand=async function(e,r=8e3){const{spawn:n}=await Promise.resolve().then(t.t.bind(t,35317,23))
|
|
46
|
+
return await new Promise((t=>{let o="",i=!1
|
|
47
|
+
const a=e=>{i||(i=!0,t(e))}
|
|
48
|
+
try{const t=n(e[0],e.slice(1),{stdio:["ignore","pipe","pipe"]}),i=e=>{o=(o+e.toString("utf8")).slice(-2e3)}
|
|
49
|
+
t.stdout?.on("data",i),t.stderr?.on("data",i)
|
|
50
|
+
const c=setTimeout((()=>{try{t.kill("SIGKILL")}catch{}a("")}),r)
|
|
51
|
+
t.on("error",(e=>{clearTimeout(c),a(String(e.message??e))})),t.on("close",(e=>{clearTimeout(c)
|
|
52
|
+
const t=o.trim().split("\n").filter(Boolean).slice(-4).join("\n")
|
|
53
|
+
a(t?`exit ${e}: ${t}`:0===e?"":`exit ${e} with no output`)}))}catch(e){a(String(e?.message??e))}}))}
|
|
54
|
+
const l=t(6175),u=t(53157),d=t(79242),m=t(76390),p=3e5,f="node:20-alpine",g="alchemy.mcp=connection"
|
|
55
|
+
exports.REGISTRY_ALLOWLIST=["registry.npmjs.org","npmjs.org","npmjs.com"]
|
|
56
|
+
const k=".alchemy-install-complete",h=12e5}}
|
package/dist/554.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict"
|
|
2
|
+
exports.id=554,exports.ids=[554],exports.modules={98554:(e,exports,n)=>{async function t(e,t){const s=l.get(e)
|
|
3
|
+
if(s&&!s.checking){s.checking=!0
|
|
4
|
+
try{const r=(0,a.getOpenCodeUrlFromConfig)(s.context.projectPath)?.replace(/\/$/,"")
|
|
5
|
+
if(!r)return
|
|
6
|
+
if(await async function(e,n){try{const t=await fetch(`${e}/session/status`,{signal:AbortSignal.timeout(5e3)})
|
|
7
|
+
if(!t.ok)return!1
|
|
8
|
+
const o=await t.json(),a=o?.[n]?.type
|
|
9
|
+
return!!a&&"idle"!==a}catch{return!1}}(r,e))return
|
|
10
|
+
if(!l.has(e))return
|
|
11
|
+
if(d.has(e))return void o(e,"already-nudged")
|
|
12
|
+
d.add(e),o(e,`nudging (${t})`)
|
|
13
|
+
const{executeAction:i}=await Promise.resolve().then(n.bind(n,21386)),f=s.planWritten?exports.vB:c,u=await i("inject-prompt",{sessionId:e,message:f},s.context)
|
|
14
|
+
u.success?s.context.logger.info("planner-handoff watch: nudge injected",{sessionId:e,trigger:t}):s.context.logger.warn("planner-handoff watch: nudge inject failed",{sessionId:e,trigger:t,error:u.error||u.message})}catch(n){s.context.logger.warn("planner-handoff watch: check failed",{sessionId:e,trigger:t,error:(0,r.getErrorMessage)(n)})}finally{s.checking=!1}}}function o(e,n){const t=l.get(e)
|
|
15
|
+
t&&(clearTimeout(t.expiry),t.poll&&clearInterval(t.poll),l.delete(e),t.context.logger.info("planner-handoff watch: stopped",{sessionId:e,reason:n}))}exports.vB=void 0,exports.trackAutonomousPlanner=function(e,n){if(!n||l.has(n)||d.has(n))return
|
|
16
|
+
const a=setTimeout((()=>{o(n,"ttl-expired")}),i)
|
|
17
|
+
a.unref?.()
|
|
18
|
+
const r={context:e,planWritten:!1,checking:!1,expiry:a}
|
|
19
|
+
r.poll=setInterval((()=>{t(n,"poll")}),s),r.poll.unref?.(),l.set(n,r),e.logger.info("planner-handoff watch: watching autonomous planner (nudge armed at spawn)",{sessionId:n})},exports.notifyPlannerHandoffToolEvent=function(e,n,t){const a=l.get(e)
|
|
20
|
+
if(!a)return
|
|
21
|
+
const r=t&&"object"==typeof t?t.operation:void 0
|
|
22
|
+
n.includes("session_message_operations")&&"offer-handoff"===r?o(e,"offer-handoff observed"):!a.planWritten&&n.includes("plan_write")&&"string"==typeof r&&f.has(r)&&(a.planWritten=!0,a.context.logger.info("planner-handoff watch: plan written",{sessionId:e}))},exports.notifyPlannerHandoffSessionIdle=function(e){return l.has(e)?t(e,"idle-event"):Promise.resolve()},exports.hasParkVetoingPlannerHandoffWatches=function(){for(const e of l.values())if(e.planWritten)return!0
|
|
23
|
+
return!1}
|
|
24
|
+
const a=n(61468),r=n(21319),s=3e4,i=216e5,f=new Set(["create","update","append","replace"])
|
|
25
|
+
exports.vB='[handoff nudge] This autonomous planning session went idle after writing the plan without offering handoff -- the flow is waiting on that call. If the plan and its requests are complete, call session_message_operations { operation: "offer-handoff", offerHandoff: { summary: "<one-line plan summary>", requestIds: ["req...", ...] } } now, then STOP. If requests are not created yet, finish decomposing first, then offer. This reminder fires only once.'
|
|
26
|
+
const l=new Map,c='[handoff nudge] This autonomous planning session went idle WITHOUT writing its plan. If you were waiting on a research subagent, its findings should have reached you by now -- proceed with what you have rather than waiting further. Fill in the plan document with plan_write, decompose it into requests, then call session_message_operations { operation: "offer-handoff", offerHandoff: { summary: "<one-line plan summary>", requestIds: ["req...", ...] } } and STOP. If you genuinely cannot plan this, say why in the plan document and offer handoff anyway. This reminder fires only once.',d=new Set}}
|
package/dist/{60.js → 565.js}
RENAMED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
"use strict"
|
|
2
|
-
exports.id=
|
|
2
|
+
exports.id=565,exports.ids=[565],exports.modules={87565:function(t,exports,e){var a=this&&this.__importDefault||function(t){return t&&t.__esModule?t:{default:t}}
|
|
3
3
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.ConfigManager=void 0,exports.createConfigManager=function(t){return new g(t)}
|
|
4
|
-
const i=a(e(
|
|
5
|
-
class g{constructor(t){this.logger=t.child({component:"config-manager"}),this.installationConfigDir=this.getInstallationConfigDir()}getInstallationConfigDir(){const t=__dirname||process.cwd(),e=
|
|
4
|
+
const i=a(e(91943)),n=a(e(16928)),o=a(e(70857)),r=e(21992),s=e(21319),c={},l={remoteServerUrl:"https://api.alchemylabcode.com",nodePath:"node"}
|
|
5
|
+
class g{constructor(t){this.logger=t.child({component:"config-manager"}),this.installationConfigDir=this.getInstallationConfigDir()}getInstallationConfigDir(){const t=__dirname||process.cwd(),e=o.default.homedir()
|
|
6
6
|
return t.includes("node_modules")?n.default.join(e,".alchemy_lab","config"):n.default.join(e,".alchemy_lab","config-dev")}async ensureDirectory(t){try{await i.default.access(t)}catch(e){await i.default.mkdir(t,{recursive:!0}),this.logger.debug("Created directory",{dirPath:t})}}async readConfig(t,e){try{const a=await i.default.readFile(t,"utf8"),n=JSON.parse(a)
|
|
7
|
-
return{...e,...n}}catch(a){return"ENOENT"===a.code||this.logger.warn("Error reading config file, using defaults",{filePath:t,error:(0,s.getErrorMessage)(a)}),e}}async writeConfig(t,e){await this.ensureDirectory(n.default.dirname(t)),await i.default.writeFile(t,JSON.stringify(e,null,2),"utf8"),this.logger.debug("Wrote config file",{filePath:t})}async getProjectConfig(t){const e=n.default.join(t,
|
|
8
|
-
return this.readConfig(e,
|
|
9
|
-
await this.writeConfig(a,i),this.logger.info("Updated project config",{projectPath:t,updates:e})}async getProjectMetadata(t){const e=n.default.join(t,
|
|
7
|
+
return{...e,...n}}catch(a){return"ENOENT"===a.code||this.logger.warn("Error reading config file, using defaults",{filePath:t,error:(0,s.getErrorMessage)(a)}),e}}async writeConfig(t,e){await this.ensureDirectory(n.default.dirname(t)),await i.default.writeFile(t,JSON.stringify(e,null,2),"utf8"),this.logger.debug("Wrote config file",{filePath:t})}async getProjectConfig(t){const e=n.default.join(t,r.ALCHEMY_DIR_NAME,"config.json")
|
|
8
|
+
return this.readConfig(e,c)}async updateProjectConfig(t,e){const a=n.default.join(t,r.ALCHEMY_DIR_NAME,"config.json"),i={...await this.getProjectConfig(t),...e}
|
|
9
|
+
await this.writeConfig(a,i),this.logger.info("Updated project config",{projectPath:t,updates:e})}async getProjectMetadata(t){const e=n.default.join(t,r.ALCHEMY_DIR_NAME,"project.json")
|
|
10
10
|
try{const t=await i.default.readFile(e,"utf8"),a=JSON.parse(t)
|
|
11
11
|
return{id:a.id,name:a.name,createdAt:a.createdAt,status:a.status}}catch(t){return"ENOENT"===t.code||this.logger.warn("Error reading project metadata",{projectJsonPath:e,error:(0,s.getErrorMessage)(t)}),null}}async getInstallationConfig(){const t=n.default.join(this.installationConfigDir,"config.json")
|
|
12
|
-
return this.readConfig(t,
|
|
12
|
+
return this.readConfig(t,l)}async updateInstallationConfig(t){const e=n.default.join(this.installationConfigDir,"config.json"),a={...await this.getInstallationConfig(),...t}
|
|
13
13
|
await this.writeConfig(e,a),this.logger.info("Updated installation config",{updates:t})}async getEffectiveConfig(t){const[e,a,i]=await Promise.all([this.getProjectConfig(t),this.getProjectMetadata(t),this.getInstallationConfig()])
|
|
14
|
-
return{remoteServerUrl:i.remoteServerUrl||
|
|
14
|
+
return{remoteServerUrl:i.remoteServerUrl||l.remoteServerUrl,nodePath:i.nodePath||l.nodePath,projectId:a?.id,projectName:a?.name}}getInstallationConfigPath(){return this.installationConfigDir}}exports.ConfigManager=g}}
|
package/dist/636.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict"
|
|
2
|
+
exports.id=636,exports.ids=[636],exports.modules={54636:(e,exports,t)=>{function n(e){const t=/(?:^|[\s:])([A-Za-z0-9_.+-]+): (?:command )?not found(?=\s|$)/m.exec(e)
|
|
3
|
+
return t?t[1]:null}async function a(e,n,a){const{actionServerFetch:s}=await Promise.resolve().then(t.bind(t,53603))
|
|
4
|
+
return(await s(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n),signal:AbortSignal.timeout(a)})).json().catch((()=>({})))}exports.trialFailures=function(e){const t=[]
|
|
5
|
+
for(const a of e){const e=n(a.output)
|
|
6
|
+
e?t.push(`${a.name}: the environment has no \`${e}\` (the command ran, but the shell said "${e}: not found")`):0!==a.exit&&t.push(`${a.name}: exited ${a.exit}: ${a.output.replace(/\s+/g," ").trim().slice(0,240)}`)}return t},exports.trialRun=async function(e){const t=await a("/api/experiments/start",{sessionId:e.sessionId,environmentId:e.environmentId,...e.branchName?{branchName:e.branchName}:{}},18e4).catch((()=>null)),n=t?.success?t?.data?.handle:null
|
|
7
|
+
if(!n)return null
|
|
8
|
+
const s=[]
|
|
9
|
+
try{for(const t of e.setup){const e=await a("/api/experiments/exec",{handle:n,command:t,timeoutMs:3e5,why:"trial of a check before it is registered (setup)"},32e4).catch((()=>null)),o=e?.data??{}
|
|
10
|
+
if(!e?.success||0!==o.exit)return s.push({name:`setup: ${t.slice(0,60)}`,command:t,exit:"number"==typeof o.exit?o.exit:-1,output:`${o.stdout??""}\n${o.stderr??e?.error??""}`}),s}for(const t of e.commands){const e=1e3*Math.min(Math.max(t.timeout,10),300),o=await a("/api/experiments/exec",{handle:n,command:t.command,timeoutMs:e,why:"trial of a check before it is registered"},e+2e4).catch((()=>null)),i=o?.data??{}
|
|
11
|
+
s.push({name:t.name,command:t.command,exit:"number"==typeof i.exit?i.exit:-1,output:`${i.stdout??""}\n${i.stderr??(o?.success?"":o?.error??"no result")}`})}}finally{await a("/api/experiments/stop",{handle:n},3e4).catch((()=>null))}return s}}}
|
package/dist/674.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict"
|
|
2
|
+
exports.id=674,exports.ids=[674],exports.modules={75674:(e,exports,t)=>{async function o(e,t){if(t){if(!n||Date.now()-n.at>i)try{const t=await e.apiClient.get(`/api/projects/${e.projectId}/session-request-associations?activeOnly=true&limit=500`),o=t?.data??t??[],r=new Map
|
|
3
|
+
for(const e of o)e?.opencodeSessionId&&e?.requestLocalId&&r.set(e.opencodeSessionId,e.requestLocalId)
|
|
4
|
+
n={at:Date.now(),bySession:r}}catch(t){e.logger.debug?.("MCP receipt: could not read associations",{error:(0,r.getErrorMessage)(t)}),n=n??{at:Date.now(),bySession:new Map}}return n.bySession.get(t)}}exports.requestForSession=o,exports.openMcpReceipt=async function(e,t){const n=await o(e,t.sessionId??""),i=t.target?` (${t.target})`:"",c=`${t.tool} on the "${t.connection}" MCP server${i}`,d=t.allowed?`Called ${c}`:`Did not run ${c}: ${t.reason}`,l={connection:t.connection,tool:t.tool,target:t.target??null,gate:t.verdict,status:t.allowed?"started":"refused",sessionId:t.sessionId??null,callId:t.callId??null,startedAt:(new Date).toISOString()}
|
|
5
|
+
try{const o=await e.apiClient.post(`/api/projects/${e.projectId}/tool-records`,{...n?{requestId:n}:{},type:"mcp-call",...t.sessionId?{cliOrigin:{providerId:"opencode",sessionId:t.sessionId,createdAt:(new Date).toISOString()}}:{},metadata:l,note:d}),r=o?.data?.id??o?.id
|
|
6
|
+
t.allowed&&t.callId&&r&&(s.set(t.callId,{recordId:String(r),startedAt:Date.now(),metadata:l}),function(){if(s.size<=a)return
|
|
7
|
+
const e=[...s.entries()].sort(((e,t)=>e[1].startedAt-t[1].startedAt))
|
|
8
|
+
for(const[t]of e){if(s.size<=a)break
|
|
9
|
+
s.delete(t)}}())}catch(o){e.logger.error("MCP receipt could not be written",{connection:t.connection,tool:t.tool,error:(0,r.getErrorMessage)(o)})}},exports.recordIdForCall=function(e){if(e)return s.get(e)?.recordId},exports.closeMcpReceipt=async function(e,t){if(!t.callId)return
|
|
10
|
+
let o=s.get(t.callId)
|
|
11
|
+
if(o||(await new Promise((e=>setTimeout(e,250))),o=s.get(t.callId)),o){s.delete(t.callId)
|
|
12
|
+
try{await e.apiClient.patch(`/api/projects/${e.projectId}/tool-records/${o.recordId}`,{metadata:{...o.metadata,status:t.ok?"completed":"failed",durationMs:Date.now()-o.startedAt,finishedAt:(new Date).toISOString(),...t.outputPreview?{outputPreview:t.outputPreview.slice(0,500)}:{},...t.error?{error:String(t.error).slice(0,500)}:{}}})}catch(o){e.logger.warn("MCP receipt could not be closed",{callId:t.callId,error:(0,r.getErrorMessage)(o)})}}}
|
|
13
|
+
const r=t(21319),s=new Map,a=500
|
|
14
|
+
let n=null
|
|
15
|
+
const i=3e4}}
|
package/dist/729.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict"
|
|
2
|
+
exports.id=729,exports.ids=[729],exports.modules={2457:function(e,exports,t){var r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
3
|
+
Object.defineProperty(exports,"__esModule",{value:!0}),exports.ProjectSynchronizer=void 0
|
|
4
|
+
const i=r(t(16928)),o=t(65696),s=t(21319)
|
|
5
|
+
exports.ProjectSynchronizer=class{constructor(e,t,r,i,o={}){this.logger=e.child({component:"project-synchronizer"}),this.registry=t,this.remoteApi=r,this.fileSystem=i,this.options={createRemoteProjects:o.createRemoteProjects??!0,maxRetryAttempts:o.maxRetryAttempts??3,retryDelayMs:o.retryDelayMs??1e3},this.logger.info("ProjectSynchronizer initialized",{options:this.options})}async ensureProjectExists(e){const t=Math.random().toString(36).substring(2,8)
|
|
6
|
+
this.logger.info("\u{1f4de} SYNC-TRACE: ensureProjectExists called",{callId:t,projectId:e,stackTrace:(new Error).stack?.split("\n").slice(1,4).map((e=>e.trim())).join(" -> ")||"unknown"})
|
|
7
|
+
try{if(!this.remoteApi.isOnline())return this.logger.info("\u{1f4de} SYNC-TRACE: System offline, returning original ID",{callId:t,projectId:e}),e
|
|
8
|
+
if(this.logger.info("\u{1f4de} SYNC-TRACE: System online, proceeding",{callId:t,projectId:e}),this.registry.isVerified(e))return this.logger.info("\u{1f4de} SYNC-TRACE: Cache hit - already verified",{callId:t,projectId:e}),e
|
|
9
|
+
this.logger.info("\u{1f4de} SYNC-TRACE: Cache miss - checking remote server",{callId:t,projectId:e})
|
|
10
|
+
const r=await this.remoteApi.fetchProject(e)
|
|
11
|
+
if(this.logger.info("\u{1f4de} SYNC-TRACE: Remote fetch completed",{callId:t,projectId:e,found:!!r,remoteProject:r?{id:r.id,name:r.name}:null}),r)return this.logger.info("Project exists on remote server",{projectId:e}),this.registry.register(r),r.id
|
|
12
|
+
if(this.logger.info("\u{1f4de} SYNC-TRACE: Project not found, will create",{callId:t,projectId:e}),!this.options.createRemoteProjects)throw this.logger.info("Project does not exist on remote and creation is disabled",{projectId:e}),new Error(`Project ${e} does not exist on remote server and creation is disabled`)
|
|
13
|
+
{this.logger.info("\u{1f4de} SYNC-TRACE: Creating project on remote server",{callId:t,projectId:e})
|
|
14
|
+
let r={id:e,name:"Remote Synchronized Project",description:"Automatically created during synchronization",status:"active"}
|
|
15
|
+
const i=this.registry.getProject(e)
|
|
16
|
+
i&&(this.logger.info("\u{1f4de} SYNC-TRACE: Using local project data",{callId:t,projectId:e,projectName:i.name}),r={...i})
|
|
17
|
+
try{this.logger.info("\u{1f4de} SYNC-TRACE: Calling remoteApi.createProject",{callId:t,projectId:e,projectName:r.name})
|
|
18
|
+
const i=await this.remoteApi.createProject(r)
|
|
19
|
+
return this.logger.info("Create project API call succeeded",{returnedId:i?.id,returnedName:i?.name}),this.registry.register(i),this.logger.info("Successfully created project on remote server",{projectId:i.id,projectName:i.name}),i.id}catch(t){if(t&&"object"==typeof t&&"status"in t&&409===t.status)return this.logger.info("Project already exists on remote (409 conflict)",{projectId:e}),this.registry.markVerified(e),e
|
|
20
|
+
throw this.logger.error("Failed to create project on remote server",{projectId:e,error:t instanceof Error?t.stack:String(t),status:t?.status,message:t instanceof Error?t.message:String(t)}),t}}}catch(t){throw this.logger.error("Error verifying project existence",{projectId:e,error:t instanceof Error?t.stack:String(t),message:(0,s.getErrorMessage)(t)}),t}}async createProject(e,t){try{if(e.id){if(!o.ProjectIDFactory.isValid(e.id)){this.logger.warn("Invalid project ID format, generating new ID",{originalId:e.id})
|
|
21
|
+
const t=o.ProjectIDFactory.create().toString()
|
|
22
|
+
e.id=t}}else{const t=o.ProjectIDFactory.create().toString()
|
|
23
|
+
e.id=t,this.logger.info("Generated new project ID",{projectId:t})}const r=(new Date).toISOString(),i={id:e.id,name:e.name||"Unnamed Project",description:e.description||"No description provided",status:e.status||"active",createdAt:e.createdAt||r,updatedAt:e.updatedAt||r,metadata:e.metadata||{}}
|
|
24
|
+
if(this.registry.register(i),t&&await this.fileSystem.writeProjectFile(i,t),this.remoteApi.isOnline())try{this.logger.info("Syncing new project to remote server",{projectId:i.id}),await this.ensureProjectExists(i.id)}catch(e){this.logger.warn("Failed to sync new project to remote, will retry later",{projectId:i.id,error:e instanceof Error?e.message:String(e)})}return i}catch(t){throw this.logger.error("Failed to create project",{projectData:e,error:t instanceof Error?t.stack:String(t)}),t}}async syncAllProjects(e){try{if(!this.remoteApi.isOnline())return void this.logger.info("Skipping project synchronization - system is offline")
|
|
25
|
+
this.logger.info("Starting project synchronization from directory",{basePath:e})
|
|
26
|
+
const t=await this.fileSystem.readProjectFile(e)
|
|
27
|
+
if(!t||!t.id)return void this.logger.info("No valid local project found, skipping synchronization",{basePath:e})
|
|
28
|
+
this.logger.info("Found local project",{projectId:t.id,projectName:t.name}),this.logger.info("Registering project in registry before synchronization",{projectId:t.id,projectName:t.name}),this.registry.register(t),this.logger.info("Ensuring project exists on remote server",{projectId:t.id}),await this.ensureProjectExists(t.id)?(this.logger.info("Project exists on remote, checking metadata sync",{projectId:t.id,projectName:t.name,basePath:e}),t.metadata&&Object.keys(t.metadata).length>0&&(this.logger.info("Syncing project metadata to remote (async)",{projectId:t.id,metadataKeys:Object.keys(t.metadata)}),this.remoteApi.updateProject(t.id,{metadata:t.metadata}).then((()=>{this.logger.info("Project metadata synced successfully",{projectId:t.id})})).catch((e=>{this.logger.warn("Failed to sync project metadata",{projectId:t.id,error:e instanceof Error?e.message:String(e)})}))),this.logger.info("Successfully synchronized project",{projectId:t.id,projectName:t.name,basePath:e})):this.logger.warn("Failed to verify/create project on remote server",{projectId:t.id,basePath:e})}catch(t){this.logger.error("Error during project synchronization",{basePath:e,error:t instanceof Error?t.stack:String(t)})}}async loadLocalProject(e){try{this.logger.info("Loading local project from directory",{basePath:e})
|
|
29
|
+
const t=await this.fileSystem.readProjectFile(e)
|
|
30
|
+
return t&&t.id?(this.registry.register(t),this.logger.info("Successfully loaded local project",{projectId:t.id,basePath:e}),t):(this.logger.info("No valid local project found",{basePath:e}),null)}catch(t){return this.logger.error("Error loading local project",{basePath:e,error:t instanceof Error?t.stack:String(t)}),null}}async getOrCreateProject(e,t={}){this.logger.info("\u{1f680} getOrCreateProject called",{basePath:e,hasProjectData:!!Object.keys(t).length,projectData:Object.keys(t)})
|
|
31
|
+
try{this.logger.info("Attempting to load existing local project",{basePath:e})
|
|
32
|
+
const r=await this.loadLocalProject(e)
|
|
33
|
+
if(r){this.logger.info("Found existing local project",{projectId:r.id,projectName:r.name,basePath:e})
|
|
34
|
+
const t=this.remoteApi.isOnline()
|
|
35
|
+
if(this.logger.info("Checking online status for verification",{isOnline:t,projectId:r.id}),!t)return this.logger.info("Using existing project (offline, skipping server verification)",{projectId:r.id,basePath:e}),r
|
|
36
|
+
{this.logger.info("System is online - starting project verification",{projectId:r.id,basePath:e})
|
|
37
|
+
const t=await this.ensureProjectExists(r.id)
|
|
38
|
+
if(this.logger.info("Project verification completed",{projectId:r.id,exists:t,basePath:e}),t)return this.logger.info("Using existing project (verified on server)",{projectId:r.id,basePath:e}),r
|
|
39
|
+
this.logger.warn("Local project not found on server, creating new project",{invalidProjectId:r.id,basePath:e})}}this.logger.info("No existing project found, creating new one",{basePath:e}),t.name||(t.name=i.default.basename(e))
|
|
40
|
+
const o=await this.createProject(t,e)
|
|
41
|
+
return this.logger.info("Created new project for directory",{projectId:o.id,basePath:e}),o}catch(t){this.logger.error("Error getting or creating project",{basePath:e,error:t instanceof Error?t.stack:String(t)})
|
|
42
|
+
const r=await this.createProject({name:`Fallback Project for ${i.default.basename(e)}`,description:"Created as fallback due to error"},e)
|
|
43
|
+
return this.logger.info("Created fallback project due to error",{projectId:r.id,basePath:e}),r}}async verifyAndFixProjectName(e){try{if(!this.remoteApi.isOnline())return this.logger.info("Skipping project name verification - system is offline"),!0
|
|
44
|
+
if(this.registry.isVerifiedWithName&&this.registry.isVerifiedWithName(e.id,e.name))return this.logger.info("Project name already verified, skipping verification",{projectId:e.id,projectName:e.name}),!0
|
|
45
|
+
const t=await this.remoteApi.fetchProject(e.id)
|
|
46
|
+
if(!t)return this.logger.warn("Cannot verify project name - project not found on remote",{projectId:e.id}),!1
|
|
47
|
+
if(t.name===e.name)return this.logger.info("Project name matches remote, marking as verified",{projectId:e.id,projectName:e.name}),this.registry.markVerifiedWithName&&this.registry.markVerifiedWithName(e.id,e.name),!0
|
|
48
|
+
this.logger.info("Project name mismatch, updating remote name",{projectId:e.id,localName:e.name,remoteName:t.name})
|
|
49
|
+
const r=this.options.maxRetryAttempts,i=this.options.retryDelayMs
|
|
50
|
+
for(let t=1;t<=r;t++)try{return await this.remoteApi.updateProject(e.id,{name:e.name}),this.logger.info("Project name updated successfully",{projectId:e.id,newName:e.name}),this.registry.markVerifiedWithName&&this.registry.markVerifiedWithName(e.id,e.name),!0}catch(o){if(!(t<r))throw o
|
|
51
|
+
this.logger.warn(`Failed to update project name, retrying (${t}/${r})`,{projectId:e.id,error:o instanceof Error?o.message:String(o)}),await new Promise((e=>setTimeout(e,i)))}return!1}catch(t){return this.logger.error("Failed to verify/fix project name",{projectId:e.id,projectName:e.name,error:t instanceof Error?t.stack:String(t)}),!1}}async syncProject(e,t){try{if(!this.remoteApi.isOnline())return this.logger.info("Skipping project synchronization - system is offline",{projectId:e}),!1
|
|
52
|
+
let r=null
|
|
53
|
+
if(t&&(r=await this.loadLocalProject(t),r&&r.id!==e&&(this.logger.warn("Project ID mismatch between request and loaded project",{requestedId:e,loadedId:r.id}),r=null)),!r){const t=this.registry.getProject(e)
|
|
54
|
+
t&&(r=t)}if(!r)return this.logger.info("Project not found locally, attempting to fetch from remote",{projectId:e}),r=await this.remoteApi.fetchProject(e),r?(this.registry.register(r),t&&await this.fileSystem.writeProjectFile(r,t),!0):(this.logger.warn("Project not found locally or remotely",{projectId:e}),!1)
|
|
55
|
+
if(!await this.ensureProjectExists(e))return!1
|
|
56
|
+
if(await this.verifyAndFixProjectName(r)||this.logger.warn("Failed to verify/fix project name",{projectId:r.id,projectName:r.name}),r.metadata&&Object.keys(r.metadata).length>0)try{this.logger.info("Syncing project metadata to remote",{projectId:r.id,metadataKeys:Object.keys(r.metadata)}),await this.remoteApi.updateProject(r.id,{metadata:r.metadata}),this.logger.info("Project metadata synced successfully",{projectId:r.id})}catch(e){this.logger.warn("Failed to sync project metadata",{projectId:r.id,error:e instanceof Error?e.message:String(e)})}return this.logger.info("Project synchronization completed successfully",{projectId:e}),!0}catch(r){return this.logger.error("Error synchronizing project",{projectId:e,basePath:t,error:r instanceof Error?r.stack:String(r)}),!1}}}},59258:function(e,exports,t){var r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
57
|
+
Object.defineProperty(exports,"__esModule",{value:!0}),exports.ProjectRegistry=void 0
|
|
58
|
+
const i=r(t(79896)),o=r(t(16928))
|
|
59
|
+
exports.ProjectRegistry=class{constructor(e,t={}){this.projects=new Map,this.verifiedIds=new Set,this.verifiedNames=new Map,this.logger=e.child({component:"project-registry"}),this.options={persistToDisk:t.persistToDisk??!1,storageDirectory:t.storageDirectory??"./temp-projects"},this.options.persistToDisk?this.logger.warn("Project persistence to disk is enabled - this may be legacy functionality"):this.logger.info("Project persistence to disk is disabled - this is the recommended configuration"),this.logger.info("ProjectRegistry initialized",{options:this.options,persistenceEnabled:this.options.persistToDisk})}register(e,t={}){if(!e.id)return void this.logger.warn("Attempted to register project without ID")
|
|
60
|
+
const r=t.markVerified??!1,i=t.saveToFile??this.options.persistToDisk
|
|
61
|
+
this.projects.set(e.id,e),r&&(this.verifiedIds.add(e.id),e.name&&this.verifiedNames.set(e.id,e.name)),this.logger.info("Registered project",{projectId:e.id,projectName:e.name,markVerified:r,saveToFile:i}),i&&(this.options.persistToDisk?this.saveProjectToFile(e):this.logger.debug("Skipping project file persistence (disabled in configuration)",{projectId:e.id}))}hasProject(e){return this.projects.has(e)}markVerified(e){this.verifiedIds.add(e),this.logger.info("Marked project as verified",{projectId:e})}isVerified(e){return this.verifiedIds.has(e)}markVerifiedWithName(e,t){this.verifiedIds.add(e),this.verifiedNames.set(e,t),this.logger.info("Marked project as verified with name",{projectId:e,projectName:t})}isVerifiedWithName(e,t){return this.verifiedIds.has(e)&&this.verifiedNames.get(e)===t}getVerifiedName(e){return this.verifiedNames.get(e)}getProject(e){return this.projects.get(e)}getAllProjects(){return Array.from(this.projects.values())}clearVerificationCache(e){e?(this.verifiedIds.delete(e),this.verifiedNames.delete(e),this.logger.info("Cleared verification for project",{projectId:e})):(this.verifiedIds.clear(),this.verifiedNames.clear(),this.logger.info("Cleared all project verifications"))}saveProjectToFile(e){try{if(!i.default.existsSync(this.options.storageDirectory))try{this.logger.info("Creating storage directory",{directory:this.options.storageDirectory,absolutePath:o.default.resolve(this.options.storageDirectory)}),i.default.mkdirSync(this.options.storageDirectory,{recursive:!0}),this.logger.info("Storage directory created successfully",{directory:this.options.storageDirectory,absolutePath:o.default.resolve(this.options.storageDirectory)})}catch(e){return void this.logger.error("Failed to create storage directory",{directory:this.options.storageDirectory,absolutePath:o.default.resolve(this.options.storageDirectory),error:e instanceof Error?e.stack:String(e)})}const t=o.default.join(this.options.storageDirectory,`project-${e.id}.json`)
|
|
62
|
+
i.default.writeFileSync(t,JSON.stringify(e,null,2),"utf8"),this.logger.info("Saved project to file",{projectId:e.id,filePath:t})}catch(t){this.logger.error("Failed to save project to file",{projectId:e.id,error:t instanceof Error?t.stack:String(t)})}}async loadFromDisk(){try{if(!i.default.existsSync(this.options.storageDirectory))try{return this.logger.info("Storage directory does not exist, creating it",{directory:this.options.storageDirectory,absolutePath:o.default.resolve(this.options.storageDirectory)}),i.default.mkdirSync(this.options.storageDirectory,{recursive:!0}),void this.logger.info("Storage directory created successfully",{directory:this.options.storageDirectory,absolutePath:o.default.resolve(this.options.storageDirectory)})}catch(e){return void this.logger.error("Failed to create storage directory",{directory:this.options.storageDirectory,absolutePath:o.default.resolve(this.options.storageDirectory),error:e instanceof Error?e.stack:String(e)})}const e=i.default.readdirSync(this.options.storageDirectory).filter((e=>e.startsWith("project-")&&e.endsWith(".json")))
|
|
63
|
+
this.logger.info("Loading projects from disk",{directory:this.options.storageDirectory,fileCount:e.length})
|
|
64
|
+
let t=0
|
|
65
|
+
for(const r of e)try{const e=o.default.join(this.options.storageDirectory,r),s=i.default.readFileSync(e,"utf8"),a=JSON.parse(s)
|
|
66
|
+
if(!a.id){this.logger.warn("Skipping project file with missing ID",{filePath:e})
|
|
67
|
+
continue}this.register(a,{saveToFile:!1}),t++}catch(e){this.logger.error("Error loading project file",{file:r,error:e instanceof Error?e.stack:String(e)})}this.logger.info("Finished loading projects from disk",{totalLoaded:t,totalFiles:e.length})}catch(e){this.logger.error("Failed to load projects from disk",{error:e instanceof Error?e.stack:String(e)})}}setStorageDirectory(e){this.options.storageDirectory=e,this.logger.info("Set storage directory",{directory:e})}setPersistToDisk(e){this.options.persistToDisk=e,this.logger.info("Set persist to disk",{persistToDisk:e})}}},65696:function(e,exports,t){var r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
68
|
+
Object.defineProperty(exports,"__esModule",{value:!0}),exports.ProjectIDBackwardCompat=exports.ProjectIDFactory=exports.ProjectID=void 0
|
|
69
|
+
const i=r(t(76982))
|
|
70
|
+
class o{static create(){return exports.ProjectIDFactory.create()}static fromString(e){return exports.ProjectIDFactory.fromString(e)}static isValid(e){return exports.ProjectIDFactory.isValid(e)}constructor(e){this.id=e}toString(){return this.id}equals(e){return this.id===e.toString()}isStandardFormat(){return this.id.includes("_")&&this.id.startsWith("prj_")}}exports.ProjectID=o,exports.ProjectIDFactory={create(){const e=Date.now().toString().substring(5),t=i.default.randomBytes(4).toString("hex")
|
|
71
|
+
return o.fromString(`prj_${e}_${t}`)},fromString(e){return this.isValid(e)?new o(e):null},isValid(e){if(!e||"string"!=typeof e||e.length<5||!e.startsWith("prj"))return!1
|
|
72
|
+
if(e.includes("_")){const t=e.split("_")
|
|
73
|
+
return t.length>=3&&"prj"===t[0]}return!1}},exports.ProjectIDBackwardCompat={create:exports.ProjectIDFactory.create,fromString:exports.ProjectIDFactory.fromString,isValid:exports.ProjectIDFactory.isValid},Object.assign(o,exports.ProjectIDBackwardCompat)},74981:function(e,exports,t){var r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
74
|
+
Object.defineProperty(exports,"__esModule",{value:!0}),exports.DefaultProjectFileSystem=void 0
|
|
75
|
+
const i=r(t(79896)),o=r(t(16928)),s=t(21992)
|
|
76
|
+
exports.DefaultProjectFileSystem=class{constructor(e){this.logger=e.child({component:"project-file-system"})}async readProjectFile(e){try{const t=o.default.join(e,"project.json"),r=o.default.join(e,s.ALCHEMY_DIR_NAME,"project.json")
|
|
77
|
+
let a=r
|
|
78
|
+
if(i.default.existsSync(t))a=t,this.logger.info("Found project file in base directory",{path:a})
|
|
79
|
+
else{if(!i.default.existsSync(r))return this.logger.info("Project file does not exist in either location",{directPath:t,nestedPath:r}),null
|
|
80
|
+
this.logger.info("Found project file in alchemy_lab subdirectory",{path:a})}const n=await i.default.promises.readFile(a,"utf8"),c=JSON.parse(n)
|
|
81
|
+
return c.id?(this.logger.info("Read project file successfully",{projectId:c.id,path:a}),c):(this.logger.warn("Project file has no ID",{path:a}),null)}catch(t){return this.logger.error("Failed to read project file",{basePath:e,error:t instanceof Error?t.stack:String(t)}),null}}async writeProjectFile(e,t){try{const r=o.default.join(t,"project.json"),a=o.default.join(t,s.ALCHEMY_DIR_NAME,"project.json")
|
|
82
|
+
let n=r
|
|
83
|
+
!i.default.existsSync(r)&&i.default.existsSync(a)?(n=a,this.logger.info("Using existing nested path for project file",{path:n})):this.logger.info("Using direct path for project file",{path:n}),await this.ensureDirectoryExists(o.default.dirname(n)),await i.default.promises.writeFile(n,JSON.stringify(e,null,2),"utf8"),this.logger.info("Wrote project file successfully",{projectId:e.id,path:n})}catch(r){throw this.logger.error("Failed to write project file",{projectId:e.id,basePath:t,error:r instanceof Error?r.stack:String(r)}),r}}async ensureDirectoryExists(e){try{i.default.existsSync(e)||(await i.default.promises.mkdir(e,{recursive:!0}),this.logger.info("Created directory",{path:e}))}catch(t){throw this.logger.error("Failed to create directory",{path:e,error:t instanceof Error?t.stack:String(t)}),t}}}},89729:(e,exports,t)=>{exports.ProjectSynchronizer=exports.ProjectFileSystem=exports.ProjectRegistry=void 0
|
|
84
|
+
var r=t(59258)
|
|
85
|
+
Object.defineProperty(exports,"ProjectRegistry",{enumerable:!0,get:function(){return r.ProjectRegistry}})
|
|
86
|
+
var i=t(74981)
|
|
87
|
+
Object.defineProperty(exports,"ProjectFileSystem",{enumerable:!0,get:function(){return i.DefaultProjectFileSystem}})
|
|
88
|
+
var o=t(2457)
|
|
89
|
+
Object.defineProperty(exports,"ProjectSynchronizer",{enumerable:!0,get:function(){return o.ProjectSynchronizer}}),t(45936)}}
|
package/dist/796.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict"
|
|
2
|
+
exports.id=796,exports.ids=[796],exports.modules={68796:(e,exports,t)=>{async function n(e){if(p&&Date.now()-p.at<d)return p.servers
|
|
3
|
+
try{const t=await e.apiClient.get(`/api/projects/${e.projectId}/mcp-servers`),n=t?.data??t??[]
|
|
4
|
+
if(Array.isArray(n))return p={at:Date.now(),servers:n},n}catch(t){e.logger.warn("MCP gate: could not read the registry",{error:(0,c.getErrorMessage)(t)})}return p?.servers??[]}function r(e){return e.filter((e=>e.enabled)).map((e=>e.name))}function o(e,t){const n=[...t].sort(((e,t)=>t.length-e.length))
|
|
5
|
+
for(const t of n){const n=`${t}_`
|
|
6
|
+
if(e.startsWith(n)&&e.length>n.length)return{server:t,tool:e.slice(n.length)}}return null}function s(e,t=200){if(!e||"object"!=typeof e||Array.isArray(e))return""
|
|
7
|
+
const n=Object.entries(e)
|
|
8
|
+
if(0===n.length)return""
|
|
9
|
+
const r=e=>{const t=u.indexOf(e)
|
|
10
|
+
return-1===t?u.length:t}
|
|
11
|
+
n.sort(((e,t)=>r(e[0])-r(t[0])))
|
|
12
|
+
const o=[]
|
|
13
|
+
for(const[e,t]of n){if(o.length>=4)break
|
|
14
|
+
let n
|
|
15
|
+
if("string"==typeof t)n=t.length>80?`${t.length} characters`:t
|
|
16
|
+
else if("number"==typeof t||"boolean"==typeof t)n=String(t)
|
|
17
|
+
else if(Array.isArray(t)){const e=t.filter((e=>"string"==typeof e))
|
|
18
|
+
n=e.length===t.length&&e.join(", ").length<=80?e.join(", "):`${t.length} items`}else{if(null==t)continue
|
|
19
|
+
n="an object"}o.push(`${e}: ${n}`)}const s=o.join(", ")
|
|
20
|
+
return s.length>t?`${s.slice(0,t-1)}\u2026`:s}function i(e,t,n,r){const o=[`Let an agent run ${t} on "${e}", an MCP server this project is connected to?`],i=function(e){if(!e||"object"!=typeof e||Array.isArray(e))return""
|
|
21
|
+
const t=s(e,400).split(", ").map((e=>{const t=e.indexOf(": ")
|
|
22
|
+
return-1===t?null:[e.slice(0,t),e.slice(t+2)]})).filter(Boolean)
|
|
23
|
+
if(0===t.length)return""
|
|
24
|
+
const n=Math.max(...t.map((([e])=>e.length)))
|
|
25
|
+
return t.map((([e,t])=>` ${e.padEnd(n)} ${t}`)).join("\n")}(r)
|
|
26
|
+
i&&o.push(i)
|
|
27
|
+
const a=n?`This runs inside "${e}", not in this project. The server's own note on ${t}: ${function(e,t=220){const n=e.trim().replace(/\s+/g," ")
|
|
28
|
+
if(n.length<=t)return n
|
|
29
|
+
const r=n.slice(0,t),o=Math.max(r.lastIndexOf(". "),r.lastIndexOf("! "),r.lastIndexOf("? "))
|
|
30
|
+
if(o>.4*t)return r.slice(0,o+1)
|
|
31
|
+
const s=r.lastIndexOf(" ")
|
|
32
|
+
return`${r.slice(0,s>0?s:t)}\u2026`}(n)}`:`This runs inside "${e}", not in this project, and the server does not say what ${t} does.`
|
|
33
|
+
return o.push(a),o.join("\n\n")}exports.invalidateMcpRegistry=function(){p=null},exports.getRegisteredMcpServers=n,exports.gatedNamespaces=r,exports.splitToolKey=o,exports.summariseArgs=s,exports.gateMcpCall=async function(e,c){const d=await n(e),p=o(c.toolName,r(d))
|
|
34
|
+
if(!p)return{allow:!0,verdict:"not-external",reason:"Not a registered MCP connection tool"}
|
|
35
|
+
const u=d.find((e=>e.name===p.server))
|
|
36
|
+
if(!u||!u.enabled)return{allow:!1,verdict:"unknown-connection",reason:`the MCP server "${p.server}" is not enabled for this project`}
|
|
37
|
+
if(function(e,t){const n=e?.find((e=>e.name===t))
|
|
38
|
+
return!0===n?.readOnly}(u.toolManifest,p.tool))return{allow:!0,verdict:"read-only",reason:`the ${p.server} MCP server marks ${p.tool} read-only`}
|
|
39
|
+
const{requestForSession:f}=await t.e(674).then(t.bind(t,75674)),h=c.sessionId?await f(e,c.sessionId):void 0,g=h??c.sessionId,v=g?`mcp:${p.server}:${g}`:`mcp:${p.server}`,y=s(c.args),$=y?`MCP ${p.server} \xb7 ${p.tool} (${y})`:`MCP ${p.server} \xb7 ${p.tool}`,m=u.toolManifest?.find((e=>e.name===p.tool))?.description
|
|
40
|
+
if((0,a.isSessionAllowed)(v))return{allow:!0,verdict:"session-allowed",reason:h?`already allowed for ${h}`:"already allowed for this run"}
|
|
41
|
+
const{id:w,promise:b,created:j}=(0,a.createApproval)(v,$)
|
|
42
|
+
w&&j&&c.sessionId&&(0,l.bridgeApprovalToNotification)(e.apiClient,e.projectId,{approvalId:w,approvalKey:v,sessionId:c.sessionId,command:$,question:i(p.server,p.tool,m,c.args),approveOption:{description:`Run it once, in "${p.server}"`},denyOption:{description:"Do not run it; the agent is told it was declined"},allowSessionOption:h?{label:`Allow for the rest of ${h}`,description:`Run it, and stop asking about "${p.server}" for the rest of this request`}:{label:"Allow while this agent keeps working",description:`Run it, and stop asking about "${p.server}" until this agent finishes`}})
|
|
43
|
+
const M=await b
|
|
44
|
+
return"deny"===M?{allow:!1,verdict:"denied",reason:"a person declined it"}:"timeout"===M?{allow:!1,verdict:"timeout",reason:"nobody answered the approval in time"}:{allow:!0,verdict:"approved",reason:"a person approved it"}}
|
|
45
|
+
const a=t(70799),l=t(36993),c=t(21319),d=3e4
|
|
46
|
+
let p=null
|
|
47
|
+
const u=["path","file","filename","file_path","filePath","paths","url","uri","endpoint","repo","repository","branch","id","key","name","title","query","q","command","sql","table"]}}
|