alchemylab 1.0.6 → 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 +137 -110
- package/dist/http-server.js +680 -717
- package/dist/index.js +582 -619
- package/dist/mcp-direct.js +813 -850
- 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,37 +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
|
-
|
|
827
|
-
|
|
828
|
-
if(
|
|
829
|
-
if(n)n.sessionId!==e&&((0,p.logSessionIdentity)(i,"_meta-session-switch",{prevSessionId:n.sessionId,prevAgentType:n.agentType,newSessionId:e}),u.sessionIdentity.setIdentity({providerId:"opencode",sessionId:e,serverUrl:n.serverUrl}))
|
|
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))
|
|
830
828
|
else{const r=await(0,d.getServerUrl)(t,m)
|
|
831
|
-
u.sessionIdentity.setIdentity({providerId:"opencode",sessionId:e,serverUrl:r||""})
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
t?(u.sessionIdentity.setIdentity({providerId:"opencode",sessionId:t.sessionId,serverUrl:e.serverUrl}),(0,p.logSessionIdentity)(i,"re-discovery",{sessionId:t.sessionId,messageId:t.messageId}),_=u.sessionIdentity.buildCliOrigin(t.messageId)):(u.sessionIdentity.setIdentity(e),_=u.sessionIdentity.buildCliOrigin(),m.info("Re-discovery found no other session, keeping current identity",{sessionId:e.sessionId})),u.sessionIdentity.markDiscoveryAttempted()}catch(t){u.sessionIdentity.setIdentity(e),_=u.sessionIdentity.buildCliOrigin(),u.sessionIdentity.markDiscoveryAttempted(),m.warn("Re-discovery failed, keeping current identity (may be stale)",{error:(0,l.getErrorMessage)(t),tool:i,sessionId:e.sessionId})}}}else if(!u.sessionIdentity.hasDiscoveryBeenAttempted())try{const e=await(0,d.getServerUrl)(t,m)
|
|
838
|
-
if(e){const t=await(0,d.getAndStoreSessionId)(e,m,i)
|
|
839
|
-
t&&(u.sessionIdentity.setIdentity({providerId:"opencode",sessionId:t.sessionId,serverUrl:e}),(0,p.logSessionIdentity)(i,"http-discovery",{sessionId:t.sessionId,messageId:t.messageId}),_=u.sessionIdentity.buildCliOrigin(t.messageId))}u.sessionIdentity.markDiscoveryAttempted()}catch(e){u.sessionIdentity.markDiscoveryAttempted(),(0,p.logSessionIdentity)(i,"discovery-failed",{error:(0,l.getErrorMessage)(e)}),m.debug("cliOrigin discovery failed",{error:(0,l.getErrorMessage)(e),tool:i})}}if(u.sessionIdentity.setCurrentCallOrigin(_),!v&&n){const e=u.sessionIdentity.getIdentity(),t=process.env.ALCHEMY_INITIAL_BRANCH
|
|
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()
|
|
833
|
+
try{const e=await(0,d.getServerUrl)(t,m)
|
|
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
|
|
840
835
|
if(e?.sessionId&&t){const r=t.match(/^requests\/(.+)$/),o="1"===process.env.ALCHEMY_ALLOW_PARALLEL
|
|
841
836
|
if(r&&!o){const t=r[1]
|
|
842
837
|
v=!0
|
|
843
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()
|
|
844
|
-
await Promise.all([i,a])}catch(e){m.warn("Error in session tag mapping / lock acquisition",{error:(0,l.getErrorMessage)(e)})}}}}
|
|
845
|
-
|
|
846
|
-
|
|
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"})
|
|
847
843
|
let r="Unknown error"
|
|
848
844
|
if(t instanceof Error)r=t.message
|
|
849
845
|
else if("string"==typeof t)r=t
|
|
@@ -1180,94 +1176,92 @@ const e=this.online,t=await this.performHealthCheck()
|
|
|
1180
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
|
|
1181
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
|
|
1182
1178
|
const r=t(6183),n=t(355)
|
|
1183
|
-
exports.def={name:"complete_task",description:"Mark a task as completed with a summary of work done.",schema:r.CompleteTaskSchema,annotations:{title:"Complete Task",readOnlyHint:!1,destructiveHint:!1,idempotentHint:!0},handler(e,t){return(0,n.handleCompleteTask)(e,t.context,t.apiClient,t.logger,t.metrics,t.mcpServer)}}},1725(e,exports,t){function r(e,t,r){try{const n=`[${(new Date).toISOString()}] ${t}${r?" "+JSON.stringify(r):""}\n`,o=(0,
|
|
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)
|
|
1184
1180
|
if(!r.ok)return null
|
|
1185
1181
|
const n=await r.json()
|
|
1186
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
|
|
1187
|
-
if(r(t,"handleSpawn called",{agent:a,promptLength:c.length,requestId:l,useExistingSession:u,cliOriginSessionId:i?.sessionId||null}),!(0,
|
|
1188
|
-
return{content:[{type:"text",text:`\u274c Unknown agent '${a}'.\n\n**Available agents:** ${e.join(", ")}\n\nChoose one of the available agents listed above to see detailed descriptions of each agent.`}],isError:!0}}try{const e=
|
|
1189
|
-
let
|
|
1190
|
-
if(r(t,"Spawn agent type check",{
|
|
1191
|
-
r(t,"Looking up agent type from action server",{sessionId:
|
|
1192
|
-
const s=await fetch(
|
|
1193
|
-
if(s.ok){const
|
|
1194
|
-
r(t,"Agent type response from action server",{sessionId:
|
|
1195
|
-
if(e&&!e.includes(a))return{content:[{type:"text",text:`\u274c Agent type '${
|
|
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)()
|
|
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
|
|
1196
1192
|
try{const e=await n(a)
|
|
1197
|
-
if(h=e?.requestContextMode,!h){const e=(0,
|
|
1193
|
+
if(h=e?.requestContextMode,!h){const e=(0,P.getBuiltInAgentConfig)(a)
|
|
1198
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}
|
|
1199
1195
|
const g=await(0,I.getServerUrl)(t,o)
|
|
1200
1196
|
r(t,"serverUrl resolved",{serverUrl:g})
|
|
1201
1197
|
const p=t.basePath
|
|
1202
1198
|
if(!p)throw new w.ValidationError("Working directory not available in context")
|
|
1203
|
-
const f=
|
|
1204
|
-
let m
|
|
1205
|
-
if(g)try{m=i?.sessionId||f?.sessionId||await(0,I.discoverParentSessionId)(g,o)}catch{}let y=""
|
|
1199
|
+
const f=i?.sessionId
|
|
1200
|
+
let m=""
|
|
1206
1201
|
if(s&&l)try{const e=s.getSessionRequestAssociationClient()
|
|
1207
|
-
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
|
|
1208
1203
|
if(r.length>0){const e=r.map((e=>e.opencodeSessionId)).join(", ")
|
|
1209
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}
|
|
1210
|
-
|
|
1211
|
-
l&&(
|
|
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}`)
|
|
1212
1207
|
let S=!1
|
|
1213
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")
|
|
1214
1209
|
try{let e
|
|
1215
|
-
try{const t=await fetch(`http://localhost:${
|
|
1210
|
+
try{const t=await fetch(`http://localhost:${j}/api/project-settings`)
|
|
1216
1211
|
if(t.ok){const r=await t.json()
|
|
1217
1212
|
if(r.data?.defaultModel){const[t,...n]=r.data.defaultModel.split("/")
|
|
1218
|
-
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:
|
|
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)})
|
|
1219
1214
|
if(!r.ok){const e=await r.text().catch((()=>"Unknown error"))
|
|
1220
|
-
throw Error(`Failed to send to existing session: ${r.status} ${e}`)}o.info("Prompt sent to existing session",{sessionId:_,agent:a})}catch(e){throw Error("Failed to use existing session: "+(0,
|
|
1221
|
-
const i=
|
|
1222
|
-
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?"...":""}`,
|
|
1223
|
-
if(!
|
|
1224
|
-
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()
|
|
1225
1220
|
if(!w.id)throw Error("Session created but no ID returned")
|
|
1226
|
-
const
|
|
1227
|
-
r(t,"Pre-created session with parentID",{preCreatedSessionId:
|
|
1228
|
-
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()
|
|
1229
1224
|
if(!n)return
|
|
1230
1225
|
let o,c
|
|
1231
|
-
if(i){const e=await n.createOrUpdateSession({externalSessionId:i,providerId:"opencode",status:"active",agentType:
|
|
1232
|
-
o=e.id,c=e.workflowId,r(t,"Registered parent session in DB",{parentSessionId:i,parentDbId:o,parentWorkflowId:c})}const l=await n.createOrUpdateSession({externalSessionId:
|
|
1233
|
-
r(t,"Registered child session in DB",{childSessionId:
|
|
1234
|
-
let
|
|
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
|
|
1235
1230
|
r(t,"Starting model resolution",{agent:a,cwd:p})
|
|
1236
|
-
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}`})
|
|
1237
1232
|
const e=await n(a)
|
|
1238
1233
|
if(r(t,"Agent config result",{agent:a,agentConfig:e||"null",hasConfig:!!e}),e){const n=e.preferredProvider||"inherit",o=e.preferredModelTier||"same"
|
|
1239
1234
|
r(t,"Agent preferences",{agent:a,preferredProvider:n,preferredTier:o,rawProvider:e.preferredProvider,rawTier:e.preferredModelTier})
|
|
1240
|
-
const s=(0,
|
|
1241
|
-
r(t,"Model resolution result",{agent:a,result:s}),s.resolved?(
|
|
1235
|
+
const s=(0,M.resolveAgentModel)(p,n,o)
|
|
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)
|
|
1242
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"
|
|
1243
1238
|
r(t,"Using built-in agent preferences",{agent:a,preferredProvider:n,preferredTier:o})
|
|
1244
|
-
const s=(0,
|
|
1245
|
-
r(t,"Built-in model resolution result",{agent:a,result:s}),s.resolved&&(
|
|
1239
|
+
const s=(0,M.resolveAgentModel)(p,n,o)
|
|
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)
|
|
1246
1241
|
if(t.ok){const e=await t.json()
|
|
1247
1242
|
return e?.data?.defaultModel||null}}catch{}return null}()
|
|
1248
|
-
if(e)if(
|
|
1249
|
-
"same"===(o?.preferredModelTier||"same")&&(
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
_
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
return u?R+=`Prompt sent to existing session ${_}.`:(R+=`Background ${a} subagent spawned successfully.`,_&&"unknown"!==_&&"spawning"!==_&&(R+=`\n[SESSION:${_}]`)),l&&(R+="\nWorking on: "+l),R+="\n\nThe subagent is now working independently. You can continue with other tasks.",{content:[{type:"text",text:R}]}}async function s(e,t,r,n,o,s,i){const a=await(0,I.getServerUrl)(r,n)
|
|
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
|
-
o||(o=await r.createOrUpdateSession({externalSessionId:t,providerId:"opencode",status:"active"}),n.info("Created caller session in DB for re-parenting",{callerSessionId:t,dbId:o?.id})),o&&(await r.createOrUpdateSession({externalSessionId:e,providerId:"opencode",parentSessionId:o.id,status:"active"}),n.info("Updated parent session for reused agent",{sessionId:e,newParentSessionId:t}))}}}catch(e){n.warn("Failed to update parent session - reports may go to wrong parent",{error:(0,
|
|
1261
|
-
if(!c)try{const t=`http://localhost:${
|
|
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
|
|
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)})
|
|
1269
1263
|
if(!s.ok){const e=await s.text().catch((()=>"Unknown error"))
|
|
1270
|
-
throw Error(`Failed to send message: ${s.status} ${e}`)}return n.info("Message sent to subagent session",{sessionId:e,agent:c}),{content:[{type:"text",text:`Message sent to session ${e}.\nThe subagent will process it in the background.`}]}}catch(e){throw Error("Failed to continue session: "+(0,
|
|
1264
|
+
throw Error(`Failed to send message: ${s.status} ${e}`)}return n.info("Message sent to subagent session",{sessionId:e,agent:c}),{content:[{type:"text",text:`Message sent to session ${e}.\nThe subagent will process it in the background.`}]}}catch(e){throw Error("Failed to continue session: "+(0,q.getErrorMessage)(e))}}function i(e){const t=Math.floor(e/1e3)
|
|
1271
1265
|
if(60>t)return t+"s"
|
|
1272
1266
|
const r=Math.floor(t/60)
|
|
1273
1267
|
return 60>r?`${r}m ${t%60}s`:`${Math.floor(r/60)}h ${r%60}m`}function a(e){const t=[]
|
|
@@ -1277,7 +1271,7 @@ 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&&R>n?{status:"working",detail:"last action "+c(n),isReady:!1}:n>
|
|
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
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)
|
|
@@ -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,
|
|
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,16 +1331,16 @@ 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
|
-
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,
|
|
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)
|
|
1350
1344
|
var o=Object.getOwnPropertyDescriptor(t,r)
|
|
1351
1345
|
o&&!("get"in o?!t.__esModule:o.writable||o.configurable)||(o={enumerable:!0,get(){return t[r]}}),Object.defineProperty(e,n,o)}:function(e,t,r,n){void 0===n&&(n=r),e[n]=t[r]}),m=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),y=this&&this.__importStar||(p=function(e){return p=Object.getOwnPropertyNames||function(e){var t=[]
|
|
1352
1346
|
for(var r in e)({}).hasOwnProperty.call(e,r)&&(t[t.length]=r)
|
|
@@ -1356,7 +1350,7 @@ if(null!=e)for(var r=p(e),n=0;n<r.length;n++)"default"!==r[n]&&f(t,e,r[n])
|
|
|
1356
1350
|
return m(t,e),t})
|
|
1357
1351
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleSpawn=o,exports.handleContinue=s,exports.handleCheckStatus=u,exports.handleAbort=h,exports.handleListSessions=g,exports.handleSubagentOperations=async function(e,t,r,n,i,a){const c=r.child({tool:"subagent_operations"}),l=n.startTimer("tool_execution_time")
|
|
1358
1352
|
try{if(e&&!e.operation&&(e.spawn?e.operation="spawn":e.continue?e.operation="continue":e.readMessages?e.operation="read-messages":e.listSessions?e.operation="list-sessions":e.prompt&&(e.agent||e.description)?e={operation:"spawn",spawn:{agent:e.agent||"coder",prompt:e.prompt,description:e.description||e.prompt.slice(0,60),requestId:e.requestId,allowParallel:e.allowParallel,useExistingSession:e.useExistingSession}}:e.sessionId&&e.prompt&&!e.spawn?e={operation:"continue",sessionId:e.sessionId,continue:{prompt:e.prompt}}:e.sessionId&&(e={operation:"check-status",sessionId:e.sessionId})),e?.spawn&&"string"==typeof e.spawn)try{e.spawn=JSON.parse(e.spawn)}catch{}if(e?.continue&&"string"==typeof e.continue)try{e.continue=JSON.parse(e.continue)}catch{}"spawn"===e?.operation&&e?.prompt&&!e?.spawn&&(e.spawn={agent:e.agent||"coder",prompt:e.prompt,description:e.description||e.prompt.slice(0,60),requestId:e.requestId},delete e.prompt,delete e.agent,delete e.description,delete e.requestId),"continue"===e?.operation&&e?.prompt&&!e?.continue&&(e.continue={prompt:e.prompt},delete e.prompt)
|
|
1359
|
-
const r=
|
|
1353
|
+
const r=E.validateArgs(e,_.SubagentOperationsSchema),{sessionId:d,operation:p}=r
|
|
1360
1354
|
let f
|
|
1361
1355
|
switch(c.info("Processing subagent_operations",{operation:p,sessionId:d}),p){case"spawn":f=await o(r.spawn,t,c,i,a)
|
|
1362
1356
|
break
|
|
@@ -1376,13 +1370,13 @@ throw Error("Failed to fetch messages: "+n.status)}const s=await n.json()
|
|
|
1376
1370
|
if(0===s.length)return{content:[{type:"text",text:`Session ${e} has no messages yet.`}]}
|
|
1377
1371
|
const i=s.map(((e,t)=>{const r="user"===e.info.role?"USER":"ASSISTANT",n=e.parts.filter((e=>"text"===e.type&&e.text)).map((e=>e.text)).join("\n"),o=n.length>5e3?n.slice(0,5e3)+"...[truncated]":n
|
|
1378
1372
|
return`[${t+1}] ${r} (${new Date(e.info.time.created).toLocaleTimeString()}):\n${o}`})).join("\n\n---\n\n")
|
|
1379
|
-
return{content:[{type:"text",text:`Session ${e} - Last ${s.length} messages:\n\n${i}`}]}}catch(e){throw Error("Failed to read messages: "+(0,
|
|
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
|
-
default:throw new w.ValidationError("Unknown operation: "+p)}return l({success:!0}),n.incrementCounter(`subagent_operations_${p}_success`,1),f}catch(e){return c.error("Subagent operations failed",{error:e instanceof Error?e.stack:e+""}),l({success:!1}),n.incrementCounter("subagent_operations_errors",1),{content:[{type:"text",text:"Subagent operation failed: "+(0,
|
|
1385
|
-
const w=t(9860),k=t(8035),I=t(7617),
|
|
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}}}
|
|
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,24 +1696,32 @@ 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",
|
|
1719
|
-
const a=i(t(1943)),c=i(t(6928)),l=t(6183),d=s(t(5967)),u=t(9860),h=t(1569),g=t(7478),p=t(8824)},2422(module){module.exports=require("@modelcontextprotocol/sdk/server/sse.js")},
|
|
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)}}
|
|
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)
|
|
1714
|
+
if((0,r.existsSync)(l))return void i.info("Worktree already exists on disk, skipping pre-spawn creation",{requestId:t,worktreePath:l})
|
|
1715
|
+
const d=(0,o.simpleGit)(e);(0,r.mkdirSync)(c,{recursive:!0})
|
|
1716
|
+
try{await d.raw(["worktree","prune"])}catch{}const u=await d.branch(),h=u.all.includes(a)
|
|
1717
|
+
try{if(h)await d.raw(["worktree","add",l,a]),i.info("Pre-spawn: created worktree for existing branch",{requestId:t,branchName:a,worktreePath:l})
|
|
1718
|
+
else{const e=u.all.includes("main")?"main":"master"
|
|
1719
|
+
await d.raw(["worktree","add","-b",a,l,e]),i.info("Pre-spawn: created worktree with new branch from latest main",{requestId:t,branchName:a,mainBranch:e,worktreePath:l})}}catch(e){const r=e instanceof Error?e.message:e+""
|
|
1720
|
+
i.warn("Pre-spawn: failed to create worktree (MCP process will retry)",{requestId:t,error:r})}}
|
|
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
|
|
1720
1722
|
const r=t(6183),n=t(3707)
|
|
1721
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})
|
|
1722
|
-
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
|
|
1723
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]"
|
|
1724
1726
|
let l=""
|
|
1725
1727
|
if(s||void 0===o?.lineCount||(l=` (${i(o.lineCount)} lines)`),s&&o?.subtreeTotals){const{files:e,lines:t}=o.subtreeTotals
|
|
@@ -1735,14 +1737,14 @@ if(30>s)return`${s} day${1===s?"":"s"} ago`
|
|
|
1735
1737
|
const i=Math.floor(s/30)
|
|
1736
1738
|
if(12>i)return`${i} month${1===i?"":"s"} ago`
|
|
1737
1739
|
const a=Math.floor(i/12)
|
|
1738
|
-
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)})`)
|
|
1739
1741
|
break
|
|
1740
1742
|
case"size":s||"number"!=typeof o.size||(l+=` (${function(e){if(0===e)return"0 bytes"
|
|
1741
1743
|
let t=e,r=0
|
|
1742
1744
|
for(;t>=1024&&4>r;)t/=1024,r++
|
|
1743
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[]
|
|
1744
|
-
try{const{fullPath:d}=
|
|
1745
|
-
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():""
|
|
1746
1748
|
let m
|
|
1747
1749
|
d.isFile()&&(m=await r(h,p.size,f))
|
|
1748
1750
|
const k={name:d.name,isDirectory:d.isDirectory(),depth:n,size:p.size,modified:p.mtime,extension:f,lineCount:m}
|
|
@@ -1751,8 +1753,8 @@ const o=[]
|
|
|
1751
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?"/":""
|
|
1752
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)
|
|
1753
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}
|
|
1754
|
-
try{const{fullPath:n}=
|
|
1755
|
-
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)
|
|
1756
1758
|
if(n.isDirectory())o.directories+=1
|
|
1757
1759
|
else{o.files+=1
|
|
1758
1760
|
const e=await y.default.stat(i),t=w.default.extname(n.name).toLowerCase(),s=await r(i,e.size,t)
|
|
@@ -1778,27 +1780,27 @@ var t={}
|
|
|
1778
1780
|
if(null!=e)for(var r=h(e),n=0;n<r.length;n++)"default"!==r[n]&&g(t,e,r[n])
|
|
1779
1781
|
return p(t,e),t}),m=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
1780
1782
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleListDirectory=async function(e,t,i,a){const h=Date.now()
|
|
1781
|
-
let g=
|
|
1782
|
-
|
|
1783
|
-
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
|
|
1784
1786
|
i.info("Listing directory: "+f)
|
|
1785
|
-
const{normalizedPath:C,fullPath:_}=
|
|
1786
|
-
g=
|
|
1787
|
+
const{normalizedPath:C,fullPath:_}=b.validateAndNormalizePath(f,t)
|
|
1788
|
+
g=b.FileOperationPhase.FILE_WRITE
|
|
1787
1789
|
try{if(!(await y.default.stat(_)).isDirectory())return{content:[{type:"text",text:"Path is not a directory: "+f}],isError:!0}
|
|
1788
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
|
|
1789
|
-
if(m>1){i.info(`Building tree structure for: ${C} (levels: ${m}, sortBy: ${
|
|
1790
|
-
const e=await o(C,t,0,m,
|
|
1791
|
-
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)
|
|
1792
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=[]
|
|
1793
|
-
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():""
|
|
1794
1796
|
let c
|
|
1795
|
-
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)))
|
|
1796
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()
|
|
1797
1799
|
E+="\n\nBranch: "+(S?.branchName||"unknown")
|
|
1798
1800
|
const T=Date.now()-h
|
|
1799
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
|
|
1800
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}}}
|
|
1801
|
-
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}}
|
|
1802
1804
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.ProjectSynchronizer=void 0
|
|
1803
1805
|
const n=r(t(6928)),o=t(8029),s=t(8824),i=t(2096)
|
|
1804
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)
|
|
@@ -1977,11 +1979,11 @@ const f=await Promise.all(p)
|
|
|
1977
1979
|
let m=""
|
|
1978
1980
|
if(t.getCurrentBranchContext)try{const e=await t.getCurrentBranchContext()
|
|
1979
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
|
|
1980
|
-
let
|
|
1981
|
-
m&&(
|
|
1982
|
+
let b="## Read Files/Documents\n\n"
|
|
1983
|
+
m&&(b+=m),b+=`**Total Requests:** ${k} - **Successful:** ${y} - **Failed:** ${w}\n\n`
|
|
1982
1984
|
for(let e=0;e<f.length;e++){const t=f[e]
|
|
1983
|
-
"file"===t.type?
|
|
1984
|
-
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
|
|
1985
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}}}
|
|
1986
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
|
|
1987
1989
|
const r=t(8824),n=t(7645),o=t(2161),s=t(5172)
|
|
@@ -2094,12 +2096,12 @@ d.info("Generating journal for request",{requestId:c})
|
|
|
2094
2096
|
const h=t.projectId
|
|
2095
2097
|
if(!h)throw(0,n.createValidationError)("Project ID is required. Make sure you are in a project context.")
|
|
2096
2098
|
o.setProjectId(h),d.info("Fetching request data, tasks, and file history in parallel")
|
|
2097
|
-
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})))
|
|
2098
2100
|
d.info(`Fetched request, ${C.length} tasks, ${w.length} tool records`)
|
|
2099
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()))
|
|
2100
2102
|
for(const e of o){const o=r(e),s=e.metadata?.comment||e.metadata?.userComment||"No comment"
|
|
2101
2103
|
n.push({type:e.type,timestamp:e.createdAt,comment:s,files:o,recordId:e.localId||e.id})
|
|
2102
|
-
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..."`
|
|
2103
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}}}
|
|
2104
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
|
|
2105
2107
|
try{const n=await r.configManager.getEffectiveConfig(r.mainBasePath)
|
|
@@ -2216,7 +2218,7 @@ var t={}
|
|
|
2216
2218
|
if(null!=e)for(var r=o(e),n=0;n<r.length;n++)"default"!==r[n]&&s(t,e,r[n])
|
|
2217
2219
|
return i(t,e),t}),c=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
2218
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()
|
|
2219
|
-
let k,I
|
|
2221
|
+
let k,b,I=u.FileOperationPhase.VALIDATION
|
|
2220
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"}
|
|
2221
2223
|
try{const i=u.validateArgs(e,d.ReplaceStringsSchema),{taskId:C,operations:_,comment:E}=i
|
|
2222
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")
|
|
@@ -2229,21 +2231,21 @@ if(S.length>0&&!t.documentFileManager)throw Error("Document file manager not ava
|
|
|
2229
2231
|
for(const e of S)P.push({type:"document",documentId:e.documentId,replacements:e.replacements,mode:e.mode||"unique"})
|
|
2230
2232
|
if(P.length>0&&t.apiClient){const e=P.map((e=>e.documentId))
|
|
2231
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}
|
|
2232
|
-
throw e}}
|
|
2233
|
-
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
|
|
2234
2236
|
let x=null
|
|
2235
|
-
T.length>0&&
|
|
2237
|
+
T.length>0&&R&&(x=await u.validateWorkItemStates(C,T[0].path,r,s,t,y,a,v.metricsPrefix))
|
|
2236
2238
|
let O={taskPromoted:!1,requestPromoted:!1}
|
|
2237
|
-
T.length>0&&
|
|
2238
|
-
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})
|
|
2239
2241
|
if(!A.success){if(A.isLockConflict)return{content:[{type:"text",text:"\u274c "+A.error}],isError:!0}
|
|
2240
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})
|
|
2241
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)
|
|
2242
|
-
T[e]={...r,path:o,fullPath:s}}}if(P.length>0&&
|
|
2243
|
-
throw e}
|
|
2244
|
-
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,
|
|
2245
|
-
if(k=$,I
|
|
2246
|
-
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)
|
|
2247
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})
|
|
2248
2250
|
const F=[]
|
|
2249
2251
|
let N=0,L=0
|
|
@@ -2255,17 +2257,17 @@ try{const o=await t.documentFileManager.getDocumentAsFile(e.documentId),s=t.docu
|
|
|
2255
2257
|
r.filename=s?.filename
|
|
2256
2258
|
const i=await l.default.readFile(o,"utf8"),{newContent:a,results:c}=await n(i,e.replacements,e.mode)
|
|
2257
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))
|
|
2258
|
-
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:
|
|
2259
|
-
try{await o.updateToolRecord(
|
|
2260
|
-
let
|
|
2261
|
-
if(t.workspaceManager&&(
|
|
2262
|
-
if(
|
|
2263
|
-
for(const t of e.replacements.filter((e=>!e.success)))
|
|
2264
|
-
for(const e of F){if("file"===e.type?
|
|
2265
|
-
for(const t of e.replacements.filter((e=>!e.success)))
|
|
2266
|
-
const
|
|
2267
|
-
return y.info("Replace strings operation completed",{duration:
|
|
2268
|
-
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}}}
|
|
2269
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)
|
|
2270
2272
|
var o=Object.getOwnPropertyDescriptor(t,r)
|
|
2271
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=[]
|
|
@@ -2351,26 +2353,26 @@ Object.defineProperty(exports,"LogLevel",{enumerable:!0,get(){return s.LogLevel}
|
|
|
2351
2353
|
const r=t(6183),n=t(8317)
|
|
2352
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}}
|
|
2353
2355
|
Object.defineProperty(exports,"__esModule",{value:!0})
|
|
2354
|
-
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})
|
|
2355
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")
|
|
2356
2358
|
q.info("Using remote server URL",{remoteServerUrl:T}),async function(){try{q.info("Finding available port...",{preferredPort:E,baseDir:_,remoteServerUrl:T})
|
|
2357
2359
|
const e=await(0,y.findAvailablePort)(E)
|
|
2358
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})
|
|
2359
2361
|
const t=new l.ProjectRegistry(q),r=new h.DefaultProjectFileSystem(q),c=n.default.join(_,m.ALCHEMY_DIR_NAME)
|
|
2360
2362
|
q.info(`Checking ${m.ALCHEMY_DIR_NAME} directory`,{alchemyPath:c}),await r.ensureDirectoryExists(c)
|
|
2361
|
-
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}})
|
|
2362
2364
|
q.info("Using project",{projectId:M.id,projectName:M.name})
|
|
2363
|
-
const
|
|
2364
|
-
|
|
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))
|
|
2365
2367
|
try{q.info("Creating MCP server instance")
|
|
2366
2368
|
const t=await(0,i.createServer)(_,q,S,T,{existingProjectId:M.id,multiAgentMode:(0,d.isMultiAgentModeEnabled)(_)})
|
|
2367
2369
|
q.info("MCP server instance created successfully")
|
|
2368
2370
|
const r=t.getContext()
|
|
2369
|
-
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")
|
|
2370
2372
|
try{const e=M.id
|
|
2371
|
-
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+""})
|
|
2372
2374
|
let t=!1
|
|
2373
|
-
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
|
|
2374
2376
|
const t=e.toLowerCase().replace(/^\./,"")
|
|
2375
2377
|
return u.has(t)}function n(e,t){if(r(t)){const t=e.match(/^([ \t]*)(.*?)\s*$/)
|
|
2376
2378
|
if(!t)return e
|
|
@@ -2461,18 +2463,18 @@ try{const a=u.validateArgs(e,d.GetFileInfoSchema),{path:h}=a
|
|
|
2461
2463
|
n.info("Getting file info: "+h)
|
|
2462
2464
|
const{normalizedPath:f,fullPath:m}=u.validateAndNormalizePath(h,t)
|
|
2463
2465
|
i=u.FileOperationPhase.FILE_WRITE
|
|
2464
|
-
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},
|
|
2465
|
-
k.isFile&&w&&
|
|
2466
|
-
const
|
|
2467
|
-
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
|
|
2468
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}
|
|
2469
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()
|
|
2470
|
-
try{const y=u.getRequestClient(),w=u.getTaskClient(),k=u.getFileClient(),
|
|
2471
|
-
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})
|
|
2472
2474
|
let E=!1
|
|
2473
2475
|
try{const e=await y.listRequests({limit:2,sortBy:"created_at",sortDirection:"desc"})
|
|
2474
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")
|
|
2475
|
-
const q=await y.createRequest({title:
|
|
2477
|
+
const q=await y.createRequest({title:I,description:v,type:"quick-edit",acceptanceCriteria:["Quick change completed successfully"]})
|
|
2476
2478
|
if(!q||!q.id)throw Error("Failed to create request")
|
|
2477
2479
|
const S=q.id
|
|
2478
2480
|
let T
|
|
@@ -2480,24 +2482,24 @@ f.info("Created request",{requestId:S})
|
|
|
2480
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)
|
|
2481
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")
|
|
2482
2484
|
f.debug("Creating task")
|
|
2483
|
-
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})
|
|
2484
2486
|
if(!e||!e.id)throw Error("Failed to create task")
|
|
2485
2487
|
let v
|
|
2486
|
-
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,
|
|
2487
|
-
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)
|
|
2488
2490
|
else{if("manage"!==t)throw new r.ValidationError("Unsupported operation type: "+t)
|
|
2489
|
-
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})
|
|
2490
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")
|
|
2491
2493
|
P?f.warn("File operation completed with partial failures",{requestId:S}):f.info("File operation completed successfully"),f.debug("Completing task")
|
|
2492
|
-
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})
|
|
2493
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")
|
|
2494
|
-
const M=P?`Quick change completed with partial success: ${
|
|
2495
|
-
let
|
|
2496
|
-
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)
|
|
2497
2499
|
if(e.isError)f.error("Request completion failed, attempting direct completion",{requestId:S,error:e.content[0].text})
|
|
2498
|
-
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
|
|
2499
2501
|
let O
|
|
2500
|
-
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
|
|
2501
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}}}
|
|
2502
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
|
|
2503
2505
|
const r=t(9860),n=t(5674)
|
|
@@ -2570,46 +2572,46 @@ return t},r(e)},function(e){if(e&&e.__esModule)return e
|
|
|
2570
2572
|
var t={}
|
|
2571
2573
|
if(null!=e)for(var s=r(e),i=0;i<s.length;i++)"default"!==s[i]&&n(t,e,s[i])
|
|
2572
2574
|
return o(t,e),t}),i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
2573
|
-
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"),
|
|
2574
|
-
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
|
|
2575
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"}
|
|
2576
|
-
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,
|
|
2577
|
-
w.info("Writing content to "+(M?"document":"file"),{taskId:i,filePath:
|
|
2578
|
-
let
|
|
2579
|
-
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
|
|
2580
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}
|
|
2581
2583
|
throw e}if(!t.documentFileManager)throw Error("Document file manager not available")
|
|
2582
2584
|
A=await t.documentFileManager.getDocumentAsFile(E)
|
|
2583
2585
|
const e=t.documentFileManager.getCachedDocumentInfo(E)
|
|
2584
2586
|
O=e?.filename,$=!0,D=!1}C=d.FileOperationPhase.TASK_VALIDATION,m.incrementCounter("write_file_phase",1,{phase:C})
|
|
2585
|
-
const N=
|
|
2587
|
+
const N=j?F:"document:"+E,L=await d.validateTaskId(i,N,n,w,m,_.metricsPrefix),z=L?.requestId
|
|
2586
2588
|
let B=null
|
|
2587
|
-
|
|
2589
|
+
j&&z&&(B=await d.validateWorkItemStates(i,N,n,s,t,w,m,_.metricsPrefix))
|
|
2588
2590
|
let H={taskPromoted:!1,requestPromoted:!1}
|
|
2589
|
-
|
|
2590
|
-
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})
|
|
2591
2593
|
if(!W.success){if(W.isLockConflict)return{content:[{type:"text",text:"\u274c "+W.error}],isError:!0}
|
|
2592
|
-
throw Error(W.error)}if(W.switched&&w.info("Workspace context successfully established",{requestId:z,branchName:W.branchName,operation:"write_file"}),
|
|
2593
|
-
|
|
2594
|
-
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}
|
|
2595
2597
|
throw e}C=d.FileOperationPhase.RECORD_CREATION,m.incrementCounter("write_file_phase",1,{phase:C})
|
|
2596
|
-
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)
|
|
2597
2599
|
let G
|
|
2598
|
-
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)
|
|
2599
2601
|
else G="string"==typeof q?q:JSON.stringify(q,null,2)
|
|
2600
2602
|
let V=G
|
|
2601
|
-
if(
|
|
2603
|
+
if(j&&t.git)try{w.debug("[WRITE-FILE] Checking for user changes before write operation")
|
|
2602
2604
|
const e=await(0,g.commitUserChangesBeforeToolOperation)(t.git,"write_file",{requestId:t.workspaceManager?.getCurrentContext()?.requestId,taskId:i},w,m)
|
|
2603
|
-
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")
|
|
2604
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)
|
|
2605
|
-
if(await c.default.mkdir(J,{recursive:!0}),await c.default.writeFile(A,V,"utf8"),w.info("Content written successfully",{path:R
|
|
2606
|
-
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,
|
|
2607
|
-
if(
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
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}\`.`)
|
|
2611
2613
|
const X=Date.now()
|
|
2612
|
-
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
|
|
2613
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}}}
|
|
2614
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
|
|
2615
2617
|
const r=t(6183),n=t(4648)
|
|
@@ -2780,10 +2782,10 @@ try{let o
|
|
|
2780
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(", ")
|
|
2781
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
|
|
2782
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
|
|
2783
|
-
try{const{normalizedPath:y,fullPath:w}=d.validateAndNormalizePath(t,o),k=await d.validateTaskId(e,y,s.getTaskClient(),a,g,"file-recover"),{toolRecordId:
|
|
2784
|
-
m=
|
|
2785
|
-
let
|
|
2786
|
-
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
|
|
2787
2789
|
if(!C)throw Error("Git is not available")
|
|
2788
2790
|
if(!(await(0,u.validateCommitHash)(C,r,a,"file-recover")).valid)throw Error(`Commit hash '${r}' is invalid or not found`)
|
|
2789
2791
|
let _
|
|
@@ -2792,9 +2794,9 @@ if(t.includes("does not exist")||t.includes("not found")||t.includes("Path"))thr
|
|
|
2792
2794
|
throw Error(`Failed to retrieve file '${y}' from commit '${r}': ${t}`)}await l.writeFile(w,_,"utf8")
|
|
2793
2795
|
let E={}
|
|
2794
2796
|
try{const t=`Recover ${y} from ${r.substring(0,8)}`
|
|
2795
|
-
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"
|
|
2796
2798
|
let S=`\u2705 **File ${q.charAt(0).toUpperCase()+q.slice(1)} Successfully**\n\n`
|
|
2797
|
-
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
|
|
2798
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}}}
|
|
2799
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"})
|
|
2800
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)
|
|
@@ -2942,15 +2944,15 @@ if(/^\d+$/.test(e)){const t=parseInt(e,10)
|
|
|
2942
2944
|
return{start:t,end:t}}const t=e.match(/^(\d+)-(\d+)$/)
|
|
2943
2945
|
if(t)return{start:parseInt(t[1],10),end:parseInt(t[2],10)}
|
|
2944
2946
|
if(e.match(/^(\d+(?:,\d+)+)$/)){const t=e.split(",").map((e=>parseInt(e,10)))
|
|
2945
|
-
return{start:Math.min(...t),end:Math.max(...t)}}return null}(p),
|
|
2946
|
-
let
|
|
2947
|
-
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})
|
|
2948
2950
|
try{if(!t.git)throw Error("Git context not available")
|
|
2949
|
-
|
|
2951
|
+
I=await t.git.raw(b)}catch(e){const t=(0,h.getErrorMessage)(e)
|
|
2950
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")
|
|
2951
2953
|
let n="",o="",s="",i=0,a=0,c=new Map
|
|
2952
2954
|
for(let e=0;e<r.length;e++){const l=r[e],d=l.match(/^([0-9a-f]{40})\s+\d+\s+(\d+)/)
|
|
2953
|
-
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)
|
|
2954
2956
|
if(0===v.length)return{content:[{type:"text",text:"\u274c No blame information found for "+w}],isError:!0}
|
|
2955
2957
|
const C=function(e){if(0===e.length)return[]
|
|
2956
2958
|
const t=[]
|
|
@@ -3186,10 +3188,10 @@ const m=g.acceptanceCriteria||[],y={unverified:0,partial:0,verified:0,partially_
|
|
|
3186
3188
|
m.forEach((e=>{const t=e.status||"unverified"
|
|
3187
3189
|
t in y&&y[t]++}))
|
|
3188
3190
|
let w=g.testVerification||null
|
|
3189
|
-
const k=g.title,
|
|
3190
|
-
let
|
|
3191
|
-
return
|
|
3192
|
-
|
|
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}}}
|
|
3193
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
|
|
3194
3196
|
for(let t=0;t<e.length;t++)r=(r<<5)-r+e.charCodeAt(t)|0
|
|
3195
3197
|
return`${t+1}${String.fromCharCode(97+Math.abs(r)%26)}`}function r(e){const r=new Map
|
|
@@ -3287,25 +3289,25 @@ if(t){const e=Date.now()-t
|
|
|
3287
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()
|
|
3288
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
|
|
3289
3291
|
const r=t(6183),n=t(2965)
|
|
3290
|
-
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
|
|
3291
|
-
try{const{requestId:
|
|
3292
|
-
if(!
|
|
3293
|
-
if(!
|
|
3294
|
-
|
|
3295
|
-
const
|
|
3296
|
-
let
|
|
3297
|
-
try{const e=await
|
|
3298
|
-
|
|
3299
|
-
return
|
|
3300
|
-
return
|
|
3301
|
-
try{await
|
|
3302
|
-
return
|
|
3303
|
-
try{
|
|
3304
|
-
return
|
|
3305
|
-
return
|
|
3306
|
-
r instanceof
|
|
3307
|
-
try{await(0,
|
|
3308
|
-
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
|
|
3309
3311
|
const r=t(6183),n=t(6285)
|
|
3310
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())}))})
|
|
3311
3313
|
return(0,o.areTestsRequiredForCompletion)()?e.extend({testVerification:t}):e}Object.defineProperty(exports,"__esModule",{value:!0}),exports.DynamicCompleteRequestSchema=void 0,exports.getDynamicCompleteRequestSchema=r
|
|
@@ -3324,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])
|
|
|
3324
3326
|
return o(t,e),t}),i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
3325
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()
|
|
3326
3328
|
let y,w,k=l.FileOperationPhase.VALIDATION
|
|
3327
|
-
const
|
|
3328
|
-
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
|
|
3329
3331
|
let S=[]
|
|
3330
3332
|
if(_)S=_.map((e=>({type:"file",target:e})))
|
|
3331
3333
|
else{if(!E)throw Error("Either paths or operations must be specified")
|
|
@@ -3333,31 +3335,31 @@ S=E.map((e=>{if(e.path)return{type:"file",target:e.path}
|
|
|
3333
3335
|
if(e.documentId)return{type:"document",target:e.documentId}
|
|
3334
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")
|
|
3335
3337
|
const T=S.filter((e=>"file"===e.type)),P=S.filter((e=>"document"===e.type)),M=S.length
|
|
3336
|
-
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,
|
|
3337
|
-
const
|
|
3338
|
-
i.info("Initial branch context",{initialBranch:
|
|
3339
|
-
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=[]
|
|
3340
3342
|
for(const e of T){const{normalizedPath:r,fullPath:n}=l.validateAndNormalizePath(e.target,t)
|
|
3341
|
-
|
|
3342
|
-
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)
|
|
3343
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})
|
|
3344
|
-
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})
|
|
3345
3347
|
if(!F.success){if(F.isLockConflict)return{content:[{type:"text",text:"\u274c "+F.error}],isError:!0}
|
|
3346
3348
|
throw Error(F.error)}let N={hadUserMods:!1,userModsCommitHash:void 0}
|
|
3347
3349
|
if(t.git)try{i.debug("[DELETE-FILES] Checking for user changes before mixed delete operations")
|
|
3348
3350
|
const e=await(0,h.commitUserChangesBeforeToolOperation)(t.git,"delete-files",{requestId:A,taskId:C,workspaceManager:t.workspaceManager},i,o)
|
|
3349
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})
|
|
3350
|
-
const{toolRecordId:L,localToolRecordId:z}=await l.createFileOperationRecords(C,A,t.projectId,
|
|
3351
|
-
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})
|
|
3352
3354
|
const B=[]
|
|
3353
3355
|
let H=0
|
|
3354
3356
|
P.length>0&&r.setProjectId(t.projectId)
|
|
3355
|
-
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}
|
|
3356
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)
|
|
3357
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
|
|
3358
3360
|
for(const e of P){const t=e.target,n={type:"document",documentId:t,success:!1,replacements:[],successfulReplacements:0,failedReplacements:0}
|
|
3359
3361
|
try{let e
|
|
3360
|
-
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)
|
|
3361
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)
|
|
3362
3364
|
throw e}}catch(e){throw Error(`Document not found or validation failed: ${t}. ${(0,f.getErrorMessage)(e)}`)}const s=await W.archiveDocument(t)
|
|
3363
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
|
|
@@ -3366,20 +3368,20 @@ let G=null
|
|
|
3366
3368
|
if(H>0){k=l.FileOperationPhase.GIT_COMMIT,o.incrementCounter("delete_files_phase",1,{phase:k})
|
|
3367
3369
|
const e=B.filter((e=>e.success)),r=e.filter((e=>"file"===e.type)).length,n=e.filter((e=>"document"===e.type)).length
|
|
3368
3370
|
let s
|
|
3369
|
-
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})
|
|
3370
3372
|
const V=B.filter((e=>e.success)),J=B.filter((e=>!e.success))
|
|
3371
|
-
await l.updateFileOperationRecords(C,y,w,x,
|
|
3372
|
-
const
|
|
3373
|
-
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=""
|
|
3374
3376
|
if(H===M){const e=V.filter((e=>"file"===e.type)).length,t=V.filter((e=>"document"===e.type)).length
|
|
3375
|
-
|
|
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})`
|
|
3376
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})`
|
|
3377
3379
|
return`\u2022 ${e.type}: ${t}: ${e.error}`})).join("\n")
|
|
3378
|
-
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
|
|
3379
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
|
|
3380
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
|
|
3381
3383
|
try{const t=r.getTaskClient(),s=r.getToolRecordClient()
|
|
3382
|
-
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)}}
|
|
3383
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)
|
|
3384
3386
|
var o=Object.getOwnPropertyDescriptor(t,r)
|
|
3385
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=[]
|
|
@@ -3463,15 +3465,13 @@ return t},r(e)},function(e){if(e&&e.__esModule)return e
|
|
|
3463
3465
|
var t={}
|
|
3464
3466
|
if(null!=e)for(var s=r(e),i=0;i<s.length;i++)"default"!==s[i]&&n(t,e,s[i])
|
|
3465
3467
|
return o(t,e),t})
|
|
3466
|
-
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")
|
|
3467
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
|
|
3468
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)
|
|
3469
|
-
const n=c.validateArgs(e,a.SpecialistOpsSchema),{operation:
|
|
3470
|
-
let
|
|
3471
|
-
switch(
|
|
3472
|
-
|
|
3473
|
-
if(!i){const e=await(0,h.getServerUrl)(r,m)
|
|
3474
|
-
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})
|
|
3475
3475
|
const s=await(0,h.getServerUrl)(r,n)
|
|
3476
3476
|
if(s)try{const r=await fetch(s.replace(/\/$/,"")+"/session")
|
|
3477
3477
|
if(!r.ok)return
|
|
@@ -3484,34 +3484,33 @@ return"specialist"===t?.agentType&&"archived"!==t?.status}))
|
|
|
3484
3484
|
if(n.info("Pool check: specialist count",{specialistCount:h.length,maxPoolSize:t}),h.length<t)return
|
|
3485
3485
|
const g=h.map((e=>{const t=l[e.id],r=u[e.id]?.type||"idle",n=t?.specialization||"(none)"
|
|
3486
3486
|
return` \u2022 ${e.id} \u2014 ${n} [${r}]`})).join("\n")
|
|
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,
|
|
3488
|
-
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
|
|
3489
3489
|
break}}let a=e.description
|
|
3490
|
-
const c=await Promise.resolve().then(t.t.bind(t,9896,23)),
|
|
3491
|
-
if(i)try{const e=await(0,h.getServerUrl)(r,
|
|
3492
|
-
if(
|
|
3493
|
-
if(
|
|
3494
|
-
|
|
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(", ")}`)
|
|
3495
3495
|
const r=(0,d.pickSpecialistName)(e)
|
|
3496
|
-
a=r,
|
|
3497
|
-
const
|
|
3498
|
-
|
|
3499
|
-
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)
|
|
3500
3500
|
if(e)try{const t=await fetch(e.replace(/\/$/,"")+"/session/status")
|
|
3501
|
-
if(t.ok){const e=await t.json(),r=e[
|
|
3502
|
-
if(r&&"idle"!==r&&"prompting"!==r){
|
|
3503
|
-
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)
|
|
3504
3504
|
const t=n.followUp.specialization
|
|
3505
3505
|
if(t&&s)try{const e=s.getCLISessionClient()
|
|
3506
|
-
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)
|
|
3507
3507
|
break
|
|
3508
|
-
case"abort":if(
|
|
3509
|
-
e&&await e.createOrUpdateSession({externalSessionId:
|
|
3510
|
-
case"list":{
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
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
|
|
3515
3514
|
const r=t(6183),n=t(2982)
|
|
3516
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)
|
|
3517
3516
|
var o=Object.getOwnPropertyDescriptor(t,r)
|
|
@@ -3588,7 +3587,7 @@ var t={}
|
|
|
3588
3587
|
if(null!=e)for(var r=n(e),i=0;i<r.length;i++)"default"!==r[i]&&o(t,e,r[i])
|
|
3589
3588
|
return s(t,e),t}),a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
3590
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()
|
|
3591
|
-
let k,I
|
|
3590
|
+
let k,b,I=d.FileOperationPhase.VALIDATION
|
|
3592
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"}
|
|
3593
3592
|
try{const i=d.validateArgs(e,l.InsertLinesSchema),{taskId:C,operations:_,comment:E}=i
|
|
3594
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")
|
|
@@ -3601,21 +3600,21 @@ if(S.length>0&&!t.documentFileManager)throw Error("Document file manager not ava
|
|
|
3601
3600
|
for(const e of S)P.push({type:"document",documentId:e.documentId,insertions:e.insertions})
|
|
3602
3601
|
if(P.length>0&&t.apiClient){const e=P.map((e=>e.documentId))
|
|
3603
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}
|
|
3604
|
-
throw e}}
|
|
3605
|
-
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
|
|
3606
3605
|
let x=null
|
|
3607
|
-
T.length>0&&
|
|
3606
|
+
T.length>0&&R&&(x=await d.validateWorkItemStates(C,T[0].path,n,s,t,y,a,v.metricsPrefix))
|
|
3608
3607
|
let O={taskPromoted:!1,requestPromoted:!1}
|
|
3609
|
-
T.length>0&&
|
|
3610
|
-
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})
|
|
3611
3610
|
if(!A.success){if(A.isLockConflict)return{content:[{type:"text",text:"\u274c "+A.error}],isError:!0}
|
|
3612
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})
|
|
3613
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)
|
|
3614
|
-
T[e]={...r,path:o,fullPath:s}}}if(P.length>0&&
|
|
3615
|
-
throw e}
|
|
3616
|
-
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,
|
|
3617
|
-
if(k=$,I
|
|
3618
|
-
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)
|
|
3619
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})
|
|
3620
3619
|
const F=[]
|
|
3621
3620
|
let N=0,L=0,z=0
|
|
@@ -3627,46 +3626,46 @@ try{const o=await t.documentFileManager.getDocumentAsFile(e.documentId),s=t.docu
|
|
|
3627
3626
|
n.filename=s?.filename
|
|
3628
3627
|
const i=await c.default.readFile(o,"utf8"),{newContent:a,results:l}=await r(i,e.insertions)
|
|
3629
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))
|
|
3630
|
-
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:
|
|
3631
|
-
try{await o.updateToolRecord(
|
|
3632
|
-
if(t.workspaceManager&&(
|
|
3633
|
-
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"
|
|
3634
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}`
|
|
3635
|
-
|
|
3636
|
-
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"
|
|
3637
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}`
|
|
3638
|
-
|
|
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")
|
|
3639
3638
|
const Q=Date.now()-w
|
|
3640
|
-
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:
|
|
3641
|
-
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}}}
|
|
3642
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
|
|
3643
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)
|
|
3644
3643
|
exports.ClientFactory=class{static async createClient(e,m,y,w={}){(m=m.child({component:"client-factory"})).info("Creating API client with components")
|
|
3645
3644
|
const k=w.tokenManager||new r.TokenManager(m,w.workingDir||process.cwd())
|
|
3646
3645
|
await k.initialize()
|
|
3647
|
-
const
|
|
3648
|
-
|
|
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)
|
|
3649
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})
|
|
3650
|
-
|
|
3649
|
+
b.registerClient(E)
|
|
3651
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})
|
|
3652
|
-
|
|
3651
|
+
b.registerClient(q),m.info("RequestClient constructor received token: "+(v?"present":"missing"))
|
|
3653
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})
|
|
3654
|
-
|
|
3653
|
+
b.registerClient(S),m.info("RequestClient post-constructor token: "+(S.getAuthToken()?"present":"missing"))
|
|
3655
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})
|
|
3656
|
-
|
|
3655
|
+
b.registerClient(T)
|
|
3657
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})
|
|
3658
|
-
|
|
3657
|
+
b.registerClient(P)
|
|
3659
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})
|
|
3660
|
-
if(
|
|
3659
|
+
if(b.registerClient(M),!w.alchemyPath)throw Error("alchemyPath is required for ProjectSynchronizer creation. Cannot create API client without project synchronization capabilities.")
|
|
3661
3660
|
try{m.info("Creating ProjectSynchronizer components")
|
|
3662
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})
|
|
3663
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)
|
|
3664
|
-
throw m.error(t,{error:e instanceof Error?e.stack:e+""}),Error(t)}const
|
|
3665
|
-
m.info("API client initialized with specialized clients"),v?(
|
|
3666
|
-
const
|
|
3667
|
-
|
|
3668
|
-
const x=
|
|
3669
|
-
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
|
|
3670
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
|
|
3671
3670
|
const r=t(1599),n=t(2690),o=t(4465),s=t(5187),i=t(5674),a=t(8824)
|
|
3672
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
|
|
@@ -3704,7 +3703,7 @@ var t={}
|
|
|
3704
3703
|
if(null!=e)for(var r=n(e),i=0;i<r.length;i++)"default"!==r[i]&&o(t,e,r[i])
|
|
3705
3704
|
return s(t,e),t}),a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
3706
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()
|
|
3707
|
-
let I,
|
|
3706
|
+
let b,I,v=d.FileOperationPhase.VALIDATION
|
|
3708
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"}
|
|
3709
3708
|
try{const i=d.validateArgs(e,l.ReplaceLinesSchema),{taskId:_,operations:E,comment:q}=i
|
|
3710
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")
|
|
@@ -3718,19 +3717,19 @@ for(const e of T)M.push({type:"document",documentId:e.documentId,replacements:e.
|
|
|
3718
3717
|
if(M.length>0&&t.apiClient){const e=M.map((e=>e.documentId))
|
|
3719
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}
|
|
3720
3719
|
throw e}}v=d.FileOperationPhase.TASK_VALIDATION,a.incrementCounter("replace_lines_phase",1,{phase:v})
|
|
3721
|
-
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
|
|
3722
3721
|
let O=null
|
|
3723
3722
|
P.length>0&&x&&(O=await d.validateWorkItemStates(_,P[0].path,n,s,t,w,a,C.metricsPrefix))
|
|
3724
3723
|
let A={taskPromoted:!1,requestPromoted:!1}
|
|
3725
|
-
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"}))
|
|
3726
3725
|
const D=await d.ensureCorrectWorkspaceContext({taskPromoted:A.taskPromoted,requestId:x,context:t,operation:"replace-lines",logger:w,metrics:a,metricsPrefix:C.metricsPrefix})
|
|
3727
3726
|
if(!D.success){if(D.isLockConflict)return{content:[{type:"text",text:"\u274c "+D.error}],isError:!0}
|
|
3728
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})
|
|
3729
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)
|
|
3730
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}
|
|
3731
3730
|
throw e}v=d.FileOperationPhase.RECORD_CREATION,a.incrementCounter("replace_lines_phase",1,{phase:v})
|
|
3732
|
-
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,
|
|
3733
|
-
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")
|
|
3734
3733
|
const e=await(0,g.commitUserChangesBeforeToolOperation)(t.git,"replace-lines",{requestId:x,taskId:_,workspaceManager:t.workspaceManager},w,a)
|
|
3735
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})
|
|
3736
3735
|
const N=[]
|
|
@@ -3743,33 +3742,33 @@ try{const o=await t.documentFileManager.getDocumentAsFile(e.documentId),s=t.docu
|
|
|
3743
3742
|
n.filename=s?.filename
|
|
3744
3743
|
const i=await c.default.readFile(o,"utf8"),{newContent:a,results:l}=await r(i,e.replacements)
|
|
3745
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))
|
|
3746
|
-
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:
|
|
3747
|
-
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"
|
|
3748
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]
|
|
3749
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"
|
|
3750
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"
|
|
3751
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"
|
|
3752
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")
|
|
3753
3752
|
const X=Date.now()-k
|
|
3754
|
-
return w.info("Replace lines operation completed",{duration:X,success:
|
|
3755
|
-
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}}}
|
|
3756
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
|
|
3757
3756
|
const r=t(9896),n=t(6928)
|
|
3758
|
-
exports.sessionIdentity=new class{constructor(){this.
|
|
3757
|
+
exports.sessionIdentity=new class{constructor(){this.parentCache=new Map}setIdentity(e){const t=this.identity
|
|
3759
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}
|
|
3760
|
-
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})}}
|
|
3761
|
-
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)
|
|
3762
3760
|
return this.log("getParentSessionId.cache-hit",{childExternalId:e,parentExternalId:t}),t}try{const n=t.getCLISessionClient()
|
|
3763
3761
|
if(!n)return r.warn("CLI session client not available"),null
|
|
3764
3762
|
const o=await n.getParent(e),s=o?.externalSessionId||null
|
|
3765
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+""
|
|
3766
|
-
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
|
|
3767
3766
|
try{const r=e.getSessionRequestAssociationClient?.()
|
|
3768
3767
|
if(!r)return t.warn("Session request association client not available"),null
|
|
3769
|
-
const
|
|
3770
|
-
if(
|
|
3771
|
-
return this.log("getSessionRequestId.resolved",{sessionId:
|
|
3772
|
-
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})
|
|
3773
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
|
|
3774
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
|
|
3775
3774
|
const r=t(6183),n=t(6651)
|
|
@@ -3829,16 +3828,16 @@ let w
|
|
|
3829
3828
|
r.setProjectId(y)
|
|
3830
3829
|
try{const P=await f.getTask(g)
|
|
3831
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=[]
|
|
3832
|
-
try{const
|
|
3833
|
-
if(s.info("Raw records response data",{responseDataType:typeof
|
|
3834
|
-
k.forEach((e=>{
|
|
3835
|
-
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=[]
|
|
3836
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
|
|
3837
3836
|
if(e&&s){const i={source:e,destination:s,recordId:o.id,timestamp:o.createdAt,type:"move-file"}
|
|
3838
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||[]]
|
|
3839
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"}
|
|
3840
|
-
t.set(s.source,e),r.set(s.destination,e),n.push(e)}}return{sourceToMove:t,destToMove:r,allMoves:n}}const b
|
|
3841
|
-
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`)
|
|
3842
3841
|
const v=k.filter((e=>{if(!e||"object"!=typeof e)return s.warn("Skipping invalid record (not an object)"),!1
|
|
3843
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
|
|
3844
3843
|
if(!e.metadata)return s.warn("Skipping record without metadata: "+e.id),!1
|
|
@@ -3886,10 +3885,10 @@ const N=new Map
|
|
|
3886
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(" -> ")}`)}))
|
|
3887
3886
|
const L=F.filter((e=>e.commitHash))
|
|
3888
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`)
|
|
3889
|
-
try{if(t.git){const J={file:$,n:10},
|
|
3890
|
-
if(
|
|
3891
|
-
const K
|
|
3892
|
-
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
|
|
3893
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"}`)
|
|
3894
3893
|
let ee=""
|
|
3895
3894
|
try{if(X)try{const te=[`${Z.commitHash}:${$}`],re=await t.git.show(te)
|
|
@@ -3914,7 +3913,7 @@ continue}let pe
|
|
|
3914
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")
|
|
3915
3914
|
try{const me=await t.git.show([`${U.commitHash}:${$}`]),ye=await t.git.show([`${B.commitHash}:${$}`])
|
|
3916
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")
|
|
3917
|
-
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}:${$}`]
|
|
3918
3917
|
s.info(`Trying fallback to show file content using git show: ${B.commitHash?B.commitHash.substring(0,8):"unknown"}:${$}`)
|
|
3919
3918
|
const Ce=await t.git.show(ve)
|
|
3920
3919
|
if(Ce&&Ce.trim().length>0){if(p){let _e=""
|
|
@@ -3926,15 +3925,15 @@ w&&"object"==typeof w&&(E+="## Task Information\n",E+=`- **Title**: ${w.title||"
|
|
|
3926
3925
|
const q=3e3
|
|
3927
3926
|
let S=0,T=!1
|
|
3928
3927
|
if(p){for(const Te of _.values())Te.hasDiff&&Te.diffText&&(S+=Te.diffText.split("\n").length)
|
|
3929
|
-
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`,
|
|
3930
|
-
for(const Pe of
|
|
3931
|
-
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)
|
|
3932
3931
|
let Oe=!1
|
|
3933
3932
|
try{await a.access(xe),Oe=!0}catch{}E+=`### ${Me} ${Oe?"":"(Deleted)"}\n\n`
|
|
3934
|
-
const Ae=new Date(
|
|
3935
|
-
E+=`**First Change**: ${Ae}\n`,E+=`**Last Change**: ${De}\n`,"pre-task"===
|
|
3936
|
-
const $e=
|
|
3937
|
-
$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}}}
|
|
3938
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
|
|
3939
3938
|
const r=t(1058)
|
|
3940
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)})
|
|
@@ -4056,42 +4055,42 @@ Object.defineProperty(exports,"__esModule",{value:!0}),exports.logSessionIdentit
|
|
|
4056
4055
|
i.existsSync(n)||i.mkdirSync(n,{recursive:!0})
|
|
4057
4056
|
const s=(new Date).toISOString(),c=Object.keys(r).length?" "+JSON.stringify(r):""
|
|
4058
4057
|
i.appendFileSync(o,`[${s}] ${e} | ${t}${c}\n`)}catch(e){}}
|
|
4059
|
-
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
|
|
4060
|
-
|
|
4061
|
-
const
|
|
4062
|
-
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)
|
|
4063
4062
|
throw new n.ValidationError("Invalid input: "+(0,i.getErrorMessage)(e))}}(e)
|
|
4064
|
-
|
|
4065
|
-
const
|
|
4066
|
-
if(!
|
|
4067
|
-
|
|
4068
|
-
const
|
|
4069
|
-
let
|
|
4070
|
-
try{const e=
|
|
4071
|
-
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()
|
|
4072
4071
|
if(t){const r=await t.getByExternalId(e)
|
|
4073
|
-
if(r?.workflowId){const e=await
|
|
4074
|
-
t?.approvalMode&&(
|
|
4075
|
-
r&&(
|
|
4076
|
-
|
|
4077
|
-
const b=await
|
|
4078
|
-
|
|
4079
|
-
const
|
|
4080
|
-
let _
|
|
4081
|
-
if(
|
|
4082
|
-
|
|
4083
|
-
try{const e=
|
|
4084
|
-
if(e){const t=await e.createToolRecord({requestId:
|
|
4085
|
-
|
|
4086
|
-
const
|
|
4087
|
-
let
|
|
4088
|
-
return
|
|
4089
|
-
else{const n=
|
|
4090
|
-
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]
|
|
4091
4090
|
let t=e.message
|
|
4092
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."
|
|
4093
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}}}
|
|
4094
|
-
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)
|
|
4095
4094
|
var o=Object.getOwnPropertyDescriptor(t,r)
|
|
4096
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)}
|
|
4097
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)
|
|
@@ -4105,7 +4104,7 @@ return o(t,e),t})
|
|
|
4105
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"})
|
|
4106
4105
|
try{const s=a.validateArgs(e,i.ModifyFileSchema),{taskId:u,operations:f,comment:m}=s
|
|
4107
4106
|
p.info("Processing modify-file operations",{taskId:u,operationCount:f.length,comment:m})
|
|
4108
|
-
const y=[],w=[],k=[],
|
|
4107
|
+
const y=[],w=[],k=[],b=[],I=[]
|
|
4109
4108
|
for(const e of f){const t={path:e.path,documentId:e.documentId}
|
|
4110
4109
|
switch(e.operationType){case"replace-string":y.push({...t,replacements:e.replaceString.replacements,mode:e.replaceString.mode})
|
|
4111
4110
|
break
|
|
@@ -4113,19 +4112,19 @@ case"insert-lines":w.push({...t,insertions:e.insertLines.insertions})
|
|
|
4113
4112
|
break
|
|
4114
4113
|
case"replace-lines":k.push({...t,replacements:e.replaceLines.replacements})
|
|
4115
4114
|
break
|
|
4116
|
-
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"})
|
|
4117
4116
|
break
|
|
4118
|
-
case"delete-lines":
|
|
4117
|
+
case"delete-lines":I.push({...t,lines:e.deleteLines.lines})}}const v=[]
|
|
4119
4118
|
if(y.length>0){p.info("Routing to replace-strings handler",{operationCount:y.length})
|
|
4120
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)
|
|
4121
4120
|
v.push({type:"replace-string",result:e})}if(w.length>0){p.info("Routing to insert-lines handler",{operationCount:w.length})
|
|
4122
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)
|
|
4123
4122
|
v.push({type:"insert-lines",result:e})}if(k.length>0){p.info("Routing to replace-lines handler",{operationCount:k.length})
|
|
4124
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)
|
|
4125
|
-
v.push({type:"replace-lines",result:e})}if(
|
|
4126
|
-
const e=await(0,c.handleReplaceStrings)({taskId:u,operations:
|
|
4127
|
-
v.push({type:"delete-string",result:e})}if(
|
|
4128
|
-
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)
|
|
4129
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
|
|
4130
4129
|
let q="## Modify File Results\n\n"
|
|
4131
4130
|
q+="**Summary:**\n",q+=`- **Total operation types:** ${v.length}\n`,q+=`- **Successful:** ${_}\n`,q+=`- **Failed:** ${E}\n\n`
|
|
@@ -4277,55 +4276,9 @@ const i=await t.updateDocument(e.planId,o),a=i.localId||i.id
|
|
|
4277
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}}}
|
|
4278
4277
|
const r=t(8824)},7613(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.def=void 0
|
|
4279
4278
|
const r=t(6183),n=t(9072)
|
|
4280
|
-
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
|
|
4281
|
-
if(e.operation!==t.operation)return!1
|
|
4282
|
-
if("ask"===e.operation){let r=e.ask||e,n=t.ask||t
|
|
4283
|
-
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
|
|
4284
|
-
return!(!o||!s)&&o===s}return!0}async function n(e,t,n,s){const i=n.child({component:"session-discovery"})
|
|
4285
|
-
try{const n=e.replace(/\/$/,"")+"/session",o=await fetch(n)
|
|
4286
|
-
if(!o.ok)return void i.warn("Failed to get session list",{status:o.status})
|
|
4287
|
-
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)
|
|
4288
|
-
if(!d.ok)return void i.warn("Failed to get session status",{status:d.status})
|
|
4289
|
-
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)))]
|
|
4290
|
-
let y=null
|
|
4291
|
-
const w=[]
|
|
4292
|
-
for(const n of m)try{const o=`${e.replace(/\/$/,"")}/session/${n.id}/message?limit=50`,a=await fetch(o)
|
|
4293
|
-
if(!a.ok){i.debug("Failed to get messages for session",{sessionId:n.id,status:a.status})
|
|
4294
|
-
continue}const c=await a.json()
|
|
4295
|
-
let l=0
|
|
4296
|
-
for(const e of c){const o=(e.info||e).role||e.role,i=e.parts
|
|
4297
|
-
if("assistant"===o&&i)for(const o of i)if("tool"===o.type){const i=o.tool,a=o.state?.status,c=o.sessionID
|
|
4298
|
-
if(l++,i&&i.includes(t)){if("running"!==a&&"pending"!==a){w.push({sessionId:n.id,tool:i,reason:"wrong state: "+a})
|
|
4299
|
-
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
|
|
4300
|
-
if(l>0&&h>6e4){w.push({sessionId:n.id,tool:i,reason:`stale: running for ${Math.round(h/1e3)}s`})
|
|
4301
|
-
continue}if(s&&t&&!r(s,t)){w.push({sessionId:n.id,tool:i,reason:"params mismatch"})
|
|
4302
|
-
continue}const g=e.info?.id
|
|
4303
|
-
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+""})
|
|
4304
|
-
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
|
|
4305
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)
|
|
4306
|
-
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
|
|
4307
|
-
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)
|
|
4308
|
-
if(!o.ok)return
|
|
4309
|
-
const s=await o.json()
|
|
4310
|
-
let i,a=0
|
|
4311
|
-
for(const e of s){const t=(e.info||e).role||e.role,n=e.parts
|
|
4312
|
-
if("assistant"===t&&n)for(const t of n){if("tool"!==t.type)continue
|
|
4313
|
-
const n=t.tool,o=t.state?.status
|
|
4314
|
-
if(!n?.includes(r))continue
|
|
4315
|
-
if("running"!==o&&"pending"!==o)continue
|
|
4316
|
-
const s=t.state?.time?.start||0
|
|
4317
|
-
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)
|
|
4318
|
-
if(!n.ok)return void t.warn("Failed to get session list",{status:n.status})
|
|
4319
|
-
const o=[...await n.json()].sort(((e,t)=>t.time.updated-e.time.updated))
|
|
4320
|
-
if(0===o.length)return void t.warn("No sessions found")
|
|
4321
|
-
const s=e.replace(/\/$/,"")+"/session/status",i=await fetch(s)
|
|
4322
|
-
if(!i.ok)return void t.warn("Failed to get session status",{status:i.status})
|
|
4323
|
-
const a=await i.json(),c=o.filter((e=>"busy"===a[e.id]?.type))
|
|
4324
|
-
for(const r of c)try{const n=`${e.replace(/\/$/,"")}/session/${r.id}/message?limit=20`,o=await fetch(n)
|
|
4325
|
-
if(!o.ok)continue
|
|
4326
|
-
const s=await o.json()
|
|
4327
|
-
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+""})}}
|
|
4328
|
-
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")
|
|
4329
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
|
|
4330
4283
|
const o=await u.getCurrentBranch(e.git,t,r)
|
|
4331
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)
|
|
@@ -4419,7 +4372,9 @@ var n=t(2037)
|
|
|
4419
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}}
|
|
4420
4373
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.MultiAgentWorkspaceManager=void 0
|
|
4421
4374
|
const n=r(t(6928)),o=t(3807),s=t(7634),i=t(8824),a=t(7075),c=t(1387),l=t(4968)
|
|
4422
|
-
|
|
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
|
|
4423
4378
|
const i=a.ConflictResolutionUtils.initializeDetectors(r,t)
|
|
4424
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
|
|
4425
4380
|
if(!e)return
|
|
@@ -4427,73 +4382,81 @@ const t=e.match(/^requests\/(.+)$/)
|
|
|
4427
4382
|
if(!t)return void this.logger.warn("ALCHEMY_INITIAL_BRANCH set but not a request branch",{initialBranch:e})
|
|
4428
4383
|
const r=t[1]
|
|
4429
4384
|
this.logger.info("ALCHEMY_INITIAL_BRANCH set, switching to worktree",{initialBranch:e,requestId:r})
|
|
4430
|
-
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)
|
|
4431
4388
|
if(!n.isValid)throw Error("Invalid request ID: "+n.errors.join(", "))
|
|
4432
4389
|
const o=n.sanitized
|
|
4433
|
-
try{
|
|
4434
|
-
const n="requests/"+o,s=await this.mainGit.branch().then((e=>e.all.includes(n)||e.all.includes("remotes/origin/"+n)))
|
|
4435
|
-
if(!s){const e=await this.mainGit.revparse(["--abbrev-ref","HEAD"]),t=(await this.mainGit.branch()).all.includes("main")?"main":"master"
|
|
4436
|
-
await this.mainGit.checkout(["-b",n,t]),this.logger.info("Created branch for request",{requestId:o,branchName:n,fromBranch:t}),await this.mainGit.checkout(e),this.logger.info("Returned to original branch after creation",{returnedTo:e,createdBranch:n})}this.workspaceStates.set(o,"initialized")
|
|
4437
|
-
const i=Date.now()-r
|
|
4438
|
-
this.metrics.recordValue("workspace.initialize",i),a.WorkspaceLogging.logOperation(this.logger,"info","Successfully initialized request with branch (no worktree)",e,"multi-agent","initializeRequest",{branchName:n,branchExisted:s,duration:i,architecture:"hybrid-creation"})}catch(t){const n=Date.now()-r
|
|
4439
|
-
throw this.metrics.recordValue("workspace.initialize",n),a.WorkspaceLogging.logOperation(this.logger,"error","Failed to initialize request",e,"multi-agent","initializeRequest",{error:(0,i.getErrorMessage)(t),duration:n}),t}}async ensureWorkspaceReady(e){const t=Date.now(),r=a.WorkspaceValidation.validateRequestId(e)
|
|
4440
|
-
if(!r.isValid)throw Error("Invalid request ID: "+r.errors.join(", "))
|
|
4441
|
-
const n=r.sanitized
|
|
4442
|
-
let s=!1
|
|
4443
|
-
if(this.apiClient)try{const e=this.apiClient.getRequestClient(),t=await e.getRequest(n)
|
|
4444
|
-
if(t&&"quick-edit"===t.type){s=!0,this.logger.info("Quick-edit request detected - checking out branch in main repo (no worktree)",{requestId:n,requestType:t.type})
|
|
4445
|
-
const e="requests/"+n
|
|
4446
|
-
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:n,branchName:e})):(await this.mainGit.checkoutLocalBranch(e),this.logger.info("Created and checked out quick-edit branch in main repo",{requestId:n,branchName:e})),this.currentRequestId=n,this.currentWorktreePath=null,this.currentGit=this.mainGit,void this.workspaceStates.set(n,"ready")}}catch(e){this.logger.warn("Failed to check request type, proceeding with normal workflow",{requestId:n,error:(0,i.getErrorMessage)(e)})}if("ready"!==this.workspaceStates.get(n)||this.currentRequestId!==n){if("ready"===this.workspaceStates.get(n)&&this.currentRequestId!==n){this.logger.info("Workspace ready but not in correct context, switching to it",{requestId:n,currentRequestId:this.currentRequestId,reason:"context_mismatch"})
|
|
4447
|
-
const e=this.worktreeManager.getWorktreeInfo(n)
|
|
4448
|
-
if(e&&e.worktreePath)return this.currentRequestId=n,this.currentWorktreePath=e.worktreePath,this.currentGit=(0,o.simpleGit)(e.worktreePath),void this.logger.info("Switched to existing ready workspace",{requestId:n,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(n)||"not-initialized",currentRequestId:this.currentRequestId,architecture:"hybrid-creation"})
|
|
4449
|
-
const r=await this.worktreeManager.ensureWorktreeExists(n,void 0,void 0)
|
|
4450
|
-
if(!r.success)throw Error("Failed to create worktree: "+r.message)
|
|
4451
|
-
if(this.currentRequestId=n,this.currentWorktreePath=r.worktreePath,this.currentGit=(0,o.simpleGit)(r.worktreePath),this.workspaceStates.set(n,"ready"),r.created){this.workspaceKnownClean=!0
|
|
4452
|
-
try{const e=(0,o.simpleGit)(r.worktreePath),t=(await this.mainGit.branch()).all.includes("main")?"main":"master",s=await this.mainGit.revparse([t]),i=await e.revparse(["HEAD"])
|
|
4453
|
-
s!==i&&0===(await e.log({from:t,to:"HEAD"})).total&&(await e.rebase([t]),this.logger.info("Rebased fresh request branch onto latest main",{requestId:n,mainHead:s.substring(0,8),previousHead:i.substring(0,8)}))}catch(e){this.logger.warn("Failed to rebase onto main, proceeding with existing branch",{requestId:n,error:(0,i.getErrorMessage)(e)})}}const s=Date.now()-t
|
|
4454
|
-
this.metrics.recordValue("workspace.ensure_ready",s),a.WorkspaceLogging.logOperation(this.logger,"info","Workspace is ready with worktree",e,"multi-agent","ensureWorkspaceReady",{worktreePath:r.worktreePath,branchName:r.branchName,duration:s,architecture:"hybrid-creation"})}catch(r){const n=Date.now()-t
|
|
4455
|
-
throw this.metrics.recordValue("workspace.ensure_ready",n),a.WorkspaceLogging.logOperation(this.logger,"error","Failed to ensure workspace ready",e,"multi-agent","ensureWorkspaceReady",{error:(0,i.getErrorMessage)(r),duration:n}),r}}else this.logger.debug("Workspace already ready and in correct context",{requestId:n,worktreePath:this.currentWorktreePath})}async switchToRequest(e,t){this.logger.debug("switchToRequest called",{requestId:e,options:t})
|
|
4456
|
-
const r=Date.now(),n=this.getCurrentContext()
|
|
4457
|
-
if(this.logger.debug("previousContext",{previousContext:n}),t?.isCompleted&&this.currentRequestId!==e)return this.logger.debug("Completed request detected - using simple checkout instead of worktree"),await this.switchToCompletedRequest(e,r,n)
|
|
4458
|
-
const o=a.WorkspaceValidation.validateRequestId(e)
|
|
4459
|
-
if(!o.isValid){const t="Invalid request ID: "+o.errors.join(", ")
|
|
4460
|
-
return a.WorkspaceLogging.logOperation(this.logger,"error",t,e,"multi-agent","switchToRequest"),{success:!1,message:t,previousContext:n,newContext:n}}try{this.logger.debug("About to call ensureWorkspaceReady",{requestId:o.sanitized}),await this.ensureWorkspaceReady(o.sanitized),this.logger.debug("ensureWorkspaceReady completed",{currentRequestId:this.currentRequestId,currentWorktreePath:this.currentWorktreePath})
|
|
4390
|
+
try{this.workspaceStates.set(o,"initialized")
|
|
4461
4391
|
const t=Date.now()-r
|
|
4462
|
-
|
|
4463
|
-
|
|
4464
|
-
|
|
4465
|
-
const
|
|
4466
|
-
|
|
4467
|
-
|
|
4468
|
-
|
|
4469
|
-
|
|
4470
|
-
|
|
4471
|
-
const
|
|
4472
|
-
return
|
|
4473
|
-
|
|
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
|
|
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()
|
|
4474
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"})
|
|
4475
4432
|
const o=await this.requestProcessor.completeRequest(e,t,{skipConflictDetection:r?.skipConflictDetection||!1}),s=Date.now()-n
|
|
4476
|
-
|
|
4477
|
-
|
|
4478
|
-
|
|
4479
|
-
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)
|
|
4480
4440
|
if(!t.isValid)throw Error("Invalid request ID: "+t.errors.join(", "))
|
|
4481
4441
|
const r=t.sanitized
|
|
4482
|
-
try{this.
|
|
4442
|
+
try{for(const[e,t]of this.sessions)t.requestId===r&&(t.requestId=null,t.worktreePath=null,t.git=this.mainGit)
|
|
4483
4443
|
const e=await this.worktreeManager.removeWorktree(r,!1)
|
|
4484
4444
|
if(!e.success)throw Error(e.message||"Failed to remove worktree")
|
|
4485
|
-
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:
|
|
4486
|
-
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)
|
|
4487
4448
|
if(!t.isValid)return null
|
|
4488
4449
|
const r=t.sanitized,n=await this.getWorktreeInfo(r)
|
|
4489
|
-
return n?{requestId:r,path:n.worktreePath,branchName:n.branchName,isActive:this.
|
|
4490
|
-
return t?t[1]:null}convertWorktreeInfoToWorkspaceInfo(e){return{requestId:e.requestId,path:e.worktreePath,branchName:e.branchName,isActive:this.
|
|
4491
|
-
return this.worktreeManager.getWorktreeInfo(t)}catch(t){return void this.logger.warn("Failed to get worktree info",{requestId:e,error:(0,i.getErrorMessage)(t)})}}getMainGit(){return this.gitAdapter.getMainGit()}getCurrentGit(){return this.
|
|
4492
|
-
|
|
4493
|
-
const
|
|
4494
|
-
if(o){
|
|
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\/(.+)$/)
|
|
4495
4457
|
if(e){const t=e[1]
|
|
4496
|
-
try{await this.ensureWorkspaceReady(t),this.logger.info("ensureReadonlyBranchIfNeeded: workspace ready",{requestId:t})}catch(e){this.logger.warn("ensureReadonlyBranchIfNeeded: failed to ensure workspace",{requestId:t,error:(0,i.getErrorMessage)(e)})}}}}
|
|
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
|
|
4497
4460
|
const r=t(4192),n=t(7163)
|
|
4498
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)+"..."})
|
|
4499
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
|
|
@@ -4511,20 +4474,20 @@ return o(t,e),t})
|
|
|
4511
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"})
|
|
4512
4475
|
try{const h=a.validateArgs(e,i.ManageFilesSchema),{taskId:g,operations:y,comment:w}=h
|
|
4513
4476
|
m.info("Processing manage-files operations",{taskId:g,operationCount:y.length,comment:w})
|
|
4514
|
-
const k=[],
|
|
4477
|
+
const k=[],b=[],I=[],v=[]
|
|
4515
4478
|
for(const e of y)switch(e.operationType){case"create-directory":k.push({path:e.createDirectory.path})
|
|
4516
4479
|
break
|
|
4517
|
-
case"move-files":for(const t of e.moveFiles.moves)
|
|
4480
|
+
case"move-files":for(const t of e.moveFiles.moves)b.push(t)
|
|
4518
4481
|
break
|
|
4519
|
-
case"delete-files":
|
|
4482
|
+
case"delete-files":I.push(...e.deleteFiles.targets)
|
|
4520
4483
|
break
|
|
4521
4484
|
case"get-file-info":v.push({path:e.getFileInfo.path})}const C=[]
|
|
4522
4485
|
for(const e of k){m.info("Routing to create-directory handler",{path:e.path})
|
|
4523
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)
|
|
4524
|
-
C.push({type:"create-directory",result:s})}if(
|
|
4525
|
-
const e=await(0,l.handleMoveFiles)({taskId:g,operations:
|
|
4526
|
-
C.push({type:"move-files",result:e})}if(
|
|
4527
|
-
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)
|
|
4528
4491
|
C.push({type:"delete-files",result:e})}for(const e of v){m.info("Routing to get-file-info handler",{path:e.path})
|
|
4529
4492
|
const r=await(0,d.handleGetFileInfo)({path:e.path},t,m,p)
|
|
4530
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
|
|
@@ -4614,19 +4577,19 @@ const n=r(t(6982))
|
|
|
4614
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")
|
|
4615
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
|
|
4616
4579
|
if(e.includes("_")){const t=e.split("_")
|
|
4617
|
-
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
|
|
4618
4581
|
try{const s={...process.env}
|
|
4619
|
-
|
|
4620
|
-
const
|
|
4621
|
-
let
|
|
4622
|
-
if(s.ALCHEMY_SESSION_TAG=`mcp-${
|
|
4623
|
-
e>0?
|
|
4624
|
-
const
|
|
4625
|
-
let
|
|
4626
|
-
try{
|
|
4627
|
-
return
|
|
4628
|
-
return
|
|
4629
|
-
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")
|
|
4630
4593
|
try{const{filters:s={}}=e,a=["open","in_progress","ready_for_review","completed","canceled","reverted"]
|
|
4631
4594
|
if(s.status&&!a.includes(s.status))throw new r.ValidationError(`Invalid status: ${s.status}. Must be one of: ${a.join(", ")}`)
|
|
4632
4595
|
if(void 0!==s.limit&&1>s.limit)throw new r.ValidationError("Limit must be at least 1")
|
|
@@ -4679,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])
|
|
|
4679
4642
|
return o(t,e),t}),i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
4680
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()
|
|
4681
4644
|
let y,w,k=d.FileOperationPhase.VALIDATION
|
|
4682
|
-
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}"}
|
|
4683
4646
|
try{const s=d.validateArgs(e,l.CreateDirectorySchema),{taskId:u,path:h,comment:g}=s
|
|
4684
|
-
f.info("Creating directory: "+h,{taskId:u,path:h,comment:g}),d.validateTaskIdFormat(u,f,i,
|
|
4685
|
-
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)
|
|
4686
4649
|
k=d.FileOperationPhase.TASK_VALIDATION,i.incrementCounter("create_directory_phase",1,{phase:k})
|
|
4687
|
-
const C=await d.validateTaskId(u,
|
|
4688
|
-
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:
|
|
4689
|
-
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})
|
|
4690
4653
|
if(!S.success){if(S.isLockConflict)return{content:[{type:"text",text:"\u274c "+S.error}],isError:!0}
|
|
4691
4654
|
throw Error(S.error)}let T=!1
|
|
4692
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})
|
|
4693
|
-
const{toolRecordId:P,localToolRecordId:M}=await d.createFileOperationRecords(u,_,t.projectId,
|
|
4694
|
-
y=P,w=P,k=
|
|
4695
|
-
let
|
|
4696
|
-
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)
|
|
4697
4660
|
try{const e=c.default.join(v,".gitkeep")
|
|
4698
|
-
await a.default.writeFile(e,"# This file makes the directory trackable by Git\n"),
|
|
4699
|
-
i.recordValue("create_directory_time",
|
|
4700
|
-
const x=`Create directory: ${
|
|
4701
|
-
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)
|
|
4702
4665
|
const D=t.getCurrentBranchContext?await t.getCurrentBranchContext():{branch:null,requestId:null,isMain:!0}
|
|
4703
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
|
|
4704
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
|
|
4705
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
|
|
4706
|
-
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)}}
|
|
4707
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=[]
|
|
4708
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"
|
|
4709
4672
|
case"replace-in-files":return"\u{1f504} Replace in Files"
|
|
@@ -4912,34 +4875,34 @@ return i(t,e),t})
|
|
|
4912
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()
|
|
4913
4876
|
try{let o
|
|
4914
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(", ")
|
|
4915
|
-
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:
|
|
4916
|
-
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,"/")
|
|
4917
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}
|
|
4918
4881
|
try{const r=await o.log({from:t,to:t,file:s,maxCount:1})
|
|
4919
4882
|
if(!r.all||0===r.all.length)return{content:[{type:"text",text:`No commit found with hash ${t} for file ${e}`}]}
|
|
4920
4883
|
const n=r.all[0],i=await o.diff([t+"^",t,"--",s])
|
|
4921
4884
|
let a="# File History - Commit Diff\n\n"
|
|
4922
|
-
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)
|
|
4923
4886
|
try{await l.access(y)}catch(e){throw Error("File not found: "+m)}const w=a.git
|
|
4924
4887
|
if(!w)throw Error("Git is not available in this context")
|
|
4925
4888
|
let k={branch:null,requestId:null,isMain:!0}
|
|
4926
|
-
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
|
|
4927
|
-
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`
|
|
4928
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)}]}
|
|
4929
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)}]}
|
|
4930
4893
|
{const e=await async function(e,t,n,o,s,i,a,c,l,d){const u=[],h=[]
|
|
4931
4894
|
if(!i.isMain&&i.branch){const g=await r(e,t,n,o,s,i.branch,a,c,l,d)
|
|
4932
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)))
|
|
4933
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)
|
|
4934
|
-
|
|
4935
|
-
const v=
|
|
4936
|
-
v>t?
|
|
4937
|
-
try{
|
|
4938
|
-
for(let e=0;e<
|
|
4939
|
-
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")
|
|
4940
4903
|
let r=0,n=0
|
|
4941
4904
|
for(const t of e)t.startsWith("+")&&!t.startsWith("+++")&&r++,t.startsWith("-")&&!t.startsWith("---")&&n++
|
|
4942
|
-
|
|
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
|
|
4943
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}}}
|
|
4944
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
|
|
4945
4908
|
const r=t(6183),n=t(6891)
|
|
@@ -5072,7 +5035,14 @@ if(!o.ok)return void this.logger.debug("Polling response not ok",{status:o.statu
|
|
|
5072
5035
|
const i=await o.json()
|
|
5073
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")
|
|
5074
5037
|
const e=this.parseTokenResponse(i.data)
|
|
5075
|
-
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)
|
|
5076
5046
|
if(!o)return n.warn("Could not get server URL for notification",{sessionId:e}),!1
|
|
5077
5047
|
let s,i
|
|
5078
5048
|
try{const t=`http://localhost:${g}/api/sessions/${encodeURIComponent(e)}/agent-type`,r=await fetch(t)
|
|
@@ -5081,27 +5051,23 @@ e.success&&e.agentType&&(s=e.agentType)}}catch(t){n.warn("Agent type lookup fail
|
|
|
5081
5051
|
if(e.ok){const t=await e.json()
|
|
5082
5052
|
if(t.data?.defaultModel){const[e,...r]=t.data.defaultModel.split("/")
|
|
5083
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}:{}})})
|
|
5084
|
-
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)}
|
|
5085
|
-
if(
|
|
5086
|
-
|
|
5087
|
-
if(!s)throw new c.ValidationError("Could not determine OpenCode server URL")
|
|
5088
|
-
const i=await(0,d.getAndStoreSessionId)(s,t,r,n),a=i?.sessionId
|
|
5089
|
-
if(!a)throw new c.ValidationError("Could not discover current session ID. Make sure you are running within an OpenCode session.")
|
|
5090
|
-
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||{}
|
|
5091
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:**")
|
|
5092
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||{}
|
|
5093
|
-
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
|
|
5094
|
-
if(!
|
|
5095
|
-
const{operation:
|
|
5096
|
-
|
|
5097
|
-
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")')
|
|
5098
5064
|
return await async function(e,t,a,l){const{type:d}=e
|
|
5099
5065
|
if(!d)throw new c.ValidationError('send operation requires type ("question" or "report")')
|
|
5100
5066
|
const u=l.getSessionMessageClient()
|
|
5101
5067
|
if(!u)throw new c.ValidationError("Session message client not available")
|
|
5102
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
|
|
5103
5069
|
if(!u||!h?.question)throw new c.ValidationError("Question requires questionType and questionContent.question")
|
|
5104
|
-
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)
|
|
5105
5071
|
if(!e)throw new c.ValidationError("Could not find parent session. Make sure this session was spawned as a subagent.")
|
|
5106
5072
|
return o.info('Resolved toSessionId "parent" to actual ID',{parentId:e}),e}return e}(d,f,a,i)
|
|
5107
5073
|
if(!("alternatives"!==u||h.options&&Array.isArray(h.options)))throw new c.ValidationError("Alternatives questions require options array")
|
|
@@ -5113,7 +5079,7 @@ if(t.context&&r.push("**Context:** "+t.context),"alternatives"===t.questionType&
|
|
|
5113
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)
|
|
5114
5080
|
if("report"===d)return await async function(e,t,s,a,l){const{status:d,summary:u,details:h,finish:p}=e
|
|
5115
5081
|
if(!d||!u)throw new c.ValidationError("Report requires status and summary")
|
|
5116
|
-
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
|
|
5117
5083
|
const t=await n(f,a,s)
|
|
5118
5084
|
if(!t)throw new c.ValidationError("Could not find parent session. This tool should only be used by subagent sessions.")
|
|
5119
5085
|
return s.info("Auto-resolved parent session",{parentSessionId:t}),t})()
|
|
@@ -5125,7 +5091,7 @@ if(e.ok){const t=await e.json()
|
|
|
5125
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]
|
|
5126
5092
|
return r.details&&(n.push(""),n.push(r.details)),n.join("\n")}(y,w),t,s)
|
|
5127
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)
|
|
5128
|
-
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)
|
|
5129
5095
|
case"reply":if(!e.messageCode)throw new c.ValidationError("reply operation requires messageCode")
|
|
5130
5096
|
return await async function(e,t,n,o){const{messageCode:a}=e
|
|
5131
5097
|
if(!a)throw new c.ValidationError("reply operation requires messageCode")
|
|
@@ -5136,26 +5102,24 @@ n.info("Answering question",{messageCode:a,respondedBySessionId:o})
|
|
|
5136
5102
|
const u=await l.answerQuestion(a,{respondedBySessionId:o,text:i,selectedOptions:c,notes:d})
|
|
5137
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]
|
|
5138
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))}]}
|
|
5139
|
-
throw new c.ValidationError(`Cannot determine message type from code "${a}". Expected Q-xxx (question) or R-xxx (report).`)}(e,t,
|
|
5140
|
-
case"offer-handoff":{const
|
|
5141
|
-
let
|
|
5142
|
-
try{
|
|
5143
|
-
if(e
|
|
5144
|
-
|
|
5145
|
-
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
|
|
5146
5111
|
const m=n.getSessionMessageClient()
|
|
5147
5112
|
if(!m)throw new c.ValidationError("Session message client not available")
|
|
5148
|
-
if(!o){const e=
|
|
5149
|
-
if(!e)return{content:[{type:"text",text:"\u26a0\ufe0f Could not
|
|
5150
|
-
|
|
5151
|
-
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})
|
|
5152
5116
|
const y={sessionId:o,direction:i,limit:p,offset:f}
|
|
5153
|
-
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)
|
|
5154
5118
|
const w=await m.listMessages(y)
|
|
5155
5119
|
if(0===w.length)return{content:[{type:"text",text:"No messages found matching the criteria."}]}
|
|
5156
5120
|
const k=[`Found ${w.length} message(s):\n`]
|
|
5157
5121
|
for(const e of w)k.push("---\n"),k.push(a(e)),k.push("")
|
|
5158
|
-
return{content:[{type:"text",text:k.join("\n")}]}}(e.list||{},
|
|
5122
|
+
return{content:[{type:"text",text:k.join("\n")}]}}(e.list||{},0,m,f)
|
|
5159
5123
|
case"get":if(!e.messageCode)throw new c.ValidationError("get operation requires messageCode")
|
|
5160
5124
|
return await async function(e,t,r){const{messageCode:n}=e
|
|
5161
5125
|
if(!n)throw new c.ValidationError("get operation requires messageCode")
|
|
@@ -5163,8 +5127,8 @@ const o=r.getSessionMessageClient()
|
|
|
5163
5127
|
if(!o)throw new c.ValidationError("Session message client not available")
|
|
5164
5128
|
t.debug("Getting message",{messageCode:n})
|
|
5165
5129
|
const s=await o.getMessage(n)
|
|
5166
|
-
return s?{content:[{type:"text",text:a(s)}]}:{content:[{type:"text",text:`\u274c Message with code ${n} not found.`}],isError:!0}}(e,
|
|
5167
|
-
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}}}
|
|
5168
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
|
|
5169
5133
|
const r=t(6183),n=t(1281)
|
|
5170
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()
|
|
@@ -5268,10 +5232,10 @@ continue}const t=(0,h.findMatches)(s,n,m,100,e.path)
|
|
|
5268
5232
|
if(a.matchesFound=t.length,0===t.length){a.error="No matches found"+(m?" (tried fuzzy matching)":""),a.success=!1
|
|
5269
5233
|
const e=(0,h.findSimilarMatches)(s,n,5,.3)
|
|
5270
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
|
|
5271
|
-
const
|
|
5272
|
-
for(const e of p)for(const t of e.matches)
|
|
5273
|
-
|
|
5274
|
-
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++)
|
|
5275
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)
|
|
5276
5240
|
var o=Object.getOwnPropertyDescriptor(t,r)
|
|
5277
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=[]
|
|
@@ -5280,48 +5244,48 @@ return t},o(e)},function(e){if(e&&e.__esModule)return e
|
|
|
5280
5244
|
var t={}
|
|
5281
5245
|
if(null!=e)for(var r=o(e),n=0;n<r.length;n++)"default"!==r[n]&&s(t,e,r[n])
|
|
5282
5246
|
return i(t,e),t}),c=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
5283
|
-
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()
|
|
5284
5248
|
let v,C=u.FileOperationPhase.VALIDATION
|
|
5285
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)
|
|
5286
5250
|
const i=u.validateArgs(e,d.ReplaceInFilesSchema),{taskId:_,operations:E,fuzzy_match:q=!0,comment:S}=i
|
|
5287
|
-
|
|
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})
|
|
5288
5252
|
const T=E.filter((e=>e.documentId)).map((e=>e.documentId))
|
|
5289
|
-
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}
|
|
5290
5254
|
throw e}C=u.FileOperationPhase.TASK_VALIDATION,a.incrementCounter("replace_in_files_phase",1,{phase:C})
|
|
5291
5255
|
const P=E[0],M=P.documentId?"document:"+P.documentId:P.path
|
|
5292
|
-
let
|
|
5293
|
-
const
|
|
5256
|
+
let j=Date.now()
|
|
5257
|
+
const R=await u.validateTaskId(_,M,r,b,a,"replace_in_files")
|
|
5294
5258
|
Date.now()
|
|
5295
|
-
const x=
|
|
5259
|
+
const x=R?.requestId,O=E.some((e=>e.path))
|
|
5296
5260
|
let A=!1
|
|
5297
|
-
if(O&&x){
|
|
5298
|
-
const e=await u.validateWorkItemStates(_,M,r,s,t,
|
|
5299
|
-
Date.now(),
|
|
5300
|
-
const n=await u.autoPromoteTaskStatus(_,
|
|
5301
|
-
n.taskPromoted&&
|
|
5302
|
-
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"})
|
|
5303
5267
|
if(!o.success){if(o.isLockConflict)return{content:[{type:"text",text:"\u274c "+o.error}],isError:!0}
|
|
5304
|
-
throw Error(o.error)}Date.now(),A=!0}if(T.length>0&&x)try{await(0,p.validateRequestStatusForDocumentOperation)(x,s,
|
|
5305
|
-
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()
|
|
5306
5270
|
const D=new Map
|
|
5307
|
-
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=[]
|
|
5308
5272
|
for(const t of e.replacements){const r=(0,h.findMatches)(n,t.old,o,100,e.path)
|
|
5309
5273
|
s.push(...r)}if(s.length>0){const o=(0,y.calculateReplacementRegion)(n,s,r.fullPath)
|
|
5310
|
-
|
|
5311
|
-
const i=await(0,w.detectExternalEdits)(t.git,o,
|
|
5312
|
-
|
|
5313
|
-
const e=await(0,f.commitUserChangesBeforeToolOperation)(t.git,"replace_in_files",{requestId:x,taskId:_,workspaceManager:t.workspaceManager},
|
|
5314
|
-
e.userChangesCommitted&&(
|
|
5315
|
-
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,
|
|
5316
|
-
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})
|
|
5317
5281
|
const F=[],N=[]
|
|
5318
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)
|
|
5319
|
-
F.push(o),o.successfulReplacements>0&&"file"===o.type&&o.path&&N.push(o.path)}Date.now(),
|
|
5320
|
-
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
|
|
5321
5285
|
Date.now(),Date.now()
|
|
5322
|
-
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}))),
|
|
5323
|
-
await o.updateToolRecord(v,{metadata:{path:M,status:0===W?"completed":"partial",operationCount:E.length,operations:V,successfulFiles:J,failedFiles:
|
|
5324
|
-
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
|
|
5325
5289
|
let l="## Replace In Files - Batch Results\n\n"
|
|
5326
5290
|
if(o.getCurrentBranchContext)try{const e=await o.getCurrentBranchContext()
|
|
5327
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"
|
|
@@ -5333,8 +5297,8 @@ for(const e of o)l+=`- \u2705 \`${e.old.substring(0,40)}${e.old.length>40?"...":
|
|
|
5333
5297
|
if(s.length>0){l+="\n**Failed Replacement Details:**\n"
|
|
5334
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)))
|
|
5335
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)
|
|
5336
|
-
return{content:[{type:"text",text:
|
|
5337
|
-
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}}}
|
|
5338
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")
|
|
5339
5303
|
const t=e.trim()
|
|
5340
5304
|
if(t.includes("-")){const r=t.split("-").map((e=>e.trim()))
|
|
@@ -5390,14 +5354,14 @@ if(n)s.WorkspaceLogging.logOperation(this.logger,"info","Branch already exists,
|
|
|
5390
5354
|
else{const t=await this.git.revparse(["--abbrev-ref","HEAD"]),r=await this.gitAdapter.branchManager.getBaseBranch()
|
|
5391
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
|
|
5392
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
|
|
5393
|
-
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
|
|
5394
|
-
if(!
|
|
5395
|
-
const n
|
|
5396
|
-
if(a
|
|
5397
|
-
try{if(s.WorkspaceLogging.logOperation(this.logger,"info","Ensuring workspace ready by switching to branch",e,"single-agent","ensureWorkspaceReady",{currentBranch:
|
|
5398
|
-
try{await this.switchToRequest(
|
|
5399
|
-
this.metrics.recordValue("workspace.ensure_ready",
|
|
5400
|
-
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)
|
|
5401
5365
|
if(!i.isValid){const t="Invalid request ID: "+i.errors.join(", ")
|
|
5402
5366
|
throw s.WorkspaceLogging.logOperation(this.logger,"error",t,e,"single-agent","switchToRequest"),Error(t)}const a=i.sanitized
|
|
5403
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"})
|
|
@@ -5407,13 +5371,13 @@ const o=Date.now()-r
|
|
|
5407
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
|
|
5408
5372
|
this.metrics.recordValue("workspace.switch",n)
|
|
5409
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}`
|
|
5410
|
-
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
|
|
5411
|
-
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)
|
|
5412
5376
|
if(!n.success)throw Error("Failed to switch to main branch: "+n.error)
|
|
5413
|
-
this.currentBranch=
|
|
5414
|
-
const o=Date.now()-
|
|
5415
|
-
return this.metrics.recordValue("workspace.switch_main",o),s.WorkspaceLogging.logOperation(this.logger,"info","Successfully switched to main branch",null,"single-agent","switchToMain",{mainBranch:
|
|
5416
|
-
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()
|
|
5417
5381
|
try{t&&t.length>0?await this.git.add(t):await this.git.add("."),await this.git.commit(e)
|
|
5418
5382
|
const n=await this.git.revparse(["HEAD"]),o=Date.now()-r
|
|
5419
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
|
|
@@ -5421,33 +5385,32 @@ throw this.metrics.recordValue("workspace.commit",n),this.logger.error("Failed t
|
|
|
5421
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"})
|
|
5422
5386
|
const o=await this.requestProcessor.completeRequest(e,t,{skipConflictDetection:r?.skipConflictDetection||!1}),i=Date.now()-n
|
|
5423
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
|
|
5424
|
-
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)
|
|
5425
5389
|
if(!t.isValid)throw Error("Invalid request ID: "+t.errors.join(", "))
|
|
5426
5390
|
const r="requests/"+t.sanitized
|
|
5427
|
-
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)
|
|
5428
5392
|
if(!t.isValid)return null
|
|
5429
5393
|
const r=t.sanitized,n="requests/"+r,o=await this.git.branch()
|
|
5430
|
-
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
|
|
5431
|
-
try{
|
|
5432
|
-
if(!
|
|
5433
|
-
|
|
5434
|
-
|
|
5435
|
-
|
|
5436
|
-
|
|
5437
|
-
|
|
5438
|
-
|
|
5439
|
-
this.
|
|
5440
|
-
|
|
5441
|
-
|
|
5442
|
-
|
|
5443
|
-
|
|
5444
|
-
|
|
5445
|
-
|
|
5446
|
-
|
|
5447
|
-
|
|
5448
|
-
this.
|
|
5449
|
-
|
|
5450
|
-
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)
|
|
5451
5414
|
if(!r.ok)return null
|
|
5452
5415
|
const n=await r.json()
|
|
5453
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])
|