alchemylab 1.0.6 → 1.0.7
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/cli.js +17 -9
- package/dist/http-server.js +78 -71
- package/dist/index.js +78 -71
- package/dist/mcp-direct.js +352 -345
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -365,7 +365,15 @@ if(!this.stuckSessionWatchdog)return void t.status(503).json({success:!1,error:"
|
|
|
365
365
|
const r=await this.stuckSessionWatchdog.retrySession(s)
|
|
366
366
|
r.success?t.json({success:!0}):t.status(400).json({success:!1,error:r.error})}async stop(){this.logger.info("Stopping AlchemyActionServer...")
|
|
367
367
|
for(const[e]of this.proxyAbortControllers)try{e.abort()}catch{}if(this.proxyAbortControllers.size>0&&await Promise.allSettled([...this.proxyAbortControllers.values()]),this.proxyAbortControllers.clear(),this.killTrackedProcesses(),this.stuckSessionWatchdog?.stop(),this.stopSSEEventForwarder(),this.isPolling=!1,this.pollAbortController&&this.pollAbortController.abort(),this.pollingInterval&&clearInterval(this.pollingInterval),this.heartbeatInterval&&clearInterval(this.heartbeatInterval),this.serverId)try{await this.apiClient.post(`/api/servers/${this.serverId}/disconnect`)}catch{}this.cliBridge.close(),await new Promise((e=>{if(this.server){const t=setTimeout((()=>{this.logger.warn("Graceful shutdown timed out after 10s, forcing close"),e()}),1e4)
|
|
368
|
-
this.server.close((()=>{clearTimeout(t),e()}))}else e()})),this.logger.info("AlchemyActionServer stopped")}getPort(){return this.port}isRunning(){return!!this.server}}exports.AlchemyActionServer=v,v.PROJECT_CONFIG_TTL=3e4},
|
|
368
|
+
this.server.close((()=>{clearTimeout(t),e()}))}else e()})),this.logger.info("AlchemyActionServer stopped")}getPort(){return this.port}isRunning(){return!!this.server}}exports.AlchemyActionServer=v,v.PROJECT_CONFIG_TTL=3e4},2424(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.ensureRequestWorktree=async function(e,t,i){const a="requests/"+t,c=(0,r.join)(e,n.ALCHEMY_DIR_NAME,"worktrees"),l=(0,r.join)(c,t)
|
|
369
|
+
if((0,s.existsSync)(l))return void i.info("Worktree already exists on disk, skipping pre-spawn creation",{requestId:t,worktreePath:l})
|
|
370
|
+
const d=(0,o.simpleGit)(e);(0,s.mkdirSync)(c,{recursive:!0})
|
|
371
|
+
try{await d.raw(["worktree","prune"])}catch{}const u=await d.branch(),h=u.all.includes(a)
|
|
372
|
+
try{if(h)await d.raw(["worktree","add",l,a]),i.info("Pre-spawn: created worktree for existing branch",{requestId:t,branchName:a,worktreePath:l})
|
|
373
|
+
else{const e=u.all.includes("main")?"main":"master"
|
|
374
|
+
await d.raw(["worktree","add","-b",a,l,e]),i.info("Pre-spawn: created worktree with new branch from latest main",{requestId:t,branchName:a,mainBranch:e,worktreePath:l})}}catch(e){const s=e instanceof Error?e.message:e+""
|
|
375
|
+
i.warn("Pre-spawn: failed to create worktree (MCP process will retry)",{requestId:t,error:s})}}
|
|
376
|
+
const s=t(9896),r=t(6928),o=t(3807),n=t(4139)},2782(e,exports,t){function s(){return"true"===process.env.ENABLE_DEBUG_TOOLS?.toLowerCase()}function r(e={}){const t={...function(e){const t={}
|
|
369
377
|
if(!s())return t.level=(0,l.isDevBuild)()?c.LogLevel.INFO:c.LogLevel.ERROR,t.logToFile=!1,t
|
|
370
378
|
if("true"===process.env.DEBUG_LOGGING?.toLowerCase()){t.level=c.LogLevel.DEBUG,t.logToFile=!0
|
|
371
379
|
const s=e||process.cwd()
|
|
@@ -708,21 +716,21 @@ let k
|
|
|
708
716
|
try{k=(0,i.openSync)(C,"a")}catch{}const S=(0,o.spawn)("opencode",v,{detached:!0,stdio:["ignore","ignore",k??"ignore"],cwd:c||process.cwd(),env:n})
|
|
709
717
|
return S.unref(),f&&f(S.pid),{success:!0,pid:S.pid}}catch(e){const t=(0,n.getErrorMessage)(e)
|
|
710
718
|
return m&&e instanceof Error&&m(e),{success:!1,error:t}}}Object.defineProperty(exports,"__esModule",{value:!0}),exports.spawnDetachedSubagent=r,exports.spawnJournalSubagent=function(e,t,s,o){return r({agent:"journal",prompt:`Generate a journal entry for request ${e}.\n\nSteps:\n1. Use ${t}__generate_request_journal tool with requestId: ${e}\n2. Write a concise narrative journal entry based on the returned data covering:\n - What was implemented and why\n - Key decisions and trade-offs made\n - Challenges encountered and solutions\n - Files modified and their purposes\n - How acceptance criteria were met\n3. Save as JOURNAL-${e}.md using ${t}__document_operations (operation: create, type: Report)\n\nKeep it story-focused and informative.`,cwd:s,parentServerUrl:o})},exports.spawnWorkSubagent=function(e,t,s){return r({agent:"work",prompt:e,cwd:t,parentServerUrl:s})}
|
|
711
|
-
const o=t(5317),n=t(8824),i=t(9896),a=t(6928)},8148(e,exports,t){function s(e,t){try{const t=(0,o.join)(e,
|
|
712
|
-
if(n.port)return"http://127.0.0.1:"+n.port}catch(e){t.debug("Could not read opencode.json for server URL",{error:(0,
|
|
713
|
-
let
|
|
714
|
-
|
|
719
|
+
const o=t(5317),n=t(8824),i=t(9896),a=t(6928)},8148(e,exports,t){function s(e,t){try{const t=(0,o.join)(e,c,"opencode.json"),s=(0,r.readFileSync)(t,"utf8"),n=JSON.parse(s)
|
|
720
|
+
if(n.port)return"http://127.0.0.1:"+n.port}catch(e){t.debug("Could not read opencode.json for server URL",{error:(0,a.getErrorMessage)(e)})}return null}Object.defineProperty(exports,"__esModule",{value:!0}),exports.getOpenCodeServerUrl=s,exports.spawnActionAgent=async function(e){const{agent:t,prompt:r,cwd:o,projectPath:c,title:l,requestId:d,parentSessionId:u,allowParallel:h,apiClient:g,logger:p,trackChildPid:f}=e,m=s(c,p)
|
|
721
|
+
let y,v=null
|
|
722
|
+
m?v=await async function(e,t,s,r,o,n,i,c){try{const l=await fetch(e+"/session",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({title:t,...o?{parentID:o}:{}})})
|
|
715
723
|
if(!l.ok)return c.warn("Failed to pre-create session via HTTP",{status:l.status}),null
|
|
716
724
|
const d=await l.json()
|
|
717
725
|
if(!d.id)return c.warn("Session created but no ID returned"),null
|
|
718
726
|
const u=d.id
|
|
719
727
|
c.info("Pre-created agent session",{sessionId:u,title:t,agent:s})
|
|
720
|
-
try{await
|
|
728
|
+
try{await i.post(`/api/projects/${n}/cli-sessions`,{externalSessionId:u,providerId:"opencode",...o?{parentExternalSessionId:o}:{},agentType:s,status:"active"}),c.info("Registered session in alchemy DB",{sessionId:u,agent:s,parentSessionId:o})}catch(e){c.warn("Failed to register session in DB",{error:(0,a.getErrorMessage)(e)})}if(r&&n){try{await i.post(`/api/projects/${n}/session-request-associations`,{opencodeSessionId:u,requestLocalId:r}),c.info("Created session-request association",{sessionId:u,requestId:r})}catch(e){c.warn("Failed to create session-request association",{error:(0,a.getErrorMessage)(e)})}if("coder"===s)try{await i.patch(`/api/projects/${n}/requests/${r}`,{cliOrigin:{providerId:"opencode",sessionId:u,createdAt:(new Date).toISOString()}}),c.info("Updated request cliOrigin to coder session",{sessionId:u,requestId:r})}catch(e){c.warn("Failed to update request cliOrigin",{error:(0,a.getErrorMessage)(e)})}}return u}catch(e){return c.warn("Failed to pre-create session",{error:(0,a.getErrorMessage)(e)}),null}}(m,l,t,d,u,e.projectId,g,p):p.warn("No OpenCode server URL \u2014 agent session will not be visible in session list")
|
|
721
729
|
try{const e=await fetch("http://localhost:3456/api/project-settings")
|
|
722
730
|
if(e.ok){const s=await e.json()
|
|
723
|
-
s.data?.defaultModel&&(
|
|
724
|
-
return
|
|
725
|
-
const r=t(9896),o=t(6928),n=t(8035),i=t(
|
|
731
|
+
s.data?.defaultModel&&(y=s.data.defaultModel,p.info("Using user default model for agent spawn",{agent:t,model:y}))}}catch{}if(d)try{await(0,i.ensureRequestWorktree)(c,d,p)}catch(e){p.warn("Pre-spawn worktree creation failed (non-fatal)",{requestId:d,error:(0,a.getErrorMessage)(e)})}const w=(0,n.spawnDetachedSubagent)({agent:t,prompt:r,cwd:o,sessionId:v||void 0,serverUrl:m||void 0,model:y,allowParallel:h??!1,onSpawn(e){e&&f&&f(e)}})
|
|
732
|
+
return w.success?(p.info("Spawned action agent",{agent:t,sessionId:v,pid:w.pid,requestId:d}),{success:!0,sessionId:v,pid:w.pid}):{success:!1,sessionId:v,error:w.error||"Spawn failed"}}
|
|
733
|
+
const r=t(9896),o=t(6928),n=t(8035),i=t(2424),a=t(8824),c=".alchemy_lab"},8524(e,exports,t){var s=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
726
734
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.CLIBridgeWebSocket=void 0,exports.setCLIBridge=function(e){n=e},exports.getCLIBridge=function(){return n}
|
|
727
735
|
const r=t(5086),o=s(t(6982))
|
|
728
736
|
exports.CLIBridgeWebSocket=class{constructor(e,t=3e4){this.wss=null,this.uiClient=null,this.pendingCommands=new Map,this.heartbeatInterval=null,this.logger=e,this.defaultTimeout=t}attach(e){this.wss=new r.WebSocketServer({server:e,path:"/ws/cli-bridge"}),this.wss.on("connection",(e=>{this.logger.info("[CLIBridge] UI client connected"),this.uiClient&&(this.logger.warn("[CLIBridge] Replacing existing UI client connection"),this.uiClient.close(1e3,"Replaced by new connection")),this.uiClient=e,this.startHeartbeat(),e.on("message",(e=>{try{const t=JSON.parse(e.toString())
|
package/dist/http-server.js
CHANGED
|
@@ -823,10 +823,9 @@ let I=Date.now()
|
|
|
823
823
|
const b=r(a)
|
|
824
824
|
if(Date.now(),I=Date.now(),y){const e=await w()
|
|
825
825
|
if(Date.now(),!e)return m.warn("Unauthenticated tool call attempt",{tool:i}),{content:[{type:"text",text:"Authentication required. Please run 'alchemylab setup' to authenticate and configure your project."}],isError:!0}}const C=(0,f.getToolByName)(i)
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
if(
|
|
829
|
-
if(n)n.sessionId!==e&&((0,p.logSessionIdentity)(i,"_meta-session-switch",{prevSessionId:n.sessionId,prevAgentType:n.agentType,newSessionId:e}),u.sessionIdentity.setIdentity({providerId:"opencode",sessionId:e,serverUrl:n.serverUrl}))
|
|
826
|
+
let _,E
|
|
827
|
+
if(I=Date.now(),n?(n.setOptions({createRecords:C?.createsRecords??!1}),m.info(`Setting record creation for tool ${i}: ${C?.createsRecords??!1}`)):m.debug(`No API client available for tool ${i} (minimal mode)`),Date.now(),Date.now(),I=Date.now(),C&&!C.readOnly)if(c?.sessionId){const e=c.sessionId,r=c.messageId,n=u.sessionIdentity.getIdentity()
|
|
828
|
+
if(n)n.sessionId!==e&&((0,p.logSessionIdentity)(i,"_meta-session-switch",{prevSessionId:n.sessionId,prevAgentType:n.agentType,newSessionId:e}),u.sessionIdentity.setIdentity({providerId:"opencode",sessionId:e,serverUrl:n.serverUrl}),t?.workspaceManager?.resetCurrentContext?.())
|
|
830
829
|
else{const r=await(0,d.getServerUrl)(t,m)
|
|
831
830
|
u.sessionIdentity.setIdentity({providerId:"opencode",sessionId:e,serverUrl:r||""}),u.sessionIdentity.markDiscoveryAttempted()}_={providerId:"opencode",sessionId:e,messageId:r,createdAt:(new Date).toISOString()},(0,p.logSessionIdentity)(i,"_meta",{sessionId:e,messageId:r})}else{const e=u.sessionIdentity.getIdentity()
|
|
832
831
|
if(e){let r,n=!1
|
|
@@ -836,7 +835,9 @@ else{m.info("Session identity mismatch: tool call not found in cached session, r
|
|
|
836
835
|
try{const t=await(0,d.getAndStoreSessionId)(e.serverUrl,m,i)
|
|
837
836
|
t?(u.sessionIdentity.setIdentity({providerId:"opencode",sessionId:t.sessionId,serverUrl:e.serverUrl}),(0,p.logSessionIdentity)(i,"re-discovery",{sessionId:t.sessionId,messageId:t.messageId}),_=u.sessionIdentity.buildCliOrigin(t.messageId)):(u.sessionIdentity.setIdentity(e),_=u.sessionIdentity.buildCliOrigin(),m.info("Re-discovery found no other session, keeping current identity",{sessionId:e.sessionId})),u.sessionIdentity.markDiscoveryAttempted()}catch(t){u.sessionIdentity.setIdentity(e),_=u.sessionIdentity.buildCliOrigin(),u.sessionIdentity.markDiscoveryAttempted(),m.warn("Re-discovery failed, keeping current identity (may be stale)",{error:(0,l.getErrorMessage)(t),tool:i,sessionId:e.sessionId})}}}else if(!u.sessionIdentity.hasDiscoveryBeenAttempted())try{const e=await(0,d.getServerUrl)(t,m)
|
|
838
837
|
if(e){const t=await(0,d.getAndStoreSessionId)(e,m,i)
|
|
839
|
-
t&&(u.sessionIdentity.setIdentity({providerId:"opencode",sessionId:t.sessionId,serverUrl:e}),(0,p.logSessionIdentity)(i,"http-discovery",{sessionId:t.sessionId,messageId:t.messageId}),_=u.sessionIdentity.buildCliOrigin(t.messageId))}u.sessionIdentity.markDiscoveryAttempted()}catch(e){u.sessionIdentity.markDiscoveryAttempted(),(0,p.logSessionIdentity)(i,"discovery-failed",{error:(0,l.getErrorMessage)(e)}),m.debug("cliOrigin discovery failed",{error:(0,l.getErrorMessage)(e),tool:i})}}if(u.sessionIdentity.setCurrentCallOrigin(_)
|
|
838
|
+
t&&(u.sessionIdentity.setIdentity({providerId:"opencode",sessionId:t.sessionId,serverUrl:e}),(0,p.logSessionIdentity)(i,"http-discovery",{sessionId:t.sessionId,messageId:t.messageId}),_=u.sessionIdentity.buildCliOrigin(t.messageId))}u.sessionIdentity.markDiscoveryAttempted()}catch(e){u.sessionIdentity.markDiscoveryAttempted(),(0,p.logSessionIdentity)(i,"discovery-failed",{error:(0,l.getErrorMessage)(e)}),m.debug("cliOrigin discovery failed",{error:(0,l.getErrorMessage)(e),tool:i})}}if(u.sessionIdentity.setCurrentCallOrigin(_),t?.workspaceManager&&!t.workspaceManager.readonlyBranchCheckDone){I=Date.now()
|
|
839
|
+
try{const e=await(0,d.getServerUrl)(t,m)
|
|
840
|
+
e&&n&&await t.workspaceManager.ensureReadonlyBranchIfNeeded(e,i,n,c?.sessionId)}catch(e){m.debug("Error during workspace check",{error:(0,l.getErrorMessage)(e)})}Date.now()}if(!v&&n){const e=u.sessionIdentity.getIdentity(),t=process.env.ALCHEMY_INITIAL_BRANCH
|
|
840
841
|
if(e?.sessionId&&t){const r=t.match(/^requests\/(.+)$/),o="1"===process.env.ALCHEMY_ALLOW_PARALLEL
|
|
841
842
|
if(r&&!o){const t=r[1]
|
|
842
843
|
v=!0
|
|
@@ -1180,94 +1181,93 @@ const e=this.online,t=await this.performHealthCheck()
|
|
|
1180
1181
|
return e!==t&&(t?(this.logger.info("Health check status changed to ONLINE"),this.options.onOnlineCallback()):(this.logger.info("Health check status changed to OFFLINE"),this.options.onOfflineCallback())),t}isOffline(){return this.forcedOfflineMode||!1}scheduleNextCheck(e=this.options.checkIntervalMs){this.checkInterval&&(clearInterval(this.checkInterval),this.checkInterval=null),0!==e?setTimeout((()=>{this.performHealthCheck().catch((()=>{}))}),e||this.options.checkIntervalMs||3e4):this.performHealthCheck().catch((()=>{}))}setOfflineMode(e){const t=this.forcedOfflineMode
|
|
1181
1182
|
this.forcedOfflineMode=e,t!==e&&(this.logger.info("Offline mode "+(e?"ENABLED":"DISABLED")),this.metrics.setGauge("health_check_forced_offline",e?1:0),e||this.scheduleNextCheck(0))}getStats(){return{consecutiveFailures:this.consecutiveFailures,currentBackoffMs:this.currentBackoffMs,lastCheckTime:this.lastCheckTime}}}},1722(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.def=void 0
|
|
1182
1183
|
const r=t(6183),n=t(355)
|
|
1183
|
-
exports.def={name:"complete_task",description:"Mark a task as completed with a summary of work done.",schema:r.CompleteTaskSchema,annotations:{title:"Complete Task",readOnlyHint:!1,destructiveHint:!1,idempotentHint:!0},handler(e,t){return(0,n.handleCompleteTask)(e,t.context,t.apiClient,t.logger,t.metrics,t.mcpServer)}}},1725(e,exports,t){function r(e,t,r){try{const n=`[${(new Date).toISOString()}] ${t}${r?" "+JSON.stringify(r):""}\n`,o=(0,
|
|
1184
|
+
exports.def={name:"complete_task",description:"Mark a task as completed with a summary of work done.",schema:r.CompleteTaskSchema,annotations:{title:"Complete Task",readOnlyHint:!1,destructiveHint:!1,idempotentHint:!0},handler(e,t){return(0,n.handleCompleteTask)(e,t.context,t.apiClient,t.logger,t.metrics,t.mcpServer)}}},1725(e,exports,t){function r(e,t,r){try{const n=`[${(new Date).toISOString()}] ${t}${r?" "+JSON.stringify(r):""}\n`,o=(0,T.join)(e.basePath||process.cwd(),".alchemy_lab","spawn-debug.log");(0,S.appendFileSync)(o,n)}catch{}}async function n(e){try{const t=`http://localhost:${R}/api/agents/by-name/${encodeURIComponent(e)}`,r=await fetch(t)
|
|
1184
1185
|
if(!r.ok)return null
|
|
1185
1186
|
const n=await r.json()
|
|
1186
1187
|
return n.success?n.data??null:null}catch{return null}}async function o(e,t,o,s,i){const{agent:a="work",prompt:c,requestId:l,allowParallel:d=!1,useExistingSession:u}=e
|
|
1187
|
-
if(r(t,"handleSpawn called",{agent:a,promptLength:c.length,requestId:l,useExistingSession:u,cliOriginSessionId:i?.sessionId||null}),!(0,
|
|
1188
|
-
return{content:[{type:"text",text:`\u274c Unknown agent '${a}'.\n\n**Available agents:** ${e.join(", ")}\n\nChoose one of the available agents listed above to see detailed descriptions of each agent.`}],isError:!0}}try{const e=(0,
|
|
1188
|
+
if(r(t,"handleSpawn called",{agent:a,promptLength:c.length,requestId:l,useExistingSession:u,cliOriginSessionId:i?.sessionId||null}),!(0,P.isValidAgent)(a)){const e=(0,P.getAgentNames)()
|
|
1189
|
+
return{content:[{type:"text",text:`\u274c Unknown agent '${a}'.\n\n**Available agents:** ${e.join(", ")}\n\nChoose one of the available agents listed above to see detailed descriptions of each agent.`}],isError:!0}}try{const e=(0,v.getCachedSession)(),n=i?.sessionId||e?.sessionId
|
|
1189
1190
|
let o=e?.agentType
|
|
1190
|
-
if(r(t,"Spawn agent type check",{cliOriginSessionId:i?.sessionId||null,cachedSessionId:e?.sessionId||null,cachedAgentType:e?.agentType||null,pid:process.pid,envSessionTag:process.env.ALCHEMY_SESSION_TAG||null,envInitialBranch:process.env.ALCHEMY_INITIAL_BRANCH||null}),!o&&n)try{const e=`http://localhost:${
|
|
1191
|
+
if(r(t,"Spawn agent type check",{cliOriginSessionId:i?.sessionId||null,cachedSessionId:e?.sessionId||null,cachedAgentType:e?.agentType||null,pid:process.pid,envSessionTag:process.env.ALCHEMY_SESSION_TAG||null,envInitialBranch:process.env.ALCHEMY_INITIAL_BRANCH||null}),!o&&n)try{const e=`http://localhost:${R}/api/sessions/${encodeURIComponent(n)}/agent-type`
|
|
1191
1192
|
r(t,"Looking up agent type from action server",{sessionId:n,url:e})
|
|
1192
1193
|
const s=await fetch(e)
|
|
1193
1194
|
if(s.ok){const e=await s.json()
|
|
1194
|
-
r(t,"Agent type response from action server",{sessionId:n,agentType:e.agentType||null,source:e.source||null,success:e.success}),e.success&&e.agentType&&(o=e.agentType,(0,
|
|
1195
|
-
if(e&&!e.includes(a))return{content:[{type:"text",text:`\u274c Agent type '${o}' cannot spawn '${a}'.\n\n**Allowed subagents for ${o}:** ${e.join(", ")}\n\nUse one of the allowed agent types instead.`}],isError:!0}}}catch(e){r(t,"allowedSubagents check failed",{error:(0,
|
|
1195
|
+
r(t,"Agent type response from action server",{sessionId:n,agentType:e.agentType||null,source:e.source||null,success:e.success}),e.success&&e.agentType&&(o=e.agentType,(0,v.updateCachedSession)({agentType:o}))}else r(t,"Agent type lookup failed",{sessionId:n,status:s.status})}catch(n){r(t,"Agent type lookup error",{sessionId:e?.sessionId,error:(0,q.getErrorMessage)(n)})}if(o){const e=(0,P.getAllowedSubagents)(o)
|
|
1196
|
+
if(e&&!e.includes(a))return{content:[{type:"text",text:`\u274c Agent type '${o}' cannot spawn '${a}'.\n\n**Allowed subagents for ${o}:** ${e.join(", ")}\n\nUse one of the allowed agent types instead.`}],isError:!0}}}catch(e){r(t,"allowedSubagents check failed",{error:(0,q.getErrorMessage)(e)})}let h
|
|
1196
1197
|
try{const e=await n(a)
|
|
1197
|
-
if(h=e?.requestContextMode,!h){const e=(0,
|
|
1198
|
+
if(h=e?.requestContextMode,!h){const e=(0,P.getBuiltInAgentConfig)(a)
|
|
1198
1199
|
h=e?.requestContextMode}}catch{}if(h&&"none"!==h&&!l)return{content:[{type:"text",text:`\u274c Agent '${a}' requires a requestId to be provided.\n\nThis agent has requestContextMode: '${h}' which means it needs to work in the context of a specific request.\n\nPlease provide a requestId when spawning this agent.`}],isError:!0}
|
|
1199
|
-
const g=await(0,
|
|
1200
|
+
const g=await(0,b.getServerUrl)(t,o)
|
|
1200
1201
|
r(t,"serverUrl resolved",{serverUrl:g})
|
|
1201
1202
|
const p=t.basePath
|
|
1202
1203
|
if(!p)throw new w.ValidationError("Working directory not available in context")
|
|
1203
|
-
const f=(0,
|
|
1204
|
+
const f=(0,v.getCachedSession)()
|
|
1204
1205
|
let m
|
|
1205
|
-
if(g)try{m=i?.sessionId||f?.sessionId||await(0,
|
|
1206
|
+
if(g)try{m=i?.sessionId||f?.sessionId||await(0,b.discoverParentSessionId)(g,o)}catch{}let y=""
|
|
1206
1207
|
if(s&&l)try{const e=s.getSessionRequestAssociationClient()
|
|
1207
1208
|
if(e){const t=await e.getSessionsForRequest(l,!0),r=m?t.filter((e=>e.opencodeSessionId!==m)):t
|
|
1208
1209
|
if(r.length>0){const e=r.map((e=>e.opencodeSessionId)).join(", ")
|
|
1209
1210
|
if(!d)return o.warn("Blocked spawn: request already has active workers",{requestId:l,existingWorkerCount:r.length,existingSessionIds:r.map((e=>e.opencodeSessionId))}),{content:[{type:"text",text:`\u274c Cannot spawn: Request ${l} already has ${r.length} active worker(s): ${e}\n\nOptions:\n\u2022 Use \`useExistingSession: "${r[0].opencodeSessionId}"\` to send work to the existing session\n\u2022 Use \`allowParallel: true\` if you really need multiple workers on the same request`}],isError:!0}
|
|
1210
|
-
y=`\u26a0\ufe0f Warning: Request ${l} already has ${r.length} active worker(s): ${e}. Proceeding anyway (allowParallel=true).\n\n`,o.warn("Spawning parallel subagent for request with existing active workers",{requestId:l,existingWorkerCount:r.length,existingSessionIds:r.map((e=>e.opencodeSessionId)),allowParallel:!0})}}}catch(e){o.debug("Failed to check for existing workers",{error:(0,
|
|
1211
|
-
l&&(
|
|
1212
|
-
let
|
|
1213
|
-
if(u){if(
|
|
1211
|
+
y=`\u26a0\ufe0f Warning: Request ${l} already has ${r.length} active worker(s): ${e}. Proceeding anyway (allowParallel=true).\n\n`,o.warn("Spawning parallel subagent for request with existing active workers",{requestId:l,existingWorkerCount:r.length,existingSessionIds:r.map((e=>e.opencodeSessionId)),allowParallel:!0})}}}catch(e){o.debug("Failed to check for existing workers",{error:(0,q.getErrorMessage)(e)})}let _,E,S=c
|
|
1212
|
+
l&&(_="requests/"+l,r(t,"Setting initialBranch for agent",{agent:a,requestId:l,initialBranch:_,agentRequestContextMode:h||"undefined"}),S="readonly"===h?`Working on request ${l} (READONLY mode - you cannot modify files, only explore and report).\n\n${c}`:`Working on request ${l}.\n\n${c}`)
|
|
1213
|
+
let T=!1
|
|
1214
|
+
if(u){if(E=u,o.info("Using existing session for spawn",{sessionId:E,requestId:l}),!g)throw new w.ValidationError("Could not determine OpenCode server URL")
|
|
1214
1215
|
try{let e
|
|
1215
|
-
try{const t=await fetch(`http://localhost:${
|
|
1216
|
+
try{const t=await fetch(`http://localhost:${R}/api/project-settings`)
|
|
1216
1217
|
if(t.ok){const r=await t.json()
|
|
1217
1218
|
if(r.data?.defaultModel){const[t,...n]=r.data.defaultModel.split("/")
|
|
1218
|
-
e={providerID:t,modelID:n.join("/")}}}}catch{}const t=`${g.replace(/\/$/,"")}/session/${
|
|
1219
|
+
e={providerID:t,modelID:n.join("/")}}}}catch{}const t=`${g.replace(/\/$/,"")}/session/${E}/prompt_async`,r=await fetch(t,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({parts:[{type:"text",text:S}],...a?{agent:a}:{},...e?{model:e}:{}}),signal:AbortSignal.timeout(1e4)})
|
|
1219
1220
|
if(!r.ok){const e=await r.text().catch((()=>"Unknown error"))
|
|
1220
|
-
throw Error(`Failed to send to existing session: ${r.status} ${e}`)}o.info("Prompt sent to existing session",{sessionId:
|
|
1221
|
-
const i=m||f?.sessionId||await(0,
|
|
1221
|
+
throw Error(`Failed to send to existing session: ${r.status} ${e}`)}o.info("Prompt sent to existing session",{sessionId:E,agent:a})}catch(e){throw Error("Failed to use existing session: "+(0,q.getErrorMessage)(e))}}else{if(T=!0,r(t,"Creating session via HTTP and spawning CLI"),!g)throw Error("Cannot spawn subagent: no server URL available")
|
|
1222
|
+
const i=m||f?.sessionId||await(0,b.discoverParentSessionId)(g,o);(0,C.logSessionIdentity)("subagent_operations.spawn",m?"early-discovery":f?"_meta":"http-discovery",{parentSessionId:i}),r(t,"Parent session discovered",{parentSessionId:i})
|
|
1222
1223
|
const u=g.replace(/\/$/,"")+"/session",h=e.title?e.title:l?`[${l}] ${c.slice(0,40)}${c.length>40?"...":""}`:`${c.slice(0,50)}${c.length>50?"...":""}`,y=await fetch(u,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({parentID:i,title:h})})
|
|
1223
1224
|
if(!y.ok)throw Error("Failed to create session: "+y.status)
|
|
1224
1225
|
const w=await y.json()
|
|
1225
1226
|
if(!w.id)throw Error("Session created but no ID returned")
|
|
1226
|
-
const
|
|
1227
|
-
r(t,"Pre-created session with parentID",{preCreatedSessionId:
|
|
1228
|
-
const
|
|
1227
|
+
const j=w.id
|
|
1228
|
+
r(t,"Pre-created session with parentID",{preCreatedSessionId:j,parentSessionId:i}),o.info("Pre-created session with parentID",{preCreatedSessionId:j,parentSessionId:i})
|
|
1229
|
+
const x=(async()=>{if(s)try{const n=s.getCLISessionClient()
|
|
1229
1230
|
if(!n)return
|
|
1230
1231
|
let o,c
|
|
1231
|
-
if(i){const e=await n.createOrUpdateSession({externalSessionId:i,providerId:"opencode",status:"active",agentType:(0,
|
|
1232
|
-
o=e.id,c=e.workflowId,r(t,"Registered parent session in DB",{parentSessionId:i,parentDbId:o,parentWorkflowId:c})}const l=await n.createOrUpdateSession({externalSessionId:
|
|
1233
|
-
r(t,"Registered child session in DB",{childSessionId:
|
|
1234
|
-
let
|
|
1232
|
+
if(i){const e=await n.createOrUpdateSession({externalSessionId:i,providerId:"opencode",status:"active",agentType:(0,v.getCachedSession)()?.agentType||void 0})
|
|
1233
|
+
o=e.id,c=e.workflowId,r(t,"Registered parent session in DB",{parentSessionId:i,parentDbId:o,parentWorkflowId:c})}const l=await n.createOrUpdateSession({externalSessionId:j,providerId:"opencode",parentSessionId:o||null,title:h,status:"active",agentType:a,specialization:e.specialization,workflowId:c||void 0})
|
|
1234
|
+
r(t,"Registered child session in DB",{childSessionId:j,childDbId:l.id,parentDbId:o})}catch(e){r(t,"Failed to register sessions in DB",{error:(0,q.getErrorMessage)(e)}),o.warn("Failed to register sessions in alchemy DB",{error:(0,q.getErrorMessage)(e)})}})()
|
|
1235
|
+
let O
|
|
1235
1236
|
r(t,"Starting model resolution",{agent:a,cwd:p})
|
|
1236
|
-
try{r(t,"Fetching agent config from action server",{agent:a,url:`http://localhost:${
|
|
1237
|
+
try{r(t,"Fetching agent config from action server",{agent:a,url:`http://localhost:${R}/api/agents/by-name/${a}`})
|
|
1237
1238
|
const e=await n(a)
|
|
1238
1239
|
if(r(t,"Agent config result",{agent:a,agentConfig:e||"null",hasConfig:!!e}),e){const n=e.preferredProvider||"inherit",o=e.preferredModelTier||"same"
|
|
1239
1240
|
r(t,"Agent preferences",{agent:a,preferredProvider:n,preferredTier:o,rawProvider:e.preferredProvider,rawTier:e.preferredModelTier})
|
|
1240
|
-
const s=(0,
|
|
1241
|
-
r(t,"Model resolution result",{agent:a,result:s}),s.resolved?(
|
|
1241
|
+
const s=(0,M.resolveAgentModel)(p,n,o)
|
|
1242
|
+
r(t,"Model resolution result",{agent:a,result:s}),s.resolved?(O=s.fullModel,r(t,"Resolved agent model",{agent:a,model:O,preferredProvider:n,preferredTier:o})):r(t,"Model resolution fallback",{agent:a,reason:s.reason})}else{const e=(0,P.getBuiltInAgentConfig)(a)
|
|
1242
1243
|
if(r(t,"No API agent config, checking built-in defaults",{agent:a,builtInConfig:e||"null"}),e){const n=e.preferredProvider||"inherit",o=e.preferredModelTier||"same"
|
|
1243
1244
|
r(t,"Using built-in agent preferences",{agent:a,preferredProvider:n,preferredTier:o})
|
|
1244
|
-
const s=(0,
|
|
1245
|
-
r(t,"Built-in model resolution result",{agent:a,result:s}),s.resolved&&(
|
|
1245
|
+
const s=(0,M.resolveAgentModel)(p,n,o)
|
|
1246
|
+
r(t,"Built-in model resolution result",{agent:a,result:s}),s.resolved&&(O=s.fullModel,r(t,"Resolved built-in agent model",{agent:a,model:O,preferredProvider:n,preferredTier:o}))}else r(t,"No built-in config found - using default model",{agent:a})}}catch(e){r(t,"Error resolving agent model",{agent:a,error:(0,q.getErrorMessage)(e)})}try{const e=await async function(){try{const e=`http://localhost:${R}/api/project-settings`,t=await fetch(e)
|
|
1246
1247
|
if(t.ok){const e=await t.json()
|
|
1247
1248
|
return e?.data?.defaultModel||null}}catch{}return null}()
|
|
1248
|
-
if(e)if(
|
|
1249
|
-
"same"===(o?.preferredModelTier||"same")&&(
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
return u?R+=`Prompt sent to existing session ${_}.`:(R+=`Background ${a} subagent spawned successfully.`,_&&"unknown"!==_&&"spawning"!==_&&(R+=`\n[SESSION:${_}]`)),l&&(R+="\nWorking on: "+l),R+="\n\nThe subagent is now working independently. You can continue with other tasks.",{content:[{type:"text",text:R}]}}async function s(e,t,r,n,o,s,i){const a=await(0,I.getServerUrl)(r,n)
|
|
1249
|
+
if(e)if(O){const o=await n(a)
|
|
1250
|
+
"same"===(o?.preferredModelTier||"same")&&(O=e,r(t,"Applied user default model (same tier)",{agent:a,userDefaultModel:e}))}else O=e,r(t,"Using user default model (no agent resolution)",{agent:a,userDefaultModel:e})}catch(e){r(t,"Failed to fetch user default model",{error:(0,q.getErrorMessage)(e)})}if(r(t,"Final resolved model before spawn",{agent:a,resolvedModel:O||"undefined (will use default)"}),await x,l&&_)try{await(0,I.ensureRequestWorktree)(p,l,o)}catch(e){r(t,"Pre-spawn worktree creation failed (non-fatal)",{requestId:l,error:(0,q.getErrorMessage)(e)})}const A=(0,k.spawnDetachedSubagent)({agent:a,prompt:S,cwd:p,sessionId:j,model:O,initialBranch:_,allowParallel:d,serverUrl:g})
|
|
1251
|
+
if(!A.success)throw Error("Failed to spawn subagent: "+A.error)
|
|
1252
|
+
E=j,r(t,"CLI spawn successful with pre-created session",{sessionId:j,pid:A.pid,parentSessionId:i}),o.info("Background subagent spawned via CLI with pre-created session",{agent:a,requestId:l,sessionId:j,pid:A.pid,parentSessionId:i})}if(s&&l&&E&&"unknown"!==E&&"spawning"!==E)try{const e=s.getSessionRequestAssociationClient()
|
|
1253
|
+
if(e&&(e.createAssociation(E,l).then((()=>o.info("Created session-request association",{sessionId:E,requestId:l}))).catch((e=>o.warn("Failed to create session-request association",{error:(0,q.getErrorMessage)(e),sessionId:E,requestId:l}))),"coder"===a)){const e=s.getRequestClient()
|
|
1254
|
+
e&&e.updateRequest(l,{cliOrigin:{providerId:"opencode",sessionId:E,createdAt:(new Date).toISOString()}}).catch((e=>o.debug("Failed to update request cliOrigin",{error:(0,q.getErrorMessage)(e)})))}}catch(e){o.warn("Failed to create session-request association",{error:(0,q.getErrorMessage)(e),sessionId:E,requestId:l})}let j=y
|
|
1255
|
+
return u?j+=`Prompt sent to existing session ${E}.`:(j+=`Background ${a} subagent spawned successfully.`,E&&"unknown"!==E&&"spawning"!==E&&(j+=`\n[SESSION:${E}]`)),l&&(j+="\nWorking on: "+l),j+="\n\nThe subagent is now working independently. You can continue with other tasks.",{content:[{type:"text",text:j}]}}async function s(e,t,r,n,o,s,i){const a=await(0,b.getServerUrl)(r,n)
|
|
1256
1256
|
if(!a)throw new w.ValidationError("Could not determine OpenCode server URL")
|
|
1257
|
-
if(n.info("Sending message to subagent session",{sessionId:e,promptLength:t.length}),o)try{const t=i?.sessionId||(0,
|
|
1257
|
+
if(n.info("Sending message to subagent session",{sessionId:e,promptLength:t.length}),o)try{const t=i?.sessionId||(0,v.getCachedSession)()?.sessionId||await(0,b.discoverParentSessionId)(a,n)
|
|
1258
1258
|
if(t){const r=o.getCLISessionClient()
|
|
1259
1259
|
if(r){let o=await r.getByExternalId(t)
|
|
1260
|
-
o||(o=await r.createOrUpdateSession({externalSessionId:t,providerId:"opencode",status:"active"}),n.info("Created caller session in DB for re-parenting",{callerSessionId:t,dbId:o?.id})),o&&(await r.createOrUpdateSession({externalSessionId:e,providerId:"opencode",parentSessionId:o.id,status:"active"}),n.info("Updated parent session for reused agent",{sessionId:e,newParentSessionId:t}))}}}catch(e){n.warn("Failed to update parent session - reports may go to wrong parent",{error:(0,
|
|
1261
|
-
if(!c)try{const t=`http://localhost:${
|
|
1260
|
+
o||(o=await r.createOrUpdateSession({externalSessionId:t,providerId:"opencode",status:"active"}),n.info("Created caller session in DB for re-parenting",{callerSessionId:t,dbId:o?.id})),o&&(await r.createOrUpdateSession({externalSessionId:e,providerId:"opencode",parentSessionId:o.id,status:"active"}),n.info("Updated parent session for reused agent",{sessionId:e,newParentSessionId:t}))}}}catch(e){n.warn("Failed to update parent session - reports may go to wrong parent",{error:(0,q.getErrorMessage)(e)})}let c=s
|
|
1261
|
+
if(!c)try{const t=`http://localhost:${R}/api/sessions/${encodeURIComponent(e)}/agent-type`,r=await fetch(t)
|
|
1262
1262
|
if(r.ok){const e=await r.json()
|
|
1263
1263
|
e.success&&e.agentType&&(c=e.agentType)}}catch{n.warn("Agent type lookup failed for session",{sessionId:e})}if(!c)throw new w.ValidationError(`Cannot continue session ${e}: unable to determine agent type. The session's agent type could not be looked up from the action server.`)
|
|
1264
1264
|
try{let r
|
|
1265
|
-
try{const e=await fetch(`http://localhost:${
|
|
1265
|
+
try{const e=await fetch(`http://localhost:${R}/api/project-settings`)
|
|
1266
1266
|
if(e.ok){const t=await e.json()
|
|
1267
1267
|
if(t.data?.defaultModel){const[e,...n]=t.data.defaultModel.split("/")
|
|
1268
1268
|
r={providerID:e,modelID:n.join("/")}}}}catch{}const o=`${a.replace(/\/$/,"")}/session/${e}/prompt_async`,s=await fetch(o,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({parts:[{type:"text",text:t}],...c?{agent:c}:{},...r?{model:r}:{}}),signal:AbortSignal.timeout(1e4)})
|
|
1269
1269
|
if(!s.ok){const e=await s.text().catch((()=>"Unknown error"))
|
|
1270
|
-
throw Error(`Failed to send message: ${s.status} ${e}`)}return n.info("Message sent to subagent session",{sessionId:e,agent:c}),{content:[{type:"text",text:`Message sent to session ${e}.\nThe subagent will process it in the background.`}]}}catch(e){throw Error("Failed to continue session: "+(0,
|
|
1270
|
+
throw Error(`Failed to send message: ${s.status} ${e}`)}return n.info("Message sent to subagent session",{sessionId:e,agent:c}),{content:[{type:"text",text:`Message sent to session ${e}.\nThe subagent will process it in the background.`}]}}catch(e){throw Error("Failed to continue session: "+(0,q.getErrorMessage)(e))}}function i(e){const t=Math.floor(e/1e3)
|
|
1271
1271
|
if(60>t)return t+"s"
|
|
1272
1272
|
const r=Math.floor(t/60)
|
|
1273
1273
|
return 60>r?`${r}m ${t%60}s`:`${Math.floor(r/60)}h ${r%60}m`}function a(e){const t=[]
|
|
@@ -1277,10 +1277,10 @@ const s=n.path||n.file||n.directory,i=n.needle||n.query||n.pattern
|
|
|
1277
1277
|
"string"==typeof s?o+=" "+(s.split("/").pop()||s):"string"==typeof i&&(o+=` "${i.length>30?i.slice(0,27)+"...":i}"`),t.push({name:o,state:e.state.status,time:r.info.time.created})}t.sort(((e,t)=>t.time-e.time))
|
|
1278
1278
|
const r=t.find((e=>"pending"===e.state||"running"===e.state)),n=t.filter((e=>"completed"===e.state||"error"===e.state)).slice(0,3),o=t.length>0?t[0].time:null
|
|
1279
1279
|
return{current:r?.name??null,recent:n.map((e=>e.name)),lastActivityTime:o}}function c(e){return 1e3>e?"<1s ago":6e4>e?Math.floor(e/1e3)+"s ago":36e5>e?Math.floor(e/6e4)+"m ago":Math.floor(e/36e5)+"h ago"}function l(e,t){const r=e||t,n=Date.now()-r
|
|
1280
|
-
return e&&
|
|
1280
|
+
return e&&j>n?{status:"working",detail:"last action "+c(n),isReady:!1}:n>x&&e?{status:"stalled",detail:"no activity for "+c(n),isReady:!0}:e?{status:"idle",detail:"no activity for "+c(n),isReady:!0}:{status:"idle",detail:"no tool activity",isReady:!0}}function d(e){let t=0,r=0,n=0
|
|
1281
1281
|
for(const o of e.trim().split("\n")){if(!o)continue
|
|
1282
1282
|
const[e,s]=o.split("\t")
|
|
1283
|
-
"-"!==e&&(t+=parseInt(e,10)||0),"-"!==s&&(r+=parseInt(s,10)||0),n++}return{additions:t,deletions:r,files:n}}async function u(e,r,n,o){const s=await(0,
|
|
1283
|
+
"-"!==e&&(t+=parseInt(e,10)||0),"-"!==s&&(r+=parseInt(s,10)||0),n++}return{additions:t,deletions:r,files:n}}async function u(e,r,n,o){const s=await(0,b.getServerUrl)(r,n)
|
|
1284
1284
|
if(!s)throw new w.ValidationError("Could not determine OpenCode server URL")
|
|
1285
1285
|
n.info("Checking status of subagent session",{sessionId:e})
|
|
1286
1286
|
try{const c=`${s.replace(/\/$/,"")}/session/${e}`,u=await fetch(c)
|
|
@@ -1305,12 +1305,12 @@ if(e.trim())return d(e)}try{const t=n(`git log main --merges --oneline -n 50 --g
|
|
|
1305
1305
|
if(t){const e=t.split("\n")[0].split(" ")[0],o=n(`git diff ${e}^1...${e} --numstat`,{cwd:r,encoding:"utf8"})
|
|
1306
1306
|
if(o.trim())return{...d(o),merged:!0}}}catch{}return null}catch{return null}}(_,r.basePath)
|
|
1307
1307
|
if(e){const t=e.additions+e.deletions,r=e.merged?" (merged)":""
|
|
1308
|
-
v=`\nDiff vs main (${_}): +${e.additions}/-${e.deletions} lines (${t} total) in ${e.files} file${1!==e.files?"s":""}${r}`}}return{content:[{type:"text",text:`Session ${e}\nTitle: ${h.title||"Untitled"}\nStatus: ${k} (${y.detail})\nReady for input: ${I?"Yes":"No"}\nAge: ${i(w)}\nTokens: ${b.toLocaleString()} (in: ${f.input.toLocaleString()}, out: ${f.output.toLocaleString()}${f.reasoning>0?", reasoning: "+f.reasoning.toLocaleString():""})${m}${C}${v}`}]}}catch(e){throw Error("Failed to check session status: "+(0,
|
|
1308
|
+
v=`\nDiff vs main (${_}): +${e.additions}/-${e.deletions} lines (${t} total) in ${e.files} file${1!==e.files?"s":""}${r}`}}return{content:[{type:"text",text:`Session ${e}\nTitle: ${h.title||"Untitled"}\nStatus: ${k} (${y.detail})\nReady for input: ${I?"Yes":"No"}\nAge: ${i(w)}\nTokens: ${b.toLocaleString()} (in: ${f.input.toLocaleString()}, out: ${f.output.toLocaleString()}${f.reasoning>0?", reasoning: "+f.reasoning.toLocaleString():""})${m}${C}${v}`}]}}catch(e){throw Error("Failed to check session status: "+(0,q.getErrorMessage)(e))}}async function h(e,t,r){const n=await(0,b.getServerUrl)(t,r)
|
|
1309
1309
|
if(!n)throw new w.ValidationError("Could not determine OpenCode server URL")
|
|
1310
1310
|
r.info("Aborting subagent session",{sessionId:e})
|
|
1311
1311
|
try{const t=`${n.replace(/\/$/,"")}/session/${e}/abort`,o=await fetch(t,{method:"POST"})
|
|
1312
1312
|
if(!o.ok){const e=await o.text().catch((()=>"Unknown error"))
|
|
1313
|
-
throw Error(`Failed to abort session: ${o.status} ${e}`)}return r.info("Session aborted",{sessionId:e}),{content:[{type:"text",text:`Session ${e} has been aborted.`}]}}catch(e){throw Error("Failed to abort session: "+(0,
|
|
1313
|
+
throw Error(`Failed to abort session: ${o.status} ${e}`)}return r.info("Session aborted",{sessionId:e}),{content:[{type:"text",text:`Session ${e} has been aborted.`}]}}catch(e){throw Error("Failed to abort session: "+(0,q.getErrorMessage)(e))}}async function g(e,t,r,n={}){const{activeOnly:o=!1,requestId:s,limit:c,minTokens:d,maxTokens:u,maxAgeHours:h}=n,g=await(0,b.getServerUrl)(e,t)
|
|
1314
1314
|
if(!g)throw new w.ValidationError("Could not determine OpenCode server URL")
|
|
1315
1315
|
t.info("Listing sessions",{filters:n})
|
|
1316
1316
|
try{const e=g.replace(/\/$/,"")+"/session",t=await fetch(e)
|
|
@@ -1346,7 +1346,7 @@ const C=t.title||"Untitled",_=C.length>50?C.slice(0,47)+"...":C
|
|
|
1346
1346
|
v.push({id:t.id,title:_,status:f,age:r,totalTokens:o,requestsInfo:y,allRequestIds:I,statusDetail:h.detail,specialization:m?.specialization??null,currentAction:i,recentActions:c})}if(0===v.length)return{content:[{type:"text",text:"No sessions match the specified filters."}]}
|
|
1347
1347
|
const C=c?v.slice(0,c):v,_=C.map((e=>{const t=e.specialization?"\n Specialization: "+e.specialization:"",r=e.currentAction?"\n Current: "+e.currentAction:"",n=e.recentActions.length>0?"\n Recent: "+e.recentActions.join(", "):""
|
|
1348
1348
|
return`\u2022 ${e.id}\n ${e.title}${t}\n Status: ${e.status} (${e.statusDetail}) | Age: ${i(e.age)} | ${e.totalTokens.toLocaleString()} tokens${e.requestsInfo}${r}${n}`})),E=c&&v.length>c?` (showing ${c} of ${v.length})`:""
|
|
1349
|
-
return{content:[{type:"text",text:`Found ${C.length} session${1!==C.length?"s":""}${E}:\n\n${_.join("\n\n")}`}]}}catch(e){throw Error("Failed to list sessions: "+(0,
|
|
1349
|
+
return{content:[{type:"text",text:`Found ${C.length} session${1!==C.length?"s":""}${E}:\n\n${_.join("\n\n")}`}]}}catch(e){throw Error("Failed to list sessions: "+(0,q.getErrorMessage)(e))}}var p,f=this&&this.__createBinding||(Object.create?function(e,t,r,n){void 0===n&&(n=r)
|
|
1350
1350
|
var o=Object.getOwnPropertyDescriptor(t,r)
|
|
1351
1351
|
o&&!("get"in o?!t.__esModule:o.writable||o.configurable)||(o={enumerable:!0,get(){return t[r]}}),Object.defineProperty(e,n,o)}:function(e,t,r,n){void 0===n&&(n=r),e[n]=t[r]}),m=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),y=this&&this.__importStar||(p=function(e){return p=Object.getOwnPropertyNames||function(e){var t=[]
|
|
1352
1352
|
for(var r in e)({}).hasOwnProperty.call(e,r)&&(t[t.length]=r)
|
|
@@ -1356,7 +1356,7 @@ if(null!=e)for(var r=p(e),n=0;n<r.length;n++)"default"!==r[n]&&f(t,e,r[n])
|
|
|
1356
1356
|
return m(t,e),t})
|
|
1357
1357
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleSpawn=o,exports.handleContinue=s,exports.handleCheckStatus=u,exports.handleAbort=h,exports.handleListSessions=g,exports.handleSubagentOperations=async function(e,t,r,n,i,a){const c=r.child({tool:"subagent_operations"}),l=n.startTimer("tool_execution_time")
|
|
1358
1358
|
try{if(e&&!e.operation&&(e.spawn?e.operation="spawn":e.continue?e.operation="continue":e.readMessages?e.operation="read-messages":e.listSessions?e.operation="list-sessions":e.prompt&&(e.agent||e.description)?e={operation:"spawn",spawn:{agent:e.agent||"coder",prompt:e.prompt,description:e.description||e.prompt.slice(0,60),requestId:e.requestId,allowParallel:e.allowParallel,useExistingSession:e.useExistingSession}}:e.sessionId&&e.prompt&&!e.spawn?e={operation:"continue",sessionId:e.sessionId,continue:{prompt:e.prompt}}:e.sessionId&&(e={operation:"check-status",sessionId:e.sessionId})),e?.spawn&&"string"==typeof e.spawn)try{e.spawn=JSON.parse(e.spawn)}catch{}if(e?.continue&&"string"==typeof e.continue)try{e.continue=JSON.parse(e.continue)}catch{}"spawn"===e?.operation&&e?.prompt&&!e?.spawn&&(e.spawn={agent:e.agent||"coder",prompt:e.prompt,description:e.description||e.prompt.slice(0,60),requestId:e.requestId},delete e.prompt,delete e.agent,delete e.description,delete e.requestId),"continue"===e?.operation&&e?.prompt&&!e?.continue&&(e.continue={prompt:e.prompt},delete e.prompt)
|
|
1359
|
-
const r=
|
|
1359
|
+
const r=E.validateArgs(e,_.SubagentOperationsSchema),{sessionId:d,operation:p}=r
|
|
1360
1360
|
let f
|
|
1361
1361
|
switch(c.info("Processing subagent_operations",{operation:p,sessionId:d}),p){case"spawn":f=await o(r.spawn,t,c,i,a)
|
|
1362
1362
|
break
|
|
@@ -1367,7 +1367,7 @@ break
|
|
|
1367
1367
|
case"abort":f=await h(d,t,c)
|
|
1368
1368
|
break
|
|
1369
1369
|
case"read-messages":const e=r.readMessages?.limit??1
|
|
1370
|
-
f=await async function(e,t,r,n){const o=await(0,
|
|
1370
|
+
f=await async function(e,t,r,n){const o=await(0,b.getServerUrl)(r,n)
|
|
1371
1371
|
if(!o)throw new w.ValidationError("Could not determine OpenCode server URL")
|
|
1372
1372
|
n.info("Reading messages from subagent session",{sessionId:e,limit:t})
|
|
1373
1373
|
try{const r=`${o.replace(/\/$/,"")}/session/${e}/message?limit=${t}`,n=await fetch(r)
|
|
@@ -1376,13 +1376,13 @@ throw Error("Failed to fetch messages: "+n.status)}const s=await n.json()
|
|
|
1376
1376
|
if(0===s.length)return{content:[{type:"text",text:`Session ${e} has no messages yet.`}]}
|
|
1377
1377
|
const i=s.map(((e,t)=>{const r="user"===e.info.role?"USER":"ASSISTANT",n=e.parts.filter((e=>"text"===e.type&&e.text)).map((e=>e.text)).join("\n"),o=n.length>5e3?n.slice(0,5e3)+"...[truncated]":n
|
|
1378
1378
|
return`[${t+1}] ${r} (${new Date(e.info.time.created).toLocaleTimeString()}):\n${o}`})).join("\n\n---\n\n")
|
|
1379
|
-
return{content:[{type:"text",text:`Session ${e} - Last ${s.length} messages:\n\n${i}`}]}}catch(e){throw Error("Failed to read messages: "+(0,
|
|
1379
|
+
return{content:[{type:"text",text:`Session ${e} - Last ${s.length} messages:\n\n${i}`}]}}catch(e){throw Error("Failed to read messages: "+(0,q.getErrorMessage)(e))}}(d,e,t,c)
|
|
1380
1380
|
break
|
|
1381
|
-
case"list-sessions":const n={activeOnly:r.listSessions?.activeOnly,requestId:r.listSessions?.requestId,limit:r.listSessions?.limit,minTokens:r.listSessions?.minTokens,maxTokens:r.listSessions?.maxTokens,maxAgeHours:r.listSessions?.maxAgeHours,parentSessionId:a?.sessionId||(0,
|
|
1381
|
+
case"list-sessions":const n={activeOnly:r.listSessions?.activeOnly,requestId:r.listSessions?.requestId,limit:r.listSessions?.limit,minTokens:r.listSessions?.minTokens,maxTokens:r.listSessions?.maxTokens,maxAgeHours:r.listSessions?.maxAgeHours,parentSessionId:a?.sessionId||(0,v.getCachedSession)()?.sessionId}
|
|
1382
1382
|
f=await g(t,c,i,n)
|
|
1383
1383
|
break
|
|
1384
|
-
default:throw new w.ValidationError("Unknown operation: "+p)}return l({success:!0}),n.incrementCounter(`subagent_operations_${p}_success`,1),f}catch(e){return c.error("Subagent operations failed",{error:e instanceof Error?e.stack:e+""}),l({success:!1}),n.incrementCounter("subagent_operations_errors",1),{content:[{type:"text",text:"Subagent operation failed: "+(0,
|
|
1385
|
-
const w=t(9860),k=t(8035),I=t(
|
|
1384
|
+
default:throw new w.ValidationError("Unknown operation: "+p)}return l({success:!0}),n.incrementCounter(`subagent_operations_${p}_success`,1),f}catch(e){return c.error("Subagent operations failed",{error:e instanceof Error?e.stack:e+""}),l({success:!1}),n.incrementCounter("subagent_operations_errors",1),{content:[{type:"text",text:"Subagent operation failed: "+(0,q.getErrorMessage)(e)}],isError:!0}}}
|
|
1385
|
+
const w=t(9860),k=t(8035),I=t(2424),b=t(7617),v=t(715),C=t(7280),_=t(6183),E=y(t(5967)),q=t(8824),S=t(9896),T=t(6928),P=t(8955),M=t(5671),R=3456,j=6e4,x=3e5},1791(e,exports,t){function r(e,t){return t.info("Creating project context middleware",{projectId:e}),(t,r,n)=>{"GET"===t.method&&(t.query.projectId=e),["POST","PATCH","PUT"].includes(t.method)&&t.body&&(t.body.projectId=e),n()}}var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
1386
1386
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.ProjectContext=void 0,exports.projectContextMiddleware=r
|
|
1387
1387
|
const o=n(t(9896)),s=n(t(6928)),i=t(4139),a=t(4055),c=t(8824)
|
|
1388
1388
|
exports.ProjectContext=class{constructor(e,t){this.projectId=null,this.initialized=!1,this.initializationInProgress=!1,this.initializationPromise=null,this.basePath=e,this.alchemyPath=s.default.join(e,i.ALCHEMY_DIR_NAME),this.projectFilePath=s.default.join(this.alchemyPath,"project.json"),this.logger=t.child({component:"project-context"}),this.logger.debug("Project context constructed",{basePath:this.basePath,alchemyPath:this.alchemyPath,projectFilePath:this.projectFilePath})}initialize(){return this.initialized&&this.projectId?(this.logger.info("Project context already initialized",{projectId:this.projectId}),Promise.resolve(this.projectId)):this.initializationInProgress&&this.initializationPromise?(this.logger.info("Project context initialization already in progress, reusing promise"),this.initializationPromise):(this.initializationInProgress=!0,this.logger.debug("Starting initialization",{basePath:this.basePath}),this.initializationPromise=this.doInitialize(),this.initializationPromise)}async doInitialize(){try{if(o.default.existsSync(this.alchemyPath))this.logger.debug("alchemy_lab directory already exists")
|
|
@@ -1716,7 +1716,15 @@ return D?.commitHash&&(L+="\nCommit: "+D.commitHash.substring(0,8)),N.requestId&
|
|
|
1716
1716
|
await n.createToolRecord({...r?{}:{taskId:e.taskId},projectId:t.projectId,type:"move-files",metadata:{status:"failed",timestamp:(new Date).toISOString(),operationCount:e.operations?.length||0,operations:e.operations||[],userComment:e.comment,error:(0,p.getErrorMessage)(o),errorDetails:o instanceof Error?o.stack:o+"",phase:I,attemptedTaskId:e.taskId,taskIdValidationFailed:r},note:"Failed to move files - "+(0,p.getErrorMessage)(o)})}catch(t){m.error("Failed to create failure record for move-files operation",{error:t instanceof Error?t.message:t+"",taskId:e.taskId,operationCount:e.operations?.length||0})}const s=Date.now()-y
|
|
1717
1717
|
if(i.recordValue("move_files_time",s),i.incrementCounter("move_files_errors",1),m.error("Error in move-files operation:",{error:(0,p.getErrorMessage)(o),time:s}),(w||k)&&e.taskId){I=d.FileOperationPhase.RECORD_UPDATE_FAILURE
|
|
1718
1718
|
try{await d.updateFileOperationRecords(e.taskId,w,k,e.operations?.[0]?.source||"unknown",b.recordType,"Failed to move files",{status:"failed",error:(0,p.getErrorMessage)(o),operationCount:e.operations?.length||0,operations:e.operations||[],userComment:e.comment},"Failed to move files",r,n,m,i,b.metricsPrefix)}catch(t){m.error("Failed to update record with failure status",{taskId:e.taskId,recordId:w,error:t instanceof Error?t.message:t+""})}}return d.handleFileOperationError(o,I,m,i,e,b)}}
|
|
1719
|
-
const a=i(t(1943)),c=i(t(6928)),l=t(6183),d=s(t(5967)),u=t(9860),h=t(1569),g=t(7478),p=t(8824)},2422(module){module.exports=require("@modelcontextprotocol/sdk/server/sse.js")},
|
|
1719
|
+
const a=i(t(1943)),c=i(t(6928)),l=t(6183),d=s(t(5967)),u=t(9860),h=t(1569),g=t(7478),p=t(8824)},2422(module){module.exports=require("@modelcontextprotocol/sdk/server/sse.js")},2424(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.ensureRequestWorktree=async function(e,t,i){const a="requests/"+t,c=(0,n.join)(e,s.ALCHEMY_DIR_NAME,"worktrees"),l=(0,n.join)(c,t)
|
|
1720
|
+
if((0,r.existsSync)(l))return void i.info("Worktree already exists on disk, skipping pre-spawn creation",{requestId:t,worktreePath:l})
|
|
1721
|
+
const d=(0,o.simpleGit)(e);(0,r.mkdirSync)(c,{recursive:!0})
|
|
1722
|
+
try{await d.raw(["worktree","prune"])}catch{}const u=await d.branch(),h=u.all.includes(a)
|
|
1723
|
+
try{if(h)await d.raw(["worktree","add",l,a]),i.info("Pre-spawn: created worktree for existing branch",{requestId:t,branchName:a,worktreePath:l})
|
|
1724
|
+
else{const e=u.all.includes("main")?"main":"master"
|
|
1725
|
+
await d.raw(["worktree","add","-b",a,l,e]),i.info("Pre-spawn: created worktree with new branch from latest main",{requestId:t,branchName:a,mainBranch:e,worktreePath:l})}}catch(e){const r=e instanceof Error?e.message:e+""
|
|
1726
|
+
i.warn("Pre-spawn: failed to create worktree (MCP process will retry)",{requestId:t,error:r})}}
|
|
1727
|
+
const r=t(9896),n=t(6928),o=t(3807),s=t(4139)},2425(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.def=void 0
|
|
1720
1728
|
const r=t(6183),n=t(3707)
|
|
1721
1729
|
exports.def={name:"quick_manage",description:"Move, delete, or create directories. Wraps the change in a request/task workflow that auto-completes.\n\nProvide an array of operations, each with operationType and corresponding data:\n\u2022 create-directory: { createDirectory: { path } }\n\u2022 move-files: { moveFiles: { moves: [{ source, destination }] } }\n\u2022 delete-files: { deleteFiles: { targets: [{ path }] } }\n\nFor read-only operations like get-file-info, use manage_files instead.\n\nRequires: title, description, operations.",schema:r.QuickManageSchema,annotations:{title:"Quick Manage",readOnlyHint:!1,destructiveHint:!0,idempotentHint:!1},handler(e,t){return(0,n.handleQuickChange)(e,"manage",t.context,t.apiClient,t.logger,t.metrics,t.mcpServer)}}},2462(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0})
|
|
1722
1730
|
const r=t(2245),n=t(9080),o=t(5692),s=t(9030),i=t(2903),a=t(4607),c=t(9499),l=t(6770),d=t(8045),u=t(9697),h=t(9196),g=t(5459),p=t(4805),f=t(260),m=t(2283),y=t(4165),w=t(7834),k=t(9373),I=t(6111),b=t(700),v=t(2783),C=t(2601),_=t(1722),E=t(7257),q=t(9230),S=t(5216),T=t(6473),P=t(4921),M=t(8850),R=t(3556),j=t(1391),x=t(6315),O=t(7713),A=t(6252),D=t(213),$=t(7250),F=t(2425),N=t(1540),L=t(5767),z=t(4973),B=t(7613),H=t(3322),W=t(5247),U=t(542);(0,r.registerTool)(n.def),(0,r.registerTool)(o.def),(0,r.registerTool)(s.def),(0,r.registerTool)(i.def),(0,r.registerTool)(a.def),(0,r.registerTool)(c.def),(0,r.registerTool)(l.def),(0,r.registerTool)(d.def),(0,r.registerTool)(u.def),(0,r.registerTool)(h.def),(0,r.registerTool)(g.def),(0,r.registerTool)(p.def),(0,r.registerTool)(f.def),(0,r.registerTool)(m.def),(0,r.registerTool)(y.def),(0,r.registerTool)(w.def),(0,r.registerTool)(k.def),(0,r.registerTool)(I.def),(0,r.registerTool)(b.def),(0,r.registerTool)(v.def),(0,r.registerTool)(C.def),(0,r.registerTool)(_.def),(0,r.registerTool)(E.def),(0,r.registerTool)(q.def),(0,r.registerTool)(S.def),(0,r.registerTool)(T.def),(0,r.registerTool)(P.def),(0,r.registerTool)(M.def),(0,r.registerTool)(R.def),(0,r.registerTool)(j.def),(0,r.registerTool)(x.def),(0,r.registerTool)(O.def),(0,r.registerTool)(A.def),(0,r.registerTool)(D.def),(0,r.registerTool)($.def),(0,r.registerTool)(F.def),(0,r.registerTool)(N.def),(0,r.registerTool)(L.def),(0,r.registerTool)(z.def),(0,r.registerTool)(B.def),(0,r.registerTools)(H.metaDefs),(0,r.registerTools)(W.testingDefs),(0,r.registerTools)(U.debugDefs),(0,t(2245).freezeRegistry)()},2478(e,exports){Object.defineProperty(exports,"__esModule",{value:!0}),exports.requestConfig=void 0,exports.areTestsRequiredForCompletion=function(){return exports.requestConfig.requireTestsForCompletion},exports.setTestsRequiredForCompletion=function(e){exports.requestConfig.requireTestsForCompletion=e},exports.getCompletionMode=function(e){return e&&["auto-merge","auto-test-then-merge","manual-review"].includes(e)?e:"auto-merge"},exports.getApprovalMode=function(e){return e&&["none","require-approval"].includes(e)?e:"none"},exports.requestConfig={requireTestsForCompletion:!1}},2537(e,exports,t){async function r(e,t,r){if(C.has(r)&&_>=t){if(0===t)return 0
|
|
@@ -4430,12 +4438,9 @@ this.logger.info("ALCHEMY_INITIAL_BRANCH set, switching to worktree",{initialBra
|
|
|
4430
4438
|
try{await this.ensureWorkspaceReady(r),this.readonlyBranchCheckDone=!0,this.logger.info("Successfully switched to worktree from ALCHEMY_INITIAL_BRANCH",{requestId:r,worktreePath:this.currentWorktreePath})}catch(t){this.logger.warn("Failed to switch to worktree from ALCHEMY_INITIAL_BRANCH",{initialBranch:e,requestId:r,error:(0,i.getErrorMessage)(t)})}}hasExactConflictMarkers(e){return!(!e||!e.trim())&&[/^\s*<{7}(?:\s|$)/m,/^\s*={7}(?:\s|$)/m,/^\s*>{7}(?:\s|$)/m].some((t=>t.test(e)))}async initializeWorktreeManager(){try{await this.worktreeManager.initialize(),this.logger.debug("Initialized multi-agent workspace manager with worktrees")}catch(e){throw this.logger.error("Failed to initialize worktree manager",{error:e}),e}}setTaskCreator(e){this.taskCreator=e}async initializeRequest(e,t){const r=Date.now(),n=a.WorkspaceValidation.validateRequestId(e)
|
|
4431
4439
|
if(!n.isValid)throw Error("Invalid request ID: "+n.errors.join(", "))
|
|
4432
4440
|
const o=n.sanitized
|
|
4433
|
-
try{
|
|
4434
|
-
const
|
|
4435
|
-
|
|
4436
|
-
await this.mainGit.checkout(["-b",n,t]),this.logger.info("Created branch for request",{requestId:o,branchName:n,fromBranch:t}),await this.mainGit.checkout(e),this.logger.info("Returned to original branch after creation",{returnedTo:e,createdBranch:n})}this.workspaceStates.set(o,"initialized")
|
|
4437
|
-
const i=Date.now()-r
|
|
4438
|
-
this.metrics.recordValue("workspace.initialize",i),a.WorkspaceLogging.logOperation(this.logger,"info","Successfully initialized request with branch (no worktree)",e,"multi-agent","initializeRequest",{branchName:n,branchExisted:s,duration:i,architecture:"hybrid-creation"})}catch(t){const n=Date.now()-r
|
|
4441
|
+
try{this.workspaceStates.set(o,"initialized")
|
|
4442
|
+
const t=Date.now()-r
|
|
4443
|
+
this.metrics.recordValue("workspace.initialize",t),a.WorkspaceLogging.logOperation(this.logger,"info","Successfully initialized request (branch deferred)",e,"multi-agent","initializeRequest",{duration:t,architecture:"hybrid-creation"})}catch(t){const n=Date.now()-r
|
|
4439
4444
|
throw this.metrics.recordValue("workspace.initialize",n),a.WorkspaceLogging.logOperation(this.logger,"error","Failed to initialize request",e,"multi-agent","initializeRequest",{error:(0,i.getErrorMessage)(t),duration:n}),t}}async ensureWorkspaceReady(e){const t=Date.now(),r=a.WorkspaceValidation.validateRequestId(e)
|
|
4440
4445
|
if(!r.isValid)throw Error("Invalid request ID: "+r.errors.join(", "))
|
|
4441
4446
|
const n=r.sanitized
|
|
@@ -4483,17 +4488,19 @@ try{this.currentRequestId===r&&await this.switchToMain()
|
|
|
4483
4488
|
const e=await this.worktreeManager.removeWorktree(r,!1)
|
|
4484
4489
|
if(!e.success)throw Error(e.message||"Failed to remove worktree")
|
|
4485
4490
|
this.logger.info("Successfully cancelled request",{requestId:r})}catch(e){throw this.logger.error("Failed to cancel request",{requestId:r,error:(0,i.getErrorMessage)(e)}),e}}getCurrentContext(){const e={requestId:this.currentRequestId,basePath:this.currentWorktreePath||this.basePath,branchName:this.currentRequestId?"requests/"+this.currentRequestId:"main",isMainBranch:!this.currentRequestId,mode:"multi-agent"}
|
|
4486
|
-
return this.logger.debug("getCurrentContext returning",{context:e}),e}resetCurrentContext(){this.currentRequestId&&this.logger.info("Resetting workspace context (session switch)",{prevRequestId:this.currentRequestId,prevWorktreePath:this.currentWorktreePath}),this.currentRequestId=null,this.currentWorktreePath=null,this.currentGit=this.mainGit}async getWorkspaceInfo(e){try{const t=a.WorkspaceValidation.validateRequestId(e)
|
|
4491
|
+
return this.logger.debug("getCurrentContext returning",{context:e}),e}resetCurrentContext(){this.currentRequestId&&this.logger.info("Resetting workspace context (session switch)",{prevRequestId:this.currentRequestId,prevWorktreePath:this.currentWorktreePath}),this.currentRequestId=null,this.currentWorktreePath=null,this.currentGit=this.mainGit,this.readonlyBranchCheckDone=!1}async getWorkspaceInfo(e){try{const t=a.WorkspaceValidation.validateRequestId(e)
|
|
4487
4492
|
if(!t.isValid)return null
|
|
4488
4493
|
const r=t.sanitized,n=await this.getWorktreeInfo(r)
|
|
4489
4494
|
return n?{requestId:r,path:n.worktreePath,branchName:n.branchName,isActive:this.currentRequestId===r,created:new Date,lastAccessed:new Date}:null}catch(t){return this.logger.error("Failed to get workspace info",{requestId:e,error:(0,i.getErrorMessage)(t)}),null}}async listActiveWorkspaces(){try{return(await this.worktreeManager.listActiveWorktrees()).map((e=>this.convertWorktreeInfoToWorkspaceInfo(e)))}catch(e){return this.logger.error("Failed to list active workspaces",{error:(0,i.getErrorMessage)(e)}),[]}}extractRequestIdFromBranch(e){const t=e.match(/^requests\/(.+)$/)
|
|
4490
4495
|
return t?t[1]:null}convertWorktreeInfoToWorkspaceInfo(e){return{requestId:e.requestId,path:e.worktreePath,branchName:e.branchName,isActive:this.currentRequestId===e.requestId,created:e.created,lastAccessed:e.lastAccessed}}async getWorktreeInfo(e){try{const t=e.replace(/[^a-zA-Z0-9_-]/g,"_")
|
|
4491
|
-
return this.worktreeManager.getWorktreeInfo(t)}catch(t){return void this.logger.warn("Failed to get worktree info",{requestId:e,error:(0,i.getErrorMessage)(t)})}}getMainGit(){return this.gitAdapter.getMainGit()}getCurrentGit(){return this.currentGit}async ensureReadonlyBranchIfNeeded(e,
|
|
4496
|
+
return this.worktreeManager.getWorktreeInfo(t)}catch(t){return void this.logger.warn("Failed to get worktree info",{requestId:e,error:(0,i.getErrorMessage)(t)})}}getMainGit(){return this.gitAdapter.getMainGit()}getCurrentGit(){return this.currentGit}async ensureReadonlyBranchIfNeeded(e,r,n,o){if(this.readonlyBranchCheckDone)return
|
|
4492
4497
|
this.readonlyBranchCheckDone=!0
|
|
4493
|
-
const
|
|
4494
|
-
if(
|
|
4498
|
+
try{const{sessionIdentity:e}=await Promise.resolve().then(t.bind(t,6688)),r=e.getIdentity()
|
|
4499
|
+
if(r&&n){const t=await e.getSessionRequestId(n,this.logger)
|
|
4500
|
+
if(t)return await this.ensureWorkspaceReady(t),void this.logger.info("ensureReadonlyBranchIfNeeded: workspace ready from session DB lookup",{requestId:t,sessionId:r.sessionId})}}catch(e){this.logger.warn("ensureReadonlyBranchIfNeeded: session DB lookup failed, falling back to env var",{error:(0,i.getErrorMessage)(e)})}const s=process.env.ALCHEMY_INITIAL_BRANCH
|
|
4501
|
+
if(s){const e=s.match(/^requests\/(.+)$/)
|
|
4495
4502
|
if(e){const t=e[1]
|
|
4496
|
-
try{await this.ensureWorkspaceReady(t),this.logger.info("ensureReadonlyBranchIfNeeded: workspace ready",{requestId:t})}catch(e){this.logger.warn("ensureReadonlyBranchIfNeeded: failed to ensure workspace",{requestId:t,error:(0,i.getErrorMessage)(e)})}}}}async cleanup(){this.logger.info("Cleaning up multi-agent workspace manager"),this.currentRequestId=null,this.currentWorktreePath=null,this.currentGit=this.mainGit}}},7645(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.ConnectionAwareClient=void 0
|
|
4503
|
+
try{await this.ensureWorkspaceReady(t),this.logger.info("ensureReadonlyBranchIfNeeded: workspace ready from env var",{requestId:t})}catch(e){this.logger.warn("ensureReadonlyBranchIfNeeded: failed to ensure workspace",{requestId:t,error:(0,i.getErrorMessage)(e)})}}}}async cleanup(){this.logger.info("Cleaning up multi-agent workspace manager"),this.currentRequestId=null,this.currentWorktreePath=null,this.currentGit=this.mainGit}}},7645(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.ConnectionAwareClient=void 0
|
|
4497
4504
|
const r=t(4192),n=t(7163)
|
|
4498
4505
|
class o extends r.BaseApiClient{constructor(e,t,r,o,s,i){t.debug("ConnectionAwareClient constructor parameters:",{hasAuthToken:!!o,hasOptions:!!s,optionsType:s?typeof s:"undefined",options:s?JSON.stringify(s):"undefined",hasConnectionManager:!!i}),super(e,t,r,o,s),this.isGettingAuthToken=!1,this.connectionStatusManager=i||{isInOfflineMode(){return!1},isOffline(){return!1},setOfflineMode(){},async checkConnectivity(){return!0},getHealthCheckStats(){return{isOffline:!1,consecutiveFailures:0,currentBackoffMs:0,lastCheckTime:0}},cleanup(){}},o&&this.logger.debug("Client initialized with auth token",{clientType:this.constructor.name,tokenPrefix:o.substring(0,10)+"..."})
|
|
4499
4506
|
try{(0,n.debugTokenAccess)(this,"ConnectionAwareClient constructor")}catch(e){this.logger.debug("Error accessing token details during init",{error:e instanceof Error?e.message:e+""})}}setConnectionStatusManager(e){this.logger.debug("Setting connection status manager in ConnectionAwareClient"),this.connectionStatusManager=e}}exports.ConnectionAwareClient=o},7660(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.projectContextMiddleware=exports.ProjectContext=exports.ProjectIDFactory=exports.ProjectID=void 0
|