alchemylab 1.3.4 → 1.3.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/http-server.js +11 -6
- package/dist/index.js +11 -6
- package/dist/mcp-direct.js +11 -6
- package/package.json +1 -1
package/dist/http-server.js
CHANGED
|
@@ -839,8 +839,10 @@ e&&s&&await o.workspaceManager.ensureReadonlyBranchIfNeeded(e,n,s,q)}catch(e){k.
|
|
|
839
839
|
if(e?.sessionId&&t){const r=t.match(/^requests\/(.+)$/),n="1"===process.env.ALCHEMY_ALLOW_PARALLEL
|
|
840
840
|
if(r&&!n){const t=r[1]
|
|
841
841
|
E=!0
|
|
842
|
-
try{const{sessionTag:r}=(0,g.getGlobalClientInfo)(),n=s.getSessionTagMappingClient(),o=s.getRequestClient()
|
|
843
|
-
|
|
842
|
+
try{const{sessionTag:r}=(0,g.getGlobalClientInfo)(),n=s.getSessionTagMappingClient(),o=s.getRequestClient()
|
|
843
|
+
let i=!1,a=null
|
|
844
|
+
const c=n?n.getMappingByOpencodeSessionId(e.sessionId).then((t=>{t?((0,g.setSessionTag)(t.sessionTag),a=t.sessionTag,k.info("Recovered session tag from mapping",{opencodeSessionId:e.sessionId,sessionTag:t.sessionTag})):(n.createOrUpdateMapping(r,e.sessionId).catch((()=>{})),k.info("Registered session tag mapping",{opencodeSessionId:e.sessionId,sessionTag:r}))}),(e=>k.debug("Mapping lookup failed",{error:(0,d.getErrorMessage)(e)}))):Promise.resolve(),l=o.lockRequest?o.lockRequest(t,r).then((e=>{i=e.locked,e.locked?k.info("Acquired request lock",{requestId:t,sessionTag:r}):k.warn("Failed to acquire request lock",{requestId:t,sessionTag:r})}),(e=>k.warn("Lock acquisition failed",{error:(0,d.getErrorMessage)(e)}))):Promise.resolve()
|
|
845
|
+
if(await Promise.all([c,l]),!i&&a&&a!==r&&o.lockRequest)try{(await o.lockRequest(t,a)).locked?k.info("Acquired lock with recovered session tag after MCP restart",{requestId:t,sessionTag:a}):k.warn("Lock still held by a different session after recovered-tag retry",{requestId:t,recoveredTag:a})}catch(e){k.warn("Lock retry with recovered tag failed",{error:(0,d.getErrorMessage)(e)})}}catch(e){k.warn("Error in session tag mapping / lock acquisition",{error:(0,d.getErrorMessage)(e)})}}}}o&&(o.currentSessionId=q||"__unknown__")
|
|
844
846
|
const S=`${Date.now()}-${Math.random().toString(36).slice(2,10)}`,T=e=>{const{getActionServerBaseUrl:r}=t(9414)
|
|
845
847
|
fetch(r()+"/api/mcp/tool-call-event",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:e,callId:S}),signal:AbortSignal.timeout(500)}).catch((()=>{}))}
|
|
846
848
|
let P
|
|
@@ -4507,10 +4509,13 @@ if(n.workspaceManager){o.debug("Using WorkspaceManager for request context switc
|
|
|
4507
4509
|
try{if("multi-agent"===n.workspaceManager.getCurrentContext(n.currentSessionId).mode)if(o.debug("Multi-agent mode: checking request lock before auto-switch",{requestId:r}),n.apiClient)try{const e=n.apiClient.getRequestClient(),{sessionTag:t}=(0,h.getGlobalClientInfo)()
|
|
4508
4510
|
c=Date.now()
|
|
4509
4511
|
const s=await e.getRequestLockStatus(r)
|
|
4510
|
-
|
|
4511
|
-
|
|
4512
|
-
if(
|
|
4513
|
-
|
|
4512
|
+
Date.now()
|
|
4513
|
+
const i=10,l=s.lockedAt?Date.now()-new Date(s.lockedAt).getTime():0,d=l>6e4*i
|
|
4514
|
+
if(s.isLocked&&s.lockedBySessionTag!==t&&!d){o.warn("Auto-switch blocked by request lock",{requestId:r,lockedByAgent:s.lockedBySessionTag,currentAgent:t,lockedAt:s.lockedAt,lockAgeMs:l})
|
|
4515
|
+
const e=Math.max(0,Math.ceil(i-l/6e4))
|
|
4516
|
+
let a=`Request ${r} is currently locked by another agent (${s.lockedBySessionTag}).\n\nLocked since: ${s.lockedAt||"unknown"}\n\nIn multi-agent mode, only one agent can work on a request at a time. If the holder is dead/abandoned, the lock will become takeover-eligible in ~${e} minute${1===e?"":"s"} \u2014 retry your operation then and it will succeed automatically. If the holder is genuinely active, wait for them to finish.`
|
|
4517
|
+
if(n.lockOverrideManager&&n.configManager)try{const e=await n.configManager.getEffectiveConfig(n.mainBasePath)
|
|
4518
|
+
e.lockOverride.enabled&&(a+=`\n\nIf you cannot wait, switch_to_branch with password: \`${n.lockOverrideManager.generatePassword(r,e.lockOverride.passwordValidityMinutes)}\` (valid for ${e.lockOverride.passwordValidityMinutes} minutes) \u2014 ONLY if you are certain the holder is dead.`)}catch(e){o.warn("Failed to check lock override config",{error:e})}throw new p.RequestLockError(a,r,s.lockedBySessionTag,s.lockedAt)}if(d&&s.lockedBySessionTag!==t&&o.info("Stale lock detected \u2014 DAO will take it over on next acquire",{requestId:r,staleBySessionTag:s.lockedBySessionTag,lockAgeMs:l}),!s.isLocked||d){c=Date.now(),o.debug("Acquiring lock for auto-switch",{requestId:r,sessionTag:t})
|
|
4514
4519
|
const n=await e.lockRequest(r,t)
|
|
4515
4520
|
if(Date.now(),!n.locked){const e=`Failed to acquire lock for request ${r} during auto-switch`
|
|
4516
4521
|
throw o.warn("Auto-switch lock acquisition failed",{requestId:r}),Error(e)}o.info("Successfully acquired lock for auto-switch",{requestId:r,sessionTag:t,lockedAt:n.lockedAt}),a=!0}}catch(e){throw o.error("Lock check/acquisition failed during auto-switch",{requestId:r,error:e instanceof Error?e.message:e+""}),e}else o.warn("Multi-agent mode but no API client available for locking",{requestId:r})
|
package/dist/index.js
CHANGED
|
@@ -841,8 +841,10 @@ e&&s&&await o.workspaceManager.ensureReadonlyBranchIfNeeded(e,n,s,q)}catch(e){k.
|
|
|
841
841
|
if(e?.sessionId&&t){const r=t.match(/^requests\/(.+)$/),n="1"===process.env.ALCHEMY_ALLOW_PARALLEL
|
|
842
842
|
if(r&&!n){const t=r[1]
|
|
843
843
|
E=!0
|
|
844
|
-
try{const{sessionTag:r}=(0,g.getGlobalClientInfo)(),n=s.getSessionTagMappingClient(),o=s.getRequestClient()
|
|
845
|
-
|
|
844
|
+
try{const{sessionTag:r}=(0,g.getGlobalClientInfo)(),n=s.getSessionTagMappingClient(),o=s.getRequestClient()
|
|
845
|
+
let i=!1,a=null
|
|
846
|
+
const c=n?n.getMappingByOpencodeSessionId(e.sessionId).then((t=>{t?((0,g.setSessionTag)(t.sessionTag),a=t.sessionTag,k.info("Recovered session tag from mapping",{opencodeSessionId:e.sessionId,sessionTag:t.sessionTag})):(n.createOrUpdateMapping(r,e.sessionId).catch((()=>{})),k.info("Registered session tag mapping",{opencodeSessionId:e.sessionId,sessionTag:r}))}),(e=>k.debug("Mapping lookup failed",{error:(0,d.getErrorMessage)(e)}))):Promise.resolve(),l=o.lockRequest?o.lockRequest(t,r).then((e=>{i=e.locked,e.locked?k.info("Acquired request lock",{requestId:t,sessionTag:r}):k.warn("Failed to acquire request lock",{requestId:t,sessionTag:r})}),(e=>k.warn("Lock acquisition failed",{error:(0,d.getErrorMessage)(e)}))):Promise.resolve()
|
|
847
|
+
if(await Promise.all([c,l]),!i&&a&&a!==r&&o.lockRequest)try{(await o.lockRequest(t,a)).locked?k.info("Acquired lock with recovered session tag after MCP restart",{requestId:t,sessionTag:a}):k.warn("Lock still held by a different session after recovered-tag retry",{requestId:t,recoveredTag:a})}catch(e){k.warn("Lock retry with recovered tag failed",{error:(0,d.getErrorMessage)(e)})}}catch(e){k.warn("Error in session tag mapping / lock acquisition",{error:(0,d.getErrorMessage)(e)})}}}}o&&(o.currentSessionId=q||"__unknown__")
|
|
846
848
|
const S=`${Date.now()}-${Math.random().toString(36).slice(2,10)}`,T=e=>{const{getActionServerBaseUrl:r}=t(9414)
|
|
847
849
|
fetch(r()+"/api/mcp/tool-call-event",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:e,callId:S}),signal:AbortSignal.timeout(500)}).catch((()=>{}))}
|
|
848
850
|
let P
|
|
@@ -4548,10 +4550,13 @@ if(n.workspaceManager){o.debug("Using WorkspaceManager for request context switc
|
|
|
4548
4550
|
try{if("multi-agent"===n.workspaceManager.getCurrentContext(n.currentSessionId).mode)if(o.debug("Multi-agent mode: checking request lock before auto-switch",{requestId:r}),n.apiClient)try{const e=n.apiClient.getRequestClient(),{sessionTag:t}=(0,h.getGlobalClientInfo)()
|
|
4549
4551
|
c=Date.now()
|
|
4550
4552
|
const s=await e.getRequestLockStatus(r)
|
|
4551
|
-
|
|
4552
|
-
|
|
4553
|
-
if(
|
|
4554
|
-
|
|
4553
|
+
Date.now()
|
|
4554
|
+
const i=10,l=s.lockedAt?Date.now()-new Date(s.lockedAt).getTime():0,d=l>6e4*i
|
|
4555
|
+
if(s.isLocked&&s.lockedBySessionTag!==t&&!d){o.warn("Auto-switch blocked by request lock",{requestId:r,lockedByAgent:s.lockedBySessionTag,currentAgent:t,lockedAt:s.lockedAt,lockAgeMs:l})
|
|
4556
|
+
const e=Math.max(0,Math.ceil(i-l/6e4))
|
|
4557
|
+
let a=`Request ${r} is currently locked by another agent (${s.lockedBySessionTag}).\n\nLocked since: ${s.lockedAt||"unknown"}\n\nIn multi-agent mode, only one agent can work on a request at a time. If the holder is dead/abandoned, the lock will become takeover-eligible in ~${e} minute${1===e?"":"s"} \u2014 retry your operation then and it will succeed automatically. If the holder is genuinely active, wait for them to finish.`
|
|
4558
|
+
if(n.lockOverrideManager&&n.configManager)try{const e=await n.configManager.getEffectiveConfig(n.mainBasePath)
|
|
4559
|
+
e.lockOverride.enabled&&(a+=`\n\nIf you cannot wait, switch_to_branch with password: \`${n.lockOverrideManager.generatePassword(r,e.lockOverride.passwordValidityMinutes)}\` (valid for ${e.lockOverride.passwordValidityMinutes} minutes) \u2014 ONLY if you are certain the holder is dead.`)}catch(e){o.warn("Failed to check lock override config",{error:e})}throw new p.RequestLockError(a,r,s.lockedBySessionTag,s.lockedAt)}if(d&&s.lockedBySessionTag!==t&&o.info("Stale lock detected \u2014 DAO will take it over on next acquire",{requestId:r,staleBySessionTag:s.lockedBySessionTag,lockAgeMs:l}),!s.isLocked||d){c=Date.now(),o.debug("Acquiring lock for auto-switch",{requestId:r,sessionTag:t})
|
|
4555
4560
|
const n=await e.lockRequest(r,t)
|
|
4556
4561
|
if(Date.now(),!n.locked){const e=`Failed to acquire lock for request ${r} during auto-switch`
|
|
4557
4562
|
throw o.warn("Auto-switch lock acquisition failed",{requestId:r}),Error(e)}o.info("Successfully acquired lock for auto-switch",{requestId:r,sessionTag:t,lockedAt:n.lockedAt}),a=!0}}catch(e){throw o.error("Lock check/acquisition failed during auto-switch",{requestId:r,error:e instanceof Error?e.message:e+""}),e}else o.warn("Multi-agent mode but no API client available for locking",{requestId:r})
|
package/dist/mcp-direct.js
CHANGED
|
@@ -738,8 +738,10 @@ e&&s&&await o.workspaceManager.ensureReadonlyBranchIfNeeded(e,n,s,q)}catch(e){k.
|
|
|
738
738
|
if(e?.sessionId&&t){const r=t.match(/^requests\/(.+)$/),n="1"===process.env.ALCHEMY_ALLOW_PARALLEL
|
|
739
739
|
if(r&&!n){const t=r[1]
|
|
740
740
|
E=!0
|
|
741
|
-
try{const{sessionTag:r}=(0,g.getGlobalClientInfo)(),n=s.getSessionTagMappingClient(),o=s.getRequestClient()
|
|
742
|
-
|
|
741
|
+
try{const{sessionTag:r}=(0,g.getGlobalClientInfo)(),n=s.getSessionTagMappingClient(),o=s.getRequestClient()
|
|
742
|
+
let i=!1,a=null
|
|
743
|
+
const c=n?n.getMappingByOpencodeSessionId(e.sessionId).then((t=>{t?((0,g.setSessionTag)(t.sessionTag),a=t.sessionTag,k.info("Recovered session tag from mapping",{opencodeSessionId:e.sessionId,sessionTag:t.sessionTag})):(n.createOrUpdateMapping(r,e.sessionId).catch((()=>{})),k.info("Registered session tag mapping",{opencodeSessionId:e.sessionId,sessionTag:r}))}),(e=>k.debug("Mapping lookup failed",{error:(0,d.getErrorMessage)(e)}))):Promise.resolve(),l=o.lockRequest?o.lockRequest(t,r).then((e=>{i=e.locked,e.locked?k.info("Acquired request lock",{requestId:t,sessionTag:r}):k.warn("Failed to acquire request lock",{requestId:t,sessionTag:r})}),(e=>k.warn("Lock acquisition failed",{error:(0,d.getErrorMessage)(e)}))):Promise.resolve()
|
|
744
|
+
if(await Promise.all([c,l]),!i&&a&&a!==r&&o.lockRequest)try{(await o.lockRequest(t,a)).locked?k.info("Acquired lock with recovered session tag after MCP restart",{requestId:t,sessionTag:a}):k.warn("Lock still held by a different session after recovered-tag retry",{requestId:t,recoveredTag:a})}catch(e){k.warn("Lock retry with recovered tag failed",{error:(0,d.getErrorMessage)(e)})}}catch(e){k.warn("Error in session tag mapping / lock acquisition",{error:(0,d.getErrorMessage)(e)})}}}}o&&(o.currentSessionId=q||"__unknown__")
|
|
743
745
|
const S=`${Date.now()}-${Math.random().toString(36).slice(2,10)}`,T=e=>{const{getActionServerBaseUrl:r}=t(9414)
|
|
744
746
|
fetch(r()+"/api/mcp/tool-call-event",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:e,callId:S}),signal:AbortSignal.timeout(500)}).catch((()=>{}))}
|
|
745
747
|
let x
|
|
@@ -4281,10 +4283,13 @@ if(n.workspaceManager){o.debug("Using WorkspaceManager for request context switc
|
|
|
4281
4283
|
try{if("multi-agent"===n.workspaceManager.getCurrentContext(n.currentSessionId).mode)if(o.debug("Multi-agent mode: checking request lock before auto-switch",{requestId:r}),n.apiClient)try{const e=n.apiClient.getRequestClient(),{sessionTag:t}=(0,h.getGlobalClientInfo)()
|
|
4282
4284
|
c=Date.now()
|
|
4283
4285
|
const s=await e.getRequestLockStatus(r)
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
if(
|
|
4287
|
-
|
|
4286
|
+
Date.now()
|
|
4287
|
+
const i=10,l=s.lockedAt?Date.now()-new Date(s.lockedAt).getTime():0,d=l>6e4*i
|
|
4288
|
+
if(s.isLocked&&s.lockedBySessionTag!==t&&!d){o.warn("Auto-switch blocked by request lock",{requestId:r,lockedByAgent:s.lockedBySessionTag,currentAgent:t,lockedAt:s.lockedAt,lockAgeMs:l})
|
|
4289
|
+
const e=Math.max(0,Math.ceil(i-l/6e4))
|
|
4290
|
+
let a=`Request ${r} is currently locked by another agent (${s.lockedBySessionTag}).\n\nLocked since: ${s.lockedAt||"unknown"}\n\nIn multi-agent mode, only one agent can work on a request at a time. If the holder is dead/abandoned, the lock will become takeover-eligible in ~${e} minute${1===e?"":"s"} \u2014 retry your operation then and it will succeed automatically. If the holder is genuinely active, wait for them to finish.`
|
|
4291
|
+
if(n.lockOverrideManager&&n.configManager)try{const e=await n.configManager.getEffectiveConfig(n.mainBasePath)
|
|
4292
|
+
e.lockOverride.enabled&&(a+=`\n\nIf you cannot wait, switch_to_branch with password: \`${n.lockOverrideManager.generatePassword(r,e.lockOverride.passwordValidityMinutes)}\` (valid for ${e.lockOverride.passwordValidityMinutes} minutes) \u2014 ONLY if you are certain the holder is dead.`)}catch(e){o.warn("Failed to check lock override config",{error:e})}throw new p.RequestLockError(a,r,s.lockedBySessionTag,s.lockedAt)}if(d&&s.lockedBySessionTag!==t&&o.info("Stale lock detected \u2014 DAO will take it over on next acquire",{requestId:r,staleBySessionTag:s.lockedBySessionTag,lockAgeMs:l}),!s.isLocked||d){c=Date.now(),o.debug("Acquiring lock for auto-switch",{requestId:r,sessionTag:t})
|
|
4288
4293
|
const n=await e.lockRequest(r,t)
|
|
4289
4294
|
if(Date.now(),!n.locked){const e=`Failed to acquire lock for request ${r} during auto-switch`
|
|
4290
4295
|
throw o.warn("Auto-switch lock acquisition failed",{requestId:r}),Error(e)}o.info("Successfully acquired lock for auto-switch",{requestId:r,sessionTag:t,lockedAt:n.lockedAt}),a=!0}}catch(e){throw o.error("Lock check/acquisition failed during auto-switch",{requestId:r,error:e instanceof Error?e.message:e+""}),e}else o.warn("Multi-agent mode but no API client available for locking",{requestId:r})
|