alchemylab 1.0.7 → 1.0.8
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/939.js +3 -3
- package/dist/cli.js +121 -102
- package/dist/http-server.js +663 -707
- package/dist/index.js +559 -603
- package/dist/mcp-direct.js +974 -1018
- package/package.json +3 -2
package/dist/http-server.js
CHANGED
|
@@ -20,13 +20,13 @@ const f={requestId:a.requestId,projectId:l,title:a.title,description:a.descripti
|
|
|
20
20
|
u.info("Task input prepared",{taskInput:JSON.stringify(f)}),u.info("Creating task via task client",{projectId:l,requestId:a.requestId,title:a.title})
|
|
21
21
|
const m=await p.createTask(f)
|
|
22
22
|
u.debug("Task creation response structure",{type:typeof m,isArray:Array.isArray(m),hasData:null!=m,properties:m?Object.keys(m):[],dataPreview:m?JSON.stringify(m).substring(0,200)+"...":"null"})
|
|
23
|
-
const y=(0,o.extractDataFromResponse)(m,{logger:u,operationName:"createTask",defaultValue:{id:"tas"+Date.now().toString().substring(5,11),title:f.title,description:f.description,status:"pending",requestId:f.requestId,projectId:l,createdAt:(new Date).toISOString(),updatedAt:(new Date).toISOString()}}),w="data"in y?y.data:y,k=w.localId||w.id||"tas"+Date.now().toString().substring(5,11),
|
|
23
|
+
const y=(0,o.extractDataFromResponse)(m,{logger:u,operationName:"createTask",defaultValue:{id:"tas"+Date.now().toString().substring(5,11),title:f.title,description:f.description,status:"pending",requestId:f.requestId,projectId:l,createdAt:(new Date).toISOString(),updatedAt:(new Date).toISOString()}}),w="data"in y?y.data:y,k=w.localId||w.id||"tas"+Date.now().toString().substring(5,11),b=w.title||f.title,I=w.description||f.description,v=w.status||"pending",C=w.requestId||f.requestId
|
|
24
24
|
let _,E="unknown"
|
|
25
|
-
w&&"object"==typeof w&&"_workingEndpoint"in w&&(E=w._workingEndpoint),u.info("Successfully extracted task data from response",{taskId:k,requestId:C,title:
|
|
25
|
+
w&&"object"==typeof w&&"_workingEndpoint"in w&&(E=w._workingEndpoint),u.info("Successfully extracted task data from response",{taskId:k,requestId:C,title:b})
|
|
26
26
|
try{const e=i.getToolRecordClient()
|
|
27
|
-
if(e){const t=await e.createToolRecord({taskId:k,requestId:C,projectId:l,type:"create-task",metadata:{status:"completed",timestamp:(new Date).toISOString(),taskTitle:
|
|
28
|
-
_=t?.id}}catch(e){u.error("Failed to create tool record for task creation, but continuing",{error:e instanceof Error?e.stack:e+"",taskId:k,requestId:C})}h({success:!0,requestId:a.requestId,projectId:l}),u.info("Task created successfully",{taskId:k,requestId:C,title:
|
|
29
|
-
let q=`Created Task ${k}: ${
|
|
27
|
+
if(e){const t=await e.createToolRecord({taskId:k,requestId:C,projectId:l,type:"create-task",metadata:{status:"completed",timestamp:(new Date).toISOString(),taskTitle:b,taskDescription:I,taskStatus:v},note:"Created task "+b})
|
|
28
|
+
_=t?.id}}catch(e){u.error("Failed to create tool record for task creation, but continuing",{error:e instanceof Error?e.stack:e+"",taskId:k,requestId:C})}h({success:!0,requestId:a.requestId,projectId:l}),u.info("Task created successfully",{taskId:k,requestId:C,title:b,projectId:l})
|
|
29
|
+
let q=`Created Task ${k}: ${b}`
|
|
30
30
|
return _&&(q+=`\n[RECORD:${_}]`),{content:[{type:"text",text:q}]}}catch(r){if(u.error("Failed to create task",{error:r instanceof Error?r.stack:r+"",args:e}),t.projectId)try{if(r instanceof Error&&(r.message.includes("Project is disabled")||r.message.includes("Project cannot accept new tasks")||r.message.includes("disabled due to tier limits")||r.message.includes("Project is inactive due to tier limits")))u.info("Skipping tool record creation for disabled project error",{projectId:t.projectId,error:r.message})
|
|
31
31
|
else{const n=i.getToolRecordClient()
|
|
32
32
|
n&&await n.createToolRecord({requestId:e.requestId,projectId:t.projectId,type:"create-task",metadata:{status:"failed",timestamp:(new Date).toISOString(),taskTitle:e.title,taskDescription:e.description?.substring(0,100)+(e.description?.length>100?"...":""),error:(0,s.getErrorMessage)(r),errorDetails:r instanceof Error?r.stack:r+""},note:"Failed to create task: "+e.title})}}catch(e){u.error("Failed to create failure record for task creation",{error:e instanceof Error?e.message:e+""})}h({success:!1,error:r instanceof Error?r.name:"unknown"})
|
|
@@ -44,19 +44,19 @@ var t={}
|
|
|
44
44
|
if(null!=e)for(var r=n(e),i=0;i<r.length;i++)"default"!==r[i]&&o(t,e,r[i])
|
|
45
45
|
return s(t,e),t}),a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
46
46
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.McpServer=void 0,exports.resetStdoutWrite=function(){process.stdout.write=x},exports.getMcpServer=r,exports.createServer=function(e,t,n,o,s={}){return r(e,t,n,o,s)}
|
|
47
|
-
const c=t(3807),l=t(8909),d=a(t(6928)),u=a(t(9896)),h=a(t(1943)),g=t(9567),p=t(3444),f=t(7660),m=t(1253),y=t(5172),w=t(7976),k=i(t(7478)),
|
|
48
|
-
!(0,p.isDebugToolsEnabled)()||O&&"true"!==process.env.DEBUG_STDOUT_CAPTURE||(process.stdout.write=function(e){try{return(0,p.isDebugToolsEnabled)()&&"true"===process.env.DEBUG_LOGGING?.toLowerCase()&&"string"==typeof e&&!e.trim().startsWith('{"jsonrpc":"2.0"')&&e.trim().length>0&&
|
|
49
|
-
class A{constructor(e,t,r,n,o={}){this.git=null,this.currentSSEConnection=null,this.stdioTransport=null,this.clientInfo=null,this.isInitializing=!1,this.isInitialized=!1,this.logger=t.child({component:"mcp-server"}),this.multiAgentMode=o.multiAgentMode||!1,this.logger.info("Creating McpServer instance",{basePath:e,remoteServerUrl:n,multiAgentMode:o.multiAgentMode||!1,hasExistingProjectId:!!o.existingProjectId}),this.basePath=e,this.alchemyPath=d.default.join(e,
|
|
47
|
+
const c=t(3807),l=t(8909),d=a(t(6928)),u=a(t(9896)),h=a(t(1943)),g=t(9567),p=t(3444),f=t(7660),m=t(1253),y=t(5172),w=t(7976),k=i(t(7478)),b=t(4139),I=new Set,v=t(9860),C=t(1472),_=t(3328),E=t(8955),q=t(3217),S=t(8411),T=t(5278),P=t(446),M=t(9060),j=t(8824),R=(0,p.createLogger)({serviceName:"stdout-capture",console:!1,logToFile:!1}),x=process.stdout.write,O=process.argv.includes("--stdio")||"true"===process.env.MCP_DIRECT_MODE
|
|
48
|
+
!(0,p.isDebugToolsEnabled)()||O&&"true"!==process.env.DEBUG_STDOUT_CAPTURE||(process.stdout.write=function(e){try{return(0,p.isDebugToolsEnabled)()&&"true"===process.env.DEBUG_LOGGING?.toLowerCase()&&"string"==typeof e&&!e.trim().startsWith('{"jsonrpc":"2.0"')&&e.trim().length>0&&R.debug("Stdout output",{content:e.substring(0,100),length:e.length}),x.call(process.stdout,e)}catch(e){return R.error("Error in safeStdoutWrite",{error:e+""}),!0}})
|
|
49
|
+
class A{constructor(e,t,r,n,o={}){this.git=null,this.currentSSEConnection=null,this.stdioTransport=null,this.clientInfo=null,this.isInitializing=!1,this.isInitialized=!1,this.logger=t.child({component:"mcp-server"}),this.multiAgentMode=o.multiAgentMode||!1,this.logger.info("Creating McpServer instance",{basePath:e,remoteServerUrl:n,multiAgentMode:o.multiAgentMode||!1,hasExistingProjectId:!!o.existingProjectId}),this.basePath=e,this.alchemyPath=d.default.join(e,b.ALCHEMY_DIR_NAME),this.metrics=r,this.remoteServerUrl=n,this.existingProjectId=o.existingProjectId,this.gitBinary=(0,l.detectGitBinary)(),this.logger.info("Detected git binary",{gitBinary:this.gitBinary,version:(0,l.getGitVersion)()}),this.projectContext=new f.ProjectContext(e,t),this.tokenManager=new m.TokenManager(t,e,{remoteServerUrl:n}),this.lockOverrideManager=new P.LockOverrideManager(t),this.configManager=new M.ConfigManager(t),this.logger.debug("Server paths initialized",{basePath:this.basePath,alchemyPath:this.alchemyPath}),this.server=new g.Server({name:"alchemy",version:"1.0.0"},{capabilities:{tools:{search:{},create_request:{},complete_task:{},get_task_information:{},complete_request:{},revert_request:{},get_request_information:{},list_tasks:{},list_requests:{},switch_to_branch:{},read_files:{},create_directory:{},move_files:{},write_file:{},replace_strings:{},insert_lines:{},replace_lines:{},delete_files:{},document_operations:{},file_history:{},task_file_history:{},request_file_history:{},quick_write:{},quick_replace:{},quick_manage:{}}}}),this.metrics.incrementCounter("mcp_server_init_started",1),this.interceptConnectMethod(),this.logger.info("Starting initialization for server instance"),this.initializationPromise=this.initialize()}get branchState(){if(!this.workspaceManager)return{currentBranch:null,activeRequestId:null,isOnMainBranch:!0}
|
|
50
50
|
const e=this.workspaceManager.getCurrentContext()
|
|
51
51
|
return{currentBranch:e.branchName,activeRequestId:e.requestId,isOnMainBranch:e.isMainBranch}}async updateBranchState(e,t){this.logger.debug("updateBranchState called - managed by WorkspaceManager",{branch:e,requestId:t})}async getCurrentBranchContext(){if(!this.workspaceManager)return{branch:null,requestId:null,isMain:!0}
|
|
52
52
|
const e=this.workspaceManager.getCurrentContext()
|
|
53
53
|
return{branch:e.branchName,requestId:e.requestId,isMain:e.isMainBranch}}async syncBranchState(){this.logger.debug("syncBranchState called - managed by WorkspaceManager")}async switchToMainContext(){return this.workspaceManager?this.workspaceManager.switchToMain():{success:!1,message:"WorkspaceManager not available"}}getCurrentRequestId(){return this.workspaceManager?.getCurrentContext().requestId||null}async getNextId(e){try{const t=this.metrics.startTimer("remote_id_generation"),r=this.apiClient.getProjectClient()
|
|
54
54
|
if(!r||"function"!=typeof r.getNextId)throw Error("Project client or getNextId method not available")
|
|
55
55
|
const n=await r.getNextId(e)
|
|
56
|
-
return t({success:!0,type:e}),this.metrics.incrementCounter("remote_id_success",1,{type:e}),n}catch(t){throw this.metrics.incrementCounter("remote_id_failure",1,{type:e,error:t instanceof Error?t.name:"unknown"}),this.logger.warn("Failed to get ID from remote server, unable to perform operation",{type:e,error:(0,
|
|
56
|
+
return t({success:!0,type:e}),this.metrics.incrementCounter("remote_id_success",1,{type:e}),n}catch(t){throw this.metrics.incrementCounter("remote_id_failure",1,{type:e,error:t instanceof Error?t.name:"unknown"}),this.logger.warn("Failed to get ID from remote server, unable to perform operation",{type:e,error:(0,j.getErrorMessage)(t)}),Error("Failed to get ID from remote server.")}}async initialize(){const e=this.remoteServerUrl||"https://api.alchemylabcode.com"
|
|
57
57
|
this.logger.debug("Using remote server URL",{remoteServerUrl:e})
|
|
58
58
|
const t=d.default.resolve(this.basePath)
|
|
59
|
-
if(
|
|
59
|
+
if(I.has(t))return this.logger.info("Path already initialized in global registry, skipping initialization",{path:t}),void(this.isInitialized=!0)
|
|
60
60
|
if(this.isInitialized)this.logger.info("Server already initialized, skipping initialization")
|
|
61
61
|
else{if(this.isInitializing)return this.logger.info("Initialization already in progress, waiting..."),void await this.initializationPromise
|
|
62
62
|
this.isInitializing=!0,this.logger.info("SERVER INITIALIZATION STARTING",{path:t,pid:process.pid,time:(new Date).toISOString()}),this.metrics.setGauge("mcp_initialization",0,{status:"starting"})
|
|
@@ -67,12 +67,12 @@ try{this.logger.info("Validating git repository for branch management...")
|
|
|
67
67
|
const e=await k.validateGitRepository(this.git,this.logger,this.metrics)
|
|
68
68
|
if(e.isGitRepository){this.logger.info("Git repository validation completed",{currentBranch:e.currentBranch,isClean:e.isClean,defaultBranch:e.defaultBranch,branchCount:e.branches.length,hasMainBranch:e.hasMainBranch,hasMasterBranch:e.hasMasterBranch})
|
|
69
69
|
const t=[],r=[]
|
|
70
|
-
e.currentBranch||(t.push("Repository is in detached HEAD state"),r.push("Switch to a proper branch: git checkout main")),e.isClean||(t.push(`Repository has ${e.uncommittedChanges.length} uncommitted changes`),r.push("Commit or stash changes before creating requests")),e.defaultBranch||(t.push("No default branch (main/master) found"),r.push("Create a default branch: git checkout -b main")),t.length>0?this.logger.warn("Git repository has potential issues for branch management",{issues:t,recommendations:r}):this.logger.info("Git repository is ready for automatic branch management"),this.metrics.setGauge("git_repository_ready",0===t.length?1:0),this.metrics.setGauge("git_repository_branch_count",e.branches.length),this.metrics.incrementCounter("git_repository_validation_success",1)}else this.logger.error("Git repository validation failed - not a valid git repository"),this.metrics.incrementCounter("git_repository_validation_failed",1)}catch(e){this.logger.warn("Git repository validation encountered an error",{error:e instanceof Error?e.message:e+""}),this.metrics.incrementCounter("git_repository_validation_error",1)}}async ensureGitignoreWithAlchemyLab(){const e=d.default.join(this.basePath,".gitignore"),t=
|
|
70
|
+
e.currentBranch||(t.push("Repository is in detached HEAD state"),r.push("Switch to a proper branch: git checkout main")),e.isClean||(t.push(`Repository has ${e.uncommittedChanges.length} uncommitted changes`),r.push("Commit or stash changes before creating requests")),e.defaultBranch||(t.push("No default branch (main/master) found"),r.push("Create a default branch: git checkout -b main")),t.length>0?this.logger.warn("Git repository has potential issues for branch management",{issues:t,recommendations:r}):this.logger.info("Git repository is ready for automatic branch management"),this.metrics.setGauge("git_repository_ready",0===t.length?1:0),this.metrics.setGauge("git_repository_branch_count",e.branches.length),this.metrics.incrementCounter("git_repository_validation_success",1)}else this.logger.error("Git repository validation failed - not a valid git repository"),this.metrics.incrementCounter("git_repository_validation_failed",1)}catch(e){this.logger.warn("Git repository validation encountered an error",{error:e instanceof Error?e.message:e+""}),this.metrics.incrementCounter("git_repository_validation_error",1)}}async ensureGitignoreWithAlchemyLab(){const e=d.default.join(this.basePath,".gitignore"),t=b.ALCHEMY_DIR_NAME+"/"
|
|
71
71
|
try{if(u.default.existsSync(e)){const r=await h.default.readFile(e,"utf8")
|
|
72
|
-
if(r.split("\n").some((e=>e.trim()===t||e.trim()===t.slice(0,-1))))this.logger.info(
|
|
72
|
+
if(r.split("\n").some((e=>e.trim()===t||e.trim()===t.slice(0,-1))))this.logger.info(b.ALCHEMY_DIR_NAME+"/ already present in .gitignore")
|
|
73
73
|
else{const n=r.trimEnd()+"\n\n# AlchemyMCP working directory\n"+t+"\n"
|
|
74
|
-
await h.default.writeFile(e,n),this.logger.info(`Added ${
|
|
75
|
-
await h.default.writeFile(e,r),this.logger.info(`Created new .gitignore with ${
|
|
74
|
+
await h.default.writeFile(e,n),this.logger.info(`Added ${b.ALCHEMY_DIR_NAME}/ to existing .gitignore`)}}else{const r=["# Dependency directories\nnode_modules/\n.npm\n.yarn\n\n# Build outputs\ndist/\nbuild/\n\n# Logs\nlogs/\n*.log\n\n# Editor files\n.DS_Store\n.vscode/\n.idea/\n\n# Environment variables\n.env\n.env.local\n\n# AlchemyMCP working directory",t,""].join("\n")
|
|
75
|
+
await h.default.writeFile(e,r),this.logger.info(`Created new .gitignore with ${b.ALCHEMY_DIR_NAME}/ entry`)}}catch(e){this.logger.warn("Failed to update .gitignore file",{error:(0,j.getErrorMessage)(e)})}}async initializeGitRepo(){try{this.logger.info("Initializing git repository"),await this.git.init(),await this.ensureGitignoreWithAlchemyLab()
|
|
76
76
|
const e=d.default.join(this.basePath,"README.md")
|
|
77
77
|
if(!u.default.existsSync(e)){const t=`# Project at ${this.basePath}\n\nCreated with AlchemyMCP Server.\n`
|
|
78
78
|
await h.default.writeFile(e,t)}this.logger.info("Git repository initialized successfully"),await this.git.add(".")
|
|
@@ -80,7 +80,7 @@ const t=await this.git.status()
|
|
|
80
80
|
t.staged.length>0?(await this.git.commit("Initial commit by AlchemyMCP Server"),this.logger.info(`Initial commit created with ${t.staged.length} files`)):this.logger.info("No files to commit in initial repository")}catch(e){this.logger.error("Failed to initialize git repository",{error:e instanceof Error?e.stack:e+""})}}setupMcpEventHandlers(){this.logger.debug("MCP event handlers set up")}captureClientInfo(e){try{const t=e.clientInfo||{}
|
|
81
81
|
this.logger.info("[CLIENT-DEBUG] captureClientInfo called",{hasClientInfo:!!t,clientInfoName:t.name,clientInfoVersion:t.version,initDataKeys:Object.keys(e),userAgent:e.userAgent||t.userAgent,connectionType:this.clientInfo?.connectionType})
|
|
82
82
|
const r=this.detectClientFromName(t.name)
|
|
83
|
-
this.logger.info("[CLIENT-DEBUG] detectClientFromName result",{inputName:t.name,detectedName:r,willUse:r||"Unknown Client"}),this.clientInfo={name:r||"Unknown Client",version:t.version||"Unknown Version",capabilities:e.capabilities||{},userAgent:e.userAgent||t.userAgent,connectedAt:(new Date).toISOString(),initializationData:e},(0,y.setGlobalClientInfo)(this.clientInfo.name||"Unknown Client",this.clientInfo.version||"Unknown Version"),this.logger.info("MCP client connected",{clientName:this.clientInfo.name,clientVersion:this.clientInfo.version,connectionType:this.clientInfo.connectionType||"unknown"})}catch(e){this.logger.error("Failed to capture client information",{error:(0,
|
|
83
|
+
this.logger.info("[CLIENT-DEBUG] detectClientFromName result",{inputName:t.name,detectedName:r,willUse:r||"Unknown Client"}),this.clientInfo={name:r||"Unknown Client",version:t.version||"Unknown Version",capabilities:e.capabilities||{},userAgent:e.userAgent||t.userAgent,connectedAt:(new Date).toISOString(),initializationData:e},(0,y.setGlobalClientInfo)(this.clientInfo.name||"Unknown Client",this.clientInfo.version||"Unknown Version"),this.logger.info("MCP client connected",{clientName:this.clientInfo.name,clientVersion:this.clientInfo.version,connectionType:this.clientInfo.connectionType||"unknown"})}catch(e){this.logger.error("Failed to capture client information",{error:(0,j.getErrorMessage)(e)})}}detectClientFromName(e){if(!e)return
|
|
84
84
|
const t=e.toLowerCase()
|
|
85
85
|
return"claude-ai"===t||t.includes("claude")?"Claude Desktop":t.includes("vscode")?"VS Code":t.includes("cursor")?"Cursor":t.includes("opencode")?"OpenCode":e}getClientInfo(){return this.clientInfo}cleanupSSEConnection(){this.currentSSEConnection&&(this.currentSSEConnection.transport.close(),this.currentSSEConnection=null,this.logger.debug("SSE connection closed"))}handleError(e,t){if(t instanceof Error){const r=(0,v.createMcpProtocolError)(t.message||"Unknown error")
|
|
86
86
|
this.logger.error("MCP error",{message:t.message,name:t.name,stack:t.stack,code:r.code}),e.status(500).json({error:{message:t.message,code:r.code,data:r.data||{details:t.message}}})}else this.logger.error("Unknown error",{error:t+""}),e.status(500).json({error:{message:"Unknown error occurred",code:-32e3,data:{details:t+""}}})
|
|
@@ -105,19 +105,19 @@ const t=await r.getSynchronizedProjectId()
|
|
|
105
105
|
t&&t!==e&&(this.logger.info("Project ID changed after synchronization",{oldId:e,newId:t}),e=t,await this.projectContext.updateProjectId(t),this.logger.info("Successfully updated project.json with synchronized ID",{synchronizedProjectId:t}),this.apiClient.setProjectId(t),this.tokenManager.setProjectId(t))}}catch(e){this.logger.warn("Initial project synchronization failed, but continuing initialization",{error:e instanceof Error?e.message:e+""})}await this.initializeGitRepositories(),await this.initializeWorkspaceManager(this.multiAgentMode),this.logger.info("Re-initializing all tools with full context...")
|
|
106
106
|
const o=this.getContext();(0,C.registerTools)(this.server,o,this.apiClient,this.logger,this.metrics,this.tokenManager,this),this.tokenManager.setProjectId(this.getProjectId()),this.logger.info("Complete initialization finished - all tools available")}async getCurrentBranchInfo(){try{if(!this.git)return{available:!1,message:"No git repository available"}
|
|
107
107
|
const e=await k.getRepositoryStatus(this.git,this.logger,this.metrics)
|
|
108
|
-
return e.isGitRepository?{available:!0,currentBranch:e.currentBranch,isClean:e.isClean,branchCount:e.branches.length,message:`On branch ${e.currentBranch}${e.isClean?" (clean)":" (uncommitted changes)"}`}:{available:!1,message:"Not a git repository"}}catch(e){return this.logger.warn("Failed to get branch info",{error:(0,
|
|
108
|
+
return e.isGitRepository?{available:!0,currentBranch:e.currentBranch,isClean:e.isClean,branchCount:e.branches.length,message:`On branch ${e.currentBranch}${e.isClean?" (clean)":" (uncommitted changes)"}`}:{available:!1,message:"Not a git repository"}}catch(e){return this.logger.warn("Failed to get branch info",{error:(0,j.getErrorMessage)(e)}),{available:!1,message:"Git error: "+(0,j.getErrorMessage)(e)}}}async createSseConnection(e,t){await this.waitForInitialization(),this.cleanupSSEConnection(),this.logger.debug("Creating new SSE connection"),this.logger.info("[CLIENT-DEBUG] createSseConnection called",{userAgent:t,hasExistingClientInfo:!!this.clientInfo,existingName:this.clientInfo?.name}),this.clientInfo?(this.clientInfo.connectionType="sse",this.clientInfo.userAgent=t):this.clientInfo={connectionType:"sse",connectedAt:(new Date).toISOString(),name:"Unknown Client",version:"Unknown Version",userAgent:t},e.setHeader("Content-Type","text/event-stream"),e.setHeader("Cache-Control","no-cache"),e.setHeader("Connection","keep-alive")
|
|
109
109
|
const r=new g.SSEServerTransport("/sse",e)
|
|
110
110
|
this.currentSSEConnection={transport:r,response:e}
|
|
111
|
-
try{await this.server.connect(r),this.extractClientInfoAfterConnection(),this.logger.info("SSE transport connected successfully")}catch(e){this.logger.error("Error connecting SSE transport",{error:(0,
|
|
112
|
-
try{await this.server.connect(this.stdioTransport),this.extractClientInfoAfterConnection(),this.logger.info("STDIO transport connected successfully")}catch(e){this.logger.error("Error connecting stdio transport",{error:(0,
|
|
111
|
+
try{await this.server.connect(r),this.extractClientInfoAfterConnection(),this.logger.info("SSE transport connected successfully")}catch(e){this.logger.error("Error connecting SSE transport",{error:(0,j.getErrorMessage)(e)})}return r}async connectStdio(){await this.waitForInitialization(),this.logger.debug("Connecting stdio transport"),this.stdioTransport=new g.StdioServerTransport,this.clientInfo?this.clientInfo.connectionType="stdio":this.clientInfo={connectionType:"stdio",connectedAt:(new Date).toISOString(),name:"Unknown Client",version:"Unknown Version"}
|
|
112
|
+
try{await this.server.connect(this.stdioTransport),this.extractClientInfoAfterConnection(),this.logger.info("STDIO transport connected successfully")}catch(e){this.logger.error("Error connecting stdio transport",{error:(0,j.getErrorMessage)(e)})}}getCurrentSSEConnection(){return this.currentSSEConnection}interceptConnectMethod(){try{const e=this.server.connect
|
|
113
113
|
"function"==typeof e&&(this.server.connect=async t=>{const r=await e.call(this.server,t)
|
|
114
|
-
return setTimeout((()=>{this.extractClientInfoAfterConnection(),this.searchForClaudeAiPattern()}),500),r})}catch(e){this.logger.error("Failed to intercept connect method",{error:(0,
|
|
114
|
+
return setTimeout((()=>{this.extractClientInfoAfterConnection(),this.searchForClaudeAiPattern()}),500),r})}catch(e){this.logger.error("Failed to intercept connect method",{error:(0,j.getErrorMessage)(e)})}}searchForClaudeAiPattern(){try{const e=this.server,t=(e,r=0)=>{if(r>3||!e||"object"!=typeof e)return!1
|
|
115
115
|
try{for(const[n,o]of Object.entries(e)){if("string"==typeof o&&"claude-ai"===o)return this.captureClientInfo({clientInfo:{name:"claude-ai",version:"0.1.0"}}),!0
|
|
116
116
|
if("object"==typeof o&&null!==o&&t(o,r+1))return!0}}catch(e){}return!1},r=[e._options,e._serverInfo,e._capabilities,this.stdioTransport,this.currentSSEConnection?.transport]
|
|
117
117
|
let n=!1
|
|
118
118
|
for(const e of r)if(e&&t(e)){n=!0
|
|
119
119
|
break}if(!n&&this.clientInfo&&"Unknown Client"===this.clientInfo.name){const e=this.detectClientUsingHeuristics()
|
|
120
|
-
e&&(this.clientInfo.name=e,this.clientInfo.version=this.clientInfo.version||"0.1.0",this.logger.info("Client detected using heuristics",{detectedClient:e,connectionType:this.clientInfo.connectionType,userAgent:this.clientInfo.userAgent}))}}catch(e){this.logger.debug("Error searching for claude-ai pattern",{error:(0,
|
|
120
|
+
e&&(this.clientInfo.name=e,this.clientInfo.version=this.clientInfo.version||"0.1.0",this.logger.info("Client detected using heuristics",{detectedClient:e,connectionType:this.clientInfo.connectionType,userAgent:this.clientInfo.userAgent}))}}catch(e){this.logger.debug("Error searching for claude-ai pattern",{error:(0,j.getErrorMessage)(e)})}}detectClientUsingHeuristics(){try{if(this.logger.info("[CLIENT-DEBUG] detectClientUsingHeuristics called",{hasClientInfo:!!this.clientInfo,connectionType:this.clientInfo?.connectionType,userAgent:this.clientInfo?.userAgent,currentName:this.clientInfo?.name}),!this.clientInfo)return null
|
|
121
121
|
if("sse"===this.clientInfo.connectionType){const e=this.clientInfo.userAgent?.toLowerCase()||""
|
|
122
122
|
if(this.logger.info("[CLIENT-DEBUG] SSE connection heuristics",{userAgent:e,hasClaude:e.includes("claude"),hasChrome:e.includes("chrome"),hasElectron:e.includes("electron")}),e.includes("claude"))return"Claude Code"
|
|
123
123
|
if(e.includes("chrome")||e.includes("electron"))return"Claude Code"}if("stdio"===this.clientInfo.connectionType){const e=process.env.TERM_PROGRAM?.toLowerCase()||""
|
|
@@ -134,36 +134,36 @@ if(o.includes("claude.app")||o.includes("electron")&&o.includes("claude"))return
|
|
|
134
134
|
if(e.includes("vscode"))return"VS Code"
|
|
135
135
|
if(e.includes("cursor"))return"Cursor"
|
|
136
136
|
if(e.includes("claude-code"))return"Claude Code"
|
|
137
|
-
if(e.includes("claude")&&e.includes("desktop"))return"Claude Desktop"}return null}catch(e){return this.logger.debug("Error in heuristic client detection",{error:(0,
|
|
137
|
+
if(e.includes("claude")&&e.includes("desktop"))return"Claude Desktop"}return null}catch(e){return this.logger.debug("Error in heuristic client detection",{error:(0,j.getErrorMessage)(e)}),null}}extractClientInfoAfterConnection(){try{setTimeout((()=>{const e=(0,w.getClientInfoForMetadata)(this);(0,y.setGlobalClientInfo)(e.clientName,e.clientVersion)
|
|
138
138
|
const t=(0,y.getGlobalClientInfo)()
|
|
139
|
-
this.logger.info("MCP session initialized with unique session tag",{clientName:e.clientName,clientVersion:e.clientVersion,sessionTag:t.sessionTag,globalInfoSet:{clientName:t.clientName,clientVersion:t.clientVersion,sessionTag:t.sessionTag}})}),100)}catch(e){this.logger.debug("Could not extract client info after connection",{error:(0,
|
|
139
|
+
this.logger.info("MCP session initialized with unique session tag",{clientName:e.clientName,clientVersion:e.clientVersion,sessionTag:t.sessionTag,globalInfoSet:{clientName:t.clientName,clientVersion:t.clientVersion,sessionTag:t.sessionTag}})}),100)}catch(e){this.logger.debug("Could not extract client info after connection",{error:(0,j.getErrorMessage)(e)})}}setCurrentSSEConnection(e){this.currentSSEConnection=e}getServer(){return this.server}getCurrentGitInstance(){if(!this.workspaceManager)return this.git||void 0
|
|
140
140
|
const e=this.workspaceManager.getCurrentContext()
|
|
141
141
|
return"multi-agent"===e.mode&&e.requestId?this.workspaceManager.getCurrentGit():this.git||void 0}getContext(){if(!this.workspaceManager)throw Error("WorkspaceManager not initialized")
|
|
142
142
|
return{mainBasePath:this.basePath,alchemyPath:this.alchemyPath,basePath:this.workspaceManager.getCurrentContext().basePath,projectId:this.getProjectId(),git:this.getCurrentGitInstance(),gitBinary:this.gitBinary,apiClient:this.apiClient,workspaceManager:this.workspaceManager,documentFileManager:this.documentFileManager,lockOverrideManager:this.lockOverrideManager,configManager:this.configManager,getNextId:this.getNextId.bind(this),getCurrentBranchContext:this.getCurrentBranchContext.bind(this),syncBranchState:this.syncBranchState.bind(this),switchToMainContext:this.switchToMainContext.bind(this),getCurrentRequestId:this.getCurrentRequestId.bind(this),updateBranchState:this.updateBranchState.bind(this),multiAgentMode:"multi-agent"===this.workspaceManager?.getCurrentContext().mode,getEffectiveBasePath:async()=>this.workspaceManager?.getCurrentContext().basePath||this.basePath}}isMainBranch(e){return"main"===e||"master"===e}extractRequestIdFromBranch(e){const t=e.match(/^feature\/req(\d+)-/)
|
|
143
|
-
return t?"req"+t[1]:null}async getEnhancedContext(){return{...this.getContext(),branchInfo:await this.getCurrentBranchInfo()}}getTokenManager(){return this.tokenManager}getProjectId(){try{return this.projectContext.getProjectId()}catch(e){return this.logger.debug("ProjectContext not initialized, using fallback project ID",{error:(0,
|
|
143
|
+
return t?"req"+t[1]:null}async getEnhancedContext(){return{...this.getContext(),branchInfo:await this.getCurrentBranchInfo()}}getTokenManager(){return this.tokenManager}getProjectId(){try{return this.projectContext.getProjectId()}catch(e){return this.logger.debug("ProjectContext not initialized, using fallback project ID",{error:(0,j.getErrorMessage)(e)}),"INITIALIZING"}}generateSessionId(){return`session_${Date.now().toString(36)}_${Math.random().toString(36).substring(2,8)}_${process.pid.toString(36)}`}getMultiAgentConfig(){return null}isMultiAgentMode(){return this.multiAgentMode}async getActiveWorktrees(){return await this.workspaceManager.listActiveWorkspaces()}async initializeWorkspaceManager(e=!1){try{if(this.logger.debug("initializeWorkspaceManager called",{multiAgentMode:e,basePath:this.basePath}),!this.git)throw Error("Git must be initialized before WorkspaceManager")
|
|
144
144
|
this.workspaceManager=(0,q.createWorkspaceManager)(this.basePath,e,this.logger,this.git,this.metrics,this.apiClient),this.logger.debug("WorkspaceManager created successfully"),this.logger.info("Initialized unified workspace manager",{mode:e?"multi-agent":"single-agent",basePath:this.basePath})}catch(e){throw this.logger.error("Failed to initialize workspace manager",{error:e}),e}}async initializeSingleAgentMode(){if(this.logger.info("Initializing single-agent mode"),!(0,S.acquireProcessLock)(this.basePath,!1)){const e=d.default.join(this.basePath,".alchemy_lab",".mcp-server.lock")
|
|
145
145
|
throw Error(`Another alchemy instance is running in ${this.basePath}.\n\nTo fix this:\n1. Close the other MCP client/instance\n2. Or if no other instance is running, manually delete the lock file:\n ${e}\n\nNote: Stale locks (>24 hours old) and locks from other computers are automatically cleared.`)}this.logger.info("Process lock acquired for single-agent mode")}async switchToRequestContext(e){return this.logger.debug("switchToRequestContext called",{requestId:e,multiAgentMode:this.multiAgentMode,hasWorkspaceManager:!!this.workspaceManager}),this.multiAgentMode&&this.workspaceManager?this.switchToWorktreeContext(e):this.switchToBranchContext(e)}async switchToWorktreeContext(e){if(this.logger.debug("Using worktree context switching for multi-agent mode",{requestId:e}),!this.workspaceManager)return{success:!1,message:"Workspace manager not available"}
|
|
146
146
|
try{let t="request-"+e
|
|
147
147
|
try{this.logger.debug("Attempting to fetch request title from API",{requestId:e})
|
|
148
148
|
const r=this.apiClient.getRequestClient(),n=await r.getRequest(e)
|
|
149
|
-
n&&n.title?(t=n.title,this.logger.debug("Successfully fetched request title for worktree",{requestId:e,actualTitle:n.title})):this.logger.warn("Request info found but no title, using fallback",{requestId:e,requestInfo:n?"exists":"null",fallbackTitle:t})}catch(r){this.logger.warn("Failed to fetch request title, using fallback",{requestId:e,fallbackTitle:t,error:(0,
|
|
149
|
+
n&&n.title?(t=n.title,this.logger.debug("Successfully fetched request title for worktree",{requestId:e,actualTitle:n.title})):this.logger.warn("Request info found but no title, using fallback",{requestId:e,requestInfo:n?"exists":"null",fallbackTitle:t})}catch(r){this.logger.warn("Failed to fetch request title, using fallback",{requestId:e,fallbackTitle:t,error:(0,j.getErrorMessage)(r),errorStack:r instanceof Error?r.stack:void 0})}const r=this.generateSessionId()
|
|
150
150
|
this.logger.info("Creating worktree for request using WorkspaceManager",{requestId:e,requestTitle:t,sessionId:r}),await this.workspaceManager.ensureWorkspaceReady(e)
|
|
151
151
|
const n=this.workspaceManager.getCurrentContext()
|
|
152
152
|
this.git=(0,c.simpleGit)({baseDir:n.basePath,binary:this.gitBinary})
|
|
153
153
|
try{const t=await k.getCurrentBranch(this.git,this.logger,this.metrics)
|
|
154
154
|
if(this.logger.info("Workspace Git instance branch status",{requestId:e,currentBranch:t,expectedBranch:n.branchName,workspacePath:n.basePath,isMainBranch:n.isMainBranch}),t!==n.branchName&&!n.isMainBranch){this.logger.warn("Workspace not on expected branch, attempting to switch",{requestId:e,currentBranch:t,expectedBranch:n.branchName})
|
|
155
155
|
const r=await k.switchToBranch(this.git,n.branchName,this.logger,this.metrics)
|
|
156
|
-
r.success?this.logger.info("Successfully switched workspace to correct branch",{requestId:e,branchName:n.branchName}):this.logger.error("Failed to switch workspace to correct branch",{requestId:e,expectedBranch:n.branchName,error:r.message})}}catch(t){this.logger.error("Failed to verify workspace branch status",{requestId:e,workspacePath:n.basePath,error:t instanceof Error?t.message:t+""})}return this.logger.info("Switched to request context",{requestId:e,workspacePath:n.basePath,branchName:n.branchName}),{success:!0,message:"Switched to workspace for request "+e,worktreePath:n.basePath}}catch(t){const r=(0,
|
|
156
|
+
r.success?this.logger.info("Successfully switched workspace to correct branch",{requestId:e,branchName:n.branchName}):this.logger.error("Failed to switch workspace to correct branch",{requestId:e,expectedBranch:n.branchName,error:r.message})}}catch(t){this.logger.error("Failed to verify workspace branch status",{requestId:e,workspacePath:n.basePath,error:t instanceof Error?t.message:t+""})}return this.logger.info("Switched to request context",{requestId:e,workspacePath:n.basePath,branchName:n.branchName}),{success:!0,message:"Switched to workspace for request "+e,worktreePath:n.basePath}}catch(t){const r=(0,j.getErrorMessage)(t)
|
|
157
157
|
return this.logger.error("Failed to switch to request context",{requestId:e,error:r}),{success:!1,message:"Failed to switch context: "+r}}}async switchToBranchContext(e){if(this.logger.debug("Using branch context switching for single-agent mode",{requestId:e}),!this.workspaceManager)return{success:!1,message:"WorkspaceManager not available"}
|
|
158
158
|
try{let t="request-"+e
|
|
159
159
|
try{const r=this.apiClient.getRequestClient(),n=await r.getRequest(e)
|
|
160
|
-
n&&n.title&&(t=n.title)}catch(t){this.logger.warn("Failed to fetch request title for branch switching",{requestId:e,error:(0,
|
|
160
|
+
n&&n.title&&(t=n.title)}catch(t){this.logger.warn("Failed to fetch request title for branch switching",{requestId:e,error:(0,j.getErrorMessage)(t)})}this.logger.info("Ensuring workspace exists before switching (single-agent)",{requestId:e,requestTitle:t,reason:"manual-context-switch"}),await this.workspaceManager.ensureWorkspaceReady(e)
|
|
161
161
|
const r={success:!0,message:"Workspace ready"}
|
|
162
162
|
if(!r.success)return{success:!1,message:r.message||"Failed to switch to request workspace"}
|
|
163
163
|
const n=this.workspaceManager.getCurrentContext()
|
|
164
164
|
this.git=(0,c.simpleGit)({baseDir:n.basePath,binary:this.gitBinary})
|
|
165
165
|
try{const t=await k.getCurrentBranch(this.git,this.logger,this.metrics)
|
|
166
|
-
return this.logger.info("Single-agent Git instance branch status",{requestId:e,currentBranch:t,expectedBranch:n.branchName,basePath:n.basePath}),{success:!0,message:`Switched to request ${e} context`}}catch(t){return this.logger.warn("Branch verification failed but continuing",{requestId:e,error:t instanceof Error?t.message:t+""}),{success:!0,message:`Switched to request ${e} context (branch verification warning)`}}}catch(t){return this.logger.error("Failed to switch to single-agent request context",{requestId:e,error:(0,
|
|
166
|
+
return this.logger.info("Single-agent Git instance branch status",{requestId:e,currentBranch:t,expectedBranch:n.branchName,basePath:n.basePath}),{success:!0,message:`Switched to request ${e} context`}}catch(t){return this.logger.warn("Branch verification failed but continuing",{requestId:e,error:t instanceof Error?t.message:t+""}),{success:!0,message:`Switched to request ${e} context (branch verification warning)`}}}catch(t){return this.logger.error("Failed to switch to single-agent request context",{requestId:e,error:(0,j.getErrorMessage)(t)}),{success:!1,message:"Failed to switch to request context: "+(0,j.getErrorMessage)(t)}}}async getEffectiveBasePath(e){if(!this.multiAgentMode||!this.workspaceManager||!e)return this.basePath
|
|
167
167
|
const t=await this.workspaceManager.getWorkspaceInfo(e)
|
|
168
168
|
return t?.path||this.basePath}}exports.McpServer=A
|
|
169
169
|
const D=new Map},213(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.def=void 0
|
|
@@ -195,13 +195,13 @@ const w=[],k=a.toLowerCase()
|
|
|
195
195
|
for(const e of y){const t=[]
|
|
196
196
|
if("all"!==l&&"title"!==l||!e.title||e.title.toLowerCase().includes(k)&&t.push({request:e,matchType:"title",matchSnippet:r(e.title,a)}),"all"!==l&&"description"!==l||!e.description||e.description.toLowerCase().includes(k)&&t.push({request:e,matchType:"description",matchSnippet:n(e.description,k,150)}),("all"===l||"criteria"===l)&&e.acceptanceCriteria)for(const r of e.acceptanceCriteria){const o="string"==typeof r?r:r.description
|
|
197
197
|
if(o&&o.toLowerCase().includes(k)){t.push({request:e,matchType:"criteria",matchSnippet:n(o,k,150)})
|
|
198
|
-
break}}t.length>0&&w.push(t[0])}const
|
|
199
|
-
if(0===
|
|
200
|
-
let v=`Found ${
|
|
201
|
-
for(const e of
|
|
198
|
+
break}}t.length>0&&w.push(t[0])}const b=g.limit||20,I=w.slice(0,b)
|
|
199
|
+
if(0===I.length)return h({success:!0,resultCount:0}),{content:[{type:"text",text:`No requests found matching "${a}".\n\nSearched in: ${l}\nTotal requests checked: ${y.length}`}]}
|
|
200
|
+
let v=`Found ${I.length} request${1===I.length?"":"s"} matching "${a}":\n\n`
|
|
201
|
+
for(const e of I){const t=e.request,r=o(t.status)
|
|
202
202
|
v+=`${s(t.type)} **${t.title}** (${t.id}) ${r}\n`,v+=" \u{1f4cd} Match in "+e.matchType,e.matchSnippet&&(v+=": "+e.matchSnippet),v+="\n\n"}v+=`---\nSearched ${y.length} requests (filtered by: `
|
|
203
203
|
const C=[]
|
|
204
|
-
return g.status&&C.push("status="+g.status),g.type&&C.push("type="+g.type),g.dateFrom&&C.push("from="+g.dateFrom),g.dateTo&&C.push("to="+g.dateTo),v+=C.length>0?C.join(", "):"none",v+=")",h({success:!0,resultCount:
|
|
204
|
+
return g.status&&C.push("status="+g.status),g.type&&C.push("type="+g.type),g.dateFrom&&C.push("from="+g.dateFrom),g.dateTo&&C.push("to="+g.dateTo),v+=C.length>0?C.join(", "):"none",v+=")",h({success:!0,resultCount:I.length}),d.incrementCounter("search_requests_success",1),{content:[{type:"text",text:v}]}}catch(e){return u.error("Search requests failed",{error:e instanceof Error?e.stack:e+""}),h({success:!1,error:(0,a.getErrorMessage)(e)}),d.incrementCounter("search_requests_errors",1),{content:[{type:"text",text:"\u274c **Search Failed:** "+(0,a.getErrorMessage)(e)}],isError:!0}}}
|
|
205
205
|
const i=t(9860),a=t(8824)},260(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.def=void 0
|
|
206
206
|
const r=t(6183),n=t(4221)
|
|
207
207
|
exports.def={name:"view_asset",description:"View an image from the project's .alchemy_lab/assets/ folder. Returns the image so you can see it. Use this when you encounter asset:filename.png references in plans or documents and need to understand the image content.",schema:r.ViewAssetSchema,annotations:{title:"View Asset Image",readOnlyHint:!0},readOnly:!0,handler(e,t){return(0,n.handleViewAsset)(e,t.context,t.logger,t.metrics)}}},270(e,exports){Object.defineProperty(exports,"__esModule",{value:!0})},293(e,exports,t){function r(e){let t
|
|
@@ -258,14 +258,14 @@ throw p.error("Failed to check request lock status",{taskId:o,requestId:w.reques
|
|
|
258
258
|
let k=d.git
|
|
259
259
|
if(d.workspaceManager){const e=d.workspaceManager.getCurrentContext()
|
|
260
260
|
if("multi-agent"===e.mode&&e.requestId){const{simpleGit}=t(3807)
|
|
261
|
-
k=simpleGit({baseDir:e.basePath,binary:d.gitBinary}),p.debug("Using workspace-aware git instance for task completion",{taskId:o,mode:e.mode,requestId:e.requestId,basePath:e.basePath})}}let
|
|
262
|
-
if(k)try{(await k.status()).isClean()||(
|
|
261
|
+
k=simpleGit({baseDir:e.basePath,binary:d.gitBinary}),p.debug("Using workspace-aware git instance for task completion",{taskId:o,mode:e.mode,requestId:e.requestId,basePath:e.basePath})}}let b=null
|
|
262
|
+
if(k)try{(await k.status()).isClean()||(b=(await k.commit(`Complete task ${o}: ${h}`)).commit,p.info("Created commit for task completion",{taskId:o,commitId:b}))}catch(e){p.warn("Failed to commit changes",{error:(0,l.getErrorMessage)(e)})}let I=null
|
|
263
263
|
try{const e=u.getToolRecordClient()
|
|
264
|
-
e&&(
|
|
265
|
-
p.info("Raw task update response data",{responseData:JSON.stringify(n)}),p.debug("Task update response structure",{type:typeof n,isArray:Array.isArray(n),hasData:null!=n,properties:n?Object.keys(n):[],dataPreview:n?JSON.stringify(n).substring(0,200)+"...":"null"}),(0,s.extractDataFromResponse)(n,{logger:p,operationName:"updateTask",defaultValue:{id:o,status:"completed"}}),p.info("Successfully completed task",{taskId:o,recordId:
|
|
264
|
+
e&&(I={id:(await e.createToolRecord({taskId:o,requestId:w.requestId,projectId:m,type:"complete-task",metadata:{status:"completed",timestamp:(new Date).toISOString(),taskTitle:w.title,completionSummary:h,lastCommit:b,completedAt:(new Date).toISOString()},note:`Completed task: ${h.substring(0,100)}${h.length>100?"...":""}`})).id})}catch(e){p.error("Failed to create tool record for task completion, but continuing",{error:e instanceof Error?e.stack:e+"",taskId:o,requestId:w.requestId})}try{const e=w.metadata||{},t=(new Date).toISOString(),r={status:"completed",metadata:{...e,lastCommit:b,completionSummary:h,completionRecordId:I?.id,completedAt:t}},n=await y.updateTask(o,r)
|
|
265
|
+
p.info("Raw task update response data",{responseData:JSON.stringify(n)}),p.debug("Task update response structure",{type:typeof n,isArray:Array.isArray(n),hasData:null!=n,properties:n?Object.keys(n):[],dataPreview:n?JSON.stringify(n).substring(0,200)+"...":"null"}),(0,s.extractDataFromResponse)(n,{logger:p,operationName:"updateTask",defaultValue:{id:o,status:"completed"}}),p.info("Successfully completed task",{taskId:o,recordId:I?.id})
|
|
266
266
|
const i=w.requestId
|
|
267
267
|
let a=`Task ${o} (${w.title}) has been marked as completed.`
|
|
268
|
-
if(
|
|
268
|
+
if(I?.id&&(a+=`\n[RECORD:${I.id}]`),b&&(a+="\nCommit: "+b.substring(0,8)),i)try{const e=await y.listTasks({requestId:i})
|
|
269
269
|
p.info("Raw tasks list response data",{responseData:JSON.stringify(e)}),p.debug("Tasks list response structure",{type:typeof e,isArray:Array.isArray(e),hasData:null!=e,properties:e?Object.keys(e):[],dataPreview:e?JSON.stringify(e).substring(0,200)+"...":"null"})
|
|
270
270
|
const t=(0,s.extractArrayFromResponse)(e,{logger:p,operationName:"listTasksForProgress",defaultValue:[]}),r=t.length,n=t.filter((e=>"completed"===e.status)).length
|
|
271
271
|
p.info("Task progress check",{requestId:i,totalTasks:r,completedTasks:n}),a+=`\n\nTask Progress: ${n}/${r} tasks completed`,n===r&&(a+=`\n\nAll tasks for request ${i} are now completed! You may consider marking the request as completed using the complete-request tool.`)}catch(e){p.warn("Failed to check task progress",{error:(0,l.getErrorMessage)(e),requestId:i})}return f({success:!0}),{content:[{type:"text",text:a}]}}catch(e){throw p.error("Failed to complete task",{error:e instanceof Error?e.stack:e+"",taskId:o}),Error("Failed to complete task: "+(0,l.getErrorMessage)(e))}}catch(t){if(p.error("Failed to complete task",{error:t instanceof Error?t.stack:t+"",args:e}),d.projectId)try{const r=u.getToolRecordClient()
|
|
@@ -328,9 +328,8 @@ t>0&&this.logger.debug("Cleaned up expired passwords",{count:t})}getActivePasswo
|
|
|
328
328
|
const r=t(1569),n=t(5997),o=t(8349),s=t(9852),i=t(9422),a=r.z.object({}),c=r.z.object({requestId:r.z.string().optional().describe("Request ID to search for")})
|
|
329
329
|
exports.debugDefs=[{name:"debug_multi_agent_status",description:"Debug tool to check multi-agent mode status, worktree state, and configuration",schema:a,annotations:{title:"Debug Multi-Agent Status",readOnlyHint:!0},debugOnly:!0,readOnly:!0,async handler(e,t){return{content:[{type:"text",text:await(0,n.handleDebugMultiAgentStatus)(e,t.context,t.logger,t.metrics)}]}}},{name:"debug_git_log",description:"Debug tool to examine git log and search for merge commits",schema:a,annotations:{title:"Debug Git Log",readOnlyHint:!0},debugOnly:!0,readOnly:!0,handler(e,t){return(0,o.handleDebugGitLog)(e,t.context,t.logger,t.metrics)}},{name:"debug_git_log_request",description:"Debug tool to examine git log for a specific request",schema:c,annotations:{title:"Debug Git Log Request",readOnlyHint:!0},debugOnly:!0,readOnly:!0,handler(e,t){return(0,s.handleDebugGitLogRequest)(e,t.context,t.logger,t.metrics)}},{name:"debug_request_file_history",description:"Debug tool to test git merge commit search patterns for request file history",schema:c,annotations:{title:"Debug Request File History",readOnlyHint:!0},debugOnly:!0,readOnly:!0,handler(e,t){return(0,i.handleDebugRequestFileHistory)(e,t.context,t.apiClient,t.logger,t.metrics)}}]},700(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.def=void 0
|
|
330
330
|
const r=t(6183),n=t(8037),o=t(5218)
|
|
331
|
-
exports.def={name:"list_requests",description:`List requests with filtering options (status, type, dates) and pagination. Shows detailed request information${(0,o.isMultiAgentModeEnabled)()?" including lock status to indicate which requests are currently in use by other agents":""}.`,schema:r.ListRequestsSchema,annotations:{title:"List Requests",readOnlyHint:!0},hidden:!0,readOnly:!0,handler(e,t){return(0,n.handleListRequests)(e,t.context,t.apiClient,t.logger,t.metrics)}}},
|
|
332
|
-
const r=t(
|
|
333
|
-
const r=t(7645),n=t(1038),o=t(2161),s=t(5172),i=t(715)
|
|
331
|
+
exports.def={name:"list_requests",description:`List requests with filtering options (status, type, dates) and pagination. Shows detailed request information${(0,o.isMultiAgentModeEnabled)()?" including lock status to indicate which requests are currently in use by other agents":""}.`,schema:r.ListRequestsSchema,annotations:{title:"List Requests",readOnlyHint:!0},hidden:!0,readOnly:!0,handler(e,t){return(0,n.handleListRequests)(e,t.context,t.apiClient,t.logger,t.metrics)}}},857(module){module.exports=require("os")},922(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.ToolRecordClient=void 0
|
|
332
|
+
const r=t(7645),n=t(1038),o=t(2161),s=t(5172),i=t(6688)
|
|
334
333
|
class a extends r.ConnectionAwareClient{constructor(e,t,r,n,o,s,i){const a=t.child({component:"tool-record-client"}),c=s||{isInOfflineMode(){return!1},isOffline(){return!1},setOfflineMode(){},async checkConnectivity(){return!0},getHealthCheckStats(){return{isOffline:!1,consecutiveFailures:0,currentBackoffMs:0,lastCheckTime:0}},cleanup(){}}
|
|
335
334
|
super(e,a,r,o,i),this.setConnectionStatusManager(c),this.projectClient=n,this.logger.info("ToolRecordClient initialized",{baseUrl:e,hasAuthToken:!!o,options:JSON.stringify(i)})}async createToolRecord(e){if(this.logger.debug("Creating tool record",{record:e}),!e.projectId)throw this.logger.error("No project ID provided for creating tool record"),Error("Project ID is required for tool record creation")
|
|
336
335
|
if(!e.type)throw this.logger.error("No record type provided for creating tool record"),Error("Record type is required for tool record creation")
|
|
@@ -339,7 +338,7 @@ try{const r=e.projectId||this.projectClient.getProjectId()
|
|
|
339
338
|
if(!r)throw this.logger.error("No project ID available for creating tool record"),Error("Project ID is required for tool record operations")
|
|
340
339
|
try{const a=`/api/projects/${r}/tool-records`
|
|
341
340
|
this.logger.debug("Using tool record endpoint",{endpoint:a,projectId:r}),this.getAuthToken(),this.logger.info("Sending tool record to server",{endpoint:a,recordType:e.type,taskId:e.taskId,requestId:e.requestId})
|
|
342
|
-
const c=(0,s.getGlobalClientInfo)(),l=
|
|
341
|
+
const c=(0,s.getGlobalClientInfo)(),l=i.sessionIdentity.getCurrentCallOrigin(),d={...e,...l&&{cliOrigin:l},metadata:{...e.metadata,clientName:c.clientName,clientVersion:c.clientVersion,sessionTag:c.sessionTag}},u=await this.requestWithRetry("POST",a,d)
|
|
343
342
|
this.logger.debug("Raw tool record creation response",{responseStatus:(0,o.isSuccessResponse)(u)?200:(0,o.isErrorResponse)(u)?u.error.statusCode:"unknown",responseData:(0,o.isSuccessResponse)(u)?JSON.stringify(u.data).substring(0,500):(0,o.isErrorResponse)(u)?JSON.stringify(u.error).substring(0,500):"unknown response format"})
|
|
344
343
|
const h=(0,o.safeGetResponseData)(u,{})
|
|
345
344
|
return t({success:!0}),this.metrics.incrementCounter("tool_record_creation_success",1),this.logger.info("Successfully created tool record",{recordId:h.id,type:h.type,taskId:h.task_id,requestId:h.request_id}),(0,n.adaptApiToolRecordToDomain)(h)}catch(s){if(404===this.extractErrorStatus(s)){this.logger.error("Tool record creation failed: Endpoint not found (404)",{endpoint:`/api/projects/${r}/tool-records`,error:this.getErrorMessage(s)})
|
|
@@ -458,21 +457,21 @@ return t},r(e)},function(e){if(e&&e.__esModule)return e
|
|
|
458
457
|
var t={}
|
|
459
458
|
if(null!=e)for(var s=r(e),i=0;i<s.length;i++)"default"!==s[i]&&n(t,e,s[i])
|
|
460
459
|
return o(t,e),t}),i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
461
|
-
Object.defineProperty(exports,"__esModule",{value:!0}),exports.registerApiRoutes=async function(e,r,n,o){const s=n.child({component:"api"}),i=r.getTokenManager(),T=process.env.REMOTE_SERVER_URL||"https://api.alchemylabcode.com",P=new m.AuthenticationManager(i,n.child({component:"auth-manager"})),M=P.getTokenSynchronizer(),
|
|
460
|
+
Object.defineProperty(exports,"__esModule",{value:!0}),exports.registerApiRoutes=async function(e,r,n,o){const s=n.child({component:"api"}),i=r.getTokenManager(),T=process.env.REMOTE_SERVER_URL||"https://api.alchemylabcode.com",P=new m.AuthenticationManager(i,n.child({component:"auth-manager"})),M=P.getTokenSynchronizer(),j=await P.getTokenString()||void 0
|
|
462
461
|
n.debug("Token retrieved from authentication manager")
|
|
463
|
-
const
|
|
462
|
+
const R=new k.ConnectionStatusManager(T,n.child({component:"connection-status-manager"}),o,{checkIntervalMs:3e4,timeoutMs:5e3}),x=new w.ProjectClient(T,n.child({component:"project-client"}),o,R,j)
|
|
464
463
|
M.registerClient(x)
|
|
465
|
-
const O=new
|
|
464
|
+
const O=new I.TaskClient(T,n.child({component:"task-client"}),o,x,R,j)
|
|
466
465
|
M.registerClient(O)
|
|
467
|
-
const A=new v.FileOperationsClient(T,n.child({component:"file-client"}),o,x,R
|
|
466
|
+
const A=new v.FileOperationsClient(T,n.child({component:"file-client"}),o,x,j,R)
|
|
468
467
|
M.registerClient(A)
|
|
469
|
-
const D=new C.ProxyClient(T,n.child({component:"proxy-client"}),o,x,R
|
|
468
|
+
const D=new C.ProxyClient(T,n.child({component:"proxy-client"}),o,x,j,R)
|
|
470
469
|
M.registerClient(D)
|
|
471
|
-
const $=new _.RequestClient(T,n.child({component:"request-client"}),o,x,R
|
|
472
|
-
$.setAuthToken(
|
|
473
|
-
const F=new E.DocumentClient(T,n.child({component:"document-client"}),o,x,R
|
|
470
|
+
const $=new _.RequestClient(T,n.child({component:"request-client"}),o,x,j,R)
|
|
471
|
+
$.setAuthToken(j),(0,d.isDebugToolsEnabled)()&&n.debug("Explicitly set token on RequestClient",{tokenPresent:!!j}),M.registerClient($)
|
|
472
|
+
const F=new E.DocumentClient(T,n.child({component:"document-client"}),o,x,j,R)
|
|
474
473
|
M.registerClient(F)
|
|
475
|
-
const N=new q.ToolRecordClient(T,n.child({component:"tool-record-client"}),o,x,R
|
|
474
|
+
const N=new q.ToolRecordClient(T,n.child({component:"tool-record-client"}),o,x,j,R)
|
|
476
475
|
M.registerClient(N)
|
|
477
476
|
const L=new S.ApiClient(P,x,O,A,$,F,N,D,n.child({component:"api-client"})),z=a.default.Router();(0,h.registerAuthRoutes)(z,{projectClient:x,taskClient:O,fileClient:A,authManager:P,apiClient:L},i,n)
|
|
478
477
|
const B=r.getContext();(0,g.registerConfigRoutes)(z,n,B.basePath),e.use("/api",z)
|
|
@@ -488,9 +487,9 @@ if((0,d.isDebugToolsEnabled)()&&s.debug("Task validation response received",{tas
|
|
|
488
487
|
let o=!1
|
|
489
488
|
if("object"==typeof e&&null!==e){404===e.statusCode&&(o=!0),404===e.response?.statusCode&&(o=!0)
|
|
490
489
|
const t=(e.message||e.error||e)+"";(t.includes("404")||t.toLowerCase().includes("not found"))&&(o=!0)}if(o)return s.info("Task ID not found - blocking operation",{taskId:n,statusCode:404,action:"blocking"}),t.status(400).json({success:!1,error:{code:"TASK_NOT_FOUND",message:"Task ID does not exist: "+n,retryable:!1,statusCode:400}})
|
|
491
|
-
s.warn("Error validating task ID",{taskId:n,error:(0,
|
|
490
|
+
s.warn("Error validating task ID",{taskId:n,error:(0,b.getErrorMessage)(e)}),s.warn("Error validating task ID, but continuing as fallback",{taskId:n,action:"continuing"}),r()}}
|
|
492
491
|
e.get("/health",((e,t)=>{o.incrementCounter("api_requests_total",1,{endpoint:"health",method:"GET"}),t.json({success:!0,data:{status:"ok",version:"0.1.0",serverType:"mcp-local-server",timestamp:(new Date).toISOString()}})})),e.get("/mcp/sse",(async(e,t)=>{s.info("New SSE connection requested",{ip:e.ip,userAgent:e.headers["user-agent"]}),o.incrementCounter("mcp_connections_total",1,{type:"sse"})
|
|
493
|
-
try{await r.createSseConnection(t,e.headers["user-agent"]),t.on("close",(()=>{s.info("SSE connection closed"),o.setGauge("mcp_active_connections",0,{type:"sse"}),r.cleanupSSEConnection()}))}catch(e){s.error("Failed to establish MCP SSE connection",{error:e instanceof Error?e.stack:e+""}),o.incrementCounter("mcp_connection_errors",1,{type:"sse",error:e instanceof Error?e.name:"unknown"}),t.headersSent?t.end():t.status(500).json({success:!1,error:"Failed to establish SSE connection",message:(0,
|
|
492
|
+
try{await r.createSseConnection(t,e.headers["user-agent"]),t.on("close",(()=>{s.info("SSE connection closed"),o.setGauge("mcp_active_connections",0,{type:"sse"}),r.cleanupSSEConnection()}))}catch(e){s.error("Failed to establish MCP SSE connection",{error:e instanceof Error?e.stack:e+""}),o.incrementCounter("mcp_connection_errors",1,{type:"sse",error:e instanceof Error?e.name:"unknown"}),t.headersSent?t.end():t.status(500).json({success:!1,error:"Failed to establish SSE connection",message:(0,b.getErrorMessage)(e)})}})),e.get("/api/files/exists",W,(async(e,t,r)=>{try{o.incrementCounter("api_requests_total",1,{endpoint:"files/exists",method:"GET"})
|
|
494
493
|
const r=H("api_request_duration")
|
|
495
494
|
try{const n=await l.default.stat(e.fullPath)
|
|
496
495
|
r({endpoint:"files/exists",method:"GET",success:!0}),t.json({success:!0,data:{exists:!0,isDirectory:n.isDirectory(),isFile:n.isFile(),size:n.size,modified:n.mtime}})}catch(e){if("ENOENT"!==e.code)throw e
|
|
@@ -540,7 +539,7 @@ r.getContext(),s.info("Manual project synchronization requested"),s.info("Starti
|
|
|
540
539
|
try{await x.syncProjects(),e({endpoint:"sync/projects",method:"POST",success:!0}),t.json({success:!0,data:{message:"Project synchronization completed successfully",timestamp:(new Date).toISOString()}})}catch(r){s.error("Project synchronization failed",{error:r instanceof Error?r.stack:r+""}),e({endpoint:"sync/projects",method:"POST",success:!1}),t.status(500).json({success:!1,error:"Project synchronization failed",message:r instanceof Error?r.message:r+"",timestamp:(new Date).toISOString()})}}catch(e){n(e)}})),e.get("/api/remote/status",(async(e,t,r)=>{try{o.incrementCounter("api_requests_total",1,{endpoint:"remote/status",method:"GET"})
|
|
541
540
|
const e=H("api_request_duration")
|
|
542
541
|
try{const r=await x.pingDetailed(),n="online"===r.status,o=r.latency
|
|
543
|
-
e({endpoint:"remote/status",method:"GET",success:!0,connected:n}),s.info("Remote server status check",{status:n?"ONLINE":"OFFLINE",latencyMs:o}),t.json({success:!0,data:{connected:n,url:T,latency:o,queueStats:{total:0,pending:0,inProgress:0,completed:0,failed:0},isOffline:x.isOffline(),serverTime:(new Date).toISOString()}})}catch(r){e({endpoint:"remote/status",method:"GET",success:!0,connected:!1}),t.json({success:!0,data:{connected:!1,url:T,error:(0,
|
|
542
|
+
e({endpoint:"remote/status",method:"GET",success:!0,connected:n}),s.info("Remote server status check",{status:n?"ONLINE":"OFFLINE",latencyMs:o}),t.json({success:!0,data:{connected:n,url:T,latency:o,queueStats:{total:0,pending:0,inProgress:0,completed:0,failed:0},isOffline:x.isOffline(),serverTime:(new Date).toISOString()}})}catch(r){e({endpoint:"remote/status",method:"GET",success:!0,connected:!1}),t.json({success:!0,data:{connected:!1,url:T,error:(0,b.getErrorMessage)(r),serverTime:(new Date).toISOString()}})}}catch(e){r(e)}})),e.get("/api/proxy/*",(async(e,t,r)=>{try{const r=e.path.substring(11)
|
|
544
543
|
try{const n=await L.proxyGet(r,e.query)
|
|
545
544
|
t.json(n)}catch(e){if(e instanceof Error&&e.message.includes("ECONNREFUSED"))return t.status(503).json({success:!1,error:"Remote server is unreachable",remotePath:r})
|
|
546
545
|
throw e}}catch(e){r(e)}})),e.post("/api/proxy/*",U,(async(e,t,r)=>{try{const r=e.path.substring(11)
|
|
@@ -550,7 +549,7 @@ throw e}}catch(e){r(e)}})),e.patch("/api/proxy/*",U,(async(e,t,r)=>{try{const r=
|
|
|
550
549
|
try{const n=await L.proxyPatch(r,e.body)
|
|
551
550
|
t.json(n)}catch(e){if(e instanceof Error&&e.message.includes("ECONNREFUSED"))return t.status(503).json({success:!1,error:"Remote server is unreachable",remotePath:r})
|
|
552
551
|
throw e}}catch(e){r(e)}}))}
|
|
553
|
-
const a=i(t(7252)),c=i(t(6928)),l=i(t(1943)),d=t(3444),u=t(9860),h=t(6776),g=t(6476),p=t(3306),f=t(4079),m=t(3895),y=s(t(5967)),w=t(4710),k=t(5681),
|
|
552
|
+
const a=i(t(7252)),c=i(t(6928)),l=i(t(1943)),d=t(3444),u=t(9860),h=t(6776),g=t(6476),p=t(3306),f=t(4079),m=t(3895),y=s(t(5967)),w=t(4710),k=t(5681),b=t(8824),I=t(2968),v=t(6153),C=t(1887),_=t(1666),E=t(9884),q=t(922),S=t(3328)},1253(e,exports,t){var r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
554
553
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.TokenManager=void 0
|
|
555
554
|
const n=r(t(6928)),o=r(t(1943)),s=r(t(6982)),i=r(t(857)),a=t(9067),c=t(8824),l="alchemy-lab"
|
|
556
555
|
exports.TokenManager=class{constructor(e,t,r={}){this.projectId=null,this.encryptionKey=null,this.pendingAuthCheck=!1,this.tempAuthCode=null,this.CACHE_TTL_MS=6e4,this.TOKEN_CACHE={manualToken:null,encryptedToken:null,hasValidToken:null},this.initPromise=null,this.initialized=!1,this.logger=e.child({component:"token-manager"}),this.remoteServerUrl=r.remoteServerUrl||"https://api.alchemylabcode.com",this.allowInteractiveAuth=!1!==r.allowInteractiveAuth,void 0!==r.cacheTtlMs&&r.cacheTtlMs>0&&(this.CACHE_TTL_MS=r.cacheTtlMs),this.serverInstallDir=this.getModuleDir(),this.tokenDirPath=this.serverInstallDir,this.authFlow=new a.ExternalAuthFlow(e,this.remoteServerUrl),this.logger.info("TokenManager initialized",{workingDir:t,serverInstallDir:this.serverInstallDir,tokenDirPath:this.tokenDirPath,allowInteractiveAuth:this.allowInteractiveAuth,cacheTtlMs:this.CACHE_TTL_MS}),this.generateEncryptionKey()}getModuleDir(){const e=__dirname||process.cwd(),t=i.default.homedir()
|
|
@@ -614,18 +613,18 @@ const r=await fetch(t,{method:"GET",headers:{Authorization:"Bearer "+e.token,"Co
|
|
|
614
613
|
if(r.ok){const e=await r.json()
|
|
615
614
|
return this.logger.info("Token validation successful",{status:e.status||"unknown",username:e.username||"unknown"}),!0}return this.logger.info("Token validation failed - token may be invalid or expired",{status:r.status,statusText:r.statusText}),this.invalidateCache(),!1}catch(e){return e instanceof Error&&"AbortError"===e.name?(this.logger.info("Token validation request timed out - assuming offline or server unavailable"),!0):(this.logger.info("Token validation request failed",{error:(0,c.getErrorMessage)(e)}),!0)}}async hasValidAndWorkingToken(){return!!await this.hasValidToken()&&await this.validateTokenWithRemoteServer()}async isGoogleOAuthAvailable(){return await this.authFlow.isGoogleOAuthAvailable()}async startGoogleOAuthFlow(){return await this.authFlow.startGoogleOAuthFlow()}async startGoogleOAuthPolling(e,t,r,n,o){return await this.authFlow.startGoogleOAuthPolling(e,t,r,n,o)}}},1281(e,exports,t){async function r(e,t,o,s,i,a,c,l,d,u=0){let p=0,f=0,m=0
|
|
616
615
|
const y=[]
|
|
617
|
-
if(o.length>=
|
|
616
|
+
if(o.length>=I||c>10)return a.debug("Stopping search in directory - hard cap or depth limit reached",{dir:e,matchesCount:o.length,hardCap:I,depth:c}),{filesCount:p,fileMatchesCount:f,subdirCount:m,subdirStats:y}
|
|
618
617
|
try{const w=await g.default.readdir(e,{withFileTypes:!0}),v=[],C=[]
|
|
619
618
|
for(const t of w){const r=h.default.join(e,t.name)
|
|
620
|
-
if(t.isDirectory()){if(
|
|
619
|
+
if(t.isDirectory()){if(b.includes(t.name)||t.name.startsWith(".")){a.debug("Skipping excluded directory: "+t.name)
|
|
621
620
|
continue}C.push({entry:t,fullPath:r})}else if(t.isFile()){if("*"!==i&&!t.name.endsWith(i)){a.debug("Skipping file due to extension mismatch",{filename:t.name,requiredExtension:i})
|
|
622
621
|
continue}v.push({entry:t,fullPath:r})}}if(v.length>0){const e=[]
|
|
623
622
|
for(let t=0;t<v.length;t+=16)e.push(v.slice(t,t+16))
|
|
624
|
-
for(const r of e){if(o.length>=
|
|
623
|
+
for(const r of e){if(o.length>=I)break
|
|
625
624
|
const e=await Promise.all(r.map((({entry:e,fullPath:r})=>n(r,t,0,o,l,d,e.name,u))))
|
|
626
625
|
for(const t of e){p++,t.hasMatches&&f++
|
|
627
|
-
for(const e of t.matches){if(o.length>=
|
|
628
|
-
o.push(e)}}}}for(const{entry:e,fullPath:n}of C){if(o.length>=
|
|
626
|
+
for(const e of t.matches){if(o.length>=I)return{filesCount:p,fileMatchesCount:f,subdirCount:m,subdirStats:y}
|
|
627
|
+
o.push(e)}}}}for(const{entry:e,fullPath:n}of C){if(o.length>=I)break
|
|
629
628
|
m++
|
|
630
629
|
const e={path:n,filesProcessed:0,filesMatched:0,subdirectories:0,errors:[]}
|
|
631
630
|
try{const l=await r(n,t,o,s,i,a,c+1,e,d,u)
|
|
@@ -636,7 +635,7 @@ let l,d=!1
|
|
|
636
635
|
const u=async()=>{if(void 0===l)try{const t=await g.default.stat(e)
|
|
637
636
|
l=t.mtime.getTime()}catch(e){l=void 0}return l}
|
|
638
637
|
if("filename"!==s&&"both"!==s||t.test(i)&&(d=!0,await u(),c.push({file:e,line:0,text:i,modifiedTime:l,matchType:"filename"})),"content"===s||"both"===s)try{const r=(await g.default.readFile(e,"utf8")).split("\n")
|
|
639
|
-
for(let o=0;o<r.length&&n.length<
|
|
638
|
+
for(let o=0;o<r.length&&n.length<I;o++)if(t.test(r[o])){d=!0,await u()
|
|
640
639
|
const t={file:e,line:o+1,text:(0,y.truncate)(r[o].trim(),120),modifiedTime:l,matchType:"content"}
|
|
641
640
|
if(a>0){const e=Math.max(0,o-a)
|
|
642
641
|
t.contextBefore=r.slice(e,o).map((e=>(0,y.truncate)(e.trim(),120)))
|
|
@@ -663,29 +662,29 @@ var t={}
|
|
|
663
662
|
if(null!=e)for(var r=a(e),n=0;n<r.length;n++)"default"!==r[n]&&c(t,e,r[n])
|
|
664
663
|
return l(t,e),t}),u=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
665
664
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleSearch=async function(e,t,n,a,c){const l=a.child({tool:"search"}),d=c.startTimer("tool_execution_time"),u=Date.now()
|
|
666
|
-
let
|
|
667
|
-
const
|
|
665
|
+
let b=0
|
|
666
|
+
const I={searchDirectory:"",resolvedPath:"",patternInfo:{needle:"",regex:"",caseSensitive:!1,fileExtension:"",normalizedExtension:""},environmentInfo:{platform:process.platform,nodeVersion:process.version,hostname:p.default.hostname(),username:p.default.userInfo().username,workingDirectory:process.cwd(),contextBasePath:t?.basePath||"unknown"},startTime:u,endTime:0,phases:{initializationTime:0,searchTime:0,directoryListingTime:0},totalFiles:0,totalMatches:0,directoryStats:[],errors:[]}
|
|
668
667
|
try{const{needle:n,directory:p,options:v={}}=e
|
|
669
668
|
if(!n||""===n.trim())return l.info("Empty needle detected, switching to list-all mode"),await(0,w.handleListDirectory)({path:p||".",levels:v.levels||1,sortBy:v.sortBy||"name"},t,a,c)
|
|
670
|
-
if("string"!=typeof n)throw
|
|
669
|
+
if("string"!=typeof n)throw I.errors.push("Search term (needle) must be a string"),(0,f.createValidationError)("Search term (needle) must be a string")
|
|
671
670
|
let C
|
|
672
|
-
if(
|
|
671
|
+
if(I.searchDirectory=p||".",p){const{normalizedPath:e,fullPath:r}=m.validateAndNormalizePath(p,t)
|
|
673
672
|
C=r}else C=t.basePath
|
|
674
|
-
|
|
673
|
+
I.resolvedPath=C
|
|
675
674
|
let _=!1
|
|
676
675
|
try{_=(await g.default.stat(C)).isFile()}catch(e){const t=`Cannot access path ${C}: ${(0,k.getErrorMessage)(e)}`
|
|
677
|
-
throw
|
|
676
|
+
throw I.errors.push(t),Error(t)}const E=v.maxResults||50,q=v.caseSensitive||!1,S=v.useRegex||!1,T=v.fileExtension,P=v.searchIn||"content"
|
|
678
677
|
let M=void 0!==v.contextLines?v.contextLines:0
|
|
679
|
-
if(0>M?M=0:M>10&&(l.warn(`contextLines ${M} exceeds maximum of 10, clamping to 10`),M=10),!_&&!T)throw
|
|
680
|
-
let R
|
|
681
|
-
if(_)
|
|
682
|
-
else if("*"===T)
|
|
683
|
-
else if(T){let e=T;(e.startsWith("*.")||e.startsWith("*"))&&(e=e.substring(1)),
|
|
684
|
-
throw
|
|
678
|
+
if(0>M?M=0:M>10&&(l.warn(`contextLines ${M} exceeds maximum of 10, clamping to 10`),M=10),!_&&!T)throw I.errors.push('File extension is required for directory search (use "*" for any extension, or formats like "ts", ".ts", "*.ts")'),(0,f.createValidationError)('File extension is required for directory search (use "*" for any extension, or formats like "ts", ".ts", "*.ts")')
|
|
679
|
+
let j,R=""
|
|
680
|
+
if(_)R="*"
|
|
681
|
+
else if("*"===T)R="*"
|
|
682
|
+
else if(T){let e=T;(e.startsWith("*.")||e.startsWith("*"))&&(e=e.substring(1)),R=e.startsWith(".")?e:"."+e}try{j=S?q?RegExp(n):RegExp(n,"i"):q?RegExp(o(n)):RegExp(o(n),"i")}catch(e){const t=`Invalid ${S?"regex":"search"} pattern: ${(0,k.getErrorMessage)(e)}`
|
|
683
|
+
throw I.errors.push(t),(0,f.createValidationError)(t)}if(I.patternInfo={needle:n,regex:j.toString(),caseSensitive:q,fileExtension:T,normalizedExtension:R},!_)try{const e=Date.now(),t=await g.default.readdir(C,{withFileTypes:!0}),r=[],n=[]
|
|
685
684
|
for(const e of t)e.isDirectory()?r.push(e.name):e.isFile()&&n.push(e.name)
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
l.info(`Searching for "${n}" in ${x} ${C} (mode: ${P})`,{needle:n,searchTarget:x,path:C,options:{maxResults:E,caseSensitive:q,fileExtension:
|
|
685
|
+
I.initialScan={totalEntries:t.length,directories:r,files:n,firstFewFiles:n.slice(0,10),scanTime:Date.now()-e},I.phases.directoryListingTime=I.initialScan.scanTime}catch(e){const t="Failed to scan directory contents: "+(0,k.getErrorMessage)(e)
|
|
686
|
+
I.errors.push(t),l.error(t)}const x=_?"file":"directory"
|
|
687
|
+
l.info(`Searching for "${n}" in ${x} ${C} (mode: ${P})`,{needle:n,searchTarget:x,path:C,options:{maxResults:E,caseSensitive:q,fileExtension:R,searchIn:P}}),b=Date.now(),I.phases.initializationTime=b-u
|
|
689
688
|
const O=Date.now()
|
|
690
689
|
let A=[],D=0,$=0
|
|
691
690
|
try{const e=await async function(e,t,n,o,s,i){const{maxResults:a,fileExtension:c,searchIn:l,isFile:d,contextLines:u}=n,p=[]
|
|
@@ -703,15 +702,15 @@ o.errors.push(r),n.error(r)}return{matches:i,totalFiles:1}}(e,t,l,s,i,u)
|
|
|
703
702
|
const f={path:e,filesProcessed:0,filesMatched:0,subdirectories:0,errors:[]}
|
|
704
703
|
try{const{filesCount:n,fileMatchesCount:c,subdirCount:d,subdirStats:h}=await r(e,t,p,a,o,s,0,f,l,u)
|
|
705
704
|
return f.filesProcessed=n,f.filesMatched=c,f.subdirectories=d,i.directoryStats.push(f),h&&h.length>0&&i.directoryStats.push(...h),s.info("performLocalSearch completed",{totalFiles:n,matchesFound:p.length,directories:d+1}),{matches:p,totalFiles:n}}catch(t){const r="Error in performLocalSearch: "+(0,k.getErrorMessage)(t)
|
|
706
|
-
return f.errors.push(r),i.directoryStats.push(f),i.errors.push(r),s.error(r,{error:t instanceof Error?t.stack:t+"",searchPath:e}),{matches:p,totalFiles:f.filesProcessed}}}(C,
|
|
705
|
+
return f.errors.push(r),i.directoryStats.push(f),i.errors.push(r),s.error(r,{error:t instanceof Error?t.stack:t+"",searchPath:e}),{matches:p,totalFiles:f.filesProcessed}}}(C,j,{maxResults:E,fileExtension:R,searchIn:P,isFile:_,contextLines:M},R,l,I)
|
|
707
706
|
A=e.matches,D=e.totalFiles
|
|
708
707
|
const t=1e3
|
|
709
708
|
A.length>0&&A.length<=t?(A.sort(((e,t)=>void 0!==e.modifiedTime&&void 0!==t.modifiedTime?t.modifiedTime-e.modifiedTime:void 0!==e.modifiedTime&&void 0===t.modifiedTime?-1:void 0===e.modifiedTime&&void 0!==t.modifiedTime?1:0)),l.info(`Sorted ${A.length} matches by modification time (newest first)`)):A.length>t&&l.info(`Skipped sorting ${A.length} matches (exceeds hard cap of ${t} for performance)`),$=A.length,A.length>E&&(A=A.slice(0,E),l.info(`Limited results to ${E} (from ${$} total matches)`)),A.forEach((e=>{e.relativePath=function(e,t){const r=h.default.relative(e,t)
|
|
710
|
-
return r?r===h.default.basename(t)?r:r.startsWith("./")?r.substring(2):r:h.default.basename(t)}(C,e.file)})),l.info(`Local search completed: found ${$||A.length} total matches in ${D} files, returning ${A.length} results`),
|
|
711
|
-
|
|
709
|
+
return r?r===h.default.basename(t)?r:r.startsWith("./")?r.substring(2):r:h.default.basename(t)}(C,e.file)})),l.info(`Local search completed: found ${$||A.length} total matches in ${D} files, returning ${A.length} results`),I.phases.searchTime=Date.now()-O}catch(e){const t="Error during search: "+(0,k.getErrorMessage)(e)
|
|
710
|
+
I.errors.push(t),l.error(t),I.phases.searchTime=Date.now()-O}I.totalFiles=D,I.totalMatches=A.length,I.endTime=Date.now()
|
|
712
711
|
let F,N=""
|
|
713
712
|
try{if(t.getCurrentBranchContext){const e=await t.getCurrentBranchContext()
|
|
714
|
-
e.branch&&(N=e.isMain?` (searched on main branch: ${e.branch})`:` (searched on request branch: ${e.branch}${e.requestId?" for "+e.requestId:""})`)}}catch(e){l.debug("Could not get branch context",{error:e}),N=" (branch context unavailable)"}l.debug("Search diagnostic information",{diagnostic:
|
|
713
|
+
e.branch&&(N=e.isMain?` (searched on main branch: ${e.branch})`:` (searched on request branch: ${e.branch}${e.requestId?" for "+e.requestId:""})`)}}catch(e){l.debug("Could not get branch context",{error:e}),N=" (branch context unavailable)"}l.debug("Search diagnostic information",{diagnostic:I})
|
|
715
714
|
const L="content"===P?"content":"filename"===P?"filenames":"content and filenames"
|
|
716
715
|
if($>A.length?(F=`Found ${$} results for "${n}" (searching ${L})`,p&&(F+=" in "+p),T&&(F+=" with extension "+T),F+=`${N}. Showing first ${A.length}:\n\n`):(F=`Found ${A.length} results for "${n}" (searching ${L})`,p&&(F+=" in "+p),T&&(F+=" with extension "+T),F+=N+":\n\n"),A.length>0)if(M>0){const{filenameMatches:e,mergedGroups:t}=function(e,t){const r=e.filter((e=>"filename"===e.matchType)),n=e.filter((e=>"content"===e.matchType))
|
|
717
716
|
if(0===n.length)return{filenameMatches:r,mergedGroups:[]}
|
|
@@ -734,10 +733,10 @@ void 0!==s&&(a+=` (${s} lines)`),a+=` - ${o} ${1===o?"match":"matches"}:`
|
|
|
734
733
|
const c=t.map((e=>` :${e.line} - ${e.text}`))
|
|
735
734
|
n.push(a+"\n"+c.join("\n"))}return n.join("\n\n")}(A)
|
|
736
735
|
else F+="No matches found."
|
|
737
|
-
return d({success:!0}),{content:[{type:"text",text:F}]}}catch(t){l.error("Search failed",{args:e,error:t instanceof Error?t.stack:t+""}),
|
|
736
|
+
return d({success:!0}),{content:[{type:"text",text:F}]}}catch(t){l.error("Search failed",{args:e,error:t instanceof Error?t.stack:t+""}),I.errors.push((0,k.getErrorMessage)(t)),I.endTime=Date.now(),l.debug("Search diagnostic information on error",{diagnostic:I})
|
|
738
737
|
let r="Search failed: "+(0,k.getErrorMessage)(t)
|
|
739
738
|
return d({success:!1,error:t instanceof Error?t.name:"unknown"}),{content:[{type:"text",text:r}],isError:!0}}}
|
|
740
|
-
const h=u(t(6928)),g=u(t(1943)),p=u(t(857)),f=t(9860),m=d(t(5967)),y=t(5967),w=t(2537),k=t(8824),
|
|
739
|
+
const h=u(t(6928)),g=u(t(1943)),p=u(t(857)),f=t(9860),m=d(t(5967)),y=t(5967),w=t(2537),k=t(8824),b=["node_modules"],I=1e4,v=new Set([".ts",".tsx",".js",".jsx",".mjs",".cjs",".py",".rb",".go",".rs",".java",".kt",".scala",".c",".cpp",".h",".hpp",".cs",".html",".css",".scss",".sass",".less",".json",".yaml",".yml",".toml",".xml",".md",".txt",".csv",".sql",".sh",".bash",".zsh",".fish",".vim",".lua",".php",".swift",".m",".vue",".svelte",".astro",".env",".gitignore",".dockerignore"]),C=1048576},1318(e,exports,t){async function r(e,t,r){try{const r=(await e.revparse(["--show-toplevel"])).trim(),n=c.default.isAbsolute(t)?t:c.default.resolve(t)
|
|
741
740
|
return c.default.relative(r,n)}catch(e){return r.warn("Failed to get repo-relative path, using original",{filePath:t,error:(0,l.getErrorMessage)(e)}),t}}function n(e){return/\(trec\d{6}\)/.test(e)}async function o(e,t,n,o,s){try{const i=await r(e,t,s),a=await e.raw(["log","-1","--pretty=format:%H|%s",`-L${n},${o}:${i}`])
|
|
742
741
|
if(!a||""===a.trim())return null
|
|
743
742
|
const c=a.trim().split("\n")[0],[l,...d]=c.split("|"),u=d.join("|")
|
|
@@ -813,38 +812,34 @@ try{return await i.hasValidToken()}catch(e){return m.error("Error checking authe
|
|
|
813
812
|
m.info(`Generating tools list with testsRequired=${e}, authenticated=${t}`)
|
|
814
813
|
const r={testsRequired:e,authenticated:t}
|
|
815
814
|
return(0,f.generateVisibleToolsList)(r)}
|
|
816
|
-
let
|
|
817
|
-
|
|
815
|
+
let b=k(),I=[]
|
|
816
|
+
b.then((e=>{I=e})).catch((e=>{m.error("Error generating initial tools list",{error:(0,l.getErrorMessage)(e)}),I=[]})),e.setRequestHandler(a.ListToolsRequestSchema,(async()=>{try{return I=await k(),{tools:I}}catch(e){return m.error("Error generating tools list",{error:(0,l.getErrorMessage)(e)}),{tools:[]}}}))
|
|
818
817
|
let v=!1
|
|
819
818
|
e.setRequestHandler(a.CallToolRequestSchema,(async e=>{try{const{name:i,arguments:a={},_meta:c}=e.params;(0,p.logSessionIdentity)(i,"_meta-debug",{has_meta:!!c,sessionId:c?.sessionId||null,messageId:c?.messageId||null,paramKeys:Object.keys(e.params)}),m.info("Tool call received: "+i,{tool:i}),s.incrementCounter("tool_calls_total",1,{tool:i})
|
|
820
819
|
const k=s.startTimer("tool_execution_time")
|
|
821
820
|
Date.now()
|
|
822
|
-
let
|
|
823
|
-
const
|
|
824
|
-
if(Date.now(),
|
|
821
|
+
let b=Date.now()
|
|
822
|
+
const I=r(a)
|
|
823
|
+
if(Date.now(),b=Date.now(),y){const e=await w()
|
|
825
824
|
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
|
-
let _
|
|
827
|
-
if(
|
|
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?.())
|
|
825
|
+
let _
|
|
826
|
+
if(b=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(),b=Date.now(),c?.sessionId){const e=c.sessionId,r=c.messageId,n=u.sessionIdentity.getIdentity()
|
|
827
|
+
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?.(e))
|
|
829
828
|
else{const r=await(0,d.getServerUrl)(t,m)
|
|
830
|
-
u.sessionIdentity.setIdentity({providerId:"opencode",sessionId:e,serverUrl:r||""})
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
else{m.info("Session identity mismatch: tool call not found in cached session, re-discovering",{prevSessionId:e.sessionId,prevAgentType:e.agentType,tool:i}),u.sessionIdentity.reset(),t?.workspaceManager?.resetCurrentContext?.()
|
|
835
|
-
try{const t=await(0,d.getAndStoreSessionId)(e.serverUrl,m,i)
|
|
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)
|
|
837
|
-
if(e){const t=await(0,d.getAndStoreSessionId)(e,m,i)
|
|
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()
|
|
829
|
+
u.sessionIdentity.setIdentity({providerId:"opencode",sessionId:e,serverUrl:r||""})}_={providerId:"opencode",sessionId:e,messageId:r,createdAt:(new Date).toISOString()},(0,p.logSessionIdentity)(i,"_meta",{sessionId:e,messageId:r})}else m.warn("No _meta.sessionId on tool call \u2014 session identity unavailable",{tool:i})
|
|
830
|
+
u.sessionIdentity.setCurrentCallOrigin(_)
|
|
831
|
+
const E=_?.sessionId||c?.sessionId
|
|
832
|
+
if(t?.workspaceManager){b=Date.now()
|
|
839
833
|
try{const e=await(0,d.getServerUrl)(t,m)
|
|
840
|
-
e&&n&&await t.workspaceManager.ensureReadonlyBranchIfNeeded(e,i,n,
|
|
834
|
+
e&&n&&await t.workspaceManager.ensureReadonlyBranchIfNeeded(e,i,n,E)}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
|
|
841
835
|
if(e?.sessionId&&t){const r=t.match(/^requests\/(.+)$/),o="1"===process.env.ALCHEMY_ALLOW_PARALLEL
|
|
842
836
|
if(r&&!o){const t=r[1]
|
|
843
837
|
v=!0
|
|
844
838
|
try{const{sessionTag:r}=(0,h.getGlobalClientInfo)(),o=n.getSessionTagMappingClient(),s=n.getRequestClient(),i=o?o.getMappingByOpencodeSessionId(e.sessionId).then((t=>{t?((0,h.setSessionTag)(t.sessionTag),m.info("Recovered session tag from mapping",{opencodeSessionId:e.sessionId,sessionTag:t.sessionTag})):(o.createOrUpdateMapping(r,e.sessionId).catch((()=>{})),m.info("Registered session tag mapping",{opencodeSessionId:e.sessionId,sessionTag:r}))}),(e=>m.debug("Mapping lookup failed",{error:(0,l.getErrorMessage)(e)}))):Promise.resolve(),a=s.lockRequest?s.lockRequest(t,r).then((e=>{e.locked?m.info("Acquired request lock",{requestId:t,sessionTag:r}):m.warn("Failed to acquire request lock",{requestId:t,sessionTag:r})}),(e=>m.warn("Lock acquisition failed",{error:(0,l.getErrorMessage)(e)}))):Promise.resolve()
|
|
845
|
-
await Promise.all([i,a])}catch(e){m.warn("Error in session tag mapping / lock acquisition",{error:(0,l.getErrorMessage)(e)})}}}}
|
|
846
|
-
|
|
847
|
-
|
|
839
|
+
await Promise.all([i,a])}catch(e){m.warn("Error in session tag mapping / lock acquisition",{error:(0,l.getErrorMessage)(e)})}}}}let q
|
|
840
|
+
if(C){const e={context:t,apiClient:n,logger:o,metrics:s,mcpServer:g,cliOrigin:_}
|
|
841
|
+
q=await C.handler(I,e)}else m.info(`Tool ${i} not found, returning negative response`),q={content:[{type:"text",text:`The tool '${i}' does not exist.`}]}
|
|
842
|
+
return Date.now(),Date.now(),k({tool:i,success:!0}),q}catch(t){m.error("Error executing tool:",{error:t instanceof Error?t.stack:t+"",tool:e.params.name}),s.incrementCounter("tool_errors_total",1,{tool:e.params.name,error:t instanceof Error?t.name:"unknown"})
|
|
848
843
|
let r="Unknown error"
|
|
849
844
|
if(t instanceof Error)r=t.message
|
|
850
845
|
else if("string"==typeof t)r=t
|
|
@@ -1181,88 +1176,87 @@ const e=this.online,t=await this.performHealthCheck()
|
|
|
1181
1176
|
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
|
|
1182
1177
|
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
|
|
1183
1178
|
const r=t(6183),n=t(355)
|
|
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:${
|
|
1179
|
+
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:${j}/api/agents/by-name/${encodeURIComponent(e)}`,r=await fetch(t)
|
|
1185
1180
|
if(!r.ok)return null
|
|
1186
1181
|
const n=await r.json()
|
|
1187
1182
|
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
|
|
1188
1183
|
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=
|
|
1190
|
-
let
|
|
1191
|
-
if(r(t,"Spawn agent type check",{
|
|
1192
|
-
r(t,"Looking up agent type from action server",{sessionId:
|
|
1193
|
-
const s=await fetch(
|
|
1194
|
-
if(s.ok){const
|
|
1195
|
-
r(t,"Agent type response from action server",{sessionId:
|
|
1196
|
-
if(e&&!e.includes(a))return{content:[{type:"text",text:`\u274c Agent type '${
|
|
1184
|
+
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=i?.sessionId
|
|
1185
|
+
let n=v.sessionIdentity.getIdentity()?.agentType
|
|
1186
|
+
if(r(t,"Spawn agent type check",{callerSessionId:e||null,cachedAgentType:n||null,pid:process.pid}),!n&&e)try{const o=`http://localhost:${j}/api/sessions/${encodeURIComponent(e)}/agent-type`
|
|
1187
|
+
r(t,"Looking up agent type from action server",{sessionId:e,url:o})
|
|
1188
|
+
const s=await fetch(o)
|
|
1189
|
+
if(s.ok){const o=await s.json()
|
|
1190
|
+
r(t,"Agent type response from action server",{sessionId:e,agentType:o.agentType||null,source:o.source||null,success:o.success}),o.success&&o.agentType&&(n=o.agentType,v.sessionIdentity.updateIdentity({agentType:n}))}else r(t,"Agent type lookup failed",{sessionId:e,status:s.status})}catch(n){r(t,"Agent type lookup error",{sessionId:e,error:(0,q.getErrorMessage)(n)})}if(n){const e=(0,P.getAllowedSubagents)(n)
|
|
1191
|
+
if(e&&!e.includes(a))return{content:[{type:"text",text:`\u274c Agent type '${n}' cannot spawn '${a}'.\n\n**Allowed subagents for ${n}:** ${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
|
|
1197
1192
|
try{const e=await n(a)
|
|
1198
1193
|
if(h=e?.requestContextMode,!h){const e=(0,P.getBuiltInAgentConfig)(a)
|
|
1199
1194
|
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}
|
|
1200
|
-
const g=await(0,
|
|
1195
|
+
const g=await(0,I.getServerUrl)(t,o)
|
|
1201
1196
|
r(t,"serverUrl resolved",{serverUrl:g})
|
|
1202
1197
|
const p=t.basePath
|
|
1203
1198
|
if(!p)throw new w.ValidationError("Working directory not available in context")
|
|
1204
|
-
const f=
|
|
1205
|
-
let m
|
|
1206
|
-
if(g)try{m=i?.sessionId||f?.sessionId||await(0,b.discoverParentSessionId)(g,o)}catch{}let y=""
|
|
1199
|
+
const f=i?.sessionId
|
|
1200
|
+
let m=""
|
|
1207
1201
|
if(s&&l)try{const e=s.getSessionRequestAssociationClient()
|
|
1208
|
-
if(e){const t=await e.getSessionsForRequest(l,!0),r=
|
|
1202
|
+
if(e){const t=await e.getSessionsForRequest(l,!0),r=f?t.filter((e=>e.opencodeSessionId!==f)):t
|
|
1209
1203
|
if(r.length>0){const e=r.map((e=>e.opencodeSessionId)).join(", ")
|
|
1210
1204
|
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}
|
|
1211
|
-
|
|
1212
|
-
l&&(
|
|
1213
|
-
let
|
|
1214
|
-
if(u){if(
|
|
1205
|
+
m=`\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 y,_,E=c
|
|
1206
|
+
l&&(y="requests/"+l,r(t,"Setting initialBranch for agent",{agent:a,requestId:l,initialBranch:y,agentRequestContextMode:h||"undefined"}),E="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}`)
|
|
1207
|
+
let S=!1
|
|
1208
|
+
if(u){if(_=u,o.info("Using existing session for spawn",{sessionId:_,requestId:l}),!g)throw new w.ValidationError("Could not determine OpenCode server URL")
|
|
1215
1209
|
try{let e
|
|
1216
|
-
try{const t=await fetch(`http://localhost:${
|
|
1210
|
+
try{const t=await fetch(`http://localhost:${j}/api/project-settings`)
|
|
1217
1211
|
if(t.ok){const r=await t.json()
|
|
1218
1212
|
if(r.data?.defaultModel){const[t,...n]=r.data.defaultModel.split("/")
|
|
1219
|
-
e={providerID:t,modelID:n.join("/")}}}}catch{}const t=`${g.replace(/\/$/,"")}/session/${
|
|
1213
|
+
e={providerID:t,modelID:n.join("/")}}}}catch{}const t=`${g.replace(/\/$/,"")}/session/${_}/prompt_async`,r=await fetch(t,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({parts:[{type:"text",text:E}],...a?{agent:a}:{},...e?{model:e}:{}}),signal:AbortSignal.timeout(1e4)})
|
|
1220
1214
|
if(!r.ok){const e=await r.text().catch((()=>"Unknown error"))
|
|
1221
|
-
throw Error(`Failed to send to existing session: ${r.status} ${e}`)}o.info("Prompt sent to existing session",{sessionId:
|
|
1222
|
-
const i=
|
|
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?"...":""}`,
|
|
1224
|
-
if(!
|
|
1225
|
-
const w=await
|
|
1215
|
+
throw Error(`Failed to send to existing session: ${r.status} ${e}`)}o.info("Prompt sent to existing session",{sessionId:_,agent:a})}catch(e){throw Error("Failed to use existing session: "+(0,q.getErrorMessage)(e))}}else{if(S=!0,r(t,"Creating session via HTTP and spawning CLI"),!g)throw Error("Cannot spawn subagent: no server URL available")
|
|
1216
|
+
const i=f;(0,C.logSessionIdentity)("subagent_operations.spawn","_meta",{parentSessionId:i}),r(t,"Parent session discovered",{parentSessionId:i})
|
|
1217
|
+
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?"...":""}`,m=await fetch(u,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({parentID:i,title:h})})
|
|
1218
|
+
if(!m.ok)throw Error("Failed to create session: "+m.status)
|
|
1219
|
+
const w=await m.json()
|
|
1226
1220
|
if(!w.id)throw Error("Session created but no ID returned")
|
|
1227
|
-
const
|
|
1228
|
-
r(t,"Pre-created session with parentID",{preCreatedSessionId:
|
|
1229
|
-
const
|
|
1221
|
+
const I=w.id
|
|
1222
|
+
r(t,"Pre-created session with parentID",{preCreatedSessionId:I,parentSessionId:i}),o.info("Pre-created session with parentID",{preCreatedSessionId:I,parentSessionId:i})
|
|
1223
|
+
const T=(async()=>{if(s)try{const n=s.getCLISessionClient()
|
|
1230
1224
|
if(!n)return
|
|
1231
1225
|
let o,c
|
|
1232
|
-
if(i){const e=await n.createOrUpdateSession({externalSessionId:i,providerId:"opencode",status:"active",agentType:
|
|
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:
|
|
1234
|
-
r(t,"Registered child session in DB",{childSessionId:
|
|
1235
|
-
let
|
|
1226
|
+
if(i){const e=await n.createOrUpdateSession({externalSessionId:i,providerId:"opencode",status:"active",agentType:v.sessionIdentity.getIdentity()?.agentType||void 0})
|
|
1227
|
+
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:I,providerId:"opencode",parentSessionId:o||null,title:h,status:"active",agentType:a,specialization:e.specialization,workflowId:c||void 0})
|
|
1228
|
+
r(t,"Registered child session in DB",{childSessionId:I,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)})}})()
|
|
1229
|
+
let R
|
|
1236
1230
|
r(t,"Starting model resolution",{agent:a,cwd:p})
|
|
1237
|
-
try{r(t,"Fetching agent config from action server",{agent:a,url:`http://localhost:${
|
|
1231
|
+
try{r(t,"Fetching agent config from action server",{agent:a,url:`http://localhost:${j}/api/agents/by-name/${a}`})
|
|
1238
1232
|
const e=await n(a)
|
|
1239
1233
|
if(r(t,"Agent config result",{agent:a,agentConfig:e||"null",hasConfig:!!e}),e){const n=e.preferredProvider||"inherit",o=e.preferredModelTier||"same"
|
|
1240
1234
|
r(t,"Agent preferences",{agent:a,preferredProvider:n,preferredTier:o,rawProvider:e.preferredProvider,rawTier:e.preferredModelTier})
|
|
1241
1235
|
const s=(0,M.resolveAgentModel)(p,n,o)
|
|
1242
|
-
r(t,"Model resolution result",{agent:a,result:s}),s.resolved?(
|
|
1236
|
+
r(t,"Model resolution result",{agent:a,result:s}),s.resolved?(R=s.fullModel,r(t,"Resolved agent model",{agent:a,model:R,preferredProvider:n,preferredTier:o})):r(t,"Model resolution fallback",{agent:a,reason:s.reason})}else{const e=(0,P.getBuiltInAgentConfig)(a)
|
|
1243
1237
|
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"
|
|
1244
1238
|
r(t,"Using built-in agent preferences",{agent:a,preferredProvider:n,preferredTier:o})
|
|
1245
1239
|
const s=(0,M.resolveAgentModel)(p,n,o)
|
|
1246
|
-
r(t,"Built-in model resolution result",{agent:a,result:s}),s.resolved&&(
|
|
1240
|
+
r(t,"Built-in model resolution result",{agent:a,result:s}),s.resolved&&(R=s.fullModel,r(t,"Resolved built-in agent model",{agent:a,model:R,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:${j}/api/project-settings`,t=await fetch(e)
|
|
1247
1241
|
if(t.ok){const e=await t.json()
|
|
1248
1242
|
return e?.data?.defaultModel||null}}catch{}return null}()
|
|
1249
|
-
if(e)if(
|
|
1250
|
-
"same"===(o?.preferredModelTier||"same")&&(
|
|
1251
|
-
if(!
|
|
1252
|
-
|
|
1253
|
-
if(e&&(e.createAssociation(
|
|
1254
|
-
e&&e.updateRequest(l,{cliOrigin:{providerId:"opencode",sessionId:
|
|
1255
|
-
return u?
|
|
1243
|
+
if(e)if(R){const o=await n(a)
|
|
1244
|
+
"same"===(o?.preferredModelTier||"same")&&(R=e,r(t,"Applied user default model (same tier)",{agent:a,userDefaultModel:e}))}else R=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:R||"undefined (will use default)"}),await T,l&&y)try{await(0,b.ensureRequestWorktree)(p,l,o)}catch(e){r(t,"Pre-spawn worktree creation failed (non-fatal)",{requestId:l,error:(0,q.getErrorMessage)(e)})}const x=(0,k.spawnDetachedSubagent)({agent:a,prompt:E,cwd:p,sessionId:I,model:R,initialBranch:y,allowParallel:d,serverUrl:g})
|
|
1245
|
+
if(!x.success)throw Error("Failed to spawn subagent: "+x.error)
|
|
1246
|
+
_=I,r(t,"CLI spawn successful with pre-created session",{sessionId:I,pid:x.pid,parentSessionId:i}),o.info("Background subagent spawned via CLI with pre-created session",{agent:a,requestId:l,sessionId:I,pid:x.pid,parentSessionId:i})}if(s&&l&&_&&"unknown"!==_&&"spawning"!==_)try{const e=s.getSessionRequestAssociationClient()
|
|
1247
|
+
if(e&&(e.createAssociation(_,l).then((()=>o.info("Created session-request association",{sessionId:_,requestId:l}))).catch((e=>o.warn("Failed to create session-request association",{error:(0,q.getErrorMessage)(e),sessionId:_,requestId:l}))),"coder"===a)){const e=s.getRequestClient()
|
|
1248
|
+
e&&e.updateRequest(l,{cliOrigin:{providerId:"opencode",sessionId:_,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:_,requestId:l})}let T=m
|
|
1249
|
+
return u?T+=`Prompt sent to existing session ${_}.`:(T+=`Background ${a} subagent spawned successfully.`,_&&"unknown"!==_&&"spawning"!==_&&(T+=`\n[SESSION:${_}]`)),l&&(T+="\nWorking on: "+l),T+="\n\nThe subagent is now working independently. You can continue with other tasks.",{content:[{type:"text",text:T}]}}async function s(e,t,r,n,o,s,i){const a=await(0,I.getServerUrl)(r,n)
|
|
1256
1250
|
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
|
|
1251
|
+
if(n.info("Sending message to subagent session",{sessionId:e,promptLength:t.length}),o)try{const t=i?.sessionId
|
|
1258
1252
|
if(t){const r=o.getCLISessionClient()
|
|
1259
1253
|
if(r){let o=await r.getByExternalId(t)
|
|
1260
1254
|
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:${
|
|
1255
|
+
if(!c)try{const t=`http://localhost:${j}/api/sessions/${encodeURIComponent(e)}/agent-type`,r=await fetch(t)
|
|
1262
1256
|
if(r.ok){const e=await r.json()
|
|
1263
1257
|
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
1258
|
try{let r
|
|
1265
|
-
try{const e=await fetch(`http://localhost:${
|
|
1259
|
+
try{const e=await fetch(`http://localhost:${j}/api/project-settings`)
|
|
1266
1260
|
if(e.ok){const t=await e.json()
|
|
1267
1261
|
if(t.data?.defaultModel){const[e,...n]=t.data.defaultModel.split("/")
|
|
1268
1262
|
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)})
|
|
@@ -1277,10 +1271,10 @@ const s=n.path||n.file||n.directory,i=n.needle||n.query||n.pattern
|
|
|
1277
1271
|
"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
1272
|
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
1273
|
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&&
|
|
1274
|
+
return e&&R>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
1275
|
for(const o of e.trim().split("\n")){if(!o)continue
|
|
1282
1276
|
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,
|
|
1277
|
+
"-"!==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,I.getServerUrl)(r,n)
|
|
1284
1278
|
if(!s)throw new w.ValidationError("Could not determine OpenCode server URL")
|
|
1285
1279
|
n.info("Checking status of subagent session",{sessionId:e})
|
|
1286
1280
|
try{const c=`${s.replace(/\/$/,"")}/session/${e}`,u=await fetch(c)
|
|
@@ -1290,7 +1284,7 @@ let f={input:0,output:0,reasoning:0},m="",y=l(null,h.time.updated)
|
|
|
1290
1284
|
if(p.ok){const e=await p.json()
|
|
1291
1285
|
for(const t of e)"assistant"===t.info.role&&t.info.tokens&&(f.input+=t.info.tokens.input||0,f.output+=t.info.tokens.output||0,f.reasoning+=t.info.tokens.reasoning||0)
|
|
1292
1286
|
const t=a(e)
|
|
1293
|
-
y=l(t.lastActivityTime,h.time.updated),t.current&&(m+="\nCurrent: "+t.current),t.recent.length>0&&(m+="\nRecent: "+t.recent.join(", "))}const w=Date.now()-h.time.created,k=y.status,
|
|
1287
|
+
y=l(t.lastActivityTime,h.time.updated),t.current&&(m+="\nCurrent: "+t.current),t.recent.length>0&&(m+="\nRecent: "+t.recent.join(", "))}const w=Date.now()-h.time.created,k=y.status,b=y.isReady,I=f.input+f.output+f.reasoning
|
|
1294
1288
|
let v="",C="",_=null
|
|
1295
1289
|
if(o)try{const t=o.getSessionRequestAssociationClient()
|
|
1296
1290
|
if(t){const r=await t.getActiveRequestsForSession(e,!1)
|
|
@@ -1305,12 +1299,12 @@ if(e.trim())return d(e)}try{const t=n(`git log main --merges --oneline -n 50 --g
|
|
|
1305
1299
|
if(t){const e=t.split("\n")[0].split(" ")[0],o=n(`git diff ${e}^1...${e} --numstat`,{cwd:r,encoding:"utf8"})
|
|
1306
1300
|
if(o.trim())return{...d(o),merged:!0}}}catch{}return null}catch{return null}}(_,r.basePath)
|
|
1307
1301
|
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: ${
|
|
1302
|
+
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: ${b?"Yes":"No"}\nAge: ${i(w)}\nTokens: ${I.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,I.getServerUrl)(t,r)
|
|
1309
1303
|
if(!n)throw new w.ValidationError("Could not determine OpenCode server URL")
|
|
1310
1304
|
r.info("Aborting subagent session",{sessionId:e})
|
|
1311
1305
|
try{const t=`${n.replace(/\/$/,"")}/session/${e}/abort`,o=await fetch(t,{method:"POST"})
|
|
1312
1306
|
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,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,
|
|
1307
|
+
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,I.getServerUrl)(e,t)
|
|
1314
1308
|
if(!g)throw new w.ValidationError("Could not determine OpenCode server URL")
|
|
1315
1309
|
t.info("Listing sessions",{filters:n})
|
|
1316
1310
|
try{const e=g.replace(/\/$/,"")+"/session",t=await fetch(e)
|
|
@@ -1324,10 +1318,10 @@ if(o&&(w=w.filter((e=>"idle"!==(y[e.id]?.type||"idle")))),void 0!==h){const e=36
|
|
|
1324
1318
|
w=w.filter((e=>e.time.created>=t))}if(0===w.length)return{content:[{type:"text",text:"No sessions match the specified filters."}]}
|
|
1325
1319
|
let k={}
|
|
1326
1320
|
if(r)try{const e=r.getCLISessionClient()
|
|
1327
|
-
e&&(k=await e.batchEnrich(w.map((e=>e.id))))}catch{}const
|
|
1321
|
+
e&&(k=await e.batchEnrich(w.map((e=>e.id))))}catch{}const b=g.replace(/\/$/,""),I=await Promise.allSettled(w.map((e=>fetch(`${b}/session/${e.id}/message`).then((e=>e.ok?e.json():[])).catch((()=>[]))))),v=[]
|
|
1328
1322
|
for(let e=0;e<w.length;e++){const t=w[e],r=Date.now()-t.time.created
|
|
1329
1323
|
let o=0,i=null,c=[],h=l(null,t.time.updated)
|
|
1330
|
-
const g=
|
|
1324
|
+
const g=I[e],p="fulfilled"===g.status?g.value:[]
|
|
1331
1325
|
for(const e of p)"assistant"===e.info.role&&e.info.tokens&&(o+=(e.info.tokens.input||0)+(e.info.tokens.output||0)+(e.info.tokens.reasoning||0))
|
|
1332
1326
|
if(p.length>0){const e=a(p)
|
|
1333
1327
|
h=l(e.lastActivityTime,t.time.updated),i=e.current||null,c=e.recent}const f=h.status
|
|
@@ -1337,13 +1331,13 @@ const m=k[t.id]
|
|
|
1337
1331
|
if(n.agentType&&(!m||m.agentType!==n.agentType))continue
|
|
1338
1332
|
if("archived"===m?.status)continue
|
|
1339
1333
|
let y=""
|
|
1340
|
-
const
|
|
1334
|
+
const b=[]
|
|
1341
1335
|
if(m?.associations&&m.associations.length>0){const e=m.associations.filter((e=>!e.endedAt)).map((e=>e.requestLocalId)),t=m.associations.filter((e=>e.endedAt)).map((e=>e.requestLocalId))
|
|
1342
|
-
|
|
1336
|
+
b.push(...e,...t)
|
|
1343
1337
|
const r=[]
|
|
1344
|
-
e.length>0&&r.push("active: "+e.join(", ")),t.length>0&&r.push("prev: "+t.join(", ")),r.length>0&&(y=` [${r.join(" | ")}]`)}if(s&&!
|
|
1338
|
+
e.length>0&&r.push("active: "+e.join(", ")),t.length>0&&r.push("prev: "+t.join(", ")),r.length>0&&(y=` [${r.join(" | ")}]`)}if(s&&!b.includes(s))continue
|
|
1345
1339
|
const C=t.title||"Untitled",_=C.length>50?C.slice(0,47)+"...":C
|
|
1346
|
-
v.push({id:t.id,title:_,status:f,age:r,totalTokens:o,requestsInfo:y,allRequestIds:
|
|
1340
|
+
v.push({id:t.id,title:_,status:f,age:r,totalTokens:o,requestsInfo:y,allRequestIds:b,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
1341
|
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
1342
|
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
1343
|
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)
|
|
@@ -1367,7 +1361,7 @@ break
|
|
|
1367
1361
|
case"abort":f=await h(d,t,c)
|
|
1368
1362
|
break
|
|
1369
1363
|
case"read-messages":const e=r.readMessages?.limit??1
|
|
1370
|
-
f=await async function(e,t,r,n){const o=await(0,
|
|
1364
|
+
f=await async function(e,t,r,n){const o=await(0,I.getServerUrl)(r,n)
|
|
1371
1365
|
if(!o)throw new w.ValidationError("Could not determine OpenCode server URL")
|
|
1372
1366
|
n.info("Reading messages from subagent session",{sessionId:e,limit:t})
|
|
1373
1367
|
try{const r=`${o.replace(/\/$/,"")}/session/${e}/message?limit=${t}`,n=await fetch(r)
|
|
@@ -1378,11 +1372,11 @@ const i=s.map(((e,t)=>{const r="user"===e.info.role?"USER":"ASSISTANT",n=e.parts
|
|
|
1378
1372
|
return`[${t+1}] ${r} (${new Date(e.info.time.created).toLocaleTimeString()}):\n${o}`})).join("\n\n---\n\n")
|
|
1379
1373
|
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
1374
|
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
|
|
1375
|
+
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}
|
|
1382
1376
|
f=await g(t,c,i,n)
|
|
1383
1377
|
break
|
|
1384
1378
|
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),
|
|
1379
|
+
const w=t(9860),k=t(8035),b=t(2424),I=t(7617),v=t(6688),C=t(7280),_=t(6183),E=y(t(5967)),q=t(8824),S=t(9896),T=t(6928),P=t(8955),M=t(5671),j=3456,R=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
1380
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.ProjectContext=void 0,exports.projectContextMiddleware=r
|
|
1387
1381
|
const o=n(t(9896)),s=n(t(6928)),i=t(4139),a=t(4055),c=t(8824)
|
|
1388
1382
|
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")
|
|
@@ -1673,26 +1667,26 @@ var t={}
|
|
|
1673
1667
|
if(null!=e)for(var s=r(e),i=0;i<s.length;i++)"default"!==s[i]&&n(t,e,s[i])
|
|
1674
1668
|
return o(t,e),t}),i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
1675
1669
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleMoveFiles=async function(e,t,r,n,o,s,i,f){const m=s.child({tool:"move_files"}),y=Date.now()
|
|
1676
|
-
let w,k,
|
|
1677
|
-
const
|
|
1670
|
+
let w,k,b=d.FileOperationPhase.VALIDATION
|
|
1671
|
+
const I={toolName:"move-files",operationName:"write",fileOperationPhase:d.FileOperationPhase.FILE_WRITE,recordType:"move-files",metricsPrefix:"move_files",successMessage:"Successfully moved files",failureMessage:"Failed to move files"}
|
|
1678
1672
|
try{const s=d.validateArgs(e,l.MoveFilesSchema),{taskId:u,operations:h,comment:v}=s
|
|
1679
1673
|
if(m.info("Moving multiple files and directories",{taskId:u,operationCount:h.length,comment:v}),!h||0===h.length)throw Error("At least one move operation must be specified")
|
|
1680
|
-
d.validateTaskIdFormat(u,m,i,
|
|
1674
|
+
d.validateTaskIdFormat(u,m,i,I.metricsPrefix)
|
|
1681
1675
|
const C=t.getCurrentBranchContext?await t.getCurrentBranchContext():{branch:null,requestId:null,isMain:!0}
|
|
1682
1676
|
m.info("Initial branch context",{initialBranch:C.branch,initialRequestId:C.requestId,isMain:C.isMain})
|
|
1683
1677
|
const _=[]
|
|
1684
1678
|
for(const e of h){const{normalizedPath:r,fullPath:n}=d.validateAndNormalizePath(e.source,t),{normalizedPath:o,fullPath:s}=d.validateAndNormalizePath(e.destination,t)
|
|
1685
|
-
_.push({source:r,destination:o,fullSource:n,fullDestination:s})}
|
|
1686
|
-
const E=await d.validateTaskId(u,_[0].source,r,m,i,
|
|
1679
|
+
_.push({source:r,destination:o,fullSource:n,fullDestination:s})}b=d.FileOperationPhase.TASK_VALIDATION,i.incrementCounter("move_files_phase",1,{phase:b})
|
|
1680
|
+
const E=await d.validateTaskId(u,_[0].source,r,m,i,I.metricsPrefix),q=E?.requestId,S=await d.validateWorkItemStates(u,_[0].source,r,o,t,m,i,I.metricsPrefix),T=await d.autoPromoteTaskStatus(u,E.status,q,S.request?.status,_[0].source,r,o,m,i,I.metricsPrefix)
|
|
1687
1681
|
T.taskPromoted&&m.info(`Auto-promoted task ${u} (${E.title||"Untitled"}) to in_progress for file operations`,{taskId:u,taskTitle:E.title,previousStatus:E.status,newStatus:T.newTaskStatus,operationCount:h.length}),T.requestPromoted&&m.info(`Auto-promoted request ${q} to in_progress for file operations`,{requestId:q,previousStatus:S.request?.status,newStatus:T.newRequestStatus,triggeringTaskId:u})
|
|
1688
|
-
const P=await d.ensureCorrectWorkspaceContext({taskPromoted:T.taskPromoted,requestId:q,context:t,operation:"move-files",logger:m,metrics:i,metricsPrefix:
|
|
1682
|
+
const P=await d.ensureCorrectWorkspaceContext({taskPromoted:T.taskPromoted,requestId:q,context:t,operation:"move-files",logger:m,metrics:i,metricsPrefix:I.metricsPrefix})
|
|
1689
1683
|
if(!P.success){if(P.isLockConflict)return{content:[{type:"text",text:"\u274c "+P.error}],isError:!0}
|
|
1690
1684
|
throw Error(P.error)}let M={hadUserMods:!1,userModsCommitHash:void 0}
|
|
1691
1685
|
if(t.git)try{m.debug("[MOVE-FILES] Checking for user changes before move operations")
|
|
1692
1686
|
const e=await(0,g.commitUserChangesBeforeToolOperation)(t.git,"move-files",{requestId:q,taskId:u,workspaceManager:t.workspaceManager},m,i)
|
|
1693
|
-
e.userChangesCommitted&&(m.debug("[MOVE-FILES] User changes committed before move operations",{commitHash:e.commitHash?.substring(0,8),filesCommitted:e.filesCommitted}),m.info("User changes committed before move-files operation",{taskId:u,moveOperationsCount:_.length,userCommitHash:e.commitHash?.substring(0,8),userFilesCommitted:e.filesCommitted}),M={hadUserMods:!0,userModsCommitHash:e.commitHash})}catch(e){m.debug("[MOVE-FILES] Pre-tool commit failed, continuing with move operations",{error:e instanceof Error?e.message:e+""}),m.warn("Pre-tool user changes commit failed, continuing with move operation",{taskId:u,moveOperationsCount:_.length,error:e instanceof Error?e.message:e+""})}m.debug("[MOVE-FILES] Proceeding with move operations",{operationCount:_.length}),
|
|
1694
|
-
const{toolRecordId:
|
|
1695
|
-
w=
|
|
1687
|
+
e.userChangesCommitted&&(m.debug("[MOVE-FILES] User changes committed before move operations",{commitHash:e.commitHash?.substring(0,8),filesCommitted:e.filesCommitted}),m.info("User changes committed before move-files operation",{taskId:u,moveOperationsCount:_.length,userCommitHash:e.commitHash?.substring(0,8),userFilesCommitted:e.filesCommitted}),M={hadUserMods:!0,userModsCommitHash:e.commitHash})}catch(e){m.debug("[MOVE-FILES] Pre-tool commit failed, continuing with move operations",{error:e instanceof Error?e.message:e+""}),m.warn("Pre-tool user changes commit failed, continuing with move operation",{taskId:u,moveOperationsCount:_.length,error:e instanceof Error?e.message:e+""})}m.debug("[MOVE-FILES] Proceeding with move operations",{operationCount:_.length}),b=d.FileOperationPhase.RECORD_CREATION,i.incrementCounter("move_files_phase",1,{phase:b})
|
|
1688
|
+
const{toolRecordId:j,localToolRecordId:R}=await d.createFileOperationRecords(u,q,t.projectId,I.recordType,_[0].source,{operationCount:h.length,operations:_.map((e=>({source:e.source,destination:e.destination}))),userComment:v,hadUserMods:M.hadUserMods,userModsCommitHash:M.userModsCommitHash},r,n,m,i,I.metricsPrefix,f)
|
|
1689
|
+
w=j,k=j,b=I.fileOperationPhase,i.incrementCounter("move_files_phase",1,{phase:b})
|
|
1696
1690
|
const x=[]
|
|
1697
1691
|
let O=0
|
|
1698
1692
|
for(const e of _){const t={operation:{source:e.source,destination:e.destination},success:!1}
|
|
@@ -1702,20 +1696,20 @@ const n=c.default.dirname(e.fullDestination)
|
|
|
1702
1696
|
try{await a.default.mkdir(n,{recursive:!0})}catch(e){throw Error("Failed to create destination directory: "+n)}try{throw await a.default.access(e.fullDestination),Error("Destination already exists: "+e.destination)}catch(e){if(!(e instanceof Error&&e.message.includes("ENOENT")))throw e}await a.default.rename(e.fullSource,e.fullDestination),t.success=!0,O++,m.info("Successfully moved "+(r?"directory":"file"),{source:e.source,destination:e.destination,isDirectory:r})}catch(r){t.error=(0,p.getErrorMessage)(r),m.warn(`Failed to move ${e.source} to ${e.destination}`,{error:t.error})}x.push(t)}const A=Date.now()-y
|
|
1703
1697
|
i.recordValue("move_files_time",A),i.incrementCounter("move_files_operations_total",h.length),i.incrementCounter("move_files_operations_success",O),i.incrementCounter("move_files_operations_failed",h.length-O),O===h.length?i.incrementCounter("move_files_success",1):O>0?i.incrementCounter("move_files_partial_success",1):i.incrementCounter("move_files_total_failure",1)
|
|
1704
1698
|
let D=null
|
|
1705
|
-
if(O>0){
|
|
1699
|
+
if(O>0){b=d.FileOperationPhase.GIT_COMMIT,i.incrementCounter("move_files_phase",1,{phase:b})
|
|
1706
1700
|
const e=x.filter((e=>e.success)),r=1===e.length?`Move ${e[0].isDirectory?"directory":"file"} from ${e[0].operation.source} to ${e[0].operation.destination} - ${v}`:`Move ${e.length} ${1===e.length?"item":"items"} - ${v}`
|
|
1707
|
-
D=await d.commitToGit(u,_[0].destination,R,
|
|
1701
|
+
D=await d.commitToGit(u,_[0].destination,j,R,r,t,m,i,I.metricsPrefix)}b=d.FileOperationPhase.RECORD_UPDATE_SUCCESS,i.incrementCounter("move_files_phase",1,{phase:b})
|
|
1708
1702
|
const $=x.filter((e=>e.success)),F=x.filter((e=>!e.success))
|
|
1709
|
-
await d.updateFileOperationRecords(u,w,k,_[0].source,
|
|
1703
|
+
await d.updateFileOperationRecords(u,w,k,_[0].source,I.recordType,O===h.length?`Successfully moved all ${h.length} items`:`Moved ${O}/${h.length} items successfully`,{status:O===h.length?"completed":"partial_success",commitHash:D?.commitHash,previousCommitHash:D?.previousCommitHash,operationCount:h.length,successCount:O,failureCount:h.length-O,successfulOperations:$.map((e=>({source:e.operation.source,destination:e.operation.destination,isDirectory:e.isDirectory}))),failedOperations:F.map((e=>({source:e.operation.source,destination:e.operation.destination,error:e.error}))),userComment:v,hadUserMods:M.hadUserMods,userModsCommitHash:M.userModsCommitHash},O===h.length?`Successfully moved all ${h.length} items`:`Moved ${O}/${h.length} items successfully`,r,n,m,i,I.metricsPrefix)
|
|
1710
1704
|
const N=t.getCurrentBranchContext?await t.getCurrentBranchContext():{branch:null,requestId:null,isMain:!0}
|
|
1711
1705
|
let L=""
|
|
1712
1706
|
if(O===h.length)L=`Successfully moved all ${h.length} ${1===h.length?"item":"items"}`
|
|
1713
1707
|
else if(O>0){const e=x.filter((e=>!e.success))
|
|
1714
1708
|
L=`Successfully moved ${O}/${h.length} items.\n\nFailed operations:\n`+e.map((e=>`\u2022 ${e.operation.source} \u2192 ${e.operation.destination}: ${e.error}`)).join("\n")}else L="All move operations failed:\n"+x.map((e=>`\u2022 ${e.operation.source} \u2192 ${e.operation.destination}: ${e.error}`)).join("\n")
|
|
1715
1709
|
return D?.commitHash&&(L+="\nCommit: "+D.commitHash.substring(0,8)),N.requestId&&(L+="\nBranch: "+N.requestId),P.lockAcquired&&P.lockedRequestId&&(L+="\n\u{1f512} **Locked request:** "+P.lockedRequestId),{content:[{type:"text",text:L}],isError:0===O}}catch(o){if(e.taskId&&n)try{const r=o instanceof u.NotFoundError||o instanceof u.ValidationError||o instanceof h.ZodError
|
|
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:
|
|
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){
|
|
1718
|
-
try{await d.updateFileOperationRecords(e.taskId,w,k,e.operations?.[0]?.source||"unknown",
|
|
1710
|
+
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:b,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
|
|
1711
|
+
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){b=d.FileOperationPhase.RECORD_UPDATE_FAILURE
|
|
1712
|
+
try{await d.updateFileOperationRecords(e.taskId,w,k,e.operations?.[0]?.source||"unknown",I.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,I.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,b,m,i,e,I)}}
|
|
1719
1713
|
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
1714
|
if((0,r.existsSync)(l))return void i.info("Worktree already exists on disk, skipping pre-spawn creation",{requestId:t,worktreePath:l})
|
|
1721
1715
|
const d=(0,o.simpleGit)(e);(0,r.mkdirSync)(c,{recursive:!0})
|
|
@@ -1727,7 +1721,7 @@ i.warn("Pre-spawn: failed to create worktree (MCP process will retry)",{requestI
|
|
|
1727
1721
|
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
|
|
1728
1722
|
const r=t(6183),n=t(3707)
|
|
1729
1723
|
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})
|
|
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),
|
|
1724
|
+
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),b=t(6111),I=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),j=t(3556),R=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)(b.def),(0,r.registerTool)(I.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)(j.def),(0,r.registerTool)(R.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
|
|
1731
1725
|
try{return(await y.default.readFile(e,"utf-8")).split("\n").length}catch{return}}}function n(e,t,r){const n="depth"in e,o=n?e:r,s=n?e.isDirectory:e.isDirectory(),a=e.name,c=s?"[\u{1f4c1} DIR]":"[\u{1f4c4} FILE]"
|
|
1732
1726
|
let l=""
|
|
1733
1727
|
if(s||void 0===o?.lineCount||(l=` (${i(o.lineCount)} lines)`),s&&o?.subtreeTotals){const{files:e,lines:t}=o.subtreeTotals
|
|
@@ -1743,14 +1737,14 @@ if(30>s)return`${s} day${1===s?"":"s"} ago`
|
|
|
1743
1737
|
const i=Math.floor(s/30)
|
|
1744
1738
|
if(12>i)return`${i} month${1===i?"":"s"} ago`
|
|
1745
1739
|
const a=Math.floor(i/12)
|
|
1746
|
-
return`${a} year${1===a?"":"s"} ago`}(o.modified)} | ${(0,
|
|
1740
|
+
return`${a} year${1===a?"":"s"} ago`}(o.modified)} | ${(0,I.formatTimestamp)(o.modified)})`)
|
|
1747
1741
|
break
|
|
1748
1742
|
case"size":s||"number"!=typeof o.size||(l+=` (${function(e){if(0===e)return"0 bytes"
|
|
1749
1743
|
let t=e,r=0
|
|
1750
1744
|
for(;t>=1024&&4>r;)t/=1024,r++
|
|
1751
1745
|
return`${0===r?t.toString():t.toFixed(10>t?1:0)}${["bytes","KB","MB","GB","TB"][r]}`}(o.size)})`)}return`${c} ${a}${l}`}async function o(e,t,n=0,s,i,l){if(n>=s)return[]
|
|
1752
|
-
try{const{fullPath:d}=
|
|
1753
|
-
for(const d of h)try{const u=w.default.join(e,d.name).replace(/\\/g,"/"),{fullPath:h}=
|
|
1746
|
+
try{const{fullPath:d}=b.validateAndNormalizePath(e,t),h=await y.default.readdir(d,{withFileTypes:!0}),g=[]
|
|
1747
|
+
for(const d of h)try{const u=w.default.join(e,d.name).replace(/\\/g,"/"),{fullPath:h}=b.validateAndNormalizePath(u,t),p=await y.default.stat(h),f=d.isFile()?w.default.extname(d.name).toLowerCase():""
|
|
1754
1748
|
let m
|
|
1755
1749
|
d.isFile()&&(m=await r(h,p.size,f))
|
|
1756
1750
|
const k={name:d.name,isDirectory:d.isDirectory(),depth:n,size:p.size,modified:p.mtime,extension:f,lineCount:m}
|
|
@@ -1759,8 +1753,8 @@ const o=[]
|
|
|
1759
1753
|
return e.forEach(((i,a)=>{const c=a===e.length-1,l=c?"\u2514\u2500\u2500 ":"\u251c\u2500\u2500 ",d=n(i,t),u=i.isDirectory?"/":""
|
|
1760
1754
|
if(o.push(`${r}${l}${d}${u}`),i.children&&i.children.length>0){const e=r+(c?" ":"\u2502 "),n=s(i.children,t,e)
|
|
1761
1755
|
n&&o.push(n)}})),o.join("\n")}function i(e){return e.toLocaleString()}async function a(e,t,n){const o={files:0,directories:0,lines:0}
|
|
1762
|
-
try{const{fullPath:n}=
|
|
1763
|
-
for(const n of s)try{const s=w.default.join(e,n.name).replace(/\\/g,"/"),{fullPath:i}=
|
|
1756
|
+
try{const{fullPath:n}=b.validateAndNormalizePath(e,t),s=await y.default.readdir(n,{withFileTypes:!0})
|
|
1757
|
+
for(const n of s)try{const s=w.default.join(e,n.name).replace(/\\/g,"/"),{fullPath:i}=b.validateAndNormalizePath(s,t)
|
|
1764
1758
|
if(n.isDirectory())o.directories+=1
|
|
1765
1759
|
else{o.files+=1
|
|
1766
1760
|
const e=await y.default.stat(i),t=w.default.extname(n.name).toLowerCase(),s=await r(i,e.size,t)
|
|
@@ -1786,27 +1780,27 @@ var t={}
|
|
|
1786
1780
|
if(null!=e)for(var r=h(e),n=0;n<r.length;n++)"default"!==r[n]&&g(t,e,r[n])
|
|
1787
1781
|
return p(t,e),t}),m=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
1788
1782
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleListDirectory=async function(e,t,i,a){const h=Date.now()
|
|
1789
|
-
let g=
|
|
1790
|
-
|
|
1791
|
-
try{const p=
|
|
1783
|
+
let g=b.FileOperationPhase.VALIDATION
|
|
1784
|
+
b.FileOperationPhase.FILE_WRITE
|
|
1785
|
+
try{const p=b.validateArgs(e,k.ListDirectorySchema),{path:f,levels:m=1,sortBy:I="name"}=p
|
|
1792
1786
|
i.info("Listing directory: "+f)
|
|
1793
|
-
const{normalizedPath:C,fullPath:_}=
|
|
1794
|
-
g=
|
|
1787
|
+
const{normalizedPath:C,fullPath:_}=b.validateAndNormalizePath(f,t)
|
|
1788
|
+
g=b.FileOperationPhase.FILE_WRITE
|
|
1795
1789
|
try{if(!(await y.default.stat(_)).isDirectory())return{content:[{type:"text",text:"Path is not a directory: "+f}],isError:!0}
|
|
1796
1790
|
await y.default.access(_,y.default.constants.R_OK)}catch(e){return e instanceof Error&&"ENOENT"===e.code?{content:[{type:"text",text:"Directory does not exist: "+f}],isError:!0}:e instanceof Error&&"EACCES"===e.code?{content:[{type:"text",text:"Directory not accessible: "+f}],isError:!0}:{content:[{type:"text",text:"Cannot access directory: "+f}],isError:!0}}let E,q
|
|
1797
|
-
if(m>1){i.info(`Building tree structure for: ${C} (levels: ${m}, sortBy: ${
|
|
1798
|
-
const e=await o(C,t,0,m,
|
|
1799
|
-
if(e.length>0){const t=s(e,
|
|
1791
|
+
if(m>1){i.info(`Building tree structure for: ${C} (levels: ${m}, sortBy: ${I})`)
|
|
1792
|
+
const e=await o(C,t,0,m,I,i)
|
|
1793
|
+
if(e.length>0){const t=s(e,I)
|
|
1800
1794
|
E=`Directory tree for ${C} (${m} levels):\n${l(c(e))}\n\n${t}`,q=d(e)}else E=`Directory ${C} is empty or inaccessible.`,q=0}else{const e=await y.default.readdir(_,{withFileTypes:!0}),o=[]
|
|
1801
|
-
for(const n of e)try{const e=w.default.join(C,n.name).replace(/\\/g,"/"),{fullPath:s}=
|
|
1795
|
+
for(const n of e)try{const e=w.default.join(C,n.name).replace(/\\/g,"/"),{fullPath:s}=b.validateAndNormalizePath(e,t),i=await y.default.stat(s),a=n.isFile()?w.default.extname(n.name).toLowerCase():""
|
|
1802
1796
|
let c
|
|
1803
|
-
n.isFile()&&(c=await r(s,i.size,a)),o.push({name:n.name,isDirectory:n.isDirectory(),depth:0,size:i.size,modified:i.mtime,extension:a,lineCount:c})}catch(e){i.debug("Excluding directory entry from listing: "+n.name,{reason:(0,v.getErrorMessage)(e)})}const s=u(o,
|
|
1797
|
+
n.isFile()&&(c=await r(s,i.size,a)),o.push({name:n.name,isDirectory:n.isDirectory(),depth:0,size:i.size,modified:i.mtime,extension:a,lineCount:c})}catch(e){i.debug("Excluding directory entry from listing: "+n.name,{reason:(0,v.getErrorMessage)(e)})}const s=u(o,I),a=s.map((e=>n({name:e.name,isDirectory(){return e.isDirectory},isFile(){return!e.isDirectory}},I,e)))
|
|
1804
1798
|
E=a.length>0?`Directory listing for ${C}:\n${l(c(s))}\n\n${a.join("\n")}`:`Directory ${C} is empty.`,q=s.length}const S=t.workspaceManager?.getCurrentContext()
|
|
1805
1799
|
E+="\n\nBranch: "+(S?.branchName||"unknown")
|
|
1806
1800
|
const T=Date.now()-h
|
|
1807
1801
|
return a.recordValue("list_directory_time",T),a.recordValue("list_directory_entries",q),a.incrementCounter("list_directory_success",1),i.info("Successfully listed directory: "+C,{entryCount:q,levels:m,time:T}),{content:[{type:"text",text:E}]}}catch(e){const t=Date.now()-h
|
|
1808
1802
|
return a.recordValue("list_directory_time",t),a.incrementCounter("list_directory_errors",1),i.error("Error listing directory:",{error:(0,v.getErrorMessage)(e),time:t}),{content:[{type:"text",text:(0,v.getErrorMessage)(e)}],isError:!0}}}
|
|
1809
|
-
const y=m(t(1943)),w=m(t(6928)),k=t(6183),
|
|
1803
|
+
const y=m(t(1943)),w=m(t(6928)),k=t(6183),b=f(t(5967)),I=t(3253),v=t(8824),C=new Set([".ts",".tsx",".js",".jsx",".mjs",".cjs",".py",".rb",".go",".rs",".java",".kt",".scala",".c",".cpp",".h",".hpp",".cs",".html",".css",".scss",".sass",".less",".json",".yaml",".yml",".toml",".xml",".md",".txt",".csv",".sql",".sh",".bash",".zsh",".fish",".vim",".lua",".php",".swift",".m",".vue",".svelte",".astro",".env",".gitignore",".dockerignore",".config",".conf",".ini",".cfg"]),_=1048576},2568(e,exports,t){var r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
1810
1804
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.ProjectSynchronizer=void 0
|
|
1811
1805
|
const n=r(t(6928)),o=t(8029),s=t(8824),i=t(2096)
|
|
1812
1806
|
exports.ProjectSynchronizer=class{constructor(e,t,r,n,o={}){this.logger=e.child({component:"project-synchronizer"}),this.registry=t,this.remoteApi=r,this.fileSystem=n,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)
|
|
@@ -1985,11 +1979,11 @@ const f=await Promise.all(p)
|
|
|
1985
1979
|
let m=""
|
|
1986
1980
|
if(t.getCurrentBranchContext)try{const e=await t.getCurrentBranchContext()
|
|
1987
1981
|
e.branch&&(m=`**Current Branch:** ${e.branch}\n`)}catch(e){i.debug("Could not get branch context",{error:e})}const y=f.filter((e=>e.success)).length,w=f.filter((e=>!e.success)).length,k=f.length
|
|
1988
|
-
let
|
|
1989
|
-
m&&(
|
|
1982
|
+
let b="## Read Files/Documents\n\n"
|
|
1983
|
+
m&&(b+=m),b+=`**Total Requests:** ${k} - **Successful:** ${y} - **Failed:** ${w}\n\n`
|
|
1990
1984
|
for(let e=0;e<f.length;e++){const t=f[e]
|
|
1991
|
-
"file"===t.type?
|
|
1992
|
-
return i.info("Multiple file/document read completed",{duration:Date.now()-a,totalRequests:k,successfulReads:y,failedReads:w,success:
|
|
1985
|
+
"file"===t.type?b+=`File ${e+1}: ${t.path}\n`:(b+=`Document ${e+1}: ${t.documentId}`,t.filename&&(b+=` (${t.filename})`),b+="\n"),t.success?(b+="**Status:** Success\n",t.lineCount&&t.totalLines&&(b+=`Lines Read / Total Lines ${t.lineCount} / ${t.totalLines}\n`),t.originalRequest?.lines&&t.totalLines&&(b+=`**Lines:** ${t.originalRequest.lines}\n`),b+=`\n**Content:**\n\`\`\`\n${t.content}\n\`\`\`\n`):(b+="**Status:** Failed\n",b+=`**Error:** ${t.error}\n`),b+="\n"}const I=0===w
|
|
1986
|
+
return i.info("Multiple file/document read completed",{duration:Date.now()-a,totalRequests:k,successfulReads:y,failedReads:w,success:I}),s.incrementCounter("read_files_total",1,{success:I}),{content:[{type:"text",text:b}],isError:!I}}catch(e){const t=Date.now()-a
|
|
1993
1987
|
return i.error("Read multiple files operation failed",{error:e instanceof Error?e.stack:e+"",duration:t}),s.incrementCounter("read_files_errors",1),{content:[{type:"text",text:"\u274c **Read Operation Failed:** "+(0,p.getErrorMessage)(e)}],isError:!0}}}
|
|
1994
1988
|
const l=c(t(1943)),d=t(6183),u=t(1569),h=a(t(5967)),g=t(9470),p=t(8824)},2968(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.TaskClient=void 0
|
|
1995
1989
|
const r=t(8824),n=t(7645),o=t(2161),s=t(5172)
|
|
@@ -2102,12 +2096,12 @@ d.info("Generating journal for request",{requestId:c})
|
|
|
2102
2096
|
const h=t.projectId
|
|
2103
2097
|
if(!h)throw(0,n.createValidationError)("Project ID is required. Make sure you are in a project context.")
|
|
2104
2098
|
o.setProjectId(h),d.info("Fetching request data, tasks, and file history in parallel")
|
|
2105
|
-
const g=o.getRequestClient(),p=o.getTaskClient(),f=o.getToolRecordClient(),[m,y,w]=await Promise.all([g.getRequest(c),p.listTasks({requestId:c}),f.getToolRecordsByRequestId(c).catch((e=>(d.warn("Failed to fetch tool records",{error:e+""}),[])))]),k=(0,s.extractDataFromResponse)(m,{logger:d,operationName:"getRequest",throwOnNoData:!0}),
|
|
2099
|
+
const g=o.getRequestClient(),p=o.getTaskClient(),f=o.getToolRecordClient(),[m,y,w]=await Promise.all([g.getRequest(c),p.listTasks({requestId:c}),f.getToolRecordsByRequestId(c).catch((e=>(d.warn("Failed to fetch tool records",{error:e+""}),[])))]),k=(0,s.extractDataFromResponse)(m,{logger:d,operationName:"getRequest",throwOnNoData:!0}),b="data"in k?k.data:k,I={id:b.id||c,title:b.title||"Unknown Request",description:b.description||"No description available",status:b.status||"unknown",type:b.type||"unknown",acceptanceCriteria:b.acceptanceCriteria||[],createdAt:b.createdAt||(new Date).toISOString(),updatedAt:b.updatedAt||(new Date).toISOString(),completedAt:b.completedAt},v=(0,s.extractDataFromResponse)(y,{logger:d,operationName:"listTasks",throwOnNoData:!1}),C=(Array.isArray(v)?v:"data"in v?v.data:[]).map((e=>({id:e.id,title:e.title||"Untitled Task",description:e.description||"No description",status:e.status||"unknown",createdAt:e.createdAt||(new Date).toISOString(),completedAt:e.metadata?.completedAt})))
|
|
2106
2100
|
d.info(`Fetched request, ${C.length} tasks, ${w.length} tool records`)
|
|
2107
2101
|
const _=await async function(e){const t=new Map,n=[],o=e.filter((e=>["write-file","replace-in-files","move-files","delete-files","manage-files"].includes(e.type))).sort(((e,t)=>new Date(e.createdAt).getTime()-new Date(t.createdAt).getTime()))
|
|
2108
2102
|
for(const e of o){const o=r(e),s=e.metadata?.comment||e.metadata?.userComment||"No comment"
|
|
2109
2103
|
n.push({type:e.type,timestamp:e.createdAt,comment:s,files:o,recordId:e.localId||e.id})
|
|
2110
|
-
for(const e of o)t.set(e,(t.get(e)||0)+1)}return{files:Array.from(t.entries()).map((([e,t])=>({path:e,operations:t}))).sort(((e,t)=>t.operations-e.operations)),operations:n}}(w),E={request:
|
|
2104
|
+
for(const e of o)t.set(e,(t.get(e)||0)+1)}return{files:Array.from(t.entries()).map((([e,t])=>({path:e,operations:t}))).sort(((e,t)=>t.operations-e.operations)),operations:n}}(w),E={request:I,tasks:C,fileChanges:{summary:{totalFiles:_.files.length,totalOperations:_.operations.length,files:_.files},operations:_.operations},suggestedFilename:`JOURNAL-${c}.md`,metadata:{projectId:h,requestId:c,generatedAt:(new Date).toISOString()}},q=`\u2705 **Request Data Fetched Successfully!**\n\n**Request:** ${I.title} (${c})\n**Status:** ${I.status}\n**Type:** ${I.type}\n**Tasks:** ${C.length}\n**Files Changed:** ${_.files.length}\n**File Operations:** ${_.operations.length}\n\n**Data Summary:**\n\`\`\`json\n${JSON.stringify(E,null,2)}\n\`\`\`\n\n**Next Steps:**\nWrite a **compact technical narrative** and save as \`JOURNAL-${c}.md\` using document_operations (create).\n\n**Style Guide:**\n- Be concise and direct - no fluff, repetition, or unnecessary elaboration\n- Write in narrative flow connecting the changes chronologically\n- Reference files with paths: "Modified \\\`src/tools/example.ts\\\` to add X..."\n- Include operation comments inline: ("comment: 'Fix bug in parser'")\n- **Link to tool records**: Use \\\`[RECORD:trec######]\\\` format to reference operations (e.g., "Modified parser.ts [RECORD:trec004123]")\n- Show key code changes with brief snippets where they add clarity\n- Explain what changed and why, skip obvious details\n- Focus on technical substance over structure\n\n**Example:** "Modified \\\`parser.ts\\\` [RECORD:trec004123] to handle edge cases (comment: 'Fix null handling'). Added \\\`if (!input) return null;\\\` check at line 45. Then updated \\\`validator.ts\\\` [RECORD:trec004124] to use the new parser behavior..."`
|
|
2111
2105
|
return u({tool:"generate_request_journal",success:!0}),l.incrementCounter("generate_request_journal_total",1,{success:!0}),{content:[{type:"text",text:q}]}}catch(e){return d.error("Error generating request journal",{error:e instanceof Error?e.stack:e+""}),u({tool:"generate_request_journal",success:!1}),l.incrementCounter("generate_request_journal_errors",1),{content:[{type:"text",text:"\u274c **Failed to generate journal:** "+(0,i.getErrorMessage)(e)}],isError:!0}}}
|
|
2112
2106
|
const n=t(9860),o=t(1569),s=t(2960),i=t(8824),a=o.z.object({requestId:o.z.string().regex(/^req[_\d].+$/,"Invalid request ID format")})},3064(e,exports,t){async function r(e,t,r,n){if(!r.lockOverrideManager||!r.configManager)return e
|
|
2113
2107
|
try{const n=await r.configManager.getEffectiveConfig(r.mainBasePath)
|
|
@@ -2224,7 +2218,7 @@ var t={}
|
|
|
2224
2218
|
if(null!=e)for(var r=o(e),n=0;n<r.length;n++)"default"!==r[n]&&s(t,e,r[n])
|
|
2225
2219
|
return i(t,e),t}),c=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
2226
2220
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleReplaceStrings=async function(e,t,r,o,s,i,a,c){const y=i.child({tool:"replace_strings"}),w=Date.now()
|
|
2227
|
-
let k,I
|
|
2221
|
+
let k,b,I=u.FileOperationPhase.VALIDATION
|
|
2228
2222
|
const v={toolName:"replace-strings",operationName:"replace-string",fileOperationPhase:u.FileOperationPhase.STRING_REPLACEMENT,recordType:"replace-strings",metricsPrefix:"replace_strings",successMessage:"Successfully replaced strings across files and documents",failureMessage:"Failed to replace strings across files and documents"}
|
|
2229
2223
|
try{const i=u.validateArgs(e,d.ReplaceStringsSchema),{taskId:C,operations:_,comment:E}=i
|
|
2230
2224
|
if(y.info("Replacing strings across files and documents",{taskId:C,operationCount:_.length,comment:E}),!_||0===_.length)throw new h.ValidationError("At least one operation is required")
|
|
@@ -2237,21 +2231,21 @@ if(S.length>0&&!t.documentFileManager)throw Error("Document file manager not ava
|
|
|
2237
2231
|
for(const e of S)P.push({type:"document",documentId:e.documentId,replacements:e.replacements,mode:e.mode||"unique"})
|
|
2238
2232
|
if(P.length>0&&t.apiClient){const e=P.map((e=>e.documentId))
|
|
2239
2233
|
try{await(0,f.ensureDocumentsNotLocked)(e,t.apiClient,y,a,"replace-strings-documents")}catch(e){if(e instanceof h.ValidationError)return{content:[{type:"text",text:e.message}],isError:!0}
|
|
2240
|
-
throw e}}
|
|
2241
|
-
const M=T.length>0?T[0].path:"document-operation",
|
|
2234
|
+
throw e}}I=u.FileOperationPhase.TASK_VALIDATION,a.incrementCounter("replace_strings_phase",1,{phase:I})
|
|
2235
|
+
const M=T.length>0?T[0].path:"document-operation",j=await u.validateTaskId(C,M,r,y,a,v.metricsPrefix),R=j?.requestId
|
|
2242
2236
|
let x=null
|
|
2243
|
-
T.length>0&&
|
|
2237
|
+
T.length>0&&R&&(x=await u.validateWorkItemStates(C,T[0].path,r,s,t,y,a,v.metricsPrefix))
|
|
2244
2238
|
let O={taskPromoted:!1,requestPromoted:!1}
|
|
2245
|
-
T.length>0&&
|
|
2246
|
-
const A=await u.ensureCorrectWorkspaceContext({taskPromoted:O.taskPromoted,requestId:
|
|
2239
|
+
T.length>0&&R&&x&&(O=await u.autoPromoteTaskStatus(C,j.status,R,x.request?.status,T[0].path,r,s,y,a,v.metricsPrefix),O.taskPromoted&&y.info("Auto-promoted task to in_progress for replace-strings operation",{taskId:C,requestId:R,previousStatus:j.status,newStatus:O.newTaskStatus,triggeringOperation:"replace-strings"}))
|
|
2240
|
+
const A=await u.ensureCorrectWorkspaceContext({taskPromoted:O.taskPromoted,requestId:R,context:t,operation:"replace-strings",logger:y,metrics:a,metricsPrefix:v.metricsPrefix})
|
|
2247
2241
|
if(!A.success){if(A.isLockConflict)return{content:[{type:"text",text:"\u274c "+A.error}],isError:!0}
|
|
2248
2242
|
throw Error(A.error)}if(T.length>0){y.debug("Re-validating file paths with correct workspace context",{operationCount:T.length,workspaceBasePath:t.workspaceManager?.getCurrentContext().basePath})
|
|
2249
2243
|
for(let e=0;e<T.length;e++){const r=T[e],n=q[e],{normalizedPath:o,fullPath:s}=u.validateAndNormalizePath(n.path,t)
|
|
2250
|
-
T[e]={...r,path:o,fullPath:s}}}if(P.length>0&&
|
|
2251
|
-
throw e}
|
|
2252
|
-
const D=[...T.map((e=>({type:"file",path:e.path,replacements:e.replacements,mode:e.mode}))),...P.map((e=>({type:"document",documentId:e.documentId,replacements:e.replacements,mode:e.mode})))],{toolRecordId:$}=await u.createFileOperationRecords(C,
|
|
2253
|
-
if(k=$,I
|
|
2254
|
-
const e=await(0,p.commitUserChangesBeforeToolOperation)(t.git,"replace-strings",{requestId:
|
|
2244
|
+
T[e]={...r,path:o,fullPath:s}}}if(P.length>0&&R)try{await(0,g.validateRequestStatusForDocumentOperation)(R,s,y,a,"replace-strings-document")}catch(e){if(e instanceof h.ValidationError)return{content:[{type:"text",text:e.message}],isError:!0}
|
|
2245
|
+
throw e}I=u.FileOperationPhase.RECORD_CREATION,a.incrementCounter("replace_strings_phase",1,{phase:I})
|
|
2246
|
+
const D=[...T.map((e=>({type:"file",path:e.path,replacements:e.replacements,mode:e.mode}))),...P.map((e=>({type:"document",documentId:e.documentId,replacements:e.replacements,mode:e.mode})))],{toolRecordId:$}=await u.createFileOperationRecords(C,R,t.projectId,v.recordType,M,{operationCount:_.length,fileOperations:T.length,documentOperations:P.length,operations:D,userComment:E},r,o,y,a,v.metricsPrefix,c)
|
|
2247
|
+
if(k=$,b=$,I=v.fileOperationPhase,a.incrementCounter("replace_strings_phase",1,{phase:I}),T.length>0&&t.git)try{y.debug("[REPLACE-STRINGS] Checking for user changes before replace operations")
|
|
2248
|
+
const e=await(0,p.commitUserChangesBeforeToolOperation)(t.git,"replace-strings",{requestId:R,taskId:C,workspaceManager:t.workspaceManager},y,a)
|
|
2255
2249
|
e.userChangesCommitted&&(y.debug("[REPLACE-STRINGS] User changes committed before replace operations",{commitHash:e.commitHash?.substring(0,8),filesCommitted:e.filesCommitted}),y.info("User changes committed before replace-strings operation",{taskId:C,fileOperationsCount:T.length,userCommitHash:e.commitHash?.substring(0,8),userFilesCommitted:e.filesCommitted}))}catch(e){y.debug("[REPLACE-STRINGS] Pre-tool commit failed, continuing with replacements",{error:e instanceof Error?e.message:e+""}),y.warn("Pre-tool user changes commit failed, continuing with replace operation",{taskId:C,fileOperationsCount:T.length,error:e instanceof Error?e.message:e+""})}y.debug("[REPLACE-STRINGS] Proceeding with file operations",{fileCount:T.length})
|
|
2256
2250
|
const F=[]
|
|
2257
2251
|
let N=0,L=0
|
|
@@ -2263,17 +2257,17 @@ try{const o=await t.documentFileManager.getDocumentAsFile(e.documentId),s=t.docu
|
|
|
2263
2257
|
r.filename=s?.filename
|
|
2264
2258
|
const i=await l.default.readFile(o,"utf8"),{newContent:a,results:c}=await n(i,e.replacements,e.mode)
|
|
2265
2259
|
r.replacements=c,r.successfulReplacements=c.filter((e=>e.success)).length,r.failedReplacements=c.filter((e=>!e.success)).length,a!==i?(await l.default.writeFile(o,a,"utf8"),t.documentFileManager.markForSync(e.documentId),r.success=!0,L++,y.info("Document updated successfully",{documentId:e.documentId,filename:r.filename,successfulReplacements:r.successfulReplacements,failedReplacements:r.failedReplacements})):0===r.failedReplacements&&(r.success=!0),N+=r.failedReplacements}catch(t){r.error=(0,m.getErrorMessage)(t),r.failedReplacements=e.replacements.length,N+=r.failedReplacements,y.error("Document operation failed",{documentId:e.documentId,error:r.error})}F.push(r)}if(P.length>0)try{for(const e of P){const r=F.find((t=>t.documentId===e.documentId))
|
|
2266
|
-
r?.success&&await t.documentFileManager.syncDocument(e.documentId)}}catch(e){y.warn("Some documents may not have synced properly",{error:e})}const z=await u.handleMultiFileGitCommit(C,T,F,L,{operationType:"Replace strings",toolRecordId:
|
|
2267
|
-
try{await o.updateToolRecord(
|
|
2268
|
-
let
|
|
2269
|
-
if(t.workspaceManager&&(
|
|
2270
|
-
if(
|
|
2271
|
-
for(const t of e.replacements.filter((e=>!e.success)))
|
|
2272
|
-
for(const e of F){if("file"===e.type?
|
|
2273
|
-
for(const t of e.replacements.filter((e=>!e.success)))
|
|
2274
|
-
const
|
|
2275
|
-
return y.info("Replace strings operation completed",{duration:
|
|
2276
|
-
if(y.error("Replace strings operation failed",{error:t instanceof Error?t.stack:t+"",duration:r,phase:
|
|
2260
|
+
r?.success&&await t.documentFileManager.syncDocument(e.documentId)}}catch(e){y.warn("Some documents may not have synced properly",{error:e})}const z=await u.handleMultiFileGitCommit(C,T,F,L,{operationType:"Replace strings",toolRecordId:b,successField:"successfulReplacements",logger:y,metrics:a,metricsPrefix:"replace_strings"},t),B=u.processMultiFileOperationResults(F,"successfulReplacements"),{successfulOperations:H,failedOperations:W,totalSuccessfulChanges:U,overallSuccess:G,successfulFiles:V,failedFiles:J}=B
|
|
2261
|
+
try{await o.updateToolRecord(b,{metadata:{path:T.length>0?T[0].path:"document:"+P[0]?.documentId,status:G?"completed":"failed",error:G?void 0:W+" operations failed",totalOperations:F.length,successfulFiles:V,failedFiles:J,operations:D,totalSuccessfulReplacements:U,totalFailedReplacements:N,operationsWithChanges:L,processingTime:Date.now()-w,userComment:E,...T.length>0&&z.success&&z.commitHash&&{commitHash:z.commitHash,previousCommitHash:z.previousCommitHash||void 0}},note:G?`String replacement completed: ${H}/${F.length} operations successful${T.length>0?" (committed to git)":""}`:`String replacement partially failed: ${W}/${F.length} operations failed`})}catch(e){y.warn("Failed to update tool record",{recordError:e})}u.formatMultiFileToolResponse("String Replacement",{successfulOperations:H,failedOperations:W,totalSuccessfulChanges:U,overallSuccess:G,successfulFiles:V,failedFiles:J},z,A)
|
|
2262
|
+
let K="## String Replacement Results\n\n"
|
|
2263
|
+
if(t.workspaceManager&&(K+=`**Branch:** \`${t.workspaceManager.getCurrentContext().branchName}\`\n\n`),K+="**Summary:**\n",K+=`- **Files processed:** ${H+W}\n`,K+=`- **Successful operations:** ${H}\n`,K+=`- **Failed operations:** ${W}\n`,K+=`- **Total replacements:** ${U} successful, ${N} failed\n\n`,z.success&&z.commitHash&&(K+="**Git Commit:**\n",K+=`- **Commit Hash:** ${z.commitHash.substring(0,8)}\n`,K+=`- **Files Committed:** ${z.filesCommitted.length}\n`,z.previousCommitHash&&(K+=`- **Previous Commit:** ${z.previousCommitHash.substring(0,8)}\n`),K+="\n"),A.lockAcquired&&A.lockedRequestId&&(K+=`\u{1f512} **Locked request:** ${A.lockedRequestId}\n\n`),1===F.length){const e=F[0]
|
|
2264
|
+
if(K+=`**Operation:** ${e.success?"\u2705 Success":"\u274c Failed"}\n`,"file"===e.type?K+=`**File:** ${e.path}\n`:(K+="**Document:** "+e.documentId,e.filename&&(K+=` (${e.filename})`),K+="\n"),e.error?K+=`**Error:** ${e.error}\n`:(K+=`**Replacements:** ${e.successfulReplacements} successful`,e.failedReplacements>0&&(K+=`, ${e.failedReplacements} failed`),K+="\n"),e.replacements.some((e=>!e.success))){K+="**Failed Replacement Details:**\n"
|
|
2265
|
+
for(const t of e.replacements.filter((e=>!e.success)))K+=`- "${t.old_str}" \u2192 "${t.new_str}": ${t.error}\n`}}else{K+="**Summary:**\n",K+=`- **Total Operations:** ${F.length}\n`,K+=`- **Successful:** ${H}\n`,K+=`- **Failed:** ${W}\n`,K+=`- **Total Replacements:** ${U} successful, ${N} failed\n\n`,K+="**Detailed Results:**\n\n"
|
|
2266
|
+
for(const e of F){if("file"===e.type?K+=`### File: ${e.path}\n`:(K+="### Document: "+e.documentId,e.filename&&(K+=` (${e.filename})`),K+="\n"),K+=`- **Status:** ${e.success?"\u2705 Success":"\u274c Failed"}\n`,e.error?K+=`- **Error:** ${e.error}\n`:(K+=`- **Replacements:** ${e.successfulReplacements} successful`,e.failedReplacements>0&&(K+=`, ${e.failedReplacements} failed`),K+="\n"),e.replacements.some((e=>!e.success))){K+="- **Failed Replacement Details:**\n"
|
|
2267
|
+
for(const t of e.replacements.filter((e=>!e.success)))K+=` - "${t.old_str}" \u2192 "${t.new_str}": ${t.error}\n`}K+="\n"}}P.length>0&&(K+="\u{1f4c4} **Document Changes:** Modified documents have been automatically synced back to the tracking system.\n\n")
|
|
2268
|
+
const Y=Date.now()-w
|
|
2269
|
+
return y.info("Replace strings operation completed",{duration:Y,success:G,totalOperations:F.length,successfulOperations:H,failedOperations:W}),a.incrementCounter("replace_strings_total",1,{success:G}),{content:[{type:"text",text:K}],isError:!G}}catch(t){const r=Date.now()-w
|
|
2270
|
+
if(y.error("Replace strings operation failed",{error:t instanceof Error?t.stack:t+"",duration:r,phase:I}),b)try{await o.updateToolRecord(b,{metadata:{path:e?.operations?.[0]?.path||e?.operations?.[0]?.documentId,status:"failed",error:(0,m.getErrorMessage)(t),phase:I,duration:r,userComment:e?.comment},note:"String replacement failed: "+(0,m.getErrorMessage)(t)})}catch(e){}return a.incrementCounter("replace_strings_errors",1,{phase:I}),{content:[{type:"text",text:"\u274c **Replace Strings Failed:** "+(0,m.getErrorMessage)(t)}],isError:!0}}}
|
|
2277
2271
|
const l=c(t(1943)),d=t(6183),u=a(t(5967)),h=t(9860),g=t(5003),p=t(7478),f=t(9949),m=t(8824)},3322(e,exports,t){var r,n=this&&this.__createBinding||(Object.create?function(e,t,r,n){void 0===n&&(n=r)
|
|
2278
2272
|
var o=Object.getOwnPropertyDescriptor(t,r)
|
|
2279
2273
|
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]}),o=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),s=this&&this.__importStar||(r=function(e){return r=Object.getOwnPropertyNames||function(e){var t=[]
|
|
@@ -2359,26 +2353,26 @@ Object.defineProperty(exports,"LogLevel",{enumerable:!0,get(){return s.LogLevel}
|
|
|
2359
2353
|
const r=t(6183),n=t(8317)
|
|
2360
2354
|
exports.def={name:"request_file_history",description:"Get file change history for an entire request. Supports summary mode (net diffs) or detailed mode (chronological operations). Can be filtered to specific task. Use query_history tool instead.",schema:r.QueryHistorySchema,annotations:{title:"Request File History",readOnlyHint:!0},hidden:!0,readOnly:!0,handler(e,t){return(0,n.handleRequestFileHistory)(e,t.context,t.apiClient,t.logger,t.metrics)}}},3611(e,exports,t){var r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
2361
2355
|
Object.defineProperty(exports,"__esModule",{value:!0})
|
|
2362
|
-
const n=r(t(6928)),o=r(t(7252)),s=r(t(8577)),i=t(184),a=t(1213),c=t(3444),l=t(9955),d=t(5218),u=t(2568),h=t(3102),g=t(1152),p=t(3884),f=t(7888),m=t(4139),y=t(6800),w=t(6539),k=t(8824),
|
|
2356
|
+
const n=r(t(6928)),o=r(t(7252)),s=r(t(8577)),i=t(184),a=t(1213),c=t(3444),l=t(9955),d=t(5218),u=t(2568),h=t(3102),g=t(1152),p=t(3884),f=t(7888),m=t(4139),y=t(6800),w=t(6539),k=t(8824),b=t(6975),I=t(1253),v=process.argv.slice(2),C=v[0]||process.cwd(),_=n.default.resolve(C),E=parseInt(process.env.LOCAL_SERVER_PORT||v[1]||"3002",10),q=(0,c.createEnvLogger)({serviceName:"mcp-http-server"});(0,c.isDebugToolsEnabled)()?q.info("HTTP server initializing",{baseDir:_,preferredPort:E,debugLogging:process.env.DEBUG_LOGGING,debugLevel:process.env.DEBUG_LEVEL}):q.info("HTTP server starting",{port:E})
|
|
2363
2357
|
const S=(0,g.createMetricsCollector)(!0),T=(process.env.REMOTE_SERVER_PORT,process.env.REMOTE_SERVER_HOST,process.env.REMOTE_SERVER_URL||"https://api.alchemylabcode.com")
|
|
2364
2358
|
q.info("Using remote server URL",{remoteServerUrl:T}),async function(){try{q.info("Finding available port...",{preferredPort:E,baseDir:_,remoteServerUrl:T})
|
|
2365
2359
|
const e=await(0,y.findAvailablePort)(E)
|
|
2366
2360
|
e!==E&&q.info(`Preferred port ${E} is in use, using port ${e} instead`),q.info("Starting HTTP API server...",{port:e,baseDir:_,remoteServerUrl:T})
|
|
2367
2361
|
const t=new l.ProjectRegistry(q),r=new h.DefaultProjectFileSystem(q),c=n.default.join(_,m.ALCHEMY_DIR_NAME)
|
|
2368
2362
|
q.info(`Checking ${m.ALCHEMY_DIR_NAME} directory`,{alchemyPath:c}),await r.ensureDirectoryExists(c)
|
|
2369
|
-
const g=new
|
|
2363
|
+
const g=new I.TokenManager(q,n.default.join(c,"auth-token.json")),v=(await w.ClientFactory.createClient(T,q,S,{tokenManager:g,workingDir:_,alchemyPath:c})).projectClient,C=new b.ProjectClientAdapter(v,q),P=new u.ProjectSynchronizer(q,t,C,r),M=await P.getOrCreateProject(_,{name:n.default.basename(_)||"Local Project",description:"Project for "+n.default.basename(_),status:"active",metadata:{basePath:_,alchemyPath:c,bootstrapped:!0}})
|
|
2370
2364
|
q.info("Using project",{projectId:M.id,projectName:M.name})
|
|
2371
|
-
const
|
|
2372
|
-
|
|
2365
|
+
const j=(0,o.default)()
|
|
2366
|
+
j.use((0,s.default)()),j.use(o.default.json({limit:"50mb"})),j.use(o.default.urlencoded({extended:!0})),j.use((0,p.requestLogger)(q))
|
|
2373
2367
|
try{q.info("Creating MCP server instance")
|
|
2374
2368
|
const t=await(0,i.createServer)(_,q,S,T,{existingProjectId:M.id,multiAgentMode:(0,d.isMultiAgentModeEnabled)(_)})
|
|
2375
2369
|
q.info("MCP server instance created successfully")
|
|
2376
2370
|
const r=t.getContext()
|
|
2377
|
-
q.info("Got server context",{projectId:r.projectId}),t.getContext()&&t.connectionManager?(q.info("Adding connection status middleware"),
|
|
2371
|
+
q.info("Got server context",{projectId:r.projectId}),t.getContext()&&t.connectionManager?(q.info("Adding connection status middleware"),j.use((0,f.addConnectionStatusInfo)(t.connectionManager))):q.warn("Unable to add connection status middleware - connection manager not available")
|
|
2378
2372
|
try{const e=M.id
|
|
2379
|
-
q.info("Setting up project context middleware",{projectId:e}),
|
|
2373
|
+
q.info("Setting up project context middleware",{projectId:e}),j.use("/api",((t,r,n)=>{"GET"===t.method&&(t.query.projectId=e),["POST","PATCH","PUT"].includes(t.method)&&t.body&&(t.body.projectId=e),n()}))}catch(e){q.warn("Failed to set up project context middleware",{error:(0,k.getErrorMessage)(e)})}(0,a.registerApiRoutes)(j,t,q,S),j.use((0,p.errorHandler)(q,S)),j.listen(e,(()=>{q.info("HTTP API server listening on port "+e,{baseDir:_,port:e,nodeVersion:process.version})}))}catch(e){q.error("Failed to create or initialize MCP server",{error:e instanceof Error?e.stack:e+""})
|
|
2380
2374
|
let t=!1
|
|
2381
|
-
e instanceof Error&&(t=e.message.includes("connection")||e.message.includes("timeout")||e.message.includes("network")||"ConnectionError"===e.name),S.incrementCounter("server_initialization_failure",1,{isConnectionError:t?"true":"false"}),
|
|
2375
|
+
e instanceof Error&&(t=e.message.includes("connection")||e.message.includes("timeout")||e.message.includes("network")||"ConnectionError"===e.name),S.incrementCounter("server_initialization_failure",1,{isConnectionError:t?"true":"false"}),j.use(((e,t,r)=>{t.set("X-Connection-Status","offline"),t.set("X-Server-Initialization-Failed","true"),r()})),j.use("/api",((t,r)=>{r.status(503).json({success:!1,error:{code:"CONNECTION_ERROR",message:"Server failed to initialize due to connection issues. Please check connectivity and try again.",details:{serverError:e instanceof Error?e.message:e+"",suggestions:["Check your network connection","Verify that the remote server is running","Try restarting the local server"],isConnectionIssue:!0},retryable:!0,statusCode:503}})})),q.warn("Continuing with limited functionality due to initialization error")}process.on("SIGINT",(()=>{q.info("Received SIGINT signal, shutting down..."),process.exit(0)})),process.on("SIGTERM",(()=>{q.info("Received SIGTERM signal, shutting down..."),process.exit(0)})),process.on("uncaughtException",(e=>{q.error("Uncaught exception",{error:e.stack}),process.exit(1)})),process.on("unhandledRejection",(e=>{q.error("Unhandled promise rejection",{reason:e}),process.exit(1)}))}catch(e){q.error("Failed to start HTTP API server",{error:e instanceof Error?e.stack:e+""}),process.exit(1)}}()},3626(e,exports,t){function r(e){if(!e)return!1
|
|
2382
2376
|
const t=e.toLowerCase().replace(/^\./,"")
|
|
2383
2377
|
return u.has(t)}function n(e,t){if(r(t)){const t=e.match(/^([ \t]*)(.*?)\s*$/)
|
|
2384
2378
|
if(!t)return e
|
|
@@ -2469,18 +2463,18 @@ try{const a=u.validateArgs(e,d.GetFileInfoSchema),{path:h}=a
|
|
|
2469
2463
|
n.info("Getting file info: "+h)
|
|
2470
2464
|
const{normalizedPath:f,fullPath:m}=u.validateAndNormalizePath(h,t)
|
|
2471
2465
|
i=u.FileOperationPhase.FILE_WRITE
|
|
2472
|
-
try{await c.default.access(m)}catch(e){throw Error("Path not accessible: "+h)}const y=await c.default.stat(m),w=y.isFile()?l.default.extname(m).slice(1):"",k={path:f,type:y.isDirectory()?"directory":"file",size:y.size,sizeFormatted:(p=y.size,u.formatFileSize(p)),created:r(y.birthtime),modified:r(y.mtime),accessed:r(y.atime),permissions:(g=y.mode,(511&g).toString(8)),isDirectory:y.isDirectory(),isFile:y.isFile(),isSymbolicLink:y.isSymbolicLink(),extension:w},
|
|
2473
|
-
k.isFile&&w&&
|
|
2474
|
-
const
|
|
2475
|
-
return o.recordValue("get_file_info_time",
|
|
2466
|
+
try{await c.default.access(m)}catch(e){throw Error("Path not accessible: "+h)}const y=await c.default.stat(m),w=y.isFile()?l.default.extname(m).slice(1):"",k={path:f,type:y.isDirectory()?"directory":"file",size:y.size,sizeFormatted:(p=y.size,u.formatFileSize(p)),created:r(y.birthtime),modified:r(y.mtime),accessed:r(y.atime),permissions:(g=y.mode,(511&g).toString(8)),isDirectory:y.isDirectory(),isFile:y.isFile(),isSymbolicLink:y.isSymbolicLink(),extension:w},b=["File Information for: "+f,"Type: "+k.type,`Size: ${k.sizeFormatted} (${k.size} bytes)`,"Created: "+k.created,"Modified: "+k.modified,"Accessed: "+k.accessed,"Permissions: "+k.permissions,"Is Directory: "+k.isDirectory,"Is File: "+k.isFile,"Is Symbolic Link: "+k.isSymbolicLink]
|
|
2467
|
+
k.isFile&&w&&b.push("Extension: "+w)
|
|
2468
|
+
const I=Date.now()-s
|
|
2469
|
+
return o.recordValue("get_file_info_time",I),o.incrementCounter("get_file_info_success",1),n.info("Successfully retrieved file info: "+f,{type:k.type,size:k.size,time:I}),{content:[{type:"text",text:b.join("\n")}]}}catch(t){const r=Date.now()-s
|
|
2476
2470
|
return o.recordValue("get_file_info_time",r),o.incrementCounter("get_file_info_errors",1),n.error("Error getting file info:",{error:(0,h.getErrorMessage)(t),time:r}),u.handleFileOperationError(t,i,n,o,e,a)}var g,p}
|
|
2477
2471
|
const c=a(t(1943)),l=a(t(6928)),d=t(6183),u=i(t(5967)),h=t(8824)},3707(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleQuickChange=async function(e,t,d,u,h,g,p){const f=h.child({tool:"quick_edit"}),m=Date.now()
|
|
2478
|
-
try{const y=u.getRequestClient(),w=u.getTaskClient(),k=u.getFileClient(),
|
|
2479
|
-
f.info("Starting quick_edit workflow",{title:
|
|
2472
|
+
try{const y=u.getRequestClient(),w=u.getTaskClient(),k=u.getFileClient(),b=u.getToolRecordClient(),{title:I,description:v,...C}=e,_=e.comment||I
|
|
2473
|
+
f.info("Starting quick_edit workflow",{title:I,operationType:t})
|
|
2480
2474
|
let E=!1
|
|
2481
2475
|
try{const e=await y.listRequests({limit:2,sortBy:"created_at",sortDirection:"desc"})
|
|
2482
2476
|
e&&2===e.length&&e.every((e=>"quick-edit"===e.type))&&(E=!0,f.info("Detected two consecutive quick-edits, will recommend normal request"))}catch(e){f.warn("Could not check recent requests for recommendation",{error:e})}f.debug("Creating quick_edit request")
|
|
2483
|
-
const q=await y.createRequest({title:
|
|
2477
|
+
const q=await y.createRequest({title:I,description:v,type:"quick-edit",acceptanceCriteria:["Quick change completed successfully"]})
|
|
2484
2478
|
if(!q||!q.id)throw Error("Failed to create request")
|
|
2485
2479
|
const S=q.id
|
|
2486
2480
|
let T
|
|
@@ -2488,24 +2482,24 @@ f.info("Created request",{requestId:S})
|
|
|
2488
2482
|
try{if(f.debug("Checking for uncommitted user changes before quick-edit branch creation"),d.git)try{const e=await(0,c.commitUserChangesBeforeToolOperation)(d.git,"quick-fix",{requestId:S,taskId:void 0,workspaceManager:d.workspaceManager},h,g)
|
|
2489
2483
|
e.userChangesCommitted?f.info("Committed user changes to main before quick-edit branch creation",{requestId:S,commitHash:e.commitHash?.substring(0,8)}):f.debug("No uncommitted changes found, proceeding with quick-edit")}catch(e){f.warn("Failed to commit user changes before quick-edit, proceeding anyway",{requestId:S,error:e instanceof Error?e.message:e+""})}else f.debug("No git instance available, skipping uncommitted changes check")
|
|
2490
2484
|
f.debug("Creating task")
|
|
2491
|
-
const e=await w.createTask({requestId:S,projectId:d.projectId,title:`Execute ${t} operation`,description:"Quick change: "+
|
|
2485
|
+
const e=await w.createTask({requestId:S,projectId:d.projectId,title:`Execute ${t} operation`,description:"Quick change: "+I})
|
|
2492
2486
|
if(!e||!e.id)throw Error("Failed to create task")
|
|
2493
2487
|
let v
|
|
2494
|
-
if(T=e.id,f.info("Created task",{taskId:T}),f.debug("Executing file operation",{operationType:t}),"write"===t)v=await(0,n.handleWriteFile)({taskId:T,...C,comment:_},d,k,w,
|
|
2495
|
-
else if("replace"===t)v=await(0,o.handleReplaceInFiles)({taskId:T,...C,comment:_},d,w,
|
|
2488
|
+
if(T=e.id,f.info("Created task",{taskId:T}),f.debug("Executing file operation",{operationType:t}),"write"===t)v=await(0,n.handleWriteFile)({taskId:T,...C,comment:_},d,k,w,b,y,h,g,p)
|
|
2489
|
+
else if("replace"===t)v=await(0,o.handleReplaceInFiles)({taskId:T,...C,comment:_},d,w,b,y,h,g,p)
|
|
2496
2490
|
else{if("manage"!==t)throw new r.ValidationError("Unsupported operation type: "+t)
|
|
2497
|
-
v=await(0,s.handleManageFiles)({taskId:T,...C,comment:_||
|
|
2491
|
+
v=await(0,s.handleManageFiles)({taskId:T,...C,comment:_||I},d,w,b,y,u,h,g,p)}if(v.isError){f.error("File operation failed, cleaning up request and task",{requestId:S,taskId:T})
|
|
2498
2492
|
try{await w.updateTaskStatus(T,"canceled"),f.info("Canceled task after operation failure",{taskId:T})}catch(e){f.warn("Failed to cancel task during cleanup",{taskId:T,error:e instanceof Error?e.message:e+""})}try{await y.updateRequest(S,{status:"canceled"}),f.info("Canceled request after operation failure",{requestId:S}),d.workspaceManager&&(await d.workspaceManager.cancelRequest(S),f.info("Cleaned up branch/worktree after operation failure",{requestId:S}))}catch(e){f.warn("Failed to cancel request during cleanup",{requestId:S,error:e instanceof Error?e.message:e+""})}return{content:[{type:"text",text:`\u274c Quick change failed during ${t} operation:\n\n${v.content[0].text}\n\nThe request (${S}) and task have been canceled and cleaned up.`}],isError:!0}}const q=v.content[0].text,P=q.includes("\u26a0\ufe0f Partial Success")||q.includes("\u274c Failed")||q.includes("\u274c 0 successful")
|
|
2499
2493
|
P?f.warn("File operation completed with partial failures",{requestId:S}):f.info("File operation completed successfully"),f.debug("Completing task")
|
|
2500
|
-
try{await(0,i.handleCompleteTask)({taskId:T,summary:`Executed ${t} operation for quick fix: ${
|
|
2494
|
+
try{await(0,i.handleCompleteTask)({taskId:T,summary:`Executed ${t} operation for quick fix: ${I}${P?" (partial success)":""}`},d,u,h,g),f.info("Task completed successfully",{taskId:T})}catch(e){f.error("Task completion via handleCompleteTask failed, attempting direct status update",{taskId:T,error:e instanceof Error?e.message:e+"",errorStack:e instanceof Error?e.stack:void 0})
|
|
2501
2495
|
try{await w.updateTaskStatus(T,"completed"),f.info("Task completed via direct updateTaskStatus call",{taskId:T})}catch(e){return f.error("Direct task completion ALSO failed - task may be stuck in in_progress",{taskId:T,error:e instanceof Error?e.message:e+"",errorStack:e instanceof Error?e.stack:void 0,operationType:t,isDocumentOperation:!!C.documentId}),{content:[{type:"text",text:`\u26a0\ufe0f Quick change operation succeeded but task completion failed.\n\n**Request:** ${S}\n**Task:** ${T}\n**Issue:** Could not mark task as completed - it remains in 'in_progress' state\n\nThe ${t} operation was successful, but we couldn't automatically complete the task. Please use the complete-task tool manually with taskId: ${T}\n\nError: `+(e instanceof Error?e.message:e+"")}],isError:!0}}}f.debug("Completing request")
|
|
2502
|
-
const M=P?`Quick change completed with partial success: ${
|
|
2503
|
-
let
|
|
2504
|
-
try{const e=await(0,a.handleCompleteRequest)({requestId:S,summary:M,acceptanceEvidence:[{evidence:
|
|
2496
|
+
const M=P?`Quick change completed with partial success: ${I}. Some replacements failed - see details below.`:"Quick change completed: "+I,j=P?t+" operation partially completed - some operations succeeded, some failed":t+" operation executed successfully"
|
|
2497
|
+
let R=!1
|
|
2498
|
+
try{const e=await(0,a.handleCompleteRequest)({requestId:S,summary:M,acceptanceEvidence:[{evidence:j}],testVerification:void 0},d,u,h,g,p)
|
|
2505
2499
|
if(e.isError)f.error("Request completion failed, attempting direct completion",{requestId:S,error:e.content[0].text})
|
|
2506
|
-
else{try{await y.updateRequest(S,{status:"completed",completionSummary:M}),f.info("Request finalized to completed",{requestId:S})}catch(e){f.warn("Failed to finalize request to completed, may be stuck at ready_for_merge",{requestId:S,error:(0,l.getErrorMessage)(e)})}
|
|
2500
|
+
else{try{await y.updateRequest(S,{status:"completed",completionSummary:M}),f.info("Request finalized to completed",{requestId:S})}catch(e){f.warn("Failed to finalize request to completed, may be stuck at ready_for_merge",{requestId:S,error:(0,l.getErrorMessage)(e)})}R=!0,f.info("Request completed successfully",{requestId:S})}}catch(e){f.error("Request completion threw exception, attempting direct completion",{requestId:S,error:e instanceof Error?e.message:e+""})}if(!R)try{f.info("Attempting direct request completion via API",{requestId:S}),await y.updateRequest(S,{status:"completed",completionSummary:M}),R=!0,f.info("Request completed successfully via direct API call",{requestId:S})}catch(e){return f.error("Direct request completion also failed",{requestId:S,error:e instanceof Error?e.message:e+""}),{content:[{type:"text",text:`\u26a0\ufe0f Quick change operation succeeded but request completion failed.\n\n**Request:** ${S}\n**Status:** Still in 'in_progress' - please complete manually\n\nThe file operation was successful, but we couldn't automatically complete the request. Please use the complete-request tool manually.`}],isError:!0}}const x=Date.now()-m
|
|
2507
2501
|
let O
|
|
2508
|
-
return f.info("Quick fix completed",{requestId:S,duration:x,hasPartialFailure:P}),O=P?`\u26a0\ufe0f Quick change completed with partial success\n\n**Request:** ${S}\n**Title:** ${
|
|
2502
|
+
return f.info("Quick fix completed",{requestId:S,duration:x,hasPartialFailure:P}),O=P?`\u26a0\ufe0f Quick change completed with partial success\n\n**Request:** ${S}\n**Title:** ${I}\n**Operation:** ${t}\n**Duration:** ${x}ms\n**Status:** Some operations succeeded, some failed\n\nThe successful changes have been applied and automatically merged to main.\n**Active branch:** main\n\n**\u26a0\ufe0f Note:** This quick-fix had partial failures. See operation details below:\n\n`+q:`\u2705 Quick change completed successfully!\n\n**Request:** ${S}\n**Title:** ${I}\n**Operation:** ${t}\n**Duration:** ${x}ms\n\nThe change has been applied and automatically merged to main.\n**Active branch:** main`+(q.match(/\[RECORD:trec\d{6}\]/)?.[0]?"\n"+q.match(/\[RECORD:trec\d{6}\]/)?.[0]:""),E&&(O+="\n\n\u{1f4a1} **Recommendation:** You've created several quick-edits in a row. For better traceability and organization, consider creating a proper feature or bugfix request with multiple tasks for your next change."),{content:[{type:"text",text:O}]}}catch(e){if(f.error("Quick change workflow failed after request creation, cleaning up",{requestId:S,error:(0,l.getErrorMessage)(e)}),T)try{await w.updateTaskStatus(T,"canceled"),f.info("Canceled task after workflow failure",{taskId:T})}catch(e){f.warn("Failed to cancel task during cleanup",{taskId:T,error:e instanceof Error?e.message:e+""})}try{await y.updateRequest(S,{status:"canceled"}),f.info("Canceled request after workflow failure",{requestId:S}),d.workspaceManager&&(await d.workspaceManager.cancelRequest(S),f.info("Cleaned up branch/worktree after workflow failure",{requestId:S}))}catch(e){f.warn("Failed to cancel request during cleanup",{requestId:S,error:e instanceof Error?e.message:e+""})}throw e}}catch(e){const t=Date.now()-m
|
|
2509
2503
|
return f.error("Quick change failed",{error:(0,l.getErrorMessage)(e),duration:t}),e instanceof r.ValidationError?{content:[{type:"text",text:"\u274c "+e.message}],isError:!0}:{content:[{type:"text",text:"\u274c Quick change failed: "+(0,l.getErrorMessage)(e)}],isError:!0}}}
|
|
2510
2504
|
const r=t(9860),n=t(4079),o=t(9442),s=t(7684),i=t(355),a=t(5715),c=t(7478),l=t(8824)},3807(module){module.exports=require("simple-git")},3884(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.middleware=exports.validateRequest=exports.authenticate=exports.corsOptions=exports.errorHandler=exports.requestLogger=void 0
|
|
2511
2505
|
const r=t(9860),n=t(5674)
|
|
@@ -2578,46 +2572,46 @@ return t},r(e)},function(e){if(e&&e.__esModule)return e
|
|
|
2578
2572
|
var t={}
|
|
2579
2573
|
if(null!=e)for(var s=r(e),i=0;i<s.length;i++)"default"!==s[i]&&n(t,e,s[i])
|
|
2580
2574
|
return o(t,e),t}),i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
2581
|
-
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleWriteFile=async function(e,t,r,n,o,s,i,m,y){const w=i.child({tool:"write_file"}),k=m.startTimer("tool_execution_time"),
|
|
2582
|
-
let
|
|
2575
|
+
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleWriteFile=async function(e,t,r,n,o,s,i,m,y){const w=i.child({tool:"write_file"}),k=m.startTimer("tool_execution_time"),b=Date.now()
|
|
2576
|
+
let I,v,C=d.FileOperationPhase.VALIDATION
|
|
2583
2577
|
const _={toolName:"write_file",operationName:"write",fileOperationPhase:d.FileOperationPhase.FILE_WRITE,recordType:"write-file",metricsPrefix:"write_file",successMessage:"Successfully wrote content",failureMessage:"Failed to write content"}
|
|
2584
|
-
try{const r=d.validateArgs(e,l.WriteFileSchema),{taskId:i,path:f,documentId:E,content:q,format:S,append:T,comment:P}=r,M=!!E,
|
|
2585
|
-
w.info("Writing content to "+(M?"document":"file"),{taskId:i,filePath:
|
|
2586
|
-
let
|
|
2587
|
-
const F=
|
|
2578
|
+
try{const r=d.validateArgs(e,l.WriteFileSchema),{taskId:i,path:f,documentId:E,content:q,format:S,append:T,comment:P}=r,M=!!E,j=!!f
|
|
2579
|
+
w.info("Writing content to "+(M?"document":"file"),{taskId:i,filePath:j?f:void 0,documentId:M?E:void 0,contentLength:"string"==typeof q?q.length:JSON.stringify(q).length,format:S,append:T,comment:P})
|
|
2580
|
+
let R,x,O,A="",D=!1,$=!1
|
|
2581
|
+
const F=j?f:void 0
|
|
2588
2582
|
if(M){if(t.apiClient)try{await(0,p.ensureDocumentNotLocked)(E,t.apiClient,w,m,"write_file-document")}catch(e){if(e instanceof u.ValidationError)return{content:[{type:"text",text:e.message}],isError:!0}
|
|
2589
2583
|
throw e}if(!t.documentFileManager)throw Error("Document file manager not available")
|
|
2590
2584
|
A=await t.documentFileManager.getDocumentAsFile(E)
|
|
2591
2585
|
const e=t.documentFileManager.getCachedDocumentInfo(E)
|
|
2592
2586
|
O=e?.filename,$=!0,D=!1}C=d.FileOperationPhase.TASK_VALIDATION,m.incrementCounter("write_file_phase",1,{phase:C})
|
|
2593
|
-
const N=
|
|
2587
|
+
const N=j?F:"document:"+E,L=await d.validateTaskId(i,N,n,w,m,_.metricsPrefix),z=L?.requestId
|
|
2594
2588
|
let B=null
|
|
2595
|
-
|
|
2589
|
+
j&&z&&(B=await d.validateWorkItemStates(i,N,n,s,t,w,m,_.metricsPrefix))
|
|
2596
2590
|
let H={taskPromoted:!1,requestPromoted:!1}
|
|
2597
|
-
|
|
2598
|
-
const W=await d.ensureCorrectWorkspaceContext({taskPromoted:H.taskPromoted,requestId:z,context:t,operation:"write_file",logger:w,metrics:m,metricsPrefix:_.metricsPrefix,requireRequestContext:
|
|
2591
|
+
j&&z&&B&&(H=await d.autoPromoteTaskStatus(i,L.status,z,B.request?.status,N,n,s,w,m,_.metricsPrefix),H.taskPromoted&&w.info("Auto-promoted task to in_progress for file operation",{taskId:i,requestId:z,previousStatus:L.status,newStatus:H.newTaskStatus,triggeringOperation:"write_file"}))
|
|
2592
|
+
const W=await d.ensureCorrectWorkspaceContext({taskPromoted:H.taskPromoted,requestId:z,context:t,operation:"write_file",logger:w,metrics:m,metricsPrefix:_.metricsPrefix,requireRequestContext:j})
|
|
2599
2593
|
if(!W.success){if(W.isLockConflict)return{content:[{type:"text",text:"\u274c "+W.error}],isError:!0}
|
|
2600
|
-
throw Error(W.error)}if(W.switched&&w.info("Workspace context successfully established",{requestId:z,branchName:W.branchName,operation:"write_file"}),
|
|
2601
|
-
|
|
2602
|
-
try{await c.default.access(x),$=!0}catch{$=!1,D=!0}w.debug("Path validated with correct workspace context",{rawPath:F,normalizedPath:
|
|
2594
|
+
throw Error(W.error)}if(W.switched&&w.info("Workspace context successfully established",{requestId:z,branchName:W.branchName,operation:"write_file"}),j&&F){const e=d.validateAndNormalizePath(F,t)
|
|
2595
|
+
R=e.normalizedPath,x=e.fullPath,A=x
|
|
2596
|
+
try{await c.default.access(x),$=!0}catch{$=!1,D=!0}w.debug("Path validated with correct workspace context",{rawPath:F,normalizedPath:R,fullPath:x,workspaceBasePath:t.workspaceManager?.getCurrentContext().basePath})}if(M&&z)try{await(0,h.validateRequestStatusForDocumentOperation)(z,s,w,m,"write_file-document")}catch(e){if(e instanceof u.ValidationError)return{content:[{type:"text",text:e.message}],isError:!0}
|
|
2603
2597
|
throw e}C=d.FileOperationPhase.RECORD_CREATION,m.incrementCounter("write_file_phase",1,{phase:C})
|
|
2604
|
-
const{toolRecordId:U}=await d.createFileOperationRecords(i,z,t.projectId,_.recordType,N,{operationType:M?"document":"file",documentId:M?E:void 0,documentFilename:O,filePath:R
|
|
2598
|
+
const{toolRecordId:U}=await d.createFileOperationRecords(i,z,t.projectId,_.recordType,N,{operationType:M?"document":"file",documentId:M?E:void 0,documentFilename:O,filePath:j?R:void 0,contentLength:"string"==typeof q?q.length:JSON.stringify(q).length,format:S||"text",append:T||!1,wasFileCreated:!$,userComment:P},n,o,w,m,_.metricsPrefix,y)
|
|
2605
2599
|
let G
|
|
2606
|
-
if(
|
|
2600
|
+
if(I=U,v=U,C=_.fileOperationPhase,m.incrementCounter("write_file_phase",1,{phase:C}),"json"===S)if("string"==typeof q)try{JSON.parse(q),G=q}catch(e){throw new u.ValidationError("Content is not valid JSON")}else G=JSON.stringify(q,null,2)
|
|
2607
2601
|
else G="string"==typeof q?q:JSON.stringify(q,null,2)
|
|
2608
2602
|
let V=G
|
|
2609
|
-
if(
|
|
2603
|
+
if(j&&t.git)try{w.debug("[WRITE-FILE] Checking for user changes before write operation")
|
|
2610
2604
|
const e=await(0,g.commitUserChangesBeforeToolOperation)(t.git,"write_file",{requestId:t.workspaceManager?.getCurrentContext()?.requestId,taskId:i},w,m)
|
|
2611
|
-
e.userChangesCommitted&&(w.debug("[WRITE-FILE] User changes committed before write operation",{commitHash:e.commitHash?.substring(0,8),filesCommitted:e.filesCommitted}),w.info("User changes committed before write-file operation",{taskId:i,path:
|
|
2605
|
+
e.userChangesCommitted&&(w.debug("[WRITE-FILE] User changes committed before write operation",{commitHash:e.commitHash?.substring(0,8),filesCommitted:e.filesCommitted}),w.info("User changes committed before write-file operation",{taskId:i,path:R,userCommitHash:e.commitHash?.substring(0,8),userFilesCommitted:e.filesCommitted}))}catch(e){w.debug("[WRITE-FILE] Pre-tool commit failed, continuing with write",{error:e instanceof Error?e.message:e+""}),w.warn("Pre-tool user changes commit failed, continuing with write operation",{taskId:i,path:R,error:e instanceof Error?e.message:e+""})}if(!A)throw Error("Target path not properly initialized")
|
|
2612
2606
|
if(w.debug("[WRITE-FILE] Proceeding with file write operation",{targetPath:A}),T&&$)try{V=await c.default.readFile(A,"utf8")+G}catch(e){w.warn("Failed to read existing content for append",{error:e})}const J=a.default.dirname(A)
|
|
2613
|
-
if(await c.default.mkdir(J,{recursive:!0}),await c.default.writeFile(A,V,"utf8"),w.info("Content written successfully",{path:R
|
|
2614
|
-
try{await t.documentFileManager.syncDocument(E),w.info("Document synced successfully",{documentId:E})}catch(e){w.warn("Failed to sync document immediately",{documentId:E,error:e})}}let Y,
|
|
2615
|
-
if(
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
Z+=`**Content Length:** ${V.length} characters\n`,
|
|
2607
|
+
if(await c.default.mkdir(J,{recursive:!0}),await c.default.writeFile(A,V,"utf8"),w.info("Content written successfully",{path:j?R:"document:"+E,finalLength:V.length,append:T,wasCreated:D}),M){t.documentFileManager.markForSync(E)
|
|
2608
|
+
try{await t.documentFileManager.syncDocument(E),w.info("Document synced successfully",{documentId:E})}catch(e){w.warn("Failed to sync document immediately",{documentId:E,error:e})}}let K,Y,Q=null
|
|
2609
|
+
if(j){if(C=d.FileOperationPhase.GIT_COMMIT,m.incrementCounter("write_file_phase",1,{phase:C}),t.workspaceManager){const e=t.workspaceManager.getCurrentContext()
|
|
2610
|
+
Y=e.branchName,w.debug("Retrieved branch name from workspace manager",{branchName:Y,requestId:e.requestId,mode:e.mode,isMainBranch:e.isMainBranch})}try{const e=`${D?"Create":T?"Append to":"Update"} ${R} (${v})`,r=await d.commitToGit(i,R,v,v,e,t,w,m,_.metricsPrefix)
|
|
2611
|
+
K=r.commitHash,Q=r.previousCommitHash,w.info("Changes committed to git via shared utility",{path:R,commitMessage:e,commitHash:K?.substring(0,8),previousCommitHash:Q?.substring(0,8),branchName:Y,toolRecordId:v})}catch(e){w.warn("Git operations failed via shared utility",{error:e})}}try{await o.updateToolRecord(v,{metadata:{path:j?R:"document:"+E,status:"completed",finalContentLength:V.length,wasFileCreated:D,wasAppended:T&&$,operationType:M?"document":"file",processingTime:Date.now()-b,userComment:P,...j&&K&&{commitHash:K,previousCommitHash:Q||void 0}},note:"Write operation completed successfully"+(M?" (document synced)":" (committed to git)")})}catch(e){w.warn("Failed to update tool record",{recordError:e})}let Z=`**${D?"Created":T?"Appended to":"Updated"} ${M?`document ${E}${O?` (${O})`:""}`:"file "+R}**\n`
|
|
2612
|
+
Z+=`**Content Length:** ${V.length} characters\n`,j&&Y&&(Z+=`**Branch:** ${Y}\n`),W.lockAcquired&&W.lockedRequestId&&(Z+=`**Locked request:** ${W.lockedRequestId}\n`),j&&K&&(Z+=`**Commit Hash:** ${K.substring(0,8)}\n`,Q&&(Z+=`**Previous Commit:** ${Q.substring(0,8)}\n`)),v&&(Z+=`[RECORD:${v}]\n`),M&&(Z+=`\n**Document Update:** The document content has been updated and synced back to the tracking system. You can continue editing using other file modification tools with documentId \`${E}\`.`)
|
|
2619
2613
|
const X=Date.now()
|
|
2620
|
-
return w.info("Write operation completed successfully",{duration:X-
|
|
2614
|
+
return w.info("Write operation completed successfully",{duration:X-b,path:j?R:"document:"+E,contentLength:V.length,wasCreated:D}),k({tool:"write_file",success:!0}),m.incrementCounter("write_file_total",1,{success:!0}),t.workspaceManager?.largeFileWarning&&(Z+=t.workspaceManager.largeFileWarning,t.workspaceManager.largeFileWarning=""),{content:[{type:"text",text:Z}]}}catch(t){const r=Date.now()-b
|
|
2621
2615
|
if(w.error("Write operation failed",{error:t instanceof Error?t.stack:t+"",duration:r,phase:C}),v)try{await o.updateToolRecord(v,{metadata:{path:e?.path,status:"failed",error:(0,f.getErrorMessage)(t),phase:C,duration:r,userComment:e?.comment},note:"Write operation failed: "+(0,f.getErrorMessage)(t)})}catch(e){}return k({tool:"write_file",success:!1}),m.incrementCounter("write_file_errors",1,{phase:C}),{content:[{type:"text",text:"\u274c **Write Operation Failed:** "+(0,f.getErrorMessage)(t)}],isError:!0}}}
|
|
2622
2616
|
const a=i(t(6928)),c=i(t(1943)),l=t(6183),d=s(t(5967)),u=t(9860),h=t(5003),g=t(7478),p=t(9949),f=t(8824)},4139(e,exports){Object.defineProperty(exports,"__esModule",{value:!0}),exports.ALCHEMY_DIR_NAME=exports.TOKEN_DIR_NAME=void 0,exports.TOKEN_DIR_NAME="alchemy-key",exports.ALCHEMY_DIR_NAME=".alchemy_lab"},4165(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.def=void 0
|
|
2623
2617
|
const r=t(6183),n=t(4648)
|
|
@@ -2788,10 +2782,10 @@ try{let o
|
|
|
2788
2782
|
try{o=i.FileRecoverSchema.parse(e)}catch(t){if(t instanceof a.ZodError){const r="Invalid arguments: "+t.errors.map((e=>e.message)).join(", ")
|
|
2789
2783
|
return p.warn("Validation error",{error:r,args:e}),{content:[{type:"text",text:"\u274c "+r}],isError:!0}}throw t}const{taskId:f,path:y,commitHash:w,createBackup:k}=o
|
|
2790
2784
|
return p.info("Recovering file to previous version",{taskId:f,filePath:y,commitHash:w,createBackup:k}),await async function(e,t,r,n,o,s,i,a,g,p,f){let m
|
|
2791
|
-
try{const{normalizedPath:y,fullPath:w}=d.validateAndNormalizePath(t,o),k=await d.validateTaskId(e,y,s.getTaskClient(),a,g,"file-recover"),{toolRecordId:
|
|
2792
|
-
m=
|
|
2793
|
-
let
|
|
2794
|
-
try{await l.access(w),v=!0,n&&(
|
|
2785
|
+
try{const{normalizedPath:y,fullPath:w}=d.validateAndNormalizePath(t,o),k=await d.validateTaskId(e,y,s.getTaskClient(),a,g,"file-recover"),{toolRecordId:b}=await d.createFileOperationRecords(e,k?.requestId,o.projectId,"file-recover",y,{operationType:"file",filePath:y,commitHash:r,createBackup:n},s.getTaskClient(),i,a,g,"file-recover",f)
|
|
2786
|
+
m=b
|
|
2787
|
+
let I,v=!1
|
|
2788
|
+
try{await l.access(w),v=!0,n&&(I=`${w}.backup-${(new Date).toISOString().replace(/[:.]/g,"-")}`,await l.copyFile(w,I),a.info("Created backup",{originalPath:w,backupPath:I}))}catch{v=!1}const C=o.git
|
|
2795
2789
|
if(!C)throw Error("Git is not available")
|
|
2796
2790
|
if(!(await(0,u.validateCommitHash)(C,r,a,"file-recover")).valid)throw Error(`Commit hash '${r}' is invalid or not found`)
|
|
2797
2791
|
let _
|
|
@@ -2800,9 +2794,9 @@ if(t.includes("does not exist")||t.includes("not found")||t.includes("Path"))thr
|
|
|
2800
2794
|
throw Error(`Failed to retrieve file '${y}' from commit '${r}': ${t}`)}await l.writeFile(w,_,"utf8")
|
|
2801
2795
|
let E={}
|
|
2802
2796
|
try{const t=`Recover ${y} from ${r.substring(0,8)}`
|
|
2803
|
-
E=await d.commitToGit(e,y,m,m,t,o,a,g,"file-recover"),a.info("Recovery committed via shared utility",{path:y,sourceCommitHash:r,newCommitHash:E.commitHash?.substring(0,8),commitMessage:t})}catch(e){a.warn("Failed to commit recovery via shared utility",{error:e})}if(m)try{await i.updateToolRecord(m,{metadata:{path:y,status:"completed",recoveredLength:_.length,hadBackup:n&&v,backupPath:
|
|
2797
|
+
E=await d.commitToGit(e,y,m,m,t,o,a,g,"file-recover"),a.info("Recovery committed via shared utility",{path:y,sourceCommitHash:r,newCommitHash:E.commitHash?.substring(0,8),commitMessage:t})}catch(e){a.warn("Failed to commit recovery via shared utility",{error:e})}if(m)try{await i.updateToolRecord(m,{metadata:{path:y,status:"completed",recoveredLength:_.length,hadBackup:n&&v,backupPath:I,wasFileCreated:!v,processingTime:Date.now()-p,...E.commitHash&&{commitHash:E.commitHash,previousCommitHash:E.previousCommitHash||void 0}},note:"File recovered successfully from "+r.substring(0,8)})}catch(e){a.warn("Failed to update tool record",{recordError:e})}const q=v?"recovered":"created from recovery"
|
|
2804
2798
|
let S=`\u2705 **File ${q.charAt(0).toUpperCase()+q.slice(1)} Successfully**\n\n`
|
|
2805
|
-
return S+=`**File:** ${y}\n`,S+=`**Recovered from:** ${r.substring(0,8)}\n`,S+=`**Content length:** ${_.length} characters\n`,n&&v&&
|
|
2799
|
+
return S+=`**File:** ${y}\n`,S+=`**Recovered from:** ${r.substring(0,8)}\n`,S+=`**Content length:** ${_.length} characters\n`,n&&v&&I&&(S+=`**Backup created:** ${c.basename(I)}\n`),S+="**Git status:** Recovery committed\n",S+="\u{1f4a1} **Tip:** The file has been restored to its state at the specified commit.",a.info("File recovery completed successfully",{path:y,commitHash:r,duration:Date.now()-p}),g.incrementCounter("file_recover_total",1,{success:!0,type:"file"}),{content:[{type:"text",text:S}]}}catch(e){throw e}}(f,y,w,k,t,r,n,p,s,m,g)}catch(e){const t=Date.now()-m
|
|
2806
2800
|
return p.error("Recovery operation failed",{error:e instanceof Error?e.stack:e+"",duration:t}),f({tool:"file_recover",success:!1}),s.incrementCounter("file_recover_errors",1),{content:[{type:"text",text:"\u274c **Recovery Failed:** "+(0,h.getErrorMessage)(e)}],isError:!0}}}
|
|
2807
2801
|
const i=t(6183),a=t(1569),c=s(t(6928)),l=s(t(1943)),d=s(t(5967)),u=t(3922),h=t(8824)},4648(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleRequestOperations=async function(e,t,u,h,g,p){const f=h.child({tool:"request_operations"})
|
|
2808
2802
|
try{for(const t of["complete","verifyCriteria","merge","revert","search","list"])if(e&&"string"==typeof e[t])try{e[t]=JSON.parse(e[t])}catch{}"complete"===e?.operation&&e?.summary&&!e?.complete&&(e.complete={summary:e.summary},delete e.summary),"complete"!==e?.operation||e?.complete||e?.summary||(e.complete={summary:""}),"merge"===e?.operation&&e?.verifications&&!e?.merge&&(e.merge={verifications:e.verifications},delete e.verifications),e?.merge&&Array.isArray(e.merge)&&(e.merge={verifications:e.merge}),"verify-criteria"===e?.operation&&(e.operation="merge",e.verifyCriteria&&!e.merge&&(e.merge=e.verifyCriteria,delete e.verifyCriteria)),"finalize"===e?.operation&&(e.operation="merge",e.merge||(e.merge={verifications:[]})),"revert"===e?.operation&&e?.reason&&!e?.revert&&(e.revert={reason:e.reason,confirmDestructive:e.confirmDestructive},delete e.reason,delete e.confirmDestructive),"search"===e?.operation&&e?.query&&!e?.search&&(e.search={query:e.query,searchIn:e.searchIn||"all",filters:e.filters},delete e.query,delete e.searchIn,delete e.filters)
|
|
@@ -2950,15 +2944,15 @@ if(/^\d+$/.test(e)){const t=parseInt(e,10)
|
|
|
2950
2944
|
return{start:t,end:t}}const t=e.match(/^(\d+)-(\d+)$/)
|
|
2951
2945
|
if(t)return{start:parseInt(t[1],10),end:parseInt(t[2],10)}
|
|
2952
2946
|
if(e.match(/^(\d+(?:,\d+)+)$/)){const t=e.split(",").map((e=>parseInt(e,10)))
|
|
2953
|
-
return{start:Math.min(...t),end:Math.max(...t)}}return null}(p),
|
|
2954
|
-
let
|
|
2955
|
-
k&&
|
|
2947
|
+
return{start:Math.min(...t),end:Math.max(...t)}}return null}(p),b=["blame","--porcelain"]
|
|
2948
|
+
let I
|
|
2949
|
+
k&&b.push(`-L${k.start},${k.end}`),f&&b.push(f),b.push("--",w),c.debug("Executing git blame",{args:b})
|
|
2956
2950
|
try{if(!t.git)throw Error("Git context not available")
|
|
2957
|
-
|
|
2951
|
+
I=await t.git.raw(b)}catch(e){const t=(0,h.getErrorMessage)(e)
|
|
2958
2952
|
return c.error("Git blame failed",{error:t}),{content:[{type:"text",text:"\u274c Git blame failed: "+t}],isError:!0}}const v=function(e){const t=[],r=e.split("\n")
|
|
2959
2953
|
let n="",o="",s="",i=0,a=0,c=new Map
|
|
2960
2954
|
for(let e=0;e<r.length;e++){const l=r[e],d=l.match(/^([0-9a-f]{40})\s+\d+\s+(\d+)/)
|
|
2961
|
-
d?(n=d[1],a=parseInt(d[2],10)):l.startsWith("author ")?o=l.substring(7):l.startsWith("author-mail ")?s=l.substring(12).replace(/[<>]/g,""):l.startsWith("author-time ")?i=parseInt(l.substring(12),10):l.startsWith("summary ")?c.set(n,l.substring(8)):l.startsWith("\t")&&t.push({lineNumber:a,commitHash:n,author:o,authorEmail:s,timestamp:i,content:l.substring(1),commitMessage:c.get(n)})}return t}(
|
|
2955
|
+
d?(n=d[1],a=parseInt(d[2],10)):l.startsWith("author ")?o=l.substring(7):l.startsWith("author-mail ")?s=l.substring(12).replace(/[<>]/g,""):l.startsWith("author-time ")?i=parseInt(l.substring(12),10):l.startsWith("summary ")?c.set(n,l.substring(8)):l.startsWith("\t")&&t.push({lineNumber:a,commitHash:n,author:o,authorEmail:s,timestamp:i,content:l.substring(1),commitMessage:c.get(n)})}return t}(I)
|
|
2962
2956
|
if(0===v.length)return{content:[{type:"text",text:"\u274c No blame information found for "+w}],isError:!0}
|
|
2963
2957
|
const C=function(e){if(0===e.length)return[]
|
|
2964
2958
|
const t=[]
|
|
@@ -3194,10 +3188,10 @@ const m=g.acceptanceCriteria||[],y={unverified:0,partial:0,verified:0,partially_
|
|
|
3194
3188
|
m.forEach((e=>{const t=e.status||"unverified"
|
|
3195
3189
|
t in y&&y[t]++}))
|
|
3196
3190
|
let w=g.testVerification||null
|
|
3197
|
-
const k=g.title,
|
|
3198
|
-
let
|
|
3199
|
-
return
|
|
3200
|
-
|
|
3191
|
+
const k=g.title,b=g.type
|
|
3192
|
+
let I=`# ${"feature"===b?"Feature":"quick-edit"===b?"Quick Edit":"Bug Fix"} Request: ${k} (${t})\nStatus: ${g.status}\nCreated: ${new Date(g.createdAt).toLocaleString()}\nUpdated: ${new Date(g.updatedAt).toLocaleString()}\n\n## Description\n${g.description||"_No description provided._"}\n\n## Progress Summary\n- Tasks: ${f.completed}/${f.total} completed (${Math.round(f.completed/f.total*100)||0}%)\n- Acceptance Criteria: ${y.verified}/${y.total} verified (${Math.round(y.verified/y.total*100)||0}%)\n`
|
|
3193
|
+
return I+=`\n## Task Status\n- Pending: ${f.pending}\n- In Progress: ${f.in_progress}\n- Blocked: ${f.blocked}\n- Ready for Review: ${f.ready_for_review}\n- Completed: ${f.completed}\n- Reverted: ${f.reverted}\n`,I+="\n## Tasks\n",0===p.length?I+="No tasks found for this request.\n":p.forEach((e=>{I+=`**[${e.id}]** ${e.title} (Status: ${e.status})\n`})),d.info(`Added task listing with ${p.length} tasks`),I+="\n## Acceptance Criteria\n",I+=(0,i.formatCriteriaWithHashes)(m)+"\n","ready_for_review"===g.status&&m.some((e=>"verified"!==e.status))&&(I+="\n> **Status: ready_for_review** \u2014 Use the merge operation to verify criteria and merge to main.\n"),w&&(I+=`\n## Test Coverage\n- Test Cases: ${w.totalTestCases||0}\n- Criteria Tested: ${w.criteriaTestedCount||0}/${y.total}\n`,w.criterionCoverage&&Array.isArray(w.criterionCoverage)&&(I+="\n### Detailed Test Coverage:\n",w.criterionCoverage.forEach((e=>{I+=`- Criterion ${e.criterionId}: ${e.coverage} coverage\n`})))),g.recentActivity&&Array.isArray(g.recentActivity)&&(I+="\n## Recent Activity\n",g.recentActivity.slice(0,5).forEach((e=>{const t=new Date(e.timestamp).toLocaleString()
|
|
3194
|
+
I+=`- ${t}: ${e.description}\n`}))),u({success:!0}),{content:[{type:"text",text:I}]}}catch(t){return d.error("Error getting request information",{args:e,error:t instanceof Error?t.stack:t+""}),u({success:!1,error:t instanceof Error?t.name:"unknown"}),t instanceof n.ConnectionError?{content:[{type:"text",text:"Unable to get request information: Connection to the server failed. Please check your network connection and try again."}],isError:!0}:{content:[{type:"text",text:"Error getting request information: "+(0,s.getErrorMessage)(t)}],isError:!0}}}
|
|
3201
3195
|
const r=t(9860),n=t(5674),o=t(2960),s=t(8824),i=t(5454)},5454(e,exports){function t(e,t){let r=0
|
|
3202
3196
|
for(let t=0;t<e.length;t++)r=(r<<5)-r+e.charCodeAt(t)|0
|
|
3203
3197
|
return`${t+1}${String.fromCharCode(97+Math.abs(r)%26)}`}function r(e){const r=new Map
|
|
@@ -3295,25 +3289,25 @@ if(t){const e=Date.now()-t
|
|
|
3295
3289
|
try{this.metrics.observeHistogram("offline_duration_ms",e,{reconnection_type:"manual"}),this.logger.info(`System was offline for ${Math.round(e/1e3)} seconds before manual reconnection`)}catch(e){this.logger.warn("Error observing histogram for offline duration on manual reconnection",{error:e instanceof Error?e.message:e+""})}}}}catch(e){this.logger.warn("Error calculating offline duration during manual mode change",{error:(0,s.getErrorMessage)(e)})}this.notifyOnlineStatus()}else!t&&e&&(this.logger.info("Manually setting connection mode to OFFLINE"),this.safeSetGauge("connection_status",0),this.safeSetGauge("last_connection_failure_timestamp",Date.now()),this.safeIncrementCounter("manual_disconnections",1),process.nextTick((()=>{exports.eventBus.emit(exports.EVENTS.OFFLINE,{timestamp:(new Date).toISOString()})})))}isOffline(){return this.isInOfflineMode()}async checkConnectivity(){return this.logger.debug("Explicit connectivity check requested"),this.healthCheckManager.requestHealthCheck()}getHealthCheckStats(){const e=this.healthCheckManager.getStats()
|
|
3296
3290
|
return{isOffline:this.isInOfflineMode(),consecutiveFailures:e.consecutiveFailures,currentBackoffMs:e.currentBackoffMs,lastCheckTime:e.lastCheckTime}}cleanup(){this.logger.debug("Cleaning up connection status manager resources"),this.healthCheckManager.stopHealthChecks(),exports.eventBus.removeAllListeners(exports.EVENTS.ONLINE),exports.eventBus.removeAllListeners(exports.EVENTS.OFFLINE)}}},5692(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.def=void 0
|
|
3297
3291
|
const r=t(6183),n=t(2965)
|
|
3298
|
-
exports.def={name:"read_files",description:'Read the contents of multiple files and documents with flexible line selection.\n\nLINE SELECTION (string format):\n- Single line: "lines": "5"\n- Multiple lines: "lines": "1,3,7,10"\n- Range: "lines": "5-15"\n- Entire file: omit "lines" parameter\n\nEXAMPLES:\n- Read first 10 lines: {"path": "file.txt", "lines": "1-10"}\n- Read specific lines: {"path": "file.txt", "lines": "1,5,25"}\n- Read line 42 only: {"path": "file.txt", "lines": "42"}\n- Read entire file: {"path": "file.txt"}\n\nSupports both filesystem files (using \'path\') and tracked documents (using \'documentId\'). More efficient than reading files one by one. Failed reads won\'t stop the entire operation.',schema:r.ReadFilesSchema,annotations:{title:"Read Files/Documents",readOnlyHint:!0},readOnly:!0,handler(e,t){return(0,n.handleReadFiles)(e,t.context,t.logger,t.metrics)}}},5715(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleCompleteRequest=async function(e,t,c,l,d,u
|
|
3299
|
-
try{const{requestId:
|
|
3300
|
-
if(!
|
|
3301
|
-
if(!
|
|
3302
|
-
|
|
3303
|
-
const
|
|
3304
|
-
let
|
|
3305
|
-
try{const e=await
|
|
3306
|
-
|
|
3307
|
-
return
|
|
3308
|
-
return
|
|
3309
|
-
try{await
|
|
3310
|
-
return
|
|
3311
|
-
try{
|
|
3312
|
-
return
|
|
3313
|
-
return
|
|
3314
|
-
r instanceof
|
|
3315
|
-
try{await(0,
|
|
3316
|
-
const r=t(9860),n=t(
|
|
3292
|
+
exports.def={name:"read_files",description:'Read the contents of multiple files and documents with flexible line selection.\n\nLINE SELECTION (string format):\n- Single line: "lines": "5"\n- Multiple lines: "lines": "1,3,7,10"\n- Range: "lines": "5-15"\n- Entire file: omit "lines" parameter\n\nEXAMPLES:\n- Read first 10 lines: {"path": "file.txt", "lines": "1-10"}\n- Read specific lines: {"path": "file.txt", "lines": "1,5,25"}\n- Read line 42 only: {"path": "file.txt", "lines": "42"}\n- Read entire file: {"path": "file.txt"}\n\nSupports both filesystem files (using \'path\') and tracked documents (using \'documentId\'). More efficient than reading files one by one. Failed reads won\'t stop the entire operation.',schema:r.ReadFilesSchema,annotations:{title:"Read Files/Documents",readOnlyHint:!0},readOnly:!0,handler(e,t){return(0,n.handleReadFiles)(e,t.context,t.logger,t.metrics)}}},5715(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleCompleteRequest=async function(e,t,a,c,l,d,u){const h=c.child({tool:"complete_request"}),g=l.startTimer("tool_execution_time")
|
|
3293
|
+
try{const{requestId:n,summary:o}=e
|
|
3294
|
+
if(!n)throw(0,r.createValidationError)("Request ID is required")
|
|
3295
|
+
if(!o)throw(0,r.createValidationError)("Summary is required")
|
|
3296
|
+
h.info("Starting request completion",{requestId:n})
|
|
3297
|
+
const c=u?.sessionId
|
|
3298
|
+
let l
|
|
3299
|
+
try{const e=await a.proxyPost(`/api/projects/${t.projectId}/requests/${n}/validate-completion`,{sessionId:c})
|
|
3300
|
+
l=e?.data||e}catch(e){const t=(0,s.getErrorMessage)(e)
|
|
3301
|
+
return h.error("Server validation failed",{requestId:n,error:t}),g({success:!1,error:"validation_request_failed"}),{content:[{type:"text",text:"Failed to validate completion: "+t}],isError:!0}}if(!l.canComplete){let e=`Cannot complete request ${n}: ${l.reason}\n`
|
|
3302
|
+
return l.blockedByTasks&&l.blockedByTasks.length>0&&(e+="\n**Tasks that must be completed or canceled first:**\n",l.blockedByTasks.forEach(((t,r)=>{e+=`${r+1}. **${t.taskId}** - ${t.title} (Status: ${t.status})\n`}))),l.lifoViolation&&(e+="\n**Requests that must be re-completed first (LIFO order):**\n",l.lifoViolation.blockingRequests.forEach(((t,r)=>{e+=`${r+1}. **${t.requestId}** - ${t.title} (Status: ${t.status})\n`}))),g({success:!1,reason:"server_blocked"}),{content:[{type:"text",text:e}],isError:!0}}const d=a.getRequestClient(),p="auto-test-then-merge"===l.completionMode,f=p?"ready_for_review":"ready_for_merge"
|
|
3303
|
+
try{await d.updateRequest(n,{status:f,completionSummary:o})}catch(e){const t=(0,s.getErrorMessage)(e)
|
|
3304
|
+
return g({success:!1,error:"status_transition_failed"}),{content:[{type:"text",text:"Failed to transition request: "+t}],isError:!0}}let m
|
|
3305
|
+
try{m=await d.getRequest(n)}catch(e){const t=(0,s.getErrorMessage)(e)
|
|
3306
|
+
return g({success:!1,error:"fetch_request_failed"}),{content:[{type:"text",text:"Failed to fetch request criteria: "+t}],isError:!0}}const y=m?.acceptanceCriteria||[]
|
|
3307
|
+
return g({success:!0}),p?{content:[{type:"text",text:`Request ${n} moved to ready_for_review. Testing is active \u2014 a notification has been created for the user to choose testing mode. Do NOT call merge or any other tool. Your work is done. Stop here and wait.`}]}:0===y.length?{content:[{type:"text",text:`Request ${n} is ready. No acceptance criteria defined \u2014 call merge directly.`}]}:{content:[{type:"text",text:`Request ${n} completion started (${f}).\n\n## Next Step: Verify & Merge\n\n${(0,i.formatVerifyInstructions)(y)}\n\nUse the merge operation with your verification evidence to merge to main.`}]}}catch(r){let s="An unexpected error occurred",i=""
|
|
3308
|
+
r instanceof n.ZodError?(s="Validation error",i=r.errors.map((e=>`${e.path.join(".")}: ${e.message}`)).join(", ")):r instanceof Error?(s=r.message,i=r.stack||""):i=r+"",h.error("Complete request failed",{error:s,details:i})
|
|
3309
|
+
try{await(0,o.createFailureToolRecord)("complete-request",r,{error:s,details:i,requestId:e?.requestId},a.getToolRecordClient(),h,l,{requestId:e?.requestId,projectId:t.projectId,note:"Failed to complete request"})}catch{}return l.startTimer("tool_execution_time")({success:!1,error:r instanceof Error?r.name:"unknown"}),{content:[{type:"text",text:"Error: "+s}],isError:!0}}}
|
|
3310
|
+
const r=t(9860),n=t(1569),o=t(8616),s=t(8824),i=t(5454)},5767(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.def=void 0
|
|
3317
3311
|
const r=t(6183),n=t(6285)
|
|
3318
3312
|
exports.def={name:"specialist_ops",description:"Manage your pool of up to 10 specialists. Each has a specialization describing their domain. Reuse specialists via follow-up before spawning new ones.\n\nOperations:\n\u2022 delegate - Spawn a new specialist (include specialization). Abort an idle specialist first if pool is full.\n\u2022 follow-up - Send follow-up instructions to an existing specialist (can update specialization)\n\u2022 check-status - Check if a specialist is busy or idle\n\u2022 list - List specialist sessions with specializations\n\u2022 abort - Cancel a stuck specialist",schema:r.SpecialistOpsSchema,annotations:{title:"Specialist Operations",readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1},handler(e,t){return(0,n.handleSpecialistOps)(e,t.context,t.logger,t.metrics,t.apiClient??void 0,t.cliOrigin)}}},5802(module){module.exports=require("@modelcontextprotocol/sdk/server/stdio.js")},5806(e,exports,t){function r(){const e=n.z.object({requestId:n.z.string(),summary:n.z.string(),acceptanceEvidence:n.z.array(n.z.object({evidence:n.z.string()}))}),t=n.z.object({testRecords:n.z.array(n.z.string()),coverage:n.z.object({criteriaTestedCount:n.z.number(),totalTestCases:n.z.number()}),criterionCoverage:n.z.array(n.z.object({coverage:n.z.enum(["none","partial","full"]),testRecords:n.z.array(n.z.string())}))})
|
|
3319
3313
|
return(0,o.areTestsRequiredForCompletion)()?e.extend({testVerification:t}):e}Object.defineProperty(exports,"__esModule",{value:!0}),exports.DynamicCompleteRequestSchema=void 0,exports.getDynamicCompleteRequestSchema=r
|
|
@@ -3332,8 +3326,8 @@ if(null!=e)for(var s=r(e),i=0;i<s.length;i++)"default"!==s[i]&&n(t,e,s[i])
|
|
|
3332
3326
|
return o(t,e),t}),i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
3333
3327
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleDeleteFiles=async function(e,t,r,n,o,s){const i=n.child({tool:"delete_files"}),m=Date.now()
|
|
3334
3328
|
let y,w,k=l.FileOperationPhase.VALIDATION
|
|
3335
|
-
const
|
|
3336
|
-
try{const n=r.getTaskClient(),u=r.getToolRecordClient(),
|
|
3329
|
+
const b={toolName:"delete-files",operationName:"delete",fileOperationPhase:l.FileOperationPhase.FILE_WRITE,recordType:"delete-files",metricsPrefix:"delete_files",successMessage:"Successfully deleted files",failureMessage:"Failed to delete files"}
|
|
3330
|
+
try{const n=r.getTaskClient(),u=r.getToolRecordClient(),I=r.getRequestClient(),v=l.validateArgs(e,c.DeleteFilesSchema),{taskId:C,paths:_,operations:E,comment:q}=v
|
|
3337
3331
|
let S=[]
|
|
3338
3332
|
if(_)S=_.map((e=>({type:"file",target:e})))
|
|
3339
3333
|
else{if(!E)throw Error("Either paths or operations must be specified")
|
|
@@ -3341,31 +3335,31 @@ S=E.map((e=>{if(e.path)return{type:"file",target:e.path}
|
|
|
3341
3335
|
if(e.documentId)return{type:"document",target:e.documentId}
|
|
3342
3336
|
throw Error("Invalid operation: neither path nor documentId specified")}))}if(0===S.length)throw Error("At least one file or document must be specified for deletion")
|
|
3343
3337
|
const T=S.filter((e=>"file"===e.type)),P=S.filter((e=>"document"===e.type)),M=S.length
|
|
3344
|
-
i.info("Starting mixed file and document deletion operation",{taskId:C,totalOperations:S.length,fileOperations:T.length,documentOperations:P.length,comment:q}),l.validateTaskIdFormat(C,i,o,
|
|
3345
|
-
const
|
|
3346
|
-
i.info("Initial branch context",{initialBranch:
|
|
3347
|
-
const
|
|
3338
|
+
i.info("Starting mixed file and document deletion operation",{taskId:C,totalOperations:S.length,fileOperations:T.length,documentOperations:P.length,comment:q}),l.validateTaskIdFormat(C,i,o,b.metricsPrefix)
|
|
3339
|
+
const j=t.getCurrentBranchContext?await t.getCurrentBranchContext():{branch:null,requestId:null,isMain:!0}
|
|
3340
|
+
i.info("Initial branch context",{initialBranch:j.branch,initialRequestId:j.requestId,isMain:j.isMain})
|
|
3341
|
+
const R=[]
|
|
3348
3342
|
for(const e of T){const{normalizedPath:r,fullPath:n}=l.validateAndNormalizePath(e.target,t)
|
|
3349
|
-
|
|
3350
|
-
const x=
|
|
3343
|
+
R.push({normalized:r,full:n})}k=l.FileOperationPhase.TASK_VALIDATION,o.incrementCounter("delete_files_phase",1,{phase:k})
|
|
3344
|
+
const x=R.length>0?R[0].normalized:"document_operations",O=await l.validateTaskId(C,x,n,i,o,b.metricsPrefix),A=O?.requestId,D=await l.validateWorkItemStates(C,x,n,I,t,i,o,b.metricsPrefix),$=await l.autoPromoteTaskStatus(C,O.status,A,D.request?.status,x,n,I,i,o,b.metricsPrefix)
|
|
3351
3345
|
$.taskPromoted&&i.info(`Auto-promoted task ${C} (${O.title||"Untitled"}) to in_progress for mixed operations`,{taskId:C,taskTitle:O.title,previousStatus:O.status,newStatus:$.newTaskStatus,totalOperations:S.length,fileOperations:T.length,documentOperations:P.length}),$.requestPromoted&&i.info(`Auto-promoted request ${A} to in_progress for file operations`,{requestId:A,previousStatus:D.request?.status,newStatus:$.newRequestStatus,triggeringTaskId:C})
|
|
3352
|
-
const F=await l.ensureCorrectWorkspaceContext({taskPromoted:$.taskPromoted,requestId:A,context:t,operation:"delete-files",logger:i,metrics:o,metricsPrefix:
|
|
3346
|
+
const F=await l.ensureCorrectWorkspaceContext({taskPromoted:$.taskPromoted,requestId:A,context:t,operation:"delete-files",logger:i,metrics:o,metricsPrefix:b.metricsPrefix})
|
|
3353
3347
|
if(!F.success){if(F.isLockConflict)return{content:[{type:"text",text:"\u274c "+F.error}],isError:!0}
|
|
3354
3348
|
throw Error(F.error)}let N={hadUserMods:!1,userModsCommitHash:void 0}
|
|
3355
3349
|
if(t.git)try{i.debug("[DELETE-FILES] Checking for user changes before mixed delete operations")
|
|
3356
3350
|
const e=await(0,h.commitUserChangesBeforeToolOperation)(t.git,"delete-files",{requestId:A,taskId:C,workspaceManager:t.workspaceManager},i,o)
|
|
3357
3351
|
e.userChangesCommitted&&(i.debug("[DELETE-FILES] User changes committed before mixed delete operations",{commitHash:e.commitHash?.substring(0,8),filesCommitted:e.filesCommitted}),i.info("User changes committed before mixed delete-files operation",{taskId:C,totalOperations:S.length,fileOperations:T.length,documentOperations:P.length,userCommitHash:e.commitHash?.substring(0,8),userFilesCommitted:e.filesCommitted}),N={hadUserMods:!0,userModsCommitHash:e.commitHash})}catch(e){i.debug("[DELETE-FILES] Pre-tool commit failed, continuing with mixed delete operations",{error:e instanceof Error?e.message:e+""}),i.warn("Pre-tool user changes commit failed, continuing with mixed delete operation",{taskId:C,totalOperations:S.length,fileOperations:T.length,documentOperations:P.length,error:e instanceof Error?e.message:e+""})}i.debug("[DELETE-FILES] Proceeding with mixed delete operations",{totalOperations:S.length,fileDeletes:T.length,documentDeletes:P.length}),k=l.FileOperationPhase.RECORD_CREATION,o.incrementCounter("delete_files_phase",1,{phase:k})
|
|
3358
|
-
const{toolRecordId:L,localToolRecordId:z}=await l.createFileOperationRecords(C,A,t.projectId,
|
|
3359
|
-
y=L,w=L,k=
|
|
3352
|
+
const{toolRecordId:L,localToolRecordId:z}=await l.createFileOperationRecords(C,A,t.projectId,b.recordType,x,{totalOperations:S.length,fileOperations:T.length,documentOperations:P.length,filePaths:R.map((e=>e.normalized)),documentIds:P.map((e=>e.target)),userComment:q,hadUserMods:N.hadUserMods,userModsCommitHash:N.userModsCommitHash},n,u,i,o,b.metricsPrefix,s)
|
|
3353
|
+
y=L,w=L,k=b.fileOperationPhase,o.incrementCounter("delete_files_phase",1,{phase:k})
|
|
3360
3354
|
const B=[]
|
|
3361
3355
|
let H=0
|
|
3362
3356
|
P.length>0&&r.setProjectId(t.projectId)
|
|
3363
|
-
for(let e=0;e<
|
|
3357
|
+
for(let e=0;e<R.length;e++){const t=R[e],r={type:"file",path:t.normalized,success:!1,replacements:[],successfulReplacements:0,failedReplacements:0}
|
|
3364
3358
|
try{try{await a.default.access(t.full)}catch(e){throw Error("File not found: "+t.normalized)}if((await a.default.stat(t.full)).isDirectory())throw Error("Cannot 'delete' a directory: "+t.normalized)
|
|
3365
3359
|
await a.default.unlink(t.full),r.success=!0,H++,i.info("Successfully deleted file",{path:t.normalized})}catch(e){r.error=(0,f.getErrorMessage)(e),i.warn("Failed to delete file "+t.normalized,{error:r.error})}B.push(r)}const W=P.length>0?r.getDocumentClient():null
|
|
3366
3360
|
for(const e of P){const t=e.target,n={type:"document",documentId:t,success:!1,replacements:[],successfulReplacements:0,failedReplacements:0}
|
|
3367
3361
|
try{let e
|
|
3368
|
-
try{if(e=await W.getDocument(t),n.filename=e.filename,i.info("Document found for archival",{documentId:e.id,filename:e.filename,type:e.type,requestId:e.requestId}),e.requestId)try{await(0,g.validateRequestStatusForDocumentOperation)(e.requestId,
|
|
3362
|
+
try{if(e=await W.getDocument(t),n.filename=e.filename,i.info("Document found for archival",{documentId:e.id,filename:e.filename,type:e.type,requestId:e.requestId}),e.requestId)try{await(0,g.validateRequestStatusForDocumentOperation)(e.requestId,I,i,o,"delete-document")}catch(e){if(e instanceof d.ValidationError)throw Error(e.message)
|
|
3369
3363
|
throw e}try{await(0,p.ensureDocumentNotLocked)(t,r,i,o,"delete-document-archive")}catch(e){if(e instanceof d.ValidationError)throw Error(e.message)
|
|
3370
3364
|
throw e}}catch(e){throw Error(`Document not found or validation failed: ${t}. ${(0,f.getErrorMessage)(e)}`)}const s=await W.archiveDocument(t)
|
|
3371
3365
|
n.success=!0,n.filename=s.filename,H++,i.info("Document archived successfully",{documentId:s.id,filename:s.filename,archivedAt:s.archived_at})}catch(e){n.error=(0,f.getErrorMessage)(e),i.warn("Failed to delete document "+t,{error:n.error})}B.push(n)}const U=Date.now()-m
|
|
@@ -3374,20 +3368,20 @@ let G=null
|
|
|
3374
3368
|
if(H>0){k=l.FileOperationPhase.GIT_COMMIT,o.incrementCounter("delete_files_phase",1,{phase:k})
|
|
3375
3369
|
const e=B.filter((e=>e.success)),r=e.filter((e=>"file"===e.type)).length,n=e.filter((e=>"document"===e.type)).length
|
|
3376
3370
|
let s
|
|
3377
|
-
s=r>0&&n>0?`Delete ${r} files and ${n} documents - ${q}`:r>0?1===r?"Delete file - "+q:`Delete ${r} files - ${q}`:1===n?"Delete document - "+q:`Delete ${n} documents - ${q}`,G=await l.commitToGit(C,x,L,z,s,t,i,o,
|
|
3371
|
+
s=r>0&&n>0?`Delete ${r} files and ${n} documents - ${q}`:r>0?1===r?"Delete file - "+q:`Delete ${r} files - ${q}`:1===n?"Delete document - "+q:`Delete ${n} documents - ${q}`,G=await l.commitToGit(C,x,L,z,s,t,i,o,b.metricsPrefix)}k=l.FileOperationPhase.RECORD_UPDATE_SUCCESS,o.incrementCounter("delete_files_phase",1,{phase:k})
|
|
3378
3372
|
const V=B.filter((e=>e.success)),J=B.filter((e=>!e.success))
|
|
3379
|
-
await l.updateFileOperationRecords(C,y,w,x,
|
|
3380
|
-
const
|
|
3381
|
-
let
|
|
3373
|
+
await l.updateFileOperationRecords(C,y,w,x,b.recordType,H===M?`Successfully deleted all ${M} operations`:`Deleted ${H}/${M} operations successfully`,{status:H===M?"completed":"partial_success",commitHash:G?.commitHash,previousCommitHash:G?.previousCommitHash,totalOperations:M,fileOperations:T.length,documentOperations:P.length,successCount:H,failureCount:M-H,successfulOperations:V.map((e=>({type:e.type,path:e.path,documentId:e.documentId,filename:e.filename}))),failedOperations:J.map((e=>({type:e.type,path:e.path,documentId:e.documentId,filename:e.filename,error:e.error}))),userComment:q,hadUserMods:N.hadUserMods,userModsCommitHash:N.userModsCommitHash},H===M?`Successfully deleted all ${M} operations`:`Deleted ${H}/${M} operations successfully`,n,u,i,o,b.metricsPrefix)
|
|
3374
|
+
const K=t.getCurrentBranchContext?await t.getCurrentBranchContext():{branch:null,requestId:null,isMain:!0}
|
|
3375
|
+
let Y=""
|
|
3382
3376
|
if(H===M){const e=V.filter((e=>"file"===e.type)).length,t=V.filter((e=>"document"===e.type)).length
|
|
3383
|
-
|
|
3377
|
+
Y=e>0&&t>0?`Successfully deleted ${e} files and ${t} documents`:e>0?`Successfully deleted all ${e} ${1===e?"file":"files"}`:`Successfully archived all ${t} ${1===t?"document":"documents"}`}else Y=H>0?`Successfully deleted ${H}/${M} operations.\n\nFailed operations:\n`+B.filter((e=>!e.success)).map((e=>{const t="file"===e.type?e.path:`${e.filename||e.documentId} (${e.documentId})`
|
|
3384
3378
|
return`\u2022 ${e.type}: ${t}: ${e.error}`})).join("\n"):"All delete operations failed:\n"+B.map((e=>{const t="file"===e.type?e.path:`${e.filename||e.documentId} (${e.documentId})`
|
|
3385
3379
|
return`\u2022 ${e.type}: ${t}: ${e.error}`})).join("\n")
|
|
3386
|
-
return G?.commitHash&&(
|
|
3380
|
+
return G?.commitHash&&(Y+="\nCommit: "+G.commitHash.substring(0,8)),K.requestId&&(Y+="\nBranch: "+K.requestId),F.lockAcquired&&F.lockedRequestId&&(Y+="\n\u{1f512} **Locked request:** "+F.lockedRequestId),{content:[{type:"text",text:Y}],isError:0===H}}catch(n){if(e.taskId&&r)try{const o=r.getToolRecordClient(),s=n instanceof d.NotFoundError||n instanceof d.ValidationError||n instanceof u.ZodError
|
|
3387
3381
|
await o.createToolRecord({...s?{}:{taskId:e.taskId},projectId:t.projectId,type:"delete-files",metadata:{status:"failed",timestamp:(new Date).toISOString(),totalOperations:e.operations?.length||e.paths?.length||0,fileOperations:e.paths?.length||e.operations?.filter((e=>e.path))?.length||0,documentOperations:e.operations?.filter((e=>e.documentId))?.length||0,paths:e.paths||e.operations?.filter((e=>e.path))?.map((e=>e.path))||[],documentIds:e.operations?.filter((e=>e.documentId))?.map((e=>e.documentId))||[],userComment:e.comment,error:(0,f.getErrorMessage)(n),errorDetails:n instanceof Error?n.stack:n+"",phase:k,attemptedTaskId:e.taskId,taskIdValidationFailed:s},note:"Failed to delete files - "+(0,f.getErrorMessage)(n)})}catch(t){i.error("Failed to create failure record for delete-files operation",{error:t instanceof Error?t.message:t+"",taskId:e.taskId,totalOperations:e.operations?.length||e.paths?.length||0,fileOperations:e.paths?.length||e.operations?.filter((e=>e.path))?.length||0,documentOperations:e.operations?.filter((e=>e.documentId))?.length||0})}const s=Date.now()-m
|
|
3388
3382
|
if(o.recordValue("delete_files_time",s),o.incrementCounter("delete_files_errors",1),i.error("Error in delete-files operation:",{error:(0,f.getErrorMessage)(n),time:s}),(y||w)&&e.taskId){k=l.FileOperationPhase.RECORD_UPDATE_FAILURE
|
|
3389
3383
|
try{const t=r.getTaskClient(),s=r.getToolRecordClient()
|
|
3390
|
-
await l.updateFileOperationRecords(e.taskId,y,w,e.paths?.[0]||e.operations?.[0]?.path||e.operations?.[0]?.documentId||"unknown",
|
|
3384
|
+
await l.updateFileOperationRecords(e.taskId,y,w,e.paths?.[0]||e.operations?.[0]?.path||e.operations?.[0]?.documentId||"unknown",b.recordType,"Failed to delete operations",{status:"failed",error:(0,f.getErrorMessage)(n),totalOperations:e.operations?.length||e.paths?.length||0,fileOperations:e.paths?.length||e.operations?.filter((e=>e.path))?.length||0,documentOperations:e.operations?.filter((e=>e.documentId))?.length||0,paths:e.paths||e.operations?.filter((e=>e.path))?.map((e=>e.path))||[],documentIds:e.operations?.filter((e=>e.documentId))?.map((e=>e.documentId))||[],userComment:e.comment},"Failed to delete operations",t,s,i,o,b.metricsPrefix)}catch(t){i.error("Failed to update record with failure status",{taskId:e.taskId,recordId:y,error:t instanceof Error?t.message:t+""})}}return l.handleFileOperationError(n,k,i,o,e,b)}}
|
|
3391
3385
|
const a=i(t(1943)),c=t(6183),l=s(t(5967)),d=t(9860),u=t(1569),h=t(7478),g=t(5003),p=t(9949),f=t(8824)},5997(e,exports,t){var r,n=this&&this.__createBinding||(Object.create?function(e,t,r,n){void 0===n&&(n=r)
|
|
3392
3386
|
var o=Object.getOwnPropertyDescriptor(t,r)
|
|
3393
3387
|
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]}),o=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),s=this&&this.__importStar||(r=function(e){return r=Object.getOwnPropertyNames||function(e){var t=[]
|
|
@@ -3471,15 +3465,13 @@ return t},r(e)},function(e){if(e&&e.__esModule)return e
|
|
|
3471
3465
|
var t={}
|
|
3472
3466
|
if(null!=e)for(var s=r(e),i=0;i<s.length;i++)"default"!==s[i]&&n(t,e,s[i])
|
|
3473
3467
|
return o(t,e),t})
|
|
3474
|
-
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleSpecialistOps=async function(e,r,n,o,s,
|
|
3468
|
+
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleSpecialistOps=async function(e,r,n,o,s,p){const f=n.child({tool:"specialist_ops"}),m=o.startTimer("tool_execution_time")
|
|
3475
3469
|
try{if(!e?.operation&&e&&(e.prompt&&!e.sessionId?e.operation="delegate":e.prompt&&e.sessionId?e.operation="follow-up":e.sessionId&&(e.operation="check-status")),e?.followUp&&"string"==typeof e.followUp)try{e.followUp=JSON.parse(e.followUp)}catch{}if(e?.delegate&&"string"==typeof e.delegate)try{e.delegate=JSON.parse(e.delegate)}catch{}if("string"==typeof e?.delegate){const t=e.delegate
|
|
3476
3470
|
e.delegate={prompt:e.prompt||t,description:e.description||t.slice(0,60),specialization:e.specialization||"general",requestId:e.requestId},e.operation=e.operation||"delegate",delete e.prompt,delete e.description,delete e.specialization,delete e.requestId}"follow-up"===e?.operation&&e?.prompt&&!e?.followUp&&(e.followUp={prompt:e.prompt,specialization:e.specialization},delete e.prompt,e.specialization&&delete e.specialization),"delegate"===e?.operation&&e?.prompt&&!e?.delegate&&(e.delegate={prompt:e.prompt,description:e.description||e.prompt.slice(0,60),specialization:e.specialization||"general",requestId:e.requestId},delete e.prompt,delete e.description,delete e.specialization,delete e.requestId)
|
|
3477
|
-
const n=c.validateArgs(e,a.SpecialistOpsSchema),{operation:
|
|
3478
|
-
let
|
|
3479
|
-
switch(
|
|
3480
|
-
|
|
3481
|
-
if(!i){const e=await(0,h.getServerUrl)(r,m)
|
|
3482
|
-
if(e)try{i=(0,g.getCachedSession)()?.sessionId||await(0,h.discoverParentSessionId)(e,m)}catch{}}if(i&&s){const e=await async function(e,t,r,n,o){n.info("enforcePoolLimit called",{parentSessionId:e,maxPoolSize:t})
|
|
3471
|
+
const n=c.validateArgs(e,a.SpecialistOpsSchema),{operation:y,sessionId:w}=n
|
|
3472
|
+
let k
|
|
3473
|
+
switch(f.info("Processing specialist_ops",{operation:y,sessionId:w}),y){case"delegate":{const e=n.delegate,o=10,i=p?.sessionId||g.sessionIdentity.getIdentity()?.sessionId
|
|
3474
|
+
if(i&&s){const e=await async function(e,t,r,n,o){n.info("enforcePoolLimit called",{parentSessionId:e,maxPoolSize:t})
|
|
3483
3475
|
const s=await(0,h.getServerUrl)(r,n)
|
|
3484
3476
|
if(s)try{const r=await fetch(s.replace(/\/$/,"")+"/session")
|
|
3485
3477
|
if(!r.ok)return
|
|
@@ -3492,34 +3484,33 @@ return"specialist"===t?.agentType&&"archived"!==t?.status}))
|
|
|
3492
3484
|
if(n.info("Pool check: specialist count",{specialistCount:h.length,maxPoolSize:t}),h.length<t)return
|
|
3493
3485
|
const g=h.map((e=>{const t=l[e.id],r=u[e.id]?.type||"idle",n=t?.specialization||"(none)"
|
|
3494
3486
|
return` \u2022 ${e.id} \u2014 ${n} [${r}]`})).join("\n")
|
|
3495
|
-
return{content:[{type:"text",text:`\u274c Specialist pool is full (${h.length}/${t}).\nAbort an idle specialist first with \`specialist_ops abort\`, then delegate again.\n\nCurrent pool:\n`+g}],isError:!0}}catch(e){return void n.warn("Pool limit check failed, allowing spawn",{error:(0,l.getErrorMessage)(e)})}}(i,o,r,
|
|
3496
|
-
if(e){
|
|
3487
|
+
return{content:[{type:"text",text:`\u274c Specialist pool is full (${h.length}/${t}).\nAbort an idle specialist first with \`specialist_ops abort\`, then delegate again.\n\nCurrent pool:\n`+g}],isError:!0}}catch(e){return void n.warn("Pool limit check failed, allowing spawn",{error:(0,l.getErrorMessage)(e)})}}(i,o,r,f,s)
|
|
3488
|
+
if(e){k=e
|
|
3497
3489
|
break}}let a=e.description
|
|
3498
|
-
const c=await Promise.resolve().then(t.t.bind(t,9896,23)),
|
|
3499
|
-
if(i)try{const e=await(0,h.getServerUrl)(r,
|
|
3500
|
-
if(
|
|
3501
|
-
if(
|
|
3502
|
-
|
|
3490
|
+
const c=await Promise.resolve().then(t.t.bind(t,9896,23)),m=e=>c.appendFileSync("/tmp/specialist-name-debug.log",`${(new Date).toISOString()} ${e}\n`)
|
|
3491
|
+
if(i)try{const e=await(0,h.getServerUrl)(r,f)
|
|
3492
|
+
if(m(`serverUrl=${e}, parentId=${i}`),e){const t=await fetch(e.replace(/\/$/,"")+"/session")
|
|
3493
|
+
if(m("session fetch status="+t.status),t.ok){const e=(await t.json()).filter((e=>(e.parentId||e.parentID)===i)).map((e=>e.title||""))
|
|
3494
|
+
m(`siblings=${e.length}: ${e.join(", ")}`)
|
|
3503
3495
|
const r=(0,d.pickSpecialistName)(e)
|
|
3504
|
-
a=r,
|
|
3505
|
-
const
|
|
3506
|
-
|
|
3507
|
-
break}case"follow-up":{const e=await(0,h.getServerUrl)(r,
|
|
3496
|
+
a=r,m("picked name: "+r)}}else m("no serverUrl")}catch(e){m("error: "+(e instanceof Error?e.message:e+""))}else m("no parentId")
|
|
3497
|
+
const y=e.requestId,w=y?`Working on request ${y}.\n\n${e.prompt}`:e.prompt
|
|
3498
|
+
k=await(0,u.handleSpawn)({agent:"specialist",prompt:w,title:a,specialization:e.specialization},r,f,s,p)
|
|
3499
|
+
break}case"follow-up":{const e=await(0,h.getServerUrl)(r,f)
|
|
3508
3500
|
if(e)try{const t=await fetch(e.replace(/\/$/,"")+"/session/status")
|
|
3509
|
-
if(t.ok){const e=await t.json(),r=e[
|
|
3510
|
-
if(r&&"idle"!==r&&"prompting"!==r){
|
|
3511
|
-
break}}}catch{}
|
|
3501
|
+
if(t.ok){const e=await t.json(),r=e[w]?.type
|
|
3502
|
+
if(r&&"idle"!==r&&"prompting"!==r){k={content:[{type:"text",text:`\u274c Specialist ${w} is currently busy (status: ${r}).\nUse \`delegate\` to spawn a new specialist instead.`}],isError:!0}
|
|
3503
|
+
break}}}catch{}k=await(0,u.handleContinue)(w,n.followUp.prompt,r,f,s,"specialist",p)
|
|
3512
3504
|
const t=n.followUp.specialization
|
|
3513
3505
|
if(t&&s)try{const e=s.getCLISessionClient()
|
|
3514
|
-
e&&(await e.createOrUpdateSession({externalSessionId:
|
|
3506
|
+
e&&(await e.createOrUpdateSession({externalSessionId:w,specialization:t}),k.content[0].text+="\nSpecialization updated to: "+t)}catch{}break}case"check-status":k=await(0,u.handleCheckStatus)(w,r,f,s)
|
|
3515
3507
|
break
|
|
3516
|
-
case"abort":if(
|
|
3517
|
-
e&&await e.createOrUpdateSession({externalSessionId:
|
|
3518
|
-
case"list":{
|
|
3519
|
-
|
|
3520
|
-
|
|
3521
|
-
|
|
3522
|
-
const i=t(9860),a=t(6183),c=s(t(5967)),l=t(8824),d=t(9089),u=t(1725),h=t(7617),g=t(715),p=t(6688)},6315(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.def=void 0
|
|
3508
|
+
case"abort":if(k=await(0,u.handleAbort)(w,r,f),!k.isError&&s)try{const e=s.getCLISessionClient()
|
|
3509
|
+
e&&await e.createOrUpdateSession({externalSessionId:w,status:"archived"})}catch{}break
|
|
3510
|
+
case"list":{const e=p?.sessionId||g.sessionIdentity.getIdentity()?.sessionId
|
|
3511
|
+
k=await(0,u.handleListSessions)(r,f,s,{activeOnly:n.list?.activeOnly,requestId:n.list?.requestId,limit:n.list?.limit,agentType:"specialist",parentSessionId:e})
|
|
3512
|
+
break}default:throw new i.ValidationError("Unknown operation: "+y)}return m({success:!0}),o.incrementCounter(`specialist_ops_${y}_success`,1),k}catch(e){return f.error("Specialist ops failed",{error:e instanceof Error?e.stack:e+""}),m({success:!1}),o.incrementCounter("specialist_ops_errors",1),{content:[{type:"text",text:"Specialist operation failed: "+(0,l.getErrorMessage)(e)}],isError:!0}}}
|
|
3513
|
+
const i=t(9860),a=t(6183),c=s(t(5967)),l=t(8824),d=t(9089),u=t(1725),h=t(7617),g=t(6688)},6315(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.def=void 0
|
|
3523
3514
|
const r=t(6183),n=t(2982)
|
|
3524
3515
|
exports.def={name:"generate_request_journal",description:"Fetch comprehensive data about a request for writing a journal entry.\n\nReturns structured data including:\n\u2022 Request details (title, description, type, status, acceptance criteria)\n\u2022 All tasks with descriptions and status\n\u2022 File changes summary (files modified, operations performed)\n\u2022 Chronological operation history\n\nUse this data to write a narrative journal entry and save it as:\nJOURNAL-{requestId}.md using document-operations (create).",schema:r.GenerateRequestJournalSchema,annotations:{title:"Generate Request Journal",readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0},readOnly:!0,hidden(){return"journal"!==process.env.ALCHEMY_MODE},handler(e,t){return(0,n.handleGenerateRequestJournal)(e,t.context,t.apiClient,t.logger,t.metrics,t.mcpServer)}}},6416(e,exports,t){var r,n=this&&this.__createBinding||(Object.create?function(e,t,r,n){void 0===n&&(n=r)
|
|
3525
3516
|
var o=Object.getOwnPropertyDescriptor(t,r)
|
|
@@ -3596,7 +3587,7 @@ var t={}
|
|
|
3596
3587
|
if(null!=e)for(var r=n(e),i=0;i<r.length;i++)"default"!==r[i]&&o(t,e,r[i])
|
|
3597
3588
|
return s(t,e),t}),a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
3598
3589
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleInsertLines=async function(e,t,n,o,s,i,a,m){const y=i.child({tool:"insert_lines"}),w=Date.now()
|
|
3599
|
-
let k,I
|
|
3590
|
+
let k,b,I=d.FileOperationPhase.VALIDATION
|
|
3600
3591
|
const v={toolName:"insert-lines",operationName:"insert-lines",fileOperationPhase:d.FileOperationPhase.FILE_WRITE,recordType:"insert-lines",metricsPrefix:"insert_lines",successMessage:"Successfully inserted lines into files and documents",failureMessage:"Failed to insert lines into files and documents"}
|
|
3601
3592
|
try{const i=d.validateArgs(e,l.InsertLinesSchema),{taskId:C,operations:_,comment:E}=i
|
|
3602
3593
|
if(y.info("Inserting lines into files and documents",{taskId:C,operationCount:_.length,comment:E}),!_||0===_.length)throw new u.ValidationError("At least one operation is required")
|
|
@@ -3609,21 +3600,21 @@ if(S.length>0&&!t.documentFileManager)throw Error("Document file manager not ava
|
|
|
3609
3600
|
for(const e of S)P.push({type:"document",documentId:e.documentId,insertions:e.insertions})
|
|
3610
3601
|
if(P.length>0&&t.apiClient){const e=P.map((e=>e.documentId))
|
|
3611
3602
|
try{await(0,p.ensureDocumentsNotLocked)(e,t.apiClient,y,a,"insert-lines-documents")}catch(e){if(e instanceof u.ValidationError)return{content:[{type:"text",text:e.message}],isError:!0}
|
|
3612
|
-
throw e}}
|
|
3613
|
-
const M=T.length>0?T[0].path:"document-operation",
|
|
3603
|
+
throw e}}I=d.FileOperationPhase.TASK_VALIDATION,a.incrementCounter("insert_lines_phase",1,{phase:I})
|
|
3604
|
+
const M=T.length>0?T[0].path:"document-operation",j=await d.validateTaskId(C,M,n,y,a,v.metricsPrefix),R=j?.requestId
|
|
3614
3605
|
let x=null
|
|
3615
|
-
T.length>0&&
|
|
3606
|
+
T.length>0&&R&&(x=await d.validateWorkItemStates(C,T[0].path,n,s,t,y,a,v.metricsPrefix))
|
|
3616
3607
|
let O={taskPromoted:!1,requestPromoted:!1}
|
|
3617
|
-
T.length>0&&
|
|
3618
|
-
const A=await d.ensureCorrectWorkspaceContext({taskPromoted:O.taskPromoted,requestId:
|
|
3608
|
+
T.length>0&&R&&x&&(O=await d.autoPromoteTaskStatus(C,j.status,R,x.request?.status,T[0].path,n,s,y,a,v.metricsPrefix),O.taskPromoted&&y.info("Auto-promoted task to in_progress for insert-lines operation",{taskId:C,requestId:R,previousStatus:j.status,newStatus:O.newTaskStatus,triggeringOperation:"insert-lines"}))
|
|
3609
|
+
const A=await d.ensureCorrectWorkspaceContext({taskPromoted:O.taskPromoted,requestId:R,context:t,operation:"insert-lines",logger:y,metrics:a,metricsPrefix:v.metricsPrefix})
|
|
3619
3610
|
if(!A.success){if(A.isLockConflict)return{content:[{type:"text",text:"\u274c "+A.error}],isError:!0}
|
|
3620
3611
|
throw Error(A.error)}if(T.length>0){y.debug("Re-validating file paths with correct workspace context",{operationCount:T.length,workspaceBasePath:t.workspaceManager?.getCurrentContext().basePath})
|
|
3621
3612
|
for(let e=0;e<T.length;e++){const r=T[e],n=q[e],{normalizedPath:o,fullPath:s}=d.validateAndNormalizePath(n.path,t)
|
|
3622
|
-
T[e]={...r,path:o,fullPath:s}}}if(P.length>0&&
|
|
3623
|
-
throw e}
|
|
3624
|
-
const D=[...T.map((e=>({type:"file",path:e.path,insertions:e.insertions}))),...P.map((e=>({type:"document",documentId:e.documentId,insertions:e.insertions})))],{toolRecordId:$}=await d.createFileOperationRecords(C,
|
|
3625
|
-
if(k=$,I
|
|
3626
|
-
const e=await(0,g.commitUserChangesBeforeToolOperation)(t.git,"insert-lines",{requestId:
|
|
3613
|
+
T[e]={...r,path:o,fullPath:s}}}if(P.length>0&&R)try{await(0,h.validateRequestStatusForDocumentOperation)(R,s,y,a,"insert-lines-document")}catch(e){if(e instanceof u.ValidationError)return{content:[{type:"text",text:e.message}],isError:!0}
|
|
3614
|
+
throw e}I=d.FileOperationPhase.RECORD_CREATION,a.incrementCounter("insert_lines_phase",1,{phase:I})
|
|
3615
|
+
const D=[...T.map((e=>({type:"file",path:e.path,insertions:e.insertions}))),...P.map((e=>({type:"document",documentId:e.documentId,insertions:e.insertions})))],{toolRecordId:$}=await d.createFileOperationRecords(C,R,t.projectId,v.recordType,M,{operationCount:_.length,fileOperations:T.length,documentOperations:P.length,operations:D,userComment:E},n,o,y,a,v.metricsPrefix,m)
|
|
3616
|
+
if(k=$,b=$,I=v.fileOperationPhase,a.incrementCounter("insert_lines_phase",1,{phase:I}),T.length>0&&t.git)try{y.debug("[INSERT-LINES] Checking for user changes before insert operations")
|
|
3617
|
+
const e=await(0,g.commitUserChangesBeforeToolOperation)(t.git,"insert-lines",{requestId:R,taskId:C,workspaceManager:t.workspaceManager},y,a)
|
|
3627
3618
|
e.userChangesCommitted&&(y.debug("[INSERT-LINES] User changes committed before insert operations",{commitHash:e.commitHash?.substring(0,8),filesCommitted:e.filesCommitted}),y.info("User changes committed before insert-lines operation",{taskId:C,fileOperationsCount:T.length,userCommitHash:e.commitHash?.substring(0,8),userFilesCommitted:e.filesCommitted}))}catch(e){y.debug("[INSERT-LINES] Pre-tool commit failed, continuing with insertions",{error:e instanceof Error?e.message:e+""}),y.warn("Pre-tool user changes commit failed, continuing with insert operation",{taskId:C,fileOperationsCount:T.length,error:e instanceof Error?e.message:e+""})}y.debug("[INSERT-LINES] Proceeding with file operations",{fileCount:T.length})
|
|
3628
3619
|
const F=[]
|
|
3629
3620
|
let N=0,L=0,z=0
|
|
@@ -3635,46 +3626,46 @@ try{const o=await t.documentFileManager.getDocumentAsFile(e.documentId),s=t.docu
|
|
|
3635
3626
|
n.filename=s?.filename
|
|
3636
3627
|
const i=await c.default.readFile(o,"utf8"),{newContent:a,results:l}=await r(i,e.insertions)
|
|
3637
3628
|
n.insertions=l,n.successfulInsertions=l.filter((e=>e.success)).length,n.failedInsertions=l.filter((e=>!e.success)).length,n.totalLinesAdded=l.filter((e=>e.success)).reduce(((e,t)=>e+(t.linesAdded||0)),0),a!==i&&n.successfulInsertions>0?(await c.default.writeFile(o,a,"utf8"),t.documentFileManager.markForSync(e.documentId),n.success=!0,z++,y.info("Document updated successfully",{documentId:e.documentId,filename:n.filename,successfulInsertions:n.successfulInsertions,failedInsertions:n.failedInsertions,linesAdded:n.totalLinesAdded})):0===n.failedInsertions&&(n.success=!0),N+=n.failedInsertions,L+=n.totalLinesAdded}catch(t){n.error=(0,f.getErrorMessage)(t),n.failedInsertions=e.insertions.length,N+=n.failedInsertions,y.error("Document operation failed",{documentId:e.documentId,error:n.error})}F.push(n)}if(P.length>0)try{for(const e of P){const r=F.find((t=>t.documentId===e.documentId))
|
|
3638
|
-
r?.success&&await t.documentFileManager.syncDocument(e.documentId)}}catch(e){y.warn("Some documents may not have synced properly",{error:e})}const B=await d.handleMultiFileGitCommit(C,T,F,z,{operationType:"Insert lines",toolRecordId:
|
|
3639
|
-
try{await o.updateToolRecord(
|
|
3640
|
-
if(t.workspaceManager&&(
|
|
3641
|
-
if(
|
|
3629
|
+
r?.success&&await t.documentFileManager.syncDocument(e.documentId)}}catch(e){y.warn("Some documents may not have synced properly",{error:e})}const B=await d.handleMultiFileGitCommit(C,T,F,z,{operationType:"Insert lines",toolRecordId:b,successField:"successfulInsertions",logger:y,metrics:a,metricsPrefix:"insert_lines"},t),H=d.processMultiFileOperationResults(F,"successfulInsertions"),{successfulOperations:W,failedOperations:U,totalSuccessfulChanges:G,overallSuccess:V,successfulFiles:J,failedFiles:K}=H
|
|
3630
|
+
try{await o.updateToolRecord(b,{metadata:{path:T.length>0?T[0].path:"document:"+P[0]?.documentId,status:V?"completed":"failed",error:V?void 0:U+" operations failed",totalOperations:F.length,successfulFiles:J,failedFiles:K,operations:D,totalSuccessfulInsertions:G,totalFailedInsertions:N,totalLinesAdded:L,operationsWithChanges:z,processingTime:Date.now()-w,userComment:E,...T.length>0&&B.success&&B.commitHash&&{commitHash:B.commitHash,previousCommitHash:B.previousCommitHash||void 0}},note:V?`Line insertion completed: ${W}/${F.length} operations successful${T.length>0?" (committed to git)":""}`:`Line insertion partially failed: ${U}/${F.length} operations failed`})}catch(e){y.warn("Failed to update tool record",{recordError:e})}let Y="## Line Insertion Results\n\n"
|
|
3631
|
+
if(t.workspaceManager&&(Y+=`**Branch:** \`${t.workspaceManager.getCurrentContext().branchName}\`\n\n`),Y+="**Summary:**\n",Y+=`- **Files processed:** ${W+U}\n`,Y+=`- **Successful operations:** ${W}\n`,Y+=`- **Failed operations:** ${U}\n`,Y+=`- **Total insertions:** ${G} successful, ${N} failed\n`,Y+=`- **Total Lines Added:** ${L}\n`,Y+="\n",B.success&&B.commitHash&&(Y+="**Git Commit:**\n",Y+=`- **Commit Hash:** ${B.commitHash.substring(0,8)}\n`,Y+=`- **Files Committed:** ${B.filesCommitted.length}\n`,B.previousCommitHash&&(Y+=`- **Previous Commit:** ${B.previousCommitHash.substring(0,8)}\n`),Y+="\n"),A.lockAcquired&&A.lockedRequestId&&(Y+=`\u{1f512} **Locked request:** ${A.lockedRequestId}\n\n`),1===F.length){const e=F[0]
|
|
3632
|
+
if(Y+=`**Operation:** ${e.success?"\u2705 Success":"\u274c Failed"}\n`,"file"===e.type?Y+=`**File:** ${e.path}\n`:(Y+="**Document:** "+e.documentId,e.filename&&(Y+=` (${e.filename})`),Y+="\n"),e.error?Y+=`**Error:** ${e.error}\n`:(Y+=`**Insertions:** ${e.successfulInsertions} successful`,e.failedInsertions>0&&(Y+=`, ${e.failedInsertions} failed`),Y+="\n",Y+=`**Lines Added:** ${e.totalLinesAdded}\n`),e.insertions.some((e=>!e.success))){Y+="**Failed Insertion Details:**\n"
|
|
3642
3633
|
for(const t of e.insertions.filter((e=>!e.success))){const e="between"===t.type?`between lines ${t.afterLine} and ${t.beforeLine}`:`${t.type} line ${t.line}`
|
|
3643
|
-
|
|
3644
|
-
for(const e of F){if("file"===e.type?
|
|
3634
|
+
Y+=`- ${t.type} insertion ${e}: ${t.error}\n`}}}else{Y+="**Summary:**\n",Y+=`- **Total Operations:** ${F.length}\n`,Y+=`- **Successful:** ${W}\n`,Y+=`- **Failed:** ${U}\n`,Y+=`- **Total Insertions:** ${G} successful, ${N} failed\n`,Y+=`- **Total Lines Added:** ${L}\n\n`,Y+="**Detailed Results:**\n\n"
|
|
3635
|
+
for(const e of F){if("file"===e.type?Y+=`### File: ${e.path}\n`:(Y+="### Document: "+e.documentId,e.filename&&(Y+=` (${e.filename})`),Y+="\n"),Y+=`- **Status:** ${e.success?"\u2705 Success":"\u274c Failed"}\n`,e.error?Y+=`- **Error:** ${e.error}\n`:(Y+=`- **Insertions:** ${e.successfulInsertions} successful`,e.failedInsertions>0&&(Y+=`, ${e.failedInsertions} failed`),Y+="\n",Y+=`- **Lines Added:** ${e.totalLinesAdded}\n`),e.insertions.some((e=>!e.success))){Y+="- **Failed Insertion Details:**\n"
|
|
3645
3636
|
for(const t of e.insertions.filter((e=>!e.success))){const e="between"===t.type?`between lines ${t.afterLine} and ${t.beforeLine}`:`${t.type} line ${t.line}`
|
|
3646
|
-
|
|
3637
|
+
Y+=` - ${t.type} insertion ${e}: ${t.error}\n`}}Y+="\n"}}P.length>0&&(Y+="\u{1f4c4} **Document Changes:** Modified documents have been automatically synced back to the tracking system.\n\n")
|
|
3647
3638
|
const Q=Date.now()-w
|
|
3648
|
-
return y.info("Insert lines operation completed",{duration:Q,success:V,totalOperations:F.length,successfulOperations:W,failedOperations:U}),a.incrementCounter("insert_lines_total",1,{success:V}),{content:[{type:"text",text:
|
|
3649
|
-
if(y.error("Insert lines operation failed",{error:t instanceof Error?t.stack:t+"",duration:r,phase:
|
|
3639
|
+
return y.info("Insert lines operation completed",{duration:Q,success:V,totalOperations:F.length,successfulOperations:W,failedOperations:U}),a.incrementCounter("insert_lines_total",1,{success:V}),{content:[{type:"text",text:Y}],isError:!V}}catch(t){const r=Date.now()-w
|
|
3640
|
+
if(y.error("Insert lines operation failed",{error:t instanceof Error?t.stack:t+"",duration:r,phase:I}),b)try{await o.updateToolRecord(b,{metadata:{path:e?.operations?.[0]?.path||e?.operations?.[0]?.documentId,status:"failed",error:(0,f.getErrorMessage)(t),phase:I,duration:r,userComment:e?.comment},note:"Line insertion failed: "+(0,f.getErrorMessage)(t)})}catch(e){}return a.incrementCounter("insert_lines_errors",1,{phase:I}),{content:[{type:"text",text:"\u274c **Insert Lines Failed:** "+(0,f.getErrorMessage)(t)}],isError:!0}}}
|
|
3650
3641
|
const c=a(t(1943)),l=t(6183),d=i(t(5967)),u=t(9860),h=t(5003),g=t(7478),p=t(9949),f=t(8824),m=t(3255)},6539(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.ClientFactory=void 0
|
|
3651
3642
|
const r=t(1253),n=t(5681),o=t(6595),s=t(3895),i=t(6848),a=t(6153),c=t(4710),l=t(6975),d=t(1887),u=t(1666),h=t(8824),g=t(9884),p=t(2968),f=t(922)
|
|
3652
3643
|
exports.ClientFactory=class{static async createClient(e,m,y,w={}){(m=m.child({component:"client-factory"})).info("Creating API client with components")
|
|
3653
3644
|
const k=w.tokenManager||new r.TokenManager(m,w.workingDir||process.cwd())
|
|
3654
3645
|
await k.initialize()
|
|
3655
|
-
const
|
|
3656
|
-
|
|
3646
|
+
const b=w.tokenSynchronizer||new i.ClientTokenSynchronizer(m),I=new s.AuthenticationManager(k,m,b),v=await I.getTokenString(),C=w.connectionStatusManager||new n.ConnectionStatusManager(e,m,y,{alchemyPath:w.alchemyPath,checkIntervalMs:w.offlineCheckIntervalMs,timeoutMs:w.timeout,retryCount:w.retryAttempts}),_=new c.ProjectClient(e,m,y,C,v||void 0,{timeout:w.timeout,retryAttempts:w.retryAttempts,retryDelay:w.retryDelay,circuitBreakerThreshold:w.circuitBreakerThreshold,circuitBreakerResetTime:w.circuitBreakerResetTime})
|
|
3647
|
+
b.registerClient(_),w.alchemyPath&&_.setAlchemyPath(w.alchemyPath)
|
|
3657
3648
|
const E=new p.TaskClient(e,m,y,_,C,v||void 0,{timeout:w.timeout,retryAttempts:w.retryAttempts,retryDelay:w.retryDelay,circuitBreakerThreshold:w.circuitBreakerThreshold,circuitBreakerResetTime:w.circuitBreakerResetTime})
|
|
3658
|
-
|
|
3649
|
+
b.registerClient(E)
|
|
3659
3650
|
const q=new a.FileOperationsClient(e,m,y,_,v||void 0,C,{timeout:w.timeout,retryAttempts:w.retryAttempts,retryDelay:w.retryDelay,circuitBreakerThreshold:w.circuitBreakerThreshold,circuitBreakerResetTime:w.circuitBreakerResetTime})
|
|
3660
|
-
|
|
3651
|
+
b.registerClient(q),m.info("RequestClient constructor received token: "+(v?"present":"missing"))
|
|
3661
3652
|
const S=new u.RequestClient(e,m,y,_,v||void 0,C,{timeout:w.timeout,retryAttempts:w.retryAttempts,retryDelay:w.retryDelay,circuitBreakerThreshold:w.circuitBreakerThreshold,circuitBreakerResetTime:w.circuitBreakerResetTime})
|
|
3662
|
-
|
|
3653
|
+
b.registerClient(S),m.info("RequestClient post-constructor token: "+(S.getAuthToken()?"present":"missing"))
|
|
3663
3654
|
const T=new g.DocumentClient(e,m,y,_,v||void 0,C,{timeout:w.timeout,retryAttempts:w.retryAttempts,retryDelay:w.retryDelay,circuitBreakerThreshold:w.circuitBreakerThreshold,circuitBreakerResetTime:w.circuitBreakerResetTime})
|
|
3664
|
-
|
|
3655
|
+
b.registerClient(T)
|
|
3665
3656
|
const P=new f.ToolRecordClient(e,m,y,_,v||void 0,C,{timeout:w.timeout,retryAttempts:w.retryAttempts,retryDelay:w.retryDelay,circuitBreakerThreshold:w.circuitBreakerThreshold,circuitBreakerResetTime:w.circuitBreakerResetTime})
|
|
3666
|
-
|
|
3657
|
+
b.registerClient(P)
|
|
3667
3658
|
const M=new d.ProxyClient(e,m,y,_,v||void 0,C,{timeout:w.timeout,retryAttempts:w.retryAttempts,retryDelay:w.retryDelay,circuitBreakerThreshold:w.circuitBreakerThreshold,circuitBreakerResetTime:w.circuitBreakerResetTime})
|
|
3668
|
-
if(
|
|
3659
|
+
if(b.registerClient(M),!w.alchemyPath)throw Error("alchemyPath is required for ProjectSynchronizer creation. Cannot create API client without project synchronization capabilities.")
|
|
3669
3660
|
try{m.info("Creating ProjectSynchronizer components")
|
|
3670
3661
|
const{ProjectRegistry,ProjectFileSystem,ProjectSynchronizer}=await t.e(478).then(t.bind(t,5478)),e=new ProjectRegistry(m),r=new ProjectFileSystem(m),n=new ProjectSynchronizer(m,e,new l.ProjectClientAdapter(_,m),r,{createRemoteProjects:!0})
|
|
3671
3662
|
_.setProjectSynchronizer(n),m.info("ProjectSynchronizer created and connected to ProjectClient")}catch(e){const t="Failed to create required ProjectSynchronizer components: "+(0,h.getErrorMessage)(e)
|
|
3672
|
-
throw m.error(t,{error:e instanceof Error?e.stack:e+""}),Error(t)}const
|
|
3673
|
-
m.info("API client initialized with specialized clients"),v?(
|
|
3674
|
-
const
|
|
3675
|
-
|
|
3676
|
-
const x=
|
|
3677
|
-
return v&&!x?(m.error("CRITICAL: ApiClient token was not set properly!"),
|
|
3663
|
+
throw m.error(t,{error:e instanceof Error?e.stack:e+""}),Error(t)}const j=new o.ApiClient(I,_,E,q,S,T,P,M,m)
|
|
3664
|
+
m.info("API client initialized with specialized clients"),v?(j.setAuthToken(v),m.info("Auth token set on ApiClient during creation",{hasToken:!0,tokenLength:v.length})):m.warn("No auth token available during ApiClient creation",{info:"Client will need to authenticate before making requests"})
|
|
3665
|
+
const R=b.verifyAllClients()
|
|
3666
|
+
R.success?m.info("Token consistency verified across all clients"):m.error(`Token inconsistency detected in ${R.failedClients.length} clients: ${R.failedClients.join(", ")}`)
|
|
3667
|
+
const x=j.getAuthToken()
|
|
3668
|
+
return v&&!x?(m.error("CRITICAL: ApiClient token was not set properly!"),j.setAuthToken(v)):x&&m.info("ApiClient token verified",{tokenLength:x.length,matches:x===v}),m.info("API client creation completed successfully"),j}}},6540(e,exports){var t
|
|
3678
3669
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.LogLevel=void 0,function(e){e.ERROR="error",e.WARN="warn",e.INFO="info",e.DEBUG="debug"}(t||(exports.LogLevel=t={}))},6595(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.ApiClient=void 0
|
|
3679
3670
|
const r=t(1599),n=t(2690),o=t(4465),s=t(5187),i=t(5674),a=t(8824)
|
|
3680
3671
|
exports.ApiClient=class{constructor(e,t,r,n,o,s,i,a,c){this.options={createRecords:!0},this.alchemyPath="",this.sessionRequestAssociationClient=null,this.sessionMessageClient=null,this.sessionTagMappingClient=null,this.cliSessionClient=null,this.logger=c,this.authManager=e,this.projectClient=t,this.taskClient=r,this.fileClient=n,this.requestClient=o,this.documentClient=s,this.toolRecordClient=i,this.proxyClient=a,this.tokenSynchronizer=e.getTokenSynchronizer(),this.baseUrl=a.baseUrl||"",this.documentClient&&"function"==typeof this.documentClient.setParentApiClient&&this.documentClient.setParentApiClient(this),this.logger.info("API client initialized with specialized clients")}async setToken(e){return this.authManager.setToken(e)}async getToken(){return this.authManager.getToken()}async hasValidToken(){return this.authManager.hasValidToken()}async removeToken(){return this.authManager.removeToken()}setOptions(e){this.options={...this.options,...e},this.logger.info("API client options updated",{options:this.options})}getOptions(){return{...this.options}}isOffline(){const e=this.projectClient.isOffline?.()||!1,t=this.fileClient.isOffline?.()||!1,r=this.proxyClient.isOffline?.()||!1,n=e||t||r
|
|
@@ -3712,7 +3703,7 @@ var t={}
|
|
|
3712
3703
|
if(null!=e)for(var r=n(e),i=0;i<r.length;i++)"default"!==r[i]&&o(t,e,r[i])
|
|
3713
3704
|
return s(t,e),t}),a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
3714
3705
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleReplaceLines=async function(e,t,n,o,s,i,a,m){const w=i.child({tool:"replace_lines"}),k=Date.now()
|
|
3715
|
-
let I,
|
|
3706
|
+
let b,I,v=d.FileOperationPhase.VALIDATION
|
|
3716
3707
|
const C={toolName:"replace-lines",operationName:"replace-lines",fileOperationPhase:d.FileOperationPhase.STRING_REPLACEMENT,recordType:"replace-lines",metricsPrefix:"replace_lines",successMessage:"Successfully replaced lines in files and documents",failureMessage:"Failed to replace lines in files and documents"}
|
|
3717
3708
|
try{const i=d.validateArgs(e,l.ReplaceLinesSchema),{taskId:_,operations:E,comment:q}=i
|
|
3718
3709
|
if(w.info("Replacing lines in files and documents",{taskId:_,operationCount:E.length,comment:q}),!E||0===E.length)throw new u.ValidationError("At least one operation is required")
|
|
@@ -3726,19 +3717,19 @@ for(const e of T)M.push({type:"document",documentId:e.documentId,replacements:e.
|
|
|
3726
3717
|
if(M.length>0&&t.apiClient){const e=M.map((e=>e.documentId))
|
|
3727
3718
|
try{await(0,p.ensureDocumentsNotLocked)(e,t.apiClient,w,a,"replace-lines-documents")}catch(e){if(e instanceof u.ValidationError)return{content:[{type:"text",text:e.message}],isError:!0}
|
|
3728
3719
|
throw e}}v=d.FileOperationPhase.TASK_VALIDATION,a.incrementCounter("replace_lines_phase",1,{phase:v})
|
|
3729
|
-
const
|
|
3720
|
+
const j=P.length>0?P[0].path:"document-operation",R=await d.validateTaskId(_,j,n,w,a,C.metricsPrefix),x=R?.requestId
|
|
3730
3721
|
let O=null
|
|
3731
3722
|
P.length>0&&x&&(O=await d.validateWorkItemStates(_,P[0].path,n,s,t,w,a,C.metricsPrefix))
|
|
3732
3723
|
let A={taskPromoted:!1,requestPromoted:!1}
|
|
3733
|
-
P.length>0&&x&&O&&(A=await d.autoPromoteTaskStatus(_,
|
|
3724
|
+
P.length>0&&x&&O&&(A=await d.autoPromoteTaskStatus(_,R.status,x,O.request?.status,P[0].path,n,s,w,a,C.metricsPrefix),A.taskPromoted&&w.info("Auto-promoted task to in_progress for replace-lines operation",{taskId:_,requestId:x,previousStatus:R.status,newStatus:A.newTaskStatus,triggeringOperation:"replace-lines"}))
|
|
3734
3725
|
const D=await d.ensureCorrectWorkspaceContext({taskPromoted:A.taskPromoted,requestId:x,context:t,operation:"replace-lines",logger:w,metrics:a,metricsPrefix:C.metricsPrefix})
|
|
3735
3726
|
if(!D.success){if(D.isLockConflict)return{content:[{type:"text",text:"\u274c "+D.error}],isError:!0}
|
|
3736
3727
|
throw Error(D.error)}if(P.length>0){w.debug("Re-validating file paths with correct workspace context",{operationCount:P.length,workspaceBasePath:t.workspaceManager?.getCurrentContext().basePath})
|
|
3737
3728
|
for(let e=0;e<P.length;e++){const r=P[e],n=S[e],{normalizedPath:o,fullPath:s}=d.validateAndNormalizePath(n.path,t)
|
|
3738
3729
|
P[e]={...r,path:o,fullPath:s}}}if(M.length>0&&x)try{await(0,h.validateRequestStatusForDocumentOperation)(x,s,w,a,"replace-lines-document")}catch(e){if(e instanceof u.ValidationError)return{content:[{type:"text",text:e.message}],isError:!0}
|
|
3739
3730
|
throw e}v=d.FileOperationPhase.RECORD_CREATION,a.incrementCounter("replace_lines_phase",1,{phase:v})
|
|
3740
|
-
const $=[...P.map((e=>({type:"file",path:e.path,replacements:e.replacements}))),...M.map((e=>({type:"document",documentId:e.documentId,replacements:e.replacements})))],{toolRecordId:F}=await d.createFileOperationRecords(_,x,t.projectId,C.recordType,
|
|
3741
|
-
if(
|
|
3731
|
+
const $=[...P.map((e=>({type:"file",path:e.path,replacements:e.replacements}))),...M.map((e=>({type:"document",documentId:e.documentId,replacements:e.replacements})))],{toolRecordId:F}=await d.createFileOperationRecords(_,x,t.projectId,C.recordType,j,{operationCount:E.length,fileOperations:P.length,documentOperations:M.length,operations:$,userComment:q},n,o,w,a,C.metricsPrefix,m)
|
|
3732
|
+
if(b=F,I=F,v=C.fileOperationPhase,a.incrementCounter("replace_lines_phase",1,{phase:v}),P.length>0&&t.git)try{w.debug("[REPLACE-LINES] Checking for user changes before replace operations")
|
|
3742
3733
|
const e=await(0,g.commitUserChangesBeforeToolOperation)(t.git,"replace-lines",{requestId:x,taskId:_,workspaceManager:t.workspaceManager},w,a)
|
|
3743
3734
|
e.userChangesCommitted&&(w.debug("[REPLACE-LINES] User changes committed before replace operations",{commitHash:e.commitHash?.substring(0,8),filesCommitted:e.filesCommitted}),w.info("User changes committed before replace-lines operation",{taskId:_,fileOperationsCount:P.length,userCommitHash:e.commitHash?.substring(0,8),userFilesCommitted:e.filesCommitted}))}catch(e){w.debug("[REPLACE-LINES] Pre-tool commit failed, continuing with replacements",{error:e instanceof Error?e.message:e+""}),w.warn("Pre-tool user changes commit failed, continuing with replace operation",{taskId:_,fileOperationsCount:P.length,error:e instanceof Error?e.message:e+""})}w.debug("[REPLACE-LINES] Proceeding with file operations",{fileCount:P.length})
|
|
3744
3735
|
const N=[]
|
|
@@ -3751,33 +3742,33 @@ try{const o=await t.documentFileManager.getDocumentAsFile(e.documentId),s=t.docu
|
|
|
3751
3742
|
n.filename=s?.filename
|
|
3752
3743
|
const i=await c.default.readFile(o,"utf8"),{newContent:a,results:l}=await r(i,e.replacements)
|
|
3753
3744
|
n.replacements=l,n.successfulReplacements=l.filter((e=>e.success)).length,n.failedReplacements=l.filter((e=>!e.success)).length,n.totalLinesReplaced=l.filter((e=>e.success)).reduce(((e,t)=>e+(t.linesReplaced||0)),0),n.totalLinesAdded=l.filter((e=>e.success)).reduce(((e,t)=>e+(t.linesAdded||0)),0),a!==i&&n.successfulReplacements>0?(await c.default.writeFile(o,a,"utf8"),t.documentFileManager.markForSync(e.documentId),n.success=!0,H++,w.info("Document updated successfully",{documentId:e.documentId,filename:n.filename,successfulReplacements:n.successfulReplacements,failedReplacements:n.failedReplacements,linesReplaced:n.totalLinesReplaced,linesAdded:n.totalLinesAdded})):0===n.failedReplacements&&(n.success=!0),L+=n.failedReplacements,z+=n.totalLinesReplaced,B+=n.totalLinesAdded}catch(t){n.error=(0,f.getErrorMessage)(t),n.failedReplacements=e.replacements.length,L+=n.failedReplacements,w.error("Document operation failed",{documentId:e.documentId,error:n.error})}N.push(n)}if(M.length>0)try{for(const e of M){const r=N.find((t=>t.documentId===e.documentId))
|
|
3754
|
-
r?.success&&await t.documentFileManager.syncDocument(e.documentId)}}catch(e){w.warn("Some documents may not have synced properly",{error:e})}const W=await d.handleMultiFileGitCommit(_,P,N,H,{operationType:"Replace lines",toolRecordId:
|
|
3755
|
-
try{await o.updateToolRecord(
|
|
3745
|
+
r?.success&&await t.documentFileManager.syncDocument(e.documentId)}}catch(e){w.warn("Some documents may not have synced properly",{error:e})}const W=await d.handleMultiFileGitCommit(_,P,N,H,{operationType:"Replace lines",toolRecordId:I,successField:"successfulReplacements",logger:w,metrics:a,metricsPrefix:"replace_lines"},t),U=d.processMultiFileOperationResults(N,"successfulReplacements"),{successfulOperations:G,failedOperations:V,totalSuccessfulChanges:J,overallSuccess:K,successfulFiles:Y,failedFiles:Q}=U
|
|
3746
|
+
try{await o.updateToolRecord(I,{metadata:{path:P.length>0?P[0].path:"document:"+M[0]?.documentId,status:K?"completed":"failed",error:K?void 0:V+" operations failed",totalOperations:N.length,successfulFiles:Y,failedFiles:Q,operations:$,totalSuccessfulReplacements:J,totalFailedReplacements:L,totalLinesReplaced:z,totalLinesAdded:B,operationsWithChanges:H,processingTime:Date.now()-k,userComment:q,...P.length>0&&W.success&&W.commitHash&&{commitHash:W.commitHash,previousCommitHash:W.previousCommitHash||void 0}},note:K?`Line replacement completed: ${G}/${N.length} operations successful${P.length>0?" (committed to git)":""}`:`Line replacement partially failed: ${V}/${N.length} operations failed`})}catch(e){w.warn("Failed to update tool record",{recordError:e})}let Z="## Line Replacement Results\n\n"
|
|
3756
3747
|
if(t.workspaceManager&&(Z+=`**Branch:** \`${t.workspaceManager.getCurrentContext().branchName}\`\n\n`),Z+="**Summary:**\n",Z+=`- **Files processed:** ${G+V}\n`,Z+=`- **Successful operations:** ${G}\n`,Z+=`- **Failed operations:** ${V}\n`,Z+=`- **Total replacements:** ${J} successful, ${L} failed\n`,Z+=`- **Total Lines Replaced:** ${z}\n`,B>0&&(Z+=`- **Total Lines Added:** ${B}\n`),Z+="\n",W.success&&W.commitHash&&(Z+="**Git Commit:**\n",Z+=`- **Commit Hash:** ${W.commitHash.substring(0,8)}\n`,Z+=`- **Files Committed:** ${W.filesCommitted.length}\n`,W.previousCommitHash&&(Z+=`- **Previous Commit:** ${W.previousCommitHash.substring(0,8)}\n`),Z+="\n"),D.lockAcquired&&D.lockedRequestId&&(Z+=`\u{1f512} **Locked request:** ${D.lockedRequestId}\n\n`),1===N.length){const e=N[0]
|
|
3757
3748
|
if(Z+=`**Operation:** ${e.success?"\u2705 Success":"\u274c Failed"}\n`,"file"===e.type?Z+=`**File:** ${e.path}\n`:(Z+="**Document:** "+e.documentId,e.filename&&(Z+=` (${e.filename})`),Z+="\n"),e.error?Z+=`**Error:** ${e.error}\n`:(Z+=`**Replacements:** ${e.successfulReplacements} successful`,e.failedReplacements>0&&(Z+=`, ${e.failedReplacements} failed`),Z+="\n",Z+=`**Lines Replaced:** ${e.totalLinesReplaced}\n`,e.totalLinesAdded>0&&(Z+=`**Lines Added:** ${e.totalLinesAdded}\n`)),e.replacements.some((e=>!e.success))){Z+="**Failed Replacement Details:**\n"
|
|
3758
3749
|
for(const t of e.replacements.filter((e=>!e.success)))Z+=`- Replace ${"number"==typeof t.lines?"line "+t.lines:Array.isArray(t.lines)?`lines [${t.lines.join(", ")}]`:`lines ${t.lines.start}-${t.lines.end}`}: ${t.error}\n`}}else{Z+="**Summary:**\n",Z+=`- **Total Operations:** ${N.length}\n`,Z+=`- **Successful:** ${G}\n`,Z+=`- **Failed:** ${V}\n`,Z+=`- **Total Replacements:** ${J} successful, ${L} failed\n`,Z+=`- **Total Lines Replaced:** ${z}\n`,B>0&&(Z+=`- **Total Lines Added:** ${B}\n`),Z+="\n",Z+="**Detailed Results:**\n\n"
|
|
3759
3750
|
for(const e of N){if("file"===e.type?Z+=`### File: ${e.path}\n`:(Z+="### Document: "+e.documentId,e.filename&&(Z+=` (${e.filename})`),Z+="\n"),Z+=`- **Status:** ${e.success?"\u2705 Success":"\u274c Failed"}\n`,e.error&&(Z+=`- **Error:** ${e.error}\n`),Z+=`- **Replacements:** ${e.successfulReplacements} successful`,e.failedReplacements>0&&(Z+=`, ${e.failedReplacements} failed`),Z+="\n",Z+=`- **Lines Replaced:** ${e.totalLinesReplaced}\n`,e.totalLinesAdded>0&&(Z+=`- **Lines Added:** ${e.totalLinesAdded}\n`),e.replacements.some((e=>!e.success))){Z+="- **Failed Replacement Details:**\n"
|
|
3760
3751
|
for(const t of e.replacements.filter((e=>!e.success)))Z+=` - Replace ${"number"==typeof t.lines?"line "+t.lines:Array.isArray(t.lines)?`lines [${t.lines.join(", ")}]`:`lines ${t.lines.start}-${t.lines.end}`}: ${t.error}\n`}Z+="\n"}}M.length>0&&(Z+="\u{1f4c4} **Document Changes:** Modified documents have been automatically synced back to the tracking system.\n\n")
|
|
3761
3752
|
const X=Date.now()-k
|
|
3762
|
-
return w.info("Replace lines operation completed",{duration:X,success:
|
|
3763
|
-
if(w.error("Replace lines operation failed",{error:t instanceof Error?t.stack:t+"",duration:r,phase:v}),
|
|
3753
|
+
return w.info("Replace lines operation completed",{duration:X,success:K,totalOperations:N.length,successfulOperations:G,failedOperations:V}),a.incrementCounter("replace_lines_total",1,{success:K}),{content:[{type:"text",text:Z}],isError:!K}}catch(t){const r=Date.now()-k
|
|
3754
|
+
if(w.error("Replace lines operation failed",{error:t instanceof Error?t.stack:t+"",duration:r,phase:v}),I)try{await o.updateToolRecord(I,{metadata:{path:e?.operations?.[0]?.path||e?.operations?.[0]?.documentId,status:"failed",error:(0,f.getErrorMessage)(t),phase:v,duration:r,userComment:e?.comment},note:"Line replacement failed: "+(0,f.getErrorMessage)(t)})}catch(e){}return a.incrementCounter("replace_lines_errors",1,{phase:v}),{content:[{type:"text",text:"\u274c **Replace Lines Failed:** "+(0,f.getErrorMessage)(t)}],isError:!0}}}
|
|
3764
3755
|
const c=a(t(1943)),l=t(6183),d=i(t(5967)),u=t(9860),h=t(5003),g=t(7478),p=t(9949),f=t(8824),m=t(3255),y=t(9470)},6688(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.sessionIdentity=void 0
|
|
3765
3756
|
const r=t(9896),n=t(6928)
|
|
3766
|
-
exports.sessionIdentity=new class{constructor(){this.
|
|
3757
|
+
exports.sessionIdentity=new class{constructor(){this.parentCache=new Map}setIdentity(e){const t=this.identity
|
|
3767
3758
|
this.identity=e,this.log("setIdentity",{sessionId:e.sessionId,serverUrl:e.serverUrl,agentType:e.agentType||null,prevSessionId:t?.sessionId||null,changed:t?.sessionId!==e.sessionId})}getIdentity(){return this.identity}updateIdentity(e){if(this.identity){const t={...this.identity}
|
|
3768
|
-
this.identity={...this.identity,...e},this.log("updateIdentity",{sessionId:this.identity.sessionId,updates:Object.keys(e),agentTypeBefore:t.agentType||null,agentTypeAfter:this.identity.agentType||null})}}
|
|
3769
|
-
this.identity=void 0,this.discoveryAttempted=!1,this.log("reset",{prevSessionId:e?.sessionId||null,prevAgentType:e?.agentType||null})}hasDiscoveryBeenAttempted(){return this.discoveryAttempted}markDiscoveryAttempted(){this.discoveryAttempted=!0}async getParentSessionId(e,t,r){if(this.parentCache.has(e)){const t=this.parentCache.get(e)
|
|
3759
|
+
this.identity={...this.identity,...e},this.log("updateIdentity",{sessionId:this.identity.sessionId,updates:Object.keys(e),agentTypeBefore:t.agentType||null,agentTypeAfter:this.identity.agentType||null})}}async getParentSessionId(e,t,r){if(this.parentCache.has(e)){const t=this.parentCache.get(e)
|
|
3770
3760
|
return this.log("getParentSessionId.cache-hit",{childExternalId:e,parentExternalId:t}),t}try{const n=t.getCLISessionClient()
|
|
3771
3761
|
if(!n)return r.warn("CLI session client not available"),null
|
|
3772
3762
|
const o=await n.getParent(e),s=o?.externalSessionId||null
|
|
3773
3763
|
return this.parentCache.set(e,s),this.log("getParentSessionId.resolved",{childExternalId:e,parentExternalId:s}),s||r.warn("Parent session not found",{sessionId:e}),s}catch(t){const n=t instanceof Error?t.message:t+""
|
|
3774
|
-
return r.warn("Error getting parent session",{sessionId:e,error:n}),null}}setParentSessionId(e,t){this.parentCache.set(e,t)}async getSessionRequestId(e,t){
|
|
3764
|
+
return r.warn("Error getting parent session",{sessionId:e,error:n}),null}}setParentSessionId(e,t){this.parentCache.set(e,t)}async getSessionRequestId(e,t,r){const n=r||this.identity?.sessionId
|
|
3765
|
+
if(!n)return t.warn("Cannot get session request: no session identity"),null
|
|
3775
3766
|
try{const r=e.getSessionRequestAssociationClient?.()
|
|
3776
3767
|
if(!r)return t.warn("Session request association client not available"),null
|
|
3777
|
-
const
|
|
3778
|
-
if(
|
|
3779
|
-
return this.log("getSessionRequestId.resolved",{sessionId:
|
|
3780
|
-
return t.warn("Error getting session request",{sessionId:
|
|
3768
|
+
const o=await r.getActiveRequestsForSession(n)
|
|
3769
|
+
if(o?.length>0){const e=o[0].requestLocalId||o[0].request_local_id
|
|
3770
|
+
return this.log("getSessionRequestId.resolved",{sessionId:n,requestId:e}),e||null}return this.log("getSessionRequestId.none",{sessionId:n}),null}catch(e){const r=e instanceof Error?e.message:e+""
|
|
3771
|
+
return t.warn("Error getting session request",{sessionId:n,error:r}),null}}buildCliOrigin(e){if(this.identity)return{providerId:this.identity.providerId,sessionId:this.identity.sessionId,messageId:e,createdAt:(new Date).toISOString()}}setCurrentCallOrigin(e){this.currentCallOrigin=e}getCurrentCallOrigin(){return this.currentCallOrigin||this.buildCliOrigin()}log(e,t){try{const o=process.env.ALCHEMY_PROJECT_PATH||process.cwd(),s=(0,n.join)(o,".alchemy_lab");(0,r.existsSync)(s)||(0,r.mkdirSync)(s,{recursive:!0})
|
|
3781
3772
|
const i=(0,n.join)(s,"mcp-identity-debug.log"),a=(new Date).toISOString(),c=process.pid,l=t?" "+JSON.stringify(t):"";(0,r.appendFileSync)(i,`[${a}] [PID:${c}] identity.${e}${l}\n`)}catch{}}},exports.sessionIdentity.log("module-load",{ALCHEMY_SESSION_TAG:process.env.ALCHEMY_SESSION_TAG||null,ALCHEMY_INITIAL_BRANCH:process.env.ALCHEMY_INITIAL_BRANCH||null,ALCHEMY_ALLOW_PARALLEL:process.env.ALCHEMY_ALLOW_PARALLEL||null})},6756(e,exports){var t,r
|
|
3782
3773
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.TaskStatus=exports.RequestStatus=void 0,function(e){e.OPEN="open",e.IN_PROGRESS="in_progress",e.COMPLETED="completed",e.CONFLICTED="conflicted",e.READY_FOR_REVIEW="ready_for_review",e.PENDING_APPROVAL="pending_approval"}(t||(exports.RequestStatus=t={})),function(e){e.PENDING="pending",e.IN_PROGRESS="in_progress",e.READY_FOR_REVIEW="ready_for_review",e.COMPLETED="completed"}(r||(exports.TaskStatus=r={}))},6770(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.def=void 0
|
|
3783
3774
|
const r=t(6183),n=t(6651)
|
|
@@ -3837,16 +3828,16 @@ let w
|
|
|
3837
3828
|
r.setProjectId(y)
|
|
3838
3829
|
try{const P=await f.getTask(g)
|
|
3839
3830
|
s.info("Raw task response data",{responseDataType:typeof P,isArray:Array.isArray(P),hasData:null!=P,properties:P&&"object"==typeof P?Object.keys(P):[]}),w=(0,l.extractDataFromResponse)(P,{logger:s,operationName:"getTask",defaultValue:{id:g,title:"Unknown Task",status:"unknown",description:"No description available"}}),s.info("Found task: "+w.title)}catch(M){s.warn("Could not fetch task information: "+(0,u.getErrorMessage)(M)),w={id:g,title:"Unknown Task",status:"unknown",description:"No description available"}}let k=[]
|
|
3840
|
-
try{const
|
|
3841
|
-
if(s.info("Raw records response data",{responseDataType:typeof
|
|
3842
|
-
k.forEach((e=>{
|
|
3843
|
-
function
|
|
3831
|
+
try{const j=await m.getToolRecordsByTaskId(g)
|
|
3832
|
+
if(s.info("Raw records response data",{responseDataType:typeof j,isArray:Array.isArray(j),hasData:null!=j,properties:j&&"object"==typeof j?Object.keys(j):[]}),k=(0,l.extractArrayFromResponse)(j,{logger:s,operationName:"searchRecords",defaultValue:[]}),k.length>0&&s.info("First record summary:",{id:k[0].id,type:k[0].type,hasMetadata:!!k[0].metadata,hasCommitHash:!!k[0].metadata?.commitHash}),s.info(`Extracted ${k.length} records for task ${g}`),k.length>0){const R={}
|
|
3833
|
+
k.forEach((e=>{R[e.type]=(R[e.type]||0)+1})),s.info("Record type distribution:",R)}}catch(x){s.warn("Error fetching records for task "+g,{error:(0,u.getErrorMessage)(x)}),k=[]}if(0===k.length)return h({success:!0,recordCount:0}),{content:[{type:"text",text:`No records found for task ${g}.`}]}
|
|
3834
|
+
function b(e){const t=new Map,r=new Map,n=[]
|
|
3844
3835
|
for(const o of e)if("move-file"===o.type&&o.metadata){const e=o.metadata.source||o.metadata.oldPath,s=o.metadata.destination||o.metadata.newPath
|
|
3845
3836
|
if(e&&s){const i={source:e,destination:s,recordId:o.id,timestamp:o.createdAt,type:"move-file"}
|
|
3846
3837
|
t.set(e,i),r.set(s,i),n.push(i)}}else if("move-files"===o.type&&o.metadata){const e=[...o.metadata.successfulOperations||[],...o.metadata.failedOperations||[]]
|
|
3847
3838
|
for(const s of e)if(s.source&&s.destination){const e={source:s.source,destination:s.destination,recordId:o.id,timestamp:o.createdAt,type:"move-files"}
|
|
3848
|
-
t.set(s.source,e),r.set(s.destination,e),n.push(e)}}return{sourceToMove:t,destToMove:r,allMoves:n}}const b
|
|
3849
|
-
s.info(`Detected ${
|
|
3839
|
+
t.set(s.source,e),r.set(s.destination,e),n.push(e)}}return{sourceToMove:t,destToMove:r,allMoves:n}}const I=b(k)
|
|
3840
|
+
s.info(`Detected ${I.allMoves.length} move operations`)
|
|
3850
3841
|
const v=k.filter((e=>{if(!e||"object"!=typeof e)return s.warn("Skipping invalid record (not an object)"),!1
|
|
3851
3842
|
if(!["write-file","replace-in-files","move-file","move-files","delete-file","delete-files","manage-files"].includes(e.type))return s.debug("Skipping record with non-file operation type: "+e.type),!1
|
|
3852
3843
|
if(!e.metadata)return s.warn("Skipping record without metadata: "+e.id),!1
|
|
@@ -3894,10 +3885,10 @@ const N=new Map
|
|
|
3894
3885
|
F.forEach((e=>{e.recordId&&e.record?.metadata?.status&&(N.has(e.recordId)||N.set(e.recordId,[]),N.get(e.recordId)?.push(e.record.metadata.status))})),N.forEach(((e,t)=>{s.info(`Record ${t} status updates: ${e.join(" -> ")}`)}))
|
|
3895
3886
|
const L=F.filter((e=>e.commitHash))
|
|
3896
3887
|
if(s.info(`Found ${L.length} records with commit hash for ${$}`),0===L.length){s.info(`No commit hashes found in record metadata for ${$}, trying git log`)
|
|
3897
|
-
try{if(t.git){const J={file:$,n:10},
|
|
3898
|
-
if(
|
|
3899
|
-
const K
|
|
3900
|
-
if(
|
|
3888
|
+
try{if(t.git){const J={file:$,n:10},K=await t.git.log(J)
|
|
3889
|
+
if(K&&K.all&&K.all.length>0){s.info(`Found ${K.all.length} commits for ${$} using git log`)
|
|
3890
|
+
const Y=K.all.map((e=>({filePath:$,recordId:"git-"+e.hash.substring(0,8),type:"git-commit",timestamp:new Date(e.date).toISOString(),commitHash:e.hash,status:"completed",record:{id:"git-"+e.hash.substring(0,8),type:"git-commit",content:e.message,createdAt:new Date(e.date).toISOString(),metadata:{commitHash:e.hash}}})))
|
|
3891
|
+
if(Y.length>0){const Q=Y.length>1?Y[Y.length-1]:Y[0],Z=Y[0],X=1===Y.length
|
|
3901
3892
|
s.info(X?`Using single git commit for ${$}: ${Z.commitHash?Z.commitHash.substring(0,8):"unknown"}`:`Using git commits for ${$}: ${Q.commitHash?Q.commitHash.substring(0,8):"unknown"} to ${Z.commitHash?Z.commitHash.substring(0,8):"unknown"}`)
|
|
3902
3893
|
let ee=""
|
|
3903
3894
|
try{if(X)try{const te=[`${Z.commitHash}:${$}`],re=await t.git.show(te)
|
|
@@ -3922,7 +3913,7 @@ continue}let pe
|
|
|
3922
3913
|
if("pre-task"===U.status?(pe=[`${U.commitHash}..${B.commitHash}`,"--",$],s.info(`Comparing pre-task commit with final commit: ${U.commitHash?U.commitHash.substring(0,8):"unknown"}..${B.commitHash?B.commitHash.substring(0,8):"unknown"} for ${$}`)):(pe=["4b825dc642cb6eb9a060e54bf8d69288fbee4904.."+B.commitHash,"--",$],s.info(`File created during task, showing full file diff using empty tree object: ${B.commitHash?B.commitHash.substring(0,8):"unknown"} for ${$}`)),G=await t.git.diff(pe),V=!!G&&G.trim().length>0,!V&&U.commitHash!==B.commitHash){s.info("No diff found between commits but commits are different, trying direct file content comparison")
|
|
3923
3914
|
try{const me=await t.git.show([`${U.commitHash}:${$}`]),ye=await t.git.show([`${B.commitHash}:${$}`])
|
|
3924
3915
|
if(me!==ye&&(V=!0,G="Changes detected through direct content comparison (not visible in standard diff)",p)){const we=me.split("\n"),ke=ye.split("\n")
|
|
3925
|
-
Math.abs(we.length-ke.length)>0&&(G+=`\n\nLine count changed: ${we.length} \u2192 ${ke.length}`),me.includes("\0")||ye.includes("\0")?G+="\n\nBinary content detected - changes not displayed":me.replace(/\s+/g,"")===ye.replace(/\s+/g,"")&&(G+="\n\nWhitespace-only changes detected")}}catch(
|
|
3916
|
+
Math.abs(we.length-ke.length)>0&&(G+=`\n\nLine count changed: ${we.length} \u2192 ${ke.length}`),me.includes("\0")||ye.includes("\0")?G+="\n\nBinary content detected - changes not displayed":me.replace(/\s+/g,"")===ye.replace(/\s+/g,"")&&(G+="\n\nWhitespace-only changes detected")}}catch(be){s.warn("Error in direct file comparison: "+(be instanceof Error?be.message:be+""))}}s.info(`Diff generation result for ${$}: hasDiff=${V}, length=${G.length}`)}}catch(Ie){if(s.warn("Error getting diff for "+$,{error:(0,u.getErrorMessage)(Ie),firstCommit:z.commitHash||"unknown",lastCommit:B.commitHash||"unknown"}),G="Error getting diff: "+(0,u.getErrorMessage)(Ie),"pre-task"!==z.status&&t.git)try{const ve=[`${B.commitHash}:${$}`]
|
|
3926
3917
|
s.info(`Trying fallback to show file content using git show: ${B.commitHash?B.commitHash.substring(0,8):"unknown"}:${$}`)
|
|
3927
3918
|
const Ce=await t.git.show(ve)
|
|
3928
3919
|
if(Ce&&Ce.trim().length>0){if(p){let _e=""
|
|
@@ -3934,15 +3925,15 @@ w&&"object"==typeof w&&(E+="## Task Information\n",E+=`- **Title**: ${w.title||"
|
|
|
3934
3925
|
const q=3e3
|
|
3935
3926
|
let S=0,T=!1
|
|
3936
3927
|
if(p){for(const Te of _.values())Te.hasDiff&&Te.diffText&&(S+=Te.diffText.split("\n").length)
|
|
3937
|
-
T=S>q,s.info(`Total diff size: ${S} lines (limit: ${q} lines)`),s.info(`Diffs ${T?"will be limited":"will be shown"} based on size`)}if(E+="## Summary\n",E+=`- **Files Modified**: ${C.size}\n`,E+=`- **Total File Operations**: ${v.length}\n`,E+="- **What's Shown**: For existing files, comparing state before task started with final state.\n",E+=" For files created during task, showing the entire file as created.\n",T?(E+=`- **Diff Display**: Limited (total diff size of ${S} lines exceeds limit of ${q} lines)\n`,E+=" Use file-history tool with individual files to see detailed changes\n\n"):E+=`- **Diff Display**: ${p?"Enabled":"Disabled"} (use showDiff=${!p} to ${p?"hide":"show"} diffs)\n\n`,
|
|
3938
|
-
for(const Pe of
|
|
3939
|
-
for(const[Me,
|
|
3928
|
+
T=S>q,s.info(`Total diff size: ${S} lines (limit: ${q} lines)`),s.info(`Diffs ${T?"will be limited":"will be shown"} based on size`)}if(E+="## Summary\n",E+=`- **Files Modified**: ${C.size}\n`,E+=`- **Total File Operations**: ${v.length}\n`,E+="- **What's Shown**: For existing files, comparing state before task started with final state.\n",E+=" For files created during task, showing the entire file as created.\n",T?(E+=`- **Diff Display**: Limited (total diff size of ${S} lines exceeds limit of ${q} lines)\n`,E+=" Use file-history tool with individual files to see detailed changes\n\n"):E+=`- **Diff Display**: ${p?"Enabled":"Disabled"} (use showDiff=${!p} to ${p?"hide":"show"} diffs)\n\n`,I.allMoves.length>0){E+="## Move Operations\n\n",E+=`Detected ${I.allMoves.length} file move operation(s):\n\n`
|
|
3929
|
+
for(const Pe of I.allMoves)E+=`- **${Pe.source}** \u2192 **${Pe.destination}**\n`,E+=` - Operation: ${Pe.type}\n`,E+=` - Timestamp: ${new Date(Pe.timestamp).toLocaleString()}\n`,E+=` - Record ID: ${Pe.recordId}\n\n`}E+="## Modified Files\n\n"
|
|
3930
|
+
for(const[Me,je]of _.entries()){const{normalizedPath:Re,fullPath:xe}=d.validateAndNormalizePath(Me,t)
|
|
3940
3931
|
let Oe=!1
|
|
3941
3932
|
try{await a.access(xe),Oe=!0}catch{}E+=`### ${Me} ${Oe?"":"(Deleted)"}\n\n`
|
|
3942
|
-
const Ae=new Date(
|
|
3943
|
-
E+=`**First Change**: ${Ae}\n`,E+=`**Last Change**: ${De}\n`,"pre-task"===
|
|
3944
|
-
const $e=
|
|
3945
|
-
$e?E+=`**\u2139\ufe0f Move Operation**: This file was moved TO **${$e.destination}**\n`:Fe&&(E+=`**\u2139\ufe0f Move Operation**: This file was moved FROM **${Fe.source}**\n`),p&&!T?
|
|
3933
|
+
const Ae=new Date(je.firstChange.timestamp).toLocaleString(),De=new Date(je.lastChange.timestamp).toLocaleString()
|
|
3934
|
+
E+=`**First Change**: ${Ae}\n`,E+=`**Last Change**: ${De}\n`,"pre-task"===je.firstChange.status&&je.firstChange.commitHash?E+=`**Pre-Task Commit**: ${je.firstChange.commitHash.substring(0,8)}\n`:je.firstChange.commitHash&&(E+=`**File Created During Task**: ${je.firstChange.commitHash.substring(0,8)}\n`),je.lastChange.commitHash&&(E+=`**Final Commit**: ${je.lastChange.commitHash.substring(0,8)}\n`)
|
|
3935
|
+
const $e=I.sourceToMove.get(Me),Fe=I.destToMove.get(Me)
|
|
3936
|
+
$e?E+=`**\u2139\ufe0f Move Operation**: This file was moved TO **${$e.destination}**\n`:Fe&&(E+=`**\u2139\ufe0f Move Operation**: This file was moved FROM **${Fe.source}**\n`),p&&!T?je.hasDiff?(E+="\n**Changes**:\n",E+="```diff\n",E+=je.diffText,E+="\n```\n\n"):E+=`\n**Note**: ${je.diffText}\n\n`:T&&je.hasDiff?(E+=`\n**Note**: File has changes (${je.diffText?je.diffText.split("\n").length:0} lines). `,E+=`Compare ${je.firstChange.commitHash?je.firstChange.commitHash.substring(0,8):"unknown"}..${je.lastChange.commitHash?je.lastChange.commitHash.substring(0,8):"unknown"} to see changes.\n\n`):je.hasDiff?E+="\n**Note**: File has changes. Use showDiff=true to see the diff.\n\n":E+=`\n**Note**: ${je.diffText}\n\n`,E+="---\n\n"}return h({success:!0,fileCount:C.size}),{content:[{type:"text",text:E}]}}catch(Ne){return s.error("Error in task file history tool",{error:Ne instanceof Error?Ne.stack:Ne+""}),h({success:!1,error:Ne instanceof Error?Ne.name:"unknown"}),{content:[{type:"text",text:"Error: "+(0,u.getErrorMessage)(Ne)}],isError:!0}}}
|
|
3946
3937
|
const i=t(9860),a=s(t(1943)),c=t(9671),l=t(2960),d=s(t(5967)),u=t(8824)},6928(module){module.exports=require("path")},6975(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.ProjectClientAdapter=void 0
|
|
3947
3938
|
const r=t(1058)
|
|
3948
3939
|
exports.ProjectClientAdapter=class{constructor(e,t){this.client=e,this.logger=t.child({component:"project-client-adapter"}),this.logger.info("ProjectClientAdapter initialized")}isOnline(){return!this.client.isOffline()}async fetchProject(e){try{return this.logger.debug("ProjectClientAdapter.fetchProject called",{projectId:e}),await this.client.getProject(e)}catch(t){return this.logger.error("Error in ProjectClientAdapter.fetchProject",{projectId:e,error:t instanceof Error?t.stack:t+""}),null}}async createProject(e){try{this.logger.debug("ProjectClientAdapter.createProject called",{projectName:e.name,projectId:e.id}),this.logger.info("Creating project via adapter",{name:e.name,id:e.id,description:e.description?.substring(0,50)})
|
|
@@ -4064,42 +4055,42 @@ Object.defineProperty(exports,"__esModule",{value:!0}),exports.logSessionIdentit
|
|
|
4064
4055
|
i.existsSync(n)||i.mkdirSync(n,{recursive:!0})
|
|
4065
4056
|
const s=(new Date).toISOString(),c=Object.keys(r).length?" "+JSON.stringify(r):""
|
|
4066
4057
|
i.appendFileSync(o,`[${s}] ${e} | ${t}${c}\n`)}catch(e){}}
|
|
4067
|
-
const i=s(t(9896)),a=s(t(6928))},7334(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleCreateRequest=async function(e,t,l,d,u,h
|
|
4068
|
-
|
|
4069
|
-
const
|
|
4070
|
-
try{if(e&&"string"==typeof e.acceptanceCriteria)try{e.acceptanceCriteria=JSON.parse(e.acceptanceCriteria)}catch{}const
|
|
4058
|
+
const i=s(t(9896)),a=s(t(6928))},7334(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleCreateRequest=async function(e,t,c,l,d,u,h){const g=l.child({tool:"create_request"})
|
|
4059
|
+
g.info("Creating new request",{args:e})
|
|
4060
|
+
const p=d.startTimer("tool_handler_duration")
|
|
4061
|
+
try{if(e&&"string"==typeof e.acceptanceCriteria)try{e.acceptanceCriteria=JSON.parse(e.acceptanceCriteria)}catch{}const l=function(e){try{return r.CreateRequestSchema.parse(e)}catch(e){if(e instanceof s.ZodError&&e.errors.length>0)throw new n.ValidationError(e.errors[0].message)
|
|
4071
4062
|
throw new n.ValidationError("Invalid input: "+(0,i.getErrorMessage)(e))}}(e)
|
|
4072
|
-
|
|
4073
|
-
const
|
|
4074
|
-
if(!
|
|
4075
|
-
|
|
4076
|
-
const
|
|
4077
|
-
let
|
|
4078
|
-
try{const e=
|
|
4079
|
-
if(e){const t=
|
|
4063
|
+
d.incrementCounter("create_request_attempts",1,{type:l.type,criteriaCounts:l.acceptanceCriteria.length})
|
|
4064
|
+
const f=t.projectId
|
|
4065
|
+
if(!f)throw new n.ValidationError("Project ID is required for creating requests.")
|
|
4066
|
+
c.setProjectId(f)
|
|
4067
|
+
const m=c.getRequestClient()
|
|
4068
|
+
let y=(0,a.getApprovalMode)()
|
|
4069
|
+
try{const e=h?.sessionId
|
|
4070
|
+
if(e){const t=c.getCLISessionClient()
|
|
4080
4071
|
if(t){const r=await t.getByExternalId(e)
|
|
4081
|
-
if(r?.workflowId){const e=await
|
|
4082
|
-
t?.approvalMode&&(
|
|
4083
|
-
r&&(
|
|
4084
|
-
|
|
4085
|
-
const b=await
|
|
4086
|
-
|
|
4087
|
-
const
|
|
4088
|
-
let _
|
|
4089
|
-
if(
|
|
4090
|
-
|
|
4091
|
-
try{const e=
|
|
4092
|
-
if(e){const t=await e.createToolRecord({requestId:
|
|
4093
|
-
|
|
4094
|
-
const
|
|
4095
|
-
let
|
|
4096
|
-
return
|
|
4097
|
-
else{const n=
|
|
4098
|
-
n&&await n.createToolRecord({projectId:t.projectId,type:"create-request",metadata:{status:"failed",timestamp:(new Date).toISOString(),requestTitle:e.title,requestType:e.type,requestDescription:e.description?.substring(0,100)+(e.description?.length>100?"...":""),criteriaCount:e.acceptanceCriteria?e.acceptanceCriteria.length:0,branchCreated:!1,branchName:null,error:(0,i.getErrorMessage)(r),errorDetails:r instanceof Error?r.stack:r+""},note:"Failed to create request: "+e.title})}}catch(e){
|
|
4072
|
+
if(r?.workflowId){const e=await c.proxyGet("/api/workflows/"+r.workflowId),t=e?.data||e
|
|
4073
|
+
t?.approvalMode&&(y=(0,a.getApprovalMode)(t.approvalMode))}}}if("none"===y)try{const e=await c.proxyGet("/api/projects/"+f),t=e?.data||e,r=t?.metadata?.defaultApprovalMode
|
|
4074
|
+
r&&(y=(0,a.getApprovalMode)(r))}catch(e){g.warn("Failed to read project metadata for approvalMode fallback",{error:(0,i.getErrorMessage)(e)})}}catch(e){g.warn("Failed to resolve approval mode, using default",{error:(0,i.getErrorMessage)(e)})}const w="require-approval"===y&&"quick-edit"!==l.type?"pending_approval":"open",k={title:l.title,description:l.description,type:l.type,acceptanceCriteria:l.acceptanceCriteria,status:w,...l.planDocumentId&&{planDocumentId:l.planDocumentId},...h&&{cliOrigin:h}}
|
|
4075
|
+
g.info("Creating request via request client",{projectId:f,title:l.title,type:l.type,criteriaCount:l.acceptanceCriteria.length})
|
|
4076
|
+
const b=await m.createRequest(k)
|
|
4077
|
+
g.debug("Create request response structure",{type:typeof b,isArray:Array.isArray(b),hasData:null!=b,properties:b?Object.keys(b):[],dataPreview:b?JSON.stringify(b).substring(0,200)+"...":"null"})
|
|
4078
|
+
const I=(0,o.extractDataFromResponse)(b,{logger:g,operationName:"createRequest",throwOnNoData:!0}),v="data"in I?I.data:I
|
|
4079
|
+
let C,_={created:!1}
|
|
4080
|
+
if(u?.workspaceManager)try{await u.workspaceManager.initializeRequest(v.id,v.title),_={created:!0,branchName:"requests/"+v.id,message:"Branch created successfully"},g.info("Request branch initialized successfully",{requestId:v.id,branchName:_.branchName,title:v.title})}catch(e){g.warn("Failed to initialize request branch, will retry on first operation",{requestId:v.id,error:(0,i.getErrorMessage)(e)})}else"quick-edit"===l.type?g.info("Quick-edit request - skipping branch creation, will work directly on main",{requestId:v.id}):g.debug("No workspace manager available, branch creation deferred",{requestId:v.id})
|
|
4081
|
+
g.info("Request created successfully",{requestId:v.id,title:v.title,branchCreated:_.created,branchName:_.branchName})
|
|
4082
|
+
try{const e=c.getToolRecordClient()
|
|
4083
|
+
if(e){const t=await e.createToolRecord({requestId:v.id,projectId:f,type:"create-request",metadata:{status:"completed",timestamp:(new Date).toISOString(),requestType:v.type,requestTitle:v.title,requestDescription:v.description,criteriaCount:v.acceptanceCriteria.length,branchCreated:_.created,branchName:_.created?_.branchName:null},note:`Created request "${v.title}" of type ${v.type}${_.created?" with branch "+_.branchName:" - branch will be created on first file operation"}`})
|
|
4084
|
+
C=t?.id}}catch(e){g.warn("Failed to create tool record for request creation",{error:(0,i.getErrorMessage)(e),requestId:v.id})}p({success:!0,type:l.type,hasProjectId:!0}),g.info("Request created successfully",{requestId:v.id,title:v.title,type:v.type,projectId:f})
|
|
4085
|
+
const E=v.localId||v.id
|
|
4086
|
+
let q="pending_approval"===w?`Created Request ${E} (pending approval)`:"Created Request "+E
|
|
4087
|
+
return C&&(q+=`\n[RECORD:${C}]`),{content:[{type:"text",text:q}]}}catch(r){if(g.error("Failed to create request",{error:r instanceof Error?r.stack:r+"",args:e}),t.projectId)try{if(r instanceof Error&&(r.message.includes("Project is disabled")||r.message.includes("Project cannot accept new requests")||r.message.includes("disabled due to tier limits")))g.info("Skipping tool record creation for disabled project error",{projectId:t.projectId,error:r.message})
|
|
4088
|
+
else{const n=c.getToolRecordClient()
|
|
4089
|
+
n&&await n.createToolRecord({projectId:t.projectId,type:"create-request",metadata:{status:"failed",timestamp:(new Date).toISOString(),requestTitle:e.title,requestType:e.type,requestDescription:e.description?.substring(0,100)+(e.description?.length>100?"...":""),criteriaCount:e.acceptanceCriteria?e.acceptanceCriteria.length:0,branchCreated:!1,branchName:null,error:(0,i.getErrorMessage)(r),errorDetails:r instanceof Error?r.stack:r+""},note:"Failed to create request: "+e.title})}}catch(e){g.error("Failed to create failure record for request creation",{error:e instanceof Error?e.message:e+""})}if(p({success:!1,error:r instanceof Error?r.name:"unknown"}),r instanceof s.ZodError&&r.errors.length>0){const e=r.errors[0]
|
|
4099
4090
|
let t=e.message
|
|
4100
4091
|
return e.path.includes("acceptanceCriteria")&&(t=`Acceptance criteria: ${t}. Please provide a list of criteria descriptions.`),{content:[{type:"text",text:"Error: "+t}],isError:!0}}let n=(0,i.getErrorMessage)(r),o="Unable to create request. Please check your input and try again."
|
|
4101
4092
|
return(n.includes("Project cannot accept new requests")||n.includes("Project is inactive due to tier limits"))&&(o="This project is currently inactive due to tier limits. Only your oldest projects can accept new requests. Please use an active project or upgrade your tier for more simultaneous projects."),{content:[{type:"text",text:`Error: ${n}\n\n${o}`}],isError:!0}}}
|
|
4102
|
-
const r=t(6183),n=t(9860),o=t(2960),s=t(1569),i=t(8824),a=t(2478)
|
|
4093
|
+
const r=t(6183),n=t(9860),o=t(2960),s=t(1569),i=t(8824),a=t(2478)},7388(e,exports,t){var r=this&&this.__createBinding||(Object.create?function(e,t,r,n){void 0===n&&(n=r)
|
|
4103
4094
|
var o=Object.getOwnPropertyDescriptor(t,r)
|
|
4104
4095
|
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]}),n=this&&this.__exportStar||function(e,exports){for(var t in e)"default"===t||{}.hasOwnProperty.call(exports,t)||r(exports,e,t)}
|
|
4105
4096
|
Object.defineProperty(exports,"__esModule",{value:!0}),n(t(441),exports),n(t(270),exports)},7456(e,exports,t){var r,n=this&&this.__createBinding||(Object.create?function(e,t,r,n){void 0===n&&(n=r)
|
|
@@ -4113,7 +4104,7 @@ return o(t,e),t})
|
|
|
4113
4104
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleModifyFile=async function(e,t,r,n,o,s,h,g){const p=s.child({tool:"modify_file"})
|
|
4114
4105
|
try{const s=a.validateArgs(e,i.ModifyFileSchema),{taskId:u,operations:f,comment:m}=s
|
|
4115
4106
|
p.info("Processing modify-file operations",{taskId:u,operationCount:f.length,comment:m})
|
|
4116
|
-
const y=[],w=[],k=[],
|
|
4107
|
+
const y=[],w=[],k=[],b=[],I=[]
|
|
4117
4108
|
for(const e of f){const t={path:e.path,documentId:e.documentId}
|
|
4118
4109
|
switch(e.operationType){case"replace-string":y.push({...t,replacements:e.replaceString.replacements,mode:e.replaceString.mode})
|
|
4119
4110
|
break
|
|
@@ -4121,19 +4112,19 @@ case"insert-lines":w.push({...t,insertions:e.insertLines.insertions})
|
|
|
4121
4112
|
break
|
|
4122
4113
|
case"replace-lines":k.push({...t,replacements:e.replaceLines.replacements})
|
|
4123
4114
|
break
|
|
4124
|
-
case"delete-string":
|
|
4115
|
+
case"delete-string":b.push({...t,replacements:e.deleteString.patterns.map((e=>({old_str:e,new_str:""}))),mode:e.deleteString.mode||"all"})
|
|
4125
4116
|
break
|
|
4126
|
-
case"delete-lines":
|
|
4117
|
+
case"delete-lines":I.push({...t,lines:e.deleteLines.lines})}}const v=[]
|
|
4127
4118
|
if(y.length>0){p.info("Routing to replace-strings handler",{operationCount:y.length})
|
|
4128
4119
|
const e=await(0,c.handleReplaceStrings)({taskId:u,operations:y,comment:m+" [via modify-file: replace-string]"},t,r,n,o,p,h,g)
|
|
4129
4120
|
v.push({type:"replace-string",result:e})}if(w.length>0){p.info("Routing to insert-lines handler",{operationCount:w.length})
|
|
4130
4121
|
const e=await(0,l.handleInsertLines)({taskId:u,operations:w,comment:m+" [via modify-file: insert-lines]"},t,r,n,o,p,h,g)
|
|
4131
4122
|
v.push({type:"insert-lines",result:e})}if(k.length>0){p.info("Routing to replace-lines handler",{operationCount:k.length})
|
|
4132
4123
|
const e=await(0,d.handleReplaceLines)({taskId:u,operations:k,comment:m+" [via modify-file: replace-lines]"},t,r,n,o,p,h,g)
|
|
4133
|
-
v.push({type:"replace-lines",result:e})}if(
|
|
4134
|
-
const e=await(0,c.handleReplaceStrings)({taskId:u,operations:
|
|
4135
|
-
v.push({type:"delete-string",result:e})}if(
|
|
4136
|
-
const e=
|
|
4124
|
+
v.push({type:"replace-lines",result:e})}if(b.length>0){p.info("Routing delete-string to replace-strings handler",{operationCount:b.length})
|
|
4125
|
+
const e=await(0,c.handleReplaceStrings)({taskId:u,operations:b,comment:m+" [via modify-file: delete-string]"},t,r,n,o,p,h,g)
|
|
4126
|
+
v.push({type:"delete-string",result:e})}if(I.length>0){p.info("Processing delete-lines operations",{operationCount:I.length})
|
|
4127
|
+
const e=I.map((e=>({path:e.path,documentId:e.documentId,replacements:[{lines:e.lines,content:[]}]}))),s=await(0,d.handleReplaceLines)({taskId:u,operations:e,comment:m+" [via modify-file: delete-lines]"},t,r,n,o,p,h,g)
|
|
4137
4128
|
v.push({type:"delete-lines",result:s})}const C=v.some((e=>e.result.isError)),_=v.filter((e=>!e.result.isError)).length,E=v.filter((e=>e.result.isError)).length
|
|
4138
4129
|
let q="## Modify File Results\n\n"
|
|
4139
4130
|
q+="**Summary:**\n",q+=`- **Total operation types:** ${v.length}\n`,q+=`- **Successful:** ${_}\n`,q+=`- **Failed:** ${E}\n\n`
|
|
@@ -4285,55 +4276,9 @@ const i=await t.updateDocument(e.planId,o),a=i.localId||i.id
|
|
|
4285
4276
|
return s.info("Plan updated",{planId:a}),{content:[{type:"text",text:`\u2705 **Plan Updated**\n\n**Plan ID:** ${a}\n**Filename:** ${i.filename}\n**Updated:** `+new Date(i.updatedAt).toLocaleString()}]}}catch(e){return s.error("Failed to update plan",{error:(0,r.getErrorMessage)(e)}),{content:[{type:"text",text:"\u274c **Failed to update plan:** "+(0,r.getErrorMessage)(e)}],isError:!0}}}
|
|
4286
4277
|
const r=t(8824)},7613(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.def=void 0
|
|
4287
4278
|
const r=t(6183),n=t(9072)
|
|
4288
|
-
exports.def={name:"session_message_operations",description:'Inter-session messaging (questions and reports).\n\nOperations:\n\u2022 send - Send a message (type: "question" or "report")\n\u2022 reply - Reply to a message (answer a question or acknowledge a report). Type inferred from code prefix (Q-/R-).\n\u2022 list - List messages (filter by messageType, direction, status)\n\u2022 get - Get a message by its code\n\u2022 offer-handoff - Present the user with a choice to start building or keep planning\n\nMessage codes: Q-{id}-{seq} for questions, R-{id}-{seq} for reports.',schema:r.SessionMessageOperationsSchema,annotations:{title:"Session Message Operations",readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1},handler(e,t){return(0,n.handleSessionMessageOperations)(e,t.context,t.logger,t.metrics,t.apiClient??void 0)}}},7617(e,exports,t){function
|
|
4289
|
-
if(e.operation!==t.operation)return!1
|
|
4290
|
-
if("ask"===e.operation){let r=e.ask||e,n=t.ask||t
|
|
4291
|
-
if("string"==typeof n)try{n=JSON.parse(n)}catch{}if("string"==typeof r)try{r=JSON.parse(r)}catch{}const o=r?.questionContent?.question||r?.question,s=n?.questionContent?.question||n?.question
|
|
4292
|
-
return!(!o||!s)&&o===s}return!0}async function n(e,t,n,s){const i=n.child({component:"session-discovery"})
|
|
4293
|
-
try{const n=e.replace(/\/$/,"")+"/session",o=await fetch(n)
|
|
4294
|
-
if(!o.ok)return void i.warn("Failed to get session list",{status:o.status})
|
|
4295
|
-
const a=await o.json(),c=a.sort(((e,t)=>t.time.updated-e.time.updated)),l=e.replace(/\/$/,"")+"/session/status",d=await fetch(l)
|
|
4296
|
-
if(!d.ok)return void i.warn("Failed to get session status",{status:d.status})
|
|
4297
|
-
const u=await d.json(),h=c.filter((e=>"busy"===u[e.id]?.type)),g=5,p=c.slice(0,g),f=new Set(h.map((e=>e.id))),m=[...h,...p.filter((e=>!f.has(e.id)))]
|
|
4298
|
-
let y=null
|
|
4299
|
-
const w=[]
|
|
4300
|
-
for(const n of m)try{const o=`${e.replace(/\/$/,"")}/session/${n.id}/message?limit=50`,a=await fetch(o)
|
|
4301
|
-
if(!a.ok){i.debug("Failed to get messages for session",{sessionId:n.id,status:a.status})
|
|
4302
|
-
continue}const c=await a.json()
|
|
4303
|
-
let l=0
|
|
4304
|
-
for(const e of c){const o=(e.info||e).role||e.role,i=e.parts
|
|
4305
|
-
if("assistant"===o&&i)for(const o of i)if("tool"===o.type){const i=o.tool,a=o.state?.status,c=o.sessionID
|
|
4306
|
-
if(l++,i&&i.includes(t)){if("running"!==a&&"pending"!==a){w.push({sessionId:n.id,tool:i,reason:"wrong state: "+a})
|
|
4307
|
-
continue}const t=o.state?.input,l=o.state?.time?.start||0,d=c||n.id,u=Date.now(),h=l>0?u-l:0
|
|
4308
|
-
if(l>0&&h>6e4){w.push({sessionId:n.id,tool:i,reason:`stale: running for ${Math.round(h/1e3)}s`})
|
|
4309
|
-
continue}if(s&&t&&!r(s,t)){w.push({sessionId:n.id,tool:i,reason:"params mismatch"})
|
|
4310
|
-
continue}const g=e.info?.id
|
|
4311
|
-
y&&l<=y.startTime||(y={sessionId:d,messageId:g,startTime:l,toolName:i})}else i&&(i.includes("session-qa")||i.includes("subagent"))&&w.push({sessionId:n.id,tool:i,reason:"name mismatch: looking for "+t})}}}catch(e){i.debug("Error checking session",{sessionId:n.id,error:e+""})
|
|
4312
|
-
continue}return y?{sessionId:y.sessionId,messageId:y.messageId}:void i.warn("Session discovery failed - no matching tool call found",{toolName:t,totalSessions:a.length,busySessions:h.length,rejectionCount:w.length,rejections:w.slice(0,10)})}catch(e){return void i.warn("Failed to discover calling session",{error:(0,o.getErrorMessage)(e)})}}Object.defineProperty(exports,"__esModule",{value:!0}),exports.getServerUrl=async function(e,r){let n=process.env.OPENCODE_TUI_URL
|
|
4279
|
+
exports.def={name:"session_message_operations",description:'Inter-session messaging (questions and reports).\n\nOperations:\n\u2022 send - Send a message (type: "question" or "report")\n\u2022 reply - Reply to a message (answer a question or acknowledge a report). Type inferred from code prefix (Q-/R-).\n\u2022 list - List messages (filter by messageType, direction, status)\n\u2022 get - Get a message by its code\n\u2022 offer-handoff - Present the user with a choice to start building or keep planning\n\nMessage codes: Q-{id}-{seq} for questions, R-{id}-{seq} for reports.',schema:r.SessionMessageOperationsSchema,annotations:{title:"Session Message Operations",readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1},handler(e,t){return(0,n.handleSessionMessageOperations)(e,t.context,t.logger,t.metrics,t.apiClient??void 0)}}},7617(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.getServerUrl=async function(e,r){let n=process.env.OPENCODE_TUI_URL
|
|
4313
4280
|
if(!n)try{const{readFileSync:o}=await Promise.resolve().then(t.t.bind(t,9896,23)),{join:s}=await Promise.resolve().then(t.t.bind(t,6928,23)),i=o(s(e.basePath,".alchemy_lab","opencode.json"),"utf8"),a=JSON.parse(i)
|
|
4314
|
-
a.port&&(n="http://127.0.0.1:"+a.port,r.debug("Discovered OpenCode server URL from .alchemy_lab/opencode.json",{serverUrl:n}))}catch(e){r.debug("Could not read .alchemy_lab/opencode.json",{error:e instanceof Error?e.message:e+""})}return n},exports
|
|
4315
|
-
if(s)return t.info("Found calling session by tool",{sessionId:s.sessionId,messageId:s.messageId,toolName:r}),s}},exports.findMessageIdForTool=async function(e,t,r){try{const n=`${e.replace(/\/$/,"")}/session/${t}/message?limit=50`,o=await fetch(n)
|
|
4316
|
-
if(!o.ok)return
|
|
4317
|
-
const s=await o.json()
|
|
4318
|
-
let i,a=0
|
|
4319
|
-
for(const e of s){const t=(e.info||e).role||e.role,n=e.parts
|
|
4320
|
-
if("assistant"===t&&n)for(const t of n){if("tool"!==t.type)continue
|
|
4321
|
-
const n=t.tool,o=t.state?.status
|
|
4322
|
-
if(!n?.includes(r))continue
|
|
4323
|
-
if("running"!==o&&"pending"!==o)continue
|
|
4324
|
-
const s=t.state?.time?.start||0
|
|
4325
|
-
s>a&&(a=s,i=e.info?.id)}}return i}catch{return}},exports.discoverCallingSession=n,exports.discoverParentSessionId=async function(e,t){try{const r=e.replace(/\/$/,"")+"/session",n=await fetch(r)
|
|
4326
|
-
if(!n.ok)return void t.warn("Failed to get session list",{status:n.status})
|
|
4327
|
-
const o=[...await n.json()].sort(((e,t)=>t.time.updated-e.time.updated))
|
|
4328
|
-
if(0===o.length)return void t.warn("No sessions found")
|
|
4329
|
-
const s=e.replace(/\/$/,"")+"/session/status",i=await fetch(s)
|
|
4330
|
-
if(!i.ok)return void t.warn("Failed to get session status",{status:i.status})
|
|
4331
|
-
const a=await i.json(),c=o.filter((e=>"busy"===a[e.id]?.type))
|
|
4332
|
-
for(const r of c)try{const n=`${e.replace(/\/$/,"")}/session/${r.id}/message?limit=20`,o=await fetch(n)
|
|
4333
|
-
if(!o.ok)continue
|
|
4334
|
-
const s=await o.json()
|
|
4335
|
-
for(const e of s)if("assistant"===e.role&&e.parts)for(const n of e.parts)if("tool-invocation"===n.type&&"subagent_operations"===n.toolInvocation?.toolName&&"spawn"===n.toolInvocation?.args?.operation&&"pending"===n.toolInvocation?.state)return t.info("Found parent session via spawn tool call",{parentSessionId:r.id}),r.id}catch{continue}return c.length>0?(t.info("Fallback: using first busy session",{parentSessionId:c[0].id}),c[0].id):(t.info("Last resort: using most recent session",{parentSessionId:o[0].id}),o[0].id)}catch(e){t.warn("Failed to query OpenCode API for parent session",{error:e instanceof Error?e.message:e+""})}}
|
|
4336
|
-
const o=t(8824)},7621(e,exports,t){async function r(e,t,r){const n=r.startTimer("get_current_git_branch_duration")
|
|
4281
|
+
a.port&&(n="http://127.0.0.1:"+a.port,r.debug("Discovered OpenCode server URL from .alchemy_lab/opencode.json",{serverUrl:n}))}catch(e){r.debug("Could not read .alchemy_lab/opencode.json",{error:e instanceof Error?e.message:e+""})}return n}},7621(e,exports,t){async function r(e,t,r){const n=r.startTimer("get_current_git_branch_duration")
|
|
4337
4282
|
try{if(!e.git)return t.debug("No git repository available"),r.incrementCounter("get_current_git_branch_no_git",1),n({success:!1,reason:"no_git"}),null
|
|
4338
4283
|
const o=await u.getCurrentBranch(e.git,t,r)
|
|
4339
4284
|
return t.debug("Retrieved current git branch",{currentBranch:o}),r.incrementCounter("get_current_git_branch_success",1),n({success:!0}),o}catch(e){const o=(0,g.getErrorMessage)(e)
|
|
@@ -4427,7 +4372,9 @@ var n=t(2037)
|
|
|
4427
4372
|
Object.defineProperty(exports,"RequestLockManager",{enumerable:!0,get(){return n.RequestLockManager}})},7636(e,exports,t){var r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
4428
4373
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.MultiAgentWorkspaceManager=void 0
|
|
4429
4374
|
const n=r(t(6928)),o=t(3807),s=t(7634),i=t(8824),a=t(7075),c=t(1387),l=t(4968)
|
|
4430
|
-
|
|
4375
|
+
class d{getSession(e){const t=e||d.DEFAULT_SESSION
|
|
4376
|
+
let r=this.sessions.get(t)
|
|
4377
|
+
return r||(r={requestId:null,worktreePath:null,git:this.mainGit,readonlyBranchCheckDone:!1,workspaceKnownClean:!1,largeFileWarning:""},this.sessions.set(t,r)),r}constructor(e,t,r,n,o){this.basePath=e,this.logger=t,this.mainGit=r,this.metrics=n,this.workspaceStates=new Map,this.sessions=new Map,this.apiClient=o
|
|
4431
4378
|
const i=a.ConflictResolutionUtils.initializeDetectors(r,t)
|
|
4432
4379
|
this.conflictDetector=i.conflictDetector,this.safetyAnalyzer=i.safetyAnalyzer,this.conflictResolver=i.conflictResolver,this.worktreeManager=new s.WorktreeManager(e,t,n),this.gitAdapter=new l.WorktreeGitAdapter(r,this.worktreeManager,this.conflictDetector,t,n),this.requestProcessor=new c.WorkspaceRequestProcessor(this.gitAdapter,this.conflictDetector,this.safetyAnalyzer,this.conflictResolver,t),this.initializeWorktreeManager(),this.initializeFromEnv()}async initializeFromEnv(){const e=process.env.ALCHEMY_INITIAL_BRANCH
|
|
4433
4380
|
if(!e)return
|
|
@@ -4435,72 +4382,81 @@ const t=e.match(/^requests\/(.+)$/)
|
|
|
4435
4382
|
if(!t)return void this.logger.warn("ALCHEMY_INITIAL_BRANCH set but not a request branch",{initialBranch:e})
|
|
4436
4383
|
const r=t[1]
|
|
4437
4384
|
this.logger.info("ALCHEMY_INITIAL_BRANCH set, switching to worktree",{initialBranch:e,requestId:r})
|
|
4438
|
-
try{await this.ensureWorkspaceReady(r)
|
|
4385
|
+
try{await this.ensureWorkspaceReady(r)
|
|
4386
|
+
const e=this.getSession()
|
|
4387
|
+
e.readonlyBranchCheckDone=!0,this.logger.info("Successfully switched to worktree from ALCHEMY_INITIAL_BRANCH",{requestId:r,worktreePath:e.worktreePath})}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)
|
|
4439
4388
|
if(!n.isValid)throw Error("Invalid request ID: "+n.errors.join(", "))
|
|
4440
4389
|
const o=n.sanitized
|
|
4441
4390
|
try{this.workspaceStates.set(o,"initialized")
|
|
4442
4391
|
const t=Date.now()-r
|
|
4443
4392
|
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
|
|
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(),
|
|
4445
|
-
if(!
|
|
4446
|
-
const
|
|
4447
|
-
let
|
|
4448
|
-
if(this.apiClient)try{const e=this.apiClient.getRequestClient(),t=await e.getRequest(
|
|
4449
|
-
if(t&&"quick-edit"===t.type){
|
|
4450
|
-
const e="requests/"+
|
|
4451
|
-
return(await this.mainGit.branch()).all.includes(e)?(await this.mainGit.checkout(e),this.logger.info("Checked out existing quick-edit branch in main repo",{requestId:
|
|
4452
|
-
const e=this.worktreeManager.getWorktreeInfo(
|
|
4453
|
-
if(e&&e.worktreePath)return
|
|
4454
|
-
const
|
|
4455
|
-
if(!
|
|
4456
|
-
if(
|
|
4457
|
-
try{const e=(0,o.simpleGit)(
|
|
4458
|
-
s
|
|
4459
|
-
this.metrics.recordValue("workspace.ensure_ready",s),a.WorkspaceLogging.logOperation(this.logger,"info","Workspace is ready with worktree",e,"multi-agent","ensureWorkspaceReady",{worktreePath:
|
|
4460
|
-
throw this.metrics.recordValue("workspace.ensure_ready",
|
|
4461
|
-
|
|
4462
|
-
|
|
4463
|
-
|
|
4464
|
-
|
|
4465
|
-
|
|
4466
|
-
|
|
4467
|
-
|
|
4468
|
-
return this.metrics?.recordValue("workspace_switch_duration",
|
|
4469
|
-
a.WorkspaceLogging.logOperation(this.logger,"
|
|
4470
|
-
|
|
4471
|
-
|
|
4472
|
-
|
|
4473
|
-
|
|
4474
|
-
|
|
4475
|
-
|
|
4476
|
-
|
|
4477
|
-
|
|
4478
|
-
|
|
4393
|
+
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,t){const r=this.getSession(t),n=Date.now(),s=a.WorkspaceValidation.validateRequestId(e)
|
|
4394
|
+
if(!s.isValid)throw Error("Invalid request ID: "+s.errors.join(", "))
|
|
4395
|
+
const c=s.sanitized
|
|
4396
|
+
let l=!1
|
|
4397
|
+
if(this.apiClient)try{const e=this.apiClient.getRequestClient(),t=await e.getRequest(c)
|
|
4398
|
+
if(t&&"quick-edit"===t.type){l=!0,this.logger.info("Quick-edit request detected - checking out branch in main repo (no worktree)",{requestId:c,requestType:t.type})
|
|
4399
|
+
const e="requests/"+c
|
|
4400
|
+
return(await this.mainGit.branch()).all.includes(e)?(await this.mainGit.checkout(e),this.logger.info("Checked out existing quick-edit branch in main repo",{requestId:c,branchName:e})):(await this.mainGit.checkoutLocalBranch(e),this.logger.info("Created and checked out quick-edit branch in main repo",{requestId:c,branchName:e})),r.requestId=c,r.worktreePath=null,r.git=this.mainGit,void this.workspaceStates.set(c,"ready")}}catch(e){this.logger.warn("Failed to check request type, proceeding with normal workflow",{requestId:c,error:(0,i.getErrorMessage)(e)})}if("ready"!==this.workspaceStates.get(c)||r.requestId!==c){if("ready"===this.workspaceStates.get(c)&&r.requestId!==c){this.logger.info("Workspace ready but not in correct context, switching to it",{requestId:c,currentRequestId:r.requestId,reason:"context_mismatch"})
|
|
4401
|
+
const e=this.worktreeManager.getWorktreeInfo(c)
|
|
4402
|
+
if(e&&e.worktreePath)return r.requestId=c,r.worktreePath=e.worktreePath,r.git=(0,o.simpleGit)(e.worktreePath),void this.logger.info("Switched to existing ready workspace",{requestId:c,worktreePath:e.worktreePath})}try{a.WorkspaceLogging.logOperation(this.logger,"info","Ensuring workspace ready by creating/switching to worktree",e,"multi-agent","ensureWorkspaceReady",{currentState:this.workspaceStates.get(c)||"not-initialized",currentRequestId:r.requestId,architecture:"hybrid-creation"})
|
|
4403
|
+
const t=await this.worktreeManager.ensureWorktreeExists(c,void 0,void 0)
|
|
4404
|
+
if(!t.success)throw Error("Failed to create worktree: "+t.message)
|
|
4405
|
+
if(r.requestId=c,r.worktreePath=t.worktreePath,r.git=(0,o.simpleGit)(t.worktreePath),this.workspaceStates.set(c,"ready"),t.created){r.workspaceKnownClean=!0
|
|
4406
|
+
try{const e=(0,o.simpleGit)(t.worktreePath),r=(await this.mainGit.branch()).all.includes("main")?"main":"master",n=await this.mainGit.revparse([r]),s=await e.revparse(["HEAD"])
|
|
4407
|
+
n!==s&&0===(await e.log({from:r,to:"HEAD"})).total&&(await e.rebase([r]),this.logger.info("Rebased fresh request branch onto latest main",{requestId:c,mainHead:n.substring(0,8),previousHead:s.substring(0,8)}))}catch(e){this.logger.warn("Failed to rebase onto main, proceeding with existing branch",{requestId:c,error:(0,i.getErrorMessage)(e)})}}const s=Date.now()-n
|
|
4408
|
+
this.metrics.recordValue("workspace.ensure_ready",s),a.WorkspaceLogging.logOperation(this.logger,"info","Workspace is ready with worktree",e,"multi-agent","ensureWorkspaceReady",{worktreePath:t.worktreePath,branchName:t.branchName,duration:s,architecture:"hybrid-creation"})}catch(t){const r=Date.now()-n
|
|
4409
|
+
throw this.metrics.recordValue("workspace.ensure_ready",r),a.WorkspaceLogging.logOperation(this.logger,"error","Failed to ensure workspace ready",e,"multi-agent","ensureWorkspaceReady",{error:(0,i.getErrorMessage)(t),duration:r}),t}}else this.logger.debug("Workspace already ready and in correct context",{requestId:c,worktreePath:r.worktreePath})}async switchToRequest(e,t){const r=t?.sessionId,n=this.getSession(r)
|
|
4410
|
+
this.logger.debug("switchToRequest called",{requestId:e,options:t,sessionId:r})
|
|
4411
|
+
const o=Date.now(),s=this.getCurrentContext(r)
|
|
4412
|
+
if(this.logger.debug("previousContext",{previousContext:s}),t?.isCompleted&&n.requestId!==e)return this.logger.debug("Completed request detected - using simple checkout instead of worktree"),await this.switchToCompletedRequest(e,o,s)
|
|
4413
|
+
const c=a.WorkspaceValidation.validateRequestId(e)
|
|
4414
|
+
if(!c.isValid){const t="Invalid request ID: "+c.errors.join(", ")
|
|
4415
|
+
return a.WorkspaceLogging.logOperation(this.logger,"error",t,e,"multi-agent","switchToRequest"),{success:!1,message:t,previousContext:s,newContext:s}}try{this.logger.debug("About to call ensureWorkspaceReady",{requestId:c.sanitized}),await this.ensureWorkspaceReady(c.sanitized,r),this.logger.debug("ensureWorkspaceReady completed",{currentRequestId:n.requestId,currentWorktreePath:n.worktreePath})
|
|
4416
|
+
const t=Date.now()-o
|
|
4417
|
+
return this.metrics?.recordValue("workspace_switch_duration",t),a.WorkspaceLogging.logOperation(this.logger,"info","Switched to worktree for request",e,"multi-agent","switchToRequest",{worktreePath:n.worktreePath,duration:t}),{success:!0,message:"Switched to worktree for request: "+e,previousContext:s,newContext:this.getCurrentContext(r),worktreePath:n.worktreePath}}catch(t){const r=Date.now()-o
|
|
4418
|
+
return this.metrics?.recordValue("workspace_switch_duration",r),a.WorkspaceLogging.logOperation(this.logger,"error","Failed to switch to request",e,"multi-agent","switchToRequest",{error:(0,i.getErrorMessage)(t),duration:r}),{success:!1,message:"Failed to switch to request: "+(0,i.getErrorMessage)(t),previousContext:s,newContext:s}}}async switchToCompletedRequest(e,t,r){try{const n="requests/"+e
|
|
4419
|
+
a.WorkspaceLogging.logOperation(this.logger,"info","Switching to completed request (no worktree)",e,"multi-agent","switchToCompletedRequest",{branchName:n}),await this.mainGit.checkout(n)
|
|
4420
|
+
const o=this.getSession()
|
|
4421
|
+
o.requestId=e,o.worktreePath=null,o.git=this.mainGit
|
|
4422
|
+
const s=Date.now()-t
|
|
4423
|
+
return this.metrics?.recordValue("workspace_switch_duration",s),a.WorkspaceLogging.logOperation(this.logger,"info","Successfully switched to completed request branch",e,"multi-agent","switchToCompletedRequest",{branchName:n,duration:s,worktree:!1}),{success:!0,message:`Switched to completed request branch: ${n} (no worktree)`,previousContext:r,newContext:this.getCurrentContext()}}catch(n){const o=Date.now()-t
|
|
4424
|
+
return this.metrics?.recordValue("workspace_switch_duration",o),a.WorkspaceLogging.logOperation(this.logger,"error","Failed to switch to completed request",e,"multi-agent","switchToCompletedRequest",{error:(0,i.getErrorMessage)(n),duration:o}),{success:!1,message:"Failed to switch to completed request: "+(0,i.getErrorMessage)(n),previousContext:r,newContext:r}}}async switchToMain(e){const t=this.getSession(e),r=this.getCurrentContext(e)
|
|
4425
|
+
return t.requestId=null,t.worktreePath=null,t.git=this.mainGit,this.logger.info("Switched to main repository context"),{success:!0,message:"Switched to main repository",previousContext:r,newContext:this.getCurrentContext(e)}}async commitChanges(e,t,r){const n=this.getSession(r),o=Date.now()
|
|
4426
|
+
if(!n.requestId||!n.worktreePath)throw new a.ConflictDetectionError("No active request context for commit","multi-agent-commit",[])
|
|
4427
|
+
try{t&&t.length>0?await n.git.add(t):await n.git.add("."),await n.git.commit(e)
|
|
4428
|
+
const r=await n.git.revparse(["HEAD"]),s=Date.now()-o
|
|
4429
|
+
return this.metrics?.recordValue("workspace_commit_duration",s),this.logger.info("Successfully committed changes in worktree",{requestId:n.requestId,worktreePath:n.worktreePath,message:e,commitHash:r.substring(0,8),filesCount:t?.length||"all",duration:s}),{hash:r,message:e,files:t||[]}}catch(t){const r=Date.now()-o
|
|
4430
|
+
throw this.metrics?.recordValue("workspace_commit_duration",r),this.logger.error("Failed to commit changes in worktree",{requestId:n.requestId,worktreePath:n.worktreePath,message:e,error:(0,i.getErrorMessage)(t),duration:r}),new a.ConflictDetectionError("Failed to commit changes: "+(0,i.getErrorMessage)(t),"multi-agent-commit",[])}}async completeRequest(e,t,r){const n=Date.now()
|
|
4479
4431
|
try{a.WorkspaceLogging.logOperation(this.logger,"info","Starting request completion (refactored)",e,"multi-agent","completeRequest",{requestTitle:t,skipConflictDetection:r?.skipConflictDetection||!1,architecture:"shared-processor"})
|
|
4480
4432
|
const o=await this.requestProcessor.completeRequest(e,t,{skipConflictDetection:r?.skipConflictDetection||!1}),s=Date.now()-n
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
throw this.
|
|
4433
|
+
this.metrics?.recordValue("workspace_complete_duration",s),this.metrics?.incrementCounter("workspace_complete_success",1)
|
|
4434
|
+
for(const[t,r]of this.sessions)r.requestId===e&&(r.requestId=null,r.worktreePath=null,r.git=this.mainGit)
|
|
4435
|
+
return a.WorkspaceLogging.logOperation(this.logger,"info","Request completion successful (refactored)",e,"multi-agent","completeRequest",{mergeCommitHash:o.mergeCommitHash.substring(0,8),mergedFiles:o.mergedFiles?.length||0,cleanedUp:o.cleanedUp,wasAutoMerged:o.autoMergeInfo?.wasAutoMerged,strategy:o.autoMergeInfo?.strategy,duration:s,architecture:"shared-processor"}),o}catch(t){const r=Date.now()-n
|
|
4436
|
+
throw this.metrics?.recordValue("workspace_complete_duration",r),this.metrics?.incrementCounter("workspace_complete_error",1),a.WorkspaceLogging.logOperation(this.logger,"error","Request completion failed (refactored)",e,"multi-agent","completeRequest",{error:(0,i.getErrorMessage)(t),duration:r,architecture:"shared-processor"}),t}}resolveFilePath(e,t){const r=this.getSession(t)
|
|
4437
|
+
if(r.worktreePath)return this.logger.debug("Resolving file path in worktree context",{relativePath:e,worktreePath:r.worktreePath,requestId:r.requestId}),n.default.resolve(r.worktreePath,e)
|
|
4438
|
+
const o=`Cannot resolve file path in multi-agent mode without request context. Current state: requestId=${r.requestId}, worktreePath=${r.worktreePath}. Ensure you switch to a request workspace before performing file operations.`
|
|
4439
|
+
throw this.logger.error("Unsafe file path resolution attempt in multi-agent mode",{relativePath:e,currentRequestId:r.requestId,currentWorktreePath:r.worktreePath,basePath:this.basePath,action:"preventing_fallback_to_main"}),Error(o)}resolveMainBranchFilePath(e){return this.logger.debug("Resolving file path in main branch context",{relativePath:e,basePath:this.basePath,context:"explicit_main_branch_operation"}),n.default.resolve(this.basePath,e)}async createCommit(e,t,r){return await this.commitChanges(e,t,r)}async cancelRequest(e){const t=a.WorkspaceValidation.validateRequestId(e)
|
|
4485
4440
|
if(!t.isValid)throw Error("Invalid request ID: "+t.errors.join(", "))
|
|
4486
4441
|
const r=t.sanitized
|
|
4487
|
-
try{this.
|
|
4442
|
+
try{for(const[e,t]of this.sessions)t.requestId===r&&(t.requestId=null,t.worktreePath=null,t.git=this.mainGit)
|
|
4488
4443
|
const e=await this.worktreeManager.removeWorktree(r,!1)
|
|
4489
4444
|
if(!e.success)throw Error(e.message||"Failed to remove worktree")
|
|
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:
|
|
4491
|
-
return this.logger.debug("getCurrentContext returning",{context:e}),
|
|
4445
|
+
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(e){const t=this.getSession(e),r={requestId:t.requestId,basePath:t.worktreePath||this.basePath,branchName:t.requestId?"requests/"+t.requestId:"main",isMainBranch:!t.requestId,mode:"multi-agent"}
|
|
4446
|
+
return this.logger.debug("getCurrentContext returning",{context:r,sessionId:e}),r}resetCurrentContext(e){const t=this.getSession(e)
|
|
4447
|
+
t.requestId&&this.logger.info("Resetting workspace context (session switch)",{prevRequestId:t.requestId,prevWorktreePath:t.worktreePath,sessionId:e}),t.requestId=null,t.worktreePath=null,t.git=this.mainGit,t.readonlyBranchCheckDone=!1}async getWorkspaceInfo(e){try{const t=a.WorkspaceValidation.validateRequestId(e)
|
|
4492
4448
|
if(!t.isValid)return null
|
|
4493
4449
|
const r=t.sanitized,n=await this.getWorktreeInfo(r)
|
|
4494
|
-
return n?{requestId:r,path:n.worktreePath,branchName:n.branchName,isActive:this.
|
|
4495
|
-
return t?t[1]:null}convertWorktreeInfoToWorkspaceInfo(e){return{requestId:e.requestId,path:e.worktreePath,branchName:e.branchName,isActive:this.
|
|
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.
|
|
4497
|
-
|
|
4498
|
-
try{const{sessionIdentity:e}=await Promise.resolve().then(t.bind(t,6688)),r=e.
|
|
4499
|
-
if(r
|
|
4500
|
-
if(
|
|
4501
|
-
if(s){const e=s.match(/^requests\/(.+)$/)
|
|
4450
|
+
return n?{requestId:r,path:n.worktreePath,branchName:n.branchName,isActive:this.isActiveForAnySession(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\/(.+)$/)
|
|
4451
|
+
return t?t[1]:null}convertWorktreeInfoToWorkspaceInfo(e){return{requestId:e.requestId,path:e.worktreePath,branchName:e.branchName,isActive:this.isActiveForAnySession(e.requestId),created:e.created,lastAccessed:e.lastAccessed}}async getWorktreeInfo(e){try{const t=e.replace(/[^a-zA-Z0-9_-]/g,"_")
|
|
4452
|
+
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(e){return this.getSession(e).git}get readonlyBranchCheckDone(){return this.getSession().readonlyBranchCheckDone}set readonlyBranchCheckDone(e){this.getSession().readonlyBranchCheckDone=e}get workspaceKnownClean(){return this.getSession().workspaceKnownClean}set workspaceKnownClean(e){this.getSession().workspaceKnownClean=e}get largeFileWarning(){return this.getSession().largeFileWarning}set largeFileWarning(e){this.getSession().largeFileWarning=e}async ensureReadonlyBranchIfNeeded(e,r,n,o){const s=this.getSession(o)
|
|
4453
|
+
if(s.readonlyBranchCheckDone)return
|
|
4454
|
+
if(s.readonlyBranchCheckDone=!0,o&&n)try{const{sessionIdentity:e}=await Promise.resolve().then(t.bind(t,6688)),r=await e.getSessionRequestId(n,this.logger,o)
|
|
4455
|
+
if(r)return await this.ensureWorkspaceReady(r,o),void this.logger.info("ensureReadonlyBranchIfNeeded: workspace ready from session DB lookup",{requestId:r,sessionId:o})}catch(e){this.logger.warn("ensureReadonlyBranchIfNeeded: session DB lookup failed, falling back to env var",{error:(0,i.getErrorMessage)(e)})}const a=process.env.ALCHEMY_INITIAL_BRANCH
|
|
4456
|
+
if(a){const e=a.match(/^requests\/(.+)$/)
|
|
4502
4457
|
if(e){const t=e[1]
|
|
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)})}}}}
|
|
4458
|
+
try{await this.ensureWorkspaceReady(t,o),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)})}}}}isActiveForAnySession(e){for(const[,t]of this.sessions)if(t.requestId===e)return!0
|
|
4459
|
+
return!1}async cleanup(){this.logger.info("Cleaning up multi-agent workspace manager"),this.sessions.clear()}}exports.MultiAgentWorkspaceManager=d,d.DEFAULT_SESSION="__default__"},7645(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.ConnectionAwareClient=void 0
|
|
4504
4460
|
const r=t(4192),n=t(7163)
|
|
4505
4461
|
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)+"..."})
|
|
4506
4462
|
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
|
|
@@ -4518,20 +4474,20 @@ return o(t,e),t})
|
|
|
4518
4474
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleManageFiles=async function(e,t,r,n,o,s,g,p,f){const m=g.child({tool:"manage_files"})
|
|
4519
4475
|
try{const h=a.validateArgs(e,i.ManageFilesSchema),{taskId:g,operations:y,comment:w}=h
|
|
4520
4476
|
m.info("Processing manage-files operations",{taskId:g,operationCount:y.length,comment:w})
|
|
4521
|
-
const k=[],
|
|
4477
|
+
const k=[],b=[],I=[],v=[]
|
|
4522
4478
|
for(const e of y)switch(e.operationType){case"create-directory":k.push({path:e.createDirectory.path})
|
|
4523
4479
|
break
|
|
4524
|
-
case"move-files":for(const t of e.moveFiles.moves)
|
|
4480
|
+
case"move-files":for(const t of e.moveFiles.moves)b.push(t)
|
|
4525
4481
|
break
|
|
4526
|
-
case"delete-files":
|
|
4482
|
+
case"delete-files":I.push(...e.deleteFiles.targets)
|
|
4527
4483
|
break
|
|
4528
4484
|
case"get-file-info":v.push({path:e.getFileInfo.path})}const C=[]
|
|
4529
4485
|
for(const e of k){m.info("Routing to create-directory handler",{path:e.path})
|
|
4530
4486
|
const s=await(0,c.handleCreateDirectory)({taskId:g,path:e.path,comment:w+" [via manage-files: create-directory]"},t,r,n,o,m,p,f)
|
|
4531
|
-
C.push({type:"create-directory",result:s})}if(
|
|
4532
|
-
const e=await(0,l.handleMoveFiles)({taskId:g,operations:
|
|
4533
|
-
C.push({type:"move-files",result:e})}if(
|
|
4534
|
-
const e=await(0,u.handleDeleteFiles)({taskId:g,operations:
|
|
4487
|
+
C.push({type:"create-directory",result:s})}if(b.length>0){m.info("Routing to move-files handler",{operationCount:b.length})
|
|
4488
|
+
const e=await(0,l.handleMoveFiles)({taskId:g,operations:b,comment:w+" [via manage-files: move-files]"},t,r,n,o,m,p,f)
|
|
4489
|
+
C.push({type:"move-files",result:e})}if(I.length>0){m.info("Routing to delete-files handler",{operationCount:I.length})
|
|
4490
|
+
const e=await(0,u.handleDeleteFiles)({taskId:g,operations:I,comment:w+" [via manage-files: delete-files]"},t,s,m,p,f)
|
|
4535
4491
|
C.push({type:"delete-files",result:e})}for(const e of v){m.info("Routing to get-file-info handler",{path:e.path})
|
|
4536
4492
|
const r=await(0,d.handleGetFileInfo)({path:e.path},t,m,p)
|
|
4537
4493
|
C.push({type:"get-file-info",result:r})}const _=C.some((e=>e.result.isError)),E=C.filter((e=>!e.result.isError)).length,q=C.filter((e=>e.result.isError)).length
|
|
@@ -4621,19 +4577,19 @@ const n=r(t(6982))
|
|
|
4621
4577
|
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=n.default.randomBytes(4).toString("hex")
|
|
4622
4578
|
return o.fromString(`prj_${e}_${t}`)},fromString(e){return this.isValid(e)?new o(e):null},isValid(e){if(!e||"string"!=typeof e||5>e.length||!e.startsWith("prj"))return!1
|
|
4623
4579
|
if(e.includes("_")){const t=e.split("_")
|
|
4624
|
-
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)},8035(e,exports,t){function r(e,t,r){try{const n=`[${(new Date).toISOString()}] [detached-subagent] ${t}${r?" "+JSON.stringify(r):""}\n`,o=(0,a.join)(e||process.cwd(),".alchemy_lab","spawn-debug.log");(0,i.appendFileSync)(o,n)}catch{}}function n(e){const{agent:t,prompt:n,cwd:
|
|
4580
|
+
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)},8035(e,exports,t){function r(e,t,r){try{const n=`[${(new Date).toISOString()}] [detached-subagent] ${t}${r?" "+JSON.stringify(r):""}\n`,o=(0,a.join)(e||process.cwd(),".alchemy_lab","spawn-debug.log");(0,i.appendFileSync)(o,n)}catch{}}function n(e){const{agent:t,prompt:n,cwd:l,parentServerUrl:d,parentSessionId:u,sessionId:h,model:g,initialBranch:p,serverUrl:f,onSpawn:m,onError:y}=e
|
|
4625
4581
|
try{const s={...process.env}
|
|
4626
|
-
|
|
4627
|
-
const
|
|
4628
|
-
let
|
|
4629
|
-
if(s.ALCHEMY_SESSION_TAG=`mcp-${
|
|
4630
|
-
e>0?
|
|
4631
|
-
const
|
|
4632
|
-
let
|
|
4633
|
-
try{
|
|
4634
|
-
return
|
|
4635
|
-
return
|
|
4636
|
-
const o=t(5317),s=t(8824),i=t(9896),a=t(6928)},8037(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleListRequests=async function(e,t,i,a,c){const l=a.child({tool:"list_requests"}),d=c.startTimer("tool_execution_time")
|
|
4582
|
+
d&&(s.OPENCODE_PARENT_SERVER=d),p&&(s.ALCHEMY_INITIAL_BRANCH=p),e.allowParallel&&(s.ALCHEMY_ALLOW_PARALLEL="1")
|
|
4583
|
+
const u=new Date,y=`${(u.getHours()+"").padStart(2,"0")}${(u.getMinutes()+"").padStart(2,"0")}${(u.getSeconds()+"").padStart(2,"0")}`,w=Math.random().toString(36).substring(2,7)
|
|
4584
|
+
let k
|
|
4585
|
+
if(s.ALCHEMY_SESSION_TAG=`mcp-${y}-${w}`,r(l,"Spawn env setup",{agent:t,initialBranch:p||"none",hasParentServer:!!d,sessionId:h||"new",attachMode:!!f}),k=f&&h&&n?["run","--attach",f,"--session",h,"--agent",t,n]:h&&n?["run","--session",h,"--agent",t,n]:n?["run","--agent",t,n]:["run","--agent",t],g){const e=k.findIndex((e=>e===n))
|
|
4586
|
+
e>0?k.splice(e,0,"--model",g):k.push("--model",g)}r(l,"Spawning opencode",{args:k.map((e=>e===n?`[prompt:${e.length}chars]`:e)),model:g||"not specified",promptLength:n?.length,promptPreview:n?.slice(0,100),cwd:l,hasSessionId:!!h,hasParentServerUrl:!!d})
|
|
4587
|
+
const b=(0,a.join)(l||process.cwd(),".alchemy_lab"),I=(0,a.join)(b,"spawn-stderr.log")
|
|
4588
|
+
let v
|
|
4589
|
+
try{v=(0,i.openSync)(I,"a")}catch{}const C=(0,c.resolveRunCommand)(),_=(0,o.spawn)(C.command,[...C.prependArgs,...k],{detached:!0,stdio:["ignore","ignore",v??"ignore"],cwd:l||process.cwd(),env:s})
|
|
4590
|
+
return _.unref(),m&&m(_.pid),{success:!0,pid:_.pid}}catch(e){const t=(0,s.getErrorMessage)(e)
|
|
4591
|
+
return y&&e instanceof Error&&y(e),{success:!1,error:t}}}Object.defineProperty(exports,"__esModule",{value:!0}),exports.spawnDetachedSubagent=n,exports.spawnJournalSubagent=function(e,t,r,o){return n({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:r,parentServerUrl:o})},exports.spawnWorkSubagent=function(e,t,r){return n({agent:"work",prompt:e,cwd:t,parentServerUrl:r})}
|
|
4592
|
+
const o=t(5317),s=t(8824),i=t(9896),a=t(6928),c=t(9068)},8037(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleListRequests=async function(e,t,i,a,c){const l=a.child({tool:"list_requests"}),d=c.startTimer("tool_execution_time")
|
|
4637
4593
|
try{const{filters:s={}}=e,a=["open","in_progress","ready_for_review","completed","canceled","reverted"]
|
|
4638
4594
|
if(s.status&&!a.includes(s.status))throw new r.ValidationError(`Invalid status: ${s.status}. Must be one of: ${a.join(", ")}`)
|
|
4639
4595
|
if(void 0!==s.limit&&1>s.limit)throw new r.ValidationError("Limit must be at least 1")
|
|
@@ -4686,31 +4642,31 @@ if(null!=e)for(var s=r(e),i=0;i<s.length;i++)"default"!==s[i]&&n(t,e,s[i])
|
|
|
4686
4642
|
return o(t,e),t}),i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
4687
4643
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleCreateDirectory=async function(e,t,r,n,o,s,i,p){const f=s.child({tool:"create_directory"}),m=Date.now()
|
|
4688
4644
|
let y,w,k=d.FileOperationPhase.VALIDATION
|
|
4689
|
-
const
|
|
4645
|
+
const b={toolName:"create-directory",operationName:"create",fileOperationPhase:d.FileOperationPhase.FILE_WRITE,recordType:"create-directory",metricsPrefix:"create_directory",successMessage:"Successfully created directory {path}",failureMessage:"Failed to create directory {path}"}
|
|
4690
4646
|
try{const s=d.validateArgs(e,l.CreateDirectorySchema),{taskId:u,path:h,comment:g}=s
|
|
4691
|
-
f.info("Creating directory: "+h,{taskId:u,path:h,comment:g}),d.validateTaskIdFormat(u,f,i,
|
|
4692
|
-
const{normalizedPath:
|
|
4647
|
+
f.info("Creating directory: "+h,{taskId:u,path:h,comment:g}),d.validateTaskIdFormat(u,f,i,b.metricsPrefix),t.getCurrentBranchContext&&await t.getCurrentBranchContext()
|
|
4648
|
+
const{normalizedPath:I,fullPath:v}=d.validateAndNormalizePath(h,t)
|
|
4693
4649
|
k=d.FileOperationPhase.TASK_VALIDATION,i.incrementCounter("create_directory_phase",1,{phase:k})
|
|
4694
|
-
const C=await d.validateTaskId(u,
|
|
4695
|
-
q.taskPromoted&&f.info(`Auto-promoted task ${u} (${C.title||"Untitled"}) to in_progress for file operation`,{taskId:u,taskTitle:C.title,previousStatus:C.status,newStatus:q.newTaskStatus,path:
|
|
4696
|
-
const S=await d.ensureCorrectWorkspaceContext({taskPromoted:q.taskPromoted,requestId:_,context:t,operation:"create-directory",logger:f,metrics:i,metricsPrefix:
|
|
4650
|
+
const C=await d.validateTaskId(u,I,r,f,i,b.metricsPrefix),_=C?.requestId,E=await d.validateWorkItemStates(u,I,r,o,t,f,i,b.metricsPrefix),q=await d.autoPromoteTaskStatus(u,C.status,_,E.request?.status,I,r,o,f,i,b.metricsPrefix)
|
|
4651
|
+
q.taskPromoted&&f.info(`Auto-promoted task ${u} (${C.title||"Untitled"}) to in_progress for file operation`,{taskId:u,taskTitle:C.title,previousStatus:C.status,newStatus:q.newTaskStatus,path:I}),q.requestPromoted&&f.info(`Auto-promoted request ${_} to in_progress for file operation`,{requestId:_,previousStatus:E.request?.status,newStatus:q.newRequestStatus,triggeringTaskId:u})
|
|
4652
|
+
const S=await d.ensureCorrectWorkspaceContext({taskPromoted:q.taskPromoted,requestId:_,context:t,operation:"create-directory",logger:f,metrics:i,metricsPrefix:b.metricsPrefix})
|
|
4697
4653
|
if(!S.success){if(S.isLockConflict)return{content:[{type:"text",text:"\u274c "+S.error}],isError:!0}
|
|
4698
4654
|
throw Error(S.error)}let T=!1
|
|
4699
4655
|
try{T=(await a.default.stat(v)).isDirectory()}catch{T=!1}k=d.FileOperationPhase.RECORD_CREATION,i.incrementCounter("create_directory_phase",1,{phase:k})
|
|
4700
|
-
const{toolRecordId:P,localToolRecordId:M}=await d.createFileOperationRecords(u,_,t.projectId,
|
|
4701
|
-
y=P,w=P,k=
|
|
4702
|
-
let
|
|
4703
|
-
if(!T){await a.default.mkdir(v,{recursive:!0}),f.info("Successfully created directory "+
|
|
4656
|
+
const{toolRecordId:P,localToolRecordId:M}=await d.createFileOperationRecords(u,_,t.projectId,b.recordType,I,{directoryExists:T,userComment:g},r,n,f,i,b.metricsPrefix,p)
|
|
4657
|
+
y=P,w=P,k=b.fileOperationPhase,i.incrementCounter("create_directory_phase",1,{phase:k})
|
|
4658
|
+
let j=T
|
|
4659
|
+
if(!T){await a.default.mkdir(v,{recursive:!0}),f.info("Successfully created directory "+I)
|
|
4704
4660
|
try{const e=c.default.join(v,".gitkeep")
|
|
4705
|
-
await a.default.writeFile(e,"# This file makes the directory trackable by Git\n"),
|
|
4706
|
-
i.recordValue("create_directory_time",
|
|
4707
|
-
const x=`Create directory: ${
|
|
4708
|
-
k=d.FileOperationPhase.RECORD_UPDATE_SUCCESS,i.incrementCounter("create_directory_phase",1,{phase:k}),await d.updateFileOperationRecords(u,y,w,b
|
|
4661
|
+
await a.default.writeFile(e,"# This file makes the directory trackable by Git\n"),j=!0,f.info("Created .gitkeep file for Git tracking")}catch(e){f.warn("Failed to create .gitkeep file",{error:e instanceof Error?e.message:e+""}),j=!1}}const R=Date.now()-m
|
|
4662
|
+
i.recordValue("create_directory_time",R),i.incrementCounter("create_directory_success",1),k=d.FileOperationPhase.GIT_COMMIT,i.incrementCounter("create_directory_phase",1,{phase:k})
|
|
4663
|
+
const x=`Create directory: ${I} - ${g||"Create directory"}`,O=!T&&j?I+"/.gitkeep":I,A=await d.commitToGit(u,O,P,M,x,t,f,i,b.metricsPrefix)
|
|
4664
|
+
k=d.FileOperationPhase.RECORD_UPDATE_SUCCESS,i.incrementCounter("create_directory_phase",1,{phase:k}),await d.updateFileOperationRecords(u,y,w,I,b.recordType,`Successfully ${T?"verified":"created"} directory: ${I}`,{status:"completed",commitHash:A.commitHash,previousCommitHash:A.previousCommitHash,directoryExists:T,isDirectory:!0,userComment:g},`Successfully ${T?"verified":"created"} directory: ${I}`,r,n,f,i,b.metricsPrefix)
|
|
4709
4665
|
const D=t.getCurrentBranchContext?await t.getCurrentBranchContext():{branch:null,requestId:null,isMain:!0}
|
|
4710
4666
|
return{content:[{type:"text",text:T?"Directory already exists":`Successfully created directory${A.commitHash?"\nCommit: "+A.commitHash.substring(0,8):""}${D.requestId?"\nBranch: "+D.requestId:""}${S.lockAcquired&&S.lockedRequestId?"\n\u{1f512} **Locked request:** "+S.lockedRequestId:""}`}]}}catch(o){if(e.taskId&&n)try{const r=o instanceof u.NotFoundError||o instanceof u.ValidationError||o instanceof h.ZodError
|
|
4711
4667
|
await n.createToolRecord({...r?{}:{taskId:e.taskId},projectId:t.projectId,type:"create-directory",metadata:{status:"failed",timestamp:(new Date).toISOString(),path:e.path,userComment:e.comment,error:(0,g.getErrorMessage)(o),errorDetails:o instanceof Error?o.stack:o+"",phase:k,attemptedTaskId:e.taskId,taskIdValidationFailed:r},note:`Failed to create directory ${e.path} - ${(0,g.getErrorMessage)(o)}`})}catch(t){f.error("Failed to create failure record for create directory operation",{error:t instanceof Error?t.message:t+"",taskId:e.taskId,path:e.path})}const s=Date.now()-m
|
|
4712
4668
|
if(i.recordValue("create_directory_time",s),i.incrementCounter("create_directory_errors",1),f.error("Error creating directory:",{error:(0,g.getErrorMessage)(o),time:s}),(y||w)&&e.taskId){k=d.FileOperationPhase.RECORD_UPDATE_FAILURE
|
|
4713
|
-
try{await d.updateFileOperationRecords(e.taskId,y,w,e.path,
|
|
4669
|
+
try{await d.updateFileOperationRecords(e.taskId,y,w,e.path,b.recordType,"Failed to create directory "+e.path,{status:"failed",error:(0,g.getErrorMessage)(o),userComment:e.comment},"Failed to create directory "+e.path,r,n,f,i,b.metricsPrefix)}catch(t){f.error("Failed to update record with failure status",{taskId:e.taskId,recordId:y,error:t instanceof Error?t.message:t+""})}}return d.handleFileOperationError(o,k,f,i,e,b)}}
|
|
4714
4670
|
const a=i(t(1943)),c=i(t(6928)),l=t(6183),d=s(t(5967)),u=t(9860),h=t(1569),g=t(8824)},8317(e,exports,t){function r(e){const t=[]
|
|
4715
4671
|
return"write-file"===e.type&&e.metadata?.path?t.push(e.metadata.path):"replace-in-files"===e.type&&e.metadata?.operations?e.metadata.operations.forEach((e=>{e.path&&t.push(e.path)})):"move-files"===e.type&&e.metadata?.successfulOperations?e.metadata.successfulOperations.forEach((e=>{e.destination&&t.push(e.destination)})):"delete-files"===e.type&&e.metadata?.paths?t.push(...e.metadata.paths):"manage-files"===e.type&&e.metadata?.operations&&e.metadata.operations.forEach((e=>{e.createDirectory?.path&&t.push(e.createDirectory.path),e.moveFiles?.moves&&e.moveFiles.moves.forEach((e=>{e.destination&&t.push(e.destination)})),e.deleteFiles?.targets&&e.deleteFiles.targets.forEach((e=>{e.path&&t.push(e.path)}))})),[...new Set(t)]}function n(e){switch(e){case"write-file":return"\u{1f4dd} Write File"
|
|
4716
4672
|
case"replace-in-files":return"\u{1f504} Replace in Files"
|
|
@@ -4919,34 +4875,34 @@ return i(t,e),t})
|
|
|
4919
4875
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleFileHistory=async function(e,t,n,o,s){const i=o.child({tool:"file_history"}),a=s.startTimer("tool_execution_time"),m=Date.now()
|
|
4920
4876
|
try{let o
|
|
4921
4877
|
try{o=d.FileHistorySchema.parse(e)}catch(t){if(t instanceof u.ZodError){const r="Invalid arguments: "+t.errors.map((e=>e.message)).join(", ")
|
|
4922
|
-
return i.warn("Validation error",{error:r,args:e}),{content:[{type:"text",text:"\u274c "+r}],isError:!0}}throw t}const{path:a,limit:y,showDiff:w,showTraceability:k,branch:
|
|
4923
|
-
return
|
|
4878
|
+
return i.warn("Validation error",{error:r,args:e}),{content:[{type:"text",text:"\u274c "+r}],isError:!0}}throw t}const{path:a,limit:y,showDiff:w,showTraceability:k,branch:b,commit:I,since:v}=o
|
|
4879
|
+
return I?(i.info("Getting diff for specific commit",{filePath:a,commit:I}),await async function(e,t,r,n){const o=r.git,s=c.normalize(e).replace(/\\/g,"/")
|
|
4924
4880
|
if(n.info("Getting full diff for commit",{filePath:e,commit:t}),!o)return{content:[{type:"text",text:"\u274c Git not initialized"}],isError:!0}
|
|
4925
4881
|
try{const r=await o.log({from:t,to:t,file:s,maxCount:1})
|
|
4926
4882
|
if(!r.all||0===r.all.length)return{content:[{type:"text",text:`No commit found with hash ${t} for file ${e}`}]}
|
|
4927
4883
|
const n=r.all[0],i=await o.diff([t+"^",t,"--",s])
|
|
4928
4884
|
let a="# File History - Commit Diff\n\n"
|
|
4929
|
-
return a+=`**File:** ${e}\n`,a+=`**Commit:** ${t.substring(0,8)}\n`,a+=`**Author:** ${n.author_name}\n`,a+=`**Date:** ${n.date}\n`,a+=`**Message:** ${n.message}\n\n`,i&&i.trim()?a+=`## Full Diff\n\n\`\`\`diff\n${i}\n\`\`\`\n`:a+="*No diff available for this commit*\n",{content:[{type:"text",text:a}]}}catch(r){return n.error("Failed to get commit diff",{error:r,commit:t,filePath:e}),{content:[{type:"text",text:`\u274c Failed to get diff for commit ${t}: ${(0,p.getErrorMessage)(r)}`}],isError:!0}}}(a,
|
|
4885
|
+
return a+=`**File:** ${e}\n`,a+=`**Commit:** ${t.substring(0,8)}\n`,a+=`**Author:** ${n.author_name}\n`,a+=`**Date:** ${n.date}\n`,a+=`**Message:** ${n.message}\n\n`,i&&i.trim()?a+=`## Full Diff\n\n\`\`\`diff\n${i}\n\`\`\`\n`:a+="*No diff available for this commit*\n",{content:[{type:"text",text:a}]}}catch(r){return n.error("Failed to get commit diff",{error:r,commit:t,filePath:e}),{content:[{type:"text",text:`\u274c Failed to get diff for commit ${t}: ${(0,p.getErrorMessage)(r)}`}],isError:!0}}}(a,I,t,i)):(i.info("Getting file history with branch support",{filePath:a,limit:y,showDiff:w,showTraceability:k,branch:b}),await async function(e,t,n,o,s,i,a,c,d,u,p){try{const{normalizedPath:m,fullPath:y}=f.validateAndNormalizePath(e,a)
|
|
4930
4886
|
try{await l.access(y)}catch(e){throw Error("File not found: "+m)}const w=a.git
|
|
4931
4887
|
if(!w)throw Error("Git is not available in this context")
|
|
4932
4888
|
let k={branch:null,requestId:null,isMain:!0}
|
|
4933
|
-
if(a.getCurrentBranchContext)try{k=await a.getCurrentBranchContext(),d.info("Current branch context detected",{branch:k.branch,requestId:k.requestId,isMain:k.isMain})}catch(e){d.warn("Could not get current branch context",{error:e})}let
|
|
4934
|
-
if(s)
|
|
4889
|
+
if(a.getCurrentBranchContext)try{k=await a.getCurrentBranchContext(),d.info("Current branch context detected",{branch:k.branch,requestId:k.requestId,isMain:k.isMain})}catch(e){d.warn("Could not get current branch context",{error:e})}let b=[],I=""
|
|
4890
|
+
if(s)b=await r(w,m,t,n,o,s,i,c,d,u),I=`## File History: ${m} (Branch: ${s})\n\n`
|
|
4935
4891
|
else{if(k.isMain&&!o)return d.info("Showing request-level timeline on main branch"),{content:[{type:"text",text:await(0,g.getRequestTimelineForFile)(w,m,c,d,u)}]}
|
|
4936
4892
|
if(k.requestId)return d.info("Showing operation-level detail on request branch",{requestId:k.requestId}),{content:[{type:"text",text:await(0,g.getOperationDetailForFile)(m,k.requestId,c,d,u)}]}
|
|
4937
4893
|
{const e=await async function(e,t,n,o,s,i,a,c,l,d){const u=[],h=[]
|
|
4938
4894
|
if(!i.isMain&&i.branch){const g=await r(e,t,n,o,s,i.branch,a,c,l,d)
|
|
4939
4895
|
u.push(...g),g.length>0&&h.push(i.branch+" (current)")}const g=await r(e,t,n,o,s,"main",a,c,l,d),p=new Set(u.map((e=>e.hash))),f=g.filter((e=>!p.has(e.hash)))
|
|
4940
4896
|
return u.push(...f),g.length>0&&h.push("main"),u.sort(((e,t)=>new Date(t.date).getTime()-new Date(e.date).getTime())),{versions:u.slice(0,n),sources:h}}(w,m,t,n,o,k,i,c,d,u)
|
|
4941
|
-
|
|
4942
|
-
const v=
|
|
4943
|
-
v>t?
|
|
4944
|
-
try{
|
|
4945
|
-
for(let e=0;e<
|
|
4946
|
-
if(
|
|
4897
|
+
b=e.versions,I=`## File History: ${m} (Combined View)\n\n`,I+=`**Current Context:** ${k.isMain?"main":`${k.branch} (${k.requestId})`}\n`,I+=`**History Sources:** ${e.sources.join(", ")}\n\n`}}if(0===b.length)return I+="\u274c **No history found**\n\nThis file has no git history. It may be:\n- A new file that hasn't been committed\n- Located outside the git repository\n- The path may be incorrect\n- No history exists in the specified branch context",{content:[{type:"text",text:I}]}
|
|
4898
|
+
const v=b.length,C=Math.min(b.length,t)
|
|
4899
|
+
v>t?I+=`\u{1f4ca} **Summary:** ${v} versions found, showing ${C} most recent\n\n`:v>0&&(I+=`\u{1f4ca} **Summary:** ${v} version${v>1?"s":""} found\n\n`),I+=`**Total Versions:** ${b.length}\n`,I+="**Current File Size:** "
|
|
4900
|
+
try{I+=(await l.stat(y)).size+" bytes\n"}catch{I+="Unknown\n"}I+="\n"
|
|
4901
|
+
for(let e=0;e<b.length;e++){const t=b[e]
|
|
4902
|
+
if(I+=`### Version ${e+1} (${t.hash.substring(0,8)})\n`,t.branch&&(I+=`- **Branch:** ${t.branch}\n`),I+=`- **Author:** ${t.author}\n`,I+=`- **Date:** ${t.date}\n`,I+=`- **Message:** ${t.message}\n`,o&&t.traceability&&(I+=`\n${(0,h.formatTraceabilityInfo)(t.traceability)}\n`),n&&t.diff){const e=t.diff.split("\n")
|
|
4947
4903
|
let r=0,n=0
|
|
4948
4904
|
for(const t of e)t.startsWith("+")&&!t.startsWith("+++")&&r++,t.startsWith("-")&&!t.startsWith("---")&&n++
|
|
4949
|
-
|
|
4905
|
+
I+=`\n**Changes:**${r>0||n>0?` (Added ${r} lines, removed ${n} lines)`:""}\n\`\`\`diff\n${t.diff}\n\`\`\`\n`}I+="\n"}return I+="\u{1f4a1} **Tips:**\n",I+="- Use `file-recover` with a commit hash to restore the file to a previous version\n",I+='- Use `{"branch": "main"}` to see only main branch history\n',I+='- Use `{"branch": "req123456"}` to see only request branch history\n\n',d.info("Branch-aware file history retrieved successfully",{path:m,versions:b.length,targetBranch:s,currentBranch:k.branch,duration:Date.now()-p}),u.incrementCounter("file_history_total",1,{success:!0,type:"file",mode:s?"single-branch":"combined"}),{content:[{type:"text",text:I}]}}catch(e){throw e}}(a,y,w,k,b,v,t,n,i,s,m))}catch(e){const t=Date.now()-m
|
|
4950
4906
|
return i.error("File/Document history operation failed",{error:e instanceof Error?e.stack:e+"",duration:t}),a({tool:"file_history",success:!1}),s.incrementCounter("file_history_errors",1),{content:[{type:"text",text:"\u274c **History Operation Failed:** "+(0,p.getErrorMessage)(e)}],isError:!0}}}
|
|
4951
4907
|
const c=a(t(6928)),l=a(t(1943)),d=t(6183),u=t(1569),h=t(1181),g=t(2085),p=t(8824),f=a(t(5967)),m=a(t(7478)),{getCurrentBranch:y}=m},8850(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.def=void 0
|
|
4952
4908
|
const r=t(6183),n=t(6891)
|
|
@@ -5079,7 +5035,14 @@ if(!o.ok)return void this.logger.debug("Polling response not ok",{status:o.statu
|
|
|
5079
5035
|
const i=await o.json()
|
|
5080
5036
|
if(this.logger.debug("Google OAuth polling response",{data:i}),i.success&&i.data&&i.data.authenticated&&i.data.token){this.logger.info("Google OAuth authentication completed")
|
|
5081
5037
|
const e=this.parseTokenResponse(i.data)
|
|
5082
|
-
e&&(this.pollingStatus=s.AUTHENTICATED,this.tokenResult=e,this.stopPolling(),r&&r(e))}else this.logger.debug("Not authenticated yet, continuing to poll",{hasSuccess:!!i.success,hasData:!!i.data,authenticated:i.data?.authenticated})}catch(e){this.logger.error("Error during Google OAuth polling",{error:(0,o.getErrorMessage)(e)}),this.pollingStatus=s.ERROR,this.pollingError=(0,o.getErrorMessage)(e),this.stopPolling(),i&&i(this.pollingError)}}),this.pollingIntervalMs),{authUrl:e,state:t}}}},
|
|
5038
|
+
e&&(this.pollingStatus=s.AUTHENTICATED,this.tokenResult=e,this.stopPolling(),r&&r(e))}else this.logger.debug("Not authenticated yet, continuing to poll",{hasSuccess:!!i.success,hasData:!!i.data,authenticated:i.data?.authenticated})}catch(e){this.logger.error("Error during Google OAuth polling",{error:(0,o.getErrorMessage)(e)}),this.pollingStatus=s.ERROR,this.pollingError=(0,o.getErrorMessage)(e),this.stopPolling(),i&&i(this.pollingError)}}),this.pollingIntervalMs),{authUrl:e,state:t}}}},9068(e,exports,t){function r(){const e=process.env.ALCHEMY_OPENCODE_DIR
|
|
5039
|
+
if(e)return e
|
|
5040
|
+
try{const e=Object(function(){var e=Error("Cannot find module 'alchemylab-opencode/package.json'")
|
|
5041
|
+
throw e.code="MODULE_NOT_FOUND",e}())
|
|
5042
|
+
return(0,o.dirname)(e)}catch{}}function n(e,t){return{command:"node",prependArgs:["--experimental-strip-types","--experimental-transform-types","--no-warnings","--import",(0,o.join)(e,"node-preload.mjs"),(0,o.join)(e,t)]}}Object.defineProperty(exports,"__esModule",{value:!0}),exports.resolveServeCommand=function(){const e=r()
|
|
5043
|
+
return e?n((0,o.join)(e,"packages","opencode","src"),"serve.ts"):{command:"opencode",prependArgs:["serve"]}},exports.resolveRunCommand=function(){const e=r()
|
|
5044
|
+
return e?n((0,o.join)(e,"packages","opencode","src"),"run.ts"):{command:"opencode",prependArgs:[]}}
|
|
5045
|
+
const o=t(6928)},9072(e,exports,t){async function r(e,t,r,n){try{const o=await(0,d.getServerUrl)(r,n)
|
|
5083
5046
|
if(!o)return n.warn("Could not get server URL for notification",{sessionId:e}),!1
|
|
5084
5047
|
let s,i
|
|
5085
5048
|
try{const t=`http://localhost:${g}/api/sessions/${encodeURIComponent(e)}/agent-type`,r=await fetch(t)
|
|
@@ -5088,27 +5051,23 @@ e.success&&e.agentType&&(s=e.agentType)}}catch(t){n.warn("Agent type lookup fail
|
|
|
5088
5051
|
if(e.ok){const t=await e.json()
|
|
5089
5052
|
if(t.data?.defaultModel){const[e,...r]=t.data.defaultModel.split("/")
|
|
5090
5053
|
i={providerID:e,modelID:r.join("/")}}}}catch{}const a=`${o.replace(/\/$/,"")}/session/${e}/prompt_async`,c=await fetch(a,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({parts:[{type:"text",text:"\x3c!-- inserted-prompt --\x3e"+t}],...s?{agent:s}:{},...i?{model:i}:{}})})
|
|
5091
|
-
return c.ok?(n.info("Notified session",{sessionId:e}),!0):(n.warn("Failed to notify session",{sessionId:e,status:c.status}),!1)}catch(t){return n.warn("Error notifying session",{sessionId:e,error:(0,l.getErrorMessage)(t)}),!1}}function n(e,t,r){return u.sessionIdentity.getParentSessionId(e,t,r)}
|
|
5092
|
-
if(
|
|
5093
|
-
|
|
5094
|
-
if(!s)throw new c.ValidationError("Could not determine OpenCode server URL")
|
|
5095
|
-
const i=await(0,d.getAndStoreSessionId)(s,t,r,n),a=i?.sessionId
|
|
5096
|
-
if(!a)throw new c.ValidationError("Could not discover current session ID. Make sure you are running within an OpenCode session.")
|
|
5097
|
-
return(0,h.logSessionIdentity)(""+r,"per-call-discovery",{sessionId:a}),a}function s(e){const t=[],r=e.content||{}
|
|
5054
|
+
return c.ok?(n.info("Notified session",{sessionId:e}),!0):(n.warn("Failed to notify session",{sessionId:e,status:c.status}),!1)}catch(t){return n.warn("Error notifying session",{sessionId:e,error:(0,l.getErrorMessage)(t)}),!1}}function n(e,t,r){return u.sessionIdentity.getParentSessionId(e,t,r)}function o(e,t,r){const n=u.sessionIdentity.getIdentity()
|
|
5055
|
+
if(!n?.sessionId)throw new c.ValidationError("No session identity available. Make sure you are running within an OpenCode session.")
|
|
5056
|
+
return(0,h.logSessionIdentity)(""+r,"identity",{sessionId:n.sessionId}),n.sessionId}function s(e){const t=[],r=e.content||{}
|
|
5098
5057
|
if(t.push("**Message Code:** "+e.messageCode),t.push(`**Type:** question (${r.questionType})`),t.push("**Status:** "+e.status),t.push("**Priority:** "+e.priority),t.push("**From:** "+e.fromSessionId),t.push(e.toSessionId?"**To:** "+e.toSessionId:"**To:** (broadcast)"),t.push("**Created:** "+e.createdAt),t.push("**Expires:** "+e.expiresAt),t.push(""),t.push("**Question:** "+r.question),r.context&&t.push("**Context:** "+r.context),"alternatives"===r.questionType&&r.options){t.push(""),t.push("**Options:**")
|
|
5099
5058
|
for(const e of r.options)t.push(` - [${e.id}] ${e.label}${e.description?" - "+e.description:""}`)}return"responded"===e.status&&e.response&&(t.push(""),t.push("---"),t.push("**Answered by:** "+e.respondedBySessionId),t.push("**Answered at:** "+e.respondedAt),e.response.text&&t.push("**Answer:** "+e.response.text),e.response.selectedOptions&&t.push("**Selected:** "+e.response.selectedOptions.join(", ")),e.response.notes&&t.push("**Notes:** "+e.response.notes)),t.join("\n")}function i(e){const t=[],r=e.content||{}
|
|
5100
|
-
return t.push("**Status:** "+(r.reportStatus||"unknown")),t.push("**Summary:** "+(r.summary||"")),r.details&&(t.push(""),t.push("**Details:**"),t.push(r.details)),t.join("\n")}function a(e){return"question"===e.messageType?s(e):i(e)}Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleSessionMessageOperations=async function(e,t,p,f
|
|
5101
|
-
if(!
|
|
5102
|
-
const{operation:
|
|
5103
|
-
|
|
5104
|
-
try{switch(
|
|
5059
|
+
return t.push("**Status:** "+(r.reportStatus||"unknown")),t.push("**Summary:** "+(r.summary||"")),r.details&&(t.push(""),t.push("**Details:**"),t.push(r.details)),t.join("\n")}function a(e){return"question"===e.messageType?s(e):i(e)}Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleSessionMessageOperations=async function(e,t,d,p,f){const m=d.child({component:"session_message_operations"})
|
|
5060
|
+
if(!f)throw new c.ValidationError("API client not available")
|
|
5061
|
+
const{operation:y}=e
|
|
5062
|
+
m.info("Session message operation",{operation:y}),p.incrementCounter("session_message_operations",1,{operation:y})
|
|
5063
|
+
try{switch(y){case"send":if(!e.type)throw new c.ValidationError('send operation requires type ("question" or "report")')
|
|
5105
5064
|
return await async function(e,t,a,l){const{type:d}=e
|
|
5106
5065
|
if(!d)throw new c.ValidationError('send operation requires type ("question" or "report")')
|
|
5107
5066
|
const u=l.getSessionMessageClient()
|
|
5108
5067
|
if(!u)throw new c.ValidationError("Session message client not available")
|
|
5109
5068
|
if("question"===d)return await async function(e,t,i,a,l){const{toSessionId:d,questionType:u,questionContent:h,priority:g,expiresInHours:p}=e
|
|
5110
5069
|
if(!u||!h?.question)throw new c.ValidationError("Question requires questionType and questionContent.question")
|
|
5111
|
-
const f=await o(
|
|
5070
|
+
const f=await o(0,0,"session_message_operations"),m=await async function(e,t,r,o){if("parent"===e){const e=await n(t,r,o)
|
|
5112
5071
|
if(!e)throw new c.ValidationError("Could not find parent session. Make sure this session was spawned as a subagent.")
|
|
5113
5072
|
return o.info('Resolved toSessionId "parent" to actual ID',{parentId:e}),e}return e}(d,f,a,i)
|
|
5114
5073
|
if(!("alternatives"!==u||h.options&&Array.isArray(h.options)))throw new c.ValidationError("Alternatives questions require options array")
|
|
@@ -5120,7 +5079,7 @@ if(t.context&&r.push("**Context:** "+t.context),"alternatives"===t.questionType&
|
|
|
5120
5079
|
for(const e of t.options)r.push(` - [${e.id}] ${e.label}${e.description?" - "+e.description:""}`)}return r.push(""),r.push(`Use \`session_message_operations\` with \`reply\` operation and message code \`${e.messageCode}\` to respond.`),r.join("\n")}(y),t,i)?"\n\n\u{1f4ec} The target session has been notified.":"\n\n\u26a0\ufe0f Could not notify the target session (may be offline)."),{content:[{type:"text",text:`\u2705 Question created!${w}\n\n**Message Code: ${y.messageCode}**\n\nUse this code to check for answers or share with other sessions.\n\n${s(y)}`}]}}(e,t,a,l,u)
|
|
5121
5080
|
if("report"===d)return await async function(e,t,s,a,l){const{status:d,summary:u,details:h,finish:p}=e
|
|
5122
5081
|
if(!d||!u)throw new c.ValidationError("Report requires status and summary")
|
|
5123
|
-
const f=await o(
|
|
5082
|
+
const f=await o(0,0,"session_message_operations"),m=await(async()=>{if(e.toSessionId&&"parent"!==e.toSessionId)return s.info("Using explicit toSessionId for report",{parentSessionId:e.toSessionId}),e.toSessionId
|
|
5124
5083
|
const t=await n(f,a,s)
|
|
5125
5084
|
if(!t)throw new c.ValidationError("Could not find parent session. This tool should only be used by subagent sessions.")
|
|
5126
5085
|
return s.info("Auto-resolved parent session",{parentSessionId:t}),t})()
|
|
@@ -5132,7 +5091,7 @@ if(e.ok){const t=await e.json()
|
|
|
5132
5091
|
t.success&&t.agentType&&(w=t.agentType)}}catch{}const k=await r(m,function(e,t="agent"){const r=e.content||{},n=[`${{success:"\u2705",partial:"\u26a0\ufe0f",failure:"\u274c",blocked:"\u{1f6ab}"}[r.reportStatus]||"\u{1f4cb}"} **Report \u2014 ${r.reportStatus}**`,`from: ${t} (${e.fromSessionId})`,"",r.summary]
|
|
5133
5092
|
return r.details&&(n.push(""),n.push(r.details)),n.join("\n")}(y,w),t,s)
|
|
5134
5093
|
return{content:[{type:"text",text:`\u2705 Report submitted.${k?"\n\n\u{1f4ec} The parent session has been notified.":"\n\n\u26a0\ufe0f Could not notify the parent session (may be offline)."}\n\n${i(y)}`}]}}(e,t,a,l,u)
|
|
5135
|
-
throw new c.ValidationError(`Unknown message type: ${d}. Use "question" or "report".`)}(e,t,
|
|
5094
|
+
throw new c.ValidationError(`Unknown message type: ${d}. Use "question" or "report".`)}(e,t,m,f)
|
|
5136
5095
|
case"reply":if(!e.messageCode)throw new c.ValidationError("reply operation requires messageCode")
|
|
5137
5096
|
return await async function(e,t,n,o){const{messageCode:a}=e
|
|
5138
5097
|
if(!a)throw new c.ValidationError("reply operation requires messageCode")
|
|
@@ -5143,26 +5102,24 @@ n.info("Answering question",{messageCode:a,respondedBySessionId:o})
|
|
|
5143
5102
|
const u=await l.answerQuestion(a,{respondedBySessionId:o,text:i,selectedOptions:c,notes:d})
|
|
5144
5103
|
return{content:[{type:"text",text:`\u2705 Question answered!${await r(u.fromSessionId,function(e){const t=e.content||{},r=e.response||{},n=["\u{1f4ec} **Your question has been answered!**","","**Question Code:** "+e.messageCode,"**Question:** "+t.question,"","---","**Answered by:** "+e.respondedBySessionId]
|
|
5145
5104
|
return r.text&&n.push("**Answer:** "+r.text),r.selectedOptions&&n.push("**Selected:** "+r.selectedOptions.join(", ")),r.notes&&n.push("**Notes:** "+r.notes),n.join("\n")}(u),t,n)?"\n\n\u{1f4ec} The asking session has been notified.":"\n\n\u26a0\ufe0f Could not notify the asking session (may be offline)."}\n\n${s(u)}`}]}}if(a.startsWith("R-"))return n.info("Acknowledging report",{messageCode:a}),{content:[{type:"text",text:"\u2705 Report acknowledged!\n\n"+i(await l.acknowledgeReport(a))}]}
|
|
5146
|
-
throw new c.ValidationError(`Cannot determine message type from code "${a}". Expected Q-xxx (question) or R-xxx (report).`)}(e,t,
|
|
5147
|
-
case"offer-handoff":{const
|
|
5148
|
-
let
|
|
5149
|
-
try{
|
|
5150
|
-
if(e
|
|
5151
|
-
|
|
5152
|
-
await e.createQuestion({fromSessionId:s,toSessionId:i||void 0,questionType:"alternatives",question:"Plan ready: "+(r.summary||"Plan complete"),options:[{id:"build",label:"Start Building",description:`Begin building ${t} request${1!==t?"s":""}`},{id:"plan",label:"Keep Planning",description:"Continue refining the plan"}],context:t>0?"Created requests: "+r.requestIds.join(", "):void 0,category:"action-required",priority:"high"}),y.info("offer-handoff: notification question created",{fromSessionId:s})}else y.warn("offer-handoff: skipping notification question",{hasClient:!!e,fromSessionId:s})}catch(e){y.warn("offer-handoff: failed to create notification question",{error:(0,l.getErrorMessage)(e)})}return{content:[{type:"text",text:'Handoff offered to user. STOP here and wait \u2014 the user will choose "Start Building" or "Keep Planning". You will receive their choice as a new message. Do NOT generate any further output until then.\nPLAN_HANDOFF_PENDING|'+JSON.stringify({summary:r.summary,requestIds:r.requestIds,parentSessionId:i})}],isError:!1}}case"list":return await async function(e,t,r,n){let{sessionId:o,messageType:s,direction:i,status:l,readStatus:u,reportStatus:g,limit:p,offset:f}=e
|
|
5105
|
+
throw new c.ValidationError(`Cannot determine message type from code "${a}". Expected Q-xxx (question) or R-xxx (report).`)}(e,t,m,f)
|
|
5106
|
+
case"offer-handoff":{const t=e.offerHandoff||{summary:e.summary||"",requestIds:e.requestIds||[]}
|
|
5107
|
+
let r=null,s=null
|
|
5108
|
+
try{r=o(0,0,"session_message_operations"),s=await n(r,f,m)}catch(e){m.warn("offer-handoff: could not resolve session/parent",{error:(0,l.getErrorMessage)(e)})}try{const e=f.getSessionMessageClient()
|
|
5109
|
+
if(e&&r){const n=t.requestIds?.length||0
|
|
5110
|
+
await e.createQuestion({fromSessionId:r,toSessionId:s||void 0,questionType:"alternatives",question:"Plan ready: "+(t.summary||"Plan complete"),options:[{id:"build",label:"Start Building",description:`Begin building ${n} request${1!==n?"s":""}`},{id:"plan",label:"Keep Planning",description:"Continue refining the plan"}],context:n>0?"Created requests: "+t.requestIds.join(", "):void 0,category:"action-required",priority:"high"}),m.info("offer-handoff: notification question created",{fromSessionId:r})}else m.warn("offer-handoff: skipping notification question",{hasClient:!!e,fromSessionId:r})}catch(e){m.warn("offer-handoff: failed to create notification question",{error:(0,l.getErrorMessage)(e)})}return{content:[{type:"text",text:'Handoff offered to user. STOP here and wait \u2014 the user will choose "Start Building" or "Keep Planning". You will receive their choice as a new message. Do NOT generate any further output until then.\nPLAN_HANDOFF_PENDING|'+JSON.stringify({summary:t.summary,requestIds:t.requestIds,parentSessionId:s})}],isError:!1}}case"list":return await async function(e,t,r,n){let{sessionId:o,messageType:s,direction:i,status:l,readStatus:d,reportStatus:g,limit:p,offset:f}=e
|
|
5153
5111
|
const m=n.getSessionMessageClient()
|
|
5154
5112
|
if(!m)throw new c.ValidationError("Session message client not available")
|
|
5155
|
-
if(!o){const e=
|
|
5156
|
-
if(!e)return{content:[{type:"text",text:"\u26a0\ufe0f Could not
|
|
5157
|
-
|
|
5158
|
-
if(o=n?.sessionId,(0,h.logSessionIdentity)("session_message_operations.list",o?"per-call-discovery":"discovery-failed",{sessionId:o}),!o)return r.warn("Session discovery FAILED for list - returning empty to prevent data leak"),{content:[{type:"text",text:"\u26a0\ufe0f Could not determine current session ID. Unable to list messages without a session context."}]}}}r.debug("Listing messages",{sessionId:o,messageType:s,direction:i,status:l,readStatus:u})
|
|
5113
|
+
if(!o){const e=u.sessionIdentity.getIdentity()
|
|
5114
|
+
if(!e?.sessionId)return r.warn("No session identity for list operation"),{content:[{type:"text",text:"\u26a0\ufe0f Could not determine current session ID. Unable to list messages without a session context."}]}
|
|
5115
|
+
o=e.sessionId,(0,h.logSessionIdentity)("session_message_operations.list","identity",{sessionId:o})}r.debug("Listing messages",{sessionId:o,messageType:s,direction:i,status:l,readStatus:d})
|
|
5159
5116
|
const y={sessionId:o,direction:i,limit:p,offset:f}
|
|
5160
|
-
s&&"all"!==s&&(y.messageType=s),l&&"all"!==l&&("report"===s?y.reportStatus=l:y.status=l),
|
|
5117
|
+
s&&"all"!==s&&(y.messageType=s),l&&"all"!==l&&("report"===s?y.reportStatus=l:y.status=l),d&&"all"!==d&&(y.readStatus=d),g&&"all"!==g&&(y.reportStatus=g)
|
|
5161
5118
|
const w=await m.listMessages(y)
|
|
5162
5119
|
if(0===w.length)return{content:[{type:"text",text:"No messages found matching the criteria."}]}
|
|
5163
5120
|
const k=[`Found ${w.length} message(s):\n`]
|
|
5164
5121
|
for(const e of w)k.push("---\n"),k.push(a(e)),k.push("")
|
|
5165
|
-
return{content:[{type:"text",text:k.join("\n")}]}}(e.list||{},
|
|
5122
|
+
return{content:[{type:"text",text:k.join("\n")}]}}(e.list||{},0,m,f)
|
|
5166
5123
|
case"get":if(!e.messageCode)throw new c.ValidationError("get operation requires messageCode")
|
|
5167
5124
|
return await async function(e,t,r){const{messageCode:n}=e
|
|
5168
5125
|
if(!n)throw new c.ValidationError("get operation requires messageCode")
|
|
@@ -5170,8 +5127,8 @@ const o=r.getSessionMessageClient()
|
|
|
5170
5127
|
if(!o)throw new c.ValidationError("Session message client not available")
|
|
5171
5128
|
t.debug("Getting message",{messageCode:n})
|
|
5172
5129
|
const s=await o.getMessage(n)
|
|
5173
|
-
return s?{content:[{type:"text",text:a(s)}]}:{content:[{type:"text",text:`\u274c Message with code ${n} not found.`}],isError:!0}}(e,
|
|
5174
|
-
default:throw new c.ValidationError(`Unknown operation: ${
|
|
5130
|
+
return s?{content:[{type:"text",text:a(s)}]}:{content:[{type:"text",text:`\u274c Message with code ${n} not found.`}],isError:!0}}(e,m,f)
|
|
5131
|
+
default:throw new c.ValidationError(`Unknown operation: ${y}. Valid operations: send, reply, list, get`)}}catch(e){return m.error("Session message operation failed",{operation:y,error:(0,l.getErrorMessage)(e)}),{content:[{type:"text",text:"\u274c Error: "+(0,l.getErrorMessage)(e)}],isError:!0}}}
|
|
5175
5132
|
const c=t(9860),l=t(8824),d=t(7617),u=t(6688),h=t(7280),g=3456},9080(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.def=void 0
|
|
5176
5133
|
const r=t(6183),n=t(1281)
|
|
5177
5134
|
exports.def={name:"search",description:"Search for text patterns in files on the currently active branch. Supports regex patterns and sorts results by file modification time (newest first).\n\nFile extensions: 'ts', '.ts', '*.ts' (all valid). Use '*' for any file type.\n\nCONTEXT LINES: Use contextLines option (0-10) to show surrounding lines before and after matches, reducing need for follow-up reads.\n\nLIST-ALL MODE: Omit 'needle' to list all files in a directory with tree structure (like ls/tree). Options: levels (1-4 depth), sortBy (name/modified/size/type).",schema:r.SearchSchema,annotations:{title:"Search Files",readOnlyHint:!0},readOnly:!0,handler(e,t){return(0,n.handleSearch)(e,t.context,t.apiClient,t.logger,t.metrics)}}},9089(e,exports){function t(e){if(e.toLowerCase().startsWith("specialist:")){const t=e.slice(11).trim()
|
|
@@ -5275,10 +5232,10 @@ continue}const t=(0,h.findMatches)(s,n,m,100,e.path)
|
|
|
5275
5232
|
if(a.matchesFound=t.length,0===t.length){a.error="No matches found"+(m?" (tried fuzzy matching)":""),a.success=!1
|
|
5276
5233
|
const e=(0,h.findSimilarMatches)(s,n,5,.3)
|
|
5277
5234
|
e.length>0&&(a.similarMatches=e),y.failedReplacements++}else"unique"===i&&t.length>1?(a.error=`Multiple matches found (${t.length}) - expected unique match`,a.success=!1,a.details=t.map(r),y.failedReplacements++):p.push({matches:t,newText:o,matchMode:i,repResult:a})}catch(e){a.error=(0,k.getErrorMessage)(e),a.success=!1,y.failedReplacements++}y.replacements.push(a)}let w=s
|
|
5278
|
-
const
|
|
5279
|
-
for(const e of p)for(const t of e.matches)
|
|
5280
|
-
|
|
5281
|
-
for(const{match:e,newText:t,repResult:n}of
|
|
5235
|
+
const b=[]
|
|
5236
|
+
for(const e of p)for(const t of e.matches)b.push({match:t,newText:e.newText,repResult:e.repResult})
|
|
5237
|
+
b.sort(((e,t)=>t.match.startPos-e.match.startPos))
|
|
5238
|
+
for(const{match:e,newText:t,repResult:n}of b)w=(0,h.replaceMatch)(w,e,t),n.success?(n.lines.push(e.line),n.details.push(r(e))):(n.success=!0,n.matchType=e.matchType,n.lines=[e.line],n.details=[r(e)],y.successfulReplacements++)
|
|
5282
5239
|
y.successfulReplacements>0&&(await l.default.writeFile(t,w,"utf8"),f&&(n.documentFileManager.markForSync(d),await n.documentFileManager.syncDocument(d))),i&&(y.externalEditWarning=i),a&&(y.externalEditDebugInfo={detectionRan:!0,...a}),y.success=0===y.failedReplacements}catch(e){y.error=(0,k.getErrorMessage)(e),y.success=!1,y.failedReplacements=g.length,y.replacements=g.map((e=>({old:e.old,new:e.new,success:!1,error:y.error})))}return y}var o,s=this&&this.__createBinding||(Object.create?function(e,t,r,n){void 0===n&&(n=r)
|
|
5283
5240
|
var o=Object.getOwnPropertyDescriptor(t,r)
|
|
5284
5241
|
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]}),i=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),a=this&&this.__importStar||(o=function(e){return o=Object.getOwnPropertyNames||function(e){var t=[]
|
|
@@ -5287,48 +5244,48 @@ return t},o(e)},function(e){if(e&&e.__esModule)return e
|
|
|
5287
5244
|
var t={}
|
|
5288
5245
|
if(null!=e)for(var r=o(e),n=0;n<r.length;n++)"default"!==r[n]&&s(t,e,r[n])
|
|
5289
5246
|
return i(t,e),t}),c=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
5290
|
-
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleReplaceInFiles=async function(e,t,r,o,s,i,a,c){const
|
|
5247
|
+
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleReplaceInFiles=async function(e,t,r,o,s,i,a,c){const b=i.child({tool:"replace_in_files"}),I=Date.now()
|
|
5291
5248
|
let v,C=u.FileOperationPhase.VALIDATION
|
|
5292
5249
|
try{if(e&&"string"==typeof e.operations)try{e.operations=JSON.parse(e.operations)}catch{}if(e&&Array.isArray(e.operations))for(const t of e.operations)t.old&&t.new&&!t.replacements&&(t.replacements=[{old:t.old,new:t.new,match_mode:t.match_mode}],delete t.old,delete t.new,delete t.match_mode)
|
|
5293
5250
|
const i=u.validateArgs(e,d.ReplaceInFilesSchema),{taskId:_,operations:E,fuzzy_match:q=!0,comment:S}=i
|
|
5294
|
-
|
|
5251
|
+
b.info("Replace in files batch operation",{taskId:_,operationCount:E.length,totalReplacements:E.reduce(((e,t)=>e+t.replacements.length),0),globalFuzzyMatch:q,comment:S})
|
|
5295
5252
|
const T=E.filter((e=>e.documentId)).map((e=>e.documentId))
|
|
5296
|
-
if(T.length>0&&t.apiClient)try{await(0,m.ensureDocumentsNotLocked)(T,t.apiClient,
|
|
5253
|
+
if(T.length>0&&t.apiClient)try{await(0,m.ensureDocumentsNotLocked)(T,t.apiClient,b,a,"replace_in_files-documents")}catch(e){if(e instanceof g.ValidationError)return{content:[{type:"text",text:e.message}],isError:!0}
|
|
5297
5254
|
throw e}C=u.FileOperationPhase.TASK_VALIDATION,a.incrementCounter("replace_in_files_phase",1,{phase:C})
|
|
5298
5255
|
const P=E[0],M=P.documentId?"document:"+P.documentId:P.path
|
|
5299
|
-
let
|
|
5300
|
-
const
|
|
5256
|
+
let j=Date.now()
|
|
5257
|
+
const R=await u.validateTaskId(_,M,r,b,a,"replace_in_files")
|
|
5301
5258
|
Date.now()
|
|
5302
|
-
const x=
|
|
5259
|
+
const x=R?.requestId,O=E.some((e=>e.path))
|
|
5303
5260
|
let A=!1
|
|
5304
|
-
if(O&&x){
|
|
5305
|
-
const e=await u.validateWorkItemStates(_,M,r,s,t,
|
|
5306
|
-
Date.now(),
|
|
5307
|
-
const n=await u.autoPromoteTaskStatus(_,
|
|
5308
|
-
n.taskPromoted&&
|
|
5309
|
-
const o=await u.ensureCorrectWorkspaceContext({taskPromoted:n.taskPromoted,requestId:x,context:t,operation:"replace_in_files",logger:
|
|
5261
|
+
if(O&&x){j=Date.now()
|
|
5262
|
+
const e=await u.validateWorkItemStates(_,M,r,s,t,b,a,"replace_in_files")
|
|
5263
|
+
Date.now(),j=Date.now()
|
|
5264
|
+
const n=await u.autoPromoteTaskStatus(_,R.status,x,e.request?.status,M,r,s,b,a,"replace_in_files")
|
|
5265
|
+
n.taskPromoted&&b.info("Auto-promoted task to in_progress",{taskId:_,requestId:x,previousStatus:R.status,newStatus:n.newTaskStatus}),Date.now(),j=Date.now()
|
|
5266
|
+
const o=await u.ensureCorrectWorkspaceContext({taskPromoted:n.taskPromoted,requestId:x,context:t,operation:"replace_in_files",logger:b,metrics:a,metricsPrefix:"replace_in_files"})
|
|
5310
5267
|
if(!o.success){if(o.isLockConflict)return{content:[{type:"text",text:"\u274c "+o.error}],isError:!0}
|
|
5311
|
-
throw Error(o.error)}Date.now(),A=!0}if(T.length>0&&x)try{await(0,p.validateRequestStatusForDocumentOperation)(x,s,
|
|
5312
|
-
throw e}
|
|
5268
|
+
throw Error(o.error)}Date.now(),A=!0}if(T.length>0&&x)try{await(0,p.validateRequestStatusForDocumentOperation)(x,s,b,a,"replace_in_files-documents")}catch(e){if(e instanceof g.ValidationError)return{content:[{type:"text",text:e.message}],isError:!0}
|
|
5269
|
+
throw e}j=Date.now()
|
|
5313
5270
|
const D=new Map
|
|
5314
|
-
if(
|
|
5271
|
+
if(b.info("\u{1f50d} Starting external edit detection",{hasFileOperations:O,hasGit:!!t.git,operationCount:E.length}),O&&t.git)for(const e of E)if(e.path&&!e.documentId)try{const r=u.validateAndNormalizePath(e.path,t),n=await l.default.readFile(r.fullPath,"utf8"),o=void 0!==e.fuzzy_match?e.fuzzy_match:q,s=[]
|
|
5315
5272
|
for(const t of e.replacements){const r=(0,h.findMatches)(n,t.old,o,100,e.path)
|
|
5316
5273
|
s.push(...r)}if(s.length>0){const o=(0,y.calculateReplacementRegion)(n,s,r.fullPath)
|
|
5317
|
-
|
|
5318
|
-
const i=await(0,w.detectExternalEdits)(t.git,o,
|
|
5319
|
-
|
|
5320
|
-
const e=await(0,f.commitUserChangesBeforeToolOperation)(t.git,"replace_in_files",{requestId:x,taskId:_,workspaceManager:t.workspaceManager},
|
|
5321
|
-
e.userChangesCommitted&&(
|
|
5322
|
-
const{toolRecordId:$}=await u.createFileOperationRecords(_,x,t.projectId,"replace-in-files",M,{operationCount:E.length,totalReplacements:E.reduce(((e,t)=>e+t.replacements.length),0),globalFuzzyMatch:q,userComment:S},r,o,
|
|
5323
|
-
v=$,Date.now(),
|
|
5274
|
+
b.info("\u{1f50d} Checking for external edits",{path:r.normalizedPath,affectedLines:o.lineRanges.map((e=>`${e.start}-${e.end}`)).join(", "),matchCount:s.length})
|
|
5275
|
+
const i=await(0,w.detectExternalEdits)(t.git,o,b)
|
|
5276
|
+
b.info("\u{1f50d} External edit detection result",{path:r.normalizedPath,hasExternalEdits:i.hasExternalEdits,conflictingLines:i.conflictingLines,hasMessage:!!i.message}),i.hasExternalEdits&&i.message?(D.set(e.path,{message:i.message,debugInfo:i.debugInfo}),b.warn("\u26a0\ufe0f External edits detected before auto-commit",{path:r.normalizedPath,conflictingLines:i.conflictingLines})):(i.debugInfo&&D.set(e.path,{message:"",debugInfo:i.debugInfo}),b.info("\u2705 No external edit conflicts detected",{path:r.normalizedPath}))}else b.info("\u2139\ufe0f No matches found for external edit detection",{path:r.normalizedPath}),D.set(e.path,{message:"",debugInfo:{detectionRan:!1,reason:"No matches found - patterns not found in file",affectedRegion:"none",uncommittedChanges:"not checked",overlapDetected:!1}})}catch(t){b.warn("Failed to check for external edits before auto-commit",{path:e.path,error:(0,k.getErrorMessage)(t)})}if(Date.now(),j=Date.now(),O&&t.git)try{b.debug("[REPLACE-IN-FILES] Checking for user changes before batch operation")
|
|
5277
|
+
const e=await(0,f.commitUserChangesBeforeToolOperation)(t.git,"replace_in_files",{requestId:x,taskId:_,workspaceManager:t.workspaceManager},b,a)
|
|
5278
|
+
e.userChangesCommitted&&(b.debug("[REPLACE-IN-FILES] User changes committed",{commitHash:e.commitHash?.substring(0,8),filesCommitted:e.filesCommitted}),b.info("User changes committed before batch operation",{taskId:_,userCommitHash:e.commitHash?.substring(0,8),userFilesCommitted:e.filesCommitted}))}catch(e){b.warn("Pre-tool user changes commit failed",{taskId:_,error:e instanceof Error?e.message:e+""})}Date.now(),j=Date.now(),C=u.FileOperationPhase.RECORD_CREATION,a.incrementCounter("replace_in_files_phase",1,{phase:C})
|
|
5279
|
+
const{toolRecordId:$}=await u.createFileOperationRecords(_,x,t.projectId,"replace-in-files",M,{operationCount:E.length,totalReplacements:E.reduce(((e,t)=>e+t.replacements.length),0),globalFuzzyMatch:q,userComment:S},r,o,b,a,"replace_in_files",c)
|
|
5280
|
+
v=$,Date.now(),j=Date.now(),C=u.FileOperationPhase.STRING_REPLACEMENT,a.incrementCounter("replace_in_files_phase",1,{phase:C})
|
|
5324
5281
|
const F=[],N=[]
|
|
5325
5282
|
for(const e of E){const r=e.path?D.get(e.path):void 0,o=await n(e,q,t,0,0,r?.message,r?.debugInfo)
|
|
5326
|
-
F.push(o),o.successfulReplacements>0&&"file"===o.type&&o.path&&N.push(o.path)}Date.now(),
|
|
5327
|
-
const L=E.filter((e=>e.path&&!e.documentId)).map((e=>({path:e.path}))),z=await u.handleMultiFileGitCommit(_,L,F,N.length,{operationType:"Replace in files",toolRecordId:$||v||"unknown",successField:"successfulReplacements",logger:
|
|
5283
|
+
F.push(o),o.successfulReplacements>0&&"file"===o.type&&o.path&&N.push(o.path)}Date.now(),j=Date.now()
|
|
5284
|
+
const L=E.filter((e=>e.path&&!e.documentId)).map((e=>({path:e.path}))),z=await u.handleMultiFileGitCommit(_,L,F,N.length,{operationType:"Replace in files",toolRecordId:$||v||"unknown",successField:"successfulReplacements",logger:b,metrics:a,metricsPrefix:"replace_in_files"},t),B=z.commitHash
|
|
5328
5285
|
Date.now(),Date.now()
|
|
5329
|
-
const H=F.filter((e=>e.success)).length,W=F.length-H,U=F.reduce(((e,t)=>e+t.successfulReplacements),0),G=F.reduce(((e,t)=>e+t.failedReplacements),0),V=F.map((e=>({type:e.type,path:e.path,documentId:e.documentId,filename:e.filename,replacements:e.replacements.map((e=>({old_str:e.old,new_str:e.new,success:e.success,error:e.error,matchesFound:e.matchesFound,matchType:e.matchType,lines:e.lines})))}))),J=F.filter((e=>e.success)).map((e=>({path:e.path,documentId:e.documentId,filename:e.filename,successfulReplacements:e.successfulReplacements,failedReplacements:e.failedReplacements}))),
|
|
5330
|
-
await o.updateToolRecord(v,{metadata:{path:M,status:0===W?"completed":"partial",operationCount:E.length,operations:V,successfulFiles:J,failedFiles:
|
|
5331
|
-
const
|
|
5286
|
+
const H=F.filter((e=>e.success)).length,W=F.length-H,U=F.reduce(((e,t)=>e+t.successfulReplacements),0),G=F.reduce(((e,t)=>e+t.failedReplacements),0),V=F.map((e=>({type:e.type,path:e.path,documentId:e.documentId,filename:e.filename,replacements:e.replacements.map((e=>({old_str:e.old,new_str:e.new,success:e.success,error:e.error,matchesFound:e.matchesFound,matchType:e.matchType,lines:e.lines})))}))),J=F.filter((e=>e.success)).map((e=>({path:e.path,documentId:e.documentId,filename:e.filename,successfulReplacements:e.successfulReplacements,failedReplacements:e.failedReplacements}))),K=F.filter((e=>!e.success)).map((e=>({path:e.path,documentId:e.documentId,filename:e.filename,error:e.error,successfulReplacements:e.successfulReplacements,failedReplacements:e.failedReplacements})))
|
|
5287
|
+
await o.updateToolRecord(v,{metadata:{path:M,status:0===W?"completed":"partial",operationCount:E.length,operations:V,successfulFiles:J,failedFiles:K,successfulReplacements:U,failedReplacements:G,processingTime:Date.now()-I,userComment:S,...z.success&&z.commitHash&&{commitHash:z.commitHash,previousCommitHash:z.previousCommitHash||void 0}}})
|
|
5288
|
+
const Y=await async function(e,t,r,n,o,s){const i=e.filter((e=>e.success)).length,a=e.length-i,c=e.filter((e=>!e.success&&!e.error&&e.successfulReplacements>0)).length
|
|
5332
5289
|
let l="## Replace In Files - Batch Results\n\n"
|
|
5333
5290
|
if(o.getCurrentBranchContext)try{const e=await o.getCurrentBranchContext()
|
|
5334
5291
|
e.branch&&(l+=`**Current Branch:** ${e.branch}\n\n`)}catch(e){}l+="**Summary:**\n",l+=`- **Files/Documents:** ${e.length} total`,l+=c>0?` (\u2705 ${i} fully succeeded, \u26a0\ufe0f ${c} partial, \u274c ${a-c} failed)\n`:` (\u2705 ${i} successful, \u274c ${a} failed)\n`,l+=`- **Replacements:** ${r+n} total (\u2705 ${r} successful, \u274c ${n} failed)\n`,t&&(l+=`- **Git Commit:** ${t.substring(0,8)}\n`),s&&(l+=`[RECORD:${s}]\n`),l+="\n---\n\n"
|
|
@@ -5340,8 +5297,8 @@ for(const e of o)l+=`- \u2705 \`${e.old.substring(0,40)}${e.old.length>40?"...":
|
|
|
5340
5297
|
if(s.length>0){l+="\n**Failed Replacement Details:**\n"
|
|
5341
5298
|
for(const e of s)l+=`- \u274c \`${e.old.substring(0,40)}${e.old.length>40?"...":""}\` \u2192 \`${e.new.substring(0,40)}${e.new.length>40?"...":""}\`: ${e.error}\n`,e.details&&e.details.length>0&&(l+=" **Candidates found:**\n",l+=e.details.slice(0,5).map((e=>` - Line ${e.line}: \`${e.actually_matched.substring(0,40)}${e.actually_matched.length>40?"...":""}\` (${e.match_type})`)).join("\n")+"\n",e.details.length>5&&(l+=` ... and ${e.details.length-5} more matches\n`)),e.similarMatches&&e.similarMatches.length>0&&(l+=" **Did you mean? (Similar matches found):**\n",l+=e.similarMatches.map((e=>` - Line ${e.line}: \`${e.text.substring(0,60)}${e.text.length>60?"...":""}\` (${e.reason}, similarity: ${(100*e.similarity).toFixed(0)}%)`)).join("\n")+"\n")}l+="\n"}const d=e.filter((e=>"document"===e.type&&(e.success||e.successfulReplacements>0)))
|
|
5342
5299
|
return d.length>0&&(l+=`\n**Document Changes:** ${d.length} modified document(s) synced back to tracking system.\n`),o.workspaceManager?.largeFileWarning&&(l+=o.workspaceManager.largeFileWarning,o.workspaceManager.largeFileWarning=""),l}(F,B,U,G,t,v)
|
|
5343
|
-
return{content:[{type:"text",text:
|
|
5344
|
-
if(
|
|
5300
|
+
return{content:[{type:"text",text:Y}],isError:0===U}}catch(e){const t=Date.now()-I
|
|
5301
|
+
if(b.error("Replace in files batch operation failed",{error:e instanceof Error?e.stack:e+"",duration:t,phase:C}),v)try{await o.updateToolRecord(v,{metadata:{status:"failed",error:(0,k.getErrorMessage)(e),phase:C,duration:t}})}catch(e){}return a.incrementCounter("replace_in_files_errors",1,{phase:C}),{content:[{type:"text",text:"\u274c **Replace In Files Failed:** "+(0,k.getErrorMessage)(e)}],isError:!0}}}
|
|
5345
5302
|
const l=c(t(1943)),d=(a(t(9896)),a(t(6928)),c(t(6982)),t(6183)),u=a(t(5967)),h=t(3626),g=t(9860),p=t(5003),f=t(7478),m=t(9949),y=t(9947),w=t(1318),k=t(8824)},9470(e,exports){Object.defineProperty(exports,"__esModule",{value:!0}),exports.parseLineSpec=function(e){if(!e||""===e.trim())throw Error("Line specification cannot be empty")
|
|
5346
5303
|
const t=e.trim()
|
|
5347
5304
|
if(t.includes("-")){const r=t.split("-").map((e=>e.trim()))
|
|
@@ -5397,14 +5354,14 @@ if(n)s.WorkspaceLogging.logOperation(this.logger,"info","Branch already exists,
|
|
|
5397
5354
|
else{const t=await this.git.revparse(["--abbrev-ref","HEAD"]),r=await this.gitAdapter.branchManager.getBaseBranch()
|
|
5398
5355
|
await this.git.checkout(["-b",i,r]),await this.git.checkout(t),s.WorkspaceLogging.logOperation(this.logger,"info","Created branch and returned to original",e,"single-agent","initializeRequest",{branchName:i,baseBranch:r,returnedTo:t})}const o=Date.now()-r
|
|
5399
5356
|
this.metrics.recordValue("workspace.initialize",o),s.WorkspaceLogging.logOperation(this.logger,"info","Successfully initialized request with branch",e,"single-agent","initializeRequest",{branchName:i,existed:n,duration:o,architecture:"hybrid-creation"})}catch(t){const n=Date.now()-r
|
|
5400
|
-
throw this.metrics.recordValue("workspace.initialize",n),s.WorkspaceLogging.logOperation(this.logger,"error","Failed to initialize request",e,"single-agent","initializeRequest",{error:(0,o.getErrorMessage)(t),duration:n}),t}}async ensureWorkspaceReady(e){const
|
|
5401
|
-
if(!
|
|
5402
|
-
const n
|
|
5403
|
-
if(a
|
|
5404
|
-
try{if(s.WorkspaceLogging.logOperation(this.logger,"info","Ensuring workspace ready by switching to branch",e,"single-agent","ensureWorkspaceReady",{currentBranch:
|
|
5405
|
-
try{await this.switchToRequest(
|
|
5406
|
-
this.metrics.recordValue("workspace.ensure_ready",
|
|
5407
|
-
throw this.metrics.recordValue("workspace.ensure_ready",n),s.WorkspaceLogging.logOperation(this.logger,"error","Failed to ensure workspace ready",e,"single-agent","ensureWorkspaceReady",{error:(0,o.getErrorMessage)(
|
|
5357
|
+
throw this.metrics.recordValue("workspace.initialize",n),s.WorkspaceLogging.logOperation(this.logger,"error","Failed to initialize request",e,"single-agent","initializeRequest",{error:(0,o.getErrorMessage)(t),duration:n}),t}}async ensureWorkspaceReady(e,t){const r=Date.now(),n=s.WorkspaceValidation.validateRequestId(e)
|
|
5358
|
+
if(!n.isValid)throw Error("Invalid request ID: "+n.errors.join(", "))
|
|
5359
|
+
const i=n.sanitized,a="requests/"+i,c=await this.git.revparse(["--abbrev-ref","HEAD"])
|
|
5360
|
+
if(c===a)return this.currentRequestId=i,this.currentBranch=a,void this.logger.debug("Workspace already ready",{requestId:i,currentBranch:this.currentBranch})
|
|
5361
|
+
try{if(s.WorkspaceLogging.logOperation(this.logger,"info","Ensuring workspace ready by switching to branch",e,"single-agent","ensureWorkspaceReady",{currentBranch:c,targetBranch:a,architecture:"hybrid-creation"}),!(await this.git.branch()).all.includes(a))throw Error(`Branch ${a} does not exist. Was initializeRequest() called?`)
|
|
5362
|
+
try{await this.switchToRequest(i)}catch(t){s.WorkspaceLogging.logOperation(this.logger,"warn","switchToRequest failed, trying direct checkout",e,"single-agent","ensureWorkspaceReady",{error:t instanceof Error?t.message:t+"",attempting:"direct-checkout",branchName:a}),await this.git.checkout(a),this.currentRequestId=i,this.currentBranch=a,s.WorkspaceLogging.logOperation(this.logger,"info","Direct checkout succeeded",e,"single-agent","ensureWorkspaceReady",{branchName:a})}const t=Date.now()-r
|
|
5363
|
+
this.metrics.recordValue("workspace.ensure_ready",t),s.WorkspaceLogging.logOperation(this.logger,"info","Workspace is ready",e,"single-agent","ensureWorkspaceReady",{branchName:this.currentBranch,duration:t,architecture:"hybrid-creation"})}catch(t){const n=Date.now()-r
|
|
5364
|
+
throw this.metrics.recordValue("workspace.ensure_ready",n),s.WorkspaceLogging.logOperation(this.logger,"error","Failed to ensure workspace ready",e,"single-agent","ensureWorkspaceReady",{error:(0,o.getErrorMessage)(t),duration:n}),t}}async switchToRequest(e,t){const r=Date.now(),n=this.getCurrentContext(),i=s.WorkspaceValidation.validateRequestId(e)
|
|
5408
5365
|
if(!i.isValid){const t="Invalid request ID: "+i.errors.join(", ")
|
|
5409
5366
|
throw s.WorkspaceLogging.logOperation(this.logger,"error",t,e,"single-agent","switchToRequest"),Error(t)}const a=i.sanitized
|
|
5410
5367
|
try{s.WorkspaceLogging.logOperation(this.logger,"info","Switching to request (assuming branch exists)",e,"single-agent","switchToRequest",{previousBranch:n.branchName,architecture:"aligned-with-multi-agent"})
|
|
@@ -5414,13 +5371,13 @@ const o=Date.now()-r
|
|
|
5414
5371
|
return this.metrics.recordValue("workspace.switch",o),s.WorkspaceLogging.logOperation(this.logger,"info","Successfully switched to request",e,"single-agent","switchToRequest",{branchName:t.branchName,previousBranch:n.branchName,duration:o,architecture:"aligned-with-multi-agent"}),{success:!0,message:"Switched to request "+a,previousContext:n,newContext:this.getCurrentContext()}}catch(t){const n=Date.now()-r
|
|
5415
5372
|
this.metrics.recordValue("workspace.switch",n)
|
|
5416
5373
|
const i=(0,o.getErrorMessage)(t),a=i.includes("does not exist"),c=a?`Branch for request ${e} does not exist. Use initializeRequest() first to create the branch.`:`Failed to switch to request ${e}: ${i}`
|
|
5417
|
-
throw s.WorkspaceLogging.logOperation(this.logger,"error","Failed to switch to request",e,"single-agent","switchToRequest",{error:i,isMissingBranch:a,duration:n,suggestion:a?"Call initializeRequest() first":"Check branch status"}),new s.ConflictDetectionError(c,"single-agent-switch-"+e,[])}}async switchToMain(){const
|
|
5418
|
-
try{const
|
|
5374
|
+
throw s.WorkspaceLogging.logOperation(this.logger,"error","Failed to switch to request",e,"single-agent","switchToRequest",{error:i,isMissingBranch:a,duration:n,suggestion:a?"Call initializeRequest() first":"Check branch status"}),new s.ConflictDetectionError(c,"single-agent-switch-"+e,[])}}async switchToMain(e){const t=Date.now(),r=this.getCurrentContext()
|
|
5375
|
+
try{const e=await this.gitAdapter.branchManager.getBaseBranch(),n=await this.gitAdapter.branchManager.switchToBranch(e)
|
|
5419
5376
|
if(!n.success)throw Error("Failed to switch to main branch: "+n.error)
|
|
5420
|
-
this.currentBranch=
|
|
5421
|
-
const o=Date.now()-
|
|
5422
|
-
return this.metrics.recordValue("workspace.switch_main",o),s.WorkspaceLogging.logOperation(this.logger,"info","Successfully switched to main branch",null,"single-agent","switchToMain",{mainBranch:
|
|
5423
|
-
throw this.metrics.recordValue("workspace.switch_main",r),s.WorkspaceLogging.logOperation(this.logger,"error","Failed to switch to main branch",null,"single-agent","switchToMain",{error:(0,o.getErrorMessage)(
|
|
5377
|
+
this.currentBranch=e,this.currentRequestId=null
|
|
5378
|
+
const o=Date.now()-t
|
|
5379
|
+
return this.metrics.recordValue("workspace.switch_main",o),s.WorkspaceLogging.logOperation(this.logger,"info","Successfully switched to main branch",null,"single-agent","switchToMain",{mainBranch:e,previousBranch:r.branchName,duration:o,architecture:"aligned-with-multi-agent"}),{success:!0,message:"Switched to "+e,previousContext:r,newContext:this.getCurrentContext()}}catch(e){const r=Date.now()-t
|
|
5380
|
+
throw this.metrics.recordValue("workspace.switch_main",r),s.WorkspaceLogging.logOperation(this.logger,"error","Failed to switch to main branch",null,"single-agent","switchToMain",{error:(0,o.getErrorMessage)(e),duration:r}),new s.ConflictDetectionError("Failed to switch to main: "+(0,o.getErrorMessage)(e),"single-agent",[])}}async commitChanges(e,t){const r=Date.now()
|
|
5424
5381
|
try{t&&t.length>0?await this.git.add(t):await this.git.add("."),await this.git.commit(e)
|
|
5425
5382
|
const n=await this.git.revparse(["HEAD"]),o=Date.now()-r
|
|
5426
5383
|
return this.metrics.recordValue("workspace.commit",o),this.logger.info("Successfully committed changes",{message:e,commitHash:n.substring(0,8),filesCount:t?.length||"all",duration:o}),{hash:n,message:e,files:t||[]}}catch(t){const n=Date.now()-r
|
|
@@ -5428,33 +5385,32 @@ throw this.metrics.recordValue("workspace.commit",n),this.logger.error("Failed t
|
|
|
5428
5385
|
try{s.WorkspaceLogging.logOperation(this.logger,"info","Starting request completion (refactored)",e,"single-agent","completeRequest",{requestTitle:t,skipConflictDetection:r?.skipConflictDetection||!1,architecture:"shared-processor"})
|
|
5429
5386
|
const o=await this.requestProcessor.completeRequest(e,t,{skipConflictDetection:r?.skipConflictDetection||!1}),i=Date.now()-n
|
|
5430
5387
|
return this.metrics.recordValue("workspace.complete",i),s.WorkspaceLogging.logOperation(this.logger,"info","Request completion successful (refactored)",e,"single-agent","completeRequest",{mergeCommitHash:o.mergeCommitHash.substring(0,8),mergedFiles:o.mergedFiles?.length||0,cleanedUp:o.cleanedUp,wasAutoMerged:o.autoMergeInfo?.wasAutoMerged,strategy:o.autoMergeInfo?.strategy,duration:i,architecture:"shared-processor"}),o}catch(t){const r=Date.now()-n
|
|
5431
|
-
throw this.metrics.recordValue("workspace.complete",r),s.WorkspaceLogging.logOperation(this.logger,"error","Request completion failed (refactored)",e,"single-agent","completeRequest",{error:(0,o.getErrorMessage)(t),duration:r,architecture:"shared-processor"}),t}}resolveFilePath(e){return n.default.resolve(this.basePath,e)}async createCommit(e,t){return await this.commitChanges(e,t)}async cancelRequest(e){const t=s.WorkspaceValidation.validateRequestId(e)
|
|
5388
|
+
throw this.metrics.recordValue("workspace.complete",r),s.WorkspaceLogging.logOperation(this.logger,"error","Request completion failed (refactored)",e,"single-agent","completeRequest",{error:(0,o.getErrorMessage)(t),duration:r,architecture:"shared-processor"}),t}}resolveFilePath(e,t){return n.default.resolve(this.basePath,e)}async createCommit(e,t,r){return await this.commitChanges(e,t)}async cancelRequest(e){const t=s.WorkspaceValidation.validateRequestId(e)
|
|
5432
5389
|
if(!t.isValid)throw Error("Invalid request ID: "+t.errors.join(", "))
|
|
5433
5390
|
const r="requests/"+t.sanitized
|
|
5434
|
-
try{s.WorkspaceLogging.logOperation(this.logger,"info","Cancelling request (deleting branch)",e,"single-agent","cancelRequest",{branchName:r,architecture:"aligned-with-multi-agent"}),this.currentBranch===r&&await this.switchToMain(),await this.git.deleteLocalBranch(r),s.WorkspaceLogging.logOperation(this.logger,"info","Successfully cancelled request",e,"single-agent","cancelRequest",{branchName:r,switchedToMain:this.currentBranch!==r})}catch(t){throw s.WorkspaceLogging.logOperation(this.logger,"error","Failed to cancel request",e,"single-agent","cancelRequest",{branchName:r,error:(0,o.getErrorMessage)(t)}),t}}async listActiveWorkspaces(){try{return(await this.git.branch()).all.filter((e=>e.startsWith("requests/"))).map((e=>({requestId:e.replace("requests/",""),path:this.basePath,branchName:e,isActive:this.currentBranch===e,created:new Date,lastAccessed:new Date})))}catch(e){return this.logger.error("Failed to list active workspaces",{error:(0,o.getErrorMessage)(e)}),[]}}getCurrentContext(){return{requestId:this.currentRequestId,basePath:this.basePath,branchName:this.currentBranch,isMainBranch:"main"===this.currentBranch||"master"===this.currentBranch,mode:"single-agent"}}async getWorkspaceInfo(e){try{const t=s.WorkspaceValidation.validateRequestId(e)
|
|
5391
|
+
try{s.WorkspaceLogging.logOperation(this.logger,"info","Cancelling request (deleting branch)",e,"single-agent","cancelRequest",{branchName:r,architecture:"aligned-with-multi-agent"}),this.currentBranch===r&&await this.switchToMain(),await this.git.deleteLocalBranch(r),s.WorkspaceLogging.logOperation(this.logger,"info","Successfully cancelled request",e,"single-agent","cancelRequest",{branchName:r,switchedToMain:this.currentBranch!==r})}catch(t){throw s.WorkspaceLogging.logOperation(this.logger,"error","Failed to cancel request",e,"single-agent","cancelRequest",{branchName:r,error:(0,o.getErrorMessage)(t)}),t}}async listActiveWorkspaces(){try{return(await this.git.branch()).all.filter((e=>e.startsWith("requests/"))).map((e=>({requestId:e.replace("requests/",""),path:this.basePath,branchName:e,isActive:this.currentBranch===e,created:new Date,lastAccessed:new Date})))}catch(e){return this.logger.error("Failed to list active workspaces",{error:(0,o.getErrorMessage)(e)}),[]}}getCurrentContext(e){return{requestId:this.currentRequestId,basePath:this.basePath,branchName:this.currentBranch,isMainBranch:"main"===this.currentBranch||"master"===this.currentBranch,mode:"single-agent"}}async getWorkspaceInfo(e){try{const t=s.WorkspaceValidation.validateRequestId(e)
|
|
5435
5392
|
if(!t.isValid)return null
|
|
5436
5393
|
const r=t.sanitized,n="requests/"+r,o=await this.git.branch()
|
|
5437
|
-
return o.all.includes(n)||o.all.includes("remotes/origin/"+n)?{requestId:r,path:this.basePath,branchName:n,isActive:this.currentBranch===n,created:new Date,lastAccessed:new Date}:null}catch(t){return this.logger.error("Failed to get workspace info",{requestId:e,error:(0,o.getErrorMessage)(t)}),null}}getMainGit(){return this.gitAdapter.getMainGit()}async getWorktreeInfo(e){}getCurrentGit(){return this.git}async ensureReadonlyBranchIfNeeded(e,r,n
|
|
5438
|
-
try{
|
|
5439
|
-
if(!
|
|
5440
|
-
|
|
5441
|
-
|
|
5442
|
-
|
|
5443
|
-
|
|
5444
|
-
|
|
5445
|
-
|
|
5446
|
-
this.
|
|
5447
|
-
|
|
5448
|
-
|
|
5449
|
-
|
|
5450
|
-
|
|
5451
|
-
|
|
5452
|
-
|
|
5453
|
-
|
|
5454
|
-
|
|
5455
|
-
this.
|
|
5456
|
-
|
|
5457
|
-
g.all.includes(h)||g.all.includes("remotes/origin/"+h)?(await this.git.checkout(h),this.currentBranch=h,this.currentRequestId=u,this.logger.info("Successfully switched to readonly branch",{currentBranch:this.currentBranch,currentRequestId:this.currentRequestId})):this.logger.warn("Readonly branch does not exist",{readonlyBranch:h})}catch(e){this.logger.debug("Error during readonly branch check",{error:(0,o.getErrorMessage)(e)})}}}async fetchAgentConfig(e){try{const t="http://localhost:3456/api/agents/by-name/"+encodeURIComponent(e),r=await fetch(t)
|
|
5394
|
+
return o.all.includes(n)||o.all.includes("remotes/origin/"+n)?{requestId:r,path:this.basePath,branchName:n,isActive:this.currentBranch===n,created:new Date,lastAccessed:new Date}:null}catch(t){return this.logger.error("Failed to get workspace info",{requestId:e,error:(0,o.getErrorMessage)(t)}),null}}getMainGit(){return this.gitAdapter.getMainGit()}async getWorktreeInfo(e){}getCurrentGit(e){return this.git}async ensureReadonlyBranchIfNeeded(e,t,r,n){if(!this.readonlyBranchCheckDone){this.readonlyBranchCheckDone=!0
|
|
5395
|
+
try{const e=n
|
|
5396
|
+
if(!e)return void this.logger.debug("No sessionId available for readonly check")
|
|
5397
|
+
this.logger.debug("Checking readonly branch for session",{sessionId:e,toolName:t})
|
|
5398
|
+
const o=r?.getCLISessionClient?.()
|
|
5399
|
+
if(!o)return void this.logger.debug("No CLI session client available for readonly check")
|
|
5400
|
+
const s=await o.getByExternalId(e)
|
|
5401
|
+
if(!s?.agentType)return void this.logger.debug("No agent type found for session",{sessionId:e})
|
|
5402
|
+
this.logger.debug("Found session agent type",{sessionId:e,agentType:s.agentType})
|
|
5403
|
+
const i=await this.fetchAgentConfig(s.agentType)
|
|
5404
|
+
if(!i||"readonly"!==i.requestContextMode)return void this.logger.debug("Agent does not have readonly requestContextMode",{agentType:s.agentType})
|
|
5405
|
+
this.logger.debug("Agent has readonly requestContextMode",{agentType:s.agentType})
|
|
5406
|
+
const a=r?.getSessionRequestAssociationClient?.()
|
|
5407
|
+
if(!a)return void this.logger.debug("No session association client available")
|
|
5408
|
+
const c=await a.getActiveRequestsForSession(e,!0)
|
|
5409
|
+
if(0===c.length)return void this.logger.debug("No active request association found for session",{sessionId:e})
|
|
5410
|
+
const l=c[0].requestLocalId,d="requests/"+l
|
|
5411
|
+
this.logger.info("Readonly agent with request association, switching to branch without locking",{sessionId:e,agentType:s.agentType,requestId:l,readonlyBranch:d})
|
|
5412
|
+
const u=await this.git.branch()
|
|
5413
|
+
u.all.includes(d)||u.all.includes("remotes/origin/"+d)?(await this.git.checkout(d),this.currentBranch=d,this.currentRequestId=l,this.logger.info("Successfully switched to readonly branch",{currentBranch:this.currentBranch,currentRequestId:this.currentRequestId})):this.logger.warn("Readonly branch does not exist",{readonlyBranch:d})}catch(e){this.logger.debug("Error during readonly branch check",{error:(0,o.getErrorMessage)(e)})}}}async fetchAgentConfig(e){try{const t="http://localhost:3456/api/agents/by-name/"+encodeURIComponent(e),r=await fetch(t)
|
|
5458
5414
|
if(!r.ok)return null
|
|
5459
5415
|
const n=await r.json()
|
|
5460
5416
|
return n.success?n.data??null:null}catch{return null}}async cleanup(){this.logger.info("Cleaning up single-agent workspace manager")}}},9671(e,exports){Object.defineProperty(exports,"__esModule",{value:!0}),exports.findPreviousCommit=async function(e,t,r){try{if(!r){const r=await e.raw(["rev-list","--max-count=1","HEAD","--",t])
|