alchemylab 1.1.0 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +6 -6
- package/dist/http-server.js +248 -242
- package/dist/index.js +30 -24
- package/dist/mcp-direct.js +82 -76
- package/package.json +1 -1
package/dist/http-server.js
CHANGED
|
@@ -35,7 +35,7 @@ return r instanceof n.NotFoundError?o=`The request ID "${e.requestId}" was not f
|
|
|
35
35
|
const r=t(6183),n=t(9860),o=t(2960),s=t(8824)},184(e,exports,t){"use strict"
|
|
36
36
|
function r(e,t,r,n,o={}){const s=d.default.resolve(e)
|
|
37
37
|
if(O.has(s))return t.child({component:"mcp-server-registry"}).debug("Using existing server for path",{path:s}),O.get(s)
|
|
38
|
-
const i=new
|
|
38
|
+
const i=new M(s,t,r,n,o)
|
|
39
39
|
return O.set(s,i),i}var n,o=this&&this.__createBinding||(Object.create?function(e,t,r,n){void 0===n&&(n=r)
|
|
40
40
|
var o=Object.getOwnPropertyDescriptor(t,r)
|
|
41
41
|
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]}),s=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),i=this&&this.__importStar||(n=function(e){return n=Object.getOwnPropertyNames||function(e){var t=[]
|
|
@@ -45,16 +45,16 @@ var t={}
|
|
|
45
45
|
if(null!=e)for(var r=n(e),i=0;i<r.length;i++)"default"!==r[i]&&o(t,e,r[i])
|
|
46
46
|
return s(t,e),t}),a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
47
47
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.McpServer=void 0,exports.resetStdoutWrite=function(){process.stdout.write=R},exports.getMcpServer=r,exports.createServer=function(e,t,n,o,s={}){return r(e,t,n,o,s)}
|
|
48
|
-
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=i(t(7478)),k=t(4139),I=new Set,b=t(9860),v=t(1472),C=t(3328),_=t(8955),E=t(3217),q=t(5278),S=t(446),
|
|
49
|
-
!(0,p.isDebugToolsEnabled)()||
|
|
50
|
-
class
|
|
48
|
+
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=i(t(7478)),k=t(4139),I=new Set,b=t(9860),v=t(1472),C=t(3328),_=t(8955),E=t(3217),q=t(5278),S=t(446),T=t(9060),P=t(8824),j=(0,p.createLogger)({serviceName:"stdout-capture",console:!1,logToFile:!1}),R=process.stdout.write,x=process.argv.includes("--stdio")||"true"===process.env.MCP_DIRECT_MODE
|
|
49
|
+
!(0,p.isDebugToolsEnabled)()||x&&"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&&j.debug("Stdout output",{content:e.substring(0,100),length:e.length}),R.call(process.stdout,e)}catch(e){return j.error("Error in safeStdoutWrite",{error:e+""}),!0}})
|
|
50
|
+
class M{constructor(e,t,r,n,o={}){this.git=null,this.currentSSEConnection=null,this.stdioTransport=null,this.isInitializing=!1,this.isInitialized=!1,this.logger=t.child({component:"mcp-server"}),this.logger.info("Creating McpServer instance",{basePath:e,remoteServerUrl:n,hasExistingProjectId:!!o.existingProjectId}),this.basePath=e,this.alchemyPath=d.default.join(e,k.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 S.LockOverrideManager(t),this.configManager=new T.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:{}}}}),(0,y.setGlobalClientInfo)("OpenCode","1.0.0"),this.metrics.incrementCounter("mcp_server_init_started",1),this.logger.info("Starting initialization for server instance"),this.initializationPromise=this.initialize()}get branchState(){if(!this.workspaceManager)return{currentBranch:null,activeRequestId:null,isOnMainBranch:!0}
|
|
51
51
|
const e=this.workspaceManager.getCurrentContext()
|
|
52
52
|
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}
|
|
53
53
|
const e=this.workspaceManager.getCurrentContext()
|
|
54
54
|
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()
|
|
55
55
|
if(!r||"function"!=typeof r.getNextId)throw Error("Project client or getNextId method not available")
|
|
56
56
|
const n=await r.getNextId(e)
|
|
57
|
-
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,
|
|
57
|
+
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,P.getErrorMessage)(t)}),Error("Failed to get ID from remote server.")}}async initialize(){const e=this.remoteServerUrl||"https://api.alchemylabcode.com"
|
|
58
58
|
this.logger.debug("Using remote server URL",{remoteServerUrl:e})
|
|
59
59
|
const t=d.default.resolve(this.basePath)
|
|
60
60
|
if(I.has(t))return this.logger.info("Path already initialized in global registry, skipping initialization",{path:t}),void(this.isInitialized=!0)
|
|
@@ -73,7 +73,7 @@ try{if(u.default.existsSync(e)){const r=await h.default.readFile(e,"utf8")
|
|
|
73
73
|
if(r.split("\n").some((e=>e.trim()===t||e.trim()===t.slice(0,-1))))this.logger.info(k.ALCHEMY_DIR_NAME+"/ already present in .gitignore")
|
|
74
74
|
else{const n=r.trimEnd()+"\n\n# AlchemyMCP working directory\n"+t+"\n"
|
|
75
75
|
await h.default.writeFile(e,n),this.logger.info(`Added ${k.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")
|
|
76
|
-
await h.default.writeFile(e,r),this.logger.info(`Created new .gitignore with ${k.ALCHEMY_DIR_NAME}/ entry`)}}catch(e){this.logger.warn("Failed to update .gitignore file",{error:(0,
|
|
76
|
+
await h.default.writeFile(e,r),this.logger.info(`Created new .gitignore with ${k.ALCHEMY_DIR_NAME}/ entry`)}}catch(e){this.logger.warn("Failed to update .gitignore file",{error:(0,P.getErrorMessage)(e)})}}async initializeGitRepo(){try{this.logger.info("Initializing git repository"),await this.git.init(),await this.ensureGitignoreWithAlchemyLab()
|
|
77
77
|
const e=d.default.join(this.basePath,"README.md")
|
|
78
78
|
if(!u.default.existsSync(e)){const t=`# Project at ${this.basePath}\n\nCreated with AlchemyMCP Server.\n`
|
|
79
79
|
await h.default.writeFile(e,t)}this.logger.info("Git repository initialized successfully"),await this.git.add(".")
|
|
@@ -101,30 +101,30 @@ const t=await r.getSynchronizedProjectId()
|
|
|
101
101
|
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.logger.info("Re-initializing all tools with full context...")
|
|
102
102
|
const o=this.getContext();(0,v.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"}
|
|
103
103
|
const e=await w.getRepositoryStatus(this.git,this.logger,this.metrics)
|
|
104
|
-
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,
|
|
104
|
+
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,P.getErrorMessage)(e)}),{available:!1,message:"Git error: "+(0,P.getErrorMessage)(e)}}}async createSseConnection(e,t){await this.waitForInitialization(),this.cleanupSSEConnection(),this.logger.debug("Creating new SSE connection"),e.setHeader("Content-Type","text/event-stream"),e.setHeader("Cache-Control","no-cache"),e.setHeader("Connection","keep-alive")
|
|
105
105
|
const r=new g.SSEServerTransport("/sse",e)
|
|
106
106
|
this.currentSSEConnection={transport:r,response:e}
|
|
107
|
-
try{await this.server.connect(r),this.logger.info("SSE transport connected successfully")}catch(e){this.logger.error("Error connecting SSE transport",{error:(0,
|
|
108
|
-
try{await this.server.connect(this.stdioTransport),this.logger.info("STDIO transport connected successfully")}catch(e){this.logger.error("Error connecting stdio transport",{error:(0,
|
|
107
|
+
try{await this.server.connect(r),this.logger.info("SSE transport connected successfully")}catch(e){this.logger.error("Error connecting SSE transport",{error:(0,P.getErrorMessage)(e)})}return r}async connectStdio(){await this.waitForInitialization(),this.logger.debug("Connecting stdio transport"),this.stdioTransport=new g.StdioServerTransport
|
|
108
|
+
try{await this.server.connect(this.stdioTransport),this.logger.info("STDIO transport connected successfully")}catch(e){this.logger.error("Error connecting stdio transport",{error:(0,P.getErrorMessage)(e)})}}getCurrentSSEConnection(){return this.currentSSEConnection}setCurrentSSEConnection(e){this.currentSSEConnection=e}getServer(){return this.server}getCurrentGitInstance(){if(!this.workspaceManager)return this.git||void 0
|
|
109
109
|
const e=this.workspaceManager.getCurrentContext()
|
|
110
110
|
return"multi-agent"===e.mode&&e.requestId?this.workspaceManager.getCurrentGit():this.git||void 0}getContext(){if(!this.workspaceManager)throw Error("WorkspaceManager not initialized")
|
|
111
111
|
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)}}isMainBranch(e){return"main"===e||"master"===e}extractRequestIdFromBranch(e){const t=e.match(/^feature\/req(\d+)-/)
|
|
112
|
-
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,
|
|
112
|
+
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,P.getErrorMessage)(e)}),"INITIALIZING"}}generateSessionId(){return`session_${Date.now().toString(36)}_${Math.random().toString(36).substring(2,8)}_${process.pid.toString(36)}`}async getActiveWorktrees(){return await this.workspaceManager.listActiveWorkspaces()}async initializeWorkspaceManager(){try{if(this.logger.debug("initializeWorkspaceManager called",{basePath:this.basePath}),!this.git)throw Error("Git must be initialized before WorkspaceManager")
|
|
113
113
|
this.workspaceManager=(0,E.createWorkspaceManager)(this.basePath,this.logger,this.git,this.metrics,this.apiClient),this.logger.debug("WorkspaceManager created successfully"),this.logger.info("Initialized unified workspace manager",{mode:"multi-agent",basePath:this.basePath})}catch(e){throw this.logger.error("Failed to initialize workspace manager",{error:e}),e}}async switchToRequestContext(e){return this.logger.debug("switchToRequestContext called",{requestId:e,hasWorkspaceManager:!!this.workspaceManager}),this.workspaceManager?this.switchToWorktreeContext(e):{success:!1,message:"Workspace manager not available"}}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"}
|
|
114
114
|
try{let t="request-"+e
|
|
115
115
|
try{this.logger.debug("Attempting to fetch request title from API",{requestId:e})
|
|
116
116
|
const r=this.apiClient.getRequestClient(),n=await r.getRequest(e)
|
|
117
|
-
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,
|
|
117
|
+
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,P.getErrorMessage)(r),errorStack:r instanceof Error?r.stack:void 0})}const r=this.generateSessionId()
|
|
118
118
|
this.logger.info("Creating worktree for request using WorkspaceManager",{requestId:e,requestTitle:t,sessionId:r}),await this.workspaceManager.ensureWorkspaceReady(e)
|
|
119
119
|
const n=this.workspaceManager.getCurrentContext()
|
|
120
120
|
this.git=(0,c.simpleGit)({baseDir:n.basePath,binary:this.gitBinary})
|
|
121
121
|
try{const t=await w.getCurrentBranch(this.git,this.logger,this.metrics)
|
|
122
122
|
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})
|
|
123
123
|
const r=await w.switchToBranch(this.git,n.branchName,this.logger,this.metrics)
|
|
124
|
-
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,
|
|
124
|
+
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,P.getErrorMessage)(t)
|
|
125
125
|
return this.logger.error("Failed to switch to request context",{requestId:e,error:r}),{success:!1,message:"Failed to switch context: "+r}}}async getEffectiveBasePath(e){if(!this.workspaceManager||!e)return this.basePath
|
|
126
126
|
const t=await this.workspaceManager.getWorkspaceInfo(e)
|
|
127
|
-
return t?.path||this.basePath}}exports.McpServer=
|
|
127
|
+
return t?.path||this.basePath}}exports.McpServer=M
|
|
128
128
|
const O=new Map},213(e,exports,t){"use strict"
|
|
129
129
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.def=void 0
|
|
130
130
|
const r=t(6183),n=t(3707)
|
|
@@ -440,23 +440,23 @@ return t},r(e)},function(e){if(e&&e.__esModule)return e
|
|
|
440
440
|
var t={}
|
|
441
441
|
if(null!=e)for(var s=r(e),i=0;i<s.length;i++)"default"!==s[i]&&n(t,e,s[i])
|
|
442
442
|
return o(t,e),t}),i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
443
|
-
Object.defineProperty(exports,"__esModule",{value:!0}),exports.registerApiRoutes=async function(e,r,n,o){const s=n.child({component:"api"}),i=r.getTokenManager(),
|
|
443
|
+
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"})),j=P.getTokenSynchronizer(),R=await P.getTokenString()||void 0
|
|
444
444
|
n.debug("Token retrieved from authentication manager")
|
|
445
|
-
const
|
|
446
|
-
j.registerClient(
|
|
447
|
-
const O=new b.TaskClient(
|
|
445
|
+
const x=new k.ConnectionStatusManager(T,n.child({component:"connection-status-manager"}),o,{checkIntervalMs:3e4,timeoutMs:5e3}),M=new w.ProjectClient(T,n.child({component:"project-client"}),o,x,R)
|
|
446
|
+
j.registerClient(M)
|
|
447
|
+
const O=new b.TaskClient(T,n.child({component:"task-client"}),o,M,x,R)
|
|
448
448
|
j.registerClient(O)
|
|
449
|
-
const $=new v.FileOperationsClient(
|
|
449
|
+
const $=new v.FileOperationsClient(T,n.child({component:"file-client"}),o,M,R,x)
|
|
450
450
|
j.registerClient($)
|
|
451
|
-
const D=new C.ProxyClient(
|
|
451
|
+
const D=new C.ProxyClient(T,n.child({component:"proxy-client"}),o,M,R,x)
|
|
452
452
|
j.registerClient(D)
|
|
453
|
-
const A=new _.RequestClient(
|
|
453
|
+
const A=new _.RequestClient(T,n.child({component:"request-client"}),o,M,R,x)
|
|
454
454
|
A.setAuthToken(R),(0,d.isDebugToolsEnabled)()&&n.debug("Explicitly set token on RequestClient",{tokenPresent:!!R}),j.registerClient(A)
|
|
455
|
-
const F=new E.DocumentClient(
|
|
455
|
+
const F=new E.DocumentClient(T,n.child({component:"document-client"}),o,M,R,x)
|
|
456
456
|
j.registerClient(F)
|
|
457
|
-
const N=new q.ToolRecordClient(
|
|
457
|
+
const N=new q.ToolRecordClient(T,n.child({component:"tool-record-client"}),o,M,R,x)
|
|
458
458
|
j.registerClient(N)
|
|
459
|
-
const L=new S.ApiClient(
|
|
459
|
+
const L=new S.ApiClient(P,M,O,$,A,F,N,D,n.child({component:"api-client"})),z=a.default.Router();(0,h.registerAuthRoutes)(z,{projectClient:M,taskClient:O,fileClient:$,authManager:P,apiClient:L},i,n)
|
|
460
460
|
const H=r.getContext();(0,g.registerConfigRoutes)(z,n,H.basePath),e.use("/api",z)
|
|
461
461
|
const B=e=>{const t=o.startTimer(e)
|
|
462
462
|
return e=>t(e)},U=(e,t,n)=>{const o=e.query.path||e.body.path
|
|
@@ -519,10 +519,10 @@ const d=await l.commit(a)
|
|
|
519
519
|
try{await l.revparse(["--abbrev-ref","HEAD"]),await l.revparse(["HEAD"]),await l.revparse(["--show-toplevel"])}catch(e){}s({endpoint:"git/commit",method:"POST",success:!0}),n.json({success:!0,data:{commit:d.commit,author:d.author,summary:d.summary,message:a}})}catch(e){s(e)}})),e.post("/api/sync/projects",(async(e,t,n)=>{try{o.incrementCounter("api_requests_total",1,{endpoint:"sync/projects",method:"POST"})
|
|
520
520
|
const e=B("api_request_duration")
|
|
521
521
|
r.getContext(),s.info("Manual project synchronization requested"),s.info("Starting manual project synchronization")
|
|
522
|
-
try{await
|
|
522
|
+
try{await M.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"})
|
|
523
523
|
const e=B("api_request_duration")
|
|
524
|
-
try{const r=await
|
|
525
|
-
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:
|
|
524
|
+
try{const r=await M.pingDetailed(),n="online"===r.status,o=r.latency
|
|
525
|
+
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:M.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,I.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)
|
|
526
526
|
try{const n=await L.proxyGet(r,e.query)
|
|
527
527
|
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})
|
|
528
528
|
throw e}}catch(e){r(e)}})),e.post("/api/proxy/*",G,(async(e,t,r)=>{try{const r=e.path.substring(11)
|
|
@@ -658,18 +658,18 @@ C=r}else C=t.basePath
|
|
|
658
658
|
b.resolvedPath=C
|
|
659
659
|
let _=!1
|
|
660
660
|
try{_=(await g.default.stat(C)).isFile()}catch(e){const t=`Cannot access path ${C}: ${(0,k.getErrorMessage)(e)}`
|
|
661
|
-
throw b.errors.push(t),Error(t)}const E=v.maxResults||50,q=v.caseSensitive||!1,S=v.useRegex||!1,
|
|
661
|
+
throw b.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"
|
|
662
662
|
let j=void 0!==v.contextLines?v.contextLines:0
|
|
663
|
-
if(0>j?j=0:j>10&&(l.warn(`contextLines ${j} exceeds maximum of 10, clamping to 10`),j=10),!_&&!
|
|
664
|
-
let R,
|
|
665
|
-
if(_)
|
|
666
|
-
else if("*"===
|
|
667
|
-
else if(
|
|
668
|
-
throw b.errors.push(t),(0,f.createValidationError)(t)}if(b.patternInfo={needle:n,regex:R.toString(),caseSensitive:q,fileExtension:
|
|
663
|
+
if(0>j?j=0:j>10&&(l.warn(`contextLines ${j} exceeds maximum of 10, clamping to 10`),j=10),!_&&!T)throw b.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")')
|
|
664
|
+
let R,x=""
|
|
665
|
+
if(_)x="*"
|
|
666
|
+
else if("*"===T)x="*"
|
|
667
|
+
else if(T){let e=T;(e.startsWith("*.")||e.startsWith("*"))&&(e=e.substring(1)),x=e.startsWith(".")?e:"."+e}try{R=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)}`
|
|
668
|
+
throw b.errors.push(t),(0,f.createValidationError)(t)}if(b.patternInfo={needle:n,regex:R.toString(),caseSensitive:q,fileExtension:T,normalizedExtension:x},!_)try{const e=Date.now(),t=await g.default.readdir(C,{withFileTypes:!0}),r=[],n=[]
|
|
669
669
|
for(const e of t)e.isDirectory()?r.push(e.name):e.isFile()&&n.push(e.name)
|
|
670
670
|
b.initialScan={totalEntries:t.length,directories:r,files:n,firstFewFiles:n.slice(0,10),scanTime:Date.now()-e},b.phases.directoryListingTime=b.initialScan.scanTime}catch(e){const t="Failed to scan directory contents: "+(0,k.getErrorMessage)(e)
|
|
671
|
-
b.errors.push(t),l.error(t)}const
|
|
672
|
-
l.info(`Searching for "${n}" in ${
|
|
671
|
+
b.errors.push(t),l.error(t)}const M=_?"file":"directory"
|
|
672
|
+
l.info(`Searching for "${n}" in ${M} ${C} (mode: ${P})`,{needle:n,searchTarget:M,path:C,options:{maxResults:E,caseSensitive:q,fileExtension:x,searchIn:P}}),I=Date.now(),b.phases.initializationTime=I-u
|
|
673
673
|
const O=Date.now()
|
|
674
674
|
let $=[],D=0,A=0
|
|
675
675
|
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=[]
|
|
@@ -687,7 +687,7 @@ o.errors.push(r),n.error(r)}return{matches:i,totalFiles:1}}(e,t,l,s,i,u)
|
|
|
687
687
|
const f={path:e,filesProcessed:0,filesMatched:0,subdirectories:0,errors:[]}
|
|
688
688
|
try{const{filesCount:n,fileMatchesCount:c,subdirCount:d,subdirStats:h}=await r(e,t,p,a,o,s,0,f,l,u)
|
|
689
689
|
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)
|
|
690
|
-
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,R,{maxResults:E,fileExtension:
|
|
690
|
+
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,R,{maxResults:E,fileExtension:x,searchIn:P,isFile:_,contextLines:j},x,l,b)
|
|
691
691
|
$=e.matches,D=e.totalFiles
|
|
692
692
|
const t=1e3
|
|
693
693
|
$.length>0&&$.length<=t?($.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 ${$.length} matches by modification time (newest first)`)):$.length>t&&l.info(`Skipped sorting ${$.length} matches (exceeds hard cap of ${t} for performance)`),A=$.length,$.length>E&&($=$.slice(0,E),l.info(`Limited results to ${E} (from ${A} total matches)`)),$.forEach((e=>{e.relativePath=function(e,t){const r=h.default.relative(e,t)
|
|
@@ -696,8 +696,8 @@ b.errors.push(t),l.error(t),b.phases.searchTime=Date.now()-O}b.totalFiles=D,b.to
|
|
|
696
696
|
let F,N=""
|
|
697
697
|
try{if(t.getCurrentBranchContext){const e=await t.getCurrentBranchContext()
|
|
698
698
|
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:b})
|
|
699
|
-
const L="content"===
|
|
700
|
-
if(A>$.length?(F=`Found ${A} results for "${n}" (searching ${L})`,p&&(F+=" in "+p),
|
|
699
|
+
const L="content"===P?"content":"filename"===P?"filenames":"content and filenames"
|
|
700
|
+
if(A>$.length?(F=`Found ${A} results for "${n}" (searching ${L})`,p&&(F+=" in "+p),T&&(F+=" with extension "+T),F+=`${N}. Showing first ${$.length}:\n\n`):(F=`Found ${$.length} results for "${n}" (searching ${L})`,p&&(F+=" in "+p),T&&(F+=" with extension "+T),F+=N+":\n\n"),$.length>0)if(j>0){const{filenameMatches:e,mergedGroups:t}=function(e,t){const r=e.filter((e=>"filename"===e.matchType)),n=e.filter((e=>"content"===e.matchType))
|
|
701
701
|
if(0===n.length)return{filenameMatches:r,mergedGroups:[]}
|
|
702
702
|
const o=new Map
|
|
703
703
|
for(const e of n){const t=o.get(e.file)||[]
|
|
@@ -1179,13 +1179,13 @@ function r(e,t,r){try{const n=`[${(new Date).toISOString()}] ${t}${r?" "+JSON.st
|
|
|
1179
1179
|
if(r(t,"handleSpawn called",{agent:i,promptLength:a.length,requestId:c,useExistingSession:d,cliOriginSessionId:s?.sessionId||null}),!(0,S.isValidAgent)(i))return{content:[{type:"text",text:`\u274c Unknown agent '${i}'.\n\n**Available agents:** ${(0,S.getAgentNames)().join(", ")}\n\nChoose one of the available agents listed above to see detailed descriptions of each agent.`}],isError:!0}
|
|
1180
1180
|
try{const e=s?.sessionId
|
|
1181
1181
|
let n=I.sessionIdentity.getIdentity()?.agentType
|
|
1182
|
-
if(r(t,"Spawn agent type check",{callerSessionId:e||null,cachedAgentType:n||null,pid:process.pid}),!n&&e)try{const o=`http://localhost:${
|
|
1182
|
+
if(r(t,"Spawn agent type check",{callerSessionId:e||null,cachedAgentType:n||null,pid:process.pid}),!n&&e)try{const o=`http://localhost:${T}/api/sessions/${encodeURIComponent(e)}/agent-type`
|
|
1183
1183
|
r(t,"Looking up agent type from action server",{sessionId:e,url:o})
|
|
1184
1184
|
const s=await fetch(o)
|
|
1185
1185
|
if(s.ok){const o=await s.json()
|
|
1186
1186
|
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,I.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,_.getErrorMessage)(n)})}if(n){const e=(0,S.getAllowedSubagents)(n)
|
|
1187
1187
|
if(e&&!e.includes(i))return{content:[{type:"text",text:`\u274c Agent type '${n}' cannot spawn '${i}'.\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,_.getErrorMessage)(e)})}let u
|
|
1188
|
-
try{const e=await async function(e){try{const t=`http://localhost:${
|
|
1188
|
+
try{const e=await async function(e){try{const t=`http://localhost:${T}/api/agents/by-name/${encodeURIComponent(e)}`,r=await fetch(t)
|
|
1189
1189
|
if(!r.ok)return null
|
|
1190
1190
|
const n=await r.json()
|
|
1191
1191
|
return n.success?n.data??null:null}catch{return null}}(i)
|
|
@@ -1206,14 +1206,14 @@ c&&(m="requests/"+c,r(t,"Setting initialBranch for agent",{agent:i,requestId:c,i
|
|
|
1206
1206
|
let E=!1
|
|
1207
1207
|
if(d){if(v=d,n.info("Using existing session for spawn",{sessionId:v,requestId:c}),!h)throw new y.ValidationError("Could not determine OpenCode server URL")
|
|
1208
1208
|
try{let e
|
|
1209
|
-
try{const t=await fetch(`http://localhost:${
|
|
1209
|
+
try{const t=await fetch(`http://localhost:${T}/api/project-settings`)
|
|
1210
1210
|
if(t.ok){const r=await t.json()
|
|
1211
1211
|
if(r.data?.defaultModel){const[t,...n]=r.data.defaultModel.split("/")
|
|
1212
1212
|
e={providerID:t,modelID:n.join("/")}}}}catch{}const t=`${h.replace(/\/$/,"")}/session/${v}/prompt_async`,r=await fetch(t,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({parts:[{type:"text",text:C}],...i?{agent:i}:{},...e?{model:e}:{}}),signal:AbortSignal.timeout(1e4)})
|
|
1213
1213
|
if(!r.ok){const e=await r.text().catch((()=>"Unknown error"))
|
|
1214
1214
|
throw Error(`Failed to send to existing session: ${r.status} ${e}`)}n.info("Prompt sent to existing session",{sessionId:v,agent:i})}catch(e){throw Error("Failed to use existing session: "+(0,_.getErrorMessage)(e))}}else{E=!0,r(t,"Creating session via spawn-session endpoint")
|
|
1215
1215
|
const o=p;(0,b.logSessionIdentity)("subagent_operations.spawn","_meta",{parentSessionId:o})
|
|
1216
|
-
try{const s=`http://localhost:${
|
|
1216
|
+
try{const s=`http://localhost:${T}/api/spawn-session`,d=await fetch(s,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({agent:i,prompt:a,requestId:c,parentSessionId:o,title:e.title,specialization:e.specialization,allowParallel:l,callerAgentType:I.sessionIdentity.getIdentity()?.agentType}),signal:AbortSignal.timeout(15e3)})
|
|
1217
1217
|
if(!d.ok){const e=await d.text().catch((()=>"Unknown error"))
|
|
1218
1218
|
throw Error(`Spawn session endpoint failed: ${d.status} ${e}`)}const u=await d.json()
|
|
1219
1219
|
if(!u.success||!u.data)throw Error(u.error||"Spawn session returned unsuccessful")
|
|
@@ -1228,11 +1228,11 @@ if(n.info("Sending message to subagent session",{sessionId:e,promptLength:t.leng
|
|
|
1228
1228
|
if(t){const r=o.getCLISessionClient()
|
|
1229
1229
|
if(r){let o=await r.getByExternalId(t)
|
|
1230
1230
|
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,_.getErrorMessage)(e)})}let c=s
|
|
1231
|
-
if(!c)try{const t=`http://localhost:${
|
|
1231
|
+
if(!c)try{const t=`http://localhost:${T}/api/sessions/${encodeURIComponent(e)}/agent-type`,r=await fetch(t)
|
|
1232
1232
|
if(r.ok){const e=await r.json()
|
|
1233
1233
|
e.success&&e.agentType&&(c=e.agentType)}}catch{n.warn("Agent type lookup failed for session",{sessionId:e})}if(!c)throw new y.ValidationError(`Cannot continue session ${e}: unable to determine agent type. The session's agent type could not be looked up from the action server.`)
|
|
1234
1234
|
try{let r
|
|
1235
|
-
try{const e=await fetch(`http://localhost:${
|
|
1235
|
+
try{const e=await fetch(`http://localhost:${T}/api/project-settings`)
|
|
1236
1236
|
if(e.ok){const t=await e.json()
|
|
1237
1237
|
if(t.data?.defaultModel){const[e,...n]=t.data.defaultModel.split("/")
|
|
1238
1238
|
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)})
|
|
@@ -1247,7 +1247,7 @@ const s=n.path||n.file||n.directory,i=n.needle||n.query||n.pattern
|
|
|
1247
1247
|
"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))
|
|
1248
1248
|
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
|
|
1249
1249
|
return{current:r?.name??null,recent:n.map((e=>e.name)),lastActivityTime:o}}function a(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 c(e,t){const r=e||t,n=Date.now()-r
|
|
1250
|
-
return e&&
|
|
1250
|
+
return e&&P>n?{status:"working",detail:"last action "+a(n),isReady:!1}:n>j&&e?{status:"stalled",detail:"no activity for "+a(n),isReady:!0}:e?{status:"idle",detail:"no activity for "+a(n),isReady:!0}:{status:"idle",detail:"no tool activity",isReady:!0}}function l(e){let t=0,r=0,n=0
|
|
1251
1251
|
for(const o of e.trim().split("\n")){if(!o)continue
|
|
1252
1252
|
const[e,s]=o.split("\t")
|
|
1253
1253
|
"-"!==e&&(t+=parseInt(e,10)||0),"-"!==s&&(r+=parseInt(s,10)||0),n++}return{additions:t,deletions:r,files:n}}async function d(e,r,n,o){const a=await(0,k.getServerUrl)(r,n)
|
|
@@ -1325,11 +1325,11 @@ b.push(...t,...r)
|
|
|
1325
1325
|
const n=[]
|
|
1326
1326
|
if(t.length>0&&n.push("active: "+t.join(", ")),r.length>0){const e=5,t=r.slice(0,e),o=r.length-t.length
|
|
1327
1327
|
n.push(`prev: ${t.join(", ")}${o>0?` +${o} more`:""}`)}n.length>0&&(y=` [${n.join(" | ")}]`)}if(a&&!b.includes(a))continue
|
|
1328
|
-
const S=t.title||"Untitled",
|
|
1329
|
-
q.push({id:t.id,title:
|
|
1330
|
-
const S=l?q.slice(0,l):q,
|
|
1331
|
-
return`\u2022 ${e.id}\n ${e.title}${t}\n Status: ${e.status} (${e.statusDetail}) | Age: ${s(e.age)} | ${e.totalTokens.toLocaleString()} tokens${e.requestsInfo}${r}${o}`})),
|
|
1332
|
-
return{content:[{type:"text",text:`Found ${S.length} session${1!==S.length?"s":""}${
|
|
1328
|
+
const S=t.title||"Untitled",T=S.length>50?S.slice(0,47)+"...":S
|
|
1329
|
+
q.push({id:t.id,title:T,status:f,age:r,totalTokens:o,requestsInfo:y,allRequestIds:b,statusDetail:h.detail,specialization:m?.specialization??null,currentAction:s,recentActions:l})}if(0===q.length)return{content:[{type:"text",text:"No sessions match the specified filters."}]}
|
|
1330
|
+
const S=l?q.slice(0,l):q,T=S.map((e=>{const t=e.specialization?"\n Specialization: "+e.specialization:"",r=e.currentAction?"\n Current: "+e.currentAction:"",o="specialist"!==n.agentType&&e.recentActions.length>0?"\n Recent: "+e.recentActions.join(", "):""
|
|
1331
|
+
return`\u2022 ${e.id}\n ${e.title}${t}\n Status: ${e.status} (${e.statusDetail}) | Age: ${s(e.age)} | ${e.totalTokens.toLocaleString()} tokens${e.requestsInfo}${r}${o}`})),P=l&&q.length>l?` (showing ${l} of ${q.length})`:""
|
|
1332
|
+
return{content:[{type:"text",text:`Found ${S.length} session${1!==S.length?"s":""}${P}:\n\n${T.join("\n\n")}`}]}}catch(e){throw Error("Failed to list sessions: "+(0,_.getErrorMessage)(e))}}var g,p=this&&this.__createBinding||(Object.create?function(e,t,r,n){void 0===n&&(n=r)
|
|
1333
1333
|
var o=Object.getOwnPropertyDescriptor(t,r)
|
|
1334
1334
|
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]}),f=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),m=this&&this.__importStar||(g=function(e){return g=Object.getOwnPropertyNames||function(e){var t=[]
|
|
1335
1335
|
for(var r in e)({}).hasOwnProperty.call(e,r)&&(t[t.length]=r)
|
|
@@ -1365,7 +1365,7 @@ case"list-sessions":const s={activeOnly:r.listSessions?.activeOnly,requestId:r.l
|
|
|
1365
1365
|
f=await h(t,c,i,s)
|
|
1366
1366
|
break
|
|
1367
1367
|
default:throw new y.ValidationError("Unknown operation: "+p)}return l({success:!0}),s.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}),s.incrementCounter("subagent_operations_errors",1),{content:[{type:"text",text:"Subagent operation failed: "+(0,_.getErrorMessage)(e)}],isError:!0}}}
|
|
1368
|
-
const y=t(9860),w=t(8035),k=t(7617),I=t(6688),b=t(7280),v=t(6183),C=m(t(5967)),_=t(8824),E=t(9896),q=t(6928),S=t(8955),
|
|
1368
|
+
const y=t(9860),w=t(8035),k=t(7617),I=t(6688),b=t(7280),v=t(6183),C=m(t(5967)),_=t(8824),E=t(9896),q=t(6928),S=t(8955),T=3456,P=6e4,j=3e5},1791(e,exports,t){"use strict"
|
|
1369
1369
|
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}}
|
|
1370
1370
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.ProjectContext=void 0,exports.projectContextMiddleware=r
|
|
1371
1371
|
const o=n(t(9896)),s=n(t(6928)),i=t(4139),a=t(4055),c=t(8824)
|
|
@@ -1680,36 +1680,36 @@ m.info("Initial branch context",{initialBranch:C.branch,initialRequestId:C.reque
|
|
|
1680
1680
|
const _=[]
|
|
1681
1681
|
for(const e of h){const{normalizedPath:r,fullPath:n}=d.validateAndNormalizePath(e.source,t),{normalizedPath:o,fullPath:s}=d.validateAndNormalizePath(e.destination,t)
|
|
1682
1682
|
_.push({source:r,destination:o,fullSource:n,fullDestination:s})}I=d.FileOperationPhase.TASK_VALIDATION,i.incrementCounter("move_files_phase",1,{phase:I})
|
|
1683
|
-
const E=await d.validateTaskId(u,_[0].source,r,m,i,b.metricsPrefix),q=E?.requestId,S=await d.validateWorkItemStates(u,_[0].source,r,o,t,m,i,b.metricsPrefix),
|
|
1684
|
-
|
|
1685
|
-
const
|
|
1686
|
-
if(!
|
|
1687
|
-
throw Error(
|
|
1683
|
+
const E=await d.validateTaskId(u,_[0].source,r,m,i,b.metricsPrefix),q=E?.requestId,S=await d.validateWorkItemStates(u,_[0].source,r,o,t,m,i,b.metricsPrefix),T=await d.autoPromoteTaskStatus(u,E.status,q,S.request?.status,_[0].source,r,o,m,i,b.metricsPrefix)
|
|
1684
|
+
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})
|
|
1685
|
+
const P=await d.ensureCorrectWorkspaceContext({taskPromoted:T.taskPromoted,requestId:q,context:t,operation:"move-files",logger:m,metrics:i,metricsPrefix:b.metricsPrefix})
|
|
1686
|
+
if(!P.success){if(P.isLockConflict)return{content:[{type:"text",text:"\u274c "+P.error}],isError:!0}
|
|
1687
|
+
throw Error(P.error)}let j={hadUserMods:!1,userModsCommitHash:void 0}
|
|
1688
1688
|
if(t.git)try{m.debug("[MOVE-FILES] Checking for user changes before move operations")
|
|
1689
1689
|
const e=await(0,g.commitUserChangesBeforeToolOperation)(t.git,"move-files",{requestId:q,taskId:u,workspaceManager:t.workspaceManager},m,i)
|
|
1690
1690
|
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}),j={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}),I=d.FileOperationPhase.RECORD_CREATION,i.incrementCounter("move_files_phase",1,{phase:I})
|
|
1691
|
-
const{toolRecordId:R,localToolRecordId:
|
|
1691
|
+
const{toolRecordId:R,localToolRecordId:x}=await d.createFileOperationRecords(u,q,t.projectId,b.recordType,_[0].source,{operationCount:h.length,operations:_.map((e=>({source:e.source,destination:e.destination}))),userComment:v,hadUserMods:j.hadUserMods,userModsCommitHash:j.userModsCommitHash},r,n,m,i,b.metricsPrefix,f)
|
|
1692
1692
|
w=R,k=R,I=b.fileOperationPhase,i.incrementCounter("move_files_phase",1,{phase:I})
|
|
1693
|
-
const
|
|
1693
|
+
const M=[]
|
|
1694
1694
|
let O=0
|
|
1695
1695
|
for(const e of _){const t={operation:{source:e.source,destination:e.destination},success:!1}
|
|
1696
1696
|
try{try{await a.default.access(e.fullSource)}catch(t){throw Error("Source path not accessible: "+e.source)}const r=(await a.default.stat(e.fullSource)).isDirectory()
|
|
1697
1697
|
t.isDirectory=r
|
|
1698
1698
|
const n=c.default.dirname(e.fullDestination)
|
|
1699
|
-
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})}
|
|
1699
|
+
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})}M.push(t)}const $=Date.now()-y
|
|
1700
1700
|
i.recordValue("move_files_time",$),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)
|
|
1701
1701
|
let D=null
|
|
1702
1702
|
if(O>0){I=d.FileOperationPhase.GIT_COMMIT,i.incrementCounter("move_files_phase",1,{phase:I})
|
|
1703
|
-
const e=
|
|
1704
|
-
D=await d.commitToGit(u,_[0].destination,R,
|
|
1705
|
-
const A=
|
|
1703
|
+
const e=M.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}`
|
|
1704
|
+
D=await d.commitToGit(u,_[0].destination,R,x,r,t,m,i,b.metricsPrefix)}I=d.FileOperationPhase.RECORD_UPDATE_SUCCESS,i.incrementCounter("move_files_phase",1,{phase:I})
|
|
1705
|
+
const A=M.filter((e=>e.success)),F=M.filter((e=>!e.success))
|
|
1706
1706
|
await d.updateFileOperationRecords(u,w,k,_[0].source,b.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:A.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:j.hadUserMods,userModsCommitHash:j.userModsCommitHash},O===h.length?`Successfully moved all ${h.length} items`:`Moved ${O}/${h.length} items successfully`,r,n,m,i,b.metricsPrefix)
|
|
1707
1707
|
const N=t.getCurrentBranchContext?await t.getCurrentBranchContext():{branch:null,requestId:null,isMain:!0}
|
|
1708
1708
|
let L=""
|
|
1709
1709
|
if(O===h.length)L=`Successfully moved all ${h.length} ${1===h.length?"item":"items"}`
|
|
1710
|
-
else if(O>0){const e=
|
|
1711
|
-
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"+
|
|
1712
|
-
return D?.commitHash&&(L+="\nCommit: "+D.commitHash.substring(0,8)),N.requestId&&(L+="\nBranch: "+N.requestId),
|
|
1710
|
+
else if(O>0){const e=M.filter((e=>!e.success))
|
|
1711
|
+
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"+M.map((e=>`\u2022 ${e.operation.source} \u2192 ${e.operation.destination}: ${e.error}`)).join("\n")
|
|
1712
|
+
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
|
|
1713
1713
|
await n.createToolRecord({...r?{}:{taskId:e.taskId},projectId:t.projectId,type:"move-files",metadata:{status:"failed",timestamp:(new Date).toISOString(),operationCount:e.operations?.length||0,operations:e.operations||[],userComment:e.comment,error:(0,p.getErrorMessage)(o),errorDetails:o instanceof Error?o.stack:o+"",phase:I,attemptedTaskId:e.taskId,taskIdValidationFailed:r},note:"Failed to move files - "+(0,p.getErrorMessage)(o)})}catch(t){m.error("Failed to create failure record for move-files operation",{error:t instanceof Error?t.message:t+"",taskId:e.taskId,operationCount:e.operations?.length||0})}const s=Date.now()-y
|
|
1714
1714
|
if(i.recordValue("move_files_time",s),i.incrementCounter("move_files_errors",1),m.error("Error in move-files operation:",{error:(0,p.getErrorMessage)(o),time:s}),(w||k)&&e.taskId){I=d.FileOperationPhase.RECORD_UPDATE_FAILURE
|
|
1715
1715
|
try{await d.updateFileOperationRecords(e.taskId,w,k,e.operations?.[0]?.source||"unknown",b.recordType,"Failed to move files",{status:"failed",error:(0,p.getErrorMessage)(o),operationCount:e.operations?.length||0,operations:e.operations||[],userComment:e.comment},"Failed to move files",r,n,m,i,b.metricsPrefix)}catch(t){m.error("Failed to update record with failure status",{taskId:e.taskId,recordId:w,error:t instanceof Error?t.message:t+""})}}return d.handleFileOperationError(o,I,m,i,e,b)}}
|
|
@@ -1719,7 +1719,7 @@ Object.defineProperty(exports,"__esModule",{value:!0}),exports.def=void 0
|
|
|
1719
1719
|
const r=t(6183),n=t(3707)
|
|
1720
1720
|
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){"use strict"
|
|
1721
1721
|
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),I=t(6111),b=t(700),v=t(2783),C=t(2601),_=t(1722),E=t(7257),q=t(9230),S=t(5216),
|
|
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),I=t(6111),b=t(700),v=t(2783),C=t(2601),_=t(1722),E=t(7257),q=t(9230),S=t(5216),T=t(6473),P=t(4921),j=t(8850),R=t(3556),x=t(1391),M=t(6315),O=t(7713),$=t(6252),D=t(213),A=t(7250),F=t(2425),N=t(1540),L=t(5767),z=t(4973),H=t(509),B=t(7613),U=t(3322),G=t(5247),W=t(542);(0,r.registerTool)(n.def),(0,r.registerTool)(o.def),(0,r.registerTool)(s.def),(0,r.registerTool)(i.def),(0,r.registerTool)(a.def),(0,r.registerTool)(c.def),(0,r.registerTool)(l.def),(0,r.registerTool)(d.def),(0,r.registerTool)(u.def),(0,r.registerTool)(h.def),(0,r.registerTool)(g.def),(0,r.registerTool)(p.def),(0,r.registerTool)(f.def),(0,r.registerTool)(m.def),(0,r.registerTool)(y.def),(0,r.registerTool)(w.def),(0,r.registerTool)(k.def),(0,r.registerTool)(I.def),(0,r.registerTool)(b.def),(0,r.registerTool)(v.def),(0,r.registerTool)(C.def),(0,r.registerTool)(_.def),(0,r.registerTool)(E.def),(0,r.registerTool)(q.def),(0,r.registerTool)(S.def),(0,r.registerTool)(T.def),(0,r.registerTool)(P.def),(0,r.registerTool)(j.def),(0,r.registerTool)(R.def),(0,r.registerTool)(x.def),(0,r.registerTool)(M.def),(0,r.registerTool)(O.def),(0,r.registerTool)($.def),(0,r.registerTool)(D.def),(0,r.registerTool)(A.def),(0,r.registerTool)(F.def),(0,r.registerTool)(N.def),(0,r.registerTool)(L.def),(0,r.registerTool)(z.def),(0,r.registerTool)(H.def),(0,r.registerTool)(B.def),(0,r.registerTools)(U.metaDefs),(0,r.registerTools)(G.testingDefs),(0,r.registerTools)(W.debugDefs),(0,t(2245).freezeRegistry)()},2478(e,exports){"use strict"
|
|
1723
1723
|
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){"use strict"
|
|
1724
1724
|
async function r(e,t,r){if(C.has(r)&&_>=t){if(0===t)return 0
|
|
1725
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]"
|
|
@@ -1797,8 +1797,8 @@ let c
|
|
|
1797
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,b),a=s.map((e=>n({name:e.name,isDirectory(){return e.isDirectory},isFile(){return!e.isDirectory}},b,e)))
|
|
1798
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()
|
|
1799
1799
|
E+="\n\nBranch: "+(S?.branchName||"unknown")
|
|
1800
|
-
const
|
|
1801
|
-
return a.recordValue("list_directory_time",
|
|
1800
|
+
const T=Date.now()-h
|
|
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
|
|
1802
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}}}
|
|
1803
1803
|
const y=m(t(1943)),w=m(t(6928)),k=t(6183),I=f(t(5967)),b=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){"use strict"
|
|
1804
1804
|
var r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
@@ -2236,47 +2236,47 @@ try{const i=u.validateArgs(e,d.ReplaceStringsSchema),{taskId:C,operations:_,comm
|
|
|
2236
2236
|
if(y.info("Replacing strings across files and documents",{taskId:C,operationCount:_.length,comment:E}),!_||0===_.length)throw new h.ValidationError("At least one operation is required")
|
|
2237
2237
|
const q=_.filter((e=>e.path)),S=_.filter((e=>e.documentId))
|
|
2238
2238
|
y.info("Operation breakdown",{fileOperations:q.length,documentOperations:S.length})
|
|
2239
|
-
const
|
|
2239
|
+
const T=[]
|
|
2240
2240
|
for(const e of q){const{normalizedPath:r,fullPath:n}=u.validateAndNormalizePath(e.path,t)
|
|
2241
|
-
|
|
2241
|
+
T.push({type:"file",path:r,fullPath:n,replacements:e.replacements,mode:e.mode||"unique"})}const P=[]
|
|
2242
2242
|
if(S.length>0&&!t.documentFileManager)throw Error("Document file manager not available - cannot process document operations")
|
|
2243
|
-
for(const e of S)
|
|
2244
|
-
if(
|
|
2243
|
+
for(const e of S)P.push({type:"document",documentId:e.documentId,replacements:e.replacements,mode:e.mode||"unique"})
|
|
2244
|
+
if(P.length>0&&t.apiClient){const e=P.map((e=>e.documentId))
|
|
2245
2245
|
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}
|
|
2246
2246
|
throw e}}b=u.FileOperationPhase.TASK_VALIDATION,a.incrementCounter("replace_strings_phase",1,{phase:b})
|
|
2247
|
-
const j=
|
|
2248
|
-
let
|
|
2249
|
-
|
|
2247
|
+
const j=T.length>0?T[0].path:"document-operation",R=await u.validateTaskId(C,j,r,y,a,v.metricsPrefix),x=R?.requestId
|
|
2248
|
+
let M=null
|
|
2249
|
+
T.length>0&&x&&(M=await u.validateWorkItemStates(C,T[0].path,r,s,t,y,a,v.metricsPrefix))
|
|
2250
2250
|
let O={taskPromoted:!1,requestPromoted:!1}
|
|
2251
|
-
|
|
2252
|
-
const $=await u.ensureCorrectWorkspaceContext({taskPromoted:O.taskPromoted,requestId:
|
|
2251
|
+
T.length>0&&x&&M&&(O=await u.autoPromoteTaskStatus(C,R.status,x,M.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:x,previousStatus:R.status,newStatus:O.newTaskStatus,triggeringOperation:"replace-strings"}))
|
|
2252
|
+
const $=await u.ensureCorrectWorkspaceContext({taskPromoted:O.taskPromoted,requestId:x,context:t,operation:"replace-strings",logger:y,metrics:a,metricsPrefix:v.metricsPrefix})
|
|
2253
2253
|
if(!$.success){if($.isLockConflict)return{content:[{type:"text",text:"\u274c "+$.error}],isError:!0}
|
|
2254
|
-
throw Error($.error)}if(
|
|
2255
|
-
for(let e=0;e<
|
|
2256
|
-
|
|
2254
|
+
throw Error($.error)}if(T.length>0){y.debug("Re-validating file paths with correct workspace context",{operationCount:T.length,workspaceBasePath:t.workspaceManager?.getCurrentContext().basePath})
|
|
2255
|
+
for(let e=0;e<T.length;e++){const r=T[e],n=q[e],{normalizedPath:o,fullPath:s}=u.validateAndNormalizePath(n.path,t)
|
|
2256
|
+
T[e]={...r,path:o,fullPath:s}}}if(P.length>0&&x)try{await(0,g.validateRequestStatusForDocumentOperation)(x,s,y,a,"replace-strings-document")}catch(e){if(e instanceof h.ValidationError)return{content:[{type:"text",text:e.message}],isError:!0}
|
|
2257
2257
|
throw e}b=u.FileOperationPhase.RECORD_CREATION,a.incrementCounter("replace_strings_phase",1,{phase:b})
|
|
2258
|
-
const D=[...
|
|
2259
|
-
if(k=A,I=A,b=v.fileOperationPhase,a.incrementCounter("replace_strings_phase",1,{phase:b}),
|
|
2260
|
-
const e=await(0,p.commitUserChangesBeforeToolOperation)(t.git,"replace-strings",{requestId:
|
|
2261
|
-
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:
|
|
2258
|
+
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:A}=await u.createFileOperationRecords(C,x,t.projectId,v.recordType,j,{operationCount:_.length,fileOperations:T.length,documentOperations:P.length,operations:D,userComment:E},r,o,y,a,v.metricsPrefix,c)
|
|
2259
|
+
if(k=A,I=A,b=v.fileOperationPhase,a.incrementCounter("replace_strings_phase",1,{phase:b}),T.length>0&&t.git)try{y.debug("[REPLACE-STRINGS] Checking for user changes before replace operations")
|
|
2260
|
+
const e=await(0,p.commitUserChangesBeforeToolOperation)(t.git,"replace-strings",{requestId:x,taskId:C,workspaceManager:t.workspaceManager},y,a)
|
|
2261
|
+
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})
|
|
2262
2262
|
const F=[]
|
|
2263
2263
|
let N=0,L=0
|
|
2264
|
-
for(const e of
|
|
2264
|
+
for(const e of T){const t={type:"file",path:e.path,success:!1,replacements:[],successfulReplacements:0,failedReplacements:0}
|
|
2265
2265
|
try{if(await l.default.access(e.fullPath),!(await l.default.stat(e.fullPath)).isFile())throw Error("Path is not a file: "+e.path)
|
|
2266
2266
|
const r=await l.default.readFile(e.fullPath,"utf8"),{newContent:o,results:s}=await n(r,e.replacements,e.mode)
|
|
2267
|
-
t.replacements=s,t.successfulReplacements=s.filter((e=>e.success)).length,t.failedReplacements=s.filter((e=>!e.success)).length,o!==r?(await l.default.writeFile(e.fullPath,o,"utf8"),t.success=!0,L++,y.info("File updated successfully",{path:e.path,successfulReplacements:t.successfulReplacements,failedReplacements:t.failedReplacements})):0===t.failedReplacements&&(t.success=!0),N+=t.failedReplacements}catch(r){t.error=(0,m.getErrorMessage)(r),t.failedReplacements=e.replacements.length,N+=t.failedReplacements,y.error("File operation failed",{path:e.path,error:t.error})}F.push(t)}for(const e of
|
|
2267
|
+
t.replacements=s,t.successfulReplacements=s.filter((e=>e.success)).length,t.failedReplacements=s.filter((e=>!e.success)).length,o!==r?(await l.default.writeFile(e.fullPath,o,"utf8"),t.success=!0,L++,y.info("File updated successfully",{path:e.path,successfulReplacements:t.successfulReplacements,failedReplacements:t.failedReplacements})):0===t.failedReplacements&&(t.success=!0),N+=t.failedReplacements}catch(r){t.error=(0,m.getErrorMessage)(r),t.failedReplacements=e.replacements.length,N+=t.failedReplacements,y.error("File operation failed",{path:e.path,error:t.error})}F.push(t)}for(const e of P){const r={type:"document",documentId:e.documentId,success:!1,replacements:[],successfulReplacements:0,failedReplacements:0}
|
|
2268
2268
|
try{const o=await t.documentFileManager.getDocumentAsFile(e.documentId),s=t.documentFileManager.getCachedDocumentInfo(e.documentId)
|
|
2269
2269
|
r.filename=s?.filename
|
|
2270
2270
|
const i=await l.default.readFile(o,"utf8"),{newContent:a,results:c}=await n(i,e.replacements,e.mode)
|
|
2271
|
-
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(
|
|
2272
|
-
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,
|
|
2273
|
-
try{await o.updateToolRecord(I,{metadata:{path:
|
|
2271
|
+
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))
|
|
2272
|
+
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:I,successField:"successfulReplacements",logger:y,metrics:a,metricsPrefix:"replace_strings"},t),H=u.processMultiFileOperationResults(F,"successfulReplacements"),{successfulOperations:B,failedOperations:U,totalSuccessfulChanges:G,overallSuccess:W,successfulFiles:V,failedFiles:J}=H
|
|
2273
|
+
try{await o.updateToolRecord(I,{metadata:{path:T.length>0?T[0].path:"document:"+P[0]?.documentId,status:W?"completed":"failed",error:W?void 0:U+" operations failed",totalOperations:F.length,successfulFiles:V,failedFiles:J,operations:D,totalSuccessfulReplacements:G,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:W?`String replacement completed: ${B}/${F.length} operations successful${T.length>0?" (committed to git)":""}`:`String replacement partially failed: ${U}/${F.length} operations failed`})}catch(e){y.warn("Failed to update tool record",{recordError:e})}u.formatMultiFileToolResponse("String Replacement",{successfulOperations:B,failedOperations:U,totalSuccessfulChanges:G,overallSuccess:W,successfulFiles:V,failedFiles:J},z,$)
|
|
2274
2274
|
let K="## String Replacement Results\n\n"
|
|
2275
2275
|
if(t.workspaceManager&&(K+=`**Branch:** \`${t.workspaceManager.getCurrentContext().branchName}\`\n\n`),K+="**Summary:**\n",K+=`- **Files processed:** ${B+U}\n`,K+=`- **Successful operations:** ${B}\n`,K+=`- **Failed operations:** ${U}\n`,K+=`- **Total replacements:** ${G} 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"),$.lockAcquired&&$.lockedRequestId&&(K+=`\u{1f512} **Locked request:** ${$.lockedRequestId}\n\n`),1===F.length){const e=F[0]
|
|
2276
2276
|
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"
|
|
2277
2277
|
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:** ${B}\n`,K+=`- **Failed:** ${U}\n`,K+=`- **Total Replacements:** ${G} successful, ${N} failed\n\n`,K+="**Detailed Results:**\n\n"
|
|
2278
2278
|
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"
|
|
2279
|
-
for(const t of e.replacements.filter((e=>!e.success)))K+=` - "${t.old_str}" \u2192 "${t.new_str}": ${t.error}\n`}K+="\n"}}
|
|
2279
|
+
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")
|
|
2280
2280
|
const Y=Date.now()-w
|
|
2281
2281
|
return y.info("Replace strings operation completed",{duration:Y,success:W,totalOperations:F.length,successfulOperations:B,failedOperations:U}),a.incrementCounter("replace_strings_total",1,{success:W}),{content:[{type:"text",text:K}],isError:!W}}catch(t){const r=Date.now()-w
|
|
2282
2282
|
if(y.error("Replace strings operation failed",{error:t instanceof Error?t.stack:t+"",duration:r,phase:b}),I)try{await o.updateToolRecord(I,{metadata:{path:e?.operations?.[0]?.path||e?.operations?.[0]?.documentId,status:"failed",error:(0,m.getErrorMessage)(t),phase:b,duration:r,userComment:e?.comment},note:"String replacement failed: "+(0,m.getErrorMessage)(t)})}catch(e){}return a.incrementCounter("replace_strings_errors",1,{phase:b}),{content:[{type:"text",text:"\u274c **Replace Strings Failed:** "+(0,m.getErrorMessage)(t)}],isError:!0}}}
|
|
@@ -2378,16 +2378,16 @@ const e=await(0,m.findAvailablePort)(_)
|
|
|
2378
2378
|
e!==_&&E.info(`Preferred port ${_} is in use, using port ${e} instead`),E.info("Starting HTTP API server...",{port:e,baseDir:C,remoteServerUrl:S})
|
|
2379
2379
|
const t=new l.ProjectRegistry(E),r=new u.DefaultProjectFileSystem(E),c=n.default.join(C,f.ALCHEMY_DIR_NAME)
|
|
2380
2380
|
E.info(`Checking ${f.ALCHEMY_DIR_NAME} directory`,{alchemyPath:c}),await r.ensureDirectoryExists(c)
|
|
2381
|
-
const h=new I.TokenManager(E,n.default.join(c,"auth-token.json")),b=(await y.ClientFactory.createClient(S,E,q,{tokenManager:h,workingDir:C,alchemyPath:c})).projectClient,v=new k.ProjectClientAdapter(b,E),
|
|
2382
|
-
E.info("Using project",{projectId:
|
|
2381
|
+
const h=new I.TokenManager(E,n.default.join(c,"auth-token.json")),b=(await y.ClientFactory.createClient(S,E,q,{tokenManager:h,workingDir:C,alchemyPath:c})).projectClient,v=new k.ProjectClientAdapter(b,E),T=new d.ProjectSynchronizer(E,t,v,r),P=await T.getOrCreateProject(C,{name:n.default.basename(C)||"Local Project",description:"Project for "+n.default.basename(C),status:"active",metadata:{basePath:C,alchemyPath:c,bootstrapped:!0}})
|
|
2382
|
+
E.info("Using project",{projectId:P.id,projectName:P.name})
|
|
2383
2383
|
const j=(0,o.default)()
|
|
2384
2384
|
j.use((0,s.default)()),j.use(o.default.json({limit:"50mb"})),j.use(o.default.urlencoded({extended:!0})),j.use((0,g.requestLogger)(E))
|
|
2385
2385
|
try{E.info("Creating MCP server instance")
|
|
2386
|
-
const t=await(0,i.createServer)(C,E,q,S,{existingProjectId:
|
|
2386
|
+
const t=await(0,i.createServer)(C,E,q,S,{existingProjectId:P.id})
|
|
2387
2387
|
E.info("MCP server instance created successfully")
|
|
2388
2388
|
const r=t.getContext()
|
|
2389
2389
|
E.info("Got server context",{projectId:r.projectId}),t.getContext()&&t.connectionManager?(E.info("Adding connection status middleware"),j.use((0,p.addConnectionStatusInfo)(t.connectionManager))):E.warn("Unable to add connection status middleware - connection manager not available")
|
|
2390
|
-
try{const e=
|
|
2390
|
+
try{const e=P.id
|
|
2391
2391
|
E.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){E.warn("Failed to set up project context middleware",{error:(0,w.getErrorMessage)(e)})}(0,a.registerApiRoutes)(j,t,E,q),j.use((0,g.errorHandler)(E,q)),j.listen(e,(()=>{E.info("HTTP API server listening on port "+e,{baseDir:C,port:e,nodeVersion:process.version})}))}catch(e){E.error("Failed to create or initialize MCP server",{error:e instanceof Error?e.stack:e+""})
|
|
2392
2392
|
let t=!1
|
|
2393
2393
|
e instanceof Error&&(t=e.message.includes("connection")||e.message.includes("timeout")||e.message.includes("network")||"ConnectionError"===e.name),q.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}})})),E.warn("Continuing with limited functionality due to initialization error")}process.on("SIGINT",(()=>{E.info("Received SIGINT signal, shutting down..."),process.exit(0)})),process.on("SIGTERM",(()=>{E.info("Received SIGTERM signal, shutting down..."),process.exit(0)})),process.on("uncaughtException",(e=>{E.error("Uncaught exception",{error:e.stack}),process.exit(1)})),process.on("unhandledRejection",(e=>{E.error("Unhandled promise rejection",{reason:e}),process.exit(1)}))}catch(e){E.error("Failed to start HTTP API server",{error:e instanceof Error?e.stack:e+""}),process.exit(1)}}()},3626(e,exports,t){"use strict"
|
|
@@ -2498,7 +2498,7 @@ e&&2===e.length&&e.every((e=>"quick-edit"===e.type))&&(E=!0,f.info("Detected two
|
|
|
2498
2498
|
const q=await y.createRequest({title:b,description:v,type:"quick-edit",acceptanceCriteria:["Quick change completed successfully"]})
|
|
2499
2499
|
if(!q||!q.id)throw Error("Failed to create request")
|
|
2500
2500
|
const S=q.id
|
|
2501
|
-
let
|
|
2501
|
+
let T
|
|
2502
2502
|
f.info("Created request",{requestId:S})
|
|
2503
2503
|
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)
|
|
2504
2504
|
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")
|
|
@@ -2506,21 +2506,21 @@ f.debug("Creating task")
|
|
|
2506
2506
|
const e=await w.createTask({requestId:S,projectId:d.projectId,title:`Execute ${t} operation`,description:"Quick change: "+b})
|
|
2507
2507
|
if(!e||!e.id)throw Error("Failed to create task")
|
|
2508
2508
|
let v
|
|
2509
|
-
if(
|
|
2510
|
-
else if("replace"===t)v=await(0,o.handleReplaceInFiles)({taskId:
|
|
2509
|
+
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,I,y,h,g,p)
|
|
2510
|
+
else if("replace"===t)v=await(0,o.handleReplaceInFiles)({taskId:T,...C,comment:_},d,w,I,y,h,g,p)
|
|
2511
2511
|
else{if("manage"!==t)throw new r.ValidationError("Unsupported operation type: "+t)
|
|
2512
|
-
v=await(0,s.handleManageFiles)({taskId:
|
|
2513
|
-
try{await w.updateTaskStatus(
|
|
2514
|
-
|
|
2515
|
-
try{await(0,i.handleCompleteTask)({taskId:
|
|
2516
|
-
try{await w.updateTaskStatus(
|
|
2517
|
-
const j=
|
|
2518
|
-
let
|
|
2512
|
+
v=await(0,s.handleManageFiles)({taskId:T,...C,comment:_||b},d,w,I,y,u,h,g,p)}if(v.isError){f.error("File operation failed, cleaning up request and task",{requestId:S,taskId:T})
|
|
2513
|
+
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")
|
|
2514
|
+
P?f.warn("File operation completed with partial failures",{requestId:S}):f.info("File operation completed successfully"),f.debug("Completing task")
|
|
2515
|
+
try{await(0,i.handleCompleteTask)({taskId:T,summary:`Executed ${t} operation for quick fix: ${b}${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})
|
|
2516
|
+
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")
|
|
2517
|
+
const j=P?`Quick change completed with partial success: ${b}. Some replacements failed - see details below.`:"Quick change completed: "+b,R=P?t+" operation partially completed - some operations succeeded, some failed":t+" operation executed successfully"
|
|
2518
|
+
let x=!1
|
|
2519
2519
|
try{const e=await(0,a.handleCompleteRequest)({requestId:S,summary:j,acceptanceEvidence:[{evidence:R}],testVerification:void 0},d,u,h,g,p)
|
|
2520
2520
|
if(e.isError)f.error("Request completion failed, attempting direct completion",{requestId:S,error:e.content[0].text})
|
|
2521
|
-
else{try{await y.updateRequest(S,{status:"completed",completionSummary:j}),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)})}
|
|
2521
|
+
else{try{await y.updateRequest(S,{status:"completed",completionSummary:j}),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)})}x=!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(!x)try{f.info("Attempting direct request completion via API",{requestId:S}),await y.updateRequest(S,{status:"completed",completionSummary:j}),x=!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 M=Date.now()-m
|
|
2522
2522
|
let O
|
|
2523
|
-
return f.info("Quick fix completed",{requestId:S,duration:
|
|
2523
|
+
return f.info("Quick fix completed",{requestId:S,duration:M,hasPartialFailure:P}),O=P?`\u26a0\ufe0f Quick change completed with partial success\n\n**Request:** ${S}\n**Title:** ${b}\n**Operation:** ${t}\n**Duration:** ${M}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:** ${b}\n**Operation:** ${t}\n**Duration:** ${M}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
|
|
2524
2524
|
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}}}
|
|
2525
2525
|
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){"use strict"
|
|
2526
2526
|
module.exports=require("simple-git")},3884(e,exports,t){"use strict"
|
|
@@ -2603,9 +2603,9 @@ return o(t,e),t}),i=this&&this.__importDefault||function(e){return e&&e.__esModu
|
|
|
2603
2603
|
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"),I=Date.now()
|
|
2604
2604
|
let b,v,C=d.FileOperationPhase.VALIDATION
|
|
2605
2605
|
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"}
|
|
2606
|
-
try{const r=d.validateArgs(e,l.WriteFileSchema),{taskId:i,path:f,documentId:E,content:q,format:S,append:
|
|
2607
|
-
w.info("Writing content to "+(j?"document":"file"),{taskId:i,filePath:R?f:void 0,documentId:j?E:void 0,contentLength:"string"==typeof q?q.length:JSON.stringify(q).length,format:S,append:
|
|
2608
|
-
let M,
|
|
2606
|
+
try{const r=d.validateArgs(e,l.WriteFileSchema),{taskId:i,path:f,documentId:E,content:q,format:S,append:T,comment:P}=r,j=!!E,R=!!f
|
|
2607
|
+
w.info("Writing content to "+(j?"document":"file"),{taskId:i,filePath:R?f:void 0,documentId:j?E:void 0,contentLength:"string"==typeof q?q.length:JSON.stringify(q).length,format:S,append:T,comment:P})
|
|
2608
|
+
let x,M,O,$="",D=!1,A=!1
|
|
2609
2609
|
const F=R?f:void 0
|
|
2610
2610
|
if(j){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}
|
|
2611
2611
|
throw e}if(!t.documentFileManager)throw Error("Document file manager not available")
|
|
@@ -2620,32 +2620,32 @@ R&&z&&H&&(B=await d.autoPromoteTaskStatus(i,L.status,z,H.request?.status,N,n,s,w
|
|
|
2620
2620
|
const U=await d.ensureCorrectWorkspaceContext({taskPromoted:B.taskPromoted,requestId:z,context:t,operation:"write_file",logger:w,metrics:m,metricsPrefix:_.metricsPrefix,requireRequestContext:R})
|
|
2621
2621
|
if(!U.success){if(U.isLockConflict)return{content:[{type:"text",text:"\u274c "+U.error}],isError:!0}
|
|
2622
2622
|
throw Error(U.error)}if(U.switched&&w.info("Workspace context successfully established",{requestId:z,branchName:U.branchName,operation:"write_file"}),R&&F){const e=d.validateAndNormalizePath(F,t)
|
|
2623
|
-
|
|
2624
|
-
try{await c.default.access(
|
|
2623
|
+
x=e.normalizedPath,M=e.fullPath,$=M
|
|
2624
|
+
try{await c.default.access(M),A=!0}catch{A=!1,D=!0}w.debug("Path validated with correct workspace context",{rawPath:F,normalizedPath:x,fullPath:M,workspaceBasePath:t.workspaceManager?.getCurrentContext().basePath})}if(j&&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}
|
|
2625
2625
|
throw e}C=d.FileOperationPhase.RECORD_CREATION,m.incrementCounter("write_file_phase",1,{phase:C})
|
|
2626
|
-
const{toolRecordId:G}=await d.createFileOperationRecords(i,z,t.projectId,_.recordType,N,{operationType:j?"document":"file",documentId:j?E:void 0,documentFilename:O,filePath:R?
|
|
2626
|
+
const{toolRecordId:G}=await d.createFileOperationRecords(i,z,t.projectId,_.recordType,N,{operationType:j?"document":"file",documentId:j?E:void 0,documentFilename:O,filePath:R?x:void 0,contentLength:"string"==typeof q?q.length:JSON.stringify(q).length,format:S||"text",append:T||!1,wasFileCreated:!A,userComment:P},n,o,w,m,_.metricsPrefix,y)
|
|
2627
2627
|
let W
|
|
2628
2628
|
if(b=G,v=G,C=_.fileOperationPhase,m.incrementCounter("write_file_phase",1,{phase:C}),"json"===S)if("string"==typeof q)try{JSON.parse(q),W=q}catch(e){throw new u.ValidationError("Content is not valid JSON")}else W=JSON.stringify(q,null,2)
|
|
2629
2629
|
else W="string"==typeof q?q:JSON.stringify(q,null,2)
|
|
2630
2630
|
let V=W
|
|
2631
2631
|
if(R&&t.git)try{w.debug("[WRITE-FILE] Checking for user changes before write operation")
|
|
2632
2632
|
const e=await(0,g.commitUserChangesBeforeToolOperation)(t.git,"write_file",{requestId:t.workspaceManager?.getCurrentContext()?.requestId,taskId:i},w,m)
|
|
2633
|
-
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:
|
|
2634
|
-
if(w.debug("[WRITE-FILE] Proceeding with file write operation",{targetPath:$}),
|
|
2635
|
-
if(await c.default.mkdir(J,{recursive:!0}),await c.default.writeFile($,V,"utf8"),w.info("Content written successfully",{path:R?
|
|
2633
|
+
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:x,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:x,error:e instanceof Error?e.message:e+""})}if(!$)throw Error("Target path not properly initialized")
|
|
2634
|
+
if(w.debug("[WRITE-FILE] Proceeding with file write operation",{targetPath:$}),T&&A)try{V=await c.default.readFile($,"utf8")+W}catch(e){w.warn("Failed to read existing content for append",{error:e})}const J=a.default.dirname($)
|
|
2635
|
+
if(await c.default.mkdir(J,{recursive:!0}),await c.default.writeFile($,V,"utf8"),w.info("Content written successfully",{path:R?x:"document:"+E,finalLength:V.length,append:T,wasCreated:D}),j){t.documentFileManager.markForSync(E)
|
|
2636
2636
|
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
|
|
2637
2637
|
if(R){if(C=d.FileOperationPhase.GIT_COMMIT,m.incrementCounter("write_file_phase",1,{phase:C}),t.workspaceManager){const e=t.workspaceManager.getCurrentContext()
|
|
2638
|
-
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":
|
|
2639
|
-
K=r.commitHash,Q=r.previousCommitHash,w.info("Changes committed to git via shared utility",{path:
|
|
2638
|
+
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"} ${x} (${v})`,r=await d.commitToGit(i,x,v,v,e,t,w,m,_.metricsPrefix)
|
|
2639
|
+
K=r.commitHash,Q=r.previousCommitHash,w.info("Changes committed to git via shared utility",{path:x,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:R?x:"document:"+E,status:"completed",finalContentLength:V.length,wasFileCreated:D,wasAppended:T&&A,operationType:j?"document":"file",processingTime:Date.now()-I,userComment:P,...R&&K&&{commitHash:K,previousCommitHash:Q||void 0}},note:"Write operation completed successfully"+(j?" (document synced)":" (committed to git)")})}catch(e){w.warn("Failed to update tool record",{recordError:e})}let Z=`**${D?"Created":T?"Appended to":"Updated"} ${j?`document ${E}${O?` (${O})`:""}`:"file "+x}**\n`
|
|
2640
2640
|
Z+=`**Content Length:** ${V.length} characters\n`,R&&Y&&(Z+=`**Branch:** ${Y}\n`),U.lockAcquired&&U.lockedRequestId&&(Z+=`**Locked request:** ${U.lockedRequestId}\n`),R&&K&&(Z+=`**Commit Hash:** ${K.substring(0,8)}\n`,Q&&(Z+=`**Previous Commit:** ${Q.substring(0,8)}\n`)),v&&(Z+=`[RECORD:${v}]\n`),j&&(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}\`.`)
|
|
2641
2641
|
const X=Date.now()
|
|
2642
|
-
return w.info("Write operation completed successfully",{duration:X-I,path:R?
|
|
2642
|
+
return w.info("Write operation completed successfully",{duration:X-I,path:R?x:"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()-I
|
|
2643
2643
|
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}}}
|
|
2644
2644
|
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){"use strict"
|
|
2645
2645
|
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){"use strict"
|
|
2646
2646
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.def=void 0
|
|
2647
2647
|
const r=t(6183),n=t(4648)
|
|
2648
|
-
exports.def={name:"request_operations",description:"Perform operations on existing requests.\n\nOperations:\n\u2022 complete - Begin completion: provide summary, get criteria keys for verification\n\u2022 verify-criteria - Verify acceptance criteria with evidence per key (triggers merge when all verified)\n\u2022 finalize - Approve and merge a request that is ready for review\n\u2022 approve - Approve a pending request so work can begin\n\u2022 revert - Completely revert a completed request, undoing all changes\n\u2022 get-info - Get comprehensive request information\n\u2022 list - List and filter requests\n\nCompletion is two-phase: first call complete with a summary, then call verify-criteria with evidence for each criterion key.\n\nNote: To create a new request, use the separate create-request tool.",schema:r.RequestOperationsSchema,annotations:{title:"Request Operations",readOnlyHint:!1,destructiveHint:!0,idempotentHint:!1},handler(e,t){return(0,n.handleRequestOperations)(e,t.context,t.apiClient,t.logger,t.metrics,t.mcpServer)}}},4192(e,exports,t){"use strict"
|
|
2648
|
+
exports.def={name:"request_operations",description:"Perform operations on existing requests.\n\nOperations:\n\u2022 complete - Begin completion: provide summary, get criteria keys for verification\n\u2022 verify-criteria - Verify acceptance criteria with evidence per key (triggers merge when all verified)\n\u2022 finalize - Approve and merge a request that is ready for review\n\u2022 approve - Approve a pending request so work can begin\n\u2022 revert - Completely revert a completed request, undoing all changes\n\u2022 get-info - Get comprehensive request information\n\u2022 list - List and filter requests\n\u2022 delete-empty - Delete a request that has no tasks (safe cleanup for mistaken or obsolete requests)\n\nCompletion is two-phase: first call complete with a summary, then call verify-criteria with evidence for each criterion key.\n\nNote: To create a new request, use the separate create-request tool.",schema:r.RequestOperationsSchema,annotations:{title:"Request Operations",readOnlyHint:!1,destructiveHint:!0,idempotentHint:!1},handler(e,t){return(0,n.handleRequestOperations)(e,t.context,t.apiClient,t.logger,t.metrics,t.mcpServer)}}},4192(e,exports,t){"use strict"
|
|
2649
2649
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.BaseApiClient=void 0
|
|
2650
2650
|
const r=t(7163)
|
|
2651
2651
|
exports.BaseApiClient=class{constructor(e,t,n,o,s){this.failureCount=0,this.circuitState="closed",this.circuitResetTimeout=null,this.baseUrl=e,this.logger=t,this.metrics=n,this.authToken=o,this.options={retryAttempts:3,retryDelay:1e3,timeout:1e4,circuitBreakerThreshold:5,circuitBreakerResetTime:3e4,...s},this.logger.debug("BaseApiClient constructor options:",{providedOptions:s?JSON.stringify(s):"undefined",mergedOptions:JSON.stringify(this.options)})
|
|
@@ -2842,21 +2842,23 @@ return p.error("Recovery operation failed",{error:e instanceof Error?e.stack:e+"
|
|
|
2842
2842
|
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){"use strict"
|
|
2843
2843
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleRequestOperations=async function(e,t,u,h,g,p){const f=h.child({tool:"request_operations"})
|
|
2844
2844
|
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)
|
|
2845
|
-
const
|
|
2846
|
-
switch(f.info("Processing request operation",{requestId:
|
|
2847
|
-
const e={requestId:
|
|
2848
|
-
return await(0,n.handleCompleteRequest)(e,t,u,h,g,p)}case"merge":return f.info("Routing to merge handler"),await(0,l.handleMergeRequest)({requestId:
|
|
2845
|
+
const m=r.RequestOperationsSchema.parse(e),{requestId:y,operation:w}=m
|
|
2846
|
+
switch(f.info("Processing request operation",{requestId:y,operation:w}),w){case"complete":{f.info("Routing to complete-request handler")
|
|
2847
|
+
const e={requestId:y,summary:m.complete.summary}
|
|
2848
|
+
return await(0,n.handleCompleteRequest)(e,t,u,h,g,p)}case"merge":return f.info("Routing to merge handler"),await(0,l.handleMergeRequest)({requestId:y,verifications:m.merge?.verifications||[]},t,u,h,g,p)
|
|
2849
2849
|
case"approve":{f.info("Routing to approve-request handler")
|
|
2850
|
-
const e={requestId:
|
|
2850
|
+
const e={requestId:y}
|
|
2851
2851
|
return await(0,c.handleApproveRequest)(e,t,u,h,g,p)}case"revert":{f.info("Routing to revert-request handler")
|
|
2852
|
-
const e={requestId:
|
|
2852
|
+
const e={requestId:y,reason:m.revert.reason,confirmDestructive:m.revert.confirmDestructive}
|
|
2853
2853
|
return await(0,o.handleRevertRequest)(e,t,u,h,g)}case"get-info":{f.info("Routing to get-request-information handler")
|
|
2854
|
-
const e={requestId:
|
|
2854
|
+
const e={requestId:y}
|
|
2855
2855
|
return await(0,s.handleGetRequestInformation)(e,t,u,h,g)}case"list":{f.info("Routing to list-requests handler")
|
|
2856
|
-
const e={filters:
|
|
2856
|
+
const e={filters:m.list?.filters}
|
|
2857
2857
|
return await(0,i.handleListRequests)(e,t,u,h,g)}case"search":{f.info("Routing to search-requests handler")
|
|
2858
|
-
const e={search:
|
|
2859
|
-
return await(0,a.handleSearchRequests)(e,t,u,h,g)}
|
|
2858
|
+
const e={search:m.search}
|
|
2859
|
+
return await(0,a.handleSearchRequests)(e,t,u,h,g)}case"delete-empty":if(f.info("Routing to delete-empty handler"),!y)return{content:[{type:"text",text:"\u274c **Request Operations Failed:** requestId is required for delete-empty"}],isError:!0}
|
|
2860
|
+
try{const e=u.getProxyClient(),r=await e.proxyGet(`/api/projects/${t.projectId}/tasks`,{requestLocalId:y,limit:1}),n=r?.data||r||[]
|
|
2861
|
+
return(Array.isArray(n)?n.length:0)>0?{content:[{type:"text",text:`\u274c Cannot delete ${y}: it has tasks. Only empty requests (no tasks created) can be deleted.`}],isError:!0}:(await e.proxyDelete(`/api/projects/${t.projectId}/requests/${y}`),f.info("Empty request deleted",{requestId:y}),{content:[{type:"text",text:`\u2705 Request ${y} deleted (had no tasks).`}]})}catch(e){return{content:[{type:"text",text:"\u274c **Failed to delete request:** "+(0,d.getErrorMessage)(e)}],isError:!0}}default:{const e="Unknown operation type: "+w
|
|
2860
2862
|
return f.error(e),{content:[{type:"text",text:"\u274c **Request Operations Failed:** "+e}],isError:!0}}}}catch(e){return f.error("Request operations failed",{error:e instanceof Error?e.stack:e+""}),g.incrementCounter("request_operations_errors",1),{content:[{type:"text",text:"\u274c **Request Operations Failed:** "+(0,d.getErrorMessage)(e)}],isError:!0}}}
|
|
2861
2863
|
const r=t(6183),n=t(5715),o=t(6416),s=t(5434),i=t(8037),a=t(233),c=t(1537),l=t(4306),d=t(8824)},4710(e,exports,t){"use strict"
|
|
2862
2864
|
var r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
@@ -3346,43 +3348,43 @@ else{if(!E)throw Error("Either paths or operations must be specified")
|
|
|
3346
3348
|
S=E.map((e=>{if(e.path)return{type:"file",target:e.path}
|
|
3347
3349
|
if(e.documentId)return{type:"document",target:e.documentId}
|
|
3348
3350
|
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")
|
|
3349
|
-
const
|
|
3350
|
-
i.info("Starting mixed file and document deletion operation",{taskId:C,totalOperations:S.length,fileOperations:
|
|
3351
|
+
const T=S.filter((e=>"file"===e.type)),P=S.filter((e=>"document"===e.type)),j=S.length
|
|
3352
|
+
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,I.metricsPrefix)
|
|
3351
3353
|
const R=t.getCurrentBranchContext?await t.getCurrentBranchContext():{branch:null,requestId:null,isMain:!0}
|
|
3352
3354
|
i.info("Initial branch context",{initialBranch:R.branch,initialRequestId:R.requestId,isMain:R.isMain})
|
|
3353
|
-
const
|
|
3354
|
-
for(const e of
|
|
3355
|
-
|
|
3356
|
-
const x
|
|
3357
|
-
A.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:A.newTaskStatus,totalOperations:S.length,fileOperations:
|
|
3355
|
+
const x=[]
|
|
3356
|
+
for(const e of T){const{normalizedPath:r,fullPath:n}=l.validateAndNormalizePath(e.target,t)
|
|
3357
|
+
x.push({normalized:r,full:n})}k=l.FileOperationPhase.TASK_VALIDATION,o.incrementCounter("delete_files_phase",1,{phase:k})
|
|
3358
|
+
const M=x.length>0?x[0].normalized:"document_operations",O=await l.validateTaskId(C,M,n,i,o,I.metricsPrefix),$=O?.requestId,D=await l.validateWorkItemStates(C,M,n,b,t,i,o,I.metricsPrefix),A=await l.autoPromoteTaskStatus(C,O.status,$,D.request?.status,M,n,b,i,o,I.metricsPrefix)
|
|
3359
|
+
A.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:A.newTaskStatus,totalOperations:S.length,fileOperations:T.length,documentOperations:P.length}),A.requestPromoted&&i.info(`Auto-promoted request ${$} to in_progress for file operations`,{requestId:$,previousStatus:D.request?.status,newStatus:A.newRequestStatus,triggeringTaskId:C})
|
|
3358
3360
|
const F=await l.ensureCorrectWorkspaceContext({taskPromoted:A.taskPromoted,requestId:$,context:t,operation:"delete-files",logger:i,metrics:o,metricsPrefix:I.metricsPrefix})
|
|
3359
3361
|
if(!F.success){if(F.isLockConflict)return{content:[{type:"text",text:"\u274c "+F.error}],isError:!0}
|
|
3360
3362
|
throw Error(F.error)}let N={hadUserMods:!1,userModsCommitHash:void 0}
|
|
3361
3363
|
if(t.git)try{i.debug("[DELETE-FILES] Checking for user changes before mixed delete operations")
|
|
3362
3364
|
const e=await(0,h.commitUserChangesBeforeToolOperation)(t.git,"delete-files",{requestId:$,taskId:C,workspaceManager:t.workspaceManager},i,o)
|
|
3363
|
-
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:
|
|
3364
|
-
const{toolRecordId:L,localToolRecordId:z}=await l.createFileOperationRecords(C,$,t.projectId,I.recordType,
|
|
3365
|
+
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})
|
|
3366
|
+
const{toolRecordId:L,localToolRecordId:z}=await l.createFileOperationRecords(C,$,t.projectId,I.recordType,M,{totalOperations:S.length,fileOperations:T.length,documentOperations:P.length,filePaths:x.map((e=>e.normalized)),documentIds:P.map((e=>e.target)),userComment:q,hadUserMods:N.hadUserMods,userModsCommitHash:N.userModsCommitHash},n,u,i,o,I.metricsPrefix,s)
|
|
3365
3367
|
y=L,w=L,k=I.fileOperationPhase,o.incrementCounter("delete_files_phase",1,{phase:k})
|
|
3366
3368
|
const H=[]
|
|
3367
3369
|
let B=0
|
|
3368
|
-
|
|
3369
|
-
for(let e=0;e<
|
|
3370
|
+
P.length>0&&r.setProjectId(t.projectId)
|
|
3371
|
+
for(let e=0;e<x.length;e++){const t=x[e],r={type:"file",path:t.normalized,success:!1,replacements:[],successfulReplacements:0,failedReplacements:0}
|
|
3370
3372
|
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)
|
|
3371
|
-
await a.default.unlink(t.full),r.success=!0,B++,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})}H.push(r)}const U=
|
|
3372
|
-
for(const e of
|
|
3373
|
+
await a.default.unlink(t.full),r.success=!0,B++,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})}H.push(r)}const U=P.length>0?r.getDocumentClient():null
|
|
3374
|
+
for(const e of P){const t=e.target,n={type:"document",documentId:t,success:!1,replacements:[],successfulReplacements:0,failedReplacements:0}
|
|
3373
3375
|
try{let e
|
|
3374
3376
|
try{if(e=await U.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,b,i,o,"delete-document")}catch(e){if(e instanceof d.ValidationError)throw Error(e.message)
|
|
3375
3377
|
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)
|
|
3376
3378
|
throw e}}catch(e){throw Error(`Document not found or validation failed: ${t}. ${(0,f.getErrorMessage)(e)}`)}const s=await U.archiveDocument(t)
|
|
3377
3379
|
n.success=!0,n.filename=s.filename,B++,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})}H.push(n)}const G=Date.now()-m
|
|
3378
|
-
o.recordValue("delete_files_time",G),o.incrementCounter("delete_files_operations_total",j),o.incrementCounter("delete_files_operations_success",B),o.incrementCounter("delete_files_operations_failed",j-B),o.incrementCounter("delete_files_file_operations",
|
|
3380
|
+
o.recordValue("delete_files_time",G),o.incrementCounter("delete_files_operations_total",j),o.incrementCounter("delete_files_operations_success",B),o.incrementCounter("delete_files_operations_failed",j-B),o.incrementCounter("delete_files_file_operations",T.length),o.incrementCounter("delete_files_document_operations",P.length),B===j?o.incrementCounter("delete_files_success",1):B>0?o.incrementCounter("delete_files_partial_success",1):o.incrementCounter("delete_files_total_failure",1)
|
|
3379
3381
|
let W=null
|
|
3380
3382
|
if(B>0){k=l.FileOperationPhase.GIT_COMMIT,o.incrementCounter("delete_files_phase",1,{phase:k})
|
|
3381
3383
|
const e=H.filter((e=>e.success)),r=e.filter((e=>"file"===e.type)).length,n=e.filter((e=>"document"===e.type)).length
|
|
3382
3384
|
let s
|
|
3383
|
-
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}`,W=await l.commitToGit(C,
|
|
3385
|
+
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}`,W=await l.commitToGit(C,M,L,z,s,t,i,o,I.metricsPrefix)}k=l.FileOperationPhase.RECORD_UPDATE_SUCCESS,o.incrementCounter("delete_files_phase",1,{phase:k})
|
|
3384
3386
|
const V=H.filter((e=>e.success)),J=H.filter((e=>!e.success))
|
|
3385
|
-
await l.updateFileOperationRecords(C,y,w,
|
|
3387
|
+
await l.updateFileOperationRecords(C,y,w,M,I.recordType,B===j?`Successfully deleted all ${j} operations`:`Deleted ${B}/${j} operations successfully`,{status:B===j?"completed":"partial_success",commitHash:W?.commitHash,previousCommitHash:W?.previousCommitHash,totalOperations:j,fileOperations:T.length,documentOperations:P.length,successCount:B,failureCount:j-B,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},B===j?`Successfully deleted all ${j} operations`:`Deleted ${B}/${j} operations successfully`,n,u,i,o,I.metricsPrefix)
|
|
3386
3388
|
const K=t.getCurrentBranchContext?await t.getCurrentBranchContext():{branch:null,requestId:null,isMain:!0}
|
|
3387
3389
|
let Y=""
|
|
3388
3390
|
if(B===j){const e=V.filter((e=>"file"===e.type)).length,t=V.filter((e=>"document"===e.type)).length
|
|
@@ -3466,7 +3468,7 @@ return"delegate"===e.operation?r&&!n&&!t:"follow-up"===e.operation?n&&!r&&t:"che
|
|
|
3466
3468
|
return"request"===e.operation?t&&!r:"check-status"===e.operation?!t&&r:"list"===e.operation&&!t&&!r}),{message:"Invalid operation data: request requires request object, check-status requires sessionId"}),exports.SwitchToRequestBranchSchema=r.z.object({requestId:s}),exports.InsertLinesSchema=r.z.object({taskId:o,operations:r.z.array(r.z.object({path:r.z.string().optional(),documentId:i.optional(),insertions:r.z.array(r.z.object({type:r.z.enum(["before","after","between"]),line:r.z.number().optional(),afterLine:r.z.number().optional(),beforeLine:r.z.number().optional(),content:r.z.union([r.z.string(),r.z.array(r.z.string())])}).refine((e=>"between"===e.type?void 0!==e.afterLine&&void 0!==e.beforeLine&&void 0===e.line:void 0!==e.line&&void 0===e.afterLine&&void 0===e.beforeLine),{message:"Invalid line parameters"}))}).refine((e=>e.path&&!e.documentId||!e.path&&e.documentId),{message:"path or documentId required"})),comment:r.z.string()}),exports.ReplaceLinesSchema=r.z.object({taskId:o,operations:r.z.array(r.z.object({path:r.z.string().optional(),documentId:i.optional(),replacements:r.z.array(r.z.object({lines:r.z.string(),content:r.z.union([r.z.string(),r.z.array(r.z.string())])}))}).refine((e=>e.path&&!e.documentId||!e.path&&e.documentId),{message:"path or documentId required"})),comment:r.z.string()}),exports.CreateDocumentSchema=r.z.object({requestId:s.optional(),filename:r.z.string().refine((e=>e.toLowerCase().endsWith(".md")),{message:"Filename must end with .md extension"}),content:r.z.string(),type:r.z.enum(["Report","Documentation","Plan","Other"],{errorMap(){return{message:"Document type must be one of: Report, Documentation, Plan, Other"}}}),comment:r.z.string()}),exports.SearchDocumentsSchema=r.z.object({query:r.z.string(),type:r.z.enum(["Report","Documentation","Plan","Other"]).optional(),requestId:s.optional(),includeArchived:r.z.boolean().default(!1),maxResults:r.z.number().min(1).max(100).default(20),dateFrom:r.z.string().optional(),dateTo:r.z.string().optional(),searchIn:r.z.enum(["content","filename","both"]).default("both")}),exports.DocumentOperationsSchema=r.z.object({operation:r.z.enum(["create","search","create-snapshot","get-history","get-version","restore-version","list-annotations","create-annotation","reply-to-annotation","resolve-annotation"]),documentId:i.optional(),requestId:s.optional(),filename:r.z.string().optional(),content:r.z.string().optional(),type:r.z.enum(["Report","Documentation","Plan","Other"]).optional(),comment:r.z.string().optional(),query:r.z.string().optional(),includeArchived:r.z.boolean().default(!1),maxResults:r.z.number().min(1).max(100).default(20),dateFrom:r.z.string().optional(),dateTo:r.z.string().optional(),searchIn:r.z.enum(["content","filename","both"]).default("both"),versionLabel:r.z.string().optional(),changeSummary:r.z.string().optional(),versionNumber:r.z.number().int().min(1).optional(),selectedText:r.z.string().optional(),prefixContext:r.z.string().optional(),suffixContext:r.z.string().optional(),lineHint:r.z.number().int().optional(),body:r.z.string().optional(),annotationId:r.z.string().optional()}).superRefine(((e,t)=>{const r=e.operation;["create-snapshot","get-history","get-version","restore-version","list-annotations","create-annotation","reply-to-annotation","resolve-annotation"].includes(r)&&!e.documentId&&t.addIssue({code:"custom",message:`documentId is required for '${r}'. Example: { "operation": "${r}", "documentId": "doc000001" }`}),"create"===r&&(e.filename?e.filename.toLowerCase().endsWith(".md")||t.addIssue({code:"custom",message:"Filename must end with .md extension"}):t.addIssue({code:"custom",message:"filename is required for create (must end with .md)"}),e.content||t.addIssue({code:"custom",message:"content is required for create"}),e.type||t.addIssue({code:"custom",message:"type is required for create (Report, Documentation, Plan, or Other)"}),e.comment||t.addIssue({code:"custom",message:"comment is required for create"})),"search"!==r||e.query||t.addIssue({code:"custom",message:'query is required for search. Example: { "operation": "search", "query": "search term" }'}),"get-version"!==r&&"restore-version"!==r||e.versionNumber||t.addIssue({code:"custom",message:`versionNumber is required for '${r}'`}),"create-annotation"===r&&(e.selectedText||t.addIssue({code:"custom",message:"selectedText is required for create-annotation"}),e.body||t.addIssue({code:"custom",message:"body is required for create-annotation"})),"reply-to-annotation"===r&&(e.annotationId||t.addIssue({code:"custom",message:"annotationId is required for reply-to-annotation"}),e.body||t.addIssue({code:"custom",message:"body is required for reply-to-annotation"})),"resolve-annotation"!==r||e.annotationId||t.addIssue({code:"custom",message:"annotationId is required for resolve-annotation"})}))
|
|
3467
3469
|
const c=r.z.string().refine((e=>!!e&&(/^doc_[0-9A-Z]{26}$/i.test(e)||/^plan\d{6}$/.test(e))),{message:"Plan ID must match format: doc_[26 alphanumeric] (ULID) or plan###### (local ID)"})
|
|
3468
3470
|
exports.PlanReadSchema=r.z.object({operation:r.z.enum(["get","get-active","list","get-history","get-requests"]),planId:c.optional(),searchQuery:r.z.string().optional(),limit:r.z.number().min(1).max(100).default(20),offset:r.z.number().min(0).default(0),sortBy:r.z.enum(["createdAt","updatedAt","filename"]).default("updatedAt"),sortDirection:r.z.enum(["ASC","DESC"]).default("DESC")}).superRefine(((e,t)=>{["get","get-history","get-requests"].includes(e.operation)&&!e.planId&&t.addIssue({code:"custom",message:`planId is required for '${e.operation}'. Example: { "operation": "${e.operation}", "planId": "plan000001" }`})})),exports.PlanWriteSchema=r.z.object({operation:r.z.enum(["update","append","replace","create-snapshot","restore","set-active"]),planId:c,content:r.z.string().optional(),name:r.z.string().optional().describe("Optional new name for the plan"),old:r.z.string().optional().describe("Text to find in the plan (for replace)"),new:r.z.string().optional().describe("Replacement text (for replace)"),versionLabel:r.z.string().optional(),changeSummary:r.z.string().optional(),versionNumber:r.z.number().int().min(1).optional()}).superRefine(((e,t)=>{const r=e.operation
|
|
3469
|
-
"update"!==r&&"append"!==r||e.content||t.addIssue({code:"custom",message:`content is required for '${r}'. Example: { "operation": "${r}", "planId": "plan000001", "content": "..." }`}),"replace"===r&&(e.old||t.addIssue({code:"custom",message:'old is required for replace. Example: { "operation": "replace", "planId": "plan000001", "old": "find this", "new": "replace with" }'}),void 0===e.new&&t.addIssue({code:"custom",message:"new is required for replace"})),"restore"!==r||e.versionNumber||t.addIssue({code:"custom",message:'versionNumber is required for restore. Example: { "operation": "restore", "planId": "plan000001", "versionNumber": 1 }'})})),exports.SwitchToMainBranchSchema=r.z.object({}),exports.SwitchToBranchSchema=r.z.object({branch:r.z.string().optional(),password:r.z.string().optional()}),exports.RevertRequestSchema=r.z.object({requestId:s,reason:r.z.string(),confirmDestructive:r.z.boolean().optional()}),exports.ModifyFileSchema=r.z.object({taskId:o,operations:r.z.array(r.z.object({path:r.z.string().optional(),documentId:i.optional(),operationType:r.z.enum(["replace-string","insert-lines","replace-lines","delete-string","delete-lines"]),replaceString:r.z.object({replacements:r.z.array(r.z.object({old_str:r.z.string(),new_str:r.z.string()})),mode:r.z.enum(["unique","all"]).optional()}).optional(),insertLines:r.z.object({insertions:r.z.array(r.z.object({type:r.z.enum(["before","after","between"]),line:r.z.number().optional(),afterLine:r.z.number().optional(),beforeLine:r.z.number().optional(),content:r.z.union([r.z.string(),r.z.array(r.z.string())])}).refine((e=>"between"===e.type?void 0!==e.afterLine&&void 0!==e.beforeLine&&void 0===e.line:void 0!==e.line&&void 0===e.afterLine&&void 0===e.beforeLine),{message:"Invalid line parameters"}))}).optional(),replaceLines:r.z.object({replacements:r.z.array(r.z.object({lines:r.z.string(),content:r.z.union([r.z.string(),r.z.array(r.z.string())])}))}).optional(),deleteString:r.z.object({patterns:r.z.array(r.z.string()),mode:r.z.enum(["all","unique"]).optional()}).optional(),deleteLines:r.z.object({lines:r.z.string()}).optional()}).refine((e=>e.path&&!e.documentId||!e.path&&e.documentId),{message:"path or documentId required"}).refine((e=>"replace-string"===e.operationType?e.replaceString&&!e.insertLines&&!e.replaceLines&&!e.deleteString&&!e.deleteLines:"insert-lines"===e.operationType?e.insertLines&&!e.replaceString&&!e.replaceLines&&!e.deleteString&&!e.deleteLines:"replace-lines"===e.operationType?e.replaceLines&&!e.replaceString&&!e.insertLines&&!e.deleteString&&!e.deleteLines:"delete-string"===e.operationType?e.deleteString&&!e.replaceString&&!e.insertLines&&!e.replaceLines&&!e.deleteLines:"delete-lines"===e.operationType&&e.deleteLines&&!e.replaceString&&!e.insertLines&&!e.replaceLines&&!e.deleteString),{message:"Invalid operation data"})),comment:r.z.string()}),exports.ManageFilesSchema=r.z.object({taskId:o,operations:r.z.array(r.z.object({operationType:r.z.enum(["create-directory","move-files","delete-files","get-file-info"]),createDirectory:r.z.object({path:r.z.string()}).optional(),moveFiles:r.z.object({moves:r.z.array(r.z.object({source:r.z.string(),destination:r.z.string()}))}).optional(),deleteFiles:r.z.object({targets:r.z.array(r.z.object({path:r.z.string().optional(),documentId:i.optional()}).refine((e=>e.path&&!e.documentId||!e.path&&e.documentId),{message:"path or documentId required"}))}).optional(),getFileInfo:r.z.object({path:r.z.string()}).optional()}).refine((e=>"create-directory"===e.operationType?e.createDirectory&&!e.moveFiles&&!e.deleteFiles&&!e.getFileInfo:"move-files"===e.operationType?e.moveFiles&&!e.createDirectory&&!e.deleteFiles&&!e.getFileInfo:"delete-files"===e.operationType?e.deleteFiles&&!e.createDirectory&&!e.moveFiles&&!e.getFileInfo:"get-file-info"===e.operationType&&e.getFileInfo&&!e.createDirectory&&!e.moveFiles&&!e.deleteFiles),{message:"Invalid operation data"})),comment:r.z.string()}),exports.RequestOperationsSchema=r.z.object({requestId:s.optional(),operation:r.z.enum(["complete","merge","approve","revert","get-info","list","search"]),complete:r.z.preprocess((e=>"string"==typeof e?(()=>{try{return JSON.parse(e)}catch{return e}})():e),r.z.object({summary:r.z.string()})).optional(),merge:r.z.preprocess((e=>"string"==typeof e?(()=>{try{return JSON.parse(e)}catch{return e}})():e),r.z.object({verifications:r.z.array(r.z.object({key:r.z.string().min(2).max(4),evidence:r.z.string().min(1)})).min(1)})).optional(),revert:r.z.object({reason:r.z.string(),confirmDestructive:r.z.boolean().optional()}).optional(),list:r.z.object({filters:r.z.object({type:r.z.enum(["feature","bugfix"]).optional(),status:r.z.enum(["pending_approval","open","in_progress","ready_for_review","ready_for_merge","resolving_conflicts","completed","canceled"]).optional(),dateFrom:r.z.string().optional(),dateTo:r.z.string().optional(),limit:r.z.number().min(1).max(100).default(20),offset:r.z.number().min(0).default(0),sortBy:r.z.enum(["created","updated"]).default("updated"),sortDirection:r.z.enum(["asc","desc"]).default("desc")}).optional()}).optional(),search:r.z.object({query:r.z.string().min(1),searchIn:r.z.enum(["title","description","criteria","all"]).default("all"),filters:r.z.object({type:r.z.enum(["feature","bugfix"]).optional(),status:r.z.enum(["pending_approval","open","in_progress","ready_for_review","ready_for_merge","resolving_conflicts","completed","canceled"]).optional(),dateFrom:r.z.string().optional(),dateTo:r.z.string().optional(),limit:r.z.number().min(1).max(100).default(20),offset:r.z.number().min(0).default(0)}).optional()}).optional(),approve:r.z.object({}).optional()}).superRefine(((e,t)=>{const r=!!e.requestId,n=e.operation
|
|
3471
|
+
"update"!==r&&"append"!==r||e.content||t.addIssue({code:"custom",message:`content is required for '${r}'. Example: { "operation": "${r}", "planId": "plan000001", "content": "..." }`}),"replace"===r&&(e.old||t.addIssue({code:"custom",message:'old is required for replace. Example: { "operation": "replace", "planId": "plan000001", "old": "find this", "new": "replace with" }'}),void 0===e.new&&t.addIssue({code:"custom",message:"new is required for replace"})),"restore"!==r||e.versionNumber||t.addIssue({code:"custom",message:'versionNumber is required for restore. Example: { "operation": "restore", "planId": "plan000001", "versionNumber": 1 }'})})),exports.SwitchToMainBranchSchema=r.z.object({}),exports.SwitchToBranchSchema=r.z.object({branch:r.z.string().optional(),password:r.z.string().optional()}),exports.RevertRequestSchema=r.z.object({requestId:s,reason:r.z.string(),confirmDestructive:r.z.boolean().optional()}),exports.ModifyFileSchema=r.z.object({taskId:o,operations:r.z.array(r.z.object({path:r.z.string().optional(),documentId:i.optional(),operationType:r.z.enum(["replace-string","insert-lines","replace-lines","delete-string","delete-lines"]),replaceString:r.z.object({replacements:r.z.array(r.z.object({old_str:r.z.string(),new_str:r.z.string()})),mode:r.z.enum(["unique","all"]).optional()}).optional(),insertLines:r.z.object({insertions:r.z.array(r.z.object({type:r.z.enum(["before","after","between"]),line:r.z.number().optional(),afterLine:r.z.number().optional(),beforeLine:r.z.number().optional(),content:r.z.union([r.z.string(),r.z.array(r.z.string())])}).refine((e=>"between"===e.type?void 0!==e.afterLine&&void 0!==e.beforeLine&&void 0===e.line:void 0!==e.line&&void 0===e.afterLine&&void 0===e.beforeLine),{message:"Invalid line parameters"}))}).optional(),replaceLines:r.z.object({replacements:r.z.array(r.z.object({lines:r.z.string(),content:r.z.union([r.z.string(),r.z.array(r.z.string())])}))}).optional(),deleteString:r.z.object({patterns:r.z.array(r.z.string()),mode:r.z.enum(["all","unique"]).optional()}).optional(),deleteLines:r.z.object({lines:r.z.string()}).optional()}).refine((e=>e.path&&!e.documentId||!e.path&&e.documentId),{message:"path or documentId required"}).refine((e=>"replace-string"===e.operationType?e.replaceString&&!e.insertLines&&!e.replaceLines&&!e.deleteString&&!e.deleteLines:"insert-lines"===e.operationType?e.insertLines&&!e.replaceString&&!e.replaceLines&&!e.deleteString&&!e.deleteLines:"replace-lines"===e.operationType?e.replaceLines&&!e.replaceString&&!e.insertLines&&!e.deleteString&&!e.deleteLines:"delete-string"===e.operationType?e.deleteString&&!e.replaceString&&!e.insertLines&&!e.replaceLines&&!e.deleteLines:"delete-lines"===e.operationType&&e.deleteLines&&!e.replaceString&&!e.insertLines&&!e.replaceLines&&!e.deleteString),{message:"Invalid operation data"})),comment:r.z.string()}),exports.ManageFilesSchema=r.z.object({taskId:o,operations:r.z.array(r.z.object({operationType:r.z.enum(["create-directory","move-files","delete-files","get-file-info"]),createDirectory:r.z.object({path:r.z.string()}).optional(),moveFiles:r.z.object({moves:r.z.array(r.z.object({source:r.z.string(),destination:r.z.string()}))}).optional(),deleteFiles:r.z.object({targets:r.z.array(r.z.object({path:r.z.string().optional(),documentId:i.optional()}).refine((e=>e.path&&!e.documentId||!e.path&&e.documentId),{message:"path or documentId required"}))}).optional(),getFileInfo:r.z.object({path:r.z.string()}).optional()}).refine((e=>"create-directory"===e.operationType?e.createDirectory&&!e.moveFiles&&!e.deleteFiles&&!e.getFileInfo:"move-files"===e.operationType?e.moveFiles&&!e.createDirectory&&!e.deleteFiles&&!e.getFileInfo:"delete-files"===e.operationType?e.deleteFiles&&!e.createDirectory&&!e.moveFiles&&!e.getFileInfo:"get-file-info"===e.operationType&&e.getFileInfo&&!e.createDirectory&&!e.moveFiles&&!e.deleteFiles),{message:"Invalid operation data"})),comment:r.z.string()}),exports.RequestOperationsSchema=r.z.object({requestId:s.optional(),operation:r.z.enum(["complete","merge","approve","revert","get-info","list","search","delete-empty"]),complete:r.z.preprocess((e=>"string"==typeof e?(()=>{try{return JSON.parse(e)}catch{return e}})():e),r.z.object({summary:r.z.string()})).optional(),merge:r.z.preprocess((e=>"string"==typeof e?(()=>{try{return JSON.parse(e)}catch{return e}})():e),r.z.object({verifications:r.z.array(r.z.object({key:r.z.string().min(2).max(4),evidence:r.z.string().min(1)})).min(1)})).optional(),revert:r.z.object({reason:r.z.string(),confirmDestructive:r.z.boolean().optional()}).optional(),list:r.z.object({filters:r.z.object({type:r.z.enum(["feature","bugfix"]).optional(),status:r.z.enum(["pending_approval","open","in_progress","ready_for_review","ready_for_merge","resolving_conflicts","completed","canceled"]).optional(),dateFrom:r.z.string().optional(),dateTo:r.z.string().optional(),limit:r.z.number().min(1).max(100).default(20),offset:r.z.number().min(0).default(0),sortBy:r.z.enum(["created","updated"]).default("updated"),sortDirection:r.z.enum(["asc","desc"]).default("desc")}).optional()}).optional(),search:r.z.object({query:r.z.string().min(1),searchIn:r.z.enum(["title","description","criteria","all"]).default("all"),filters:r.z.object({type:r.z.enum(["feature","bugfix"]).optional(),status:r.z.enum(["pending_approval","open","in_progress","ready_for_review","ready_for_merge","resolving_conflicts","completed","canceled"]).optional(),dateFrom:r.z.string().optional(),dateTo:r.z.string().optional(),limit:r.z.number().min(1).max(100).default(20),offset:r.z.number().min(0).default(0)}).optional()}).optional(),approve:r.z.object({}).optional()}).superRefine(((e,t)=>{const r=!!e.requestId,n=e.operation
|
|
3470
3472
|
if(["complete","merge","approve","revert","get-info"].includes(n)&&!r)return void t.addIssue({code:"custom",message:`requestId is required for '${n}' operation`})
|
|
3471
3473
|
const o={complete:{field:"complete",hint:'Provide: { complete: { summary: "..." } }'},merge:{field:"merge",hint:'Provide: { merge: { verifications: [{key: "1a", evidence: "..."}] } }'},revert:{field:"revert",hint:'Provide: { revert: { reason: "..." } }'},search:{field:"search",hint:'Provide: { search: { query: "..." } }'}}[n]
|
|
3472
3474
|
o&&!e[o.field]&&t.addIssue({code:"custom",message:`'${n}' operation requires '${o.field}' data. ${o.hint}`})})),exports.QuickWriteSchema=r.z.object({title:r.z.string().min(1,"Title is required"),description:r.z.string().min(1,"Description is required"),path:r.z.string().optional(),documentId:i.optional(),content:r.z.union([r.z.string(),r.z.record(r.z.any()),r.z.array(r.z.unknown())]),format:r.z.enum(["text","json"]).optional(),append:r.z.boolean().optional()}),exports.QuickReplaceSchema=r.z.object({title:r.z.string().min(1,"Title is required"),description:r.z.string().min(1,"Description is required"),operations:r.z.array(r.z.object({path:r.z.string().optional(),documentId:i.optional(),replacements:r.z.array(r.z.object({old:r.z.string().min(1),new:r.z.string(),match_mode:r.z.enum(["unique","all"]).optional()})).min(1),fuzzy_match:r.z.boolean().optional()})).min(1),fuzzy_match:r.z.boolean().optional(),comment:r.z.string().min(1,"Comment describing the change is required")}),exports.QuickManageSchema=r.z.object({title:r.z.string().min(1,"Title is required"),description:r.z.string().min(1,"Description is required"),operations:r.z.array(r.z.object({operationType:r.z.enum(["create-directory","move-files","delete-files"]),createDirectory:r.z.object({path:r.z.string()}).optional(),moveFiles:r.z.object({moves:r.z.array(r.z.object({source:r.z.string(),destination:r.z.string()}))}).optional(),deleteFiles:r.z.object({targets:r.z.array(r.z.object({path:r.z.string().optional(),documentId:i.optional()}))}).optional()})).min(1)}),exports.GenerateRequestJournalSchema=r.z.object({requestId:r.z.string().regex(/^req[_\d].+$/,"Invalid request ID format. Expected format: req_[26 chars] or req######")}),exports.MetaWorkflowListSchema=r.z.object({}),exports.MetaWorkflowGetSchema=r.z.object({workflowId:r.z.string().describe("Workflow ID to retrieve")}),exports.MetaWorkflowCreateSchema=r.z.object({name:r.z.string().min(1).describe("Unique name for the workflow"),shortName:r.z.string().min(1).max(10).describe("Short display name (required, max 10 chars)"),description:r.z.string().optional().describe("Description of what the workflow does"),documentation:r.z.string().optional().describe("Detailed documentation"),defaultAgent:r.z.string().optional().describe("Default agent template to use"),completionMode:r.z.enum(["auto-merge","auto-test-then-merge","manual-review"]).optional().describe("Request completion behavior: auto-merge (default), auto-test-then-merge, or manual-review"),approvalMode:r.z.enum(["none","require-approval"]).optional().describe("Pre-work approval: none (default) or require-approval")}),exports.MetaWorkflowUpdateSchema=r.z.object({workflowId:r.z.string().describe("Workflow ID to update"),name:r.z.string().min(1).optional().describe("New name"),shortName:r.z.string().max(10).optional().describe("New short name (max 10 chars)"),description:r.z.string().optional().describe("New description"),documentation:r.z.string().optional().describe("New documentation"),defaultAgent:r.z.string().optional().describe("New default agent"),completionMode:r.z.enum(["auto-merge","auto-test-then-merge","manual-review"]).optional().describe("Request completion behavior"),approvalMode:r.z.enum(["none","require-approval"]).optional().describe("Pre-work approval: none (default) or require-approval")}),exports.MetaRecipeListSchema=r.z.object({}),exports.MetaRecipeGetSchema=r.z.object({recipeId:r.z.string().describe("Recipe ID to retrieve")}),exports.MetaRecipeCreateSchema=r.z.object({name:r.z.string().min(1).describe("Unique name for the recipe"),description:r.z.string().optional().describe("Description of what the recipe does"),documentation:r.z.string().optional().describe("Detailed documentation")}),exports.MetaRecipeAddHookSchema=r.z.object({recipeId:r.z.string().describe("Recipe ID to add the hook to"),hookId:r.z.string().describe("Hook template ID to add"),position:r.z.number().int().min(0).optional().describe("Position in the recipe (0-based, appended if omitted)")}),exports.MetaRecipeRemoveHookSchema=r.z.object({recipeId:r.z.string().describe("Recipe ID to remove the hook from"),hookId:r.z.string().describe("Hook template ID to remove")}),exports.MetaHookListSchema=r.z.object({}),exports.MetaHookCreateSchema=r.z.object({name:r.z.string().min(1).describe("Unique name for the hook"),description:r.z.string().optional().describe("Description of what the hook does"),eventType:r.z.string().describe("Event type that triggers this hook (e.g., session_idle, request_completed, custom:plan_ready)"),category:r.z.enum(["alchemy","session","message","editing","reading","file_management","documents","history","tool"]).default("session").describe("Hook category"),agent:r.z.string().describe("Agent template to execute when hook fires"),promptTemplate:r.z.string().describe("Prompt template with {{variable}} substitution"),condition:r.z.record(r.z.any()).optional().describe("Condition object for filtering when hook fires"),executionMode:r.z.enum(["same_session","sub_agent","background","notification","direct_report"]).default("background").describe("How to execute the hook"),timing:r.z.enum(["before","after"]).default("after").describe("When to fire relative to the event"),maxIterations:r.z.number().int().min(1).optional().describe("Maximum times to fire per session"),emitEvent:r.z.string().optional().describe("Custom event to emit on completion"),emitEventOnCondition:r.z.union([r.z.object({condition:r.z.object({field:r.z.string(),operator:r.z.enum(["contains","not_contains","equals","not_equals","matches","not_matches"]),value:r.z.string()}),event:r.z.string()}),r.z.array(r.z.object({condition:r.z.object({field:r.z.string(),operator:r.z.enum(["contains","not_contains","equals","not_equals","matches","not_matches"]),value:r.z.string()}),event:r.z.string()}))]).optional().describe("Conditional event emission based on output")}),exports.MetaWorkflowAddRecipeSchema=r.z.object({workflowId:r.z.string().describe("Workflow ID to add the recipe to"),recipeId:r.z.string().describe("Recipe ID to add"),position:r.z.number().int().min(0).optional().describe("Position in the workflow (0-based, appended if omitted)")}),exports.MetaWorkflowRemoveRecipeSchema=r.z.object({workflowId:r.z.string().describe("Workflow ID to remove the recipe from"),recipeId:r.z.string().describe("Recipe ID to remove")}),exports.MetaAgentListSchema=r.z.object({}),exports.MetaReferenceSchema=r.z.object({}),exports.TestingProcessListSchema=r.z.object({}),exports.TestingProcessGetSchema=r.z.object({processId:r.z.string().describe("Test process ID to retrieve")})
|
|
@@ -3617,48 +3619,48 @@ try{const i=d.validateArgs(e,l.InsertLinesSchema),{taskId:C,operations:_,comment
|
|
|
3617
3619
|
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")
|
|
3618
3620
|
const q=_.filter((e=>e.path)),S=_.filter((e=>e.documentId))
|
|
3619
3621
|
y.info("Operation breakdown",{fileOperations:q.length,documentOperations:S.length})
|
|
3620
|
-
const
|
|
3622
|
+
const T=[]
|
|
3621
3623
|
for(const e of q){const{normalizedPath:r,fullPath:n}=d.validateAndNormalizePath(e.path,t)
|
|
3622
|
-
|
|
3624
|
+
T.push({type:"file",path:r,fullPath:n,insertions:e.insertions})}const P=[]
|
|
3623
3625
|
if(S.length>0&&!t.documentFileManager)throw Error("Document file manager not available - cannot process document operations")
|
|
3624
|
-
for(const e of S)
|
|
3625
|
-
if(
|
|
3626
|
+
for(const e of S)P.push({type:"document",documentId:e.documentId,insertions:e.insertions})
|
|
3627
|
+
if(P.length>0&&t.apiClient){const e=P.map((e=>e.documentId))
|
|
3626
3628
|
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}
|
|
3627
3629
|
throw e}}b=d.FileOperationPhase.TASK_VALIDATION,a.incrementCounter("insert_lines_phase",1,{phase:b})
|
|
3628
|
-
const j=
|
|
3629
|
-
let
|
|
3630
|
-
|
|
3630
|
+
const j=T.length>0?T[0].path:"document-operation",R=await d.validateTaskId(C,j,n,y,a,v.metricsPrefix),x=R?.requestId
|
|
3631
|
+
let M=null
|
|
3632
|
+
T.length>0&&x&&(M=await d.validateWorkItemStates(C,T[0].path,n,s,t,y,a,v.metricsPrefix))
|
|
3631
3633
|
let O={taskPromoted:!1,requestPromoted:!1}
|
|
3632
|
-
|
|
3633
|
-
const $=await d.ensureCorrectWorkspaceContext({taskPromoted:O.taskPromoted,requestId:
|
|
3634
|
+
T.length>0&&x&&M&&(O=await d.autoPromoteTaskStatus(C,R.status,x,M.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:x,previousStatus:R.status,newStatus:O.newTaskStatus,triggeringOperation:"insert-lines"}))
|
|
3635
|
+
const $=await d.ensureCorrectWorkspaceContext({taskPromoted:O.taskPromoted,requestId:x,context:t,operation:"insert-lines",logger:y,metrics:a,metricsPrefix:v.metricsPrefix})
|
|
3634
3636
|
if(!$.success){if($.isLockConflict)return{content:[{type:"text",text:"\u274c "+$.error}],isError:!0}
|
|
3635
|
-
throw Error($.error)}if(
|
|
3636
|
-
for(let e=0;e<
|
|
3637
|
-
|
|
3637
|
+
throw Error($.error)}if(T.length>0){y.debug("Re-validating file paths with correct workspace context",{operationCount:T.length,workspaceBasePath:t.workspaceManager?.getCurrentContext().basePath})
|
|
3638
|
+
for(let e=0;e<T.length;e++){const r=T[e],n=q[e],{normalizedPath:o,fullPath:s}=d.validateAndNormalizePath(n.path,t)
|
|
3639
|
+
T[e]={...r,path:o,fullPath:s}}}if(P.length>0&&x)try{await(0,h.validateRequestStatusForDocumentOperation)(x,s,y,a,"insert-lines-document")}catch(e){if(e instanceof u.ValidationError)return{content:[{type:"text",text:e.message}],isError:!0}
|
|
3638
3640
|
throw e}b=d.FileOperationPhase.RECORD_CREATION,a.incrementCounter("insert_lines_phase",1,{phase:b})
|
|
3639
|
-
const D=[...
|
|
3640
|
-
if(k=A,I=A,b=v.fileOperationPhase,a.incrementCounter("insert_lines_phase",1,{phase:b}),
|
|
3641
|
-
const e=await(0,g.commitUserChangesBeforeToolOperation)(t.git,"insert-lines",{requestId:
|
|
3642
|
-
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:
|
|
3641
|
+
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:A}=await d.createFileOperationRecords(C,x,t.projectId,v.recordType,j,{operationCount:_.length,fileOperations:T.length,documentOperations:P.length,operations:D,userComment:E},n,o,y,a,v.metricsPrefix,m)
|
|
3642
|
+
if(k=A,I=A,b=v.fileOperationPhase,a.incrementCounter("insert_lines_phase",1,{phase:b}),T.length>0&&t.git)try{y.debug("[INSERT-LINES] Checking for user changes before insert operations")
|
|
3643
|
+
const e=await(0,g.commitUserChangesBeforeToolOperation)(t.git,"insert-lines",{requestId:x,taskId:C,workspaceManager:t.workspaceManager},y,a)
|
|
3644
|
+
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})
|
|
3643
3645
|
const F=[]
|
|
3644
3646
|
let N=0,L=0,z=0
|
|
3645
|
-
for(const e of
|
|
3647
|
+
for(const e of T){const t={type:"file",path:e.path,success:!1,insertions:[],successfulInsertions:0,failedInsertions:0,totalLinesAdded:0}
|
|
3646
3648
|
try{if(await c.default.access(e.fullPath),!(await c.default.stat(e.fullPath)).isFile())throw Error("Path is not a file: "+e.path)
|
|
3647
3649
|
const n=await c.default.readFile(e.fullPath,"utf8"),{newContent:o,results:s}=await r(n,e.insertions)
|
|
3648
|
-
t.insertions=s,t.successfulInsertions=s.filter((e=>e.success)).length,t.failedInsertions=s.filter((e=>!e.success)).length,t.totalLinesAdded=s.filter((e=>e.success)).reduce(((e,t)=>e+(t.linesAdded||0)),0),o!==n&&t.successfulInsertions>0?(await c.default.writeFile(e.fullPath,o,"utf8"),t.success=!0,z++,y.info("File updated successfully",{path:e.path,successfulInsertions:t.successfulInsertions,failedInsertions:t.failedInsertions,linesAdded:t.totalLinesAdded})):0===t.failedInsertions&&(t.success=!0),N+=t.failedInsertions,L+=t.totalLinesAdded}catch(r){t.error=(0,f.getErrorMessage)(r),t.failedInsertions=e.insertions.length,N+=t.failedInsertions,y.error("File operation failed",{path:e.path,error:t.error})}F.push(t)}for(const e of
|
|
3650
|
+
t.insertions=s,t.successfulInsertions=s.filter((e=>e.success)).length,t.failedInsertions=s.filter((e=>!e.success)).length,t.totalLinesAdded=s.filter((e=>e.success)).reduce(((e,t)=>e+(t.linesAdded||0)),0),o!==n&&t.successfulInsertions>0?(await c.default.writeFile(e.fullPath,o,"utf8"),t.success=!0,z++,y.info("File updated successfully",{path:e.path,successfulInsertions:t.successfulInsertions,failedInsertions:t.failedInsertions,linesAdded:t.totalLinesAdded})):0===t.failedInsertions&&(t.success=!0),N+=t.failedInsertions,L+=t.totalLinesAdded}catch(r){t.error=(0,f.getErrorMessage)(r),t.failedInsertions=e.insertions.length,N+=t.failedInsertions,y.error("File operation failed",{path:e.path,error:t.error})}F.push(t)}for(const e of P){const n={type:"document",documentId:e.documentId,success:!1,insertions:[],successfulInsertions:0,failedInsertions:0,totalLinesAdded:0}
|
|
3649
3651
|
try{const o=await t.documentFileManager.getDocumentAsFile(e.documentId),s=t.documentFileManager.getCachedDocumentInfo(e.documentId)
|
|
3650
3652
|
n.filename=s?.filename
|
|
3651
3653
|
const i=await c.default.readFile(o,"utf8"),{newContent:a,results:l}=await r(i,e.insertions)
|
|
3652
|
-
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(
|
|
3653
|
-
r?.success&&await t.documentFileManager.syncDocument(e.documentId)}}catch(e){y.warn("Some documents may not have synced properly",{error:e})}const H=await d.handleMultiFileGitCommit(C,
|
|
3654
|
-
try{await o.updateToolRecord(I,{metadata:{path:
|
|
3654
|
+
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))
|
|
3655
|
+
r?.success&&await t.documentFileManager.syncDocument(e.documentId)}}catch(e){y.warn("Some documents may not have synced properly",{error:e})}const H=await d.handleMultiFileGitCommit(C,T,F,z,{operationType:"Insert lines",toolRecordId:I,successField:"successfulInsertions",logger:y,metrics:a,metricsPrefix:"insert_lines"},t),B=d.processMultiFileOperationResults(F,"successfulInsertions"),{successfulOperations:U,failedOperations:G,totalSuccessfulChanges:W,overallSuccess:V,successfulFiles:J,failedFiles:K}=B
|
|
3656
|
+
try{await o.updateToolRecord(I,{metadata:{path:T.length>0?T[0].path:"document:"+P[0]?.documentId,status:V?"completed":"failed",error:V?void 0:G+" operations failed",totalOperations:F.length,successfulFiles:J,failedFiles:K,operations:D,totalSuccessfulInsertions:W,totalFailedInsertions:N,totalLinesAdded:L,operationsWithChanges:z,processingTime:Date.now()-w,userComment:E,...T.length>0&&H.success&&H.commitHash&&{commitHash:H.commitHash,previousCommitHash:H.previousCommitHash||void 0}},note:V?`Line insertion completed: ${U}/${F.length} operations successful${T.length>0?" (committed to git)":""}`:`Line insertion partially failed: ${G}/${F.length} operations failed`})}catch(e){y.warn("Failed to update tool record",{recordError:e})}let Y="## Line Insertion Results\n\n"
|
|
3655
3657
|
if(t.workspaceManager&&(Y+=`**Branch:** \`${t.workspaceManager.getCurrentContext().branchName}\`\n\n`),Y+="**Summary:**\n",Y+=`- **Files processed:** ${U+G}\n`,Y+=`- **Successful operations:** ${U}\n`,Y+=`- **Failed operations:** ${G}\n`,Y+=`- **Total insertions:** ${W} successful, ${N} failed\n`,Y+=`- **Total Lines Added:** ${L}\n`,Y+="\n",H.success&&H.commitHash&&(Y+="**Git Commit:**\n",Y+=`- **Commit Hash:** ${H.commitHash.substring(0,8)}\n`,Y+=`- **Files Committed:** ${H.filesCommitted.length}\n`,H.previousCommitHash&&(Y+=`- **Previous Commit:** ${H.previousCommitHash.substring(0,8)}\n`),Y+="\n"),$.lockAcquired&&$.lockedRequestId&&(Y+=`\u{1f512} **Locked request:** ${$.lockedRequestId}\n\n`),1===F.length){const e=F[0]
|
|
3656
3658
|
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"
|
|
3657
3659
|
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}`
|
|
3658
3660
|
Y+=`- ${t.type} insertion ${e}: ${t.error}\n`}}}else{Y+="**Summary:**\n",Y+=`- **Total Operations:** ${F.length}\n`,Y+=`- **Successful:** ${U}\n`,Y+=`- **Failed:** ${G}\n`,Y+=`- **Total Insertions:** ${W} successful, ${N} failed\n`,Y+=`- **Total Lines Added:** ${L}\n\n`,Y+="**Detailed Results:**\n\n"
|
|
3659
3661
|
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"
|
|
3660
3662
|
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}`
|
|
3661
|
-
Y+=` - ${t.type} insertion ${e}: ${t.error}\n`}}Y+="\n"}}
|
|
3663
|
+
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")
|
|
3662
3664
|
const Q=Date.now()-w
|
|
3663
3665
|
return y.info("Insert lines operation completed",{duration:Q,success:V,totalOperations:F.length,successfulOperations:U,failedOperations:G}),a.incrementCounter("insert_lines_total",1,{success:V}),{content:[{type:"text",text:Y}],isError:!V}}catch(t){const r=Date.now()-w
|
|
3664
3666
|
if(y.error("Insert lines operation failed",{error:t instanceof Error?t.stack:t+"",duration:r,phase:b}),I)try{await o.updateToolRecord(I,{metadata:{path:e?.operations?.[0]?.path||e?.operations?.[0]?.documentId,status:"failed",error:(0,f.getErrorMessage)(t),phase:b,duration:r,userComment:e?.comment},note:"Line insertion failed: "+(0,f.getErrorMessage)(t)})}catch(e){}return a.incrementCounter("insert_lines_errors",1,{phase:b}),{content:[{type:"text",text:"\u274c **Insert Lines Failed:** "+(0,f.getErrorMessage)(t)}],isError:!0}}}
|
|
@@ -3676,21 +3678,21 @@ const q=new a.FileOperationsClient(e,m,y,_,v||void 0,C,{timeout:w.timeout,retryA
|
|
|
3676
3678
|
I.registerClient(q),m.info("RequestClient constructor received token: "+(v?"present":"missing"))
|
|
3677
3679
|
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})
|
|
3678
3680
|
I.registerClient(S),m.info("RequestClient post-constructor token: "+(S.getAuthToken()?"present":"missing"))
|
|
3679
|
-
const
|
|
3680
|
-
I.registerClient(P)
|
|
3681
|
-
const T=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})
|
|
3681
|
+
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})
|
|
3682
3682
|
I.registerClient(T)
|
|
3683
|
+
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})
|
|
3684
|
+
I.registerClient(P)
|
|
3683
3685
|
const j=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})
|
|
3684
3686
|
if(I.registerClient(j),!w.alchemyPath)throw Error("alchemyPath is required for ProjectSynchronizer creation. Cannot create API client without project synchronization capabilities.")
|
|
3685
3687
|
try{m.info("Creating ProjectSynchronizer components")
|
|
3686
3688
|
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})
|
|
3687
3689
|
_.setProjectSynchronizer(n),m.info("ProjectSynchronizer created and connected to ProjectClient")}catch(e){const t="Failed to create required ProjectSynchronizer components: "+(0,h.getErrorMessage)(e)
|
|
3688
|
-
throw m.error(t,{error:e instanceof Error?e.stack:e+""}),Error(t)}const R=new o.ApiClient(b,_,E,q,S,P,
|
|
3690
|
+
throw m.error(t,{error:e instanceof Error?e.stack:e+""}),Error(t)}const R=new o.ApiClient(b,_,E,q,S,T,P,j,m)
|
|
3689
3691
|
m.info("API client initialized with specialized clients"),v?(R.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"})
|
|
3690
|
-
const
|
|
3691
|
-
|
|
3692
|
-
const
|
|
3693
|
-
return v&&!
|
|
3692
|
+
const x=I.verifyAllClients()
|
|
3693
|
+
x.success?m.info("Token consistency verified across all clients"):m.error(`Token inconsistency detected in ${x.failedClients.length} clients: ${x.failedClients.join(", ")}`)
|
|
3694
|
+
const M=R.getAuthToken()
|
|
3695
|
+
return v&&!M?(m.error("CRITICAL: ApiClient token was not set properly!"),R.setAuthToken(v)):M&&m.info("ApiClient token verified",{tokenLength:M.length,matches:M===v}),m.info("API client creation completed successfully"),R}}},6540(e,exports){"use strict"
|
|
3694
3696
|
var t
|
|
3695
3697
|
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){"use strict"
|
|
3696
3698
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.ApiClient=void 0
|
|
@@ -3735,34 +3737,34 @@ let I,b,v=d.FileOperationPhase.VALIDATION
|
|
|
3735
3737
|
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"}
|
|
3736
3738
|
try{const i=d.validateArgs(e,l.ReplaceLinesSchema),{taskId:_,operations:E,comment:q}=i
|
|
3737
3739
|
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")
|
|
3738
|
-
const S=E.filter((e=>e.path)),
|
|
3739
|
-
w.info("Operation breakdown",{fileOperations:S.length,documentOperations:
|
|
3740
|
-
const
|
|
3740
|
+
const S=E.filter((e=>e.path)),T=E.filter((e=>e.documentId))
|
|
3741
|
+
w.info("Operation breakdown",{fileOperations:S.length,documentOperations:T.length})
|
|
3742
|
+
const P=[]
|
|
3741
3743
|
for(const e of S){const{normalizedPath:r,fullPath:n}=d.validateAndNormalizePath(e.path,t)
|
|
3742
|
-
|
|
3743
|
-
if(
|
|
3744
|
-
for(const e of
|
|
3744
|
+
P.push({type:"file",path:r,fullPath:n,replacements:e.replacements.map((e=>({lines:(0,y.parseLineSpec)(e.lines),content:e.content})))})}const j=[]
|
|
3745
|
+
if(T.length>0&&!t.documentFileManager)throw Error("Document file manager not available - cannot process document operations")
|
|
3746
|
+
for(const e of T)j.push({type:"document",documentId:e.documentId,replacements:e.replacements.map((e=>({lines:(0,y.parseLineSpec)(e.lines),content:e.content})))})
|
|
3745
3747
|
if(j.length>0&&t.apiClient){const e=j.map((e=>e.documentId))
|
|
3746
3748
|
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}
|
|
3747
3749
|
throw e}}v=d.FileOperationPhase.TASK_VALIDATION,a.incrementCounter("replace_lines_phase",1,{phase:v})
|
|
3748
|
-
const R=
|
|
3750
|
+
const R=P.length>0?P[0].path:"document-operation",x=await d.validateTaskId(_,R,n,w,a,C.metricsPrefix),M=x?.requestId
|
|
3749
3751
|
let O=null
|
|
3750
|
-
|
|
3752
|
+
P.length>0&&M&&(O=await d.validateWorkItemStates(_,P[0].path,n,s,t,w,a,C.metricsPrefix))
|
|
3751
3753
|
let $={taskPromoted:!1,requestPromoted:!1}
|
|
3752
|
-
|
|
3753
|
-
const D=await d.ensureCorrectWorkspaceContext({taskPromoted:$.taskPromoted,requestId:
|
|
3754
|
+
P.length>0&&M&&O&&($=await d.autoPromoteTaskStatus(_,x.status,M,O.request?.status,P[0].path,n,s,w,a,C.metricsPrefix),$.taskPromoted&&w.info("Auto-promoted task to in_progress for replace-lines operation",{taskId:_,requestId:M,previousStatus:x.status,newStatus:$.newTaskStatus,triggeringOperation:"replace-lines"}))
|
|
3755
|
+
const D=await d.ensureCorrectWorkspaceContext({taskPromoted:$.taskPromoted,requestId:M,context:t,operation:"replace-lines",logger:w,metrics:a,metricsPrefix:C.metricsPrefix})
|
|
3754
3756
|
if(!D.success){if(D.isLockConflict)return{content:[{type:"text",text:"\u274c "+D.error}],isError:!0}
|
|
3755
|
-
throw Error(D.error)}if(
|
|
3756
|
-
for(let e=0;e<
|
|
3757
|
-
|
|
3757
|
+
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})
|
|
3758
|
+
for(let e=0;e<P.length;e++){const r=P[e],n=S[e],{normalizedPath:o,fullPath:s}=d.validateAndNormalizePath(n.path,t)
|
|
3759
|
+
P[e]={...r,path:o,fullPath:s}}}if(j.length>0&&M)try{await(0,h.validateRequestStatusForDocumentOperation)(M,s,w,a,"replace-lines-document")}catch(e){if(e instanceof u.ValidationError)return{content:[{type:"text",text:e.message}],isError:!0}
|
|
3758
3760
|
throw e}v=d.FileOperationPhase.RECORD_CREATION,a.incrementCounter("replace_lines_phase",1,{phase:v})
|
|
3759
|
-
const A=[...
|
|
3760
|
-
if(I=F,b=F,v=C.fileOperationPhase,a.incrementCounter("replace_lines_phase",1,{phase:v}),
|
|
3761
|
-
const e=await(0,g.commitUserChangesBeforeToolOperation)(t.git,"replace-lines",{requestId:
|
|
3762
|
-
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:
|
|
3761
|
+
const A=[...P.map((e=>({type:"file",path:e.path,replacements:e.replacements}))),...j.map((e=>({type:"document",documentId:e.documentId,replacements:e.replacements})))],{toolRecordId:F}=await d.createFileOperationRecords(_,M,t.projectId,C.recordType,R,{operationCount:E.length,fileOperations:P.length,documentOperations:j.length,operations:A,userComment:q},n,o,w,a,C.metricsPrefix,m)
|
|
3762
|
+
if(I=F,b=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")
|
|
3763
|
+
const e=await(0,g.commitUserChangesBeforeToolOperation)(t.git,"replace-lines",{requestId:M,taskId:_,workspaceManager:t.workspaceManager},w,a)
|
|
3764
|
+
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})
|
|
3763
3765
|
const N=[]
|
|
3764
3766
|
let L=0,z=0,H=0,B=0
|
|
3765
|
-
for(const e of
|
|
3767
|
+
for(const e of P){const t={type:"file",path:e.path,success:!1,replacements:[],successfulReplacements:0,failedReplacements:0,totalLinesReplaced:0,totalLinesAdded:0}
|
|
3766
3768
|
try{if(await c.default.access(e.fullPath),!(await c.default.stat(e.fullPath)).isFile())throw Error("Path is not a file: "+e.path)
|
|
3767
3769
|
const n=await c.default.readFile(e.fullPath,"utf8"),{newContent:o,results:s}=await r(n,e.replacements)
|
|
3768
3770
|
t.replacements=s,t.successfulReplacements=s.filter((e=>e.success)).length,t.failedReplacements=s.filter((e=>!e.success)).length,t.totalLinesReplaced=s.filter((e=>e.success)).reduce(((e,t)=>e+(t.linesReplaced||0)),0),t.totalLinesAdded=s.filter((e=>e.success)).reduce(((e,t)=>e+(t.linesAdded||0)),0),o!==n&&t.successfulReplacements>0?(await c.default.writeFile(e.fullPath,o,"utf8"),t.success=!0,B++,w.info("File updated successfully",{path:e.path,successfulReplacements:t.successfulReplacements,failedReplacements:t.failedReplacements,linesReplaced:t.totalLinesReplaced,linesAdded:t.totalLinesAdded})):0===t.failedReplacements&&(t.success=!0),L+=t.failedReplacements,z+=t.totalLinesReplaced,H+=t.totalLinesAdded}catch(r){t.error=(0,f.getErrorMessage)(r),t.failedReplacements=e.replacements.length,L+=t.failedReplacements,w.error("File operation failed",{path:e.path,error:t.error})}N.push(t)}for(const e of j){const n={type:"document",documentId:e.documentId,success:!1,replacements:[],successfulReplacements:0,failedReplacements:0,totalLinesReplaced:0,totalLinesAdded:0}
|
|
@@ -3770,8 +3772,8 @@ try{const o=await t.documentFileManager.getDocumentAsFile(e.documentId),s=t.docu
|
|
|
3770
3772
|
n.filename=s?.filename
|
|
3771
3773
|
const i=await c.default.readFile(o,"utf8"),{newContent:a,results:l}=await r(i,e.replacements)
|
|
3772
3774
|
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,B++,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,H+=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(j.length>0)try{for(const e of j){const r=N.find((t=>t.documentId===e.documentId))
|
|
3773
|
-
r?.success&&await t.documentFileManager.syncDocument(e.documentId)}}catch(e){w.warn("Some documents may not have synced properly",{error:e})}const U=await d.handleMultiFileGitCommit(_,
|
|
3774
|
-
try{await o.updateToolRecord(b,{metadata:{path:
|
|
3775
|
+
r?.success&&await t.documentFileManager.syncDocument(e.documentId)}}catch(e){w.warn("Some documents may not have synced properly",{error:e})}const U=await d.handleMultiFileGitCommit(_,P,N,B,{operationType:"Replace lines",toolRecordId:b,successField:"successfulReplacements",logger:w,metrics:a,metricsPrefix:"replace_lines"},t),G=d.processMultiFileOperationResults(N,"successfulReplacements"),{successfulOperations:W,failedOperations:V,totalSuccessfulChanges:J,overallSuccess:K,successfulFiles:Y,failedFiles:Q}=G
|
|
3776
|
+
try{await o.updateToolRecord(b,{metadata:{path:P.length>0?P[0].path:"document:"+j[0]?.documentId,status:K?"completed":"failed",error:K?void 0:V+" operations failed",totalOperations:N.length,successfulFiles:Y,failedFiles:Q,operations:A,totalSuccessfulReplacements:J,totalFailedReplacements:L,totalLinesReplaced:z,totalLinesAdded:H,operationsWithChanges:B,processingTime:Date.now()-k,userComment:q,...P.length>0&&U.success&&U.commitHash&&{commitHash:U.commitHash,previousCommitHash:U.previousCommitHash||void 0}},note:K?`Line replacement completed: ${W}/${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"
|
|
3775
3777
|
if(t.workspaceManager&&(Z+=`**Branch:** \`${t.workspaceManager.getCurrentContext().branchName}\`\n\n`),Z+="**Summary:**\n",Z+=`- **Files processed:** ${W+V}\n`,Z+=`- **Successful operations:** ${W}\n`,Z+=`- **Failed operations:** ${V}\n`,Z+=`- **Total replacements:** ${J} successful, ${L} failed\n`,Z+=`- **Total Lines Replaced:** ${z}\n`,H>0&&(Z+=`- **Total Lines Added:** ${H}\n`),Z+="\n",U.success&&U.commitHash&&(Z+="**Git Commit:**\n",Z+=`- **Commit Hash:** ${U.commitHash.substring(0,8)}\n`,Z+=`- **Files Committed:** ${U.filesCommitted.length}\n`,U.previousCommitHash&&(Z+=`- **Previous Commit:** ${U.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]
|
|
3776
3778
|
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"
|
|
3777
3779
|
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:** ${W}\n`,Z+=`- **Failed:** ${V}\n`,Z+=`- **Total Replacements:** ${J} successful, ${L} failed\n`,Z+=`- **Total Lines Replaced:** ${z}\n`,H>0&&(Z+=`- **Total Lines Added:** ${H}\n`),Z+="\n",Z+="**Detailed Results:**\n\n"
|
|
@@ -3862,11 +3864,11 @@ s.info("Getting file changes for task "+g,{showDiff:p})
|
|
|
3862
3864
|
const f=r.getTaskClient(),m=r.getToolRecordClient(),y=t.projectId
|
|
3863
3865
|
let w
|
|
3864
3866
|
r.setProjectId(y)
|
|
3865
|
-
try{const
|
|
3866
|
-
s.info("Raw task response data",{responseDataType:typeof
|
|
3867
|
+
try{const P=await f.getTask(g)
|
|
3868
|
+
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(j){s.warn("Could not fetch task information: "+(0,u.getErrorMessage)(j)),w={id:g,title:"Unknown Task",status:"unknown",description:"No description available"}}let k=[]
|
|
3867
3869
|
try{const R=await m.getToolRecordsByTaskId(g)
|
|
3868
|
-
if(s.info("Raw records response data",{responseDataType:typeof R,isArray:Array.isArray(R),hasData:null!=R,properties:R&&"object"==typeof R?Object.keys(R):[]}),k=(0,l.extractArrayFromResponse)(R,{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
|
|
3869
|
-
k.forEach((e=>{
|
|
3870
|
+
if(s.info("Raw records response data",{responseDataType:typeof R,isArray:Array.isArray(R),hasData:null!=R,properties:R&&"object"==typeof R?Object.keys(R):[]}),k=(0,l.extractArrayFromResponse)(R,{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 x={}
|
|
3871
|
+
k.forEach((e=>{x[e.type]=(x[e.type]||0)+1})),s.info("Record type distribution:",x)}}catch(M){s.warn("Error fetching records for task "+g,{error:(0,u.getErrorMessage)(M)}),k=[]}if(0===k.length)return h({success:!0,recordCount:0}),{content:[{type:"text",text:`No records found for task ${g}.`}]}
|
|
3870
3872
|
function I(e){const t=new Map,r=new Map,n=[]
|
|
3871
3873
|
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
|
|
3872
3874
|
if(e&&s){const i={source:e,destination:s,recordId:o.id,timestamp:o.createdAt,type:"move-file"}
|
|
@@ -3959,17 +3961,17 @@ W=_e}else W="File created during this task. Content:\n"+Ce
|
|
|
3959
3961
|
V=!0,s.info("Fallback succeeded, got file content of length "+Ce.length)}}catch(Se){s.warn("Fallback also failed for "+A,{error:Se instanceof Error?Se.message:Se+""})}}_.set(A,{firstChange:G,lastChange:H,hasDiff:V,diffText:W||"No changes detected between commits"})}else V=G.commitHash!==H.commitHash,W=V?"File has changes":"No changes detected between commits",_.set(A,{firstChange:G,lastChange:H,hasDiff:V,diffText:W})}let E=`# File Changes for Task: ${g}\n\n`
|
|
3960
3962
|
w&&"object"==typeof w&&(E+="## Task Information\n",E+=`- **Title**: ${w.title||"Unknown"}\n`,E+=`- **Status**: ${w.status||"Unknown"}\n`,E+=`- **Description**: ${w.description||"No description"}\n\n`)
|
|
3961
3963
|
const q=3e3
|
|
3962
|
-
let S=0,
|
|
3963
|
-
if(p){for(const
|
|
3964
|
-
|
|
3965
|
-
for(const
|
|
3966
|
-
for(const[je,Re]of _.entries()){const{normalizedPath:
|
|
3964
|
+
let S=0,T=!1
|
|
3965
|
+
if(p){for(const Te of _.values())Te.hasDiff&&Te.diffText&&(S+=Te.diffText.split("\n").length)
|
|
3966
|
+
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`,b.allMoves.length>0){E+="## Move Operations\n\n",E+=`Detected ${b.allMoves.length} file move operation(s):\n\n`
|
|
3967
|
+
for(const Pe of b.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"
|
|
3968
|
+
for(const[je,Re]of _.entries()){const{normalizedPath:xe,fullPath:Me}=d.validateAndNormalizePath(je,t)
|
|
3967
3969
|
let Oe=!1
|
|
3968
|
-
try{await a.access(
|
|
3970
|
+
try{await a.access(Me),Oe=!0}catch{}E+=`### ${je} ${Oe?"":"(Deleted)"}\n\n`
|
|
3969
3971
|
const $e=new Date(Re.firstChange.timestamp).toLocaleString(),De=new Date(Re.lastChange.timestamp).toLocaleString()
|
|
3970
3972
|
E+=`**First Change**: ${$e}\n`,E+=`**Last Change**: ${De}\n`,"pre-task"===Re.firstChange.status&&Re.firstChange.commitHash?E+=`**Pre-Task Commit**: ${Re.firstChange.commitHash.substring(0,8)}\n`:Re.firstChange.commitHash&&(E+=`**File Created During Task**: ${Re.firstChange.commitHash.substring(0,8)}\n`),Re.lastChange.commitHash&&(E+=`**Final Commit**: ${Re.lastChange.commitHash.substring(0,8)}\n`)
|
|
3971
3973
|
const Ae=b.sourceToMove.get(je),Fe=b.destToMove.get(je)
|
|
3972
|
-
Ae?E+=`**\u2139\ufe0f Move Operation**: This file was moved TO **${Ae.destination}**\n`:Fe&&(E+=`**\u2139\ufe0f Move Operation**: This file was moved FROM **${Fe.source}**\n`),p&&!
|
|
3974
|
+
Ae?E+=`**\u2139\ufe0f Move Operation**: This file was moved TO **${Ae.destination}**\n`:Fe&&(E+=`**\u2139\ufe0f Move Operation**: This file was moved FROM **${Fe.source}**\n`),p&&!T?Re.hasDiff?(E+="\n**Changes**:\n",E+="```diff\n",E+=Re.diffText,E+="\n```\n\n"):E+=`\n**Note**: ${Re.diffText}\n\n`:T&&Re.hasDiff?(E+=`\n**Note**: File has changes (${Re.diffText?Re.diffText.split("\n").length:0} lines). `,E+=`Compare ${Re.firstChange.commitHash?Re.firstChange.commitHash.substring(0,8):"unknown"}..${Re.lastChange.commitHash?Re.lastChange.commitHash.substring(0,8):"unknown"} to see changes.\n\n`):Re.hasDiff?E+="\n**Note**: File has changes. Use showDiff=true to see the diff.\n\n":E+=`\n**Note**: ${Re.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}}}
|
|
3973
3975
|
const i=t(9860),a=s(t(1943)),c=t(9671),l=t(2960),d=s(t(5967)),u=t(8824)},6928(module){"use strict"
|
|
3974
3976
|
module.exports=require("path")},6975(e,exports,t){"use strict"
|
|
3975
3977
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.ProjectClientAdapter=void 0
|
|
@@ -4119,20 +4121,24 @@ if(e){const t=c.getCLISessionClient()
|
|
|
4119
4121
|
if(t){const r=await t.getByExternalId(e)
|
|
4120
4122
|
if(r?.workflowId){const e=await c.proxyGet("/api/workflows/"+r.workflowId),t=e?.data||e
|
|
4121
4123
|
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
|
|
4122
|
-
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"
|
|
4124
|
+
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"
|
|
4125
|
+
let k=h
|
|
4126
|
+
if(h?.sessionId)try{const e=c.getCLISessionClient()
|
|
4127
|
+
if(e){const t=await e.getByExternalId(h.sessionId)
|
|
4128
|
+
"planner"!==t?.agentType&&"auto-planner"!==t?.agentType||(k=void 0,g.info("Skipping cliOrigin for planner-created request",{agentType:t.agentType}))}}catch{}const I={title:l.title,description:l.description,type:l.type,acceptanceCriteria:l.acceptanceCriteria,status:w,...l.planDocumentId&&{planDocumentId:l.planDocumentId},...k&&{cliOrigin:k}}
|
|
4123
4129
|
g.info("Creating request via request client",{projectId:f,title:l.title,type:l.type,criteriaCount:l.acceptanceCriteria.length})
|
|
4124
|
-
const
|
|
4125
|
-
g.debug("Create request response structure",{type:typeof
|
|
4126
|
-
const
|
|
4127
|
-
let
|
|
4128
|
-
if(u?.workspaceManager)try{await u.workspaceManager.initializeRequest(
|
|
4129
|
-
g.info("Request created successfully",{requestId:
|
|
4130
|
+
const b=await m.createRequest(I)
|
|
4131
|
+
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"})
|
|
4132
|
+
const v=(0,o.extractDataFromResponse)(b,{logger:g,operationName:"createRequest",throwOnNoData:!0}),C="data"in v?v.data:v
|
|
4133
|
+
let _,E={created:!1}
|
|
4134
|
+
if(u?.workspaceManager)try{await u.workspaceManager.initializeRequest(C.id,C.title),E={created:!0,branchName:"requests/"+C.id,message:"Branch created successfully"},g.info("Request branch initialized successfully",{requestId:C.id,branchName:E.branchName,title:C.title})}catch(e){g.warn("Failed to initialize request branch, will retry on first operation",{requestId:C.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:C.id}):g.debug("No workspace manager available, branch creation deferred",{requestId:C.id})
|
|
4135
|
+
g.info("Request created successfully",{requestId:C.id,title:C.title,branchCreated:E.created,branchName:E.branchName})
|
|
4130
4136
|
try{const e=c.getToolRecordClient()
|
|
4131
|
-
if(e){const t=await e.createToolRecord({requestId:
|
|
4132
|
-
|
|
4133
|
-
const
|
|
4134
|
-
let
|
|
4135
|
-
return
|
|
4137
|
+
if(e){const t=await e.createToolRecord({requestId:C.id,projectId:f,type:"create-request",metadata:{status:"completed",timestamp:(new Date).toISOString(),requestType:C.type,requestTitle:C.title,requestDescription:C.description,criteriaCount:C.acceptanceCriteria.length,branchCreated:E.created,branchName:E.created?E.branchName:null},note:`Created request "${C.title}" of type ${C.type}${E.created?" with branch "+E.branchName:" - branch will be created on first file operation"}`})
|
|
4138
|
+
_=t?.id}}catch(e){g.warn("Failed to create tool record for request creation",{error:(0,i.getErrorMessage)(e),requestId:C.id})}p({success:!0,type:l.type,hasProjectId:!0}),g.info("Request created successfully",{requestId:C.id,title:C.title,type:C.type,projectId:f})
|
|
4139
|
+
const q=C.localId||C.id
|
|
4140
|
+
let S="pending_approval"===w?`Created Request ${q} (pending approval)`:"Created Request "+q
|
|
4141
|
+
return _&&(S+=`\n[RECORD:${_}]`),{content:[{type:"text",text:S}]}}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})
|
|
4136
4142
|
else{const n=c.getToolRecordClient()
|
|
4137
4143
|
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]
|
|
4138
4144
|
let t=e.message
|
|
@@ -4711,19 +4717,19 @@ const C=await d.validateTaskId(u,b,r,f,i,I.metricsPrefix),_=C?.requestId,E=await
|
|
|
4711
4717
|
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:b}),q.requestPromoted&&f.info(`Auto-promoted request ${_} to in_progress for file operation`,{requestId:_,previousStatus:E.request?.status,newStatus:q.newRequestStatus,triggeringTaskId:u})
|
|
4712
4718
|
const S=await d.ensureCorrectWorkspaceContext({taskPromoted:q.taskPromoted,requestId:_,context:t,operation:"create-directory",logger:f,metrics:i,metricsPrefix:I.metricsPrefix})
|
|
4713
4719
|
if(!S.success){if(S.isLockConflict)return{content:[{type:"text",text:"\u274c "+S.error}],isError:!0}
|
|
4714
|
-
throw Error(S.error)}let
|
|
4715
|
-
try{
|
|
4716
|
-
const{toolRecordId:
|
|
4717
|
-
y=
|
|
4718
|
-
let R=
|
|
4719
|
-
if(!
|
|
4720
|
+
throw Error(S.error)}let T=!1
|
|
4721
|
+
try{T=(await a.default.stat(v)).isDirectory()}catch{T=!1}k=d.FileOperationPhase.RECORD_CREATION,i.incrementCounter("create_directory_phase",1,{phase:k})
|
|
4722
|
+
const{toolRecordId:P,localToolRecordId:j}=await d.createFileOperationRecords(u,_,t.projectId,I.recordType,b,{directoryExists:T,userComment:g},r,n,f,i,I.metricsPrefix,p)
|
|
4723
|
+
y=P,w=P,k=I.fileOperationPhase,i.incrementCounter("create_directory_phase",1,{phase:k})
|
|
4724
|
+
let R=T
|
|
4725
|
+
if(!T){await a.default.mkdir(v,{recursive:!0}),f.info("Successfully created directory "+b)
|
|
4720
4726
|
try{const e=c.default.join(v,".gitkeep")
|
|
4721
|
-
await a.default.writeFile(e,"# This file makes the directory trackable by Git\n"),R=!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+""}),R=!1}}const
|
|
4722
|
-
i.recordValue("create_directory_time",
|
|
4723
|
-
const
|
|
4724
|
-
k=d.FileOperationPhase.RECORD_UPDATE_SUCCESS,i.incrementCounter("create_directory_phase",1,{phase:k}),await d.updateFileOperationRecords(u,y,w,b,I.recordType,`Successfully ${
|
|
4727
|
+
await a.default.writeFile(e,"# This file makes the directory trackable by Git\n"),R=!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+""}),R=!1}}const x=Date.now()-m
|
|
4728
|
+
i.recordValue("create_directory_time",x),i.incrementCounter("create_directory_success",1),k=d.FileOperationPhase.GIT_COMMIT,i.incrementCounter("create_directory_phase",1,{phase:k})
|
|
4729
|
+
const M=`Create directory: ${b} - ${g||"Create directory"}`,O=!T&&R?b+"/.gitkeep":b,$=await d.commitToGit(u,O,P,j,M,t,f,i,I.metricsPrefix)
|
|
4730
|
+
k=d.FileOperationPhase.RECORD_UPDATE_SUCCESS,i.incrementCounter("create_directory_phase",1,{phase:k}),await d.updateFileOperationRecords(u,y,w,b,I.recordType,`Successfully ${T?"verified":"created"} directory: ${b}`,{status:"completed",commitHash:$.commitHash,previousCommitHash:$.previousCommitHash,directoryExists:T,isDirectory:!0,userComment:g},`Successfully ${T?"verified":"created"} directory: ${b}`,r,n,f,i,I.metricsPrefix)
|
|
4725
4731
|
const D=t.getCurrentBranchContext?await t.getCurrentBranchContext():{branch:null,requestId:null,isMain:!0}
|
|
4726
|
-
return{content:[{type:"text",text:
|
|
4732
|
+
return{content:[{type:"text",text:T?"Directory already exists":`Successfully created directory${$.commitHash?"\nCommit: "+$.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
|
|
4727
4733
|
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
|
|
4728
4734
|
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
|
|
4729
4735
|
try{await d.updateFileOperationRecords(e.taskId,y,w,e.path,I.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,I.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,I)}}
|
|
@@ -5250,23 +5256,23 @@ let v,C=u.FileOperationPhase.VALIDATION
|
|
|
5250
5256
|
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)
|
|
5251
5257
|
const i=u.validateArgs(e,d.ReplaceInFilesSchema),{taskId:_,operations:E,fuzzy_match:q=!0,comment:S}=i
|
|
5252
5258
|
I.info("Replace in files batch operation",{taskId:_,operationCount:E.length,totalReplacements:E.reduce(((e,t)=>e+t.replacements.length),0),globalFuzzyMatch:q,comment:S})
|
|
5253
|
-
const
|
|
5254
|
-
if(
|
|
5259
|
+
const T=E.filter((e=>e.documentId)).map((e=>e.documentId))
|
|
5260
|
+
if(T.length>0&&t.apiClient)try{await(0,m.ensureDocumentsNotLocked)(T,t.apiClient,I,a,"replace_in_files-documents")}catch(e){if(e instanceof g.ValidationError)return{content:[{type:"text",text:e.message}],isError:!0}
|
|
5255
5261
|
throw e}C=u.FileOperationPhase.TASK_VALIDATION,a.incrementCounter("replace_in_files_phase",1,{phase:C})
|
|
5256
|
-
const
|
|
5262
|
+
const P=E[0],j=P.documentId?"document:"+P.documentId:P.path
|
|
5257
5263
|
let R=Date.now()
|
|
5258
|
-
const
|
|
5264
|
+
const x=await u.validateTaskId(_,j,r,I,a,"replace_in_files")
|
|
5259
5265
|
Date.now()
|
|
5260
|
-
const x
|
|
5266
|
+
const M=x?.requestId,O=E.some((e=>e.path))
|
|
5261
5267
|
let $=!1
|
|
5262
|
-
if(O&&
|
|
5268
|
+
if(O&&M){R=Date.now()
|
|
5263
5269
|
const e=await u.validateWorkItemStates(_,j,r,s,t,I,a,"replace_in_files")
|
|
5264
5270
|
Date.now(),R=Date.now()
|
|
5265
|
-
const n=await u.autoPromoteTaskStatus(_,
|
|
5266
|
-
n.taskPromoted&&I.info("Auto-promoted task to in_progress",{taskId:_,requestId:
|
|
5267
|
-
const o=await u.ensureCorrectWorkspaceContext({taskPromoted:n.taskPromoted,requestId:
|
|
5271
|
+
const n=await u.autoPromoteTaskStatus(_,x.status,M,e.request?.status,j,r,s,I,a,"replace_in_files")
|
|
5272
|
+
n.taskPromoted&&I.info("Auto-promoted task to in_progress",{taskId:_,requestId:M,previousStatus:x.status,newStatus:n.newTaskStatus}),Date.now(),R=Date.now()
|
|
5273
|
+
const o=await u.ensureCorrectWorkspaceContext({taskPromoted:n.taskPromoted,requestId:M,context:t,operation:"replace_in_files",logger:I,metrics:a,metricsPrefix:"replace_in_files"})
|
|
5268
5274
|
if(!o.success){if(o.isLockConflict)return{content:[{type:"text",text:"\u274c "+o.error}],isError:!0}
|
|
5269
|
-
throw Error(o.error)}Date.now(),$=!0}if(
|
|
5275
|
+
throw Error(o.error)}Date.now(),$=!0}if(T.length>0&&M)try{await(0,p.validateRequestStatusForDocumentOperation)(M,s,I,a,"replace_in_files-documents")}catch(e){if(e instanceof g.ValidationError)return{content:[{type:"text",text:e.message}],isError:!0}
|
|
5270
5276
|
throw e}R=Date.now()
|
|
5271
5277
|
const D=new Map
|
|
5272
5278
|
if(I.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=[]
|
|
@@ -5275,9 +5281,9 @@ s.push(...r)}if(s.length>0){const o=(0,y.calculateReplacementRegion)(n,s,r.fullP
|
|
|
5275
5281
|
I.info("\u{1f50d} Checking for external edits",{path:r.normalizedPath,affectedLines:o.lineRanges.map((e=>`${e.start}-${e.end}`)).join(", "),matchCount:s.length})
|
|
5276
5282
|
const i=await(0,w.detectExternalEdits)(t.git,o,I)
|
|
5277
5283
|
I.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}),I.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}),I.info("\u2705 No external edit conflicts detected",{path:r.normalizedPath}))}else I.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){I.warn("Failed to check for external edits before auto-commit",{path:e.path,error:(0,k.getErrorMessage)(t)})}if(Date.now(),R=Date.now(),O&&t.git)try{I.debug("[REPLACE-IN-FILES] Checking for user changes before batch operation")
|
|
5278
|
-
const e=await(0,f.commitUserChangesBeforeToolOperation)(t.git,"replace_in_files",{requestId:
|
|
5284
|
+
const e=await(0,f.commitUserChangesBeforeToolOperation)(t.git,"replace_in_files",{requestId:M,taskId:_,workspaceManager:t.workspaceManager},I,a)
|
|
5279
5285
|
e.userChangesCommitted&&(I.debug("[REPLACE-IN-FILES] User changes committed",{commitHash:e.commitHash?.substring(0,8),filesCommitted:e.filesCommitted}),I.info("User changes committed before batch operation",{taskId:_,userCommitHash:e.commitHash?.substring(0,8),userFilesCommitted:e.filesCommitted}))}catch(e){I.warn("Pre-tool user changes commit failed",{taskId:_,error:e instanceof Error?e.message:e+""})}Date.now(),R=Date.now(),C=u.FileOperationPhase.RECORD_CREATION,a.incrementCounter("replace_in_files_phase",1,{phase:C})
|
|
5280
|
-
const{toolRecordId:A}=await u.createFileOperationRecords(_,
|
|
5286
|
+
const{toolRecordId:A}=await u.createFileOperationRecords(_,M,t.projectId,"replace-in-files",j,{operationCount:E.length,totalReplacements:E.reduce(((e,t)=>e+t.replacements.length),0),globalFuzzyMatch:q,userComment:S},r,o,I,a,"replace_in_files",c)
|
|
5281
5287
|
v=A,Date.now(),R=Date.now(),C=u.FileOperationPhase.STRING_REPLACEMENT,a.incrementCounter("replace_in_files_phase",1,{phase:C})
|
|
5282
5288
|
const F=[],N=[]
|
|
5283
5289
|
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)
|